From 3cb261be89838bafdc80f2d5f35785e81f48e327 Mon Sep 17 00:00:00 2001 From: Damon Ding Date: Tue, 18 Jul 2023 10:34:49 +0800 Subject: [PATCH] drm/rockchip: drv: fix the dclk calculation of mcu interface dclk = htotal * vtotal * frame-rate * cycles-per-pixel * pix-total Signed-off-by: Damon Ding Change-Id: I6b78463dc8290f562cfe44040d6b6030d652213d --- drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 24 ++++++++++++++++++++ drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 1 + drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 16 ++++++++----- drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 20 ++++------------ 4 files changed, 40 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index ddb27d358701..f1aa9e3e5c7f 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -189,6 +189,30 @@ uint32_t rockchip_drm_get_bpp(const struct drm_format_info *info) } EXPORT_SYMBOL(rockchip_drm_get_bpp); +uint32_t rockchip_drm_get_cycles_per_pixel(uint32_t bus_format) +{ + switch (bus_format) { + case MEDIA_BUS_FMT_RGB565_1X16: + case MEDIA_BUS_FMT_RGB666_1X18: + case MEDIA_BUS_FMT_RGB888_1X24: + case MEDIA_BUS_FMT_RGB666_1X24_CPADHI: + return 1; + case MEDIA_BUS_FMT_RGB565_2X8_LE: + case MEDIA_BUS_FMT_BGR565_2X8_LE: + return 2; + case MEDIA_BUS_FMT_RGB666_3X6: + case MEDIA_BUS_FMT_RGB888_3X8: + case MEDIA_BUS_FMT_BGR888_3X8: + return 3; + case MEDIA_BUS_FMT_RGB888_DUMMY_4X8: + case MEDIA_BUS_FMT_BGR888_DUMMY_4X8: + return 4; + default: + return 1; + } +} +EXPORT_SYMBOL(rockchip_drm_get_cycles_per_pixel); + /** * rockchip_drm_of_find_possible_crtcs - find the possible CRTCs for an active * encoder port diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h index 2a7ff11bcb61..86ff47be01fb 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h @@ -577,6 +577,7 @@ int rockchip_drm_endpoint_is_subdriver(struct device_node *ep); uint32_t rockchip_drm_of_find_possible_crtcs(struct drm_device *dev, struct device_node *port); uint32_t rockchip_drm_get_bpp(const struct drm_format_info *info); +uint32_t rockchip_drm_get_cycles_per_pixel(uint32_t bus_format); int rockchip_drm_get_yuv422_format(struct drm_connector *connector, struct edid *edid); int rockchip_drm_parse_cea_ext(struct rockchip_drm_dsc_cap *dsc_cap, diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 7a64cb6b7e8f..b2e027f0e501 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -3201,8 +3201,8 @@ static bool vop_crtc_mode_fixup(struct drm_crtc *crtc, { struct vop *vop = to_vop(crtc); const struct vop_data *vop_data = vop->data; - struct rockchip_crtc_state *s = - to_rockchip_crtc_state(crtc->state); + struct drm_crtc_state *new_crtc_state = container_of(mode, struct drm_crtc_state, mode); + struct rockchip_crtc_state *s = to_rockchip_crtc_state(new_crtc_state); unsigned long rate; if (mode->hdisplay > vop_data->max_output.width) @@ -3219,6 +3219,10 @@ static bool vop_crtc_mode_fixup(struct drm_crtc *crtc, s->output_if & VOP_OUTPUT_IF_BT656)) adj_mode->crtc_clock *= 2; + if (vop->mcu_timing.mcu_pix_total) + adj_mode->crtc_clock *= rockchip_drm_get_cycles_per_pixel(s->bus_format) * + (vop->mcu_timing.mcu_pix_total + 1); + /* * Clock craziness. * @@ -3245,11 +3249,11 @@ static bool vop_crtc_mode_fixup(struct drm_crtc *crtc, * 4. Store the rounded up rate so that we don't need to worry about * this in the actual clk_set_rate(). */ - rate = clk_round_rate(vop->dclk, adj_mode->clock * 1000); - if (rate / 1000 != adj_mode->clock) + rate = clk_round_rate(vop->dclk, adj_mode->crtc_clock * 1000); + if (rate / 1000 != adj_mode->crtc_clock) rate = clk_round_rate(vop->dclk, - adj_mode->clock * 1000 + 999); - adj_mode->clock = DIV_ROUND_UP(rate, 1000); + adj_mode->crtc_clock * 1000 + 999); + adj_mode->crtc_clock = DIV_ROUND_UP(rate, 1000); return true; } diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index a4888d986069..8fbfd4c104f5 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -6834,12 +6834,9 @@ static bool vop2_crtc_mode_fixup(struct drm_crtc *crtc, if (mode->flags & DRM_MODE_FLAG_DBLCLK || vcstate->output_if & VOP_OUTPUT_IF_BT656) adj_mode->crtc_clock *= 2; - if (vp->mcu_timing.mcu_pix_total) { - if (vcstate->output_mode == ROCKCHIP_OUT_MODE_S888) - adj_mode->crtc_clock *= 3; - else if (vcstate->output_mode == ROCKCHIP_OUT_MODE_S888_DUMMY) - adj_mode->crtc_clock *= 4; - } + if (vp->mcu_timing.mcu_pix_total) + adj_mode->crtc_clock *= rockchip_drm_get_cycles_per_pixel(vcstate->bus_format) * + (vp->mcu_timing.mcu_pix_total + 1); drm_connector_list_iter_begin(crtc->dev, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) { @@ -7695,14 +7692,6 @@ static void vop3_setup_pipe_dly(struct vop2_video_port *vp, const struct vop2_zp } } -static int vop2_get_vrefresh(struct vop2_video_port *vp, const struct drm_display_mode *mode) -{ - if (vp->mcu_timing.mcu_pix_total) - return drm_mode_vrefresh(mode) / vp->mcu_timing.mcu_pix_total; - else - return drm_mode_vrefresh(mode); -} - static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state) { struct vop2_video_port *vp = to_vop2_video_port(crtc); @@ -7749,7 +7738,8 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_sta vop2_lock(vop2); DRM_DEV_INFO(vop2->dev, "Update mode to %dx%d%s%d, type: %d(if:%x, flag:0x%x) for vp%d dclk: %d\n", hdisplay, adjusted_mode->vdisplay, interlaced ? "i" : "p", - vop2_get_vrefresh(vp, adjusted_mode), vcstate->output_type, vcstate->output_if, vcstate->output_flags, + drm_mode_vrefresh(adjusted_mode), + vcstate->output_type, vcstate->output_if, vcstate->output_flags, vp->id, adjusted_mode->crtc_clock * 1000); if (adjusted_mode->hdisplay > VOP2_MAX_VP_OUTPUT_WIDTH) {