aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/linux-yocto-4.19.8/1069-drm-amd-display-Redefine-DMCU_SCRATCH-to-identify-DM.patch
diff options
context:
space:
mode:
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.patch242
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
+