Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 87401969 authored by Andrew Jiang's avatar Andrew Jiang Committed by Alex Deucher
Browse files

drm/amd/display: Move power control from link encoder to hwsequencer



A recent commit moved the backlight control code along with the register
defines, but did not move the power control code. This along with
remnant fields in the dce110_link_enc_registers struct made it so that
the code still compiled, but any attempts to access the
LVTMA_PWRSEQ_STATE register led to reading from an address of 0. This
patch corrects that.

Also, rename blacklight_control to edp_backlight_control (Typo fix).

Signed-off-by: default avatarAndrew Jiang <Andrew.Jiang@amd.com>
Reviewed-by: default avatarTony Cheng <Tony.Cheng@amd.com>
Acked-by: default avatarHarry Wentland <Harry.Wentland@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent b87d78d6
Loading
Loading
Loading
Loading
+9 −8
Original line number Diff line number Diff line
@@ -78,14 +78,15 @@ static void destruct(struct dc_link *link)
		dc_sink_release(link->remote_sinks[i]);
}

static struct gpio *get_hpd_gpio(const struct dc_link *link)
struct gpio *get_hpd_gpio(struct dc_bios *dcb,
		struct graphics_object_id link_id,
		struct gpio_service *gpio_service)
{
	enum bp_result bp_result;
	struct dc_bios *dcb = link->ctx->dc_bios;
	struct graphics_object_hpd_info hpd_info;
	struct gpio_pin_info pin_info;

	if (dcb->funcs->get_hpd_info(dcb, link->link_id, &hpd_info) != BP_RESULT_OK)
	if (dcb->funcs->get_hpd_info(dcb, link_id, &hpd_info) != BP_RESULT_OK)
		return NULL;

	bp_result = dcb->funcs->get_gpio_pin_info(dcb,
@@ -97,7 +98,7 @@ static struct gpio *get_hpd_gpio(const struct dc_link *link)
	}

	return dal_gpio_service_create_irq(
		link->ctx->gpio_service,
		gpio_service,
		pin_info.offset,
		pin_info.mask);
}
@@ -153,7 +154,7 @@ static bool program_hpd_filter(
	}

	/* Obtain HPD handle */
	hpd = get_hpd_gpio(link);
	hpd = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service);

	if (!hpd)
		return result;
@@ -186,7 +187,7 @@ static bool detect_sink(struct dc_link *link, enum dc_connection_type *type)
	struct gpio *hpd_pin;

	/* todo: may need to lock gpio access */
	hpd_pin = get_hpd_gpio(link);
	hpd_pin = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service);
	if (hpd_pin == NULL)
		goto hpd_gpio_failure;

@@ -795,7 +796,7 @@ static enum hpd_source_id get_hpd_line(
	struct gpio *hpd;
	enum hpd_source_id hpd_id = HPD_SOURCEID_UNKNOWN;

	hpd = get_hpd_gpio(link);
	hpd = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service);

	if (hpd) {
		switch (dal_irq_get_source(hpd)) {
@@ -965,7 +966,7 @@ static bool construct(
		goto create_fail;
	}

	hpd_gpio = get_hpd_gpio(link);
	hpd_gpio = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service);

	if (hpd_gpio != NULL)
		link->irq_source_hpd = dal_irq_get_source(hpd_gpio);
+4 −4
Original line number Diff line number Diff line
@@ -89,12 +89,12 @@ void dp_enable_link_phy(

	if (dc_is_dp_sst_signal(signal)) {
		if (signal == SIGNAL_TYPE_EDP) {
			link_enc->funcs->power_control(link_enc, true);
			link->dc->hwss.edp_power_control(link->link_enc, true);
			link_enc->funcs->enable_dp_output(
						link_enc,
						link_settings,
						clock_source);
			link->dc->hwss.backlight_control(link, true);
			link->dc->hwss.edp_backlight_control(link, true);
		} else
			link_enc->funcs->enable_dp_output(
						link_enc,
@@ -138,10 +138,10 @@ void dp_disable_link_phy(struct dc_link *link, enum signal_type signal)
		dp_receiver_power_ctrl(link, false);

	if (signal == SIGNAL_TYPE_EDP) {
		link->dc->hwss.backlight_control(link, false);
		link->dc->hwss.edp_backlight_control(link, false);
		edp_receiver_ready_T9(link);
		link->link_enc->funcs->disable_output(link->link_enc, signal, link);
		link->link_enc->funcs->power_control(link->link_enc, false);
		link->dc->hwss.edp_power_control(link->link_enc, false);
	} else
		link->link_enc->funcs->disable_output(link->link_enc, signal, link);

+13 −5
Original line number Diff line number Diff line
@@ -391,23 +391,27 @@ struct dce_hwseq_registers {
	HWS_SF(BLND_, V_UPDATE_LOCK, BLND_DCP_GRPH_SURF_V_UPDATE_LOCK, mask_sh),\
	HWS_SF(BLND_, CONTROL, BLND_MODE, mask_sh),\
	HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh),\
	HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh),\
	HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_)

#define HWSEQ_DCE10_MASK_SH_LIST(mask_sh)\
	HWSEQ_DCEF_MASK_SH_LIST(mask_sh, DCFE_),\
	HWSEQ_BLND_MASK_SH_LIST(mask_sh, BLND_),\
	HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_), \
	HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh)
	HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh), \
	HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh)

