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! 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