From 20e1ae80f26a2a86516da431e51e031c80e75a79 Mon Sep 17 00:00:00 2001 From: Amy Zhang 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 Acked-by: Harry Wentland Reviewed-by: Tony Cheng Signed-off-by: Alex Deucher --- 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