osd: add viu2 support for tl1 [1/1]
authorpengcheng chen <pengcheng.chen@amlogic.com>
Tue, 20 Nov 2018 01:42:44 +0000 (09:42 +0800)
committerNick Xie <nick@khadas.com>
Mon, 5 Aug 2019 06:46:00 +0000 (14:46 +0800)
PD#172587

Problem:
add viu2 support for tl1.

Solution:
add viu2 support for tl1.

Verify:
verified by x301

Change-Id: Ie728f6ee7e0c4c4062e5e12e3d80515d99d020f8
Signed-off-by: pengcheng chen <pengcheng.chen@amlogic.com>
ff60d15 osd: calc osd parameters used num/den replace left/right shift
[1/1]
481d4f2 osd: set hdr size according osd blend0 out size  [1/1]
42b54ce osd: afbc decode error when loop viu1 to vdin [1/1]
91bda20 osd: fix afbc decoder error caused flicker in display [1/1]
799ba4c osd: fix hotplug hdmi causes system crash [1/1]
e9fadfe5 osd: fix osd afbc can't display on android5.1 [1/1]
1f8aa33 osd: frame just display on half screen [1/1]
7bcfa18 osd: set osd1 scaler before osd blend [1/1]
6913eaa osd: osd display color abnormal when run drm [1/1]
6862fb2 osd: add viu2 fence support [1/1]
f59b7a6 drm: a113d support drm issue [1/1]
50557a1 osd: reset afbcd flag when convert format value [1/1]
cfbcb3d osd: fix buidroot compile error issue [1/1]
6163540 osd: rdma write miss caused afbc mosaic [1/1]
032a712 osd: fix display frame offset caused osd display abnormal [1/1]
2c1269e osd: osd: recovey mode always blank [1/1]
3be570b osd: osd: reserve vs_ctrl bit for VPP [1/1]
40bfe97 osd: add viu2 support for tl1 [1/1]

osd: osd: reserve vs_ctrl bit for VPP [1/1]

PD#172587

Problem:
reserve vs_ctrl bit for VPP

Solution:
Avoid operating VPP_OFIFO_SIZE bit19 on OSD code

Verify:
verified on t962x2_x301

Change-Id: Ic450d6f64e2349d97d02f0802058b4031564fea4
Signed-off-by: Jian Cao <jian.cao@amlogic.com>
osd: osd: recovey mode always blank [1/1]

PD#TV-1287

Problem:
recovey mode always blank

Solution:
set right condition to enable free_scale

Verify:
verified on P321 board

Change-Id: I2f70b9c5436b30156f157a3297a11a2ef1cfec67
Signed-off-by: Jian Cao <jian.cao@amlogic.com>
osd: fix display frame offset caused osd display abnormal [1/1]

PD#OTT-1663

Problem:
display frame offset caused osd display abnormal

Solution:
remove unnecessary blend dst_data adjust

Verify:
Locally on raven

Change-Id: I38b97f6da750f5edea97416b4d7fc0172dea7466
Signed-off-by: Pengcheng Chen <pengcheng.chen@amlogic.com>
osd: rdma write miss caused afbc mosaic [1/1]

PD#SWPL-4502

Problem:
afbc mosaic when bandwidth is high, root cause is
rdma write regs missed.

Solution:
1. add vsync line detected, if rdma write nearly
vsync, wait vsync needed
2. add rdma write detected, if rdma write missed
wait vsync needed
3. add tl1/g12b afbc backup

Verify:
Locally on tl1

Change-Id: If4fd303c3808525fa44e1118742a3e26830323f5
Signed-off-by: Pengcheng Chen <pengcheng.chen@amlogic.com>
osd: fix buidroot compile error issue [1/1]

PD#SWPL-4502

Problem:
buidlroot compile error

Solution:
fix buidroot compile error issue

Verify:
buildroot make linux-build

Change-Id: I0277c2b3f439946ab680f4c34f30c16e31ea6034
Signed-off-by: Pengcheng Chen <pengcheng.chen@amlogic.com>
osd: reset afbcd flag when convert format value [1/1]

PD#SWPL-5185

Problem:
"fence color format error 28" when test weston-simple-egl

Solution:
reset afbcd flag when convert format value

Verify:
Locally on g12b_w400

Change-Id: I81a9394288026bc596f6b3438cec72ceaad7749f
Signed-off-by: Jian Cao <jian.cao@amlogic.com>
drm: a113d support drm issue [1/1]

PD#SH-397

Problem:
use  modetest to test A113D DRM function, displaying is incorrect

Solution:
add linear addr config for a113d drm mode

Verify:
verified on s400

Change-Id: Id6a2c6ad94bc0148815076561d9dc2ae8ded6884
Signed-off-by: Dezhi Kong <dezhi.kong@amlogic.com>
osd: add viu2 fence support [1/1]

PD#SWPL-6384

Problem:
viu2 not support fence

Solution:
add viu2 fence support.

Verify:
test pass on tl1

Change-Id: I94a5e483c88cace79b7386bb918c203ada6b8274
Signed-off-by: Pengcheng Chen <pengcheng.chen@amlogic.com>
osd: osd display color abnormal when run drm [1/1]

PD#SWPL-6867

Problem:
osd dispaly color abnormal because osd enable not update.

Solution:
update osd enalbe flag in drm process.

Verify:
Verified u212

Change-Id: I1c2e8b62d9d5af203c95d3d0ac940fb512dd8e5e
Signed-off-by: Pengcheng Chen <pengcheng.chen@amlogic.com>
osd: set osd1 scaler before osd blend [1/1]

PD#SWPL-6596

Problem:
bring up osd for TM2

Solution:
set osd1 scaler before osd blend

Verify:
Verified on T962e2_ab319

Change-Id: I9e7d5fa83b2edc8e9359371695ea46fa3b39e09c
Signed-off-by: Pengcheng Chen <pengcheng.chen@amlogic.com>
osd: frame just display on half screen [1/1]

PD#SWPL-7039

Problem:
bring up osd for TM2
frame just display on half screen

Solution:
fix field_out_en value from array

Verify:
Verified on T962e2_ab319

Change-Id: Id07f3d813242f031125fcac11d3fa05205895448
Signed-off-by: Jian Cao <jian.cao@amlogic.com>
osd: fix osd afbc can't display on android5.1 [1/1]

PD#SWPL-6869

Problem:
afbc can't display with android5.1, because blank enable
called before afbc set, which make osd enable not updated
and afbc not enable when hwc post frame

Solution:
if mali afbc enable, call osd enable.

Verify:
verified on x301

Change-Id: I1d727a586a66c6e7848d09dfb5c5b74ff7a2e3e6
Signed-off-by: Shuide Chen <shuide.chen@amlogic.com>
osd: fix hotplug hdmi causes system crash [1/1]

PD#SWPL-7009

Problem:
hotplug hdmi causes system crash
when unplug hdmi display mode is null, hwc hasn't received
event and post frame normal but osd vsync lost, which caused
wait hw vsync timeout(1s), and fd leak.

Solution:
when process every frame, if display mode is null, exit frame process
just process fence.

Verify:
verified on Raven, franklin

Change-Id: Icbe7cd76776e46a6ed79c6cee3ea05772cc5f9d2
Signed-off-by: Pengcheng Chen <pengcheng.chen@amlogic.com>
osd: fix afbc decoder error caused flicker in display [1/1]

PD#OTT-3000

Problem:
afbc decoder error caused flicker in display.

Solution:
close osd prefetch.

Verify:
Verified with raven

Change-Id: I44356c028b41e251f7a98b5e931b2cbd583b0829
Signed-off-by: Pengcheng Chen <pengcheng.chen@amlogic.com>
osd: afbc decode error when loop viu1 to vdin [1/1]

PD#TV-5024

Problem:
afbc decode error when loop viu1 to vdin.

Solution:
set osd hold line to max if vinfo is dummy_panel

Verify:
Tl1 X301

Change-Id: I0ebb312d381accb1890233164f071a095310d2f1
Signed-off-by: Pengcheng Chen <pengcheng.chen@amlogic.com>
osd: set hdr size according osd blend0 out size  [1/1]

PD#IPTV-2395

Problem:
osd last line have abnormal data

Solution:
set hdr size according osd blend0 out size

Verify:
Verfied on u212

Change-Id: Iad738b16fce066270c78213f1b696a802e1b8da6
Signed-off-by: Pengcheng Chen <pengcheng.chen@amlogic.com>
osd: calc osd parameters used num/den replace left/right shift  [1/1]

PD#OTT-3615

Problem:
a line on the right displayed

Solution:
calc osd parameters used num/den replace left/right shift

Verify:
Verfied on u212

Change-Id: If59d9de0bb3c525d2b67d05ec449d458fbbcdfe2
Signed-off-by: Pengcheng Chen <pengcheng.chen@amlogic.com>
drivers/amlogic/media/osd/osd.h
drivers/amlogic/media/osd/osd_debug.c
drivers/amlogic/media/osd/osd_drm.c
drivers/amlogic/media/osd/osd_fb.c
drivers/amlogic/media/osd/osd_hw.c
drivers/amlogic/media/osd/osd_hw.h
drivers/amlogic/media/osd/osd_reg.h

