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@xxxxxxx] Sent: Wednesday, May 04, 2022 5:38 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 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@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