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;
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 |
(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);
(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 */
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);
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,
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
}
#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
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 &&
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 &=
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:
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)
{
struct class_attribute *attr,
const char *buf, size_t count)
{
-
int r;
int val;
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,
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),
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
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 */
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)
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>");