osd: fix osd flicker issue on AXG
authorPengcheng Chen <pengcheng.chen@amlogic.com>
Mon, 3 Jul 2017 07:26:39 +0000 (15:26 +0800)
committerJianxin Pan <jianxin.pan@amlogic.com>
Tue, 11 Jul 2017 07:34:09 +0000 (00:34 -0700)
PD#146558: osd: fix osd flicker issue on AXG

1. osd: move reg update to vsync interrupt
2. osd: add osd hold line size to 24
3. osd: add read/wirte reg function
4. osd: add osd fps stat function

Change-Id: Iaa382bb8deba49ecb94732691a3608cec9fb9679
Signed-off-by: Pengcheng Chen <pengcheng.chen@amlogic.com>
arch/arm64/boot/dts/amlogic/axg_s400.dts
drivers/amlogic/media/osd/osd.h
drivers/amlogic/media/osd/osd_fb.c
drivers/amlogic/media/osd/osd_hw.c
drivers/amlogic/media/osd/osd_hw.h
drivers/amlogic/media/osd/osd_hw_def.h

index 796d6e6..9930467 100644 (file)
@@ -61,9 +61,9 @@
                        //reg = <0x0 0x3e000000 0x0 0x1f00000>;
                        compatible = "shared-dma-pool";
                        reusable;
-                       size = <0x0 0x1000000>;
+                       size = <0x0 0x2000000>;
                        alignment = <0x0 0x400000>;
-                       alloc-ranges = <0x0 0x3f000000 0x0 0x1000000>;
+                       alloc-ranges = <0x0 0x3e000000 0x0 0x2000000>;
                };
        };
        mtd_nand {
                interrupts = <0 3 1
                        0 89 1>;
                interrupt-names = "viu-vsync", "rdma";
-               mem_size = <0x00300000 0x600000 0x00000000>;
+               mem_size = <0x00300000 0x1800000 0x00000000>;
                /* uboot logo,fb0/fb1 memory size */
                display_mode_default = "1080p60hz";
                scale_mode = <0>;
                /** 0:VPU free scale 1:OSD free scale 2:OSD super scale */
                display_size_default = <768 1024 768 2048 32>;
                /*768*1024*4*2 = 0x600000*/
-               logo_addr = "0x3f000000";
+               logo_addr = "0x3e000000";
                pxp_mode = <0>; /** 0:normal mode 1:pxp mode */
        };
 
index 260d2d9..6207e79 100644 (file)
@@ -357,6 +357,8 @@ struct hw_para_s {
        struct afbcd_data_s osd_afbcd[HW_OSD_COUNT];
        u32 urgent[HW_OSD_COUNT];
        u32 osd_deband_enable;
+       u32 osd_fps;
+       u32 osd_fps_start;
 };
 
 #endif /* _OSD_H_ */
index 065fdb0..090d9b8 100644 (file)
@@ -1266,7 +1266,8 @@ static int osd_open(struct fb_info *info, int arg)
        if (osd_check_fbsize(var, info))
                return -ENOMEM;
        /* clear osd buffer if not logo layer */
