From d0f8322530283e481a9d465baa3a740cdb349852 Mon Sep 17 00:00:00 2001 From: zwl Date: Thu, 7 Aug 2014 08:45:54 +0800 Subject: [PATCH] rk312x lcdc: when in hdmi/cvbs mode ,vop overlay in yuv domain --- drivers/video/rockchip/lcdc/rk312x_lcdc.c | 80 +++++++++++++++++++++-- drivers/video/rockchip/lcdc/rk312x_lcdc.h | 27 ++++++-- include/linux/rk_fb.h | 1 + 3 files changed, 97 insertions(+), 11 deletions(-) diff --git a/drivers/video/rockchip/lcdc/rk312x_lcdc.c b/drivers/video/rockchip/lcdc/rk312x_lcdc.c index 792757caf8f8..a3dee0f480f7 100755 --- a/drivers/video/rockchip/lcdc/rk312x_lcdc.c +++ b/drivers/video/rockchip/lcdc/rk312x_lcdc.c @@ -230,12 +230,59 @@ static int rk312x_lcdc_alpha_cfg(struct lcdc_device *lcdc_dev) return 0; } +static void lcdc_layer_csc_mode(struct lcdc_device *lcdc_dev, + struct rk_lcdc_win *win) +{ + struct rk_screen *screen = lcdc_dev->driver.cur_screen; + + if (lcdc_dev->overlay_mode == VOP_YUV_DOMAIN) { + switch (win->fmt_cfg) { + case VOP_FORMAT_ARGB888: + case VOP_FORMAT_RGB888: + case VOP_FORMAT_RGB565: + if ((screen->mode.xres < 1280 ) && + (screen->mode.yres < 720)) { + win->csc_mode = VOP_R2Y_CSC_BT601; + } else { + win->csc_mode = VOP_R2Y_CSC_BT709; + } + break; + default: + break; + } + if (win->id == 0) { + lcdc_msk_reg(lcdc_dev, DSP_CTRL0, m_WIN0_CSC_MODE, + v_WIN0_CSC_MODE(win->csc_mode)); + } else if (win->id == 1) { + lcdc_msk_reg(lcdc_dev, DSP_CTRL0, m_WIN1_CSC_MODE, + v_WIN1_CSC_MODE(win->csc_mode)); + } + } else if (lcdc_dev->overlay_mode == VOP_RGB_DOMAIN) { + switch (win->fmt_cfg) { + case VOP_FORMAT_YCBCR420: + if (win->id == 0) { + win->csc_mode = VOP_Y2R_CSC_MPEG; + lcdc_msk_reg(lcdc_dev, DSP_CTRL0, m_WIN0_CSC_MODE, + v_WIN0_CSC_MODE(win->csc_mode)); + } + break; + default: + break; + } + } + +} + + static void lcdc_layer_update_regs(struct lcdc_device *lcdc_dev, struct rk_lcdc_win *win) { u32 mask, val; if (win->state == 1) { + if (lcdc_dev->soc_type == VOP_RK312X) + lcdc_layer_csc_mode(lcdc_dev,win); + if (win->id == 0) { mask = m_WIN0_EN | m_WIN0_FORMAT | m_WIN0_RB_SWAP; val = v_WIN0_EN(win->state) | @@ -734,6 +781,7 @@ static int rk312x_load_screen(struct rk_lcdc_driver *dev_drv, bool initscreen) mask = m_RGB_DCLK_EN | m_RGB_DCLK_INVERT; val = v_RGB_DCLK_EN(1) | v_RGB_DCLK_INVERT(0); lcdc_msk_reg(lcdc_dev, AXI_BUS_CTRL, mask, val); + lcdc_dev->overlay_mode = VOP_RGB_DOMAIN; } break; case SCREEN_LVDS: @@ -741,6 +789,7 @@ static int rk312x_load_screen(struct rk_lcdc_driver *dev_drv, bool initscreen) mask = m_LVDS_DCLK_EN | m_LVDS_DCLK_INVERT; val = v_LVDS_DCLK_EN(1) | v_LVDS_DCLK_INVERT(0); lcdc_msk_reg(lcdc_dev, AXI_BUS_CTRL, mask, val); + lcdc_dev->overlay_mode = VOP_RGB_DOMAIN; } break; case SCREEN_MIPI: @@ -748,6 +797,7 @@ static int rk312x_load_screen(struct rk_lcdc_driver *dev_drv, bool initscreen) mask = m_MIPI_DCLK_EN | m_MIPI_DCLK_INVERT; val = v_MIPI_DCLK_EN(1) | v_MIPI_DCLK_INVERT(0); lcdc_msk_reg(lcdc_dev, AXI_BUS_CTRL, mask, val); + lcdc_dev->overlay_mode = VOP_RGB_DOMAIN; } break; case SCREEN_HDMI: @@ -758,6 +808,9 @@ static int rk312x_load_screen(struct rk_lcdc_driver *dev_drv, bool initscreen) val |= v_CORE_CLK_DIV_EN(1); } lcdc_msk_reg(lcdc_dev, AXI_BUS_CTRL, mask, val); + if (lcdc_dev->soc_type == VOP_RK312X) { + lcdc_dev->overlay_mode = VOP_YUV_DOMAIN; + } break; case SCREEN_TVOUT: mask = m_TVE_DAC_DCLK_EN; @@ -778,12 +831,14 @@ static int rk312x_load_screen(struct rk_lcdc_driver *dev_drv, bool initscreen) "unsupported video timing!\n"); return -1; } + if (lcdc_dev->soc_type == VOP_RK312X) { + lcdc_dev->overlay_mode = VOP_YUV_DOMAIN; + } break; default: dev_err(lcdc_dev->dev, "un supported interface!\n"); break; } - if (lcdc_dev->soc_type == VOP_RK312X) { switch (screen->face) { case OUT_P565: @@ -835,7 +890,9 @@ static int rk312x_load_screen(struct rk_lcdc_driver *dev_drv, bool initscreen) default: dev_err(lcdc_dev->dev, "un supported interface!\n"); break; - } + } + lcdc_msk_reg(lcdc_dev, DSP_CTRL0, m_SW_OVERLAY_MODE, + v_SW_OVERLAY_MODE(lcdc_dev->overlay_mode)); } mask = m_DSP_OUT_FORMAT | m_HSYNC_POL | m_VSYNC_POL | @@ -1477,9 +1534,13 @@ static int rk312x_lcdc_open_bcsh(struct rk_lcdc_driver *dev_drv, bool open) spin_lock(&lcdc_dev->reg_lock); if (lcdc_dev->clk_on) { if (open) { - lcdc_writel(lcdc_dev, BCSH_CTRL, 0x1); - lcdc_writel(lcdc_dev, BCSH_BCS, 0xd0010000); - lcdc_writel(lcdc_dev, BCSH_H, 0x01000000); + lcdc_writel(lcdc_dev, BCSH_CTRL, + v_BCSH_EN(1) | v_BCSH_OUT_MODE(3)); + lcdc_writel(lcdc_dev, BCSH_BCS, + v_BCSH_BRIGHTNESS(0x00) | + v_BCSH_CONTRAST(0x80) | + v_BCSH_SAT_CON(0x80)); + lcdc_writel(lcdc_dev, BCSH_H, v_BCSH_COS_HUE(0x80)); } else { mask = m_BCSH_EN; val = v_BCSH_EN(0); @@ -1487,6 +1548,15 @@ static int rk312x_lcdc_open_bcsh(struct rk_lcdc_driver *dev_drv, bool open) } lcdc_cfg_done(lcdc_dev); } + + if (lcdc_dev->overlay_mode == VOP_YUV_DOMAIN) { + lcdc_msk_reg(lcdc_dev, BCSH_CTRL, m_BCSH_R2Y_CSC_MODE, + v_BCSH_R2Y_CSC_MODE(VOP_Y2R_CSC_BYPASS)); + } else { + lcdc_msk_reg(lcdc_dev, BCSH_CTRL, m_BCSH_R2Y_CSC_MODE, + v_BCSH_R2Y_CSC_MODE(VOP_Y2R_CSC_MPEG)); + } + spin_unlock(&lcdc_dev->reg_lock); return 0; } diff --git a/drivers/video/rockchip/lcdc/rk312x_lcdc.h b/drivers/video/rockchip/lcdc/rk312x_lcdc.h index 57b475f9107c..f880202dde6e 100755 --- a/drivers/video/rockchip/lcdc/rk312x_lcdc.h +++ b/drivers/video/rockchip/lcdc/rk312x_lcdc.h @@ -92,6 +92,7 @@ enum _VOP_SOC_TYPE { #define m_WIN0_ALPHA_MODE BITS(1, 18) #define m_WIN1_ALPHA_MODE BITS(1, 19) #define m_WIN0_CSC_MODE BITS(3, 20) + #define m_WIN1_CSC_MODE BITS(1, 22) #define m_WIN0_YUV_CLIP BITS(1, 23) #define m_TVE_MODE BITS(1, 25) #define m_SW_UV_OFFSET_EN BITS(1, 26) /* use for rk312x */ @@ -120,6 +121,7 @@ enum _VOP_SOC_TYPE { #define v_WIN0_ALPHA_MODE(x) BITS_MASK(x, 1, 18) #define v_WIN1_ALPHA_MODE(x) BITS_MASK(x, 1, 19) #define v_WIN0_CSC_MODE(x) BITS_MASK(x, 3, 20) + #define v_WIN1_CSC_MODE(x) BITS_MASK(x, 1, 22) #define v_WIN0_YUV_CLIP(x) BITS_MASK(x, 1, 23) #define v_TVE_MODE(x) BITS_MASK(x, 1, 25) #define v_SW_UV_OFFSET_EN(x) BITS_MASK(x, 1, 26) /* rk312x */ @@ -437,10 +439,10 @@ enum _VOP_SOC_TYPE { #define BCSH_H (0xdc) #define m_BCSH_SIN_HUE BITS(0xff, 0) - #define m_BCSH_COS_HUE BITS(0xff, 16) + #define m_BCSH_COS_HUE BITS(0xff, 8) #define v_BCSH_SIN_HUE(x) BITS_MASK(x, 0xff, 0) - #define v_BCSH_COS_HUE(x) BITS_MASK(x, 0xff, 16) + #define v_BCSH_COS_HUE(x) BITS_MASK(x, 0xff, 8) #define FRC_LOWER01_0 (0xe0) #define FRC_LOWER01_1 (0xe4) @@ -623,10 +625,16 @@ enum _vop_tv_mode { TV_PAL, }; -enum _vop_csc_mode { - VOP_CSC_BT601 = 0, - VOP_CSC_JPEG, - VOP_CSC_BT709 +enum _vop_r2y_csc_mode { + VOP_R2Y_CSC_BT601 = 0, + VOP_R2Y_CSC_BT709 +}; + +enum _vop_y2r_csc_mode { + VOP_Y2R_CSC_MPEG = 0, + VOP_Y2R_CSC_JPEG, + VOP_Y2R_CSC_HD, + VOP_Y2R_CSC_BYPASS }; enum _vop_hwc_size { @@ -634,6 +642,12 @@ enum _vop_hwc_size { VOP_HWC_SIZE_64 }; +enum _vop_overlay_mode { + VOP_RGB_DOMAIN, + VOP_YUV_DOMAIN +}; + + #define CalScale(x, y) ((((u32)(x - 1)) * 0x1000) / (y - 1)) struct rk_lcdc_drvdata { @@ -673,6 +687,7 @@ struct lcdc_device { u32 s_pixclock; u32 standby; /* 1:standby,0:work */ + u16 overlay_mode; }; static inline void lcdc_writel(struct lcdc_device *lcdc_dev, u32 offset, u32 v) diff --git a/include/linux/rk_fb.h b/include/linux/rk_fb.h index 60c8e558a3ab..a52077480bd9 100755 --- a/include/linux/rk_fb.h +++ b/include/linux/rk_fb.h @@ -381,6 +381,7 @@ struct rk_lcdc_win { u32 alpha_mode; u32 g_alpha_val; u32 color_key_val; + u8 csc_mode; struct rk_lcdc_win_area area[RK_WIN_MAX_AREA]; struct rk_lcdc_post_cfg post_cfg; -- 2.34.1