Browse Source

Merge "disp: msm: dp: add colorspace property for MSM DP"

qctecmdr 6 years ago
parent
commit
60d59191c8
13 changed files with 640 additions and 165 deletions
  1. 169 91
      msm/dp/dp_catalog.c
  2. 12 28
      msm/dp/dp_catalog.h
  3. 45 2
      msm/dp/dp_display.c
  4. 2 0
      msm/dp/dp_display.h
  5. 45 0
      msm/dp/dp_drm.c
  6. 21 0
      msm/dp/dp_drm.h
  7. 1 1
      msm/dp/dp_link.c
  8. 277 42
      msm/dp/dp_panel.c
  9. 3 1
      msm/dp/dp_panel.h
  10. 1 0
      msm/msm_drv.h
  11. 51 0
      msm/sde/sde_connector.c
  12. 11 0
      msm/sde/sde_connector.h
  13. 2 0
      msm/sde/sde_kms.c

+ 169 - 91
msm/dp/dp_catalog.c

@@ -6,7 +6,6 @@
 
 
 #include <linux/delay.h>
 #include <linux/delay.h>
 #include <linux/iopoll.h>
 #include <linux/iopoll.h>
-#include <drm/drm_dp_helper.h>
 
 
 #include "dp_catalog.h"
 #include "dp_catalog.h"
 #include "dp_reg.h"
 #include "dp_reg.h"
@@ -478,6 +477,29 @@ static u32 dp_catalog_ctrl_read_hdcp_status(struct dp_catalog_ctrl *ctrl)
 	return dp_read(catalog->exe_mode, io_data, DP_HDCP_STATUS);
 	return dp_read(catalog->exe_mode, io_data, DP_HDCP_STATUS);
 }
 }
 
 
+static void dp_catalog_panel_sdp_update(struct dp_catalog_panel *panel)
+{
+	struct dp_catalog_private *catalog;
+	struct dp_io_data *io_data;
+	u32 sdp_cfg3_off = 0;
+
+	if (panel->stream_id >= DP_STREAM_MAX) {
+		pr_err("invalid stream_id:%d\n", panel->stream_id);
+		return;
+	}
+
+	if (panel->stream_id == DP_STREAM_1)
+		sdp_cfg3_off = MMSS_DP1_SDP_CFG3 - MMSS_DP_SDP_CFG3;
+
+	catalog = dp_catalog_get_priv(panel);
+	io_data = catalog->io.dp_link;
+
+	dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG3 + sdp_cfg3_off,
+			 0x01);
+	dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG3 + sdp_cfg3_off,
+			 0x00);
+}
+
 static void dp_catalog_panel_setup_vsif_infoframe_sdp(
 static void dp_catalog_panel_setup_vsif_infoframe_sdp(
 		struct dp_catalog_panel *panel)
 		struct dp_catalog_panel *panel)
 {
 {
@@ -496,11 +518,11 @@ static void dp_catalog_panel_setup_vsif_infoframe_sdp(
 		mst_offset = MMSS_DP1_VSCEXT_0 - MMSS_DP_VSCEXT_0;
 		mst_offset = MMSS_DP1_VSCEXT_0 - MMSS_DP_VSCEXT_0;
 
 
 	catalog = dp_catalog_get_priv(panel);
 	catalog = dp_catalog_get_priv(panel);
-	hdr = &panel->hdr_data.hdr_meta;
+	hdr = &panel->hdr_meta;
 	io_data = catalog->io.dp_link;
 	io_data = catalog->io.dp_link;
 
 
 	/* HEADER BYTE 1 */
 	/* HEADER BYTE 1 */
-	header = panel->hdr_data.vscext_header_byte1;
+	header = panel->dhdr_vsif_sdp.HB1;
 	parity = dp_header_get_parity(header);
 	parity = dp_header_get_parity(header);
 	data   = ((header << HEADER_BYTE_1_BIT)
 	data   = ((header << HEADER_BYTE_1_BIT)
 			| (parity << PARITY_BYTE_1_BIT));
 			| (parity << PARITY_BYTE_1_BIT));
@@ -510,7 +532,7 @@ static void dp_catalog_panel_setup_vsif_infoframe_sdp(
 	off += sizeof(data);
 	off += sizeof(data);
 
 
 	/* HEADER BYTE 2 */
 	/* HEADER BYTE 2 */
-	header = panel->hdr_data.vscext_header_byte2;
+	header = panel->dhdr_vsif_sdp.HB2;
 	parity = dp_header_get_parity(header);
 	parity = dp_header_get_parity(header);
 	data   = ((header << HEADER_BYTE_2_BIT)
 	data   = ((header << HEADER_BYTE_2_BIT)
 			| (parity << PARITY_BYTE_2_BIT));
 			| (parity << PARITY_BYTE_2_BIT));
@@ -518,7 +540,7 @@ static void dp_catalog_panel_setup_vsif_infoframe_sdp(
 			data);
 			data);
 
 
 	/* HEADER BYTE 3 */
 	/* HEADER BYTE 3 */
-	header = panel->hdr_data.vscext_header_byte3;
+	header = panel->dhdr_vsif_sdp.HB3;
 	parity = dp_header_get_parity(header);
 	parity = dp_header_get_parity(header);
 	data   = ((header << HEADER_BYTE_3_BIT)
 	data   = ((header << HEADER_BYTE_3_BIT)
 			| (parity << PARITY_BYTE_3_BIT));
 			| (parity << PARITY_BYTE_3_BIT));
@@ -541,6 +563,8 @@ static void dp_catalog_panel_setup_hdr_infoframe_sdp(
 	struct dp_io_data *io_data;
 	struct dp_io_data *io_data;
 	u32 header, parity, data, mst_offset = 0;
 	u32 header, parity, data, mst_offset = 0;
 	u8 buf[SZ_64], off = 0;
 	u8 buf[SZ_64], off = 0;
+	u32 const version = 0x01;
+	u32 const length = 0x1a;
 
 
 	if (panel->stream_id >= DP_STREAM_MAX) {
 	if (panel->stream_id >= DP_STREAM_MAX) {
 		DP_ERR("invalid stream_id:%d\n", panel->stream_id);
 		DP_ERR("invalid stream_id:%d\n", panel->stream_id);
@@ -551,11 +575,11 @@ static void dp_catalog_panel_setup_hdr_infoframe_sdp(
 		mst_offset = MMSS_DP1_GENERIC2_0 - MMSS_DP_GENERIC2_0;
 		mst_offset = MMSS_DP1_GENERIC2_0 - MMSS_DP_GENERIC2_0;
 
 
 	catalog = dp_catalog_get_priv(panel);
 	catalog = dp_catalog_get_priv(panel);
-	hdr = &panel->hdr_data.hdr_meta;
+	hdr = &panel->hdr_meta;
 	io_data = catalog->io.dp_link;
 	io_data = catalog->io.dp_link;
 
 
 	/* HEADER BYTE 1 */
 	/* HEADER BYTE 1 */
-	header = panel->hdr_data.shdr_header_byte1;
+	header = panel->shdr_if_sdp.HB1;
 	parity = dp_header_get_parity(header);
 	parity = dp_header_get_parity(header);
 	data   = ((header << HEADER_BYTE_1_BIT)
 	data   = ((header << HEADER_BYTE_1_BIT)
 			| (parity << PARITY_BYTE_1_BIT));
 			| (parity << PARITY_BYTE_1_BIT));
@@ -565,7 +589,7 @@ static void dp_catalog_panel_setup_hdr_infoframe_sdp(
 	off += sizeof(data);
 	off += sizeof(data);
 
 
 	/* HEADER BYTE 2 */
 	/* HEADER BYTE 2 */
-	header = panel->hdr_data.shdr_header_byte2;
+	header = panel->shdr_if_sdp.HB2;
 	parity = dp_header_get_parity(header);
 	parity = dp_header_get_parity(header);
 	data   = ((header << HEADER_BYTE_2_BIT)
 	data   = ((header << HEADER_BYTE_2_BIT)
 			| (parity << PARITY_BYTE_2_BIT));
 			| (parity << PARITY_BYTE_2_BIT));
@@ -573,7 +597,7 @@ static void dp_catalog_panel_setup_hdr_infoframe_sdp(
 			data);
 			data);
 
 
 	/* HEADER BYTE 3 */
 	/* HEADER BYTE 3 */
-	header = panel->hdr_data.shdr_header_byte3;
+	header = panel->shdr_if_sdp.HB3;
 	parity = dp_header_get_parity(header);
 	parity = dp_header_get_parity(header);
 	data   = ((header << HEADER_BYTE_3_BIT)
 	data   = ((header << HEADER_BYTE_3_BIT)
 			| (parity << PARITY_BYTE_3_BIT));
 			| (parity << PARITY_BYTE_3_BIT));
@@ -584,8 +608,8 @@ static void dp_catalog_panel_setup_hdr_infoframe_sdp(
 	memcpy(buf + off, &data, sizeof(data));
 	memcpy(buf + off, &data, sizeof(data));
 	off += sizeof(data);
 	off += sizeof(data);
 
 
-	data = panel->hdr_data.version;
-	data |= panel->hdr_data.length << 8;
+	data = version;
+	data |= length << 8;
 	data |= hdr->eotf << 16;
 	data |= hdr->eotf << 16;
 	dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC2_2 + mst_offset,
 	dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC2_2 + mst_offset,
 			data);
 			data);
@@ -661,7 +685,7 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel)
 	struct dp_catalog_private *catalog;
 	struct dp_catalog_private *catalog;
 	struct dp_io_data *io_data;
 	struct dp_io_data *io_data;
 	u32 header, parity, data, mst_offset = 0;
 	u32 header, parity, data, mst_offset = 0;
-	u8 bpc, off = 0;
+	u8 off = 0;
 	u8 buf[SZ_128];
 	u8 buf[SZ_128];
 
 
 	if (!panel) {
 	if (!panel) {
@@ -681,7 +705,7 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel)
 	io_data = catalog->io.dp_link;
 	io_data = catalog->io.dp_link;
 
 
 	/* HEADER BYTE 1 */
 	/* HEADER BYTE 1 */
-	header = panel->hdr_data.vsc_header_byte1;
+	header = panel->vsc_colorimetry.header.HB1;
 	parity = dp_header_get_parity(header);
 	parity = dp_header_get_parity(header);
 	data   = ((header << HEADER_BYTE_1_BIT)
 	data   = ((header << HEADER_BYTE_1_BIT)
 			| (parity << PARITY_BYTE_1_BIT));
 			| (parity << PARITY_BYTE_1_BIT));
@@ -691,7 +715,7 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel)
 	off += sizeof(data);
 	off += sizeof(data);
 
 
 	/* HEADER BYTE 2 */
 	/* HEADER BYTE 2 */
-	header = panel->hdr_data.vsc_header_byte2;
+	header = panel->vsc_colorimetry.header.HB2;
 	parity = dp_header_get_parity(header);
 	parity = dp_header_get_parity(header);
 	data   = ((header << HEADER_BYTE_2_BIT)
 	data   = ((header << HEADER_BYTE_2_BIT)
 			| (parity << PARITY_BYTE_2_BIT));
 			| (parity << PARITY_BYTE_2_BIT));
@@ -699,7 +723,7 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel)
 			data);
 			data);
 
 
 	/* HEADER BYTE 3 */
 	/* HEADER BYTE 3 */
-	header = panel->hdr_data.vsc_header_byte3;
+	header = panel->vsc_colorimetry.header.HB3;
 	parity = dp_header_get_parity(header);
 	parity = dp_header_get_parity(header);
 	data   = ((header << HEADER_BYTE_3_BIT)
 	data   = ((header << HEADER_BYTE_3_BIT)
 			| (parity << PARITY_BYTE_3_BIT));
 			| (parity << PARITY_BYTE_3_BIT));
@@ -731,24 +755,9 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel)
 	memcpy(buf + off, &data, sizeof(data));
 	memcpy(buf + off, &data, sizeof(data));
 	off += sizeof(data);
 	off += sizeof(data);
 
 
-	switch (panel->hdr_data.bpc) {
-	default:
-	case 10:
-		bpc = BIT(1);
-		break;
-	case 8:
-		bpc = BIT(0);
-		break;
-	case 6:
-		bpc = 0;
-		break;
-	}
-
-	data = (panel->hdr_data.colorimetry & 0xF) |
-		((panel->hdr_data.pixel_encoding & 0xF) << 4) |
-		(bpc << 8) |
-		((panel->hdr_data.dynamic_range & 0x1) << 15) |
-		((panel->hdr_data.content_type & 0x7) << 16);
+	data = (panel->vsc_colorimetry.data[16] & 0xFF) |
+		((panel->vsc_colorimetry.data[17] & 0xFF) << 8) |
+		((panel->vsc_colorimetry.data[18] & 0x7) << 16);
 
 
 	dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC0_6 + mst_offset,
 	dp_write(catalog->exe_mode, io_data, MMSS_DP_GENERIC0_6 + mst_offset,
 			data);
 			data);
