vpp: add osd and video zorder control [2/6]
authorBrian Zhu <brian.zhu@amlogic.com>
Thu, 17 Jan 2019 19:25:21 +0000 (03:25 +0800)
committerJianxin Pan <jianxin.pan@amlogic.com>
Wed, 30 Jan 2019 11:42:14 +0000 (03:42 -0800)
PD#SWPL-85

Problem:
Upper layer need control osd and video layer zorder

Solution:
1.Add video layer zorder interface by sysfs and ioctl
2.Switch the osd and video layer order in vsync

Verify:
Verify on U212

Change-Id: Ic50e81784b865cc57e4ab9a63d74806f7a8721cf
Signed-off-by: Brian Zhu <brian.zhu@amlogic.com>
drivers/amlogic/media/osd/osd_backup.c
drivers/amlogic/media/osd/osd_hw.c
drivers/amlogic/media/osd/osd_hw.h
drivers/amlogic/media/video_sink/video.c
include/linux/amlogic/media/video_sink/vpp.h

index 64d9cd9..9ad324f 100644 (file)
@@ -1538,7 +1538,11 @@ static s32 get_recovery_item_g12a(u32 addr, u32 *value, u32 *mask)
                        u32 regmask = table->mask;
                        u32 real_value = osd_reg_read(addr);
 
