aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c123
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h10
-rw-r--r--drivers/gpu/drm/amd/display/modules/power/power_helpers.c3
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 dea40b322191..e927c8934681 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(
}
#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
-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);
}