From: hjc Date: Fri, 9 Jan 2015 06:44:04 +0000 (+0800) Subject: rk3368 lcdc: add CABC mode config X-Git-Tag: firefly_0821_release~4158^2~460 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=bd946e8d24bb50d012f5cefb42c9593bef839c91;p=firefly-linux-kernel-4.4.55.git rk3368 lcdc: add CABC mode config Signed-off-by: hjc --- diff --git a/drivers/video/of_display_timing.c b/drivers/video/of_display_timing.c index 405dbd68a0d4..6522edabfa51 100644 --- a/drivers/video/of_display_timing.c +++ b/drivers/video/of_display_timing.c @@ -123,6 +123,15 @@ static struct display_timing *of_get_display_timing(struct device_node *np) ret = of_property_read_u32_array(np, "dsp-lut",dt->dsp_lut, length >> 2); } + prop = of_find_property(np, "cabc-lut", &length); + if (prop) { + dt->cabc_lut = kzalloc(length, GFP_KERNEL); + if (dt->cabc_lut) + ret = of_property_read_u32_array(np, + "cabc-lut", + dt->cabc_lut, + length >> 2); + } #endif if (ret) { diff --git a/drivers/video/rockchip/lcdc/rk3368_lcdc.c b/drivers/video/rockchip/lcdc/rk3368_lcdc.c index 8f5f9a979161..82e429879fa6 100644 --- a/drivers/video/rockchip/lcdc/rk3368_lcdc.c +++ b/drivers/video/rockchip/lcdc/rk3368_lcdc.c @@ -95,6 +95,30 @@ u32 rk3368_get_hard_ware_vskiplines(u32 srch, u32 dsth) return vscalednmult; } + +static int rk3368_set_cabc_lut(struct rk_lcdc_driver *dev_drv, int *cabc_lut) +{ + int i; + int __iomem *c; + u32 v; + struct lcdc_device *lcdc_dev = + container_of(dev_drv, struct lcdc_device, driver); + + lcdc_msk_reg(lcdc_dev, CABC_CTRL1, m_CABC_LUT_EN, + v_CABC_LUT_EN(0)); + lcdc_cfg_done(lcdc_dev); + mdelay(25); + for (i = 0; i < 256; i++) { + v = cabc_lut[i]; + c = lcdc_dev->cabc_lut_addr_base + i; + writel_relaxed(v, c); + } + lcdc_msk_reg(lcdc_dev, CABC_CTRL1, m_CABC_LUT_EN, + v_CABC_LUT_EN(1)); + return 0; +} + + static int rk3368_lcdc_set_lut(struct rk_lcdc_driver *dev_drv, int *dsp_lut) { int i; @@ -102,7 +126,9 @@ static int rk3368_lcdc_set_lut(struct rk_lcdc_driver *dev_drv, int *dsp_lut) u32 v; struct lcdc_device *lcdc_dev = container_of(dev_drv, struct lcdc_device, driver); - lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_LUT_EN, v_DSP_LUT_EN(0)); + + lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_LUT_EN, + v_DSP_LUT_EN(0)); lcdc_cfg_done(lcdc_dev); mdelay(25); for (i = 0; i < 256; i++) { @@ -110,7 +136,8 @@ static int rk3368_lcdc_set_lut(struct rk_lcdc_driver *dev_drv, int *dsp_lut) c = lcdc_dev->dsp_lut_addr_base + i; writel_relaxed(v, c); } - lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_LUT_EN, v_DSP_LUT_EN(1)); + lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_LUT_EN, + v_DSP_LUT_EN(1)); return 0; } @@ -427,6 +454,7 @@ static int rk3368_lcdc_pre_init(struct rk_lcdc_driver *dev_drv) mask = m_AUTO_GATING_EN; val = v_AUTO_GATING_EN(0); + lcdc_msk_reg(lcdc_dev, SYS_CTRL, mask, val); lcdc_cfg_done(lcdc_dev); /*disable win0 to workaround iommu pagefault */ /*if (dev_drv->iommu_enabled) */ @@ -1875,6 +1903,13 @@ static int rk3368_load_screen(struct rk_lcdc_driver *dev_drv, bool initscreen) else lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_LUT_EN, v_DSP_LUT_EN(1)); + if (screen->cabc_lut == NULL) { + lcdc_msk_reg(lcdc_dev, CABC_CTRL0, m_CABC_EN, + v_CABC_EN(0)); + } else { + lcdc_msk_reg(lcdc_dev, CABC_CTRL1, m_CABC_LUT_EN, + v_CABC_LUT_EN(1)); + } rk3368_lcdc_bcsh_path_sel(dev_drv); rk3368_config_timing(dev_drv); } @@ -2006,6 +2041,9 @@ static int rk3368_lcdc_open(struct rk_lcdc_driver *dev_drv, int win_id, if (dev_drv->cur_screen->dsp_lut) rk3368_lcdc_set_lut(dev_drv, dev_drv->cur_screen->dsp_lut); + if (dev_drv->cur_screen->cabc_lut) + rk3368_set_cabc_lut(dev_drv, + dev_drv->cur_screen->cabc_lut); spin_unlock(&lcdc_dev->reg_lock); } @@ -3028,6 +3066,9 @@ static int rk3368_lcdc_early_resume(struct rk_lcdc_driver *dev_drv) if (dev_drv->cur_screen->dsp_lut) rk3368_lcdc_set_lut(dev_drv, dev_drv->cur_screen->dsp_lut); + if (dev_drv->cur_screen->cabc_lut) + rk3368_set_cabc_lut(dev_drv, + dev_drv->cur_screen->cabc_lut); lcdc_msk_reg(lcdc_dev, DSP_CTRL0, m_DSP_OUT_ZERO, v_DSP_OUT_ZERO(0)); @@ -3825,11 +3866,11 @@ static int rk3368_lcdc_get_dsp_addr(struct rk_lcdc_driver *dev_drv, } static struct lcdc_cabc_mode cabc_mode[4] = { - /* pixel_num,8 stage_up, stage_down */ - {5, 282, 171, 300}, /*mode 1 */ - {10, 282, 171, 300}, /*mode 2 */ - {15, 282, 171, 300}, /*mode 3 */ - {20, 282, 171, 300}, /*mode 4 */ + /* calc, up, down, global_limit */ + {5, 256, 256, 256}, /*mode 1 0*/ + {5, 258, 253, 277}, /*mode 2 15%*/ + {5, 259, 252, 330}, /*mode 3 40%*/ + {5, 267, 244, 400}, /*mode 4 60%*/ }; static int rk3368_lcdc_set_dsp_cabc(struct rk_lcdc_driver *dev_drv, int mode) @@ -3839,8 +3880,16 @@ static int rk3368_lcdc_set_dsp_cabc(struct rk_lcdc_driver *dev_drv, int mode) struct rk_screen *screen = dev_drv->cur_screen; u32 total_pixel, calc_pixel, stage_up, stage_down; u32 pixel_num, global_su; - u32 stage_up_rec, stage_down_rec, global_su_rec; + u32 stage_up_rec, stage_down_rec, global_su_rec, gamma_global_su_rec; u32 mask = 0, val = 0, cabc_en = 0; + int *cabc_lut = NULL; + + if (!screen->cabc_lut) { + pr_err("screen cabc lut not config, so not open cabc\n"); + return 0; + } else { + cabc_lut = screen->cabc_lut; + } dev_drv->cabc_mode = mode; cabc_en = (mode > 0) ? 1 : 0; @@ -3865,7 +3914,8 @@ static int rk3368_lcdc_set_dsp_cabc(struct rk_lcdc_driver *dev_drv, int mode) stage_up_rec = 256 * 256 / stage_up; stage_down_rec = 256 * 256 / stage_down; - global_su_rec = 256 * 256 / global_su; + global_su_rec = (256 * 256 / global_su) - 1; + gamma_global_su_rec = cabc_lut[global_su_rec]; spin_lock(&lcdc_dev->reg_lock); if (lcdc_dev->clk_on) { @@ -3875,7 +3925,7 @@ static int rk3368_lcdc_set_dsp_cabc(struct rk_lcdc_driver *dev_drv, int mode) lcdc_msk_reg(lcdc_dev, CABC_CTRL0, mask, val); mask = m_CABC_TOTAL_PIXEL_NUM | m_CABC_LUT_EN; - val = v_CABC_TOTAL_PIXEL_NUM(total_pixel) | v_CABC_LUT_EN(0); + val = v_CABC_TOTAL_PIXEL_NUM(total_pixel) | v_CABC_LUT_EN(1); lcdc_msk_reg(lcdc_dev, CABC_CTRL1, mask, val); mask = m_CABC_STAGE_UP | m_CABC_STAGE_UP_REC | @@ -3883,7 +3933,7 @@ static int rk3368_lcdc_set_dsp_cabc(struct rk_lcdc_driver *dev_drv, int mode) val = v_CABC_STAGE_UP(stage_up) | v_CABC_STAGE_UP_REC(stage_up_rec) | v_CABC_GLOBAL_SU_LIMIT_EN(1) | - v_CABC_GLOBAL_SU_REC(global_su_rec); + v_CABC_GLOBAL_SU_REC(gamma_global_su_rec); lcdc_msk_reg(lcdc_dev, CABC_CTRL2, mask, val); mask = m_CABC_STAGE_DOWN | m_CABC_STAGE_DOWN_REC | @@ -4161,6 +4211,7 @@ static struct rk_lcdc_drv_ops lcdc_drv_ops = { .fb_get_win_id = rk3368_lcdc_get_win_id, .fb_win_remap = rk3368_fb_win_remap, .set_dsp_lut = rk3368_lcdc_set_lut, + .set_cabc_lut = rk3368_set_cabc_lut, .poll_vblank = rk3368_lcdc_poll_vblank, .dpi_open = rk3368_lcdc_dpi_open, .dpi_win_sel = rk3368_lcdc_dpi_win_sel, @@ -4392,6 +4443,7 @@ static int rk3368_lcdc_probe(struct platform_device *pdev) if (IS_ERR(lcdc_dev->regsbak)) return PTR_ERR(lcdc_dev->regsbak); lcdc_dev->dsp_lut_addr_base = (lcdc_dev->regs + GAMMA_LUT_ADDR); + lcdc_dev->cabc_lut_addr_base = (lcdc_dev->regs + CABC_GAMMA_LUT_ADDR); lcdc_dev->grf_base = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); if (IS_ERR(lcdc_dev->grf_base)) { diff --git a/drivers/video/rockchip/lcdc/rk3368_lcdc.h b/drivers/video/rockchip/lcdc/rk3368_lcdc.h index a916e979ae2e..2561961c40c1 100644 --- a/drivers/video/rockchip/lcdc/rk3368_lcdc.h +++ b/drivers/video/rockchip/lcdc/rk3368_lcdc.h @@ -1217,6 +1217,7 @@ #define v_BL_EN(x) (((x)&1)<<8) #define v_CLK_SEL(x) (((x)&1)<<9) #define v_PRESCALE(x) (((x)&7)<<12) +#define v_CABC_PWM_OUT_POL(x) (((x)&1)<<15) #define v_SCALE(x) (((x)&0xff)<<16) #define v_RPT(x) (((x)&0xff)<<24) @@ -1228,6 +1229,8 @@ #define m_OUTPUT_MODE (1<<5) #define m_BL_EN (1<<8) #define m_CLK_SEL (1<<9) +#define m_CABC_PWM_OUT_POL (1<<15) + #define m_PRESCALE (7<<12) #define m_SCALE (0xff<<16) #define m_RPT ((u32)0xff<<24) @@ -1746,6 +1749,7 @@ struct lcdc_device { spinlock_t reg_lock; int __iomem *dsp_lut_addr_base; + int __iomem *cabc_lut_addr_base; int prop; /*used for primary or extended display device*/ diff --git a/drivers/video/rockchip/rk_fb.c b/drivers/video/rockchip/rk_fb.c index 5779256a67c5..7113efa5b9f6 100644 --- a/drivers/video/rockchip/rk_fb.c +++ b/drivers/video/rockchip/rk_fb.c @@ -438,6 +438,7 @@ int rk_fb_video_mode_from_timing(const struct display_timing *dt, screen->face = dt->face; screen->color_mode = dt->color_mode; screen->dsp_lut = dt->dsp_lut; + screen->cabc_lut = dt->cabc_lut; if (dt->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE) screen->pin_dclk = 1; diff --git a/drivers/video/rockchip/rkfb_sysfs.c b/drivers/video/rockchip/rkfb_sysfs.c index 477d718c61ac..0a18f27cdb58 100644 --- a/drivers/video/rockchip/rkfb_sysfs.c +++ b/drivers/video/rockchip/rkfb_sysfs.c @@ -493,6 +493,50 @@ static ssize_t set_hwc_lut(struct device *dev, struct device_attribute *attr, return count; } +static ssize_t show_cabc_lut(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return 0; +} + +static ssize_t set_cabc_lut(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int cabc_lut[256]; + const char *start = buf; + int i = 256, temp; + int space_max = 10; + + struct fb_info *fbi = dev_get_drvdata(dev); + struct rk_fb_par *fb_par = (struct rk_fb_par *)fbi->par; + struct rk_lcdc_driver *dev_drv = fb_par->lcdc_drv; + + for (i = 0; i < 256; i++) { + temp = i; + /*init by default value*/ + cabc_lut[i] = temp + (temp << 8) + (temp << 16); + } + for (i = 0; i < 256; i++) { + space_max = 10; /*max space number 10*/ + temp = simple_strtoul(start, NULL, 10); + cabc_lut[i] = temp; + do { + start++; + space_max--; + } while ((*start != ' ') && space_max); + + if (!space_max) + break; + else + start++; + } + if (dev_drv->ops->set_cabc_lut) + dev_drv->ops->set_cabc_lut(dev_drv, cabc_lut); + + return count; +} + + static ssize_t show_dsp_lut(struct device *dev, struct device_attribute *attr, char *buf) { @@ -773,6 +817,7 @@ static struct device_attribute rkfb_attrs[] = { __ATTR(fps, S_IRUGO | S_IWUSR, show_fps, set_fps), __ATTR(map, S_IRUGO | S_IWUSR, show_fb_win_map, set_fb_win_map), __ATTR(dsp_lut, S_IRUGO | S_IWUSR, show_dsp_lut, set_dsp_lut), + __ATTR(cabc_lut, S_IRUGO | S_IWUSR, show_cabc_lut, set_cabc_lut), __ATTR(hwc_lut, S_IRUGO | S_IWUSR, show_hwc_lut, set_hwc_lut), __ATTR(cabc, S_IRUGO | S_IWUSR, show_dsp_cabc, set_dsp_cabc), __ATTR(bcsh, S_IRUGO | S_IWUSR, show_dsp_bcsh, set_dsp_bcsh), diff --git a/include/linux/rk_fb.h b/include/linux/rk_fb.h index 002b7c0838ac..e828731b4504 100644 --- a/include/linux/rk_fb.h +++ b/include/linux/rk_fb.h @@ -445,6 +445,7 @@ struct rk_lcdc_drv_ops { int (*fb_win_remap) (struct rk_lcdc_driver *dev_drv, u16 fb_win_map_order); int (*set_dsp_lut) (struct rk_lcdc_driver *dev_drv, int *lut); + int (*set_cabc_lut)(struct rk_lcdc_driver *dev_drv, int *lut); int (*set_hwc_lut) (struct rk_lcdc_driver *dev_drv, int *hwc_lut, int mode); int (*read_dsp_lut) (struct rk_lcdc_driver *dev_drv, int *lut); int (*lcdc_hdmi_process) (struct rk_lcdc_driver *dev_drv, int mode); /*some lcdc need to some process in hdmi mode*/ diff --git a/include/linux/rk_screen.h b/include/linux/rk_screen.h old mode 100755 new mode 100644 index 681c453f5805..3f0fcc8b37e4 --- a/include/linux/rk_screen.h +++ b/include/linux/rk_screen.h @@ -79,7 +79,8 @@ struct rk_screen { u16 width; u16 height; u8 ft; - int *dsp_lut; + int *dsp_lut; + int *cabc_lut; #if defined(CONFIG_MFD_RK616) || defined(CONFIG_LCDC_RK312X) u32 pll_cfg_val; //bellow are for jettaB diff --git a/include/video/display_timing.h b/include/video/display_timing.h index 6c5585a6316c..82723915e2b3 100644 --- a/include/video/display_timing.h +++ b/include/video/display_timing.h @@ -81,6 +81,7 @@ struct display_timing { u16 face; /*display output interface format:24bit 18bit 16bit*/ u16 color_mode; /* input color mode: RGB or YUV */ u32 *dsp_lut; + u32 *cabc_lut; #endif };