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