linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] drm/ast: Create the driver for ASPEED proprietory  Display-Port
@ 2021-11-22 10:36 KuoHsiang Chou
  2021-11-25 15:49 ` [PATCH] drm/ast: fix semicolon.cocci warnings kernel test robot
                   ` (4 more replies)
  0 siblings, 5 replies; 21+ messages in thread
From: KuoHsiang Chou @ 2021-11-22 10:36 UTC (permalink / raw)
  To: tzimmermann, dri-devel, linux-kernel
  Cc: airlied, airlied, daniel, jenmin_yuan, kuohsiang_chou, arc_sung,
	tommy_huang, brandon_chen, hungju_huang, luke_chen

1. The MCU FW controling ASPEED DP is loaded by BMC boot loader.
2. Driver starts after CR[3:1] == 111b that indicates Tx is ASTDP,
   and CRD1[5] has been asserted by BMVC boot loader.
3. EDID is prioritized by DP monitor.
4. DP's EDID has high priority to decide resolution supporting.

Signed-off-by: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com>
---
 drivers/gpu/drm/ast/Makefile   |   2 +-
 drivers/gpu/drm/ast/ast_dp.c   | 286 +++++++++++++++++++++++++++++++++
 drivers/gpu/drm/ast/ast_drv.h  |  13 ++
 drivers/gpu/drm/ast/ast_main.c |   7 +-
 drivers/gpu/drm/ast/ast_mode.c |  50 +++++-
 drivers/gpu/drm/ast/ast_post.c |   4 +-
 6 files changed, 353 insertions(+), 9 deletions(-)
 create mode 100644 drivers/gpu/drm/ast/ast_dp.c

diff --git a/drivers/gpu/drm/ast/Makefile b/drivers/gpu/drm/ast/Makefile
index 438a2d05b..9bd0756e0 100644
--- a/drivers/gpu/drm/ast/Makefile
+++ b/drivers/gpu/drm/ast/Makefile
@@ -3,6 +3,6 @@
 # Makefile for the drm device driver.  This driver provides support for the
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
 
-ast-y := ast_drv.o ast_main.o ast_mm.o ast_mode.o ast_post.o ast_dp501.o
+ast-y := ast_drv.o ast_main.o ast_mm.o ast_mode.o ast_post.o ast_dp501.o ast_dp.o
 
 obj-$(CONFIG_DRM_AST) := ast.o
diff --git a/drivers/gpu/drm/ast/ast_dp.c b/drivers/gpu/drm/ast/ast_dp.c
new file mode 100644
index 000000000..537eaf4fa
--- /dev/null
+++ b/drivers/gpu/drm/ast/ast_dp.c
@@ -0,0 +1,286 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ */
+/*
+ * Authors: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com>
+ */
+
+#include <linux/firmware.h>
+#include <linux/delay.h>
+#include <drm/drm_print.h>
+#include "ast_drv.h"
+
+bool ast_dp_read_edid(struct drm_device *dev, u8 *ediddata)
+{
+	struct ast_private *ast = to_ast_private(dev);
+	u8 i = 0, j = 0;
+
+#ifdef DPControlPower
+	u8 bDPState_Change = false;
+
+	// Check DP power off or not.
+	if (ast->ASTDP_State & 0x10) {
+		// DP power on
+		ast_dp_PowerOnOff(dev, 1);
+		bDPState_Change = true;
+	}
+#endif
+
+	/*
+	 * CRD1[b5]: DP MCU FW is executing
+	 * CRDC[b0]: DP link success
+	 * CRDF[b0]: DP HPD
+	 * CRE5[b0]: Host reading EDID process is done
+	 */
+	if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, 0x20) &&
+		ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, 0x01) &&
+		ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, 0x01) &&
+		ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, 0x01))) {
+#ifdef DPControlPower
+		// Set back power off
+		if (bDPState_Change)
+			ast_dp_PowerOnOff(dev, 0);
+#endif
+		return false;
+	}
+
+	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, 0x00, 0x00);
+
+	for (i = 0; i < 32; i++) {
+		/*
+		 * CRE4[7:0]: Read-Pointer for EDID (Unit: 4bytes); valid range: 0~64
+		 */
+		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE4, 0x00, (u8) i);
+		j = 0;
+
+		/*
+		 * CRD7[b0]: valid flag for EDID
+		 * CRD6[b0]: mirror read pointer for EDID
+		 */
+		while ((ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD7, 0x01) != 0x01) ||
+			(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD6, 0xFF) != i)) {
+			mdelay(j+1);
+
+			if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, 0x20) &&
+				ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, 0x01) &&
+				ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, 0x01))) {
+				ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, 0x00, 0x01);
+				return false;
+			}
+
+			j++;
+			if (j > 200) {
+				ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, 0x00, 0x01);
+				return false;
+			}
+		}
+
+		*(ediddata) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD8, 0xFF);
+		*(ediddata + 1) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD9, 0xFF);
+		*(ediddata + 2) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDA, 0xFF);
+		*(ediddata + 3) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDB, 0xFF);
+
+		if (i == 31) {
+			*(ediddata + 3) = *(ediddata + 3) + *(ediddata + 2);
+			*(ediddata + 2) = 0;
+		}
+
+		ediddata += 4;
+	}
+
+	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, 0x00, 0x01);
+
+#ifdef DPControlPower
+	// Set back power off
+	if (bDPState_Change)
+		ast_dp_PowerOnOff(dev, 0);
+#endif
+
+	return true;
+}
+
+/*
+ * Launch Aspeed DP
+ */
+bool ast_dp_launch(struct drm_device *dev, u8 bPower)
+{
+	u32 i = 0, j = 0, WaitCount = 1;
+	u8 bDPTX = 0;
+	u8 bDPExecute = 1;
+
+	struct ast_private *ast = to_ast_private(dev);
+	// S3 come back, need more time to wait BMC ready.
+	if (bPower)
+		WaitCount = 300;
+
+	// Fill
+	ast->tx_chip_type = AST_TX_NONE;
+
+	// Wait total count by different condition.
+	// This is a temp solution for DP check
+	for (j = 0; j < WaitCount; j++) {
+		bDPTX = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, 0x0E);
+
+		if (bDPTX)
+			break;
+
+		msleep(100);
+	}
+
+	// 0xE : ASTDP with DPMCU FW handling
+	if (bDPTX == 0x0E) {
+		// Wait one second then timeout.
+		i = 0;
+
+		while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, 0x20) != 0x20) {
+			i++;
+			// wait 100 ms
+			msleep(100);
+
+			if (i >= 10) {
+				// DP would not be ready.
+				bDPExecute = 0;
+				break;
+			}
+		};
+
+		if (bDPExecute)
+			ast->tx_chip_type = AST_TX_ASTDP;
+	}
+
+	return true;
+}
+
+#ifdef DPControlPower
+
+void ast_dp_PowerOnOff(struct drm_device *dev, u8 Mode)
+{
+	struct ast_private *ast = to_ast_private(dev);
+	// Read and Turn off DP PHY sleep
+	u8 bE3 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, 0x0F);
+
+	// Turn on DP PHY sleep
+	if (!Mode)
+		bE3 |= 0x10;
+
+	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, 0x00, bE3); // DP Power on/off
+
+	// Save ASTDP power state
+	ast->ASTDP_State = bE3;
+}
+
+#endif
+
+void ast_dp_SetOnOff(struct drm_device *dev, u8 Mode)
+{
+	struct ast_private *ast = to_ast_private(dev);
+
+	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, 0x00, Mode); // video on/off
+
+	// Save ASTDP power state
+	ast->ASTDP_State = Mode;
+
+    // If DP plug in and link successful then check video on / off status
+	if (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, 0x01) &&
+		ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, 0x01)) {
+		Mode <<= 4;
+		while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, 0x10) != Mode) {
+			// wait 1 ms
+			mdelay(1);
+		}
+	}
+}
+
+void ast_dp_SetOutput(struct drm_crtc *crtc, struct ast_vbios_mode_info *vbios_mode)
+{
+	struct ast_private *ast = to_ast_private(crtc->dev);
+
+	u32 ulRefreshRateIndex;
+	u8 ModeIdx;
+
+	ulRefreshRateIndex = vbios_mode->enh_table->refresh_rate_index - 1;
+
+	switch (crtc->mode.crtc_hdisplay) {
+	case 320:
+		ModeIdx = 0x11;
+		break;
+	case 400:
+		ModeIdx = 0x12;
+		break;
+	case 512:
+		ModeIdx = 0x13;
+		break;
+	case 640:
+		ModeIdx = (0x00 + (u8) ulRefreshRateIndex);
+		break;
+	case 800:
+		ModeIdx = (0x04 + (u8) ulRefreshRateIndex);
+		break;
+	case 1024:
+		ModeIdx = (0x09 + (u8) ulRefreshRateIndex);
+		break;
+	case 1152:
+		ModeIdx = 0x1F;
+		break;
+	case 1280:
+		if (crtc->mode.crtc_vdisplay == 800)
+			ModeIdx = (0x17 - (u8) ulRefreshRateIndex);	// For RB/Non-RB
+		else		// 1024
+			ModeIdx = (0x0D + (u8) ulRefreshRateIndex);
+		break;
+	case 1360:
+	case 1366:
+		ModeIdx = 0x1E;
+		break;
+	case 1440:
+		ModeIdx = (0x19 - (u8) ulRefreshRateIndex);	// For RB/Non-RB
+		break;
+	case 1600:
+		if (crtc->mode.crtc_vdisplay == 900)
+			ModeIdx = (0x1D - (u8) ulRefreshRateIndex);	// For RB/Non-RB
+		else		//1200
+			ModeIdx = 0x10;
+		break;
+	case 1680:
+		ModeIdx = (0x1B - (u8) ulRefreshRateIndex);	// For RB/Non-RB
+		break;
+	case 1920:
+		if (crtc->mode.crtc_vdisplay == 1080)
+			ModeIdx = 0x15;
+		else		//1200
+			ModeIdx = 0x14;
+		break;
+	default:
+		return;
+	}
+
+	/*
+	 * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp)
+	 * CRE1[7:0]: MISC1 (default: 0x00)
+	 * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50)
+	 */
+	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE0, 0x00, 0x20);
+	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE1, 0x00, 0x00);
+	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE2, 0x00, ModeIdx);
+}
diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
index 2cfce7dc9..e56d5d57b 100644
--- a/drivers/gpu/drm/ast/ast_drv.h
+++ b/drivers/gpu/drm/ast/ast_drv.h
@@ -71,6 +71,7 @@ enum ast_tx_chip {
 	AST_TX_SIL164,
 	AST_TX_ITE66121,
 	AST_TX_DP501,
+	AST_TX_ASTDP,
 };
 
 #define AST_DRAM_512Mx16 0
@@ -175,6 +176,9 @@ struct ast_private {
 	u8 dp501_maxclk;
 	u8 *dp501_fw_addr;
 	const struct firmware *dp501_fw;	/* dp501 fw */
+
+    // ASTDP
+	u8 ASTDP_State;
 };
 
 static inline struct ast_private *to_ast_private(struct drm_device *dev)
@@ -356,5 +360,14 @@ bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 size);
 bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata);
 u8 ast_get_dp501_max_clk(struct drm_device *dev);
 void ast_init_3rdtx(struct drm_device *dev);
+/* aspeed DP */
+#define DPControlPower
+bool ast_dp_read_edid(struct drm_device *dev, u8 *ediddata);
+bool ast_dp_launch(struct drm_device *dev, u8 bPower);
+#ifdef DPControlPower
+void ast_dp_PowerOnOff(struct drm_device *dev, u8 Mode);
+#endif
+void ast_dp_SetOnOff(struct drm_device *dev, u8 Mode);
+void ast_dp_SetOutput(struct drm_crtc *crtc, struct ast_vbios_mode_info *vbios_mode);
 
 #endif
diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c
index 79a361867..de5d69888 100644
--- a/drivers/gpu/drm/ast/ast_main.c
+++ b/drivers/gpu/drm/ast/ast_main.c
@@ -212,7 +212,7 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
 		}
 		break;
 	}
-
+	ast->support_wide_screen = true;
 	/* Check 3rd Tx option (digital output afaik) */
 	ast->tx_chip_type = AST_TX_NONE;
 
@@ -230,7 +230,7 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
 			ast->tx_chip_type = AST_TX_SIL164;
 	}
 
-	if ((ast->chip == AST2300) || (ast->chip == AST2400)) {
+	if ((ast->chip == AST2300) || (ast->chip == AST2400) || (ast->chip == AST2500)) {
 		/*
 		 * On AST2300 and 2400, look the configuration set by the SoC in
 		 * the SOC scratch register #1 bits 11:8 (interestingly marked
@@ -254,7 +254,8 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
 		case 0x0c:
 			ast->tx_chip_type = AST_TX_DP501;
 		}
-	}
+	} else if (ast->chip == AST2600)
+		ast_dp_launch(&ast->base, 0);
 
 	/* Print stuff for diagnostic purposes */
 	switch(ast->tx_chip_type) {
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index 6bfaefa01..d7347d510 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -987,20 +987,44 @@ static int ast_cursor_plane_init(struct ast_private *ast)
 static void ast_crtc_dpms(struct drm_crtc *crtc, int mode)
 {
 	struct ast_private *ast = to_ast_private(crtc->dev);
+	u8 ch = 0x03;
 
 	/* TODO: Maybe control display signal generation with
 	 *       Sync Enable (bit CR17.7).
 	 */
 	switch (mode) {
 	case DRM_MODE_DPMS_ON:
-	case DRM_MODE_DPMS_STANDBY:
-	case DRM_MODE_DPMS_SUSPEND:
+		ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT,  0x01, 0xdf, 0);
+		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, 0);
 		if (ast->tx_chip_type == AST_TX_DP501)
 			ast_set_dp501_video_output(crtc->dev, 1);
+
+		if (ast->tx_chip_type == AST_TX_ASTDP) {
+#ifdef DPControlPower
+			ast_dp_PowerOnOff(crtc->dev, 1);
+#endif
+			ast_wait_for_vretrace(ast);
+			ast_dp_SetOnOff(crtc->dev, 1);
+		}
+
+		ast_crtc_load_lut(ast, crtc);
 		break;
+	case DRM_MODE_DPMS_STANDBY:
+	case DRM_MODE_DPMS_SUSPEND:
 	case DRM_MODE_DPMS_OFF:
+		ch = mode;
 		if (ast->tx_chip_type == AST_TX_DP501)
 			ast_set_dp501_video_output(crtc->dev, 0);
+
+		if (ast->tx_chip_type == AST_TX_ASTDP) {
+			ast_dp_SetOnOff(crtc->dev, 0);
+#ifdef DPControlPower
+			ast_dp_PowerOnOff(crtc->dev, 0);
+#endif
+		}
+
+		ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT,  0x01, 0xdf, 0x20);
+		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, ch);
 		break;
 	}
 }
@@ -1044,6 +1068,8 @@ ast_crtc_helper_atomic_flush(struct drm_crtc *crtc,
 	struct ast_private *ast = to_ast_private(crtc->dev);
 	struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
 	struct ast_crtc_state *old_ast_crtc_state = to_ast_crtc_state(old_crtc_state);
+struct ast_vbios_mode_info *vbios_mode_info =
+		&ast_crtc_state->vbios_mode_info;
 
 	/*
 	 * The gamma LUT has to be reloaded after changing the primary
@@ -1051,6 +1077,10 @@ ast_crtc_helper_atomic_flush(struct drm_crtc *crtc,
 	 */
 	if (old_ast_crtc_state->format != ast_crtc_state->format)
 		ast_crtc_load_lut(ast, crtc);
+
+	//Set Aspeed Display-Port
+	if (ast->tx_chip_type == AST_TX_ASTDP)
+		ast_dp_SetOutput(crtc, vbios_mode_info);
 }
 
 static void
@@ -1225,7 +1255,16 @@ static int ast_get_modes(struct drm_connector *connector)
 			ast->dp501_maxclk = ast_get_dp501_max_clk(connector->dev);
 		else
 			kfree(edid);
+	} else if (ast->tx_chip_type == AST_TX_ASTDP) {
+		edid = kmalloc(128, GFP_KERNEL);
+		if (!edid)
+			return -ENOMEM;
+
+		flags = ast_dp_read_edid(connector->dev, (u8 *)edid);
+		if (!flags)
+			kfree(edid);
 	}
+
 	if (!flags)
 		edid = drm_get_edid(connector, &ast_connector->i2c->adapter);
 	if (edid) {
@@ -1256,10 +1295,12 @@ static enum drm_mode_status ast_mode_valid(struct drm_connector *connector,
 			return MODE_OK;
 		if ((mode->hdisplay == 1600) && (mode->vdisplay == 900))
 			return MODE_OK;
+		if ((mode->hdisplay == 1152) && (mode->vdisplay == 864))
+			return MODE_OK;
 
 		if ((ast->chip == AST2100) || (ast->chip == AST2200) ||
 		    (ast->chip == AST2300) || (ast->chip == AST2400) ||
-		    (ast->chip == AST2500)) {
+		    (ast->chip == AST2500) || (ast->chip == AST2600)) {
 			if ((mode->hdisplay == 1920) && (mode->vdisplay == 1080))
 				return MODE_OK;
 
@@ -1400,7 +1441,8 @@ int ast_mode_config_init(struct ast_private *ast)
 	    ast->chip == AST2200 ||
 	    ast->chip == AST2300 ||
 	    ast->chip == AST2400 ||
-	    ast->chip == AST2500) {
+	    ast->chip == AST2500 ||
+	    ast->chip == AST2600) {
 		dev->mode_config.max_width = 1920;
 		dev->mode_config.max_height = 2048;
 	} else {
diff --git a/drivers/gpu/drm/ast/ast_post.c b/drivers/gpu/drm/ast/ast_post.c
index b5d92f652..0aa9cf0fb 100644
--- a/drivers/gpu/drm/ast/ast_post.c
+++ b/drivers/gpu/drm/ast/ast_post.c
@@ -379,7 +379,9 @@ void ast_post_gpu(struct drm_device *dev)
 	ast_enable_mmio(dev);
 	ast_set_def_ext_reg(dev);
 
-	if (ast->config_mode == ast_use_p2a) {
+	if (ast->chip == AST2600) {
+		ast_dp_launch(dev, 1);
+	} else if (ast->config_mode == ast_use_p2a) {
 		if (ast->chip == AST2500)
 			ast_post_chip_2500(dev);
 		else if (ast->chip == AST2300 || ast->chip == AST2400)
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH] drm/ast: fix semicolon.cocci warnings
  2021-11-22 10:36 [PATCH] drm/ast: Create the driver for ASPEED proprietory Display-Port KuoHsiang Chou
@ 2021-11-25 15:49 ` kernel test robot
  2021-11-25 15:56 ` [PATCH] drm/ast: Create the driver for ASPEED proprietory Display-Port kernel test robot
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 21+ messages in thread
From: kernel test robot @ 2021-11-25 15:49 UTC (permalink / raw)
  To: KuoHsiang Chou, tzimmermann, dri-devel, linux-kernel
  Cc: kbuild-all, airlied, airlied, daniel, jenmin_yuan,
	kuohsiang_chou, arc_sung, tommy_huang

From: kernel test robot <lkp@intel.com>

drivers/gpu/drm/ast/ast_dp.c:166:3-4: Unneeded semicolon


 Remove unneeded semicolon.

Generated by: scripts/coccinelle/misc/semicolon.cocci

CC: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com>
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: kernel test robot <lkp@intel.com>
---

url:    https://github.com/0day-ci/linux/commits/KuoHsiang-Chou/drm-ast-Create-the-driver-for-ASPEED-proprietory-Display-Port/20211122-183830
base:   git://anongit.freedesktop.org/drm/drm drm-next
:::::: branch date: 3 days ago
:::::: commit date: 3 days ago

 ast_dp.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/drivers/gpu/drm/ast/ast_dp.c
+++ b/drivers/gpu/drm/ast/ast_dp.c
@@ -163,7 +163,7 @@ bool ast_dp_launch(struct drm_device *de
 				bDPExecute = 0;
 				break;
 			}
-		};
+		}
 
 		if (bDPExecute)
 			ast->tx_chip_type = AST_TX_ASTDP;

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] drm/ast: Create the driver for ASPEED proprietory Display-Port
  2021-11-22 10:36 [PATCH] drm/ast: Create the driver for ASPEED proprietory Display-Port KuoHsiang Chou
  2021-11-25 15:49 ` [PATCH] drm/ast: fix semicolon.cocci warnings kernel test robot
@ 2021-11-25 15:56 ` kernel test robot
  2021-12-03  6:31 ` Kuo-Hsiang Chou
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 21+ messages in thread
From: kernel test robot @ 2021-11-25 15:56 UTC (permalink / raw)
  To: KuoHsiang Chou, tzimmermann, dri-devel, linux-kernel
  Cc: kbuild-all, airlied, airlied, daniel, jenmin_yuan,
	kuohsiang_chou, arc_sung, tommy_huang

Hi KuoHsiang,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on drm/drm-next]
[also build test WARNING on drm-intel/for-linux-next drm-tip/drm-tip drm-exynos/exynos-drm-next tegra-drm/drm/tegra/for-next v5.16-rc2 next-20211125]
[cannot apply to airlied/drm-next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/KuoHsiang-Chou/drm-ast-Create-the-driver-for-ASPEED-proprietory-Display-Port/20211122-183830
base:   git://anongit.freedesktop.org/drm/drm drm-next
config: i386-randconfig-c021-20211123 (https://download.01.org/0day-ci/archive/20211125/202111252305.4CNMgIAc-lkp@intel.com/config)
compiler: gcc-9 (Debian 9.3.0-22) 9.3.0

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>


cocci warnings: (new ones prefixed by >>)
>> drivers/gpu/drm/ast/ast_dp.c:166:3-4: Unneeded semicolon

Please review and possibly fold the followup patch.

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

^ permalink raw reply	[flat|nested] 21+ messages in thread

* RE: [PATCH] drm/ast: Create the driver for ASPEED proprietory Display-Port
  2021-11-22 10:36 [PATCH] drm/ast: Create the driver for ASPEED proprietory Display-Port KuoHsiang Chou
  2021-11-25 15:49 ` [PATCH] drm/ast: fix semicolon.cocci warnings kernel test robot
  2021-11-25 15:56 ` [PATCH] drm/ast: Create the driver for ASPEED proprietory Display-Port kernel test robot
@ 2021-12-03  6:31 ` Kuo-Hsiang Chou
  2021-12-03  8:54   ` Thomas Zimmermann
  2022-01-01 19:41 ` [PATCH] drm/ast: fix semicolon.cocci warnings kernel test robot
  2022-01-01 19:51 ` [PATCH] drm/ast: Create the driver for ASPEED proprietory Display-Port kernel test robot
  4 siblings, 1 reply; 21+ messages in thread
From: Kuo-Hsiang Chou @ 2021-12-03  6:31 UTC (permalink / raw)
  To: tzimmermann, dri-devel, linux-kernel
  Cc: airlied, airlied, daniel, Jenmin Yuan, Arc Sung, Tommy Huang,
	Brandon Chen, Hungju Huang, Luke Chen

Hi Thomas,

Hi Tomas,
Good day! 
May I get the review status, or is there anything I can do to improve it? Thanks!

Best Regards,
	Kuo-Hsiang Chou

-----Original Message-----
From: Kuo-Hsiang Chou 
Sent: Monday, November 22, 2021 6:36 PM
To: tzimmermann@suse.de; dri-devel@lists.freedesktop.org; linux-kernel@vger.kernel.org
Subject: [PATCH] drm/ast: Create the driver for ASPEED proprietory Display-Port

1. The MCU FW controling ASPEED DP is loaded by BMC boot loader.
2. Driver starts after CR[3:1] == 111b that indicates Tx is ASTDP,
   and CRD1[5] has been asserted by BMVC boot loader.
3. EDID is prioritized by DP monitor.
4. DP's EDID has high priority to decide resolution supporting.

Signed-off-by: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com>
---
 drivers/gpu/drm/ast/Makefile   |   2 +-
 drivers/gpu/drm/ast/ast_dp.c   | 286 +++++++++++++++++++++++++++++++++
 drivers/gpu/drm/ast/ast_drv.h  |  13 ++
 drivers/gpu/drm/ast/ast_main.c |   7 +-
 drivers/gpu/drm/ast/ast_mode.c |  50 +++++-
 drivers/gpu/drm/ast/ast_post.c |   4 +-
 6 files changed, 353 insertions(+), 9 deletions(-)  create mode 100644 drivers/gpu/drm/ast/ast_dp.c

diff --git a/drivers/gpu/drm/ast/Makefile b/drivers/gpu/drm/ast/Makefile index 438a2d05b..9bd0756e0 100644
--- a/drivers/gpu/drm/ast/Makefile
+++ b/drivers/gpu/drm/ast/Makefile
@@ -3,6 +3,6 @@
 # Makefile for the drm device driver.  This driver provides support for the  # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
 
-ast-y := ast_drv.o ast_main.o ast_mm.o ast_mode.o ast_post.o ast_dp501.o
+ast-y := ast_drv.o ast_main.o ast_mm.o ast_mode.o ast_post.o 
+ast_dp501.o ast_dp.o
 
 obj-$(CONFIG_DRM_AST) := ast.o
diff --git a/drivers/gpu/drm/ast/ast_dp.c b/drivers/gpu/drm/ast/ast_dp.c new file mode 100644 index 000000000..537eaf4fa
--- /dev/null
+++ b/drivers/gpu/drm/ast/ast_dp.c
@@ -0,0 +1,286 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person 
+obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject 
+to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
+EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
+MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT 
+SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR 
+ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 
+OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 
+OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial 
+portions
+ * of the Software.
+ *
+ */
+/*
+ * Authors: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com>  */
+
+#include <linux/firmware.h>
+#include <linux/delay.h>
+#include <drm/drm_print.h>
+#include "ast_drv.h"
+
+bool ast_dp_read_edid(struct drm_device *dev, u8 *ediddata) {
+	struct ast_private *ast = to_ast_private(dev);
+	u8 i = 0, j = 0;
+
+#ifdef DPControlPower
+	u8 bDPState_Change = false;
+
+	// Check DP power off or not.
+	if (ast->ASTDP_State & 0x10) {
+		// DP power on
+		ast_dp_PowerOnOff(dev, 1);
+		bDPState_Change = true;
+	}
+#endif
+
+	/*
+	 * CRD1[b5]: DP MCU FW is executing
+	 * CRDC[b0]: DP link success
+	 * CRDF[b0]: DP HPD
+	 * CRE5[b0]: Host reading EDID process is done
+	 */
+	if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, 0x20) &&
+		ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, 0x01) &&
+		ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, 0x01) &&
+		ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, 0x01))) { #ifdef 
+DPControlPower
+		// Set back power off
+		if (bDPState_Change)
+			ast_dp_PowerOnOff(dev, 0);
+#endif
+		return false;
+	}
+
+	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, 0x00, 0x00);
+
+	for (i = 0; i < 32; i++) {
+		/*
+		 * CRE4[7:0]: Read-Pointer for EDID (Unit: 4bytes); valid range: 0~64
+		 */
+		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE4, 0x00, (u8) i);
+		j = 0;
+
+		/*
+		 * CRD7[b0]: valid flag for EDID
+		 * CRD6[b0]: mirror read pointer for EDID
+		 */
+		while ((ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD7, 0x01) != 0x01) ||
+			(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD6, 0xFF) != i)) {
+			mdelay(j+1);
+
+			if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, 0x20) &&
+				ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, 0x01) &&
+				ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, 0x01))) {
+				ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, 0x00, 0x01);
+				return false;
+			}
+
+			j++;
+			if (j > 200) {
+				ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, 0x00, 0x01);
+				return false;
+			}
+		}
+
+		*(ediddata) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD8, 0xFF);
+		*(ediddata + 1) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD9, 0xFF);
+		*(ediddata + 2) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDA, 0xFF);
+		*(ediddata + 3) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDB, 
+0xFF);
+
+		if (i == 31) {
+			*(ediddata + 3) = *(ediddata + 3) + *(ediddata + 2);
+			*(ediddata + 2) = 0;
+		}
+
+		ediddata += 4;
+	}
+
+	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, 0x00, 0x01);
+
+#ifdef DPControlPower
+	// Set back power off
+	if (bDPState_Change)
+		ast_dp_PowerOnOff(dev, 0);
+#endif
+
+	return true;
+}
+
+/*
+ * Launch Aspeed DP
+ */
+bool ast_dp_launch(struct drm_device *dev, u8 bPower) {
+	u32 i = 0, j = 0, WaitCount = 1;
+	u8 bDPTX = 0;
+	u8 bDPExecute = 1;
+
+	struct ast_private *ast = to_ast_private(dev);
+	// S3 come back, need more time to wait BMC ready.
+	if (bPower)
+		WaitCount = 300;
+
+	// Fill
+	ast->tx_chip_type = AST_TX_NONE;
+
+	// Wait total count by different condition.
+	// This is a temp solution for DP check
+	for (j = 0; j < WaitCount; j++) {
+		bDPTX = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, 0x0E);
+
+		if (bDPTX)
+			break;
+
+		msleep(100);
+	}
+
+	// 0xE : ASTDP with DPMCU FW handling
+	if (bDPTX == 0x0E) {
+		// Wait one second then timeout.
+		i = 0;
+
+		while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, 0x20) != 0x20) {
+			i++;
+			// wait 100 ms
+			msleep(100);
+
+			if (i >= 10) {
+				// DP would not be ready.
+				bDPExecute = 0;
+				break;
+			}
+		};
+
+		if (bDPExecute)
+			ast->tx_chip_type = AST_TX_ASTDP;
+	}
+
+	return true;
+}
+
+#ifdef DPControlPower
+
+void ast_dp_PowerOnOff(struct drm_device *dev, u8 Mode) {
+	struct ast_private *ast = to_ast_private(dev);
+	// Read and Turn off DP PHY sleep
+	u8 bE3 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, 0x0F);
+
+	// Turn on DP PHY sleep
+	if (!Mode)
+		bE3 |= 0x10;
+
+	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, 0x00, bE3); // DP 
+Power on/off
+
+	// Save ASTDP power state
+	ast->ASTDP_State = bE3;
+}
+
+#endif
+
+void ast_dp_SetOnOff(struct drm_device *dev, u8 Mode) {
+	struct ast_private *ast = to_ast_private(dev);
+
+	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, 0x00, Mode); // 
+video on/off
+
+	// Save ASTDP power state
+	ast->ASTDP_State = Mode;
+
+    // If DP plug in and link successful then check video on / off status
+	if (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, 0x01) &&
+		ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, 0x01)) {
+		Mode <<= 4;
+		while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, 0x10) != Mode) {
+			// wait 1 ms
+			mdelay(1);
+		}
+	}
+}
+
+void ast_dp_SetOutput(struct drm_crtc *crtc, struct ast_vbios_mode_info 
+*vbios_mode) {
+	struct ast_private *ast = to_ast_private(crtc->dev);
+
+	u32 ulRefreshRateIndex;
+	u8 ModeIdx;
+
+	ulRefreshRateIndex = vbios_mode->enh_table->refresh_rate_index - 1;
+
+	switch (crtc->mode.crtc_hdisplay) {
+	case 320:
+		ModeIdx = 0x11;
+		break;
+	case 400:
+		ModeIdx = 0x12;
+		break;
+	case 512:
+		ModeIdx = 0x13;
+		break;
+	case 640:
+		ModeIdx = (0x00 + (u8) ulRefreshRateIndex);
+		break;
+	case 800:
+		ModeIdx = (0x04 + (u8) ulRefreshRateIndex);
+		break;
+	case 1024:
+		ModeIdx = (0x09 + (u8) ulRefreshRateIndex);
+		break;
+	case 1152:
+		ModeIdx = 0x1F;
+		break;
+	case 1280:
+		if (crtc->mode.crtc_vdisplay == 800)
+			ModeIdx = (0x17 - (u8) ulRefreshRateIndex);	// For RB/Non-RB
+		else		// 1024
+			ModeIdx = (0x0D + (u8) ulRefreshRateIndex);
+		break;
+	case 1360:
+	case 1366:
+		ModeIdx = 0x1E;
+		break;
+	case 1440:
+		ModeIdx = (0x19 - (u8) ulRefreshRateIndex);	// For RB/Non-RB
+		break;
+	case 1600:
+		if (crtc->mode.crtc_vdisplay == 900)
+			ModeIdx = (0x1D - (u8) ulRefreshRateIndex);	// For RB/Non-RB
+		else		//1200
+			ModeIdx = 0x10;
+		break;
+	case 1680:
+		ModeIdx = (0x1B - (u8) ulRefreshRateIndex);	// For RB/Non-RB
+		break;
+	case 1920:
+		if (crtc->mode.crtc_vdisplay == 1080)
+			ModeIdx = 0x15;
+		else		//1200
+			ModeIdx = 0x14;
+		break;
+	default:
+		return;
+	}
+
+	/*
+	 * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp)
+	 * CRE1[7:0]: MISC1 (default: 0x00)
+	 * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50)
+	 */
+	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE0, 0x00, 0x20);
+	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE1, 0x00, 0x00);
+	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE2, 0x00, ModeIdx); }
diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index 2cfce7dc9..e56d5d57b 100644
--- a/drivers/gpu/drm/ast/ast_drv.h
+++ b/drivers/gpu/drm/ast/ast_drv.h
@@ -71,6 +71,7 @@ enum ast_tx_chip {
 	AST_TX_SIL164,
 	AST_TX_ITE66121,
 	AST_TX_DP501,
+	AST_TX_ASTDP,
 };
 
 #define AST_DRAM_512Mx16 0
@@ -175,6 +176,9 @@ struct ast_private {
 	u8 dp501_maxclk;
 	u8 *dp501_fw_addr;
 	const struct firmware *dp501_fw;	/* dp501 fw */
+
+    // ASTDP
+	u8 ASTDP_State;
 };
 
 static inline struct ast_private *to_ast_private(struct drm_device *dev) @@ -356,5 +360,14 @@ bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 size);  bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata);
 u8 ast_get_dp501_max_clk(struct drm_device *dev);  void ast_init_3rdtx(struct drm_device *dev);
+/* aspeed DP */
+#define DPControlPower
+bool ast_dp_read_edid(struct drm_device *dev, u8 *ediddata); bool 
+ast_dp_launch(struct drm_device *dev, u8 bPower); #ifdef DPControlPower 
+void ast_dp_PowerOnOff(struct drm_device *dev, u8 Mode); #endif void 
+ast_dp_SetOnOff(struct drm_device *dev, u8 Mode); void 
+ast_dp_SetOutput(struct drm_crtc *crtc, struct ast_vbios_mode_info 
+*vbios_mode);
 
 #endif
diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c index 79a361867..de5d69888 100644
--- a/drivers/gpu/drm/ast/ast_main.c
+++ b/drivers/gpu/drm/ast/ast_main.c
@@ -212,7 +212,7 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
 		}
 		break;
 	}
-
+	ast->support_wide_screen = true;
 	/* Check 3rd Tx option (digital output afaik) */
 	ast->tx_chip_type = AST_TX_NONE;
 
@@ -230,7 +230,7 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
 			ast->tx_chip_type = AST_TX_SIL164;
 	}
 
-	if ((ast->chip == AST2300) || (ast->chip == AST2400)) {
+	if ((ast->chip == AST2300) || (ast->chip == AST2400) || (ast->chip == 
+AST2500)) {
 		/*
 		 * On AST2300 and 2400, look the configuration set by the SoC in
 		 * the SOC scratch register #1 bits 11:8 (interestingly marked @@ -254,7 +254,8 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
 		case 0x0c:
 			ast->tx_chip_type = AST_TX_DP501;
 		}
-	}
+	} else if (ast->chip == AST2600)
+		ast_dp_launch(&ast->base, 0);
 
 	/* Print stuff for diagnostic purposes */
 	switch(ast->tx_chip_type) {
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 6bfaefa01..d7347d510 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -987,20 +987,44 @@ static int ast_cursor_plane_init(struct ast_private *ast)  static void ast_crtc_dpms(struct drm_crtc *crtc, int mode)  {
 	struct ast_private *ast = to_ast_private(crtc->dev);
+	u8 ch = 0x03;
 
 	/* TODO: Maybe control display signal generation with
 	 *       Sync Enable (bit CR17.7).
 	 */
 	switch (mode) {
 	case DRM_MODE_DPMS_ON:
-	case DRM_MODE_DPMS_STANDBY:
-	case DRM_MODE_DPMS_SUSPEND:
+		ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT,  0x01, 0xdf, 0);
+		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, 0);
 		if (ast->tx_chip_type == AST_TX_DP501)
 			ast_set_dp501_video_output(crtc->dev, 1);
+
+		if (ast->tx_chip_type == AST_TX_ASTDP) { #ifdef DPControlPower
+			ast_dp_PowerOnOff(crtc->dev, 1);
+#endif
+			ast_wait_for_vretrace(ast);
+			ast_dp_SetOnOff(crtc->dev, 1);
+		}
+
+		ast_crtc_load_lut(ast, crtc);
 		break;
+	case DRM_MODE_DPMS_STANDBY:
+	case DRM_MODE_DPMS_SUSPEND:
 	case DRM_MODE_DPMS_OFF:
+		ch = mode;
 		if (ast->tx_chip_type == AST_TX_DP501)
 			ast_set_dp501_video_output(crtc->dev, 0);
+
+		if (ast->tx_chip_type == AST_TX_ASTDP) {
+			ast_dp_SetOnOff(crtc->dev, 0);
+#ifdef DPControlPower
+			ast_dp_PowerOnOff(crtc->dev, 0);
+#endif
+		}
+
+		ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT,  0x01, 0xdf, 0x20);
+		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, ch);
 		break;
 	}
 }
@@ -1044,6 +1068,8 @@ ast_crtc_helper_atomic_flush(struct drm_crtc *crtc,
 	struct ast_private *ast = to_ast_private(crtc->dev);
 	struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
 	struct ast_crtc_state *old_ast_crtc_state = to_ast_crtc_state(old_crtc_state);
+struct ast_vbios_mode_info *vbios_mode_info =
+		&ast_crtc_state->vbios_mode_info;
 
 	/*
 	 * The gamma LUT has to be reloaded after changing the primary @@ -1051,6 +1077,10 @@ ast_crtc_helper_atomic_flush(struct drm_crtc *crtc,
 	 */
 	if (old_ast_crtc_state->format != ast_crtc_state->format)
 		ast_crtc_load_lut(ast, crtc);
+
+	//Set Aspeed Display-Port
+	if (ast->tx_chip_type == AST_TX_ASTDP)
+		ast_dp_SetOutput(crtc, vbios_mode_info);
 }
 
 static void
@@ -1225,7 +1255,16 @@ static int ast_get_modes(struct drm_connector *connector)
 			ast->dp501_maxclk = ast_get_dp501_max_clk(connector->dev);
 		else
 			kfree(edid);
+	} else if (ast->tx_chip_type == AST_TX_ASTDP) {
+		edid = kmalloc(128, GFP_KERNEL);
+		if (!edid)
+			return -ENOMEM;
+
+		flags = ast_dp_read_edid(connector->dev, (u8 *)edid);
+		if (!flags)
+			kfree(edid);
 	}
+
 	if (!flags)
 		edid = drm_get_edid(connector, &ast_connector->i2c->adapter);
 	if (edid) {
@@ -1256,10 +1295,12 @@ static enum drm_mode_status ast_mode_valid(struct drm_connector *connector,
 			return MODE_OK;
 		if ((mode->hdisplay == 1600) && (mode->vdisplay == 900))
 			return MODE_OK;
+		if ((mode->hdisplay == 1152) && (mode->vdisplay == 864))
+			return MODE_OK;
 
 		if ((ast->chip == AST2100) || (ast->chip == AST2200) ||
 		    (ast->chip == AST2300) || (ast->chip == AST2400) ||
-		    (ast->chip == AST2500)) {
+		    (ast->chip == AST2500) || (ast->chip == AST2600)) {
 			if ((mode->hdisplay == 1920) && (mode->vdisplay == 1080))
 				return MODE_OK;
 
@@ -1400,7 +1441,8 @@ int ast_mode_config_init(struct ast_private *ast)
 	    ast->chip == AST2200 ||
 	    ast->chip == AST2300 ||
 	    ast->chip == AST2400 ||
-	    ast->chip == AST2500) {
+	    ast->chip == AST2500 ||
+	    ast->chip == AST2600) {
 		dev->mode_config.max_width = 1920;
 		dev->mode_config.max_height = 2048;
 	} else {
diff --git a/drivers/gpu/drm/ast/ast_post.c b/drivers/gpu/drm/ast/ast_post.c index b5d92f652..0aa9cf0fb 100644
--- a/drivers/gpu/drm/ast/ast_post.c
+++ b/drivers/gpu/drm/ast/ast_post.c
@@ -379,7 +379,9 @@ void ast_post_gpu(struct drm_device *dev)
 	ast_enable_mmio(dev);
 	ast_set_def_ext_reg(dev);
 
-	if (ast->config_mode == ast_use_p2a) {
+	if (ast->chip == AST2600) {
+		ast_dp_launch(dev, 1);
+	} else if (ast->config_mode == ast_use_p2a) {
 		if (ast->chip == AST2500)
 			ast_post_chip_2500(dev);
 		else if (ast->chip == AST2300 || ast->chip == AST2400)
--
2.27.0


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] drm/ast: Create the driver for ASPEED proprietory Display-Port
  2021-12-03  6:31 ` Kuo-Hsiang Chou
@ 2021-12-03  8:54   ` Thomas Zimmermann
  2021-12-27  8:37     ` [PATCH v2] " KuoHsiang Chou
  0 siblings, 1 reply; 21+ messages in thread
From: Thomas Zimmermann @ 2021-12-03  8:54 UTC (permalink / raw)
  To: Kuo-Hsiang Chou, dri-devel, linux-kernel
  Cc: Hungju Huang, airlied, Brandon Chen, Tommy Huang, Jenmin Yuan,
	airlied, Arc Sung, Luke Chen


[-- Attachment #1.1: Type: text/plain, Size: 18481 bytes --]

Hi

Am 03.12.21 um 07:31 schrieb Kuo-Hsiang Chou:
> Hi Thomas,
> 
> Hi Tomas,
> Good day!
> May I get the review status, or is there anything I can do to improve it? Thanks!
> 
> Best Regards,
> 	Kuo-Hsiang Chou
> 
> -----Original Message-----
> From: Kuo-Hsiang Chou
> Sent: Monday, November 22, 2021 6:36 PM
> To: tzimmermann@suse.de; dri-devel@lists.freedesktop.org; linux-kernel@vger.kernel.org
> Subject: [PATCH] drm/ast: Create the driver for ASPEED proprietory Display-Port
> 
> 1. The MCU FW controling ASPEED DP is loaded by BMC boot loader.
> 2. Driver starts after CR[3:1] == 111b that indicates Tx is ASTDP,
>     and CRD1[5] has been asserted by BMVC boot loader.
> 3. EDID is prioritized by DP monitor.
> 4. DP's EDID has high priority to decide resolution supporting.
> 
> Signed-off-by: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com>
> ---
>   drivers/gpu/drm/ast/Makefile   |   2 +-
>   drivers/gpu/drm/ast/ast_dp.c   | 286 +++++++++++++++++++++++++++++++++
>   drivers/gpu/drm/ast/ast_drv.h  |  13 ++
>   drivers/gpu/drm/ast/ast_main.c |   7 +-
>   drivers/gpu/drm/ast/ast_mode.c |  50 +++++-
>   drivers/gpu/drm/ast/ast_post.c |   4 +-
>   6 files changed, 353 insertions(+), 9 deletions(-)  create mode 100644 drivers/gpu/drm/ast/ast_dp.c
> 
> diff --git a/drivers/gpu/drm/ast/Makefile b/drivers/gpu/drm/ast/Makefile index 438a2d05b..9bd0756e0 100644
> --- a/drivers/gpu/drm/ast/Makefile
> +++ b/drivers/gpu/drm/ast/Makefile
> @@ -3,6 +3,6 @@
>   # Makefile for the drm device driver.  This driver provides support for the  # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
>   
> -ast-y := ast_drv.o ast_main.o ast_mm.o ast_mode.o ast_post.o ast_dp501.o
> +ast-y := ast_drv.o ast_main.o ast_mm.o ast_mode.o ast_post.o
> +ast_dp501.o ast_dp.o
>   
>   obj-$(CONFIG_DRM_AST) := ast.o
> diff --git a/drivers/gpu/drm/ast/ast_dp.c b/drivers/gpu/drm/ast/ast_dp.c new file mode 100644 index 000000000..537eaf4fa
> --- /dev/null
> +++ b/drivers/gpu/drm/ast/ast_dp.c
> @@ -0,0 +1,286 @@
> +/*
> + * Copyright 2012 Red Hat Inc.

You didn't even put in your company's copyright. So what am I supposed 
to do about this patch?

For the rest of the code, it's just bolted onto the existing connector. 
Which already has been hacked to support an DP port. I began redesigning 
the whole thing to support each connector individually. I'm not going to 
add more hacks to it.

Best regards
Thomas

> + *
> + * Permission is hereby granted, free of charge, to any person
> +obtaining a
> + * copy of this software and associated documentation files (the
> + * "Software"), to deal in the Software without restriction, including
> + * without limitation the rights to use, copy, modify, merge, publish,
> + * distribute, sub license, and/or sell copies of the Software, and to
> + * permit persons to whom the Software is furnished to do so, subject
> +to
> + * the following conditions:
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> +EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> +MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT
> +SHALL
> + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR
> +ANY CLAIM,
> + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
> +OR
> + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
> +OR THE
> + * USE OR OTHER DEALINGS IN THE SOFTWARE.
> + *
> + * The above copyright notice and this permission notice (including the
> + * next paragraph) shall be included in all copies or substantial
> +portions
> + * of the Software.
> + *
> + */
> +/*
> + * Authors: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com>  */
> +
> +#include <linux/firmware.h>
> +#include <linux/delay.h>
> +#include <drm/drm_print.h>
> +#include "ast_drv.h"
> +
> +bool ast_dp_read_edid(struct drm_device *dev, u8 *ediddata) {
> +	struct ast_private *ast = to_ast_private(dev);
> +	u8 i = 0, j = 0;
> +
> +#ifdef DPControlPower
> +	u8 bDPState_Change = false;
> +
> +	// Check DP power off or not.
> +	if (ast->ASTDP_State & 0x10) {
> +		// DP power on
> +		ast_dp_PowerOnOff(dev, 1);
> +		bDPState_Change = true;
> +	}
> +#endif
> +
> +	/*
> +	 * CRD1[b5]: DP MCU FW is executing
> +	 * CRDC[b0]: DP link success
> +	 * CRDF[b0]: DP HPD
> +	 * CRE5[b0]: Host reading EDID process is done
> +	 */
> +	if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, 0x20) &&
> +		ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, 0x01) &&
> +		ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, 0x01) &&
> +		ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, 0x01))) { #ifdef
> +DPControlPower
> +		// Set back power off
> +		if (bDPState_Change)
> +			ast_dp_PowerOnOff(dev, 0);
> +#endif
> +		return false;
> +	}
> +
> +	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, 0x00, 0x00);
> +
> +	for (i = 0; i < 32; i++) {
> +		/*
> +		 * CRE4[7:0]: Read-Pointer for EDID (Unit: 4bytes); valid range: 0~64
> +		 */
> +		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE4, 0x00, (u8) i);
> +		j = 0;
> +
> +		/*
> +		 * CRD7[b0]: valid flag for EDID
> +		 * CRD6[b0]: mirror read pointer for EDID
> +		 */
> +		while ((ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD7, 0x01) != 0x01) ||
> +			(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD6, 0xFF) != i)) {
> +			mdelay(j+1);
> +
> +			if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, 0x20) &&
> +				ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, 0x01) &&
> +				ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, 0x01))) {
> +				ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, 0x00, 0x01);
> +				return false;
> +			}
> +
> +			j++;
> +			if (j > 200) {
> +				ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, 0x00, 0x01);
> +				return false;
> +			}
> +		}
> +
> +		*(ediddata) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD8, 0xFF);
> +		*(ediddata + 1) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD9, 0xFF);
> +		*(ediddata + 2) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDA, 0xFF);
> +		*(ediddata + 3) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDB,
> +0xFF);
> +
> +		if (i == 31) {
> +			*(ediddata + 3) = *(ediddata + 3) + *(ediddata + 2);
> +			*(ediddata + 2) = 0;
> +		}
> +
> +		ediddata += 4;
> +	}
> +
> +	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, 0x00, 0x01);
> +
> +#ifdef DPControlPower
> +	// Set back power off
> +	if (bDPState_Change)
> +		ast_dp_PowerOnOff(dev, 0);
> +#endif
> +
> +	return true;
> +}
> +
> +/*
> + * Launch Aspeed DP
> + */
> +bool ast_dp_launch(struct drm_device *dev, u8 bPower) {
> +	u32 i = 0, j = 0, WaitCount = 1;
> +	u8 bDPTX = 0;
> +	u8 bDPExecute = 1;
> +
> +	struct ast_private *ast = to_ast_private(dev);
> +	// S3 come back, need more time to wait BMC ready.
> +	if (bPower)
> +		WaitCount = 300;
> +
> +	// Fill
> +	ast->tx_chip_type = AST_TX_NONE;
> +
> +	// Wait total count by different condition.
> +	// This is a temp solution for DP check
> +	for (j = 0; j < WaitCount; j++) {
> +		bDPTX = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, 0x0E);
> +
> +		if (bDPTX)
> +			break;
> +
> +		msleep(100);
> +	}
> +
> +	// 0xE : ASTDP with DPMCU FW handling
> +	if (bDPTX == 0x0E) {
> +		// Wait one second then timeout.
> +		i = 0;
> +
> +		while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, 0x20) != 0x20) {
> +			i++;
> +			// wait 100 ms
> +			msleep(100);
> +
> +			if (i >= 10) {
> +				// DP would not be ready.
> +				bDPExecute = 0;
> +				break;
> +			}
> +		};
> +
> +		if (bDPExecute)
> +			ast->tx_chip_type = AST_TX_ASTDP;
> +	}
> +
> +	return true;
> +}
> +
> +#ifdef DPControlPower
> +
> +void ast_dp_PowerOnOff(struct drm_device *dev, u8 Mode) {
> +	struct ast_private *ast = to_ast_private(dev);
> +	// Read and Turn off DP PHY sleep
> +	u8 bE3 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, 0x0F);
> +
> +	// Turn on DP PHY sleep
> +	if (!Mode)
> +		bE3 |= 0x10;
> +
> +	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, 0x00, bE3); // DP
> +Power on/off
> +
> +	// Save ASTDP power state
> +	ast->ASTDP_State = bE3;
> +}
> +
> +#endif
> +
> +void ast_dp_SetOnOff(struct drm_device *dev, u8 Mode) {
> +	struct ast_private *ast = to_ast_private(dev);
> +
> +	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, 0x00, Mode); //
> +video on/off
> +
> +	// Save ASTDP power state
> +	ast->ASTDP_State = Mode;
> +
> +    // If DP plug in and link successful then check video on / off status
> +	if (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, 0x01) &&
> +		ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, 0x01)) {
> +		Mode <<= 4;
> +		while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, 0x10) != Mode) {
> +			// wait 1 ms
> +			mdelay(1);
> +		}
> +	}
> +}
> +
> +void ast_dp_SetOutput(struct drm_crtc *crtc, struct ast_vbios_mode_info
> +*vbios_mode) {
> +	struct ast_private *ast = to_ast_private(crtc->dev);
> +
> +	u32 ulRefreshRateIndex;
> +	u8 ModeIdx;
> +
> +	ulRefreshRateIndex = vbios_mode->enh_table->refresh_rate_index - 1;
> +
> +	switch (crtc->mode.crtc_hdisplay) {
> +	case 320:
> +		ModeIdx = 0x11;
> +		break;
> +	case 400:
> +		ModeIdx = 0x12;
> +		break;
> +	case 512:
> +		ModeIdx = 0x13;
> +		break;
> +	case 640:
> +		ModeIdx = (0x00 + (u8) ulRefreshRateIndex);
> +		break;
> +	case 800:
> +		ModeIdx = (0x04 + (u8) ulRefreshRateIndex);
> +		break;
> +	case 1024:
> +		ModeIdx = (0x09 + (u8) ulRefreshRateIndex);
> +		break;
> +	case 1152:
> +		ModeIdx = 0x1F;
> +		break;
> +	case 1280:
> +		if (crtc->mode.crtc_vdisplay == 800)
> +			ModeIdx = (0x17 - (u8) ulRefreshRateIndex);	// For RB/Non-RB
> +		else		// 1024
> +			ModeIdx = (0x0D + (u8) ulRefreshRateIndex);
> +		break;
> +	case 1360:
> +	case 1366:
> +		ModeIdx = 0x1E;
> +		break;
> +	case 1440:
> +		ModeIdx = (0x19 - (u8) ulRefreshRateIndex);	// For RB/Non-RB
> +		break;
> +	case 1600:
> +		if (crtc->mode.crtc_vdisplay == 900)
> +			ModeIdx = (0x1D - (u8) ulRefreshRateIndex);	// For RB/Non-RB
> +		else		//1200
> +			ModeIdx = 0x10;
> +		break;
> +	case 1680:
> +		ModeIdx = (0x1B - (u8) ulRefreshRateIndex);	// For RB/Non-RB
> +		break;
> +	case 1920:
> +		if (crtc->mode.crtc_vdisplay == 1080)
> +			ModeIdx = 0x15;
> +		else		//1200
> +			ModeIdx = 0x14;
> +		break;
> +	default:
> +		return;
> +	}
> +
> +	/*
> +	 * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp)
> +	 * CRE1[7:0]: MISC1 (default: 0x00)
> +	 * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50)
> +	 */
> +	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE0, 0x00, 0x20);
> +	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE1, 0x00, 0x00);
> +	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE2, 0x00, ModeIdx); }
> diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index 2cfce7dc9..e56d5d57b 100644
> --- a/drivers/gpu/drm/ast/ast_drv.h
> +++ b/drivers/gpu/drm/ast/ast_drv.h
> @@ -71,6 +71,7 @@ enum ast_tx_chip {
>   	AST_TX_SIL164,
>   	AST_TX_ITE66121,
>   	AST_TX_DP501,
> +	AST_TX_ASTDP,
>   };
>   
>   #define AST_DRAM_512Mx16 0
> @@ -175,6 +176,9 @@ struct ast_private {
>   	u8 dp501_maxclk;
>   	u8 *dp501_fw_addr;
>   	const struct firmware *dp501_fw;	/* dp501 fw */
> +
> +    // ASTDP
> +	u8 ASTDP_State;
>   };
>   
>   static inline struct ast_private *to_ast_private(struct drm_device *dev) @@ -356,5 +360,14 @@ bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 size);  bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata);
>   u8 ast_get_dp501_max_clk(struct drm_device *dev);  void ast_init_3rdtx(struct drm_device *dev);
> +/* aspeed DP */
> +#define DPControlPower
> +bool ast_dp_read_edid(struct drm_device *dev, u8 *ediddata); bool
> +ast_dp_launch(struct drm_device *dev, u8 bPower); #ifdef DPControlPower
> +void ast_dp_PowerOnOff(struct drm_device *dev, u8 Mode); #endif void
> +ast_dp_SetOnOff(struct drm_device *dev, u8 Mode); void
> +ast_dp_SetOutput(struct drm_crtc *crtc, struct ast_vbios_mode_info
> +*vbios_mode);
>   
>   #endif
> diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c index 79a361867..de5d69888 100644
> --- a/drivers/gpu/drm/ast/ast_main.c
> +++ b/drivers/gpu/drm/ast/ast_main.c
> @@ -212,7 +212,7 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
>   		}
>   		break;
>   	}
> -
> +	ast->support_wide_screen = true;
>   	/* Check 3rd Tx option (digital output afaik) */
>   	ast->tx_chip_type = AST_TX_NONE;
>   
> @@ -230,7 +230,7 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
>   			ast->tx_chip_type = AST_TX_SIL164;
>   	}
>   
> -	if ((ast->chip == AST2300) || (ast->chip == AST2400)) {
> +	if ((ast->chip == AST2300) || (ast->chip == AST2400) || (ast->chip ==
> +AST2500)) {
>   		/*
>   		 * On AST2300 and 2400, look the configuration set by the SoC in
>   		 * the SOC scratch register #1 bits 11:8 (interestingly marked @@ -254,7 +254,8 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
>   		case 0x0c:
>   			ast->tx_chip_type = AST_TX_DP501;
>   		}
> -	}
> +	} else if (ast->chip == AST2600)
> +		ast_dp_launch(&ast->base, 0);
>   
>   	/* Print stuff for diagnostic purposes */
>   	switch(ast->tx_chip_type) {
> diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 6bfaefa01..d7347d510 100644
> --- a/drivers/gpu/drm/ast/ast_mode.c
> +++ b/drivers/gpu/drm/ast/ast_mode.c
> @@ -987,20 +987,44 @@ static int ast_cursor_plane_init(struct ast_private *ast)  static void ast_crtc_dpms(struct drm_crtc *crtc, int mode)  {
>   	struct ast_private *ast = to_ast_private(crtc->dev);
> +	u8 ch = 0x03;
>   
>   	/* TODO: Maybe control display signal generation with
>   	 *       Sync Enable (bit CR17.7).
>   	 */
>   	switch (mode) {
>   	case DRM_MODE_DPMS_ON:
> -	case DRM_MODE_DPMS_STANDBY:
> -	case DRM_MODE_DPMS_SUSPEND:
> +		ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT,  0x01, 0xdf, 0);
> +		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, 0);
>   		if (ast->tx_chip_type == AST_TX_DP501)
>   			ast_set_dp501_video_output(crtc->dev, 1);
> +
> +		if (ast->tx_chip_type == AST_TX_ASTDP) { #ifdef DPControlPower
> +			ast_dp_PowerOnOff(crtc->dev, 1);
> +#endif
> +			ast_wait_for_vretrace(ast);
> +			ast_dp_SetOnOff(crtc->dev, 1);
> +		}
> +
> +		ast_crtc_load_lut(ast, crtc);
>   		break;
> +	case DRM_MODE_DPMS_STANDBY:
> +	case DRM_MODE_DPMS_SUSPEND:
>   	case DRM_MODE_DPMS_OFF:
> +		ch = mode;
>   		if (ast->tx_chip_type == AST_TX_DP501)
>   			ast_set_dp501_video_output(crtc->dev, 0);
> +
> +		if (ast->tx_chip_type == AST_TX_ASTDP) {
> +			ast_dp_SetOnOff(crtc->dev, 0);
> +#ifdef DPControlPower
> +			ast_dp_PowerOnOff(crtc->dev, 0);
> +#endif
> +		}
> +
> +		ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT,  0x01, 0xdf, 0x20);
> +		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, ch);
>   		break;
>   	}
>   }
> @@ -1044,6 +1068,8 @@ ast_crtc_helper_atomic_flush(struct drm_crtc *crtc,
>   	struct ast_private *ast = to_ast_private(crtc->dev);
>   	struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
>   	struct ast_crtc_state *old_ast_crtc_state = to_ast_crtc_state(old_crtc_state);
> +struct ast_vbios_mode_info *vbios_mode_info =
> +		&ast_crtc_state->vbios_mode_info;
>   
>   	/*
>   	 * The gamma LUT has to be reloaded after changing the primary @@ -1051,6 +1077,10 @@ ast_crtc_helper_atomic_flush(struct drm_crtc *crtc,
>   	 */
>   	if (old_ast_crtc_state->format != ast_crtc_state->format)
>   		ast_crtc_load_lut(ast, crtc);
> +
> +	//Set Aspeed Display-Port
> +	if (ast->tx_chip_type == AST_TX_ASTDP)
> +		ast_dp_SetOutput(crtc, vbios_mode_info);
>   }
>   
>   static void
> @@ -1225,7 +1255,16 @@ static int ast_get_modes(struct drm_connector *connector)
>   			ast->dp501_maxclk = ast_get_dp501_max_clk(connector->dev);
>   		else
>   			kfree(edid);
> +	} else if (ast->tx_chip_type == AST_TX_ASTDP) {
> +		edid = kmalloc(128, GFP_KERNEL);
> +		if (!edid)
> +			return -ENOMEM;
> +
> +		flags = ast_dp_read_edid(connector->dev, (u8 *)edid);
> +		if (!flags)
> +			kfree(edid);
>   	}
> +
>   	if (!flags)
>   		edid = drm_get_edid(connector, &ast_connector->i2c->adapter);
>   	if (edid) {
> @@ -1256,10 +1295,12 @@ static enum drm_mode_status ast_mode_valid(struct drm_connector *connector,
>   			return MODE_OK;
>   		if ((mode->hdisplay == 1600) && (mode->vdisplay == 900))
>   			return MODE_OK;
> +		if ((mode->hdisplay == 1152) && (mode->vdisplay == 864))
> +			return MODE_OK;
>   
>   		if ((ast->chip == AST2100) || (ast->chip == AST2200) ||
>   		    (ast->chip == AST2300) || (ast->chip == AST2400) ||
> -		    (ast->chip == AST2500)) {
> +		    (ast->chip == AST2500) || (ast->chip == AST2600)) {
>   			if ((mode->hdisplay == 1920) && (mode->vdisplay == 1080))
>   				return MODE_OK;
>   
> @@ -1400,7 +1441,8 @@ int ast_mode_config_init(struct ast_private *ast)
>   	    ast->chip == AST2200 ||
>   	    ast->chip == AST2300 ||
>   	    ast->chip == AST2400 ||
> -	    ast->chip == AST2500) {
> +	    ast->chip == AST2500 ||
> +	    ast->chip == AST2600) {
>   		dev->mode_config.max_width = 1920;
>   		dev->mode_config.max_height = 2048;
>   	} else {
> diff --git a/drivers/gpu/drm/ast/ast_post.c b/drivers/gpu/drm/ast/ast_post.c index b5d92f652..0aa9cf0fb 100644
> --- a/drivers/gpu/drm/ast/ast_post.c
> +++ b/drivers/gpu/drm/ast/ast_post.c
> @@ -379,7 +379,9 @@ void ast_post_gpu(struct drm_device *dev)
>   	ast_enable_mmio(dev);
>   	ast_set_def_ext_reg(dev);
>   
> -	if (ast->config_mode == ast_use_p2a) {
> +	if (ast->chip == AST2600) {
> +		ast_dp_launch(dev, 1);
> +	} else if (ast->config_mode == ast_use_p2a) {
>   		if (ast->chip == AST2500)
>   			ast_post_chip_2500(dev);
>   		else if (ast->chip == AST2300 || ast->chip == AST2400)
> --
> 2.27.0
> 

-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Ivo Totev

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v2] drm/ast: Create the driver for ASPEED proprietory Display-Port
  2021-12-03  8:54   ` Thomas Zimmermann
@ 2021-12-27  8:37     ` KuoHsiang Chou
  0 siblings, 0 replies; 21+ messages in thread
From: KuoHsiang Chou @ 2021-12-27  8:37 UTC (permalink / raw)
  To: tzimmermann, dri-devel, linux-kernel
  Cc: airlied, airlied, daniel, jenmin_yuan, kuohsiang_chou, arc_sung,
	tommy_huang, brandon_chen, hungju_huang, luke_chen

V1:
1. The MCU FW controling ASPEED DP is loaded by BMC boot loader.
2. Driver starts after CR[3:1] == 111b that indicates Tx is ASTDP,
   and CRD1[5] has been asserted by BMVC boot loader.
3. EDID is prioritized by DP monitor.
4. DP's EDID has high priority to decide resolution supporting.

V2:
Modules description:
1. ASTDP (ASPEED DisplayPort) is controlled by dedicated
   AST-MCU (ASPEED propriatary MCU).
2. MCU is looping in charged of HPD, Read EDID, Link Training with
   DP sink.
3. ASTDP and AST-MUC reside in BMC (Baseboard Management controller)
   addressing-space.
4. ASPEED DRM driver requests MCU to get HPD and EDID by CR-scratched
   register.

Booting sequence:
1. Check if TX is ASTDP					// ast_dp_launch()
2. Check if DP-MCU FW has loaded					// ast_dp_launch()
3. Read EDID					// ast_dp_read_edid()
4. Resolution switch					// ast_dp_SetOutput()

Signed-off-by: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com>
---
 drivers/gpu/drm/ast/Makefile   |   2 +-
 drivers/gpu/drm/ast/ast_dp.c   | 292 +++++++++++++++++++++++++++++++++
 drivers/gpu/drm/ast/ast_drv.h  | 127 ++++++++++++++
 drivers/gpu/drm/ast/ast_main.c |   5 +-
 drivers/gpu/drm/ast/ast_mode.c |  46 +++++-
 drivers/gpu/drm/ast/ast_post.c |   4 +-
 6 files changed, 468 insertions(+), 8 deletions(-)
 create mode 100644 drivers/gpu/drm/ast/ast_dp.c

diff --git a/drivers/gpu/drm/ast/Makefile b/drivers/gpu/drm/ast/Makefile
index 21f71160b..5a53ce51f 100644
--- a/drivers/gpu/drm/ast/Makefile
+++ b/drivers/gpu/drm/ast/Makefile
@@ -3,6 +3,6 @@
 # Makefile for the drm device driver.  This driver provides support for the
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.

-ast-y := ast_drv.o ast_i2c.o ast_main.o ast_mm.o ast_mode.o ast_post.o ast_dp501.o
+ast-y := ast_drv.o ast_i2c.o ast_main.o ast_mm.o ast_mode.o ast_post.o ast_dp501.o ast_dp.o

 obj-$(CONFIG_DRM_AST) := ast.o
diff --git a/drivers/gpu/drm/ast/ast_dp.c b/drivers/gpu/drm/ast/ast_dp.c
new file mode 100644
index 000000000..4ac719ab0
--- /dev/null
+++ b/drivers/gpu/drm/ast/ast_dp.c
@@ -0,0 +1,292 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2021, ASPEED Technology Inc.
+// Authors: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com>
+
+#include <linux/firmware.h>
+#include <linux/delay.h>
+#include <drm/drm_print.h>
+#include "ast_drv.h"
+
+bool ast_dp_read_edid(struct drm_device *dev, u8 *ediddata)
+{
+	struct ast_private *ast = to_ast_private(dev);
+	u8 i = 0, j = 0;
+
+#ifdef DPControlPower
+	u8 bDPState_Change = false;
+
+	// Check DP power off or not.
+	if (ast->ASTDP_State & AST_DP_PHY_SLEEP) {
+		// DP power on
+		ast_dp_PowerOnOff(dev, AST_DP_POWER_ON);
+		bDPState_Change = true;
+	}
+#endif
+
+	/*
+	 * CRD1[b5]: DP MCU FW is executing
+	 * CRDC[b0]: DP link success
+	 * CRDF[b0]: DP HPD
+	 * CRE5[b0]: Host reading EDID process is done
+	 */
+	if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, ASTDP_MCU_FW_EXECUTING) &&
+		ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, ASTDP_LINK_SUCCESS) &&
+		ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD) &&
+		ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
+								ASTDP_HOST_EDID_READ_DONE_MASK))) {
+#ifdef DPControlPower
+		// Set back power off
+		if (bDPState_Change)
+			ast_dp_PowerOnOff(dev, AST_DP_POWER_OFF);
+#endif
+		return false;
+	}
+
+	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
+							0x00);
+
+	for (i = 0; i < 32; i++) {
+		/*
+		 * CRE4[7:0]: Read-Pointer for EDID (Unit: 4bytes); valid range: 0~64
+		 */
+		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE4,
+					(u8) ~ASTDP_EDID_READ_POINTER_MASK, (u8) i);
+		j = 0;
+
+		/*
+		 * CRD7[b0]: valid flag for EDID
+		 * CRD6[b0]: mirror read pointer for EDID
+		 */
+		while ((ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD7,
+				ASTDP_EDID_VALID_FLAG_MASK) != 0x01) ||
+			(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD6,
+						ASTDP_EDID_READ_POINTER_MASK) != i)) {
+			mdelay(j+1);
+
+			if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1,
+							ASTDP_MCU_FW_EXECUTING) &&
+				ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC,
+							ASTDP_LINK_SUCCESS) &&
+				ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD))) {
+				ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
+							(u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
+							ASTDP_HOST_EDID_READ_DONE);
+				return false;
+			}
+
+			j++;
+			if (j > 200) {
+				ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
+							(u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
+							ASTDP_HOST_EDID_READ_DONE);
+				return false;
+			}
+		}
+
+		*(ediddata) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT,
+							0xD8, ASTDP_EDID_READ_DATA_MASK);
+		*(ediddata + 1) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD9,
+								ASTDP_EDID_READ_DATA_MASK);
+		*(ediddata + 2) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDA,
+								ASTDP_EDID_READ_DATA_MASK);
+		*(ediddata + 3) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDB,
+								ASTDP_EDID_READ_DATA_MASK);
+
+		if (i == 31) {
+			/*
+			 * For 128-bytes EDID_1.3,
+			 * 1. Add the value of Bytes-126 to Bytes-127.
+			 *		The Bytes-127 is Checksum. Sum of all 128bytes should
+			 *		equal 0	(mod 256).
+			 * 2. Modify Bytes-126 to be 0.
+			 *		The Bytes-126 indicates the Number of extensions to
+			 *		follow. 0 represents noextensions.
+			 */
+			*(ediddata + 3) = *(ediddata + 3) + *(ediddata + 2);
+			*(ediddata + 2) = 0;
+		}
+
+		ediddata += 4;
+	}
+
+	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
+							ASTDP_HOST_EDID_READ_DONE);
+
+#ifdef DPControlPower
+	// Set back power off
+	if (bDPState_Change)
+		ast_dp_PowerOnOff(dev, AST_DP_POWER_OFF);
+#endif
+
+	return true;
+}
+
+/*
+ * Launch Aspeed DP
+ */
+bool ast_dp_launch(struct drm_device *dev, u8 bPower)
+{
+	u32 i = 0, j = 0, WaitCount = 1;
+	u8 bDPTX = 0;
+	u8 bDPExecute = 1;
+
+	struct ast_private *ast = to_ast_private(dev);
+	// S3 come back, need more time to wait BMC ready.
+	if (bPower)
+		WaitCount = 300;
+
+	// Fill
+	ast->tx_chip_type = AST_TX_NONE;
+
+	// Wait total count by different condition.
+	// This is a temp solution for DP check
+	for (j = 0; j < WaitCount; j++) {
+		bDPTX = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, TX_TYPE_MASK);
+
+		if (bDPTX)
+			break;
+
+		msleep(100);
+	}
+
+	// 0xE : ASTDP with DPMCU FW handling
+	if (bDPTX == ASTDP_DPMCU_TX) {
+		// Wait one second then timeout.
+		i = 0;
+
+		while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, COPROCESSOR_LAUNCH) !=
+			COPROCESSOR_LAUNCH) {
+			i++;
+			// wait 100 ms
+			msleep(100);
+
+			if (i >= 10) {
+				// DP would not be ready.
+				bDPExecute = 0;
+				break;
+			}
+		};
+
+		if (bDPExecute)
+			ast->tx_chip_type = AST_TX_ASTDP;
+	}
+
+	return true;
+}
+
+#ifdef DPControlPower
+
+void ast_dp_PowerOnOff(struct drm_device *dev, u8 Mode)
+{
+	struct ast_private *ast = to_ast_private(dev);
+	// Read and Turn off DP PHY sleep
+	u8 bE3 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, AST_DP_VIDEO_ENABLE);
+
+	// Turn on DP PHY sleep
+	if (!Mode)
+		bE3 |= AST_DP_PHY_SLEEP;
+
+	// DP Power on/off
+	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, (u8) ~AST_DP_PHY_SLEEP, bE3);
+
+	// Save ASTDP power state
+	ast->ASTDP_State = bE3;
+}
+
+#endif
+
+void ast_dp_SetOnOff(struct drm_device *dev, u8 Mode)
+{
+	struct ast_private *ast = to_ast_private(dev);
+
+	// Video On/Off
+	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, (u8) ~AST_DP_VIDEO_ENABLE, Mode);
+
+	// Save ASTDP power state
+	ast->ASTDP_State = Mode;
+
+	// If DP plug in and link successful then check video on / off status
+	if (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, ASTDP_LINK_SUCCESS) &&
+		ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD)) {
+		Mode <<= 4;
+		while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF,
+						ASTDP_MIRROR_VIDEO_ENABLE) != Mode) {
+			// wait 1 ms
+			mdelay(1);
+		}
+	}
+}
+
+void ast_dp_SetOutput(struct drm_crtc *crtc, struct ast_vbios_mode_info *vbios_mode)
+{
+	struct ast_private *ast = to_ast_private(crtc->dev);
+
+	u32 ulRefreshRateIndex;
+	u8 ModeIdx;
+
+	ulRefreshRateIndex = vbios_mode->enh_table->refresh_rate_index - 1;
+
+	switch (crtc->mode.crtc_hdisplay) {
+	case 320:
+		ModeIdx = ASTDP_320x240_60;
+		break;
+	case 400:
+		ModeIdx = ASTDP_400x300_60;
+		break;
+	case 512:
+		ModeIdx = ASTDP_512x384_60;
+		break;
+	case 640:
+		ModeIdx = (ASTDP_640x480_60 + (u8) ulRefreshRateIndex);
+		break;
+	case 800:
+		ModeIdx = (ASTDP_800x600_56 + (u8) ulRefreshRateIndex);
+		break;
+	case 1024:
+		ModeIdx = (ASTDP_1024x768_60 + (u8) ulRefreshRateIndex);
+		break;
+	case 1152:
+		ModeIdx = ASTDP_1152x864_75;
+		break;
+	case 1280:
+		if (crtc->mode.crtc_vdisplay == 800)
+			ModeIdx = (ASTDP_1280x800_60_RB - (u8) ulRefreshRateIndex);
+		else		// 1024
+			ModeIdx = (ASTDP_1280x1024_60 + (u8) ulRefreshRateIndex);
+		break;
+	case 1360:
+	case 1366:
+		ModeIdx = ASTDP_1366x768_60;
+		break;
+	case 1440:
+		ModeIdx = (ASTDP_1440x900_60_RB - (u8) ulRefreshRateIndex);
+		break;
+	case 1600:
+		if (crtc->mode.crtc_vdisplay == 900)
+			ModeIdx = (ASTDP_1600x900_60_RB - (u8) ulRefreshRateIndex);
+		else		//1200
+			ModeIdx = ASTDP_1600x1200_60;
+		break;
+	case 1680:
+		ModeIdx = (ASTDP_1680x1050_60_RB - (u8) ulRefreshRateIndex);
+		break;
+	case 1920:
+		if (crtc->mode.crtc_vdisplay == 1080)
+			ModeIdx = ASTDP_1920x1080_60;
+		else		//1200
+			ModeIdx = ASTDP_1920x1200_60;
+		break;
+	default:
+		return;
+	}
+
+	/*
+	 * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp)
+	 * CRE1[7:0]: MISC1 (default: 0x00)
+	 * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50)
+	 */
+	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE0, (u8) ~ASTDP_CLEAR_MASK,
+				ASTDP_MISC0_24bpp);
+	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE1, (u8) ~ASTDP_CLEAR_MASK, ASTDP_MISC1);
+	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE2, (u8) ~ASTDP_CLEAR_MASK, ModeIdx);
+}
diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
index 00bfa41ff..799828503 100644
--- a/drivers/gpu/drm/ast/ast_drv.h
+++ b/drivers/gpu/drm/ast/ast_drv.h
@@ -71,6 +71,7 @@ enum ast_tx_chip {
 	AST_TX_SIL164,
 	AST_TX_ITE66121,
 	AST_TX_DP501,
+	AST_TX_ASTDP,
 };

 #define AST_DRAM_512Mx16 0
@@ -175,6 +176,9 @@ struct ast_private {
 	u8 dp501_maxclk;
 	u8 *dp501_fw_addr;
 	const struct firmware *dp501_fw;	/* dp501 fw */
+
+    // ASTDP
+	u8 ASTDP_State;
 };

 static inline struct ast_private *to_ast_private(struct drm_device *dev)
@@ -336,10 +340,123 @@ int ast_mode_config_init(struct ast_private *ast);
 #define AST_DP501_EDID_DATA	0xf020

 /* Define for Soc scratched reg */
+#define COPROCESSOR_LAUNCH			BIT(5)
+
+#define TX_TYPE_MASK				GENMASK(3, 1)
+#define NO_TX						(0 << 1)
+#define ITE66121_VBIOS_TX			(1 << 1)
+#define SI164_VBIOS_TX				(2 << 1)
+#define CH7003_VBIOS_TX			(3 << 1)
+#define DP501_VBIOS_TX				(4 << 1)
+#define ANX9807_VBIOS_TX			(5 << 1)
+#define TX_FW_EMBEDDED_FW_TX		(6 << 1)
+#define ASTDP_DPMCU_TX				(7 << 1)
+
 #define AST_VRAM_INIT_STATUS_MASK	GENMASK(7, 6)
 //#define AST_VRAM_INIT_BY_BMC		BIT(7)
 //#define AST_VRAM_INIT_READY		BIT(6)

+/* Define for Soc scratched reg used on ASTDP */
+#define AST_DP_PHY_SLEEP			BIT(4)
+#define AST_DP_VIDEO_ENABLE		BIT(0)
+
+#define AST_DP_POWER_ON			true
+#define AST_DP_POWER_OFF			false
+
+/*
+ * CRD1[b5]: DP MCU FW is executing
+ * CRDC[b0]: DP link success
+ * CRDF[b0]: DP HPD
+ * CRE5[b0]: Host reading EDID process is done
+ */
+#define ASTDP_MCU_FW_EXECUTING			BIT(5)
+#define ASTDP_LINK_SUCCESS				BIT(0)
+#define ASTDP_HPD						BIT(0)
+#define ASTDP_HOST_EDID_READ_DONE		BIT(0)
+#define ASTDP_HOST_EDID_READ_DONE_MASK	GENMASK(0, 0)
+
+/*
+ * CRB8[b1]: Enable VSYNC off
+ * CRB8[b0]: Enable HSYNC off
+ */
+#define AST_DPMS_VSYNC_OFF				BIT(1)
+#define AST_DPMS_HSYNC_OFF				BIT(0)
+
+/*
+ * CRDF[b4]: Mirror of AST_DP_VIDEO_ENABLE
+ * Precondition:	A. ~AST_DP_PHY_SLEEP  &&
+ *			B. DP_HPD &&
+ *			C. DP_LINK_SUCCESS
+ */
+#define ASTDP_MIRROR_VIDEO_ENABLE		BIT(4)
+
+#define ASTDP_EDID_READ_POINTER_MASK	GENMASK(7, 0)
+#define ASTDP_EDID_VALID_FLAG_MASK		GENMASK(0, 0)
+#define ASTDP_EDID_READ_DATA_MASK		GENMASK(7, 0)
+
+/*
+ * Display Transmittor Type:
+ */
+#define TX_TYPE_MASK				GENMASK(3, 1)
+#define NO_TX						(0 << 1)
+#define ITE66121_VBIOS_TX			(1 << 1)
+#define SI164_VBIOS_TX				(2 << 1)
+#define CH7003_VBIOS_TX			(3 << 1)
+#define DP501_VBIOS_TX				(4 << 1)
+#define ANX9807_VBIOS_TX			(5 << 1)
+#define TX_FW_EMBEDDED_FW_TX		(6 << 1)
+#define ASTDP_DPMCU_TX				(7 << 1)
+
+/*
+ * ASTDP setmode registers:
+ * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp)
+ * CRE1[7:0]: MISC1 (default: 0x00)
+ * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50)
+ */
+#define ASTDP_MISC0_24bpp			BIT(5)
+#define ASTDP_MISC1				0
+#define ASTDP_CLEAR_MASK			GENMASK(7, 0)
+
+/*
+ * ASTDP resoultion table:
+ * EX:	ASTDP_A_B_C:
+ *		A: Resolution
+ *		B: Refresh Rate
+ *		C: Misc information, such as CVT, Reduce Blanked
+ */
+#define ASTDP_640x480_60		0x00
+#define ASTDP_640x480_72		0x01
+#define ASTDP_640x480_75		0x02
+#define ASTDP_640x480_85		0x03
+#define ASTDP_800x600_56		0x04
+#define ASTDP_800x600_60		0x05
+#define ASTDP_800x600_72		0x06
+#define ASTDP_800x600_75		0x07
+#define ASTDP_800x600_85		0x08
+#define ASTDP_1024x768_60		0x09
+#define ASTDP_1024x768_70		0x0A
+#define ASTDP_1024x768_75		0x0B
+#define ASTDP_1024x768_85		0x0C
+#define ASTDP_1280x1024_60		0x0D
+#define ASTDP_1280x1024_75		0x0E
+#define ASTDP_1280x1024_85		0x0F
+#define ASTDP_1600x1200_60		0x10
+#define ASTDP_320x240_60		0x11
+#define ASTDP_400x300_60		0x12
+#define ASTDP_512x384_60		0x13
+#define ASTDP_1920x1200_60		0x14
+#define ASTDP_1920x1080_60		0x15
+#define ASTDP_1280x800_60		0x16
+#define ASTDP_1280x800_60_RB	0x17
+#define ASTDP_1440x900_60		0x18
+#define ASTDP_1440x900_60_RB	0x19
+#define ASTDP_1680x1050_60		0x1A
+#define ASTDP_1680x1050_60_RB	0x1B
+#define ASTDP_1600x900_60		0x1C
+#define ASTDP_1600x900_60_RB	0x1D
+#define ASTDP_1366x768_60		0x1E
+#define ASTDP_1152x864_75		0x1F
+
 int ast_mm_init(struct ast_private *ast);

 /* ast post */
@@ -360,4 +477,14 @@ void ast_init_3rdtx(struct drm_device *dev);
 /* ast_i2c.c */
 struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev);

+/* aspeed DP */
+#define DPControlPower
+bool ast_dp_read_edid(struct drm_device *dev, u8 *ediddata);
+bool ast_dp_launch(struct drm_device *dev, u8 bPower);
+#ifdef DPControlPower
+void ast_dp_PowerOnOff(struct drm_device *dev, u8 Mode);
+#endif
+void ast_dp_SetOnOff(struct drm_device *dev, u8 Mode);
+void ast_dp_SetOutput(struct drm_crtc *crtc, struct ast_vbios_mode_info *vbios_mode);
+
 #endif
diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c
index 79a361867..9f25fa2c8 100644
--- a/drivers/gpu/drm/ast/ast_main.c
+++ b/drivers/gpu/drm/ast/ast_main.c
@@ -230,7 +230,7 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
 			ast->tx_chip_type = AST_TX_SIL164;
 	}

-	if ((ast->chip == AST2300) || (ast->chip == AST2400)) {
+	if ((ast->chip == AST2300) || (ast->chip == AST2400) || (ast->chip == AST2500)) {
 		/*
 		 * On AST2300 and 2400, look the configuration set by the SoC in
 		 * the SOC scratch register #1 bits 11:8 (interestingly marked
@@ -254,7 +254,8 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
 		case 0x0c:
 			ast->tx_chip_type = AST_TX_DP501;
 		}
-	}
+	} else if (ast->chip == AST2600)
+		ast_dp_launch(&ast->base, 0);

 	/* Print stuff for diagnostic purposes */
 	switch(ast->tx_chip_type) {
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index 44c2aafcb..1c7a57a03 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -984,21 +984,45 @@ static int ast_cursor_plane_init(struct ast_private *ast)
 static void ast_crtc_dpms(struct drm_crtc *crtc, int mode)
 {
 	struct ast_private *ast = to_ast_private(crtc->dev);
+	u8 ch = AST_DPMS_VSYNC_OFF | AST_DPMS_HSYNC_OFF;

 	/* TODO: Maybe control display signal generation with
 	 *       Sync Enable (bit CR17.7).
 	 */
 	switch (mode) {
 	case DRM_MODE_DPMS_ON:
-	case DRM_MODE_DPMS_STANDBY:
-	case DRM_MODE_DPMS_SUSPEND:
+		ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT,  0x01, 0xdf, 0);
+		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, 0);
 		if (ast->tx_chip_type == AST_TX_DP501)
 			ast_set_dp501_video_output(crtc->dev, 1);
+
+		if (ast->tx_chip_type == AST_TX_ASTDP) {
+#ifdef DPControlPower
+			ast_dp_PowerOnOff(crtc->dev, AST_DP_POWER_ON);
+#endif
+			ast_wait_for_vretrace(ast);
+			ast_dp_SetOnOff(crtc->dev, 1);
+		}
+
+		ast_crtc_load_lut(ast, crtc);
 		break;
+	case DRM_MODE_DPMS_STANDBY:
+	case DRM_MODE_DPMS_SUSPEND:
 	case DRM_MODE_DPMS_OFF:
+		ch = mode;
 		if (ast->tx_chip_type == AST_TX_DP501)
 			ast_set_dp501_video_output(crtc->dev, 0);
 		break;
+
+		if (ast->tx_chip_type == AST_TX_ASTDP) {
+			ast_dp_SetOnOff(crtc->dev, 0);
+#ifdef DPControlPower
+			ast_dp_PowerOnOff(crtc->dev, AST_DP_POWER_OFF);
+#endif
+		}
+
+		ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT,  0x01, 0xdf, 0x20);
+		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, ch);
 	}
 }

@@ -1041,6 +1065,7 @@ ast_crtc_helper_atomic_flush(struct drm_crtc *crtc,
 	struct ast_private *ast = to_ast_private(crtc->dev);
 	struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
 	struct ast_crtc_state *old_ast_crtc_state = to_ast_crtc_state(old_crtc_state);
+	struct ast_vbios_mode_info *vbios_mode_info = &ast_crtc_state->vbios_mode_info;

 	/*
 	 * The gamma LUT has to be reloaded after changing the primary
@@ -1048,6 +1073,10 @@ ast_crtc_helper_atomic_flush(struct drm_crtc *crtc,
 	 */
 	if (old_ast_crtc_state->format != ast_crtc_state->format)
 		ast_crtc_load_lut(ast, crtc);
+
+	//Set Aspeed Display-Port
+	if (ast->tx_chip_type == AST_TX_ASTDP)
+		ast_dp_SetOutput(crtc, vbios_mode_info);
 }

 static void
@@ -1222,6 +1251,14 @@ static int ast_get_modes(struct drm_connector *connector)
 			ast->dp501_maxclk = ast_get_dp501_max_clk(connector->dev);
 		else
 			kfree(edid);
+	} else if (ast->tx_chip_type == AST_TX_ASTDP) {
+		edid = kmalloc(128, GFP_KERNEL);
+		if (!edid)
+			return -ENOMEM;
+
+		flags = ast_dp_read_edid(connector->dev, (u8 *)edid);
+		if (!flags)
+			kfree(edid);
 	}
 	if (!flags && ast_connector->i2c)
 		edid = drm_get_edid(connector, &ast_connector->i2c->adapter);
@@ -1256,7 +1293,7 @@ static enum drm_mode_status ast_mode_valid(struct drm_connector *connector,

 		if ((ast->chip == AST2100) || (ast->chip == AST2200) ||
 		    (ast->chip == AST2300) || (ast->chip == AST2400) ||
-		    (ast->chip == AST2500)) {
+		    (ast->chip == AST2500) || (ast->chip == AST2600)) {
 			if ((mode->hdisplay == 1920) && (mode->vdisplay == 1080))
 				return MODE_OK;

@@ -1378,7 +1415,8 @@ int ast_mode_config_init(struct ast_private *ast)
 	    ast->chip == AST2200 ||
 	    ast->chip == AST2300 ||
 	    ast->chip == AST2400 ||
-	    ast->chip == AST2500) {
+	    ast->chip == AST2500 ||
+	    ast->chip == AST2600) {
 		dev->mode_config.max_width = 1920;
 		dev->mode_config.max_height = 2048;
 	} else {
diff --git a/drivers/gpu/drm/ast/ast_post.c b/drivers/gpu/drm/ast/ast_post.c
index b5d92f652..0aa9cf0fb 100644
--- a/drivers/gpu/drm/ast/ast_post.c
+++ b/drivers/gpu/drm/ast/ast_post.c
@@ -379,7 +379,9 @@ void ast_post_gpu(struct drm_device *dev)
 	ast_enable_mmio(dev);
 	ast_set_def_ext_reg(dev);

-	if (ast->config_mode == ast_use_p2a) {
+	if (ast->chip == AST2600) {
+		ast_dp_launch(dev, 1);
+	} else if (ast->config_mode == ast_use_p2a) {
 		if (ast->chip == AST2500)
 			ast_post_chip_2500(dev);
 		else if (ast->chip == AST2300 || ast->chip == AST2400)
--
2.27.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH] drm/ast: fix semicolon.cocci warnings
  2021-11-22 10:36 [PATCH] drm/ast: Create the driver for ASPEED proprietory Display-Port KuoHsiang Chou
                   ` (2 preceding siblings ...)
  2021-12-03  6:31 ` Kuo-Hsiang Chou
@ 2022-01-01 19:41 ` kernel test robot
  2022-01-01 19:51 ` [PATCH] drm/ast: Create the driver for ASPEED proprietory Display-Port kernel test robot
  4 siblings, 0 replies; 21+ messages in thread
From: kernel test robot @ 2022-01-01 19:41 UTC (permalink / raw)
  To: KuoHsiang Chou, tzimmermann, dri-devel, linux-kernel
  Cc: kbuild-all, airlied, airlied, daniel, jenmin_yuan,
	kuohsiang_chou, arc_sung, tommy_huang

From: kernel test robot <lkp@intel.com>

drivers/gpu/drm/ast/ast_dp.c:166:3-4: Unneeded semicolon


 Remove unneeded semicolon.

Generated by: scripts/coccinelle/misc/semicolon.cocci

CC: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com>
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: kernel test robot <lkp@intel.com>
---

url:    https://github.com/0day-ci/linux/commits/KuoHsiang-Chou/drm-ast-Create-the-driver-for-ASPEED-proprietory-Display-Port/20211122-183830
base:   git://anongit.freedesktop.org/drm/drm drm-next
:::::: branch date: 6 weeks ago
:::::: commit date: 6 weeks ago

 ast_dp.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/drivers/gpu/drm/ast/ast_dp.c
+++ b/drivers/gpu/drm/ast/ast_dp.c
@@ -163,7 +163,7 @@ bool ast_dp_launch(struct drm_device *de
 				bDPExecute = 0;
 				break;
 			}
-		};
+		}
 
 		if (bDPExecute)
 			ast->tx_chip_type = AST_TX_ASTDP;

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH] drm/ast: Create the driver for ASPEED proprietory Display-Port
  2021-11-22 10:36 [PATCH] drm/ast: Create the driver for ASPEED proprietory Display-Port KuoHsiang Chou
                   ` (3 preceding siblings ...)
  2022-01-01 19:41 ` [PATCH] drm/ast: fix semicolon.cocci warnings kernel test robot
@ 2022-01-01 19:51 ` kernel test robot
  2022-01-04  8:50   ` [PATCH v3] " KuoHsiang Chou
  4 siblings, 1 reply; 21+ messages in thread
From: kernel test robot @ 2022-01-01 19:51 UTC (permalink / raw)
  To: KuoHsiang Chou, tzimmermann, dri-devel, linux-kernel
  Cc: kbuild-all, airlied, airlied, daniel, jenmin_yuan,
	kuohsiang_chou, arc_sung, tommy_huang

Hi KuoHsiang,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on drm/drm-next]
[also build test WARNING on tegra-drm/drm/tegra/for-next v5.16-rc7]
[cannot apply to drm-intel/for-linux-next drm-tip/drm-tip drm-exynos/exynos-drm-next airlied/drm-next next-20211224]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/KuoHsiang-Chou/drm-ast-Create-the-driver-for-ASPEED-proprietory-Display-Port/20211122-183830
base:   git://anongit.freedesktop.org/drm/drm drm-next
config: i386-randconfig-c021-20211123 (https://download.01.org/0day-ci/archive/20220102/202201020329.lEcno4eh-lkp@intel.com/config)
compiler: gcc-9 (Debian 9.3.0-22) 9.3.0

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>


cocci warnings: (new ones prefixed by >>)
>> drivers/gpu/drm/ast/ast_dp.c:166:3-4: Unneeded semicolon

Please review and possibly fold the followup patch.

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v3] drm/ast: Create the driver for ASPEED proprietory Display-Port
  2022-01-01 19:51 ` [PATCH] drm/ast: Create the driver for ASPEED proprietory Display-Port kernel test robot
@ 2022-01-04  8:50   ` KuoHsiang Chou
  2022-01-12 15:04     ` Thomas Zimmermann
  0 siblings, 1 reply; 21+ messages in thread
From: KuoHsiang Chou @ 2022-01-04  8:50 UTC (permalink / raw)
  To: tzimmermann, dri-devel, linux-kernel
  Cc: airlied, airlied, daniel, kuohsiang_chou, arc_sung, tommy_huang,
	brandon_chen, hungju_huang, luke_chen, kernel test robot

V1:
1. The MCU FW controling ASPEED DP is loaded by BMC boot loader.
2. Driver starts after CR[3:1] == 111b that indicates Tx is ASTDP,
   and CRD1[5] has been asserted by BMVC boot loader.
3. EDID is prioritized by DP monitor.
4. DP's EDID has high priority to decide resolution supporting.

V2:
Modules description:
1. ASTDP (ASPEED DisplayPort) is controlled by dedicated
   AST-MCU (ASPEED propriatary MCU).
2. MCU is looping in charged of HPD, Read EDID, Link Training with
   DP sink.
3. ASTDP and AST-MUC reside in BMC (Baseboard Management controller)
   addressing-space.
4. ASPEED DRM driver requests MCU to get HPD and EDID by CR-scratched
   register.

Booting sequence:
1. Check if TX is ASTDP					// ast_dp_launch()
2. Check if DP-MCU FW has loaded					// ast_dp_launch()
3. Read EDID					// ast_dp_read_edid()
4. Resolution switch					// ast_dp_SetOutput()

V3:
1. Remove unneeded semicolon.
2. Apply to git://anongit.freedesktop.org/drm/drm, instead of
   git://anongit.freedesktop.org/drm/drm-misc
3. Resolve auto build test WARNINGs on V1 patch.

Signed-off-by: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com>
Reported-by: kernel test robot <lkp@intel.com>
---
 drivers/gpu/drm/ast/Makefile   |   2 +-
 drivers/gpu/drm/ast/ast_dp.c   | 292 +++++++++++++++++++++++++++++++++
 drivers/gpu/drm/ast/ast_drv.h  | 127 ++++++++++++++
 drivers/gpu/drm/ast/ast_main.c |   5 +-
 drivers/gpu/drm/ast/ast_mode.c |  46 +++++-
 drivers/gpu/drm/ast/ast_post.c |   4 +-
 6 files changed, 468 insertions(+), 8 deletions(-)
 create mode 100644 drivers/gpu/drm/ast/ast_dp.c

diff --git a/drivers/gpu/drm/ast/Makefile b/drivers/gpu/drm/ast/Makefile
index 21f71160b..5a53ce51f 100644
--- a/drivers/gpu/drm/ast/Makefile
+++ b/drivers/gpu/drm/ast/Makefile
@@ -3,6 +3,6 @@
 # Makefile for the drm device driver.  This driver provides support for the
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.

-ast-y := ast_drv.o ast_i2c.o ast_main.o ast_mm.o ast_mode.o ast_post.o ast_dp501.o
+ast-y := ast_drv.o ast_i2c.o ast_main.o ast_mm.o ast_mode.o ast_post.o ast_dp501.o ast_dp.o

 obj-$(CONFIG_DRM_AST) := ast.o
diff --git a/drivers/gpu/drm/ast/ast_dp.c b/drivers/gpu/drm/ast/ast_dp.c
new file mode 100644
index 000000000..1daa25d92
--- /dev/null
+++ b/drivers/gpu/drm/ast/ast_dp.c
@@ -0,0 +1,292 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2021, ASPEED Technology Inc.
+// Authors: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com>
+
+#include <linux/firmware.h>
+#include <linux/delay.h>
+#include <drm/drm_print.h>
+#include "ast_drv.h"
+
+bool ast_dp_read_edid(struct drm_device *dev, u8 *ediddata)
+{
+	struct ast_private *ast = to_ast_private(dev);
+	u8 i = 0, j = 0;
+
+#ifdef DPControlPower
+	u8 bDPState_Change = false;
+
+	// Check DP power off or not.
+	if (ast->ASTDP_State & AST_DP_PHY_SLEEP) {
+		// DP power on
+		ast_dp_PowerOnOff(dev, AST_DP_POWER_ON);
+		bDPState_Change = true;
+	}
+#endif
+
+	/*
+	 * CRD1[b5]: DP MCU FW is executing
+	 * CRDC[b0]: DP link success
+	 * CRDF[b0]: DP HPD
+	 * CRE5[b0]: Host reading EDID process is done
+	 */
+	if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, ASTDP_MCU_FW_EXECUTING) &&
+		ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, ASTDP_LINK_SUCCESS) &&
+		ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD) &&
+		ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
+								ASTDP_HOST_EDID_READ_DONE_MASK))) {
+#ifdef DPControlPower
+		// Set back power off
+		if (bDPState_Change)
+			ast_dp_PowerOnOff(dev, AST_DP_POWER_OFF);
+#endif
+		return false;
+	}
+
+	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
+							0x00);
+
+	for (i = 0; i < 32; i++) {
+		/*
+		 * CRE4[7:0]: Read-Pointer for EDID (Unit: 4bytes); valid range: 0~64
+		 */
+		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE4,
+					(u8) ~ASTDP_EDID_READ_POINTER_MASK, (u8) i);
+		j = 0;
+
+		/*
+		 * CRD7[b0]: valid flag for EDID
+		 * CRD6[b0]: mirror read pointer for EDID
+		 */
+		while ((ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD7,
+				ASTDP_EDID_VALID_FLAG_MASK) != 0x01) ||
+			(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD6,
+						ASTDP_EDID_READ_POINTER_MASK) != i)) {
+			mdelay(j+1);
+
+			if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1,
+							ASTDP_MCU_FW_EXECUTING) &&
+				ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC,
+							ASTDP_LINK_SUCCESS) &&
+				ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD))) {
+				ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
+							(u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
+							ASTDP_HOST_EDID_READ_DONE);
+				return false;
+			}
+
+			j++;
+			if (j > 200) {
+				ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
+							(u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
+							ASTDP_HOST_EDID_READ_DONE);
+				return false;
+			}
+		}
+
+		*(ediddata) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT,
+							0xD8, ASTDP_EDID_READ_DATA_MASK);
+		*(ediddata + 1) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD9,
+								ASTDP_EDID_READ_DATA_MASK);
+		*(ediddata + 2) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDA,
+								ASTDP_EDID_READ_DATA_MASK);
+		*(ediddata + 3) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDB,
+								ASTDP_EDID_READ_DATA_MASK);
+
+		if (i == 31) {
+			/*
+			 * For 128-bytes EDID_1.3,
+			 * 1. Add the value of Bytes-126 to Bytes-127.
+			 *		The Bytes-127 is Checksum. Sum of all 128bytes should
+			 *		equal 0	(mod 256).
+			 * 2. Modify Bytes-126 to be 0.
+			 *		The Bytes-126 indicates the Number of extensions to
+			 *		follow. 0 represents noextensions.
+			 */
+			*(ediddata + 3) = *(ediddata + 3) + *(ediddata + 2);
+			*(ediddata + 2) = 0;
+		}
+
+		ediddata += 4;
+	}
+
+	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
+							ASTDP_HOST_EDID_READ_DONE);
+
+#ifdef DPControlPower
+	// Set back power off
+	if (bDPState_Change)
+		ast_dp_PowerOnOff(dev, AST_DP_POWER_OFF);
+#endif
+
+	return true;
+}
+
+/*
+ * Launch Aspeed DP
+ */
+bool ast_dp_launch(struct drm_device *dev, u8 bPower)
+{
+	u32 i = 0, j = 0, WaitCount = 1;
+	u8 bDPTX = 0;
+	u8 bDPExecute = 1;
+
+	struct ast_private *ast = to_ast_private(dev);
+	// S3 come back, need more time to wait BMC ready.
+	if (bPower)
+		WaitCount = 300;
+
+	// Fill
+	ast->tx_chip_type = AST_TX_NONE;
+
+	// Wait total count by different condition.
+	// This is a temp solution for DP check
+	for (j = 0; j < WaitCount; j++) {
+		bDPTX = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, TX_TYPE_MASK);
+
+		if (bDPTX)
+			break;
+
+		msleep(100);
+	}
+
+	// 0xE : ASTDP with DPMCU FW handling
+	if (bDPTX == ASTDP_DPMCU_TX) {
+		// Wait one second then timeout.
+		i = 0;
+
+		while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, COPROCESSOR_LAUNCH) !=
+			COPROCESSOR_LAUNCH) {
+			i++;
+			// wait 100 ms
+			msleep(100);
+
+			if (i >= 10) {
+				// DP would not be ready.
+				bDPExecute = 0;
+				break;
+			}
+		}
+
+		if (bDPExecute)
+			ast->tx_chip_type = AST_TX_ASTDP;
+	}
+
+	return true;
+}
+
+#ifdef DPControlPower
+
+void ast_dp_PowerOnOff(struct drm_device *dev, u8 Mode)
+{
+	struct ast_private *ast = to_ast_private(dev);
+	// Read and Turn off DP PHY sleep
+	u8 bE3 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, AST_DP_VIDEO_ENABLE);
+
+	// Turn on DP PHY sleep
+	if (!Mode)
+		bE3 |= AST_DP_PHY_SLEEP;
+
+	// DP Power on/off
+	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, (u8) ~AST_DP_PHY_SLEEP, bE3);
+
+	// Save ASTDP power state
+	ast->ASTDP_State = bE3;
+}
+
+#endif
+
+void ast_dp_SetOnOff(struct drm_device *dev, u8 Mode)
+{
+	struct ast_private *ast = to_ast_private(dev);
+
+	// Video On/Off
+	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, (u8) ~AST_DP_VIDEO_ENABLE, Mode);
+
+	// Save ASTDP power state
+	ast->ASTDP_State = Mode;
+
+	// If DP plug in and link successful then check video on / off status
+	if (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, ASTDP_LINK_SUCCESS) &&
+		ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD)) {
+		Mode <<= 4;
+		while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF,
+						ASTDP_MIRROR_VIDEO_ENABLE) != Mode) {
+			// wait 1 ms
+			mdelay(1);
+		}
+	}
+}
+
+void ast_dp_SetOutput(struct drm_crtc *crtc, struct ast_vbios_mode_info *vbios_mode)
+{
+	struct ast_private *ast = to_ast_private(crtc->dev);
+
+	u32 ulRefreshRateIndex;
+	u8 ModeIdx;
+
+	ulRefreshRateIndex = vbios_mode->enh_table->refresh_rate_index - 1;
+
+	switch (crtc->mode.crtc_hdisplay) {
+	case 320:
+		ModeIdx = ASTDP_320x240_60;
+		break;
+	case 400:
+		ModeIdx = ASTDP_400x300_60;
+		break;
+	case 512:
+		ModeIdx = ASTDP_512x384_60;
+		break;
+	case 640:
+		ModeIdx = (ASTDP_640x480_60 + (u8) ulRefreshRateIndex);
+		break;
+	case 800:
+		ModeIdx = (ASTDP_800x600_56 + (u8) ulRefreshRateIndex);
+		break;
+	case 1024:
+		ModeIdx = (ASTDP_1024x768_60 + (u8) ulRefreshRateIndex);
+		break;
+	case 1152:
+		ModeIdx = ASTDP_1152x864_75;
+		break;
+	case 1280:
+		if (crtc->mode.crtc_vdisplay == 800)
+			ModeIdx = (ASTDP_1280x800_60_RB - (u8) ulRefreshRateIndex);
+		else		// 1024
+			ModeIdx = (ASTDP_1280x1024_60 + (u8) ulRefreshRateIndex);
+		break;
+	case 1360:
+	case 1366:
+		ModeIdx = ASTDP_1366x768_60;
+		break;
+	case 1440:
+		ModeIdx = (ASTDP_1440x900_60_RB - (u8) ulRefreshRateIndex);
+		break;
+	case 1600:
+		if (crtc->mode.crtc_vdisplay == 900)
+			ModeIdx = (ASTDP_1600x900_60_RB - (u8) ulRefreshRateIndex);
+		else		//1200
+			ModeIdx = ASTDP_1600x1200_60;
+		break;
+	case 1680:
+		ModeIdx = (ASTDP_1680x1050_60_RB - (u8) ulRefreshRateIndex);
+		break;
+	case 1920:
+		if (crtc->mode.crtc_vdisplay == 1080)
+			ModeIdx = ASTDP_1920x1080_60;
+		else		//1200
+			ModeIdx = ASTDP_1920x1200_60;
+		break;
+	default:
+		return;
+	}
+
+	/*
+	 * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp)
+	 * CRE1[7:0]: MISC1 (default: 0x00)
+	 * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50)
+	 */
+	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE0, (u8) ~ASTDP_CLEAR_MASK,
+				ASTDP_MISC0_24bpp);
+	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE1, (u8) ~ASTDP_CLEAR_MASK, ASTDP_MISC1);
+	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE2, (u8) ~ASTDP_CLEAR_MASK, ModeIdx);
+}
diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
index 00bfa41ff..799828503 100644
--- a/drivers/gpu/drm/ast/ast_drv.h
+++ b/drivers/gpu/drm/ast/ast_drv.h
@@ -71,6 +71,7 @@ enum ast_tx_chip {
 	AST_TX_SIL164,
 	AST_TX_ITE66121,
 	AST_TX_DP501,
+	AST_TX_ASTDP,
 };

 #define AST_DRAM_512Mx16 0
@@ -175,6 +176,9 @@ struct ast_private {
 	u8 dp501_maxclk;
 	u8 *dp501_fw_addr;
 	const struct firmware *dp501_fw;	/* dp501 fw */
+
+    // ASTDP
+	u8 ASTDP_State;
 };

 static inline struct ast_private *to_ast_private(struct drm_device *dev)
@@ -336,10 +340,123 @@ int ast_mode_config_init(struct ast_private *ast);
 #define AST_DP501_EDID_DATA	0xf020

 /* Define for Soc scratched reg */
+#define COPROCESSOR_LAUNCH			BIT(5)
+
+#define TX_TYPE_MASK				GENMASK(3, 1)
+#define NO_TX						(0 << 1)
+#define ITE66121_VBIOS_TX			(1 << 1)
+#define SI164_VBIOS_TX				(2 << 1)
+#define CH7003_VBIOS_TX			(3 << 1)
+#define DP501_VBIOS_TX				(4 << 1)
+#define ANX9807_VBIOS_TX			(5 << 1)
+#define TX_FW_EMBEDDED_FW_TX		(6 << 1)
+#define ASTDP_DPMCU_TX				(7 << 1)
+
 #define AST_VRAM_INIT_STATUS_MASK	GENMASK(7, 6)
 //#define AST_VRAM_INIT_BY_BMC		BIT(7)
 //#define AST_VRAM_INIT_READY		BIT(6)

+/* Define for Soc scratched reg used on ASTDP */
+#define AST_DP_PHY_SLEEP			BIT(4)
+#define AST_DP_VIDEO_ENABLE		BIT(0)
+
+#define AST_DP_POWER_ON			true
+#define AST_DP_POWER_OFF			false
+
+/*
+ * CRD1[b5]: DP MCU FW is executing
+ * CRDC[b0]: DP link success
+ * CRDF[b0]: DP HPD
+ * CRE5[b0]: Host reading EDID process is done
+ */
+#define ASTDP_MCU_FW_EXECUTING			BIT(5)
+#define ASTDP_LINK_SUCCESS				BIT(0)
+#define ASTDP_HPD						BIT(0)
+#define ASTDP_HOST_EDID_READ_DONE		BIT(0)
+#define ASTDP_HOST_EDID_READ_DONE_MASK	GENMASK(0, 0)
+
+/*
+ * CRB8[b1]: Enable VSYNC off
+ * CRB8[b0]: Enable HSYNC off
+ */
+#define AST_DPMS_VSYNC_OFF				BIT(1)
+#define AST_DPMS_HSYNC_OFF				BIT(0)
+
+/*
+ * CRDF[b4]: Mirror of AST_DP_VIDEO_ENABLE
+ * Precondition:	A. ~AST_DP_PHY_SLEEP  &&
+ *			B. DP_HPD &&
+ *			C. DP_LINK_SUCCESS
+ */
+#define ASTDP_MIRROR_VIDEO_ENABLE		BIT(4)
+
+#define ASTDP_EDID_READ_POINTER_MASK	GENMASK(7, 0)
+#define ASTDP_EDID_VALID_FLAG_MASK		GENMASK(0, 0)
+#define ASTDP_EDID_READ_DATA_MASK		GENMASK(7, 0)
+
+/*
+ * Display Transmittor Type:
+ */
+#define TX_TYPE_MASK				GENMASK(3, 1)
+#define NO_TX						(0 << 1)
+#define ITE66121_VBIOS_TX			(1 << 1)
+#define SI164_VBIOS_TX				(2 << 1)
+#define CH7003_VBIOS_TX			(3 << 1)
+#define DP501_VBIOS_TX				(4 << 1)
+#define ANX9807_VBIOS_TX			(5 << 1)
+#define TX_FW_EMBEDDED_FW_TX		(6 << 1)
+#define ASTDP_DPMCU_TX				(7 << 1)
+
+/*
+ * ASTDP setmode registers:
+ * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp)
+ * CRE1[7:0]: MISC1 (default: 0x00)
+ * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50)
+ */
+#define ASTDP_MISC0_24bpp			BIT(5)
+#define ASTDP_MISC1				0
+#define ASTDP_CLEAR_MASK			GENMASK(7, 0)
+
+/*
+ * ASTDP resoultion table:
+ * EX:	ASTDP_A_B_C:
+ *		A: Resolution
+ *		B: Refresh Rate
+ *		C: Misc information, such as CVT, Reduce Blanked
+ */
+#define ASTDP_640x480_60		0x00
+#define ASTDP_640x480_72		0x01
+#define ASTDP_640x480_75		0x02
+#define ASTDP_640x480_85		0x03
+#define ASTDP_800x600_56		0x04
+#define ASTDP_800x600_60		0x05
+#define ASTDP_800x600_72		0x06
+#define ASTDP_800x600_75		0x07
+#define ASTDP_800x600_85		0x08
+#define ASTDP_1024x768_60		0x09
+#define ASTDP_1024x768_70		0x0A
+#define ASTDP_1024x768_75		0x0B
+#define ASTDP_1024x768_85		0x0C
+#define ASTDP_1280x1024_60		0x0D
+#define ASTDP_1280x1024_75		0x0E
+#define ASTDP_1280x1024_85		0x0F
+#define ASTDP_1600x1200_60		0x10
+#define ASTDP_320x240_60		0x11
+#define ASTDP_400x300_60		0x12
+#define ASTDP_512x384_60		0x13
+#define ASTDP_1920x1200_60		0x14
+#define ASTDP_1920x1080_60		0x15
+#define ASTDP_1280x800_60		0x16
+#define ASTDP_1280x800_60_RB	0x17
+#define ASTDP_1440x900_60		0x18
+#define ASTDP_1440x900_60_RB	0x19
+#define ASTDP_1680x1050_60		0x1A
+#define ASTDP_1680x1050_60_RB	0x1B
+#define ASTDP_1600x900_60		0x1C
+#define ASTDP_1600x900_60_RB	0x1D
+#define ASTDP_1366x768_60		0x1E
+#define ASTDP_1152x864_75		0x1F
+
 int ast_mm_init(struct ast_private *ast);

 /* ast post */
@@ -360,4 +477,14 @@ void ast_init_3rdtx(struct drm_device *dev);
 /* ast_i2c.c */
 struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev);

+/* aspeed DP */
+#define DPControlPower
+bool ast_dp_read_edid(struct drm_device *dev, u8 *ediddata);
+bool ast_dp_launch(struct drm_device *dev, u8 bPower);
+#ifdef DPControlPower
+void ast_dp_PowerOnOff(struct drm_device *dev, u8 Mode);
+#endif
+void ast_dp_SetOnOff(struct drm_device *dev, u8 Mode);
+void ast_dp_SetOutput(struct drm_crtc *crtc, struct ast_vbios_mode_info *vbios_mode);
+
 #endif
diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c
index 79a361867..9f25fa2c8 100644
--- a/drivers/gpu/drm/ast/ast_main.c
+++ b/drivers/gpu/drm/ast/ast_main.c
@@ -230,7 +230,7 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
 			ast->tx_chip_type = AST_TX_SIL164;
 	}

-	if ((ast->chip == AST2300) || (ast->chip == AST2400)) {
+	if ((ast->chip == AST2300) || (ast->chip == AST2400) || (ast->chip == AST2500)) {
 		/*
 		 * On AST2300 and 2400, look the configuration set by the SoC in
 		 * the SOC scratch register #1 bits 11:8 (interestingly marked
@@ -254,7 +254,8 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
 		case 0x0c:
 			ast->tx_chip_type = AST_TX_DP501;
 		}
-	}
+	} else if (ast->chip == AST2600)
+		ast_dp_launch(&ast->base, 0);

 	/* Print stuff for diagnostic purposes */
 	switch(ast->tx_chip_type) {
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index 44c2aafcb..1c7a57a03 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -984,21 +984,45 @@ static int ast_cursor_plane_init(struct ast_private *ast)
 static void ast_crtc_dpms(struct drm_crtc *crtc, int mode)
 {
 	struct ast_private *ast = to_ast_private(crtc->dev);
+	u8 ch = AST_DPMS_VSYNC_OFF | AST_DPMS_HSYNC_OFF;

 	/* TODO: Maybe control display signal generation with
 	 *       Sync Enable (bit CR17.7).
 	 */
 	switch (mode) {
 	case DRM_MODE_DPMS_ON:
-	case DRM_MODE_DPMS_STANDBY:
-	case DRM_MODE_DPMS_SUSPEND:
+		ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT,  0x01, 0xdf, 0);
+		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, 0);
 		if (ast->tx_chip_type == AST_TX_DP501)
 			ast_set_dp501_video_output(crtc->dev, 1);
+
+		if (ast->tx_chip_type == AST_TX_ASTDP) {
+#ifdef DPControlPower
+			ast_dp_PowerOnOff(crtc->dev, AST_DP_POWER_ON);
+#endif
+			ast_wait_for_vretrace(ast);
+			ast_dp_SetOnOff(crtc->dev, 1);
+		}
+
+		ast_crtc_load_lut(ast, crtc);
 		break;
+	case DRM_MODE_DPMS_STANDBY:
+	case DRM_MODE_DPMS_SUSPEND:
 	case DRM_MODE_DPMS_OFF:
+		ch = mode;
 		if (ast->tx_chip_type == AST_TX_DP501)
 			ast_set_dp501_video_output(crtc->dev, 0);
 		break;
+
+		if (ast->tx_chip_type == AST_TX_ASTDP) {
+			ast_dp_SetOnOff(crtc->dev, 0);
+#ifdef DPControlPower
+			ast_dp_PowerOnOff(crtc->dev, AST_DP_POWER_OFF);
+#endif
+		}
+
+		ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT,  0x01, 0xdf, 0x20);
+		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, ch);
 	}
 }

@@ -1041,6 +1065,7 @@ ast_crtc_helper_atomic_flush(struct drm_crtc *crtc,
 	struct ast_private *ast = to_ast_private(crtc->dev);
 	struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
 	struct ast_crtc_state *old_ast_crtc_state = to_ast_crtc_state(old_crtc_state);
+	struct ast_vbios_mode_info *vbios_mode_info = &ast_crtc_state->vbios_mode_info;

 	/*
 	 * The gamma LUT has to be reloaded after changing the primary
@@ -1048,6 +1073,10 @@ ast_crtc_helper_atomic_flush(struct drm_crtc *crtc,
 	 */
 	if (old_ast_crtc_state->format != ast_crtc_state->format)
 		ast_crtc_load_lut(ast, crtc);
+
+	//Set Aspeed Display-Port
+	if (ast->tx_chip_type == AST_TX_ASTDP)
+		ast_dp_SetOutput(crtc, vbios_mode_info);
 }

 static void
@@ -1222,6 +1251,14 @@ static int ast_get_modes(struct drm_connector *connector)
 			ast->dp501_maxclk = ast_get_dp501_max_clk(connector->dev);
 		else
 			kfree(edid);
+	} else if (ast->tx_chip_type == AST_TX_ASTDP) {
+		edid = kmalloc(128, GFP_KERNEL);
+		if (!edid)
+			return -ENOMEM;
+
+		flags = ast_dp_read_edid(connector->dev, (u8 *)edid);
+		if (!flags)
+			kfree(edid);
 	}
 	if (!flags && ast_connector->i2c)
 		edid = drm_get_edid(connector, &ast_connector->i2c->adapter);
@@ -1256,7 +1293,7 @@ static enum drm_mode_status ast_mode_valid(struct drm_connector *connector,

 		if ((ast->chip == AST2100) || (ast->chip == AST2200) ||
 		    (ast->chip == AST2300) || (ast->chip == AST2400) ||
-		    (ast->chip == AST2500)) {
+		    (ast->chip == AST2500) || (ast->chip == AST2600)) {
 			if ((mode->hdisplay == 1920) && (mode->vdisplay == 1080))
 				return MODE_OK;

@@ -1378,7 +1415,8 @@ int ast_mode_config_init(struct ast_private *ast)
 	    ast->chip == AST2200 ||
 	    ast->chip == AST2300 ||
 	    ast->chip == AST2400 ||
-	    ast->chip == AST2500) {
+	    ast->chip == AST2500 ||
+	    ast->chip == AST2600) {
 		dev->mode_config.max_width = 1920;
 		dev->mode_config.max_height = 2048;
 	} else {
diff --git a/drivers/gpu/drm/ast/ast_post.c b/drivers/gpu/drm/ast/ast_post.c
index b5d92f652..0aa9cf0fb 100644
--- a/drivers/gpu/drm/ast/ast_post.c
+++ b/drivers/gpu/drm/ast/ast_post.c
@@ -379,7 +379,9 @@ void ast_post_gpu(struct drm_device *dev)
 	ast_enable_mmio(dev);
 	ast_set_def_ext_reg(dev);

-	if (ast->config_mode == ast_use_p2a) {
+	if (ast->chip == AST2600) {
+		ast_dp_launch(dev, 1);
+	} else if (ast->config_mode == ast_use_p2a) {
 		if (ast->chip == AST2500)
 			ast_post_chip_2500(dev);
 		else if (ast->chip == AST2300 || ast->chip == AST2400)

base-commit: cb6846fbb83b574c85c2a80211b402a6347b60b1
--
2.27.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [PATCH v3] drm/ast: Create the driver for ASPEED proprietory Display-Port
  2022-01-04  8:50   ` [PATCH v3] " KuoHsiang Chou
@ 2022-01-12 15:04     ` Thomas Zimmermann
  2022-04-28  7:56       ` [PATCH v4] " KuoHsiang Chou
  0 siblings, 1 reply; 21+ messages in thread
From: Thomas Zimmermann @ 2022-01-12 15:04 UTC (permalink / raw)
  To: KuoHsiang Chou, dri-devel, linux-kernel
  Cc: kernel test robot, hungju_huang, airlied, brandon_chen,
	tommy_huang, airlied, arc_sung, luke_chen


[-- Attachment #1.1: Type: text/plain, Size: 25295 bytes --]

Hi

Am 04.01.22 um 09:50 schrieb KuoHsiang Chou:
> V1:
> 1. The MCU FW controling ASPEED DP is loaded by BMC boot loader.
> 2. Driver starts after CR[3:1] == 111b that indicates Tx is ASTDP,
>     and CRD1[5] has been asserted by BMVC boot loader.
> 3. EDID is prioritized by DP monitor.
> 4. DP's EDID has high priority to decide resolution supporting.
> 
> V2:
> Modules description:
> 1. ASTDP (ASPEED DisplayPort) is controlled by dedicated
>     AST-MCU (ASPEED propriatary MCU).
> 2. MCU is looping in charged of HPD, Read EDID, Link Training with
>     DP sink.
> 3. ASTDP and AST-MUC reside in BMC (Baseboard Management controller)
>     addressing-space.
> 4. ASPEED DRM driver requests MCU to get HPD and EDID by CR-scratched
>     register.
> 
> Booting sequence:
> 1. Check if TX is ASTDP					// ast_dp_launch()
> 2. Check if DP-MCU FW has loaded					// ast_dp_launch()
> 3. Read EDID					// ast_dp_read_edid()
> 4. Resolution switch					// ast_dp_SetOutput()
> 
> V3:
> 1. Remove unneeded semicolon.
> 2. Apply to git://anongit.freedesktop.org/drm/drm, instead of
>     git://anongit.freedesktop.org/drm/drm-misc
> 3. Resolve auto build test WARNINGs on V1 patch.
> 
> Signed-off-by: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com>
> Reported-by: kernel test robot <lkp@intel.com>
> ---
>   drivers/gpu/drm/ast/Makefile   |   2 +-
>   drivers/gpu/drm/ast/ast_dp.c   | 292 +++++++++++++++++++++++++++++++++
>   drivers/gpu/drm/ast/ast_drv.h  | 127 ++++++++++++++
>   drivers/gpu/drm/ast/ast_main.c |   5 +-
>   drivers/gpu/drm/ast/ast_mode.c |  46 +++++-
>   drivers/gpu/drm/ast/ast_post.c |   4 +-
>   6 files changed, 468 insertions(+), 8 deletions(-)
>   create mode 100644 drivers/gpu/drm/ast/ast_dp.c
> 
> diff --git a/drivers/gpu/drm/ast/Makefile b/drivers/gpu/drm/ast/Makefile
> index 21f71160b..5a53ce51f 100644
> --- a/drivers/gpu/drm/ast/Makefile
> +++ b/drivers/gpu/drm/ast/Makefile
> @@ -3,6 +3,6 @@
>   # Makefile for the drm device driver.  This driver provides support for the
>   # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
> 
> -ast-y := ast_drv.o ast_i2c.o ast_main.o ast_mm.o ast_mode.o ast_post.o ast_dp501.o
> +ast-y := ast_drv.o ast_i2c.o ast_main.o ast_mm.o ast_mode.o ast_post.o ast_dp501.o ast_dp.o
> 
>   obj-$(CONFIG_DRM_AST) := ast.o
> diff --git a/drivers/gpu/drm/ast/ast_dp.c b/drivers/gpu/drm/ast/ast_dp.c
> new file mode 100644
> index 000000000..1daa25d92
> --- /dev/null
> +++ b/drivers/gpu/drm/ast/ast_dp.c
> @@ -0,0 +1,292 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Copyright (c) 2021, ASPEED Technology Inc.
> +// Authors: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com>
> +
> +#include <linux/firmware.h>
> +#include <linux/delay.h>
> +#include <drm/drm_print.h>
> +#include "ast_drv.h"
> +
> +bool ast_dp_read_edid(struct drm_device *dev, u8 *ediddata)
> +{
> +	struct ast_private *ast = to_ast_private(dev);
> +	u8 i = 0, j = 0;
> +
> +#ifdef DPControlPower

This define needs to go away. Here and in all other places. It's always 
enabled anyway. Either keep the enclosed code or remove it.

AFAIU, the DP chips needs to be pwered on to be used. So what exactly 
does this #ifdef protect?


> +	u8 bDPState_Change = false;
> +
> +	// Check DP power off or not.
> +	if (ast->ASTDP_State & AST_DP_PHY_SLEEP) {
> +		// DP power on
> +		ast_dp_PowerOnOff(dev, AST_DP_POWER_ON);
> +		bDPState_Change = true;
> +	}
> +#endif

The TX chip should already be running when ast_dp_read_edid() runs. At 
least put it into the caller.  More generally speaking, the modesetting 
callbacks should handle this somewhere.


> +
> +	/*
> +	 * CRD1[b5]: DP MCU FW is executing
> +	 * CRDC[b0]: DP link success
> +	 * CRDF[b0]: DP HPD
> +	 * CRE5[b0]: Host reading EDID process is done
> +	 */
> +	if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, ASTDP_MCU_FW_EXECUTING) &&
> +		ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, ASTDP_LINK_SUCCESS) &&
> +		ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD) &&
> +		ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
> +								ASTDP_HOST_EDID_READ_DONE_MASK))) {
> +#ifdef DPControlPower
> +		// Set back power off
> +		if (bDPState_Change)
> +			ast_dp_PowerOnOff(dev, AST_DP_POWER_OFF);
> +#endif
> +		return false;
> +	}
> +
> +	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
> +							0x00);
> +
> +	for (i = 0; i < 32; i++) {
> +		/*
> +		 * CRE4[7:0]: Read-Pointer for EDID (Unit: 4bytes); valid range: 0~64
> +		 */
> +		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE4,
> +					(u8) ~ASTDP_EDID_READ_POINTER_MASK, (u8) i);
> +		j = 0;
> +
> +		/*
> +		 * CRD7[b0]: valid flag for EDID
> +		 * CRD6[b0]: mirror read pointer for EDID
> +		 */
> +		while ((ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD7,
> +				ASTDP_EDID_VALID_FLAG_MASK) != 0x01) ||
> +			(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD6,
> +						ASTDP_EDID_READ_POINTER_MASK) != i)) {
> +			mdelay(j+1);

I don't understand 'mdelay(j + 1)'. Delays are getting longer with each 
retry?

> +
> +			if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1,
> +							ASTDP_MCU_FW_EXECUTING) &&
> +				ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC,
> +							ASTDP_LINK_SUCCESS) &&
> +				ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD))) {
> +				ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
> +							(u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
> +							ASTDP_HOST_EDID_READ_DONE);
> +				return false;
> +			}
> +
> +			j++;
> +			if (j > 200) {
> +				ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
> +							(u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
> +							ASTDP_HOST_EDID_READ_DONE);
> +				return false;

Rather than doing a cleanup here, jump out of the for loop (goto out;) 
and use the regular clean-up code. This would also reset the chip's 
power state on errors. The return value of this function would depend on 
the success or failure.

> +			}
> +		}
> +
> +		*(ediddata) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT,
> +							0xD8, ASTDP_EDID_READ_DATA_MASK);
> +		*(ediddata + 1) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD9,
> +								ASTDP_EDID_READ_DATA_MASK);
> +		*(ediddata + 2) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDA,
> +								ASTDP_EDID_READ_DATA_MASK);
> +		*(ediddata + 3) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDB,
> +								ASTDP_EDID_READ_DATA_MASK);
> +
> +		if (i == 31) {
> +			/*
> +			 * For 128-bytes EDID_1.3,
> +			 * 1. Add the value of Bytes-126 to Bytes-127.
> +			 *		The Bytes-127 is Checksum. Sum of all 128bytes should
> +			 *		equal 0	(mod 256).
> +			 * 2. Modify Bytes-126 to be 0.
> +			 *		The Bytes-126 indicates the Number of extensions to
> +			 *		follow. 0 represents noextensions.
> +			 */
> +			*(ediddata + 3) = *(ediddata + 3) + *(ediddata + 2);
> +			*(ediddata + 2) = 0;
> +		}
> +
> +		ediddata += 4;
> +	}
> +
> +	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
> +							ASTDP_HOST_EDID_READ_DONE);
> +
> +#ifdef DPControlPower
> +	// Set back power off
> +	if (bDPState_Change)
> +		ast_dp_PowerOnOff(dev, AST_DP_POWER_OFF);
> +#endif
> +
> +	return true;

Rather than returning a boolean value, it's better style to return 0 on 
success or a negative errno code on failure. If the register operations 
fail, returning -EIO might be appropriate.

> +}
> +
> +/*
> + * Launch Aspeed DP
> + */
> +bool ast_dp_launch(struct drm_device *dev, u8 bPower)
> +{
> +	u32 i = 0, j = 0, WaitCount = 1;
> +	u8 bDPTX = 0;
> +	u8 bDPExecute = 1;
> +
> +	struct ast_private *ast = to_ast_private(dev);
> +	// S3 come back, need more time to wait BMC ready.
> +	if (bPower)
> +		WaitCount = 300;
> +
> +	// Fill
> +	ast->tx_chip_type = AST_TX_NONE;

This needs to be cleared elsewhere. Right now it just interferes with 
other places that set this field.

Ideally, you'd have a test function that detects the TX chip and launch 
functions that starts the detected chip.

> +
> +	// Wait total count by different condition.
> +	// This is a temp solution for DP check
> +	for (j = 0; j < WaitCount; j++) {
> +		bDPTX = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, TX_TYPE_MASK);
> +
> +		if (bDPTX)
> +			break;
> +
> +		msleep(100);
> +	}
> +
> +	// 0xE : ASTDP with DPMCU FW handling
> +	if (bDPTX == ASTDP_DPMCU_TX) {
> +		// Wait one second then timeout.
> +		i = 0;
> +
> +		while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, COPROCESSOR_LAUNCH) !=
> +			COPROCESSOR_LAUNCH) {
> +			i++;
> +			// wait 100 ms
> +			msleep(100);
> +
> +			if (i >= 10) {
> +				// DP would not be ready.
> +				bDPExecute = 0;
> +				break;
> +			}
> +		}
> +
> +		if (bDPExecute)
> +			ast->tx_chip_type = AST_TX_ASTDP;
> +	}
> +
> +	return true;

There's no way this function fails, so no need for a return value. If 
there is a possible error, it should be returned as negative errno code.

> +}
> +
> +#ifdef DPControlPower
> +
> +void ast_dp_PowerOnOff(struct drm_device *dev, u8 Mode)

We don't use CamelCase style. Rather call ths function 
ast_dp_power_on_off(). Same applies to all functions with CamelCase.

Instead of 'u8 Mode', 'bool on' seems appropriate.

> +{
> +	struct ast_private *ast = to_ast_private(dev);
> +	// Read and Turn off DP PHY sleep
> +	u8 bE3 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, AST_DP_VIDEO_ENABLE);
> +
> +	// Turn on DP PHY sleep
> +	if (!Mode)
> +		bE3 |= AST_DP_PHY_SLEEP;
> +
> +	// DP Power on/off
> +	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, (u8) ~AST_DP_PHY_SLEEP, bE3);
> +
> +	// Save ASTDP power state
> +	ast->ASTDP_State = bE3;

Never hold full registers in the driver's state. Either read the 
register's value when you need it, or store some logical state 
(on/off/sleep, etc).

Chances are that ASTDP_State belongs into connector state anyway; 
instead of the struct ast_private.

> +}
> +
> +#endif
> +
> +void ast_dp_SetOnOff(struct drm_device *dev, u8 Mode)

As far as I understand, ast_dp_PowerOnOff() is for the chip as a whole 
and this function only enables/disables the video signal?

Again, instead of 'u8 Mode' a 'bool on' seems appropriate.

CamelCase

> +{
> +	struct ast_private *ast = to_ast_private(dev);
> +
> +	// Video On/Off
> +	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, (u8) ~AST_DP_VIDEO_ENABLE, Mode);
> +
> +	// Save ASTDP power state
> +	ast->ASTDP_State = Mode;
> +
> +	// If DP plug in and link successful then check video on / off status
> +	if (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, ASTDP_LINK_SUCCESS) &&
> +		ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD)) {
> +		Mode <<= 4;
> +		while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF,
> +						ASTDP_MIRROR_VIDEO_ENABLE) != Mode) {
> +			// wait 1 ms
> +			mdelay(1);
> +		}
> +	}
> +}
> +
> +void ast_dp_SetOutput(struct drm_crtc *crtc, struct ast_vbios_mode_info *vbios_mode)

CamelCase

Maybe rater call it ast_dp_set_mode();

> +{
> +	struct ast_private *ast = to_ast_private(crtc->dev);
> +
> +	u32 ulRefreshRateIndex;
> +	u8 ModeIdx;
> +
> +	ulRefreshRateIndex = vbios_mode->enh_table->refresh_rate_index - 1;
> +
> +	switch (crtc->mode.crtc_hdisplay) {
> +	case 320:
> +		ModeIdx = ASTDP_320x240_60;
> +		break;
> +	case 400:
> +		ModeIdx = ASTDP_400x300_60;
> +		break;
> +	case 512:
> +		ModeIdx = ASTDP_512x384_60;
> +		break;
> +	case 640:
> +		ModeIdx = (ASTDP_640x480_60 + (u8) ulRefreshRateIndex);
> +		break;
> +	case 800:
> +		ModeIdx = (ASTDP_800x600_56 + (u8) ulRefreshRateIndex);
> +		break;
> +	case 1024:
> +		ModeIdx = (ASTDP_1024x768_60 + (u8) ulRefreshRateIndex);
> +		break;
> +	case 1152:
> +		ModeIdx = ASTDP_1152x864_75;
> +		break;
> +	case 1280:
> +		if (crtc->mode.crtc_vdisplay == 800)
> +			ModeIdx = (ASTDP_1280x800_60_RB - (u8) ulRefreshRateIndex);
> +		else		// 1024
> +			ModeIdx = (ASTDP_1280x1024_60 + (u8) ulRefreshRateIndex);
> +		break;
> +	case 1360:
> +	case 1366:
> +		ModeIdx = ASTDP_1366x768_60;
> +		break;
> +	case 1440:
> +		ModeIdx = (ASTDP_1440x900_60_RB - (u8) ulRefreshRateIndex);
> +		break;
> +	case 1600:
> +		if (crtc->mode.crtc_vdisplay == 900)
> +			ModeIdx = (ASTDP_1600x900_60_RB - (u8) ulRefreshRateIndex);
> +		else		//1200
> +			ModeIdx = ASTDP_1600x1200_60;
> +		break;
> +	case 1680:
> +		ModeIdx = (ASTDP_1680x1050_60_RB - (u8) ulRefreshRateIndex);
> +		break;
> +	case 1920:
> +		if (crtc->mode.crtc_vdisplay == 1080)
> +			ModeIdx = ASTDP_1920x1080_60;
> +		else		//1200
> +			ModeIdx = ASTDP_1920x1200_60;
> +		break;
> +	default:
> +		return;
> +	}
> +
> +	/*
> +	 * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp)
> +	 * CRE1[7:0]: MISC1 (default: 0x00)
> +	 * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50)
> +	 */
> +	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE0, (u8) ~ASTDP_CLEAR_MASK,
> +				ASTDP_MISC0_24bpp);
> +	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE1, (u8) ~ASTDP_CLEAR_MASK, ASTDP_MISC1);
> +	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE2, (u8) ~ASTDP_CLEAR_MASK, ModeIdx);
> +}
> diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
> index 00bfa41ff..799828503 100644
> --- a/drivers/gpu/drm/ast/ast_drv.h
> +++ b/drivers/gpu/drm/ast/ast_drv.h
> @@ -71,6 +71,7 @@ enum ast_tx_chip {
>   	AST_TX_SIL164,
>   	AST_TX_ITE66121,
>   	AST_TX_DP501,
> +	AST_TX_ASTDP,
>   };
> 
>   #define AST_DRAM_512Mx16 0
> @@ -175,6 +176,9 @@ struct ast_private {
>   	u8 dp501_maxclk;
>   	u8 *dp501_fw_addr;
>   	const struct firmware *dp501_fw;	/* dp501 fw */
> +
> +    // ASTDP
> +	u8 ASTDP_State;
>   };
> 
>   static inline struct ast_private *to_ast_private(struct drm_device *dev)
> @@ -336,10 +340,123 @@ int ast_mode_config_init(struct ast_private *ast);
>   #define AST_DP501_EDID_DATA	0xf020
> 
>   /* Define for Soc scratched reg */
> +#define COPROCESSOR_LAUNCH			BIT(5)
> +
> +#define TX_TYPE_MASK				GENMASK(3, 1)
> +#define NO_TX						(0 << 1)
> +#define ITE66121_VBIOS_TX			(1 << 1)
> +#define SI164_VBIOS_TX				(2 << 1)
> +#define CH7003_VBIOS_TX			(3 << 1)
> +#define DP501_VBIOS_TX				(4 << 1)
> +#define ANX9807_VBIOS_TX			(5 << 1)
> +#define TX_FW_EMBEDDED_FW_TX		(6 << 1)
> +#define ASTDP_DPMCU_TX				(7 << 1)
> +
>   #define AST_VRAM_INIT_STATUS_MASK	GENMASK(7, 6)
>   //#define AST_VRAM_INIT_BY_BMC		BIT(7)
>   //#define AST_VRAM_INIT_READY		BIT(6)
> 
> +/* Define for Soc scratched reg used on ASTDP */
> +#define AST_DP_PHY_SLEEP			BIT(4)
> +#define AST_DP_VIDEO_ENABLE		BIT(0)
> +
> +#define AST_DP_POWER_ON			true
> +#define AST_DP_POWER_OFF			false
> +
> +/*
> + * CRD1[b5]: DP MCU FW is executing
> + * CRDC[b0]: DP link success
> + * CRDF[b0]: DP HPD
> + * CRE5[b0]: Host reading EDID process is done
> + */
> +#define ASTDP_MCU_FW_EXECUTING			BIT(5)
> +#define ASTDP_LINK_SUCCESS				BIT(0)
> +#define ASTDP_HPD						BIT(0)
> +#define ASTDP_HOST_EDID_READ_DONE		BIT(0)
> +#define ASTDP_HOST_EDID_READ_DONE_MASK	GENMASK(0, 0)
> +
> +/*
> + * CRB8[b1]: Enable VSYNC off
> + * CRB8[b0]: Enable HSYNC off
> + */
> +#define AST_DPMS_VSYNC_OFF				BIT(1)
> +#define AST_DPMS_HSYNC_OFF				BIT(0)
> +
> +/*
> + * CRDF[b4]: Mirror of AST_DP_VIDEO_ENABLE
> + * Precondition:	A. ~AST_DP_PHY_SLEEP  &&
> + *			B. DP_HPD &&
> + *			C. DP_LINK_SUCCESS
> + */
> +#define ASTDP_MIRROR_VIDEO_ENABLE		BIT(4)
> +
> +#define ASTDP_EDID_READ_POINTER_MASK	GENMASK(7, 0)
> +#define ASTDP_EDID_VALID_FLAG_MASK		GENMASK(0, 0)
> +#define ASTDP_EDID_READ_DATA_MASK		GENMASK(7, 0)
> +
> +/*
> + * Display Transmittor Type:

'Transmitter'

> + */
> +#define TX_TYPE_MASK				GENMASK(3, 1)
> +#define NO_TX						(0 << 1)
> +#define ITE66121_VBIOS_TX			(1 << 1)
> +#define SI164_VBIOS_TX				(2 << 1)
> +#define CH7003_VBIOS_TX			(3 << 1)
> +#define DP501_VBIOS_TX				(4 << 1)
> +#define ANX9807_VBIOS_TX			(5 << 1)
> +#define TX_FW_EMBEDDED_FW_TX		(6 << 1)
> +#define ASTDP_DPMCU_TX				(7 << 1)

This duplicates the defines from just a few lines above.

> +
> +/*
> + * ASTDP setmode registers:
> + * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp)
> + * CRE1[7:0]: MISC1 (default: 0x00)
> + * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50)
> + */
> +#define ASTDP_MISC0_24bpp			BIT(5)
> +#define ASTDP_MISC1				0
> +#define ASTDP_CLEAR_MASK			GENMASK(7, 0)
> +
> +/*
> + * ASTDP resoultion table:
> + * EX:	ASTDP_A_B_C:
> + *		A: Resolution
> + *		B: Refresh Rate
> + *		C: Misc information, such as CVT, Reduce Blanked
> + */
> +#define ASTDP_640x480_60		0x00
> +#define ASTDP_640x480_72		0x01
> +#define ASTDP_640x480_75		0x02
> +#define ASTDP_640x480_85		0x03
> +#define ASTDP_800x600_56		0x04
> +#define ASTDP_800x600_60		0x05
> +#define ASTDP_800x600_72		0x06
> +#define ASTDP_800x600_75		0x07
> +#define ASTDP_800x600_85		0x08
> +#define ASTDP_1024x768_60		0x09
> +#define ASTDP_1024x768_70		0x0A
> +#define ASTDP_1024x768_75		0x0B
> +#define ASTDP_1024x768_85		0x0C
> +#define ASTDP_1280x1024_60		0x0D
> +#define ASTDP_1280x1024_75		0x0E
> +#define ASTDP_1280x1024_85		0x0F
> +#define ASTDP_1600x1200_60		0x10
> +#define ASTDP_320x240_60		0x11
> +#define ASTDP_400x300_60		0x12
> +#define ASTDP_512x384_60		0x13
> +#define ASTDP_1920x1200_60		0x14
> +#define ASTDP_1920x1080_60		0x15
> +#define ASTDP_1280x800_60		0x16
> +#define ASTDP_1280x800_60_RB	0x17
> +#define ASTDP_1440x900_60		0x18
> +#define ASTDP_1440x900_60_RB	0x19
> +#define ASTDP_1680x1050_60		0x1A
> +#define ASTDP_1680x1050_60_RB	0x1B
> +#define ASTDP_1600x900_60		0x1C
> +#define ASTDP_1600x900_60_RB	0x1D
> +#define ASTDP_1366x768_60		0x1E
> +#define ASTDP_1152x864_75		0x1F
> +
>   int ast_mm_init(struct ast_private *ast);
> 
>   /* ast post */
> @@ -360,4 +477,14 @@ void ast_init_3rdtx(struct drm_device *dev);
>   /* ast_i2c.c */
>   struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev);
> 
> +/* aspeed DP */
> +#define DPControlPower
> +bool ast_dp_read_edid(struct drm_device *dev, u8 *ediddata);
> +bool ast_dp_launch(struct drm_device *dev, u8 bPower);
> +#ifdef DPControlPower
> +void ast_dp_PowerOnOff(struct drm_device *dev, u8 Mode);
> +#endif
> +void ast_dp_SetOnOff(struct drm_device *dev, u8 Mode);
> +void ast_dp_SetOutput(struct drm_crtc *crtc, struct ast_vbios_mode_info *vbios_mode);
> +
>   #endif
> diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c
> index 79a361867..9f25fa2c8 100644
> --- a/drivers/gpu/drm/ast/ast_main.c
> +++ b/drivers/gpu/drm/ast/ast_main.c
> @@ -230,7 +230,7 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
>   			ast->tx_chip_type = AST_TX_SIL164;
>   	}
> 
> -	if ((ast->chip == AST2300) || (ast->chip == AST2400)) {
> +	if ((ast->chip == AST2300) || (ast->chip == AST2400) || (ast->chip == AST2500)) {
>   		/*
>   		 * On AST2300 and 2400, look the configuration set by the SoC in
>   		 * the SOC scratch register #1 bits 11:8 (interestingly marked
> @@ -254,7 +254,8 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
>   		case 0x0c:
>   			ast->tx_chip_type = AST_TX_DP501;
>   		}
> -	}
> +	} else if (ast->chip == AST2600)
> +		ast_dp_launch(&ast->base, 0);
> 
>   	/* Print stuff for diagnostic purposes */
>   	switch(ast->tx_chip_type) {
> diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
> index 44c2aafcb..1c7a57a03 100644
> --- a/drivers/gpu/drm/ast/ast_mode.c
> +++ b/drivers/gpu/drm/ast/ast_mode.c

Everything in this file needs an overhaul. All the CRTC and connector 
functions handle all TX chips. A better design would provide CRTC and 
conenctor for each TX chip.

I began to rework the modesetting mode in the patchset at

 
https://lore.kernel.org/dri-devel/20220111120058.10510-1-tzimmermann@suse.de/T/#m9203552f7f87f18df530cb4a679ca2188fce85a9

You're welcome to comment and test.

But I don't have ast hardware with the dedicated TX chips, so 
refactoring goes slowly.

> @@ -984,21 +984,45 @@ static int ast_cursor_plane_init(struct ast_private *ast)
>   static void ast_crtc_dpms(struct drm_crtc *crtc, int mode)
>   {
>   	struct ast_private *ast = to_ast_private(crtc->dev);
> +	u8 ch = AST_DPMS_VSYNC_OFF | AST_DPMS_HSYNC_OFF;
> 
>   	/* TODO: Maybe control display signal generation with
>   	 *       Sync Enable (bit CR17.7).
>   	 */
>   	switch (mode) {
>   	case DRM_MODE_DPMS_ON:
> -	case DRM_MODE_DPMS_STANDBY:
> -	case DRM_MODE_DPMS_SUSPEND:
> +		ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT,  0x01, 0xdf, 0);
> +		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, 0);
>   		if (ast->tx_chip_type == AST_TX_DP501)
>   			ast_set_dp501_video_output(crtc->dev, 1);
> +
> +		if (ast->tx_chip_type == AST_TX_ASTDP) {
> +#ifdef DPControlPower
> +			ast_dp_PowerOnOff(crtc->dev, AST_DP_POWER_ON);
> +#endif

Just a general comment: DPMS is for signal generation. It seems like 
you'd want to power up the TX chip elsewhere in the code. But I cannot 
really point to a good location.

> +			ast_wait_for_vretrace(ast);
> +			ast_dp_SetOnOff(crtc->dev, 1);
> +		}
> +
> +		ast_crtc_load_lut(ast, crtc);
>   		break;
> +	case DRM_MODE_DPMS_STANDBY:
> +	case DRM_MODE_DPMS_SUSPEND:
>   	case DRM_MODE_DPMS_OFF:
> +		ch = mode;
>   		if (ast->tx_chip_type == AST_TX_DP501)
>   			ast_set_dp501_video_output(crtc->dev, 0);
>   		break;
> +
> +		if (ast->tx_chip_type == AST_TX_ASTDP) {
> +			ast_dp_SetOnOff(crtc->dev, 0);
> +#ifdef DPControlPower
> +			ast_dp_PowerOnOff(crtc->dev, AST_DP_POWER_OFF);
> +#endif
> +		}
> +
> +		ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT,  0x01, 0xdf, 0x20);
> +		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, ch);
>   	}
>   }
> 
> @@ -1041,6 +1065,7 @@ ast_crtc_helper_atomic_flush(struct drm_crtc *crtc,
>   	struct ast_private *ast = to_ast_private(crtc->dev);
>   	struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
>   	struct ast_crtc_state *old_ast_crtc_state = to_ast_crtc_state(old_crtc_state);
> +	struct ast_vbios_mode_info *vbios_mode_info = &ast_crtc_state->vbios_mode_info;
> 
>   	/*
>   	 * The gamma LUT has to be reloaded after changing the primary
> @@ -1048,6 +1073,10 @@ ast_crtc_helper_atomic_flush(struct drm_crtc *crtc,
>   	 */
>   	if (old_ast_crtc_state->format != ast_crtc_state->format)
>   		ast_crtc_load_lut(ast, crtc);
> +
> +	//Set Aspeed Display-Port
> +	if (ast->tx_chip_type == AST_TX_ASTDP)
> +		ast_dp_SetOutput(crtc, vbios_mode_info);
>   }
> 
>   static void
> @@ -1222,6 +1251,14 @@ static int ast_get_modes(struct drm_connector *connector)
>   			ast->dp501_maxclk = ast_get_dp501_max_clk(connector->dev);
>   		else
>   			kfree(edid);
> +	} else if (ast->tx_chip_type == AST_TX_ASTDP) {
> +		edid = kmalloc(128, GFP_KERNEL);

There's EDID_LENGTH for the constant of 128.


Best regards
Thomas

> +		if (!edid)
> +			return -ENOMEM;
> +
> +		flags = ast_dp_read_edid(connector->dev, (u8 *)edid);
> +		if (!flags)
> +			kfree(edid);
>   	}
>   	if (!flags && ast_connector->i2c)
>   		edid = drm_get_edid(connector, &ast_connector->i2c->adapter);
> @@ -1256,7 +1293,7 @@ static enum drm_mode_status ast_mode_valid(struct drm_connector *connector,
> 
>   		if ((ast->chip == AST2100) || (ast->chip == AST2200) ||
>   		    (ast->chip == AST2300) || (ast->chip == AST2400) ||
> -		    (ast->chip == AST2500)) {
> +		    (ast->chip == AST2500) || (ast->chip == AST2600)) {
>   			if ((mode->hdisplay == 1920) && (mode->vdisplay == 1080))
>   				return MODE_OK;
> 
> @@ -1378,7 +1415,8 @@ int ast_mode_config_init(struct ast_private *ast)
>   	    ast->chip == AST2200 ||
>   	    ast->chip == AST2300 ||
>   	    ast->chip == AST2400 ||
> -	    ast->chip == AST2500) {
> +	    ast->chip == AST2500 ||
> +	    ast->chip == AST2600) {
>   		dev->mode_config.max_width = 1920;
>   		dev->mode_config.max_height = 2048;
>   	} else {
> diff --git a/drivers/gpu/drm/ast/ast_post.c b/drivers/gpu/drm/ast/ast_post.c
> index b5d92f652..0aa9cf0fb 100644
> --- a/drivers/gpu/drm/ast/ast_post.c
> +++ b/drivers/gpu/drm/ast/ast_post.c
> @@ -379,7 +379,9 @@ void ast_post_gpu(struct drm_device *dev)
>   	ast_enable_mmio(dev);
>   	ast_set_def_ext_reg(dev);
> 
> -	if (ast->config_mode == ast_use_p2a) {
> +	if (ast->chip == AST2600) {
> +		ast_dp_launch(dev, 1);
> +	} else if (ast->config_mode == ast_use_p2a) {
>   		if (ast->chip == AST2500)
>   			ast_post_chip_2500(dev);
>   		else if (ast->chip == AST2300 || ast->chip == AST2400)
> 
> base-commit: cb6846fbb83b574c85c2a80211b402a6347b60b1
> --
> 2.27.0
> 

-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Ivo Totev

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v4] drm/ast: Create the driver for ASPEED proprietory Display-Port
  2022-01-12 15:04     ` Thomas Zimmermann
@ 2022-04-28  7:56       ` KuoHsiang Chou
  2022-05-04  7:27         ` Thomas Zimmermann
  0 siblings, 1 reply; 21+ messages in thread
From: KuoHsiang Chou @ 2022-04-28  7:56 UTC (permalink / raw)
  To: tzimmermann, dri-devel, linux-kernel
  Cc: airlied, airlied, daniel, kuohsiang_chou, arc_sung, tommy_huang,
	hungju_huang, luke_chen

V1:
1. The MCU FW controling ASPEED DP is loaded by BMC boot loader.
2. Driver starts after CR[3:1] == 111b that indicates Tx is ASTDP,
   and CRD1[5] has been asserted by BMVC boot loader.
3. EDID is prioritized by DP monitor.
4. DP's EDID has high priority to decide resolution supporting.

V2:
Modules description:
1. ASTDP (ASPEED DisplayPort) is controlled by dedicated
   AST-MCU (ASPEED propriatary MCU).
2. MCU is looping in charged of HPD, Read EDID, Link Training with
   DP sink.
3. ASTDP and AST-MUC reside in BMC (Baseboard Management controller)
   addressing-space.
4. ASPEED DRM driver requests MCU to get HPD and EDID by CR-scratched
   register.

Booting sequence:
1. Check if TX is ASTDP					// ast_dp_launch()
2. Check if DP-MCU FW has loaded					// ast_dp_launch()
3. Read EDID					// ast_dp_read_edid()
4. Resolution switch					// ast_dp_SetOutput()

V3:
1. Remove unneeded semicolon.
2. Apply to git://anongit.freedesktop.org/drm/drm, instead of
   git://anongit.freedesktop.org/drm/drm-misc
3. Resolve auto build test WARNINGs on V1 patch.

V4:
1. Sync code-base with kernel 5.17_rc6
2. Remove the define of DPControlPower, because DP chips need to be
   powered on to be used.
3. Remove the switches of PHY and Display from EDID procedure.
4. Revise increaing delay to fixed delay, because this version kernel
   doesn't detect minitor consistenntly.
5. Create clean-up code used for reset of power state on errors with
   -EIO manner.
6. Revise the DP detection by TX type and its DP-FW status during
   booting and resume.
7. Correct the CamelCase Style.
8. Use register reading while needing, and remove to hold full
   register.
9. Instead of 'u8', revise to 'bool' on swwitch of PHY and video.
10.Correct typo
11.Remove the duplicated copy of TX definition.
12.Use EDID_LENGTH as the constant of 128.

Signed-off-by: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com>
---
 drivers/gpu/drm/ast/Makefile   |   2 +-
 drivers/gpu/drm/ast/ast_dp.c   | 282 +++++++++++++++++++++++++++++++++
 drivers/gpu/drm/ast/ast_drv.h  | 115 ++++++++++++++
 drivers/gpu/drm/ast/ast_main.c |   5 +-
 drivers/gpu/drm/ast/ast_mode.c | 124 ++++++++++++++-
 drivers/gpu/drm/ast/ast_post.c |   4 +-
 6 files changed, 524 insertions(+), 8 deletions(-)
 create mode 100644 drivers/gpu/drm/ast/ast_dp.c

diff --git a/drivers/gpu/drm/ast/Makefile b/drivers/gpu/drm/ast/Makefile
index 21f71160b..5a53ce51f 100644
--- a/drivers/gpu/drm/ast/Makefile
+++ b/drivers/gpu/drm/ast/Makefile
@@ -3,6 +3,6 @@
 # Makefile for the drm device driver.  This driver provides support for the
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.

-ast-y := ast_drv.o ast_i2c.o ast_main.o ast_mm.o ast_mode.o ast_post.o ast_dp501.o
+ast-y := ast_drv.o ast_i2c.o ast_main.o ast_mm.o ast_mode.o ast_post.o ast_dp501.o ast_dp.o

 obj-$(CONFIG_DRM_AST) := ast.o
diff --git a/drivers/gpu/drm/ast/ast_dp.c b/drivers/gpu/drm/ast/ast_dp.c
new file mode 100644
index 000000000..4551bc8a3
--- /dev/null
+++ b/drivers/gpu/drm/ast/ast_dp.c
@@ -0,0 +1,282 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2021, ASPEED Technology Inc.
+// Authors: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com>
+
+#include <linux/firmware.h>
+#include <linux/delay.h>
+#include <drm/drm_print.h>
+#include "ast_drv.h"
+
+int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata)
+{
+	struct ast_private *ast = to_ast_private(dev);
+	u8 i = 0, j = 0;
+
+	/*
+	 * CRD1[b5]: DP MCU FW is executing
+	 * CRDC[b0]: DP link success
+	 * CRDF[b0]: DP HPD
+	 * CRE5[b0]: Host reading EDID process is done
+	 */
+	if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, ASTDP_MCU_FW_EXECUTING) &&
+		ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, ASTDP_LINK_SUCCESS) &&
+		ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD) &&
+		ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
+								ASTDP_HOST_EDID_READ_DONE_MASK))) {
+		goto err_astdp_edid_not_ready;
+	}
+
+	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
+							0x00);
+
+	for (i = 0; i < 32; i++) {
+		/*
+		 * CRE4[7:0]: Read-Pointer for EDID (Unit: 4bytes); valid range: 0~64
+		 */
+		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE4,
+					(u8) ~ASTDP_EDID_READ_POINTER_MASK, (u8) i);
+		j = 0;
+
+		/*
+		 * CRD7[b0]: valid flag for EDID
+		 * CRD6[b0]: mirror read pointer for EDID
+		 */
+		while ((ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD7,
+				ASTDP_EDID_VALID_FLAG_MASK) != 0x01) ||
+			(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD6,
+						ASTDP_EDID_READ_POINTER_MASK) != i)) {
+			/*
+			 * Delay are getting longer with each retry.
+			 * 1. The Delays are often 2 loops when users request "Display Settings"
+			 *	  of right-click of mouse.
+			 * 2. The Delays are often longer a lot when system resume from S3/S4.
+			 */
+			mdelay(j+1);
+
+			if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1,
+							ASTDP_MCU_FW_EXECUTING) &&
+				ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC,
+							ASTDP_LINK_SUCCESS) &&
+				ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD))) {
+				goto err_astdp_jump_out_loop_of_edid;
+			}
+
+			j++;
+			if (j > 200)
+				goto err_astdp_jump_out_loop_of_edid;
+		}
+
+		*(ediddata) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT,
+							0xD8, ASTDP_EDID_READ_DATA_MASK);
+		*(ediddata + 1) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD9,
+								ASTDP_EDID_READ_DATA_MASK);
+		*(ediddata + 2) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDA,
+								ASTDP_EDID_READ_DATA_MASK);
+		*(ediddata + 3) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDB,
+								ASTDP_EDID_READ_DATA_MASK);
+
+		if (i == 31) {
+			/*
+			 * For 128-bytes EDID_1.3,
+			 * 1. Add the value of Bytes-126 to Bytes-127.
+			 *		The Bytes-127 is Checksum. Sum of all 128bytes should
+			 *		equal 0	(mod 256).
+			 * 2. Modify Bytes-126 to be 0.
+			 *		The Bytes-126 indicates the Number of extensions to
+			 *		follow. 0 represents noextensions.
+			 */
+			*(ediddata + 3) = *(ediddata + 3) + *(ediddata + 2);
+			*(ediddata + 2) = 0;
+		}
+
+		ediddata += 4;
+	}
+
+	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
+							ASTDP_HOST_EDID_READ_DONE);
+
+	return 0;
+
+err_astdp_jump_out_loop_of_edid:
+	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
+							(u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
+							ASTDP_HOST_EDID_READ_DONE);
+	return (~(j+256) + 1);
+
+err_astdp_edid_not_ready:
+	if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, ASTDP_MCU_FW_EXECUTING)))
+		return (~0xD1 + 1);
+	if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, ASTDP_LINK_SUCCESS)))
+		return (~0xDC + 1);
+	if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD)))
+		return (~0xDF + 1);
+	if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, ASTDP_HOST_EDID_READ_DONE_MASK)))
+		return (~0xE5 + 1);
+
+	return	0;
+}
+
+/*
+ * Launch Aspeed DP
+ */
+void ast_dp_launch(struct drm_device *dev, u8 bPower)
+{
+	u32 i = 0, j = 0, WaitCount = 1;
+	u8 bDPTX = 0;
+	u8 bDPExecute = 1;
+
+	struct ast_private *ast = to_ast_private(dev);
+	// S3 come back, need more time to wait BMC ready.
+	if (bPower)
+		WaitCount = 300;
+
+
+	// Wait total count by different condition.
+	for (j = 0; j < WaitCount; j++) {
+		bDPTX = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, TX_TYPE_MASK);
+
+		if (bDPTX)
+			break;
+
+		msleep(100);
+	}
+
+	// 0xE : ASTDP with DPMCU FW handling
+	if (bDPTX == ASTDP_DPMCU_TX) {
+		// Wait one second then timeout.
+		i = 0;
+
+		while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, COPROCESSOR_LAUNCH) !=
+			COPROCESSOR_LAUNCH) {
+			i++;
+			// wait 100 ms
+			msleep(100);
+
+			if (i >= 10) {
+				// DP would not be ready.
+				bDPExecute = 0;
+				break;
+			}
+		}
+
+		if (bDPExecute)
+			ast->tx_chip_type = AST_TX_ASTDP;
+
+		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
+							(u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
+							ASTDP_HOST_EDID_READ_DONE);
+	} else
+		ast->tx_chip_type = AST_TX_NONE;
+}
+
+
+
+void ast_dp_power_on_off(struct drm_device *dev, bool on)
+{
+	struct ast_private *ast = to_ast_private(dev);
+	// Read and Turn off DP PHY sleep
+	u8 bE3 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, AST_DP_VIDEO_ENABLE);
+
+	// Turn on DP PHY sleep
+	if (!on)
+		bE3 |= AST_DP_PHY_SLEEP;
+
+	// DP Power on/off
+	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, (u8) ~AST_DP_PHY_SLEEP, bE3);
+}
+
+
+
+void ast_dp_set_on_off(struct drm_device *dev, bool on)
+{
+	struct ast_private *ast = to_ast_private(dev);
+	u8 video_on_off = on;
+
+	// Video On/Off
+	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, (u8) ~AST_DP_VIDEO_ENABLE, on);
+
+	// If DP plug in and link successful then check video on / off status
+	if (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, ASTDP_LINK_SUCCESS) &&
+		ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD)) {
+		video_on_off <<= 4;
+		while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF,
+						ASTDP_MIRROR_VIDEO_ENABLE) != video_on_off) {
+			// wait 1 ms
+			mdelay(1);
+		}
+	}
+}
+
+void ast_dp_set_mode(struct drm_crtc *crtc, struct ast_vbios_mode_info *vbios_mode)
+{
+	struct ast_private *ast = to_ast_private(crtc->dev);
+
+	u32 ulRefreshRateIndex;
+	u8 ModeIdx;
+
+	ulRefreshRateIndex = vbios_mode->enh_table->refresh_rate_index - 1;
+
+	switch (crtc->mode.crtc_hdisplay) {
+	case 320:
+		ModeIdx = ASTDP_320x240_60;
+		break;
+	case 400:
+		ModeIdx = ASTDP_400x300_60;
+		break;
+	case 512:
+		ModeIdx = ASTDP_512x384_60;
+		break;
+	case 640:
+		ModeIdx = (ASTDP_640x480_60 + (u8) ulRefreshRateIndex);
+		break;
+	case 800:
+		ModeIdx = (ASTDP_800x600_56 + (u8) ulRefreshRateIndex);
+		break;
+	case 1024:
+		ModeIdx = (ASTDP_1024x768_60 + (u8) ulRefreshRateIndex);
+		break;
+	case 1152:
+		ModeIdx = ASTDP_1152x864_75;
+		break;
+	case 1280:
+		if (crtc->mode.crtc_vdisplay == 800)
+			ModeIdx = (ASTDP_1280x800_60_RB - (u8) ulRefreshRateIndex);
+		else		// 1024
+			ModeIdx = (ASTDP_1280x1024_60 + (u8) ulRefreshRateIndex);
+		break;
+	case 1360:
+	case 1366:
+		ModeIdx = ASTDP_1366x768_60;
+		break;
+	case 1440:
+		ModeIdx = (ASTDP_1440x900_60_RB - (u8) ulRefreshRateIndex);
+		break;
+	case 1600:
+		if (crtc->mode.crtc_vdisplay == 900)
+			ModeIdx = (ASTDP_1600x900_60_RB - (u8) ulRefreshRateIndex);
+		else		//1200
+			ModeIdx = ASTDP_1600x1200_60;
+		break;
+	case 1680:
+		ModeIdx = (ASTDP_1680x1050_60_RB - (u8) ulRefreshRateIndex);
+		break;
+	case 1920:
+		if (crtc->mode.crtc_vdisplay == 1080)
+			ModeIdx = ASTDP_1920x1080_60;
+		else		//1200
+			ModeIdx = ASTDP_1920x1200_60;
+		break;
+	default:
+		return;
+	}
+
+	/*
+	 * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp)
+	 * CRE1[7:0]: MISC1 (default: 0x00)
+	 * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50)
+	 */
+	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE0, (u8) ~ASTDP_CLEAR_MASK,
+				ASTDP_MISC0_24bpp);
+	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE1, (u8) ~ASTDP_CLEAR_MASK, ASTDP_MISC1);
+	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE2, (u8) ~ASTDP_CLEAR_MASK, ModeIdx);
+}
diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
index a19315b2f..ff1ae314b 100644
--- a/drivers/gpu/drm/ast/ast_drv.h
+++ b/drivers/gpu/drm/ast/ast_drv.h
@@ -70,6 +70,7 @@ enum ast_tx_chip {
 	AST_TX_NONE,
 	AST_TX_SIL164,
 	AST_TX_DP501,
+	AST_TX_ASTDP,
 };

 #define AST_DRAM_512Mx16 0
@@ -184,6 +185,10 @@ struct ast_private {
 			struct drm_encoder encoder;
 			struct drm_connector connector;
 		} dp501;
+		struct {
+			struct drm_encoder encoder;
+			struct drm_connector connector;
+		} astdp;
 	} output;

 	bool support_wide_screen;
@@ -357,10 +362,113 @@ int ast_mode_config_init(struct ast_private *ast);
 #define AST_DP501_EDID_DATA	0xf020

 /* Define for Soc scratched reg */
+#define COPROCESSOR_LAUNCH			BIT(5)
+
+/*
+ * Display Transmitter Type:
+ */
+#define TX_TYPE_MASK				GENMASK(3, 1)
+#define NO_TX						(0 << 1)
+#define ITE66121_VBIOS_TX			(1 << 1)
+#define SI164_VBIOS_TX				(2 << 1)
+#define CH7003_VBIOS_TX			(3 << 1)
+#define DP501_VBIOS_TX				(4 << 1)
+#define ANX9807_VBIOS_TX			(5 << 1)
+#define TX_FW_EMBEDDED_FW_TX		(6 << 1)
+#define ASTDP_DPMCU_TX				(7 << 1)
+
 #define AST_VRAM_INIT_STATUS_MASK	GENMASK(7, 6)
 //#define AST_VRAM_INIT_BY_BMC		BIT(7)
 //#define AST_VRAM_INIT_READY		BIT(6)

+/* Define for Soc scratched reg used on ASTDP */
+#define AST_DP_PHY_SLEEP			BIT(4)
+#define AST_DP_VIDEO_ENABLE		BIT(0)
+
+#define AST_DP_POWER_ON			true
+#define AST_DP_POWER_OFF			false
+
+/*
+ * CRD1[b5]: DP MCU FW is executing
+ * CRDC[b0]: DP link success
+ * CRDF[b0]: DP HPD
+ * CRE5[b0]: Host reading EDID process is done
+ */
+#define ASTDP_MCU_FW_EXECUTING			BIT(5)
+#define ASTDP_LINK_SUCCESS				BIT(0)
+#define ASTDP_HPD						BIT(0)
+#define ASTDP_HOST_EDID_READ_DONE		BIT(0)
+#define ASTDP_HOST_EDID_READ_DONE_MASK	GENMASK(0, 0)
+
+/*
+ * CRB8[b1]: Enable VSYNC off
+ * CRB8[b0]: Enable HSYNC off
+ */
+#define AST_DPMS_VSYNC_OFF				BIT(1)
+#define AST_DPMS_HSYNC_OFF				BIT(0)
+
+/*
+ * CRDF[b4]: Mirror of AST_DP_VIDEO_ENABLE
+ * Precondition:	A. ~AST_DP_PHY_SLEEP  &&
+ *			B. DP_HPD &&
+ *			C. DP_LINK_SUCCESS
+ */
+#define ASTDP_MIRROR_VIDEO_ENABLE		BIT(4)
+
+#define ASTDP_EDID_READ_POINTER_MASK	GENMASK(7, 0)
+#define ASTDP_EDID_VALID_FLAG_MASK		GENMASK(0, 0)
+#define ASTDP_EDID_READ_DATA_MASK		GENMASK(7, 0)
+
+/*
+ * ASTDP setmode registers:
+ * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp)
+ * CRE1[7:0]: MISC1 (default: 0x00)
+ * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50)
+ */
+#define ASTDP_MISC0_24bpp			BIT(5)
+#define ASTDP_MISC1				0
+#define ASTDP_CLEAR_MASK			GENMASK(7, 0)
+
+/*
+ * ASTDP resoultion table:
+ * EX:	ASTDP_A_B_C:
+ *		A: Resolution
+ *		B: Refresh Rate
+ *		C: Misc information, such as CVT, Reduce Blanked
+ */
+#define ASTDP_640x480_60		0x00
+#define ASTDP_640x480_72		0x01
+#define ASTDP_640x480_75		0x02
+#define ASTDP_640x480_85		0x03
+#define ASTDP_800x600_56		0x04
+#define ASTDP_800x600_60		0x05
+#define ASTDP_800x600_72		0x06
+#define ASTDP_800x600_75		0x07
+#define ASTDP_800x600_85		0x08
+#define ASTDP_1024x768_60		0x09
+#define ASTDP_1024x768_70		0x0A
+#define ASTDP_1024x768_75		0x0B
+#define ASTDP_1024x768_85		0x0C
+#define ASTDP_1280x1024_60		0x0D
+#define ASTDP_1280x1024_75		0x0E
+#define ASTDP_1280x1024_85		0x0F
+#define ASTDP_1600x1200_60		0x10
+#define ASTDP_320x240_60		0x11
+#define ASTDP_400x300_60		0x12
+#define ASTDP_512x384_60		0x13
+#define ASTDP_1920x1200_60		0x14
+#define ASTDP_1920x1080_60		0x15
+#define ASTDP_1280x800_60		0x16
+#define ASTDP_1280x800_60_RB	0x17
+#define ASTDP_1440x900_60		0x18
+#define ASTDP_1440x900_60_RB	0x19
+#define ASTDP_1680x1050_60		0x1A
+#define ASTDP_1680x1050_60_RB	0x1B
+#define ASTDP_1600x900_60		0x1C
+#define ASTDP_1600x900_60_RB	0x1D
+#define ASTDP_1366x768_60		0x1E
+#define ASTDP_1152x864_75		0x1F
+
 int ast_mm_init(struct ast_private *ast);

 /* ast post */
@@ -381,4 +489,11 @@ void ast_init_3rdtx(struct drm_device *dev);
 /* ast_i2c.c */
 struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev);

+/* aspeed DP */
+int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata);
+void ast_dp_launch(struct drm_device *dev, u8 bPower);
+void ast_dp_power_on_off(struct drm_device *dev, bool no);
+void ast_dp_set_on_off(struct drm_device *dev, bool no);
+void ast_dp_set_mode(struct drm_crtc *crtc, struct ast_vbios_mode_info *vbios_mode);
+
 #endif
diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c
index 22e9e2d3c..1113ee1cb 100644
--- a/drivers/gpu/drm/ast/ast_main.c
+++ b/drivers/gpu/drm/ast/ast_main.c
@@ -232,7 +232,7 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
 			ast->tx_chip_type = AST_TX_SIL164;
 	}

-	if ((ast->chip == AST2300) || (ast->chip == AST2400)) {
+	if ((ast->chip == AST2300) || (ast->chip == AST2400) || (ast->chip == AST2500)) {
 		/*
 		 * On AST2300 and 2400, look the configuration set by the SoC in
 		 * the SOC scratch register #1 bits 11:8 (interestingly marked
@@ -256,7 +256,8 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
 		case 0x0c:
 			ast->tx_chip_type = AST_TX_DP501;
 		}
-	}
+	} else if (ast->chip == AST2600)
+		ast_dp_launch(&ast->base, 0);

 	/* Print stuff for diagnostic purposes */
 	switch(ast->tx_chip_type) {
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index 45b56b39a..4728825b7 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -988,21 +988,41 @@ static int ast_cursor_plane_init(struct ast_private *ast)
 static void ast_crtc_dpms(struct drm_crtc *crtc, int mode)
 {
 	struct ast_private *ast = to_ast_private(crtc->dev);
+	u8 ch = AST_DPMS_VSYNC_OFF | AST_DPMS_HSYNC_OFF;

 	/* TODO: Maybe control display signal generation with
 	 *       Sync Enable (bit CR17.7).
 	 */
 	switch (mode) {
 	case DRM_MODE_DPMS_ON:
-	case DRM_MODE_DPMS_STANDBY:
-	case DRM_MODE_DPMS_SUSPEND:
+		ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT,  0x01, 0xdf, 0);
+		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, 0);
 		if (ast->tx_chip_type == AST_TX_DP501)
 			ast_set_dp501_video_output(crtc->dev, 1);
+
+		if (ast->tx_chip_type == AST_TX_ASTDP) {
+			ast_dp_power_on_off(crtc->dev, AST_DP_POWER_ON);
+			ast_wait_for_vretrace(ast);
+			ast_dp_set_on_off(crtc->dev, 1);
+		}
+
+		ast_crtc_load_lut(ast, crtc);
 		break;
+	case DRM_MODE_DPMS_STANDBY:
+	case DRM_MODE_DPMS_SUSPEND:
 	case DRM_MODE_DPMS_OFF:
+		ch = mode;
 		if (ast->tx_chip_type == AST_TX_DP501)
 			ast_set_dp501_video_output(crtc->dev, 0);
 		break;
+
+		if (ast->tx_chip_type == AST_TX_ASTDP) {
+			ast_dp_set_on_off(crtc->dev, 0);
+			ast_dp_power_on_off(crtc->dev, AST_DP_POWER_OFF);
+		}
+
+		ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT,  0x01, 0xdf, 0x20);
+		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, ch);
 	}
 }

@@ -1027,7 +1047,7 @@ ast_crtc_helper_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode

 		if ((ast->chip == AST2100) || (ast->chip == AST2200) ||
 		    (ast->chip == AST2300) || (ast->chip == AST2400) ||
-		    (ast->chip == AST2500)) {
+		    (ast->chip == AST2500) || (ast->chip == AST2600)) {
 			if ((mode->hdisplay == 1920) && (mode->vdisplay == 1080))
 				return MODE_OK;

@@ -1110,6 +1130,7 @@ ast_crtc_helper_atomic_flush(struct drm_crtc *crtc,
 	struct ast_private *ast = to_ast_private(crtc->dev);
 	struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
 	struct ast_crtc_state *old_ast_crtc_state = to_ast_crtc_state(old_crtc_state);
+	struct ast_vbios_mode_info *vbios_mode_info = &ast_crtc_state->vbios_mode_info;

 	/*
 	 * The gamma LUT has to be reloaded after changing the primary
@@ -1117,6 +1138,10 @@ ast_crtc_helper_atomic_flush(struct drm_crtc *crtc,
 	 */
 	if (old_ast_crtc_state->format != ast_crtc_state->format)
 		ast_crtc_load_lut(ast, crtc);
+
+	//Set Aspeed Display-Port
+	if (ast->tx_chip_type == AST_TX_ASTDP)
+		ast_dp_set_mode(crtc, vbios_mode_info);
 }

 static void
@@ -1527,6 +1552,93 @@ static int ast_dp501_output_init(struct ast_private *ast)
 	return 0;
 }

+/*
+ * ASPEED Display-Port Connector
+ */
+
+static int ast_astdp_connector_helper_get_modes(struct drm_connector *connector)
+{
+	void *edid;
+
+	int succ;
+	int count;
+
+	edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
+	if (!edid)
+		goto err_drm_connector_update_edid_property;
+
+	succ = ast_astdp_read_edid(connector->dev, edid);
+	if (succ < 0)
+		goto err_kfree;
+
+	drm_connector_update_edid_property(connector, edid);
+	count = drm_add_edid_modes(connector, edid);
+	kfree(edid);
+
+	return count;
+
+err_kfree:
+	kfree(edid);
+err_drm_connector_update_edid_property:
+	drm_connector_update_edid_property(connector, NULL);
+	return 0;
+}
+
+static const struct drm_connector_helper_funcs ast_astdp_connector_helper_funcs = {
+	.get_modes = ast_astdp_connector_helper_get_modes,
+};
+
+static const struct drm_connector_funcs ast_astdp_connector_funcs = {
+	.reset = drm_atomic_helper_connector_reset,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.destroy = drm_connector_cleanup,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static int ast_astdp_connector_init(struct drm_device *dev, struct drm_connector *connector)
+{
+	int ret;
+
+	ret = drm_connector_init(dev, connector, &ast_astdp_connector_funcs,
+				 DRM_MODE_CONNECTOR_DisplayPort);
+	if (ret)
+		return ret;
+
+	drm_connector_helper_add(connector, &ast_astdp_connector_helper_funcs);
+
+	connector->interlace_allowed = 0;
+	connector->doublescan_allowed = 0;
+
+	connector->polled = DRM_CONNECTOR_POLL_CONNECT;
+
+	return 0;
+}
+
+static int ast_astdp_output_init(struct ast_private *ast)
+{
+	struct drm_device *dev = &ast->base;
+	struct drm_crtc *crtc = &ast->crtc;
+	struct drm_encoder *encoder = &ast->output.astdp.encoder;
+	struct drm_connector *connector = &ast->output.astdp.connector;
+	int ret;
+
+	ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_TMDS);
+	if (ret)
+		return ret;
+	encoder->possible_crtcs = drm_crtc_mask(crtc);
+
+	ret = ast_astdp_connector_init(dev, connector);
+	if (ret)
+		return ret;
+
+	ret = drm_connector_attach_encoder(connector, encoder);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
 /*
  * Mode config
  */
@@ -1563,7 +1675,8 @@ int ast_mode_config_init(struct ast_private *ast)
 	    ast->chip == AST2200 ||
 	    ast->chip == AST2300 ||
 	    ast->chip == AST2400 ||
-	    ast->chip == AST2500) {
+	    ast->chip == AST2500 ||
+	    ast->chip == AST2600) {
 		dev->mode_config.max_width = 1920;
 		dev->mode_config.max_height = 2048;
 	} else {
@@ -1594,6 +1707,9 @@ int ast_mode_config_init(struct ast_private *ast)
 	case AST_TX_DP501:
 		ret = ast_dp501_output_init(ast);
 		break;
+	case AST_TX_ASTDP:
+		ret = ast_astdp_output_init(ast);
+		break;
 	}
 	if (ret)
 		return ret;
diff --git a/drivers/gpu/drm/ast/ast_post.c b/drivers/gpu/drm/ast/ast_post.c
index b5d92f652..0aa9cf0fb 100644
--- a/drivers/gpu/drm/ast/ast_post.c
+++ b/drivers/gpu/drm/ast/ast_post.c
@@ -379,7 +379,9 @@ void ast_post_gpu(struct drm_device *dev)
 	ast_enable_mmio(dev);
 	ast_set_def_ext_reg(dev);

-	if (ast->config_mode == ast_use_p2a) {
+	if (ast->chip == AST2600) {
+		ast_dp_launch(dev, 1);
+	} else if (ast->config_mode == ast_use_p2a) {
 		if (ast->chip == AST2500)
 			ast_post_chip_2500(dev);
 		else if (ast->chip == AST2300 || ast->chip == AST2400)

base-commit: c54b39a565227538c52ead2349eb17d54aadd6f7
--
2.27.0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [PATCH v4] drm/ast: Create the driver for ASPEED proprietory Display-Port
  2022-04-28  7:56       ` [PATCH v4] " KuoHsiang Chou
@ 2022-05-04  7:27         ` Thomas Zimmermann
       [not found]           ` <PSAPR06MB48056FC903142B7F60A3BD388CC39@PSAPR06MB4805.apcprd06.prod.outlook.com>
  0 siblings, 1 reply; 21+ messages in thread
From: Thomas Zimmermann @ 2022-05-04  7:27 UTC (permalink / raw)
  To: KuoHsiang Chou, dri-devel, linux-kernel
  Cc: airlied, airlied, daniel, arc_sung, tommy_huang, hungju_huang, luke_chen


[-- Attachment #1.1: Type: text/plain, Size: 25443 bytes --]

Hi

Am 28.04.22 um 09:56 schrieb KuoHsiang Chou:
> V1:
> 1. The MCU FW controling ASPEED DP is loaded by BMC boot loader.
> 2. Driver starts after CR[3:1] == 111b that indicates Tx is ASTDP,
>     and CRD1[5] has been asserted by BMVC boot loader.
> 3. EDID is prioritized by DP monitor.
> 4. DP's EDID has high priority to decide resolution supporting.
> 
> V2:
> Modules description:
> 1. ASTDP (ASPEED DisplayPort) is controlled by dedicated
>     AST-MCU (ASPEED propriatary MCU).
> 2. MCU is looping in charged of HPD, Read EDID, Link Training with
>     DP sink.
> 3. ASTDP and AST-MUC reside in BMC (Baseboard Management controller)
>     addressing-space.
> 4. ASPEED DRM driver requests MCU to get HPD and EDID by CR-scratched
>     register.
> 
> Booting sequence:
> 1. Check if TX is ASTDP					// ast_dp_launch()
> 2. Check if DP-MCU FW has loaded					// ast_dp_launch()
> 3. Read EDID					// ast_dp_read_edid()
> 4. Resolution switch					// ast_dp_SetOutput()
> 
> V3:
> 1. Remove unneeded semicolon.
> 2. Apply to git://anongit.freedesktop.org/drm/drm, instead of
>     git://anongit.freedesktop.org/drm/drm-misc
> 3. Resolve auto build test WARNINGs on V1 patch.
> 
> V4:
> 1. Sync code-base with kernel 5.17_rc6
> 2. Remove the define of DPControlPower, because DP chips need to be
>     powered on to be used.
> 3. Remove the switches of PHY and Display from EDID procedure.
> 4. Revise increaing delay to fixed delay, because this version kernel
>     doesn't detect minitor consistenntly.
> 5. Create clean-up code used for reset of power state on errors with
>     -EIO manner.
> 6. Revise the DP detection by TX type and its DP-FW status during
>     booting and resume.
> 7. Correct the CamelCase Style.
> 8. Use register reading while needing, and remove to hold full
>     register.
> 9. Instead of 'u8', revise to 'bool' on swwitch of PHY and video.
> 10.Correct typo
> 11.Remove the duplicated copy of TX definition.
> 12.Use EDID_LENGTH as the constant of 128.
> 
> Signed-off-by: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com>

Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de>

I've meanwhile added your patch to drm-misc-next. It should show up in 
one of the next kernel releases.  Thanks a lot.

Best regards
Thomas

> ---
>   drivers/gpu/drm/ast/Makefile   |   2 +-
>   drivers/gpu/drm/ast/ast_dp.c   | 282 +++++++++++++++++++++++++++++++++
>   drivers/gpu/drm/ast/ast_drv.h  | 115 ++++++++++++++
>   drivers/gpu/drm/ast/ast_main.c |   5 +-
>   drivers/gpu/drm/ast/ast_mode.c | 124 ++++++++++++++-
>   drivers/gpu/drm/ast/ast_post.c |   4 +-
>   6 files changed, 524 insertions(+), 8 deletions(-)
>   create mode 100644 drivers/gpu/drm/ast/ast_dp.c
> 
> diff --git a/drivers/gpu/drm/ast/Makefile b/drivers/gpu/drm/ast/Makefile
> index 21f71160b..5a53ce51f 100644
> --- a/drivers/gpu/drm/ast/Makefile
> +++ b/drivers/gpu/drm/ast/Makefile
> @@ -3,6 +3,6 @@
>   # Makefile for the drm device driver.  This driver provides support for the
>   # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
> 
> -ast-y := ast_drv.o ast_i2c.o ast_main.o ast_mm.o ast_mode.o ast_post.o ast_dp501.o
> +ast-y := ast_drv.o ast_i2c.o ast_main.o ast_mm.o ast_mode.o ast_post.o ast_dp501.o ast_dp.o
> 
>   obj-$(CONFIG_DRM_AST) := ast.o
> diff --git a/drivers/gpu/drm/ast/ast_dp.c b/drivers/gpu/drm/ast/ast_dp.c
> new file mode 100644
> index 000000000..4551bc8a3
> --- /dev/null
> +++ b/drivers/gpu/drm/ast/ast_dp.c
> @@ -0,0 +1,282 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Copyright (c) 2021, ASPEED Technology Inc.
> +// Authors: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com>
> +
> +#include <linux/firmware.h>
> +#include <linux/delay.h>
> +#include <drm/drm_print.h>
> +#include "ast_drv.h"
> +
> +int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata)
> +{
> +	struct ast_private *ast = to_ast_private(dev);
> +	u8 i = 0, j = 0;
> +
> +	/*
> +	 * CRD1[b5]: DP MCU FW is executing
> +	 * CRDC[b0]: DP link success
> +	 * CRDF[b0]: DP HPD
> +	 * CRE5[b0]: Host reading EDID process is done
> +	 */
> +	if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, ASTDP_MCU_FW_EXECUTING) &&
> +		ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, ASTDP_LINK_SUCCESS) &&
> +		ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD) &&
> +		ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
> +								ASTDP_HOST_EDID_READ_DONE_MASK))) {
> +		goto err_astdp_edid_not_ready;
> +	}
> +
> +	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
> +							0x00);
> +
> +	for (i = 0; i < 32; i++) {
> +		/*
> +		 * CRE4[7:0]: Read-Pointer for EDID (Unit: 4bytes); valid range: 0~64
> +		 */
> +		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE4,
> +					(u8) ~ASTDP_EDID_READ_POINTER_MASK, (u8) i);
> +		j = 0;
> +
> +		/*
> +		 * CRD7[b0]: valid flag for EDID
> +		 * CRD6[b0]: mirror read pointer for EDID
> +		 */
> +		while ((ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD7,
> +				ASTDP_EDID_VALID_FLAG_MASK) != 0x01) ||
> +			(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD6,
> +						ASTDP_EDID_READ_POINTER_MASK) != i)) {
> +			/*
> +			 * Delay are getting longer with each retry.
> +			 * 1. The Delays are often 2 loops when users request "Display Settings"
> +			 *	  of right-click of mouse.
> +			 * 2. The Delays are often longer a lot when system resume from S3/S4.
> +			 */
> +			mdelay(j+1);
> +
> +			if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1,
> +							ASTDP_MCU_FW_EXECUTING) &&
> +				ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC,
> +							ASTDP_LINK_SUCCESS) &&
> +				ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD))) {
> +				goto err_astdp_jump_out_loop_of_edid;
> +			}
> +
> +			j++;
> +			if (j > 200)
> +				goto err_astdp_jump_out_loop_of_edid;
> +		}
> +
> +		*(ediddata) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT,
> +							0xD8, ASTDP_EDID_READ_DATA_MASK);
> +		*(ediddata + 1) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD9,
> +								ASTDP_EDID_READ_DATA_MASK);
> +		*(ediddata + 2) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDA,
> +								ASTDP_EDID_READ_DATA_MASK);
> +		*(ediddata + 3) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDB,
> +								ASTDP_EDID_READ_DATA_MASK);
> +
> +		if (i == 31) {
> +			/*
> +			 * For 128-bytes EDID_1.3,
> +			 * 1. Add the value of Bytes-126 to Bytes-127.
> +			 *		The Bytes-127 is Checksum. Sum of all 128bytes should
> +			 *		equal 0	(mod 256).
> +			 * 2. Modify Bytes-126 to be 0.
> +			 *		The Bytes-126 indicates the Number of extensions to
> +			 *		follow. 0 represents noextensions.
> +			 */
> +			*(ediddata + 3) = *(ediddata + 3) + *(ediddata + 2);
> +			*(ediddata + 2) = 0;
> +		}
> +
> +		ediddata += 4;
> +	}
> +
> +	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
> +							ASTDP_HOST_EDID_READ_DONE);
> +
> +	return 0;
> +
> +err_astdp_jump_out_loop_of_edid:
> +	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
> +							(u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
> +							ASTDP_HOST_EDID_READ_DONE);
> +	return (~(j+256) + 1);
> +
> +err_astdp_edid_not_ready:
> +	if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, ASTDP_MCU_FW_EXECUTING)))
> +		return (~0xD1 + 1);
> +	if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, ASTDP_LINK_SUCCESS)))
> +		return (~0xDC + 1);
> +	if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD)))
> +		return (~0xDF + 1);
> +	if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, ASTDP_HOST_EDID_READ_DONE_MASK)))
> +		return (~0xE5 + 1);
> +
> +	return	0;
> +}
> +
> +/*
> + * Launch Aspeed DP
> + */
> +void ast_dp_launch(struct drm_device *dev, u8 bPower)
> +{
> +	u32 i = 0, j = 0, WaitCount = 1;
> +	u8 bDPTX = 0;
> +	u8 bDPExecute = 1;
> +
> +	struct ast_private *ast = to_ast_private(dev);
> +	// S3 come back, need more time to wait BMC ready.
> +	if (bPower)
> +		WaitCount = 300;
> +
> +
> +	// Wait total count by different condition.
> +	for (j = 0; j < WaitCount; j++) {
> +		bDPTX = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, TX_TYPE_MASK);
> +
> +		if (bDPTX)
> +			break;
> +
> +		msleep(100);
> +	}
> +
> +	// 0xE : ASTDP with DPMCU FW handling
> +	if (bDPTX == ASTDP_DPMCU_TX) {
> +		// Wait one second then timeout.
> +		i = 0;
> +
> +		while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, COPROCESSOR_LAUNCH) !=
> +			COPROCESSOR_LAUNCH) {
> +			i++;
> +			// wait 100 ms
> +			msleep(100);
> +
> +			if (i >= 10) {
> +				// DP would not be ready.
> +				bDPExecute = 0;
> +				break;
> +			}
> +		}
> +
> +		if (bDPExecute)
> +			ast->tx_chip_type = AST_TX_ASTDP;
> +
> +		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
> +							(u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
> +							ASTDP_HOST_EDID_READ_DONE);
> +	} else
> +		ast->tx_chip_type = AST_TX_NONE;
> +}
> +
> +
> +
> +void ast_dp_power_on_off(struct drm_device *dev, bool on)
> +{
> +	struct ast_private *ast = to_ast_private(dev);
> +	// Read and Turn off DP PHY sleep
> +	u8 bE3 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, AST_DP_VIDEO_ENABLE);
> +
> +	// Turn on DP PHY sleep
> +	if (!on)
> +		bE3 |= AST_DP_PHY_SLEEP;
> +
> +	// DP Power on/off
> +	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, (u8) ~AST_DP_PHY_SLEEP, bE3);
> +}
> +
> +
> +
> +void ast_dp_set_on_off(struct drm_device *dev, bool on)
> +{
> +	struct ast_private *ast = to_ast_private(dev);
> +	u8 video_on_off = on;
> +
> +	// Video On/Off
> +	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, (u8) ~AST_DP_VIDEO_ENABLE, on);
> +
> +	// If DP plug in and link successful then check video on / off status
> +	if (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, ASTDP_LINK_SUCCESS) &&
> +		ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD)) {
> +		video_on_off <<= 4;
> +		while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF,
> +						ASTDP_MIRROR_VIDEO_ENABLE) != video_on_off) {
> +			// wait 1 ms
> +			mdelay(1);
> +		}
> +	}
> +}
> +
> +void ast_dp_set_mode(struct drm_crtc *crtc, struct ast_vbios_mode_info *vbios_mode)
> +{
> +	struct ast_private *ast = to_ast_private(crtc->dev);
> +
> +	u32 ulRefreshRateIndex;
> +	u8 ModeIdx;
> +
> +	ulRefreshRateIndex = vbios_mode->enh_table->refresh_rate_index - 1;
> +
> +	switch (crtc->mode.crtc_hdisplay) {
> +	case 320:
> +		ModeIdx = ASTDP_320x240_60;
> +		break;
> +	case 400:
> +		ModeIdx = ASTDP_400x300_60;
> +		break;
> +	case 512:
> +		ModeIdx = ASTDP_512x384_60;
> +		break;
> +	case 640:
> +		ModeIdx = (ASTDP_640x480_60 + (u8) ulRefreshRateIndex);
> +		break;
> +	case 800:
> +		ModeIdx = (ASTDP_800x600_56 + (u8) ulRefreshRateIndex);
> +		break;
> +	case 1024:
> +		ModeIdx = (ASTDP_1024x768_60 + (u8) ulRefreshRateIndex);
> +		break;
> +	case 1152:
> +		ModeIdx = ASTDP_1152x864_75;
> +		break;
> +	case 1280:
> +		if (crtc->mode.crtc_vdisplay == 800)
> +			ModeIdx = (ASTDP_1280x800_60_RB - (u8) ulRefreshRateIndex);
> +		else		// 1024
> +			ModeIdx = (ASTDP_1280x1024_60 + (u8) ulRefreshRateIndex);
> +		break;
> +	case 1360:
> +	case 1366:
> +		ModeIdx = ASTDP_1366x768_60;
> +		break;
> +	case 1440:
> +		ModeIdx = (ASTDP_1440x900_60_RB - (u8) ulRefreshRateIndex);
> +		break;
> +	case 1600:
> +		if (crtc->mode.crtc_vdisplay == 900)
> +			ModeIdx = (ASTDP_1600x900_60_RB - (u8) ulRefreshRateIndex);
> +		else		//1200
> +			ModeIdx = ASTDP_1600x1200_60;
> +		break;
> +	case 1680:
> +		ModeIdx = (ASTDP_1680x1050_60_RB - (u8) ulRefreshRateIndex);
> +		break;
> +	case 1920:
> +		if (crtc->mode.crtc_vdisplay == 1080)
> +			ModeIdx = ASTDP_1920x1080_60;
> +		else		//1200
> +			ModeIdx = ASTDP_1920x1200_60;
> +		break;
> +	default:
> +		return;
> +	}
> +
> +	/*
> +	 * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp)
> +	 * CRE1[7:0]: MISC1 (default: 0x00)
> +	 * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50)
> +	 */
> +	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE0, (u8) ~ASTDP_CLEAR_MASK,
> +				ASTDP_MISC0_24bpp);
> +	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE1, (u8) ~ASTDP_CLEAR_MASK, ASTDP_MISC1);
> +	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE2, (u8) ~ASTDP_CLEAR_MASK, ModeIdx);
> +}
> diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
> index a19315b2f..ff1ae314b 100644
> --- a/drivers/gpu/drm/ast/ast_drv.h
> +++ b/drivers/gpu/drm/ast/ast_drv.h
> @@ -70,6 +70,7 @@ enum ast_tx_chip {
>   	AST_TX_NONE,
>   	AST_TX_SIL164,
>   	AST_TX_DP501,
> +	AST_TX_ASTDP,
>   };
> 
>   #define AST_DRAM_512Mx16 0
> @@ -184,6 +185,10 @@ struct ast_private {
>   			struct drm_encoder encoder;
>   			struct drm_connector connector;
>   		} dp501;
> +		struct {
> +			struct drm_encoder encoder;
> +			struct drm_connector connector;
> +		} astdp;
>   	} output;
> 
>   	bool support_wide_screen;
> @@ -357,10 +362,113 @@ int ast_mode_config_init(struct ast_private *ast);
>   #define AST_DP501_EDID_DATA	0xf020
> 
>   /* Define for Soc scratched reg */
> +#define COPROCESSOR_LAUNCH			BIT(5)
> +
> +/*
> + * Display Transmitter Type:
> + */
> +#define TX_TYPE_MASK				GENMASK(3, 1)
> +#define NO_TX						(0 << 1)
> +#define ITE66121_VBIOS_TX			(1 << 1)
> +#define SI164_VBIOS_TX				(2 << 1)
> +#define CH7003_VBIOS_TX			(3 << 1)
> +#define DP501_VBIOS_TX				(4 << 1)
> +#define ANX9807_VBIOS_TX			(5 << 1)
> +#define TX_FW_EMBEDDED_FW_TX		(6 << 1)
> +#define ASTDP_DPMCU_TX				(7 << 1)
> +
>   #define AST_VRAM_INIT_STATUS_MASK	GENMASK(7, 6)
>   //#define AST_VRAM_INIT_BY_BMC		BIT(7)
>   //#define AST_VRAM_INIT_READY		BIT(6)
> 
> +/* Define for Soc scratched reg used on ASTDP */
> +#define AST_DP_PHY_SLEEP			BIT(4)
> +#define AST_DP_VIDEO_ENABLE		BIT(0)
> +
> +#define AST_DP_POWER_ON			true
> +#define AST_DP_POWER_OFF			false
> +
> +/*
> + * CRD1[b5]: DP MCU FW is executing
> + * CRDC[b0]: DP link success
> + * CRDF[b0]: DP HPD
> + * CRE5[b0]: Host reading EDID process is done
> + */
> +#define ASTDP_MCU_FW_EXECUTING			BIT(5)
> +#define ASTDP_LINK_SUCCESS				BIT(0)
> +#define ASTDP_HPD						BIT(0)
> +#define ASTDP_HOST_EDID_READ_DONE		BIT(0)
> +#define ASTDP_HOST_EDID_READ_DONE_MASK	GENMASK(0, 0)
> +
> +/*
> + * CRB8[b1]: Enable VSYNC off
> + * CRB8[b0]: Enable HSYNC off
> + */
> +#define AST_DPMS_VSYNC_OFF				BIT(1)
> +#define AST_DPMS_HSYNC_OFF				BIT(0)
> +
> +/*
> + * CRDF[b4]: Mirror of AST_DP_VIDEO_ENABLE
> + * Precondition:	A. ~AST_DP_PHY_SLEEP  &&
> + *			B. DP_HPD &&
> + *			C. DP_LINK_SUCCESS
> + */
> +#define ASTDP_MIRROR_VIDEO_ENABLE		BIT(4)
> +
> +#define ASTDP_EDID_READ_POINTER_MASK	GENMASK(7, 0)
> +#define ASTDP_EDID_VALID_FLAG_MASK		GENMASK(0, 0)
> +#define ASTDP_EDID_READ_DATA_MASK		GENMASK(7, 0)
> +
> +/*
> + * ASTDP setmode registers:
> + * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp)
> + * CRE1[7:0]: MISC1 (default: 0x00)
> + * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50)
> + */
> +#define ASTDP_MISC0_24bpp			BIT(5)
> +#define ASTDP_MISC1				0
> +#define ASTDP_CLEAR_MASK			GENMASK(7, 0)
> +
> +/*
> + * ASTDP resoultion table:
> + * EX:	ASTDP_A_B_C:
> + *		A: Resolution
> + *		B: Refresh Rate
> + *		C: Misc information, such as CVT, Reduce Blanked
> + */
> +#define ASTDP_640x480_60		0x00
> +#define ASTDP_640x480_72		0x01
> +#define ASTDP_640x480_75		0x02
> +#define ASTDP_640x480_85		0x03
> +#define ASTDP_800x600_56		0x04
> +#define ASTDP_800x600_60		0x05
> +#define ASTDP_800x600_72		0x06
> +#define ASTDP_800x600_75		0x07
> +#define ASTDP_800x600_85		0x08
> +#define ASTDP_1024x768_60		0x09
> +#define ASTDP_1024x768_70		0x0A
> +#define ASTDP_1024x768_75		0x0B
> +#define ASTDP_1024x768_85		0x0C
> +#define ASTDP_1280x1024_60		0x0D
> +#define ASTDP_1280x1024_75		0x0E
> +#define ASTDP_1280x1024_85		0x0F
> +#define ASTDP_1600x1200_60		0x10
> +#define ASTDP_320x240_60		0x11
> +#define ASTDP_400x300_60		0x12
> +#define ASTDP_512x384_60		0x13
> +#define ASTDP_1920x1200_60		0x14
> +#define ASTDP_1920x1080_60		0x15
> +#define ASTDP_1280x800_60		0x16
> +#define ASTDP_1280x800_60_RB	0x17
> +#define ASTDP_1440x900_60		0x18
> +#define ASTDP_1440x900_60_RB	0x19
> +#define ASTDP_1680x1050_60		0x1A
> +#define ASTDP_1680x1050_60_RB	0x1B
> +#define ASTDP_1600x900_60		0x1C
> +#define ASTDP_1600x900_60_RB	0x1D
> +#define ASTDP_1366x768_60		0x1E
> +#define ASTDP_1152x864_75		0x1F
> +
>   int ast_mm_init(struct ast_private *ast);
> 
>   /* ast post */
> @@ -381,4 +489,11 @@ void ast_init_3rdtx(struct drm_device *dev);
>   /* ast_i2c.c */
>   struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev);
> 
> +/* aspeed DP */
> +int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata);
> +void ast_dp_launch(struct drm_device *dev, u8 bPower);
> +void ast_dp_power_on_off(struct drm_device *dev, bool no);
> +void ast_dp_set_on_off(struct drm_device *dev, bool no);
> +void ast_dp_set_mode(struct drm_crtc *crtc, struct ast_vbios_mode_info *vbios_mode);
> +
>   #endif
> diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c
> index 22e9e2d3c..1113ee1cb 100644
> --- a/drivers/gpu/drm/ast/ast_main.c
> +++ b/drivers/gpu/drm/ast/ast_main.c
> @@ -232,7 +232,7 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
>   			ast->tx_chip_type = AST_TX_SIL164;
>   	}
> 
> -	if ((ast->chip == AST2300) || (ast->chip == AST2400)) {
> +	if ((ast->chip == AST2300) || (ast->chip == AST2400) || (ast->chip == AST2500)) {
>   		/*
>   		 * On AST2300 and 2400, look the configuration set by the SoC in
>   		 * the SOC scratch register #1 bits 11:8 (interestingly marked
> @@ -256,7 +256,8 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
>   		case 0x0c:
>   			ast->tx_chip_type = AST_TX_DP501;
>   		}
> -	}
> +	} else if (ast->chip == AST2600)
> +		ast_dp_launch(&ast->base, 0);
> 
>   	/* Print stuff for diagnostic purposes */
>   	switch(ast->tx_chip_type) {
> diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
> index 45b56b39a..4728825b7 100644
> --- a/drivers/gpu/drm/ast/ast_mode.c
> +++ b/drivers/gpu/drm/ast/ast_mode.c
> @@ -988,21 +988,41 @@ static int ast_cursor_plane_init(struct ast_private *ast)
>   static void ast_crtc_dpms(struct drm_crtc *crtc, int mode)
>   {
>   	struct ast_private *ast = to_ast_private(crtc->dev);
> +	u8 ch = AST_DPMS_VSYNC_OFF | AST_DPMS_HSYNC_OFF;
> 
>   	/* TODO: Maybe control display signal generation with
>   	 *       Sync Enable (bit CR17.7).
>   	 */
>   	switch (mode) {
>   	case DRM_MODE_DPMS_ON:
> -	case DRM_MODE_DPMS_STANDBY:
> -	case DRM_MODE_DPMS_SUSPEND:
> +		ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT,  0x01, 0xdf, 0);
> +		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, 0);
>   		if (ast->tx_chip_type == AST_TX_DP501)
>   			ast_set_dp501_video_output(crtc->dev, 1);
> +
> +		if (ast->tx_chip_type == AST_TX_ASTDP) {
> +			ast_dp_power_on_off(crtc->dev, AST_DP_POWER_ON);
> +			ast_wait_for_vretrace(ast);
> +			ast_dp_set_on_off(crtc->dev, 1);
> +		}
> +
> +		ast_crtc_load_lut(ast, crtc);
>   		break;
> +	case DRM_MODE_DPMS_STANDBY:
> +	case DRM_MODE_DPMS_SUSPEND:
>   	case DRM_MODE_DPMS_OFF:
> +		ch = mode;
>   		if (ast->tx_chip_type == AST_TX_DP501)
>   			ast_set_dp501_video_output(crtc->dev, 0);
>   		break;
> +
> +		if (ast->tx_chip_type == AST_TX_ASTDP) {
> +			ast_dp_set_on_off(crtc->dev, 0);
> +			ast_dp_power_on_off(crtc->dev, AST_DP_POWER_OFF);
> +		}
> +
> +		ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT,  0x01, 0xdf, 0x20);
> +		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, ch);
>   	}
>   }
> 
> @@ -1027,7 +1047,7 @@ ast_crtc_helper_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode
> 
>   		if ((ast->chip == AST2100) || (ast->chip == AST2200) ||
>   		    (ast->chip == AST2300) || (ast->chip == AST2400) ||
> -		    (ast->chip == AST2500)) {
> +		    (ast->chip == AST2500) || (ast->chip == AST2600)) {
>   			if ((mode->hdisplay == 1920) && (mode->vdisplay == 1080))
>   				return MODE_OK;
> 
> @@ -1110,6 +1130,7 @@ ast_crtc_helper_atomic_flush(struct drm_crtc *crtc,
>   	struct ast_private *ast = to_ast_private(crtc->dev);
>   	struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
>   	struct ast_crtc_state *old_ast_crtc_state = to_ast_crtc_state(old_crtc_state);
> +	struct ast_vbios_mode_info *vbios_mode_info = &ast_crtc_state->vbios_mode_info;
> 
>   	/*
>   	 * The gamma LUT has to be reloaded after changing the primary
> @@ -1117,6 +1138,10 @@ ast_crtc_helper_atomic_flush(struct drm_crtc *crtc,
>   	 */
>   	if (old_ast_crtc_state->format != ast_crtc_state->format)
>   		ast_crtc_load_lut(ast, crtc);
> +
> +	//Set Aspeed Display-Port
> +	if (ast->tx_chip_type == AST_TX_ASTDP)
> +		ast_dp_set_mode(crtc, vbios_mode_info);
>   }
> 
>   static void
> @@ -1527,6 +1552,93 @@ static int ast_dp501_output_init(struct ast_private *ast)
>   	return 0;
>   }
> 
> +/*
> + * ASPEED Display-Port Connector
> + */
> +
> +static int ast_astdp_connector_helper_get_modes(struct drm_connector *connector)
> +{
> +	void *edid;
> +
> +	int succ;
> +	int count;
> +
> +	edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
> +	if (!edid)
> +		goto err_drm_connector_update_edid_property;
> +
> +	succ = ast_astdp_read_edid(connector->dev, edid);
> +	if (succ < 0)
> +		goto err_kfree;
> +
> +	drm_connector_update_edid_property(connector, edid);
> +	count = drm_add_edid_modes(connector, edid);
> +	kfree(edid);
> +
> +	return count;
> +
> +err_kfree:
> +	kfree(edid);
> +err_drm_connector_update_edid_property:
> +	drm_connector_update_edid_property(connector, NULL);
> +	return 0;
> +}
> +
> +static const struct drm_connector_helper_funcs ast_astdp_connector_helper_funcs = {
> +	.get_modes = ast_astdp_connector_helper_get_modes,
> +};
> +
> +static const struct drm_connector_funcs ast_astdp_connector_funcs = {
> +	.reset = drm_atomic_helper_connector_reset,
> +	.fill_modes = drm_helper_probe_single_connector_modes,
> +	.destroy = drm_connector_cleanup,
> +	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> +	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
> +};
> +
> +static int ast_astdp_connector_init(struct drm_device *dev, struct drm_connector *connector)
> +{
> +	int ret;
> +
> +	ret = drm_connector_init(dev, connector, &ast_astdp_connector_funcs,
> +				 DRM_MODE_CONNECTOR_DisplayPort);
> +	if (ret)
> +		return ret;
> +
> +	drm_connector_helper_add(connector, &ast_astdp_connector_helper_funcs);
> +
> +	connector->interlace_allowed = 0;
> +	connector->doublescan_allowed = 0;
> +
> +	connector->polled = DRM_CONNECTOR_POLL_CONNECT;
> +
> +	return 0;
> +}
> +
> +static int ast_astdp_output_init(struct ast_private *ast)
> +{
> +	struct drm_device *dev = &ast->base;
> +	struct drm_crtc *crtc = &ast->crtc;
> +	struct drm_encoder *encoder = &ast->output.astdp.encoder;
> +	struct drm_connector *connector = &ast->output.astdp.connector;
> +	int ret;
> +
> +	ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_TMDS);
> +	if (ret)
> +		return ret;
> +	encoder->possible_crtcs = drm_crtc_mask(crtc);
> +
> +	ret = ast_astdp_connector_init(dev, connector);
> +	if (ret)
> +		return ret;
> +
> +	ret = drm_connector_attach_encoder(connector, encoder);
> +	if (ret)
> +		return ret;
> +
> +	return 0;
> +}
> +
>   /*
>    * Mode config
>    */
> @@ -1563,7 +1675,8 @@ int ast_mode_config_init(struct ast_private *ast)
>   	    ast->chip == AST2200 ||
>   	    ast->chip == AST2300 ||
>   	    ast->chip == AST2400 ||
> -	    ast->chip == AST2500) {
> +	    ast->chip == AST2500 ||
> +	    ast->chip == AST2600) {
>   		dev->mode_config.max_width = 1920;
>   		dev->mode_config.max_height = 2048;
>   	} else {
> @@ -1594,6 +1707,9 @@ int ast_mode_config_init(struct ast_private *ast)
>   	case AST_TX_DP501:
>   		ret = ast_dp501_output_init(ast);
>   		break;
> +	case AST_TX_ASTDP:
> +		ret = ast_astdp_output_init(ast);
> +		break;
>   	}
>   	if (ret)
>   		return ret;
> diff --git a/drivers/gpu/drm/ast/ast_post.c b/drivers/gpu/drm/ast/ast_post.c
> index b5d92f652..0aa9cf0fb 100644
> --- a/drivers/gpu/drm/ast/ast_post.c
> +++ b/drivers/gpu/drm/ast/ast_post.c
> @@ -379,7 +379,9 @@ void ast_post_gpu(struct drm_device *dev)
>   	ast_enable_mmio(dev);
>   	ast_set_def_ext_reg(dev);
> 
> -	if (ast->config_mode == ast_use_p2a) {
> +	if (ast->chip == AST2600) {
> +		ast_dp_launch(dev, 1);
> +	} else if (ast->config_mode == ast_use_p2a) {
>   		if (ast->chip == AST2500)
>   			ast_post_chip_2500(dev);
>   		else if (ast->chip == AST2300 || ast->chip == AST2400)
> 
> base-commit: c54b39a565227538c52ead2349eb17d54aadd6f7
> --
> 2.27.0
> 

-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Ivo Totev

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v4] drm/ast: Create the driver for ASPEED proprietory Display-Port
       [not found]           ` <PSAPR06MB48056FC903142B7F60A3BD388CC39@PSAPR06MB4805.apcprd06.prod.outlook.com>
@ 2022-05-04  9:37             ` Thomas Zimmermann
  2022-05-05  2:41               ` Kuo-Hsiang Chou
  2022-05-10 10:56             ` Thomas Zimmermann
  1 sibling, 1 reply; 21+ messages in thread
From: Thomas Zimmermann @ 2022-05-04  9:37 UTC (permalink / raw)
  To: Kuo-Hsiang Chou, dri-devel, linux-kernel
  Cc: Hungju Huang, airlied, Tommy Huang, airlied, Arc Sung, Luke Chen


[-- Attachment #1.1: Type: text/plain, Size: 40940 bytes --]

Hi

Am 04.05.22 um 10:49 schrieb Kuo-Hsiang Chou:
> Hi Thomas,
> 
> Thanks for your efforts to review this patch.
> 
> Now, I observe a change that after DP unplugged and then the system is 
> unable to get EDID from D-sub connecting.
> 
> The reason seems that TXs are merged into union structure in 
> /drivers/gpu/drm/ast/ast_drv.h 
>   (a59b026419f33040d7d28b8e3b1cea681b9ce7a7 
> <https://cgit.freedesktop.org/drm/drm-misc/commit/?id=a59b026419f33040d7d28b8e3b1cea681b9ce7a7>)

The test system has a DP and a VGA adapter?  We need create two separate 
connectors and encoders in that case.  I'll try to provide a patch in 
the next days.

> 
> Another, do you need the ast2600 EVB to ease verification on "drm/ast" ?

The EVB is an evaluation board?  I'd be happy to have one of these. How 
can I get one?

Best regards
Thomas

> 
> Regards,
> 
>          Kuo-Hsiang Chou
> 
> -----Original Message-----
> From: Thomas Zimmermann [mailto:tzimmermann@suse.de]
> Sent: Wednesday, May 04, 2022 3:28 PM
> To: Kuo-Hsiang Chou <kuohsiang_chou@aspeedtech.com>; 
> dri-devel@lists.freedesktop.org; linux-kernel@vger.kernel.org
> Subject: Re: [PATCH v4] drm/ast: Create the driver for ASPEED 
> proprietory Display-Port
> 
> Hi
> 
> Am 28.04.22 um 09:56 schrieb KuoHsiang Chou:
> 
>> V1:
> 
>> 1. The MCU FW controling ASPEED DP is loaded by BMC boot loader.
> 
>> 2. Driver starts after CR[3:1] == 111b that indicates Tx is ASTDP,
> 
>>     and CRD1[5] has been asserted by BMVC boot loader.
> 
>> 3. EDID is prioritized by DP monitor.
> 
>> 4. DP's EDID has high priority to decide resolution supporting.
> 
>> 
> 
>> V2:
> 
>> Modules description:
> 
>> 1. ASTDP (ASPEED DisplayPort) is controlled by dedicated
> 
>>     AST-MCU (ASPEED propriatary MCU).
> 
>> 2. MCU is looping in charged of HPD, Read EDID, Link Training with
> 
>>     DP sink.
> 
>> 3. ASTDP and AST-MUC reside in BMC (Baseboard Management controller)
> 
>>     addressing-space.
> 
>> 4. ASPEED DRM driver requests MCU to get HPD and EDID by CR-scratched
> 
>>     register.
> 
>> 
> 
>> Booting sequence:
> 
>> 1. Check if TX is ASTDP                                        // ast_dp_launch()
> 
>> 2. Check if DP-MCU FW has loaded                                    // ast_dp_launch()
> 
>> 3. Read EDID                                        // ast_dp_read_edid()
> 
>> 4. Resolution switch                                     // ast_dp_SetOutput()
> 
>> 
> 
>> V3:
> 
>> 1. Remove unneeded semicolon.
> 
>> 2. Apply to git://anongit.freedesktop.org/drm/drm, instead of
> 
>>     git://anongit.freedesktop.org/drm/drm-misc
> 
>> 3. Resolve auto build test WARNINGs on V1 patch.
> 
>> 
> 
>> V4:
> 
>> 1. Sync code-base with kernel 5.17_rc6 2. Remove the define of
> 
>> DPControlPower, because DP chips need to be
> 
>>     powered on to be used.
> 
>> 3. Remove the switches of PHY and Display from EDID procedure.
> 
>> 4. Revise increaing delay to fixed delay, because this version kernel
> 
>>     doesn't detect minitor consistenntly.
> 
>> 5. Create clean-up code used for reset of power state on errors with
> 
>>     -EIO manner.
> 
>> 6. Revise the DP detection by TX type and its DP-FW status during
> 
>>     booting and resume.
> 
>> 7. Correct the CamelCase Style.
> 
>> 8. Use register reading while needing, and remove to hold full
> 
>>     register.
> 
>> 9. Instead of 'u8', revise to 'bool' on swwitch of PHY and video.
> 
>> 10.Correct typo
> 
>> 11.Remove the duplicated copy of TX definition.
> 
>> 12.Use EDID_LENGTH as the constant of 128.
> 
>> 
> 
>> Signed-off-by: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com <mailto:kuohsiang_chou@aspeedtech.com>>
> 
> Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de 
> <mailto:tzimmermann@suse.de>>
> 
> I've meanwhile added your patch to drm-misc-next. It should show up in 
> one of the next kernel releases.  Thanks a lot.
> 
> Best regards
> 
> Thomas
> 
>> ---
> 
>>   drivers/gpu/drm/ast/Makefile   |   2 +-
> 
>>   drivers/gpu/drm/ast/ast_dp.c   | 282 +++++++++++++++++++++++++++++++++
> 
>>   drivers/gpu/drm/ast/ast_drv.h  | 115 ++++++++++++++
> 
>>   drivers/gpu/drm/ast/ast_main.c |   5 +-
> 
>>   drivers/gpu/drm/ast/ast_mode.c | 124 ++++++++++++++-
> 
>>   drivers/gpu/drm/ast/ast_post.c |   4 +-
> 
>>   6 files changed, 524 insertions(+), 8 deletions(-)
> 
>>   create mode 100644 drivers/gpu/drm/ast/ast_dp.c
> 
>> 
> 
>> diff --git a/drivers/gpu/drm/ast/Makefile
> 
>> b/drivers/gpu/drm/ast/Makefile index 21f71160b..5a53ce51f 100644
> 
>> --- a/drivers/gpu/drm/ast/Makefile
> 
>> +++ b/drivers/gpu/drm/ast/Makefile
> 
>> @@ -3,6 +3,6 @@
> 
>>   # Makefile for the drm device driver.  This driver provides support for the
> 
>>   # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
> 
>> 
> 
>> -ast-y := ast_drv.o ast_i2c.o ast_main.o ast_mm.o ast_mode.o
> 
>> ast_post.o ast_dp501.o
> 
>> +ast-y := ast_drv.o ast_i2c.o ast_main.o ast_mm.o ast_mode.o
> 
>> +ast_post.o ast_dp501.o ast_dp.o
> 
>> 
> 
>>   obj-$(CONFIG_DRM_AST) := ast.o
> 
>> diff --git a/drivers/gpu/drm/ast/ast_dp.c
> 
>> b/drivers/gpu/drm/ast/ast_dp.c new file mode 100644 index
> 
>> 000000000..4551bc8a3
> 
>> --- /dev/null
> 
>> +++ b/drivers/gpu/drm/ast/ast_dp.c
> 
>> @@ -0,0 +1,282 @@
> 
>> +// SPDX-License-Identifier: GPL-2.0
> 
>> +// Copyright (c) 2021, ASPEED Technology Inc.
> 
>> +// Authors: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com <mailto:kuohsiang_chou@aspeedtech.com>>
> 
>> +
> 
>> +#include <linux/firmware.h>
> 
>> +#include <linux/delay.h>
> 
>> +#include <drm/drm_print.h>
> 
>> +#include "ast_drv.h"
> 
>> +
> 
>> +int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata) {
> 
>> +   struct ast_private *ast = to_ast_private(dev);
> 
>> +   u8 i = 0, j = 0;
> 
>> +
> 
>> +   /*
> 
>> +   * CRD1[b5]: DP MCU FW is executing
> 
>> +   * CRDC[b0]: DP link success
> 
>> +   * CRDF[b0]: DP HPD
> 
>> +   * CRE5[b0]: Host reading EDID process is done
> 
>> +   */
> 
>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, ASTDP_MCU_FW_EXECUTING) &&
> 
>> +           ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, ASTDP_LINK_SUCCESS) &&
> 
>> +           ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD) &&
> 
>> +           ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
> 
>> +                                                           ASTDP_HOST_EDID_READ_DONE_MASK))) {
> 
>> +           goto err_astdp_edid_not_ready;
> 
>> +   }
> 
>> +
> 
>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
> 
>> +                                                   0x00);
> 
>> +
> 
>> +   for (i = 0; i < 32; i++) {
> 
>> +           /*
> 
>> +           * CRE4[7:0]: Read-Pointer for EDID (Unit: 4bytes); valid range: 0~64
> 
>> +           */
> 
>> +           ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE4,
> 
>> +                                   (u8) ~ASTDP_EDID_READ_POINTER_MASK, (u8) i);
> 
>> +           j = 0;
> 
>> +
> 
>> +           /*
> 
>> +           * CRD7[b0]: valid flag for EDID
> 
>> +           * CRD6[b0]: mirror read pointer for EDID
> 
>> +           */
> 
>> +           while ((ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD7,
> 
>> +                           ASTDP_EDID_VALID_FLAG_MASK) != 0x01) ||
> 
>> +                   (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD6,
> 
>> +                                           ASTDP_EDID_READ_POINTER_MASK) != i)) {
> 
>> +                   /*
> 
>> +                   * Delay are getting longer with each retry.
> 
>> +                   * 1. The Delays are often 2 loops when users request "Display Settings"
> 
>> +                   *      of right-click of mouse.
> 
>> +                   * 2. The Delays are often longer a lot when system resume from S3/S4.
> 
>> +                   */
> 
>> +                   mdelay(j+1);
> 
>> +
> 
>> +                   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1,
> 
>> +                                                   ASTDP_MCU_FW_EXECUTING) &&
> 
>> +                           ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC,
> 
>> +                                                   ASTDP_LINK_SUCCESS) &&
> 
>> +                           ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD))) {
> 
>> +                           goto err_astdp_jump_out_loop_of_edid;
> 
>> +                   }
> 
>> +
> 
>> +                   j++;
> 
>> +                   if (j > 200)
> 
>> +                           goto err_astdp_jump_out_loop_of_edid;
> 
>> +           }
> 
>> +
> 
>> +           *(ediddata) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT,
> 
>> +                                                   0xD8, ASTDP_EDID_READ_DATA_MASK);
> 
>> +           *(ediddata + 1) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD9,
> 
>> +                                                           ASTDP_EDID_READ_DATA_MASK);
> 
>> +           *(ediddata + 2) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDA,
> 
>> +                                                           ASTDP_EDID_READ_DATA_MASK);
> 
>> +           *(ediddata + 3) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDB,
> 
>> +                                                           ASTDP_EDID_READ_DATA_MASK);
> 
>> +
> 
>> +           if (i == 31) {
> 
>> +                   /*
> 
>> +                   * For 128-bytes EDID_1.3,
> 
>> +                   * 1. Add the value of Bytes-126 to Bytes-127.
> 
>> +                   *            The Bytes-127 is Checksum. Sum of all 128bytes should
> 
>> +                   *            equal 0    (mod 256).
> 
>> +                   * 2. Modify Bytes-126 to be 0.
> 
>> +                   *            The Bytes-126 indicates the Number of extensions to
> 
>> +                   *            follow. 0 represents noextensions.
> 
>> +                   */
> 
>> +                   *(ediddata + 3) = *(ediddata + 3) + *(ediddata + 2);
> 
>> +                   *(ediddata + 2) = 0;
> 
>> +           }
> 
>> +
> 
>> +           ediddata += 4;
> 
>> +   }
> 
>> +
> 
>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
> 
>> +                                                   ASTDP_HOST_EDID_READ_DONE);
> 
>> +
> 
>> +   return 0;
> 
>> +
> 
>> +err_astdp_jump_out_loop_of_edid:
> 
>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
> 
>> +                                                   (u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
> 
>> +                                                   ASTDP_HOST_EDID_READ_DONE);
> 
>> +   return (~(j+256) + 1);
> 
>> +
> 
>> +err_astdp_edid_not_ready:
> 
>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, ASTDP_MCU_FW_EXECUTING)))
> 
>> +           return (~0xD1 + 1);
> 
>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, ASTDP_LINK_SUCCESS)))
> 
>> +           return (~0xDC + 1);
> 
>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD)))
> 
>> +           return (~0xDF + 1);
> 
>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, ASTDP_HOST_EDID_READ_DONE_MASK)))
> 
>> +           return (~0xE5 + 1);
> 
>> +
> 
>> +   return      0;
> 
>> +}
> 
>> +
> 
>> +/*
> 
>> + * Launch Aspeed DP
> 
>> + */
> 
>> +void ast_dp_launch(struct drm_device *dev, u8 bPower) {
> 
>> +   u32 i = 0, j = 0, WaitCount = 1;
> 
>> +   u8 bDPTX = 0;
> 
>> +   u8 bDPExecute = 1;
> 
>> +
> 
>> +   struct ast_private *ast = to_ast_private(dev);
> 
>> +   // S3 come back, need more time to wait BMC ready.
> 
>> +   if (bPower)
> 
>> +           WaitCount = 300;
> 
>> +
> 
>> +
> 
>> +   // Wait total count by different condition.
> 
>> +   for (j = 0; j < WaitCount; j++) {
> 
>> +           bDPTX = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1,
> 
>> +TX_TYPE_MASK);
> 
>> +
> 
>> +           if (bDPTX)
> 
>> +                   break;
> 
>> +
> 
>> +           msleep(100);
> 
>> +   }
> 
>> +
> 
>> +   // 0xE : ASTDP with DPMCU FW handling
> 
>> +   if (bDPTX == ASTDP_DPMCU_TX) {
> 
>> +           // Wait one second then timeout.
> 
>> +           i = 0;
> 
>> +
> 
>> +           while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, COPROCESSOR_LAUNCH) !=
> 
>> +                   COPROCESSOR_LAUNCH) {
> 
>> +                   i++;
> 
>> +                   // wait 100 ms
> 
>> +                   msleep(100);
> 
>> +
> 
>> +                   if (i >= 10) {
> 
>> +                           // DP would not be ready.
> 
>> +                           bDPExecute = 0;
> 
>> +                           break;
> 
>> +                   }
> 
>> +           }
> 
>> +
> 
>> +           if (bDPExecute)
> 
>> +                   ast->tx_chip_type = AST_TX_ASTDP;
> 
>> +
> 
>> +           ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
> 
>> +                                                   (u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
> 
>> +                                                   ASTDP_HOST_EDID_READ_DONE);
> 
>> +   } else
> 
>> +           ast->tx_chip_type = AST_TX_NONE;
> 
>> +}
> 
>> +
> 
>> +
> 
>> +
> 
>> +void ast_dp_power_on_off(struct drm_device *dev, bool on) {
> 
>> +   struct ast_private *ast = to_ast_private(dev);
> 
>> +   // Read and Turn off DP PHY sleep
> 
>> +   u8 bE3 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3,
> 
>> +AST_DP_VIDEO_ENABLE);
> 
>> +
> 
>> +   // Turn on DP PHY sleep
> 
>> +   if (!on)
> 
>> +           bE3 |= AST_DP_PHY_SLEEP;
> 
>> +
> 
>> +   // DP Power on/off
> 
>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, (u8)
> 
>> +~AST_DP_PHY_SLEEP, bE3); }
> 
>> +
> 
>> +
> 
>> +
> 
>> +void ast_dp_set_on_off(struct drm_device *dev, bool on) {
> 
>> +   struct ast_private *ast = to_ast_private(dev);
> 
>> +   u8 video_on_off = on;
> 
>> +
> 
>> +   // Video On/Off
> 
>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, (u8)
> 
>> +~AST_DP_VIDEO_ENABLE, on);
> 
>> +
> 
>> +   // If DP plug in and link successful then check video on / off status
> 
>> +   if (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, ASTDP_LINK_SUCCESS) &&
> 
>> +           ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD)) {
> 
>> +           video_on_off <<= 4;
> 
>> +           while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF,
> 
>> +                                           ASTDP_MIRROR_VIDEO_ENABLE) != video_on_off) {
> 
>> +                   // wait 1 ms
> 
>> +                   mdelay(1);
> 
>> +           }
> 
>> +   }
> 
>> +}
> 
>> +
> 
>> +void ast_dp_set_mode(struct drm_crtc *crtc, struct
> 
>> +ast_vbios_mode_info *vbios_mode) {
> 
>> +   struct ast_private *ast = to_ast_private(crtc->dev);
> 
>> +
> 
>> +   u32 ulRefreshRateIndex;
> 
>> +   u8 ModeIdx;
> 
>> +
> 
>> +   ulRefreshRateIndex = vbios_mode->enh_table->refresh_rate_index - 1;
> 
>> +
> 
>> +   switch (crtc->mode.crtc_hdisplay) {
> 
>> +   case 320:
> 
>> +           ModeIdx = ASTDP_320x240_60;
> 
>> +           break;
> 
>> +   case 400:
> 
>> +           ModeIdx = ASTDP_400x300_60;
> 
>> +           break;
> 
>> +   case 512:
> 
>> +           ModeIdx = ASTDP_512x384_60;
> 
>> +           break;
> 
>> +   case 640:
> 
>> +           ModeIdx = (ASTDP_640x480_60 + (u8) ulRefreshRateIndex);
> 
>> +           break;
> 
>> +   case 800:
> 
>> +           ModeIdx = (ASTDP_800x600_56 + (u8) ulRefreshRateIndex);
> 
>> +           break;
> 
>> +   case 1024:
> 
>> +           ModeIdx = (ASTDP_1024x768_60 + (u8) ulRefreshRateIndex);
> 
>> +           break;
> 
>> +   case 1152:
> 
>> +           ModeIdx = ASTDP_1152x864_75;
> 
>> +           break;
> 
>> +   case 1280:
> 
>> +           if (crtc->mode.crtc_vdisplay == 800)
> 
>> +                   ModeIdx = (ASTDP_1280x800_60_RB - (u8) ulRefreshRateIndex);
> 
>> +           else          // 1024
> 
>> +                   ModeIdx = (ASTDP_1280x1024_60 + (u8) ulRefreshRateIndex);
> 
>> +           break;
> 
>> +   case 1360:
> 
>> +   case 1366:
> 
>> +           ModeIdx = ASTDP_1366x768_60;
> 
>> +           break;
> 
>> +   case 1440:
> 
>> +           ModeIdx = (ASTDP_1440x900_60_RB - (u8) ulRefreshRateIndex);
> 
>> +           break;
> 
>> +   case 1600:
> 
>> +           if (crtc->mode.crtc_vdisplay == 900)
> 
>> +                   ModeIdx = (ASTDP_1600x900_60_RB - (u8) ulRefreshRateIndex);
> 
>> +           else          //1200
> 
>> +                   ModeIdx = ASTDP_1600x1200_60;
> 
>> +           break;
> 
>> +   case 1680:
> 
>> +           ModeIdx = (ASTDP_1680x1050_60_RB - (u8) ulRefreshRateIndex);
> 
>> +           break;
> 
>> +   case 1920:
> 
>> +           if (crtc->mode.crtc_vdisplay == 1080)
> 
>> +                   ModeIdx = ASTDP_1920x1080_60;
> 
>> +           else          //1200
> 
>> +                   ModeIdx = ASTDP_1920x1200_60;
> 
>> +           break;
> 
>> +   default:
> 
>> +           return;
> 
>> +   }
> 
>> +
> 
>> +   /*
> 
>> +   * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp)
> 
>> +   * CRE1[7:0]: MISC1 (default: 0x00)
> 
>> +   * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50)
> 
>> +   */
> 
>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE0, (u8) ~ASTDP_CLEAR_MASK,
> 
>> +                           ASTDP_MISC0_24bpp);
> 
>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE1, (u8) ~ASTDP_CLEAR_MASK, ASTDP_MISC1);
> 
>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE2, (u8)
> 
>> +~ASTDP_CLEAR_MASK, ModeIdx); }
> 
>> diff --git a/drivers/gpu/drm/ast/ast_drv.h
> 
>> b/drivers/gpu/drm/ast/ast_drv.h index a19315b2f..ff1ae314b 100644
> 
>> --- a/drivers/gpu/drm/ast/ast_drv.h
> 
>> +++ b/drivers/gpu/drm/ast/ast_drv.h
> 
>> @@ -70,6 +70,7 @@ enum ast_tx_chip {
> 
>>           AST_TX_NONE,
> 
>>           AST_TX_SIL164,
> 
>>           AST_TX_DP501,
> 
>> +   AST_TX_ASTDP,
> 
>>   };
> 
>> 
> 
>>   #define AST_DRAM_512Mx16 0
> 
>> @@ -184,6 +185,10 @@ struct ast_private {
> 
>>                           struct drm_encoder encoder;
> 
>>                           struct drm_connector connector;
> 
>>                   } dp501;
> 
>> +           struct {
> 
>> +                   struct drm_encoder encoder;
> 
>> +                   struct drm_connector connector;
> 
>> +           } astdp;
> 
>>           } output;
> 
>> 
> 
>>           bool support_wide_screen;
> 
>> @@ -357,10 +362,113 @@ int ast_mode_config_init(struct ast_private *ast);
> 
>>   #define AST_DP501_EDID_DATA    0xf020
> 
>> 
> 
>>   /* Define for Soc scratched reg */
> 
>> +#define COPROCESSOR_LAUNCH                     BIT(5)
> 
>> +
> 
>> +/*
> 
>> + * Display Transmitter Type:
> 
>> + */
> 
>> +#define TX_TYPE_MASK                            GENMASK(3, 1)
> 
>> +#define NO_TX                                           (0 << 1)
> 
>> +#define ITE66121_VBIOS_TX                     (1 << 1)
> 
>> +#define SI164_VBIOS_TX                           (2 << 1)
> 
>> +#define CH7003_VBIOS_TX                       (3 << 1)
> 
>> +#define DP501_VBIOS_TX                         (4 << 1)
> 
>> +#define ANX9807_VBIOS_TX                     (5 << 1)
> 
>> +#define TX_FW_EMBEDDED_FW_TX                (6 << 1)
> 
>> +#define ASTDP_DPMCU_TX                               (7 << 1)
> 
>> +
> 
>>   #define AST_VRAM_INIT_STATUS_MASK       GENMASK(7, 6)
> 
>>   //#define AST_VRAM_INIT_BY_BMC             BIT(7)
> 
>>   //#define AST_VRAM_INIT_READY                BIT(6)
> 
>> 
> 
>> +/* Define for Soc scratched reg used on ASTDP */
> 
>> +#define AST_DP_PHY_SLEEP                     BIT(4)
> 
>> +#define AST_DP_VIDEO_ENABLE              BIT(0)
> 
>> +
> 
>> +#define AST_DP_POWER_ON                    true
> 
>> +#define AST_DP_POWER_OFF                   false
> 
>> +
> 
>> +/*
> 
>> + * CRD1[b5]: DP MCU FW is executing
> 
>> + * CRDC[b0]: DP link success
> 
>> + * CRDF[b0]: DP HPD
> 
>> + * CRE5[b0]: Host reading EDID process is done  */
> 
>> +#define ASTDP_MCU_FW_EXECUTING                     BIT(5)
> 
>> +#define ASTDP_LINK_SUCCESS                          BIT(0)
> 
>> +#define ASTDP_HPD                                          BIT(0)
> 
>> +#define ASTDP_HOST_EDID_READ_DONE                BIT(0)
> 
>> +#define ASTDP_HOST_EDID_READ_DONE_MASK    GENMASK(0, 0)
> 
>> +
> 
>> +/*
> 
>> + * CRB8[b1]: Enable VSYNC off
> 
>> + * CRB8[b0]: Enable HSYNC off
> 
>> + */
> 
>> +#define AST_DPMS_VSYNC_OFF                               BIT(1)
> 
>> +#define AST_DPMS_HSYNC_OFF                               BIT(0)
> 
>> +
> 
>> +/*
> 
>> + * CRDF[b4]: Mirror of AST_DP_VIDEO_ENABLE
> 
>> + * Precondition:  A. ~AST_DP_PHY_SLEEP  &&
> 
>> + *                        B. DP_HPD &&
> 
>> + *                        C. DP_LINK_SUCCESS
> 
>> + */
> 
>> +#define ASTDP_MIRROR_VIDEO_ENABLE                BIT(4)
> 
>> +
> 
>> +#define ASTDP_EDID_READ_POINTER_MASK  GENMASK(7, 0)
> 
>> +#define ASTDP_EDID_VALID_FLAG_MASK                GENMASK(0, 0)
> 
>> +#define ASTDP_EDID_READ_DATA_MASK        GENMASK(7, 0)
> 
>> +
> 
>> +/*
> 
>> + * ASTDP setmode registers:
> 
>> + * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp)
> 
>> + * CRE1[7:0]: MISC1 (default: 0x00)
> 
>> + * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50)  */
> 
>> +#define ASTDP_MISC0_24bpp                   BIT(5)
> 
>> +#define ASTDP_MISC1                               0
> 
>> +#define ASTDP_CLEAR_MASK                   GENMASK(7, 0)
> 
>> +
> 
>> +/*
> 
>> + * ASTDP resoultion table:
> 
>> + * EX:  ASTDP_A_B_C:
> 
>> + *                A: Resolution
> 
>> + *                B: Refresh Rate
> 
>> + *                C: Misc information, such as CVT, Reduce Blanked
> 
>> + */
> 
>> +#define ASTDP_640x480_60              0x00
> 
>> +#define ASTDP_640x480_72              0x01
> 
>> +#define ASTDP_640x480_75              0x02
> 
>> +#define ASTDP_640x480_85              0x03
> 
>> +#define ASTDP_800x600_56              0x04
> 
>> +#define ASTDP_800x600_60              0x05
> 
>> +#define ASTDP_800x600_72              0x06
> 
>> +#define ASTDP_800x600_75              0x07
> 
>> +#define ASTDP_800x600_85              0x08
> 
>> +#define ASTDP_1024x768_60            0x09
> 
>> +#define ASTDP_1024x768_70            0x0A
> 
>> +#define ASTDP_1024x768_75            0x0B
> 
>> +#define ASTDP_1024x768_85            0x0C
> 
>> +#define ASTDP_1280x1024_60          0x0D
> 
>> +#define ASTDP_1280x1024_75          0x0E
> 
>> +#define ASTDP_1280x1024_85          0x0F
> 
>> +#define ASTDP_1600x1200_60          0x10
> 
>> +#define ASTDP_320x240_60              0x11
> 
>> +#define ASTDP_400x300_60              0x12
> 
>> +#define ASTDP_512x384_60              0x13
> 
>> +#define ASTDP_1920x1200_60          0x14
> 
>> +#define ASTDP_1920x1080_60          0x15
> 
>> +#define ASTDP_1280x800_60            0x16
> 
>> +#define ASTDP_1280x800_60_RB     0x17
> 
>> +#define ASTDP_1440x900_60            0x18
> 
>> +#define ASTDP_1440x900_60_RB     0x19
> 
>> +#define ASTDP_1680x1050_60          0x1A
> 
>> +#define ASTDP_1680x1050_60_RB   0x1B
> 
>> +#define ASTDP_1600x900_60            0x1C
> 
>> +#define ASTDP_1600x900_60_RB     0x1D
> 
>> +#define ASTDP_1366x768_60            0x1E
> 
>> +#define ASTDP_1152x864_75            0x1F
> 
>> +
> 
>>   int ast_mm_init(struct ast_private *ast);
> 
>> 
> 
>>   /* ast post */
> 
>> @@ -381,4 +489,11 @@ void ast_init_3rdtx(struct drm_device *dev);
> 
>>   /* ast_i2c.c */
> 
>>   struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev);
> 
>> 
> 
>> +/* aspeed DP */
> 
>> +int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata); void
> 
>> +ast_dp_launch(struct drm_device *dev, u8 bPower); void
> 
>> +ast_dp_power_on_off(struct drm_device *dev, bool no); void
> 
>> +ast_dp_set_on_off(struct drm_device *dev, bool no); void
> 
>> +ast_dp_set_mode(struct drm_crtc *crtc, struct ast_vbios_mode_info
> 
>> +*vbios_mode);
> 
>> +
> 
>>   #endif
> 
>> diff --git a/drivers/gpu/drm/ast/ast_main.c
> 
>> b/drivers/gpu/drm/ast/ast_main.c index 22e9e2d3c..1113ee1cb 100644
> 
>> --- a/drivers/gpu/drm/ast/ast_main.c
> 
>> +++ b/drivers/gpu/drm/ast/ast_main.c
> 
>> @@ -232,7 +232,7 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
> 
>>                           ast->tx_chip_type = AST_TX_SIL164;
> 
>>           }
> 
>> 
> 
>> -    if ((ast->chip == AST2300) || (ast->chip == AST2400)) {
> 
>> +   if ((ast->chip == AST2300) || (ast->chip == AST2400) || (ast->chip
> 
>> +== AST2500)) {
> 
>>                   /*
> 
>>                    * On AST2300 and 2400, look the configuration set by the SoC in
> 
>>                    * the SOC scratch register #1 bits 11:8 (interestingly marked @@
> 
>> -256,7 +256,8 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
> 
>>                   case 0x0c:
> 
>>                           ast->tx_chip_type = AST_TX_DP501;
> 
>>                   }
> 
>> -    }
> 
>> +   } else if (ast->chip == AST2600)
> 
>> +           ast_dp_launch(&ast->base, 0);
> 
>> 
> 
>>           /* Print stuff for diagnostic purposes */
> 
>>           switch(ast->tx_chip_type) {
> 
>> diff --git a/drivers/gpu/drm/ast/ast_mode.c
> 
>> b/drivers/gpu/drm/ast/ast_mode.c index 45b56b39a..4728825b7 100644
> 
>> --- a/drivers/gpu/drm/ast/ast_mode.c
> 
>> +++ b/drivers/gpu/drm/ast/ast_mode.c
> 
>> @@ -988,21 +988,41 @@ static int ast_cursor_plane_init(struct ast_private *ast)
> 
>>   static void ast_crtc_dpms(struct drm_crtc *crtc, int mode)
> 
>>   {
> 
>>           struct ast_private *ast = to_ast_private(crtc->dev);
> 
>> +   u8 ch = AST_DPMS_VSYNC_OFF | AST_DPMS_HSYNC_OFF;
> 
>> 
> 
>>           /* TODO: Maybe control display signal generation with
> 
>>            *       Sync Enable (bit CR17.7).
> 
>>            */
> 
>>           switch (mode) {
> 
>>           case DRM_MODE_DPMS_ON:
> 
>> -    case DRM_MODE_DPMS_STANDBY:
> 
>> -    case DRM_MODE_DPMS_SUSPEND:
> 
>> +           ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT,  0x01, 0xdf, 0);
> 
>> +           ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, 0);
> 
>>                   if (ast->tx_chip_type == AST_TX_DP501)
> 
>>                           ast_set_dp501_video_output(crtc->dev, 1);
> 
>> +
> 
>> +           if (ast->tx_chip_type == AST_TX_ASTDP) {
> 
>> +                   ast_dp_power_on_off(crtc->dev, AST_DP_POWER_ON);
> 
>> +                   ast_wait_for_vretrace(ast);
> 
>> +                   ast_dp_set_on_off(crtc->dev, 1);
> 
>> +           }
> 
>> +
> 
>> +           ast_crtc_load_lut(ast, crtc);
> 
>>                   break;
> 
>> +   case DRM_MODE_DPMS_STANDBY:
> 
>> +   case DRM_MODE_DPMS_SUSPEND:
> 
>>           case DRM_MODE_DPMS_OFF:
> 
>> +           ch = mode;
> 
>>                   if (ast->tx_chip_type == AST_TX_DP501)
> 
>>                           ast_set_dp501_video_output(crtc->dev, 0);
> 
>>                   break;
> 
>> +
> 
>> +           if (ast->tx_chip_type == AST_TX_ASTDP) {
> 
>> +                   ast_dp_set_on_off(crtc->dev, 0);
> 
>> +                   ast_dp_power_on_off(crtc->dev, AST_DP_POWER_OFF);
> 
>> +           }
> 
>> +
> 
>> +           ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT,  0x01, 0xdf, 0x20);
> 
>> +           ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, ch);
> 
>>           }
> 
>>   }
> 
>> 
> 
>> @@ -1027,7 +1047,7 @@ ast_crtc_helper_mode_valid(struct drm_crtc
> 
>> *crtc, const struct drm_display_mode
> 
>> 
> 
>>                   if ((ast->chip == AST2100) || (ast->chip == AST2200) ||
> 
>>                       (ast->chip == AST2300) || (ast->chip == AST2400) ||
> 
>> -                (ast->chip == AST2500)) {
> 
>> +               (ast->chip == AST2500) || (ast->chip == AST2600)) {
> 
>>                           if ((mode->hdisplay == 1920) && (mode->vdisplay == 1080))
> 
>>                                   return MODE_OK;
> 
>> 
> 
>> @@ -1110,6 +1130,7 @@ ast_crtc_helper_atomic_flush(struct drm_crtc *crtc,
> 
>>           struct ast_private *ast = to_ast_private(crtc->dev);
> 
>>           struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
> 
>>           struct ast_crtc_state *old_ast_crtc_state =
> 
>> to_ast_crtc_state(old_crtc_state);
> 
>> +   struct ast_vbios_mode_info *vbios_mode_info =
> 
>> +&ast_crtc_state->vbios_mode_info;
> 
>> 
> 
>>           /*
> 
>>            * The gamma LUT has to be reloaded after changing the primary @@
> 
>> -1117,6 +1138,10 @@ ast_crtc_helper_atomic_flush(struct drm_crtc *crtc,
> 
>>            */
> 
>>           if (old_ast_crtc_state->format != ast_crtc_state->format)
> 
>>                   ast_crtc_load_lut(ast, crtc);
> 
>> +
> 
>> +   //Set Aspeed Display-Port
> 
>> +   if (ast->tx_chip_type == AST_TX_ASTDP)
> 
>> +           ast_dp_set_mode(crtc, vbios_mode_info);
> 
>>   }
> 
>> 
> 
>>   static void
> 
>> @@ -1527,6 +1552,93 @@ static int ast_dp501_output_init(struct ast_private *ast)
> 
>>           return 0;
> 
>>   }
> 
>> 
> 
>> +/*
> 
>> + * ASPEED Display-Port Connector
> 
>> + */
> 
>> +
> 
>> +static int ast_astdp_connector_helper_get_modes(struct drm_connector
> 
>> +*connector) {
> 
>> +   void *edid;
> 
>> +
> 
>> +   int succ;
> 
>> +   int count;
> 
>> +
> 
>> +   edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
> 
>> +   if (!edid)
> 
>> +           goto err_drm_connector_update_edid_property;
> 
>> +
> 
>> +   succ = ast_astdp_read_edid(connector->dev, edid);
> 
>> +   if (succ < 0)
> 
>> +           goto err_kfree;
> 
>> +
> 
>> +   drm_connector_update_edid_property(connector, edid);
> 
>> +   count = drm_add_edid_modes(connector, edid);
> 
>> +   kfree(edid);
> 
>> +
> 
>> +   return count;
> 
>> +
> 
>> +err_kfree:
> 
>> +   kfree(edid);
> 
>> +err_drm_connector_update_edid_property:
> 
>> +   drm_connector_update_edid_property(connector, NULL);
> 
>> +   return 0;
> 
>> +}
> 
>> +
> 
>> +static const struct drm_connector_helper_funcs ast_astdp_connector_helper_funcs = {
> 
>> +   .get_modes = ast_astdp_connector_helper_get_modes,
> 
>> +};
> 
>> +
> 
>> +static const struct drm_connector_funcs ast_astdp_connector_funcs = {
> 
>> +   .reset = drm_atomic_helper_connector_reset,
> 
>> +   .fill_modes = drm_helper_probe_single_connector_modes,
> 
>> +   .destroy = drm_connector_cleanup,
> 
>> +   .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> 
>> +   .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
> 
>> +};
> 
>> +
> 
>> +static int ast_astdp_connector_init(struct drm_device *dev, struct
> 
>> +drm_connector *connector) {
> 
>> +   int ret;
> 
>> +
> 
>> +   ret = drm_connector_init(dev, connector, &ast_astdp_connector_funcs,
> 
>> +                           DRM_MODE_CONNECTOR_DisplayPort);
> 
>> +   if (ret)
> 
>> +           return ret;
> 
>> +
> 
>> +   drm_connector_helper_add(connector,
> 
>> +&ast_astdp_connector_helper_funcs);
> 
>> +
> 
>> +   connector->interlace_allowed = 0;
> 
>> +   connector->doublescan_allowed = 0;
> 
>> +
> 
>> +   connector->polled = DRM_CONNECTOR_POLL_CONNECT;
> 
>> +
> 
>> +   return 0;
> 
>> +}
> 
>> +
> 
>> +static int ast_astdp_output_init(struct ast_private *ast) {
> 
>> +   struct drm_device *dev = &ast->base;
> 
>> +   struct drm_crtc *crtc = &ast->crtc;
> 
>> +   struct drm_encoder *encoder = &ast->output.astdp.encoder;
> 
>> +   struct drm_connector *connector = &ast->output.astdp.connector;
> 
>> +   int ret;
> 
>> +
> 
>> +   ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_TMDS);
> 
>> +   if (ret)
> 
>> +           return ret;
> 
>> +   encoder->possible_crtcs = drm_crtc_mask(crtc);
> 
>> +
> 
>> +   ret = ast_astdp_connector_init(dev, connector);
> 
>> +   if (ret)
> 
>> +           return ret;
> 
>> +
> 
>> +   ret = drm_connector_attach_encoder(connector, encoder);
> 
>> +   if (ret)
> 
>> +           return ret;
> 
>> +
> 
>> +   return 0;
> 
>> +}
> 
>> +
> 
>>   /*
> 
>>    * Mode config
> 
>>    */
> 
>> @@ -1563,7 +1675,8 @@ int ast_mode_config_init(struct ast_private *ast)
> 
>>               ast->chip == AST2200 ||
> 
>>               ast->chip == AST2300 ||
> 
>>               ast->chip == AST2400 ||
> 
>> -        ast->chip == AST2500) {
> 
>> +       ast->chip == AST2500 ||
> 
>> +       ast->chip == AST2600) {
> 
>>                   dev->mode_config.max_width = 1920;
> 
>>                   dev->mode_config.max_height = 2048;
> 
>>           } else {
> 
>> @@ -1594,6 +1707,9 @@ int ast_mode_config_init(struct ast_private *ast)
> 
>>           case AST_TX_DP501:
> 
>>                   ret = ast_dp501_output_init(ast);
> 
>>                   break;
> 
>> +   case AST_TX_ASTDP:
> 
>> +           ret = ast_astdp_output_init(ast);
> 
>> +           break;
> 
>>           }
> 
>>           if (ret)
> 
>>                   return ret;
> 
>> diff --git a/drivers/gpu/drm/ast/ast_post.c
> 
>> b/drivers/gpu/drm/ast/ast_post.c index b5d92f652..0aa9cf0fb 100644
> 
>> --- a/drivers/gpu/drm/ast/ast_post.c
> 
>> +++ b/drivers/gpu/drm/ast/ast_post.c
> 
>> @@ -379,7 +379,9 @@ void ast_post_gpu(struct drm_device *dev)
> 
>>           ast_enable_mmio(dev);
> 
>>           ast_set_def_ext_reg(dev);
> 
>> 
> 
>> -    if (ast->config_mode == ast_use_p2a) {
> 
>> +   if (ast->chip == AST2600) {
> 
>> +           ast_dp_launch(dev, 1);
> 
>> +   } else if (ast->config_mode == ast_use_p2a) {
> 
>>                   if (ast->chip == AST2500)
> 
>>                           ast_post_chip_2500(dev);
> 
>>                   else if (ast->chip == AST2300 || ast->chip == AST2400)
> 
>> 
> 
>> base-commit: c54b39a565227538c52ead2349eb17d54aadd6f7
> 
>> --
> 
>> 2.27.0
> 
>> 
> 
> --
> 
> Thomas Zimmermann
> 
> Graphics Driver Developer
> 
> SUSE Software Solutions Germany GmbH
> 
> Maxfeldstr. 5, 90409 Nürnberg, Germany
> 
> (HRB 36809, AG Nürnberg)
> 
> Geschäftsführer: Ivo Totev
> 

-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Ivo Totev

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 21+ messages in thread

* RE: [PATCH v4] drm/ast: Create the driver for ASPEED proprietory Display-Port
  2022-05-04  9:37             ` Thomas Zimmermann
@ 2022-05-05  2:41               ` Kuo-Hsiang Chou
  2022-05-05  2:51                 ` Luke Chen
  0 siblings, 1 reply; 21+ messages in thread
From: Kuo-Hsiang Chou @ 2022-05-05  2:41 UTC (permalink / raw)
  To: Thomas Zimmermann, dri-devel, linux-kernel
  Cc: Hungju Huang, airlied, Tommy Huang, airlied, Arc Sung, Luke Chen

Hi Luke,

Please help on the EVB request that DRM reviewer, Thomas, needs one AST2600 EVB to ease Display-Port verification on ASPEED DRM diver. 
Thanks

Regards,
	Kuo-Hsiang Chou

-----Original Message-----
From: Thomas Zimmermann [mailto:tzimmermann@suse.de] 
Sent: Wednesday, May 04, 2022 5:38 PM
To: Kuo-Hsiang Chou <kuohsiang_chou@aspeedtech.com>; dri-devel@lists.freedesktop.org; linux-kernel@vger.kernel.org
Subject: Re: [PATCH v4] drm/ast: Create the driver for ASPEED proprietory Display-Port

Hi Thomas,

Hi

Am 04.05.22 um 10:49 schrieb Kuo-Hsiang Chou:
> Hi Thomas,
> 
> Thanks for your efforts to review this patch.
> 
> Now, I observe a change that after DP unplugged and then the system is 
> unable to get EDID from D-sub connecting.
> 
> The reason seems that TXs are merged into union structure in 
> /drivers/gpu/drm/ast/ast_drv.h
>   (a59b026419f33040d7d28b8e3b1cea681b9ce7a7
> <https://cgit.freedesktop.org/drm/drm-misc/commit/?id=a59b026419f33040
> d7d28b8e3b1cea681b9ce7a7>)

The test system has a DP and a VGA adapter?  We need create two separate connectors and encoders in that case.  I'll try to provide a patch in the next days.

Yes, the same content are displayed (as mirror mode) on DP and VGA monitor as same time.

In previous drm/ast version, the EDID read from DP is first priority for resolution validation.
If DP is detected as un-connected, and then reading EDID from VGA is used for the second run of resolution validation.
Finally, if both DP and VGA are detected as un-connected, only 1024*768 and 800*600 are able to be selected as default resolution.

> 
> Another, do you need the ast2600 EVB to ease verification on "drm/ast" ?

The EVB is an evaluation board? 
Yes. the EVB is developed to clarify the differences between custom's CRB.
The EVB is connect to Host by PCI-e 1-Lane adapter.

I'd be happy to have one of these. How can I get one?
I forward the request to ASPEED VP about EVB delivery to you.

Best regards
Thomas

> 
> Regards,
> 
>          Kuo-Hsiang Chou
> 
> -----Original Message-----
> From: Thomas Zimmermann [mailto:tzimmermann@suse.de]
> Sent: Wednesday, May 04, 2022 3:28 PM
> To: Kuo-Hsiang Chou <kuohsiang_chou@aspeedtech.com>; 
> dri-devel@lists.freedesktop.org; linux-kernel@vger.kernel.org
> Subject: Re: [PATCH v4] drm/ast: Create the driver for ASPEED 
> proprietory Display-Port
> 
> Hi
> 
> Am 28.04.22 um 09:56 schrieb KuoHsiang Chou:
> 
>> V1:
> 
>> 1. The MCU FW controling ASPEED DP is loaded by BMC boot loader.
> 
>> 2. Driver starts after CR[3:1] == 111b that indicates Tx is ASTDP,
> 
>>     and CRD1[5] has been asserted by BMVC boot loader.
> 
>> 3. EDID is prioritized by DP monitor.
> 
>> 4. DP's EDID has high priority to decide resolution supporting.
> 
>> 
> 
>> V2:
> 
>> Modules description:
> 
>> 1. ASTDP (ASPEED DisplayPort) is controlled by dedicated
> 
>>     AST-MCU (ASPEED propriatary MCU).
> 
>> 2. MCU is looping in charged of HPD, Read EDID, Link Training with
> 
>>     DP sink.
> 
>> 3. ASTDP and AST-MUC reside in BMC (Baseboard Management controller)
> 
>>     addressing-space.
> 
>> 4. ASPEED DRM driver requests MCU to get HPD and EDID by CR-scratched
> 
>>     register.
> 
>> 
> 
>> Booting sequence:
> 
>> 1. Check if TX is ASTDP                                        // 
>> ast_dp_launch()
> 
>> 2. Check if DP-MCU FW has loaded                                    
>> // ast_dp_launch()
> 
>> 3. Read EDID                                        // 
>> ast_dp_read_edid()
> 
>> 4. Resolution switch                                     // 
>> ast_dp_SetOutput()
> 
>> 
> 
>> V3:
> 
>> 1. Remove unneeded semicolon.
> 
>> 2. Apply to git://anongit.freedesktop.org/drm/drm, instead of
> 
>>     git://anongit.freedesktop.org/drm/drm-misc
> 
>> 3. Resolve auto build test WARNINGs on V1 patch.
> 
>> 
> 
>> V4:
> 
>> 1. Sync code-base with kernel 5.17_rc6 2. Remove the define of
> 
>> DPControlPower, because DP chips need to be
> 
>>     powered on to be used.
> 
>> 3. Remove the switches of PHY and Display from EDID procedure.
> 
>> 4. Revise increaing delay to fixed delay, because this version kernel
> 
>>     doesn't detect minitor consistenntly.
> 
>> 5. Create clean-up code used for reset of power state on errors with
> 
>>     -EIO manner.
> 
>> 6. Revise the DP detection by TX type and its DP-FW status during
> 
>>     booting and resume.
> 
>> 7. Correct the CamelCase Style.
> 
>> 8. Use register reading while needing, and remove to hold full
> 
>>     register.
> 
>> 9. Instead of 'u8', revise to 'bool' on swwitch of PHY and video.
> 
>> 10.Correct typo
> 
>> 11.Remove the duplicated copy of TX definition.
> 
>> 12.Use EDID_LENGTH as the constant of 128.
> 
>> 
> 
>> Signed-off-by: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com 
>> <mailto:kuohsiang_chou@aspeedtech.com>>
> 
> Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de 
> <mailto:tzimmermann@suse.de>>
> 
> I've meanwhile added your patch to drm-misc-next. It should show up in 
> one of the next kernel releases.  Thanks a lot.
> 
> Best regards
> 
> Thomas
> 
>> ---
> 
>>   drivers/gpu/drm/ast/Makefile   |   2 +-
> 
>>   drivers/gpu/drm/ast/ast_dp.c   | 282 
>>+++++++++++++++++++++++++++++++++
> 
>>   drivers/gpu/drm/ast/ast_drv.h  | 115 ++++++++++++++
> 
>>   drivers/gpu/drm/ast/ast_main.c |   5 +-
> 
>>   drivers/gpu/drm/ast/ast_mode.c | 124 ++++++++++++++-
> 
>>   drivers/gpu/drm/ast/ast_post.c |   4 +-
> 
>>   6 files changed, 524 insertions(+), 8 deletions(-)
> 
>>   create mode 100644 drivers/gpu/drm/ast/ast_dp.c
> 
>> 
> 
>> diff --git a/drivers/gpu/drm/ast/Makefile
> 
>> b/drivers/gpu/drm/ast/Makefile index 21f71160b..5a53ce51f 100644
> 
>> --- a/drivers/gpu/drm/ast/Makefile
> 
>> +++ b/drivers/gpu/drm/ast/Makefile
> 
>> @@ -3,6 +3,6 @@
> 
>>   # Makefile for the drm device driver.  This driver provides support 
>>for the
> 
>>   # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
> 
>> 
> 
>> -ast-y := ast_drv.o ast_i2c.o ast_main.o ast_mm.o ast_mode.o
> 
>> ast_post.o ast_dp501.o
> 
>> +ast-y := ast_drv.o ast_i2c.o ast_main.o ast_mm.o ast_mode.o
> 
>> +ast_post.o ast_dp501.o ast_dp.o
> 
>> 
> 
>>   obj-$(CONFIG_DRM_AST) := ast.o
> 
>> diff --git a/drivers/gpu/drm/ast/ast_dp.c
> 
>> b/drivers/gpu/drm/ast/ast_dp.c new file mode 100644 index
> 
>> 000000000..4551bc8a3
> 
>> --- /dev/null
> 
>> +++ b/drivers/gpu/drm/ast/ast_dp.c
> 
>> @@ -0,0 +1,282 @@
> 
>> +// SPDX-License-Identifier: GPL-2.0
> 
>> +// Copyright (c) 2021, ASPEED Technology Inc.
> 
>> +// Authors: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com 
>> +<mailto:kuohsiang_chou@aspeedtech.com>>
> 
>> +
> 
>> +#include <linux/firmware.h>
> 
>> +#include <linux/delay.h>
> 
>> +#include <drm/drm_print.h>
> 
>> +#include "ast_drv.h"
> 
>> +
> 
>> +int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata) {
> 
>> +   struct ast_private *ast = to_ast_private(dev);
> 
>> +   u8 i = 0, j = 0;
> 
>> +
> 
>> +   /*
> 
>> +   * CRD1[b5]: DP MCU FW is executing
> 
>> +   * CRDC[b0]: DP link success
> 
>> +   * CRDF[b0]: DP HPD
> 
>> +   * CRE5[b0]: Host reading EDID process is done
> 
>> +   */
> 
>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, 
>> +ASTDP_MCU_FW_EXECUTING) &&
> 
>> +           ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, 
>> +ASTDP_LINK_SUCCESS) &&
> 
>> +           ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, 
>> +ASTDP_HPD) &&
> 
>> +           ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
> 
>> +                                                           
>> +ASTDP_HOST_EDID_READ_DONE_MASK))) {
> 
>> +           goto err_astdp_edid_not_ready;
> 
>> +   }
> 
>> +
> 
>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8) 
>> +~ASTDP_HOST_EDID_READ_DONE_MASK,
> 
>> +                                                   0x00);
> 
>> +
> 
>> +   for (i = 0; i < 32; i++) {
> 
>> +           /*
> 
>> +           * CRE4[7:0]: Read-Pointer for EDID (Unit: 4bytes); valid 
>> +range: 0~64
> 
>> +           */
> 
>> +           ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE4,
> 
>> +                                   (u8) 
>> +~ASTDP_EDID_READ_POINTER_MASK, (u8) i);
> 
>> +           j = 0;
> 
>> +
> 
>> +           /*
> 
>> +           * CRD7[b0]: valid flag for EDID
> 
>> +           * CRD6[b0]: mirror read pointer for EDID
> 
>> +           */
> 
>> +           while ((ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 
>> +0xD7,
> 
>> +                           ASTDP_EDID_VALID_FLAG_MASK) != 0x01) ||
> 
>> +                   (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 
>> +0xD6,
> 
>> +                                           
>> +ASTDP_EDID_READ_POINTER_MASK) != i)) {
> 
>> +                   /*
> 
>> +                   * Delay are getting longer with each retry.
> 
>> +                   * 1. The Delays are often 2 loops when users request "Display Settings"
> 
>> +                   *      of right-click of mouse.
> 
>> +                   * 2. The Delays are often longer a lot when system resume from S3/S4.
> 
>> +                   */
> 
>> +                   mdelay(j+1);
> 
>> +
> 
>> +                   if (!(ast_get_index_reg_mask(ast, 
>> +AST_IO_CRTC_PORT, 0xD1,
> 
>> +                                                   
>> +ASTDP_MCU_FW_EXECUTING) &&
> 
>> +                           ast_get_index_reg_mask(ast, 
>> +AST_IO_CRTC_PORT, 0xDC,
> 
>> +                                                   
>> +ASTDP_LINK_SUCCESS) &&
> 
>> +                           ast_get_index_reg_mask(ast, 
>> +AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD))) {
> 
>> +                           goto err_astdp_jump_out_loop_of_edid;
> 
>> +                   }
> 
>> +
> 
>> +                   j++;
> 
>> +                   if (j > 200)
> 
>> +                           goto err_astdp_jump_out_loop_of_edid;
> 
>> +           }
> 
>> +
> 
>> +           *(ediddata) = ast_get_index_reg_mask(ast, 
>> +AST_IO_CRTC_PORT,
> 
>> +                                                   0xD8, 
>> +ASTDP_EDID_READ_DATA_MASK);
> 
>> +           *(ediddata + 1) = ast_get_index_reg_mask(ast, 
>> +AST_IO_CRTC_PORT, 0xD9,
> 
>> +                                                           
>> +ASTDP_EDID_READ_DATA_MASK);
> 
>> +           *(ediddata + 2) = ast_get_index_reg_mask(ast, 
>> +AST_IO_CRTC_PORT, 0xDA,
> 
>> +                                                           
>> +ASTDP_EDID_READ_DATA_MASK);
> 
>> +           *(ediddata + 3) = ast_get_index_reg_mask(ast, 
>> +AST_IO_CRTC_PORT, 0xDB,
> 
>> +                                                           
>> +ASTDP_EDID_READ_DATA_MASK);
> 
>> +
> 
>> +           if (i == 31) {
> 
>> +                   /*
> 
>> +                   * For 128-bytes EDID_1.3,
> 
>> +                   * 1. Add the value of Bytes-126 to Bytes-127.
> 
>> +                   *            The Bytes-127 is Checksum. Sum of 
>> +all 128bytes should
> 
>> +                   *            equal 0    (mod 256).
> 
>> +                   * 2. Modify Bytes-126 to be 0.
> 
>> +                   *            The Bytes-126 indicates the Number 
>> +of extensions to
> 
>> +                   *            follow. 0 represents noextensions.
> 
>> +                   */
> 
>> +                   *(ediddata + 3) = *(ediddata + 3) + *(ediddata + 
>> +2);
> 
>> +                   *(ediddata + 2) = 0;
> 
>> +           }
> 
>> +
> 
>> +           ediddata += 4;
> 
>> +   }
> 
>> +
> 
>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8) 
>> +~ASTDP_HOST_EDID_READ_DONE_MASK,
> 
>> +                                                   
>> +ASTDP_HOST_EDID_READ_DONE);
> 
>> +
> 
>> +   return 0;
> 
>> +
> 
>> +err_astdp_jump_out_loop_of_edid:
> 
>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
> 
>> +                                                   (u8) 
>> +~ASTDP_HOST_EDID_READ_DONE_MASK,
> 
>> +                                                   
>> +ASTDP_HOST_EDID_READ_DONE);
> 
>> +   return (~(j+256) + 1);
> 
>> +
> 
>> +err_astdp_edid_not_ready:
> 
>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, 
>> +ASTDP_MCU_FW_EXECUTING)))
> 
>> +           return (~0xD1 + 1);
> 
>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, 
>> +ASTDP_LINK_SUCCESS)))
> 
>> +           return (~0xDC + 1);
> 
>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, 
>> +ASTDP_HPD)))
> 
>> +           return (~0xDF + 1);
> 
>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, 
>> +ASTDP_HOST_EDID_READ_DONE_MASK)))
> 
>> +           return (~0xE5 + 1);
> 
>> +
> 
>> +   return      0;
> 
>> +}
> 
>> +
> 
>> +/*
> 
>> + * Launch Aspeed DP
> 
>> + */
> 
>> +void ast_dp_launch(struct drm_device *dev, u8 bPower) {
> 
>> +   u32 i = 0, j = 0, WaitCount = 1;
> 
>> +   u8 bDPTX = 0;
> 
>> +   u8 bDPExecute = 1;
> 
>> +
> 
>> +   struct ast_private *ast = to_ast_private(dev);
> 
>> +   // S3 come back, need more time to wait BMC ready.
> 
>> +   if (bPower)
> 
>> +           WaitCount = 300;
> 
>> +
> 
>> +
> 
>> +   // Wait total count by different condition.
> 
>> +   for (j = 0; j < WaitCount; j++) {
> 
>> +           bDPTX = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 
>> +0xD1,
> 
>> +TX_TYPE_MASK);
> 
>> +
> 
>> +           if (bDPTX)
> 
>> +                   break;
> 
>> +
> 
>> +           msleep(100);
> 
>> +   }
> 
>> +
> 
>> +   // 0xE : ASTDP with DPMCU FW handling
> 
>> +   if (bDPTX == ASTDP_DPMCU_TX) {
> 
>> +           // Wait one second then timeout.
> 
>> +           i = 0;
> 
>> +
> 
>> +           while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 
>> +0xD1, COPROCESSOR_LAUNCH) !=
> 
>> +                   COPROCESSOR_LAUNCH) {
> 
>> +                   i++;
> 
>> +                   // wait 100 ms
> 
>> +                   msleep(100);
> 
>> +
> 
>> +                   if (i >= 10) {
> 
>> +                           // DP would not be ready.
> 
>> +                           bDPExecute = 0;
> 
>> +                           break;
> 
>> +                   }
> 
>> +           }
> 
>> +
> 
>> +           if (bDPExecute)
> 
>> +                   ast->tx_chip_type = AST_TX_ASTDP;
> 
>> +
> 
>> +           ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
> 
>> +                                                   (u8) 
>> +~ASTDP_HOST_EDID_READ_DONE_MASK,
> 
>> +                                                   
>> +ASTDP_HOST_EDID_READ_DONE);
> 
>> +   } else
> 
>> +           ast->tx_chip_type = AST_TX_NONE;
> 
>> +}
> 
>> +
> 
>> +
> 
>> +
> 
>> +void ast_dp_power_on_off(struct drm_device *dev, bool on) {
> 
>> +   struct ast_private *ast = to_ast_private(dev);
> 
>> +   // Read and Turn off DP PHY sleep
> 
>> +   u8 bE3 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3,
> 
>> +AST_DP_VIDEO_ENABLE);
> 
>> +
> 
>> +   // Turn on DP PHY sleep
> 
>> +   if (!on)
> 
>> +           bE3 |= AST_DP_PHY_SLEEP;
> 
>> +
> 
>> +   // DP Power on/off
> 
>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, (u8)
> 
>> +~AST_DP_PHY_SLEEP, bE3); }
> 
>> +
> 
>> +
> 
>> +
> 
>> +void ast_dp_set_on_off(struct drm_device *dev, bool on) {
> 
>> +   struct ast_private *ast = to_ast_private(dev);
> 
>> +   u8 video_on_off = on;
> 
>> +
> 
>> +   // Video On/Off
> 
>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, (u8)
> 
>> +~AST_DP_VIDEO_ENABLE, on);
> 
>> +
> 
>> +   // If DP plug in and link successful then check video on / off 
>> +status
> 
>> +   if (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, 
>> +ASTDP_LINK_SUCCESS) &&
> 
>> +           ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, 
>> +ASTDP_HPD)) {
> 
>> +           video_on_off <<= 4;
> 
>> +           while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 
>> +0xDF,
> 
>> +                                           
>> +ASTDP_MIRROR_VIDEO_ENABLE) != video_on_off) {
> 
>> +                   // wait 1 ms
> 
>> +                   mdelay(1);
> 
>> +           }
> 
>> +   }
> 
>> +}
> 
>> +
> 
>> +void ast_dp_set_mode(struct drm_crtc *crtc, struct
> 
>> +ast_vbios_mode_info *vbios_mode) {
> 
>> +   struct ast_private *ast = to_ast_private(crtc->dev);
> 
>> +
> 
>> +   u32 ulRefreshRateIndex;
> 
>> +   u8 ModeIdx;
> 
>> +
> 
>> +   ulRefreshRateIndex = vbios_mode->enh_table->refresh_rate_index - 
>> +1;
> 
>> +
> 
>> +   switch (crtc->mode.crtc_hdisplay) {
> 
>> +   case 320:
> 
>> +           ModeIdx = ASTDP_320x240_60;
> 
>> +           break;
> 
>> +   case 400:
> 
>> +           ModeIdx = ASTDP_400x300_60;
> 
>> +           break;
> 
>> +   case 512:
> 
>> +           ModeIdx = ASTDP_512x384_60;
> 
>> +           break;
> 
>> +   case 640:
> 
>> +           ModeIdx = (ASTDP_640x480_60 + (u8) ulRefreshRateIndex);
> 
>> +           break;
> 
>> +   case 800:
> 
>> +           ModeIdx = (ASTDP_800x600_56 + (u8) ulRefreshRateIndex);
> 
>> +           break;
> 
>> +   case 1024:
> 
>> +           ModeIdx = (ASTDP_1024x768_60 + (u8) ulRefreshRateIndex);
> 
>> +           break;
> 
>> +   case 1152:
> 
>> +           ModeIdx = ASTDP_1152x864_75;
> 
>> +           break;
> 
>> +   case 1280:
> 
>> +           if (crtc->mode.crtc_vdisplay == 800)
> 
>> +                   ModeIdx = (ASTDP_1280x800_60_RB - (u8) 
>> +ulRefreshRateIndex);
> 
>> +           else          // 1024
> 
>> +                   ModeIdx = (ASTDP_1280x1024_60 + (u8) 
>> +ulRefreshRateIndex);
> 
>> +           break;
> 
>> +   case 1360:
> 
>> +   case 1366:
> 
>> +           ModeIdx = ASTDP_1366x768_60;
> 
>> +           break;
> 
>> +   case 1440:
> 
>> +           ModeIdx = (ASTDP_1440x900_60_RB - (u8) 
>> +ulRefreshRateIndex);
> 
>> +           break;
> 
>> +   case 1600:
> 
>> +           if (crtc->mode.crtc_vdisplay == 900)
> 
>> +                   ModeIdx = (ASTDP_1600x900_60_RB - (u8) 
>> +ulRefreshRateIndex);
> 
>> +           else          //1200
> 
>> +                   ModeIdx = ASTDP_1600x1200_60;
> 
>> +           break;
> 
>> +   case 1680:
> 
>> +           ModeIdx = (ASTDP_1680x1050_60_RB - (u8) 
>> +ulRefreshRateIndex);
> 
>> +           break;
> 
>> +   case 1920:
> 
>> +           if (crtc->mode.crtc_vdisplay == 1080)
> 
>> +                   ModeIdx = ASTDP_1920x1080_60;
> 
>> +           else          //1200
> 
>> +                   ModeIdx = ASTDP_1920x1200_60;
> 
>> +           break;
> 
>> +   default:
> 
>> +           return;
> 
>> +   }
> 
>> +
> 
>> +   /*
> 
>> +   * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp)
> 
>> +   * CRE1[7:0]: MISC1 (default: 0x00)
> 
>> +   * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50)
> 
>> +   */
> 
>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE0, (u8) 
>> +~ASTDP_CLEAR_MASK,
> 
>> +                           ASTDP_MISC0_24bpp);
> 
>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE1, (u8) 
>> +~ASTDP_CLEAR_MASK, ASTDP_MISC1);
> 
>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE2, (u8)
> 
>> +~ASTDP_CLEAR_MASK, ModeIdx); }
> 
>> diff --git a/drivers/gpu/drm/ast/ast_drv.h
> 
>> b/drivers/gpu/drm/ast/ast_drv.h index a19315b2f..ff1ae314b 100644
> 
>> --- a/drivers/gpu/drm/ast/ast_drv.h
> 
>> +++ b/drivers/gpu/drm/ast/ast_drv.h
> 
>> @@ -70,6 +70,7 @@ enum ast_tx_chip {
> 
>>           AST_TX_NONE,
> 
>>           AST_TX_SIL164,
> 
>>           AST_TX_DP501,
> 
>> +   AST_TX_ASTDP,
> 
>>   };
> 
>> 
> 
>>   #define AST_DRAM_512Mx16 0
> 
>> @@ -184,6 +185,10 @@ struct ast_private {
> 
>>                           struct drm_encoder encoder;
> 
>>                           struct drm_connector connector;
> 
>>                   } dp501;
> 
>> +           struct {
> 
>> +                   struct drm_encoder encoder;
> 
>> +                   struct drm_connector connector;
> 
>> +           } astdp;
> 
>>           } output;
> 
>> 
> 
>>           bool support_wide_screen;
> 
>> @@ -357,10 +362,113 @@ int ast_mode_config_init(struct ast_private 
>> *ast);
> 
>>   #define AST_DP501_EDID_DATA    0xf020
> 
>> 
> 
>>   /* Define for Soc scratched reg */
> 
>> +#define COPROCESSOR_LAUNCH                     BIT(5)
> 
>> +
> 
>> +/*
> 
>> + * Display Transmitter Type:
> 
>> + */
> 
>> +#define TX_TYPE_MASK                            GENMASK(3, 1)
> 
>> +#define NO_TX                                           (0 << 1)
> 
>> +#define ITE66121_VBIOS_TX                     (1 << 1)
> 
>> +#define SI164_VBIOS_TX                           (2 << 1)
> 
>> +#define CH7003_VBIOS_TX                       (3 << 1)
> 
>> +#define DP501_VBIOS_TX                         (4 << 1)
> 
>> +#define ANX9807_VBIOS_TX                     (5 << 1)
> 
>> +#define TX_FW_EMBEDDED_FW_TX                (6 << 1)
> 
>> +#define ASTDP_DPMCU_TX                               (7 << 1)
> 
>> +
> 
>>   #define AST_VRAM_INIT_STATUS_MASK       GENMASK(7, 6)
> 
>>   //#define AST_VRAM_INIT_BY_BMC             BIT(7)
> 
>>   //#define AST_VRAM_INIT_READY                BIT(6)
> 
>> 
> 
>> +/* Define for Soc scratched reg used on ASTDP */
> 
>> +#define AST_DP_PHY_SLEEP                     BIT(4)
> 
>> +#define AST_DP_VIDEO_ENABLE              BIT(0)
> 
>> +
> 
>> +#define AST_DP_POWER_ON                    true
> 
>> +#define AST_DP_POWER_OFF                   false
> 
>> +
> 
>> +/*
> 
>> + * CRD1[b5]: DP MCU FW is executing
> 
>> + * CRDC[b0]: DP link success
> 
>> + * CRDF[b0]: DP HPD
> 
>> + * CRE5[b0]: Host reading EDID process is done  */
> 
>> +#define ASTDP_MCU_FW_EXECUTING                     BIT(5)
> 
>> +#define ASTDP_LINK_SUCCESS                          BIT(0)
> 
>> +#define ASTDP_HPD                                          BIT(0)
> 
>> +#define ASTDP_HOST_EDID_READ_DONE                BIT(0)
> 
>> +#define ASTDP_HOST_EDID_READ_DONE_MASK    GENMASK(0, 0)
> 
>> +
> 
>> +/*
> 
>> + * CRB8[b1]: Enable VSYNC off
> 
>> + * CRB8[b0]: Enable HSYNC off
> 
>> + */
> 
>> +#define AST_DPMS_VSYNC_OFF                               BIT(1)
> 
>> +#define AST_DPMS_HSYNC_OFF                               BIT(0)
> 
>> +
> 
>> +/*
> 
>> + * CRDF[b4]: Mirror of AST_DP_VIDEO_ENABLE
> 
>> + * Precondition:  A. ~AST_DP_PHY_SLEEP  &&
> 
>> + *                        B. DP_HPD &&
> 
>> + *                        C. DP_LINK_SUCCESS
> 
>> + */
> 
>> +#define ASTDP_MIRROR_VIDEO_ENABLE                BIT(4)
> 
>> +
> 
>> +#define ASTDP_EDID_READ_POINTER_MASK  GENMASK(7, 0)
> 
>> +#define ASTDP_EDID_VALID_FLAG_MASK                GENMASK(0, 0)
> 
>> +#define ASTDP_EDID_READ_DATA_MASK        GENMASK(7, 0)
> 
>> +
> 
>> +/*
> 
>> + * ASTDP setmode registers:
> 
>> + * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp)
> 
>> + * CRE1[7:0]: MISC1 (default: 0x00)
> 
>> + * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50)  */
> 
>> +#define ASTDP_MISC0_24bpp                   BIT(5)
> 
>> +#define ASTDP_MISC1                               0
> 
>> +#define ASTDP_CLEAR_MASK                   GENMASK(7, 0)
> 
>> +
> 
>> +/*
> 
>> + * ASTDP resoultion table:
> 
>> + * EX:  ASTDP_A_B_C:
> 
>> + *                A: Resolution
> 
>> + *                B: Refresh Rate
> 
>> + *                C: Misc information, such as CVT, Reduce Blanked
> 
>> + */
> 
>> +#define ASTDP_640x480_60              0x00
> 
>> +#define ASTDP_640x480_72              0x01
> 
>> +#define ASTDP_640x480_75              0x02
> 
>> +#define ASTDP_640x480_85              0x03
> 
>> +#define ASTDP_800x600_56              0x04
> 
>> +#define ASTDP_800x600_60              0x05
> 
>> +#define ASTDP_800x600_72              0x06
> 
>> +#define ASTDP_800x600_75              0x07
> 
>> +#define ASTDP_800x600_85              0x08
> 
>> +#define ASTDP_1024x768_60            0x09
> 
>> +#define ASTDP_1024x768_70            0x0A
> 
>> +#define ASTDP_1024x768_75            0x0B
> 
>> +#define ASTDP_1024x768_85            0x0C
> 
>> +#define ASTDP_1280x1024_60          0x0D
> 
>> +#define ASTDP_1280x1024_75          0x0E
> 
>> +#define ASTDP_1280x1024_85          0x0F
> 
>> +#define ASTDP_1600x1200_60          0x10
> 
>> +#define ASTDP_320x240_60              0x11
> 
>> +#define ASTDP_400x300_60              0x12
> 
>> +#define ASTDP_512x384_60              0x13
> 
>> +#define ASTDP_1920x1200_60          0x14
> 
>> +#define ASTDP_1920x1080_60          0x15
> 
>> +#define ASTDP_1280x800_60            0x16
> 
>> +#define ASTDP_1280x800_60_RB     0x17
> 
>> +#define ASTDP_1440x900_60            0x18
> 
>> +#define ASTDP_1440x900_60_RB     0x19
> 
>> +#define ASTDP_1680x1050_60          0x1A
> 
>> +#define ASTDP_1680x1050_60_RB   0x1B
> 
>> +#define ASTDP_1600x900_60            0x1C
> 
>> +#define ASTDP_1600x900_60_RB     0x1D
> 
>> +#define ASTDP_1366x768_60            0x1E
> 
>> +#define ASTDP_1152x864_75            0x1F
> 
>> +
> 
>>   int ast_mm_init(struct ast_private *ast);
> 
>> 
> 
>>   /* ast post */
> 
>> @@ -381,4 +489,11 @@ void ast_init_3rdtx(struct drm_device *dev);
> 
>>   /* ast_i2c.c */
> 
>>   struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev);
> 
>> 
> 
>> +/* aspeed DP */
> 
>> +int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata); void
> 
>> +ast_dp_launch(struct drm_device *dev, u8 bPower); void
> 
>> +ast_dp_power_on_off(struct drm_device *dev, bool no); void
> 
>> +ast_dp_set_on_off(struct drm_device *dev, bool no); void
> 
>> +ast_dp_set_mode(struct drm_crtc *crtc, struct ast_vbios_mode_info
> 
>> +*vbios_mode);
> 
>> +
> 
>>   #endif
> 
>> diff --git a/drivers/gpu/drm/ast/ast_main.c
> 
>> b/drivers/gpu/drm/ast/ast_main.c index 22e9e2d3c..1113ee1cb 100644
> 
>> --- a/drivers/gpu/drm/ast/ast_main.c
> 
>> +++ b/drivers/gpu/drm/ast/ast_main.c
> 
>> @@ -232,7 +232,7 @@ static int ast_detect_chip(struct drm_device 
>> *dev, bool *need_post)
> 
>>                           ast->tx_chip_type = AST_TX_SIL164;
> 
>>           }
> 
>> 
> 
>> -    if ((ast->chip == AST2300) || (ast->chip == AST2400)) {
> 
>> +   if ((ast->chip == AST2300) || (ast->chip == AST2400) || 
>> +(ast->chip
> 
>> +== AST2500)) {
> 
>>                   /*
> 
>>                    * On AST2300 and 2400, look the configuration set 
>>by the SoC in
> 
>>                    * the SOC scratch register #1 bits 11:8 
>>(interestingly marked @@
> 
>> -256,7 +256,8 @@ static int ast_detect_chip(struct drm_device *dev, 
>> bool *need_post)
> 
>>                   case 0x0c:
> 
>>                           ast->tx_chip_type = AST_TX_DP501;
> 
>>                   }
> 
>> -    }
> 
>> +   } else if (ast->chip == AST2600)
> 
>> +           ast_dp_launch(&ast->base, 0);
> 
>> 
> 
>>           /* Print stuff for diagnostic purposes */
> 
>>           switch(ast->tx_chip_type) {
> 
>> diff --git a/drivers/gpu/drm/ast/ast_mode.c
> 
>> b/drivers/gpu/drm/ast/ast_mode.c index 45b56b39a..4728825b7 100644
> 
>> --- a/drivers/gpu/drm/ast/ast_mode.c
> 
>> +++ b/drivers/gpu/drm/ast/ast_mode.c
> 
>> @@ -988,21 +988,41 @@ static int ast_cursor_plane_init(struct 
>> ast_private *ast)
> 
>>   static void ast_crtc_dpms(struct drm_crtc *crtc, int mode)
> 
>>   {
> 
>>           struct ast_private *ast = to_ast_private(crtc->dev);
> 
>> +   u8 ch = AST_DPMS_VSYNC_OFF | AST_DPMS_HSYNC_OFF;
> 
>> 
> 
>>           /* TODO: Maybe control display signal generation with
> 
>>            *       Sync Enable (bit CR17.7).
> 
>>            */
> 
>>           switch (mode) {
> 
>>           case DRM_MODE_DPMS_ON:
> 
>> -    case DRM_MODE_DPMS_STANDBY:
> 
>> -    case DRM_MODE_DPMS_SUSPEND:
> 
>> +           ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT,  0x01, 0xdf, 
>> +0);
> 
>> +           ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, 
>> +0);
> 
>>                   if (ast->tx_chip_type == AST_TX_DP501)
> 
>>                           ast_set_dp501_video_output(crtc->dev, 1);
> 
>> +
> 
>> +           if (ast->tx_chip_type == AST_TX_ASTDP) {
> 
>> +                   ast_dp_power_on_off(crtc->dev, AST_DP_POWER_ON);
> 
>> +                   ast_wait_for_vretrace(ast);
> 
>> +                   ast_dp_set_on_off(crtc->dev, 1);
> 
>> +           }
> 
>> +
> 
>> +           ast_crtc_load_lut(ast, crtc);
> 
>>                   break;
> 
>> +   case DRM_MODE_DPMS_STANDBY:
> 
>> +   case DRM_MODE_DPMS_SUSPEND:
> 
>>           case DRM_MODE_DPMS_OFF:
> 
>> +           ch = mode;
> 
>>                   if (ast->tx_chip_type == AST_TX_DP501)
> 
>>                           ast_set_dp501_video_output(crtc->dev, 0);
> 
>>                   break;
> 
>> +
> 
>> +           if (ast->tx_chip_type == AST_TX_ASTDP) {
> 
>> +                   ast_dp_set_on_off(crtc->dev, 0);
> 
>> +                   ast_dp_power_on_off(crtc->dev, AST_DP_POWER_OFF);
> 
>> +           }
> 
>> +
> 
>> +           ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT,  0x01, 0xdf, 
>> +0x20);
> 
>> +           ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, 
>> +ch);
> 
>>           }
> 
>>   }
> 
>> 
> 
>> @@ -1027,7 +1047,7 @@ ast_crtc_helper_mode_valid(struct drm_crtc
> 
>> *crtc, const struct drm_display_mode
> 
>> 
> 
>>                   if ((ast->chip == AST2100) || (ast->chip == 
>>AST2200) ||
> 
>>                       (ast->chip == AST2300) || (ast->chip == 
>>AST2400) ||
> 
>> -                (ast->chip == AST2500)) {
> 
>> +               (ast->chip == AST2500) || (ast->chip == AST2600)) {
> 
>>                           if ((mode->hdisplay == 1920) && 
>>(mode->vdisplay == 1080))
> 
>>                                   return MODE_OK;
> 
>> 
> 
>> @@ -1110,6 +1130,7 @@ ast_crtc_helper_atomic_flush(struct drm_crtc 
>> *crtc,
> 
>>           struct ast_private *ast = to_ast_private(crtc->dev);
> 
>>           struct ast_crtc_state *ast_crtc_state = 
>>to_ast_crtc_state(crtc_state);
> 
>>           struct ast_crtc_state *old_ast_crtc_state =
> 
>> to_ast_crtc_state(old_crtc_state);
> 
>> +   struct ast_vbios_mode_info *vbios_mode_info =
> 
>> +&ast_crtc_state->vbios_mode_info;
> 
>> 
> 
>>           /*
> 
>>            * The gamma LUT has to be reloaded after changing the 
>>primary @@
> 
>> -1117,6 +1138,10 @@ ast_crtc_helper_atomic_flush(struct drm_crtc 
>> *crtc,
> 
>>            */
> 
>>           if (old_ast_crtc_state->format != ast_crtc_state->format)
> 
>>                   ast_crtc_load_lut(ast, crtc);
> 
>> +
> 
>> +   //Set Aspeed Display-Port
> 
>> +   if (ast->tx_chip_type == AST_TX_ASTDP)
> 
>> +           ast_dp_set_mode(crtc, vbios_mode_info);
> 
>>   }
> 
>> 
> 
>>   static void
> 
>> @@ -1527,6 +1552,93 @@ static int ast_dp501_output_init(struct 
>> ast_private *ast)
> 
>>           return 0;
> 
>>   }
> 
>> 
> 
>> +/*
> 
>> + * ASPEED Display-Port Connector
> 
>> + */
> 
>> +
> 
>> +static int ast_astdp_connector_helper_get_modes(struct drm_connector
> 
>> +*connector) {
> 
>> +   void *edid;
> 
>> +
> 
>> +   int succ;
> 
>> +   int count;
> 
>> +
> 
>> +   edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
> 
>> +   if (!edid)
> 
>> +           goto err_drm_connector_update_edid_property;
> 
>> +
> 
>> +   succ = ast_astdp_read_edid(connector->dev, edid);
> 
>> +   if (succ < 0)
> 
>> +           goto err_kfree;
> 
>> +
> 
>> +   drm_connector_update_edid_property(connector, edid);
> 
>> +   count = drm_add_edid_modes(connector, edid);
> 
>> +   kfree(edid);
> 
>> +
> 
>> +   return count;
> 
>> +
> 
>> +err_kfree:
> 
>> +   kfree(edid);
> 
>> +err_drm_connector_update_edid_property:
> 
>> +   drm_connector_update_edid_property(connector, NULL);
> 
>> +   return 0;
> 
>> +}
> 
>> +
> 
>> +static const struct drm_connector_helper_funcs 
>> +ast_astdp_connector_helper_funcs = {
> 
>> +   .get_modes = ast_astdp_connector_helper_get_modes,
> 
>> +};
> 
>> +
> 
>> +static const struct drm_connector_funcs ast_astdp_connector_funcs = 
>> +{
> 
>> +   .reset = drm_atomic_helper_connector_reset,
> 
>> +   .fill_modes = drm_helper_probe_single_connector_modes,
> 
>> +   .destroy = drm_connector_cleanup,
> 
>> +   .atomic_duplicate_state = 
>> +drm_atomic_helper_connector_duplicate_state,
> 
>> +   .atomic_destroy_state = 
>> +drm_atomic_helper_connector_destroy_state,
> 
>> +};
> 
>> +
> 
>> +static int ast_astdp_connector_init(struct drm_device *dev, struct
> 
>> +drm_connector *connector) {
> 
>> +   int ret;
> 
>> +
> 
>> +   ret = drm_connector_init(dev, connector, 
>> +&ast_astdp_connector_funcs,
> 
>> +                           DRM_MODE_CONNECTOR_DisplayPort);
> 
>> +   if (ret)
> 
>> +           return ret;
> 
>> +
> 
>> +   drm_connector_helper_add(connector,
> 
>> +&ast_astdp_connector_helper_funcs);
> 
>> +
> 
>> +   connector->interlace_allowed = 0;
> 
>> +   connector->doublescan_allowed = 0;
> 
>> +
> 
>> +   connector->polled = DRM_CONNECTOR_POLL_CONNECT;
> 
>> +
> 
>> +   return 0;
> 
>> +}
> 
>> +
> 
>> +static int ast_astdp_output_init(struct ast_private *ast) {
> 
>> +   struct drm_device *dev = &ast->base;
> 
>> +   struct drm_crtc *crtc = &ast->crtc;
> 
>> +   struct drm_encoder *encoder = &ast->output.astdp.encoder;
> 
>> +   struct drm_connector *connector = &ast->output.astdp.connector;
> 
>> +   int ret;
> 
>> +
> 
>> +   ret = drm_simple_encoder_init(dev, encoder, 
>> +DRM_MODE_ENCODER_TMDS);
> 
>> +   if (ret)
> 
>> +           return ret;
> 
>> +   encoder->possible_crtcs = drm_crtc_mask(crtc);
> 
>> +
> 
>> +   ret = ast_astdp_connector_init(dev, connector);
> 
>> +   if (ret)
> 
>> +           return ret;
> 
>> +
> 
>> +   ret = drm_connector_attach_encoder(connector, encoder);
> 
>> +   if (ret)
> 
>> +           return ret;
> 
>> +
> 
>> +   return 0;
> 
>> +}
> 
>> +
> 
>>   /*
> 
>>    * Mode config
> 
>>    */
> 
>> @@ -1563,7 +1675,8 @@ int ast_mode_config_init(struct ast_private 
>> *ast)
> 
>>               ast->chip == AST2200 ||
> 
>>               ast->chip == AST2300 ||
> 
>>               ast->chip == AST2400 ||
> 
>> -        ast->chip == AST2500) {
> 
>> +       ast->chip == AST2500 ||
> 
>> +       ast->chip == AST2600) {
> 
>>                   dev->mode_config.max_width = 1920;
> 
>>                   dev->mode_config.max_height = 2048;
> 
>>           } else {
> 
>> @@ -1594,6 +1707,9 @@ int ast_mode_config_init(struct ast_private 
>> *ast)
> 
>>           case AST_TX_DP501:
> 
>>                   ret = ast_dp501_output_init(ast);
> 
>>                   break;
> 
>> +   case AST_TX_ASTDP:
> 
>> +           ret = ast_astdp_output_init(ast);
> 
>> +           break;
> 
>>           }
> 
>>           if (ret)
> 
>>                   return ret;
> 
>> diff --git a/drivers/gpu/drm/ast/ast_post.c
> 
>> b/drivers/gpu/drm/ast/ast_post.c index b5d92f652..0aa9cf0fb 100644
> 
>> --- a/drivers/gpu/drm/ast/ast_post.c
> 
>> +++ b/drivers/gpu/drm/ast/ast_post.c
> 
>> @@ -379,7 +379,9 @@ void ast_post_gpu(struct drm_device *dev)
> 
>>           ast_enable_mmio(dev);
> 
>>           ast_set_def_ext_reg(dev);
> 
>> 
> 
>> -    if (ast->config_mode == ast_use_p2a) {
> 
>> +   if (ast->chip == AST2600) {
> 
>> +           ast_dp_launch(dev, 1);
> 
>> +   } else if (ast->config_mode == ast_use_p2a) {
> 
>>                   if (ast->chip == AST2500)
> 
>>                           ast_post_chip_2500(dev);
> 
>>                   else if (ast->chip == AST2300 || ast->chip == 
>>AST2400)
> 
>> 
> 
>> base-commit: c54b39a565227538c52ead2349eb17d54aadd6f7
> 
>> --
> 
>> 2.27.0
> 
>> 
> 
> --
> 
> Thomas Zimmermann
> 
> Graphics Driver Developer
> 
> SUSE Software Solutions Germany GmbH
> 
> Maxfeldstr. 5, 90409 Nürnberg, Germany
> 
> (HRB 36809, AG Nürnberg)
> 
> Geschäftsführer: Ivo Totev
> 

--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Ivo Totev

^ permalink raw reply	[flat|nested] 21+ messages in thread

* RE: [PATCH v4] drm/ast: Create the driver for ASPEED proprietory Display-Port
  2022-05-05  2:41               ` Kuo-Hsiang Chou
@ 2022-05-05  2:51                 ` Luke Chen
  0 siblings, 0 replies; 21+ messages in thread
From: Luke Chen @ 2022-05-05  2:51 UTC (permalink / raw)
  To: Kuo-Hsiang Chou, Thomas Zimmermann, dri-devel, linux-kernel
  Cc: Hungju Huang, airlied, Tommy Huang, airlied, Arc Sung

Hi Thomas
Nice to e-meet you via this email.
I am preparing 1pcs AST2600 demo board for you.

Is it ok for you to sign NDA with ASPEED, then I can release the demo board and all AST2600 technical doc to you?
Thanks.


Best wishes

Luke Chen
(O) : +886-3-5751185
(M) : +886-935-592-892
4F, No.1,Sec. 3,Gongdao 5th Road, East Dist.,
Hsinchu City, 30069,Taiwan,R.O.C.


-----Original Message-----
From: Kuo-Hsiang Chou <kuohsiang_chou@aspeedtech.com> 
Sent: Thursday, May 5, 2022 10:41 AM
To: Thomas Zimmermann <tzimmermann@suse.de>; dri-devel@lists.freedesktop.org; linux-kernel@vger.kernel.org
Cc: Hungju Huang <hungju_huang@aspeedtech.com>; airlied@linux.ie; Tommy Huang <tommy_huang@aspeedtech.com>; airlied@redhat.com; Arc Sung <arc_sung@aspeedtech.com>; Luke Chen <luke_chen@aspeedtech.com>
Subject: RE: [PATCH v4] drm/ast: Create the driver for ASPEED proprietory Display-Port

Hi Luke,

Please help on the EVB request that DRM reviewer, Thomas, needs one AST2600 EVB to ease Display-Port verification on ASPEED DRM diver. 
Thanks

Regards,
	Kuo-Hsiang Chou

-----Original Message-----
From: Thomas Zimmermann [mailto:tzimmermann@suse.de]
Sent: Wednesday, May 04, 2022 5:38 PM
To: Kuo-Hsiang Chou <kuohsiang_chou@aspeedtech.com>; dri-devel@lists.freedesktop.org; linux-kernel@vger.kernel.org
Subject: Re: [PATCH v4] drm/ast: Create the driver for ASPEED proprietory Display-Port

Hi Thomas,

Hi

Am 04.05.22 um 10:49 schrieb Kuo-Hsiang Chou:
> Hi Thomas,
> 
> Thanks for your efforts to review this patch.
> 
> Now, I observe a change that after DP unplugged and then the system is 
> unable to get EDID from D-sub connecting.
> 
> The reason seems that TXs are merged into union structure in 
> /drivers/gpu/drm/ast/ast_drv.h
>   (a59b026419f33040d7d28b8e3b1cea681b9ce7a7
> <https://cgit.freedesktop.org/drm/drm-misc/commit/?id=a59b026419f33040
> d7d28b8e3b1cea681b9ce7a7>)

The test system has a DP and a VGA adapter?  We need create two separate connectors and encoders in that case.  I'll try to provide a patch in the next days.

Yes, the same content are displayed (as mirror mode) on DP and VGA monitor as same time.

In previous drm/ast version, the EDID read from DP is first priority for resolution validation.
If DP is detected as un-connected, and then reading EDID from VGA is used for the second run of resolution validation.
Finally, if both DP and VGA are detected as un-connected, only 1024*768 and 800*600 are able to be selected as default resolution.

> 
> Another, do you need the ast2600 EVB to ease verification on "drm/ast" ?

The EVB is an evaluation board? 
Yes. the EVB is developed to clarify the differences between custom's CRB.
The EVB is connect to Host by PCI-e 1-Lane adapter.

I'd be happy to have one of these. How can I get one?
I forward the request to ASPEED VP about EVB delivery to you.

Best regards
Thomas

> 
> Regards,
> 
>          Kuo-Hsiang Chou
> 
> -----Original Message-----
> From: Thomas Zimmermann [mailto:tzimmermann@suse.de]
> Sent: Wednesday, May 04, 2022 3:28 PM
> To: Kuo-Hsiang Chou <kuohsiang_chou@aspeedtech.com>; 
> dri-devel@lists.freedesktop.org; linux-kernel@vger.kernel.org
> Subject: Re: [PATCH v4] drm/ast: Create the driver for ASPEED 
> proprietory Display-Port
> 
> Hi
> 
> Am 28.04.22 um 09:56 schrieb KuoHsiang Chou:
> 
>> V1:
> 
>> 1. The MCU FW controling ASPEED DP is loaded by BMC boot loader.
> 
>> 2. Driver starts after CR[3:1] == 111b that indicates Tx is ASTDP,
> 
>>     and CRD1[5] has been asserted by BMVC boot loader.
> 
>> 3. EDID is prioritized by DP monitor.
> 
>> 4. DP's EDID has high priority to decide resolution supporting.
> 
>> 
> 
>> V2:
> 
>> Modules description:
> 
>> 1. ASTDP (ASPEED DisplayPort) is controlled by dedicated
> 
>>     AST-MCU (ASPEED propriatary MCU).
> 
>> 2. MCU is looping in charged of HPD, Read EDID, Link Training with
> 
>>     DP sink.
> 
>> 3. ASTDP and AST-MUC reside in BMC (Baseboard Management controller)
> 
>>     addressing-space.
> 
>> 4. ASPEED DRM driver requests MCU to get HPD and EDID by CR-scratched
> 
>>     register.
> 
>> 
> 
>> Booting sequence:
> 
>> 1. Check if TX is ASTDP                                        //
>> ast_dp_launch()
> 
>> 2. Check if DP-MCU FW has loaded // ast_dp_launch()
> 
>> 3. Read EDID                                        //
>> ast_dp_read_edid()
> 
>> 4. Resolution switch                                     //
>> ast_dp_SetOutput()
> 
>> 
> 
>> V3:
> 
>> 1. Remove unneeded semicolon.
> 
>> 2. Apply to git://anongit.freedesktop.org/drm/drm, instead of
> 
>>     git://anongit.freedesktop.org/drm/drm-misc
> 
>> 3. Resolve auto build test WARNINGs on V1 patch.
> 
>> 
> 
>> V4:
> 
>> 1. Sync code-base with kernel 5.17_rc6 2. Remove the define of
> 
>> DPControlPower, because DP chips need to be
> 
>>     powered on to be used.
> 
>> 3. Remove the switches of PHY and Display from EDID procedure.
> 
>> 4. Revise increaing delay to fixed delay, because this version kernel
> 
>>     doesn't detect minitor consistenntly.
> 
>> 5. Create clean-up code used for reset of power state on errors with
> 
>>     -EIO manner.
> 
>> 6. Revise the DP detection by TX type and its DP-FW status during
> 
>>     booting and resume.
> 
>> 7. Correct the CamelCase Style.
> 
>> 8. Use register reading while needing, and remove to hold full
> 
>>     register.
> 
>> 9. Instead of 'u8', revise to 'bool' on swwitch of PHY and video.
> 
>> 10.Correct typo
> 
>> 11.Remove the duplicated copy of TX definition.
> 
>> 12.Use EDID_LENGTH as the constant of 128.
> 
>> 
> 
>> Signed-off-by: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com 
>> <mailto:kuohsiang_chou@aspeedtech.com>>
> 
> Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de 
> <mailto:tzimmermann@suse.de>>
> 
> I've meanwhile added your patch to drm-misc-next. It should show up in 
> one of the next kernel releases.  Thanks a lot.
> 
> Best regards
> 
> Thomas
> 
>> ---
> 
>>   drivers/gpu/drm/ast/Makefile   |   2 +-
> 
>>   drivers/gpu/drm/ast/ast_dp.c   | 282
>>+++++++++++++++++++++++++++++++++
> 
>>   drivers/gpu/drm/ast/ast_drv.h  | 115 ++++++++++++++
> 
>>   drivers/gpu/drm/ast/ast_main.c |   5 +-
> 
>>   drivers/gpu/drm/ast/ast_mode.c | 124 ++++++++++++++-
> 
>>   drivers/gpu/drm/ast/ast_post.c |   4 +-
> 
>>   6 files changed, 524 insertions(+), 8 deletions(-)
> 
>>   create mode 100644 drivers/gpu/drm/ast/ast_dp.c
> 
>> 
> 
>> diff --git a/drivers/gpu/drm/ast/Makefile
> 
>> b/drivers/gpu/drm/ast/Makefile index 21f71160b..5a53ce51f 100644
> 
>> --- a/drivers/gpu/drm/ast/Makefile
> 
>> +++ b/drivers/gpu/drm/ast/Makefile
> 
>> @@ -3,6 +3,6 @@
> 
>>   # Makefile for the drm device driver.  This driver provides support 
>>for the
> 
>>   # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
> 
>> 
> 
>> -ast-y := ast_drv.o ast_i2c.o ast_main.o ast_mm.o ast_mode.o
> 
>> ast_post.o ast_dp501.o
> 
>> +ast-y := ast_drv.o ast_i2c.o ast_main.o ast_mm.o ast_mode.o
> 
>> +ast_post.o ast_dp501.o ast_dp.o
> 
>> 
> 
>>   obj-$(CONFIG_DRM_AST) := ast.o
> 
>> diff --git a/drivers/gpu/drm/ast/ast_dp.c
> 
>> b/drivers/gpu/drm/ast/ast_dp.c new file mode 100644 index
> 
>> 000000000..4551bc8a3
> 
>> --- /dev/null
> 
>> +++ b/drivers/gpu/drm/ast/ast_dp.c
> 
>> @@ -0,0 +1,282 @@
> 
>> +// SPDX-License-Identifier: GPL-2.0
> 
>> +// Copyright (c) 2021, ASPEED Technology Inc.
> 
>> +// Authors: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com 
>> +<mailto:kuohsiang_chou@aspeedtech.com>>
> 
>> +
> 
>> +#include <linux/firmware.h>
> 
>> +#include <linux/delay.h>
> 
>> +#include <drm/drm_print.h>
> 
>> +#include "ast_drv.h"
> 
>> +
> 
>> +int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata) {
> 
>> +   struct ast_private *ast = to_ast_private(dev);
> 
>> +   u8 i = 0, j = 0;
> 
>> +
> 
>> +   /*
> 
>> +   * CRD1[b5]: DP MCU FW is executing
> 
>> +   * CRDC[b0]: DP link success
> 
>> +   * CRDF[b0]: DP HPD
> 
>> +   * CRE5[b0]: Host reading EDID process is done
> 
>> +   */
> 
>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1,
>> +ASTDP_MCU_FW_EXECUTING) &&
> 
>> +           ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC,
>> +ASTDP_LINK_SUCCESS) &&
> 
>> +           ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF,
>> +ASTDP_HPD) &&
> 
>> +           ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
> 
>> +                                                           
>> +ASTDP_HOST_EDID_READ_DONE_MASK))) {
> 
>> +           goto err_astdp_edid_not_ready;
> 
>> +   }
> 
>> +
> 
>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8) 
>> +~ASTDP_HOST_EDID_READ_DONE_MASK,
> 
>> +                                                   0x00);
> 
>> +
> 
>> +   for (i = 0; i < 32; i++) {
> 
>> +           /*
> 
>> +           * CRE4[7:0]: Read-Pointer for EDID (Unit: 4bytes); valid
>> +range: 0~64
> 
>> +           */
> 
>> +           ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE4,
> 
>> +                                   (u8) 
>> +~ASTDP_EDID_READ_POINTER_MASK, (u8) i);
> 
>> +           j = 0;
> 
>> +
> 
>> +           /*
> 
>> +           * CRD7[b0]: valid flag for EDID
> 
>> +           * CRD6[b0]: mirror read pointer for EDID
> 
>> +           */
> 
>> +           while ((ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 
>> +0xD7,
> 
>> +                           ASTDP_EDID_VALID_FLAG_MASK) != 0x01) ||
> 
>> +                   (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 
>> +0xD6,
> 
>> +                                           
>> +ASTDP_EDID_READ_POINTER_MASK) != i)) {
> 
>> +                   /*
> 
>> +                   * Delay are getting longer with each retry.
> 
>> +                   * 1. The Delays are often 2 loops when users request "Display Settings"
> 
>> +                   *      of right-click of mouse.
> 
>> +                   * 2. The Delays are often longer a lot when system resume from S3/S4.
> 
>> +                   */
> 
>> +                   mdelay(j+1);
> 
>> +
> 
>> +                   if (!(ast_get_index_reg_mask(ast, 
>> +AST_IO_CRTC_PORT, 0xD1,
> 
>> +                                                   
>> +ASTDP_MCU_FW_EXECUTING) &&
> 
>> +                           ast_get_index_reg_mask(ast, 
>> +AST_IO_CRTC_PORT, 0xDC,
> 
>> +                                                   
>> +ASTDP_LINK_SUCCESS) &&
> 
>> +                           ast_get_index_reg_mask(ast, 
>> +AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD))) {
> 
>> +                           goto err_astdp_jump_out_loop_of_edid;
> 
>> +                   }
> 
>> +
> 
>> +                   j++;
> 
>> +                   if (j > 200)
> 
>> +                           goto err_astdp_jump_out_loop_of_edid;
> 
>> +           }
> 
>> +
> 
>> +           *(ediddata) = ast_get_index_reg_mask(ast, 
>> +AST_IO_CRTC_PORT,
> 
>> +                                                   0xD8, 
>> +ASTDP_EDID_READ_DATA_MASK);
> 
>> +           *(ediddata + 1) = ast_get_index_reg_mask(ast, 
>> +AST_IO_CRTC_PORT, 0xD9,
> 
>> +                                                           
>> +ASTDP_EDID_READ_DATA_MASK);
> 
>> +           *(ediddata + 2) = ast_get_index_reg_mask(ast, 
>> +AST_IO_CRTC_PORT, 0xDA,
> 
>> +                                                           
>> +ASTDP_EDID_READ_DATA_MASK);
> 
>> +           *(ediddata + 3) = ast_get_index_reg_mask(ast, 
>> +AST_IO_CRTC_PORT, 0xDB,
> 
>> +                                                           
>> +ASTDP_EDID_READ_DATA_MASK);
> 
>> +
> 
>> +           if (i == 31) {
> 
>> +                   /*
> 
>> +                   * For 128-bytes EDID_1.3,
> 
>> +                   * 1. Add the value of Bytes-126 to Bytes-127.
> 
>> +                   *            The Bytes-127 is Checksum. Sum of 
>> +all 128bytes should
> 
>> +                   *            equal 0    (mod 256).
> 
>> +                   * 2. Modify Bytes-126 to be 0.
> 
>> +                   *            The Bytes-126 indicates the Number 
>> +of extensions to
> 
>> +                   *            follow. 0 represents noextensions.
> 
>> +                   */
> 
>> +                   *(ediddata + 3) = *(ediddata + 3) + *(ediddata + 
>> +2);
> 
>> +                   *(ediddata + 2) = 0;
> 
>> +           }
> 
>> +
> 
>> +           ediddata += 4;
> 
>> +   }
> 
>> +
> 
>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8) 
>> +~ASTDP_HOST_EDID_READ_DONE_MASK,
> 
>> +                                                   
>> +ASTDP_HOST_EDID_READ_DONE);
> 
>> +
> 
>> +   return 0;
> 
>> +
> 
>> +err_astdp_jump_out_loop_of_edid:
> 
>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
> 
>> +                                                   (u8) 
>> +~ASTDP_HOST_EDID_READ_DONE_MASK,
> 
>> +                                                   
>> +ASTDP_HOST_EDID_READ_DONE);
> 
>> +   return (~(j+256) + 1);
> 
>> +
> 
>> +err_astdp_edid_not_ready:
> 
>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1,
>> +ASTDP_MCU_FW_EXECUTING)))
> 
>> +           return (~0xD1 + 1);
> 
>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC,
>> +ASTDP_LINK_SUCCESS)))
> 
>> +           return (~0xDC + 1);
> 
>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF,
>> +ASTDP_HPD)))
> 
>> +           return (~0xDF + 1);
> 
>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
>> +ASTDP_HOST_EDID_READ_DONE_MASK)))
> 
>> +           return (~0xE5 + 1);
> 
>> +
> 
>> +   return      0;
> 
>> +}
> 
>> +
> 
>> +/*
> 
>> + * Launch Aspeed DP
> 
>> + */
> 
>> +void ast_dp_launch(struct drm_device *dev, u8 bPower) {
> 
>> +   u32 i = 0, j = 0, WaitCount = 1;
> 
>> +   u8 bDPTX = 0;
> 
>> +   u8 bDPExecute = 1;
> 
>> +
> 
>> +   struct ast_private *ast = to_ast_private(dev);
> 
>> +   // S3 come back, need more time to wait BMC ready.
> 
>> +   if (bPower)
> 
>> +           WaitCount = 300;
> 
>> +
> 
>> +
> 
>> +   // Wait total count by different condition.
> 
>> +   for (j = 0; j < WaitCount; j++) {
> 
>> +           bDPTX = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 
>> +0xD1,
> 
>> +TX_TYPE_MASK);
> 
>> +
> 
>> +           if (bDPTX)
> 
>> +                   break;
> 
>> +
> 
>> +           msleep(100);
> 
>> +   }
> 
>> +
> 
>> +   // 0xE : ASTDP with DPMCU FW handling
> 
>> +   if (bDPTX == ASTDP_DPMCU_TX) {
> 
>> +           // Wait one second then timeout.
> 
>> +           i = 0;
> 
>> +
> 
>> +           while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 
>> +0xD1, COPROCESSOR_LAUNCH) !=
> 
>> +                   COPROCESSOR_LAUNCH) {
> 
>> +                   i++;
> 
>> +                   // wait 100 ms
> 
>> +                   msleep(100);
> 
>> +
> 
>> +                   if (i >= 10) {
> 
>> +                           // DP would not be ready.
> 
>> +                           bDPExecute = 0;
> 
>> +                           break;
> 
>> +                   }
> 
>> +           }
> 
>> +
> 
>> +           if (bDPExecute)
> 
>> +                   ast->tx_chip_type = AST_TX_ASTDP;
> 
>> +
> 
>> +           ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
> 
>> +                                                   (u8) 
>> +~ASTDP_HOST_EDID_READ_DONE_MASK,
> 
>> +                                                   
>> +ASTDP_HOST_EDID_READ_DONE);
> 
>> +   } else
> 
>> +           ast->tx_chip_type = AST_TX_NONE;
> 
>> +}
> 
>> +
> 
>> +
> 
>> +
> 
>> +void ast_dp_power_on_off(struct drm_device *dev, bool on) {
> 
>> +   struct ast_private *ast = to_ast_private(dev);
> 
>> +   // Read and Turn off DP PHY sleep
> 
>> +   u8 bE3 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3,
> 
>> +AST_DP_VIDEO_ENABLE);
> 
>> +
> 
>> +   // Turn on DP PHY sleep
> 
>> +   if (!on)
> 
>> +           bE3 |= AST_DP_PHY_SLEEP;
> 
>> +
> 
>> +   // DP Power on/off
> 
>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, (u8)
> 
>> +~AST_DP_PHY_SLEEP, bE3); }
> 
>> +
> 
>> +
> 
>> +
> 
>> +void ast_dp_set_on_off(struct drm_device *dev, bool on) {
> 
>> +   struct ast_private *ast = to_ast_private(dev);
> 
>> +   u8 video_on_off = on;
> 
>> +
> 
>> +   // Video On/Off
> 
>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, (u8)
> 
>> +~AST_DP_VIDEO_ENABLE, on);
> 
>> +
> 
>> +   // If DP plug in and link successful then check video on / off 
>> +status
> 
>> +   if (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC,
>> +ASTDP_LINK_SUCCESS) &&
> 
>> +           ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF,
>> +ASTDP_HPD)) {
> 
>> +           video_on_off <<= 4;
> 
>> +           while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 
>> +0xDF,
> 
>> +                                           
>> +ASTDP_MIRROR_VIDEO_ENABLE) != video_on_off) {
> 
>> +                   // wait 1 ms
> 
>> +                   mdelay(1);
> 
>> +           }
> 
>> +   }
> 
>> +}
> 
>> +
> 
>> +void ast_dp_set_mode(struct drm_crtc *crtc, struct
> 
>> +ast_vbios_mode_info *vbios_mode) {
> 
>> +   struct ast_private *ast = to_ast_private(crtc->dev);
> 
>> +
> 
>> +   u32 ulRefreshRateIndex;
> 
>> +   u8 ModeIdx;
> 
>> +
> 
>> +   ulRefreshRateIndex = vbios_mode->enh_table->refresh_rate_index - 
>> +1;
> 
>> +
> 
>> +   switch (crtc->mode.crtc_hdisplay) {
> 
>> +   case 320:
> 
>> +           ModeIdx = ASTDP_320x240_60;
> 
>> +           break;
> 
>> +   case 400:
> 
>> +           ModeIdx = ASTDP_400x300_60;
> 
>> +           break;
> 
>> +   case 512:
> 
>> +           ModeIdx = ASTDP_512x384_60;
> 
>> +           break;
> 
>> +   case 640:
> 
>> +           ModeIdx = (ASTDP_640x480_60 + (u8) ulRefreshRateIndex);
> 
>> +           break;
> 
>> +   case 800:
> 
>> +           ModeIdx = (ASTDP_800x600_56 + (u8) ulRefreshRateIndex);
> 
>> +           break;
> 
>> +   case 1024:
> 
>> +           ModeIdx = (ASTDP_1024x768_60 + (u8) ulRefreshRateIndex);
> 
>> +           break;
> 
>> +   case 1152:
> 
>> +           ModeIdx = ASTDP_1152x864_75;
> 
>> +           break;
> 
>> +   case 1280:
> 
>> +           if (crtc->mode.crtc_vdisplay == 800)
> 
>> +                   ModeIdx = (ASTDP_1280x800_60_RB - (u8) 
>> +ulRefreshRateIndex);
> 
>> +           else          // 1024
> 
>> +                   ModeIdx = (ASTDP_1280x1024_60 + (u8) 
>> +ulRefreshRateIndex);
> 
>> +           break;
> 
>> +   case 1360:
> 
>> +   case 1366:
> 
>> +           ModeIdx = ASTDP_1366x768_60;
> 
>> +           break;
> 
>> +   case 1440:
> 
>> +           ModeIdx = (ASTDP_1440x900_60_RB - (u8) 
>> +ulRefreshRateIndex);
> 
>> +           break;
> 
>> +   case 1600:
> 
>> +           if (crtc->mode.crtc_vdisplay == 900)
> 
>> +                   ModeIdx = (ASTDP_1600x900_60_RB - (u8) 
>> +ulRefreshRateIndex);
> 
>> +           else          //1200
> 
>> +                   ModeIdx = ASTDP_1600x1200_60;
> 
>> +           break;
> 
>> +   case 1680:
> 
>> +           ModeIdx = (ASTDP_1680x1050_60_RB - (u8) 
>> +ulRefreshRateIndex);
> 
>> +           break;
> 
>> +   case 1920:
> 
>> +           if (crtc->mode.crtc_vdisplay == 1080)
> 
>> +                   ModeIdx = ASTDP_1920x1080_60;
> 
>> +           else          //1200
> 
>> +                   ModeIdx = ASTDP_1920x1200_60;
> 
>> +           break;
> 
>> +   default:
> 
>> +           return;
> 
>> +   }
> 
>> +
> 
>> +   /*
> 
>> +   * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp)
> 
>> +   * CRE1[7:0]: MISC1 (default: 0x00)
> 
>> +   * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50)
> 
>> +   */
> 
>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE0, (u8) 
>> +~ASTDP_CLEAR_MASK,
> 
>> +                           ASTDP_MISC0_24bpp);
> 
>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE1, (u8) 
>> +~ASTDP_CLEAR_MASK, ASTDP_MISC1);
> 
>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE2, (u8)
> 
>> +~ASTDP_CLEAR_MASK, ModeIdx); }
> 
>> diff --git a/drivers/gpu/drm/ast/ast_drv.h
> 
>> b/drivers/gpu/drm/ast/ast_drv.h index a19315b2f..ff1ae314b 100644
> 
>> --- a/drivers/gpu/drm/ast/ast_drv.h
> 
>> +++ b/drivers/gpu/drm/ast/ast_drv.h
> 
>> @@ -70,6 +70,7 @@ enum ast_tx_chip {
> 
>>           AST_TX_NONE,
> 
>>           AST_TX_SIL164,
> 
>>           AST_TX_DP501,
> 
>> +   AST_TX_ASTDP,
> 
>>   };
> 
>> 
> 
>>   #define AST_DRAM_512Mx16 0
> 
>> @@ -184,6 +185,10 @@ struct ast_private {
> 
>>                           struct drm_encoder encoder;
> 
>>                           struct drm_connector connector;
> 
>>                   } dp501;
> 
>> +           struct {
> 
>> +                   struct drm_encoder encoder;
> 
>> +                   struct drm_connector connector;
> 
>> +           } astdp;
> 
>>           } output;
> 
>> 
> 
>>           bool support_wide_screen;
> 
>> @@ -357,10 +362,113 @@ int ast_mode_config_init(struct ast_private 
>> *ast);
> 
>>   #define AST_DP501_EDID_DATA    0xf020
> 
>> 
> 
>>   /* Define for Soc scratched reg */
> 
>> +#define COPROCESSOR_LAUNCH                     BIT(5)
> 
>> +
> 
>> +/*
> 
>> + * Display Transmitter Type:
> 
>> + */
> 
>> +#define TX_TYPE_MASK                            GENMASK(3, 1)
> 
>> +#define NO_TX                                           (0 << 1)
> 
>> +#define ITE66121_VBIOS_TX                     (1 << 1)
> 
>> +#define SI164_VBIOS_TX                           (2 << 1)
> 
>> +#define CH7003_VBIOS_TX                       (3 << 1)
> 
>> +#define DP501_VBIOS_TX                         (4 << 1)
> 
>> +#define ANX9807_VBIOS_TX                     (5 << 1)
> 
>> +#define TX_FW_EMBEDDED_FW_TX                (6 << 1)
> 
>> +#define ASTDP_DPMCU_TX                               (7 << 1)
> 
>> +
> 
>>   #define AST_VRAM_INIT_STATUS_MASK       GENMASK(7, 6)
> 
>>   //#define AST_VRAM_INIT_BY_BMC             BIT(7)
> 
>>   //#define AST_VRAM_INIT_READY                BIT(6)
> 
>> 
> 
>> +/* Define for Soc scratched reg used on ASTDP */
> 
>> +#define AST_DP_PHY_SLEEP                     BIT(4)
> 
>> +#define AST_DP_VIDEO_ENABLE              BIT(0)
> 
>> +
> 
>> +#define AST_DP_POWER_ON                    true
> 
>> +#define AST_DP_POWER_OFF                   false
> 
>> +
> 
>> +/*
> 
>> + * CRD1[b5]: DP MCU FW is executing
> 
>> + * CRDC[b0]: DP link success
> 
>> + * CRDF[b0]: DP HPD
> 
>> + * CRE5[b0]: Host reading EDID process is done  */
> 
>> +#define ASTDP_MCU_FW_EXECUTING                     BIT(5)
> 
>> +#define ASTDP_LINK_SUCCESS                          BIT(0)
> 
>> +#define ASTDP_HPD                                          BIT(0)
> 
>> +#define ASTDP_HOST_EDID_READ_DONE                BIT(0)
> 
>> +#define ASTDP_HOST_EDID_READ_DONE_MASK    GENMASK(0, 0)
> 
>> +
> 
>> +/*
> 
>> + * CRB8[b1]: Enable VSYNC off
> 
>> + * CRB8[b0]: Enable HSYNC off
> 
>> + */
> 
>> +#define AST_DPMS_VSYNC_OFF                               BIT(1)
> 
>> +#define AST_DPMS_HSYNC_OFF                               BIT(0)
> 
>> +
> 
>> +/*
> 
>> + * CRDF[b4]: Mirror of AST_DP_VIDEO_ENABLE
> 
>> + * Precondition:  A. ~AST_DP_PHY_SLEEP  &&
> 
>> + *                        B. DP_HPD &&
> 
>> + *                        C. DP_LINK_SUCCESS
> 
>> + */
> 
>> +#define ASTDP_MIRROR_VIDEO_ENABLE                BIT(4)
> 
>> +
> 
>> +#define ASTDP_EDID_READ_POINTER_MASK  GENMASK(7, 0)
> 
>> +#define ASTDP_EDID_VALID_FLAG_MASK                GENMASK(0, 0)
> 
>> +#define ASTDP_EDID_READ_DATA_MASK        GENMASK(7, 0)
> 
>> +
> 
>> +/*
> 
>> + * ASTDP setmode registers:
> 
>> + * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp)
> 
>> + * CRE1[7:0]: MISC1 (default: 0x00)
> 
>> + * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50)  */
> 
>> +#define ASTDP_MISC0_24bpp                   BIT(5)
> 
>> +#define ASTDP_MISC1                               0
> 
>> +#define ASTDP_CLEAR_MASK                   GENMASK(7, 0)
> 
>> +
> 
>> +/*
> 
>> + * ASTDP resoultion table:
> 
>> + * EX:  ASTDP_A_B_C:
> 
>> + *                A: Resolution
> 
>> + *                B: Refresh Rate
> 
>> + *                C: Misc information, such as CVT, Reduce Blanked
> 
>> + */
> 
>> +#define ASTDP_640x480_60              0x00
> 
>> +#define ASTDP_640x480_72              0x01
> 
>> +#define ASTDP_640x480_75              0x02
> 
>> +#define ASTDP_640x480_85              0x03
> 
>> +#define ASTDP_800x600_56              0x04
> 
>> +#define ASTDP_800x600_60              0x05
> 
>> +#define ASTDP_800x600_72              0x06
> 
>> +#define ASTDP_800x600_75              0x07
> 
>> +#define ASTDP_800x600_85              0x08
> 
>> +#define ASTDP_1024x768_60            0x09
> 
>> +#define ASTDP_1024x768_70            0x0A
> 
>> +#define ASTDP_1024x768_75            0x0B
> 
>> +#define ASTDP_1024x768_85            0x0C
> 
>> +#define ASTDP_1280x1024_60          0x0D
> 
>> +#define ASTDP_1280x1024_75          0x0E
> 
>> +#define ASTDP_1280x1024_85          0x0F
> 
>> +#define ASTDP_1600x1200_60          0x10
> 
>> +#define ASTDP_320x240_60              0x11
> 
>> +#define ASTDP_400x300_60              0x12
> 
>> +#define ASTDP_512x384_60              0x13
> 
>> +#define ASTDP_1920x1200_60          0x14
> 
>> +#define ASTDP_1920x1080_60          0x15
> 
>> +#define ASTDP_1280x800_60            0x16
> 
>> +#define ASTDP_1280x800_60_RB     0x17
> 
>> +#define ASTDP_1440x900_60            0x18
> 
>> +#define ASTDP_1440x900_60_RB     0x19
> 
>> +#define ASTDP_1680x1050_60          0x1A
> 
>> +#define ASTDP_1680x1050_60_RB   0x1B
> 
>> +#define ASTDP_1600x900_60            0x1C
> 
>> +#define ASTDP_1600x900_60_RB     0x1D
> 
>> +#define ASTDP_1366x768_60            0x1E
> 
>> +#define ASTDP_1152x864_75            0x1F
> 
>> +
> 
>>   int ast_mm_init(struct ast_private *ast);
> 
>> 
> 
>>   /* ast post */
> 
>> @@ -381,4 +489,11 @@ void ast_init_3rdtx(struct drm_device *dev);
> 
>>   /* ast_i2c.c */
> 
>>   struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev);
> 
>> 
> 
>> +/* aspeed DP */
> 
>> +int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata); void
> 
>> +ast_dp_launch(struct drm_device *dev, u8 bPower); void
> 
>> +ast_dp_power_on_off(struct drm_device *dev, bool no); void
> 
>> +ast_dp_set_on_off(struct drm_device *dev, bool no); void
> 
>> +ast_dp_set_mode(struct drm_crtc *crtc, struct ast_vbios_mode_info
> 
>> +*vbios_mode);
> 
>> +
> 
>>   #endif
> 
>> diff --git a/drivers/gpu/drm/ast/ast_main.c
> 
>> b/drivers/gpu/drm/ast/ast_main.c index 22e9e2d3c..1113ee1cb 100644
> 
>> --- a/drivers/gpu/drm/ast/ast_main.c
> 
>> +++ b/drivers/gpu/drm/ast/ast_main.c
> 
>> @@ -232,7 +232,7 @@ static int ast_detect_chip(struct drm_device 
>> *dev, bool *need_post)
> 
>>                           ast->tx_chip_type = AST_TX_SIL164;
> 
>>           }
> 
>> 
> 
>> -    if ((ast->chip == AST2300) || (ast->chip == AST2400)) {
> 
>> +   if ((ast->chip == AST2300) || (ast->chip == AST2400) || 
>> +(ast->chip
> 
>> +== AST2500)) {
> 
>>                   /*
> 
>>                    * On AST2300 and 2400, look the configuration set 
>>by the SoC in
> 
>>                    * the SOC scratch register #1 bits 11:8 
>>(interestingly marked @@
> 
>> -256,7 +256,8 @@ static int ast_detect_chip(struct drm_device *dev, 
>> bool *need_post)
> 
>>                   case 0x0c:
> 
>>                           ast->tx_chip_type = AST_TX_DP501;
> 
>>                   }
> 
>> -    }
> 
>> +   } else if (ast->chip == AST2600)
> 
>> +           ast_dp_launch(&ast->base, 0);
> 
>> 
> 
>>           /* Print stuff for diagnostic purposes */
> 
>>           switch(ast->tx_chip_type) {
> 
>> diff --git a/drivers/gpu/drm/ast/ast_mode.c
> 
>> b/drivers/gpu/drm/ast/ast_mode.c index 45b56b39a..4728825b7 100644
> 
>> --- a/drivers/gpu/drm/ast/ast_mode.c
> 
>> +++ b/drivers/gpu/drm/ast/ast_mode.c
> 
>> @@ -988,21 +988,41 @@ static int ast_cursor_plane_init(struct 
>> ast_private *ast)
> 
>>   static void ast_crtc_dpms(struct drm_crtc *crtc, int mode)
> 
>>   {
> 
>>           struct ast_private *ast = to_ast_private(crtc->dev);
> 
>> +   u8 ch = AST_DPMS_VSYNC_OFF | AST_DPMS_HSYNC_OFF;
> 
>> 
> 
>>           /* TODO: Maybe control display signal generation with
> 
>>            *       Sync Enable (bit CR17.7).
> 
>>            */
> 
>>           switch (mode) {
> 
>>           case DRM_MODE_DPMS_ON:
> 
>> -    case DRM_MODE_DPMS_STANDBY:
> 
>> -    case DRM_MODE_DPMS_SUSPEND:
> 
>> +           ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT,  0x01, 0xdf, 
>> +0);
> 
>> +           ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, 
>> +0);
> 
>>                   if (ast->tx_chip_type == AST_TX_DP501)
> 
>>                           ast_set_dp501_video_output(crtc->dev, 1);
> 
>> +
> 
>> +           if (ast->tx_chip_type == AST_TX_ASTDP) {
> 
>> +                   ast_dp_power_on_off(crtc->dev, AST_DP_POWER_ON);
> 
>> +                   ast_wait_for_vretrace(ast);
> 
>> +                   ast_dp_set_on_off(crtc->dev, 1);
> 
>> +           }
> 
>> +
> 
>> +           ast_crtc_load_lut(ast, crtc);
> 
>>                   break;
> 
>> +   case DRM_MODE_DPMS_STANDBY:
> 
>> +   case DRM_MODE_DPMS_SUSPEND:
> 
>>           case DRM_MODE_DPMS_OFF:
> 
>> +           ch = mode;
> 
>>                   if (ast->tx_chip_type == AST_TX_DP501)
> 
>>                           ast_set_dp501_video_output(crtc->dev, 0);
> 
>>                   break;
> 
>> +
> 
>> +           if (ast->tx_chip_type == AST_TX_ASTDP) {
> 
>> +                   ast_dp_set_on_off(crtc->dev, 0);
> 
>> +                   ast_dp_power_on_off(crtc->dev, AST_DP_POWER_OFF);
> 
>> +           }
> 
>> +
> 
>> +           ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT,  0x01, 0xdf, 
>> +0x20);
> 
>> +           ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, 
>> +ch);
> 
>>           }
> 
>>   }
> 
>> 
> 
>> @@ -1027,7 +1047,7 @@ ast_crtc_helper_mode_valid(struct drm_crtc
> 
>> *crtc, const struct drm_display_mode
> 
>> 
> 
>>                   if ((ast->chip == AST2100) || (ast->chip ==
>>AST2200) ||
> 
>>                       (ast->chip == AST2300) || (ast->chip ==
>>AST2400) ||
> 
>> -                (ast->chip == AST2500)) {
> 
>> +               (ast->chip == AST2500) || (ast->chip == AST2600)) {
> 
>>                           if ((mode->hdisplay == 1920) && 
>>(mode->vdisplay == 1080))
> 
>>                                   return MODE_OK;
> 
>> 
> 
>> @@ -1110,6 +1130,7 @@ ast_crtc_helper_atomic_flush(struct drm_crtc 
>> *crtc,
> 
>>           struct ast_private *ast = to_ast_private(crtc->dev);
> 
>>           struct ast_crtc_state *ast_crtc_state = 
>>to_ast_crtc_state(crtc_state);
> 
>>           struct ast_crtc_state *old_ast_crtc_state =
> 
>> to_ast_crtc_state(old_crtc_state);
> 
>> +   struct ast_vbios_mode_info *vbios_mode_info =
> 
>> +&ast_crtc_state->vbios_mode_info;
> 
>> 
> 
>>           /*
> 
>>            * The gamma LUT has to be reloaded after changing the 
>>primary @@
> 
>> -1117,6 +1138,10 @@ ast_crtc_helper_atomic_flush(struct drm_crtc 
>> *crtc,
> 
>>            */
> 
>>           if (old_ast_crtc_state->format != ast_crtc_state->format)
> 
>>                   ast_crtc_load_lut(ast, crtc);
> 
>> +
> 
>> +   //Set Aspeed Display-Port
> 
>> +   if (ast->tx_chip_type == AST_TX_ASTDP)
> 
>> +           ast_dp_set_mode(crtc, vbios_mode_info);
> 
>>   }
> 
>> 
> 
>>   static void
> 
>> @@ -1527,6 +1552,93 @@ static int ast_dp501_output_init(struct 
>> ast_private *ast)
> 
>>           return 0;
> 
>>   }
> 
>> 
> 
>> +/*
> 
>> + * ASPEED Display-Port Connector
> 
>> + */
> 
>> +
> 
>> +static int ast_astdp_connector_helper_get_modes(struct drm_connector
> 
>> +*connector) {
> 
>> +   void *edid;
> 
>> +
> 
>> +   int succ;
> 
>> +   int count;
> 
>> +
> 
>> +   edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
> 
>> +   if (!edid)
> 
>> +           goto err_drm_connector_update_edid_property;
> 
>> +
> 
>> +   succ = ast_astdp_read_edid(connector->dev, edid);
> 
>> +   if (succ < 0)
> 
>> +           goto err_kfree;
> 
>> +
> 
>> +   drm_connector_update_edid_property(connector, edid);
> 
>> +   count = drm_add_edid_modes(connector, edid);
> 
>> +   kfree(edid);
> 
>> +
> 
>> +   return count;
> 
>> +
> 
>> +err_kfree:
> 
>> +   kfree(edid);
> 
>> +err_drm_connector_update_edid_property:
> 
>> +   drm_connector_update_edid_property(connector, NULL);
> 
>> +   return 0;
> 
>> +}
> 
>> +
> 
>> +static const struct drm_connector_helper_funcs 
>> +ast_astdp_connector_helper_funcs = {
> 
>> +   .get_modes = ast_astdp_connector_helper_get_modes,
> 
>> +};
> 
>> +
> 
>> +static const struct drm_connector_funcs ast_astdp_connector_funcs = 
>> +{
> 
>> +   .reset = drm_atomic_helper_connector_reset,
> 
>> +   .fill_modes = drm_helper_probe_single_connector_modes,
> 
>> +   .destroy = drm_connector_cleanup,
> 
>> +   .atomic_duplicate_state =
>> +drm_atomic_helper_connector_duplicate_state,
> 
>> +   .atomic_destroy_state =
>> +drm_atomic_helper_connector_destroy_state,
> 
>> +};
> 
>> +
> 
>> +static int ast_astdp_connector_init(struct drm_device *dev, struct
> 
>> +drm_connector *connector) {
> 
>> +   int ret;
> 
>> +
> 
>> +   ret = drm_connector_init(dev, connector, 
>> +&ast_astdp_connector_funcs,
> 
>> +                           DRM_MODE_CONNECTOR_DisplayPort);
> 
>> +   if (ret)
> 
>> +           return ret;
> 
>> +
> 
>> +   drm_connector_helper_add(connector,
> 
>> +&ast_astdp_connector_helper_funcs);
> 
>> +
> 
>> +   connector->interlace_allowed = 0;
> 
>> +   connector->doublescan_allowed = 0;
> 
>> +
> 
>> +   connector->polled = DRM_CONNECTOR_POLL_CONNECT;
> 
>> +
> 
>> +   return 0;
> 
>> +}
> 
>> +
> 
>> +static int ast_astdp_output_init(struct ast_private *ast) {
> 
>> +   struct drm_device *dev = &ast->base;
> 
>> +   struct drm_crtc *crtc = &ast->crtc;
> 
>> +   struct drm_encoder *encoder = &ast->output.astdp.encoder;
> 
>> +   struct drm_connector *connector = &ast->output.astdp.connector;
> 
>> +   int ret;
> 
>> +
> 
>> +   ret = drm_simple_encoder_init(dev, encoder, 
>> +DRM_MODE_ENCODER_TMDS);
> 
>> +   if (ret)
> 
>> +           return ret;
> 
>> +   encoder->possible_crtcs = drm_crtc_mask(crtc);
> 
>> +
> 
>> +   ret = ast_astdp_connector_init(dev, connector);
> 
>> +   if (ret)
> 
>> +           return ret;
> 
>> +
> 
>> +   ret = drm_connector_attach_encoder(connector, encoder);
> 
>> +   if (ret)
> 
>> +           return ret;
> 
>> +
> 
>> +   return 0;
> 
>> +}
> 
>> +
> 
>>   /*
> 
>>    * Mode config
> 
>>    */
> 
>> @@ -1563,7 +1675,8 @@ int ast_mode_config_init(struct ast_private
>> *ast)
> 
>>               ast->chip == AST2200 ||
> 
>>               ast->chip == AST2300 ||
> 
>>               ast->chip == AST2400 ||
> 
>> -        ast->chip == AST2500) {
> 
>> +       ast->chip == AST2500 ||
> 
>> +       ast->chip == AST2600) {
> 
>>                   dev->mode_config.max_width = 1920;
> 
>>                   dev->mode_config.max_height = 2048;
> 
>>           } else {
> 
>> @@ -1594,6 +1707,9 @@ int ast_mode_config_init(struct ast_private
>> *ast)
> 
>>           case AST_TX_DP501:
> 
>>                   ret = ast_dp501_output_init(ast);
> 
>>                   break;
> 
>> +   case AST_TX_ASTDP:
> 
>> +           ret = ast_astdp_output_init(ast);
> 
>> +           break;
> 
>>           }
> 
>>           if (ret)
> 
>>                   return ret;
> 
>> diff --git a/drivers/gpu/drm/ast/ast_post.c
> 
>> b/drivers/gpu/drm/ast/ast_post.c index b5d92f652..0aa9cf0fb 100644
> 
>> --- a/drivers/gpu/drm/ast/ast_post.c
> 
>> +++ b/drivers/gpu/drm/ast/ast_post.c
> 
>> @@ -379,7 +379,9 @@ void ast_post_gpu(struct drm_device *dev)
> 
>>           ast_enable_mmio(dev);
> 
>>           ast_set_def_ext_reg(dev);
> 
>> 
> 
>> -    if (ast->config_mode == ast_use_p2a) {
> 
>> +   if (ast->chip == AST2600) {
> 
>> +           ast_dp_launch(dev, 1);
> 
>> +   } else if (ast->config_mode == ast_use_p2a) {
> 
>>                   if (ast->chip == AST2500)
> 
>>                           ast_post_chip_2500(dev);
> 
>>                   else if (ast->chip == AST2300 || ast->chip ==
>>AST2400)
> 
>> 
> 
>> base-commit: c54b39a565227538c52ead2349eb17d54aadd6f7
> 
>> --
> 
>> 2.27.0
> 
>> 
> 
> --
> 
> Thomas Zimmermann
> 
> Graphics Driver Developer
> 
> SUSE Software Solutions Germany GmbH
> 
> Maxfeldstr. 5, 90409 Nürnberg, Germany
> 
> (HRB 36809, AG Nürnberg)
> 
> Geschäftsführer: Ivo Totev
> 

--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Ivo Totev

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v4] drm/ast: Create the driver for ASPEED proprietory Display-Port
       [not found]           ` <PSAPR06MB48056FC903142B7F60A3BD388CC39@PSAPR06MB4805.apcprd06.prod.outlook.com>
  2022-05-04  9:37             ` Thomas Zimmermann
@ 2022-05-10 10:56             ` Thomas Zimmermann
  2022-05-13  9:07               ` Kuo-Hsiang Chou
  1 sibling, 1 reply; 21+ messages in thread
From: Thomas Zimmermann @ 2022-05-10 10:56 UTC (permalink / raw)
  To: Kuo-Hsiang Chou, dri-devel, linux-kernel
  Cc: airlied, airlied, daniel, Arc Sung, Tommy Huang, Hungju Huang, Luke Chen


[-- Attachment #1.1: Type: text/plain, Size: 40902 bytes --]

Hi

Am 04.05.22 um 10:49 schrieb Kuo-Hsiang Chou:
> Hi Thomas,
> 
> Thanks for your efforts to review this patch.
> 
> Now, I observe a change that after DP unplugged and then the system is 
> unable to get EDID from D-sub connecting.
> 
> The reason seems that TXs are merged into union structure in 
> /drivers/gpu/drm/ast/ast_drv.h 
>   (a59b026419f33040d7d28b8e3b1cea681b9ce7a7 
> <https://cgit.freedesktop.org/drm/drm-misc/commit/?id=a59b026419f33040d7d28b8e3b1cea681b9ce7a7>)

I have posted a patch that enables multiple parallel outputs. See

 
<https://lore.kernel.org/dri-devel/20220510105010.20712-1-tzimmermann@suse.de/T/#u>

If you have the time, I'd appreciate if you could test it.

Best regards
Thomas

> 
> Another, do you need the ast2600 EVB to ease verification on "drm/ast" ?
> 
> Regards,
> 
>          Kuo-Hsiang Chou
> 
> -----Original Message-----
> From: Thomas Zimmermann [mailto:tzimmermann@suse.de]
> Sent: Wednesday, May 04, 2022 3:28 PM
> To: Kuo-Hsiang Chou <kuohsiang_chou@aspeedtech.com>; 
> dri-devel@lists.freedesktop.org; linux-kernel@vger.kernel.org
> Subject: Re: [PATCH v4] drm/ast: Create the driver for ASPEED 
> proprietory Display-Port
> 
> Hi
> 
> Am 28.04.22 um 09:56 schrieb KuoHsiang Chou:
> 
>> V1:
> 
>> 1. The MCU FW controling ASPEED DP is loaded by BMC boot loader.
> 
>> 2. Driver starts after CR[3:1] == 111b that indicates Tx is ASTDP,
> 
>>     and CRD1[5] has been asserted by BMVC boot loader.
> 
>> 3. EDID is prioritized by DP monitor.
> 
>> 4. DP's EDID has high priority to decide resolution supporting.
> 
>> 
> 
>> V2:
> 
>> Modules description:
> 
>> 1. ASTDP (ASPEED DisplayPort) is controlled by dedicated
> 
>>     AST-MCU (ASPEED propriatary MCU).
> 
>> 2. MCU is looping in charged of HPD, Read EDID, Link Training with
> 
>>     DP sink.
> 
>> 3. ASTDP and AST-MUC reside in BMC (Baseboard Management controller)
> 
>>     addressing-space.
> 
>> 4. ASPEED DRM driver requests MCU to get HPD and EDID by CR-scratched
> 
>>     register.
> 
>> 
> 
>> Booting sequence:
> 
>> 1. Check if TX is ASTDP                                        // ast_dp_launch()
> 
>> 2. Check if DP-MCU FW has loaded                                    // ast_dp_launch()
> 
>> 3. Read EDID                                        // ast_dp_read_edid()
> 
>> 4. Resolution switch                                     // ast_dp_SetOutput()
> 
>> 
> 
>> V3:
> 
>> 1. Remove unneeded semicolon.
> 
>> 2. Apply to git://anongit.freedesktop.org/drm/drm, instead of
> 
>>     git://anongit.freedesktop.org/drm/drm-misc
> 
>> 3. Resolve auto build test WARNINGs on V1 patch.
> 
>> 
> 
>> V4:
> 
>> 1. Sync code-base with kernel 5.17_rc6 2. Remove the define of
> 
>> DPControlPower, because DP chips need to be
> 
>>     powered on to be used.
> 
>> 3. Remove the switches of PHY and Display from EDID procedure.
> 
>> 4. Revise increaing delay to fixed delay, because this version kernel
> 
>>     doesn't detect minitor consistenntly.
> 
>> 5. Create clean-up code used for reset of power state on errors with
> 
>>     -EIO manner.
> 
>> 6. Revise the DP detection by TX type and its DP-FW status during
> 
>>     booting and resume.
> 
>> 7. Correct the CamelCase Style.
> 
>> 8. Use register reading while needing, and remove to hold full
> 
>>     register.
> 
>> 9. Instead of 'u8', revise to 'bool' on swwitch of PHY and video.
> 
>> 10.Correct typo
> 
>> 11.Remove the duplicated copy of TX definition.
> 
>> 12.Use EDID_LENGTH as the constant of 128.
> 
>> 
> 
>> Signed-off-by: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com <mailto:kuohsiang_chou@aspeedtech.com>>
> 
> Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de 
> <mailto:tzimmermann@suse.de>>
> 
> I've meanwhile added your patch to drm-misc-next. It should show up in 
> one of the next kernel releases.  Thanks a lot.
> 
> Best regards
> 
> Thomas
> 
>> ---
> 
>>   drivers/gpu/drm/ast/Makefile   |   2 +-
> 
>>   drivers/gpu/drm/ast/ast_dp.c   | 282 +++++++++++++++++++++++++++++++++
> 
>>   drivers/gpu/drm/ast/ast_drv.h  | 115 ++++++++++++++
> 
>>   drivers/gpu/drm/ast/ast_main.c |   5 +-
> 
>>   drivers/gpu/drm/ast/ast_mode.c | 124 ++++++++++++++-
> 
>>   drivers/gpu/drm/ast/ast_post.c |   4 +-
> 
>>   6 files changed, 524 insertions(+), 8 deletions(-)
> 
>>   create mode 100644 drivers/gpu/drm/ast/ast_dp.c
> 
>> 
> 
>> diff --git a/drivers/gpu/drm/ast/Makefile
> 
>> b/drivers/gpu/drm/ast/Makefile index 21f71160b..5a53ce51f 100644
> 
>> --- a/drivers/gpu/drm/ast/Makefile
> 
>> +++ b/drivers/gpu/drm/ast/Makefile
> 
>> @@ -3,6 +3,6 @@
> 
>>   # Makefile for the drm device driver.  This driver provides support for the
> 
>>   # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
> 
>> 
> 
>> -ast-y := ast_drv.o ast_i2c.o ast_main.o ast_mm.o ast_mode.o
> 
>> ast_post.o ast_dp501.o
> 
>> +ast-y := ast_drv.o ast_i2c.o ast_main.o ast_mm.o ast_mode.o
> 
>> +ast_post.o ast_dp501.o ast_dp.o
> 
>> 
> 
>>   obj-$(CONFIG_DRM_AST) := ast.o
> 
>> diff --git a/drivers/gpu/drm/ast/ast_dp.c
> 
>> b/drivers/gpu/drm/ast/ast_dp.c new file mode 100644 index
> 
>> 000000000..4551bc8a3
> 
>> --- /dev/null
> 
>> +++ b/drivers/gpu/drm/ast/ast_dp.c
> 
>> @@ -0,0 +1,282 @@
> 
>> +// SPDX-License-Identifier: GPL-2.0
> 
>> +// Copyright (c) 2021, ASPEED Technology Inc.
> 
>> +// Authors: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com <mailto:kuohsiang_chou@aspeedtech.com>>
> 
>> +
> 
>> +#include <linux/firmware.h>
> 
>> +#include <linux/delay.h>
> 
>> +#include <drm/drm_print.h>
> 
>> +#include "ast_drv.h"
> 
>> +
> 
>> +int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata) {
> 
>> +   struct ast_private *ast = to_ast_private(dev);
> 
>> +   u8 i = 0, j = 0;
> 
>> +
> 
>> +   /*
> 
>> +   * CRD1[b5]: DP MCU FW is executing
> 
>> +   * CRDC[b0]: DP link success
> 
>> +   * CRDF[b0]: DP HPD
> 
>> +   * CRE5[b0]: Host reading EDID process is done
> 
>> +   */
> 
>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, ASTDP_MCU_FW_EXECUTING) &&
> 
>> +           ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, ASTDP_LINK_SUCCESS) &&
> 
>> +           ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD) &&
> 
>> +           ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
> 
>> +                                                           ASTDP_HOST_EDID_READ_DONE_MASK))) {
> 
>> +           goto err_astdp_edid_not_ready;
> 
>> +   }
> 
>> +
> 
>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
> 
>> +                                                   0x00);
> 
>> +
> 
>> +   for (i = 0; i < 32; i++) {
> 
>> +           /*
> 
>> +           * CRE4[7:0]: Read-Pointer for EDID (Unit: 4bytes); valid range: 0~64
> 
>> +           */
> 
>> +           ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE4,
> 
>> +                                   (u8) ~ASTDP_EDID_READ_POINTER_MASK, (u8) i);
> 
>> +           j = 0;
> 
>> +
> 
>> +           /*
> 
>> +           * CRD7[b0]: valid flag for EDID
> 
>> +           * CRD6[b0]: mirror read pointer for EDID
> 
>> +           */
> 
>> +           while ((ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD7,
> 
>> +                           ASTDP_EDID_VALID_FLAG_MASK) != 0x01) ||
> 
>> +                   (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD6,
> 
>> +                                           ASTDP_EDID_READ_POINTER_MASK) != i)) {
> 
>> +                   /*
> 
>> +                   * Delay are getting longer with each retry.
> 
>> +                   * 1. The Delays are often 2 loops when users request "Display Settings"
> 
>> +                   *      of right-click of mouse.
> 
>> +                   * 2. The Delays are often longer a lot when system resume from S3/S4.
> 
>> +                   */
> 
>> +                   mdelay(j+1);
> 
>> +
> 
>> +                   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1,
> 
>> +                                                   ASTDP_MCU_FW_EXECUTING) &&
> 
>> +                           ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC,
> 
>> +                                                   ASTDP_LINK_SUCCESS) &&
> 
>> +                           ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD))) {
> 
>> +                           goto err_astdp_jump_out_loop_of_edid;
> 
>> +                   }
> 
>> +
> 
>> +                   j++;
> 
>> +                   if (j > 200)
> 
>> +                           goto err_astdp_jump_out_loop_of_edid;
> 
>> +           }
> 
>> +
> 
>> +           *(ediddata) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT,
> 
>> +                                                   0xD8, ASTDP_EDID_READ_DATA_MASK);
> 
>> +           *(ediddata + 1) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD9,
> 
>> +                                                           ASTDP_EDID_READ_DATA_MASK);
> 
>> +           *(ediddata + 2) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDA,
> 
>> +                                                           ASTDP_EDID_READ_DATA_MASK);
> 
>> +           *(ediddata + 3) = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDB,
> 
>> +                                                           ASTDP_EDID_READ_DATA_MASK);
> 
>> +
> 
>> +           if (i == 31) {
> 
>> +                   /*
> 
>> +                   * For 128-bytes EDID_1.3,
> 
>> +                   * 1. Add the value of Bytes-126 to Bytes-127.
> 
>> +                   *            The Bytes-127 is Checksum. Sum of all 128bytes should
> 
>> +                   *            equal 0    (mod 256).
> 
>> +                   * 2. Modify Bytes-126 to be 0.
> 
>> +                   *            The Bytes-126 indicates the Number of extensions to
> 
>> +                   *            follow. 0 represents noextensions.
> 
>> +                   */
> 
>> +                   *(ediddata + 3) = *(ediddata + 3) + *(ediddata + 2);
> 
>> +                   *(ediddata + 2) = 0;
> 
>> +           }
> 
>> +
> 
>> +           ediddata += 4;
> 
>> +   }
> 
>> +
> 
>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
> 
>> +                                                   ASTDP_HOST_EDID_READ_DONE);
> 
>> +
> 
>> +   return 0;
> 
>> +
> 
>> +err_astdp_jump_out_loop_of_edid:
> 
>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
> 
>> +                                                   (u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
> 
>> +                                                   ASTDP_HOST_EDID_READ_DONE);
> 
>> +   return (~(j+256) + 1);
> 
>> +
> 
>> +err_astdp_edid_not_ready:
> 
>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, ASTDP_MCU_FW_EXECUTING)))
> 
>> +           return (~0xD1 + 1);
> 
>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, ASTDP_LINK_SUCCESS)))
> 
>> +           return (~0xDC + 1);
> 
>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD)))
> 
>> +           return (~0xDF + 1);
> 
>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, ASTDP_HOST_EDID_READ_DONE_MASK)))
> 
>> +           return (~0xE5 + 1);
> 
>> +
> 
>> +   return      0;
> 
>> +}
> 
>> +
> 
>> +/*
> 
>> + * Launch Aspeed DP
> 
>> + */
> 
>> +void ast_dp_launch(struct drm_device *dev, u8 bPower) {
> 
>> +   u32 i = 0, j = 0, WaitCount = 1;
> 
>> +   u8 bDPTX = 0;
> 
>> +   u8 bDPExecute = 1;
> 
>> +
> 
>> +   struct ast_private *ast = to_ast_private(dev);
> 
>> +   // S3 come back, need more time to wait BMC ready.
> 
>> +   if (bPower)
> 
>> +           WaitCount = 300;
> 
>> +
> 
>> +
> 
>> +   // Wait total count by different condition.
> 
>> +   for (j = 0; j < WaitCount; j++) {
> 
>> +           bDPTX = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1,
> 
>> +TX_TYPE_MASK);
> 
>> +
> 
>> +           if (bDPTX)
> 
>> +                   break;
> 
>> +
> 
>> +           msleep(100);
> 
>> +   }
> 
>> +
> 
>> +   // 0xE : ASTDP with DPMCU FW handling
> 
>> +   if (bDPTX == ASTDP_DPMCU_TX) {
> 
>> +           // Wait one second then timeout.
> 
>> +           i = 0;
> 
>> +
> 
>> +           while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, COPROCESSOR_LAUNCH) !=
> 
>> +                   COPROCESSOR_LAUNCH) {
> 
>> +                   i++;
> 
>> +                   // wait 100 ms
> 
>> +                   msleep(100);
> 
>> +
> 
>> +                   if (i >= 10) {
> 
>> +                           // DP would not be ready.
> 
>> +                           bDPExecute = 0;
> 
>> +                           break;
> 
>> +                   }
> 
>> +           }
> 
>> +
> 
>> +           if (bDPExecute)
> 
>> +                   ast->tx_chip_type = AST_TX_ASTDP;
> 
>> +
> 
>> +           ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
> 
>> +                                                   (u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
> 
>> +                                                   ASTDP_HOST_EDID_READ_DONE);
> 
>> +   } else
> 
>> +           ast->tx_chip_type = AST_TX_NONE;
> 
>> +}
> 
>> +
> 
>> +
> 
>> +
> 
>> +void ast_dp_power_on_off(struct drm_device *dev, bool on) {
> 
>> +   struct ast_private *ast = to_ast_private(dev);
> 
>> +   // Read and Turn off DP PHY sleep
> 
>> +   u8 bE3 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3,
> 
>> +AST_DP_VIDEO_ENABLE);
> 
>> +
> 
>> +   // Turn on DP PHY sleep
> 
>> +   if (!on)
> 
>> +           bE3 |= AST_DP_PHY_SLEEP;
> 
>> +
> 
>> +   // DP Power on/off
> 
>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, (u8)
> 
>> +~AST_DP_PHY_SLEEP, bE3); }
> 
>> +
> 
>> +
> 
>> +
> 
>> +void ast_dp_set_on_off(struct drm_device *dev, bool on) {
> 
>> +   struct ast_private *ast = to_ast_private(dev);
> 
>> +   u8 video_on_off = on;
> 
>> +
> 
>> +   // Video On/Off
> 
>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, (u8)
> 
>> +~AST_DP_VIDEO_ENABLE, on);
> 
>> +
> 
>> +   // If DP plug in and link successful then check video on / off status
> 
>> +   if (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, ASTDP_LINK_SUCCESS) &&
> 
>> +           ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD)) {
> 
>> +           video_on_off <<= 4;
> 
>> +           while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF,
> 
>> +                                           ASTDP_MIRROR_VIDEO_ENABLE) != video_on_off) {
> 
>> +                   // wait 1 ms
> 
>> +                   mdelay(1);
> 
>> +           }
> 
>> +   }
> 
>> +}
> 
>> +
> 
>> +void ast_dp_set_mode(struct drm_crtc *crtc, struct
> 
>> +ast_vbios_mode_info *vbios_mode) {
> 
>> +   struct ast_private *ast = to_ast_private(crtc->dev);
> 
>> +
> 
>> +   u32 ulRefreshRateIndex;
> 
>> +   u8 ModeIdx;
> 
>> +
> 
>> +   ulRefreshRateIndex = vbios_mode->enh_table->refresh_rate_index - 1;
> 
>> +
> 
>> +   switch (crtc->mode.crtc_hdisplay) {
> 
>> +   case 320:
> 
>> +           ModeIdx = ASTDP_320x240_60;
> 
>> +           break;
> 
>> +   case 400:
> 
>> +           ModeIdx = ASTDP_400x300_60;
> 
>> +           break;
> 
>> +   case 512:
> 
>> +           ModeIdx = ASTDP_512x384_60;
> 
>> +           break;
> 
>> +   case 640:
> 
>> +           ModeIdx = (ASTDP_640x480_60 + (u8) ulRefreshRateIndex);
> 
>> +           break;
> 
>> +   case 800:
> 
>> +           ModeIdx = (ASTDP_800x600_56 + (u8) ulRefreshRateIndex);
> 
>> +           break;
> 
>> +   case 1024:
> 
>> +           ModeIdx = (ASTDP_1024x768_60 + (u8) ulRefreshRateIndex);
> 
>> +           break;
> 
>> +   case 1152:
> 
>> +           ModeIdx = ASTDP_1152x864_75;
> 
>> +           break;
> 
>> +   case 1280:
> 
>> +           if (crtc->mode.crtc_vdisplay == 800)
> 
>> +                   ModeIdx = (ASTDP_1280x800_60_RB - (u8) ulRefreshRateIndex);
> 
>> +           else          // 1024
> 
>> +                   ModeIdx = (ASTDP_1280x1024_60 + (u8) ulRefreshRateIndex);
> 
>> +           break;
> 
>> +   case 1360:
> 
>> +   case 1366:
> 
>> +           ModeIdx = ASTDP_1366x768_60;
> 
>> +           break;
> 
>> +   case 1440:
> 
>> +           ModeIdx = (ASTDP_1440x900_60_RB - (u8) ulRefreshRateIndex);
> 
>> +           break;
> 
>> +   case 1600:
> 
>> +           if (crtc->mode.crtc_vdisplay == 900)
> 
>> +                   ModeIdx = (ASTDP_1600x900_60_RB - (u8) ulRefreshRateIndex);
> 
>> +           else          //1200
> 
>> +                   ModeIdx = ASTDP_1600x1200_60;
> 
>> +           break;
> 
>> +   case 1680:
> 
>> +           ModeIdx = (ASTDP_1680x1050_60_RB - (u8) ulRefreshRateIndex);
> 
>> +           break;
> 
>> +   case 1920:
> 
>> +           if (crtc->mode.crtc_vdisplay == 1080)
> 
>> +                   ModeIdx = ASTDP_1920x1080_60;
> 
>> +           else          //1200
> 
>> +                   ModeIdx = ASTDP_1920x1200_60;
> 
>> +           break;
> 
>> +   default:
> 
>> +           return;
> 
>> +   }
> 
>> +
> 
>> +   /*
> 
>> +   * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp)
> 
>> +   * CRE1[7:0]: MISC1 (default: 0x00)
> 
>> +   * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50)
> 
>> +   */
> 
>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE0, (u8) ~ASTDP_CLEAR_MASK,
> 
>> +                           ASTDP_MISC0_24bpp);
> 
>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE1, (u8) ~ASTDP_CLEAR_MASK, ASTDP_MISC1);
> 
>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE2, (u8)
> 
>> +~ASTDP_CLEAR_MASK, ModeIdx); }
> 
>> diff --git a/drivers/gpu/drm/ast/ast_drv.h
> 
>> b/drivers/gpu/drm/ast/ast_drv.h index a19315b2f..ff1ae314b 100644
> 
>> --- a/drivers/gpu/drm/ast/ast_drv.h
> 
>> +++ b/drivers/gpu/drm/ast/ast_drv.h
> 
>> @@ -70,6 +70,7 @@ enum ast_tx_chip {
> 
>>           AST_TX_NONE,
> 
>>           AST_TX_SIL164,
> 
>>           AST_TX_DP501,
> 
>> +   AST_TX_ASTDP,
> 
>>   };
> 
>> 
> 
>>   #define AST_DRAM_512Mx16 0
> 
>> @@ -184,6 +185,10 @@ struct ast_private {
> 
>>                           struct drm_encoder encoder;
> 
>>                           struct drm_connector connector;
> 
>>                   } dp501;
> 
>> +           struct {
> 
>> +                   struct drm_encoder encoder;
> 
>> +                   struct drm_connector connector;
> 
>> +           } astdp;
> 
>>           } output;
> 
>> 
> 
>>           bool support_wide_screen;
> 
>> @@ -357,10 +362,113 @@ int ast_mode_config_init(struct ast_private *ast);
> 
>>   #define AST_DP501_EDID_DATA    0xf020
> 
>> 
> 
>>   /* Define for Soc scratched reg */
> 
>> +#define COPROCESSOR_LAUNCH                     BIT(5)
> 
>> +
> 
>> +/*
> 
>> + * Display Transmitter Type:
> 
>> + */
> 
>> +#define TX_TYPE_MASK                            GENMASK(3, 1)
> 
>> +#define NO_TX                                           (0 << 1)
> 
>> +#define ITE66121_VBIOS_TX                     (1 << 1)
> 
>> +#define SI164_VBIOS_TX                           (2 << 1)
> 
>> +#define CH7003_VBIOS_TX                       (3 << 1)
> 
>> +#define DP501_VBIOS_TX                         (4 << 1)
> 
>> +#define ANX9807_VBIOS_TX                     (5 << 1)
> 
>> +#define TX_FW_EMBEDDED_FW_TX                (6 << 1)
> 
>> +#define ASTDP_DPMCU_TX                               (7 << 1)
> 
>> +
> 
>>   #define AST_VRAM_INIT_STATUS_MASK       GENMASK(7, 6)
> 
>>   //#define AST_VRAM_INIT_BY_BMC             BIT(7)
> 
>>   //#define AST_VRAM_INIT_READY                BIT(6)
> 
>> 
> 
>> +/* Define for Soc scratched reg used on ASTDP */
> 
>> +#define AST_DP_PHY_SLEEP                     BIT(4)
> 
>> +#define AST_DP_VIDEO_ENABLE              BIT(0)
> 
>> +
> 
>> +#define AST_DP_POWER_ON                    true
> 
>> +#define AST_DP_POWER_OFF                   false
> 
>> +
> 
>> +/*
> 
>> + * CRD1[b5]: DP MCU FW is executing
> 
>> + * CRDC[b0]: DP link success
> 
>> + * CRDF[b0]: DP HPD
> 
>> + * CRE5[b0]: Host reading EDID process is done  */
> 
>> +#define ASTDP_MCU_FW_EXECUTING                     BIT(5)
> 
>> +#define ASTDP_LINK_SUCCESS                          BIT(0)
> 
>> +#define ASTDP_HPD                                          BIT(0)
> 
>> +#define ASTDP_HOST_EDID_READ_DONE                BIT(0)
> 
>> +#define ASTDP_HOST_EDID_READ_DONE_MASK    GENMASK(0, 0)
> 
>> +
> 
>> +/*
> 
>> + * CRB8[b1]: Enable VSYNC off
> 
>> + * CRB8[b0]: Enable HSYNC off
> 
>> + */
> 
>> +#define AST_DPMS_VSYNC_OFF                               BIT(1)
> 
>> +#define AST_DPMS_HSYNC_OFF                               BIT(0)
> 
>> +
> 
>> +/*
> 
>> + * CRDF[b4]: Mirror of AST_DP_VIDEO_ENABLE
> 
>> + * Precondition:  A. ~AST_DP_PHY_SLEEP  &&
> 
>> + *                        B. DP_HPD &&
> 
>> + *                        C. DP_LINK_SUCCESS
> 
>> + */
> 
>> +#define ASTDP_MIRROR_VIDEO_ENABLE                BIT(4)
> 
>> +
> 
>> +#define ASTDP_EDID_READ_POINTER_MASK  GENMASK(7, 0)
> 
>> +#define ASTDP_EDID_VALID_FLAG_MASK                GENMASK(0, 0)
> 
>> +#define ASTDP_EDID_READ_DATA_MASK        GENMASK(7, 0)
> 
>> +
> 
>> +/*
> 
>> + * ASTDP setmode registers:
> 
>> + * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp)
> 
>> + * CRE1[7:0]: MISC1 (default: 0x00)
> 
>> + * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50)  */
> 
>> +#define ASTDP_MISC0_24bpp                   BIT(5)
> 
>> +#define ASTDP_MISC1                               0
> 
>> +#define ASTDP_CLEAR_MASK                   GENMASK(7, 0)
> 
>> +
> 
>> +/*
> 
>> + * ASTDP resoultion table:
> 
>> + * EX:  ASTDP_A_B_C:
> 
>> + *                A: Resolution
> 
>> + *                B: Refresh Rate
> 
>> + *                C: Misc information, such as CVT, Reduce Blanked
> 
>> + */
> 
>> +#define ASTDP_640x480_60              0x00
> 
>> +#define ASTDP_640x480_72              0x01
> 
>> +#define ASTDP_640x480_75              0x02
> 
>> +#define ASTDP_640x480_85              0x03
> 
>> +#define ASTDP_800x600_56              0x04
> 
>> +#define ASTDP_800x600_60              0x05
> 
>> +#define ASTDP_800x600_72              0x06
> 
>> +#define ASTDP_800x600_75              0x07
> 
>> +#define ASTDP_800x600_85              0x08
> 
>> +#define ASTDP_1024x768_60            0x09
> 
>> +#define ASTDP_1024x768_70            0x0A
> 
>> +#define ASTDP_1024x768_75            0x0B
> 
>> +#define ASTDP_1024x768_85            0x0C
> 
>> +#define ASTDP_1280x1024_60          0x0D
> 
>> +#define ASTDP_1280x1024_75          0x0E
> 
>> +#define ASTDP_1280x1024_85          0x0F
> 
>> +#define ASTDP_1600x1200_60          0x10
> 
>> +#define ASTDP_320x240_60              0x11
> 
>> +#define ASTDP_400x300_60              0x12
> 
>> +#define ASTDP_512x384_60              0x13
> 
>> +#define ASTDP_1920x1200_60          0x14
> 
>> +#define ASTDP_1920x1080_60          0x15
> 
>> +#define ASTDP_1280x800_60            0x16
> 
>> +#define ASTDP_1280x800_60_RB     0x17
> 
>> +#define ASTDP_1440x900_60            0x18
> 
>> +#define ASTDP_1440x900_60_RB     0x19
> 
>> +#define ASTDP_1680x1050_60          0x1A
> 
>> +#define ASTDP_1680x1050_60_RB   0x1B
> 
>> +#define ASTDP_1600x900_60            0x1C
> 
>> +#define ASTDP_1600x900_60_RB     0x1D
> 
>> +#define ASTDP_1366x768_60            0x1E
> 
>> +#define ASTDP_1152x864_75            0x1F
> 
>> +
> 
>>   int ast_mm_init(struct ast_private *ast);
> 
>> 
> 
>>   /* ast post */
> 
>> @@ -381,4 +489,11 @@ void ast_init_3rdtx(struct drm_device *dev);
> 
>>   /* ast_i2c.c */
> 
>>   struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev);
> 
>> 
> 
>> +/* aspeed DP */
> 
>> +int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata); void
> 
>> +ast_dp_launch(struct drm_device *dev, u8 bPower); void
> 
>> +ast_dp_power_on_off(struct drm_device *dev, bool no); void
> 
>> +ast_dp_set_on_off(struct drm_device *dev, bool no); void
> 
>> +ast_dp_set_mode(struct drm_crtc *crtc, struct ast_vbios_mode_info
> 
>> +*vbios_mode);
> 
>> +
> 
>>   #endif
> 
>> diff --git a/drivers/gpu/drm/ast/ast_main.c
> 
>> b/drivers/gpu/drm/ast/ast_main.c index 22e9e2d3c..1113ee1cb 100644
> 
>> --- a/drivers/gpu/drm/ast/ast_main.c
> 
>> +++ b/drivers/gpu/drm/ast/ast_main.c
> 
>> @@ -232,7 +232,7 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
> 
>>                           ast->tx_chip_type = AST_TX_SIL164;
> 
>>           }
> 
>> 
> 
>> -    if ((ast->chip == AST2300) || (ast->chip == AST2400)) {
> 
>> +   if ((ast->chip == AST2300) || (ast->chip == AST2400) || (ast->chip
> 
>> +== AST2500)) {
> 
>>                   /*
> 
>>                    * On AST2300 and 2400, look the configuration set by the SoC in
> 
>>                    * the SOC scratch register #1 bits 11:8 (interestingly marked @@
> 
>> -256,7 +256,8 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
> 
>>                   case 0x0c:
> 
>>                           ast->tx_chip_type = AST_TX_DP501;
> 
>>                   }
> 
>> -    }
> 
>> +   } else if (ast->chip == AST2600)
> 
>> +           ast_dp_launch(&ast->base, 0);
> 
>> 
> 
>>           /* Print stuff for diagnostic purposes */
> 
>>           switch(ast->tx_chip_type) {
> 
>> diff --git a/drivers/gpu/drm/ast/ast_mode.c
> 
>> b/drivers/gpu/drm/ast/ast_mode.c index 45b56b39a..4728825b7 100644
> 
>> --- a/drivers/gpu/drm/ast/ast_mode.c
> 
>> +++ b/drivers/gpu/drm/ast/ast_mode.c
> 
>> @@ -988,21 +988,41 @@ static int ast_cursor_plane_init(struct ast_private *ast)
> 
>>   static void ast_crtc_dpms(struct drm_crtc *crtc, int mode)
> 
>>   {
> 
>>           struct ast_private *ast = to_ast_private(crtc->dev);
> 
>> +   u8 ch = AST_DPMS_VSYNC_OFF | AST_DPMS_HSYNC_OFF;
> 
>> 
> 
>>           /* TODO: Maybe control display signal generation with
> 
>>            *       Sync Enable (bit CR17.7).
> 
>>            */
> 
>>           switch (mode) {
> 
>>           case DRM_MODE_DPMS_ON:
> 
>> -    case DRM_MODE_DPMS_STANDBY:
> 
>> -    case DRM_MODE_DPMS_SUSPEND:
> 
>> +           ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT,  0x01, 0xdf, 0);
> 
>> +           ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, 0);
> 
>>                   if (ast->tx_chip_type == AST_TX_DP501)
> 
>>                           ast_set_dp501_video_output(crtc->dev, 1);
> 
>> +
> 
>> +           if (ast->tx_chip_type == AST_TX_ASTDP) {
> 
>> +                   ast_dp_power_on_off(crtc->dev, AST_DP_POWER_ON);
> 
>> +                   ast_wait_for_vretrace(ast);
> 
>> +                   ast_dp_set_on_off(crtc->dev, 1);
> 
>> +           }
> 
>> +
> 
>> +           ast_crtc_load_lut(ast, crtc);
> 
>>                   break;
> 
>> +   case DRM_MODE_DPMS_STANDBY:
> 
>> +   case DRM_MODE_DPMS_SUSPEND:
> 
>>           case DRM_MODE_DPMS_OFF:
> 
>> +           ch = mode;
> 
>>                   if (ast->tx_chip_type == AST_TX_DP501)
> 
>>                           ast_set_dp501_video_output(crtc->dev, 0);
> 
>>                   break;
> 
>> +
> 
>> +           if (ast->tx_chip_type == AST_TX_ASTDP) {
> 
>> +                   ast_dp_set_on_off(crtc->dev, 0);
> 
>> +                   ast_dp_power_on_off(crtc->dev, AST_DP_POWER_OFF);
> 
>> +           }
> 
>> +
> 
>> +           ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT,  0x01, 0xdf, 0x20);
> 
>> +           ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, ch);
> 
>>           }
> 
>>   }
> 
>> 
> 
>> @@ -1027,7 +1047,7 @@ ast_crtc_helper_mode_valid(struct drm_crtc
> 
>> *crtc, const struct drm_display_mode
> 
>> 
> 
>>                   if ((ast->chip == AST2100) || (ast->chip == AST2200) ||
> 
>>                       (ast->chip == AST2300) || (ast->chip == AST2400) ||
> 
>> -                (ast->chip == AST2500)) {
> 
>> +               (ast->chip == AST2500) || (ast->chip == AST2600)) {
> 
>>                           if ((mode->hdisplay == 1920) && (mode->vdisplay == 1080))
> 
>>                                   return MODE_OK;
> 
>> 
> 
>> @@ -1110,6 +1130,7 @@ ast_crtc_helper_atomic_flush(struct drm_crtc *crtc,
> 
>>           struct ast_private *ast = to_ast_private(crtc->dev);
> 
>>           struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
> 
>>           struct ast_crtc_state *old_ast_crtc_state =
> 
>> to_ast_crtc_state(old_crtc_state);
> 
>> +   struct ast_vbios_mode_info *vbios_mode_info =
> 
>> +&ast_crtc_state->vbios_mode_info;
> 
>> 
> 
>>           /*
> 
>>            * The gamma LUT has to be reloaded after changing the primary @@
> 
>> -1117,6 +1138,10 @@ ast_crtc_helper_atomic_flush(struct drm_crtc *crtc,
> 
>>            */
> 
>>           if (old_ast_crtc_state->format != ast_crtc_state->format)
> 
>>                   ast_crtc_load_lut(ast, crtc);
> 
>> +
> 
>> +   //Set Aspeed Display-Port
> 
>> +   if (ast->tx_chip_type == AST_TX_ASTDP)
> 
>> +           ast_dp_set_mode(crtc, vbios_mode_info);
> 
>>   }
> 
>> 
> 
>>   static void
> 
>> @@ -1527,6 +1552,93 @@ static int ast_dp501_output_init(struct ast_private *ast)
> 
>>           return 0;
> 
>>   }
> 
>> 
> 
>> +/*
> 
>> + * ASPEED Display-Port Connector
> 
>> + */
> 
>> +
> 
>> +static int ast_astdp_connector_helper_get_modes(struct drm_connector
> 
>> +*connector) {
> 
>> +   void *edid;
> 
>> +
> 
>> +   int succ;
> 
>> +   int count;
> 
>> +
> 
>> +   edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
> 
>> +   if (!edid)
> 
>> +           goto err_drm_connector_update_edid_property;
> 
>> +
> 
>> +   succ = ast_astdp_read_edid(connector->dev, edid);
> 
>> +   if (succ < 0)
> 
>> +           goto err_kfree;
> 
>> +
> 
>> +   drm_connector_update_edid_property(connector, edid);
> 
>> +   count = drm_add_edid_modes(connector, edid);
> 
>> +   kfree(edid);
> 
>> +
> 
>> +   return count;
> 
>> +
> 
>> +err_kfree:
> 
>> +   kfree(edid);
> 
>> +err_drm_connector_update_edid_property:
> 
>> +   drm_connector_update_edid_property(connector, NULL);
> 
>> +   return 0;
> 
>> +}
> 
>> +
> 
>> +static const struct drm_connector_helper_funcs ast_astdp_connector_helper_funcs = {
> 
>> +   .get_modes = ast_astdp_connector_helper_get_modes,
> 
>> +};
> 
>> +
> 
>> +static const struct drm_connector_funcs ast_astdp_connector_funcs = {
> 
>> +   .reset = drm_atomic_helper_connector_reset,
> 
>> +   .fill_modes = drm_helper_probe_single_connector_modes,
> 
>> +   .destroy = drm_connector_cleanup,
> 
>> +   .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> 
>> +   .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
> 
>> +};
> 
>> +
> 
>> +static int ast_astdp_connector_init(struct drm_device *dev, struct
> 
>> +drm_connector *connector) {
> 
>> +   int ret;
> 
>> +
> 
>> +   ret = drm_connector_init(dev, connector, &ast_astdp_connector_funcs,
> 
>> +                           DRM_MODE_CONNECTOR_DisplayPort);
> 
>> +   if (ret)
> 
>> +           return ret;
> 
>> +
> 
>> +   drm_connector_helper_add(connector,
> 
>> +&ast_astdp_connector_helper_funcs);
> 
>> +
> 
>> +   connector->interlace_allowed = 0;
> 
>> +   connector->doublescan_allowed = 0;
> 
>> +
> 
>> +   connector->polled = DRM_CONNECTOR_POLL_CONNECT;
> 
>> +
> 
>> +   return 0;
> 
>> +}
> 
>> +
> 
>> +static int ast_astdp_output_init(struct ast_private *ast) {
> 
>> +   struct drm_device *dev = &ast->base;
> 
>> +   struct drm_crtc *crtc = &ast->crtc;
> 
>> +   struct drm_encoder *encoder = &ast->output.astdp.encoder;
> 
>> +   struct drm_connector *connector = &ast->output.astdp.connector;
> 
>> +   int ret;
> 
>> +
> 
>> +   ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_TMDS);
> 
>> +   if (ret)
> 
>> +           return ret;
> 
>> +   encoder->possible_crtcs = drm_crtc_mask(crtc);
> 
>> +
> 
>> +   ret = ast_astdp_connector_init(dev, connector);
> 
>> +   if (ret)
> 
>> +           return ret;
> 
>> +
> 
>> +   ret = drm_connector_attach_encoder(connector, encoder);
> 
>> +   if (ret)
> 
>> +           return ret;
> 
>> +
> 
>> +   return 0;
> 
>> +}
> 
>> +
> 
>>   /*
> 
>>    * Mode config
> 
>>    */
> 
>> @@ -1563,7 +1675,8 @@ int ast_mode_config_init(struct ast_private *ast)
> 
>>               ast->chip == AST2200 ||
> 
>>               ast->chip == AST2300 ||
> 
>>               ast->chip == AST2400 ||
> 
>> -        ast->chip == AST2500) {
> 
>> +       ast->chip == AST2500 ||
> 
>> +       ast->chip == AST2600) {
> 
>>                   dev->mode_config.max_width = 1920;
> 
>>                   dev->mode_config.max_height = 2048;
> 
>>           } else {
> 
>> @@ -1594,6 +1707,9 @@ int ast_mode_config_init(struct ast_private *ast)
> 
>>           case AST_TX_DP501:
> 
>>                   ret = ast_dp501_output_init(ast);
> 
>>                   break;
> 
>> +   case AST_TX_ASTDP:
> 
>> +           ret = ast_astdp_output_init(ast);
> 
>> +           break;
> 
>>           }
> 
>>           if (ret)
> 
>>                   return ret;
> 
>> diff --git a/drivers/gpu/drm/ast/ast_post.c
> 
>> b/drivers/gpu/drm/ast/ast_post.c index b5d92f652..0aa9cf0fb 100644
> 
>> --- a/drivers/gpu/drm/ast/ast_post.c
> 
>> +++ b/drivers/gpu/drm/ast/ast_post.c
> 
>> @@ -379,7 +379,9 @@ void ast_post_gpu(struct drm_device *dev)
> 
>>           ast_enable_mmio(dev);
> 
>>           ast_set_def_ext_reg(dev);
> 
>> 
> 
>> -    if (ast->config_mode == ast_use_p2a) {
> 
>> +   if (ast->chip == AST2600) {
> 
>> +           ast_dp_launch(dev, 1);
> 
>> +   } else if (ast->config_mode == ast_use_p2a) {
> 
>>                   if (ast->chip == AST2500)
> 
>>                           ast_post_chip_2500(dev);
> 
>>                   else if (ast->chip == AST2300 || ast->chip == AST2400)
> 
>> 
> 
>> base-commit: c54b39a565227538c52ead2349eb17d54aadd6f7
> 
>> --
> 
>> 2.27.0
> 
>> 
> 
> --
> 
> Thomas Zimmermann
> 
> Graphics Driver Developer
> 
> SUSE Software Solutions Germany GmbH
> 
> Maxfeldstr. 5, 90409 Nürnberg, Germany
> 
> (HRB 36809, AG Nürnberg)
> 
> Geschäftsführer: Ivo Totev
> 

-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Ivo Totev

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 21+ messages in thread

* RE: [PATCH v4] drm/ast: Create the driver for ASPEED proprietory Display-Port
  2022-05-10 10:56             ` Thomas Zimmermann
@ 2022-05-13  9:07               ` Kuo-Hsiang Chou
  2022-05-13 10:20                 ` Thomas Zimmermann
  0 siblings, 1 reply; 21+ messages in thread
From: Kuo-Hsiang Chou @ 2022-05-13  9:07 UTC (permalink / raw)
  To: Thomas Zimmermann, dri-devel, linux-kernel
  Cc: airlied, airlied, daniel, Arc Sung, Tommy Huang, Hungju Huang, Luke Chen



-----Original Message-----
From: Thomas Zimmermann [mailto:tzimmermann@suse.de] 
Sent: Tuesday, May 10, 2022 6:56 PM
To: Kuo-Hsiang Chou <kuohsiang_chou@aspeedtech.com>; dri-devel@lists.freedesktop.org; linux-kernel@vger.kernel.org
Subject: Re: [PATCH v4] drm/ast: Create the driver for ASPEED proprietory Display-Port

Hi

Am 04.05.22 um 10:49 schrieb Kuo-Hsiang Chou:
> Hi Thomas,
> 
> Thanks for your efforts to review this patch.
> 
> Now, I observe a change that after DP unplugged and then the system is 
> unable to get EDID from D-sub connecting.
> 
> The reason seems that TXs are merged into union structure in 
> /drivers/gpu/drm/ast/ast_drv.h
>   (a59b026419f33040d7d28b8e3b1cea681b9ce7a7
> <https://cgit.freedesktop.org/drm/drm-misc/commit/?id=a59b026419f33040
> d7d28b8e3b1cea681b9ce7a7>)

I have posted a patch that enables multiple parallel outputs. See

 
<https://lore.kernel.org/dri-devel/20220510105010.20712-1-tzimmermann@suse.de/T/#u>

If you have the time, I'd appreciate if you could test it.

Hi Thomas,
First, thanks for your efforts on this patch of " enables multiple parallel outputs ".
But it doesn't work. There is still NO EDID got from D-sub after DP unplugged.

Base on your patch, I am trying to find out the solution also.
Final, thanks for your help again!

Regards,
	Kuo-Hsiang Chou

Best regards
Thomas

> 
> Another, do you need the ast2600 EVB to ease verification on "drm/ast" ?
> 
> Regards,
> 
>          Kuo-Hsiang Chou
> 
> -----Original Message-----
> From: Thomas Zimmermann [mailto:tzimmermann@suse.de]
> Sent: Wednesday, May 04, 2022 3:28 PM
> To: Kuo-Hsiang Chou <kuohsiang_chou@aspeedtech.com>; 
> dri-devel@lists.freedesktop.org; linux-kernel@vger.kernel.org
> Subject: Re: [PATCH v4] drm/ast: Create the driver for ASPEED 
> proprietory Display-Port
> 
> Hi
> 
> Am 28.04.22 um 09:56 schrieb KuoHsiang Chou:
> 
>> V1:
> 
>> 1. The MCU FW controling ASPEED DP is loaded by BMC boot loader.
> 
>> 2. Driver starts after CR[3:1] == 111b that indicates Tx is ASTDP,
> 
>>     and CRD1[5] has been asserted by BMVC boot loader.
> 
>> 3. EDID is prioritized by DP monitor.
> 
>> 4. DP's EDID has high priority to decide resolution supporting.
> 
>> 
> 
>> V2:
> 
>> Modules description:
> 
>> 1. ASTDP (ASPEED DisplayPort) is controlled by dedicated
> 
>>     AST-MCU (ASPEED propriatary MCU).
> 
>> 2. MCU is looping in charged of HPD, Read EDID, Link Training with
> 
>>     DP sink.
> 
>> 3. ASTDP and AST-MUC reside in BMC (Baseboard Management controller)
> 
>>     addressing-space.
> 
>> 4. ASPEED DRM driver requests MCU to get HPD and EDID by CR-scratched
> 
>>     register.
> 
>> 
> 
>> Booting sequence:
> 
>> 1. Check if TX is ASTDP                                        // 
>> ast_dp_launch()
> 
>> 2. Check if DP-MCU FW has loaded                                    
>> // ast_dp_launch()
> 
>> 3. Read EDID                                        // 
>> ast_dp_read_edid()
> 
>> 4. Resolution switch                                     // 
>> ast_dp_SetOutput()
> 
>> 
> 
>> V3:
> 
>> 1. Remove unneeded semicolon.
> 
>> 2. Apply to git://anongit.freedesktop.org/drm/drm, instead of
> 
>>     git://anongit.freedesktop.org/drm/drm-misc
> 
>> 3. Resolve auto build test WARNINGs on V1 patch.
> 
>> 
> 
>> V4:
> 
>> 1. Sync code-base with kernel 5.17_rc6 2. Remove the define of
> 
>> DPControlPower, because DP chips need to be
> 
>>     powered on to be used.
> 
>> 3. Remove the switches of PHY and Display from EDID procedure.
> 
>> 4. Revise increaing delay to fixed delay, because this version kernel
> 
>>     doesn't detect minitor consistenntly.
> 
>> 5. Create clean-up code used for reset of power state on errors with
> 
>>     -EIO manner.
> 
>> 6. Revise the DP detection by TX type and its DP-FW status during
> 
>>     booting and resume.
> 
>> 7. Correct the CamelCase Style.
> 
>> 8. Use register reading while needing, and remove to hold full
> 
>>     register.
> 
>> 9. Instead of 'u8', revise to 'bool' on swwitch of PHY and video.
> 
>> 10.Correct typo
> 
>> 11.Remove the duplicated copy of TX definition.
> 
>> 12.Use EDID_LENGTH as the constant of 128.
> 
>> 
> 
>> Signed-off-by: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com 
>> <mailto:kuohsiang_chou@aspeedtech.com>>
> 
> Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de 
> <mailto:tzimmermann@suse.de>>
> 
> I've meanwhile added your patch to drm-misc-next. It should show up in 
> one of the next kernel releases.  Thanks a lot.
> 
> Best regards
> 
> Thomas
> 
>> ---
> 
>>   drivers/gpu/drm/ast/Makefile   |   2 +-
> 
>>   drivers/gpu/drm/ast/ast_dp.c   | 282 
>>+++++++++++++++++++++++++++++++++
> 
>>   drivers/gpu/drm/ast/ast_drv.h  | 115 ++++++++++++++
> 
>>   drivers/gpu/drm/ast/ast_main.c |   5 +-
> 
>>   drivers/gpu/drm/ast/ast_mode.c | 124 ++++++++++++++-
> 
>>   drivers/gpu/drm/ast/ast_post.c |   4 +-
> 
>>   6 files changed, 524 insertions(+), 8 deletions(-)
> 
>>   create mode 100644 drivers/gpu/drm/ast/ast_dp.c
> 
>> 
> 
>> diff --git a/drivers/gpu/drm/ast/Makefile
> 
>> b/drivers/gpu/drm/ast/Makefile index 21f71160b..5a53ce51f 100644
> 
>> --- a/drivers/gpu/drm/ast/Makefile
> 
>> +++ b/drivers/gpu/drm/ast/Makefile
> 
>> @@ -3,6 +3,6 @@
> 
>>   # Makefile for the drm device driver.  This driver provides support 
>>for the
> 
>>   # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
> 
>> 
> 
>> -ast-y := ast_drv.o ast_i2c.o ast_main.o ast_mm.o ast_mode.o
> 
>> ast_post.o ast_dp501.o
> 
>> +ast-y := ast_drv.o ast_i2c.o ast_main.o ast_mm.o ast_mode.o
> 
>> +ast_post.o ast_dp501.o ast_dp.o
> 
>> 
> 
>>   obj-$(CONFIG_DRM_AST) := ast.o
> 
>> diff --git a/drivers/gpu/drm/ast/ast_dp.c
> 
>> b/drivers/gpu/drm/ast/ast_dp.c new file mode 100644 index
> 
>> 000000000..4551bc8a3
> 
>> --- /dev/null
> 
>> +++ b/drivers/gpu/drm/ast/ast_dp.c
> 
>> @@ -0,0 +1,282 @@
> 
>> +// SPDX-License-Identifier: GPL-2.0
> 
>> +// Copyright (c) 2021, ASPEED Technology Inc.
> 
>> +// Authors: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com 
>> +<mailto:kuohsiang_chou@aspeedtech.com>>
> 
>> +
> 
>> +#include <linux/firmware.h>
> 
>> +#include <linux/delay.h>
> 
>> +#include <drm/drm_print.h>
> 
>> +#include "ast_drv.h"
> 
>> +
> 
>> +int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata) {
> 
>> +   struct ast_private *ast = to_ast_private(dev);
> 
>> +   u8 i = 0, j = 0;
> 
>> +
> 
>> +   /*
> 
>> +   * CRD1[b5]: DP MCU FW is executing
> 
>> +   * CRDC[b0]: DP link success
> 
>> +   * CRDF[b0]: DP HPD
> 
>> +   * CRE5[b0]: Host reading EDID process is done
> 
>> +   */
> 
>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, 
>> +ASTDP_MCU_FW_EXECUTING) &&
> 
>> +           ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, 
>> +ASTDP_LINK_SUCCESS) &&
> 
>> +           ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, 
>> +ASTDP_HPD) &&
> 
>> +           ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
> 
>> +                                                           
>> +ASTDP_HOST_EDID_READ_DONE_MASK))) {
> 
>> +           goto err_astdp_edid_not_ready;
> 
>> +   }
> 
>> +
> 
>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8) 
>> +~ASTDP_HOST_EDID_READ_DONE_MASK,
> 
>> +                                                   0x00);
> 
>> +
> 
>> +   for (i = 0; i < 32; i++) {
> 
>> +           /*
> 
>> +           * CRE4[7:0]: Read-Pointer for EDID (Unit: 4bytes); valid 
>> +range: 0~64
> 
>> +           */
> 
>> +           ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE4,
> 
>> +                                   (u8) 
>> +~ASTDP_EDID_READ_POINTER_MASK, (u8) i);
> 
>> +           j = 0;
> 
>> +
> 
>> +           /*
> 
>> +           * CRD7[b0]: valid flag for EDID
> 
>> +           * CRD6[b0]: mirror read pointer for EDID
> 
>> +           */
> 
>> +           while ((ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 
>> +0xD7,
> 
>> +                           ASTDP_EDID_VALID_FLAG_MASK) != 0x01) ||
> 
>> +                   (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 
>> +0xD6,
> 
>> +                                           
>> +ASTDP_EDID_READ_POINTER_MASK) != i)) {
> 
>> +                   /*
> 
>> +                   * Delay are getting longer with each retry.
> 
>> +                   * 1. The Delays are often 2 loops when users request "Display Settings"
> 
>> +                   *      of right-click of mouse.
> 
>> +                   * 2. The Delays are often longer a lot when system resume from S3/S4.
> 
>> +                   */
> 
>> +                   mdelay(j+1);
> 
>> +
> 
>> +                   if (!(ast_get_index_reg_mask(ast, 
>> +AST_IO_CRTC_PORT, 0xD1,
> 
>> +                                                   
>> +ASTDP_MCU_FW_EXECUTING) &&
> 
>> +                           ast_get_index_reg_mask(ast, 
>> +AST_IO_CRTC_PORT, 0xDC,
> 
>> +                                                   
>> +ASTDP_LINK_SUCCESS) &&
> 
>> +                           ast_get_index_reg_mask(ast, 
>> +AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD))) {
> 
>> +                           goto err_astdp_jump_out_loop_of_edid;
> 
>> +                   }
> 
>> +
> 
>> +                   j++;
> 
>> +                   if (j > 200)
> 
>> +                           goto err_astdp_jump_out_loop_of_edid;
> 
>> +           }
> 
>> +
> 
>> +           *(ediddata) = ast_get_index_reg_mask(ast, 
>> +AST_IO_CRTC_PORT,
> 
>> +                                                   0xD8, 
>> +ASTDP_EDID_READ_DATA_MASK);
> 
>> +           *(ediddata + 1) = ast_get_index_reg_mask(ast, 
>> +AST_IO_CRTC_PORT, 0xD9,
> 
>> +                                                           
>> +ASTDP_EDID_READ_DATA_MASK);
> 
>> +           *(ediddata + 2) = ast_get_index_reg_mask(ast, 
>> +AST_IO_CRTC_PORT, 0xDA,
> 
>> +                                                           
>> +ASTDP_EDID_READ_DATA_MASK);
> 
>> +           *(ediddata + 3) = ast_get_index_reg_mask(ast, 
>> +AST_IO_CRTC_PORT, 0xDB,
> 
>> +                                                           
>> +ASTDP_EDID_READ_DATA_MASK);
> 
>> +
> 
>> +           if (i == 31) {
> 
>> +                   /*
> 
>> +                   * For 128-bytes EDID_1.3,
> 
>> +                   * 1. Add the value of Bytes-126 to Bytes-127.
> 
>> +                   *            The Bytes-127 is Checksum. Sum of 
>> +all 128bytes should
> 
>> +                   *            equal 0    (mod 256).
> 
>> +                   * 2. Modify Bytes-126 to be 0.
> 
>> +                   *            The Bytes-126 indicates the Number 
>> +of extensions to
> 
>> +                   *            follow. 0 represents noextensions.
> 
>> +                   */
> 
>> +                   *(ediddata + 3) = *(ediddata + 3) + *(ediddata + 
>> +2);
> 
>> +                   *(ediddata + 2) = 0;
> 
>> +           }
> 
>> +
> 
>> +           ediddata += 4;
> 
>> +   }
> 
>> +
> 
>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8) 
>> +~ASTDP_HOST_EDID_READ_DONE_MASK,
> 
>> +                                                   
>> +ASTDP_HOST_EDID_READ_DONE);
> 
>> +
> 
>> +   return 0;
> 
>> +
> 
>> +err_astdp_jump_out_loop_of_edid:
> 
>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
> 
>> +                                                   (u8) 
>> +~ASTDP_HOST_EDID_READ_DONE_MASK,
> 
>> +                                                   
>> +ASTDP_HOST_EDID_READ_DONE);
> 
>> +   return (~(j+256) + 1);
> 
>> +
> 
>> +err_astdp_edid_not_ready:
> 
>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, 
>> +ASTDP_MCU_FW_EXECUTING)))
> 
>> +           return (~0xD1 + 1);
> 
>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, 
>> +ASTDP_LINK_SUCCESS)))
> 
>> +           return (~0xDC + 1);
> 
>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, 
>> +ASTDP_HPD)))
> 
>> +           return (~0xDF + 1);
> 
>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, 
>> +ASTDP_HOST_EDID_READ_DONE_MASK)))
> 
>> +           return (~0xE5 + 1);
> 
>> +
> 
>> +   return      0;
> 
>> +}
> 
>> +
> 
>> +/*
> 
>> + * Launch Aspeed DP
> 
>> + */
> 
>> +void ast_dp_launch(struct drm_device *dev, u8 bPower) {
> 
>> +   u32 i = 0, j = 0, WaitCount = 1;
> 
>> +   u8 bDPTX = 0;
> 
>> +   u8 bDPExecute = 1;
> 
>> +
> 
>> +   struct ast_private *ast = to_ast_private(dev);
> 
>> +   // S3 come back, need more time to wait BMC ready.
> 
>> +   if (bPower)
> 
>> +           WaitCount = 300;
> 
>> +
> 
>> +
> 
>> +   // Wait total count by different condition.
> 
>> +   for (j = 0; j < WaitCount; j++) {
> 
>> +           bDPTX = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 
>> +0xD1,
> 
>> +TX_TYPE_MASK);
> 
>> +
> 
>> +           if (bDPTX)
> 
>> +                   break;
> 
>> +
> 
>> +           msleep(100);
> 
>> +   }
> 
>> +
> 
>> +   // 0xE : ASTDP with DPMCU FW handling
> 
>> +   if (bDPTX == ASTDP_DPMCU_TX) {
> 
>> +           // Wait one second then timeout.
> 
>> +           i = 0;
> 
>> +
> 
>> +           while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 
>> +0xD1, COPROCESSOR_LAUNCH) !=
> 
>> +                   COPROCESSOR_LAUNCH) {
> 
>> +                   i++;
> 
>> +                   // wait 100 ms
> 
>> +                   msleep(100);
> 
>> +
> 
>> +                   if (i >= 10) {
> 
>> +                           // DP would not be ready.
> 
>> +                           bDPExecute = 0;
> 
>> +                           break;
> 
>> +                   }
> 
>> +           }
> 
>> +
> 
>> +           if (bDPExecute)
> 
>> +                   ast->tx_chip_type = AST_TX_ASTDP;
> 
>> +
> 
>> +           ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
> 
>> +                                                   (u8) 
>> +~ASTDP_HOST_EDID_READ_DONE_MASK,
> 
>> +                                                   
>> +ASTDP_HOST_EDID_READ_DONE);
> 
>> +   } else
> 
>> +           ast->tx_chip_type = AST_TX_NONE;
> 
>> +}
> 
>> +
> 
>> +
> 
>> +
> 
>> +void ast_dp_power_on_off(struct drm_device *dev, bool on) {
> 
>> +   struct ast_private *ast = to_ast_private(dev);
> 
>> +   // Read and Turn off DP PHY sleep
> 
>> +   u8 bE3 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3,
> 
>> +AST_DP_VIDEO_ENABLE);
> 
>> +
> 
>> +   // Turn on DP PHY sleep
> 
>> +   if (!on)
> 
>> +           bE3 |= AST_DP_PHY_SLEEP;
> 
>> +
> 
>> +   // DP Power on/off
> 
>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, (u8)
> 
>> +~AST_DP_PHY_SLEEP, bE3); }
> 
>> +
> 
>> +
> 
>> +
> 
>> +void ast_dp_set_on_off(struct drm_device *dev, bool on) {
> 
>> +   struct ast_private *ast = to_ast_private(dev);
> 
>> +   u8 video_on_off = on;
> 
>> +
> 
>> +   // Video On/Off
> 
>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, (u8)
> 
>> +~AST_DP_VIDEO_ENABLE, on);
> 
>> +
> 
>> +   // If DP plug in and link successful then check video on / off 
>> +status
> 
>> +   if (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, 
>> +ASTDP_LINK_SUCCESS) &&
> 
>> +           ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, 
>> +ASTDP_HPD)) {
> 
>> +           video_on_off <<= 4;
> 
>> +           while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 
>> +0xDF,
> 
>> +                                           
>> +ASTDP_MIRROR_VIDEO_ENABLE) != video_on_off) {
> 
>> +                   // wait 1 ms
> 
>> +                   mdelay(1);
> 
>> +           }
> 
>> +   }
> 
>> +}
> 
>> +
> 
>> +void ast_dp_set_mode(struct drm_crtc *crtc, struct
> 
>> +ast_vbios_mode_info *vbios_mode) {
> 
>> +   struct ast_private *ast = to_ast_private(crtc->dev);
> 
>> +
> 
>> +   u32 ulRefreshRateIndex;
> 
>> +   u8 ModeIdx;
> 
>> +
> 
>> +   ulRefreshRateIndex = vbios_mode->enh_table->refresh_rate_index - 
>> +1;
> 
>> +
> 
>> +   switch (crtc->mode.crtc_hdisplay) {
> 
>> +   case 320:
> 
>> +           ModeIdx = ASTDP_320x240_60;
> 
>> +           break;
> 
>> +   case 400:
> 
>> +           ModeIdx = ASTDP_400x300_60;
> 
>> +           break;
> 
>> +   case 512:
> 
>> +           ModeIdx = ASTDP_512x384_60;
> 
>> +           break;
> 
>> +   case 640:
> 
>> +           ModeIdx = (ASTDP_640x480_60 + (u8) ulRefreshRateIndex);
> 
>> +           break;
> 
>> +   case 800:
> 
>> +           ModeIdx = (ASTDP_800x600_56 + (u8) ulRefreshRateIndex);
> 
>> +           break;
> 
>> +   case 1024:
> 
>> +           ModeIdx = (ASTDP_1024x768_60 + (u8) ulRefreshRateIndex);
> 
>> +           break;
> 
>> +   case 1152:
> 
>> +           ModeIdx = ASTDP_1152x864_75;
> 
>> +           break;
> 
>> +   case 1280:
> 
>> +           if (crtc->mode.crtc_vdisplay == 800)
> 
>> +                   ModeIdx = (ASTDP_1280x800_60_RB - (u8) 
>> +ulRefreshRateIndex);
> 
>> +           else          // 1024
> 
>> +                   ModeIdx = (ASTDP_1280x1024_60 + (u8) 
>> +ulRefreshRateIndex);
> 
>> +           break;
> 
>> +   case 1360:
> 
>> +   case 1366:
> 
>> +           ModeIdx = ASTDP_1366x768_60;
> 
>> +           break;
> 
>> +   case 1440:
> 
>> +           ModeIdx = (ASTDP_1440x900_60_RB - (u8) 
>> +ulRefreshRateIndex);
> 
>> +           break;
> 
>> +   case 1600:
> 
>> +           if (crtc->mode.crtc_vdisplay == 900)
> 
>> +                   ModeIdx = (ASTDP_1600x900_60_RB - (u8) 
>> +ulRefreshRateIndex);
> 
>> +           else          //1200
> 
>> +                   ModeIdx = ASTDP_1600x1200_60;
> 
>> +           break;
> 
>> +   case 1680:
> 
>> +           ModeIdx = (ASTDP_1680x1050_60_RB - (u8) 
>> +ulRefreshRateIndex);
> 
>> +           break;
> 
>> +   case 1920:
> 
>> +           if (crtc->mode.crtc_vdisplay == 1080)
> 
>> +                   ModeIdx = ASTDP_1920x1080_60;
> 
>> +           else          //1200
> 
>> +                   ModeIdx = ASTDP_1920x1200_60;
> 
>> +           break;
> 
>> +   default:
> 
>> +           return;
> 
>> +   }
> 
>> +
> 
>> +   /*
> 
>> +   * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp)
> 
>> +   * CRE1[7:0]: MISC1 (default: 0x00)
> 
>> +   * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50)
> 
>> +   */
> 
>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE0, (u8) 
>> +~ASTDP_CLEAR_MASK,
> 
>> +                           ASTDP_MISC0_24bpp);
> 
>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE1, (u8) 
>> +~ASTDP_CLEAR_MASK, ASTDP_MISC1);
> 
>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE2, (u8)
> 
>> +~ASTDP_CLEAR_MASK, ModeIdx); }
> 
>> diff --git a/drivers/gpu/drm/ast/ast_drv.h
> 
>> b/drivers/gpu/drm/ast/ast_drv.h index a19315b2f..ff1ae314b 100644
> 
>> --- a/drivers/gpu/drm/ast/ast_drv.h
> 
>> +++ b/drivers/gpu/drm/ast/ast_drv.h
> 
>> @@ -70,6 +70,7 @@ enum ast_tx_chip {
> 
>>           AST_TX_NONE,
> 
>>           AST_TX_SIL164,
> 
>>           AST_TX_DP501,
> 
>> +   AST_TX_ASTDP,
> 
>>   };
> 
>> 
> 
>>   #define AST_DRAM_512Mx16 0
> 
>> @@ -184,6 +185,10 @@ struct ast_private {
> 
>>                           struct drm_encoder encoder;
> 
>>                           struct drm_connector connector;
> 
>>                   } dp501;
> 
>> +           struct {
> 
>> +                   struct drm_encoder encoder;
> 
>> +                   struct drm_connector connector;
> 
>> +           } astdp;
> 
>>           } output;
> 
>> 
> 
>>           bool support_wide_screen;
> 
>> @@ -357,10 +362,113 @@ int ast_mode_config_init(struct ast_private 
>> *ast);
> 
>>   #define AST_DP501_EDID_DATA    0xf020
> 
>> 
> 
>>   /* Define for Soc scratched reg */
> 
>> +#define COPROCESSOR_LAUNCH                     BIT(5)
> 
>> +
> 
>> +/*
> 
>> + * Display Transmitter Type:
> 
>> + */
> 
>> +#define TX_TYPE_MASK                            GENMASK(3, 1)
> 
>> +#define NO_TX                                           (0 << 1)
> 
>> +#define ITE66121_VBIOS_TX                     (1 << 1)
> 
>> +#define SI164_VBIOS_TX                           (2 << 1)
> 
>> +#define CH7003_VBIOS_TX                       (3 << 1)
> 
>> +#define DP501_VBIOS_TX                         (4 << 1)
> 
>> +#define ANX9807_VBIOS_TX                     (5 << 1)
> 
>> +#define TX_FW_EMBEDDED_FW_TX                (6 << 1)
> 
>> +#define ASTDP_DPMCU_TX                               (7 << 1)
> 
>> +
> 
>>   #define AST_VRAM_INIT_STATUS_MASK       GENMASK(7, 6)
> 
>>   //#define AST_VRAM_INIT_BY_BMC             BIT(7)
> 
>>   //#define AST_VRAM_INIT_READY                BIT(6)
> 
>> 
> 
>> +/* Define for Soc scratched reg used on ASTDP */
> 
>> +#define AST_DP_PHY_SLEEP                     BIT(4)
> 
>> +#define AST_DP_VIDEO_ENABLE              BIT(0)
> 
>> +
> 
>> +#define AST_DP_POWER_ON                    true
> 
>> +#define AST_DP_POWER_OFF                   false
> 
>> +
> 
>> +/*
> 
>> + * CRD1[b5]: DP MCU FW is executing
> 
>> + * CRDC[b0]: DP link success
> 
>> + * CRDF[b0]: DP HPD
> 
>> + * CRE5[b0]: Host reading EDID process is done  */
> 
>> +#define ASTDP_MCU_FW_EXECUTING                     BIT(5)
> 
>> +#define ASTDP_LINK_SUCCESS                          BIT(0)
> 
>> +#define ASTDP_HPD                                          BIT(0)
> 
>> +#define ASTDP_HOST_EDID_READ_DONE                BIT(0)
> 
>> +#define ASTDP_HOST_EDID_READ_DONE_MASK    GENMASK(0, 0)
> 
>> +
> 
>> +/*
> 
>> + * CRB8[b1]: Enable VSYNC off
> 
>> + * CRB8[b0]: Enable HSYNC off
> 
>> + */
> 
>> +#define AST_DPMS_VSYNC_OFF                               BIT(1)
> 
>> +#define AST_DPMS_HSYNC_OFF                               BIT(0)
> 
>> +
> 
>> +/*
> 
>> + * CRDF[b4]: Mirror of AST_DP_VIDEO_ENABLE
> 
>> + * Precondition:  A. ~AST_DP_PHY_SLEEP  &&
> 
>> + *                        B. DP_HPD &&
> 
>> + *                        C. DP_LINK_SUCCESS
> 
>> + */
> 
>> +#define ASTDP_MIRROR_VIDEO_ENABLE                BIT(4)
> 
>> +
> 
>> +#define ASTDP_EDID_READ_POINTER_MASK  GENMASK(7, 0)
> 
>> +#define ASTDP_EDID_VALID_FLAG_MASK                GENMASK(0, 0)
> 
>> +#define ASTDP_EDID_READ_DATA_MASK        GENMASK(7, 0)
> 
>> +
> 
>> +/*
> 
>> + * ASTDP setmode registers:
> 
>> + * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp)
> 
>> + * CRE1[7:0]: MISC1 (default: 0x00)
> 
>> + * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50)  */
> 
>> +#define ASTDP_MISC0_24bpp                   BIT(5)
> 
>> +#define ASTDP_MISC1                               0
> 
>> +#define ASTDP_CLEAR_MASK                   GENMASK(7, 0)
> 
>> +
> 
>> +/*
> 
>> + * ASTDP resoultion table:
> 
>> + * EX:  ASTDP_A_B_C:
> 
>> + *                A: Resolution
> 
>> + *                B: Refresh Rate
> 
>> + *                C: Misc information, such as CVT, Reduce Blanked
> 
>> + */
> 
>> +#define ASTDP_640x480_60              0x00
> 
>> +#define ASTDP_640x480_72              0x01
> 
>> +#define ASTDP_640x480_75              0x02
> 
>> +#define ASTDP_640x480_85              0x03
> 
>> +#define ASTDP_800x600_56              0x04
> 
>> +#define ASTDP_800x600_60              0x05
> 
>> +#define ASTDP_800x600_72              0x06
> 
>> +#define ASTDP_800x600_75              0x07
> 
>> +#define ASTDP_800x600_85              0x08
> 
>> +#define ASTDP_1024x768_60            0x09
> 
>> +#define ASTDP_1024x768_70            0x0A
> 
>> +#define ASTDP_1024x768_75            0x0B
> 
>> +#define ASTDP_1024x768_85            0x0C
> 
>> +#define ASTDP_1280x1024_60          0x0D
> 
>> +#define ASTDP_1280x1024_75          0x0E
> 
>> +#define ASTDP_1280x1024_85          0x0F
> 
>> +#define ASTDP_1600x1200_60          0x10
> 
>> +#define ASTDP_320x240_60              0x11
> 
>> +#define ASTDP_400x300_60              0x12
> 
>> +#define ASTDP_512x384_60              0x13
> 
>> +#define ASTDP_1920x1200_60          0x14
> 
>> +#define ASTDP_1920x1080_60          0x15
> 
>> +#define ASTDP_1280x800_60            0x16
> 
>> +#define ASTDP_1280x800_60_RB     0x17
> 
>> +#define ASTDP_1440x900_60            0x18
> 
>> +#define ASTDP_1440x900_60_RB     0x19
> 
>> +#define ASTDP_1680x1050_60          0x1A
> 
>> +#define ASTDP_1680x1050_60_RB   0x1B
> 
>> +#define ASTDP_1600x900_60            0x1C
> 
>> +#define ASTDP_1600x900_60_RB     0x1D
> 
>> +#define ASTDP_1366x768_60            0x1E
> 
>> +#define ASTDP_1152x864_75            0x1F
> 
>> +
> 
>>   int ast_mm_init(struct ast_private *ast);
> 
>> 
> 
>>   /* ast post */
> 
>> @@ -381,4 +489,11 @@ void ast_init_3rdtx(struct drm_device *dev);
> 
>>   /* ast_i2c.c */
> 
>>   struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev);
> 
>> 
> 
>> +/* aspeed DP */
> 
>> +int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata); void
> 
>> +ast_dp_launch(struct drm_device *dev, u8 bPower); void
> 
>> +ast_dp_power_on_off(struct drm_device *dev, bool no); void
> 
>> +ast_dp_set_on_off(struct drm_device *dev, bool no); void
> 
>> +ast_dp_set_mode(struct drm_crtc *crtc, struct ast_vbios_mode_info
> 
>> +*vbios_mode);
> 
>> +
> 
>>   #endif
> 
>> diff --git a/drivers/gpu/drm/ast/ast_main.c
> 
>> b/drivers/gpu/drm/ast/ast_main.c index 22e9e2d3c..1113ee1cb 100644
> 
>> --- a/drivers/gpu/drm/ast/ast_main.c
> 
>> +++ b/drivers/gpu/drm/ast/ast_main.c
> 
>> @@ -232,7 +232,7 @@ static int ast_detect_chip(struct drm_device 
>> *dev, bool *need_post)
> 
>>                           ast->tx_chip_type = AST_TX_SIL164;
> 
>>           }
> 
>> 
> 
>> -    if ((ast->chip == AST2300) || (ast->chip == AST2400)) {
> 
>> +   if ((ast->chip == AST2300) || (ast->chip == AST2400) || 
>> +(ast->chip
> 
>> +== AST2500)) {
> 
>>                   /*
> 
>>                    * On AST2300 and 2400, look the configuration set 
>>by the SoC in
> 
>>                    * the SOC scratch register #1 bits 11:8 
>>(interestingly marked @@
> 
>> -256,7 +256,8 @@ static int ast_detect_chip(struct drm_device *dev, 
>> bool *need_post)
> 
>>                   case 0x0c:
> 
>>                           ast->tx_chip_type = AST_TX_DP501;
> 
>>                   }
> 
>> -    }
> 
>> +   } else if (ast->chip == AST2600)
> 
>> +           ast_dp_launch(&ast->base, 0);
> 
>> 
> 
>>           /* Print stuff for diagnostic purposes */
> 
>>           switch(ast->tx_chip_type) {
> 
>> diff --git a/drivers/gpu/drm/ast/ast_mode.c
> 
>> b/drivers/gpu/drm/ast/ast_mode.c index 45b56b39a..4728825b7 100644
> 
>> --- a/drivers/gpu/drm/ast/ast_mode.c
> 
>> +++ b/drivers/gpu/drm/ast/ast_mode.c
> 
>> @@ -988,21 +988,41 @@ static int ast_cursor_plane_init(struct 
>> ast_private *ast)
> 
>>   static void ast_crtc_dpms(struct drm_crtc *crtc, int mode)
> 
>>   {
> 
>>           struct ast_private *ast = to_ast_private(crtc->dev);
> 
>> +   u8 ch = AST_DPMS_VSYNC_OFF | AST_DPMS_HSYNC_OFF;
> 
>> 
> 
>>           /* TODO: Maybe control display signal generation with
> 
>>            *       Sync Enable (bit CR17.7).
> 
>>            */
> 
>>           switch (mode) {
> 
>>           case DRM_MODE_DPMS_ON:
> 
>> -    case DRM_MODE_DPMS_STANDBY:
> 
>> -    case DRM_MODE_DPMS_SUSPEND:
> 
>> +           ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT,  0x01, 0xdf, 
>> +0);
> 
>> +           ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, 
>> +0);
> 
>>                   if (ast->tx_chip_type == AST_TX_DP501)
> 
>>                           ast_set_dp501_video_output(crtc->dev, 1);
> 
>> +
> 
>> +           if (ast->tx_chip_type == AST_TX_ASTDP) {
> 
>> +                   ast_dp_power_on_off(crtc->dev, AST_DP_POWER_ON);
> 
>> +                   ast_wait_for_vretrace(ast);
> 
>> +                   ast_dp_set_on_off(crtc->dev, 1);
> 
>> +           }
> 
>> +
> 
>> +           ast_crtc_load_lut(ast, crtc);
> 
>>                   break;
> 
>> +   case DRM_MODE_DPMS_STANDBY:
> 
>> +   case DRM_MODE_DPMS_SUSPEND:
> 
>>           case DRM_MODE_DPMS_OFF:
> 
>> +           ch = mode;
> 
>>                   if (ast->tx_chip_type == AST_TX_DP501)
> 
>>                           ast_set_dp501_video_output(crtc->dev, 0);
> 
>>                   break;
> 
>> +
> 
>> +           if (ast->tx_chip_type == AST_TX_ASTDP) {
> 
>> +                   ast_dp_set_on_off(crtc->dev, 0);
> 
>> +                   ast_dp_power_on_off(crtc->dev, AST_DP_POWER_OFF);
> 
>> +           }
> 
>> +
> 
>> +           ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT,  0x01, 0xdf, 
>> +0x20);
> 
>> +           ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, 
>> +ch);
> 
>>           }
> 
>>   }
> 
>> 
> 
>> @@ -1027,7 +1047,7 @@ ast_crtc_helper_mode_valid(struct drm_crtc
> 
>> *crtc, const struct drm_display_mode
> 
>> 
> 
>>                   if ((ast->chip == AST2100) || (ast->chip == 
>>AST2200) ||
> 
>>                       (ast->chip == AST2300) || (ast->chip == 
>>AST2400) ||
> 
>> -                (ast->chip == AST2500)) {
> 
>> +               (ast->chip == AST2500) || (ast->chip == AST2600)) {
> 
>>                           if ((mode->hdisplay == 1920) && 
>>(mode->vdisplay == 1080))
> 
>>                                   return MODE_OK;
> 
>> 
> 
>> @@ -1110,6 +1130,7 @@ ast_crtc_helper_atomic_flush(struct drm_crtc 
>> *crtc,
> 
>>           struct ast_private *ast = to_ast_private(crtc->dev);
> 
>>           struct ast_crtc_state *ast_crtc_state = 
>>to_ast_crtc_state(crtc_state);
> 
>>           struct ast_crtc_state *old_ast_crtc_state =
> 
>> to_ast_crtc_state(old_crtc_state);
> 
>> +   struct ast_vbios_mode_info *vbios_mode_info =
> 
>> +&ast_crtc_state->vbios_mode_info;
> 
>> 
> 
>>           /*
> 
>>            * The gamma LUT has to be reloaded after changing the 
>>primary @@
> 
>> -1117,6 +1138,10 @@ ast_crtc_helper_atomic_flush(struct drm_crtc 
>> *crtc,
> 
>>            */
> 
>>           if (old_ast_crtc_state->format != ast_crtc_state->format)
> 
>>                   ast_crtc_load_lut(ast, crtc);
> 
>> +
> 
>> +   //Set Aspeed Display-Port
> 
>> +   if (ast->tx_chip_type == AST_TX_ASTDP)
> 
>> +           ast_dp_set_mode(crtc, vbios_mode_info);
> 
>>   }
> 
>> 
> 
>>   static void
> 
>> @@ -1527,6 +1552,93 @@ static int ast_dp501_output_init(struct 
>> ast_private *ast)
> 
>>           return 0;
> 
>>   }
> 
>> 
> 
>> +/*
> 
>> + * ASPEED Display-Port Connector
> 
>> + */
> 
>> +
> 
>> +static int ast_astdp_connector_helper_get_modes(struct drm_connector
> 
>> +*connector) {
> 
>> +   void *edid;
> 
>> +
> 
>> +   int succ;
> 
>> +   int count;
> 
>> +
> 
>> +   edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
> 
>> +   if (!edid)
> 
>> +           goto err_drm_connector_update_edid_property;
> 
>> +
> 
>> +   succ = ast_astdp_read_edid(connector->dev, edid);
> 
>> +   if (succ < 0)
> 
>> +           goto err_kfree;
> 
>> +
> 
>> +   drm_connector_update_edid_property(connector, edid);
> 
>> +   count = drm_add_edid_modes(connector, edid);
> 
>> +   kfree(edid);
> 
>> +
> 
>> +   return count;
> 
>> +
> 
>> +err_kfree:
> 
>> +   kfree(edid);
> 
>> +err_drm_connector_update_edid_property:
> 
>> +   drm_connector_update_edid_property(connector, NULL);
> 
>> +   return 0;
> 
>> +}
> 
>> +
> 
>> +static const struct drm_connector_helper_funcs 
>> +ast_astdp_connector_helper_funcs = {
> 
>> +   .get_modes = ast_astdp_connector_helper_get_modes,
> 
>> +};
> 
>> +
> 
>> +static const struct drm_connector_funcs ast_astdp_connector_funcs = 
>> +{
> 
>> +   .reset = drm_atomic_helper_connector_reset,
> 
>> +   .fill_modes = drm_helper_probe_single_connector_modes,
> 
>> +   .destroy = drm_connector_cleanup,
> 
>> +   .atomic_duplicate_state = 
>> +drm_atomic_helper_connector_duplicate_state,
> 
>> +   .atomic_destroy_state = 
>> +drm_atomic_helper_connector_destroy_state,
> 
>> +};
> 
>> +
> 
>> +static int ast_astdp_connector_init(struct drm_device *dev, struct
> 
>> +drm_connector *connector) {
> 
>> +   int ret;
> 
>> +
> 
>> +   ret = drm_connector_init(dev, connector, 
>> +&ast_astdp_connector_funcs,
> 
>> +                           DRM_MODE_CONNECTOR_DisplayPort);
> 
>> +   if (ret)
> 
>> +           return ret;
> 
>> +
> 
>> +   drm_connector_helper_add(connector,
> 
>> +&ast_astdp_connector_helper_funcs);
> 
>> +
> 
>> +   connector->interlace_allowed = 0;
> 
>> +   connector->doublescan_allowed = 0;
> 
>> +
> 
>> +   connector->polled = DRM_CONNECTOR_POLL_CONNECT;
> 
>> +
> 
>> +   return 0;
> 
>> +}
> 
>> +
> 
>> +static int ast_astdp_output_init(struct ast_private *ast) {
> 
>> +   struct drm_device *dev = &ast->base;
> 
>> +   struct drm_crtc *crtc = &ast->crtc;
> 
>> +   struct drm_encoder *encoder = &ast->output.astdp.encoder;
> 
>> +   struct drm_connector *connector = &ast->output.astdp.connector;
> 
>> +   int ret;
> 
>> +
> 
>> +   ret = drm_simple_encoder_init(dev, encoder, 
>> +DRM_MODE_ENCODER_TMDS);
> 
>> +   if (ret)
> 
>> +           return ret;
> 
>> +   encoder->possible_crtcs = drm_crtc_mask(crtc);
> 
>> +
> 
>> +   ret = ast_astdp_connector_init(dev, connector);
> 
>> +   if (ret)
> 
>> +           return ret;
> 
>> +
> 
>> +   ret = drm_connector_attach_encoder(connector, encoder);
> 
>> +   if (ret)
> 
>> +           return ret;
> 
>> +
> 
>> +   return 0;
> 
>> +}
> 
>> +
> 
>>   /*
> 
>>    * Mode config
> 
>>    */
> 
>> @@ -1563,7 +1675,8 @@ int ast_mode_config_init(struct ast_private 
>> *ast)
> 
>>               ast->chip == AST2200 ||
> 
>>               ast->chip == AST2300 ||
> 
>>               ast->chip == AST2400 ||
> 
>> -        ast->chip == AST2500) {
> 
>> +       ast->chip == AST2500 ||
> 
>> +       ast->chip == AST2600) {
> 
>>                   dev->mode_config.max_width = 1920;
> 
>>                   dev->mode_config.max_height = 2048;
> 
>>           } else {
> 
>> @@ -1594,6 +1707,9 @@ int ast_mode_config_init(struct ast_private 
>> *ast)
> 
>>           case AST_TX_DP501:
> 
>>                   ret = ast_dp501_output_init(ast);
> 
>>                   break;
> 
>> +   case AST_TX_ASTDP:
> 
>> +           ret = ast_astdp_output_init(ast);
> 
>> +           break;
> 
>>           }
> 
>>           if (ret)
> 
>>                   return ret;
> 
>> diff --git a/drivers/gpu/drm/ast/ast_post.c
> 
>> b/drivers/gpu/drm/ast/ast_post.c index b5d92f652..0aa9cf0fb 100644
> 
>> --- a/drivers/gpu/drm/ast/ast_post.c
> 
>> +++ b/drivers/gpu/drm/ast/ast_post.c
> 
>> @@ -379,7 +379,9 @@ void ast_post_gpu(struct drm_device *dev)
> 
>>           ast_enable_mmio(dev);
> 
>>           ast_set_def_ext_reg(dev);
> 
>> 
> 
>> -    if (ast->config_mode == ast_use_p2a) {
> 
>> +   if (ast->chip == AST2600) {
> 
>> +           ast_dp_launch(dev, 1);
> 
>> +   } else if (ast->config_mode == ast_use_p2a) {
> 
>>                   if (ast->chip == AST2500)
> 
>>                           ast_post_chip_2500(dev);
> 
>>                   else if (ast->chip == AST2300 || ast->chip == 
>>AST2400)
> 
>> 
> 
>> base-commit: c54b39a565227538c52ead2349eb17d54aadd6f7
> 
>> --
> 
>> 2.27.0
> 
>> 
> 
> --
> 
> Thomas Zimmermann
> 
> Graphics Driver Developer
> 
> SUSE Software Solutions Germany GmbH
> 
> Maxfeldstr. 5, 90409 Nürnberg, Germany
> 
> (HRB 36809, AG Nürnberg)
> 
> Geschäftsführer: Ivo Totev
> 

--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Ivo Totev

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v4] drm/ast: Create the driver for ASPEED proprietory Display-Port
  2022-05-13  9:07               ` Kuo-Hsiang Chou
@ 2022-05-13 10:20                 ` Thomas Zimmermann
  2022-05-13 10:39                   ` Kuo-Hsiang Chou
  0 siblings, 1 reply; 21+ messages in thread
From: Thomas Zimmermann @ 2022-05-13 10:20 UTC (permalink / raw)
  To: Kuo-Hsiang Chou, dri-devel, linux-kernel
  Cc: Hungju Huang, airlied, Tommy Huang, airlied, Arc Sung, Luke Chen


[-- Attachment #1.1: Type: text/plain, Size: 42424 bytes --]

Hi

Am 13.05.22 um 11:07 schrieb Kuo-Hsiang Chou:
> 
> 
> -----Original Message-----
> From: Thomas Zimmermann [mailto:tzimmermann@suse.de]
> Sent: Tuesday, May 10, 2022 6:56 PM
> To: Kuo-Hsiang Chou <kuohsiang_chou@aspeedtech.com>; dri-devel@lists.freedesktop.org; linux-kernel@vger.kernel.org
> Subject: Re: [PATCH v4] drm/ast: Create the driver for ASPEED proprietory Display-Port
> 
> Hi
> 
> Am 04.05.22 um 10:49 schrieb Kuo-Hsiang Chou:
>> Hi Thomas,
>>
>> Thanks for your efforts to review this patch.
>>
>> Now, I observe a change that after DP unplugged and then the system is
>> unable to get EDID from D-sub connecting.
>>
>> The reason seems that TXs are merged into union structure in
>> /drivers/gpu/drm/ast/ast_drv.h
>>    (a59b026419f33040d7d28b8e3b1cea681b9ce7a7
>> <https://cgit.freedesktop.org/drm/drm-misc/commit/?id=a59b026419f33040
>> d7d28b8e3b1cea681b9ce7a7>)
> 
> I have posted a patch that enables multiple parallel outputs. See
> 
>   
> <https://lore.kernel.org/dri-devel/20220510105010.20712-1-tzimmermann@suse.de/T/#u>
> 
> If you have the time, I'd appreciate if you could test it.
> 
> Hi Thomas,
> First, thanks for your efforts on this patch of " enables multiple parallel outputs ".
> But it doesn't work. There is still NO EDID got from D-sub after DP unplugged.
> 
> Base on your patch, I am trying to find out the solution also.
> Final, thanks for your help again!

Let's try to find a solution. I might be able to come up with something 
if I have enough information.

How are these outputs connected to each each other?

They are both served by the same CRTC. Can they be used at the same 
time?  Are they mutually exclusive?

Best regards
Thomas

> 
> Regards,
> 	Kuo-Hsiang Chou
> 
> Best regards
> Thomas
> 
>>
>> Another, do you need the ast2600 EVB to ease verification on "drm/ast" ?
>>
>> Regards,
>>
>>           Kuo-Hsiang Chou
>>
>> -----Original Message-----
>> From: Thomas Zimmermann [mailto:tzimmermann@suse.de]
>> Sent: Wednesday, May 04, 2022 3:28 PM
>> To: Kuo-Hsiang Chou <kuohsiang_chou@aspeedtech.com>;
>> dri-devel@lists.freedesktop.org; linux-kernel@vger.kernel.org
>> Subject: Re: [PATCH v4] drm/ast: Create the driver for ASPEED
>> proprietory Display-Port
>>
>> Hi
>>
>> Am 28.04.22 um 09:56 schrieb KuoHsiang Chou:
>>
>>> V1:
>>
>>> 1. The MCU FW controling ASPEED DP is loaded by BMC boot loader.
>>
>>> 2. Driver starts after CR[3:1] == 111b that indicates Tx is ASTDP,
>>
>>>       and CRD1[5] has been asserted by BMVC boot loader.
>>
>>> 3. EDID is prioritized by DP monitor.
>>
>>> 4. DP's EDID has high priority to decide resolution supporting.
>>
>>>
>>
>>> V2:
>>
>>> Modules description:
>>
>>> 1. ASTDP (ASPEED DisplayPort) is controlled by dedicated
>>
>>>       AST-MCU (ASPEED propriatary MCU).
>>
>>> 2. MCU is looping in charged of HPD, Read EDID, Link Training with
>>
>>>       DP sink.
>>
>>> 3. ASTDP and AST-MUC reside in BMC (Baseboard Management controller)
>>
>>>       addressing-space.
>>
>>> 4. ASPEED DRM driver requests MCU to get HPD and EDID by CR-scratched
>>
>>>       register.
>>
>>>
>>
>>> Booting sequence:
>>
>>> 1. Check if TX is ASTDP                                        //
>>> ast_dp_launch()
>>
>>> 2. Check if DP-MCU FW has loaded
>>> // ast_dp_launch()
>>
>>> 3. Read EDID                                        //
>>> ast_dp_read_edid()
>>
>>> 4. Resolution switch                                     //
>>> ast_dp_SetOutput()
>>
>>>
>>
>>> V3:
>>
>>> 1. Remove unneeded semicolon.
>>
>>> 2. Apply to git://anongit.freedesktop.org/drm/drm, instead of
>>
>>>       git://anongit.freedesktop.org/drm/drm-misc
>>
>>> 3. Resolve auto build test WARNINGs on V1 patch.
>>
>>>
>>
>>> V4:
>>
>>> 1. Sync code-base with kernel 5.17_rc6 2. Remove the define of
>>
>>> DPControlPower, because DP chips need to be
>>
>>>       powered on to be used.
>>
>>> 3. Remove the switches of PHY and Display from EDID procedure.
>>
>>> 4. Revise increaing delay to fixed delay, because this version kernel
>>
>>>       doesn't detect minitor consistenntly.
>>
>>> 5. Create clean-up code used for reset of power state on errors with
>>
>>>       -EIO manner.
>>
>>> 6. Revise the DP detection by TX type and its DP-FW status during
>>
>>>       booting and resume.
>>
>>> 7. Correct the CamelCase Style.
>>
>>> 8. Use register reading while needing, and remove to hold full
>>
>>>       register.
>>
>>> 9. Instead of 'u8', revise to 'bool' on swwitch of PHY and video.
>>
>>> 10.Correct typo
>>
>>> 11.Remove the duplicated copy of TX definition.
>>
>>> 12.Use EDID_LENGTH as the constant of 128.
>>
>>>
>>
>>> Signed-off-by: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com
>>> <mailto:kuohsiang_chou@aspeedtech.com>>
>>
>> Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de
>> <mailto:tzimmermann@suse.de>>
>>
>> I've meanwhile added your patch to drm-misc-next. It should show up in
>> one of the next kernel releases.  Thanks a lot.
>>
>> Best regards
>>
>> Thomas
>>
>>> ---
>>
>>>     drivers/gpu/drm/ast/Makefile   |   2 +-
>>
>>>     drivers/gpu/drm/ast/ast_dp.c   | 282
>>> +++++++++++++++++++++++++++++++++
>>
>>>     drivers/gpu/drm/ast/ast_drv.h  | 115 ++++++++++++++
>>
>>>     drivers/gpu/drm/ast/ast_main.c |   5 +-
>>
>>>     drivers/gpu/drm/ast/ast_mode.c | 124 ++++++++++++++-
>>
>>>     drivers/gpu/drm/ast/ast_post.c |   4 +-
>>
>>>     6 files changed, 524 insertions(+), 8 deletions(-)
>>
>>>     create mode 100644 drivers/gpu/drm/ast/ast_dp.c
>>
>>>
>>
>>> diff --git a/drivers/gpu/drm/ast/Makefile
>>
>>> b/drivers/gpu/drm/ast/Makefile index 21f71160b..5a53ce51f 100644
>>
>>> --- a/drivers/gpu/drm/ast/Makefile
>>
>>> +++ b/drivers/gpu/drm/ast/Makefile
>>
>>> @@ -3,6 +3,6 @@
>>
>>>     # Makefile for the drm device driver.  This driver provides support
>>> for the
>>
>>>     # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
>>
>>>
>>
>>> -ast-y := ast_drv.o ast_i2c.o ast_main.o ast_mm.o ast_mode.o
>>
>>> ast_post.o ast_dp501.o
>>
>>> +ast-y := ast_drv.o ast_i2c.o ast_main.o ast_mm.o ast_mode.o
>>
>>> +ast_post.o ast_dp501.o ast_dp.o
>>
>>>
>>
>>>     obj-$(CONFIG_DRM_AST) := ast.o
>>
>>> diff --git a/drivers/gpu/drm/ast/ast_dp.c
>>
>>> b/drivers/gpu/drm/ast/ast_dp.c new file mode 100644 index
>>
>>> 000000000..4551bc8a3
>>
>>> --- /dev/null
>>
>>> +++ b/drivers/gpu/drm/ast/ast_dp.c
>>
>>> @@ -0,0 +1,282 @@
>>
>>> +// SPDX-License-Identifier: GPL-2.0
>>
>>> +// Copyright (c) 2021, ASPEED Technology Inc.
>>
>>> +// Authors: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com
>>> +<mailto:kuohsiang_chou@aspeedtech.com>>
>>
>>> +
>>
>>> +#include <linux/firmware.h>
>>
>>> +#include <linux/delay.h>
>>
>>> +#include <drm/drm_print.h>
>>
>>> +#include "ast_drv.h"
>>
>>> +
>>
>>> +int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata) {
>>
>>> +   struct ast_private *ast = to_ast_private(dev);
>>
>>> +   u8 i = 0, j = 0;
>>
>>> +
>>
>>> +   /*
>>
>>> +   * CRD1[b5]: DP MCU FW is executing
>>
>>> +   * CRDC[b0]: DP link success
>>
>>> +   * CRDF[b0]: DP HPD
>>
>>> +   * CRE5[b0]: Host reading EDID process is done
>>
>>> +   */
>>
>>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1,
>>> +ASTDP_MCU_FW_EXECUTING) &&
>>
>>> +           ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC,
>>> +ASTDP_LINK_SUCCESS) &&
>>
>>> +           ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF,
>>> +ASTDP_HPD) &&
>>
>>> +           ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
>>
>>> +
>>> +ASTDP_HOST_EDID_READ_DONE_MASK))) {
>>
>>> +           goto err_astdp_edid_not_ready;
>>
>>> +   }
>>
>>> +
>>
>>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8)
>>> +~ASTDP_HOST_EDID_READ_DONE_MASK,
>>
>>> +                                                   0x00);
>>
>>> +
>>
>>> +   for (i = 0; i < 32; i++) {
>>
>>> +           /*
>>
>>> +           * CRE4[7:0]: Read-Pointer for EDID (Unit: 4bytes); valid
>>> +range: 0~64
>>
>>> +           */
>>
>>> +           ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE4,
>>
>>> +                                   (u8)
>>> +~ASTDP_EDID_READ_POINTER_MASK, (u8) i);
>>
>>> +           j = 0;
>>
>>> +
>>
>>> +           /*
>>
>>> +           * CRD7[b0]: valid flag for EDID
>>
>>> +           * CRD6[b0]: mirror read pointer for EDID
>>
>>> +           */
>>
>>> +           while ((ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT,
>>> +0xD7,
>>
>>> +                           ASTDP_EDID_VALID_FLAG_MASK) != 0x01) ||
>>
>>> +                   (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT,
>>> +0xD6,
>>
>>> +
>>> +ASTDP_EDID_READ_POINTER_MASK) != i)) {
>>
>>> +                   /*
>>
>>> +                   * Delay are getting longer with each retry.
>>
>>> +                   * 1. The Delays are often 2 loops when users request "Display Settings"
>>
>>> +                   *      of right-click of mouse.
>>
>>> +                   * 2. The Delays are often longer a lot when system resume from S3/S4.
>>
>>> +                   */
>>
>>> +                   mdelay(j+1);
>>
>>> +
>>
>>> +                   if (!(ast_get_index_reg_mask(ast,
>>> +AST_IO_CRTC_PORT, 0xD1,
>>
>>> +
>>> +ASTDP_MCU_FW_EXECUTING) &&
>>
>>> +                           ast_get_index_reg_mask(ast,
>>> +AST_IO_CRTC_PORT, 0xDC,
>>
>>> +
>>> +ASTDP_LINK_SUCCESS) &&
>>
>>> +                           ast_get_index_reg_mask(ast,
>>> +AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD))) {
>>
>>> +                           goto err_astdp_jump_out_loop_of_edid;
>>
>>> +                   }
>>
>>> +
>>
>>> +                   j++;
>>
>>> +                   if (j > 200)
>>
>>> +                           goto err_astdp_jump_out_loop_of_edid;
>>
>>> +           }
>>
>>> +
>>
>>> +           *(ediddata) = ast_get_index_reg_mask(ast,
>>> +AST_IO_CRTC_PORT,
>>
>>> +                                                   0xD8,
>>> +ASTDP_EDID_READ_DATA_MASK);
>>
>>> +           *(ediddata + 1) = ast_get_index_reg_mask(ast,
>>> +AST_IO_CRTC_PORT, 0xD9,
>>
>>> +
>>> +ASTDP_EDID_READ_DATA_MASK);
>>
>>> +           *(ediddata + 2) = ast_get_index_reg_mask(ast,
>>> +AST_IO_CRTC_PORT, 0xDA,
>>
>>> +
>>> +ASTDP_EDID_READ_DATA_MASK);
>>
>>> +           *(ediddata + 3) = ast_get_index_reg_mask(ast,
>>> +AST_IO_CRTC_PORT, 0xDB,
>>
>>> +
>>> +ASTDP_EDID_READ_DATA_MASK);
>>
>>> +
>>
>>> +           if (i == 31) {
>>
>>> +                   /*
>>
>>> +                   * For 128-bytes EDID_1.3,
>>
>>> +                   * 1. Add the value of Bytes-126 to Bytes-127.
>>
>>> +                   *            The Bytes-127 is Checksum. Sum of
>>> +all 128bytes should
>>
>>> +                   *            equal 0    (mod 256).
>>
>>> +                   * 2. Modify Bytes-126 to be 0.
>>
>>> +                   *            The Bytes-126 indicates the Number
>>> +of extensions to
>>
>>> +                   *            follow. 0 represents noextensions.
>>
>>> +                   */
>>
>>> +                   *(ediddata + 3) = *(ediddata + 3) + *(ediddata +
>>> +2);
>>
>>> +                   *(ediddata + 2) = 0;
>>
>>> +           }
>>
>>> +
>>
>>> +           ediddata += 4;
>>
>>> +   }
>>
>>> +
>>
>>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8)
>>> +~ASTDP_HOST_EDID_READ_DONE_MASK,
>>
>>> +
>>> +ASTDP_HOST_EDID_READ_DONE);
>>
>>> +
>>
>>> +   return 0;
>>
>>> +
>>
>>> +err_astdp_jump_out_loop_of_edid:
>>
>>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
>>
>>> +                                                   (u8)
>>> +~ASTDP_HOST_EDID_READ_DONE_MASK,
>>
>>> +
>>> +ASTDP_HOST_EDID_READ_DONE);
>>
>>> +   return (~(j+256) + 1);
>>
>>> +
>>
>>> +err_astdp_edid_not_ready:
>>
>>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1,
>>> +ASTDP_MCU_FW_EXECUTING)))
>>
>>> +           return (~0xD1 + 1);
>>
>>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC,
>>> +ASTDP_LINK_SUCCESS)))
>>
>>> +           return (~0xDC + 1);
>>
>>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF,
>>> +ASTDP_HPD)))
>>
>>> +           return (~0xDF + 1);
>>
>>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
>>> +ASTDP_HOST_EDID_READ_DONE_MASK)))
>>
>>> +           return (~0xE5 + 1);
>>
>>> +
>>
>>> +   return      0;
>>
>>> +}
>>
>>> +
>>
>>> +/*
>>
>>> + * Launch Aspeed DP
>>
>>> + */
>>
>>> +void ast_dp_launch(struct drm_device *dev, u8 bPower) {
>>
>>> +   u32 i = 0, j = 0, WaitCount = 1;
>>
>>> +   u8 bDPTX = 0;
>>
>>> +   u8 bDPExecute = 1;
>>
>>> +
>>
>>> +   struct ast_private *ast = to_ast_private(dev);
>>
>>> +   // S3 come back, need more time to wait BMC ready.
>>
>>> +   if (bPower)
>>
>>> +           WaitCount = 300;
>>
>>> +
>>
>>> +
>>
>>> +   // Wait total count by different condition.
>>
>>> +   for (j = 0; j < WaitCount; j++) {
>>
>>> +           bDPTX = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT,
>>> +0xD1,
>>
>>> +TX_TYPE_MASK);
>>
>>> +
>>
>>> +           if (bDPTX)
>>
>>> +                   break;
>>
>>> +
>>
>>> +           msleep(100);
>>
>>> +   }
>>
>>> +
>>
>>> +   // 0xE : ASTDP with DPMCU FW handling
>>
>>> +   if (bDPTX == ASTDP_DPMCU_TX) {
>>
>>> +           // Wait one second then timeout.
>>
>>> +           i = 0;
>>
>>> +
>>
>>> +           while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT,
>>> +0xD1, COPROCESSOR_LAUNCH) !=
>>
>>> +                   COPROCESSOR_LAUNCH) {
>>
>>> +                   i++;
>>
>>> +                   // wait 100 ms
>>
>>> +                   msleep(100);
>>
>>> +
>>
>>> +                   if (i >= 10) {
>>
>>> +                           // DP would not be ready.
>>
>>> +                           bDPExecute = 0;
>>
>>> +                           break;
>>
>>> +                   }
>>
>>> +           }
>>
>>> +
>>
>>> +           if (bDPExecute)
>>
>>> +                   ast->tx_chip_type = AST_TX_ASTDP;
>>
>>> +
>>
>>> +           ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
>>
>>> +                                                   (u8)
>>> +~ASTDP_HOST_EDID_READ_DONE_MASK,
>>
>>> +
>>> +ASTDP_HOST_EDID_READ_DONE);
>>
>>> +   } else
>>
>>> +           ast->tx_chip_type = AST_TX_NONE;
>>
>>> +}
>>
>>> +
>>
>>> +
>>
>>> +
>>
>>> +void ast_dp_power_on_off(struct drm_device *dev, bool on) {
>>
>>> +   struct ast_private *ast = to_ast_private(dev);
>>
>>> +   // Read and Turn off DP PHY sleep
>>
>>> +   u8 bE3 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3,
>>
>>> +AST_DP_VIDEO_ENABLE);
>>
>>> +
>>
>>> +   // Turn on DP PHY sleep
>>
>>> +   if (!on)
>>
>>> +           bE3 |= AST_DP_PHY_SLEEP;
>>
>>> +
>>
>>> +   // DP Power on/off
>>
>>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, (u8)
>>
>>> +~AST_DP_PHY_SLEEP, bE3); }
>>
>>> +
>>
>>> +
>>
>>> +
>>
>>> +void ast_dp_set_on_off(struct drm_device *dev, bool on) {
>>
>>> +   struct ast_private *ast = to_ast_private(dev);
>>
>>> +   u8 video_on_off = on;
>>
>>> +
>>
>>> +   // Video On/Off
>>
>>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, (u8)
>>
>>> +~AST_DP_VIDEO_ENABLE, on);
>>
>>> +
>>
>>> +   // If DP plug in and link successful then check video on / off
>>> +status
>>
>>> +   if (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC,
>>> +ASTDP_LINK_SUCCESS) &&
>>
>>> +           ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF,
>>> +ASTDP_HPD)) {
>>
>>> +           video_on_off <<= 4;
>>
>>> +           while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT,
>>> +0xDF,
>>
>>> +
>>> +ASTDP_MIRROR_VIDEO_ENABLE) != video_on_off) {
>>
>>> +                   // wait 1 ms
>>
>>> +                   mdelay(1);
>>
>>> +           }
>>
>>> +   }
>>
>>> +}
>>
>>> +
>>
>>> +void ast_dp_set_mode(struct drm_crtc *crtc, struct
>>
>>> +ast_vbios_mode_info *vbios_mode) {
>>
>>> +   struct ast_private *ast = to_ast_private(crtc->dev);
>>
>>> +
>>
>>> +   u32 ulRefreshRateIndex;
>>
>>> +   u8 ModeIdx;
>>
>>> +
>>
>>> +   ulRefreshRateIndex = vbios_mode->enh_table->refresh_rate_index -
>>> +1;
>>
>>> +
>>
>>> +   switch (crtc->mode.crtc_hdisplay) {
>>
>>> +   case 320:
>>
>>> +           ModeIdx = ASTDP_320x240_60;
>>
>>> +           break;
>>
>>> +   case 400:
>>
>>> +           ModeIdx = ASTDP_400x300_60;
>>
>>> +           break;
>>
>>> +   case 512:
>>
>>> +           ModeIdx = ASTDP_512x384_60;
>>
>>> +           break;
>>
>>> +   case 640:
>>
>>> +           ModeIdx = (ASTDP_640x480_60 + (u8) ulRefreshRateIndex);
>>
>>> +           break;
>>
>>> +   case 800:
>>
>>> +           ModeIdx = (ASTDP_800x600_56 + (u8) ulRefreshRateIndex);
>>
>>> +           break;
>>
>>> +   case 1024:
>>
>>> +           ModeIdx = (ASTDP_1024x768_60 + (u8) ulRefreshRateIndex);
>>
>>> +           break;
>>
>>> +   case 1152:
>>
>>> +           ModeIdx = ASTDP_1152x864_75;
>>
>>> +           break;
>>
>>> +   case 1280:
>>
>>> +           if (crtc->mode.crtc_vdisplay == 800)
>>
>>> +                   ModeIdx = (ASTDP_1280x800_60_RB - (u8)
>>> +ulRefreshRateIndex);
>>
>>> +           else          // 1024
>>
>>> +                   ModeIdx = (ASTDP_1280x1024_60 + (u8)
>>> +ulRefreshRateIndex);
>>
>>> +           break;
>>
>>> +   case 1360:
>>
>>> +   case 1366:
>>
>>> +           ModeIdx = ASTDP_1366x768_60;
>>
>>> +           break;
>>
>>> +   case 1440:
>>
>>> +           ModeIdx = (ASTDP_1440x900_60_RB - (u8)
>>> +ulRefreshRateIndex);
>>
>>> +           break;
>>
>>> +   case 1600:
>>
>>> +           if (crtc->mode.crtc_vdisplay == 900)
>>
>>> +                   ModeIdx = (ASTDP_1600x900_60_RB - (u8)
>>> +ulRefreshRateIndex);
>>
>>> +           else          //1200
>>
>>> +                   ModeIdx = ASTDP_1600x1200_60;
>>
>>> +           break;
>>
>>> +   case 1680:
>>
>>> +           ModeIdx = (ASTDP_1680x1050_60_RB - (u8)
>>> +ulRefreshRateIndex);
>>
>>> +           break;
>>
>>> +   case 1920:
>>
>>> +           if (crtc->mode.crtc_vdisplay == 1080)
>>
>>> +                   ModeIdx = ASTDP_1920x1080_60;
>>
>>> +           else          //1200
>>
>>> +                   ModeIdx = ASTDP_1920x1200_60;
>>
>>> +           break;
>>
>>> +   default:
>>
>>> +           return;
>>
>>> +   }
>>
>>> +
>>
>>> +   /*
>>
>>> +   * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp)
>>
>>> +   * CRE1[7:0]: MISC1 (default: 0x00)
>>
>>> +   * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50)
>>
>>> +   */
>>
>>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE0, (u8)
>>> +~ASTDP_CLEAR_MASK,
>>
>>> +                           ASTDP_MISC0_24bpp);
>>
>>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE1, (u8)
>>> +~ASTDP_CLEAR_MASK, ASTDP_MISC1);
>>
>>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE2, (u8)
>>
>>> +~ASTDP_CLEAR_MASK, ModeIdx); }
>>
>>> diff --git a/drivers/gpu/drm/ast/ast_drv.h
>>
>>> b/drivers/gpu/drm/ast/ast_drv.h index a19315b2f..ff1ae314b 100644
>>
>>> --- a/drivers/gpu/drm/ast/ast_drv.h
>>
>>> +++ b/drivers/gpu/drm/ast/ast_drv.h
>>
>>> @@ -70,6 +70,7 @@ enum ast_tx_chip {
>>
>>>             AST_TX_NONE,
>>
>>>             AST_TX_SIL164,
>>
>>>             AST_TX_DP501,
>>
>>> +   AST_TX_ASTDP,
>>
>>>     };
>>
>>>
>>
>>>     #define AST_DRAM_512Mx16 0
>>
>>> @@ -184,6 +185,10 @@ struct ast_private {
>>
>>>                             struct drm_encoder encoder;
>>
>>>                             struct drm_connector connector;
>>
>>>                     } dp501;
>>
>>> +           struct {
>>
>>> +                   struct drm_encoder encoder;
>>
>>> +                   struct drm_connector connector;
>>
>>> +           } astdp;
>>
>>>             } output;
>>
>>>
>>
>>>             bool support_wide_screen;
>>
>>> @@ -357,10 +362,113 @@ int ast_mode_config_init(struct ast_private
>>> *ast);
>>
>>>     #define AST_DP501_EDID_DATA    0xf020
>>
>>>
>>
>>>     /* Define for Soc scratched reg */
>>
>>> +#define COPROCESSOR_LAUNCH                     BIT(5)
>>
>>> +
>>
>>> +/*
>>
>>> + * Display Transmitter Type:
>>
>>> + */
>>
>>> +#define TX_TYPE_MASK                            GENMASK(3, 1)
>>
>>> +#define NO_TX   ��                                       (0 << 1)
>>
>>> +#define ITE66121_VBIOS_TX                     (1 << 1)
>>
>>> +#define SI164_VBIOS_TX                           (2 << 1)
>>
>>> +#define CH7003_VBIOS_TX                       (3 << 1)
>>
>>> +#define DP501_VBIOS_TX                         (4 << 1)
>>
>>> +#define ANX9807_VBIOS_TX                     (5 << 1)
>>
>>> +#define TX_FW_EMBEDDED_FW_TX                (6 << 1)
>>
>>> +#define ASTDP_DPMCU_TX                               (7 << 1)
>>
>>> +
>>
>>>     #define AST_VRAM_INIT_STATUS_MASK       GENMASK(7, 6)
>>
>>>     //#define AST_VRAM_INIT_BY_BMC             BIT(7)
>>
>>>     //#define AST_VRAM_INIT_READY                BIT(6)
>>
>>>
>>
>>> +/* Define for Soc scratched reg used on ASTDP */
>>
>>> +#define AST_DP_PHY_SLEEP                     BIT(4)
>>
>>> +#define AST_DP_VIDEO_ENABLE              BIT(0)
>>
>>> +
>>
>>> +#define AST_DP_POWER_ON                    true
>>
>>> +#define AST_DP_POWER_OFF                   false
>>
>>> +
>>
>>> +/*
>>
>>> + * CRD1[b5]: DP MCU FW is executing
>>
>>> + * CRDC[b0]: DP link success
>>
>>> + * CRDF[b0]: DP HPD
>>
>>> + * CRE5[b0]: Host reading EDID process is done  */
>>
>>> +#define ASTDP_MCU_FW_EXECUTING                     BIT(5)
>>
>>> +#define ASTDP_LINK_SUCCESS                          BIT(0)
>>
>>> +#define ASTDP_HPD                                          BIT(0)
>>
>>> +#define ASTDP_HOST_EDID_READ_DONE                BIT(0)
>>
>>> +#define ASTDP_HOST_EDID_READ_DONE_MASK    GENMASK(0, 0)
>>
>>> +
>>
>>> +/*
>>
>>> + * CRB8[b1]: Enable VSYNC off
>>
>>> + * CRB8[b0]: Enable HSYNC off
>>
>>> + */
>>
>>> +#define AST_DPMS_VSYNC_OFF                               BIT(1)
>>
>>> +#define AST_DPMS_HSYNC_OFF                               BIT(0)
>>
>>> +
>>
>>> +/*
>>
>>> + * CRDF[b4]: Mirror of AST_DP_VIDEO_ENABLE
>>
>>> + * Precondition:  A. ~AST_DP_PHY_SLEEP  &&
>>
>>> + *                        B. DP_HPD &&
>>
>>> + *                        C. DP_LINK_SUCCESS
>>
>>> + */
>>
>>> +#define ASTDP_MIRROR_VIDEO_ENABLE                BIT(4)
>>
>>> +
>>
>>> +#define ASTDP_EDID_READ_POINTER_MASK  GENMASK(7, 0)
>>
>>> +#define ASTDP_EDID_VALID_FLAG_MASK                GENMASK(0, 0)
>>
>>> +#define ASTDP_EDID_READ_DATA_MASK        GENMASK(7, 0)
>>
>>> +
>>
>>> +/*
>>
>>> + * ASTDP setmode registers:
>>
>>> + * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp)
>>
>>> + * CRE1[7:0]: MISC1 (default: 0x00)
>>
>>> + * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50)  */
>>
>>> +#define ASTDP_MISC0_24bpp                   BIT(5)
>>
>>> +#define ASTDP_MISC1                               0
>>
>>> +#define ASTDP_CLEAR_MASK                   GENMASK(7, 0)
>>
>>> +
>>
>>> +/*
>>
>>> + * ASTDP resoultion table:
>>
>>> + * EX:  ASTDP_A_B_C:
>>
>>> + *                A: Resolution
>>
>>> + *                B: Refresh Rate
>>
>>> + *                C: Misc information, such as CVT, Reduce Blanked
>>
>>> + */
>>
>>> +#define ASTDP_640x480_60              0x00
>>
>>> +#define ASTDP_640x480_72              0x01
>>
>>> +#define ASTDP_640x480_75              0x02
>>
>>> +#define ASTDP_640x480_85              0x03
>>
>>> +#define ASTDP_800x600_56              0x04
>>
>>> +#define ASTDP_800x600_60              0x05
>>
>>> +#define ASTDP_800x600_72              0x06
>>
>>> +#define ASTDP_800x600_75              0x07
>>
>>> +#define ASTDP_800x600_85              0x08
>>
>>> +#define ASTDP_1024x768_60            0x09
>>
>>> +#define ASTDP_1024x768_70            0x0A
>>
>>> +#define ASTDP_1024x768_75            0x0B
>>
>>> +#define ASTDP_1024x768_85            0x0C
>>
>>> +#define ASTDP_1280x1024_60          0x0D
>>
>>> +#define ASTDP_1280x1024_75          0x0E
>>
>>> +#define ASTDP_1280x1024_85          0x0F
>>
>>> +#define ASTDP_1600x1200_60          0x10
>>
>>> +#define ASTDP_320x240_60              0x11
>>
>>> +#define ASTDP_400x300_60              0x12
>>
>>> +#define ASTDP_512x384_60              0x13
>>
>>> +#define ASTDP_1920x1200_60          0x14
>>
>>> +#define ASTDP_1920x1080_60          0x15
>>
>>> +#define ASTDP_1280x800_60            0x16
>>
>>> +#define ASTDP_1280x800_60_RB     0x17
>>
>>> +#define ASTDP_1440x900_60            0x18
>>
>>> +#define ASTDP_1440x900_60_RB     0x19
>>
>>> +#define ASTDP_1680x1050_60          0x1A
>>
>>> +#define ASTDP_1680x1050_60_RB   0x1B
>>
>>> +#define ASTDP_1600x900_60            0x1C
>>
>>> +#define ASTDP_1600x900_60_RB     0x1D
>>
>>> +#define ASTDP_1366x768_60            0x1E
>>
>>> +#define ASTDP_1152x864_75            0x1F
>>
>>> +
>>
>>>     int ast_mm_init(struct ast_private *ast);
>>
>>>
>>
>>>     /* ast post */
>>
>>> @@ -381,4 +489,11 @@ void ast_init_3rdtx(struct drm_device *dev);
>>
>>>     /* ast_i2c.c */
>>
>>>    struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev);
>>
>>>
>>
>>> +/* aspeed DP */
>>
>>> +int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata); void
>>
>>> +ast_dp_launch(struct drm_device *dev, u8 bPower); void
>>
>>> +ast_dp_power_on_off(struct drm_device *dev, bool no); void
>>
>>> +ast_dp_set_on_off(struct drm_device *dev, bool no); void
>>
>>> +ast_dp_set_mode(struct drm_crtc *crtc, struct ast_vbios_mode_info
>>
>>> +*vbios_mode);
>>
>>> +
>>
>>>     #endif
>>
>>> diff --git a/drivers/gpu/drm/ast/ast_main.c
>>
>>> b/drivers/gpu/drm/ast/ast_main.c index 22e9e2d3c..1113ee1cb 100644
>>
>>> --- a/drivers/gpu/drm/ast/ast_main.c
>>
>>> +++ b/drivers/gpu/drm/ast/ast_main.c
>>
>>> @@ -232,7 +232,7 @@ static int ast_detect_chip(struct drm_device
>>> *dev, bool *need_post)
>>
>>>                            ast->tx_chip_type = AST_TX_SIL164;
>>
>>>             }
>>
>>>
>>
>>> -    if ((ast->chip == AST2300) || (ast->chip == AST2400)) {
>>
>>> +   if ((ast->chip == AST2300) || (ast->chip == AST2400) ||
>>> +(ast->chip
>>
>>> +== AST2500)) {
>>
>>>                     /*
>>
>>>                      * On AST2300 and 2400, look the configuration set
>>> by the SoC in
>>
>>>                      * the SOC scratch register #1 bits 11:8
>>> (interestingly marked @@
>>
>>> -256,7 +256,8 @@ static int ast_detect_chip(struct drm_device *dev,
>>> bool *need_post)
>>
>>>                     case 0x0c:
>>
>>>                             ast->tx_chip_type = AST_TX_DP501;
>>
>>>                     }
>>
>>> -    }
>>
>>> +   } else if (ast->chip == AST2600)
>>
>>> +           ast_dp_launch(&ast->base, 0);
>>
>>>
>>
>>>             /* Print stuff for diagnostic purposes */
>>
>>>             switch(ast->tx_chip_type) {
>>
>>> diff --git a/drivers/gpu/drm/ast/ast_mode.c
>>
>>> b/drivers/gpu/drm/ast/ast_mode.c index 45b56b39a..4728825b7 100644
>>
>>> --- a/drivers/gpu/drm/ast/ast_mode.c
>>
>>> +++ b/drivers/gpu/drm/ast/ast_mode.c
>>
>>> @@ -988,21 +988,41 @@ static int ast_cursor_plane_init(struct
>>> ast_private *ast)
>>
>>>     static void ast_crtc_dpms(struct drm_crtc *crtc, int mode)
>>
>>>     {
>>
>>>             struct ast_private *ast = to_ast_private(crtc->dev);
>>
>>> +   u8 ch = AST_DPMS_VSYNC_OFF | AST_DPMS_HSYNC_OFF;
>>
>>>
>>
>>>             /* TODO: Maybe control display signal generation with
>>
>>>              *       Sync Enable (bit CR17.7).
>>
>>>              */
>>
>>>             switch (mode) {
>>
>>>             case DRM_MODE_DPMS_ON:
>>
>>> -    case DRM_MODE_DPMS_STANDBY:
>>
>>> -    case DRM_MODE_DPMS_SUSPEND:
>>
>>> +           ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT,  0x01, 0xdf,
>>> +0);
>>
>>> +           ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc,
>>> +0);
>>
>>>                     if (ast->tx_chip_type == AST_TX_DP501)
>>
>>>                             ast_set_dp501_video_output(crtc->dev, 1);
>>
>>> +
>>
>>> +           if (ast->tx_chip_type == AST_TX_ASTDP) {
>>
>>> +                   ast_dp_power_on_off(crtc->dev, AST_DP_POWER_ON);
>>
>>> +                   ast_wait_for_vretrace(ast);
>>
>>> +                   ast_dp_set_on_off(crtc->dev, 1);
>>
>>> +           }
>>
>>> +
>>
>>> +           ast_crtc_load_lut(ast, crtc);
>>
>>>                     break;
>>
>>> +   case DRM_MODE_DPMS_STANDBY:
>>
>>> +   case DRM_MODE_DPMS_SUSPEND:
>>
>>>             case DRM_MODE_DPMS_OFF:
>>
>>> +           ch = mode;
>>
>>>                     if (ast->tx_chip_type == AST_TX_DP501)
>>
>>>                             ast_set_dp501_video_output(crtc->dev, 0);
>>
>>>                     break;
>>
>>> +
>>
>>> +           if (ast->tx_chip_type == AST_TX_ASTDP) {
>>
>>> +                   ast_dp_set_on_off(crtc->dev, 0);
>>
>>> +                   ast_dp_power_on_off(crtc->dev, AST_DP_POWER_OFF);
>>
>>> +           }
>>
>>> +
>>
>>> +           ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT,  0x01, 0xdf,
>>> +0x20);
>>
>>> +           ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc,
>>> +ch);
>>
>>>             }
>>
>>>     }
>>
>>>
>>
>>> @@ -1027,7 +1047,7 @@ ast_crtc_helper_mode_valid(struct drm_crtc
>>
>>> *crtc, const struct drm_display_mode
>>
>>>
>>
>>>                     if ((ast->chip == AST2100) || (ast->chip ==
>>> AST2200) ||
>>
>>>                         (ast->chip == AST2300) || (ast->chip ==
>>> AST2400) ||
>>
>>> -                (ast->chip == AST2500)) {
>>
>>> +               (ast->chip == AST2500) || (ast->chip == AST2600)) {
>>
>>>                             if ((mode->hdisplay == 1920) &&
>>> (mode->vdisplay == 1080))
>>
>>>                                     return MODE_OK;
>>
>>>
>>
>>> @@ -1110,6 +1130,7 @@ ast_crtc_helper_atomic_flush(struct drm_crtc
>>> *crtc,
>>
>>>             struct ast_private *ast = to_ast_private(crtc->dev);
>>
>>>             struct ast_crtc_state *ast_crtc_state =
>>> to_ast_crtc_state(crtc_state);
>>
>>>             struct ast_crtc_state *old_ast_crtc_state =
>>
>>> to_ast_crtc_state(old_crtc_state);
>>
>>> +   struct ast_vbios_mode_info *vbios_mode_info =
>>
>>> +&ast_crtc_state->vbios_mode_info;
>>
>>>
>>
>>>             /*
>>
>>>              * The gamma LUT has to be reloaded after changing the
>>> primary @@
>>
>>> -1117,6 +1138,10 @@ ast_crtc_helper_atomic_flush(struct drm_crtc
>>> *crtc,
>>
>>>              */
>>
>>>             if (old_ast_crtc_state->format != ast_crtc_state->format)
>>
>>>                     ast_crtc_load_lut(ast, crtc);
>>
>>> +
>>
>>> +   //Set Aspeed Display-Port
>>
>>> +   if (ast->tx_chip_type == AST_TX_ASTDP)
>>
>>> +           ast_dp_set_mode(crtc, vbios_mode_info);
>>
>>>     }
>>
>>>
>>
>>>     static void
>>
>>> @@ -1527,6 +1552,93 @@ static int ast_dp501_output_init(struct
>>> ast_private *ast)
>>
>>>             return 0;
>>
>>>     }
>>
>>>
>>
>>> +/*
>>
>>> + * ASPEED Display-Port Connector
>>
>>> + */
>>
>>> +
>>
>>> +static int ast_astdp_connector_helper_get_modes(struct drm_connector
>>
>>> +*connector) {
>>
>>> +   void *edid;
>>
>>> +
>>
>>> +   int succ;
>>
>>> +   int count;
>>
>>> +
>>
>>> +   edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
>>
>>> +   if (!edid)
>>
>>> +           goto err_drm_connector_update_edid_property;
>>
>>> +
>>
>>> +   succ = ast_astdp_read_edid(connector->dev, edid);
>>
>>> +   if (succ < 0)
>>
>>> +           goto err_kfree;
>>
>>> +
>>
>>> +   drm_connector_update_edid_property(connector, edid);
>>
>>> +   count = drm_add_edid_modes(connector, edid);
>>
>>> +   kfree(edid);
>>
>>> +
>>
>>> +   return count;
>>
>>> +
>>
>>> +err_kfree:
>>
>>> +   kfree(edid);
>>
>>> +err_drm_connector_update_edid_property:
>>
>>> +   drm_connector_update_edid_property(connector, NULL);
>>
>>> +   return 0;
>>
>>> +}
>>
>>> +
>>
>>> +static const struct drm_connector_helper_funcs
>>> +ast_astdp_connector_helper_funcs = {
>>
>>> +   .get_modes = ast_astdp_connector_helper_get_modes,
>>
>>> +};
>>
>>> +
>>
>>> +static const struct drm_connector_funcs ast_astdp_connector_funcs =
>>> +{
>>
>>> +   .reset = drm_atomic_helper_connector_reset,
>>
>>> +   .fill_modes = drm_helper_probe_single_connector_modes,
>>
>>> +   .destroy = drm_connector_cleanup,
>>
>>> +   .atomic_duplicate_state =
>>> +drm_atomic_helper_connector_duplicate_state,
>>
>>> +   .atomic_destroy_state =
>>> +drm_atomic_helper_connector_destroy_state,
>>
>>> +};
>>
>>> +
>>
>>> +static int ast_astdp_connector_init(struct drm_device *dev, struct
>>
>>> +drm_connector *connector) {
>>
>>> +   int ret;
>>
>>> +
>>
>>> +   ret = drm_connector_init(dev, connector,
>>> +&ast_astdp_connector_funcs,
>>
>>> +                           DRM_MODE_CONNECTOR_DisplayPort);
>>
>>> +   if (ret)
>>
>>> +           return ret;
>>
>>> +
>>
>>> +   drm_connector_helper_add(connector,
>>
>>> +&ast_astdp_connector_helper_funcs);
>>
>>> +
>>
>>> +   connector->interlace_allowed = 0;
>>
>>> +   connector->doublescan_allowed = 0;
>>
>>> +
>>
>>> +   connector->polled = DRM_CONNECTOR_POLL_CONNECT;
>>
>>> +
>>
>>> +   return 0;
>>
>>> +}
>>
>>> +
>>
>>> +static int ast_astdp_output_init(struct ast_private *ast) {
>>
>>> +   struct drm_device *dev = &ast->base;
>>
>>> +   struct drm_crtc *crtc = &ast->crtc;
>>
>>> +   struct drm_encoder *encoder = &ast->output.astdp.encoder;
>>
>>> +   struct drm_connector *connector = &ast->output.astdp.connector;
>>
>>> +   int ret;
>>
>>> +
>>
>>> +   ret = drm_simple_encoder_init(dev, encoder,
>>> +DRM_MODE_ENCODER_TMDS);
>>
>>> +   if (ret)
>>
>>> +           return ret;
>>
>>> +   encoder->possible_crtcs = drm_crtc_mask(crtc);
>>
>>> +
>>
>>> +   ret = ast_astdp_connector_init(dev, connector);
>>
>>> +   if (ret)
>>
>>> +           return ret;
>>
>>> +
>>
>>> +   ret = drm_connector_attach_encoder(connector, encoder);
>>
>>> +   if (ret)
>>
>>> +           return ret;
>>
>>> +
>>
>>> +   return 0;
>>
>>> +}
>>
>>> +
>>
>>>     /*
>>
>>>      * Mode config
>>
>>>      */
>>
>>> @@ -1563,7 +1675,8 @@ int ast_mode_config_init(struct ast_private
>>> *ast)
>>
>>>                 ast->chip == AST2200 ||
>>
>>>                 ast->chip == AST2300 ||
>>
>>>                 ast->chip == AST2400 ||
>>
>>> -        ast->chip == AST2500) {
>>
>>> +       ast->chip == AST2500 ||
>>
>>> +       ast->chip == AST2600) {
>>
>>>                     dev->mode_config.max_width = 1920;
>>
>>>                     dev->mode_config.max_height = 2048;
>>
>>>             } else {
>>
>>> @@ -1594,6 +1707,9 @@ int ast_mode_config_init(struct ast_private
>>> *ast)
>>
>>>             case AST_TX_DP501:
>>
>>>                     ret = ast_dp501_output_init(ast);
>>
>>>                     break;
>>
>>> +   case AST_TX_ASTDP:
>>
>>> +           ret = ast_astdp_output_init(ast);
>>
>>> +           break;
>>
>>>             }
>>
>>>             if (ret)
>>
>>>                     return ret;
>>
>>> diff --git a/drivers/gpu/drm/ast/ast_post.c
>>
>>> b/drivers/gpu/drm/ast/ast_post.c index b5d92f652..0aa9cf0fb 100644
>>
>>> --- a/drivers/gpu/drm/ast/ast_post.c
>>
>>> +++ b/drivers/gpu/drm/ast/ast_post.c
>>
>>> @@ -379,7 +379,9 @@ void ast_post_gpu(struct drm_device *dev)
>>
>>>             ast_enable_mmio(dev);
>>
>>>             ast_set_def_ext_reg(dev);
>>
>>>
>>
>>> -    if (ast->config_mode == ast_use_p2a) {
>>
>>> +   if (ast->chip == AST2600) {
>>
>>> +           ast_dp_launch(dev, 1);
>>
>>> +   } else if (ast->config_mode == ast_use_p2a) {
>>
>>>                     if (ast->chip == AST2500)
>>
>>>                             ast_post_chip_2500(dev);
>>
>>>                     else if (ast->chip == AST2300 || ast->chip ==
>>> AST2400)
>>
>>>
>>
>>> base-commit: c54b39a565227538c52ead2349eb17d54aadd6f7
>>
>>> --
>>
>>> 2.27.0
>>
>>>
>>
>> --
>>
>> Thomas Zimmermann
>>
>> Graphics Driver Developer
>>
>> SUSE Software Solutions Germany GmbH
>>
>> Maxfeldstr. 5, 90409 Nürnberg, Germany
>>
>> (HRB 36809, AG Nürnberg)
>>
>> Geschäftsführer: Ivo Totev
>>
> 
> --
> Thomas Zimmermann
> Graphics Driver Developer
> SUSE Software Solutions Germany GmbH
> Maxfeldstr. 5, 90409 Nürnberg, Germany
> (HRB 36809, AG Nürnberg)
> Geschäftsführer: Ivo Totev

-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Ivo Totev

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 21+ messages in thread

* RE: [PATCH v4] drm/ast: Create the driver for ASPEED proprietory Display-Port
  2022-05-13 10:20                 ` Thomas Zimmermann
@ 2022-05-13 10:39                   ` Kuo-Hsiang Chou
  2022-05-30  6:05                     ` Kuo-Hsiang Chou
  0 siblings, 1 reply; 21+ messages in thread
From: Kuo-Hsiang Chou @ 2022-05-13 10:39 UTC (permalink / raw)
  To: Thomas Zimmermann, dri-devel, linux-kernel
  Cc: Hungju Huang, airlied, Tommy Huang, airlied, Arc Sung, Luke Chen

Hi Thomas,

-----Original Message-----
From: Thomas Zimmermann [mailto:tzimmermann@suse.de] 
Sent: Friday, May 13, 2022 6:21 PM
To: Kuo-Hsiang Chou <kuohsiang_chou@aspeedtech.com>; dri-devel@lists.freedesktop.org; linux-kernel@vger.kernel.org
Subject: Re: [PATCH v4] drm/ast: Create the driver for ASPEED proprietory Display-Port


Hi

Am 13.05.22 um 11:07 schrieb Kuo-Hsiang Chou:
> 
> 
> -----Original Message-----
> From: Thomas Zimmermann [mailto:tzimmermann@suse.de]
> Sent: Tuesday, May 10, 2022 6:56 PM
> To: Kuo-Hsiang Chou <kuohsiang_chou@aspeedtech.com>; 
> dri-devel@lists.freedesktop.org; linux-kernel@vger.kernel.org
> Subject: Re: [PATCH v4] drm/ast: Create the driver for ASPEED 
> proprietory Display-Port
> 
> Hi
> 
> Am 04.05.22 um 10:49 schrieb Kuo-Hsiang Chou:
>> Hi Thomas,
>>
>> Thanks for your efforts to review this patch.
>>
>> Now, I observe a change that after DP unplugged and then the system 
>> is unable to get EDID from D-sub connecting.
>>
>> The reason seems that TXs are merged into union structure in 
>> /drivers/gpu/drm/ast/ast_drv.h
>>    (a59b026419f33040d7d28b8e3b1cea681b9ce7a7
>> <https://cgit.freedesktop.org/drm/drm-misc/commit/?id=a59b026419f3304
>> 0
>> d7d28b8e3b1cea681b9ce7a7>)
> 
> I have posted a patch that enables multiple parallel outputs. See
> 
>   
> <https://lore.kernel.org/dri-devel/20220510105010.20712-1-tzimmermann@
> suse.de/T/#u>
> 
> If you have the time, I'd appreciate if you could test it.
> 
> Hi Thomas,
> First, thanks for your efforts on this patch of " enables multiple parallel outputs ".
> But it doesn't work. There is still NO EDID got from D-sub after DP unplugged.
> 
> Base on your patch, I am trying to find out the solution also.
> Final, thanks for your help again!

Let's try to find a solution. I might be able to come up with something if I have enough information.

How are these outputs connected to each each other?
1. DP and D-sub both connected: it is correct to get EDID and monitor type is correctly shown on display setting. Resolution is up to 1920*1200.
2. DP unplugged and only D-sub connected: Unknown Display is shown on display setting. Only 800*600 and 1024*768 are available for Resolution.

They are both served by the same CRTC. Can they be used at the same time?  
No, 2 different monitors are connected at same time. 
One is connected by D-sub and another is connected by DP connecting.

Are they mutually exclusive?
Yes, If DP and D-sub are all connecting, DP's EDID is first priority for Display setting.
When DP unplugged, EDID got from D-sub are used for Display setting.

Now, I try to add the codes of ast_vga_connector_helper_get_modes() into ast_astdp_connector_helper_get_modes().
The result is failed.
Anyway, I will continue to try and test the feature next Monday. 
Thanks for your great help!

Regards,
	Kuo-Hsiang Chou

Best regards
Thomas

> 
> Regards,
> 	Kuo-Hsiang Chou
> 
> Best regards
> Thomas
> 
>>
>> Another, do you need the ast2600 EVB to ease verification on "drm/ast" ?
>>
>> Regards,
>>
>>           Kuo-Hsiang Chou
>>
>> -----Original Message-----
>> From: Thomas Zimmermann [mailto:tzimmermann@suse.de]
>> Sent: Wednesday, May 04, 2022 3:28 PM
>> To: Kuo-Hsiang Chou <kuohsiang_chou@aspeedtech.com>; 
>> dri-devel@lists.freedesktop.org; linux-kernel@vger.kernel.org
>> Subject: Re: [PATCH v4] drm/ast: Create the driver for ASPEED 
>> proprietory Display-Port
>>
>> Hi
>>
>> Am 28.04.22 um 09:56 schrieb KuoHsiang Chou:
>>
>>> V1:
>>
>>> 1. The MCU FW controling ASPEED DP is loaded by BMC boot loader.
>>
>>> 2. Driver starts after CR[3:1] == 111b that indicates Tx is ASTDP,
>>
>>>       and CRD1[5] has been asserted by BMVC boot loader.
>>
>>> 3. EDID is prioritized by DP monitor.
>>
>>> 4. DP's EDID has high priority to decide resolution supporting.
>>
>>>
>>
>>> V2:
>>
>>> Modules description:
>>
>>> 1. ASTDP (ASPEED DisplayPort) is controlled by dedicated
>>
>>>       AST-MCU (ASPEED propriatary MCU).
>>
>>> 2. MCU is looping in charged of HPD, Read EDID, Link Training with
>>
>>>       DP sink.
>>
>>> 3. ASTDP and AST-MUC reside in BMC (Baseboard Management controller)
>>
>>>       addressing-space.
>>
>>> 4. ASPEED DRM driver requests MCU to get HPD and EDID by 
>>> CR-scratched
>>
>>>       register.
>>
>>>
>>
>>> Booting sequence:
>>
>>> 1. Check if TX is ASTDP                                        //
>>> ast_dp_launch()
>>
>>> 2. Check if DP-MCU FW has loaded
>>> // ast_dp_launch()
>>
>>> 3. Read EDID                                        //
>>> ast_dp_read_edid()
>>
>>> 4. Resolution switch                                     //
>>> ast_dp_SetOutput()
>>
>>>
>>
>>> V3:
>>
>>> 1. Remove unneeded semicolon.
>>
>>> 2. Apply to git://anongit.freedesktop.org/drm/drm, instead of
>>
>>>       git://anongit.freedesktop.org/drm/drm-misc
>>
>>> 3. Resolve auto build test WARNINGs on V1 patch.
>>
>>>
>>
>>> V4:
>>
>>> 1. Sync code-base with kernel 5.17_rc6 2. Remove the define of
>>
>>> DPControlPower, because DP chips need to be
>>
>>>       powered on to be used.
>>
>>> 3. Remove the switches of PHY and Display from EDID procedure.
>>
>>> 4. Revise increaing delay to fixed delay, because this version 
>>> kernel
>>
>>>       doesn't detect minitor consistenntly.
>>
>>> 5. Create clean-up code used for reset of power state on errors with
>>
>>>       -EIO manner.
>>
>>> 6. Revise the DP detection by TX type and its DP-FW status during
>>
>>>       booting and resume.
>>
>>> 7. Correct the CamelCase Style.
>>
>>> 8. Use register reading while needing, and remove to hold full
>>
>>>       register.
>>
>>> 9. Instead of 'u8', revise to 'bool' on swwitch of PHY and video.
>>
>>> 10.Correct typo
>>
>>> 11.Remove the duplicated copy of TX definition.
>>
>>> 12.Use EDID_LENGTH as the constant of 128.
>>
>>>
>>
>>> Signed-off-by: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com 
>>> <mailto:kuohsiang_chou@aspeedtech.com>>
>>
>> Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de 
>> <mailto:tzimmermann@suse.de>>
>>
>> I've meanwhile added your patch to drm-misc-next. It should show up 
>> in one of the next kernel releases.  Thanks a lot.
>>
>> Best regards
>>
>> Thomas
>>
>>> ---
>>
>>>     drivers/gpu/drm/ast/Makefile   |   2 +-
>>
>>>     drivers/gpu/drm/ast/ast_dp.c   | 282
>>> +++++++++++++++++++++++++++++++++
>>
>>>     drivers/gpu/drm/ast/ast_drv.h  | 115 ++++++++++++++
>>
>>>     drivers/gpu/drm/ast/ast_main.c |   5 +-
>>
>>>     drivers/gpu/drm/ast/ast_mode.c | 124 ++++++++++++++-
>>
>>>     drivers/gpu/drm/ast/ast_post.c |   4 +-
>>
>>>     6 files changed, 524 insertions(+), 8 deletions(-)
>>
>>>     create mode 100644 drivers/gpu/drm/ast/ast_dp.c
>>
>>>
>>
>>> diff --git a/drivers/gpu/drm/ast/Makefile
>>
>>> b/drivers/gpu/drm/ast/Makefile index 21f71160b..5a53ce51f 100644
>>
>>> --- a/drivers/gpu/drm/ast/Makefile
>>
>>> +++ b/drivers/gpu/drm/ast/Makefile
>>
>>> @@ -3,6 +3,6 @@
>>
>>>     # Makefile for the drm device driver.  This driver provides 
>>> support for the
>>
>>>     # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
>>
>>>
>>
>>> -ast-y := ast_drv.o ast_i2c.o ast_main.o ast_mm.o ast_mode.o
>>
>>> ast_post.o ast_dp501.o
>>
>>> +ast-y := ast_drv.o ast_i2c.o ast_main.o ast_mm.o ast_mode.o
>>
>>> +ast_post.o ast_dp501.o ast_dp.o
>>
>>>
>>
>>>     obj-$(CONFIG_DRM_AST) := ast.o
>>
>>> diff --git a/drivers/gpu/drm/ast/ast_dp.c
>>
>>> b/drivers/gpu/drm/ast/ast_dp.c new file mode 100644 index
>>
>>> 000000000..4551bc8a3
>>
>>> --- /dev/null
>>
>>> +++ b/drivers/gpu/drm/ast/ast_dp.c
>>
>>> @@ -0,0 +1,282 @@
>>
>>> +// SPDX-License-Identifier: GPL-2.0
>>
>>> +// Copyright (c) 2021, ASPEED Technology Inc.
>>
>>> +// Authors: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com 
>>> +<mailto:kuohsiang_chou@aspeedtech.com>>
>>
>>> +
>>
>>> +#include <linux/firmware.h>
>>
>>> +#include <linux/delay.h>
>>
>>> +#include <drm/drm_print.h>
>>
>>> +#include "ast_drv.h"
>>
>>> +
>>
>>> +int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata) {
>>
>>> +   struct ast_private *ast = to_ast_private(dev);
>>
>>> +   u8 i = 0, j = 0;
>>
>>> +
>>
>>> +   /*
>>
>>> +   * CRD1[b5]: DP MCU FW is executing
>>
>>> +   * CRDC[b0]: DP link success
>>
>>> +   * CRDF[b0]: DP HPD
>>
>>> +   * CRE5[b0]: Host reading EDID process is done
>>
>>> +   */
>>
>>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1,
>>> +ASTDP_MCU_FW_EXECUTING) &&
>>
>>> +           ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC,
>>> +ASTDP_LINK_SUCCESS) &&
>>
>>> +           ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF,
>>> +ASTDP_HPD) &&
>>
>>> +           ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
>>
>>> +
>>> +ASTDP_HOST_EDID_READ_DONE_MASK))) {
>>
>>> +           goto err_astdp_edid_not_ready;
>>
>>> +   }
>>
>>> +
>>
>>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8) 
>>> +~ASTDP_HOST_EDID_READ_DONE_MASK,
>>
>>> +                                                   0x00);
>>
>>> +
>>
>>> +   for (i = 0; i < 32; i++) {
>>
>>> +           /*
>>
>>> +           * CRE4[7:0]: Read-Pointer for EDID (Unit: 4bytes); valid
>>> +range: 0~64
>>
>>> +           */
>>
>>> +           ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE4,
>>
>>> +                                   (u8) 
>>> +~ASTDP_EDID_READ_POINTER_MASK, (u8) i);
>>
>>> +           j = 0;
>>
>>> +
>>
>>> +           /*
>>
>>> +           * CRD7[b0]: valid flag for EDID
>>
>>> +           * CRD6[b0]: mirror read pointer for EDID
>>
>>> +           */
>>
>>> +           while ((ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 
>>> +0xD7,
>>
>>> +                           ASTDP_EDID_VALID_FLAG_MASK) != 0x01) ||
>>
>>> +                   (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 
>>> +0xD6,
>>
>>> +
>>> +ASTDP_EDID_READ_POINTER_MASK) != i)) {
>>
>>> +                   /*
>>
>>> +                   * Delay are getting longer with each retry.
>>
>>> +                   * 1. The Delays are often 2 loops when users request "Display Settings"
>>
>>> +                   *      of right-click of mouse.
>>
>>> +                   * 2. The Delays are often longer a lot when system resume from S3/S4.
>>
>>> +                   */
>>
>>> +                   mdelay(j+1);
>>
>>> +
>>
>>> +                   if (!(ast_get_index_reg_mask(ast, 
>>> +AST_IO_CRTC_PORT, 0xD1,
>>
>>> +
>>> +ASTDP_MCU_FW_EXECUTING) &&
>>
>>> +                           ast_get_index_reg_mask(ast, 
>>> +AST_IO_CRTC_PORT, 0xDC,
>>
>>> +
>>> +ASTDP_LINK_SUCCESS) &&
>>
>>> +                           ast_get_index_reg_mask(ast, 
>>> +AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD))) {
>>
>>> +                           goto err_astdp_jump_out_loop_of_edid;
>>
>>> +                   }
>>
>>> +
>>
>>> +                   j++;
>>
>>> +                   if (j > 200)
>>
>>> +                           goto err_astdp_jump_out_loop_of_edid;
>>
>>> +           }
>>
>>> +
>>
>>> +           *(ediddata) = ast_get_index_reg_mask(ast, 
>>> +AST_IO_CRTC_PORT,
>>
>>> +                                                   0xD8, 
>>> +ASTDP_EDID_READ_DATA_MASK);
>>
>>> +           *(ediddata + 1) = ast_get_index_reg_mask(ast, 
>>> +AST_IO_CRTC_PORT, 0xD9,
>>
>>> +
>>> +ASTDP_EDID_READ_DATA_MASK);
>>
>>> +           *(ediddata + 2) = ast_get_index_reg_mask(ast, 
>>> +AST_IO_CRTC_PORT, 0xDA,
>>
>>> +
>>> +ASTDP_EDID_READ_DATA_MASK);
>>
>>> +           *(ediddata + 3) = ast_get_index_reg_mask(ast, 
>>> +AST_IO_CRTC_PORT, 0xDB,
>>
>>> +
>>> +ASTDP_EDID_READ_DATA_MASK);
>>
>>> +
>>
>>> +           if (i == 31) {
>>
>>> +                   /*
>>
>>> +                   * For 128-bytes EDID_1.3,
>>
>>> +                   * 1. Add the value of Bytes-126 to Bytes-127.
>>
>>> +                   *            The Bytes-127 is Checksum. Sum of 
>>> +all 128bytes should
>>
>>> +                   *            equal 0    (mod 256).
>>
>>> +                   * 2. Modify Bytes-126 to be 0.
>>
>>> +                   *            The Bytes-126 indicates the Number 
>>> +of extensions to
>>
>>> +                   *            follow. 0 represents noextensions.
>>
>>> +                   */
>>
>>> +                   *(ediddata + 3) = *(ediddata + 3) + *(ediddata + 
>>> +2);
>>
>>> +                   *(ediddata + 2) = 0;
>>
>>> +           }
>>
>>> +
>>
>>> +           ediddata += 4;
>>
>>> +   }
>>
>>> +
>>
>>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8) 
>>> +~ASTDP_HOST_EDID_READ_DONE_MASK,
>>
>>> +
>>> +ASTDP_HOST_EDID_READ_DONE);
>>
>>> +
>>
>>> +   return 0;
>>
>>> +
>>
>>> +err_astdp_jump_out_loop_of_edid:
>>
>>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
>>
>>> +                                                   (u8) 
>>> +~ASTDP_HOST_EDID_READ_DONE_MASK,
>>
>>> +
>>> +ASTDP_HOST_EDID_READ_DONE);
>>
>>> +   return (~(j+256) + 1);
>>
>>> +
>>
>>> +err_astdp_edid_not_ready:
>>
>>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1,
>>> +ASTDP_MCU_FW_EXECUTING)))
>>
>>> +           return (~0xD1 + 1);
>>
>>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC,
>>> +ASTDP_LINK_SUCCESS)))
>>
>>> +           return (~0xDC + 1);
>>
>>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF,
>>> +ASTDP_HPD)))
>>
>>> +           return (~0xDF + 1);
>>
>>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
>>> +ASTDP_HOST_EDID_READ_DONE_MASK)))
>>
>>> +           return (~0xE5 + 1);
>>
>>> +
>>
>>> +   return      0;
>>
>>> +}
>>
>>> +
>>
>>> +/*
>>
>>> + * Launch Aspeed DP
>>
>>> + */
>>
>>> +void ast_dp_launch(struct drm_device *dev, u8 bPower) {
>>
>>> +   u32 i = 0, j = 0, WaitCount = 1;
>>
>>> +   u8 bDPTX = 0;
>>
>>> +   u8 bDPExecute = 1;
>>
>>> +
>>
>>> +   struct ast_private *ast = to_ast_private(dev);
>>
>>> +   // S3 come back, need more time to wait BMC ready.
>>
>>> +   if (bPower)
>>
>>> +           WaitCount = 300;
>>
>>> +
>>
>>> +
>>
>>> +   // Wait total count by different condition.
>>
>>> +   for (j = 0; j < WaitCount; j++) {
>>
>>> +           bDPTX = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 
>>> +0xD1,
>>
>>> +TX_TYPE_MASK);
>>
>>> +
>>
>>> +           if (bDPTX)
>>
>>> +                   break;
>>
>>> +
>>
>>> +           msleep(100);
>>
>>> +   }
>>
>>> +
>>
>>> +   // 0xE : ASTDP with DPMCU FW handling
>>
>>> +   if (bDPTX == ASTDP_DPMCU_TX) {
>>
>>> +           // Wait one second then timeout.
>>
>>> +           i = 0;
>>
>>> +
>>
>>> +           while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 
>>> +0xD1, COPROCESSOR_LAUNCH) !=
>>
>>> +                   COPROCESSOR_LAUNCH) {
>>
>>> +                   i++;
>>
>>> +                   // wait 100 ms
>>
>>> +                   msleep(100);
>>
>>> +
>>
>>> +                   if (i >= 10) {
>>
>>> +                           // DP would not be ready.
>>
>>> +                           bDPExecute = 0;
>>
>>> +                           break;
>>
>>> +                   }
>>
>>> +           }
>>
>>> +
>>
>>> +           if (bDPExecute)
>>
>>> +                   ast->tx_chip_type = AST_TX_ASTDP;
>>
>>> +
>>
>>> +           ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
>>
>>> +                                                   (u8) 
>>> +~ASTDP_HOST_EDID_READ_DONE_MASK,
>>
>>> +
>>> +ASTDP_HOST_EDID_READ_DONE);
>>
>>> +   } else
>>
>>> +           ast->tx_chip_type = AST_TX_NONE;
>>
>>> +}
>>
>>> +
>>
>>> +
>>
>>> +
>>
>>> +void ast_dp_power_on_off(struct drm_device *dev, bool on) {
>>
>>> +   struct ast_private *ast = to_ast_private(dev);
>>
>>> +   // Read and Turn off DP PHY sleep
>>
>>> +   u8 bE3 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3,
>>
>>> +AST_DP_VIDEO_ENABLE);
>>
>>> +
>>
>>> +   // Turn on DP PHY sleep
>>
>>> +   if (!on)
>>
>>> +           bE3 |= AST_DP_PHY_SLEEP;
>>
>>> +
>>
>>> +   // DP Power on/off
>>
>>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, (u8)
>>
>>> +~AST_DP_PHY_SLEEP, bE3); }
>>
>>> +
>>
>>> +
>>
>>> +
>>
>>> +void ast_dp_set_on_off(struct drm_device *dev, bool on) {
>>
>>> +   struct ast_private *ast = to_ast_private(dev);
>>
>>> +   u8 video_on_off = on;
>>
>>> +
>>
>>> +   // Video On/Off
>>
>>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, (u8)
>>
>>> +~AST_DP_VIDEO_ENABLE, on);
>>
>>> +
>>
>>> +   // If DP plug in and link successful then check video on / off 
>>> +status
>>
>>> +   if (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC,
>>> +ASTDP_LINK_SUCCESS) &&
>>
>>> +           ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF,
>>> +ASTDP_HPD)) {
>>
>>> +           video_on_off <<= 4;
>>
>>> +           while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 
>>> +0xDF,
>>
>>> +
>>> +ASTDP_MIRROR_VIDEO_ENABLE) != video_on_off) {
>>
>>> +                   // wait 1 ms
>>
>>> +                   mdelay(1);
>>
>>> +           }
>>
>>> +   }
>>
>>> +}
>>
>>> +
>>
>>> +void ast_dp_set_mode(struct drm_crtc *crtc, struct
>>
>>> +ast_vbios_mode_info *vbios_mode) {
>>
>>> +   struct ast_private *ast = to_ast_private(crtc->dev);
>>
>>> +
>>
>>> +   u32 ulRefreshRateIndex;
>>
>>> +   u8 ModeIdx;
>>
>>> +
>>
>>> +   ulRefreshRateIndex = vbios_mode->enh_table->refresh_rate_index - 
>>> +1;
>>
>>> +
>>
>>> +   switch (crtc->mode.crtc_hdisplay) {
>>
>>> +   case 320:
>>
>>> +           ModeIdx = ASTDP_320x240_60;
>>
>>> +           break;
>>
>>> +   case 400:
>>
>>> +           ModeIdx = ASTDP_400x300_60;
>>
>>> +           break;
>>
>>> +   case 512:
>>
>>> +           ModeIdx = ASTDP_512x384_60;
>>
>>> +           break;
>>
>>> +   case 640:
>>
>>> +           ModeIdx = (ASTDP_640x480_60 + (u8) ulRefreshRateIndex);
>>
>>> +           break;
>>
>>> +   case 800:
>>
>>> +           ModeIdx = (ASTDP_800x600_56 + (u8) ulRefreshRateIndex);
>>
>>> +           break;
>>
>>> +   case 1024:
>>
>>> +           ModeIdx = (ASTDP_1024x768_60 + (u8) ulRefreshRateIndex);
>>
>>> +           break;
>>
>>> +   case 1152:
>>
>>> +           ModeIdx = ASTDP_1152x864_75;
>>
>>> +           break;
>>
>>> +   case 1280:
>>
>>> +           if (crtc->mode.crtc_vdisplay == 800)
>>
>>> +                   ModeIdx = (ASTDP_1280x800_60_RB - (u8) 
>>> +ulRefreshRateIndex);
>>
>>> +           else          // 1024
>>
>>> +                   ModeIdx = (ASTDP_1280x1024_60 + (u8) 
>>> +ulRefreshRateIndex);
>>
>>> +           break;
>>
>>> +   case 1360:
>>
>>> +   case 1366:
>>
>>> +           ModeIdx = ASTDP_1366x768_60;
>>
>>> +           break;
>>
>>> +   case 1440:
>>
>>> +           ModeIdx = (ASTDP_1440x900_60_RB - (u8) 
>>> +ulRefreshRateIndex);
>>
>>> +           break;
>>
>>> +   case 1600:
>>
>>> +           if (crtc->mode.crtc_vdisplay == 900)
>>
>>> +                   ModeIdx = (ASTDP_1600x900_60_RB - (u8) 
>>> +ulRefreshRateIndex);
>>
>>> +           else          //1200
>>
>>> +                   ModeIdx = ASTDP_1600x1200_60;
>>
>>> +           break;
>>
>>> +   case 1680:
>>
>>> +           ModeIdx = (ASTDP_1680x1050_60_RB - (u8) 
>>> +ulRefreshRateIndex);
>>
>>> +           break;
>>
>>> +   case 1920:
>>
>>> +           if (crtc->mode.crtc_vdisplay == 1080)
>>
>>> +                   ModeIdx = ASTDP_1920x1080_60;
>>
>>> +           else          //1200
>>
>>> +                   ModeIdx = ASTDP_1920x1200_60;
>>
>>> +           break;
>>
>>> +   default:
>>
>>> +           return;
>>
>>> +   }
>>
>>> +
>>
>>> +   /*
>>
>>> +   * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp)
>>
>>> +   * CRE1[7:0]: MISC1 (default: 0x00)
>>
>>> +   * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50)
>>
>>> +   */
>>
>>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE0, (u8) 
>>> +~ASTDP_CLEAR_MASK,
>>
>>> +                           ASTDP_MISC0_24bpp);
>>
>>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE1, (u8) 
>>> +~ASTDP_CLEAR_MASK, ASTDP_MISC1);
>>
>>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE2, (u8)
>>
>>> +~ASTDP_CLEAR_MASK, ModeIdx); }
>>
>>> diff --git a/drivers/gpu/drm/ast/ast_drv.h
>>
>>> b/drivers/gpu/drm/ast/ast_drv.h index a19315b2f..ff1ae314b 100644
>>
>>> --- a/drivers/gpu/drm/ast/ast_drv.h
>>
>>> +++ b/drivers/gpu/drm/ast/ast_drv.h
>>
>>> @@ -70,6 +70,7 @@ enum ast_tx_chip {
>>
>>>             AST_TX_NONE,
>>
>>>             AST_TX_SIL164,
>>
>>>             AST_TX_DP501,
>>
>>> +   AST_TX_ASTDP,
>>
>>>     };
>>
>>>
>>
>>>     #define AST_DRAM_512Mx16 0
>>
>>> @@ -184,6 +185,10 @@ struct ast_private {
>>
>>>                             struct drm_encoder encoder;
>>
>>>                             struct drm_connector connector;
>>
>>>                     } dp501;
>>
>>> +           struct {
>>
>>> +                   struct drm_encoder encoder;
>>
>>> +                   struct drm_connector connector;
>>
>>> +           } astdp;
>>
>>>             } output;
>>
>>>
>>
>>>             bool support_wide_screen;
>>
>>> @@ -357,10 +362,113 @@ int ast_mode_config_init(struct ast_private 
>>> *ast);
>>
>>>     #define AST_DP501_EDID_DATA    0xf020
>>
>>>
>>
>>>     /* Define for Soc scratched reg */
>>
>>> +#define COPROCESSOR_LAUNCH                     BIT(5)
>>
>>> +
>>
>>> +/*
>>
>>> + * Display Transmitter Type:
>>
>>> + */
>>
>>> +#define TX_TYPE_MASK                            GENMASK(3, 1)
>>
>>> +#define NO_TX                                            (0 << 1)
>>
>>> +#define ITE66121_VBIOS_TX                     (1 << 1)
>>
>>> +#define SI164_VBIOS_TX                           (2 << 1)
>>
>>> +#define CH7003_VBIOS_TX                       (3 << 1)
>>
>>> +#define DP501_VBIOS_TX                         (4 << 1)
>>
>>> +#define ANX9807_VBIOS_TX                     (5 << 1)
>>
>>> +#define TX_FW_EMBEDDED_FW_TX                (6 << 1)
>>
>>> +#define ASTDP_DPMCU_TX                               (7 << 1)
>>
>>> +
>>
>>>     #define AST_VRAM_INIT_STATUS_MASK       GENMASK(7, 6)
>>
>>>     //#define AST_VRAM_INIT_BY_BMC             BIT(7)
>>
>>>     //#define AST_VRAM_INIT_READY                BIT(6)
>>
>>>
>>
>>> +/* Define for Soc scratched reg used on ASTDP */
>>
>>> +#define AST_DP_PHY_SLEEP                     BIT(4)
>>
>>> +#define AST_DP_VIDEO_ENABLE              BIT(0)
>>
>>> +
>>
>>> +#define AST_DP_POWER_ON                    true
>>
>>> +#define AST_DP_POWER_OFF                   false
>>
>>> +
>>
>>> +/*
>>
>>> + * CRD1[b5]: DP MCU FW is executing
>>
>>> + * CRDC[b0]: DP link success
>>
>>> + * CRDF[b0]: DP HPD
>>
>>> + * CRE5[b0]: Host reading EDID process is done  */
>>
>>> +#define ASTDP_MCU_FW_EXECUTING                     BIT(5)
>>
>>> +#define ASTDP_LINK_SUCCESS                          BIT(0)
>>
>>> +#define ASTDP_HPD                                          BIT(0)
>>
>>> +#define ASTDP_HOST_EDID_READ_DONE                BIT(0)
>>
>>> +#define ASTDP_HOST_EDID_READ_DONE_MASK    GENMASK(0, 0)
>>
>>> +
>>
>>> +/*
>>
>>> + * CRB8[b1]: Enable VSYNC off
>>
>>> + * CRB8[b0]: Enable HSYNC off
>>
>>> + */
>>
>>> +#define AST_DPMS_VSYNC_OFF                               BIT(1)
>>
>>> +#define AST_DPMS_HSYNC_OFF                               BIT(0)
>>
>>> +
>>
>>> +/*
>>
>>> + * CRDF[b4]: Mirror of AST_DP_VIDEO_ENABLE
>>
>>> + * Precondition:  A. ~AST_DP_PHY_SLEEP  &&
>>
>>> + *                        B. DP_HPD &&
>>
>>> + *                        C. DP_LINK_SUCCESS
>>
>>> + */
>>
>>> +#define ASTDP_MIRROR_VIDEO_ENABLE                BIT(4)
>>
>>> +
>>
>>> +#define ASTDP_EDID_READ_POINTER_MASK  GENMASK(7, 0)
>>
>>> +#define ASTDP_EDID_VALID_FLAG_MASK                GENMASK(0, 0)
>>
>>> +#define ASTDP_EDID_READ_DATA_MASK        GENMASK(7, 0)
>>
>>> +
>>
>>> +/*
>>
>>> + * ASTDP setmode registers:
>>
>>> + * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp)
>>
>>> + * CRE1[7:0]: MISC1 (default: 0x00)
>>
>>> + * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50)  */
>>
>>> +#define ASTDP_MISC0_24bpp                   BIT(5)
>>
>>> +#define ASTDP_MISC1                               0
>>
>>> +#define ASTDP_CLEAR_MASK                   GENMASK(7, 0)
>>
>>> +
>>
>>> +/*
>>
>>> + * ASTDP resoultion table:
>>
>>> + * EX:  ASTDP_A_B_C:
>>
>>> + *                A: Resolution
>>
>>> + *                B: Refresh Rate
>>
>>> + *                C: Misc information, such as CVT, Reduce Blanked
>>
>>> + */
>>
>>> +#define ASTDP_640x480_60              0x00
>>
>>> +#define ASTDP_640x480_72              0x01
>>
>>> +#define ASTDP_640x480_75              0x02
>>
>>> +#define ASTDP_640x480_85              0x03
>>
>>> +#define ASTDP_800x600_56              0x04
>>
>>> +#define ASTDP_800x600_60              0x05
>>
>>> +#define ASTDP_800x600_72              0x06
>>
>>> +#define ASTDP_800x600_75              0x07
>>
>>> +#define ASTDP_800x600_85              0x08
>>
>>> +#define ASTDP_1024x768_60            0x09
>>
>>> +#define ASTDP_1024x768_70            0x0A
>>
>>> +#define ASTDP_1024x768_75            0x0B
>>
>>> +#define ASTDP_1024x768_85            0x0C
>>
>>> +#define ASTDP_1280x1024_60          0x0D
>>
>>> +#define ASTDP_1280x1024_75          0x0E
>>
>>> +#define ASTDP_1280x1024_85          0x0F
>>
>>> +#define ASTDP_1600x1200_60          0x10
>>
>>> +#define ASTDP_320x240_60              0x11
>>
>>> +#define ASTDP_400x300_60              0x12
>>
>>> +#define ASTDP_512x384_60              0x13
>>
>>> +#define ASTDP_1920x1200_60          0x14
>>
>>> +#define ASTDP_1920x1080_60          0x15
>>
>>> +#define ASTDP_1280x800_60            0x16
>>
>>> +#define ASTDP_1280x800_60_RB     0x17
>>
>>> +#define ASTDP_1440x900_60            0x18
>>
>>> +#define ASTDP_1440x900_60_RB     0x19
>>
>>> +#define ASTDP_1680x1050_60          0x1A
>>
>>> +#define ASTDP_1680x1050_60_RB   0x1B
>>
>>> +#define ASTDP_1600x900_60            0x1C
>>
>>> +#define ASTDP_1600x900_60_RB     0x1D
>>
>>> +#define ASTDP_1366x768_60            0x1E
>>
>>> +#define ASTDP_1152x864_75            0x1F
>>
>>> +
>>
>>>     int ast_mm_init(struct ast_private *ast);
>>
>>>
>>
>>>     /* ast post */
>>
>>> @@ -381,4 +489,11 @@ void ast_init_3rdtx(struct drm_device *dev);
>>
>>>     /* ast_i2c.c */
>>
>>>    struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev);
>>
>>>
>>
>>> +/* aspeed DP */
>>
>>> +int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata); void
>>
>>> +ast_dp_launch(struct drm_device *dev, u8 bPower); void
>>
>>> +ast_dp_power_on_off(struct drm_device *dev, bool no); void
>>
>>> +ast_dp_set_on_off(struct drm_device *dev, bool no); void
>>
>>> +ast_dp_set_mode(struct drm_crtc *crtc, struct ast_vbios_mode_info
>>
>>> +*vbios_mode);
>>
>>> +
>>
>>>     #endif
>>
>>> diff --git a/drivers/gpu/drm/ast/ast_main.c
>>
>>> b/drivers/gpu/drm/ast/ast_main.c index 22e9e2d3c..1113ee1cb 100644
>>
>>> --- a/drivers/gpu/drm/ast/ast_main.c
>>
>>> +++ b/drivers/gpu/drm/ast/ast_main.c
>>
>>> @@ -232,7 +232,7 @@ static int ast_detect_chip(struct drm_device 
>>> *dev, bool *need_post)
>>
>>>                            ast->tx_chip_type = AST_TX_SIL164;
>>
>>>             }
>>
>>>
>>
>>> -    if ((ast->chip == AST2300) || (ast->chip == AST2400)) {
>>
>>> +   if ((ast->chip == AST2300) || (ast->chip == AST2400) || 
>>> +(ast->chip
>>
>>> +== AST2500)) {
>>
>>>                     /*
>>
>>>                      * On AST2300 and 2400, look the configuration 
>>> set by the SoC in
>>
>>>                      * the SOC scratch register #1 bits 11:8 
>>> (interestingly marked @@
>>
>>> -256,7 +256,8 @@ static int ast_detect_chip(struct drm_device *dev, 
>>> bool *need_post)
>>
>>>                     case 0x0c:
>>
>>>                             ast->tx_chip_type = AST_TX_DP501;
>>
>>>                     }
>>
>>> -    }
>>
>>> +   } else if (ast->chip == AST2600)
>>
>>> +           ast_dp_launch(&ast->base, 0);
>>
>>>
>>
>>>             /* Print stuff for diagnostic purposes */
>>
>>>             switch(ast->tx_chip_type) {
>>
>>> diff --git a/drivers/gpu/drm/ast/ast_mode.c
>>
>>> b/drivers/gpu/drm/ast/ast_mode.c index 45b56b39a..4728825b7 100644
>>
>>> --- a/drivers/gpu/drm/ast/ast_mode.c
>>
>>> +++ b/drivers/gpu/drm/ast/ast_mode.c
>>
>>> @@ -988,21 +988,41 @@ static int ast_cursor_plane_init(struct 
>>> ast_private *ast)
>>
>>>     static void ast_crtc_dpms(struct drm_crtc *crtc, int mode)
>>
>>>     {
>>
>>>             struct ast_private *ast = to_ast_private(crtc->dev);
>>
>>> +   u8 ch = AST_DPMS_VSYNC_OFF | AST_DPMS_HSYNC_OFF;
>>
>>>
>>
>>>             /* TODO: Maybe control display signal generation with
>>
>>>              *       Sync Enable (bit CR17.7).
>>
>>>              */
>>
>>>             switch (mode) {
>>
>>>             case DRM_MODE_DPMS_ON:
>>
>>> -    case DRM_MODE_DPMS_STANDBY:
>>
>>> -    case DRM_MODE_DPMS_SUSPEND:
>>
>>> +           ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT,  0x01, 
>>> +0xdf, 0);
>>
>>> +           ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 
>>> +0xfc, 0);
>>
>>>                     if (ast->tx_chip_type == AST_TX_DP501)
>>
>>>                             ast_set_dp501_video_output(crtc->dev, 
>>> 1);
>>
>>> +
>>
>>> +           if (ast->tx_chip_type == AST_TX_ASTDP) {
>>
>>> +                   ast_dp_power_on_off(crtc->dev, AST_DP_POWER_ON);
>>
>>> +                   ast_wait_for_vretrace(ast);
>>
>>> +                   ast_dp_set_on_off(crtc->dev, 1);
>>
>>> +           }
>>
>>> +
>>
>>> +           ast_crtc_load_lut(ast, crtc);
>>
>>>                     break;
>>
>>> +   case DRM_MODE_DPMS_STANDBY:
>>
>>> +   case DRM_MODE_DPMS_SUSPEND:
>>
>>>             case DRM_MODE_DPMS_OFF:
>>
>>> +           ch = mode;
>>
>>>                     if (ast->tx_chip_type == AST_TX_DP501)
>>
>>>                             ast_set_dp501_video_output(crtc->dev, 
>>> 0);
>>
>>>                     break;
>>
>>> +
>>
>>> +           if (ast->tx_chip_type == AST_TX_ASTDP) {
>>
>>> +                   ast_dp_set_on_off(crtc->dev, 0);
>>
>>> +                   ast_dp_power_on_off(crtc->dev, 
>>> +AST_DP_POWER_OFF);
>>
>>> +           }
>>
>>> +
>>
>>> +           ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT,  0x01, 
>>> +0xdf, 0x20);
>>
>>> +           ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 
>>> +0xfc, ch);
>>
>>>             }
>>
>>>     }
>>
>>>
>>
>>> @@ -1027,7 +1047,7 @@ ast_crtc_helper_mode_valid(struct drm_crtc
>>
>>> *crtc, const struct drm_display_mode
>>
>>>
>>
>>>                     if ((ast->chip == AST2100) || (ast->chip ==
>>> AST2200) ||
>>
>>>                         (ast->chip == AST2300) || (ast->chip ==
>>> AST2400) ||
>>
>>> -                (ast->chip == AST2500)) {
>>
>>> +               (ast->chip == AST2500) || (ast->chip == AST2600)) {
>>
>>>                             if ((mode->hdisplay == 1920) && 
>>> (mode->vdisplay == 1080))
>>
>>>                                     return MODE_OK;
>>
>>>
>>
>>> @@ -1110,6 +1130,7 @@ ast_crtc_helper_atomic_flush(struct drm_crtc 
>>> *crtc,
>>
>>>             struct ast_private *ast = to_ast_private(crtc->dev);
>>
>>>             struct ast_crtc_state *ast_crtc_state = 
>>> to_ast_crtc_state(crtc_state);
>>
>>>             struct ast_crtc_state *old_ast_crtc_state =
>>
>>> to_ast_crtc_state(old_crtc_state);
>>
>>> +   struct ast_vbios_mode_info *vbios_mode_info =
>>
>>> +&ast_crtc_state->vbios_mode_info;
>>
>>>
>>
>>>             /*
>>
>>>              * The gamma LUT has to be reloaded after changing the 
>>> primary @@
>>
>>> -1117,6 +1138,10 @@ ast_crtc_helper_atomic_flush(struct drm_crtc 
>>> *crtc,
>>
>>>              */
>>
>>>             if (old_ast_crtc_state->format != 
>>> ast_crtc_state->format)
>>
>>>                     ast_crtc_load_lut(ast, crtc);
>>
>>> +
>>
>>> +   //Set Aspeed Display-Port
>>
>>> +   if (ast->tx_chip_type == AST_TX_ASTDP)
>>
>>> +           ast_dp_set_mode(crtc, vbios_mode_info);
>>
>>>     }
>>
>>>
>>
>>>     static void
>>
>>> @@ -1527,6 +1552,93 @@ static int ast_dp501_output_init(struct 
>>> ast_private *ast)
>>
>>>             return 0;
>>
>>>     }
>>
>>>
>>
>>> +/*
>>
>>> + * ASPEED Display-Port Connector
>>
>>> + */
>>
>>> +
>>
>>> +static int ast_astdp_connector_helper_get_modes(struct 
>>> +drm_connector
>>
>>> +*connector) {
>>
>>> +   void *edid;
>>
>>> +
>>
>>> +   int succ;
>>
>>> +   int count;
>>
>>> +
>>
>>> +   edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
>>
>>> +   if (!edid)
>>
>>> +           goto err_drm_connector_update_edid_property;
>>
>>> +
>>
>>> +   succ = ast_astdp_read_edid(connector->dev, edid);
>>
>>> +   if (succ < 0)
>>
>>> +           goto err_kfree;
>>
>>> +
>>
>>> +   drm_connector_update_edid_property(connector, edid);
>>
>>> +   count = drm_add_edid_modes(connector, edid);
>>
>>> +   kfree(edid);
>>
>>> +
>>
>>> +   return count;
>>
>>> +
>>
>>> +err_kfree:
>>
>>> +   kfree(edid);
>>
>>> +err_drm_connector_update_edid_property:
>>
>>> +   drm_connector_update_edid_property(connector, NULL);
>>
>>> +   return 0;
>>
>>> +}
>>
>>> +
>>
>>> +static const struct drm_connector_helper_funcs 
>>> +ast_astdp_connector_helper_funcs = {
>>
>>> +   .get_modes = ast_astdp_connector_helper_get_modes,
>>
>>> +};
>>
>>> +
>>
>>> +static const struct drm_connector_funcs ast_astdp_connector_funcs = 
>>> +{
>>
>>> +   .reset = drm_atomic_helper_connector_reset,
>>
>>> +   .fill_modes = drm_helper_probe_single_connector_modes,
>>
>>> +   .destroy = drm_connector_cleanup,
>>
>>> +   .atomic_duplicate_state =
>>> +drm_atomic_helper_connector_duplicate_state,
>>
>>> +   .atomic_destroy_state =
>>> +drm_atomic_helper_connector_destroy_state,
>>
>>> +};
>>
>>> +
>>
>>> +static int ast_astdp_connector_init(struct drm_device *dev, struct
>>
>>> +drm_connector *connector) {
>>
>>> +   int ret;
>>
>>> +
>>
>>> +   ret = drm_connector_init(dev, connector, 
>>> +&ast_astdp_connector_funcs,
>>
>>> +                           DRM_MODE_CONNECTOR_DisplayPort);
>>
>>> +   if (ret)
>>
>>> +           return ret;
>>
>>> +
>>
>>> +   drm_connector_helper_add(connector,
>>
>>> +&ast_astdp_connector_helper_funcs);
>>
>>> +
>>
>>> +   connector->interlace_allowed = 0;
>>
>>> +   connector->doublescan_allowed = 0;
>>
>>> +
>>
>>> +   connector->polled = DRM_CONNECTOR_POLL_CONNECT;
>>
>>> +
>>
>>> +   return 0;
>>
>>> +}
>>
>>> +
>>
>>> +static int ast_astdp_output_init(struct ast_private *ast) {
>>
>>> +   struct drm_device *dev = &ast->base;
>>
>>> +   struct drm_crtc *crtc = &ast->crtc;
>>
>>> +   struct drm_encoder *encoder = &ast->output.astdp.encoder;
>>
>>> +   struct drm_connector *connector = &ast->output.astdp.connector;
>>
>>> +   int ret;
>>
>>> +
>>
>>> +   ret = drm_simple_encoder_init(dev, encoder, 
>>> +DRM_MODE_ENCODER_TMDS);
>>
>>> +   if (ret)
>>
>>> +           return ret;
>>
>>> +   encoder->possible_crtcs = drm_crtc_mask(crtc);
>>
>>> +
>>
>>> +   ret = ast_astdp_connector_init(dev, connector);
>>
>>> +   if (ret)
>>
>>> +           return ret;
>>
>>> +
>>
>>> +   ret = drm_connector_attach_encoder(connector, encoder);
>>
>>> +   if (ret)
>>
>>> +           return ret;
>>
>>> +
>>
>>> +   return 0;
>>
>>> +}
>>
>>> +
>>
>>>     /*
>>
>>>      * Mode config
>>
>>>      */
>>
>>> @@ -1563,7 +1675,8 @@ int ast_mode_config_init(struct ast_private
>>> *ast)
>>
>>>                 ast->chip == AST2200 ||
>>
>>>                 ast->chip == AST2300 ||
>>
>>>                 ast->chip == AST2400 ||
>>
>>> -        ast->chip == AST2500) {
>>
>>> +       ast->chip == AST2500 ||
>>
>>> +       ast->chip == AST2600) {
>>
>>>                     dev->mode_config.max_width = 1920;
>>
>>>                     dev->mode_config.max_height = 2048;
>>
>>>             } else {
>>
>>> @@ -1594,6 +1707,9 @@ int ast_mode_config_init(struct ast_private
>>> *ast)
>>
>>>             case AST_TX_DP501:
>>
>>>                     ret = ast_dp501_output_init(ast);
>>
>>>                     break;
>>
>>> +   case AST_TX_ASTDP:
>>
>>> +           ret = ast_astdp_output_init(ast);
>>
>>> +           break;
>>
>>>             }
>>
>>>             if (ret)
>>
>>>                     return ret;
>>
>>> diff --git a/drivers/gpu/drm/ast/ast_post.c
>>
>>> b/drivers/gpu/drm/ast/ast_post.c index b5d92f652..0aa9cf0fb 100644
>>
>>> --- a/drivers/gpu/drm/ast/ast_post.c
>>
>>> +++ b/drivers/gpu/drm/ast/ast_post.c
>>
>>> @@ -379,7 +379,9 @@ void ast_post_gpu(struct drm_device *dev)
>>
>>>             ast_enable_mmio(dev);
>>
>>>             ast_set_def_ext_reg(dev);
>>
>>>
>>
>>> -    if (ast->config_mode == ast_use_p2a) {
>>
>>> +   if (ast->chip == AST2600) {
>>
>>> +           ast_dp_launch(dev, 1);
>>
>>> +   } else if (ast->config_mode == ast_use_p2a) {
>>
>>>                     if (ast->chip == AST2500)
>>
>>>                             ast_post_chip_2500(dev);
>>
>>>                     else if (ast->chip == AST2300 || ast->chip ==
>>> AST2400)
>>
>>>
>>
>>> base-commit: c54b39a565227538c52ead2349eb17d54aadd6f7
>>
>>> --
>>
>>> 2.27.0
>>
>>>
>>
>> --
>>
>> Thomas Zimmermann
>>
>> Graphics Driver Developer
>>
>> SUSE Software Solutions Germany GmbH
>>
>> Maxfeldstr. 5, 90409 Nürnberg, Germany
>>
>> (HRB 36809, AG Nürnberg)
>>
>> Geschäftsführer: Ivo Totev
>>
> 
> --
> Thomas Zimmermann
> Graphics Driver Developer
> SUSE Software Solutions Germany GmbH
> Maxfeldstr. 5, 90409 Nürnberg, Germany (HRB 36809, AG Nürnberg)
> Geschäftsführer: Ivo Totev

--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Ivo Totev

^ permalink raw reply	[flat|nested] 21+ messages in thread

* RE: [PATCH v4] drm/ast: Create the driver for ASPEED proprietory Display-Port
  2022-05-13 10:39                   ` Kuo-Hsiang Chou
@ 2022-05-30  6:05                     ` Kuo-Hsiang Chou
  2022-06-01 10:42                       ` Thomas Zimmermann
  0 siblings, 1 reply; 21+ messages in thread
From: Kuo-Hsiang Chou @ 2022-05-30  6:05 UTC (permalink / raw)
  To: Kuo-Hsiang Chou, Thomas Zimmermann, dri-devel, linux-kernel
  Cc: Hungju Huang, airlied, Tommy Huang, airlied, Arc Sung, Luke Chen

Hi Thomas,

-----Original Message-----
From: dri-devel [mailto:dri-devel-bounces@lists.freedesktop.org] On Behalf Of Kuo-Hsiang Chou
Sent: Friday, May 13, 2022 6:39 PM
To: Thomas Zimmermann <tzimmermann@suse.de>; dri-devel@lists.freedesktop.org; linux-kernel@vger.kernel.org
Subject: RE: [PATCH v4] drm/ast: Create the driver for ASPEED proprietory Display-Port

Hi Thomas,

-----Original Message-----
From: Thomas Zimmermann [mailto:tzimmermann@suse.de] 
Sent: Friday, May 13, 2022 6:21 PM
To: Kuo-Hsiang Chou <kuohsiang_chou@aspeedtech.com>; dri-devel@lists.freedesktop.org; linux-kernel@vger.kernel.org
Subject: Re: [PATCH v4] drm/ast: Create the driver for ASPEED proprietory Display-Port


Hi

Am 13.05.22 um 11:07 schrieb Kuo-Hsiang Chou:
> 
> 
> -----Original Message-----
> From: Thomas Zimmermann [mailto:tzimmermann@suse.de]
> Sent: Tuesday, May 10, 2022 6:56 PM
> To: Kuo-Hsiang Chou <kuohsiang_chou@aspeedtech.com>; 
> dri-devel@lists.freedesktop.org; linux-kernel@vger.kernel.org
> Subject: Re: [PATCH v4] drm/ast: Create the driver for ASPEED 
> proprietory Display-Port
> 
> Hi
> 
> Am 04.05.22 um 10:49 schrieb Kuo-Hsiang Chou:
>> Hi Thomas,
>>
>> Thanks for your efforts to review this patch.
>>
>> Now, I observe a change that after DP unplugged and then the system 
>> is unable to get EDID from D-sub connecting.
>>
>> The reason seems that TXs are merged into union structure in 
>> /drivers/gpu/drm/ast/ast_drv.h
>>    (a59b026419f33040d7d28b8e3b1cea681b9ce7a7
>> <https://cgit.freedesktop.org/drm/drm-misc/commit/?id=a59b026419f3304
>> 0
>> d7d28b8e3b1cea681b9ce7a7>)
> 
> I have posted a patch that enables multiple parallel outputs. See
> 
>   
> <https://lore.kernel.org/dri-devel/20220510105010.20712-1-tzimmermann@
> suse.de/T/#u>
> 
> If you have the time, I'd appreciate if you could test it.
> 
> Hi Thomas,
> First, thanks for your efforts on this patch of " enables multiple parallel outputs ".
> But it doesn't work. There is still NO EDID got from D-sub after DP unplugged.
> 
> Base on your patch, I am trying to find out the solution also.
> Final, thanks for your help again!

Let's try to find a solution. I might be able to come up with something if I have enough information.

How are these outputs connected to each each other?
1. DP and D-sub both connected: it is correct to get EDID and monitor type is correctly shown on display setting. Resolution is up to 1920*1200.
2. DP unplugged and only D-sub connected: Unknown Display is shown on display setting. Only 800*600 and 1024*768 are available for Resolution.

They are both served by the same CRTC. Can they be used at the same time?  
No, 2 different monitors are connected at same time. 
One is connected by D-sub and another is connected by DP connecting.

Are they mutually exclusive?
Yes, If DP and D-sub are all connecting, DP's EDID is first priority for Display setting.
When DP unplugged, EDID got from D-sub are used for Display setting.

Now, I try to add the codes of ast_vga_connector_helper_get_modes() into ast_astdp_connector_helper_get_modes().
The result is failed.
Anyway, I will continue to try and test the feature next Monday. 
Thanks for your great help!

Hi Thomas,
Your patch is workable to switch resolution on Single Display option of Display setting.

And I test resolution switching on Single Display between ASTDP and VGA.
Yes, the left-top number indicates the current resolution decided by ASTDP or VGA.

I also try to change resolution on Mirror and Join Display option.
But there is on Apply button shown in the right-top corner of Display setting.

Thanks for your help!
Regards,
	Kuo-Hsiang Chou

Regards,
	Kuo-Hsiang Chou

Best regards
Thomas

> 
> Regards,
> 	Kuo-Hsiang Chou
> 
> Best regards
> Thomas
> 
>>
>> Another, do you need the ast2600 EVB to ease verification on "drm/ast" ?
>>
>> Regards,
>>
>>           Kuo-Hsiang Chou
>>
>> -----Original Message-----
>> From: Thomas Zimmermann [mailto:tzimmermann@suse.de]
>> Sent: Wednesday, May 04, 2022 3:28 PM
>> To: Kuo-Hsiang Chou <kuohsiang_chou@aspeedtech.com>; 
>> dri-devel@lists.freedesktop.org; linux-kernel@vger.kernel.org
>> Subject: Re: [PATCH v4] drm/ast: Create the driver for ASPEED 
>> proprietory Display-Port
>>
>> Hi
>>
>> Am 28.04.22 um 09:56 schrieb KuoHsiang Chou:
>>
>>> V1:
>>
>>> 1. The MCU FW controling ASPEED DP is loaded by BMC boot loader.
>>
>>> 2. Driver starts after CR[3:1] == 111b that indicates Tx is ASTDP,
>>
>>>       and CRD1[5] has been asserted by BMVC boot loader.
>>
>>> 3. EDID is prioritized by DP monitor.
>>
>>> 4. DP's EDID has high priority to decide resolution supporting.
>>
>>>
>>
>>> V2:
>>
>>> Modules description:
>>
>>> 1. ASTDP (ASPEED DisplayPort) is controlled by dedicated
>>
>>>       AST-MCU (ASPEED propriatary MCU).
>>
>>> 2. MCU is looping in charged of HPD, Read EDID, Link Training with
>>
>>>       DP sink.
>>
>>> 3. ASTDP and AST-MUC reside in BMC (Baseboard Management controller)
>>
>>>       addressing-space.
>>
>>> 4. ASPEED DRM driver requests MCU to get HPD and EDID by 
>>> CR-scratched
>>
>>>       register.
>>
>>>
>>
>>> Booting sequence:
>>
>>> 1. Check if TX is ASTDP                                        //
>>> ast_dp_launch()
>>
>>> 2. Check if DP-MCU FW has loaded
>>> // ast_dp_launch()
>>
>>> 3. Read EDID                                        //
>>> ast_dp_read_edid()
>>
>>> 4. Resolution switch                                     //
>>> ast_dp_SetOutput()
>>
>>>
>>
>>> V3:
>>
>>> 1. Remove unneeded semicolon.
>>
>>> 2. Apply to git://anongit.freedesktop.org/drm/drm, instead of
>>
>>>       git://anongit.freedesktop.org/drm/drm-misc
>>
>>> 3. Resolve auto build test WARNINGs on V1 patch.
>>
>>>
>>
>>> V4:
>>
>>> 1. Sync code-base with kernel 5.17_rc6 2. Remove the define of
>>
>>> DPControlPower, because DP chips need to be
>>
>>>       powered on to be used.
>>
>>> 3. Remove the switches of PHY and Display from EDID procedure.
>>
>>> 4. Revise increaing delay to fixed delay, because this version 
>>> kernel
>>
>>>       doesn't detect minitor consistenntly.
>>
>>> 5. Create clean-up code used for reset of power state on errors with
>>
>>>       -EIO manner.
>>
>>> 6. Revise the DP detection by TX type and its DP-FW status during
>>
>>>       booting and resume.
>>
>>> 7. Correct the CamelCase Style.
>>
>>> 8. Use register reading while needing, and remove to hold full
>>
>>>       register.
>>
>>> 9. Instead of 'u8', revise to 'bool' on swwitch of PHY and video.
>>
>>> 10.Correct typo
>>
>>> 11.Remove the duplicated copy of TX definition.
>>
>>> 12.Use EDID_LENGTH as the constant of 128.
>>
>>>
>>
>>> Signed-off-by: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com 
>>> <mailto:kuohsiang_chou@aspeedtech.com>>
>>
>> Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de 
>> <mailto:tzimmermann@suse.de>>
>>
>> I've meanwhile added your patch to drm-misc-next. It should show up 
>> in one of the next kernel releases.  Thanks a lot.
>>
>> Best regards
>>
>> Thomas
>>
>>> ---
>>
>>>     drivers/gpu/drm/ast/Makefile   |   2 +-
>>
>>>     drivers/gpu/drm/ast/ast_dp.c   | 282
>>> +++++++++++++++++++++++++++++++++
>>
>>>     drivers/gpu/drm/ast/ast_drv.h  | 115 ++++++++++++++
>>
>>>     drivers/gpu/drm/ast/ast_main.c |   5 +-
>>
>>>     drivers/gpu/drm/ast/ast_mode.c | 124 ++++++++++++++-
>>
>>>     drivers/gpu/drm/ast/ast_post.c |   4 +-
>>
>>>     6 files changed, 524 insertions(+), 8 deletions(-)
>>
>>>     create mode 100644 drivers/gpu/drm/ast/ast_dp.c
>>
>>>
>>
>>> diff --git a/drivers/gpu/drm/ast/Makefile
>>
>>> b/drivers/gpu/drm/ast/Makefile index 21f71160b..5a53ce51f 100644
>>
>>> --- a/drivers/gpu/drm/ast/Makefile
>>
>>> +++ b/drivers/gpu/drm/ast/Makefile
>>
>>> @@ -3,6 +3,6 @@
>>
>>>     # Makefile for the drm device driver.  This driver provides 
>>> support for the
>>
>>>     # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
>>
>>>
>>
>>> -ast-y := ast_drv.o ast_i2c.o ast_main.o ast_mm.o ast_mode.o
>>
>>> ast_post.o ast_dp501.o
>>
>>> +ast-y := ast_drv.o ast_i2c.o ast_main.o ast_mm.o ast_mode.o
>>
>>> +ast_post.o ast_dp501.o ast_dp.o
>>
>>>
>>
>>>     obj-$(CONFIG_DRM_AST) := ast.o
>>
>>> diff --git a/drivers/gpu/drm/ast/ast_dp.c
>>
>>> b/drivers/gpu/drm/ast/ast_dp.c new file mode 100644 index
>>
>>> 000000000..4551bc8a3
>>
>>> --- /dev/null
>>
>>> +++ b/drivers/gpu/drm/ast/ast_dp.c
>>
>>> @@ -0,0 +1,282 @@
>>
>>> +// SPDX-License-Identifier: GPL-2.0
>>
>>> +// Copyright (c) 2021, ASPEED Technology Inc.
>>
>>> +// Authors: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com 
>>> +<mailto:kuohsiang_chou@aspeedtech.com>>
>>
>>> +
>>
>>> +#include <linux/firmware.h>
>>
>>> +#include <linux/delay.h>
>>
>>> +#include <drm/drm_print.h>
>>
>>> +#include "ast_drv.h"
>>
>>> +
>>
>>> +int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata) {
>>
>>> +   struct ast_private *ast = to_ast_private(dev);
>>
>>> +   u8 i = 0, j = 0;
>>
>>> +
>>
>>> +   /*
>>
>>> +   * CRD1[b5]: DP MCU FW is executing
>>
>>> +   * CRDC[b0]: DP link success
>>
>>> +   * CRDF[b0]: DP HPD
>>
>>> +   * CRE5[b0]: Host reading EDID process is done
>>
>>> +   */
>>
>>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1,
>>> +ASTDP_MCU_FW_EXECUTING) &&
>>
>>> +           ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC,
>>> +ASTDP_LINK_SUCCESS) &&
>>
>>> +           ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF,
>>> +ASTDP_HPD) &&
>>
>>> +           ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
>>
>>> +
>>> +ASTDP_HOST_EDID_READ_DONE_MASK))) {
>>
>>> +           goto err_astdp_edid_not_ready;
>>
>>> +   }
>>
>>> +
>>
>>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8) 
>>> +~ASTDP_HOST_EDID_READ_DONE_MASK,
>>
>>> +                                                   0x00);
>>
>>> +
>>
>>> +   for (i = 0; i < 32; i++) {
>>
>>> +           /*
>>
>>> +           * CRE4[7:0]: Read-Pointer for EDID (Unit: 4bytes); valid
>>> +range: 0~64
>>
>>> +           */
>>
>>> +           ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE4,
>>
>>> +                                   (u8) 
>>> +~ASTDP_EDID_READ_POINTER_MASK, (u8) i);
>>
>>> +           j = 0;
>>
>>> +
>>
>>> +           /*
>>
>>> +           * CRD7[b0]: valid flag for EDID
>>
>>> +           * CRD6[b0]: mirror read pointer for EDID
>>
>>> +           */
>>
>>> +           while ((ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 
>>> +0xD7,
>>
>>> +                           ASTDP_EDID_VALID_FLAG_MASK) != 0x01) ||
>>
>>> +                   (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 
>>> +0xD6,
>>
>>> +
>>> +ASTDP_EDID_READ_POINTER_MASK) != i)) {
>>
>>> +                   /*
>>
>>> +                   * Delay are getting longer with each retry.
>>
>>> +                   * 1. The Delays are often 2 loops when users request "Display Settings"
>>
>>> +                   *      of right-click of mouse.
>>
>>> +                   * 2. The Delays are often longer a lot when system resume from S3/S4.
>>
>>> +                   */
>>
>>> +                   mdelay(j+1);
>>
>>> +
>>
>>> +                   if (!(ast_get_index_reg_mask(ast, 
>>> +AST_IO_CRTC_PORT, 0xD1,
>>
>>> +
>>> +ASTDP_MCU_FW_EXECUTING) &&
>>
>>> +                           ast_get_index_reg_mask(ast, 
>>> +AST_IO_CRTC_PORT, 0xDC,
>>
>>> +
>>> +ASTDP_LINK_SUCCESS) &&
>>
>>> +                           ast_get_index_reg_mask(ast, 
>>> +AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD))) {
>>
>>> +                           goto err_astdp_jump_out_loop_of_edid;
>>
>>> +                   }
>>
>>> +
>>
>>> +                   j++;
>>
>>> +                   if (j > 200)
>>
>>> +                           goto err_astdp_jump_out_loop_of_edid;
>>
>>> +           }
>>
>>> +
>>
>>> +           *(ediddata) = ast_get_index_reg_mask(ast, 
>>> +AST_IO_CRTC_PORT,
>>
>>> +                                                   0xD8, 
>>> +ASTDP_EDID_READ_DATA_MASK);
>>
>>> +           *(ediddata + 1) = ast_get_index_reg_mask(ast, 
>>> +AST_IO_CRTC_PORT, 0xD9,
>>
>>> +
>>> +ASTDP_EDID_READ_DATA_MASK);
>>
>>> +           *(ediddata + 2) = ast_get_index_reg_mask(ast, 
>>> +AST_IO_CRTC_PORT, 0xDA,
>>
>>> +
>>> +ASTDP_EDID_READ_DATA_MASK);
>>
>>> +           *(ediddata + 3) = ast_get_index_reg_mask(ast, 
>>> +AST_IO_CRTC_PORT, 0xDB,
>>
>>> +
>>> +ASTDP_EDID_READ_DATA_MASK);
>>
>>> +
>>
>>> +           if (i == 31) {
>>
>>> +                   /*
>>
>>> +                   * For 128-bytes EDID_1.3,
>>
>>> +                   * 1. Add the value of Bytes-126 to Bytes-127.
>>
>>> +                   *            The Bytes-127 is Checksum. Sum of 
>>> +all 128bytes should
>>
>>> +                   *            equal 0    (mod 256).
>>
>>> +                   * 2. Modify Bytes-126 to be 0.
>>
>>> +                   *            The Bytes-126 indicates the Number 
>>> +of extensions to
>>
>>> +                   *            follow. 0 represents noextensions.
>>
>>> +                   */
>>
>>> +                   *(ediddata + 3) = *(ediddata + 3) + *(ediddata + 
>>> +2);
>>
>>> +                   *(ediddata + 2) = 0;
>>
>>> +           }
>>
>>> +
>>
>>> +           ediddata += 4;
>>
>>> +   }
>>
>>> +
>>
>>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8) 
>>> +~ASTDP_HOST_EDID_READ_DONE_MASK,
>>
>>> +
>>> +ASTDP_HOST_EDID_READ_DONE);
>>
>>> +
>>
>>> +   return 0;
>>
>>> +
>>
>>> +err_astdp_jump_out_loop_of_edid:
>>
>>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
>>
>>> +                                                   (u8) 
>>> +~ASTDP_HOST_EDID_READ_DONE_MASK,
>>
>>> +
>>> +ASTDP_HOST_EDID_READ_DONE);
>>
>>> +   return (~(j+256) + 1);
>>
>>> +
>>
>>> +err_astdp_edid_not_ready:
>>
>>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1,
>>> +ASTDP_MCU_FW_EXECUTING)))
>>
>>> +           return (~0xD1 + 1);
>>
>>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC,
>>> +ASTDP_LINK_SUCCESS)))
>>
>>> +           return (~0xDC + 1);
>>
>>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF,
>>> +ASTDP_HPD)))
>>
>>> +           return (~0xDF + 1);
>>
>>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
>>> +ASTDP_HOST_EDID_READ_DONE_MASK)))
>>
>>> +           return (~0xE5 + 1);
>>
>>> +
>>
>>> +   return      0;
>>
>>> +}
>>
>>> +
>>
>>> +/*
>>
>>> + * Launch Aspeed DP
>>
>>> + */
>>
>>> +void ast_dp_launch(struct drm_device *dev, u8 bPower) {
>>
>>> +   u32 i = 0, j = 0, WaitCount = 1;
>>
>>> +   u8 bDPTX = 0;
>>
>>> +   u8 bDPExecute = 1;
>>
>>> +
>>
>>> +   struct ast_private *ast = to_ast_private(dev);
>>
>>> +   // S3 come back, need more time to wait BMC ready.
>>
>>> +   if (bPower)
>>
>>> +           WaitCount = 300;
>>
>>> +
>>
>>> +
>>
>>> +   // Wait total count by different condition.
>>
>>> +   for (j = 0; j < WaitCount; j++) {
>>
>>> +           bDPTX = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 
>>> +0xD1,
>>
>>> +TX_TYPE_MASK);
>>
>>> +
>>
>>> +           if (bDPTX)
>>
>>> +                   break;
>>
>>> +
>>
>>> +           msleep(100);
>>
>>> +   }
>>
>>> +
>>
>>> +   // 0xE : ASTDP with DPMCU FW handling
>>
>>> +   if (bDPTX == ASTDP_DPMCU_TX) {
>>
>>> +           // Wait one second then timeout.
>>
>>> +           i = 0;
>>
>>> +
>>
>>> +           while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 
>>> +0xD1, COPROCESSOR_LAUNCH) !=
>>
>>> +                   COPROCESSOR_LAUNCH) {
>>
>>> +                   i++;
>>
>>> +                   // wait 100 ms
>>
>>> +                   msleep(100);
>>
>>> +
>>
>>> +                   if (i >= 10) {
>>
>>> +                           // DP would not be ready.
>>
>>> +                           bDPExecute = 0;
>>
>>> +                           break;
>>
>>> +                   }
>>
>>> +           }
>>
>>> +
>>
>>> +           if (bDPExecute)
>>
>>> +                   ast->tx_chip_type = AST_TX_ASTDP;
>>
>>> +
>>
>>> +           ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
>>
>>> +                                                   (u8) 
>>> +~ASTDP_HOST_EDID_READ_DONE_MASK,
>>
>>> +
>>> +ASTDP_HOST_EDID_READ_DONE);
>>
>>> +   } else
>>
>>> +           ast->tx_chip_type = AST_TX_NONE;
>>
>>> +}
>>
>>> +
>>
>>> +
>>
>>> +
>>
>>> +void ast_dp_power_on_off(struct drm_device *dev, bool on) {
>>
>>> +   struct ast_private *ast = to_ast_private(dev);
>>
>>> +   // Read and Turn off DP PHY sleep
>>
>>> +   u8 bE3 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3,
>>
>>> +AST_DP_VIDEO_ENABLE);
>>
>>> +
>>
>>> +   // Turn on DP PHY sleep
>>
>>> +   if (!on)
>>
>>> +           bE3 |= AST_DP_PHY_SLEEP;
>>
>>> +
>>
>>> +   // DP Power on/off
>>
>>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, (u8)
>>
>>> +~AST_DP_PHY_SLEEP, bE3); }
>>
>>> +
>>
>>> +
>>
>>> +
>>
>>> +void ast_dp_set_on_off(struct drm_device *dev, bool on) {
>>
>>> +   struct ast_private *ast = to_ast_private(dev);
>>
>>> +   u8 video_on_off = on;
>>
>>> +
>>
>>> +   // Video On/Off
>>
>>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, (u8)
>>
>>> +~AST_DP_VIDEO_ENABLE, on);
>>
>>> +
>>
>>> +   // If DP plug in and link successful then check video on / off 
>>> +status
>>
>>> +   if (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC,
>>> +ASTDP_LINK_SUCCESS) &&
>>
>>> +           ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF,
>>> +ASTDP_HPD)) {
>>
>>> +           video_on_off <<= 4;
>>
>>> +           while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 
>>> +0xDF,
>>
>>> +
>>> +ASTDP_MIRROR_VIDEO_ENABLE) != video_on_off) {
>>
>>> +                   // wait 1 ms
>>
>>> +                   mdelay(1);
>>
>>> +           }
>>
>>> +   }
>>
>>> +}
>>
>>> +
>>
>>> +void ast_dp_set_mode(struct drm_crtc *crtc, struct
>>
>>> +ast_vbios_mode_info *vbios_mode) {
>>
>>> +   struct ast_private *ast = to_ast_private(crtc->dev);
>>
>>> +
>>
>>> +   u32 ulRefreshRateIndex;
>>
>>> +   u8 ModeIdx;
>>
>>> +
>>
>>> +   ulRefreshRateIndex = vbios_mode->enh_table->refresh_rate_index - 
>>> +1;
>>
>>> +
>>
>>> +   switch (crtc->mode.crtc_hdisplay) {
>>
>>> +   case 320:
>>
>>> +           ModeIdx = ASTDP_320x240_60;
>>
>>> +           break;
>>
>>> +   case 400:
>>
>>> +           ModeIdx = ASTDP_400x300_60;
>>
>>> +           break;
>>
>>> +   case 512:
>>
>>> +           ModeIdx = ASTDP_512x384_60;
>>
>>> +           break;
>>
>>> +   case 640:
>>
>>> +           ModeIdx = (ASTDP_640x480_60 + (u8) ulRefreshRateIndex);
>>
>>> +           break;
>>
>>> +   case 800:
>>
>>> +           ModeIdx = (ASTDP_800x600_56 + (u8) ulRefreshRateIndex);
>>
>>> +           break;
>>
>>> +   case 1024:
>>
>>> +           ModeIdx = (ASTDP_1024x768_60 + (u8) ulRefreshRateIndex);
>>
>>> +           break;
>>
>>> +   case 1152:
>>
>>> +           ModeIdx = ASTDP_1152x864_75;
>>
>>> +           break;
>>
>>> +   case 1280:
>>
>>> +           if (crtc->mode.crtc_vdisplay == 800)
>>
>>> +                   ModeIdx = (ASTDP_1280x800_60_RB - (u8) 
>>> +ulRefreshRateIndex);
>>
>>> +           else          // 1024
>>
>>> +                   ModeIdx = (ASTDP_1280x1024_60 + (u8) 
>>> +ulRefreshRateIndex);
>>
>>> +           break;
>>
>>> +   case 1360:
>>
>>> +   case 1366:
>>
>>> +           ModeIdx = ASTDP_1366x768_60;
>>
>>> +           break;
>>
>>> +   case 1440:
>>
>>> +           ModeIdx = (ASTDP_1440x900_60_RB - (u8) 
>>> +ulRefreshRateIndex);
>>
>>> +           break;
>>
>>> +   case 1600:
>>
>>> +           if (crtc->mode.crtc_vdisplay == 900)
>>
>>> +                   ModeIdx = (ASTDP_1600x900_60_RB - (u8) 
>>> +ulRefreshRateIndex);
>>
>>> +           else          //1200
>>
>>> +                   ModeIdx = ASTDP_1600x1200_60;
>>
>>> +           break;
>>
>>> +   case 1680:
>>
>>> +           ModeIdx = (ASTDP_1680x1050_60_RB - (u8) 
>>> +ulRefreshRateIndex);
>>
>>> +           break;
>>
>>> +   case 1920:
>>
>>> +           if (crtc->mode.crtc_vdisplay == 1080)
>>
>>> +                   ModeIdx = ASTDP_1920x1080_60;
>>
>>> +           else          //1200
>>
>>> +                   ModeIdx = ASTDP_1920x1200_60;
>>
>>> +           break;
>>
>>> +   default:
>>
>>> +           return;
>>
>>> +   }
>>
>>> +
>>
>>> +   /*
>>
>>> +   * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp)
>>
>>> +   * CRE1[7:0]: MISC1 (default: 0x00)
>>
>>> +   * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50)
>>
>>> +   */
>>
>>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE0, (u8) 
>>> +~ASTDP_CLEAR_MASK,
>>
>>> +                           ASTDP_MISC0_24bpp);
>>
>>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE1, (u8) 
>>> +~ASTDP_CLEAR_MASK, ASTDP_MISC1);
>>
>>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE2, (u8)
>>
>>> +~ASTDP_CLEAR_MASK, ModeIdx); }
>>
>>> diff --git a/drivers/gpu/drm/ast/ast_drv.h
>>
>>> b/drivers/gpu/drm/ast/ast_drv.h index a19315b2f..ff1ae314b 100644
>>
>>> --- a/drivers/gpu/drm/ast/ast_drv.h
>>
>>> +++ b/drivers/gpu/drm/ast/ast_drv.h
>>
>>> @@ -70,6 +70,7 @@ enum ast_tx_chip {
>>
>>>             AST_TX_NONE,
>>
>>>             AST_TX_SIL164,
>>
>>>             AST_TX_DP501,
>>
>>> +   AST_TX_ASTDP,
>>
>>>     };
>>
>>>
>>
>>>     #define AST_DRAM_512Mx16 0
>>
>>> @@ -184,6 +185,10 @@ struct ast_private {
>>
>>>                             struct drm_encoder encoder;
>>
>>>                             struct drm_connector connector;
>>
>>>                     } dp501;
>>
>>> +           struct {
>>
>>> +                   struct drm_encoder encoder;
>>
>>> +                   struct drm_connector connector;
>>
>>> +           } astdp;
>>
>>>             } output;
>>
>>>
>>
>>>             bool support_wide_screen;
>>
>>> @@ -357,10 +362,113 @@ int ast_mode_config_init(struct ast_private 
>>> *ast);
>>
>>>     #define AST_DP501_EDID_DATA    0xf020
>>
>>>
>>
>>>     /* Define for Soc scratched reg */
>>
>>> +#define COPROCESSOR_LAUNCH                     BIT(5)
>>
>>> +
>>
>>> +/*
>>
>>> + * Display Transmitter Type:
>>
>>> + */
>>
>>> +#define TX_TYPE_MASK                            GENMASK(3, 1)
>>
>>> +#define NO_TX                                            (0 << 1)
>>
>>> +#define ITE66121_VBIOS_TX                     (1 << 1)
>>
>>> +#define SI164_VBIOS_TX                           (2 << 1)
>>
>>> +#define CH7003_VBIOS_TX                       (3 << 1)
>>
>>> +#define DP501_VBIOS_TX                         (4 << 1)
>>
>>> +#define ANX9807_VBIOS_TX                     (5 << 1)
>>
>>> +#define TX_FW_EMBEDDED_FW_TX                (6 << 1)
>>
>>> +#define ASTDP_DPMCU_TX                               (7 << 1)
>>
>>> +
>>
>>>     #define AST_VRAM_INIT_STATUS_MASK       GENMASK(7, 6)
>>
>>>     //#define AST_VRAM_INIT_BY_BMC             BIT(7)
>>
>>>     //#define AST_VRAM_INIT_READY                BIT(6)
>>
>>>
>>
>>> +/* Define for Soc scratched reg used on ASTDP */
>>
>>> +#define AST_DP_PHY_SLEEP                     BIT(4)
>>
>>> +#define AST_DP_VIDEO_ENABLE              BIT(0)
>>
>>> +
>>
>>> +#define AST_DP_POWER_ON                    true
>>
>>> +#define AST_DP_POWER_OFF                   false
>>
>>> +
>>
>>> +/*
>>
>>> + * CRD1[b5]: DP MCU FW is executing
>>
>>> + * CRDC[b0]: DP link success
>>
>>> + * CRDF[b0]: DP HPD
>>
>>> + * CRE5[b0]: Host reading EDID process is done  */
>>
>>> +#define ASTDP_MCU_FW_EXECUTING                     BIT(5)
>>
>>> +#define ASTDP_LINK_SUCCESS                          BIT(0)
>>
>>> +#define ASTDP_HPD                                          BIT(0)
>>
>>> +#define ASTDP_HOST_EDID_READ_DONE                BIT(0)
>>
>>> +#define ASTDP_HOST_EDID_READ_DONE_MASK    GENMASK(0, 0)
>>
>>> +
>>
>>> +/*
>>
>>> + * CRB8[b1]: Enable VSYNC off
>>
>>> + * CRB8[b0]: Enable HSYNC off
>>
>>> + */
>>
>>> +#define AST_DPMS_VSYNC_OFF                               BIT(1)
>>
>>> +#define AST_DPMS_HSYNC_OFF                               BIT(0)
>>
>>> +
>>
>>> +/*
>>
>>> + * CRDF[b4]: Mirror of AST_DP_VIDEO_ENABLE
>>
>>> + * Precondition:  A. ~AST_DP_PHY_SLEEP  &&
>>
>>> + *                        B. DP_HPD &&
>>
>>> + *                        C. DP_LINK_SUCCESS
>>
>>> + */
>>
>>> +#define ASTDP_MIRROR_VIDEO_ENABLE                BIT(4)
>>
>>> +
>>
>>> +#define ASTDP_EDID_READ_POINTER_MASK  GENMASK(7, 0)
>>
>>> +#define ASTDP_EDID_VALID_FLAG_MASK                GENMASK(0, 0)
>>
>>> +#define ASTDP_EDID_READ_DATA_MASK        GENMASK(7, 0)
>>
>>> +
>>
>>> +/*
>>
>>> + * ASTDP setmode registers:
>>
>>> + * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp)
>>
>>> + * CRE1[7:0]: MISC1 (default: 0x00)
>>
>>> + * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50)  */
>>
>>> +#define ASTDP_MISC0_24bpp                   BIT(5)
>>
>>> +#define ASTDP_MISC1                               0
>>
>>> +#define ASTDP_CLEAR_MASK                   GENMASK(7, 0)
>>
>>> +
>>
>>> +/*
>>
>>> + * ASTDP resoultion table:
>>
>>> + * EX:  ASTDP_A_B_C:
>>
>>> + *                A: Resolution
>>
>>> + *                B: Refresh Rate
>>
>>> + *                C: Misc information, such as CVT, Reduce Blanked
>>
>>> + */
>>
>>> +#define ASTDP_640x480_60              0x00
>>
>>> +#define ASTDP_640x480_72              0x01
>>
>>> +#define ASTDP_640x480_75              0x02
>>
>>> +#define ASTDP_640x480_85              0x03
>>
>>> +#define ASTDP_800x600_56              0x04
>>
>>> +#define ASTDP_800x600_60              0x05
>>
>>> +#define ASTDP_800x600_72              0x06
>>
>>> +#define ASTDP_800x600_75              0x07
>>
>>> +#define ASTDP_800x600_85              0x08
>>
>>> +#define ASTDP_1024x768_60            0x09
>>
>>> +#define ASTDP_1024x768_70            0x0A
>>
>>> +#define ASTDP_1024x768_75            0x0B
>>
>>> +#define ASTDP_1024x768_85            0x0C
>>
>>> +#define ASTDP_1280x1024_60          0x0D
>>
>>> +#define ASTDP_1280x1024_75          0x0E
>>
>>> +#define ASTDP_1280x1024_85          0x0F
>>
>>> +#define ASTDP_1600x1200_60          0x10
>>
>>> +#define ASTDP_320x240_60              0x11
>>
>>> +#define ASTDP_400x300_60              0x12
>>
>>> +#define ASTDP_512x384_60              0x13
>>
>>> +#define ASTDP_1920x1200_60          0x14
>>
>>> +#define ASTDP_1920x1080_60          0x15
>>
>>> +#define ASTDP_1280x800_60            0x16
>>
>>> +#define ASTDP_1280x800_60_RB     0x17
>>
>>> +#define ASTDP_1440x900_60            0x18
>>
>>> +#define ASTDP_1440x900_60_RB     0x19
>>
>>> +#define ASTDP_1680x1050_60          0x1A
>>
>>> +#define ASTDP_1680x1050_60_RB   0x1B
>>
>>> +#define ASTDP_1600x900_60            0x1C
>>
>>> +#define ASTDP_1600x900_60_RB     0x1D
>>
>>> +#define ASTDP_1366x768_60            0x1E
>>
>>> +#define ASTDP_1152x864_75            0x1F
>>
>>> +
>>
>>>     int ast_mm_init(struct ast_private *ast);
>>
>>>
>>
>>>     /* ast post */
>>
>>> @@ -381,4 +489,11 @@ void ast_init_3rdtx(struct drm_device *dev);
>>
>>>     /* ast_i2c.c */
>>
>>>    struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev);
>>
>>>
>>
>>> +/* aspeed DP */
>>
>>> +int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata); void
>>
>>> +ast_dp_launch(struct drm_device *dev, u8 bPower); void
>>
>>> +ast_dp_power_on_off(struct drm_device *dev, bool no); void
>>
>>> +ast_dp_set_on_off(struct drm_device *dev, bool no); void
>>
>>> +ast_dp_set_mode(struct drm_crtc *crtc, struct ast_vbios_mode_info
>>
>>> +*vbios_mode);
>>
>>> +
>>
>>>     #endif
>>
>>> diff --git a/drivers/gpu/drm/ast/ast_main.c
>>
>>> b/drivers/gpu/drm/ast/ast_main.c index 22e9e2d3c..1113ee1cb 100644
>>
>>> --- a/drivers/gpu/drm/ast/ast_main.c
>>
>>> +++ b/drivers/gpu/drm/ast/ast_main.c
>>
>>> @@ -232,7 +232,7 @@ static int ast_detect_chip(struct drm_device 
>>> *dev, bool *need_post)
>>
>>>                            ast->tx_chip_type = AST_TX_SIL164;
>>
>>>             }
>>
>>>
>>
>>> -    if ((ast->chip == AST2300) || (ast->chip == AST2400)) {
>>
>>> +   if ((ast->chip == AST2300) || (ast->chip == AST2400) || 
>>> +(ast->chip
>>
>>> +== AST2500)) {
>>
>>>                     /*
>>
>>>                      * On AST2300 and 2400, look the configuration 
>>> set by the SoC in
>>
>>>                      * the SOC scratch register #1 bits 11:8 
>>> (interestingly marked @@
>>
>>> -256,7 +256,8 @@ static int ast_detect_chip(struct drm_device *dev, 
>>> bool *need_post)
>>
>>>                     case 0x0c:
>>
>>>                             ast->tx_chip_type = AST_TX_DP501;
>>
>>>                     }
>>
>>> -    }
>>
>>> +   } else if (ast->chip == AST2600)
>>
>>> +           ast_dp_launch(&ast->base, 0);
>>
>>>
>>
>>>             /* Print stuff for diagnostic purposes */
>>
>>>             switch(ast->tx_chip_type) {
>>
>>> diff --git a/drivers/gpu/drm/ast/ast_mode.c
>>
>>> b/drivers/gpu/drm/ast/ast_mode.c index 45b56b39a..4728825b7 100644
>>
>>> --- a/drivers/gpu/drm/ast/ast_mode.c
>>
>>> +++ b/drivers/gpu/drm/ast/ast_mode.c
>>
>>> @@ -988,21 +988,41 @@ static int ast_cursor_plane_init(struct 
>>> ast_private *ast)
>>
>>>     static void ast_crtc_dpms(struct drm_crtc *crtc, int mode)
>>
>>>     {
>>
>>>             struct ast_private *ast = to_ast_private(crtc->dev);
>>
>>> +   u8 ch = AST_DPMS_VSYNC_OFF | AST_DPMS_HSYNC_OFF;
>>
>>>
>>
>>>             /* TODO: Maybe control display signal generation with
>>
>>>              *       Sync Enable (bit CR17.7).
>>
>>>              */
>>
>>>             switch (mode) {
>>
>>>             case DRM_MODE_DPMS_ON:
>>
>>> -    case DRM_MODE_DPMS_STANDBY:
>>
>>> -    case DRM_MODE_DPMS_SUSPEND:
>>
>>> +           ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT,  0x01, 
>>> +0xdf, 0);
>>
>>> +           ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 
>>> +0xfc, 0);
>>
>>>                     if (ast->tx_chip_type == AST_TX_DP501)
>>
>>>                             ast_set_dp501_video_output(crtc->dev, 
>>> 1);
>>
>>> +
>>
>>> +           if (ast->tx_chip_type == AST_TX_ASTDP) {
>>
>>> +                   ast_dp_power_on_off(crtc->dev, AST_DP_POWER_ON);
>>
>>> +                   ast_wait_for_vretrace(ast);
>>
>>> +                   ast_dp_set_on_off(crtc->dev, 1);
>>
>>> +           }
>>
>>> +
>>
>>> +           ast_crtc_load_lut(ast, crtc);
>>
>>>                     break;
>>
>>> +   case DRM_MODE_DPMS_STANDBY:
>>
>>> +   case DRM_MODE_DPMS_SUSPEND:
>>
>>>             case DRM_MODE_DPMS_OFF:
>>
>>> +           ch = mode;
>>
>>>                     if (ast->tx_chip_type == AST_TX_DP501)
>>
>>>                             ast_set_dp501_video_output(crtc->dev, 
>>> 0);
>>
>>>                     break;
>>
>>> +
>>
>>> +           if (ast->tx_chip_type == AST_TX_ASTDP) {
>>
>>> +                   ast_dp_set_on_off(crtc->dev, 0);
>>
>>> +                   ast_dp_power_on_off(crtc->dev, 
>>> +AST_DP_POWER_OFF);
>>
>>> +           }
>>
>>> +
>>
>>> +           ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT,  0x01, 
>>> +0xdf, 0x20);
>>
>>> +           ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 
>>> +0xfc, ch);
>>
>>>             }
>>
>>>     }
>>
>>>
>>
>>> @@ -1027,7 +1047,7 @@ ast_crtc_helper_mode_valid(struct drm_crtc
>>
>>> *crtc, const struct drm_display_mode
>>
>>>
>>
>>>                     if ((ast->chip == AST2100) || (ast->chip ==
>>> AST2200) ||
>>
>>>                         (ast->chip == AST2300) || (ast->chip ==
>>> AST2400) ||
>>
>>> -                (ast->chip == AST2500)) {
>>
>>> +               (ast->chip == AST2500) || (ast->chip == AST2600)) {
>>
>>>                             if ((mode->hdisplay == 1920) && 
>>> (mode->vdisplay == 1080))
>>
>>>                                     return MODE_OK;
>>
>>>
>>
>>> @@ -1110,6 +1130,7 @@ ast_crtc_helper_atomic_flush(struct drm_crtc 
>>> *crtc,
>>
>>>             struct ast_private *ast = to_ast_private(crtc->dev);
>>
>>>             struct ast_crtc_state *ast_crtc_state = 
>>> to_ast_crtc_state(crtc_state);
>>
>>>             struct ast_crtc_state *old_ast_crtc_state =
>>
>>> to_ast_crtc_state(old_crtc_state);
>>
>>> +   struct ast_vbios_mode_info *vbios_mode_info =
>>
>>> +&ast_crtc_state->vbios_mode_info;
>>
>>>
>>
>>>             /*
>>
>>>              * The gamma LUT has to be reloaded after changing the 
>>> primary @@
>>
>>> -1117,6 +1138,10 @@ ast_crtc_helper_atomic_flush(struct drm_crtc 
>>> *crtc,
>>
>>>              */
>>
>>>             if (old_ast_crtc_state->format != 
>>> ast_crtc_state->format)
>>
>>>                     ast_crtc_load_lut(ast, crtc);
>>
>>> +
>>
>>> +   //Set Aspeed Display-Port
>>
>>> +   if (ast->tx_chip_type == AST_TX_ASTDP)
>>
>>> +           ast_dp_set_mode(crtc, vbios_mode_info);
>>
>>>     }
>>
>>>
>>
>>>     static void
>>
>>> @@ -1527,6 +1552,93 @@ static int ast_dp501_output_init(struct 
>>> ast_private *ast)
>>
>>>             return 0;
>>
>>>     }
>>
>>>
>>
>>> +/*
>>
>>> + * ASPEED Display-Port Connector
>>
>>> + */
>>
>>> +
>>
>>> +static int ast_astdp_connector_helper_get_modes(struct 
>>> +drm_connector
>>
>>> +*connector) {
>>
>>> +   void *edid;
>>
>>> +
>>
>>> +   int succ;
>>
>>> +   int count;
>>
>>> +
>>
>>> +   edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
>>
>>> +   if (!edid)
>>
>>> +           goto err_drm_connector_update_edid_property;
>>
>>> +
>>
>>> +   succ = ast_astdp_read_edid(connector->dev, edid);
>>
>>> +   if (succ < 0)
>>
>>> +           goto err_kfree;
>>
>>> +
>>
>>> +   drm_connector_update_edid_property(connector, edid);
>>
>>> +   count = drm_add_edid_modes(connector, edid);
>>
>>> +   kfree(edid);
>>
>>> +
>>
>>> +   return count;
>>
>>> +
>>
>>> +err_kfree:
>>
>>> +   kfree(edid);
>>
>>> +err_drm_connector_update_edid_property:
>>
>>> +   drm_connector_update_edid_property(connector, NULL);
>>
>>> +   return 0;
>>
>>> +}
>>
>>> +
>>
>>> +static const struct drm_connector_helper_funcs 
>>> +ast_astdp_connector_helper_funcs = {
>>
>>> +   .get_modes = ast_astdp_connector_helper_get_modes,
>>
>>> +};
>>
>>> +
>>
>>> +static const struct drm_connector_funcs ast_astdp_connector_funcs = 
>>> +{
>>
>>> +   .reset = drm_atomic_helper_connector_reset,
>>
>>> +   .fill_modes = drm_helper_probe_single_connector_modes,
>>
>>> +   .destroy = drm_connector_cleanup,
>>
>>> +   .atomic_duplicate_state =
>>> +drm_atomic_helper_connector_duplicate_state,
>>
>>> +   .atomic_destroy_state =
>>> +drm_atomic_helper_connector_destroy_state,
>>
>>> +};
>>
>>> +
>>
>>> +static int ast_astdp_connector_init(struct drm_device *dev, struct
>>
>>> +drm_connector *connector) {
>>
>>> +   int ret;
>>
>>> +
>>
>>> +   ret = drm_connector_init(dev, connector, 
>>> +&ast_astdp_connector_funcs,
>>
>>> +                           DRM_MODE_CONNECTOR_DisplayPort);
>>
>>> +   if (ret)
>>
>>> +           return ret;
>>
>>> +
>>
>>> +   drm_connector_helper_add(connector,
>>
>>> +&ast_astdp_connector_helper_funcs);
>>
>>> +
>>
>>> +   connector->interlace_allowed = 0;
>>
>>> +   connector->doublescan_allowed = 0;
>>
>>> +
>>
>>> +   connector->polled = DRM_CONNECTOR_POLL_CONNECT;
>>
>>> +
>>
>>> +   return 0;
>>
>>> +}
>>
>>> +
>>
>>> +static int ast_astdp_output_init(struct ast_private *ast) {
>>
>>> +   struct drm_device *dev = &ast->base;
>>
>>> +   struct drm_crtc *crtc = &ast->crtc;
>>
>>> +   struct drm_encoder *encoder = &ast->output.astdp.encoder;
>>
>>> +   struct drm_connector *connector = &ast->output.astdp.connector;
>>
>>> +   int ret;
>>
>>> +
>>
>>> +   ret = drm_simple_encoder_init(dev, encoder, 
>>> +DRM_MODE_ENCODER_TMDS);
>>
>>> +   if (ret)
>>
>>> +           return ret;
>>
>>> +   encoder->possible_crtcs = drm_crtc_mask(crtc);
>>
>>> +
>>
>>> +   ret = ast_astdp_connector_init(dev, connector);
>>
>>> +   if (ret)
>>
>>> +           return ret;
>>
>>> +
>>
>>> +   ret = drm_connector_attach_encoder(connector, encoder);
>>
>>> +   if (ret)
>>
>>> +           return ret;
>>
>>> +
>>
>>> +   return 0;
>>
>>> +}
>>
>>> +
>>
>>>     /*
>>
>>>      * Mode config
>>
>>>      */
>>
>>> @@ -1563,7 +1675,8 @@ int ast_mode_config_init(struct ast_private
>>> *ast)
>>
>>>                 ast->chip == AST2200 ||
>>
>>>                 ast->chip == AST2300 ||
>>
>>>                 ast->chip == AST2400 ||
>>
>>> -        ast->chip == AST2500) {
>>
>>> +       ast->chip == AST2500 ||
>>
>>> +       ast->chip == AST2600) {
>>
>>>                     dev->mode_config.max_width = 1920;
>>
>>>                     dev->mode_config.max_height = 2048;
>>
>>>             } else {
>>
>>> @@ -1594,6 +1707,9 @@ int ast_mode_config_init(struct ast_private
>>> *ast)
>>
>>>             case AST_TX_DP501:
>>
>>>                     ret = ast_dp501_output_init(ast);
>>
>>>                     break;
>>
>>> +   case AST_TX_ASTDP:
>>
>>> +           ret = ast_astdp_output_init(ast);
>>
>>> +           break;
>>
>>>             }
>>
>>>             if (ret)
>>
>>>                     return ret;
>>
>>> diff --git a/drivers/gpu/drm/ast/ast_post.c
>>
>>> b/drivers/gpu/drm/ast/ast_post.c index b5d92f652..0aa9cf0fb 100644
>>
>>> --- a/drivers/gpu/drm/ast/ast_post.c
>>
>>> +++ b/drivers/gpu/drm/ast/ast_post.c
>>
>>> @@ -379,7 +379,9 @@ void ast_post_gpu(struct drm_device *dev)
>>
>>>             ast_enable_mmio(dev);
>>
>>>             ast_set_def_ext_reg(dev);
>>
>>>
>>
>>> -    if (ast->config_mode == ast_use_p2a) {
>>
>>> +   if (ast->chip == AST2600) {
>>
>>> +           ast_dp_launch(dev, 1);
>>
>>> +   } else if (ast->config_mode == ast_use_p2a) {
>>
>>>                     if (ast->chip == AST2500)
>>
>>>                             ast_post_chip_2500(dev);
>>
>>>                     else if (ast->chip == AST2300 || ast->chip ==
>>> AST2400)
>>
>>>
>>
>>> base-commit: c54b39a565227538c52ead2349eb17d54aadd6f7
>>
>>> --
>>
>>> 2.27.0
>>
>>>
>>
>> --
>>
>> Thomas Zimmermann
>>
>> Graphics Driver Developer
>>
>> SUSE Software Solutions Germany GmbH
>>
>> Maxfeldstr. 5, 90409 Nürnberg, Germany
>>
>> (HRB 36809, AG Nürnberg)
>>
>> Geschäftsführer: Ivo Totev
>>
> 
> --
> Thomas Zimmermann
> Graphics Driver Developer
> SUSE Software Solutions Germany GmbH
> Maxfeldstr. 5, 90409 Nürnberg, Germany (HRB 36809, AG Nürnberg)
> Geschäftsführer: Ivo Totev

--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Ivo Totev

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v4] drm/ast: Create the driver for ASPEED proprietory Display-Port
  2022-05-30  6:05                     ` Kuo-Hsiang Chou
@ 2022-06-01 10:42                       ` Thomas Zimmermann
  0 siblings, 0 replies; 21+ messages in thread
From: Thomas Zimmermann @ 2022-06-01 10:42 UTC (permalink / raw)
  To: Kuo-Hsiang Chou, dri-devel, linux-kernel
  Cc: Hungju Huang, airlied, Tommy Huang, airlied, Arc Sung, Luke Chen


[-- Attachment #1.1: Type: text/plain, Size: 47230 bytes --]

Hi

Am 30.05.22 um 08:05 schrieb Kuo-Hsiang Chou:
> Hi Thomas,
> 
> -----Original Message-----
> From: dri-devel [mailto:dri-devel-bounces@lists.freedesktop.org] On Behalf Of Kuo-Hsiang Chou
> Sent: Friday, May 13, 2022 6:39 PM
> To: Thomas Zimmermann <tzimmermann@suse.de>; dri-devel@lists.freedesktop.org; linux-kernel@vger.kernel.org
> Subject: RE: [PATCH v4] drm/ast: Create the driver for ASPEED proprietory Display-Port
> 
> Hi Thomas,
> 
> -----Original Message-----
> From: Thomas Zimmermann [mailto:tzimmermann@suse.de]
> Sent: Friday, May 13, 2022 6:21 PM
> To: Kuo-Hsiang Chou <kuohsiang_chou@aspeedtech.com>; dri-devel@lists.freedesktop.org; linux-kernel@vger.kernel.org
> Subject: Re: [PATCH v4] drm/ast: Create the driver for ASPEED proprietory Display-Port
> 
> 
> Hi
> 
> Am 13.05.22 um 11:07 schrieb Kuo-Hsiang Chou:
>>
>>
>> -----Original Message-----
>> From: Thomas Zimmermann [mailto:tzimmermann@suse.de]
>> Sent: Tuesday, May 10, 2022 6:56 PM
>> To: Kuo-Hsiang Chou <kuohsiang_chou@aspeedtech.com>;
>> dri-devel@lists.freedesktop.org; linux-kernel@vger.kernel.org
>> Subject: Re: [PATCH v4] drm/ast: Create the driver for ASPEED
>> proprietory Display-Port
>>
>> Hi
>>
>> Am 04.05.22 um 10:49 schrieb Kuo-Hsiang Chou:
>>> Hi Thomas,
>>>
>>> Thanks for your efforts to review this patch.
>>>
>>> Now, I observe a change that after DP unplugged and then the system
>>> is unable to get EDID from D-sub connecting.
>>>
>>> The reason seems that TXs are merged into union structure in
>>> /drivers/gpu/drm/ast/ast_drv.h
>>>     (a59b026419f33040d7d28b8e3b1cea681b9ce7a7
>>> <https://cgit.freedesktop.org/drm/drm-misc/commit/?id=a59b026419f3304
>>> 0
>>> d7d28b8e3b1cea681b9ce7a7>)
>>
>> I have posted a patch that enables multiple parallel outputs. See
>>
>>    
>> <https://lore.kernel.org/dri-devel/20220510105010.20712-1-tzimmermann@
>> suse.de/T/#u>
>>
>> If you have the time, I'd appreciate if you could test it.
>>
>> Hi Thomas,
>> First, thanks for your efforts on this patch of " enables multiple parallel outputs ".
>> But it doesn't work. There is still NO EDID got from D-sub after DP unplugged.
>>
>> Base on your patch, I am trying to find out the solution also.
>> Final, thanks for your help again!
> 
> Let's try to find a solution. I might be able to come up with something if I have enough information.
> 
> How are these outputs connected to each each other?
> 1. DP and D-sub both connected: it is correct to get EDID and monitor type is correctly shown on display setting. Resolution is up to 1920*1200.
> 2. DP unplugged and only D-sub connected: Unknown Display is shown on display setting. Only 800*600 and 1024*768 are available for Resolution.
> 
> They are both served by the same CRTC. Can they be used at the same time?
> No, 2 different monitors are connected at same time.
> One is connected by D-sub and another is connected by DP connecting.
> 
> Are they mutually exclusive?
> Yes, If DP and D-sub are all connecting, DP's EDID is first priority for Display setting.
> When DP unplugged, EDID got from D-sub are used for Display setting.
> 
> Now, I try to add the codes of ast_vga_connector_helper_get_modes() into ast_astdp_connector_helper_get_modes().

That's not allowed in DRM. If there are two different connectors, there 
also need to be two different data structures in the driver.  Possible 
dependencies among these connectors have to be modeled in the 
atomic_check and atomic_flush functions.

> The result is failed.
> Anyway, I will continue to try and test the feature next Monday.
> Thanks for your great help!
> 
> Hi Thomas,
> Your patch is workable to switch resolution on Single Display option of Display setting.
> 
> And I test resolution switching on Single Display between ASTDP and VGA.
> Yes, the left-top number indicates the current resolution decided by ASTDP or VGA.
> 
> I also try to change resolution on Mirror and Join Display option.
> But there is on Apply button shown in the right-top corner of Display setting.

That's hard to say for me without testing.  I meanwhile posted a 
patchset to further improve mode-detection in ast. [1] Even hot-plugging 
of the conenctor cables should now be supported. Maybe it helps a bit.

Best regards
Thomas

[1] 
https://lore.kernel.org/dri-devel/fc6f7963-5abf-bf53-b671-a4d10bb68d10@suse.de/T/#t

> 
> Thanks for your help!
> Regards,
> 	Kuo-Hsiang Chou
> 
> Regards,
> 	Kuo-Hsiang Chou
> 
> Best regards
> Thomas
> 
>>
>> Regards,
>> 	Kuo-Hsiang Chou
>>
>> Best regards
>> Thomas
>>
>>>
>>> Another, do you need the ast2600 EVB to ease verification on "drm/ast" ?
>>>
>>> Regards,
>>>
>>>            Kuo-Hsiang Chou
>>>
>>> -----Original Message-----
>>> From: Thomas Zimmermann [mailto:tzimmermann@suse.de]
>>> Sent: Wednesday, May 04, 2022 3:28 PM
>>> To: Kuo-Hsiang Chou <kuohsiang_chou@aspeedtech.com>;
>>> dri-devel@lists.freedesktop.org; linux-kernel@vger.kernel.org
>>> Subject: Re: [PATCH v4] drm/ast: Create the driver for ASPEED
>>> proprietory Display-Port
>>>
>>> Hi
>>>
>>> Am 28.04.22 um 09:56 schrieb KuoHsiang Chou:
>>>
>>>> V1:
>>>
>>>> 1. The MCU FW controling ASPEED DP is loaded by BMC boot loader.
>>>
>>>> 2. Driver starts after CR[3:1] == 111b that indicates Tx is ASTDP,
>>>
>>>>        and CRD1[5] has been asserted by BMVC boot loader.
>>>
>>>> 3. EDID is prioritized by DP monitor.
>>>
>>>> 4. DP's EDID has high priority to decide resolution supporting.
>>>
>>>>
>>>
>>>> V2:
>>>
>>>> Modules description:
>>>
>>>> 1. ASTDP (ASPEED DisplayPort) is controlled by dedicated
>>>
>>>>        AST-MCU (ASPEED propriatary MCU).
>>>
>>>> 2. MCU is looping in charged of HPD, Read EDID, Link Training with
>>>
>>>>        DP sink.
>>>
>>>> 3. ASTDP and AST-MUC reside in BMC (Baseboard Management controller)
>>>
>>>>        addressing-space.
>>>
>>>> 4. ASPEED DRM driver requests MCU to get HPD and EDID by
>>>> CR-scratched
>>>
>>>>        register.
>>>
>>>>
>>>
>>>> Booting sequence:
>>>
>>>> 1. Check if TX is ASTDP                                        //
>>>> ast_dp_launch()
>>>
>>>> 2. Check if DP-MCU FW has loaded
>>>> // ast_dp_launch()
>>>
>>>> 3. Read EDID                                        //
>>>> ast_dp_read_edid()
>>>
>>>> 4. Resolution switch                                     //
>>>> ast_dp_SetOutput()
>>>
>>>>
>>>
>>>> V3:
>>>
>>>> 1. Remove unneeded semicolon.
>>>
>>>> 2. Apply to git://anongit.freedesktop.org/drm/drm, instead of
>>>
>>>>        git://anongit.freedesktop.org/drm/drm-misc
>>>
>>>> 3. Resolve auto build test WARNINGs on V1 patch.
>>>
>>>>
>>>
>>>> V4:
>>>
>>>> 1. Sync code-base with kernel 5.17_rc6 2. Remove the define of
>>>
>>>> DPControlPower, because DP chips need to be
>>>
>>>>        powered on to be used.
>>>
>>>> 3. Remove the switches of PHY and Display from EDID procedure.
>>>
>>>> 4. Revise increaing delay to fixed delay, because this version
>>>> kernel
>>>
>>>>        doesn't detect minitor consistenntly.
>>>
>>>> 5. Create clean-up code used for reset of power state on errors with
>>>
>>>>        -EIO manner.
>>>
>>>> 6. Revise the DP detection by TX type and its DP-FW status during
>>>
>>>>        booting and resume.
>>>
>>>> 7. Correct the CamelCase Style.
>>>
>>>> 8. Use register reading while needing, and remove to hold full
>>>
>>>>        register.
>>>
>>>> 9. Instead of 'u8', revise to 'bool' on swwitch of PHY and video.
>>>
>>>> 10.Correct typo
>>>
>>>> 11.Remove the duplicated copy of TX definition.
>>>
>>>> 12.Use EDID_LENGTH as the constant of 128.
>>>
>>>>
>>>
>>>> Signed-off-by: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com
>>>> <mailto:kuohsiang_chou@aspeedtech.com>>
>>>
>>> Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de
>>> <mailto:tzimmermann@suse.de>>
>>>
>>> I've meanwhile added your patch to drm-misc-next. It should show up
>>> in one of the next kernel releases.  Thanks a lot.
>>>
>>> Best regards
>>>
>>> Thomas
>>>
>>>> ---
>>>
>>>>      drivers/gpu/drm/ast/Makefile   |   2 +-
>>>
>>>>      drivers/gpu/drm/ast/ast_dp.c   | 282
>>>> +++++++++++++++++++++++++++++++++
>>>
>>>>      drivers/gpu/drm/ast/ast_drv.h  | 115 ++++++++++++++
>>>
>>>>      drivers/gpu/drm/ast/ast_main.c |   5 +-
>>>
>>>>      drivers/gpu/drm/ast/ast_mode.c | 124 ++++++++++++++-
>>>
>>>>      drivers/gpu/drm/ast/ast_post.c |   4 +-
>>>
>>>>      6 files changed, 524 insertions(+), 8 deletions(-)
>>>
>>>>      create mode 100644 drivers/gpu/drm/ast/ast_dp.c
>>>
>>>>
>>>
>>>> diff --git a/drivers/gpu/drm/ast/Makefile
>>>
>>>> b/drivers/gpu/drm/ast/Makefile index 21f71160b..5a53ce51f 100644
>>>
>>>> --- a/drivers/gpu/drm/ast/Makefile
>>>
>>>> +++ b/drivers/gpu/drm/ast/Makefile
>>>
>>>> @@ -3,6 +3,6 @@
>>>
>>>>      # Makefile for the drm device driver.  This driver provides
>>>> support for the
>>>
>>>>      # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
>>>
>>>>
>>>
>>>> -ast-y := ast_drv.o ast_i2c.o ast_main.o ast_mm.o ast_mode.o
>>>
>>>> ast_post.o ast_dp501.o
>>>
>>>> +ast-y := ast_drv.o ast_i2c.o ast_main.o ast_mm.o ast_mode.o
>>>
>>>> +ast_post.o ast_dp501.o ast_dp.o
>>>
>>>>
>>>
>>>>      obj-$(CONFIG_DRM_AST) := ast.o
>>>
>>>> diff --git a/drivers/gpu/drm/ast/ast_dp.c
>>>
>>>> b/drivers/gpu/drm/ast/ast_dp.c new file mode 100644 index
>>>
>>>> 000000000..4551bc8a3
>>>
>>>> --- /dev/null
>>>
>>>> +++ b/drivers/gpu/drm/ast/ast_dp.c
>>>
>>>> @@ -0,0 +1,282 @@
>>>
>>>> +// SPDX-License-Identifier: GPL-2.0
>>>
>>>> +// Copyright (c) 2021, ASPEED Technology Inc.
>>>
>>>> +// Authors: KuoHsiang Chou <kuohsiang_chou@aspeedtech.com
>>>> +<mailto:kuohsiang_chou@aspeedtech.com>>
>>>
>>>> +
>>>
>>>> +#include <linux/firmware.h>
>>>
>>>> +#include <linux/delay.h>
>>>
>>>> +#include <drm/drm_print.h>
>>>
>>>> +#include "ast_drv.h"
>>>
>>>> +
>>>
>>>> +int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata) {
>>>
>>>> +   struct ast_private *ast = to_ast_private(dev);
>>>
>>>> +   u8 i = 0, j = 0;
>>>
>>>> +
>>>
>>>> +   /*
>>>
>>>> +   * CRD1[b5]: DP MCU FW is executing
>>>
>>>> +   * CRDC[b0]: DP link success
>>>
>>>> +   * CRDF[b0]: DP HPD
>>>
>>>> +   * CRE5[b0]: Host reading EDID process is done
>>>
>>>> +   */
>>>
>>>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1,
>>>> +ASTDP_MCU_FW_EXECUTING) &&
>>>
>>>> +           ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC,
>>>> +ASTDP_LINK_SUCCESS) &&
>>>
>>>> +           ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF,
>>>> +ASTDP_HPD) &&
>>>
>>>> +           ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
>>>
>>>> +
>>>> +ASTDP_HOST_EDID_READ_DONE_MASK))) {
>>>
>>>> +           goto err_astdp_edid_not_ready;
>>>
>>>> +   }
>>>
>>>> +
>>>
>>>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8)
>>>> +~ASTDP_HOST_EDID_READ_DONE_MASK,
>>>
>>>> +                                                   0x00);
>>>
>>>> +
>>>
>>>> +   for (i = 0; i < 32; i++) {
>>>
>>>> +           /*
>>>
>>>> +           * CRE4[7:0]: Read-Pointer for EDID (Unit: 4bytes); valid
>>>> +range: 0~64
>>>
>>>> +           */
>>>
>>>> +           ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE4,
>>>
>>>> +                                   (u8)
>>>> +~ASTDP_EDID_READ_POINTER_MASK, (u8) i);
>>>
>>>> +           j = 0;
>>>
>>>> +
>>>
>>>> +           /*
>>>
>>>> +           * CRD7[b0]: valid flag for EDID
>>>
>>>> +           * CRD6[b0]: mirror read pointer for EDID
>>>
>>>> +           */
>>>
>>>> +           while ((ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT,
>>>> +0xD7,
>>>
>>>> +                           ASTDP_EDID_VALID_FLAG_MASK) != 0x01) ||
>>>
>>>> +                   (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT,
>>>> +0xD6,
>>>
>>>> +
>>>> +ASTDP_EDID_READ_POINTER_MASK) != i)) {
>>>
>>>> +                   /*
>>>
>>>> +                   * Delay are getting longer with each retry.
>>>
>>>> +                   * 1. The Delays are often 2 loops when users request "Display Settings"
>>>
>>>> +                   *      of right-click of mouse.
>>>
>>>> +                   * 2. The Delays are often longer a lot when system resume from S3/S4.
>>>
>>>> +                   */
>>>
>>>> +                   mdelay(j+1);
>>>
>>>> +
>>>
>>>> +                   if (!(ast_get_index_reg_mask(ast,
>>>> +AST_IO_CRTC_PORT, 0xD1,
>>>
>>>> +
>>>> +ASTDP_MCU_FW_EXECUTING) &&
>>>
>>>> +                           ast_get_index_reg_mask(ast,
>>>> +AST_IO_CRTC_PORT, 0xDC,
>>>
>>>> +
>>>> +ASTDP_LINK_SUCCESS) &&
>>>
>>>> +                           ast_get_index_reg_mask(ast,
>>>> +AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD))) {
>>>
>>>> +                           goto err_astdp_jump_out_loop_of_edid;
>>>
>>>> +                   }
>>>
>>>> +
>>>
>>>> +                   j++;
>>>
>>>> +                   if (j > 200)
>>>
>>>> +                           goto err_astdp_jump_out_loop_of_edid;
>>>
>>>> +           }
>>>
>>>> +
>>>
>>>> +           *(ediddata) = ast_get_index_reg_mask(ast,
>>>> +AST_IO_CRTC_PORT,
>>>
>>>> +                                                   0xD8,
>>>> +ASTDP_EDID_READ_DATA_MASK);
>>>
>>>> +           *(ediddata + 1) = ast_get_index_reg_mask(ast,
>>>> +AST_IO_CRTC_PORT, 0xD9,
>>>
>>>> +
>>>> +ASTDP_EDID_READ_DATA_MASK);
>>>
>>>> +           *(ediddata + 2) = ast_get_index_reg_mask(ast,
>>>> +AST_IO_CRTC_PORT, 0xDA,
>>>
>>>> +
>>>> +ASTDP_EDID_READ_DATA_MASK);
>>>
>>>> +           *(ediddata + 3) = ast_get_index_reg_mask(ast,
>>>> +AST_IO_CRTC_PORT, 0xDB,
>>>
>>>> +
>>>> +ASTDP_EDID_READ_DATA_MASK);
>>>
>>>> +
>>>
>>>> +           if (i == 31) {
>>>
>>>> +                   /*
>>>
>>>> +                   * For 128-bytes EDID_1.3,
>>>
>>>> +                   * 1. Add the value of Bytes-126 to Bytes-127.
>>>
>>>> +                   *            The Bytes-127 is Checksum. Sum of
>>>> +all 128bytes should
>>>
>>>> +                   *            equal 0    (mod 256).
>>>
>>>> +                   * 2. Modify Bytes-126 to be 0.
>>>
>>>> +                   *            The Bytes-126 indicates the Number
>>>> +of extensions to
>>>
>>>> +                   *            follow. 0 represents noextensions.
>>>
>>>> +                   */
>>>
>>>> +                   *(ediddata + 3) = *(ediddata + 3) + *(ediddata +
>>>> +2);
>>>
>>>> +                   *(ediddata + 2) = 0;
>>>
>>>> +           }
>>>
>>>> +
>>>
>>>> +           ediddata += 4;
>>>
>>>> +   }
>>>
>>>> +
>>>
>>>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8)
>>>> +~ASTDP_HOST_EDID_READ_DONE_MASK,
>>>
>>>> +
>>>> +ASTDP_HOST_EDID_READ_DONE);
>>>
>>>> +
>>>
>>>> +   return 0;
>>>
>>>> +
>>>
>>>> +err_astdp_jump_out_loop_of_edid:
>>>
>>>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
>>>
>>>> +                                                   (u8)
>>>> +~ASTDP_HOST_EDID_READ_DONE_MASK,
>>>
>>>> +
>>>> +ASTDP_HOST_EDID_READ_DONE);
>>>
>>>> +   return (~(j+256) + 1);
>>>
>>>> +
>>>
>>>> +err_astdp_edid_not_ready:
>>>
>>>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1,
>>>> +ASTDP_MCU_FW_EXECUTING)))
>>>
>>>> +           return (~0xD1 + 1);
>>>
>>>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC,
>>>> +ASTDP_LINK_SUCCESS)))
>>>
>>>> +           return (~0xDC + 1);
>>>
>>>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF,
>>>> +ASTDP_HPD)))
>>>
>>>> +           return (~0xDF + 1);
>>>
>>>> +   if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
>>>> +ASTDP_HOST_EDID_READ_DONE_MASK)))
>>>
>>>> +           return (~0xE5 + 1);
>>>
>>>> +
>>>
>>>> +   return      0;
>>>
>>>> +}
>>>
>>>> +
>>>
>>>> +/*
>>>
>>>> + * Launch Aspeed DP
>>>
>>>> + */
>>>
>>>> +void ast_dp_launch(struct drm_device *dev, u8 bPower) {
>>>
>>>> +   u32 i = 0, j = 0, WaitCount = 1;
>>>
>>>> +   u8 bDPTX = 0;
>>>
>>>> +   u8 bDPExecute = 1;
>>>
>>>> +
>>>
>>>> +   struct ast_private *ast = to_ast_private(dev);
>>>
>>>> +   // S3 come back, need more time to wait BMC ready.
>>>
>>>> +   if (bPower)
>>>
>>>> +           WaitCount = 300;
>>>
>>>> +
>>>
>>>> +
>>>
>>>> +   // Wait total count by different condition.
>>>
>>>> +   for (j = 0; j < WaitCount; j++) {
>>>
>>>> +           bDPTX = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT,
>>>> +0xD1,
>>>
>>>> +TX_TYPE_MASK);
>>>
>>>> +
>>>
>>>> +           if (bDPTX)
>>>
>>>> +                   break;
>>>
>>>> +
>>>
>>>> +           msleep(100);
>>>
>>>> +   }
>>>
>>>> +
>>>
>>>> +   // 0xE : ASTDP with DPMCU FW handling
>>>
>>>> +   if (bDPTX == ASTDP_DPMCU_TX) {
>>>
>>>> +           // Wait one second then timeout.
>>>
>>>> +           i = 0;
>>>
>>>> +
>>>
>>>> +           while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT,
>>>> +0xD1, COPROCESSOR_LAUNCH) !=
>>>
>>>> +                   COPROCESSOR_LAUNCH) {
>>>
>>>> +                   i++;
>>>
>>>> +                   // wait 100 ms
>>>
>>>> +                   msleep(100);
>>>
>>>> +
>>>
>>>> +                   if (i >= 10) {
>>>
>>>> +                           // DP would not be ready.
>>>
>>>> +                           bDPExecute = 0;
>>>
>>>> +                           break;
>>>
>>>> +                   }
>>>
>>>> +           }
>>>
>>>> +
>>>
>>>> +           if (bDPExecute)
>>>
>>>> +                   ast->tx_chip_type = AST_TX_ASTDP;
>>>
>>>> +
>>>
>>>> +           ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
>>>
>>>> +                                                   (u8)
>>>> +~ASTDP_HOST_EDID_READ_DONE_MASK,
>>>
>>>> +
>>>> +ASTDP_HOST_EDID_READ_DONE);
>>>
>>>> +   } else
>>>
>>>> +           ast->tx_chip_type = AST_TX_NONE;
>>>
>>>> +}
>>>
>>>> +
>>>
>>>> +
>>>
>>>> +
>>>
>>>> +void ast_dp_power_on_off(struct drm_device *dev, bool on) {
>>>
>>>> +   struct ast_private *ast = to_ast_private(dev);
>>>
>>>> +   // Read and Turn off DP PHY sleep
>>>
>>>> +   u8 bE3 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3,
>>>
>>>> +AST_DP_VIDEO_ENABLE);
>>>
>>>> +
>>>
>>>> +   // Turn on DP PHY sleep
>>>
>>>> +   if (!on)
>>>
>>>> +           bE3 |= AST_DP_PHY_SLEEP;
>>>
>>>> +
>>>
>>>> +   // DP Power on/off
>>>
>>>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, (u8)
>>>
>>>> +~AST_DP_PHY_SLEEP, bE3); }
>>>
>>>> +
>>>
>>>> +
>>>
>>>> +
>>>
>>>> +void ast_dp_set_on_off(struct drm_device *dev, bool on) {
>>>
>>>> +   struct ast_private *ast = to_ast_private(dev);
>>>
>>>> +   u8 video_on_off = on;
>>>
>>>> +
>>>
>>>> +   // Video On/Off
>>>
>>>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE3, (u8)
>>>
>>>> +~AST_DP_VIDEO_ENABLE, on);
>>>
>>>> +
>>>
>>>> +   // If DP plug in and link successful then check video on / off
>>>> +status
>>>
>>>> +   if (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC,
>>>> +ASTDP_LINK_SUCCESS) &&
>>>
>>>> +           ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF,
>>>> +ASTDP_HPD)) {
>>>
>>>> +           video_on_off <<= 4;
>>>
>>>> +           while (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT,
>>>> +0xDF,
>>>
>>>> +
>>>> +ASTDP_MIRROR_VIDEO_ENABLE) != video_on_off) {
>>>
>>>> +                   // wait 1 ms
>>>
>>>> +                   mdelay(1);
>>>
>>>> +           }
>>>
>>>> +   }
>>>
>>>> +}
>>>
>>>> +
>>>
>>>> +void ast_dp_set_mode(struct drm_crtc *crtc, struct
>>>
>>>> +ast_vbios_mode_info *vbios_mode) {
>>>
>>>> +   struct ast_private *ast = to_ast_private(crtc->dev);
>>>
>>>> +
>>>
>>>> +   u32 ulRefreshRateIndex;
>>>
>>>> +   u8 ModeIdx;
>>>
>>>> +
>>>
>>>> +   ulRefreshRateIndex = vbios_mode->enh_table->refresh_rate_index -
>>>> +1;
>>>
>>>> +
>>>
>>>> +   switch (crtc->mode.crtc_hdisplay) {
>>>
>>>> +   case 320:
>>>
>>>> +           ModeIdx = ASTDP_320x240_60;
>>>
>>>> +           break;
>>>
>>>> +   case 400:
>>>
>>>> +           ModeIdx = ASTDP_400x300_60;
>>>
>>>> +           break;
>>>
>>>> +   case 512:
>>>
>>>> +           ModeIdx = ASTDP_512x384_60;
>>>
>>>> +           break;
>>>
>>>> +   case 640:
>>>
>>>> +           ModeIdx = (ASTDP_640x480_60 + (u8) ulRefreshRateIndex);
>>>
>>>> +           break;
>>>
>>>> +   case 800:
>>>
>>>> +           ModeIdx = (ASTDP_800x600_56 + (u8) ulRefreshRateIndex);
>>>
>>>> +           break;
>>>
>>>> +   case 1024:
>>>
>>>> +           ModeIdx = (ASTDP_1024x768_60 + (u8) ulRefreshRateIndex);
>>>
>>>> +           break;
>>>
>>>> +   case 1152:
>>>
>>>> +           ModeIdx = ASTDP_1152x864_75;
>>>
>>>> +           break;
>>>
>>>> +   case 1280:
>>>
>>>> +           if (crtc->mode.crtc_vdisplay == 800)
>>>
>>>> +                   ModeIdx = (ASTDP_1280x800_60_RB - (u8)
>>>> +ulRefreshRateIndex);
>>>
>>>> +           else          // 1024
>>>
>>>> +                   ModeIdx = (ASTDP_1280x1024_60 + (u8)
>>>> +ulRefreshRateIndex);
>>>
>>>> +           break;
>>>
>>>> +   case 1360:
>>>
>>>> +   case 1366:
>>>
>>>> +           ModeIdx = ASTDP_1366x768_60;
>>>
>>>> +           break;
>>>
>>>> +   case 1440:
>>>
>>>> +           ModeIdx = (ASTDP_1440x900_60_RB - (u8)
>>>> +ulRefreshRateIndex);
>>>
>>>> +           break;
>>>
>>>> +   case 1600:
>>>
>>>> +           if (crtc->mode.crtc_vdisplay == 900)
>>>
>>>> +                   ModeIdx = (ASTDP_1600x900_60_RB - (u8)
>>>> +ulRefreshRateIndex);
>>>
>>>> +           else          //1200
>>>
>>>> +                   ModeIdx = ASTDP_1600x1200_60;
>>>
>>>> +           break;
>>>
>>>> +   case 1680:
>>>
>>>> +           ModeIdx = (ASTDP_1680x1050_60_RB - (u8)
>>>> +ulRefreshRateIndex);
>>>
>>>> +           break;
>>>
>>>> +   case 1920:
>>>
>>>> +           if (crtc->mode.crtc_vdisplay == 1080)
>>>
>>>> +                   ModeIdx = ASTDP_1920x1080_60;
>>>
>>>> +           else          //1200
>>>
>>>> +                   ModeIdx = ASTDP_1920x1200_60;
>>>
>>>> +           break;
>>>
>>>> +   default:
>>>
>>>> +           return;
>>>
>>>> +   }
>>>
>>>> +
>>>
>>>> +   /*
>>>
>>>> +   * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp)
>>>
>>>> +   * CRE1[7:0]: MISC1 (default: 0x00)
>>>
>>>> +   * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50)
>>>
>>>> +   */
>>>
>>>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE0, (u8)
>>>> +~ASTDP_CLEAR_MASK,
>>>
>>>> +                           ASTDP_MISC0_24bpp);
>>>
>>>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE1, (u8)
>>>> +~ASTDP_CLEAR_MASK, ASTDP_MISC1);
>>>
>>>> +   ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE2, (u8)
>>>
>>>> +~ASTDP_CLEAR_MASK, ModeIdx); }
>>>
>>>> diff --git a/drivers/gpu/drm/ast/ast_drv.h
>>>
>>>> b/drivers/gpu/drm/ast/ast_drv.h index a19315b2f..ff1ae314b 100644
>>>
>>>> --- a/drivers/gpu/drm/ast/ast_drv.h
>>>
>>>> +++ b/drivers/gpu/drm/ast/ast_drv.h
>>>
>>>> @@ -70,6 +70,7 @@ enum ast_tx_chip {
>>>
>>>>              AST_TX_NONE,
>>>
>>>>              AST_TX_SIL164,
>>>
>>>>              AST_TX_DP501,
>>>
>>>> +   AST_TX_ASTDP,
>>>
>>>>      };
>>>
>>>>
>>>
>>>>      #define AST_DRAM_512Mx16 0
>>>
>>>> @@ -184,6 +185,10 @@ struct ast_private {
>>>
>>>>                              struct drm_encoder encoder;
>>>
>>>>                              struct drm_connector connector;
>>>
>>>>                      } dp501;
>>>
>>>> +           struct {
>>>
>>>> +                   struct drm_encoder encoder;
>>>
>>>> +                   struct drm_connector connector;
>>>
>>>> +           } astdp;
>>>
>>>>              } output;
>>>
>>>>
>>>
>>>>              bool support_wide_screen;
>>>
>>>> @@ -357,10 +362,113 @@ int ast_mode_config_init(struct ast_private
>>>> *ast);
>>>
>>>>      #define AST_DP501_EDID_DATA    0xf020
>>>
>>>>
>>>
>>>>      /* Define for Soc scratched reg */
>>>
>>>> +#define COPROCESSOR_LAUNCH                     BIT(5)
>>>
>>>> +
>>>
>>>> +/*
>>>
>>>> + * Display Transmitter Type:
>>>
>>>> + */
>>>
>>>> +#define TX_TYPE_MASK                            GENMASK(3, 1)
>>>
>>>> +#define NO_TX                                            (0 << 1)
>>>
>>>> +#define ITE66121_VBIOS_TX                     (1 << 1)
>>>
>>>> +#define SI164_VBIOS_TX                           (2 << 1)
>>>
>>>> +#define CH7003_VBIOS_TX                       (3 << 1)
>>>
>>>> +#define DP501_VBIOS_TX                         (4 << 1)
>>>
>>>> +#define ANX9807_VBIOS_TX                     (5 << 1)
>>>
>>>> +#define TX_FW_EMBEDDED_FW_TX                (6 << 1)
>>>
>>>> +#define ASTDP_DPMCU_TX                               (7 << 1)
>>>
>>>> +
>>>
>>>>      #define AST_VRAM_INIT_STATUS_MASK       GENMASK(7, 6)
>>>
>>>>      //#define AST_VRAM_INIT_BY_BMC             BIT(7)
>>>
>>>>      //#define AST_VRAM_INIT_READY                BIT(6)
>>>
>>>>
>>>
>>>> +/* Define for Soc scratched reg used on ASTDP */
>>>
>>>> +#define AST_DP_PHY_SLEEP                     BIT(4)
>>>
>>>> +#define AST_DP_VIDEO_ENABLE              BIT(0)
>>>
>>>> +
>>>
>>>> +#define AST_DP_POWER_ON                    true
>>>
>>>> +#define AST_DP_POWER_OFF                   false
>>>
>>>> +
>>>
>>>> +/*
>>>
>>>> + * CRD1[b5]: DP MCU FW is executing
>>>
>>>> + * CRDC[b0]: DP link success
>>>
>>>> + * CRDF[b0]: DP HPD
>>>
>>>> + * CRE5[b0]: Host reading EDID process is done  */
>>>
>>>> +#define ASTDP_MCU_FW_EXECUTING                     BIT(5)
>>>
>>>> +#define ASTDP_LINK_SUCCESS                          BIT(0)
>>>
>>>> +#define ASTDP_HPD                                          BIT(0)
>>>
>>>> +#define ASTDP_HOST_EDID_READ_DONE                BIT(0)
>>>
>>>> +#define ASTDP_HOST_EDID_READ_DONE_MASK    GENMASK(0, 0)
>>>
>>>> +
>>>
>>>> +/*
>>>
>>>> + * CRB8[b1]: Enable VSYNC off
>>>
>>>> + * CRB8[b0]: Enable HSYNC off
>>>
>>>> + */
>>>
>>>> +#define AST_DPMS_VSYNC_OFF                               BIT(1)
>>>
>>>> +#define AST_DPMS_HSYNC_OFF                               BIT(0)
>>>
>>>> +
>>>
>>>> +/*
>>>
>>>> + * CRDF[b4]: Mirror of AST_DP_VIDEO_ENABLE
>>>
>>>> + * Precondition:  A. ~AST_DP_PHY_SLEEP  &&
>>>
>>>> + *                        B. DP_HPD &&
>>>
>>>> + *                        C. DP_LINK_SUCCESS
>>>
>>>> + */
>>>
>>>> +#define ASTDP_MIRROR_VIDEO_ENABLE                BIT(4)
>>>
>>>> +
>>>
>>>> +#define ASTDP_EDID_READ_POINTER_MASK  GENMASK(7, 0)
>>>
>>>> +#define ASTDP_EDID_VALID_FLAG_MASK                GENMASK(0, 0)
>>>
>>>> +#define ASTDP_EDID_READ_DATA_MASK        GENMASK(7, 0)
>>>
>>>> +
>>>
>>>> +/*
>>>
>>>> + * ASTDP setmode registers:
>>>
>>>> + * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp)
>>>
>>>> + * CRE1[7:0]: MISC1 (default: 0x00)
>>>
>>>> + * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50)  */
>>>
>>>> +#define ASTDP_MISC0_24bpp                   BIT(5)
>>>
>>>> +#define ASTDP_MISC1                               0
>>>
>>>> +#define ASTDP_CLEAR_MASK                   GENMASK(7, 0)
>>>
>>>> +
>>>
>>>> +/*
>>>
>>>> + * ASTDP resoultion table:
>>>
>>>> + * EX:  ASTDP_A_B_C:
>>>
>>>> + *                A: Resolution
>>>
>>>> + *                B: Refresh Rate
>>>
>>>> + *                C: Misc information, such as CVT, Reduce Blanked
>>>
>>>> + */
>>>
>>>> +#define ASTDP_640x480_60              0x00
>>>
>>>> +#define ASTDP_640x480_72              0x01
>>>
>>>> +#define ASTDP_640x480_75              0x02
>>>
>>>> +#define ASTDP_640x480_85              0x03
>>>
>>>> +#define ASTDP_800x600_56              0x04
>>>
>>>> +#define ASTDP_800x600_60              0x05
>>>
>>>> +#define ASTDP_800x600_72              0x06
>>>
>>>> +#define ASTDP_800x600_75              0x07
>>>
>>>> +#define ASTDP_800x600_85              0x08
>>>
>>>> +#define ASTDP_1024x768_60            0x09
>>>
>>>> +#define ASTDP_1024x768_70            0x0A
>>>
>>>> +#define ASTDP_1024x768_75            0x0B
>>>
>>>> +#define ASTDP_1024x768_85            0x0C
>>>
>>>> +#define ASTDP_1280x1024_60          0x0D
>>>
>>>> +#define ASTDP_1280x1024_75          0x0E
>>>
>>>> +#define ASTDP_1280x1024_85          0x0F
>>>
>>>> +#define ASTDP_1600x1200_60          0x10
>>>
>>>> +#define ASTDP_320x240_60              0x11
>>>
>>>> +#define ASTDP_400x300_60              0x12
>>>
>>>> +#define ASTDP_512x384_60              0x13
>>>
>>>> +#define ASTDP_1920x1200_60          0x14
>>>
>>>> +#define ASTDP_1920x1080_60          0x15
>>>
>>>> +#define ASTDP_1280x800_60            0x16
>>>
>>>> +#define ASTDP_1280x800_60_RB     0x17
>>>
>>>> +#define ASTDP_1440x900_60            0x18
>>>
>>>> +#define ASTDP_1440x900_60_RB     0x19
>>>
>>>> +#define ASTDP_1680x1050_60          0x1A
>>>
>>>> +#define ASTDP_1680x1050_60_RB   0x1B
>>>
>>>> +#define ASTDP_1600x900_60            0x1C
>>>
>>>> +#define ASTDP_1600x900_60_RB     0x1D
>>>
>>>> +#define ASTDP_1366x768_60            0x1E
>>>
>>>> +#define ASTDP_1152x864_75            0x1F
>>>
>>>> +
>>>
>>>>      int ast_mm_init(struct ast_private *ast);
>>>
>>>>
>>>
>>>>      /* ast post */
>>>
>>>> @@ -381,4 +489,11 @@ void ast_init_3rdtx(struct drm_device *dev);
>>>
>>>>      /* ast_i2c.c */
>>>
>>>>     struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev);
>>>
>>>>
>>>
>>>> +/* aspeed DP */
>>>
>>>> +int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata); void
>>>
>>>> +ast_dp_launch(struct drm_device *dev, u8 bPower); void
>>>
>>>> +ast_dp_power_on_off(struct drm_device *dev, bool no); void
>>>
>>>> +ast_dp_set_on_off(struct drm_device *dev, bool no); void
>>>
>>>> +ast_dp_set_mode(struct drm_crtc *crtc, struct ast_vbios_mode_info
>>>
>>>> +*vbios_mode);
>>>
>>>> +
>>>
>>>>      #endif
>>>
>>>> diff --git a/drivers/gpu/drm/ast/ast_main.c
>>>
>>>> b/drivers/gpu/drm/ast/ast_main.c index 22e9e2d3c..1113ee1cb 100644
>>>
>>>> --- a/drivers/gpu/drm/ast/ast_main.c
>>>
>>>> +++ b/drivers/gpu/drm/ast/ast_main.c
>>>
>>>> @@ -232,7 +232,7 @@ static int ast_detect_chip(struct drm_device
>>>> *dev, bool *need_post)
>>>
>>>>                             ast->tx_chip_type = AST_TX_SIL164;
>>>
>>>>              }
>>>
>>>>
>>>
>>>> -    if ((ast->chip == AST2300) || (ast->chip == AST2400)) {
>>>
>>>> +   if ((ast->chip == AST2300) || (ast->chip == AST2400) ||
>>>> +(ast->chip
>>>
>>>> +== AST2500)) {
>>>
>>>>                      /*
>>>
>>>>                       * On AST2300 and 2400, look the configuration
>>>> set by the SoC in
>>>
>>>>                       * the SOC scratch register #1 bits 11:8
>>>> (interestingly marked @@
>>>
>>>> -256,7 +256,8 @@ static int ast_detect_chip(struct drm_device *dev,
>>>> bool *need_post)
>>>
>>>>                      case 0x0c:
>>>
>>>>                              ast->tx_chip_type = AST_TX_DP501;
>>>
>>>>                      }
>>>
>>>> -    }
>>>
>>>> +   } else if (ast->chip == AST2600)
>>>
>>>> +           ast_dp_launch(&ast->base, 0);
>>>
>>>>
>>>
>>>>              /* Print stuff for diagnostic purposes */
>>>
>>>>              switch(ast->tx_chip_type) {
>>>
>>>> diff --git a/drivers/gpu/drm/ast/ast_mode.c
>>>
>>>> b/drivers/gpu/drm/ast/ast_mode.c index 45b56b39a..4728825b7 100644
>>>
>>>> --- a/drivers/gpu/drm/ast/ast_mode.c
>>>
>>>> +++ b/drivers/gpu/drm/ast/ast_mode.c
>>>
>>>> @@ -988,21 +988,41 @@ static int ast_cursor_plane_init(struct
>>>> ast_private *ast)
>>>
>>>>      static void ast_crtc_dpms(struct drm_crtc *crtc, int mode)
>>>
>>>>      {
>>>
>>>>              struct ast_private *ast = to_ast_private(crtc->dev);
>>>
>>>> +   u8 ch = AST_DPMS_VSYNC_OFF | AST_DPMS_HSYNC_OFF;
>>>
>>>>
>>>
>>>>              /* TODO: Maybe control display signal generation with
>>>
>>>>               *       Sync Enable (bit CR17.7).
>>>
>>>>               */
>>>
>>>>              switch (mode) {
>>>
>>>>              case DRM_MODE_DPMS_ON:
>>>
>>>> -    case DRM_MODE_DPMS_STANDBY:
>>>
>>>> -    case DRM_MODE_DPMS_SUSPEND:
>>>
>>>> +           ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT,  0x01,
>>>> +0xdf, 0);
>>>
>>>> +           ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6,
>>>> +0xfc, 0);
>>>
>>>>                      if (ast->tx_chip_type == AST_TX_DP501)
>>>
>>>>                              ast_set_dp501_video_output(crtc->dev,
>>>> 1);
>>>
>>>> +
>>>
>>>> +           if (ast->tx_chip_type == AST_TX_ASTDP) {
>>>
>>>> +                   ast_dp_power_on_off(crtc->dev, AST_DP_POWER_ON);
>>>
>>>> +                   ast_wait_for_vretrace(ast);
>>>
>>>> +                   ast_dp_set_on_off(crtc->dev, 1);
>>>
>>>> +           }
>>>
>>>> +
>>>
>>>> +           ast_crtc_load_lut(ast, crtc);
>>>
>>>>                      break;
>>>
>>>> +   case DRM_MODE_DPMS_STANDBY:
>>>
>>>> +   case DRM_MODE_DPMS_SUSPEND:
>>>
>>>>              case DRM_MODE_DPMS_OFF:
>>>
>>>> +           ch = mode;
>>>
>>>>                      if (ast->tx_chip_type == AST_TX_DP501)
>>>
>>>>                              ast_set_dp501_video_output(crtc->dev,
>>>> 0);
>>>
>>>>                      break;
>>>
>>>> +
>>>
>>>> +           if (ast->tx_chip_type == AST_TX_ASTDP) {
>>>
>>>> +                   ast_dp_set_on_off(crtc->dev, 0);
>>>
>>>> +                   ast_dp_power_on_off(crtc->dev,
>>>> +AST_DP_POWER_OFF);
>>>
>>>> +           }
>>>
>>>> +
>>>
>>>> +           ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT,  0x01,
>>>> +0xdf, 0x20);
>>>
>>>> +           ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6,
>>>> +0xfc, ch);
>>>
>>>>              }
>>>
>>>>      }
>>>
>>>>
>>>
>>>> @@ -1027,7 +1047,7 @@ ast_crtc_helper_mode_valid(struct drm_crtc
>>>
>>>> *crtc, const struct drm_display_mode
>>>
>>>>
>>>
>>>>                      if ((ast->chip == AST2100) || (ast->chip ==
>>>> AST2200) ||
>>>
>>>>                          (ast->chip == AST2300) || (ast->chip ==
>>>> AST2400) ||
>>>
>>>> -                (ast->chip == AST2500)) {
>>>
>>>> +               (ast->chip == AST2500) || (ast->chip == AST2600)) {
>>>
>>>>                              if ((mode->hdisplay == 1920) &&
>>>> (mode->vdisplay == 1080))
>>>
>>>>                                      return MODE_OK;
>>>
>>>>
>>>
>>>> @@ -1110,6 +1130,7 @@ ast_crtc_helper_atomic_flush(struct drm_crtc
>>>> *crtc,
>>>
>>>>              struct ast_private *ast = to_ast_private(crtc->dev);
>>>
>>>>              struct ast_crtc_state *ast_crtc_state =
>>>> to_ast_crtc_state(crtc_state);
>>>
>>>>              struct ast_crtc_state *old_ast_crtc_state =
>>>
>>>> to_ast_crtc_state(old_crtc_state);
>>>
>>>> +   struct ast_vbios_mode_info *vbios_mode_info =
>>>
>>>> +&ast_crtc_state->vbios_mode_info;
>>>
>>>>
>>>
>>>>              /*
>>>
>>>>               * The gamma LUT has to be reloaded after changing the
>>>> primary @@
>>>
>>>> -1117,6 +1138,10 @@ ast_crtc_helper_atomic_flush(struct drm_crtc
>>>> *crtc,
>>>
>>>>               */
>>>
>>>>              if (old_ast_crtc_state->format !=
>>>> ast_crtc_state->format)
>>>
>>>>                      ast_crtc_load_lut(ast, crtc);
>>>
>>>> +
>>>
>>>> +   //Set Aspeed Display-Port
>>>
>>>> +   if (ast->tx_chip_type == AST_TX_ASTDP)
>>>
>>>> +           ast_dp_set_mode(crtc, vbios_mode_info);
>>>
>>>>      }
>>>
>>>>
>>>
>>>>      static void
>>>
>>>> @@ -1527,6 +1552,93 @@ static int ast_dp501_output_init(struct
>>>> ast_private *ast)
>>>
>>>>              return 0;
>>>
>>>>      }
>>>
>>>>
>>>
>>>> +/*
>>>
>>>> + * ASPEED Display-Port Connector
>>>
>>>> + */
>>>
>>>> +
>>>
>>>> +static int ast_astdp_connector_helper_get_modes(struct
>>>> +drm_connector
>>>
>>>> +*connector) {
>>>
>>>> +   void *edid;
>>>
>>>> +
>>>
>>>> +   int succ;
>>>
>>>> +   int count;
>>>
>>>> +
>>>
>>>> +   edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
>>>
>>>> +   if (!edid)
>>>
>>>> +           goto err_drm_connector_update_edid_property;
>>>
>>>> +
>>>
>>>> +   succ = ast_astdp_read_edid(connector->dev, edid);
>>>
>>>> +   if (succ < 0)
>>>
>>>> +           goto err_kfree;
>>>
>>>> +
>>>
>>>> +   drm_connector_update_edid_property(connector, edid);
>>>
>>>> +   count = drm_add_edid_modes(connector, edid);
>>>
>>>> +   kfree(edid);
>>>
>>>> +
>>>
>>>> +   return count;
>>>
>>>> +
>>>
>>>> +err_kfree:
>>>
>>>> +   kfree(edid);
>>>
>>>> +err_drm_connector_update_edid_property:
>>>
>>>> +   drm_connector_update_edid_property(connector, NULL);
>>>
>>>> +   return 0;
>>>
>>>> +}
>>>
>>>> +
>>>
>>>> +static const struct drm_connector_helper_funcs
>>>> +ast_astdp_connector_helper_funcs = {
>>>
>>>> +   .get_modes = ast_astdp_connector_helper_get_modes,
>>>
>>>> +};
>>>
>>>> +
>>>
>>>> +static const struct drm_connector_funcs ast_astdp_connector_funcs =
>>>> +{
>>>
>>>> +   .reset = drm_atomic_helper_connector_reset,
>>>
>>>> +   .fill_modes = drm_helper_probe_single_connector_modes,
>>>
>>>> +   .destroy = drm_connector_cleanup,
>>>
>>>> +   .atomic_duplicate_state =
>>>> +drm_atomic_helper_connector_duplicate_state,
>>>
>>>> +   .atomic_destroy_state =
>>>> +drm_atomic_helper_connector_destroy_state,
>>>
>>>> +};
>>>
>>>> +
>>>
>>>> +static int ast_astdp_connector_init(struct drm_device *dev, struct
>>>
>>>> +drm_connector *connector) {
>>>
>>>> +   int ret;
>>>
>>>> +
>>>
>>>> +   ret = drm_connector_init(dev, connector,
>>>> +&ast_astdp_connector_funcs,
>>>
>>>> +                           DRM_MODE_CONNECTOR_DisplayPort);
>>>
>>>> +   if (ret)
>>>
>>>> +           return ret;
>>>
>>>> +
>>>
>>>> +   drm_connector_helper_add(connector,
>>>
>>>> +&ast_astdp_connector_helper_funcs);
>>>
>>>> +
>>>
>>>> +   connector->interlace_allowed = 0;
>>>
>>>> +   connector->doublescan_allowed = 0;
>>>
>>>> +
>>>
>>>> +   connector->polled = DRM_CONNECTOR_POLL_CONNECT;
>>>
>>>> +
>>>
>>>> +   return 0;
>>>
>>>> +}
>>>
>>>> +
>>>
>>>> +static int ast_astdp_output_init(struct ast_private *ast) {
>>>
>>>> +   struct drm_device *dev = &ast->base;
>>>
>>>> +   struct drm_crtc *crtc = &ast->crtc;
>>>
>>>> +   struct drm_encoder *encoder = &ast->output.astdp.encoder;
>>>
>>>> +   struct drm_connector *connector = &ast->output.astdp.connector;
>>>
>>>> +   int ret;
>>>
>>>> +
>>>
>>>> +   ret = drm_simple_encoder_init(dev, encoder,
>>>> +DRM_MODE_ENCODER_TMDS);
>>>
>>>> +   if (ret)
>>>
>>>> +           return ret;
>>>
>>>> +   encoder->possible_crtcs = drm_crtc_mask(crtc);
>>>
>>>> +
>>>
>>>> +   ret = ast_astdp_connector_init(dev, connector);
>>>
>>>> +   if (ret)
>>>
>>>> +           return ret;
>>>
>>>> +
>>>
>>>> +   ret = drm_connector_attach_encoder(connector, encoder);
>>>
>>>> +   if (ret)
>>>
>>>> +           return ret;
>>>
>>>> +
>>>
>>>> +   return 0;
>>>
>>>> +}
>>>
>>>> +
>>>
>>>>      /*
>>>
>>>>       * Mode config
>>>
>>>>       */
>>>
>>>> @@ -1563,7 +1675,8 @@ int ast_mode_config_init(struct ast_private
>>>> *ast)
>>>
>>>>                  ast->chip == AST2200 ||
>>>
>>>>                  ast->chip == AST2300 ||
>>>
>>>>                  ast->chip == AST2400 ||
>>>
>>>> -        ast->chip == AST2500) {
>>>
>>>> +       ast->chip == AST2500 ||
>>>
>>>> +       ast->chip == AST2600) {
>>>
>>>>                      dev->mode_config.max_width = 1920;
>>>
>>>>                      dev->mode_config.max_height = 2048;
>>>
>>>>              } else {
>>>
>>>> @@ -1594,6 +1707,9 @@ int ast_mode_config_init(struct ast_private
>>>> *ast)
>>>
>>>>              case AST_TX_DP501:
>>>
>>>>                      ret = ast_dp501_output_init(ast);
>>>
>>>>                      break;
>>>
>>>> +   case AST_TX_ASTDP:
>>>
>>>> +           ret = ast_astdp_output_init(ast);
>>>
>>>> +           break;
>>>
>>>>              }
>>>
>>>>              if (ret)
>>>
>>>>                      return ret;
>>>
>>>> diff --git a/drivers/gpu/drm/ast/ast_post.c
>>>
>>>> b/drivers/gpu/drm/ast/ast_post.c index b5d92f652..0aa9cf0fb 100644
>>>
>>>> --- a/drivers/gpu/drm/ast/ast_post.c
>>>
>>>> +++ b/drivers/gpu/drm/ast/ast_post.c
>>>
>>>> @@ -379,7 +379,9 @@ void ast_post_gpu(struct drm_device *dev)
>>>
>>>>              ast_enable_mmio(dev);
>>>
>>>>              ast_set_def_ext_reg(dev);
>>>
>>>>
>>>
>>>> -    if (ast->config_mode == ast_use_p2a) {
>>>
>>>> +   if (ast->chip == AST2600) {
>>>
>>>> +           ast_dp_launch(dev, 1);
>>>
>>>> +   } else if (ast->config_mode == ast_use_p2a) {
>>>
>>>>                      if (ast->chip == AST2500)
>>>
>>>>                              ast_post_chip_2500(dev);
>>>
>>>>                      else if (ast->chip == AST2300 || ast->chip ==
>>>> AST2400)
>>>
>>>>
>>>
>>>> base-commit: c54b39a565227538c52ead2349eb17d54aadd6f7
>>>
>>>> --
>>>
>>>> 2.27.0
>>>
>>>>
>>>
>>> --
>>>
>>> Thomas Zimmermann
>>>
>>> Graphics Driver Developer
>>>
>>> SUSE Software Solutions Germany GmbH
>>>
>>> Maxfeldstr. 5, 90409 Nürnberg, Germany
>>>
>>> (HRB 36809, AG Nürnberg)
>>>
>>> Geschäftsführer: Ivo Totev
>>>
>>
>> --
>> Thomas Zimmermann
>> Graphics Driver Developer
>> SUSE Software Solutions Germany GmbH
>> Maxfeldstr. 5, 90409 Nürnberg, Germany (HRB 36809, AG Nürnberg)
>> Geschäftsführer: Ivo Totev
> 
> --
> Thomas Zimmermann
> Graphics Driver Developer
> SUSE Software Solutions Germany GmbH
> Maxfeldstr. 5, 90409 Nürnberg, Germany
> (HRB 36809, AG Nürnberg)
> Geschäftsführer: Ivo Totev

-- 
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Maxfeldstr. 5, 90409 Nürnberg, Germany
(HRB 36809, AG Nürnberg)
Geschäftsführer: Ivo Totev

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2022-06-01 10:42 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-11-22 10:36 [PATCH] drm/ast: Create the driver for ASPEED proprietory Display-Port KuoHsiang Chou
2021-11-25 15:49 ` [PATCH] drm/ast: fix semicolon.cocci warnings kernel test robot
2021-11-25 15:56 ` [PATCH] drm/ast: Create the driver for ASPEED proprietory Display-Port kernel test robot
2021-12-03  6:31 ` Kuo-Hsiang Chou
2021-12-03  8:54   ` Thomas Zimmermann
2021-12-27  8:37     ` [PATCH v2] " KuoHsiang Chou
2022-01-01 19:41 ` [PATCH] drm/ast: fix semicolon.cocci warnings kernel test robot
2022-01-01 19:51 ` [PATCH] drm/ast: Create the driver for ASPEED proprietory Display-Port kernel test robot
2022-01-04  8:50   ` [PATCH v3] " KuoHsiang Chou
2022-01-12 15:04     ` Thomas Zimmermann
2022-04-28  7:56       ` [PATCH v4] " KuoHsiang Chou
2022-05-04  7:27         ` Thomas Zimmermann
     [not found]           ` <PSAPR06MB48056FC903142B7F60A3BD388CC39@PSAPR06MB4805.apcprd06.prod.outlook.com>
2022-05-04  9:37             ` Thomas Zimmermann
2022-05-05  2:41               ` Kuo-Hsiang Chou
2022-05-05  2:51                 ` Luke Chen
2022-05-10 10:56             ` Thomas Zimmermann
2022-05-13  9:07               ` Kuo-Hsiang Chou
2022-05-13 10:20                 ` Thomas Zimmermann
2022-05-13 10:39                   ` Kuo-Hsiang Chou
2022-05-30  6:05                     ` Kuo-Hsiang Chou
2022-06-01 10:42                       ` Thomas Zimmermann

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).