index 8003c51..b5fdc53 100644 (file)
@@ -106,7 +106,6 @@ enum color_index_e {
 #define FBIOPUT_OSD_CURSOR     \
        _IOWR(FB_IOC_MAGIC, 0x0,  struct fb_cursor_user)
 
-
 /* OSD color definition */
 #define KEYCOLOR_FLAG_TARGET  1
 #define KEYCOLOR_FLAG_ONHOLD  2
@@ -114,6 +113,8 @@ enum color_index_e {
 
 #define HW_OSD_COUNT 4
 #define OSD_BLEND_LAYERS 4
+#define VIU_COUNT     2
+
 /* OSD block definition */
 #define HW_OSD_BLOCK_COUNT 4
 #define HW_OSD_BLOCK_REG_COUNT (HW_OSD_BLOCK_COUNT*2)
@@ -509,6 +510,7 @@ struct osd_device_data_s {
        u32 vpp_fifo_len;
        u32 dummy_data;
        u32 has_viu2;
+       u32 osd0_sc_independ;
        u32 viu1_osd_count;
        u32 viu2_index;
        struct clk *vpu_clkc;
@@ -611,8 +613,10 @@ struct hw_osd_blending_s {
        bool osd1_freescale_disable;
        u32 vinfo_width;
        u32 vinfo_height;
-       u32 screen_ratio_w;
-       u32 screen_ratio_h;
+       u32 screen_ratio_w_num;
+       u32 screen_ratio_w_den;
+       u32 screen_ratio_h_num;
+       u32 screen_ratio_h_den;
        struct dispdata_s dst_data;
        struct layer_blend_reg_s blend_reg;
        struct layer_blend_s layer_blend;
@@ -707,7 +711,7 @@ struct hw_para_s {
        u32 scan_mode[HW_OSD_COUNT];
        u32 order[HW_OSD_COUNT];
        u32 premult_en[HW_OSD_COUNT];
-       struct display_flip_info_s disp_info;
+       struct display_flip_info_s disp_info[VIU_COUNT];
        struct osd_3d_mode_s mode_3d[HW_OSD_COUNT];
        u32 updated[HW_OSD_COUNT];
        /* u32 block_windows[HW_OSD_COUNT][HW_OSD_BLOCK_REG_COUNT]; */
@@ -722,7 +726,7 @@ struct hw_para_s {
        int use_h_filter_mode[HW_OSD_COUNT];
        int use_v_filter_mode[HW_OSD_COUNT];
        struct hw_list_s reg[HW_REG_INDEX_MAX];
-       u32 field_out_en;
+       u32 field_out_en[VIU_COUNT];
        u32 scale_workaround;
        u32 fb_for_4k2k;
        u32 antiflicker_mode;
@@ -734,21 +738,21 @@ struct hw_para_s {
        struct osd_device_data_s osd_meson_dev;
        u32 urgent[HW_OSD_COUNT];
        u32 osd_deband_enable;
-       u32 osd_fps;
-       u32 osd_fps_start;
+       u32 osd_fps[VIU_COUNT];
+       u32 osd_fps_start[VIU_COUNT];
        u32 osd_display_debug;
        ulong screen_base[HW_OSD_COUNT];
        ulong screen_size[HW_OSD_COUNT];
        ulong screen_base_backup[HW_OSD_COUNT];
        ulong screen_size_backup[HW_OSD_COUNT];
-       u32 vinfo_width;
-       u32 vinfo_height;
+       u32 vinfo_width[VIU_COUNT];
+       u32 vinfo_height[VIU_COUNT];
        u32 fb_drvier_probe;
        u32 afbc_force_reset;
        u32 afbc_regs_backup;
        u32 afbc_status_err_reset;
        u32 afbc_use_latch;
-       u32 hwc_enable;
+       u32 hwc_enable[VIU_COUNT];
        u32 osd_use_latch[HW_OSD_COUNT];
        u32 hw_cursor_en;
        u32 hw_rdma_en;
@@ -761,8 +765,8 @@ struct hw_para_s {
        u32 viu_type;
        u32 line_n_rdma;
        struct hw_debug_s osd_debug;
-       int out_fence_fd;
+       int out_fence_fd[VIU_COUNT];
        int in_fd[HW_OSD_COUNT];
-       struct osd_fence_fun_s osd_fence[2];
+       struct osd_fence_fun_s osd_fence[VIU_COUNT][2];
 };
 #endif /* _OSD_H_ */
index 701da24..eb1dd8d 100644 (file)
@@ -66,7 +66,9 @@ static void osd_debug_dump_value(void)
 
        osd_log_info("--- OSD ---\n");
        osd_log_info("bot_type: %d\n", hwpara->bot_type);
-       osd_log_info("field_out_en: %d\n", hwpara->field_out_en);
+       osd_log_info("field_out_en: %d\n", hwpara->field_out_en[VIU1]);
+       if (osd_hw.osd_meson_dev.has_viu2)
+               osd_log_info("field_out_en: %d\n", hwpara->field_out_en[VIU2]);
 
        if (hwpara->osd_meson_dev.osd_ver == OSD_HIGH_ONE) {
                struct hw_osd_blending_s *blend_para = NULL;
@@ -345,7 +347,7 @@ static void osd_debug_dump_register_all(void)
 
        if (osd_hw.osd_meson_dev.cpu_id >= __MESON_CPU_MAJOR_ID_G12B) {
                if (osd_hw.osd_meson_dev.has_viu2 &&
-                       osd_hw.powered[OSD4]) {
+                       osd_hw.powered[osd_hw.osd_meson_dev.viu2_index]) {
                        reg = VPP2_MISC;
                        osd_log_info("reg[0x%x]: 0x%08x\n",
                                reg, osd_reg_read(reg));
index d2cb627..3732b20 100644 (file)
@@ -563,11 +563,13 @@ static ssize_t osd_hwc_enable_read_file(struct file *file,
                                char __user *userbuf,
                                size_t count, loff_t *ppos)
 {
+       struct seq_file *s = file->private_data;
+       int osd_id = *(int *)s;
        char buf[128];
        ssize_t len;
        unsigned int hwc_enable = 0;
 
-       osd_get_hwc_enable(&hwc_enable);
+       osd_get_hwc_enable(osd_id, &hwc_enable);
        len = snprintf(buf, 128, "%d\n", hwc_enable);
        return simple_read_from_buffer(userbuf, count, ppos, buf, len);
 }
@@ -576,6 +578,8 @@ static ssize_t osd_hwc_enable_write_file(struct file *file,
                                const char __user *userbuf,
                                size_t count, loff_t *ppos)
 {
+       struct seq_file *s = file->private_data;
+       int osd_id = *(int *)s;
        char buf[128];
        unsigned int hwc_enable = 0;
        int ret = 0;
@@ -586,7 +590,7 @@ static ssize_t osd_hwc_enable_write_file(struct file *file,
        buf[count] = 0;
        ret = kstrtoint(buf, 0, &hwc_enable);
        osd_log_info("hwc enable: %d\n", hwc_enable);
-       osd_set_hwc_enable(hwc_enable);
+       osd_set_hwc_enable(osd_id, hwc_enable);
        return count;
 }
 
@@ -594,6 +598,8 @@ static ssize_t osd_do_hwc_write_file(struct file *file,
                                const char __user *userbuf,
                                size_t count, loff_t *ppos)
 {
+       struct seq_file *s = file->private_data;
+       int osd_id = *(int *)s;
        char buf[128];
        unsigned int do_hwc = 0;
        int ret = 0;
@@ -605,7 +611,7 @@ static ssize_t osd_do_hwc_write_file(struct file *file,
        ret = kstrtoint(buf, 0, &do_hwc);
        osd_log_info("do_hwc: %d\n", do_hwc);
        if (do_hwc)
-               osd_do_hwc();
+               osd_do_hwc(osd_id);
        return count;
 }
 
index 71a881e..81c3648 100644 (file)
@@ -684,19 +684,24 @@ static int osd_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 
 static int osd_set_par(struct fb_info *info)
 {
-       const struct vinfo_s *vinfo;
+       const struct vinfo_s *vinfo = NULL;
        struct osd_fb_dev_s *fbdev = (struct osd_fb_dev_s *)info->par;
        struct osd_ctl_s *osd_ctrl = &fbdev->osd_ctl;
        u32 virt_end_x, virt_end_y;
+       u32 output_index;
+
+       output_index = get_output_device_id(fbdev->fb_index);
 
-       if (fbdev->fb_index <= OSD3) {
+       if (fbdev->fb_index < osd_hw.osd_meson_dev.viu1_osd_count) {
                vinfo = get_current_vinfo();
                if (!vinfo) {
                        osd_log_err("current vinfo NULL\n");
                        return -1;
                }
        } else {
+#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
                vinfo = get_current_vinfo2();
+#endif
                if (!vinfo) {
                        osd_log_err("current vinfo NULL\n");
                        return -1;
@@ -888,7 +893,7 @@ static int osd_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
                                arg & 0xffff ? 1 : 0);
                break;
        case FBIOGET_OSD_FLUSH_RATE:
-               osd_get_flush_rate_hw(&flush_rate);
+               osd_get_flush_rate_hw(info->node, &flush_rate);
                if (copy_to_user(argp, &flush_rate, sizeof(u32)))
                        return -EFAULT;
                break;
@@ -1098,12 +1103,12 @@ static int osd_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
 #endif
                break;
        case FBIOPUT_OSD_HWC_ENABLE:
-               osd_set_hwc_enable(hwc_enable);
+               osd_set_hwc_enable(info->node, hwc_enable);
                ret = 0;
                break;
        case FBIOPUT_OSD_DO_HWC:
                do_hwc_cmd.out_fen_fd =
-                       osd_sync_do_hwc(&do_hwc_cmd);
+                       osd_sync_do_hwc(info->node, &do_hwc_cmd);
                ret = copy_to_user(argp,
                        &do_hwc_cmd,
                        sizeof(struct do_hwc_cmd_s));
@@ -1500,7 +1505,7 @@ static int osd_open(struct fb_info *info, int arg)
 
        fb_index = fbdev->fb_index;
        if ((osd_meson_dev.has_viu2)
-               && (fb_index == OSD4)) {
+               && (fb_index == osd_meson_dev.viu2_index)) {
                int vpu_clkc_rate;
 
                /* select mux0, if select mux1, mux0 must be set */
@@ -1893,13 +1898,14 @@ static int osd_cursor(struct fb_info *fbi, struct fb_cursor *var)
 {
        s16 startx = 0, starty = 0;
        struct osd_fb_dev_s *fb_dev = gp_fbdev_list[1];
+       u32 output_index;
 
        if (fb_dev) {
                startx = fb_dev->osd_ctl.disp_start_x;
                starty = fb_dev->osd_ctl.disp_start_y;
        }
-
-       if (osd_hw.hwc_enable)
+       output_index = get_output_device_id(fbi->node);
+       if (osd_hw.hwc_enable[output_index])
                osd_cursor_hw_no_scale(fbi->node, (s16)var->hot.x,
                        (s16)var->hot.y, (s16)startx, (s16)starty,
                        fbi->var.xres, fbi->var.yres);
@@ -1991,18 +1997,22 @@ int osd_notify_callback(struct notifier_block *block, unsigned long cmd,
        if ((!strcmp(vinfo->name, "invalid")) ||
                (!strcmp(vinfo->name, "null")))
                return -1;
-       osd_hw.vinfo_width = vinfo->width;
-       osd_hw.vinfo_height = vinfo->field_height;
-       osd_hw.field_out_en = is_interlaced(vinfo);
+       osd_hw.vinfo_width[VIU1] = vinfo->width;
+       osd_hw.vinfo_height[VIU1] = vinfo->field_height;
+       osd_hw.field_out_en[VIU1] = is_interlaced(vinfo);
        switch (cmd) {
        case  VOUT_EVENT_MODE_CHANGE:
                set_osd_logo_freescaler();
+               if (!strcmp(vinfo->name, "dummy_panel"))
+                       osd_set_hold_line(MAX_HOLD_LINE);
+               else
+                       osd_set_hold_line(DEFAULT_HOLD_LINE);
                if (osd_hw.osd_meson_dev.cpu_id == __MESON_CPU_MAJOR_ID_G12B &&
                        is_meson_rev_b())
                        set_reset_rdma_trigger_line();
                if ((osd_meson_dev.osd_ver == OSD_NORMAL)
                        || (osd_meson_dev.osd_ver == OSD_SIMPLE)
-                       || (osd_hw.hwc_enable == 0)) {
+                       || (osd_hw.hwc_enable[VIU1] == 0)) {
                for (i = 0; i < osd_meson_dev.viu1_osd_count; i++) {
                        fb_dev = gp_fbdev_list[i];
                        if (fb_dev == NULL)
@@ -2033,7 +2043,7 @@ int osd_notify_callback(struct notifier_block *block, unsigned long cmd,
        case VOUT_EVENT_OSD_DISP_AXIS:
                if ((osd_meson_dev.osd_ver == OSD_NORMAL)
                        || (osd_meson_dev.osd_ver == OSD_SIMPLE)
-                       || (osd_hw.hwc_enable == 0)) {
+                       || (osd_hw.hwc_enable[VIU1] == 0)) {
 
                disp_rect = (struct disp_rect_s *)para;
                for (i = 0; i < osd_meson_dev.viu1_osd_count; i++) {
@@ -2084,111 +2094,6 @@ int osd_notify_callback(struct notifier_block *block, unsigned long cmd,
        return 0;
 }
 
-#if 0
-int osd_notify_callback(struct notifier_block *block, unsigned long cmd,
-                       void *para)
-{
-       struct vinfo_s *vinfo;
-       struct osd_fb_dev_s *fb_dev;
-       int  i, blank;
-       struct disp_rect_s *disp_rect;
-
-       vinfo = get_current_vinfo();
-       if (!vinfo) {
-               osd_log_err("current vinfo NULL\n");
-               return -1;
-       }
-       osd_log_info("current vmode=%s, cmd: 0x%lx\n",
-               vinfo->name, cmd);
-       if ((!strcmp(vinfo->name, "invalid")) ||
-               (!strcmp(vinfo->name, "null")))
-               return -1;
-       osd_hw.vinfo_width = vinfo->width;
-       osd_hw.vinfo_height = vinfo->field_height;
-       osd_hw.field_out_en = is_interlaced(vinfo);
-       switch (cmd) {
-       case  VOUT_EVENT_MODE_CHANGE:
-               set_osd_logo_freescaler();
-               for (i = 0; i < osd_meson_dev.viu1_osd_count; i++) {
-                       fb_dev = gp_fbdev_list[i];
-                       if (fb_dev == NULL)
-                               continue;
-                       set_default_display_axis(&fb_dev->fb_info->var,
-                                       &fb_dev->osd_ctl, vinfo);
-                       console_lock();
-                       osddev_update_disp_axis(fb_dev, 1);
-                       if ((osd_meson_dev.osd_ver == OSD_NORMAL)
-                               || (osd_meson_dev.osd_ver == OSD_SIMPLE))
-                               osd_set_antiflicker_hw(DEV_OSD1, vinfo,
-                                      gp_fbdev_list
-                                      [DEV_OSD1]->fb_info->var.yres);
-                       else if (osd_meson_dev.osd_ver == OSD_HIGH_ONE)
-                               osd_set_antiflicker_hw(i, vinfo,
-                                      gp_fbdev_list[i]->fb_info->var.yres);
-                       osd_reg_write(VPP_POSTBLEND_H_SIZE, vinfo->width);
-                       console_unlock();
-               }
-               break;
-       case VOUT_EVENT_OSD_BLANK:
-               blank = *(int *)para;
-               for (i = 0; i < osd_meson_dev.viu1_osd_count; i++) {
-                       fb_dev = gp_fbdev_list[i];
-                       if (fb_dev == NULL)
-                               continue;
-                       console_lock();
-                       osd_blank(blank, fb_dev->fb_info);
-                       console_unlock();
-               }
-               break;
-       case VOUT_EVENT_OSD_DISP_AXIS:
-               disp_rect = (struct disp_rect_s *)para;
-               for (i = 0; i < osd_meson_dev.viu1_osd_count; i++) {
-                       if (!disp_rect)
-                               break;
-
-                       /* vout serve send only two layer axis */
-                       if (i >= 2)
-                               break;
-
-                       fb_dev = gp_fbdev_list[i];
-                       /*
-                        * if osd layer preblend,
-                        * it's position is controlled by vpp.
-                       if (fb_dev->preblend_enable)
-                               break;
-                       */
-                       fb_dev->osd_ctl.disp_start_x = disp_rect->x;
-                       fb_dev->osd_ctl.disp_start_y = disp_rect->y;
-                       osd_log_dbg("set disp axis: x:%d y:%d w:%d h:%d\n",
-                                   disp_rect->x, disp_rect->y,
-                                   disp_rect->w, disp_rect->h);
-                       if (disp_rect->x + disp_rect->w > vinfo->width)
-                               fb_dev->osd_ctl.disp_end_x = vinfo->width - 1;
-                       else
-                               fb_dev->osd_ctl.disp_end_x =
-                                       fb_dev->osd_ctl.disp_start_x +
-                                       disp_rect->w - 1;
-                       if (disp_rect->y + disp_rect->h > vinfo->height)
-                               fb_dev->osd_ctl.disp_end_y = vinfo->height - 1;
-                       else
-                               fb_dev->osd_ctl.disp_end_y =
-                                       fb_dev->osd_ctl.disp_start_y +
-                                       disp_rect->h - 1;
-                       disp_rect++;
-                       osd_log_dbg("new disp axis: x0:%d y0:%d x1:%d y1:%d\n",
-                                   fb_dev->osd_ctl.disp_start_x,
-                                   fb_dev->osd_ctl.disp_start_y,
-                                   fb_dev->osd_ctl.disp_end_x,
-                                   fb_dev->osd_ctl.disp_end_y);
-                       console_lock();
-                       osddev_update_disp_axis(fb_dev, 0);
-                       console_unlock();
-               }
-               break;
-       }
-       return 0;
-}
-#endif
 int osd_notify_callback_viu2(struct notifier_block *block, unsigned long cmd,
                        void *para)
 {
@@ -2209,6 +2114,8 @@ int osd_notify_callback_viu2(struct notifier_block *block, unsigned long cmd,
                vinfo->name, cmd);
        if (!strcmp(vinfo->name, "invalid"))
                return -1;
+       osd_hw.vinfo_width[VIU2] = vinfo->width;
+       osd_hw.vinfo_height[VIU2] = vinfo->field_height;
        i = osd_meson_dev.viu2_index;
        switch (cmd) {
        case  VOUT_EVENT_MODE_CHANGE:
@@ -2843,9 +2750,10 @@ static ssize_t show_flush_rate(struct device *device,
                               struct device_attribute *attr,
                               char *buf)
 {
+       struct fb_info *fb_info = dev_get_drvdata(device);
        u32 flush_rate = 0;
 
-       osd_get_flush_rate_hw(&flush_rate);
+       osd_get_flush_rate_hw(fb_info->node, &flush_rate);
        return snprintf(buf, PAGE_SIZE, "flush_rate:[%d]\n", flush_rate);
 }
 
@@ -2897,15 +2805,22 @@ static ssize_t store_antiflicker(struct device *device,
                                 struct device_attribute *attr,
                                 const char *buf, size_t count)
 {
-       struct vinfo_s *vinfo;
+       struct vinfo_s *vinfo = NULL;
        unsigned int osd_antiflicker = 0;
        struct fb_info *fb_info = dev_get_drvdata(device);
        int res = 0;
        int ret = 0;
+       u32 output_index;
 
        ret = kstrtoint(buf, 0, &res);
        osd_antiflicker = res;
-       vinfo = get_current_vinfo();
+       output_index = get_output_device_id(fb_info->node);
+       if (output_index == VIU1)
+               vinfo = get_current_vinfo();
+#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
+       else if (output_index == VIU2)
+               vinfo = get_current_vinfo2();
+#endif
        if (!vinfo) {
                osd_log_err("get current vinfo NULL\n");
                return 0;
@@ -3021,9 +2936,10 @@ static ssize_t show_osd_fps(struct device *device,
                                struct device_attribute *attr,
                                char *buf)
 {
+       struct fb_info *fb_info = dev_get_drvdata(device);
        u32 osd_fps;
 
-       osd_get_fps(&osd_fps);
+       osd_get_fps(fb_info->node, &osd_fps);
        return snprintf(buf, 40, "%d\n",
                osd_fps);
 }
@@ -3032,11 +2948,12 @@ static ssize_t store_osd_fps(struct device *device,
                           struct device_attribute *attr,
                           const char *buf, size_t count)
 {
+       struct fb_info *fb_info = dev_get_drvdata(device);
        int res = 0;
        int ret = 0;
 
        ret = kstrtoint(buf, 0, &res);
-       osd_set_fps(res);
+       osd_set_fps(fb_info->node, res);
 
        return count;
 }
@@ -3123,9 +3040,10 @@ static ssize_t show_osd_background_size(struct device *device,
                                struct device_attribute *attr,
                                char *buf)
 {
+       struct fb_info *fb_info = dev_get_drvdata(device);
        struct display_flip_info_s disp_info;
 
-       osd_get_background_size(&disp_info);
+       osd_get_background_size(fb_info->node, &disp_info);
        return snprintf(buf, 80, "%d %d %d %d %d %d %d %d\n",
                disp_info.background_w,
                disp_info.background_h,
@@ -3141,12 +3059,14 @@ static ssize_t store_osd_background_size(struct device *device,
                           struct device_attribute *attr,
                           const char *buf, size_t count)
 {
+       struct fb_info *fb_info = dev_get_drvdata(device);
        int parsed[8];
 
-       if (likely(parse_para(buf, 8, parsed) == 8)) {
+       if (likely(parse_para(buf, 8, parsed) == 8))
                osd_set_background_size(
+                           fb_info->node,
                                (struct display_flip_info_s *)&parsed);
-       else
+       else
                osd_log_err("set background size error\n");
 
        return count;
@@ -3209,9 +3129,10 @@ static ssize_t show_osd_hwc_enalbe(struct device *device,
                                struct device_attribute *attr,
                                char *buf)
 {
+       struct fb_info *fb_info = dev_get_drvdata(device);
        u32 hwc_enalbe;
 
-       osd_get_hwc_enable(&hwc_enalbe);
+       osd_get_hwc_enable(fb_info->node, &hwc_enalbe);
        return snprintf(buf, 40, "%d\n",
                hwc_enalbe);
 }
@@ -3220,13 +3141,14 @@ static ssize_t store_osd_hwc_enalbe(struct device *device,
                           struct device_attribute *attr,
                           const char *buf, size_t count)
 {
+       struct fb_info *fb_info = dev_get_drvdata(device);
        int res = 0;
        int ret = 0;
 
        ret = kstrtoint(buf, 0, &res);
        if (ret < 0)
                return -EINVAL;
-       osd_set_hwc_enable(res);
+       osd_set_hwc_enable(fb_info->node, res);
 
        return count;
 }
@@ -3235,6 +3157,7 @@ static ssize_t store_do_hwc(struct device *device,
                           struct device_attribute *attr,
                           const char *buf, size_t count)
 {
+       struct fb_info *fb_info = dev_get_drvdata(device);
        int res = 0;
        int ret = 0;
 
@@ -3242,7 +3165,7 @@ static ssize_t store_do_hwc(struct device *device,
        if (ret < 0)
                return -EINVAL;
        if (res)
-               osd_do_hwc();
+               osd_do_hwc(fb_info->node);
 
        return count;
 }
@@ -3276,13 +3199,14 @@ static ssize_t store_osd_single_step_mode(struct device *device,
                           struct device_attribute *attr,
                           const char *buf, size_t count)
 {
+       struct fb_info *fb_info = dev_get_drvdata(device);
        int res = 0;
        int ret = 0;
 
        ret = kstrtoint(buf, 0, &res);
        if (ret < 0)
                return -EINVAL;
-       osd_set_single_step_mode(res);
+       osd_set_single_step_mode(fb_info->node, res);
 
        return count;
 }
@@ -3291,13 +3215,14 @@ static ssize_t store_osd_single_step(struct device *device,
                           struct device_attribute *attr,
                           const char *buf, size_t count)
 {
+       struct fb_info *fb_info = dev_get_drvdata(device);
        int res = 0;
        int ret = 0;
 
        ret = kstrtoint(buf, 0, &res);
        if (ret < 0)
                return -EINVAL;
-       osd_set_single_step(res);
+       osd_set_single_step(fb_info->node, res);
 
        return count;
 }
@@ -3866,6 +3791,7 @@ static struct osd_device_data_s osd_gxbb = {
        .vpp_fifo_len = 0x77f,
        .dummy_data = 0x00808000,
        .has_viu2 = 0,
+       .osd0_sc_independ = 0,
 };
 
 static struct osd_device_data_s osd_gxtvbb = {
@@ -3881,6 +3807,7 @@ static struct osd_device_data_s osd_gxtvbb = {
        .vpp_fifo_len = 0xfff,
        .dummy_data = 0x0,
        .has_viu2 = 0,
+       .osd0_sc_independ = 0,
 };
 
 static struct osd_device_data_s osd_gxl = {
@@ -3896,6 +3823,7 @@ static struct osd_device_data_s osd_gxl = {
        .vpp_fifo_len = 0x77f,
        .dummy_data = 0x00808000,
        .has_viu2 = 0,
+       .osd0_sc_independ = 0,
 };
 
 static struct osd_device_data_s osd_gxm = {
@@ -3911,6 +3839,7 @@ static struct osd_device_data_s osd_gxm = {
        .vpp_fifo_len = 0xfff,
        .dummy_data = 0x00202000,/* dummy data is different */
        .has_viu2 = 0,
+       .osd0_sc_independ = 0,
 };
 
 static struct osd_device_data_s osd_txl = {
@@ -3926,6 +3855,7 @@ static struct osd_device_data_s osd_txl = {
        .vpp_fifo_len = 0x77f,
        .dummy_data = 0x00808000,
        .has_viu2 = 0,
+       .osd0_sc_independ = 0,
 };
 
 static struct osd_device_data_s osd_txlx = {
@@ -3941,6 +3871,7 @@ static struct osd_device_data_s osd_txlx = {
        .vpp_fifo_len = 0x77f,
        .dummy_data = 0x00808000,
        .has_viu2 = 0,
+       .osd0_sc_independ = 0,
 };
 
 static struct osd_device_data_s osd_axg = {
@@ -3957,6 +3888,7 @@ static struct osd_device_data_s osd_axg = {
        .vpp_fifo_len = 0x400,
        .dummy_data = 0x00808000,
        .has_viu2 = 0,
+       .osd0_sc_independ = 0,
 };
 
 static struct osd_device_data_s osd_g12a = {
@@ -3972,6 +3904,7 @@ static struct osd_device_data_s osd_g12a = {
        .vpp_fifo_len = 0xfff,/* 2048 */
        .dummy_data = 0x00808000,
        .has_viu2 = 1,
+       .osd0_sc_independ = 0,
 };
 
 static struct osd_device_data_s osd_g12b = {
@@ -3987,6 +3920,7 @@ static struct osd_device_data_s osd_g12b = {
        .vpp_fifo_len = 0xfff,/* 2048 */
        .dummy_data = 0x00808000,
        .has_viu2 = 1,
+       .osd0_sc_independ = 0,
 };
 
 static struct osd_device_data_s osd_tl1 = {
@@ -4002,6 +3936,7 @@ static struct osd_device_data_s osd_tl1 = {
        .vpp_fifo_len = 0xfff,/* 2048 */
        .dummy_data = 0x00808000,
        .has_viu2 = 1,
+       .osd0_sc_independ = 0,
 };
 
 static struct osd_device_data_s osd_sm1 = {
@@ -4017,6 +3952,7 @@ static struct osd_device_data_s osd_sm1 = {
        .vpp_fifo_len = 0xfff,/* 2048 */
        .dummy_data = 0x00808000,
        .has_viu2 = 1,
+       .osd0_sc_independ = 0,
 };
 
 static struct osd_device_data_s osd_tm2 = {
@@ -4027,11 +3963,12 @@ static struct osd_device_data_s osd_tm2 = {
        .has_deband = 1,
        .has_lut = 1,
        .has_rdma = 1,
-       .has_dolby_vision = 1,
+       .has_dolby_vision = 0,
        .osd_fifo_len = 64, /* fifo len 64*8 = 512 */
        .vpp_fifo_len = 0xfff,/* 2048 */
        .dummy_data = 0x00808000,
        .has_viu2 = 1,
+       .osd0_sc_independ = 1,
 };
 
 static const struct of_device_id meson_fb_dt_match[] = {
@@ -4129,7 +4066,6 @@ static int osd_probe(struct platform_device *pdev)
                        return -ENODEV;
                }
        }
-
        /* get interrupt resource */
        int_viu_vsync = platform_get_irq_byname(pdev, "viu-vsync");
        if (int_viu_vsync  == -ENXIO) {
index c145728..c032403 100644 (file)
@@ -75,7 +75,6 @@
 #include "osd_hw_def.h"
 #include "osd_fb.h"
 
-#define OSD_BLEND_SHIFT_WORKAROUND
 #ifdef CONFIG_AMLOGIC_VSYNC_FIQ_ENABLE
 #define FIQ_VSYNC
 #endif
@@ -95,7 +94,6 @@
 
 #define osd_tprintk(...)
 
-#define OSD_CALC    14
 #define FREE_SCALE_MAX_WIDTH    1920
 struct hw_para_s osd_hw;
 static DEFINE_MUTEX(osd_mutex);
@@ -108,11 +106,13 @@ static int osd_afbc_dec_enable;
 static int ext_canvas_id[HW_OSD_COUNT];
 static int osd_extra_idx[HW_OSD_COUNT][2];
 static bool suspend_flag;
-
+static u32 rdma_dt_cnt;
 static void osd_clone_pan(u32 index, u32 yoffset, int debug_flag);
 static void osd_set_dummy_data(u32 index, u32 alpha);
 
-struct hw_osd_reg_s hw_osd_reg_array[HW_OSD_COUNT] = {
+struct hw_osd_reg_s hw_osd_reg_array[HW_OSD_COUNT];
+
+struct hw_osd_reg_s hw_osd_reg_array_g12a[HW_OSD_COUNT] = {
        {
                VIU_OSD1_CTRL_STAT,
                VIU_OSD1_CTRL_STAT2,
@@ -134,8 +134,6 @@ struct hw_osd_reg_s hw_osd_reg_array[HW_OSD_COUNT] = {
                VIU_OSD1_PROT_CTRL,
                VIU_OSD1_MALI_UNPACK_CTRL,
                VIU_OSD1_DIMM_CTRL,
-               //VIU_OSD_BLEND_DIN0_SCOPE_H,
-               //VIU_OSD_BLEND_DIN0_SCOPE_V,
 
                VPP_OSD_SCALE_COEF_IDX,
                VPP_OSD_SCALE_COEF,
@@ -187,8 +185,6 @@ struct hw_osd_reg_s hw_osd_reg_array[HW_OSD_COUNT] = {
                VIU_OSD2_PROT_CTRL,
                VIU_OSD2_MALI_UNPACK_CTRL,
                VIU_OSD2_DIMM_CTRL,
-               //VIU_OSD_BLEND_DIN2_SCOPE_H,
-               //VIU_OSD_BLEND_DIN2_SCOPE_V,
 
                OSD2_SCALE_COEF_IDX,
                OSD2_SCALE_COEF,
@@ -239,8 +235,6 @@ struct hw_osd_reg_s hw_osd_reg_array[HW_OSD_COUNT] = {
                VIU_OSD3_PROT_CTRL,
                VIU_OSD3_MALI_UNPACK_CTRL,
                VIU_OSD3_DIMM_CTRL,
-               //VIU_OSD_BLEND_DIN3_SCOPE_H,
-               //VIU_OSD_BLEND_DIN3_SCOPE_V,
 
                OSD34_SCALE_COEF_IDX,
                OSD34_SCALE_COEF,
@@ -319,66 +313,226 @@ struct hw_osd_reg_s hw_osd_reg_array[HW_OSD_COUNT] = {
                VIU2_OSD1_UNSUPPORT,
                }
 };
+
+struct hw_osd_reg_s hw_osd_reg_array_tl1[HW_OSD_COUNT] = {
+       {
+               VIU_OSD1_CTRL_STAT,
+               VIU_OSD1_CTRL_STAT2,
+               VIU_OSD1_COLOR_ADDR,
+               VIU_OSD1_COLOR,
+               VIU_OSD1_TCOLOR_AG0,
+               VIU_OSD1_TCOLOR_AG1,
+               VIU_OSD1_TCOLOR_AG2,
+               VIU_OSD1_TCOLOR_AG3,
+               VIU_OSD1_BLK0_CFG_W0,
+               VIU_OSD1_BLK0_CFG_W1,
+               VIU_OSD1_BLK0_CFG_W2,
+               VIU_OSD1_BLK0_CFG_W3,
+               VIU_OSD1_BLK0_CFG_W4,
+               VIU_OSD1_BLK1_CFG_W4,
+               VIU_OSD1_BLK2_CFG_W4,
+               VIU_OSD1_FIFO_CTRL_STAT,
+               VIU_OSD1_TEST_RDDATA,
+               VIU_OSD1_PROT_CTRL,
+               VIU_OSD1_MALI_UNPACK_CTRL,
+               VIU_OSD1_DIMM_CTRL,
+
+               VPP_OSD_SCALE_COEF_IDX,
+               VPP_OSD_SCALE_COEF,
+               VPP_OSD_VSC_PHASE_STEP,
+               VPP_OSD_VSC_INI_PHASE,
+               VPP_OSD_VSC_CTRL0,
+               VPP_OSD_HSC_PHASE_STEP,
+               VPP_OSD_HSC_INI_PHASE,
+               VPP_OSD_HSC_CTRL0,
+               VPP_OSD_SC_DUMMY_DATA,
+               VPP_OSD_SC_CTRL0,
+               VPP_OSD_SCI_WH_M1,
+               VPP_OSD_SCO_H_START_END,
+               VPP_OSD_SCO_V_START_END,
+               VPU_MAFBC_HEADER_BUF_ADDR_LOW_S0,
+               VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S0,
+               VPU_MAFBC_FORMAT_SPECIFIER_S0,
+               VPU_MAFBC_BUFFER_WIDTH_S0,
+               VPU_MAFBC_BUFFER_HEIGHT_S0,
+               VPU_MAFBC_BOUNDING_BOX_X_START_S0,
+               VPU_MAFBC_BOUNDING_BOX_X_END_S0,
+               VPU_MAFBC_BOUNDING_BOX_Y_START_S0,
+               VPU_MAFBC_BOUNDING_BOX_Y_END_S0,
+               VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S0,
+               VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S0,
+               VPU_MAFBC_OUTPUT_BUF_STRIDE_S0,
+               VPU_MAFBC_PREFETCH_CFG_S0,
+
+
+       },
+       {
+               VIU_OSD2_CTRL_STAT,
+               VIU_OSD2_CTRL_STAT2,
+               VIU_OSD2_COLOR_ADDR,
+               VIU_OSD2_COLOR,
+               VIU_OSD2_TCOLOR_AG0,
+               VIU_OSD2_TCOLOR_AG1,
+               VIU_OSD2_TCOLOR_AG2,
+               VIU_OSD2_TCOLOR_AG3,
+               VIU_OSD2_BLK0_CFG_W0,
+               VIU_OSD2_BLK0_CFG_W1,
+               VIU_OSD2_BLK0_CFG_W2,
+               VIU_OSD2_BLK0_CFG_W3,
+               VIU_OSD2_BLK0_CFG_W4,
+               VIU_OSD2_BLK1_CFG_W4,
+               VIU_OSD2_BLK2_CFG_W4,
+               VIU_OSD2_FIFO_CTRL_STAT,
+               VIU_OSD2_TEST_RDDATA,
+               VIU_OSD2_PROT_CTRL,
+               VIU_OSD2_MALI_UNPACK_CTRL,
+               VIU_OSD2_DIMM_CTRL,
+
+               OSD2_SCALE_COEF_IDX,
+               OSD2_SCALE_COEF,
+               OSD2_VSC_PHASE_STEP,
+               OSD2_VSC_INI_PHASE,
+               OSD2_VSC_CTRL0,
+               OSD2_HSC_PHASE_STEP,
+               OSD2_HSC_INI_PHASE,
+               OSD2_HSC_CTRL0,
+               OSD2_SC_DUMMY_DATA,
+               OSD2_SC_CTRL0,
+               OSD2_SCI_WH_M1,
+               OSD2_SCO_H_START_END,
+               OSD2_SCO_V_START_END,
+               VPU_MAFBC_HEADER_BUF_ADDR_LOW_S1,
+               VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S1,
+               VPU_MAFBC_FORMAT_SPECIFIER_S1,
+               VPU_MAFBC_BUFFER_WIDTH_S1,
+               VPU_MAFBC_BUFFER_HEIGHT_S1,
+               VPU_MAFBC_BOUNDING_BOX_X_START_S1,
+               VPU_MAFBC_BOUNDING_BOX_X_END_S1,
+               VPU_MAFBC_BOUNDING_BOX_Y_START_S1,
+               VPU_MAFBC_BOUNDING_BOX_Y_END_S1,
+               VPU_MAFBC_OUTPUT_BUF_ADDR_LOW_S1,
+               VPU_MAFBC_OUTPUT_BUF_ADDR_HIGH_S1,
+               VPU_MAFBC_OUTPUT_BUF_STRIDE_S1,
+               VPU_MAFBC_PREFETCH_CFG_S1,
+
+       },
+       {
+               VIU2_OSD1_CTRL_STAT,
+               VIU2_OSD1_CTRL_STAT2,
+               VIU2_OSD1_COLOR_ADDR,
+               VIU2_OSD1_COLOR,
+               VIU2_OSD1_TCOLOR_AG0,
+               VIU2_OSD1_TCOLOR_AG1,
+               VIU2_OSD1_TCOLOR_AG2,
+               VIU2_OSD1_TCOLOR_AG3,
+               VIU2_OSD1_BLK0_CFG_W0,
+               VIU2_OSD1_BLK0_CFG_W1,
+               VIU2_OSD1_BLK0_CFG_W2,
+               VIU2_OSD1_BLK0_CFG_W3,
+               VIU2_OSD1_BLK0_CFG_W4,
+               VIU2_OSD1_BLK1_CFG_W4,
+               VIU2_OSD1_BLK2_CFG_W4,
+               VIU2_OSD1_FIFO_CTRL_STAT,
+               VIU2_OSD1_TEST_RDDATA,
+               VIU2_OSD1_PROT_CTRL,
+               VIU2_OSD1_MALI_UNPACK_CTRL,
+               VIU2_OSD1_DIMM_CTRL,
+
+               VIU2_OSD1_UNSUPPORT,
+               VIU2_OSD1_UNSUPPORT,
+               VIU2_OSD1_UNSUPPORT,
+               VIU2_OSD1_UNSUPPORT,
+               VIU2_OSD1_UNSUPPORT,
+               VIU2_OSD1_UNSUPPORT,
+               VIU2_OSD1_UNSUPPORT,
+               VIU2_OSD1_UNSUPPORT,
+               VIU2_OSD1_UNSUPPORT,
+               VIU2_OSD1_UNSUPPORT,
+               VIU2_OSD1_UNSUPPORT,
+               VIU2_OSD1_UNSUPPORT,
+               VIU2_OSD1_UNSUPPORT,
+               VIU2_OSD1_UNSUPPORT,
+               VIU2_OSD1_UNSUPPORT,
+               VIU2_OSD1_UNSUPPORT,
+               VIU2_OSD1_UNSUPPORT,
+               VIU2_OSD1_UNSUPPORT,
+               VIU2_OSD1_UNSUPPORT,
+               VIU2_OSD1_UNSUPPORT,
+               VIU2_OSD1_UNSUPPORT,
+               VIU2_OSD1_UNSUPPORT,
+               VIU2_OSD1_UNSUPPORT,
+               VIU2_OSD1_UNSUPPORT,
+               VIU2_OSD1_UNSUPPORT,
+               VIU2_OSD1_UNSUPPORT,
+               }
+};
+
 static int osd_setting_blending_scope(u32 index);
 static int vpp_blend_setting_default(u32 index);
 
 #ifdef CONFIG_AMLOGIC_MEDIA_FB_OSD_SYNC_FENCE
 /* sync fence relative varible. */
-static int timeline_created;
-static void *osd_timeline;
-static u32 cur_streamline_val;
+static int timeline_created[VIU_COUNT];
+static void *osd_timeline[VIU_COUNT];
+static u32 cur_streamline_val[VIU_COUNT];
 /* thread control part */
-struct kthread_worker buffer_toggle_worker;
-struct task_struct *buffer_toggle_thread;
-struct kthread_work buffer_toggle_work;
-struct list_head post_fence_list;
-struct mutex post_fence_list_lock;
-struct osd_layers_fence_map_s map_layers;
+struct kthread_worker buffer_toggle_worker[VIU_COUNT];
+struct task_struct *buffer_toggle_thread[VIU_COUNT];
+struct kthread_work buffer_toggle_work[VIU_COUNT];
+struct list_head post_fence_list[VIU_COUNT];
+struct mutex post_fence_list_lock[VIU_COUNT]; /*post fence mutex*/
+struct osd_layers_fence_map_s map_layers[VIU_COUNT];
 struct file *displayed_bufs[HW_OSD_COUNT];
 static void osd_pan_display_single_fence(
        struct osd_fence_map_s *fence_map);
 static void osd_pan_display_layers_fence(
        struct osd_layers_fence_map_s *fence_map);
+static void osd_pan_display_single_fence_viu2(
+       struct osd_fence_map_s *fence_map);
+static void osd_pan_display_layers_fence_viu2(
+       struct osd_layers_fence_map_s *fence_map);
 
 
-static void *osd_timeline_create(void)
+static void *osd_timeline_create(u32 output_index)
 {
-       const char *tlName = "osd_timeline";
+       char tlname[32] = {};
 
-       if (osd_timeline == NULL) {
-               if (osd_hw.hwc_enable)
+       sprintf(tlname, "osd_timeline_%d", output_index);
+       if (!osd_timeline[output_index]) {
+               if (osd_hw.hwc_enable[output_index])
                        /* present fence */
-                       cur_streamline_val = 0;
+                       cur_streamline_val[output_index] = 0;
                else
-                       cur_streamline_val = 1;
-               osd_timeline = aml_sync_create_timeline(tlName);
+                       cur_streamline_val[output_index] = 1;
+               osd_timeline[output_index] = aml_sync_create_timeline(tlname);
                osd_tprintk("osd timeline create\n");
        }
-
-       return osd_timeline;
+       return osd_timeline[output_index];
 }
 
-static int osd_timeline_create_fence(void)
+static int osd_timeline_create_fence(u32 output_index)
 {
        int out_fence_fd = -1;
        u32 pt_val = 0;
 
-       pt_val = cur_streamline_val + 1;
-       out_fence_fd = aml_sync_create_fence(osd_timeline, pt_val);
+       pt_val = cur_streamline_val[output_index] + 1;
+       out_fence_fd = aml_sync_create_fence
+               (osd_timeline[output_index], pt_val);
        osd_tprintk("osd created out pt:%d, fence_fd:%d\n",
                        pt_val, out_fence_fd);
 
        if (out_fence_fd >= 0)
-               cur_streamline_val++;
+               cur_streamline_val[output_index]++;
        else
                pr_info("create fence returned %d", out_fence_fd);
        return out_fence_fd;
 }
 
-static void  osd_timeline_increase(void)
+static void  osd_timeline_increase(u32 output_index)
 {
-       aml_sync_inc_timeline(osd_timeline, 1);
-       osd_tprintk("osd out timeline inc\n");
+       aml_sync_inc_timeline(osd_timeline[output_index], 1);
+       osd_tprintk("osd out timeline %d inc\n", output_index);
+
 }
 
 static struct fence *osd_get_fenceobj(int fencefd)
@@ -454,12 +608,15 @@ module_param(enable_vd_zorder, uint, 0664);
 static int vsync_enter_line_max;
 static int vsync_exit_line_max;
 static int vsync_line_threshold = 950;
+static int line_threshold = 90;
 MODULE_PARM_DESC(vsync_enter_line_max, "\n vsync_enter_line_max\n");
 module_param(vsync_enter_line_max, uint, 0664);
 MODULE_PARM_DESC(vsync_exit_line_max, "\n vsync_exit_line_max\n");
 module_param(vsync_exit_line_max, uint, 0664);
 MODULE_PARM_DESC(vsync_line_threshold, "\n vsync_line_threshold\n");
 module_param(vsync_line_threshold, uint, 0664);
+MODULE_PARM_DESC(line_threshold, "\n line_threshold\n");
+module_param(line_threshold, uint, 0664);
 
 static unsigned int osd_filter_coefs_bicubic_sharp[] = {
        0x01fa008c, 0x01fa0100, 0xff7f0200, 0xfe7f0300,
@@ -692,48 +849,44 @@ static void f2v_get_vertical_phase(
 static bool osd_hdr_on;
 #endif
 
-static int cnt;
-#ifdef CONFIG_AMLOGIC_MEDIA_FB_OSD_SYNC_FENCE
 static int get_encp_line(void)
 {
        int enc_line = 0;
+       int active_line_begin = 0;
+       unsigned int reg = 0;
 
        switch (osd_reg_read(VPU_VIU_VENC_MUX_CTRL) & 0x3) {
        case 0:
-               enc_line = (osd_reg_read(ENCL_INFO_READ) >> 16) & 0x1fff;
+               reg = osd_reg_read(ENCL_INFO_READ);
+               active_line_begin =
+                       osd_reg_read(ENCL_VIDEO_VAVON_BLINE);
                break;
        case 1:
-               enc_line = (osd_reg_read(ENCI_INFO_READ) >> 16) & 0x1fff;
+               reg = osd_reg_read(ENCI_INFO_READ);
+               active_line_begin =
+                       osd_reg_read(ENCI_VFIFO2VD_LINE_TOP_START);
                break;
        case 2:
-               enc_line = (osd_reg_read(ENCP_INFO_READ) >> 16) & 0x1fff;
+               reg = osd_reg_read(ENCP_INFO_READ);
+               active_line_begin =
+                       osd_reg_read(ENCP_VIDEO_VAVON_BLINE);
                break;
        case 3:
-               enc_line = (osd_reg_read(ENCT_INFO_READ) >> 16) & 0x1fff;
+               reg = osd_reg_read(ENCT_INFO_READ);
+               active_line_begin =
+                       osd_reg_read(ENCT_VIDEO_VAVON_BLINE);
                break;
        }
+       enc_line = (reg >> 16) & 0x1fff;
+       enc_line -= active_line_begin;
        return enc_line;
 }
-#endif
 
 static int get_enter_encp_line(void)
 {
        int enc_line = 0;
 
-       switch (osd_reg_read(VPU_VIU_VENC_MUX_CTRL) & 0x3) {
-       case 0:
-               enc_line = (osd_reg_read(ENCL_INFO_READ) >> 16) & 0x1fff;
-               break;
-       case 1:
-               enc_line = (osd_reg_read(ENCI_INFO_READ) >> 16) & 0x1fff;
-               break;
-       case 2:
-               enc_line = (osd_reg_read(ENCP_INFO_READ) >> 16) & 0x1fff;
-               break;
-       case 3:
-               enc_line = (osd_reg_read(ENCT_INFO_READ) >> 16) & 0x1fff;
-               break;
-       }
+       enc_line = get_encp_line();
        if (enc_line > vsync_enter_line_max)
                vsync_enter_line_max = enc_line;
        return enc_line;
@@ -743,20 +896,7 @@ static int get_exit_encp_line(void)
 {
        int enc_line = 0;
 
-       switch (osd_reg_read(VPU_VIU_VENC_MUX_CTRL) & 0x3) {
-       case 0:
-               enc_line = (osd_reg_read(ENCL_INFO_READ) >> 16) & 0x1fff;
-               break;
-       case 1:
-               enc_line = (osd_reg_read(ENCI_INFO_READ) >> 16) & 0x1fff;
-               break;
-       case 2:
-               enc_line = (osd_reg_read(ENCP_INFO_READ) >> 16) & 0x1fff;
-               break;
-       case 3:
-               enc_line = (osd_reg_read(ENCT_INFO_READ) >> 16) & 0x1fff;
-               break;
-       }
+       enc_line = get_encp_line();
        if (enc_line > vsync_exit_line_max)
                vsync_exit_line_max = enc_line;
        return enc_line;
@@ -809,12 +949,40 @@ static void osd_vpu_power_on_viu2(void)
 #endif
 }
 
-static int get_osd_hwc_type(void)
+u32 get_output_device_id(u32 index)
+{
+       u32 output_index = VIU1;
+
+       if (osd_hw.osd_meson_dev.has_viu2) {
+               switch (osd_hw.osd_meson_dev.cpu_id) {
+               case __MESON_CPU_MAJOR_ID_G12A:
+               case __MESON_CPU_MAJOR_ID_G12B:
+                       if (index == osd_hw.osd_meson_dev.viu2_index)
+                               output_index = VIU2;
+                       else
+                               output_index = VIU1;
+                       break;
+               case __MESON_CPU_MAJOR_ID_TL1:
+                       if (index == osd_hw.osd_meson_dev.viu2_index)
+                               output_index = VIU2;
+                       else
+                               output_index = VIU1;
+                       break;
+               default:
+                       break;
+               }
+       }
+       return output_index;
+}
+
+static int get_osd_hwc_type(u32 index)
 {
        int ret = 0;
+       u32 output_index;
 
+       output_index = get_output_device_id(index);
        /* new hwcomposer enable */
-       if (osd_hw.hwc_enable) {
+       if (osd_hw.hwc_enable[output_index]) {
                if (osd_hw.osd_meson_dev.osd_ver == OSD_HIGH_ONE)
                        ret = OSD_G12A_NEW_HWC;
                else
@@ -844,10 +1012,10 @@ static void osd_toggle_buffer_single(struct kthread_work *work)
        struct osd_fence_map_s *data, *next;
        struct list_head saved_list;
 
-       mutex_lock(&post_fence_list_lock);
-       saved_list = post_fence_list;
-       list_replace_init(&post_fence_list, &saved_list);
-       mutex_unlock(&post_fence_list_lock);
+       mutex_lock(&post_fence_list_lock[VIU1]);
+       saved_list = post_fence_list[VIU1];
+       list_replace_init(&post_fence_list[VIU1], &saved_list);
+       mutex_unlock(&post_fence_list_lock[VIU1]);
        list_for_each_entry_safe(data, next, &saved_list, list) {
                osd_pan_display_single_fence(data);
                list_del(&data->list);
@@ -860,10 +1028,10 @@ static void osd_toggle_buffer_layers(struct kthread_work *work)
        struct osd_layers_fence_map_s *data, *next;
        struct list_head saved_list;
 
-       mutex_lock(&post_fence_list_lock);
-       saved_list = post_fence_list;
-       list_replace_init(&post_fence_list, &saved_list);
-       mutex_unlock(&post_fence_list_lock);
+       mutex_lock(&post_fence_list_lock[VIU1]);
+       saved_list = post_fence_list[VIU1];
+       list_replace_init(&post_fence_list[VIU1], &saved_list);
+       mutex_unlock(&post_fence_list_lock[VIU1]);
        list_for_each_entry_safe(data, next, &saved_list, list) {
                osd_pan_display_layers_fence(data);
                list_del(&data->list);
@@ -874,38 +1042,94 @@ static void osd_toggle_buffer_layers(struct kthread_work *work)
 
 static void osd_toggle_buffer(struct kthread_work *work)
 {
-       osd_hw.osd_fence[osd_hw.hwc_enable].
-               toggle_buffer_handler(work);
+       u32 hwc_enable;
+
+       hwc_enable = osd_hw.hwc_enable[VIU1];
+       if (osd_hw.osd_fence[VIU1][hwc_enable].toggle_buffer_handler)
+               osd_hw.osd_fence[VIU1][hwc_enable]
+                       .toggle_buffer_handler(work);
+}
+
+static void osd_toggle_buffer_single_viu2(struct kthread_work *work)
+{
+       struct osd_fence_map_s *data, *next;
+       struct list_head saved_list;
+
+       mutex_lock(&post_fence_list_lock[VIU2]);
+       saved_list = post_fence_list[VIU2];
+       list_replace_init(&post_fence_list[VIU2], &saved_list);
+       mutex_unlock(&post_fence_list_lock[VIU2]);
+       list_for_each_entry_safe(data, next, &saved_list, list) {
+               osd_pan_display_single_fence_viu2(data);
+               list_del(&data->list);
+               kfree(data);
+       }
+}
+
+static void osd_toggle_buffer_layers_viu2(struct kthread_work *work)
+{
+       struct osd_layers_fence_map_s *data, *next;
+       struct list_head saved_list;
+
+       mutex_lock(&post_fence_list_lock[VIU2]);
+       saved_list = post_fence_list[VIU2];
+       list_replace_init(&post_fence_list[VIU2], &saved_list);
+       mutex_unlock(&post_fence_list_lock[VIU2]);
+       list_for_each_entry_safe(data, next, &saved_list, list) {
+               osd_pan_display_layers_fence_viu2(data);
+               list_del(&data->list);
+               kfree(data);
+       }
+}
+
+static void osd_toggle_buffer_viu2(struct kthread_work *work)
+{
+       u32 hwc_enable;
+
+       hwc_enable = osd_hw.hwc_enable[VIU2];
+       if (osd_hw.osd_fence[VIU2][hwc_enable].toggle_buffer_handler)
+               osd_hw.osd_fence[VIU2][hwc_enable]
+                       .toggle_buffer_handler(work);
 }
 
-static int out_fence_create(int *release_fence_fd)
+static int out_fence_create(u32 output_index, int *release_fence_fd)
 {
        int out_fence_fd = -1;
        struct sched_param param = {.sched_priority = 2};
+       char toggle_thread_name[32] = {};
 
-       if (!timeline_created) {
+       if (!timeline_created[output_index]) {
                /* timeline has not been created */
-               if (osd_timeline_create()) {
-                       kthread_init_worker(&buffer_toggle_worker);
-                       buffer_toggle_thread = kthread_run(
+               if (osd_timeline_create(output_index)) {
+                       kthread_init_worker
+                               (&buffer_toggle_worker[output_index]);
+                       sprintf(toggle_thread_name,
+                               "aml_buf_toggle_%d", output_index);
+                       buffer_toggle_thread[output_index] = kthread_run(
                                        kthread_worker_fn,
-                                       &buffer_toggle_worker,
-                                       "aml_buf_toggle");
-                       if (IS_ERR(buffer_toggle_thread)) {
+                                       &buffer_toggle_worker[output_index],
+                                       toggle_thread_name);
+                       if (IS_ERR(buffer_toggle_thread[output_index])) {
                                osd_log_err("create osd toggle kthread failed");
                                return -1;
                        }
-                       sched_setscheduler(buffer_toggle_thread,
-                                       SCHED_FIFO, &param);
-                       kthread_init_work(
-                                       &buffer_toggle_work, osd_toggle_buffer);
-                       timeline_created = 1;
+                       sched_setscheduler(buffer_toggle_thread[output_index],
+                                          SCHED_FIFO, &param);
+                       if (output_index == VIU1)
+                               kthread_init_work(
+                                       &buffer_toggle_work[output_index],
+                                       osd_toggle_buffer);
+                       else if (output_index == VIU2)
+                               kthread_init_work(
+                                       &buffer_toggle_work[output_index],
+                                       osd_toggle_buffer_viu2);
+                       timeline_created[output_index] = 1;
                }
        }
 
        /* hwc_enable disable create fence every time */
-       if (!osd_hw.hwc_enable) {
-               out_fence_fd = osd_timeline_create_fence();
+       if (!osd_hw.hwc_enable[output_index]) {
+               out_fence_fd = osd_timeline_create_fence(output_index);
                if (out_fence_fd < 0) {
                        osd_log_err("fence obj create fail\n");
                        out_fence_fd = -1;
@@ -914,15 +1138,16 @@ static int out_fence_create(int *release_fence_fd)
                /* hwc_enable enable create fence
                 * when first sync request called
                 */
-               if (osd_hw.out_fence_fd == -1) {
-                       out_fence_fd = osd_timeline_create_fence();
+               if (osd_hw.out_fence_fd[output_index] == -1) {
+                       out_fence_fd = osd_timeline_create_fence(output_index);
                        if (out_fence_fd < 0) {
                                osd_log_err("fence obj create fail\n");
                                out_fence_fd = -1;
                        }
-                       osd_hw.out_fence_fd = out_fence_fd;
-               } else
-                       out_fence_fd = osd_hw.out_fence_fd;
+                       osd_hw.out_fence_fd[output_index] = out_fence_fd;
+               } else {
+                       out_fence_fd = osd_hw.out_fence_fd[output_index];
+               }
        }
        if (release_fence_fd)
                *release_fence_fd = out_fence_fd;
@@ -934,17 +1159,19 @@ int osd_sync_request(u32 index, u32 yres, struct fb_sync_request_s *request)
        int out_fence_fd = -1;
        int buf_num = 0;
        int in_fence_fd = -1;
+       u32 output_index = 0;
        struct osd_fence_map_s *fence_map =
                kzalloc(sizeof(struct osd_fence_map_s), GFP_KERNEL);
 
-       osd_hw.hwc_enable = 0;
+       output_index = get_output_device_id(index);
+       osd_hw.hwc_enable[output_index] = 0;
        if (request->sync_req.magic == FB_SYNC_REQUEST_MAGIC) {
                buf_num = find_buf_num(yres, request->sync_req.yoffset);
                if (!fence_map) {
                        osd_log_err("could not allocate osd_fence_map\n");
                        return -ENOMEM;
                }
-               mutex_lock(&post_fence_list_lock);
+               mutex_lock(&post_fence_list_lock[output_index]);
                fence_map->op = 0xffffffff;
                fence_map->fb_index = index;
                fence_map->buf_num = buf_num;
@@ -958,14 +1185,14 @@ int osd_sync_request(u32 index, u32 yres, struct fb_sync_request_s *request)
                fence_map->in_fence = osd_get_fenceobj(
                        request->sync_req.in_fen_fd);
                fence_map->out_fd =
-                       out_fence_create(&out_fence_fd);
+                       out_fence_create(output_index, &out_fence_fd);
        } else {
                buf_num = find_buf_num(yres, request->sync_req_old.yoffset);
                if (!fence_map) {
                        osd_log_err("could not allocate osd_fence_map\n");
                        return -ENOMEM;
                }
-               mutex_lock(&post_fence_list_lock);
+               mutex_lock(&post_fence_list_lock[output_index]);
                fence_map->op = 0xffffffff;
                fence_map->fb_index = index;
                fence_map->buf_num = buf_num;
@@ -978,11 +1205,12 @@ int osd_sync_request(u32 index, u32 yres, struct fb_sync_request_s *request)
                fence_map->in_fence = osd_get_fenceobj(
                                request->sync_req_old.in_fen_fd);
                fence_map->out_fd =
-                       out_fence_create(&out_fence_fd);
+                       out_fence_create(output_index, &out_fence_fd);
        }
-       list_add_tail(&fence_map->list, &post_fence_list);
-       mutex_unlock(&post_fence_list_lock);
-       kthread_queue_work(&buffer_toggle_worker, &buffer_toggle_work);
+       list_add_tail(&fence_map->list, &post_fence_list[output_index]);
+       mutex_unlock(&post_fence_list_lock[output_index]);
+       kthread_queue_work(&buffer_toggle_worker[output_index],
+                          &buffer_toggle_work[output_index]);
        if (in_fence_fd >= 0)
                __close_fd(current->files, in_fence_fd);
        return  out_fence_fd;
@@ -997,6 +1225,7 @@ static int sync_render_single_fence(u32 index, u32 yres,
        int out_fence_fd = -1;
        int buf_num = 0;
        u32 xoffset, yoffset;
+       u32 output_index = 0;
        struct osd_fence_map_s *fence_map =  NULL;
 
        if (index > OSD1)
@@ -1009,7 +1238,8 @@ static int sync_render_single_fence(u32 index, u32 yres,
                osd_log_err("could not allocate osd_fence_map\n");
                return -ENOMEM;
        }
-       mutex_lock(&post_fence_list_lock);
+       output_index = get_output_device_id(index);
+       mutex_lock(&post_fence_list_lock[output_index]);
        fence_map->op = 0xffffffff;
        fence_map->fb_index = index;
        fence_map->buf_num = buf_num;
@@ -1037,13 +1267,15 @@ static int sync_render_single_fence(u32 index, u32 yres,
        osd_tprintk("direct render fence fd:%d\n", fence_map->in_fd);
        fence_map->in_fence = osd_get_fenceobj(fence_map->in_fd);
        fence_map->out_fd =
-               out_fence_create(&out_fence_fd);
+               out_fence_create(output_index, &out_fence_fd);
        /* Todo: */
-       list_add_tail(&fence_map->list, &post_fence_list);
-       mutex_unlock(&post_fence_list_lock);
-       kthread_queue_work(&buffer_toggle_worker, &buffer_toggle_work);
+       list_add_tail(&fence_map->list, &post_fence_list[output_index]);
+       mutex_unlock(&post_fence_list_lock[output_index]);
+       kthread_queue_work(&buffer_toggle_worker[output_index],
+                          &buffer_toggle_work[output_index]);
        request->out_fen_fd = out_fence_fd;
-       __close_fd(current->files, request->in_fen_fd);
+       if (request->in_fen_fd >= 0)
+               __close_fd(current->files, request->in_fen_fd);
        return out_fence_fd;
 }
 
@@ -1054,13 +1286,15 @@ static int sync_render_layers_fence(u32 index, u32 yres,
 {
        int out_fence_fd = -1;
        s32 in_fence_fd;
+       u32 output_index = 0;
        struct osd_layers_fence_map_s *fence_map = NULL;
 
        if (index > OSD_MAX)
                return -1;
+       output_index = get_output_device_id(index);
        in_fence_fd = request->in_fen_fd;
-       mutex_lock(&post_fence_list_lock);
-       fence_map = &map_layers;
+       mutex_lock(&post_fence_list_lock[output_index]);
+       fence_map = &map_layers[output_index];
        fence_map->cmd = LAYER_SYNC;
        fence_map->layer_map[index].fb_index = index;
        /* layer_map[index].enable will update if have blank ioctl */
@@ -1101,15 +1335,17 @@ static int sync_render_layers_fence(u32 index, u32 yres,
        /* no longer put list, will put them via do_hwc */
        fence_map->layer_map[index].in_fence = osd_get_fenceobj(in_fence_fd);
        fence_map->layer_map[index].out_fd =
-               out_fence_create(&out_fence_fd);
-       mutex_unlock(&post_fence_list_lock);
+               out_fence_create(output_index, &out_fence_fd);
+       mutex_unlock(&post_fence_list_lock[output_index]);
        osd_log_dbg(MODULE_FENCE, "sync_render_layers_fence:osd%d: ind_fd=%d,out_fd=%d\n",
                fence_map->layer_map[index].fb_index,
                fence_map->layer_map[index].in_fd,
                fence_map->layer_map[index].out_fd);
        request->out_fen_fd = out_fence_fd;
-       __close_fd(current->files, in_fence_fd);
-       __close_fd(current->files, request->shared_fd);
+       if (in_fence_fd >= 0)
+               __close_fd(current->files, in_fence_fd);
+       if (request->shared_fd >= 0)
+               __close_fd(current->files, request->shared_fd);
        return out_fence_fd;
 }
 
@@ -1118,49 +1354,53 @@ int osd_sync_request_render(u32 index, u32 yres,
        u32 phys_addr,
        size_t len)
 {
-       int line;
+       int line, hwc_enable;
+       u32 output_index = 0;
 
-       cnt++;
        line = get_encp_line();
+       output_index = get_output_device_id(index);
        osd_log_dbg2(MODULE_RENDER,
-                       "enter osd_sync_request_render:cnt=%d,encp line=%d\n",
-                       cnt, line);
+                       "enter osd_sync_request_render:encp line=%d\n",
+                       line);
        if (request->magic == FB_SYNC_REQUEST_RENDER_MAGIC_V1)
-               osd_hw.hwc_enable = 0;
+               osd_hw.hwc_enable[output_index] = 0;
        else if (request->magic == FB_SYNC_REQUEST_RENDER_MAGIC_V2)
-               osd_hw.hwc_enable = 1;
-       if (index == OSD4)
-               osd_hw.viu_type = VIU2;
-       else
-               osd_hw.viu_type = VIU1;
-       osd_hw.osd_fence[osd_hw.hwc_enable].sync_fence_handler(
-               index, yres, request, phys_addr, len);
+               osd_hw.hwc_enable[output_index] = 1;
+       output_index = get_output_device_id(index);
+       hwc_enable = osd_hw.hwc_enable[output_index];
+
+       if (osd_hw.osd_fence[output_index][hwc_enable].sync_fence_handler)
+               osd_hw.osd_fence[output_index][hwc_enable]
+                       .sync_fence_handler(index, yres,
+                       request, phys_addr, len);
        return request->out_fen_fd;
 }
 
-int osd_sync_do_hwc(struct do_hwc_cmd_s *hwc_cmd)
+int osd_sync_do_hwc(u32 index, struct do_hwc_cmd_s *hwc_cmd)
 {
        int out_fence_fd = -1;
        struct osd_layers_fence_map_s *fence_map = NULL;
        int line;
+       u32 output_index = 0;
 
+       output_index = get_output_device_id(index);
        line = get_encp_line();
        osd_log_dbg2(MODULE_RENDER,
-               "enter osd_sync_do_hwc:cnt=%d,encp line=%d\n",
-               cnt, line);
+               "enter osd_sync_do_hwc:encp line=%d\n",
+               line);
        fence_map = kzalloc(
                sizeof(struct osd_layers_fence_map_s), GFP_KERNEL);
        if (!fence_map)
                return -ENOMEM;
-       osd_hw.hwc_enable = 1;
-       mutex_lock(&post_fence_list_lock);
-       memcpy(fence_map, &map_layers,
-               sizeof(struct osd_layers_fence_map_s));
+       osd_hw.hwc_enable[output_index] = 1;
+       mutex_lock(&post_fence_list_lock[output_index]);
+       memcpy(fence_map, &map_layers[output_index],
+              sizeof(struct osd_layers_fence_map_s));
        /* clear map_layers, need alloc next add_sync ioctl */
-       memset(&map_layers, 0,
-               sizeof(struct osd_layers_fence_map_s));
+       memset(&map_layers[output_index], 0,
+              sizeof(struct osd_layers_fence_map_s));
        fence_map->out_fd =
-               out_fence_create(&out_fence_fd);
+               out_fence_create(output_index, &out_fence_fd);
        fence_map->disp_info.background_w =
                hwc_cmd->disp_info.background_w;
        fence_map->disp_info.background_h =
@@ -1179,12 +1419,14 @@ int osd_sync_do_hwc(struct do_hwc_cmd_s *hwc_cmd)
                hwc_cmd->disp_info.position_h;
        fence_map->hdr_mode = hwc_cmd->hdr_mode;
        /* other info set via add_sync and blank ioctl */
-       list_add_tail(&fence_map->list, &post_fence_list);
+       list_add_tail(&fence_map->list, &post_fence_list[output_index]);
        /* after do_hwc, clear osd_hw.out_fence_fd */
-       if (timeline_created && osd_hw.out_fence_fd)
-               osd_hw.out_fence_fd = -1;
-       mutex_unlock(&post_fence_list_lock);
-       kthread_queue_work(&buffer_toggle_worker, &buffer_toggle_work);
+       if (timeline_created[output_index] &&
+           osd_hw.out_fence_fd[output_index])
+               osd_hw.out_fence_fd[output_index] = -1;
+       mutex_unlock(&post_fence_list_lock[output_index]);
+       kthread_queue_work(&buffer_toggle_worker[output_index],
+                          &buffer_toggle_work[output_index]);
        if (get_logo_loaded()) {
                int logo_index;
 
@@ -1258,7 +1500,7 @@ int osd_sync_request_render(u32 index, u32 yres,
        return -5566;
 }
 
-int osd_sync_do_hwc(struct do_hwc_cmd_s *hwc_cmd)
+int osd_sync_do_hwc(u32 output_index, struct do_hwc_cmd_s *hwc_cmd)
 {
        osd_log_err("osd_do_hwc not supported\n");
        return -5566;
@@ -1268,7 +1510,10 @@ int osd_sync_do_hwc(struct do_hwc_cmd_s *hwc_cmd)
 
 void osd_set_enable_hw(u32 index, u32 enable)
 {
-       if (osd_hw.hwc_enable) {
+       u32 output_index = 0;
+
+       output_index = get_output_device_id(index);
+       if (osd_hw.hwc_enable[output_index]) {
                if (index > OSD_MAX)
                        return;
                if ((osd_hw.osd_meson_dev.osd_ver < OSD_HIGH_ONE)
@@ -1276,11 +1521,13 @@ void osd_set_enable_hw(u32 index, u32 enable)
                        osd_enable_hw(index, enable);
                else {
 #ifdef CONFIG_AMLOGIC_MEDIA_FB_OSD_SYNC_FENCE
-                       mutex_lock(&post_fence_list_lock);
-                       map_layers.layer_map[index].fb_index = index;
-                       map_layers.layer_map[index].enable = enable;
-                       map_layers.cmd = BLANK_CMD;
-                       mutex_unlock(&post_fence_list_lock);
+                       mutex_lock(&post_fence_list_lock[output_index]);
+                       map_layers[output_index].layer_map[index]
+                               .fb_index = index;
+                       map_layers[output_index].layer_map[index]
+                               .enable = enable;
+                       map_layers[output_index].cmd = BLANK_CMD;
+                       mutex_unlock(&post_fence_list_lock[output_index]);
                        osd_log_dbg(MODULE_BASE, "osd_set_enable_hw: osd%d,enable=%d\n",
                                index, enable);
 #endif
@@ -1441,7 +1688,6 @@ static void osd_update_interlace_mode(int index)
 {
        /* only called by vsync irq or rdma irq */
        unsigned int fb0_cfg_w0 = 0, fb1_cfg_w0 = 0;
-       unsigned int fb3_cfg_w0 = 0;
        unsigned int scan_line_number = 0;
        unsigned int odd_even;
 
@@ -1494,35 +1740,17 @@ static void osd_update_interlace_mode(int index)
        if ((index & (1 << OSD1)) == (1 << OSD1)) {
                VSYNCOSD_IRQ_WR_MPEG_REG(
                hw_osd_reg_array[OSD1].osd_blk0_cfg_w0, fb0_cfg_w0);
-               if (osd_hw.osd_meson_dev.osd_ver == OSD_HIGH_ONE)
-                       VSYNCOSD_IRQ_WR_MPEG_REG(
-                       hw_osd_reg_array[OSD3].osd_blk0_cfg_w0, fb0_cfg_w0);
+               if (osd_hw.osd_meson_dev.osd_ver == OSD_HIGH_ONE) {
+                       if ((osd_hw.osd_meson_dev.viu1_osd_count - 1) == OSD3)
+                               VSYNCOSD_IRQ_WR_MPEG_REG(
+                               hw_osd_reg_array[OSD3].osd_blk0_cfg_w0,
+                               fb0_cfg_w0);
+               }
        }
        if ((index & (1 << OSD2)) == (1 << OSD2))
                VSYNCOSD_IRQ_WR_MPEG_REG(
                hw_osd_reg_array[OSD2].osd_blk0_cfg_w0, fb1_cfg_w0);
 
-       if (osd_hw.powered[OSD4]) {
-               if (osd_hw.powered[OSD4])
-                       fb3_cfg_w0 = VSYNCOSD_RD_MPEG_REG(
-                       hw_osd_reg_array[OSD4].osd_blk0_cfg_w0);
-               if (osd_hw.scan_mode[OSD4] == SCAN_MODE_INTERLACE) {
-                       if ((osd_hw.pandata[OSD4].y_start % 2) == 1) {
-                               odd_even = (osd_reg_read(ENCI_INFO_READ) &
-                                       (1 << 29)) ? OSD_TYPE_TOP_FIELD :
-                                       OSD_TYPE_BOT_FIELD;
-                       } else {
-                               odd_even = (osd_reg_read(ENCI_INFO_READ)
-                               & (1 << 29)) ? OSD_TYPE_BOT_FIELD :
-                               OSD_TYPE_TOP_FIELD;
-                       }
-               }
-               fb3_cfg_w0 &= ~1;
-               fb3_cfg_w0 |= odd_even;
-               if ((index & (1 << OSD4)) == (1 << OSD4))
-                       VSYNCOSD_IRQ_WR_MPEG_REG(
-                       hw_osd_reg_array[OSD4].osd_blk0_cfg_w0, fb3_cfg_w0);
-       }
        spin_unlock_irqrestore(&osd_lock, lock_flags);
 }
 
@@ -1531,18 +1759,26 @@ void osd_update_scan_mode(void)
        /* only called by vsync irq or rdma irq */
        unsigned int output_type = 0;
        int index = 0;
+       int viu2_index = osd_hw.osd_meson_dev.viu2_index;
+       int osd_count = osd_hw.osd_meson_dev.viu1_osd_count;
+       int has_osd3 = 0;
 
+       if ((osd_count - 1) == OSD3)
+               has_osd3 = 1;
+       //todo: Karry
        output_type = osd_reg_read(VPU_VIU_VENC_MUX_CTRL) & 0x3;
        osd_hw.scan_mode[OSD1] = SCAN_MODE_PROGRESSIVE;
        osd_hw.scan_mode[OSD2] = SCAN_MODE_PROGRESSIVE;
-       osd_hw.scan_mode[OSD3] = SCAN_MODE_PROGRESSIVE;
-       osd_hw.scan_mode[OSD4] = SCAN_MODE_PROGRESSIVE;
+       if (has_osd3)
+               osd_hw.scan_mode[OSD3] = SCAN_MODE_PROGRESSIVE;
+       osd_hw.scan_mode[viu2_index] = SCAN_MODE_PROGRESSIVE;
        switch (output_type) {
        case VOUT_ENCP:
                if (osd_reg_read(ENCP_VIDEO_MODE) & (1 << 12)) {
                        /* 1080i */
                        osd_hw.scan_mode[OSD1] = SCAN_MODE_INTERLACE;
                        osd_hw.scan_mode[OSD2] = SCAN_MODE_INTERLACE;
+                       if (has_osd3)
                        osd_hw.scan_mode[OSD3] = SCAN_MODE_INTERLACE;
                }
                break;
@@ -1550,25 +1786,11 @@ void osd_update_scan_mode(void)
                if (osd_reg_read(ENCI_VIDEO_EN) & 1) {
                        osd_hw.scan_mode[OSD1] = SCAN_MODE_INTERLACE;
                        osd_hw.scan_mode[OSD2] = SCAN_MODE_INTERLACE;
+                       if (has_osd3)
                        osd_hw.scan_mode[OSD3] = SCAN_MODE_INTERLACE;
                }
                break;
        }
-       if (osd_hw.powered[OSD4]) {
-               output_type = (osd_reg_read(VPU_VIU_VENC_MUX_CTRL) >> 2) & 0x3;
-               switch (output_type) {
-               case VOUT_ENCP:
-                       if (osd_reg_read(ENCP_VIDEO_MODE) & (1 << 12))
-                               /* 1080i */
-                               osd_hw.scan_mode[OSD4] = SCAN_MODE_INTERLACE;
-                       break;
-               case VOUT_ENCI:
-                       if (osd_reg_read(ENCI_VIDEO_EN) & 1)
-                               osd_hw.scan_mode[OSD4] = SCAN_MODE_INTERLACE;
-                       break;
-               }
-
-       }
        if (osd_hw.hw_cursor_en) {
                /* 3 layers osd don't support osd2 cursor */
                if (osd_hw.free_scale_enable[OSD1])
@@ -1593,11 +1815,72 @@ void osd_update_scan_mode(void)
                }
        }
        if ((osd_hw.scan_mode[OSD1] == SCAN_MODE_INTERLACE)
-               || (osd_hw.scan_mode[OSD2] == SCAN_MODE_INTERLACE)
-               || (osd_hw.scan_mode[OSD4] == SCAN_MODE_INTERLACE))
+               || (osd_hw.scan_mode[OSD2] == SCAN_MODE_INTERLACE))
                osd_update_interlace_mode(index);
 }
 
+static void osd_update_interlace_mode_viu2(void)
+{
+       /* only called by vsync irq or rdma irq */
+       unsigned int fb3_cfg_w0 = 0;
+       unsigned int odd_even = 0;
+       u32 viu2_index;
+
+       spin_lock_irqsave(&osd_lock, lock_flags);
+       viu2_index = osd_hw.osd_meson_dev.viu2_index;
+       if (osd_hw.powered[viu2_index]) {
+               fb3_cfg_w0 = VSYNCOSD_RD_MPEG_REG(
+                       hw_osd_reg_array[viu2_index].osd_blk0_cfg_w0);
+               if (osd_hw.scan_mode[viu2_index] == SCAN_MODE_INTERLACE) {
+                       if ((osd_hw.pandata[viu2_index].y_start % 2) == 1) {
+                               odd_even = (osd_reg_read(ENCI_INFO_READ) &
+                                       (1 << 29)) ? OSD_TYPE_TOP_FIELD :
+                                       OSD_TYPE_BOT_FIELD;
+                       } else {
+                               odd_even = (osd_reg_read(ENCI_INFO_READ)
+                               & (1 << 29)) ? OSD_TYPE_BOT_FIELD :
+                               OSD_TYPE_TOP_FIELD;
+                       }
+               }
+               fb3_cfg_w0 &= ~1;
+               fb3_cfg_w0 |= odd_even;
+               VSYNCOSD_IRQ_WR_MPEG_REG(
+                       hw_osd_reg_array[viu2_index].osd_blk0_cfg_w0,
+                       fb3_cfg_w0);
+       }
+       spin_unlock_irqrestore(&osd_lock, lock_flags);
+}
+
+void osd_update_scan_mode_viu2(void)
+{
+       /* only called by vsync irq or rdma irq */
+       unsigned int output_type = 0;
+       int viu2_index = osd_hw.osd_meson_dev.viu2_index;
+
+       output_type = osd_reg_read(VPU_VIU_VENC_MUX_CTRL) & 0x3;
+       osd_hw.scan_mode[viu2_index] = SCAN_MODE_PROGRESSIVE;
+       if (osd_hw.powered[viu2_index]) {
+               output_type = (osd_reg_read(VPU_VIU_VENC_MUX_CTRL)
+                       >> 2) & 0x3;
+               switch (output_type) {
+               case VOUT_ENCP:
+                       if (osd_reg_read(ENCP_VIDEO_MODE) & (1 << 12))
+                               /* 1080i */
+                               osd_hw.scan_mode[viu2_index] =
+                               SCAN_MODE_INTERLACE;
+                       break;
+               case VOUT_ENCI:
+                       if (osd_reg_read(ENCI_VIDEO_EN) & 1)
+                               osd_hw.scan_mode[viu2_index] =
+                               SCAN_MODE_INTERLACE;
+                       break;
+               }
+
+       }
+       if (osd_hw.scan_mode[viu2_index] == SCAN_MODE_INTERLACE)
+               osd_update_interlace_mode_viu2();
+}
+
 //not rdma will call update func;
 void walk_through_update_list(void)
 {
@@ -1624,7 +1907,8 @@ static bool mali_afbc_get_error(void)
 
        status = VSYNCOSD_RD_MPEG_REG(VPU_MAFBC_IRQ_RAW_STATUS);
        if (status & 0x3c) {
-               osd_log_dbg(MODULE_BASE, "afbc error happened\n");
+               osd_log_dbg(MODULE_BASE,
+                       "afbc error happened,status=0x%x\n", status);
                osd_hw.afbc_err_cnt++;
                error = true;
        }
@@ -1852,6 +2136,7 @@ static void osd_viu2_fiq_isr(void)
 static irqreturn_t vsync_viu2_isr(int irq, void *dev_id)
 #endif
 {
+       osd_update_scan_mode_viu2();
 #ifndef FIQ_VSYNC
        return IRQ_HANDLED;
 #endif
@@ -1902,8 +2187,16 @@ void osd_wait_vsync_hw(void)
 
                if (pxp_mode)
                        timeout = msecs_to_jiffies(50);
-               else
-               timeout = msecs_to_jiffies(1000);
+               else {
+                       struct vinfo_s *vinfo;
+
+                       vinfo = get_current_vinfo();
+                       if (vinfo && (!strcmp(vinfo->name, "invalid") ||
+                               !strcmp(vinfo->name, "null"))) {
+                               timeout = msecs_to_jiffies(1);
+                       } else
+                               timeout = msecs_to_jiffies(1000);
+               }
                wait_event_interruptible_timeout(
                                osd_vsync_wq, vsync_hit, timeout);
        }
@@ -1928,6 +2221,8 @@ s64 osd_wait_vsync_event(void)
 
 int is_interlaced(struct vinfo_s *vinfo)
 {
+       if (!vinfo)
+               return 0;
        if (vinfo->mode == VMODE_CVBS)
                return 1;
        if (vinfo->height != vinfo->field_height)
@@ -1938,12 +2233,19 @@ int is_interlaced(struct vinfo_s *vinfo)
 
 int osd_set_scan_mode(u32 index)
 {
-       struct vinfo_s *vinfo;
+       struct vinfo_s *vinfo = NULL;
        u32 data32 = 0x0;
        s32 y_end = 0;
+       u32 output_index;
 
+       output_index = get_output_device_id(index);
        osd_hw.scan_mode[index] = SCAN_MODE_PROGRESSIVE;
-       vinfo = get_current_vinfo();
+       if (output_index == VIU1)
+               vinfo = get_current_vinfo();
+#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
+               else if (output_index == VIU2)
+                       vinfo = get_current_vinfo2();
+#endif
        if (vinfo && (strcmp(vinfo->name, "invalid") &&
                strcmp(vinfo->name, "null"))) {
                osd_hw.scale_workaround = 0;
@@ -1959,7 +2261,7 @@ int osd_set_scan_mode(u32 index)
                        if ((vinfo->width == 720)
                                && (vinfo->height == 480)) {
                                if (osd_hw.free_scale_mode[index]) {
-                                       osd_hw.field_out_en = 1;
+                                       osd_hw.field_out_en[output_index] = 1;
                                        switch (y_end) {
                                        case 719:
                                                osd_hw.bot_type = 2;
@@ -1979,7 +2281,7 @@ int osd_set_scan_mode(u32 index)
                        } else if ((vinfo->width == 720)
                                && (vinfo->height == 576)) {
                                if (osd_hw.free_scale_mode[index]) {
-                                       osd_hw.field_out_en = 1;
+                                       osd_hw.field_out_en[output_index] = 1;
                                        switch (y_end) {
                                        case 719:
                                                osd_hw.bot_type = 2;
@@ -2000,7 +2302,7 @@ int osd_set_scan_mode(u32 index)
                        } else if ((vinfo->width == 1920)
                                && (vinfo->height == 1080)) {
                                if (osd_hw.free_scale_mode[index]) {
-                                       osd_hw.field_out_en = 1;
+                                       osd_hw.field_out_en[output_index] = 1;
                                        switch (y_end) {
                                        case 719:
                                                osd_hw.bot_type = 1;
@@ -2023,7 +2325,7 @@ int osd_set_scan_mode(u32 index)
                                        && (osd_hw.free_scale_enable[index]))
                                        if (!(osd_hw.osd_meson_dev.afbc_type))
                                                osd_hw.scale_workaround = 1;
-                               osd_hw.field_out_en = 0;
+                               osd_hw.field_out_en[output_index] = 0;
                        } else if (((vinfo->width == 720)
                                && (vinfo->height == 480))
                                || ((vinfo->width == 720)
@@ -2033,10 +2335,10 @@ int osd_set_scan_mode(u32 index)
                                        osd_v_filter_mode = 6;
                                }
                                if (osd_hw.free_scale_mode[index])
-                                       osd_hw.field_out_en = 0;
+                                       osd_hw.field_out_en[output_index] = 0;
                        } else {
                                if (osd_hw.free_scale_mode[index])
-                                       osd_hw.field_out_en = 0;
+                                       osd_hw.field_out_en[output_index] = 0;
                        }
                }
        }
@@ -2457,7 +2759,10 @@ static void osd_set_free_scale_enable_mode1(u32 index, u32 enable)
 
 void osd_set_free_scale_enable_hw(u32 index, u32 enable)
 {
-       if (osd_hw.free_scale_mode[index] && (index != OSD4)) {
+       if (osd_hw.free_scale_mode[index]
+               && (osd_hw.osd_meson_dev.has_viu2 ?
+                       ((index != osd_hw.osd_meson_dev.viu2_index) ?
+                               1 : 0) : 1)) {
                osd_set_free_scale_enable_mode1(index, enable);
                if (osd_hw.osd_meson_dev.osd_ver == OSD_NORMAL) {
                        u32 height_dst, height_src;
@@ -2552,11 +2857,18 @@ void osd_set_scale_axis_hw(u32 index, s32 x0, s32 y0, s32 x1, s32 y1)
 
 void osd_get_window_axis_hw(u32 index, s32 *x0, s32 *y0, s32 *x1, s32 *y1)
 {
-       struct vinfo_s *vinfo;
+       struct vinfo_s *vinfo = NULL;
        s32 height;
+       u32 output_index;
 
+       output_index = get_output_device_id(index);
        if (osd_hw.osd_meson_dev.osd_ver <= OSD_NORMAL) {
-               vinfo = get_current_vinfo();
+               if (output_index == VIU1)
+                       vinfo = get_current_vinfo();
+#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
+               else if (output_index == VIU2)
+                       vinfo = get_current_vinfo2();
+#endif
                if (vinfo && (strcmp(vinfo->name, "invalid") &&
                        strcmp(vinfo->name, "null"))) {
                        if (is_interlaced(vinfo)) {
@@ -2592,15 +2904,17 @@ void osd_get_window_axis_hw(u32 index, s32 *x0, s32 *y0, s32 *x1, s32 *y1)
 
 void osd_set_window_axis_hw(u32 index, s32 x0, s32 y0, s32 x1, s32 y1)
 {
-       struct vinfo_s *vinfo;
+       struct vinfo_s *vinfo = NULL;
        s32 temp_y0, temp_y1;
+       u32 output_index;
 
-       #if 0
-       if (osd_hw.hwc_enable &&
-               (osd_hw.osd_display_debug != OSD_DISP_DEBUG))
-               return;
-       #endif
-       vinfo = get_current_vinfo();
+       output_index = get_output_device_id(index);
+       if (output_index == VIU1)
+               vinfo = get_current_vinfo();
+#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
+       else if (output_index == VIU2)
+               vinfo = get_current_vinfo2();
+#endif
        mutex_lock(&osd_mutex);
        if (vinfo && (strcmp(vinfo->name, "invalid") &&
                strcmp(vinfo->name, "null"))) {
@@ -2637,13 +2951,12 @@ void osd_set_window_axis_hw(u32 index, s32 x0, s32 y0, s32 x1, s32 y1)
        if (osd_hw.free_dst_data[index].y_end >= 2159)
                osd_set_dummy_data(index, 0xff);
        osd_update_window_axis = true;
-       if (osd_hw.hwc_enable &&
-               (osd_hw.osd_display_debug == OSD_DISP_DEBUG))
-               osd_setting_blend();
+       if (osd_hw.hwc_enable[output_index] &&
+           (osd_hw.osd_display_debug == OSD_DISP_DEBUG))
+               osd_setting_blend(output_index);
        mutex_unlock(&osd_mutex);
 }
 
-
 s32 osd_get_position_from_reg(
        u32 index,
        s32 *src_x_start, s32 *src_x_end,
@@ -2654,7 +2967,7 @@ s32 osd_get_position_from_reg(
        struct hw_osd_reg_s *osd_reg = &hw_osd_reg_array[index];
        u32 data32 = 0x0;
 
-       if (index >= OSD4)
+       if (index >= OSD_MAX)
                return -1;
 
        if (!src_x_start || !src_x_end || !src_y_start || !src_y_end
@@ -2789,6 +3102,7 @@ void osd_enable_hw(u32 index, u32 enable)
 {
        int i = 0;
        int count = (pxp_mode == 1)?3:WAIT_AFBC_READY_COUNT;
+       u32 output_index;
 
        if (index == 0) {
                osd_log_info("osd[%d] enable: %d (%s)\n",
@@ -2800,8 +3114,8 @@ void osd_enable_hw(u32 index, u32 enable)
 
        /* reset viu 31bit ?? */
        if (!osd_hw.enable[index] &&
-                       osd_hw.osd_afbcd[index].enable && enable
-                       && (get_osd_hwc_type() != OSD_G12A_NEW_HWC)) {
+                       osd_hw.osd_afbcd[index].enable && enable &&
+                       (get_osd_hwc_type(index) != OSD_G12A_NEW_HWC)) {
                spin_lock_irqsave(&osd_lock, lock_flags);
                if (osd_hw.osd_meson_dev.afbc_type == MESON_AFBC) {
                        osd_reg_write(VIU_SW_RESET, 0x80000000);
@@ -2829,11 +3143,13 @@ void osd_enable_hw(u32 index, u32 enable)
        }
 
        osd_hw.enable[index] = enable;
-       if (get_osd_hwc_type() != OSD_G12A_NEW_HWC) {
+       output_index = get_output_device_id(index);
+       if (get_osd_hwc_type(index) != OSD_G12A_NEW_HWC) {
                add_to_update_list(index, OSD_ENABLE);
                osd_wait_vsync_hw();
-       } else if (osd_hw.hwc_enable && osd_hw.osd_display_debug)
-               osd_setting_blend();
+       } else if (osd_hw.hwc_enable[output_index] &&
+               osd_hw.osd_display_debug)
+               osd_setting_blend(output_index);
 }
 
 void osd_set_2x_scale_hw(u32 index, u16 h_scale_enable, u16 v_scale_enable)
@@ -2862,11 +3178,20 @@ void osd_set_2x_scale_hw(u32 index, u16 h_scale_enable, u16 v_scale_enable)
        osd_wait_vsync_hw();
 }
 
-void osd_get_flush_rate_hw(u32 *break_rate)
+void osd_get_flush_rate_hw(u32 index, u32 *break_rate)
 {
-       const struct vinfo_s *vinfo;
+       const struct vinfo_s *vinfo = NULL;
+       u32 output_index;
 
-       vinfo = get_current_vinfo();
+       output_index = get_output_device_id(index);
+       if (output_index == VIU1)
+               vinfo = get_current_vinfo();
+#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
+       else if (output_index == VIU2)
+               vinfo = get_current_vinfo2();
+#endif
+       if (!vinfo)
+               return;
        *break_rate = vinfo->sync_duration_num / vinfo->sync_duration_den;
 }
 
@@ -3151,26 +3476,33 @@ void osd_set_deband(u32 osd_deband_enable)
 }
 
 
-void osd_get_fps(u32 *osd_fps)
+void osd_get_fps(u32 index, u32 *osd_fps)
 {
-       *osd_fps = osd_hw.osd_fps;
+       u32 output_index;
+
+       output_index = get_output_device_id(index);
+       *osd_fps = osd_hw.osd_fps[output_index];
+
 }
 
-void osd_set_fps(u32 osd_fps_start)
+void osd_set_fps(u32 index, u32 osd_fps_start)
 {
        static int stime, etime;
+       u32 output_index;
 
-       osd_hw.osd_fps_start = osd_fps_start;
+       output_index = get_output_device_id(index);
+       osd_hw.osd_fps_start[output_index] = osd_fps_start;
        if (osd_fps_start) {
                /* start to calc fps */
                stime = ktime_to_us(ktime_get());
-               osd_hw.osd_fps = 0;
+               osd_hw.osd_fps[output_index] = 0;
        } else {
                /* stop to calc fps */
                etime = ktime_to_us(ktime_get());
-               osd_hw.osd_fps = (osd_hw.osd_fps * 1000000)
+               osd_hw.osd_fps[output_index] =
+                       (osd_hw.osd_fps[output_index] * 1000000)
                        / (etime - stime);
-               osd_log_info("osd fps:=%d\n", osd_hw.osd_fps);
+               osd_log_info("osd fps:=%d\n", osd_hw.osd_fps[output_index]);
        }
 }
 
@@ -3184,16 +3516,22 @@ void osd_set_display_debug(u32 osd_display_debug_enable)
        osd_hw.osd_display_debug = osd_display_debug_enable;
 }
 
-void osd_get_background_size(struct display_flip_info_s *disp_info)
+void osd_get_background_size(u32 index, struct display_flip_info_s *disp_info)
 {
-       memcpy(disp_info, &osd_hw.disp_info,
-               sizeof(struct display_flip_info_s));
+       u32 output_index;
+
+       output_index = get_output_device_id(index);
+       memcpy(disp_info, &osd_hw.disp_info[output_index],
+              sizeof(struct display_flip_info_s));
 }
 
-void osd_set_background_size(struct display_flip_info_s *disp_info)
+void osd_set_background_size(u32 index, struct display_flip_info_s *disp_info)
 {
-       memcpy(&osd_hw.disp_info, disp_info,
-               sizeof(struct display_flip_info_s));
+       u32 output_index;
+
+       output_index = get_output_device_id(index);
+       memcpy(&osd_hw.disp_info[output_index], disp_info,
+              sizeof(struct display_flip_info_s));
 }
 
 void osd_get_hdr_used(u32 *val)
@@ -3218,22 +3556,31 @@ void osd_set_afbc_format(u32 index, u32 format, u32 inter_format)
        osd_hw.osd_afbcd[index].inter_format = inter_format;
 }
 
-void osd_get_hwc_enable(u32 *hwc_enable)
+void osd_get_hwc_enable(u32 index, u32 *hwc_enable)
 {
-       *hwc_enable = osd_hw.hwc_enable;
+       u32 output_index;
+
+       output_index = get_output_device_id(index);
+       *hwc_enable = osd_hw.hwc_enable[output_index];
 }
 
-void osd_set_hwc_enable(u32 hwc_enable)
+void osd_set_hwc_enable(u32 index, u32 hwc_enable)
 {
-       osd_hw.hwc_enable = hwc_enable;
+       u32 output_index;
+
+       output_index = get_output_device_id(index);
+       osd_hw.hwc_enable[output_index] = hwc_enable;
        /* setting default hwc path */
        if (!hwc_enable)
-               osd_setting_blend();
+               osd_setting_blend(OSD1);
 }
 
-void osd_do_hwc(void)
+void osd_do_hwc(u32 index)
 {
-       osd_setting_blend();
+       u32 output_index;
+
+       output_index = get_output_device_id(index);
+       osd_setting_blend(output_index);
 }
 
 static void osd_set_two_ports(bool set)
@@ -3273,26 +3620,36 @@ void osd_set_urgent_info(u32 ports, u32 basic_urgent)
        osd_set_two_ports(osd_hw.two_ports);
 }
 
-void osd_set_single_step_mode(u32 osd_single_step_mode)
+void osd_set_single_step_mode(u32 index, u32 osd_single_step_mode)
 {
+       u32 output_index;
+
+       output_index = get_output_device_id(index);
+       if (output_index != VIU1)
+               return;
        osd_hw.osd_debug.osd_single_step_mode = osd_single_step_mode;
        if ((osd_hw.osd_debug.wait_fence_release) &&
                (osd_hw.osd_debug.osd_single_step_mode == 0)) {
 #ifdef CONFIG_AMLOGIC_MEDIA_FB_OSD_SYNC_FENCE
-               osd_timeline_increase();
+               osd_timeline_increase(output_index);
 #endif
                osd_hw.osd_debug.wait_fence_release = false;
        }
 
 }
 
-void osd_set_single_step(u32 osd_single_step)
+void osd_set_single_step(u32 index, u32 osd_single_step)
 {
+       u32 output_index;
+
+       output_index = get_output_device_id(index);
+       if (output_index != VIU1)
+               return;
        osd_hw.osd_debug.osd_single_step = osd_single_step;
        if ((osd_hw.osd_debug.wait_fence_release) &&
                (osd_hw.osd_debug.osd_single_step > 0)) {
 #ifdef CONFIG_AMLOGIC_MEDIA_FB_OSD_SYNC_FENCE
-               osd_timeline_increase();
+               osd_timeline_increase(output_index);
 #endif
                osd_hw.osd_debug.wait_fence_release = false;
        }
@@ -3305,7 +3662,7 @@ void osd_get_rotate(u32 index, u32 *osd_rotate)
 
 void osd_set_rotate(u32 index, u32 osd_rotate)
 {
-       if (index != OSD4)
+       if (index != osd_hw.osd_meson_dev.viu2_index)
                osd_log_err("osd%d not support rotate\n", index);
        osd_hw.osd_rotate[index] = osd_rotate;
        add_to_update_list(index, DISP_OSD_ROTATE);
@@ -3329,6 +3686,25 @@ void osd_set_dimm_info(u32 index, u32 osd_dimm_layer, u32 osd_dimm_color)
        osd_hw.dim_color[index] = osd_dimm_color;
 }
 
+void osd_set_hold_line(int hold_line)
+{
+       int i;
+       unsigned int data32 = 0, val = 0;
+
+       for (i = 0; i <= osd_hw.osd_meson_dev.viu1_osd_count; i++) {
+               if (osd_hw.powered[i]) {
+                       data32 = VSYNCOSD_RD_MPEG_REG
+                               (hw_osd_reg_array[i].osd_fifo_ctrl_stat);
+                       val = (data32 >> 5) & 0x1f;
+                       if (val != hold_line) {
+                               VSYNCOSD_WR_MPEG_REG_BITS
+                                       (hw_osd_reg_array[i].osd_fifo_ctrl_stat,
+                                       hold_line & 0x1f, 5, 5);
+                       }
+               }
+       }
+}
+
 int osd_get_capbility(u32 index)
 {
        u32 capbility = 0;
@@ -3338,10 +3714,10 @@ int osd_get_capbility(u32 index)
                        capbility |= OSD_LAYER_ENABLE | OSD_FREESCALE
                                | OSD_UBOOT_LOGO | OSD_ZORDER | OSD_VIU1
                                | OSD_PRIMARY;
-               else if ((index == OSD2) || (index == OSD3))
+               else if (index < osd_hw.osd_meson_dev.viu1_osd_count)
                        capbility |= OSD_LAYER_ENABLE | OSD_FREESCALE |
                                OSD_ZORDER | OSD_VIU1;
-               else if (index == OSD4)
+               else if (index == osd_hw.osd_meson_dev.viu2_index)
                        capbility |= OSD_LAYER_ENABLE | OSD_VIU2;
        } else if (osd_hw.osd_meson_dev.osd_ver == OSD_NORMAL) {
                if (index == OSD1)
@@ -3735,30 +4111,30 @@ static bool osd_direct_compose_pan_display(struct osd_fence_map_s *fence_map)
                        height_dst) / height_src - 1;
 
                if (osd_hw.osd_reverse[index] == REVERSE_TRUE) {
-                       x_start = osd_hw.vinfo_width
+                       x_start = osd_hw.vinfo_width[VIU1]
                                - freescale_dst[index].x_end - 1;
-                       y_start = osd_hw.vinfo_height
+                       y_start = osd_hw.vinfo_height[VIU1]
                                - freescale_dst[index].y_end - 1;
-                       x_end = osd_hw.vinfo_width
+                       x_end = osd_hw.vinfo_width[VIU1]
                                - freescale_dst[index].x_start - 1;
-                       y_end = osd_hw.vinfo_height
+                       y_end = osd_hw.vinfo_height[VIU1]
                                - freescale_dst[index].y_start - 1;
                        freescale_dst[index].x_start = x_start;
                        freescale_dst[index].y_start = y_start;
                        freescale_dst[index].x_end = x_end;
                        freescale_dst[index].y_end = y_end;
                } else if (osd_hw.osd_reverse[index] == REVERSE_X) {
-                       x_start = osd_hw.vinfo_width
+                       x_start = osd_hw.vinfo_width[VIU1]
                                - freescale_dst[index].x_end - 1;
-                       x_end = osd_hw.vinfo_width
+                       x_end = osd_hw.vinfo_width[VIU1]
                                - freescale_dst[index].x_start - 1;
                        freescale_dst[index].x_start = x_start;
                        freescale_dst[index].x_end = x_end;
 
                } else if (osd_hw.osd_reverse[index] == REVERSE_Y) {
-                       y_start = osd_hw.vinfo_height
+                       y_start = osd_hw.vinfo_height[VIU1]
                                - freescale_dst[index].y_end - 1;
-                       y_end = osd_hw.vinfo_height
+                       y_end = osd_hw.vinfo_height[VIU1]
                                - freescale_dst[index].y_start - 1;
                        freescale_dst[index].y_start = y_start;
                        freescale_dst[index].y_end = y_end;
@@ -3815,30 +4191,30 @@ static bool osd_direct_compose_pan_display(struct osd_fence_map_s *fence_map)
                osd_hw.dispdata[index].y_end =
                        fence_map->dst_y + fence_map->dst_h - 1;
                if (osd_hw.osd_reverse[index] == REVERSE_TRUE) {
-                       x_start = osd_hw.vinfo_width
+                       x_start = osd_hw.vinfo_width[VIU1]
                                - osd_hw.dispdata[index].x_end - 1;
-                       y_start = osd_hw.vinfo_height
+                       y_start = osd_hw.vinfo_height[VIU1]
                                - osd_hw.dispdata[index].y_end - 1;
-                       x_end = osd_hw.vinfo_width
+                       x_end = osd_hw.vinfo_width[VIU1]
                                - osd_hw.dispdata[index].x_start - 1;
-                       y_end = osd_hw.vinfo_height
+                       y_end = osd_hw.vinfo_height[VIU1]
                                - osd_hw.dispdata[index].y_start - 1;
                        osd_hw.dispdata[index].x_start = x_start;
                        osd_hw.dispdata[index].y_start = y_start;
                        osd_hw.dispdata[index].x_end = x_end;
                        osd_hw.dispdata[index].y_end = y_end;
                } else if (osd_hw.osd_reverse[index] == REVERSE_X) {
-                       x_start = osd_hw.vinfo_width
+                       x_start = osd_hw.vinfo_width[VIU1]
                                - osd_hw.dispdata[index].x_end - 1;
-                       x_end = osd_hw.vinfo_width
+                       x_end = osd_hw.vinfo_width[VIU1]
                                - osd_hw.dispdata[index].x_start - 1;
                        osd_hw.dispdata[index].x_start = x_start;
                        osd_hw.dispdata[index].x_end = x_end;
 
                } else if (osd_hw.osd_reverse[index] == REVERSE_Y) {
-                       y_start = osd_hw.vinfo_height
+                       y_start = osd_hw.vinfo_height[VIU1]
                                - osd_hw.dispdata[index].y_end - 1;
-                       y_end = osd_hw.vinfo_height
+                       y_end = osd_hw.vinfo_height[VIU1]
                                - osd_hw.dispdata[index].y_start - 1;
                        osd_hw.dispdata[index].y_start = y_start;
                        osd_hw.dispdata[index].y_end = y_end;
@@ -3861,19 +4237,27 @@ static void osd_pan_display_single_fence(struct osd_fence_map_s *fence_map)
        u32 osd_enable = 0;
        bool skip = false;
        const struct vinfo_s *vinfo;
-
+       u32 output_index = VIU1;
 
        if (index >= OSD2)
                goto out;
-       if (timeline_created) { /* out fence created success. */
+       vinfo = get_current_vinfo();
+       if (!vinfo || (!strcmp(vinfo->name, "invalid") ||
+                       !strcmp(vinfo->name, "null")))
+               goto out;
+
+       osd_hw.vinfo_width[output_index] = vinfo->width;
+       osd_hw.vinfo_height[output_index] = vinfo->height;
+
+       if (timeline_created[output_index]) { /* out fence created success. */
                ret = osd_wait_buf_ready(fence_map);
                if (ret < 0)
                        osd_log_dbg(MODULE_BASE, "fence wait ret %d\n", ret);
        }
        if (ret) {
                osd_hw.buffer_alloc[index] = 1;
-               if (osd_hw.osd_fps_start)
-                       osd_hw.osd_fps++;
+               if (osd_hw.osd_fps_start[output_index])
+                       osd_hw.osd_fps[output_index]++;
                if (fence_map->op == 0xffffffff)
                        skip = true;
                else
@@ -3886,14 +4270,6 @@ static void osd_pan_display_single_fence(struct osd_fence_map_s *fence_map)
                                 AFBC_EN | BLOCK_SPLIT |
                                 YUV_TRANSFORM | SUPER_BLOCK_ASPECT;
                }
-               vinfo = get_current_vinfo();
-               if (vinfo) {
-                       if ((strcmp(vinfo->name, "invalid")) &&
-                               (strcmp(vinfo->name, "null"))) {
-                               osd_hw.vinfo_width = vinfo->width;
-                               osd_hw.vinfo_height = vinfo->height;
-                       }
-               }
                /* Todo: */
                if (fence_map->ext_addr && fence_map->width
                        && fence_map->height) {
@@ -3939,7 +4315,10 @@ static void osd_pan_display_single_fence(struct osd_fence_map_s *fence_map)
                                        .update_func(index);
                                osd_update_window_axis = false;
                        }
-                       if ((osd_enable != osd_hw.enable[index])
+                       if ((osd_enable != osd_hw.enable[index] ||
+                               (osd_hw.osd_meson_dev.afbc_type
+                                       == MALI_AFBC &&
+                               osd_hw.osd_afbcd[index].enable))
                                && (skip == false)
                                && (suspend_flag == false)) {
                                osd_hw.enable[index] = osd_enable;
@@ -4060,7 +4439,10 @@ static void osd_pan_display_single_fence(struct osd_fence_map_s *fence_map)
                                                .update_func(index);
                                osd_update_window_axis = false;
                        }
-                       if ((osd_enable != osd_hw.enable[index])
+                       if ((osd_enable != osd_hw.enable[index] ||
+                               (osd_hw.osd_meson_dev.afbc_type
+                                       == MALI_AFBC &&
+                               osd_hw.osd_afbcd[index].enable))
                                && (skip == false)
                                && (suspend_flag == false)) {
                                osd_hw.enable[index] = osd_enable;
@@ -4072,7 +4454,9 @@ static void osd_pan_display_single_fence(struct osd_fence_map_s *fence_map)
                                osd_mali_afbc_start();
                        spin_unlock_irqrestore(&osd_lock, lock_flags);
                        osd_wait_vsync_hw();
-               } else if ((osd_enable != osd_hw.enable[index])
+               } else if ((osd_enable != osd_hw.enable[index] ||
+                       (osd_hw.osd_meson_dev.afbc_type == MALI_AFBC &&
+                       osd_hw.osd_afbcd[index].enable))
                        && (skip == false)) {
                        spin_lock_irqsave(&osd_lock, lock_flags);
                        if (suspend_flag == false) {
@@ -4087,20 +4471,24 @@ static void osd_pan_display_single_fence(struct osd_fence_map_s *fence_map)
                        osd_wait_vsync_hw();
                }
        }
-       if (timeline_created) {
+#ifdef CONFIG_AMLOGIC_MEDIA_FB_EXT
+               if (ret)
+                       osd_ext_clone_pan(index);
+#endif
+out:
+       if (timeline_created[output_index]) {
                if (ret)
-                       osd_timeline_increase();
+                       osd_timeline_increase(output_index);
                else
                        osd_log_err("------NOT signal out_fence ERROR\n");
        }
-#ifdef CONFIG_AMLOGIC_MEDIA_FB_EXT
-       if (ret)
-               osd_ext_clone_pan(index);
-#endif
-out:
        if (fence_map->in_fence)
                osd_put_fenceobj(fence_map->in_fence);
+}
 
+static void osd_pan_display_single_fence_viu2(struct osd_fence_map_s *fence_map)
+{
+       osd_log_err("osd hwc version not support viu2\n");
 }
 
 static void osd_pan_display_update_info(struct layer_fence_map_s *layer_map)
@@ -4109,6 +4497,7 @@ static void osd_pan_display_update_info(struct layer_fence_map_s *layer_map)
        const struct color_bit_define_s *color = NULL;
        u32 ext_addr = 0;
        u32 format = 0;
+       u32 output_index = 0;
 
        if (index > OSD_MAX)
                return;
@@ -4272,7 +4661,8 @@ static void osd_pan_display_update_info(struct layer_fence_map_s *layer_map)
                                layer_map->dst_x + layer_map->dst_w - 1;
                        osd_hw.free_dst_data[index].y_end =
                                layer_map->dst_y + layer_map->dst_h - 1;
-                       if (osd_hw.field_out_en) {
+                       output_index = get_output_device_id(index);
+                       if (osd_hw.field_out_en[output_index]) {
                                osd_hw.free_dst_data[index].y_start /= 2;
                                osd_hw.free_dst_data[index].y_end /= 2;
                        }
@@ -4284,31 +4674,49 @@ static void osd_pan_display_update_info(struct layer_fence_map_s *layer_map)
        #endif
 }
 
-static void osd_pan_display_layers_fence(
+static void _osd_pan_display_layers_fence(
+       u32 output_index,
+       struct vinfo_s *vinfo,
        struct osd_layers_fence_map_s *fence_map)
 {
        int i = 0;
        int ret;
-       int osd_count = osd_hw.osd_meson_dev.osd_count - 1;
+       int start_index = 0;
+       int backup_en = 0;
+       int osd_count = 0;
        /* osd_count need -1 when VIU2 enable */
        struct layer_fence_map_s *layer_map = NULL;
-       struct vinfo_s *vinfo;
 
-       if (osd_hw.osd_meson_dev.osd_ver <= OSD_NORMAL)
-               osd_count = 1;
-       vinfo = get_current_vinfo();
-       if (vinfo && (strcmp(vinfo->name, "invalid") &&
-                       strcmp(vinfo->name, "null"))) {
-               osd_hw.vinfo_width = vinfo->width;
-               osd_hw.vinfo_height = vinfo->field_height;
+       if (!vinfo || (!strcmp(vinfo->name, "invalid") ||
+                               !strcmp(vinfo->name, "null")))
+               /* vout is null, release fence */
+               goto out;
+
+       osd_hw.vinfo_width[output_index] = vinfo->width;
+       osd_hw.vinfo_height[output_index] = vinfo->field_height;
+       memcpy(&osd_hw.disp_info[output_index], &fence_map->disp_info,
+              sizeof(struct display_flip_info_s));
+       if (output_index == VIU1) {
+               osd_count = osd_hw.osd_meson_dev.viu1_osd_count;
+               if (osd_hw.osd_meson_dev.osd_ver <= OSD_NORMAL)
+                       osd_count = 1;
+               start_index = 0;
+               backup_en = 1;
+       } else if (output_index == VIU2) {
+               start_index = osd_hw.osd_meson_dev.viu2_index;
+               osd_count = start_index + 1;
+               backup_en = 0;
+       } else {
+               osd_log_err("invald output_index=%d\n", output_index);
+               return;
        }
-       osd_set_background_size(&(fence_map->disp_info));
 
-       if (osd_hw.osd_fps_start)
-               osd_hw.osd_fps++;
-       clear_backup_info();
+       if (osd_hw.osd_fps_start[output_index])
+               osd_hw.osd_fps[output_index]++;
+       if (backup_en)
+               clear_backup_info();
        osd_hw.hdr_used = fence_map->hdr_mode;
-       for (i = 0; i < osd_count; i++) {
+       for (i = start_index; i < osd_count; i++) {
                layer_map = &fence_map->layer_map[i];
                if (i != layer_map->fb_index) {
                        osd_hw.screen_base[i] = 0;
@@ -4317,7 +4725,7 @@ static void osd_pan_display_layers_fence(
                        continue;
                }
                /* wait in fence */
-               if (timeline_created && layer_map->enable
+               if (timeline_created[output_index] && layer_map->enable
                        && (fence_map->cmd == LAYER_SYNC)) {
                        ret = osd_wait_buf_ready_combine(layer_map);
                        if (ret < 0)
@@ -4325,23 +4733,25 @@ static void osd_pan_display_layers_fence(
                                        "fence wait ret %d\n", ret);
                }
                osd_pan_display_update_info(layer_map);
-               save_layer_info(layer_map);
+               if (backup_en)
+                       save_layer_info(layer_map);
        }
        /* set hw regs */
        if (osd_hw.osd_display_debug != OSD_DISP_DEBUG)
-               osd_setting_blend();
+               osd_setting_blend(output_index);
+out:
        /* signal out fence */
-       if (timeline_created) {
+       if (timeline_created[output_index]) {
                if (osd_hw.osd_debug.osd_single_step_mode) {
                        /* single step mode */
                        if (osd_hw.osd_debug.osd_single_step > 0) {
-                               osd_timeline_increase();
+                               osd_timeline_increase(output_index);
                                osd_log_dbg(MODULE_FENCE, "signal out fence\n");
                                osd_hw.osd_debug.osd_single_step--;
                        } else
                                osd_hw.osd_debug.wait_fence_release = true;
                } else
-                       osd_timeline_increase();
+                       osd_timeline_increase(output_index);
        }
        /*clear last displayed buffer.*/
        for (i = 0; i < HW_OSD_COUNT; i++) {
@@ -4351,7 +4761,7 @@ static void osd_pan_display_layers_fence(
                }
        }
        /* clear osd layer's order */
-       for (i = 0; i < osd_count; i++) {
+       for (i = start_index; i < osd_count; i++) {
                layer_map = &fence_map->layer_map[i];
                if (layer_map->buf_file)
                        displayed_bufs[i] = layer_map->buf_file;
@@ -4360,14 +4770,42 @@ static void osd_pan_display_layers_fence(
                osd_hw.order[i] = 0;
        }
 }
+
+static void osd_pan_display_layers_fence(
+       struct osd_layers_fence_map_s *fence_map)
+{
+       u32 output_index = VIU1;
+       struct vinfo_s *vinfo = NULL;
+
+       vinfo = get_current_vinfo();
+
+       _osd_pan_display_layers_fence(output_index,
+                                     vinfo, fence_map);
+}
+
+static void osd_pan_display_layers_fence_viu2(
+       struct osd_layers_fence_map_s *fence_map)
+{
+       u32 output_index = VIU2;
+       struct vinfo_s *vinfo = NULL;
+
+#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
+       vinfo = get_current_vinfo2();
+#endif
+
+       _osd_pan_display_layers_fence(output_index,
+                                     vinfo, fence_map);
+}
 #endif
 
 void osd_pan_display_hw(u32 index, unsigned int xoffset, unsigned int yoffset)
 {
        long diff_x, diff_y;
+       u32 output_index;
 
        if (index >= HW_OSD_COUNT)
                return;
+       output_index = get_output_device_id(index);
        if (xoffset != osd_hw.pandata[index].x_start
            || yoffset != osd_hw.pandata[index].y_start) {
                diff_x = xoffset - osd_hw.pandata[index].x_start;
@@ -4383,8 +4821,8 @@ void osd_pan_display_hw(u32 index, unsigned int xoffset, unsigned int yoffset)
                osd_hw.src_data[index].h = osd_hw.pandata[index].y_end
                        - osd_hw.pandata[index].y_start + 1;
                add_to_update_list(index, DISP_GEOMETRY);
-               if (osd_hw.osd_fps_start)
-                       osd_hw.osd_fps++;
+               if (osd_hw.osd_fps_start[output_index])
+                       osd_hw.osd_fps[output_index]++;
                /* osd_wait_vsync_hw(); */
        }
 #ifdef CONFIG_AMLOGIC_MEDIA_FB_EXT
@@ -4458,6 +4896,7 @@ static void osd_update_disp_freescale_enable(u32 index)
        struct hw_osd_reg_s *osd_reg = &hw_osd_reg_array[index];
        u32 data32 = 0x0;
        u32 shift_workaround = 0;
+       u32 output_index = 0;
 
        if (osd_hw.osd_meson_dev.osd_ver != OSD_HIGH_ONE)
                osd_reg = &hw_osd_reg_array[0];
@@ -4467,7 +4906,8 @@ static void osd_update_disp_freescale_enable(u32 index)
        else
                vf_bank_len = 4;
 
-       if (osd_hw.hwc_enable && (index == OSD1))
+       output_index = get_output_device_id(index);
+       if (osd_hw.hwc_enable[output_index] && (index == OSD1))
                shift_workaround = osd_hw.workaround_line;
 
 #ifndef NEW_PPS_PHASE
@@ -4525,7 +4965,7 @@ static void osd_update_disp_freescale_enable(u32 index)
                vf_phase_step = (src_h << 20) / dst_h;
 
 #ifdef NEW_PPS_PHASE
-       if (osd_hw.field_out_en) {
+       if (osd_hw.field_out_en[output_index]) {
                struct osd_f2v_vphase_s vphase;
 
                f2v_get_vertical_phase(
@@ -4556,7 +4996,7 @@ static void osd_update_disp_freescale_enable(u32 index)
                bot_ini_phase = 0;
        }
 #else
-       if (osd_hw.field_out_en)   /* interface output */
+       if (osd_hw.field_out_en[output_index])   /* interface output */
                bot_ini_phase = ((vf_phase_step / 2) >> 4);
        else
                bot_ini_phase = 0;
@@ -4568,7 +5008,7 @@ static void osd_update_disp_freescale_enable(u32 index)
        data32 = 0x0;
        if (shift_workaround) {
                vsc_ini_rcv_num++;
-               if (osd_hw.field_out_en)
+               if (osd_hw.field_out_en[output_index])
                        vsc_bot_rcv_num++;
        }
 
@@ -4590,7 +5030,7 @@ static void osd_update_disp_freescale_enable(u32 index)
                data32 |= (vf_bank_len & 0x7)
                        | ((vsc_ini_rcv_num & 0xf) << 3)
                        | ((vsc_ini_rpt_p0_num & 0x3) << 8);
-               if (osd_hw.field_out_en)
+               if (osd_hw.field_out_en[output_index])
                        data32 |= ((vsc_bot_rcv_num & 0xf) << 11)
                                | ((vsc_bot_rpt_p0_num & 0x3) << 16)
                                | (1 << 23);
@@ -4625,8 +5065,8 @@ static void osd_update_disp_freescale_enable(u32 index)
                VSYNCOSD_WR_MPEG_REG(
                        osd_reg->osd_vsc_init_phase, data32);
        }
-       if ((osd_hw.osd_meson_dev.osd_ver == OSD_HIGH_ONE)
-               && (!osd_hw.hwc_enable)) {
+       if ((osd_hw.osd_meson_dev.osd_ver == OSD_HIGH_ONE) &&
+           (!osd_hw.hwc_enable[output_index])) {
                osd_setting_blending_scope(index);
                vpp_blend_setting_default(index);
        }
@@ -4927,8 +5367,10 @@ static void osd_update_enable(u32 index)
                        notify_to_amvideo();
                        VSYNCOSD_CLR_MPEG_REG_MASK(VPP_MISC, temp_val);
                }
-               VSYNCOSD_CLR_MPEG_REG_MASK(
-                       osd_reg->osd_ctrl_stat, 1 << 0);
+               if (!(osd_hw.osd_meson_dev.cpu_id ==
+                       __MESON_CPU_MAJOR_ID_G12B))
+                       VSYNCOSD_CLR_MPEG_REG_MASK(
+                               osd_reg->osd_ctrl_stat, 1 << 0);
        }
        if (osd_hw.osd_meson_dev.afbc_type == MESON_AFBC) {
                if ((osd_hw.osd_afbcd[index].enable == ENABLE)
@@ -5053,7 +5495,7 @@ static void osd_update_disp_osd_rotate(u32 index)
        u32 data32;
        enum color_index_e idx;
        struct dispdata_s src_data;
-       const struct vinfo_s *vinfo;
+       const struct vinfo_s *vinfo = NULL;
        int out_y_crop_start, out_y_crop_end;
 
        if (osd_hw.osd_meson_dev.cpu_id != __MESON_CPU_MAJOR_ID_G12B)
@@ -5063,11 +5505,14 @@ static void osd_update_disp_osd_rotate(u32 index)
        src_data.y = 0;
        src_data.w = osd_hw.fb_gem[index].xres;
        src_data.h = osd_hw.fb_gem[index].yres;
+               src_data.h = osd_hw.fb_gem[index].yres;
+#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
        vinfo = get_current_vinfo2();
        if (!vinfo) {
                osd_log_err("current vinfo NULL\n");
                return;
        }
+#endif
        out_y_crop_start = 0;
        out_y_crop_end = vinfo->height;
        src_width = src_data.w;
@@ -5331,13 +5776,12 @@ static u32 blend_din_to_osd(
 
        osd_index =
                blending->osd_to_bdin_table[blend_din_index];
-       if (osd_index > OSD3)
+       if (osd_index >= osd_hw.osd_meson_dev.viu1_osd_count)
                return OSD_MAX;
        else
                return osd_index;
 }
 
-#ifdef OSD_BLEND_SHIFT_WORKAROUND
 static u32 get_max_order(u32 order1, u32 order2)
 {
        u32 max_order = 0;
@@ -5627,179 +6071,30 @@ static void generate_blend_din_table(struct hw_osd_blending_s *blending)
                blending->din_reoder_sel;
 }
 
-#else
-static void generate_blend_din_table(struct hw_osd_blending_s *blending)
+static bool is_freescale_para_changed(u32 index)
 {
-       int i = 0;
-       int osd_count = osd_hw.osd_meson_dev.osd_count - 1;
-
-       /* reorder[i] = osd[i]'s display layer */
-       for (i = 0; i < OSD_BLEND_LAYERS; i++)
-               blending->osd_to_bdin_table[i] = -1;
-       blending->din_reoder_sel = 0;
-       switch (blending->layer_cnt) {
-       case 0:
-               break;
-       case 1:
-               for (i = 0; i < osd_count; i++) {
-                       if (blending->reorder[i] != LAYER_UNSUPPORT) {
-                               /* blend_din1 */
-                               blending->din_reoder_sel |= (i + 1) << 0;
-                               /* blend_din1 -- osdx */
-                               blending->osd_to_bdin_table[0] = i;
-                               break;
-                       }
-               }
-               break;
-       case 2:
-       {
-               int temp_index[2] = {0};
-               int j = 0;
+       static int first[HW_OSD_COUNT - 1] = {1};
+       bool freescale_update = false;
 
-               for (i = 0; i < osd_count; i++) {
-                       if (blending->reorder[i] != LAYER_UNSUPPORT) {
-                               /* save the osd index */
-                               temp_index[j] = i;
-                               j++;
-                       }
-               }
-               osd_log_dbg(MODULE_BLEND, "blend_din4==%d\n",
-                       blending->reorder[temp_index[0]]);
-               osd_log_dbg(MODULE_BLEND, "blend_din1==%d\n",
-                       blending->reorder[temp_index[1]]);
-               /* mode A_C */
-               if (blending->osd_blend_mode == OSD_BLEND_A_C) {
-                       /* blend_din1 */
-                       blending->din_reoder_sel |= (temp_index[0] + 1) << 0;
-                       /* blend_din1 -- osdx */
-                       blending->osd_to_bdin_table[0] = temp_index[0];
-                       /* blend_din3 */
-                       blending->din_reoder_sel |= (temp_index[1] + 1) << 12;
-                       /* blend_din3 -- osdx */
-                       blending->osd_to_bdin_table[3] = temp_index[1];
-                       /* exchane vpp osd blend in order */
-                       if (blending->reorder[temp_index[0]] <
-                               blending->reorder[temp_index[1]]) {
-                               blending->b_exchange_blend_in = true;
-                               osd_log_dbg(MODULE_BLEND, "need exchange vpp order\n");
-                       }
-               } else {
-                       if (blending->reorder[temp_index[0]] <
-                               blending->reorder[temp_index[1]]) {
-                               /* blend_din4 */
-                               blending->din_reoder_sel |=
-                                       (temp_index[0] + 1) << 12;
-                               /* blend_din3 -- osdx */
-                               blending->osd_to_bdin_table[3] = temp_index[0];
-                               /* blend_din1 */
-                               blending->din_reoder_sel |=
-                                       (temp_index[1] + 1) << 0;
-                               /* blend_din1 -- osdx */
-                               blending->osd_to_bdin_table[0] = temp_index[1];
-                               blending->b_exchange_din = true;
-                               osd_log_dbg(MODULE_BLEND, "need exchange osd din order\n");
-                       } else {
-                               /* blend_din1 */
-                               blending->din_reoder_sel |=
-                                       (temp_index[0] + 1) << 0;
-                               /* blend_din1 -- osdx */
-                               blending->osd_to_bdin_table[0] = temp_index[0];
-                               /* blend_din3 */
-                               blending->din_reoder_sel |=
-                                       (temp_index[1] + 1) << 12;
-                               /* blend_din3 -- osdx */
-                               blending->osd_to_bdin_table[3] = temp_index[1];
-                       }
-               }
-               break;
+       if (memcmp(&(osd_hw.free_src_data[index]),
+               &osd_hw.free_src_data_backup[index],
+               sizeof(struct pandata_s)) != 0 ||
+               memcmp(&(osd_hw.free_dst_data[index]),
+               &osd_hw.free_dst_data_backup[index],
+               sizeof(struct pandata_s)) != 0) {
+               memcpy(&(osd_hw.free_src_data_backup[index]),
+                       &osd_hw.free_src_data[index],
+                       sizeof(struct pandata_s));
+               memcpy(&(osd_hw.free_dst_data_backup[index]),
+                       &osd_hw.free_dst_data[index],
+                       sizeof(struct pandata_s));
+               freescale_update = true;
        }
-       case 3:
-               /* blend_din1 is bottom, blend_din4 is top layer */
-               /* mode A_BC */
-               /* osd0 always used blend_din1 */
-               /* blend_din1 */
-               blending->din_reoder_sel |= 1 << 0;
-               /* blend_din1 -- osd1 */
-               blending->osd_to_bdin_table[0] = OSD1;
-               if (blending->reorder[OSD2] > blending->reorder[OSD3]) {
-                       /* blend_din4 */
-                       blending->din_reoder_sel |= (OSD3 + 1) << 12;
-                       /* blend_din4 -- osd3 */
-                       blending->osd_to_bdin_table[3] = OSD3;
-
-                       /* blend_din3 */
-                       blending->din_reoder_sel |= (OSD2 + 1) << 8;
-                       /* blend_din3 -- osd2 */
-                       blending->osd_to_bdin_table[2] = OSD2;
-               } else {
-                       /* blend_din3 */
-                       blending->din_reoder_sel |= (OSD2 + 1) << 12;
-                       /* blend_din3 -- osd2 */
-                       blending->osd_to_bdin_table[3] = OSD2;
-
-                       /* blend_din3 */
-                       blending->din_reoder_sel |= (OSD3 + 1) << 8;
-                       /* blend_din3 -- osd2 */
-                       blending->osd_to_bdin_table[2] = OSD3;
-
-               }
-               if (blending->reorder[OSD1] < blending->reorder[OSD3]) {
-                       if (blending->osd_blend_mode == OSD_BLEND_A_BC) {
-                               blending->b_exchange_blend_in = true;
-                               osd_log_dbg(MODULE_BLEND, "need exchange vpp order\n");
-                       } else {
-                               u32 temp1, temp2;
-
-                               blending->b_exchange_din = true;
-                               osd_log_dbg(MODULE_BLEND, "need exchange osd din order\n");
-                               temp1 = blending->osd_to_bdin_table[2];
-                               temp2 = blending->osd_to_bdin_table[3];
-                               blending->osd_to_bdin_table[3] =
-                                       blending->osd_to_bdin_table[0];
-                               blending->osd_to_bdin_table[2] = temp2;
-                               blending->osd_to_bdin_table[0] = temp1;
-                               temp1 = blending->din_reoder_sel & 0xf000;
-                               temp2 = blending->din_reoder_sel & 0x0f00;
-                               blending->din_reoder_sel = (1 << 12);
-                               blending->din_reoder_sel |= temp1 >> 4;
-                               blending->din_reoder_sel |= temp2 >> 8;
-                       }
-               }
-               break;
-       }
-       osd_log_dbg(MODULE_BLEND, "osd_to_bdin_table[i]=[%x,%x,%x,%x]\n",
-               blending->osd_to_bdin_table[0],
-               blending->osd_to_bdin_table[1],
-               blending->osd_to_bdin_table[2],
-               blending->osd_to_bdin_table[3]);
-       blending->blend_reg.din_reoder_sel =
-               blending->din_reoder_sel;
-}
-#endif
-static bool is_freescale_para_changed(u32 index)
-{
-       static int first[HW_OSD_COUNT - 1] = {1};
-       bool freescale_update = false;
-
-       if (memcmp(&(osd_hw.free_src_data[index]),
-               &osd_hw.free_src_data_backup[index],
-               sizeof(struct pandata_s)) != 0 ||
-               memcmp(&(osd_hw.free_dst_data[index]),
-               &osd_hw.free_dst_data_backup[index],
-               sizeof(struct pandata_s)) != 0) {
-               memcpy(&(osd_hw.free_src_data_backup[index]),
-                       &osd_hw.free_src_data[index],
-                       sizeof(struct pandata_s));
-               memcpy(&(osd_hw.free_dst_data_backup[index]),
-                       &osd_hw.free_dst_data[index],
-                       sizeof(struct pandata_s));
-               freescale_update = true;
-       }
-       if (first[index])
-               freescale_update = true;
-       first[index] = 0;
-       return freescale_update;
-}
+       if (first[index])
+               freescale_update = true;
+       first[index] = 0;
+       return freescale_update;
+}
 
 static int osd_setting_blending_scope(u32 index)
 {
@@ -5807,7 +6102,7 @@ static int osd_setting_blending_scope(u32 index)
        u32 bld_osd_v_start, bld_osd_v_end;
        u32 reg_offset = 2;
 
-       if (index > OSD3) {
+       if (index >= osd_hw.osd_meson_dev.viu1_osd_count) {
                osd_log_err("error osd index=%d\n", index);
                return -1;
        }
@@ -5854,7 +6149,7 @@ static int vpp_blend_setting_default(u32 index)
 
        osd_log_dbg(MODULE_BASE, "vpp_blend_setting_default\n");
 
-       if (index > OSD3) {
+       if (index >= osd_hw.osd_meson_dev.viu1_osd_count) {
                osd_log_err("error osd index=%d\n", index);
                return -1;
        }
@@ -5877,8 +6172,6 @@ static int vpp_blend_setting_default(u32 index)
                osd1_v_start = osd_hw.dispdata[index].y_start;
                osd1_v_end = osd_hw.dispdata[index].y_end;
        }
-       VSYNCOSD_WR_MPEG_REG(VPP_OSD1_IN_SIZE,
-               osd1_dst_h | osd1_dst_v << 16);
 
        /* setting blend scope */
        VSYNCOSD_WR_MPEG_REG(VPP_OSD1_BLD_H_SCOPE,
@@ -5934,13 +6227,9 @@ static void set_blend_order(struct hw_osd_blending_s *blending)
 static void set_blend_din(struct hw_osd_blending_s *blending)
 {
        int i = 0, osd_index;
-#ifdef OSD_BLEND_SHIFT_WORKAROUND
        /* workaround for shift issue */
        /* blend_din_en must equal 5 */
        u32 blend_din_en = 0x5;
-#else
-       u32 blend_din_en = 0x9;
-#endif
 
        if (!blending)
                return;
@@ -5961,7 +6250,6 @@ static void set_blend_din(struct hw_osd_blending_s *blending)
 static void set_blend_mode(struct hw_osd_blending_s *blending)
 {
        u8 osd_blend_mode = OSD_BLEND_NONE;
-       //u32 osd_index;
 
        if (!blending)
                return;
@@ -5985,11 +6273,7 @@ static void set_blend_mode(struct hw_osd_blending_s *blending)
                if (osd_hw.hdr_used)
                        osd_blend_mode = OSD_BLEND_ABC;
                else
-#ifdef OSD_BLEND_SHIFT_WORKAROUND
                        osd_blend_mode = OSD_BLEND_AB_C;
-#else
-                       osd_blend_mode = OSD_BLEND_A_BC;
-#endif
                break;
        }
        blending->osd_blend_mode = osd_blend_mode;
@@ -6133,19 +6417,9 @@ static void osd_setting_blend1(struct hw_osd_blending_s *blending)
        }
        layer_blend = &(blending->layer_blend);
        blend_reg = &(blending->blend_reg);
-#ifdef OSD_BLEND_SHIFT_WORKAROUND
        /* blend1_dout to blend2 */
        blend_reg->din2_osd_sel = 0;
-#else
-       /* input1 default route to blend1 */
-       if (layer_blend->input1 & BYPASS_DIN) {
-               /* blend1_dout to dout1 */
-               blend_reg->din2_osd_sel = 1;
-               layer_blend->input1 &= ~BYPASS_DIN;
-       } else
-               /* blend1_dout to blend2 */
-               blend_reg->din2_osd_sel = 0;
-#endif
+
        if (layer_blend->input2 & BYPASS_DIN) {
                /* blend1_din3 bypass to dout1 */
                blend_reg->din3_osd_sel = 1;
@@ -6209,7 +6483,6 @@ static void osd_setting_blend1(struct hw_osd_blending_s *blending)
        }
        if (blend_reg->din3_osd_sel || layer_blend->input1 == BLEND_NO_DIN) {
                /* blend din3 bypass,output == input */
-#ifdef OSD_BLEND_SHIFT_WORKAROUND
        if (layer_blend->input2 == BLEND_NO_DIN) {
                memcpy(&layer_blend->output_data,
                        &layer_blend->input1_data,
@@ -6220,16 +6493,7 @@ static void osd_setting_blend1(struct hw_osd_blending_s *blending)
                        sizeof(struct dispdata_s));
        }
        layer_blend->output_data.h += workaround_line;
-#else
-               layer_blend->output_data.x = 0;
-               layer_blend->output_data.y = 0;
-               layer_blend->output_data.w =
-                       layer_blend->input2_data.x +
-                       layer_blend->input2_data.w;
-               layer_blend->output_data.h =
-                       layer_blend->input2_data.y +
-                       layer_blend->input2_data.h;
-#endif
+
        } else
                calc_max_output(blending);
        blend_hsize = layer_blend->output_data.w;
@@ -6262,7 +6526,6 @@ static void osd_setting_blend2(struct hw_osd_blending_s *blending)
        /* osd_blend_blend0_size share with blend2_size*/
        blend_reg->osd_blend_blend0_size =
                blend_vsize  << 16 | blend_hsize;
-#ifdef OSD_BLEND_SHIFT_WORKAROUND
        switch (layer_blend->input2) {
        case BLEND1_DIN:
                blend1_input = 0;
@@ -6272,19 +6535,7 @@ static void osd_setting_blend2(struct hw_osd_blending_s *blending)
                blend1_input = 1;
                break;
        }
-#else
-       switch (layer_blend->input2) {
-       case BLEND1_DIN:
-               /* blend1_dout to blend2 */
-               blend_reg->din2_osd_sel = 0;
-               break;
-       default:
-               /* blend1_dout to dout1 */
-               blend_reg->din2_osd_sel = 1;
-               break;
-       }
-       blend1_input = blend_reg->din2_osd_sel;
-#endif
+
        /* premult set */
        blend_reg->blend2_premult_en = 3;
        if (blend1_input)
@@ -6296,11 +6547,9 @@ static void osd_setting_blend2(struct hw_osd_blending_s *blending)
                blend_vsize = layer_blend->output_data.h;
                blend_reg->osd_blend_blend0_size =
                        blend_vsize  << 16 | blend_hsize;
-#ifdef OSD_BLEND_SHIFT_WORKAROUND
                /* blend 0 and blend1 size need same */
                blend_reg->osd_blend_blend1_size =
                        blend_reg->osd_blend_blend0_size;
-#endif
        }
        osd_log_dbg2(MODULE_BLEND, "layer_blend2->output_data:%d,%d,%d,%d\n",
                layer_blend->output_data.x,
@@ -6339,11 +6588,7 @@ static void vpp_setting_blend(struct hw_osd_blending_s *blending)
        switch (layer_blend->input1) {
        case BLEND1_DIN:
                blend_reg->postbld_src3_sel = POSTBLD_OSD2;
-#ifdef OSD_BLEND_SHIFT_WORKAROUND
                if (layer_blend->blend_core1_bypass)
-#else
-               if (blend_reg->din3_osd_sel)
-#endif
                        blend_reg->postbld_osd1_premult = 0;
                else
                        blend_reg->postbld_osd1_premult = 1;
@@ -6372,11 +6617,7 @@ static void vpp_setting_blend(struct hw_osd_blending_s *blending)
        switch (layer_blend->input2) {
        case BLEND1_DIN:
                blend_reg->postbld_src4_sel = POSTBLD_OSD2;
-#ifdef OSD_BLEND_SHIFT_WORKAROUND
                if (layer_blend->blend_core1_bypass)
-#else
-               if (blend_reg->din3_osd_sel)
-#endif
                        blend_reg->postbld_osd2_premult = 0;
                else
                        blend_reg->postbld_osd2_premult = 1;
@@ -6411,7 +6652,6 @@ static void vpp_setting_blend(struct hw_osd_blending_s *blending)
                blend_reg->vpp_osd2_blend_v_scope);
 }
 
-/* input w, h is background */
 static void osd_set_freescale(u32 index,
        struct hw_osd_blending_s *blending)
 
@@ -6421,10 +6661,11 @@ static void osd_set_freescale(u32 index,
        u32 width, height;
        u32 src_height;
        u32 workaround_line = osd_hw.workaround_line;
+       u32 output_index = 0;
 
        layer_blend = &(blending->layer_blend);
        blend_reg = &(blending->blend_reg);
-       if (index > OSD3) {
+       if (index >= osd_hw.osd_meson_dev.viu1_osd_count) {
                osd_log_err("error osd index=%d\n", index);
                return;
        }
@@ -6432,6 +6673,7 @@ static void osd_set_freescale(u32 index,
        osd_hw.free_scale[index].h_enable = 1;
        osd_hw.free_scale[index].v_enable = 1;
        osd_hw.free_scale_mode[index] = 1;
+       output_index = get_output_device_id(index);
 
        if (index == OSD1) {
                osd_hw.free_src_data[index].x_start =
@@ -6447,11 +6689,13 @@ static void osd_set_freescale(u32 index,
 
                osd_hw.free_dst_data[index].x_start = 0;
                osd_hw.free_dst_data[index].y_start = 0;
-               width = layer_blend->output_data.w
-                       * blending->screen_ratio_w >> OSD_CALC;
-               height = (layer_blend->output_data.h - workaround_line)
-                       * blending->screen_ratio_h >> OSD_CALC;
-               if (osd_hw.field_out_en)
+               width = layer_blend->output_data.w *
+                       blending->screen_ratio_w_num /
+                       blending->screen_ratio_w_den;
+               height = (layer_blend->output_data.h - workaround_line) *
+                       blending->screen_ratio_h_num /
+                       blending->screen_ratio_h_den;
+               if (osd_hw.field_out_en[output_index])
                        height = height >> 1;
        } else {
                osd_hw.free_src_data[index].x_start =
@@ -6469,15 +6713,19 @@ static void osd_set_freescale(u32 index,
                        (blending->osd_blend_mode == OSD_BLEND_ABC)) {
                        /* combine mode, need uniformization */
                        osd_hw.free_dst_data[index].x_start =
-                               (osd_hw.dst_data[index].x << OSD_CALC) /
-                               blending->screen_ratio_w;
+                               osd_hw.dst_data[index].x *
+                               blending->screen_ratio_w_den /
+                               blending->screen_ratio_w_num;
                        osd_hw.free_dst_data[index].y_start =
-                               (osd_hw.dst_data[index].y << OSD_CALC) /
-                               blending->screen_ratio_h;
-                       width = (osd_hw.dst_data[index].w << OSD_CALC) /
-                               blending->screen_ratio_w;
-                       height = (osd_hw.dst_data[index].h << OSD_CALC) /
-                               blending->screen_ratio_h;
+                               osd_hw.dst_data[index].y *
+                               blending->screen_ratio_h_den /
+                               blending->screen_ratio_h_num;
+                       width = osd_hw.dst_data[index].w *
+                               blending->screen_ratio_w_den /
+                               blending->screen_ratio_w_num;
+                       height = osd_hw.dst_data[index].h *
+                               blending->screen_ratio_h_den /
+                               blending->screen_ratio_h_num;
                        if (width > FREE_SCALE_MAX_WIDTH)
                                width = FREE_SCALE_MAX_WIDTH;
                } else if (blending->osd_blend_mode == OSD_BLEND_AB_C) {
@@ -6486,17 +6734,19 @@ static void osd_set_freescale(u32 index,
                        if (blending->blend_din != BLEND_DIN4) {
                                /* combine mode, need uniformization */
                                osd_hw.free_dst_data[index].x_start =
-                                       (osd_hw.dst_data[index].x << OSD_CALC) /
-                                       blending->screen_ratio_w;
+                                       osd_hw.dst_data[index].x *
+                                       blending->screen_ratio_w_den /
+                                       blending->screen_ratio_w_num;
                                osd_hw.free_dst_data[index].y_start =
-                                       (osd_hw.dst_data[index].y << OSD_CALC) /
-                                       blending->screen_ratio_h;
-                               width = (osd_hw.dst_data[index].w
-                                       << OSD_CALC) /
-                                       blending->screen_ratio_w;
-                               height = (osd_hw.dst_data[index].h
-                                       << OSD_CALC) /
-                                       blending->screen_ratio_h;
+                                       osd_hw.dst_data[index].y *
+                                       blending->screen_ratio_h_den /
+                                       blending->screen_ratio_h_num;
+                               width = osd_hw.dst_data[index].w *
+                                       blending->screen_ratio_w_den /
+                                       blending->screen_ratio_w_num;
+                               height = osd_hw.dst_data[index].h *
+                                       blending->screen_ratio_h_den /
+                                       blending->screen_ratio_h_num;
                        } else {
                                /* direct used dst as freescale dst */
                                osd_hw.free_dst_data[index].x_start =
@@ -6506,7 +6756,7 @@ static void osd_set_freescale(u32 index,
                                width = osd_hw.dst_data[index].w;
                                height = osd_hw.dst_data[index].h;
                                /* interleaced case */
-                               if (osd_hw.field_out_en) {
+                               if (osd_hw.field_out_en[output_index]) {
                                        height = height >> 1;
                                        osd_hw.free_dst_data[index].y_start
                                                >>= 1;
@@ -6520,7 +6770,7 @@ static void osd_set_freescale(u32 index,
                                osd_hw.dst_data[index].y;
                        width = osd_hw.dst_data[index].w;
                        height = osd_hw.dst_data[index].h;
-                       if (osd_hw.field_out_en) {
+                       if (osd_hw.field_out_en[output_index]) {
                                height = height >> 1;
                                osd_hw.free_dst_data[index].y_start >>= 1;
                        }
@@ -6650,7 +6900,6 @@ static void osd_setting_blend1_input(u32 index,
                layer_blend->output_data.h);
 }
 
-/* every output is next path input */
 static void set_blend_path(struct hw_osd_blending_s *blending)
 {
        struct layer_blend_s *layer_blend;
@@ -6658,14 +6907,14 @@ static void set_blend_path(struct hw_osd_blending_s *blending)
        struct dispdata_s output1_data;
        u32 index = 0;
        u8 input1 = 0, input2 = 0;
+       u32 output_index;
 
        if (!blending)
                return;
+       output_index = get_output_device_id(index);
        layer_blend = &(blending->layer_blend);
        blend_reg = &(blending->blend_reg);
-#ifdef OSD_BLEND_SHIFT_WORKAROUND
        layer_blend->blend_core1_bypass = 0;
-#endif
        switch (blending->osd_blend_mode) {
        case OSD_BLEND_NONE:
                blend_reg->postbld_osd1_premult = 0;
@@ -6706,13 +6955,13 @@ static void set_blend_path(struct hw_osd_blending_s *blending)
 
                        layer_blend->input1_data.x =
                                osd_hw.free_dst_data[index].x_start +
-                               osd_hw.disp_info.position_x;
+                               osd_hw.disp_info[output_index].position_x;
                        layer_blend->input1_data.w =
                                osd_hw.free_dst_data[index].x_end -
                                osd_hw.free_dst_data[index].x_start + 1;
                        layer_blend->input1_data.y =
                                osd_hw.free_dst_data[index].y_start +
-                               osd_hw.disp_info.position_y;
+                               osd_hw.disp_info[output_index].position_y;
                        layer_blend->input1_data.h =
                                osd_hw.free_dst_data[index].y_end -
                                osd_hw.free_dst_data[index].y_start + 1;
@@ -6721,13 +6970,13 @@ static void set_blend_path(struct hw_osd_blending_s *blending)
                                "first: set osd%d freescale\n", index);
                        osd_set_freescale(index, blending);
                        osd_hw.free_dst_data[index].x_start +=
-                               osd_hw.disp_info.position_x;
+                               osd_hw.disp_info[output_index].position_x;
                        osd_hw.free_dst_data[index].x_end +=
-                               osd_hw.disp_info.position_x;
+                               osd_hw.disp_info[output_index].position_x;
                        osd_hw.free_dst_data[index].y_start +=
-                               osd_hw.disp_info.position_y;
+                               osd_hw.disp_info[output_index].position_y;
                        osd_hw.free_dst_data[index].y_end +=
-                               osd_hw.disp_info.position_y;
+                               osd_hw.disp_info[output_index].position_y;
 
                        osd_setting_blend0_input(index, blending);
                        osd_setting_blend0(blending);
@@ -6773,9 +7022,6 @@ static void set_blend_path(struct hw_osd_blending_s *blending)
                index = blend_din_to_osd(input1, blending);
                if (index >= OSD_MAX)
                        return;
-#ifndef OSD_BLEND_SHIFT_WORKAROUND
-               osd_setting_blend0_input(index, blending);
-#endif
                if (index != OSD1) {
                        /* here used freescale osd1/osd2 */
                        osd_log_dbg2(MODULE_BLEND,
@@ -6783,9 +7029,7 @@ static void set_blend_path(struct hw_osd_blending_s *blending)
                                index);
                        osd_set_freescale(index, blending);
                }
-#ifdef OSD_BLEND_SHIFT_WORKAROUND
                osd_setting_blend0_input(index, blending);
-#endif
                osd_setting_blend0(blending);
                memcpy(&output1_data, &(layer_blend->output_data),
                        sizeof(struct dispdata_s));
@@ -6801,22 +7045,7 @@ static void set_blend_path(struct hw_osd_blending_s *blending)
                }
                layer_blend->input1 = BLEND_NO_DIN;
                layer_blend->input2 = input2;
-#ifndef OSD_BLEND_SHIFT_WORKAROUND
-               if (osd_hw.blend_bypass)
-                       layer_blend->input2 |= BYPASS_DIN;
-#endif
-#if 0
-               layer_blend->input2_data.x =
-                       osd_hw.free_dst_data[index].x_start;
-               layer_blend->input2_data.w =
-                       osd_hw.free_dst_data[index].x_end -
-                       osd_hw.free_dst_data[index].x_start + 1;
-               layer_blend->input2_data.y =
-                       osd_hw.free_dst_data[index].y_start;
-               layer_blend->input2_data.h =
-                       osd_hw.free_dst_data[index].y_end -
-                       osd_hw.free_dst_data[index].y_start + 1;
-#endif
+
                osd_setting_blend1_input(index, blending);
                memcpy(&layer_blend->input2_data,
                        &layer_blend->output_data,
@@ -6838,13 +7067,13 @@ static void set_blend_path(struct hw_osd_blending_s *blending)
                layer_blend->input2 = BLEND_NO_DIN;
                layer_blend->input1_data.x =
                        osd_hw.free_dst_data[OSD1].x_start +
-                       osd_hw.disp_info.position_x;
+                       osd_hw.disp_info[output_index].position_x;
                layer_blend->input1_data.w =
                        osd_hw.free_dst_data[OSD1].x_end -
                        osd_hw.free_dst_data[OSD1].x_start + 1;
                layer_blend->input1_data.y =
                        osd_hw.free_dst_data[OSD1].y_start +
-                       osd_hw.disp_info.position_y;
+                       osd_hw.disp_info[output_index].position_y;
                layer_blend->input1_data.h =
                        osd_hw.free_dst_data[OSD1].y_end -
                        osd_hw.free_dst_data[OSD1].y_start + 1;
@@ -6882,20 +7111,20 @@ static void set_blend_path(struct hw_osd_blending_s *blending)
                /* save freescale output */
                output1_data.x =
                        osd_hw.free_dst_data[index].x_start +
-                       osd_hw.disp_info.position_x;
+                       osd_hw.disp_info[output_index].position_x;
                output1_data.w =
                        osd_hw.free_dst_data[index].x_end -
                        osd_hw.free_dst_data[index].x_start + 1;
                output1_data.y =
                        osd_hw.free_dst_data[index].y_start +
-                       osd_hw.disp_info.position_y;
+                       osd_hw.disp_info[output_index].position_y;
                output1_data.h =
                        osd_hw.free_dst_data[index].y_end -
                        osd_hw.free_dst_data[index].y_start + 1;
 
                osd_log_dbg2(MODULE_BLEND, "position_x=%d, y=%d\n",
-                       osd_hw.disp_info.position_x,
-                       osd_hw.disp_info.position_y);
+                       osd_hw.disp_info[output_index].position_x,
+                       osd_hw.disp_info[output_index].position_y);
 
                index = blend_din_to_osd(BLEND_DIN4, blending);
                if (index >= OSD_MAX)
@@ -6904,41 +7133,19 @@ static void set_blend_path(struct hw_osd_blending_s *blending)
                osd_log_dbg2(MODULE_BLEND,
                "before blend1: set osd%d freescale\n", index);
                osd_set_freescale(index, blending);
-#ifdef OSD_BLEND_SHIFT_WORKAROUND
                layer_blend->input1 = BLEND_NO_DIN;
                /* must bypass for shift workaround */
                layer_blend->input2 = BLEND_DIN4 | BYPASS_DIN;
                layer_blend->blend_core1_bypass = 1;
-#else
-               /* always route(bypass) to dout1 */
-               layer_blend->input1 = BLEND_NO_DIN | BYPASS_DIN;
-               layer_blend->input2 = BLEND_DIN4;
-               if (osd_hw.blend_bypass)
-                       layer_blend->input2 |= BYPASS_DIN;
-#endif
-               #if 0
-               layer_blend->input2_data.x =
-                       osd_hw.free_dst_data[index].x_start +
-                       osd_hw.disp_info.position_x;
-               layer_blend->input2_data.w =
-                       osd_hw.free_dst_data[index].x_end -
-                       osd_hw.free_dst_data[index].x_start + 1;
-               layer_blend->input2_data.y =
-                       osd_hw.free_dst_data[index].y_start +
-                       osd_hw.disp_info.position_y;
-               layer_blend->input2_data.h =
-                       osd_hw.free_dst_data[index].y_end -
-                       osd_hw.free_dst_data[index].y_start + 1;
-               #endif
                osd_setting_blend1_input(index, blending);
                memcpy(&layer_blend->input2_data,
                        &layer_blend->output_data,
                        sizeof(struct dispdata_s));
                /* adjust offset*/
                layer_blend->input2_data.x +=
-                       osd_hw.disp_info.position_x;
+                       osd_hw.disp_info[output_index].position_x;
                layer_blend->input2_data.y +=
-                       osd_hw.disp_info.position_y;
+                       osd_hw.disp_info[output_index].position_y;
 
                osd_setting_blend1(blending);
 
@@ -7014,10 +7221,8 @@ static void set_blend_path(struct hw_osd_blending_s *blending)
                layer_blend->input2 = BLEND1_DIN;
                memcpy(&layer_blend->input1_data, &output1_data,
                        sizeof(struct dispdata_s));
-#ifdef OSD_BLEND_SHIFT_WORKAROUND
                memcpy(&layer_blend->input2_data, &layer_blend->output_data,
                        sizeof(struct dispdata_s));
-#endif
                osd_setting_blend2(blending);
                /* used osd0 freescale */
                osd_set_freescale(OSD1, blending);
@@ -7026,21 +7231,600 @@ static void set_blend_path(struct hw_osd_blending_s *blending)
                layer_blend->input2 = BLEND_NO_DIN;
                layer_blend->input1_data.x =
                        osd_hw.free_dst_data[OSD1].x_start +
-                       osd_hw.disp_info.position_x;
+                       osd_hw.disp_info[output_index].position_x;
                layer_blend->input1_data.w =
                        osd_hw.free_dst_data[OSD1].x_end -
                        osd_hw.free_dst_data[OSD1].x_start + 1;
                layer_blend->input1_data.y =
                        osd_hw.free_dst_data[OSD1].y_start +
-                       osd_hw.disp_info.position_y;
+                       osd_hw.disp_info[output_index].position_y;
                layer_blend->input1_data.h =
                        osd_hw.free_dst_data[OSD1].y_end -
                        osd_hw.free_dst_data[OSD1].y_start + 1;
                vpp_setting_blend(blending);
                break;
-       case OSD_BLEND_A_BC:
-               /* blend0 -->blend2-->sc->vpp_osd1 */
-               /* 2input-->sc-->blend1 -->vpp_osd2 */
+       case OSD_BLEND_A_BC:
+               /* blend0 -->blend2-->sc->vpp_osd1 */
+               /* 2input-->sc-->blend1 -->vpp_osd2 */
+               layer_blend->input1 = BLEND_DIN1;
+               if (osd_hw.blend_bypass)
+                       layer_blend->input1 |= BYPASS_DIN;
+               layer_blend->input2 = BLEND_NO_DIN;
+               index = blend_din_to_osd(BLEND_DIN1, blending);
+               if (index >= OSD_MAX)
+                       return;
+               osd_setting_blend0_input(index, blending);
+               osd_setting_blend0(blending);
+
+               if (!blend_reg->din0_byp_blend) {
+                       layer_blend->input1 = BLEND0_DIN;
+                       layer_blend->input2 = BLEND_NO_DIN;
+                       memcpy(&layer_blend->input1_data,
+                               &layer_blend->output_data,
+                               sizeof(struct dispdata_s));
+                       /* background is same with blend0's background */
+                       osd_setting_blend2(blending);
+               }
+
+               osd_log_dbg(MODULE_BLEND,
+                       "after blend2: set osd%d freescale\n", index);
+               osd_set_freescale(index, blending);
+               /* save freescale output */
+               output1_data.x =
+                       osd_hw.free_dst_data[index].x_start +
+                       osd_hw.disp_info[output_index].position_x;
+               output1_data.w =
+                       osd_hw.free_dst_data[index].x_end -
+                       osd_hw.free_dst_data[index].x_start + 1;
+               output1_data.y =
+                       osd_hw.free_dst_data[index].y_start +
+                       osd_hw.disp_info[output_index].position_y;
+               output1_data.h =
+                       osd_hw.free_dst_data[index].y_end -
+                       osd_hw.free_dst_data[index].y_start + 1;
+               index = blend_din_to_osd(BLEND_DIN3, blending);
+               if (index >= OSD_MAX)
+                       return;
+               osd_log_dbg2(MODULE_BLEND,
+                       "before blend1: set osd%d freescale\n", index);
+               osd_set_freescale(index, blending);
+               layer_blend->input1_data.x =
+                       osd_hw.free_dst_data[index].x_start +
+                       osd_hw.disp_info[output_index].position_x;
+               layer_blend->input1_data.w =
+                       osd_hw.free_dst_data[index].x_end -
+                       osd_hw.free_dst_data[index].x_start + 1;
+               layer_blend->input1_data.y =
+                       osd_hw.free_dst_data[index].y_start +
+                       osd_hw.disp_info[output_index].position_y;
+               layer_blend->input1_data.h =
+                       osd_hw.free_dst_data[index].y_end -
+                       osd_hw.free_dst_data[index].y_start + 1;
+
+               index = blend_din_to_osd(BLEND_DIN4, blending);
+               if (index >= OSD_MAX)
+                       return;
+               osd_log_dbg2(MODULE_BLEND,
+                       "before blend1: set osd%d freescale\n", index);
+               osd_set_freescale(index, blending);
+               layer_blend->input2_data.x =
+                       osd_hw.free_dst_data[index].x_start +
+                       osd_hw.disp_info[output_index].position_x;
+               layer_blend->input2_data.w =
+                       osd_hw.free_dst_data[index].x_end -
+                       osd_hw.free_dst_data[index].x_start + 1;
+               layer_blend->input2_data.y =
+                       osd_hw.free_dst_data[index].y_start +
+                       osd_hw.disp_info[output_index].position_y;
+               layer_blend->input2_data.h =
+                       osd_hw.free_dst_data[index].y_end -
+                       osd_hw.free_dst_data[index].y_start + 1;
+
+               /* always route(bypass) to dout1 */
+               layer_blend->input1 = BLEND_DIN3 | BYPASS_DIN;
+               layer_blend->input2 = BLEND_DIN4;
+
+               osd_setting_blend1(blending);
+
+               if (!blending->b_exchange_blend_in) {
+                       layer_blend->input1 = BLEND2_DIN;
+                       layer_blend->input2 = BLEND1_DIN;
+                       memcpy(&layer_blend->input1_data, &output1_data,
+                               sizeof(struct dispdata_s));
+                       memcpy(&layer_blend->input2_data,
+                               &layer_blend->output_data,
+                               sizeof(struct dispdata_s));
+               } else {
+                       layer_blend->input1 = BLEND1_DIN;
+                       layer_blend->input2 = BLEND2_DIN;
+                       memcpy(&layer_blend->input1_data,
+                               &layer_blend->output_data,
+                               sizeof(struct dispdata_s));
+                       memcpy(&layer_blend->input2_data,
+                               &output1_data,
+                               sizeof(struct dispdata_s));
+               }
+               vpp_setting_blend(blending);
+               break;
+       case OSD_BLEND_AB_C:
+               /* blend0 -->blend2-->sc->vpp_osd1 */
+               /* sc-->blend1-->blend2-->sc-->vpp_osd1 */
+               /* sc -->vpp_osd2 */
+               layer_blend->input1 = BLEND_DIN1;
+               layer_blend->input2 = BLEND_NO_DIN;
+               blending->blend_din = BLEND_DIN1;
+               index = blend_din_to_osd(BLEND_DIN1, blending);
+               if (index != OSD1) {
+                       osd_log_info("index=%d, need set freescale\n", index);
+                       osd_set_freescale(index, blending);
+               }
+               osd_setting_blend0_input(index, blending);
+               osd_setting_blend0(blending);
+               /* save blend0 output */
+               memcpy(&output1_data, &(layer_blend->output_data),
+                       sizeof(struct dispdata_s));
+
+               /* din3 input to blend1 */
+               layer_blend->input1 = BLEND_DIN3;
+               layer_blend->input2 = BLEND_NO_DIN | BYPASS_DIN;
+               layer_blend->blend_core1_bypass = 1;
+               blending->blend_din = BLEND_DIN3;
+               index = blend_din_to_osd(BLEND_DIN3, blending);
+               if (index != OSD1) {
+                       osd_log_dbg2(MODULE_BLEND,
+                               "before blend1: set osd%d freescale\n",
+                               index);
+                       osd_set_freescale(index, blending);
+               }
+               osd_setting_blend1_input(index, blending);
+               memcpy(&layer_blend->input1_data,
+                       &layer_blend->output_data,
+                       sizeof(struct dispdata_s));
+               osd_setting_blend1(blending);
+
+               /* din1=>blend0 & din3-> blend1 ==> blend2 */
+               layer_blend->input1 = BLEND0_DIN;
+               layer_blend->input2 = BLEND1_DIN;
+               memcpy(&layer_blend->input1_data, &output1_data,
+                       sizeof(struct dispdata_s));
+               memcpy(&layer_blend->input2_data, &layer_blend->output_data,
+                       sizeof(struct dispdata_s));
+               osd_setting_blend2(blending);
+
+               /* blend2 ==> osd0 freescale */
+               osd_set_freescale(OSD1, blending);
+               output1_data.x =
+                       osd_hw.free_dst_data[OSD1].x_start +
+                       osd_hw.disp_info[output_index].position_x;
+               output1_data.w =
+                       osd_hw.free_dst_data[OSD1].x_end -
+                       osd_hw.free_dst_data[OSD1].x_start + 1;
+               output1_data.y =
+                       osd_hw.free_dst_data[OSD1].y_start +
+                       osd_hw.disp_info[output_index].position_y;
+               output1_data.h =
+                       osd_hw.free_dst_data[OSD1].y_end -
+                       osd_hw.free_dst_data[OSD1].y_start + 1;
+               osd_log_dbg2(MODULE_BLEND, "output1_data:%d,%d,%d,%d\n",
+                       output1_data.x,
+                       output1_data.w,
+                       output1_data.y,
+                       output1_data.h);
+
+
+               /* din4 ==> vpp */
+               index = blend_din_to_osd(BLEND_DIN4, blending);
+               blending->blend_din = BLEND_DIN4;
+               osd_log_dbg2(MODULE_BLEND,
+                       "bypass blend1: set osd%d freescale\n", index);
+               osd_set_freescale(index, blending);
+
+               layer_blend->input2_data.x =
+                       osd_hw.free_dst_data[index].x_start +
+                       osd_hw.disp_info[output_index].position_x;
+               layer_blend->input2_data.w =
+                       osd_hw.free_dst_data[index].x_end -
+                       osd_hw.free_dst_data[index].x_start + 1;
+               layer_blend->input2_data.y =
+                       osd_hw.free_dst_data[index].y_start +
+                       osd_hw.disp_info[output_index].position_y;
+               layer_blend->input2_data.h =
+                       osd_hw.free_dst_data[index].y_end -
+                       osd_hw.free_dst_data[index].y_start + 1;
+
+               /* 2vpp input */
+               if (!blending->b_exchange_blend_in) {
+                       layer_blend->input1 = BLEND2_DIN;
+                       layer_blend->input2 = BLEND1_DIN;
+                       memcpy(&layer_blend->input1_data, &output1_data,
+                               sizeof(struct dispdata_s));
+               } else {
+                       layer_blend->input1 = BLEND1_DIN;
+                       layer_blend->input2 = BLEND2_DIN;
+                       memcpy(&layer_blend->input1_data,
+                               &layer_blend->input2_data,
+                               sizeof(struct dispdata_s));
+                       memcpy(&layer_blend->input2_data,
+                               &output1_data,
+                               sizeof(struct dispdata_s));
+               }
+               vpp_setting_blend(blending);
+               break;
+       }
+}
+
+static void osd_setting_blend0_new(struct hw_osd_blending_s *blending)
+{
+       struct layer_blend_reg_s *blend_reg;
+       struct layer_blend_s *layer_blend;
+       u32 index = 0;
+       u32 bld_osd_h_start = 0, bld_osd_h_end = 0;
+       u32 bld_osd_v_start = 0, bld_osd_v_end = 0;
+
+       if (!blending)
+               return;
+       layer_blend = &(blending->layer_blend);
+       blend_reg = &(blending->blend_reg);
+       /* blend0 only accept input1 */
+       if (layer_blend->input1 & BYPASS_DIN) {
+               blend_reg->din0_byp_blend = 1;
+               layer_blend->input1 &= ~BYPASS_DIN;
+       } else
+               blend_reg->din0_byp_blend = 0;
+       if (layer_blend->input1 != BLEND_NO_DIN) {
+               /* calculate osd blend din scope */
+               index = blend_din_to_osd(layer_blend->input1, blending);
+               if (index >= OSD_MAX)
+                       return;
+               layer_blend->input1_data.x =
+                       osd_hw.free_dst_data[index].x_start;
+               layer_blend->input1_data.y =
+                       osd_hw.free_dst_data[index].y_start;
+               layer_blend->input1_data.w =
+                       osd_hw.free_dst_data[index].x_end -
+                       osd_hw.free_dst_data[index].x_start + 1;
+               layer_blend->input1_data.h =
+                       osd_hw.free_dst_data[index].y_end -
+                       osd_hw.free_dst_data[index].y_start + 1;
+
+               bld_osd_h_start =
+                       layer_blend->input1_data.x;
+               bld_osd_h_end =
+                       layer_blend->input1_data.x +
+                       layer_blend->input1_data.w - 1;
+               bld_osd_v_start =
+                       layer_blend->input1_data.y;
+               bld_osd_v_end =
+                       layer_blend->input1_data.y +
+                       layer_blend->input1_data.h - 1;
+               blend_reg->osd_blend_din_scope_h[index] =
+                       bld_osd_h_end << 16 | bld_osd_h_start;
+               blend_reg->osd_blend_din_scope_v[index] =
+                       bld_osd_v_end << 16 | bld_osd_v_start;
+       }
+       layer_blend->output_data.x = 0;
+       layer_blend->output_data.y = 0;
+       layer_blend->output_data.w = layer_blend->input1_data.x
+               + layer_blend->input1_data.w;
+       layer_blend->output_data.h = layer_blend->input1_data.y
+               + layer_blend->input1_data.h;
+       osd_log_dbg2(MODULE_BLEND,
+               "blend0:input1_data[osd%d]:%d,%d,%d,%d\n",
+               index,
+               layer_blend->input1_data.x,
+               layer_blend->input1_data.y,
+               layer_blend->input1_data.w,
+               layer_blend->input1_data.h);
+       osd_log_dbg2(MODULE_BLEND,
+               "blend0:layer_blend->output_data:%d,%d,%d,%d\n",
+               layer_blend->output_data.x,
+               layer_blend->output_data.y,
+               layer_blend->output_data.w,
+               layer_blend->output_data.h);
+}
+
+static void osd_setting_blend1_new(struct hw_osd_blending_s *blending)
+{
+       struct layer_blend_s *layer_blend;
+       struct layer_blend_reg_s *blend_reg;
+       u32 index = 0;
+       u32 blend_hsize, blend_vsize;
+       u32 bld_osd_h_start = 0, bld_osd_h_end = 0;
+       u32 bld_osd_v_start = 0, bld_osd_v_end = 0;
+       /* for g12a blend shift issue */
+
+       if (!blending)
+               return;
+       layer_blend = &(blending->layer_blend);
+       blend_reg = &(blending->blend_reg);
+       /* blend1_dout to blend2 */
+       blend_reg->din2_osd_sel = 0;
+
+       if (layer_blend->input2 & BYPASS_DIN) {
+               /* blend1_din3 bypass to dout1 */
+               blend_reg->din3_osd_sel = 1;
+               layer_blend->input2 &= ~BYPASS_DIN;
+       } else
+               /* blend1_din3 input to blend1 */
+               blend_reg->din3_osd_sel = 0;
+
+       if (layer_blend->input1 != BLEND_NO_DIN) {
+               index = blend_din_to_osd(layer_blend->input1, blending);
+               if (index >= OSD_MAX)
+                       return;
+               layer_blend->input1_data.x =
+                       osd_hw.free_dst_data[index].x_start;
+               layer_blend->input1_data.y =
+                       osd_hw.free_dst_data[index].y_start;
+               layer_blend->input1_data.w =
+                       osd_hw.free_dst_data[index].x_end -
+                       osd_hw.free_dst_data[index].x_start + 1;
+               layer_blend->input1_data.h =
+                       osd_hw.free_dst_data[index].y_end -
+                       osd_hw.free_dst_data[index].y_start + 1;
+
+               /* calculate osd blend din scope */
+               bld_osd_h_start =
+                       layer_blend->input1_data.x;
+               bld_osd_h_end =
+                       layer_blend->input1_data.x +
+                       layer_blend->input1_data.w - 1;
+               bld_osd_v_start =
+                       layer_blend->input1_data.y;
+               bld_osd_v_end =
+                       layer_blend->input1_data.y +
+                       layer_blend->input1_data.h - 1;
+               blend_reg->osd_blend_din_scope_h[index] =
+                       bld_osd_h_end << 16 | bld_osd_h_start;
+               blend_reg->osd_blend_din_scope_v[index] =
+                       bld_osd_v_end << 16 | bld_osd_v_start;
+               osd_log_dbg2(MODULE_BLEND,
+                       "blend1:input1_data(osd%d):%d,%d,%d,%d\n",
+                       index,
+                       layer_blend->input1_data.x,
+                       layer_blend->input1_data.y,
+                       layer_blend->input1_data.w,
+                       layer_blend->input1_data.h);
+       }
+       if (layer_blend->input2 != BLEND_NO_DIN) {
+               index = blend_din_to_osd(layer_blend->input2, blending);
+               if (index >= OSD_MAX)
+                       return;
+               layer_blend->input2_data.x =
+                       osd_hw.free_dst_data[index].x_start;
+               layer_blend->input2_data.y =
+                       osd_hw.free_dst_data[index].y_start;
+               layer_blend->input2_data.w =
+                       osd_hw.free_dst_data[index].x_end -
+                       osd_hw.free_dst_data[index].x_start + 1;
+               layer_blend->input2_data.h =
+                       osd_hw.free_dst_data[index].y_end -
+                       osd_hw.free_dst_data[index].y_start + 1;
+               /* calculate osd blend din scope */
+               bld_osd_h_start =
+                       layer_blend->input2_data.x;
+               bld_osd_h_end =
+                       layer_blend->input2_data.x +
+                       layer_blend->input2_data.w - 1;
+               bld_osd_v_start =
+                       layer_blend->input2_data.y;
+               bld_osd_v_end =
+                       layer_blend->input2_data.y +
+                       layer_blend->input2_data.h - 1;
+               blend_reg->osd_blend_din_scope_h[index] =
+                       bld_osd_h_end << 16 | bld_osd_h_start;
+               blend_reg->osd_blend_din_scope_v[index] =
+                       bld_osd_v_end << 16 | bld_osd_v_start;
+               osd_log_dbg2(MODULE_BLEND,
+                       "layer_blend->input2_data:%d,%d,%d,%d\n",
+                       layer_blend->input2_data.x,
+                       layer_blend->input2_data.y,
+                       layer_blend->input2_data.w,
+                       layer_blend->input2_data.h);
+       }
+       if (blend_reg->din3_osd_sel || layer_blend->input1 == BLEND_NO_DIN) {
+               /* blend din3 bypass,output == input */
+               if (layer_blend->input2 == BLEND_NO_DIN) {
+                       memcpy(&layer_blend->output_data,
+                               &layer_blend->input1_data,
+                               sizeof(struct dispdata_s));
+               } else {
+                       memcpy(&layer_blend->output_data,
+                               &layer_blend->input2_data,
+                               sizeof(struct dispdata_s));
+               }
+       } else
+               calc_max_output(blending);
+       blend_hsize = layer_blend->output_data.w;
+       blend_vsize = layer_blend->output_data.h;
+       blend_reg->osd_blend_blend1_size =
+               blend_vsize  << 16 | blend_hsize;
+
+       osd_log_dbg2(MODULE_BLEND, "layer_blend1->output_data:%d,%d,%d,%d\n",
+               layer_blend->output_data.x,
+               layer_blend->output_data.y,
+               layer_blend->output_data.w,
+               layer_blend->output_data.h);
+}
+
+/* input w, h is background */
+static void osd_set_freescale_new(u32 index,
+       struct hw_osd_blending_s *blending)
+
+{
+       struct layer_blend_s *layer_blend;
+       struct layer_blend_reg_s *blend_reg;
+       u32 width, height;
+       u32 src_height;
+       u32 output_index;
+
+       layer_blend = &(blending->layer_blend);
+       blend_reg = &(blending->blend_reg);
+       if (index >= osd_hw.osd_meson_dev.viu1_osd_count) {
+               osd_log_err("error osd index=%d\n", index);
+               return;
+       }
+       output_index = get_output_device_id(index);
+       osd_hw.free_scale_enable[index] = 0x10001;
+       osd_hw.free_scale[index].h_enable = 1;
+       osd_hw.free_scale[index].v_enable = 1;
+       osd_hw.free_scale_mode[index] = 1;
+
+       osd_hw.free_src_data[index].x_start =
+               osd_hw.src_data[index].x;
+       osd_hw.free_src_data[index].x_end =
+               osd_hw.src_data[index].x +
+               osd_hw.src_data[index].w - 1;
+       osd_hw.free_src_data[index].y_start =
+               osd_hw.src_data[index].y;
+       osd_hw.free_src_data[index].y_end =
+               osd_hw.src_data[index].y +
+               osd_hw.src_data[index].h - 1;
+
+       /* direct used dst as freescale dst */
+       osd_hw.free_dst_data[index].x_start =
+               osd_hw.dst_data[index].x;
+       osd_hw.free_dst_data[index].y_start =
+               osd_hw.dst_data[index].y;
+       width = osd_hw.dst_data[index].w;
+       height = osd_hw.dst_data[index].h;
+       if (osd_hw.field_out_en[output_index]) {
+               height = height >> 1;
+               osd_hw.free_dst_data[index].y_start >>= 1;
+       }
+       osd_hw.free_dst_data[index].x_end =
+               osd_hw.free_dst_data[index].x_start +
+               width - 1;
+       osd_hw.free_dst_data[index].y_end =
+               osd_hw.free_dst_data[index].y_start +
+               height - 1;
+
+       src_height = osd_hw.free_src_data[index].x_end -
+               osd_hw.free_src_data[index].x_start + 1;
+       osd_set_dummy_data(index, 0xff);
+       osd_log_dbg2(MODULE_BLEND, "osd%d:free_src_data:%d,%d,%d,%d\n",
+               index,
+               osd_hw.free_src_data[index].x_start,
+               osd_hw.free_src_data[index].y_start,
+               osd_hw.free_src_data[index].x_end,
+               osd_hw.free_src_data[index].y_end);
+       osd_log_dbg2(MODULE_BLEND, "osd%d:free_dst_data:%d,%d,%d,%d\n",
+               index,
+               osd_hw.free_dst_data[index].x_start,
+               osd_hw.free_dst_data[index].y_start,
+               osd_hw.free_dst_data[index].x_end,
+               osd_hw.free_dst_data[index].y_end);
+}
+
+/* every output is next path input */
+static void set_blend_path_new(struct hw_osd_blending_s *blending)
+{
+       struct layer_blend_s *layer_blend;
+       struct layer_blend_reg_s *blend_reg;
+       struct dispdata_s output1_data;
+       u32 index = 0;
+       u8 input1 = 0, input2 = 0;
+       u32 output_index;
+
+       if (!blending)
+               return;
+       output_index = get_output_device_id(index);
+
+       layer_blend = &(blending->layer_blend);
+       blend_reg = &(blending->blend_reg);
+       layer_blend->blend_core1_bypass = 0;
+       switch (blending->osd_blend_mode) {
+       case OSD_BLEND_NONE:
+               blend_reg->postbld_osd1_premult = 0;
+               blend_reg->postbld_src4_sel = POSTBLD_CLOSE;
+               blend_reg->postbld_src3_sel = POSTBLD_CLOSE;
+               blend_reg->postbld_osd2_premult = 0;
+               break;
+       case OSD_BLEND_A:
+               /* sc-->blend0-->blend2-->vpp_osd1 */
+               layer_blend->input1 = BLEND_DIN1;
+               if (osd_hw.blend_bypass)
+                       layer_blend->input1 |= BYPASS_DIN;
+               layer_blend->input2 = BLEND_NO_DIN;
+               index = blend_din_to_osd(BLEND_DIN1, blending);
+               if (index >= OSD_MAX)
+                       return;
+               osd_set_freescale_new(index, blending);
+               osd_setting_blend0_new(blending);
+               if (!blend_reg->din0_byp_blend) {
+                       layer_blend->input1 = BLEND0_DIN;
+                       layer_blend->input2 = BLEND_NO_DIN;
+                       memcpy(&layer_blend->input1_data,
+                               &layer_blend->output_data,
+                               sizeof(struct dispdata_s));
+                       /* same with blend0's background */
+                       osd_setting_blend2(blending);
+               }
+               layer_blend->input1 = BLEND2_DIN;
+               layer_blend->input2 = BLEND_NO_DIN;
+               memcpy(&(layer_blend->input1_data),
+                               &(layer_blend->output_data),
+                               sizeof(struct dispdata_s));
+               layer_blend->input1_data.x +=
+                       osd_hw.disp_info[output_index].position_x;
+               layer_blend->input1_data.y +=
+                       osd_hw.disp_info[output_index].position_y;
+               vpp_setting_blend(blending);
+               break;
+       case OSD_BLEND_AC:
+               /* sc-->blend0 -->blend1-->blend2-->vpp_osd1 */
+               /* sc-->blend0 & blend1-->blend2-->vpp_osd1 */
+               if (!blending->b_exchange_din) {
+                       input1 = BLEND_DIN1;
+                       input2 = BLEND_DIN4;
+               } else {
+                       input1 = BLEND_DIN4;
+                       input2 = BLEND_DIN1;
+               }
+               layer_blend->input1 = input1;
+               layer_blend->input2 = BLEND_NO_DIN;
+               index = blend_din_to_osd(input1, blending);
+               if (index >= OSD_MAX)
+                       return;
+               osd_set_freescale_new(index, blending);
+               osd_setting_blend0_new(blending);
+               /* save blend0 output */
+               memcpy(&output1_data, &(layer_blend->output_data),
+                       sizeof(struct dispdata_s));
+
+               index = blend_din_to_osd(input2, blending);
+               if (index >= OSD_MAX)
+                       return;
+               osd_set_freescale_new(index, blending);
+               layer_blend->input1 = BLEND_NO_DIN;
+               layer_blend->input2 = input2;
+               osd_setting_blend1_new(blending);
+
+               layer_blend->input1 = BLEND0_DIN;
+               layer_blend->input2 = BLEND1_DIN;
+
+               /* blend0 output-> blend2  input1 */
+               memcpy(&layer_blend->input1_data, &output1_data,
+                       sizeof(struct dispdata_s));
+               /* blend1 output-> blend2  input2 */
+               memcpy(&layer_blend->input2_data, &layer_blend->output_data,
+                       sizeof(struct dispdata_s));
+               osd_setting_blend2(blending);
+
+               layer_blend->input1 = BLEND2_DIN;
+               layer_blend->input2 = BLEND_NO_DIN;
+               memcpy(&(layer_blend->input1_data),
+                               &(layer_blend->output_data),
+                               sizeof(struct dispdata_s));
+               layer_blend->input1_data.x +=
+                       osd_hw.disp_info[output_index].position_x;
+               layer_blend->input1_data.y +=
+                       osd_hw.disp_info[output_index].position_y;
+               vpp_setting_blend(blending);
+               break;
+       case OSD_BLEND_A_C:
+               /* sc-->blend0 -->blend2->vpp_osd1 */
+               /* sc-->blend1 -->vpp_osd2 */
                layer_blend->input1 = BLEND_DIN1;
                if (osd_hw.blend_bypass)
                        layer_blend->input1 |= BYPASS_DIN;
@@ -7048,9 +7832,8 @@ static void set_blend_path(struct hw_osd_blending_s *blending)
                index = blend_din_to_osd(BLEND_DIN1, blending);
                if (index >= OSD_MAX)
                        return;
-               osd_setting_blend0_input(index, blending);
-               osd_setting_blend0(blending);
-
+               osd_set_freescale_new(index, blending);
+               osd_setting_blend0_new(blending);
                if (!blend_reg->din0_byp_blend) {
                        layer_blend->input1 = BLEND0_DIN;
                        layer_blend->input2 = BLEND_NO_DIN;
@@ -7060,66 +7843,28 @@ static void set_blend_path(struct hw_osd_blending_s *blending)
                        /* background is same with blend0's background */
                        osd_setting_blend2(blending);
                }
-
-               osd_log_dbg(MODULE_BLEND,
-                       "after blend2: set osd%d freescale\n", index);
-               osd_set_freescale(index, blending);
-               /* save freescale output */
-               output1_data.x =
-                       osd_hw.free_dst_data[index].x_start +
-                       osd_hw.disp_info.position_x;
-               output1_data.w =
-                       osd_hw.free_dst_data[index].x_end -
-                       osd_hw.free_dst_data[index].x_start + 1;
-               output1_data.y =
-                       osd_hw.free_dst_data[index].y_start +
-                       osd_hw.disp_info.position_y;
-               output1_data.h =
-                       osd_hw.free_dst_data[index].y_end -
-                       osd_hw.free_dst_data[index].y_start + 1;
-               index = blend_din_to_osd(BLEND_DIN3, blending);
-               if (index >= OSD_MAX)
-                       return;
-               osd_log_dbg2(MODULE_BLEND,
-                       "before blend1: set osd%d freescale\n", index);
-               osd_set_freescale(index, blending);
-               layer_blend->input1_data.x =
-                       osd_hw.free_dst_data[index].x_start +
-                       osd_hw.disp_info.position_x;
-               layer_blend->input1_data.w =
-                       osd_hw.free_dst_data[index].x_end -
-                       osd_hw.free_dst_data[index].x_start + 1;
-               layer_blend->input1_data.y =
-                       osd_hw.free_dst_data[index].y_start +
-                       osd_hw.disp_info.position_y;
-               layer_blend->input1_data.h =
-                       osd_hw.free_dst_data[index].y_end -
-                       osd_hw.free_dst_data[index].y_start + 1;
+               /* save blend0/blend2 output */
+               memcpy(&output1_data, &(layer_blend->output_data),
+                       sizeof(struct dispdata_s));
+               /* adjust input 1 offset*/
+               output1_data.x +=
+                       osd_hw.disp_info[output_index].position_x;
+               output1_data.y +=
+                       osd_hw.disp_info[output_index].position_y;
 
                index = blend_din_to_osd(BLEND_DIN4, blending);
                if (index >= OSD_MAX)
                        return;
-               osd_log_dbg2(MODULE_BLEND,
-                       "before blend1: set osd%d freescale\n", index);
-               osd_set_freescale(index, blending);
-               layer_blend->input2_data.x =
-                       osd_hw.free_dst_data[index].x_start +
-                       osd_hw.disp_info.position_x;
-               layer_blend->input2_data.w =
-                       osd_hw.free_dst_data[index].x_end -
-                       osd_hw.free_dst_data[index].x_start + 1;
-               layer_blend->input2_data.y =
-                       osd_hw.free_dst_data[index].y_start +
-                       osd_hw.disp_info.position_y;
-               layer_blend->input2_data.h =
-                       osd_hw.free_dst_data[index].y_end -
-                       osd_hw.free_dst_data[index].y_start + 1;
-
-               /* always route(bypass) to dout1 */
-               layer_blend->input1 = BLEND_DIN3 | BYPASS_DIN;
-               layer_blend->input2 = BLEND_DIN4;
-
-               osd_setting_blend1(blending);
+               osd_set_freescale_new(index, blending);
+               layer_blend->input1 = BLEND_NO_DIN;
+               layer_blend->input2 = BLEND_DIN4 | BYPASS_DIN;
+               layer_blend->blend_core1_bypass = 1;
+               osd_setting_blend1_new(blending);
+               /* adjust input 2 offset*/
+               layer_blend->output_data.x +=
+                       osd_hw.disp_info[output_index].position_x;
+               layer_blend->output_data.y +=
+                       osd_hw.disp_info[output_index].position_y;
 
                if (!blending->b_exchange_blend_in) {
                        layer_blend->input1 = BLEND2_DIN;
@@ -7135,27 +7880,66 @@ static void set_blend_path(struct hw_osd_blending_s *blending)
                        memcpy(&layer_blend->input1_data,
                                &layer_blend->output_data,
                                sizeof(struct dispdata_s));
-                       memcpy(&layer_blend->input2_data,
-                               &output1_data,
+                       memcpy(&layer_blend->input2_data, &output1_data,
                                sizeof(struct dispdata_s));
                }
                vpp_setting_blend(blending);
                break;
-#ifdef OSD_BLEND_SHIFT_WORKAROUND
+       case OSD_BLEND_ABC:
+               /* sc->blend0 -->blend2-->vpp_osd1 */
+               /* sc-->blend1 -->blend2 */
+               input1 = BLEND_DIN1;
+               input2 = BLEND_DIN4;
+               layer_blend->input1 = input1;
+               layer_blend->input2 = BLEND_NO_DIN;
+               index = blend_din_to_osd(input1, blending);
+               if (index >= OSD_MAX)
+                       return;
+               osd_set_freescale_new(index, blending);
+               osd_setting_blend0_new(blending);
+               /* save blend0 output */
+               memcpy(&output1_data, &(layer_blend->output_data),
+                       sizeof(struct dispdata_s));
+
+               layer_blend->input1 = BLEND_DIN3;
+               layer_blend->input2 = input2;
+               index = blend_din_to_osd(layer_blend->input1, blending);
+               osd_set_freescale_new(index, blending);
+               index = blend_din_to_osd(layer_blend->input2, blending);
+               osd_set_freescale_new(index, blending);
+               osd_setting_blend1_new(blending);
+
+               layer_blend->input1 = BLEND0_DIN;
+               layer_blend->input2 = BLEND1_DIN;
+               memcpy(&layer_blend->input1_data, &output1_data,
+                       sizeof(struct dispdata_s));
+               memcpy(&layer_blend->input2_data, &layer_blend->output_data,
+                       sizeof(struct dispdata_s));
+               osd_setting_blend2(blending);
+
+               layer_blend->input1 = BLEND2_DIN;
+               layer_blend->input2 = BLEND_NO_DIN;
+               memcpy(&(layer_blend->input1_data),
+                               &(layer_blend->output_data),
+                               sizeof(struct dispdata_s));
+               layer_blend->input1_data.x +=
+                       osd_hw.disp_info[output_index].position_x;
+               layer_blend->input1_data.y +=
+                       osd_hw.disp_info[output_index].position_y;
+               vpp_setting_blend(blending);
+               break;
        case OSD_BLEND_AB_C:
-               /* blend0 -->blend2-->sc->vpp_osd1 */
-               /* sc-->blend1-->blend2-->sc-->vpp_osd1 */
+               /* sc-->blend0 -->blend2->vpp_osd1 */
+               /* sc-->blend1-->blend2-->vpp_osd1 */
                /* sc -->vpp_osd2 */
                layer_blend->input1 = BLEND_DIN1;
                layer_blend->input2 = BLEND_NO_DIN;
                blending->blend_din = BLEND_DIN1;
                index = blend_din_to_osd(BLEND_DIN1, blending);
-               if (index != OSD1) {
-                       osd_log_info("index=%d, need set freescale\n", index);
-                       osd_set_freescale(index, blending);
-               }
-               osd_setting_blend0_input(index, blending);
-               osd_setting_blend0(blending);
+               if (index >= OSD_MAX)
+                       return;
+               osd_set_freescale_new(index, blending);
+               osd_setting_blend0_new(blending);
                /* save blend0 output */
                memcpy(&output1_data, &(layer_blend->output_data),
                        sizeof(struct dispdata_s));
@@ -7166,17 +7950,8 @@ static void set_blend_path(struct hw_osd_blending_s *blending)
                layer_blend->blend_core1_bypass = 1;
                blending->blend_din = BLEND_DIN3;
                index = blend_din_to_osd(BLEND_DIN3, blending);
-               if (index != OSD1) {
-                       osd_log_dbg2(MODULE_BLEND,
-                               "before blend1: set osd%d freescale\n",
-                               index);
-                       osd_set_freescale(index, blending);
-               }
-               osd_setting_blend1_input(index, blending);
-               memcpy(&layer_blend->input1_data,
-                       &layer_blend->output_data,
-                       sizeof(struct dispdata_s));
-               osd_setting_blend1(blending);
+               osd_set_freescale_new(index, blending);
+               osd_setting_blend1_new(blending);
 
                /* din1=>blend0 & din3-> blend1 ==> blend2 */
                layer_blend->input1 = BLEND0_DIN;
@@ -7186,21 +7961,12 @@ static void set_blend_path(struct hw_osd_blending_s *blending)
                memcpy(&layer_blend->input2_data, &layer_blend->output_data,
                        sizeof(struct dispdata_s));
                osd_setting_blend2(blending);
-
-               /* blend2 ==> osd0 freescale */
-               osd_set_freescale(OSD1, blending);
-               output1_data.x =
-                       osd_hw.free_dst_data[OSD1].x_start +
-                       osd_hw.disp_info.position_x;
-               output1_data.w =
-                       osd_hw.free_dst_data[OSD1].x_end -
-                       osd_hw.free_dst_data[OSD1].x_start + 1;
-               output1_data.y =
-                       osd_hw.free_dst_data[OSD1].y_start +
-                       osd_hw.disp_info.position_y;
-               output1_data.h =
-                       osd_hw.free_dst_data[OSD1].y_end -
-                       osd_hw.free_dst_data[OSD1].y_start + 1;
+               memcpy(&output1_data, &(layer_blend->output_data),
+                       sizeof(struct dispdata_s));
+               output1_data.x +=
+                       osd_hw.disp_info[output_index].position_x;
+               output1_data.y +=
+                       osd_hw.disp_info[output_index].position_y;
                osd_log_dbg2(MODULE_BLEND, "output1_data:%d,%d,%d,%d\n",
                        output1_data.x,
                        output1_data.w,
@@ -7211,19 +7977,16 @@ static void set_blend_path(struct hw_osd_blending_s *blending)
                /* din4 ==> vpp */
                index = blend_din_to_osd(BLEND_DIN4, blending);
                blending->blend_din = BLEND_DIN4;
-               osd_log_dbg2(MODULE_BLEND,
-                       "bypass blend1: set osd%d freescale\n", index);
-               osd_set_freescale(index, blending);
-
+               osd_set_freescale_new(index, blending);
                layer_blend->input2_data.x =
                        osd_hw.free_dst_data[index].x_start +
-                       osd_hw.disp_info.position_x;
+                       osd_hw.disp_info[output_index].position_x;
                layer_blend->input2_data.w =
                        osd_hw.free_dst_data[index].x_end -
                        osd_hw.free_dst_data[index].x_start + 1;
                layer_blend->input2_data.y =
                        osd_hw.free_dst_data[index].y_start +
-                       osd_hw.disp_info.position_y;
+                       osd_hw.disp_info[output_index].position_y;
                layer_blend->input2_data.h =
                        osd_hw.free_dst_data[index].y_end -
                        osd_hw.free_dst_data[index].y_start + 1;
@@ -7246,7 +8009,6 @@ static void set_blend_path(struct hw_osd_blending_s *blending)
                }
                vpp_setting_blend(blending);
                break;
-#endif
        }
 }
 
@@ -7255,16 +8017,16 @@ static void set_blend_reg(struct layer_blend_reg_s *blend_reg)
        int i;
        u32 reg_offset = 2;
        u32 osd1_alpha_div = 0, osd2_alpha_div = 0;
-#ifdef OSD_BLEND_SHIFT_WORKAROUND
        u32 osd_count = OSD_BLEND_LAYERS;
-#else
-       u32 osd_count = osd_hw.osd_meson_dev.viu1_osd_count;
-#endif
        u32 dv_core2_hsize;
        u32 dv_core2_vsize;
 
        if (!blend_reg)
                return;
+       /* osd0 scale position before osd blend */
+       if (osd_hw.osd_meson_dev.osd0_sc_independ)
+               VSYNCOSD_WR_MPEG_REG(VPP_OSD_SCALE_CTRL, 0x01);
+
        /* osd blend ctrl */
        VSYNCOSD_WR_MPEG_REG(VIU_OSD_BLEND_CTRL,
                4                                 << 29|
@@ -7305,6 +8067,10 @@ static void set_blend_reg(struct layer_blend_reg_s *blend_reg)
 
        VSYNCOSD_WR_MPEG_REG(VIU_OSD_BLEND_BLEND0_SIZE,
                blend_reg->osd_blend_blend0_size);
+       /* hdr input size should set to osd blend0 output size */
+       VSYNCOSD_WR_MPEG_REG(VPP_OSD1_IN_SIZE,
+               blend_reg->osd_blend_blend0_size);
+
        VSYNCOSD_WR_MPEG_REG(VIU_OSD_BLEND_BLEND1_SIZE,
                blend_reg->osd_blend_blend1_size);
 
@@ -7326,7 +8092,6 @@ static void set_blend_reg(struct layer_blend_reg_s *blend_reg)
                        VIU_OSD_BLEND_DIN0_SCOPE_V + reg_offset * i,
                        blend_reg->osd_blend_din_scope_v[i]);
                }
-#ifdef OSD_BLEND_SHIFT_WORKAROUND
                else {
                        if ((blend_reg->osd_blend_din_scope_v[i] & 0xffff) == 0)
                                blend_reg->osd_blend_din_scope_v[i] = 0x43a0439;
@@ -7334,7 +8099,6 @@ static void set_blend_reg(struct layer_blend_reg_s *blend_reg)
                                VIU_OSD_BLEND_DIN0_SCOPE_V + reg_offset * i,
                                blend_reg->osd_blend_din_scope_v[i]);
                }
-#endif
        }
 
        dv_core2_vsize = (blend_reg->osd_blend_blend0_size >> 16) & 0xfff;
@@ -7358,25 +8122,18 @@ static void set_blend_reg(struct layer_blend_reg_s *blend_reg)
 static void uniformization_fb(u32 index,
        struct hw_osd_blending_s *blending)
 {
-       blending->dst_data.x = (osd_hw.dst_data[index].x << OSD_CALC) /
-               blending->screen_ratio_w;
-       blending->dst_data.y = (osd_hw.dst_data[index].y << OSD_CALC) /
-               blending->screen_ratio_h;
-       blending->dst_data.w = (osd_hw.dst_data[index].w << OSD_CALC) /
-               blending->screen_ratio_w;
-       blending->dst_data.h = (osd_hw.dst_data[index].h << OSD_CALC) /
-               blending->screen_ratio_h;
-       if (osd_hw.dst_data[index].w < osd_hw.disp_info.position_w)
-               osd_log_err("base dispframe w(%d) must >= position_w(%d)\n",
-               osd_hw.dst_data[index].w, osd_hw.disp_info.position_w);
-       if ((blending->dst_data.w + blending->dst_data.x) >
-               osd_hw.disp_info.background_w) {
-               blending->dst_data.w = osd_hw.disp_info.background_w
-                       - blending->dst_data.x;
-               osd_log_info("blending w(%d) must < base fb w(%d)\n",
-                       blending->dst_data.w + blending->dst_data.x,
-                       osd_hw.disp_info.background_w);
-       }
+       blending->dst_data.x = osd_hw.dst_data[index].x *
+               blending->screen_ratio_w_den /
+               blending->screen_ratio_w_num;
+       blending->dst_data.y = osd_hw.dst_data[index].y *
+               blending->screen_ratio_h_den /
+               blending->screen_ratio_h_num;
+       blending->dst_data.w = osd_hw.dst_data[index].w *
+               blending->screen_ratio_w_den /
+               blending->screen_ratio_w_num;
+       blending->dst_data.h = osd_hw.dst_data[index].h *
+               blending->screen_ratio_h_den /
+               blending->screen_ratio_h_num;
        osd_log_dbg2(MODULE_BLEND,
                "uniformization:osd%d:dst_data:%d,%d,%d,%d\n",
                index,
@@ -7386,17 +8143,29 @@ static void uniformization_fb(u32 index,
                blending->dst_data.h);
 }
 
-static void adjust_dst_position(void)
+static void adjust_dst_position(u32 output_index)
 {
        int i = 0;
-       int osd_count = osd_hw.osd_meson_dev.viu1_osd_count;
+       int osd_count = 0;
+       int start_index = 0;
+
+       if (output_index == VIU1) {
+               osd_count = osd_hw.osd_meson_dev.viu1_osd_count;
+               start_index = 0;
+       } else if (output_index == VIU2) {
+               start_index = osd_hw.osd_meson_dev.viu2_index;
+               osd_count = start_index + 1;
+       } else {
+               osd_log_err("invald output_index=%d\n", output_index);
+               return;
+       }
 
        for (i = 0; i < osd_count; i++) {
                if (osd_hw.enable[i]) {
                        osd_hw.dst_data[i].x -=
-                               osd_hw.disp_info.position_x;
+                               osd_hw.disp_info[output_index].position_x;
                        osd_hw.dst_data[i].y -=
-                               osd_hw.disp_info.position_y;
+                               osd_hw.disp_info[output_index].position_y;
                        if (osd_hw.dst_data[i].x < 0)
                                osd_hw.dst_data[i].x = 0;
                        if (osd_hw.dst_data[i].y < 0)
@@ -7410,12 +8179,13 @@ static void adjust_dst_position(void)
                                osd_hw.dst_data[i].h);
                }
        }
-       if (osd_hw.field_out_en)
-               osd_hw.disp_info.position_y /= 2;
+       if (osd_hw.field_out_en[output_index])
+               osd_hw.disp_info[output_index].position_y /= 2;
 }
 
-static int osd_setting_order(void)
+static int osd_setting_order(u32 output_index)
 {
+#define RDMA_DETECT_REG VIU_OSD2_TCOLOR_AG2
        int i;
        struct layer_blend_reg_s *blend_reg;
        struct hw_osd_blending_s *blending;
@@ -7424,18 +8194,21 @@ static int osd_setting_order(void)
        int line1;
        int line2;
        int vinfo_height;
+       u32 val;
 
        blending = &osd_blending;
        blend_reg = &(blending->blend_reg);
 
-       blending->vinfo_width = osd_hw.vinfo_width;
-       blending->vinfo_height = osd_hw.vinfo_height;
-       blending->screen_ratio_w =
-               (osd_hw.disp_info.position_w << OSD_CALC)
-               / osd_hw.disp_info.background_w;
-       blending->screen_ratio_h =
-               (osd_hw.disp_info.position_h << OSD_CALC)
-               / osd_hw.disp_info.background_h;
+       blending->vinfo_width = osd_hw.vinfo_width[output_index];
+       blending->vinfo_height = osd_hw.vinfo_height[output_index];
+       blending->screen_ratio_w_num =
+               osd_hw.disp_info[output_index].position_w;
+       blending->screen_ratio_w_den =
+               osd_hw.disp_info[output_index].background_w;
+       blending->screen_ratio_h_num =
+               osd_hw.disp_info[output_index].position_h;
+       blending->screen_ratio_h_den =
+               osd_hw.disp_info[output_index].background_h;
        blending->layer_cnt = get_available_layers();
        set_blend_order(blending);
 
@@ -7445,8 +8218,9 @@ static int osd_setting_order(void)
        blending->b_exchange_din = false;
        blending->b_exchange_blend_in = false;
        blending->osd1_freescale_disable = false;
-       adjust_dst_position();
-       uniformization_fb(OSD1, blending);
+       adjust_dst_position(output_index);
+       if (!osd_hw.osd_meson_dev.osd0_sc_independ)
+               uniformization_fb(OSD1, blending);
 
        /* set blend mode */
        set_blend_mode(blending);
@@ -7455,14 +8229,19 @@ static int osd_setting_order(void)
        set_blend_din(blending);
 
        /* set blend path */
-       set_blend_path(blending);
+       if (osd_hw.osd_meson_dev.osd0_sc_independ)
+               set_blend_path_new(blending);
+       else
+               set_blend_path(blending);
        line1 = get_enter_encp_line();
-       vinfo_height = osd_hw.field_out_en ?
-               (osd_hw.vinfo_height * 2) : osd_hw.vinfo_height;
-       if (line1 >= vinfo_height) {
+       vinfo_height = osd_hw.field_out_en[output_index] ?
+               (osd_hw.vinfo_height[output_index] * 2) :
+               osd_hw.vinfo_height[output_index];
+       /* if nearly vsync signal, wait vsync here */
+       if (line1 >= vinfo_height * line_threshold / 100) {
                osd_log_dbg(MODULE_RENDER,
-                       "enter osd_setting_order:cnt=%d,encp line=%d\n",
-                       cnt, line1);
+                       "enter osd_setting_order:encp line=%d\n",
+                       line1);
                osd_wait_vsync_hw();
                line1 = get_enter_encp_line();
        }
@@ -7533,14 +8312,21 @@ static int osd_setting_order(void)
 
        set_blend_reg(blend_reg);
        save_blend_reg(blend_reg);
+       /* append RDMA_DETECT_REG at last and detect if rdma missed some regs */
+       rdma_dt_cnt++;
+       VSYNCOSD_WR_MPEG_REG(RDMA_DETECT_REG, rdma_dt_cnt);
        spin_unlock_irqrestore(&osd_lock, lock_flags);
        line2 = get_exit_encp_line();
        osd_log_dbg2(MODULE_RENDER,
-               "enter osd_setting_order:cnt=%d,encp line=%d\n",
-               cnt, line2);
-       if (line2 < line1)
-               osd_log_info("osd line %d,%d\n", line1, line2);
+               "enter osd_setting_order:encp line=%d\n",
+               line2);
        osd_wait_vsync_hw();
+       val = osd_reg_read(RDMA_DETECT_REG);
+       /* if missed, need wait vsync */
+       if (/*(line2 < line1) || */(val != rdma_dt_cnt)) {
+               osd_wait_vsync_hw();
+               osd_log_dbg(MODULE_RENDER, "osd line %d,%d\n", line1, line2);
+       }
        return 0;
 }
 
@@ -7606,8 +8392,8 @@ static void osd_setting_default_hwc(void)
                0x0  << 11 |
                0x0);
 
-       blend_hsize = osd_hw.disp_info.background_w;
-       blend_vsize = osd_hw.disp_info.background_h;
+       blend_hsize = osd_hw.disp_info[VIU1].background_w;
+       blend_vsize = osd_hw.disp_info[VIU1].background_h;
 
        VSYNCOSD_WR_MPEG_REG(VIU_OSD_BLEND_BLEND0_SIZE,
                blend_vsize  << 16 |
@@ -7615,6 +8401,10 @@ static void osd_setting_default_hwc(void)
        VSYNCOSD_WR_MPEG_REG(VIU_OSD_BLEND_BLEND1_SIZE,
                blend_vsize  << 16 |
                blend_hsize);
+       /* hdr input size should set to osd blend0 output size */
+       VSYNCOSD_WR_MPEG_REG(VPP_OSD1_IN_SIZE,
+               blend_vsize  << 16 |
+               blend_hsize);
        VSYNCOSD_WR_MPEG_REG_BITS(DOLBY_PATH_CTRL,
                0x3, 2, 2);
 }
@@ -7624,29 +8414,29 @@ static bool set_old_hwc_freescale(u32 index)
        u32 x_start, x_end, y_start, y_end, height_dst, height_src;
 
        if (osd_hw.osd_reverse[index] == REVERSE_TRUE) {
-               x_start = osd_hw.vinfo_width
+               x_start = osd_hw.vinfo_width[VIU1]
                        - osd_hw.free_dst_data[index].x_end - 1;
-               y_start = osd_hw.vinfo_height
+               y_start = osd_hw.vinfo_height[VIU1]
                        - osd_hw.free_dst_data[index].y_end - 1;
-               x_end = osd_hw.vinfo_width
+               x_end = osd_hw.vinfo_width[VIU1]
                        - osd_hw.free_dst_data[index].x_start - 1;
-               y_end = osd_hw.vinfo_height
+               y_end = osd_hw.vinfo_height[VIU1]
                        - osd_hw.free_dst_data[index].y_start - 1;
                osd_hw.free_dst_data[index].x_start = x_start;
                osd_hw.free_dst_data[index].y_start = y_start;
                osd_hw.free_dst_data[index].x_end = x_end;
                osd_hw.free_dst_data[index].y_end = y_end;
        } else if (osd_hw.osd_reverse[index] == REVERSE_X) {
-               x_start = osd_hw.vinfo_width
+               x_start = osd_hw.vinfo_width[VIU1]
                        - osd_hw.free_dst_data[index].x_end - 1;
-               x_end = osd_hw.vinfo_width
+               x_end = osd_hw.vinfo_width[VIU1]
                        - osd_hw.free_dst_data[index].x_start - 1;
                osd_hw.free_dst_data[index].x_start = x_start;
                osd_hw.free_dst_data[index].x_end = x_end;
        } else if (osd_hw.osd_reverse[index] == REVERSE_Y) {
-               y_start = osd_hw.vinfo_height
+               y_start = osd_hw.vinfo_height[VIU1]
                        - osd_hw.free_dst_data[index].y_end - 1;
-               y_end = osd_hw.vinfo_height
+               y_end = osd_hw.vinfo_height[VIU1]
                        - osd_hw.free_dst_data[index].y_start - 1;
                osd_hw.free_dst_data[index].y_start = y_start;
                osd_hw.free_dst_data[index].y_end = y_end;
@@ -7678,101 +8468,6 @@ static bool set_old_hwc_freescale(u32 index)
                return false;
 }
 
-#if 0
-static bool set_old_hwc_freescale(u32 index)
-{
-       u32 x_start, x_end, y_start, y_end;
-       u32 width_src = 0, width_dst = 0, height_src = 0, height_dst = 0;
-       u32 width, height;
-       u32 screen_ratio_w, screen_ratio_h;
-
-       width_src = osd_hw.disp_info.background_w;
-       height_src = osd_hw.disp_info.background_h;
-
-       width_dst = osd_hw.vinfo_width;
-       height_dst = osd_hw.vinfo_height;
-       screen_ratio_w = (osd_hw.disp_info.position_w << OSD_CALC)
-               / osd_hw.disp_info.background_w;
-       screen_ratio_h = (osd_hw.disp_info.position_h << OSD_CALC)
-               / osd_hw.disp_info.background_h;
-       osd_log_dbg("width_src:%d,%d\n",
-               width_src, height_src);
-       osd_log_dbg("width_src:%d,%d\n",
-               width_dst, height_dst);
-
-       width = osd_hw.free_dst_data[index].x_end -
-               osd_hw.free_dst_data[index].x_start;
-       height = osd_hw.free_dst_data[index].y_end -
-               osd_hw.free_dst_data[index].y_start;
-       osd_hw.free_dst_data[index].x_start =
-               (osd_hw.free_dst_data[index].x_start
-               * screen_ratio_w >> OSD_CALC);
-       osd_hw.free_dst_data[index].y_start =
-               (osd_hw.free_dst_data[index].y_start
-               * screen_ratio_h >> OSD_CALC);
-       width = (width * screen_ratio_w >> OSD_CALC);
-       height = (height * screen_ratio_h >> OSD_CALC);
-
-       osd_hw.free_dst_data[index].x_start +=
-               osd_hw.disp_info.position_x;
-       osd_hw.free_dst_data[index].x_end =
-               osd_hw.free_dst_data[index].x_start + width;
-       osd_hw.free_dst_data[index].y_start +=
-               osd_hw.disp_info.position_y;
-       osd_hw.free_dst_data[index].y_end =
-               osd_hw.free_dst_data[index].y_start + height;
-
-       if (osd_hw.osd_reverse[index] == REVERSE_TRUE) {
-               x_start = osd_hw.vinfo_width
-                       - osd_hw.free_dst_data[index].x_end - 1;
-               y_start = osd_hw.vinfo_height
-                       - osd_hw.free_dst_data[index].y_end - 1;
-               x_end = osd_hw.vinfo_width
-                       - osd_hw.free_dst_data[index].x_start - 1;
-               y_end = osd_hw.vinfo_height
-                       - osd_hw.free_dst_data[index].y_start - 1;
-               osd_hw.free_dst_data[index].x_start = x_start;
-               osd_hw.free_dst_data[index].y_start = y_start;
-               osd_hw.free_dst_data[index].x_end = x_end;
-               osd_hw.free_dst_data[index].y_end = y_end;
-       } else if (osd_hw.osd_reverse[index] == REVERSE_X) {
-               x_start = osd_hw.vinfo_width
-                       - osd_hw.free_dst_data[index].x_end - 1;
-               x_end = osd_hw.vinfo_width
-                       - osd_hw.free_dst_data[index].x_start - 1;
-               osd_hw.free_dst_data[index].x_start = x_start;
-               osd_hw.free_dst_data[index].x_end = x_end;
-       } else if (osd_hw.osd_reverse[index] == REVERSE_Y) {
-               y_start = osd_hw.vinfo_height
-                       - osd_hw.free_dst_data[index].y_end - 1;
-               y_end = osd_hw.vinfo_height
-                       - osd_hw.free_dst_data[index].y_start - 1;
-               osd_hw.free_dst_data[index].y_start = y_start;
-               osd_hw.free_dst_data[index].y_end = y_end;
-       }
-       osd_log_dbg("free_dst_data: %x,%x,%x,%x\n",
-               osd_hw.free_dst_data[index].x_start,
-               osd_hw.free_dst_data[index].x_end,
-               osd_hw.free_dst_data[index].y_start,
-               osd_hw.free_dst_data[index].y_end);
-       if ((memcmp(&(osd_hw.free_src_data[index]),
-               &osd_hw.free_src_data_backup[index],
-               sizeof(struct pandata_s)) != 0) ||
-               (memcmp(&(osd_hw.free_dst_data[index]),
-               &osd_hw.free_dst_data_backup[index],
-               sizeof(struct pandata_s)) != 0)) {
-               memcpy(&osd_hw.free_src_data_backup[index],
-                       &osd_hw.free_src_data[index],
-                       sizeof(struct pandata_s));
-               memcpy(&osd_hw.free_dst_data_backup[index],
-                       &osd_hw.free_dst_data[index],
-                       sizeof(struct pandata_s));
-               return true;
-       } else
-               return false;
-}
-#endif
-
 static void osd_setting_old_hwc(void)
 {
        int index = OSD1;
@@ -7817,7 +8512,7 @@ static void osd_setting_old_hwc(void)
 
 static void osd_setting_viu2(void)
 {
-       int index = OSD4;
+       int index = osd_hw.osd_meson_dev.viu2_index;
 
        if (!osd_hw.osd_afbcd[index].enable)
                canvas_config(osd_hw.fb_gem[index].canvas_idx,
@@ -7833,25 +8528,28 @@ static void osd_setting_viu2(void)
        if (!osd_hw.osd_display_debug)
                osd_hw.reg[OSD_ENABLE]
                .update_func(index);
+       osd_wait_vsync_hw();
 }
 
 
-int osd_setting_blend(void)
+int osd_setting_blend(u32 output_index)
 {
        int ret;
 
        if (osd_hw.osd_meson_dev.osd_ver < OSD_HIGH_ONE)
                osd_setting_old_hwc();
        else {
-               if (osd_hw.hwc_enable) {
-                       if (osd_hw.viu_type == VIU1) {
-                               ret = osd_setting_order();
+               if (osd_hw.hwc_enable[output_index]) {
+                       if (output_index == VIU1) {
+                               ret = osd_setting_order(output_index);
                                if (ret < 0)
                                        return -1;
-                       } else if (osd_hw.viu_type == VIU2)
+                       } else if (output_index == VIU2) {
                                osd_setting_viu2();
-               } else
+                       }
+               } else {
                        osd_setting_default_hwc();
+               }
        }
        return 0;
 }
@@ -8275,7 +8973,10 @@ static void osd_update_fifo(u32 index)
 {
        u32 data32;
 
-       data32 = osd_hw.urgent[index] & 1;
+       data32 = VSYNCOSD_RD_MPEG_REG(
+               hw_osd_reg_array[index].osd_fifo_ctrl_stat);
+       data32 |= osd_hw.urgent[index] & 1;
+       #if 0
        data32 |= 4 << 5; /* hold_fifo_lines */
 
        /* burst_len_sel: 3=64, g12a = 5 */
@@ -8298,6 +8999,7 @@ static void osd_update_fifo(u32 index)
        data32 |= 2 << 22;
        /* bit 28:24, fifo_lim */
        data32 |= 2 << 24;
+       #endif
        VSYNCOSD_WR_MPEG_REG(
                hw_osd_reg_array[index].osd_fifo_ctrl_stat, data32);
        remove_from_update_list(index, OSD_FIFO);
@@ -8364,6 +9066,17 @@ void osd_init_hw(u32 logo_loaded, u32 osd_probe,
                sizeof(struct osd_device_data_s));
 
        osd_vpu_power_on();
+       if (osd_meson->cpu_id == __MESON_CPU_MAJOR_ID_TL1) {
+               /* VIU1 2 OSD + 1 VIU2 1 OSD*/
+               memcpy(&hw_osd_reg_array[0], &hw_osd_reg_array_tl1[0],
+                       sizeof(struct hw_osd_reg_s) *
+                       osd_hw.osd_meson_dev.osd_count);
+       } else {
+               /* VIU1 3 OSD + 1 VIU2 1 OSD or VIU1 2 OSD*/
+               memcpy(&hw_osd_reg_array[0], &hw_osd_reg_array_g12a[0],
+                       sizeof(struct hw_osd_reg_s) *
+                       osd_hw.osd_meson_dev.osd_count);
+       }
        if (osd_meson->cpu_id == __MESON_CPU_MAJOR_ID_GXTVBB)
                backup_regs_init(HW_RESET_AFBCD_REGS);
        else if (osd_meson->cpu_id == __MESON_CPU_MAJOR_ID_GXM)
@@ -8385,7 +9098,8 @@ void osd_init_hw(u32 logo_loaded, u32 osd_probe,
        osd_hdr_on = false;
 #endif
        osd_hw.hw_reset_flag = HW_RESET_NONE;
-       osd_hw.hwc_enable = 0;
+       osd_hw.hwc_enable[VIU1] = 0;
+       osd_hw.hwc_enable[VIU2] = 0;
        if (osd_hw.osd_meson_dev.osd_ver <= OSD_NORMAL) {
                osd_hw.hw_cursor_en = 1;
                if (osd_hw.osd_meson_dev.has_rdma)
@@ -8402,7 +9116,7 @@ void osd_init_hw(u32 logo_loaded, u32 osd_probe,
                /* init vpu fifo control register */
                data32 = osd_reg_read(VPP_OFIFO_SIZE);
                if (osd_hw.osd_meson_dev.osd_ver >= OSD_HIGH_ONE) {
-                       data32 = 0; /* reset value 0xfff0fff */
+                       data32 &= ~((0xfff << 20) | 0x3fff);
                        data32 |= (osd_hw.osd_meson_dev.vpp_fifo_len) << 20;
                        data32 |= osd_hw.osd_meson_dev.vpp_fifo_len + 1;
                } else
@@ -8480,18 +9194,18 @@ void osd_init_hw(u32 logo_loaded, u32 osd_probe,
                osd_hw.order[OSD1] = LAYER_1;
                osd_hw.order[OSD2] = LAYER_2;
                osd_hw.order[OSD3] = LAYER_3;
-               //osd_hw.osd_blend_mode = OSD_BLEND_NONE;
-               osd_hw.disp_info.background_w = 1920;
-               osd_hw.disp_info.background_h = 1080;
-               osd_hw.disp_info.fullscreen_w = 1920;
-               osd_hw.disp_info.fullscreen_h = 1080;
-               osd_hw.disp_info.position_x = 0;
-               osd_hw.disp_info.position_y = 0;
-               osd_hw.disp_info.position_w = 1920;
-               osd_hw.disp_info.position_h = 1080;
-               osd_hw.vinfo_width = 1920;
-               osd_hw.vinfo_height = 1080;
-               osd_hw.workaround_line = 0;
+               for (idx = 0; idx < VIU_COUNT; idx++) {
+                       osd_hw.disp_info[idx].background_w = 1920;
+                       osd_hw.disp_info[idx].background_h = 1080;
+                       osd_hw.disp_info[idx].fullscreen_w = 1920;
+                       osd_hw.disp_info[idx].fullscreen_h = 1080;
+                       osd_hw.disp_info[idx].position_x = 0;
+                       osd_hw.disp_info[idx].position_y = 0;
+                       osd_hw.disp_info[idx].position_w = 1920;
+                       osd_hw.disp_info[idx].background_h = 1080;
+                       osd_hw.vinfo_width[idx] = 1920;
+                       osd_hw.vinfo_height[idx] = 1080;
+               }
                if ((osd_hw.osd_meson_dev.cpu_id ==
                        __MESON_CPU_MAJOR_ID_G12A) ||
                        ((osd_hw.osd_meson_dev.cpu_id ==
@@ -8513,7 +9227,7 @@ void osd_init_hw(u32 logo_loaded, u32 osd_probe,
                                osd_hw.afbc_regs_backup = 1;
                        } else {
                                osd_hw.afbc_force_reset = 1;
-                               osd_hw.afbc_regs_backup = 0;
+                               osd_hw.afbc_regs_backup = 1;
                                data32 = osd_reg_read(MALI_AFBCD_TOP_CTRL);
                                osd_reg_write(MALI_AFBCD_TOP_CTRL,
                                        data32 | 0x800000);
@@ -8529,13 +9243,11 @@ void osd_init_hw(u32 logo_loaded, u32 osd_probe,
                                osd_reg_set_bits(
                                hw_osd_reg_array[idx].osd_fifo_ctrl_stat,
                                1, 10, 2);
-                               /* TODO: temp set at here,
-                                * need check for logo
-                                */
-                               if (idx > 0)
-                                       osd_reg_set_bits(
-                                       hw_osd_reg_array[idx].osd_ctrl_stat,
-                                       0, 0, 1);
+                               if (osd_hw.osd_meson_dev.cpu_id ==
+                                       __MESON_CPU_MAJOR_ID_G12B)
+                                       osd_reg_set_bits
+                                       (hw_osd_reg_array[idx].osd_ctrl_stat,
+                                       1, 0, 1);
                                osd_reg_set_bits(
                                hw_osd_reg_array[idx].osd_ctrl_stat,
                                0, 31, 1);
@@ -8619,26 +9331,39 @@ void osd_init_hw(u32 logo_loaded, u32 osd_probe,
        }
        /* hwc_enable == 0 handler */
 #ifdef CONFIG_AMLOGIC_MEDIA_FB_OSD_SYNC_FENCE
-       osd_hw.osd_fence[DISABLE].sync_fence_handler =
+       osd_hw.osd_fence[VIU1][DISABLE].sync_fence_handler =
                sync_render_single_fence;
-       osd_hw.osd_fence[DISABLE].toggle_buffer_handler =
+       osd_hw.osd_fence[VIU1][DISABLE].toggle_buffer_handler =
                osd_toggle_buffer_single;
        /* hwc_enable == 1 handler */
-       osd_hw.osd_fence[ENABLE].sync_fence_handler =
+       osd_hw.osd_fence[VIU1][ENABLE].sync_fence_handler =
                sync_render_layers_fence;
-       osd_hw.osd_fence[ENABLE].toggle_buffer_handler =
+       osd_hw.osd_fence[VIU1][ENABLE].toggle_buffer_handler =
                osd_toggle_buffer_layers;
+       if (osd_hw.osd_meson_dev.has_viu2) {
+               osd_hw.osd_fence[VIU2][DISABLE].sync_fence_handler =
+                       sync_render_single_fence;
+               osd_hw.osd_fence[VIU2][DISABLE].toggle_buffer_handler =
+                       osd_toggle_buffer_single_viu2;
+               /* hwc_enable == 1 handler */
+               osd_hw.osd_fence[VIU2][ENABLE].sync_fence_handler =
+                       sync_render_layers_fence;
+               osd_hw.osd_fence[VIU2][ENABLE].toggle_buffer_handler =
+                       osd_toggle_buffer_layers_viu2;
+       }
 #endif
        osd_hw.fb_gem[OSD1].canvas_idx = OSD1_CANVAS_INDEX;
        osd_hw.fb_gem[OSD2].canvas_idx = OSD2_CANVAS_INDEX;
        if (osd_hw.osd_meson_dev.osd_ver == OSD_HIGH_ONE) {
                osd_hw.fb_gem[OSD3].canvas_idx = OSD3_CANVAS_INDEX;
+               if (osd_hw.osd_meson_dev.osd_count == 4)
                osd_hw.fb_gem[OSD4].canvas_idx = OSD4_CANVAS_INDEX;
        }
        osd_extra_canvas_alloc();
        osd_hw.antiflicker_mode = 0;
        osd_hw.osd_deband_enable = 1;
-       osd_hw.out_fence_fd = -1;
+       osd_hw.out_fence_fd[VIU1] = -1;
+       osd_hw.out_fence_fd[VIU2] = -1;
        osd_hw.blend_bypass = 0;
        osd_hw.afbc_err_cnt = 0;
        if (osd_hw.osd_meson_dev.osd_ver == OSD_SIMPLE) {
@@ -8653,8 +9378,10 @@ void osd_init_hw(u32 logo_loaded, u32 osd_probe,
        osd_set_deband(osd_hw.osd_deband_enable);
        if (osd_hw.fb_drvier_probe) {
 #ifdef CONFIG_AMLOGIC_MEDIA_FB_OSD_SYNC_FENCE
-               INIT_LIST_HEAD(&post_fence_list);
-               mutex_init(&post_fence_list_lock);
+               INIT_LIST_HEAD(&post_fence_list[VIU1]);
+               mutex_init(&post_fence_list_lock[VIU1]);
+               INIT_LIST_HEAD(&post_fence_list[VIU2]);
+               mutex_init(&post_fence_list_lock[VIU2]);
 #endif
 #ifdef FIQ_VSYNC
                osd_hw.fiq_handle_item.handle = vsync_isr;
@@ -8690,6 +9417,7 @@ void osd_init_hw(u32 logo_loaded, u32 osd_probe,
 void osd_init_viu2(void)
 {
        u32 idx, data32;
+       struct vinfo_s *vinfo;
 
        set_viu2_rgb2yuv(1);
 
@@ -8702,7 +9430,11 @@ void osd_init_viu2(void)
         * set DDR request priority to be urgent
         */
        data32 = 1;
-       data32 |= 4 << 5;  /* hold_fifo_lines */
+       vinfo = get_current_vinfo2();
+       if (vinfo && (!strcmp(vinfo->name, "dummy_panel"))) {
+               data32 |= MAX_HOLD_LINE << 5;  /* hold_fifo_lines */
+       } else
+               data32 |= DEFAULT_HOLD_LINE << 5;  /* hold_fifo_lines */
        /* burst_len_sel: 3=64, g12a = 5 */
        if (osd_hw.osd_meson_dev.osd_ver == OSD_HIGH_ONE) {
                data32 |= 1 << 10;
@@ -8934,7 +9666,7 @@ void osd_cursor_hw_no_scale(u32 index, s16 x, s16 y, s16 xstart, s16 ystart,
                memcpy(&disp_tmp, &osd_hw.dispdata[OSD1],
                                sizeof(struct pandata_s));
 
-       if (osd_hw.field_out_en) {
+       if (osd_hw.field_out_en[VIU1]) {
                disp_tmp.y_start *= 2;
                disp_tmp.y_end *= 2;
        }
@@ -9040,7 +9772,7 @@ void osd_cursor_hw_no_scale(u32 index, s16 x, s16 y, s16 xstart, s16 ystart,
                }
        }
 
-       if (osd_hw.field_out_en)
+       if (osd_hw.field_out_en[VIU1])
                osd_hw.dispdata[OSD2].y_start /= 2;
 
        osd_hw.dispdata[OSD2].x_end = osd_hw.dispdata[OSD2].x_start +
@@ -9519,6 +10251,7 @@ static const struct color_bit_define_s *convert_panel_format(u32 format)
 {
        const struct color_bit_define_s *color = NULL;
 
+       format &= ~AFBC_EN;
        switch (format) {
        case COLOR_INDEX_02_PAL4:
        case COLOR_INDEX_04_PAL16:
@@ -9560,19 +10293,27 @@ static bool osd_direct_render(struct osd_plane_map_s *plane_map)
        u32 x_start, x_end, y_start, y_end;
        bool freescale_update = false;
        struct pandata_s freescale_dst[HW_OSD_COUNT];
+       u32 output_index;
 
+       output_index = get_output_device_id(index);
        phy_addr = phy_addr + plane_map->byte_stride * plane_map->src_y;
        osd_hw.screen_base[index] = phy_addr;
        osd_hw.screen_size[index] =
                plane_map->byte_stride * plane_map->src_h;
        osd_log_dbg(MODULE_RENDER, "canvas_id=%x, phy_addr=%x\n",
                osd_hw.fb_gem[index].canvas_idx, phy_addr);
-       canvas_config(osd_hw.fb_gem[index].canvas_idx,
-               phy_addr,
-               plane_map->byte_stride,
-               plane_map->src_h,
-               CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR);
-       if (osd_hw.hwc_enable) {
+       if (osd_hw.osd_meson_dev.osd_ver == OSD_SIMPLE) {
+               osd_hw.fb_gem[index].addr = phy_addr;
+               osd_hw.fb_gem[index].width = plane_map->byte_stride;
+               osd_update_phy_addr(0);
+       } else {
+               canvas_config(osd_hw.fb_gem[index].canvas_idx,
+                       phy_addr,
+                       plane_map->byte_stride,
+                       plane_map->src_h,
+                       CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR);
+       }
+       if (osd_hw.hwc_enable[output_index]) {
                /* just get para, need update via do_hwc */
                osd_hw.order[index] = plane_map->zorder;
                switch (plane_map->blend_mode) {
@@ -9664,30 +10405,30 @@ static bool osd_direct_render(struct osd_plane_map_s *plane_map)
                        ((plane_map->dst_y + plane_map->dst_h) *
                        height_dst) / height_src - 1;
                if (osd_hw.osd_reverse[index] == REVERSE_TRUE) {
-                       x_start = osd_hw.vinfo_width
+                       x_start = osd_hw.vinfo_width[output_index]
                                - freescale_dst[index].x_end - 1;
-                       y_start = osd_hw.vinfo_height
+                       y_start = osd_hw.vinfo_height[output_index]
                                - freescale_dst[index].y_end - 1;
-                       x_end = osd_hw.vinfo_width
+                       x_end = osd_hw.vinfo_width[output_index]
                                - freescale_dst[index].x_start - 1;
-                       y_end = osd_hw.vinfo_height
+                       y_end = osd_hw.vinfo_height[output_index]
                                - freescale_dst[index].y_start - 1;
                        freescale_dst[index].x_start = x_start;
                        freescale_dst[index].y_start = y_start;
                        freescale_dst[index].x_end = x_end;
                        freescale_dst[index].y_end = y_end;
                } else if (osd_hw.osd_reverse[index] == REVERSE_X) {
-                       x_start = osd_hw.vinfo_width
+                       x_start = osd_hw.vinfo_width[output_index]
                                - freescale_dst[index].x_end - 1;
-                       x_end = osd_hw.vinfo_width
+                       x_end = osd_hw.vinfo_width[output_index]
                                - freescale_dst[index].x_start - 1;
                        freescale_dst[index].x_start = x_start;
                        freescale_dst[index].x_end = x_end;
 
                } else if (osd_hw.osd_reverse[index] == REVERSE_Y) {
-                       y_start = osd_hw.vinfo_height
+                       y_start = osd_hw.vinfo_height[output_index]
                                - freescale_dst[index].y_end - 1;
-                       y_end = osd_hw.vinfo_height
+                       y_end = osd_hw.vinfo_height[output_index]
                                - freescale_dst[index].y_start - 1;
                        freescale_dst[index].y_start = y_start;
                        freescale_dst[index].y_end = y_end;
@@ -9753,30 +10494,30 @@ static bool osd_direct_render(struct osd_plane_map_s *plane_map)
                osd_hw.dispdata[index].y_end =
                        plane_map->dst_y + plane_map->dst_h - 1;
                if (osd_hw.osd_reverse[index] == REVERSE_TRUE) {
-                       x_start = osd_hw.vinfo_width
+                       x_start = osd_hw.vinfo_width[output_index]
                                - osd_hw.dispdata[index].x_end - 1;
-                       y_start = osd_hw.vinfo_height
+                       y_start = osd_hw.vinfo_height[output_index]
                                - osd_hw.dispdata[index].y_end - 1;
-                       x_end = osd_hw.vinfo_width
+                       x_end = osd_hw.vinfo_width[output_index]
                                - osd_hw.dispdata[index].x_start - 1;
-                       y_end = osd_hw.vinfo_height
+                       y_end = osd_hw.vinfo_height[output_index]
                                - osd_hw.dispdata[index].y_start - 1;
                        osd_hw.dispdata[index].x_start = x_start;
                        osd_hw.dispdata[index].y_start = y_start;
                        osd_hw.dispdata[index].x_end = x_end;
                        osd_hw.dispdata[index].y_end = y_end;
                } else if (osd_hw.osd_reverse[index] == REVERSE_X) {
-                       x_start = osd_hw.vinfo_width
+                       x_start = osd_hw.vinfo_width[output_index]
                                - osd_hw.dispdata[index].x_end - 1;
-                       x_end = osd_hw.vinfo_width
+                       x_end = osd_hw.vinfo_width[output_index]
                                - osd_hw.dispdata[index].x_start - 1;
                        osd_hw.dispdata[index].x_start = x_start;
                        osd_hw.dispdata[index].x_end = x_end;
 
                } else if (osd_hw.osd_reverse[index] == REVERSE_Y) {
-                       y_start = osd_hw.vinfo_height
+                       y_start = osd_hw.vinfo_height[output_index]
                                - osd_hw.dispdata[index].y_end - 1;
-                       y_end = osd_hw.vinfo_height
+                       y_end = osd_hw.vinfo_height[output_index]
                                - osd_hw.dispdata[index].y_start - 1;
                        osd_hw.dispdata[index].y_start = y_start;
                        osd_hw.dispdata[index].y_end = y_end;
@@ -9804,9 +10545,11 @@ static void osd_cursor_move(struct osd_plane_map_s *plane_map)
        u32 x, y;
        struct pandata_s disp_tmp;
        struct pandata_s free_dst_data_backup;
+       u32 output_index;
 
        if (index != OSD2)
                return;
+       output_index = get_output_device_id(index);
        phy_addr = phy_addr + plane_map->byte_stride * plane_map->src_y;
        osd_hw.screen_base[index] = phy_addr;
        osd_hw.screen_size[index] =
@@ -9904,29 +10647,29 @@ static void osd_cursor_move(struct osd_plane_map_s *plane_map)
                osd_hw.pandata[OSD2].y_end - osd_hw.pandata[OSD2].y_start;
 
        if (osd_hw.osd_reverse[OSD2] == REVERSE_TRUE) {
-               x_start = osd_hw.vinfo_width
+               x_start = osd_hw.vinfo_width[output_index]
                        - osd_hw.dispdata[index].x_end - 1;
-               y_start = osd_hw.vinfo_height
+               y_start = osd_hw.vinfo_height[output_index]
                        - osd_hw.dispdata[index].y_end - 1;
-               x_end = osd_hw.vinfo_width
+               x_end = osd_hw.vinfo_width[output_index]
                        - osd_hw.dispdata[index].x_start - 1;
-               y_end = osd_hw.vinfo_height
+               y_end = osd_hw.vinfo_height[output_index]
                        - osd_hw.dispdata[index].y_start - 1;
                osd_hw.dispdata[index].x_start = x_start;
                osd_hw.dispdata[index].y_start = y_start;
                osd_hw.dispdata[index].x_end = x_end;
                osd_hw.dispdata[index].y_end = y_end;
        } else if (osd_hw.osd_reverse[OSD2] == REVERSE_X) {
-               x_start = osd_hw.vinfo_width
+               x_start = osd_hw.vinfo_width[output_index]
                        - osd_hw.dispdata[index].x_end - 1;
-               x_end = osd_hw.vinfo_width
+               x_end = osd_hw.vinfo_width[output_index]
                        - osd_hw.dispdata[index].x_start - 1;
                osd_hw.dispdata[index].x_start = x_start;
                osd_hw.dispdata[index].x_end = x_end;
                } else if (osd_hw.osd_reverse[OSD2] == REVERSE_Y) {
-               y_start = osd_hw.vinfo_height
+               y_start = osd_hw.vinfo_height[output_index]
                        - osd_hw.dispdata[index].y_end - 1;
-               y_end = osd_hw.vinfo_height
+               y_end = osd_hw.vinfo_height[output_index]
                        - osd_hw.dispdata[index].y_start - 1;
                osd_hw.dispdata[index].y_start = y_start;
                osd_hw.dispdata[index].y_end = y_end;
@@ -9964,9 +10707,11 @@ void osd_page_flip(struct osd_plane_map_s *plane_map)
        bool freescale_update = false;
        u32 osd_enable = 0;
        u32 format = 0;
-       const struct vinfo_s *vinfo;
+       const struct vinfo_s *vinfo = NULL;
+       u32 output_index;
 
-       if (!osd_hw.hwc_enable) {
+       output_index = get_output_device_id(index);
+       if (!osd_hw.hwc_enable[output_index]) {
                if (index >= OSD2)
                        return;
        } else {
@@ -9975,16 +10720,23 @@ void osd_page_flip(struct osd_plane_map_s *plane_map)
        }
 
        osd_hw.buffer_alloc[index] = 1;
-       if (osd_hw.osd_fps_start)
-               osd_hw.osd_fps++;
-
+       if (osd_hw.osd_fps_start[output_index])
+               osd_hw.osd_fps[output_index]++;
        osd_enable = (plane_map->enable & 1) ? ENABLE : DISABLE;
-       vinfo = get_current_vinfo();
-       if (vinfo && (strcmp(vinfo->name, "invalid") &&
-               strcmp(vinfo->name, "null"))) {
-               osd_hw.vinfo_width = vinfo->width;
-               osd_hw.vinfo_height = vinfo->height;
+
+       if (output_index == VIU1)
+               vinfo = get_current_vinfo();
+#ifdef CONFIG_AMLOGIC_VOUT2_SERVE
+       else if (output_index == VIU2)
+               vinfo = get_current_vinfo2();
+#endif
+       if (!vinfo || (!strcmp(vinfo->name, "invalid") ||
+                               !strcmp(vinfo->name, "null"))) {
+               return;
        }
+       osd_hw.vinfo_width[output_index] = vinfo->width;
+       osd_hw.vinfo_height[output_index] = vinfo->height;
+
        osd_hw.osd_afbcd[index].enable =
                (plane_map->afbc_inter_format & AFBC_EN) >> 31;
        if (osd_hw.osd_meson_dev.osd_ver <= OSD_NORMAL) {
@@ -10079,7 +10831,7 @@ void osd_page_flip(struct osd_plane_map_s *plane_map)
                                osd_hw.osd_afbcd[index].phy_addr =
                                        plane_map->phy_addr;
                        osd_hw.reg[OSD_COLOR_MODE].update_func(index);
-                       if (!osd_hw.hwc_enable) {
+                       if (!osd_hw.hwc_enable[output_index]) {
                                osd_hw.reg[DISP_GEOMETRY].update_func(index);
                                osd_hw.reg[DISP_OSD_REVERSE].update_func(index);
                                if ((osd_hw.free_scale_enable[index]
index ce8ec87..2e1217e 100644 (file)
@@ -23,6 +23,8 @@
 #include "osd_sync.h"
 #include "osd_drm.h"
 
+#define MAX_HOLD_LINE     0x1f
+#define DEFAULT_HOLD_LINE 0x04
 //#define REG_OFFSET (0x20)
 #define OSD_RELATIVE_BITS 0x33330
 #include "osd_rdma.h"
@@ -102,7 +104,7 @@ extern void osd_set_block_mode_hw(u32 index, u32 mode);
 extern void osd_enable_3d_mode_hw(u32 index, u32 enable);
 extern void osd_set_2x_scale_hw(u32 index, u16 h_scale_enable,
                                u16 v_scale_enable);
-extern void osd_get_flush_rate_hw(u32 *break_rate);
+extern void osd_get_flush_rate_hw(u32 index, u32 *break_rate);
 extern void osd_set_reverse_hw(u32 index, u32 reverse, u32 update);
 extern void osd_get_reverse_hw(u32 index, u32 *reverse);
 extern void osd_set_antiflicker_hw(u32 index, struct vinfo_s *vinfo, u32 yres);
@@ -126,7 +128,7 @@ extern int osd_sync_request_render(u32 index, u32 yres,
        struct sync_req_render_s *request,
        u32 phys_addr,
        size_t len);
-extern int osd_sync_do_hwc(struct do_hwc_cmd_s *hwc_cmd);
+int osd_sync_do_hwc(u32 output_index, struct do_hwc_cmd_s *hwc_cmd);
 extern s64  osd_wait_vsync_event(void);
 extern void osd_cursor_hw(u32 index, s16 x, s16 y, s16 xstart, s16 ystart,
                          u32 osd_w, u32 osd_h);
@@ -165,8 +167,8 @@ extern void osd_get_urgent(u32 index, u32 *urgent);
 extern void osd_set_urgent(u32 index, u32 urgent);
 void osd_get_deband(u32 *osd_deband_enable);
 void osd_set_deband(u32 osd_deband_enable);
-void osd_get_fps(u32 *osd_fps);
-void osd_set_fps(u32 osd_fps_start);
+void osd_get_fps(u32 index, u32 *osd_fps);
+void osd_set_fps(u32 index, u32 osd_fps_start);
 extern void osd_get_info(u32 index, u32 *addr, u32 *width, u32 *height);
 void osd_update_scan_mode(void);
 void osd_update_3d_mode(void);
@@ -180,15 +182,15 @@ int set_osd_logo_freescaler(void);
 int is_interlaced(struct vinfo_s *vinfo);
 void osd_get_display_debug(u32 *osd_display_debug_enable);
 void osd_set_display_debug(u32 osd_display_debug_enable);
-void osd_get_background_size(struct display_flip_info_s *disp_info);
-void osd_set_background_size(struct display_flip_info_s *disp_info);
+void osd_get_background_size(u32 index, struct display_flip_info_s *disp_info);
+void osd_set_background_size(u32 index, struct display_flip_info_s *disp_info);
 void osd_get_hdr_used(u32 *val);
 void osd_set_hdr_used(u32 val);
 void osd_get_afbc_format(u32 index, u32 *format, u32 *inter_format);
 void osd_set_afbc_format(u32 index, u32 format, u32 inter_format);
-void osd_get_hwc_enable(u32 *hwc_enable);
-void osd_set_hwc_enable(u32 hwc_enable);
-void osd_do_hwc(void);
+void osd_get_hwc_enable(u32 index, u32 *hwc_enable);
+void osd_set_hwc_enable(u32 index, u32 hwc_enable);
+void osd_do_hwc(u32 index);
 int osd_get_capbility(u32 index);
 void osd_backup_screen_info(
        u32 index,
@@ -204,12 +206,12 @@ ssize_t dd_vmap_write(u32 index, const char __user *buf,
 int osd_set_clear(u32 index);
 void osd_page_flip(struct osd_plane_map_s *plane_map);
 void walk_through_update_list(void);
-int osd_setting_blend(void);
-void osd_set_hwc_enable(u32 hwc_enable);
+int osd_setting_blend(u32 output_index);
+void osd_set_hwc_enable(u32 index, u32 hwc_enable);
 void osd_set_urgent_info(u32 ports, u32 basic_urgent);
 void osd_get_urgent_info(u32 *ports, u32 *basic_urgent);
-void osd_set_single_step_mode(u32 osd_single_step_mode);
-void osd_set_single_step(u32 osd_single_step);
+void osd_set_single_step_mode(u32 index, u32 osd_single_step_mode);
+void osd_set_single_step(u32 index, u32 osd_single_step);
 void output_save_info(void);
 void osd_get_rotate(u32 index, u32 *osd_rotate);
 void osd_set_rotate(u32 index, u32 osd_rotate);
@@ -218,4 +220,6 @@ void osd_get_dimm_info(u32 index, u32 *osd_dimm_layer, u32 *osd_dimm_color);
 void osd_set_dimm_info(u32 index, u32 osd_dimm_layer, u32 osd_dimm_color);
 u32 osd_get_line_n_rdma(void);
 void  osd_set_line_n_rdma(u32 line_n_rdma);
+u32 get_output_device_id(u32 index);
+void osd_set_hold_line(int hold_line);
 #endif
index 8821d24..eee86b8 100644 (file)
 #define VPP_OSD_SCALE_COEF_IDX 0x1dcc
 #define VPP_OSD_SCALE_COEF 0x1dcd
 #define VPP_INT_LINE_NUM 0x1dce
-
+#define VPP_OSD_SCALE_CTRL 0x1dff
 /* osd2 scaler */
 #define OSD2_VSC_PHASE_STEP 0x3d00
 #define OSD2_VSC_INI_PHASE 0x3d01