-       if ((logo_index < 0) || (logo_index != fb_index)) {
+       if (((logo_index < 0) || (logo_index != fb_index)) ||
+               (get_cpu_type() == MESON_CPU_MAJOR_ID_AXG)) {
                osd_log_info("---------------clear fb%d memory %p\n",
                        fb_index, fbdev->fb_mem_vaddr);
                set_logo_loaded();
@@ -2270,6 +2271,83 @@ static ssize_t store_osd_deband(struct device *device,
 
        return count;
 }
+
+static ssize_t show_osd_fps(struct device *device,
+                               struct device_attribute *attr,
+                               char *buf)
+{
+       u32 osd_fps;
+
+       osd_get_fps(&osd_fps);
+       return snprintf(buf, 40, "%d\n",
+               osd_fps);
+}
+
+static ssize_t store_osd_fps(struct device *device,
+                          struct device_attribute *attr,
+                          const char *buf, size_t count)
+{
+       int res = 0;
+       int ret = 0;
+
+       ret = kstrtoint(buf, 0, &res);
+       osd_set_fps(res);
+
+       return count;
+}
+
+static void parse_param(char *buf_orig, char **parm)
+{
+       char *ps, *token;
+       unsigned int n = 0;
+       char delim1[3] = " ";
+       char delim2[2] = "\n";
+
+       ps = buf_orig;
+       strcat(delim1, delim2);
+       while (1) {
+               token = strsep(&ps, delim1);
+               if (token == NULL)
+                       break;
+               if (*token == '\0')
+                       continue;
+               parm[n++] = token;
+       }
+}
+
+
+
+static ssize_t store_osd_reg(struct device *device,
+                          struct device_attribute *attr,
+                          const char *buf, size_t count)
+{
+       char *buf_orig, *parm[8] = {NULL};
+       long val = 0;
+       unsigned int reg_addr, reg_val;
+
+       if (!buf)
+               return count;
+       buf_orig = kstrdup(buf, GFP_KERNEL);
+       parse_param(buf_orig, (char **)&parm);
+       if (!strcmp(parm[0], "rv")) {
+               if (kstrtoul(parm[1], 16, &val) < 0)
+                       return -EINVAL;
+               reg_addr = val;
+               reg_val = osd_reg_read(reg_addr);
+               pr_info("reg[0x%04x]=0x%08x\n", reg_addr, reg_val);
+       } else if (!strcmp(parm[0], "wv")) {
+               if (kstrtoul(parm[1], 16, &val) < 0)
+                       return -EINVAL;
+               reg_addr = val;
+               if (kstrtoul(parm[2], 16, &val) < 0)
+                       return -EINVAL;
+               reg_val = val;
+               osd_reg_write(reg_addr, reg_val);
+       }
+       return count;
+}
+
+
 static inline  int str2lower(char *str)
 {
        while (*str != '\0') {
@@ -2452,6 +2530,10 @@ static struct device_attribute osd_attrs[] = {
                        NULL, free_scale_switch),
        __ATTR(osd_deband, 0644,
                        show_osd_deband, store_osd_deband),
+       __ATTR(osd_fps, 0644,
+                       show_osd_fps, store_osd_fps),
+       __ATTR(osd_reg, 0220,
+                       NULL, store_osd_reg),
 };
 
 #ifdef CONFIG_PM
index 32859c8..c877f31 100644 (file)
@@ -1950,6 +1950,32 @@ void osd_set_deband(u32 osd_deband_enable)
                }
        }
 }
+
+
+void osd_get_fps(u32 *osd_fps)
+{
+       *osd_fps = osd_hw.osd_fps;
+}
+
+void osd_set_fps(u32 osd_fps_start)
+{
+       static int stime, etime;
+
+       osd_hw.osd_fps_start = osd_fps_start;
+       if (osd_fps_start) {
+               /* start to calc fps */
+               stime = ktime_to_us(ktime_get());
+               osd_hw.osd_fps = 0;
+       } else {
+               /* stop to calc fps */
+               etime = ktime_to_us(ktime_get());
+               osd_hw.osd_fps = (osd_hw.osd_fps * 1000000)
+                       / (etime - stime);
+               osd_log_info("osd fps:=%d\n", osd_hw.osd_fps);
+       }
+}
+
+
 #ifdef CONFIG_AMLOGIC_MEDIA_FB_OSD_SYNC_FENCE
 enum {
        HAL_PIXEL_FORMAT_RGBA_8888 = 1,
@@ -2157,6 +2183,8 @@ static void osd_pan_display_fence(struct osd_fence_map_s *fence_map)
                        osd_log_dbg("fence wait ret %d\n", ret);
        }
        if (ret) {
+               if (osd_hw.osd_fps_start)
+                       osd_hw.osd_fps++;
                if (fence_map->op == 0xffffffff)
                        skip = true;
                else
@@ -2356,6 +2384,8 @@ void osd_pan_display_hw(u32 index, unsigned int xoffset, unsigned int yoffset)
                osd_hw.pandata[index].y_start += diff_y;
                osd_hw.pandata[index].y_end   += diff_y;
                add_to_update_list(index, DISP_GEOMETRY);
+               if (osd_hw.osd_fps_start)
+                       osd_hw.osd_fps++;
                osd_wait_vsync_hw();
        }
 #ifdef CONFIG_AMLOGIC_MEDIA_FB_EXT
