Blob Blame History Raw
From: Anthony Koo <Anthony.Koo@amd.com>
Date: Tue, 24 Jan 2017 15:19:42 -0500
Subject: drm/amd/display: Move backlight from encoder to ABM
Git-commit: 6728b30c974e38711f70dc38edf68503bf71c4a9
Patch-mainline: v4.15-rc1
References: FATE#326289 FATE#326079 FATE#326049 FATE#322398 FATE#326166

Signed-off-by: Anthony Koo <anthony.koo@amd.com>
Reviewed-by: Aric Cyr <Aric.Cyr@amd.com>
Acked-by: Harry Wentland <Harry.Wentland@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Acked-by: Petr Tesarik <ptesarik@suse.com>
---
 drivers/gpu/drm/amd/display/dc/core/dc.c                      |   34 -
 drivers/gpu/drm/amd/display/dc/core/dc_link.c                 |   63 +-
 drivers/gpu/drm/amd/display/dc/dc.h                           |    5 
 drivers/gpu/drm/amd/display/dc/dce/dce_abm.c                  |  264 +++++++++-
 drivers/gpu/drm/amd/display/dc/dce/dce_abm.h                  |   35 +
 drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c         |  260 ---------
 drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h         |   24 
 drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c   |    4 
 drivers/gpu/drm/amd/display/dc/inc/hw/abm.h                   |    5 
 drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h          |    5 
 drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h             |    4 
 drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c |   13 
 12 files changed, 316 insertions(+), 400 deletions(-)

--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -240,34 +240,6 @@ static void stream_update_scaling(
 	}
 }
 
