Hi Thomas,
-----Original Message-----
From: dri-devel [mailto:dri-devel-bounces@xxxxxxxxxxxxxxxxxxxxx] On Behalf Of Kuo-Hsiang Chou
Sent: Friday, May 13, 2022 6:39 PM
To: Thomas Zimmermann <tzimmermann@xxxxxxx>; dri-devel@xxxxxxxxxxxxxxxxxxxxx; linux-kernel@xxxxxxxxxxxxxxx
Subject: RE: [PATCH v4] drm/ast: Create the driver for ASPEED proprietory Display-Port
Hi Thomas,
-----Original Message-----
From: Thomas Zimmermann [mailto:tzimmermann@xxxxxxx]
Sent: Friday, May 13, 2022 6:21 PM
To: Kuo-Hsiang Chou <kuohsiang_chou@xxxxxxxxxxxxxx>; dri-devel@xxxxxxxxxxxxxxxxxxxxx; linux-kernel@xxxxxxxxxxxxxxx
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@xxxxxxx]
Sent: Tuesday, May 10, 2022 6:56 PM
To: Kuo-Hsiang Chou <kuohsiang_chou@xxxxxxxxxxxxxx>;
dri-devel@xxxxxxxxxxxxxxxxxxxxx; linux-kernel@xxxxxxxxxxxxxxx
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@xxxxxxx]
Sent: Wednesday, May 04, 2022 3:28 PM
To: Kuo-Hsiang Chou <kuohsiang_chou@xxxxxxxxxxxxxx>;
dri-devel@xxxxxxxxxxxxxxxxxxxxx; linux-kernel@xxxxxxxxxxxxxxx
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@xxxxxxxxxxxxxx
<mailto:kuohsiang_chou@xxxxxxxxxxxxxx>>
Reviewed-by: Thomas Zimmermann <tzimmermann@xxxxxxx
<mailto:tzimmermann@xxxxxxx>>
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@xxxxxxxxxxxxxx
+<mailto:kuohsiang_chou@xxxxxxxxxxxxxx>>
+
+#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:
OpenPGP_signature
Description: OpenPGP digital signature