@@ -3858,6 +3888,11 @@ void osd_init_hw(u32 logo_loaded)
                osd_reg_write(VPP_OSD_SC_DUMMY_DATA, 0xff);
        else
                osd_reg_write(VPP_OSD_SC_DUMMY_DATA, 0x008080ff);
+       if (get_cpu_type() == MESON_CPU_MAJOR_ID_AXG) {
+               data32 = osd_reg_read(VIU_OSD1_FIFO_CTRL_STAT);
+               data32 |= 0x18 << 5;
+               osd_reg_write(VIU_OSD1_FIFO_CTRL_STAT, data32);
+       }
        osd_set_deband(osd_hw.osd_deband_enable);
        /* osd_hw.osd_afbcd[OSD1].enable = 0;
         * osd_hw.osd_afbcd[OSD2].enable = 0;
index c421ae3..279222a 100644 (file)
@@ -151,6 +151,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);
 extern void osd_get_info(u32 index, u32 *addr, u32 *width, u32 *height);
 int logo_work_init(void);
 void set_logo_loaded(void);
index 96f076f..a561f26 100644 (file)
@@ -97,7 +97,10 @@ static update_func_t hw_func_array[HW_OSD_COUNT][HW_REG_INDEX_MAX] = {
                spin_lock_irqsave(&osd_lock, lock_flags); \
                raw_local_save_flags(fiq_flag); \
                local_fiq_disable(); \
-               osd_hw.reg[osd_idx][cmd_idx].update_func(); \
+               if (get_cpu_type() == MESON_CPU_MAJOR_ID_AXG) \
+                       osd_hw.updated[osd_idx] |= (1<<cmd_idx); \
+               else \
+                       osd_hw.reg[osd_idx][cmd_idx].update_func(); \
                raw_local_irq_restore(fiq_flag); \
                spin_unlock_irqrestore(&osd_lock, lock_flags); \
        } while (0)
@@ -105,7 +108,10 @@ static update_func_t hw_func_array[HW_OSD_COUNT][HW_REG_INDEX_MAX] = {
 #define add_to_update_list(osd_idx, cmd_idx) \
        do { \
                spin_lock_irqsave(&osd_lock, lock_flags); \
-               osd_hw.reg[osd_idx][cmd_idx].update_func(); \
+               if (get_cpu_type() == MESON_CPU_MAJOR_ID_AXG) \
+                       osd_hw.updated[osd_idx] |= (1<<cmd_idx); \
+               else \
+                       osd_hw.reg[osd_idx][cmd_idx].update_func(); \
                spin_unlock_irqrestore(&osd_lock, lock_flags); \
        } while (0)
 #endif
@@ -131,7 +137,11 @@ static update_func_t hw_func_array[HW_OSD_COUNT][HW_REG_INDEX_MAX] = {
 #endif
 
 #ifdef CONFIG_AMLOGIC_MEDIA_FB_OSD_VSYNC_RDMA
-#define remove_from_update_list(osd_idx, cmd_idx)
+#define remove_from_update_list(osd_idx, cmd_idx) \
+       do { \
+               if (get_cpu_type() == MESON_CPU_MAJOR_ID_AXG) \
+                       (osd_hw.updated[osd_idx] &= ~(1<<cmd_idx)); \
+       } while (0)
 #else
 #define remove_from_update_list(osd_idx, cmd_idx) \
        (osd_hw.updated[osd_idx] &= ~(1<<cmd_idx))