Commit 3548f073 authored by Amy Zhang's avatar Amy Zhang Committed by Alex Deucher
Browse files

drm/amd/display: DMCU PSR Refactor



- Move PSR programming from link encoder to dmcu

Signed-off-by: default avatarAmy Zhang <Amy.Zhang@amd.com>
Acked-by: default avatarHarry Wentland <Harry.Wentland@amd.com>
Reviewed-by: default avatarTony Cheng <Tony.Cheng@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent d5b4f2bc
Loading
Loading
Loading
Loading
+13 −8
Original line number Diff line number Diff line
@@ -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;
+208 −0
Original line number Diff line number Diff line
@@ -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(
+103 −4
Original line number Diff line number Diff line
@@ -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,7 +57,19 @@
	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), \
@@ -59,7 +80,18 @@
	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,
+37 −243
Original line number Diff line number Diff line
@@ -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,
+6 −67

File changed.

Preview size limit exceeded, changes collapsed.

Loading