diff options
Diffstat (limited to 'meta-v1000/recipes-kernel/linux/linux-yocto-4.14.71/0233-drm-amd-display-DMCU-PSR-Refactor.patch')
-rw-r--r-- | meta-v1000/recipes-kernel/linux/linux-yocto-4.14.71/0233-drm-amd-display-DMCU-PSR-Refactor.patch | 933 |
1 files changed, 933 insertions, 0 deletions
diff --git a/meta-v1000/recipes-kernel/linux/linux-yocto-4.14.71/0233-drm-amd-display-DMCU-PSR-Refactor.patch b/meta-v1000/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-v1000/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 + |