diff options
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.19.8/1069-drm-amd-display-Redefine-DMCU_SCRATCH-to-identify-DM.patch')
-rw-r--r-- | common/recipes-kernel/linux/linux-yocto-4.19.8/1069-drm-amd-display-Redefine-DMCU_SCRATCH-to-identify-DM.patch | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.19.8/1069-drm-amd-display-Redefine-DMCU_SCRATCH-to-identify-DM.patch b/common/recipes-kernel/linux/linux-yocto-4.19.8/1069-drm-amd-display-Redefine-DMCU_SCRATCH-to-identify-DM.patch new file mode 100644 index 00000000..04674cde --- /dev/null +++ b/common/recipes-kernel/linux/linux-yocto-4.19.8/1069-drm-amd-display-Redefine-DMCU_SCRATCH-to-identify-DM.patch @@ -0,0 +1,242 @@ +From fe4c3891ead24b6d70e5f7c90e4ab4f7fd0ab0bb Mon Sep 17 00:00:00 2001 +From: Martin Tsai <martin.tsai@amd.com> +Date: Thu, 13 Dec 2018 12:25:19 +0800 +Subject: [PATCH 1069/2940] drm/amd/display: Redefine DMCU_SCRATCH to identify + DMCU state + +[why] +To resume system before entering S0i3 completely will cause PSP not +reload DMCU FW since there is not HW power state change. +In this case, driver cannot get correct DMCU version from IRAM +since driver override it and DMCU didn't reload to update it. +It makes driver return false in dcn10_dmcu_init(). + +[how] +1.To redefine DMCU_SCRATCH to identify different DMCU state. +2.To reserve IRAM 0xF0~0xFF write by DMCU only. +3.To remove dcn10_get_dmcu_state + +Signed-off-by: Martin Tsai <martin.tsai@amd.com> +Reviewed-by: Anthony Koo <Anthony.Koo@amd.com> +Acked-by: Leo Li <sunpeng.li@amd.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +--- + drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c | 123 ++++++------------ + drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h | 10 +- + .../amd/display/modules/power/power_helpers.c | 3 +- + 3 files changed, 52 insertions(+), 84 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c +index ca7989e4932b..897c5a79ef5b 100644 +--- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c ++++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c +@@ -51,7 +51,6 @@ + #define PSR_SET_WAITLOOP 0x31 + #define MCP_INIT_DMCU 0x88 + #define MCP_INIT_IRAM 0x89 +-#define MCP_DMCU_VERSION 0x90 + #define MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK 0x00000001L + + static bool dce_dmcu_init(struct dmcu *dmcu) +@@ -317,38 +316,11 @@ static void dce_get_psr_wait_loop( + } + + #ifdef CONFIG_X86 +-static void dcn10_get_dmcu_state(struct dmcu *dmcu) +-{ +- struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); +- uint32_t dmcu_state_offset = 0xf6; +- +- /* Enable write access to IRAM */ +- REG_UPDATE_2(DMCU_RAM_ACCESS_CTRL, +- IRAM_HOST_ACCESS_EN, 1, +- IRAM_RD_ADDR_AUTO_INC, 1); +- +- REG_WAIT(DMU_MEM_PWR_CNTL, DMCU_IRAM_MEM_PWR_STATE, 0, 2, 10); +- +- /* Write address to IRAM_RD_ADDR in DMCU_IRAM_RD_CTRL */ +- REG_WRITE(DMCU_IRAM_RD_CTRL, dmcu_state_offset); +- +- /* Read data from IRAM_RD_DATA in DMCU_IRAM_RD_DATA*/ +- dmcu->dmcu_state = REG_READ(DMCU_IRAM_RD_DATA); +- +- /* Disable write access to IRAM to allow dynamic sleep state */ +- REG_UPDATE_2(DMCU_RAM_ACCESS_CTRL, +- IRAM_HOST_ACCESS_EN, 0, +- IRAM_RD_ADDR_AUTO_INC, 0); +-} +- + static void dcn10_get_dmcu_version(struct dmcu *dmcu) + { + struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); + uint32_t dmcu_version_offset = 0xf1; + +- /* Clear scratch */ +- REG_WRITE(DC_DMCU_SCRATCH, 0); +- + /* Enable write access to IRAM */ + REG_UPDATE_2(DMCU_RAM_ACCESS_CTRL, + IRAM_HOST_ACCESS_EN, 1, +@@ -368,76 +340,65 @@ static void dcn10_get_dmcu_version(struct dmcu *dmcu) + REG_UPDATE_2(DMCU_RAM_ACCESS_CTRL, + IRAM_HOST_ACCESS_EN, 0, + IRAM_RD_ADDR_AUTO_INC, 0); +- +- /* Send MCP command message to DMCU to get version reply from FW. +- * We expect this version should match the one in IRAM, otherwise +- * something is wrong with DMCU and we should fail and disable UC. +- */ +- REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 800); +- +- /* Set command to get DMCU version from microcontroller */ +- REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, +- MCP_DMCU_VERSION); +- +- /* Notify microcontroller of new command */ +- REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); +- +- /* Ensure command has been executed before continuing */ +- REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 800); +- +- /* Somehow version does not match, so fail and return version 0 */ +- if (dmcu->dmcu_version.interface_version != REG_READ(DC_DMCU_SCRATCH)) +- dmcu->dmcu_version.interface_version = 0; + } + + static bool dcn10_dmcu_init(struct dmcu *dmcu) + { + struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu); ++ bool status = false; + +- /* DMCU FW should populate the scratch register if running */ +- if (REG_READ(DC_DMCU_SCRATCH) == 0) +- return false; +- +- /* Check state is uninitialized */ +- dcn10_get_dmcu_state(dmcu); +- +- /* If microcontroller is already initialized, do nothing */ +- if (dmcu->dmcu_state == DMCU_RUNNING) +- return true; +- +- /* Retrieve and cache the DMCU firmware version. */ +- dcn10_get_dmcu_version(dmcu); +- +- /* Check interface version to confirm firmware is loaded and running */ +- if (dmcu->dmcu_version.interface_version == 0) +- return false; ++ /* Definition of DC_DMCU_SCRATCH ++ * 0 : firmare not loaded ++ * 1 : PSP load DMCU FW but not initialized ++ * 2 : Firmware already initialized ++ */ ++ dmcu->dmcu_state = REG_READ(DC_DMCU_SCRATCH); + +- /* Wait until microcontroller is ready to process interrupt */ +- REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 800); ++ switch (dmcu->dmcu_state) { ++ case DMCU_UNLOADED: ++ status = false; ++ break; ++ case DMCU_LOADED_UNINITIALIZED: ++ /* Wait until microcontroller is ready to process interrupt */ ++ REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 800); + +- /* Set initialized ramping boundary value */ +- REG_WRITE(MASTER_COMM_DATA_REG1, 0xFFFF); ++ /* Set initialized ramping boundary value */ ++ REG_WRITE(MASTER_COMM_DATA_REG1, 0xFFFF); + +- /* Set command to initialize microcontroller */ +- REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, ++ /* Set command to initialize microcontroller */ ++ REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, + MCP_INIT_DMCU); + +- /* Notify microcontroller of new command */ +- REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); ++ /* Notify microcontroller of new command */ ++ REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); + +- /* Ensure command has been executed before continuing */ +- REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 800); ++ /* Ensure command has been executed before continuing */ ++ REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0, 100, 800); + +- // Check state is initialized +- dcn10_get_dmcu_state(dmcu); ++ // Check state is initialized ++ dmcu->dmcu_state = REG_READ(DC_DMCU_SCRATCH); + +- // If microcontroller is not in running state, fail +- if (dmcu->dmcu_state != DMCU_RUNNING) +- return false; ++ // If microcontroller is not in running state, fail ++ if (dmcu->dmcu_state == DMCU_RUNNING) { ++ /* Retrieve and cache the DMCU firmware version. */ ++ dcn10_get_dmcu_version(dmcu); ++ status = true; ++ } else ++ status = false; + +- return true; ++ break; ++ case DMCU_RUNNING: ++ status = true; ++ break; ++ default: ++ status = false; ++ break; ++ } ++ ++ return status; + } + ++ + static bool dcn10_dmcu_load_iram(struct dmcu *dmcu, + unsigned int start_offset, + const char *src, +diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h +index cb85eaa9857f..ed32a7503684 100644 +--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h ++++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h +@@ -27,9 +27,15 @@ + + #include "dm_services_types.h" + ++/* If HW itself ever powered down it will be 0. ++ * fwDmcuInit will write to 1. ++ * Driver will only call MCP init if current state is 1, ++ * and the MCP command will transition this to 2. ++ */ + enum dmcu_state { +- DMCU_NOT_INITIALIZED = 0, +- DMCU_RUNNING = 1 ++ DMCU_UNLOADED = 0, ++ DMCU_LOADED_UNINITIALIZED = 1, ++ DMCU_RUNNING = 2, + }; + + struct dmcu_version { +diff --git a/drivers/gpu/drm/amd/display/modules/power/power_helpers.c b/drivers/gpu/drm/amd/display/modules/power/power_helpers.c +index c11a443dcbc8..89b082b5d107 100644 +--- a/drivers/gpu/drm/amd/display/modules/power/power_helpers.c ++++ b/drivers/gpu/drm/amd/display/modules/power/power_helpers.c +@@ -56,6 +56,7 @@ static const unsigned char abm_config[abm_defines_max_config][abm_defines_max_le + #define NUM_AGGR_LEVEL 4 + #define NUM_POWER_FN_SEGS 8 + #define NUM_BL_CURVE_SEGS 16 ++#define IRAM_RESERVE_AREA_START 0xF0 // reserve 0xF0~0xFF are write by DMCU only + + #pragma pack(push, 1) + /* NOTE: iRAM is 256B in size */ +@@ -324,5 +325,5 @@ bool dmcu_load_iram(struct dmcu *dmcu, + params, &ram_table); + + return dmcu->funcs->load_iram( +- dmcu, 0, (char *)(&ram_table), sizeof(ram_table)); ++ dmcu, 0, (char *)(&ram_table), IRAM_RESERVE_AREA_START); + } +-- +2.17.1 + |