RE: [PATCH v4] drm/ast: Create the driver for ASPEED proprietory Display-Port

From: Luke Chen
Date: Wed May 04 2022 - 22:51:48 EST


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@xxxxxxxxxxxxxx>
Sent: Thursday, May 5, 2022 10:41 AM
To: Thomas Zimmermann <tzimmermann@xxxxxxx>; dri-devel@xxxxxxxxxxxxxxxxxxxxx; linux-kernel@xxxxxxxxxxxxxxx
Cc: Hungju Huang <hungju_huang@xxxxxxxxxxxxxx>; airlied@xxxxxxxx; Tommy Huang <tommy_huang@xxxxxxxxxxxxxx>; airlied@xxxxxxxxxx; Arc Sung <arc_sung@xxxxxxxxxxxxxx>; Luke Chen <luke_chen@xxxxxxxxxxxxxx>
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@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