[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <d6c93aa6-db63-2e16-83f3-057cef30e9d4@suse.de>
Date: Tue, 7 Jun 2022 13:30:27 +0200
From: Thomas Zimmermann <tzimmermann@...e.de>
To: KuoHsiang Chou <kuohsiang_chou@...eedtech.com>,
dri-devel@...ts.freedesktop.org, linux-kernel@...r.kernel.org
Cc: kernel test robot <lkp@...el.com>, hungju_huang@...eedtech.com,
airlied@...ux.ie, tommy_huang@...eedtech.com, airlied@...hat.com,
arc_sung@...eedtech.com, luke_chen@...eedtech.com
Subject: Re: [PATCH v5] drm/ast: Create the driver for ASPEED proprietory
Display-Port
Hi,
thanks for the update, but the change is already in the DRM tree. You
need to write a patch on top of the latest DRM tree. See [1].
Best regards
Thomas
[1] https://cgit.freedesktop.org/drm/drm-tip/
Am 07.06.22 um 10:49 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.
>
> V5:
> 1.Fixed sparse:cast truncates bits form constant value ()cast
> truncates bits from constant value (ffffffffffffff00 becomes 0)
>
> Signed-off-by: KuoHsiang Chou <kuohsiang_chou@...eedtech.com>
> Reported-by: kernel test robot <lkp@...el.com>
> ---
> drivers/gpu/drm/ast/Makefile | 2 +-
> drivers/gpu/drm/ast/ast_dp.c | 282 +++++++++++++++++++++++++++++++++
> drivers/gpu/drm/ast/ast_drv.h | 115 ++++++++++++++
> drivers/gpu/drm/ast/ast_main.c | 5 +-
> drivers/gpu/drm/ast/ast_mode.c | 124 ++++++++++++++-
> drivers/gpu/drm/ast/ast_post.c | 4 +-
> 6 files changed, 524 insertions(+), 8 deletions(-)
> create mode 100644 drivers/gpu/drm/ast/ast_dp.c
>
> diff --git a/drivers/gpu/drm/ast/Makefile b/drivers/gpu/drm/ast/Makefile
> index 21f71160b..5a53ce51f 100644
> --- a/drivers/gpu/drm/ast/Makefile
> +++ b/drivers/gpu/drm/ast/Makefile
> @@ -3,6 +3,6 @@
> # Makefile for the drm device driver. This driver provides support for the
> # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
>
> -ast-y := ast_drv.o ast_i2c.o ast_main.o ast_mm.o ast_mode.o ast_post.o ast_dp501.o
> +ast-y := ast_drv.o ast_i2c.o ast_main.o ast_mm.o ast_mode.o ast_post.o ast_dp501.o ast_dp.o
>
> obj-$(CONFIG_DRM_AST) := ast.o
> diff --git a/drivers/gpu/drm/ast/ast_dp.c b/drivers/gpu/drm/ast/ast_dp.c
> new file mode 100644
> index 000000000..1ae12c407
> --- /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@...eedtech.com>
> +
> +#include <linux/firmware.h>
> +#include <linux/delay.h>
> +#include <drm/drm_print.h>
> +#include "ast_drv.h"
> +
> +int ast_astdp_read_edid(struct drm_device *dev, u8 *ediddata)
> +{
> + struct ast_private *ast = to_ast_private(dev);
> + u8 i = 0, j = 0;
> +
> + /*
> + * CRD1[b5]: DP MCU FW is executing
> + * CRDC[b0]: DP link success
> + * CRDF[b0]: DP HPD
> + * CRE5[b0]: Host reading EDID process is done
> + */
> + if (!(ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xD1, ASTDP_MCU_FW_EXECUTING) &&
> + ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDC, ASTDP_LINK_SUCCESS) &&
> + ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xDF, ASTDP_HPD) &&
> + ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
> + ASTDP_HOST_EDID_READ_DONE_MASK))) {
> + goto err_astdp_edid_not_ready;
> + }
> +
> + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5, (u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
> + 0x00);
> +
> + for (i = 0; i < 32; i++) {
> + /*
> + * CRE4[7:0]: Read-Pointer for EDID (Unit: 4bytes); valid range: 0~64
> + */
> + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE4,
> + ASTDP_AND_CLEAR_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, ASTDP_AND_CLEAR_MASK,
> + ASTDP_MISC0_24bpp);
> + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE1, ASTDP_AND_CLEAR_MASK, ASTDP_MISC1);
> + ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE2, ASTDP_AND_CLEAR_MASK, ModeIdx);
> +}
> diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
> index a19315b2f..79451130c 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_AND_CLEAR_MASK 0x00
> +
> +/*
> + * 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
Download attachment "OpenPGP_signature" of type "application/pgp-signature" (841 bytes)
Powered by blists - more mailing lists