rk3368 lcdc: add CABC mode config

Signed-off-by: hjc <hjc@rock-chips.com>
This commit is contained in:
hjc 2015-01-09 14:44:04 +08:00 committed by Huang, Tao
parent 3b966f2960
commit bd946e8d24
8 changed files with 126 additions and 12 deletions

View 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) {

View 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)) {

View File

@ -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*/

View 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;

View 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),

View 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*/

3
include/linux/rk_screen.h Executable file → Normal file
View File

@ -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

View 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
};