From af82c9e477edad50cb3a428b821c616bb6345e13 Mon Sep 17 00:00:00 2001 From: Pengcheng Chen Date: Mon, 3 Jul 2017 15:26:39 +0800 Subject: [PATCH] osd: fix osd flicker issue on AXG 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 --- arch/arm64/boot/dts/amlogic/axg_s400.dts | 8 +-- drivers/amlogic/media/osd/osd.h | 2 + drivers/amlogic/media/osd/osd_fb.c | 84 +++++++++++++++++++++++++++++++- drivers/amlogic/media/osd/osd_hw.c | 35 +++++++++++++ drivers/amlogic/media/osd/osd_hw.h | 2 + drivers/amlogic/media/osd/osd_hw_def.h | 16 ++++-- 6 files changed, 139 insertions(+), 8 deletions(-) diff --git a/arch/arm64/boot/dts/amlogic/axg_s400.dts b/arch/arm64/boot/dts/amlogic/axg_s400.dts index 796d6e6..9930467 100644 --- a/arch/arm64/boot/dts/amlogic/axg_s400.dts +++ b/arch/arm64/boot/dts/amlogic/axg_s400.dts @@ -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 { @@ -738,14 +738,14 @@ 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 */ }; diff --git a/drivers/amlogic/media/osd/osd.h b/drivers/amlogic/media/osd/osd.h index 260d2d9..6207e79 100644 --- a/drivers/amlogic/media/osd/osd.h +++ b/drivers/amlogic/media/osd/osd.h @@ -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_ */ diff --git a/drivers/amlogic/media/osd/osd_fb.c b/drivers/amlogic/media/osd/osd_fb.c index 065fdb0..090d9b8 100644 --- a/drivers/amlogic/media/osd/osd_fb.c +++ b/drivers/amlogic/media/osd/osd_fb.c @@ -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 diff --git a/drivers/amlogic/media/osd/osd_hw.c b/drivers/amlogic/media/osd/osd_hw.c index 32859c8..c877f31 100644 --- a/drivers/amlogic/media/osd/osd_hw.c +++ b/drivers/amlogic/media/osd/osd_hw.c @@ -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; diff --git a/drivers/amlogic/media/osd/osd_hw.h b/drivers/amlogic/media/osd/osd_hw.h index c421ae3..279222a 100644 --- a/drivers/amlogic/media/osd/osd_hw.h +++ b/drivers/amlogic/media/osd/osd_hw.h @@ -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); diff --git a/drivers/amlogic/media/osd/osd_hw_def.h b/drivers/amlogic/media/osd/osd_hw_def.h index 96f076f..a561f26 100644 --- a/drivers/amlogic/media/osd/osd_hw_def.h +++ b/drivers/amlogic/media/osd/osd_hw_def.h @@ -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<