osd: range of mouse is wrong under 4K mode [1/2]
authorJian Cao <jian.cao@amlogic.com>
Wed, 5 Dec 2018 07:31:30 +0000 (15:31 +0800)
committerLuan Yuan <luan.yuan@amlogic.com>
Mon, 17 Dec 2018 06:51:32 +0000 (14:51 +0800)
PD#SWPL-2551

Problem:
range of mouse is wrong under 4K mode

Solution:
new cursor coordinate paras without using scale
add osd_cursor_hw_no_scale() to deal with it.

Verify:
verified on P212

Change-Id: I1748df569b96522eb58dc00af862983bca17815a
Signed-off-by: Jian Cao <jian.cao@amlogic.com>
drivers/amlogic/media/osd/osd_fb.c
drivers/amlogic/media/osd/osd_hw.c
drivers/amlogic/media/osd/osd_hw.h

index 96768bd..ed2eebb 100644 (file)
@@ -1597,8 +1597,16 @@ static int osd_cursor(struct fb_info *fbi, struct fb_cursor *var)
                startx = fb_dev->osd_ctl.disp_start_x;
                starty = fb_dev->osd_ctl.disp_start_y;
        }
-       osd_cursor_hw(fbi->node, (s16)var->hot.x, (s16)var->hot.y, (s16)startx,
-                     (s16)starty, fbi->var.xres, fbi->var.yres);
+
+       if (osd_hw.hwc_enable)
+               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);
+       else
+               osd_cursor_hw(fbi->node, (s16)var->hot.x,
+                       (s16)var->hot.y, (s16)startx, (s16)starty,
+                       fbi->var.xres, fbi->var.yres);
+
        return 0;
 }
 
index c3e4a1c..1d10d04 100644 (file)
@@ -8791,6 +8791,151 @@ void osd_cursor_hw(u32 index, s16 x, s16 y, s16 xstart, s16 ystart, u32 osd_w,
                osd_hw.dispdata[OSD2].y_start, osd_hw.dispdata[OSD2].y_end);
 }
 
