dv: support PIP [1/1]
authorrobin zhu <robin.zhu@amlogic.com>
Tue, 25 Jun 2019 20:02:14 +0000 (13:02 -0700)
committerJianxin Pan <jianxin.pan@amlogic.com>
Fri, 26 Jul 2019 06:12:35 +0000 (23:12 -0700)
PD#SWPL-9950

Problem:
  not support VD1+VD2 PIP for DV+None_DV or 2xNone_DV
  need bypass HDR+ to HDR module when Sink support
  need always bypass to HDR module for HLG
  not fully support convert between format SDR/HDR(+)/HLG
  not support convert all format to IPT(DV)
  not support follow sink/follow src policy for PIP

Solution:
  add full matrix support to convert between SDR/HDR formats
  add support to convert all format to IPT(DV)
  rewrite policy, video process and tx handing for PIP

Verify:
  tested and merged in raven project
  need test on for src
  need test for sink(has regression, need to fix)

Change-Id: I001d9dcdcb94c95fb2b7651e726d1ebadc8f4551
Signed-off-by: robin zhu <robin.zhu@amlogic.com>
17 files changed:
MAINTAINERS
drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c
drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.h
drivers/amlogic/media/enhancement/amvecm/Makefile
drivers/amlogic/media/enhancement/amvecm/amcsc.c
drivers/amlogic/media/enhancement/amvecm/amcsc.h
drivers/amlogic/media/enhancement/amvecm/amcsc_pip.c [new file with mode: 0644]
drivers/amlogic/media/enhancement/amvecm/amcsc_pip.h [new file with mode: 0644]
drivers/amlogic/media/enhancement/amvecm/amvecm.c
drivers/amlogic/media/enhancement/amvecm/hdr/am_hdr10_plus.c
drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.c
drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.h
drivers/amlogic/media/video_sink/video.c
drivers/amlogic/media/vout/hdmitx/hdmi_tx_20/hdmi_tx_main.c
include/linux/amlogic/media/amdolbyvision/dolby_vision.h
include/linux/amlogic/media/amvecm/amvecm.h
include/linux/amlogic/media/vout/vinfo.h

index 2e5f1e0..70cffc2 100644 (file)
@@ -13924,7 +13924,7 @@ F:      drivers/amlogic/media/enhancement/amvecm/arch/*
 F:     drivers/amlogic/media/enhancement/amvecm/dnlp_algorithm/*
 F:     include/linux/amlogic/media/amvecm/*
 F:     drivers/amlogic/media/enhancement/amvecm/hdr/*
-F:      drivers/amlogic/media/enhancement/amvecm/amprime_sl/*
+F:  drivers/amlogic/media/enhancement/amvecm/amprime_sl/*
 
 AMLOGIC GXL ADD SKT DTS
 M: Yun Cai <yun.cai@amlogic.com>
index 91b19ee..72ff32d 100644 (file)
@@ -35,6 +35,7 @@
 #include "../amvecm/arch/vpp_regs.h"
 #include "../amvecm/arch/vpp_hdr_regs.h"
 #include "../amvecm/arch/vpp_dolbyvision_regs.h"
+#include "../amvecm/amcsc.h"
 #include <linux/amlogic/media/registers/regs/viu_regs.h>
 #include <linux/amlogic/media/amdolbyvision/dolby_vision.h>
 #include <linux/cma.h>
@@ -77,12 +78,6 @@ static struct amdolby_vision_dev_s amdolby_vision_dev;
 struct dv_device_data_s dv_meson_dev;
 static unsigned int dolby_vision_request_mode = 0xff;
 
-#define DOLBY_VISION_OUTPUT_MODE_IPT                   0
-#define DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL            1
-#define DOLBY_VISION_OUTPUT_MODE_HDR10                 2
-#define DOLBY_VISION_OUTPUT_MODE_SDR10                 3
-#define DOLBY_VISION_OUTPUT_MODE_SDR8                  4
-#define DOLBY_VISION_OUTPUT_MODE_BYPASS                        5
 static unsigned int dolby_vision_mode = DOLBY_VISION_OUTPUT_MODE_BYPASS;
 module_param(dolby_vision_mode, uint, 0664);
 MODULE_PARM_DESC(dolby_vision_mode, "\n dolby_vision_mode\n");
@@ -98,29 +93,32 @@ MODULE_PARM_DESC(dolby_vision_level, "\n dolby_vision_level\n");
 /* STB: if sink support DV, always output DV*/
 /*             else always output SDR/HDR */
 /* TV:  when source is DV, convert to SDR */
-#define DOLBY_VISION_FOLLOW_SINK               0
+/* #define DOLBY_VISION_FOLLOW_SINK            0 */
 
 /* STB: output DV only if source is DV*/
 /*             and sink support DV*/
 /*             else always output SDR/HDR */
 /* TV:  when source is DV or HDR, convert to SDR */
-#define DOLBY_VISION_FOLLOW_SOURCE             1
+/* #define DOLBY_VISION_FOLLOW_SOURCE          1 */
 
 /* STB: always follow dolby_vision_mode */
 /* TV:  if set dolby_vision_mode to SDR8,*/
 /*             convert all format to SDR by TV core,*/
 /*             else bypass Dolby Vision */
-#define DOLBY_VISION_FORCE_OUTPUT_MODE 2
+/* #define DOLBY_VISION_FORCE_OUTPUT_MODE      2 */
 
 static unsigned int dolby_vision_policy;
 module_param(dolby_vision_policy, uint, 0664);
 MODULE_PARM_DESC(dolby_vision_policy, "\n dolby_vision_policy\n");
+static unsigned int last_dolby_vision_policy;
 
-/* bit0: 0: bypass hdr to vpp, 1: process hdr by dolby core */
-/* bit1: 0: output to sdr, 1: output to hdr if sink support hdr not dovi */
-static unsigned int dolby_vision_hdr10_policy;
+/* bit0: follow sink 0: bypass hdr to vpp, 1: process hdr by dolby core */
+/* bit1: follow source 0: bypass hdr to vpp, 1: process hdr by dolby core */
+/* bit2: 0: bypass hlg/hdr10+ to vpp, 1: process hlg/hdr10+ by dolby core */
+static unsigned int dolby_vision_hdr10_policy = 1;
 module_param(dolby_vision_hdr10_policy, uint, 0664);
 MODULE_PARM_DESC(dolby_vision_hdr10_policy, "\n dolby_vision_hdr10_policy\n");
+static unsigned int last_dolby_vision_hdr10_policy = 1;
 
 static bool dolby_vision_enable;
 module_param(dolby_vision_enable, bool, 0664);
@@ -197,6 +195,10 @@ MODULE_PARM_DESC(dolby_vision_ll_policy, "\n dolby_vision_ll_policy\n");
 static u32 last_dolby_vision_ll_policy = DOLBY_VISION_LL_DISABLE;
 #endif
 
+static unsigned int dolby_vision_src_format;
+module_param(dolby_vision_src_format, uint, 0664);
+MODULE_PARM_DESC(dolby_vision_src_format, "\n dolby_vision_src_format\n");
+
 static uint dolby_vision_on_count;
 static bool dolby_vision_el_disable;
 
@@ -244,7 +246,7 @@ static unsigned int g_vtotal_add = 0x80;
 static unsigned int g_vsize_add;
 static unsigned int g_vwidth = 0x18;
 static unsigned int g_hwidth = 0x10;
-static unsigned int g_vpotch = 0x8;
+static unsigned int g_vpotch = 0x10;
 static unsigned int g_hpotch = 0x10;
 /*dma size:1877x2x64 bit = 30032 byte*/
 #define TV_DMA_TBL_SIZE 3754
@@ -264,6 +266,8 @@ static u32 core1_disp_hsize;
 static u32 core1_disp_vsize;
 static u32 vsync_count;
 #define FLAG_VSYNC_CNT 10
+#define MAX_TRANSITION_DELAY 15
+#define MIN_TRANSITION_DELAY 2
 
 static bool is_osd_off;
 static bool force_reset_core2;
@@ -274,6 +278,9 @@ MODULE_PARM_DESC(vtotal_add, "\n vtotal_add\n");
 module_param(vpotch, uint, 0664);
 MODULE_PARM_DESC(vpotch, "\n vpotch\n");
 
+module_param(g_vpotch, uint, 0664);
+MODULE_PARM_DESC(g_vpotch, "\n vpotch\n");
+
 static unsigned int dolby_vision_target_min = 50; /* 0.0001 */
 #ifdef V2_4
 static unsigned int dolby_vision_target_max[3][3] = {
@@ -296,7 +303,7 @@ static unsigned int dolby_vision_default_max[3][3] = {
 };
 
 static unsigned int dolby_vision_graphic_min = 50; /* 0.0001 */
-static unsigned int dolby_vision_graphic_max; /* 100 *//* 0.1 */
+static unsigned int dolby_vision_graphic_max; /* 100 */
 module_param(dolby_vision_graphic_min, uint, 0664);
 MODULE_PARM_DESC(dolby_vision_graphic_min, "\n dolby_vision_graphic_min\n");
 module_param(dolby_vision_graphic_max, uint, 0664);
@@ -316,6 +323,8 @@ static unsigned int dv_target_graphics_LL_max[3][3] = {
 /*these two parameters form OSD*/
 static unsigned int osd_graphic_width = 1920;
 static unsigned int osd_graphic_height = 1080;
+static unsigned int new_osd_graphic_width = 1920;
+static unsigned int new_osd_graphic_height = 1080;
 
 static unsigned int dv_cert_graphic_width = 1920;
 static unsigned int dv_cert_graphic_height = 1080;
@@ -1013,7 +1022,14 @@ MODULE_PARM_DESC(debug_dolby_frame, "\n debug_dolby_frame\n");
 #define dump_enable \
        ((debug_dolby_frame >= 0xffff) || \
        (debug_dolby_frame + 1 == frame_count))
-
+static int is_graphics_output_off(void)
+{
+       if (is_meson_g12())
+               return !(READ_VPP_REG(OSD1_BLEND_SRC_CTRL) & (0xf<<8))
+               && !(READ_VPP_REG(OSD2_BLEND_SRC_CTRL) & (0xf<<8));
+       else
+               return (!(READ_VPP_REG(VPP_MISC) & (1<<12)));
+}
 #define single_step_enable \
        (((debug_dolby_frame >= 0xffff) || \
        ((debug_dolby_frame + 1) == frame_count)) && \
@@ -1249,14 +1265,6 @@ static unsigned int amdolby_vision_poll(struct file *file, poll_table *wait)
        return mask;
 }
 
-static int is_graphics_output_off(void)
-{
-       if (is_meson_g12() || is_meson_tm2_stbmode())
-               return !(READ_VPP_DV_REG(OSD1_BLEND_SRC_CTRL) & (1<<8));
-       else
-               return (!(READ_VPP_DV_REG(VPP_MISC) & (1<<12)));
-}
-
 static void dump_tv_setting(
        struct tv_dovi_setting_s *setting,
        int frame_cnt, int debug_flag)
@@ -2543,8 +2551,39 @@ static int dolby_core3_set(
 void update_graphic_width_height(unsigned int width,
        unsigned int height)
 {
-       osd_graphic_width = width;
-       osd_graphic_height = height;
+       new_osd_graphic_width = width;
+       new_osd_graphic_height = height;
+}
+
+static int is_graphic_changed(void)
+{
+       int ret = 0;
+
+       if (is_graphics_output_off()) {
+               if (!is_osd_off) {
+                       pr_dolby_dbg("osd off\n");
+                       is_osd_off = true;
+                       ret |= 1;
+               }
+       } else if (is_osd_off) {
+               /* force reset core2 when osd off->on */
+               force_reset_core2 = true;
+               pr_dolby_dbg("osd on\n");
+               is_osd_off = false;
+               ret |= 1;
+       }
+       if ((osd_graphic_width != new_osd_graphic_width) ||
+       (osd_graphic_height != new_osd_graphic_height)) {
+               pr_dolby_dbg("osd changed %d %d-%d %d\n",
+                       osd_graphic_width,
+                       osd_graphic_height,
+                       new_osd_graphic_width,
+                       new_osd_graphic_height);
+               osd_graphic_width = new_osd_graphic_width;
+               osd_graphic_height = new_osd_graphic_height;
+               ret |= 2;
+       }
+       return ret;
 }
 
 static void apply_stb_core_settings(
@@ -2561,6 +2600,7 @@ static void apply_stb_core_settings(
 #endif
        u32 graphics_w = osd_graphic_width;
        u32 graphics_h = osd_graphic_height;
+
        if (is_dolby_vision_stb_mode()
                && (dolby_vision_flags & FLAG_CERTIFICAION)) {
                graphics_w = dv_cert_graphic_width;
@@ -2920,6 +2960,7 @@ void enable_dolby_vision(int enable)
 
        if (enable) {
                if (!dolby_vision_on) {
+                       dolby_vision_wait_on = true;
                        dolby_ctrl_backup =
                                VSYNC_RD_DV_REG(VPP_DOLBY_CTRL);
                        viu_misc_ctrl_backup =
@@ -3128,23 +3169,27 @@ void enable_dolby_vision(int enable)
 #endif
                                pr_dolby_dbg("Dolby Vision STB cores turn on\n");
                        } else if (is_meson_g12() || is_meson_tm2_stbmode()) {
+                               hdr_osd_off();
+                               hdr_vd1_off();
+                               set_hdr_module_status(VD1_PATH,
+                                       HDR_MODULE_BYPASS);
                                if (dolby_vision_mask & 4)
                                        VSYNC_WR_DV_REG_BITS(VPP_DOLBY_CTRL,
                                                1, 3, 1);   /* core3 enable */
                                else
                                        VSYNC_WR_DV_REG_BITS(VPP_DOLBY_CTRL,
                                                0, 3, 1);   /* bypass core3  */
-
-                               if (is_meson_g12()) {
-                                       /*g12a/g12b/sm1: osd1 green line*/
-                                       enable_osd1_mtx(0);
-                               } else if (is_meson_tm2_stbmode()) {
+                               if (is_meson_tm2_stbmode()) {
+                                       /* TODO: backup reg */
                                        VSYNC_WR_DV_REG(
-                                       VPP_WRAP_OSD1_MATRIX_EN_CTRL, 0x0);
+                                               VPP_WRAP_OSD1_MATRIX_EN_CTRL,
+                                               0x0);
                                        VSYNC_WR_DV_REG(
-                                       VPP_WRAP_OSD2_MATRIX_EN_CTRL, 0x0);
+                                               VPP_WRAP_OSD2_MATRIX_EN_CTRL,
+                                               0x0);
                                        VSYNC_WR_DV_REG(
-                                       VPP_WRAP_OSD3_MATRIX_EN_CTRL, 0x0);
+                                               VPP_WRAP_OSD3_MATRIX_EN_CTRL,
+                                               0x0);
                                }
                                if (dolby_vision_mask & 2)
                                        VSYNC_WR_DV_REG_BITS(
@@ -3438,16 +3483,17 @@ void enable_dolby_vision(int enable)
                                memset(&dovi_setting, 0, sizeof(dovi_setting));
                                pr_dolby_dbg("Dolby Vision STB cores turn off\n");
                        } else if (is_meson_g12() || is_meson_tm2_stbmode()) {
-                               if (is_meson_g12()) {
-                                       /*g12a/g12b/sm1:osd1 green line*/
-                                       enable_osd1_mtx(1);
-                               } else if (is_meson_tm2_stbmode()) {
+                               if (is_meson_tm2_stbmode()) {
+                                       /* TODO: restore reg */
                                        VSYNC_WR_DV_REG(
-                                       VPP_WRAP_OSD1_MATRIX_EN_CTRL, 0x1);
+                                               VPP_WRAP_OSD1_MATRIX_EN_CTRL,
+                                               0x1);
                                        VSYNC_WR_DV_REG(
-                                       VPP_WRAP_OSD2_MATRIX_EN_CTRL, 0x1);
+                                               VPP_WRAP_OSD2_MATRIX_EN_CTRL,
+                                               0x1);
                                        VSYNC_WR_DV_REG(
-                                       VPP_WRAP_OSD3_MATRIX_EN_CTRL, 0x1);
+                                               VPP_WRAP_OSD3_MATRIX_EN_CTRL,
+                                               0x1);
                                }
                                VSYNC_WR_DV_REG_BITS(
                                        DOLBY_PATH_CTRL,
@@ -3561,12 +3607,16 @@ void enable_dolby_vision(int enable)
                core1_disp_hsize = 0;
                core1_disp_vsize = 0;
                dolby_vision_on = false;
+               force_reset_core2 = true;
                dolby_vision_core1_on = false;
                dolby_vision_wait_on = false;
                dolby_vision_wait_init = false;
                dolby_vision_wait_count = 0;
                dolby_vision_status = BYPASS_PROCESS;
                dolby_vision_on_count = 0;
+               cur_csc_type[VD1_PATH] = VPP_MATRIX_NULL;
+               hdr_osd_off();
+               hdr_vd1_off();
        }
 }
 EXPORT_SYMBOL(enable_dolby_vision);
@@ -3929,12 +3979,12 @@ static int sink_support_dolby_vision(const struct vinfo_s *vinfo)
                return 0;
        if (dolby_vision_flags & FLAG_DISABLE_DOVI_OUT)
                return 0;
-       if ((vinfo->width >= 1920) &&
-               (vinfo->height >= 1080) &&
-               (vinfo->field_height >= 1080))
-               return 1;
-       else
-               return 0;
+       if ((strstr(vinfo->name, "2160p60hz") != NULL) ||
+               (strstr(vinfo->name, "2160p50hz") != NULL)) {
+               if (!vinfo->vout_device->dv_info->sup_2160p60hz)
+                       return 0;
+       }
+       return 1;
 }
 
 static int sink_support_hdr(const struct vinfo_s *vinfo)
@@ -3947,6 +3997,145 @@ static int sink_support_hdr(const struct vinfo_s *vinfo)
        return 0;
 }
 
+static int sink_support_hdr10_plus(const struct vinfo_s *vinfo)
+{
+       if ((vinfo->hdr_info.hdr10plus_info.ieeeoui
+                       == 0x90848B) &&
+               (vinfo->hdr_info.hdr10plus_info.application_version
+                       == 1))
+               return 1;
+
+       return 0;
+}
+
+static bool is_vinfo_available(const struct vinfo_s *vinfo)
+{
+       return strcmp(vinfo->name, "invalid") &&
+               strcmp(vinfo->name, "null") &&
+               strcmp(vinfo->name, "576cvbs") &&
+               strcmp(vinfo->name, "470cvbs");
+}
+
+static int current_hdr_cap = -1; /* should set when probe */
+static int current_sink_available;
+static int is_sink_cap_changed(const struct vinfo_s *vinfo)
+{
+       int hdr_cap;
+       int sink_available;
+       int ret = 0;
+
+       if (is_vinfo_available(vinfo)) {
+               hdr_cap = (1 << 0) |
+                       (sink_support_dolby_vision(vinfo) << 1) |
+                       (sink_support_hdr10_plus(vinfo) << 2) |
+                       (sink_support_hdr(vinfo) << 3);
+               sink_available = 1;
+       } else {
+               hdr_cap = 0;
+               current_hdr_cap = 0;
+               sink_available = 0;
+       }
+       if (current_hdr_cap == -1) {
+               current_hdr_cap = hdr_cap;
+               pr_dolby_dbg("hdr cap=%d, output=%s\n",
+                       hdr_cap, vinfo->name);
+               ret |= 4;
+       } else if (current_hdr_cap != hdr_cap) {
+               pr_dolby_dbg("hdr cap changed %d->%d, video %s, output=%s\n",
+                       current_hdr_cap, hdr_cap,
+                       get_video_enabled() ? "on" : "off", vinfo->name);
+               current_hdr_cap = hdr_cap;
+               ret |= 2;
+       }
+       if (current_sink_available != sink_available) {
+               pr_dolby_dbg("sink available = %d\n", sink_available);
+               current_sink_available = sink_available;
+               ret |= 1;
+       }
+       return ret;
+}
+
+static int is_policy_changed(void)
+{
+       int ret = 0;
+
+       if (last_dolby_vision_policy != dolby_vision_policy) {
+               /* handle policy change */
+               pr_dolby_dbg("policy changed %d->%d\n",
+                       last_dolby_vision_policy,
+                       dolby_vision_policy);
+               last_dolby_vision_policy = dolby_vision_policy;
+               ret |= 1;
+       }
+#if 0 // do not need to monitor, since this is dynamic changing
+       if (last_dolby_vision_ll_policy != dolby_vision_ll_policy) {
+               /* handle policy change */
+               pr_dolby_dbg("ll policy changed %d->%d\n",
+                       last_dolby_vision_ll_policy,
+                       dolby_vision_ll_policy);
+               ret |= 2;
+       }
+#endif
+       if (last_dolby_vision_hdr10_policy != dolby_vision_hdr10_policy) {
+               /* handle policy change */
+               pr_dolby_dbg("hdr10 policy changed %d->%d\n",
+                       last_dolby_vision_hdr10_policy,
+                       dolby_vision_hdr10_policy);
+               last_dolby_vision_hdr10_policy = dolby_vision_hdr10_policy;
+               ret |= 4;
+       }
+       return ret;
+}
+
+static bool vf_is_hdr10_plus(struct vframe_s *vf);
+static bool vf_is_hdr10(struct vframe_s *vf);
+static bool vf_is_hlg(struct vframe_s *vf);
+
+static const char *input_str[7] = {
+       "NONE",
+       "HDR",
+       "HDR+",
+       "DOVI",
+       "PRIME",
+       "HLG",
+       "SDR"
+};
+
+static void update_src_format(
+       enum signal_format_e src_format, struct vframe_s *vf)
+{
+       enum signal_format_e cur_format = dolby_vision_src_format;
+
+       if (src_format == FORMAT_DOVI) {
+               dolby_vision_src_format = 3;
+       } else {
+               if (vf) {
+                       if (vf_is_hdr10_plus(vf))
+                               dolby_vision_src_format = 2;
+                       else if (vf_is_hdr10(vf))
+                               dolby_vision_src_format = 1;
+                       else if (vf_is_hlg(vf))
+                               dolby_vision_src_format = 5;
+                       else
+                               dolby_vision_src_format = 6;
+                       if (cur_format != dolby_vision_src_format) {
+                               pr_dolby_dbg(
+                                       "dolby_vision_src_format changed: %s => %s, signal_type = 0x%x\n",
+                                       input_str[cur_format],
+                                       input_str[dolby_vision_src_format],
+                                       vf->signal_type);
+                               cur_format = dolby_vision_src_format;
+                       }
+               }
+       }
+}
+
+int get_dolby_vision_src_format(void)
+{
+       return dolby_vision_src_format;
+}
+EXPORT_SYMBOL(get_dolby_vision_src_format);
+
 static int dolby_vision_policy_process(
        int *mode, enum signal_format_e src_format)
 {
@@ -4049,68 +4238,94 @@ static int dolby_vision_policy_process(
                                mode_change = 0;
                        return mode_change;
                }
-               if (vinfo && sink_support_dolby_vision(vinfo)) {
+
+               if (((src_format == FORMAT_HLG) ||
+                       (src_format == FORMAT_HDR10PLUS))
+                       && !(dolby_vision_hdr10_policy & 4)) {
+                       if (dolby_vision_mode !=
+                               DOLBY_VISION_OUTPUT_MODE_BYPASS) {
+                               if (debug_dolby & 2)
+                                       pr_dolby_dbg(
+                                               "hlg/hdr+, dovi output -> DOLBY_VISION_OUTPUT_MODE_BYPASS\n");
+                               *mode = DOLBY_VISION_OUTPUT_MODE_BYPASS;
+                               mode_change = 1;
+                       }
+               } else if ((cur_csc_type[VD1_PATH] != 0xffff) &&
+                       (get_hdr_module_status(VD1_PATH) == HDR_MODULE_ON) &&
+                       (src_format != FORMAT_DOVI) &&
+                       (src_format != FORMAT_DOVI_LL)) {
+                       /*if vpp is playing hlg/hdr10+*/
+                       /*dolby need bypass at this time*/
+                       if (dolby_vision_mode !=
+                               DOLBY_VISION_OUTPUT_MODE_BYPASS) {
+                               if (debug_dolby & 2)
+                                       pr_dolby_dbg(
+                                               "src=%d, hdr module on, dovi output -> DOLBY_VISION_OUTPUT_MODE_BYPASS\n",
+                                               src_format);
+                               *mode = DOLBY_VISION_OUTPUT_MODE_BYPASS;
+                               mode_change = 1;
+                       }
+                       return mode_change;
+               } else if (vinfo && sink_support_dolby_vision(vinfo)) {
                        /* TV support DOVI, All -> DOVI */
                        if (dolby_vision_mode !=
                        DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL) {
-                               pr_dolby_dbg("dovi output -> DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL\n");
+                               pr_dolby_dbg("src=%d, dovi output -> DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL\n",
+                                       src_format);
                                *mode = DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL;
                                mode_change = 1;
                        }
-               } else if (vinfo && sink_support_hdr(vinfo)
-                       && (dolby_vision_hdr10_policy & 2)) {
+               } else if (vinfo && sink_support_hdr(vinfo)) {
                        /* TV support HDR, All -> HDR */
                        if (dolby_vision_mode !=
                                DOLBY_VISION_OUTPUT_MODE_HDR10) {
-                               pr_dolby_dbg("dovi output -> DOLBY_VISION_OUTPUT_MODE_HDR10\n");
+                               pr_dolby_dbg("src=%d, dovi output -> DOLBY_VISION_OUTPUT_MODE_HDR10\n",
+                                       src_format);
                                *mode = DOLBY_VISION_OUTPUT_MODE_HDR10;
                                mode_change = 1;
                        }
                } else {
-                       /* TV not support DOVI */
+                       /* TV not support DOVI and HDR */
                        if ((src_format == FORMAT_DOVI) ||
                                (src_format == FORMAT_DOVI_LL)) {
                                /* DOVI to SDR */
                                if (dolby_vision_mode !=
                                DOLBY_VISION_OUTPUT_MODE_SDR8) {
-                                       pr_dolby_dbg("dovi output -> DOLBY_VISION_OUTPUT_MODE_SDR8\n");
-                                       *mode = DOLBY_VISION_OUTPUT_MODE_SDR8;
-                                       mode_change = 1;
-                               }
-                       } else if (src_format == FORMAT_HDR10
-                               && (dolby_vision_hdr10_policy & 1)) {
-                               if (dolby_vision_mode !=
-                               DOLBY_VISION_OUTPUT_MODE_SDR8) {
-                                       /* HDR10 to SDR */
-                                       pr_dolby_dbg("dovi output -> DOLBY_VISION_OUTPUT_MODE_SDR8\n");
+                                       pr_dolby_dbg("dovi, dovi output -> DOLBY_VISION_OUTPUT_MODE_SDR8\n");
                                        *mode = DOLBY_VISION_OUTPUT_MODE_SDR8;
                                        mode_change = 1;
                                }
-                       } else if (src_format == FORMAT_HDR10
-                               && (!(dolby_vision_hdr10_policy & 1))) {
-                               if (dolby_vision_mode !=
-                               DOLBY_VISION_OUTPUT_MODE_BYPASS) {
+                       } else if (src_format == FORMAT_HDR10) {
+                               if (dolby_vision_hdr10_policy & 0x01) {
+                                       if (dolby_vision_mode !=
+                                       DOLBY_VISION_OUTPUT_MODE_SDR8) {
+                                               /* HDR10 to SDR */
+                                               pr_dolby_dbg("hdr, dovi output -> DOLBY_VISION_OUTPUT_MODE_SDR8\n");
+                                               *mode =
+                                               DOLBY_VISION_OUTPUT_MODE_SDR8;
+                                               mode_change = 1;
+                                       }
+                               } else if (dolby_vision_mode !=
+                                       DOLBY_VISION_OUTPUT_MODE_BYPASS) {
                                        /* HDR bypass */
-                                       pr_dolby_dbg("dovi output -> DOLBY_VISION_OUTPUT_MODE_BYPASS\n");
+                                       pr_dolby_dbg("hdr, dovi output -> DOLBY_VISION_OUTPUT_MODE_BYPASS\n");
                                        *mode = DOLBY_VISION_OUTPUT_MODE_BYPASS;
                                        mode_change = 1;
                                }
                        } else if ((is_meson_g12b_cpu() && is_meson_rev_a()) ||
                                is_meson_g12a_cpu()) {
-                               /*g12 verA has a hardware bug.Therefore,dv cores
-                                *must keep working even if under sdr mode
-                                */
+                               /* dv cores keep on if in sdr mode */
                                if (dolby_vision_mode !=
-                                       DOLBY_VISION_OUTPUT_MODE_SDR8) {
+                               DOLBY_VISION_OUTPUT_MODE_SDR8) {
                                        /* SDR to SDR */
-                                       pr_dolby_dbg("dovi output -> DOLBY_VISION_OUTPUT_MODE_SDR8\n");
+                                       pr_dolby_dbg("sdr, dovi output -> DOLBY_VISION_OUTPUT_MODE_SDR8\n");
                                        *mode = DOLBY_VISION_OUTPUT_MODE_SDR8;
                                        mode_change = 1;
                                }
                        } else if (dolby_vision_mode !=
-                               DOLBY_VISION_OUTPUT_MODE_BYPASS) {
-                               /* SDR bypass */
-                               pr_dolby_dbg("dovi output -> DOLBY_VISION_OUTPUT_MODE_BYPASS\n");
+                       DOLBY_VISION_OUTPUT_MODE_BYPASS) {
+                               /* HDR/SDR bypass */
+                               pr_dolby_dbg("sdr, dovi output -> DOLBY_VISION_OUTPUT_MODE_BYPASS\n");
                                *mode = DOLBY_VISION_OUTPUT_MODE_BYPASS;
                                mode_change = 1;
                        }
@@ -4126,47 +4341,77 @@ static int dolby_vision_policy_process(
                                mode_change = 0;
                        return mode_change;
                }
-               if ((src_format == FORMAT_DOVI) ||
+               if ((cur_csc_type[VD1_PATH] != 0xffff) &&
+                       (get_hdr_module_status(VD1_PATH) == HDR_MODULE_ON) &&
+                       (src_format != FORMAT_DOVI) &&
+                       (src_format != FORMAT_DOVI_LL)) {
+                       /* bypass dolby incase VPP is not in sdr mode */
+                       if (dolby_vision_mode !=
+                               DOLBY_VISION_OUTPUT_MODE_BYPASS) {
+                               pr_dolby_dbg("hdr module on, dovi output -> DOLBY_VISION_OUTPUT_MODE_BYPASS\n");
+                               *mode = DOLBY_VISION_OUTPUT_MODE_BYPASS;
+                               mode_change = 1;
+                       }
+                       return mode_change;
+               } else if ((src_format == FORMAT_DOVI) ||
                        (src_format == FORMAT_DOVI_LL)) {
                        /* DOVI source */
                        if (vinfo && sink_support_dolby_vision(vinfo)) {
                                /* TV support DOVI, DOVI -> DOVI */
                                if (dolby_vision_mode !=
                                DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL) {
-                                       pr_dolby_dbg("dovi output -> DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL\n");
+                                       pr_dolby_dbg("dovi, dovi output -> DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL\n");
                                        *mode =
                                        DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL;
                                        mode_change = 1;
                                }
+                       } else if (vinfo && sink_support_hdr(vinfo)) {
+                               /* TV support HDR, DOVI -> HDR */
+                               if (dolby_vision_mode !=
+                               DOLBY_VISION_OUTPUT_MODE_HDR10) {
+                                       pr_dolby_dbg("dovi, dovi output -> DOLBY_VISION_OUTPUT_MODE_HDR10\n");
+                                       *mode = DOLBY_VISION_OUTPUT_MODE_HDR10;
+                                       mode_change = 1;
+                               }
                        } else {
-                               /* TV not support DOVI, DOVI -> SDR */
+                               /* TV not support DOVI and HDR, DOVI -> SDR */
                                if (dolby_vision_mode !=
                                DOLBY_VISION_OUTPUT_MODE_SDR8) {
-                                       pr_dolby_dbg("dovi output -> DOLBY_VISION_OUTPUT_MODE_SDR8\n");
+                                       pr_dolby_dbg("dovi, dovi output -> DOLBY_VISION_OUTPUT_MODE_SDR8\n");
                                        *mode = DOLBY_VISION_OUTPUT_MODE_SDR8;
                                        mode_change = 1;
                                }
                        }
-               } else if (src_format == FORMAT_HDR10
-                       && (dolby_vision_hdr10_policy & 1)) {
-                       if (dolby_vision_mode !=
-                       DOLBY_VISION_OUTPUT_MODE_SDR8) {
-                               /* HDR10 to SDR */
-                               pr_dolby_dbg("dovi output -> DOLBY_VISION_OUTPUT_MODE_SDR8\n");
-                               *mode = DOLBY_VISION_OUTPUT_MODE_SDR8;
-                               mode_change = 1;
+               } else if ((src_format == FORMAT_HDR10)
+               && (dolby_vision_hdr10_policy & 0x02)) {
+                       if (vinfo && sink_support_hdr(vinfo)) {
+                               /* TV support HDR, HDR -> HDR */
+                               if (dolby_vision_mode !=
+                               DOLBY_VISION_OUTPUT_MODE_HDR10) {
+                                       pr_dolby_dbg("hdr10, dovi output -> DOLBY_VISION_OUTPUT_MODE_HDR10\n");
+                                       *mode = DOLBY_VISION_OUTPUT_MODE_HDR10;
+                                       mode_change = 1;
+                               }
+                       } else {
+                               if (dolby_vision_mode !=
+                               DOLBY_VISION_OUTPUT_MODE_SDR8) {
+                                       /* HDR10 to SDR */
+                                       pr_dolby_dbg("hdr10, dovi output -> DOLBY_VISION_OUTPUT_MODE_SDR8\n");
+                                       *mode = DOLBY_VISION_OUTPUT_MODE_SDR8;
+                                       mode_change = 1;
+                               }
                        }
                } else if (dolby_vision_mode !=
                        DOLBY_VISION_OUTPUT_MODE_BYPASS) {
                        /* HDR/SDR bypass */
-                       pr_dolby_dbg("dovi output -> DOLBY_VISION_OUTPUT_MODE_BYPASS");
+                       pr_dolby_dbg("sdr, dovi output -> DOLBY_VISION_OUTPUT_MODE_BYPASS");
                        *mode = DOLBY_VISION_OUTPUT_MODE_BYPASS;
                        mode_change = 1;
                }
        } else if (dolby_vision_policy == DOLBY_VISION_FORCE_OUTPUT_MODE) {
                if (dolby_vision_mode != *mode) {
-                       pr_dolby_dbg("dovi output mode change %d -> %d\n",
-                               dolby_vision_mode, *mode);
+                       pr_dolby_dbg("src=%d, dovi output mode change %d -> %d\n",
+                               src_format, dolby_vision_mode, *mode);
                        mode_change = 1;
                }
        }
@@ -4247,7 +4492,59 @@ EXPORT_SYMBOL(is_dovi_dual_layer_frame);
 
 #define signal_color_primaries ((vf->signal_type >> 16) & 0xff)
 #define signal_transfer_characteristic ((vf->signal_type >> 8) & 0xff)
-static bool is_hdr10_frame(struct vframe_s *vf)
+
+static bool vf_is_hlg(struct vframe_s *vf)
+{
+       if (((signal_transfer_characteristic == 14) ||
+               (signal_transfer_characteristic == 18)) &&
+               (signal_color_primaries == 9))
+               return true;
+       return false;
+}
+
+static bool is_hlg_frame(struct vframe_s *vf)
+{
+       if (!vf)
+               return false;
+       if (!(dolby_vision_hdr10_policy & 4)) {
+               if (((signal_transfer_characteristic == 14) ||
+                       (signal_transfer_characteristic == 18)) &&
+                       (signal_color_primaries == 9))
+                       return true;
+       }
+
+       return false;
+}
+
+static bool vf_is_hdr10_plus(struct vframe_s *vf)
+{
+       if ((signal_transfer_characteristic == 0x30)
+               && ((signal_color_primaries == 9)
+               || (signal_color_primaries == 2)))
+               return true;
+       return false;
+}
+
+static bool is_hdr10plus_frame(struct vframe_s *vf)
+{
+       const struct vinfo_s *vinfo = get_current_vinfo();
+
+       if (!vf)
+               return false;
+       if (!(dolby_vision_hdr10_policy & 4)) {
+               /* report hdr10 for the content hdr10+ and
+                * sink is hdr10+ case
+                */
+               if ((signal_transfer_characteristic == 0x30)
+                       && (sink_support_hdr10_plus(vinfo))
+                       && ((signal_color_primaries == 9)
+                       || (signal_color_primaries == 2)))
+                       return true;
+       }
+       return false;
+}
+
+static bool vf_is_hdr10(struct vframe_s *vf)
 {
        if ((signal_transfer_characteristic == 16)
                && ((signal_color_primaries == 9)
@@ -4256,6 +4553,64 @@ static bool is_hdr10_frame(struct vframe_s *vf)
        return false;
 }
 
+static bool is_hdr10_frame(struct vframe_s *vf)
+{
+       const struct vinfo_s *vinfo = get_current_vinfo();
+
+       if (!vf)
+               return false;
+       if (((signal_transfer_characteristic == 16) ||
+               /* report hdr10 for the content hdr10+ and
+                * sink is not hdr10+ case
+                */
+               ((signal_transfer_characteristic == 0x30) &&
+               (!sink_support_hdr10_plus(vinfo))))
+               && ((signal_color_primaries == 9)
+               || (signal_color_primaries == 2)))
+               return true;
+       return false;
+}
+
+int dolby_vision_check_hlg(struct vframe_s *vf)
+{
+       int mode;
+
+       if (is_hlg_frame(vf) && !dolby_vision_on) {
+               /* dovi source, but dovi not enabled */
+               mode = dolby_vision_mode;
+               if (dolby_vision_policy_process(
+                       &mode, FORMAT_HLG)) {
+                       if ((mode != DOLBY_VISION_OUTPUT_MODE_BYPASS)
+                               && (dolby_vision_mode ==
+                               DOLBY_VISION_OUTPUT_MODE_BYPASS))
+                               dolby_vision_wait_on = true;
+                       return 1;
+               }
+       }
+       return 0;
+}
+EXPORT_SYMBOL(dolby_vision_check_hlg);
+
+int dolby_vision_check_hdr10plus(struct vframe_s *vf)
+{
+       int mode;
+
+       if (is_hdr10plus_frame(vf) && !dolby_vision_on) {
+               /* dovi source, but dovi not enabled */
+               mode = dolby_vision_mode;
+               if (dolby_vision_policy_process(
+                       &mode, FORMAT_HDR10PLUS)) {
+                       if ((mode != DOLBY_VISION_OUTPUT_MODE_BYPASS)
+                               && (dolby_vision_mode ==
+                               DOLBY_VISION_OUTPUT_MODE_BYPASS))
+                               dolby_vision_wait_on = true;
+                       return 1;
+               }
+       }
+       return 0;
+}
+EXPORT_SYMBOL(dolby_vision_check_hdr10plus);
+
 int dolby_vision_check_hdr10(struct vframe_s *vf)
 {
        int mode;
@@ -4567,28 +4922,6 @@ static u32 bt2020_white_point[2] = {
        0.3127 * INORM + 0.5, 0.3290 * INORM + 0.5
 };
 
-static int check_primaries(struct vframe_master_display_colour_s *p_mdc)
-{
-       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 */
-       return 0;
-}
-
-
 void prepare_hdr10_param(
        struct vframe_master_display_colour_s *p_mdc,
        struct hdr10_param_s *p_hdr10_param)
@@ -4628,8 +4961,11 @@ void prepare_hdr10_param(
                return;
        }
 
-       primaries_type = check_primaries(p_mdc);
+       primaries_type = get_primaries_type(p_mdc);
        if (primaries_type == 2) {
+               /* GBR -> RGB as dolby will swap back to GBR
+                * in send_hdmi_pkt
+                */
                if ((p_hdr10_param->
                max_display_mastering_luminance
                        != p_mdc->luminance[0])
@@ -4677,6 +5013,9 @@ void prepare_hdr10_param(
                                = p_mdc->white_point[1];
                }
        } else if (primaries_type == 1) {
+               /* RGB -> RGB and dolby will swap to send as GBR
+                * in send_hdmi_pkt
+                */
                if ((p_hdr10_param->
                max_display_mastering_luminance
                        != p_mdc->luminance[0])
@@ -4724,6 +5063,9 @@ void prepare_hdr10_param(
                                = p_mdc->white_point[1];
                }
        } else {
+               /* GBR -> RGB as dolby will swap back to GBR
+                * in send_hdmi_pkt
+                */
                if ((p_hdr10_param->
                min_display_mastering_luminance
                        != min_lum)
@@ -4876,13 +5218,15 @@ static int prepare_vsif_pkt(
 static u32 last_dst_format = FORMAT_SDR;
 static bool send_hdmi_pkt(
        enum signal_format_e dst_format,
-       const struct vinfo_s *vinfo)
+       const struct vinfo_s *vinfo, struct vframe_s *vf)
 {
        struct hdr_10_infoframe_s *p_hdr;
        int i;
        bool flag = false;
+       static int sdr_transition_delay;
 
        if (dst_format == FORMAT_HDR10) {
+               sdr_transition_delay = 0;
                p_hdr = &dovi_setting.hdr_info;
                hdr10_data.features =
                          (1 << 29)     /* video available */
@@ -4993,8 +5337,10 @@ static bool send_hdmi_pkt(
 #ifdef HDMI_SEND_ALL_PKT
                if (vinfo && vinfo->vout_device &&
                        vinfo->vout_device->fresh_tx_vsif_pkt)
-                       vinfo->vout_device->fresh_tx_vsif_pkt(0, 0, NULL);
+                       vinfo->vout_device->fresh_tx_vsif_pkt(0, 0, NULL, true);
 #endif
+               if (last_dst_format != FORMAT_HDR10)
+                       pr_info("send_hdmi_pkt: HDR10\n");
                last_dst_format = dst_format;
                if (flag) {
                        pr_dolby_dbg("Info frame for hdr10 changed:\n");
@@ -5019,6 +5365,7 @@ static bool send_hdmi_pkt(
        } else if (dst_format == FORMAT_DOVI) {
                struct dv_vsif_para vsif;
 
+               sdr_transition_delay = 0;
                memset(&vsif, 0, sizeof(vsif));
 #ifdef V2_4
                if (vinfo)
@@ -5056,47 +5403,79 @@ static bool send_hdmi_pkt(
                                        EOTF_T_LL_MODE,
                                        dovi_setting.diagnostic_enable
                                        ? RGB_10_12BIT : YUV422_BIT12,
-                                       &vsif);
+                                       &vsif, false);
                        else
 #endif
                                vinfo->vout_device->fresh_tx_vsif_pkt(
                                        EOTF_T_DOLBYVISION,
                                        dolby_vision_mode ==
                                        DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL
-                                       ? RGB_8BIT : YUV422_BIT12, &vsif);
+                                       ? RGB_8BIT : YUV422_BIT12, &vsif,
+                                       false);
                }
+               if (last_dst_format != FORMAT_DOVI)
+                       pr_info("send_hdmi_pkt: %s\n",
+                               dovi_setting.dovi_ll_enable ? "LL" : "DV");
                last_dst_format = dst_format;
        } else if (last_dst_format != dst_format) {
                if (last_dst_format == FORMAT_HDR10) {
-                       hdr10_data.features =
-                                 (1 << 29)     /* video available */
-                               | (5 << 26)     /* unspecified */
-                               | (0 << 25)     /* limit */
-                               | (1 << 24)     /* color available */
-                               | (1 << 16)     /* bt709 */
-                               | (1 << 8)      /* bt709 */
-                               | (1 << 0);     /* bt709 */
-                       for (i = 0; i < 3; i++) {
-                               hdr10_data.primaries[i][0] = 0;
-                               hdr10_data.primaries[i][1] = 0;
+                       sdr_transition_delay = 0;
+                       if (!(vf && (is_hlg_frame(vf) ||
+                               is_hdr10plus_frame(vf)))) {
+                               hdr10_data.features =
+                                         (1 << 29)     /* video available */
+                                       | (5 << 26)     /* unspecified */
+                                       | (0 << 25)     /* limit */
+                                       | (1 << 24)     /* color available */
+                                       | (1 << 16)     /* bt709 */
+                                       | (1 << 8)      /* bt709 */
+                                       | (1 << 0);     /* bt709 */
+                               for (i = 0; i < 3; i++) {
+                                       hdr10_data.primaries[i][0] = 0;
+                                       hdr10_data.primaries[i][1] = 0;
+                               }
+                               hdr10_data.white_point[0] = 0;
+                               hdr10_data.white_point[1] = 0;
+                               hdr10_data.luminance[0] = 0;
+                               hdr10_data.luminance[1] = 0;
+                               hdr10_data.max_content = 0;
+                               hdr10_data.max_frame_average = 0;
+                               if (vinfo && vinfo->vout_device &&
+                                       vinfo->vout_device->fresh_tx_hdr_pkt)
+                                       vinfo->vout_device->fresh_tx_hdr_pkt(
+                                               &hdr10_data);
                        }
-                       hdr10_data.white_point[0] = 0;
-                       hdr10_data.white_point[1] = 0;
-                       hdr10_data.luminance[0] = 0;
-                       hdr10_data.luminance[1] = 0;
-                       hdr10_data.max_content = 0;
-                       hdr10_data.max_frame_average = 0;
-                       if (vinfo && vinfo->vout_device &&
-                               vinfo->vout_device->fresh_tx_hdr_pkt)
-                               vinfo->vout_device->fresh_tx_hdr_pkt(
-                                       &hdr10_data);
+                       last_dst_format = dst_format;
                } else if (last_dst_format == FORMAT_DOVI) {
                        if (vinfo && vinfo->vout_device &&
-                               vinfo->vout_device->fresh_tx_vsif_pkt)
-                               vinfo->vout_device->fresh_tx_vsif_pkt(
-                                       0, 0, NULL);
+                               vinfo->vout_device->fresh_tx_vsif_pkt) {
+                               if (vf && (is_hlg_frame(vf) ||
+                                       is_hdr10plus_frame(vf))) {
+                                       /* HLG/HDR10+ case: first switch to SDR
+                                        * immediately.
+                                        */
+                                       pr_info("send_hdmi_pkt: HDR10+/HLG: signal SDR first\n");
+                                       vinfo->vout_device->fresh_tx_vsif_pkt(
+                                               0, 0, NULL, true);
+                                       last_dst_format = dst_format;
+                                       sdr_transition_delay = 0;
+                               } else if (sdr_transition_delay >=
+                                               MAX_TRANSITION_DELAY) {
+                                       pr_info("send_hdmi_pkt: VSIF disabled, signal SDR\n");
+                                       vinfo->vout_device->fresh_tx_vsif_pkt(
+                                               0, 0, NULL, true);
+                                       last_dst_format = dst_format;
+                                       sdr_transition_delay = 0;
+                               } else {
+                                       if (sdr_transition_delay == 0) {
+                                       pr_info("send_hdmi_pkt: disable Dovi/H14b VSIF\n");
+                                       vinfo->vout_device->fresh_tx_vsif_pkt(
+                                               0, 0, NULL, false);
+                                       }
+                                       sdr_transition_delay++;
+                               }
+                       }
                }
-               last_dst_format = dst_format;
        }
        return flag;
 }
@@ -5115,10 +5494,12 @@ static int is_video_output_off(struct vframe_s *vf)
                        null_vf_cnt++;
                else
                        null_vf_cnt = 0;
-               if (null_vf_cnt > dolby_vision_wait_delay + 3) {
+               if (null_vf_cnt > dolby_vision_wait_delay + 1) {
                        null_vf_cnt = 0;
                        return 1;
                }
+               if (video_off_handled)
+                       return 1;
        } else
                video_off_handled = 0;
        return 0;
@@ -5209,6 +5590,8 @@ int dolby_vision_parse_metadata(
        u32 graphic_min = 50; /* 0.0001 */
        u32 graphic_max = 100; /* 1 */
        int ret_flags = 0;
+       static int bypass_frame = -1;
+       static int last_current_format;
        int ret = -1;
        bool mel_flag = false;
 
@@ -5378,6 +5761,17 @@ int dolby_vision_parse_metadata(
                        src_bdp = 10;
                        req.dv_enhance_exist = 0;
                }
+
+               if ((src_format != FORMAT_DOVI)
+                       && is_hlg_frame(vf)) {
+                       src_format = FORMAT_HLG;
+               }
+
+               if ((src_format != FORMAT_DOVI)
+                       && is_hdr10plus_frame(vf)) {
+                       src_format = FORMAT_HDR10PLUS;
+               }
+
 #ifdef V2_4
                /* TODO: need 962e ? */
                if ((src_format == FORMAT_SDR)
@@ -5389,11 +5783,13 @@ int dolby_vision_parse_metadata(
                        || (frame_count == 0))
                        && (toggle_mode == 1))
                        pr_info(
-                       "DOLBY: frame %d pts %lld, src bdp: %d format: %s, aux_size:%d, enhance: %d\n",
+                       "frame %d pts %lld, src bdp: %d format: %s, aux_size:%d, enhance: %d\n",
                        frame_count, vf->pts_us64, src_bdp,
                        (src_format == FORMAT_HDR10) ? "HDR10" :
                        (src_format == FORMAT_DOVI ? "DOVI" :
-                       (req.dv_enhance_exist ? "DOVI (el meta)" : "SDR")),
+                       (src_format == FORMAT_HLG ? "HLG" :
+                       (src_format == FORMAT_HDR10PLUS ? "HDR10+" :
+                       (req.dv_enhance_exist ? "DOVI (el meta)" : "SDR")))),
                        req.aux_size, req.dv_enhance_exist);
                if ((src_format != FORMAT_DOVI)
                        && !req.dv_enhance_exist)
@@ -5491,8 +5887,9 @@ int dolby_vision_parse_metadata(
                        else
                                el_flag = tv_dovi_setting->el_flag;
                        mel_flag = mel_mode;
-                       pr_dolby_dbg("update el_flag %d, melFlag %d\n",
-                               el_flag, mel_flag);
+                       if (debug_dolby & 2)
+                               pr_dolby_dbg("update el_flag %d, melFlag %d\n",
+                                       el_flag, mel_flag);
                        meta_flag_bl = 0;
                }
 
@@ -5549,12 +5946,41 @@ int dolby_vision_parse_metadata(
                dolby_vision_mode = current_mode;
                if (is_dolby_vision_stb_mode())
                        new_dovi_setting.mode_changed = 1;
+               pr_dolby_dbg("[dolby_vision_parse_metadata] output change from %d to %d(%d, %p, %d)\n",
+                       dolby_vision_mode, current_mode,
+                       toggle_mode, vf, src_format);
+       }
+       if (vf) {
+               update_src_format(check_format, vf);
+               last_current_format = check_format;
+       }
+
+       if ((get_hdr_module_status(VD1_PATH) != HDR_MODULE_ON)
+       && (check_format == FORMAT_SDR)) {
+               /* insert 2 SDR frames before send DOVI */
+               if (((dolby_vision_mode == DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL)
+               || (dolby_vision_mode == DOLBY_VISION_OUTPUT_MODE_IPT))
+               && ((last_current_format == FORMAT_HLG)
+               || (last_current_format == FORMAT_HDR10PLUS))) {
+                       bypass_frame = 0;
+                       pr_dolby_dbg("[dolby_vision_parse_metadata] source transition from %d to %d\n",
+                               last_current_format, check_format);
+               }
+               last_current_format = check_format;
        }
 
+       if ((bypass_frame >= 0) && (bypass_frame < MIN_TRANSITION_DELAY)) {
+               dolby_vision_mode = DOLBY_VISION_OUTPUT_MODE_BYPASS;
+               bypass_frame++;
+       } else
+               bypass_frame = -1;
+
        if (dolby_vision_mode == DOLBY_VISION_OUTPUT_MODE_BYPASS) {
                new_dovi_setting.video_width = 0;
                new_dovi_setting.video_height = 0;
                new_dovi_setting.mode_changed = 0;
+               if (get_hdr_module_status(VD1_PATH) == HDR_MODULE_BYPASS)
+                       return 1;
                return -1;
        }
 
@@ -5719,29 +6145,18 @@ int dolby_vision_parse_metadata(
        if (dolby_vision_graphic_max != 0)
                graphic_max = dolby_vision_graphic_max;
        else {
-               graphic_max =
-                       dv_target_graphics_max[src_format][dst_format];
-
                if ((dolby_vision_flags & FLAG_FORCE_DOVI_LL) ||
-                       (dolby_vision_ll_policy >= DOLBY_VISION_LL_YUV422)) {
+               (dolby_vision_ll_policy >= DOLBY_VISION_LL_YUV422)) {
                        graphic_max =
-                       dv_target_graphics_LL_max[src_format][dst_format];
+                               dv_target_graphics_LL_max
+                                       [src_format][dst_format];
+               } else {
+                       graphic_max =
+                               dv_target_graphics_max
+                                       [src_format][dst_format];
                }
        }
 
-       if (is_graphics_output_off()) {
-               graphic_min = 0;
-               graphic_max = 0;
-               is_osd_off = true;
-       } else {
-               /* force reset core2 when osd off->on */
-               /* TODO: 962e need ? */
-               if (is_osd_off)
-                       force_reset_core2 = true;
-               if (new_dovi_setting.mode_changed)
-                       force_reset_core2 = true;
-               is_osd_off = false;
-       }
        if (dolby_vision_flags & FLAG_USE_SINK_MIN_MAX) {
                if (vinfo->vout_device->dv_info->ieeeoui == 0x00d046) {
                        if (vinfo->vout_device->dv_info->ver == 0) {
@@ -5795,6 +6210,9 @@ int dolby_vision_parse_metadata(
                }
        }
 
+       if (is_osd_off)
+               graphic_min = graphic_max = 0;
+
 #ifdef V2_4
        if ((src_format != dovi_setting.src_format)
                || (dst_format != dovi_setting.dst_format) ||
@@ -5897,6 +6315,14 @@ int dolby_vision_parse_metadata(
                        new_dovi_setting.vsvdb_len = 0;
                }
        }
+
+#if 0 /* check video/graphics priority on the fly */
+       if (get_video_enabled() && is_graphics_output_off())
+               dolby_vision_graphics_priority = 0;
+       else
+               dolby_vision_graphics_priority = 1;
+#endif
+
        if (dolby_vision_graphics_priority ||
                (dolby_vision_flags &
                FLAG_PRIORITY_GRAPHIC))
@@ -6003,8 +6429,15 @@ int dolby_vision_parse_metadata(
                new_dovi_setting.video_height = h;
                dovi_setting_video_flag = video_frame;
                if (debug_dolby & 1) {
+                       if (is_video_output_off(vf))
+                               pr_dolby_dbg("setting %d->%d(T:%d-%d), osd:%dx%d\n",
+                               src_format, dst_format,
+                               dolby_vision_target_min,
+                               dolby_vision_target_max[src_format][dst_format],
+                               osd_graphic_width,
+                               osd_graphic_height);
                        if (el_flag)
-                               pr_dolby_dbg("setting %d->%d(T:%d-%d): flag=%x,md=%d,comp=%d, frame:%d\n",
+                               pr_dolby_dbg("setting %d->%d(T:%d-%d): flag=%x, md=%d,comp=%d, frame:%d\n",
                                src_format, dst_format,
                                dolby_vision_target_min,
                                dolby_vision_target_max[src_format][dst_format],
@@ -6012,7 +6445,7 @@ int dolby_vision_parse_metadata(
                                total_md_size, total_comp_size,
                                frame_count);
                        else
-                               pr_dolby_dbg("setting %d->%d(T:%d-%d): flag=%x,md=%d, frame:%d\n",
+                               pr_dolby_dbg("setting %d->%d(T:%d-%d): flag=%x, md=%d, frame:%d\n",
                                src_format, dst_format,
                                dolby_vision_target_min,
                                dolby_vision_target_max[src_format][dst_format],
@@ -6027,7 +6460,8 @@ int dolby_vision_parse_metadata(
        if (flag < 0) {
                new_dovi_setting.video_width = 0;
                new_dovi_setting.video_height = 0;
-               pr_dolby_error("control_path() failed\n");
+               pr_dolby_error("control_path(%d, %d) failed\n",
+                       src_format, dst_format);
        }
        return -1; /* do nothing for this frame */
 }
@@ -6043,6 +6477,7 @@ int dolby_vision_wait_metadata(struct vframe_s *vf)
        struct vframe_s *el_vf;
        int ret = 0;
        unsigned int mode = dolby_vision_mode;
+       enum signal_format_e check_format;
 
        if (single_step_enable) {
                if (dolby_vision_flags & FLAG_SINGLE_STEP)
@@ -6121,32 +6556,18 @@ int dolby_vision_wait_metadata(struct vframe_s *vf)
 
        if (!dolby_vision_wait_init
                && !dolby_vision_core1_on) {
-               if (is_dovi_frame(vf)) {
-                       if (dolby_vision_policy_process(
-                               &mode, FORMAT_DOVI)) {
-                               if ((mode != DOLBY_VISION_OUTPUT_MODE_BYPASS)
-                               && (dolby_vision_mode ==
-                               DOLBY_VISION_OUTPUT_MODE_BYPASS)) {
-                                       dolby_vision_wait_init = true;
-                                       dolby_vision_wait_count =
-                                               dolby_vision_wait_delay;
-                                       dolby_vision_wait_on = true;
-                               }
-                       }
-               } else if (is_hdr10_frame(vf)) {
-                       if (dolby_vision_policy_process(
-                               &mode, FORMAT_HDR10)) {
-                               if ((mode != DOLBY_VISION_OUTPUT_MODE_BYPASS)
-                               && (dolby_vision_mode ==
-                               DOLBY_VISION_OUTPUT_MODE_BYPASS)) {
-                                       dolby_vision_wait_init = true;
-                                       dolby_vision_wait_count =
-                                               dolby_vision_wait_delay;
-                                       dolby_vision_wait_on = true;
-                               }
-                       }
-               } else if (dolby_vision_policy_process(
-                       &mode, FORMAT_SDR)) {
+               if (is_dovi_frame(vf))
+                       check_format = FORMAT_DOVI;
+               else if (is_hdr10_frame(vf))
+                       check_format = FORMAT_HDR10;
+               else if (is_hlg_frame(vf))
+                       check_format = FORMAT_HLG;
+               else if (is_hdr10plus_frame(vf))
+                       check_format = FORMAT_HDR10PLUS;
+               else
+                       check_format = FORMAT_SDR;
+               if (dolby_vision_policy_process(
+                       &mode, check_format)) {
                        if ((mode != DOLBY_VISION_OUTPUT_MODE_BYPASS)
                                && (dolby_vision_mode ==
                                DOLBY_VISION_OUTPUT_MODE_BYPASS)) {
@@ -6154,8 +6575,13 @@ int dolby_vision_wait_metadata(struct vframe_s *vf)
                                dolby_vision_wait_count =
                                        dolby_vision_wait_delay;
                                dolby_vision_wait_on = true;
+                               pr_dolby_dbg("dolby_vision_need_wait src=%d mode=%d\n",
+                                       check_format, mode);
                        }
                }
+               if (vf)
+                       update_src_format(check_format, vf);
+
                /* don't use run mode when sdr -> dv and vd1 not disable */
                if (dolby_vision_wait_init &&
                        (READ_VPP_DV_REG(VPP_MISC) & (1<<10)))
@@ -6240,7 +6666,6 @@ static void bypass_pps_path(u8 pps_state)
        }
 }
 
-static unsigned int last_dolby_vision_policy;
 int dolby_vision_process(struct vframe_s *vf, u32 display_size,
        u8 pps_state) /* 0: no change, 1: pps enable, 2: pps disable */
 {
@@ -6250,6 +6675,8 @@ int dolby_vision_process(struct vframe_s *vf, u32 display_size,
        const struct vinfo_s *vinfo = get_current_vinfo();
        bool reset_flag = false;
        bool force_set = false;
+       static int sdr_delay;
+       unsigned int mode;
 
        if (!is_meson_box() && !is_meson_txlx() && !is_meson_tm2())
                return -1;
@@ -6313,30 +6740,34 @@ int dolby_vision_process(struct vframe_s *vf, u32 display_size,
                && !video_off_handled) {
                dolby_vision_set_toggle_flag(1);
                frame_count = 0;
+               video_off_handled = 1;
                if (debug_dolby & 2) {
-                       video_off_handled = 1;
                        pr_dolby_dbg("video off\n");
                }
        }
 
-       if (last_dolby_vision_policy != dolby_vision_policy) {
-               /* handle policy change */
+       if (is_sink_cap_changed(vinfo)) {
+               if (vf)
+                       dolby_vision_parse_metadata(vf, 1, false);
                dolby_vision_set_toggle_flag(1);
-               last_dolby_vision_policy = dolby_vision_policy;
        }
 
-#ifdef V2_4
-       if (is_meson_txlx_stbmode()  || is_meson_box()
-               || is_meson_tm2_stbmode() || force_stb_mode) {
-               if (last_dolby_vision_ll_policy
-                       != dolby_vision_ll_policy) {
-                       /* handle ll mode policy change */
-                       dolby_vision_set_toggle_flag(1);
-               }
-       }
-#endif
+       /* only monitor dolby_vision_policy */
+       /* other policy will be updated for video */
+       if (is_policy_changed() & 1)
+               dolby_vision_set_toggle_flag(1);
+       if (is_graphic_changed())
+               dolby_vision_set_toggle_flag(1);
 
-       if (!vf) {
+       if (!vf && !get_video_enabled()) {
+               if (dolby_vision_policy == DOLBY_VISION_FOLLOW_SINK
+               && !is_dolby_vision_video_on()) {
+                       if (dolby_vision_policy_process(
+                               &mode, FORMAT_SDR)) {
+                               dolby_vision_set_toggle_flag(1);
+                               pr_dolby_dbg("Fake SDR, mode->%d\n", mode);
+                       }
+               }
                if (dolby_vision_flags & FLAG_TOGGLE_FRAME)
                        dolby_vision_parse_metadata(
                                NULL, 1, false);
@@ -6354,15 +6785,43 @@ int dolby_vision_process(struct vframe_s *vf, u32 display_size,
                        }
                }
                if (dolby_vision_status != BYPASS_PROCESS) {
-                       enable_dolby_vision(0);
-                       if (vinfo &&
-                               !is_meson_tvmode() &&
-                               !force_stb_mode)
-                               send_hdmi_pkt(FORMAT_SDR, vinfo);
+                       if (vinfo && !is_meson_tvmode() &&
+                               !force_stb_mode) {
+                               if (vf && is_hdr10plus_frame(vf)) {
+                                       /* disable dolby immediately */
+                                       pr_info("Dolby bypass: HDR10+: Switched to SDR first\n");
+                                       send_hdmi_pkt(FORMAT_SDR, vinfo, vf);
+                                       enable_dolby_vision(0);
+                               } else if (vf && is_hlg_frame(vf)) {
+                                       /* disable dolby immediately */
+                                       pr_info("Dolby bypass: HLG: Switched to SDR first\n");
+                                       send_hdmi_pkt(FORMAT_SDR, vinfo, vf);
+                                       enable_dolby_vision(0);
+                               } else if (last_dst_format != FORMAT_DOVI) {
+                                       /* disable dolby immediately */
+                                       pr_info("Dolby bypass: Switched %d to SDR\n",
+                                               last_dst_format);
+                                       send_hdmi_pkt(FORMAT_SDR, vinfo, vf);
+                                       enable_dolby_vision(0);
+                               } else {
+                                       send_hdmi_pkt(FORMAT_SDR, vinfo, vf);
+                                       if (sdr_delay >= MAX_TRANSITION_DELAY) {
+                                               pr_info("Dolby bypass: Done - Switched to SDR\n");
+                                               enable_dolby_vision(0);
+                                               sdr_delay = 0;
+                                       }
+                                       sdr_delay++;
+                               }
+                       } else
+                               enable_dolby_vision(0);
+
                        if (dolby_vision_flags & FLAG_TOGGLE_FRAME)
                                dolby_vision_flags &= ~FLAG_TOGGLE_FRAME;
                }
                return 0;
+       } else if (sdr_delay != 0) {
+               /* in case mode change to a mode requiring dolby block */
+               sdr_delay = 0;
        }
 
        if ((dolby_vision_flags & FLAG_CERTIFICAION)
@@ -6456,7 +6915,8 @@ int dolby_vision_process(struct vframe_s *vf, u32 display_size,
                                /* send HDMI packet according to dst_format */
                                if (vinfo && !force_stb_mode)
                                        send_hdmi_pkt(
-                                               dovi_setting.dst_format, vinfo);
+                                               dovi_setting.dst_format,
+                                               vinfo, vf);
                                update_dolby_vision_status(
                                        dovi_setting.src_format);
                        }
@@ -6561,6 +7021,13 @@ bool is_dolby_vision_on(void)
 }
 EXPORT_SYMBOL(is_dolby_vision_on);
 
+bool is_dolby_vision_video_on(void)
+{
+       return dolby_vision_core1_on;
+}
+EXPORT_SYMBOL(is_dolby_vision_video_on);
+
+
 bool for_dolby_vision_certification(void)
 {
        return is_dolby_vision_on() &&
@@ -6624,6 +7091,12 @@ bool is_dolby_vision_el_disable(void)
 }
 EXPORT_SYMBOL(is_dolby_vision_el_disable);
 
+int get_dolby_vision_policy(void)
+{
+       return dolby_vision_policy;
+}
+EXPORT_SYMBOL(get_dolby_vision_policy);
+
 int register_dv_functions(const struct dolby_vision_func_s *func)
 {
        int ret = -1;
index b3da1b5..75b9444 100644 (file)
@@ -205,7 +205,9 @@ enum signal_format_e {
        FORMAT_HDR10 = 1,
        FORMAT_SDR = 2,
        FORMAT_DOVI_LL = 3,
-       FORMAT_SDR_2020 = 4
+       FORMAT_HLG = 4,
+       FORMAT_HDR10PLUS = 5,
+       FORMAT_SDR_2020 = 6
 };
 
 enum priority_mode_e {
@@ -532,6 +534,7 @@ struct dovi_setting_s {
        uint32_t vout_width;
        uint32_t vout_height;
        u8 vsvdb_tbl[32];
+       u8 hdrdb_tbl[7];
        struct ext_md_s ext_md;
        uint32_t vsvdb_len;
        uint32_t vsvdb_changed;
index 4e258fb..07733fb 100644 (file)
@@ -6,6 +6,7 @@ obj-$(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM) += am_vecm.o
 am_vecm-objs := amve.o
 am_vecm-objs += amcm.o
 am_vecm-objs += amcsc.o
+am_vecm-objs += amcsc_pip.o
 am_vecm-objs += amvecm.o
 am_vecm-objs += keystone_correction.o
 am_vecm-objs += bitdepth.o
index 3efccde..e9c930b 100644 (file)
 #include "../../osd/osd_rdma.h"
 
 #include "amcsc.h"
+#include "amcsc_pip.h"
 #include "set_hdr2_v0.h"
 #include <linux/amlogic/media/amdolbyvision/dolby_vision.h>
 #include "hdr/am_hdr10_plus.h"
 #include "hdr/am_hdr10_plus_ootf.h"
 
-#define pr_csc(fmt, args...)\
-       do {\
-               if (debug_csc)\
-                       pr_info(fmt, ## args);\
-       } while (0)
+
+uint debug_csc;
+module_param(debug_csc, uint, 0664);
+MODULE_PARM_DESC(debug_csc, "\n debug_csc\n");
 
 signed int vd1_contrast_offset;
 
 signed int saturation_offset;
 
 /*hdr------------------------------------*/
+
+void hdr_osd_off(void)
+{
+       enum hdr_process_sel cur_hdr_process;
+
+       cur_hdr_process = hdr_func(OSD1_HDR, HDR_BYPASS, get_current_vinfo());
+       pr_csc(8, "am_vecm: module=OSD1_HDR, process=HDR_BYPASS(%d, %d)\n",
+               HDR_BYPASS, cur_hdr_process);
+}
+
+void hdr_vd1_off(void)
+{
+       enum hdr_process_sel cur_hdr_process;
+
+       cur_hdr_process = hdr_func(VD1_HDR, HDR_BYPASS, get_current_vinfo());
+       pr_csc(8, "am_vecm: module=VD1_HDR, process=HDR_BYPASS(%d, %d)\n",
+               HDR_BYPASS, cur_hdr_process);
+}
+
 static struct hdr_data_t *phdr;
 
 struct hdr_data_t *hdr_get_data(void)
@@ -108,7 +127,7 @@ static ssize_t write_file_hdr_cfgosd(
 
        hdr_set_cfg_osd_100(val);
 
-       pr_info("hdr:en_osd_lut_100: %d\n", phdr->hdr_cfg.en_osd_lut_100);
+       pr_info("en_osd_lut_100: %d\n", phdr->hdr_cfg.en_osd_lut_100);
 
        return count;
 }
@@ -272,10 +291,6 @@ static struct vframe_s *dbg_vf;
 static struct master_display_info_s dbg_hdr_send;
 static struct hdr_info receiver_hdr_info;
 
-static uint debug_csc;
-module_param(debug_csc, uint, 0664);
-MODULE_PARM_DESC(debug_csc, "\n debug_csc\n");
-
 static bool print_lut_mtx;
 module_param(print_lut_mtx, bool, 0664);
 MODULE_PARM_DESC(print_lut_mtx, "\n print_lut_mtx\n");
@@ -307,9 +322,15 @@ static int wb_val[10] = {
 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 = VFRAME_SOURCE_TYPE_COMP;
-uint cur_csc_type = 0xffff;
-module_param(cur_csc_type, uint, 0444);
+static enum vframe_source_type_e pre_src_type[VD_PATH_MAX] = {
+       VFRAME_SOURCE_TYPE_COMP,
+       VFRAME_SOURCE_TYPE_COMP
+};
+
+static unsigned int vd_path_max = VD_PATH_MAX;
+
+uint cur_csc_type[VD_PATH_MAX] = {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");
 
 static uint hdmi_csc_type = 0xffff;
@@ -320,36 +341,46 @@ 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");
 
-static uint hdr_process_mode = 1; /* 0: hdr->hdr, 1:hdr->sdr */
-static uint cur_hdr_process_mode = 2; /* 0: hdr->hdr, 1:hdr->sdr */
-module_param(hdr_process_mode, uint, 0444);
+static uint cur_hdr_mode;
+
+/* 0: hdr->hdr, 1:hdr->sdr, 2:hdr->hlg */
+uint hdr_process_mode[VD_PATH_MAX];
+uint cur_hdr_process_mode[VD_PATH_MAX] = {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");
 
-static uint hdr10_plus_process_mode; /* 0: bypass, 1:hdr10p->sdr */
-static uint cur_hdr10_plus_process_mode = 2; /* 0: bypass, 1:hdr10p->sdr */
+/* 0:bypass, 1:hdr10p->hdr, 2:hdr10p->sdr, 3:hdr10p->hlg */
+uint hdr10_plus_process_mode[VD_PATH_MAX];
+uint cur_hdr10_plus_process_mode[VD_PATH_MAX] = {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: tx don't support hdr10+, 1: tx support hdr10+*/
-static uint tx_hdr10_plus_support;
+uint tx_hdr10_plus_support;
 
-/* 0: hlg->hlg, 1:hlg->hdr*/
-static uint hlg_process_mode = 1;
-/* 0: hdr->hdr, 1:hdr->sdr 2:hlg->hdr*/
-static uint cur_hlg_process_mode = 2;
-module_param(hlg_process_mode, uint, 0444);
+/* 0: hlg->hlg, 1:hlg->sdr 2:hlg->hdr*/
+uint hlg_process_mode[VD_PATH_MAX];
+uint cur_hlg_process_mode[VD_PATH_MAX] = {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");
 
-static uint force_pure_hlg;
-module_param(force_pure_hlg, uint, 0664);
+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 */
-static uint sdr_process_mode = 2; /* 0: sdr->sdr, 1:sdr->hdr */
-static uint cur_sdr_process_mode = 2; /* 0: sdr->sdr, 1:sdr->hdr */
-static int sdr_saturation_offset = 20; /* 0: sdr->sdr, 1:sdr->hdr */
 module_param(sdr_mode, uint, 0664);
 MODULE_PARM_DESC(sdr_mode, "\n set sdr_mode\n");
-module_param(sdr_process_mode, uint, 0444);
+
+static uint cur_sdr_mode;
+
+/* 0: sdr->sdr, 1:sdr->hdr, 2:sdr->hlg */
+uint sdr_process_mode[VD_PATH_MAX];
+uint cur_sdr_process_mode[VD_PATH_MAX] = {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");
 
@@ -361,13 +392,17 @@ static uint cur_hdr_support;
 module_param(cur_hdr_support, uint, 0664);
 MODULE_PARM_DESC(cur_hdr_support, "\n cur_hdr_support\n");
 
+static uint cur_colorimetry_support;
+module_param(cur_colorimetry_support, uint, 0664);
+MODULE_PARM_DESC(cur_colorimetry_support, "\n cur_colorimetry_support\n");
+
 static uint cur_hlg_support;
 module_param(cur_hlg_support, uint, 0664);
 MODULE_PARM_DESC(cur_hlg_support, "\n cur_hlg_support\n");
 
-static uint cur_output_mode;
-module_param(cur_output_mode, uint, 0664);
-MODULE_PARM_DESC(cur_output_mode, "\n cur_output_mode\n");
+static uint cur_color_fmt;
+module_param(cur_color_fmt, uint, 0664);
+MODULE_PARM_DESC(cur_color_fmt, "\n cur_color_fmt\n");
 
 static uint range_control;
 module_param(range_control, uint, 0664);
@@ -377,10 +412,32 @@ MODULE_PARM_DESC(range_control, "\n range_control 0:limit 1:full\n");
 /* bit 1: use display primary,*/
 /* bit 2: adjust contrast according to source lumin,*/
 /* bit 3: adjust saturation according to source lumin */
-uint hdr_flag = (1 << 0) | (1 << 1) | (0 << 2) | (0 << 3);
+/* 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");
 
+/* 0: off, 1: normal, 2: bypass */
+static int video_process_status[VD_PATH_MAX];
+module_param_array(video_process_status, uint, &vd_path_max, 0664);
+MODULE_PARM_DESC(video_process_status, "\n video_process_status\n");
+int get_hdr_module_status(enum vd_path_e vd_path)
+{
+       return video_process_status[vd_path];
+}
+EXPORT_SYMBOL(get_hdr_module_status);
+
+void set_hdr_module_status(enum vd_path_e vd_path, int status)
+{
+       video_process_status[vd_path] = status;
+}
+EXPORT_SYMBOL(set_hdr_module_status);
+
+#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) |
@@ -680,7 +737,7 @@ static void load_knee_lut(int on)
        int final_knee_setting[MAX_KNEE_SETTING];
 
        if ((cur_knee_factor != knee_factor) && (!lut_289_en) && (on)) {
-               pr_csc("Knee_factor changed from %d to %d\n",
+               pr_csc(1, "Knee_factor changed from %d to %d\n",
                        cur_knee_factor, knee_factor);
                for (i = 0; i < MAX_KNEE_SETTING; i++) {
                        final_knee_setting[i] =
@@ -703,8 +760,9 @@ static void load_knee_lut(int on)
                                VSYNC_WR_MPEG_REG(XVYCC_LUT_R_DATA_PORT + 2 * j,
                                                value);
                                if (j == 0)
-                                       pr_csc("xvycc_lut[%1d][%3d] = 0x%03x\n",
-                                                       j, i, value);
+                                       pr_csc(1,
+                                               "xvycc_lut[%1d][%3d] = 0x%03x\n",
+                                               j, i, value);
                        }
                        for (i = 16; i < 272; i++) {
                                k = 1 + ((i - 16) >> 3);
@@ -726,8 +784,9 @@ static void load_knee_lut(int on)
                                VSYNC_WR_MPEG_REG(XVYCC_LUT_R_DATA_PORT + 2 * j,
                                                value);
                                if (j == 0)
-                                       pr_csc("xvycc_lut[%1d][%3d] = 0x%03x\n",
-                                                       j, i, value);
+                                       pr_csc(1,
+                                               "xvycc_lut[%1d][%3d] = 0x%03x\n",
+                                               j, i, value);
                        }
                        for (i = 272; i < 289; i++) {
                                k = MAX_KNEE_SETTING - 2;
@@ -741,8 +800,9 @@ static void load_knee_lut(int on)
                                VSYNC_WR_MPEG_REG(XVYCC_LUT_R_DATA_PORT + 2 * j,
                                                value);
                                if (j == 0)
-                                       pr_csc("xvycc_lut[%1d][%3d] = 0x%03x\n",
-                                                       j, i, value);
+                                       pr_csc(1,
+                                               "xvycc_lut[%1d][%3d] = 0x%03x\n",
+                                               j, i, value);
                        }
                }
                cur_knee_factor = knee_factor;
@@ -1906,25 +1966,25 @@ static void print_vpp_matrix(int m_select, int *s, int on)
        else
                return;
 
-       pr_csc("%s matrix %s:\n", matrix_name[m_select],
+       pr_csc(1, "%s matrix %s:\n", matrix_name[m_select],
                on ? "on" : "off");
 
        if (size == MATRIX_5x3_COEF_SIZE) {
-               pr_csc(
+               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(
+               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(
+               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]),
@@ -1932,34 +1992,34 @@ static void print_vpp_matrix(int m_select, int *s, int on)
                                SIGN(s[11]), DECI(s[11]), FRAC(s[11]),
                                SIGN(s[20]), DECI(s[20]), FRAC(s[20]));
                if (s[21]) {
-                       pr_csc("\t\t%s%1d.%04d\t%s%1d.%04d\t%s%1d.%04d\n",
+                       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("\t\t%s%1d.%04d\t%s%1d.%04d\t%s%1d.%04d\n",
+                       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("\tright shift=%d\n", s[22]);
+                       pr_csc(1, "\tright shift=%d\n", s[22]);
        } else {
-               pr_csc("\t%s%1d.%04d\t%s%1d.%04d\t%s%1d.%04d\n",
+               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("\t%s%1d.%04d\t%s%1d.%04d\t%s%1d.%04d\n",
+               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("\t%s%1d.%04d\t%s%1d.%04d\t%s%1d.%04d\n",
+               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("\tright shift=%d\n", s[9]);
+                       pr_csc(1, "\tright shift=%d\n", s[9]);
        }
-       pr_csc("\n");
+       pr_csc(1, "\n");
 }
 
 static int *cur_osd_mtx = RGB709_to_YUV709l_coeff;
@@ -2661,12 +2721,12 @@ static void print_vpp_lut(
                WRITE_VPP_REG(addr_port, 61);
                data = READ_VPP_REG(data_port);
                b_map[OSD_OETF_LUT_SIZE - 1] = data & 0xffff;
-               pr_csc("%s lut %s:\n", lut_name[lut_sel], on ? "on" : "off");
+               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("\t[%d] = 0x%04x 0x%04x 0x%04x\n",
+                       pr_csc(1, "\t[%d] = 0x%04x 0x%04x 0x%04x\n",
                                i, r_map[i], g_map[i], b_map[i]);
                }
-               pr_csc("\n");
+               pr_csc(1, "\n");
        } else if (lut_sel == VPP_LUT_OSD_EOTF) {
                WRITE_VPP_REG(addr_port, 0);
                for (i = 0; i < 16; i++) {
@@ -2689,12 +2749,12 @@ static void print_vpp_lut(
                }
                data = READ_VPP_REG(data_port);
                b_map[EOTF_LUT_SIZE - 1] = data & 0xffff;
-               pr_csc("%s lut %s:\n", lut_name[lut_sel], on ? "on" : "off");
+               pr_csc(1, "%s lut %s:\n", lut_name[lut_sel], on ? "on" : "off");
                for (i = 0; i < EOTF_LUT_SIZE; i++) {
-                       pr_csc("\t[%d] = 0x%04x 0x%04x 0x%04x\n",
+                       pr_csc(1, "\t[%d] = 0x%04x 0x%04x 0x%04x\n",
                                i, r_map[i], g_map[i], b_map[i]);
                }
-               pr_csc("\n");
+               pr_csc(1, "\n");
        } else if (lut_sel == VPP_LUT_EOTF) {
                WRITE_VPP_REG(addr_port, 0);
                for (i = 0; i < 16; i++) {
@@ -2717,12 +2777,12 @@ static void print_vpp_lut(
                }
                data = READ_VPP_REG(data_port);
                b_map[EOTF_LUT_SIZE - 1] = data & 0xffff;
-               pr_csc("%s lut %s:\n", lut_name[lut_sel], on ? "on" : "off");
+               pr_csc(1, "%s lut %s:\n", lut_name[lut_sel], on ? "on" : "off");
                for (i = 0; i < EOTF_LUT_SIZE; i++) {
-                       pr_csc("\t[%d] = 0x%04x 0x%04x 0x%04x\n",
+                       pr_csc(1, "\t[%d] = 0x%04x 0x%04x 0x%04x\n",
                                i, r_map[i], g_map[i], b_map[i]);
                }
-               pr_csc("\n");
+               pr_csc(1, "\n");
        } else if (lut_sel == VPP_LUT_OETF) {
                WRITE_VPP_REG(ctrl_port, 0x0);
                WRITE_VPP_REG(addr_port, 0);
@@ -2734,17 +2794,17 @@ static void print_vpp_lut(
                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("%s lut %s:\n", lut_name[lut_sel], on ? "on" : "off");
+               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("\t[%d] = 0x%04x 0x%04x 0x%04x\n",
+                       pr_csc(1, "\t[%d] = 0x%04x 0x%04x 0x%04x\n",
                                i, r_map[i], g_map[i], b_map[i]);
                }
-               pr_csc("\n");
+               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("%s lut %s:\n", lut_name[lut_sel], on ? "on" : "off");
+               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;
@@ -2752,12 +2812,12 @@ static void print_vpp_lut(
                        WRITE_VPP_REG(addr_port, i);
                        data = READ_VPP_REG(data_port) & 0xfff;
                        if (data & 0x800)
-                               pr_csc("\t[%d] = %d\n",
+                               pr_csc(1, "\t[%d] = %d\n",
                                        i, -(~(data|0xfffff000) + 1));
                        else
-                               pr_csc("\t[%d] = %d\n", i, data);
+                               pr_csc(1, "\t[%d] = %d\n", i, data);
                }
-               pr_csc("\n");
+               pr_csc(1, "\n");
                if (on)
                        WRITE_VPP_REG_BITS(ctrl_port, 1<<2, 12, 3);
        }
@@ -3364,40 +3424,46 @@ static void vpp_set_matrix3(
        cur_csc_mode = csc_mode;
 }
 
-static uint cur_signal_type = 0xffffffff;
-module_param(cur_signal_type, uint, 0664);
+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 = {
-       0,
+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},
+                       {0, 0},
+                       {0, 0},
+               },
+               {0, 0},
+               {0, 0}
+       }
 };
 
-#define SIG_CS_CHG     0x01
-#define SIG_SRC_CHG    0x02
-#define SIG_PRI_INFO   0x04
-#define SIG_KNEE_FACTOR        0x08
-#define SIG_HDR_MODE   0x10
-#define SIG_HDR_SUPPORT        0x20
-#define SIG_WB_CHG     0x40
-#define SIG_HLG_MODE   0x80
-#define SIG_HLG_SUPPORT        0x100
-#define SIG_OP_CHG     0x200
-#define SIG_SRC_OUTPUT_CHG     0x400/*for box*/
-#define SIG_HDR10_PLUS_MODE    0x800
-
-unsigned int pre_vd1_mtx_sel = VPP_MATRIX_NULL;
-module_param(pre_vd1_mtx_sel, uint, 0664);
+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)
+       struct vinfo_s *vinfo, enum vd_path_e vd_path)
 {
        unsigned int width, height;
 
@@ -3420,15 +3486,229 @@ static int src_timing_outputmode_changed(struct vframe_s *vf,
        else
                vd1_mtx_sel = VPP_MATRIX_NULL;
 
-       if (pre_vd1_mtx_sel != vd1_mtx_sel) {
-               pre_vd1_mtx_sel = vd1_mtx_sel;
+       if (pre_vd1_mtx_sel[vd_path] != vd1_mtx_sel) {
+               pre_vd1_mtx_sel[vd_path] = vd1_mtx_sel;
                return 1;
        }
 
        return 0;
 }
 
-int signal_type_changed(struct vframe_s *vf, struct vinfo_s *vinfo)
+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 default 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];
+}
+
+int get_primaries_type(struct vframe_master_display_colour_s *p_mdc)
+{
+       if (!p_mdc->present_flag)
+               return 0;
+
+#if 0
+       /* revisit if needed */
+       /* check endian by white point */
+       /* need to fix by container parser */
+       if (((p_mdc->white_point[0] & 0x00f0) == 0x30)
+       && ((p_mdc->white_point[1] & 0x00f0) == 0x40)
+       && (((p_mdc->white_point[0] & 0xf000) != 0x3000)
+       || ((p_mdc->white_point[1] & 0xf000) != 0x4000))) {
+               for (i = 0; i < 2; i++)
+                       p_mdc->white_point[i] =
+                               ((p_mdc->white_point[i] & 0xff) << 8) |
+                               ((p_mdc->white_point[i] & 0xff00) >> 8);
+
+               for (i = 0; i < 3; i++)
+                       for (j = 0; j < 2; j++)
+                               p_mdc->primaries[i][j] =
+                               ((p_mdc->primaries[i][j] & 0xff) << 8) |
+                               ((p_mdc->primaries[i][j] & 0xff00) >> 8);
+               if (p_mdc->luminance[0] < 1000 * 10000)
+                       p_mdc->luminance[0] = 1000 * 10000;
+               else if (p_mdc->luminance[0] > 10000 * 10000)
+                       p_mdc->luminance[0] = 10000 * 10000;
+               if (p_mdc->luminance[1] > 100)
+                       p_mdc->luminance[1] = 100;
+               else if (p_mdc->luminance[1] < 50)
+                       p_mdc->luminance[1] = 50;
+               //pr_csc(1, "master_display_colour endian wrong!\n");
+       }
+#endif
+
+       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 */
+       return 0;
+}
+EXPORT_SYMBOL(get_primaries_type);
+
+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;
+       uint8_t flag = 0;
+       uint32_t max_lum = 1000 * 10000;
+       uint32_t min_lum = 50;
+       int primaries_type = 0;
+       int i, j;
+
+       primaries_type = get_primaries_type(p_mdc);
+       if (primaries_type == 0) {
+               if ((p_hdr10_param->luminance[0]
+               != max_lum)
+               || (p_hdr10_param->luminance[1]
+               != min_lum)) {
+                       flag |= 1;
+                       p_hdr10_param->luminance[0]
+                               = max_lum;
+                       p_hdr10_param->luminance[1]
+                               = min_lum;
+               }
+               for (i = 0; i < 2; i++) {
+                       if (p_hdr10_param->white_point[i]
+                       != bt2020_white_point[i]) {
+                               flag |= 4;
+                               p_hdr10_param->
+                               white_point[i] =
+                                       bt2020_white_point[i];
+                       }
+               }
+               for (i = 0; i < 3; i++) {
+                       /* GBR -> GBR */
+                       for (j = 0; j < 2; j++) {
+                               if (p_hdr10_param->
+                               primaries[i][j]
+                               != p_mdc->
+                               primaries[i][j]) {
+                                       p_hdr10_param->
+                                       primaries[i][j]
+                                               = p_mdc->
+                                               primaries[i][j];
+                                       flag |= 2;
+                               }
+                       }
+               }
+               p_hdr10_param->present_flag = 1;
+       } else {
+               for (i = 0; i < 2; i++) {
+                       if (p_hdr10_param->luminance[i]
+                       != p_mdc->luminance[i]) {
+                               flag |= 1;
+                               p_hdr10_param->
+                               luminance[i]
+                                       = p_mdc->luminance[i];
+                       }
+                       if (p_hdr10_param->white_point[i]
+                       != p_mdc->white_point[i]) {
+                               flag |= 4;
+                               p_hdr10_param->
+                               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 (p_hdr10_param->
+                                       primaries[i][j]
+                                       != p_mdc->
+                                       primaries[(i + 2) % 3][j]) {
+                                               p_hdr10_param->
+                                               primaries[i][j] = p_mdc->
+                                               primaries[(i + 2) % 3][j];
+                                               flag |= 2;
+                                       }
+                               }
+                       }
+                       p_hdr10_param->present_flag = 0x21;
+               } else if (primaries_type == 2) {
+                       /* GBR -> GBR */
+                       for (i = 0; i < 3; i++) {
+                               for (j = 0; j < 2; j++) {
+                                       if (p_hdr10_param->
+                                       primaries[i][j]
+                                       != p_mdc->
+                                       primaries[i][j]) {
+                                               p_hdr10_param->
+                                               primaries[i][j]
+                                                       = p_mdc->
+                                                       primaries[i][j];
+                                               flag |= 2;
+                                       }
+                               }
+                       }
+                       p_hdr10_param->present_flag = 0x11;
+               }
+       }
+
+       if (p_cll->present_flag) {
+               if ((p_hdr10_param->content_light_level.max_content
+                       != p_cll->max_content)
+               || (p_hdr10_param->content_light_level.max_pic_average
+                       != p_cll->max_pic_average))
+                       flag |= 8;
+               if (flag & 8) {
+                       p_hdr10_param->content_light_level.max_content
+                               = p_cll->max_content;
+                       p_hdr10_param->content_light_level.max_pic_average
+                               = p_cll->max_pic_average;
+               }
+               p_hdr10_param->content_light_level.present_flag = 1;
+       } else {
+               if ((p_hdr10_param->content_light_level.max_content != 0)
+               || (p_hdr10_param->content_light_level.max_pic_average != 0)) {
+                       p_hdr10_param->content_light_level.max_content = 0;
+                       p_hdr10_param->content_light_level.max_pic_average = 0;
+               }
+               if (p_hdr10_param->content_light_level.present_flag)
+                       flag |= 8;
+               p_hdr10_param->content_light_level.present_flag = 0;
+       }
+       return flag;
+}
+
+int signal_type_changed(struct vframe_s *vf,
+       struct vinfo_s *vinfo, enum vd_path_e vd_path)
 {
        u32 signal_type = 0;
        u32 default_signal_type;
@@ -3437,6 +3717,7 @@ int signal_type_changed(struct vframe_s *vf, struct vinfo_s *vinfo)
        struct vframe_master_display_colour_s *p_cur;
        struct vframe_master_display_colour_s *p_new;
        struct vframe_master_display_colour_s cus;
+       int ret;
 
        if (!vf)
                return 0;
@@ -3493,7 +3774,7 @@ int signal_type_changed(struct vframe_s *vf, struct vinfo_s *vinfo)
                signal_type = default_signal_type;
 
        p_new = &vf->prop.master_display_colour;
-       p_cur = &cur_master_display_colour;
+       p_cur = &cur_master_display_colour[vd_path];
        /* customer overwrite */
        if (customer_master_display_en
        && ((p_new->present_flag & 0x80000000) == 0)) {
@@ -3539,125 +3820,107 @@ int signal_type_changed(struct vframe_s *vf, struct vinfo_s *vinfo)
                /*vf->signal_type, signal_type);*/
        }
 
-       if (p_new->present_flag & 1) {
-               for (i = 0; i < 3; i++)
-                       for (j = 0; j < 2; j++) {
-                               if (p_cur->primaries[i][j]
-                                != p_new->primaries[i][j])
-                                       change_flag |= SIG_PRI_INFO;
-                               p_cur->primaries[i][j]
-                                       = p_new->primaries[i][j];
-                       }
-               for (i = 0; i < 2; i++) {
-                       if (p_cur->white_point[i]
-                        != p_new->white_point[i])
-                               change_flag |= SIG_PRI_INFO;
-                       p_cur->white_point[i]
-                               = p_new->white_point[i];
-               }
-               for (i = 0; i < 2; i++) {
-                       if (p_cur->luminance[i]
-                        != p_new->luminance[i])
-                               change_flag |= SIG_PRI_INFO;
-                       p_cur->luminance[i]
-                               = p_new->luminance[i];
-               }
-               if (p_cur->content_light_level.present_flag !=
-                       p_new->content_light_level.present_flag) {
-                       change_flag |= SIG_PRI_INFO;
-                       p_cur->content_light_level.present_flag =
-                               p_new->content_light_level.present_flag;
-               }
-               if (p_cur->content_light_level.max_content !=
-                       p_new->content_light_level.max_content) {
-                       change_flag |= SIG_PRI_INFO;
-                       p_cur->content_light_level.max_content =
-                               p_new->content_light_level.max_content;
-               }
-               if (p_cur->content_light_level.max_pic_average !=
-                       p_new->content_light_level.max_pic_average) {
-                       change_flag |= SIG_PRI_INFO;
-                       p_cur->content_light_level.max_pic_average =
-                               p_new->content_light_level.max_pic_average;
-               }
-               if (!p_cur->present_flag) {
-                       p_cur->present_flag = 1;
-                       change_flag |= SIG_PRI_INFO;
-               }
-       } else if (p_cur->present_flag) {
-               p_cur->present_flag = 0;
+       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.\n",
+                       vd_path + 1, ret);
+               print_primaries_info(p_cur);
        }
-       if (change_flag & SIG_PRI_INFO)
-               pr_csc("Master_display_colour changed.\n");
-
-       if (signal_type != cur_signal_type) {
-               pr_csc("Signal type changed from 0x%x to 0x%x.\n",
-                       cur_signal_type, signal_type);
+       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 = signal_type;
+               cur_signal_type[vd_path] = signal_type;
        }
-       if (pre_src_type != vf->source_type) {
-               pr_csc("Signal source changed from 0x%x to 0x%x.\n",
-                       pre_src_type, vf->source_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 = vf->source_type;
+               pre_src_type[vd_path] = vf->source_type;
        }
        if (cur_knee_factor != knee_factor) {
-               pr_csc("Knee factor changed.\n");
+               pr_csc(1, "vd%d Knee factor changed.\n", vd_path + 1);
                change_flag |= SIG_KNEE_FACTOR;
                cur_knee_factor = knee_factor;
        }
-       if (cur_hdr_process_mode != hdr_process_mode) {
-               pr_csc("HDR mode changed.\n");
-               change_flag |= SIG_HDR_MODE;
-       }
-       if (cur_hlg_process_mode != hlg_process_mode) {
-               pr_csc("HLG mode changed.\n");
-               change_flag |= SIG_HLG_MODE;
-       }
-       if (cur_sdr_process_mode != sdr_process_mode) {
-               pr_csc("SDR mode changed.\n");
-               change_flag |= SIG_HDR_MODE;
+       if (!is_dolby_vision_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_hdr_support != (vinfo->hdr_info.hdr_support & 0x4)) {
-               pr_csc("Tx HDR support changed.\n");
+
+       if (cur_hdr_support
+       != (vinfo->hdr_info.hdr_support & 0x4)) {
+               pr_csc(1, "Tx HDR support changed.\n");
                change_flag |= SIG_HDR_SUPPORT;
-               cur_hdr_support = vinfo->hdr_info.hdr_support & 0x4;
+               cur_hdr_support =
+                       vinfo->hdr_info.hdr_support & 0x4;
        }
-       if (cur_output_mode != vinfo->viu_color_fmt) {
-               pr_csc("output mode changed.\n");
+       if (cur_colorimetry_support != (vinfo->hdr_info.colorimetry_support)) {
+               pr_csc(1, "Tx colorimetry support changed.\n");
+               change_flag |= SIG_COLORIMETRY_SUPPORT;
+               cur_colorimetry_support = vinfo->hdr_info.colorimetry_support;
+       }
+       if (cur_color_fmt != vinfo->viu_color_fmt) {
+               pr_csc(1, "color format changed.\n");
                change_flag |= SIG_OP_CHG;
-               cur_output_mode = vinfo->viu_color_fmt;
+               cur_color_fmt = vinfo->viu_color_fmt;
        }
        if (cur_hlg_support != (vinfo->hdr_info.hdr_support & 0x8)) {
-               pr_csc("Tx HLG support changed.\n");
+               pr_csc(1, "Tx HLG support changed.\n");
                change_flag |= SIG_HLG_SUPPORT;
                cur_hlg_support = vinfo->hdr_info.hdr_support & 0x8;
        }
 
-       if (cur_hdr10_plus_process_mode != hdr10_plus_process_mode) {
-               pr_csc("HDR10 plus mode changed.\n");
-               change_flag |= SIG_HDR10_PLUS_MODE;
-               cur_hdr10_plus_process_mode = hdr10_plus_process_mode;
-       }
-
        if ((cur_eye_protect_mode != wb_val[0]) ||
                (cur_eye_protect_mode == 1)) {
-               pr_csc(eye protect mode changed.\n");
+               pr_csc(1, "eye protect mode changed.\n");
                change_flag |= SIG_WB_CHG;
        }
 
-       if (src_timing_outputmode_changed(vf, vinfo)) {
-               pr_csc(" source timing output mode changed.\n");
+       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;
        }
+
        return change_flag;
 }
 
-#define signal_range ((cur_signal_type >> 25) & 1)
-#define signal_color_primaries ((cur_signal_type >> 16) & 0xff)
-#define signal_transfer_characteristic ((cur_signal_type >> 8) & 0xff)
+#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;
@@ -3679,36 +3942,44 @@ enum vpp_matrix_csc_e get_csc_type(void)
                if (signal_transfer_characteristic == 16) {
                        /* smpte st-2084 */
                        if (signal_color_primaries != 9)
-                               pr_csc("\tWARNING: non-standard HDR!!!\n");
+                               pr_csc(1, "\tWARNING: non-standard HDR!!!\n");
                        csc_type = VPP_MATRIX_BT2020YUV_BT2020RGB;
                } else if (signal_transfer_characteristic == 14) {
                        /* bt2020-10 */
-                       pr_csc("\tWARNING: bt2020-10 HDR!!!\n");
+                       pr_csc(1, "\tWARNING: bt2020-10 HDR!!!\n");
                        csc_type = VPP_MATRIX_BT2020YUV_BT2020RGB;
                } else if (signal_transfer_characteristic == 15) {
                        /* bt2020-12 */
-                       pr_csc("\tWARNING: bt2020-12 HDR!!!\n");
+                       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 == 18) {
                        /* bt2020-12 */
-                       pr_csc("\tWARNING: HLG!!!\n");
+                       /* pr_csc(1, "\tHLG!!!\n"); */
                        csc_type = VPP_MATRIX_BT2020YUV_BT2020RGB;
                } else if (signal_transfer_characteristic == 0x30) {
-                       pr_csc("\tWARNING: HDR10 PLUS!!!\n");
-                       csc_type = VPP_MATRIX_BT2020YUV_BT2020RGB_DYNAMIC;
+                       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("\tWARNING: unknown HDR!!!\n");
+                       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 {
-               pr_csc("\tWARNING: unsupported colour space!!!\n");
+               if (signal_format == 0)
+                       pr_csc(1, "\tWARNING: unknown colour space!!!\n");
                if (signal_range == 0)
                        csc_type = VPP_MATRIX_YUV601_RGB;
                else
@@ -3731,11 +4002,15 @@ static int get_hdr_type(void)
 
 void get_hdr_source_type(void)
 {
-       if ((signal_transfer_characteristic == 18) ||
-               (signal_transfer_characteristic == 14))
+       if (((signal_transfer_characteristic == 14) ||
+               (signal_transfer_characteristic == 18)) &&
+               (signal_color_primaries == 9))
                hdr_source_type = HLG_SOURCE;
-       else if ((signal_color_primaries == 9) ||
-                       (signal_transfer_characteristic == 16))
+       else if ((signal_transfer_characteristic == 0x30)
+               && (signal_color_primaries == 9))
+               hdr_source_type = HDR10PLUS_SOURCE;
+       else if ((signal_transfer_characteristic == 16)
+               || (signal_color_primaries == 9))
                hdr_source_type = HDR10_SOURCE;
        else
                hdr_source_type = SDR_SOURCE;
@@ -3949,13 +4224,13 @@ static void cal_mtx_seting(
                m->right_shift = right_shift;
        }
        N2C(in, ibl, obl);
-       pr_csc("\tHDR color convert matrix:\n");
+       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("\t\t%04x %04x %04x\n",
+               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));
@@ -4163,22 +4438,6 @@ static int calculate_contrast_adj(int max_lumin)
        return target_contrast - vd1_contrast;
 }
 
-static void print_primaries_info(struct vframe_master_display_colour_s *p)
-{
-       int i, j;
-
-       for (i = 0; i < 3; i++)
-               for (j = 0; j < 2; j++)
-                       pr_csc(
-                               "\t\tprimaries[%1d][%1d] = %04x\n",
-                               i, j,
-                               p->primaries[i][j]);
-       pr_csc("\t\twhite_point = (%04x, %04x)\n",
-               p->white_point[0], p->white_point[1]);
-       pr_csc("\t\tmax,min luminance = %08x, %08x\n",
-               p->luminance[0], p->luminance[1]);
-}
-
 static void amvecm_cp_hdr_info(struct master_display_info_s *hdr_data,
                struct vframe_master_display_colour_s *p)
 {
@@ -4353,7 +4612,8 @@ static void vpp_lut_curve_set(enum vpp_lut_sel_e lut_sel,
 static int hdr_process(
        enum vpp_matrix_csc_e csc_type,
        struct vinfo_s *vinfo,
-       struct vframe_master_display_colour_s *master_info)
+       struct vframe_master_display_colour_s *master_info,
+       enum vd_path_e vd_path)
 {
        int need_adjust_contrast_saturation = 0;
        int max_lumin = 10000;
@@ -4398,13 +4658,13 @@ static int hdr_process(
        int i, j;
 
        if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) {
-               hdr_func(OSD1_HDR, HDR_BYPASS);
-               hdr_func(VD1_HDR, HDR_SDR);
+               hdr_func(OSD1_HDR, HDR_BYPASS, vinfo);
+               hdr_func(VD1_HDR, HDR_SDR, vinfo);
                return need_adjust_contrast_saturation;
        }
 
        if (master_info->present_flag & 1) {
-               pr_csc("\tMaster_display_colour available.\n");
+               pr_csc(1, "\tMaster_display_colour available.\n");
                print_primaries_info(master_info);
                /* for VIDEO */
                csc_type =
@@ -4421,7 +4681,7 @@ static int hdr_process(
                need_adjust_contrast_saturation |= 1;
        } else {
                /* use bt2020 primaries */
-               pr_csc("\tNo master_display_colour.\n");
+               pr_csc(1, "\tNo master_display_colour.\n");
                /* for VIDEO */
                csc_type =
                        prepare_customer_matrix(
@@ -4599,7 +4859,8 @@ static int hdr_process(
 static int hlg_process(
        enum vpp_matrix_csc_e csc_type,
        struct vinfo_s *vinfo,
-       struct vframe_master_display_colour_s *master_info)
+       struct vframe_master_display_colour_s *master_info,
+       enum vd_path_e vd_path)
 {
        int need_adjust_contrast_saturation = 0;
        int max_lumin = 10000;
@@ -4644,13 +4905,13 @@ static int hlg_process(
        int i, j;
 
        if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) {
-               hdr_func(VD1_HDR, HLG_SDR);
-               hdr_func(OSD1_HDR, HDR_BYPASS);
+               hdr_func(VD1_HDR, HLG_SDR, vinfo);
+               hdr_func(OSD1_HDR, HDR_BYPASS, vinfo);
                return need_adjust_contrast_saturation;
        }
 
        if (master_info->present_flag & 1) {
-               pr_csc("\tMaster_display_colour available.\n");
+               pr_csc(1, "\tMaster_display_colour available.\n");
                print_primaries_info(master_info);
                /* for VIDEO */
                csc_type =
@@ -4667,7 +4928,7 @@ static int hlg_process(
                need_adjust_contrast_saturation |= 1;
        } else {
                /* use bt2020 primaries */
-               pr_csc("\tNo master_display_colour.\n");
+               pr_csc(1, "\tNo master_display_colour.\n");
                /* for VIDEO */
                csc_type =
                        prepare_customer_matrix(
@@ -4839,7 +5100,8 @@ static int hlg_process(
 static void bypass_hdr_process(
        enum vpp_matrix_csc_e csc_type,
        struct vinfo_s *vinfo,
-       struct vframe_master_display_colour_s *master_info)
+       struct vframe_master_display_colour_s *master_info,
+       enum vd_path_e vd_path)
 {
        struct matrix_s osd_m = {
                {0, 0, 0},
@@ -4863,17 +5125,17 @@ static void bypass_hdr_process(
        int i, j;
 
        if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) {
-               hdr_func(VD1_HDR, HDR_BYPASS);
+               hdr_func(VD1_HDR, HDR_BYPASS, vinfo);
                if ((csc_type == VPP_MATRIX_BT2020YUV_BT2020RGB) &&
                        ((vinfo->hdr_info.hdr_support & 0xc) &&
                        (vinfo->viu_color_fmt != COLOR_FMT_RGB444))) {
                        if (get_hdr_type() & HLG_FLAG)
-                               hdr_func(OSD1_HDR, SDR_HLG);
+                               hdr_func(OSD1_HDR, SDR_HLG, vinfo);
                        else
-                               hdr_func(OSD1_HDR, SDR_HDR);
-                       pr_csc("\t osd sdr->hdr/hlg\n");
+                               hdr_func(OSD1_HDR, SDR_HDR, vinfo);
+                       pr_csc(1, "\t osd sdr->hdr/hlg\n");
                } else
-                       hdr_func(OSD1_HDR, HDR_BYPASS);
+                       hdr_func(OSD1_HDR, HDR_BYPASS, vinfo);
                return;
        }
        /*vpp matrix mux read*/
@@ -4919,14 +5181,15 @@ static void bypass_hdr_process(
                        }
                        /* osd eotf matrix 709->2020 */
                        if (master_info->present_flag & 1) {
-                               pr_csc("\tMaster_display_colour available.\n");
+                               pr_csc(1,
+                                       "\tMaster_display_colour available.\n");
                                print_primaries_info(master_info);
                                prepare_customer_matrix(
                                        &master_info->primaries,
                                        &master_info->white_point,
                                        vinfo, &osd_m, 1);
                        } else {
-                               pr_csc("\tNo master_display_colour.\n");
+                               pr_csc(1, "\tNo master_display_colour.\n");
                                prepare_customer_matrix(
                                        &bt2020_primaries,
                                        &bt2020_white_point,
@@ -5083,7 +5346,7 @@ static void bypass_hdr_process(
                                        CSC_ON);
                }
                /* xvycc inv lut */
-               if (sdr_process_mode &&
+               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)))
@@ -5154,7 +5417,7 @@ static void bypass_hdr_process(
                load_knee_lut(CSC_OFF);
                /* xvycc inv lut */
 
-               if (sdr_process_mode)
+               if (sdr_process_mode[vd_path])
                        set_vpp_lut(VPP_LUT_INV_EOTF,
                                NULL,
                                NULL,
@@ -5186,7 +5449,8 @@ static void bypass_hdr_process(
 static void set_bt2020csc_process(
        enum vpp_matrix_csc_e csc_type,
        struct vinfo_s *vinfo,
-       struct vframe_master_display_colour_s *master_info)
+       struct vframe_master_display_colour_s *master_info,
+       enum vd_path_e vd_path)
 {
        struct matrix_s osd_m = {
                {0, 0, 0},
@@ -5238,14 +5502,15 @@ static void set_bt2020csc_process(
 
                        /* osd eotf matrix 709->2020 */
                        if (master_info->present_flag & 1) {
-                               pr_csc("\tMaster_display_colour available.\n");
+                               pr_csc(1,
+                                       "\tMaster_display_colour available.\n");
                                print_primaries_info(master_info);
                                prepare_customer_matrix(
                                        &master_info->primaries,
                                        &master_info->white_point,
                                        vinfo, &osd_m, 1);
                        } else {
-                               pr_csc("\tNo master_display_colour.\n");
+                               pr_csc(1, "\tNo master_display_colour.\n");
                                prepare_customer_matrix(
                                        &bt2020_primaries,
                                        &bt2020_white_point,
@@ -5388,7 +5653,7 @@ static void set_bt2020csc_process(
                                        CSC_ON);
                }
                /* xvycc inv lut */
-               if (sdr_process_mode &&
+               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)))
@@ -5453,7 +5718,7 @@ static void set_bt2020csc_process(
                load_knee_lut(CSC_OFF);
                /* xvycc inv lut */
 
-               if (sdr_process_mode)
+               if (sdr_process_mode[vd_path])
                        set_vpp_lut(VPP_LUT_INV_EOTF,
                                NULL,
                                NULL,
@@ -5485,7 +5750,8 @@ static void set_bt2020csc_process(
 static void hlg_hdr_process(
        enum vpp_matrix_csc_e csc_type,
        struct vinfo_s *vinfo,
-       struct vframe_master_display_colour_s *master_info)
+       struct vframe_master_display_colour_s *master_info,
+       enum vd_path_e vd_path)
 {
        struct matrix_s osd_m = {
                {0, 0, 0},
@@ -5509,8 +5775,8 @@ static void hlg_hdr_process(
        int i, j;
 
        if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) {
-               hdr_func(VD1_HDR, HLG_HDR);
-               hdr_func(OSD1_HDR, SDR_HDR);
+               hdr_func(VD1_HDR, HLG_HDR, vinfo);
+               hdr_func(OSD1_HDR, SDR_HDR, vinfo);
                return;
        }
        /*vpp matrix mux read*/
@@ -5543,14 +5809,15 @@ static void hlg_hdr_process(
 
                        /* osd eotf matrix 709->2020 */
                        if (master_info->present_flag & 1) {
-                               pr_csc("\tMaster_display_colour available.\n");
+                               pr_csc(1,
+                                       "\tMaster_display_colour available.\n");
                                print_primaries_info(master_info);
                                prepare_customer_matrix(
                                        &master_info->primaries,
                                        &master_info->white_point,
                                        vinfo, &osd_m, 1);
                        } else {
-                               pr_csc("\tNo master_display_colour.\n");
+                               pr_csc(1, "\tNo master_display_colour.\n");
                                prepare_customer_matrix(
                                        &bt2020_primaries,
                                        &bt2020_white_point,
@@ -5715,7 +5982,7 @@ static void hlg_hdr_process(
                load_knee_lut(CSC_OFF);
                /* xvycc inv lut */
 
-               if (sdr_process_mode)
+               if (sdr_process_mode[vd_path])
                        set_vpp_lut(VPP_LUT_INV_EOTF,
                                NULL,
                                NULL,
@@ -5747,12 +6014,13 @@ static void hlg_hdr_process(
 static void sdr_hdr_process(
        enum vpp_matrix_csc_e csc_type,
        struct vinfo_s *vinfo,
-       struct vframe_master_display_colour_s *master_info)
+       struct vframe_master_display_colour_s *master_info,
+       enum vd_path_e vd_path)
 {
        if (vinfo->viu_color_fmt != COLOR_FMT_RGB444) {
                if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) {
-                       hdr_func(VD1_HDR, SDR_HDR);
-                       hdr_func(OSD1_HDR, SDR_HDR);
+                       hdr_func(VD1_HDR, SDR_HDR, vinfo);
+                       hdr_func(OSD1_HDR, SDR_HDR, vinfo);
                        return;
                }
                /*vpp matrix mux read*/
@@ -5839,12 +6107,13 @@ static void sdr_hdr_process(
                /*vpp matrix mux write*/
                vpp_set_mtx_en_write();
        } else
-               bypass_hdr_process(csc_type, vinfo, master_info);
+               bypass_hdr_process(csc_type, vinfo, master_info, vd_path);
 }
 
 static int vpp_eye_protection_process(
        enum vpp_matrix_csc_e csc_type,
-       struct vinfo_s *vinfo)
+       struct vinfo_s *vinfo,
+       enum vd_path_e vd_path)
 {
        cur_eye_protect_mode = wb_val[0];
        memcpy(&video_rgb_ogo, wb_val,
@@ -5853,10 +6122,10 @@ static int vpp_eye_protection_process(
        vpp_set_mtx_en_read();
        /* only SDR need switch csc */
        if ((csc_type == VPP_MATRIX_BT2020YUV_BT2020RGB) &&
-                       hdr_process_mode)
+                       hdr_process_mode[vd_path])
                return 0;
        if ((csc_type < VPP_MATRIX_BT2020YUV_BT2020RGB) &&
-                       sdr_process_mode)
+                       sdr_process_mode[vd_path])
                return 0;
 
        if (vinfo->viu_color_fmt == COLOR_FMT_RGB444)
@@ -5912,7 +6181,7 @@ static int vpp_eye_protection_process(
        return 0;
 }
 
-static void hdr_support_process(struct vinfo_s *vinfo)
+static void hdr_support_process(struct vinfo_s *vinfo, enum vd_path_e vd_path)
 {
        /*check if hdmitx support hdr10+*/
        if ((vinfo->hdr_info.hdr10plus_info.ieeeoui
@@ -5929,65 +6198,101 @@ static void hdr_support_process(struct vinfo_s *vinfo)
                /*hdr_support & bit3 is hlg*/
                if ((vinfo->hdr_info.hdr_support & HDR_SUPPORT) &&
                        (vinfo->hdr_info.hdr_support & HLG_SUPPORT)) {
-                       hdr_process_mode = 0; /* hdr->hdr*/
-                       hlg_process_mode = 0; /* hlg->hlg*/
+                       hdr_process_mode[vd_path] = PROC_BYPASS; /* hdr->hdr*/
+                       hlg_process_mode[vd_path] = PROC_BYPASS; /* hlg->hlg*/
                } else if ((vinfo->hdr_info.hdr_support & HDR_SUPPORT) &&
                        !(vinfo->hdr_info.hdr_support & HLG_SUPPORT)) {
-                       hdr_process_mode = 0; /* hdr->hdr*/
-                       if (force_pure_hlg)
-                               hlg_process_mode = 0;
-                       else
-                               hlg_process_mode = 1; /* hlg->hdr10*/
+                       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 (!(vinfo->hdr_info.hdr_support & HDR_SUPPORT) &&
                        (vinfo->hdr_info.hdr_support & HLG_SUPPORT)) {
-                       hdr_process_mode = 1;
-                       hlg_process_mode = 0;
+                       hdr_process_mode[vd_path] = PROC_MATCH;
+                       hlg_process_mode[vd_path] = PROC_BYPASS;
                } else {
-                       hdr_process_mode = 1;
-                       hlg_process_mode = 1;
+                       hdr_process_mode[vd_path] = PROC_MATCH;
+                       hlg_process_mode[vd_path] = PROC_MATCH;
                }
 
                if (tx_hdr10_plus_support)
-                       hdr10_plus_process_mode = 0;
+                       hdr10_plus_process_mode[vd_path] = PROC_BYPASS;
                else
-                       hdr10_plus_process_mode = 1;
+                       hdr10_plus_process_mode[vd_path] = PROC_MATCH;
        } else if (hdr_mode == 1) {
-               hdr_process_mode = 1;
-               hlg_process_mode = 1;
-               hdr10_plus_process_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 = 0;
-               if (vinfo->hdr_info.hdr_support & HDR_SUPPORT) {
-                       if ((vinfo->hdr_info.hdr_support & HLG_SUPPORT) ||
-                               (force_pure_hlg))
-                               hlg_process_mode = 0;
-                       else
-                               hlg_process_mode = 1;
-               } else
-                       hlg_process_mode = 0;
-
-               hdr10_plus_process_mode = 0;
+               if (vinfo->hdr_info.hdr_support & HDR_SUPPORT)
+                       hdr_process_mode[vd_path] = PROC_BYPASS;
+               else
+                       hdr_process_mode[vd_path] = PROC_MATCH;
+               if ((vinfo->hdr_info.hdr_support & HLG_SUPPORT) ||
+               (force_pure_hlg[vd_path]))
+                       hlg_process_mode[vd_path] = PROC_BYPASS;
+               else
+                       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;
        }
 
        if (sdr_mode == 2) { /* auto */
                if ((vinfo->hdr_info.hdr_support & 0x4) &&
                ((cpu_after_eq(MESON_CPU_MAJOR_ID_GXL)) &&
                 (vinfo->viu_color_fmt != COLOR_FMT_RGB444)))
-                       sdr_process_mode = 1; /*box sdr->hdr*/
+                       /*box sdr->hdr*/
+                       sdr_process_mode[vd_path] = PROC_SDR_TO_HDR;
                else if ((vinfo->viu_color_fmt == COLOR_FMT_RGB444) &&
                        ((get_cpu_type() == MESON_CPU_MAJOR_ID_GXTVBB) ||
                        (get_cpu_type() == MESON_CPU_MAJOR_ID_TXL)))
-                       sdr_process_mode = 1; /*tv sdr->hdr*/
+                       /*tv sdr->hdr*/
+                       sdr_process_mode[vd_path] = PROC_SDR_TO_HDR;
                else
-                       sdr_process_mode = 0; /* sdr->sdr*/
+                       /* sdr->sdr*/
+                       sdr_process_mode[vd_path] = PROC_BYPASS;
        } else
-               sdr_process_mode = sdr_mode; /* force sdr->hdr */
+               /* force sdr->hdr */
+               sdr_process_mode[vd_path] = sdr_mode;
+}
 
+static enum hdr_type_e get_source_type(enum vd_path_e vd_path)
+{
+       get_cur_vd_signal_type(vd_path);
+       if (((signal_transfer_characteristic == 14) ||
+               (signal_transfer_characteristic == 18)) &&
+               (signal_color_primaries == 9))
+               return HDRTYPE_HLG;
+       else if ((signal_transfer_characteristic == 0x30)
+               && (signal_color_primaries == 9))
+               return HDRTYPE_HDR10PLUS;
+       else if ((signal_transfer_characteristic == 16)
+               || (signal_color_primaries == 9))
+               return HDRTYPE_HDR10;
+       else
+               return HDRTYPE_SDR;
+}
+
+static bool video_layer_wait_on[VD_PATH_MAX];
+bool is_video_layer_on(enum vd_path_e vd_path)
+{
+       bool video_on =
+               (vd_path == VD1_PATH) ?
+               get_video_enabled() :
+               get_videopip_enabled();
+
+       if (video_on)
+               video_layer_wait_on[vd_path] = false;
+       return video_on ||
+               video_layer_wait_on[vd_path];
 }
 
 static void hdr10_plus_metadata_update(struct vframe_s *vf,
        enum vpp_matrix_csc_e csc_type,
-       struct hdr10plus_para *hdmitx_hdr10plus_param)
+       struct hdr10plus_para *p)
 {
        if (!vf)
                return;
@@ -5998,10 +6303,127 @@ static void hdr10_plus_metadata_update(struct vframe_s *vf,
 
        hdr10_plus_ootf_gen();
 
-       if (tx_hdr10_plus_support)
-               hdr10_plus_hdmitx_vsif_parser(hdmitx_hdr10plus_param,
-               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));
+       }
+}
+
+static struct hdr10plus_para hdmitx_hdr10plus_params[VD_PATH_MAX];
+static int hdr10_plus_pkt_update;
+static bool hdr10_plus_pkt_on;
+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);
+
+void update_hdr10_plus_pkt(bool enable,
+       void *hdr10plus_params,
+       void *send_info)
+{
+       struct vinfo_s *vinfo = get_current_vinfo();
+       struct vout_device_s *vdev = NULL;
+
+       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 {
+               vdev->fresh_tx_hdr_pkt(
+                       &cur_send_info);
+               vdev->fresh_tx_hdr10plus_pkt(0,
+                       &cur_hdr10plus_params);
+               hdr10_plus_pkt_update = HDRPLUS_PKT_IDLE;
+               pr_csc(2, "update_hdr10_plus_pkt off\n");
+       }
+}
+EXPORT_SYMBOL(update_hdr10_plus_pkt);
+
+void send_hdr10_plus_pkt(enum vd_path_e vd_path)
+{
+       struct vinfo_s *vinfo = get_current_vinfo();
+       struct vout_device_s *vdev = NULL;
+
+       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) {
+               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)) {
+               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);
 
 static void hdr_tx_pkt_cb(
        struct vinfo_s *vinfo,
@@ -6009,7 +6431,8 @@ static void hdr_tx_pkt_cb(
        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 hdr10plus_para *hdmitx_hdr10plus_param,
+       enum vd_path_e vd_path)
 {
        struct vout_device_s *vdev = NULL;
        struct master_display_info_s send_info;
@@ -6024,7 +6447,7 @@ static void hdr_tx_pkt_cb(
                /*hdr10 plus*/
                (tx_hdr10_plus_support) ||
                (signal_change_flag & SIG_HDR10_PLUS_MODE))) {
-               if (sdr_process_mode &&
+               if (sdr_process_mode[vd_path] &&
                        (csc_type < VPP_MATRIX_BT2020YUV_BT2020RGB)) {
                        /* sdr source convert to hdr */
                        /* send hdr info */
@@ -6044,7 +6467,7 @@ static void hdr_tx_pkt_cb(
                                        vdev->fresh_tx_hdr_pkt(&send_info);
                        }
 
-                       if (cur_csc_type ==
+                       if (cur_csc_type[vd_path] ==
                                VPP_MATRIX_BT2020YUV_BT2020RGB_DYNAMIC) {
                                if (vdev) {
                                        if (vdev->fresh_tx_hdr10plus_pkt)
@@ -6057,8 +6480,8 @@ static void hdr_tx_pkt_cb(
                                hdmi_csc_type = VPP_MATRIX_BT2020YUV_BT2020RGB;
                                *hdmi_scs_type_changed = 1;
                        }
-               } else if ((hdr_process_mode == 0) &&
-                       (hlg_process_mode == 0) &&
+               } 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 discribe source info */
@@ -6083,8 +6506,8 @@ static void hdr_tx_pkt_cb(
                                hdmi_csc_type = VPP_MATRIX_BT2020YUV_BT2020RGB;
                                *hdmi_scs_type_changed = 1;
                        }
-               } else if ((hdr_process_mode == 0) &&
-                       (hlg_process_mode == 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 discribe source info */
@@ -6121,8 +6544,8 @@ static void hdr_tx_pkt_cb(
                                hdmi_csc_type = VPP_MATRIX_BT2020YUV_BT2020RGB;
                                *hdmi_scs_type_changed = 1;
                        }
-               } else if ((hdr_process_mode == 1) &&
-                       (hlg_process_mode == 0) &&
+               } 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 discribe source info */
@@ -6158,14 +6581,45 @@ static void hdr_tx_pkt_cb(
                                hdmi_csc_type = VPP_MATRIX_BT2020YUV_BT2020RGB;
                                *hdmi_scs_type_changed = 1;
                        }
-               } else if ((hdr10_plus_process_mode == 0) &&
+               } else if ((hdr10_plus_process_mode[vd_path] == 0) &&
                        (csc_type == VPP_MATRIX_BT2020YUV_BT2020RGB_DYNAMIC)) {
-                       /*source is hdr10 plus, send hdr10 plus info*/
+                       /* source is hdr10+, send hdr10 drm packet as well*/
+                       /* use the features to discribe 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) {
-                               if (vdev->fresh_tx_hdr10plus_pkt)
-                                       vdev->fresh_tx_hdr10plus_pkt(1,
-                                               hdmitx_hdr10plus_param);
+                               /* source is hdr10 plus, send hdr10 plus info */
+                               if (get_hdr10_plus_pkt_delay()) {
+                                       update_hdr10_plus_pkt(true,
+                                               hdmitx_hdr10plus_param,
+                                               &send_info);
+                               } else {
+                                       /* send HDR10 DRM packet */
+                                       if (vdev->fresh_tx_hdr_pkt)
+                                               vdev->fresh_tx_hdr_pkt(
+                                                       &send_info);
+                                       /* send hdr10 plus info */
+                                       if (vdev->fresh_tx_hdr10plus_pkt)
+                                               vdev->fresh_tx_hdr10plus_pkt(1,
+                                                       hdmitx_hdr10plus_param);
+                               }
+                       }
+                       if (hdmi_csc_type !=
+                               VPP_MATRIX_BT2020YUV_BT2020RGB_DYNAMIC) {
+                               hdmi_csc_type =
+                                       VPP_MATRIX_BT2020YUV_BT2020RGB_DYNAMIC;
+                               *hdmi_scs_type_changed = 1;
                        }
+
                } else {
                        /* sdr source send normal info*/
                        /* use the features to discribe source info */
@@ -6195,21 +6649,24 @@ static void hdr_tx_pkt_cb(
                                        | (1 << 8)      /* bt709 */
                                        | (1 << 0);     /* bt709 */
                        amvecm_cp_hdr_info(&send_info, p);
-                       if (cur_csc_type <= VPP_MATRIX_BT2020YUV_BT2020RGB) {
+                       if (cur_csc_type[vd_path] <=
+                               VPP_MATRIX_BT2020YUV_BT2020RGB) {
                                if (vdev) {
                                        if (vdev->fresh_tx_hdr_pkt)
                                                vdev->fresh_tx_hdr_pkt(
                                                        &send_info);
                                }
-                       } else if (cur_csc_type ==
+                       } else if (cur_csc_type[vd_path] ==
                                VPP_MATRIX_BT2020YUV_BT2020RGB_DYNAMIC) {
                                if (vdev) {
+                                       if (vdev->fresh_tx_hdr_pkt)
+                                               vdev->fresh_tx_hdr_pkt(
+                                                       &send_info);
                                        if (vdev->fresh_tx_hdr10plus_pkt)
                                                vdev->fresh_tx_hdr10plus_pkt(0,
                                                        hdmitx_hdr10plus_param);
                                }
                        }
-
                        if (hdmi_csc_type != VPP_MATRIX_YUV709_RGB) {
                                hdmi_csc_type = VPP_MATRIX_YUV709_RGB;
                                *hdmi_scs_type_changed = 1;
@@ -6223,14 +6680,15 @@ static void video_process(
        enum vpp_matrix_csc_e csc_type,
        int signal_change_flag,
        struct vinfo_s *vinfo,
-       struct vframe_master_display_colour_s *p)
+       struct vframe_master_display_colour_s *p,
+       enum vd_path_e vd_path)
 {
        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 == 1) &&
-               (hlg_process_mode == 1)) {
+               (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 |
@@ -6240,22 +6698,27 @@ static void video_process(
                                SIG_HDR_SUPPORT |
                                SIG_HLG_MODE)
                        ) ||
-                       (cur_csc_type <
+                       (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);
+                                       hlg_process(csc_type, vinfo, p,
+                                               vd_path);
                        else
                                need_adjust_contrast_saturation
-                               = hdr_process(csc_type, vinfo, p);
-                       pr_csc("hdr_process_mode = 0x%x\n"
+                               = hdr_process(
+                                       csc_type, vinfo, p, vd_path);
+                       pr_csc(1, "vd_path = %d\n"
+                               "hdr_process_mode = 0x%x\n"
                                "hlg_process_mode = 0x%x.\n",
-                       hdr_process_mode, hlg_process_mode);
+                               vd_path + 1,
+                               hdr_process_mode[vd_path],
+                               hlg_process_mode[vd_path]);
                }
        } else if ((csc_type == VPP_MATRIX_BT2020YUV_BT2020RGB) &&
-               (hdr_process_mode == 0) &&
-               (hlg_process_mode == 1)) {
-               /* hdr->hdr hlg->hlg*/
+               (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 |
@@ -6264,18 +6727,22 @@ static void video_process(
                                SIG_HDR_SUPPORT |
                                SIG_HLG_MODE)
                        ) ||
-                       (cur_csc_type <
+                       (cur_csc_type[vd_path] <
                                VPP_MATRIX_BT2020YUV_BT2020RGB)) {
                        if (get_hdr_type() & HLG_FLAG)
-                               hlg_hdr_process(csc_type, vinfo, p);
+                               hlg_hdr_process(csc_type, vinfo, p, vd_path);
                        else
-                               bypass_hdr_process(csc_type, vinfo, p);
-                       pr_csc("hdr_process_mode = 0x%x\n"
-                               "hlg_process_mode = 0x%x.\n",
-                               hdr_process_mode, hlg_process_mode);
+                               bypass_hdr_process(csc_type, vinfo, p, vd_path);
+                       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 == 1) && (hlg_process_mode == 0)) {
+               (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 |
@@ -6285,19 +6752,25 @@ static void video_process(
                                SIG_HDR_SUPPORT |
                                SIG_HLG_MODE)
                        ) ||
-                       (cur_csc_type <
+                       (cur_csc_type[vd_path] <
                                VPP_MATRIX_BT2020YUV_BT2020RGB)) {
                        if (get_hdr_type() & HLG_FLAG)
-                               bypass_hdr_process(csc_type, vinfo, p);
+                               bypass_hdr_process(csc_type, vinfo, p,
+                                       vd_path);
                        else
                                need_adjust_contrast_saturation =
-                                       hdr_process(csc_type, vinfo, p);
-                       pr_csc("hdr_process_mode = 0x%x\n"
-                               "hlg_process_mode = 0x%x.\n",
-                               hdr_process_mode, hlg_process_mode);
+                                       hdr_process(csc_type, vinfo, p,
+                                               vd_path);
+                       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 == 0) && (hlg_process_mode == 0)) {
+               (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 |
@@ -6306,25 +6779,36 @@ static void video_process(
                        SIG_HDR_MODE |
                        SIG_HDR_SUPPORT |
                        SIG_HLG_MODE)) ||
-                       (cur_csc_type <
+                       (cur_csc_type[vd_path] <
                                VPP_MATRIX_BT2020YUV_BT2020RGB)) {
-                       bypass_hdr_process(csc_type, vinfo, p);
-                       pr_csc("bypass_hdr_process: 0x%x, 0x%x.\n",
-                               hdr_process_mode, hlg_process_mode);
+                       bypass_hdr_process(csc_type, vinfo, p,
+                               vd_path);
+                       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) &&
-               (hdr10_plus_process_mode == 1)) {
+       } else if (csc_type == VPP_MATRIX_BT2020YUV_BT2020RGB_DYNAMIC) {
                if ((signal_change_flag & SIG_HDR10_PLUS_MODE) ||
-                       (cur_csc_type !=
-                       VPP_MATRIX_BT2020YUV_BT2020RGB_DYNAMIC))
-                       hdr_process(csc_type, vinfo, p);
-                       /* hdr10_plus_process(vf); */
-               pr_csc("hdr10_plus_process.\n");
+                       (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) {
+                               hdr_process(csc_type, vinfo, p, vd_path);
+                               /* hdr10_plus_process(vf); */
+                       } else {
+                               bypass_hdr_process(
+                                       csc_type, vinfo, p, vd_path);
+                       }
+               }
+               pr_csc(1, "vd_path = %d\nhdr10_plus_process.\n",
+                       vd_path + 1);
        } else {
                if ((csc_type < VPP_MATRIX_BT2020YUV_BT2020RGB) &&
-                       sdr_process_mode)
+                       sdr_process_mode[vd_path])
                        /* for gxl and gxm SDR to HDR process */
-                       sdr_hdr_process(csc_type, vinfo, p);
+                       sdr_hdr_process(csc_type, vinfo, p, vd_path);
                else {
                        /* for gxtvbb and gxl HDR bypass process */
                        if (((vinfo->hdr_info.hdr_support &
@@ -6335,13 +6819,20 @@ static void video_process(
                                VPP_MATRIX_BT2020YUV_BT2020RGB)
                                && tx_op_color_primary)
                                set_bt2020csc_process(csc_type,
-                               vinfo, p);
+                               vinfo, p, vd_path);
                        else
                                bypass_hdr_process(csc_type,
-                               vinfo, p);
-                       pr_csc("csc_type = 0x%x\n"
-                               "sdr_process_mode = 0x%x.\n",
-                               csc_type, sdr_process_mode);
+                               vinfo, p, vd_path);
+                       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]);
                }
        }
 
@@ -6353,20 +6844,35 @@ static void video_process(
                                MATRIX_YUV709_RGB, MTX_ON);
        }
 
-       if (cur_hdr_process_mode != hdr_process_mode) {
-               cur_hdr_process_mode = hdr_process_mode;
-               pr_csc("hdr_process_mode changed to %d",
-                       hdr_process_mode);
+       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 != sdr_process_mode) {
-               cur_sdr_process_mode = sdr_process_mode;
-               pr_csc("sdr_process_mode changed to %d",
-                       sdr_process_mode);
+       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 != hlg_process_mode) {
-               cur_hlg_process_mode = hlg_process_mode;
-               pr_csc("hlg_process_mode changed to %d",
-                       hlg_process_mode);
+       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 (need_adjust_contrast_saturation & 1) {
                if (lut_289_en &&
@@ -6385,31 +6891,34 @@ static void video_process(
        } else {
                if (((get_cpu_type() == MESON_CPU_MAJOR_ID_GXTVBB) ||
                        (get_cpu_type() == MESON_CPU_MAJOR_ID_TXL)) &&
-                       (sdr_process_mode == 1))
+                       (sdr_process_mode[vd_path] == PROC_SDR_TO_HDR))
                        saturation_offset = sdr_saturation_offset;
                else
                        saturation_offset = 0;
                vecm_latch_flag |= FLAG_VADJ1_COLOR;
        }
-       if (cur_csc_type != csc_type) {
-               pr_csc("CSC from 0x%x to 0x%x.\n",
-                       cur_csc_type, csc_type);
-               pr_csc("contrast offset = %d.\n",
-                       vd1_contrast_offset);
-               pr_csc("saturation offset = %d.\n",
-                       saturation_offset);
-               cur_csc_type = csc_type;
+       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;
+
        }
 }
 
 static int vpp_matrix_update(
-       struct vframe_s *vf, struct vinfo_s *vinfo, int flags)
+       struct vframe_s *vf, struct vinfo_s *vinfo, int flags,
+       enum vd_path_e vd_path)
 {
        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;
+       struct vframe_master_display_colour_s *p =
+               &cur_master_display_colour[vd_path];
        int hdmi_scs_type_changed = 0;
-       struct hdr10plus_para hdmitx_hdr10plus_param;
+       bool hdr10p_meta_updated = false;
 
        if (vinfo == NULL)
                return 0;
@@ -6418,25 +6927,78 @@ static int vpp_matrix_update(
        memcpy(&receiver_hdr_info, &vinfo->hdr_info,
                        sizeof(struct hdr_info));
 
-       hdr_support_process(vinfo);
+       if (!cpu_after_eq(MESON_CPU_MAJOR_ID_G12A) ||
+       (get_cpu_type() == MESON_CPU_MAJOR_ID_TL1))
+               hdr_support_process(vinfo, vd_path);
 
        if (vf && vinfo)
-               signal_change_flag = signal_type_changed(vf, vinfo);
+               signal_change_flag =
+                       signal_type_changed(vf, vinfo, vd_path);
 
+       get_cur_vd_signal_type(vd_path);
        if (force_csc_type != 0xff)
                csc_type = force_csc_type;
        else
                csc_type = get_csc_type();
 
-       hdr10_plus_metadata_update(vf, csc_type,
-               &hdmitx_hdr10plus_param);
 
-       hdr_tx_pkt_cb(vinfo,
-               signal_change_flag,
-               csc_type,
-               p,
-               &hdmi_scs_type_changed,
-               &hdmitx_hdr10plus_param);
+       if (video_process_status[vd_path] == HDR_MODULE_BYPASS) {
+               if (is_video_layer_on(vd_path) &&
+               (!is_dolby_vision_on() || (vd_path == VD2_PATH)))
+                       video_process_status[vd_path] = HDR_MODULE_ON;
+               else
+                       return 2;
+       }
+
+       if (is_dolby_vision_on() && (vd_path == VD1_PATH))
+               return 0;
+
+       if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A) &&
+       (get_cpu_type() != MESON_CPU_MAJOR_ID_TL1)) {
+               enum hdr_type_e source_format[VD_PATH_MAX];
+               enum vd_path_e oth_path =
+                       (vd_path == VD1_PATH) ? VD2_PATH : VD1_PATH;
+
+               source_format[VD1_PATH] = get_source_type(VD1_PATH);
+               source_format[VD2_PATH] = get_source_type(VD2_PATH);
+               get_cur_vd_signal_type(vd_path);
+               signal_change_flag |=
+                       hdr_policy_process(vinfo, source_format, vd_path);
+               if (signal_change_flag & SIG_OUTPUT_MODE_CHG) {
+                       if (!is_video_layer_on(vd_path))
+                               video_layer_wait_on[vd_path] = true;
+                       video_process_flags[oth_path] |=
+                               PROC_FLAG_FORCE_PROCESS;
+                       return 1;
+               }
+       }
+
+       if ((vf != NULL) && (flags & CSC_FLAG_TOGGLE_FRAME)) {
+               hdr10_plus_metadata_update(vf, csc_type,
+                       &hdmitx_hdr10plus_params[vd_path]);
+               hdr10p_meta_updated = true;
+       }
+
+       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)))
+                       hdmi_packet_process(signal_change_flag, vinfo, p,
+                               hdr10p_meta_updated ?
+                               &hdmitx_hdr10plus_params[vd_path] : NULL,
+                               vd_path);
+       } 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);
+       }
 
        if (hdmi_scs_type_changed &&
                (flags & CSC_FLAG_CHECK_OUTPUT) &&
@@ -6447,38 +7009,47 @@ static int vpp_matrix_update(
                && ((flags & CSC_FLAG_TOGGLE_FRAME) == 0))
                return 0;
 
-       if ((cur_csc_type != csc_type)
+       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)))
-               video_process(vf, csc_type, signal_change_flag, vinfo, p);
+               SIG_SRC_OUTPUT_CHG | SIG_HDR10_PLUS_MODE |
+               SIG_SRC_CHG))) {
+               if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A) &&
+               (get_cpu_type() != MESON_CPU_MAJOR_ID_TL1))
+                       video_post_process(csc_type, vinfo, vd_path);
+               else
+                       video_process(vf, csc_type, signal_change_flag,
+                               vinfo, p, vd_path);
+       }
 
        /* eye protection mode */
        if (signal_change_flag & SIG_WB_CHG)
-               vpp_eye_protection_process(csc_type, vinfo);
+               vpp_eye_protection_process(csc_type, vinfo, vd_path);
 
        return 0;
 }
 
-static struct vframe_s *last_vf;
-static int last_vf_signal_type;
-static int null_vf_cnt;
+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];
 static int prev_hdr_support;
-static int prev_output_mode;
+static int prev_color_fmt;
 
 static unsigned int fg_vf_sw_dbg;
-unsigned int null_vf_max = 1;
+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)
+       struct vframe_s *vf, struct vframe_s *vf_rpt, int flags,
+       enum vd_path_e vd_path)
 {
        struct vframe_s fake_vframe;
        struct vinfo_s *vinfo = get_current_vinfo();
        int toggle_frame;
        int i;
+       int ret;
 
        if ((get_cpu_type() < MESON_CPU_MAJOR_ID_GXTVBB) ||
                is_meson_gxl_package_905M2() || (csc_en == 0))
@@ -6500,86 +7071,165 @@ int amvecm_matrix_process(
                                        CSC_ON);
        }
 
-       if (is_dolby_vision_on())
-               return 0;
+       if (is_dolby_vision_on() && vd_path == VD1_PATH) {
+               if ((video_process_status[vd_path] == HDR_MODULE_BYPASS)
+               && (vf || vf_rpt))
+                       return vpp_matrix_update(
+                               vf ? vf : vf_rpt, vinfo, flags, vd_path);
+               else
+                       return 0;
+       }
 
-       if (flags & CSC_FLAG_CHECK_OUTPUT) {
-               if (vpp_matrix_update(vf, vinfo, flags) == 1) {
-                       pr_csc("hdr/sdr output changing ...\n");
+       if ((vf != NULL) && (flags & CSC_FLAG_CHECK_OUTPUT)) {
+               ret = vpp_matrix_update(vf, vinfo, flags, vd_path);
+               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;
                }
-       }
-       if (vf != NULL) {
-               if (debug_csc & 2)
-                       pr_csc("new frame %x%s\n",
-                               vf->signal_type,
-                               get_video_enabled() ? " " : ", video off");
-               vpp_matrix_update(vf, vinfo, flags);
-               last_vf = vf;
-               last_vf_signal_type = vf->signal_type;
-               null_vf_cnt = 0;
+       } else if ((vf != NULL) && (flags & CSC_FLAG_TOGGLE_FRAME)) {
+               if (is_video_layer_on(vd_path) ||
+               video_process_flags[vd_path] & PROC_FLAG_FORCE_PROCESS) {
+                       video_process_status[vd_path] = HDR_MODULE_ON;
+                       vpp_matrix_update(vf, vinfo, flags, vd_path);
+                       video_process_flags[vd_path] &=
+                               ~PROC_FLAG_FORCE_PROCESS;
+                       last_vf[vd_path] = vf;
+                       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 = vf;
-       } else if (vf_rpt != NULL) {
-               if (debug_csc & 2)
-                       pr_csc("rpt frame\n");
-               null_vf_cnt = 0;
+       } else if ((vf_rpt != NULL) && is_video_layer_on(vd_path)) {
+               if (video_process_flags[vd_path] & PROC_FLAG_FORCE_PROCESS) {
+                       vpp_matrix_update(vf_rpt, vinfo, flags, vd_path);
+                       video_process_flags[vd_path] &=
+                               ~PROC_FLAG_FORCE_PROCESS;
+                       pr_csc(2, "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 (get_video_enabled() && (last_vf != NULL)) {
-               if (debug_csc & 2)
-                       pr_csc("rpt frame local\n");
-               null_vf_cnt = 0;
+       } else if ((last_vf[vd_path] != NULL) && is_video_layer_on(vd_path)) {
+               pr_csc(2, "vd%d: rpt frame local\n",
+                       vd_path + 1);
+               null_vf_cnt[vd_path] = 0;
                fg_vf_sw_dbg = 3;
        } else {
                /* handle change between TV support/not support HDR */
                if (prev_hdr_support != vinfo->hdr_info.hdr_support) {
-                       null_vf_cnt = 0;
+                       if ((vd_path == VD1_PATH) ||
+                       ((vd_path == VD2_PATH) &&
+                       is_video_layer_on(VD2_PATH)))
+                               null_vf_cnt[vd_path] = 0;
                        prev_hdr_support = vinfo->hdr_info.hdr_support;
+                       pr_csc(2, "vd%d: hdr_support changed\n",
+                               vd_path + 1);
                }
                /* handle change between output mode*/
-               if (prev_output_mode != vinfo->viu_color_fmt) {
-                       null_vf_cnt = 0;
-                       prev_output_mode =      vinfo->viu_color_fmt;
+               if (prev_color_fmt != vinfo->viu_color_fmt) {
+                       if ((vd_path == VD1_PATH) ||
+                       ((vd_path == VD2_PATH) &&
+                       is_video_layer_on(VD2_PATH)))
+                               null_vf_cnt[vd_path] = 0;
+                       prev_color_fmt = vinfo->viu_color_fmt;
+                       pr_csc(2, "vd%d: output color format changed\n",
+                               vd_path + 1);
                }
                /* handle eye protect mode */
-               if (cur_eye_protect_mode != wb_val[0])
-                       null_vf_cnt = 0;
-               if (csc_en & 0x10)
+               if ((cur_eye_protect_mode != wb_val[0])
+               && (vd_path == VD1_PATH)) {
+                       null_vf_cnt[vd_path] = 0;
+                       pr_csc(2, "vd%d: eye_protect_mode changed\n",
+                               vd_path + 1);
+               }
+
+               if (!is_video_layer_on(vd_path)
+               && (video_process_status[vd_path] == HDR_MODULE_ON))
+                       null_vf_cnt[vd_path] = toggle_frame = 1;
+               else if (csc_en & 0x10)
                        toggle_frame = null_vf_max;
                else
                        toggle_frame = 0;
-               /* when sdr mode change */
-               if ((vinfo->hdr_info.hdr_support & 0x4) &&
+
+               /* handle sdr_mode change */
+               if ((vinfo->hdr_info.hdr_support & 0xc) &&
                        ((cpu_after_eq(MESON_CPU_MAJOR_ID_GXL)) &&
-                       (vinfo->viu_color_fmt != COLOR_FMT_RGB444)))
-                       if (((sdr_process_mode != 1) && (sdr_mode > 0))
-                               || ((sdr_process_mode > 0) && (sdr_mode == 0)))
-                               null_vf_cnt = toggle_frame;
-               if ((null_vf_cnt == 0) || (null_vf_cnt == toggle_frame)) {
-                       pr_csc("Fake SDR frame\n");
-                       /*send a faked vframe to switch matrix*/
-                       /*from 2020 to 601 when video disabled */
-                       fake_vframe.source_type = VFRAME_SOURCE_TYPE_OTHERS;
-                       fake_vframe.signal_type = 0;
-                       fake_vframe.width = 1920;
-                       fake_vframe.height = 1080;
-                       fake_vframe.prop.master_display_colour.present_flag
-                               = 0x80000000;
-                       if (null_vf_cnt == toggle_frame)
-                               vpp_matrix_update(
-                                       &fake_vframe, vinfo,
-                                       CSC_FLAG_TOGGLE_FRAME);
-                       else if (null_vf_cnt == 0)
-                               vpp_matrix_update(
-                                       &fake_vframe, vinfo,
-                                       CSC_FLAG_CHECK_OUTPUT);
-                       last_vf = NULL;
+                       (vinfo->viu_color_fmt != COLOR_FMT_RGB444))) {
+                       if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) {
+                               if (hdr_mode != cur_hdr_mode) {
+                                       null_vf_cnt[vd_path] = toggle_frame;
+                                       cur_hdr_mode = hdr_mode;
+                                       pr_csc(2, "vd%d: hdr_mode changed\n",
+                                               vd_path + 1);
+                               }
+                               if (sdr_mode != cur_sdr_mode) {
+                                       null_vf_cnt[vd_path] = toggle_frame;
+                                       cur_sdr_mode = sdr_mode;
+                                       pr_csc(2, "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] = toggle_frame;
+               }
+
+               if (null_vf_cnt[vd_path] == toggle_frame) {
+                       pr_csc(8,
+                               "vd%d: %d %d Fake SDR frame%s, dolby on=%d, dolby policy =%d\n",
+                               vd_path + 1,
+                               null_vf_cnt[vd_path],
+                               toggle_frame,
+                               is_video_layer_on(vd_path) ?
+                               " " : ", video off",
+                               is_dolby_vision_on(),
+                               get_dolby_vision_policy());
+                       video_process_status[vd_path] = HDR_MODULE_OFF;
+                       if ((get_dolby_vision_policy() != 0) ||
+                           (!is_dolby_vision_on())) {
+                               /*send a faked vframe to switch matrix*/
+                               /*from 2020 to 601 when video disabled */
+                               fake_vframe.source_type =
+                                       VFRAME_SOURCE_TYPE_OTHERS;
+                               fake_vframe.signal_type = 0;
+                               fake_vframe.width = 1920;
+                               fake_vframe.height = 1080;
+                               fake_vframe.prop.
+                               master_display_colour.present_flag
+                                       = 0x80000000;
+                               if (null_vf_cnt[vd_path] == toggle_frame)
+                                       vpp_matrix_update(
+                                               &fake_vframe, vinfo,
+                                               CSC_FLAG_TOGGLE_FRAME, vd_path);
+                               else if (null_vf_cnt[vd_path] == 0)
+                                       vpp_matrix_update(
+                                               &fake_vframe, vinfo,
+                                               CSC_FLAG_CHECK_OUTPUT, vd_path);
+                       }
+                       last_vf[vd_path] = NULL;
+                       null_vf_cnt[vd_path] = null_vf_max;
                        fg_vf_sw_dbg = 4;
                        dbg_vf = NULL;
+                       video_process_status[vd_path] = HDR_MODULE_BYPASS;
                }
-               if (null_vf_cnt <= null_vf_max)
-                       null_vf_cnt++;
+               if (null_vf_cnt[vd_path] <= null_vf_max)
+                       null_vf_cnt[vd_path]++;
        }
        return 0;
 }
@@ -6701,27 +7351,27 @@ hdr_dump:
        pr_err("customer_master_display_en:0x%x\n", customer_master_display_en);
 
        pr_err("hdr_mode:0x%x, hdr_process_mode:0x%x, cur_hdr_process_mode:0x%x\n",
-               hdr_mode, hdr_process_mode, cur_hdr_process_mode);
+               hdr_mode, hdr_process_mode[0], cur_hdr_process_mode[0]);
 
        pr_err("hlg_process_mode: 0x%x :0->hlg->hlg,1->hlg->sdr,2->hlg->hdr10\n",
-               hlg_process_mode);
+               hlg_process_mode[0]);
 
        pr_err("sdr_mode:0x%x, sdr_process_mode:0x%x, cur_sdr_process_mode:0x%x\n",
-               sdr_mode, sdr_process_mode, cur_sdr_process_mode);
+               sdr_mode, sdr_process_mode[0], cur_sdr_process_mode[0]);
 
        pr_err("hdr_flag:0x%x,     fg_vf_sw_dbg:0x%x\n",
                hdr_flag, fg_vf_sw_dbg);
        pr_err("cur_signal_type:0x%x, cur_csc_mode:0x%x, cur_csc_type:0x%x\n",
-               cur_signal_type, cur_csc_mode, cur_csc_type);
+               cur_signal_type[0], cur_csc_mode, cur_csc_type[0]);
 
        pr_err("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_err("tx_hdr10_plus_support = 0x%x\n", tx_hdr10_plus_support);
-       pr_err("hdr10_plus_process_mode = 0x%x\n", hdr10_plus_process_mode);
+       pr_err("hdr10_plus_process_mode = 0x%x\n", hdr10_plus_process_mode[0]);
 
        //if (signal_transfer_characteristic == 0x30)
-       if (cur_csc_type == VPP_MATRIX_BT2020YUV_BT2020RGB_DYNAMIC)
+       if (cur_csc_type[0] == VPP_MATRIX_BT2020YUV_BT2020RGB_DYNAMIC)
                hdr10_plus_debug();
 
        if ((receiver_hdr_info.hdr_support & 0xc) == 0)
index b0ccbc0..3839fdf 100644 (file)
 #ifndef AM_CSC_H
 #define AM_CSC_H
 
+extern uint debug_csc;
+#define pr_csc(lvl, fmt, args...)\
+       do {\
+               if (debug_csc & lvl)\
+                       pr_info(fmt, ## args);\
+       } while (0)
+
 /* white balance value */
 extern void ve_ogo_param_update(void);
 extern struct tcon_rgb_ogo_s video_rgb_ogo;
@@ -75,6 +82,16 @@ enum mtx_en_e {
        OSD1_MTX_EN
 };
 
+enum output_format_e {
+       UNKNOWN_FMT = 0,
+       BT709,
+       BT2020,
+       BT2020_PQ,
+       BT2020_PQ_DYNAMIC,
+       BT2020_HLG,
+       BT2100_IPT
+};
+
 #define POST_MTX_EN_MASK (1 << POST_MTX_EN)
 #define VD2_MTX_EN_MASK  (1 << VD2_MTX_EN)
 #define VD1_MTX_EN_MASK  (1 << VD1_MTX_EN)
@@ -84,6 +101,21 @@ enum mtx_en_e {
 #define HDR_SUPPORT            (1 << 2)
 #define HLG_SUPPORT            (1 << 3)
 
+#define SIG_CS_CHG     0x01
+#define SIG_SRC_CHG    0x02
+#define SIG_PRI_INFO   0x04
+#define SIG_KNEE_FACTOR        0x08
+#define SIG_HDR_MODE   0x10
+#define SIG_HDR_SUPPORT        0x20
+#define SIG_WB_CHG     0x40
+#define SIG_HLG_MODE   0x80
+#define SIG_HLG_SUPPORT        0x100
+#define SIG_OP_CHG     0x200
+#define SIG_SRC_OUTPUT_CHG     0x400/*for box*/
+#define SIG_HDR10_PLUS_MODE    0x800
+#define SIG_COLORIMETRY_SUPPORT 0x1000
+#define SIG_OUTPUT_MODE_CHG    0x2000
+
 #define LUT_289_SIZE   289
 extern unsigned int lut_289_mapping[LUT_289_SIZE];
 extern int dnlp_en;
@@ -97,15 +129,36 @@ extern uint hdr_flag;
 extern int video_rgb_ogo_xvy_mtx_latch;
 extern int video_rgb_ogo_xvy_mtx;
 extern int tx_op_color_primary;
-extern uint cur_csc_type;
+extern uint cur_csc_type[VD_PATH_MAX];
+
+/* 0: hdr->hdr, 1:hdr->sdr, 2:hdr->hlg */
+extern uint hdr_process_mode[VD_PATH_MAX];
+extern uint cur_hdr_process_mode[VD_PATH_MAX];
+
+/* 0: bypass, 1:hdr10p->hdr, 2:hdr10p->sdr, 3:hdr10p->hlg */
+extern uint hdr10_plus_process_mode[VD_PATH_MAX];
+extern uint cur_hdr10_plus_process_mode[VD_PATH_MAX];
+
+/* 0: hlg->hlg, 1:hlg->sdr 2:hlg->hdr*/
+extern uint hlg_process_mode[VD_PATH_MAX];
+extern uint cur_hlg_process_mode[VD_PATH_MAX];
+
+/* 0: sdr->sdr, 1:sdr->hdr, 2:sdr->hlg */
+extern uint sdr_process_mode[VD_PATH_MAX];
+extern uint cur_sdr_process_mode[VD_PATH_MAX];
 
+/* 0: tx don't support hdr10+, 1: tx support hdr10+*/
+extern uint tx_hdr10_plus_support;
 
 extern int amvecm_matrix_process(
-       struct vframe_s *vf, struct vframe_s *vf_rpt, int flags);
+       struct vframe_s *vf, struct vframe_s *vf_rpt, int flags,
+       enum vd_path_e vd_path);
 extern int amvecm_hdr_dbg(u32 sel);
 
 extern u32 get_video_enabled(void);
+extern u32 get_videopip_enabled(void);
 extern void get_hdr_source_type(void);
+extern void get_cur_vd_signal_type(enum vd_path_e vd_path);
 extern enum color_primary_e get_color_primary(void);
 /*hdr*/
 /*#define DBG_BUF_SIZE (1024)*/
@@ -125,6 +178,44 @@ struct hdr_data_t {
 extern void hdr_init(struct hdr_data_t *phdr_data);
 extern void hdr_exit(void);
 extern void hdr_set_cfg_osd_100(int val);
+extern void hdr_osd_off(void);
+extern void hdr_vd1_off(void);
+extern bool is_video_layer_on(enum vd_path_e vd_path);
+
+#define HDR_MODULE_OFF         0
+#define HDR_MODULE_ON          1
+#define HDR_MODULE_BYPASS      2
+extern void set_hdr_module_status(enum vd_path_e vd_path, int status);
+extern int get_hdr_module_status(enum vd_path_e vd_path);
+extern int get_primaries_type(struct vframe_master_display_colour_s *p_mdc);
+
+#define PROC_BYPASS                    0
+/* to backward compatible */
+#define PROC_MATCH                     1
+#define PROC_OFF                       4
+/* sdr */
+#define PROC_SDR_TO_HDR                1
+#define PROC_SDR_TO_HLG                2
+/* hdr */
+#define PROC_HDR_TO_SDR                1
+#define PROC_HDR_TO_HLG                2
+/* hlg */
+#define PROC_HLG_TO_SDR                1
+#define PROC_HLG_TO_HDR                2
+/* hdr+ */
+#define PROC_HDRP_TO_HDR       1
+#define PROC_HDRP_TO_SDR       2
+#define PROC_HDRP_TO_HLG       3
+
+extern uint get_hdr10_plus_pkt_delay(void);
+extern void update_hdr10_plus_pkt(bool enable,
+       void *hdr10plus_params,
+       void *send_info);
+extern void send_hdr10_plus_pkt(enum vd_path_e vd_path);
+
+#define HDRPLUS_PKT_UPDATE     2
+#define HDRPLUS_PKT_REPEAT     1
+#define HDRPLUS_PKT_IDLE       0
 
 #endif /* AM_CSC_H */
 
diff --git a/drivers/amlogic/media/enhancement/amvecm/amcsc_pip.c b/drivers/amlogic/media/enhancement/amvecm/amcsc_pip.c
new file mode 100644 (file)
index 0000000..2e8162d
--- /dev/null
@@ -0,0 +1,929 @@
+/*
+ * drivers/amlogic/media/enhancement/amvecm/amcsc_pip.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <linux/amlogic/media/vfm/vframe.h>
+#include <linux/amlogic/media/vfm/video_common.h>
+#include <linux/amlogic/media/amvecm/amvecm.h>
+#include <linux/amlogic/media/amdolbyvision/dolby_vision.h>
+#include "amcsc.h"
+#include "set_hdr2_v0.h"
+#include "hdr/am_hdr10_plus.h"
+
+/* 0: follow sink, 1: follow source */
+static uint hdr_policy;
+static uint cur_hdr_policy;
+static enum output_format_e target_format[VD_PATH_MAX];
+static enum hdr_type_e cur_source_format[VD_PATH_MAX];
+static enum output_format_e output_format;
+
+static const char *module_str[7] = {
+       "UNKNOWN",
+       "VD1",
+       "VD2",
+       "OSD1",
+       "VDIN0",
+       "VDIN1",
+       "DI"
+};
+
+static const char *process_str[15] = {
+       "UNKNOWN",
+       "HDR_BYPASS",
+       "HDR_SDR",
+       "SDR_HDR",
+       "HLG_BYPASS",
+       "HLG_SDR",
+       "HLG_HDR",
+       "SDR_HLG",
+       "SDR_IPT",
+       "HDR_IPT",
+       "HLG_IPT",
+       "HDR_HLG",
+       "RGB_YUV",
+       "RGB_HDR",
+       "RGB_HLG"
+};
+
+static const char *policy_str[3] = {
+       "follow_sink",
+       "follow_source",
+       "force_output"
+};
+
+static const char *input_str[7] = {
+       "NONE",
+       "HDR",
+       "HDR+",
+       "DOVI",
+       "PRIME",
+       "HLG",
+       "SDR"
+};
+
+/* output_format_e */
+static const char *output_str[7] = {
+       "UNKNOWN",
+       "709",
+       "2020",
+       "HDR",
+       "HDR+",
+       "HLG",
+       "IPT"
+};
+
+static const char *dv_output_str[6] = {
+       "IPT",
+       "TUNNEL",
+       "HDR10",
+       "SDR10",
+       "SDR8",
+       "BYPASS"
+};
+
+void hdr_proc(
+       enum hdr_module_sel module_sel,
+       enum hdr_process_sel hdr_process_select,
+       struct vinfo_s *vinfo)
+{
+       enum hdr_process_sel cur_hdr_process;
+
+       cur_hdr_process = hdr_func(
+               module_sel, hdr_process_select, vinfo);
+       if (cur_hdr_process != hdr_process_select)
+               pr_csc(8, "am_vecm: module=%s, process=%s(%s)\n",
+                       module_str[module_sel],
+                       process_str[hdr_process_select],
+                       process_str[cur_hdr_process]);
+       else
+               pr_csc(8, "am_vecm: hdr module=%s, process=%s\n",
+                       module_str[module_sel],
+                       process_str[hdr_process_select]);
+}
+
+int hdr_policy_process(
+       struct vinfo_s *vinfo,
+       enum hdr_type_e *source_format,
+       enum vd_path_e vd_path)
+{
+       int change_flag = 0;
+       enum vd_path_e oth_path =
+               (vd_path == VD1_PATH) ? VD2_PATH : VD1_PATH;
+       int dv_policy = 0;
+       int dv_mode = 0;
+       bool hdr10_plus_support =
+               (vinfo->hdr_info.hdr10plus_info.ieeeoui
+               == HDR_PLUS_IEEE_OUI) &&
+               (vinfo->hdr_info.hdr10plus_info.application_version
+               == 1);
+
+       tx_hdr10_plus_support = hdr10_plus_support;
+
+       cur_hdr_policy = hdr_policy;
+       if (is_dolby_vision_enable()) {
+               /* sync hdr_policy with dolby_vision_policy */
+               /* get current dolby_vision_mode */
+               dv_policy = get_dolby_vision_policy();
+               dv_mode = get_dolby_vision_mode();
+               if ((dv_policy != DOLBY_VISION_FORCE_OUTPUT_MODE)
+               || (dv_mode != DOLBY_VISION_OUTPUT_MODE_BYPASS)) {
+                       /* use dv policy when not force bypass */
+                       cur_hdr_policy = dv_policy;
+               }
+       }
+
+       if ((get_hdr_module_status(vd_path) != HDR_MODULE_ON)
+       && is_dolby_vision_enable()) {
+               sdr_process_mode[vd_path] = PROC_BYPASS;
+               hdr_process_mode[vd_path] = PROC_BYPASS;
+               hlg_process_mode[vd_path] = PROC_BYPASS;
+               hdr10_plus_process_mode[vd_path] = PROC_BYPASS;
+               target_format[vd_path] = BT709;
+       } else if (cur_hdr_policy == 0) {
+               if ((vd_path == VD1_PATH)
+               && (source_format[vd_path] == HDRTYPE_HLG)
+               && (vinfo->hdr_info.hdr_support & HLG_SUPPORT)) {
+                       /* vd1 bypass hlg */
+                       hlg_process_mode[vd_path] = PROC_BYPASS;
+                       target_format[vd_path] = BT2020_HLG;
+               } else if ((vd_path == VD1_PATH)
+               && (!is_video_layer_on(VD2_PATH))
+               && (source_format[vd_path] == HDRTYPE_HDR10PLUS)
+               && hdr10_plus_support) {
+                       /* vd1 bypass hdr+ when vd2 off */
+                       hdr10_plus_process_mode[vd_path] = PROC_BYPASS;
+                       target_format[vd_path] = BT2020_PQ_DYNAMIC;
+               } else if (is_dolby_vision_on() && (vd_path == VD2_PATH)) {
+                       /* vd2 *->ipt when vd1 dolby on */
+                       hdr_process_mode[vd_path] = PROC_MATCH;
+                       hlg_process_mode[vd_path] = PROC_MATCH;
+                       sdr_process_mode[vd_path] = PROC_MATCH;
+                       hdr10_plus_process_mode[vd_path] = PROC_MATCH;
+                       target_format[vd_path] = BT2100_IPT;
+               } else if ((vd_path == VD2_PATH)
+               && is_video_layer_on(VD1_PATH)) {
+                       /* vd1 on and vd2 follow vd1 output */
+                       if (target_format[VD1_PATH] == BT2020_HLG) {
+                               /* vd2 *->hlg when vd1 output hlg */
+                               sdr_process_mode[vd_path] = PROC_SDR_TO_HLG;
+                               hdr_process_mode[vd_path] = PROC_HDR_TO_HLG;
+                               hlg_process_mode[vd_path] = PROC_BYPASS;
+                               hdr10_plus_process_mode[vd_path] =
+                                       PROC_HDRP_TO_HLG;
+                               target_format[vd_path] = BT2020_HLG;
+                       } else if ((target_format[VD1_PATH] == BT2020_PQ) ||
+                       (target_format[VD1_PATH] == BT2020_PQ_DYNAMIC)) {
+                               /* vd2 *->hdr when vd1 output hdr/hdr+ */
+                               sdr_process_mode[vd_path] = PROC_SDR_TO_HDR;
+                               hdr_process_mode[vd_path] = PROC_BYPASS;
+                               hlg_process_mode[vd_path] = PROC_HLG_TO_HDR;
+                               hdr10_plus_process_mode[vd_path] =
+                                       PROC_HDRP_TO_HDR;
+                               target_format[vd_path] = BT2020_PQ;
+                       } else {
+                               /* vd2 *->sdr when vd1 output sdr */
+                               sdr_process_mode[vd_path] = PROC_BYPASS;
+                               hdr_process_mode[vd_path] = PROC_HDR_TO_SDR;
+                               hlg_process_mode[vd_path] = PROC_HLG_TO_SDR;
+                               hdr10_plus_process_mode[vd_path] =
+                                       PROC_HDRP_TO_SDR;
+                               if ((target_format[VD1_PATH] == BT2020) &&
+                               (source_format[vd_path] == HDRTYPE_HLG))
+                                       target_format[vd_path] = BT2020;
+                               else
+                                       target_format[vd_path] = BT709;
+                       }
+               } else if ((vinfo->hdr_info.hdr_support & HDR_SUPPORT)
+               && ((source_format[vd_path] != HDRTYPE_HLG)
+               || ((source_format[vd_path] == HDRTYPE_HLG)
+               && (hdr_flag & 0x10)))) {
+                       /* *->hdr */
+                       sdr_process_mode[vd_path] = PROC_SDR_TO_HDR;
+                       hdr_process_mode[vd_path] = PROC_BYPASS;
+                       hlg_process_mode[vd_path] = PROC_HLG_TO_HDR;
+                       hdr10_plus_process_mode[vd_path] =
+                               PROC_HDRP_TO_HDR;
+                       target_format[vd_path] = BT2020_PQ;
+               } else {
+                       /* *->sdr */
+                       sdr_process_mode[vd_path] = PROC_BYPASS;
+                       hdr_process_mode[vd_path] = PROC_HDR_TO_SDR;
+                       hlg_process_mode[vd_path] = PROC_HLG_TO_SDR;
+                       hdr10_plus_process_mode[vd_path] =
+                               PROC_HDRP_TO_SDR;
+#if 0
+                       if ((vinfo->hdr_info.colorimetry_support
+                       & SINK_SUPPORTS_BT2020) &&
+                       (source_format[vd_path] == HDRTYPE_HLG) &&
+                       !is_video_layer_on(oth_path))
+                               target_format[vd_path] = BT2020;
+                       else
+                               target_format[vd_path] = BT709;
+#else
+                       target_format[vd_path] = BT709;
+#endif
+               }
+       } else if (cur_hdr_policy == 1) {
+               if ((vd_path == VD2_PATH) && is_dolby_vision_on()) {
+                       /* VD2 with VD1 in DV mode */
+                       hdr_process_mode[vd_path] = PROC_MATCH;
+                       hlg_process_mode[vd_path] = PROC_MATCH;
+                       sdr_process_mode[vd_path] = PROC_MATCH; /* *->ipt */
+                       target_format[vd_path] = BT2100_IPT;
+               } else if ((vd_path == VD1_PATH)
+               || ((vd_path == VD2_PATH) && !is_video_layer_on(VD1_PATH))) {
+                       /* VD1(with/without VD2) */
+                       /* or VD2(without VD1) <= should switch to VD1 */
+                       switch (source_format[vd_path]) {
+                       case HDRTYPE_SDR:
+                               if (is_video_layer_on(oth_path)) {
+                                       if ((target_format[oth_path] ==
+                                       BT2020_PQ) ||
+                                       (target_format[oth_path] ==
+                                       BT2020_PQ_DYNAMIC)) {
+                                               /* other layer output HDR */
+                                               /* sdr *->hdr */
+                                               sdr_process_mode[vd_path] =
+                                                       PROC_SDR_TO_HDR;
+                                               target_format[vd_path] =
+                                                       BT2020_PQ;
+                                       } else if (target_format[oth_path] ==
+                                       BT2020_HLG) {
+                                               /* other layer output hlg */
+                                               /* sdr *->hlg */
+                                               sdr_process_mode[vd_path] =
+                                                       PROC_SDR_TO_HLG;
+                                               target_format[vd_path] =
+                                                       BT2020_HLG;
+                                       } else {
+                                               /* sdr->sdr */
+                                               sdr_process_mode[vd_path] =
+                                                       PROC_BYPASS;
+                                               target_format[vd_path] = BT709;
+                                       }
+                               } else {
+                                       /* sdr->sdr */
+                                       sdr_process_mode[vd_path] =
+                                               PROC_BYPASS;
+                                       target_format[vd_path] = BT709;
+                               }
+                               break;
+                       case HDRTYPE_HLG:
+                               /* source HLG */
+                               if (is_video_layer_on(oth_path)
+                               && ((target_format[oth_path] ==
+                               BT2020_PQ) ||
+                               (target_format[oth_path] ==
+                               BT2020_PQ_DYNAMIC))) {
+                                       /* hlg->hdr */
+                                       hlg_process_mode[vd_path] =
+                                               PROC_HLG_TO_HDR;
+                                       target_format[vd_path] =
+                                               BT2020_PQ;
+                               } else if (vinfo->hdr_info.hdr_support
+                               & HLG_SUPPORT) {
+                                       /* hlg->hlg */
+                                       hlg_process_mode[vd_path] =
+                                               PROC_BYPASS;
+                                       target_format[vd_path] =
+                                               BT2020_HLG;
+                               } else if ((vinfo->hdr_info.hdr_support
+                               & HDR_SUPPORT) && (hdr_flag & 0x10)) {
+                                       /* hlg->hdr */
+                                       hlg_process_mode[vd_path] =
+                                               PROC_HLG_TO_HDR;
+                                       target_format[vd_path] =
+                                               BT2020_PQ;
+                               } else {
+                                       /* hlg->sdr */
+                                       hlg_process_mode[vd_path] =
+                                               PROC_HLG_TO_SDR;
+#if 0
+                                       if ((vinfo->hdr_info.colorimetry_support
+                                       & SINK_SUPPORTS_BT2020) &&
+                                       !is_video_layer_on(oth_path))
+                                               target_format[vd_path] =
+                                                       BT2020;
+                                       else
+                                               target_format[vd_path] =
+                                                       BT709;
+#else
+                                       target_format[vd_path] = BT709;
+#endif
+                               }
+                               break;
+                       case HDRTYPE_HDR10:
+                               /* source HDR10 */
+                               if (vinfo->hdr_info.hdr_support & HDR_SUPPORT) {
+                                       /* hdr bypass */
+                                       hdr_process_mode[vd_path] =
+                                               PROC_BYPASS;
+                                       target_format[vd_path] =
+                                               BT2020_PQ;
+                               } else if (vinfo->hdr_info.hdr_support
+                               & HLG_SUPPORT) {
+                                       /* hdr->hlg */
+                                       hdr_process_mode[vd_path] =
+                                               PROC_HDR_TO_HLG;
+                                       target_format[vd_path] =
+                                               BT2020_HLG;
+                               } else {
+                                       /* hdr ->sdr */
+                                       hdr_process_mode[vd_path] =
+                                               PROC_HDR_TO_SDR;
+                                       target_format[vd_path] =
+                                               BT709;
+                               }
+                               break;
+                       case HDRTYPE_HDR10PLUS:
+                               /* source HDR10+ */
+                               if (hdr10_plus_support
+                               && !is_video_layer_on(oth_path)) {
+                                       /* hdr+ bypass */
+                                       hdr10_plus_process_mode[vd_path] =
+                                               PROC_BYPASS;
+                                       target_format[vd_path] =
+                                               BT2020_PQ_DYNAMIC;
+                               } else if (vinfo->hdr_info.hdr_support
+                               & HDR_SUPPORT) {
+                                       /* hdr+->hdr */
+                                       hdr10_plus_process_mode[vd_path] =
+                                               PROC_HDRP_TO_HDR;
+                                       target_format[vd_path] = BT2020_PQ;
+                               } else if (vinfo->hdr_info.hdr_support
+                               & HLG_SUPPORT) {
+                                       /* hdr+->hlg */
+                                       hdr10_plus_process_mode[vd_path] =
+                                               PROC_HDRP_TO_HLG;
+                                       target_format[vd_path] = BT2020_HLG;
+                               } else {
+                                       /* hdr+ *->sdr */
+                                       hdr10_plus_process_mode[vd_path] =
+                                               PROC_HDRP_TO_SDR;
+                                       target_format[vd_path] = BT709;
+                               }
+                               break;
+                       default:
+                               break;
+                       }
+               } else {
+                       /* VD2 with VD1 */
+                       if (is_dolby_vision_on()) {
+                               /* VD1 is dolby vision */
+                               hdr_process_mode[vd_path] = PROC_MATCH;
+                               hlg_process_mode[vd_path] = PROC_MATCH;
+                               sdr_process_mode[vd_path] = PROC_MATCH;
+                               target_format[vd_path] = BT2100_IPT;
+                       } else {
+                               oth_path = VD1_PATH;
+                               switch (source_format[vd_path]) {
+                               case HDRTYPE_SDR:
+                                       /* VD2 source SDR */
+                                       if ((target_format[oth_path] ==
+                                       BT2020_PQ)
+                                       || (target_format[oth_path] ==
+                                       BT2020_PQ_DYNAMIC)) {
+                                               /* other layer output HDR */
+                                               /* sdr *->hdr */
+                                               sdr_process_mode[vd_path] =
+                                                       PROC_SDR_TO_HDR;
+                                               target_format[vd_path] =
+                                                       BT2020_PQ;
+                                       } else if (target_format[oth_path] ==
+                                       BT2020_HLG) {
+                                               /* other layer on and not sdr */
+                                               /* sdr *->hlg */
+                                               sdr_process_mode[vd_path] =
+                                                       PROC_SDR_TO_HLG;
+                                               target_format[vd_path] =
+                                                       BT2020_HLG;
+                                       } else {
+                                               /* sdr->sdr */
+                                               sdr_process_mode[vd_path] =
+                                                       PROC_BYPASS;
+                                               target_format[vd_path] = BT709;
+                                       }
+                                       break;
+                               case HDRTYPE_HLG:
+                                       /* VD2 source HLG */
+                                       if (target_format[oth_path]
+                                       == BT2020_HLG) {
+                                               /* hlg->hlg */
+                                               hlg_process_mode[vd_path] =
+                                                       PROC_BYPASS;
+                                               target_format[vd_path] =
+                                                       BT2020_HLG;
+                                       } else if ((target_format[oth_path] ==
+                                       BT2020_PQ)
+                                       || (target_format[oth_path] ==
+                                       BT2020_PQ_DYNAMIC)) {
+                                               /* hlg->hdr */
+                                               hlg_process_mode[vd_path] =
+                                                       PROC_HLG_TO_HDR;
+                                               target_format[vd_path] =
+                                                       BT2020_PQ;
+                                       } else if (target_format[oth_path] ==
+                                       BT709) {
+                                               /* hlg->sdr */
+                                               hlg_process_mode[vd_path] =
+                                                       PROC_HLG_TO_SDR;
+                                               target_format[vd_path] = BT709;
+                                       }
+                                       break;
+                               case HDRTYPE_HDR10:
+                                       /* VD2 source HDR10 */
+                                       if ((target_format[oth_path] ==
+                                       BT2020_PQ)
+                                       || (target_format[oth_path] ==
+                                       BT2020_PQ_DYNAMIC)) {
+                                               /* hdr->hdr */
+                                               hdr_process_mode[vd_path] =
+                                                       PROC_BYPASS;
+                                               target_format[vd_path] =
+                                                       BT2020_PQ;
+                                       } else if (target_format[oth_path]
+                                       == BT2020_HLG) {
+                                               /* hdr->hlg */
+                                               hdr_process_mode[vd_path] =
+                                                       PROC_HDR_TO_HLG;
+                                               target_format[vd_path] =
+                                                       BT2020_HLG;
+                                       } else {
+                                               /* hdr->sdr */
+                                               hdr_process_mode[vd_path] =
+                                                       PROC_HDR_TO_SDR;
+                                               target_format[vd_path] = BT709;
+                                       }
+                                       break;
+                               case HDRTYPE_HDR10PLUS:
+                                       /* VD2 source HDR10+ */
+                                       if ((target_format[oth_path] ==
+                                       BT2020_PQ)
+                                       || (target_format[oth_path] ==
+                                       BT2020_PQ_DYNAMIC)) {
+                                               /* hdr->hdr */
+                                               hdr10_plus_process_mode[vd_path]
+                                                       = PROC_HDRP_TO_HDR;
+                                               target_format[vd_path] =
+                                                       BT2020_PQ;
+                                       } else if (target_format[oth_path]
+                                       == BT2020_HLG) {
+                                               /* hdr->hlg */
+                                               hdr_process_mode[vd_path] =
+                                                       PROC_HDR_TO_HLG;
+                                               target_format[vd_path] =
+                                                       BT2020_HLG;
+                                       } else {
+                                               /* hdr->sdr */
+                                               hdr10_plus_process_mode[vd_path]
+                                                       = PROC_HDRP_TO_SDR;
+                                               target_format[vd_path] = BT709;
+                                       }
+                                       break;
+                               default:
+                                       break;
+                               }
+                       }
+               }
+       } else if (cur_hdr_policy == 2) {
+               /* *->ipt */
+               hdr_process_mode[vd_path] = PROC_MATCH;
+               hlg_process_mode[vd_path] = PROC_MATCH;
+               sdr_process_mode[vd_path] = PROC_MATCH;
+               target_format[vd_path] = BT2100_IPT;
+       }
+
+       /* update change flags */
+       if (is_dolby_vision_on()
+       && (vd_path == VD1_PATH)) {
+               pr_csc(4, "am_vecm: vd%d: (%s) %s->%s.\n",
+                       vd_path + 1,
+                       policy_str[dv_policy],
+                       input_str[get_dolby_vision_src_format()],
+                       dv_output_str[dv_mode]);
+       } else {
+               if (cur_hdr10_plus_process_mode[vd_path]
+               != hdr10_plus_process_mode[vd_path])
+                       change_flag |= SIG_HDR_MODE;
+               if (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])
+                       change_flag |= SIG_HLG_MODE;
+               if (cur_sdr_process_mode[vd_path]
+               != sdr_process_mode[vd_path])
+                       change_flag |= SIG_HDR_MODE;
+               if (cur_source_format[vd_path]
+               != source_format[vd_path])
+                       change_flag |= SIG_SRC_CHG;
+               if (change_flag)
+                       pr_csc(4, "am_vecm: vd%d: (%s) %s->%s (%s).\n",
+                               vd_path + 1,
+                               policy_str[cur_hdr_policy],
+                               input_str[source_format[vd_path]],
+                               output_str[target_format[vd_path]],
+                               is_dolby_vision_on() ?
+                               dv_output_str[dv_mode] :
+                               output_str[output_format]);
+       }
+       cur_source_format[vd_path] = source_format[vd_path];
+
+       if (is_dolby_vision_on()
+       && (vd_path == VD2_PATH)
+       && is_video_layer_on(VD2_PATH)
+       && (target_format[vd_path] != BT2100_IPT)) {
+               pr_csc(4, "am_vecm: vd%d output mode not match to dolby %s.\n",
+                       vd_path + 1,
+                       output_str[target_format[vd_path]]);
+               change_flag |= SIG_OUTPUT_MODE_CHG;
+       } else if (!is_dolby_vision_on()
+       && is_video_layer_on(VD1_PATH)
+       && is_video_layer_on(VD2_PATH)
+       && (target_format[vd_path]
+       != target_format[oth_path])) {
+               pr_csc(4, "am_vecm: vd%d output mode not match %s %s.\n",
+                       vd_path + 1,
+                       output_str[target_format[vd_path]],
+                       output_str[target_format[oth_path]]);
+               change_flag |= SIG_OUTPUT_MODE_CHG;
+       }
+       if (change_flag & SIG_OUTPUT_MODE_CHG) {
+               /* need change video process for another path */
+               switch (cur_source_format[oth_path]) {
+               case HDRTYPE_HDR10PLUS:
+                       cur_hdr10_plus_process_mode[oth_path] =
+                               PROC_OFF;
+                       break;
+               case HDRTYPE_HDR10:
+                       cur_hdr_process_mode[oth_path] = PROC_OFF;
+                       break;
+               case HDRTYPE_HLG:
+                       cur_hlg_process_mode[oth_path] = PROC_OFF;
+                       break;
+               case HDRTYPE_SDR:
+                       cur_sdr_process_mode[oth_path] = PROC_OFF;
+                       break;
+               default:
+                       break;
+               }
+       }
+       return change_flag;
+}
+
+static void prepare_hdr_info(
+       struct master_display_info_s *hdr_data,
+       struct vframe_master_display_colour_s *p)
+{
+       memset(hdr_data->primaries, 0, sizeof(hdr_data->primaries));
+       if ((p->present_flag & 1)
+       && (((hdr_data->features >> 16) & 0xff) == 9)) {
+               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;
+               }
+               hdr_data->luminance[0] = hdr_data->luminance[0] / 10000;
+               hdr_data->present_flag = 1;
+       }
+}
+
+void hdmi_packet_process(
+       int signal_change_flag,
+       struct vinfo_s *vinfo,
+       struct vframe_master_display_colour_s *p,
+       struct hdr10plus_para *hdmitx_hdr10plus_param,
+       enum vd_path_e vd_path)
+{
+       struct vout_device_s *vdev = NULL;
+       struct master_display_info_s send_info;
+       enum output_format_e cur_output_format = output_format;
+
+       if (!vinfo)
+               return;
+       if (!vinfo->vout_device) {
+               pr_info("vinfo->vout_device is null, return\n");
+               return;
+       }
+       vdev = vinfo->vout_device;
+       if (!vdev->fresh_tx_hdr_pkt) {
+               pr_info("vdev->fresh_tx_hdr_pkt is null, return\n");
+               /* continue */
+       }
+
+       if ((target_format[vd_path] == cur_output_format)
+       && (cur_output_format != BT2020_PQ_DYNAMIC)
+       && ((cur_output_format == BT2020_PQ) &&
+       !(signal_change_flag & SIG_PRI_INFO)))
+               return;
+
+       /* clean hdr10plus packet when switch to others */
+       if ((target_format[vd_path] != BT2020_PQ_DYNAMIC)
+       && (cur_output_format == BT2020_PQ_DYNAMIC)) {
+               if (get_hdr10_plus_pkt_delay()) {
+                       update_hdr10_plus_pkt(false,
+                               (void *)NULL,
+                               (void *)NULL);
+               } else if (vdev->fresh_tx_hdr10plus_pkt)
+                       vdev->fresh_tx_hdr10plus_pkt(0,
+                               hdmitx_hdr10plus_param);
+               pr_csc(4, "am_vecm: vd%d hdmi clean hdr10+ pkt\n",
+                       vd_path + 1);
+       }
+
+       if (output_format != target_format[vd_path]) {
+               pr_csc(4,
+                       "am_vecm: vd%d %s %s, vd2 %s %s, output_format %s => %s\n",
+                       vd_path + 1,
+                       is_video_layer_on(VD1_PATH) ? "on" : "off",
+                       output_str[target_format[VD1_PATH]],
+                       is_video_layer_on(VD2_PATH) ? "on" : "off",
+                       output_str[target_format[VD2_PATH]],
+                       output_str[cur_output_format],
+                       output_str[target_format[vd_path]]);
+               output_format = target_format[vd_path];
+       }
+
+       switch (output_format) {
+       case BT709:
+               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 */
+               break;
+       case BT2020:
+               send_info.features =
+                       /* default 709 full */
+                       (1 << 30) /*sdr output 709*/
+                       | (1 << 29) /*video available*/
+                       | (5 << 26) /* unspecified */
+                       | (0 << 25) /* limit */
+                       | (1 << 24) /*color available*/
+                       | (9 << 16) /* 2020 */
+                       | (1 << 8)      /* bt709 */
+                       | (10 << 0);
+               break;
+       case BT2020_PQ:
+               send_info.features =
+                       (0 << 30) /*sdr output 709*/
+                       | (1 << 29)     /*video available*/
+                       | (5 << 26)     /* unspecified */
+                       | (0 << 25)     /* limit */
+                       | (1 << 24)     /*color available*/
+                       | (9 << 16)
+                       | (16 << 8)
+                       | (10 << 0);    /* bt2020c */
+               break;
+       case BT2020_HLG:
+               send_info.features =
+                       (0 << 30) /*sdr output 709*/
+                       | (1 << 29)     /*video available*/
+                       | (5 << 26)     /* unspecified */
+                       | (0 << 25)     /* limit */
+                       | (1 << 24)     /*color available*/
+                       | (9 << 16)
+                       | (18 << 8)
+                       | (10 << 0);
+               break;
+       case BT2020_PQ_DYNAMIC:
+               send_info.features =
+                       (0 << 30) /*sdr output 709*/
+                       | (1 << 29)     /*video available*/
+                       | (5 << 26)     /* unspecified */
+                       | (0 << 25)     /* limit */
+                       | (1 << 24)     /*color available*/
+                       | (9 << 16)
+                       | (16 << 8)  /* Always HDR10 */
+                       | (10 << 0); /* bt2020c */
+               break;
+       case UNKNOWN_FMT:
+       case BT2100_IPT:
+               /* handle by dolby vision */
+               return;
+       }
+
+       /* drm */
+       prepare_hdr_info(&send_info, p);
+
+       /* hdr10+ */
+       if ((output_format == BT2020_PQ_DYNAMIC)
+       && hdmitx_hdr10plus_param) {
+               if (get_hdr10_plus_pkt_delay()) {
+                       update_hdr10_plus_pkt(true,
+                               (void *)hdmitx_hdr10plus_param,
+                               (void *)&send_info);
+               } else {
+                       if (vdev->fresh_tx_hdr_pkt)
+                               vdev->fresh_tx_hdr_pkt(&send_info);
+                       if (vdev->fresh_tx_hdr10plus_pkt)
+                               vdev->fresh_tx_hdr10plus_pkt(
+                                       1, hdmitx_hdr10plus_param);
+               }
+               return;
+       }
+       /* none hdr+ */
+       if (vdev->fresh_tx_hdr_pkt)
+               vdev->fresh_tx_hdr_pkt(&send_info);
+}
+
+void video_post_process(
+       enum vpp_matrix_csc_e csc_type,
+       struct vinfo_s *vinfo,
+       enum vd_path_e vd_path)
+{
+       switch (cur_source_format[vd_path]) {
+       case HDRTYPE_SDR:
+               if (vd_path == VD2_PATH && is_dolby_vision_on()) {
+                       hdr_proc(VD2_HDR, SDR_IPT, vinfo);
+               } else if (sdr_process_mode[vd_path] == PROC_BYPASS) {
+                       if (vd_path == VD1_PATH)
+                               hdr_proc(VD1_HDR, HDR_BYPASS, vinfo);
+                       else
+                               hdr_proc(VD2_HDR, HDR_BYPASS, vinfo);
+                       if (((vd_path == VD1_PATH) &&
+                       !is_video_layer_on(VD2_PATH))
+                       || ((vd_path == VD2_PATH) &&
+                       !is_video_layer_on(VD1_PATH)))
+                               hdr_proc(OSD1_HDR, HDR_BYPASS, vinfo);
+               } else if (sdr_process_mode[vd_path] == PROC_SDR_TO_HDR) {
+                       if (vd_path == VD1_PATH)
+                               hdr_proc(VD1_HDR, SDR_HDR, vinfo);
+                       else
+                               hdr_proc(VD2_HDR, SDR_HDR, vinfo);
+                       hdr_proc(OSD1_HDR, SDR_HDR, vinfo);
+               } else if (sdr_process_mode[vd_path] == PROC_SDR_TO_HLG) {
+                       if (vd_path == VD1_PATH)
+                               hdr_proc(VD1_HDR, SDR_HLG, vinfo);
+                       else if (vd_path == VD2_PATH)
+                               hdr_proc(VD2_HDR, SDR_HLG, vinfo);
+                       hdr_proc(OSD1_HDR, SDR_HLG, vinfo);
+               }
+               break;
+       case HDRTYPE_HDR10:
+               if (vd_path == VD2_PATH && is_dolby_vision_on()) {
+                       hdr_proc(VD2_HDR, HDR_IPT, vinfo);
+               } else if (hdr_process_mode[vd_path] == PROC_BYPASS) {
+                       if (vd_path == VD1_PATH)
+                               hdr_proc(VD1_HDR, HDR_BYPASS, vinfo);
+                       else
+                               hdr_proc(VD2_HDR, HDR_BYPASS, vinfo);
+                       hdr_proc(OSD1_HDR, SDR_HDR, vinfo);
+               } else if (hdr_process_mode[vd_path] == PROC_HDR_TO_SDR) {
+                       if (vd_path == VD1_PATH)
+                               hdr_proc(VD1_HDR, HDR_SDR, vinfo);
+                       else
+                               hdr_proc(VD2_HDR, HDR_SDR, vinfo);
+                       hdr_proc(OSD1_HDR, HDR_BYPASS, vinfo);
+               } else if (hdr_process_mode[vd_path] == PROC_HDR_TO_HLG) {
+                       if (vd_path == VD1_PATH)
+                               hdr_proc(VD1_HDR, HDR_HLG, vinfo);
+                       else
+                               hdr_proc(VD2_HDR, HDR_HLG, vinfo);
+                       hdr_proc(OSD1_HDR, SDR_HLG, vinfo);
+               }
+               break;
+       case HDRTYPE_HLG:
+               if (vd_path == VD2_PATH && is_dolby_vision_on()) {
+                       hdr_proc(VD2_HDR, HLG_IPT, vinfo);
+               } else if (hlg_process_mode[vd_path] == PROC_BYPASS) {
+                       if (vd_path == VD1_PATH)
+                               hdr_proc(VD1_HDR, HDR_BYPASS, vinfo);
+                       else
+                               hdr_proc(VD2_HDR, HDR_BYPASS, vinfo);
+                       hdr_proc(OSD1_HDR, SDR_HLG, vinfo);
+               } else if (hlg_process_mode[vd_path] == PROC_HLG_TO_SDR) {
+                       if (vd_path == VD1_PATH)
+                               hdr_proc(VD1_HDR, HLG_SDR, vinfo);
+                       else
+                               hdr_proc(VD2_HDR, HLG_SDR, vinfo);
+                       hdr_proc(OSD1_HDR, HDR_BYPASS, vinfo);
+               } else if (hlg_process_mode[vd_path] == PROC_HLG_TO_HDR) {
+                       if (vd_path == VD1_PATH)
+                               hdr_proc(VD1_HDR, HLG_HDR, vinfo);
+                       else
+                               hdr_proc(VD2_HDR, HLG_HDR, vinfo);
+                       hdr_proc(OSD1_HDR, SDR_HDR, vinfo);
+               }
+
+               break;
+       case HDRTYPE_HDR10PLUS:
+               if ((vd_path == VD2_PATH) && is_dolby_vision_on()) {
+                       hdr_proc(VD2_HDR, HDR_IPT, vinfo);
+               } else if (hdr10_plus_process_mode[vd_path] ==
+               PROC_BYPASS) {
+                       if (vd_path == VD1_PATH)
+                               hdr_proc(VD1_HDR, HDR_BYPASS, vinfo);
+                       else
+                               hdr_proc(VD2_HDR, HDR_BYPASS, vinfo);
+                       hdr_proc(OSD1_HDR, SDR_HDR, vinfo);
+               } else if (hdr10_plus_process_mode[vd_path] ==
+               PROC_HDRP_TO_HDR) {
+                       if (vd_path == VD1_PATH)
+                               hdr_proc(VD1_HDR, HDR_BYPASS, vinfo);
+                       else
+                               hdr_proc(VD2_HDR, HDR_BYPASS, vinfo);
+                       hdr_proc(OSD1_HDR, SDR_HDR, vinfo);
+               } else if (hdr10_plus_process_mode[vd_path] ==
+               PROC_HDRP_TO_SDR) {
+                       if (vd_path == VD1_PATH)
+                               hdr_proc(VD1_HDR, HDR_SDR, vinfo);
+                       else
+                               hdr_proc(VD2_HDR, HDR_SDR, vinfo);
+                       hdr_proc(OSD1_HDR, HDR_BYPASS, vinfo);
+               } else if (hdr10_plus_process_mode[vd_path] ==
+               PROC_HDRP_TO_HLG) {
+                       if (vd_path == VD1_PATH)
+                               hdr_proc(VD1_HDR, HDR_HLG, vinfo);
+                       else
+                               hdr_proc(VD2_HDR, HDR_HLG, vinfo);
+                       hdr_proc(OSD1_HDR, SDR_HLG, vinfo);
+               }
+
+               break;
+       default:
+               break;
+       }
+
+       if (cur_sdr_process_mode[vd_path] !=
+               sdr_process_mode[vd_path]) {
+               if (cur_source_format[vd_path] == HDRTYPE_SDR)
+                       pr_csc(1,
+                               "am_vecm: vd%d: sdr_process_mode %d to %d\n",
+                               vd_path + 1,
+                               cur_sdr_process_mode[vd_path],
+                               sdr_process_mode[vd_path]);
+               cur_sdr_process_mode[vd_path] =
+                       sdr_process_mode[vd_path];
+       }
+       if (cur_hdr_process_mode[vd_path] !=
+               hdr_process_mode[vd_path]) {
+               if (cur_source_format[vd_path] == HDRTYPE_HDR10)
+                       pr_csc(1,
+                               "am_vecm: vd%d: hdr_process_mode %d to %d\n",
+                               vd_path + 1,
+                               cur_hdr_process_mode[vd_path],
+                               hdr_process_mode[vd_path]);
+               cur_hdr_process_mode[vd_path] =
+                       hdr_process_mode[vd_path];
+       }
+       if (cur_hlg_process_mode[vd_path] !=
+               hlg_process_mode[vd_path]) {
+               if (cur_source_format[vd_path] == HDRTYPE_HLG)
+                       pr_csc(1,
+                               "am_vecm: vd%d: hlg_process_mode %d to %d\n",
+                               vd_path + 1,
+                               cur_hlg_process_mode[vd_path],
+                               hlg_process_mode[vd_path]);
+               cur_hlg_process_mode[vd_path] =
+                       hlg_process_mode[vd_path];
+       }
+       if (cur_hdr10_plus_process_mode[vd_path] !=
+               hdr10_plus_process_mode[vd_path]) {
+               if (cur_source_format[vd_path] == HDRTYPE_HDR10PLUS)
+                       pr_csc(1,
+                               "am_vecm: vd%d: hdr10_plus_process_mode %d to %d\n",
+                               vd_path + 1,
+                               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];
+       }
+       if (cur_csc_type[vd_path] != csc_type) {
+               pr_csc(1, "am_vecm: vd%d: csc from 0x%x to 0x%x.\n",
+                       vd_path + 1, cur_csc_type[vd_path], csc_type);
+               cur_csc_type[vd_path] = csc_type;
+       }
+}
diff --git a/drivers/amlogic/media/enhancement/amvecm/amcsc_pip.h b/drivers/amlogic/media/enhancement/amvecm/amcsc_pip.h
new file mode 100644 (file)
index 0000000..84887f8
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * drivers/amlogic/media/enhancement/amvecm/amcsc_pip.h
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef AM_CSC_PIP_H
+#define AM_CSC_PIP_H
+extern int hdr_policy_process(
+       struct vinfo_s *vinfo,
+       enum hdr_type_e *source_format,
+       enum vd_path_e vd_path);
+extern void hdmi_packet_process(
+       int signal_change_flag,
+       struct vinfo_s *vinfo,
+       struct vframe_master_display_colour_s *p,
+       struct hdr10plus_para *hdmitx_hdr10plus_param,
+       enum vd_path_e vd_path);
+extern void video_post_process(
+       enum vpp_matrix_csc_e csc_type,
+       struct vinfo_s *vinfo,
+       enum vd_path_e vd_path);
+#endif
index 194a037..8b6c2d5 100644 (file)
@@ -183,7 +183,7 @@ unsigned int debug_game_mode_1;
 module_param(debug_game_mode_1, uint, 0664);
 MODULE_PARM_DESC(debug_game_mode_1, "\n debug_game_mode_1\n");
 unsigned int pq_user_value;
-enum hdr_type_e hdr_source_type = HDRTYPE_SDR;
+enum hdr_type_e hdr_source_type = HDRTYPE_NONE;
 
 #define SR0_OFFSET 0xc00
 #define SR1_OFFSET 0xc80
@@ -1078,44 +1078,59 @@ int amvecm_on_vs(
        unsigned int sps_w_in,
        unsigned int sps_h_in,
        unsigned int cm_in_w,
-       unsigned int cm_in_h)
+       unsigned int cm_in_h,
+       enum vd_path_e vd_path)
 {
        int result = 0;
 
        if (probe_ok == 0)
                return 0;
 #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
-       if (for_dolby_vision_certification())
+       if (for_dolby_vision_certification() && (vd_path == VD1_PATH))
                return 0;
 #endif
-       if (!dnlp_insmod_ok)
+       if (!dnlp_insmod_ok && vd_path == VD1_PATH)
                dnlp_alg_param_init();
+
        if (flags & CSC_FLAG_CHECK_OUTPUT) {
-               if (toggle_vf)
-                       amvecm_fresh_overscan(toggle_vf);
-               else if (vf)
-                       amvecm_fresh_overscan(vf);
+               if (vd_path == VD1_PATH) {
+                       if (toggle_vf)
+                               amvecm_fresh_overscan(toggle_vf);
+                       else if (vf)
+                               amvecm_fresh_overscan(vf);
+               }
                /* to test if output will change */
                return amvecm_matrix_process(
-                       toggle_vf, vf, flags);
-       }
+                       toggle_vf, vf, flags, vd_path);
+       } else if (vd_path == VD1_PATH)
+               send_hdr10_plus_pkt(vd_path);
        if ((toggle_vf != NULL) || (vf != NULL)) {
                /* matrix adjust */
-               result = amvecm_matrix_process(toggle_vf, vf, flags);
-               if (toggle_vf) {
+               result = amvecm_matrix_process(
+                       toggle_vf, vf, flags, vd_path);
+               if (toggle_vf)
                        ioctrl_get_hdr_metadata(toggle_vf);
+
+               if (toggle_vf && vd_path == VD1_PATH) {
                        lc_process(toggle_vf, sps_h_en, sps_v_en,
                                sps_w_in, sps_h_in);
                        amvecm_size_patch(cm_in_w, cm_in_h);
                }
        } else {
-               amvecm_reset_overscan();
-               result = amvecm_matrix_process(NULL, NULL, flags);
-               ve_hist_gamma_reset();
-               lc_process(NULL, sps_h_en, sps_v_en,
-                       sps_w_in, sps_h_in);
+               if (vd_path == VD1_PATH)
+                       amvecm_reset_overscan();
+               result = amvecm_matrix_process(
+                       NULL, NULL, flags, vd_path);
+               if (vd_path == VD1_PATH) {
+                       ve_hist_gamma_reset();
+                       lc_process(NULL, sps_h_en, sps_v_en,
+                               sps_w_in, sps_h_in);
+               }
        }
 
+       if (vd_path != VD1_PATH)
+               return result;
+
        if (!is_dolby_vision_on())
                get_hdr_source_type();
 
@@ -1617,7 +1632,8 @@ static long amvecm_ioctl(struct file *file,
        case AMVECM_IOC_G_CSCTYPE:
                argp = (void __user *)arg;
                if (copy_to_user(argp,
-                               &cur_csc_type, sizeof(enum vpp_matrix_csc_e)))
+                               &cur_csc_type[VD1_PATH],
+                               sizeof(enum vpp_matrix_csc_e)))
                        ret = -EFAULT;
                break;
        case AMVECM_IOC_G_COLOR_PRI:
@@ -1628,7 +1644,7 @@ static long amvecm_ioctl(struct file *file,
                        ret = -EFAULT;
                break;
        case AMVECM_IOC_S_CSCTYPE:
-               if (copy_from_user(&cur_csc_type,
+               if (copy_from_user(&cur_csc_type[VD1_PATH],
                                (void __user *)arg,
                                sizeof(enum vpp_matrix_csc_e))) {
                        ret = -EFAULT;
@@ -6781,7 +6797,7 @@ static int aml_vecm_probe(struct platform_device *pdev)
        if (is_meson_gxl_cpu() || is_meson_gxm_cpu())
                hdr_flag = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3);
        else
-               hdr_flag = (1 << 0) | (1 << 1) | (0 << 2) | (0 << 3);
+               hdr_flag = (1 << 0) | (1 << 1) | (0 << 2) | (0 << 3) | (1 << 4);
 
        hdr_init(&amvecm_dev.hdr_d);
        aml_vecm_dt_parse(pdev);
index de81b10..5976b9e 100644 (file)
@@ -638,6 +638,7 @@ void hdr10_plus_hdmitx_vsif_parser(
        int i;
        int kpx, kpy;
        int bz_cur_anchors[9];
+       u32 maxrgb_99_percentiles = 0;
 
        memset(hdmitx_hdr10plus_param, 0, sizeof(struct hdr10plus_para));
 
@@ -702,7 +703,9 @@ void hdr10_plus_hdmitx_vsif_parser(
        hdmitx_hdr10plus_param->average_maxrgb = (u8)ave_maxrgb;
 
        for (i = 0; i < 9; i++) {
-               if (i == 2) {
+               if ((i == 2) &&
+                       /* V0 sei update */
+                       (hdmitx_hdr10plus_param->application_version != 0)) {
                        distribution_values[i] =
                        hdr_plus_sei.distribution_maxrgb_percentiles[0][i];
                        hdmitx_hdr10plus_param->distribution_values[i] =
@@ -711,6 +714,14 @@ void hdr10_plus_hdmitx_vsif_parser(
                }
                distribution_values[i] =
                        hdr_plus_sei.distribution_maxrgb_percentiles[0][i] / 10;
+               /* V0 sei update */
+               if ((hdr_plus_sei.num_distribution_maxrgb_percentiles[0] == 10)
+                       && (hdmitx_hdr10plus_param->application_version == 0)
+                       && (i == 8)) {
+                       maxrgb_99_percentiles =
+                       hdr_plus_sei.distribution_maxrgb_percentiles[0][i + 1];
+                       distribution_values[i] = maxrgb_99_percentiles / 10;
+               }
                if (distribution_values[i] < (1 << 12)) {
                        distribution_values[i] =
                                (distribution_values[i] + (1 << 3)) >> 4;
@@ -763,7 +774,7 @@ void hdr10_plus_hdmitx_vsif_parser(
        /*only video, don't include graphic*/
        hdmitx_hdr10plus_param->graphics_overlay_flag = 0;
        /*metadata and video have no delay*/
-       hdmitx_hdr10plus_param->no_delay_flag = 0;
+       hdmitx_hdr10plus_param->no_delay_flag = 1;
 
        memcpy(&dbg_hdr10plus_pkt, hdmitx_hdr10plus_param,
                sizeof(struct hdr10plus_para));
index b5cd1f0..b39bdf0 100644 (file)
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/amlogic/media/amvecm/amvecm.h>
+#include <linux/amlogic/media/amdolbyvision/dolby_vision.h>
 #include "set_hdr2_v0.h"
 #include "arch/vpp_hdr_regs.h"
 #include "arch/vpp_regs.h"
+#include "arch/vpp_dolbyvision_regs.h"
 
 //#define HDR2_MODULE
 //#define HDR2_PRINT
@@ -115,6 +117,27 @@ int eo_y_lut_hdr[143] = {
 module_param_array(eo_y_lut_hdr, int, &num_eo_y_lut_hdr, 0664);
 MODULE_PARM_DESC(eo_y_lut_hdr, "\n eo_y_lut_hdr\n");
 
+int eo_y_lut_pq[143] = {
+       59392, 66560, 94208, 110592, 121984, 132160, 138816, 146432,
+       151264, 156096, 161440, 165568, 168768, 172224, 175952, 179968,
+       182240, 200680, 215102, 226400, 235271, 244625, 250984, 258029,
+       264312, 269323, 275208, 280295, 284260, 288817, 294028, 297434,
+       300794, 304586, 308851, 312465, 315139, 318120, 321437, 325119,
+       328439, 330693, 333181, 335922, 338938, 342251, 344974, 346965,
+       349143, 351524, 354124, 356960, 360050, 361931, 363762, 365751,
+       367912, 370258, 372802, 375559, 377689, 379306, 381056, 382948,
+       384994, 387204, 389591, 392167, 394081, 395581, 397197, 398940,
+       400818, 402840, 405018, 407363, 409743, 411100, 412561, 414132,
+       415820, 417636, 419588, 421685, 423939, 426172, 427472, 428869,
+       430370, 431980, 433710, 435567, 437561, 439701, 441999, 443416,
+       444740, 446160, 447685, 449321, 451078, 452962, 454986, 457157,
+       459120, 460370, 461713, 463154, 464701, 466363, 468146, 470061,
+       472118, 474326, 475917, 477191, 478560, 480031, 481611, 483309,
+       485135, 487098, 489208, 491477, 492719, 494032, 495444, 496965,
+       498601, 500363, 502261, 504304, 506506, 508391, 509670, 511049,
+       512536, 514140, 515870, 517739, 519756, 521934, 524287
+};
+
 int eo_y_lut_hlg[143] = {
        0, 169296, 202068, 221184, 234837, 246442, 253952, 262485, 267605,
        273408, 279210, 282794, 286720, 290986, 295253, 297728, 300373, 319488,
@@ -230,19 +253,21 @@ static int oe_y_lut_bypass[149] = {
 };
 
 int oo_y_lut_hdr_hlg[149] = {
-       4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095,
-       4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095,
-       4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095,
-       3917, 3776, 3662, 3565, 3410, 3288, 3188, 3104, 2968, 2862, 2775,
-       2702, 2639, 2584, 2535, 2491, 2452, 2416, 2383, 2352, 2297, 2249,
-       2207, 2169, 2134, 2103, 2074, 2047, 2000, 1958, 1921, 1888, 1858,
-       1831, 1806, 1782, 1741, 1705, 1672, 1644, 1617, 1594, 1572, 1552,
-       1515, 1484, 1456, 1431, 1408, 1387, 1368, 1351, 1319, 1292, 1267,
-       1245, 1226, 1208, 1191, 1176, 1148, 1124, 1103, 1084, 1067, 1051,
-       1037, 1023, 1000, 979, 960, 944, 929, 915, 903, 891, 870, 852,
-       836, 822, 808, 797, 786, 776, 757, 742, 728, 715, 704, 693, 684,
-       675, 659, 646, 633, 622, 613, 604, 595, 588, 581, 574, 568, 562,
-       557, 551, 546, 542, 537, 533, 529, 525, 522, 518, 515, 512
+       4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095,
+       4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095,
+       4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095,
+       4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095,
+       4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095,
+       4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095,
+       4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095,
+       4095, 4095, 4095, 4095, 4095, 4095, 3983, 3703, 3469, 3270,
+       3098, 2948, 2816, 2698, 2592, 2409, 2257, 2127, 2016, 1918,
+       1832, 1755, 1686, 1567, 1468, 1384, 1311, 1248, 1192, 1142,
+       1097, 1020, 955, 900, 853, 812, 775, 743, 714, 663,
+       621, 586, 555, 528, 504, 483, 464, 431, 404, 381,
+       361, 343, 328, 314, 302, 281, 263, 248, 235, 223,
+       213, 204, 196, 189, 182, 176, 171, 166, 161, 157,
+       152, 149, 145, 142, 139, 136, 133, 130, 128
 };
 
 static int num_hdr_sdr_lut = 149;
@@ -265,96 +290,180 @@ module_param_array(oo_y_lut_hdr_sdr, int, &num_hdr_sdr_lut, 0664);
 MODULE_PARM_DESC(oo_y_lut_hdr_sdr, "\n num_hdr_sdr_lut\n");
 
 int oo_y_lut_bypass[149] = {
-       255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-       255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-       255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-       255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-       255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-       255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-       255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-       255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-       255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-       255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-       255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-       255, 255, 255, 255, 255, 255
+       512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512,
+       512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512,
+       512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512,
+       512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512,
+       512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512,
+       512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512,
+       512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512,
+       512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512,
+       512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512,
+       512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512,
+       512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512,
+       512, 512, 512, 512, 512, 512
+};
+
+/* HDR map to 4000 gain=512*4000/10000, 512 as 1.0 */
+int oo_y_lut_hdr_hdr_4000[149] = {
+       205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205,
+       205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205,
+       205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205,
+       205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205,
+       205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205,
+       205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205,
+       205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205,
+       205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205,
+       205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205,
+       205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205,
+       205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205,
+       205, 205, 205, 205, 205, 205
+};
+
+/* HDR map to 2500 gain=512*2500/10000, 512 as 1.0 */
+int oo_y_lut_hdr_hdr_2500[149] = {
+       128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+       128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+       128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+       128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+       128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+       128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+       128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+       128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+       128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+       128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+       128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+       128, 128, 128, 128, 128, 128
+};
+
+/* HDR map to 1200 gain=512*1200/10000, 512 as 1.0 */
+int oo_y_lut_hdr_hdr_1200[149] = {
+       61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
+       61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
+       61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
+       61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
+       61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
+       61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
+       61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
+       61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
+       61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
+       61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
+       61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
+       61, 61, 61, 61, 61, 61
 };
 
 int oo_y_lut_hlg_hdr[149] = {
-       4, 8, 9, 11, 12, 14, 16, 19, 22, 23, 24, 24, 25, 26, 27, 28, 29,
-       30, 31, 32, 33, 35, 36, 37, 38, 40, 42, 43, 44, 46, 48, 49, 51,
-       53, 55, 57, 58, 61, 63, 65, 67, 70, 73, 75, 77, 79, 81, 82, 84,
-       85, 86, 88, 89, 91, 93, 95, 96, 98, 99, 101, 102, 104, 107, 109,
-       111, 112, 114, 116, 117, 120, 122, 125, 127, 129, 131, 133, 135,
-       138, 141, 144, 146, 148, 151, 153, 155, 158, 162, 165, 168, 171,
-       173, 176, 178, 182, 186, 190, 193, 196, 199, 202, 204, 209, 214,
-       218, 222, 225, 229, 232, 235, 240, 245, 250, 255, 259, 263, 266,
-       270, 276, 282, 288, 293, 297, 302, 306, 310, 317, 324, 330, 336,
-       342, 347, 352, 356, 360, 365, 369, 372, 376, 380, 383, 386, 389,
-       392, 395, 398, 401, 404, 407, 409
+       6, 10, 12, 13, 16, 18, 21, 24, 27, 29,
+       30, 31, 32, 33, 34, 35, 36, 38, 39, 41,
+       42, 44, 45, 47, 48, 50, 52, 54, 55, 58,
+       60, 62, 64, 66, 69, 71, 73, 76, 79, 82,
+       84, 88, 91, 94, 97, 99, 101, 103, 105, 106,
+       108, 110, 111, 114, 116, 118, 120, 122, 124, 126,
+       128, 131, 133, 136, 138, 141, 143, 145, 147, 150,
+       153, 156, 159, 162, 164, 166, 168, 172, 176, 180,
+       183, 186, 188, 191, 194, 198, 202, 206, 210, 213,
+       216, 220, 222, 228, 233, 237, 241, 245, 249, 252,
+       256, 262, 267, 272, 277, 282, 286, 290, 294, 301,
+       307, 313, 318, 324, 328, 333, 337, 345, 353, 360,
+       366, 372, 377, 383, 388, 397, 405, 413, 420, 427,
+       433, 440, 445, 451, 456, 461, 466, 470, 475, 479,
+       483, 487, 491, 494, 498, 502, 505, 508, 512
 };
 
+/* SDR convert to 625 gain=512*625/10000 lumin HDR, 512 as 1.0 */
 static int num_sdr_hdr_lut = 149;
 int oo_y_lut_sdr_hdr[149] = {
-       38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
-       38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
-       38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
-       38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
-       38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
-       38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
-       38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
-       38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
-       38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
-       38, 38, 38, 38, 38
+       32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+       32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+       32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+       32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+       32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+       32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+       32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+       32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+       32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+       32, 32, 32, 32, 32
 };
 module_param_array(oo_y_lut_sdr_hdr, int, &num_sdr_hdr_lut, 0664);
 MODULE_PARM_DESC(oo_y_lut_sdr_hdr, "\n num_sdr_hdr_lut\n");
 
-int oo_y_lut_hlg_sdr[149] = {
-       245, 269, 275, 282, 288, 295, 302, 309, 316, 318, 320, 322, 323,
-       326, 327, 329, 331, 333, 335, 337, 338, 341, 343, 345, 346, 349,
-       351, 353, 354, 357, 359, 361, 362, 365, 367, 369, 371, 373, 376,
-       378, 379, 382, 384, 386, 388, 390, 391, 392, 393, 394, 395, 396,
-       397, 399, 400, 401, 402, 403, 404, 405, 406, 408, 409, 410, 412,
-       413, 414, 415, 416, 417, 419, 420, 421, 422, 423, 424, 425, 427,
-       428, 430, 431, 432, 433, 434, 435, 437, 438, 440, 441, 442, 443,
-       444, 445, 447, 448, 450, 451, 452, 453, 454, 455, 457, 459, 460,
-       462, 463, 464, 465, 466, 468, 469, 471, 472, 473, 475, 476, 477,
-       479, 480, 482, 483, 484, 486, 487, 488, 490, 491, 493, 494, 496,
-       497, 498, 499, 500, 501, 502, 503, 503, 504, 505, 506, 506, 507,
-       508, 508, 509, 509, 510, 510
+
+/* SDR convert to 100 gain=512*100/10000 lumin HDR, 512 as 1.0 */
+int oo_y_lut_sdr_hdr_100[149] = {
+       5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+       5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+       5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+       5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+       5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+       5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+       5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+       5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+       5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+       5, 5, 5, 5, 5
 };
 
-int oo_y_lut_sdr_hlg[149] = {
-       1060, 967, 946, 924, 903, 883, 863, 844, 825, 819, 814, 810, 806,
-       800, 795, 791, 788, 782, 777, 773, 770, 764, 760, 756, 753,
-       747, 743, 739, 736, 730, 726, 722, 719, 714, 710, 706, 703,
-       698, 694, 690, 687, 682, 678, 674, 671, 669, 667, 664, 663,
-       661, 659, 658, 656, 654, 651, 649, 648, 646, 644, 643, 641,
-       639, 637, 635, 633, 631, 630, 628, 627, 625, 622, 620, 619,
-       617, 616, 614, 613, 610, 608, 606, 605, 603, 602, 600, 599,
-       597, 595, 593, 591, 590, 588, 587, 585, 583, 581, 579, 578,
-       576, 575, 573, 572, 570, 568, 566, 565, 563, 562, 561, 559,
-       557, 555, 554, 552, 550, 549, 548, 547, 545, 543, 541, 539,
-       538, 537, 536, 534, 532, 530, 529, 527, 526, 525, 523, 522,
-       521, 520, 519, 518, 518, 517, 516, 515, 515, 514, 513, 513,
-       512, 512, 511, 511
+/* SDR convert to 250 gain=512*250/12000 lumin HDR, 512 as 1.0 */
+int oo_y_lut_sdr_hdr_250[149] = {
+       12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+       12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+       12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+       12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+       12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+       12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+       12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+       12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+       12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+       12, 12, 12, 12, 12
+};
+
+/* SDR convert to 310 gain=512*310/10000 lumin HDR, 512 as 1.0 */
+int oo_y_lut_sdr_hdr_300[149] = {
+       16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+       16, 16, 16, 16, 16
+};
+
+int oo_y_lut_hlg_sdr[149] = {
+       790, 749, 739, 729, 719, 709, 699, 690, 681, 678,
+       675, 673, 671, 669, 666, 664, 662, 659, 657, 655,
+       653, 651, 648, 646, 645, 642, 639, 638, 636, 633,
+       631, 629, 627, 625, 622, 620, 619, 616, 614, 612,
+       610, 608, 606, 604, 602, 601, 600, 598, 597, 596,
+       596, 595, 594, 593, 591, 590, 589, 588, 588, 587,
+       586, 585, 583, 582, 581, 580, 580, 579, 578, 577,
+       576, 575, 574, 573, 572, 571, 570, 569, 568, 567,
+       566, 565, 564, 563, 563, 561, 560, 559, 558, 557,
+       556, 556, 555, 554, 553, 552, 551, 550, 549, 548,
+       548, 546, 545, 544, 543, 542, 542, 541, 540, 539,
+       538, 537, 536, 535, 534, 533, 533, 532, 530, 529,
+       529, 528, 527, 526, 526, 524, 523, 522, 521, 521,
+       520, 519, 519, 518, 517, 517, 516, 516, 515, 515,
+       514, 514, 514, 513, 513, 512, 512, 512, 512
 };
 
-int oo_y_lut_1[149] = {
-       4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095,
-       4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095,
-       4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095,
-       4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095,
-       4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095,
-       4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095,
-       4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095,
-       4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095,
-       4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095,
-       4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095,
-       4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095,
-       4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095,
-       4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095, 4095,
-       4095, 4095, 4095, 4095, 4095, 4095
+int oo_y_lut_sdr_hlg[149] = {
+       331, 349, 354, 359, 364, 369, 374, 379, 384, 386,
+       387, 389, 390, 391, 393, 394, 395, 397, 398, 399,
+       400, 402, 404, 405, 406, 408, 409, 410, 411, 413,
+       415, 416, 417, 419, 420, 422, 423, 425, 426, 427,
+       429, 430, 432, 433, 434, 435, 436, 437, 438, 439,
+       439, 440, 440, 441, 442, 443, 444, 445, 445, 446,
+       446, 447, 448, 449, 450, 451, 451, 452, 453, 454,
+       455, 455, 456, 457, 458, 458, 459, 460, 461, 462,
+       462, 463, 464, 464, 465, 466, 467, 468, 469, 469,
+       470, 471, 471, 472, 473, 474, 475, 476, 477, 477,
+       478, 479, 480, 481, 482, 482, 483, 484, 484, 486,
+       487, 487, 488, 489, 490, 490, 491, 492, 493, 494,
+       495, 496, 496, 497, 498, 499, 500, 501, 502, 503,
+       503, 504, 505, 505, 506, 506, 507, 507, 508, 508,
+       509, 509, 509, 510, 510, 511, 511, 511, 512
 };
 
 #else //HDR2_MODULE
@@ -692,9 +801,14 @@ static uint in_luma = 1;/*1 as 100luminance*/
 module_param(in_luma, uint, 0664);
 MODULE_PARM_DESC(in_luma, "\n in_luma\n");
 
-static uint adp_scal_shift = 10;/*1 as 100luminance*/
-module_param(adp_scal_shift, uint, 0664);
-MODULE_PARM_DESC(adp_scal_shift, "\n adp_scal_shift\n");
+static uint adp_scal_y_shift = 10; /* 1.0 =1024 */
+module_param(adp_scal_y_shift, uint, 0664);
+MODULE_PARM_DESC(adp_scal_y_shift, "\n adp_scal_y_shift\n");
+
+#define X_SHFT 10
+static uint adp_scal_x_shift = X_SHFT; /* 1.0 = 1024 */
+module_param(adp_scal_x_shift, uint, 0664);
+MODULE_PARM_DESC(adp_scal_x_shift, "\n adp_scal_x_shift\n");
 
 static uint alpha_oe_a = 0x1;
 module_param(alpha_oe_a, uint, 0664);
@@ -719,18 +833,45 @@ int ncl_2020_709[9] = {
 /* standard2020->dcip3-d65 8bit*/
 int ncl_2020_p3[9] = {
        368, -96, -16, -16, 275, -3, 1, -8, 263};
+int gamut_bypass_8bit[9] = {
+       256, 0, 0, 0, 256, 0, 0, 0, 256};
 
 /*for iptv special primary->709rgb*/
 int ncl_sp_709[9] = {
        2684, -489, -147, -201, 2266, -17, -29, -171, 2248};
 
+/* gamut bypass */
+int gamut_bypass[9] = {2048, 0, 0, 0, 2048, 0, 0, 0, 2048};
+
 /*int cl_2020_709[9] =*/
        /*{-1775, 3867, -44, 3422, -1154, -220 ,-304,   43, 2309}; */
 int ncl_709_2020[9] = {1285, 674, 89, 142, 1883, 23, 34, 180, 1834};
 /*int cl_709_2020[9] =*/
        /*{436, 1465, 148, 1285, 674, 89, 34, 180, 1834}; */
-/*int yrb2ycbcr_cl2020[15] =*/
-       /*{876, 0, 0, -566, 0, 566, -902, 902, 0, -462, 0, 462, -521, 521, 0};*/
+
+
+/* 1688, 2146,  262, */
+/*  683, 2951,  462, */
+/*   99,  309, 3688, */
+/* 4096 as 1.0 */
+int rgb2lms_ncl2020[9] = {
+       844, 1073, 131,
+       342, 1475, 231,
+       50, 154, 1844
+};
+
+/* ncl_709_2020 * rgb2lms_ncl2020 */
+/* 606.133 1275.828 166.040 */
+/* 320.411 1489.315 238.273 */
+/* 72.384  320.413 1655.203 */
+int rgb709_to_lms2020[9] = {
+       606, 1276, 166,
+       321, 1489, 238,
+       72, 320, 1656
+};
+
+/* Ys coeff, 1.0 = 1024 */
+int ys_coef[3] = {269, 694, 61};
 
 /* matrix coef */
 int rgb2yuvpre[3]      = {0, 0, 0};
@@ -741,29 +882,115 @@ int bypass_pre[3] = {0, 0, 0};
 int bypass_pos[3] = {0, 0, 0};
 
 /*matrix coef BT709*/
-int yuv2rgbmat[15] = {
-       1197, 0, 0, 1197, 1851, 0, 1197, 0, 1163, 1197, 2271, 0, 1197, 0, 2011};
-int rgb2ycbcr[15] = {
-       230, 594, 52, -125, -323, 448, 448, -412, -36, 0, 0, 0, 0, 0, 0};
-int rgb2ycbcr_ncl2020[15] = {
-       230, 594, 52, -125, -323, 448, 448, -412, -36, 0, 0, 0, 0, 0, 0};
-int rgb2ycbcr_709[15] = {
-       186, 627, 63, -103, -345, 448, 448, -407, -41, 0, 0, 0, 0, 0, 0};
-int ycbcr2rgb_709[15]  = {
-       1192, 0, 1836, 1192, -217, -546, 1192, 2166, 0, 0, 0, 0, 0, 0, 0};
-/*int yrb2ycbcr_cl2020[15] =*/
-       /*{876, 0, 0, -566, 0, 566, -902, 902, 0, -462, 0, 462, -521, 521, 0};*/
-int ycbcr2rgb_ncl2020[15] = {
-       1197, 0, 1726, 1197, -193, -669, 1197, 2202, 0, 0, 0, 0, 0, 0, 0};
-/*int ycbcr2yrb_cl2020[15] =*/
-       /*{1197,0,0,1197,0,1163,1197,1851,0, 1197, 0, 2011, 1197, 2271, 0};*/
-
-static int bypass_coeff[15] = {
+int yuv2rgbmat[MTX_NUM_PARAM] = {
+       1197, 0, 0,
+       1197, 1851, 0,
+       1197, 0, 1163,
+       1197, 2271, 0,
+       1197, 0, 2011,
+       0
+};
+
+int rgb2ycbcr[MTX_NUM_PARAM] = {
+       230, 594, 52,
+       -125, -323,
+       448, 448, -412,
+       -36, 0, 0,
+       0, 0, 0,
+       0
+};
+
+int rgb2ycbcr_ncl2020[MTX_NUM_PARAM] = {
+       230, 594, 52,
+       -125, -323, 448,
+       448, -412, -36,
+       0, 0, 0,
+       0, 0, 0,
+       0
+};
+
+int rgb2ycbcr_709[MTX_NUM_PARAM] = {
+       186, 627, 63,
+       -103, -345, 448,
+       448, -407, -41,
+       0, 0, 0,
+       0, 0, 0,
+       0
+};
+
+int ycbcr2rgb_709[MTX_NUM_PARAM]  = {
+       1192, 0, 1836,
+       1192, -217, -546,
+       1192, 2166,
+       0, 0, 0,
+       0, 0, 0,
+       0
+};
+
+/* int yrb2ycbcr_cl2020[MTX_NUM_PARAM] = { */
+/*     876, 0, 0,    */
+/*     -566, 0, 566, */
+/*     -902, 902, 0, */
+/*     -462, 0, 462, */
+/*     -521, 521, 0, */
+/*     0};     */
+
+int ycbcr2rgb_ncl2020[MTX_NUM_PARAM] = {
+       1197, 0, 1726,
+       1197, -193, -669,
+       1197, 2202, 0,
+       0, 0, 0,
+       0, 0, 0,
+       0
+};
+
+/* int ycbcr2yrb_cl2020[MTX_NUM_PARAM] = { */
+/*     1197, 0, 0, */
+/*     1197, 0, 1163, */
+/*     1197, 1851, 0, */
+/*     1197, 0, 2011, */
+/*     1197, 2271, 0, */
+/*     0 */
+/*}; */
+
+/* int yrb2ycbcr_cl2020[MTX_NUM_PARAM] = { */
+/*     876, 0, 0, */
+/*     -566, 0, 566, */
+/*     -902, 902, 0, */
+/*     -462, 0, 462, */
+/*     -521, 521, 0, */
+/*     0 */
+/* }; */
+
+/* [ 2048,  2048,    0], */
+/* [ 6610,-13613, 7003], */
+/* [17933,-17390, -543] / 4096 */
+/* int lms2ipt_ncl2020[MTX_NUM_PARAM] = { */
+/*     256, 256, 0, */
+/*     2242, -2174, -68, */
+/*     827, -1702, 875, */
+/*     0, 0, 0, */
+/*     0, 0, 0, */
+/*     7 << 5 */
+/* }; */
+
+
+int lms2ipt_ncl2020[MTX_NUM_PARAM] = {
+       410,    410,  204,
+       2281, -2484,  203,
+       413,    183, -596,
+       0, 0, 0,
+       0, 0, 0,
+       0
+};
+
+static int bypass_coeff[MTX_NUM_PARAM] = {
        1024, 0, 0,
        0, 1024, 0,
        0, 0, 1024,
        0, 0, 0,
        0, 0, 0,
+       0
 };
 
 unsigned int _log2(unsigned int value)
@@ -837,23 +1064,37 @@ void set_hdr_matrix(
        int c_gain_lim_coef[3];
        int gmut_coef[3][3];
        int gmut_shift;
-       int adpscl_enable[3];
+       int adpscl_bypass[3];
        int adpscl_alpha[3] = {0, 0, 0};
        int adpscl_shift[3];
-       int adpscl_ys_coef[3] = {0, 0, 0};
+       int adpscl_ys_coef[3] = {
+               269,
+               694,
+               61
+       };
        int adpscl_beta[3];
        int adpscl_beta_s[3];
 
        int i = 0;
-       int mtx[15] = {
+       int in_mtx[MTX_NUM_PARAM] = {
                1024, 0, 0,
                0, 1024, 0,
                0, 0, 1024,
                0, 0, 0,
                0, 0, 0,
+               0
        };
 
-       if (module_sel & VD1_HDR) {
+       int out_mtx[MTX_NUM_PARAM] = {
+               1024, 0, 0,
+               0, 1024, 0,
+               0, 0, 1024,
+               0, 0, 0,
+               0, 0, 0,
+               0
+       };
+
+       if (module_sel == VD1_HDR) {
                MATRIXI_COEF00_01 = VD1_HDR2_MATRIXI_COEF00_01;
                MATRIXI_COEF00_01 = VD1_HDR2_MATRIXI_COEF00_01;
                MATRIXI_COEF02_10 = VD1_HDR2_MATRIXI_COEF02_10;
@@ -905,59 +1146,59 @@ void set_hdr_matrix(
                GMUT_COEF4 = VD1_HDR2_GMUT_COEF4;
 
                hdr_ctrl = VD1_HDR2_CTRL;
-       } else if (module_sel & VD2_HDR) {
-               MATRIXI_COEF00_01 = VDIN1_HDR2_MATRIXI_COEF00_01;
-               MATRIXI_COEF00_01 = VDIN1_HDR2_MATRIXI_COEF00_01;
-               MATRIXI_COEF02_10 = VDIN1_HDR2_MATRIXI_COEF02_10;
-               MATRIXI_COEF11_12 = VDIN1_HDR2_MATRIXI_COEF11_12;
-               MATRIXI_COEF20_21 = VDIN1_HDR2_MATRIXI_COEF20_21;
-               MATRIXI_COEF22 = VDIN1_HDR2_MATRIXI_COEF22;
-               MATRIXI_COEF30_31 = VDIN1_HDR2_MATRIXI_COEF30_31;
-               MATRIXI_COEF32_40 = VDIN1_HDR2_MATRIXI_COEF32_40;
-               MATRIXI_COEF41_42 = VDIN1_HDR2_MATRIXI_COEF41_42;
-               MATRIXI_OFFSET0_1 = VDIN1_HDR2_MATRIXI_OFFSET0_1;
-               MATRIXI_OFFSET2 = VDIN1_HDR2_MATRIXI_OFFSET2;
-               MATRIXI_PRE_OFFSET0_1 = VDIN1_HDR2_MATRIXI_PRE_OFFSET0_1;
-               MATRIXI_PRE_OFFSET2 = VDIN1_HDR2_MATRIXI_PRE_OFFSET2;
-               MATRIXI_CLIP = VDIN1_HDR2_MATRIXI_CLIP;
-               MATRIXI_EN_CTRL = VDIN1_HDR2_MATRIXI_EN_CTRL;
-
-               MATRIXO_COEF00_01 = VDIN1_HDR2_MATRIXO_COEF00_01;
-               MATRIXO_COEF00_01 = VDIN1_HDR2_MATRIXO_COEF00_01;
-               MATRIXO_COEF02_10 = VDIN1_HDR2_MATRIXO_COEF02_10;
-               MATRIXO_COEF11_12 = VDIN1_HDR2_MATRIXO_COEF11_12;
-               MATRIXO_COEF20_21 = VDIN1_HDR2_MATRIXO_COEF20_21;
-               MATRIXO_COEF22 = VDIN1_HDR2_MATRIXO_COEF22;
-               MATRIXO_COEF30_31 = VDIN1_HDR2_MATRIXO_COEF30_31;
-               MATRIXO_COEF32_40 = VDIN1_HDR2_MATRIXO_COEF32_40;
-               MATRIXO_COEF41_42 = VDIN1_HDR2_MATRIXO_COEF41_42;
-               MATRIXO_OFFSET0_1 = VDIN1_HDR2_MATRIXO_OFFSET0_1;
-               MATRIXO_OFFSET2 = VDIN1_HDR2_MATRIXO_OFFSET2;
-               MATRIXO_PRE_OFFSET0_1 = VDIN1_HDR2_MATRIXO_PRE_OFFSET0_1;
-               MATRIXO_PRE_OFFSET2 = VDIN1_HDR2_MATRIXO_PRE_OFFSET2;
-               MATRIXO_CLIP = VDIN1_HDR2_MATRIXO_CLIP;
-               MATRIXO_EN_CTRL = VDIN1_HDR2_MATRIXO_EN_CTRL;
+       } else if (module_sel == VD2_HDR) {
+               MATRIXI_COEF00_01 = VD2_HDR2_MATRIXI_COEF00_01;
+               MATRIXI_COEF00_01 = VD2_HDR2_MATRIXI_COEF00_01;
+               MATRIXI_COEF02_10 = VD2_HDR2_MATRIXI_COEF02_10;
+               MATRIXI_COEF11_12 = VD2_HDR2_MATRIXI_COEF11_12;
+               MATRIXI_COEF20_21 = VD2_HDR2_MATRIXI_COEF20_21;
+               MATRIXI_COEF22 = VD2_HDR2_MATRIXI_COEF22;
+               MATRIXI_COEF30_31 = VD2_HDR2_MATRIXI_COEF30_31;
+               MATRIXI_COEF32_40 = VD2_HDR2_MATRIXI_COEF32_40;
+               MATRIXI_COEF41_42 = VD2_HDR2_MATRIXI_COEF41_42;
+               MATRIXI_OFFSET0_1 = VD2_HDR2_MATRIXI_OFFSET0_1;
+               MATRIXI_OFFSET2 = VD2_HDR2_MATRIXI_OFFSET2;
+               MATRIXI_PRE_OFFSET0_1 = VD2_HDR2_MATRIXI_PRE_OFFSET0_1;
+               MATRIXI_PRE_OFFSET2 = VD2_HDR2_MATRIXI_PRE_OFFSET2;
+               MATRIXI_CLIP = VD2_HDR2_MATRIXI_CLIP;
+               MATRIXI_EN_CTRL = VD2_HDR2_MATRIXI_EN_CTRL;
+
+               MATRIXO_COEF00_01 = VD2_HDR2_MATRIXO_COEF00_01;
+               MATRIXO_COEF00_01 = VD2_HDR2_MATRIXO_COEF00_01;
+               MATRIXO_COEF02_10 = VD2_HDR2_MATRIXO_COEF02_10;
+               MATRIXO_COEF11_12 = VD2_HDR2_MATRIXO_COEF11_12;
+               MATRIXO_COEF20_21 = VD2_HDR2_MATRIXO_COEF20_21;
+               MATRIXO_COEF22 = VD2_HDR2_MATRIXO_COEF22;
+               MATRIXO_COEF30_31 = VD2_HDR2_MATRIXO_COEF30_31;
+               MATRIXO_COEF32_40 = VD2_HDR2_MATRIXO_COEF32_40;
+               MATRIXO_COEF41_42 = VD2_HDR2_MATRIXO_COEF41_42;
+               MATRIXO_OFFSET0_1 = VD2_HDR2_MATRIXO_OFFSET0_1;
+               MATRIXO_OFFSET2 = VD2_HDR2_MATRIXO_OFFSET2;
+               MATRIXO_PRE_OFFSET0_1 = VD2_HDR2_MATRIXO_PRE_OFFSET0_1;
+               MATRIXO_PRE_OFFSET2 = VD2_HDR2_MATRIXO_PRE_OFFSET2;
+               MATRIXO_CLIP = VD2_HDR2_MATRIXO_CLIP;
+               MATRIXO_EN_CTRL = VD2_HDR2_MATRIXO_EN_CTRL;
+
+               CGAIN_OFFT = VD2_HDR2_CGAIN_OFFT;
+               CGAIN_COEF0 = VD2_HDR2_CGAIN_COEF0;
+               CGAIN_COEF1 = VD2_HDR2_CGAIN_COEF1;
+               ADPS_CTRL = VD2_HDR2_ADPS_CTRL;
+               ADPS_ALPHA0 = VD2_HDR2_ADPS_ALPHA0;
+               ADPS_ALPHA1 = VD2_HDR2_ADPS_ALPHA1;
+               ADPS_BETA0 = VD2_HDR2_ADPS_BETA0;
+               ADPS_BETA1 = VD2_HDR2_ADPS_BETA1;
+               ADPS_BETA2 = VD2_HDR2_ADPS_BETA2;
+               ADPS_COEF0 = VD2_HDR2_ADPS_COEF0;
+               ADPS_COEF1 = VD2_HDR2_ADPS_COEF1;
+               GMUT_CTRL = VD2_HDR2_GMUT_CTRL;
+               GMUT_COEF0 = VD2_HDR2_GMUT_COEF0;
+               GMUT_COEF1 = VD2_HDR2_GMUT_COEF1;
+               GMUT_COEF2 = VD2_HDR2_GMUT_COEF2;
+               GMUT_COEF3 = VD2_HDR2_GMUT_COEF3;
+               GMUT_COEF4 = VD2_HDR2_GMUT_COEF4;
 
-               CGAIN_OFFT = VDIN1_HDR2_CGAIN_OFFT;
-               CGAIN_COEF0 = VDIN1_HDR2_CGAIN_COEF0;
-               CGAIN_COEF1 = VDIN1_HDR2_CGAIN_COEF1;
-               ADPS_CTRL = VDIN1_HDR2_ADPS_CTRL;
-               ADPS_ALPHA0 = VDIN1_HDR2_ADPS_ALPHA0;
-               ADPS_ALPHA1 = VDIN1_HDR2_ADPS_ALPHA1;
-               ADPS_BETA0 = VDIN1_HDR2_ADPS_BETA0;
-               ADPS_BETA1 = VDIN1_HDR2_ADPS_BETA1;
-               ADPS_BETA2 = VDIN1_HDR2_ADPS_BETA2;
-               ADPS_COEF0 = VDIN1_HDR2_ADPS_COEF0;
-               ADPS_COEF1 = VDIN1_HDR2_ADPS_COEF1;
-               GMUT_CTRL = VDIN1_HDR2_GMUT_CTRL;
-               GMUT_COEF0 = VDIN1_HDR2_GMUT_COEF0;
-               GMUT_COEF1 = VDIN1_HDR2_GMUT_COEF1;
-               GMUT_COEF2 = VDIN1_HDR2_GMUT_COEF2;
-               GMUT_COEF3 = VDIN1_HDR2_GMUT_COEF3;
-               GMUT_COEF4 = VDIN1_HDR2_GMUT_COEF4;
-
-               hdr_ctrl = VDIN1_HDR2_CTRL;
-       } else if (module_sel & OSD1_HDR) {
+               hdr_ctrl = VD2_HDR2_CTRL;
+       } else if (module_sel == OSD1_HDR) {
                MATRIXI_COEF00_01 = OSD1_HDR2_MATRIXI_COEF00_01;
                MATRIXI_COEF00_01 = OSD1_HDR2_MATRIXI_COEF00_01;
                MATRIXI_COEF02_10 = OSD1_HDR2_MATRIXI_COEF02_10;
@@ -1009,7 +1250,7 @@ void set_hdr_matrix(
                GMUT_COEF4 = OSD1_HDR2_GMUT_COEF4;
 
                hdr_ctrl = OSD1_HDR2_CTRL;
-       } else if (module_sel & DI_HDR) {
+       } else if (module_sel == DI_HDR) {
                MATRIXI_COEF00_01 = DI_HDR2_MATRIXI_COEF00_01;
                MATRIXI_COEF00_01 = DI_HDR2_MATRIXI_COEF00_01;
                MATRIXI_COEF02_10 = DI_HDR2_MATRIXI_COEF02_10;
@@ -1061,7 +1302,7 @@ void set_hdr_matrix(
                GMUT_COEF4 = DI_HDR2_GMUT_COEF4;
 
                hdr_ctrl = DI_HDR2_CTRL;
-       } else if (module_sel & VDIN0_HDR) {
+       } else if (module_sel == VDIN0_HDR) {
                MATRIXI_COEF00_01 = VDIN0_HDR2_MATRIXI_COEF00_01;
                MATRIXI_COEF00_01 = VDIN0_HDR2_MATRIXI_COEF00_01;
                MATRIXI_COEF02_10 = VDIN0_HDR2_MATRIXI_COEF02_10;
@@ -1113,7 +1354,7 @@ void set_hdr_matrix(
                GMUT_COEF4 = VDIN0_HDR2_GMUT_COEF4;
 
                hdr_ctrl = VDIN0_HDR2_CTRL;
-       } else if (module_sel & VDIN1_HDR) {
+       } else if (module_sel == VDIN1_HDR) {
                MATRIXI_COEF00_01 = VDIN1_HDR2_MATRIXI_COEF00_01;
                MATRIXI_COEF00_01 = VDIN1_HDR2_MATRIXI_COEF00_01;
                MATRIXI_COEF02_10 = VDIN1_HDR2_MATRIXI_COEF02_10;
@@ -1171,51 +1412,66 @@ void set_hdr_matrix(
                return;
 
        if ((is_meson_g12b_cpu() && is_meson_rev_b()) &&
-               (module_sel & OSD1_HDR))
+               (module_sel == OSD1_HDR))
                _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl,
                        hdr_mtx_param->mtx_on, 13, 1);
        else
                VSYNC_WR_MPEG_REG_BITS(hdr_ctrl,
                        hdr_mtx_param->mtx_on, 13, 1);
 
-       if (mtx_sel & HDR_IN_MTX) {
-               if ((is_meson_g12b_cpu() && is_meson_rev_b()) &&
-                       (module_sel & OSD1_HDR)) {
-                       for (i = 0; i < 15; i++)
-                               mtx[i] = hdr_mtx_param->mtx_in[i];
+       if (mtx_sel == HDR_IN_MTX) {
+               for (i = 0; i < MTX_NUM_PARAM; i++)
+                       in_mtx[i] = hdr_mtx_param->mtx_in[i];
 
-                       /*for rtl bug osd1 green line at the bottom*/
+#ifdef HDR2_PRINT
+               pr_info("hdr: in_mtx %d %d = %x,%x %x %x %x %x,%x\n",
+                       hdr_mtx_param->mtx_on,
+                       hdr_mtx_param->mtx_only,
+                       (hdr_mtx_param->mtxi_pre_offset[0] << 16) |
+                       (hdr_mtx_param->mtxi_pre_offset[1] & 0xFFF),
+                       (in_mtx[0 * 3 + 0] << 16) |
+                       (in_mtx[0 * 3 + 1] & 0x1FFF),
+                       (in_mtx[0 * 3 + 2] << 16) |
+                       (in_mtx[1 * 3 + 0] & 0x1FFF),
+                       (in_mtx[1 * 3 + 1] << 16) |
+                       (in_mtx[1 * 3 + 2] & 0x1FFF),
+                       (in_mtx[2 * 3 + 0] << 16) |
+                       (in_mtx[2 * 3 + 1] & 0x1FFF),
+                       in_mtx[2 * 3 + 2],
+                       (hdr_mtx_param->mtxi_pos_offset[0] << 16) |
+                       (hdr_mtx_param->mtxi_pos_offset[1] & 0xFFF));
+#endif
+
+               if ((is_meson_g12b_cpu() && is_meson_rev_b()) &&
+                       (module_sel == OSD1_HDR)) {
+                       /* only enable in_mtx */
                        if ((hdr_mtx_param->mtx_only == MTX_ONLY) &&
                                (!hdr_mtx_param->mtx_on))
                                _VSYNC_WR_MPEG_REG(MATRIXI_EN_CTRL, 1);
                        else
                                _VSYNC_WR_MPEG_REG(MATRIXI_EN_CTRL,
-                               hdr_mtx_param->mtx_on);
-                       /*yuv in*/
+                                       hdr_mtx_param->mtx_on);
                        _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl,
                                hdr_mtx_param->mtx_on, 4, 1);
-
                        _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl,
                                hdr_mtx_param->mtx_only,
                                16, 1);
-                       _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, 0, 17, 1);
-                       /*mtx in en*/
                        _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, 1, 14, 1);
 
                        _VSYNC_WR_MPEG_REG(MATRIXI_COEF00_01,
-                               (mtx[0 * 3 + 0] << 16) |
-                               (mtx[0 * 3 + 1] & 0x1FFF));
+                               (in_mtx[0 * 3 + 0] << 16) |
+                               (in_mtx[0 * 3 + 1] & 0x1FFF));
                        _VSYNC_WR_MPEG_REG(MATRIXI_COEF02_10,
-                               (mtx[0 * 3 + 2] << 16) |
-                               (mtx[1 * 3 + 0] & 0x1FFF));
+                               (in_mtx[0 * 3 + 2] << 16) |
+                               (in_mtx[1 * 3 + 0] & 0x1FFF));
                        _VSYNC_WR_MPEG_REG(MATRIXI_COEF11_12,
-                               (mtx[1 * 3 + 1] << 16) |
-                               (mtx[1 * 3 + 2] & 0x1FFF));
+                               (in_mtx[1 * 3 + 1] << 16) |
+                               (in_mtx[1 * 3 + 2] & 0x1FFF));
                        _VSYNC_WR_MPEG_REG(MATRIXI_COEF20_21,
-                               (mtx[2 * 3 + 0] << 16) |
-                               (mtx[2 * 3 + 1] & 0x1FFF));
+                               (in_mtx[2 * 3 + 0] << 16) |
+                               (in_mtx[2 * 3 + 1] & 0x1FFF));
                        _VSYNC_WR_MPEG_REG(MATRIXI_COEF22,
-                               mtx[2 * 3 + 2]);
+                               in_mtx[2 * 3 + 2]);
                        _VSYNC_WR_MPEG_REG(MATRIXI_OFFSET0_1,
                                (hdr_mtx_param->mtxi_pos_offset[0] << 16) |
                                (hdr_mtx_param->mtxi_pos_offset[1] & 0xFFF));
@@ -1229,35 +1485,33 @@ void set_hdr_matrix(
 
                        return;
                }
-               for (i = 0; i < 15; i++)
-                       mtx[i] = hdr_mtx_param->mtx_in[i];
-
-               /*for rtl bug osd1 green line at the bottom*/
                if ((hdr_mtx_param->mtx_only == MTX_ONLY) &&
-                       (!hdr_mtx_param->mtx_on))
+               (!hdr_mtx_param->mtx_on))
                        VSYNC_WR_MPEG_REG(MATRIXI_EN_CTRL, 1);
                else
                        VSYNC_WR_MPEG_REG(MATRIXI_EN_CTRL,
-                       hdr_mtx_param->mtx_on);
-               /*yuv in*/
-               VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, hdr_mtx_param->mtx_on, 4, 1);
-
-               VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, hdr_mtx_param->mtx_only,
+                               hdr_mtx_param->mtx_on);
+               VSYNC_WR_MPEG_REG_BITS(hdr_ctrl,
+                       hdr_mtx_param->mtx_on, 4, 1);
+               VSYNC_WR_MPEG_REG_BITS(hdr_ctrl,
+                       hdr_mtx_param->mtx_only,
                        16, 1);
-               VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, 0, 17, 1);
-               /*mtx in en*/
                VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, 1, 14, 1);
 
                VSYNC_WR_MPEG_REG(MATRIXI_COEF00_01,
-                       (mtx[0 * 3 + 0] << 16) | (mtx[0 * 3 + 1] & 0x1FFF));
+                       (in_mtx[0 * 3 + 0] << 16) |
+                       (in_mtx[0 * 3 + 1] & 0x1FFF));
                VSYNC_WR_MPEG_REG(MATRIXI_COEF02_10,
-                       (mtx[0 * 3 + 2] << 16) | (mtx[1 * 3 + 0] & 0x1FFF));
+                       (in_mtx[0 * 3 + 2] << 16) |
+                       (in_mtx[1 * 3 + 0] & 0x1FFF));
                VSYNC_WR_MPEG_REG(MATRIXI_COEF11_12,
-                       (mtx[1 * 3 + 1] << 16) | (mtx[1 * 3 + 2] & 0x1FFF));
+                       (in_mtx[1 * 3 + 1] << 16) |
+                       (in_mtx[1 * 3 + 2] & 0x1FFF));
                VSYNC_WR_MPEG_REG(MATRIXI_COEF20_21,
-                       (mtx[2 * 3 + 0] << 16) | (mtx[2 * 3 + 1] & 0x1FFF));
+                       (in_mtx[2 * 3 + 0] << 16) |
+                       (in_mtx[2 * 3 + 1] & 0x1FFF));
                VSYNC_WR_MPEG_REG(MATRIXI_COEF22,
-                       mtx[2 * 3 + 2]);
+                       in_mtx[2 * 3 + 2]);
                VSYNC_WR_MPEG_REG(MATRIXI_OFFSET0_1,
                        (hdr_mtx_param->mtxi_pos_offset[0] << 16) |
                        (hdr_mtx_param->mtxi_pos_offset[1] & 0xFFF));
@@ -1268,79 +1522,100 @@ void set_hdr_matrix(
                        (hdr_mtx_param->mtxi_pre_offset[1] & 0xFFF));
                VSYNC_WR_MPEG_REG(MATRIXI_PRE_OFFSET2,
                        hdr_mtx_param->mtxi_pre_offset[2]);
-       } else if (mtx_sel & HDR_GAMUT_MTX) {
+       } else if (mtx_sel == HDR_GAMUT_MTX) {
                for (i = 0; i < 9; i++)
                        gmut_coef[i/3][i%3] =
                                hdr_mtx_param->mtx_gamut[i];
-               /*for g12a/g12b osd blend shift rtl bug*/
-               if ((is_meson_g12a_cpu() ||
-                       (is_meson_g12b_cpu() && is_meson_rev_a())) &&
-                       (hdr_mtx_param->p_sel & HDR_BYPASS) &&
-                       (module_sel & OSD1_HDR))
-                       gmut_shift = 10;
-               else if (hdr_mtx_param->p_sel & HDR_SDR)
-                       /*work around for gamut bug*/
-                       gmut_shift = 0;/*11*/
+               if (hdr_mtx_param->p_sel == HDR_SDR)
+                       /* use integer mode for gamut coeff */
+                       gmut_shift = 0;
                else
-                       /*default 11, set 12 avoid gamut overwrite*/
-                       gmut_shift = 12;
+                       /* 2048 as 1.0 for gamut coeff */
+                       gmut_shift = 11;
 
                for (i = 0; i < 3; i++)
                        c_gain_lim_coef[i] =
                                hdr_mtx_param->mtx_cgain[i] << 2;
-               /*0, nolinear input, 1, max linear, 2, adpscl mode*/
-               adpscl_mode = 1;
+               /* 0: adptive scaler mode(Ys); 1: max linear(RGB max) */
+               /* 2: none linear Ys -- Do NOT use it */
+               if (hdr_mtx_param->p_sel == HLG_HDR ||
+                       hdr_mtx_param->p_sel == HLG_SDR ||
+                       hdr_mtx_param->p_sel == HLG_IPT)
+                       adpscl_mode = 0;
+               else
+                       adpscl_mode = 1;
+
                for (i = 0; i < 3; i++) {
-                       if ((is_meson_g12a_cpu() ||
-                               (is_meson_g12b_cpu() && is_meson_rev_a())) &&
-                               (hdr_mtx_param->p_sel & HDR_BYPASS) &&
-                               (module_sel & OSD1_HDR))
-                               adpscl_enable[i] = 1;
+                       /* bypass adpscl for OSD rgb2yuv*/
+                       if ((hdr_mtx_param->p_sel == RGB_YUV
+                       || hdr_mtx_param->mtx_only)
+                       && (module_sel == OSD1_HDR))
+                               adpscl_bypass[i] = 1;
+                       else
+                               adpscl_bypass[i] = 0;
+                       if (hdr_mtx_param->p_sel == HLG_HDR ||
+                               hdr_mtx_param->p_sel == HLG_IPT)
+                               adpscl_alpha[i] = 1000 *
+                                       (1 << adp_scal_y_shift) / 10000;
                        else
-                               adpscl_enable[i] = 0;
-                       if (hdr_mtx_param->p_sel & HDR_SDR)
-                               adpscl_alpha[i] =
-                                       (1 << adp_scal_shift);
-                       else if (hdr_mtx_param->p_sel & SDR_HDR)
                                adpscl_alpha[i] =
-                                       (1 << adp_scal_shift);
-                       else if (hdr_mtx_param->p_sel & HDR_BYPASS)
-                               adpscl_alpha[i] = out_luma *
-                                       (1 << adp_scal_shift) / in_luma;
-                       else if (hdr_mtx_param->p_sel & HLG_SDR) {
-                               adpscl_alpha[i] = out_luma *
-                                       (1 << adp_scal_shift) / in_luma;
-                               adpscl_mode = 2;
-                       } else if (hdr_mtx_param->p_sel & HLG_HDR)
-                               adpscl_alpha[i] = 1 *
-                                       (1 << adp_scal_shift) / in_luma;
-                       else if (hdr_mtx_param->p_sel & SDR_HLG)
-                               adpscl_alpha[i] = 10 * in_luma *
-                                       (1 << adp_scal_shift) / out_luma;
-
-                       adpscl_ys_coef[i] =
-                                       1 << adp_scal_shift;
+                                       (1 << adp_scal_y_shift);
+
+                       if (adpscl_mode == 1)
+                               adpscl_ys_coef[i] =
+                                       1 << adp_scal_x_shift;
+                       else
+                               adpscl_ys_coef[i] =
+                                       ys_coef[i] >> (10 - adp_scal_x_shift);
+
+
                        adpscl_beta_s[i] = 0;
                        adpscl_beta[i] = 0;
                }
 
                /*shift0 is for x coordinate*/
-               adpscl_shift[0] = adp_scal_shift;
                /*shift1 is for scale multiple*/
-               if (hdr_mtx_param->p_sel & HDR_SDR)
-                       adpscl_shift[1] = adp_scal_shift -
-                       _log2((1 << adp_scal_shift) / oo_y_lut_hdr_sdr[148]);
-               else
-                       adpscl_shift[1] = adp_scal_shift - 1;
+               if (hdr_mtx_param->p_sel == HDR_SDR) {
+                       adpscl_shift[0] = adp_scal_x_shift - 1;
+                       adpscl_shift[1] = OO_NOR -
+                       _log2((1 << OO_NOR) / oo_y_lut_hdr_sdr[148] - 1);
+               } else if (hdr_mtx_param->p_sel == HDR_HLG) {
+                       adpscl_shift[0] = adp_scal_x_shift;
+                       adpscl_shift[1] = OO_NOR -
+                       _log2((1 << OO_NOR) / oo_y_lut_hdr_hlg[148]);
+               } else {
+                       adpscl_shift[0] = adp_scal_x_shift;
+                       adpscl_shift[1] = OO_NOR;
+               }
+
                /*shift2 is not used, set default*/
-               adpscl_shift[2] = adp_scal_shift;
+               adpscl_shift[2] = adp_scal_y_shift;
+
+#ifdef HDR2_PRINT
+               pr_info("hdr: gamut_mtx %d mode %d shift %d = %x %x %x %x %x\n",
+                       hdr_mtx_param->mtx_on,
+                       hdr_mtx_param->mtx_gamut_mode,
+                       gmut_shift,
+                       (gmut_coef[0][1] & 0xffff) << 16 |
+                       (gmut_coef[0][0] & 0xffff),
+                       (gmut_coef[1][0] & 0xffff) << 16 |
+                       (gmut_coef[0][2] & 0xffff),
+                       (gmut_coef[1][2] & 0xffff) << 16 |
+                       (gmut_coef[1][1] & 0xffff),
+                       (gmut_coef[2][1] & 0xffff) << 16 |
+                       (gmut_coef[2][0] & 0xffff),
+                       gmut_coef[2][2] & 0xffff);
+               pr_info("hdr: adpscl bypass %d, x_shift %d, y_shift %d\n",
+                       adpscl_bypass[0], adpscl_shift[0], adpscl_shift[1]);
+#endif
 
                /*gamut mode: 1->gamut before ootf*/
                                        /*2->gamut after ootf*/
                                        /*other->disable gamut*/
                if ((is_meson_g12b_cpu() && is_meson_rev_b()) &&
-                       (module_sel & OSD1_HDR)) {
-                       _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, 1, 6, 2);
+                       (module_sel == OSD1_HDR)) {
+                       _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl,
+                               hdr_mtx_param->mtx_gamut_mode, 6, 2);
 
                    _VSYNC_WR_MPEG_REG(GMUT_CTRL, gmut_shift);
                    _VSYNC_WR_MPEG_REG(GMUT_COEF0,
@@ -1365,9 +1640,9 @@ void set_hdr_matrix(
                                c_gain_lim_coef[2], 0, 12);
 
                    _VSYNC_WR_MPEG_REG(ADPS_CTRL,
-                               adpscl_enable[2] << 6 |
-                               adpscl_enable[1] << 5 |
-                               adpscl_enable[0] << 4 |
+                               adpscl_bypass[2] << 6 |
+                               adpscl_bypass[1] << 5 |
+                               adpscl_bypass[0] << 4 |
                                adpscl_mode);
                        _VSYNC_WR_MPEG_REG(ADPS_ALPHA0,
                                        adpscl_alpha[1]<<16 | adpscl_alpha[0]);
@@ -1387,11 +1662,10 @@ void set_hdr_matrix(
                                adpscl_ys_coef[0]);
                    _VSYNC_WR_MPEG_REG(ADPS_COEF1,
                                adpscl_ys_coef[2]);
-
                        return;
                }
-               VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, 1, 6, 2);
-
+               VSYNC_WR_MPEG_REG_BITS(hdr_ctrl,
+                       hdr_mtx_param->mtx_gamut_mode, 6, 2);
                VSYNC_WR_MPEG_REG(GMUT_CTRL, gmut_shift);
                VSYNC_WR_MPEG_REG(GMUT_COEF0,
                        (gmut_coef[0][1] & 0xffff) << 16 |
@@ -1411,19 +1685,21 @@ void set_hdr_matrix(
                VSYNC_WR_MPEG_REG(CGAIN_COEF0,
                        c_gain_lim_coef[1] << 16 |
                        c_gain_lim_coef[0]);
-               VSYNC_WR_MPEG_REG_BITS(CGAIN_COEF1, c_gain_lim_coef[2],
-                       0, 12);
-
-               VSYNC_WR_MPEG_REG(ADPS_CTRL, adpscl_enable[2] << 6 |
-                                               adpscl_enable[1] << 5 |
-                                               adpscl_enable[0] << 4 |
-                                               adpscl_mode);
+               VSYNC_WR_MPEG_REG_BITS(CGAIN_COEF1,
+                       c_gain_lim_coef[2],     0, 12);
+
+               VSYNC_WR_MPEG_REG(ADPS_CTRL,
+                       adpscl_bypass[2] << 6 |
+                       adpscl_bypass[1] << 5 |
+                       adpscl_bypass[0] << 4 |
+                       adpscl_mode);
                VSYNC_WR_MPEG_REG(ADPS_ALPHA0,
-                               adpscl_alpha[1]<<16 | adpscl_alpha[0]);
-               VSYNC_WR_MPEG_REG(ADPS_ALPHA1, adpscl_shift[0] << 24 |
-                                               adpscl_shift[1] << 20 |
-                                               adpscl_shift[2] << 16 |
-                                               adpscl_alpha[2]);
+                       adpscl_alpha[1]<<16 | adpscl_alpha[0]);
+               VSYNC_WR_MPEG_REG(ADPS_ALPHA1,
+                       adpscl_shift[0] << 24 |
+                       adpscl_shift[1] << 20 |
+                       adpscl_shift[2] << 16 |
+                       adpscl_alpha[2]);
                VSYNC_WR_MPEG_REG(ADPS_BETA0,
                        adpscl_beta_s[0] << 20 | adpscl_beta[0]);
                VSYNC_WR_MPEG_REG(ADPS_BETA1,
@@ -1431,42 +1707,56 @@ void set_hdr_matrix(
                VSYNC_WR_MPEG_REG(ADPS_BETA2,
                        adpscl_beta_s[2] << 20 | adpscl_beta[2]);
                VSYNC_WR_MPEG_REG(ADPS_COEF0,
-                       adpscl_ys_coef[1] << 16 | adpscl_ys_coef[0]);
-               VSYNC_WR_MPEG_REG(ADPS_COEF1, adpscl_ys_coef[2]);
-       } else if (mtx_sel & HDR_OUT_MTX) {
+                       adpscl_ys_coef[1] << 16 |
+                       adpscl_ys_coef[0]);
+               VSYNC_WR_MPEG_REG(ADPS_COEF1,
+                       adpscl_ys_coef[2]);
+       } else if (mtx_sel == HDR_OUT_MTX) {
+               for (i = 0; i < MTX_NUM_PARAM; i++)
+                       out_mtx[i] = hdr_mtx_param->mtx_out[i];
+#ifdef HDR2_PRINT
+               pr_info("hdr: out_mtx %d %d = %x,%x %x %x %x %x,%x\n",
+                       hdr_mtx_param->mtx_on,
+                       hdr_mtx_param->mtx_only,
+                       (hdr_mtx_param->mtxo_pre_offset[0] << 16) |
+                       (hdr_mtx_param->mtxo_pre_offset[1] & 0xFFF),
+                       (out_mtx[0 * 3 + 0] << 16) |
+                       (out_mtx[0 * 3 + 1] & 0x1FFF),
+                       (out_mtx[0 * 3 + 2] << 16) |
+                       (out_mtx[1 * 3 + 0] & 0x1FFF),
+                       (out_mtx[1 * 3 + 1] << 16) |
+                       (out_mtx[1 * 3 + 2] & 0x1FFF),
+                       (out_mtx[2 * 3 + 0] << 16) |
+                       (out_mtx[2 * 3 + 1] & 0x1FFF),
+                       out_mtx[2 * 3 + 2],
+                       (hdr_mtx_param->mtxo_pos_offset[0] << 16) |
+                       (hdr_mtx_param->mtxo_pos_offset[1] & 0xFFF));
+#endif
+
                if ((is_meson_g12b_cpu() && is_meson_rev_b()) &&
-                       (module_sel & OSD1_HDR)) {
-                       for (i = 0; i < 15; i++)
-                               mtx[i] = hdr_mtx_param->mtx_out[i];
+                       (module_sel == OSD1_HDR)) {
                        _VSYNC_WR_MPEG_REG(CGAIN_OFFT,
                                (rgb2yuvpos[2] << 16) | rgb2yuvpos[1]);
                        _VSYNC_WR_MPEG_REG(MATRIXO_EN_CTRL,
                                hdr_mtx_param->mtx_on);
-                       /*yuv in*/
-                       _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl,
-                               hdr_mtx_param->mtx_on, 4, 1);
-
-                       _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl,
-                               hdr_mtx_param->mtx_only,
-                               16, 1);
                        _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, 0, 17, 1);
-                       /*mtx out en*/
                        _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, 1, 15, 1);
 
                        _VSYNC_WR_MPEG_REG(MATRIXO_COEF00_01,
-                               (mtx[0 * 3 + 0] << 16) |
-                               (mtx[0 * 3 + 1] & 0x1FFF));
+                               (out_mtx[0 * 3 + 0] << 16) |
+                               (out_mtx[0 * 3 + 1] & 0x1FFF));
                        _VSYNC_WR_MPEG_REG(MATRIXO_COEF02_10,
-                               (mtx[0 * 3 + 2] << 16) |
-                               (mtx[1 * 3 + 0] & 0x1FFF));
+                               (out_mtx[0 * 3 + 2] << 16) |
+                               (out_mtx[1 * 3 + 0] & 0x1FFF));
                        _VSYNC_WR_MPEG_REG(MATRIXO_COEF11_12,
-                               (mtx[1 * 3 + 1] << 16) |
-                               (mtx[1 * 3 + 2] & 0x1FFF));
+                               (out_mtx[1 * 3 + 1] << 16) |
+                               (out_mtx[1 * 3 + 2] & 0x1FFF));
                        _VSYNC_WR_MPEG_REG(MATRIXO_COEF20_21,
-                               (mtx[2 * 3 + 0] << 16) |
-                               (mtx[2 * 3 + 1] & 0x1FFF));
+                               (out_mtx[2 * 3 + 0] << 16) |
+                               (out_mtx[2 * 3 + 1] & 0x1FFF));
                        _VSYNC_WR_MPEG_REG(MATRIXO_COEF22,
-                               mtx[2 * 3 + 2]);
+                               out_mtx[2 * 3 + 2]);
+
                        _VSYNC_WR_MPEG_REG(MATRIXO_OFFSET0_1,
                                (hdr_mtx_param->mtxo_pos_offset[0] << 16) |
                                (hdr_mtx_param->mtxo_pos_offset[1]&0xFFF));
@@ -1479,30 +1769,29 @@ void set_hdr_matrix(
                                hdr_mtx_param->mtxo_pre_offset[2]);
                        return;
                }
-               for (i = 0; i < 15; i++)
-                       mtx[i] = hdr_mtx_param->mtx_out[i];
+
                VSYNC_WR_MPEG_REG(CGAIN_OFFT,
                        (rgb2yuvpos[2] << 16) | rgb2yuvpos[1]);
-               VSYNC_WR_MPEG_REG(MATRIXO_EN_CTRL, hdr_mtx_param->mtx_on);
-               /*yuv in*/
-               VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, hdr_mtx_param->mtx_on, 4, 1);
-
-               VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, hdr_mtx_param->mtx_only,
-                       16, 1);
+               VSYNC_WR_MPEG_REG(MATRIXO_EN_CTRL,
+                       hdr_mtx_param->mtx_on);
                VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, 0, 17, 1);
-               /*mtx out en*/
                VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, 1, 15, 1);
 
                VSYNC_WR_MPEG_REG(MATRIXO_COEF00_01,
-                       (mtx[0 * 3 + 0] << 16) | (mtx[0 * 3 + 1] & 0x1FFF));
+                       (out_mtx[0 * 3 + 0] << 16) |
+                       (out_mtx[0 * 3 + 1] & 0x1FFF));
                VSYNC_WR_MPEG_REG(MATRIXO_COEF02_10,
-                       (mtx[0 * 3 + 2] << 16) | (mtx[1 * 3 + 0] & 0x1FFF));
+                       (out_mtx[0 * 3 + 2] << 16) |
+                       (out_mtx[1 * 3 + 0] & 0x1FFF));
                VSYNC_WR_MPEG_REG(MATRIXO_COEF11_12,
-                       (mtx[1 * 3 + 1] << 16) | (mtx[1 * 3 + 2] & 0x1FFF));
+                       (out_mtx[1 * 3 + 1] << 16) |
+                       (out_mtx[1 * 3 + 2] & 0x1FFF));
                VSYNC_WR_MPEG_REG(MATRIXO_COEF20_21,
-                       (mtx[2 * 3 + 0] << 16) | (mtx[2 * 3 + 1] & 0x1FFF));
+                       (out_mtx[2 * 3 + 0] << 16) |
+                       (out_mtx[2 * 3 + 1] & 0x1FFF));
                VSYNC_WR_MPEG_REG(MATRIXO_COEF22,
-                       mtx[2 * 3 + 2]);
+                       out_mtx[2 * 3 + 2]);
+
                VSYNC_WR_MPEG_REG(MATRIXO_OFFSET0_1,
                        (hdr_mtx_param->mtxo_pos_offset[0] << 16) |
                        (hdr_mtx_param->mtxo_pos_offset[1]&0xFFF));
@@ -1526,27 +1815,27 @@ void set_eotf_lut(
        unsigned int hdr_ctrl = 0;
        unsigned int i = 0;
 
-       if (module_sel & VD1_HDR) {
+       if (module_sel == VD1_HDR) {
                eotf_lut_addr_port = VD1_EOTF_LUT_ADDR_PORT;
                eotf_lut_data_port = VD1_EOTF_LUT_DATA_PORT;
                hdr_ctrl = VD1_HDR2_CTRL;
-       } else if (module_sel & VD2_HDR) {
+       } else if (module_sel == VD2_HDR) {
                eotf_lut_addr_port = VD2_EOTF_LUT_ADDR_PORT;
                eotf_lut_data_port = VD2_EOTF_LUT_DATA_PORT;
                hdr_ctrl = VD2_HDR2_CTRL;
-       } else if (module_sel & OSD1_HDR) {
+       } else if (module_sel == OSD1_HDR) {
                eotf_lut_addr_port = OSD1_EOTF_LUT_ADDR_PORT;
                eotf_lut_data_port = OSD1_EOTF_LUT_DATA_PORT;
                hdr_ctrl = OSD1_HDR2_CTRL;
-       } else if (module_sel & DI_HDR) {
+       } else if (module_sel == DI_HDR) {
                eotf_lut_addr_port = DI_EOTF_LUT_ADDR_PORT;
                eotf_lut_data_port = DI_EOTF_LUT_DATA_PORT;
                hdr_ctrl = DI_HDR2_CTRL;
-       } else if (module_sel & VDIN0_HDR) {
+       } else if (module_sel == VDIN0_HDR) {
                eotf_lut_addr_port = VDIN0_EOTF_LUT_ADDR_PORT;
                eotf_lut_data_port = VDIN0_EOTF_LUT_DATA_PORT;
                hdr_ctrl = VDIN0_HDR2_CTRL;
-       } else if (module_sel & VDIN1_HDR) {
+       } else if (module_sel == VDIN1_HDR) {
                eotf_lut_addr_port = VDIN1_EOTF_LUT_ADDR_PORT;
                eotf_lut_data_port = VDIN1_EOTF_LUT_DATA_PORT;
                hdr_ctrl = VDIN1_HDR2_CTRL;
@@ -1554,8 +1843,9 @@ void set_eotf_lut(
 
        for (i = 0; i < HDR2_EOTF_LUT_SIZE; i++)
                lut[i] = hdr_lut_param->eotf_lut[i];
+
        if ((is_meson_g12b_cpu() && is_meson_rev_b()) &&
-               (module_sel & OSD1_HDR)) {
+               (module_sel == OSD1_HDR)) {
                _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, hdr_lut_param->lut_on, 3, 1);
 
                if (!hdr_lut_param->lut_on)
@@ -1586,27 +1876,27 @@ void set_ootf_lut(
        unsigned int hdr_ctrl = 0;
        unsigned int i = 0;
 
-       if (module_sel & VD1_HDR) {
+       if (module_sel == VD1_HDR) {
                ootf_lut_addr_port = VD1_OGAIN_LUT_ADDR_PORT;
                ootf_lut_data_port = VD1_OGAIN_LUT_DATA_PORT;
                hdr_ctrl = VD1_HDR2_CTRL;
-       } else if (module_sel & VD2_HDR) {
+       } else if (module_sel == VD2_HDR) {
                ootf_lut_addr_port = VD2_OGAIN_LUT_ADDR_PORT;
                ootf_lut_data_port = VD2_OGAIN_LUT_DATA_PORT;
                hdr_ctrl = VD2_HDR2_CTRL;
-       } else if (module_sel & OSD1_HDR) {
+       } else if (module_sel == OSD1_HDR) {
                ootf_lut_addr_port = OSD1_OGAIN_LUT_ADDR_PORT;
                ootf_lut_data_port = OSD1_OGAIN_LUT_DATA_PORT;
                hdr_ctrl = OSD1_HDR2_CTRL;
-       } else if (module_sel & DI_HDR) {
+       } else if (module_sel == DI_HDR) {
                ootf_lut_addr_port = DI_OGAIN_LUT_ADDR_PORT;
                ootf_lut_data_port = DI_OGAIN_LUT_DATA_PORT;
                hdr_ctrl = DI_HDR2_CTRL;
-       } else if (module_sel & VDIN0_HDR) {
+       } else if (module_sel == VDIN0_HDR) {
                ootf_lut_addr_port = VDIN0_OGAIN_LUT_ADDR_PORT;
                ootf_lut_data_port = VDIN0_OGAIN_LUT_DATA_PORT;
                hdr_ctrl = VDIN0_HDR2_CTRL;
-       } else if (module_sel & VDIN1_HDR) {
+       } else if (module_sel == VDIN1_HDR) {
                ootf_lut_addr_port = VDIN1_OGAIN_LUT_ADDR_PORT;
                ootf_lut_data_port = VDIN1_OGAIN_LUT_DATA_PORT;
                hdr_ctrl = VDIN1_HDR2_CTRL;
@@ -1614,9 +1904,8 @@ void set_ootf_lut(
 
        for (i = 0; i < HDR2_OOTF_LUT_SIZE; i++)
                lut[i] = hdr_lut_param->ogain_lut[i];
-
        if ((is_meson_g12b_cpu() && is_meson_rev_b()) &&
-               (module_sel & OSD1_HDR)) {
+               (module_sel == OSD1_HDR)) {
                _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, hdr_lut_param->lut_on, 1, 1);
 
                if (!hdr_lut_param->lut_on)
@@ -1631,7 +1920,6 @@ void set_ootf_lut(
 
                return;
        }
-
        VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, hdr_lut_param->lut_on, 1, 1);
 
        if (!hdr_lut_param->lut_on)
@@ -1655,27 +1943,27 @@ void set_oetf_lut(
        unsigned int hdr_ctrl = 0;
        unsigned int i = 0;
 
-       if (module_sel & VD1_HDR) {
+       if (module_sel == VD1_HDR) {
                oetf_lut_addr_port = VD1_OETF_LUT_ADDR_PORT;
                oetf_lut_data_port = VD1_OETF_LUT_DATA_PORT;
                hdr_ctrl = VD1_HDR2_CTRL;
-       } else if (module_sel & VD2_HDR) {
+       } else if (module_sel == VD2_HDR) {
                oetf_lut_addr_port = VD2_OETF_LUT_ADDR_PORT;
                oetf_lut_data_port = VD2_OETF_LUT_DATA_PORT;
                hdr_ctrl = VD2_HDR2_CTRL;
-       } else if (module_sel & OSD1_HDR) {
+       } else if (module_sel == OSD1_HDR) {
                oetf_lut_addr_port = OSD1_OETF_LUT_ADDR_PORT;
                oetf_lut_data_port = OSD1_OETF_LUT_DATA_PORT;
                hdr_ctrl = OSD1_HDR2_CTRL;
-       } else if (module_sel & DI_HDR) {
+       } else if (module_sel == DI_HDR) {
                oetf_lut_addr_port = DI_OETF_LUT_ADDR_PORT;
                oetf_lut_data_port = DI_OETF_LUT_DATA_PORT;
                hdr_ctrl = DI_HDR2_CTRL;
-       } else if (module_sel & VDIN0_HDR) {
+       } else if (module_sel == VDIN0_HDR) {
                oetf_lut_addr_port = VDIN0_OETF_LUT_ADDR_PORT;
                oetf_lut_data_port = VDIN0_OETF_LUT_DATA_PORT;
                hdr_ctrl = VDIN0_HDR2_CTRL;
-       } else if (module_sel & VDIN1_HDR) {
+       } else if (module_sel == VDIN1_HDR) {
                oetf_lut_addr_port = VDIN1_OETF_LUT_ADDR_PORT;
                oetf_lut_data_port = VDIN1_OETF_LUT_DATA_PORT;
                hdr_ctrl = VDIN1_HDR2_CTRL;
@@ -1685,7 +1973,7 @@ void set_oetf_lut(
                lut[i] = hdr_lut_param->oetf_lut[i];
 
        if ((is_meson_g12b_cpu() && is_meson_rev_b()) &&
-               (module_sel & OSD1_HDR)) {
+               (module_sel == OSD1_HDR)) {
                _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, hdr_lut_param->lut_on, 2, 1);
 
                if (!hdr_lut_param->lut_on)
@@ -1709,7 +1997,6 @@ void set_oetf_lut(
 
                return;
        }
-
        VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, hdr_lut_param->lut_on, 2, 1);
 
        if (!hdr_lut_param->lut_on)
@@ -1743,32 +2030,32 @@ void set_c_gain(
        unsigned int cgain_coef1 = 0;
        unsigned int i = 0;
 
-       if (module_sel & VD1_HDR) {
+       if (module_sel == VD1_HDR) {
                cgain_lut_addr_port = VD1_CGAIN_LUT_ADDR_PORT;
                cgain_lut_data_port = VD1_CGAIN_LUT_DATA_PORT;
                hdr_ctrl = VD1_HDR2_CTRL;
                cgain_coef1 = VD1_HDR2_CGAIN_COEF1;
-       } else if (module_sel & VD2_HDR) {
+       } else if (module_sel == VD2_HDR) {
                cgain_lut_addr_port = VD2_CGAIN_LUT_ADDR_PORT;
                cgain_lut_data_port = VD2_CGAIN_LUT_DATA_PORT;
                hdr_ctrl = VD2_HDR2_CTRL;
                cgain_coef1 = VD2_HDR2_CGAIN_COEF1;
-       } else if (module_sel & OSD1_HDR) {
+       } else if (module_sel == OSD1_HDR) {
                cgain_lut_addr_port = OSD1_CGAIN_LUT_ADDR_PORT;
                cgain_lut_data_port = OSD1_CGAIN_LUT_DATA_PORT;
                hdr_ctrl = OSD1_HDR2_CTRL;
                cgain_coef1 = OSD1_HDR2_CGAIN_COEF1;
-       } else if (module_sel & DI_HDR) {
+       } else if (module_sel == DI_HDR) {
                cgain_lut_addr_port = DI_CGAIN_LUT_ADDR_PORT;
                cgain_lut_data_port = DI_CGAIN_LUT_DATA_PORT;
                hdr_ctrl = DI_HDR2_CTRL;
                cgain_coef1 = DI_HDR2_CGAIN_COEF1;
-       } else if (module_sel & VDIN0_HDR) {
+       } else if (module_sel == VDIN0_HDR) {
                cgain_lut_addr_port = VDIN0_CGAIN_LUT_ADDR_PORT;
                cgain_lut_data_port = VDIN0_CGAIN_LUT_DATA_PORT;
                hdr_ctrl = VDIN0_HDR2_CTRL;
                cgain_coef1 = VDIN0_HDR2_CGAIN_COEF1;
-       } else if (module_sel & VDIN1_HDR) {
+       } else if (module_sel == VDIN1_HDR) {
                cgain_lut_addr_port = VDIN1_CGAIN_LUT_ADDR_PORT;
                cgain_lut_data_port = VDIN1_CGAIN_LUT_DATA_PORT;
                hdr_ctrl = VDIN1_HDR2_CTRL;
@@ -1781,12 +2068,21 @@ void set_c_gain(
        /*cgain mode: 0->y domin*/
        /*cgain mode: 1->rgb domin, use r/g/b max*/
        if ((is_meson_g12b_cpu() && is_meson_rev_b()) &&
-               (module_sel & OSD1_HDR)) {
+               (module_sel == OSD1_HDR)) {
                _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl,
-                       hdr_lut_param->cgain_en, 12, 1);
+                       0, 12, 1);
                _VSYNC_WR_MPEG_REG_BITS(hdr_ctrl,
                        hdr_lut_param->cgain_en, 0, 1);
 
+               if (cpu_after_eq(MESON_CPU_MAJOR_ID_SM1)) {
+                       if (hdr_lut_param->bitdepth == 10)
+                               _VSYNC_WR_MPEG_REG_BITS(cgain_coef1,
+                                       0x400, 16, 13);
+                       else if (hdr_lut_param->bitdepth == 12)
+                               _VSYNC_WR_MPEG_REG_BITS(cgain_coef1,
+                                       0x1000, 16, 13);
+               }
+
                if (!hdr_lut_param->cgain_en)
                        return;
 
@@ -1797,16 +2093,18 @@ void set_c_gain(
                _VSYNC_WR_MPEG_REG(cgain_lut_data_port, lut[64]);
                return;
        }
-
-       /*cgain mode force 0*/
-       VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, 0, 12, 1);
-       VSYNC_WR_MPEG_REG_BITS(hdr_ctrl, hdr_lut_param->cgain_en, 0, 1);
+       VSYNC_WR_MPEG_REG_BITS(hdr_ctrl,
+               0, 12, 1);
+       VSYNC_WR_MPEG_REG_BITS(hdr_ctrl,
+               hdr_lut_param->cgain_en, 0, 1);
 
        if (cpu_after_eq(MESON_CPU_MAJOR_ID_SM1)) {
                if (hdr_lut_param->bitdepth == 10)
-                       VSYNC_WR_MPEG_REG_BITS(cgain_coef1, 0x400, 16, 13);
+                       VSYNC_WR_MPEG_REG_BITS(cgain_coef1,
+                               0x400, 16, 13);
                else if (hdr_lut_param->bitdepth == 12)
-                       VSYNC_WR_MPEG_REG_BITS(cgain_coef1, 0x1000, 16, 13);
+                       VSYNC_WR_MPEG_REG_BITS(cgain_coef1,
+                               0x1000, 16, 13);
        }
 
        if (!hdr_lut_param->cgain_en)
@@ -1821,22 +2119,49 @@ void set_c_gain(
 
 struct hdr_proc_lut_param_s hdr_lut_param;
 
-void hdr_func(enum hdr_module_sel module_sel,
-       enum hdr_process_sel hdr_process_select)
+enum hdr_process_sel hdr_func(enum hdr_module_sel module_sel,
+       enum hdr_process_sel hdr_process_select,
+       struct vinfo_s *vinfo)
 {
        int bit_depth;
        unsigned int i = 0;
        struct hdr_proc_mtx_param_s hdr_mtx_param;
+       int output_mode;
+       bool mtx_only_mode = false;
 
        memset(&hdr_mtx_param, 0, sizeof(struct hdr_proc_mtx_param_s));
        memset(&hdr_lut_param, 0, sizeof(struct hdr_proc_lut_param_s));
 
-       if (module_sel & (VD1_HDR | VD2_HDR | OSD1_HDR))
+       if ((module_sel == OSD1_HDR)
+       && (is_meson_g12() || is_meson_sm1_cpu() || is_meson_tl1_cpu())) {
+               /* turn off OSD mtx and use HDR for g12, sm1, tl1 */
+               VSYNC_WR_MPEG_REG(
+                       VPP_WRAP_OSD1_MATRIX_EN_CTRL, 0);
+               if (!is_dolby_vision_on()) {
+                       if (hdr_process_select == HDR_BYPASS)
+                               hdr_process_select = RGB_YUV;
+                       else if (hdr_process_select == SDR_HDR)
+                               hdr_process_select = RGB_HDR;
+                       else if (hdr_process_select == SDR_HLG)
+                               hdr_process_select = RGB_HLG;
+                       /* use in_mtx for g12b rev b, sm1, tl1 */
+                       if (hdr_process_select == RGB_YUV
+                       && (is_meson_sm1_cpu() || is_meson_tl1_cpu()
+                       || (is_meson_g12b_cpu() && is_meson_rev_b())))
+                               mtx_only_mode = true;
+               }
+       }
+
+       if (module_sel == VD1_HDR ||
+               module_sel == VD2_HDR ||
+               module_sel == OSD1_HDR)
                bit_depth = 12;
-       else if (module_sel & (VDIN0_HDR | VDIN1_HDR | DI_HDR))
+       else if (module_sel == VDIN0_HDR
+               || module_sel == VDIN1_HDR
+               || module_sel == DI_HDR)
                bit_depth = 10;
        else
-               return;
+               return hdr_process_select;
 
        if (is_meson_tl1_cpu())
                bit_depth = 10;
@@ -1846,7 +2171,8 @@ void hdr_func(enum hdr_module_sel module_sel,
                sld_eotf, sld_oetf, hlg_eotf, hlg_oetf, ootf_gain,
                nolinear_cgain, hlg_gain};
 
-       if (hdr_process_select & HDR_BYPASS) {
+       if (hdr_process_select == HDR_BYPASS
+       || hdr_process_select == HDR_OFF) {
                /*lut parameters*/
                eotf_float_gen(hdr_lut_param.eotf_lut, fun[2]);
                oetf_float_gen(hdr_lut_param.oetf_lut, fun[1]);
@@ -1854,7 +2180,7 @@ void hdr_func(enum hdr_module_sel module_sel,
                nolinear_lut_gen(hdr_lut_param.cgain_lut, fun[9]);
                hdr_lut_param.lut_on = LUT_OFF;
                hdr_lut_param.bitdepth = bit_depth;
-       } else if (hdr_process_select & HDR_SDR) {
+       } else if (hdr_process_select == HDR_SDR) {
                /*lut parameters*/
                eotf_float_gen(hdr_lut_param.eotf_lut, fun[2]);
                oetf_float_gen(hdr_lut_param.oetf_lut, fun[1]);
@@ -1862,7 +2188,7 @@ void hdr_func(enum hdr_module_sel module_sel,
                nolinear_lut_gen(hdr_lut_param.cgain_lut, fun[9]);
                hdr_lut_param.lut_on = LUT_ON;
                hdr_lut_param.bitdepth = bit_depth;
-       } else if (hdr_process_select & SDR_HDR) {
+       } else if (hdr_process_select == SDR_HDR) {
                /*lut parameters*/
                eotf_float_gen(hdr_lut_param.eotf_lut, fun[2]);
                oetf_float_gen(hdr_lut_param.oetf_lut, fun[1]);
@@ -1871,59 +2197,45 @@ void hdr_func(enum hdr_module_sel module_sel,
                hdr_lut_param.lut_on = LUT_ON;
                hdr_lut_param.bitdepth = bit_depth;
        } else
-               return;
+               return hdr_process_select;
 #else
        /*lut parameters*/
-       if (hdr_process_select & HDR_BYPASS) {
-               /*for g12a/g12b osd blend shift rtl bug*/
-               if ((is_meson_g12a_cpu() ||
-                       (is_meson_g12b_cpu() && is_meson_rev_a())) &&
-                       (module_sel & OSD1_HDR)) {
-                       for (i = 0; i < HDR2_OETF_LUT_SIZE; i++) {
-                               hdr_lut_param.oetf_lut[i]  = oe_y_lut_bypass[i];
-                               hdr_lut_param.ogain_lut[i] = oo_y_lut_bypass[i];
-                               if (i < HDR2_EOTF_LUT_SIZE)
-                                       hdr_lut_param.eotf_lut[i] =
-                                               eo_y_lut_bypass[i];
-                               if (i < HDR2_CGAIN_LUT_SIZE)
-                                       hdr_lut_param.cgain_lut[i] =
-                                               cgain_lut_bypass[i] - 1;
-                       }
-                       hdr_lut_param.lut_on = LUT_ON;
-                       hdr_lut_param.bitdepth = bit_depth;
-                       hdr_lut_param.cgain_en = LUT_ON;
-               } else {
-                       for (i = 0; i < HDR2_OETF_LUT_SIZE; i++) {
-                               hdr_lut_param.oetf_lut[i]  = oe_y_lut_sdr[i];
-                               hdr_lut_param.ogain_lut[i] =
-                                       oo_y_lut_hdr_sdr[i];
-                               if (i < HDR2_EOTF_LUT_SIZE)
-                                       hdr_lut_param.eotf_lut[i] =
-                                               eo_y_lut_hdr[i];
-                               if (i < HDR2_CGAIN_LUT_SIZE)
-                                       hdr_lut_param.cgain_lut[i] =
-                                               cgain_lut1[i] - 1;
-                       }
+       if (hdr_process_select == RGB_YUV) {
+               for (i = 0; i < HDR2_OETF_LUT_SIZE; i++) {
+                       hdr_lut_param.oetf_lut[i] =     oe_y_lut_bypass[i];
+                       hdr_lut_param.ogain_lut[i] = oo_y_lut_bypass[i];
+                       if (i < HDR2_EOTF_LUT_SIZE)
+                               hdr_lut_param.eotf_lut[i] =
+                                       eo_y_lut_bypass[i];
+                       if (i < HDR2_CGAIN_LUT_SIZE)
+                               hdr_lut_param.cgain_lut[i] =
+                                       cgain_lut_bypass[i] - 1;
+               }
+               hdr_lut_param.bitdepth = bit_depth;
+               if (mtx_only_mode) {
                        hdr_lut_param.lut_on = LUT_OFF;
-                       hdr_lut_param.bitdepth = bit_depth;
                        hdr_lut_param.cgain_en = LUT_OFF;
+               } else {
+                       hdr_lut_param.lut_on = LUT_ON;
+                       hdr_lut_param.cgain_en = LUT_ON;
                }
-       } else if (hdr_process_select & HDR_SDR) {
+       } else if (hdr_process_select == RGB_HDR) {
                for (i = 0; i < HDR2_OETF_LUT_SIZE; i++) {
-                       hdr_lut_param.oetf_lut[i]  = oe_y_lut_sdr[i];
-                       hdr_lut_param.ogain_lut[i] = oo_y_lut_hdr_sdr[i];
+                       hdr_lut_param.oetf_lut[i]  = oe_y_lut_hdr[i];
+                       hdr_lut_param.ogain_lut[i] = oo_y_lut_sdr_hdr[i];
                        if (i < HDR2_EOTF_LUT_SIZE)
-                               hdr_lut_param.eotf_lut[i] = eo_y_lut_hdr[i];
+                               hdr_lut_param.eotf_lut[i] =     eo_y_lut_sdr[i];
                        if (i < HDR2_CGAIN_LUT_SIZE)
-                               hdr_lut_param.cgain_lut[i] = cgain_lut1[i] - 1;
+                               hdr_lut_param.cgain_lut[i] =
+                                       cgain_lut_bypass[i] - 1;
                }
-               hdr_lut_param.lut_on = LUT_ON;
                hdr_lut_param.bitdepth = bit_depth;
+               hdr_lut_param.lut_on = LUT_ON;
                hdr_lut_param.cgain_en = LUT_ON;
-       } else if (hdr_process_select & SDR_HDR) {
+       } else if (hdr_process_select == RGB_HLG) {
                for (i = 0; i < HDR2_OETF_LUT_SIZE; i++) {
-                       hdr_lut_param.oetf_lut[i]  = oe_y_lut_hdr[i];
-                       hdr_lut_param.ogain_lut[i] = oo_y_lut_sdr_hdr[i];
+                       hdr_lut_param.oetf_lut[i]  = oe_y_lut_hlg[i];
+                       hdr_lut_param.ogain_lut[i] = oo_y_lut_sdr_hlg[i];
                        if (i < HDR2_EOTF_LUT_SIZE)
                                hdr_lut_param.eotf_lut[i] = eo_y_lut_sdr[i];
                        if (i < HDR2_CGAIN_LUT_SIZE)
@@ -1932,26 +2244,48 @@ void hdr_func(enum hdr_module_sel module_sel,
                }
                hdr_lut_param.lut_on = LUT_ON;
                hdr_lut_param.bitdepth = bit_depth;
-               /*for g12a/g12b osd blend shift rtl bug*/
-               if ((is_meson_g12a_cpu() ||
-                       (is_meson_g12b_cpu() && is_meson_rev_a())) &&
-                       (module_sel & OSD1_HDR))
-                       hdr_lut_param.cgain_en = LUT_ON;
-               else
-                       hdr_lut_param.cgain_en = LUT_OFF;
-       } else if (hdr_process_select & HLG_BYPASS) {
+               hdr_lut_param.cgain_en = LUT_ON;
+       } else if (hdr_process_select == HDR_BYPASS
+       || hdr_process_select == HLG_BYPASS) {
+               for (i = 0; i < HDR2_OETF_LUT_SIZE; i++) {
+                       hdr_lut_param.oetf_lut[i] =     oe_y_lut_bypass[i];
+                       hdr_lut_param.ogain_lut[i] = oo_y_lut_bypass[i];
+                       if (i < HDR2_EOTF_LUT_SIZE)
+                               hdr_lut_param.eotf_lut[i] =
+                                       eo_y_lut_bypass[i];
+                       if (i < HDR2_CGAIN_LUT_SIZE)
+                               hdr_lut_param.cgain_lut[i] =
+                                       cgain_lut_bypass[i] - 1;
+               }
+               hdr_lut_param.lut_on = LUT_OFF;
+               hdr_lut_param.bitdepth = bit_depth;
+               hdr_lut_param.cgain_en = LUT_OFF;
+       } else if (hdr_process_select == HDR_SDR) {
                for (i = 0; i < HDR2_OETF_LUT_SIZE; i++) {
                        hdr_lut_param.oetf_lut[i]  = oe_y_lut_sdr[i];
                        hdr_lut_param.ogain_lut[i] = oo_y_lut_hdr_sdr[i];
                        if (i < HDR2_EOTF_LUT_SIZE)
-                               hdr_lut_param.eotf_lut[i] = eo_y_lut_hlg[i];
+                               hdr_lut_param.eotf_lut[i] = eo_y_lut_hdr[i];
                        if (i < HDR2_CGAIN_LUT_SIZE)
                                hdr_lut_param.cgain_lut[i] = cgain_lut1[i] - 1;
                }
-               hdr_lut_param.lut_on = LUT_OFF;
+               hdr_lut_param.lut_on = LUT_ON;
                hdr_lut_param.bitdepth = bit_depth;
                hdr_lut_param.cgain_en = LUT_OFF;
-       } else if (hdr_process_select & HLG_SDR) {
+       } else if (hdr_process_select == SDR_HDR) {
+               for (i = 0; i < HDR2_OETF_LUT_SIZE; i++) {
+                       hdr_lut_param.oetf_lut[i]  = oe_y_lut_hdr[i];
+                       hdr_lut_param.ogain_lut[i] = oo_y_lut_sdr_hdr[i];
+                       if (i < HDR2_EOTF_LUT_SIZE)
+                               hdr_lut_param.eotf_lut[i] = eo_y_lut_sdr[i];
+                       if (i < HDR2_CGAIN_LUT_SIZE)
+                               hdr_lut_param.cgain_lut[i] =
+                                       cgain_lut_bypass[i] - 1;
+               }
+               hdr_lut_param.lut_on = LUT_ON;
+               hdr_lut_param.bitdepth = bit_depth;
+               hdr_lut_param.cgain_en = LUT_OFF;
+       } else if (hdr_process_select == HLG_SDR) {
                for (i = 0; i < HDR2_OETF_LUT_SIZE; i++) {
                        hdr_lut_param.oetf_lut[i]  = oe_y_lut_sdr[i];
                        hdr_lut_param.ogain_lut[i] = oo_y_lut_hlg_sdr[i];
@@ -1962,8 +2296,8 @@ void hdr_func(enum hdr_module_sel module_sel,
                }
                hdr_lut_param.lut_on = LUT_ON;
                hdr_lut_param.bitdepth = bit_depth;
-               hdr_lut_param.cgain_en = LUT_ON;
-       } else if (hdr_process_select & HLG_HDR) {
+               hdr_lut_param.cgain_en = LUT_OFF;
+       } else if (hdr_process_select == HLG_HDR) {
                for (i = 0; i < HDR2_OETF_LUT_SIZE; i++) {
                        hdr_lut_param.oetf_lut[i]  = oe_y_lut_hdr[i];
                        hdr_lut_param.ogain_lut[i] = oo_y_lut_hlg_hdr[i];
@@ -1975,7 +2309,7 @@ void hdr_func(enum hdr_module_sel module_sel,
                hdr_lut_param.lut_on = LUT_ON;
                hdr_lut_param.bitdepth = bit_depth;
                hdr_lut_param.cgain_en = LUT_ON;
-       } else if (hdr_process_select & SDR_HLG) {
+       } else if (hdr_process_select == SDR_HLG) {
                for (i = 0; i < HDR2_OETF_LUT_SIZE; i++) {
                        hdr_lut_param.oetf_lut[i]  = oe_y_lut_hlg[i];
                        hdr_lut_param.ogain_lut[i] = oo_y_lut_sdr_hlg[i];
@@ -1987,57 +2321,138 @@ void hdr_func(enum hdr_module_sel module_sel,
                }
                hdr_lut_param.lut_on = LUT_ON;
                hdr_lut_param.bitdepth = bit_depth;
-               /*for g12a/g12b osd blend shift rtl bug*/
-               if ((is_meson_g12a_cpu() ||
-                       (is_meson_g12b_cpu() && is_meson_rev_a())) &&
-                       (module_sel & OSD1_HDR))
-                       hdr_lut_param.cgain_en = LUT_ON;
-               else
-                       hdr_lut_param.cgain_en = LUT_OFF;
+               hdr_lut_param.cgain_en = LUT_OFF;
+       } else if (hdr_process_select == SDR_IPT) {
+               for (i = 0; i < HDR2_OETF_LUT_SIZE; i++) {
+                       hdr_lut_param.oetf_lut[i]  = oe_y_lut_hdr[i];
+                       output_mode = get_dolby_vision_mode();
+                       if (output_mode == DOLBY_VISION_OUTPUT_MODE_SDR10 ||
+                       output_mode == DOLBY_VISION_OUTPUT_MODE_SDR8)
+                               hdr_lut_param.ogain_lut[i] =
+                                       oo_y_lut_sdr_hdr_250[i];
+                       else if (output_mode == DOLBY_VISION_OUTPUT_MODE_HDR10)
+                               hdr_lut_param.ogain_lut[i] =
+                                       oo_y_lut_sdr_hdr_250[i];
+                       else if (output_mode == DOLBY_VISION_OUTPUT_MODE_IPT ||
+                       output_mode == DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL)
+                               hdr_lut_param.ogain_lut[i] =
+                                       oo_y_lut_sdr_hdr_300[i];
+                       if (i < HDR2_EOTF_LUT_SIZE)
+                               hdr_lut_param.eotf_lut[i] = eo_y_lut_sdr[i];
+                       if (i < HDR2_CGAIN_LUT_SIZE)
+                               hdr_lut_param.cgain_lut[i] =
+                                       cgain_lut0[i] - 1;
+               }
+               //pr_info("\t oo_gain = %lld of 512\n",
+               //      hdr_lut_param.ogain_lut[0]);
+               hdr_lut_param.lut_on = LUT_ON;
+               hdr_lut_param.bitdepth = bit_depth;
+               hdr_lut_param.cgain_en = LUT_ON;
+       } else if (hdr_process_select == HLG_IPT) {
+               for (i = 0; i < HDR2_OETF_LUT_SIZE; i++) {
+                       hdr_lut_param.oetf_lut[i]  = oe_y_lut_hdr[i];
+                       // hdr_lut_param.ogain_lut[i] = oo_y_lut_bypass[i];
+                       output_mode = get_dolby_vision_mode();
+                       if (output_mode == DOLBY_VISION_OUTPUT_MODE_SDR10 ||
+                       output_mode == DOLBY_VISION_OUTPUT_MODE_SDR8)
+                               hdr_lut_param.ogain_lut[i] =
+                                       oo_y_lut_hdr_hdr_1200[i];
+                       else if (output_mode ==
+                       DOLBY_VISION_OUTPUT_MODE_HDR10)
+                               hdr_lut_param.ogain_lut[i] =
+                                       oo_y_lut_hdr_hdr_2500[i];
+                       else if (output_mode == DOLBY_VISION_OUTPUT_MODE_IPT ||
+                       output_mode == DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL)
+                               hdr_lut_param.ogain_lut[i] =
+                                       oo_y_lut_hdr_hdr_4000[i];
+                       if (i < HDR2_EOTF_LUT_SIZE)
+                               hdr_lut_param.eotf_lut[i] = eo_y_lut_hlg[i];
+                       if (i < HDR2_CGAIN_LUT_SIZE)
+                               hdr_lut_param.cgain_lut[i] =
+                                       cgain_lut0[i] - 1;
+               }
+               //pr_info("\t oo_gain = %lld of 512\n",
+               //      hdr_lut_param.ogain_lut[0]);
+               hdr_lut_param.lut_on = LUT_ON;
+               hdr_lut_param.bitdepth = bit_depth;
+               hdr_lut_param.cgain_en = LUT_ON;
+       } else if (hdr_process_select == HDR_IPT) {
+               for (i = 0; i < HDR2_OETF_LUT_SIZE; i++) {
+                       hdr_lut_param.oetf_lut[i]  = oe_y_lut_hdr[i];
+                       output_mode = get_dolby_vision_mode();
+                       if (output_mode == DOLBY_VISION_OUTPUT_MODE_SDR10 ||
+                       output_mode == DOLBY_VISION_OUTPUT_MODE_SDR8)
+                               hdr_lut_param.ogain_lut[i] =
+                                       oo_y_lut_hdr_hdr_1200[i];
+                       else if (output_mode == DOLBY_VISION_OUTPUT_MODE_HDR10)
+                               hdr_lut_param.ogain_lut[i] =
+                                       oo_y_lut_bypass[i];
+                       else if (output_mode == DOLBY_VISION_OUTPUT_MODE_IPT ||
+                       output_mode == DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL)
+                               hdr_lut_param.ogain_lut[i] =
+                                       oo_y_lut_bypass[i];
+                       if (i < HDR2_EOTF_LUT_SIZE)
+                               hdr_lut_param.eotf_lut[i] = eo_y_lut_pq[i];
+                       if (i < HDR2_CGAIN_LUT_SIZE)
+                               hdr_lut_param.cgain_lut[i] =
+                                       cgain_lut1[i] - 1;
+               }
+               //pr_info("\t oo_gain = %lld of 512\n",
+               //      hdr_lut_param.ogain_lut[0]);
+               hdr_lut_param.lut_on = LUT_ON;
+               hdr_lut_param.bitdepth = bit_depth;
+               hdr_lut_param.cgain_en = LUT_ON;
+       } else if (hdr_process_select == HDR_HLG) {
+               for (i = 0; i < HDR2_OETF_LUT_SIZE; i++) {
+                       hdr_lut_param.oetf_lut[i]  = oe_y_lut_hlg[i];
+                       hdr_lut_param.ogain_lut[i] = oo_y_lut_hdr_hlg[i];
+                       if (i < HDR2_EOTF_LUT_SIZE)
+                               hdr_lut_param.eotf_lut[i] = eo_y_lut_pq[i];
+                       if (i < HDR2_CGAIN_LUT_SIZE)
+                               hdr_lut_param.cgain_lut[i] = cgain_lut1[i] - 1;
+               }
+               //pr_info("\t oo_gain = %lld of 512\n",
+               //      hdr_lut_param.ogain_lut[0]);
+               hdr_lut_param.lut_on = LUT_ON;
+               hdr_lut_param.bitdepth = bit_depth;
+               hdr_lut_param.cgain_en = LUT_OFF;
        } else
-               return;
+               return hdr_process_select;
+#ifdef HDR2_PRINT
+       pr_info("hdr: oo_gain %d = %lld-%lld-%lld, c_gain %d = %lld-%lld-%lld\n",
+               hdr_lut_param.lut_on,
+               hdr_lut_param.ogain_lut[0], hdr_lut_param.ogain_lut[74],
+               hdr_lut_param.ogain_lut[148],
+               hdr_lut_param.cgain_en,
+               hdr_lut_param.cgain_lut[0], hdr_lut_param.cgain_lut[32],
+               hdr_lut_param.cgain_lut[64]);
+#endif
 #endif
        /*mtx parameters*/
-       if (hdr_process_select & (HDR_BYPASS | HLG_BYPASS)) {
-               hdr_mtx_param.mtx_only = HDR_ONLY;
-               /*for g12a/g12b osd blend shift rtl bug*/
-               if ((is_meson_g12a_cpu() ||
-                       (is_meson_g12b_cpu() && is_meson_rev_a())) &&
-                       (module_sel & OSD1_HDR)) {
-                       for (i = 0; i < 15; i++) {
-                               hdr_mtx_param.mtx_in[i] = bypass_coeff[i];
-                               hdr_mtx_param.mtx_cgain[i] = bypass_coeff[i];
-                               hdr_mtx_param.mtx_ogain[i] = bypass_coeff[i];
-                               hdr_mtx_param.mtx_out[i] = rgb2ycbcr_709[i];
-                               if (i < 9)
-                                       hdr_mtx_param.mtx_gamut[i] =
-                                               bypass_coeff[i];
-                               if (i < 3) {
-                                       hdr_mtx_param.mtxi_pre_offset[i] =
-                                               bypass_pre[i];
-                                       hdr_mtx_param.mtxi_pos_offset[i] =
-                                               bypass_pos[i];
-                                       hdr_mtx_param.mtxo_pre_offset[i] =
-                                               rgb2yuvpre[i];
-                                       hdr_mtx_param.mtxo_pos_offset[i] =
-                                               rgb2yuvpos[i];
-                               }
-                       }
-                       hdr_mtx_param.mtx_on = MTX_ON;
-                       hdr_mtx_param.p_sel = HDR_BYPASS;
-               } else if ((is_meson_sm1_cpu() ||
-                       is_meson_tl1_cpu() ||
-                       (is_meson_g12b_cpu() && is_meson_rev_b())) &&
-                       (module_sel & OSD1_HDR)) {
-                       /*for rtl bug osd1 green line at the bottom*/
-                       for (i = 0; i < 15; i++) {
+       /* default pre/post in:yuv_rgb out:rgb_yuv */
+       for (i = 0; i < 3; i++) {
+               hdr_mtx_param.mtxi_pre_offset[i] =
+                       yuv2rgbpre[i];
+               hdr_mtx_param.mtxi_pos_offset[i] =
+                       yuv2rgbpos[i];
+               hdr_mtx_param.mtxo_pre_offset[i] =
+                       rgb2yuvpre[i];
+               hdr_mtx_param.mtxo_pos_offset[i] =
+                       rgb2yuvpos[i];
+       }
+
+       if (hdr_process_select == RGB_YUV) {
+               hdr_mtx_param.mtx_gamut_mode = 1;
+               if (mtx_only_mode) {
+                       hdr_mtx_param.mtx_only = MTX_ONLY;
+                       for (i = 0; i < MTX_NUM_PARAM; i++) {
                                hdr_mtx_param.mtx_in[i] = rgb2ycbcr_709[i];
                                hdr_mtx_param.mtx_cgain[i] = bypass_coeff[i];
                                hdr_mtx_param.mtx_ogain[i] = bypass_coeff[i];
                                hdr_mtx_param.mtx_out[i] = bypass_coeff[i];
                                if (i < 9)
                                        hdr_mtx_param.mtx_gamut[i] =
-                                               bypass_coeff[i];
+                                               gamut_bypass[i];
                                if (i < 3) {
                                        hdr_mtx_param.mtxi_pre_offset[i] =
                                                rgb2yuvpre[i];
@@ -2050,180 +2465,182 @@ void hdr_func(enum hdr_module_sel module_sel,
                                }
                        }
                        hdr_mtx_param.mtx_on = MTX_OFF;
-                       hdr_mtx_param.p_sel = HDR_BYPASS;
-                       hdr_mtx_param.mtx_only = MTX_ONLY;
                } else {
-                       for (i = 0; i < 15; i++) {
+                       hdr_mtx_param.mtx_only = HDR_ONLY;
+                       for (i = 0; i < MTX_NUM_PARAM; i++) {
                                hdr_mtx_param.mtx_in[i] = bypass_coeff[i];
                                hdr_mtx_param.mtx_cgain[i] = bypass_coeff[i];
                                hdr_mtx_param.mtx_ogain[i] = bypass_coeff[i];
-                               hdr_mtx_param.mtx_out[i] = bypass_coeff[i];
+                               hdr_mtx_param.mtx_out[i] = rgb2ycbcr_709[i];
                                if (i < 9)
                                        hdr_mtx_param.mtx_gamut[i] =
-                                               bypass_coeff[i];
+                                               gamut_bypass[i];
                                if (i < 3) {
                                        hdr_mtx_param.mtxi_pre_offset[i] =
                                                bypass_pre[i];
                                        hdr_mtx_param.mtxi_pos_offset[i] =
-                                               bypass_pre[i];
-                                       hdr_mtx_param.mtxo_pre_offset[i] =
-                                               bypass_pre[i];
-                                       hdr_mtx_param.mtxo_pos_offset[i] =
                                                bypass_pos[i];
                                }
                        }
-                       hdr_mtx_param.mtx_on = MTX_OFF;
-                       hdr_mtx_param.p_sel = HDR_BYPASS;
+                       hdr_mtx_param.mtx_on = MTX_ON;
                }
-       } else if (hdr_process_select & (HDR_SDR | HLG_SDR)) {
+               hdr_mtx_param.p_sel = RGB_YUV;
+       } else if (hdr_process_select == RGB_HDR ||
+       (hdr_process_select == RGB_HLG)) {
+               hdr_mtx_param.mtx_gamut_mode = 1;
                hdr_mtx_param.mtx_only = HDR_ONLY;
-               for (i = 0; i < 15; i++) {
-                       hdr_mtx_param.mtx_in[i] = ycbcr2rgb_ncl2020[i];
-                       hdr_mtx_param.mtx_cgain[i] = rgb2ycbcr_709[i];
-                       hdr_mtx_param.mtx_ogain[i] = rgb2ycbcr_ncl2020[i];
-                       hdr_mtx_param.mtx_out[i] = rgb2ycbcr_709[i];
-                       if (i < 9) {
-                               if (hdr_process_select & HLG_SDR)
-                                       hdr_mtx_param.mtx_gamut[i] =
-                                               ncl_2020_709[i];
-                               else
-                                       hdr_mtx_param.mtx_gamut[i] =
-                                               ncl_2020_p3[i];
-                       }
+               for (i = 0; i < MTX_NUM_PARAM; i++) {
+                       hdr_mtx_param.mtx_in[i] = bypass_coeff[i];
+                       hdr_mtx_param.mtx_cgain[i] =
+                               rgb2ycbcr_ncl2020[i];
+                       hdr_mtx_param.mtx_ogain[i] = rgb2ycbcr_709[i];
+                       hdr_mtx_param.mtx_out[i] = rgb2ycbcr_ncl2020[i];
+                       if (i < 9)
+                               hdr_mtx_param.mtx_gamut[i] =
+                                       ncl_709_2020[i];
                        if (i < 3) {
                                hdr_mtx_param.mtxi_pre_offset[i] =
-                                       yuv2rgbpre[i];
+                                       bypass_pre[i];
                                hdr_mtx_param.mtxi_pos_offset[i] =
-                                       yuv2rgbpos[i];
-                               hdr_mtx_param.mtxo_pre_offset[i] =
-                                       rgb2yuvpre[i];
-                               hdr_mtx_param.mtxo_pos_offset[i] =
-                                       rgb2yuvpos[i];
+                                       bypass_pos[i];
                        }
                }
                hdr_mtx_param.mtx_on = MTX_ON;
+               hdr_mtx_param.p_sel = hdr_process_select;
+       } else if (hdr_process_select == HDR_BYPASS ||
+       hdr_process_select == HLG_BYPASS) {
+               hdr_mtx_param.mtx_only = HDR_ONLY;
+               hdr_mtx_param.mtx_gamut_mode = 1;
 
-               if (hdr_process_select & HDR_SDR)
-                       hdr_mtx_param.p_sel = HDR_SDR;
-               else if (hdr_process_select & HLG_SDR)
-                       hdr_mtx_param.p_sel = HLG_SDR;
-
-       } else if (hdr_process_select & SDR_HDR) {
+               for (i = 0; i < MTX_NUM_PARAM; i++) {
+                       hdr_mtx_param.mtx_in[i] = bypass_coeff[i];
+                       hdr_mtx_param.mtx_cgain[i] = bypass_coeff[i];
+                       hdr_mtx_param.mtx_ogain[i] = bypass_coeff[i];
+                       hdr_mtx_param.mtx_out[i] = bypass_coeff[i];
+                       if (i < 9)
+                               hdr_mtx_param.mtx_gamut[i] =
+                                       gamut_bypass[i];
+               }
+               hdr_mtx_param.mtx_on = MTX_OFF;
+               hdr_mtx_param.p_sel = hdr_process_select;
+       } else if (hdr_process_select == HDR_SDR ||
+               hdr_process_select == HLG_SDR) {
                hdr_mtx_param.mtx_only = HDR_ONLY;
-               if ((is_meson_sm1_cpu() ||
-                       is_meson_tl1_cpu() ||
-                       is_meson_g12b_cpu() ||
-                       is_meson_g12a_cpu()) &&
-                       (module_sel & OSD1_HDR)) {
-                       /*for rtl bug osd1 green line at the bottom*/
-                       for (i = 0; i < 15; i++) {
-                               hdr_mtx_param.mtx_in[i] = bypass_coeff[i];
-                               hdr_mtx_param.mtx_cgain[i] =
-                                       rgb2ycbcr_ncl2020[i];
-                               hdr_mtx_param.mtx_ogain[i] = rgb2ycbcr_709[i];
-                               hdr_mtx_param.mtx_out[i] = rgb2ycbcr_ncl2020[i];
-                               if (i < 9)
+               hdr_mtx_param.mtx_gamut_mode = 1;
+               for (i = 0; i < MTX_NUM_PARAM; i++) {
+                       hdr_mtx_param.mtx_in[i] = ycbcr2rgb_ncl2020[i];
+                       hdr_mtx_param.mtx_cgain[i] = rgb2ycbcr_709[i];
+                       hdr_mtx_param.mtx_ogain[i] = rgb2ycbcr_709[i];
+                       hdr_mtx_param.mtx_out[i] = rgb2ycbcr_709[i];
+                       if (i < 9) {
+                               if (hdr_process_select == HLG_SDR) {
                                        hdr_mtx_param.mtx_gamut[i] =
-                                       ncl_709_2020[i];
-                               if (i < 3) {
-                                       hdr_mtx_param.mtxi_pre_offset[i] =
-                                               bypass_pre[i];
-                                       hdr_mtx_param.mtxi_pos_offset[i] =
-                                               bypass_pos[i];
-                                       hdr_mtx_param.mtxo_pre_offset[i] =
-                                               rgb2yuvpre[i];
-                                       hdr_mtx_param.mtxo_pos_offset[i] =
-                                               rgb2yuvpos[i];
-                               }
-                       }
-               } else {
-                       for (i = 0; i < 15; i++) {
-                               hdr_mtx_param.mtx_in[i] = ycbcr2rgb_709[i];
-                               hdr_mtx_param.mtx_cgain[i] =
-                                       rgb2ycbcr_ncl2020[i];
-                               hdr_mtx_param.mtx_ogain[i] = rgb2ycbcr_709[i];
-                               hdr_mtx_param.mtx_out[i] = rgb2ycbcr_ncl2020[i];
-                               if (i < 9)
+                                               ncl_2020_709[i];
+                               } else {
                                        hdr_mtx_param.mtx_gamut[i] =
-                                       ncl_709_2020[i];
-                               if (i < 3) {
-                                       hdr_mtx_param.mtxi_pre_offset[i] =
-                                               yuv2rgbpre[i];
-                                       hdr_mtx_param.mtxi_pos_offset[i] =
-                                               yuv2rgbpos[i];
-                                       hdr_mtx_param.mtxo_pre_offset[i] =
-                                               rgb2yuvpre[i];
-                                       hdr_mtx_param.mtxo_pos_offset[i] =
-                                               rgb2yuvpos[i];
+                                               ncl_2020_p3[i]; /* 1.0 = 256 */
                                }
                        }
                }
                hdr_mtx_param.mtx_on = MTX_ON;
+               hdr_mtx_param.p_sel = hdr_process_select;
+       } else if (hdr_process_select == HDR_HLG) {
+               hdr_mtx_param.mtx_only = HDR_ONLY;
+               hdr_mtx_param.mtx_gamut_mode = 1;
+               for (i = 0; i < MTX_NUM_PARAM; i++) {
+                       hdr_mtx_param.mtx_in[i] = ycbcr2rgb_ncl2020[i];
+                       hdr_mtx_param.mtx_cgain[i] = rgb2ycbcr_ncl2020[i];
+                       hdr_mtx_param.mtx_ogain[i] = rgb2ycbcr_ncl2020[i];
+                       hdr_mtx_param.mtx_out[i] = rgb2ycbcr_ncl2020[i];
+                       if (i < 9)
+                               hdr_mtx_param.mtx_gamut[i] =
+                                       gamut_bypass[i];
+               }
+               hdr_mtx_param.mtx_on = MTX_ON;
+               hdr_mtx_param.p_sel = HDR_HLG;
+       } else if (hdr_process_select == SDR_HDR) {
+               hdr_mtx_param.mtx_only = HDR_ONLY;
+               hdr_mtx_param.mtx_gamut_mode = 1;
+               for (i = 0; i < MTX_NUM_PARAM; i++) {
+                       hdr_mtx_param.mtx_in[i] = ycbcr2rgb_709[i];
+                       hdr_mtx_param.mtx_cgain[i] =
+                               rgb2ycbcr_ncl2020[i];
+                       hdr_mtx_param.mtx_ogain[i] = rgb2ycbcr_709[i];
+                       hdr_mtx_param.mtx_out[i] = rgb2ycbcr_ncl2020[i];
+                       if (i < 9)
+                               hdr_mtx_param.mtx_gamut[i] =
+                                       ncl_709_2020[i];
+               }
+               hdr_mtx_param.mtx_on = MTX_ON;
                hdr_mtx_param.p_sel = SDR_HDR;
-       } else if (hdr_process_select & HLG_HDR) {
+       } else if (hdr_process_select == HLG_HDR) {
                hdr_mtx_param.mtx_only = HDR_ONLY;
-               for (i = 0; i < 15; i++) {
+               hdr_mtx_param.mtx_gamut_mode = 1;
+               for (i = 0; i < MTX_NUM_PARAM; i++) {
                        hdr_mtx_param.mtx_in[i] = ycbcr2rgb_ncl2020[i];
                        hdr_mtx_param.mtx_cgain[i] = bypass_coeff[i];
                        hdr_mtx_param.mtx_ogain[i] = bypass_coeff[i];
                        hdr_mtx_param.mtx_out[i] = rgb2ycbcr_ncl2020[i];
                        if (i < 9)
-                               hdr_mtx_param.mtx_gamut[i] = bypass_coeff[i];
+                               hdr_mtx_param.mtx_gamut[i] = gamut_bypass[i];
                }
                hdr_mtx_param.mtx_on = MTX_ON;
                hdr_mtx_param.p_sel = HLG_HDR;
-       }  else if (hdr_process_select & SDR_HLG) {
+       }  else if (hdr_process_select == SDR_HLG) {
                hdr_mtx_param.mtx_only = HDR_ONLY;
-               if ((is_meson_sm1_cpu() ||
-                       is_meson_tl1_cpu() ||
-                       is_meson_g12b_cpu() ||
-                       is_meson_g12a_cpu()) &&
-                       (module_sel & OSD1_HDR)) {
-                       /*for rtl bug osd1 green line at the bottom*/
-                       for (i = 0; i < 15; i++) {
-                               hdr_mtx_param.mtx_in[i] = bypass_coeff[i];
-                               hdr_mtx_param.mtx_cgain[i] =
-                                       rgb2ycbcr_ncl2020[i];
-                               hdr_mtx_param.mtx_ogain[i] = rgb2ycbcr_709[i];
-                               hdr_mtx_param.mtx_out[i] = rgb2ycbcr_ncl2020[i];
-                               if (i < 9)
-                                       hdr_mtx_param.mtx_gamut[i] =
-                                       ncl_709_2020[i];
-                               if (i < 3) {
-                                       hdr_mtx_param.mtxi_pre_offset[i] =
-                                               bypass_pre[i];
-                                       hdr_mtx_param.mtxi_pos_offset[i] =
-                                               bypass_pos[i];
-                                       hdr_mtx_param.mtxo_pre_offset[i] =
-                                               rgb2yuvpre[i];
-                                       hdr_mtx_param.mtxo_pos_offset[i] =
-                                               rgb2yuvpos[i];
-                               }
-                       }
-               } else {
-                       for (i = 0; i < 15; i++) {
-                               hdr_mtx_param.mtx_in[i] = ycbcr2rgb_709[i];
-                               hdr_mtx_param.mtx_cgain[i] =
-                                       rgb2ycbcr_ncl2020[i];
-                               hdr_mtx_param.mtx_ogain[i] = rgb2ycbcr_709[i];
-                               hdr_mtx_param.mtx_out[i] = rgb2ycbcr_ncl2020[i];
-                               if (i < 9)
-                                       hdr_mtx_param.mtx_gamut[i] =
+               hdr_mtx_param.mtx_gamut_mode = 1;
+               for (i = 0; i < MTX_NUM_PARAM; i++) {
+                       hdr_mtx_param.mtx_in[i] = ycbcr2rgb_709[i];
+                       hdr_mtx_param.mtx_cgain[i] =
+                               rgb2ycbcr_ncl2020[i];
+                       hdr_mtx_param.mtx_ogain[i] = rgb2ycbcr_709[i];
+                       hdr_mtx_param.mtx_out[i] = rgb2ycbcr_ncl2020[i];
+                       if (i < 9)
+                               hdr_mtx_param.mtx_gamut[i] =
                                        ncl_709_2020[i];
-                               if (i < 3) {
-                                       hdr_mtx_param.mtxi_pre_offset[i] =
-                                               yuv2rgbpre[i];
-                                       hdr_mtx_param.mtxi_pos_offset[i] =
-                                               yuv2rgbpos[i];
-                                       hdr_mtx_param.mtxo_pre_offset[i] =
-                                               rgb2yuvpre[i];
-                                       hdr_mtx_param.mtxo_pos_offset[i] =
-                                               rgb2yuvpos[i];
-                               }
-                       }
                }
                hdr_mtx_param.mtx_on = MTX_ON;
                hdr_mtx_param.p_sel = SDR_HLG;
+       }  else if (hdr_process_select == SDR_IPT) {
+               hdr_mtx_param.mtx_only = HDR_ONLY;
+               hdr_mtx_param.mtx_gamut_mode = 2;
+               for (i = 0; i < MTX_NUM_PARAM; i++) {
+                       hdr_mtx_param.mtx_in[i] = ycbcr2rgb_709[i];
+                       hdr_mtx_param.mtx_cgain[i] = lms2ipt_ncl2020[i];
+                       hdr_mtx_param.mtx_ogain[i] = rgb2ycbcr_709[i];
+                       hdr_mtx_param.mtx_out[i] = lms2ipt_ncl2020[i];
+                       if (i < 9)
+                               hdr_mtx_param.mtx_gamut[i] =
+                                       rgb709_to_lms2020[i];
+               }
+               hdr_mtx_param.mtx_on = MTX_ON;
+               hdr_mtx_param.p_sel = SDR_IPT;
+       }  else if (hdr_process_select == HLG_IPT) {
+               hdr_mtx_param.mtx_only = HDR_ONLY;
+               hdr_mtx_param.mtx_gamut_mode = 2;
+               for (i = 0; i < MTX_NUM_PARAM; i++) {
+                       hdr_mtx_param.mtx_in[i] = ycbcr2rgb_ncl2020[i];
+                       hdr_mtx_param.mtx_cgain[i] = lms2ipt_ncl2020[i];
+                       hdr_mtx_param.mtx_ogain[i] = rgb2ycbcr_ncl2020[i];
+                       hdr_mtx_param.mtx_out[i] = lms2ipt_ncl2020[i];
+                       if (i < 9)
+                               hdr_mtx_param.mtx_gamut[i] = rgb2lms_ncl2020[i];
+               }
+               hdr_mtx_param.mtx_on = MTX_ON;
+               hdr_mtx_param.p_sel = HLG_IPT;
+       }  else if (hdr_process_select == HDR_IPT) {
+               hdr_mtx_param.mtx_only = HDR_ONLY;
+               hdr_mtx_param.mtx_gamut_mode = 2;
+               for (i = 0; i < MTX_NUM_PARAM; i++) {
+                       hdr_mtx_param.mtx_in[i] = ycbcr2rgb_ncl2020[i];
+                       hdr_mtx_param.mtx_cgain[i] = lms2ipt_ncl2020[i];
+                       hdr_mtx_param.mtx_ogain[i] = rgb2ycbcr_ncl2020[i];
+                       hdr_mtx_param.mtx_out[i] = lms2ipt_ncl2020[i];
+                       if (i < 9)
+                               hdr_mtx_param.mtx_gamut[i] = rgb2lms_ncl2020[i];
+               }
+               hdr_mtx_param.mtx_on = MTX_ON;
+               hdr_mtx_param.p_sel = HDR_IPT;
        }
 
        set_hdr_matrix(module_sel, HDR_IN_MTX, &hdr_mtx_param);
@@ -2239,6 +2656,8 @@ void hdr_func(enum hdr_module_sel module_sel,
        set_hdr_matrix(module_sel, HDR_OUT_MTX, &hdr_mtx_param);
 
        set_c_gain(module_sel, &hdr_lut_param);
+
+       return hdr_process_select;
 }
 
 /*G12A matrix setting*/
@@ -2261,7 +2680,7 @@ void mtx_setting(enum vpp_matrix_e mtx_sel,
        unsigned int matrix_pre_offset2 = 0;
        unsigned int matrix_en_ctrl = 0;
 
-       if (mtx_sel & VD1_MTX) {
+       if (mtx_sel == VD1_MTX) {
                matrix_coef00_01 = VPP_VD1_MATRIX_COEF00_01;
                matrix_coef02_10 = VPP_VD1_MATRIX_COEF02_10;
                matrix_coef11_12 = VPP_VD1_MATRIX_COEF11_12;
@@ -2278,7 +2697,7 @@ void mtx_setting(enum vpp_matrix_e mtx_sel,
                matrix_en_ctrl = VPP_VD1_MATRIX_EN_CTRL;
 
                WRITE_VPP_REG_BITS(VPP_VD1_MATRIX_EN_CTRL, mtx_on, 0, 1);
-       } else if (mtx_sel & POST2_MTX) {
+       } else if (mtx_sel == POST2_MTX) {
                matrix_coef00_01 = VPP_POST2_MATRIX_COEF00_01;
                matrix_coef02_10 = VPP_POST2_MATRIX_COEF02_10;
                matrix_coef11_12 = VPP_POST2_MATRIX_COEF11_12;
@@ -2295,7 +2714,7 @@ void mtx_setting(enum vpp_matrix_e mtx_sel,
                matrix_en_ctrl = VPP_POST2_MATRIX_EN_CTRL;
 
                WRITE_VPP_REG_BITS(VPP_POST2_MATRIX_EN_CTRL, mtx_on, 0, 1);
-       } else if (mtx_sel & POST_MTX) {
+       } else if (mtx_sel == POST_MTX) {
                matrix_coef00_01 = VPP_POST_MATRIX_COEF00_01;
                matrix_coef02_10 = VPP_POST_MATRIX_COEF02_10;
                matrix_coef11_12 = VPP_POST_MATRIX_COEF11_12;
@@ -2344,15 +2763,3 @@ void mtx_setting(enum vpp_matrix_e mtx_sel,
                break;
        }
 }
-/*for rtl bug osd1 green line at the bottom, used for dv*/
-void enable_osd1_mtx(unsigned int en)
-{
-       if (is_meson_g12b_cpu() && is_meson_rev_b())
-               _VSYNC_WR_MPEG_REG_BITS(OSD1_HDR2_MATRIXI_EN_CTRL, en, 0, 1);
-       else if ((is_meson_g12b_cpu() && is_meson_rev_a()) ||
-                       is_meson_g12a_cpu())
-               VSYNC_WR_MPEG_REG_BITS(OSD1_HDR2_MATRIXO_EN_CTRL, en, 0, 1);
-       else
-               VSYNC_WR_MPEG_REG_BITS(OSD1_HDR2_MATRIXI_EN_CTRL, en, 0, 1);
-}
-EXPORT_SYMBOL(enable_osd1_mtx);
index e570d85..4c15106 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/amlogic/media/vout/vinfo.h>
 
 #ifndef MAX
 #define MAX(x1, x2) (double)(x1 > x2 ? x1 : x2)
@@ -50,43 +51,48 @@ int64_t FloatRev(int64_t iA);
 int64_t FloatCon(int64_t iA, int MOD);
 
 enum hdr_module_sel {
-       VD1_HDR = 0x1,
-       VD2_HDR = 0x2,
-       OSD1_HDR = 0x4,
-       VDIN0_HDR = 0x8,
-       VDIN1_HDR = 0x10,
-       DI_HDR = 0x20,
+       VD1_HDR = 1,
+       VD2_HDR = 2,
+       OSD1_HDR = 3,
+       VDIN0_HDR = 4,
+       VDIN1_HDR = 5,
+       DI_HDR = 6,
        HDR_MAX
 };
 
 enum hdr_matrix_sel {
-       HDR_IN_MTX = 0x1,
-       HDR_GAMUT_MTX = 0x2,
-       HDR_OUT_MTX = 0x4,
+       HDR_IN_MTX = 1,
+       HDR_GAMUT_MTX = 2,
+       HDR_OUT_MTX = 3,
        HDR_MTX_MAX
 };
 
 enum hdr_lut_sel {
-       HDR_EOTF_LUT = 0x1,
-       HDR_OOTF_LUT = 0x2,
-       HDR_OETF_LUT = 0x4,
-       HDR_CGAIN_LUT = 0x8,
+       HDR_EOTF_LUT = 1,
+       HDR_OOTF_LUT = 2,
+       HDR_OETF_LUT = 3,
+       HDR_CGAIN_LUT = 4,
        HDR_LUT_MAX
 };
 
 enum hdr_process_sel {
-       HDR_BYPASS = 0x1,
-       HDR_SDR = 0x2,
-       SDR_HDR = 0x4,
-       HLG_BYPASS = 0x8,
-       HLG_SDR = 0x10,
-       HLG_HDR = 0x20,
-       SDR_HLG = 0X40,
-       HDRPLUS_SDR = 0x80,
+       HDR_BYPASS = 1,
+       HDR_SDR = 2,
+       SDR_HDR = 3,
+       HLG_BYPASS = 4,
+       HLG_SDR = 5,
+       HLG_HDR = 6,
+       SDR_HLG = 7,
+       SDR_IPT = 8,
+       HDR_IPT = 9,
+       HLG_IPT = 10,
+       HDR_HLG = 11,
+       RGB_YUV = 12,
+       RGB_HDR = 13,
+       RGB_HLG = 14,
        HDR_p_MAX
 };
 
-
 #define MTX_ON  1
 #define MTX_OFF 0
 
@@ -101,13 +107,16 @@ enum hdr_process_sel {
 #define HDR2_OETF_LUT_SIZE 149
 #define HDR2_CGAIN_LUT_SIZE 65
 
+
+#define MTX_NUM_PARAM 16
 struct hdr_proc_mtx_param_s {
        int mtx_only;
-       int mtx_in[15];
+       int mtx_in[MTX_NUM_PARAM];
        int mtx_gamut[9];
-       int mtx_cgain[15];
-       int mtx_ogain[15];
-       int mtx_out[15];
+       int mtx_gamut_mode;
+       int mtx_cgain[MTX_NUM_PARAM];
+       int mtx_ogain[MTX_NUM_PARAM];
+       int mtx_out[MTX_NUM_PARAM];
        int mtxi_pre_offset[3];
        int mtxi_pos_offset[3];
        int mtxo_pre_offset[3];
@@ -116,6 +125,10 @@ struct hdr_proc_mtx_param_s {
        enum hdr_process_sel p_sel;
 };
 
+#define OO_BITS                        12
+#define OO_GAIN_SHIFT  3
+#define OO_NOR                 (OO_BITS - OO_GAIN_SHIFT)
+
 struct hdr_proc_lut_param_s {
        int64_t eotf_lut[143];
        int64_t oetf_lut[149];
@@ -130,8 +143,9 @@ typedef int64_t(*MenuFun)(int64_t);
 void eotf_float_gen(int64_t *o_out, MenuFun eotf);
 void oetf_float_gen(int64_t *bin_e, MenuFun oetf);
 void nolinear_lut_gen(int64_t *bin_c, MenuFun cgain);
-extern void hdr_func(enum hdr_module_sel module_sel,
-       enum hdr_process_sel hdr_process_select);
+extern enum hdr_process_sel hdr_func(enum hdr_module_sel module_sel,
+       enum hdr_process_sel hdr_process_select,
+       struct vinfo_s *vinfo);
 /*G12A vpp matrix*/
 enum vpp_matrix_e {
        VD1_MTX = 0x1,
index 4a1cace..18451d4 100644 (file)
@@ -1009,11 +1009,13 @@ u32 get_video_enabled(void)
 {
        return video_enabled;
 }
+EXPORT_SYMBOL(get_video_enabled);
 
 u32 get_videopip_enabled(void)
 {
        return video2_enabled;
 }
+EXPORT_SYMBOL(get_videopip_enabled);
 
 /* show first frame*/
 static bool show_first_frame_nosync;
@@ -5995,7 +5997,7 @@ struct vframe_s *dolby_vision_toggle_frame(struct vframe_s *vf)
        struct vframe_s *toggle_vf = NULL;
        int width_bl, width_el;
        int height_bl, height_el;
-       int ret = dolby_vision_update_metadata(vf);
+       int ret;
 
        if (!is_dolby_vision_el_disable() || for_dolby_vision_certification())
                cur_dispbuf2 = dolby_vision_vf_peek_el(vf);
@@ -6051,11 +6053,24 @@ struct vframe_s *dolby_vision_toggle_frame(struct vframe_s *vf)
                ori2_end_y_lines =
                        height_el - 1;
        }
+
+       if (!get_video_enabled()) {
+               /* when video layer off */
+               /* not need to update setting */
+               dolby_vision_set_toggle_flag(0);
+               return NULL;
+       };
+
+       ret = dolby_vision_update_metadata(vf);
        if (ret == 0) {
                /* setting generated for this frame */
                /* or DOVI in bypass mode */
                toggle_vf = vf;
                dolby_vision_set_toggle_flag(1);
+       } else if (ret == 1) {
+               /* both dolby and hdr module bypass */
+               toggle_vf = vf;
+               dolby_vision_set_toggle_flag(0);
        } else {
                /* fail generating setting for this frame */
                toggle_vf = NULL;
@@ -6572,6 +6587,7 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id)
        int toggle_cnt;
        struct vframe_s *toggle_vf = NULL;
        struct vframe_s *toggle_frame = NULL;
+       struct vframe_s *toggle_pip_frame = NULL;
        int video1_off_req = 0;
        int video2_off_req = 0;
        struct vframe_s *cur_dispbuf_back = cur_dispbuf;
@@ -6816,8 +6832,11 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id)
 #endif
 #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
        /* check video frame before VECM process */
-       if (is_dolby_vision_enable() && vf)
+       if (is_dolby_vision_enable() && vf) {
                dolby_vision_check_hdr10(vf);
+               dolby_vision_check_hdr10plus(vf);
+               dolby_vision_check_hlg(vf);
+       }
 #endif
 #ifdef CONFIG_TVIN_VDIN
        /* patch for m8 4k2k wifidisplay bandwidth bottleneck */
@@ -7167,7 +7186,6 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id)
                        }
 
 #if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM)
-                       refresh_on_vs(vf);
                        if (amvecm_on_vs(
                                (cur_dispbuf != &vf_local)
                                ? cur_dispbuf : NULL,
@@ -7177,7 +7195,8 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id)
                                0,
                                0,
                                0,
-                               0) == 1)
+                               0,
+                               VD1_PATH) == 1)
                                break;
 #endif
                        vsync_toggle_frame(vf, __LINE__);
@@ -7262,7 +7281,6 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id)
                                                break;
 #endif
 #if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM)
-                                       refresh_on_vs(vf);
                                        if (amvecm_on_vs(
                                                (cur_dispbuf != &vf_local)
                                                ? cur_dispbuf : NULL,
@@ -7272,7 +7290,8 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id)
                                                0,
                                                0,
                                                0,
-                                               0) == 1)
+                                               0,
+                                               VD1_PATH) == 1)
                                                break;
 #endif
                                        vf = video_vf_get();
@@ -7319,7 +7338,8 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id)
                                } else
                                        vsync_toggle_frame(cur_dispbuf,
                                                        __LINE__);
-                               if (is_dolby_vision_enable()) {
+                               if (is_dolby_vision_enable()
+                               && is_dolby_vision_video_on()) {
                                        pause_vf = cur_dispbuf;
                                        video_pause_global = 1;
                                } else {
@@ -7331,8 +7351,10 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id)
                            && is_dolby_vision_enable()) {
                                toggle_vf = pause_vf;
                                dolby_vision_parse_metadata(
-                                       cur_dispbuf, 0, false);
+                                       cur_dispbuf, 2, false);
                                dolby_vision_set_toggle_flag(1);
+                               //use previous setting
+                               //pr_info("DOLBY: pause frame %p\n", toggle_vf);
                        }
                        break;
                }
@@ -7361,11 +7383,38 @@ SET_FILTER:
                pip_toggle_frame(cur_pipbuf);
 
        while (vf) {
-               vf = pip_vf_get();
-               if (vf) {
-                       if (!vf->frame_dirty)
+               if (!vf->frame_dirty) {
+                       if (amvecm_on_vs(
+                               vf,
+                               vf, CSC_FLAG_CHECK_OUTPUT,
+                               cur_frame_par ?
+                               cur_frame_par->supsc1_hori_ratio
+                               : 0,
+                               cur_frame_par ?
+                               cur_frame_par->supsc1_vert_ratio
+                               : 0,
+                               cur_frame_par ?
+                               cur_frame_par->spsc1_w_in :
+                               0,
+                               cur_frame_par ?
+                               cur_frame_par->spsc1_h_in :
+                               0,
+                               cur_frame_par ?
+                               cur_frame_par->cm_input_w :
+                               0,
+                               cur_frame_par ?
+                               cur_frame_par->cm_input_h :
+                               0,
+                               VD2_PATH) == 1)
+                               break;
+                       vf = pip_vf_get();
+                       if (vf) {
                                pip_toggle_frame(vf);
-                       else
+                               toggle_pip_frame = vf;
+                       }
+               } else {
+                       vf = pip_vf_get();
+                       if (vf)
                                pip_vf_put(vf);
                }
                vf = pip_vf_peek();
@@ -7379,29 +7428,62 @@ SET_FILTER:
        }
 
 #if defined(CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM)
-               amvecm_on_vs(
-                       (cur_dispbuf != &vf_local)
-                       ? cur_dispbuf : NULL,
-                       toggle_frame,
-                       toggle_frame ? CSC_FLAG_TOGGLE_FRAME : 0,
-                       cur_frame_par ?
-                       cur_frame_par->supsc1_hori_ratio :
-                       0,
-                       cur_frame_par ?
-                       cur_frame_par->supsc1_vert_ratio :
-                       0,
-                       cur_frame_par ?
-                       cur_frame_par->spsc1_w_in :
-                       0,
-                       cur_frame_par ?
-                       cur_frame_par->spsc1_h_in :
-                       0,
-                       cur_frame_par ?
-                       cur_frame_par->cm_input_w :
-                       0,
-                       cur_frame_par ?
-                       cur_frame_par->cm_input_h :
-                       0);
+       if (toggle_frame)
+               refresh_on_vs(toggle_frame);
+       else if (cur_dispbuf)
+               refresh_on_vs(cur_dispbuf);
+
+       amvecm_on_vs(
+               (cur_dispbuf != &vf_local)
+               ? cur_dispbuf : NULL,
+               toggle_frame,
+               toggle_frame ? CSC_FLAG_TOGGLE_FRAME : 0,
+               cur_frame_par ?
+               cur_frame_par->supsc1_hori_ratio :
+               0,
+               cur_frame_par ?
+               cur_frame_par->supsc1_vert_ratio :
+               0,
+               cur_frame_par ?
+               cur_frame_par->spsc1_w_in :
+               0,
+               cur_frame_par ?
+               cur_frame_par->spsc1_h_in :
+               0,
+               cur_frame_par ?
+               cur_frame_par->cm_input_w :
+               0,
+               cur_frame_par ?
+               cur_frame_par->cm_input_h :
+               0,
+               VD1_PATH);
+
+#ifdef VIDEO_PIP
+       amvecm_on_vs(
+               (cur_pipbuf != &local_pip)
+               ? cur_pipbuf : NULL,
+               toggle_pip_frame,
+               toggle_pip_frame ? CSC_FLAG_TOGGLE_FRAME : 0,
+               cur_frame_par ?
+               cur_frame_par->supsc1_hori_ratio :
+               0,
+               cur_frame_par ?
+               cur_frame_par->supsc1_vert_ratio :
+               0,
+               cur_frame_par ?
+               cur_frame_par->spsc1_w_in :
+               0,
+               cur_frame_par ?
+               cur_frame_par->spsc1_h_in :
+               0,
+               cur_frame_par ?
+               cur_frame_par->cm_input_w :
+               0,
+               cur_frame_par ?
+               cur_frame_par->cm_input_h :
+               0,
+               VD2_PATH);
+#endif
 #endif
 
 #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
@@ -7412,11 +7494,13 @@ SET_FILTER:
                /* force toggle when keeping frame after playing */
                if ((cur_dispbuf == &vf_local)
                        && !toggle_vf
-                       && is_dolby_vision_on()) {
+                       && is_dolby_vision_video_on()
+                       && get_video_enabled()) {
                        toggle_vf = cur_dispbuf;
                        dolby_vision_parse_metadata(
-                               cur_dispbuf, 2, false);
+                               toggle_vf, 2, false);
                        dolby_vision_set_toggle_flag(1);
+                       //pr_info("DOLBY: keep frame %p", toggle_vf);
                }
 /* pause mode was moved to video display property */
 #if 0
@@ -7473,7 +7557,8 @@ SET_FILTER:
                                toggle_vf->compHeight : toggle_vf->height;
                        frame_size = (h_size << 16) | v_size;
                }
-               dolby_vision_process(toggle_vf, frame_size, pps_state);
+               dolby_vision_process((cur_dispbuf != &vf_local)
+                       ? cur_dispbuf : toggle_vf, frame_size, pps_state);
                dolby_vision_update_setting();
        }
 #endif
@@ -13059,6 +13144,12 @@ int vout_notify_callback(struct notifier_block *block, unsigned long cmd,
                vsync_pts_inc_scale_base = vinfo->sync_duration_num;
                spin_unlock_irqrestore(&lock, flags);
                new_vmode = vinfo->mode;
+#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
+               pr_info("vout_notify_callback: VOUT_EVENT_MODE_CHANGE");
+               /* make sure dolby policy process runs atleast once */
+               if (is_dolby_vision_enable())
+                       dolby_vision_set_toggle_flag(1);
+#endif
                break;
        case VOUT_EVENT_OSD_PREBLEND_ENABLE:
                break;
index 54ea409..3841aae 100644 (file)
@@ -73,13 +73,14 @@ static int set_disp_mode_auto(void);
 static void hdmitx_get_edid(struct hdmitx_dev *hdev);
 static void hdmitx_set_drm_pkt(struct master_display_info_s *data);
 static void hdmitx_set_vsif_pkt(enum eotf_type type, enum mode_type
-       tunnel_mode, struct dv_vsif_para *data);
+       tunnel_mode, struct dv_vsif_para *data, bool switch_to_sdr);
 static void hdmitx_set_hdr10plus_pkt(unsigned int flag,
        struct hdr10plus_para *data);
 static void hdmitx_set_emp_pkt(unsigned char *data,
        unsigned int type, unsigned int size);
 static int check_fbc_special(unsigned char *edid_dat);
 static struct vinfo_s *hdmitx_get_current_vinfo(void);
+static void hdmitx_fmt_attr(struct hdmitx_dev *hdev);
 
 static DEFINE_MUTEX(setclk_mutex);
 static DEFINE_MUTEX(getedid_mutex);
@@ -607,8 +608,12 @@ static ssize_t show_attr(struct device *dev,
        struct device_attribute *attr, char *buf)
 {
        int pos = 0;
-
-       pos += snprintf(buf+pos, PAGE_SIZE, "%s\n\r", hdmitx_device.fmt_attr);
+       if (!memcmp(hdmitx_device.fmt_attr, "default,", 7)) {
+               memset(hdmitx_device.fmt_attr, 0,
+                       sizeof(hdmitx_device.fmt_attr));
+               hdmitx_fmt_attr(&hdmitx_device);
+       }
+       pos += snprintf(buf+pos, PAGE_SIZE, "%s\n", hdmitx_device.fmt_attr);
        return pos;
 }
 
@@ -617,6 +622,14 @@ ssize_t store_attr(struct device *dev,
 {
        strncpy(hdmitx_device.fmt_attr, buf, sizeof(hdmitx_device.fmt_attr));
        hdmitx_device.fmt_attr[15] = '\0';
+       if (!memcmp(hdmitx_device.fmt_attr, "rgb", 3))
+               hdmitx_device.para->cs = COLORSPACE_RGB444;
+       else if (!memcmp(hdmitx_device.fmt_attr, "422", 3))
+               hdmitx_device.para->cs = COLORSPACE_YUV422;
+       else if (!memcmp(hdmitx_device.fmt_attr, "420", 3))
+               hdmitx_device.para->cs = COLORSPACE_YUV420;
+       else
+               hdmitx_device.para->cs = COLORSPACE_YUV444;
        return count;
 }
 /*aud_mode attr*/
@@ -1387,7 +1400,7 @@ static void hdmitx_set_drm_pkt(struct master_display_info_s *data)
 }
 
 static void hdmitx_set_vsif_pkt(enum eotf_type type,
-       enum mode_type tunnel_mode, struct dv_vsif_para *data)
+       enum mode_type tunnel_mode, struct dv_vsif_para *data, bool signal_sdr)
 {
        struct hdmitx_dev *hdev = &hdmitx_device;
        struct dv_vsif_para para = {0};
@@ -1484,14 +1497,17 @@ static void hdmitx_set_vsif_pkt(enum eotf_type type,
                        else
                                hdev->HWOp.SetPacket(
                                        HDMI_PACKET_VEND, NULL, NULL);
-                       hdev->HWOp.CntlConfig(hdev,
-                               CONF_AVI_RGBYCC_INDIC, hdev->para->cs);
-                       hdev->HWOp.CntlConfig(hdev,
-                               CONF_AVI_Q01, RGB_RANGE_LIM);
-                       hdev->HWOp.CntlConfig(hdev,
-                               CONF_AVI_YQ01, YCC_RANGE_LIM);
-                       hdev->HWOp.CntlConfig(hdev, CONF_AVI_BT2020,
-                               CLR_AVI_BT2020);/*BT709*/
+                       if (signal_sdr) {
+                               pr_info("hdmitx: H14b VSIF, switching signal to SDR\n");
+                               hdev->HWOp.CntlConfig(hdev,
+                                       CONF_AVI_RGBYCC_INDIC, hdev->para->cs);
+                               hdev->HWOp.CntlConfig(hdev,
+                                       CONF_AVI_Q01, RGB_RANGE_DEFAULT);
+                               hdev->HWOp.CntlConfig(hdev,
+                                       CONF_AVI_YQ01, YCC_RANGE_LIM);
+                               hdev->HWOp.CntlConfig(hdev, CONF_AVI_BT2020,
+                                       CLR_AVI_BT2020);/*BT709*/
+                       }
                }
 
        }
@@ -1503,6 +1519,8 @@ static void hdmitx_set_vsif_pkt(enum eotf_type type,
 
                if (data == NULL)
                        data = &para;
+               len = 0x1b;
+
                /*4k vsif package */
                if ((vic == HDMI_3840x2160p30_16x9) ||
                    (vic == HDMI_3840x2160p25_16x9) ||
@@ -1513,14 +1531,13 @@ static void hdmitx_set_vsif_pkt(enum eotf_type type,
                switch (type) {
                case EOTF_T_DOLBYVISION:
                case EOTF_T_LL_MODE:
-                       len = 0x1b;
                        hdev->dv_src_feature = 1;
                        break;
                case EOTF_T_HDR10:
                case EOTF_T_SDR:
                case EOTF_T_NULL:
                default:
-                       len = 0x5;
+
                        hdev->dv_src_feature = 0;
                        break;
                }
@@ -1605,14 +1622,18 @@ static void hdmitx_set_vsif_pkt(enum eotf_type type,
                        } else
                                hdev->HWOp.SetPacket(
                                        HDMI_PACKET_VEND, NULL, NULL);
-                       hdev->HWOp.CntlConfig(hdev,
-                               CONF_AVI_RGBYCC_INDIC, hdev->para->cs);
-                       hdev->HWOp.CntlConfig(hdev,
-                               CONF_AVI_Q01, RGB_RANGE_LIM);
-                       hdev->HWOp.CntlConfig(hdev,
-                               CONF_AVI_YQ01, YCC_RANGE_LIM);
-                       hdev->HWOp.CntlConfig(hdev, CONF_AVI_BT2020,
+
+                       if (signal_sdr) {
+                               pr_info("hdmitx: Dolby VSIF, switching signal to SDR\n");
+                               hdev->HWOp.CntlConfig(hdev,
+                                       CONF_AVI_RGBYCC_INDIC, hdev->para->cs);
+                               hdev->HWOp.CntlConfig(hdev,
+                                       CONF_AVI_Q01, RGB_RANGE_DEFAULT);
+                               hdev->HWOp.CntlConfig(hdev,
+                                       CONF_AVI_YQ01, YCC_RANGE_LIM);
+                               hdev->HWOp.CntlConfig(hdev, CONF_AVI_BT2020,
                                CLR_AVI_BT2020);/*BT709*/
+                       }
                }
        }
 }
@@ -2049,7 +2070,7 @@ static ssize_t store_config(struct device *dev,
                data.features = 0x00091200;
                hdmitx_set_drm_pkt(&data);
        } else if (strncmp(buf, "vsif", 4) == 0)
-               hdmitx_set_vsif_pkt(buf[4] - '0', buf[5] == '1', NULL);
+               hdmitx_set_vsif_pkt(buf[4] - '0', buf[5] == '1', NULL, true);
        else if (strncmp(buf, "emp", 3) == 0) {
                if (hdmitx_device.chip_type >= MESON_CPU_ID_G12A)
                        hdmitx_set_emp_pkt(NULL, 1, 1);
@@ -4100,7 +4121,7 @@ static void hdmitx_hpd_plugout_handler(struct work_struct *work)
                return;
        }
        /*after plugout, DV mode can't be supported*/
-       hdmitx_set_vsif_pkt(0, 0, NULL);
+       hdmitx_set_vsif_pkt(0, 0, NULL, true);
        hdmitx_set_hdr10plus_pkt(0, NULL);
        hdev->ready = 0;
        if (hdev->repeater_tx)
@@ -4271,7 +4292,7 @@ static int get_dt_vend_init_data(struct device_node *np,
        return 0;
 }
 
-static void hdmitx_init_fmt_attr(struct hdmitx_dev *hdev)
+static void hdmitx_fmt_attr(struct hdmitx_dev *hdev)
 {
        if (strlen(hdev->fmt_attr) >= 8) {
                pr_info(SYS "fmt_attr %s\n", hdev->fmt_attr);
@@ -4317,6 +4338,20 @@ static void hdmitx_init_fmt_attr(struct hdmitx_dev *hdev)
        pr_info(SYS "fmt_attr %s\n", hdev->fmt_attr);
 }
 
+static void hdmitx_init_fmt_attr(struct hdmitx_dev *hdev)
+{
+       if (strlen(hdev->fmt_attr) >= 8) {
+               pr_info(SYS "fmt_attr %s\n", hdev->fmt_attr);
+               return;
+       }
+       if ((hdev->para->cd == COLORDEPTH_RESERVED) &&
+           (hdev->para->cs == COLORSPACE_RESERVED)) {
+               strcpy(hdev->fmt_attr, "default");
+       } else
+               hdmitx_fmt_attr(hdev);
+       pr_info(SYS "fmt_attr %s\n", hdev->fmt_attr);
+}
+
 /* for notify to cec */
 static BLOCKING_NOTIFIER_HEAD(hdmitx_event_notify_list);
 int hdmitx_event_notifier_regist(struct notifier_block *nb)
index b44d1e0..227cd6d 100644 (file)
 
 #include <linux/types.h>
 
+#define DOLBY_VISION_OUTPUT_MODE_IPT                   0
+#define DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL            1
+#define DOLBY_VISION_OUTPUT_MODE_HDR10                 2
+#define DOLBY_VISION_OUTPUT_MODE_SDR10                 3
+#define DOLBY_VISION_OUTPUT_MODE_SDR8                  4
+#define DOLBY_VISION_OUTPUT_MODE_BYPASS                        5
+
+/* STB: if sink support DV, always output DV*/
+/*             else always output SDR/HDR */
+/* TV:  when source is DV, convert to SDR */
+#define DOLBY_VISION_FOLLOW_SINK               0
+
+/* STB: output DV only if source is DV*/
+/*             and sink support DV*/
+/*             else always output SDR/HDR */
+/* TV:  when source is DV or HDR, convert to SDR */
+#define DOLBY_VISION_FOLLOW_SOURCE             1
+
+/* STB: always follow dolby_vision_mode */
+/* TV:  if set dolby_vision_mode to SDR8,*/
+/*             convert all format to SDR by TV core,*/
+/*             else bypass Dolby Vision */
+#define DOLBY_VISION_FORCE_OUTPUT_MODE 2
+
 extern void enable_dolby_vision(int enable);
 extern bool is_dolby_vision_enable(void);
 extern bool is_dolby_vision_on(void);
+extern bool is_dolby_vision_video_on(void);
 extern bool for_dolby_vision_certification(void);
 extern void set_dolby_vision_mode(int mode);
 extern int get_dolby_vision_mode(void);
@@ -60,6 +85,8 @@ extern void tv_dolby_vision_crc_clear(int flag);
 extern char *tv_dolby_vision_get_crc(u32 *len);
 extern void tv_dolby_vision_insert_crc(bool print);
 extern int dolby_vision_check_hdr10(struct vframe_s *vf);
+extern int dolby_vision_check_hlg(struct vframe_s *vf);
+extern int dolby_vision_check_hdr10plus(struct vframe_s *vf);
 extern void tv_dolby_vision_dma_table_modify(
        u32 tbl_id, uint64_t value);
 extern void tv_dolby_vision_efuse_info(void);
@@ -75,6 +102,8 @@ extern int enable_rgb_to_yuv_matrix_for_dvll(
 extern bool is_dovi_frame(struct vframe_s *vf);
 extern void update_graphic_width_height(unsigned int width,
        unsigned int height);
+extern int get_dolby_vision_policy(void);
+extern int get_dolby_vision_src_format(void);
 extern bool is_dolby_vision_el_disable(void);
 extern bool is_dovi_dual_layer_frame(struct vframe_s *vf);
 #endif
index 68cc471..269f00e 100644 (file)
 #define MTX_BYPASS_RGB_OGO                     (1 << 0)
 #define MTX_RGB2YUVL_RGB_OGO           (1 << 1)
 
-#define SDR_SOURCE    (1 << 0)
-#define HDR10_SOURCE  (1 << 1)
-#define HLG_SOURCE    (1 << 2)
+#define UNKNOWN_SOURCE         0
+#define HDR10_SOURCE           1
+#define HDR10PLUS_SOURCE       2
+#define DOVI_SOURCE                    3
+#define PRIMESL_SOURCE         4
+#define HLG_SOURCE                     5
+#define SDR_SOURCE                     6
 
 enum cm_hist_e {
        CM_HUE_HIST = 0,
@@ -270,11 +274,12 @@ enum vpp_matrix_csc_e {
 };
 
 enum hdr_type_e {
-       HDRTYPE_NONE = 0,
-       HDRTYPE_SDR = 0x1,
-       HDRTYPE_HDR10 = 0x2,
-       HDRTYPE_HLG = 0x4,
-       HDRTYPE_MAX,
+       HDRTYPE_NONE = UNKNOWN_SOURCE,
+       HDRTYPE_SDR = SDR_SOURCE,
+       HDRTYPE_HDR10 = HDR10_SOURCE,
+       HDRTYPE_HLG = HLG_SOURCE,
+       HDRTYPE_HDR10PLUS = HDR10PLUS_SOURCE,
+       HDRTYPE_DOVI = DOVI_SOURCE
 };
 
 enum vpp_transfer_characteristic_e {
@@ -351,6 +356,12 @@ struct vecm_match_data_s {
        u32 vlk_pll_sel;/*independent panel pll and hdmitx pll*/
 };
 
+enum vd_path_e {
+       VD1_PATH = 0,
+       VD2_PATH = 1,
+       VD_PATH_MAX = 2
+};
+
 /*overscan:
  *length 0~31bit :number of crop;
  *src_timing: bit31: on: load/save all crop
@@ -464,7 +475,8 @@ extern int amvecm_on_vs(
        unsigned int sps_w_in,
        unsigned int sps_h_in,
        unsigned int cm_in_w,
-       unsigned int cm_in_h);
+       unsigned int cm_in_h,
+       enum vd_path_e vd_path);
 extern void refresh_on_vs(struct vframe_s *vf);
 extern void pc_mode_process(void);
 extern void pq_user_latch_process(void);
index ee462b0..26294cb 100644 (file)
@@ -102,6 +102,7 @@ struct hdr10_plus_info {
 struct hdr_info {
 /* RX EDID hdr support types */
        u32 hdr_support;
+       unsigned char rawdata[7];
 /*
  *dynamic_info[0] expresses type1's parameters certainly
  *dynamic_info[1] expresses type2's parameters certainly
@@ -219,7 +220,8 @@ struct vout_device_s {
        const struct dv_info *dv_info;
        void (*fresh_tx_hdr_pkt)(struct master_display_info_s *data);
        void (*fresh_tx_vsif_pkt)(enum eotf_type type,
-               enum mode_type tunnel_mode, struct dv_vsif_para *data);
+               enum mode_type tunnel_mode, struct dv_vsif_para *data,
+               bool signal_sdr);
        void (*fresh_tx_hdr10plus_pkt)(unsigned int flag,
                struct hdr10plus_para *data);
        void  (*fresh_tx_emp_pkt)(unsigned char *data, unsigned int type,