osd: add osd support hwc interface
authorpengcheng chen <pengcheng.chen@amlogic.com>
Mon, 26 Feb 2018 06:39:34 +0000 (14:39 +0800)
committerYixun Lan <yixun.lan@amlogic.com>
Fri, 27 Apr 2018 08:52:57 +0000 (01:52 -0700)
PD#163270: osd: add osd support hwc interface

Change-Id: I17854518b63b0ecb6c13a4550364b6ede02fdb8d
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.h
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
drivers/amlogic/media/osd/osd_sync.h

index bad8b45..e9d7049 100644 (file)
@@ -17,7 +17,8 @@
 
 #ifndef _OSD_H_
 #define _OSD_H_
-
+#include <linux/kthread.h>
+#include "osd_sync.h"
 enum color_index_e {
        COLOR_INDEX_02_PAL4    = 2,  /* 0 */
        COLOR_INDEX_04_PAL16   = 4, /* 0 */
@@ -96,6 +97,8 @@ enum color_index_e {
 #define FBIOPUT_OSD_SYNC_RENDER_ADD      0x4519
 #define FBIOPUT_OSD_HWC_ENABLE           0x451a
 #define FBIOPUT_OSD_DO_HWC               0x451b
+#define FBIOPUT_OSD_BLANK                0x451c
+#define FBIOGET_OSD_CAPBILITY            0x451e
 
 #define FB_IOC_MAGIC   'O'
 #define FBIOPUT_OSD_CURSOR     \
@@ -142,12 +145,21 @@ enum color_index_e {
 
 #define MALI_AFBC_SPLIT_OFF  0
 #define MALI_AFBC_SPLIT_ON   1
+#define OSD_HW_CURSOR           (1 << 0)
+#define OSD_VIDEO_CONFLICT      (1 << 1)
+#define OSD_FREESCALE           (1 << 2)
+#define OSD_UBOOT_LOGO          (1 << 3)
+#define OSD_LAYER_ENABLE        (1 << 31)
+
+#define BYPASS_DIN        (1 << 7)
+#define OSD_BACKUP_COUNT 8
 
 enum osd_index_e {
        OSD1 = 0,
        OSD2,
        OSD3,
        OSD4,
+       OSD_MAX = OSD4,
 };
 
 enum osd_enable_e {
@@ -278,7 +290,19 @@ enum osd_blend_din_index_e {
        BLEND_DIN1 = 0,
        BLEND_DIN2,
        BLEND_DIN3,
-       BLEND_DIN4
+       BLEND_DIN4,
+       BLEND0_DIN,
+       BLEND1_DIN,
+       BLEND2_DIN,
+       BLEND_NO_DIN,
+};
+
+enum vpp_blend_input_e {
+       POSTBLD_CLOSE = 0,
+       POSTBLD_VD1,
+       POSTBLD_VD2,
+       POSTBLD_OSD1,
+       POSTBLD_OSD2,
 };
 
 enum osd_zorder_e {
@@ -295,8 +319,10 @@ enum osd_zorder_e {
  */
 enum osd_blend_mode_e {
        OSD_BLEND_NONE,
+       OSD_BLEND_A,
+       OSD_BLEND_AC,
+       OSD_BLEND_A_C,
        OSD_BLEND_ABC,
-       OSD_BLEND_AB_C,
        OSD_BLEND_A_BC,
 };
 
@@ -357,7 +383,6 @@ struct osd_rotate_s {
 
 struct osd_fence_map_s {
        struct list_head list;
-
        u32 fb_index;
        u32 buf_num;
        u32 xoffset;
@@ -377,16 +402,48 @@ struct osd_fence_map_s {
        u32 dst_h;
        int byte_stride;
        int pxiel_stride;
+       u32 zorder;
+       u32 blend_mode;
+       u32 plane_alpha;
+       u32 afbc_inter_format;
        u32 background_w;
        u32 background_h;
-       u32 zorder;
-       u32 premult_en;
-       u32 afbc_en;
+       struct fence *in_fence;
+};
+
+struct layer_fence_map_s {
+       u32 fb_index;
+       u32 enable;
+       s32 in_fd;
+       s32 out_fd;
+       u32 ext_addr;
+       u32 format;
+       u32 compose_type;
+       u32 src_x;
+       u32 src_y;
+       u32 src_w;
+       u32 src_h;
+       u32 dst_x;
+       u32 dst_y;
+       u32 dst_w;
+       u32 dst_h;
+       int byte_stride;
+       int pxiel_stride;
        u32 afbc_inter_format;
-       u32 reserve;
+       u32 zorder;
+       u32 blend_mode;
+       u32 plane_alpha;
        struct fence *in_fence;
 };
 
+struct osd_layers_fence_map_s {
+       struct list_head list;
+       int out_fd;
+       u32 background_w;
+       u32 background_h;
+       struct layer_fence_map_s layer_map[HW_OSD_COUNT];
+};
+
 struct afbcd_data_s {
        u32 enable;
        u32 phy_addr;
@@ -468,12 +525,57 @@ struct hw_osd_reg_s {
        u32 afbc_prefetch_cfg_s;/* VPU_MAFBC_PREFETCH_CFG_S0 */
 };
 
+struct layer_blend_reg_s {
+       u32 hold_line;
+       u32 blend2_premult_en;
+       u32 din0_byp_blend;
+       u32 din2_osd_sel;
+       u32 din3_osd_sel;
+       u32 blend_din_en;
+       u32 din_premult_en;
+       u32 din_reoder_sel;
+       u32 osd_blend_din_scope_h[OSD_BLEND_LAYERS];
+       u32 osd_blend_din_scope_v[OSD_BLEND_LAYERS];
+       u32 osd_blend_blend0_size;
+       u32 osd_blend_blend1_size;
+       /* post blend */
+       u32 postbld_src3_sel;
+       u32 postbld_osd1_premult;
+       u32 postbld_src4_sel;
+       u32 postbld_osd2_premult;
+       u32 vpp_osd1_blend_h_scope;
+       u32 vpp_osd1_blend_v_scope;
+       u32 vpp_osd2_blend_h_scope;
+       u32 vpp_osd2_blend_v_scope;
+};
+
+struct layer_blend_s {
+       u8 input1;
+       u8 input2;
+       struct dispdata_s input1_data;
+       struct dispdata_s input2_data;
+       struct dispdata_s output_data;
+       u32 background_w;
+       u32 background_h;
+};
 struct hw_osd_blending_s {
+       u8 osd_blend_mode;
        u8 osd_to_bdin_table[OSD_BLEND_LAYERS];
        u8 reorder[HW_OSD_COUNT];
-       u32 input_src_w[HW_OSD_COUNT];
        u32 din_reoder_sel;
        u32 layer_cnt;
+       bool change_order;
+       bool b_continuous;
+       bool b_exchange_din;
+       bool b_exchange_blend_in;
+       bool osd1_freescale_used;
+       bool osd1_freescale_disable;
+       u32 background_w;
+       u32 background_h;
+       u32 vinfo_width;
+       u32 vinfo_height;
+       struct layer_blend_reg_s blend_reg;
+       struct layer_blend_s layer_blend;
 };
 
 extern struct hw_osd_reg_s hw_osd_reg_array[HW_OSD_COUNT];
@@ -483,6 +585,45 @@ struct hw_list_s {
        update_func_t update_func;
 };
 
+typedef int (*sync_render_fence)(u32 index, u32 yres,
+       struct sync_req_render_s *request,
+       u32 phys_addr);
+typedef void (*osd_toggle_buffer_op)(
+       struct kthread_work *work);
+struct osd_fence_fun_s {
+       sync_render_fence sync_fence_handler;
+       osd_toggle_buffer_op toggle_buffer_handler;
+};
+
+struct layer_info_s {
+       int enable;
+       u32 ext_addr;
+       unsigned int    src_x;
+       unsigned int    src_y;
+       unsigned int    src_w;
+       unsigned int    src_h;
+       unsigned int    dst_x;
+       unsigned int    dst_y;
+       unsigned int    dst_w;
+       unsigned int    dst_h;
+       unsigned int  zorder;
+       unsigned int  blend_mode;
+};
+
+struct osd_debug_backup_s {
+       struct layer_info_s layer[HW_OSD_COUNT];
+       struct layer_blend_reg_s blend_reg;
+};
+
+
+struct hw_debug_s {
+       bool wait_fence_release;
+       u32 osd_single_step_mode;
+       u32 osd_single_step;
+       int backup_count;
+       struct osd_debug_backup_s osd_backup[OSD_BACKUP_COUNT];
+};
+
 struct hw_para_s {
        struct pandata_s pandata[HW_OSD_COUNT];
        struct pandata_s dispdata[HW_OSD_COUNT];
@@ -497,7 +638,6 @@ struct hw_para_s {
        struct dispdata_s src_data[HW_OSD_COUNT];
        struct dispdata_s dst_data[HW_OSD_COUNT];
        u32 buffer_alloc[HW_OSD_COUNT];
-
        u32 gbl_alpha[HW_OSD_COUNT];
        u32 color_key[HW_OSD_COUNT];
        u32 color_key_enable[HW_OSD_COUNT];
@@ -520,7 +660,6 @@ struct hw_para_s {
        u32 scan_mode[HW_OSD_COUNT];
        u32 order[HW_OSD_COUNT];
        u32 premult_en[HW_OSD_COUNT];
-       u32 osd_blend_mode;
        u32 background_w;
        u32 background_h;
 
@@ -558,7 +697,6 @@ struct hw_para_s {
        u32 vinfo_width;
        u32 vinfo_height;
        u32 fb_drvier_probe;
-       u32 afbc_start_in_vsync;
        u32 afbc_force_reset;
        u32 afbc_status_err_reset;
        u32 afbc_use_latch;
@@ -566,5 +704,13 @@ struct hw_para_s {
        u32 osd_use_latch[HW_OSD_COUNT];
        u32 hw_cursor_en;
        u32 hw_rdma_en;
+       u32 blend_bypass;
+       u32 hdr_used;
+       u32 basic_urgent;
+       u32 two_ports;
+       struct hw_debug_s osd_debug;
+       int out_fence_fd;
+       int in_fd[HW_OSD_COUNT];
+       struct osd_fence_fun_s osd_fence[2];
 };
 #endif /* _OSD_H_ */
index c9150bb..ceec4ae 100644 (file)
@@ -68,6 +68,31 @@ static void osd_debug_dump_value(void)
        osd_log_info("bot_type: %d\n", hwpara->bot_type);
        osd_log_info("field_out_en: %d\n", hwpara->field_out_en);
 
+       if (hwpara->osd_meson_dev.osd_ver == OSD_HIGH_ONE) {
+               struct hw_osd_blending_s *blend_para = NULL;
+
+               osd_get_blending_para(&blend_para);
+               if (blend_para != NULL) {
+                       osd_log_info("OSD LAYER: %d\n", blend_para->layer_cnt);
+                       osd_log_info("OSD background size: %d, %d\n",
+                               blend_para->background_w,
+                               blend_para->background_h);
+                       osd_log_info("|index\t|order\t|src axis\t|dst axis\n");
+                       for (index = 0; index < HW_OSD_COUNT; index++) {
+                               osd_log_info("%2d\t%2d\t(%4d,%4d,%4d,%4d)\t(%4d,%4d,%4d,%4d)\n",
+                                       index,
+                                       hwpara->order[index],
+                                       hwpara->src_data[index].x,
+                                       hwpara->src_data[index].y,
+                                       hwpara->src_data[index].w,
+                                       hwpara->src_data[index].h,
+                                       hwpara->dst_data[index].x,
+                                       hwpara->dst_data[index].y,
+                                       hwpara->dst_data[index].w,
+                                       hwpara->dst_data[index].h);
+                       }
+               }
+       }
        for (index = 0; index < HW_OSD_COUNT; index++) {
                osd_log_info("\n--- OSD%d ---\n", index);
                osd_log_info("order: %d\n", hwpara->order[index]);
@@ -182,7 +207,8 @@ static void osd_debug_dump_register_all(void)
                osd_log_info("reg[0x%x]: 0x%08x\n", reg, osd_reg_read(reg));
                reg = VPP_OUT_H_V_SIZE;
                osd_log_info("reg[0x%x]: 0x%08x\n", reg, osd_reg_read(reg));
-
+               if (!osd_hw.powered[count - 1])
+                       count--;
        }
        if (osd_hw.osd_meson_dev.osd_ver == OSD_NORMAL) {
                reg = VPP_OSD_SC_CTRL0;
@@ -194,13 +220,12 @@ static void osd_debug_dump_register_all(void)
                reg = VPP_OSD_SCO_V_START_END;
                osd_log_info("reg[0x%x]: 0x%08x\n\n", reg, osd_reg_read(reg));
        }
+       #if 0
        if (osd_hw.osd_meson_dev.osd_ver == OSD_SIMPLE) {
                reg = OSD_DB_FLT_CTRL;
                osd_log_info("reg[0x%x]: 0x%08x\n\n", reg, osd_reg_read(reg));
        }
-
-       if (!osd_hw.powered[count - 1])
-               count--;
+       #endif
        for (index = 0; index < count; index++) {
                osd_reg = &hw_osd_reg_array[index];
                reg = osd_reg->osd_fifo_ctrl_stat;
@@ -633,6 +658,9 @@ int osd_set_debug_hw(const char *buf)
        case 't':
                osd_debug_auto_test();
                break;
+       case 's':
+               output_save_info();
+               break;
        default:
                osd_log_err("arg error\n");
                break;
index b52aa3a..2ade1e5 100644 (file)
@@ -38,6 +38,8 @@ struct osd_plane_map_s {
        u32 premult_en;
        u32 afbc_en;
        u32 afbc_inter_format;
+       u32 blend_mode;
+       int  plane_alpha;
        u32 reserve;
 };
 
index 3a1e410..d03dbea 100644 (file)
@@ -713,6 +713,8 @@ static int osd_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
        u32 srckey_enable;
        u32 gbl_alpha;
        u32 osd_order;
+       u32 blank;
+       u32 capbility;
        s32 osd_axis[4] = {0};
        s32 osd_dst_axis[4] = {0};
        u32 block_windows[8] = {0};
@@ -720,10 +722,12 @@ static int osd_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
        u32 hwc_enable;
        unsigned long ret;
        u32 flush_rate;
+       int out_fen_fd;
+       int xoffset, yoffset;
        struct fb_sync_request_s sync_request;
-       struct fb_sync_request_render_s sync_request_render;
        struct fb_dmabuf_export dmaexp;
        struct fb_cursor cursor;
+       struct do_hwc_cmd_s do_hwc_cmd;
 
        switch (cmd) {
        case  FBIOPUT_OSD_SRCKEY_ENABLE:
@@ -739,13 +743,10 @@ static int osd_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
                ret = copy_from_user(&osd_axis, argp, 4 * sizeof(s32));
                break;
        case FBIOPUT_OSD_SYNC_ADD:
+       case FBIOPUT_OSD_SYNC_RENDER_ADD:
                ret = copy_from_user(&sync_request, argp,
                                sizeof(struct fb_sync_request_s));
                break;
-       case FBIOPUT_OSD_SYNC_RENDER_ADD:
-               ret = copy_from_user(&sync_request_render, argp,
-                               sizeof(struct fb_sync_request_render_s));
-               break;
        case FBIO_WAITFORVSYNC:
        case FBIOGET_OSD_SCALE_AXIS:
        case FBIOPUT_OSD_ORDER:
@@ -764,6 +765,7 @@ static int osd_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
        case FBIOPUT_OSD_REVERSE:
        case FBIOPUT_OSD_ROTATE_ON:
        case FBIOPUT_OSD_ROTATE_ANGLE:
+       case FBIOGET_OSD_CAPBILITY:
                break;
        case FBIOGET_OSD_DMABUF:
                ret = copy_from_user(&dmaexp, argp,
@@ -788,6 +790,11 @@ static int osd_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
                ret = copy_from_user(&hwc_enable, argp, sizeof(u32));
                break;
        case FBIOPUT_OSD_DO_HWC:
+               ret = copy_from_user(&do_hwc_cmd, argp,
+                               sizeof(struct do_hwc_cmd_s));
+               break;
+       case FBIOPUT_OSD_BLANK:
+               ret = copy_from_user(&blank, argp, sizeof(u32));
                break;
        default:
                osd_log_err("command 0x%x not supported (%s)\n",
@@ -928,64 +935,78 @@ static int osd_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
                        osd_dst_axis[1], osd_dst_axis[2], osd_dst_axis[3]);
                break;
        case FBIOPUT_OSD_SYNC_ADD:
-               sync_request.out_fen_fd =
+               out_fen_fd =
                        osd_sync_request(info->node, info->var.yres,
-                                       sync_request.xoffset,
-                                       sync_request.yoffset,
-                                       sync_request.in_fen_fd);
-               ret = copy_to_user(argp, &sync_request,
+                                       &sync_request);
+               if ((sync_request.sync_req.magic & 0xfffffffe) ==
+                       (FB_SYNC_REQUEST_MAGIC & 0xfffffffe)) {
+                       sync_request.sync_req.out_fen_fd = out_fen_fd;
+                       xoffset = sync_request.sync_req.xoffset;
+                       yoffset = sync_request.sync_req.yoffset;
+                       ret = copy_to_user(argp, &sync_request,
                                sizeof(struct fb_sync_request_s));
-               if (sync_request.out_fen_fd  < 0) {
+               } else {
+                       sync_request.sync_req_old.out_fen_fd = out_fen_fd;
+                       xoffset = sync_request.sync_req_old.xoffset;
+                       yoffset = sync_request.sync_req_old.yoffset;
+                       ret = copy_to_user(argp, &sync_request,
+                               sizeof(struct fb_sync_request_s));
+               }
+               if (out_fen_fd  < 0) {
                        /* fence create fail. */
                        ret = -1;
                } else {
-                       info->var.xoffset = sync_request.xoffset;
-                       info->var.yoffset = sync_request.yoffset;
+                       info->var.xoffset = xoffset;
+                       info->var.yoffset = yoffset;
                }
                break;
        case FBIOPUT_OSD_SYNC_RENDER_ADD:
-               {
-                       ion_phys_addr_t addr;
-                       size_t len;
-                       u32 phys_addr;
-
-                       if (sync_request_render.shared_fd >= 0) {
-                               ret = meson_ion_share_fd_to_phys(fb_ion_client,
-                                       sync_request_render.shared_fd,
-                                       &addr, &len);
-                               if (ret == 0) {
-                                       if (sync_request_render.type ==
-                                               GE2D_COMPOSE_MODE) {
-                                               phys_addr = addr +
-                                               sync_request_render.yoffset
+       {
+               ion_phys_addr_t addr;
+               size_t len;
+               u32 phys_addr;
+
+               if ((sync_request.sync_req_render.magic & 0xfffffffe) ==
+                       (FB_SYNC_REQUEST_RENDER_MAGIC_V1 & 0xfffffffe)) {
+                       struct sync_req_render_s *sync_request_render;
+
+                       sync_request_render =
+                               &sync_request.sync_req_render;
+                       ret = meson_ion_share_fd_to_phys(fb_ion_client,
+                               sync_request_render->shared_fd,
+                               &addr, &len);
+                       if (ret == 0) {
+                               if (sync_request_render->type ==
+                                       GE2D_COMPOSE_MODE) {
+                                       phys_addr = addr +
+                                       sync_request_render->yoffset
                                                * info->fix.line_length;
-                                       } else
-                                               phys_addr = addr;
                                } else
-                                       phys_addr = 0;
+                                       phys_addr = addr;
                        } else
                                phys_addr = 0;
 
-                       sync_request_render.out_fen_fd =
+                       sync_request_render->out_fen_fd =
                                osd_sync_request_render(info->node,
                                info->var.yres,
-                               &sync_request_render, phys_addr);
+                               sync_request_render, phys_addr);
                        osd_restore_screen_info(info->node,
                                &info->screen_base, &info->screen_size);
                        ret = copy_to_user(argp,
-                               &sync_request_render,
-                               sizeof(struct fb_sync_request_render_s));
-                       if (sync_request_render.out_fen_fd  < 0) {
+                               &sync_request,
+                               sizeof(struct fb_sync_request_s));
+                       if (sync_request_render->out_fen_fd  < 0) {
                                /* fence create fail. */
                                ret = -1;
                        } else {
                                info->var.xoffset =
-                                       sync_request_render.xoffset;
+                                       sync_request_render->xoffset;
                                info->var.yoffset =
-                                       sync_request_render.yoffset;
+                                       sync_request_render->yoffset;
                        }
                }
                break;
+       }
        case FBIOGET_OSD_DMABUF:
 #ifdef CONFIG_ION
                if (osd_get_afbc(info->node)) {
@@ -1019,10 +1040,25 @@ static int osd_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
                break;
        case FBIOPUT_OSD_HWC_ENABLE:
                osd_set_hwc_enable(hwc_enable);
+               ret = 0;
                break;
        case FBIOPUT_OSD_DO_HWC:
-               osd_setting_blend();
+               do_hwc_cmd.out_fen_fd =
+                       osd_sync_do_hwc(do_hwc_cmd.background_w,
+                               do_hwc_cmd.background_h);
+               ret = copy_to_user(argp,
+                       &do_hwc_cmd,
+                       sizeof(struct do_hwc_cmd_s));
+               if (do_hwc_cmd.out_fen_fd >= 0)
+                       ret = 0;
                break;
+       case FBIOPUT_OSD_BLANK:
+               osd_set_enable_hw(info->node, (blank != 0) ? 0 : 1);
+               ret = 0;
+               break;
+       case FBIOGET_OSD_CAPBILITY:
+               capbility = osd_get_capbility(info->node);
+               ret = copy_to_user(argp, &capbility, sizeof(u32));
        default:
                break;
        }
@@ -1380,7 +1416,7 @@ static int malloc_osd_memory(struct fb_info *info)
 
 static int osd_open(struct fb_info *info, int arg)
 {
-       u32 fb_index;
+       u32 fb_index, logo_index;
        struct osd_fb_dev_s *fbdev;
        struct fb_fix_screeninfo *fix = NULL;
        int ret = 0;
@@ -1428,6 +1464,14 @@ static int osd_open(struct fb_info *info, int arg)
                if (!fb_ion_client)
                        fb_ion_client = meson_ion_client_create(-1, "meson-fb");
        }
+       logo_index = osd_get_logo_index();
+       /* clear osd buffer if not logo layer */
+       if (((logo_index < 0) || (logo_index != fb_index)) ||
+               (osd_meson_dev.cpu_id == __MESON_CPU_MAJOR_ID_AXG) ||
+               (osd_meson_dev.cpu_id == __MESON_CPU_MAJOR_ID_G12A)) {
+               osd_log_info("set logo loaded\n");
+               set_logo_loaded();
+       }
        return 0;
 }
 
@@ -2741,6 +2785,61 @@ static ssize_t store_do_hwc(struct device *device,
        return count;
 }
 
+static ssize_t show_osd_urgent(
+       struct device *device, struct device_attribute *attr,
+       char *buf)
+{
+       u32 urgent[2];
+
+       osd_get_urgent_info(&urgent[0], &urgent[1]);
+
+       return snprintf(buf, PAGE_SIZE, "%d %d\n", urgent[0], urgent[1]);
+}
+
+static ssize_t store_osd_urgent(
+       struct device *device, struct device_attribute *attr,
+       const char *buf, size_t count)
+{
+       int parsed[2];
+
+       if (likely(parse_para(buf, 2, parsed) == 2))
+               osd_set_urgent_info(parsed[0], parsed[1]);
+       else
+               osd_log_err("set osd_set_urgent_info size error\n");
+
+       return count;
+}
+
+static ssize_t store_osd_single_step_mode(struct device *device,
+                          struct device_attribute *attr,
+                          const char *buf, size_t count)
+{
+       int res = 0;
+       int ret = 0;
+
+       ret = kstrtoint(buf, 0, &res);
+       if (ret < 0)
+               return -EINVAL;
+       osd_set_single_step_mode(res);
+
+       return count;
+}
+
+static ssize_t store_osd_single_step(struct device *device,
+                          struct device_attribute *attr,
+                          const char *buf, size_t count)
+{
+       int res = 0;
+       int ret = 0;
+
+       ret = kstrtoint(buf, 0, &res);
+       if (ret < 0)
+               return -EINVAL;
+       osd_set_single_step(res);
+
+       return count;
+}
+
 static inline  int str2lower(char *str)
 {
        while (*str != '\0') {
@@ -2939,6 +3038,13 @@ static struct device_attribute osd_attrs[] = {
                        show_osd_hwc_enalbe, store_osd_hwc_enalbe),
        __ATTR(osd_do_hwc, 0220,
                        NULL, store_do_hwc),
+       __ATTR(osd_urgent, 0644,
+                       show_osd_urgent, store_osd_urgent),
+       __ATTR(osd_single_step_mode, 0220,
+                       NULL, store_osd_single_step_mode),
+       __ATTR(osd_single_step, 0220,
+                       NULL, store_osd_single_step),
+
 };
 
 static struct device_attribute osd_attrs_viu2[] = {
index d335076..0b1fc95 100644 (file)
@@ -83,14 +83,12 @@ static DECLARE_WAIT_QUEUE_HEAD(osd_vsync_wq);
 static bool vsync_hit;
 static bool osd_update_window_axis;
 static int osd_afbc_dec_enable;
-//static u32 extern_canvas[2] = {EXTERN1_CANVAS, EXTERN2_CANVAS};
-static int ext_canvas_id;
-static int osd_extra_idx[3][2];
+static int ext_canvas_id[HW_OSD_COUNT];
+static int osd_extra_idx[HW_OSD_COUNT][2];
 
 static void osd_clone_pan(u32 index, u32 yoffset, int debug_flag);
 static void osd_set_dummy_data(u32 index, u32 alpha);
 
-#if 1
 struct hw_osd_reg_s hw_osd_reg_array[HW_OSD_COUNT] = {
        {
                VIU_OSD1_CTRL_STAT,
@@ -298,8 +296,6 @@ struct hw_osd_reg_s hw_osd_reg_array[HW_OSD_COUNT] = {
                VIU2_OSD1_UNSUPPORT,
                }
 };
-#endif
-
 static int osd_setting_blending_scope(u32 index);
 static int vpp_blend_setting_default(u32 index);
 
@@ -314,14 +310,28 @@ struct task_struct *buffer_toggle_thread;
 struct kthread_work buffer_toggle_work;
 struct list_head post_fence_list;
 struct mutex post_fence_list_lock;
-static void osd_pan_display_fence(struct osd_fence_map_s *fence_map);
+struct osd_layers_fence_map_s map_layers;
+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);
+
+#define OSD_DISP_DEBUG    1
+#define ENCP_LINE         16
+#define OSD_OLD_HWC         (0x01 << 0)
+#define OSD_OTHER_NEW_HWC   (0x01 << 1)
+#define OSD_G12A_NEW_HWC    (0x01 << 2)
 
 static void *osd_timeline_create(void)
 {
        const char *tlName = "osd_timeline";
 
        if (osd_timeline == NULL) {
-               cur_streamline_val = 1;
+               if (osd_hw.hwc_enable)
+                       /* present fence */
+                       cur_streamline_val = 0;
+               else
+                       cur_streamline_val = 1;
                osd_timeline = aml_sync_create_timeline(tlName);
                osd_tprintk("osd timeline create\n");
        }
@@ -342,7 +352,7 @@ static int osd_timeline_create_fence(void)
        if (out_fence_fd >= 0)
                cur_streamline_val++;
        else
-               pr_debug("create fence returned %d", out_fence_fd);
+               pr_info("create fence returned %d", out_fence_fd);
        return out_fence_fd;
 }
 
@@ -384,6 +394,9 @@ static int pxp_mode;
 
 static unsigned int osd_h_filter_mode = 1;
 #define CANVAS_ALIGNED(x)      (((x) + 31) & ~31)
+#define BYTE_32_ALIGNED(x)     (((x) + 31) & ~31)
+#define BYTE_16_ALIGNED(x)     (((x) + 15) & ~15)
+#define BYTE_8_ALIGNED(x)      (((x) + 7) & ~7)
 module_param(osd_h_filter_mode, uint, 0664);
 MODULE_PARM_DESC(osd_h_filter_mode, "osd_h_filter_mode");
 
@@ -407,6 +420,16 @@ static u32 osd_vpp_misc_mask = OSD_RELATIVE_BITS;
 module_param(osd_vpp_misc, uint, 0444);
 MODULE_PARM_DESC(osd_vpp_misc, "osd_vpp_misc");
 
+static int vsync_enter_line_max;
+static int vsync_exit_line_max;
+static int vsync_line_threshold = 950;
+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);
+
 static unsigned int osd_filter_coefs_bicubic_sharp[] = {
        0x01fa008c, 0x01fa0100, 0xff7f0200, 0xfe7f0300,
        0xfd7e0500, 0xfc7e0600, 0xfb7d0800, 0xfb7c0900,
@@ -527,6 +550,74 @@ static unsigned int *filter_table[] = {
 static bool osd_hdr_on;
 #endif
 
+static int cnt;
+static int get_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;
+       }
+       return enc_line;
+}
+
+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;
+       }
+       if (enc_line > vsync_enter_line_max)
+               vsync_enter_line_max = enc_line;
+       return enc_line;
+}
+
+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;
+       }
+       if (enc_line > vsync_exit_line_max)
+               vsync_exit_line_max = enc_line;
+       return enc_line;
+}
+
 static void osd_vpu_power_on(void)
 {
 #ifdef CONFIG_AMLOGIC_VPU
@@ -572,6 +663,21 @@ static void osd_vpu_power_on_viu2(void)
 #endif
 }
 
+static int get_osd_hwc_type(void)
+{
+       int ret = 0;
+
+       /* new hwcomposer enable */
+       if (osd_hw.hwc_enable) {
+               if (osd_hw.osd_meson_dev.osd_ver == OSD_HIGH_ONE)
+                       ret = OSD_G12A_NEW_HWC;
+               else
+                       ret = OSD_OTHER_NEW_HWC;
+       } else
+               ret = OSD_OLD_HWC;
+       return ret;
+}
+
 #ifdef CONFIG_AMLOGIC_MEDIA_FB_OSD_SYNC_FENCE
 static inline  int  find_buf_num(u32 yres, u32 yoffset)
 {
@@ -587,8 +693,7 @@ static inline  int  find_buf_num(u32 yres, u32 yoffset)
        return i;
 }
 
-/* next we will process two osd layer in toggle buffer. */
-static void osd_toggle_buffer(struct kthread_work *work)
+static void osd_toggle_buffer_single(struct kthread_work *work)
 {
        struct osd_fence_map_s *data, *next;
        struct list_head saved_list;
@@ -598,87 +703,149 @@ static void osd_toggle_buffer(struct kthread_work *work)
        list_replace_init(&post_fence_list, &saved_list);
        mutex_unlock(&post_fence_list_lock);
        list_for_each_entry_safe(data, next, &saved_list, list) {
-               osd_pan_display_fence(data);
-               if (data->in_fence)
-                       osd_put_fenceobj(data->in_fence);
+               osd_pan_display_single_fence(data);
+               list_del(&data->list);
+               kfree(data);
+       }
+}
+
+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);
+       list_for_each_entry_safe(data, next, &saved_list, list) {
+               osd_pan_display_layers_fence(data);
                list_del(&data->list);
                kfree(data);
        }
 }
 
-static int out_fence_create(int *release_fence_fd, u32 *val, u32 buf_num)
+
+static void osd_toggle_buffer(struct kthread_work *work)
+{
+       osd_hw.osd_fence[osd_hw.hwc_enable].
+               toggle_buffer_handler(work);
+}
+
+static int out_fence_create(int *release_fence_fd)
 {
        int out_fence_fd = -1;
 
-       if (!timeline_created) {
-               if (osd_timeline_create() == NULL)
-                       return -1;
 
-               kthread_init_worker(&buffer_toggle_worker);
-               buffer_toggle_thread = kthread_run(kthread_worker_fn,
-                       &buffer_toggle_worker, "aml_buf_toggle");
-               kthread_init_work(&buffer_toggle_work, osd_toggle_buffer);
-               timeline_created = 1;
+       if (!timeline_created) {
+               /* timeline has not been created */
+               if (osd_timeline_create()) {
+                       kthread_init_worker(&buffer_toggle_worker);
+                       buffer_toggle_thread = kthread_run(
+                               kthread_worker_fn,
+                               &buffer_toggle_worker,
+                               "aml_buf_toggle");
+                       kthread_init_work(
+                               &buffer_toggle_work, osd_toggle_buffer);
+                       timeline_created = 1;
+               }
        }
-
-       out_fence_fd = osd_timeline_create_fence();
-       if (out_fence_fd < 0) {
-               osd_log_err("fence obj create fail\n");
-               out_fence_fd = -1;
+       /* hwc_enable disable create fence every time */
+       if (!osd_hw.hwc_enable) {
+               out_fence_fd = osd_timeline_create_fence();
+               if (out_fence_fd < 0) {
+                       osd_log_err("fence obj create fail\n");
+                       out_fence_fd = -1;
+               }
+       } else {
+               /* 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 (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;
        }
-       *release_fence_fd = out_fence_fd;
-
+       if (release_fence_fd)
+               *release_fence_fd = out_fence_fd;
        return out_fence_fd;
 }
 
-int osd_sync_request(u32 index, u32 yres, u32 xoffset, u32 yoffset,
-                    s32 in_fence_fd)
+int osd_sync_request(u32 index, u32 yres, struct fb_sync_request_s *request)
 {
        int out_fence_fd = -1;
        int buf_num = 0;
-       u32 val;
-
        struct osd_fence_map_s *fence_map =
                kzalloc(sizeof(struct osd_fence_map_s), GFP_KERNEL);
-       buf_num = find_buf_num(yres, yoffset);
-       if (!fence_map) {
-               osd_log_err("could not allocate osd_fence_map\n");
-               return -ENOMEM;
+
+       osd_hw.hwc_enable = 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);
+               fence_map->op = 0xffffffff;
+               fence_map->fb_index = index;
+               fence_map->buf_num = buf_num;
+               fence_map->yoffset = request->sync_req.yoffset;
+               fence_map->xoffset = request->sync_req.xoffset;
+               fence_map->yres = yres;
+               fence_map->format = request->sync_req.format;
+               fence_map->in_fd = request->sync_req.in_fen_fd;
+               osd_tprintk("request fence fd:%d\n", fence_map->in_fd);
+               fence_map->in_fence = osd_get_fenceobj(
+                       request->sync_req.in_fen_fd);
+               fence_map->out_fd =
+                       out_fence_create(&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);
+               fence_map->op = 0xffffffff;
+               fence_map->fb_index = index;
+               fence_map->buf_num = buf_num;
+               fence_map->yoffset = request->sync_req_old.yoffset;
+               fence_map->xoffset = request->sync_req_old.xoffset;
+               fence_map->yres = yres;
+               fence_map->in_fd = request->sync_req_old.in_fen_fd;
+               osd_tprintk("request fence fd:%d\n", fence_map->in_fd);
+               fence_map->in_fence = osd_get_fenceobj(
+                               request->sync_req_old.in_fen_fd);
+               fence_map->out_fd =
+                       out_fence_create(&out_fence_fd);
        }
-       mutex_lock(&post_fence_list_lock);
-       fence_map->op = 0xffffffff;
-       fence_map->fb_index = index;
-       fence_map->buf_num = buf_num;
-       fence_map->yoffset = yoffset;
-       fence_map->xoffset = xoffset;
-       fence_map->yres = yres;
-       fence_map->in_fd = in_fence_fd;
-       osd_tprintk("request fence fd:%d\n", in_fence_fd);
-       fence_map->in_fence = osd_get_fenceobj(in_fence_fd);
-       fence_map->out_fd =
-               out_fence_create(&out_fence_fd, &val, buf_num);
        list_add_tail(&fence_map->list, &post_fence_list);
        mutex_unlock(&post_fence_list_lock);
        kthread_queue_work(&buffer_toggle_worker, &buffer_toggle_work);
-       __close_fd(current->files, in_fence_fd);
+       __close_fd(current->files, fence_map->in_fd);
        return  out_fence_fd;
 }
 
-int osd_sync_request_render(u32 index, u32 yres,
-       struct fb_sync_request_render_s *request,
+
+static int sync_render_single_fence(u32 index, u32 yres,
+       struct sync_req_render_s *request,
        u32 phys_addr)
 {
        int out_fence_fd = -1;
        int buf_num = 0;
        u32 xoffset, yoffset;
-       s32 in_fence_fd;
-       u32 val;
        struct osd_fence_map_s *fence_map =
                kzalloc(sizeof(struct osd_fence_map_s), GFP_KERNEL);
 
+       if (index > OSD1)
+               return -1;
        xoffset = request->xoffset;
        yoffset = request->yoffset;
-       in_fence_fd = request->in_fen_fd;
        buf_num = find_buf_num(yres, yoffset);
        if (!fence_map) {
                osd_log_err("could not allocate osd_fence_map\n");
@@ -691,10 +858,9 @@ int osd_sync_request_render(u32 index, u32 yres,
        fence_map->yoffset = yoffset;
        fence_map->xoffset = xoffset;
        fence_map->yres = yres;
-       fence_map->in_fd = in_fence_fd;
+       fence_map->in_fd = request->in_fen_fd;
        fence_map->ext_addr = phys_addr;
        if (fence_map->ext_addr) {
-               fence_map->format = request->format;
                fence_map->width = request->width;
                fence_map->height = request->height;
                fence_map->dst_x = request->dst_x;
@@ -703,27 +869,137 @@ int osd_sync_request_render(u32 index, u32 yres,
                fence_map->dst_h = request->dst_h;
                fence_map->byte_stride = request->byte_stride;
                fence_map->pxiel_stride = request->pxiel_stride;
-               fence_map->background_w = request->background_w;
-               fence_map->background_h = request->background_h;
-               fence_map->zorder = request->zorder;
-               fence_map->premult_en = request->premult_en;
-               fence_map->afbc_en = request->afbc_en;
                fence_map->afbc_inter_format = request->afbc_inter_format;
-               fence_map->reserve = request->reserve;
        }
+       fence_map->format = request->format;
        fence_map->compose_type = request->type;
        fence_map->op = request->op;
-       osd_tprintk("direct render fence fd:%d\n", in_fence_fd);
-       fence_map->in_fence = osd_get_fenceobj(in_fence_fd);
+
+       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, &val, buf_num);
+               out_fence_create(&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);
        request->out_fen_fd = out_fence_fd;
+       __close_fd(current->files, fence_map->in_fd);
+       return out_fence_fd;
+}
+
+static int sync_render_layers_fence(u32 index, u32 yres,
+       struct sync_req_render_s *request,
+       u32 phys_addr)
+{
+       int out_fence_fd = -1;
+       s32 in_fence_fd;
+       struct osd_layers_fence_map_s *fence_map = NULL;
+
+       if (index > OSD_MAX)
+               return -1;
+       in_fence_fd = request->in_fen_fd;
+       mutex_lock(&post_fence_list_lock);
+       fence_map = &map_layers;
+       fence_map->layer_map[index].fb_index = index;
+       /* layer_map[index].enable will update if have blank ioctl */
+       fence_map->layer_map[index].enable = 1;
+       fence_map->layer_map[index].in_fd = request->in_fen_fd;
+       fence_map->layer_map[index].ext_addr = phys_addr;
+       fence_map->layer_map[index].format = request->format;
+       fence_map->layer_map[index].compose_type = request->type;
+       fence_map->layer_map[index].src_x = request->xoffset;
+       fence_map->layer_map[index].src_y = request->yoffset;
+       fence_map->layer_map[index].src_w = request->width;
+       fence_map->layer_map[index].src_h = request->height;
+       fence_map->layer_map[index].dst_x = request->dst_x;
+       fence_map->layer_map[index].dst_y = request->dst_y;
+       fence_map->layer_map[index].dst_w = request->dst_w;
+       fence_map->layer_map[index].dst_h = request->dst_h;
+       fence_map->layer_map[index].byte_stride =
+               request->byte_stride;
+       fence_map->layer_map[index].pxiel_stride =
+               request->pxiel_stride;
+       fence_map->layer_map[index].afbc_inter_format =
+               request->afbc_inter_format;
+       fence_map->layer_map[index].zorder = request->zorder;
+       fence_map->layer_map[index].blend_mode =
+               request->blend_mode;
+       fence_map->layer_map[index].plane_alpha =
+               request->plane_alpha;
+       /* just return out_fd,but not signal */
+       /* 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);
+       osd_log_dbg("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);
-       return  out_fence_fd;
+       return out_fence_fd;
+}
+
+int osd_sync_request_render(u32 index, u32 yres,
+       struct sync_req_render_s *request,
+       u32 phys_addr)
+{
+       int line;
+
+       cnt++;
+       line = get_encp_line();
+       if (osd_hw.osd_display_debug == ENCP_LINE)
+               osd_log_info(
+                       "enter osd_sync_request_render:cnt=%d,encp line=%d\n",
+                       cnt, line);
+       if (request->magic == FB_SYNC_REQUEST_RENDER_MAGIC_V1)
+               osd_hw.hwc_enable = 0;
+       else if (request->magic == FB_SYNC_REQUEST_RENDER_MAGIC_V2)
+               osd_hw.hwc_enable = 1;
+       osd_hw.osd_fence[osd_hw.hwc_enable].sync_fence_handler(
+               index, yres, request, phys_addr);
+       return request->out_fen_fd;
+}
+
+int osd_sync_do_hwc(u32 width, u32 height)
+{
+       int out_fence_fd = -1;
+       struct osd_layers_fence_map_s *fence_map = NULL;
+       int line;
+
+       line = get_encp_line();
+       if (osd_hw.osd_display_debug == ENCP_LINE)
+               osd_log_info(
+                       "enter osd_sync_do_hwc:cnt=%d,encp line=%d\n",
+                       cnt, 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));
+       /* clear map_layers, need alloc next add_sync ioctl */
+       memset(&map_layers, 0,
+               sizeof(struct osd_layers_fence_map_s));
+       fence_map->out_fd =
+               out_fence_create(&out_fence_fd);
+       fence_map->background_w = width;
+       fence_map->background_h = height;
+       /* other info set via add_sync and blank ioctl */
+       list_add_tail(&fence_map->list, &post_fence_list);
+       /* 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);
+
+       osd_log_dbg("osd_sync_do_hwc :out_fence_fd=%d\n",
+               out_fence_fd);
+       return out_fence_fd;
 }
 
 static int osd_wait_buf_ready(struct osd_fence_map_s *fence_map)
@@ -748,9 +1024,28 @@ static int osd_wait_buf_ready(struct osd_fence_map_s *fence_map)
        return ret;
 }
 
+static int osd_wait_buf_ready_combine(struct layer_fence_map_s *layer_map)
+{
+       s32 ret = -1;
+       struct fence *buf_ready_fence = NULL;
+
+       if (layer_map->in_fd <= 0)
+               return -1;
+       buf_ready_fence = layer_map->in_fence;
+       ret = osd_wait_fenceobj(buf_ready_fence, 4000);
+       if (ret < 0)
+               osd_log_err("osd%d: Sync Fence wait error:%d\n",
+               layer_map->fb_index, ret);
+       else
+               ret = 1;
+
+       osd_log_dbg("osd_wait_buf_ready_combine:osd%d,in_fd=%d\n",
+               layer_map->fb_index, layer_map->in_fd);
+       return ret;
+}
+
 #else
-int osd_sync_request(u32 index, u32 yres, u32 xoffset, u32 yoffset,
-                    s32 in_fence_fd)
+int osd_sync_request(u32 index, u32 yres, struct fb_sync_request_s *request)
 {
        osd_log_err("osd_sync_request not supported\n");
        return -5566;
@@ -758,15 +1053,43 @@ int osd_sync_request(u32 index, u32 yres, u32 xoffset, u32 yoffset,
 
 
 int osd_sync_request_render(u32 index, u32 yres,
-       struct fb_sync_request_render_s *request,
+       struct sync_req_render_s *request,
        u32 phys_addr)
 {
        osd_log_err("osd_sync_request_render not supported\n");
        return -5566;
 }
+
+int osd_sync_do_hwc(u32 width, u32 height)
+{
+       osd_log_err("osd_do_hwc not supported\n");
+       return -5566;
+}
 #endif
 
 
+void osd_set_enable_hw(u32 index, u32 enable)
+{
+       if (osd_hw.hwc_enable) {
+               if (index > OSD_MAX)
+                       return;
+               if (osd_hw.osd_meson_dev.osd_ver < OSD_HIGH_ONE)
+                       osd_enable_hw(index, enable);
+               else {
+               /* Todo: */
+#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;
+               mutex_unlock(&post_fence_list_lock);
+               osd_log_dbg("osd_set_enable_hw: osd%d,enable=%d\n",
+                       index, enable);
+#endif
+               }
+       } else
+               osd_enable_hw(index, enable);
+}
+
 void osd_update_3d_mode(void)
 {
        int i = 0;
@@ -1165,8 +1488,6 @@ void osd_hw_reset(void)
                        VIU_SW_RESET, reset_bit);
                VSYNCOSD_IRQ_WR_MPEG_REG(
                        VIU_SW_RESET, 0);
-               if (reset_bit == HW_RESET_MALI_AFBCD_REGS)
-                       osd_log_dbg("reset_bit=%x\n", reset_bit);
                if (reset_bit & HW_RESET_OSD1_REGS) {
                        /* restore osd regs */
                        int i;
@@ -1290,7 +1611,6 @@ void osd_set_pxp_mode(u32 mode)
 void osd_set_afbc(u32 index, u32 enable)
 {
        if (osd_hw.osd_meson_dev.afbc_type)
-               if (index != OSD4)
                osd_hw.osd_afbcd[index].enable = enable;
        osd_log_info("afbc_type=%d,enable=%d\n",
                osd_hw.osd_meson_dev.afbc_type,
@@ -1299,7 +1619,19 @@ void osd_set_afbc(u32 index, u32 enable)
 
 u32 osd_get_afbc(u32 index)
 {
-       return osd_hw.osd_afbcd[index].enable;
+       u32 afbc_type = 0;
+
+       if (osd_hw.osd_afbcd[index].enable) {
+               if (osd_hw.osd_meson_dev.cpu_id ==
+                       __MESON_CPU_MAJOR_ID_GXM)
+                       afbc_type = 1;
+               else if (osd_hw.osd_meson_dev.cpu_id ==
+                       __MESON_CPU_MAJOR_ID_G12A)
+                       afbc_type = 2;
+               else
+                       afbc_type = 0;
+       }
+       return afbc_type;
 }
 
 u32 osd_get_reset_status(void)
@@ -1592,6 +1924,7 @@ void osd_update_disp_axis_hw(
        if (mode_change) /* modify pandata . */
                osd_hw.reg[OSD_COLOR_MODE].update_func(index);
        osd_hw.reg[DISP_GEOMETRY].update_func(index);
+       osd_update_window_axis = true;
        spin_unlock_irqrestore(&osd_lock, lock_flags);
        osd_wait_vsync_hw();
 }
@@ -1699,6 +2032,8 @@ void osd_setup_hw(u32 index,
                        index, osd_hw.fb_gem[index].xres);
                osd_log_info("osd[%d] frame.height=%d\n",
                        index, osd_hw.fb_gem[index].yres);
+               osd_log_info("osd[%d] out_addr_id =0x%x\n",
+                       index, osd_hw.osd_afbcd[index].out_addr_id);
 
                if (osd_hw.osd_meson_dev.osd_ver == OSD_SIMPLE)
                        osd_update_phy_addr(0);
@@ -1983,6 +2318,8 @@ 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_setting_blend();
        mutex_unlock(&osd_mutex);
 }
 
@@ -2056,7 +2393,8 @@ void osd_enable_hw(u32 index, u32 enable)
 
        /* reset viu 31bit ?? */
        if (!osd_hw.enable[index] &&
-                       osd_hw.osd_afbcd[index].enable && enable) {
+                       osd_hw.osd_afbcd[index].enable && enable
+                       && (get_osd_hwc_type() != 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);
@@ -2083,8 +2421,11 @@ void osd_enable_hw(u32 index, u32 enable)
                osd_log_info("osd[%d]: wait %d vsync first buffer ready.\n",
                        index, i);
        osd_hw.enable[index] = enable;
-       add_to_update_list(index, OSD_ENABLE);
-       osd_wait_vsync_hw();
+       if (get_osd_hwc_type() != 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();
 }
 
 void osd_set_2x_scale_hw(u32 index, u16 h_scale_enable, u16 v_scale_enable)
@@ -2450,16 +2791,16 @@ void osd_set_premult(u32 index, u32 premult)
 
 void osd_get_afbc_debug(u32 *val1, u32 *val2, u32 *val3, u32 *val4)
 {
-       *val1 = osd_hw.afbc_start_in_vsync;
-       *val2 = osd_hw.afbc_force_reset;
+       *val1 = osd_hw.blend_bypass;
+       *val2 = osd_hw.hdr_used;
        *val3 = osd_hw.afbc_status_err_reset;
        *val4 = osd_hw.afbc_use_latch;
 }
 
 void osd_set_afbc_debug(u32 val1, u32 val2, u32 val3, u32 val4)
 {
-       osd_hw.afbc_start_in_vsync = val1;
-       osd_hw.afbc_force_reset = val2;
+       osd_hw.blend_bypass = val1;
+       osd_hw.hdr_used = val2;
        osd_hw.afbc_status_err_reset = val3;
        osd_hw.afbc_use_latch = val4;
 }
@@ -2494,6 +2835,226 @@ void osd_do_hwc(void)
 {
        osd_setting_blend();
 }
+
+static void osd_set_two_ports(bool set)
+{
+       static u32 data32[2];
+
+       if (set) {
+               data32[0] = osd_reg_read(VPP_RDARB_MODE);
+               data32[1] = osd_reg_read(VPU_RDARB_MODE_L2C1);
+               osd_reg_set_bits(VPP_RDARB_MODE, 2, 20, 8);
+               osd_reg_set_bits(VPU_RDARB_MODE_L2C1, 2, 16, 8);
+       } else {
+               osd_reg_write(VPP_RDARB_MODE, data32[0]);
+               osd_reg_write(VPU_RDARB_MODE_L2C1, data32[1]);
+       }
+}
+
+static void osd_set_basic_urgent(bool set)
+{
+       if (set)
+               osd_reg_write(0x27c2, 0xffff);
+       else
+               osd_reg_write(0x27c2, 0x0);
+}
+
+void osd_get_urgent_info(u32 *ports, u32 *basic_urgent)
+{
+       *basic_urgent = osd_hw.basic_urgent;
+       *ports = osd_hw.two_ports;
+}
+
+void osd_set_urgent_info(u32 ports, u32 basic_urgent)
+{
+       osd_hw.basic_urgent = basic_urgent;
+       osd_hw.two_ports = ports;
+       osd_set_basic_urgent(osd_hw.basic_urgent);
+       osd_set_two_ports(osd_hw.two_ports);
+}
+
+void osd_set_single_step_mode(u32 osd_single_step_mode)
+{
+       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)) {
+               osd_timeline_increase();
+               osd_log_info("signal fence\n");
+               osd_hw.osd_debug.wait_fence_release = false;
+       }
+
+}
+
+void osd_set_single_step(u32 osd_single_step)
+{
+       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)) {
+               osd_timeline_increase();
+               osd_log_info("signal fence\n");
+               osd_hw.osd_debug.wait_fence_release = false;
+       }
+}
+
+int osd_get_capbility(u32 index)
+{
+       u32 capbility = 0;
+
+       if (osd_hw.osd_meson_dev.osd_ver == OSD_HIGH_ONE) {
+               if (index == OSD1)
+                       capbility |= OSD_LAYER_ENABLE | OSD_FREESCALE
+                               | OSD_UBOOT_LOGO;
+               else if ((index == OSD2) || (index == OSD3))
+                       capbility |= OSD_LAYER_ENABLE |
+                               OSD_VIDEO_CONFLICT | OSD_FREESCALE;
+       } else if (osd_hw.osd_meson_dev.osd_ver == OSD_NORMAL) {
+               if (index == OSD1)
+                       capbility |= OSD_LAYER_ENABLE | OSD_FREESCALE;
+               else if (index == OSD2)
+                       capbility |= OSD_LAYER_ENABLE |
+                               OSD_HW_CURSOR | OSD_FREESCALE
+                               | OSD_UBOOT_LOGO;
+       }
+       return capbility;
+}
+
+static void clear_backup_info(void)
+{
+       struct osd_debug_backup_s *osd_backup;
+       int count = osd_hw.osd_debug.backup_count;
+       int i;
+
+       osd_backup = &osd_hw.osd_debug.osd_backup[count];
+       for (i = 0; i < HW_OSD_COUNT; i++)
+               memset(&(osd_backup->layer[i]), 0x0,
+                       sizeof(struct layer_info_s));
+}
+
+static void save_layer_info(struct layer_fence_map_s *layer_map)
+{
+       struct osd_debug_backup_s *osd_backup;
+       int count = osd_hw.osd_debug.backup_count;
+       u32 index = layer_map->fb_index;
+
+       osd_backup = &osd_hw.osd_debug.osd_backup[count];
+       osd_backup->layer[index].enable = layer_map->enable;
+       osd_backup->layer[index].ext_addr = layer_map->ext_addr;
+       osd_backup->layer[index].src_x = layer_map->src_x;
+       osd_backup->layer[index].src_y = layer_map->src_y;
+       osd_backup->layer[index].src_w = layer_map->src_w;
+       osd_backup->layer[index].src_h = layer_map->src_h;
+       osd_backup->layer[index].dst_x = layer_map->dst_x;
+       osd_backup->layer[index].dst_y = layer_map->dst_y;
+       osd_backup->layer[index].dst_w = layer_map->dst_w;
+       osd_backup->layer[index].dst_h = layer_map->dst_h;
+       osd_backup->layer[index].zorder = layer_map->zorder;
+       osd_backup->layer[index].blend_mode = layer_map->blend_mode;
+}
+
+static void save_blend_reg(struct layer_blend_reg_s *blend_reg)
+{
+       struct osd_debug_backup_s *osd_backup;
+       int count = osd_hw.osd_debug.backup_count;
+
+       osd_backup = &osd_hw.osd_debug.osd_backup[count];
+       memcpy(&(osd_backup->blend_reg), blend_reg,
+               sizeof(struct layer_blend_reg_s));
+       osd_hw.osd_debug.backup_count++;
+       if (osd_hw.osd_debug.backup_count >= OSD_BACKUP_COUNT)
+               osd_hw.osd_debug.backup_count = 0;
+}
+
+static void osd_info_output(int count)
+{
+       struct osd_debug_backup_s *osd_backup;
+       struct layer_blend_reg_s *blend_reg;
+       int index;
+       u32 value;
+
+       osd_backup = &osd_hw.osd_debug.osd_backup[count];
+       osd_log_info("|index|enable|ext_addr|order|blend_mode|src axis|dst axis\n");
+       for (index = 0; index < HW_OSD_COUNT; index++) {
+               if (osd_backup->layer[index].enable) {
+               osd_log_info("%d\t%4d\t  0x%8x %2d\t%2d\t(%4d,%4d,%4d,%4d)\t(%4d,%4d,%4d,%4d)\n",
+                       index,
+                       osd_backup->layer[index].enable,
+                       osd_backup->layer[index].ext_addr,
+                       osd_backup->layer[index].zorder,
+                       osd_backup->layer[index].blend_mode,
+                       osd_backup->layer[index].src_x,
+                       osd_backup->layer[index].src_y,
+                       osd_backup->layer[index].src_w,
+                       osd_backup->layer[index].src_h,
+                       osd_backup->layer[index].dst_x,
+                       osd_backup->layer[index].dst_h,
+                       osd_backup->layer[index].dst_w,
+                       osd_backup->layer[index].dst_h);
+               }
+       }
+
+       blend_reg = &osd_backup->blend_reg;
+       value = 4                                 << 29|
+               blend_reg->blend2_premult_en << 27|
+               blend_reg->din0_byp_blend         << 26|
+               blend_reg->din2_osd_sel   << 25|
+               blend_reg->din3_osd_sel   << 24|
+               blend_reg->blend_din_en   << 20|
+               blend_reg->din_premult_en         << 16|
+               blend_reg->din_reoder_sel;
+       osd_log_info("(0x39b0)=0x%x\n", value);
+       for (index = 0; index < HW_OSD_COUNT; index++) {
+               if (osd_hw.enable[index]) {
+                       osd_log_info("(0x%x)=0x%x, (0x%x)=0x%x\n",
+                       VIU_OSD_BLEND_DIN0_SCOPE_H + 2 * index,
+                       blend_reg->osd_blend_din_scope_h[index],
+                       VIU_OSD_BLEND_DIN0_SCOPE_V + 2 * index,
+                       blend_reg->osd_blend_din_scope_v[index]);
+               }
+       }
+       /* vpp osd1 blend ctrl */
+       value = (0 & 0xf) << 0 |
+               (0 & 0x1) << 4 |
+               (blend_reg->postbld_src3_sel & 0xf) << 8 |
+               (blend_reg->postbld_osd1_premult & 0x1) << 16|
+               (1 & 0x1) << 20;
+       osd_log_info("(0x1dfd)=0x%x\n", value);
+       osd_log_info("(0x39bb)=0x%x\n",
+               blend_reg->osd_blend_blend0_size);
+
+       /* vpp osd2 blend ctrl */
+       value = (0 & 0xf) << 0 |
+               (0 & 0x1) << 4 |
+               (blend_reg->postbld_src4_sel & 0xf) << 8 |
+               (blend_reg->postbld_osd2_premult & 0x1) << 16 |
+               (1 & 0x1) << 20;
+       osd_log_info("(0x1dfe)=0x%x\n", value);
+       osd_log_info("(0x39bc)=0x%x\n",
+               blend_reg->osd_blend_blend0_size);
+       osd_log_info("(0x1df5)=0x%x, (0x1df6)=0x%x\n",
+               blend_reg->vpp_osd1_blend_h_scope,
+               blend_reg->vpp_osd1_blend_v_scope);
+       osd_log_info("(0x1df7)=0x%x, (0x1df8)=0x%x\n",
+               blend_reg->vpp_osd2_blend_h_scope,
+               blend_reg->vpp_osd2_blend_v_scope);
+}
+
+void output_save_info(void)
+{
+       struct osd_debug_backup_s *osd_backup;
+       int count = osd_hw.osd_debug.backup_count - 1;
+       int i;
+
+       osd_backup = &osd_hw.osd_debug.osd_backup[count];
+       for (i = count; i >= 0; i--) {
+               osd_log_info("save list %d\n", i);
+               osd_info_output(i);
+       }
+       for (i = OSD_BACKUP_COUNT - 1; i > count; i--) {
+               osd_log_info("save list %d\n", i);
+               osd_info_output(i);
+       }
+}
+
 #ifdef CONFIG_AMLOGIC_MEDIA_FB_OSD_SYNC_FENCE
 enum {
        HAL_PIXEL_FORMAT_RGBA_8888 = 1,
@@ -2557,6 +3118,7 @@ static bool osd_ge2d_compose_pan_display(struct osd_fence_map_s *fence_map)
 {
        u32 index = fence_map->fb_index;
        bool free_scale_set = false;
+       void *vaddr = NULL;
 
        canvas_config(osd_hw.fb_gem[index].canvas_idx,
                fence_map->ext_addr,
@@ -2564,11 +3126,17 @@ static bool osd_ge2d_compose_pan_display(struct osd_fence_map_s *fence_map)
                (osd_hw.color_info[index]->bpp >> 3)),
                fence_map->height,
                CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR);
+       vaddr = phys_to_virt(fence_map->ext_addr);
+       osd_hw.screen_base[index] = vaddr;
+       osd_hw.screen_size[index] =
+               CANVAS_ALIGNED(fence_map->width *
+               osd_hw.color_info[index]->bpp) * fence_map->height;
 
        osd_hw.pandata[index].x_start = 0;
        osd_hw.pandata[index].x_end = fence_map->width - 1;
        osd_hw.pandata[index].y_start = 0;
        osd_hw.pandata[index].y_end = fence_map->height - 1;
+       #if 0
        if ((osd_hw.screen_base[index] !=
                osd_hw.screen_base_backup[index])
                || (osd_hw.screen_size[index] !=
@@ -2577,7 +3145,7 @@ static bool osd_ge2d_compose_pan_display(struct osd_fence_map_s *fence_map)
                osd_hw.screen_size[index] = osd_hw.screen_size_backup[index];
                free_scale_set = true;
        }
-
+       #endif
        if ((memcmp(&osd_hw.dispdata[index],
                &osd_hw.dispdata_backup[index],
                sizeof(struct pandata_s)) != 0) ||
@@ -2620,7 +3188,6 @@ static bool osd_ge2d_compose_pan_display(struct osd_fence_map_s *fence_map)
        return free_scale_set;
 }
 
-#if 1
 static bool osd_direct_compose_pan_display(struct osd_fence_map_s *fence_map)
 {
        u32 index = fence_map->fb_index;
@@ -2659,38 +3226,8 @@ static bool osd_direct_compose_pan_display(struct osd_fence_map_s *fence_map)
                                osd_hw.osd_afbcd[index].conv_lbuf_len = 512;
                        else
                                osd_hw.osd_afbcd[index].conv_lbuf_len = 1024;
-               } else if (osd_hw.osd_meson_dev.afbc_type == MALI_AFBC) {
-
                }
        }
-       if (osd_hw.hwc_enable) {
-               #if 1
-               fence_map->zorder = 1;
-               fence_map->premult_en = 0;
-               fence_map->background_w = 1920;
-               fence_map->background_h = 1080;
-               fence_map->afbc_inter_format = 0x3;
-               #endif
-               /* just get para, need update via do_hwc */
-               osd_hw.order[index] = fence_map->zorder;
-               osd_hw.premult_en[index] = fence_map->premult_en;
-               osd_hw.background_w = fence_map->background_w;
-               osd_hw.background_h = fence_map->background_h;
-               osd_hw.osd_afbcd[index].enable = fence_map->afbc_en;
-               osd_hw.osd_afbcd[index].inter_format =
-                       fence_map->afbc_inter_format;
-
-               osd_hw.src_data[index].x = fence_map->xoffset;
-               osd_hw.src_data[index].y = fence_map->yoffset;
-               osd_hw.src_data[index].w = fence_map->width;
-               osd_hw.src_data[index].h = fence_map->height;
-
-               osd_hw.dst_data[index].x = fence_map->dst_x;
-               osd_hw.dst_data[index].y = fence_map->dst_y;
-               osd_hw.dst_data[index].w = fence_map->dst_w;
-               osd_hw.dst_data[index].h = fence_map->dst_h;
-               return 0;
-       }
        width_dst = osd_hw.free_dst_data_backup[index].x_end -
                osd_hw.free_dst_data_backup[index].x_start + 1;
        width_src = osd_hw.free_src_data_backup[index].x_end -
@@ -2852,7 +3389,7 @@ static bool osd_direct_compose_pan_display(struct osd_fence_map_s *fence_map)
        return freescale_update;
 }
 
-static void osd_pan_display_fence(struct osd_fence_map_s *fence_map)
+static void osd_pan_display_single_fence(struct osd_fence_map_s *fence_map)
 {
        s32 ret = 1;
        long diff_x, diff_y;
@@ -2866,13 +3403,9 @@ static void osd_pan_display_fence(struct osd_fence_map_s *fence_map)
        bool skip = false;
        const struct vinfo_s *vinfo;
 
-       if (!osd_hw.hwc_enable) {
-               if (index >= OSD2)
-                       return;
-       } else {
-               if (index >= OSD3)
-                       return;
-       }
+
+       if (index >= OSD2)
+               goto out;
        if (timeline_created) { /* out fence created success. */
                ret = osd_wait_buf_ready(fence_map);
                if (ret < 0)
@@ -2887,7 +3420,13 @@ static void osd_pan_display_fence(struct osd_fence_map_s *fence_map)
                else
                        osd_enable = (fence_map->op & 1) ? DISABLE : ENABLE;
                /* need update via direct render interface later */
-               fence_map->afbc_en = osd_hw.osd_afbcd[index].enable;
+               //fence_map->afbc_en = osd_hw.osd_afbcd[index].enable;
+               if ((osd_hw.osd_meson_dev.osd_ver == OSD_HIGH_ONE)
+                       && (osd_hw.osd_afbcd[index].enable)) {
+                       osd_hw.osd_afbcd[index].inter_format =
+                                AFBC_EN | BLOCK_SPLIT |
+                                YUV_TRANSFORM | SUPER_BLOCK_ASPECT;
+               }
                vinfo = get_current_vinfo();
                if (vinfo) {
                        osd_hw.vinfo_width = vinfo->width;
@@ -2898,10 +3437,10 @@ static void osd_pan_display_fence(struct osd_fence_map_s *fence_map)
                        && fence_map->height) {
                        spin_lock_irqsave(&osd_lock, lock_flags);
                        use_ext = true;
-                       if (!fence_map->afbc_en) {
+                       if (!osd_hw.osd_afbcd[index].enable) {
                                osd_hw.fb_gem[index].canvas_idx =
-                                       osd_extra_idx[index][ext_canvas_id];
-                               ext_canvas_id ^= 1;
+                               osd_extra_idx[index][ext_canvas_id[index]];
+                               ext_canvas_id[index] ^= 1;
                                osd_hw.osd_afbcd[index].enable = DISABLE;
                        } else
                                osd_hw.osd_afbcd[index].enable = ENABLE;
@@ -2926,17 +3465,16 @@ static void osd_pan_display_fence(struct osd_fence_map_s *fence_map)
                        }
 
                        osd_hw.reg[OSD_COLOR_MODE].update_func(index);
-                       if (!osd_hw.hwc_enable) {
+
                        /* geometry and freescale need update with ioctl */
-                               osd_hw.reg[DISP_GEOMETRY].update_func(index);
-                               if ((osd_hw.free_scale_enable[index]
-                                               && osd_update_window_axis)
-                                               || freescale_update) {
-                                       if (!osd_hw.osd_display_debug)
-                                       osd_hw.reg[DISP_FREESCALE_ENABLE]
-                                               .update_func(index);
-                                       osd_update_window_axis = false;
-                               }
+                       osd_hw.reg[DISP_GEOMETRY].update_func(index);
+                       if ((osd_hw.free_scale_enable[index]
+                                       && osd_update_window_axis)
+                                       || freescale_update) {
+                               if (!osd_hw.osd_display_debug)
+                               osd_hw.reg[DISP_FREESCALE_ENABLE]
+                                       .update_func(index);
+                               osd_update_window_axis = false;
                        }
                        if ((osd_enable != osd_hw.enable[index])
                                && skip == false) {
@@ -2951,7 +3489,7 @@ static void osd_pan_display_fence(struct osd_fence_map_s *fence_map)
                        osd_wait_vsync_hw();
                } else if (xoffset != osd_hw.pandata[index].x_start
                        || yoffset != osd_hw.pandata[index].y_start
-                       || (use_ext /*&& index == OSD1*/)) {
+                       || (use_ext)) {
                        spin_lock_irqsave(&osd_lock, lock_flags);
                        if (use_ext) {
                                osd_hw.fb_gem[index].canvas_idx =
@@ -3000,8 +3538,6 @@ static void osd_pan_display_fence(struct osd_fence_map_s *fence_map)
                                        osd_hw.dispdata_backup[index].y_start,
                                        osd_hw.dispdata_backup[index].y_end);
 
-                               osd_hw.color_info[index] =
-                                       osd_hw.color_backup[index];
                                canvas_config(osd_hw.fb_gem[index].canvas_idx,
                                        osd_hw.fb_gem[index].addr,
                                        osd_hw.fb_gem[index].width,
@@ -3021,8 +3557,7 @@ static void osd_pan_display_fence(struct osd_fence_map_s *fence_map)
                                osd_hw.pandata[index].y_start += diff_y;
                                osd_hw.pandata[index].y_end   += diff_y;
                        }
-                       if (/* index == OSD1 && */
-                               osd_hw.osd_afbcd[index].enable == ENABLE) {
+                       if (osd_hw.osd_afbcd[index].enable == ENABLE) {
                                /* osd_hw.osd_afbcd[index].phy_addr =
                                 *      (osd_hw.pandata[index].y_start /
                                 *      osd_hw.osd_afbcd[index].frame_height) *
@@ -3036,6 +3571,17 @@ static void osd_pan_display_fence(struct osd_fence_map_s *fence_map)
                                        [osd_hw.pandata[index].y_start /
                                        osd_hw.osd_afbcd[index].frame_height];
                        }
+                       color = convert_hal_format(fence_map->format);
+                       if (color) {
+                               if (color != osd_hw.color_backup[index]) {
+                                       color_mode = true;
+                                       osd_hw.color_backup[index] = color;
+                               }
+                               osd_hw.color_info[index] = color;
+                       } else {
+                               osd_log_err("fence color format error %d\n",
+                                       fence_map->format);
+                       }
                        if (color_mode)
                                osd_hw.reg[OSD_COLOR_MODE].update_func(index);
                        osd_hw.reg[DISP_GEOMETRY].update_func(index);
@@ -3082,6 +3628,203 @@ static void osd_pan_display_fence(struct osd_fence_map_s *fence_map)
        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_update_info(struct layer_fence_map_s *layer_map)
+{
+       u32 index = layer_map->fb_index;
+       const struct color_bit_define_s *color = NULL;
+       u32 ext_addr = 0;
+       void *vaddr = NULL;
+
+       if (index > OSD_MAX)
+               return;
+       /* get in fence_fd */
+       osd_hw.in_fd[index] = layer_map->in_fd;
+       osd_hw.buffer_alloc[index] = 1;
+       osd_hw.enable[index] = layer_map->enable;
+       osd_hw.osd_afbcd[index].enable =
+               (layer_map->afbc_inter_format & AFBC_EN) >> 31;
+       /* Todo: */
+       if (layer_map->ext_addr && layer_map->src_w
+               && layer_map->src_h) {
+               if (!osd_hw.osd_afbcd[index].enable) {
+                       osd_hw.fb_gem[index].canvas_idx =
+                               osd_extra_idx[index][ext_canvas_id[index]];
+                       ext_canvas_id[index] ^= 1;
+                       osd_hw.osd_afbcd[index].enable = DISABLE;
+               } else
+                       osd_hw.osd_afbcd[index].enable = ENABLE;
+               color = convert_hal_format(layer_map->format);
+               if (color) {
+                       osd_hw.color_info[index] = color;
+               } else
+                       osd_log_err("fence color format error %d\n",
+                               layer_map->format);
+
+               if (DIRECT_COMPOSE_MODE !=
+                       layer_map->compose_type)
+                       return;
+               ext_addr = layer_map->ext_addr;
+               #if 0
+               ext_addr = ext_addr +
+                       layer_map->byte_stride *
+                       layer_map->src_y;
+               #endif
+               vaddr = phys_to_virt(ext_addr);
+               if (!osd_hw.osd_afbcd[index].enable) {
+                       canvas_config(osd_hw.fb_gem[index].canvas_idx,
+                               ext_addr,
+                               layer_map->byte_stride,
+                               layer_map->src_h,
+                               CANVAS_ADDR_NOWRAP,
+                               CANVAS_BLKMODE_LINEAR);
+               } else {
+                       osd_hw.osd_afbcd[index].phy_addr = ext_addr;
+                       if (osd_hw.osd_meson_dev.afbc_type ==
+                               MESON_AFBC) {
+                               osd_hw.osd_afbcd[index].frame_width =
+                                       layer_map->src_w;
+                               osd_hw.osd_afbcd[index].frame_height =
+                                       layer_map->src_h;
+                               if (layer_map->src_w <= 128)
+                                       osd_hw.osd_afbcd[index]
+                                               .conv_lbuf_len = 32;
+                               else if (layer_map->src_w <= 256)
+                                       osd_hw.osd_afbcd[index]
+                                               .conv_lbuf_len = 64;
+                               else if (layer_map->src_w <= 512)
+                                       osd_hw.osd_afbcd[index]
+                                               .conv_lbuf_len = 128;
+                               else if (layer_map->src_w <= 1024)
+                                       osd_hw.osd_afbcd[index]
+                                               .conv_lbuf_len = 256;
+                               else if (layer_map->src_w <= 2048)
+                                       osd_hw.osd_afbcd[index]
+                                               .conv_lbuf_len = 512;
+                               else
+                                       osd_hw.osd_afbcd[index]
+                                               .conv_lbuf_len = 1024;
+                       } else if (osd_hw.osd_meson_dev
+                               .afbc_type == MALI_AFBC) {
+                               osd_hw.osd_afbcd[index].frame_width =
+                                       layer_map->byte_stride / 4;
+                                       //BYTE_32_ALIGNED(layer_map->src_w);
+                               osd_hw.osd_afbcd[index].frame_height =
+                                       BYTE_8_ALIGNED(layer_map->src_h);
+                       }
+               }
+               osd_hw.screen_base[index] = vaddr;
+               osd_hw.screen_size[index] =
+                       layer_map->byte_stride * layer_map->src_h;
+               /* just get para, need update via do_hwc */
+               osd_hw.order[index] = layer_map->zorder;
+               switch (layer_map->blend_mode) {
+               case BLEND_MODE_PREMULTIPLIED:
+                       osd_hw.premult_en[index] = 1;
+                       break;
+               case BLEND_MODE_COVERAGE:
+               case BLEND_MODE_NONE:
+               case BLEND_MODE_INVALID:
+                       osd_hw.premult_en[index] = 0;
+                       break;
+               }
+               //Todo: fence_map.plane_alpha
+               osd_hw.osd_afbcd[index].inter_format =
+                       layer_map->afbc_inter_format & 0x7fffffff;
+               osd_hw.src_data[index].x = layer_map->src_x;
+               osd_hw.src_data[index].y = layer_map->src_y;
+               osd_hw.src_data[index].w = layer_map->src_w;
+               osd_hw.src_data[index].h = layer_map->src_h;
+               osd_hw.dst_data[index].x = layer_map->dst_x;
+               osd_hw.dst_data[index].y = layer_map->dst_y;
+               osd_hw.dst_data[index].w = layer_map->dst_w;
+               osd_hw.dst_data[index].h = layer_map->dst_h;
+       }
+}
+
+static void osd_pan_display_layers_fence(
+       struct osd_layers_fence_map_s *fence_map)
+{
+       int i = 0, index = 0;
+       int ret;
+       int osd_count = osd_hw.osd_meson_dev.osd_count;
+       /* osd_count need -1 when VIU2 enable */
+       struct layer_fence_map_s *layer_map = NULL;
+
+       osd_set_background_size(
+               fence_map->background_w, fence_map->background_h);
+       clear_backup_info();
+       for (i = 0; i < osd_count; i++) {
+               layer_map = &fence_map->layer_map[i];
+               index = layer_map->fb_index;
+               if (i != layer_map->fb_index) {
+                       osd_hw.screen_base[i] = NULL;
+                       osd_hw.screen_size[i] = 0;
+                       osd_hw.enable[i] = 0;
+                       continue;
+               }
+               /* wait in fence */
+               if (timeline_created && osd_hw.enable[index]) {
+                       ret = osd_wait_buf_ready_combine(layer_map);
+                       if (ret < 0)
+                               osd_log_dbg("fence wait ret %d\n", ret);
+               }
+               osd_pan_display_update_info(layer_map);
+               save_layer_info(layer_map);
+       }
+       /* set hw regs */
+       if (osd_hw.osd_display_debug != OSD_DISP_DEBUG)
+               osd_setting_blend();
+       /* signal out fence */
+       if (timeline_created) {
+               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_log_dbg("signal out fence\n");
+                               osd_hw.osd_debug.osd_single_step--;
+                       } else
+                               osd_hw.osd_debug.wait_fence_release = true;
+               } else
+                       osd_timeline_increase();
+       }
+       /* clear osd layer's order */
+       for (i = 0; i < osd_count; i++) {
+               layer_map = &fence_map->layer_map[i];
+               if (layer_map->in_fence)
+               osd_put_fenceobj(layer_map->in_fence);
+               osd_hw.order[i] = 0;
+       }
+}
+#endif
+
+void osd_pan_display_hw(u32 index, unsigned int xoffset, unsigned int yoffset)
+{
+       long diff_x, diff_y;
+
+       if (index >= HW_OSD_COUNT)
+               return;
+       if (xoffset != osd_hw.pandata[index].x_start
+           || yoffset != osd_hw.pandata[index].y_start) {
+               diff_x = xoffset - osd_hw.pandata[index].x_start;
+               diff_y = yoffset - osd_hw.pandata[index].y_start;
+               osd_hw.pandata[index].x_start += diff_x;
+               osd_hw.pandata[index].x_end   += diff_x;
+               osd_hw.pandata[index].y_start += diff_y;
+               osd_hw.pandata[index].y_end   += diff_y;
+               add_to_update_list(index, DISP_GEOMETRY);
+               if (osd_hw.osd_fps_start)
+                       osd_hw.osd_fps++;
+               /* osd_wait_vsync_hw(); */
+       }
+#ifdef CONFIG_AMLOGIC_MEDIA_FB_EXT
+       osd_ext_clone_pan(index);
+#endif
        osd_log_dbg2("offset[%d-%d]x[%d-%d]y[%d-%d]\n",
                    xoffset, yoffset,
                    osd_hw.pandata[index].x_start,
@@ -3089,545 +3832,85 @@ static void osd_pan_display_fence(struct osd_fence_map_s *fence_map)
                    osd_hw.pandata[index].y_start,
                    osd_hw.pandata[index].y_end);
 }
-#else
-static bool osd_direct_compose_pan_display(struct osd_fence_map_s *fence_map)
+
+void osd_get_info(u32 index, u32 *addr, u32 *width, u32 *height)
 {
-       u32 index = fence_map->fb_index;
-       u32 ext_addr = fence_map->ext_addr;
-       u32 width_src, width_dst, height_src, height_dst;
-       u32 x_start, x_end, y_start, y_end;
-       bool freescale_update = false;
-       struct pandata_s freescale_dst[HW_OSD_COUNT];
-       void *vaddr = NULL;
+       *addr = osd_hw.fb_gem[index].addr;
+       *width = osd_hw.fb_gem[index].width;
+       *height = osd_hw.fb_gem[index].yres;
+}
 
-       ext_addr = ext_addr + fence_map->byte_stride * fence_map->yoffset;
-       vaddr = phys_to_virt(ext_addr);
+static  void  osd_update_disp_scale_enable(u32 index)
+{
+       u32 osd2_cursor = 0;
+       struct hw_osd_reg_s *osd_reg = &hw_osd_reg_array[index];
 
-       if (!osd_hw.osd_afbcd[index].enable) {
-               canvas_config(osd_hw.fb_gem[index].canvas_idx,
-                       ext_addr,
-                       fence_map->byte_stride,
-                       fence_map->height,
-                       CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR);
-       } else {
-               osd_hw.osd_afbcd[index].phy_addr = ext_addr;
-               osd_hw.osd_afbcd[index].frame_width =
-                       fence_map->width;
-               osd_hw.osd_afbcd[index].frame_height =
-                       fence_map->height;
-               if (osd_hw.osd_meson_dev.afbc_type == MESON_AFBC) {
-                       if (fence_map->width <= 128)
-                               osd_hw.osd_afbcd[index].conv_lbuf_len = 32;
-                       else if (fence_map->width <= 256)
-                               osd_hw.osd_afbcd[index].conv_lbuf_len = 64;
-                       else if (fence_map->width <= 512)
-                               osd_hw.osd_afbcd[index].conv_lbuf_len = 128;
-                       else if (fence_map->width <= 1024)
-                               osd_hw.osd_afbcd[index].conv_lbuf_len = 256;
-                       else if (fence_map->width <= 2048)
-                               osd_hw.osd_afbcd[index].conv_lbuf_len = 512;
-                       else
-                               osd_hw.osd_afbcd[index].conv_lbuf_len = 1024;
-               } else if (osd_hw.osd_meson_dev.afbc_type
-                       == MALI_AFBC) {
+       if (osd_hw.hw_cursor_en)
+               osd2_cursor = 1;
 
+       if (osd_hw.scale[index].h_enable) {
+               VSYNCOSD_SET_MPEG_REG_MASK(
+                       osd_reg->osd_blk0_cfg_w0, 3 << 12);
+               if ((index == OSD2) && osd2_cursor) {
+                       VSYNCOSD_CLR_MPEG_REG_MASK(
+                               osd_reg->osd_blk0_cfg_w0, 3 << 12);
                }
+       } else
+               VSYNCOSD_CLR_MPEG_REG_MASK(
+                       osd_reg->osd_blk0_cfg_w0, 3 << 12);
+
+       if (osd_hw.scan_mode[index] != SCAN_MODE_INTERLACE) {
+               if (osd_hw.scale[index].v_enable) {
+                       VSYNCOSD_SET_MPEG_REG_MASK(
+                               osd_reg->osd_blk0_cfg_w0, 1 << 14);
+                       if ((index == OSD2) && osd2_cursor) {
+                               VSYNCOSD_CLR_MPEG_REG_MASK(
+                                       osd_reg->osd_blk0_cfg_w0, 1 << 14);
+                       }
+               } else
+                       VSYNCOSD_CLR_MPEG_REG_MASK(
+                               osd_reg->osd_blk0_cfg_w0, 1 << 14);
        }
+       remove_from_update_list(index, DISP_SCALE_ENABLE);
+}
 
-       width_dst = osd_hw.free_dst_data_backup[index].x_end -
-               osd_hw.free_dst_data_backup[index].x_start + 1;
-       width_src = osd_hw.free_src_data_backup[index].x_end -
-               osd_hw.free_src_data_backup[index].x_start + 1;
+static void osd_set_dummy_data(u32 index, u32 alpha)
+{
+       VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[index].osd_sc_dummy_data,
+               osd_hw.osd_meson_dev.dummy_data | alpha);
+}
 
-       height_dst = osd_hw.free_dst_data_backup[index].y_end -
-               osd_hw.free_dst_data_backup[index].y_start + 1;
-       height_src = osd_hw.free_src_data_backup[index].y_end -
-               osd_hw.free_src_data_backup[index].y_start + 1;
+static void osd_update_disp_freescale_enable(u32 index)
+{
+       int hf_phase_step, vf_phase_step;
+       int src_w, src_h, dst_w, dst_h;
+       int bot_ini_phase;
+       int vsc_ini_rcv_num, vsc_ini_rpt_p0_num;
+       int vsc_bot_rcv_num = 0, vsc_bot_rpt_p0_num = 0;
+       int hsc_ini_rcv_num, hsc_ini_rpt_p0_num;
+       int hf_bank_len = 4;
+       int vf_bank_len = 4;
+       struct hw_osd_reg_s *osd_reg = &hw_osd_reg_array[index];
+       u32 data32 = 0x0;
 
-       osd_hw.screen_base[index] = vaddr;
-       osd_hw.screen_size[index] = fence_map->byte_stride * fence_map->height;
-       if (osd_hw.free_scale_enable[index] ||
-               (width_src != width_dst) ||
-               (height_src != height_dst) ||
-               (fence_map->width != fence_map->dst_w) ||
-               (fence_map->height != fence_map->dst_h)) {
-               osd_hw.free_scale[index].h_enable = 1;
-               osd_hw.free_scale[index].v_enable = 1;
-               osd_hw.free_scale_enable[index] = 0x10001;
-               osd_hw.free_scale_mode[index] = 1;
-               if (osd_hw.free_scale_enable[index] !=
-                       osd_hw.free_scale_enable_backup[index]) {
-                       osd_set_scan_mode(index);
-                       freescale_update = true;
-               }
+       if (osd_hw.osd_meson_dev.osd_ver != OSD_HIGH_ONE)
+               osd_reg = &hw_osd_reg_array[0];
 
-               osd_hw.pandata[index].x_start = fence_map->xoffset;
-               osd_hw.pandata[index].x_end =
-                       fence_map->xoffset + fence_map->width - 1;
-               osd_hw.pandata[index].y_start = 0;
-               osd_hw.pandata[index].y_end = fence_map->height - 1;
+       if (osd_hw.scale_workaround)
+               vf_bank_len = 2;
+       else
+               vf_bank_len = 4;
 
-               freescale_dst[index].x_start =
-                       osd_hw.free_dst_data_backup[index].x_start +
-                       (fence_map->dst_x * width_dst) / width_src;
-               freescale_dst[index].x_end =
-                       osd_hw.free_dst_data_backup[index].x_start +
-                       ((fence_map->dst_x + fence_map->dst_w) *
-                       width_dst) / width_src - 1;
-
-               freescale_dst[index].y_start =
-                       osd_hw.free_dst_data_backup[index].y_start +
-                       (fence_map->dst_y * height_dst) / height_src;
-               freescale_dst[index].y_end =
-                       osd_hw.free_dst_data_backup[index].y_start +
-                       ((fence_map->dst_y + fence_map->dst_h) *
-                       height_dst) / height_src - 1;
-               if (osd_hw.osd_reverse[index] == REVERSE_TRUE) {
-                       x_start = osd_hw.vinfo_width
-                               - freescale_dst[index].x_end - 1;
-                       y_start = osd_hw.vinfo_height
-                               - freescale_dst[index].y_end - 1;
-                       x_end = osd_hw.vinfo_width
-                               - freescale_dst[index].x_start - 1;
-                       y_end = osd_hw.vinfo_height
-                               - 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
-                               - freescale_dst[index].x_end - 1;
-                       x_end = osd_hw.vinfo_width
-                               - 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
-                               - freescale_dst[index].y_end - 1;
-                       y_end = osd_hw.vinfo_height
-                               - freescale_dst[index].y_start - 1;
-                       freescale_dst[index].y_start = y_start;
-                       freescale_dst[index].y_end = y_end;
-               }
-               if (memcmp(&(osd_hw.free_src_data[index]),
-                       &osd_hw.pandata[index],
-                       sizeof(struct pandata_s)) != 0 ||
-                       memcmp(&(osd_hw.free_dst_data[index]),
-                       &freescale_dst[index],
-                       sizeof(struct pandata_s)) != 0) {
-                       memcpy(&(osd_hw.free_src_data[index]),
-                               &osd_hw.pandata[index],
-                               sizeof(struct pandata_s));
-                       memcpy(&(osd_hw.free_dst_data[index]),
-                               &freescale_dst[index],
-                               sizeof(struct pandata_s));
-                       freescale_update = true;
-
-                       if ((height_dst != height_src) ||
-                               (width_dst != width_src))
-                               osd_set_dummy_data(index, 0);
-                       else
-                               osd_set_dummy_data(index, 0xff);
-                       osd_log_dbg("direct pandata x=%d,x_end=%d,y=%d,y_end=%d,width=%d,height=%d\n",
-                               osd_hw.pandata[index].x_start,
-                               osd_hw.pandata[index].x_end,
-                               osd_hw.pandata[index].y_start,
-                               osd_hw.pandata[index].y_end,
-                               fence_map->width,
-                               fence_map->height);
-                       osd_log_dbg("fence_map:xoffset=%d,yoffset=%d\n",
-                               fence_map->xoffset,
-                               fence_map->yoffset);
-                       osd_log_dbg("fence_map:dst_x=%d,dst_y=%d,dst_w=%d,dst_h=%d,byte_stride=%d\n",
-                               fence_map->dst_x,
-                               fence_map->dst_y,
-                               fence_map->dst_w,
-                               fence_map->dst_h,
-                               fence_map->byte_stride);
-               }
-       } else {
-               osd_hw.pandata[index].x_start = 0;
-               osd_hw.pandata[index].x_end = fence_map->width - 1;
-               osd_hw.pandata[index].y_start = 0;
-               osd_hw.pandata[index].y_end = fence_map->height - 1;
-
-               osd_hw.dispdata[index].x_start = fence_map->dst_x;
-               osd_hw.dispdata[index].x_end =
-                       fence_map->dst_x + fence_map->dst_w - 1;
-               osd_hw.dispdata[index].y_start = fence_map->dst_y;
-               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
-                               - osd_hw.dispdata[index].x_end - 1;
-                       y_start = osd_hw.vinfo_height
-                               - osd_hw.dispdata[index].y_end - 1;
-                       x_end = osd_hw.vinfo_width
-                               - osd_hw.dispdata[index].x_start - 1;
-                       y_end = osd_hw.vinfo_height
-                               - 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
-                               - osd_hw.dispdata[index].x_end - 1;
-                       x_end = osd_hw.vinfo_width
-                               - 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
-                               - osd_hw.dispdata[index].y_end - 1;
-                       y_end = osd_hw.vinfo_height
-                               - osd_hw.dispdata[index].y_start - 1;
-                       osd_hw.dispdata[index].y_start = y_start;
-                       osd_hw.dispdata[index].y_end = y_end;
-               }
-       }
-       fence_map->ext_addr = ext_addr;
-       return freescale_update;
-}
-
-static void osd_pan_display_fence(struct osd_fence_map_s *fence_map)
-{
-       s32 ret = 1;
-       long diff_x, diff_y;
-       u32 index = fence_map->fb_index;
-       u32 xoffset = fence_map->xoffset;
-       u32 yoffset = fence_map->yoffset;
-       const struct color_bit_define_s *color = NULL;
-       bool color_mode = false;
-       bool freescale_update = false;
-       u32 osd_enable = 0;
-       bool skip = false;
-       const struct vinfo_s *vinfo;
-
-       if (index >= 2)
-               return;
-       if (timeline_created) { /* out fence created success. */
-               ret = osd_wait_buf_ready(fence_map);
-               if (ret < 0)
-                       osd_log_dbg("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 (fence_map->op == 0xffffffff)
-                       skip = true;
-               else
-                       osd_enable = (fence_map->op & 1) ? DISABLE : ENABLE;
-               /* need update via direct render interface later */
-               fence_map->afbc_en = osd_hw.osd_afbcd[OSD1].enable;
-               vinfo = get_current_vinfo();
-               if (vinfo) {
-                       osd_hw.vinfo_width = vinfo->width;
-                       osd_hw.vinfo_height = vinfo->height;
-               }
-               if (fence_map->ext_addr && fence_map->width
-                               && fence_map->height) {
-                       spin_lock_irqsave(&osd_lock, lock_flags);
-                       use_ext = true;
-                       if (!fence_map->afbc_en) {
-                               osd_hw.fb_gem[index].canvas_idx =
-                                       osd_extra_idx[index][ext_canvas_id];
-                               ext_canvas_id ^= 1;
-                               osd_hw.osd_afbcd[index].enable = DISABLE;
-                       } else
-                               osd_hw.osd_afbcd[index].enable = ENABLE;
-
-                       color = convert_hal_format(fence_map->format);
-                       if (color) {
-                               osd_hw.color_info[index] = color;
-                       } else
-                               osd_log_err("fence color format error %d\n",
-                                       fence_map->format);
-
-                       if (DIRECT_COMPOSE_MODE ==
-                               fence_map->compose_type)
-                               freescale_update =
-                               osd_direct_compose_pan_display(fence_map);
-                       else if (GE2D_COMPOSE_MODE ==
-                               fence_map->compose_type) {
-                               freescale_update =
-                               osd_ge2d_compose_pan_display(fence_map);
-                               if (freescale_update)
-                                       osd_set_dummy_data(index, 0xff);
-                       }
-
-                       osd_hw.reg[OSD_COLOR_MODE].update_func(index);
-                       osd_hw.reg[DISP_GEOMETRY].update_func(index);
-                       if ((osd_hw.free_scale_enable[index]
-                                       && osd_update_window_axis)
-                                       || freescale_update) {
-                               if (!osd_hw.osd_display_debug)
-                               osd_hw.reg[DISP_FREESCALE_ENABLE]
-                                       .update_func(index);
-                               osd_update_window_axis = false;
-                       }
-                       if ((osd_enable != osd_hw.enable[index])
-                               && skip == false) {
-                               osd_hw.enable[index] = osd_enable;
-                               if (!osd_hw.osd_display_debug)
-                                       osd_hw.reg[OSD_ENABLE]
-                                       .update_func(index);
-                       }
-                       spin_unlock_irqrestore(&osd_lock, lock_flags);
-                       osd_wait_vsync_hw();
-               } else if (xoffset != osd_hw.pandata[index].x_start
-                       || yoffset != osd_hw.pandata[index].y_start
-                       || (use_ext && index == OSD1)) {
-                       spin_lock_irqsave(&osd_lock, lock_flags);
-                       if ((use_ext)) {
-                               osd_hw.fb_gem[index].canvas_idx =
-                                       OSD1_CANVAS_INDEX;
-
-                               osd_hw.pandata[index].x_start = xoffset;
-                               osd_hw.pandata[index].x_end   = xoffset +
-                                       osd_hw.fb_gem[index].xres - 1;
-                               osd_hw.pandata[index].y_start = yoffset;
-                               osd_hw.pandata[index].y_end   = yoffset +
-                                       osd_hw.fb_gem[index].yres - 1;
-                               osd_hw.screen_base[index] =
-                                       osd_hw.screen_base_backup[index];
-                               osd_hw.screen_size[index] =
-                                       osd_hw.screen_size_backup[index];
-
-                               osd_hw.dispdata[index].x_start =
-                                       osd_hw.dispdata_backup[index].x_start;
-                               osd_hw.dispdata[index].x_end =
-                                       osd_hw.dispdata_backup[index].x_end;
-                               osd_hw.dispdata[index].y_start =
-                                       osd_hw.dispdata_backup[index].y_start;
-                               osd_hw.dispdata[index].y_end =
-                                       osd_hw.dispdata_backup[index].y_end;
-
-                               /* restore free_scale info */
-                               osd_hw.free_scale[index].h_enable =
-                               osd_hw.free_scale_backup[index].h_enable;
-                               osd_hw.free_scale[index].v_enable =
-                               osd_hw.free_scale_backup[index].v_enable;
-                               osd_hw.free_scale_enable[index] =
-                                       osd_hw.free_scale_enable_backup[index];
-                               osd_hw.free_scale_mode[index] =
-                                       osd_hw.free_scale_mode_backup[index];
-
-                               memcpy(&osd_hw.free_src_data[index],
-                                       &osd_hw.free_src_data_backup[index],
-                                       sizeof(struct pandata_s));
-                               memcpy(&osd_hw.free_dst_data[index],
-                                       &osd_hw.free_dst_data_backup[index],
-                                       sizeof(struct pandata_s));
-                               osd_set_dummy_data(index, 0xff);
-                               osd_log_dbg("switch back dispdata_backup x=%d,x_end=%d,y=%d,y_end=%d\n",
-                                       osd_hw.dispdata_backup[index].x_start,
-                                       osd_hw.dispdata_backup[index].x_end,
-                                       osd_hw.dispdata_backup[index].y_start,
-                                       osd_hw.dispdata_backup[index].y_end);
-
-                               osd_hw.color_info[index] =
-                                       osd_hw.color_backup[index];
-                               canvas_config(osd_hw.fb_gem[index].canvas_idx,
-                                       osd_hw.fb_gem[index].addr,
-                                       osd_hw.fb_gem[index].width,
-                                       osd_hw.fb_gem[index].height,
-                                       CANVAS_ADDR_NOWRAP,
-                                       CANVAS_BLKMODE_LINEAR);
-                               use_ext = false;
-                               color_mode = true;
-                               freescale_update = true;
-                       } else {
-                               diff_x = xoffset -
-                                       osd_hw.pandata[index].x_start;
-                               diff_y = yoffset -
-                                       osd_hw.pandata[index].y_start;
-                               osd_hw.pandata[index].x_start += diff_x;
-                               osd_hw.pandata[index].x_end   += diff_x;
-                               osd_hw.pandata[index].y_start += diff_y;
-                               osd_hw.pandata[index].y_end   += diff_y;
-                       }
-                       if (/* index == OSD1 && */
-                               osd_hw.osd_afbcd[index].enable == ENABLE) {
-                               /* osd_hw.osd_afbcd[index].phy_addr =
-                                *      (osd_hw.pandata[index].y_start /
-                                *      osd_hw.osd_afbcd[index].frame_height) *
-                                *      osd_hw.osd_afbcd[index].frame_height *
-                                *  osd_hw.fb_gem[index].width;
-                                *  osd_hw.osd_afbcd[index].phy_addr +=
-                                *  osd_hw.fb_gem[index].addr;
-                                */
-                               osd_hw.osd_afbcd[index].phy_addr =
-                                       osd_hw.osd_afbcd[index].addr
-                                       [osd_hw.pandata[index].y_start /
-                                       osd_hw.osd_afbcd[index].frame_height];
-                       }
-                       if (color_mode)
-                               osd_hw.reg[OSD_COLOR_MODE].update_func(index);
-                       osd_hw.reg[DISP_GEOMETRY].update_func(index);
-                       if ((osd_hw.free_scale_enable[index]
-                                       && osd_update_window_axis)
-                                       || (osd_hw.free_scale_enable[index]
-                                       && freescale_update)) {
-                               if (!osd_hw.osd_display_debug)
-                                       osd_hw.reg[DISP_FREESCALE_ENABLE]
-                                               .update_func(index);
-                               osd_update_window_axis = false;
-                       }
-                       if ((osd_enable != osd_hw.enable[index])
-                               && skip == false) {
-                               osd_hw.enable[index] = osd_enable;
-                               if (!osd_hw.osd_display_debug)
-                                       osd_hw.reg[OSD_ENABLE]
-                                       .update_func(index);
-                       }
-                       spin_unlock_irqrestore(&osd_lock, lock_flags);
-                       osd_wait_vsync_hw();
-               } else if ((osd_enable != osd_hw.enable[index])
-                                       && skip == false) {
-                       spin_lock_irqsave(&osd_lock, lock_flags);
-                       osd_hw.enable[index] = osd_enable;
-                       if (!osd_hw.osd_display_debug)
-                               osd_hw.reg[OSD_ENABLE]
-                               .update_func(index);
-                       spin_unlock_irqrestore(&osd_lock, lock_flags);
-                       osd_wait_vsync_hw();
-               }
-       }
-       if (timeline_created) {
-               if (ret)
-                       osd_timeline_increase();
-               else
-                       osd_log_err("------NOT signal out_fence ERROR\n");
-       }
-#ifdef CONFIG_AMLOGIC_MEDIA_FB_EXT
-       if (ret)
-               osd_ext_clone_pan(index);
-#endif
-       osd_log_dbg2("offset[%d-%d]x[%d-%d]y[%d-%d]\n",
-                   xoffset, yoffset,
-                   osd_hw.pandata[index].x_start,
-                   osd_hw.pandata[index].x_end,
-                   osd_hw.pandata[index].y_start,
-                   osd_hw.pandata[index].y_end);
-}
-
-#endif
-
-#endif
-
-void osd_pan_display_hw(u32 index, unsigned int xoffset, unsigned int yoffset)
-{
-       long diff_x, diff_y;
-
-       if (index >= HW_OSD_COUNT)
-               return;
-       if (xoffset != osd_hw.pandata[index].x_start
-           || yoffset != osd_hw.pandata[index].y_start) {
-               diff_x = xoffset - osd_hw.pandata[index].x_start;
-               diff_y = yoffset - osd_hw.pandata[index].y_start;
-               osd_hw.pandata[index].x_start += diff_x;
-               osd_hw.pandata[index].x_end   += diff_x;
-               osd_hw.pandata[index].y_start += diff_y;
-               osd_hw.pandata[index].y_end   += diff_y;
-               add_to_update_list(index, DISP_GEOMETRY);
-               if (osd_hw.osd_fps_start)
-                       osd_hw.osd_fps++;
-               /* osd_wait_vsync_hw(); */
-       }
-#ifdef CONFIG_AMLOGIC_MEDIA_FB_EXT
-       osd_ext_clone_pan(index);
-#endif
-       osd_log_dbg2("offset[%d-%d]x[%d-%d]y[%d-%d]\n",
-                   xoffset, yoffset,
-                   osd_hw.pandata[index].x_start,
-                   osd_hw.pandata[index].x_end,
-                   osd_hw.pandata[index].y_start,
-                   osd_hw.pandata[index].y_end);
-}
-
-void osd_get_info(u32 index, u32 *addr, u32 *width, u32 *height)
-{
-       *addr = osd_hw.fb_gem[index].addr;
-       *width = osd_hw.fb_gem[index].width;
-       *height = osd_hw.fb_gem[index].yres;
-}
-
-static  void  osd_update_disp_scale_enable(u32 index)
-{
-       u32 osd2_cursor = 0;
-       struct hw_osd_reg_s *osd_reg = &hw_osd_reg_array[index];
-
-       if (osd_hw.hw_cursor_en)
-               osd2_cursor = 1;
-
-       if (osd_hw.scale[index].h_enable) {
-               VSYNCOSD_SET_MPEG_REG_MASK(
-                       osd_reg->osd_blk0_cfg_w0, 3 << 12);
-               if ((index == OSD2) && osd2_cursor) {
-                       VSYNCOSD_CLR_MPEG_REG_MASK(
-                               osd_reg->osd_blk0_cfg_w0, 3 << 12);
-               }
-       } else
-               VSYNCOSD_CLR_MPEG_REG_MASK(
-                       osd_reg->osd_blk0_cfg_w0, 3 << 12);
-
-       if (osd_hw.scan_mode[index] != SCAN_MODE_INTERLACE) {
-               if (osd_hw.scale[index].v_enable) {
-                       VSYNCOSD_SET_MPEG_REG_MASK(
-                               osd_reg->osd_blk0_cfg_w0, 1 << 14);
-                       if ((index == OSD2) && osd2_cursor) {
-                               VSYNCOSD_CLR_MPEG_REG_MASK(
-                                       osd_reg->osd_blk0_cfg_w0, 1 << 14);
-                       }
-               } else
-                       VSYNCOSD_CLR_MPEG_REG_MASK(
-                               osd_reg->osd_blk0_cfg_w0, 1 << 14);
-       }
-       remove_from_update_list(index, DISP_SCALE_ENABLE);
-}
-
-static void osd_set_dummy_data(u32 index, u32 alpha)
-{
-       VSYNCOSD_WR_MPEG_REG(hw_osd_reg_array[index].osd_sc_dummy_data,
-               osd_hw.osd_meson_dev.dummy_data | alpha);
-}
-
-static void osd_update_disp_freescale_enable(u32 index)
-{
-       int hf_phase_step, vf_phase_step;
-       int src_w, src_h, dst_w, dst_h;
-       int bot_ini_phase;
-       int vsc_ini_rcv_num, vsc_ini_rpt_p0_num;
-       int vsc_bot_rcv_num = 0, vsc_bot_rpt_p0_num = 0;
-       int hsc_ini_rcv_num, hsc_ini_rpt_p0_num;
-       int hf_bank_len = 4;
-       int vf_bank_len = 4;
-       struct hw_osd_reg_s *osd_reg = &hw_osd_reg_array[index];
-       u32 data32 = 0x0;
-
-       if (osd_hw.osd_meson_dev.osd_ver != OSD_HIGH_ONE)
-               osd_reg = &hw_osd_reg_array[0];
-
-       if (osd_hw.scale_workaround)
-               vf_bank_len = 2;
-       else
-               vf_bank_len = 4;
-
-       if (osd_hw.bot_type == 1) {
-               vsc_bot_rcv_num = 4;
-               vsc_bot_rpt_p0_num = 1;
-       } else if (osd_hw.bot_type == 2) {
-               vsc_bot_rcv_num = 6;
-               vsc_bot_rpt_p0_num = 2;
-       } else if (osd_hw.bot_type == 3) {
-               vsc_bot_rcv_num = 8;
-               vsc_bot_rpt_p0_num = 3;
-       }
+       if (osd_hw.bot_type == 1) {
+               vsc_bot_rcv_num = 4;
+               vsc_bot_rpt_p0_num = 1;
+       } else if (osd_hw.bot_type == 2) {
+               vsc_bot_rcv_num = 6;
+               vsc_bot_rpt_p0_num = 2;
+       } else if (osd_hw.bot_type == 3) {
+               vsc_bot_rcv_num = 8;
+               vsc_bot_rpt_p0_num = 3;
+       }
 
        hsc_ini_rcv_num = hf_bank_len;
        vsc_ini_rcv_num = vf_bank_len;
@@ -3723,7 +4006,6 @@ static void osd_update_disp_freescale_enable(u32 index)
                VSYNCOSD_WR_MPEG_REG(
                        osd_reg->osd_vsc_init_phase, data32);
        }
-       osd_log_dbg("osd_hw.hwc_enable=%x\n", osd_hw.hwc_enable);
        if ((osd_hw.osd_meson_dev.osd_ver == OSD_HIGH_ONE)
                && (!osd_hw.hwc_enable)) {
                osd_setting_blending_scope(index);
@@ -3768,8 +4050,6 @@ static void osd_update_coef(u32 index)
                } else
                        need_update_coef = false;
        }
-       osd_log_dbg("osd vf scaler need_update_coef=%d\n",
-               need_update_coef);
        if (need_update_coef) {
                vf_coef = filter_table[use_v_filter_mode];
                osd_reg_set_bits(OSD_SCALE_COEF_IDX, 0x0000, 0, 9);
@@ -3782,8 +4062,6 @@ static void osd_update_coef(u32 index)
                need_update_coef = true;
        }
        hf_coef = filter_table[use_h_filter_mode];
-       osd_log_dbg("osd hf scaler need_update_coef=%d\n",
-               need_update_coef);
        if (need_update_coef) {
                osd_reg_set_bits(OSD_SCALE_COEF_IDX, 0x0100, 0, 9);
                for (i = 0; i < 33; i++)
@@ -3913,10 +4191,10 @@ static void osd_update_color_mode(u32 index)
                                 */
                        } else if (
                        osd_hw.osd_meson_dev.afbc_type == MALI_AFBC) {
-                               u32  bpp, pixel_format;
+                               u32 bpp, pixel_format;
                                u32 line_stride, output_stride;
-                               //u32 fmt_mode = COLOR_INDEX_32_ABGR;
                                u32 aligned_32 = 1; /* need get from hwc line */
+                               #if 0
                                u32 super_block_aspect = MALI_AFBC_16X16_PIXEL;
                                /* 00:16x16 pixels
                                 * 01:32x8 pixels
@@ -3929,6 +4207,7 @@ static void osd_update_color_mode(u32 index)
                                /* 0  Internal YUV transform off.
                                 * 1  Internal YUV transform on.
                                 */
+                               #endif
                                u32 afbc_color_reorder = 0x1234;
                                /* 0x4321 = ABGR
                                 * 0x1234 = RGBA
@@ -3945,18 +4224,10 @@ static void osd_update_color_mode(u32 index)
                                        pixel_format,
                                        osd_hw.osd_afbcd[index].frame_width,
                                        aligned_32);
-                               super_block_aspect =
-                                       osd_hw.osd_afbcd[index].inter_format
-                                       >> 1 & 0x3;
-                               block_split =
-                                       osd_hw.osd_afbcd[index].inter_format
-                                       & 0x1;
                                VSYNCOSD_WR_MPEG_REG(
                                        osd_reg->afbc_format_specifier_s,
-                                       (super_block_aspect & 0x3) << 16 |
-                                       (block_split & 0x1) << 9        |
-                                       (yuv_transform & 0x1) << 8      |
-                                       (pixel_format & 0xf));
+                                       (osd_hw.osd_afbcd[index].inter_format |
+                                       (pixel_format & 0xf)));
                                VSYNCOSD_WR_MPEG_REG_BITS(
                                        osd_reg->osd_mali_unpack_ctrl,
                                        afbc_color_reorder,
@@ -3964,13 +4235,9 @@ static void osd_update_color_mode(u32 index)
                                VSYNCOSD_WR_MPEG_REG_BITS(
                                        osd_reg->osd_blk2_cfg_w4,
                                        line_stride, 0, 12);
-                               osd_log_dbg("line_stride=%x\n",
-                                       line_stride);
                                output_stride =
                                        osd_hw.osd_afbcd[index].frame_width
                                        * bpp;
-                               osd_log_dbg("output_stride=%x\n",
-                                       output_stride);
                                VSYNCOSD_WR_MPEG_REG(
                                        osd_reg->afbc_output_buf_stride_s,
                                        output_stride);
@@ -4075,7 +4342,6 @@ static void osd_update_enable(u32 index)
                                VSYNCOSD_WR_MPEG_REG_BITS(
                                        VPU_MAFBC_SURFACE_CFG,
                                        1, index, 1);
-                               osd_log_dbg("set surface index=%d\n", index);
                                osd_hw.osd_afbcd[index].afbc_start = 1;
                        } else {
                                /* disable mali afbc */
@@ -4294,6 +4560,7 @@ void insert_sort(u32 *array, int length)
        int i = 0, j = 0;
        u32 temp;
 
+       /* decrease */
        for (j = 0; j < length; j++) {
                for (i = j + 1; i <= length; i++) {
                        if (array[j] < array[i]) {
@@ -4329,8 +4596,6 @@ static int check_order_continuous(u32 *order)
                        j++;
                }
        }
-       for (i = 0; i < j; i++)
-               osd_log_dbg("save_order:%d\n", save_order[i]);
        switch (j) {
        case 0:
                break;
@@ -4360,11 +4625,9 @@ static int blend_din_to_osd(
        osd_index =
                blending->osd_to_bdin_table[blend_din_index];
        if ((osd_index > OSD3)
-               || (osd_index < OSD1)) {
-               osd_log_dbg("blend_din:%d no match osd find!\n",
-                       blend_din_index);
+               || (osd_index < OSD1))
                return -1;
-       else
+       else
                return osd_index;
 }
 
@@ -4381,6 +4644,7 @@ static bool osd_need_scaler(u32 index)
        return scaler;
 }
 
+#if 0
 static bool is_osd_scaling_same(u32 index1, u32 index2)
 {
        bool same;
@@ -4394,84 +4658,7 @@ static bool is_osd_scaling_same(u32 index1, u32 index2)
                same = false;
        return same;
 }
-
-static void set_freescale_para(u32 index, u32 w, u32 h)
-{
-       osd_hw.free_scale_enable[index] = 0x10001;
-
-       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;
-
-       osd_hw.free_dst_data[index].x_start =
-               osd_hw.dst_data[index].x;
-       osd_hw.free_dst_data[index].x_end =
-               osd_hw.dst_data[index].x +
-               osd_hw.dst_data[index].w * w /
-               osd_hw.background_w - 1;
-       osd_hw.free_dst_data[index].y_start =
-               osd_hw.dst_data[index].y;
-       osd_hw.free_dst_data[index].y_end =
-               osd_hw.dst_data[index].y +
-               osd_hw.dst_data[index].h * h /
-               osd_hw.background_h - 1;
-}
-
-static void adjust_freescale_para(struct hw_osd_blending_s *blending)
-{
-       int i;
-       int osd_index;
-       int width = 0, height = 0;
-
-       if (blending->layer_cnt >= 1) {
-               osd_index = blend_din_to_osd(BLEND_DIN1, blending);
-               set_freescale_para(osd_index,
-                       osd_hw.vinfo_width, osd_hw.vinfo_height);
-       }
-       if (blending->layer_cnt == 2) {
-               if (osd_hw.osd_blend_mode == OSD_BLEND_ABC) {
-                       width = osd_hw.background_w;
-                       height = osd_hw.background_h;
-               } else if (osd_hw.osd_blend_mode == OSD_BLEND_AB_C) {
-                       width = osd_hw.vinfo_width;
-                       height = osd_hw.vinfo_height;
-               }
-               osd_index = blend_din_to_osd(BLEND_DIN4, blending);
-               set_freescale_para(osd_index, width, height);
-       } else if (blending->layer_cnt == 3) {
-               if (osd_hw.osd_blend_mode == OSD_BLEND_ABC) {
-                       width = osd_hw.background_w;
-                       height = osd_hw.background_h;
-               } else if (osd_hw.osd_blend_mode == OSD_BLEND_A_BC) {
-                       width = osd_hw.vinfo_width;
-                       height = osd_hw.vinfo_height;
-               }
-               osd_index = blend_din_to_osd(BLEND_DIN3, blending);
-               set_freescale_para(osd_index, width, height);
-               osd_index = blend_din_to_osd(BLEND_DIN4, blending);
-               set_freescale_para(osd_index, width, height);
-       }
-       for (i = 0; i < 3; i++) {
-               osd_log_dbg("free_src_data:%d,%d,%d,%d\n",
-                       osd_hw.free_src_data[i].x_start,
-                       osd_hw.free_src_data[i].y_start,
-                       osd_hw.free_src_data[i].x_end,
-                       osd_hw.free_src_data[i].y_end);
-               osd_log_dbg("free_dst_data:%d,%d,%d,%d\n",
-                       osd_hw.free_dst_data[i].x_start,
-                       osd_hw.free_dst_data[i].y_start,
-                       osd_hw.free_dst_data[i].x_end,
-                       osd_hw.free_dst_data[i].y_end);
-       }
-
-}
+#endif
 
 static void generate_blend_din_table(struct hw_osd_blending_s *blending)
 {
@@ -4508,21 +4695,12 @@ static void generate_blend_din_table(struct hw_osd_blending_s *blending)
                                j++;
                        }
                }
-               if (blending->reorder[temp_index[0]] <
-                       blending->reorder[temp_index[1]]) {
-                       //printf("blend_din4==%d\n",reorder[temp_index[0]]);
-                       //printf("blend_din1==%d\n",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];
-               } else {
-                       //printf("blend_din1==%d\n",reorder[temp_index[0]]);
-                       //printf("blend_din4==%d\n",reorder[temp_index[1]]);
+               osd_log_dbg("blend_din4==%d\n",
+                       blending->reorder[temp_index[0]]);
+               osd_log_dbg("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 */
@@ -4531,31 +4709,92 @@ static void generate_blend_din_table(struct hw_osd_blending_s *blending)
                        blending->din_reoder_sel |= (temp_index[1] + 1) << 12;
                        /* blend_din3 -- osdx */
                        blending->osd_to_bdin_table[3] = temp_index[1];
-               }
-               break;
-       }
-       case 3:
-               for (i = 0; i < osd_count; i++) {
-                       switch (blending->reorder[i]) {
-                       /* blend_din1 is bottom, blend_din4 is top layer */
-                       case LAYER_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("need exchange vpp order\n");
+                       }
+               } else {
+                       if (blending->reorder[temp_index[0]] <
+                               blending->reorder[temp_index[1]]) {
                                /* blend_din4 */
-                               blending->din_reoder_sel |= (i + 1) << 12;
-                               /* blend_din4 -- osdx */
-                               blending->osd_to_bdin_table[3] = i;
-                               break;
-                       case LAYER_2:
-                               /* blend_din3 */
-                               blending->din_reoder_sel |= (i + 1) << 8;
+                               blending->din_reoder_sel |=
+                                       (temp_index[0] + 1) << 12;
                                /* blend_din3 -- osdx */
-                               blending->osd_to_bdin_table[2] = i;
-                               break;
-                       case LAYER_3:
+                               blending->osd_to_bdin_table[3] = temp_index[0];
                                /* blend_din1 */
-                               blending->din_reoder_sel |= (i + 1) << 0;
+                               blending->din_reoder_sel |=
+                                       (temp_index[1] + 1) << 0;
                                /* blend_din1 -- osdx */
-                               blending->osd_to_bdin_table[0] = i;
-                               break;
+                               blending->osd_to_bdin_table[0] = temp_index[1];
+                               blending->b_exchange_din = true;
+                               osd_log_dbg("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;
+       }
+       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("need exchange vpp order\n");
+                       } else {
+                               u32 temp1, temp2;
+
+                               blending->b_exchange_din = true;
+                               osd_log_dbg("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;
@@ -4565,6 +4804,8 @@ static void generate_blend_din_table(struct hw_osd_blending_s *blending)
                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;
        osd_log_dbg("blend_din1 == osd%d\n",
                blend_din_to_osd(BLEND_DIN1, blending) + 1);
        osd_log_dbg("blend_din3 == osd%d\n",
@@ -4573,6 +4814,7 @@ static void generate_blend_din_table(struct hw_osd_blending_s *blending)
                blend_din_to_osd(BLEND_DIN4, blending) + 1);
 }
 
+#if 0
 static void adjust_blend_din_table(struct hw_osd_blending_s *blending)
 {
        int i = 0;
@@ -4603,61 +4845,71 @@ static void adjust_blend_din_table(struct hw_osd_blending_s *blending)
                blending->osd_to_bdin_table[1],
                blending->osd_to_bdin_table[2],
                blending->osd_to_bdin_table[3]);
+       osd_log_dbg("blending->din_reoder_sel=%d\n",
+               blending->din_reoder_sel);
+       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;
 }
 
 static int osd_setting_blending_scope(u32 index)
 {
        u32 bld_osd_h_start, bld_osd_h_end;
        u32 bld_osd_v_start, bld_osd_v_end;
-       u32 reg_offset = 2;
-
-       if (index > OSD3) {
-               osd_log_err("error osd index=%d\n", index);
-               return -1;
-       }
-       if (index == OSD1) {
-               /* use freescale after blend2 */
-               if (osd_hw.free_scale_enable[index]) {
-                       bld_osd_h_start =
-                               osd_hw.free_src_data[index].x_start;
-                       bld_osd_h_end =
-                               osd_hw.free_src_data[index].x_end;
-                       bld_osd_v_start =
-                               osd_hw.free_src_data[index].y_start;
-                       bld_osd_v_end =
-                               osd_hw.free_src_data[index].y_end;
-               } else {
-                       bld_osd_h_start =
-                               osd_hw.pandata[index].x_start;
-                       bld_osd_h_end =
-                               osd_hw.pandata[index].x_end;
-                       bld_osd_v_start =
-                               osd_hw.pandata[index].y_start;
-                       bld_osd_v_end =
-                               osd_hw.pandata[index].y_end;
-                       osd_log_dbg("freescale disable, index=%x\n", index);
-               }
-       } else {
-               if (osd_hw.free_scale_enable[index]) {
-                       bld_osd_h_start =
-                               osd_hw.free_dst_data[index].x_start;
-                       bld_osd_h_end =
-                               osd_hw.free_dst_data[index].x_end;
-                       bld_osd_v_start =
-                               osd_hw.free_dst_data[index].y_start;
-                       bld_osd_v_end =
-                               osd_hw.free_dst_data[index].y_end;
-               } else {
-                       bld_osd_h_start =
-                               osd_hw.dispdata[index].x_start;
-                       bld_osd_h_end =
-                               osd_hw.dispdata[index].x_end;
-                       bld_osd_v_start =
-                               osd_hw.dispdata[index].y_start;
-                       bld_osd_v_end =
-                               osd_hw.dispdata[index].y_end;
-               }
+       u32 reg_offset = 2;
+
+       if (index > OSD3) {
+               osd_log_err("error osd index=%d\n", index);
+               return -1;
        }
+       bld_osd_h_start =
+               osd_hw.dst_data[index].x;
+       bld_osd_h_end =
+               osd_hw.dst_data[index].x +
+               osd_hw.dst_data[index].w - 1;
+       bld_osd_v_start =
+               osd_hw.dst_data[index].y;
+       bld_osd_v_end =
+               osd_hw.dst_data[index].y +
+               osd_hw.dst_data[index].h - 1;
+
+       osd_log_dbg("osd%d_hw.dst_data:%d,%d,%d,%d\n",
+               index,
+               osd_hw.dst_data[index].x,
+               osd_hw.dst_data[index].y,
+               osd_hw.dst_data[index].w,
+               osd_hw.dst_data[index].h);
+       osd_log_dbg("h,v axis:%d,%d,%d,%d\n",
+               bld_osd_h_start,
+               bld_osd_h_end,
+               bld_osd_v_start,
+               bld_osd_v_end);
+
        /* it is setting for osdx */
        VSYNCOSD_WR_MPEG_REG(
                VIU_OSD_BLEND_DIN0_SCOPE_H + reg_offset * index,
@@ -4670,82 +4922,6 @@ static int osd_setting_blending_scope(u32 index)
        return 0;
 }
 
-static int vpp_blend_setting(struct hw_osd_blending_s *blending)
-{
-       u32 index;
-       u32 osd1_dst_h = 0, osd1_dst_v = 0;
-       u32 osd1_h_start = 0, osd1_h_end = 0;
-       u32 osd1_v_start = 0, osd1_v_end = 0;
-       u32 osd2_h_start = 0, osd2_h_end = 0;
-       u32 osd2_v_start = 0, osd2_v_end = 0;
-
-       index = blend_din_to_osd(BLEND_DIN1, blending);
-       if (index > OSD3) {
-               osd_log_err("error osd index=%d\n", index);
-               return -1;
-       }
-       if (osd_hw.free_scale_enable[index]) {
-               osd1_dst_h = osd_hw.free_dst_data[index].x_end
-                       - osd_hw.free_dst_data[index].x_start + 1;
-               osd1_dst_v = osd_hw.free_dst_data[index].y_end
-                       - osd_hw.free_dst_data[index].y_start + 1;
-               osd1_h_start = osd_hw.free_dst_data[index].x_start;
-               osd1_h_end = osd_hw.free_dst_data[index].x_end;
-               osd1_v_start = osd_hw.free_dst_data[index].y_start;
-               osd1_v_end = osd_hw.free_dst_data[index].y_end;
-       } else {
-               osd1_dst_h = osd_hw.dispdata[index].x_end
-                       - osd_hw.dispdata[index].x_start + 1;
-               osd1_dst_v = osd_hw.dispdata[index].y_end
-                       - osd_hw.dispdata[index].y_start + 1;
-               osd1_h_start = osd_hw.dispdata[index].x_start;
-               osd1_h_end = osd_hw.dispdata[index].x_end;
-               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,
-               osd1_h_start << 16 | osd1_h_end);
-       VSYNCOSD_WR_MPEG_REG(VPP_OSD1_BLD_V_SCOPE,
-               osd1_v_start << 16 | osd1_v_end);
-
-       if (osd_hw.osd_blend_mode == OSD_BLEND_AB_C) {
-               if (blending->layer_cnt == 3)
-                       index =  blend_din_to_osd(BLEND_DIN4, blending);
-               else if (blending->layer_cnt == 2)
-                       index =  blend_din_to_osd(BLEND_DIN4, blending);
-               if (osd_hw.free_scale_enable[index]) {
-                       osd2_h_start = osd_hw.free_dst_data[index].x_start;
-                       osd2_h_end = osd_hw.free_dst_data[index].x_end;
-                       osd2_v_start = osd_hw.free_dst_data[index].y_start;
-                       osd2_v_end = osd_hw.free_dst_data[index].y_end;
-               } else {
-                       osd2_h_start = osd_hw.dispdata[index].x_start;
-                       osd2_h_end = osd_hw.dispdata[index].x_end;
-                       osd2_v_start = osd_hw.dispdata[index].y_start;
-                       osd2_v_end = osd_hw.dispdata[index].y_end;
-               }
-       } else if (osd_hw.osd_blend_mode == OSD_BLEND_A_BC) {
-               osd2_h_start = 0;
-               osd2_h_end = osd_hw.background_w - 1;
-               osd2_v_start = 0;
-               osd2_v_end = osd_hw.background_h - 1;
-       }
-
-       osd_log_dbg("index=%d,osd2_h_end=%d,dst_end=%d\n",
-               index, osd2_h_end,
-               osd_hw.free_dst_data[index].x_end);
-       VSYNCOSD_WR_MPEG_REG(VPP_OSD2_BLD_H_SCOPE,
-               osd2_h_start << 16 | osd2_h_end);
-       VSYNCOSD_WR_MPEG_REG(VPP_OSD2_BLD_V_SCOPE,
-               osd2_v_start << 16 | osd2_v_end);
-
-       return 0;
-}
-
 static int vpp_blend_setting_default(u32 index)
 {
        u32 osd1_dst_h = 0, osd1_dst_v = 0;
@@ -4803,26 +4979,14 @@ static int vpp_blend_setting_default(u32 index)
 static u32 order[HW_OSD_COUNT];
 static struct hw_osd_blending_s osd_blending;
 
-static int osd_setting_order(void)
+static void set_blend_order(struct hw_osd_blending_s *blending)
 {
-       u32 ret;
-       u32 blend2_premult_en = 0, din_premult_en = 0;
-       u32 blend_din_en = 0x0;
-       /* blend_din0 input to blend0 */
-       u32 din0_byp_blend = 0;
-       /* blend1_dout to blend2 */
-       u32 din2_osd_sel = 0;
-       /* blend1_din3 input to blend1 */
-       u32 din3_osd_sel = 0;
-       u32 postbld_src3_sel = 0, postbld_src4_sel = 0;
-       u32 postbld_osd1_premult = 0, postbld_osd2_premult = 0;
        u32 org_order[HW_OSD_COUNT];
-       int i = 0, j = 0, osd_index;
-       int osd_blend_mode = 0;
-       bool b_exchange = false, b_continuous = false;
-       u32 blend_hsize, blend_vsize;
+       int i = 0, j = 0;
        u32 osd_count = osd_hw.osd_meson_dev.osd_count - 1;
 
+       if (!blending)
+               return;
        /* number largest is top layer */
        for (i = 0; i < osd_count; i++) {
                org_order[i] = osd_hw.order[i];
@@ -4831,7 +4995,7 @@ static int osd_setting_order(void)
                order[i] = org_order[i];
        }
        insert_sort(order, osd_count);
-       b_continuous = check_order_continuous(order);
+       blending->b_continuous = check_order_continuous(order);
        osd_log_dbg("after sort:zorder:%d,%d,%d\n",
                order[0], order[1], order[2]);
 
@@ -4840,327 +5004,1130 @@ static int osd_setting_order(void)
                for (j = 0; j < osd_count; j++) {
                        if (order[i] == org_order[j]) {
                                if (osd_hw.enable[j])
-                                       osd_blending.reorder[j] = LAYER_1 + i;
+                                       blending->reorder[j] = LAYER_1 + i;
                                else
-                                       osd_blending.reorder[j] =
+                                       blending->reorder[j] =
                                        LAYER_UNSUPPORT;
                        }
                }
        }
-       osd_blending.layer_cnt = get_available_layers();
-
        osd_log_dbg("after reorder:zorder:%d,%d,%d\n",
-               osd_blending.reorder[0],
-               osd_blending.reorder[1],
-               osd_blending.reorder[2]);
-       generate_blend_din_table(&osd_blending);
-       osd_log_dbg("layer_cnt:%d\n", osd_blending.layer_cnt);
-
-       postbld_src3_sel = 3;//src1 is bottom
-       postbld_src4_sel = 4;//src4 is top
-       switch (osd_blending.layer_cnt) {
+               blending->reorder[0],
+               blending->reorder[1],
+               blending->reorder[2]);
+}
+
+static void set_blend_din(struct hw_osd_blending_s *blending)
+{
+       int i = 0, osd_index;
+       u32 blend_din_en = 0x9;
+
+       if (!blending)
+               return;
+       for (i = 0; i < OSD_BLEND_LAYERS; i++) {
+               /* find osd index */
+               osd_index = blend_din_to_osd(i, blending);
+               if ((osd_index >= OSD1) && (osd_index <= OSD3)) {
+                       /* depend on osd enable */
+                       blend_din_en = _set_bits(
+                               blend_din_en,
+                               i,
+                       osd_hw.enable[osd_index]);
+               }
+       }
+       blending->blend_reg.blend_din_en = blend_din_en;
+}
+
+static void set_blend_mode(struct hw_osd_blending_s *blending)
+{
+       u8 osd_blend_mode = OSD_BLEND_NONE;
+       //u32 osd_index;
+
+       if (!blending)
+               return;
+       switch (blending->layer_cnt) {
        case 0:
                osd_blend_mode = OSD_BLEND_NONE;
-               postbld_src3_sel = 0; //close vpp osd1
-               postbld_src4_sel = 0; //close vpp osd2
                break;
        case 1:
                /* select blend_din1 always */
-               osd_blend_mode = OSD_BLEND_ABC;
-               postbld_src3_sel = 3;
-               postbld_src4_sel = 0;//close vpp osd2
+               osd_blend_mode = OSD_BLEND_A;
                break;
        case 2:
                /* select blend_din1, blend_din4 always */
-               osd_blend_mode = OSD_BLEND_AB_C;
-               if (b_continuous) {
-                       osd_index = blend_din_to_osd(
-                               BLEND_DIN1, &osd_blending);
-                       if (!osd_need_scaler(osd_index)) {
-                               /* do not need scaler, mode ABC */
-                               osd_blend_mode = OSD_BLEND_ABC;
-                               postbld_src4_sel = 0;
-                       } else {
-                               u32 index4;
-
-                               index4 = blend_din_to_osd(
-                                       BLEND_DIN4, &osd_blending);
-                               if (is_osd_scaling_same(
-                                       osd_index, index4)) {
-                                       /* scaler is same, mode ABC */
-                                       osd_blend_mode = OSD_BLEND_ABC;
-                                       postbld_src4_sel = 0;
-                               }
-                       }
-               }
+               if (osd_hw.hdr_used)
+                       osd_blend_mode = OSD_BLEND_AC;
+               else
+                       osd_blend_mode = OSD_BLEND_A_C;
                break;
        case 3:
-               if (order[0] == order[1] + 1) {
-                       if (order[1] == order[2] + 1) {
-                               osd_index = blend_din_to_osd(
-                                       BLEND_DIN1, &osd_blending);
-                               if (!osd_need_scaler(osd_index)) {
-                                       /* do not need scaler, mode ABC */
-                                       osd_blend_mode = OSD_BLEND_ABC;
-                                       postbld_src4_sel = 0;
-                               } else {
-                                       u32 index3, index4;
-
-                                       index3 = blend_din_to_osd(BLEND_DIN3,
-                                               &osd_blending);
-                                       index4 = blend_din_to_osd(BLEND_DIN4,
-                                               &osd_blending);
-                                       osd_log_dbg(
-                                               "BLEND_DIN1 need scaler,check osd%d, osd%d\n",
-                                               index3, index4);
-                                       if ((is_osd_scaling_same(
-                                               osd_index, index3))
-                                               && (is_osd_scaling_same(
-                                               osd_index, index4))) {
-                                               /* scaler is same */
-                                               osd_blend_mode = OSD_BLEND_ABC;
-                                               postbld_src4_sel = 0;
-                                       } else
-                                               osd_blend_mode = OSD_BLEND_A_BC;
-                               }
-                       } else
-                               osd_blend_mode = OSD_BLEND_A_BC;
-               } else {
-                       osd_log_dbg("adjust din map\n");
+               /* select blend_din1, blend_din3 blend_din4 always */
+               if (osd_hw.hdr_used)
+                       osd_blend_mode = OSD_BLEND_ABC;
+               else
                        osd_blend_mode = OSD_BLEND_A_BC;
-                       b_exchange = 1;
-                       adjust_blend_din_table(&osd_blending);
-               }
                break;
        }
-       osd_log_dbg("is osd_blend_mode=%d\n", osd_blend_mode);
-       osd_log_dbg("blend_din1 == osd%d\n",
-               blend_din_to_osd(BLEND_DIN1, &osd_blending) + 1);
-       osd_log_dbg("blend_din3 == osd%d\n",
-               blend_din_to_osd(BLEND_DIN3, &osd_blending) + 1);
-       osd_log_dbg("blend_din4 == osd%d\n",
-               blend_din_to_osd(BLEND_DIN4, &osd_blending) + 1);
-       osd_log_dbg("din_reoder_sel=%x\n",
-               osd_blending.din_reoder_sel);
+       blending->osd_blend_mode = osd_blend_mode;
+       osd_log_dbg("osd_blend_mode=%d\n",
+               blending->osd_blend_mode);
+}
 
-       for (i = 0; i < OSD_BLEND_LAYERS; i++) {
-               /* find osd index */
-               osd_index = blend_din_to_osd(i, &osd_blending);
-               if ((osd_index >= OSD1) && (osd_index <= OSD3)) {
-                       /* depend on osd enable */
-                       blend_din_en = _set_bits(
-                               blend_din_en,
-                               i,
-                       osd_hw.enable[osd_index]);
-                       din_premult_en = _set_bits(
-                               din_premult_en,
-                               i,
-                               osd_hw.premult_en[osd_index]);
-               }
-       }
-       switch (osd_blend_mode) {
-       case OSD_BLEND_ABC:
-               /* blend1_dout to blend1 */
-               din2_osd_sel = 0;
+static void osd_setting_blend0(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);
+               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_dbg("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);
+       }
+       if (blend_reg->din0_byp_blend) {
+               /* output == input */
+               memcpy(&(layer_blend->output_data), &(layer_blend->input1_data),
+                       sizeof(struct dispdata_s));
+       } else {
+               /* always used background as output */
+               layer_blend->output_data.x = 0;
+               layer_blend->output_data.y = 0;
+               layer_blend->output_data.w = layer_blend->background_w;
+               layer_blend->output_data.h = layer_blend->background_h;
+       }
+       osd_log_dbg("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);
+       osd_log_dbg("layer_blend->background_w=%d,h=%d\n",
+               layer_blend->background_w, layer_blend->background_h);
+}
+
+static void osd_setting_blend1(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;
+
+       if (!blending)
+               return;
+       layer_blend = &(blending->layer_blend);
+       blend_reg = &(blending->blend_reg);
+
+       /* 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;
+
+       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 */
-               din3_osd_sel = 0;
+               blend_reg->din3_osd_sel = 0;
+       osd_log_dbg("osd_setting_blend1:input1=%d,din2_osd_sel=%d,input2=%d,din3_osd_sel=%d\n",
+               layer_blend->input1, blend_reg->din2_osd_sel,
+               layer_blend->input2, blend_reg->din3_osd_sel);
+
+       if (layer_blend->input1 != BLEND_NO_DIN) {
+               index = blend_din_to_osd(layer_blend->input1, blending);
+               /* 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_dbg("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);
+               /* 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_dbg("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) {
+               /* blend din3 bypass,output == input */
+               memcpy(&(layer_blend->output_data), &(layer_blend->input2_data),
+                       sizeof(struct dispdata_s));
+               //layer_blend->background_w = layer_blend->output_data.w;
+               //layer_blend->background_h = layer_blend->output_data.h;
+       } else {
+               /* always used input1_data */
+               blend_hsize = layer_blend->background_w;
+               blend_vsize = layer_blend->background_h;
+               blend_reg->osd_blend_blend1_size =
+                       blend_vsize  << 16 | blend_hsize;
+               /* always used background as output */
+               layer_blend->output_data.x = 0;
+               layer_blend->output_data.y = 0;
+               layer_blend->output_data.w = layer_blend->background_w;
+               layer_blend->output_data.h = layer_blend->background_h;
+       }
+       osd_log_dbg("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);
+       osd_log_dbg("blend1:background_w=%d,background_h=%d\n",
+               layer_blend->background_w,
+               layer_blend->background_h);
+
+}
+
+static void osd_setting_blend2(struct hw_osd_blending_s *blending)
+{
+       struct layer_blend_s *layer_blend;
+       struct layer_blend_reg_s *blend_reg;
+       u32 blend_hsize, blend_vsize;
 
-               switch (osd_blending.layer_cnt) {
-               case 1:
-                       /* blend_din0 bypass to dout0 */
-                       din0_byp_blend = 1;
-                       break;
-               case 2:
-               case 3:
-                       /* blend_din0 input to blend0 */
-                       din0_byp_blend = 0;
-                       /* if one blend input, output is premult = 1 */
-                       blend2_premult_en = _set_bits(
-                               blend2_premult_en,
-                               0, 1);
-                       blend2_premult_en = _set_bits(
-                               blend2_premult_en,
-                               1, 1);
-               /* depend on blend2_premult_en */
-               postbld_osd1_premult = _set_bits(
-                       postbld_osd1_premult,
-                       0,
-                       (blend2_premult_en & 0x3) ? 1 : 0);
-               /* no vpp_osd2 */
-               /* need close vpp_osd2 input */
-                       break;
+       if (!blending)
+               return;
+       layer_blend = &(blending->layer_blend);
+       blend_reg = &(blending->blend_reg);
+
+       blend_hsize = layer_blend->input1_data.w;
+       blend_vsize = layer_blend->input1_data.h;
+       /* always used input1_data */
+       /* osd_blend_blend0_size share with blend2_size*/
+       blend_reg->osd_blend_blend0_size =
+               blend_vsize  << 16 | blend_hsize;
+       #if 0
+       switch (layer_blend->input1) {
+       case BLEND0_DIN:
+               break;
+       case BLEND1_DIN:
+               break;
+       default:
+               break;
+       }
+       #endif
+       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;
+       }
+       osd_log_dbg("osd_setting_blend2:input2=%d,din2_osd_sel=%d\n",
+               layer_blend->input2, blend_reg->din2_osd_sel);
+       /* premult set */
+       blend_reg->blend2_premult_en = 3;
+       /* always used background as output */
+       layer_blend->output_data.x = 0;
+       layer_blend->output_data.y = 0;
+       layer_blend->output_data.w = layer_blend->background_w;
+       layer_blend->output_data.h = layer_blend->background_h;
+       osd_log_dbg("layer_blend2->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);
+       osd_log_dbg("blend2:background_w=%d,background_h=%d\n",
+               layer_blend->background_w,
+               layer_blend->background_h);
+}
+
+static void vpp_setting_blend(struct hw_osd_blending_s *blending)
+{
+       struct layer_blend_s *layer_blend;
+       struct layer_blend_reg_s *blend_reg;
+       u32 osd1_h_start = 0, osd1_h_end = 0;
+       u32 osd1_v_start = 0, osd1_v_end = 0;
+       u32 osd2_h_start = 0, osd2_h_end = 0;
+       u32 osd2_v_start = 0, osd2_v_end = 0;
+
+       if (!blending)
+               return;
+       layer_blend = &(blending->layer_blend);
+       blend_reg = &(blending->blend_reg);
+
+       osd1_h_start = layer_blend->input1_data.x;
+       osd1_h_end = layer_blend->input1_data.x +
+               layer_blend->input1_data.w - 1;
+       osd1_v_start = layer_blend->input1_data.y;
+       osd1_v_end = layer_blend->input1_data.y +
+               layer_blend->input1_data.h - 1;
+       osd2_h_start = layer_blend->input2_data.x;
+       osd2_h_end = layer_blend->input2_data.x +
+               layer_blend->input2_data.w - 1;
+       osd2_v_start = layer_blend->input2_data.y;
+       osd2_v_end = layer_blend->input2_data.y +
+               layer_blend->input2_data.h - 1;
+       osd_log_dbg("osd1_h_start=%x,osd1_h_end=%x\n",
+               osd1_h_start, osd1_h_end);
+       osd_log_dbg("osd1_h_start=%x, osd1_v_end=%x\n",
+               osd1_v_start, osd1_v_end);
+
+       osd_log_dbg("osd2_h_start=%x,osd2_h_end=%x\n",
+               osd2_h_start, osd2_h_end);
+       osd_log_dbg("osd2_h_start=%x, osd2_v_end=%x\n",
+               osd2_v_start, osd2_v_end);
+
+       switch (layer_blend->input1) {
+       case BLEND1_DIN:
+               blend_reg->postbld_src3_sel = POSTBLD_OSD2;
+               if (blend_reg->din3_osd_sel)
+                       blend_reg->postbld_osd1_premult = 0;
+               else
+                       blend_reg->postbld_osd1_premult = 1;
+               blend_reg->vpp_osd1_blend_h_scope =
+                       (osd2_h_start << 16 | osd2_h_end);
+               blend_reg->vpp_osd1_blend_v_scope =
+                       (osd2_v_start << 16 | osd2_v_end);
+               break;
+       case BLEND2_DIN:
+               blend_reg->postbld_src3_sel = POSTBLD_OSD1;
+               if (blend_reg->din0_byp_blend)
+                       blend_reg->postbld_osd1_premult = 0;
+               else
+                       blend_reg->postbld_osd1_premult = 1;
+               blend_reg->vpp_osd1_blend_h_scope =
+                       (osd1_h_start << 16 | osd1_h_end);
+               blend_reg->vpp_osd1_blend_v_scope =
+                       (osd1_v_start << 16 | osd1_v_end);
+               break;
+       default:
+               blend_reg->postbld_src3_sel = POSTBLD_CLOSE;
+               blend_reg->postbld_osd1_premult = 0;
+               break;
+       }
+
+       switch (layer_blend->input2) {
+       case BLEND1_DIN:
+               blend_reg->postbld_src4_sel = POSTBLD_OSD2;
+               if (blend_reg->din3_osd_sel)
+                       blend_reg->postbld_osd2_premult = 0;
+               else
+                       blend_reg->postbld_osd2_premult = 1;
+               blend_reg->vpp_osd2_blend_h_scope =
+                       (osd2_h_start << 16 | osd2_h_end);
+               blend_reg->vpp_osd2_blend_v_scope =
+                       (osd2_v_start << 16 | osd2_v_end);
+               break;
+       case BLEND2_DIN:
+               blend_reg->postbld_src4_sel = POSTBLD_OSD1;
+               if (blend_reg->din0_byp_blend)
+                       blend_reg->postbld_osd2_premult = 0;
+               else
+                       blend_reg->postbld_osd2_premult = 1;
+               blend_reg->vpp_osd2_blend_h_scope =
+                       (osd1_h_start << 16 | osd1_h_end);
+               blend_reg->vpp_osd2_blend_v_scope =
+                       (osd1_v_start << 16 | osd1_v_end);
+               break;
+       default:
+               blend_reg->postbld_src4_sel = POSTBLD_CLOSE;
+               blend_reg->postbld_osd2_premult = 0;
+               break;
+       }
+       osd_log_dbg("vpp_osd1_blend_h_scope=%x, vpp_osd1_blend_v_scope=%x\n",
+               blend_reg->vpp_osd1_blend_h_scope,
+               blend_reg->vpp_osd1_blend_v_scope);
+       osd_log_dbg("vpp_osd2_blend_h_scope=%x, vpp_osd2_blend_v_scope=%x\n",
+               blend_reg->vpp_osd2_blend_h_scope,
+               blend_reg->vpp_osd2_blend_v_scope);
+
+}
+
+/* input w, h is background */
+static void osd_set_freescale(u32 index, u32 w, u32 h,
+       struct hw_osd_blending_s *blending)
+
+{
+       struct layer_blend_s *layer_blend;
+       struct layer_blend_reg_s *blend_reg;
+       u32 background_w = 0, background_h = 0;
+
+       layer_blend = &(blending->layer_blend);
+       blend_reg = &(blending->blend_reg);
+       if (index > OSD3) {
+               osd_log_err("error osd index=%d\n", index);
+               return;
+       }
+       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;
+
+       if (index == OSD1) {
+               osd_hw.free_src_data[index].x_start =
+                       layer_blend->output_data.x;
+               osd_hw.free_src_data[index].x_end =
+                       layer_blend->output_data.x +
+                       layer_blend->output_data.w - 1;
+               osd_hw.free_src_data[index].y_start =
+                       layer_blend->output_data.y;
+               osd_hw.free_src_data[index].y_end =
+                       layer_blend->output_data.y +
+                       layer_blend->output_data.h - 1;
+               if (blend_reg->din0_byp_blend) {
+                       osd_hw.free_dst_data[index].x_start =
+                               layer_blend->output_data.x *
+                               blending->vinfo_width / w;
+                       osd_hw.free_dst_data[index].x_end =
+                               (layer_blend->output_data.x +
+                               layer_blend->output_data.w) *
+                               blending->vinfo_width / w - 1;
+                       osd_hw.free_dst_data[index].y_start =
+                               layer_blend->output_data.y *
+                               blending->vinfo_height / h;
+                       osd_hw.free_dst_data[index].y_end =
+                               (layer_blend->output_data.y +
+                               layer_blend->output_data.h) *
+                               blending->vinfo_height / h - 1;
+               } else {
+                       osd_hw.free_dst_data[index].x_start = 0;
+                       osd_hw.free_dst_data[index].x_end =
+                               blending->vinfo_width - 1;
+                       osd_hw.free_dst_data[index].y_start = 0;
+                       osd_hw.free_dst_data[index].y_end =
+                               blending->vinfo_height - 1;
+               }
+       } else {
+               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;
+               if ((blending->osd_blend_mode == OSD_BLEND_AC) ||
+                       (blending->osd_blend_mode == OSD_BLEND_ABC)) {
+                       background_w = blending->background_w;
+                       background_h = blending->background_h;
+                       osd_hw.free_dst_data[index].x_start =
+                               osd_hw.dst_data[index].x *
+                               w / background_w;
+                       osd_hw.free_dst_data[index].x_end =
+                               (osd_hw.dst_data[index].x +
+                               osd_hw.dst_data[index].w) *
+                               w / background_w - 1;
+                       osd_hw.free_dst_data[index].y_start =
+                               osd_hw.dst_data[index].y *
+                               h / background_h;
+                       osd_hw.free_dst_data[index].y_end =
+                               (osd_hw.dst_data[index].y +
+                               osd_hw.dst_data[index].h) *
+                               h / background_h - 1;
+               } else {
+                       background_w = blending->vinfo_width;
+                       background_h = blending->vinfo_height;
+                       osd_hw.free_dst_data[index].x_start =
+                               osd_hw.dst_data[index].x *
+                               background_w / w;
+                       osd_hw.free_dst_data[index].x_end =
+                               (osd_hw.dst_data[index].x +
+                               osd_hw.dst_data[index].w) *
+                               background_w / w - 1;
+                       osd_hw.free_dst_data[index].y_start =
+                               osd_hw.dst_data[index].y *
+                               background_h / h;
+                       osd_hw.free_dst_data[index].y_end =
+                               (osd_hw.dst_data[index].y +
+                               osd_hw.dst_data[index].h) *
+                               background_h / h - 1;
+               }
+       }
+       osd_log_dbg("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_dbg("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);
+}
+
+static void osd_setting_blend0_input(u32 index,
+       struct hw_osd_blending_s *blending)
+{
+       u32 background_w = 0, background_h = 0;
+       struct layer_blend_s *layer_blend;
+
+       layer_blend = &(blending->layer_blend);
+       if ((index == OSD1) && osd_need_scaler(index)) {
+               layer_blend->input1_data.x = osd_hw.dst_data[index].x
+                       * osd_hw.src_data[index].w
+                       /osd_hw.dst_data[index].w;
+               layer_blend->input1_data.y = osd_hw.dst_data[index].y
+                       * osd_hw.src_data[index].h
+                       /osd_hw.dst_data[index].h;
+               layer_blend->input1_data.w = osd_hw.dst_data[index].w
+                       * osd_hw.src_data[index].w
+                       /osd_hw.dst_data[index].w;
+               layer_blend->input1_data.h = osd_hw.dst_data[index].h
+                       * osd_hw.src_data[index].h
+                       /osd_hw.dst_data[index].h;
+               background_w = blending->background_w
+                       * osd_hw.src_data[index].w
+                       /osd_hw.dst_data[index].w;
+               background_h = blending->background_h
+                       * osd_hw.src_data[index].h
+                       /osd_hw.dst_data[index].h;
+       } else {
+               layer_blend->input1_data.x = osd_hw.dst_data[index].x;
+               layer_blend->input1_data.y = osd_hw.dst_data[index].y;
+               layer_blend->input1_data.w = osd_hw.dst_data[index].w;
+               layer_blend->input1_data.h = osd_hw.dst_data[index].h;
+               background_w = blending->background_w;
+               background_h = blending->background_h;
+       }
+       osd_log_dbg("osd_hw.src_data[index].w=%d,h=%d\n",
+               osd_hw.src_data[index].w, osd_hw.src_data[index].h);
+       osd_log_dbg("osd_hw.dst_data[index].w=%d,h=%d\n",
+               osd_hw.dst_data[index].w, osd_hw.dst_data[index].h);
+       osd_log_dbg("blend0: background_w=%d, background_h=%d\n",
+               background_w, background_h);
+       layer_blend->background_w = background_w;
+       layer_blend->background_h = background_h;
+}
+
+static void set_blend_path(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;
+
+       if (!blending)
+               return;
+       layer_blend = &(blending->layer_blend);
+       blend_reg = &(blending->blend_reg);
+       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_osd2_premult = 0;
+               break;
+       case OSD_BLEND_A:
+               /* blend0-->blend2-->sc-->vpp_osd1 or */
+               /* 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);
+               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);
+               }
+               /* osd1 freescale,output is vinfo.w/h */
+               osd_log_dbg("after blend: set osd%d freescale\n", index);
+               if (index != OSD1) {
+                       /* if not osd1, need disable osd1 freescale */
+                       osd_hw.free_scale_enable[OSD1] = 0x0;
+                       osd_hw.free_scale[OSD1].h_enable = 0;
+                       osd_hw.free_scale[OSD1].v_enable = 0;
+                       blending->osd1_freescale_disable = true;
+               }
+               /* osd1 freescale input is background */
+               osd_set_freescale(index, layer_blend->background_w,
+                       layer_blend->background_h, blending);
+
+               layer_blend->input1 = BLEND2_DIN;
+               layer_blend->input2 = BLEND_NO_DIN;
+               if (blend_reg->din0_byp_blend) {
+                       layer_blend->input1_data.x =
+                               osd_hw.free_dst_data[index].x_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.y =
+                               osd_hw.free_dst_data[index].y_start;
+                       layer_blend->input1_data.h =
+                               osd_hw.free_dst_data[index].y_end -
+                               osd_hw.free_dst_data[index].y_start + 1;
+               } else {
+                       layer_blend->input1_data.x = 0;
+                       layer_blend->input1_data.y = 0;
+                       layer_blend->input1_data.w = blending->vinfo_width;
+                       layer_blend->input1_data.h = blending->vinfo_height;
+               }
+               vpp_setting_blend(blending);
+               break;
+       case OSD_BLEND_AC:
+               /* blend0 & sc-->blend1-->blend2-->sc-->vpp_osd1 */
+               /* sc-->blend0 & blend1-->blend2-->sc-->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);
+               osd_setting_blend0_input(index, blending);
+               if (index != OSD1) {
+                       /* here used freescale osd1/osd2 */
+                       osd_log_dbg("before blend0: set osd%d freescale\n",
+                               index);
+                       osd_set_freescale(index, layer_blend->background_w,
+                               layer_blend->background_h, blending);
+               }
+               osd_setting_blend0(blending);
+               memcpy(&output1_data, &(layer_blend->output_data),
+                       sizeof(struct dispdata_s));
+
+               index = blend_din_to_osd(input2, blending);
+               if (index != OSD1) {
+                       osd_log_dbg("before blend1: set osd%d freescale\n",
+                               index);
+                       osd_set_freescale(index, layer_blend->background_w,
+                               layer_blend->background_h, blending);
+               }
+               layer_blend->input1 = BLEND_NO_DIN;
+               layer_blend->input2 = input2;
+               if (osd_hw.blend_bypass)
+                       layer_blend->input2 |= BYPASS_DIN;
+               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;
+               osd_setting_blend1(blending);
+
+               layer_blend->input1 = BLEND0_DIN;
+               layer_blend->input2 = BLEND1_DIN;
                #if 0
-               blend2_premult_en = _set_bits(
-                       blend2_premult_en,
-                       1,
-                       (din_premult_en & 0xc0) ? 1 : 0);
+               /* always used input1_data */
+               memcpy(&layer_blend->input1, &output1_data,
+                       sizeof(struct dispdata_s));
+               memcpy(&layer_blend->input2,
+                       &(layer_blend->output_data),
+                       sizeof(struct dispdata_s));
+               #else
+               layer_blend->input1_data.x = 0;
+               layer_blend->input1_data.y = 0;
+               layer_blend->input1_data.w = layer_blend->background_w;
+               layer_blend->input1_data.h = layer_blend->background_h;
                #endif
+               osd_setting_blend2(blending);
+
+               /* used osd0 freescale */
+               osd_set_freescale(OSD1, layer_blend->background_w,
+                       layer_blend->background_h, blending);
+
+               layer_blend->input1 = BLEND2_DIN;
+               layer_blend->input2 = BLEND_NO_DIN;
+               layer_blend->input1_data.x = 0;
+               layer_blend->input1_data.y = 0;
+               layer_blend->input1_data.w = blending->vinfo_width;
+               layer_blend->input1_data.h = blending->vinfo_height;
+               vpp_setting_blend(blending);
+               break;
+       case OSD_BLEND_A_C:
+               /* blend0 -->blend2-->sc->vpp_osd1 */
+               /* sc-->blend1 -->vpp_osd2 */
+               /* or */
+               /* sc-->blend0 -->blend2-->vpp_osd1 */
+               /* 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);
+               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);
+               }
+               /* here freescale osd0 used */
+               osd_log_dbg("after blend2: set osd%d freescale\n", index);
+               osd_set_freescale(index, layer_blend->background_w,
+                       layer_blend->background_h, blending);
+               /* save freescale output */
+               output1_data.x =
+                       osd_hw.free_dst_data[index].x_start;
+               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;
+               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_DIN4, blending);
+               /* here freescale osd1/osd2 used */
+               osd_log_dbg("before blend1: set osd%d freescale\n", index);
+               osd_set_freescale(index, blending->background_w,
+                       blending->background_h, blending);
+
+               /* 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;
+               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;
+               layer_blend->background_w = blending->vinfo_width;
+               layer_blend->background_h = blending->vinfo_height;
+               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:
-               if (osd_blending.layer_cnt == 3) {
-                       /* blend_din0 input to blend0 */
-                       din0_byp_blend = 0;
-                       /* blend1_dout to blend2 */
-                       din2_osd_sel = 0;
-                       /* blend1_din3 bypass to dout1 */
-                       din3_osd_sel = 1;
-                       blend2_premult_en = _set_bits(
-                               blend2_premult_en,
-                               0,
-                               1);
-                       blend2_premult_en = _set_bits(
-                               blend2_premult_en,
-                               1,
-                               1);
-                       /* depend on blend2_premult_en */
-                       postbld_osd1_premult = _set_bits(
-                               postbld_osd1_premult,
-                               0,
-                               (blend2_premult_en & 0x3) ? 1 : 0);
-                       /* depend on din_premult_en bit 4 */
-                       postbld_osd2_premult = _set_bits(
-                               postbld_osd2_premult,
-                               0,
-                               (din_premult_en & 0x8) ? 1 : 0);
-               } else if (osd_blending.layer_cnt == 2) {
-                       /* blend_din0 input to blend0 */
-                       din0_byp_blend = 1;
-                       /* blend1_dout to dout1 */
-                       din2_osd_sel = 1;
-                       /* blend1_din3 input to blend1 */
-                       din3_osd_sel = 1;
-
-                       /* depend on din0_premult_en */
-                       postbld_osd1_premult = _set_bits(
-                               postbld_osd1_premult,
-                               0,
-                               (din_premult_en & 0x1) ? 1 : 0);
-                       /* depend on din_premult_en bit 4 */
-                       postbld_osd2_premult = _set_bits(
-                               postbld_osd2_premult,
-                               0,
-                               (din_premult_en & 0x8) ? 1 : 0);
-                       osd_log_dbg("postbld_osd1_premult=%x\n",
-                               postbld_osd1_premult);
-                       osd_log_dbg("postbld_osd2_premult=%x\n",
-                               postbld_osd2_premult);
+       case OSD_BLEND_ABC:
+               /* blend0 -->blend2-->sc-->vpp_osd1 */
+               /* sc-->blend1 -->blend2 */
+               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);
+               osd_setting_blend0_input(index, blending);
+               if (index != OSD1)
+                       osd_log_err("not support case!!!\n");
+               osd_setting_blend0(blending);
+               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);
+               if (index != OSD1) {
+                       osd_log_dbg("before blend1: set osd%d freescale\n",
+                               index);
+                       osd_set_freescale(index, layer_blend->background_w,
+                               layer_blend->background_h, blending);
+               }
+               layer_blend->input1_data.x =
+                       osd_hw.free_dst_data[index].x_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.y =
+                       osd_hw.free_dst_data[index].y_start;
+               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(layer_blend->input2, blending);
+               if (index != OSD1) {
+                       osd_log_dbg("before blend1: set osd%d freescale\n",
+                               index);
+                       osd_set_freescale(index, layer_blend->background_w,
+                               layer_blend->background_h, blending);
+               }
+               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;
+               osd_setting_blend1(blending);
+
+               layer_blend->input1 = BLEND0_DIN;
+               layer_blend->input2 = BLEND1_DIN;
+               layer_blend->input1_data.x = 0;
+               layer_blend->input1_data.y = 0;
+               layer_blend->input1_data.w = layer_blend->background_w;
+               layer_blend->input1_data.h = layer_blend->background_h;
+               osd_setting_blend2(blending);
+               /* used osd0 freescale */
+               osd_set_freescale(OSD1, layer_blend->background_w,
+                       layer_blend->background_h, blending);
+
+               layer_blend->input1 = BLEND2_DIN;
+               layer_blend->input2 = BLEND_NO_DIN;
+               layer_blend->input1_data.x = 0;
+               layer_blend->input1_data.y = 0;
+               layer_blend->input1_data.w = blending->vinfo_width;
+               layer_blend->input1_data.h = blending->vinfo_height;
+               layer_blend->input2_data.x = 0;
+               layer_blend->input2_data.y = 0;
+               layer_blend->input2_data.w = blending->vinfo_width;
+               layer_blend->input2_data.h = blending->vinfo_height;
+               vpp_setting_blend(blending);
                break;
        case OSD_BLEND_A_BC:
-               /* blend_din0 bypass to dout0 */
-               din0_byp_blend = 1;
-               /* blend1_dout to dout1 */
-               din2_osd_sel = 1;
-               /* blend1_din3 input to blend1 */
-               din3_osd_sel = 0;
-               /* no input to blend0 & blend1 */
-               /* depend on din_premult_en bit 1 */
-               postbld_osd1_premult = _set_bits(
-                       postbld_osd1_premult,
-                       0,
-                       (din_premult_en & 0x1) ? 1 : 0);
-               /* via blend2 always premult */
-               postbld_osd2_premult = _set_bits(
-                       postbld_osd2_premult,
-                       0, 1);
-               #if 0
-               /* depend on din_premult_en bit 3_4 */
-               postbld_osd2_premult = _set_bits(
-                       postbld_osd2_premult,
-                       0,
-                       (din_premult_en & 0xc) ? 1 : 0);
-               #endif
+               /* 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);
+               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("after blend2: set osd%d freescale\n", index);
+               osd_set_freescale(index, layer_blend->background_w,
+                       layer_blend->background_h, blending);
+               /* save freescale output */
+               output1_data.x =
+                       osd_hw.free_dst_data[index].x_start;
+               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;
+               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);
+               osd_log_dbg("before blend1: set osd%d freescale\n", index);
+               osd_set_freescale(index, blending->background_w,
+                       blending->background_h, blending);
+               layer_blend->input1_data.x =
+                       osd_hw.free_dst_data[index].x_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.y =
+                       osd_hw.free_dst_data[index].y_start;
+               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);
+               osd_log_dbg("before blend1: set osd%d freescale\n", index);
+               osd_set_freescale(index, blending->background_w,
+                       blending->background_h, blending);
+               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;
+
+               /* always route(bypass) to dout1 */
+               layer_blend->input1 = BLEND_DIN3 | BYPASS_DIN;
+               layer_blend->input2 = BLEND_DIN4;
+               /* input is set by freescale dst axis */
+               layer_blend->background_w = blending->vinfo_width;
+               layer_blend->background_h = blending->vinfo_height;
+               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;
        }
-       if (b_exchange) {
-               u32 temp = 0;
+}
+
+static void set_blend_reg(struct layer_blend_reg_s *blend_reg)
+{
+       int i;
+       u32 reg_offset = 2;
+       u32 osd_count = osd_hw.osd_meson_dev.osd_count - 1;
+
+       if (!blend_reg)
+               return;
+       /* osd blend ctrl */
+       VSYNCOSD_WR_MPEG_REG(VIU_OSD_BLEND_CTRL,
+               4                                 << 29|
+               blend_reg->blend2_premult_en << 27|
+               blend_reg->din0_byp_blend         << 26|
+               blend_reg->din2_osd_sel   << 25|
+               blend_reg->din3_osd_sel   << 24|
+               blend_reg->blend_din_en   << 20|
+               blend_reg->din_premult_en         << 16|
+               blend_reg->din_reoder_sel);
+       /* vpp osd1 blend ctrl */
+       VSYNCOSD_WR_MPEG_REG(OSD1_BLEND_SRC_CTRL,
+               (0 & 0xf) << 0 |
+               (0 & 0x1) << 4 |
+               (blend_reg->postbld_src3_sel & 0xf) << 8 |
+               (blend_reg->postbld_osd1_premult & 0x1) << 16|
+               (1 & 0x1) << 20);
+       /* vpp osd2 blend ctrl */
+       VSYNCOSD_WR_MPEG_REG(OSD2_BLEND_SRC_CTRL,
+               (0 & 0xf) << 0 |
+               (0 & 0x1) << 4 |
+               (blend_reg->postbld_src4_sel & 0xf) << 8 |
+               (blend_reg->postbld_osd2_premult & 0x1) << 16 |
+               (1 & 0x1) << 20);
+
+       VSYNCOSD_WR_MPEG_REG(VIU_OSD_BLEND_BLEND0_SIZE,
+               blend_reg->osd_blend_blend0_size);
+       VSYNCOSD_WR_MPEG_REG(VIU_OSD_BLEND_BLEND1_SIZE,
+               blend_reg->osd_blend_blend1_size);
+
+       VSYNCOSD_WR_MPEG_REG(VPP_OSD1_BLD_H_SCOPE,
+               blend_reg->vpp_osd1_blend_h_scope);
+       VSYNCOSD_WR_MPEG_REG(VPP_OSD1_BLD_V_SCOPE,
+               blend_reg->vpp_osd1_blend_v_scope);
+
+       VSYNCOSD_WR_MPEG_REG(VPP_OSD2_BLD_H_SCOPE,
+               blend_reg->vpp_osd2_blend_h_scope);
+       VSYNCOSD_WR_MPEG_REG(VPP_OSD2_BLD_V_SCOPE,
+               blend_reg->vpp_osd2_blend_v_scope);
+       for (i = 0; i < osd_count; i++) {
+               if (osd_hw.enable[i]) {
+               VSYNCOSD_WR_MPEG_REG(
+                       VIU_OSD_BLEND_DIN0_SCOPE_H + reg_offset * i,
+                       blend_reg->osd_blend_din_scope_h[i]);
+               VSYNCOSD_WR_MPEG_REG(
+                       VIU_OSD_BLEND_DIN0_SCOPE_V + reg_offset * i,
+                       blend_reg->osd_blend_din_scope_v[i]);
+               }
+       }
+}
+
+static int osd_setting_order(void)
+{
+       int i;
+       struct layer_blend_reg_s *blend_reg;
+       struct hw_osd_blending_s *blending;
+       u32 osd_count = osd_hw.osd_meson_dev.osd_count - 1;
+       bool update = false;
+       int line;
+
+       blending = &osd_blending;
+       blend_reg = &(blending->blend_reg);
+
+       blending->background_w = osd_hw.background_w;
+       blending->background_h = osd_hw.background_h;
+       blending->vinfo_width = osd_hw.vinfo_width;
+       blending->vinfo_height = osd_hw.vinfo_height;
+       set_blend_order(blending);
+
+       blending->layer_cnt = get_available_layers();
+       osd_log_dbg("layer_cnt:%d\n", blending->layer_cnt);
+
+       blending->b_exchange_din = false;
+       blending->b_exchange_blend_in = false;
+       blending->osd1_freescale_disable = false;
+
+       /* set blend mode */
+       set_blend_mode(blending);
+       generate_blend_din_table(blending);
+
+       set_blend_din(blending);
+
+       /* set blend path */
+       set_blend_path(blending);
 
-               postbld_src3_sel = 4;//src1 is bottom
-               postbld_src4_sel = 3;//src4 is top
-               temp = postbld_osd1_premult;
-               postbld_osd1_premult = postbld_osd2_premult;
-               postbld_osd2_premult = temp;
-       }
        osd_log_dbg("blend_din_en=%x,din_premult_en=%x,blend2_premult_en=%x\n",
-               blend_din_en,
-               din_premult_en,
-               blend2_premult_en);
+               blend_reg->blend_din_en,
+               blend_reg->din_premult_en,
+               blend_reg->blend2_premult_en);
 
        osd_log_dbg("din0_sel=%x,din2_sel=%x,din3_sel=%x\n",
-               din0_byp_blend,
-               din2_osd_sel,
-               din3_osd_sel);
+               blend_reg->din0_byp_blend,
+               blend_reg->din2_osd_sel,
+               blend_reg->din3_osd_sel);
 
        osd_log_dbg("postbld_osd1_premult=%x,postbld_osd2_premult=%x\n",
-               postbld_osd1_premult,
-               postbld_osd2_premult);
+               blend_reg->postbld_osd1_premult,
+               blend_reg->postbld_osd2_premult);
+
+       line = get_enter_encp_line();
+       if (osd_hw.osd_display_debug == ENCP_LINE)
+               osd_log_info(
+                       "enter osd_setting_order:cnt=%d,encp line=%d\n",
+                       cnt, line);
 
-       //spin_lock_irqsave(&osd_lock, lock_flags);
+       spin_lock_irqsave(&osd_lock, lock_flags);
+       if (blending->osd1_freescale_disable)
+               osd_hw.reg[DISP_FREESCALE_ENABLE].update_func(OSD1);
        for (i = 0; i < osd_count; i++) {
-               adjust_freescale_para(&osd_blending);
-               osd_hw.free_scale[i].h_enable = 1;
-               osd_hw.free_scale[i].v_enable = 1;
-               //osd_hw.free_scale_backup[i].h_enable = 1;
-               //osd_hw.free_scale_backup[i].v_enable = 1;
-               ret = osd_set_scan_mode(i);
-               if (ret)
+               if (osd_hw.enable[i]) {
+                       struct hw_osd_reg_s *osd_reg = &hw_osd_reg_array[i];
+
+                       update = is_freescale_para_changed(i);
                        osd_hw.reg[OSD_COLOR_MODE].update_func(i);
-               osd_hw.reg[OSD_FREESCALE_COEF].update_func(i);
-               osd_hw.reg[DISP_GEOMETRY].update_func(i);
-               osd_hw.reg[DISP_FREESCALE_ENABLE].update_func(i);
+                       osd_hw.reg[DISP_GEOMETRY].update_func(i);
+                       if (update || osd_update_window_axis) {
+                               osd_hw.reg
+                                       [OSD_FREESCALE_COEF].update_func(i);
+                               osd_hw.reg[DISP_FREESCALE_ENABLE]
+                               .update_func(i);
+                       }
+                       if (osd_hw.premult_en[i])
+                               VSYNCOSD_WR_MPEG_REG_BITS(
+                               osd_reg->osd_mali_unpack_ctrl, 0x1, 28, 1);
+                       else
+                               VSYNCOSD_WR_MPEG_REG_BITS(
+                               osd_reg->osd_mali_unpack_ctrl, 0x0, 28, 1);
+               }
                osd_hw.reg[OSD_ENABLE].update_func(i);
        }
-       /* osd blend ctrl */
-       VSYNCOSD_WR_MPEG_REG(VIU_OSD_BLEND_CTRL,
-               4                                 << 29|
-               blend2_premult_en << 27|
-               din0_byp_blend    << 26|
-               din2_osd_sel      << 25|
-               din3_osd_sel      << 24|
-               blend_din_en      << 20|
-               din_premult_en    << 16|
-               osd_blending.din_reoder_sel);
-       /* vpp osd1 blend ctrl */
-       VSYNCOSD_WR_MPEG_REG(OSD1_BLEND_SRC_CTRL,
-               (0 & 0xf) << 0 |
-               (0 & 0x1) << 4 |
-               (postbld_src3_sel & 0xf) << 8 |
-               (postbld_osd1_premult & 0x1) << 16|
-               (1 & 0x1) << 20);
-       /* vpp osd2 blend ctrl */
-       VSYNCOSD_WR_MPEG_REG(OSD2_BLEND_SRC_CTRL,
-               (0 & 0xf) << 0 |
-               (0 & 0x1) << 4 |
-               (postbld_src4_sel & 0xf) << 8 |
-               (postbld_osd2_premult & 0x1) << 16 |
-               (1 & 0x1) << 20);
-       blend_hsize = osd_hw.background_w;
-       blend_vsize = osd_hw.background_h;
 
-       VSYNCOSD_WR_MPEG_REG(VIU_OSD_BLEND_BLEND0_SIZE,
-               blend_vsize  << 16 |
-               blend_hsize);
-       VSYNCOSD_WR_MPEG_REG(VIU_OSD_BLEND_BLEND1_SIZE,
-               blend_vsize  << 16 |
-               blend_hsize);
-       #if 0
-       /* close vd1, vd2 for debug */
-       VSYNCOSD_WR_MPEG_REG(VD1_BLEND_SRC_CTRL, 0);
-       VSYNCOSD_WR_MPEG_REG(VD2_BLEND_SRC_CTRL, 0);
+       //for (i = 0; i < osd_count; i++)
+       //      osd_hw.reg[OSD_ENABLE].update_func(i);
 
-       VSYNCOSD_WR_MPEG_REG_BITS(DOLBY_PATH_CTRL,
-               0xf, 0, 4);
-       #endif
-       for (i = 0; i < osd_count; i++) {
-               if (osd_hw.enable[i])
-                       ret = osd_setting_blending_scope(i);
-       }
-       osd_hw.osd_blend_mode = osd_blend_mode;
-       ret = vpp_blend_setting(&osd_blending);
-       //spin_unlock_irqrestore(&osd_lock, lock_flags);
-       return ret;
+       if (osd_hw.hw_rdma_en)
+               osd_mali_afbc_start();
+
+       set_blend_reg(blend_reg);
+       save_blend_reg(blend_reg);
+       spin_unlock_irqrestore(&osd_lock, lock_flags);
+       line = get_exit_encp_line();
+       if (osd_hw.osd_display_debug == ENCP_LINE)
+               osd_log_info(
+                       "enter osd_setting_order:cnt=%d,encp line=%d\n",
+                       cnt, line);
 
+       osd_wait_vsync_hw();
        return 0;
 }
 
@@ -5235,6 +6202,194 @@ static void osd_setting_default_hwc(void)
                0x3, 2, 2);
 }
 
+static bool set_old_hwc_freescale(u32 index)
+{
+       bool freescale_update = false;
+       struct pandata_s freescale_dst[HW_OSD_COUNT];
+       u32 width_src = 0, width_dst = 0, height_src = 0, height_dst = 0;
+       u32 x_start, x_end, y_start, y_end;
+
+       width_dst = osd_hw.free_dst_data_backup[index].x_end -
+               osd_hw.free_dst_data_backup[index].x_start + 1;
+       width_src = osd_hw.free_src_data_backup[index].x_end -
+               osd_hw.free_src_data_backup[index].x_start + 1;
+
+       height_dst = osd_hw.free_dst_data_backup[index].y_end -
+               osd_hw.free_dst_data_backup[index].y_start + 1;
+       height_src = osd_hw.free_src_data_backup[index].y_end -
+               osd_hw.free_src_data_backup[index].y_start + 1;
+
+       if (osd_hw.free_scale_enable[index] ||
+               (width_src != width_dst) ||
+               (height_src != height_dst) ||
+               (osd_hw.src_data[index].w != osd_hw.dst_data[index].w) ||
+               (osd_hw.src_data[index].h != osd_hw.dst_data[index].h)) {
+               osd_hw.free_scale[index].h_enable = 1;
+               osd_hw.free_scale[index].v_enable = 1;
+               osd_hw.free_scale_enable[index] = 0x10001;
+               osd_hw.free_scale_mode[index] = 1;
+               if (osd_hw.free_scale_enable[index] !=
+                       osd_hw.free_scale_enable_backup[index]) {
+                       /* Todo: */
+                       osd_set_scan_mode(index);
+                       freescale_update = true;
+               }
+
+               osd_hw.pandata[index].x_start = osd_hw.src_data[index].x;
+               osd_hw.pandata[index].x_end =
+                       osd_hw.src_data[index].x + osd_hw.src_data[index].w - 1;
+               osd_hw.pandata[index].y_start = 0;
+               osd_hw.pandata[index].y_end = osd_hw.src_data[index].h - 1;
+
+               freescale_dst[index].x_start =
+                       osd_hw.free_dst_data_backup[index].x_start +
+                       (osd_hw.dst_data[index].x * width_dst) / width_src;
+               freescale_dst[index].x_end =
+                       osd_hw.free_dst_data_backup[index].x_start +
+                       ((osd_hw.dst_data[index].x + osd_hw.dst_data[index].w) *
+                       width_dst) / width_src - 1;
+
+               freescale_dst[index].y_start =
+                       osd_hw.free_dst_data_backup[index].y_start +
+                       (osd_hw.dst_data[index].y * height_dst) / height_src;
+               freescale_dst[index].y_end =
+                       osd_hw.free_dst_data_backup[index].y_start +
+                       ((osd_hw.dst_data[index].y + osd_hw.dst_data[index].h) *
+                       height_dst) / height_src - 1;
+
+               if (osd_hw.osd_reverse[index] == REVERSE_TRUE) {
+                       x_start = osd_hw.vinfo_width
+                               - freescale_dst[index].x_end - 1;
+                       y_start = osd_hw.vinfo_height
+                               - freescale_dst[index].y_end - 1;
+                       x_end = osd_hw.vinfo_width
+                               - freescale_dst[index].x_start - 1;
+                       y_end = osd_hw.vinfo_height
+                               - 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
+                               - freescale_dst[index].x_end - 1;
+                       x_end = osd_hw.vinfo_width
+                               - 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
+                               - freescale_dst[index].y_end - 1;
+                       y_end = osd_hw.vinfo_height
+                               - freescale_dst[index].y_start - 1;
+                       freescale_dst[index].y_start = y_start;
+                       freescale_dst[index].y_end = y_end;
+               }
+               if (memcmp(&(osd_hw.free_src_data[index]),
+                       &osd_hw.pandata[index],
+                       sizeof(struct pandata_s)) != 0 ||
+                       memcmp(&(osd_hw.free_dst_data[index]),
+                       &freescale_dst[index],
+                       sizeof(struct pandata_s)) != 0) {
+                       memcpy(&(osd_hw.free_src_data[index]),
+                               &osd_hw.pandata[index],
+                               sizeof(struct pandata_s));
+                       memcpy(&(osd_hw.free_dst_data[index]),
+                               &freescale_dst[index],
+                               sizeof(struct pandata_s));
+                       freescale_update = true;
+
+                       if ((height_dst != height_src) ||
+                               (width_dst != width_src))
+                               osd_set_dummy_data(index, 0);
+                       else
+                               osd_set_dummy_data(index, 0xff);
+                       osd_log_dbg("direct pandata x=%d,x_end=%d,y=%d,y_end=%d,width=%d,height=%d\n",
+                               osd_hw.pandata[index].x_start,
+                               osd_hw.pandata[index].x_end,
+                               osd_hw.pandata[index].y_start,
+                               osd_hw.pandata[index].y_end,
+                               osd_hw.src_data[index].w,
+                               osd_hw.src_data[index].h);
+                       osd_log_dbg("fence_map:xoffset=%d,yoffset=%d\n",
+                               osd_hw.src_data[index].x,
+                               osd_hw.src_data[index].y);
+                       osd_log_dbg("fence_map:dst_x=%d,dst_y=%d,dst_w=%d,dst_h=%d\n",
+                               osd_hw.dst_data[index].x,
+                               osd_hw.dst_data[index].y,
+                               osd_hw.dst_data[index].w,
+                               osd_hw.dst_data[index].h);
+               }
+       } else {
+               osd_hw.pandata[index].x_start = 0;
+               osd_hw.pandata[index].x_end = osd_hw.src_data[index].w - 1;
+               osd_hw.pandata[index].y_start = 0;
+               osd_hw.pandata[index].y_end = osd_hw.src_data[index].h - 1;
+
+               osd_hw.dispdata[index].x_start = osd_hw.dst_data[index].x;
+               osd_hw.dispdata[index].x_end =
+                       osd_hw.dst_data[index].x + osd_hw.dst_data[index].w - 1;
+               osd_hw.dispdata[index].y_start = osd_hw.dst_data[index].y;
+               osd_hw.dispdata[index].y_end =
+                       osd_hw.dst_data[index].y + osd_hw.dst_data[index].h - 1;
+               if (osd_hw.osd_reverse[index] == REVERSE_TRUE) {
+                       x_start = osd_hw.vinfo_width
+                               - osd_hw.dispdata[index].x_end - 1;
+                       y_start = osd_hw.vinfo_height
+                               - osd_hw.dispdata[index].y_end - 1;
+                       x_end = osd_hw.vinfo_width
+                               - osd_hw.dispdata[index].x_start - 1;
+                       y_end = osd_hw.vinfo_height
+                               - 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
+                               - osd_hw.dispdata[index].x_end - 1;
+                       x_end = osd_hw.vinfo_width
+                               - 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
+                               - osd_hw.dispdata[index].y_end - 1;
+                       y_end = osd_hw.vinfo_height
+                               - osd_hw.dispdata[index].y_start - 1;
+                       osd_hw.dispdata[index].y_start = y_start;
+                       osd_hw.dispdata[index].y_end = y_end;
+               }
+       }
+       return freescale_update;
+}
+static void osd_setting_old_hwc(void)
+{
+       int index = OSD1;
+       bool freescale_update = false;
+
+       spin_lock_irqsave(&osd_lock, lock_flags);
+       osd_hw.reg[OSD_COLOR_MODE].update_func(index);
+       freescale_update = set_old_hwc_freescale(index);
+       /* geometry and freescale need update with ioctl */
+       osd_hw.reg[DISP_GEOMETRY].update_func(index);
+       if ((osd_hw.free_scale_enable[index]
+               && osd_update_window_axis)
+               || freescale_update) {
+               if (!osd_hw.osd_display_debug)
+                       osd_hw.reg[DISP_FREESCALE_ENABLE]
+                               .update_func(index);
+               osd_update_window_axis = false;
+       }
+       if (!osd_hw.osd_display_debug)
+               osd_hw.reg[OSD_ENABLE]
+               .update_func(index);
+       spin_unlock_irqrestore(&osd_lock, lock_flags);
+       osd_wait_vsync_hw();
+}
+
 int osd_setting_blend(void)
 {
        int ret;
@@ -5250,14 +6405,15 @@ int osd_setting_blend(void)
        }
 
        if (osd_hw.osd_meson_dev.osd_ver < OSD_HIGH_ONE)
-               return 0;
-       if (osd_hw.hwc_enable) {
-               ret = osd_setting_order();
-               if (ret < 0)
-                       return -1;
-       } else
-               osd_setting_default_hwc();
-
+               osd_setting_old_hwc();
+       else {
+               if (osd_hw.hwc_enable) {
+                       ret = osd_setting_order();
+                       if (ret < 0)
+                               return -1;
+               } else
+                       osd_setting_default_hwc();
+       }
        return 0;
 }
 
@@ -5275,12 +6431,6 @@ void osd_mali_afbc_start(void)
                                /* afbc_enable |= 0x10000; */
                        }
                }
-               /*
-               if (osd_hw.afbc_start_in_vsync)
-                       VSYNCOSD_WR_MPEG_REG(
-                               VPU_MAFBC_SURFACE_CFG,
-                               afbc_enable);
-               */
                if (afbc_enable)
                        VSYNCOSD_WR_MPEG_REG(
                                VPU_MAFBC_COMMAND,
@@ -5317,7 +6467,6 @@ static void osd_basic_update_disp_geometry(u32 index)
                        /* set frame addr in linear: out_addr_id */
                        headr_addr = osd_hw.osd_afbcd[index].phy_addr;
                        out_addr = osd_hw.osd_afbcd[index].out_addr_id << 24;
-
                        /*  0:canvas_araddr
                         *  1:linear_araddr
                         */
@@ -5363,6 +6512,22 @@ static void osd_basic_update_disp_geometry(u32 index)
                        VSYNCOSD_WR_MPEG_REG(
                                osd_reg->afbc_output_buf_addr_high_s,
                                (out_addr >> 32) & 0xffffffff);
+                       if (osd_hw.osd_afbcd[index].enable) {
+                               VSYNCOSD_WR_MPEG_REG(
+                                       osd_reg->afbc_boundings_box_x_start_s,
+                                       osd_hw.src_data[index].x);
+                               VSYNCOSD_WR_MPEG_REG(
+                                       osd_reg->afbc_boundings_box_x_end_s,
+                                       osd_hw.src_data[index].x +
+                                       osd_hw.src_data[index].w - 1);
+                               VSYNCOSD_WR_MPEG_REG(
+                                       osd_reg->afbc_boundings_box_y_start_s,
+                                       osd_hw.src_data[index].y);
+                               VSYNCOSD_WR_MPEG_REG(
+                                       osd_reg->afbc_boundings_box_y_end_s,
+                                       osd_hw.src_data[index].y +
+                                       osd_hw.src_data[index].h -  1);
+                       }
                } else {
                        /* osd swtich to mali */
                        VSYNCOSD_WR_MPEG_REG_BITS(
@@ -5389,20 +6554,6 @@ static void osd_basic_update_disp_geometry(u32 index)
                         (osd_hw.free_src_data[index].x_end & 0x1fff) << 16;
                VSYNCOSD_WR_MPEG_REG(
                        osd_reg->osd_blk0_cfg_w1, data32);
-               if (osd_hw.osd_afbcd[index].enable) {
-                       VSYNCOSD_WR_MPEG_REG(
-                               osd_reg->afbc_boundings_box_x_start_s,
-                               osd_hw.free_src_data[index].x_start);
-                       VSYNCOSD_WR_MPEG_REG(
-                               osd_reg->afbc_boundings_box_x_end_s,
-                               osd_hw.free_src_data[index].x_end);
-                       VSYNCOSD_WR_MPEG_REG(
-                               osd_reg->afbc_boundings_box_y_start_s,
-                               osd_hw.free_src_data[index].y_start);
-                       VSYNCOSD_WR_MPEG_REG(
-                               osd_reg->afbc_boundings_box_y_end_s,
-                               osd_hw.free_src_data[index].y_end);
-               }
                data32 = ((osd_hw.free_src_data[index].y_start
                        + osd_hw.pandata[index].y_start) & 0x1fff)
                        | ((osd_hw.free_src_data[index].y_end
@@ -5414,41 +6565,20 @@ static void osd_basic_update_disp_geometry(u32 index)
                        | (osd_hw.pandata[index].x_end & 0x1fff) << 16;
                VSYNCOSD_WR_MPEG_REG(
                        osd_reg->osd_blk0_cfg_w1, data32);
-               if (osd_hw.osd_afbcd[index].enable) {
-                       u32 virtual_y_start, virtual_y_end;
-
-                       virtual_y_start = osd_hw.pandata[index].y_start %
-                               osd_hw.osd_afbcd[index].frame_height;
-                       virtual_y_end = osd_hw.pandata[index].y_end -
-                               osd_hw.pandata[index].y_start + virtual_y_start;
-                       VSYNCOSD_WR_MPEG_REG(
-                               osd_reg->afbc_boundings_box_x_start_s,
-                               osd_hw.pandata[index].x_start);
-                       VSYNCOSD_WR_MPEG_REG(
-                               osd_reg->afbc_boundings_box_x_end_s,
-                               osd_hw.pandata[index].x_end);
-                       VSYNCOSD_WR_MPEG_REG(
-                               osd_reg->afbc_boundings_box_y_start_s,
-                               virtual_y_start);
-                       VSYNCOSD_WR_MPEG_REG(
-                               osd_reg->afbc_boundings_box_y_end_s,
-                               virtual_y_end);
-               }
                data32 = (osd_hw.pandata[index].y_start & 0x1fff)
                        | (osd_hw.pandata[index].y_end & 0x1fff) << 16;
                VSYNCOSD_WR_MPEG_REG(osd_reg->osd_blk0_cfg_w2, data32);
        }
-
-       data32 = (osd_hw.free_src_data[OSD1].x_start & 0x1fff) |
-                        (osd_hw.free_src_data[OSD1].x_end & 0x1fff) << 16;
+       data32 = (osd_hw.src_data[index].x & 0x1fff) |
+                        ((osd_hw.src_data[index].x +
+                        osd_hw.src_data[index].w - 1) & 0x1fff) << 16;
        VSYNCOSD_WR_MPEG_REG(
-               hw_osd_reg_array[OSD1].osd_blk0_cfg_w1, data32);
+               hw_osd_reg_array[index].osd_blk0_cfg_w1, data32);
        buffer_w = ((data32 >> 16) & 0x1fff) - (data32 & 0x1fff) + 1;
-       data32 = ((osd_hw.free_src_data[OSD1].y_start
-               + osd_hw.pandata[OSD1].y_start) & 0x1fff)
-               | ((osd_hw.free_src_data[OSD1].y_end
-               + osd_hw.pandata[OSD1].y_start) & 0x1fff) << 16;
-       VSYNCOSD_WR_MPEG_REG(VIU_OSD1_BLK0_CFG_W2, data32);
+       data32 = (osd_hw.src_data[index].y & 0x1fff)
+               | ((osd_hw.src_data[index].y +
+               osd_hw.src_data[index].h - 1) & 0x1fff) << 16;
+       VSYNCOSD_WR_MPEG_REG(osd_reg->osd_blk0_cfg_w2, data32);
        buffer_h = ((data32 >> 16) & 0x1fff) - (data32 & 0x1fff) + 1;
        if (osd_hw.osd_meson_dev.has_dolby_vision) {
                VSYNCOSD_WR_MPEG_REG(
@@ -5914,7 +7044,7 @@ 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.osd_blend_mode = OSD_BLEND_NONE;
                osd_hw.background_w = 1920;
                osd_hw.background_h = 1080;
                for (idx = 0; idx < osd_hw.osd_meson_dev.osd_count; idx++) {
@@ -5924,8 +7054,8 @@ void osd_init_hw(u32 logo_loaded, u32 osd_probe,
                                MALI_AFBC_32X8_PIXEL << 1 |
                                MALI_AFBC_SPLIT_ON;
                        osd_hw.osd_afbcd[idx].afbc_start = 0;
-                       osd_hw.afbc_start_in_vsync = 0;
                        osd_hw.afbc_force_reset = 1;
+                       osd_hw.osd_afbcd[idx].out_addr_id = idx + 1;
                        if (idx < osd_hw.osd_meson_dev.osd_count - 1) {
                                /* TODO: temp set at here,
                                 * need move it to uboot
@@ -5957,6 +7087,7 @@ void osd_init_hw(u32 logo_loaded, u32 osd_probe,
                                hw_osd_reg_array[idx].osd_ctrl_stat, data32);
 #endif
                }
+               #if 0
                /* TODO: temp power down */
                switch_vpu_mem_pd_vmod(
                        VPU_VIU_OSD2,
@@ -5970,6 +7101,9 @@ void osd_init_hw(u32 logo_loaded, u32 osd_probe,
                switch_vpu_mem_pd_vmod(
                        VPU_OSD_BLD34,
                        VPU_MEM_POWER_DOWN);
+               #endif
+               osd_set_basic_urgent(true);
+               osd_set_two_ports(true);
                osd_setting_default_hwc();
        }
        /* disable deband as default */
@@ -6018,6 +7152,16 @@ void osd_init_hw(u32 logo_loaded, u32 osd_probe,
                 */
                osd_set_dummy_data(idx, 0xff);
        }
+       /* hwc_enable == 0 handler */
+       osd_hw.osd_fence[DISABLE].sync_fence_handler =
+               sync_render_single_fence;
+       osd_hw.osd_fence[DISABLE].toggle_buffer_handler =
+               osd_toggle_buffer_single;
+       /* hwc_enable == 1 handler */
+       osd_hw.osd_fence[ENABLE].sync_fence_handler =
+               sync_render_layers_fence;
+       osd_hw.osd_fence[ENABLE].toggle_buffer_handler =
+               osd_toggle_buffer_layers;
        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) {
@@ -6027,6 +7171,8 @@ void osd_init_hw(u32 logo_loaded, u32 osd_probe,
        osd_extra_canvas_alloc();
        osd_hw.antiflicker_mode = 0;
        osd_hw.osd_deband_enable = 1;
+       osd_hw.out_fence_fd = -1;
+       osd_hw.blend_bypass = 0;
        if (osd_hw.osd_meson_dev.osd_ver == OSD_SIMPLE) {
                data32 = osd_reg_read(
                        hw_osd_reg_array[OSD1].osd_fifo_ctrl_stat);
@@ -6036,12 +7182,11 @@ void osd_init_hw(u32 logo_loaded, u32 osd_probe,
        }
        osd_set_deband(osd_hw.osd_deband_enable);
        /* memset(osd_hw.rotate, 0, sizeof(struct osd_rotate_s)); */
+       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);
+               mutex_init(&post_fence_list_lock);
 #endif
-
-       if (osd_hw.fb_drvier_probe) {
 #ifdef FIQ_VSYNC
                osd_hw.fiq_handle_item.handle = vsync_isr;
                osd_hw.fiq_handle_item.key = (u32)vsync_isr;
@@ -6391,6 +7536,10 @@ void osd_get_hw_para(struct hw_para_s **para)
 {
        *para = &osd_hw;
 }
+void osd_get_blending_para(struct hw_osd_blending_s **para)
+{
+       *para = &osd_blending;
+}
 void osd_backup_screen_info(
        u32 index,
        char __iomem *screen_base,
@@ -6482,22 +7631,21 @@ static bool osd_direct_render(struct osd_plane_map_s *plane_map)
                plane_map->src_h,
                CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR);
        if (osd_hw.hwc_enable) {
-       #if 1
-               plane_map->zorder = 1;
-               plane_map->premult_en = 0;
-               plane_map->background_w = 1920;
-               plane_map->background_h = 1080;
-               plane_map->afbc_inter_format = 0x3;
-               plane_map->afbc_en = 0;
-       #endif
                /* just get para, need update via do_hwc */
                osd_hw.order[index] = plane_map->zorder;
-               osd_hw.premult_en[index] = plane_map->premult_en;
-               osd_hw.background_w = plane_map->background_w;
-               osd_hw.background_h = plane_map->background_h;
-               osd_hw.osd_afbcd[index].enable = plane_map->afbc_en;
+               switch (plane_map->blend_mode) {
+               case BLEND_MODE_PREMULTIPLIED:
+                       osd_hw.premult_en[index] = 1;
+                       break;
+               case BLEND_MODE_COVERAGE:
+               case BLEND_MODE_NONE:
+               case BLEND_MODE_INVALID:
+                       osd_hw.premult_en[index] = 0;
+                       break;
+               }
+               //Todo: fence_map.plane_alpha
                osd_hw.osd_afbcd[index].inter_format =
-                       plane_map->afbc_inter_format;
+                       plane_map->afbc_inter_format & 0x7fffffff;
 
                osd_hw.src_data[index].x = plane_map->src_x;
                osd_hw.src_data[index].y = plane_map->src_y;
@@ -6508,6 +7656,14 @@ static bool osd_direct_render(struct osd_plane_map_s *plane_map)
                osd_hw.dst_data[index].y = plane_map->dst_y;
                osd_hw.dst_data[index].w = plane_map->dst_w;
                osd_hw.dst_data[index].h = plane_map->dst_h;
+               osd_log_dbg2("index=%d\n", index);
+               osd_log_dbg2("order=%d\n", osd_hw.order[index]);
+               osd_log_dbg2("premult_en=%d\n", osd_hw.premult_en[index]);
+               osd_log_dbg2("osd_afbcd_en=%d\n",
+                       osd_hw.osd_afbcd[index].enable);
+               osd_log_dbg2("osd_afbcd_inter_format=%d\n",
+                       osd_hw.osd_afbcd[index].inter_format);
+
                return 0;
        }
 
@@ -6844,7 +8000,7 @@ void osd_page_flip(struct osd_plane_map_s *plane_map)
                if (index >= OSD2)
                        return;
        } else {
-               if (index >= OSD3)
+               if (index > OSD3)
                        return;
        }
 
@@ -6858,12 +8014,14 @@ void osd_page_flip(struct osd_plane_map_s *plane_map)
                osd_hw.vinfo_width = vinfo->width;
                osd_hw.vinfo_height = 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) {
                if (plane_map->phy_addr && plane_map->src_w
                                && plane_map->src_h && index == OSD1) {
                        osd_hw.fb_gem[index].canvas_idx =
-                               osd_extra_idx[index][ext_canvas_id];
-                       ext_canvas_id ^= 1;
+                               osd_extra_idx[index][ext_canvas_id[index]];
+                       ext_canvas_id[index] ^= 1;
                        color = convert_panel_format(plane_map->format);
                        if (color) {
                                osd_hw.color_info[index] = color;
@@ -6923,8 +8081,8 @@ void osd_page_flip(struct osd_plane_map_s *plane_map)
                                && plane_map->src_h) {
 #if 1
                        osd_hw.fb_gem[index].canvas_idx =
-                               osd_extra_idx[index][ext_canvas_id];
-                       ext_canvas_id ^= 1;
+                               osd_extra_idx[index][ext_canvas_id[index]];
+                       ext_canvas_id[index] ^= 1;
 #endif
                        color = convert_panel_format(plane_map->format);
                        if (color) {
index 7ad5aee..7b06f22 100644 (file)
@@ -110,13 +110,15 @@ extern void osd_setpal_hw(u32 index, unsigned int regno,
                                unsigned int red, unsigned int green,
                                unsigned int blue, unsigned int transp);
 extern void osd_enable_hw(u32 index, u32 enable);
+extern void osd_set_enable_hw(u32 index, u32 enable);
 extern void osd_pan_display_hw(u32 index, unsigned int xoffset,
                               unsigned int yoffset);
-extern int osd_sync_request(u32 index, u32 yres, u32 xoffset, u32 yoffset,
-                           s32 in_fence_fd);
+extern int osd_sync_request(u32 index, u32 yres,
+       struct fb_sync_request_s *request);
 extern int osd_sync_request_render(u32 index, u32 yres,
-       struct fb_sync_request_render_s *request,
+       struct sync_req_render_s *request,
        u32 phys_addr);
+extern int osd_sync_do_hwc(u32 width, u32 height);
 extern s32  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);
@@ -132,6 +134,7 @@ extern void osd_set_logo_index(int index);
 extern int osd_get_logo_index(void);
 extern int osd_get_init_hw_flag(void);
 extern void osd_get_hw_para(struct hw_para_s **para);
+extern void osd_get_blending_para(struct hw_osd_blending_s **para);
 extern int osd_set_debug_hw(const char *buf);
 extern char *osd_get_debug_hw(void);
 #ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
@@ -176,6 +179,7 @@ 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);
+int osd_get_capbility(u32 index);
 void osd_backup_screen_info(
        u32 index,
        char __iomem *screen_base,
@@ -189,4 +193,9 @@ 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);
+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 output_save_info(void);
 #endif
index 9e11f87..947835b 100644 (file)
 
 #define VPP_POST_BLEND_BLEND_DUMMY_DATA            0x3968
 #define VPP_POST_BLEND_DUMMY_ALPHA                 0x3969
+#define VPP_RDARB_MODE                             0x3978
+#define VPU_RDARB_MODE_L2C1                        0x279d
 #endif
index a7e7935..fb6153e 100644 (file)
@@ -24,15 +24,48 @@ enum {
        GE2D_COMPOSE_MODE = 2,
 };
 
-struct fb_sync_request_s {
+#define FB_SYNC_REQUEST_MAGIC  0x54376812
+#define FB_SYNC_REQUEST_RENDER_MAGIC_V1  0x55386816
+#define FB_SYNC_REQUEST_RENDER_MAGIC_V2  0x55386817
+
+#define AFBC_EN                (1 << 31)
+#define TILED_HEADER_EN        (1 << 18)
+#define SUPER_BLOCK_ASPECT     (1 << 16)
+#define BLOCK_SPLIT            (1 << 9)
+#define YUV_TRANSFORM          (1 << 8)
+
+/* Blend modes, settable per layer */
+enum {
+       BLEND_MODE_INVALID = 0,
+       /* colorOut = colorSrc */
+       BLEND_MODE_NONE = 1,
+       /* colorOut = colorSrc + colorDst * (1 - alphaSrc) */
+       BLEND_MODE_PREMULTIPLIED = 2,
+       /* colorOut = colorSrc * alphaSrc + colorDst * (1 - alphaSrc) */
+       BLEND_MODE_COVERAGE = 3,
+};
+
+struct sync_req_old_s {
        unsigned int xoffset;
        unsigned int yoffset;
        int in_fen_fd;
        int out_fen_fd;
 };
 
-#if 0
-struct fb_sync_request_render_s {
+struct sync_req_s {
+       int magic;
+       int len;
+       unsigned int xoffset;
+       unsigned int yoffset;
+       int in_fen_fd;
+       int out_fen_fd;
+       int format;
+       int reserved[3];
+};
+
+struct sync_req_render_s {
+       int magic;
+       int len;
        unsigned int    xoffset;
        unsigned int    yoffset;
        int             in_fen_fd;
@@ -49,33 +82,24 @@ struct fb_sync_request_render_s {
        unsigned int    dst_h;
        int                             byte_stride;
        int                             pxiel_stride;
-       unsigned int    reserve;
+       int  afbc_inter_format;
+       unsigned int  zorder;
+       unsigned int  blend_mode;
+       int  plane_alpha;
+       int  reserve;
 };
-#endif
-struct fb_sync_request_render_s {
-unsigned int    xoffset;
-unsigned int    yoffset;
-int             in_fen_fd;
-int             out_fen_fd;
-int             width;
-int             height;
-int             format;
-int             shared_fd;
-unsigned int    op;
-unsigned int    type; /*direct render or ge2d*/
-unsigned int    dst_x;
-unsigned int    dst_y;
-unsigned int    dst_w;
-unsigned int    dst_h;
-int     byte_stride;
-int     pxiel_stride;
-unsigned int  background_w;
-unsigned int  background_h;
-unsigned int  zorder;
-unsigned int  premult_en;
-unsigned int  afbc_en;
-unsigned int  afbc_inter_format;
-int  reserve;
+
+struct fb_sync_request_s {
+       union {
+               struct sync_req_old_s sync_req_old;
+               struct sync_req_s sync_req;
+               struct sync_req_render_s sync_req_render;
+       };
 };
 
+struct do_hwc_cmd_s {
+       int out_fen_fd;
+       unsigned int  background_w;
+       unsigned int  background_h;
+};
 #endif