#define HWSEQ_DCE11_MASK_SH_LIST(mask_sh)\
	HWSEQ_DCE10_MASK_SH_LIST(mask_sh),\
	SF(DCFEV_CLOCK_CONTROL, DCFEV_CLOCK_ENABLE, mask_sh),\
	HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh),\
	HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh),\
	HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_)

#define HWSEQ_DCE112_MASK_SH_LIST(mask_sh)\
	HWSEQ_DCE10_MASK_SH_LIST(mask_sh),\
	HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh),\
	HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh),\
	HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_)

#define HWSEQ_GFX9_DCHUB_MASK_SH_LIST(mask_sh)\
@@ -416,7 +420,8 @@ struct dce_hwseq_registers {
	SF(DCHUB_AGP_BASE, AGP_BASE, mask_sh),\
	SF(DCHUB_AGP_BOT, AGP_BOT, mask_sh),\
	SF(DCHUB_AGP_TOP, AGP_TOP, mask_sh), \
	HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh)
	HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh), \
	HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh)

#define HWSEQ_DCE12_MASK_SH_LIST(mask_sh)\
	HWSEQ_DCEF_MASK_SH_LIST(mask_sh, DCFE0_DCFE_),\
@@ -424,7 +429,8 @@ struct dce_hwseq_registers {
	HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_),\
	HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_),\
	HWSEQ_GFX9_DCHUB_MASK_SH_LIST(mask_sh), \
	HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh)
	HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh), \
	HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh)

#define HWSEQ_DCN_MASK_SH_LIST(mask_sh)\
	HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, OTG0_),\
@@ -489,7 +495,8 @@ struct dce_hwseq_registers {
	HWS_SF(, DOMAIN6_PG_STATUS, DOMAIN6_PGFSM_PWR_STATUS, mask_sh), \
	HWS_SF(, DOMAIN7_PG_STATUS, DOMAIN7_PGFSM_PWR_STATUS, mask_sh), \
	HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \
	HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh)
	HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh), \
	HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh)

#define HWSEQ_REG_FIELD_LIST(type) \
	type DCFE_CLOCK_ENABLE; \
