From 09c9eeed007d965e5fb52d0cc6c05406ccaa79fa Mon Sep 17 00:00:00 2001 From: Andy Yan Date: Mon, 30 Nov 2020 08:35:28 +0800 Subject: [PATCH] drm/rockchip: vop2: Add writeback support VOP2 has a writeback with max 1920 x 1080 output. Writeback work as a connector in drm system. Change-Id: I670ca8de5155f1102454c618c62dd0c51fa45202 Signed-off-by: Andy Yan --- drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 26 ++ drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 355 ++++++++++++++++++- drivers/gpu/drm/rockchip/rockchip_vop2_reg.c | 35 ++ drivers/gpu/drm/rockchip/rockchip_vop_reg.h | 5 + 4 files changed, 420 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h index 8eb7f57b05bd..56405214b4e6 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h @@ -601,6 +601,20 @@ struct vop2_video_port_regs { struct vop_reg bcsh_en; }; +struct vop2_wb_regs { + struct vop_reg enable; + struct vop_reg format; + struct vop_reg dither_en; + struct vop_reg r2y_en; + struct vop_reg yrgb_mst; + struct vop_reg uv_mst; + struct vop_reg vp_id; + struct vop_reg fifo_throd; + struct vop_reg scale_x_factor; + struct vop_reg scale_x_en; + struct vop_reg scale_y_en; +}; + struct vop_win_data { uint32_t base; enum drm_plane_type type; @@ -644,6 +658,13 @@ struct vop2_win_data { const uint8_t dly[VOP2_DLY_MODE_MAX]; }; +struct vop2_wb_data { + uint32_t nformats; + const uint32_t *formats; + struct vop_rect max_output; + const struct vop2_wb_regs *regs; +}; + struct vop2_video_port_data { char id; uint32_t feature; @@ -712,6 +733,7 @@ struct vop_data { struct vop2_ctrl { struct vop_reg cfg_done_en; + struct vop_reg wb_cfg_done; struct vop_reg auto_gating_en; struct vop_reg ovl_cfg_done_port; struct vop_reg ovl_port_mux_cfg_done_imd; @@ -804,6 +826,7 @@ struct vop2_data { const struct vop2_ctrl *ctrl; const struct vop2_win_data *win; const struct vop2_video_port_data *vp; + const struct vop2_wb_data *wb; const struct vop2_layer_data *layer; const struct vop_csc_table *csc_table; const struct vop_hdr_table *hdr_table; @@ -834,6 +857,9 @@ struct vop2_data { #define DMA_FINISH_INTR BIT(14) #define FS_FIELD_INTR BIT(15) #define FE_INTR BIT(16) +#define WB_UV_FIFO_FULL_INTR BIT(17) +#define WB_YRGB_FIFO_FULL_INTR BIT(18) +#define WB_COMPLETE_INTR BIT(19) #define INTR_MASK (DSP_HOLD_VALID_INTR | FS_INTR | \ LINE_FLAG_INTR | BUS_ERROR_INTR | \ diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index bdb4d0ccd7fe..44d6162e4fa6 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -10,6 +10,7 @@ #include #include #include +#include #ifdef CONFIG_DRM_ANALOGIX_DP #include #endif @@ -124,6 +125,7 @@ #define to_vop2_video_port(c) container_of(c, struct vop2_video_port, crtc) #define to_vop2_win(x) container_of(x, struct vop2_win, base) #define to_vop2_plane_state(x) container_of(x, struct vop2_plane_state, base) +#define to_wb_state(x) container_of(x, struct vop2_wb_connector_state, base) #define ROCKCHIP_AFBC_MOD DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16) @@ -322,6 +324,31 @@ struct vop2_layer { const struct vop2_layer_regs *regs; }; +struct vop2_wb { + uint8_t vp_id; + struct drm_writeback_connector conn; + const struct vop2_wb_regs *regs; +}; + +enum vop2_wb_format { + VOP2_WB_ARGB8888, + VOP2_WB_RGB888, + VOP2_WB_RGB565, + VOP2_WB_YUV420SP = 4, + VOP2_WB_INVALID = -1, +}; + +struct vop2_wb_connector_state { + struct drm_connector_state base; + dma_addr_t yrgb_addr; + dma_addr_t uv_addr; + enum vop2_wb_format format; + uint16_t scale_x_factor; + uint8_t scale_x_en; + uint8_t scale_y_en; + uint8_t vp_id; +}; + struct vop2_video_port { struct drm_crtc crtc; struct vop2 *vop2; @@ -355,6 +382,17 @@ struct vop2_video_port { */ bool sdr2hdr_en; + /** + * @wb_en: write back enabled on this port; + */ + bool wb_en; + + /** + * @fs_vsync_cnt: frame start vysnc counter, + * used to get the write back complete event; + */ + uint32_t fs_vsync_cnt; + /** * @bg_ovl_dly: The timing delay from background layer * to overlay module. @@ -386,6 +424,7 @@ struct vop2 { struct device *dev; struct drm_device *drm_dev; struct vop2_video_port vps[ROCKCHIP_MAX_CRTC]; + struct vop2_wb wb; struct dentry *debugfs; struct drm_info_list *debugfs_files; struct drm_property *soc_id_prop; @@ -680,6 +719,13 @@ static inline void vop2_cfg_done(struct drm_crtc *crtc) VOP_MODULE_SET(vop2, vp, cfg_done, 1); } +static inline void vop2_wb_cfg_done(struct vop2 *vop2) +{ + uint32_t val = RK3568_VOP2_WB_CFG_DONE | (RK3568_VOP2_WB_CFG_DONE << 16); + + vop2_writel(vop2, 0, val); +} + static void vop2_win_disable(struct vop2_win *win) { struct vop2 *vop2 = win->vop2; @@ -765,6 +811,23 @@ static enum vop2_afbc_format vop2_convert_afbc_format(uint32_t format) return -EINVAL; } +static enum vop2_wb_format vop2_convert_wb_format(uint32_t format) +{ + switch (format) { + case DRM_FORMAT_ARGB8888: + return VOP2_WB_ARGB8888; + case DRM_FORMAT_RGB888: + return VOP2_WB_RGB888; + case DRM_FORMAT_RGB565: + return VOP2_WB_RGB565; + case DRM_FORMAT_NV12: + return VOP2_WB_YUV420SP; + default: + DRM_ERROR("unsupported wb format[%08x]\n", format); + return VOP2_WB_INVALID; + } +} + static bool vop2_win_rb_swap(uint32_t format) { switch (format) { @@ -1452,6 +1515,264 @@ static void vop2_core_clks_disable(struct vop2 *vop2) clk_disable(vop2->hclk); } +static void vop2_wb_connector_reset(struct drm_connector *connector) +{ + struct vop2_wb_connector_state *wb_state; + + if (connector->state) { + __drm_atomic_helper_connector_destroy_state(connector->state); + kfree(connector->state); + connector->state = NULL; + } + + wb_state = kzalloc(sizeof(*wb_state), GFP_KERNEL); + if (wb_state) + __drm_atomic_helper_connector_reset(connector, &wb_state->base); +} + +static enum drm_connector_status +vop2_wb_connector_detect(struct drm_connector *connector, bool force) +{ + return connector_status_connected; +} + +static void vop2_wb_connector_destroy(struct drm_connector *connector) +{ + drm_connector_cleanup(connector); +} + +static struct drm_connector_state * +vop2_wb_connector_duplicate_state(struct drm_connector *connector) +{ + struct vop2_wb_connector_state *wb_state; + + if (WARN_ON(!connector->state)) + return NULL; + + wb_state = kzalloc(sizeof(*wb_state), GFP_KERNEL); + if (!wb_state) + return NULL; + + __drm_atomic_helper_connector_duplicate_state(connector, &wb_state->base); + + return &wb_state->base; +} + +static const struct drm_connector_funcs vop2_wb_connector_funcs = { + .reset = vop2_wb_connector_reset, + .detect = vop2_wb_connector_detect, + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = vop2_wb_connector_destroy, + .atomic_duplicate_state = vop2_wb_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, +}; + +static int vop2_wb_connector_get_modes(struct drm_connector *connector) +{ + struct drm_display_mode *mode; + int i; + + for (i = 0; i < 2; i++) { + mode = drm_mode_create(connector->dev); + if (!mode) + break; + + mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER; + mode->clock = 148500 >> i; + mode->hdisplay = 1920 >> i; + mode->hsync_start = 1930 >> i; + mode->hsync_end = 1940 >> i; + mode->htotal = 1990 >> i; + mode->vdisplay = 1080 >> i; + mode->vsync_start = 1090 >> i; + mode->vsync_end = 1100 >> i; + mode->vtotal = 1110 >> i; + mode->flags = 0; + + drm_mode_set_name(mode); + drm_mode_probed_add(connector, mode); + } + return i; +} + +static enum drm_mode_status +vop2_wb_connector_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + + struct drm_writeback_connector *wb_conn; + struct vop2_wb *wb; + struct vop2 *vop2; + int w, h; + + wb_conn = container_of(connector, struct drm_writeback_connector, base); + wb = container_of(wb_conn, struct vop2_wb, conn); + vop2 = container_of(wb, struct vop2, wb); + w = mode->hdisplay; + h = mode->vdisplay; + + + if (w > vop2->data->wb->max_output.width) + return MODE_BAD_HVALUE; + + if (h > vop2->data->wb->max_output.height) + return MODE_BAD_VVALUE; + + return MODE_OK; +} + +static int vop2_wb_encoder_atomic_check(struct drm_encoder *encoder, + struct drm_crtc_state *cstate, + struct drm_connector_state *conn_state) +{ + struct vop2_wb_connector_state *wb_state = to_wb_state(conn_state); + struct drm_crtc *crtc = cstate->crtc; + struct vop2_video_port *vp = to_vop2_video_port(crtc); + struct drm_framebuffer *fb; + + if (!conn_state->writeback_job || !conn_state->writeback_job->fb) + return 0; + + fb = conn_state->writeback_job->fb; + DRM_DEV_DEBUG(vp->vop2->dev, "%d x % d\n", fb->width, fb->height); + if ((fb->width > cstate->mode.hdisplay) || + ((fb->height != cstate->mode.vdisplay) && + (fb->height != (cstate->mode.vdisplay >> 1)))) { + DRM_DEBUG_KMS("Invalid framebuffer size %ux%u, Only support x scale down and 1/2 y scale down\n", + fb->width, fb->height); + return -EINVAL; + } + + wb_state->scale_x_factor = vop2_scale_factor(SCALE_DOWN, VOP2_SCALE_DOWN_BIL, + cstate->mode.hdisplay, fb->width); + wb_state->scale_x_en = (fb->width < cstate->mode.hdisplay) ? 1 : 0; + wb_state->scale_y_en = (fb->height < cstate->mode.vdisplay) ? 1 : 0; + + wb_state->format = vop2_convert_wb_format(fb->format->format); + if (wb_state->format < 0) { + struct drm_format_name_buf format_name; + + DRM_DEBUG_KMS("Invalid pixel format %s\n", + drm_get_format_name(fb->format->format, + &format_name)); + return -EINVAL; + } + + wb_state->vp_id = vp->id; + wb_state->yrgb_addr = rockchip_fb_get_dma_addr(fb, 0); + if (fb->format->is_yuv) { + wb_state->uv_addr = rockchip_fb_get_dma_addr(fb, 1); + wb_state->uv_addr += fb->offsets[1]; + } + + return 0; +} + +static const struct drm_encoder_helper_funcs vop2_wb_encoder_helper_funcs = { + .atomic_check = vop2_wb_encoder_atomic_check, +}; + +static const struct drm_connector_helper_funcs vop2_wb_connector_helper_funcs = { + .get_modes = vop2_wb_connector_get_modes, + .mode_valid = vop2_wb_connector_mode_valid, +}; + + +static int vop2_wb_connector_init(struct vop2 *vop2) +{ + const struct vop2_data *vop2_data = vop2->data; + int ret; + + vop2->wb.regs = vop2_data->wb->regs; + vop2->wb.conn.encoder.possible_crtcs = (1 << vop2_data->nr_vps) - 1; + drm_connector_helper_add(&vop2->wb.conn.base, &vop2_wb_connector_helper_funcs); + + ret = drm_writeback_connector_init(vop2->drm_dev, &vop2->wb.conn, + &vop2_wb_connector_funcs, + &vop2_wb_encoder_helper_funcs, + vop2_data->wb->formats, + vop2_data->wb->nformats); + if (ret) + DRM_DEV_ERROR(vop2->dev, "writeback connector init failed\n"); + return ret; +} + +static void vop2_wb_irqs_enable(struct vop2 *vop2) +{ + const struct vop2_data *vop2_data = vop2->data; + const struct vop_intr *intr = &vop2_data->axi_intr[0]; + uint32_t irqs = WB_UV_FIFO_FULL_INTR | WB_YRGB_FIFO_FULL_INTR; + + VOP_INTR_SET_TYPE(vop2, intr, clear, irqs, 1); + VOP_INTR_SET_TYPE(vop2, intr, enable, irqs, 1); +} + +static uint32_t vop2_read_and_clear_wb_irqs(struct vop2 *vop2) +{ + const struct vop2_data *vop2_data = vop2->data; + const struct vop_intr *intr = &vop2_data->axi_intr[0]; + uint32_t irqs = WB_UV_FIFO_FULL_INTR | WB_YRGB_FIFO_FULL_INTR; + uint32_t val; + + val = VOP_INTR_GET_TYPE(vop2, intr, status, irqs); + if (val) + VOP_INTR_SET_TYPE(vop2, intr, clear, val, 1); + + + return val; +} + +static void vop2_wb_commit(struct drm_crtc *crtc) +{ + struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state); + struct vop2_video_port *vp = to_vop2_video_port(crtc); + struct vop2 *vop2 = vp->vop2; + struct vop2_wb *wb = &vop2->wb; + struct drm_writeback_connector *wb_conn = &wb->conn; + struct drm_connector_state *conn_state = wb_conn->base.state; + struct vop2_wb_connector_state *wb_state; + uint32_t fifo_throd; + uint8_t r2y; + + if (!conn_state) + return; + wb_state = to_wb_state(conn_state); + + if (wb_state->vp_id != vp->id) + return; + + if (conn_state->writeback_job && conn_state->writeback_job->fb) { + struct drm_framebuffer *fb = conn_state->writeback_job->fb; + + DRM_DEV_DEBUG(vop2->dev, "Enable wb %ux%u fmt: %u pitches: %d\n", + fb->width, fb->height, wb_state->format, fb->pitches[0]); + + drm_writeback_queue_job(wb_conn, conn_state->writeback_job); + conn_state->writeback_job = NULL; + + fifo_throd = fb->pitches[0] >> 4; + r2y = is_yuv_support(fb->format->format) && (!is_yuv_output(vcstate->bus_format)); + + /* + * the vp_id register config done immediately + */ + VOP_MODULE_SET(vop2, wb, vp_id, wb_state->vp_id); + VOP_MODULE_SET(vop2, wb, format, wb_state->format); + VOP_MODULE_SET(vop2, wb, yrgb_mst, wb_state->yrgb_addr); + VOP_MODULE_SET(vop2, wb, uv_mst, wb_state->uv_addr); + VOP_MODULE_SET(vop2, wb, fifo_throd, fifo_throd); + VOP_MODULE_SET(vop2, wb, scale_x_factor, wb_state->scale_x_factor); + VOP_MODULE_SET(vop2, wb, scale_x_en, wb_state->scale_x_en); + VOP_MODULE_SET(vop2, wb, scale_y_en, wb_state->scale_y_en); + VOP_MODULE_SET(vop2, wb, r2y_en, r2y); + VOP_MODULE_SET(vop2, wb, enable, 1); + vop2_wb_irqs_enable(vop2); + vp->wb_en = true; + vp->fs_vsync_cnt = 0; + } +} + + static void vop2_crtc_load_lut(struct drm_crtc *crtc) { struct vop2_video_port *vp = to_vop2_video_port(crtc); @@ -3917,6 +4238,7 @@ static void vop2_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_crtc_state spin_lock_irqsave(&vop2->irq_lock, flags); + vop2_wb_commit(crtc); vop2_cfg_done(crtc); spin_unlock_irqrestore(&vop2->irq_lock, flags); @@ -4234,9 +4556,11 @@ static irqreturn_t vop2_isr(int irq, void *data) const struct vop2_data *vop2_data = vop2->data; size_t vp_max = min_t(size_t, vop2_data->nr_vps, ROCKCHIP_MAX_CRTC); size_t axi_max = min_t(size_t, vop2_data->nr_axi_intr, VOP2_SYS_AXI_BUS_NUM); + struct vop2_wb *wb = &vop2->wb; uint32_t vp_irqs[ROCKCHIP_MAX_CRTC]; uint32_t axi_irqs[VOP2_SYS_AXI_BUS_NUM]; uint32_t active_irqs; + uint32_t wb_irqs; unsigned long flags; int ret = IRQ_NONE; int i; @@ -4271,6 +4595,7 @@ static irqreturn_t vop2_isr(int irq, void *data) vp_irqs[i] = vop2_read_and_clear_active_vp_irqs(vop2, i); for (i = 0; i < axi_max; i++) axi_irqs[i] = vop2_read_and_clear_axi_irqs(vop2, i); + wb_irqs = vop2_read_and_clear_wb_irqs(vop2); spin_unlock_irqrestore(&vop2->irq_lock, flags); for (i = 0; i < vp_max; i++) { @@ -4293,6 +4618,28 @@ static irqreturn_t vop2_isr(int irq, void *data) drm_crtc_handle_vblank(crtc); vop2_handle_vblank(vop2, crtc); active_irqs &= ~FS_FIELD_INTR; + + if (vp->wb_en) { + vp->fs_vsync_cnt++; + /* + * First frame start, the start of the write back + * we should stop when write back complete. + */ + if (vp->fs_vsync_cnt == 1) { + VOP_MODULE_SET(vop2, wb, enable, 0); + vop2_wb_cfg_done(vop2); + } + + /* + * Second frame start, write back complete now. + */ + if (vp->fs_vsync_cnt == 2) { + drm_writeback_signal_completion(&vop2->wb.conn, 0); + vp->wb_en = 0; + } + + + } ret = IRQ_HANDLED; } @@ -4303,6 +4650,12 @@ static irqreturn_t vop2_isr(int irq, void *data) DRM_ERROR("Unknown video_port%d IRQs: %02x\n", i, active_irqs); } + if (wb_irqs) { + active_irqs = wb_irqs; + ERROR_HANDLER(WB_UV_FIFO_FULL); + ERROR_HANDLER(WB_YRGB_FIFO_FULL); + } + for (i = 0; i < axi_max; i++) { active_irqs = axi_irqs[i]; @@ -4842,7 +5195,7 @@ static int vop2_bind(struct device *dev, struct device *master, void *data) ret = vop2_gamma_init(vop2); if (ret) return ret; - + vop2_wb_connector_init(vop2); pm_runtime_enable(&pdev->dev); return 0; diff --git a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c index f0f13ebc10be..1a0dca53adbd 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c @@ -53,6 +53,13 @@ static const uint32_t formats_win_lite[] = { DRM_FORMAT_BGR565, }; +static const u32 formats_wb[] = { + DRM_FORMAT_RGB888, + DRM_FORMAT_ARGB8888, + DRM_FORMAT_RGB565, + DRM_FORMAT_NV12, +}; + static const u32 sdr2hdr_bt1886eotf_yn_for_hlg_hdr[65] = { 0, 1, 7, 17, 35, @@ -287,6 +294,11 @@ static const struct vop_hdr_table rk3568_vop_hdr_table = { static const int rk3568_vop_axi_intrs[] = { 0, BUS_ERROR_INTR, + 0, + WB_UV_FIFO_FULL_INTR, + WB_YRGB_FIFO_FULL_INTR, + WB_COMPLETE_INTR, + }; static const struct vop_intr rk3568_vop_axi_intr[] = { @@ -347,6 +359,27 @@ static const struct vop_intr rk3568_vp2_intr = { .clear = VOP_REG_MASK(RK3568_VP2_INT_CLR, 0xffff, 0), }; +static const struct vop2_wb_regs rk3568_vop_wb_regs = { + .enable = VOP_REG(RK3568_WB_CTRL, 0x1, 0), + .format = VOP_REG(RK3568_WB_CTRL, 0x7, 1), + .dither_en = VOP_REG(RK3568_WB_CTRL, 0x1, 4), + .r2y_en = VOP_REG(RK3568_WB_CTRL, 0x1, 5), + .scale_x_en = VOP_REG(RK3568_WB_CTRL, 0x1, 7), + .scale_y_en = VOP_REG(RK3568_WB_CTRL, 0x1, 8), + .scale_x_factor = VOP_REG(RK3568_WB_XSCAL_FACTOR, 0x3fff, 16), + .yrgb_mst = VOP_REG(RK3568_WB_YRGB_MST, 0xffffffff, 0), + .uv_mst = VOP_REG(RK3568_WB_CBR_MST, 0xffffffff, 0), + .vp_id = VOP_REG(RK3568_LUT_PORT_SEL, 0x3, 8), + .fifo_throd = VOP_REG(RK3568_WB_XSCAL_FACTOR, 0x3ff, 0), +}; + +static const struct vop2_wb_data rk3568_vop_wb_data = { + .formats = formats_wb, + .nformats = ARRAY_SIZE(formats_wb), + .max_output = { 1920, 1080 }, + .regs = &rk3568_vop_wb_regs, +}; + static const struct vop2_video_port_regs rk3568_vop_vp0_regs = { .cfg_done = VOP_REG(RK3568_REG_CFG_DONE, 0x1, 0), .overlay_mode = VOP_REG(RK3568_OVL_CTRL, 0x1, 0), @@ -1059,6 +1092,7 @@ static const struct vop_grf_ctrl rk3568_grf_ctrl = { static const struct vop2_ctrl rk3568_vop_ctrl = { .cfg_done_en = VOP_REG(RK3568_REG_CFG_DONE, 0x1, 15), + .wb_cfg_done = VOP_REG_MASK(RK3568_REG_CFG_DONE, 0x1, 14), .auto_gating_en = VOP_REG(RK3568_SYS_AUTO_GATING_CTRL, 0x1, 31), .ovl_cfg_done_port = VOP_REG(RK3568_OVL_CTRL, 0x3, 30), .ovl_port_mux_cfg_done_imd = VOP_REG(RK3568_OVL_CTRL, 0x1, 28), @@ -1127,6 +1161,7 @@ static const struct vop2_data rk3568_vop = { .axi_intr = rk3568_vop_axi_intr, .nr_axi_intr = ARRAY_SIZE(rk3568_vop_axi_intr), .vp = rk3568_vop_video_ports, + .wb = &rk3568_vop_wb_data, .layer = rk3568_vop_layers, .nr_layers = ARRAY_SIZE(rk3568_vop_layers), .win = rk3568_vop_win_data, diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.h b/drivers/gpu/drm/rockchip/rockchip_vop_reg.h index a3875b77cde5..2b3b302e4884 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.h +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.h @@ -1050,11 +1050,16 @@ #define RK3568_GRF_VO_CON1 0x0364 /* System registers definition */ #define RK3568_REG_CFG_DONE 0x000 +#define RK3568_VOP2_WB_CFG_DONE BIT(14) #define RK3568_VERSION_INFO 0x004 #define RK3568_SYS_AUTO_GATING_CTRL 0x008 #define RK3568_DSP_IF_EN 0x028 #define RK3568_DSP_IF_CTRL 0x02c #define RK3568_DSP_IF_POL 0x030 +#define RK3568_WB_CTRL 0x40 +#define RK3568_WB_XSCAL_FACTOR 0x44 +#define RK3568_WB_YRGB_MST 0x48 +#define RK3568_WB_CBR_MST 0x4C #define RK3568_LUT_PORT_SEL 0x058 #define RK3568_VP0_LINE_FLAG 0x70 #define RK3568_VP1_LINE_FLAG 0x74