From 6360549b2cf2c238cdc898910f21b5e4b01ce39d Mon Sep 17 00:00:00 2001 From: Mark Yao Date: Mon, 21 Sep 2015 15:57:30 +0800 Subject: [PATCH] rk_fb: video: add rk3228 vop support Change-Id: Iaa8ea3da4de2746c4cff5e0e820b8f0508c44d55 Signed-off-by: Mark Yao --- drivers/video/rockchip/lcdc/Kconfig | 6 + drivers/video/rockchip/lcdc/Makefile | 1 + drivers/video/rockchip/lcdc/rk3228_lcdc.c | 3528 +++++++++++++++++++++ drivers/video/rockchip/lcdc/rk3228_lcdc.h | 1676 ++++++++++ 4 files changed, 5211 insertions(+) mode change 100755 => 100644 drivers/video/rockchip/lcdc/Kconfig create mode 100644 drivers/video/rockchip/lcdc/rk3228_lcdc.c create mode 100644 drivers/video/rockchip/lcdc/rk3228_lcdc.h diff --git a/drivers/video/rockchip/lcdc/Kconfig b/drivers/video/rockchip/lcdc/Kconfig old mode 100755 new mode 100644 index 9944657ce54a..bf63152d06a8 --- a/drivers/video/rockchip/lcdc/Kconfig +++ b/drivers/video/rockchip/lcdc/Kconfig @@ -50,3 +50,9 @@ config LCDC_RK3368 depends on ARM64 help Driver for rk3368 lcdc.There are one lcd controllers on rk3368 + +config LCDC_RK3228 + bool "rk3228 lcdc support" + depends on FB_ROCKCHIP + help + Driver for rk3228 lcdc.There are one lcd controllers on rk3228 diff --git a/drivers/video/rockchip/lcdc/Makefile b/drivers/video/rockchip/lcdc/Makefile index 8c878d025af9..fd84d05fb048 100644 --- a/drivers/video/rockchip/lcdc/Makefile +++ b/drivers/video/rockchip/lcdc/Makefile @@ -6,3 +6,4 @@ obj-$(CONFIG_LCDC_RK3288) += rk3288_lcdc.o obj-$(CONFIG_LCDC_RK3036) += rk3036_lcdc.o obj-$(CONFIG_LCDC_RK312X) += rk312x_lcdc.o obj-$(CONFIG_LCDC_RK3368) += rk3368_lcdc.o +obj-$(CONFIG_LCDC_RK3228) += rk3228_lcdc.o diff --git a/drivers/video/rockchip/lcdc/rk3228_lcdc.c b/drivers/video/rockchip/lcdc/rk3228_lcdc.c new file mode 100644 index 000000000000..3eb517cd880d --- /dev/null +++ b/drivers/video/rockchip/lcdc/rk3228_lcdc.c @@ -0,0 +1,3528 @@ +/* + * drivers/video/rockchip/lcdc/rk3228_lcdc.c + * + * Copyright (C) 2015 ROCKCHIP, Inc. + * Author: Mark Yao + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rk3228_lcdc.h" + +/*#define CONFIG_RK_FPGA 1*/ + +static int dbg_thresd; +module_param(dbg_thresd, int, S_IRUGO | S_IWUSR); + +#define DBG(level, x...) do { \ + if (unlikely(dbg_thresd >= level)) \ + pr_info(x);\ + } while (0) + +static const uint32_t csc_y2r_bt601_limit[12] = { + 0x04a8, 0, 0x0662, 0xfffc8654, + 0x04a8, 0xfe6f, 0xfcbf, 0x00022056, + 0x04a8, 0x0812, 0, 0xfffbaeac, +}; + +static const uint32_t csc_y2r_bt709_full[12] = { + 0x04a8, 0, 0x072c, 0xfffc219e, + 0x04a8, 0xff26, 0xfdde, 0x0001357b, + 0x04a8, 0x0873, 0, 0xfffb7dee, +}; + +static const uint32_t csc_y2r_bt601_full[12] = { + 0x0400, 0, 0x059c, 0xfffd342d, + 0x0400, 0xfea0, 0xfd25, 0x00021fcc, + 0x0400, 0x0717, 0, 0xfffc76bc, +}; + +static const uint32_t csc_y2r_bt601_limit_10[12] = { + 0x04a8, 0, 0x0662, 0xfff2134e, + 0x04a8, 0xfe6f, 0xfcbf, 0x00087b58, + 0x04a8, 0x0812, 0, 0xffeeb4b0, +}; + +static const uint32_t csc_y2r_bt709_full_10[12] = { + 0x04a8, 0, 0x072c, 0xfff08077, + 0x04a8, 0xff26, 0xfdde, 0x0004cfed, + 0x04a8, 0x0873, 0, 0xffedf1b8, +}; + +static const uint32_t csc_y2r_bt601_full_10[12] = { + 0x0400, 0, 0x059c, 0xfff4cab4, + 0x0400, 0xfea0, 0xfd25, 0x00087932, + 0x0400, 0x0717, 0, 0xfff1d4f2, +}; + +static const uint32_t csc_y2r_bt2020[12] = { + 0x04a8, 0, 0x06b6, 0xfff16bfc, + 0x04a8, 0xff40, 0xfd66, 0x58ae9, + 0x04a8, 0x0890, 0, 0xffedb828, +}; + +static const uint32_t csc_r2y_bt601_limit[12] = { + 0x0107, 0x0204, 0x0064, 0x04200, + 0xff68, 0xfed6, 0x01c2, 0x20200, + 0x01c2, 0xfe87, 0xffb7, 0x20200, +}; + +static const uint32_t csc_r2y_bt709_full[12] = { + 0x00bb, 0x0275, 0x003f, 0x04200, + 0xff99, 0xfea5, 0x01c2, 0x20200, + 0x01c2, 0xfe68, 0xffd7, 0x20200, +}; + +static const uint32_t csc_r2y_bt601_full[12] = { + 0x0132, 0x0259, 0x0075, 0x200, + 0xff53, 0xfead, 0x0200, 0x20200, + 0x0200, 0xfe53, 0xffad, 0x20200, +}; + +static const uint32_t csc_r2y_bt601_limit_10[12] = { + 0x0107, 0x0204, 0x0064, 0x10200, + 0xff68, 0xfed6, 0x01c2, 0x80200, + 0x01c2, 0xfe87, 0xffb7, 0x80200, +}; + +static const uint32_t csc_r2y_bt709_full_10[12] = { + 0x00bb, 0x0275, 0x003f, 0x10200, + 0xff99, 0xfea5, 0x01c2, 0x80200, + 0x01c2, 0xfe68, 0xffd7, 0x80200, +}; + +static const uint32_t csc_r2y_bt601_full_10[12] = { + 0x0132, 0x0259, 0x0075, 0x200, + 0xff53, 0xfead, 0x0200, 0x80200, + 0x0200, 0xfe53, 0xffad, 0x80200, +}; + +static const uint32_t csc_r2y_bt2020[12] = { + 0x00e6, 0x0253, 0x0034, 0x10200, + 0xff83, 0xfebd, 0x01c1, 0x80200, + 0x01c1, 0xfe64, 0xffdc, 0x80200, +}; + +static const uint32_t csc_r2r_bt2020to709[12] = { + 0x06a4, 0xfda6, 0xffb5, 0x200, + 0xff80, 0x0488, 0xfff8, 0x200, + 0xffed, 0xff99, 0x047a, 0x200, +}; + +static const uint32_t csc_r2r_bt709to2020[12] = { + 0x282, 0x151, 0x02c, 0x200, + 0x047, 0x3ae, 0x00c, 0x200, + 0x011, 0x05a, 0x395, 0x200, +}; + +static struct rk_lcdc_win vop_win[] = { + { .name = "win0", .id = 0}, + { .name = "win1", .id = 1}, + { .name = "hwc", .id = 2} +}; + +static void vop_load_csc_table(struct vop_device *vop_dev, u32 offset, + const uint32_t *table) +{ + uint32_t csc_val; + + csc_val = table[1] << 16 | table[0]; + vop_writel(vop_dev, offset, csc_val); + csc_val = table[3] << 16 | table[2]; + vop_writel(vop_dev, offset + 4, csc_val); + csc_val = table[5] << 16 | table[4]; + vop_writel(vop_dev, offset + 8, csc_val); + csc_val = table[7] << 16 | table[6]; + vop_writel(vop_dev, offset + 0xc, csc_val); + csc_val = table[8]; + vop_writel(vop_dev, offset + 0x10, csc_val); + csc_val = table[9]; + vop_writel(vop_dev, offset + 0x14, csc_val); + csc_val = table[10]; + vop_writel(vop_dev, offset + 0x18, csc_val); + csc_val = table[11]; + vop_writel(vop_dev, offset + 0x1c, csc_val); +} + +static int vop_set_bcsh(struct rk_lcdc_driver *dev_drv, bool enable); + +static int vop_clk_enable(struct vop_device *vop_dev) +{ + if (!vop_dev->clk_on) { + clk_prepare_enable(vop_dev->hclk); + clk_prepare_enable(vop_dev->dclk); + clk_prepare_enable(vop_dev->aclk); + spin_lock(&vop_dev->reg_lock); + vop_dev->clk_on = 1; + spin_unlock(&vop_dev->reg_lock); + } + + return 0; +} + +static int vop_clk_disable(struct vop_device *vop_dev) +{ + if (vop_dev->clk_on) { + spin_lock(&vop_dev->reg_lock); + vop_dev->clk_on = 0; + spin_unlock(&vop_dev->reg_lock); + mdelay(25); + clk_disable_unprepare(vop_dev->dclk); + clk_disable_unprepare(vop_dev->hclk); + clk_disable_unprepare(vop_dev->aclk); + } + + return 0; +} + +static int __maybe_unused vop_disable_irq(struct vop_device *vop_dev) +{ + if (likely(vop_dev->clk_on)) { + spin_lock(&vop_dev->reg_lock); + vop_writel(vop_dev, INTR_EN0, 0); + vop_writel(vop_dev, INTR_EN1, 0); + vop_writel(vop_dev, INTR_CLEAR0, 0xffff); + vop_writel(vop_dev, INTR_CLEAR1, 0xffff); + vop_cfg_done(vop_dev); + spin_unlock(&vop_dev->reg_lock); + }; + + return 0; +} + +static int vop_reg_dump(struct rk_lcdc_driver *dev_drv) +{ + struct vop_device *vop_dev = + container_of(dev_drv, struct vop_device, driver); + int *cbase = (int *)vop_dev->regs; + int *regsbak = (int *)vop_dev->regsbak; + int i, j, val; + char dbg_message[30]; + char buf[10]; + + pr_info("lcd back up reg:\n"); + memset(dbg_message, 0, sizeof(dbg_message)); + memset(buf, 0, sizeof(buf)); + for (i = 0; i <= (0x200 >> 4); i++) { + val = sprintf(dbg_message, "0x%04x: ", i * 16); + for (j = 0; j < 4; j++) { + val = sprintf(buf, "%08x ", *(regsbak + i * 4 + j)); + strcat(dbg_message, buf); + } + pr_info("%s\n", dbg_message); + memset(dbg_message, 0, sizeof(dbg_message)); + memset(buf, 0, sizeof(buf)); + } + + pr_info("lcdc reg:\n"); + for (i = 0; i <= (0x200 >> 4); i++) { + val = sprintf(dbg_message, "0x%04x: ", i * 16); + for (j = 0; j < 4; j++) { + sprintf(buf, "%08x ", + readl_relaxed(cbase + i * 4 + j)); + strcat(dbg_message, buf); + } + pr_info("%s\n", dbg_message); + memset(dbg_message, 0, sizeof(dbg_message)); + memset(buf, 0, sizeof(buf)); + } + + return 0; +} + +#define WIN_EN(id) \ +static int win##id##_enable(struct vop_device *vop_dev, int en) \ +{ \ + spin_lock(&vop_dev->reg_lock); \ + vop_msk_reg(vop_dev, WIN##id##_CTRL0, V_WIN##id##_EN((u64)en)); \ + vop_cfg_done(vop_dev); \ + spin_unlock(&vop_dev->reg_lock); \ + return 0; \ +} + +WIN_EN(0); +WIN_EN(1); + +/*enable/disable win directly*/ +static int vop_win_direct_en(struct rk_lcdc_driver *drv, + int win_id, int en) +{ + struct vop_device *vop_dev = + container_of(drv, struct vop_device, driver); + if (win_id == 0) + win0_enable(vop_dev, en); + else if (win_id == 1) + win1_enable(vop_dev, en); + else + dev_err(vop_dev->dev, "invalid win number:%d\n", win_id); + return 0; +} + +#define SET_WIN_ADDR(id) \ +static int set_win##id##_addr(struct vop_device *vop_dev, u32 addr) \ +{ \ + spin_lock(&vop_dev->reg_lock); \ + vop_writel(vop_dev, WIN##id##_YRGB_MST, addr); \ + vop_msk_reg(vop_dev, WIN##id##_CTRL0, V_WIN##id##_EN(1)); \ + vop_cfg_done(vop_dev); \ + spin_unlock(&vop_dev->reg_lock); \ + return 0; \ +} + +SET_WIN_ADDR(0); +SET_WIN_ADDR(1); +int vop_direct_set_win_addr(struct rk_lcdc_driver *dev_drv, + int win_id, u32 addr) +{ + struct vop_device *vop_dev = + container_of(dev_drv, struct vop_device, driver); + if (win_id == 0) + set_win0_addr(vop_dev, addr); + else + set_win1_addr(vop_dev, addr); + + return 0; +} + +static void lcdc_read_reg_defalut_cfg(struct vop_device *vop_dev) +{ + int reg = 0; + u32 val = 0; + struct rk_screen *screen = vop_dev->driver.cur_screen; + u32 h_pw_bp = screen->mode.hsync_len + screen->mode.left_margin; + u32 V_pw_bp = screen->mode.vsync_len + screen->mode.upper_margin; + u32 st_x, st_y; + struct rk_lcdc_win *win0 = vop_dev->driver.win[0]; + + spin_lock(&vop_dev->reg_lock); + for (reg = 0; reg < vop_dev->len; reg += 4) { + val = vop_readl_backup(vop_dev, reg); + switch (reg) { + case WIN0_ACT_INFO: + win0->area[0].xact = (val & MASK(WIN0_ACT_WIDTH)) + 1; + win0->area[0].yact = + ((val & MASK(WIN0_ACT_HEIGHT)) >> 16) + 1; + break; + case WIN0_DSP_INFO: + win0->area[0].xsize = (val & MASK(WIN0_DSP_WIDTH)) + 1; + win0->area[0].ysize = + ((val & MASK(WIN0_DSP_HEIGHT)) >> 16) + 1; + break; + case WIN0_DSP_ST: + st_x = val & MASK(WIN0_DSP_XST); + st_y = (val & MASK(WIN0_DSP_YST)) >> 16; + win0->area[0].xpos = st_x - h_pw_bp; + win0->area[0].ypos = st_y - V_pw_bp; + break; + case WIN0_CTRL0: + win0->state = val & MASK(WIN0_EN); + win0->area[0].fmt_cfg = + (val & MASK(WIN0_DATA_FMT)) >> 1; + win0->fmt_10 = (val & MASK(WIN0_FMT_10)) >> 4; + win0->area[0].format = win0->area[0].fmt_cfg; + break; + case WIN0_VIR: + win0->area[0].y_vir_stride = + val & MASK(WIN0_VIR_STRIDE); + win0->area[0].uv_vir_stride = + (val & MASK(WIN0_VIR_STRIDE_UV)) >> 16; + if (win0->area[0].format == ARGB888) + win0->area[0].xvir = win0->area[0].y_vir_stride; + else if (win0->area[0].format == RGB888) + win0->area[0].xvir = + win0->area[0].y_vir_stride * 4 / 3; + else if (win0->area[0].format == RGB565) + win0->area[0].xvir = + 2 * win0->area[0].y_vir_stride; + else + win0->area[0].xvir = + 4 * win0->area[0].y_vir_stride; + break; + case WIN0_YRGB_MST: + win0->area[0].smem_start = val; + break; + case WIN0_CBR_MST: + win0->area[0].cbr_start = val; + break; + default: + break; + } + } + spin_unlock(&vop_dev->reg_lock); +} + +/********do basic init*********/ +static int vop_pre_init(struct rk_lcdc_driver *dev_drv) +{ + struct vop_device *vop_dev = + container_of(dev_drv, struct vop_device, driver); + if (vop_dev->pre_init) + return 0; + + vop_dev->hclk = devm_clk_get(vop_dev->dev, "hclk_lcdc"); + vop_dev->aclk = devm_clk_get(vop_dev->dev, "aclk_lcdc"); + vop_dev->dclk = devm_clk_get(vop_dev->dev, "dclk_lcdc"); + + if ((IS_ERR(vop_dev->aclk)) || (IS_ERR(vop_dev->dclk)) || + (IS_ERR(vop_dev->hclk))) { + dev_err(vop_dev->dev, "failed to get lcdc%d clk source\n", + vop_dev->id); + } + if (!support_uboot_display()) + rk_disp_pwr_enable(dev_drv); + vop_clk_enable(vop_dev); + + memcpy(vop_dev->regsbak, vop_dev->regs, vop_dev->len); + /*backup reg config at uboot */ + lcdc_read_reg_defalut_cfg(vop_dev); + #ifndef CONFIG_RK_FPGA + /* + * Todo, not verified + * + if (vop_dev->pwr18 == 1) { + v = 0x00200020; + vop_grf_writel(vop_dev->pmugrf_base, + PMUGRF_SOC_CON0_VOP, v); + } else { + v = 0x00200000; + vop_grf_writel(vop_dev->pmugrf_base, + PMUGRF_SOC_CON0_VOP, v); + } + */ + #endif + vop_writel(vop_dev, FRC_LOWER01_0, 0x12844821); + vop_writel(vop_dev, FRC_LOWER01_1, 0x21488412); + vop_writel(vop_dev, FRC_LOWER10_0, 0xa55a9696); + vop_writel(vop_dev, FRC_LOWER10_1, 0x5aa56969); + vop_writel(vop_dev, FRC_LOWER11_0, 0xdeb77deb); + vop_writel(vop_dev, FRC_LOWER11_1, 0xed7bb7de); + + vop_msk_reg(vop_dev, SYS_CTRL, V_AUTO_GATING_EN(0)); + vop_msk_reg(vop_dev, DSP_CTRL1, V_DITHER_UP_EN(1)); + vop_cfg_done(vop_dev); + vop_dev->pre_init = true; + + return 0; +} + +static void vop_deint(struct vop_device *vop_dev) +{ + if (vop_dev->clk_on) { + vop_disable_irq(vop_dev); + spin_lock(&vop_dev->reg_lock); + vop_msk_reg(vop_dev, WIN0_CTRL0, V_WIN0_EN(0)); + vop_msk_reg(vop_dev, WIN1_CTRL0, V_WIN0_EN(0)); + + vop_cfg_done(vop_dev); + spin_unlock(&vop_dev->reg_lock); + } +} + + +static void vop_win_csc_mode(struct vop_device *vop_dev, + struct rk_lcdc_win *win, + int csc_mode) +{ + u64 val; + + if (win->id == 0) { + val = V_WIN0_CSC_MODE(csc_mode); + vop_msk_reg(vop_dev, WIN0_CTRL0, val); + } else if (win->id == 1) { + val = V_WIN1_CSC_MODE(csc_mode); + vop_msk_reg(vop_dev, WIN1_CTRL0, val); + } else { + val = V_HWC_CSC_MODE(csc_mode); + vop_msk_reg(vop_dev, HWC_CTRL0, val); + } +} + +/* + * colorspace path: + * Input Win csc Post csc Output + * 1. YUV(2020) --> bypass ---+ Y2R->2020To709->R2Y --> YUV_OUTPUT(601/709) + * RGB --> R2Y(709) __/ + * + * 2. YUV(2020) --> bypass ---+ bypass --> YUV_OUTPUT(2020) + * RGB --> R2Y(709) __/ + * + * 3. YUV(2020) --> bypass ---+ Y2R->2020To709 --> RGB_OUTPUT(709) + * RGB --> R2Y(709) __/ + * + * 4. YUV(601/709)-> bypass ---+ Y2R->709To2020->R2Y --> YUV_OUTPUT(2020) + * RGB --> R2Y(709) __/ + * + * 5. YUV(601/709)-> bypass ---+ bypass --> YUV_OUTPUT(709) + * RGB --> R2Y(709) __/ + * + * 6. YUV(601/709)-> bypass ---+ bypass --> YUV_OUTPUT(601) + * RGB --> R2Y(601) __/ + * + * 7. YUV(601/709)-> Y2R(mpeg)---+ bypass --> RGB_OUTPUT(709) + * RGB --> bypass __/ + * + * 8. RGB --> bypass ---> 709To2020->R2Y --> YUV_OUTPUT(2020) + * + * 9. RGB --> R2Y(709) ---> Y2R --> YUV_OUTPUT(709) + * + * 10. RGB --> R2Y(601) ---> Y2R --> YUV_OUTPUT(601) + * + * 11. RGB --> bypass ---> bypass --> RGB_OUTPUT(709) + */ + +static void vop_post_csc_cfg(struct rk_lcdc_driver *dev_drv) +{ + struct vop_device *vop_dev = + container_of(dev_drv, struct vop_device, driver); + struct rk_lcdc_win *win; + int output_color = dev_drv->output_color; + int i, r2y_mode; + int overlay_mode; + int win_csc = COLOR_RGB; + u64 val; + + if (output_color == COLOR_RGB) + overlay_mode = VOP_RGB_DOMAIN; + else + overlay_mode = VOP_YUV_DOMAIN; + + if (output_color == COLOR_YCBCR) + r2y_mode = VOP_R2Y_CSC_BT601; + else + r2y_mode = VOP_R2Y_CSC_BT709; + + for (i = 0; i < dev_drv->lcdc_win_num; i++) { + win = dev_drv->win[i]; + if (!win->state) + continue; + /* + * force use yuv domain when there is a windows's csc is bt2020. + */ + if (win->colorspace == CSC_BT2020) { + overlay_mode = VOP_YUV_DOMAIN; + r2y_mode = VOP_R2Y_CSC_BT709; + win_csc = COLOR_YCBCR_BT2020; + break; + } + if (IS_YUV(win->area[0].fmt_cfg)) + win_csc = COLOR_YCBCR; + } + + for (i = 0; i < dev_drv->lcdc_win_num; i++) { + win = dev_drv->win[i]; + if (!win->state) + continue; + if (overlay_mode == VOP_YUV_DOMAIN && + !IS_YUV(win->area[0].fmt_cfg)) + vop_win_csc_mode(vop_dev, win, r2y_mode); + else if (IS_YUV(win->area[0].fmt_cfg)) + vop_win_csc_mode(vop_dev, win, VOP_Y2R_CSC_MPEG); + } + + val = 0; + /* Y2R */ + if ((win_csc == COLOR_YCBCR && output_color == COLOR_RGB) || + (win_csc == COLOR_YCBCR && output_color == COLOR_YCBCR_BT2020)) { + val |= V_YUV2YUV_POST_Y2R_EN(1); + vop_load_csc_table(vop_dev, POST_YUV2YUV_Y2R_COE, + csc_y2r_bt709_full); + } + if (win_csc == COLOR_YCBCR_BT2020 && + output_color != COLOR_YCBCR_BT2020) { + val |= V_YUV2YUV_POST_Y2R_EN(1); + vop_load_csc_table(vop_dev, POST_YUV2YUV_Y2R_COE, + csc_y2r_bt2020); + } + + /* R2R */ + if ((win_csc == COLOR_YCBCR || + win_csc == COLOR_YCBCR_BT709 || + win_csc == COLOR_RGB) && output_color == COLOR_YCBCR_BT2020) { + val |= V_YUV2YUV_POST_EN(1); + vop_load_csc_table(vop_dev, POST_YUV2YUV_3x3_COE, + csc_r2r_bt709to2020); + } + if (win_csc == COLOR_YCBCR_BT2020 && + (output_color == COLOR_YCBCR || + output_color == COLOR_YCBCR_BT709 || + output_color == COLOR_RGB)) { + val |= V_YUV2YUV_POST_EN(1); + vop_load_csc_table(vop_dev, POST_YUV2YUV_3x3_COE, + csc_r2r_bt2020to709); + } + + /* Y2R */ + if (output_color != COLOR_RGB) { + val |= V_YUV2YUV_POST_R2Y_EN(1); + + if (output_color == COLOR_YCBCR_BT2020) + vop_load_csc_table(vop_dev, POST_YUV2YUV_R2Y_COE, + csc_r2y_bt2020); + else + vop_load_csc_table(vop_dev, POST_YUV2YUV_R2Y_COE, + csc_r2y_bt709_full); + } + + vop_msk_reg(vop_dev, YUV2YUV_POST, val); +} + +static int vop_post_cfg(struct rk_lcdc_driver *dev_drv) +{ + struct vop_device *vop_dev = + container_of(dev_drv, struct vop_device, driver); + struct rk_screen *screen = dev_drv->cur_screen; + u16 x_res = screen->mode.xres; + u16 y_res = screen->mode.yres; + u64 val; + u16 h_total, v_total; + u16 post_hsd_en, post_vsd_en; + u16 post_dsp_hact_st, post_dsp_hact_end; + u16 post_dsp_vact_st, post_dsp_vact_end; + 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 + + y_res + screen->mode.lower_margin; + + if (screen->post_dsp_stx + screen->post_xsize > x_res) { + dev_warn(vop_dev->dev, "post:stx[%d]+xsize[%d]>x_res[%d]\n", + screen->post_dsp_stx, screen->post_xsize, x_res); + screen->post_dsp_stx = x_res - screen->post_xsize; + } + if (screen->x_mirror == 0) { + post_dsp_hact_st = screen->post_dsp_stx + + screen->mode.hsync_len + screen->mode.left_margin; + post_dsp_hact_end = post_dsp_hact_st + screen->post_xsize; + } else { + post_dsp_hact_end = h_total - screen->mode.right_margin - + screen->post_dsp_stx; + post_dsp_hact_st = post_dsp_hact_end - screen->post_xsize; + } + if ((screen->post_xsize < x_res) && (screen->post_xsize != 0)) { + post_hsd_en = 1; + post_h_fac = + GET_SCALE_FACTOR_BILI_DN(x_res, screen->post_xsize); + } else { + post_hsd_en = 0; + post_h_fac = 0x1000; + } + + if (screen->post_dsp_sty + screen->post_ysize > y_res) { + dev_warn(vop_dev->dev, "post:sty[%d]+ysize[%d]> y_res[%d]\n", + screen->post_dsp_sty, screen->post_ysize, y_res); + screen->post_dsp_sty = y_res - 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, + screen->post_ysize); + } else { + post_vsd_en = 0; + post_v_fac = 0x1000; + } + + 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; + } + DBG(1, "post:xsize=%d,ysize=%d,xpos=%d", + screen->post_xsize, screen->post_ysize, screen->xpos); + DBG(1, ",ypos=%d,hsd_en=%d,h_fac=%d,vsd_en=%d,v_fac=%d\n", + screen->ypos, post_hsd_en, post_h_fac, post_vsd_en, post_v_fac); + val = V_DSP_HACT_END_POST(post_dsp_hact_end) | + V_DSP_HACT_ST_POST(post_dsp_hact_st); + vop_msk_reg(vop_dev, POST_DSP_HACT_INFO, val); + + val = V_DSP_VACT_END_POST(post_dsp_vact_end) | + V_DSP_VACT_ST_POST(post_dsp_vact_st); + vop_msk_reg(vop_dev, POST_DSP_VACT_INFO, val); + + val = V_POST_HS_FACTOR_YRGB(post_h_fac) | + V_POST_VS_FACTOR_YRGB(post_v_fac); + vop_msk_reg(vop_dev, POST_SCL_FACTOR_YRGB, val); + val = V_DSP_VACT_END_POST(post_dsp_vact_end_f1) | + V_DSP_VACT_ST_POST(post_dsp_vact_st_f1); + vop_msk_reg(vop_dev, POST_DSP_VACT_INFO_F1, val); + val = V_POST_HOR_SD_EN(post_hsd_en) | V_POST_VER_SD_EN(post_vsd_en); + vop_msk_reg(vop_dev, POST_SCL_CTRL, val); + + vop_post_csc_cfg(dev_drv); + + return 0; +} + +static int vop_clr_key_cfg(struct rk_lcdc_driver *dev_drv) +{ + struct vop_device *vop_dev = + container_of(dev_drv, struct vop_device, driver); + struct rk_lcdc_win *win; + u32 colorkey_r, colorkey_g, colorkey_b; + int i, key_val; + + for (i = 0; i < dev_drv->lcdc_win_num; i++) { + win = dev_drv->win[i]; + key_val = win->color_key_val; + colorkey_r = (key_val & 0xff) << 2; + colorkey_g = ((key_val >> 8) & 0xff) << 12; + colorkey_b = ((key_val >> 16) & 0xff) << 22; + /* color key dither 565/888->aaa */ + key_val = colorkey_r | colorkey_g | colorkey_b; + switch (i) { + case 0: + vop_writel(vop_dev, WIN0_COLOR_KEY, key_val); + break; + case 1: + vop_writel(vop_dev, WIN1_COLOR_KEY, key_val); + break; + default: + pr_info("%s:un support win num:%d\n", + __func__, i); + break; + } + } + return 0; +} + +static int vop_alpha_cfg(struct rk_lcdc_driver *dev_drv, int win_id) +{ + struct vop_device *vop_dev = + container_of(dev_drv, struct vop_device, driver); + struct rk_lcdc_win *win = dev_drv->win[win_id]; + struct alpha_config alpha_config; + u64 val; + int ppixel_alpha = 0, global_alpha = 0, i; + u32 src_alpha_ctl, dst_alpha_ctl; + + 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; + alpha_config.src_global_alpha_val = win->g_alpha_val; + win->alpha_mode = AB_SRC_OVER; + + switch (win->alpha_mode) { + case AB_USER_DEFINE: + break; + case AB_CLEAR: + alpha_config.src_factor_mode = AA_ZERO; + alpha_config.dst_factor_mode = AA_ZERO; + break; + case AB_SRC: + alpha_config.src_factor_mode = AA_ONE; + alpha_config.dst_factor_mode = AA_ZERO; + break; + case AB_DST: + alpha_config.src_factor_mode = AA_ZERO; + alpha_config.dst_factor_mode = AA_ONE; + break; + case AB_SRC_OVER: + alpha_config.src_color_mode = AA_SRC_PRE_MUL; + if (global_alpha) + alpha_config.src_factor_mode = AA_SRC_GLOBAL; + else + alpha_config.src_factor_mode = AA_ONE; + alpha_config.dst_factor_mode = AA_SRC_INVERSE; + break; + case AB_DST_OVER: + alpha_config.src_color_mode = AA_SRC_PRE_MUL; + alpha_config.src_factor_mode = AA_SRC_INVERSE; + alpha_config.dst_factor_mode = AA_ONE; + break; + case AB_SRC_IN: + alpha_config.src_color_mode = AA_SRC_PRE_MUL; + alpha_config.src_factor_mode = AA_SRC; + alpha_config.dst_factor_mode = AA_ZERO; + break; + case AB_DST_IN: + alpha_config.src_factor_mode = AA_ZERO; + alpha_config.dst_factor_mode = AA_SRC; + break; + case AB_SRC_OUT: + alpha_config.src_color_mode = AA_SRC_PRE_MUL; + alpha_config.src_factor_mode = AA_SRC_INVERSE; + alpha_config.dst_factor_mode = AA_ZERO; + break; + case AB_DST_OUT: + alpha_config.src_factor_mode = AA_ZERO; + alpha_config.dst_factor_mode = AA_SRC_INVERSE; + break; + case AB_SRC_ATOP: + alpha_config.src_color_mode = AA_SRC_PRE_MUL; + alpha_config.src_factor_mode = AA_SRC; + alpha_config.dst_factor_mode = AA_SRC_INVERSE; + break; + case AB_DST_ATOP: + alpha_config.src_color_mode = AA_SRC_PRE_MUL; + alpha_config.src_factor_mode = AA_SRC_INVERSE; + alpha_config.dst_factor_mode = AA_SRC; + break; + case XOR: + alpha_config.src_color_mode = AA_SRC_PRE_MUL; + alpha_config.src_factor_mode = AA_SRC_INVERSE; + alpha_config.dst_factor_mode = AA_SRC_INVERSE; + break; + case AB_SRC_OVER_GLOBAL: + alpha_config.src_global_alpha_mode = AA_PER_PIX_GLOBAL; + alpha_config.src_color_mode = AA_SRC_NO_PRE_MUL; + alpha_config.src_factor_mode = AA_SRC_GLOBAL; + alpha_config.dst_factor_mode = AA_SRC_INVERSE; + break; + default: + pr_err("alpha mode error\n"); + break; + } + if ((ppixel_alpha == 1) && (global_alpha == 1)) + alpha_config.src_global_alpha_mode = AA_PER_PIX_GLOBAL; + else if (ppixel_alpha == 1) + alpha_config.src_global_alpha_mode = AA_PER_PIX; + else if (global_alpha == 1) + alpha_config.src_global_alpha_mode = AA_GLOBAL; + alpha_config.src_alpha_mode = AA_STRAIGHT; + alpha_config.src_alpha_cal_m0 = AA_NO_SAT; + + switch (win_id) { + case 0: + src_alpha_ctl = 0x60; + dst_alpha_ctl = 0x64; + break; + case 1: + src_alpha_ctl = 0xa0; + dst_alpha_ctl = 0xa4; + break; + case 2: + src_alpha_ctl = 0x160; + dst_alpha_ctl = 0x164; + break; + } + val = V_WIN0_DST_FACTOR_MODE(alpha_config.dst_factor_mode); + vop_msk_reg(vop_dev, dst_alpha_ctl, val); + val = V_WIN0_SRC_ALPHA_EN(1) | + V_WIN0_SRC_COLOR_MODE(alpha_config.src_color_mode) | + V_WIN0_SRC_ALPHA_MODE(alpha_config.src_alpha_mode) | + V_WIN0_SRC_BLEND_MODE(alpha_config.src_global_alpha_mode) | + V_WIN0_SRC_ALPHA_CAL_MODE(alpha_config.src_alpha_cal_m0) | + V_WIN0_SRC_FACTOR_MODE(alpha_config.src_factor_mode) | + V_WIN0_SRC_GLOBAL_ALPHA(alpha_config.src_global_alpha_val); + + vop_msk_reg(vop_dev, src_alpha_ctl, val); + + return 0; +} + +static int vop_axi_gather_cfg(struct vop_device *vop_dev, + struct rk_lcdc_win *win) +{ + u64 val; + u16 yrgb_gather_num = 3; + u16 cbcr_gather_num = 1; + + switch (win->area[0].format) { + case ARGB888: + case XBGR888: + case ABGR888: + yrgb_gather_num = 3; + break; + case RGB888: + case RGB565: + yrgb_gather_num = 2; + break; + case YUV444: + case YUV422: + case YUV420: + case YUV420_NV21: + yrgb_gather_num = 1; + cbcr_gather_num = 2; + break; + default: + dev_err(vop_dev->driver.dev, "%s:un supported format!\n", + __func__); + return -EINVAL; + } + + if ((win->id == 0) || (win->id == 1)) { + val = V_WIN0_YRGB_AXI_GATHER_EN(1) | + V_WIN0_CBR_AXI_GATHER_EN(1) | + V_WIN0_YRGB_AXI_GATHER_NUM(yrgb_gather_num) | + V_WIN0_CBR_AXI_GATHER_NUM(cbcr_gather_num); + vop_msk_reg(vop_dev, WIN0_CTRL1 + (win->id * 0x40), val); + } else if (win->id == 2) { + val = V_HWC_AXI_GATHER_EN(1) | + V_HWC_AXI_GATHER_NUM(yrgb_gather_num); + vop_msk_reg(vop_dev, HWC_CTRL1, val); + } + return 0; +} + +static int vop_win_0_1_reg_update(struct rk_lcdc_driver *dev_drv, int win_id) +{ + struct vop_device *vop_dev = + container_of(dev_drv, struct vop_device, driver); + struct rk_lcdc_win *win = dev_drv->win[win_id]; + u64 val; + uint32_t off; + + off = win_id * 0x40; + + if (win->state == 1) { + vop_axi_gather_cfg(vop_dev, win); + val = V_WIN0_EN(win->state) | + V_WIN0_DATA_FMT(win->area[0].fmt_cfg) | + V_WIN0_FMT_10(win->fmt_10) | + V_WIN0_LB_MODE(win->win_lb_mode) | + V_WIN0_RB_SWAP(win->area[0].swap_rb) | + V_WIN0_X_MIR_EN(win->mirror_en) | + V_WIN0_Y_MIR_EN(win->mirror_en) | + V_WIN0_UV_SWAP(win->area[0].swap_uv); + vop_msk_reg(vop_dev, WIN0_CTRL0 + off, val); + val = V_WIN0_BIC_COE_SEL(win->bic_coe_el) | + V_WIN0_VSD_YRGB_GT4(win->vsd_yrgb_gt4) | + V_WIN0_VSD_YRGB_GT2(win->vsd_yrgb_gt2) | + V_WIN0_VSD_CBR_GT4(win->vsd_cbr_gt4) | + V_WIN0_VSD_CBR_GT2(win->vsd_cbr_gt2) | + V_WIN0_YRGB_HOR_SCL_MODE(win->yrgb_hor_scl_mode) | + V_WIN0_YRGB_VER_SCL_MODE(win->yrgb_ver_scl_mode) | + V_WIN0_YRGB_HSD_MODE(win->yrgb_hsd_mode) | + V_WIN0_YRGB_VSU_MODE(win->yrgb_vsu_mode) | + V_WIN0_YRGB_VSD_MODE(win->yrgb_vsd_mode) | + V_WIN0_CBR_HOR_SCL_MODE(win->cbr_hor_scl_mode) | + V_WIN0_CBR_VER_SCL_MODE(win->cbr_ver_scl_mode) | + V_WIN0_CBR_HSD_MODE(win->cbr_hsd_mode) | + V_WIN0_CBR_VSU_MODE(win->cbr_vsu_mode) | + V_WIN0_CBR_VSD_MODE(win->cbr_vsd_mode); + vop_msk_reg(vop_dev, WIN0_CTRL1 + off, val); + val = V_WIN0_VIR_STRIDE(win->area[0].y_vir_stride) | + V_WIN0_VIR_STRIDE_UV(win->area[0].uv_vir_stride); + vop_writel(vop_dev, WIN0_VIR + off, val); + val = V_WIN0_ACT_WIDTH(win->area[0].xact - 1) | + V_WIN0_ACT_HEIGHT(win->area[0].yact - 1); + vop_writel(vop_dev, WIN0_ACT_INFO + off, val); + + val = V_WIN0_DSP_WIDTH(win->area[0].xsize - 1) | + V_WIN0_DSP_HEIGHT(win->area[0].ysize - 1); + vop_writel(vop_dev, WIN0_DSP_INFO + off, val); + + val = V_WIN0_DSP_XST(win->area[0].dsp_stx) | + V_WIN0_DSP_YST(win->area[0].dsp_sty); + vop_writel(vop_dev, WIN0_DSP_ST + off, val); + + val = V_WIN0_HS_FACTOR_YRGB(win->scale_yrgb_x) | + V_WIN0_VS_FACTOR_YRGB(win->scale_yrgb_y); + vop_writel(vop_dev, WIN0_SCL_FACTOR_YRGB + off, val); + + val = V_WIN0_HS_FACTOR_CBR(win->scale_cbcr_x) | + V_WIN0_VS_FACTOR_CBR(win->scale_cbcr_y); + vop_writel(vop_dev, WIN0_SCL_FACTOR_CBR + off, val); + if (win->alpha_en == 1) { + vop_alpha_cfg(dev_drv, win_id); + } else { + val = V_WIN0_SRC_ALPHA_EN(0); + vop_msk_reg(vop_dev, WIN0_SRC_ALPHA_CTRL + off, val); + } + + if (dev_drv->cur_screen->mode.vmode == FB_VMODE_INTERLACED) { + if (win->area[0].yact == 2 * win->area[0].ysize) + val = V_WIN0_YRGB_DEFLICK(0) | + V_WIN0_CBR_DEFLICK(0); + else + val = V_WIN0_YRGB_DEFLICK(1) | + V_WIN0_CBR_DEFLICK(1); + vop_msk_reg(vop_dev, WIN0_CTRL0, val); + } + } else { + val = V_WIN0_EN(win->state); + vop_msk_reg(vop_dev, WIN0_CTRL0 + off, val); + } + + return 0; +} + +static int vop_hwc_reg_update(struct rk_lcdc_driver *dev_drv, int win_id) +{ + struct vop_device *vop_dev = + container_of(dev_drv, struct vop_device, driver); + struct rk_lcdc_win *win = dev_drv->win[win_id]; + unsigned int hwc_size = 0; + u64 val; + + if (win->state == 1) { + vop_axi_gather_cfg(vop_dev, win); + val = V_HWC_EN(1) | V_HWC_DATA_FMT(win->area[0].fmt_cfg) | + V_HWC_RB_SWAP(win->area[0].swap_rb); + vop_msk_reg(vop_dev, HWC_CTRL0, val); + + if ((win->area[0].xsize == 32) && (win->area[0].ysize == 32)) + hwc_size = 0; + else if ((win->area[0].xsize == 64) && + (win->area[0].ysize == 64)) + hwc_size = 1; + else if ((win->area[0].xsize == 96) && + (win->area[0].ysize == 96)) + hwc_size = 2; + else if ((win->area[0].xsize == 128) && + (win->area[0].ysize == 128)) + hwc_size = 3; + else + dev_err(vop_dev->dev, "un supported hwc size!\n"); + + val = V_HWC_SIZE(hwc_size); + vop_msk_reg(vop_dev, HWC_CTRL0, val); + + val = V_HWC_DSP_XST(win->area[0].dsp_stx) | + V_HWC_DSP_YST(win->area[0].dsp_sty); + vop_msk_reg(vop_dev, HWC_DSP_ST, val); + + if (win->alpha_en == 1) { + vop_alpha_cfg(dev_drv, win_id); + } else { + val = V_WIN2_SRC_ALPHA_EN(0); + vop_msk_reg(vop_dev, HWC_SRC_ALPHA_CTRL, val); + } + } else { + val = V_HWC_EN(win->state); + vop_msk_reg(vop_dev, HWC_CTRL0, val); + } + + return 0; +} + +static int vop_layer_update_regs(struct vop_device *vop_dev, + struct rk_lcdc_win *win) +{ + struct rk_lcdc_driver *dev_drv = &vop_dev->driver; + + if (likely(vop_dev->clk_on)) { + vop_msk_reg(vop_dev, SYS_CTRL, + V_VOP_STANDBY_EN(vop_dev->standby)); + if ((win->id == 0) || (win->id == 1)) + vop_win_0_1_reg_update(dev_drv, win->id); + else if (win->id == 2) + vop_hwc_reg_update(dev_drv, win->id); + vop_cfg_done(vop_dev); + } + + DBG(2, "%s for lcdc%d\n", __func__, vop_dev->id); + return 0; +} + +static int __maybe_unused vop_mmu_en(struct rk_lcdc_driver *dev_drv) +{ + u64 val; + struct vop_device *vop_dev = + container_of(dev_drv, struct vop_device, driver); + + if (unlikely(!vop_dev->clk_on)) { + pr_info("%s,clk_on = %d\n", __func__, vop_dev->clk_on); + return 0; + } +#if defined(CONFIG_ROCKCHIP_IOMMU) + if (dev_drv->iommu_enabled) { + if (!vop_dev->iommu_status && dev_drv->mmu_dev) { + if (likely(vop_dev->clk_on)) { + val = V_VOP_MMU_EN(1); + vop_msk_reg(vop_dev, SYS_CTRL, val); + val = V_AXI_OUTSTANDING_MAX_NUM(31) | + V_AXI_MAX_OUTSTANDING_EN(1); + vop_msk_reg(vop_dev, SYS_CTRL1, val); + } + vop_dev->iommu_status = 1; + rockchip_iovmm_activate(dev_drv->dev); + } + } +#endif + return 0; +} + +static int vop_set_dclk(struct rk_lcdc_driver *dev_drv, int reset_rate) +{ + int ret = 0, fps = 0; + struct vop_device *vop_dev = + container_of(dev_drv, struct vop_device, driver); + struct rk_screen *screen = dev_drv->cur_screen; +#ifdef CONFIG_RK_FPGA + return 0; +#endif + if (reset_rate) + ret = clk_set_rate(vop_dev->dclk, screen->mode.pixclock); + if (ret) + dev_err(dev_drv->dev, "set lcdc%d dclk failed\n", vop_dev->id); + vop_dev->pixclock = + div_u64(1000000000000llu, clk_get_rate(vop_dev->dclk)); + vop_dev->driver.pixclock = vop_dev->pixclock; + + fps = rk_fb_calc_fps(screen, vop_dev->pixclock); + screen->ft = 1000 / fps; + dev_info(vop_dev->dev, "%s: dclk:%lu>>fps:%d ", + vop_dev->driver.name, clk_get_rate(vop_dev->dclk), fps); + return 0; +} + +static int vop_config_timing(struct rk_lcdc_driver *dev_drv) +{ + struct vop_device *vop_dev = + container_of(dev_drv, struct vop_device, driver); + struct rk_screen *screen = dev_drv->cur_screen; + u16 hsync_len = screen->mode.hsync_len; + u16 left_margin = screen->mode.left_margin; + u16 right_margin = screen->mode.right_margin; + u16 vsync_len = screen->mode.vsync_len; + u16 upper_margin = screen->mode.upper_margin; + u16 lower_margin = screen->mode.lower_margin; + u16 x_res = screen->mode.xres; + u16 y_res = screen->mode.yres; + u64 val; + u16 h_total, v_total; + u16 vact_end_f1, vact_st_f1, vs_end_f1, vs_st_f1; + + h_total = hsync_len + left_margin + x_res + right_margin; + v_total = vsync_len + upper_margin + y_res + lower_margin; + + val = V_DSP_HS_END(hsync_len) | V_DSP_HTOTAL(h_total); + vop_msk_reg(vop_dev, DSP_HTOTAL_HS_END, val); + + val = V_DSP_HACT_END(hsync_len + left_margin + x_res) | + V_DSP_HACT_ST(hsync_len + left_margin); + vop_msk_reg(vop_dev, DSP_HACT_ST_END, val); + + if (screen->mode.vmode == FB_VMODE_INTERLACED) { + /* First Field Timing */ + val = V_DSP_VS_END(vsync_len) | + V_DSP_VTOTAL(2 * (vsync_len + upper_margin + + lower_margin) + y_res + 1); + vop_msk_reg(vop_dev, DSP_VTOTAL_VS_END, val); + + val = V_DSP_VACT_END(vsync_len + upper_margin + y_res / 2) | + V_DSP_VACT_ST(vsync_len + upper_margin); + vop_msk_reg(vop_dev, DSP_VACT_ST_END, val); + + /* Second Field Timing */ + vs_st_f1 = vsync_len + upper_margin + y_res / 2 + lower_margin; + vs_end_f1 = 2 * vsync_len + upper_margin + y_res / 2 + + lower_margin; + val = V_DSP_VS_ST_F1(vs_st_f1) | V_DSP_VS_END_F1(vs_end_f1); + vop_msk_reg(vop_dev, DSP_VS_ST_END_F1, val); + + vact_end_f1 = 2 * (vsync_len + upper_margin) + y_res + + lower_margin + 1; + vact_st_f1 = 2 * (vsync_len + upper_margin) + y_res / 2 + + lower_margin + 1; + val = V_DSP_VACT_END_F1(vact_end_f1) | + V_DSP_VACT_ST_F1(vact_st_f1); + vop_msk_reg(vop_dev, DSP_VACT_ST_END_F1, val); + vop_msk_reg(vop_dev, DSP_CTRL0, + V_DSP_INTERLACE(1) | V_DSP_FIELD_POL(0)); + val = V_WIN0_INTERLACE_READ(1) | V_WIN0_YRGB_DEFLICK(0) | + V_WIN0_CBR_DEFLICK(0); + vop_msk_reg(vop_dev, WIN0_CTRL0, val); + + val = V_WIN1_INTERLACE_READ(1) | V_WIN1_YRGB_DEFLICK(0) | + V_WIN1_CBR_DEFLICK(0); + vop_msk_reg(vop_dev, WIN1_CTRL0, val); + + val = V_WIN2_INTERLACE_READ(1); + vop_msk_reg(vop_dev, WIN2_CTRL0, val); + + val = V_WIN3_INTERLACE_READ(1); + vop_msk_reg(vop_dev, WIN3_CTRL0, val); + + val = V_HWC_INTERLACE_READ(1); + vop_msk_reg(vop_dev, HWC_CTRL0, val); + + val = V_DSP_LINE_FLAG_NUM_0(vact_end_f1) | + V_DSP_LINE_FLAG_NUM_1(vact_end_f1); + vop_msk_reg(vop_dev, LINE_FLAG, val); + } else { + val = V_DSP_VS_END(vsync_len) | V_DSP_VTOTAL(v_total); + vop_msk_reg(vop_dev, DSP_VTOTAL_VS_END, val); + + val = V_DSP_VACT_END(vsync_len + upper_margin + y_res) | + V_DSP_VACT_ST(vsync_len + upper_margin); + vop_msk_reg(vop_dev, DSP_VACT_ST_END, val); + + vop_msk_reg(vop_dev, DSP_CTRL0, V_DSP_INTERLACE(0) | + V_DSP_FIELD_POL(0)); + + val = V_WIN0_INTERLACE_READ(0) | V_WIN0_YRGB_DEFLICK(0) | + V_WIN0_CBR_DEFLICK(0); + vop_msk_reg(vop_dev, WIN0_CTRL0, val); + + val = V_WIN1_INTERLACE_READ(0) | V_WIN1_YRGB_DEFLICK(0) | + V_WIN1_CBR_DEFLICK(0); + vop_msk_reg(vop_dev, WIN1_CTRL0, val); + + val = V_WIN2_INTERLACE_READ(0); + vop_msk_reg(vop_dev, WIN2_CTRL0, val); + + val = V_WIN3_INTERLACE_READ(0); + vop_msk_reg(vop_dev, WIN3_CTRL0, val); + + val = V_HWC_INTERLACE_READ(0); + vop_msk_reg(vop_dev, HWC_CTRL0, val); + + val = V_DSP_LINE_FLAG_NUM_0(vsync_len + upper_margin + y_res) | + V_DSP_LINE_FLAG_NUM_1(vsync_len + upper_margin + y_res); + vop_msk_reg(vop_dev, LINE_FLAG, val); + } + vop_post_cfg(dev_drv); + + return 0; +} + +static void vop_bcsh_path_sel(struct rk_lcdc_driver *dev_drv) +{ + struct vop_device *vop_dev = + container_of(dev_drv, struct vop_device, driver); + u32 bcsh_ctrl; + + vop_msk_reg(vop_dev, SYS_CTRL, V_OVERLAY_MODE(dev_drv->overlay_mode)); + if (dev_drv->overlay_mode == VOP_YUV_DOMAIN) { + if (dev_drv->output_color == COLOR_YCBCR) /* bypass */ + vop_msk_reg(vop_dev, BCSH_CTRL, + V_BCSH_Y2R_EN(0) | V_BCSH_R2Y_EN(0)); + else /* YUV2RGB */ + vop_msk_reg(vop_dev, BCSH_CTRL, V_BCSH_Y2R_EN(1) | + V_BCSH_Y2R_CSC_MODE(VOP_Y2R_CSC_MPEG) | + V_BCSH_R2Y_EN(0)); + } else { + /* overlay_mode=VOP_RGB_DOMAIN */ + /* bypass --need check,if bcsh close? */ + if (dev_drv->output_color == COLOR_RGB) { + bcsh_ctrl = vop_readl(vop_dev, BCSH_CTRL); + if (((bcsh_ctrl & MASK(BCSH_EN)) == 1) || + (dev_drv->bcsh.enable == 1))/*bcsh enabled */ + vop_msk_reg(vop_dev, BCSH_CTRL, + V_BCSH_R2Y_EN(1) | + V_BCSH_Y2R_EN(1)); + else + vop_msk_reg(vop_dev, BCSH_CTRL, + V_BCSH_R2Y_EN(0) | + V_BCSH_Y2R_EN(0)); + } else { + /* RGB2YUV */ + vop_msk_reg(vop_dev, BCSH_CTRL, + V_BCSH_R2Y_EN(1) | + V_BCSH_R2Y_CSC_MODE(VOP_Y2R_CSC_MPEG) | + V_BCSH_Y2R_EN(0)); + } + } +} + +static int vop_get_dspbuf_info(struct rk_lcdc_driver *dev_drv, u16 *xact, + u16 *yact, int *format, u32 *dsp_addr) +{ + struct vop_device *vop_dev = + container_of(dev_drv, struct vop_device, driver); + u32 val; + + spin_lock(&vop_dev->reg_lock); + + val = vop_readl(vop_dev, WIN0_ACT_INFO); + *xact = (val & MASK(WIN0_ACT_WIDTH)) + 1; + *yact = ((val & MASK(WIN0_ACT_HEIGHT))>>16) + 1; + + val = vop_readl(vop_dev, WIN0_CTRL0); + *format = (val & MASK(WIN0_DATA_FMT)) >> 1; + *dsp_addr = vop_readl(vop_dev, WIN0_YRGB_MST); + + spin_unlock(&vop_dev->reg_lock); + + return 0; +} + +static int vop_post_dspbuf(struct rk_lcdc_driver *dev_drv, u32 rgb_mst, + int format, u16 xact, u16 yact, u16 xvir) +{ + struct vop_device *vop_dev = + container_of(dev_drv, struct vop_device, driver); + int swap = (format == RGB888) ? 1 : 0; + u64 val; + + val = V_WIN0_DATA_FMT(format) | V_WIN0_RB_SWAP(swap); + vop_msk_reg(vop_dev, WIN0_CTRL0, val); + + vop_msk_reg(vop_dev, WIN0_VIR, V_WIN0_VIR_STRIDE(xvir)); + vop_writel(vop_dev, WIN0_ACT_INFO, V_WIN0_ACT_WIDTH(xact - 1) | + V_WIN0_ACT_HEIGHT(yact - 1)); + + vop_writel(vop_dev, WIN0_YRGB_MST, rgb_mst); + + vop_cfg_done(vop_dev); + + return 0; +} + +/* +static int lcdc_reset(struct rk_lcdc_driver *dev_drv, bool initscreen) +{ + struct vop_device *vop_dev = + container_of(dev_drv, struct vop_device, driver); + u64 val; + u32 __maybe_unused v; + + if (!vop_dev->standby && initscreen && (dev_drv->first_frame != 1)) { + mdelay(150); + val = V_WIN0_EN(0); + vop_msk_reg(vop_dev, WIN0_CTRL0, val); + vop_msk_reg(vop_dev, WIN1_CTRL0, val); + + val = V_WIN2_EN(0) | V_WIN2_MST0_EN(0) | + V_WIN2_MST1_EN(0) | + V_WIN2_MST2_EN(0) | V_WIN2_MST3_EN(0); + vop_msk_reg(vop_dev, WIN2_CTRL0, val); + vop_msk_reg(vop_dev, WIN3_CTRL0, val); + val = V_HDMI_OUT_EN(0); + vop_msk_reg(vop_dev, SYS_CTRL, val); + vop_cfg_done(vop_dev); + mdelay(50); + vop_msk_reg(vop_dev, SYS_CTRL, V_VOP_STANDBY_EN(1)); + writel_relaxed(0, vop_dev->regs + REG_CFG_DONE); + mdelay(50); + } + + return 0; +} +*/ + +static int vop_load_screen(struct rk_lcdc_driver *dev_drv, bool initscreen) +{ + u16 face = 0; + u16 dclk_ddr = 0; + struct vop_device *vop_dev = + container_of(dev_drv, struct vop_device, driver); + struct rk_screen *screen = dev_drv->cur_screen; + u64 val; + + if (unlikely(!vop_dev->clk_on)) { + pr_info("%s,clk_on = %d\n", __func__, vop_dev->clk_on); + return 0; + } + + if (!vop_dev->standby && initscreen && (dev_drv->first_frame != 1)) + flush_kthread_worker(&dev_drv->update_regs_worker); + + spin_lock(&vop_dev->reg_lock); + if (likely(vop_dev->clk_on)) { + switch (screen->face) { + case OUT_P888: + face = OUT_P888; + val = V_DITHER_DOWN_EN(0); + break; + case OUT_YUV_420: + /*yuv420 output prefer yuv domain overlay */ + face = OUT_YUV_420; + dclk_ddr = 1; + val = V_DITHER_DOWN_EN(0); + break; + default: + dev_err(vop_dev->dev, "un supported interface!\n"); + break; + } + + vop_msk_reg(vop_dev, DSP_CTRL1, val); + + if (screen->color_mode == COLOR_RGB) + dev_drv->overlay_mode = VOP_RGB_DOMAIN; + else + dev_drv->overlay_mode = VOP_YUV_DOMAIN; + val = V_HDMI_OUT_EN(1); + vop_msk_reg(vop_dev, SYS_CTRL, val); + val = V_HDMI_HSYNC_POL(screen->pin_hsync) | + V_HDMI_VSYNC_POL(screen->pin_vsync) | + V_HDMI_DEN_POL(screen->pin_den) | + V_HDMI_DCLK_POL(screen->pin_dclk); + + /*hsync vsync den dclk polo,dither */ + vop_msk_reg(vop_dev, DSP_CTRL1, val); +#ifndef CONFIG_RK_FPGA + /* + * Todo: + * writel_relaxed(v, RK_GRF_VIRT + vop_GRF_SOC_CON7); + * move to lvds driver + */ + /*GRF_SOC_CON7 bit[15]:0->dsi/lvds mode,1->ttl mode */ +#endif + val = V_DSP_OUT_MODE(face) | V_DSP_DCLK_DDR(dclk_ddr) | + V_DSP_BG_SWAP(screen->swap_gb) | + V_DSP_RB_SWAP(screen->swap_rb) | + V_DSP_RG_SWAP(screen->swap_rg) | + V_DSP_DELTA_SWAP(screen->swap_delta) | + V_DSP_DUMMY_SWAP(screen->swap_dumy) | V_DSP_OUT_ZERO(0) | + V_DSP_BLANK_EN(0) | V_DSP_BLACK_EN(0) | + V_DSP_X_MIR_EN(screen->x_mirror) | + V_DSP_Y_MIR_EN(screen->y_mirror); + vop_msk_reg(vop_dev, DSP_CTRL0, val); + /* BG color */ + 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); + vop_msk_reg(vop_dev, DSP_BG, val); + dev_drv->output_color = screen->color_mode; + vop_bcsh_path_sel(dev_drv); + vop_config_timing(dev_drv); + vop_cfg_done(vop_dev); + } + spin_unlock(&vop_dev->reg_lock); + vop_set_dclk(dev_drv, 1); + if (screen->type != SCREEN_HDMI && screen->type != SCREEN_TVOUT && + dev_drv->trsm_ops && dev_drv->trsm_ops->enable) + dev_drv->trsm_ops->enable(); + if (screen->init) + screen->init(); + + return 0; +} + +/*enable layer,open:1,enable;0 disable*/ +static void vop_layer_enable(struct vop_device *vop_dev, + unsigned int win_id, bool open) +{ + spin_lock(&vop_dev->reg_lock); + if (likely(vop_dev->clk_on) && + vop_dev->driver.win[win_id]->state != open) { + if (open) { + if (!vop_dev->atv_layer_cnt) { + dev_info(vop_dev->dev, + "wakeup from standby!\n"); + vop_dev->standby = 0; + } + vop_dev->atv_layer_cnt |= (1 << win_id); + } else { + if (vop_dev->atv_layer_cnt & (1 << win_id)) + vop_dev->atv_layer_cnt &= ~(1 << win_id); + } + vop_dev->driver.win[win_id]->state = open; + if (!open) { + vop_layer_update_regs(vop_dev, + vop_dev->driver.win[win_id]); + vop_cfg_done(vop_dev); + } + /* if no layer used,disable lcdc */ + if (!vop_dev->atv_layer_cnt) { + dev_info(vop_dev->dev, + "no layer is used,go to standby!\n"); + vop_dev->standby = 1; + } + } + spin_unlock(&vop_dev->reg_lock); +} + +static int vop_enable_irq(struct rk_lcdc_driver *dev_drv) +{ + struct vop_device *vop_dev = container_of(dev_drv, + struct vop_device, driver); + u64 val; + /* struct rk_screen *screen = dev_drv->cur_screen; */ + + vop_mask_writel(vop_dev, INTR_CLEAR0, INTR_MASK, INTR_MASK); + + val = INTR_FS | INTR_LINE_FLAG0 | INTR_BUS_ERROR | INTR_LINE_FLAG1; + vop_mask_writel(vop_dev, INTR_EN0, INTR_MASK, val); + + return 0; +} + +static int vop_open(struct rk_lcdc_driver *dev_drv, int win_id, + bool open) +{ + struct vop_device *vop_dev = + container_of(dev_drv, struct vop_device, driver); + + /* enable clk,when first layer open */ + if ((open) && (!vop_dev->atv_layer_cnt)) { + /* rockchip_set_system_status(sys_status); */ + vop_pre_init(dev_drv); + vop_clk_enable(vop_dev); + vop_enable_irq(dev_drv); +#if defined(CONFIG_ROCKCHIP_IOMMU) + if (dev_drv->iommu_enabled) { + if (!dev_drv->mmu_dev) { + dev_drv->mmu_dev = + rk_fb_get_sysmmu_device_by_compatible + (dev_drv->mmu_dts_name); + if (dev_drv->mmu_dev) { + rk_fb_platform_set_sysmmu + (dev_drv->mmu_dev, dev_drv->dev); + } else { + dev_err(dev_drv->dev, + "fail get rk iommu device\n"); + return -1; + } + } + } +#endif + if ((support_uboot_display() && (vop_dev->prop == PRMRY))) + vop_set_dclk(dev_drv, 0); + else + vop_load_screen(dev_drv, 1); + if (dev_drv->bcsh.enable) + vop_set_bcsh(dev_drv, 1); + spin_lock(&vop_dev->reg_lock); + spin_unlock(&vop_dev->reg_lock); + } + + if (win_id < ARRAY_SIZE(vop_win)) + vop_layer_enable(vop_dev, win_id, open); + else + dev_err(vop_dev->dev, "invalid win id:%d\n", win_id); + + dev_drv->first_frame = 0; + return 0; +} + +static int win_0_1_display(struct vop_device *vop_dev, + struct rk_lcdc_win *win) +{ + u32 y_addr; + u32 uv_addr; + unsigned int off; + + off = win->id * 0x40; + /*win->smem_start + win->y_offset; */ + y_addr = win->area[0].smem_start + win->area[0].y_offset; + uv_addr = win->area[0].cbr_start + win->area[0].c_offset; + DBG(2, "lcdc[%d]:win[%d]>>:y_addr:0x%x>>uv_addr:0x%x", + vop_dev->id, win->id, y_addr, uv_addr); + DBG(2, ">>y_offset:0x%x>>c_offset=0x%x\n", + win->area[0].y_offset, win->area[0].c_offset); + spin_lock(&vop_dev->reg_lock); + if (likely(vop_dev->clk_on)) { + win->area[0].y_addr = y_addr; + win->area[0].uv_addr = uv_addr; + vop_writel(vop_dev, WIN0_YRGB_MST + off, win->area[0].y_addr); + vop_writel(vop_dev, WIN0_CBR_MST + off, win->area[0].uv_addr); + } + spin_unlock(&vop_dev->reg_lock); + + return 0; +} + +static int hwc_display(struct vop_device *vop_dev, struct rk_lcdc_win *win) +{ + u32 y_addr; + + y_addr = win->area[0].smem_start + win->area[0].y_offset; + DBG(2, "lcdc[%d]:hwc>>%s>>y_addr:0x%x>>\n", + vop_dev->id, __func__, y_addr); + spin_lock(&vop_dev->reg_lock); + if (likely(vop_dev->clk_on)) { + win->area[0].y_addr = y_addr; + vop_writel(vop_dev, HWC_MST, win->area[0].y_addr); + } + spin_unlock(&vop_dev->reg_lock); + + return 0; +} + +static int vop_pan_display(struct rk_lcdc_driver *dev_drv, int win_id) +{ + struct vop_device *vop_dev = + container_of(dev_drv, struct vop_device, driver); + struct rk_lcdc_win *win = NULL; + struct rk_screen *screen = dev_drv->cur_screen; + + win = dev_drv->win[win_id]; + if (!screen) { + dev_err(dev_drv->dev, "screen is null!\n"); + return -ENOENT; + } + if (unlikely(!vop_dev->clk_on)) { + pr_info("%s,clk_on = %d\n", __func__, vop_dev->clk_on); + return 0; + } + if (win_id == 0) { + win_0_1_display(vop_dev, win); + } else if (win_id == 1) { + win_0_1_display(vop_dev, win); + } else if (win_id == 2) { + hwc_display(vop_dev, win); + } else { + dev_err(dev_drv->dev, "invalid win number:%d!\n", win_id); + return -EINVAL; + } + + return 0; +} + +static int vop_cal_scl_fac(struct rk_lcdc_win *win, struct rk_screen *screen) +{ + u16 srcW; + u16 srcH; + u16 dstW; + u16 dstH; + u16 yrgb_srcW; + u16 yrgb_srcH; + u16 yrgb_dstW; + u16 yrgb_dstH; + u32 yrgb_vscalednmult; + u32 yrgb_xscl_factor; + u32 yrgb_yscl_factor; + u8 yrgb_vsd_bil_gt2 = 0; + u8 yrgb_vsd_bil_gt4 = 0; + + u16 cbcr_srcW; + u16 cbcr_srcH; + u16 cbcr_dstW; + u16 cbcr_dstH; + u32 cbcr_vscalednmult; + u32 cbcr_xscl_factor; + u32 cbcr_yscl_factor; + u8 cbcr_vsd_bil_gt2 = 0; + u8 cbcr_vsd_bil_gt4 = 0; + u8 yuv_fmt = 0; + + srcW = win->area[0].xact; + if ((screen->mode.vmode == FB_VMODE_INTERLACED) && + (win->area[0].yact == 2 * win->area[0].ysize)) { + srcH = win->area[0].yact / 2; + yrgb_vsd_bil_gt2 = 1; + cbcr_vsd_bil_gt2 = 1; + } else { + srcH = win->area[0].yact; + } + dstW = win->area[0].xsize; + dstH = win->area[0].ysize; + + /*yrgb scl mode */ + yrgb_srcW = srcW; + yrgb_srcH = srcH; + yrgb_dstW = dstW; + yrgb_dstH = dstH; + if ((yrgb_dstW * 8 <= yrgb_srcW) || (yrgb_dstH * 8 <= yrgb_srcH)) { + pr_err("ERROR: yrgb scale exceed 8,"); + pr_err("srcW=%d,srcH=%d,dstW=%d,dstH=%d\n", + yrgb_srcW, yrgb_srcH, yrgb_dstW, yrgb_dstH); + } + if (yrgb_srcW < yrgb_dstW) + win->yrgb_hor_scl_mode = SCALE_UP; + else if (yrgb_srcW > yrgb_dstW) + win->yrgb_hor_scl_mode = SCALE_DOWN; + else + win->yrgb_hor_scl_mode = SCALE_NONE; + + if (yrgb_srcH < yrgb_dstH) + win->yrgb_ver_scl_mode = SCALE_UP; + else if (yrgb_srcH > yrgb_dstH) + win->yrgb_ver_scl_mode = SCALE_DOWN; + else + win->yrgb_ver_scl_mode = SCALE_NONE; + + /*cbcr scl mode */ + switch (win->area[0].format) { + case YUV422: + case YUV422_A: + cbcr_srcW = srcW / 2; + cbcr_dstW = dstW; + cbcr_srcH = srcH; + cbcr_dstH = dstH; + yuv_fmt = 1; + break; + case YUV420: + case YUV420_A: + case YUV420_NV21: + cbcr_srcW = srcW / 2; + cbcr_dstW = dstW; + cbcr_srcH = srcH / 2; + cbcr_dstH = dstH; + yuv_fmt = 1; + break; + case YUV444: + case YUV444_A: + cbcr_srcW = srcW; + cbcr_dstW = dstW; + cbcr_srcH = srcH; + cbcr_dstH = dstH; + yuv_fmt = 1; + break; + default: + cbcr_srcW = 0; + cbcr_dstW = 0; + cbcr_srcH = 0; + cbcr_dstH = 0; + yuv_fmt = 0; + break; + } + if (yuv_fmt) { + if ((cbcr_dstW * 8 <= cbcr_srcW) || + (cbcr_dstH * 8 <= cbcr_srcH)) { + pr_err("ERROR: cbcr scale exceed 8,"); + pr_err("srcW=%d,srcH=%d,dstW=%d,dstH=%d\n", cbcr_srcW, + cbcr_srcH, cbcr_dstW, cbcr_dstH); + } + } + + if (cbcr_srcW < cbcr_dstW) + win->cbr_hor_scl_mode = SCALE_UP; + else if (cbcr_srcW > cbcr_dstW) + win->cbr_hor_scl_mode = SCALE_DOWN; + else + win->cbr_hor_scl_mode = SCALE_NONE; + + if (cbcr_srcH < cbcr_dstH) + win->cbr_ver_scl_mode = SCALE_UP; + else if (cbcr_srcH > cbcr_dstH) + win->cbr_ver_scl_mode = SCALE_DOWN; + else + win->cbr_ver_scl_mode = SCALE_NONE; + + /* 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) { + if ((cbcr_dstW > VOP_INPUT_MAX_WIDTH / 2) || + (cbcr_dstW == 0)) + pr_err("ERROR cbcr_dstW = %d,exceeds 2048\n", + cbcr_dstW); + else if (cbcr_dstW > 1280) + win->win_lb_mode = LB_YUV_3840X5; + else + win->win_lb_mode = LB_YUV_2560X8; + } else { /* SCALE_UP or SCALE_NONE */ + if ((cbcr_srcW > VOP_INPUT_MAX_WIDTH / 2) || + (cbcr_srcW == 0)) + pr_err("ERROR cbcr_srcW = %d,exceeds 2048\n", + cbcr_srcW); + else if (cbcr_srcW > 1280) + win->win_lb_mode = LB_YUV_3840X5; + else + win->win_lb_mode = LB_YUV_2560X8; + } + } else { + if (win->yrgb_hor_scl_mode == SCALE_DOWN) { + if ((yrgb_dstW > VOP_INPUT_MAX_WIDTH) || + (yrgb_dstW == 0)) + pr_err("ERROR yrgb_dstW = %d\n", yrgb_dstW); + else if (yrgb_dstW > 2560) + win->win_lb_mode = LB_RGB_3840X2; + else if (yrgb_dstW > 1920) + win->win_lb_mode = LB_RGB_2560X4; + else if (yrgb_dstW > 1280) + win->win_lb_mode = LB_RGB_1920X5; + else + win->win_lb_mode = LB_RGB_1280X8; + } else { /* SCALE_UP or SCALE_NONE */ + if ((yrgb_srcW > VOP_INPUT_MAX_WIDTH) || + (yrgb_srcW == 0)) + pr_err("ERROR yrgb_srcW = %d\n", yrgb_srcW); + else if (yrgb_srcW > 2560) + win->win_lb_mode = LB_RGB_3840X2; + else if (yrgb_srcW > 1920) + win->win_lb_mode = LB_RGB_2560X4; + else if (yrgb_srcW > 1280) + win->win_lb_mode = LB_RGB_1920X5; + else + win->win_lb_mode = LB_RGB_1280X8; + } + } + DBG(1, "win->win_lb_mode = %d;\n", win->win_lb_mode); + + /* vsd/vsu scale ALGORITHM */ + win->yrgb_hsd_mode = SCALE_DOWN_BIL; /*not to specify */ + win->cbr_hsd_mode = SCALE_DOWN_BIL; /*not to specify */ + win->yrgb_vsd_mode = SCALE_DOWN_BIL; /*not to specify */ + win->cbr_vsd_mode = SCALE_DOWN_BIL; /*not to specify */ + switch (win->win_lb_mode) { + case LB_YUV_3840X5: + case LB_YUV_2560X8: + case LB_RGB_1920X5: + case LB_RGB_1280X8: + win->yrgb_vsu_mode = SCALE_UP_BIC; + win->cbr_vsu_mode = SCALE_UP_BIC; + break; + case LB_RGB_3840X2: + if (win->yrgb_ver_scl_mode != SCALE_NONE) + pr_err("ERROR : not allow yrgb ver scale\n"); + if (win->cbr_ver_scl_mode != SCALE_NONE) + pr_err("ERROR : not allow cbcr ver scale\n"); + break; + case LB_RGB_2560X4: + win->yrgb_vsu_mode = SCALE_UP_BIL; + win->cbr_vsu_mode = SCALE_UP_BIL; + break; + default: + pr_info("%s:un supported win_lb_mode:%d\n", + __func__, win->win_lb_mode); + break; + } + + if (win->mirror_en == 1) + win->yrgb_vsd_mode = SCALE_DOWN_BIL; + if (screen->mode.vmode == FB_VMODE_INTERLACED) { + /* interlace mode must bill */ + win->yrgb_vsd_mode = SCALE_DOWN_BIL; + win->cbr_vsd_mode = SCALE_DOWN_BIL; + } + if ((win->yrgb_ver_scl_mode == SCALE_DOWN) && + (win->area[0].fbdc_en == 1)) { + /* in this pattern,use bil mode,not support souble scd, + use avg mode, support double scd, but aclk should be + bigger than dclk,aclk>>dclk */ + if (yrgb_srcH >= 2 * yrgb_dstH) { + pr_err("ERROR : fbdc mode,not support y scale down:"); + pr_err("srcH[%d] > 2 *dstH[%d]\n", + yrgb_srcH, yrgb_dstH); + } + } + DBG(1, "yrgb:hsd=%d,vsd=%d,vsu=%d;cbcr:hsd=%d,vsd=%d,vsu=%d\n", + win->yrgb_hsd_mode, win->yrgb_vsd_mode, win->yrgb_vsu_mode, + win->cbr_hsd_mode, win->cbr_vsd_mode, win->cbr_vsu_mode); + + /* SCALE FACTOR */ + + /* (1.1)YRGB HOR SCALE FACTOR */ + switch (win->yrgb_hor_scl_mode) { + case SCALE_NONE: + yrgb_xscl_factor = (1 << SCALE_FACTOR_DEFAULT_FIXPOINT_SHIFT); + break; + case SCALE_UP: + yrgb_xscl_factor = GET_SCALE_FACTOR_BIC(yrgb_srcW, yrgb_dstW); + break; + case SCALE_DOWN: + switch (win->yrgb_hsd_mode) { + case SCALE_DOWN_BIL: + yrgb_xscl_factor = + GET_SCALE_FACTOR_BILI_DN(yrgb_srcW, yrgb_dstW); + break; + case SCALE_DOWN_AVG: + yrgb_xscl_factor = + GET_SCALE_FACTOR_AVRG(yrgb_srcW, yrgb_dstW); + break; + default: + pr_info("%s:un supported yrgb_hsd_mode:%d\n", __func__, + win->yrgb_hsd_mode); + break; + } + break; + default: + pr_info("%s:un supported yrgb_hor_scl_mode:%d\n", + __func__, win->yrgb_hor_scl_mode); + break; + } + + /* (1.2)YRGB VER SCALE FACTOR */ + switch (win->yrgb_ver_scl_mode) { + case SCALE_NONE: + yrgb_yscl_factor = (1 << SCALE_FACTOR_DEFAULT_FIXPOINT_SHIFT); + break; + case SCALE_UP: + switch (win->yrgb_vsu_mode) { + case SCALE_UP_BIL: + yrgb_yscl_factor = + GET_SCALE_FACTOR_BILI_UP(yrgb_srcH, yrgb_dstH); + break; + case SCALE_UP_BIC: + if (yrgb_srcH < 3) { + pr_err("yrgb_srcH should be"); + pr_err(" greater than 3 !!!\n"); + } + yrgb_yscl_factor = GET_SCALE_FACTOR_BIC(yrgb_srcH, + yrgb_dstH); + break; + default: + pr_info("%s:un support yrgb_vsu_mode:%d\n", + __func__, win->yrgb_vsu_mode); + break; + } + break; + case SCALE_DOWN: + switch (win->yrgb_vsd_mode) { + case SCALE_DOWN_BIL: + yrgb_vscalednmult = + vop_get_hard_ware_vskiplines(yrgb_srcH, yrgb_dstH); + yrgb_yscl_factor = + GET_SCALE_FACTOR_BILI_DN_VSKIP(yrgb_srcH, yrgb_dstH, + yrgb_vscalednmult); + if (yrgb_yscl_factor >= 0x2000) { + pr_err("yrgb_yscl_factor should less 0x2000"); + pr_err("yrgb_yscl_factor=%4x;\n", + yrgb_yscl_factor); + } + if (yrgb_vscalednmult == 4) { + yrgb_vsd_bil_gt4 = 1; + yrgb_vsd_bil_gt2 = 0; + } else if (yrgb_vscalednmult == 2) { + yrgb_vsd_bil_gt4 = 0; + yrgb_vsd_bil_gt2 = 1; + } else { + yrgb_vsd_bil_gt4 = 0; + yrgb_vsd_bil_gt2 = 0; + } + break; + case SCALE_DOWN_AVG: + yrgb_yscl_factor = GET_SCALE_FACTOR_AVRG(yrgb_srcH, + yrgb_dstH); + break; + default: + pr_info("%s:un support yrgb_vsd_mode:%d\n", + __func__, win->yrgb_vsd_mode); + break; + } /*win->yrgb_vsd_mode */ + break; + default: + pr_info("%s:un supported yrgb_ver_scl_mode:%d\n", + __func__, win->yrgb_ver_scl_mode); + break; + } + win->scale_yrgb_x = yrgb_xscl_factor; + win->scale_yrgb_y = yrgb_yscl_factor; + win->vsd_yrgb_gt4 = yrgb_vsd_bil_gt4; + win->vsd_yrgb_gt2 = yrgb_vsd_bil_gt2; + DBG(1, "yrgb:h_fac=%d, V_fac=%d,gt4=%d, gt2=%d\n", yrgb_xscl_factor, + yrgb_yscl_factor, yrgb_vsd_bil_gt4, yrgb_vsd_bil_gt2); + + /*(2.1)CBCR HOR SCALE FACTOR */ + switch (win->cbr_hor_scl_mode) { + case SCALE_NONE: + cbcr_xscl_factor = (1 << SCALE_FACTOR_DEFAULT_FIXPOINT_SHIFT); + break; + case SCALE_UP: + cbcr_xscl_factor = GET_SCALE_FACTOR_BIC(cbcr_srcW, cbcr_dstW); + break; + case SCALE_DOWN: + switch (win->cbr_hsd_mode) { + case SCALE_DOWN_BIL: + cbcr_xscl_factor = + GET_SCALE_FACTOR_BILI_DN(cbcr_srcW, cbcr_dstW); + break; + case SCALE_DOWN_AVG: + cbcr_xscl_factor = + GET_SCALE_FACTOR_AVRG(cbcr_srcW, cbcr_dstW); + break; + default: + pr_info("%s:un support cbr_hsd_mode:%d\n", + __func__, win->cbr_hsd_mode); + break; + } + break; + default: + pr_info("%s:un supported cbr_hor_scl_mode:%d\n", + __func__, win->cbr_hor_scl_mode); + break; + } /*win->cbr_hor_scl_mode */ + + /* (2.2)CBCR VER SCALE FACTOR */ + switch (win->cbr_ver_scl_mode) { + case SCALE_NONE: + cbcr_yscl_factor = (1 << SCALE_FACTOR_DEFAULT_FIXPOINT_SHIFT); + break; + case SCALE_UP: + switch (win->cbr_vsu_mode) { + case SCALE_UP_BIL: + cbcr_yscl_factor = + GET_SCALE_FACTOR_BILI_UP(cbcr_srcH, cbcr_dstH); + break; + case SCALE_UP_BIC: + if (cbcr_srcH < 3) { + pr_err("cbcr_srcH should be "); + pr_err("greater than 3 !!!\n"); + } + cbcr_yscl_factor = GET_SCALE_FACTOR_BIC(cbcr_srcH, + cbcr_dstH); + break; + default: + pr_info("%s:un support cbr_vsu_mode:%d\n", + __func__, win->cbr_vsu_mode); + break; + } + break; + case SCALE_DOWN: + switch (win->cbr_vsd_mode) { + case SCALE_DOWN_BIL: + cbcr_vscalednmult = + vop_get_hard_ware_vskiplines(cbcr_srcH, cbcr_dstH); + cbcr_yscl_factor = + GET_SCALE_FACTOR_BILI_DN_VSKIP(cbcr_srcH, cbcr_dstH, + cbcr_vscalednmult); + if (cbcr_yscl_factor >= 0x2000) { + pr_err("cbcr_yscl_factor should be less "); + pr_err("than 0x2000,cbcr_yscl_factor=%4x;\n", + cbcr_yscl_factor); + } + + if (cbcr_vscalednmult == 4) { + cbcr_vsd_bil_gt4 = 1; + cbcr_vsd_bil_gt2 = 0; + } else if (cbcr_vscalednmult == 2) { + cbcr_vsd_bil_gt4 = 0; + cbcr_vsd_bil_gt2 = 1; + } else { + cbcr_vsd_bil_gt4 = 0; + cbcr_vsd_bil_gt2 = 0; + } + break; + case SCALE_DOWN_AVG: + cbcr_yscl_factor = GET_SCALE_FACTOR_AVRG(cbcr_srcH, + cbcr_dstH); + break; + default: + pr_info("%s:un support cbr_vsd_mode:%d\n", + __func__, win->cbr_vsd_mode); + break; + } + break; + default: + pr_info("%s:un supported cbr_ver_scl_mode:%d\n", + __func__, win->cbr_ver_scl_mode); + break; + } + win->scale_cbcr_x = cbcr_xscl_factor; + win->scale_cbcr_y = cbcr_yscl_factor; + win->vsd_cbr_gt4 = cbcr_vsd_bil_gt4; + win->vsd_cbr_gt2 = cbcr_vsd_bil_gt2; + + DBG(1, "cbcr:h_fac=%d,v_fac=%d,gt4=%d,gt2=%d\n", cbcr_xscl_factor, + cbcr_yscl_factor, cbcr_vsd_bil_gt4, cbcr_vsd_bil_gt2); + 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 vop_device *vop_dev, + struct rk_screen *screen, struct rk_lcdc_win *win) +{ + u32 xact, yact, xvir, yvir, xpos, ypos; + u8 fmt_cfg = 0, swap_rb, swap_uv = 0; + char fmt[9] = "NULL"; + + xpos = dsp_x_pos(win->mirror_en, screen, &win->area[0]); + ypos = dsp_y_pos(win->mirror_en, screen, &win->area[0]); + + spin_lock(&vop_dev->reg_lock); + if (likely(vop_dev->clk_on)) { + vop_cal_scl_fac(win, screen); + 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; + win->fmt_10 = 0; + break; + case XBGR888: + case ABGR888: + fmt_cfg = 0; + swap_rb = 1; + win->fmt_10 = 0; + break; + case RGB888: + fmt_cfg = 1; + swap_rb = 0; + win->fmt_10 = 0; + break; + case RGB565: + fmt_cfg = 2; + swap_rb = 0; + win->fmt_10 = 0; + break; + case YUV422: + fmt_cfg = 5; + swap_rb = 0; + win->fmt_10 = 0; + break; + case YUV420: + fmt_cfg = 4; + 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->fmt_10 = 0; + break; + case YUV422_A: + fmt_cfg = 5; + swap_rb = 0; + win->fmt_10 = 1; + break; + case YUV420_A: + fmt_cfg = 4; + swap_rb = 0; + win->fmt_10 = 1; + break; + case YUV444_A: + fmt_cfg = 6; + swap_rb = 0; + win->fmt_10 = 1; + break; + default: + dev_err(vop_dev->driver.dev, "%s:unsupport format!\n", + __func__); + break; + } + 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; + yact = win->area[0].yact; + xvir = win->area[0].xvir; + yvir = win->area[0].yvir; + } + vop_win_0_1_reg_update(&vop_dev->driver, win->id); + spin_unlock(&vop_dev->reg_lock); + + DBG(1, "lcdc[%d]:win[%d]\n>>format:%s>>>xact:%d>>yact:%d>>xsize:%d", + vop_dev->id, win->id, get_format_string(win->area[0].format, fmt), + xact, yact, win->area[0].xsize); + DBG(1, ">>ysize:%d>>xvir:%d>>yvir:%d>>xpos:%d>>ypos:%d>>\n", + win->area[0].ysize, xvir, yvir, xpos, ypos); + + return 0; +} + +static int hwc_set_par(struct vop_device *vop_dev, + struct rk_screen *screen, struct rk_lcdc_win *win) +{ + u32 xact, yact, xvir, yvir, xpos, ypos; + u8 fmt_cfg = 0, swap_rb; + char fmt[9] = "NULL"; + + 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; + + spin_lock(&vop_dev->reg_lock); + if (likely(vop_dev->clk_on)) { + switch (win->area[0].format) { + case ARGB888: + fmt_cfg = 0; + swap_rb = 0; + break; + case XBGR888: + case ABGR888: + fmt_cfg = 0; + swap_rb = 1; + break; + case RGB888: + fmt_cfg = 1; + swap_rb = 0; + break; + case RGB565: + fmt_cfg = 2; + swap_rb = 0; + break; + default: + dev_err(vop_dev->driver.dev, + "%s:un supported format!\n", __func__); + break; + } + win->area[0].fmt_cfg = fmt_cfg; + win->area[0].swap_rb = swap_rb; + win->area[0].dsp_stx = xpos; + win->area[0].dsp_sty = ypos; + xact = win->area[0].xact; + yact = win->area[0].yact; + xvir = win->area[0].xvir; + yvir = win->area[0].yvir; + } + vop_hwc_reg_update(&vop_dev->driver, 4); + spin_unlock(&vop_dev->reg_lock); + + DBG(1, "lcdc[%d]:hwc>>%s\n>>format:%s>>>xact:%d>>yact:%d>>xsize:%d", + vop_dev->id, __func__, get_format_string(win->area[0].format, fmt), + xact, yact, win->area[0].xsize); + DBG(1, ">>ysize:%d>>xvir:%d>>yvir:%d>>xpos:%d>>ypos:%d>>\n", + win->area[0].ysize, xvir, yvir, xpos, ypos); + return 0; +} + +static int vop_set_par(struct rk_lcdc_driver *dev_drv, int win_id) +{ + struct vop_device *vop_dev = + container_of(dev_drv, struct vop_device, driver); + struct rk_lcdc_win *win = NULL; + struct rk_screen *screen = dev_drv->cur_screen; + + if (unlikely(!vop_dev->clk_on)) { + pr_info("%s,clk_on = %d\n", __func__, vop_dev->clk_on); + return 0; + } + win = dev_drv->win[win_id]; + switch (win_id) { + case 0: + win_0_1_set_par(vop_dev, screen, win); + break; + case 1: + win_0_1_set_par(vop_dev, screen, win); + break; + case 2: + hwc_set_par(vop_dev, screen, win); + break; + default: + dev_err(dev_drv->dev, "unsupported win number:%d\n", win_id); + break; + } + return 0; +} + +static int vop_ioctl(struct rk_lcdc_driver *dev_drv, unsigned int cmd, + unsigned long arg, int win_id) +{ + struct vop_device *vop_dev = + container_of(dev_drv, struct vop_device, driver); + u32 panel_size[2]; + void __user *argp = (void __user *)arg; + struct color_key_cfg clr_key_cfg; + + switch (cmd) { + case RK_FBIOGET_PANEL_SIZE: + panel_size[0] = vop_dev->screen->mode.xres; + panel_size[1] = vop_dev->screen->mode.yres; + if (copy_to_user(argp, panel_size, 8)) + return -EFAULT; + break; + case RK_FBIOPUT_COLOR_KEY_CFG: + if (copy_from_user(&clr_key_cfg, argp, + sizeof(struct color_key_cfg))) + return -EFAULT; + vop_clr_key_cfg(dev_drv); + vop_writel(vop_dev, WIN0_COLOR_KEY, + clr_key_cfg.win0_color_key_cfg); + vop_writel(vop_dev, WIN1_COLOR_KEY, + clr_key_cfg.win1_color_key_cfg); + break; + + default: + break; + } + return 0; +} + +static int vop_get_backlight_device(struct rk_lcdc_driver *dev_drv) +{ + struct vop_device *vop_dev = container_of(dev_drv, + struct vop_device, driver); + struct device_node *backlight; + struct property *prop; + u32 *brightness_levels; + u32 length, max, last; + + if (vop_dev->backlight) + return 0; + backlight = of_parse_phandle(vop_dev->dev->of_node, "backlight", 0); + if (backlight) { + vop_dev->backlight = of_find_backlight_by_node(backlight); + if (!vop_dev->backlight) + dev_info(vop_dev->dev, "No find backlight device\n"); + } else { + dev_info(vop_dev->dev, "No find backlight device node\n"); + } + prop = of_find_property(backlight, "brightness-levels", &length); + if (!prop) + return -EINVAL; + max = length / sizeof(u32); + last = max - 1; + brightness_levels = kmalloc(256, GFP_KERNEL); + if (brightness_levels) + return -ENOMEM; + + if (!of_property_read_u32_array(backlight, "brightness-levels", + brightness_levels, max)) { + if (brightness_levels[0] > brightness_levels[last]) + dev_drv->cabc_pwm_pol = 1;/*negative*/ + else + dev_drv->cabc_pwm_pol = 0;/*positive*/ + } else { + dev_info(vop_dev->dev, + "Can not read brightness-levels value\n"); + } + + kfree(brightness_levels); + + return 0; +} + +static int vop_early_suspend(struct rk_lcdc_driver *dev_drv) +{ + struct vop_device *vop_dev = + container_of(dev_drv, struct vop_device, driver); + + if (dev_drv->suspend_flag) + return 0; + + dev_drv->suspend_flag = 1; + flush_kthread_worker(&dev_drv->update_regs_worker); + + if (dev_drv->trsm_ops && dev_drv->trsm_ops->disable) + dev_drv->trsm_ops->disable(); + + if (likely(vop_dev->clk_on)) { + spin_lock(&vop_dev->reg_lock); + vop_msk_reg(vop_dev, DSP_CTRL0, V_DSP_BLANK_EN(1)); + vop_mask_writel(vop_dev, INTR_CLEAR0, INTR_MASK, INTR_MASK); + vop_msk_reg(vop_dev, DSP_CTRL0, V_DSP_OUT_ZERO(1)); + vop_msk_reg(vop_dev, SYS_CTRL, V_VOP_STANDBY_EN(1)); + vop_cfg_done(vop_dev); + + if (dev_drv->iommu_enabled && dev_drv->mmu_dev) + rockchip_iovmm_deactivate(dev_drv->dev); + + spin_unlock(&vop_dev->reg_lock); + } + + vop_clk_disable(vop_dev); + rk_disp_pwr_disable(dev_drv); + + return 0; +} + +static int vop_early_resume(struct rk_lcdc_driver *dev_drv) +{ + struct vop_device *vop_dev = + container_of(dev_drv, struct vop_device, driver); + + if (!dev_drv->suspend_flag) + return 0; + rk_disp_pwr_enable(dev_drv); + + vop_clk_enable(vop_dev); + memcpy(vop_dev->regs, vop_dev->regsbak, vop_dev->len); + + spin_lock(&vop_dev->reg_lock); + + vop_msk_reg(vop_dev, DSP_CTRL0, V_DSP_OUT_ZERO(0)); + vop_msk_reg(vop_dev, SYS_CTRL, V_VOP_STANDBY_EN(0)); + vop_msk_reg(vop_dev, DSP_CTRL0, V_DSP_BLANK_EN(0)); + vop_cfg_done(vop_dev); + spin_unlock(&vop_dev->reg_lock); + + if (dev_drv->iommu_enabled && dev_drv->mmu_dev) { + /* win address maybe effect after next frame start, + * but mmu maybe effect right now, so we delay 50ms + */ + mdelay(50); + rockchip_iovmm_activate(dev_drv->dev); + } + + dev_drv->suspend_flag = 0; + + if (dev_drv->trsm_ops && dev_drv->trsm_ops->enable) + dev_drv->trsm_ops->enable(); + + return 0; +} + +static int vop_blank(struct rk_lcdc_driver *dev_drv, int win_id, int blank_mode) +{ + switch (blank_mode) { + case FB_BLANK_UNBLANK: + vop_early_resume(dev_drv); + break; + case FB_BLANK_NORMAL: + vop_early_suspend(dev_drv); + break; + default: + vop_early_suspend(dev_drv); + break; + } + + dev_info(dev_drv->dev, "blank mode:%d\n", blank_mode); + + return 0; +} + +static int vop_get_win_state(struct rk_lcdc_driver *dev_drv, + int win_id, int area_id) +{ + struct vop_device *vop_dev = + container_of(dev_drv, struct vop_device, driver); + u32 area_status = 0, state = 0; + + switch (win_id) { + case 0: + area_status = vop_read_bit(vop_dev, WIN0_CTRL0, V_WIN0_EN(0)); + break; + case 1: + area_status = vop_read_bit(vop_dev, WIN1_CTRL0, V_WIN1_EN(0)); + break; + case 2: + area_status = vop_read_bit(vop_dev, HWC_CTRL0, V_HWC_EN(0)); + break; + default: + pr_err("!!!%s,win[%d]area[%d],unsupport!!!\n", + __func__, win_id, area_id); + break; + } + + state = (area_status > 0) ? 1 : 0; + return state; +} + +static int vop_get_area_num(struct rk_lcdc_driver *dev_drv, + unsigned int *area_support) +{ + area_support[0] = 1; + area_support[1] = 1; + + return 0; +} + +/*overlay will be do at regupdate*/ +static int vop_ovl_mgr(struct rk_lcdc_driver *dev_drv, int swap, bool set) +{ + struct vop_device *vop_dev = + container_of(dev_drv, struct vop_device, driver); + struct rk_lcdc_win *win = NULL; + int i, ovl; + u64 val; + int z_order_num = 0; + int layer0_sel, layer1_sel, layer2_sel, layer3_sel; + + if (swap == 0) { + for (i = 0; i < dev_drv->lcdc_win_num; i++) { + win = dev_drv->win[i]; + if (win->state == 1) + z_order_num++; + } + for (i = 0; i < dev_drv->lcdc_win_num; i++) { + win = dev_drv->win[i]; + if (win->state == 0) + win->z_order = z_order_num++; + switch (win->z_order) { + case 0: + layer0_sel = win->id; + break; + case 1: + layer1_sel = win->id; + break; + case 2: + layer2_sel = win->id; + break; + case 3: + layer3_sel = win->id; + break; + default: + break; + } + } + } else { + layer0_sel = swap % 10; + layer1_sel = swap / 10 % 10; + layer2_sel = swap / 100 % 10; + layer3_sel = swap / 1000; + } + + spin_lock(&vop_dev->reg_lock); + if (vop_dev->clk_on) { + if (set) { + val = V_DSP_LAYER0_SEL(layer0_sel) | + V_DSP_LAYER1_SEL(layer1_sel) | + V_DSP_LAYER2_SEL(layer2_sel) | + V_DSP_LAYER3_SEL(layer3_sel); + vop_msk_reg(vop_dev, DSP_CTRL1, val); + } else { + layer0_sel = vop_read_bit(vop_dev, DSP_CTRL1, + V_DSP_LAYER0_SEL(0)); + layer1_sel = vop_read_bit(vop_dev, DSP_CTRL1, + V_DSP_LAYER1_SEL(0)); + layer2_sel = vop_read_bit(vop_dev, DSP_CTRL1, + V_DSP_LAYER2_SEL(0)); + layer3_sel = vop_read_bit(vop_dev, DSP_CTRL1, + V_DSP_LAYER3_SEL(0)); + ovl = layer3_sel * 1000 + layer2_sel * 100 + + layer1_sel * 10 + layer0_sel; + } + } else { + ovl = -EPERM; + } + spin_unlock(&vop_dev->reg_lock); + + return ovl; +} + +static char *vop_format_to_string(int format, char *fmt) +{ + if (!fmt) + return NULL; + + switch (format) { + case 0: + strcpy(fmt, "ARGB888"); + break; + case 1: + strcpy(fmt, "RGB888"); + break; + case 2: + strcpy(fmt, "RGB565"); + break; + case 4: + strcpy(fmt, "YCbCr420"); + break; + case 5: + strcpy(fmt, "YCbCr422"); + break; + case 6: + strcpy(fmt, "YCbCr444"); + break; + default: + strcpy(fmt, "invalid\n"); + break; + } + return fmt; +} +static ssize_t vop_get_disp_info(struct rk_lcdc_driver *dev_drv, + char *buf, int win_id) +{ + struct vop_device *vop_dev = + container_of(dev_drv, struct vop_device, driver); + struct rk_screen *screen = dev_drv->cur_screen; + u16 hsync_len = screen->mode.hsync_len; + u16 left_margin = screen->mode.left_margin; + u16 vsync_len = screen->mode.vsync_len; + u16 upper_margin = screen->mode.upper_margin; + u32 h_pw_bp = hsync_len + left_margin; + u32 v_pw_bp = vsync_len + upper_margin; + u32 fmt_id; + char format_w0[9] = "NULL"; + char format_w1[9] = "NULL"; + char dsp_buf[100]; + u32 win_ctrl, zorder, vir_info, act_info, dsp_info, dsp_st; + u32 y_factor, uv_factor; + u8 layer0_sel, layer1_sel; + u8 w0_state, w1_state; + + u32 w0_vir_y, w0_vir_uv, w0_act_x, w0_act_y, w0_dsp_x, w0_dsp_y; + u32 w0_st_x = h_pw_bp, w0_st_y = v_pw_bp; + u32 w1_vir_y, w1_vir_uv, w1_act_x, w1_act_y, w1_dsp_x, w1_dsp_y; + u32 w1_st_x = h_pw_bp, w1_st_y = v_pw_bp; + u32 w0_y_h_fac, w0_y_v_fac, w0_uv_h_fac, w0_uv_v_fac; + u32 w1_y_h_fac, w1_y_v_fac, w1_uv_h_fac, w1_uv_v_fac; + + u32 dclk_freq; + int size = 0; + + dclk_freq = screen->mode.pixclock; + /*vop_reg_dump(dev_drv); */ + + spin_lock(&vop_dev->reg_lock); + if (vop_dev->clk_on) { + zorder = vop_readl(vop_dev, DSP_CTRL1); + layer0_sel = (zorder & MASK(DSP_LAYER0_SEL)) >> 8; + layer1_sel = (zorder & MASK(DSP_LAYER1_SEL)) >> 10; + /* WIN0 */ + win_ctrl = vop_readl(vop_dev, WIN0_CTRL0); + w0_state = win_ctrl & MASK(WIN0_EN); + fmt_id = (win_ctrl & MASK(WIN0_DATA_FMT)) >> 1; + vop_format_to_string(fmt_id, format_w0); + vir_info = vop_readl(vop_dev, WIN0_VIR); + act_info = vop_readl(vop_dev, WIN0_ACT_INFO); + dsp_info = vop_readl(vop_dev, WIN0_DSP_INFO); + dsp_st = vop_readl(vop_dev, WIN0_DSP_ST); + y_factor = vop_readl(vop_dev, WIN0_SCL_FACTOR_YRGB); + uv_factor = vop_readl(vop_dev, WIN0_SCL_FACTOR_CBR); + w0_vir_y = vir_info & MASK(WIN0_VIR_STRIDE); + w0_vir_uv = (vir_info & MASK(WIN0_VIR_STRIDE_UV)) >> 16; + w0_act_x = (act_info & MASK(WIN0_ACT_WIDTH)) + 1; + w0_act_y = ((act_info & MASK(WIN0_ACT_HEIGHT)) >> 16) + 1; + w0_dsp_x = (dsp_info & MASK(WIN0_DSP_WIDTH)) + 1; + w0_dsp_y = ((dsp_info & MASK(WIN0_DSP_HEIGHT)) >> 16) + 1; + if (w0_state) { + w0_st_x = dsp_st & MASK(WIN0_DSP_XST); + w0_st_y = (dsp_st & MASK(WIN0_DSP_YST)) >> 16; + } + w0_y_h_fac = y_factor & MASK(WIN0_HS_FACTOR_YRGB); + w0_y_v_fac = (y_factor & MASK(WIN0_VS_FACTOR_YRGB)) >> 16; + w0_uv_h_fac = uv_factor & MASK(WIN0_HS_FACTOR_CBR); + w0_uv_v_fac = (uv_factor & MASK(WIN0_VS_FACTOR_CBR)) >> 16; + + /* WIN1 */ + win_ctrl = vop_readl(vop_dev, WIN1_CTRL0); + w1_state = win_ctrl & MASK(WIN1_EN); + fmt_id = (win_ctrl & MASK(WIN1_DATA_FMT)) >> 1; + vop_format_to_string(fmt_id, format_w1); + vir_info = vop_readl(vop_dev, WIN1_VIR); + act_info = vop_readl(vop_dev, WIN1_ACT_INFO); + dsp_info = vop_readl(vop_dev, WIN1_DSP_INFO); + dsp_st = vop_readl(vop_dev, WIN1_DSP_ST); + y_factor = vop_readl(vop_dev, WIN1_SCL_FACTOR_YRGB); + uv_factor = vop_readl(vop_dev, WIN1_SCL_FACTOR_CBR); + w1_vir_y = vir_info & MASK(WIN1_VIR_STRIDE); + w1_vir_uv = (vir_info & MASK(WIN1_VIR_STRIDE_UV)) >> 16; + w1_act_x = (act_info & MASK(WIN1_ACT_WIDTH)) + 1; + w1_act_y = ((act_info & MASK(WIN1_ACT_HEIGHT)) >> 16) + 1; + w1_dsp_x = (dsp_info & MASK(WIN1_DSP_WIDTH)) + 1; + w1_dsp_y = ((dsp_info & MASK(WIN1_DSP_HEIGHT)) >> 16) + 1; + if (w1_state) { + w1_st_x = dsp_st & MASK(WIN1_DSP_XST); + w1_st_y = (dsp_st & MASK(WIN1_DSP_YST)) >> 16; + } + w1_y_h_fac = y_factor & MASK(WIN1_HS_FACTOR_YRGB); + w1_y_v_fac = (y_factor & MASK(WIN1_VS_FACTOR_YRGB)) >> 16; + w1_uv_h_fac = uv_factor & MASK(WIN1_HS_FACTOR_CBR); + w1_uv_v_fac = (uv_factor & MASK(WIN1_VS_FACTOR_CBR)) >> 16; + } else { + spin_unlock(&vop_dev->reg_lock); + return -EPERM; + } + spin_unlock(&vop_dev->reg_lock); + size += snprintf(dsp_buf, 80, + "z-order:\n win[%d]\n win[%d]\n", + layer1_sel, layer0_sel); + strcat(buf, dsp_buf); + memset(dsp_buf, 0, sizeof(dsp_buf)); + /* win0 */ + size += snprintf(dsp_buf, 80, + "win0:\n state:%d, fmt:%7s\n y_vir:%4d, uv_vir:%4d,", + w0_state, format_w0, w0_vir_y, w0_vir_uv); + strcat(buf, dsp_buf); + memset(dsp_buf, 0, sizeof(dsp_buf)); + + size += snprintf(dsp_buf, 80, + " x_act :%5d, y_act :%5d, dsp_x :%5d, dsp_y :%5d\n", + w0_act_x, w0_act_y, w0_dsp_x, w0_dsp_y); + strcat(buf, dsp_buf); + memset(dsp_buf, 0, sizeof(dsp_buf)); + + size += snprintf(dsp_buf, 80, + " x_st :%4d, y_st :%4d, y_h_fac:%5d, y_v_fac:%5d, ", + w0_st_x-h_pw_bp, w0_st_y-v_pw_bp, w0_y_h_fac, w0_y_v_fac); + strcat(buf, dsp_buf); + memset(dsp_buf, 0, sizeof(dsp_buf)); + + size += snprintf(dsp_buf, 80, + "uv_h_fac:%5d, uv_v_fac:%5d\n y_addr:0x%08x, uv_addr:0x%08x\n", + w0_uv_h_fac, w0_uv_v_fac, vop_readl(vop_dev, WIN0_YRGB_MST), + vop_readl(vop_dev, WIN0_CBR_MST)); + strcat(buf, dsp_buf); + memset(dsp_buf, 0, sizeof(dsp_buf)); + + /* win1 */ + size += snprintf(dsp_buf, 80, + "win1:\n state:%d, fmt:%7s\n y_vir:%4d, uv_vir:%4d,", + w1_state, format_w1, w1_vir_y, w1_vir_uv); + strcat(buf, dsp_buf); + memset(dsp_buf, 0, sizeof(dsp_buf)); + + size += snprintf(dsp_buf, 80, + " x_act :%5d, y_act :%5d, dsp_x :%5d, dsp_y :%5d\n", + w1_act_x, w1_act_y, w1_dsp_x, w1_dsp_y); + strcat(buf, dsp_buf); + memset(dsp_buf, 0, sizeof(dsp_buf)); + + size += snprintf(dsp_buf, 80, + " x_st :%4d, y_st :%4d, y_h_fac:%5d, y_v_fac:%5d, ", + w1_st_x-h_pw_bp, w1_st_y-v_pw_bp, w1_y_h_fac, w1_y_v_fac); + strcat(buf, dsp_buf); + memset(dsp_buf, 0, sizeof(dsp_buf)); + + size += snprintf(dsp_buf, 80, + "uv_h_fac:%5d, uv_v_fac:%5d\n y_addr:0x%08x, uv_addr:0x%08x\n", + w1_uv_h_fac, w1_uv_v_fac, vop_readl(vop_dev, WIN1_YRGB_MST), + vop_readl(vop_dev, WIN1_CBR_MST)); + strcat(buf, dsp_buf); + memset(dsp_buf, 0, sizeof(dsp_buf)); + + return size; +} + +static int vop_fps_mgr(struct rk_lcdc_driver *dev_drv, int fps, bool set) +{ + struct vop_device *vop_dev = + container_of(dev_drv, struct vop_device, driver); + struct rk_screen *screen = dev_drv->cur_screen; + u64 ft = 0; + u32 dotclk; + int ret; + u32 pixclock; + u32 x_total, y_total; + + if (set) { + if (fps == 0) { + dev_info(dev_drv->dev, "unsupport set fps=0\n"); + return 0; + } + ft = div_u64(1000000000000llu, fps); + x_total = + screen->mode.upper_margin + screen->mode.lower_margin + + screen->mode.yres + screen->mode.vsync_len; + y_total = + screen->mode.left_margin + screen->mode.right_margin + + 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(vop_dev->dclk, dotclk); + } + + pixclock = div_u64(1000000000000llu, clk_get_rate(vop_dev->dclk)); + vop_dev->pixclock = pixclock; + dev_drv->pixclock = vop_dev->pixclock; + fps = rk_fb_calc_fps(screen, pixclock); + screen->ft = 1000 / fps; /*one frame time in ms */ + + if (set) + dev_info(dev_drv->dev, "%s:dclk:%lu,fps:%d\n", __func__, + clk_get_rate(vop_dev->dclk), fps); + + return fps; +} + +static int vop_fb_win_remap(struct rk_lcdc_driver *dev_drv, u16 order) +{ + mutex_lock(&dev_drv->fb_win_id_mutex); + if (order == FB_DEFAULT_ORDER) + order = FB0_WIN0_FB1_WIN1_FB2_WIN2_FB3_WIN3_FB4_HWC; + dev_drv->fb4_win_id = order / 10000; + dev_drv->fb3_win_id = (order / 1000) % 10; + dev_drv->fb2_win_id = (order / 100) % 10; + dev_drv->fb1_win_id = (order / 10) % 10; + dev_drv->fb0_win_id = order % 10; + mutex_unlock(&dev_drv->fb_win_id_mutex); + + return 0; +} + +static int vop_get_win_id(struct rk_lcdc_driver *dev_drv, const char *id) +{ + int win_id = 0; + + mutex_lock(&dev_drv->fb_win_id_mutex); + if (!strcmp(id, "fb0") || !strcmp(id, "fb5")) + win_id = dev_drv->fb0_win_id; + else if (!strcmp(id, "fb1") || !strcmp(id, "fb6")) + win_id = dev_drv->fb1_win_id; + else if (!strcmp(id, "fb2") || !strcmp(id, "fb7")) + win_id = dev_drv->fb2_win_id; + else if (!strcmp(id, "fb3") || !strcmp(id, "fb8")) + win_id = dev_drv->fb3_win_id; + else if (!strcmp(id, "fb4") || !strcmp(id, "fb9")) + win_id = dev_drv->fb4_win_id; + mutex_unlock(&dev_drv->fb_win_id_mutex); + + return win_id; +} + +static int vop_config_done(struct rk_lcdc_driver *dev_drv) +{ + struct vop_device *vop_dev = + container_of(dev_drv, struct vop_device, driver); + int i; + u64 val; + struct rk_lcdc_win *win = NULL; + + spin_lock(&vop_dev->reg_lock); + vop_post_cfg(dev_drv); + vop_msk_reg(vop_dev, SYS_CTRL, V_VOP_STANDBY_EN(vop_dev->standby)); + for (i = 0; i < dev_drv->lcdc_win_num; i++) { + win = dev_drv->win[i]; + if ((win->state == 0) && (win->last_state == 1)) { + switch (win->id) { + case 0: + val = V_WIN0_EN(0); + vop_msk_reg(vop_dev, WIN0_CTRL0, val); + break; + case 1: + val = V_WIN1_EN(0); + vop_msk_reg(vop_dev, WIN1_CTRL0, val); + break; + case 2: + val = V_HWC_EN(0); + vop_msk_reg(vop_dev, HWC_CTRL0, val); + break; + default: + break; + } + } + win->last_state = win->state; + } + vop_cfg_done(vop_dev); + spin_unlock(&vop_dev->reg_lock); + return 0; +} + +static int vop_dpi_open(struct rk_lcdc_driver *dev_drv, bool open) +{ + struct vop_device *vop_dev = + container_of(dev_drv, struct vop_device, driver); + spin_lock(&vop_dev->reg_lock); + vop_msk_reg(vop_dev, SYS_CTRL, V_DIRECT_PATH_EN(open)); + vop_cfg_done(vop_dev); + spin_unlock(&vop_dev->reg_lock); + return 0; +} + +static int vop_dpi_win_sel(struct rk_lcdc_driver *dev_drv, int win_id) +{ + struct vop_device *vop_dev = container_of(dev_drv, + struct vop_device, driver); + spin_lock(&vop_dev->reg_lock); + vop_msk_reg(vop_dev, SYS_CTRL, V_DIRECT_PATH_LAYER_SEL(win_id)); + vop_cfg_done(vop_dev); + spin_unlock(&vop_dev->reg_lock); + return 0; +} + +static int vop_dpi_status(struct rk_lcdc_driver *dev_drv) +{ + struct vop_device *vop_dev = + container_of(dev_drv, struct vop_device, driver); + int ovl; + + spin_lock(&vop_dev->reg_lock); + ovl = vop_read_bit(vop_dev, SYS_CTRL, V_DIRECT_PATH_EN(0)); + spin_unlock(&vop_dev->reg_lock); + return ovl; +} + +static int vop_set_irq_to_cpu(struct rk_lcdc_driver *dev_drv, int enable) +{ + struct vop_device *vop_dev = + container_of(dev_drv, struct vop_device, driver); + if (enable) + enable_irq(vop_dev->irq); + else + disable_irq(vop_dev->irq); + return 0; +} + +int vop_poll_vblank(struct rk_lcdc_driver *dev_drv) +{ + struct vop_device *vop_dev = + container_of(dev_drv, struct vop_device, driver); + u32 int_reg; + int ret; + + if (vop_dev->clk_on && (!dev_drv->suspend_flag)) { + int_reg = vop_readl(vop_dev, INTR_STATUS0); + if (int_reg & INTR_LINE_FLAG0) { + vop_dev->driver.frame_time.last_framedone_t = + vop_dev->driver.frame_time.framedone_t; + vop_dev->driver.frame_time.framedone_t = cpu_clock(0); + vop_mask_writel(vop_dev, INTR_CLEAR0, INTR_LINE_FLAG0, + INTR_LINE_FLAG0); + ret = RK_LF_STATUS_FC; + } else { + ret = RK_LF_STATUS_FR; + } + } else { + ret = RK_LF_STATUS_NC; + } + + return ret; +} + +static int vop_get_dsp_addr(struct rk_lcdc_driver *dev_drv, + unsigned int dsp_addr[][4]) +{ + struct vop_device *vop_dev = + container_of(dev_drv, struct vop_device, driver); + spin_lock(&vop_dev->reg_lock); + if (vop_dev->clk_on) { + dsp_addr[0][0] = vop_readl(vop_dev, WIN0_YRGB_MST); + dsp_addr[1][0] = vop_readl(vop_dev, WIN1_YRGB_MST); + dsp_addr[2][0] = vop_readl(vop_dev, HWC_MST); + } + spin_unlock(&vop_dev->reg_lock); + return 0; +} + +static u32 pwm_period_hpr, pwm_duty_lpr; + +int vop_update_pwm(int bl_pwm_period, int bl_pwm_duty) +{ + pwm_period_hpr = bl_pwm_period; + pwm_duty_lpr = bl_pwm_duty; + /*pr_info("bl_pwm_period_hpr = 0x%x, bl_pwm_duty_lpr = 0x%x\n", + bl_pwm_period, bl_pwm_duty);*/ + return 0; +} + +/* + a:[-30~0]: + sin_hue = sin(a)*256 +0x100; + cos_hue = cos(a)*256; + a:[0~30] + sin_hue = sin(a)*256; + cos_hue = cos(a)*256; +*/ +static int vop_get_bcsh_hue(struct rk_lcdc_driver *dev_drv, bcsh_hue_mode mode) +{ +#if 1 + struct vop_device *vop_dev = + container_of(dev_drv, struct vop_device, driver); + u32 val; + + spin_lock(&vop_dev->reg_lock); + if (vop_dev->clk_on) { + val = vop_readl(vop_dev, BCSH_H); + switch (mode) { + case H_SIN: + val &= MASK(SIN_HUE); + break; + case H_COS: + val &= MASK(COS_HUE); + val >>= 16; + break; + default: + break; + } + } + spin_unlock(&vop_dev->reg_lock); + + return val; +#endif + return 0; +} + +static int vop_set_bcsh_hue(struct rk_lcdc_driver *dev_drv, + int sin_hue, int cos_hue) +{ + struct vop_device *vop_dev = + container_of(dev_drv, struct vop_device, driver); + u64 val; + + spin_lock(&vop_dev->reg_lock); + if (vop_dev->clk_on) { + val = V_SIN_HUE(sin_hue) | V_COS_HUE(cos_hue); + vop_msk_reg(vop_dev, BCSH_H, val); + vop_cfg_done(vop_dev); + } + spin_unlock(&vop_dev->reg_lock); + + return 0; +} + +static int vop_set_bcsh_bcs(struct rk_lcdc_driver *dev_drv, + bcsh_bcs_mode mode, int value) +{ + struct vop_device *vop_dev = + container_of(dev_drv, struct vop_device, driver); + u64 val; + + spin_lock(&vop_dev->reg_lock); + if (vop_dev->clk_on) { + switch (mode) { + case BRIGHTNESS: + /*from 0 to 255,typical is 128 */ + if (value < 0x80) + value += 0x80; + else if (value >= 0x80) + value = value - 0x80; + val = V_BRIGHTNESS(value); + break; + case CONTRAST: + /*from 0 to 510,typical is 256 */ + val = V_CONTRAST(value); + break; + case SAT_CON: + /*from 0 to 1015,typical is 256 */ + val = V_SAT_CON(value); + break; + default: + break; + } + vop_msk_reg(vop_dev, BCSH_BCS, val); + vop_cfg_done(vop_dev); + } + spin_unlock(&vop_dev->reg_lock); + + return val; +} + +static int vop_get_bcsh_bcs(struct rk_lcdc_driver *dev_drv, bcsh_bcs_mode mode) +{ + struct vop_device *vop_dev = + container_of(dev_drv, struct vop_device, driver); + u64 val; + + spin_lock(&vop_dev->reg_lock); + if (vop_dev->clk_on) { + val = vop_readl(vop_dev, BCSH_BCS); + switch (mode) { + case BRIGHTNESS: + val &= MASK(BRIGHTNESS); + if (val > 0x80) + val -= 0x80; + else + val += 0x80; + break; + case CONTRAST: + val &= MASK(CONTRAST); + val >>= 8; + break; + case SAT_CON: + val &= MASK(SAT_CON); + val >>= 20; + break; + default: + break; + } + } + spin_unlock(&vop_dev->reg_lock); + return val; +} + +static int vop_open_bcsh(struct rk_lcdc_driver *dev_drv, bool open) +{ + struct vop_device *vop_dev = + container_of(dev_drv, struct vop_device, driver); + + spin_lock(&vop_dev->reg_lock); + if (vop_dev->clk_on) { + if (open) { + vop_writel(vop_dev, BCSH_COLOR_BAR, 0x1); + vop_writel(vop_dev, BCSH_BCS, 0xd0010000); + vop_writel(vop_dev, BCSH_H, 0x01000000); + dev_drv->bcsh.enable = 1; + } else { + vop_msk_reg(vop_dev, BCSH_COLOR_BAR, V_BCSH_EN(0)); + dev_drv->bcsh.enable = 0; + } + vop_bcsh_path_sel(dev_drv); + vop_cfg_done(vop_dev); + } + spin_unlock(&vop_dev->reg_lock); + + return 0; +} + +static int vop_set_bcsh(struct rk_lcdc_driver *dev_drv, bool enable) +{ + if (!enable || !dev_drv->bcsh.enable) { + vop_open_bcsh(dev_drv, false); + return 0; + } + + if (dev_drv->bcsh.brightness <= 255 || + dev_drv->bcsh.contrast <= 510 || + dev_drv->bcsh.sat_con <= 1015 || + (dev_drv->bcsh.sin_hue <= 511 && dev_drv->bcsh.cos_hue <= 511)) { + vop_open_bcsh(dev_drv, true); + if (dev_drv->bcsh.brightness <= 255) + vop_set_bcsh_bcs(dev_drv, BRIGHTNESS, + dev_drv->bcsh.brightness); + if (dev_drv->bcsh.contrast <= 510) + vop_set_bcsh_bcs(dev_drv, CONTRAST, + dev_drv->bcsh.contrast); + if (dev_drv->bcsh.sat_con <= 1015) + vop_set_bcsh_bcs(dev_drv, SAT_CON, + dev_drv->bcsh.sat_con); + if (dev_drv->bcsh.sin_hue <= 511 && + dev_drv->bcsh.cos_hue <= 511) + vop_set_bcsh_hue(dev_drv, dev_drv->bcsh.sin_hue, + dev_drv->bcsh.cos_hue); + } + + return 0; +} + +static int __maybe_unused +vop_dsp_black(struct rk_lcdc_driver *dev_drv, int enable) +{ + struct vop_device *vop_dev = + container_of(dev_drv, struct vop_device, driver); + + if (enable) { + spin_lock(&vop_dev->reg_lock); + if (likely(vop_dev->clk_on)) { + vop_msk_reg(vop_dev, DSP_CTRL0, V_DSP_BLACK_EN(1)); + vop_cfg_done(vop_dev); + } + spin_unlock(&vop_dev->reg_lock); + } else { + spin_lock(&vop_dev->reg_lock); + if (likely(vop_dev->clk_on)) { + vop_msk_reg(vop_dev, DSP_CTRL0, V_DSP_BLACK_EN(0)); + + vop_cfg_done(vop_dev); + } + spin_unlock(&vop_dev->reg_lock); + } + + return 0; +} + +static int vop_backlight_close(struct rk_lcdc_driver *dev_drv, int enable) +{ + struct vop_device *vop_dev = + container_of(dev_drv, struct vop_device, driver); + + if (unlikely(!vop_dev->clk_on)) { + pr_info("%s,clk_on = %d\n", __func__, vop_dev->clk_on); + return 0; + } + vop_get_backlight_device(dev_drv); + + if (enable) { + /* close the backlight */ + if (vop_dev->backlight) { + vop_dev->backlight->props.power = FB_BLANK_POWERDOWN; + backlight_update_status(vop_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); + /* open the backlight */ + if (vop_dev->backlight) { + vop_dev->backlight->props.power = FB_BLANK_UNBLANK; + backlight_update_status(vop_dev->backlight); + } + } + + return 0; +} + +static int vop_set_overscan(struct rk_lcdc_driver *dev_drv, + struct overscan *overscan) +{ + struct vop_device *vop_dev = + container_of(dev_drv, struct vop_device, driver); + + if (unlikely(!vop_dev->clk_on)) { + pr_info("%s,clk_on = %d\n", __func__, vop_dev->clk_on); + return 0; + } + /*vop_post_cfg(dev_drv);*/ + + return 0; +} + +static struct rk_lcdc_drv_ops lcdc_drv_ops = { + .open = vop_open, + .win_direct_en = vop_win_direct_en, + .load_screen = vop_load_screen, + .get_dspbuf_info = vop_get_dspbuf_info, + .post_dspbuf = vop_post_dspbuf, + .set_par = vop_set_par, + .pan_display = vop_pan_display, + .direct_set_addr = vop_direct_set_win_addr, + /*.lcdc_reg_update = vop_reg_update,*/ + .blank = vop_blank, + .ioctl = vop_ioctl, + .suspend = vop_early_suspend, + .resume = vop_early_resume, + .get_win_state = vop_get_win_state, + .area_support_num = vop_get_area_num, + .ovl_mgr = vop_ovl_mgr, + .get_disp_info = vop_get_disp_info, + .fps_mgr = vop_fps_mgr, + .fb_get_win_id = vop_get_win_id, + .fb_win_remap = vop_fb_win_remap, + .poll_vblank = vop_poll_vblank, + .dpi_open = vop_dpi_open, + .dpi_win_sel = vop_dpi_win_sel, + .dpi_status = vop_dpi_status, + .get_dsp_addr = vop_get_dsp_addr, + .set_dsp_bcsh_hue = vop_set_bcsh_hue, + .set_dsp_bcsh_bcs = vop_set_bcsh_bcs, + .get_dsp_bcsh_hue = vop_get_bcsh_hue, + .get_dsp_bcsh_bcs = vop_get_bcsh_bcs, + .open_bcsh = vop_open_bcsh, + .dump_reg = vop_reg_dump, + .cfg_done = vop_config_done, + .set_irq_to_cpu = vop_set_irq_to_cpu, + /*.dsp_black = vop_dsp_black,*/ + .backlight_close = vop_backlight_close, + .mmu_en = vop_mmu_en, + .set_overscan = vop_set_overscan, +}; + +static irqreturn_t vop_isr(int irq, void *dev_id) +{ + struct vop_device *vop_dev = (struct vop_device *)dev_id; + ktime_t timestamp = ktime_get(); + u32 intr_status; + unsigned long flags; + + spin_lock_irqsave(&vop_dev->irq_lock, flags); + + intr_status = vop_readl(vop_dev, INTR_STATUS0); + vop_mask_writel(vop_dev, INTR_CLEAR0, INTR_MASK, intr_status); + + spin_unlock_irqrestore(&vop_dev->irq_lock, flags); + /* This is expected for vop iommu irqs, since the irq is shared */ + if (!intr_status) + return IRQ_NONE; + + if (intr_status & INTR_FS) { + timestamp = ktime_get(); + vop_dev->driver.vsync_info.timestamp = timestamp; + wake_up_interruptible_all(&vop_dev->driver.vsync_info.wait); + intr_status &= ~INTR_FS; + } + + if (intr_status & INTR_LINE_FLAG0) + intr_status &= ~INTR_LINE_FLAG0; + + if (intr_status & INTR_LINE_FLAG1) + intr_status &= ~INTR_LINE_FLAG1; + + if (intr_status & INTR_FS_NEW) + intr_status &= ~INTR_FS_NEW; + + if (intr_status & INTR_BUS_ERROR) { + intr_status &= ~INTR_BUS_ERROR; + dev_warn(vop_dev->dev, "bus error!"); + } + if (intr_status) + dev_err(vop_dev->dev, "Unknown VOP IRQs: %#02x\n", intr_status); + + return IRQ_HANDLED; +} + +#if defined(CONFIG_PM) +static int vop_suspend(struct platform_device *pdev, pm_message_t state) +{ + return 0; +} + +static int vop_resume(struct platform_device *pdev) +{ + return 0; +} +#else +#define vop_suspend NULL +#define vop_resume NULL +#endif + +static int vop_parse_dt(struct vop_device *vop_dev) +{ + struct device_node *np = vop_dev->dev->of_node; + struct rk_lcdc_driver *dev_drv = &vop_dev->driver; + int val; + + if (of_property_read_u32(np, "rockchip,prop", &val)) + vop_dev->prop = PRMRY; /*default set it as primary */ + else + vop_dev->prop = val; + + if (of_property_read_u32(np, "rockchip,mirror", &val)) + dev_drv->rotate_mode = NO_MIRROR; + else + dev_drv->rotate_mode = val; + + if (of_property_read_u32(np, "rockchip,pwr18", &val)) + /*default set it as 3.xv power supply */ + vop_dev->pwr18 = false; + else + vop_dev->pwr18 = (val ? true : false); + + if (of_property_read_u32(np, "rockchip,fb-win-map", &val)) + dev_drv->fb_win_map = FB_DEFAULT_ORDER; + else + dev_drv->fb_win_map = val; + + if (of_property_read_u32(np, "rockchip,bcsh-en", &val)) + dev_drv->bcsh.enable = false; + else + dev_drv->bcsh.enable = (val ? true : false); + + if (of_property_read_u32(np, "rockchip,brightness", &val)) + dev_drv->bcsh.brightness = 0xffff; + else + dev_drv->bcsh.brightness = val; + + if (of_property_read_u32(np, "rockchip,contrast", &val)) + dev_drv->bcsh.contrast = 0xffff; + else + dev_drv->bcsh.contrast = val; + + if (of_property_read_u32(np, "rockchip,sat-con", &val)) + dev_drv->bcsh.sat_con = 0xffff; + else + dev_drv->bcsh.sat_con = val; + + if (of_property_read_u32(np, "rockchip,hue", &val)) { + dev_drv->bcsh.sin_hue = 0xffff; + dev_drv->bcsh.cos_hue = 0xffff; + } else { + dev_drv->bcsh.sin_hue = val & 0xff; + dev_drv->bcsh.cos_hue = (val >> 8) & 0xff; + } + +#if defined(CONFIG_ROCKCHIP_IOMMU) + if (of_property_read_u32(np, "rockchip,iommu-enabled", &val)) + dev_drv->iommu_enabled = 0; + else + dev_drv->iommu_enabled = val; +#else + dev_drv->iommu_enabled = 0; +#endif + return 0; +} + +static int vop_probe(struct platform_device *pdev) +{ + struct vop_device *vop_dev = NULL; + struct rk_lcdc_driver *dev_drv; + struct device *dev = &pdev->dev; + struct resource *res; + struct device_node *np = pdev->dev.of_node; + int prop; + int ret = 0; + + /* if the primary lcdc has not registered ,the extend + * lcdc register later + */ + of_property_read_u32(np, "rockchip,prop", &prop); + if (prop == EXTEND) { + if (!is_prmry_rk_lcdc_registered()) + return -EPROBE_DEFER; + } + vop_dev = devm_kzalloc(dev, sizeof(struct vop_device), GFP_KERNEL); + if (!vop_dev) { + dev_err(&pdev->dev, "rk3228 lcdc device kmalloc fail!"); + return -ENOMEM; + } + platform_set_drvdata(pdev, vop_dev); + vop_dev->dev = dev; + vop_parse_dt(vop_dev); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + vop_dev->reg_phy_base = res->start; + vop_dev->len = resource_size(res); + vop_dev->regs = devm_ioremap_resource(dev, res); + if (IS_ERR(vop_dev->regs)) + return PTR_ERR(vop_dev->regs); + else + dev_info(dev, "vop_dev->regs=0x%lx\n", (long)vop_dev->regs); + + vop_dev->regsbak = devm_kzalloc(dev, vop_dev->len, GFP_KERNEL); + if (IS_ERR(vop_dev->regsbak)) + return PTR_ERR(vop_dev->regsbak); + + vop_dev->id = 0; + dev_set_name(vop_dev->dev, "vop%d", vop_dev->id); + dev_drv = &vop_dev->driver; + dev_drv->dev = dev; + dev_drv->prop = prop; + dev_drv->id = vop_dev->id; + dev_drv->ops = &lcdc_drv_ops; + dev_drv->lcdc_win_num = ARRAY_SIZE(vop_win); + dev_drv->reserved_fb = 1;/*only need reserved 1 buffer*/ + spin_lock_init(&vop_dev->reg_lock); + spin_lock_init(&vop_dev->irq_lock); + + vop_dev->irq = platform_get_irq(pdev, 0); + if (vop_dev->irq < 0) { + dev_err(&pdev->dev, "cannot find IRQ for lcdc%d\n", + vop_dev->id); + return -ENXIO; + } + + ret = devm_request_irq(dev, vop_dev->irq, vop_isr, + IRQF_DISABLED | IRQF_SHARED, + dev_name(dev), vop_dev); + if (ret) { + dev_err(&pdev->dev, "cannot requeset irq %d - err %d\n", + vop_dev->irq, ret); + return ret; + } + + if (dev_drv->iommu_enabled) + strcpy(dev_drv->mmu_dts_name, VOP_IOMMU_COMPATIBLE_NAME); + + ret = rk_fb_register(dev_drv, vop_win, vop_dev->id); + if (ret < 0) { + dev_err(dev, "register fb for lcdc%d failed!\n", vop_dev->id); + return ret; + } + vop_dev->screen = dev_drv->screen0; + dev_info(dev, "lcdc%d probe ok, iommu %s\n", + vop_dev->id, dev_drv->iommu_enabled ? "enabled" : "disabled"); + + return 0; +} + +static int vop_remove(struct platform_device *pdev) +{ + return 0; +} + +static void vop_shutdown(struct platform_device *pdev) +{ + struct vop_device *vop_dev = platform_get_drvdata(pdev); + struct rk_lcdc_driver *dev_drv = &vop_dev->driver; + + dev_drv->suspend_flag = 1; + mdelay(100); + flush_kthread_worker(&dev_drv->update_regs_worker); + kthread_stop(dev_drv->update_regs_thread); + vop_deint(vop_dev); + /*if (dev_drv->trsm_ops && dev_drv->trsm_ops->disable) + dev_drv->trsm_ops->disable();*/ + + vop_clk_disable(vop_dev); + rk_disp_pwr_disable(dev_drv); +} + +#if defined(CONFIG_OF) +static const struct of_device_id vop_dt_ids[] = { + {.compatible = "rockchip,rk3228-lcdc",}, + {} +}; +#endif + +static struct platform_driver vop_driver = { + .probe = vop_probe, + .remove = vop_remove, + .driver = { + .name = "rk3228-lcdc", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(vop_dt_ids), + }, + .suspend = vop_suspend, + .resume = vop_resume, + .shutdown = vop_shutdown, +}; + +static int __init vop_module_init(void) +{ + return platform_driver_register(&vop_driver); +} + +static void __exit vop_module_exit(void) +{ + platform_driver_unregister(&vop_driver); +} + +fs_initcall(vop_module_init); +module_exit(vop_module_exit); diff --git a/drivers/video/rockchip/lcdc/rk3228_lcdc.h b/drivers/video/rockchip/lcdc/rk3228_lcdc.h new file mode 100644 index 000000000000..9df5760967fe --- /dev/null +++ b/drivers/video/rockchip/lcdc/rk3228_lcdc.h @@ -0,0 +1,1676 @@ +#ifndef RK3228_LCDC_H_ +#define RK3228_LCDC_H_ + +#include +#include +#include +#include +#include + +#define VOP_INPUT_MAX_WIDTH 4096 +/* + * Registers in this file + * REG_CFG_DONE: Register config done flag + * VERSION_INFO: Version for vop + * SYS_CTRL: System control register0 + * SYS_CTRL1: System control register1 + * DSP_CTRL0: Display control register0 + * DSP_CTRL1: Display control register1 + * DSP_BG: Background color + * MCU_CTRL: MCU mode control register + * WB_CTRL0: write back ctrl0 + * WB_CTRL1: write back ctrl1 + * WB_YRGB_MST: write back yrgb mst + * WB_CBR_MST: write back cbr mst + * WIN0_CTRL0: Win0 ctrl register0 + * WIN0_CTRL1: Win0 ctrl register1 + * WIN0_COLOR_KEY: Win0 color key register + * WIN0_VIR: Win0 virtual stride + * WIN0_YRGB_MST: Win0 YRGB memory start address + * WIN0_CBR_MST: Win0 Cbr memory start address + * WIN0_ACT_INFO: Win0 active window width/height + * WIN0_DSP_INFO: Win0 display width/height on panel + * WIN0_DSP_ST: Win0 display start point on panel + * WIN0_SCL_FACTOR_YRGB: Win0 YRGB scaling factor + * WIN0_SCL_FACTOR_CBR: Win0 Cbr scaling factor + * WIN0_SCL_OFFSET: Win0 scaling start point offset + * WIN0_SRC_ALPHA_CTRL: Win0 alpha source control register + * WIN0_DST_ALPHA_CTRL: Win0 alpha destination control register + * WIN0_FADING_CTRL: Win0 fading contrl register + * WIN0_CTRL2: Win0 ctrl register2 + * WIN1_CTRL0: Win1 ctrl register0 + * WIN1_CTRL1: Win1 ctrl register1 + * WIN1_COLOR_KEY: Win1 color key register + * WIN1_VIR: win1 virtual stride + * WIN1_YRGB_MST: Win1 YRGB memory start address + * WIN1_CBR_MST: Win1 Cbr memory start address + * WIN1_ACT_INFO: Win1 active window width/height + * WIN1_DSP_INFO: Win1 display width/height on panel + * WIN1_DSP_ST: Win1 display start point on panel + * WIN1_SCL_FACTOR_YRGB: Win1 YRGB scaling factor + * WIN1_SCL_FACTOR_CBR: Win1 Cbr scaling factor + * WIN1_SCL_OFFSET: Win1 scaling start point offset + * WIN1_SRC_ALPHA_CTRL: Win1 alpha source control register + * WIN1_DST_ALPHA_CTRL: Win1 alpha destination control register + * WIN1_FADING_CTRL: Win1 fading contrl register + * WIN1_CTRL2: Win1 ctrl register2 + * WIN2_CTRL0: win2 ctrl register0 + * WIN2_CTRL1: win2 ctrl register1 + * WIN2_VIR0_1: Win2 virtual stride0 and virtaul stride1 + * WIN2_VIR2_3: Win2 virtual stride2 and virtaul stride3 + * WIN2_MST0: Win2 memory start address0 + * WIN2_DSP_INFO0: Win2 display width0/height0 on panel + * WIN2_DSP_ST0: Win2 display start point0 on panel + * WIN2_COLOR_KEY: Win2 color key register + * WIN2_MST1: Win2 memory start address1 + * WIN2_DSP_INFO1: Win2 display width1/height1 on panel + * WIN2_DSP_ST1: Win2 display start point1 on panel + * WIN2_SRC_ALPHA_CTRL: Win2 alpha source control register + * WIN2_MST2: Win2 memory start address2 + * WIN2_DSP_INFO2: Win2 display width2/height2 on panel + * WIN2_DSP_ST2: Win2 display start point2 on panel + * WIN2_DST_ALPHA_CTRL: Win2 alpha destination control register + * WIN2_MST3: Win2 memory start address3 + * WIN2_DSP_INFO3: Win2 display width3/height3 on panel + * WIN2_DSP_ST3: Win2 display start point3 on panel + * WIN2_FADING_CTRL: Win2 fading contrl register + * WIN3_CTRL0: Win3 ctrl register0 + * WIN3_CTRL1: Win3 ctrl register1 + * WIN3_VIR0_1: Win3 virtual stride0 and virtaul stride1 + * WIN3_VIR2_3: Win3 virtual stride2 and virtaul stride3 + * WIN3_MST0: Win3 memory start address0 + * WIN3_DSP_INFO0: Win3 display width0/height0 on panel + * WIN3_DSP_ST0: Win3 display start point0 on panel + * WIN3_COLOR_KEY: Win3 color key register + * WIN3_MST1: Win3 memory start address1 + * WIN3_DSP_INFO1: Win3 display width1/height1 on panel + * WIN3_DSP_ST1: Win3 display start point1 on panel + * WIN3_SRC_ALPHA_CTRL: Win3 alpha source control register + * WIN3_MST2: Win3 memory start address2 + * WIN3_DSP_INFO2: Win3 display width2/height2 on panel + * WIN3_DSP_ST2: Win3 display start point2 on panel + * WIN3_DST_ALPHA_CTRL: Win3 alpha destination control register + * WIN3_MST3: Win3 memory start address3 + * WIN3_DSP_INFO3: Win3 display width3/height3 on panel + * WIN3_DSP_ST3: Win3 display start point3 on panel + * WIN3_FADING_CTRL: Win3 fading contrl register + * HWC_CTRL0: Hwc ctrl register0 + * HWC_CTRL1: Hwc ctrl register1 + * HWC_MST: Hwc memory start address + * HWC_DSP_ST: Hwc display start point on panel + * HWC_SRC_ALPHA_CTRL: Hwc alpha source control register + * HWC_DST_ALPHA_CTRL: Hwc alpha destination control register + * HWC_FADING_CTRL: Hwc fading contrl register + * HWC_RESERVED1: Hwc reserved + * POST_DSP_HACT_INFO: Post scaler down horizontal start and end + * POST_DSP_VACT_INFO: Panel active horizontal scanning start point + * and end point + * POST_SCL_FACTOR_YRGB: Post yrgb scaling factor + * POST_RESERVED: Post reserved + * POST_SCL_CTRL: Post scaling start point offset + * POST_DSP_VACT_INFO_F1: Panel active horizontal scanning start point + * and end point F1 + * DSP_HTOTAL_HS_END: Panel scanning horizontal width and hsync pulse end point + * DSP_HACT_ST_END: Panel active horizontal scanning start point and end point + * DSP_VTOTAL_VS_END: Panel scanning vertical height and vsync pulse end point + * DSP_VACT_ST_END: Panel active vertical scanning start point and end point + * DSP_VS_ST_END_F1: Vertical scanning start point and vsync pulse end point + * of even filed in interlace mode + * DSP_VACT_ST_END_F1: Vertical scanning active start point and end point of + * even filed in interlace mode + * PWM_CTRL: PWM Control Register + * PWM_PERIOD_HPR: PWM Period Register/High Polarity Capture Register + * PWM_DUTY_LPR: PWM Duty Register/Low Polarity Capture Register + * PWM_CNT: PWM Counter Register + * BCSH_COLOR_BAR: Color bar config register + * BCSH_BCS: Brightness contrast saturation*contrast config register + * BCSH_H: Sin hue and cos hue config register + * BCSH_CTRL: BCSH contrl register + * CABC_CTRL0: Content Adaptive Backlight Control register0 + * CABC_CTRL1: Content Adaptive Backlight Control register1 + * CABC_CTRL2: Content Adaptive Backlight Control register2 + * CABC_CTRL3: Content Adaptive Backlight Control register3 + * CABC_GAUSS_LINE0_0: CABC gauss line config register00 + * CABC_GAUSS_LINE0_1: CABC gauss line config register01 + * CABC_GAUSS_LINE1_0: CABC gauss line config register10 + * CABC_GAUSS_LINE1_1: CABC gauss line config register11 + * CABC_GAUSS_LINE2_0: CABC gauss line config register20 + * CABC_GAUSS_LINE2_1: CABC gauss line config register21 + * FRC_LOWER01_0: FRC lookup table config register010 + * FRC_LOWER01_1: FRC lookup table config register011 + * FRC_LOWER10_0: FRC lookup table config register100 + * FRC_LOWER10_1: FRC lookup table config register101 + * FRC_LOWER11_0: FRC lookup table config register110 + * FRC_LOWER11_1: FRC lookup table config register111 + * AFBCD0_CTRL: + * AFBCD0_HDR_PTR: + * AFBCD0_PIC_SIZE: + * AFBCD0_STATUS: + * AFBCD1_CTRL: + * AFBCD1_HDR_PTR: + * AFBCD1_PIC_SIZE: + * AFBCD1_STATUS: + * AFBCD2_CTRL: + * AFBCD2_HDR_PTR: + * AFBCD2_PIC_SIZE: + * AFBCD2_STATUS: + * AFBCD3_CTRL: + * AFBCD3_HDR_PTR: + * AFBCD3_PIC_SIZE: + * AFBCD3_STATUS: + * INTR_EN0: Interrupt enable register + * INTR_CLEAR0: Interrupt clear register + * INTR_STATUS0: interrupt status + * INTR_RAW_STATUS0: raw interrupt status + * INTR_EN1: Interrupt enable register + * INTR_CLEAR1: Interrupt clear register + * INTR_STATUS1: interrupt status + * INTR_RAW_STATUS1: raw interrupt status + * LINE_FLAG: Line flag config register + * VOP_STATUS: vop status register + * BLANKING_VALUE: Register0000 Abstract + * WIN0_DSP_BG: Win0 layer background color + * WIN1_DSP_BG: Win1 layer background color + * WIN2_DSP_BG: Win2 layer background color + * WIN3_DSP_BG: Win3 layer background color + * DBG_PERF_LATENCY_CTRL0: Axi performance latency module contrl register0 + * DBG_PERF_RD_MAX_LATENCY_NUM0: Read max latency number + * DBG_PERF_RD_LATENCY_THR_NUM0: The number of bigger than configed + * threshold value + * DBG_PERF_RD_LATENCY_SAMP_NUM0: Total sample number + * DBG_CABC0: CABC debug register0 + * DBG_CABC1: CABC debug register1 + * DBG_CABC2: CABC debug register2 + * DBG_CABC3: CABC debug register3 + * DBG_WIN0_REG0: Vop debug win0 register0 + * DBG_WIN0_REG1: Vop debug win0 register1 + * DBG_WIN0_REG2: Vop debug win0 register2 + * DBG_WIN0_RESERVED: Vop debug win0 register3 reserved + * DBG_WIN1_REG0: Vop debug win1 register0 + * DBG_WIN1_REG1: Vop debug win1 register1 + * DBG_WIN1_REG2: Vop debug win1 register2 + * DBG_WIN1_RESERVED: Vop debug win1 register3 reserved + * DBG_WIN2_REG0: Vop debug win2 register0 + * DBG_WIN2_REG1: Vop debug win2 register1 + * DBG_WIN2_REG2: Vop debug win2 register2 + * DBG_WIN2_REG3: Vop debug win2 register3 + * DBG_WIN3_REG0: Vop debug win3 register0 + * DBG_WIN3_REG1: Vop debug win3 register1 + * DBG_WIN3_REG2: Vop debug win3 register2 + * DBG_WIN3_REG3: Vop debug win3 register3 + * DBG_PRE_REG0: Vop debug pre register0 + * DBG_PRE_RESERVED: Vop debug pre register1 reserved + * DBG_POST_REG0: Vop debug post register0 + * DBG_POST_RESERVED: Vop debug post register1 reserved + * DBG_DATAO: debug data output path + * DBG_DATAO_2: debug data output path 2 + * WIN2_LUT_ADDR: Win2 lut base address + * WIN3_LUT_ADDR: Win3 lut base address + * HWC_LUT_ADDR: Hwc lut base address + * GAMMA0_LUT_ADDR: GAMMA lut base address + * GAMMA1_LUT_ADDR: GAMMA lut base address + * CABC_GAMMA_LUT_ADDR: CABC GAMMA lut base address + * MCU_BYPASS_WPORT: + * MCU_BYPASS_RPORT: + */ + +static inline u64 val_mask(int val, u64 msk, int shift) +{ + return (msk << (shift + 32)) | ((msk & val) << shift); +} + +#define VAL_MASK(x, width, shift) val_mask(x, (1 << width) - 1, shift) + +#define MASK(x) (V_##x(0) >> 32) + +#define REG_CFG_DONE 0x00000000 +#define V_REG_LOAD_EN(x) VAL_MASK(x, 1, 0) +#define V_REG_LOAD_WIN0_EN(x) VAL_MASK(x, 1, 1) +#define V_REG_LOAD_WIN1_EN(x) VAL_MASK(x, 1, 2) +#define V_REG_LOAD_WIN2_EN(x) VAL_MASK(x, 1, 3) +#define V_REG_LOAD_WIN3_EN(x) VAL_MASK(x, 1, 4) +#define V_REG_LOAD_HWC_EN(x) VAL_MASK(x, 1, 5) +#define V_REG_LOAD_IEP_EN(x) VAL_MASK(x, 1, 6) +#define V_REG_LOAD_FBDC_EN(x) VAL_MASK(x, 1, 7) +#define V_REG_LOAD_SYS_EN(x) VAL_MASK(x, 1, 8) +#define V_WRITE_MASK(x) VAL_MASK(x, 16, 16) +#define VERSION_INFO 0x00000004 +#define V_SVNBUILD(x) VAL_MASK(x, 16, 0) +#define V_MINOR(x) VAL_MASK(x, 8, 16) +#define V_MAJOR(x) VAL_MASK(x, 8, 24) +#define SYS_CTRL 0x00000008 +#define V_DIRECT_PATH_EN(x) VAL_MASK(x, 1, 0) +#define V_DIRECT_PATH_LAYER_SEL(x) VAL_MASK(x, 2, 1) +#define V_EDPI_HALT_EN(x) VAL_MASK(x, 1, 8) +#define V_EDPI_WMS_MODE(x) VAL_MASK(x, 1, 9) +#define V_EDPI_WMS_FS(x) VAL_MASK(x, 1, 10) +#define V_GLOBAL_REGDONE_EN(x) VAL_MASK(x, 1, 11) +#define V_RGB_OUT_EN(x) VAL_MASK(x, 1, 12) +#define V_HDMI_OUT_EN(x) VAL_MASK(x, 1, 13) +#define V_EDP_OUT_EN(x) VAL_MASK(x, 1, 14) +#define V_MIPI_OUT_EN(x) VAL_MASK(x, 1, 15) +#define V_OVERLAY_MODE(x) VAL_MASK(x, 1, 16) +#define V_FS_SAME_ADDR_MASK_EN(x) VAL_MASK(x, 1, 17) +#define V_POST_LB_MODE(x) VAL_MASK(x, 1, 18) +#define V_WIN23_PRI_OPT_MODE(x) VAL_MASK(x, 1, 19) +#define V_VOP_MMU_EN(x) VAL_MASK(x, 1, 20) +#define V_VOP_DMA_STOP(x) VAL_MASK(x, 1, 21) +#define V_VOP_STANDBY_EN(x) VAL_MASK(x, 1, 22) +#define V_AUTO_GATING_EN(x) VAL_MASK(x, 1, 23) +#define V_SW_IMD_TVE_DCLK_EN(x) VAL_MASK(x, 1, 24) +#define V_SW_IMD_TVE_DCLK_POL(x) VAL_MASK(x, 1, 25) +#define V_SW_TVE_MODE(x) VAL_MASK(x, 1, 26) +#define V_SW_UV_OFFSET_EN(x) VAL_MASK(x, 1, 27) +#define V_SW_GENLOCK(x) VAL_MASK(x, 1, 28) +#define V_SW_DAC_SEL(x) VAL_MASK(x, 1, 29) +#define V_VOP_FIELD_TVE_POL(x) VAL_MASK(x, 1, 30) +#define V_IO_PAD_CLK_SEL(x) VAL_MASK(x, 1, 31) +#define SYS_CTRL1 0x0000000c +#define V_NOC_HURRY_EN(x) VAL_MASK(x, 1, 0) +#define V_NOC_HURRY_VALUE(x) VAL_MASK(x, 2, 1) +#define V_NOC_HURRY_THRESHOLD(x) VAL_MASK(x, 6, 3) +#define V_NOC_QOS_EN(x) VAL_MASK(x, 1, 9) +#define V_NOC_WIN_QOS(x) VAL_MASK(x, 2, 10) +#define V_AXI_MAX_OUTSTANDING_EN(x) VAL_MASK(x, 1, 12) +#define V_AXI_OUTSTANDING_MAX_NUM(x) VAL_MASK(x, 5, 13) +#define V_NOC_HURRY_W_MODE(x) VAL_MASK(x, 2, 20) +#define V_NOC_HURRY_W_VALUE(x) VAL_MASK(x, 2, 22) +#define V_DSP_FP_STANDBY(x) VAL_MASK(x, 1, 31) +#define DSP_CTRL0 0x00000010 +#define V_DSP_OUT_MODE(x) VAL_MASK(x, 4, 0) +#define V_SW_CORE_DCLK_SEL(x) VAL_MASK(x, 1, 4) +#define V_SW_HDMI_CLK_I_SEL(x) VAL_MASK(x, 1, 5) +#define V_DSP_DCLK_DDR(x) VAL_MASK(x, 1, 8) +#define V_DSP_DDR_PHASE(x) VAL_MASK(x, 1, 9) +#define V_DSP_INTERLACE(x) VAL_MASK(x, 1, 10) +#define V_DSP_FIELD_POL(x) VAL_MASK(x, 1, 11) +#define V_DSP_BG_SWAP(x) VAL_MASK(x, 1, 12) +#define V_DSP_RB_SWAP(x) VAL_MASK(x, 1, 13) +#define V_DSP_RG_SWAP(x) VAL_MASK(x, 1, 14) +#define V_DSP_DELTA_SWAP(x) VAL_MASK(x, 1, 15) +#define V_DSP_DUMMY_SWAP(x) VAL_MASK(x, 1, 16) +#define V_DSP_OUT_ZERO(x) VAL_MASK(x, 1, 17) +#define V_DSP_BLANK_EN(x) VAL_MASK(x, 1, 18) +#define V_DSP_BLACK_EN(x) VAL_MASK(x, 1, 19) +#define V_DSP_CCIR656_AVG(x) VAL_MASK(x, 1, 20) +#define V_DSP_YUV_CLIP(x) VAL_MASK(x, 1, 21) +#define V_DSP_X_MIR_EN(x) VAL_MASK(x, 1, 22) +#define V_DSP_Y_MIR_EN(x) VAL_MASK(x, 1, 23) +#define V_DSP_FIELD(x) VAL_MASK(x, 1, 31) +#define DSP_CTRL1 0x00000014 +#define V_DSP_LUT_EN(x) VAL_MASK(x, 1, 0) +#define V_PRE_DITHER_DOWN_EN(x) VAL_MASK(x, 1, 1) +#define V_DITHER_DOWN_EN(x) VAL_MASK(x, 1, 2) +#define V_DITHER_DOWN_MODE(x) VAL_MASK(x, 1, 3) +#define V_DITHER_DOWN_SEL(x) VAL_MASK(x, 1, 4) +#define V_DITHER_UP_EN(x) VAL_MASK(x, 1, 6) +#define V_UPDATE_GAMMA_LUT(x) VAL_MASK(x, 1, 7) +#define V_DSP_LAYER0_SEL(x) VAL_MASK(x, 2, 8) +#define V_DSP_LAYER1_SEL(x) VAL_MASK(x, 2, 10) +#define V_DSP_LAYER2_SEL(x) VAL_MASK(x, 2, 12) +#define V_DSP_LAYER3_SEL(x) VAL_MASK(x, 2, 14) +#define V_RGB_LVDS_HSYNC_POL(x) VAL_MASK(x, 1, 16) +#define V_RGB_LVDS_VSYNC_POL(x) VAL_MASK(x, 1, 17) +#define V_RGB_LVDS_DEN_POL(x) VAL_MASK(x, 1, 18) +#define V_RGB_LVDS_DCLK_POL(x) VAL_MASK(x, 1, 19) +#define V_HDMI_HSYNC_POL(x) VAL_MASK(x, 1, 20) +#define V_HDMI_VSYNC_POL(x) VAL_MASK(x, 1, 21) +#define V_HDMI_DEN_POL(x) VAL_MASK(x, 1, 22) +#define V_HDMI_DCLK_POL(x) VAL_MASK(x, 1, 23) +#define V_EDP_HSYNC_POL(x) VAL_MASK(x, 1, 24) +#define V_EDP_VSYNC_POL(x) VAL_MASK(x, 1, 25) +#define V_EDP_DEN_POL(x) VAL_MASK(x, 1, 26) +#define V_EDP_DCLK_POL(x) VAL_MASK(x, 1, 27) +#define V_MIPI_HSYNC_POL(x) VAL_MASK(x, 1, 28) +#define V_MIPI_VSYNC_POL(x) VAL_MASK(x, 1, 29) +#define V_MIPI_DEN_POL(x) VAL_MASK(x, 1, 30) +#define V_MIPI_DCLK_POL(x) VAL_MASK(x, 1, 31) +#define DSP_BG 0x00000018 +#define V_DSP_BG_BLUE(x) VAL_MASK(x, 8, 0) +#define V_DSP_BG_GREEN(x) VAL_MASK(x, 8, 8) +#define V_DSP_BG_RED(x) VAL_MASK(x, 8, 16) +#define MCU_CTRL 0x0000001c +#define V_MCU_PIX_TOTAL(x) VAL_MASK(x, 6, 0) +#define V_MCU_CS_PST(x) VAL_MASK(x, 4, 6) +#define V_MCU_CS_PEND(x) VAL_MASK(x, 6, 10) +#define V_MCU_RW_PST(x) VAL_MASK(x, 4, 16) +#define V_MCU_RW_PEND(x) VAL_MASK(x, 6, 20) +#define V_MCU_CLK_SEL(x) VAL_MASK(x, 1, 26) +#define V_MCU_HOLD_MODE(x) VAL_MASK(x, 1, 27) +#define V_MCU_FRAME_ST(x) VAL_MASK(x, 1, 28) +#define V_MCU_RS(x) VAL_MASK(x, 1, 29) +#define V_MCU_BYPASS(x) VAL_MASK(x, 1, 30) +#define V_MCU_TYPE(x) VAL_MASK(x, 1, 31) +#define WB_CTRL0 0x00000020 +#define V_WB_EN(x) VAL_MASK(x, 1, 0) +#define V_WB_FMT(x) VAL_MASK(x, 3, 1) +#define V_WB_DITHER_EN(x) VAL_MASK(x, 1, 4) +#define V_WB_RGB2YUV_EN(x) VAL_MASK(x, 1, 5) +#define V_WB_RGB2YUV_MODE(x) VAL_MASK(x, 1, 6) +#define V_WB_XPSD_BIL_EN(x) VAL_MASK(x, 1, 7) +#define V_WB_YTHROW_EN(x) VAL_MASK(x, 1, 8) +#define V_WB_YTHROW_MODE(x) VAL_MASK(x, 1, 9) +#define V_WB_HANDSHAKE_MODE(x) VAL_MASK(x, 1, 11) +#define V_WB_YRGB_ID(x) VAL_MASK(x, 4, 24) +#define V_WB_UV_ID(x) VAL_MASK(x, 4, 28) +#define WB_CTRL1 0x00000024 +#define V_WB_WIDTH(x) VAL_MASK(x, 12, 0) +#define V_WB_XPSD_BIL_FACTOR(x) VAL_MASK(x, 14, 16) +#define WB_YRGB_MST 0x00000028 +#define V_WB_YRGB_MST(x) VAL_MASK(x, 32, 0) +#define WB_CBR_MST 0x0000002c +#define V_WB_CBR_MST(x) VAL_MASK(x, 32, 0) +#define WIN0_CTRL0 0x00000030 +#define V_WIN0_EN(x) VAL_MASK(x, 1, 0) +#define V_WIN0_DATA_FMT(x) VAL_MASK(x, 3, 1) +#define V_WIN0_FMT_10(x) VAL_MASK(x, 1, 4) +#define V_WIN0_LB_MODE(x) VAL_MASK(x, 3, 5) +#define V_WIN0_INTERLACE_READ(x) VAL_MASK(x, 1, 8) +#define V_WIN0_NO_OUTSTANDING(x) VAL_MASK(x, 1, 9) +#define V_WIN0_CSC_MODE(x) VAL_MASK(x, 2, 10) +#define V_WIN0_RB_SWAP(x) VAL_MASK(x, 1, 12) +#define V_WIN0_ALPHA_SWAP(x) VAL_MASK(x, 1, 13) +#define V_WIN0_MID_SWAP(x) VAL_MASK(x, 1, 14) +#define V_WIN0_UV_SWAP(x) VAL_MASK(x, 1, 15) +#define V_WIN0_HW_PRE_MUL_EN(x) VAL_MASK(x, 1, 16) +#define V_WIN0_YRGB_DEFLICK(x) VAL_MASK(x, 1, 18) +#define V_WIN0_CBR_DEFLICK(x) VAL_MASK(x, 1, 19) +#define V_WIN0_YUV_CLIP(x) VAL_MASK(x, 1, 20) +#define V_WIN0_X_MIR_EN(x) VAL_MASK(x, 1, 21) +#define V_WIN0_Y_MIR_EN(x) VAL_MASK(x, 1, 22) +#define V_WIN0_AXI_MAX_OUTSTANDING_EN(x) VAL_MASK(x, 1, 24) +#define V_WIN0_AXI_OUTSTANDING_MAX_NUM(x) VAL_MASK(x, 5, 25) +#define V_WIN0_DMA_BURST_LENGTH(x) VAL_MASK(x, 2, 30) +#define WIN0_CTRL1 0x00000034 +#define V_WIN0_YRGB_AXI_GATHER_EN(x) VAL_MASK(x, 1, 0) +#define V_WIN0_CBR_AXI_GATHER_EN(x) VAL_MASK(x, 1, 1) +#define V_WIN0_BIC_COE_SEL(x) VAL_MASK(x, 2, 2) +#define V_WIN0_VSD_YRGB_GT4(x) VAL_MASK(x, 1, 4) +#define V_WIN0_VSD_YRGB_GT2(x) VAL_MASK(x, 1, 5) +#define V_WIN0_VSD_CBR_GT4(x) VAL_MASK(x, 1, 6) +#define V_WIN0_VSD_CBR_GT2(x) VAL_MASK(x, 1, 7) +#define V_WIN0_YRGB_AXI_GATHER_NUM(x) VAL_MASK(x, 4, 8) +#define V_WIN0_CBR_AXI_GATHER_NUM(x) VAL_MASK(x, 3, 12) +#define V_WIN0_LINE_LOAD_MODE(x) VAL_MASK(x, 1, 15) +#define V_WIN0_YRGB_HOR_SCL_MODE(x) VAL_MASK(x, 2, 16) +#define V_WIN0_YRGB_VER_SCL_MODE(x) VAL_MASK(x, 2, 18) +#define V_WIN0_YRGB_HSD_MODE(x) VAL_MASK(x, 2, 20) +#define V_WIN0_YRGB_VSU_MODE(x) VAL_MASK(x, 1, 22) +#define V_WIN0_YRGB_VSD_MODE(x) VAL_MASK(x, 1, 23) +#define V_WIN0_CBR_HOR_SCL_MODE(x) VAL_MASK(x, 2, 24) +#define V_WIN0_CBR_VER_SCL_MODE(x) VAL_MASK(x, 2, 26) +#define V_WIN0_CBR_HSD_MODE(x) VAL_MASK(x, 2, 28) +#define V_WIN0_CBR_VSU_MODE(x) VAL_MASK(x, 1, 30) +#define V_WIN0_CBR_VSD_MODE(x) VAL_MASK(x, 1, 31) +#define WIN0_COLOR_KEY 0x00000038 +#define V_WIN0_KEY_COLOR(x) VAL_MASK(x, 24, 0) +#define V_WIN0_KEY_EN(x) VAL_MASK(x, 1, 31) +#define WIN0_VIR 0x0000003c +#define V_WIN0_VIR_STRIDE(x) VAL_MASK(x, 16, 0) +#define V_WIN0_VIR_STRIDE_UV(x) VAL_MASK(x, 16, 16) +#define WIN0_YRGB_MST 0x00000040 +#define V_WIN0_YRGB_MST(x) VAL_MASK(x, 32, 0) +#define WIN0_CBR_MST 0x00000044 +#define V_WIN0_CBR_MST(x) VAL_MASK(x, 32, 0) +#define WIN0_ACT_INFO 0x00000048 +#define V_WIN0_ACT_WIDTH(x) VAL_MASK(x, 13, 0) +#define V_FIELD0002(x) VAL_MASK(x, 1, 13) +#define V_FIELD0001(x) VAL_MASK(x, 1, 14) +#define V_FIELD0000(x) VAL_MASK(x, 1, 15) +#define V_WIN0_ACT_HEIGHT(x) VAL_MASK(x, 13, 16) +#define WIN0_DSP_INFO 0x0000004c +#define V_WIN0_DSP_WIDTH(x) VAL_MASK(x, 12, 0) +#define V_WIN0_DSP_HEIGHT(x) VAL_MASK(x, 12, 16) +#define WIN0_DSP_ST 0x00000050 +#define V_WIN0_DSP_XST(x) VAL_MASK(x, 13, 0) +#define V_WIN0_DSP_YST(x) VAL_MASK(x, 13, 16) +#define WIN0_SCL_FACTOR_YRGB 0x00000054 +#define V_WIN0_HS_FACTOR_YRGB(x) VAL_MASK(x, 16, 0) +#define V_WIN0_VS_FACTOR_YRGB(x) VAL_MASK(x, 16, 16) +#define WIN0_SCL_FACTOR_CBR 0x00000058 +#define V_WIN0_HS_FACTOR_CBR(x) VAL_MASK(x, 16, 0) +#define V_WIN0_VS_FACTOR_CBR(x) VAL_MASK(x, 16, 16) +#define WIN0_SCL_OFFSET 0x0000005c +#define V_WIN0_HS_OFFSET_YRGB(x) VAL_MASK(x, 8, 0) +#define V_WIN0_HS_OFFSET_CBR(x) VAL_MASK(x, 8, 8) +#define V_WIN0_VS_OFFSET_YRGB(x) VAL_MASK(x, 8, 16) +#define V_WIN0_VS_OFFSET_CBR(x) VAL_MASK(x, 8, 24) +#define WIN0_SRC_ALPHA_CTRL 0x00000060 +#define V_WIN0_SRC_ALPHA_EN(x) VAL_MASK(x, 1, 0) +#define V_WIN0_SRC_COLOR_MODE(x) VAL_MASK(x, 1, 1) +#define V_WIN0_SRC_ALPHA_MODE(x) VAL_MASK(x, 1, 2) +#define V_WIN0_SRC_BLEND_MODE(x) VAL_MASK(x, 2, 3) +#define V_WIN0_SRC_ALPHA_CAL_MODE(x) VAL_MASK(x, 1, 5) +#define V_WIN0_SRC_FACTOR_MODE(x) VAL_MASK(x, 3, 6) +#define V_WIN0_SRC_GLOBAL_ALPHA(x) VAL_MASK(x, 8, 16) +#define V_WIN0_FADING_VALUE(x) VAL_MASK(x, 8, 24) +#define WIN0_DST_ALPHA_CTRL 0x00000064 +#define V_WIN0_DST_M0_RESERVED(x) VAL_MASK(x, 6, 0) +#define V_WIN0_DST_FACTOR_MODE(x) VAL_MASK(x, 3, 6) +#define WIN0_FADING_CTRL 0x00000068 +#define V_LAYER0_FADING_OFFSET_R(x) VAL_MASK(x, 8, 0) +#define V_LAYER0_FADING_OFFSET_G(x) VAL_MASK(x, 8, 8) +#define V_LAYER0_FADING_OFFSET_B(x) VAL_MASK(x, 8, 16) +#define V_LAYER0_FADING_EN(x) VAL_MASK(x, 1, 24) +#define WIN0_CTRL2 0x0000006c +#define V_WIN_RID_WIN0_YRGB(x) VAL_MASK(x, 4, 0) +#define V_WIN_RID_WIN0_CBR(x) VAL_MASK(x, 4, 4) +#define WIN1_CTRL0 0x00000070 +#define V_WIN1_EN(x) VAL_MASK(x, 1, 0) +#define V_WIN1_DATA_FMT(x) VAL_MASK(x, 3, 1) +#define V_WIN1_FMT_10(x) VAL_MASK(x, 1, 4) +#define V_WIN1_LB_MODE(x) VAL_MASK(x, 3, 5) +#define V_WIN1_INTERLACE_READ(x) VAL_MASK(x, 1, 8) +#define V_WIN1_NO_OUTSTANDING(x) VAL_MASK(x, 1, 9) +#define V_WIN1_CSC_MODE(x) VAL_MASK(x, 2, 10) +#define V_WIN1_RB_SWAP(x) VAL_MASK(x, 1, 12) +#define V_WIN1_ALPHA_SWAP(x) VAL_MASK(x, 1, 13) +#define V_WIN1_MID_SWAP(x) VAL_MASK(x, 1, 14) +#define V_WIN1_UV_SWAP(x) VAL_MASK(x, 1, 15) +#define V_WIN1_HW_PRE_MUL_EN(x) VAL_MASK(x, 1, 16) +#define V_WIN1_YRGB_DEFLICK(x) VAL_MASK(x, 1, 18) +#define V_WIN1_CBR_DEFLICK(x) VAL_MASK(x, 1, 19) +#define V_WIN1_YUV_CLIP(x) VAL_MASK(x, 1, 20) +#define V_WIN1_X_MIR_EN(x) VAL_MASK(x, 1, 21) +#define V_WIN1_Y_MIR_EN(x) VAL_MASK(x, 1, 22) +#define V_WIN1_AXI_MAX_OUTSTANDING_EN(x) VAL_MASK(x, 1, 24) +#define V_WIN1_AXI_MAX_OUTSTANDING_NUM(x) VAL_MASK(x, 5, 25) +#define V_WIN1_DMA_BURST_LENGTH(x) VAL_MASK(x, 2, 30) +#define WIN1_CTRL1 0x00000074 +#define V_WIN1_YRGB_AXI_GATHER_EN(x) VAL_MASK(x, 1, 0) +#define V_WIN1_CBR_AXI_GATHER_EN(x) VAL_MASK(x, 1, 1) +#define V_WIN1_BIC_COE_SEL(x) VAL_MASK(x, 2, 2) +#define V_WIN1_VSD_YRGB_GT4(x) VAL_MASK(x, 1, 4) +#define V_WIN1_VSD_YRGB_GT2(x) VAL_MASK(x, 1, 5) +#define V_WIN1_VSD_CBR_GT4(x) VAL_MASK(x, 1, 6) +#define V_WIN1_VSD_CBR_GT2(x) VAL_MASK(x, 1, 7) +#define V_WIN1_YRGB_AXI_GATHER_NUM(x) VAL_MASK(x, 4, 8) +#define V_WIN1_CBR_AXI_GATHER_NUM(x) VAL_MASK(x, 3, 12) +#define V_WIN1_LINE_LOAD_MODE(x) VAL_MASK(x, 1, 15) +#define V_WIN1_YRGB_HOR_SCL_MODE(x) VAL_MASK(x, 2, 16) +#define V_WIN1_YRGB_VER_SCL_MODE(x) VAL_MASK(x, 2, 18) +#define V_WIN1_YRGB_HSD_MODE(x) VAL_MASK(x, 2, 20) +#define V_WIN1_YRGB_VSU_MODE(x) VAL_MASK(x, 1, 22) +#define V_WIN1_YRGB_VSD_MODE(x) VAL_MASK(x, 1, 23) +#define V_WIN1_CBR_HOR_SCL_MODE(x) VAL_MASK(x, 2, 24) +#define V_WIN1_CBR_VER_SCL_MODE(x) VAL_MASK(x, 2, 26) +#define V_WIN1_CBR_HSD_MODE(x) VAL_MASK(x, 2, 28) +#define V_WIN1_CBR_VSU_MODE(x) VAL_MASK(x, 1, 30) +#define V_WIN1_CBR_VSD_MODE(x) VAL_MASK(x, 1, 31) +#define WIN1_COLOR_KEY 0x00000078 +#define V_WIN1_KEY_COLOR(x) VAL_MASK(x, 24, 0) +#define V_WIN1_KEY_EN(x) VAL_MASK(x, 1, 31) +#define WIN1_VIR 0x0000007c +#define V_WIN1_VIR_STRIDE(x) VAL_MASK(x, 16, 0) +#define V_WIN1_VIR_STRIDE_UV(x) VAL_MASK(x, 16, 16) +#define WIN1_YRGB_MST 0x00000080 +#define V_WIN1_YRGB_MST(x) VAL_MASK(x, 32, 0) +#define WIN1_CBR_MST 0x00000084 +#define V_WIN1_CBR_MST(x) VAL_MASK(x, 32, 0) +#define WIN1_ACT_INFO 0x00000088 +#define V_WIN1_ACT_WIDTH(x) VAL_MASK(x, 13, 0) +#define V_WIN1_ACT_HEIGHT(x) VAL_MASK(x, 13, 16) +#define WIN1_DSP_INFO 0x0000008c +#define V_WIN1_DSP_WIDTH(x) VAL_MASK(x, 12, 0) +#define V_WIN1_DSP_HEIGHT(x) VAL_MASK(x, 12, 16) +#define WIN1_DSP_ST 0x00000090 +#define V_WIN1_DSP_XST(x) VAL_MASK(x, 13, 0) +#define V_WIN1_DSP_YST(x) VAL_MASK(x, 13, 16) +#define WIN1_SCL_FACTOR_YRGB 0x00000094 +#define V_WIN1_HS_FACTOR_YRGB(x) VAL_MASK(x, 16, 0) +#define V_WIN1_VS_FACTOR_YRGB(x) VAL_MASK(x, 16, 16) +#define WIN1_SCL_FACTOR_CBR 0x00000098 +#define V_WIN1_HS_FACTOR_CBR(x) VAL_MASK(x, 16, 0) +#define V_WIN1_VS_FACTOR_CBR(x) VAL_MASK(x, 16, 16) +#define WIN1_SCL_OFFSET 0x0000009c +#define V_WIN1_HS_OFFSET_YRGB(x) VAL_MASK(x, 8, 0) +#define V_WIN1_HS_OFFSET_CBR(x) VAL_MASK(x, 8, 8) +#define V_WIN1_VS_OFFSET_YRGB(x) VAL_MASK(x, 8, 16) +#define V_WIN1_VS_OFFSET_CBR(x) VAL_MASK(x, 8, 24) +#define WIN1_SRC_ALPHA_CTRL 0x000000a0 +#define V_WIN1_SRC_ALPHA_EN(x) VAL_MASK(x, 1, 0) +#define V_WIN1_SRC_COLOR_MODE(x) VAL_MASK(x, 1, 1) +#define V_WIN1_SRC_ALPHA_MODE(x) VAL_MASK(x, 1, 2) +#define V_WIN1_SRC_BLEND_MODE(x) VAL_MASK(x, 2, 3) +#define V_WIN1_SRC_ALPHA_CAL_MODE(x) VAL_MASK(x, 1, 5) +#define V_WIN1_SRC_FACTOR_MODE(x) VAL_MASK(x, 3, 6) +#define V_WIN1_SRC_GLOBAL_ALPHA(x) VAL_MASK(x, 8, 16) +#define V_WIN1_FADING_VALUE(x) VAL_MASK(x, 8, 24) +#define WIN1_DST_ALPHA_CTRL 0x000000a4 +#define V_WIN1_DSP_M0_RESERVED(x) VAL_MASK(x, 6, 0) +#define V_WIN1_DST_FACTOR_M0(x) VAL_MASK(x, 3, 6) +#define WIN1_FADING_CTRL 0x000000a8 +#define V_WIN1_FADING_OFFSET_R(x) VAL_MASK(x, 8, 0) +#define V_WIN1_FADING_OFFSET_G(x) VAL_MASK(x, 8, 8) +#define V_WIN1_FADING_OFFSET_B(x) VAL_MASK(x, 8, 16) +#define V_WIN1_FADING_EN(x) VAL_MASK(x, 1, 24) +#define WIN1_CTRL2 0x000000ac +#define V_WIN_RID_WIN1_YRGB(x) VAL_MASK(x, 4, 0) +#define V_WIN_RID_WIN1_CBR(x) VAL_MASK(x, 4, 4) +#define WIN2_CTRL0 0x000000b0 +#define V_WIN2_EN(x) VAL_MASK(x, 1, 0) +#define V_WIN2_INTERLACE_READ(x) VAL_MASK(x, 1, 1) +#define V_WIN2_CSC_MODE(x) VAL_MASK(x, 1, 2) +#define V_WIN2_MST0_EN(x) VAL_MASK(x, 1, 4) +#define V_WIN2_DATA_FMT0(x) VAL_MASK(x, 2, 5) +#define V_WIN2_MST1_EN(x) VAL_MASK(x, 1, 8) +#define V_WIN2_DATA_FMT1(x) VAL_MASK(x, 2, 9) +#define V_WIN2_MST2_EN(x) VAL_MASK(x, 1, 12) +#define V_WIN2_DATA_FMT2(x) VAL_MASK(x, 2, 13) +#define V_WIN2_MST3_EN(x) VAL_MASK(x, 1, 16) +#define V_WIN2_DATA_FMT3(x) VAL_MASK(x, 2, 17) +#define V_WIN2_RB_SWAP0(x) VAL_MASK(x, 1, 20) +#define V_WIN2_ALPHA_SWAP0(x) VAL_MASK(x, 1, 21) +#define V_WIN2_ENDIAN_SWAP0(x) VAL_MASK(x, 1, 22) +#define V_WIN2_RB_SWAP1(x) VAL_MASK(x, 1, 23) +#define V_WIN2_ALPHA_SWAP1(x) VAL_MASK(x, 1, 24) +#define V_WIN2_ENDIAN_SWAP1(x) VAL_MASK(x, 1, 25) +#define V_WIN2_RB_SWAP2(x) VAL_MASK(x, 1, 26) +#define V_WIN2_ALPHA_SWAP2(x) VAL_MASK(x, 1, 27) +#define V_WIN2_ENDIAN_SWAP2(x) VAL_MASK(x, 1, 28) +#define V_WIN2_RB_SWAP3(x) VAL_MASK(x, 1, 29) +#define V_WIN2_ALPHA_SWAP3(x) VAL_MASK(x, 1, 30) +#define V_WIN2_ENDIAN_SWAP3(x) VAL_MASK(x, 1, 31) +#define WIN2_CTRL1 0x000000b4 +#define V_WIN2_AXI_GATHER_EN(x) VAL_MASK(x, 1, 0) +#define V_WIN2_AXI_MAX_OUTSTANDING_EN(x) VAL_MASK(x, 1, 1) +#define V_WIN2_DMA_BURST_LENGTH(x) VAL_MASK(x, 2, 2) +#define V_WIN2_AXI_GATHER_NUM(x) VAL_MASK(x, 4, 4) +#define V_WIN2_AXI_MAX_OUTSTANDING_NUM(x) VAL_MASK(x, 5, 8) +#define V_WIN2_NO_OUTSTANDING(x) VAL_MASK(x, 1, 14) +#define V_WIN2_Y_MIR_EN(x) VAL_MASK(x, 1, 15) +#define V_WIN2_LUT_EN(x) VAL_MASK(x, 1, 16) +#define V_WIN_RID_WIN2(x) VAL_MASK(x, 4, 20) +#define WIN2_VIR0_1 0x000000b8 +#define V_WIN2_VIR_STRIDE0(x) VAL_MASK(x, 16, 0) +#define V_WIN2_VIR_STRIDE1(x) VAL_MASK(x, 16, 16) +#define WIN2_VIR2_3 0x000000bc +#define V_WIN2_VIR_STRIDE2(x) VAL_MASK(x, 16, 0) +#define V_WIN2_VIR_STRIDE3(x) VAL_MASK(x, 16, 16) +#define WIN2_MST0 0x000000c0 +#define V_WIN2_MST0(x) VAL_MASK(x, 32, 0) +#define WIN2_DSP_INFO0 0x000000c4 +#define V_WIN2_DSP_WIDTH0(x) VAL_MASK(x, 12, 0) +#define V_WIN2_DSP_HEIGHT0(x) VAL_MASK(x, 12, 16) +#define WIN2_DSP_ST0 0x000000c8 +#define V_WIN2_DSP_XST0(x) VAL_MASK(x, 13, 0) +#define V_WIN2_DSP_YST0(x) VAL_MASK(x, 13, 16) +#define WIN2_COLOR_KEY 0x000000cc +#define V_WIN2_KEY_COLOR(x) VAL_MASK(x, 24, 0) +#define V_WIN2_KEY_EN(x) VAL_MASK(x, 1, 24) +#define WIN2_MST1 0x000000d0 +#define V_WIN2_MST1(x) VAL_MASK(x, 32, 0) +#define WIN2_DSP_INFO1 0x000000d4 +#define V_WIN2_DSP_WIDTH1(x) VAL_MASK(x, 12, 0) +#define V_WIN2_DSP_HEIGHT1(x) VAL_MASK(x, 12, 16) +#define WIN2_DSP_ST1 0x000000d8 +#define V_WIN2_DSP_XST1(x) VAL_MASK(x, 13, 0) +#define V_WIN2_DSP_YST1(x) VAL_MASK(x, 13, 16) +#define WIN2_SRC_ALPHA_CTRL 0x000000dc +#define V_WIN2_SRC_ALPHA_EN(x) VAL_MASK(x, 1, 0) +#define V_WIN2_SRC_COLOR_MODE(x) VAL_MASK(x, 1, 1) +#define V_WIN2_SRC_ALPHA_MODE(x) VAL_MASK(x, 1, 2) +#define V_WIN2_SRC_BLEND_MODE(x) VAL_MASK(x, 2, 3) +#define V_WIN2_SRC_ALPHA_CAL_MODE(x) VAL_MASK(x, 1, 5) +#define V_WIN2_SRC_FACTOR_MODE(x) VAL_MASK(x, 3, 6) +#define V_WIN2_SRC_GLOBAL_ALPHA(x) VAL_MASK(x, 8, 16) +#define V_WIN2_FADING_VALUE(x) VAL_MASK(x, 8, 24) +#define WIN2_MST2 0x000000e0 +#define V_WIN2_MST2(x) VAL_MASK(x, 32, 0) +#define WIN2_DSP_INFO2 0x000000e4 +#define V_WIN2_DSP_WIDTH2(x) VAL_MASK(x, 12, 0) +#define V_WIN2_DSP_HEIGHT2(x) VAL_MASK(x, 12, 16) +#define WIN2_DSP_ST2 0x000000e8 +#define V_WIN2_DSP_XST2(x) VAL_MASK(x, 13, 0) +#define V_WIN2_DSP_YST2(x) VAL_MASK(x, 13, 16) +#define WIN2_DST_ALPHA_CTRL 0x000000ec +#define V_WIN2_DST_M0_RESERVED(x) VAL_MASK(x, 6, 0) +#define V_WIN2_DST_FACTOR_MODE(x) VAL_MASK(x, 3, 6) +#define WIN2_MST3 0x000000f0 +#define V_WIN2_MST3(x) VAL_MASK(x, 32, 0) +#define WIN2_DSP_INFO3 0x000000f4 +#define V_WIN2_DSP_WIDTH3(x) VAL_MASK(x, 12, 0) +#define V_WIN2_DSP_HEIGHT3(x) VAL_MASK(x, 12, 16) +#define WIN2_DSP_ST3 0x000000f8 +#define V_WIN2_DSP_XST3(x) VAL_MASK(x, 13, 0) +#define V_WIN2_DSP_YST3(x) VAL_MASK(x, 13, 16) +#define WIN2_FADING_CTRL 0x000000fc +#define V_WIN2_FADING_OFFSET_R(x) VAL_MASK(x, 8, 0) +#define V_WIN2_FADING_OFFSET_G(x) VAL_MASK(x, 8, 8) +#define V_WIN2_FADING_OFFSET_B(x) VAL_MASK(x, 8, 16) +#define V_WIN2_FADING_EN(x) VAL_MASK(x, 1, 24) +#define WIN3_CTRL0 0x00000100 +#define V_WIN3_EN(x) VAL_MASK(x, 1, 0) +#define V_WIN3_INTERLACE_READ(x) VAL_MASK(x, 1, 1) +#define V_WIN3_CSC_MODE(x) VAL_MASK(x, 1, 2) +#define V_WIN3_MST0_EN(x) VAL_MASK(x, 1, 4) +#define V_WIN3_DATA_FMT0(x) VAL_MASK(x, 2, 5) +#define V_WIN3_MST1_EN(x) VAL_MASK(x, 1, 8) +#define V_WIN3_DATA_FMT1(x) VAL_MASK(x, 2, 9) +#define V_WIN3_MST2_EN(x) VAL_MASK(x, 1, 12) +#define V_WIN3_DATA_FMT2(x) VAL_MASK(x, 2, 13) +#define V_WIN3_MST3_EN(x) VAL_MASK(x, 1, 16) +#define V_WIN3_DATA_FMT3(x) VAL_MASK(x, 2, 17) +#define V_WIN3_RB_SWAP0(x) VAL_MASK(x, 1, 20) +#define V_WIN3_ALPHA_SWAP0(x) VAL_MASK(x, 1, 21) +#define V_WIN3_ENDIAN_SWAP0(x) VAL_MASK(x, 1, 22) +#define V_WIN3_RB_SWAP1(x) VAL_MASK(x, 1, 23) +#define V_WIN3_ALPHA_SWAP1(x) VAL_MASK(x, 1, 24) +#define V_WIN3_ENDIAN_SWAP1(x) VAL_MASK(x, 1, 25) +#define V_WIN3_RB_SWAP2(x) VAL_MASK(x, 1, 26) +#define V_WIN3_ALPHA_SWAP2(x) VAL_MASK(x, 1, 27) +#define V_WIN3_ENDIAN_SWAP2(x) VAL_MASK(x, 1, 28) +#define V_WIN3_RB_SWAP3(x) VAL_MASK(x, 1, 29) +#define V_WIN3_ALPHA_SWAP3(x) VAL_MASK(x, 1, 30) +#define V_WIN3_ENDIAN_SWAP3(x) VAL_MASK(x, 1, 31) +#define WIN3_CTRL1 0x00000104 +#define V_WIN3_AXI_GATHER_EN(x) VAL_MASK(x, 1, 0) +#define V_WIN3_AXI_MAX_OUTSTANDING_EN(x) VAL_MASK(x, 1, 1) +#define V_WIN3_DMA_BURST_LENGTH(x) VAL_MASK(x, 2, 2) +#define V_WIN3_AXI_GATHER_NUM(x) VAL_MASK(x, 4, 4) +#define V_WIN3_AXI_MAX_OUTSTANDING_NUM(x) VAL_MASK(x, 5, 8) +#define V_WIN3_NO_OUTSTANDING(x) VAL_MASK(x, 1, 14) +#define V_WIN3_Y_MIR_EN(x) VAL_MASK(x, 1, 15) +#define V_WIN3_LUT_EN(x) VAL_MASK(x, 1, 16) +#define V_WIN_RID_WIN3(x) VAL_MASK(x, 4, 20) +#define WIN3_VIR0_1 0x00000108 +#define V_WIN3_VIR_STRIDE0(x) VAL_MASK(x, 16, 0) +#define V_WIN3_VIR_STRIDE1(x) VAL_MASK(x, 16, 16) +#define WIN3_VIR2_3 0x0000010c +#define V_WIN3_VIR_STRIDE2(x) VAL_MASK(x, 16, 0) +#define V_WIN3_VIR_STRIDE3(x) VAL_MASK(x, 16, 16) +#define WIN3_MST0 0x00000110 +#define V_WIN3_MST0(x) VAL_MASK(x, 32, 0) +#define WIN3_DSP_INFO0 0x00000114 +#define V_WIN3_DSP_WIDTH0(x) VAL_MASK(x, 12, 0) +#define V_WIN3_DSP_HEIGHT0(x) VAL_MASK(x, 12, 16) +#define WIN3_DSP_ST0 0x00000118 +#define V_WIN3_DSP_XST0(x) VAL_MASK(x, 13, 0) +#define V_WIN3_DSP_YST0(x) VAL_MASK(x, 13, 16) +#define WIN3_COLOR_KEY 0x0000011c +#define V_WIN3_KEY_COLOR(x) VAL_MASK(x, 24, 0) +#define V_WIN3_KEY_EN(x) VAL_MASK(x, 1, 24) +#define WIN3_MST1 0x00000120 +#define V_WIN3_MST1(x) VAL_MASK(x, 32, 0) +#define WIN3_DSP_INFO1 0x00000124 +#define V_WIN3_DSP_WIDTH1(x) VAL_MASK(x, 12, 0) +#define V_WIN3_DSP_HEIGHT1(x) VAL_MASK(x, 12, 16) +#define WIN3_DSP_ST1 0x00000128 +#define V_WIN3_DSP_XST1(x) VAL_MASK(x, 13, 0) +#define V_WIN3_DSP_YST1(x) VAL_MASK(x, 13, 16) +#define WIN3_SRC_ALPHA_CTRL 0x0000012c +#define V_WIN3_SRC_ALPHA_EN(x) VAL_MASK(x, 1, 0) +#define V_WIN3_SRC_COLOR_MODE(x) VAL_MASK(x, 1, 1) +#define V_WIN3_SRC_ALPHA_MODE(x) VAL_MASK(x, 1, 2) +#define V_WIN3_SRC_BLEND_MODE(x) VAL_MASK(x, 2, 3) +#define V_WIN3_SRC_ALPHA_CAL_MODE(x) VAL_MASK(x, 1, 5) +#define V_WIN3_SRC_FACTOR_MODE(x) VAL_MASK(x, 3, 6) +#define V_WIN3_SRC_GLOBAL_ALPHA(x) VAL_MASK(x, 8, 16) +#define V_WIN3_FADING_VALUE(x) VAL_MASK(x, 8, 24) +#define WIN3_MST2 0x00000130 +#define V_WIN3_MST2(x) VAL_MASK(x, 32, 0) +#define WIN3_DSP_INFO2 0x00000134 +#define V_WIN3_DSP_WIDTH2(x) VAL_MASK(x, 12, 0) +#define V_WIN3_DSP_HEIGHT2(x) VAL_MASK(x, 12, 16) +#define WIN3_DSP_ST2 0x00000138 +#define V_WIN3_DSP_XST2(x) VAL_MASK(x, 13, 0) +#define V_WIN3_DSP_YST2(x) VAL_MASK(x, 13, 16) +#define WIN3_DST_ALPHA_CTRL 0x0000013c +#define V_WIN3_DST_FACTOR_RESERVED(x) VAL_MASK(x, 6, 0) +#define V_WIN3_DST_FACTOR_MODE(x) VAL_MASK(x, 3, 6) +#define WIN3_MST3 0x00000140 +#define V_WIN3_MST3(x) VAL_MASK(x, 32, 0) +#define WIN3_DSP_INFO3 0x00000144 +#define V_WIN3_DSP_WIDTH3(x) VAL_MASK(x, 12, 0) +#define V_WIN3_DSP_HEIGHT3(x) VAL_MASK(x, 12, 16) +#define WIN3_DSP_ST3 0x00000148 +#define V_WIN3_DSP_XST3(x) VAL_MASK(x, 13, 0) +#define V_WIN3_DSP_YST3(x) VAL_MASK(x, 13, 16) +#define WIN3_FADING_CTRL 0x0000014c +#define V_WIN3_FADING_OFFSET_R(x) VAL_MASK(x, 8, 0) +#define V_WIN3_FADING_OFFSET_G(x) VAL_MASK(x, 8, 8) +#define V_WIN3_FADING_OFFSET_B(x) VAL_MASK(x, 8, 16) +#define V_WIN3_FADING_EN(x) VAL_MASK(x, 1, 24) +#define HWC_CTRL0 0x00000150 +#define V_HWC_EN(x) VAL_MASK(x, 1, 0) +#define V_HWC_DATA_FMT(x) VAL_MASK(x, 3, 1) +#define V_HWC_MODE(x) VAL_MASK(x, 1, 4) +#define V_HWC_SIZE(x) VAL_MASK(x, 2, 5) +#define V_HWC_INTERLACE_READ(x) VAL_MASK(x, 1, 8) +#define V_HWC_CSC_MODE(x) VAL_MASK(x, 1, 10) +#define V_HWC_RB_SWAP(x) VAL_MASK(x, 1, 12) +#define V_HWC_ALPHA_SWAP(x) VAL_MASK(x, 1, 13) +#define V_HWC_ENDIAN_SWAP(x) VAL_MASK(x, 1, 14) +#define HWC_CTRL1 0x00000154 +#define V_HWC_AXI_GATHER_EN(x) VAL_MASK(x, 1, 0) +#define V_HWC_AXI_MAX_OUTSTANDING_EN(x) VAL_MASK(x, 1, 1) +#define V_HWC_DMA_BURST_LENGTH(x) VAL_MASK(x, 2, 2) +#define V_HWC_AXI_GATHER_NUM(x) VAL_MASK(x, 3, 4) +#define V_HWC_AXI_MAX_OUTSTANDING_NUM(x) VAL_MASK(x, 5, 8) +#define V_HWC_RGB2YUV_EN(x) VAL_MASK(x, 1, 13) +#define V_HWC_NO_OUTSTANDING(x) VAL_MASK(x, 1, 14) +#define V_HWC_Y_MIR_EN(x) VAL_MASK(x, 1, 15) +#define V_HWC_LUT_EN(x) VAL_MASK(x, 1, 16) +#define V_WIN_RID_HWC(x) VAL_MASK(x, 4, 20) +#define HWC_MST 0x00000158 +#define V_HWC_MST(x) VAL_MASK(x, 32, 0) +#define HWC_DSP_ST 0x0000015c +#define V_HWC_DSP_XST(x) VAL_MASK(x, 13, 0) +#define V_HWC_DSP_YST(x) VAL_MASK(x, 13, 16) +#define HWC_SRC_ALPHA_CTRL 0x00000160 +#define V_HWC_SRC_ALPHA_EN(x) VAL_MASK(x, 1, 0) +#define V_HWC_SRC_COLOR_MODE(x) VAL_MASK(x, 1, 1) +#define V_HWC_SRC_ALPHA_MODE(x) VAL_MASK(x, 1, 2) +#define V_HWC_SRC_BLEND_MODE(x) VAL_MASK(x, 2, 3) +#define V_HWC_SRC_ALPHA_CAL_MODE(x) VAL_MASK(x, 1, 5) +#define V_HWC_SRC_FACTOR_MODE(x) VAL_MASK(x, 3, 6) +#define V_HWC_SRC_GLOBAL_ALPHA(x) VAL_MASK(x, 8, 16) +#define V_HWC_FADING_VALUE(x) VAL_MASK(x, 8, 24) +#define HWC_DST_ALPHA_CTRL 0x00000164 +#define V_HWC_DST_M0_RESERVED(x) VAL_MASK(x, 6, 0) +#define V_HWC_DST_FACTOR_MODE(x) VAL_MASK(x, 3, 6) +#define HWC_FADING_CTRL 0x00000168 +#define V_HWC_FADING_OFFSET_R(x) VAL_MASK(x, 8, 0) +#define V_HWC_FADING_OFFSET_G(x) VAL_MASK(x, 8, 8) +#define V_HWC_FADING_OFFSET_B(x) VAL_MASK(x, 8, 16) +#define V_HWC_FADING_EN(x) VAL_MASK(x, 1, 24) +#define HWC_RESERVED1 0x0000016c +#define POST_DSP_HACT_INFO 0x00000170 +#define V_DSP_HACT_END_POST(x) VAL_MASK(x, 13, 0) +#define V_DSP_HACT_ST_POST(x) VAL_MASK(x, 13, 16) +#define POST_DSP_VACT_INFO 0x00000174 +#define V_DSP_VACT_END_POST(x) VAL_MASK(x, 13, 0) +#define V_DSP_VACT_ST_POST(x) VAL_MASK(x, 13, 16) +#define POST_SCL_FACTOR_YRGB 0x00000178 +#define V_POST_HS_FACTOR_YRGB(x) VAL_MASK(x, 16, 0) +#define V_POST_VS_FACTOR_YRGB(x) VAL_MASK(x, 16, 16) +#define POST_RESERVED 0x0000017c +#define POST_SCL_CTRL 0x00000180 +#define V_POST_HOR_SD_EN(x) VAL_MASK(x, 1, 0) +#define V_POST_VER_SD_EN(x) VAL_MASK(x, 1, 1) +#define POST_DSP_VACT_INFO_F1 0x00000184 +#define V_DSP_VACT_END_POST(x) VAL_MASK(x, 13, 0) +#define V_DSP_VACT_ST_POST(x) VAL_MASK(x, 13, 16) +#define DSP_HTOTAL_HS_END 0x00000188 +#define V_DSP_HS_END(x) VAL_MASK(x, 13, 0) +#define V_DSP_HTOTAL(x) VAL_MASK(x, 13, 16) +#define DSP_HACT_ST_END 0x0000018c +#define V_DSP_HACT_END(x) VAL_MASK(x, 13, 0) +#define V_DSP_HACT_ST(x) VAL_MASK(x, 13, 16) +#define DSP_VTOTAL_VS_END 0x00000190 +#define V_DSP_VS_END(x) VAL_MASK(x, 13, 0) +#define V_SW_DSP_VTOTAL_IMD(x) VAL_MASK(x, 1, 15) +#define V_DSP_VTOTAL(x) VAL_MASK(x, 13, 16) +#define DSP_VACT_ST_END 0x00000194 +#define V_DSP_VACT_END(x) VAL_MASK(x, 13, 0) +#define V_DSP_VACT_ST(x) VAL_MASK(x, 13, 16) +#define DSP_VS_ST_END_F1 0x00000198 +#define V_DSP_VS_END_F1(x) VAL_MASK(x, 13, 0) +#define V_DSP_VS_ST_F1(x) VAL_MASK(x, 13, 16) +#define DSP_VACT_ST_END_F1 0x0000019c +#define V_DSP_VACT_END_F1(x) VAL_MASK(x, 13, 0) +#define V_DSP_VACT_ST_F1(x) VAL_MASK(x, 13, 16) +#define PWM_CTRL 0x000001a0 +#define V_PWM_EN(x) VAL_MASK(x, 1, 0) +#define V_PWM_MODE(x) VAL_MASK(x, 2, 1) +#define V_DUTY_POL(x) VAL_MASK(x, 1, 3) +#define V_INACTIVE_POL(x) VAL_MASK(x, 1, 4) +#define V_OUTPUT_MODE(x) VAL_MASK(x, 1, 5) +#define V_LP_EN(x) VAL_MASK(x, 1, 8) +#define V_CLK_SEL(x) VAL_MASK(x, 1, 9) +#define V_PRESCALE(x) VAL_MASK(x, 3, 12) +#define V_SCALE(x) VAL_MASK(x, 8, 16) +#define V_RPT(x) VAL_MASK(x, 8, 24) +#define PWM_PERIOD_HPR 0x000001a4 +#define V_PWM_PERIOD(x) VAL_MASK(x, 32, 0) +#define PWM_DUTY_LPR 0x000001a8 +#define V_PWM_DUTY(x) VAL_MASK(x, 32, 0) +#define PWM_CNT 0x000001ac +#define V_PWM_CNT(x) VAL_MASK(x, 32, 0) +#define BCSH_COLOR_BAR 0x000001b0 +#define V_BCSH_EN(x) VAL_MASK(x, 1, 0) +#define V_COLOR_BAR_Y(x) VAL_MASK(x, 8, 8) +#define V_COLOR_BAR_U(x) VAL_MASK(x, 8, 16) +#define V_COLOR_BAR_V(x) VAL_MASK(x, 8, 24) +#define BCSH_BCS 0x000001b4 +#define V_BRIGHTNESS(x) VAL_MASK(x, 8, 0) +#define V_CONTRAST(x) VAL_MASK(x, 9, 8) +#define V_SAT_CON(x) VAL_MASK(x, 10, 20) +#define V_OUT_MODE(x) VAL_MASK(x, 2, 30) +#define BCSH_H 0x000001b8 +#define V_SIN_HUE(x) VAL_MASK(x, 9, 0) +#define V_COS_HUE(x) VAL_MASK(x, 9, 16) +#define BCSH_CTRL 0x000001bc +#define V_BCSH_Y2R_EN(x) VAL_MASK(x, 1, 0) +#define V_BCSH_Y2R_CSC_MODE(x) VAL_MASK(x, 2, 2) +#define V_BCSH_R2Y_EN(x) VAL_MASK(x, 1, 4) +#define V_BCSH_R2Y_CSC_MODE(x) VAL_MASK(x, 1, 6) +#define CABC_CTRL0 0x000001c0 +#define V_CABC_EN(x) VAL_MASK(x, 1, 0) +#define V_PWM_CONFIG_MODE(x) VAL_MASK(x, 2, 1) +#define V_CABC_HANDLE_EN(x) VAL_MASK(x, 1, 3) +#define V_CABC_CALC_PIXEL_NUM(x) VAL_MASK(x, 23, 4) +#define CABC_CTRL1 0x000001c4 +#define V_CABC_LUT_EN(x) VAL_MASK(x, 1, 0) +#define V_CABC_TOTAL_NUM(x) VAL_MASK(x, 23, 4) +#define CABC_CTRL2 0x000001c8 +#define V_CABC_STAGE_DOWN(x) VAL_MASK(x, 8, 0) +#define V_CABC_STAGE_UP(x) VAL_MASK(x, 9, 8) +#define V_CABC_STAGE_UP_MODE(x) VAL_MASK(x, 1, 19) +#define CABC_CTRL3 0x000001cc +#define V_CABC_GLOBAL_DN(x) VAL_MASK(x, 8, 0) +#define V_CABC_GLOBAL_DN_LIMIT_EN(x) VAL_MASK(x, 1, 8) +#define CABC_GAUSS_LINE0_0 0x000001d0 +#define V_T_LINE0_0(x) VAL_MASK(x, 8, 0) +#define V_T_LINE0_1(x) VAL_MASK(x, 8, 8) +#define V_T_LINE0_2(x) VAL_MASK(x, 8, 16) +#define V_T_LINE0_3(x) VAL_MASK(x, 8, 24) +#define CABC_GAUSS_LINE0_1 0x000001d4 +#define V_T_LINE0_4(x) VAL_MASK(x, 8, 0) +#define V_T_LINE0_5(x) VAL_MASK(x, 8, 8) +#define V_T_LINE0_6(x) VAL_MASK(x, 8, 16) +#define CABC_GAUSS_LINE1_0 0x000001d8 +#define V_T_LINE1_0(x) VAL_MASK(x, 8, 0) +#define V_T_LINE1_1(x) VAL_MASK(x, 8, 8) +#define V_T_LINE1_2(x) VAL_MASK(x, 8, 16) +#define V_T_LINE1_3(x) VAL_MASK(x, 8, 24) +#define CABC_GAUSS_LINE1_1 0x000001dc +#define V_T_LINE1_4(x) VAL_MASK(x, 8, 0) +#define V_T_LINE1_5(x) VAL_MASK(x, 8, 8) +#define V_T_LINE1_6(x) VAL_MASK(x, 8, 16) +#define CABC_GAUSS_LINE2_0 0x000001e0 +#define V_T_LINE2_0(x) VAL_MASK(x, 8, 0) +#define V_T_LINE2_1(x) VAL_MASK(x, 8, 8) +#define V_T_LINE2_2(x) VAL_MASK(x, 8, 16) +#define V_T_LINE2_3(x) VAL_MASK(x, 8, 24) +#define CABC_GAUSS_LINE2_1 0x000001e4 +#define V_T_LINE2_4(x) VAL_MASK(x, 8, 0) +#define V_T_LINE2_5(x) VAL_MASK(x, 8, 8) +#define V_T_LINE2_6(x) VAL_MASK(x, 8, 16) +#define FRC_LOWER01_0 0x000001e8 +#define V_LOWER01_FRM0(x) VAL_MASK(x, 16, 0) +#define V_LOWER01_FRM1(x) VAL_MASK(x, 16, 16) +#define FRC_LOWER01_1 0x000001ec +#define V_LOWER01_FRM2(x) VAL_MASK(x, 16, 0) +#define V_LOWER01_FRM3(x) VAL_MASK(x, 16, 16) +#define FRC_LOWER10_0 0x000001f0 +#define V_LOWER10_FRM0(x) VAL_MASK(x, 16, 0) +#define V_LOWER10_FRM1(x) VAL_MASK(x, 16, 16) +#define FRC_LOWER10_1 0x000001f4 +#define V_LOWER10_FRM2(x) VAL_MASK(x, 16, 0) +#define V_LOWER10_FRM3(x) VAL_MASK(x, 16, 16) +#define FRC_LOWER11_0 0x000001f8 +#define V_LOWER11_FRM0(x) VAL_MASK(x, 16, 0) +#define V_LOWER11_FRM1(x) VAL_MASK(x, 16, 16) +#define FRC_LOWER11_1 0x000001fc +#define V_LOWER11_FRM2(x) VAL_MASK(x, 16, 0) +#define V_LOWER11_FRM3(x) VAL_MASK(x, 16, 16) +#define AFBCD0_CTRL 0x00000200 +#define V_VOP_FBDC_EN(x) VAL_MASK(x, 1, 0) +#define V_VOP_FBDC_WIN_SEL(x) VAL_MASK(x, 2, 1) +#define V_FBDC_RSTN(x) VAL_MASK(x, 1, 3) +#define V_VOP_FBDC_AXI_MAX_OUTSTANDING_NUM(x) VAL_MASK(x, 5, 4) +#define V_VOP_FBDC_AXI_MAX_OUTSTANDING_EN(x) VAL_MASK(x, 1, 9) +#define V_FBDC_RID(x) VAL_MASK(x, 4, 12) +#define V_AFBCD_HREG_PIXEL_PACKING_FMT(x) VAL_MASK(x, 5, 16) +#define V_AFBCD_HREG_BLOCK_SPLIT(x) VAL_MASK(x, 1, 21) +#define AFBCD0_HDR_PTR 0x00000204 +#define V_AFBCD_HREG_HDR_PTR(x) VAL_MASK(x, 32, 0) +#define AFBCD0_PIC_SIZE 0x00000208 +#define V_AFBCD_HREG_PIC_WIDTH(x) VAL_MASK(x, 16, 0) +#define V_AFBCD_HREG_PIC_HEIGHT(x) VAL_MASK(x, 16, 16) +#define AFBCD0_STATUS 0x0000020c +#define V_AFBCD_HREG_IDLE_N(x) VAL_MASK(x, 1, 0) +#define V_AFBCD_HREG_DEC_RESP(x) VAL_MASK(x, 1, 1) +#define V_AFBCD_HREG_AXI_RRESP(x) VAL_MASK(x, 1, 2) +#define AFBCD1_CTRL 0x00000220 +#define V_VOP_FBDC1_EN(x) VAL_MASK(x, 1, 0) +#define V_VOP_FBDC1_WIN_SEL(x) VAL_MASK(x, 2, 1) +#define V_FBDC1_RSTN(x) VAL_MASK(x, 1, 3) +#define V_VOP_FBDC1_AXI_MAX_OUTSTANDING_NUM(x) VAL_MASK(x, 5, 4) +#define V_VOP_FBDC1_AXI_MAX_OUTSTANDING_EN(x) VAL_MASK(x, 1, 9) +#define V_FBDC1_RID(x) VAL_MASK(x, 4, 12) +#define V_AFBCD1_HREG_PIXEL_PACKING_FMT(x) VAL_MASK(x, 5, 16) +#define V_AFBCD1_HREG_BLOCK_SPLIT(x) VAL_MASK(x, 1, 21) +#define AFBCD1_HDR_PTR 0x00000224 +#define V_AFBCD1_HREG_HDR_PTR(x) VAL_MASK(x, 32, 0) +#define AFBCD1_PIC_SIZE 0x00000228 +#define V_AFBCD1_HREG_PIC_WIDTH(x) VAL_MASK(x, 16, 0) +#define V_AFBCD1_HREG_PIC_HEIGHT(x) VAL_MASK(x, 16, 16) +#define AFBCD1_STATUS 0x0000022c +#define V_AFBCD1_HREG_IDLE_N(x) VAL_MASK(x, 1, 0) +#define V_AFBCD1_HREG_DEC_RESP(x) VAL_MASK(x, 1, 1) +#define V_AFBCD1_HREG_AXI_RRESP(x) VAL_MASK(x, 1, 2) +#define AFBCD2_CTRL 0x00000240 +#define V_VOP_FBDC2_EN(x) VAL_MASK(x, 1, 0) +#define V_VOP_FBDC2_WIN_SEL(x) VAL_MASK(x, 2, 1) +#define V_FBDC2_RSTN(x) VAL_MASK(x, 1, 3) +#define V_VOP_FBDC2_AXI_MAX_OUTSTANDING_NUM(x) VAL_MASK(x, 5, 4) +#define V_VOP_FBDC2_AXI_MAX_OUTSTANDING_EN(x) VAL_MASK(x, 1, 9) +#define V_FBDC2_RID(x) VAL_MASK(x, 4, 12) +#define V_AFBCD2_HREG_PIXEL_PACKING_FMT(x) VAL_MASK(x, 5, 16) +#define V_AFBCD2_HREG_BLOCK_SPLIT(x) VAL_MASK(x, 1, 21) +#define AFBCD2_HDR_PTR 0x00000244 +#define V_AFBCD2_HREG_HDR_PTR(x) VAL_MASK(x, 32, 0) +#define AFBCD2_PIC_SIZE 0x00000248 +#define V_AFBCD2_HREG_PIC_WIDTH(x) VAL_MASK(x, 16, 0) +#define V_AFBCD2_HREG_PIC_HEIGHT(x) VAL_MASK(x, 16, 16) +#define AFBCD2_STATUS 0x0000024c +#define V_AFBCD2_HREG_IDLE_N(x) VAL_MASK(x, 1, 0) +#define V_AFBCD2_HREG_DEC_RESP(x) VAL_MASK(x, 1, 1) +#define V_AFBCD2_HREG_AXI_RRESP(x) VAL_MASK(x, 1, 2) +#define AFBCD3_CTRL 0x00000260 +#define V_VOP_FBDC3_EN(x) VAL_MASK(x, 1, 0) +#define V_VOP_FBDC3_WIN_SEL(x) VAL_MASK(x, 1, 1) +#define V_FBDC3_RSTN(x) VAL_MASK(x, 1, 2) +#define V_VOP_FBDC3_AXI_MAX_OUTSTANDING_NUM(x) VAL_MASK(x, 5, 3) +#define V_VOP_FBDC3_AXI_MAX_OUTSTANDING_EN(x) VAL_MASK(x, 1, 8) +#define V_FBDC3_RID(x) VAL_MASK(x, 4, 12) +#define V_AFBCD3_HREG_PIXEL_PACKING_FMT(x) VAL_MASK(x, 5, 16) +#define V_AFBCD3_HREG_BLOCK_SPLIT(x) VAL_MASK(x, 1, 21) +#define AFBCD3_HDR_PTR 0x00000264 +#define V_AFBCD3_HREG_HDR_PTR(x) VAL_MASK(x, 32, 0) +#define AFBCD3_PIC_SIZE 0x00000268 +#define V_AFBCD3_HREG_PIC_WIDTH(x) VAL_MASK(x, 16, 0) +#define V_AFBCD3_HREG_PIC_HEIGHT(x) VAL_MASK(x, 16, 16) +#define AFBCD3_STATUS 0x0000026c +#define V_AFBCD3_HREG_IDLE_N(x) VAL_MASK(x, 1, 0) +#define V_AFBCD3_HREG_DEC_RESP(x) VAL_MASK(x, 1, 1) +#define V_AFBCD3_HREG_AXI_RRESP(x) VAL_MASK(x, 1, 2) +#define INTR_EN0 0x00000280 +#define V_INTR_EN_FS(x) VAL_MASK(x, 1, 0) +#define V_INTR_EN_FS_NEW(x) VAL_MASK(x, 1, 1) +#define V_INTR_EN_ADDR_SAME(x) VAL_MASK(x, 1, 2) +#define V_INTR_EN_LINE_FLAG0(x) VAL_MASK(x, 1, 3) +#define V_INTR_EN_LINE_FLAG1(x) VAL_MASK(x, 1, 4) +#define V_INTR_EN_BUS_ERROR(x) VAL_MASK(x, 1, 5) +#define V_INTR_EN_WIN0_EMPTY(x) VAL_MASK(x, 1, 6) +#define V_INTR_EN_WIN1_EMPTY(x) VAL_MASK(x, 1, 7) +#define V_INTR_EN_WIN2_EMPTY(x) VAL_MASK(x, 1, 8) +#define V_INTR_EN_WIN3_EMPTY(x) VAL_MASK(x, 1, 9) +#define V_INTR_EN_HWC_EMPTY(x) VAL_MASK(x, 1, 10) +#define V_INTR_EN_POST_BUF_EMPTY(x) VAL_MASK(x, 1, 11) +#define V_INTR_EN_PWM_GEN(x) VAL_MASK(x, 1, 12) +#define V_INTR_EN_DSP_HOLD_VALID(x) VAL_MASK(x, 1, 13) +#define V_INTR_EN_MMU(x) VAL_MASK(x, 1, 14) +#define V_INTR_EN_DMA_FINISH(x) VAL_MASK(x, 1, 15) +#define V_WRITE_MASK(x) VAL_MASK(x, 16, 16) +#define INTR_CLEAR0 0x00000284 +#define V_INT_CLR_FS(x) VAL_MASK(x, 1, 0) +#define V_INT_CLR_FS_NEW(x) VAL_MASK(x, 1, 1) +#define V_INT_CLR_ADDR_SAME(x) VAL_MASK(x, 1, 2) +#define V_INT_CLR_LINE_FLAG0(x) VAL_MASK(x, 1, 3) +#define V_INT_CLR_LINE_FLAG1(x) VAL_MASK(x, 1, 4) +#define V_INT_CLR_BUS_ERROR(x) VAL_MASK(x, 1, 5) +#define V_INT_CLR_WIN0_EMPTY(x) VAL_MASK(x, 1, 6) +#define V_INT_CLR_WIN1_EMPTY(x) VAL_MASK(x, 1, 7) +#define V_INT_CLR_WIN2_EMPTY(x) VAL_MASK(x, 1, 8) +#define V_INT_CLR_WIN3_EMPTY(x) VAL_MASK(x, 1, 9) +#define V_INT_CLR_HWC_EMPTY(x) VAL_MASK(x, 1, 10) +#define V_INT_CLR_POST_BUF_EMPTY(x) VAL_MASK(x, 1, 11) +#define V_INT_CLR_PWM_GEN(x) VAL_MASK(x, 1, 12) +#define V_INT_CLR_DSP_HOLD_VALID(x) VAL_MASK(x, 1, 13) +#define V_INT_CLR_MMU(x) VAL_MASK(x, 1, 14) +#define V_INT_CLR_DMA_FINISH(x) VAL_MASK(x, 1, 15) +#define V_WRITE_MASK(x) VAL_MASK(x, 16, 16) +#define INTR_STATUS0 0x00000288 +#define V_INT_STATUS_FS(x) VAL_MASK(x, 1, 0) +#define V_INT_STATUS_FS_NEW(x) VAL_MASK(x, 1, 1) +#define V_INT_STATUS_ADDR_SAME(x) VAL_MASK(x, 1, 2) +#define V_INT_STATUS_LINE_FLAG0(x) VAL_MASK(x, 1, 3) +#define V_INT_STATUS_LINE_FLAG1(x) VAL_MASK(x, 1, 4) +#define V_INT_STATUS_BUS_ERROR(x) VAL_MASK(x, 1, 5) +#define V_INT_STATUS_WIN0_EMPTY(x) VAL_MASK(x, 1, 6) +#define V_INT_STATUS_WIN1_EMPTY(x) VAL_MASK(x, 1, 7) +#define V_INT_STATUS_WIN2_EMPTY(x) VAL_MASK(x, 1, 8) +#define V_INT_STATUS_WIN3_EMPTY(x) VAL_MASK(x, 1, 9) +#define V_INT_STATUS_HWC_EMPTY(x) VAL_MASK(x, 1, 10) +#define V_INT_STATUS_POST_BUF_EMPTY(x) VAL_MASK(x, 1, 11) +#define V_INT_STATUS_PWM_GEN(x) VAL_MASK(x, 1, 12) +#define V_INT_STATUS_DSP_HOLD_VALID(x) VAL_MASK(x, 1, 13) +#define V_INT_STATUS_MMU(x) VAL_MASK(x, 1, 14) +#define V_INT_STATUS_DMA_FINISH(x) VAL_MASK(x, 1, 15) +#define INTR_RAW_STATUS0 0x0000028c +#define V_INT_RAW_STATUS_FS(x) VAL_MASK(x, 1, 0) +#define V_INT_RAW_STATUS_FS_NEW(x) VAL_MASK(x, 1, 1) +#define V_INT_RAW_STATUS_ADDR_SAME(x) VAL_MASK(x, 1, 2) +#define V_INT_RAW_STATUS_LINE_FRAG0(x) VAL_MASK(x, 1, 3) +#define V_INT_RAW_STATUS_LINE_FRAG1(x) VAL_MASK(x, 1, 4) +#define V_INT_RAW_STATUS_BUS_ERROR(x) VAL_MASK(x, 1, 5) +#define V_INT_RAW_STATUS_WIN0_EMPTY(x) VAL_MASK(x, 1, 6) +#define V_INT_RAW_STATUS_WIN1_EMPTY(x) VAL_MASK(x, 1, 7) +#define V_INT_RAW_STATUS_WIN2_EMPTY(x) VAL_MASK(x, 1, 8) +#define V_INT_RAW_STATUS_WIN3_EMPTY(x) VAL_MASK(x, 1, 9) +#define V_INT_RAW_STATUS_HWC_EMPTY(x) VAL_MASK(x, 1, 10) +#define V_INT_RAW_STATUS_POST_BUF_EMPTY(x) VAL_MASK(x, 1, 11) +#define V_INT_RAW_STATUS_PWM_GEN(x) VAL_MASK(x, 1, 12) +#define V_INT_RAW_STATUS_DSP_HOLD_VALID(x) VAL_MASK(x, 1, 13) +#define V_INT_RAW_STATUS_MMU(x) VAL_MASK(x, 1, 14) +#define V_INT_RAW_STATUS_DMA_FINISH(x) VAL_MASK(x, 1, 15) +#define INTR_EN1 0x00000290 +#define V_INT_EN_FBCD0(x) VAL_MASK(x, 1, 0) +#define V_INT_EN_FBCD1(x) VAL_MASK(x, 1, 1) +#define V_INT_EN_FBCD2(x) VAL_MASK(x, 1, 2) +#define V_INT_EN_FBCD3(x) VAL_MASK(x, 1, 3) +#define V_INT_EN_AFBCD0_HREG_DEC_RESP(x) VAL_MASK(x, 1, 4) +#define V_INT_EN_AFBCD0_HREG_AXI_RRESP(x) VAL_MASK(x, 1, 5) +#define V_INT_EN_AFBCD1_HREG_DEC_RESP(x) VAL_MASK(x, 1, 6) +#define V_INT_EN_AFBCD1_HREG_AXI_RRESP(x) VAL_MASK(x, 1, 7) +#define V_INT_EN_AFBCD2_HREG_DEC_RESP(x) VAL_MASK(x, 1, 8) +#define V_INT_EN_AFBCD2_HREG_AXI_RRESP(x) VAL_MASK(x, 1, 9) +#define V_INT_EN_AFBCD3_HREG_DEC_RESP(x) VAL_MASK(x, 1, 10) +#define V_INT_EN_AFBCD3_HREG_AXI_RRESP(x) VAL_MASK(x, 1, 11) +#define V_INT_EN_WB_YRGB_FIFO_FULL(x) VAL_MASK(x, 1, 12) +#define V_INT_EN_WB_UV_FIFO_FULL(x) VAL_MASK(x, 1, 13) +#define V_INT_EN_WB_FINISH(x) VAL_MASK(x, 1, 14) +#define V_INT_EN_VFP(x) VAL_MASK(x, 1, 15) +#define V_WRITE_MASK(x) VAL_MASK(x, 16, 16) +#define INTR_CLEAR1 0x00000294 +#define V_INT_CLR_FBCD0(x) VAL_MASK(x, 1, 0) +#define V_INT_CLR_FBCD1(x) VAL_MASK(x, 1, 1) +#define V_INT_CLR_FBCD2(x) VAL_MASK(x, 1, 2) +#define V_INT_CLR_FBCD3(x) VAL_MASK(x, 1, 3) +#define V_INT_CLR_AFBCD0_HREG_DEC_RESP(x) VAL_MASK(x, 1, 4) +#define V_INT_CLR_AFBCD0_HREG_AXI_RRESP(x) VAL_MASK(x, 1, 5) +#define V_INT_CLR_AFBCD1_HREG_DEC_RESP(x) VAL_MASK(x, 1, 6) +#define V_INT_CLR_AFBCD1_HREG_AXI_RRESP(x) VAL_MASK(x, 1, 7) +#define V_INT_CLR_AFBCD2_HREG_DEC_RESP(x) VAL_MASK(x, 1, 8) +#define V_INT_CLR_AFBCD2_HREG_AXI_RRESP(x) VAL_MASK(x, 1, 9) +#define V_INT_CLR_AFBCD3_HREG_DEC_RESP(x) VAL_MASK(x, 1, 10) +#define V_INT_CLR_AFBCD3_HREG_AXI_RRESP(x) VAL_MASK(x, 1, 11) +#define V_INT_CLR_VFP(x) VAL_MASK(x, 1, 15) +#define INTR_STATUS1 0x00000298 +#define V_INT_STATUS_FBCD0(x) VAL_MASK(x, 1, 0) +#define V_INT_STATUS_FBCD1(x) VAL_MASK(x, 1, 1) +#define V_INT_STATUS_FBCD2(x) VAL_MASK(x, 1, 2) +#define V_INT_STATUS_FBCD3(x) VAL_MASK(x, 1, 3) +#define V_INT_STATUS_AFBCD0_HREG_DEC_RESP(x) VAL_MASK(x, 1, 4) +#define V_INT_STATUS_AFBCD0_HREG_AXI_RRESP(x) VAL_MASK(x, 1, 5) +#define V_INT_STATUS_AFBCD1_HREG_DEC_RESP(x) VAL_MASK(x, 1, 6) +#define V_INT_STATUS_AFBCD1_HREG_AXI_RRESP(x) VAL_MASK(x, 1, 7) +#define V_INT_STATUS_AFBCD2_HREG_DEC_RESP(x) VAL_MASK(x, 1, 8) +#define V_INT_STATUS_AFBCD2_HREG_AXI_RRESP(x) VAL_MASK(x, 1, 9) +#define V_INT_STATUS_AFBCD3_HREG_DEC_RESP(x) VAL_MASK(x, 1, 10) +#define V_INT_STATUS_AFBCD4_HREG_DEC_RESP(x) VAL_MASK(x, 1, 11) +#define V_INT_STATUS_VFP(x) VAL_MASK(x, 1, 15) +#define INTR_RAW_STATUS1 0x0000029c +#define V_INT_RAW_STATUS_FBCD0(x) VAL_MASK(x, 1, 0) +#define V_INT_RAW_STATUS_FBCD1(x) VAL_MASK(x, 1, 1) +#define V_INT_RAW_STATUS_FBCD2(x) VAL_MASK(x, 1, 2) +#define V_INT_RAW_STATUS_FBCD3(x) VAL_MASK(x, 1, 3) +#define V_INT_RAW_STATUS_AFBCD0_HREG_DEC_RESP(x) VAL_MASK(x, 1, 4) +#define V_INT_RAW_STATUS_AFBCD0_HREG_AXI_RRESP(x) VAL_MASK(x, 1, 5) +#define V_INT_RAW_STATUS_AFBCD1_HREG_DEC_RESP(x) VAL_MASK(x, 1, 6) +#define V_INT_RAW_STATUS_AFBCD1_HREG_AXI_RRESP(x) VAL_MASK(x, 1, 7) +#define V_INT_RAW_STATUS_AFBCD2_HREG_DEC_RESP(x) VAL_MASK(x, 1, 8) +#define V_INT_RAW_STATUS_AFBCD2_HREG_AXI_RRESP(x) VAL_MASK(x, 1, 9) +#define V_INT_RAW_STATUS_AFBCD3_HREG_DEC_RESP(x) VAL_MASK(x, 1, 10) +#define V_INT_RAW_STATUS_AFBCD3_HREG_AXI_RRESP(x) VAL_MASK(x, 1, 11) +#define V_INT_RAW_STATUS_VFP(x) VAL_MASK(x, 1, 15) +#define LINE_FLAG 0x000002a0 +#define V_DSP_LINE_FLAG_NUM_0(x) VAL_MASK(x, 13, 0) +#define V_DSP_LINE_FLAG_NUM_1(x) VAL_MASK(x, 13, 16) +#define VOP_STATUS 0x000002a4 +#define V_DSP_VCNT(x) VAL_MASK(x, 13, 0) +#define V_MMU_IDLE(x) VAL_MASK(x, 1, 16) +#define V_DMA_STOP_VALID(x) VAL_MASK(x, 1, 17) +#define BLANKING_VALUE 0x000002a8 +#define V_BLANKING_VALUE(x) VAL_MASK(x, 24, 0) +#define V_BLANKING_VALUE_CONFIG_EN(x) VAL_MASK(x, 1, 24) +#define MCU_BYPASS_PORT 0x000002ac +#define WIN0_DSP_BG 0x000002b0 +#define V_WIN0_DSP_BG_BLUE(x) VAL_MASK(x, 8, 0) +#define V_WIN0_DSP_BG_GREEN(x) VAL_MASK(x, 8, 8) +#define V_WIN0_DSP_BG_RED(x) VAL_MASK(x, 8, 16) +#define V_WIN0_BG_EN(x) VAL_MASK(x, 1, 31) +#define WIN1_DSP_BG 0x000002b4 +#define V_WIN1_DSP_BG_BLUE(x) VAL_MASK(x, 8, 0) +#define V_WIN1_DSP_BG_GREEN(x) VAL_MASK(x, 8, 8) +#define V_WIN1_DSP_BG_RED(x) VAL_MASK(x, 8, 16) +#define V_WIN1_BG_EN(x) VAL_MASK(x, 1, 31) +#define WIN2_DSP_BG 0x000002b8 +#define V_WIN2_DSP_BG_BLUE(x) VAL_MASK(x, 8, 0) +#define V_WIN2_DSP_BG_GREEN(x) VAL_MASK(x, 8, 8) +#define V_WIN2_DSP_BG_RED(x) VAL_MASK(x, 8, 16) +#define V_WIN2_BG_EN(x) VAL_MASK(x, 1, 31) +#define WIN3_DSP_BG 0x000002bc +#define V_WIN3_DSP_BG_BLUE(x) VAL_MASK(x, 8, 0) +#define V_WIN3_DSP_BG_GREEN(x) VAL_MASK(x, 8, 8) +#define V_WIN3_DSP_BG_RED(x) VAL_MASK(x, 8, 16) +#define V_WIN3_BG_EN(x) VAL_MASK(x, 1, 31) +#define YUV2YUV_WIN 0x000002c0 +#define V_WIN0_YUV2YUV_EN(x) VAL_MASK(x, 1, 0) +#define V_WIN0_YUV2YUV_Y2R_EN(x) VAL_MASK(x, 1, 1) +#define V_WIN0_YUV2YUV_R2Y_EN(x) VAL_MASK(x, 1, 2) +#define V_WIN0_YUV2YUV_GAMMA_MODE(x) VAL_MASK(x, 1, 3) +#define V_WIN0_YUV2YUV_Y2R_MODE(x) VAL_MASK(x, 2, 4) +#define V_WIN0_YUV2YUV_R2Y_MODE(x) VAL_MASK(x, 2, 6) +#define V_WIN1_YUV2YUV_EN(x) VAL_MASK(x, 1, 8) +#define V_WIN1_YUV2YUV_Y2R_EN(x) VAL_MASK(x, 1, 9) +#define V_WIN1_YUV2YUV_R2Y_EN(x) VAL_MASK(x, 1, 10) +#define V_WIN1_YUV2YUV_GAMMA_MODE(x) VAL_MASK(x, 1, 11) +#define V_WIN1_YUV2YUV_Y2R_MODE(x) VAL_MASK(x, 2, 12) +#define V_WIN1_YUV2YUV_R2Y_MODE(x) VAL_MASK(x, 2, 14) +#define V_WIN2_YUV2YUV_EN(x) VAL_MASK(x, 1, 16) +#define V_WIN2_YUV2YUV_R2Y_EN(x) VAL_MASK(x, 1, 18) +#define V_WIN2_YUV2YUV_GAMMA_MODE(x) VAL_MASK(x, 1, 19) +#define V_WIN2_YUV2YUV_R2Y_MODE(x) VAL_MASK(x, 2, 22) +#define V_WIN3_YUV2YUV_EN(x) VAL_MASK(x, 1, 24) +#define V_WIN3_YUV2YUV_R2Y_EN(x) VAL_MASK(x, 1, 26) +#define V_WIN3_YUV2YUV_GAMMA_MODE(x) VAL_MASK(x, 1, 27) +#define V_WIN3_YUV2YUV_R2Y_MODE(x) VAL_MASK(x, 2, 30) +#define YUV2YUV_POST 0x000002c4 +#define V_YUV2YUV_POST_EN(x) VAL_MASK(x, 1, 0) +#define V_YUV2YUV_POST_Y2R_EN(x) VAL_MASK(x, 1, 1) +#define V_YUV2YUV_POST_R2Y_EN(x) VAL_MASK(x, 1, 2) +#define V_YUV2YUV_GAMMA_MODE(x) VAL_MASK(x, 1, 3) +#define V_YUV2YUV_POST_Y2R_MODE(x) VAL_MASK(x, 2, 4) +#define V_YUV2YUV_POST_R2Y_MODE(x) VAL_MASK(x, 2, 6) +#define AUTO_GATING_EN 0x000002cc +#define V_WIN0_ACLK_GATING_EN(x) VAL_MASK(x, 1, 0) +#define V_WIN1_ACLK_GATING_EN(x) VAL_MASK(x, 1, 1) +#define V_WIN2_ACLK_GATING_EN(x) VAL_MASK(x, 1, 2) +#define V_WIN3_ACLK_GATING_EN(x) VAL_MASK(x, 1, 3) +#define V_HWC_ACLK_GATING_EN(x) VAL_MASK(x, 1, 4) +#define V_OVERLAY_ACLK_GATING_EN(x) VAL_MASK(x, 1, 5) +#define V_GAMMA_ACLK_GATING_EN(x) VAL_MASK(x, 1, 6) +#define V_CABC_ACLK_GATING_EN(x) VAL_MASK(x, 1, 7) +#define V_WB_ACLK_GATING_EN(x) VAL_MASK(x, 1, 8) +#define V_PWM_PWMCLK_GATING_EN(x) VAL_MASK(x, 1, 9) +#define V_DIRECT_PATH_ACLK_GATING_EN(x) VAL_MASK(x, 1, 10) +#define V_FBCD0_ACLK_GATING_EN(x) VAL_MASK(x, 1, 12) +#define V_FBCD1_ACLK_GATING_EN(x) VAL_MASK(x, 1, 13) +#define V_FBCD2_ACLK_GATING_EN(x) VAL_MASK(x, 1, 14) +#define V_FBCD3_ACLK_GATING_EN(x) VAL_MASK(x, 1, 15) +#define DBG_PERF_LATENCY_CTRL0 0x00000300 +#define V_RD_LATENCY_EN(x) VAL_MASK(x, 1, 0) +#define V_HAND_LATENCY_CLR(x) VAL_MASK(x, 1, 1) +#define V_RD_LATENCY_MODE(x) VAL_MASK(x, 1, 2) +#define V_RD_LATENCY_ID0(x) VAL_MASK(x, 4, 4) +#define V_RD_LATENCY_THR(x) VAL_MASK(x, 12, 8) +#define V_RD_LATENCY_ST_NUM(x) VAL_MASK(x, 5, 20) +#define DBG_PERF_RD_MAX_LATENCY_NUM0 0x00000304 +#define V_RD_MAX_LATENCY_NUM_CH0(x) VAL_MASK(x, 12, 0) +#define V_RD_LATENCY_OVERFLOW_CH0(x) VAL_MASK(x, 1, 16) +#define DBG_PERF_RD_LATENCY_THR_NUM0 0x00000308 +#define V_RD_LATENCY_THR_NUM_CH0(x) VAL_MASK(x, 24, 0) +#define DBG_PERF_RD_LATENCY_SAMP_NUM0 0x0000030c +#define V_RD_LATENCY_SAMP_NUM_CH0(x) VAL_MASK(x, 24, 0) +#define DBG_CABC0 0x00000310 +#define DBG_CABC1 0x00000314 +#define DBG_CABC2 0x00000318 +#define V_PWM_MUL_POST_VALUE(x) VAL_MASK(x, 8, 8) +#define DBG_CABC3 0x0000031c +#define DBG_WIN0_REG0 0x00000320 +#define DBG_WIN0_REG1 0x00000324 +#define DBG_WIN0_REG2 0x00000328 +#define V_DBG_WIN0_YRGB_CMD_LINE_CNT(x) VAL_MASK(x, 13, 16) +#define DBG_WIN0_RESERVED 0x0000032c +#define DBG_WIN1_REG0 0x00000330 +#define DBG_WIN1_REG1 0x00000334 +#define DBG_WIN1_REG2 0x00000338 +#define DBG_WIN1_RESERVED 0x0000033c +#define DBG_WIN2_REG0 0x00000340 +#define DBG_WIN2_REG1 0x00000344 +#define DBG_WIN2_REG2 0x00000348 +#define DBG_WIN2_REG3 0x0000034c +#define DBG_WIN3_REG0 0x00000350 +#define DBG_WIN3_REG1 0x00000354 +#define DBG_WIN3_REG2 0x00000358 +#define DBG_WIN3_REG3 0x0000035c +#define DBG_PRE_REG0 0x00000360 +#define DBG_PRE_RESERVED 0x00000364 +#define DBG_POST_REG0 0x00000368 +#define DBG_POST_REG1 0x0000036c +#define V_GAMMA_A2HCLK_CHANGE_DONE(x) VAL_MASK(x, 1, 0) +#define V_WHICH_GAMMA_LUT_WORKING(x) VAL_MASK(x, 1, 1) +#define DBG_DATAO 0x00000370 +#define V_SW_DATAO_SEL(x) VAL_MASK(x, 2, 30) +#define DBG_DATAO_2 0x00000374 +#define V_VOP_DATA_O_2(x) VAL_MASK(x, 30, 0) +#define V_SW_DATAO_SEL_2(x) VAL_MASK(x, 2, 30) +#define WIN0_CSC_COE 0x000003a0 +#define WIN1_CSC_COE 0x000003c0 +#define WIN2_CSC_COE 0x000003e0 +#define WIN3_CSC_COE 0x00000400 +#define HWC_CSC_COE 0x00000420 +#define BCSH_R2Y_CSC_COE 0x00000440 +#define BCSH_Y2R_CSC_COE 0x00000460 +#define POST_YUV2YUV_Y2R_COE 0x00000480 +#define POST_YUV2YUV_3x3_COE 0x000004a0 +#define POST_YUV2YUV_R2Y_COE 0x000004c0 +#define WIN2_LUT_ADDR 0x00001000 +#define V_WIN2_LUT_ADDR(x) VAL_MASK(x, 32, 0) +#define WIN3_LUT_ADDR 0x00001400 +#define V_WIN3_LUT_ADDR(x) VAL_MASK(x, 32, 0) +#define HWC_LUT_ADDR 0x00001800 +#define V_HWC_LUT_ADDR(x) VAL_MASK(x, 32, 0) +#define CABC_GAMMA_LUT_ADDR 0x00001c00 +#define V_GAMMA_LUT_ADDR(x) VAL_MASK(x, 32, 0) +#define GAMMA_LUT_ADDR 0x00002000 +#define V_GAMMA_LUT_ADDR(x) VAL_MASK(x, 32, 0) +#define TVE 0x00003e00 + +#define INTR_FS (1 << 0) +#define INTR_FS_NEW (1 << 1) +#define INTR_ADDR_SAME (1 << 2) +#define INTR_LINE_FLAG0 (1 << 3) +#define INTR_LINE_FLAG1 (1 << 4) +#define INTR_BUS_ERROR (1 << 5) +#define INTR_WIN0_EMPTY (1 << 6) +#define INTR_WIN1_EMPTY (1 << 7) +#define INTR_WIN2_EMPTY (1 << 8) +#define INTR_WIN3_EMPTY (1 << 9) +#define INTR_HWC_EMPTY (1 << 10) +#define INTR_POST_BUF_EMPTY (1 << 11) +#define INTR_PWM_GEN (1 << 12) +#define INTR_DSP_HOLD_VALID (1 << 13) +#define INTR_MMU (1 << 14) +#define INTR_DMA_FINISH (1 << 15) + +#define INTR_MASK (INTR_FS | INTR_FS_NEW | INTR_ADDR_SAME | INTR_LINE_FLAG0 | \ + INTR_LINE_FLAG1 | INTR_BUS_ERROR | INTR_WIN0_EMPTY | \ + INTR_WIN1_EMPTY | INTR_WIN2_EMPTY | INTR_WIN3_EMPTY | \ + INTR_HWC_EMPTY | INTR_POST_BUF_EMPTY | INTR_PWM_GEN | \ + INTR_DSP_HOLD_VALID | INTR_MMU | INTR_DMA_FINISH) + +#define INTR1_FBCD0 (1 << 0) +#define INTR1_FBCD1 (1 << 1) +#define INTR1_FBCD2 (1 << 2) +#define INTR1_FBCD3 (1 << 3) +#define INTR1_AFBCD0_HREG_DEC_RESP (1 << 4) +#define INTR1_AFBCD0_HREG_AXI_RRESP (1 << 5) +#define INTR1_AFBCD1_HREG_DEC_RESP (1 << 6) +#define INTR1_AFBCD1_HREG_AXI_RRESP (1 << 7) +#define INTR1_AFBCD2_HREG_DEC_RESP (1 << 8) +#define INTR1_AFBCD2_HREG_AXI_RRESP (1 << 9) +#define INTR1_AFBCD3_HREG_DEC_RESP (1 << 10) +#define INTR1_AFBCD3_HREG_AXI_RRESP (1 << 11) +#define INTR1_WB_YRGB_FIFO_FULL (1 << 12) +#define INTR1_WB_UV_FIFO_FULL (1 << 13) +#define INTR1_WB_FINISH (1 << 14) + +#define OUT_CCIR656_MODE_0 5 +#define OUT_CCIR656_MODE_1 6 +#define OUT_CCIR656_MODE_2 7 + +struct vop_device { + int id; + struct rk_lcdc_driver driver; + struct device *dev; + struct rk_screen *screen; + + void __iomem *regs; + void *regsbak; + u32 reg_phy_base; + u32 len; + + /* one time only one process allowed to config the register */ + spinlock_t reg_lock; + + int prop; /*used for primary or extended display device*/ + bool pre_init; + bool pwr18; /*if lcdc use 1.8v power supply*/ + /*if aclk or hclk is closed ,acess to register is not allowed*/ + bool clk_on; + /*active layer counter,when atv_layer_cnt = 0,disable lcdc*/ + u8 atv_layer_cnt; + + unsigned int irq; + + struct clk *hclk; /*lcdc AHP clk*/ + struct clk *dclk; /*lcdc dclk*/ + struct clk *aclk; /*lcdc share memory frequency*/ + u32 pixclock; + + u32 standby; /*1:standby,0:wrok*/ + u32 iommu_status; + struct backlight_device *backlight; + struct clk *pll_sclk; + + /* lock vop irq reg */ + spinlock_t irq_lock; +}; + +static inline void vop_writel(struct vop_device *vop_dev, u32 offset, u32 v) +{ + u32 *_pv = (u32 *)vop_dev->regsbak; + + _pv += (offset >> 2); + *_pv = v; + writel_relaxed(v, vop_dev->regs + offset); +} + +static inline u32 vop_readl(struct vop_device *vop_dev, u32 offset) +{ + u32 v; + + v = readl_relaxed(vop_dev->regs + offset); + return v; +} + +static inline u32 vop_readl_backup(struct vop_device *vop_dev, u32 offset) +{ + u32 v; + u32 *_pv = (u32 *)vop_dev->regsbak; + + _pv += (offset >> 2); + v = readl_relaxed(vop_dev->regs + offset); + *_pv = v; + return v; +} + +static inline u32 vop_read_bit(struct vop_device *vop_dev, u32 offset, u64 v) +{ + u32 _v = readl_relaxed(vop_dev->regs + offset); + + _v &= v >> 32; + v = (_v ? 1 : 0); + return v; +} + +static inline void vop_set_bit(struct vop_device *vop_dev, u32 offset, u64 v) +{ + u32 *_pv = (u32 *)vop_dev->regsbak; + + _pv += (offset >> 2); + (*_pv) |= v >> 32; + writel_relaxed(*_pv, vop_dev->regs + offset); +} + +static inline void vop_clr_bit(struct vop_device *vop_dev, u32 offset, u64 v) +{ + u32 *_pv = (u32 *)vop_dev->regsbak; + + _pv += (offset >> 2); + (*_pv) &= (~(v >> 32)); + writel_relaxed(*_pv, vop_dev->regs + offset); +} + +static inline void vop_msk_reg(struct vop_device *vop_dev, u32 offset, u64 v) +{ + u32 *_pv = (u32 *)vop_dev->regsbak; + + _pv += (offset >> 2); + (*_pv) &= (~(v >> 32)); + (*_pv) |= (u32)v; + writel_relaxed(*_pv, vop_dev->regs + offset); +} + +static inline void vop_mask_writel(struct vop_device *vop_dev, u32 offset, + u32 mask, u32 v) +{ + v = mask << 16 | v; + writel_relaxed(v , vop_dev->regs + offset); +} + +static inline void vop_cfg_done(struct vop_device *vop_dev) +{ + writel_relaxed(0x001f001f, vop_dev->regs + REG_CFG_DONE); + dsb(sy); +} + +static inline int vop_grf_writel(struct regmap *base, u32 offset, u32 val) +{ + regmap_write(base, offset, val); + dsb(sy); + + return 0; +} + +static inline int vop_cru_writel(struct regmap *base, u32 offset, u32 val) +{ + regmap_write(base, offset, val); + dsb(sy); + + return 0; +} + +static inline int vop_cru_readl(struct regmap *base, u32 offset) +{ + u32 v; + + regmap_read(base, offset, &v); + + return v; +} + +enum lb_mode { + LB_YUV_3840X5 = 0x0, + LB_YUV_2560X8 = 0x1, + LB_RGB_3840X2 = 0x2, + LB_RGB_2560X4 = 0x3, + LB_RGB_1920X5 = 0x4, + LB_RGB_1280X8 = 0x5 +}; + +enum sacle_up_mode { + SCALE_UP_BIL = 0x0, + SCALE_UP_BIC = 0x1 +}; + +enum scale_down_mode { + SCALE_DOWN_BIL = 0x0, + SCALE_DOWN_AVG = 0x1 +}; + +/*ALPHA BLENDING MODE*/ +enum alpha_mode { /* Fs Fd */ + AB_USER_DEFINE = 0x0, + AB_CLEAR = 0x1,/* 0 0*/ + AB_SRC = 0x2,/* 1 0*/ + AB_DST = 0x3,/* 0 1 */ + AB_SRC_OVER = 0x4,/* 1 1-As''*/ + AB_DST_OVER = 0x5,/* 1-Ad'' 1*/ + AB_SRC_IN = 0x6, + AB_DST_IN = 0x7, + AB_SRC_OUT = 0x8, + AB_DST_OUT = 0x9, + AB_SRC_ATOP = 0xa, + AB_DST_ATOP = 0xb, + XOR = 0xc, + AB_SRC_OVER_GLOBAL = 0xd +}; /*alpha_blending_mode*/ + +enum src_alpha_mode { + AA_STRAIGHT = 0x0, + AA_INVERSE = 0x1 +};/*src_alpha_mode*/ + +enum global_alpha_mode { + AA_GLOBAL = 0x0, + AA_PER_PIX = 0x1, + AA_PER_PIX_GLOBAL = 0x2 +};/*src_global_alpha_mode*/ + +enum src_alpha_sel { + AA_SAT = 0x0, + AA_NO_SAT = 0x1 +};/*src_alpha_sel*/ + +enum src_color_mode { + AA_SRC_PRE_MUL = 0x0, + AA_SRC_NO_PRE_MUL = 0x1 +};/*src_color_mode*/ + +enum factor_mode { + AA_ZERO = 0x0, + AA_ONE = 0x1, + AA_SRC = 0x2, + AA_SRC_INVERSE = 0x3, + AA_SRC_GLOBAL = 0x4 +};/*src_factor_mode && dst_factor_mode*/ + +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_format { + VOP_FORMAT_ARGB888 = 0, + VOP_FORMAT_RGB888, + VOP_FORMAT_RGB565, + VOP_FORMAT_YCBCR420 = 4, + VOP_FORMAT_YCBCR422, + VOP_FORMAT_YCBCR444 +}; + +#define IS_YUV(x) ((x) >= VOP_FORMAT_YCBCR420) + +enum _vop_overlay_mode { + VOP_RGB_DOMAIN, + VOP_YUV_DOMAIN +}; + +struct alpha_config { + enum src_alpha_mode src_alpha_mode; /*win0_src_alpha_m0*/ + u32 src_global_alpha_val; /*win0_src_global_alpha*/ + enum global_alpha_mode src_global_alpha_mode;/*win0_src_blend_m0*/ + enum src_alpha_sel src_alpha_cal_m0; /*win0_src_alpha_cal_m0*/ + enum src_color_mode src_color_mode; /*win0_src_color_m0*/ + enum factor_mode src_factor_mode; /*win0_src_factor_m0*/ + enum factor_mode dst_factor_mode; /*win0_dst_factor_m0*/ +}; + +struct lcdc_cabc_mode { + u32 pixel_num; /* pixel precent number */ + u16 stage_up; /* up stride */ + u16 stage_down; /* down stride */ + u16 global_su; +}; + +#define CUBIC_PRECISE 0 +#define CUBIC_SPLINE 1 +#define CUBIC_CATROM 2 +#define CUBIC_MITCHELL 3 + +#define FBDC_FMT_RGB565 0x5 +#define FBDC_FMT_U8U8U8U8 0xc /*ARGB888*/ +#define FBDC_FMT_U8U8U8 0x3a /*RGBP888*/ + +#define CUBIC_MODE_SELETION CUBIC_PRECISE + +/*************************************************************/ +#define SCALE_FACTOR_BILI_DN_FIXPOINT_SHIFT 12 /* 4.12*/ +#define SCALE_FACTOR_BILI_DN_FIXPOINT(x) \ + ((INT32)((x) * (1 << SCALE_FACTOR_BILI_DN_FIXPOINT_SHIFT))) + +#define SCALE_FACTOR_BILI_UP_FIXPOINT_SHIFT 16 /* 0.16*/ + +#define SCALE_FACTOR_AVRG_FIXPOINT_SHIFT 16 /*0.16*/ +#define SCALE_FACTOR_AVRG_FIXPOINT(x) \ + ((INT32)((x) * (1 << SCALE_FACTOR_AVRG_FIXPOINT_SHIFT))) + +#define SCALE_FACTOR_BIC_FIXPOINT_SHIFT 16 /* 0.16*/ +#define SCALE_FACTOR_BIC_FIXPOINT(x) \ + ((INT32)((x) * (1 << SCALE_FACTOR_BIC_FIXPOINT_SHIFT))) + +#define SCALE_FACTOR_DEFAULT_FIXPOINT_SHIFT 12 /*NONE SCALE,vsd_bil*/ +#define SCALE_FACTOR_VSDBIL_FIXPOINT_SHIFT 12 /*VER SCALE DOWN BIL*/ + +/*********************************************************/ + +/*#define GET_SCALE_FACTOR_BILI(src, dst) \ + ((((src) - 1) << SCALE_FACTOR_BILI_FIXPOINT_SHIFT) / ((dst) - 1))*/ +/*#define GET_SCALE_FACTOR_BIC(src, dst) \ + ((((src) - 1) << SCALE_FACTOR_BIC_FIXPOINT_SHIFT) / ((dst) - 1))*/ +/*modified by hpz*/ +#define GET_SCALE_FACTOR_BILI_DN(src, dst) \ + ((((src) * 2 - 3) << (SCALE_FACTOR_BILI_DN_FIXPOINT_SHIFT - 1)) \ + / ((dst) - 1)) +#define GET_SCALE_FACTOR_BILI_UP(src, dst) \ + ((((src) * 2 - 3) << (SCALE_FACTOR_BILI_UP_FIXPOINT_SHIFT - 1)) \ + / ((dst) - 1)) +#define GET_SCALE_FACTOR_BIC(src, dst) \ + ((((src) * 2 - 3) << (SCALE_FACTOR_BIC_FIXPOINT_SHIFT - 1)) \ + / ((dst) - 1)) + +/*********************************************************/ +/*NOTE: hardware in order to save resource , srch first to get interlace line +(srch+vscalednmult-1)/vscalednmult; and do scale*/ +#define GET_SCALE_DN_ACT_HEIGHT(srch, vscalednmult) \ + (((srch) + (vscalednmult) - 1) / (vscalednmult)) + +/*#define VSKIP_MORE_PRECISE*/ + +#ifdef VSKIP_MORE_PRECISE +#define MIN_SCALE_FACTOR_AFTER_VSKIP 1.5f +#define GET_SCALE_FACTOR_BILI_DN_VSKIP(srch, dsth, vscalednmult) \ + (GET_SCALE_FACTOR_BILI_DN(GET_SCALE_DN_ACT_HEIGHT((srch),\ + (vscalednmult)), (dsth))) +#else +#define MIN_SCALE_FACTOR_AFTER_VSKIP 1 +#define GET_SCALE_FACTOR_BILI_DN_VSKIP(srch, dsth, vscalednmult) \ + ((GET_SCALE_DN_ACT_HEIGHT((srch) , (vscalednmult)) == (dsth)) \ + ? (GET_SCALE_FACTOR_BILI_DN((srch) , (dsth)) / (vscalednmult)) \ + : (GET_SCALE_DN_ACT_HEIGHT((srch) , (vscalednmult)) == ((dsth) * 2)) \ + ? GET_SCALE_FACTOR_BILI_DN(GET_SCALE_DN_ACT_HEIGHT(((srch) - 1),\ + (vscalednmult)) , (dsth)) : \ + GET_SCALE_FACTOR_BILI_DN(GET_SCALE_DN_ACT_HEIGHT((srch),\ + (vscalednmult)) , (dsth))) + +#endif +/*****************************************************************/ + +/*scalefactor must >= dst/src, or pixels at end of line may be unused*/ +/*scalefactor must < dst/(src-1), or dst buffer may overflow*/ +/*avrg old code: ((((dst) << SCALE_FACTOR_AVRG_FIXPOINT_SHIFT))\ + /((src) - 1)) hxx_chgsrc*/ +/*modified by hpz:*/ +#define GET_SCALE_FACTOR_AVRG(src, dst) ((((dst) << \ + (SCALE_FACTOR_AVRG_FIXPOINT_SHIFT + 1))) / (2 * (src) - 1)) + +/*************************************************************************/ +/*Scale Coordinate Accumulate, x.16*/ +#define SCALE_COOR_ACC_FIXPOINT_SHIFT 16 +#define SCALE_COOR_ACC_FIXPOINT_ONE (1 << SCALE_COOR_ACC_FIXPOINT_SHIFT) +#define SCALE_COOR_ACC_FIXPOINT(x) \ + ((INT32)((x)*(1 << SCALE_COOR_ACC_FIXPOINT_SHIFT))) +#define SCALE_COOR_ACC_FIXPOINT_REVERT(x) \ + ((((x) >> (SCALE_COOR_ACC_FIXPOINT_SHIFT - 1)) + 1) >> 1) + +#define SCALE_GET_COOR_ACC_FIXPOINT(scalefactor, factorfixpointshift) \ + ((scalefactor) << \ + (SCALE_COOR_ACC_FIXPOINT_SHIFT - (factorfixpointshift))) + +/************************************************************************/ +/*CoarsePart of Scale Coordinate Accumulate, used for pixel mult-add factor, 0.8*/ +#define SCALE_FILTER_FACTOR_FIXPOINT_SHIFT 8 +#define SCALE_FILTER_FACTOR_FIXPOINT_ONE \ + (1 << SCALE_FILTER_FACTOR_FIXPOINT_SHIFT) +#define SCALE_FILTER_FACTOR_FIXPOINT(x) \ + ((INT32)((x) * (1 << SCALE_FILTER_FACTOR_FIXPOINT_SHIFT))) +#define SCALE_FILTER_FACTOR_FIXPOINT_REVERT(x) \ + ((((x) >> (SCALE_FILTER_FACTOR_FIXPOINT_SHIFT-1)) + 1) >> 1) + +#define SCALE_GET_FILTER_FACTOR_FIXPOINT(cooraccumulate, \ + cooraccfixpointshift) \ + (((cooraccumulate) >> \ + ((cooraccfixpointshift) - SCALE_FILTER_FACTOR_FIXPOINT_SHIFT)) & \ + (SCALE_FILTER_FACTOR_FIXPOINT_ONE - 1)) + +#define SCALE_OFFSET_FIXPOINT_SHIFT 8 +#define SCALE_OFFSET_FIXPOINT(x) \ + ((INT32)((x) * (1 << SCALE_OFFSET_FIXPOINT_SHIFT))) + +static inline u32 vop_get_hard_ware_vskiplines(u32 srch, u32 dsth) +{ + u32 vscalednmult; + + if (srch >= (u32) (4 * dsth * MIN_SCALE_FACTOR_AFTER_VSKIP)) + vscalednmult = 4; + else if (srch >= (u32) (2 * dsth * MIN_SCALE_FACTOR_AFTER_VSKIP)) + vscalednmult = 2; + else + vscalednmult = 1; + + return vscalednmult; +} + +#endif -- 2.34.1