@@ -520,7 +527,8 @@ struct dce_hwseq_registers {
	type LOGICAL_ADDR; \
	type ENABLE_L1_TLB;\
	type SYSTEM_ACCESS_MODE;\
	type LVTMA_BLON;
	type LVTMA_BLON;\
	type LVTMA_PWRSEQ_TARGET_STATE_R;

#define HWSEQ_DCN_REG_FIELD_LIST(type) \
	type VUPDATE_NO_LOCK_EVENT_CLEAR; \
+2 −169
Original line number Diff line number Diff line
@@ -82,13 +82,6 @@
#define DCE110_DIG_FE_SOURCE_SELECT_DIGF 0x20
#define DCE110_DIG_FE_SOURCE_SELECT_DIGG 0x40

/* all values are in milliseconds */
/* For eDP, after power-up/power/down,
 * 300/500 msec max. delay from LCDVCC to black video generation */
#define PANEL_POWER_UP_TIMEOUT 300
#define PANEL_POWER_DOWN_TIMEOUT 500
#define HPD_CHECK_INTERVAL 10

/* Minimum pixel clock, in KHz. For TMDS signal is 25.00 MHz */
#define TMDS_MIN_PIXEL_CLOCK 25000
/* Maximum pixel clock, in KHz. For TMDS signal is 165.00 MHz */
@@ -122,7 +115,6 @@ static const struct link_encoder_funcs dce110_lnk_enc_funcs = {
	.psr_program_dp_dphy_fast_training =
			dce110_psr_program_dp_dphy_fast_training,
	.psr_program_secondary_packet = dce110_psr_program_secondary_packet,
	.power_control = dce110_link_encoder_edp_power_control,
	.connect_dig_be_to_fe = dce110_link_encoder_connect_dig_be_to_fe,
	.enable_hpd = dce110_link_encoder_enable_hpd,
	.disable_hpd = dce110_link_encoder_disable_hpd,
@@ -492,165 +484,6 @@ static void configure_encoder(
	REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_ADVANCE, 1);
}

static bool is_panel_powered_on(struct dce110_link_encoder *enc110)
{
	bool ret;
	uint32_t value;

	REG_GET(LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, &value);
	ret = value;

	return ret == 1;
}


/* TODO duplicate of dc_link.c version */
static struct gpio *get_hpd_gpio(const struct link_encoder *enc)
{
	enum bp_result bp_result;
	struct dc_bios *dcb = enc->ctx->dc_bios;
	struct graphics_object_hpd_info hpd_info;
	struct gpio_pin_info pin_info;

	if (dcb->funcs->get_hpd_info(dcb, enc->connector, &hpd_info) != BP_RESULT_OK)
		return NULL;

	bp_result = dcb->funcs->get_gpio_pin_info(dcb,
		hpd_info.hpd_int_gpio_uid, &pin_info);

	if (bp_result != BP_RESULT_OK) {
		ASSERT(bp_result == BP_RESULT_NORECORD);
		return NULL;
	}

	return dal_gpio_service_create_irq(
		enc->ctx->gpio_service,
		pin_info.offset,
		pin_info.mask);
}

/*
 * @brief
 * eDP only.
 */
static void link_encoder_edp_wait_for_hpd_ready(
	struct dce110_link_encoder *enc110,
	bool power_up)
{
	struct dc_context *ctx = enc110->base.ctx;
	struct graphics_object_id connector = enc110->base.connector;
	struct gpio *hpd;
	bool edp_hpd_high = false;
	uint32_t time_elapsed = 0;
	uint32_t timeout = power_up ?
		PANEL_POWER_UP_TIMEOUT : PANEL_POWER_DOWN_TIMEOUT;

	if (dal_graphics_object_id_get_connector_id(connector) !=
		CONNECTOR_ID_EDP) {
		BREAK_TO_DEBUGGER();
		return;
	}

	if (!power_up)
		/* from KV, we will not HPD low after turning off VCC -
		 * instead, we will check the SW timer in power_up(). */
		return;

	/* when we power on/off the eDP panel,
	 * we need to wait until SENSE bit is high/low */

	/* obtain HPD */
	/* TODO what to do with this? */
	hpd = get_hpd_gpio(&enc110->base);

	if (!hpd) {
		BREAK_TO_DEBUGGER();
		return;
	}

	dal_gpio_open(hpd, GPIO_MODE_INTERRUPT);

	/* wait until timeout or panel detected */

	do {
		uint32_t detected = 0;

		dal_gpio_get_value(hpd, &detected);

		if (!(detected ^ power_up)) {
			edp_hpd_high = true;
			break;
		}

		msleep(HPD_CHECK_INTERVAL);

		time_elapsed += HPD_CHECK_INTERVAL;
	} while (time_elapsed < timeout);

	dal_gpio_close(hpd);

	dal_gpio_destroy_irq(&hpd);

	if (false == edp_hpd_high) {
		dm_logger_write(ctx->logger, LOG_ERROR,
				"%s: wait timed out!\n", __func__);
	}
}

/*
 * @brief
 * eDP only. Control the power of the eDP panel.
 */
void dce110_link_encoder_edp_power_control(
	struct link_encoder *enc,
	bool power_up)
{
	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
	struct dc_context *ctx = enc110->base.ctx;
	struct bp_transmitter_control cntl = { 0 };
	enum bp_result bp_result;

	if (dal_graphics_object_id_get_connector_id(enc110->base.connector) !=
		CONNECTOR_ID_EDP) {
		BREAK_TO_DEBUGGER();
		return;
	}

	if ((power_up && !is_panel_powered_on(enc110)) ||
		(!power_up && is_panel_powered_on(enc110))) {

		/* Send VBIOS command to prompt eDP panel power */

		dm_logger_write(ctx->logger, LOG_HW_RESUME_S3,
				"%s: Panel Power action: %s\n",
				__func__, (power_up ? "On":"Off"));

		cntl.action = power_up ?
			TRANSMITTER_CONTROL_POWER_ON :
			TRANSMITTER_CONTROL_POWER_OFF;
		cntl.transmitter = enc110->base.transmitter;
		cntl.connector_obj_id = enc110->base.connector;
		cntl.coherent = false;
		cntl.lanes_number = LANE_COUNT_FOUR;
		cntl.hpd_sel = enc110->base.hpd_source;

		bp_result = link_transmitter_control(enc110, &cntl);

		if (BP_RESULT_OK != bp_result) {

			dm_logger_write(ctx->logger, LOG_ERROR,
					"%s: Panel Power bp_result: %d\n",
					__func__, bp_result);
		}
	} else {
		dm_logger_write(ctx->logger, LOG_HW_RESUME_S3,
				"%s: Skipping Panel Power action: %s\n",
				__func__, (power_up ? "On":"Off"));
	}

	link_encoder_edp_wait_for_hpd_ready(enc110, true);
}

static void aux_initialize(
	struct dce110_link_encoder *enc110)
{
@@ -1018,7 +851,7 @@ void dce110_link_encoder_hw_init(
		ASSERT(result == BP_RESULT_OK);

	} else if (enc110->base.connector.id == CONNECTOR_ID_EDP) {
		enc->funcs->power_control(&enc110->base, true);
		ctx->dc->hwss.edp_power_control(enc, true);
	}
	aux_initialize(enc110);

@@ -1218,7 +1051,7 @@ void dce110_link_encoder_disable_output(
		return;
	}
	if (enc110->base.connector.id == CONNECTOR_ID_EDP)
		ctx->dc->hwss.backlight_control(link, false);
		ctx->dc->hwss.edp_backlight_control(link, false);
	/* Power-down RX and disable GPU PHY should be paired.
	 * Disabling PHY without powering down RX may cause
	 * symbol lock loss, on which we will get DP Sink interrupt. */
+0 −8
Original line number Diff line number Diff line
@@ -114,10 +114,6 @@ struct dce110_link_enc_hpd_registers {
};

struct dce110_link_enc_registers {
	/* Backlight registers */
	uint32_t LVTMA_PWRSEQ_CNTL;
	uint32_t LVTMA_PWRSEQ_STATE;

	/* DMCU registers */
	uint32_t MASTER_COMM_DATA_REG1;
	uint32_t MASTER_COMM_DATA_REG2;
@@ -250,10 +246,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_edp_power_control(
	struct link_encoder *enc,
	bool power_up);

void dce110_link_encoder_connect_dig_be_to_fe(
	struct link_encoder *enc,
	enum engine_id engine,
Loading