diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 3c9703b08491..5aee0ebc200e 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -211,6 +211,9 @@ static const struct edid_quirk {
 
 	/* OSVR HDK and HDK2 VR Headsets */
 	{ "SVR", 0x1019, EDID_QUIRK_NON_DESKTOP },
+
+	/* Samsung eDP panel */
+	{ "SDC", 0x4141, EDID_QUIRK_NON_STD_BRIGHTNESS_CONTROL },
 };
 
 /*
@@ -1938,7 +1941,7 @@ static bool edid_vendor(const struct edid *edid, const char *vendor)
  *
  * This tells subsequent routines what fixes they need to apply.
  */
-static u32 edid_get_quirks(const struct edid *edid)
+u32 edid_get_quirks(const struct edid *edid)
 {
 	const struct edid_quirk *quirk;
 	int i;
@@ -1953,6 +1956,7 @@ static u32 edid_get_quirks(const struct edid *edid)
 
 	return 0;
 }
+EXPORT_SYMBOL(edid_get_quirks);
 
 #define MODE_SIZE(m) ((m)->hdisplay * (m)->vdisplay)
 #define MODE_REFRESH_DIFF(c,t) (abs((c) - (t)))
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 2b1e71f992b0..89193bd2d8ea 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -7097,6 +7097,13 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 	}
 	intel_connector->edid = edid;
 
+	if (edid_get_quirks(intel_connector->edid) ==
+	    EDID_QUIRK_NON_STD_BRIGHTNESS_CONTROL) {
+		i915_modparams.enable_dpcd_backlight = true;
+		i915_modparams.fastboot = false;
+		DRM_DEBUG_KMS("Using specific DPCD to control brightness\n");
+	}
+
 	fixed_mode = intel_panel_edid_fixed_mode(intel_connector);
 	if (fixed_mode)
 		downclock_mode = intel_dp_drrs_init(intel_connector, fixed_mode);
diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
index 020422da2ae2..7d9a2249cfb1 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
@@ -25,6 +25,117 @@
 #include "intel_display_types.h"
 #include "intel_dp_aux_backlight.h"
 