@@ -775,15 +784,125 @@ static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog_panel *panel)
 			DUMP_PREFIX_NONE, 16, 4, buf, off, false);
 			DUMP_PREFIX_NONE, 16, 4, buf, off, false);
 }
 }
 
 
+static void dp_catalog_panel_config_sdp(struct dp_catalog_panel *panel,
+	bool en)
+{
+	struct dp_catalog_private *catalog;
+	struct dp_io_data *io_data;
+	u32 cfg, cfg2;
+	u32 sdp_cfg_off = 0;
+	u32 sdp_cfg2_off = 0;
+
+	if (panel->stream_id >= DP_STREAM_MAX) {
+		DP_ERR("invalid stream_id:%d\n", panel->stream_id);
+		return;
+	}
+
+	catalog = dp_catalog_get_priv(panel);
+	io_data = catalog->io.dp_link;
+
+	if (panel->stream_id == DP_STREAM_1) {
+		sdp_cfg_off = MMSS_DP1_SDP_CFG - MMSS_DP_SDP_CFG;
+		sdp_cfg2_off = MMSS_DP1_SDP_CFG2 - MMSS_DP_SDP_CFG2;
+	}
+
+	cfg = dp_read(catalog->exe_mode, io_data,
+				MMSS_DP_SDP_CFG + sdp_cfg_off);
+	cfg2 = dp_read(catalog->exe_mode, io_data,
+				MMSS_DP_SDP_CFG2 + sdp_cfg2_off);
+
+	if (en) {
+		/* GEN0_SDP_EN */
+		cfg |= BIT(17);
+		dp_write(catalog->exe_mode, io_data,
+				 MMSS_DP_SDP_CFG + sdp_cfg_off, cfg);
+
+		/* GENERIC0_SDPSIZE */
+		cfg2 |= BIT(16);
+		dp_write(catalog->exe_mode, io_data,
+				 MMSS_DP_SDP_CFG2 + sdp_cfg2_off, cfg2);
+
+		/* setup the GENERIC0 in case of en = true */
+		dp_catalog_panel_setup_vsc_sdp(panel);
+
+	} else {
+		/* GEN0_SDP_EN */
+		cfg &= ~BIT(17);
+		dp_write(catalog->exe_mode, io_data,
+				 MMSS_DP_SDP_CFG + sdp_cfg_off, cfg);
+
+		/* GENERIC0_SDPSIZE */
+		cfg2 &= ~BIT(16);
+		dp_write(catalog->exe_mode, io_data,
+				 MMSS_DP_SDP_CFG2 + sdp_cfg2_off, cfg2);
+	}
+
+	dp_catalog_panel_sdp_update(panel);
+}
+
+static void dp_catalog_panel_config_misc(struct dp_catalog_panel *panel)
+{
+	struct dp_catalog_private *catalog;
+	struct dp_io_data *io_data;
+	u32 reg_offset = 0;
+
+	if (!panel) {
+		pr_err("invalid input\n");
+		return;
+	}
+
+	if (panel->stream_id >= DP_STREAM_MAX) {
+		pr_err("invalid stream_id:%d\n", panel->stream_id);
+		return;
+	}
+
+	catalog = dp_catalog_get_priv(panel);
+	io_data = catalog->io.dp_link;
+
+	if (panel->stream_id == DP_STREAM_1)
+		reg_offset = DP1_MISC1_MISC0 - DP_MISC1_MISC0;
+
+	DP_DEBUG("misc settings = 0x%x\n", panel->misc_val);
+	dp_write(catalog->exe_mode, io_data, DP_MISC1_MISC0 + reg_offset,
+			panel->misc_val);
+}
+
+static int dp_catalog_panel_set_colorspace(struct dp_catalog_panel *panel,
+bool vsc_supported)
+{
+	struct dp_catalog_private *catalog;
+	struct dp_io_data *io_data;
+
+	if (!panel) {
+		pr_err("invalid input\n");
+		return -EINVAL;
+	}
+
+	if (panel->stream_id >= DP_STREAM_MAX) {
+		pr_err("invalid stream_id:%d\n", panel->stream_id);
+		return -EINVAL;
+	}
+
+	catalog = dp_catalog_get_priv(panel);
+	io_data = catalog->io.dp_link;
+
+	if (vsc_supported) {
+		dp_catalog_panel_setup_vsc_sdp(panel);
+		dp_catalog_panel_sdp_update(panel);
+	} else
+		dp_catalog_panel_config_misc(panel);
+
+	return 0;
+}
+
 static void dp_catalog_panel_config_hdr(struct dp_catalog_panel *panel, bool en,
 static void dp_catalog_panel_config_hdr(struct dp_catalog_panel *panel, bool en,
-		u32 dhdr_max_pkts)
+	u32 dhdr_max_pkts, bool flush)
 {
 {
 	struct dp_catalog_private *catalog;
 	struct dp_catalog_private *catalog;
 	struct dp_io_data *io_data;
 	struct dp_io_data *io_data;
 	u32 cfg, cfg2, cfg4, misc;
 	u32 cfg, cfg2, cfg4, misc;
 	u32 sdp_cfg_off = 0;
 	u32 sdp_cfg_off = 0;
 	u32 sdp_cfg2_off = 0;
 	u32 sdp_cfg2_off = 0;
-	u32 sdp_cfg3_off = 0;
 	u32 sdp_cfg4_off = 0;
 	u32 sdp_cfg4_off = 0;
 	u32 misc1_misc0_off = 0;
 	u32 misc1_misc0_off = 0;
 
 
@@ -803,7 +922,6 @@ static void dp_catalog_panel_config_hdr(struct dp_catalog_panel *panel, bool en,
 	if (panel->stream_id == DP_STREAM_1) {
 	if (panel->stream_id == DP_STREAM_1) {
 		sdp_cfg_off = MMSS_DP1_SDP_CFG - MMSS_DP_SDP_CFG;
 		sdp_cfg_off = MMSS_DP1_SDP_CFG - MMSS_DP_SDP_CFG;
 		sdp_cfg2_off = MMSS_DP1_SDP_CFG2 - MMSS_DP_SDP_CFG2;
 		sdp_cfg2_off = MMSS_DP1_SDP_CFG2 - MMSS_DP_SDP_CFG2;
-		sdp_cfg3_off = MMSS_DP1_SDP_CFG3 - MMSS_DP_SDP_CFG3;
 		sdp_cfg4_off = MMSS_DP1_SDP_CFG4 - MMSS_DP_SDP_CFG4;
 		sdp_cfg4_off = MMSS_DP1_SDP_CFG4 - MMSS_DP_SDP_CFG4;
 		misc1_misc0_off = DP1_MISC1_MISC0 - DP_MISC1_MISC0;
 		misc1_misc0_off = DP1_MISC1_MISC0 - DP_MISC1_MISC0;
 	}
 	}
@@ -826,34 +944,30 @@ static void dp_catalog_panel_config_hdr(struct dp_catalog_panel *panel, bool en,
 			dp_catalog_panel_setup_vsif_infoframe_sdp(panel);
 			dp_catalog_panel_setup_vsif_infoframe_sdp(panel);
 		}
 		}
 
 
-		/* GEN0_SDP_EN, GEN2_SDP_EN */
-		cfg |= BIT(17) | BIT(19);
+		/* GEN2_SDP_EN */
+		cfg |= BIT(19);
 		dp_write(catalog->exe_mode, io_data,
 		dp_write(catalog->exe_mode, io_data,
 				MMSS_DP_SDP_CFG + sdp_cfg_off, cfg);
 				MMSS_DP_SDP_CFG + sdp_cfg_off, cfg);
 
 
-		/* GENERIC0_SDPSIZE GENERIC2_SDPSIZE */
-		cfg2 |= BIT(16) | BIT(20);
+		/* GENERIC2_SDPSIZE */
+		cfg2 |= BIT(20);
 		dp_write(catalog->exe_mode, io_data,
 		dp_write(catalog->exe_mode, io_data,
 				MMSS_DP_SDP_CFG2 + sdp_cfg2_off, cfg2);
 				MMSS_DP_SDP_CFG2 + sdp_cfg2_off, cfg2);
 
 
-		dp_catalog_panel_setup_vsc_sdp(panel);
 		dp_catalog_panel_setup_hdr_infoframe_sdp(panel);
 		dp_catalog_panel_setup_hdr_infoframe_sdp(panel);
 
 
-		/* indicates presence of VSC (BIT(6) of MISC1) */
-		misc |= BIT(14);
-
-		if (panel->hdr_data.hdr_meta.eotf)
+		if (panel->hdr_meta.eotf)
 			DP_DEBUG("Enabled\n");
 			DP_DEBUG("Enabled\n");
 		else
 		else
 			DP_DEBUG("Reset\n");
 			DP_DEBUG("Reset\n");
 	} else {
 	} else {
-		/* VSCEXT_SDP_EN, GEN0_SDP_EN */
-		cfg &= ~BIT(16) & ~BIT(17) & ~BIT(19);
+		/* VSCEXT_SDP_ENG */
+		cfg &= ~BIT(16) & ~BIT(19);
 		dp_write(catalog->exe_mode, io_data,
 		dp_write(catalog->exe_mode, io_data,
 				MMSS_DP_SDP_CFG + sdp_cfg_off, cfg);
 				MMSS_DP_SDP_CFG + sdp_cfg_off, cfg);
 
 
 		/* GENERIC0_SDPSIZE GENERIC2_SDPSIZE */
 		/* GENERIC0_SDPSIZE GENERIC2_SDPSIZE */
-		cfg2 &= ~BIT(16) & ~BIT(20);
+		cfg2 &= ~BIT(20);
 		dp_write(catalog->exe_mode, io_data,
 		dp_write(catalog->exe_mode, io_data,
 				MMSS_DP_SDP_CFG2 + sdp_cfg2_off, cfg2);
 				MMSS_DP_SDP_CFG2 + sdp_cfg2_off, cfg2);
 
 
@@ -862,19 +976,13 @@ static void dp_catalog_panel_config_hdr(struct dp_catalog_panel *panel, bool en,
 		dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG4
 		dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG4
 				+ sdp_cfg4_off, cfg4);
 				+ sdp_cfg4_off, cfg4);
 
 
-		/* switch back to MSA */
-		misc &= ~BIT(14);
-
 		DP_DEBUG("Disabled\n");
 		DP_DEBUG("Disabled\n");
 	}
 	}
 
 