-static bool set_backlight(struct dc *dc, unsigned int backlight_level,
-			unsigned int frame_ramp, const struct dc_stream *stream)
-{
-	struct core_dc *core_dc = DC_TO_CORE(dc);
-	int i;
-
-	if (stream->sink->sink_signal == SIGNAL_TYPE_EDP) {
-		for (i = 0; i < core_dc->link_count; i++)
-			dc_link_set_backlight_level(&core_dc->links[i]->public,
-					backlight_level, frame_ramp, stream);
-	}
-
-	return true;
-
-}
-
-static bool init_dmcu_backlight_settings(struct dc *dc)
-{
-	struct core_dc *core_dc = DC_TO_CORE(dc);
-	int i;
-
-	for (i = 0; i < core_dc->link_count; i++)
-		dc_link_init_dmcu_backlight_settings
-			(&core_dc->links[i]->public);
-
-	return true;
-}
-
 static bool set_psr_enable(struct dc *dc, bool enable)
 {
 	struct core_dc *core_dc = DC_TO_CORE(dc);
@@ -390,12 +362,6 @@ static void allocate_dc_stream_funcs(str
 	core_dc->public.stream_funcs.set_gamut_remap =
 			set_gamut_remap;
 
-	core_dc->public.stream_funcs.set_backlight =
-			set_backlight;
-
-	core_dc->public.stream_funcs.init_dmcu_backlight_settings =
-			init_dmcu_backlight_settings;
-
 	core_dc->public.stream_funcs.set_psr_enable =
 			set_psr_enable;
 
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
@@ -37,6 +37,7 @@
 #include "link_encoder.h"
 #include "hw_sequencer.h"
 #include "resource.h"
+#include "abm.h"
 #include "fixed31_32.h"
 #include "dpcd_defs.h"
 
@@ -1386,48 +1387,40 @@ bool dc_link_set_backlight_level(const s
 		uint32_t frame_ramp, 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 core_stream *core_stream = DC_STREAM_TO_CORE(stream);
+	struct core_dc *core_dc = DC_TO_CORE(link->ctx->dc);
+	struct core_stream *core_stream = NULL;
+	struct abm *abm = core_dc->res_pool->abm;
 	unsigned int controller_id = 0;
 	int i;
-	uint32_t dmcu_status;
 
-	dm_logger_write(ctx->logger, LOG_BACKLIGHT,
-			"New Backlight level: %d (0x%X)\n", level, level);
+	if ((abm == NULL) || (abm->funcs->set_backlight_level == NULL))
+		return false;
 
-	dmcu_status = dm_read_reg(ctx, mmDMCU_STATUS);
+	dm_logger_write(link->ctx->logger, LOG_BACKLIGHT,
+			"New Backlight level: %d (0x%X)\n", level, level);
 
-	/* If DMCU is in reset state, DMCU is uninitialized */
-	if (get_reg_field_value(dmcu_status, mmDMCU_STATUS, UC_IN_RESET)) {
-		link->link_enc->funcs->set_lcd_backlight_level(link->link_enc,
-						level);
-	} else {
-		for (i = 0; i < MAX_PIPES; i++) {
-			if (core_dc->current_context->res_ctx.pipe_ctx[i].stream
-					== core_stream)
-				/* dmcu -1 for all controller id values,
-				 * therefore +1 here
-				 */
-				controller_id = core_dc->current_context->res_ctx.
-						pipe_ctx[i].tg->inst + 1;
+	if (link->device_tag.dev_id.device_type == DEVICE_TYPE_LCD) {
+		if (stream != NULL) {
+			core_stream = DC_STREAM_TO_CORE(stream);
+			for (i = 0; i < MAX_PIPES; i++) {
+				if (core_dc->current_context->res_ctx.
+						pipe_ctx[i].stream
+						== core_stream)
+					/* DMCU -1 for all controller id values,
+					 * therefore +1 here
+					 */
+					controller_id =
+						core_dc->current_context->
+						res_ctx.pipe_ctx[i].tg->inst +
+						1;
+			}
 		}
-
-		link->link_enc->funcs->set_dmcu_backlight_level
-				(link->link_enc, level,
-				frame_ramp, controller_id);
+		abm->funcs->set_backlight_level(
+				abm,
+				level,
+				frame_ramp,
+				controller_id);
 	}
-	return true;
-}
-
-
-bool dc_link_init_dmcu_backlight_settings(const struct dc_link *dc_link)
-{
-	struct core_link *link = DC_LINK_TO_CORE(dc_link);
-
-	if (link->link_enc->funcs->init_dmcu_backlight_settings != NULL)
-		link->link_enc->funcs->
-			init_dmcu_backlight_settings(link->link_enc);
 
 	return true;
 }
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -100,9 +100,6 @@ struct dc_stream_funcs {
 			const struct rect *dst);
 	bool (*set_gamut_remap)(struct dc *dc,
 			const struct dc_stream **stream, int num_streams);
-	bool (*set_backlight)(struct dc *dc, unsigned int backlight_level,
-		unsigned int frame_ramp, const struct dc_stream *stream);
-	bool (*init_dmcu_backlight_settings)(struct dc *dc);
 	bool (*set_psr_enable)(struct dc *dc, bool enable);
 	bool (*setup_psr)(struct dc *dc, const struct dc_stream *stream);
 };
@@ -572,8 +569,6 @@ const struct graphics_object_id dc_get_l
 bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level,
 		uint32_t frame_ramp, const struct dc_stream *stream);
 
-bool dc_link_init_dmcu_backlight_settings(const struct dc_link *dc_link);
-
 bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable);
 
 bool dc_link_setup_psr(const struct dc_link *dc_link,
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c
@@ -29,6 +29,9 @@
 #include "fixed32_32.h"
 #include "dc.h"
 
+#include "atom.h"
+
+
 #define TO_DCE_ABM(abm)\
 	container_of(abm, struct dce_abm, base)
 
@@ -43,6 +46,19 @@
 	abm_dce->base.ctx
 
 #define MCP_ABM_LEVEL_SET 0x65
+#define MCP_ABM_PIPE_SET 0x66
+#define MCP_BL_SET 0x67
+
+struct abm_backlight_registers {
+	unsigned int BL_PWM_CNTL;
+	unsigned int BL_PWM_CNTL2;
+	unsigned int BL_PWM_PERIOD_CNTL;
+	unsigned int LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV;
+};
+
+/* registers setting needs to be save and restored used at InitBacklight */
+static struct abm_backlight_registers stored_backlight_registers = {0};
+
 
 static unsigned int get_current_backlight(struct dce_abm *abm_dce)
 {
@@ -93,7 +109,147 @@ static unsigned int get_current_backligh
 	return (uint32_t)(current_backlight);
 }
 
-void dce_abm_init(struct abm *abm)
+static void driver_set_backlight_level(struct dce_abm *abm_dce, uint32_t level)
+{
+	uint32_t backlight_24bit;
+	uint32_t backlight_17bit;
+	uint32_t backlight_16bit;
+	uint32_t masked_pwm_period;
+	uint8_t rounding_bit;
+	uint8_t bit_count;
+	uint64_t active_duty_cycle;
+	uint32_t pwm_period_bitcnt;
+
+	/*
+	 * 1. Convert 8-bit value to 17 bit U1.16 format
+	 * (1 integer, 16 fractional bits)
+	 */
+
+	/* 1.1 multiply 8 bit value by 0x10101 to get a 24 bit value,
+	 * effectively multiplying value by 256/255
+	 * eg. for a level of 0xEF, backlight_24bit = 0xEF * 0x10101 = 0xEFEFEF
+	 */
+	backlight_24bit = level * 0x10101;
+
+	/* 1.2 The upper 16 bits of the 24 bit value is the fraction, lower 8
+	 * used for rounding, take most significant bit of fraction for
+	 * rounding, e.g. for 0xEFEFEF, rounding bit is 1
+	 */
+	rounding_bit = (backlight_24bit >> 7) & 1;
+
+	/* 1.3 Add the upper 16 bits of the 24 bit value with the rounding bit
+	 * resulting in a 17 bit value e.g. 0xEFF0 = (0xEFEFEF >> 8) + 1
+	 */
+	backlight_17bit = (backlight_24bit >> 8) + rounding_bit;
+
+	/*
+	 * 2. Find  16 bit backlight active duty cycle, where 0 <= backlight
+	 * active duty cycle <= backlight period
+	 */
+
+	/* 2.1 Apply bitmask for backlight period value based on value of BITCNT
+	 */
+	REG_GET_2(BL_PWM_PERIOD_CNTL,
+			BL_PWM_PERIOD_BITCNT, &pwm_period_bitcnt,
+			BL_PWM_PERIOD, &masked_pwm_period);
+
+	if (pwm_period_bitcnt == 0)
+		bit_count = 16;
+	else
+		bit_count = pwm_period_bitcnt;
+
+	/* e.g. maskedPwmPeriod = 0x24 when bitCount is 6 */
+	masked_pwm_period = masked_pwm_period & ((1 << bit_count) - 1);
+
+	/* 2.2 Calculate integer active duty cycle required upper 16 bits
+	 * contain integer component, lower 16 bits contain fractional component
+	 * of active duty cycle e.g. 0x21BDC0 = 0xEFF0 * 0x24
+	 */
+	active_duty_cycle = backlight_17bit * masked_pwm_period;
+
+	/* 2.3 Calculate 16 bit active duty cycle from integer and fractional
+	 * components shift by bitCount then mask 16 bits and add rounding bit
+	 * from MSB of fraction e.g. 0x86F7 = ((0x21BDC0 >> 6) & 0xFFF) + 0
+	 */
+	backlight_16bit = active_duty_cycle >> bit_count;
+	backlight_16bit &= 0xFFFF;
+	backlight_16bit += (active_duty_cycle >> (bit_count - 1)) & 0x1;
+
+	/*
+	 * 3. Program register with updated value
+	 */
+
+	/* 3.1 Lock group 2 backlight registers */
+
+	REG_UPDATE_2(BL_PWM_GRP1_REG_LOCK,
+			BL_PWM_GRP1_IGNORE_MASTER_LOCK_EN, 1,
+			BL_PWM_GRP1_REG_LOCK, 1);
+
+	// 3.2 Write new active duty cycle
+	REG_UPDATE(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, backlight_16bit);
+
+	/* 3.3 Unlock group 2 backlight registers */
+	REG_UPDATE(BL_PWM_GRP1_REG_LOCK,
+			BL_PWM_GRP1_REG_LOCK, 0);
+
+	/* 5.4.4 Wait for pending bit to be cleared */
+	REG_WAIT(BL_PWM_GRP1_REG_LOCK, BL_PWM_GRP1_REG_UPDATE_PENDING,
+			0, 10, 1000);
+}
+
+static void dmcu_set_backlight_level(
+	struct dce_abm *abm_dce,
+	uint32_t level,
+	uint32_t frame_ramp,
+	uint32_t controller_id)
+{
+	unsigned int backlight_16_bit = (level * 0x10101) >> 8;
+	unsigned int backlight_17_bit = backlight_16_bit +
+				(((backlight_16_bit & 0x80) >> 7) & 1);
+	uint32_t rampingBoundary = 0xFFFF;
+	uint32_t s2;
+
+	/* set ramping boundary */
+	REG_WRITE(MASTER_COMM_DATA_REG1, rampingBoundary);
+
+	/* setDMCUParam_Pipe */
+	REG_UPDATE_2(MASTER_COMM_CMD_REG,
+			MASTER_COMM_CMD_REG_BYTE0, MCP_ABM_PIPE_SET,
+			MASTER_COMM_CMD_REG_BYTE1, controller_id);
+
+	/* notifyDMCUMsg */
+	REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1);
+
+	/* waitDMCUReadyForCmd */
+	REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT,
+			0, 100, 800);
+
+	/* setDMCUParam_BL */
+	REG_UPDATE(BL1_PWM_USER_LEVEL, BL1_PWM_USER_LEVEL, backlight_17_bit);
+
+	/* write ramp */
+	if (controller_id == 0)
+		frame_ramp = 0;
+	REG_WRITE(MASTER_COMM_DATA_REG1, frame_ramp);
+
+	/* setDMCUParam_Cmd */
+	REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, MCP_BL_SET);
+
+	/* notifyDMCUMsg */
+	REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1);
+
+	/* UpdateRequestedBacklightLevel */
+	s2 = REG_READ(BIOS_SCRATCH_2);
+
+	s2 &= ~ATOM_S2_CURRENT_BL_LEVEL_MASK;
+	level &= (ATOM_S2_CURRENT_BL_LEVEL_MASK >>
+				ATOM_S2_CURRENT_BL_LEVEL_SHIFT);
+	s2 |= (level << ATOM_S2_CURRENT_BL_LEVEL_SHIFT);
+
+	REG_WRITE(BIOS_SCRATCH_2, s2);
+}
+
+static void dce_abm_init(struct abm *abm)
 {
 	struct dce_abm *abm_dce = TO_DCE_ABM(abm);
 	unsigned int backlight = get_current_backlight(abm_dce);
@@ -133,24 +289,13 @@ void dce_abm_init(struct abm *abm)
 			ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, 1);
 }
 
