#if defined(CONFIG_HAS_EARLYSUSPEND)
#include <linux/earlysuspend.h>
#endif
-#define CONFIG_RK_FPGA 1
+/*#define CONFIG_RK_FPGA 1*/
static int dbg_thresd;
module_param(dbg_thresd, int, S_IRUGO | S_IWUSR);
return vscalednmult;
}
-static int rk3368_lcdc_set_lut(struct rk_lcdc_driver *dev_drv)
+
+static int rk3368_set_cabc_lut(struct rk_lcdc_driver *dev_drv, int *cabc_lut)
{
- int i, j;
+ int i;
int __iomem *c;
- u32 v, r, g, b;
+ 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, 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 = dev_drv->cur_screen->dsp_lut[i];
- c = lcdc_dev->dsp_lut_addr_base + (i << 2);
- b = (v & 0xff) << 2;
- g = (v & 0xff00) << 4;
- r = (v & 0xff0000) << 6;
- v = r + g + b;
- for (j = 0; j < 4; j++) {
- writel_relaxed(v, c);
- v += (1 + (1 << 10) + (1 << 20));
- c++;
- }
+ v = cabc_lut[i];
+ c = lcdc_dev->cabc_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, 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;
+ int __iomem *c;
+ 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_cfg_done(lcdc_dev);
+ mdelay(25);
+ for (i = 0; i < 256; i++) {
+ v = dsp_lut[i];
+ 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));
return 0;
}
clk_prepare_enable(lcdc_dev->hclk);
clk_prepare_enable(lcdc_dev->dclk);
clk_prepare_enable(lcdc_dev->aclk);
- clk_prepare_enable(lcdc_dev->pd);
+ /*clk_prepare_enable(lcdc_dev->pd);*/
spin_lock(&lcdc_dev->reg_lock);
lcdc_dev->clk_on = 1;
spin_unlock(&lcdc_dev->reg_lock);
clk_disable_unprepare(lcdc_dev->dclk);
clk_disable_unprepare(lcdc_dev->hclk);
clk_disable_unprepare(lcdc_dev->aclk);
- clk_disable_unprepare(lcdc_dev->pd);
+ /*clk_disable_unprepare(lcdc_dev->pd);*/
}
return 0;
}
-static int rk3368_lcdc_disable_irq(struct lcdc_device *lcdc_dev)
+static int __maybe_unused
+ rk3368_lcdc_disable_irq(struct lcdc_device *lcdc_dev)
{
u32 mask, val;
struct rk_lcdc_win *win0 = lcdc_dev->driver.win[0];
spin_lock(&lcdc_dev->reg_lock);
- for (reg = 0; reg < FRC_LOWER11_1; reg += 4) {
- val = lcdc_readl(lcdc_dev, reg);
+ for (reg = 0; reg < SCAN_LINE_NUM; reg += 4) {
+ val = lcdc_readl_backup(lcdc_dev, reg);
switch (reg) {
case WIN0_ACT_INFO:
win0->area[0].xact = (val & m_WIN0_ACT_WIDTH) + 1;
/********do basic init*********/
static int rk3368_lcdc_pre_init(struct rk_lcdc_driver *dev_drv)
{
- u32 mask, val;
+ u32 mask, val, v;
struct lcdc_device *lcdc_dev =
container_of(dev_drv, struct lcdc_device, driver);
if (lcdc_dev->pre_init)
lcdc_dev->hclk = devm_clk_get(lcdc_dev->dev, "hclk_lcdc");
lcdc_dev->aclk = devm_clk_get(lcdc_dev->dev, "aclk_lcdc");
lcdc_dev->dclk = devm_clk_get(lcdc_dev->dev, "dclk_lcdc");
- lcdc_dev->pll_sclk = devm_clk_get(lcdc_dev->dev, "sclk_pll");
- lcdc_dev->pd = devm_clk_get(lcdc_dev->dev, "pd_lcdc");
+ /*lcdc_dev->pd = devm_clk_get(lcdc_dev->dev, "pd_lcdc");*/
- if (IS_ERR(lcdc_dev->pd) || (IS_ERR(lcdc_dev->aclk)) ||
+ if (/*IS_ERR(lcdc_dev->pd) || */(IS_ERR(lcdc_dev->aclk)) ||
(IS_ERR(lcdc_dev->dclk)) || (IS_ERR(lcdc_dev->hclk))) {
dev_err(lcdc_dev->dev, "failed to get lcdc%d clk source\n",
lcdc_dev->id);
/*backup reg config at uboot */
lcdc_read_reg_defalut_cfg(lcdc_dev);
+ if (lcdc_dev->pwr18 == 1) {
+ v = 0x00200020; /*bit5: 1,1.8v;0,3.3v*/
+ lcdc_grf_writel(lcdc_dev->pmugrf_base,
+ PMUGRF_SOC_CON0_VOP, v);
+ } else {
+ v = 0x00200000; /*bit5: 1,1.8v;0,3.3v*/
+ lcdc_grf_writel(lcdc_dev->pmugrf_base,
+ PMUGRF_SOC_CON0_VOP, v);
+ }
lcdc_writel(lcdc_dev, CABC_GAUSS_LINE0_0, 0x15110903);
lcdc_writel(lcdc_dev, CABC_GAUSS_LINE0_1, 0x00030911);
lcdc_writel(lcdc_dev, CABC_GAUSS_LINE1_0, 0x1a150b04);
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) */
static void rk3368_lcdc_deint(struct lcdc_device *lcdc_dev)
{
- rk3368_lcdc_disable_irq(lcdc_dev);
- spin_lock(&lcdc_dev->reg_lock);
- if (likely(lcdc_dev->clk_on)) {
- lcdc_dev->clk_on = 0;
- lcdc_set_bit(lcdc_dev, SYS_CTRL, m_STANDBY_EN);
- lcdc_cfg_done(lcdc_dev);
- spin_unlock(&lcdc_dev->reg_lock);
- } else {
- spin_unlock(&lcdc_dev->reg_lock);
- }
- mdelay(1);
}
static int rk3368_lcdc_post_cfg(struct rk_lcdc_driver *dev_drv)
u16 post_dsp_vact_st_f1, post_dsp_vact_end_f1;
u16 post_h_fac, post_v_fac;
+ screen->post_dsp_stx = x_res * (100 - dev_drv->overscan.left) / 200;
+ screen->post_dsp_sty = y_res * (100 - dev_drv->overscan.top) / 200;
+ screen->post_xsize = x_res *
+ (dev_drv->overscan.left + dev_drv->overscan.right) / 200;
+ screen->post_ysize = y_res *
+ (dev_drv->overscan.top + dev_drv->overscan.bottom) / 200;
+
h_total = screen->mode.hsync_len + screen->mode.left_margin +
x_res + screen->mode.right_margin;
v_total = screen->mode.vsync_len + screen->mode.upper_margin +
screen->post_dsp_sty = y_res - screen->post_ysize;
}
- if (screen->y_mirror == 0) {
- post_dsp_vact_st = screen->post_dsp_sty +
- screen->mode.vsync_len + screen->mode.upper_margin;
- post_dsp_vact_end = post_dsp_vact_st + screen->post_ysize;
- } else {
- post_dsp_vact_end = v_total - screen->mode.lower_margin -
- screen->post_dsp_sty;
- post_dsp_vact_st = post_dsp_vact_end - screen->post_ysize;
- }
if ((screen->post_ysize < y_res) && (screen->post_ysize != 0)) {
post_vsd_en = 1;
post_v_fac = GET_SCALE_FACTOR_BILI_DN(y_res,
post_v_fac = 0x1000;
}
- if (screen->interlace == 1) {
- post_dsp_vact_st_f1 = v_total + post_dsp_vact_st;
- post_dsp_vact_end_f1 = post_dsp_vact_st_f1 + screen->post_ysize;
+ if (screen->mode.vmode == FB_VMODE_INTERLACED) {
+ post_dsp_vact_st = screen->post_dsp_sty / 2 +
+ screen->mode.vsync_len +
+ screen->mode.upper_margin;
+ post_dsp_vact_end = post_dsp_vact_st +
+ screen->post_ysize / 2;
+
+ post_dsp_vact_st_f1 = screen->mode.vsync_len +
+ screen->mode.upper_margin +
+ y_res/2 +
+ screen->mode.lower_margin +
+ screen->mode.vsync_len +
+ screen->mode.upper_margin +
+ screen->post_dsp_sty / 2 +
+ 1;
+ post_dsp_vact_end_f1 = post_dsp_vact_st_f1 +
+ screen->post_ysize/2;
} else {
+ if (screen->y_mirror == 0) {
+ post_dsp_vact_st = screen->post_dsp_sty +
+ screen->mode.vsync_len +
+ screen->mode.upper_margin;
+ post_dsp_vact_end = post_dsp_vact_st +
+ screen->post_ysize;
+ } else {
+ post_dsp_vact_end = v_total -
+ screen->mode.lower_margin -
+ screen->post_dsp_sty;
+ post_dsp_vact_st = post_dsp_vact_end -
+ screen->post_ysize;
+ }
post_dsp_vact_st_f1 = 0;
post_dsp_vact_end_f1 = 0;
}
for (i = 0; i < win->area_num; i++) {
ppixel_alpha |= ((win->area[i].format == ARGB888) ||
+ (win->area[i].format == FBDC_ARGB_888) ||
+ (win->area[i].format == FBDC_ABGR_888) ||
(win->area[i].format == ABGR888)) ? 1 : 0;
}
global_alpha = (win->g_alpha_val == 0) ? 0 : 1;
return 0;
}
-static int rk3368_lcdc_area_swap(struct rk_lcdc_win *win, int area_num)
+static int __maybe_unused
+ rk3368_lcdc_area_swap(struct rk_lcdc_win *win, int area_num)
{
struct rk_lcdc_win_area area_temp;
return 0;
}
-static int rk3368_win_area_check_var(int win_id, int area_num,
- struct rk_lcdc_win_area *area_pre,
- struct rk_lcdc_win_area *area_now)
+static int __maybe_unused
+rk3368_win_area_check_var(int win_id, int area_num,
+ struct rk_lcdc_win_area *area_pre,
+ struct rk_lcdc_win_area *area_now)
{
if ((area_pre->xpos > area_now->xpos) ||
((area_pre->xpos + area_pre->xsize > area_now->xpos) &&
val = v_IFBDC_TILES_NUM(win->area[0].fbdc_num_tiles);
lcdc_msk_reg(lcdc_dev, IFBDC_TILES_NUM, mask, val);
- mask = m_IFBDC_BASE_ADDR;
- val = v_IFBDC_BASE_ADDR(win->area[0].y_addr);
- lcdc_msk_reg(lcdc_dev, IFBDC_BASE_ADDR, mask, val);
-
mask = m_IFBDC_MB_SIZE_WIDTH | m_IFBDC_MB_SIZE_HEIGHT;
val = v_IFBDC_MB_SIZE_WIDTH(win->area[0].fbdc_mb_width) |
v_IFBDC_MB_SIZE_HEIGHT(win->area[0].fbdc_mb_height);
mb_w_size = 16;
break;
case VOP_FORMAT_RGB565:
+ fbdc_dsp_width_ratio = 1;
mb_w_size = 32;
break;
default:
(fbdc_mb_yst * fbdc_mb_vir_width) + fbdc_mb_xst;
}
/*fbdc fmt maybe need to change*/
- win->area[0].fbdc_fmt_cfg = win->area[0].fbdc_data_format;
win->area[0].fbdc_dsp_width_ratio = fbdc_dsp_width_ratio;
win->area[0].fbdc_mb_vir_width = fbdc_mb_vir_width;
win->area[0].fbdc_mb_vir_height = fbdc_mb_vir_height;
if (win->state == 1) {
rk3368_lcdc_csc_mode(lcdc_dev, win);
- if (win->area[0].fbdc_en)
+ if (win->area[0].fbdc_en) {
rk3368_fbdc_reg_update(&lcdc_dev->driver, win_id);
+ } else {
+ mask = m_IFBDC_CTRL_FBDC_EN;
+ val = v_IFBDC_CTRL_FBDC_EN(0);
+ lcdc_msk_reg(lcdc_dev, IFBDC_CTRL, mask, val);
+ }
mask = m_WIN0_EN | m_WIN0_DATA_FMT | m_WIN0_FMT_10 |
m_WIN0_LB_MODE | m_WIN0_RB_SWAP | m_WIN0_X_MIRROR |
- m_WIN0_Y_MIRROR | m_WIN0_CSC_MODE;
+ m_WIN0_Y_MIRROR | m_WIN0_CSC_MODE |m_WIN0_UV_SWAP;
val = v_WIN0_EN(win->state) |
v_WIN0_DATA_FMT(win->area[0].fmt_cfg) |
v_WIN0_FMT_10(win->fmt_10) |
v_WIN0_RB_SWAP(win->area[0].swap_rb) |
v_WIN0_X_MIRROR(win->mirror_en) |
v_WIN0_Y_MIRROR(win->mirror_en) |
- v_WIN0_CSC_MODE(win->csc_mode);
+ v_WIN0_CSC_MODE(win->csc_mode) |
+ v_WIN0_UV_SWAP(win->area[0].swap_uv);
lcdc_msk_reg(lcdc_dev, WIN0_CTRL0 + off, mask, val);
mask = m_WIN0_BIC_COE_SEL |
struct lcdc_device *lcdc_dev =
container_of(dev_drv, struct lcdc_device, driver);
struct rk_lcdc_win *win = dev_drv->win[win_id];
- struct rk_screen *screen = dev_drv->cur_screen;
unsigned int mask, val, off;
off = (win_id - 2) * 0x50;
rk3368_lcdc_area_xst(win, win->area_num);
- if (((screen->y_mirror == 1) || (win->mirror_en)) &&
- (win->area_num > 1)) {
- rk3368_lcdc_area_swap(win, win->area_num);
- }
if (win->state == 1) {
rk3368_lcdc_csc_mode(lcdc_dev, win);
- if (win->area[0].fbdc_en)
+ if (win->area[0].fbdc_en) {
rk3368_fbdc_reg_update(&lcdc_dev->driver, win_id);
+ } else {
+ mask = m_IFBDC_CTRL_FBDC_EN;
+ val = v_IFBDC_CTRL_FBDC_EN(0);
+ lcdc_msk_reg(lcdc_dev, IFBDC_CTRL, mask, val);
+ }
mask = m_WIN2_EN | m_WIN2_CSC_MODE;
val = v_WIN2_EN(1) | v_WIN1_CSC_MODE(win->csc_mode);
}
/*area 1 */
if (win->area[1].state == 1) {
- rk3368_win_area_check_var(win_id, 1,
+ /*rk3368_win_area_check_var(win_id, 1,
&win->area[0], &win->area[1]);
+ */
mask = m_WIN2_MST1_EN | m_WIN2_DATA_FMT1 |
m_WIN2_RB_SWAP1;
val = v_WIN2_MST1_EN(win->area[1].state) |
- v_WIN2_DATA_FMT0(win->area[1].fmt_cfg) |
- v_WIN2_RB_SWAP0(win->area[1].swap_rb);
+ v_WIN2_DATA_FMT1(win->area[1].fmt_cfg) |
+ v_WIN2_RB_SWAP1(win->area[1].swap_rb);
lcdc_msk_reg(lcdc_dev, WIN2_CTRL0 + off, mask, val);
mask = m_WIN2_VIR_STRIDE1;
}
/*area 2 */
if (win->area[2].state == 1) {
- rk3368_win_area_check_var(win_id, 2,
+ /*rk3368_win_area_check_var(win_id, 2,
&win->area[1], &win->area[2]);
+ */
mask = m_WIN2_MST2_EN | m_WIN2_DATA_FMT2 |
m_WIN2_RB_SWAP2;
val = v_WIN2_MST2_EN(win->area[2].state) |
- v_WIN2_DATA_FMT0(win->area[2].fmt_cfg) |
- v_WIN2_RB_SWAP0(win->area[2].swap_rb);
+ v_WIN2_DATA_FMT2(win->area[2].fmt_cfg) |
+ v_WIN2_RB_SWAP2(win->area[2].swap_rb);
lcdc_msk_reg(lcdc_dev, WIN2_CTRL0 + off, mask, val);
mask = m_WIN2_VIR_STRIDE2;
}
/*area 3 */
if (win->area[3].state == 1) {
- rk3368_win_area_check_var(win_id, 3,
+ /*rk3368_win_area_check_var(win_id, 3,
&win->area[2], &win->area[3]);
+ */
mask = m_WIN2_MST3_EN | m_WIN2_DATA_FMT3 |
m_WIN2_RB_SWAP3;
val = v_WIN2_MST3_EN(win->area[3].state) |
- v_WIN2_DATA_FMT0(win->area[3].fmt_cfg) |
- v_WIN2_RB_SWAP0(win->area[3].swap_rb);
+ v_WIN2_DATA_FMT3(win->area[3].fmt_cfg) |
+ v_WIN2_RB_SWAP3(win->area[3].swap_rb);
lcdc_msk_reg(lcdc_dev, WIN2_CTRL0 + off, mask, val);
mask = m_WIN2_VIR_STRIDE3;
static int rk3368_lcdc_reg_restore(struct lcdc_device *lcdc_dev)
{
- if (lcdc_dev->driver.iommu_enabled)
- memcpy((u8 *)lcdc_dev->regs, (u8 *)lcdc_dev->regsbak, 0x330);
- else
- memcpy((u8 *)lcdc_dev->regs, (u8 *)lcdc_dev->regsbak, 0x260);
+ memcpy((u8 *)lcdc_dev->regs, (u8 *)lcdc_dev->regsbak, 0x270);
return 0;
}
u32 mask, val;
struct lcdc_device *lcdc_dev =
container_of(dev_drv, struct lcdc_device, driver);
- /*spin_lock(&lcdc_dev->reg_lock); */
- if (likely(lcdc_dev->clk_on)) {
- mask = m_MMU_EN;
- val = v_MMU_EN(1);
- lcdc_msk_reg(lcdc_dev, SYS_CTRL, mask, val);
- mask = m_AXI_MAX_OUTSTANDING_EN | m_AXI_OUTSTANDING_MAX_NUM;
- val = v_AXI_OUTSTANDING_MAX_NUM(31) |
- v_AXI_MAX_OUTSTANDING_EN(1);
- lcdc_msk_reg(lcdc_dev, SYS_CTRL1, mask, val);
- }
- /*spin_unlock(&lcdc_dev->reg_lock); */
+
#if defined(CONFIG_ROCKCHIP_IOMMU)
if (dev_drv->iommu_enabled) {
if (!lcdc_dev->iommu_status && dev_drv->mmu_dev) {
+ if (likely(lcdc_dev->clk_on)) {
+ mask = m_MMU_EN;
+ val = v_MMU_EN(1);
+ lcdc_msk_reg(lcdc_dev, SYS_CTRL, mask, val);
+ mask = m_AXI_MAX_OUTSTANDING_EN |
+ m_AXI_OUTSTANDING_MAX_NUM;
+ val = v_AXI_OUTSTANDING_MAX_NUM(31) |
+ v_AXI_MAX_OUTSTANDING_EN(1);
+ lcdc_msk_reg(lcdc_dev, SYS_CTRL1, mask, val);
+ }
lcdc_dev->iommu_status = 1;
rockchip_iovmm_activate(dev_drv->dev);
- rk312x_lcdc_mmu_en(dev_drv);
}
}
#endif
return 0;
}
-static int rk3368_lcdc_set_dclk(struct rk_lcdc_driver *dev_drv)
+static int rk3368_lcdc_set_dclk(struct rk_lcdc_driver *dev_drv, int reset_rate)
{
int ret = 0, fps = 0;
struct lcdc_device *lcdc_dev =
#ifdef CONFIG_RK_FPGA
return 0;
#endif
- /*set pll */
- ret = clk_set_rate(lcdc_dev->pll_sclk, screen->mode.pixclock);
- if (ret)
- dev_err(dev_drv->dev, "set lcdc%d pll_sclk failed\n",
- lcdc_dev->id);
-
- ret = clk_set_rate(lcdc_dev->dclk, screen->mode.pixclock);/*set pll */
+ if (reset_rate)
+ ret = clk_set_rate(lcdc_dev->dclk, screen->mode.pixclock);/*set pll */
if (ret)
dev_err(dev_drv->dev, "set lcdc%d dclk failed\n", lcdc_dev->id);
lcdc_dev->pixclock =
h_total = hsync_len + left_margin + x_res + right_margin;
v_total = vsync_len + upper_margin + y_res + lower_margin;
- screen->post_dsp_stx = x_res * (100 - screen->overscan.left) / 200;
- screen->post_dsp_sty = y_res * (100 - screen->overscan.top) / 200;
- screen->post_xsize = x_res *
- (screen->overscan.left + screen->overscan.right) / 200;
- screen->post_ysize = y_res *
- (screen->overscan.top + screen->overscan.bottom) / 200;
-
mask = m_DSP_HS_PW | m_DSP_HTOTAL;
val = v_DSP_HS_PW(hsync_len) | v_DSP_HTOTAL(h_total);
lcdc_msk_reg(lcdc_dev, DSP_HTOTAL_HS_END, mask, val);
val = v_HWC_INTERLACE_READ(1);
lcdc_msk_reg(lcdc_dev, HWC_CTRL0, mask, val);
- mask = m_DSP_LINE_FLAG0_NUM;
+ mask = m_DSP_LINE_FLAG0_NUM | m_DSP_LINE_FLAG1_NUM;
val =
- v_DSP_LINE_FLAG0_NUM(vsync_len + upper_margin + y_res / 2);
+ v_DSP_LINE_FLAG0_NUM(vsync_len + upper_margin + y_res / 2) |
+ v_DSP_LINE_FLAG1_NUM(vsync_len + upper_margin + y_res / 2);
lcdc_msk_reg(lcdc_dev, LINE_FLAG, mask, val);
} else {
mask = m_DSP_VS_PW | m_DSP_VTOTAL;
val = v_HWC_INTERLACE_READ(0);
lcdc_msk_reg(lcdc_dev, HWC_CTRL0, mask, val);
- mask = m_DSP_LINE_FLAG0_NUM;
- val = v_DSP_LINE_FLAG0_NUM(vsync_len + upper_margin + y_res);
+ mask = m_DSP_LINE_FLAG0_NUM | m_DSP_LINE_FLAG1_NUM;
+ val = v_DSP_LINE_FLAG0_NUM(vsync_len + upper_margin + y_res) |
+ v_DSP_LINE_FLAG1_NUM(vsync_len + upper_margin + y_res);
lcdc_msk_reg(lcdc_dev, LINE_FLAG, mask, val);
}
rk3368_lcdc_post_cfg(dev_drv);
container_of(dev_drv, struct lcdc_device, driver);
u32 bcsh_ctrl;
+ lcdc_msk_reg(lcdc_dev, SYS_CTRL, m_OVERLAY_MODE,
+ v_OVERLAY_MODE(dev_drv->overlay_mode));
if (dev_drv->overlay_mode == VOP_YUV_DOMAIN) {
if (dev_drv->output_color == COLOR_YCBCR) /* bypass */
lcdc_msk_reg(lcdc_dev, BCSH_CTRL,
/* bypass --need check,if bcsh close? */
if (dev_drv->output_color == COLOR_RGB) {
bcsh_ctrl = lcdc_readl(lcdc_dev, BCSH_CTRL);
- if ((bcsh_ctrl & m_BCSH_EN) == 1)/*bcsh enabled */
+ if (((bcsh_ctrl & m_BCSH_EN) == 1) ||
+ (dev_drv->bcsh.enable == 1))/*bcsh enabled */
lcdc_msk_reg(lcdc_dev, BCSH_CTRL,
m_BCSH_R2Y_EN |
m_BCSH_Y2R_EN,
}
}
+static int rk3368_get_dspbuf_info(struct rk_lcdc_driver *dev_drv, u16 *xact,
+ u16 *yact, int *format, u32 *dsp_addr)
+{
+ struct lcdc_device *lcdc_dev = container_of(dev_drv,
+ struct lcdc_device, driver);
+ u32 val;
+
+ spin_lock(&lcdc_dev->reg_lock);
+
+ val = lcdc_readl(lcdc_dev, WIN0_ACT_INFO);
+ *xact = (val & m_WIN0_ACT_WIDTH) + 1;
+ *yact = ((val & m_WIN0_ACT_HEIGHT)>>16) + 1;
+
+ val = lcdc_readl(lcdc_dev, WIN0_CTRL0);
+ *format = (val & m_WIN0_DATA_FMT) >> 1;
+ *dsp_addr = lcdc_readl(lcdc_dev, WIN0_YRGB_MST);
+
+ spin_unlock(&lcdc_dev->reg_lock);
+
+ return 0;
+}
+
+static int rk3368_post_dspbuf(struct rk_lcdc_driver *dev_drv, u32 rgb_mst,
+ int format, u16 xact, u16 yact, u16 xvir)
+{
+ struct lcdc_device *lcdc_dev = container_of(dev_drv,
+ struct lcdc_device, driver);
+ u32 val, mask;
+ int swap = (format == RGB888) ? 1 : 0;
+
+ mask = m_WIN0_DATA_FMT | m_WIN0_RB_SWAP;
+ val = v_WIN0_DATA_FMT(format) | v_WIN0_RB_SWAP(swap);
+ lcdc_msk_reg(lcdc_dev, WIN0_CTRL0, mask, val);
+
+ lcdc_msk_reg(lcdc_dev, WIN0_VIR, m_WIN0_VIR_STRIDE,
+ v_WIN0_VIR_STRIDE(xvir));
+ lcdc_writel(lcdc_dev, WIN0_ACT_INFO, v_WIN0_ACT_WIDTH(xact) |
+ v_WIN0_ACT_HEIGHT(yact));
+
+ lcdc_writel(lcdc_dev, WIN0_YRGB_MST, rgb_mst);
+
+ lcdc_cfg_done(lcdc_dev);
+
+ return 0;
+}
+
+
static int rk3368_load_screen(struct rk_lcdc_driver *dev_drv, bool initscreen)
{
u16 face = 0;
v = 0 << 15 | (1 << (15 + 16));
break;
case SCREEN_HDMI:
- face = OUT_RGB_AAA;
- mask = m_HDMI_OUT_EN;
- val = v_HDMI_OUT_EN(1);
+ /*face = OUT_RGB_AAA;*/
+ if (screen->color_mode == COLOR_RGB)
+ dev_drv->overlay_mode = VOP_RGB_DOMAIN;
+ else
+ dev_drv->overlay_mode = VOP_YUV_DOMAIN;
+ mask = m_HDMI_OUT_EN | m_RGB_OUT_EN;
+ val = v_HDMI_OUT_EN(1) | v_RGB_OUT_EN(0);
lcdc_msk_reg(lcdc_dev, SYS_CTRL, mask, val);
mask = m_HDMI_HSYNC_POL | m_HDMI_VSYNC_POL |
m_HDMI_DEN_POL | m_HDMI_DCLK_POL;
v_HDMI_DCLK_POL(screen->pin_dclk);
break;
case SCREEN_MIPI:
- mask = m_MIPI_OUT_EN;
- val = v_MIPI_OUT_EN(1);
+ mask = m_MIPI_OUT_EN | m_RGB_OUT_EN;
+ val = v_MIPI_OUT_EN(1) | v_RGB_OUT_EN(0);
lcdc_msk_reg(lcdc_dev, SYS_CTRL, mask, val);
mask = m_MIPI_HSYNC_POL | m_MIPI_VSYNC_POL |
m_MIPI_DEN_POL | m_MIPI_DCLK_POL;
v_MIPI_DCLK_POL(screen->pin_dclk);
break;
case SCREEN_DUAL_MIPI:
- mask = m_MIPI_OUT_EN | m_DOUB_CHANNEL_EN;
- val = v_MIPI_OUT_EN(1) | v_DOUB_CHANNEL_EN(1);
+ mask = m_MIPI_OUT_EN | m_DOUB_CHANNEL_EN |
+ m_RGB_OUT_EN;
+ val = v_MIPI_OUT_EN(1) | v_DOUB_CHANNEL_EN(1) |
+ v_RGB_OUT_EN(0);
lcdc_msk_reg(lcdc_dev, SYS_CTRL, mask, val);
mask = m_MIPI_HSYNC_POL | m_MIPI_VSYNC_POL |
m_MIPI_DEN_POL | m_MIPI_DCLK_POL;
v_MIPI_DCLK_POL(screen->pin_dclk);
break;
case SCREEN_EDP:
- face = OUT_RGB_AAA; /*RGB AAA output */
+ face = OUT_P888; /*RGB 888 output */
- mask = m_EDP_OUT_EN;
- val = v_EDP_OUT_EN(1);
+ mask = m_EDP_OUT_EN | m_RGB_OUT_EN;
+ val = v_EDP_OUT_EN(1) | v_RGB_OUT_EN(0);
lcdc_msk_reg(lcdc_dev, SYS_CTRL, mask, val);
/*because edp have to sent aaa fmt */
mask = m_DITHER_DOWN_EN | m_DITHER_UP_EN;
lcdc_msk_reg(lcdc_dev, DSP_CTRL0, mask, val);
/*BG color */
mask = m_DSP_BG_BLUE | m_DSP_BG_GREEN | m_DSP_BG_RED;
- val = v_DSP_BG_BLUE(0) | v_DSP_BG_GREEN(0) | v_DSP_BG_RED(0);
+ if (dev_drv->overlay_mode == VOP_YUV_DOMAIN)
+ val = v_DSP_BG_BLUE(0x80) | v_DSP_BG_GREEN(0x10) |
+ v_DSP_BG_RED(0x80);
+ else
+ val = v_DSP_BG_BLUE(0) | v_DSP_BG_GREEN(0) |
+ v_DSP_BG_RED(0);
lcdc_msk_reg(lcdc_dev, DSP_BG, mask, val);
+ dev_drv->output_color = screen->color_mode;
+ if (screen->dsp_lut == NULL)
+ lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_LUT_EN,
+ v_DSP_LUT_EN(0));
+ 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);
}
spin_unlock(&lcdc_dev->reg_lock);
- rk3368_lcdc_set_dclk(dev_drv);
+ rk3368_lcdc_set_dclk(dev_drv, 1);
if (screen->type != SCREEN_HDMI && dev_drv->trsm_ops &&
dev_drv->trsm_ops->enable)
dev_drv->trsm_ops->enable();
v_LINE_FLAG0_INTR_CLR(1) | v_LINE_FLAG1_INTR_CLR(1);
lcdc_msk_reg(lcdc_dev, INTR_CLEAR, mask, val);
- mask = m_FS_INTR_EN | m_LINE_FLAG0_INTR_EN | m_BUS_ERROR_INTR_EN;
+ mask = m_FS_INTR_EN | m_LINE_FLAG0_INTR_EN |
+ m_BUS_ERROR_INTR_EN | m_LINE_FLAG1_INTR_EN;
val = v_FS_INTR_EN(1) | v_LINE_FLAG0_INTR_EN(1) |
- v_BUS_ERROR_INTR_EN(1);
+ v_BUS_ERROR_INTR_EN(1) | v_LINE_FLAG1_INTR_EN(0);
lcdc_msk_reg(lcdc_dev, INTR_EN, mask, val);
#ifdef LCDC_IRQ_EMPTY_DEBUG
{
struct lcdc_device *lcdc_dev =
container_of(dev_drv, struct lcdc_device, driver);
-#ifndef CONFIG_RK_FPGA
+#if 0/*ndef CONFIG_RK_FPGA*/
int sys_status =
(dev_drv->id == 0) ? SYS_STATUS_LCDC0 : SYS_STATUS_LCDC1;
#endif
/*enable clk,when first layer open */
if ((open) && (!lcdc_dev->atv_layer_cnt)) {
-#ifndef CONFIG_RK_FPGA
- rockchip_set_system_status(sys_status);
-#endif
+ /*rockchip_set_system_status(sys_status);*/
rk3368_lcdc_pre_init(dev_drv);
rk3368_lcdc_clk_enable(lcdc_dev);
#if defined(CONFIG_ROCKCHIP_IOMMU)
/*if (dev_drv->iommu_enabled)
rk3368_lcdc_mmu_en(dev_drv); */
if ((support_uboot_display() && (lcdc_dev->prop == PRMRY))) {
- /*rk3368_lcdc_set_dclk(dev_drv); */
+ rk3368_lcdc_set_dclk(dev_drv, 0);
rk3368_lcdc_enable_irq(dev_drv);
} else {
rk3368_load_screen(dev_drv, 1);
rk3368_lcdc_set_bcsh(dev_drv, 1);
spin_lock(&lcdc_dev->reg_lock);
if (dev_drv->cur_screen->dsp_lut)
- rk3368_lcdc_set_lut(dev_drv);
+ 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);
}
win->area[0].uv_addr = uv_addr;
lcdc_writel(lcdc_dev, WIN0_YRGB_MST + off, win->area[0].y_addr);
lcdc_writel(lcdc_dev, WIN0_CBR_MST + off, win->area[0].uv_addr);
- /*lcdc_cfg_done(lcdc_dev); */
+ if (win->area[0].fbdc_en == 1)
+ lcdc_writel(lcdc_dev, IFBDC_BASE_ADDR,
+ win->area[0].y_addr);
}
spin_unlock(&lcdc_dev->reg_lock);
lcdc_writel(lcdc_dev, WIN2_MST1 + off, win->area[1].y_addr);
lcdc_writel(lcdc_dev, WIN2_MST2 + off, win->area[2].y_addr);
lcdc_writel(lcdc_dev, WIN2_MST3 + off, win->area[3].y_addr);
+ if (win->area[0].fbdc_en == 1)
+ lcdc_writel(lcdc_dev, IFBDC_BASE_ADDR,
+ win->area[0].y_addr);
}
spin_unlock(&lcdc_dev->reg_lock);
return 0;
break;
case YUV420:
case YUV420_A:
+ case YUV420_NV21:
cbcr_srcW = srcW / 2;
cbcr_dstW = dstW;
cbcr_srcH = srcH / 2;
/*line buffer mode */
if ((win->area[0].format == YUV422) ||
(win->area[0].format == YUV420) ||
+ (win->area[0].format == YUV420_NV21) ||
(win->area[0].format == YUV422_A) ||
(win->area[0].format == YUV420_A)) {
if (win->cbr_hor_scl_mode == SCALE_DOWN) {
return 0;
}
+static int dsp_x_pos(int mirror_en, struct rk_screen *screen,
+ struct rk_lcdc_win_area *area)
+{
+ int pos;
+
+ if (screen->x_mirror && mirror_en)
+ pr_err("not support both win and global mirror\n");
+
+ if ((!mirror_en) && (!screen->x_mirror))
+ pos = area->xpos + screen->mode.left_margin +
+ screen->mode.hsync_len;
+ else
+ pos = screen->mode.xres - area->xpos -
+ area->xsize + screen->mode.left_margin +
+ screen->mode.hsync_len;
+
+ return pos;
+}
+
+static int dsp_y_pos(int mirror_en, struct rk_screen *screen,
+ struct rk_lcdc_win_area *area)
+{
+ int pos;
+
+ if (screen->y_mirror && mirror_en)
+ pr_err("not support both win and global mirror\n");
+ if (screen->mode.vmode == FB_VMODE_NONINTERLACED) {
+ if ((!mirror_en) && (!screen->y_mirror))
+ pos = area->ypos + screen->mode.upper_margin +
+ screen->mode.vsync_len;
+ else
+ pos = screen->mode.yres - area->ypos -
+ area->ysize + screen->mode.upper_margin +
+ screen->mode.vsync_len;
+ } else if (screen->mode.vmode == FB_VMODE_INTERLACED) {
+ pos = area->ypos / 2 + screen->mode.upper_margin +
+ screen->mode.vsync_len;
+ area->ysize /= 2;
+ }
+
+ return pos;
+}
+
static int win_0_1_set_par(struct lcdc_device *lcdc_dev,
struct rk_screen *screen, struct rk_lcdc_win *win)
{
u32 xact, yact, xvir, yvir, xpos, ypos;
- u8 fmt_cfg = 0, swap_rb;
+ u8 fmt_cfg = 0, swap_rb, swap_uv = 0;
char fmt[9] = "NULL";
- if (!win->mirror_en) {
- xpos = win->area[0].xpos + screen->mode.left_margin +
- screen->mode.hsync_len;
- ypos = win->area[0].ypos + screen->mode.upper_margin +
- screen->mode.vsync_len;
- } else {
- xpos = screen->mode.xres - win->area[0].xpos -
- win->area[0].xsize +
- screen->mode.left_margin + screen->mode.hsync_len;
- ypos = screen->mode.yres - win->area[0].ypos -
- win->area[0].ysize + screen->mode.upper_margin +
- screen->mode.vsync_len;
- }
+ xpos = dsp_x_pos(win->mirror_en, screen, &win->area[0]);
+ ypos = dsp_y_pos(win->mirror_en, screen, &win->area[0]);
+
spin_lock(&lcdc_dev->reg_lock);
if (likely(lcdc_dev->clk_on)) {
rk3368_lcdc_cal_scl_fac(win); /*fac,lb,gt2,gt4 */
switch (win->area[0].format) {
+ case FBDC_RGB_565:
+ fmt_cfg = 2;
+ swap_rb = 0;
+ win->fmt_10 = 0;
+ win->area[0].fbdc_fmt_cfg = 0x05;
+ break;
+ case FBDC_ARGB_888:
+ fmt_cfg = 0;
+ swap_rb = 0;
+ win->fmt_10 = 0;
+ win->area[0].fbdc_fmt_cfg = 0x0c;
+ break;
+ case FBDC_ABGR_888:
+ fmt_cfg = 0;
+ swap_rb = 1;
+ win->fmt_10 = 0;
+ win->area[0].fbdc_fmt_cfg = 0x0c;
+ break;
+ case FBDC_RGBX_888:
+ fmt_cfg = 0;
+ swap_rb = 0;
+ win->fmt_10 = 0;
+ win->area[0].fbdc_fmt_cfg = 0x3a;
+ break;
case ARGB888:
fmt_cfg = 0;
swap_rb = 0;
swap_rb = 0;
win->fmt_10 = 0;
break;
+ case YUV420_NV21:
+ fmt_cfg = 4;
+ swap_rb = 0;
+ swap_uv = 1;
+ win->fmt_10 = 0;
+ break;
case YUV444:
fmt_cfg = 6;
swap_rb = 0;
}
win->area[0].fmt_cfg = fmt_cfg;
win->area[0].swap_rb = swap_rb;
+ win->area[0].swap_uv = swap_uv;
win->area[0].dsp_stx = xpos;
win->area[0].dsp_sty = ypos;
xact = win->area[0].xact;
u8 fmt_cfg, swap_rb;
char fmt[9] = "NULL";
+ if (win->mirror_en)
+ pr_err("win[%d] not support y mirror\n", win->id);
spin_lock(&lcdc_dev->reg_lock);
if (likely(lcdc_dev->clk_on)) {
DBG(2, "lcdc[%d]:win[%d]>>\n>\n", lcdc_dev->id, win->id);
for (i = 0; i < win->area_num; i++) {
switch (win->area[i].format) {
+ case FBDC_RGB_565:
+ fmt_cfg = 2;
+ swap_rb = 0;
+ win->fmt_10 = 0;
+ win->area[0].fbdc_fmt_cfg = 0x05;
+ break;
+ case FBDC_ARGB_888:
+ fmt_cfg = 0;
+ swap_rb = 0;
+ win->fmt_10 = 0;
+ win->area[0].fbdc_fmt_cfg = 0x0c;
+ break;
+ case FBDC_RGBX_888:
+ fmt_cfg = 0;
+ swap_rb = 0;
+ win->fmt_10 = 0;
+ win->area[0].fbdc_fmt_cfg = 0x3a;
+ break;
case ARGB888:
fmt_cfg = 0;
swap_rb = 0;
}
win->area[i].fmt_cfg = fmt_cfg;
win->area[i].swap_rb = swap_rb;
- win->area[i].dsp_stx = win->area[i].xpos +
- screen->mode.left_margin + screen->mode.hsync_len;
- if (screen->y_mirror == 1) {
- win->area[i].dsp_sty = screen->mode.yres -
- win->area[i].ypos -
- win->area[i].ysize +
- screen->mode.upper_margin +
- screen->mode.vsync_len;
- } else {
- win->area[i].dsp_sty = win->area[i].ypos +
- screen->mode.upper_margin +
- screen->mode.vsync_len;
+ win->area[i].dsp_stx =
+ dsp_x_pos(win->mirror_en, screen,
+ &win->area[i]);
+ win->area[i].dsp_sty =
+ dsp_y_pos(win->mirror_en, screen,
+ &win->area[i]);
+ if ((win->area[i].xact != win->area[i].xsize) ||
+ (win->area[i].yact != win->area[i].ysize)) {
+ pr_err("win[%d]->area[%d],not support scale\n",
+ win->id, i);
+ pr_err("xact=%d,yact=%d,xsize=%d,ysize=%d\n",
+ win->area[i].xact,win->area[i].yact,
+ win->area[i].xsize,win->area[i].ysize);
+ win->area[i].xsize = win->area[i].xact;
+ win->area[i].ysize = win->area[i].yact;
}
-
DBG(2, "fmt:%s:xsize:%d>>ysize:%d>>xpos:%d>>ypos:%d\n",
get_format_string(win->area[i].format, fmt),
win->area[i].xsize, win->area[i].ysize,
static int rk3368_lcdc_early_suspend(struct rk_lcdc_driver *dev_drv)
{
- u32 reg;
struct lcdc_device *lcdc_dev =
container_of(dev_drv, struct lcdc_device, driver);
if (dev_drv->suspend_flag)
dev_drv->suspend_flag = 1;
flush_kthread_worker(&dev_drv->update_regs_worker);
- for (reg = MMU_DTE_ADDR; reg <= MMU_AUTO_GATING; reg += 4)
- lcdc_readl(lcdc_dev, reg);
if (dev_drv->trsm_ops && dev_drv->trsm_ops->disable)
dev_drv->trsm_ops->disable();
{
struct lcdc_device *lcdc_dev =
container_of(dev_drv, struct lcdc_device, driver);
- int i, j;
- int __iomem *c;
- int v, r, g, b;
if (!dev_drv->suspend_flag)
return 0;
rk3368_lcdc_reg_restore(lcdc_dev);
spin_lock(&lcdc_dev->reg_lock);
- if (dev_drv->cur_screen->dsp_lut) {
- 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++) {
- v = dev_drv->cur_screen->dsp_lut[i];
- c = lcdc_dev->dsp_lut_addr_base + (i << 2);
- b = (v & 0xff);
- g = (v & 0xff00);
- r = (v & 0xff0000);
- v = r + g + b;
- for (j = 0; j < 4; j++) {
- writel_relaxed(v, c);
- v += (1 + (1 << 10) + (1 << 20));
- c++;
- }
- }
- lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_LUT_EN,
- v_DSP_LUT_EN(1));
- }
+ 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));
if (dev_drv->trsm_ops && dev_drv->trsm_ops->enable)
dev_drv->trsm_ops->enable();
-
return 0;
}
static int rk3368_lcdc_get_win_state(struct rk_lcdc_driver *dev_drv, int win_id)
{
- return 0;
+ struct lcdc_device *lcdc_dev =
+ container_of(dev_drv, struct lcdc_device, driver);
+ int win_status = 0;
+ if (win_id == 0)
+ win_status = lcdc_read_bit(lcdc_dev, WIN0_CTRL0, m_WIN0_EN);
+ else if (win_id == 1)
+ win_status = lcdc_read_bit(lcdc_dev, WIN1_CTRL0, m_WIN1_EN);
+ else if (win_id == 2)
+ win_status = lcdc_read_bit(lcdc_dev, WIN2_CTRL0, m_WIN2_EN);
+ else if (win_id == 3)
+ win_status = lcdc_read_bit(lcdc_dev, WIN3_CTRL0, m_WIN3_EN);
+ else if (win_id == 4)
+ win_status = lcdc_read_bit(lcdc_dev, HWC_CTRL0, m_HWC_EN);
+ else
+ pr_err("!!!%s,win_id :%d,unsupport!!!\n",__func__,win_id);
+
+ return win_status;
}
/*overlay will be do at regupdate*/
/*WIN2 */
win_ctrl = lcdc_readl(lcdc_dev, WIN2_CTRL0);
w2_state = win_ctrl & m_WIN2_EN;
- w2_0_state = (win_ctrl & m_WIN2_MST0_EN) >> 4;
- w2_1_state = (win_ctrl & m_WIN2_MST1_EN) >> 5;
- w2_2_state = (win_ctrl & m_WIN2_MST2_EN) >> 6;
- w2_3_state = (win_ctrl & m_WIN2_MST3_EN) >> 7;
+ w2_0_state = (win_ctrl & 0x10) >> 4;
+ w2_1_state = (win_ctrl & 0x100) >> 8;
+ w2_2_state = (win_ctrl & 0x1000) >> 12;
+ w2_3_state = (win_ctrl & 0x10000) >> 16;
vir_info = lcdc_readl(lcdc_dev, WIN2_VIR0_1);
w2_0_vir_y = vir_info & m_WIN2_VIR_STRIDE0;
w2_1_vir_y = (vir_info & m_WIN2_VIR_STRIDE1) >> 16;
win_ctrl = lcdc_readl(lcdc_dev, WIN3_CTRL0);
w3_state = win_ctrl & m_WIN3_EN;
w3_0_state = (win_ctrl & m_WIN3_MST0_EN) >> 4;
- w3_1_state = (win_ctrl & m_WIN3_MST1_EN) >> 5;
- w3_2_state = (win_ctrl & m_WIN3_MST2_EN) >> 6;
- w3_3_state = (win_ctrl & m_WIN3_MST3_EN) >> 7;
+ w3_1_state = (win_ctrl & m_WIN3_MST1_EN) >> 8;
+ w3_2_state = (win_ctrl & m_WIN3_MST2_EN) >> 12;
+ w3_3_state = (win_ctrl & m_WIN3_MST3_EN) >> 16;
vir_info = lcdc_readl(lcdc_dev, WIN3_VIR0_1);
w3_0_vir_y = vir_info & m_WIN3_VIR_STRIDE0;
w3_1_vir_y = (vir_info & m_WIN3_VIR_STRIDE1) >> 16;
screen->mode.xres + screen->mode.hsync_len;
dev_drv->pixclock = div_u64(ft, x_total * y_total);
dotclk = div_u64(1000000000000llu, dev_drv->pixclock);
- ret = clk_set_rate(lcdc_dev->pll_sclk, dotclk); /*set pll */
- if (ret)
- dev_err(dev_drv->dev,
- "set lcdc%d pll_sclk failed\n", lcdc_dev->id);
-
ret = clk_set_rate(lcdc_dev->dclk, dotclk);
- /*SET NEW PLL FOR RK3368 */
}
pixclock = div_u64(1000000000000llu, clk_get_rate(lcdc_dev->dclk));
return win_id;
}
-static int rk3368_set_dsp_lut(struct rk_lcdc_driver *dev_drv, int *lut)
-{
- int i, j;
- int __iomem *c;
- int v, r, g, b;
- int ret = 0;
-
- 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_cfg_done(lcdc_dev);
- mdelay(25);
- if (dev_drv->cur_screen->dsp_lut) {
- for (i = 0; i < 256; i++) {
- dev_drv->cur_screen->dsp_lut[i] = lut[i];
- v = dev_drv->cur_screen->dsp_lut[i];
- c = lcdc_dev->dsp_lut_addr_base + (i << 2);
- b = (v & 0xff) << 2;
- g = (v & 0xff00) << 4;
- r = (v & 0xff0000) << 6;
- v = r + g + b;
- for (j = 0; j < 4; j++) {
- writel_relaxed(v, c);
- v += (1 + (1 << 10) + (1 << 20));
- c++;
- }
- }
- } else {
- dev_err(dev_drv->dev, "no buffer to backup lut data!\n");
- ret = -1;
- }
-
- do {
- lcdc_msk_reg(lcdc_dev, DSP_CTRL1, m_DSP_LUT_EN,
- v_DSP_LUT_EN(1));
- lcdc_cfg_done(lcdc_dev);
- } while (!lcdc_read_bit(lcdc_dev, DSP_CTRL1, m_DSP_LUT_EN));
- return ret;
-}
-
static int rk3368_lcdc_config_done(struct rk_lcdc_driver *dev_drv)
{
struct lcdc_device *lcdc_dev =
}
static struct lcdc_cabc_mode cabc_mode[4] = {
- /* pixel_num,8 stage_up, stage_down */
- {5, 148, 20, 300}, /*mode 1 */
- {10, 148, 20, 300}, /*mode 2 */
- {15, 148, 20, 300}, /*mode 3 */
- {20, 148, 20, 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)
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;
- u32 __maybe_unused max_mode_num =
- sizeof(cabc_mode) / sizeof(struct lcdc_cabc_mode);
+ int *cabc_lut = NULL;
- dev_drv->cabc_mode = mode;
-#if 0/*ndef CONFIG_RK_FPGA*/
- /* iomux connect to vop or pwm */
- if (mode == 0) {
- DBG(3, "close cabc and select rk pwm\n");
- val = 0x30002;
- writel_relaxed(val, RK_GRF_VIRT + rk3368_GRF_GPIO3C_IOMUX);
- cabc_en = 0;
- } else if (mode > 0 && mode <= max_mode_num) {
- DBG(3, "open cabc and select vop pwm\n");
- val = 0x30003;
- writel_relaxed(val, RK_GRF_VIRT + rk3368_GRF_GPIO3C_IOMUX);
- cabc_en = 1;
- } else if (mode > 0x10 && mode <= (max_mode_num + 0x10)) {
- DBG(3, "open cabc and select rk pwm\n");
- val = 0x30003;
- writel_relaxed(val, RK_GRF_VIRT + rk3368_GRF_GPIO3C_IOMUX);
- cabc_en = 1;
- mode -= 0x10;
- } else if (mode == 0xff) {
- DBG(3, "close cabc and select vop pwm\n");
- val = 0x30002;
- writel_relaxed(val, RK_GRF_VIRT + rk3368_GRF_GPIO3C_IOMUX);
- cabc_en = 0;
- } else {
- dev_err(lcdc_dev->dev, "invalid cabc mode value:%d", mode);
+ if (!screen->cabc_lut) {
+ pr_err("screen cabc lut not config, so not open cabc\n");
return 0;
+ } else {
+ cabc_lut = screen->cabc_lut;
}
-#endif
+
+ dev_drv->cabc_mode = mode;
+ cabc_en = (mode > 0) ? 1 : 0;
+
if (cabc_en == 0) {
spin_lock(&lcdc_dev->reg_lock);
if (lcdc_dev->clk_on) {
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) {
- mask = m_CABC_CALC_PIXEL_NUM;
- val = v_CABC_CALC_PIXEL_NUM(calc_pixel);
+ mask = m_CABC_CALC_PIXEL_NUM | m_CABC_EN;
+ val = v_CABC_CALC_PIXEL_NUM(calc_pixel) |
+ v_CABC_EN(cabc_en);
lcdc_msk_reg(lcdc_dev, CABC_CTRL0, mask, val);
- mask = m_CABC_TOTAL_PIXEL_NUM;
- val = v_CABC_TOTAL_PIXEL_NUM(total_pixel);
+ mask = m_CABC_TOTAL_PIXEL_NUM | m_CABC_LUT_EN;
+ 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 |
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 |
spin_lock(&lcdc_dev->reg_lock);
if (lcdc_dev->clk_on) {
- rk3368_lcdc_bcsh_path_sel(dev_drv);
if (open) {
lcdc_writel(lcdc_dev, BCSH_COLOR_BAR, 0x1);
lcdc_writel(lcdc_dev, BCSH_BCS, 0xd0010000);
lcdc_writel(lcdc_dev, BCSH_H, 0x01000000);
+ dev_drv->bcsh.enable = 1;
} else {
mask = m_BCSH_EN;
val = v_BCSH_EN(0);
lcdc_msk_reg(lcdc_dev, BCSH_COLOR_BAR, mask, val);
+ dev_drv->bcsh.enable = 0;
}
+ rk3368_lcdc_bcsh_path_sel(dev_drv);
lcdc_cfg_done(lcdc_dev);
}
spin_unlock(&lcdc_dev->reg_lock);
struct lcdc_device *lcdc_dev =
container_of(dev_drv, struct lcdc_device, driver);
- rk3368_lcdc_get_backlight_device(dev_drv);
-
if (enable) {
- /* close the backlight */
- if (lcdc_dev->backlight) {
- lcdc_dev->backlight->props.power = FB_BLANK_POWERDOWN;
- backlight_update_status(lcdc_dev->backlight);
- }
-#if 1
spin_lock(&lcdc_dev->reg_lock);
if (likely(lcdc_dev->clk_on)) {
lcdc_msk_reg(lcdc_dev, DSP_CTRL0, m_DSP_BLACK_EN,
lcdc_cfg_done(lcdc_dev);
}
spin_unlock(&lcdc_dev->reg_lock);
-#endif
- if (dev_drv->trsm_ops && dev_drv->trsm_ops->disable)
- dev_drv->trsm_ops->disable();
} else {
-#if 1
spin_lock(&lcdc_dev->reg_lock);
if (likely(lcdc_dev->clk_on)) {
lcdc_msk_reg(lcdc_dev, DSP_CTRL0, m_DSP_BLACK_EN,
lcdc_cfg_done(lcdc_dev);
}
spin_unlock(&lcdc_dev->reg_lock);
-#endif
+ }
+
+ return 0;
+}
+
+
+static int rk3368_lcdc_backlight_close(struct rk_lcdc_driver *dev_drv,
+ int enable)
+{
+ struct lcdc_device *lcdc_dev =
+ container_of(dev_drv, struct lcdc_device, driver);
+
+ rk3368_lcdc_get_backlight_device(dev_drv);
+
+ if (enable) {
+ /* close the backlight */
+ if (lcdc_dev->backlight) {
+ lcdc_dev->backlight->props.power = FB_BLANK_POWERDOWN;
+ backlight_update_status(lcdc_dev->backlight);
+ }
+ if (dev_drv->trsm_ops && dev_drv->trsm_ops->disable)
+ dev_drv->trsm_ops->disable();
+ } else {
if (dev_drv->trsm_ops && dev_drv->trsm_ops->enable)
dev_drv->trsm_ops->enable();
msleep(100);
return 0;
}
+static int rk3368_lcdc_set_overscan(struct rk_lcdc_driver *dev_drv,
+ struct overscan *overscan)
+{
+ rk3368_lcdc_post_cfg(dev_drv);
+
+ return 0;
+}
+
static struct rk_lcdc_drv_ops lcdc_drv_ops = {
.open = rk3368_lcdc_open,
.win_direct_en = rk3368_lcdc_win_direct_en,
.load_screen = rk3368_load_screen,
+ .get_dspbuf_info = rk3368_get_dspbuf_info,
+ .post_dspbuf = rk3368_post_dspbuf,
.set_par = rk3368_lcdc_set_par,
.pan_display = rk3368_lcdc_pan_display,
.direct_set_addr = rk3368_lcdc_direct_set_win_addr,
.fps_mgr = rk3368_lcdc_fps_mgr,
.fb_get_win_id = rk3368_lcdc_get_win_id,
.fb_win_remap = rk3368_fb_win_remap,
- .set_dsp_lut = rk3368_set_dsp_lut,
+ .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,
.cfg_done = rk3368_lcdc_config_done,
.set_irq_to_cpu = rk3368_lcdc_set_irq_to_cpu,
.dsp_black = rk3368_lcdc_dsp_black,
+ .backlight_close = rk3368_lcdc_backlight_close,
.mmu_en = rk3368_lcdc_mmu_en,
+ .set_overscan = rk3368_lcdc_set_overscan,
};
#ifdef LCDC_IRQ_EMPTY_DEBUG
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)) {
+ dev_err(&pdev->dev, "can't find lcdc grf property\n");
+ return PTR_ERR(lcdc_dev->grf_base);
+ }
+ lcdc_dev->pmugrf_base =
+ syscon_regmap_lookup_by_phandle(np, "rockchip,pmugrf");
+ if (IS_ERR(lcdc_dev->pmugrf_base)) {
+ dev_err(&pdev->dev, "can't find lcdc pmu grf property\n");
+ return PTR_ERR(lcdc_dev->pmugrf_base);
+ }
lcdc_dev->id = 0;
dev_set_name(lcdc_dev->dev, "lcdc%d", lcdc_dev->id);
dev_drv = &lcdc_dev->driver;
{
struct lcdc_device *lcdc_dev = platform_get_drvdata(pdev);
+ rk3368_lcdc_early_suspend(&lcdc_dev->driver);
rk3368_lcdc_deint(lcdc_dev);
- rk_disp_pwr_disable(&lcdc_dev->driver);
}
#if defined(CONFIG_OF)