aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/0233-drm-amd-display-DMCU-PSR-Refactor.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/0233-drm-amd-display-DMCU-PSR-Refactor.patch')
-rw-r--r--meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/0233-drm-amd-display-DMCU-PSR-Refactor.patch933
1 files changed, 933 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/0233-drm-amd-display-DMCU-PSR-Refactor.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/0233-drm-amd-display-DMCU-PSR-Refactor.patch
new file mode 100644
index 00000000..55cbf497
--- /dev/null
+++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/0233-drm-amd-display-DMCU-PSR-Refactor.patch
@@ -0,0 +1,933 @@
+From 20e1ae80f26a2a86516da431e51e031c80e75a79 Mon Sep 17 00:00:00 2001
+From: Amy Zhang <Amy.Zhang@amd.com>
+Date: Fri, 17 Feb 2017 11:56:03 -0500
+Subject: [PATCH 0233/4131] drm/amd/display: DMCU PSR Refactor
+
+- Move PSR programming from link encoder to dmcu
+
+Signed-off-by: Amy Zhang <Amy.Zhang@amd.com>
+Acked-by: Harry Wentland <Harry.Wentland@amd.com>
+Reviewed-by: Tony Cheng <Tony.Cheng@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+---
+ drivers/gpu/drm/amd/display/dc/core/dc_link.c | 21 +-
+ drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c | 208 +++++++++++++++
+ drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h | 107 +++++++-
+ .../gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 280 +++------------------
+ .../gpu/drm/amd/display/dc/dce/dce_link_encoder.h | 73 +-----
+ drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h | 4 +
+ .../gpu/drm/amd/display/dc/inc/hw/link_encoder.h | 9 +-
+ 7 files changed, 376 insertions(+), 326 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
+index 2b92939..8eb6b34 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
+@@ -40,6 +40,7 @@
+ #include "abm.h"
+ #include "fixed31_32.h"
+ #include "dpcd_defs.h"
++#include "dmcu.h"
+
+ #include "dce/dce_11_0_d.h"
+ #include "dce/dce_11_0_enum.h"
+@@ -1433,28 +1434,33 @@ bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level,
+ bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable)
+ {
+ struct core_link *link = DC_LINK_TO_CORE(dc_link);
++ struct dc_context *ctx = link->ctx;
++ struct core_dc *core_dc = DC_TO_CORE(ctx->dc);
++ struct dmcu *dmcu = core_dc->res_pool->dmcu;
++
++ if (dmcu != NULL && dc_link->psr_caps.psr_version > 0)
++ dmcu->funcs->set_psr_enable(dmcu, enable);
+
+- if (dc_link != NULL && dc_link->psr_caps.psr_version > 0)
+- link->link_enc->funcs->set_dmcu_psr_enable(link->link_enc,
+- enable);
+ return true;
+ }
+
+ bool dc_link_setup_psr(const struct dc_link *dc_link,
+ const struct dc_stream *stream)
+ {
+-
+ struct core_link *link = DC_LINK_TO_CORE(dc_link);
+ struct dc_context *ctx = link->ctx;
+ struct core_dc *core_dc = DC_TO_CORE(ctx->dc);
++ struct dmcu *dmcu = core_dc->res_pool->dmcu;
+ struct core_stream *core_stream = DC_STREAM_TO_CORE(stream);
+- struct psr_dmcu_context psr_context = {0};
++ struct psr_context psr_context = {0};
+ int i;
+
+ psr_context.controllerId = CONTROLLER_ID_UNDEFINED;
+
+
+- if (dc_link != NULL && dc_link->psr_caps.psr_version > 0) {
++ if (dc_link != NULL &&
++ dmcu != NULL &&
++ dc_link->psr_caps.psr_version > 0) {
+ /* updateSinkPsrDpcdConfig*/
+ union dpcd_psr_configuration psr_configuration;
+
+@@ -1552,8 +1558,7 @@ bool dc_link_setup_psr(const struct dc_link *dc_link,
+ */
+ psr_context.frame_delay = 0;
+
+- link->link_enc->funcs->setup_dmcu_psr
+- (link->link_enc, &psr_context);
++ dmcu->funcs->setup_psr(dmcu, link, &psr_context);
+ return true;
+ } else
+ return false;
+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 eb0e95f..44eeeeb 100644
+--- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c
++++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c
+@@ -23,6 +23,8 @@
+ *
+ */
+
++#include "core_types.h"
++#include "link_encoder.h"
+ #include "dce_dmcu.h"
+ #include "dm_services.h"
+ #include "reg_helper.h"
+@@ -42,6 +44,12 @@
+ #define CTX \
+ dmcu_dce->base.ctx
+
++/* PSR related commands */
++#define PSR_ENABLE 0x20
++#define PSR_EXIT 0x21
++#define PSR_SET 0x23
++#define MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK 0x00000001L
++
+ bool dce_dmcu_load_iram(struct dmcu *dmcu,
+ unsigned int start_offset,
+ const char *src,
+@@ -76,8 +84,208 @@ bool dce_dmcu_load_iram(struct dmcu *dmcu,
+ return true;
+ }
+
++static void dce_get_dmcu_psr_state(struct dmcu *dmcu, uint32_t *psr_state)
++{
++ struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu);
++
++ uint32_t count = 0;
++ uint32_t psrStateOffset = 0xf0;
++ uint32_t value = -1;
++
++ /* Enable write access to IRAM */
++ REG_UPDATE(DMCU_RAM_ACCESS_CTRL, IRAM_HOST_ACCESS_EN, 1);
++
++ while (REG(DCI_MEM_PWR_STATUS) && value != 0 && count++ < 10) {
++ dm_delay_in_microseconds(dmcu->ctx, 2);
++ REG_GET(DCI_MEM_PWR_STATUS, DMCU_IRAM_MEM_PWR_STATE, &value);
++ }
++ while (REG(DMU_MEM_PWR_CNTL) && value != 0 && count++ < 10) {
++ dm_delay_in_microseconds(dmcu->ctx, 2);
++ REG_GET(DMU_MEM_PWR_CNTL, DMCU_IRAM_MEM_PWR_STATE, &value);
++ }
++
++ /* Write address to IRAM_RD_ADDR in DMCU_IRAM_RD_CTRL */
++ REG_WRITE(DMCU_IRAM_RD_CTRL, psrStateOffset);
++
++ /* Read data from IRAM_RD_DATA in DMCU_IRAM_RD_DATA*/
++ *psr_state = REG_READ(DMCU_IRAM_RD_DATA);
++
++ /* Disable write access to IRAM after finished using IRAM
++ * in order to allow dynamic sleep state
++ */
++ REG_UPDATE(DMCU_RAM_ACCESS_CTRL, IRAM_HOST_ACCESS_EN, 0);
++}
++
++static void dce_dmcu_set_psr_enable(struct dmcu *dmcu, bool enable)
++{
++ struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu);
++ unsigned int dmcu_max_retry_on_wait_reg_ready = 801;
++ unsigned int dmcu_wait_reg_ready_interval = 100;
++
++ unsigned int regValue;
++
++ unsigned int retryCount;
++ uint32_t psr_state = 0;
++
++ /* waitDMCUReadyForCmd */
++ do {
++ dm_delay_in_microseconds(dmcu->ctx,
++ dmcu_wait_reg_ready_interval);
++ regValue = REG_READ(MASTER_COMM_CNTL_REG);
++ dmcu_max_retry_on_wait_reg_ready--;
++ } while
++ /* expected value is 0, loop while not 0*/
++ ((MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK & regValue) &&
++ dmcu_max_retry_on_wait_reg_ready > 0);
++
++ /* setDMCUParam_Cmd */
++ if (enable)
++ REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0,
++ PSR_ENABLE);
++ else
++ REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0,
++ PSR_EXIT);
++
++ /* notifyDMCUMsg */
++ REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1);
++
++ for (retryCount = 0; retryCount <= 100; retryCount++) {
++ dce_get_dmcu_psr_state(dmcu, &psr_state);
++ if (enable) {
++ if (psr_state != 0)
++ break;
++ } else {
++ if (psr_state == 0)
++ break;
++ }
++ dm_delay_in_microseconds(dmcu->ctx, 10);
++ }
++}
++
++static void dce_dmcu_setup_psr(struct dmcu *dmcu,
++ struct core_link *link,
++ struct psr_context *psr_context)
++{
++ struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu);
++
++ unsigned int dmcu_max_retry_on_wait_reg_ready = 801;
++ unsigned int dmcu_wait_reg_ready_interval = 100;
++ unsigned int regValue;
++
++ union dce_dmcu_psr_config_data_reg1 masterCmdData1;
++ union dce_dmcu_psr_config_data_reg2 masterCmdData2;
++ union dce_dmcu_psr_config_data_reg3 masterCmdData3;
++
++ link->link_enc->funcs->psr_program_dp_dphy_fast_training(link->link_enc,
++ psr_context->psrExitLinkTrainingRequired);
++
++ /* Enable static screen interrupts for PSR supported display */
++ /* Disable the interrupt coming from other displays. */
++ REG_UPDATE_4(DMCU_INTERRUPT_TO_UC_EN_MASK,
++ STATIC_SCREEN1_INT_TO_UC_EN, 0,
++ STATIC_SCREEN2_INT_TO_UC_EN, 0,
++ STATIC_SCREEN3_INT_TO_UC_EN, 0,
++ STATIC_SCREEN4_INT_TO_UC_EN, 0);
++
++ switch (psr_context->controllerId) {
++ /* Driver uses case 1 for unconfigured */
++ case 1:
++ REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK,
++ STATIC_SCREEN1_INT_TO_UC_EN, 1);
++ break;
++ case 2:
++ REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK,
++ STATIC_SCREEN2_INT_TO_UC_EN, 1);
++ break;
++ case 3:
++ REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK,
++ STATIC_SCREEN3_INT_TO_UC_EN, 1);
++ break;
++ case 4:
++ REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK,
++ STATIC_SCREEN4_INT_TO_UC_EN, 1);
++ break;
++ case 5:
++ /* CZ/NL only has 4 CRTC!!
++ * really valid.
++ * There is no interrupt enable mask for these instances.
++ */
++ break;
++ case 6:
++ /* CZ/NL only has 4 CRTC!!
++ * These are here because they are defined in HW regspec,
++ * but not really valid. There is no interrupt enable mask
++ * for these instances.
++ */
++ break;
++ default:
++ REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK,
++ STATIC_SCREEN1_INT_TO_UC_EN, 1);
++ break;
++ }
++
++ link->link_enc->funcs->psr_program_secondary_packet(link->link_enc,
++ psr_context->sdpTransmitLineNumDeadline);
++
++ if (psr_context->psr_level.bits.SKIP_SMU_NOTIFICATION)
++ REG_UPDATE(SMU_INTERRUPT_CONTROL, DC_SMU_INT_ENABLE, 1);
++
++ /* waitDMCUReadyForCmd */
++ do {
++ dm_delay_in_microseconds(dmcu->ctx,
++ dmcu_wait_reg_ready_interval);
++ regValue = REG_READ(MASTER_COMM_CNTL_REG);
++ dmcu_max_retry_on_wait_reg_ready--;
++ } while
++ /* expected value is 0, loop while not 0*/
++ ((MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK & regValue) &&
++ dmcu_max_retry_on_wait_reg_ready > 0);
++
++ /* setDMCUParam_PSRHostConfigData */
++ masterCmdData1.u32All = 0;
++ masterCmdData1.bits.timehyst_frames = psr_context->timehyst_frames;
++ masterCmdData1.bits.hyst_lines = psr_context->hyst_lines;
++ masterCmdData1.bits.rfb_update_auto_en =
++ psr_context->rfb_update_auto_en;
++ masterCmdData1.bits.dp_port_num = psr_context->transmitterId;
++ masterCmdData1.bits.dcp_sel = psr_context->controllerId;
++ masterCmdData1.bits.phy_type = psr_context->phyType;
++ masterCmdData1.bits.frame_cap_ind =
++ psr_context->psrFrameCaptureIndicationReq;
++ masterCmdData1.bits.aux_chan = psr_context->channel;
++ masterCmdData1.bits.aux_repeat = psr_context->aux_repeats;
++ dm_write_reg(dmcu->ctx, REG(MASTER_COMM_DATA_REG1),
++ masterCmdData1.u32All);
++
++ masterCmdData2.u32All = 0;
++ masterCmdData2.bits.dig_fe = psr_context->engineId;
++ masterCmdData2.bits.dig_be = psr_context->transmitterId;
++ masterCmdData2.bits.skip_wait_for_pll_lock =
++ psr_context->skipPsrWaitForPllLock;
++ masterCmdData2.bits.frame_delay = psr_context->frame_delay;
++ masterCmdData2.bits.smu_phy_id = psr_context->smuPhyId;
++ masterCmdData2.bits.num_of_controllers =
++ psr_context->numberOfControllers;
++ dm_write_reg(dmcu->ctx, REG(MASTER_COMM_DATA_REG2),
++ masterCmdData2.u32All);
++
++ masterCmdData3.u32All = 0;
++ masterCmdData3.bits.psr_level = psr_context->psr_level.u32all;
++ dm_write_reg(dmcu->ctx, REG(MASTER_COMM_DATA_REG3),
++ masterCmdData3.u32All);
++
++ /* setDMCUParam_Cmd */
++ REG_UPDATE(MASTER_COMM_CMD_REG,
++ MASTER_COMM_CMD_REG_BYTE0, PSR_SET);
++
++ /* notifyDMCUMsg */
++ REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1);
++}
++
+ static const struct dmcu_funcs dce_funcs = {
+ .load_iram = dce_dmcu_load_iram,
++ .set_psr_enable = dce_dmcu_set_psr_enable,
++ .setup_psr = dce_dmcu_setup_psr,
+ };
+
+ static void dce_dmcu_construct(
+diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h
+index 33c1754..7dc2538 100644
+--- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h
++++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.h
+@@ -33,7 +33,16 @@
+ SR(DMCU_CTRL), \
+ SR(DMCU_RAM_ACCESS_CTRL), \
+ SR(DMCU_IRAM_WR_CTRL), \
+- SR(DMCU_IRAM_WR_DATA)
++ SR(DMCU_IRAM_WR_DATA), \
++ SR(MASTER_COMM_DATA_REG1), \
++ SR(MASTER_COMM_DATA_REG2), \
++ SR(MASTER_COMM_DATA_REG3), \
++ SR(MASTER_COMM_CMD_REG), \
++ SR(MASTER_COMM_CNTL_REG), \
++ SR(DMCU_IRAM_RD_CTRL), \
++ SR(DMCU_IRAM_RD_DATA), \
++ SR(DMCU_INTERRUPT_TO_UC_EN_MASK), \
++ SR(SMU_INTERRUPT_CONTROL)
+
+ #define DMCU_DCE110_COMMON_REG_LIST() \
+ DMCU_COMMON_REG_LIST_DCE_BASE(), \
+@@ -48,18 +57,41 @@
+ DMCU_SF(DMCU_RAM_ACCESS_CTRL, \
+ IRAM_HOST_ACCESS_EN, mask_sh), \
+ DMCU_SF(DMCU_RAM_ACCESS_CTRL, \
+- IRAM_WR_ADDR_AUTO_INC, mask_sh)
++ IRAM_WR_ADDR_AUTO_INC, mask_sh), \
++ DMCU_SF(MASTER_COMM_CMD_REG, \
++ MASTER_COMM_CMD_REG_BYTE0, mask_sh), \
++ DMCU_SF(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, mask_sh), \
++ DMCU_SF(DMCU_INTERRUPT_TO_UC_EN_MASK, \
++ STATIC_SCREEN1_INT_TO_UC_EN, mask_sh), \
++ DMCU_SF(DMCU_INTERRUPT_TO_UC_EN_MASK, \
++ STATIC_SCREEN2_INT_TO_UC_EN, mask_sh), \
++ DMCU_SF(DMCU_INTERRUPT_TO_UC_EN_MASK, \
++ STATIC_SCREEN3_INT_TO_UC_EN, mask_sh), \
++ DMCU_SF(DMCU_INTERRUPT_TO_UC_EN_MASK, \
++ STATIC_SCREEN4_INT_TO_UC_EN, mask_sh), \
++ DMCU_SF(SMU_INTERRUPT_CONTROL, DC_SMU_INT_ENABLE, mask_sh)
+
+ #define DMCU_MASK_SH_LIST_DCE110(mask_sh) \
+ DMCU_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \
+ DMCU_SF(DCI_MEM_PWR_STATUS, \
+- DMCU_IRAM_MEM_PWR_STATE, mask_sh)
++ DMCU_IRAM_MEM_PWR_STATE, mask_sh)
+
+ #define DMCU_REG_FIELD_LIST(type) \
+ type DMCU_IRAM_MEM_PWR_STATE; \
+ type IRAM_HOST_ACCESS_EN; \
+ type IRAM_WR_ADDR_AUTO_INC; \
+- type DMCU_ENABLE
++ type DMCU_ENABLE; \
++ type MASTER_COMM_CMD_REG_BYTE0; \
++ type MASTER_COMM_INTERRUPT; \
++ type DPHY_RX_FAST_TRAINING_CAPABLE; \
++ type DPHY_LOAD_BS_COUNT; \
++ type STATIC_SCREEN1_INT_TO_UC_EN; \
++ type STATIC_SCREEN2_INT_TO_UC_EN; \
++ type STATIC_SCREEN3_INT_TO_UC_EN; \
++ type STATIC_SCREEN4_INT_TO_UC_EN; \
++ type DP_SEC_GSP0_LINE_NUM; \
++ type DP_SEC_GSP0_PRIORITY; \
++ type DC_SMU_INT_ENABLE
+
+ struct dce_dmcu_shift {
+ DMCU_REG_FIELD_LIST(uint8_t);
+@@ -76,6 +108,16 @@ struct dce_dmcu_registers {
+ uint32_t DMU_MEM_PWR_CNTL;
+ uint32_t DMCU_IRAM_WR_CTRL;
+ uint32_t DMCU_IRAM_WR_DATA;
++
++ uint32_t MASTER_COMM_DATA_REG1;
++ uint32_t MASTER_COMM_DATA_REG2;
++ uint32_t MASTER_COMM_DATA_REG3;
++ uint32_t MASTER_COMM_CMD_REG;
++ uint32_t MASTER_COMM_CNTL_REG;
++ uint32_t DMCU_IRAM_RD_CTRL;
++ uint32_t DMCU_IRAM_RD_DATA;
++ uint32_t DMCU_INTERRUPT_TO_UC_EN_MASK;
++ uint32_t SMU_INTERRUPT_CONTROL;
+ };
+
+ struct dce_dmcu {
+@@ -85,6 +127,63 @@ struct dce_dmcu {
+ const struct dce_dmcu_mask *dmcu_mask;
+ };
+
++/*******************************************************************
++ * MASTER_COMM_DATA_REG1 Bit position Data
++ * 7:0 hyst_frames[7:0]
++ * 14:8 hyst_lines[6:0]
++ * 15 RFB_UPDATE_AUTO_EN
++ * 18:16 phy_num[2:0]
++ * 21:19 dcp_sel[2:0]
++ * 22 phy_type
++ * 23 frame_cap_ind
++ * 26:24 aux_chan[2:0]
++ * 30:27 aux_repeat[3:0]
++ * 31:31 reserved[31:31]
++ ******************************************************************/
++union dce_dmcu_psr_config_data_reg1 {
++ struct {
++ unsigned int timehyst_frames:8; /*[7:0]*/
++ unsigned int hyst_lines:7; /*[14:8]*/
++ unsigned int rfb_update_auto_en:1; /*[15:15]*/
++ unsigned int dp_port_num:3; /*[18:16]*/
++ unsigned int dcp_sel:3; /*[21:19]*/
++ unsigned int phy_type:1; /*[22:22]*/
++ unsigned int frame_cap_ind:1; /*[23:23]*/
++ unsigned int aux_chan:3; /*[26:24]*/
++ unsigned int aux_repeat:4; /*[30:27]*/
++ unsigned int reserved:1; /*[31:31]*/
++ } bits;
++ unsigned int u32All;
++};
++
++/*******************************************************************
++ * MASTER_COMM_DATA_REG2
++ *******************************************************************/
++union dce_dmcu_psr_config_data_reg2 {
++ struct {
++ unsigned int dig_fe:3; /*[2:0]*/
++ unsigned int dig_be:3; /*[5:3]*/
++ unsigned int skip_wait_for_pll_lock:1; /*[6:6]*/
++ unsigned int reserved:9; /*[15:7]*/
++ unsigned int frame_delay:8; /*[23:16]*/
++ unsigned int smu_phy_id:4; /*[27:24]*/
++ unsigned int num_of_controllers:4; /*[31:28]*/
++ } bits;
++ unsigned int u32All;
++};
++
++/*******************************************************************
++ * MASTER_COMM_DATA_REG3
++ *******************************************************************/
++union dce_dmcu_psr_config_data_reg3 {
++ struct {
++ unsigned int psr_level:16; /*[15:0]*/
++ unsigned int link_rate:4; /*[19:16]*/
++ unsigned int reserved:12; /*[31:20]*/
++ } bits;
++ unsigned int u32All;
++};
++
+ struct dmcu *dce_dmcu_create(
+ struct dc_context *ctx,
+ const struct dce_dmcu_registers *regs,
+diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c
+index 305a9d8..a1d35ad 100644
+--- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c
++++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c
+@@ -95,14 +95,6 @@
+ /* For current ASICs pixel clock - 600MHz */
+ #define MAX_ENCODER_CLOCK 600000
+
+-/* PSR related commands */
+-#define PSR_ENABLE 0x20
+-#define PSR_EXIT 0x21
+-#define PSR_SET 0x23
+-
+-/*TODO: Used for psr wakeup for set backlight level*/
+-static unsigned int psr_crtc_offset;
+-
+ enum {
+ DP_MST_UPDATE_MAX_RETRY = 50
+ };
+@@ -126,8 +118,9 @@ static const struct link_encoder_funcs dce110_lnk_enc_funcs = {
+ .dp_set_phy_pattern = dce110_link_encoder_dp_set_phy_pattern,
+ .update_mst_stream_allocation_table =
+ dce110_link_encoder_update_mst_stream_allocation_table,
+- .set_dmcu_psr_enable = dce110_link_encoder_set_dmcu_psr_enable,
+- .setup_dmcu_psr = dce110_link_encoder_setup_dmcu_psr,
++ .psr_program_dp_dphy_fast_training =
++ dce110_psr_program_dp_dphy_fast_training,
++ .psr_program_secondary_packet = dce110_psr_program_secondary_packet,
+ .backlight_control = dce110_link_encoder_edp_backlight_control,
+ .power_control = dce110_link_encoder_edp_power_control,
+ .connect_dig_be_to_fe = dce110_link_encoder_connect_dig_be_to_fe,
+@@ -136,7 +129,6 @@ static const struct link_encoder_funcs dce110_lnk_enc_funcs = {
+ .destroy = dce110_link_encoder_destroy
+ };
+
+-
+ static enum bp_result link_transmitter_control(
+ struct dce110_link_encoder *enc110,
+ struct bp_transmitter_control *cntl)
+@@ -721,6 +713,40 @@ static bool is_panel_backlight_on(struct dce110_link_encoder *enc110)
+ return value;
+ }
+
++void dce110_psr_program_dp_dphy_fast_training(struct link_encoder *enc,
++ bool exit_link_training_required)
++{
++ struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
++
++ if (exit_link_training_required)
++ REG_UPDATE(DP_DPHY_FAST_TRAINING,
++ DPHY_RX_FAST_TRAINING_CAPABLE, 1);
++ else {
++ REG_UPDATE(DP_DPHY_FAST_TRAINING,
++ DPHY_RX_FAST_TRAINING_CAPABLE, 0);
++ /*In DCE 11, we are able to pre-program a Force SR register
++ * to be able to trigger SR symbol after 5 idle patterns
++ * transmitted. Upon PSR Exit, DMCU can trigger
++ * DPHY_LOAD_BS_COUNT_START = 1. Upon writing 1 to
++ * DPHY_LOAD_BS_COUNT_START and the internal counter
++ * reaches DPHY_LOAD_BS_COUNT, the next BS symbol will be
++ * replaced by SR symbol once.
++ */
++
++ REG_UPDATE(DP_DPHY_BS_SR_SWAP_CNTL, DPHY_LOAD_BS_COUNT, 0x5);
++ }
++}
++
++void dce110_psr_program_secondary_packet(struct link_encoder *enc,
++ unsigned int sdp_transmit_line_num_deadline)
++{
++ struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
++
++ REG_UPDATE_2(DP_SEC_CNTL1,
++ DP_SEC_GSP0_LINE_NUM, sdp_transmit_line_num_deadline,
++ DP_SEC_GSP0_PRIORITY, 1);
++}
++
+ /*todo: cloned in stream enc, fix*/
+ /*
+ * @brief
+@@ -1560,238 +1586,6 @@ void dce110_link_encoder_update_mst_stream_allocation_table(
+ } while (retries < DP_MST_UPDATE_MAX_RETRY);
+ }
+
+-static void get_dmcu_psr_state(struct link_encoder *enc, uint32_t *psr_state)
+-{
+- struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
+- struct dc_context *ctx = enc110->base.ctx;
+-
+- uint32_t count = 0;
+- uint32_t psrStateOffset = 0xf0;
+- uint32_t value = -1;
+-
+- /* Enable write access to IRAM */
+- REG_UPDATE(DMCU_RAM_ACCESS_CTRL, IRAM_HOST_ACCESS_EN, 1);
+-
+- while (REG(DCI_MEM_PWR_STATUS) && value != 0 && count++ < 10) {
+- dm_delay_in_microseconds(ctx, 2);
+- REG_GET(DCI_MEM_PWR_STATUS, DMCU_IRAM_MEM_PWR_STATE, &value);
+- }
+- while (REG(DMU_MEM_PWR_CNTL) && value != 0 && count++ < 10) {
+- dm_delay_in_microseconds(ctx, 2);
+- REG_GET(DMU_MEM_PWR_CNTL, DMCU_IRAM_MEM_PWR_STATE, &value);
+- }
+-
+- /* Write address to IRAM_RD_ADDR in DMCU_IRAM_RD_CTRL */
+- REG_WRITE(DMCU_IRAM_RD_CTRL, psrStateOffset);
+-
+- /* Read data from IRAM_RD_DATA in DMCU_IRAM_RD_DATA*/
+- *psr_state = REG_READ(DMCU_IRAM_RD_DATA);
+-
+- /* Disable write access to IRAM after finished using IRAM
+- * in order to allow dynamic sleep state
+- */
+- REG_UPDATE(DMCU_RAM_ACCESS_CTRL, IRAM_HOST_ACCESS_EN, 0);
+-}
+-
+-void dce110_link_encoder_set_dmcu_psr_enable(struct link_encoder *enc,
+- bool enable)
+-{
+- struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
+- struct dc_context *ctx = enc110->base.ctx;
+-
+- unsigned int dmcu_max_retry_on_wait_reg_ready = 801;
+- unsigned int dmcu_wait_reg_ready_interval = 100;
+-
+- unsigned int regValue;
+-
+- unsigned int retryCount;
+- uint32_t psr_state = 0;
+-
+- /* waitDMCUReadyForCmd */
+- do {
+- dm_delay_in_microseconds(ctx, dmcu_wait_reg_ready_interval);
+- regValue = REG_READ(MASTER_COMM_CNTL_REG);
+- dmcu_max_retry_on_wait_reg_ready--;
+- } while
+- /* expected value is 0, loop while not 0*/
+- ((MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK & regValue) &&
+- dmcu_max_retry_on_wait_reg_ready > 0);
+-
+- /* setDMCUParam_Cmd */
+- if (enable)
+- REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, PSR_ENABLE);
+- else
+- REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, PSR_EXIT);
+-
+- /* notifyDMCUMsg */
+- REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1);
+-
+- for (retryCount = 0; retryCount <= 100; retryCount++) {
+- get_dmcu_psr_state(enc, &psr_state);
+- if (enable) {
+- if (psr_state != 0)
+- break;
+- } else {
+- if (psr_state == 0)
+- break;
+- }
+- dm_delay_in_microseconds(ctx, 10);
+- }
+-}
+-
+-void dce110_link_encoder_setup_dmcu_psr(struct link_encoder *enc,
+- struct psr_dmcu_context *psr_context)
+-{
+- struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
+- struct dc_context *ctx = enc110->base.ctx;
+-
+- unsigned int dmcu_max_retry_on_wait_reg_ready = 801;
+- unsigned int dmcu_wait_reg_ready_interval = 100;
+- unsigned int regValue;
+-
+- union dce110_dmcu_psr_config_data_reg1 masterCmdData1;
+- union dce110_dmcu_psr_config_data_reg2 masterCmdData2;
+- union dce110_dmcu_psr_config_data_reg3 masterCmdData3;
+-
+- if (psr_context->psrExitLinkTrainingRequired)
+- REG_UPDATE(DP_DPHY_FAST_TRAINING, DPHY_RX_FAST_TRAINING_CAPABLE, 1);
+- else {
+- REG_UPDATE(DP_DPHY_FAST_TRAINING, DPHY_RX_FAST_TRAINING_CAPABLE, 0);
+- /*In DCE 11, we are able to pre-program a Force SR register
+- * to be able to trigger SR symbol after 5 idle patterns
+- * transmitted. Upon PSR Exit, DMCU can trigger
+- * DPHY_LOAD_BS_COUNT_START = 1. Upon writing 1 to
+- * DPHY_LOAD_BS_COUNT_START and the internal counter
+- * reaches DPHY_LOAD_BS_COUNT, the next BS symbol will be
+- * replaced by SR symbol once.
+- */
+-
+- REG_UPDATE(DP_DPHY_BS_SR_SWAP_CNTL, DPHY_LOAD_BS_COUNT, 0x5);
+- }
+-
+- /* Enable static screen interrupts for PSR supported display */
+- /* Disable the interrupt coming from other displays. */
+- REG_UPDATE_4(DMCU_INTERRUPT_TO_UC_EN_MASK,
+- STATIC_SCREEN1_INT_TO_UC_EN, 0,
+- STATIC_SCREEN2_INT_TO_UC_EN, 0,
+- STATIC_SCREEN3_INT_TO_UC_EN, 0,
+- STATIC_SCREEN4_INT_TO_UC_EN, 0);
+-
+- switch (psr_context->controllerId) {
+- /* Driver uses case 1 for unconfigured */
+- case 1:
+- psr_crtc_offset = mmCRTC0_CRTC_STATIC_SCREEN_CONTROL -
+- mmCRTC0_CRTC_STATIC_SCREEN_CONTROL;
+-
+- REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK,
+- STATIC_SCREEN1_INT_TO_UC_EN, 1);
+- break;
+- case 2:
+- psr_crtc_offset = mmCRTC1_CRTC_STATIC_SCREEN_CONTROL -
+- mmCRTC0_CRTC_STATIC_SCREEN_CONTROL;
+-
+- REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK,
+- STATIC_SCREEN2_INT_TO_UC_EN, 1);
+- break;
+- case 3:
+- psr_crtc_offset = mmCRTC2_CRTC_STATIC_SCREEN_CONTROL -
+- mmCRTC0_CRTC_STATIC_SCREEN_CONTROL;
+-
+- REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK,
+- STATIC_SCREEN3_INT_TO_UC_EN, 1);
+- break;
+- case 4:
+- psr_crtc_offset = mmCRTC3_CRTC_STATIC_SCREEN_CONTROL -
+- mmCRTC0_CRTC_STATIC_SCREEN_CONTROL;
+-
+- REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK,
+- STATIC_SCREEN4_INT_TO_UC_EN, 1);
+- break;
+- case 5:
+- psr_crtc_offset = mmCRTC4_CRTC_STATIC_SCREEN_CONTROL -
+- mmCRTC0_CRTC_STATIC_SCREEN_CONTROL;
+- /* CZ/NL only has 4 CRTC!!
+- * really valid.
+- * There is no interrupt enable mask for these instances.
+- */
+- break;
+- case 6:
+- psr_crtc_offset = mmCRTC5_CRTC_STATIC_SCREEN_CONTROL -
+- mmCRTC0_CRTC_STATIC_SCREEN_CONTROL;
+- /* CZ/NL only has 4 CRTC!!
+- * These are here because they are defined in HW regspec,
+- * but not really valid. There is no interrupt enable mask
+- * for these instances.
+- */
+- break;
+- default:
+- psr_crtc_offset = mmCRTC0_CRTC_STATIC_SCREEN_CONTROL -
+- mmCRTC0_CRTC_STATIC_SCREEN_CONTROL;
+-
+- REG_UPDATE(DMCU_INTERRUPT_TO_UC_EN_MASK,
+- STATIC_SCREEN1_INT_TO_UC_EN, 1);
+- break;
+- }
+-
+- REG_UPDATE_2(DP_SEC_CNTL1,
+- DP_SEC_GSP0_LINE_NUM, psr_context->sdpTransmitLineNumDeadline,
+- DP_SEC_GSP0_PRIORITY, 1);
+-
+- if (psr_context->psr_level.bits.SKIP_SMU_NOTIFICATION) {
+- REG_UPDATE(SMU_INTERRUPT_CONTROL, DC_SMU_INT_ENABLE, 1);
+- }
+-
+- /* waitDMCUReadyForCmd */
+- do {
+- dm_delay_in_microseconds(ctx, dmcu_wait_reg_ready_interval);
+- regValue = REG_READ(MASTER_COMM_CNTL_REG);
+- dmcu_max_retry_on_wait_reg_ready--;
+- } while
+- /* expected value is 0, loop while not 0*/
+- ((MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK & regValue) &&
+- dmcu_max_retry_on_wait_reg_ready > 0);
+-
+- /* setDMCUParam_PSRHostConfigData */
+- masterCmdData1.u32All = 0;
+- masterCmdData1.bits.timehyst_frames = psr_context->timehyst_frames;
+- masterCmdData1.bits.hyst_lines = psr_context->hyst_lines;
+- masterCmdData1.bits.rfb_update_auto_en =
+- psr_context->rfb_update_auto_en;
+- masterCmdData1.bits.dp_port_num = psr_context->transmitterId;
+- masterCmdData1.bits.dcp_sel = psr_context->controllerId;
+- masterCmdData1.bits.phy_type = psr_context->phyType;
+- masterCmdData1.bits.frame_cap_ind =
+- psr_context->psrFrameCaptureIndicationReq;
+- masterCmdData1.bits.aux_chan = psr_context->channel;
+- masterCmdData1.bits.aux_repeat = psr_context->aux_repeats;
+- dm_write_reg(ctx, REG(MASTER_COMM_DATA_REG1),
+- masterCmdData1.u32All);
+-
+- masterCmdData2.u32All = 0;
+- masterCmdData2.bits.dig_fe = psr_context->engineId;
+- masterCmdData2.bits.dig_be = psr_context->transmitterId;
+- masterCmdData2.bits.skip_wait_for_pll_lock =
+- psr_context->skipPsrWaitForPllLock;
+- masterCmdData2.bits.frame_delay = psr_context->frame_delay;
+- masterCmdData2.bits.smu_phy_id = psr_context->smuPhyId;
+- masterCmdData2.bits.num_of_controllers =
+- psr_context->numberOfControllers;
+- dm_write_reg(ctx, REG(MASTER_COMM_DATA_REG2),
+- masterCmdData2.u32All);
+-
+- masterCmdData3.u32All = 0;
+- masterCmdData3.bits.psr_level = psr_context->psr_level.u32all;
+- dm_write_reg(ctx, REG(MASTER_COMM_DATA_REG3),
+- masterCmdData3.u32All);
+-
+- /* setDMCUParam_Cmd */
+- REG_UPDATE(MASTER_COMM_CMD_REG,
+- MASTER_COMM_CMD_REG_BYTE0, PSR_SET);
+-
+- /* notifyDMCUMsg */
+- REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1);
+-}
+-
+ void dce110_link_encoder_connect_dig_be_to_fe(
+ struct link_encoder *enc,
+ enum engine_id engine,
+diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h
+index d382a68..f337d60 100644
+--- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h
++++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h
+@@ -39,11 +39,6 @@
+ SRI(DC_HPD_CONTROL, HPD, id)
+
+ #define LE_COMMON_REG_LIST_BASE(id) \
+- SR(MASTER_COMM_DATA_REG1), \
+- SR(MASTER_COMM_DATA_REG2), \
+- SR(MASTER_COMM_DATA_REG3), \
+- SR(MASTER_COMM_CMD_REG), \
+- SR(MASTER_COMM_CNTL_REG), \
+ SR(LVTMA_PWRSEQ_CNTL), \
+ SR(LVTMA_PWRSEQ_STATE), \
+ SR(DMCU_RAM_ACCESS_CTRL), \
+@@ -149,62 +144,6 @@ struct dce110_link_encoder {
+ const struct dce110_link_enc_hpd_registers *hpd_regs;
+ };
+
+-/*******************************************************************
+-* MASTER_COMM_DATA_REG1 Bit position Data
+-* 7:0 hyst_frames[7:0]
+-* 14:8 hyst_lines[6:0]
+-* 15 RFB_UPDATE_AUTO_EN
+-* 18:16 phy_num[2:0]
+-* 21:19 dcp_sel[2:0]
+-* 22 phy_type
+-* 23 frame_cap_ind
+-* 26:24 aux_chan[2:0]
+-* 30:27 aux_repeat[3:0]
+-* 31:31 reserved[31:31]
+-*******************************************************************/
+-union dce110_dmcu_psr_config_data_reg1 {
+- struct {
+- unsigned int timehyst_frames:8; /*[7:0]*/
+- unsigned int hyst_lines:7; /*[14:8]*/
+- unsigned int rfb_update_auto_en:1; /*[15:15]*/
+- unsigned int dp_port_num:3; /*[18:16]*/
+- unsigned int dcp_sel:3; /*[21:19]*/
+- unsigned int phy_type:1; /*[22:22]*/
+- unsigned int frame_cap_ind:1; /*[23:23]*/
+- unsigned int aux_chan:3; /*[26:24]*/
+- unsigned int aux_repeat:4; /*[30:27]*/
+- unsigned int reserved:1; /*[31:31]*/
+- } bits;
+- unsigned int u32All;
+-};
+-
+-/*******************************************************************
+-* MASTER_COMM_DATA_REG2
+-*******************************************************************/
+-union dce110_dmcu_psr_config_data_reg2 {
+- struct {
+- unsigned int dig_fe:3; /*[2:0]*/
+- unsigned int dig_be:3; /*[5:3]*/
+- unsigned int skip_wait_for_pll_lock:1; /*[6:6]*/
+- unsigned int reserved:9; /*[15:7]*/
+- unsigned int frame_delay:8; /*[23:16]*/
+- unsigned int smu_phy_id:4; /*[27:24]*/
+- unsigned int num_of_controllers:4; /*[31:28]*/
+- } bits;
+- unsigned int u32All;
+-};
+-
+-/*******************************************************************
+-* MASTER_COMM_DATA_REG3
+-*******************************************************************/
+-union dce110_dmcu_psr_config_data_reg3 {
+- struct {
+- unsigned int psr_level:16; /*[15:0]*/
+- unsigned int link_rate:4; /*[19:16]*/
+- unsigned int reserved:12; /*[31:20]*/
+- } bits;
+- unsigned int u32All;
+-};
+
+ bool dce110_link_encoder_construct(
+ struct dce110_link_encoder *enc110,
+@@ -290,12 +229,6 @@ void dce110_link_encoder_update_mst_stream_allocation_table(
+ struct link_encoder *enc,
+ const struct link_mst_stream_allocation_table *table);
+
+-void dce110_link_encoder_set_dmcu_psr_enable(
+- struct link_encoder *enc, bool enable);
+-
+-void dce110_link_encoder_setup_dmcu_psr(struct link_encoder *enc,
+- struct psr_dmcu_context *psr_context);
+-
+ void dce110_link_encoder_edp_backlight_control(
+ struct link_encoder *enc,
+ bool enable);
+@@ -317,4 +250,10 @@ void dce110_link_encoder_enable_hpd(struct link_encoder *enc);
+
+ void dce110_link_encoder_disable_hpd(struct link_encoder *enc);
+
++void dce110_psr_program_dp_dphy_fast_training(struct link_encoder *enc,
++ bool exit_link_training_required);
++
++void dce110_psr_program_secondary_packet(struct link_encoder *enc,
++ unsigned int sdp_transmit_line_num_deadline);
++
+ #endif /* __DC_LINK_ENCODER__DCE110_H__ */
+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 62012f0..656cfdc 100644
+--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h
++++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h
+@@ -37,6 +37,10 @@ struct dmcu_funcs {
+ unsigned int start_offset,
+ const char *src,
+ unsigned int bytes);
++ void (*set_psr_enable)(struct dmcu *dmcu, bool enable);
++ void (*setup_psr)(struct dmcu *dmcu,
++ struct core_link *link,
++ struct psr_context *psr_context);
+ };
+
+ #endif
+diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h
+index 7b37b96..7307f96 100644
+--- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h
++++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h
+@@ -116,7 +116,7 @@ union psr_sink_psr_status {
+ unsigned char raw;
+ };
+
+-struct psr_dmcu_context {
++struct psr_context {
+ /* ddc line */
+ enum channel_id channel;
+ /* Transmitter id */
+@@ -220,9 +220,10 @@ struct link_encoder_funcs {
+ void (*update_mst_stream_allocation_table)(
+ struct link_encoder *enc,
+ const struct link_mst_stream_allocation_table *table);
+- void (*set_dmcu_psr_enable)(struct link_encoder *enc, bool enable);
+- void (*setup_dmcu_psr)(struct link_encoder *enc,
+- struct psr_dmcu_context *psr_context);
++ void (*psr_program_dp_dphy_fast_training)(struct link_encoder *enc,
++ bool exit_link_training_required);
++ void (*psr_program_secondary_packet)(struct link_encoder *enc,
++ unsigned int sdp_transmit_line_num_deadline);
+ void (*backlight_control) (struct link_encoder *enc,
+ bool enable);
+ void (*power_control) (struct link_encoder *enc,
+--
+2.7.4
+