From 3000b7c70268b5093534773bf3149466ba3d0eec Mon Sep 17 00:00:00 2001 From: Brian Zhu Date: Fri, 18 Jan 2019 03:25:21 +0800 Subject: [PATCH] vpp: add osd and video zorder control [2/6] 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 --- drivers/amlogic/media/osd/osd_backup.c | 6 +- drivers/amlogic/media/osd/osd_hw.c | 58 +++++--- drivers/amlogic/media/osd/osd_hw.h | 1 + drivers/amlogic/media/video_sink/video.c | 205 ++++++++++++++++++++++++--- include/linux/amlogic/media/video_sink/vpp.h | 4 + 5 files changed, 232 insertions(+), 42 deletions(-) diff --git a/drivers/amlogic/media/osd/osd_backup.c b/drivers/amlogic/media/osd/osd_backup.c index 64d9cd9..9ad324f 100644 --- a/drivers/amlogic/media/osd/osd_backup.c +++ b/drivers/amlogic/media/osd/osd_backup.c @@ -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; diff --git a/drivers/amlogic/media/osd/osd_hw.c b/drivers/amlogic/media/osd/osd_hw.c index 9eee092..acf4bd4 100644 --- a/drivers/amlogic/media/osd/osd_hw.c +++ b/drivers/amlogic/media/osd/osd_hw.c @@ -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, diff --git a/drivers/amlogic/media/osd/osd_hw.h b/drivers/amlogic/media/osd/osd_hw.h index 61c14dc..874c978 100644 --- a/drivers/amlogic/media/osd/osd_hw.h +++ b/drivers/amlogic/media/osd/osd_hw.h @@ -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); diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index 2069094..b460fdb 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -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 "); diff --git a/include/linux/amlogic/media/video_sink/vpp.h b/include/linux/amlogic/media/video_sink/vpp.h index bc2068f..f61c44d 100644 --- a/include/linux/amlogic/media/video_sink/vpp.h +++ b/include/linux/amlogic/media/video_sink/vpp.h @@ -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 { -- 2.7.4