-bool dce_abm_set_level(struct abm *abm, uint32_t level)
+static bool dce_abm_set_level(struct abm *abm, uint32_t level)
 {
 	struct dce_abm *abm_dce = TO_DCE_ABM(abm);
 	struct dc_context *ctx = abm_dce->base.ctx;
 
-	unsigned int dmcu_max_retry_on_wait_reg_ready = 801;
-	unsigned int dmcu_wait_reg_ready_interval = 100;
-	unsigned int value;
-
-	/* waitDMCUReadyForCmd */
-	do {
-		dm_delay_in_microseconds(ctx, dmcu_wait_reg_ready_interval);
-		REG_GET(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, &value);
-		dmcu_max_retry_on_wait_reg_ready--;
-	} while
-	/* expected value is 0, loop while not 0*/
-	((value & abm_dce->abm_mask->MASTER_COMM_INTERRUPT) &&
-		dmcu_max_retry_on_wait_reg_ready > 0);
+	REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0,
+			100, 800);
 
 	/* setDMCUParam_ABMLevel */
 	REG_UPDATE_2(MASTER_COMM_CMD_REG,
@@ -163,9 +308,98 @@ bool dce_abm_set_level(struct abm *abm,
 	return true;
 }
 
+static bool dce_abm_init_backlight(struct abm *abm)
+{
+	struct dce_abm *abm_dce = TO_DCE_ABM(abm);
+	uint32_t value;
+
+	/* It must not be 0, so we have to restore them
+	 * Bios bug w/a - period resets to zero,
+	 * restoring to cache values which is always correct
+	 */
+	REG_GET(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, &value);
+	if (value == 0 || value == 1) {
+		if (stored_backlight_registers.BL_PWM_CNTL != 0) {
+			REG_WRITE(BL_PWM_CNTL,
+				stored_backlight_registers.BL_PWM_CNTL);
+			REG_WRITE(BL_PWM_CNTL2,
+				stored_backlight_registers.BL_PWM_CNTL2);
+			REG_WRITE(BL_PWM_PERIOD_CNTL,
+				stored_backlight_registers.BL_PWM_PERIOD_CNTL);
+			REG_UPDATE(LVTMA_PWRSEQ_REF_DIV,
+				BL_PWM_REF_DIV,
+				stored_backlight_registers.
+				LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV);
+		} else {
+			/* TODO: Note: This should not really happen since VBIOS
+			 * should have initialized PWM registers on boot.
+			 */
+			REG_WRITE(BL_PWM_CNTL, 0xC000FA00);
+			REG_WRITE(BL_PWM_PERIOD_CNTL, 0x000C0FA0);
+		}
+	} else {
+		stored_backlight_registers.BL_PWM_CNTL =
+				REG_READ(BL_PWM_CNTL);
+		stored_backlight_registers.BL_PWM_CNTL2 =
+				REG_READ(BL_PWM_CNTL2);
+		stored_backlight_registers.BL_PWM_PERIOD_CNTL =
+				REG_READ(BL_PWM_PERIOD_CNTL);
+
+		REG_GET(LVTMA_PWRSEQ_REF_DIV, BL_PWM_REF_DIV,
+				&stored_backlight_registers.
+				LVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV);
+	}
+
+	/* Have driver take backlight control
+	 * TakeBacklightControl(true)
+	 */
+	value = REG_READ(BIOS_SCRATCH_2);
+	value |= ATOM_S2_VRI_BRIGHT_ENABLE;
+	REG_WRITE(BIOS_SCRATCH_2, value);
+
+	/* Enable the backlight output */
+	REG_UPDATE(BL_PWM_CNTL, BL_PWM_EN, 1);
+
+	/* Unlock group 2 backlight registers */
+	REG_UPDATE(BL_PWM_GRP1_REG_LOCK,
+			BL_PWM_GRP1_REG_LOCK, 0);
+
+	return true;
+}
+
+static bool dce_abm_set_backlight_level(
+		struct abm *abm,
+		unsigned int backlight_level,
+		unsigned int frame_ramp,
+		unsigned int controller_id)
+{
+	struct dce_abm *abm_dce = TO_DCE_ABM(abm);
+	unsigned int dmcu_uc_reset;
+
+	dm_logger_write(abm->ctx->logger, LOG_BACKLIGHT,
+			"New Backlight level: %d (0x%X)\n",
+			backlight_level, backlight_level);
+
+	REG_GET(DMCU_STATUS, UC_IN_RESET, &dmcu_uc_reset);
+
+	/* If DMCU is in reset state, DMCU is uninitialized */
+	if (dmcu_uc_reset) {
+		driver_set_backlight_level(abm_dce, backlight_level);
+	} else {
+		dmcu_set_backlight_level(abm_dce,
+				backlight_level,
+				frame_ramp,
+				controller_id);
+	}
+
+	return true;
+}
+
 static const struct abm_funcs dce_funcs = {
 	.abm_init = dce_abm_init,
 	.set_abm_level = dce_abm_set_level,
+	.init_backlight = dce_abm_init_backlight,
+	.set_backlight_level = dce_abm_set_backlight_level
 };
 
 static void dce_abm_construct(
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h
@@ -32,8 +32,13 @@
 #define ABM_COMMON_REG_LIST_DCE_BASE() \
 	SR(BL_PWM_PERIOD_CNTL), \
 	SR(BL_PWM_CNTL), \
+	SR(BL_PWM_CNTL2), \
+	SR(BL_PWM_GRP1_REG_LOCK), \
+	SR(LVTMA_PWRSEQ_REF_DIV), \
 	SR(MASTER_COMM_CNTL_REG), \
-	SR(MASTER_COMM_CMD_REG)
+	SR(MASTER_COMM_CMD_REG), \
+	SR(MASTER_COMM_DATA_REG1), \
+	SR(DMCU_STATUS)
 
 #define ABM_DCE110_COMMON_REG_LIST() \
 	ABM_COMMON_REG_LIST_DCE_BASE(), \
@@ -46,7 +51,8 @@
 	SR(BL1_PWM_TARGET_ABM_LEVEL), \
 	SR(BL1_PWM_USER_LEVEL), \
 	SR(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES), \
-	SR(DC_ABM1_HGLS_REG_READ_PROGRESS)
+	SR(DC_ABM1_HGLS_REG_READ_PROGRESS), \
+	SR(BIOS_SCRATCH_2)
 
 #define ABM_SF(reg_name, field_name, post_fix)\
 	.field_name = reg_name ## __ ## field_name ## post_fix
@@ -56,9 +62,16 @@
 	ABM_SF(BL_PWM_PERIOD_CNTL, BL_PWM_PERIOD_BITCNT, mask_sh), \
 	ABM_SF(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, mask_sh), \
 	ABM_SF(BL_PWM_CNTL, BL_PWM_FRACTIONAL_EN, mask_sh), \
+	ABM_SF(BL_PWM_CNTL, BL_PWM_EN, mask_sh), \
+	ABM_SF(BL_PWM_GRP1_REG_LOCK, BL_PWM_GRP1_IGNORE_MASTER_LOCK_EN, mask_sh), \
+	ABM_SF(BL_PWM_GRP1_REG_LOCK, BL_PWM_GRP1_REG_LOCK, mask_sh), \
+	ABM_SF(BL_PWM_GRP1_REG_LOCK, BL_PWM_GRP1_REG_UPDATE_PENDING, mask_sh), \
+	ABM_SF(LVTMA_PWRSEQ_REF_DIV, BL_PWM_REF_DIV, mask_sh), \
 	ABM_SF(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, mask_sh), \
 	ABM_SF(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, mask_sh), \
-	ABM_SF(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE2, mask_sh)
+	ABM_SF(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE1, mask_sh), \
+	ABM_SF(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE2, mask_sh), \
+	ABM_SF(DMCU_STATUS, UC_IN_RESET, mask_sh)
 
 #define ABM_MASK_SH_LIST_DCE110(mask_sh) \
 	ABM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \
@@ -91,6 +104,7 @@
 	ABM_SF(DC_ABM1_HGLS_REG_READ_PROGRESS, \
 			ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, mask_sh)
 
+
 #define ABM_REG_FIELD_LIST(type) \
 	type ABM1_HG_NUM_OF_BINS_SEL; \
 	type ABM1_HG_VMAX_SEL; \
@@ -112,7 +126,14 @@
 	type BL_PWM_FRACTIONAL_EN; \
 	type MASTER_COMM_INTERRUPT; \
 	type MASTER_COMM_CMD_REG_BYTE0; \
-	type MASTER_COMM_CMD_REG_BYTE2
+	type MASTER_COMM_CMD_REG_BYTE1; \
+	type MASTER_COMM_CMD_REG_BYTE2; \
+	type BL_PWM_REF_DIV; \
+	type BL_PWM_EN; \
+	type UC_IN_RESET; \
+	type BL_PWM_GRP1_IGNORE_MASTER_LOCK_EN; \
+	type BL_PWM_GRP1_REG_LOCK; \
+	type BL_PWM_GRP1_REG_UPDATE_PENDING
 
 struct dce_abm_shift {
 	ABM_REG_FIELD_LIST(uint8_t);
@@ -125,6 +146,8 @@ struct dce_abm_mask {
 struct dce_abm_registers {
 	uint32_t BL_PWM_PERIOD_CNTL;
 	uint32_t BL_PWM_CNTL;
+	uint32_t BL_PWM_CNTL2;
+	uint32_t LVTMA_PWRSEQ_REF_DIV;
 	uint32_t DC_ABM1_HG_SAMPLE_RATE;
 	uint32_t DC_ABM1_LS_SAMPLE_RATE;
 	uint32_t BL1_PWM_BL_UPDATE_SAMPLE_RATE;
@@ -137,6 +160,10 @@ struct dce_abm_registers {
 	uint32_t DC_ABM1_HGLS_REG_READ_PROGRESS;
 	uint32_t MASTER_COMM_CNTL_REG;
 	uint32_t MASTER_COMM_CMD_REG;
+	uint32_t MASTER_COMM_DATA_REG1;
+	uint32_t BIOS_SCRATCH_2;
+	uint32_t DMCU_STATUS;
+	uint32_t BL_PWM_GRP1_REG_LOCK;
 };
 
 struct dce_abm {
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c
@@ -38,15 +38,6 @@
 #include "dce/dce_11_0_sh_mask.h"
 #include "dce/dce_11_0_enum.h"
 
-#ifndef ATOM_S2_CURRENT_BL_LEVEL_MASK
-#define ATOM_S2_CURRENT_BL_LEVEL_MASK   0x0000FF00L
-#define ATOM_S2_VRI_BRIGHT_ENABLE       0x20000000L
-#endif
-
-#ifndef ATOM_S2_CURRENT_BL_LEVEL_SHIFT
-#define ATOM_S2_CURRENT_BL_LEVEL_SHIFT  8
-#endif
-
 #ifndef HPD0_DC_HPD_CONTROL__DC_HPD_EN_MASK
 #define HPD0_DC_HPD_CONTROL__DC_HPD_EN_MASK  0x10000000L
 #endif
@@ -96,13 +87,6 @@
 /* For current ASICs pixel clock - 600MHz */
 #define MAX_ENCODER_CLOCK 600000
 
-/* Set the ABM Pipe */
-#define MCP_ABM_PIPE_SET 0x66
-/* Set the ABM level */
-#define MCP_ABM_LEVEL_SET 0x65
-/* Set backlight level */
-#define MCP_BL_SET 0x67
-
 /* PSR related commands */
 #define PSR_ENABLE 0x20
 #define PSR_EXIT 0x21
@@ -111,9 +95,6 @@
 /*TODO: Used for psr wakeup for set backlight level*/
 static unsigned int psr_crtc_offset;
 
-/* registers setting needs to be save and restored used at InitBacklight */
-static struct dce110_abm_backlight_registers stored_backlight_registers;
-
 enum {
 	DP_MST_UPDATE_MAX_RETRY = 50
 };
@@ -137,11 +118,6 @@ static const struct link_encoder_funcs d
 	.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_lcd_backlight_level = dce110_link_encoder_set_lcd_backlight_level,
-	.set_dmcu_backlight_level =
-			dce110_link_encoder_set_dmcu_backlight_level,
-	.init_dmcu_backlight_settings =
-			dce110_link_encoder_init_dmcu_backlight_settings,
 	.set_dmcu_psr_enable = dce110_link_encoder_set_dmcu_psr_enable,
 	.setup_dmcu_psr = dce110_link_encoder_setup_dmcu_psr,
 	.backlight_control = dce110_link_encoder_edp_backlight_control,
@@ -1574,242 +1550,6 @@ void dce110_link_encoder_update_mst_stre
 	} while (retries < DP_MST_UPDATE_MAX_RETRY);
 }
 
-void dce110_link_encoder_set_lcd_backlight_level(
-	struct link_encoder *enc,
-	uint32_t level)
-{
-	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
-
-	const uint32_t backlight_update_pending_max_retry = 1000;
-
-	uint32_t backlight_lock;
-
-	uint32_t i;
-	uint32_t backlight_24bit;
-	uint32_t backlight_17bit;
-	uint32_t backlight_16bit;
-	uint32_t masked_pwm_period;
-	uint8_t rounding_bit;
-	uint8_t bit_count;
-	uint64_t active_duty_cycle;
-	uint32_t pwm_period_bitcnt;
-
-	backlight_lock = REG_READ(BL_PWM_GRP1_REG_LOCK);
-
-	/*
-	 * 1. Convert 8-bit value to 17 bit U1.16 format
-	 * (1 integer, 16 fractional bits)
-	 */
-
-	/* 1.1 multiply 8 bit value by 0x10101 to get a 24 bit value,
-	 * effectively multiplying value by 256/255
-	 * eg. for a level of 0xEF, backlight_24bit = 0xEF * 0x10101 = 0xEFEFEF
-	 */
-	backlight_24bit = level * 0x10101;
-
-	/* 1.2 The upper 16 bits of the 24 bit value is the fraction, lower 8
-	 * used for rounding, take most significant bit of fraction for
-	 * rounding, e.g. for 0xEFEFEF, rounding bit is 1
-	 */
-	rounding_bit = (backlight_24bit >> 7) & 1;
-
-	/* 1.3 Add the upper 16 bits of the 24 bit value with the rounding bit
-	 * resulting in a 17 bit value e.g. 0xEFF0 = (0xEFEFEF >> 8) + 1
-	 */
-	backlight_17bit = (backlight_24bit >> 8) + rounding_bit;
-
-	/*
-	 * 2. Find  16 bit backlight active duty cycle, where 0 <= backlight
-	 * active duty cycle <= backlight period
-	 */
-
-	/* 2.1 Apply bitmask for backlight period value based on value of BITCNT
-	 */
-	{
-		REG_GET(BL_PWM_PERIOD_CNTL,
-			BL_PWM_PERIOD_BITCNT, &pwm_period_bitcnt);
-
-		if (pwm_period_bitcnt == 0)
-			bit_count = 16;
-		else
-			bit_count = pwm_period_bitcnt;
-	}
-
-	/* e.g. maskedPwmPeriod = 0x24 when bitCount is 6 */
-	masked_pwm_period =
-		REG_GET(BL_PWM_PERIOD_CNTL,
-				BL_PWM_PERIOD, &masked_pwm_period)
-		& ((1 << bit_count) - 1);
-
-	/* 2.2 Calculate integer active duty cycle required upper 16 bits
-	 * contain integer component, lower 16 bits contain fractional component
-	 * of active duty cycle e.g. 0x21BDC0 = 0xEFF0 * 0x24
-	 */
-	active_duty_cycle = backlight_17bit * masked_pwm_period;
-
-	/* 2.3 Calculate 16 bit active duty cycle from integer and fractional
-	 * components shift by bitCount then mask 16 bits and add rounding bit
-	 * from MSB of fraction e.g. 0x86F7 = ((0x21BDC0 >> 6) & 0xFFF) + 0
-	 */
-	backlight_16bit = active_duty_cycle >> bit_count;
-	backlight_16bit &= 0xFFFF;
-	backlight_16bit += (active_duty_cycle >> (bit_count - 1)) & 0x1;
-
-	REG_UPDATE(BL_PWM_CNTL,
-			BL_ACTIVE_INT_FRAC_CNT, backlight_16bit);
-
-	/*
-	 * 3. Program register with updated value
-	 */
-
-	/* 3.1 Lock group 2 backlight registers */
-
-	REG_UPDATE(BL_PWM_GRP1_REG_LOCK,
-			BL_PWM_GRP1_IGNORE_MASTER_LOCK_EN, 1);
-
-	REG_UPDATE(BL_PWM_GRP1_REG_LOCK,
-			BL_PWM_GRP1_REG_LOCK, 1);
-
-	/* 3.3 Unlock group 2 backlight registers */
-	REG_UPDATE(BL_PWM_GRP1_REG_LOCK,
-			BL_PWM_GRP1_REG_LOCK, 0);
-
-	/* 5.4.4 Wait for pending bit to be cleared */
-	for (i = 0; i < backlight_update_pending_max_retry; ++i) {
-		REG_GET(BL_PWM_GRP1_REG_LOCK,
-						BL_PWM_GRP1_REG_UPDATE_PENDING, &backlight_lock);
-		if (!backlight_lock)
-			break;
-
-		udelay(10);
-	}
-}
-
-void dce110_link_encoder_set_dmcu_backlight_level(
-	struct link_encoder *enc,
-	uint32_t level,
-	uint32_t frame_ramp,
-	uint32_t controller_id)
-{
-	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 backlight_17bit = level * 0x10101;
-	unsigned char temp_uchar =
-			(unsigned char)(((backlight_17bit & 0x80) >> 7) & 1);
-	unsigned int regValue;
-	uint32_t rampingBoundary = 0xFFFF;
-	uint32_t s2;
-
-	backlight_17bit = (backlight_17bit >> 8) + temp_uchar;
-
-	/* set ramping boundary */
-	REG_WRITE(MASTER_COMM_DATA_REG1, rampingBoundary);
-
-	/* setDMCUParam_Pipe */
-	REG_UPDATE_2(MASTER_COMM_CMD_REG,
-			MASTER_COMM_CMD_REG_BYTE0, MCP_ABM_PIPE_SET,
-			MASTER_COMM_CMD_REG_BYTE1, controller_id);
-
-	/* notifyDMCUMsg */
-	REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 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_BL */
-	REG_UPDATE(BL1_PWM_USER_LEVEL, BL1_PWM_USER_LEVEL, backlight_17bit);
-
-	/* write ramp */
-	REG_WRITE(MASTER_COMM_DATA_REG1, frame_ramp);
-
-	/* setDMCUParam_Cmd */
-	REG_UPDATE(MASTER_COMM_CMD_REG, MASTER_COMM_CMD_REG_BYTE0, MCP_BL_SET);
-
-	/* notifyDMCUMsg */
-	REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1);
-
-	/* UpdateRequestedBacklightLevel */
-	s2 = REG_READ(BIOS_SCRATCH_2);
-
-	s2 &= ~ATOM_S2_CURRENT_BL_LEVEL_MASK;
-	level &= (ATOM_S2_CURRENT_BL_LEVEL_MASK >>
-				ATOM_S2_CURRENT_BL_LEVEL_SHIFT);
-	s2 |= (level << ATOM_S2_CURRENT_BL_LEVEL_SHIFT);
-
-	REG_WRITE(BIOS_SCRATCH_2, s2);
-}
-
-void dce110_link_encoder_init_dmcu_backlight_settings(
-	struct link_encoder *enc)
-{
-	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
-	uint32_t bl_pwm_cntl;
-	uint32_t pwmCntl;
-	uint32_t pwmCntl2;
-	uint32_t periodCntl;
-	uint32_t s2;
-	uint32_t value;
-
-	if (enc->ctx->dc->debug.disable_dmcu)
-		return;
-
-	bl_pwm_cntl = REG_READ(BL_PWM_CNTL);
-
-	/* It must not be 0, so we have to restore them
-	 * Bios bug w/a - period resets to zero,
-	 * restoring to cache values which is always correct
-	 */
-	REG_GET(BL_PWM_CNTL, BL_ACTIVE_INT_FRAC_CNT, &value);
-	if (value == 0 || bl_pwm_cntl == 1) {
-		if (stored_backlight_registers.vBL_PWM_CNTL != 0) {
-			pwmCntl = stored_backlight_registers.vBL_PWM_CNTL;
-			REG_WRITE(BL_PWM_CNTL, pwmCntl);
-
-			pwmCntl2 = stored_backlight_registers.vBL_PWM_CNTL2;
-			REG_WRITE(BL_PWM_CNTL2, pwmCntl2);
-
-			periodCntl =
-				stored_backlight_registers.vBL_PWM_PERIOD_CNTL;
-			REG_WRITE(BL_PWM_PERIOD_CNTL, periodCntl);
-
-			REG_UPDATE(LVTMA_PWRSEQ_REF_DIV,
-				BL_PWM_REF_DIV,
-				stored_backlight_registers.
-				vLVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV);
-		}
-	} else {
-		stored_backlight_registers.vBL_PWM_CNTL =
-				REG_READ(BL_PWM_CNTL);
-		stored_backlight_registers.vBL_PWM_CNTL2 =
-				REG_READ(BL_PWM_CNTL2);
-		stored_backlight_registers.vBL_PWM_PERIOD_CNTL =
-				REG_READ(BL_PWM_PERIOD_CNTL);
-
-		REG_GET(LVTMA_PWRSEQ_REF_DIV, BL_PWM_REF_DIV,
-				&stored_backlight_registers.
-				vLVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV);
-	}
-
-	/* Have driver take backlight control
-	 * TakeBacklightControl(true)
-	 */
-	s2 = REG_READ(BIOS_SCRATCH_2);
-	s2 |= ATOM_S2_VRI_BRIGHT_ENABLE;
-	REG_WRITE(BIOS_SCRATCH_2, s2);
-
-	/* Enable the backlight output */
-	REG_UPDATE(BL_PWM_CNTL, BL_PWM_EN, 1);
-}
-
 static void get_dmcu_psr_state(struct link_encoder *enc, uint32_t *psr_state)
 {
 	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h
@@ -226,13 +226,6 @@ union dce110_dmcu_psr_config_data_reg3 {
 	unsigned int u32All;
 };
 
-struct dce110_abm_backlight_registers {
-	unsigned int vBL_PWM_CNTL;
-	unsigned int vBL_PWM_CNTL2;
-	unsigned int vBL_PWM_PERIOD_CNTL;
-	unsigned int vLVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV;
-};
-
 bool dce110_link_encoder_construct(
 	struct dce110_link_encoder *enc110,
 	const struct encoder_init_data *init_data,
@@ -317,23 +310,6 @@ void dce110_link_encoder_update_mst_stre
 	struct link_encoder *enc,
 	const struct link_mst_stream_allocation_table *table);
 
-void dce110_link_encoder_set_lcd_backlight_level(
-	struct link_encoder *enc,
-	uint32_t level);
-
-void dce110_link_encoder_set_dmcu_backlight_level(
-	struct link_encoder *enc,
-	uint32_t level,
-	uint32_t frame_ramp,
-	uint32_t controller_id);
-
-void dce110_link_encoder_init_dmcu_backlight_settings(
-	struct link_encoder *enc);
-
-void dce110_link_encoder_set_dmcu_abm_level(
-	struct link_encoder *enc,
-	uint32_t level);
-
 void dce110_link_encoder_set_dmcu_psr_enable(
 		struct link_encoder *enc, bool enable);
 
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
@@ -2214,8 +2214,10 @@ static void init_hw(struct core_dc *dc)
 	}
 
 	abm = dc->res_pool->abm;
-	if (abm != NULL)
+	if (abm != NULL) {
+		abm->funcs->init_backlight(abm);
 		abm->funcs->abm_init(abm);
+	}
 }
 
 /* TODO: move this to apply_ctx_tohw some how?*/
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/abm.h
@@ -35,6 +35,11 @@ struct abm {
 struct abm_funcs {
 	void (*abm_init)(struct abm *abm);
 	bool (*set_abm_level)(struct abm *abm, unsigned int abm_level);
+	bool (*init_backlight)(struct abm *abm);
+	bool (*set_backlight_level)(struct abm *abm,
+			unsigned int backlight_level,
+			unsigned int frame_ramp,
+			unsigned int controller_id);
 };
 
 #endif
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h
@@ -220,11 +220,6 @@ struct link_encoder_funcs {
 	void (*update_mst_stream_allocation_table)(
 		struct link_encoder *enc,
 		const struct link_mst_stream_allocation_table *table);
-	void (*set_lcd_backlight_level) (struct link_encoder *enc,
-		uint32_t level);
-	void (*set_dmcu_backlight_level)(struct link_encoder *enc,
-		uint32_t level, uint32_t frame_ramp, uint32_t controller_id);
-	void (*init_dmcu_backlight_settings)(struct link_encoder *enc);
 	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);
--- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
@@ -94,10 +94,6 @@ struct hw_sequencer_funcs {
 			int group_size,
 			struct pipe_ctx *grouped_pipes[]);
 
-	/* backlight control */
-	void (*encoder_set_lcd_backlight_level)(
-		struct link_encoder *enc, uint32_t level);
-
 	void (*enable_display_pipe_clock_gating)(
 					struct dc_context *ctx,
 					bool clock_gating);
--- a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c
@@ -72,16 +72,6 @@ static void virtual_link_encoder_update_
 	struct link_encoder *enc,
 	const struct link_mst_stream_allocation_table *table) {}
 
-static void virtual_link_encoder_set_lcd_backlight_level(
-	struct link_encoder *enc,
-	uint32_t level) {}
-
-static void virtual_link_encoder_set_dmcu_backlight_level(
-	struct link_encoder *enc,
-	uint32_t level,
-	uint32_t frame_ramp,
-	uint32_t controller_id) {}
-
 static void virtual_link_encoder_edp_backlight_control(
 	struct link_encoder *enc,
 	bool enable) {}
@@ -115,9 +105,6 @@ static const struct link_encoder_funcs v
 	.dp_set_phy_pattern = virtual_link_encoder_dp_set_phy_pattern,
 	.update_mst_stream_allocation_table =
 		virtual_link_encoder_update_mst_stream_allocation_table,
-	.set_lcd_backlight_level = virtual_link_encoder_set_lcd_backlight_level,
-	.set_dmcu_backlight_level =
-			virtual_link_encoder_set_dmcu_backlight_level,
 	.backlight_control = virtual_link_encoder_edp_backlight_control,
 	.power_control = virtual_link_encoder_edp_power_control,
 	.connect_dig_be_to_fe = virtual_link_encoder_connect_dig_be_to_fe,