rk3368 lcdc: add CABC mode config
authorhjc <hjc@rock-chips.com>
Fri, 9 Jan 2015 06:44:04 +0000 (14:44 +0800)
committerHuang, Tao <huangtao@rock-chips.com>
Mon, 12 Jan 2015 09:11:34 +0000 (17:11 +0800)
Signed-off-by: hjc <hjc@rock-chips.com>
drivers/video/of_display_timing.c
drivers/video/rockchip/lcdc/rk3368_lcdc.c
drivers/video/rockchip/lcdc/rk3368_lcdc.h
drivers/video/rockchip/rk_fb.c
drivers/video/rockchip/rkfb_sysfs.c
include/linux/rk_fb.h
include/linux/rk_screen.h [changed mode: 0755->0644]
include/video/display_timing.h

index 405dbd68a0d45b8c0f5c960f0496e6b432f1d00b..6522edabfa51d0f8b7ad831a01303d43f5e9017f 100644 (file)
@@ -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) {
index 8f5f9a979161dfbf8381f240ae62c5ef6f518641..82e429879fa651e42090ab0cad435c7f31410168 100644 (file)
@@ -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)) {
index a916e979ae2ea4ad3db8ef0daf339bd6cc52e3ad..2561961c40c149d3ea4231845f8aeba527f476a1 100644 (file)
 #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)
 
 #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*/
index 5779256a67c5a1d94c61e19dbf0450acd6d41c9f..7113efa5b9f655f1f7c876206aaeb3e67651ccb6 100644 (file)
@@ -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;
index 477d718c61ac3337675fffdf004ec3f1af5865c6..0a18f27cdb58b88c089f3fc690b3ab9bbe19df52 100644 (file)
@@ -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),
index 002b7c0838ac2e464eb7f9a77e2bf731ce3bf384..e828731b450414a6233cd1f888955eefc726a4ac 100644 (file)
@@ -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*/
old mode 100755 (executable)
new mode 100644 (file)
index 681c453..3f0fcc8
@@ -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
index 6c5585a6316c6b8e6219dd7151b402c0df02ebc4..82723915e2b3394fd9e26cd56a1d72d66d73e11b 100644 (file)
@@ -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
 };