+void osd_cursor_hw_no_scale(u32 index, s16 x, s16 y, s16 xstart, s16 ystart,
+                       u32 osd_w, u32 osd_h)
+{
+       struct pandata_s disp_tmp;
+       struct vinfo_s *vinfo = NULL;
+       int w = 0, h = 0;
+       int w_diff = 0;
+
+       if (index != 1)
+               return;
+
+       osd_log_dbg2("cursor: x=%d, y=%d, x0=%d, y0=%d, w=%d, h=%d\n",
+                       x, y, xstart, ystart, osd_w, osd_h);
+
+       if (osd_hw.free_scale_mode[OSD1]) {
+               if (osd_hw.free_scale_enable[OSD1])
+                       memcpy(&disp_tmp, &osd_hw.cursor_dispdata[OSD1],
+                                       sizeof(struct pandata_s));
+               else
+                       memcpy(&disp_tmp, &osd_hw.dispdata[OSD1],
+                                       sizeof(struct pandata_s));
+       } else
+               memcpy(&disp_tmp, &osd_hw.dispdata[OSD1],
+                               sizeof(struct pandata_s));
+
+       if (osd_hw.field_out_en) {
+               disp_tmp.y_start *= 2;
+               disp_tmp.y_end *= 2;
+       }
+
+       if (osd_hw.osd_reverse[OSD2] == REVERSE_TRUE) {
+               vinfo = get_current_vinfo();
+
+               if ((vinfo == NULL) || (vinfo->mode == VMODE_INIT_NULL))
+                       return;
+
+               w = vinfo->width;
+               h = vinfo->height;
+
+               x = w - x;
+               y = h - y;
+       }
+
+       x += xstart;
+       y += ystart;
+
+       if (osd_hw.osd_reverse[OSD2] == REVERSE_TRUE) {
+               if (osd_w >= osd_h)
+                       w_diff = osd_w - osd_h;
+               else
+                       w_diff = 0;
+               osd_hw.pandata[OSD2].x_start = w_diff;
+               osd_hw.pandata[OSD2].x_end = osd_w - 1;
+               osd_hw.pandata[OSD2].y_start = 0;
+               osd_hw.pandata[OSD2].y_end = osd_h - 1;
+               x -= osd_w;
+               y -= osd_h;
+               osd_log_dbg2("x=%d,y=%d\n", x, y);
+       }
+
+
+       /*
+        * Use pandata to show a partial cursor when it is at the edge because
+        * the registers can't have negative values and because we need to
+        * manually clip the cursor when it is past the edge.  The edge is
+        * hardcoded to the OSD0 area.
+        */
+       osd_hw.dispdata[OSD2].x_start = x;
+       osd_hw.dispdata[OSD2].y_start = y;
+       if (osd_hw.osd_reverse[OSD2] == REVERSE_TRUE) {
+               if (x <  disp_tmp.x_start) {
+                       /* if negative position, set osd x pan. */
+                       if ((disp_tmp.x_start - x) < osd_w) {
+                               osd_hw.pandata[OSD2].x_start =
+                                       w_diff;
+                               osd_hw.pandata[OSD2].x_end =
+                                       osd_w - 1 - (disp_tmp.x_start - x);
+                       }
+                       /* set osd x to disp_tmp.x_start */
+                       osd_hw.dispdata[OSD2].x_start = disp_tmp.x_start;
+               }
+               if (y < disp_tmp.y_start) {
+                       /* if negative position, set osd y pan. */
+                       if ((disp_tmp.y_start - y) < osd_h) {
+                               osd_hw.pandata[OSD2].y_start = 0;
+                               osd_hw.pandata[OSD2].y_end =
+                                       osd_h - 1 - (disp_tmp.y_start - y);
+                       }
+                       /* set osd y to disp_tmp.y_start */
+                       osd_hw.dispdata[OSD2].y_start = disp_tmp.y_start;
+               }
+       } else {
+               if (x <  disp_tmp.x_start) {
+                       /* if negative position, set osd to 0,y and pan. */
+                       if ((disp_tmp.x_start - x) < osd_w) {
+                               osd_hw.pandata[OSD2].x_start =
+                                       disp_tmp.x_start - x;
+                               osd_hw.pandata[OSD2].x_end = osd_w - 1;
+                       }
+                       osd_hw.dispdata[OSD2].x_start = 0;
+               } else {
+                       osd_hw.pandata[OSD2].x_start = 0;
+                       if (x + osd_w > disp_tmp.x_end) {
+                               /*
+                                * if past positive edge,
+                                * set osd to inside of the edge and pan.
+                                */
+                               if (x < disp_tmp.x_end)
+                                       osd_hw.pandata[OSD2].x_end =
+                                       disp_tmp.x_end - x;
+                       } else
+                               osd_hw.pandata[OSD2].x_end = osd_w - 1;
+               }
+               if (y < disp_tmp.y_start) {
+                       if ((disp_tmp.y_start - y) < osd_h) {
+                               osd_hw.pandata[OSD2].y_start =
+                                       disp_tmp.y_start - y;
+                               osd_hw.pandata[OSD2].y_end = osd_h - 1;
+                       }
+                       osd_hw.dispdata[OSD2].y_start = 0;
+               } else {
+                       osd_hw.pandata[OSD2].y_start = 0;
+                       if (y + osd_h > disp_tmp.y_end) {
+                               if (y < disp_tmp.y_end)
+                                       osd_hw.pandata[OSD2].y_end =
+                                       disp_tmp.y_end - y;
+                       } else
+                               osd_hw.pandata[OSD2].y_end = osd_h - 1;
+               }
+       }
+
+       if (osd_hw.field_out_en)
+               osd_hw.dispdata[OSD2].y_start /= 2;
+
+       osd_hw.dispdata[OSD2].x_end = osd_hw.dispdata[OSD2].x_start +
+               osd_hw.pandata[OSD2].x_end - osd_hw.pandata[OSD2].x_start;
+       osd_hw.dispdata[OSD2].y_end = osd_hw.dispdata[OSD2].y_start +
+               osd_hw.pandata[OSD2].y_end - osd_hw.pandata[OSD2].y_start;
+       add_to_update_list(OSD2, OSD_COLOR_MODE);
+       add_to_update_list(OSD2, DISP_GEOMETRY);
+       osd_log_dbg2("dispdata: %d,%d,%d,%d\n",
+               osd_hw.dispdata[OSD2].x_start, osd_hw.dispdata[OSD2].x_end,
+               osd_hw.dispdata[OSD2].y_start, osd_hw.dispdata[OSD2].y_end);
+}
+
 void  osd_suspend_hw(void)
 {
        if (osd_hw.osd_meson_dev.osd_ver <= OSD_NORMAL) {
index 4b2680f..ee15fcb 100644 (file)
@@ -128,6 +128,8 @@ extern int osd_sync_do_hwc(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);
+extern void osd_cursor_hw_no_scale(u32 index, s16 x, s16 y, s16 xstart,
+                         s16 ystart, u32 osd_w, u32 osd_h);
 extern void osd_init_scan_mode(void);
 extern void osd_suspend_hw(void);
 extern void osd_resume_hw(void);