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