-	dp_write(catalog->exe_mode, io_data, DP_MISC1_MISC0 + misc1_misc0_off,
-			misc);
-
-	dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG3 + sdp_cfg3_off,
-			0x01);
-	dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG3 + sdp_cfg3_off,
-			0x00);
+	if (flush) {
+		DP_DEBUG("flushing HDR metadata\n");
+		dp_catalog_panel_sdp_update(panel);
+	}
 }
 }
 
 
 static void dp_catalog_panel_update_transfer_unit(
 static void dp_catalog_panel_update_transfer_unit(
@@ -1109,33 +1217,6 @@ static void dp_catalog_ctrl_mainlink_ctrl(struct dp_catalog_ctrl *ctrl,
 	}
 	}
 }
 }
 
 
-static void dp_catalog_panel_config_misc(struct dp_catalog_panel *panel)
-{
-	struct dp_catalog_private *catalog;
-	struct dp_io_data *io_data;
-	u32 reg_offset = 0;
-
-	if (!panel) {
-		DP_ERR("invalid input\n");
-		return;
-	}
-
-	if (panel->stream_id >= DP_STREAM_MAX) {
-		DP_ERR("invalid stream_id:%d\n", panel->stream_id);
-		return;
-	}
-
-	catalog = dp_catalog_get_priv(panel);
-	io_data = catalog->io.dp_link;
-
-	if (panel->stream_id == DP_STREAM_1)
-		reg_offset = DP1_MISC1_MISC0 - DP_MISC1_MISC0;
-
-	DP_DEBUG("misc settings = 0x%x\n", panel->misc_val);
-	dp_write(catalog->exe_mode, io_data, DP_MISC1_MISC0 + reg_offset,
-			panel->misc_val);
-}
-
 static void dp_catalog_panel_config_msa(struct dp_catalog_panel *panel,
 static void dp_catalog_panel_config_msa(struct dp_catalog_panel *panel,
 					u32 rate, u32 stream_rate_khz)
 					u32 rate, u32 stream_rate_khz)
 {
 {
@@ -2494,7 +2575,6 @@ static void dp_catalog_panel_config_spd(struct dp_catalog_panel *panel)
 	u32 offset = 0;
 	u32 offset = 0;
 	u32 sdp_cfg_off = 0;
 	u32 sdp_cfg_off = 0;
 	u32 sdp_cfg2_off = 0;
 	u32 sdp_cfg2_off = 0;
-	u32 sdp_cfg3_off = 0;
 
 
 	/*
 	/*
 	 * Source Device Information
 	 * Source Device Information
@@ -2567,7 +2647,6 @@ static void dp_catalog_panel_config_spd(struct dp_catalog_panel *panel)
 	if (panel->stream_id == DP_STREAM_1) {
 	if (panel->stream_id == DP_STREAM_1) {
 		sdp_cfg_off = MMSS_DP1_SDP_CFG - MMSS_DP_SDP_CFG;
 		sdp_cfg_off = MMSS_DP1_SDP_CFG - MMSS_DP_SDP_CFG;
 		sdp_cfg2_off = MMSS_DP1_SDP_CFG2 - MMSS_DP_SDP_CFG2;
 		sdp_cfg2_off = MMSS_DP1_SDP_CFG2 - MMSS_DP_SDP_CFG2;
-		sdp_cfg3_off = MMSS_DP1_SDP_CFG3 - MMSS_DP_SDP_CFG3;
 	}
 	}
 
 
 	spd_cfg = dp_read(catalog->exe_mode, io_data,
 	spd_cfg = dp_read(catalog->exe_mode, io_data,
@@ -2584,10 +2663,7 @@ static void dp_catalog_panel_config_spd(struct dp_catalog_panel *panel)
 	dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG2 + sdp_cfg2_off,
 	dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG2 + sdp_cfg2_off,
 			spd_cfg2);
 			spd_cfg2);
 
 
-	dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG3 + sdp_cfg3_off,
-				0x1);
-	dp_write(catalog->exe_mode, io_data, MMSS_DP_SDP_CFG3 + sdp_cfg3_off,
-				0x0);
+	dp_catalog_panel_sdp_update(panel);
 }
 }
 
 
 static void dp_catalog_get_io_buf(struct dp_catalog_private *catalog)
 static void dp_catalog_get_io_buf(struct dp_catalog_private *catalog)
@@ -2745,9 +2821,11 @@ struct dp_catalog *dp_catalog_get(struct device *dev, struct dp_parser *parser)
 	struct dp_catalog_panel panel = {
 	struct dp_catalog_panel panel = {
 		.timing_cfg = dp_catalog_panel_timing_cfg,
 		.timing_cfg = dp_catalog_panel_timing_cfg,
 		.config_hdr = dp_catalog_panel_config_hdr,
 		.config_hdr = dp_catalog_panel_config_hdr,
+		.config_sdp = dp_catalog_panel_config_sdp,
 		.tpg_config = dp_catalog_panel_tpg_cfg,
 		.tpg_config = dp_catalog_panel_tpg_cfg,
 		.config_spd = dp_catalog_panel_config_spd,
 		.config_spd = dp_catalog_panel_config_spd,
 		.config_misc = dp_catalog_panel_config_misc,
 		.config_misc = dp_catalog_panel_config_misc,
+		.set_colorspace = dp_catalog_panel_set_colorspace,
 		.config_msa = dp_catalog_panel_config_msa,
 		.config_msa = dp_catalog_panel_config_msa,
 		.update_transfer_unit = dp_catalog_panel_update_transfer_unit,
 		.update_transfer_unit = dp_catalog_panel_update_transfer_unit,
 		.config_ctrl = dp_catalog_panel_config_ctrl,
 		.config_ctrl = dp_catalog_panel_config_ctrl,

+ 12 - 28
msm/dp/dp_catalog.h

@@ -6,6 +6,7 @@
 #ifndef _DP_CATALOG_H_
 #ifndef _DP_CATALOG_H_
 #define _DP_CATALOG_H_
 #define _DP_CATALOG_H_
 
 
+#include <drm/drm_dp_helper.h>
 #include <drm/msm_drm.h>
 #include <drm/msm_drm.h>
 
 
 #include "dp_parser.h"
 #include "dp_parser.h"
@@ -39,32 +40,9 @@ enum dp_stream_id {
 	DP_STREAM_MAX,
 	DP_STREAM_MAX,
 };
 };
 
 
-struct dp_catalog_hdr_data {
-	u32 vsc_header_byte0;
-	u32 vsc_header_byte1;
-	u32 vsc_header_byte2;
-	u32 vsc_header_byte3;
-
-	u32 vscext_header_byte0;
-	u32 vscext_header_byte1;
-	u32 vscext_header_byte2;
-	u32 vscext_header_byte3;
-
-	u32 shdr_header_byte0;
-	u32 shdr_header_byte1;
-	u32 shdr_header_byte2;
-	u32 shdr_header_byte3;
-
-	u32 bpc;
-
-	u32 version;
-	u32 length;
-	u32 pixel_encoding;
-	u32 colorimetry;
-	u32 dynamic_range;
-	u32 content_type;
-
-	struct drm_msm_ext_hdr_metadata hdr_meta;
+struct dp_catalog_vsc_sdp_colorimetry {
+	struct dp_sdp_header header;
+	u8 data[32];
 };
 };
 
 
 struct dp_catalog_aux {
 struct dp_catalog_aux {
@@ -197,7 +175,10 @@ struct dp_catalog_panel {
 	u8 *spd_vendor_name;
 	u8 *spd_vendor_name;
 	u8 *spd_product_description;
 	u8 *spd_product_description;
 
 
-	struct dp_catalog_hdr_data hdr_data;
+	struct dp_catalog_vsc_sdp_colorimetry vsc_colorimetry;
+	struct dp_sdp_header dhdr_vsif_sdp;
+	struct dp_sdp_header shdr_if_sdp;
+	struct drm_msm_ext_hdr_metadata hdr_meta;
 
 
 	/* TPG */
 	/* TPG */
 	u32 hsync_period;
 	u32 hsync_period;
@@ -222,7 +203,10 @@ struct dp_catalog_panel {
 
 
 	int (*timing_cfg)(struct dp_catalog_panel *panel);
 	int (*timing_cfg)(struct dp_catalog_panel *panel);
 	void (*config_hdr)(struct dp_catalog_panel *panel, bool en,
 	void (*config_hdr)(struct dp_catalog_panel *panel, bool en,
-			u32 dhdr_max_pkts);
+		u32 dhdr_max_pkts, bool flush);
+	void (*config_sdp)(struct dp_catalog_panel *panel, bool en);
+	int (*set_colorspace)(struct dp_catalog_panel *panel,
+		 bool vsc_supported);
 	void (*tpg_config)(struct dp_catalog_panel *panel, bool enable);
 	void (*tpg_config)(struct dp_catalog_panel *panel, bool enable);
 	void (*config_spd)(struct dp_catalog_panel *panel);
 	void (*config_spd)(struct dp_catalog_panel *panel);
 	void (*config_misc)(struct dp_catalog_panel *panel);
 	void (*config_misc)(struct dp_catalog_panel *panel);

+ 45 - 2
msm/dp/dp_display.c

@@ -1627,7 +1627,7 @@ static void dp_display_stream_post_enable(struct dp_display_private *dp,
 			struct dp_panel *dp_panel)
 			struct dp_panel *dp_panel)
 {
 {
 	dp_panel->spd_config(dp_panel);
 	dp_panel->spd_config(dp_panel);
-	dp_panel->setup_hdr(dp_panel, NULL, false, 0);
+	dp_panel->setup_hdr(dp_panel, NULL, false, 0, true);
 }
 }
 
 
 static int dp_display_post_enable(struct dp_display *dp_display, void *panel)
 static int dp_display_post_enable(struct dp_display *dp_display, void *panel)
@@ -1676,6 +1676,14 @@ end:
 	return 0;
 	return 0;
 }
 }
 
 
