From 2f7c68cb55ecb7331f2381deb497c27155f32faf Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Wed, 03 Jan 2024 09:43:39 +0000 Subject: [PATCH] update kernel to 5.10.198 --- kernel/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 145 ++++++++++++++++++++++++++++++++++-------------- 1 files changed, 103 insertions(+), 42 deletions(-) diff --git a/kernel/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/kernel/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index 52dbcca..2c7a66a 100644 --- a/kernel/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/kernel/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -20,7 +20,6 @@ #ifdef CONFIG_DRM_ANALOGIX_DP #include <drm/bridge/analogix_dp.h> #endif -#include <dt-bindings/soc/rockchip-system-status.h> #include <linux/debugfs.h> #include <linux/fixp-arith.h> @@ -46,6 +45,7 @@ #include <linux/rockchip/cpu.h> #include <linux/workqueue.h> #include <linux/types.h> +#include <soc/rockchip/rockchip_csu.h> #include <soc/rockchip/rockchip_dmc.h> #include <soc/rockchip/rockchip-system-status.h> #include <uapi/linux/videodev2.h> @@ -885,6 +885,7 @@ struct clk *pclk; struct reset_control *ahb_rst; struct reset_control *axi_rst; + struct csu_clk *csu_aclk; /* list_head of extend clk */ struct list_head extend_clk_list_head; @@ -929,6 +930,7 @@ { MEDIA_BUS_FMT_UYYVYY8_0_5X24, "UYYVYY8_0_5X24" }, { MEDIA_BUS_FMT_YUV10_1X30, "YUV10_1X30" }, { MEDIA_BUS_FMT_UYYVYY10_0_5X30, "UYYVYY10_0_5X30" }, + { MEDIA_BUS_FMT_RGB565_2X8_LE, "RGB565_2X8_LE" }, { MEDIA_BUS_FMT_RGB888_3X8, "RGB888_3X8" }, { MEDIA_BUS_FMT_RGB888_DUMMY_4X8, "RGB888_DUMMY_4X8" }, { MEDIA_BUS_FMT_RGB888_1X24, "RGB888_1X24" }, @@ -3243,8 +3245,21 @@ return 0; } +static void vop2_wb_encoder_atomic_disable(struct drm_encoder *encoder, + struct drm_atomic_state *state) +{ + struct drm_crtc *crtc = encoder->crtc; + struct vop2_video_port *vp = to_vop2_video_port(crtc); + + if (!crtc->state->active_changed && !crtc->state->mode_changed) { + crtc->state->connectors_changed = false; + DRM_DEBUG("VP%d force change connectors_changed to false when disable wb\n", vp->id); + } +} + static const struct drm_encoder_helper_funcs vop2_wb_encoder_helper_funcs = { .atomic_check = vop2_wb_encoder_atomic_check, + .atomic_disable = vop2_wb_encoder_atomic_disable, }; static const struct drm_connector_helper_funcs vop2_wb_connector_helper_funcs = { @@ -5142,7 +5157,7 @@ actual_w = drm_rect_width(src) >> 16; actual_h = drm_rect_height(src) >> 16; - if (!actual_w || !actual_h) { + if (!actual_w || !actual_h || !bpp) { vop2_win_disable(win, true); return; } @@ -5263,10 +5278,6 @@ /* AFBC pic_vir_width is count by pixel, this is different * with WIN_VIR_STRIDE. */ - if (!bpp) { - WARN(1, "bpp is zero\n"); - bpp = 1; - } stride = (fb->pitches[0] << 3) / bpp; if ((stride & 0x3f) && (vpstate->xmirror_en || vpstate->rotate_90_en || vpstate->rotate_270_en)) @@ -6111,6 +6122,27 @@ return 0; } +static void vop2_crtc_csu_set_rate(struct drm_crtc *crtc) +{ + struct vop2_video_port *vp = to_vop2_video_port(crtc); + struct vop2 *vop2 = vp->vop2; + unsigned long aclk_rate = 0, dclk_rate = 0; + u32 csu_div = 0; + + if (!vop2->csu_aclk) + return; + + aclk_rate = clk_get_rate(vop2->aclk); + dclk_rate = clk_get_rate(vp->dclk); + if (!dclk_rate) + return; + + /* aclk >= 1/2 * dclk */ + csu_div = aclk_rate * 2 / dclk_rate; + + rockchip_csu_set_div(vop2->csu_aclk, csu_div); +} + static int vop2_crtc_loader_protect(struct drm_crtc *crtc, bool on, void *data) { struct vop2_video_port *vp = to_vop2_video_port(crtc); @@ -6190,6 +6222,8 @@ cubic_lut_mst = cubic_lut->offset + private->cubic_lut_dma_addr; VOP_MODULE_SET(vop2, vp, cubic_lut_mst, cubic_lut_mst); } + + vop2_crtc_csu_set_rate(crtc); } else { vop2_crtc_atomic_disable(crtc, NULL); } @@ -6330,7 +6364,8 @@ /* only need to dump once at first active crtc for vop2 */ for (i = 0; i < vop2_data->nr_vps; i++) { - if (vop2->vps[i].rockchip_crtc.crtc.state->active) { + if (vop2->vps[i].rockchip_crtc.crtc.state && + vop2->vps[i].rockchip_crtc.crtc.state->active) { first_active_crtc = &vop2->vps[i].rockchip_crtc.crtc; break; } @@ -6373,7 +6408,8 @@ /* only need to dump once at first active crtc for vop2 */ for (i = 0; i < vop2_data->nr_vps; i++) { - if (vop2->vps[i].rockchip_crtc.crtc.state->active) { + if (vop2->vps[i].rockchip_crtc.crtc.state && + vop2->vps[i].rockchip_crtc.crtc.state->active) { first_active_crtc = &vop2->vps[i].rockchip_crtc.crtc; break; } @@ -6543,7 +6579,8 @@ } else { if (request_clock > VOP2_MAX_DCLK_RATE) request_clock = request_clock >> 2; - clock = clk_round_rate(vp->dclk, request_clock * 1000) / 1000; + clock = rockchip_drm_dclk_round_rate(vop2->version, vp->dclk, + request_clock * 1000) / 1000; } /* @@ -6586,7 +6623,7 @@ size_t bandwidth; if (src_width <= 0 || src_height <= 0 || dst_width <= 0 || - dst_height <= 0) + dst_height <= 0 || !bpp) return 0; bandwidth = src_width * bpp / 8; @@ -6832,6 +6869,14 @@ if (mode->flags & DRM_MODE_FLAG_DBLCLK || vcstate->output_if & VOP_OUTPUT_IF_BT656) adj_mode->crtc_clock *= 2; + /* + * For RK3528, the path of CVBS output is like: + * VOP BT656 ENCODER -> CVBS BT656 DECODER -> CVBS ENCODER -> CVBS VDAC + * The vop2 dclk should be four times crtc_clock for CVBS sampling clock needs. + */ + if (vop2->version == VOP_VERSION_RK3528 && vcstate->output_if & VOP_OUTPUT_IF_BT656) + 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); @@ -6847,9 +6892,11 @@ } drm_connector_list_iter_end(&conn_iter); - if (adj_mode->crtc_clock <= VOP2_MAX_DCLK_RATE) - adj_mode->crtc_clock = DIV_ROUND_UP(clk_round_rate(vp->dclk, - adj_mode->crtc_clock * 1000), 1000); + if (adj_mode->crtc_clock <= VOP2_MAX_DCLK_RATE) { + adj_mode->crtc_clock = rockchip_drm_dclk_round_rate(vop2->version, vp->dclk, + adj_mode->crtc_clock * 1000); + adj_mode->crtc_clock = DIV_ROUND_UP(adj_mode->crtc_clock, 1000); + } return true; } @@ -7745,11 +7792,11 @@ vop2_set_system_status(vop2); 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", + DRM_DEV_INFO(vop2->dev, "Update mode to %dx%d%s%d, type: %d(if:%x, flag:0x%x) for vp%d dclk: %llu\n", hdisplay, adjusted_mode->vdisplay, interlaced ? "i" : "p", drm_mode_vrefresh(adjusted_mode), vcstate->output_type, vcstate->output_if, vcstate->output_flags, - vp->id, adjusted_mode->crtc_clock * 1000); + vp->id, (unsigned long long)adjusted_mode->crtc_clock * 1000); if (adjusted_mode->hdisplay > VOP2_MAX_VP_OUTPUT_WIDTH) { vcstate->splice_mode = true; @@ -8081,19 +8128,12 @@ if (ret < 0) goto out; - clk_set_rate(vp->dclk, dclk->rate); + rockchip_drm_dclk_set_rate(vop2->version, vp->dclk, dclk->rate); DRM_DEV_INFO(vop2->dev, "set %s to %ld, get %ld\n", __clk_get_name(vp->dclk), dclk->rate, clk_get_rate(vp->dclk)); } else { - /* - * For RK3528, the path of CVBS output is like: - * VOP BT656 ENCODER -> CVBS BT656 DECODER -> CVBS ENCODER -> CVBS VDAC - * The vop2 dclk should be four times crtc_clock for CVBS sampling clock needs. - */ - if (vop2->version == VOP_VERSION_RK3528 && vcstate->output_if & VOP_OUTPUT_IF_BT656) - clk_set_rate(vp->dclk, 4 * adjusted_mode->crtc_clock * 1000); - else - clk_set_rate(vp->dclk, adjusted_mode->crtc_clock * 1000); + rockchip_drm_dclk_set_rate(vop2->version, vp->dclk, + adjusted_mode->crtc_clock * 1000); } if (vp_data->feature & VOP_FEATURE_OVERSCAN) @@ -8122,6 +8162,7 @@ if (is_vop3(vop2)) vop3_setup_pipe_dly(vp, NULL); + vop2_crtc_csu_set_rate(crtc); vop2_cfg_done(crtc); /* @@ -8158,6 +8199,30 @@ vop2_crtc_load_lut(crtc); vop2_cfg_done(crtc); vop2_wait_for_fs_by_done_bit_status(vp); + } + + /* + * In RK3588 VOP, HDMI1/eDP1 MUX1 module's reset signal should be released + * when PD_VOP turn on. If this reset signal is not be released, the HDMI1 + * or eDP1 output interface can't work normally. + * However, If the deassert signal want to transfer to HDMI1/eDP1 MUX1 and + * take effect, it need the video port0 dclk's source clk work a few moment. + * In some cases, the video port0 dclk's source clk is disabled(now only the + * hdmi0/1 phy pll as the dclk source parent will appear) after PD_VOP turn + * on, for example, vidoe port0 dclk source select hdmi phy pll. To fix + * this issue, enable video port0 dclk for a few monent when active a video + * port which attach to eDP1/HDMI1. + */ + if (vop2->version == VOP_VERSION_RK3588) { + if (vp->id != 0 && (vp->output_if & (VOP_OUTPUT_IF_eDP1 | VOP_OUTPUT_IF_HDMI1))) { + struct vop2_video_port *vp0 = &vop2->vps[0]; + + clk_prepare_enable(vp0->dclk); + if (!clk_get_rate(vp0->dclk)) + clk_set_rate(vp0->dclk, 148500000); + udelay(20); + clk_disable_unprepare(vp0->dclk); + } } out: vop2_unlock(vop2); @@ -10941,25 +11006,14 @@ return 0; } -static struct drm_plane *vop2_cursor_plane_init(struct vop2_video_port *vp) +static struct drm_plane *vop2_cursor_plane_init(struct vop2_video_port *vp, u32 possible_crtcs) { struct vop2 *vop2 = vp->vop2; struct drm_plane *cursor = NULL; struct vop2_win *win; - unsigned long possible_crtcs = 0; win = vop2_find_win_by_phys_id(vop2, vp->cursor_win_id); if (win) { - if (vop2->disable_win_move) { - const struct vop2_data *vop2_data = vop2->data; - struct drm_crtc *crtc = vop2_find_crtc_by_plane_mask(vop2, win->phys_id); - - if (crtc) - possible_crtcs = drm_crtc_mask(crtc); - else - possible_crtcs = (1 << vop2_data->nr_vps) - 1; - } - if (win->possible_crtcs) possible_crtcs = win->possible_crtcs; win->type = DRM_PLANE_TYPE_CURSOR; @@ -11263,11 +11317,13 @@ possible_crtcs = BIT(registered_num_crtcs); /* - * we assume a vp with a zere plane_mask(set from dts or bootloader) + * we assume a vp with a zero plane_mask(set from dts or bootloader) * as unused. */ - if (!vp->plane_mask && bootloader_initialized) + if (!vp->plane_mask && bootloader_initialized) { + DRM_DEV_INFO(vop2->dev, "VP%d plane_mask is zero, so ignore register crtc\n", vp->id); continue; + } if (vop2_soc_is_rk3566()) soc_id = vp_data->soc_id[1]; @@ -11389,7 +11445,7 @@ } if (vp->cursor_win_id >= 0) { - cursor = vop2_cursor_plane_init(vp); + cursor = vop2_cursor_plane_init(vp, possible_crtcs); if (!cursor) DRM_WARN("failed to init cursor plane for vp%d\n", vp->id); else @@ -11587,6 +11643,7 @@ struct vop2_win *win; struct vop2_layer *layer; char name[DRM_PROP_NAME_LEN]; + char area_name[DRM_PROP_NAME_LEN]; unsigned int num_wins = 0; uint8_t plane_id = 0; unsigned int i, j; @@ -11662,8 +11719,8 @@ area->phys_id = win->phys_id; area->area_id = j + 1; area->plane_id = plane_id++; - snprintf(name, min(sizeof(name), strlen(win->name)), "%s", win->name); - snprintf(name, sizeof(name), "%s%d", name, area->area_id); + snprintf(area_name, min(sizeof(area_name), strlen(win->name)), "%s", win->name); + snprintf(name, sizeof(name), "%s%d", area_name, area->area_id); area->name = devm_kstrdup(vop2->dev, name, GFP_KERNEL); num_wins++; } @@ -11957,6 +12014,10 @@ return PTR_ERR(vop2->axi_rst); } + vop2->csu_aclk = rockchip_csu_get(dev, "aclk"); + if (IS_ERR(vop2->csu_aclk)) + vop2->csu_aclk = NULL; + vop2->irq = platform_get_irq(pdev, 0); if (vop2->irq < 0) { DRM_DEV_ERROR(dev, "cannot find irq for vop2\n"); -- Gitblit v1.6.2