+#define DPCD_EDP_GETSET_CTRL_PARAMS		0x344
+#define DPCD_EDP_CONTENT_LUMINANCE		0x346
+#define DPCD_EDP_PANEL_LUMINANCE_OVERRIDE	0x34a
+#define DPCD_EDP_BRIGHTNESS_NITS		0x354
+#define DPCD_EDP_BRIGHTNESS_OPTIMIZATION	0x358
+
+#define EDP_CUSTOMIZE_MAX_BRIGHTNESS_LEVEL	(512)
+
+static uint32_t intel_dp_aux_get_customize_backlight(struct intel_connector *connector)
+{
+	struct intel_dp *intel_dp = enc_to_intel_dp(&connector->encoder->base);
+	uint8_t read_val[2] = { 0x0 };
+
+	if (drm_dp_dpcd_read(&intel_dp->aux, DPCD_EDP_BRIGHTNESS_NITS,
+			     &read_val, sizeof(read_val)) < 0) {
+		DRM_DEBUG_KMS("Failed to read DPCD register %x\n",
+			DPCD_EDP_BRIGHTNESS_NITS);
+		return 0;
+	}
+
+	return (read_val[1] << 8 | read_val[0]);
+}
+
+static void
+intel_dp_aux_set_customize_backlight(const struct drm_connector_state *conn_state, u32 level)
+{
+	struct intel_connector *connector = to_intel_connector(conn_state->connector);
+	struct intel_dp *intel_dp = enc_to_intel_dp(&connector->encoder->base);
+	struct intel_panel *panel = &connector->panel;
+	uint8_t new_vals[4];
+
+	if (level > panel->backlight.max)
+		level = panel->backlight.max;
+
+	new_vals[0] = level & 0xFF;
+	new_vals[1] = (level & 0xFF00) >> 8;
+	new_vals[2] = 0;
+	new_vals[3] = 0;
+
+	if (drm_dp_dpcd_write(&intel_dp->aux, DPCD_EDP_BRIGHTNESS_NITS, new_vals, 4) < 0)
+		DRM_DEBUG_KMS("Failed to write aux backlight level\n");
+}
+
+static void intel_dp_aux_enable_customize_backlight(const struct intel_crtc_state *crtc_state,
+					  const struct drm_connector_state *conn_state)
+{
+	struct intel_connector *connector = to_intel_connector(conn_state->connector);
+	struct intel_dp *intel_dp = enc_to_intel_dp(&connector->encoder->base);
+	uint8_t read_val[4], i;
+	uint8_t write_val[8] = {0x00, 0x00, 0xF0, 0x01, 0x90, 0x01, 0x00, 0x00};
+
+	if (drm_dp_dpcd_write(&intel_dp->aux, DPCD_EDP_PANEL_LUMINANCE_OVERRIDE, write_val, sizeof(write_val)) < 0)
+		DRM_DEBUG_KMS("Failed to write panel luminance.\n");
+
+	if (drm_dp_dpcd_writeb(&intel_dp->aux, DPCD_EDP_BRIGHTNESS_OPTIMIZATION, 0x01) < 0)
+		DRM_DEBUG_KMS("Failed to write %x\n",
+			DPCD_EDP_BRIGHTNESS_OPTIMIZATION);
+	/* write source OUI */
+	write_val[0] = 0x00;
+	write_val[1] = 0xaa;
+	write_val[2] = 0x01;
+	if (drm_dp_dpcd_write(&intel_dp->aux, DP_SOURCE_OUI, write_val, 3) < 0)
+		DRM_DEBUG_KMS("Failed to write OUI\n");
+
+	if (drm_dp_dpcd_readb(&intel_dp->aux, DPCD_EDP_GETSET_CTRL_PARAMS, read_val) != 1)
+		DRM_DEBUG_KMS("Failed to read %x\n",
+			DPCD_EDP_GETSET_CTRL_PARAMS);
+
+	if (drm_dp_dpcd_writeb(&intel_dp->aux, DPCD_EDP_GETSET_CTRL_PARAMS, 0) != 1)
+		DRM_DEBUG_KMS("Failed to write %x\n",
+			DPCD_EDP_GETSET_CTRL_PARAMS);
+
+	if (drm_dp_dpcd_readb(&intel_dp->aux, DPCD_EDP_GETSET_CTRL_PARAMS, read_val) != 1)
+		DRM_DEBUG_KMS("Failed to read %x\n",
+			DPCD_EDP_GETSET_CTRL_PARAMS);
+
+	if (drm_dp_dpcd_read(&intel_dp->aux, DPCD_EDP_CONTENT_LUMINANCE, &read_val, sizeof(read_val)) < 0)
+		DRM_DEBUG_KMS("Failed to read %x\n",
+			DPCD_EDP_CONTENT_LUMINANCE);
+
+	memset(read_val, 0x0, 4);
+	if (drm_dp_dpcd_write(&intel_dp->aux, DPCD_EDP_CONTENT_LUMINANCE, read_val, sizeof(read_val)) < 0)
+		DRM_DEBUG_KMS("Failed to write %x\n",
+			DPCD_EDP_CONTENT_LUMINANCE);
+
+	if (drm_dp_dpcd_readb(&intel_dp->aux, DPCD_EDP_GETSET_CTRL_PARAMS, read_val) != 1)
+		DRM_DEBUG_KMS("Failed to read %x\n",
+			DPCD_EDP_GETSET_CTRL_PARAMS);
+
+	if (drm_dp_dpcd_read(&intel_dp->aux, DP_SOURCE_OUI, read_val, 4) < 0)
+		DRM_DEBUG_KMS("Failed to read OUI\n");
+
+	DRM_DEBUG_KMS("got OUI %3ph\n", read_val);
+
+	for (i = 0; i < 6; i++) {
+		intel_dp_aux_set_customize_backlight(conn_state, connector->panel.backlight.level);
+
+		msleep(60);
+		if (intel_dp_aux_get_customize_backlight(connector))
+			return;
+	}
+
+	DRM_DEBUG_KMS("Restore brightness may have problem.\n");
+}
+
+static void intel_dp_aux_disable_customize_backlight(const struct drm_connector_state *old_conn_state)
+{
+	// do nothing
+	return;
+}
+
 static void set_aux_backlight_enable(struct intel_dp *intel_dp, bool enable)
 {
 	u8 reg_val = 0;
@@ -225,6 +336,19 @@ static void intel_dp_aux_disable_backlight(const struct drm_connector_state *old
 	set_aux_backlight_enable(enc_to_intel_dp(old_conn_state->best_encoder), false);
 }
 
+static int intel_dp_aux_setup_customize_backlight(struct intel_connector *connector,
+					enum pipe pipe)
+{
+	struct intel_panel *panel = &connector->panel;
+
+	panel->backlight.max = EDP_CUSTOMIZE_MAX_BRIGHTNESS_LEVEL;
+	panel->backlight.min = 0;
+	panel->backlight.level = panel->backlight.get(connector);
+	panel->backlight.enabled = panel->backlight.level != 0;
+
+	return 0;
+}
+
 static int intel_dp_aux_setup_backlight(struct intel_connector *connector,
 					enum pipe pipe)
 {
@@ -274,11 +398,20 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector)
 	if (!intel_dp_aux_display_control_capable(intel_connector))
 		return -ENODEV;
 
-	panel->backlight.setup = intel_dp_aux_setup_backlight;
-	panel->backlight.enable = intel_dp_aux_enable_backlight;
-	panel->backlight.disable = intel_dp_aux_disable_backlight;
-	panel->backlight.set = intel_dp_aux_set_backlight;
-	panel->backlight.get = intel_dp_aux_get_backlight;
+	if (edid_get_quirks(intel_connector->edid) ==
+	    EDID_QUIRK_NON_STD_BRIGHTNESS_CONTROL) {
+		panel->backlight.setup   = intel_dp_aux_setup_customize_backlight;
+		panel->backlight.enable  = intel_dp_aux_enable_customize_backlight;
+		panel->backlight.disable = intel_dp_aux_disable_customize_backlight;
+		panel->backlight.set = intel_dp_aux_set_customize_backlight;
+		panel->backlight.get = intel_dp_aux_get_customize_backlight;
+	} else {
+		panel->backlight.setup   = intel_dp_aux_setup_backlight;
+		panel->backlight.enable  = intel_dp_aux_enable_backlight;
+		panel->backlight.disable = intel_dp_aux_disable_backlight;
+		panel->backlight.set = intel_dp_aux_set_backlight;
+		panel->backlight.get = intel_dp_aux_get_backlight;
+	}
 
 	return 0;
 }
diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
index b9719418c3d2..b73bc3ee071e 100644
--- a/include/drm/drm_edid.h
+++ b/include/drm/drm_edid.h
@@ -282,6 +282,8 @@ struct detailed_timing {
 
 #define DRM_ELD_CEA_SAD(mnl, sad)	(20 + (mnl) + 3 * (sad))
 
+#define EDID_QUIRK_NON_STD_BRIGHTNESS_CONTROL	(1 << 13)
+
 struct edid {
 	u8 header[8];
 	/* Vendor & product info */
@@ -500,4 +502,5 @@ void drm_edid_get_monitor_name(struct edid *edid, char *name,
 struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
 					   int hsize, int vsize, int fresh,
 					   bool rb);
+u32 edid_get_quirks(const struct edid *edid);
 #endif /* __DRM_EDID_H__ */