+static void dp_display_clear_colorspaces(struct dp_display *dp_display)
+{
+	struct drm_connector *connector;
+
+	connector = dp_display->base_connector;
+	connector->color_enc_fmt = 0;
+}
+
 static int dp_display_pre_disable(struct dp_display *dp_display, void *panel)
 static int dp_display_pre_disable(struct dp_display *dp_display, void *panel)
 {
 {
 	struct dp_display_private *dp;
 	struct dp_display_private *dp;
@@ -1732,6 +1740,8 @@ static int dp_display_pre_disable(struct dp_display *dp_display, void *panel)
 		}
 		}
 	}
 	}
 
 
+	dp_display_clear_colorspaces(dp_display);
+
 clean:
 clean:
 	if (dp_panel->audio_supported)
 	if (dp_panel->audio_supported)
 		dp_panel->audio->off(dp_panel->audio);
 		dp_panel->audio->off(dp_panel->audio);
@@ -2082,8 +2092,10 @@ static int dp_display_config_hdr(struct dp_display *dp_display, void *panel,
 			struct drm_msm_ext_hdr_metadata *hdr, bool dhdr_update)
 			struct drm_msm_ext_hdr_metadata *hdr, bool dhdr_update)
 {
 {
 	struct dp_panel *dp_panel;
 	struct dp_panel *dp_panel;
+	struct sde_connector *sde_conn;
 	struct dp_display_private *dp;
 	struct dp_display_private *dp;
 	u64 core_clk_rate;
 	u64 core_clk_rate;
+	bool flush_hdr;
 
 
 	if (!dp_display || !panel) {
 	if (!dp_display || !panel) {
 		DP_ERR("invalid input\n");
 		DP_ERR("invalid input\n");
@@ -2092,6 +2104,7 @@ static int dp_display_config_hdr(struct dp_display *dp_display, void *panel,
 
 
 	dp_panel = panel;
 	dp_panel = panel;
 	dp = container_of(dp_display, struct dp_display_private, dp_display);
 	dp = container_of(dp_display, struct dp_display_private, dp_display);
+	sde_conn =  to_sde_connector(dp_panel->connector);
 
 
 	core_clk_rate = dp->power->clk_get_rate(dp->power, "core_clk");
 	core_clk_rate = dp->power->clk_get_rate(dp->power, "core_clk");
 	if (!core_clk_rate) {
 	if (!core_clk_rate) {
@@ -2099,7 +2112,36 @@ static int dp_display_config_hdr(struct dp_display *dp_display, void *panel,
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
-	return dp_panel->setup_hdr(dp_panel, hdr, dhdr_update, core_clk_rate);
+	/*
+	 * In rare cases where HDR metadata is updated independently
+	 * flush the HDR metadata immediately instead of relying on
+	 * the colorspace
+	 */
+	flush_hdr = !sde_conn->colorspace_updated;
+
+	if (flush_hdr)
+		DP_DEBUG("flushing the HDR metadata\n");
+	else
+		DP_DEBUG("piggy-backing with colorspace\n");
+
+	return dp_panel->setup_hdr(dp_panel, hdr, dhdr_update,
+		core_clk_rate, flush_hdr);
+}
+
+static int dp_display_setup_colospace(struct dp_display *dp_display,
+		void *panel,
+		u32 colorspace)
+{
+	struct dp_panel *dp_panel;
+
+	if (!dp_display || !panel) {
+		pr_err("invalid input\n");
+		return -EINVAL;
+	}
+
+	dp_panel = panel;
+
+	return dp_panel->set_colorspace(dp_panel, colorspace);
 }
 }
 
 
 static int dp_display_create_workqueue(struct dp_display_private *dp)
 static int dp_display_create_workqueue(struct dp_display_private *dp)
@@ -2623,6 +2665,7 @@ static int dp_display_probe(struct platform_device *pdev)
 					dp_display_mst_get_fixed_topology_port;
 					dp_display_mst_get_fixed_topology_port;
 	g_dp_display->wakeup_phy_layer =
 	g_dp_display->wakeup_phy_layer =
 					dp_display_wakeup_phy_layer;
 					dp_display_wakeup_phy_layer;
+	g_dp_display->set_colorspace = dp_display_setup_colospace;
 
 
 	rc = component_add(&pdev->dev, &dp_display_comp_ops);
 	rc = component_add(&pdev->dev, &dp_display_comp_ops);
 	if (rc) {
 	if (rc) {

+ 2 - 0
msm/dp/dp_display.h

@@ -93,6 +93,8 @@ struct dp_display {
 	int (*config_hdr)(struct dp_display *dp_display, void *panel,
 	int (*config_hdr)(struct dp_display *dp_display, void *panel,
 				struct drm_msm_ext_hdr_metadata *hdr_meta,
 				struct drm_msm_ext_hdr_metadata *hdr_meta,
 				bool dhdr_update);
 				bool dhdr_update);
+	int (*set_colorspace)(struct dp_display *dp_display, void *panel,
+				u32 colorspace);
 	int (*post_init)(struct dp_display *dp_display);
 	int (*post_init)(struct dp_display *dp_display);
 	int (*mst_install)(struct dp_display *dp_display,
 	int (*mst_install)(struct dp_display *dp_display,
 			struct dp_mst_drm_install_info *mst_install_info);
 			struct dp_mst_drm_install_info *mst_install_info);

+ 45 - 0
msm/dp/dp_drm.c

@@ -326,6 +326,25 @@ int dp_connector_config_hdr(struct drm_connector *connector, void *display,
 			c_state->dyn_hdr_meta.dynamic_hdr_update);
 			c_state->dyn_hdr_meta.dynamic_hdr_update);
 }
 }
 
 
+int dp_connector_set_colorspace(struct drm_connector *connector,
+	void *display)
+{
+	struct dp_display *dp_display = display;
+	struct sde_connector *sde_conn;
+
+	if (!dp_display || !connector)
+		return -EINVAL;
+
+	sde_conn = to_sde_connector(connector);
+	if (!sde_conn->drv_panel) {
+		pr_err("invalid dp panel\n");
+		return -EINVAL;
+	}
+
+	return dp_display->set_colorspace(dp_display,
+		sde_conn->drv_panel, connector->state->colorspace);
+}
+
 int dp_connector_post_init(struct drm_connector *connector, void *display)
 int dp_connector_post_init(struct drm_connector *connector, void *display)
 {
 {
 	int rc;
 	int rc;
@@ -469,6 +488,32 @@ void dp_connector_post_open(struct drm_connector *connector, void *display)
 		dp->post_open(dp);
 		dp->post_open(dp);
 }
 }
 
 
+int dp_connector_atomic_check(struct drm_connector *connector,
+	void *display,
+	struct drm_connector_state *c_state)
+{
+	struct sde_connector *sde_conn;
+	struct drm_connector_state *old_state =
+		drm_atomic_get_old_connector_state(c_state->state, connector);
+
+	if (!connector || !display)
+		return -EINVAL;
+
+	sde_conn = to_sde_connector(connector);
+
+	/*
+	 * Marking the colorspace has been changed
+	 * the flag shall be checked in the pre_kickoff
+	 * to configure the new colorspace in HW
+	 */
+	if (c_state->colorspace != old_state->colorspace) {
+		DP_DEBUG("colorspace has been updated\n");
+		sde_conn->colorspace_updated = true;
+	}
+
+	return 0;
+}
+
 int dp_connector_get_modes(struct drm_connector *connector,
 int dp_connector_get_modes(struct drm_connector *connector,
 		void *display, const struct msm_resource_caps_info *avail_res)
 		void *display, const struct msm_resource_caps_info *avail_res)
 {
 {

+ 21 - 0
msm/dp/dp_drm.h

@@ -37,6 +37,27 @@ int dp_connector_config_hdr(struct drm_connector *connector,
 		void *display,
 		void *display,
 		struct sde_connector_state *c_state);
 		struct sde_connector_state *c_state);
 
 
+/**
+ * dp_connector_atomic_check - callback to perform atomic
+ * check for DP
+ * @connector: Pointer to drm connector structure
+ * @display: Pointer to private display handle
+ * @c_state: connect state data
+ * Returns: Zero on success
+ */
+int dp_connector_atomic_check(struct drm_connector *connector,
+	void *display,
+	struct drm_connector_state *c_state);
+
+/**
+ * dp_connector_set_colorspace - callback to set new colorspace
+ * @connector: Pointer to drm connector structure
+ * @display: Pointer to private display handle
+ * Returns: Zero on success
+ */
+int dp_connector_set_colorspace(struct drm_connector *connector,
+	void *display);
+
 /**
 /**
  * dp_connector_post_init - callback to perform additional initialization steps
  * dp_connector_post_init - callback to perform additional initialization steps
  * @connector: Pointer to drm connector structure
  * @connector: Pointer to drm connector structure

+ 1 - 1
msm/dp/dp_link.c

@@ -1352,7 +1352,7 @@ static int dp_link_get_colorimetry_config(struct dp_link *dp_link)
 	/* Only RGB_VESA nd RGB_CEA supported for now */
 	/* Only RGB_VESA nd RGB_CEA supported for now */
 	switch (dr) {
 	switch (dr) {
 	case DP_DYNAMIC_RANGE_RGB_CEA:
 	case DP_DYNAMIC_RANGE_RGB_CEA:
-		cc = BIT(3);
+		cc = BIT(2);
 		break;
 		break;
 	case DP_DYNAMIC_RANGE_RGB_VESA:
 	case DP_DYNAMIC_RANGE_RGB_VESA:
 	default:
 	default:

+ 277 - 42
msm/dp/dp_panel.c

@@ -189,6 +189,98 @@ struct tu_algo_data {
 	s64 ratio;
 	s64 ratio;
 };
 };
 
 
+/**
+ * Mapper function which outputs colorimetry and dynamic range
+ * to be used for a given colorspace value when the vsc sdp
+ * packets are used to change the colorimetry.
+ */
+static void get_sdp_colorimetry_range(struct dp_panel_private *panel,
+	u32 colorspace, u32 *colorimetry, u32 *dynamic_range)
+{
+
+	u32 cc;
+
+	/*
+	 * Some rules being used for assignment of dynamic
+	 * range for colorimetry using SDP:
+	 *
+	 * 1) If compliance test is ongoing return sRGB with
+	 *    CEA primaries
+	 * 2) For BT2020 cases, dynamic range shall be CEA
+	 * 3) For DCI-P3 cases, as per HW team dynamic range
+	 *    shall be VESA for RGB and CEA for YUV content
+	 *    Hence defaulting to RGB and picking VESA
+	 * 4) Default shall be sRGB with VESA
+	 */
+
+	cc = panel->link->get_colorimetry_config(panel->link);
+
+	if (cc) {
+		*colorimetry = sRGB;
+		*dynamic_range = CEA;
+		return;
+	}
+
+	switch (colorspace) {
+	case DRM_MODE_COLORIMETRY_BT2020_RGB:
+		*colorimetry = ITU_R_BT_2020_RGB;
+		*dynamic_range = CEA;
+		break;
+	case DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65:
+	case DRM_MODE_COLORIMETRY_DCI_P3_RGB_THEATER:
+		*colorimetry = DCI_P3;
+		*dynamic_range = VESA;
+		break;
+	default:
+		*colorimetry = sRGB;
+		*dynamic_range = VESA;
+	}
+}
+
+/**
+ * Mapper function which outputs colorimetry to be used for a
+ * given colorspace value when misc field of MSA is used to
+ * change the colorimetry. Currently only RGB formats have been
+ * added. This API will be extended to YUV once its supported on DP.
+ */
+static u8 get_misc_colorimetry_val(struct dp_panel_private *panel,
+	u32 colorspace)
+{
+	u8 colorimetry;
+	u32 cc;
+
+	cc = panel->link->get_colorimetry_config(panel->link);
+	/*
+	 * If there is a non-zero value then compliance test-case
+	 * is going on, otherwise we can honor the colorspace setting
+	 */
+	if (cc)
+		return cc;
+
+	switch (colorspace) {
+	case DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65:
+	case DRM_MODE_COLORIMETRY_DCI_P3_RGB_THEATER:
+		colorimetry = 0x7;
+		break;
+	case DRM_MODE_DP_COLORIMETRY_SRGB:
+		colorimetry = 0x4;
+		break;
+	case DRM_MODE_DP_COLORIMETRY_RGB_WIDE_GAMUT:
+		colorimetry = 0x3;
+		break;
+	case DRM_MODE_DP_COLORIMETRY_SCRGB:
+		colorimetry = 0xb;
+		break;
+	case DRM_MODE_COLORIMETRY_OPRGB:
+		colorimetry = 0xc;
+		break;
+	default:
+		colorimetry = 0;
+	}
+
+	return colorimetry;
+}
+
 static int _tu_param_compare(s64 a, s64 b)
 static int _tu_param_compare(s64 a, s64 b)
 {
 {
 	u32 a_int, a_frac, a_sign;
 	u32 a_int, a_frac, a_sign;
@@ -2485,7 +2577,11 @@ static int dp_panel_deinit_panel_info(struct dp_panel *dp_panel, u32 flags)
 {
 {
 	int rc = 0;
 	int rc = 0;
 	struct dp_panel_private *panel;
 	struct dp_panel_private *panel;
-	struct dp_catalog_hdr_data *hdr;
+	struct drm_msm_ext_hdr_metadata *hdr_meta;
+	struct dp_sdp_header *dhdr_vsif_sdp;
+	struct sde_connector *sde_conn;
+	struct dp_sdp_header *shdr_if_sdp;
+	struct dp_catalog_vsc_sdp_colorimetry *vsc_colorimetry;
 	struct drm_connector *connector;
 	struct drm_connector *connector;
 	struct sde_connector_state *c_state;
 	struct sde_connector_state *c_state;
 
 
@@ -2500,17 +2596,26 @@ static int dp_panel_deinit_panel_info(struct dp_panel *dp_panel, u32 flags)
 	}
 	}
 
 
 	panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
 	panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
-	hdr = &panel->catalog->hdr_data;
+	hdr_meta = &panel->catalog->hdr_meta;
+	dhdr_vsif_sdp = &panel->catalog->dhdr_vsif_sdp;
+	shdr_if_sdp = &panel->catalog->shdr_if_sdp;
+	vsc_colorimetry = &panel->catalog->vsc_colorimetry;
 
 
 	if (!panel->custom_edid && dp_panel->edid_ctrl->edid)
 	if (!panel->custom_edid && dp_panel->edid_ctrl->edid)
 		sde_free_edid((void **)&dp_panel->edid_ctrl);
 		sde_free_edid((void **)&dp_panel->edid_ctrl);
 
 
 	dp_panel_set_stream_info(dp_panel, DP_STREAM_MAX, 0, 0, 0, 0);
 	dp_panel_set_stream_info(dp_panel, DP_STREAM_MAX, 0, 0, 0, 0);
 	memset(&dp_panel->pinfo, 0, sizeof(dp_panel->pinfo));
 	memset(&dp_panel->pinfo, 0, sizeof(dp_panel->pinfo));
-	memset(&hdr->hdr_meta, 0, sizeof(hdr->hdr_meta));
+	memset(hdr_meta, 0, sizeof(struct drm_msm_ext_hdr_metadata));
+	memset(dhdr_vsif_sdp, 0, sizeof(struct dp_sdp_header));
+	memset(shdr_if_sdp, 0, sizeof(struct dp_sdp_header));
+	memset(vsc_colorimetry, 0,
+		sizeof(struct dp_catalog_vsc_sdp_colorimetry));
+
 	panel->panel_on = false;
 	panel->panel_on = false;
 
 
 	connector = dp_panel->connector;
 	connector = dp_panel->connector;
+	sde_conn = to_sde_connector(connector);
 	c_state = to_sde_connector_state(connector->state);
 	c_state = to_sde_connector_state(connector->state);
 
 
 	connector->hdr_eotf = 0;
 	connector->hdr_eotf = 0;
@@ -2521,6 +2626,8 @@ static int dp_panel_deinit_panel_info(struct dp_panel *dp_panel, u32 flags)
 	connector->hdr_supported = false;
 	connector->hdr_supported = false;
 	connector->hdr_plus_app_ver = 0;
 	connector->hdr_plus_app_ver = 0;
 
 
+	sde_conn->colorspace_updated = false;
+
 	memset(&c_state->hdr_meta, 0, sizeof(c_state->hdr_meta));
 	memset(&c_state->hdr_meta, 0, sizeof(c_state->hdr_meta));
 	memset(&c_state->dyn_hdr_meta, 0, sizeof(c_state->dyn_hdr_meta));
 	memset(&c_state->dyn_hdr_meta, 0, sizeof(c_state->dyn_hdr_meta));
 
 
@@ -2651,14 +2758,133 @@ static u32 dp_panel_calc_dhdr_pkt_limit(struct dp_panel *dp_panel,
 	return calc_pkt_limit;
 	return calc_pkt_limit;
 }
 }
 
 
+static void dp_panel_setup_colorimetry_sdp(struct dp_panel *dp_panel,
+	u32 cspace)
+{
+	struct dp_panel_private *panel;
+	struct dp_catalog_vsc_sdp_colorimetry *hdr_colorimetry;
+	u8 bpc;
+	u32 colorimetry = 0;
+	u32 dynamic_range = 0;
+
+	panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
+	hdr_colorimetry = &panel->catalog->vsc_colorimetry;
+
+	hdr_colorimetry->header.HB0 = 0x00;
+	hdr_colorimetry->header.HB1 = 0x07;
+	hdr_colorimetry->header.HB2 = 0x05;
+	hdr_colorimetry->header.HB3 = 0x13;
+
+	get_sdp_colorimetry_range(panel, cspace, &colorimetry,
+		&dynamic_range);
+
+	/* VSC SDP Payload for DB16 */
+	hdr_colorimetry->data[16] = (RGB << 4) | colorimetry;
+
+	/* VSC SDP Payload for DB17 */
+	hdr_colorimetry->data[17] = (dynamic_range << 7);
+	bpc = (dp_panel->pinfo.bpp / 3);
+
+	switch (bpc) {
+	default:
+	case 10:
+		hdr_colorimetry->data[17] |= BIT(1);
+		break;
+	case 8:
+		hdr_colorimetry->data[17] |= BIT(0);
+		break;
+	case 6:
+		hdr_colorimetry->data[17] |= 0;
+		break;
+	}
+
+	/* VSC SDP Payload for DB18 */
+	hdr_colorimetry->data[18] = GRAPHICS;
+}
+
+static void dp_panel_setup_hdr_if(struct dp_panel_private *panel)
+{
+	struct dp_sdp_header *shdr_if;
+
+	shdr_if = &panel->catalog->shdr_if_sdp;
+
+	shdr_if->HB0 = 0x00;
+	shdr_if->HB1 = 0x87;
+	shdr_if->HB2 = 0x1D;
+	shdr_if->HB3 = 0x13 << 2;
+}
+
+static void dp_panel_setup_dhdr_vsif(struct dp_panel_private *panel)
+{
+	struct dp_sdp_header *dhdr_vsif;
+
+	dhdr_vsif = &panel->catalog->dhdr_vsif_sdp;
+
+	dhdr_vsif->HB0 = 0x00;
+	dhdr_vsif->HB1 = 0x81;
+	dhdr_vsif->HB2 = 0x1D;
+	dhdr_vsif->HB3 = 0x13 << 2;
+}
+
+static void dp_panel_setup_misc_colorimetry(struct dp_panel *dp_panel,
+	u32 colorspace)
+{
+	struct dp_panel_private *panel;
+	struct dp_catalog_panel *catalog;
+
+	panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
+	catalog = panel->catalog;
+
+	catalog->misc_val &= ~0x1e;
+
+	catalog->misc_val |= (get_misc_colorimetry_val(panel,
+		colorspace) << 1);
+}
+
+static int dp_panel_set_colorspace(struct dp_panel *dp_panel,
+	u32 colorspace)
+{
+	int rc = 0;
+	struct dp_panel_private *panel;
+
+	if (!dp_panel) {
+		pr_err("invalid input\n");
+		rc = -EINVAL;
+		goto end;
+	}
+
+	panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
+
+	if (panel->vsc_supported)
+		dp_panel_setup_colorimetry_sdp(dp_panel,
+			colorspace);
+	else
+		dp_panel_setup_misc_colorimetry(dp_panel,
+			colorspace);
+
+	/*
+	 * During the first frame update panel_on will be false and
+	 * the colorspace will be cached in the connector's state which
+	 * shall be used in the dp_panel_hw_cfg
+	 */
+	if (panel->panel_on) {
+		DP_DEBUG("panel is ON programming colorspace\n");
+		rc =  panel->catalog->set_colorspace(panel->catalog,
+			  panel->vsc_supported);
+	}
+
+end:
+	return rc;
+}
+
 static int dp_panel_setup_hdr(struct dp_panel *dp_panel,
 static int dp_panel_setup_hdr(struct dp_panel *dp_panel,
 		struct drm_msm_ext_hdr_metadata *hdr_meta,
 		struct drm_msm_ext_hdr_metadata *hdr_meta,
-		bool dhdr_update, u64 core_clk_rate)
+		bool dhdr_update, u64 core_clk_rate, bool flush)
 {
 {
 	int rc = 0, max_pkts = 0;
 	int rc = 0, max_pkts = 0;
 	struct dp_panel_private *panel;
 	struct dp_panel_private *panel;
-	struct dp_catalog_hdr_data *hdr;
 	struct dp_dhdr_maxpkt_calc_input input;
 	struct dp_dhdr_maxpkt_calc_input input;
+	struct drm_msm_ext_hdr_metadata *catalog_hdr_meta;
 
 
 	if (!dp_panel) {
 	if (!dp_panel) {
 		DP_ERR("invalid input\n");
 		DP_ERR("invalid input\n");
@@ -2667,11 +2893,12 @@ static int dp_panel_setup_hdr(struct dp_panel *dp_panel,
 	}
 	}
 
 
 	panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
 	panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
-	hdr = &panel->catalog->hdr_data;
+
+	catalog_hdr_meta = &panel->catalog->hdr_meta;
 
 
 	/* use cached meta data in case meta data not provided */
 	/* use cached meta data in case meta data not provided */
 	if (!hdr_meta) {
 	if (!hdr_meta) {
-		if (hdr->hdr_meta.hdr_state)
+		if (catalog_hdr_meta->hdr_state)
 			goto cached;
 			goto cached;
 		else
 		else
 			goto end;
 			goto end;
@@ -2679,41 +2906,18 @@ static int dp_panel_setup_hdr(struct dp_panel *dp_panel,
 
 
 	panel->hdr_state = hdr_meta->hdr_state;
 	panel->hdr_state = hdr_meta->hdr_state;
 
 
-	hdr->vsc_header_byte0 = 0x00;
-	hdr->vsc_header_byte1 = 0x07;
-	hdr->vsc_header_byte2 = 0x05;
-	hdr->vsc_header_byte3 = 0x13;
-
-	hdr->shdr_header_byte0 = 0x00;
-	hdr->shdr_header_byte1 = 0x87;
-	hdr->shdr_header_byte2 = 0x1D;
-	hdr->shdr_header_byte3 = 0x13 << 2;
-
-	/* VSC SDP Payload for DB16 */
-	hdr->pixel_encoding = RGB;
-	hdr->colorimetry = ITU_R_BT_2020_RGB;
-
-	/* VSC SDP Payload for DB17 */
-	hdr->dynamic_range = CEA;
-
-	/* VSC SDP Payload for DB18 */
-	hdr->content_type = GRAPHICS;
-
-	hdr->bpc = dp_panel->pinfo.bpp / 3;
+	dp_panel_setup_hdr_if(panel);
 
 
-	hdr->version = 0x01;
-	hdr->length = 0x1A;
-
-	if (panel->hdr_state)
-		memcpy(&hdr->hdr_meta, hdr_meta, sizeof(hdr->hdr_meta));
-	else
-		memset(&hdr->hdr_meta, 0, sizeof(hdr->hdr_meta));
+	if (panel->hdr_state) {
+		memcpy(catalog_hdr_meta, hdr_meta,
+			   sizeof(struct drm_msm_ext_hdr_metadata));
+	} else {
+		memset(catalog_hdr_meta, 0,
+			sizeof(struct drm_msm_ext_hdr_metadata));
+	}
 cached:
 cached:
 	if (dhdr_update) {
 	if (dhdr_update) {
-		hdr->vscext_header_byte0 = 0x00;
-		hdr->vscext_header_byte1 = 0x81;
-		hdr->vscext_header_byte2 = 0x1D;
-		hdr->vscext_header_byte3 = 0x13 << 2;
+		dp_panel_setup_dhdr_vsif(panel);
 
 
 		input.mdp_clk = core_clk_rate;
 		input.mdp_clk = core_clk_rate;
 		input.lclk = dp_panel->link_info.rate;
 		input.lclk = dp_panel->link_info.rate;
@@ -2729,7 +2933,7 @@ cached:
 	if (panel->panel_on) {
 	if (panel->panel_on) {
 		panel->catalog->stream_id = dp_panel->stream_id;
 		panel->catalog->stream_id = dp_panel->stream_id;
 		panel->catalog->config_hdr(panel->catalog, panel->hdr_state,
 		panel->catalog->config_hdr(panel->catalog, panel->hdr_state,
-				max_pkts);
+			max_pkts, flush);
 		if (dhdr_update)
 		if (dhdr_update)
 			panel->catalog->dhdr_flush(panel->catalog);
 			panel->catalog->dhdr_flush(panel->catalog);
 	}
 	}
@@ -2808,19 +3012,29 @@ static void dp_panel_config_misc(struct dp_panel *dp_panel)
 {
 {
 	struct dp_panel_private *panel;
 	struct dp_panel_private *panel;
 	struct dp_catalog_panel *catalog;
 	struct dp_catalog_panel *catalog;
+	struct drm_connector *connector;
 	u32 misc_val;
 	u32 misc_val;
-	u32 tb, cc;
+	u32 tb, cc, colorspace;
 
 
 	panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
 	panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
 	catalog = panel->catalog;
 	catalog = panel->catalog;
+	connector = dp_panel->connector;
+	cc = 0;
 
 
 	tb = panel->link->get_test_bits_depth(panel->link, dp_panel->pinfo.bpp);
 	tb = panel->link->get_test_bits_depth(panel->link, dp_panel->pinfo.bpp);
-	cc = panel->link->get_colorimetry_config(panel->link);
+	colorspace = connector->state->colorspace;
+
+
+	cc = (get_misc_colorimetry_val(panel, colorspace) << 1);
 
 
 	misc_val = cc;
 	misc_val = cc;
 	misc_val |= (tb << 5);
 	misc_val |= (tb << 5);
 	misc_val |= BIT(0); /* Configure clock to synchronous mode */
 	misc_val |= BIT(0); /* Configure clock to synchronous mode */
 
 
+	/* if VSC is supported then set bit 6 of MISC1 */
+	if (panel->vsc_supported)
+		misc_val |= BIT(14);
+
 	catalog->misc_val = misc_val;
 	catalog->misc_val = misc_val;
 	catalog->config_misc(catalog);
 	catalog->config_misc(catalog);
 }
 }
@@ -2862,9 +3076,21 @@ static void dp_panel_resolution_info(struct dp_panel_private *panel)
 		panel->link->link_params.lane_count);
 		panel->link->link_params.lane_count);
 }
 }
 
 
+static void dp_panel_config_sdp(struct dp_panel *dp_panel,
+	bool en)
+{
+	struct dp_panel_private *panel;
+
+	panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
+	panel->catalog->stream_id = dp_panel->stream_id;
+
+	panel->catalog->config_sdp(panel->catalog, en);
+}
+
 static int dp_panel_hw_cfg(struct dp_panel *dp_panel, bool enable)
 static int dp_panel_hw_cfg(struct dp_panel *dp_panel, bool enable)
 {
 {
 	struct dp_panel_private *panel;
 	struct dp_panel_private *panel;
+	struct drm_connector *connector;
 
 
 	if (!dp_panel) {
 	if (!dp_panel) {
 		DP_ERR("invalid input\n");
 		DP_ERR("invalid input\n");
@@ -2878,15 +3104,23 @@ static int dp_panel_hw_cfg(struct dp_panel *dp_panel, bool enable)
 
 
 	panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
 	panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
 	panel->catalog->stream_id = dp_panel->stream_id;
 	panel->catalog->stream_id = dp_panel->stream_id;
+	connector = dp_panel->connector;
 
 
 	if (enable) {
 	if (enable) {
 		dp_panel_config_ctrl(dp_panel);
 		dp_panel_config_ctrl(dp_panel);
 		dp_panel_config_misc(dp_panel);
 		dp_panel_config_misc(dp_panel);
 		dp_panel_config_msa(dp_panel);
 		dp_panel_config_msa(dp_panel);
+		if (panel->vsc_supported) {
+			dp_panel_setup_colorimetry_sdp(dp_panel,
+				connector->state->colorspace);
+			dp_panel_config_sdp(dp_panel, true);
+		}
 		dp_panel_config_dsc(dp_panel, enable);
 		dp_panel_config_dsc(dp_panel, enable);
 		dp_panel_config_tr_unit(dp_panel);
 		dp_panel_config_tr_unit(dp_panel);
 		dp_panel_config_timing(dp_panel);
 		dp_panel_config_timing(dp_panel);
 		dp_panel_resolution_info(panel);
 		dp_panel_resolution_info(panel);
+	} else {
+		dp_panel_config_sdp(dp_panel, false);
 	}
 	}
 
 
 	panel->catalog->config_dto(panel->catalog, !enable);
 	panel->catalog->config_dto(panel->catalog, !enable);
@@ -3100,6 +3334,7 @@ struct dp_panel *dp_panel_get(struct dp_panel_in *in)
 	dp_panel->tpg_config = dp_panel_tpg_config;
 	dp_panel->tpg_config = dp_panel_tpg_config;
 	dp_panel->spd_config = dp_panel_spd_config;
 	dp_panel->spd_config = dp_panel_spd_config;
 	dp_panel->setup_hdr = dp_panel_setup_hdr;
 	dp_panel->setup_hdr = dp_panel_setup_hdr;
+	dp_panel->set_colorspace = dp_panel_set_colorspace;
 	dp_panel->hdr_supported = dp_panel_hdr_supported;
 	dp_panel->hdr_supported = dp_panel_hdr_supported;
 	dp_panel->set_stream_info = dp_panel_set_stream_info;
 	dp_panel->set_stream_info = dp_panel_set_stream_info;
 	dp_panel->read_sink_status = dp_panel_read_sink_sts;
 	dp_panel->read_sink_status = dp_panel_read_sink_sts;

+ 3 - 1
msm/dp/dp_panel.h

@@ -150,7 +150,9 @@ struct dp_panel {
 	int (*set_dpcd)(struct dp_panel *dp_panel, u8 *dpcd);
 	int (*set_dpcd)(struct dp_panel *dp_panel, u8 *dpcd);
 	int (*setup_hdr)(struct dp_panel *dp_panel,
 	int (*setup_hdr)(struct dp_panel *dp_panel,
 		struct drm_msm_ext_hdr_metadata *hdr_meta,
 		struct drm_msm_ext_hdr_metadata *hdr_meta,
-		bool dhdr_update, u64 core_clk_rate);
+			bool dhdr_update, u64 core_clk_rate, bool flush);
+	int (*set_colorspace)(struct dp_panel *dp_panel,
+		u32 colorspace);
 	void (*tpg_config)(struct dp_panel *dp_panel, bool enable);
 	void (*tpg_config)(struct dp_panel *dp_panel, bool enable);
 	int (*spd_config)(struct dp_panel *dp_panel);
 	int (*spd_config)(struct dp_panel *dp_panel);
 	bool (*hdr_supported)(struct dp_panel *dp_panel);
 	bool (*hdr_supported)(struct dp_panel *dp_panel);

+ 1 - 0
msm/msm_drv.h

@@ -190,6 +190,7 @@ enum msm_mdp_conn_property {
 	CONNECTOR_PROP_ROI_V1,
 	CONNECTOR_PROP_ROI_V1,
 	CONNECTOR_PROP_BL_SCALE,
 	CONNECTOR_PROP_BL_SCALE,
 	CONNECTOR_PROP_SV_BL_SCALE,
 	CONNECTOR_PROP_SV_BL_SCALE,
+	CONNECTOR_PROP_SUPPORTED_COLORSPACES,
 
 
 	/* enum/bitmask properties */
 	/* enum/bitmask properties */
 	CONNECTOR_PROP_TOPOLOGY_NAME,
 	CONNECTOR_PROP_TOPOLOGY_NAME,

+ 51 - 0
msm/sde/sde_connector.c

@@ -606,6 +606,19 @@ static int _sde_connector_update_bl_scale(struct sde_connector *c_conn)
 	return rc;
 	return rc;
 }
 }
 
 
+void sde_connector_set_colorspace(struct sde_connector *c_conn)
+{
+	int rc = 0;
+
+	if (c_conn->ops.set_colorspace)
+		rc = c_conn->ops.set_colorspace(&c_conn->base,
+			c_conn->display);
+
+	if (rc)
+		SDE_ERROR_CONN(c_conn, "cannot apply new colorspace %d\n", rc);
+
+}
+
 void sde_connector_set_qsync_params(struct drm_connector *connector)
 void sde_connector_set_qsync_params(struct drm_connector *connector)
 {
 {
 	struct sde_connector *c_conn = to_sde_connector(connector);
 	struct sde_connector *c_conn = to_sde_connector(connector);
@@ -680,6 +693,12 @@ static int _sde_connector_update_dirty_properties(
 		}
 		}
 	}
 	}
 
 
+	/* if colorspace needs to be updated do it first */
+	if (c_conn->colorspace_updated) {
+		c_conn->colorspace_updated = false;
+		sde_connector_set_colorspace(c_conn);
+	}
+
 	/*
 	/*
 	 * Special handling for postproc properties and
 	 * Special handling for postproc properties and
 	 * for updating backlight if any unset backlight level is present
 	 * for updating backlight if any unset backlight level is present
@@ -1480,6 +1499,20 @@ static void sde_connector_update_hdr_props(struct drm_connector *connector)
 			&hdr, sizeof(hdr), CONNECTOR_PROP_EXT_HDR_INFO);
 			&hdr, sizeof(hdr), CONNECTOR_PROP_EXT_HDR_INFO);
 }
 }
 
 
+static void sde_connector_update_colorspace(struct drm_connector *connector)
+{
+	int ret;
+
+	ret = msm_property_set_property(
+			sde_connector_get_propinfo(connector),
+			sde_connector_get_property_state(connector->state),
+			CONNECTOR_PROP_SUPPORTED_COLORSPACES,
+				connector->color_enc_fmt);
+
+	if (ret)
+		SDE_ERROR("failed to set colorspace property for connector\n");
+}
+
 static enum drm_connector_status
 static enum drm_connector_status
 sde_connector_detect(struct drm_connector *connector, bool force)
 sde_connector_detect(struct drm_connector *connector, bool force)
 {
 {
@@ -1920,6 +1953,9 @@ static int sde_connector_get_modes(struct drm_connector *connector)
 	if (c_conn->hdr_capable)
 	if (c_conn->hdr_capable)
 		sde_connector_update_hdr_props(connector);
 		sde_connector_update_hdr_props(connector);
 
 
+	if (c_conn->connector_type == DRM_MODE_CONNECTOR_DisplayPort)
+		sde_connector_update_colorspace(connector);
+
 	return mode_count;
 	return mode_count;
 }
 }
 
 
@@ -2118,6 +2154,7 @@ static const struct drm_connector_helper_funcs sde_connector_helper_ops = {
 	.get_modes =    sde_connector_get_modes,
 	.get_modes =    sde_connector_get_modes,
 	.mode_valid =   sde_connector_mode_valid,
 	.mode_valid =   sde_connector_mode_valid,
 	.best_encoder = sde_connector_best_encoder,
 	.best_encoder = sde_connector_best_encoder,
+	.atomic_check = sde_connector_atomic_check,
 };
 };
 
 
 static const struct drm_connector_helper_funcs sde_connector_helper_ops_v2 = {
 static const struct drm_connector_helper_funcs sde_connector_helper_ops_v2 = {
@@ -2295,6 +2332,7 @@ static int _sde_connector_install_properties(struct drm_device *dev,
 {
 {
 	struct dsi_display *dsi_display;
 	struct dsi_display *dsi_display;
 	int rc;
 	int rc;
+	struct drm_connector *connector;
 
 
 	msm_property_install_blob(&c_conn->property_info, "capabilities",
 	msm_property_install_blob(&c_conn->property_info, "capabilities",
 			DRM_MODE_PROP_IMMUTABLE, CONNECTOR_PROP_SDE_INFO);
 			DRM_MODE_PROP_IMMUTABLE, CONNECTOR_PROP_SDE_INFO);
@@ -2307,6 +2345,8 @@ static int _sde_connector_install_properties(struct drm_device *dev,
 		return rc;
 		return rc;
 	}
 	}
 
 
+	connector = &c_conn->base;
+
 	msm_property_install_blob(&c_conn->property_info, "mode_properties",
 	msm_property_install_blob(&c_conn->property_info, "mode_properties",
 			DRM_MODE_PROP_IMMUTABLE, CONNECTOR_PROP_MODE_INFO);
 			DRM_MODE_PROP_IMMUTABLE, CONNECTOR_PROP_MODE_INFO);
 
 
@@ -2350,6 +2390,11 @@ static int _sde_connector_install_properties(struct drm_device *dev,
 			      &hdr,
 			      &hdr,
 			      sizeof(hdr),
 			      sizeof(hdr),
 			      CONNECTOR_PROP_EXT_HDR_INFO);
 			      CONNECTOR_PROP_EXT_HDR_INFO);
+
+		/* create and attach colorspace property for DP */
+		if (!drm_mode_create_colorspace_property(connector))
+			drm_object_attach_property(&connector->base,
+				connector->colorspace_property, 0);
 	}
 	}
 
 
 	msm_property_install_volatile_range(&c_conn->property_info,
 	msm_property_install_volatile_range(&c_conn->property_info,
@@ -2389,6 +2434,12 @@ static int _sde_connector_install_properties(struct drm_device *dev,
 	c_conn->bl_scale = MAX_BL_SCALE_LEVEL;
 	c_conn->bl_scale = MAX_BL_SCALE_LEVEL;
 	c_conn->bl_scale_sv = MAX_SV_BL_SCALE_LEVEL;
 	c_conn->bl_scale_sv = MAX_SV_BL_SCALE_LEVEL;
 
 
+	if (connector_type == DRM_MODE_CONNECTOR_DisplayPort)
+		msm_property_install_range(&c_conn->property_info,
+			"supported_colorspaces",
+			DRM_MODE_PROP_IMMUTABLE, 0, 0xffff, 0,
+			CONNECTOR_PROP_SUPPORTED_COLORSPACES);
+
 	/* enum/bitmask properties */
 	/* enum/bitmask properties */
 	msm_property_install_enum(&c_conn->property_info, "topology_name",
 	msm_property_install_enum(&c_conn->property_info, "topology_name",
 			DRM_MODE_PROP_IMMUTABLE, 0, e_topology_name,
 			DRM_MODE_PROP_IMMUTABLE, 0, e_topology_name,

+ 11 - 0
msm/sde/sde_connector.h

@@ -168,6 +168,14 @@ struct sde_connector_ops {
 	int (*set_backlight)(struct drm_connector *connector,
 	int (*set_backlight)(struct drm_connector *connector,
 			void *display, u32 bl_lvl);
 			void *display, u32 bl_lvl);
 
 
+	/**
+	 * set_colorspace - set colorspace for connector
+	 * @connector: Pointer to drm connector structure
+	 * @display: Pointer to private display structure
+	 */
+	int (*set_colorspace)(struct drm_connector *connector,
+			void *display);
+
 	/**
 	/**
 	 * soft_reset - perform a soft reset on the connector
 	 * soft_reset - perform a soft reset on the connector
 	 * @display: Pointer to private display structure
 	 * @display: Pointer to private display structure
@@ -400,6 +408,7 @@ struct sde_connector_dyn_hdr_metadata {
  * @allow_bl_update: Flag to indicate if BL update is allowed currently or not
  * @allow_bl_update: Flag to indicate if BL update is allowed currently or not
  * @qsync_mode: Cached Qsync mode, 0=disabled, 1=continuous mode
  * @qsync_mode: Cached Qsync mode, 0=disabled, 1=continuous mode
  * @qsync_updated: Qsync settings were updated
  * @qsync_updated: Qsync settings were updated
+ * @colorspace_updated: Colorspace property was updated
  * last_cmd_tx_sts: status of the last command transfer
  * last_cmd_tx_sts: status of the last command transfer
  * @hdr_capable: external hdr support present
  * @hdr_capable: external hdr support present
  * @core_clk_rate: MDP core clk rate used for dynamic HDR packet calculation
  * @core_clk_rate: MDP core clk rate used for dynamic HDR packet calculation
@@ -452,6 +461,8 @@ struct sde_connector {
 	u32 qsync_mode;
 	u32 qsync_mode;
 	bool qsync_updated;
 	bool qsync_updated;
 
 
+	bool colorspace_updated;
+
 	bool last_cmd_tx_sts;
 	bool last_cmd_tx_sts;
 	bool hdr_capable;
 	bool hdr_capable;
 };
 };

+ 2 - 0
msm/sde/sde_kms.c

@@ -1222,11 +1222,13 @@ static int _sde_kms_setup_displays(struct drm_device *dev,
 		.post_init  = dp_connector_post_init,
 		.post_init  = dp_connector_post_init,
 		.detect     = dp_connector_detect,
 		.detect     = dp_connector_detect,
 		.get_modes  = dp_connector_get_modes,
 		.get_modes  = dp_connector_get_modes,
+		.atomic_check = dp_connector_atomic_check,
 		.mode_valid = dp_connector_mode_valid,
 		.mode_valid = dp_connector_mode_valid,
 		.get_info   = dp_connector_get_info,
 		.get_info   = dp_connector_get_info,
 		.get_mode_info  = dp_connector_get_mode_info,
 		.get_mode_info  = dp_connector_get_mode_info,
 		.post_open  = dp_connector_post_open,
 		.post_open  = dp_connector_post_open,
 		.check_status = NULL,
 		.check_status = NULL,
+		.set_colorspace = dp_connector_set_colorspace,
 		.config_hdr = dp_connector_config_hdr,
 		.config_hdr = dp_connector_config_hdr,
 		.cmd_transfer = NULL,
 		.cmd_transfer = NULL,
 		.cont_splash_config = NULL,
 		.cont_splash_config = NULL,