-                       if ((real_value & regmask)
+                       if (enable_vd_zorder &&
+                               (addr == OSD2_BLEND_SRC_CTRL)) {
+                               ret = 1;
+                               table->recovery = 0;
+                       } else if ((real_value & regmask)
                                == (table->val & regmask)) {
                                ret = 1;
                                *mask = regmask;
index 9eee092..acf4bd4 100644 (file)
@@ -597,6 +597,10 @@ static unsigned int supsend_delay;
 module_param(supsend_delay, uint, 0664);
 MODULE_PARM_DESC(supsend_delay, "supsend_delay");
 
+int enable_vd_zorder = 1;
+MODULE_PARM_DESC(enable_vd_zorder, "\n enable_vd_zorder\n");
+module_param(enable_vd_zorder, uint, 0664);
+
 static int vsync_enter_line_max;
 static int vsync_exit_line_max;
 static int vsync_line_threshold = 950;
@@ -5149,14 +5153,16 @@ static void osd_update_enable(u32 index)
                if (osd_hw.enable[index] == ENABLE)
                        postbld_src_sel = (index == 0) ? 3 : 4;
                if (index == 0)
-                       VSYNCOSD_WR_MPEG_REG(OSD1_BLEND_SRC_CTRL,
+                       VSYNCOSD_WR_MPEG_REG(
+                               OSD1_BLEND_SRC_CTRL,
                                (0 & 0xf) << 0 |
                                (0 & 0x1) << 4 |
                                (postbld_src_sel & 0xf) << 8 |
                                (0 & 0x1) << 16|
                                (1 & 0x1) << 20);
-               else if (index == 1)
-                       VSYNCOSD_WR_MPEG_REG(OSD2_BLEND_SRC_CTRL,
+               else if ((index == 1) && (!enable_vd_zorder))
+                       VSYNCOSD_WR_MPEG_REG(
+                               OSD2_BLEND_SRC_CTRL,
                                (0 & 0xf) << 0 |
                                (0 & 0x1) << 4 |
                                (postbld_src_sel & 0xf) << 8 |
@@ -7457,12 +7463,15 @@ static void set_blend_reg(struct layer_blend_reg_s *blend_reg)
                (0 << 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 |
-               (0 << 16) |
-               (1 & 0x1) << 20);
+       if (!enable_vd_zorder)
+               VSYNCOSD_WR_MPEG_REG(
+                       OSD2_BLEND_SRC_CTRL,
+                       (0 & 0xf) << 0 |
+                       (0 & 0x1) << 4 |
+                       (blend_reg->postbld_src4_sel & 0xf)
+                       << 8 |
+                       (0 << 16) |
+                       (1 & 0x1) << 20);
 
        VSYNCOSD_WR_MPEG_REG(VIU_OSD_BLEND_BLEND0_SIZE,
                blend_reg->osd_blend_blend0_size);
@@ -7733,12 +7742,16 @@ static void osd_setting_default_hwc(void)
                (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);
+       if (!enable_vd_zorder)
+               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);
 
        /* Do later: different format select different dummy_data */
        /* used default dummy data */
@@ -9237,15 +9250,19 @@ void  osd_suspend_hw(void)
                        osd_reg_read(VIU_OSD_BLEND_CTRL);
                osd_hw.reg_status_save1 =
                        osd_reg_read(OSD1_BLEND_SRC_CTRL);
-               osd_hw.reg_status_save2 =
-                       osd_reg_read(OSD2_BLEND_SRC_CTRL);
+
                osd_hw.reg_status_save3 =
                        osd_reg_read(VPP_RDARB_REQEN_SLV);
                osd_hw.reg_status_save4 =
                        osd_reg_read(VPU_MAFBC_SURFACE_CFG);
                osd_reg_clr_mask(VIU_OSD_BLEND_CTRL, 0xf0000);
                osd_reg_clr_mask(OSD1_BLEND_SRC_CTRL, 0xf0f);
-               osd_reg_clr_mask(OSD2_BLEND_SRC_CTRL, 0xf0f);
+               if (!enable_vd_zorder) {
+                       osd_hw.reg_status_save2 =
+                               osd_reg_read(OSD2_BLEND_SRC_CTRL);
+                       osd_reg_clr_mask(
+                               OSD2_BLEND_SRC_CTRL, 0xf0f);
+               }
                osd_reg_clr_mask(VPP_RDARB_REQEN_SLV,
                        rdarb_reqen_slv);
                osd_reg_write(VPU_MAFBC_SURFACE_CFG, 0);
@@ -9300,8 +9317,9 @@ void osd_resume_hw(void)
                        osd_hw.reg_status_save);
                osd_reg_write(OSD1_BLEND_SRC_CTRL,
                        osd_hw.reg_status_save1);
-               osd_reg_write(OSD2_BLEND_SRC_CTRL,
-                       osd_hw.reg_status_save2);
+               if (!enable_vd_zorder)
+                       osd_reg_write(OSD2_BLEND_SRC_CTRL,
+                               osd_hw.reg_status_save2);
                osd_reg_write(VPP_RDARB_REQEN_SLV,
                        osd_hw.reg_status_save3);
                osd_reg_write(VPU_MAFBC_SURFACE_CFG,
index 61c14dc..874c978 100644 (file)
@@ -30,6 +30,7 @@
 extern int int_viu_vsync;
 extern int int_viu2_vsync;
 extern struct hw_para_s osd_hw;
+extern int enable_vd_zorder;
 
 #ifdef CONFIG_HIBERNATION
 extern void osd_freeze_hw(void);
index 2069094..b460fdb 100644 (file)
@@ -410,6 +410,8 @@ static u32 layer_cap;
 
 static struct disp_info_s glayer_info[MAX_VD_LAYERS];
 
+static u32 reference_zorder = 128;
+
 #define MAX_ZOOM_RATIO 300
 
 #define VPP_PREBLEND_VD_V_END_LIMIT 2304
@@ -5882,6 +5884,45 @@ void set_hdr_to_frame(struct vframe_s *vf)
 }
 #endif
 
+static int vpp_zorder_check(void)
+{
+       int force_flush = 0;
+       u32 layer0_sel = 0; /* vd1 */
+       u32 layer1_sel = 1; /* vd2 */
+
+       if (legacy_vpp)
+               return 0;
+
+       if (glayer_info[1].zorder < glayer_info[0].zorder) {
+               layer0_sel = 1;
+               layer1_sel = 0;
+               if ((glayer_info[0].zorder >= reference_zorder)
+                       && (glayer_info[1].zorder < reference_zorder))
+                       layer0_sel++;
+       } else {
+               layer0_sel = 0;
+               layer1_sel = 1;
+               if ((glayer_info[1].zorder >= reference_zorder)
+                       && (glayer_info[0].zorder < reference_zorder))
+                       layer1_sel++;
+       }
+
+       glayer_info[0].cur_sel_port = layer0_sel;
+       glayer_info[1].cur_sel_port = layer1_sel;
+
+       if ((glayer_info[0].cur_sel_port !=
+               glayer_info[0].last_sel_port) ||
+               (glayer_info[1].cur_sel_port !=
+               glayer_info[1].last_sel_port)) {
+               force_flush = 1;
+               glayer_info[0].last_sel_port =
+                       glayer_info[0].cur_sel_port;
+               glayer_info[1].last_sel_port =
+                       glayer_info[1].cur_sel_port;
+       }
+       return force_flush;
+}
+
 #ifdef FIQ_VSYNC
 void vsync_fisr_in(void)
 #else
@@ -7428,6 +7469,7 @@ SET_FILTER:
 
        if (!legacy_vpp) {
                u32 set_value = 0;
+               int force_flush = vpp_zorder_check();
 
                /* for sr core0, put it between prebld & pps as default */
                if (cur_frame_par &&
@@ -7484,31 +7526,60 @@ SET_FILTER:
                        VPP_PREBLEND_EN |
                        VPP_POSTBLEND_EN |
                        0xf);
-               if (vpp_misc_set != vpp_misc_save) {
-                       /* vd1 need always enable pre bld */
-                       if (vpp_misc_set & VPP_VD1_POSTBLEND)
-                               set_value =
-                                       ((1 << 16) | /* post bld premult*/
-                                       (1 << 8) | /* post src */
-                                       (1 << 4) | /* pre bld premult*/
+               if ((vpp_misc_set != vpp_misc_save)
+                       || force_flush) {
+                       u32 port_val[3] = {0, 0, 0};
+                       u32 vd1_port, vd2_port, icnt;
+                       u32 post_blend_reg[3] = {
+                               VD1_BLEND_SRC_CTRL,
+                               VD2_BLEND_SRC_CTRL,
+                               OSD2_BLEND_SRC_CTRL
+                       };
+
+                       /* just reset the select port */
+                       if ((glayer_info[0].cur_sel_port > 2)
+                               || (glayer_info[1].cur_sel_port > 2)) {
+                               glayer_info[0].cur_sel_port = 0;
+                               glayer_info[1].cur_sel_port = 1;
+                       }
+
+                       vd1_port = glayer_info[0].cur_sel_port;
+                       vd2_port = glayer_info[1].cur_sel_port;
+
+                       /* post bld premult*/
+                       port_val[0] |= (1 << 16);
+
+                       /* vd2 path sel */
+                       if (vpp_misc_set & VPP_VD2_POSTBLEND)
+                               port_val[1] |= (1 << 20);
+                       else
+                               port_val[1] &= ~(1 << 20);
+
+                       /* osd2 path sel */
+                       port_val[2] |= (1 << 20);
+
+                       if (vpp_misc_set & VPP_VD1_POSTBLEND) {
+                                /* post src */
+                               port_val[vd1_port] |= (1 << 8);
+                               port_val[0] |=
+                                       ((1 << 4) | /* pre bld premult*/
                                        (1 << 0)); /* pre bld src 1 */
-                       VSYNC_WR_MPEG_REG(
-                               VD1_BLEND_SRC_CTRL + cur_dev->vpp_off,
-                               set_value);
+                       } else
+                               port_val[0] &= ~0xff;
 
-                       set_value = 0;
                        if (vpp_misc_set & VPP_VD2_POSTBLEND)
-                               set_value =
-                                       ((1 << 20) |
-                                       (0 << 16) | /* post bld premult*/
-                                       (2 << 8)); /* post src */
+                                /* post src */
+                               port_val[vd2_port] |= (2 << 8);
                        else if (vpp_misc_set & VPP_VD2_PREBLEND)
-                               set_value =
+                               port_val[1] |=
                                        ((1 << 4) | /* pre bld premult*/
                                        (2 << 0)); /* pre bld src 1 */
-                       VSYNC_WR_MPEG_REG(
-                               VD2_BLEND_SRC_CTRL + cur_dev->vpp_off,
-                               set_value);
+
+                       for (icnt = 0; icnt < 3; icnt++)
+                               VSYNC_WR_MPEG_REG(
+                                       post_blend_reg[icnt]
+                                       + cur_dev->vpp_off,
+                                       port_val[icnt]);
 
                        set_value = vpp_misc_set;
                        set_value &=
@@ -8980,10 +9051,26 @@ static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg)
 
        case AMSTREAM_IOC_GET_PIP_ZORDER:
        case AMSTREAM_IOC_GET_ZORDER:
+               put_user(layer->zorder, (u32 __user *)argp);
                break;
 
        case AMSTREAM_IOC_SET_PIP_ZORDER:
-       case AMSTREAM_IOC_SET_ZORDER:
+       case AMSTREAM_IOC_SET_ZORDER:{
+                       u32 zorder, new_prop = 0;
+
+                       if (copy_from_user(&zorder, argp, sizeof(u32)) == 0) {
+                               if (layer->zorder != zorder)
+                                       new_prop = 1;
+                               layer->zorder = zorder;
+                               if ((layer->layer_id == 0) && new_prop)
+                                       video_property_changed = 1;
+#ifdef VIDEO_PIP
+                               else if ((layer->layer_id == 1) && new_prop)
+                                       pip_property_changed = 1;
+#endif
+                       } else
+                               ret = -EFAULT;
+               }
                break;
 
        case AMSTREAM_IOC_QUERY_LAYER:
@@ -10981,6 +11068,36 @@ static ssize_t video_inuse_store(struct class *class,
        return count;
 }
 
+static ssize_t video_zorder_show(
+       struct class *cla,
+       struct class_attribute *attr,
+       char *buf)
+{
+       struct disp_info_s *layer = &glayer_info[0];
+
+       return sprintf(buf, "%d\n", layer->zorder);
+}
+
+static ssize_t video_zorder_store(
+       struct class *cla,
+       struct class_attribute *attr,
+       const char *buf, size_t count)
+{
+       int zorder;
+       int ret = 0;
+       struct disp_info_s *layer = &glayer_info[0];
+
+       ret = kstrtoint(buf, 0, &zorder);
+       if (ret < 0)
+               return -EINVAL;
+
+       if (zorder != layer->zorder) {
+               layer->zorder = zorder;
+               video_property_changed = 1;
+       }
+       return count;
+}
+
 #ifdef VIDEO_PIP
 static int _videopip_set_disable(u32 val)
 {
@@ -11076,7 +11193,6 @@ static ssize_t videopip_disable_store(
        struct class_attribute *attr,
        const char *buf, size_t count)
 {
-
        int r;
        int val;
 
@@ -11182,6 +11298,36 @@ static ssize_t videopip_global_output_store(
        return count;
 }
 
+static ssize_t videopip_zorder_show(
+       struct class *cla,
+       struct class_attribute *attr,
+       char *buf)
+{
+       struct disp_info_s *layer = &glayer_info[1];
+
+       return sprintf(buf, "%d\n", layer->zorder);
+}
+
+static ssize_t videopip_zorder_store(
+       struct class *cla,
+       struct class_attribute *attr,
+       const char *buf, size_t count)
+{
+       int zorder;
+       int ret = 0;
+       struct disp_info_s *layer = &glayer_info[1];
+
+       ret = kstrtoint(buf, 0, &zorder);
+       if (ret < 0)
+               return -EINVAL;
+
+       if (zorder != layer->zorder) {
+               layer->zorder = zorder;
+               pip_property_changed = 1;
+       }
+       return count;
+}
+
 static ssize_t videopip_state_show(
        struct class *cla,
        struct class_attribute *attr,
@@ -11445,6 +11591,10 @@ static struct class_attribute amvideo_class_attrs[] = {
               0664,
               video_inuse_show,
               video_inuse_store),
+        __ATTR(video_zorder,
+              0664,
+              video_zorder_show,
+              video_zorder_store),
        __ATTR_RO(frame_addr),
        __ATTR_RO(frame_canvas_width),
        __ATTR_RO(frame_canvas_height),
@@ -11483,6 +11633,10 @@ static struct class_attribute amvideo_class_attrs[] = {
               0664,
               videopip_global_output_show,
               videopip_global_output_store),
+        __ATTR(videopip_zorder,
+              0664,
+              videopip_zorder_show,
+              videopip_zorder_store),
        __ATTR_RO(videopip_state),
 #endif
        __ATTR_NULL
@@ -11943,6 +12097,8 @@ static int __init video_early_init(void)
                WRITE_VCBUS_REG(
                        VPP_POST_BLEND_DUMMY_ALPHA,
                        0x7fffffff);
+               WRITE_VCBUS_REG_BITS(
+                       VPP_MISC1, 0x100, 0, 9);
        }
        if (is_meson_tl1_cpu()) {
                /* force bypass dolby for TL1, no dolby function */
@@ -12209,9 +12365,13 @@ static int __init video_init(void)
                goto err5;
        }
 
+       /* make vd1 below vd2 */
        for (i = 0; i < MAX_VD_LAYERS; i++) {
                vpp_disp_info_init(&glayer_info[i], i);
                glayer_info[i].wide_mode = 1;
+               glayer_info[i].zorder = reference_zorder - 2 + i;
+               glayer_info[i].cur_sel_port = i;
+               glayer_info[i].last_sel_port = i;
        }
 
        if (legacy_vpp)
@@ -12505,6 +12665,9 @@ module_param(toggle_count, uint, 0664);
 MODULE_PARM_DESC(vpp_hold_line, "\n vpp_hold_line\n");
 module_param(vpp_hold_line, uint, 0664);
 
+MODULE_PARM_DESC(reference_zorder, "\n reference_zorder\n");
+module_param(reference_zorder, uint, 0664);
+
 MODULE_DESCRIPTION("AMLOGIC video output driver");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Tim Yao <timyao@amlogic.com>");
index bc2068f..f61c44d 100644 (file)
@@ -183,6 +183,10 @@ struct disp_info_s {
        s32 global_offset_y;
        u32 speed_check_width;
        u32 speed_check_height;
+
+       u32 zorder;
+       u32 cur_sel_port;
+       u32 last_sel_port;
 };
 
 enum select_scaler_path_e {