Hi
Am 28.04.22 um 09:56 schrieb KuoHsiang Chou:
V1:
- The MCU FW controling ASPEED DP is loaded by BMC boot loader.
- Driver starts after CR[3:1] == 111b that indicates Tx is ASTDP, and CRD1[5] has been asserted by BMVC boot loader.
- EDID is prioritized by DP monitor.
- DP's EDID has high priority to decide resolution supporting.
V2: Modules description:
- ASTDP (ASPEED DisplayPort) is controlled by dedicated AST-MCU (ASPEED propriatary MCU).
- MCU is looping in charged of HPD, Read EDID, Link Training with DP sink.
- ASTDP and AST-MUC reside in BMC (Baseboard Management controller) addressing-space.
- ASPEED DRM driver requests MCU to get HPD and EDID by CR-scratched register.
Booting sequence:
- Check if TX is ASTDP // ast_dp_launch()
- Check if DP-MCU FW has loaded // ast_dp_launch()
- Read EDID // ast_dp_read_edid()
- Resolution switch // ast_dp_SetOutput()
V3:
- Remove unneeded semicolon.
- Apply to git://anongit.freedesktop.org/drm/drm, instead of git://anongit.freedesktop.org/drm/drm-misc
- Resolve auto build test WARNINGs on V1 patch.
V4:
- Sync code-base with kernel 5.17_rc6
- Remove the define of DPControlPower, because DP chips need to be powered on to be used.
- Remove the switches of PHY and Display from EDID procedure.
- Revise increaing delay to fixed delay, because this version kernel doesn't detect minitor consistenntly.
- Create clean-up code used for reset of power state on errors with -EIO manner.
- Revise the DP detection by TX type and its DP-FW status during booting and resume.
- Correct the CamelCase Style.
- Use register reading while needing, and remove to hold full register.
- 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@aspeedtech.com
Reviewed-by: Thomas Zimmermann tzimmermann@suse.de
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@aspeedtech.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,
(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);
if (ast->tx_chip_type == AST_TX_DP501) ast_set_dp501_video_output(crtc->dev, 1);ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, 0);
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);
}
break;ast_crtc_load_lut(ast, crtc);
- case DRM_MODE_DPMS_STANDBY:
- case DRM_MODE_DPMS_SUSPEND: case DRM_MODE_DPMS_OFF:
if (ast->tx_chip_type == AST_TX_DP501) ast_set_dp501_video_output(crtc->dev, 0); break;ch = mode;
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 ||
dev->mode_config.max_width = 1920; dev->mode_config.max_height = 2048; } else {ast->chip == AST2600) {
@@ -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);
} if (ret) return ret;break;
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