All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/18] drm/i915: Pimp DP DFP handling
@ 2020-09-04 11:53 ` Ville Syrjala
  0 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjala @ 2020-09-04 11:53 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Attempt to deal with DP downstream facing ports (DFP) more
thoroughly. This involves reading more of the port caps
and dealing with various clock/bpc limitations.

And we try to enable YCbCr 444->420 conversion for HDMI DFPs
which could allow some 4k displays to actually use 4k on
pre-icl hardware (which doesn't have native 420 output),
assuming we don't run into some other hardware limits.

I dropped my earlier patches to also hook in the DP dual mode
adapter probing since sadly I've not actually seen a DP->DP++
dongle that passes through the i2c traffic for those.

Only pimped the SST side of things. Not sure what would
be required to get it all working for MST.

Ville Syrjälä (18):
  drm/dp: Dump downstream facing port caps
  drm/i915/lspcon: Do not send infoframes to non-HDMI sinks
  drm/dp: Define protocol converter DPCD registers
  drm/dp: Define more downstream facing port caps
  drm/i915: Reworkd DFP max bpc handling
  drm/dp: Add helpers to identify downstream facing port types
  drm/dp: Pimp drm_dp_downstream_max_bpc()
  drm/dp: Redo drm_dp_downstream_max_clock() as
    drm_dp_downstream_max_dotclock()
  drm/i915: Reworkd DP DFP clock handling
  drm/dp: Add drm_dp_downstream_{min,max}_tmds_clock()
  drm/i915: Deal with TMDS DFP clock limits
  drm/i915: Configure DP 1.3+ protocol converted HDMI mode
  drm/dp: Add drm_dp_downstream_mode()
  drm/i915: Handle downstream facing ports w/o EDID
  drm/i915: Extract intel_hdmi_has_audio()
  drm/i915: DP->HDMI TMDS clock limits vs. deep color
  drm/dp: Add helpers for DFP YCbCr 4:2:0 handling
  drm/i915: Do YCbCr 444->420 conversion via DP protocol converters

 drivers/gpu/drm/drm_dp_helper.c               | 382 +++++++++++++++---
 drivers/gpu/drm/drm_edid.c                    |  19 +
 drivers/gpu/drm/i915/display/intel_ddi.c      |  11 +-
 .../drm/i915/display/intel_display_debugfs.c  |   3 +-
 .../drm/i915/display/intel_display_types.h    |   9 +
 drivers/gpu/drm/i915/display/intel_dp.c       | 304 +++++++++++---
 drivers/gpu/drm/i915/display/intel_dp.h       |   1 +
 drivers/gpu/drm/i915/display/intel_hdmi.c     |  82 ++--
 drivers/gpu/drm/i915/display/intel_hdmi.h     |   2 +
 include/drm/drm_dp_helper.h                   |  63 ++-
 include/drm/drm_edid.h                        |   4 +
 11 files changed, 738 insertions(+), 142 deletions(-)

-- 
2.26.2

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [Intel-gfx] [PATCH v2 00/18] drm/i915: Pimp DP DFP handling
@ 2020-09-04 11:53 ` Ville Syrjala
  0 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjala @ 2020-09-04 11:53 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Attempt to deal with DP downstream facing ports (DFP) more
thoroughly. This involves reading more of the port caps
and dealing with various clock/bpc limitations.

And we try to enable YCbCr 444->420 conversion for HDMI DFPs
which could allow some 4k displays to actually use 4k on
pre-icl hardware (which doesn't have native 420 output),
assuming we don't run into some other hardware limits.

I dropped my earlier patches to also hook in the DP dual mode
adapter probing since sadly I've not actually seen a DP->DP++
dongle that passes through the i2c traffic for those.

Only pimped the SST side of things. Not sure what would
be required to get it all working for MST.

Ville Syrjälä (18):
  drm/dp: Dump downstream facing port caps
  drm/i915/lspcon: Do not send infoframes to non-HDMI sinks
  drm/dp: Define protocol converter DPCD registers
  drm/dp: Define more downstream facing port caps
  drm/i915: Reworkd DFP max bpc handling
  drm/dp: Add helpers to identify downstream facing port types
  drm/dp: Pimp drm_dp_downstream_max_bpc()
  drm/dp: Redo drm_dp_downstream_max_clock() as
    drm_dp_downstream_max_dotclock()
  drm/i915: Reworkd DP DFP clock handling
  drm/dp: Add drm_dp_downstream_{min,max}_tmds_clock()
  drm/i915: Deal with TMDS DFP clock limits
  drm/i915: Configure DP 1.3+ protocol converted HDMI mode
  drm/dp: Add drm_dp_downstream_mode()
  drm/i915: Handle downstream facing ports w/o EDID
  drm/i915: Extract intel_hdmi_has_audio()
  drm/i915: DP->HDMI TMDS clock limits vs. deep color
  drm/dp: Add helpers for DFP YCbCr 4:2:0 handling
  drm/i915: Do YCbCr 444->420 conversion via DP protocol converters

 drivers/gpu/drm/drm_dp_helper.c               | 382 +++++++++++++++---
 drivers/gpu/drm/drm_edid.c                    |  19 +
 drivers/gpu/drm/i915/display/intel_ddi.c      |  11 +-
 .../drm/i915/display/intel_display_debugfs.c  |   3 +-
 .../drm/i915/display/intel_display_types.h    |   9 +
 drivers/gpu/drm/i915/display/intel_dp.c       | 304 +++++++++++---
 drivers/gpu/drm/i915/display/intel_dp.h       |   1 +
 drivers/gpu/drm/i915/display/intel_hdmi.c     |  82 ++--
 drivers/gpu/drm/i915/display/intel_hdmi.h     |   2 +
 include/drm/drm_dp_helper.h                   |  63 ++-
 include/drm/drm_edid.h                        |   4 +
 11 files changed, 738 insertions(+), 142 deletions(-)

-- 
2.26.2

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [PATCH v2 01/18] drm/dp: Dump downstream facing port caps
  2020-09-04 11:53 ` [Intel-gfx] " Ville Syrjala
@ 2020-09-04 11:53   ` Ville Syrjala
  -1 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjala @ 2020-09-04 11:53 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

It helps when the logs have a dump of the DFP capabilities.

v2: Move the dumping to the new helper

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/drm_dp_helper.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index 1e7c638873c8..c21bbfc3d714 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -545,8 +545,13 @@ int drm_dp_read_downstream_info(struct drm_dp_aux *aux,
 	ret = drm_dp_dpcd_read(aux, DP_DOWNSTREAM_PORT_0, downstream_ports, len);
 	if (ret < 0)
 		return ret;
+	if (ret != len)
+		return -EIO;
 
-	return ret == len ? 0 : -EIO;
+	DRM_DEBUG_KMS("%s: DPCD DFP: %*ph\n",
+		      aux->name, len, downstream_ports);
+
+	return 0;
 }
 EXPORT_SYMBOL(drm_dp_read_downstream_info);
 
-- 
2.26.2

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [Intel-gfx] [PATCH v2 01/18] drm/dp: Dump downstream facing port caps
@ 2020-09-04 11:53   ` Ville Syrjala
  0 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjala @ 2020-09-04 11:53 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

It helps when the logs have a dump of the DFP capabilities.

v2: Move the dumping to the new helper

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/drm_dp_helper.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index 1e7c638873c8..c21bbfc3d714 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -545,8 +545,13 @@ int drm_dp_read_downstream_info(struct drm_dp_aux *aux,
 	ret = drm_dp_dpcd_read(aux, DP_DOWNSTREAM_PORT_0, downstream_ports, len);
 	if (ret < 0)
 		return ret;
+	if (ret != len)
+		return -EIO;
 
-	return ret == len ? 0 : -EIO;
+	DRM_DEBUG_KMS("%s: DPCD DFP: %*ph\n",
+		      aux->name, len, downstream_ports);
+
+	return 0;
 }
 EXPORT_SYMBOL(drm_dp_read_downstream_info);
 
-- 
2.26.2

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v2 02/18] drm/i915/lspcon: Do not send infoframes to non-HDMI sinks
  2020-09-04 11:53 ` [Intel-gfx] " Ville Syrjala
@ 2020-09-04 11:53   ` Ville Syrjala
  -1 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjala @ 2020-09-04 11:53 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Non-HDMI sinks shouldn't be sent infoframes. Check for that when
using LSPCON.

FIXME: How do we turn off infoframes once enabled? Do we even
       have to?

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_ddi.c           | 10 ++++------
 drivers/gpu/drm/i915/display/intel_display_types.h |  1 +
 drivers/gpu/drm/i915/display/intel_dp.c            |  7 ++++++-
 3 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
index 6af080542c96..28ff85493f25 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -3581,19 +3581,17 @@ static void intel_ddi_pre_enable(struct intel_atomic_state *state,
 		intel_ddi_pre_enable_hdmi(state, encoder, crtc_state,
 					  conn_state);
 	} else {
-		struct intel_lspcon *lspcon =
-				enc_to_intel_lspcon(encoder);
+		struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
 
 		intel_ddi_pre_enable_dp(state, encoder, crtc_state,
 					conn_state);
-		if (lspcon->active) {
-			struct intel_digital_port *dig_port =
-					enc_to_dig_port(encoder);
 
+		/* FIXME precompute everything properly */
+		/* FIXME how do we turn infoframes off again? */
+		if (dig_port->lspcon.active && dig_port->dp.has_hdmi_sink)
 			dig_port->set_infoframes(encoder,
 						 crtc_state->has_infoframe,
 						 crtc_state, conn_state);
-		}
 	}
 }
 
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 413b60337a0b..6f3a3dde99c8 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1277,6 +1277,7 @@ struct intel_dp {
 	u8 sink_count;
 	bool link_mst;
 	bool link_trained;
+	bool has_hdmi_sink;
 	bool has_audio;
 	bool reset_link_params;
 	u8 dpcd[DP_RECEIVER_CAP_SIZE];
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 8a673d0d7051..60bf01a8b4ad 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -6069,7 +6069,11 @@ intel_dp_set_edid(struct intel_dp *intel_dp)
 	edid = intel_dp_get_edid(intel_dp);
 	intel_connector->detect_edid = edid;
 
-	intel_dp->has_audio = drm_detect_monitor_audio(edid);
+	if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
+		intel_dp->has_hdmi_sink = drm_detect_hdmi_monitor(edid);
+		intel_dp->has_audio = drm_detect_monitor_audio(edid);
+	}
+
 	drm_dp_cec_set_edid(&intel_dp->aux, edid);
 	intel_dp->edid_quirks = drm_dp_get_edid_quirks(edid);
 }
@@ -6083,6 +6087,7 @@ intel_dp_unset_edid(struct intel_dp *intel_dp)
 	kfree(intel_connector->detect_edid);
 	intel_connector->detect_edid = NULL;
 
+	intel_dp->has_hdmi_sink = false;
 	intel_dp->has_audio = false;
 	intel_dp->edid_quirks = 0;
 }
-- 
2.26.2

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [Intel-gfx] [PATCH v2 02/18] drm/i915/lspcon: Do not send infoframes to non-HDMI sinks
@ 2020-09-04 11:53   ` Ville Syrjala
  0 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjala @ 2020-09-04 11:53 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Non-HDMI sinks shouldn't be sent infoframes. Check for that when
using LSPCON.

FIXME: How do we turn off infoframes once enabled? Do we even
       have to?

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_ddi.c           | 10 ++++------
 drivers/gpu/drm/i915/display/intel_display_types.h |  1 +
 drivers/gpu/drm/i915/display/intel_dp.c            |  7 ++++++-
 3 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
index 6af080542c96..28ff85493f25 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -3581,19 +3581,17 @@ static void intel_ddi_pre_enable(struct intel_atomic_state *state,
 		intel_ddi_pre_enable_hdmi(state, encoder, crtc_state,
 					  conn_state);
 	} else {
-		struct intel_lspcon *lspcon =
-				enc_to_intel_lspcon(encoder);
+		struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
 
 		intel_ddi_pre_enable_dp(state, encoder, crtc_state,
 					conn_state);
-		if (lspcon->active) {
-			struct intel_digital_port *dig_port =
-					enc_to_dig_port(encoder);
 
+		/* FIXME precompute everything properly */
+		/* FIXME how do we turn infoframes off again? */
+		if (dig_port->lspcon.active && dig_port->dp.has_hdmi_sink)
 			dig_port->set_infoframes(encoder,
 						 crtc_state->has_infoframe,
 						 crtc_state, conn_state);
-		}
 	}
 }
 
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 413b60337a0b..6f3a3dde99c8 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1277,6 +1277,7 @@ struct intel_dp {
 	u8 sink_count;
 	bool link_mst;
 	bool link_trained;
+	bool has_hdmi_sink;
 	bool has_audio;
 	bool reset_link_params;
 	u8 dpcd[DP_RECEIVER_CAP_SIZE];
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 8a673d0d7051..60bf01a8b4ad 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -6069,7 +6069,11 @@ intel_dp_set_edid(struct intel_dp *intel_dp)
 	edid = intel_dp_get_edid(intel_dp);
 	intel_connector->detect_edid = edid;
 
-	intel_dp->has_audio = drm_detect_monitor_audio(edid);
+	if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
+		intel_dp->has_hdmi_sink = drm_detect_hdmi_monitor(edid);
+		intel_dp->has_audio = drm_detect_monitor_audio(edid);
+	}
+
 	drm_dp_cec_set_edid(&intel_dp->aux, edid);
 	intel_dp->edid_quirks = drm_dp_get_edid_quirks(edid);
 }
@@ -6083,6 +6087,7 @@ intel_dp_unset_edid(struct intel_dp *intel_dp)
 	kfree(intel_connector->detect_edid);
 	intel_connector->detect_edid = NULL;
 
+	intel_dp->has_hdmi_sink = false;
 	intel_dp->has_audio = false;
 	intel_dp->edid_quirks = 0;
 }
-- 
2.26.2

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v2 03/18] drm/dp: Define protocol converter DPCD registers
  2020-09-04 11:53 ` [Intel-gfx] " Ville Syrjala
@ 2020-09-04 11:53   ` Ville Syrjala
  -1 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjala @ 2020-09-04 11:53 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

DP 1.3 and 1.4 introduced some new registers for DP->HDMI protocol
converters. Define those.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 include/drm/drm_dp_helper.h | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index 5c45195ced32..17d32d7632b6 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -984,6 +984,16 @@
 #define DP_CEC_TX_MESSAGE_BUFFER               0x3020
 #define DP_CEC_MESSAGE_BUFFER_LENGTH             0x10
 
+#define DP_PROTOCOL_CONVERTER_CONTROL_0		0x3050 /* DP 1.3 */
+# define DP_HDMI_DVI_OUTPUT_CONFIG		(1 << 0) /* DP 1.3 */
+#define DP_PROTOCOL_CONVERTER_CONTROL_1		0x3051 /* DP 1.3 */
+# define DP_CONVERSION_TO_YCBCR420_ENABLE	(1 << 0) /* DP 1.3 */
+# define DP_HDMI_EDID_PROCESSING_DISABLE	(1 << 1) /* DP 1.4 */
+# define DP_HDMI_AUTONOMOUS_SCRAMBLING_DISABLE	(1 << 2) /* DP 1.4 */
+# define DP_HDMI_FORCE_SCRAMBLING		(1 << 3) /* DP 1.4 */
+#define DP_PROTOCOL_CONVERTER_CONTROL_2		0x3052 /* DP 1.3 */
+# define DP_CONVERSION_TO_YCBCR422_ENABLE	(1 << 0) /* DP 1.3 */
+
 #define DP_AUX_HDCP_BKSV		0x68000
 #define DP_AUX_HDCP_RI_PRIME		0x68005
 #define DP_AUX_HDCP_AKSV		0x68007
-- 
2.26.2

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [Intel-gfx] [PATCH v2 03/18] drm/dp: Define protocol converter DPCD registers
@ 2020-09-04 11:53   ` Ville Syrjala
  0 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjala @ 2020-09-04 11:53 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

DP 1.3 and 1.4 introduced some new registers for DP->HDMI protocol
converters. Define those.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 include/drm/drm_dp_helper.h | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index 5c45195ced32..17d32d7632b6 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -984,6 +984,16 @@
 #define DP_CEC_TX_MESSAGE_BUFFER               0x3020
 #define DP_CEC_MESSAGE_BUFFER_LENGTH             0x10
 
+#define DP_PROTOCOL_CONVERTER_CONTROL_0		0x3050 /* DP 1.3 */
+# define DP_HDMI_DVI_OUTPUT_CONFIG		(1 << 0) /* DP 1.3 */
+#define DP_PROTOCOL_CONVERTER_CONTROL_1		0x3051 /* DP 1.3 */
+# define DP_CONVERSION_TO_YCBCR420_ENABLE	(1 << 0) /* DP 1.3 */
+# define DP_HDMI_EDID_PROCESSING_DISABLE	(1 << 1) /* DP 1.4 */
+# define DP_HDMI_AUTONOMOUS_SCRAMBLING_DISABLE	(1 << 2) /* DP 1.4 */
+# define DP_HDMI_FORCE_SCRAMBLING		(1 << 3) /* DP 1.4 */
+#define DP_PROTOCOL_CONVERTER_CONTROL_2		0x3052 /* DP 1.3 */
+# define DP_CONVERSION_TO_YCBCR422_ENABLE	(1 << 0) /* DP 1.3 */
+
 #define DP_AUX_HDCP_BKSV		0x68000
 #define DP_AUX_HDCP_RI_PRIME		0x68005
 #define DP_AUX_HDCP_AKSV		0x68007
-- 
2.26.2

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v2 04/18] drm/dp: Define more downstream facing port caps
  2020-09-04 11:53 ` [Intel-gfx] " Ville Syrjala
@ 2020-09-04 11:53   ` Ville Syrjala
  -1 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjala @ 2020-09-04 11:53 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Our definitions for the DPCD DFP capabilities are lacking.
Add the missing bits.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 include/drm/drm_dp_helper.h | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index 17d32d7632b6..86461a40066b 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -386,12 +386,18 @@
 # define DP_DS_PORT_TYPE_WIRELESS           6
 # define DP_DS_PORT_HPD			    (1 << 3)
 /* offset 1 for VGA is maximum megapixels per second / 8 */
-/* offset 2 */
+/* offset 1 for DVI/HDMI is maximum TMDS clock in Mbps / 2.5 */
+/* offset 2 for VGA/DVI/HDMI */
 # define DP_DS_MAX_BPC_MASK	            (3 << 0)
 # define DP_DS_8BPC		            0
 # define DP_DS_10BPC		            1
 # define DP_DS_12BPC		            2
 # define DP_DS_16BPC		            3
+/* offset 3 for DVI */
+# define DP_DS_DVI_DUAL_LINK		    (1 << 1)
+# define DP_DS_DVI_HIGH_COLOR_DEPTH	    (1 << 2)
+/* offset 3 for HDMI */
+# define DP_DS_HDMI_FRAME_SEQ_TO_FRAME_PACK (1 << 0)
 
 #define DP_MAX_DOWNSTREAM_PORTS		    0x10
 
-- 
2.26.2

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [Intel-gfx] [PATCH v2 04/18] drm/dp: Define more downstream facing port caps
@ 2020-09-04 11:53   ` Ville Syrjala
  0 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjala @ 2020-09-04 11:53 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Our definitions for the DPCD DFP capabilities are lacking.
Add the missing bits.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 include/drm/drm_dp_helper.h | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index 17d32d7632b6..86461a40066b 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -386,12 +386,18 @@
 # define DP_DS_PORT_TYPE_WIRELESS           6
 # define DP_DS_PORT_HPD			    (1 << 3)
 /* offset 1 for VGA is maximum megapixels per second / 8 */
-/* offset 2 */
+/* offset 1 for DVI/HDMI is maximum TMDS clock in Mbps / 2.5 */
+/* offset 2 for VGA/DVI/HDMI */
 # define DP_DS_MAX_BPC_MASK	            (3 << 0)
 # define DP_DS_8BPC		            0
 # define DP_DS_10BPC		            1
 # define DP_DS_12BPC		            2
 # define DP_DS_16BPC		            3
+/* offset 3 for DVI */
+# define DP_DS_DVI_DUAL_LINK		    (1 << 1)
+# define DP_DS_DVI_HIGH_COLOR_DEPTH	    (1 << 2)
+/* offset 3 for HDMI */
+# define DP_DS_HDMI_FRAME_SEQ_TO_FRAME_PACK (1 << 0)
 
 #define DP_MAX_DOWNSTREAM_PORTS		    0x10
 
-- 
2.26.2

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v2 05/18] drm/i915: Reworkd DFP max bpc handling
  2020-09-04 11:53 ` [Intel-gfx] " Ville Syrjala
@ 2020-09-04 11:53   ` Ville Syrjala
  -1 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjala @ 2020-09-04 11:53 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Stash the downstream facing port max bpc away during
intel_dp_set_edid(). We'll soon need the EDID in there so
we can't figure this out so easily during .compute_config() anymore.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 .../drm/i915/display/intel_display_types.h    |  5 +++++
 drivers/gpu/drm/i915/display/intel_dp.c       | 22 ++++++++++++++-----
 2 files changed, 21 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 6f3a3dde99c8..8699c001969d 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1379,6 +1379,11 @@ struct intel_dp {
 	/* Displayport compliance testing */
 	struct intel_dp_compliance compliance;
 
+	/* Downstream facing port caps */
+	struct {
+		u8 max_bpc;
+	} dfp;
+
 	/* Display stream compression testing */
 	bool force_dsc_en;
 
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 60bf01a8b4ad..2c8e82d97a34 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1973,13 +1973,12 @@ static int intel_dp_compute_bpp(struct intel_dp *intel_dp,
 {
 	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
 	struct intel_connector *intel_connector = intel_dp->attached_connector;
-	int bpp, bpc;
+	int bpp;
 
 	bpp = pipe_config->pipe_bpp;
-	bpc = drm_dp_downstream_max_bpc(intel_dp->dpcd, intel_dp->downstream_ports);
 
-	if (bpc > 0)
-		bpp = min(bpp, 3*bpc);
+	if (intel_dp->dfp.max_bpc)
+		bpp = min(bpp, 3 * intel_dp->dfp.max_bpc);
 
 	if (intel_dp_is_edp(intel_dp)) {
 		/* Get bpp from vbt only for panels that dont have bpp in edid */
@@ -6062,12 +6061,21 @@ intel_dp_get_edid(struct intel_dp *intel_dp)
 static void
 intel_dp_set_edid(struct intel_dp *intel_dp)
 {
-	struct intel_connector *intel_connector = intel_dp->attached_connector;
+	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+	struct intel_connector *connector = intel_dp->attached_connector;
 	struct edid *edid;
 
 	intel_dp_unset_edid(intel_dp);
 	edid = intel_dp_get_edid(intel_dp);
-	intel_connector->detect_edid = edid;
+	connector->detect_edid = edid;
+
+	intel_dp->dfp.max_bpc =
+		drm_dp_downstream_max_bpc(intel_dp->dpcd,
+					  intel_dp->downstream_ports);
+
+	drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] DFP max bpc %d\n",
+		    connector->base.base.id, connector->base.name,
+		    intel_dp->dfp.max_bpc);
 
 	if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
 		intel_dp->has_hdmi_sink = drm_detect_hdmi_monitor(edid);
@@ -6090,6 +6098,8 @@ intel_dp_unset_edid(struct intel_dp *intel_dp)
 	intel_dp->has_hdmi_sink = false;
 	intel_dp->has_audio = false;
 	intel_dp->edid_quirks = 0;
+
+	intel_dp->dfp.max_bpc = 0;
 }
 
 static int
-- 
2.26.2

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [Intel-gfx] [PATCH v2 05/18] drm/i915: Reworkd DFP max bpc handling
@ 2020-09-04 11:53   ` Ville Syrjala
  0 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjala @ 2020-09-04 11:53 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Stash the downstream facing port max bpc away during
intel_dp_set_edid(). We'll soon need the EDID in there so
we can't figure this out so easily during .compute_config() anymore.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 .../drm/i915/display/intel_display_types.h    |  5 +++++
 drivers/gpu/drm/i915/display/intel_dp.c       | 22 ++++++++++++++-----
 2 files changed, 21 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 6f3a3dde99c8..8699c001969d 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1379,6 +1379,11 @@ struct intel_dp {
 	/* Displayport compliance testing */
 	struct intel_dp_compliance compliance;
 
+	/* Downstream facing port caps */
+	struct {
+		u8 max_bpc;
+	} dfp;
+
 	/* Display stream compression testing */
 	bool force_dsc_en;
 
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 60bf01a8b4ad..2c8e82d97a34 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1973,13 +1973,12 @@ static int intel_dp_compute_bpp(struct intel_dp *intel_dp,
 {
 	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
 	struct intel_connector *intel_connector = intel_dp->attached_connector;
-	int bpp, bpc;
+	int bpp;
 
 	bpp = pipe_config->pipe_bpp;
-	bpc = drm_dp_downstream_max_bpc(intel_dp->dpcd, intel_dp->downstream_ports);
 
-	if (bpc > 0)
-		bpp = min(bpp, 3*bpc);
+	if (intel_dp->dfp.max_bpc)
+		bpp = min(bpp, 3 * intel_dp->dfp.max_bpc);
 
 	if (intel_dp_is_edp(intel_dp)) {
 		/* Get bpp from vbt only for panels that dont have bpp in edid */
@@ -6062,12 +6061,21 @@ intel_dp_get_edid(struct intel_dp *intel_dp)
 static void
 intel_dp_set_edid(struct intel_dp *intel_dp)
 {
-	struct intel_connector *intel_connector = intel_dp->attached_connector;
+	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+	struct intel_connector *connector = intel_dp->attached_connector;
 	struct edid *edid;
 
 	intel_dp_unset_edid(intel_dp);
 	edid = intel_dp_get_edid(intel_dp);
-	intel_connector->detect_edid = edid;
+	connector->detect_edid = edid;
+
+	intel_dp->dfp.max_bpc =
+		drm_dp_downstream_max_bpc(intel_dp->dpcd,
+					  intel_dp->downstream_ports);
+
+	drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] DFP max bpc %d\n",
+		    connector->base.base.id, connector->base.name,
+		    intel_dp->dfp.max_bpc);
 
 	if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
 		intel_dp->has_hdmi_sink = drm_detect_hdmi_monitor(edid);
@@ -6090,6 +6098,8 @@ intel_dp_unset_edid(struct intel_dp *intel_dp)
 	intel_dp->has_hdmi_sink = false;
 	intel_dp->has_audio = false;
 	intel_dp->edid_quirks = 0;
+
+	intel_dp->dfp.max_bpc = 0;
 }
 
 static int
-- 
2.26.2

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v2 06/18] drm/dp: Add helpers to identify downstream facing port types
  2020-09-04 11:53 ` [Intel-gfx] " Ville Syrjala
@ 2020-09-04 11:53   ` Ville Syrjala
  -1 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjala @ 2020-09-04 11:53 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Add a few helpers to let us better identify which kind of DFP
we're dealing with.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/drm_dp_helper.c | 60 +++++++++++++++++++++++++++++++++
 include/drm/drm_dp_helper.h     |  5 +++
 2 files changed, 65 insertions(+)

diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index c21bbfc3d714..0fcb94f7dbe5 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -363,6 +363,66 @@ int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux,
 }
 EXPORT_SYMBOL(drm_dp_dpcd_read_link_status);
 
+static bool is_edid_digital_input_dp(const struct edid *edid)
+{
+	return edid && edid->revision >= 4 &&
+		edid->input & DRM_EDID_INPUT_DIGITAL &&
+		(edid->input & DRM_EDID_DIGITAL_TYPE_MASK) == DRM_EDID_DIGITAL_TYPE_DP;
+}
+
+/**
+ * drm_dp_downstream_is_type() - is the downstream facing port of certain type?
+ * @dpcd: DisplayPort configuration data
+ * @port_cap: port capabilities
+ *
+ * Caveat: Only works with DPCD 1.1+ port caps.
+ *
+ * Returns whether the downstream facing port matches the type.
+ */
+bool drm_dp_downstream_is_type(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+			       const u8 port_cap[4], u8 type)
+{
+	return drm_dp_is_branch(dpcd) &&
+		dpcd[DP_DPCD_REV] >= 0x11 &&
+		(port_cap[0] & DP_DS_PORT_TYPE_MASK) == type;
+}
+EXPORT_SYMBOL(drm_dp_downstream_is_type);
+
+/**
+ * drm_dp_downstream_is_tmds() - is the downstream facing port TMDS?
+ * @dpcd: DisplayPort configuration data
+ * @port_cap: port capabilities
+ * @edid: EDID
+ *
+ * Returns whether the downstream facing port is TMDS (HDMI/DVI).
+ */
+bool drm_dp_downstream_is_tmds(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+			       const u8 port_cap[4],
+			       const struct edid *edid)
+{
+	if (dpcd[DP_DPCD_REV] < 0x11) {
+		switch (dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_TYPE_MASK) {
+		case DP_DWN_STRM_PORT_TYPE_TMDS:
+			return true;
+		default:
+			return false;
+		}
+	}
+
+	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
+	case DP_DS_PORT_TYPE_DP_DUALMODE:
+		if (is_edid_digital_input_dp(edid))
+			return false;
+		fallthrough;
+	case DP_DS_PORT_TYPE_DVI:
+	case DP_DS_PORT_TYPE_HDMI:
+		return true;
+	default:
+		return false;
+	}
+}
+EXPORT_SYMBOL(drm_dp_downstream_is_tmds);
+
 /**
  * drm_dp_send_real_edid_checksum() - send back real edid checksum value
  * @aux: DisplayPort AUX channel
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index 86461a40066b..4f946826dfce 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -1638,6 +1638,11 @@ bool drm_dp_send_real_edid_checksum(struct drm_dp_aux *aux,
 int drm_dp_read_downstream_info(struct drm_dp_aux *aux,
 				const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 				u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS]);
+bool drm_dp_downstream_is_type(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+			       const u8 port_cap[4], u8 type);
+bool drm_dp_downstream_is_tmds(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+			       const u8 port_cap[4],
+			       const struct edid *edid);
 int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 				const u8 port_cap[4]);
 int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
-- 
2.26.2

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [Intel-gfx] [PATCH v2 06/18] drm/dp: Add helpers to identify downstream facing port types
@ 2020-09-04 11:53   ` Ville Syrjala
  0 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjala @ 2020-09-04 11:53 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Add a few helpers to let us better identify which kind of DFP
we're dealing with.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/drm_dp_helper.c | 60 +++++++++++++++++++++++++++++++++
 include/drm/drm_dp_helper.h     |  5 +++
 2 files changed, 65 insertions(+)

diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index c21bbfc3d714..0fcb94f7dbe5 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -363,6 +363,66 @@ int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux,
 }
 EXPORT_SYMBOL(drm_dp_dpcd_read_link_status);
 
+static bool is_edid_digital_input_dp(const struct edid *edid)
+{
+	return edid && edid->revision >= 4 &&
+		edid->input & DRM_EDID_INPUT_DIGITAL &&
+		(edid->input & DRM_EDID_DIGITAL_TYPE_MASK) == DRM_EDID_DIGITAL_TYPE_DP;
+}
+
+/**
+ * drm_dp_downstream_is_type() - is the downstream facing port of certain type?
+ * @dpcd: DisplayPort configuration data
+ * @port_cap: port capabilities
+ *
+ * Caveat: Only works with DPCD 1.1+ port caps.
+ *
+ * Returns whether the downstream facing port matches the type.
+ */
+bool drm_dp_downstream_is_type(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+			       const u8 port_cap[4], u8 type)
+{
+	return drm_dp_is_branch(dpcd) &&
+		dpcd[DP_DPCD_REV] >= 0x11 &&
+		(port_cap[0] & DP_DS_PORT_TYPE_MASK) == type;
+}
+EXPORT_SYMBOL(drm_dp_downstream_is_type);
+
+/**
+ * drm_dp_downstream_is_tmds() - is the downstream facing port TMDS?
+ * @dpcd: DisplayPort configuration data
+ * @port_cap: port capabilities
+ * @edid: EDID
+ *
+ * Returns whether the downstream facing port is TMDS (HDMI/DVI).
+ */
+bool drm_dp_downstream_is_tmds(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+			       const u8 port_cap[4],
+			       const struct edid *edid)
+{
+	if (dpcd[DP_DPCD_REV] < 0x11) {
+		switch (dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_TYPE_MASK) {
+		case DP_DWN_STRM_PORT_TYPE_TMDS:
+			return true;
+		default:
+			return false;
+		}
+	}
+
+	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
+	case DP_DS_PORT_TYPE_DP_DUALMODE:
+		if (is_edid_digital_input_dp(edid))
+			return false;
+		fallthrough;
+	case DP_DS_PORT_TYPE_DVI:
+	case DP_DS_PORT_TYPE_HDMI:
+		return true;
+	default:
+		return false;
+	}
+}
+EXPORT_SYMBOL(drm_dp_downstream_is_tmds);
+
 /**
  * drm_dp_send_real_edid_checksum() - send back real edid checksum value
  * @aux: DisplayPort AUX channel
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index 86461a40066b..4f946826dfce 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -1638,6 +1638,11 @@ bool drm_dp_send_real_edid_checksum(struct drm_dp_aux *aux,
 int drm_dp_read_downstream_info(struct drm_dp_aux *aux,
 				const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 				u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS]);
+bool drm_dp_downstream_is_type(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+			       const u8 port_cap[4], u8 type);
+bool drm_dp_downstream_is_tmds(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+			       const u8 port_cap[4],
+			       const struct edid *edid);
 int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 				const u8 port_cap[4]);
 int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
-- 
2.26.2

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v2 07/18] drm/dp: Pimp drm_dp_downstream_max_bpc()
  2020-09-04 11:53 ` [Intel-gfx] " Ville Syrjala
@ 2020-09-04 11:53   ` Ville Syrjala
  -1 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjala @ 2020-09-04 11:53 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Deal with more cases in drm_dp_downstream_max_bpc():
- DPCD 1.0 -> assume 8bpc for non-DP
- DPCD 1.1+ DP (or DP++ with DP sink) -> allow anything
- DPCD 1.1+ TMDS -> check the caps, assume 8bpc if the value is crap
- anything else -> assume 8bpc

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/drm_dp_helper.c               | 69 +++++++++++--------
 .../drm/i915/display/intel_display_debugfs.c  |  3 +-
 drivers/gpu/drm/i915/display/intel_dp.c       |  2 +-
 include/drm/drm_dp_helper.h                   | 10 ++-
 4 files changed, 51 insertions(+), 33 deletions(-)

diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index 0fcb94f7dbe5..ab87209c25d8 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -653,36 +653,44 @@ int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 EXPORT_SYMBOL(drm_dp_downstream_max_clock);
 
 /**
- * drm_dp_downstream_max_bpc() - extract branch device max
- *                               bits per component
- * @dpcd: DisplayPort configuration data
- * @port_cap: port capabilities
- *
- * See also:
- * drm_dp_read_downstream_info()
- * drm_dp_downstream_max_clock()
- *
- * Returns: Max bpc on success or 0 if max bpc not defined
- */
+  * drm_dp_downstream_max_bpc() - extract downstream facing port max
+  *                               bits per component
+  * @dpcd: DisplayPort configuration data
+  * @port_cap: downstream facing port capabilities
+  * @edid: EDID
+  *
+  * Returns max bpc on success or 0 if max bpc not defined
+  */
 int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
-			      const u8 port_cap[4])
+			      const u8 port_cap[4],
+			      const struct edid *edid)
 {
-	int type = port_cap[0] & DP_DS_PORT_TYPE_MASK;
-	bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] &
-		DP_DETAILED_CAP_INFO_AVAILABLE;
-	int bpc;
-
-	if (!detailed_cap_info)
+	if (!drm_dp_is_branch(dpcd))
 		return 0;
 
-	switch (type) {
-	case DP_DS_PORT_TYPE_VGA:
-	case DP_DS_PORT_TYPE_DVI:
-	case DP_DS_PORT_TYPE_HDMI:
+	if (dpcd[DP_DPCD_REV] < 0x11) {
+		switch (dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_TYPE_MASK) {
+		case DP_DWN_STRM_PORT_TYPE_DP:
+			return 0;
+		default:
+			return 8;
+		}
+	}
+
+	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
+	case DP_DS_PORT_TYPE_DP:
+		return 0;
 	case DP_DS_PORT_TYPE_DP_DUALMODE:
-		bpc = port_cap[2] & DP_DS_MAX_BPC_MASK;
+		if (is_edid_digital_input_dp(edid))
+			return 0;
+		fallthrough;
+	case DP_DS_PORT_TYPE_HDMI:
+	case DP_DS_PORT_TYPE_DVI:
+	case DP_DS_PORT_TYPE_VGA:
+		if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
+			return 8;
 
-		switch (bpc) {
+		switch (port_cap[2] & DP_DS_MAX_BPC_MASK) {
 		case DP_DS_8BPC:
 			return 8;
 		case DP_DS_10BPC:
@@ -691,10 +699,12 @@ int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 			return 12;
 		case DP_DS_16BPC:
 			return 16;
+		default:
+			return 8;
 		}
-		fallthrough;
+		break;
 	default:
-		return 0;
+		return 8;
 	}
 }
 EXPORT_SYMBOL(drm_dp_downstream_max_bpc);
@@ -717,12 +727,15 @@ EXPORT_SYMBOL(drm_dp_downstream_id);
  * @m: pointer for debugfs file
  * @dpcd: DisplayPort configuration data
  * @port_cap: port capabilities
+ * @edid: EDID
  * @aux: DisplayPort AUX channel
  *
  */
 void drm_dp_downstream_debug(struct seq_file *m,
 			     const u8 dpcd[DP_RECEIVER_CAP_SIZE],
-			     const u8 port_cap[4], struct drm_dp_aux *aux)
+			     const u8 port_cap[4],
+			     const struct edid *edid,
+			     struct drm_dp_aux *aux)
 {
 	bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] &
 				 DP_DETAILED_CAP_INFO_AVAILABLE;
@@ -789,7 +802,7 @@ void drm_dp_downstream_debug(struct seq_file *m,
 				seq_printf(m, "\t\tMax TMDS clock: %d kHz\n", clk);
 		}
 
-		bpc = drm_dp_downstream_max_bpc(dpcd, port_cap);
+		bpc = drm_dp_downstream_max_bpc(dpcd, port_cap, edid);
 
 		if (bpc > 0)
 			seq_printf(m, "\t\tMax bpc: %d\n", bpc);
diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
index 53a0a3d9a22d..0bf31f9a8af5 100644
--- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
+++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
@@ -626,6 +626,7 @@ static void intel_dp_info(struct seq_file *m,
 {
 	struct intel_encoder *intel_encoder = intel_attached_encoder(intel_connector);
 	struct intel_dp *intel_dp = enc_to_intel_dp(intel_encoder);
+	const struct drm_property_blob *edid = intel_connector->base.edid_blob_ptr;
 
 	seq_printf(m, "\tDPCD rev: %x\n", intel_dp->dpcd[DP_DPCD_REV]);
 	seq_printf(m, "\taudio support: %s\n", yesno(intel_dp->has_audio));
@@ -633,7 +634,7 @@ static void intel_dp_info(struct seq_file *m,
 		intel_panel_info(m, &intel_connector->panel);
 
 	drm_dp_downstream_debug(m, intel_dp->dpcd, intel_dp->downstream_ports,
-				&intel_dp->aux);
+				edid ? edid->data : NULL, &intel_dp->aux);
 }
 
 static void intel_dp_mst_info(struct seq_file *m,
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 2c8e82d97a34..c73b3efd84e0 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -6071,7 +6071,7 @@ intel_dp_set_edid(struct intel_dp *intel_dp)
 
 	intel_dp->dfp.max_bpc =
 		drm_dp_downstream_max_bpc(intel_dp->dpcd,
-					  intel_dp->downstream_ports);
+					  intel_dp->downstream_ports, edid);
 
 	drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] DFP max bpc %d\n",
 		    connector->base.base.id, connector->base.name,
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index 4f946826dfce..6218de1294c1 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -1646,10 +1646,14 @@ bool drm_dp_downstream_is_tmds(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 				const u8 port_cap[4]);
 int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
-			      const u8 port_cap[4]);
+			      const u8 port_cap[4],
+			      const struct edid *edid);
 int drm_dp_downstream_id(struct drm_dp_aux *aux, char id[6]);
-void drm_dp_downstream_debug(struct seq_file *m, const u8 dpcd[DP_RECEIVER_CAP_SIZE],
-			     const u8 port_cap[4], struct drm_dp_aux *aux);
+void drm_dp_downstream_debug(struct seq_file *m,
+			     const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+			     const u8 port_cap[4],
+			     const struct edid *edid,
+			     struct drm_dp_aux *aux);
 enum drm_mode_subconnector
 drm_dp_subconnector_type(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 			 const u8 port_cap[4]);
-- 
2.26.2

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [Intel-gfx] [PATCH v2 07/18] drm/dp: Pimp drm_dp_downstream_max_bpc()
@ 2020-09-04 11:53   ` Ville Syrjala
  0 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjala @ 2020-09-04 11:53 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Deal with more cases in drm_dp_downstream_max_bpc():
- DPCD 1.0 -> assume 8bpc for non-DP
- DPCD 1.1+ DP (or DP++ with DP sink) -> allow anything
- DPCD 1.1+ TMDS -> check the caps, assume 8bpc if the value is crap
- anything else -> assume 8bpc

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/drm_dp_helper.c               | 69 +++++++++++--------
 .../drm/i915/display/intel_display_debugfs.c  |  3 +-
 drivers/gpu/drm/i915/display/intel_dp.c       |  2 +-
 include/drm/drm_dp_helper.h                   | 10 ++-
 4 files changed, 51 insertions(+), 33 deletions(-)

diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index 0fcb94f7dbe5..ab87209c25d8 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -653,36 +653,44 @@ int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 EXPORT_SYMBOL(drm_dp_downstream_max_clock);
 
 /**
- * drm_dp_downstream_max_bpc() - extract branch device max
- *                               bits per component
- * @dpcd: DisplayPort configuration data
- * @port_cap: port capabilities
- *
- * See also:
- * drm_dp_read_downstream_info()
- * drm_dp_downstream_max_clock()
- *
- * Returns: Max bpc on success or 0 if max bpc not defined
- */
+  * drm_dp_downstream_max_bpc() - extract downstream facing port max
+  *                               bits per component
+  * @dpcd: DisplayPort configuration data
+  * @port_cap: downstream facing port capabilities
+  * @edid: EDID
+  *
+  * Returns max bpc on success or 0 if max bpc not defined
+  */
 int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
-			      const u8 port_cap[4])
+			      const u8 port_cap[4],
+			      const struct edid *edid)
 {
-	int type = port_cap[0] & DP_DS_PORT_TYPE_MASK;
-	bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] &
-		DP_DETAILED_CAP_INFO_AVAILABLE;
-	int bpc;
-
-	if (!detailed_cap_info)
+	if (!drm_dp_is_branch(dpcd))
 		return 0;
 
-	switch (type) {
-	case DP_DS_PORT_TYPE_VGA:
-	case DP_DS_PORT_TYPE_DVI:
-	case DP_DS_PORT_TYPE_HDMI:
+	if (dpcd[DP_DPCD_REV] < 0x11) {
+		switch (dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_TYPE_MASK) {
+		case DP_DWN_STRM_PORT_TYPE_DP:
+			return 0;
+		default:
+			return 8;
+		}
+	}
+
+	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
+	case DP_DS_PORT_TYPE_DP:
+		return 0;
 	case DP_DS_PORT_TYPE_DP_DUALMODE:
-		bpc = port_cap[2] & DP_DS_MAX_BPC_MASK;
+		if (is_edid_digital_input_dp(edid))
+			return 0;
+		fallthrough;
+	case DP_DS_PORT_TYPE_HDMI:
+	case DP_DS_PORT_TYPE_DVI:
+	case DP_DS_PORT_TYPE_VGA:
+		if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
+			return 8;
 
-		switch (bpc) {
+		switch (port_cap[2] & DP_DS_MAX_BPC_MASK) {
 		case DP_DS_8BPC:
 			return 8;
 		case DP_DS_10BPC:
@@ -691,10 +699,12 @@ int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 			return 12;
 		case DP_DS_16BPC:
 			return 16;
+		default:
+			return 8;
 		}
-		fallthrough;
+		break;
 	default:
-		return 0;
+		return 8;
 	}
 }
 EXPORT_SYMBOL(drm_dp_downstream_max_bpc);
@@ -717,12 +727,15 @@ EXPORT_SYMBOL(drm_dp_downstream_id);
  * @m: pointer for debugfs file
  * @dpcd: DisplayPort configuration data
  * @port_cap: port capabilities
+ * @edid: EDID
  * @aux: DisplayPort AUX channel
  *
  */
 void drm_dp_downstream_debug(struct seq_file *m,
 			     const u8 dpcd[DP_RECEIVER_CAP_SIZE],
-			     const u8 port_cap[4], struct drm_dp_aux *aux)
+			     const u8 port_cap[4],
+			     const struct edid *edid,
+			     struct drm_dp_aux *aux)
 {
 	bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] &
 				 DP_DETAILED_CAP_INFO_AVAILABLE;
@@ -789,7 +802,7 @@ void drm_dp_downstream_debug(struct seq_file *m,
 				seq_printf(m, "\t\tMax TMDS clock: %d kHz\n", clk);
 		}
 
-		bpc = drm_dp_downstream_max_bpc(dpcd, port_cap);
+		bpc = drm_dp_downstream_max_bpc(dpcd, port_cap, edid);
 
 		if (bpc > 0)
 			seq_printf(m, "\t\tMax bpc: %d\n", bpc);
diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
index 53a0a3d9a22d..0bf31f9a8af5 100644
--- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
+++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
@@ -626,6 +626,7 @@ static void intel_dp_info(struct seq_file *m,
 {
 	struct intel_encoder *intel_encoder = intel_attached_encoder(intel_connector);
 	struct intel_dp *intel_dp = enc_to_intel_dp(intel_encoder);
+	const struct drm_property_blob *edid = intel_connector->base.edid_blob_ptr;
 
 	seq_printf(m, "\tDPCD rev: %x\n", intel_dp->dpcd[DP_DPCD_REV]);
 	seq_printf(m, "\taudio support: %s\n", yesno(intel_dp->has_audio));
@@ -633,7 +634,7 @@ static void intel_dp_info(struct seq_file *m,
 		intel_panel_info(m, &intel_connector->panel);
 
 	drm_dp_downstream_debug(m, intel_dp->dpcd, intel_dp->downstream_ports,
-				&intel_dp->aux);
+				edid ? edid->data : NULL, &intel_dp->aux);
 }
 
 static void intel_dp_mst_info(struct seq_file *m,
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 2c8e82d97a34..c73b3efd84e0 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -6071,7 +6071,7 @@ intel_dp_set_edid(struct intel_dp *intel_dp)
 
 	intel_dp->dfp.max_bpc =
 		drm_dp_downstream_max_bpc(intel_dp->dpcd,
-					  intel_dp->downstream_ports);
+					  intel_dp->downstream_ports, edid);
 
 	drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] DFP max bpc %d\n",
 		    connector->base.base.id, connector->base.name,
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index 4f946826dfce..6218de1294c1 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -1646,10 +1646,14 @@ bool drm_dp_downstream_is_tmds(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 				const u8 port_cap[4]);
 int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
-			      const u8 port_cap[4]);
+			      const u8 port_cap[4],
+			      const struct edid *edid);
 int drm_dp_downstream_id(struct drm_dp_aux *aux, char id[6]);
-void drm_dp_downstream_debug(struct seq_file *m, const u8 dpcd[DP_RECEIVER_CAP_SIZE],
-			     const u8 port_cap[4], struct drm_dp_aux *aux);
+void drm_dp_downstream_debug(struct seq_file *m,
+			     const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+			     const u8 port_cap[4],
+			     const struct edid *edid,
+			     struct drm_dp_aux *aux);
 enum drm_mode_subconnector
 drm_dp_subconnector_type(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 			 const u8 port_cap[4]);
-- 
2.26.2

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v2 08/18] drm/dp: Redo drm_dp_downstream_max_clock() as drm_dp_downstream_max_dotclock()
  2020-09-04 11:53 ` [Intel-gfx] " Ville Syrjala
@ 2020-09-04 11:53   ` Ville Syrjala
  -1 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjala @ 2020-09-04 11:53 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

We want to differentiate between the DFP dotclock and TMDS clock
limits. Let's convert the current thing to just give us the
dotclock limit.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/drm_dp_helper.c         | 46 +++++++++----------------
 drivers/gpu/drm/i915/display/intel_dp.c |  4 +--
 include/drm/drm_dp_helper.h             |  4 +--
 3 files changed, 20 insertions(+), 34 deletions(-)

diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index ab87209c25d8..822a30e609ef 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -616,41 +616,32 @@ int drm_dp_read_downstream_info(struct drm_dp_aux *aux,
 EXPORT_SYMBOL(drm_dp_read_downstream_info);
 
 /**
- * drm_dp_downstream_max_clock() - extract branch device max
- *                                 pixel rate for legacy VGA
- *                                 converter or max TMDS clock
- *                                 rate for others
+ * drm_dp_downstream_max_dotclock() - extract downstream facing port max dot clock
  * @dpcd: DisplayPort configuration data
  * @port_cap: port capabilities
  *
- * See also:
- * drm_dp_read_downstream_info()
- * drm_dp_downstream_max_bpc()
- *
- * Returns: Max clock in kHz on success or 0 if max clock not defined
+ * Returns downstream facing port max dot clock in kHz on success,
+ * or 0 if max clock not defined
  */
-int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
-				const u8 port_cap[4])
+int drm_dp_downstream_max_dotclock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+				   const u8 port_cap[4])
 {
-	int type = port_cap[0] & DP_DS_PORT_TYPE_MASK;
-	bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] &
-		DP_DETAILED_CAP_INFO_AVAILABLE;
+	if (!drm_dp_is_branch(dpcd))
+		return 0;
 
-	if (!detailed_cap_info)
+	if (dpcd[DP_DPCD_REV] < 0x11)
 		return 0;
 
-	switch (type) {
+	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
 	case DP_DS_PORT_TYPE_VGA:
-		return port_cap[1] * 8 * 1000;
-	case DP_DS_PORT_TYPE_DVI:
-	case DP_DS_PORT_TYPE_HDMI:
-	case DP_DS_PORT_TYPE_DP_DUALMODE:
-		return port_cap[1] * 2500;
+		if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
+			return 0;
+		return port_cap[1] * 8000;
 	default:
 		return 0;
 	}
 }
-EXPORT_SYMBOL(drm_dp_downstream_max_clock);
+EXPORT_SYMBOL(drm_dp_downstream_max_dotclock);
 
 /**
   * drm_dp_downstream_max_bpc() - extract downstream facing port max
@@ -793,14 +784,9 @@ void drm_dp_downstream_debug(struct seq_file *m,
 		seq_printf(m, "\t\tSW: %d.%d\n", rev[0], rev[1]);
 
 	if (detailed_cap_info) {
-		clk = drm_dp_downstream_max_clock(dpcd, port_cap);
-
-		if (clk > 0) {
-			if (type == DP_DS_PORT_TYPE_VGA)
-				seq_printf(m, "\t\tMax dot clock: %d kHz\n", clk);
-			else
-				seq_printf(m, "\t\tMax TMDS clock: %d kHz\n", clk);
-		}
+		clk = drm_dp_downstream_max_dotclock(dpcd, port_cap);
+		if (clk > 0)
+			seq_printf(m, "\t\tMax dot clock: %d kHz\n", clk);
 
 		bpc = drm_dp_downstream_max_bpc(dpcd, port_cap, edid);
 
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index c73b3efd84e0..8f4aee35c203 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -261,8 +261,8 @@ intel_dp_downstream_max_dotclock(struct intel_dp *intel_dp)
 	if (type != DP_DS_PORT_TYPE_VGA)
 		return max_dotclk;
 
-	ds_max_dotclk = drm_dp_downstream_max_clock(intel_dp->dpcd,
-						    intel_dp->downstream_ports);
+	ds_max_dotclk = drm_dp_downstream_max_dotclock(intel_dp->dpcd,
+						       intel_dp->downstream_ports);
 
 	if (ds_max_dotclk != 0)
 		max_dotclk = min(max_dotclk, ds_max_dotclk);
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index 6218de1294c1..19bc04207788 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -1643,8 +1643,8 @@ bool drm_dp_downstream_is_type(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 bool drm_dp_downstream_is_tmds(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 			       const u8 port_cap[4],
 			       const struct edid *edid);
-int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
-				const u8 port_cap[4]);
+int drm_dp_downstream_max_dotclock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+				   const u8 port_cap[4]);
 int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 			      const u8 port_cap[4],
 			      const struct edid *edid);
-- 
2.26.2

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [Intel-gfx] [PATCH v2 08/18] drm/dp: Redo drm_dp_downstream_max_clock() as drm_dp_downstream_max_dotclock()
@ 2020-09-04 11:53   ` Ville Syrjala
  0 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjala @ 2020-09-04 11:53 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

We want to differentiate between the DFP dotclock and TMDS clock
limits. Let's convert the current thing to just give us the
dotclock limit.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/drm_dp_helper.c         | 46 +++++++++----------------
 drivers/gpu/drm/i915/display/intel_dp.c |  4 +--
 include/drm/drm_dp_helper.h             |  4 +--
 3 files changed, 20 insertions(+), 34 deletions(-)

diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index ab87209c25d8..822a30e609ef 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -616,41 +616,32 @@ int drm_dp_read_downstream_info(struct drm_dp_aux *aux,
 EXPORT_SYMBOL(drm_dp_read_downstream_info);
 
 /**
- * drm_dp_downstream_max_clock() - extract branch device max
- *                                 pixel rate for legacy VGA
- *                                 converter or max TMDS clock
- *                                 rate for others
+ * drm_dp_downstream_max_dotclock() - extract downstream facing port max dot clock
  * @dpcd: DisplayPort configuration data
  * @port_cap: port capabilities
  *
- * See also:
- * drm_dp_read_downstream_info()
- * drm_dp_downstream_max_bpc()
- *
- * Returns: Max clock in kHz on success or 0 if max clock not defined
+ * Returns downstream facing port max dot clock in kHz on success,
+ * or 0 if max clock not defined
  */
-int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
-				const u8 port_cap[4])
+int drm_dp_downstream_max_dotclock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+				   const u8 port_cap[4])
 {
-	int type = port_cap[0] & DP_DS_PORT_TYPE_MASK;
-	bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] &
-		DP_DETAILED_CAP_INFO_AVAILABLE;
+	if (!drm_dp_is_branch(dpcd))
+		return 0;
 
-	if (!detailed_cap_info)
+	if (dpcd[DP_DPCD_REV] < 0x11)
 		return 0;
 
-	switch (type) {
+	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
 	case DP_DS_PORT_TYPE_VGA:
-		return port_cap[1] * 8 * 1000;
-	case DP_DS_PORT_TYPE_DVI:
-	case DP_DS_PORT_TYPE_HDMI:
-	case DP_DS_PORT_TYPE_DP_DUALMODE:
-		return port_cap[1] * 2500;
+		if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
+			return 0;
+		return port_cap[1] * 8000;
 	default:
 		return 0;
 	}
 }
-EXPORT_SYMBOL(drm_dp_downstream_max_clock);
+EXPORT_SYMBOL(drm_dp_downstream_max_dotclock);
 
 /**
   * drm_dp_downstream_max_bpc() - extract downstream facing port max
@@ -793,14 +784,9 @@ void drm_dp_downstream_debug(struct seq_file *m,
 		seq_printf(m, "\t\tSW: %d.%d\n", rev[0], rev[1]);
 
 	if (detailed_cap_info) {
-		clk = drm_dp_downstream_max_clock(dpcd, port_cap);
-
-		if (clk > 0) {
-			if (type == DP_DS_PORT_TYPE_VGA)
-				seq_printf(m, "\t\tMax dot clock: %d kHz\n", clk);
-			else
-				seq_printf(m, "\t\tMax TMDS clock: %d kHz\n", clk);
-		}
+		clk = drm_dp_downstream_max_dotclock(dpcd, port_cap);
+		if (clk > 0)
+			seq_printf(m, "\t\tMax dot clock: %d kHz\n", clk);
 
 		bpc = drm_dp_downstream_max_bpc(dpcd, port_cap, edid);
 
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index c73b3efd84e0..8f4aee35c203 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -261,8 +261,8 @@ intel_dp_downstream_max_dotclock(struct intel_dp *intel_dp)
 	if (type != DP_DS_PORT_TYPE_VGA)
 		return max_dotclk;
 
-	ds_max_dotclk = drm_dp_downstream_max_clock(intel_dp->dpcd,
-						    intel_dp->downstream_ports);
+	ds_max_dotclk = drm_dp_downstream_max_dotclock(intel_dp->dpcd,
+						       intel_dp->downstream_ports);
 
 	if (ds_max_dotclk != 0)
 		max_dotclk = min(max_dotclk, ds_max_dotclk);
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index 6218de1294c1..19bc04207788 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -1643,8 +1643,8 @@ bool drm_dp_downstream_is_type(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 bool drm_dp_downstream_is_tmds(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 			       const u8 port_cap[4],
 			       const struct edid *edid);
-int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
-				const u8 port_cap[4]);
+int drm_dp_downstream_max_dotclock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+				   const u8 port_cap[4]);
 int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 			      const u8 port_cap[4],
 			      const struct edid *edid);
-- 
2.26.2

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v2 09/18] drm/i915: Reworkd DP DFP clock handling
  2020-09-04 11:53 ` [Intel-gfx] " Ville Syrjala
@ 2020-09-04 11:53   ` Ville Syrjala
  -1 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjala @ 2020-09-04 11:53 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Move the downstream facing port dotclock check into a new function
(intel_dp_mode_valid_downstream()) so that we have a nice future
place where we can collect other related checks.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 .../drm/i915/display/intel_display_types.h    |  1 +
 drivers/gpu/drm/i915/display/intel_dp.c       | 55 +++++++++----------
 2 files changed, 28 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 8699c001969d..1dea017dc505 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1381,6 +1381,7 @@ struct intel_dp {
 
 	/* Downstream facing port caps */
 	struct {
+		int max_dotclock;
 		u8 max_bpc;
 	} dfp;
 
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 8f4aee35c203..6f55e15136b0 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -247,29 +247,6 @@ intel_dp_max_data_rate(int max_link_clock, int max_lanes)
 	return max_link_clock * max_lanes;
 }
 
-static int
-intel_dp_downstream_max_dotclock(struct intel_dp *intel_dp)
-{
-	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
-	struct intel_encoder *encoder = &dig_port->base;
-	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
-	int max_dotclk = dev_priv->max_dotclk_freq;
-	int ds_max_dotclk;
-
-	int type = intel_dp->downstream_ports[0] & DP_DS_PORT_TYPE_MASK;
-
-	if (type != DP_DS_PORT_TYPE_VGA)
-		return max_dotclk;
-
-	ds_max_dotclk = drm_dp_downstream_max_dotclock(intel_dp->dpcd,
-						       intel_dp->downstream_ports);
-
-	if (ds_max_dotclk != 0)
-		max_dotclk = min(max_dotclk, ds_max_dotclk);
-
-	return max_dotclk;
-}
-
 static int cnl_max_source_rate(struct intel_dp *intel_dp)
 {
 	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
@@ -634,6 +611,19 @@ static bool intel_dp_hdisplay_bad(struct drm_i915_private *dev_priv,
 	return hdisplay == 4096 && !HAS_DDI(dev_priv);
 }
 
+static enum drm_mode_status
+intel_dp_mode_valid_downstream(struct intel_connector *connector,
+			       int target_clock)
+{
+	struct intel_dp *intel_dp = intel_attached_dp(connector);
+
+	if (intel_dp->dfp.max_dotclock &&
+	    target_clock > intel_dp->dfp.max_dotclock)
+		return MODE_CLOCK_HIGH;
+
+	return MODE_OK;
+}
+
 static enum drm_mode_status
 intel_dp_mode_valid(struct drm_connector *connector,
 		    struct drm_display_mode *mode)
@@ -644,15 +634,14 @@ intel_dp_mode_valid(struct drm_connector *connector,
 	struct drm_i915_private *dev_priv = to_i915(connector->dev);
 	int target_clock = mode->clock;
 	int max_rate, mode_rate, max_lanes, max_link_clock;
-	int max_dotclk;
+	int max_dotclk = dev_priv->max_dotclk_freq;
 	u16 dsc_max_output_bpp = 0;
 	u8 dsc_slice_count = 0;
+	enum drm_mode_status status;
 
 	if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
 		return MODE_NO_DBLESCAN;
 
-	max_dotclk = intel_dp_downstream_max_dotclock(intel_dp);
-
 	if (intel_dp_is_edp(intel_dp) && fixed_mode) {
 		if (mode->hdisplay > fixed_mode->hdisplay)
 			return MODE_PANEL;
@@ -708,6 +697,10 @@ intel_dp_mode_valid(struct drm_connector *connector,
 	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
 		return MODE_H_ILLEGAL;
 
+	status = intel_dp_mode_valid_downstream(intel_connector, target_clock);
+	if (status != MODE_OK)
+		return status;
+
 	return intel_mode_valid_max_plane_size(dev_priv, mode);
 }
 
@@ -6073,9 +6066,14 @@ intel_dp_set_edid(struct intel_dp *intel_dp)
 		drm_dp_downstream_max_bpc(intel_dp->dpcd,
 					  intel_dp->downstream_ports, edid);
 
-	drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] DFP max bpc %d\n",
+	intel_dp->dfp.max_dotclock =
+		drm_dp_downstream_max_dotclock(intel_dp->dpcd,
+					       intel_dp->downstream_ports);
+
+	drm_dbg_kms(&i915->drm,
+		    "[CONNECTOR:%d:%s] DFP max bpc %d, max dotclock %d\n",
 		    connector->base.base.id, connector->base.name,
-		    intel_dp->dfp.max_bpc);
+		    intel_dp->dfp.max_bpc, intel_dp->dfp.max_dotclock);
 
 	if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
 		intel_dp->has_hdmi_sink = drm_detect_hdmi_monitor(edid);
@@ -6100,6 +6098,7 @@ intel_dp_unset_edid(struct intel_dp *intel_dp)
 	intel_dp->edid_quirks = 0;
 
 	intel_dp->dfp.max_bpc = 0;
+	intel_dp->dfp.max_dotclock = 0;
 }
 
 static int
-- 
2.26.2

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [Intel-gfx] [PATCH v2 09/18] drm/i915: Reworkd DP DFP clock handling
@ 2020-09-04 11:53   ` Ville Syrjala
  0 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjala @ 2020-09-04 11:53 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Move the downstream facing port dotclock check into a new function
(intel_dp_mode_valid_downstream()) so that we have a nice future
place where we can collect other related checks.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 .../drm/i915/display/intel_display_types.h    |  1 +
 drivers/gpu/drm/i915/display/intel_dp.c       | 55 +++++++++----------
 2 files changed, 28 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 8699c001969d..1dea017dc505 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1381,6 +1381,7 @@ struct intel_dp {
 
 	/* Downstream facing port caps */
 	struct {
+		int max_dotclock;
 		u8 max_bpc;
 	} dfp;
 
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 8f4aee35c203..6f55e15136b0 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -247,29 +247,6 @@ intel_dp_max_data_rate(int max_link_clock, int max_lanes)
 	return max_link_clock * max_lanes;
 }
 
-static int
-intel_dp_downstream_max_dotclock(struct intel_dp *intel_dp)
-{
-	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
-	struct intel_encoder *encoder = &dig_port->base;
-	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
-	int max_dotclk = dev_priv->max_dotclk_freq;
-	int ds_max_dotclk;
-
-	int type = intel_dp->downstream_ports[0] & DP_DS_PORT_TYPE_MASK;
-
-	if (type != DP_DS_PORT_TYPE_VGA)
-		return max_dotclk;
-
-	ds_max_dotclk = drm_dp_downstream_max_dotclock(intel_dp->dpcd,
-						       intel_dp->downstream_ports);
-
-	if (ds_max_dotclk != 0)
-		max_dotclk = min(max_dotclk, ds_max_dotclk);
-
-	return max_dotclk;
-}
-
 static int cnl_max_source_rate(struct intel_dp *intel_dp)
 {
 	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
@@ -634,6 +611,19 @@ static bool intel_dp_hdisplay_bad(struct drm_i915_private *dev_priv,
 	return hdisplay == 4096 && !HAS_DDI(dev_priv);
 }
 
+static enum drm_mode_status
+intel_dp_mode_valid_downstream(struct intel_connector *connector,
+			       int target_clock)
+{
+	struct intel_dp *intel_dp = intel_attached_dp(connector);
+
+	if (intel_dp->dfp.max_dotclock &&
+	    target_clock > intel_dp->dfp.max_dotclock)
+		return MODE_CLOCK_HIGH;
+
+	return MODE_OK;
+}
+
 static enum drm_mode_status
 intel_dp_mode_valid(struct drm_connector *connector,
 		    struct drm_display_mode *mode)
@@ -644,15 +634,14 @@ intel_dp_mode_valid(struct drm_connector *connector,
 	struct drm_i915_private *dev_priv = to_i915(connector->dev);
 	int target_clock = mode->clock;
 	int max_rate, mode_rate, max_lanes, max_link_clock;
-	int max_dotclk;
+	int max_dotclk = dev_priv->max_dotclk_freq;
 	u16 dsc_max_output_bpp = 0;
 	u8 dsc_slice_count = 0;
+	enum drm_mode_status status;
 
 	if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
 		return MODE_NO_DBLESCAN;
 
-	max_dotclk = intel_dp_downstream_max_dotclock(intel_dp);
-
 	if (intel_dp_is_edp(intel_dp) && fixed_mode) {
 		if (mode->hdisplay > fixed_mode->hdisplay)
 			return MODE_PANEL;
@@ -708,6 +697,10 @@ intel_dp_mode_valid(struct drm_connector *connector,
 	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
 		return MODE_H_ILLEGAL;
 
+	status = intel_dp_mode_valid_downstream(intel_connector, target_clock);
+	if (status != MODE_OK)
+		return status;
+
 	return intel_mode_valid_max_plane_size(dev_priv, mode);
 }
 
@@ -6073,9 +6066,14 @@ intel_dp_set_edid(struct intel_dp *intel_dp)
 		drm_dp_downstream_max_bpc(intel_dp->dpcd,
 					  intel_dp->downstream_ports, edid);
 
-	drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] DFP max bpc %d\n",
+	intel_dp->dfp.max_dotclock =
+		drm_dp_downstream_max_dotclock(intel_dp->dpcd,
+					       intel_dp->downstream_ports);
+
+	drm_dbg_kms(&i915->drm,
+		    "[CONNECTOR:%d:%s] DFP max bpc %d, max dotclock %d\n",
 		    connector->base.base.id, connector->base.name,
-		    intel_dp->dfp.max_bpc);
+		    intel_dp->dfp.max_bpc, intel_dp->dfp.max_dotclock);
 
 	if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
 		intel_dp->has_hdmi_sink = drm_detect_hdmi_monitor(edid);
@@ -6100,6 +6098,7 @@ intel_dp_unset_edid(struct intel_dp *intel_dp)
 	intel_dp->edid_quirks = 0;
 
 	intel_dp->dfp.max_bpc = 0;
+	intel_dp->dfp.max_dotclock = 0;
 }
 
 static int
-- 
2.26.2

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v2 10/18] drm/dp: Add drm_dp_downstream_{min, max}_tmds_clock()
  2020-09-04 11:53 ` [Intel-gfx] " Ville Syrjala
@ 2020-09-04 11:53   ` Ville Syrjala
  -1 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjala @ 2020-09-04 11:53 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Add helpers to get the TMDS clock limits for HDMI/DVI downstream
facing ports.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/drm_dp_helper.c | 116 ++++++++++++++++++++++++++++++++
 include/drm/drm_dp_helper.h     |   6 ++
 2 files changed, 122 insertions(+)

diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index 822a30e609ef..f567428f2aef 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -643,6 +643,114 @@ int drm_dp_downstream_max_dotclock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 }
 EXPORT_SYMBOL(drm_dp_downstream_max_dotclock);
 
+/**
+ * drm_dp_downstream_max_tmds_clock() - extract downstream facing port max TMDS clock
+ * @dpcd: DisplayPort configuration data
+ * @port_cap: port capabilities
+ * @edid: EDID
+ *
+ * Returns HDMI/DVI downstream facing port max TMDS clock in kHz on success,
+ * or 0 if max TMDS clock not defined
+ */
+int drm_dp_downstream_max_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+				     const u8 port_cap[4],
+				     const struct edid *edid)
+{
+	if (!drm_dp_is_branch(dpcd))
+		return 0;
+
+	if (dpcd[DP_DPCD_REV] < 0x11) {
+		switch (dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_TYPE_MASK) {
+		case DP_DWN_STRM_PORT_TYPE_TMDS:
+			return 165000;
+		default:
+			return 0;
+		}
+	}
+
+	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
+	case DP_DS_PORT_TYPE_DP_DUALMODE:
+		if (is_edid_digital_input_dp(edid))
+			return 0;
+		/*
+		 * It's left up to the driver to check the
+		 * DP dual mode adapter's max TMDS clock.
+		 *
+		 * Unfortunatley it looks like branch devices
+		 * may not fordward that the DP dual mode i2c
+		 * access so we just usually get i2c nak :(
+		 */
+		fallthrough;
+	case DP_DS_PORT_TYPE_HDMI:
+		 /*
+		  * We should perhaps assume 165 MHz when detailed cap
+		  * info is not available. But looks like many typical
+		  * branch devices fall into that category and so we'd
+		  * probably end up with users complaining that they can't
+		  * get high resolution modes with their favorite dongle.
+		  *
+		  * So let's limit to 300 MHz instead since DPCD 1.4
+		  * HDMI 2.0 DFPs are required to have the detailed cap
+		  * info. So it's more likely we're dealing with a HDMI 1.4
+		  * compatible* device here.
+		  */
+		if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
+			return 300000;
+		return port_cap[1] * 2500;
+	case DP_DS_PORT_TYPE_DVI:
+		if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
+			return 165000;
+		/* FIXME what to do about DVI dual link? */
+		return port_cap[1] * 2500;
+	default:
+		return 0;
+	}
+}
+EXPORT_SYMBOL(drm_dp_downstream_max_tmds_clock);
+
+/**
+ * drm_dp_downstream_min_tmds_clock() - extract downstream facing port min TMDS clock
+ * @dpcd: DisplayPort configuration data
+ * @port_cap: port capabilities
+ * @edid: EDID
+ *
+ * Returns HDMI/DVI downstream facing port min TMDS clock in kHz on success,
+ * or 0 if max TMDS clock not defined
+ */
+int drm_dp_downstream_min_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+				     const u8 port_cap[4],
+				     const struct edid *edid)
+{
+	if (!drm_dp_is_branch(dpcd))
+		return 0;
+
+	if (dpcd[DP_DPCD_REV] < 0x11) {
+		switch (dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_TYPE_MASK) {
+		case DP_DWN_STRM_PORT_TYPE_TMDS:
+			return 25000;
+		default:
+			return 0;
+		}
+	}
+
+	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
+	case DP_DS_PORT_TYPE_DP_DUALMODE:
+		if (is_edid_digital_input_dp(edid))
+			return 0;
+		fallthrough;
+	case DP_DS_PORT_TYPE_DVI:
+	case DP_DS_PORT_TYPE_HDMI:
+		/*
+		 * Unclear whether the protocol converter could
+		 * utilize pixel replication. Assume it won't.
+		 */
+		return 25000;
+	default:
+		return 0;
+	}
+}
+EXPORT_SYMBOL(drm_dp_downstream_min_tmds_clock);
+
 /**
   * drm_dp_downstream_max_bpc() - extract downstream facing port max
   *                               bits per component
@@ -788,6 +896,14 @@ void drm_dp_downstream_debug(struct seq_file *m,
 		if (clk > 0)
 			seq_printf(m, "\t\tMax dot clock: %d kHz\n", clk);
 
+		clk = drm_dp_downstream_max_tmds_clock(dpcd, port_cap, edid);
+		if (clk > 0)
+			seq_printf(m, "\t\tMax TMDS clock: %d kHz\n", clk);
+
+		clk = drm_dp_downstream_min_tmds_clock(dpcd, port_cap, edid);
+		if (clk > 0)
+			seq_printf(m, "\t\tMin TMDS clock: %d kHz\n", clk);
+
 		bpc = drm_dp_downstream_max_bpc(dpcd, port_cap, edid);
 
 		if (bpc > 0)
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index 19bc04207788..6812a3e0de8d 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -1645,6 +1645,12 @@ bool drm_dp_downstream_is_tmds(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 			       const struct edid *edid);
 int drm_dp_downstream_max_dotclock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 				   const u8 port_cap[4]);
+int drm_dp_downstream_max_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+				     const u8 port_cap[4],
+				     const struct edid *edid);
+int drm_dp_downstream_min_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+				     const u8 port_cap[4],
+				     const struct edid *edid);
 int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 			      const u8 port_cap[4],
 			      const struct edid *edid);
-- 
2.26.2

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [Intel-gfx] [PATCH v2 10/18] drm/dp: Add drm_dp_downstream_{min, max}_tmds_clock()
@ 2020-09-04 11:53   ` Ville Syrjala
  0 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjala @ 2020-09-04 11:53 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Add helpers to get the TMDS clock limits for HDMI/DVI downstream
facing ports.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/drm_dp_helper.c | 116 ++++++++++++++++++++++++++++++++
 include/drm/drm_dp_helper.h     |   6 ++
 2 files changed, 122 insertions(+)

diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index 822a30e609ef..f567428f2aef 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -643,6 +643,114 @@ int drm_dp_downstream_max_dotclock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 }
 EXPORT_SYMBOL(drm_dp_downstream_max_dotclock);
 
+/**
+ * drm_dp_downstream_max_tmds_clock() - extract downstream facing port max TMDS clock
+ * @dpcd: DisplayPort configuration data
+ * @port_cap: port capabilities
+ * @edid: EDID
+ *
+ * Returns HDMI/DVI downstream facing port max TMDS clock in kHz on success,
+ * or 0 if max TMDS clock not defined
+ */
+int drm_dp_downstream_max_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+				     const u8 port_cap[4],
+				     const struct edid *edid)
+{
+	if (!drm_dp_is_branch(dpcd))
+		return 0;
+
+	if (dpcd[DP_DPCD_REV] < 0x11) {
+		switch (dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_TYPE_MASK) {
+		case DP_DWN_STRM_PORT_TYPE_TMDS:
+			return 165000;
+		default:
+			return 0;
+		}
+	}
+
+	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
+	case DP_DS_PORT_TYPE_DP_DUALMODE:
+		if (is_edid_digital_input_dp(edid))
+			return 0;
+		/*
+		 * It's left up to the driver to check the
+		 * DP dual mode adapter's max TMDS clock.
+		 *
+		 * Unfortunatley it looks like branch devices
+		 * may not fordward that the DP dual mode i2c
+		 * access so we just usually get i2c nak :(
+		 */
+		fallthrough;
+	case DP_DS_PORT_TYPE_HDMI:
+		 /*
+		  * We should perhaps assume 165 MHz when detailed cap
+		  * info is not available. But looks like many typical
+		  * branch devices fall into that category and so we'd
+		  * probably end up with users complaining that they can't
+		  * get high resolution modes with their favorite dongle.
+		  *
+		  * So let's limit to 300 MHz instead since DPCD 1.4
+		  * HDMI 2.0 DFPs are required to have the detailed cap
+		  * info. So it's more likely we're dealing with a HDMI 1.4
+		  * compatible* device here.
+		  */
+		if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
+			return 300000;
+		return port_cap[1] * 2500;
+	case DP_DS_PORT_TYPE_DVI:
+		if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
+			return 165000;
+		/* FIXME what to do about DVI dual link? */
+		return port_cap[1] * 2500;
+	default:
+		return 0;
+	}
+}
+EXPORT_SYMBOL(drm_dp_downstream_max_tmds_clock);
+
+/**
+ * drm_dp_downstream_min_tmds_clock() - extract downstream facing port min TMDS clock
+ * @dpcd: DisplayPort configuration data
+ * @port_cap: port capabilities
+ * @edid: EDID
+ *
+ * Returns HDMI/DVI downstream facing port min TMDS clock in kHz on success,
+ * or 0 if max TMDS clock not defined
+ */
+int drm_dp_downstream_min_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+				     const u8 port_cap[4],
+				     const struct edid *edid)
+{
+	if (!drm_dp_is_branch(dpcd))
+		return 0;
+
+	if (dpcd[DP_DPCD_REV] < 0x11) {
+		switch (dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_TYPE_MASK) {
+		case DP_DWN_STRM_PORT_TYPE_TMDS:
+			return 25000;
+		default:
+			return 0;
+		}
+	}
+
+	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
+	case DP_DS_PORT_TYPE_DP_DUALMODE:
+		if (is_edid_digital_input_dp(edid))
+			return 0;
+		fallthrough;
+	case DP_DS_PORT_TYPE_DVI:
+	case DP_DS_PORT_TYPE_HDMI:
+		/*
+		 * Unclear whether the protocol converter could
+		 * utilize pixel replication. Assume it won't.
+		 */
+		return 25000;
+	default:
+		return 0;
+	}
+}
+EXPORT_SYMBOL(drm_dp_downstream_min_tmds_clock);
+
 /**
   * drm_dp_downstream_max_bpc() - extract downstream facing port max
   *                               bits per component
@@ -788,6 +896,14 @@ void drm_dp_downstream_debug(struct seq_file *m,
 		if (clk > 0)
 			seq_printf(m, "\t\tMax dot clock: %d kHz\n", clk);
 
+		clk = drm_dp_downstream_max_tmds_clock(dpcd, port_cap, edid);
+		if (clk > 0)
+			seq_printf(m, "\t\tMax TMDS clock: %d kHz\n", clk);
+
+		clk = drm_dp_downstream_min_tmds_clock(dpcd, port_cap, edid);
+		if (clk > 0)
+			seq_printf(m, "\t\tMin TMDS clock: %d kHz\n", clk);
+
 		bpc = drm_dp_downstream_max_bpc(dpcd, port_cap, edid);
 
 		if (bpc > 0)
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index 19bc04207788..6812a3e0de8d 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -1645,6 +1645,12 @@ bool drm_dp_downstream_is_tmds(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 			       const struct edid *edid);
 int drm_dp_downstream_max_dotclock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 				   const u8 port_cap[4]);
+int drm_dp_downstream_max_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+				     const u8 port_cap[4],
+				     const struct edid *edid);
+int drm_dp_downstream_min_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+				     const u8 port_cap[4],
+				     const struct edid *edid);
 int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 			      const u8 port_cap[4],
 			      const struct edid *edid);
-- 
2.26.2

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v2 11/18] drm/i915: Deal with TMDS DFP clock limits
  2020-09-04 11:53 ` [Intel-gfx] " Ville Syrjala
@ 2020-09-04 11:53   ` Ville Syrjala
  -1 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjala @ 2020-09-04 11:53 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Use the new helpers to extract the TMDS clock limits from
the downstream facing port and check them in .mode_valid().

TODO: we should check these in .compute_config() too to eg.
determine if we can do deep color on the HDMI side or not

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 .../drm/i915/display/intel_display_types.h    |  1 +
 drivers/gpu/drm/i915/display/intel_dp.c       | 36 +++++++++++++++++--
 2 files changed, 34 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 1dea017dc505..7980426e618b 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1381,6 +1381,7 @@ struct intel_dp {
 
 	/* Downstream facing port caps */
 	struct {
+		int min_tmds_clock, max_tmds_clock;
 		int max_dotclock;
 		u8 max_bpc;
 	} dfp;
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 6f55e15136b0..a703e4659e47 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -613,14 +613,29 @@ static bool intel_dp_hdisplay_bad(struct drm_i915_private *dev_priv,
 
 static enum drm_mode_status
 intel_dp_mode_valid_downstream(struct intel_connector *connector,
+			       const struct drm_display_mode *mode,
 			       int target_clock)
 {
 	struct intel_dp *intel_dp = intel_attached_dp(connector);
+	const struct drm_display_info *info = &connector->base.display_info;
+	int tmds_clock;
 
 	if (intel_dp->dfp.max_dotclock &&
 	    target_clock > intel_dp->dfp.max_dotclock)
 		return MODE_CLOCK_HIGH;
 
+	/* Assume 8bpc for the DP++/HDMI/DVI TMDS clock check */
+	tmds_clock = target_clock;
+	if (drm_mode_is_420_only(info, mode))
+		tmds_clock /= 2;
+
+	if (intel_dp->dfp.min_tmds_clock &&
+	    tmds_clock < intel_dp->dfp.min_tmds_clock)
+		return MODE_CLOCK_LOW;
+	if (intel_dp->dfp.max_tmds_clock &&
+	    tmds_clock > intel_dp->dfp.max_tmds_clock)
+		return MODE_CLOCK_HIGH;
+
 	return MODE_OK;
 }
 
@@ -697,7 +712,8 @@ intel_dp_mode_valid(struct drm_connector *connector,
 	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
 		return MODE_H_ILLEGAL;
 
-	status = intel_dp_mode_valid_downstream(intel_connector, target_clock);
+	status = intel_dp_mode_valid_downstream(intel_connector,
+						mode, target_clock);
 	if (status != MODE_OK)
 		return status;
 
@@ -6070,10 +6086,22 @@ intel_dp_set_edid(struct intel_dp *intel_dp)
 		drm_dp_downstream_max_dotclock(intel_dp->dpcd,
 					       intel_dp->downstream_ports);
 
+	intel_dp->dfp.min_tmds_clock =
+		drm_dp_downstream_min_tmds_clock(intel_dp->dpcd,
+						 intel_dp->downstream_ports,
+						 edid);
+	intel_dp->dfp.max_tmds_clock =
+		drm_dp_downstream_max_tmds_clock(intel_dp->dpcd,
+						 intel_dp->downstream_ports,
+						 edid);
+
 	drm_dbg_kms(&i915->drm,
-		    "[CONNECTOR:%d:%s] DFP max bpc %d, max dotclock %d\n",
+		    "[CONNECTOR:%d:%s] DFP max bpc %d, max dotclock %d, TMDS clock %d-%d\n",
 		    connector->base.base.id, connector->base.name,
-		    intel_dp->dfp.max_bpc, intel_dp->dfp.max_dotclock);
+		    intel_dp->dfp.max_bpc,
+		    intel_dp->dfp.max_dotclock,
+		    intel_dp->dfp.min_tmds_clock,
+		    intel_dp->dfp.max_tmds_clock);
 
 	if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
 		intel_dp->has_hdmi_sink = drm_detect_hdmi_monitor(edid);
@@ -6099,6 +6127,8 @@ intel_dp_unset_edid(struct intel_dp *intel_dp)
 
 	intel_dp->dfp.max_bpc = 0;
 	intel_dp->dfp.max_dotclock = 0;
+	intel_dp->dfp.min_tmds_clock = 0;
+	intel_dp->dfp.max_tmds_clock = 0;
 }
 
 static int
-- 
2.26.2

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [Intel-gfx] [PATCH v2 11/18] drm/i915: Deal with TMDS DFP clock limits
@ 2020-09-04 11:53   ` Ville Syrjala
  0 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjala @ 2020-09-04 11:53 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Use the new helpers to extract the TMDS clock limits from
the downstream facing port and check them in .mode_valid().

TODO: we should check these in .compute_config() too to eg.
determine if we can do deep color on the HDMI side or not

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 .../drm/i915/display/intel_display_types.h    |  1 +
 drivers/gpu/drm/i915/display/intel_dp.c       | 36 +++++++++++++++++--
 2 files changed, 34 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 1dea017dc505..7980426e618b 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1381,6 +1381,7 @@ struct intel_dp {
 
 	/* Downstream facing port caps */
 	struct {
+		int min_tmds_clock, max_tmds_clock;
 		int max_dotclock;
 		u8 max_bpc;
 	} dfp;
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 6f55e15136b0..a703e4659e47 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -613,14 +613,29 @@ static bool intel_dp_hdisplay_bad(struct drm_i915_private *dev_priv,
 
 static enum drm_mode_status
 intel_dp_mode_valid_downstream(struct intel_connector *connector,
+			       const struct drm_display_mode *mode,
 			       int target_clock)
 {
 	struct intel_dp *intel_dp = intel_attached_dp(connector);
+	const struct drm_display_info *info = &connector->base.display_info;
+	int tmds_clock;
 
 	if (intel_dp->dfp.max_dotclock &&
 	    target_clock > intel_dp->dfp.max_dotclock)
 		return MODE_CLOCK_HIGH;
 
+	/* Assume 8bpc for the DP++/HDMI/DVI TMDS clock check */
+	tmds_clock = target_clock;
+	if (drm_mode_is_420_only(info, mode))
+		tmds_clock /= 2;
+
+	if (intel_dp->dfp.min_tmds_clock &&
+	    tmds_clock < intel_dp->dfp.min_tmds_clock)
+		return MODE_CLOCK_LOW;
+	if (intel_dp->dfp.max_tmds_clock &&
+	    tmds_clock > intel_dp->dfp.max_tmds_clock)
+		return MODE_CLOCK_HIGH;
+
 	return MODE_OK;
 }
 
@@ -697,7 +712,8 @@ intel_dp_mode_valid(struct drm_connector *connector,
 	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
 		return MODE_H_ILLEGAL;
 
-	status = intel_dp_mode_valid_downstream(intel_connector, target_clock);
+	status = intel_dp_mode_valid_downstream(intel_connector,
+						mode, target_clock);
 	if (status != MODE_OK)
 		return status;
 
@@ -6070,10 +6086,22 @@ intel_dp_set_edid(struct intel_dp *intel_dp)
 		drm_dp_downstream_max_dotclock(intel_dp->dpcd,
 					       intel_dp->downstream_ports);
 
+	intel_dp->dfp.min_tmds_clock =
+		drm_dp_downstream_min_tmds_clock(intel_dp->dpcd,
+						 intel_dp->downstream_ports,
+						 edid);
+	intel_dp->dfp.max_tmds_clock =
+		drm_dp_downstream_max_tmds_clock(intel_dp->dpcd,
+						 intel_dp->downstream_ports,
+						 edid);
+
 	drm_dbg_kms(&i915->drm,
-		    "[CONNECTOR:%d:%s] DFP max bpc %d, max dotclock %d\n",
+		    "[CONNECTOR:%d:%s] DFP max bpc %d, max dotclock %d, TMDS clock %d-%d\n",
 		    connector->base.base.id, connector->base.name,
-		    intel_dp->dfp.max_bpc, intel_dp->dfp.max_dotclock);
+		    intel_dp->dfp.max_bpc,
+		    intel_dp->dfp.max_dotclock,
+		    intel_dp->dfp.min_tmds_clock,
+		    intel_dp->dfp.max_tmds_clock);
 
 	if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
 		intel_dp->has_hdmi_sink = drm_detect_hdmi_monitor(edid);
@@ -6099,6 +6127,8 @@ intel_dp_unset_edid(struct intel_dp *intel_dp)
 
 	intel_dp->dfp.max_bpc = 0;
 	intel_dp->dfp.max_dotclock = 0;
+	intel_dp->dfp.min_tmds_clock = 0;
+	intel_dp->dfp.max_tmds_clock = 0;
 }
 
 static int
-- 
2.26.2

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v2 12/18] drm/i915: Configure DP 1.3+ protocol converted HDMI mode
  2020-09-04 11:53 ` [Intel-gfx] " Ville Syrjala
@ 2020-09-04 11:53   ` Ville Syrjala
  -1 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjala @ 2020-09-04 11:53 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

DP 1.3 adds some extra control knobs for DP->HDMI protocol conversion.
Let's use that to configure the "HDMI mode" (ie. infoframes vs. not)
based on the capabilities of the sink.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_ddi.c |  1 +
 drivers/gpu/drm/i915/display/intel_dp.c  | 23 +++++++++++++++++++++++
 drivers/gpu/drm/i915/display/intel_dp.h  |  1 +
 3 files changed, 25 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
index 28ff85493f25..9adba0d0b4aa 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -3470,6 +3470,7 @@ static void hsw_ddi_pre_enable_dp(struct intel_atomic_state *state,
 	intel_ddi_init_dp_buf_reg(encoder);
 	if (!is_mst)
 		intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
+	intel_dp_configure_protocol_converter(intel_dp);
 	intel_dp_sink_set_decompression_state(intel_dp, crtc_state,
 					      true);
 	intel_dp_sink_set_fec_ready(intel_dp, crtc_state);
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index a703e4659e47..047449253a54 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -3792,6 +3792,28 @@ static void intel_dp_enable_port(struct intel_dp *intel_dp,
 	intel_de_posting_read(dev_priv, intel_dp->output_reg);
 }
 
+void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp)
+{
+	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+	u8 tmp;
+
+	if (intel_dp->dpcd[DP_DPCD_REV] < 0x13)
+		return;
+
+	if (!drm_dp_is_branch(intel_dp->dpcd))
+		return;
+
+	tmp = intel_dp->has_hdmi_sink ?
+		DP_HDMI_DVI_OUTPUT_CONFIG : 0;
+
+	if (drm_dp_dpcd_writeb(&intel_dp->aux,
+			       DP_PROTOCOL_CONVERTER_CONTROL_0, tmp) <= 0)
+		drm_dbg_kms(&i915->drm, "Failed to set protocol converter HDMI mode to %s\n",
+			    enableddisabled(intel_dp->has_hdmi_sink));
+
+	/* TODO: configure YCbCr 4:2:2/4:2:0 conversion */
+}
+
 static void intel_enable_dp(struct intel_atomic_state *state,
 			    struct intel_encoder *encoder,
 			    const struct intel_crtc_state *pipe_config,
@@ -3829,6 +3851,7 @@ static void intel_enable_dp(struct intel_atomic_state *state,
 	}
 
 	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
+	intel_dp_configure_protocol_converter(intel_dp);
 	intel_dp_start_link_train(intel_dp);
 	intel_dp_stop_link_train(intel_dp);
 
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
index ec5688a21f66..08a1c0aa8b94 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -51,6 +51,7 @@ int intel_dp_get_link_train_fallback_values(struct intel_dp *intel_dp,
 int intel_dp_retrain_link(struct intel_encoder *encoder,
 			  struct drm_modeset_acquire_ctx *ctx);
 void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode);
+void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp);
 void intel_dp_sink_set_decompression_state(struct intel_dp *intel_dp,
 					   const struct intel_crtc_state *crtc_state,
 					   bool enable);
-- 
2.26.2

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [Intel-gfx] [PATCH v2 12/18] drm/i915: Configure DP 1.3+ protocol converted HDMI mode
@ 2020-09-04 11:53   ` Ville Syrjala
  0 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjala @ 2020-09-04 11:53 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

DP 1.3 adds some extra control knobs for DP->HDMI protocol conversion.
Let's use that to configure the "HDMI mode" (ie. infoframes vs. not)
based on the capabilities of the sink.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_ddi.c |  1 +
 drivers/gpu/drm/i915/display/intel_dp.c  | 23 +++++++++++++++++++++++
 drivers/gpu/drm/i915/display/intel_dp.h  |  1 +
 3 files changed, 25 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
index 28ff85493f25..9adba0d0b4aa 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -3470,6 +3470,7 @@ static void hsw_ddi_pre_enable_dp(struct intel_atomic_state *state,
 	intel_ddi_init_dp_buf_reg(encoder);
 	if (!is_mst)
 		intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
+	intel_dp_configure_protocol_converter(intel_dp);
 	intel_dp_sink_set_decompression_state(intel_dp, crtc_state,
 					      true);
 	intel_dp_sink_set_fec_ready(intel_dp, crtc_state);
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index a703e4659e47..047449253a54 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -3792,6 +3792,28 @@ static void intel_dp_enable_port(struct intel_dp *intel_dp,
 	intel_de_posting_read(dev_priv, intel_dp->output_reg);
 }
 
+void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp)
+{
+	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+	u8 tmp;
+
+	if (intel_dp->dpcd[DP_DPCD_REV] < 0x13)
+		return;
+
+	if (!drm_dp_is_branch(intel_dp->dpcd))
+		return;
+
+	tmp = intel_dp->has_hdmi_sink ?
+		DP_HDMI_DVI_OUTPUT_CONFIG : 0;
+
+	if (drm_dp_dpcd_writeb(&intel_dp->aux,
+			       DP_PROTOCOL_CONVERTER_CONTROL_0, tmp) <= 0)
+		drm_dbg_kms(&i915->drm, "Failed to set protocol converter HDMI mode to %s\n",
+			    enableddisabled(intel_dp->has_hdmi_sink));
+
+	/* TODO: configure YCbCr 4:2:2/4:2:0 conversion */
+}
+
 static void intel_enable_dp(struct intel_atomic_state *state,
 			    struct intel_encoder *encoder,
 			    const struct intel_crtc_state *pipe_config,
@@ -3829,6 +3851,7 @@ static void intel_enable_dp(struct intel_atomic_state *state,
 	}
 
 	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
+	intel_dp_configure_protocol_converter(intel_dp);
 	intel_dp_start_link_train(intel_dp);
 	intel_dp_stop_link_train(intel_dp);
 
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
index ec5688a21f66..08a1c0aa8b94 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -51,6 +51,7 @@ int intel_dp_get_link_train_fallback_values(struct intel_dp *intel_dp,
 int intel_dp_retrain_link(struct intel_encoder *encoder,
 			  struct drm_modeset_acquire_ctx *ctx);
 void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode);
+void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp);
 void intel_dp_sink_set_decompression_state(struct intel_dp *intel_dp,
 					   const struct intel_crtc_state *crtc_state,
 					   bool enable);
-- 
2.26.2

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v2 13/18] drm/dp: Add drm_dp_downstream_mode()
  2020-09-04 11:53 ` [Intel-gfx] " Ville Syrjala
@ 2020-09-04 11:53   ` Ville Syrjala
  -1 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjala @ 2020-09-04 11:53 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

The downstream facing port caps in the DPCD can give us a hint
as to what kind of display mode the sink can use if it doesn't
have an EDID. Use that information to pick a suitable mode.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/drm_dp_helper.c | 54 +++++++++++++++++++++++++++++++++
 drivers/gpu/drm/drm_edid.c      | 19 ++++++++++++
 include/drm/drm_dp_helper.h     | 12 ++++++++
 include/drm/drm_edid.h          |  4 +++
 4 files changed, 89 insertions(+)

diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index f567428f2aef..0d5e9bcf11d0 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -808,6 +808,60 @@ int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 }
 EXPORT_SYMBOL(drm_dp_downstream_max_bpc);
 
+/**
+ * drm_dp_downstream_mode() - return a mode for downstream facing port
+ * @dpcd: DisplayPort configuration data
+ * @port_cap: port capabilities
+ *
+ * Provides a suitable mode for downstream facing ports without EDID.
+ *
+ * Returns a new drm_display_mode on success or NULL on failure
+ */
+struct drm_display_mode *
+drm_dp_downstream_mode(struct drm_device *dev,
+		       const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+		       const u8 port_cap[4])
+
+{
+	u8 vic;
+
+	if (!drm_dp_is_branch(dpcd))
+		return NULL;
+
+	if (dpcd[DP_DPCD_REV] < 0x11)
+		return NULL;
+
+	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
+	case DP_DS_PORT_TYPE_NON_EDID:
+		switch (port_cap[0] & DP_DS_NON_EDID_MASK) {
+		case DP_DS_NON_EDID_720x480i_60:
+			vic = 6;
+			break;
+		case DP_DS_NON_EDID_720x480i_50:
+			vic = 21;
+			break;
+		case DP_DS_NON_EDID_1920x1080i_60:
+			vic = 5;
+			break;
+		case DP_DS_NON_EDID_1920x1080i_50:
+			vic = 20;
+			break;
+		case DP_DS_NON_EDID_1280x720_60:
+			vic = 4;
+			break;
+		case DP_DS_NON_EDID_1280x720_50:
+			vic = 19;
+			break;
+		default:
+			return NULL;
+		}
+		return drm_display_mode_from_cea_vic(dev, vic);
+	default:
+		return NULL;
+	}
+}
+EXPORT_SYMBOL(drm_dp_downstream_mode);
+
 /**
  * drm_dp_downstream_id() - identify branch device
  * @aux: DisplayPort AUX channel
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 6840f0530a38..b9419fed6c28 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -3738,6 +3738,25 @@ drm_add_cmdb_modes(struct drm_connector *connector, u8 svd)
 	bitmap_set(hdmi->y420_cmdb_modes, vic, 1);
 }
 
+struct drm_display_mode *
+drm_display_mode_from_cea_vic(struct drm_device *dev,
+			      u8 video_code)
+{
+	const struct drm_display_mode *cea_mode;
+	struct drm_display_mode *newmode;
+
+	cea_mode = cea_mode_for_vic(video_code);
+	if (!cea_mode)
+		return NULL;
+
+	newmode = drm_mode_duplicate(dev, cea_mode);
+	if (!newmode)
+		return NULL;
+
+	return newmode;
+}
+EXPORT_SYMBOL(drm_display_mode_from_cea_vic);
+
 static int
 do_cea_modes(struct drm_connector *connector, const u8 *db, u8 len)
 {
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index 6812a3e0de8d..fbba4a0f7366 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -28,6 +28,8 @@
 #include <linux/types.h>
 #include <drm/drm_connector.h>
 
+struct drm_device;
+
 /*
  * Unless otherwise noted, all values are from the DP 1.1a spec.  Note that
  * DP and DPCD versions are independent.  Differences from 1.0 are not noted,
@@ -385,6 +387,13 @@
 # define DP_DS_PORT_TYPE_DP_DUALMODE        5
 # define DP_DS_PORT_TYPE_WIRELESS           6
 # define DP_DS_PORT_HPD			    (1 << 3)
+# define DP_DS_NON_EDID_MASK		    (0xf << 4)
+# define DP_DS_NON_EDID_720x480i_60	    (1 << 4)
+# define DP_DS_NON_EDID_720x480i_50	    (2 << 4)
+# define DP_DS_NON_EDID_1920x1080i_60	    (3 << 4)
+# define DP_DS_NON_EDID_1920x1080i_50	    (4 << 4)
+# define DP_DS_NON_EDID_1280x720_60	    (5 << 4)
+# define DP_DS_NON_EDID_1280x720_50	    (7 << 4)
 /* offset 1 for VGA is maximum megapixels per second / 8 */
 /* offset 1 for DVI/HDMI is maximum TMDS clock in Mbps / 2.5 */
 /* offset 2 for VGA/DVI/HDMI */
@@ -1654,6 +1663,9 @@ int drm_dp_downstream_min_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 			      const u8 port_cap[4],
 			      const struct edid *edid);
+struct drm_display_mode *drm_dp_downstream_mode(struct drm_device *dev,
+						const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+						const u8 port_cap[4]);
 int drm_dp_downstream_id(struct drm_dp_aux *aux, char id[6]);
 void drm_dp_downstream_debug(struct seq_file *m,
 			     const u8 dpcd[DP_RECEIVER_CAP_SIZE],
diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
index cfa4f5af49af..b27a0e2169c8 100644
--- a/include/drm/drm_edid.h
+++ b/include/drm/drm_edid.h
@@ -517,4 +517,8 @@ 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);
+struct drm_display_mode *
+drm_display_mode_from_cea_vic(struct drm_device *dev,
+			      u8 video_code);
+
 #endif /* __DRM_EDID_H__ */
-- 
2.26.2

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [Intel-gfx] [PATCH v2 13/18] drm/dp: Add drm_dp_downstream_mode()
@ 2020-09-04 11:53   ` Ville Syrjala
  0 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjala @ 2020-09-04 11:53 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

The downstream facing port caps in the DPCD can give us a hint
as to what kind of display mode the sink can use if it doesn't
have an EDID. Use that information to pick a suitable mode.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/drm_dp_helper.c | 54 +++++++++++++++++++++++++++++++++
 drivers/gpu/drm/drm_edid.c      | 19 ++++++++++++
 include/drm/drm_dp_helper.h     | 12 ++++++++
 include/drm/drm_edid.h          |  4 +++
 4 files changed, 89 insertions(+)

diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index f567428f2aef..0d5e9bcf11d0 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -808,6 +808,60 @@ int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 }
 EXPORT_SYMBOL(drm_dp_downstream_max_bpc);
 
+/**
+ * drm_dp_downstream_mode() - return a mode for downstream facing port
+ * @dpcd: DisplayPort configuration data
+ * @port_cap: port capabilities
+ *
+ * Provides a suitable mode for downstream facing ports without EDID.
+ *
+ * Returns a new drm_display_mode on success or NULL on failure
+ */
+struct drm_display_mode *
+drm_dp_downstream_mode(struct drm_device *dev,
+		       const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+		       const u8 port_cap[4])
+
+{
+	u8 vic;
+
+	if (!drm_dp_is_branch(dpcd))
+		return NULL;
+
+	if (dpcd[DP_DPCD_REV] < 0x11)
+		return NULL;
+
+	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
+	case DP_DS_PORT_TYPE_NON_EDID:
+		switch (port_cap[0] & DP_DS_NON_EDID_MASK) {
+		case DP_DS_NON_EDID_720x480i_60:
+			vic = 6;
+			break;
+		case DP_DS_NON_EDID_720x480i_50:
+			vic = 21;
+			break;
+		case DP_DS_NON_EDID_1920x1080i_60:
+			vic = 5;
+			break;
+		case DP_DS_NON_EDID_1920x1080i_50:
+			vic = 20;
+			break;
+		case DP_DS_NON_EDID_1280x720_60:
+			vic = 4;
+			break;
+		case DP_DS_NON_EDID_1280x720_50:
+			vic = 19;
+			break;
+		default:
+			return NULL;
+		}
+		return drm_display_mode_from_cea_vic(dev, vic);
+	default:
+		return NULL;
+	}
+}
+EXPORT_SYMBOL(drm_dp_downstream_mode);
+
 /**
  * drm_dp_downstream_id() - identify branch device
  * @aux: DisplayPort AUX channel
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 6840f0530a38..b9419fed6c28 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -3738,6 +3738,25 @@ drm_add_cmdb_modes(struct drm_connector *connector, u8 svd)
 	bitmap_set(hdmi->y420_cmdb_modes, vic, 1);
 }
 
+struct drm_display_mode *
+drm_display_mode_from_cea_vic(struct drm_device *dev,
+			      u8 video_code)
+{
+	const struct drm_display_mode *cea_mode;
+	struct drm_display_mode *newmode;
+
+	cea_mode = cea_mode_for_vic(video_code);
+	if (!cea_mode)
+		return NULL;
+
+	newmode = drm_mode_duplicate(dev, cea_mode);
+	if (!newmode)
+		return NULL;
+
+	return newmode;
+}
+EXPORT_SYMBOL(drm_display_mode_from_cea_vic);
+
 static int
 do_cea_modes(struct drm_connector *connector, const u8 *db, u8 len)
 {
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index 6812a3e0de8d..fbba4a0f7366 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -28,6 +28,8 @@
 #include <linux/types.h>
 #include <drm/drm_connector.h>
 
+struct drm_device;
+
 /*
  * Unless otherwise noted, all values are from the DP 1.1a spec.  Note that
  * DP and DPCD versions are independent.  Differences from 1.0 are not noted,
@@ -385,6 +387,13 @@
 # define DP_DS_PORT_TYPE_DP_DUALMODE        5
 # define DP_DS_PORT_TYPE_WIRELESS           6
 # define DP_DS_PORT_HPD			    (1 << 3)
+# define DP_DS_NON_EDID_MASK		    (0xf << 4)
+# define DP_DS_NON_EDID_720x480i_60	    (1 << 4)
+# define DP_DS_NON_EDID_720x480i_50	    (2 << 4)
+# define DP_DS_NON_EDID_1920x1080i_60	    (3 << 4)
+# define DP_DS_NON_EDID_1920x1080i_50	    (4 << 4)
+# define DP_DS_NON_EDID_1280x720_60	    (5 << 4)
+# define DP_DS_NON_EDID_1280x720_50	    (7 << 4)
 /* offset 1 for VGA is maximum megapixels per second / 8 */
 /* offset 1 for DVI/HDMI is maximum TMDS clock in Mbps / 2.5 */
 /* offset 2 for VGA/DVI/HDMI */
@@ -1654,6 +1663,9 @@ int drm_dp_downstream_min_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 			      const u8 port_cap[4],
 			      const struct edid *edid);
+struct drm_display_mode *drm_dp_downstream_mode(struct drm_device *dev,
+						const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+						const u8 port_cap[4]);
 int drm_dp_downstream_id(struct drm_dp_aux *aux, char id[6]);
 void drm_dp_downstream_debug(struct seq_file *m,
 			     const u8 dpcd[DP_RECEIVER_CAP_SIZE],
diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
index cfa4f5af49af..b27a0e2169c8 100644
--- a/include/drm/drm_edid.h
+++ b/include/drm/drm_edid.h
@@ -517,4 +517,8 @@ 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);
+struct drm_display_mode *
+drm_display_mode_from_cea_vic(struct drm_device *dev,
+			      u8 video_code);
+
 #endif /* __DRM_EDID_H__ */
-- 
2.26.2

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v2 14/18] drm/i915: Handle downstream facing ports w/o EDID
  2020-09-04 11:53 ` [Intel-gfx] " Ville Syrjala
@ 2020-09-04 11:53   ` Ville Syrjala
  -1 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjala @ 2020-09-04 11:53 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Use drm_dp_downstream_mode() to get a suitable mode for downstream
facing ports which don't have an EDID.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 047449253a54..2798621a466a 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -6310,7 +6310,7 @@ static int intel_dp_get_modes(struct drm_connector *connector)
 	}
 
 	/* if eDP has no EDID, fall back to fixed mode */
-	if (intel_dp_is_edp(intel_attached_dp(to_intel_connector(connector))) &&
+	if (intel_dp_is_edp(intel_attached_dp(intel_connector)) &&
 	    intel_connector->panel.fixed_mode) {
 		struct drm_display_mode *mode;
 
@@ -6322,6 +6322,19 @@ static int intel_dp_get_modes(struct drm_connector *connector)
 		}
 	}
 
+	if (!edid) {
+		struct intel_dp *intel_dp = intel_attached_dp(intel_connector);
+		struct drm_display_mode *mode;
+
+		mode = drm_dp_downstream_mode(connector->dev,
+					      intel_dp->dpcd,
+					      intel_dp->downstream_ports);
+		if (mode) {
+			drm_mode_probed_add(connector, mode);
+			return 1;
+		}
+	}
+
 	return 0;
 }
 
-- 
2.26.2

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [Intel-gfx] [PATCH v2 14/18] drm/i915: Handle downstream facing ports w/o EDID
@ 2020-09-04 11:53   ` Ville Syrjala
  0 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjala @ 2020-09-04 11:53 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Use drm_dp_downstream_mode() to get a suitable mode for downstream
facing ports which don't have an EDID.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 047449253a54..2798621a466a 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -6310,7 +6310,7 @@ static int intel_dp_get_modes(struct drm_connector *connector)
 	}
 
 	/* if eDP has no EDID, fall back to fixed mode */
-	if (intel_dp_is_edp(intel_attached_dp(to_intel_connector(connector))) &&
+	if (intel_dp_is_edp(intel_attached_dp(intel_connector)) &&
 	    intel_connector->panel.fixed_mode) {
 		struct drm_display_mode *mode;
 
@@ -6322,6 +6322,19 @@ static int intel_dp_get_modes(struct drm_connector *connector)
 		}
 	}
 
+	if (!edid) {
+		struct intel_dp *intel_dp = intel_attached_dp(intel_connector);
+		struct drm_display_mode *mode;
+
+		mode = drm_dp_downstream_mode(connector->dev,
+					      intel_dp->dpcd,
+					      intel_dp->downstream_ports);
+		if (mode) {
+			drm_mode_probed_add(connector, mode);
+			return 1;
+		}
+	}
+
 	return 0;
 }
 
-- 
2.26.2

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v2 15/18] drm/i915: Extract intel_hdmi_has_audio()
  2020-09-04 11:53 ` [Intel-gfx] " Ville Syrjala
@ 2020-09-04 11:53   ` Ville Syrjala
  -1 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjala @ 2020-09-04 11:53 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Pull the "do we want to enable audio?" computation into a small helper
to make intel_hdmi_compute_config() less messy. Will make it easier to
add more checks for this later (eg. we should actually be checking
at the hblank is long enough for audio transmission).

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_hdmi.c | 28 +++++++++++++++--------
 1 file changed, 19 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
index 0978b0d8f4c6..9bf664bfd7de 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -2465,6 +2465,23 @@ bool intel_hdmi_limited_color_range(const struct intel_crtc_state *crtc_state,
 	}
 }
 
+static bool intel_hdmi_has_audio(struct intel_encoder *encoder,
+				 const struct intel_crtc_state *crtc_state,
+				 const struct drm_connector_state *conn_state)
+{
+	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+	const struct intel_digital_connector_state *intel_conn_state =
+		to_intel_digital_connector_state(conn_state);
+
+	if (!crtc_state->has_hdmi_sink)
+		return false;
+
+	if (intel_conn_state->force_audio == HDMI_AUDIO_AUTO)
+		return intel_hdmi->has_audio;
+	else
+		return intel_conn_state->force_audio == HDMI_AUDIO_ON;
+}
+
 int intel_hdmi_compute_config(struct intel_encoder *encoder,
 			      struct intel_crtc_state *pipe_config,
 			      struct drm_connector_state *conn_state)
@@ -2474,8 +2491,6 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder,
 	struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
 	struct drm_connector *connector = conn_state->connector;
 	struct drm_scdc *scdc = &connector->display_info.hdmi.scdc;
-	struct intel_digital_connector_state *intel_conn_state =
-		to_intel_digital_connector_state(conn_state);
 	int ret;
 
 	if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
@@ -2501,13 +2516,8 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder,
 	if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv))
 		pipe_config->has_pch_encoder = true;
 
-	if (pipe_config->has_hdmi_sink) {
-		if (intel_conn_state->force_audio == HDMI_AUDIO_AUTO)
-			pipe_config->has_audio = intel_hdmi->has_audio;
-		else
-			pipe_config->has_audio =
-				intel_conn_state->force_audio == HDMI_AUDIO_ON;
-	}
+	pipe_config->has_audio =
+		intel_hdmi_has_audio(encoder, pipe_config, conn_state);
 
 	ret = intel_hdmi_compute_clock(encoder, pipe_config);
 	if (ret)
-- 
2.26.2

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [Intel-gfx] [PATCH v2 15/18] drm/i915: Extract intel_hdmi_has_audio()
@ 2020-09-04 11:53   ` Ville Syrjala
  0 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjala @ 2020-09-04 11:53 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Pull the "do we want to enable audio?" computation into a small helper
to make intel_hdmi_compute_config() less messy. Will make it easier to
add more checks for this later (eg. we should actually be checking
at the hblank is long enough for audio transmission).

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_hdmi.c | 28 +++++++++++++++--------
 1 file changed, 19 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
index 0978b0d8f4c6..9bf664bfd7de 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -2465,6 +2465,23 @@ bool intel_hdmi_limited_color_range(const struct intel_crtc_state *crtc_state,
 	}
 }
 
+static bool intel_hdmi_has_audio(struct intel_encoder *encoder,
+				 const struct intel_crtc_state *crtc_state,
+				 const struct drm_connector_state *conn_state)
+{
+	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+	const struct intel_digital_connector_state *intel_conn_state =
+		to_intel_digital_connector_state(conn_state);
+
+	if (!crtc_state->has_hdmi_sink)
+		return false;
+
+	if (intel_conn_state->force_audio == HDMI_AUDIO_AUTO)
+		return intel_hdmi->has_audio;
+	else
+		return intel_conn_state->force_audio == HDMI_AUDIO_ON;
+}
+
 int intel_hdmi_compute_config(struct intel_encoder *encoder,
 			      struct intel_crtc_state *pipe_config,
 			      struct drm_connector_state *conn_state)
@@ -2474,8 +2491,6 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder,
 	struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
 	struct drm_connector *connector = conn_state->connector;
 	struct drm_scdc *scdc = &connector->display_info.hdmi.scdc;
-	struct intel_digital_connector_state *intel_conn_state =
-		to_intel_digital_connector_state(conn_state);
 	int ret;
 
 	if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
@@ -2501,13 +2516,8 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder,
 	if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv))
 		pipe_config->has_pch_encoder = true;
 
-	if (pipe_config->has_hdmi_sink) {
-		if (intel_conn_state->force_audio == HDMI_AUDIO_AUTO)
-			pipe_config->has_audio = intel_hdmi->has_audio;
-		else
-			pipe_config->has_audio =
-				intel_conn_state->force_audio == HDMI_AUDIO_ON;
-	}
+	pipe_config->has_audio =
+		intel_hdmi_has_audio(encoder, pipe_config, conn_state);
 
 	ret = intel_hdmi_compute_clock(encoder, pipe_config);
 	if (ret)
-- 
2.26.2

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v2 16/18] drm/i915: DP->HDMI TMDS clock limits vs. deep color
  2020-09-04 11:53 ` [Intel-gfx] " Ville Syrjala
@ 2020-09-04 11:53   ` Ville Syrjala
  -1 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjala @ 2020-09-04 11:53 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Account for the TMDS clock limits declared by the DFP/DP++ dongle
when determining what color depth we're going to use.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp.c   | 63 ++++++++++++++++++++---
 drivers/gpu/drm/i915/display/intel_hdmi.c | 50 ++++++++++--------
 drivers/gpu/drm/i915/display/intel_hdmi.h |  2 +
 3 files changed, 88 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 2798621a466a..c7aa66d2eb90 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1977,18 +1977,69 @@ static bool intel_dp_supports_dsc(struct intel_dp *intel_dp,
 		drm_dp_sink_supports_dsc(intel_dp->dsc_dpcd);
 }
 
-static int intel_dp_compute_bpp(struct intel_dp *intel_dp,
-				struct intel_crtc_state *pipe_config)
+static bool intel_dp_hdmi_ycbcr420(struct intel_dp *intel_dp,
+				   const struct intel_crtc_state *crtc_state)
+{
+	return crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420;
+}
+
+static int intel_dp_hdmi_tmds_clock(struct intel_dp *intel_dp,
+				    const struct intel_crtc_state *crtc_state, int bpc)
+{
+	int clock = crtc_state->hw.adjusted_mode.crtc_clock * bpc / 8;
+
+	if (intel_dp_hdmi_ycbcr420(intel_dp, crtc_state))
+		clock /= 2;
+
+	return clock;
+}
+
+static bool intel_dp_hdmi_tmds_clock_valid(struct intel_dp *intel_dp,
+					   const struct intel_crtc_state *crtc_state, int bpc)
+{
+	int tmds_clock = intel_dp_hdmi_tmds_clock(intel_dp, crtc_state, bpc);
+
+	if (intel_dp->dfp.min_tmds_clock &&
+	    tmds_clock < intel_dp->dfp.min_tmds_clock)
+		return false;
+
+	if (intel_dp->dfp.max_tmds_clock &&
+	    tmds_clock > intel_dp->dfp.max_tmds_clock)
+		return false;
+
+	return true;
+}
+
+static bool intel_dp_hdmi_deep_color_possible(struct intel_dp *intel_dp,
+					      const struct intel_crtc_state *crtc_state,
+					      int bpc)
+{
+	bool has_hdmi_sink = intel_dp->has_hdmi_sink;
+
+	return intel_hdmi_deep_color_possible(crtc_state, bpc, has_hdmi_sink) &&
+		intel_dp_hdmi_tmds_clock_valid(intel_dp, crtc_state, bpc);
+}
+
+static int intel_dp_max_bpp(struct intel_dp *intel_dp,
+			    const struct intel_crtc_state *crtc_state)
 {
 	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
 	struct intel_connector *intel_connector = intel_dp->attached_connector;
-	int bpp;
+	int bpp, bpc;
 
-	bpp = pipe_config->pipe_bpp;
+	bpc = crtc_state->pipe_bpp / 3;
 
 	if (intel_dp->dfp.max_bpc)
-		bpp = min(bpp, 3 * intel_dp->dfp.max_bpc);
+		bpc = min_t(int, bpc, intel_dp->dfp.max_bpc);
 
+	if (intel_dp->dfp.min_tmds_clock) {
+		for (; bpc >= 10; bpc -= 2) {
+			if (intel_dp_hdmi_deep_color_possible(intel_dp, crtc_state, bpc))
+				break;
+		}
+	}
+
+	bpp = bpc * 3;
 	if (intel_dp_is_edp(intel_dp)) {
 		/* Get bpp from vbt only for panels that dont have bpp in edid */
 		if (intel_connector->base.display_info.bpc == 0 &&
@@ -2310,7 +2361,7 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
 	limits.max_lane_count = intel_dp_max_lane_count(intel_dp);
 
 	limits.min_bpp = intel_dp_min_bpp(pipe_config);
-	limits.max_bpp = intel_dp_compute_bpp(intel_dp, pipe_config);
+	limits.max_bpp = intel_dp_max_bpp(intel_dp, pipe_config);
 
 	if (intel_dp_is_edp(intel_dp)) {
 		/*
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
index 9bf664bfd7de..929ae22b0a49 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -2277,35 +2277,18 @@ intel_hdmi_mode_valid(struct drm_connector *connector,
 	return intel_mode_valid_max_plane_size(dev_priv, mode);
 }
 
-static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
-				     int bpc)
+bool intel_hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
+				    int bpc, bool has_hdmi_sink)
 {
-	struct drm_i915_private *dev_priv =
-		to_i915(crtc_state->uapi.crtc->dev);
 	struct drm_atomic_state *state = crtc_state->uapi.state;
 	struct drm_connector_state *connector_state;
 	struct drm_connector *connector;
-	const struct drm_display_mode *adjusted_mode =
-		&crtc_state->hw.adjusted_mode;
 	int i;
 
-	if (HAS_GMCH(dev_priv))
-		return false;
-
-	if (bpc == 10 && INTEL_GEN(dev_priv) < 11)
-		return false;
-
 	if (crtc_state->pipe_bpp < bpc * 3)
 		return false;
 
-	if (!crtc_state->has_hdmi_sink)
-		return false;
-
-	/*
-	 * HDMI deep color affects the clocks, so it's only possible
-	 * when not cloning with other encoder types.
-	 */
-	if (crtc_state->output_types != 1 << INTEL_OUTPUT_HDMI)
+	if (!has_hdmi_sink)
 		return false;
 
 	for_each_new_connector_in_state(state, connector, connector_state, i) {
@@ -2333,6 +2316,30 @@ static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
 		}
 	}
 
+	return true;
+}
+
+static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
+				     int bpc)
+{
+	struct drm_i915_private *dev_priv =
+		to_i915(crtc_state->uapi.crtc->dev);
+	const struct drm_display_mode *adjusted_mode =
+		&crtc_state->hw.adjusted_mode;
+
+	if (HAS_GMCH(dev_priv))
+		return false;
+
+	if (bpc == 10 && INTEL_GEN(dev_priv) < 11)
+		return false;
+
+	/*
+	 * HDMI deep color affects the clocks, so it's only possible
+	 * when not cloning with other encoder types.
+	 */
+	if (crtc_state->output_types != BIT(INTEL_OUTPUT_HDMI))
+		return false;
+
 	/* Display Wa_1405510057:icl,ehl */
 	if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 &&
 	    bpc == 10 && IS_GEN(dev_priv, 11) &&
@@ -2340,7 +2347,8 @@ static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
 	     adjusted_mode->crtc_hblank_start) % 8 == 2)
 		return false;
 
-	return true;
+	return intel_hdmi_deep_color_possible(crtc_state, bpc,
+					      crtc_state->has_hdmi_sink);
 }
 
 static int
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.h b/drivers/gpu/drm/i915/display/intel_hdmi.h
index 5b348dcab77a..c382930a992e 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.h
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.h
@@ -48,5 +48,7 @@ void intel_read_infoframe(struct intel_encoder *encoder,
 			  union hdmi_infoframe *frame);
 bool intel_hdmi_limited_color_range(const struct intel_crtc_state *crtc_state,
 				    const struct drm_connector_state *conn_state);
+bool intel_hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
+				    int bpc, bool has_hdmi_sink);
 
 #endif /* __INTEL_HDMI_H__ */
-- 
2.26.2

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [Intel-gfx] [PATCH v2 16/18] drm/i915: DP->HDMI TMDS clock limits vs. deep color
@ 2020-09-04 11:53   ` Ville Syrjala
  0 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjala @ 2020-09-04 11:53 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Account for the TMDS clock limits declared by the DFP/DP++ dongle
when determining what color depth we're going to use.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp.c   | 63 ++++++++++++++++++++---
 drivers/gpu/drm/i915/display/intel_hdmi.c | 50 ++++++++++--------
 drivers/gpu/drm/i915/display/intel_hdmi.h |  2 +
 3 files changed, 88 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 2798621a466a..c7aa66d2eb90 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1977,18 +1977,69 @@ static bool intel_dp_supports_dsc(struct intel_dp *intel_dp,
 		drm_dp_sink_supports_dsc(intel_dp->dsc_dpcd);
 }
 
-static int intel_dp_compute_bpp(struct intel_dp *intel_dp,
-				struct intel_crtc_state *pipe_config)
+static bool intel_dp_hdmi_ycbcr420(struct intel_dp *intel_dp,
+				   const struct intel_crtc_state *crtc_state)
+{
+	return crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420;
+}
+
+static int intel_dp_hdmi_tmds_clock(struct intel_dp *intel_dp,
+				    const struct intel_crtc_state *crtc_state, int bpc)
+{
+	int clock = crtc_state->hw.adjusted_mode.crtc_clock * bpc / 8;
+
+	if (intel_dp_hdmi_ycbcr420(intel_dp, crtc_state))
+		clock /= 2;
+
+	return clock;
+}
+
+static bool intel_dp_hdmi_tmds_clock_valid(struct intel_dp *intel_dp,
+					   const struct intel_crtc_state *crtc_state, int bpc)
+{
+	int tmds_clock = intel_dp_hdmi_tmds_clock(intel_dp, crtc_state, bpc);
+
+	if (intel_dp->dfp.min_tmds_clock &&
+	    tmds_clock < intel_dp->dfp.min_tmds_clock)
+		return false;
+
+	if (intel_dp->dfp.max_tmds_clock &&
+	    tmds_clock > intel_dp->dfp.max_tmds_clock)
+		return false;
+
+	return true;
+}
+
+static bool intel_dp_hdmi_deep_color_possible(struct intel_dp *intel_dp,
+					      const struct intel_crtc_state *crtc_state,
+					      int bpc)
+{
+	bool has_hdmi_sink = intel_dp->has_hdmi_sink;
+
+	return intel_hdmi_deep_color_possible(crtc_state, bpc, has_hdmi_sink) &&
+		intel_dp_hdmi_tmds_clock_valid(intel_dp, crtc_state, bpc);
+}
+
+static int intel_dp_max_bpp(struct intel_dp *intel_dp,
+			    const struct intel_crtc_state *crtc_state)
 {
 	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
 	struct intel_connector *intel_connector = intel_dp->attached_connector;
-	int bpp;
+	int bpp, bpc;
 
-	bpp = pipe_config->pipe_bpp;
+	bpc = crtc_state->pipe_bpp / 3;
 
 	if (intel_dp->dfp.max_bpc)
-		bpp = min(bpp, 3 * intel_dp->dfp.max_bpc);
+		bpc = min_t(int, bpc, intel_dp->dfp.max_bpc);
 
+	if (intel_dp->dfp.min_tmds_clock) {
+		for (; bpc >= 10; bpc -= 2) {
+			if (intel_dp_hdmi_deep_color_possible(intel_dp, crtc_state, bpc))
+				break;
+		}
+	}
+
+	bpp = bpc * 3;
 	if (intel_dp_is_edp(intel_dp)) {
 		/* Get bpp from vbt only for panels that dont have bpp in edid */
 		if (intel_connector->base.display_info.bpc == 0 &&
@@ -2310,7 +2361,7 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
 	limits.max_lane_count = intel_dp_max_lane_count(intel_dp);
 
 	limits.min_bpp = intel_dp_min_bpp(pipe_config);
-	limits.max_bpp = intel_dp_compute_bpp(intel_dp, pipe_config);
+	limits.max_bpp = intel_dp_max_bpp(intel_dp, pipe_config);
 
 	if (intel_dp_is_edp(intel_dp)) {
 		/*
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
index 9bf664bfd7de..929ae22b0a49 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -2277,35 +2277,18 @@ intel_hdmi_mode_valid(struct drm_connector *connector,
 	return intel_mode_valid_max_plane_size(dev_priv, mode);
 }
 
-static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
-				     int bpc)
+bool intel_hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
+				    int bpc, bool has_hdmi_sink)
 {
-	struct drm_i915_private *dev_priv =
-		to_i915(crtc_state->uapi.crtc->dev);
 	struct drm_atomic_state *state = crtc_state->uapi.state;
 	struct drm_connector_state *connector_state;
 	struct drm_connector *connector;
-	const struct drm_display_mode *adjusted_mode =
-		&crtc_state->hw.adjusted_mode;
 	int i;
 
-	if (HAS_GMCH(dev_priv))
-		return false;
-
-	if (bpc == 10 && INTEL_GEN(dev_priv) < 11)
-		return false;
-
 	if (crtc_state->pipe_bpp < bpc * 3)
 		return false;
 
-	if (!crtc_state->has_hdmi_sink)
-		return false;
-
-	/*
-	 * HDMI deep color affects the clocks, so it's only possible
-	 * when not cloning with other encoder types.
-	 */
-	if (crtc_state->output_types != 1 << INTEL_OUTPUT_HDMI)
+	if (!has_hdmi_sink)
 		return false;
 
 	for_each_new_connector_in_state(state, connector, connector_state, i) {
@@ -2333,6 +2316,30 @@ static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
 		}
 	}
 
+	return true;
+}
+
+static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
+				     int bpc)
+{
+	struct drm_i915_private *dev_priv =
+		to_i915(crtc_state->uapi.crtc->dev);
+	const struct drm_display_mode *adjusted_mode =
+		&crtc_state->hw.adjusted_mode;
+
+	if (HAS_GMCH(dev_priv))
+		return false;
+
+	if (bpc == 10 && INTEL_GEN(dev_priv) < 11)
+		return false;
+
+	/*
+	 * HDMI deep color affects the clocks, so it's only possible
+	 * when not cloning with other encoder types.
+	 */
+	if (crtc_state->output_types != BIT(INTEL_OUTPUT_HDMI))
+		return false;
+
 	/* Display Wa_1405510057:icl,ehl */
 	if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 &&
 	    bpc == 10 && IS_GEN(dev_priv, 11) &&
@@ -2340,7 +2347,8 @@ static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
 	     adjusted_mode->crtc_hblank_start) % 8 == 2)
 		return false;
 
-	return true;
+	return intel_hdmi_deep_color_possible(crtc_state, bpc,
+					      crtc_state->has_hdmi_sink);
 }
 
 static int
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.h b/drivers/gpu/drm/i915/display/intel_hdmi.h
index 5b348dcab77a..c382930a992e 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.h
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.h
@@ -48,5 +48,7 @@ void intel_read_infoframe(struct intel_encoder *encoder,
 			  union hdmi_infoframe *frame);
 bool intel_hdmi_limited_color_range(const struct intel_crtc_state *crtc_state,
 				    const struct drm_connector_state *conn_state);
+bool intel_hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
+				    int bpc, bool has_hdmi_sink);
 
 #endif /* __INTEL_HDMI_H__ */
-- 
2.26.2

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v2 17/18] drm/dp: Add helpers for DFP YCbCr 4:2:0 handling
  2020-09-04 11:53 ` [Intel-gfx] " Ville Syrjala
@ 2020-09-04 11:53   ` Ville Syrjala
  -1 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjala @ 2020-09-04 11:53 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Add helpers to determine whether the DFP supports
YCbCr 4:2:0 passthrough or YCbCr 4:4:4->4:2:0 conversion.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/drm_dp_helper.c | 44 +++++++++++++++++++++++++++++++++
 include/drm/drm_dp_helper.h     |  8 ++++++
 2 files changed, 52 insertions(+)

diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index 0d5e9bcf11d0..dc68e10aa1fd 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -808,6 +808,50 @@ int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 }
 EXPORT_SYMBOL(drm_dp_downstream_max_bpc);
 
+bool drm_dp_downstream_420_passthrough(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+				       const u8 port_cap[4])
+{
+	if (!drm_dp_is_branch(dpcd))
+		return false;
+
+	if (dpcd[DP_DPCD_REV] < 0x13)
+		return false;
+
+	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
+	case DP_DS_PORT_TYPE_DP:
+		return true;
+	case DP_DS_PORT_TYPE_HDMI:
+		if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
+			return false;
+
+		return port_cap[3] & DP_DS_HDMI_YCBCR420_PASS_THROUGH;
+	default:
+		return false;
+	}
+}
+EXPORT_SYMBOL(drm_dp_downstream_420_passthrough);
+
+bool drm_dp_downstream_444_to_420_conversion(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+					     const u8 port_cap[4])
+{
+	if (!drm_dp_is_branch(dpcd))
+		return false;
+
+	if (dpcd[DP_DPCD_REV] < 0x13)
+		return false;
+
+	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
+	case DP_DS_PORT_TYPE_HDMI:
+		if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
+			return false;
+
+		return port_cap[3] & DP_DS_HDMI_YCBCR444_TO_420_CONV;
+	default:
+		return false;
+	}
+}
+EXPORT_SYMBOL(drm_dp_downstream_444_to_420_conversion);
+
 /**
  * drm_dp_downstream_mode() - return a mode for downstream facing port
  * @dpcd: DisplayPort configuration data
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index fbba4a0f7366..c9f2851904d0 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -407,6 +407,10 @@ struct drm_device;
 # define DP_DS_DVI_HIGH_COLOR_DEPTH	    (1 << 2)
 /* offset 3 for HDMI */
 # define DP_DS_HDMI_FRAME_SEQ_TO_FRAME_PACK (1 << 0)
+# define DP_DS_HDMI_YCBCR422_PASS_THROUGH   (1 << 1)
+# define DP_DS_HDMI_YCBCR420_PASS_THROUGH   (1 << 2)
+# define DP_DS_HDMI_YCBCR444_TO_422_CONV    (1 << 3)
+# define DP_DS_HDMI_YCBCR444_TO_420_CONV    (1 << 4)
 
 #define DP_MAX_DOWNSTREAM_PORTS		    0x10
 
@@ -1663,6 +1667,10 @@ int drm_dp_downstream_min_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 			      const u8 port_cap[4],
 			      const struct edid *edid);
+bool drm_dp_downstream_420_passthrough(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+				       const u8 port_cap[4]);
+bool drm_dp_downstream_444_to_420_conversion(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+					     const u8 port_cap[4]);
 struct drm_display_mode *drm_dp_downstream_mode(struct drm_device *dev,
 						const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 						const u8 port_cap[4]);
-- 
2.26.2

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [Intel-gfx] [PATCH v2 17/18] drm/dp: Add helpers for DFP YCbCr 4:2:0 handling
@ 2020-09-04 11:53   ` Ville Syrjala
  0 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjala @ 2020-09-04 11:53 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Add helpers to determine whether the DFP supports
YCbCr 4:2:0 passthrough or YCbCr 4:4:4->4:2:0 conversion.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/drm_dp_helper.c | 44 +++++++++++++++++++++++++++++++++
 include/drm/drm_dp_helper.h     |  8 ++++++
 2 files changed, 52 insertions(+)

diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index 0d5e9bcf11d0..dc68e10aa1fd 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -808,6 +808,50 @@ int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 }
 EXPORT_SYMBOL(drm_dp_downstream_max_bpc);
 
+bool drm_dp_downstream_420_passthrough(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+				       const u8 port_cap[4])
+{
+	if (!drm_dp_is_branch(dpcd))
+		return false;
+
+	if (dpcd[DP_DPCD_REV] < 0x13)
+		return false;
+
+	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
+	case DP_DS_PORT_TYPE_DP:
+		return true;
+	case DP_DS_PORT_TYPE_HDMI:
+		if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
+			return false;
+
+		return port_cap[3] & DP_DS_HDMI_YCBCR420_PASS_THROUGH;
+	default:
+		return false;
+	}
+}
+EXPORT_SYMBOL(drm_dp_downstream_420_passthrough);
+
+bool drm_dp_downstream_444_to_420_conversion(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+					     const u8 port_cap[4])
+{
+	if (!drm_dp_is_branch(dpcd))
+		return false;
+
+	if (dpcd[DP_DPCD_REV] < 0x13)
+		return false;
+
+	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
+	case DP_DS_PORT_TYPE_HDMI:
+		if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
+			return false;
+
+		return port_cap[3] & DP_DS_HDMI_YCBCR444_TO_420_CONV;
+	default:
+		return false;
+	}
+}
+EXPORT_SYMBOL(drm_dp_downstream_444_to_420_conversion);
+
 /**
  * drm_dp_downstream_mode() - return a mode for downstream facing port
  * @dpcd: DisplayPort configuration data
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index fbba4a0f7366..c9f2851904d0 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -407,6 +407,10 @@ struct drm_device;
 # define DP_DS_DVI_HIGH_COLOR_DEPTH	    (1 << 2)
 /* offset 3 for HDMI */
 # define DP_DS_HDMI_FRAME_SEQ_TO_FRAME_PACK (1 << 0)
+# define DP_DS_HDMI_YCBCR422_PASS_THROUGH   (1 << 1)
+# define DP_DS_HDMI_YCBCR420_PASS_THROUGH   (1 << 2)
+# define DP_DS_HDMI_YCBCR444_TO_422_CONV    (1 << 3)
+# define DP_DS_HDMI_YCBCR444_TO_420_CONV    (1 << 4)
 
 #define DP_MAX_DOWNSTREAM_PORTS		    0x10
 
@@ -1663,6 +1667,10 @@ int drm_dp_downstream_min_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 			      const u8 port_cap[4],
 			      const struct edid *edid);
+bool drm_dp_downstream_420_passthrough(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+				       const u8 port_cap[4]);
+bool drm_dp_downstream_444_to_420_conversion(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
+					     const u8 port_cap[4]);
 struct drm_display_mode *drm_dp_downstream_mode(struct drm_device *dev,
 						const u8 dpcd[DP_RECEIVER_CAP_SIZE],
 						const u8 port_cap[4]);
-- 
2.26.2

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [PATCH v2 18/18] drm/i915: Do YCbCr 444->420 conversion via DP protocol converters
  2020-09-04 11:53 ` [Intel-gfx] " Ville Syrjala
@ 2020-09-04 11:53   ` Ville Syrjala
  -1 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjala @ 2020-09-04 11:53 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

For platforms that can't do native 4:2:0 outout we may still be
able to do it by getting the DP->HDMI protocol converter to
perform the 4:4:4->4:2:0 downsamling for us. In this case we
have to configure our hardware to output YCbCr 4:4:4, which we've
already hooked up so all we need to do is flip the switch.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 .../drm/i915/display/intel_display_types.h    |   1 +
 drivers/gpu/drm/i915/display/intel_dp.c       | 121 +++++++++++++++---
 drivers/gpu/drm/i915/display/intel_hdmi.c     |   8 +-
 drivers/gpu/drm/i915/display/intel_hdmi.h     |   4 +-
 4 files changed, 109 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 7980426e618b..293b06f9ac61 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1384,6 +1384,7 @@ struct intel_dp {
 		int min_tmds_clock, max_tmds_clock;
 		int max_dotclock;
 		u8 max_bpc;
+		bool ycbcr_444_to_420;
 	} dfp;
 
 	/* Display stream compression testing */
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index c7aa66d2eb90..156a23b540fd 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1980,7 +1980,9 @@ static bool intel_dp_supports_dsc(struct intel_dp *intel_dp,
 static bool intel_dp_hdmi_ycbcr420(struct intel_dp *intel_dp,
 				   const struct intel_crtc_state *crtc_state)
 {
-	return crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420;
+	return crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 ||
+		(crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR444 &&
+		 intel_dp->dfp.ycbcr_444_to_420);
 }
 
 static int intel_dp_hdmi_tmds_clock(struct intel_dp *intel_dp,
@@ -2014,9 +2016,10 @@ static bool intel_dp_hdmi_deep_color_possible(struct intel_dp *intel_dp,
 					      const struct intel_crtc_state *crtc_state,
 					      int bpc)
 {
-	bool has_hdmi_sink = intel_dp->has_hdmi_sink;
 
-	return intel_hdmi_deep_color_possible(crtc_state, bpc, has_hdmi_sink) &&
+	return intel_hdmi_deep_color_possible(crtc_state, bpc,
+					      intel_dp->has_hdmi_sink,
+					      intel_dp_hdmi_ycbcr420(intel_dp, crtc_state)) &&
 		intel_dp_hdmi_tmds_clock_valid(intel_dp, crtc_state, bpc);
 }
 
@@ -2436,11 +2439,17 @@ intel_dp_ycbcr420_config(struct intel_dp *intel_dp,
 	const struct drm_display_mode *adjusted_mode =
 		&crtc_state->hw.adjusted_mode;
 
-	if (!drm_mode_is_420_only(info, adjusted_mode) ||
-	    !intel_dp_get_colorimetry_status(intel_dp) ||
-	    !connector->ycbcr_420_allowed)
+	if (!connector->ycbcr_420_allowed)
 		return 0;
 
+	if (!drm_mode_is_420_only(info, adjusted_mode))
+		return 0;
+
+	if (intel_dp->dfp.ycbcr_444_to_420) {
+		crtc_state->output_format = INTEL_OUTPUT_FORMAT_YCBCR444;
+		return 0;
+	}
+
 	crtc_state->output_format = INTEL_OUTPUT_FORMAT_YCBCR420;
 
 	return intel_pch_panel_fitting(crtc_state, conn_state);
@@ -3858,11 +3867,26 @@ void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp)
 		DP_HDMI_DVI_OUTPUT_CONFIG : 0;
 
 	if (drm_dp_dpcd_writeb(&intel_dp->aux,
-			       DP_PROTOCOL_CONVERTER_CONTROL_0, tmp) <= 0)
+			       DP_PROTOCOL_CONVERTER_CONTROL_0, tmp) != 1)
 		drm_dbg_kms(&i915->drm, "Failed to set protocol converter HDMI mode to %s\n",
 			    enableddisabled(intel_dp->has_hdmi_sink));
 
-	/* TODO: configure YCbCr 4:2:2/4:2:0 conversion */
+	tmp = intel_dp->dfp.ycbcr_444_to_420 ?
+		DP_CONVERSION_TO_YCBCR420_ENABLE : 0;
+
+	if (drm_dp_dpcd_writeb(&intel_dp->aux,
+			       DP_PROTOCOL_CONVERTER_CONTROL_1, tmp) != 1)
+		drm_dbg_kms(&i915->drm,
+			    "Failed to set protocol converter YCbCr 4:2:0 conversion mode to %s\n",
+			    enableddisabled(intel_dp->dfp.ycbcr_444_to_420));
+
+	tmp = 0;
+
+	if (drm_dp_dpcd_writeb(&intel_dp->aux,
+			       DP_PROTOCOL_CONVERTER_CONTROL_2, tmp) <= 0)
+		drm_dbg_kms(&i915->drm,
+			    "Failed to set protocol converter YCbCr 4:2:2 conversion mode to %s\n",
+			    enableddisabled(false));
 }
 
 static void intel_enable_dp(struct intel_atomic_state *state,
@@ -6142,15 +6166,11 @@ intel_dp_get_edid(struct intel_dp *intel_dp)
 }
 
 static void
-intel_dp_set_edid(struct intel_dp *intel_dp)
+intel_dp_update_dfp(struct intel_dp *intel_dp,
+		    const struct edid *edid)
 {
 	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
 	struct intel_connector *connector = intel_dp->attached_connector;
-	struct edid *edid;
-
-	intel_dp_unset_edid(intel_dp);
-	edid = intel_dp_get_edid(intel_dp);
-	connector->detect_edid = edid;
 
 	intel_dp->dfp.max_bpc =
 		drm_dp_downstream_max_bpc(intel_dp->dpcd,
@@ -6176,6 +6196,67 @@ intel_dp_set_edid(struct intel_dp *intel_dp)
 		    intel_dp->dfp.max_dotclock,
 		    intel_dp->dfp.min_tmds_clock,
 		    intel_dp->dfp.max_tmds_clock);
+}
+
+static void
+intel_dp_update_420(struct intel_dp *intel_dp)
+{
+	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+	struct intel_connector *connector = intel_dp->attached_connector;
+	bool is_branch, ycbcr_420_passthrough, ycbcr_444_to_420;
+
+	/* No YCbCr output support on gmch platforms */
+	if (HAS_GMCH(i915))
+		return;
+
+	/*
+	 * ILK doesn't seem capable of DP YCbCr output. The
+	 * displayed image is severly corrupted. SNB+ is fine.
+	 */
+	if (IS_GEN(i915, 5))
+		return;
+
+	is_branch = drm_dp_is_branch(intel_dp->dpcd);
+	ycbcr_420_passthrough =
+		drm_dp_downstream_420_passthrough(intel_dp->dpcd,
+						  intel_dp->downstream_ports);
+	ycbcr_444_to_420 =
+		drm_dp_downstream_444_to_420_conversion(intel_dp->dpcd,
+							intel_dp->downstream_ports);
+
+	if (INTEL_GEN(i915) >= 11) {
+		/* Prefer 4:2:0 passthrough over 4:4:4->4:2:0 conversion */
+		intel_dp->dfp.ycbcr_444_to_420 =
+			ycbcr_444_to_420 && !ycbcr_420_passthrough;
+
+		connector->base.ycbcr_420_allowed =
+			!is_branch || ycbcr_444_to_420 || ycbcr_420_passthrough;
+	} else {
+		/* 4:4:4->4:2:0 conversion is the only way */
+		intel_dp->dfp.ycbcr_444_to_420 = ycbcr_444_to_420;
+
+		connector->base.ycbcr_420_allowed = ycbcr_444_to_420;
+	}
+
+	drm_dbg_kms(&i915->drm,
+		    "[CONNECTOR:%d:%s] YCbCr 4:2:0 allowed? %s, YCbCr 4:4:4->4:2:0 conversion? %s\n",
+		    connector->base.base.id, connector->base.name,
+		    yesno(connector->base.ycbcr_420_allowed),
+		    yesno(intel_dp->dfp.ycbcr_444_to_420));
+}
+
+static void
+intel_dp_set_edid(struct intel_dp *intel_dp)
+{
+	struct intel_connector *connector = intel_dp->attached_connector;
+	struct edid *edid;
+
+	intel_dp_unset_edid(intel_dp);
+	edid = intel_dp_get_edid(intel_dp);
+	connector->detect_edid = edid;
+
+	intel_dp_update_dfp(intel_dp, edid);
+	intel_dp_update_420(intel_dp);
 
 	if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
 		intel_dp->has_hdmi_sink = drm_detect_hdmi_monitor(edid);
@@ -6189,11 +6270,11 @@ intel_dp_set_edid(struct intel_dp *intel_dp)
 static void
 intel_dp_unset_edid(struct intel_dp *intel_dp)
 {
-	struct intel_connector *intel_connector = intel_dp->attached_connector;
+	struct intel_connector *connector = intel_dp->attached_connector;
 
 	drm_dp_cec_unset_edid(&intel_dp->aux);
-	kfree(intel_connector->detect_edid);
-	intel_connector->detect_edid = NULL;
+	kfree(connector->detect_edid);
+	connector->detect_edid = NULL;
 
 	intel_dp->has_hdmi_sink = false;
 	intel_dp->has_audio = false;
@@ -6203,6 +6284,9 @@ intel_dp_unset_edid(struct intel_dp *intel_dp)
 	intel_dp->dfp.max_dotclock = 0;
 	intel_dp->dfp.min_tmds_clock = 0;
 	intel_dp->dfp.max_tmds_clock = 0;
+
+	intel_dp->dfp.ycbcr_444_to_420 = false;
+	connector->base.ycbcr_420_allowed = false;
 }
 
 static int
@@ -7726,9 +7810,6 @@ intel_dp_init_connector(struct intel_digital_port *dig_port,
 		connector->interlace_allowed = true;
 	connector->doublescan_allowed = 0;
 
-	if (INTEL_GEN(dev_priv) >= 11)
-		connector->ycbcr_420_allowed = true;
-
 	intel_encoder->hpd_pin = intel_hpd_pin_default(dev_priv, port);
 	intel_connector->polled = DRM_CONNECTOR_POLL_HPD;
 
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
index 929ae22b0a49..ef90607f1cd8 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -2278,7 +2278,7 @@ intel_hdmi_mode_valid(struct drm_connector *connector,
 }
 
 bool intel_hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
-				    int bpc, bool has_hdmi_sink)
+				    int bpc, bool has_hdmi_sink, bool ycbcr420_output)
 {
 	struct drm_atomic_state *state = crtc_state->uapi.state;
 	struct drm_connector_state *connector_state;
@@ -2297,7 +2297,7 @@ bool intel_hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
 		if (connector_state->crtc != crtc_state->uapi.crtc)
 			continue;
 
-		if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420) {
+		if (ycbcr420_output) {
 			const struct drm_hdmi_info *hdmi = &info->hdmi;
 
 			if (bpc == 12 && !(hdmi->y420_dc_modes &
@@ -2348,7 +2348,9 @@ static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
 		return false;
 
 	return intel_hdmi_deep_color_possible(crtc_state, bpc,
-					      crtc_state->has_hdmi_sink);
+					      crtc_state->has_hdmi_sink,
+					      crtc_state->output_format ==
+					      INTEL_OUTPUT_FORMAT_YCBCR420);
 }
 
 static int
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.h b/drivers/gpu/drm/i915/display/intel_hdmi.h
index c382930a992e..15eb0ccde76e 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.h
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.h
@@ -48,7 +48,7 @@ void intel_read_infoframe(struct intel_encoder *encoder,
 			  union hdmi_infoframe *frame);
 bool intel_hdmi_limited_color_range(const struct intel_crtc_state *crtc_state,
 				    const struct drm_connector_state *conn_state);
-bool intel_hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
-				    int bpc, bool has_hdmi_sink);
+bool intel_hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state, int bpc,
+				    bool has_hdmi_sink, bool ycbcr420_output);
 
 #endif /* __INTEL_HDMI_H__ */
-- 
2.26.2

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [Intel-gfx] [PATCH v2 18/18] drm/i915: Do YCbCr 444->420 conversion via DP protocol converters
@ 2020-09-04 11:53   ` Ville Syrjala
  0 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjala @ 2020-09-04 11:53 UTC (permalink / raw)
  To: dri-devel; +Cc: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

For platforms that can't do native 4:2:0 outout we may still be
able to do it by getting the DP->HDMI protocol converter to
perform the 4:4:4->4:2:0 downsamling for us. In this case we
have to configure our hardware to output YCbCr 4:4:4, which we've
already hooked up so all we need to do is flip the switch.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 .../drm/i915/display/intel_display_types.h    |   1 +
 drivers/gpu/drm/i915/display/intel_dp.c       | 121 +++++++++++++++---
 drivers/gpu/drm/i915/display/intel_hdmi.c     |   8 +-
 drivers/gpu/drm/i915/display/intel_hdmi.h     |   4 +-
 4 files changed, 109 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 7980426e618b..293b06f9ac61 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1384,6 +1384,7 @@ struct intel_dp {
 		int min_tmds_clock, max_tmds_clock;
 		int max_dotclock;
 		u8 max_bpc;
+		bool ycbcr_444_to_420;
 	} dfp;
 
 	/* Display stream compression testing */
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index c7aa66d2eb90..156a23b540fd 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1980,7 +1980,9 @@ static bool intel_dp_supports_dsc(struct intel_dp *intel_dp,
 static bool intel_dp_hdmi_ycbcr420(struct intel_dp *intel_dp,
 				   const struct intel_crtc_state *crtc_state)
 {
-	return crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420;
+	return crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 ||
+		(crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR444 &&
+		 intel_dp->dfp.ycbcr_444_to_420);
 }
 
 static int intel_dp_hdmi_tmds_clock(struct intel_dp *intel_dp,
@@ -2014,9 +2016,10 @@ static bool intel_dp_hdmi_deep_color_possible(struct intel_dp *intel_dp,
 					      const struct intel_crtc_state *crtc_state,
 					      int bpc)
 {
-	bool has_hdmi_sink = intel_dp->has_hdmi_sink;
 
-	return intel_hdmi_deep_color_possible(crtc_state, bpc, has_hdmi_sink) &&
+	return intel_hdmi_deep_color_possible(crtc_state, bpc,
+					      intel_dp->has_hdmi_sink,
+					      intel_dp_hdmi_ycbcr420(intel_dp, crtc_state)) &&
 		intel_dp_hdmi_tmds_clock_valid(intel_dp, crtc_state, bpc);
 }
 
@@ -2436,11 +2439,17 @@ intel_dp_ycbcr420_config(struct intel_dp *intel_dp,
 	const struct drm_display_mode *adjusted_mode =
 		&crtc_state->hw.adjusted_mode;
 
-	if (!drm_mode_is_420_only(info, adjusted_mode) ||
-	    !intel_dp_get_colorimetry_status(intel_dp) ||
-	    !connector->ycbcr_420_allowed)
+	if (!connector->ycbcr_420_allowed)
 		return 0;
 
+	if (!drm_mode_is_420_only(info, adjusted_mode))
+		return 0;
+
+	if (intel_dp->dfp.ycbcr_444_to_420) {
+		crtc_state->output_format = INTEL_OUTPUT_FORMAT_YCBCR444;
+		return 0;
+	}
+
 	crtc_state->output_format = INTEL_OUTPUT_FORMAT_YCBCR420;
 
 	return intel_pch_panel_fitting(crtc_state, conn_state);
@@ -3858,11 +3867,26 @@ void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp)
 		DP_HDMI_DVI_OUTPUT_CONFIG : 0;
 
 	if (drm_dp_dpcd_writeb(&intel_dp->aux,
-			       DP_PROTOCOL_CONVERTER_CONTROL_0, tmp) <= 0)
+			       DP_PROTOCOL_CONVERTER_CONTROL_0, tmp) != 1)
 		drm_dbg_kms(&i915->drm, "Failed to set protocol converter HDMI mode to %s\n",
 			    enableddisabled(intel_dp->has_hdmi_sink));
 
-	/* TODO: configure YCbCr 4:2:2/4:2:0 conversion */
+	tmp = intel_dp->dfp.ycbcr_444_to_420 ?
+		DP_CONVERSION_TO_YCBCR420_ENABLE : 0;
+
+	if (drm_dp_dpcd_writeb(&intel_dp->aux,
+			       DP_PROTOCOL_CONVERTER_CONTROL_1, tmp) != 1)
+		drm_dbg_kms(&i915->drm,
+			    "Failed to set protocol converter YCbCr 4:2:0 conversion mode to %s\n",
+			    enableddisabled(intel_dp->dfp.ycbcr_444_to_420));
+
+	tmp = 0;
+
+	if (drm_dp_dpcd_writeb(&intel_dp->aux,
+			       DP_PROTOCOL_CONVERTER_CONTROL_2, tmp) <= 0)
+		drm_dbg_kms(&i915->drm,
+			    "Failed to set protocol converter YCbCr 4:2:2 conversion mode to %s\n",
+			    enableddisabled(false));
 }
 
 static void intel_enable_dp(struct intel_atomic_state *state,
@@ -6142,15 +6166,11 @@ intel_dp_get_edid(struct intel_dp *intel_dp)
 }
 
 static void
-intel_dp_set_edid(struct intel_dp *intel_dp)
+intel_dp_update_dfp(struct intel_dp *intel_dp,
+		    const struct edid *edid)
 {
 	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
 	struct intel_connector *connector = intel_dp->attached_connector;
-	struct edid *edid;
-
-	intel_dp_unset_edid(intel_dp);
-	edid = intel_dp_get_edid(intel_dp);
-	connector->detect_edid = edid;
 
 	intel_dp->dfp.max_bpc =
 		drm_dp_downstream_max_bpc(intel_dp->dpcd,
@@ -6176,6 +6196,67 @@ intel_dp_set_edid(struct intel_dp *intel_dp)
 		    intel_dp->dfp.max_dotclock,
 		    intel_dp->dfp.min_tmds_clock,
 		    intel_dp->dfp.max_tmds_clock);
+}
+
+static void
+intel_dp_update_420(struct intel_dp *intel_dp)
+{
+	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+	struct intel_connector *connector = intel_dp->attached_connector;
+	bool is_branch, ycbcr_420_passthrough, ycbcr_444_to_420;
+
+	/* No YCbCr output support on gmch platforms */
+	if (HAS_GMCH(i915))
+		return;
+
+	/*
+	 * ILK doesn't seem capable of DP YCbCr output. The
+	 * displayed image is severly corrupted. SNB+ is fine.
+	 */
+	if (IS_GEN(i915, 5))
+		return;
+
+	is_branch = drm_dp_is_branch(intel_dp->dpcd);
+	ycbcr_420_passthrough =
+		drm_dp_downstream_420_passthrough(intel_dp->dpcd,
+						  intel_dp->downstream_ports);
+	ycbcr_444_to_420 =
+		drm_dp_downstream_444_to_420_conversion(intel_dp->dpcd,
+							intel_dp->downstream_ports);
+
+	if (INTEL_GEN(i915) >= 11) {
+		/* Prefer 4:2:0 passthrough over 4:4:4->4:2:0 conversion */
+		intel_dp->dfp.ycbcr_444_to_420 =
+			ycbcr_444_to_420 && !ycbcr_420_passthrough;
+
+		connector->base.ycbcr_420_allowed =
+			!is_branch || ycbcr_444_to_420 || ycbcr_420_passthrough;
+	} else {
+		/* 4:4:4->4:2:0 conversion is the only way */
+		intel_dp->dfp.ycbcr_444_to_420 = ycbcr_444_to_420;
+
+		connector->base.ycbcr_420_allowed = ycbcr_444_to_420;
+	}
+
+	drm_dbg_kms(&i915->drm,
+		    "[CONNECTOR:%d:%s] YCbCr 4:2:0 allowed? %s, YCbCr 4:4:4->4:2:0 conversion? %s\n",
+		    connector->base.base.id, connector->base.name,
+		    yesno(connector->base.ycbcr_420_allowed),
+		    yesno(intel_dp->dfp.ycbcr_444_to_420));
+}
+
+static void
+intel_dp_set_edid(struct intel_dp *intel_dp)
+{
+	struct intel_connector *connector = intel_dp->attached_connector;
+	struct edid *edid;
+
+	intel_dp_unset_edid(intel_dp);
+	edid = intel_dp_get_edid(intel_dp);
+	connector->detect_edid = edid;
+
+	intel_dp_update_dfp(intel_dp, edid);
+	intel_dp_update_420(intel_dp);
 
 	if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) {
 		intel_dp->has_hdmi_sink = drm_detect_hdmi_monitor(edid);
@@ -6189,11 +6270,11 @@ intel_dp_set_edid(struct intel_dp *intel_dp)
 static void
 intel_dp_unset_edid(struct intel_dp *intel_dp)
 {
-	struct intel_connector *intel_connector = intel_dp->attached_connector;
+	struct intel_connector *connector = intel_dp->attached_connector;
 
 	drm_dp_cec_unset_edid(&intel_dp->aux);
-	kfree(intel_connector->detect_edid);
-	intel_connector->detect_edid = NULL;
+	kfree(connector->detect_edid);
+	connector->detect_edid = NULL;
 
 	intel_dp->has_hdmi_sink = false;
 	intel_dp->has_audio = false;
@@ -6203,6 +6284,9 @@ intel_dp_unset_edid(struct intel_dp *intel_dp)
 	intel_dp->dfp.max_dotclock = 0;
 	intel_dp->dfp.min_tmds_clock = 0;
 	intel_dp->dfp.max_tmds_clock = 0;
+
+	intel_dp->dfp.ycbcr_444_to_420 = false;
+	connector->base.ycbcr_420_allowed = false;
 }
 
 static int
@@ -7726,9 +7810,6 @@ intel_dp_init_connector(struct intel_digital_port *dig_port,
 		connector->interlace_allowed = true;
 	connector->doublescan_allowed = 0;
 
-	if (INTEL_GEN(dev_priv) >= 11)
-		connector->ycbcr_420_allowed = true;
-
 	intel_encoder->hpd_pin = intel_hpd_pin_default(dev_priv, port);
 	intel_connector->polled = DRM_CONNECTOR_POLL_HPD;
 
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
index 929ae22b0a49..ef90607f1cd8 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -2278,7 +2278,7 @@ intel_hdmi_mode_valid(struct drm_connector *connector,
 }
 
 bool intel_hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
-				    int bpc, bool has_hdmi_sink)
+				    int bpc, bool has_hdmi_sink, bool ycbcr420_output)
 {
 	struct drm_atomic_state *state = crtc_state->uapi.state;
 	struct drm_connector_state *connector_state;
@@ -2297,7 +2297,7 @@ bool intel_hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
 		if (connector_state->crtc != crtc_state->uapi.crtc)
 			continue;
 
-		if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420) {
+		if (ycbcr420_output) {
 			const struct drm_hdmi_info *hdmi = &info->hdmi;
 
 			if (bpc == 12 && !(hdmi->y420_dc_modes &
@@ -2348,7 +2348,9 @@ static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
 		return false;
 
 	return intel_hdmi_deep_color_possible(crtc_state, bpc,
-					      crtc_state->has_hdmi_sink);
+					      crtc_state->has_hdmi_sink,
+					      crtc_state->output_format ==
+					      INTEL_OUTPUT_FORMAT_YCBCR420);
 }
 
 static int
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.h b/drivers/gpu/drm/i915/display/intel_hdmi.h
index c382930a992e..15eb0ccde76e 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.h
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.h
@@ -48,7 +48,7 @@ void intel_read_infoframe(struct intel_encoder *encoder,
 			  union hdmi_infoframe *frame);
 bool intel_hdmi_limited_color_range(const struct intel_crtc_state *crtc_state,
 				    const struct drm_connector_state *conn_state);
-bool intel_hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
-				    int bpc, bool has_hdmi_sink);
+bool intel_hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state, int bpc,
+				    bool has_hdmi_sink, bool ycbcr420_output);
 
 #endif /* __INTEL_HDMI_H__ */
-- 
2.26.2

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 76+ messages in thread

* [Intel-gfx] ✗ Fi.CI.SPARSE: warning for drm/i915: Pimp DP DFP handling (rev2)
  2020-09-04 11:53 ` [Intel-gfx] " Ville Syrjala
                   ` (18 preceding siblings ...)
  (?)
@ 2020-09-04 13:06 ` Patchwork
  -1 siblings, 0 replies; 76+ messages in thread
From: Patchwork @ 2020-09-04 13:06 UTC (permalink / raw)
  To: Ville Syrjala; +Cc: intel-gfx

== Series Details ==

Series: drm/i915: Pimp DP DFP handling (rev2)
URL   : https://patchwork.freedesktop.org/series/72928/
State : warning

== Summary ==

$ dim sparse --fast origin/drm-tip
Sparse version: v0.6.2
Fast mode used, each commit won't be checked separately.
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:1019:47:    expected unsigned int [addressable] [usertype] ulClockParams
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:1019:47:    got restricted __le32 [usertype]
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:1019:47: warning: incorrect type in assignment (different base types)
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:1028:50: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:1029:49: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:1037:47: warning: too many warnings
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:184:44: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:283:14: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:320:14: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:323:14: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:326:14: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:329:18: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:330:26: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:338:30: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:340:38: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:342:30: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:346:30: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:348:30: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:353:33: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:367:43: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:369:38: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:374:67: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:375:53: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:378:66: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:389:80: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:395:57: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:402:69: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:403:53: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:406:66: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:414:66: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:423:69: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:424:69: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:473:30: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:476:45: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:477:45: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:484:54: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:52:28: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:531:35: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:53:29: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:533:25: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:54:26: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:55:27: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:56:25: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:57:26: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:577:21: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:581:25: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:58:25: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:583:21: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:586:25: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:590:25: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:59:26: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:598:21: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:600:21: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:617:25: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:621:21: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:623:21: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:630:21: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:632:21: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:644:25: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:648:21: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:650:21: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:657:21: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:659:21: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:662:21: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:664:21: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:676:25: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:688:25: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:691:47: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:697:25: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:796:46: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:797:40: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:800:46: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:801:40: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:804:46: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:805:40: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:812:46: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:813:40: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:816:46: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:817:40: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:820:46: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:821:40: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:828:46: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:829:40: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:832:46: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:833:40: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:836:46: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:837:40: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:844:46: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:845:40: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:848:46: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:849:40: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:852:46: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:853:40: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:916:47: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:918:49: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:920:52: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:934:47: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:936:49: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:938:52: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:956:47: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:958:49: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c:960:52: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:328:34: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:365:34: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:395:25: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:397:25: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:404:25: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:418:40: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:441:40: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:44:21: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:482:53: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:486:33: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:489:61: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:490:64: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:492:54: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:518:17: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:521:21: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:64:25: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:80:17: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:80:17: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:80:17: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:85:30: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:86:24: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c:98:39: warning: cast to restricted __le16
+drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c:222:29: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c:226:37: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c:226:37: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c:226:37: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c:227:37: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c:233:43: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c:236:44: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c:239:51: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c:458:41: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c:458:41: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c:458:41: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c:464:39: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c:465:30: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c:466:39: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c:468:24: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c:140:26:    expected unsigned long long [usertype] *chunk_array_user
+drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c:140:26:    got void [noderef] __user *
+drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c:140:26: warning: incorrect type in assignment (different address spaces)
+drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c:141:41:    expected void const [noderef] __user *from
+drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c:141:41:    got unsigned long long [usertype] *chunk_array_user
+drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c:141:41: warning: incorrect type in argument 2 (different address spaces)
+drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c:160:27:    expected struct drm_amdgpu_cs_chunk [noderef] __user **chunk_ptr
+drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c:160:27:    got void [noderef] __user *
+drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c:160:27: warning: incorrect type in assignment (different address spaces)
+drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c:1613:21:    expected struct drm_amdgpu_fence *fences_user
+drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c:1613:21:    got void [noderef] __user *
+drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c:1613:21: warning: incorrect type in assignment (different address spaces)
+drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c:1614:36:    expected void const [noderef] __user *from
+drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c:1614:36:    got struct drm_amdgpu_fence *fences_user
+drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c:1614:36: warning: incorrect type in argument 2 (different address spaces)
+drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c:161:49:    expected void const [noderef] __user *from
+drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c:161:49:    got struct drm_amdgpu_cs_chunk [noderef] __user **chunk_ptr
+drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c:161:49: warning: incorrect type in argument 2 (different address spaces)
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:1357:25: error: incompatible types in comparison expression (different address spaces):
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:1357:25:    struct dma_fence *
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:1357:25:    struct dma_fence [noderef] __rcu *
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:1358:17: error: incompatible types in comparison expression (different address spaces):
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:1358:17:    struct dma_fence *
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:1358:17:    struct dma_fence [noderef] __rcu *
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:138:17:    expected restricted __poll_t ( *poll )( ... )
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:138:17:    got unsigned int ( * )( ... )
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:138:17: warning: incorrect type in initializer (different base types)
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:1417:17: error: incompatible types in comparison expression (different address spaces):
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:1417:17:    struct dma_fence *
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:1417:17:    struct dma_fence [noderef] __rcu *
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:261:29:    expected void const volatile [noderef] __user *
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:261:29:    got unsigned int [usertype] *
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:261:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:261:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:261:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:261:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:261:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:261:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:261:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:261:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:261:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:261:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:261:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:261:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:261:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:261:29: warning: incorrect type in argument 1 (different address spaces)
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:263:29:    expected void const volatile [noderef] __user *
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:263:29:    got unsigned int [usertype] *
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:263:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:263:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:263:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:263:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:263:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:263:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:263:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:263:29: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:263:29: warning: incorrect type in argument 1 (different address spaces)
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:354:21:    expected void const volatile [noderef] __user *
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:354:21:    got unsigned int [usertype] *
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:354:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:354:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:354:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:354:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:354:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:354:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:354:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:354:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:354:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:354:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:354:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:354:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:354:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:354:21: warning: incorrect type in argument 1 (different address spaces)
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:412:21:    expected void const volatile [noderef] __user *
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:412:21:    got unsigned int [usertype] *
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:412:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:412:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:412:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:412:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:412:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:412:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:412:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:412:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:412:21: warning: incorrect type in argument 1 (different address spaces)
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:473:21:    expected void const volatile [noderef] __user *
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:473:21:    got unsigned int [usertype] *
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:473:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:473:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:473:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:473:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:473:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:473:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:473:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:473:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:473:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:473:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:473:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:473:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:473:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:473:21: warning: incorrect type in argument 1 (different address spaces)
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:531:21:    expected void const volatile [noderef] __user *
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:531:21:    got unsigned int [usertype] *
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:531:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:531:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:531:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:531:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:531:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:531:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:531:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:531:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:531:21: warning: incorrect type in argument 1 (different address spaces)
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:592:21:    expected void const volatile [noderef] __user *
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:592:21:    got unsigned int [usertype] *
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:592:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:592:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:592:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:592:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:592:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:592:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:592:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:592:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:592:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:592:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:592:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:592:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:592:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:592:21: warning: incorrect type in argument 1 (different address spaces)
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:650:21:    expected void const volatile [noderef] __user *
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:650:21:    got unsigned int [usertype] *
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:650:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:650:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:650:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:650:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:650:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:650:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:650:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:650:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:650:21: warning: incorrect type in argument 1 (different address spaces)
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:747:21:    expected void const volatile [noderef] __user *
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:747:21:    got unsigned int [usertype] *
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:747:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:747:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:747:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:747:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:747:21: warning: cast removes address space '__user' of expression
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:747:21: warning: incorrect type in argument 1 (different address spaces)
+drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c:747:21: warning: too many warnings
+drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:1666:65: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:1674:55: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:1675:50: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:1676:50: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:1677:56: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:1679:25: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:1680:45: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:1681:51: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:1682:55: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:1683:57: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:1685:25: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:1686:53: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:1688:25: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:1690:25: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:1691:46: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:1695:73: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:1697:33: warning: cast to restricted __le32
+drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:1699:33: warning: cast to restricted __le32
+drivers/gpu/drm/amd/am


_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [Intel-gfx] ✓ Fi.CI.BAT: success for drm/i915: Pimp DP DFP handling (rev2)
  2020-09-04 11:53 ` [Intel-gfx] " Ville Syrjala
                   ` (19 preceding siblings ...)
  (?)
@ 2020-09-04 13:21 ` Patchwork
  -1 siblings, 0 replies; 76+ messages in thread
From: Patchwork @ 2020-09-04 13:21 UTC (permalink / raw)
  To: Ville Syrjala; +Cc: intel-gfx


[-- Attachment #1.1: Type: text/plain, Size: 5023 bytes --]

== Series Details ==

Series: drm/i915: Pimp DP DFP handling (rev2)
URL   : https://patchwork.freedesktop.org/series/72928/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_8965 -> Patchwork_18442
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18442/index.html

Known issues
------------

  Here are the changes found in Patchwork_18442 that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@i915_pm_rpm@basic-pci-d3-state:
    - fi-byt-j1900:       [PASS][1] -> [DMESG-WARN][2] ([i915#1982])
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_8965/fi-byt-j1900/igt@i915_pm_rpm@basic-pci-d3-state.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18442/fi-byt-j1900/igt@i915_pm_rpm@basic-pci-d3-state.html

  * igt@i915_selftest@live@execlists:
    - fi-icl-y:           [PASS][3] -> [INCOMPLETE][4] ([i915#2276])
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_8965/fi-icl-y/igt@i915_selftest@live@execlists.html
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18442/fi-icl-y/igt@i915_selftest@live@execlists.html

  * igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy:
    - fi-icl-u2:          [PASS][5] -> [DMESG-WARN][6] ([i915#1982])
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_8965/fi-icl-u2/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy.html
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18442/fi-icl-u2/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-legacy.html

  
#### Possible fixes ####

  * igt@kms_cursor_legacy@basic-busy-flip-before-cursor-atomic:
    - fi-byt-j1900:       [DMESG-WARN][7] ([i915#1982]) -> [PASS][8]
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_8965/fi-byt-j1900/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-atomic.html
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18442/fi-byt-j1900/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-atomic.html
    - {fi-kbl-7560u}:     [DMESG-WARN][9] ([i915#1982]) -> [PASS][10]
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_8965/fi-kbl-7560u/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-atomic.html
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18442/fi-kbl-7560u/igt@kms_cursor_legacy@basic-busy-flip-before-cursor-atomic.html

  
#### Warnings ####

  * igt@i915_pm_rpm@module-reload:
    - fi-kbl-guc:         [SKIP][11] ([fdo#109271]) -> [DMESG-WARN][12] ([i915#2203])
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_8965/fi-kbl-guc/igt@i915_pm_rpm@module-reload.html
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18442/fi-kbl-guc/igt@i915_pm_rpm@module-reload.html

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
  [i915#1982]: https://gitlab.freedesktop.org/drm/intel/issues/1982
  [i915#2203]: https://gitlab.freedesktop.org/drm/intel/issues/2203
  [i915#2276]: https://gitlab.freedesktop.org/drm/intel/issues/2276


Participating hosts (36 -> 33)
------------------------------

  Missing    (3): fi-byt-clapper fi-byt-squawks fi-bsw-cyan 


Build changes
-------------

  * Linux: CI_DRM_8965 -> Patchwork_18442

  CI-20190529: 20190529
  CI_DRM_8965: f4cbf17fababf80c1c67c6f1687fb8bf7e00a263 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_5778: 9a9db93fd2f2f59eb37b79d4b9a623067a945bac @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools
  Patchwork_18442: 6435daadb7ce482636a1fd2b57c02152f1aca6f1 @ git://anongit.freedesktop.org/gfx-ci/linux


== Linux commits ==

6435daadb7ce drm/i915: Do YCbCr 444->420 conversion via DP protocol converters
8b4dc01e472f drm/dp: Add helpers for DFP YCbCr 4:2:0 handling
c21132de3f0e drm/i915: DP->HDMI TMDS clock limits vs. deep color
a15752d9a614 drm/i915: Extract intel_hdmi_has_audio()
a59fad0f91e3 drm/i915: Handle downstream facing ports w/o EDID
45765ccce410 drm/dp: Add drm_dp_downstream_mode()
cb1f81c5536d drm/i915: Configure DP 1.3+ protocol converted HDMI mode
3dde5b00ff39 drm/i915: Deal with TMDS DFP clock limits
bad373543848 drm/dp: Add drm_dp_downstream_{min, max}_tmds_clock()
e11f279d7591 drm/i915: Reworkd DP DFP clock handling
ba465fed59f1 drm/dp: Redo drm_dp_downstream_max_clock() as drm_dp_downstream_max_dotclock()
ca3eb83d39a4 drm/dp: Pimp drm_dp_downstream_max_bpc()
f402b8c8847c drm/dp: Add helpers to identify downstream facing port types
0fd2901f3f3d drm/i915: Reworkd DFP max bpc handling
f98c09c9cf85 drm/dp: Define more downstream facing port caps
e495acd8f0f1 drm/dp: Define protocol converter DPCD registers
6a66200c3b95 drm/i915/lspcon: Do not send infoframes to non-HDMI sinks
42d7b45dcd52 drm/dp: Dump downstream facing port caps

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18442/index.html

[-- Attachment #1.2: Type: text/html, Size: 6078 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v2 00/18] drm/i915: Pimp DP DFP handling
  2020-09-04 11:53 ` [Intel-gfx] " Ville Syrjala
@ 2020-09-04 20:09   ` Lyude Paul
  -1 siblings, 0 replies; 76+ messages in thread
From: Lyude Paul @ 2020-09-04 20:09 UTC (permalink / raw)
  To: Ville Syrjala, dri-devel; +Cc: intel-gfx

Will try to look at this today, if I don't have the time though I'll definitely
have the time on Tuesday

On Fri, 2020-09-04 at 14:53 +0300, Ville Syrjala wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Attempt to deal with DP downstream facing ports (DFP) more
> thoroughly. This involves reading more of the port caps
> and dealing with various clock/bpc limitations.
> 
> And we try to enable YCbCr 444->420 conversion for HDMI DFPs
> which could allow some 4k displays to actually use 4k on
> pre-icl hardware (which doesn't have native 420 output),
> assuming we don't run into some other hardware limits.
> 
> I dropped my earlier patches to also hook in the DP dual mode
> adapter probing since sadly I've not actually seen a DP->DP++
> dongle that passes through the i2c traffic for those.
> 
> Only pimped the SST side of things. Not sure what would
> be required to get it all working for MST.
> 
> Ville Syrjälä (18):
>   drm/dp: Dump downstream facing port caps
>   drm/i915/lspcon: Do not send infoframes to non-HDMI sinks
>   drm/dp: Define protocol converter DPCD registers
>   drm/dp: Define more downstream facing port caps
>   drm/i915: Reworkd DFP max bpc handling
>   drm/dp: Add helpers to identify downstream facing port types
>   drm/dp: Pimp drm_dp_downstream_max_bpc()
>   drm/dp: Redo drm_dp_downstream_max_clock() as
>     drm_dp_downstream_max_dotclock()
>   drm/i915: Reworkd DP DFP clock handling
>   drm/dp: Add drm_dp_downstream_{min,max}_tmds_clock()
>   drm/i915: Deal with TMDS DFP clock limits
>   drm/i915: Configure DP 1.3+ protocol converted HDMI mode
>   drm/dp: Add drm_dp_downstream_mode()
>   drm/i915: Handle downstream facing ports w/o EDID
>   drm/i915: Extract intel_hdmi_has_audio()
>   drm/i915: DP->HDMI TMDS clock limits vs. deep color
>   drm/dp: Add helpers for DFP YCbCr 4:2:0 handling
>   drm/i915: Do YCbCr 444->420 conversion via DP protocol converters
> 
>  drivers/gpu/drm/drm_dp_helper.c               | 382 +++++++++++++++---
>  drivers/gpu/drm/drm_edid.c                    |  19 +
>  drivers/gpu/drm/i915/display/intel_ddi.c      |  11 +-
>  .../drm/i915/display/intel_display_debugfs.c  |   3 +-
>  .../drm/i915/display/intel_display_types.h    |   9 +
>  drivers/gpu/drm/i915/display/intel_dp.c       | 304 +++++++++++---
>  drivers/gpu/drm/i915/display/intel_dp.h       |   1 +
>  drivers/gpu/drm/i915/display/intel_hdmi.c     |  82 ++--
>  drivers/gpu/drm/i915/display/intel_hdmi.h     |   2 +
>  include/drm/drm_dp_helper.h                   |  63 ++-
>  include/drm/drm_edid.h                        |   4 +
>  11 files changed, 738 insertions(+), 142 deletions(-)
> 
-- 
Sincerely,
      Lyude Paul (she/her)
      Software Engineer at Red Hat

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Intel-gfx] [PATCH v2 00/18] drm/i915: Pimp DP DFP handling
@ 2020-09-04 20:09   ` Lyude Paul
  0 siblings, 0 replies; 76+ messages in thread
From: Lyude Paul @ 2020-09-04 20:09 UTC (permalink / raw)
  To: Ville Syrjala, dri-devel; +Cc: intel-gfx

Will try to look at this today, if I don't have the time though I'll definitely
have the time on Tuesday

On Fri, 2020-09-04 at 14:53 +0300, Ville Syrjala wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Attempt to deal with DP downstream facing ports (DFP) more
> thoroughly. This involves reading more of the port caps
> and dealing with various clock/bpc limitations.
> 
> And we try to enable YCbCr 444->420 conversion for HDMI DFPs
> which could allow some 4k displays to actually use 4k on
> pre-icl hardware (which doesn't have native 420 output),
> assuming we don't run into some other hardware limits.
> 
> I dropped my earlier patches to also hook in the DP dual mode
> adapter probing since sadly I've not actually seen a DP->DP++
> dongle that passes through the i2c traffic for those.
> 
> Only pimped the SST side of things. Not sure what would
> be required to get it all working for MST.
> 
> Ville Syrjälä (18):
>   drm/dp: Dump downstream facing port caps
>   drm/i915/lspcon: Do not send infoframes to non-HDMI sinks
>   drm/dp: Define protocol converter DPCD registers
>   drm/dp: Define more downstream facing port caps
>   drm/i915: Reworkd DFP max bpc handling
>   drm/dp: Add helpers to identify downstream facing port types
>   drm/dp: Pimp drm_dp_downstream_max_bpc()
>   drm/dp: Redo drm_dp_downstream_max_clock() as
>     drm_dp_downstream_max_dotclock()
>   drm/i915: Reworkd DP DFP clock handling
>   drm/dp: Add drm_dp_downstream_{min,max}_tmds_clock()
>   drm/i915: Deal with TMDS DFP clock limits
>   drm/i915: Configure DP 1.3+ protocol converted HDMI mode
>   drm/dp: Add drm_dp_downstream_mode()
>   drm/i915: Handle downstream facing ports w/o EDID
>   drm/i915: Extract intel_hdmi_has_audio()
>   drm/i915: DP->HDMI TMDS clock limits vs. deep color
>   drm/dp: Add helpers for DFP YCbCr 4:2:0 handling
>   drm/i915: Do YCbCr 444->420 conversion via DP protocol converters
> 
>  drivers/gpu/drm/drm_dp_helper.c               | 382 +++++++++++++++---
>  drivers/gpu/drm/drm_edid.c                    |  19 +
>  drivers/gpu/drm/i915/display/intel_ddi.c      |  11 +-
>  .../drm/i915/display/intel_display_debugfs.c  |   3 +-
>  .../drm/i915/display/intel_display_types.h    |   9 +
>  drivers/gpu/drm/i915/display/intel_dp.c       | 304 +++++++++++---
>  drivers/gpu/drm/i915/display/intel_dp.h       |   1 +
>  drivers/gpu/drm/i915/display/intel_hdmi.c     |  82 ++--
>  drivers/gpu/drm/i915/display/intel_hdmi.h     |   2 +
>  include/drm/drm_dp_helper.h                   |  63 ++-
>  include/drm/drm_edid.h                        |   4 +
>  11 files changed, 738 insertions(+), 142 deletions(-)
> 
-- 
Sincerely,
      Lyude Paul (she/her)
      Software Engineer at Red Hat

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* [Intel-gfx] ✗ Fi.CI.IGT: failure for drm/i915: Pimp DP DFP handling (rev2)
  2020-09-04 11:53 ` [Intel-gfx] " Ville Syrjala
                   ` (21 preceding siblings ...)
  (?)
@ 2020-09-04 21:32 ` Patchwork
  -1 siblings, 0 replies; 76+ messages in thread
From: Patchwork @ 2020-09-04 21:32 UTC (permalink / raw)
  To: Ville Syrjala; +Cc: intel-gfx


[-- Attachment #1.1: Type: text/plain, Size: 12632 bytes --]

== Series Details ==

Series: drm/i915: Pimp DP DFP handling (rev2)
URL   : https://patchwork.freedesktop.org/series/72928/
State : failure

== Summary ==

CI Bug Log - changes from CI_DRM_8965_full -> Patchwork_18442_full
====================================================

Summary
-------

  **FAILURE**

  Serious unknown changes coming with Patchwork_18442_full absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in Patchwork_18442_full, please notify your bug team to allow them
  to document this new failure mode, which will reduce false positives in CI.

  

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in Patchwork_18442_full:

### IGT changes ###

#### Possible regressions ####

  * igt@kms_flip@absolute-wf_vblank@c-dp1:
    - shard-kbl:          [PASS][1] -> [INCOMPLETE][2]
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_8965/shard-kbl7/igt@kms_flip@absolute-wf_vblank@c-dp1.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18442/shard-kbl7/igt@kms_flip@absolute-wf_vblank@c-dp1.html

  
Known issues
------------

  Here are the changes found in Patchwork_18442_full that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@gem_exec_params@invalid-fence-in-submit:
    - shard-apl:          [PASS][3] -> [DMESG-WARN][4] ([i915#1635] / [i915#1982])
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_8965/shard-apl3/igt@gem_exec_params@invalid-fence-in-submit.html
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18442/shard-apl6/igt@gem_exec_params@invalid-fence-in-submit.html

  * igt@gem_exec_whisper@basic-contexts-forked-all:
    - shard-glk:          [PASS][5] -> [DMESG-WARN][6] ([i915#118] / [i915#95])
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_8965/shard-glk8/igt@gem_exec_whisper@basic-contexts-forked-all.html
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18442/shard-glk2/igt@gem_exec_whisper@basic-contexts-forked-all.html

  * igt@gem_workarounds@suspend-resume-fd:
    - shard-skl:          [PASS][7] -> [INCOMPLETE][8] ([i915#198]) +1 similar issue
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_8965/shard-skl5/igt@gem_workarounds@suspend-resume-fd.html
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18442/shard-skl10/igt@gem_workarounds@suspend-resume-fd.html

  * igt@i915_suspend@forcewake:
    - shard-skl:          [PASS][9] -> [INCOMPLETE][10] ([i915#636])
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_8965/shard-skl2/igt@i915_suspend@forcewake.html
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18442/shard-skl5/igt@i915_suspend@forcewake.html

  * igt@kms_cursor_legacy@2x-long-flip-vs-cursor-atomic:
    - shard-glk:          [PASS][11] -> [FAIL][12] ([i915#72])
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_8965/shard-glk9/igt@kms_cursor_legacy@2x-long-flip-vs-cursor-atomic.html
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18442/shard-glk9/igt@kms_cursor_legacy@2x-long-flip-vs-cursor-atomic.html

  * igt@kms_flip@basic-plain-flip@a-edp1:
    - shard-skl:          [PASS][13] -> [DMESG-WARN][14] ([i915#1982]) +12 similar issues
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_8965/shard-skl2/igt@kms_flip@basic-plain-flip@a-edp1.html
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18442/shard-skl3/igt@kms_flip@basic-plain-flip@a-edp1.html

  * igt@kms_frontbuffer_tracking@fbcpsr-1p-primscrn-indfb-msflip-blt:
    - shard-tglb:         [PASS][15] -> [DMESG-WARN][16] ([i915#1982])
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_8965/shard-tglb8/igt@kms_frontbuffer_tracking@fbcpsr-1p-primscrn-indfb-msflip-blt.html
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18442/shard-tglb8/igt@kms_frontbuffer_tracking@fbcpsr-1p-primscrn-indfb-msflip-blt.html

  * igt@kms_hdr@bpc-switch-suspend:
    - shard-skl:          [PASS][17] -> [FAIL][18] ([i915#1188])
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_8965/shard-skl1/igt@kms_hdr@bpc-switch-suspend.html
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18442/shard-skl1/igt@kms_hdr@bpc-switch-suspend.html

  * igt@kms_plane@plane-panning-bottom-right-suspend-pipe-c-planes:
    - shard-kbl:          [PASS][19] -> [DMESG-WARN][20] ([i915#180])
   [19]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_8965/shard-kbl4/igt@kms_plane@plane-panning-bottom-right-suspend-pipe-c-planes.html
   [20]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18442/shard-kbl4/igt@kms_plane@plane-panning-bottom-right-suspend-pipe-c-planes.html

  * igt@kms_plane_alpha_blend@pipe-c-constant-alpha-min:
    - shard-skl:          [PASS][21] -> [FAIL][22] ([fdo#108145] / [i915#265]) +1 similar issue
   [21]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_8965/shard-skl1/igt@kms_plane_alpha_blend@pipe-c-constant-alpha-min.html
   [22]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18442/shard-skl1/igt@kms_plane_alpha_blend@pipe-c-constant-alpha-min.html

  * igt@kms_psr@psr2_dpms:
    - shard-iclb:         [PASS][23] -> [SKIP][24] ([fdo#109441]) +2 similar issues
   [23]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_8965/shard-iclb2/igt@kms_psr@psr2_dpms.html
   [24]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18442/shard-iclb8/igt@kms_psr@psr2_dpms.html

  * igt@kms_setmode@basic:
    - shard-apl:          [PASS][25] -> [FAIL][26] ([i915#1635] / [i915#31])
   [25]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_8965/shard-apl2/igt@kms_setmode@basic.html
   [26]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18442/shard-apl3/igt@kms_setmode@basic.html

  
#### Possible fixes ####

  * igt@gem_exec_reloc@basic-many-active@vecs0:
    - shard-glk:          [FAIL][27] ([i915#2389]) -> [PASS][28]
   [27]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_8965/shard-glk7/igt@gem_exec_reloc@basic-many-active@vecs0.html
   [28]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18442/shard-glk6/igt@gem_exec_reloc@basic-many-active@vecs0.html

  * igt@gem_partial_pwrite_pread@reads-uncached:
    - shard-glk:          [FAIL][29] ([i915#2261]) -> [PASS][30]
   [29]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_8965/shard-glk7/igt@gem_partial_pwrite_pread@reads-uncached.html
   [30]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18442/shard-glk5/igt@gem_partial_pwrite_pread@reads-uncached.html

  * igt@gem_userptr_blits@unsync-unmap-cycles:
    - shard-skl:          [TIMEOUT][31] ([i915#1958]) -> [PASS][32]
   [31]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_8965/shard-skl7/igt@gem_userptr_blits@unsync-unmap-cycles.html
   [32]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18442/shard-skl3/igt@gem_userptr_blits@unsync-unmap-cycles.html

  * igt@gen9_exec_parse@allowed-single:
    - shard-skl:          [DMESG-WARN][33] ([i915#1436] / [i915#716]) -> [PASS][34]
   [33]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_8965/shard-skl3/igt@gen9_exec_parse@allowed-single.html
   [34]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18442/shard-skl10/igt@gen9_exec_parse@allowed-single.html

  * igt@i915_module_load@reload-with-fault-injection:
    - shard-kbl:          [INCOMPLETE][35] ([i915#1373] / [i915#726]) -> [PASS][36]
   [35]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_8965/shard-kbl4/igt@i915_module_load@reload-with-fault-injection.html
   [36]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18442/shard-kbl1/igt@i915_module_load@reload-with-fault-injection.html

  * igt@kms_flip@2x-plain-flip-fb-recreate-interruptible@ab-hdmi-a1-hdmi-a2:
    - shard-glk:          [FAIL][37] ([i915#2122]) -> [PASS][38]
   [37]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_8965/shard-glk8/igt@kms_flip@2x-plain-flip-fb-recreate-interruptible@ab-hdmi-a1-hdmi-a2.html
   [38]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18442/shard-glk3/igt@kms_flip@2x-plain-flip-fb-recreate-interruptible@ab-hdmi-a1-hdmi-a2.html

  * igt@kms_flip@flip-vs-suspend-interruptible@a-dp1:
    - shard-kbl:          [DMESG-WARN][39] ([i915#180]) -> [PASS][40] +5 similar issues
   [39]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_8965/shard-kbl7/igt@kms_flip@flip-vs-suspend-interruptible@a-dp1.html
   [40]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18442/shard-kbl1/igt@kms_flip@flip-vs-suspend-interruptible@a-dp1.html

  * igt@kms_frontbuffer_tracking@fbc-1p-shrfb-fliptrack:
    - shard-iclb:         [DMESG-WARN][41] ([i915#1982]) -> [PASS][42]
   [41]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_8965/shard-iclb3/igt@kms_frontbuffer_tracking@fbc-1p-shrfb-fliptrack.html
   [42]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18442/shard-iclb6/igt@kms_frontbuffer_tracking@fbc-1p-shrfb-fliptrack.html

  * igt@kms_plane@plane-position-hole-pipe-a-planes:
    - shard-skl:          [DMESG-WARN][43] ([i915#1982]) -> [PASS][44] +1 similar issue
   [43]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_8965/shard-skl4/igt@kms_plane@plane-position-hole-pipe-a-planes.html
   [44]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18442/shard-skl4/igt@kms_plane@plane-position-hole-pipe-a-planes.html

  * igt@kms_plane_alpha_blend@pipe-a-constant-alpha-min:
    - shard-skl:          [FAIL][45] ([fdo#108145] / [i915#265]) -> [PASS][46]
   [45]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_8965/shard-skl2/igt@kms_plane_alpha_blend@pipe-a-constant-alpha-min.html
   [46]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18442/shard-skl6/igt@kms_plane_alpha_blend@pipe-a-constant-alpha-min.html

  * igt@kms_psr@psr2_sprite_plane_move:
    - shard-iclb:         [SKIP][47] ([fdo#109441]) -> [PASS][48] +4 similar issues
   [47]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_8965/shard-iclb1/igt@kms_psr@psr2_sprite_plane_move.html
   [48]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18442/shard-iclb2/igt@kms_psr@psr2_sprite_plane_move.html

  
#### Warnings ####

  * igt@i915_pm_dc@dc3co-vpb-simulation:
    - shard-iclb:         [SKIP][49] ([i915#658]) -> [SKIP][50] ([i915#588])
   [49]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_8965/shard-iclb1/igt@i915_pm_dc@dc3co-vpb-simulation.html
   [50]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18442/shard-iclb2/igt@i915_pm_dc@dc3co-vpb-simulation.html

  
  [fdo#108145]: https://bugs.freedesktop.org/show_bug.cgi?id=108145
  [fdo#109441]: https://bugs.freedesktop.org/show_bug.cgi?id=109441
  [i915#118]: https://gitlab.freedesktop.org/drm/intel/issues/118
  [i915#1188]: https://gitlab.freedesktop.org/drm/intel/issues/1188
  [i915#1373]: https://gitlab.freedesktop.org/drm/intel/issues/1373
  [i915#1436]: https://gitlab.freedesktop.org/drm/intel/issues/1436
  [i915#1635]: https://gitlab.freedesktop.org/drm/intel/issues/1635
  [i915#180]: https://gitlab.freedesktop.org/drm/intel/issues/180
  [i915#1958]: https://gitlab.freedesktop.org/drm/intel/issues/1958
  [i915#198]: https://gitlab.freedesktop.org/drm/intel/issues/198
  [i915#1982]: https://gitlab.freedesktop.org/drm/intel/issues/1982
  [i915#2122]: https://gitlab.freedesktop.org/drm/intel/issues/2122
  [i915#2261]: https://gitlab.freedesktop.org/drm/intel/issues/2261
  [i915#2389]: https://gitlab.freedesktop.org/drm/intel/issues/2389
  [i915#265]: https://gitlab.freedesktop.org/drm/intel/issues/265
  [i915#31]: https://gitlab.freedesktop.org/drm/intel/issues/31
  [i915#588]: https://gitlab.freedesktop.org/drm/intel/issues/588
  [i915#636]: https://gitlab.freedesktop.org/drm/intel/issues/636
  [i915#658]: https://gitlab.freedesktop.org/drm/intel/issues/658
  [i915#716]: https://gitlab.freedesktop.org/drm/intel/issues/716
  [i915#72]: https://gitlab.freedesktop.org/drm/intel/issues/72
  [i915#726]: https://gitlab.freedesktop.org/drm/intel/issues/726
  [i915#95]: https://gitlab.freedesktop.org/drm/intel/issues/95


Participating hosts (10 -> 10)
------------------------------

  No changes in participating hosts


Build changes
-------------

  * Linux: CI_DRM_8965 -> Patchwork_18442

  CI-20190529: 20190529
  CI_DRM_8965: f4cbf17fababf80c1c67c6f1687fb8bf7e00a263 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_5778: 9a9db93fd2f2f59eb37b79d4b9a623067a945bac @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools
  Patchwork_18442: 6435daadb7ce482636a1fd2b57c02152f1aca6f1 @ git://anongit.freedesktop.org/gfx-ci/linux
  piglit_4509: fdc5a4ca11124ab8413c7988896eec4c97336694 @ git://anongit.freedesktop.org/piglit

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_18442/index.html

[-- Attachment #1.2: Type: text/html, Size: 14446 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v2 06/18] drm/dp: Add helpers to identify downstream facing port types
  2020-09-04 11:53   ` [Intel-gfx] " Ville Syrjala
@ 2020-09-08 17:30     ` Lyude Paul
  -1 siblings, 0 replies; 76+ messages in thread
From: Lyude Paul @ 2020-09-08 17:30 UTC (permalink / raw)
  To: Ville Syrjala, dri-devel; +Cc: intel-gfx

On Fri, 2020-09-04 at 14:53 +0300, Ville Syrjala wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Add a few helpers to let us better identify which kind of DFP
> we're dealing with.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/drm_dp_helper.c | 60 +++++++++++++++++++++++++++++++++
>  include/drm/drm_dp_helper.h     |  5 +++
>  2 files changed, 65 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_dp_helper.c
> b/drivers/gpu/drm/drm_dp_helper.c
> index c21bbfc3d714..0fcb94f7dbe5 100644
> --- a/drivers/gpu/drm/drm_dp_helper.c
> +++ b/drivers/gpu/drm/drm_dp_helper.c
> @@ -363,6 +363,66 @@ int drm_dp_dpcd_read_link_status(struct drm_dp_aux
> *aux,
>  }
>  EXPORT_SYMBOL(drm_dp_dpcd_read_link_status);
>  
> +static bool is_edid_digital_input_dp(const struct edid *edid)
> +{
> +	return edid && edid->revision >= 4 &&
> +		edid->input & DRM_EDID_INPUT_DIGITAL &&
> +		(edid->input & DRM_EDID_DIGITAL_TYPE_MASK) ==
> DRM_EDID_DIGITAL_TYPE_DP;
> +}
> +
> +/**
> + * drm_dp_downstream_is_type() - is the downstream facing port of certain
> type?
> + * @dpcd: DisplayPort configuration data
> + * @port_cap: port capabilities
> + *
> + * Caveat: Only works with DPCD 1.1+ port caps.
> + *
> + * Returns whether the downstream facing port matches the type.

Nitpick: s/Returns/Returns:/ for kdoc purposes

> + */
> +bool drm_dp_downstream_is_type(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> +			       const u8 port_cap[4], u8 type)
> +{
> +	return drm_dp_is_branch(dpcd) &&
> +		dpcd[DP_DPCD_REV] >= 0x11 &&
> +		(port_cap[0] & DP_DS_PORT_TYPE_MASK) == type;
> +}
> +EXPORT_SYMBOL(drm_dp_downstream_is_type);
> +
> +/**
> + * drm_dp_downstream_is_tmds() - is the downstream facing port TMDS?
> + * @dpcd: DisplayPort configuration data
> + * @port_cap: port capabilities
> + * @edid: EDID
> + *
> + * Returns whether the downstream facing port is TMDS (HDMI/DVI).

Same nitpick here

> + */
> +bool drm_dp_downstream_is_tmds(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> +			       const u8 port_cap[4],
> +			       const struct edid *edid)
> +{
> +	if (dpcd[DP_DPCD_REV] < 0x11) {
> +		switch (dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> DP_DWN_STRM_PORT_TYPE_MASK) {
> +		case DP_DWN_STRM_PORT_TYPE_TMDS:
> +			return true;
> +		default:
> +			return false;
> +		}
> +	}
> +
> +	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
> +	case DP_DS_PORT_TYPE_DP_DUALMODE:
> +		if (is_edid_digital_input_dp(edid))
> +			return false;
> +		fallthrough;
> +	case DP_DS_PORT_TYPE_DVI:
> +	case DP_DS_PORT_TYPE_HDMI:
> +		return true;
> +	default:
> +		return false;
> +	}
> +}
> +EXPORT_SYMBOL(drm_dp_downstream_is_tmds);
> +
>  /**
>   * drm_dp_send_real_edid_checksum() - send back real edid checksum value
>   * @aux: DisplayPort AUX channel
> diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
> index 86461a40066b..4f946826dfce 100644
> --- a/include/drm/drm_dp_helper.h
> +++ b/include/drm/drm_dp_helper.h
> @@ -1638,6 +1638,11 @@ bool drm_dp_send_real_edid_checksum(struct drm_dp_aux
> *aux,
>  int drm_dp_read_downstream_info(struct drm_dp_aux *aux,
>  				const u8 dpcd[DP_RECEIVER_CAP_SIZE],
>  				u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS]);
> +bool drm_dp_downstream_is_type(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> +			       const u8 port_cap[4], u8 type);
> +bool drm_dp_downstream_is_tmds(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> +			       const u8 port_cap[4],
> +			       const struct edid *edid);
>  int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
>  				const u8 port_cap[4]);
>  int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
-- 
Cheers,
	Lyude Paul (she/her)
	Software Engineer at Red Hat

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Intel-gfx] [PATCH v2 06/18] drm/dp: Add helpers to identify downstream facing port types
@ 2020-09-08 17:30     ` Lyude Paul
  0 siblings, 0 replies; 76+ messages in thread
From: Lyude Paul @ 2020-09-08 17:30 UTC (permalink / raw)
  To: Ville Syrjala, dri-devel; +Cc: intel-gfx

On Fri, 2020-09-04 at 14:53 +0300, Ville Syrjala wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Add a few helpers to let us better identify which kind of DFP
> we're dealing with.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/drm_dp_helper.c | 60 +++++++++++++++++++++++++++++++++
>  include/drm/drm_dp_helper.h     |  5 +++
>  2 files changed, 65 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_dp_helper.c
> b/drivers/gpu/drm/drm_dp_helper.c
> index c21bbfc3d714..0fcb94f7dbe5 100644
> --- a/drivers/gpu/drm/drm_dp_helper.c
> +++ b/drivers/gpu/drm/drm_dp_helper.c
> @@ -363,6 +363,66 @@ int drm_dp_dpcd_read_link_status(struct drm_dp_aux
> *aux,
>  }
>  EXPORT_SYMBOL(drm_dp_dpcd_read_link_status);
>  
> +static bool is_edid_digital_input_dp(const struct edid *edid)
> +{
> +	return edid && edid->revision >= 4 &&
> +		edid->input & DRM_EDID_INPUT_DIGITAL &&
> +		(edid->input & DRM_EDID_DIGITAL_TYPE_MASK) ==
> DRM_EDID_DIGITAL_TYPE_DP;
> +}
> +
> +/**
> + * drm_dp_downstream_is_type() - is the downstream facing port of certain
> type?
> + * @dpcd: DisplayPort configuration data
> + * @port_cap: port capabilities
> + *
> + * Caveat: Only works with DPCD 1.1+ port caps.
> + *
> + * Returns whether the downstream facing port matches the type.

Nitpick: s/Returns/Returns:/ for kdoc purposes

> + */
> +bool drm_dp_downstream_is_type(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> +			       const u8 port_cap[4], u8 type)
> +{
> +	return drm_dp_is_branch(dpcd) &&
> +		dpcd[DP_DPCD_REV] >= 0x11 &&
> +		(port_cap[0] & DP_DS_PORT_TYPE_MASK) == type;
> +}
> +EXPORT_SYMBOL(drm_dp_downstream_is_type);
> +
> +/**
> + * drm_dp_downstream_is_tmds() - is the downstream facing port TMDS?
> + * @dpcd: DisplayPort configuration data
> + * @port_cap: port capabilities
> + * @edid: EDID
> + *
> + * Returns whether the downstream facing port is TMDS (HDMI/DVI).

Same nitpick here

> + */
> +bool drm_dp_downstream_is_tmds(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> +			       const u8 port_cap[4],
> +			       const struct edid *edid)
> +{
> +	if (dpcd[DP_DPCD_REV] < 0x11) {
> +		switch (dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> DP_DWN_STRM_PORT_TYPE_MASK) {
> +		case DP_DWN_STRM_PORT_TYPE_TMDS:
> +			return true;
> +		default:
> +			return false;
> +		}
> +	}
> +
> +	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
> +	case DP_DS_PORT_TYPE_DP_DUALMODE:
> +		if (is_edid_digital_input_dp(edid))
> +			return false;
> +		fallthrough;
> +	case DP_DS_PORT_TYPE_DVI:
> +	case DP_DS_PORT_TYPE_HDMI:
> +		return true;
> +	default:
> +		return false;
> +	}
> +}
> +EXPORT_SYMBOL(drm_dp_downstream_is_tmds);
> +
>  /**
>   * drm_dp_send_real_edid_checksum() - send back real edid checksum value
>   * @aux: DisplayPort AUX channel
> diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
> index 86461a40066b..4f946826dfce 100644
> --- a/include/drm/drm_dp_helper.h
> +++ b/include/drm/drm_dp_helper.h
> @@ -1638,6 +1638,11 @@ bool drm_dp_send_real_edid_checksum(struct drm_dp_aux
> *aux,
>  int drm_dp_read_downstream_info(struct drm_dp_aux *aux,
>  				const u8 dpcd[DP_RECEIVER_CAP_SIZE],
>  				u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS]);
> +bool drm_dp_downstream_is_type(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> +			       const u8 port_cap[4], u8 type);
> +bool drm_dp_downstream_is_tmds(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> +			       const u8 port_cap[4],
> +			       const struct edid *edid);
>  int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
>  				const u8 port_cap[4]);
>  int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
-- 
Cheers,
	Lyude Paul (she/her)
	Software Engineer at Red Hat

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v2 07/18] drm/dp: Pimp drm_dp_downstream_max_bpc()
  2020-09-04 11:53   ` [Intel-gfx] " Ville Syrjala
@ 2020-09-08 17:32     ` Lyude Paul
  -1 siblings, 0 replies; 76+ messages in thread
From: Lyude Paul @ 2020-09-08 17:32 UTC (permalink / raw)
  To: Ville Syrjala, dri-devel; +Cc: intel-gfx

On Fri, 2020-09-04 at 14:53 +0300, Ville Syrjala wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Deal with more cases in drm_dp_downstream_max_bpc():
> - DPCD 1.0 -> assume 8bpc for non-DP
> - DPCD 1.1+ DP (or DP++ with DP sink) -> allow anything
> - DPCD 1.1+ TMDS -> check the caps, assume 8bpc if the value is crap
> - anything else -> assume 8bpc
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/drm_dp_helper.c               | 69 +++++++++++--------
>  .../drm/i915/display/intel_display_debugfs.c  |  3 +-
>  drivers/gpu/drm/i915/display/intel_dp.c       |  2 +-
>  include/drm/drm_dp_helper.h                   | 10 ++-
>  4 files changed, 51 insertions(+), 33 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_dp_helper.c
> b/drivers/gpu/drm/drm_dp_helper.c
> index 0fcb94f7dbe5..ab87209c25d8 100644
> --- a/drivers/gpu/drm/drm_dp_helper.c
> +++ b/drivers/gpu/drm/drm_dp_helper.c
> @@ -653,36 +653,44 @@ int drm_dp_downstream_max_clock(const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
>  EXPORT_SYMBOL(drm_dp_downstream_max_clock);
>  
>  /**
> - * drm_dp_downstream_max_bpc() - extract branch device max
> - *                               bits per component
> - * @dpcd: DisplayPort configuration data
> - * @port_cap: port capabilities
> - *
> - * See also:
> - * drm_dp_read_downstream_info()
> - * drm_dp_downstream_max_clock()
> - *
> - * Returns: Max bpc on success or 0 if max bpc not defined
> - */
> +  * drm_dp_downstream_max_bpc() - extract downstream facing port max
> +  *                               bits per component
> +  * @dpcd: DisplayPort configuration data
> +  * @port_cap: downstream facing port capabilities
> +  * @edid: EDID
> +  *
> +  * Returns max bpc on success or 0 if max bpc not defined

s/Returns/Returns:/

> +  */
>  int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> -			      const u8 port_cap[4])
> +			      const u8 port_cap[4],
> +			      const struct edid *edid)
>  {
> -	int type = port_cap[0] & DP_DS_PORT_TYPE_MASK;
> -	bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> -		DP_DETAILED_CAP_INFO_AVAILABLE;
> -	int bpc;
> -
> -	if (!detailed_cap_info)
> +	if (!drm_dp_is_branch(dpcd))
>  		return 0;
>  
> -	switch (type) {
> -	case DP_DS_PORT_TYPE_VGA:
> -	case DP_DS_PORT_TYPE_DVI:
> -	case DP_DS_PORT_TYPE_HDMI:
> +	if (dpcd[DP_DPCD_REV] < 0x11) {
> +		switch (dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> DP_DWN_STRM_PORT_TYPE_MASK) {
> +		case DP_DWN_STRM_PORT_TYPE_DP:
> +			return 0;
> +		default:
> +			return 8;
> +		}
> +	}
> +
> +	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
> +	case DP_DS_PORT_TYPE_DP:
> +		return 0;
>  	case DP_DS_PORT_TYPE_DP_DUALMODE:
> -		bpc = port_cap[2] & DP_DS_MAX_BPC_MASK;
> +		if (is_edid_digital_input_dp(edid))
> +			return 0;
> +		fallthrough;
> +	case DP_DS_PORT_TYPE_HDMI:
> +	case DP_DS_PORT_TYPE_DVI:
> +	case DP_DS_PORT_TYPE_VGA:
> +		if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
> +			return 8;
>  
> -		switch (bpc) {
> +		switch (port_cap[2] & DP_DS_MAX_BPC_MASK) {
>  		case DP_DS_8BPC:
>  			return 8;
>  		case DP_DS_10BPC:
> @@ -691,10 +699,12 @@ int drm_dp_downstream_max_bpc(const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
>  			return 12;
>  		case DP_DS_16BPC:
>  			return 16;
> +		default:
> +			return 8;
>  		}
> -		fallthrough;
> +		break;
>  	default:
> -		return 0;
> +		return 8;
>  	}
>  }
>  EXPORT_SYMBOL(drm_dp_downstream_max_bpc);
> @@ -717,12 +727,15 @@ EXPORT_SYMBOL(drm_dp_downstream_id);
>   * @m: pointer for debugfs file
>   * @dpcd: DisplayPort configuration data
>   * @port_cap: port capabilities
> + * @edid: EDID
>   * @aux: DisplayPort AUX channel
>   *
>   */
>  void drm_dp_downstream_debug(struct seq_file *m,
>  			     const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> -			     const u8 port_cap[4], struct drm_dp_aux *aux)
> +			     const u8 port_cap[4],
> +			     const struct edid *edid,
> +			     struct drm_dp_aux *aux)
>  {
>  	bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] &
>  				 DP_DETAILED_CAP_INFO_AVAILABLE;
> @@ -789,7 +802,7 @@ void drm_dp_downstream_debug(struct seq_file *m,
>  				seq_printf(m, "\t\tMax TMDS clock: %d kHz\n",
> clk);
>  		}
>  
> -		bpc = drm_dp_downstream_max_bpc(dpcd, port_cap);
> +		bpc = drm_dp_downstream_max_bpc(dpcd, port_cap, edid);
>  
>  		if (bpc > 0)
>  			seq_printf(m, "\t\tMax bpc: %d\n", bpc);
> diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> index 53a0a3d9a22d..0bf31f9a8af5 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> @@ -626,6 +626,7 @@ static void intel_dp_info(struct seq_file *m,
>  {
>  	struct intel_encoder *intel_encoder =
> intel_attached_encoder(intel_connector);
>  	struct intel_dp *intel_dp = enc_to_intel_dp(intel_encoder);
> +	const struct drm_property_blob *edid = intel_connector-
> >base.edid_blob_ptr;
>  
>  	seq_printf(m, "\tDPCD rev: %x\n", intel_dp->dpcd[DP_DPCD_REV]);
>  	seq_printf(m, "\taudio support: %s\n", yesno(intel_dp->has_audio));
> @@ -633,7 +634,7 @@ static void intel_dp_info(struct seq_file *m,
>  		intel_panel_info(m, &intel_connector->panel);
>  
>  	drm_dp_downstream_debug(m, intel_dp->dpcd, intel_dp->downstream_ports,
> -				&intel_dp->aux);
> +				edid ? edid->data : NULL, &intel_dp->aux);
>  }
>  
>  static void intel_dp_mst_info(struct seq_file *m,
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c
> b/drivers/gpu/drm/i915/display/intel_dp.c
> index 2c8e82d97a34..c73b3efd84e0 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -6071,7 +6071,7 @@ intel_dp_set_edid(struct intel_dp *intel_dp)
>  
>  	intel_dp->dfp.max_bpc =
>  		drm_dp_downstream_max_bpc(intel_dp->dpcd,
> -					  intel_dp->downstream_ports);
> +					  intel_dp->downstream_ports, edid);
>  
>  	drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] DFP max bpc %d\n",
>  		    connector->base.base.id, connector->base.name,
> diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
> index 4f946826dfce..6218de1294c1 100644
> --- a/include/drm/drm_dp_helper.h
> +++ b/include/drm/drm_dp_helper.h
> @@ -1646,10 +1646,14 @@ bool drm_dp_downstream_is_tmds(const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
>  int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
>  				const u8 port_cap[4]);
>  int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> -			      const u8 port_cap[4]);
> +			      const u8 port_cap[4],
> +			      const struct edid *edid);
>  int drm_dp_downstream_id(struct drm_dp_aux *aux, char id[6]);
> -void drm_dp_downstream_debug(struct seq_file *m, const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
> -			     const u8 port_cap[4], struct drm_dp_aux *aux);
> +void drm_dp_downstream_debug(struct seq_file *m,
> +			     const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> +			     const u8 port_cap[4],
> +			     const struct edid *edid,
> +			     struct drm_dp_aux *aux);
>  enum drm_mode_subconnector
>  drm_dp_subconnector_type(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
>  			 const u8 port_cap[4]);
-- 
Cheers,
	Lyude Paul (she/her)
	Software Engineer at Red Hat

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Intel-gfx] [PATCH v2 07/18] drm/dp: Pimp drm_dp_downstream_max_bpc()
@ 2020-09-08 17:32     ` Lyude Paul
  0 siblings, 0 replies; 76+ messages in thread
From: Lyude Paul @ 2020-09-08 17:32 UTC (permalink / raw)
  To: Ville Syrjala, dri-devel; +Cc: intel-gfx

On Fri, 2020-09-04 at 14:53 +0300, Ville Syrjala wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Deal with more cases in drm_dp_downstream_max_bpc():
> - DPCD 1.0 -> assume 8bpc for non-DP
> - DPCD 1.1+ DP (or DP++ with DP sink) -> allow anything
> - DPCD 1.1+ TMDS -> check the caps, assume 8bpc if the value is crap
> - anything else -> assume 8bpc
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/drm_dp_helper.c               | 69 +++++++++++--------
>  .../drm/i915/display/intel_display_debugfs.c  |  3 +-
>  drivers/gpu/drm/i915/display/intel_dp.c       |  2 +-
>  include/drm/drm_dp_helper.h                   | 10 ++-
>  4 files changed, 51 insertions(+), 33 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_dp_helper.c
> b/drivers/gpu/drm/drm_dp_helper.c
> index 0fcb94f7dbe5..ab87209c25d8 100644
> --- a/drivers/gpu/drm/drm_dp_helper.c
> +++ b/drivers/gpu/drm/drm_dp_helper.c
> @@ -653,36 +653,44 @@ int drm_dp_downstream_max_clock(const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
>  EXPORT_SYMBOL(drm_dp_downstream_max_clock);
>  
>  /**
> - * drm_dp_downstream_max_bpc() - extract branch device max
> - *                               bits per component
> - * @dpcd: DisplayPort configuration data
> - * @port_cap: port capabilities
> - *
> - * See also:
> - * drm_dp_read_downstream_info()
> - * drm_dp_downstream_max_clock()
> - *
> - * Returns: Max bpc on success or 0 if max bpc not defined
> - */
> +  * drm_dp_downstream_max_bpc() - extract downstream facing port max
> +  *                               bits per component
> +  * @dpcd: DisplayPort configuration data
> +  * @port_cap: downstream facing port capabilities
> +  * @edid: EDID
> +  *
> +  * Returns max bpc on success or 0 if max bpc not defined

s/Returns/Returns:/

> +  */
>  int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> -			      const u8 port_cap[4])
> +			      const u8 port_cap[4],
> +			      const struct edid *edid)
>  {
> -	int type = port_cap[0] & DP_DS_PORT_TYPE_MASK;
> -	bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> -		DP_DETAILED_CAP_INFO_AVAILABLE;
> -	int bpc;
> -
> -	if (!detailed_cap_info)
> +	if (!drm_dp_is_branch(dpcd))
>  		return 0;
>  
> -	switch (type) {
> -	case DP_DS_PORT_TYPE_VGA:
> -	case DP_DS_PORT_TYPE_DVI:
> -	case DP_DS_PORT_TYPE_HDMI:
> +	if (dpcd[DP_DPCD_REV] < 0x11) {
> +		switch (dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> DP_DWN_STRM_PORT_TYPE_MASK) {
> +		case DP_DWN_STRM_PORT_TYPE_DP:
> +			return 0;
> +		default:
> +			return 8;
> +		}
> +	}
> +
> +	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
> +	case DP_DS_PORT_TYPE_DP:
> +		return 0;
>  	case DP_DS_PORT_TYPE_DP_DUALMODE:
> -		bpc = port_cap[2] & DP_DS_MAX_BPC_MASK;
> +		if (is_edid_digital_input_dp(edid))
> +			return 0;
> +		fallthrough;
> +	case DP_DS_PORT_TYPE_HDMI:
> +	case DP_DS_PORT_TYPE_DVI:
> +	case DP_DS_PORT_TYPE_VGA:
> +		if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
> +			return 8;
>  
> -		switch (bpc) {
> +		switch (port_cap[2] & DP_DS_MAX_BPC_MASK) {
>  		case DP_DS_8BPC:
>  			return 8;
>  		case DP_DS_10BPC:
> @@ -691,10 +699,12 @@ int drm_dp_downstream_max_bpc(const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
>  			return 12;
>  		case DP_DS_16BPC:
>  			return 16;
> +		default:
> +			return 8;
>  		}
> -		fallthrough;
> +		break;
>  	default:
> -		return 0;
> +		return 8;
>  	}
>  }
>  EXPORT_SYMBOL(drm_dp_downstream_max_bpc);
> @@ -717,12 +727,15 @@ EXPORT_SYMBOL(drm_dp_downstream_id);
>   * @m: pointer for debugfs file
>   * @dpcd: DisplayPort configuration data
>   * @port_cap: port capabilities
> + * @edid: EDID
>   * @aux: DisplayPort AUX channel
>   *
>   */
>  void drm_dp_downstream_debug(struct seq_file *m,
>  			     const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> -			     const u8 port_cap[4], struct drm_dp_aux *aux)
> +			     const u8 port_cap[4],
> +			     const struct edid *edid,
> +			     struct drm_dp_aux *aux)
>  {
>  	bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] &
>  				 DP_DETAILED_CAP_INFO_AVAILABLE;
> @@ -789,7 +802,7 @@ void drm_dp_downstream_debug(struct seq_file *m,
>  				seq_printf(m, "\t\tMax TMDS clock: %d kHz\n",
> clk);
>  		}
>  
> -		bpc = drm_dp_downstream_max_bpc(dpcd, port_cap);
> +		bpc = drm_dp_downstream_max_bpc(dpcd, port_cap, edid);
>  
>  		if (bpc > 0)
>  			seq_printf(m, "\t\tMax bpc: %d\n", bpc);
> diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> index 53a0a3d9a22d..0bf31f9a8af5 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> @@ -626,6 +626,7 @@ static void intel_dp_info(struct seq_file *m,
>  {
>  	struct intel_encoder *intel_encoder =
> intel_attached_encoder(intel_connector);
>  	struct intel_dp *intel_dp = enc_to_intel_dp(intel_encoder);
> +	const struct drm_property_blob *edid = intel_connector-
> >base.edid_blob_ptr;
>  
>  	seq_printf(m, "\tDPCD rev: %x\n", intel_dp->dpcd[DP_DPCD_REV]);
>  	seq_printf(m, "\taudio support: %s\n", yesno(intel_dp->has_audio));
> @@ -633,7 +634,7 @@ static void intel_dp_info(struct seq_file *m,
>  		intel_panel_info(m, &intel_connector->panel);
>  
>  	drm_dp_downstream_debug(m, intel_dp->dpcd, intel_dp->downstream_ports,
> -				&intel_dp->aux);
> +				edid ? edid->data : NULL, &intel_dp->aux);
>  }
>  
>  static void intel_dp_mst_info(struct seq_file *m,
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c
> b/drivers/gpu/drm/i915/display/intel_dp.c
> index 2c8e82d97a34..c73b3efd84e0 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -6071,7 +6071,7 @@ intel_dp_set_edid(struct intel_dp *intel_dp)
>  
>  	intel_dp->dfp.max_bpc =
>  		drm_dp_downstream_max_bpc(intel_dp->dpcd,
> -					  intel_dp->downstream_ports);
> +					  intel_dp->downstream_ports, edid);
>  
>  	drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] DFP max bpc %d\n",
>  		    connector->base.base.id, connector->base.name,
> diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
> index 4f946826dfce..6218de1294c1 100644
> --- a/include/drm/drm_dp_helper.h
> +++ b/include/drm/drm_dp_helper.h
> @@ -1646,10 +1646,14 @@ bool drm_dp_downstream_is_tmds(const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
>  int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
>  				const u8 port_cap[4]);
>  int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> -			      const u8 port_cap[4]);
> +			      const u8 port_cap[4],
> +			      const struct edid *edid);
>  int drm_dp_downstream_id(struct drm_dp_aux *aux, char id[6]);
> -void drm_dp_downstream_debug(struct seq_file *m, const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
> -			     const u8 port_cap[4], struct drm_dp_aux *aux);
> +void drm_dp_downstream_debug(struct seq_file *m,
> +			     const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> +			     const u8 port_cap[4],
> +			     const struct edid *edid,
> +			     struct drm_dp_aux *aux);
>  enum drm_mode_subconnector
>  drm_dp_subconnector_type(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
>  			 const u8 port_cap[4]);
-- 
Cheers,
	Lyude Paul (she/her)
	Software Engineer at Red Hat

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v2 07/18] drm/dp: Pimp drm_dp_downstream_max_bpc()
  2020-09-04 11:53   ` [Intel-gfx] " Ville Syrjala
@ 2020-09-08 17:51     ` Lyude Paul
  -1 siblings, 0 replies; 76+ messages in thread
From: Lyude Paul @ 2020-09-08 17:51 UTC (permalink / raw)
  To: Ville Syrjala, dri-devel; +Cc: intel-gfx

On Fri, 2020-09-04 at 14:53 +0300, Ville Syrjala wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Deal with more cases in drm_dp_downstream_max_bpc():
> - DPCD 1.0 -> assume 8bpc for non-DP
> - DPCD 1.1+ DP (or DP++ with DP sink) -> allow anything
> - DPCD 1.1+ TMDS -> check the caps, assume 8bpc if the value is crap
> - anything else -> assume 8bpc
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/drm_dp_helper.c               | 69 +++++++++++--------
>  .../drm/i915/display/intel_display_debugfs.c  |  3 +-
>  drivers/gpu/drm/i915/display/intel_dp.c       |  2 +-
>  include/drm/drm_dp_helper.h                   | 10 ++-
>  4 files changed, 51 insertions(+), 33 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_dp_helper.c
> b/drivers/gpu/drm/drm_dp_helper.c
> index 0fcb94f7dbe5..ab87209c25d8 100644
> --- a/drivers/gpu/drm/drm_dp_helper.c
> +++ b/drivers/gpu/drm/drm_dp_helper.c
> @@ -653,36 +653,44 @@ int drm_dp_downstream_max_clock(const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
>  EXPORT_SYMBOL(drm_dp_downstream_max_clock);
>  
>  /**
> - * drm_dp_downstream_max_bpc() - extract branch device max
> - *                               bits per component
> - * @dpcd: DisplayPort configuration data
> - * @port_cap: port capabilities
> - *
> - * See also:
> - * drm_dp_read_downstream_info()
> - * drm_dp_downstream_max_clock()
> - *
> - * Returns: Max bpc on success or 0 if max bpc not defined
> - */
> +  * drm_dp_downstream_max_bpc() - extract downstream facing port max
> +  *                               bits per component
> +  * @dpcd: DisplayPort configuration data
> +  * @port_cap: downstream facing port capabilities
> +  * @edid: EDID
> +  *
> +  * Returns max bpc on success or 0 if max bpc not defined
> +  */
>  int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> -			      const u8 port_cap[4])
> +			      const u8 port_cap[4],
> +			      const struct edid *edid)
>  {
> -	int type = port_cap[0] & DP_DS_PORT_TYPE_MASK;
> -	bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> -		DP_DETAILED_CAP_INFO_AVAILABLE;
> -	int bpc;
> -
> -	if (!detailed_cap_info)

I don't think we can drop this check. There's a somewhat surprising blurb
about downstream port caps in the DP 2.0 spec (section 5.3.3.1):

   In addition, the adapter shall set the Detailed Capabilities Info registers
   (DPCD Addresses 00080h through 0008Fh) to show all the downstream types,
   including DFP 0. Either one or four bytes are used, per DFP type
   indication. Therefore, up to 16 (with 1-byte descriptor) or four (with 4-
   byte descriptor) DFP capabilities can be stored.

I've never once actually seen a sink do this, but this does mean it's
technically possible tthat if we don't check the detailed caps bit then we
might end up reading another port's DFP type instead of max_bpc info. Note
though that we can make the assumption the four byte version of the field is
used for DP 1.4+

> +	if (!drm_dp_is_branch(dpcd))
>  		return 0;
>  
> -	switch (type) {
> -	case DP_DS_PORT_TYPE_VGA:
> -	case DP_DS_PORT_TYPE_DVI:
> -	case DP_DS_PORT_TYPE_HDMI:
> +	if (dpcd[DP_DPCD_REV] < 0x11) {
> +		switch (dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> DP_DWN_STRM_PORT_TYPE_MASK) {
> +		case DP_DWN_STRM_PORT_TYPE_DP:
> +			return 0;
> +		default:
> +			return 8;
> +		}
> +	}
> +
> +	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
> +	case DP_DS_PORT_TYPE_DP:
> +		return 0;
>  	case DP_DS_PORT_TYPE_DP_DUALMODE:
> -		bpc = port_cap[2] & DP_DS_MAX_BPC_MASK;
> +		if (is_edid_digital_input_dp(edid))
> +			return 0;
> +		fallthrough;
> +	case DP_DS_PORT_TYPE_HDMI:
> +	case DP_DS_PORT_TYPE_DVI:
> +	case DP_DS_PORT_TYPE_VGA:
> +		if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
> +			return 8;
>  
> -		switch (bpc) {
> +		switch (port_cap[2] & DP_DS_MAX_BPC_MASK) {
>  		case DP_DS_8BPC:
>  			return 8;
>  		case DP_DS_10BPC:
> @@ -691,10 +699,12 @@ int drm_dp_downstream_max_bpc(const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
>  			return 12;
>  		case DP_DS_16BPC:
>  			return 16;
> +		default:
> +			return 8;
>  		}
> -		fallthrough;
> +		break;
>  	default:
> -		return 0;
> +		return 8;
>  	}
>  }
>  EXPORT_SYMBOL(drm_dp_downstream_max_bpc);
> @@ -717,12 +727,15 @@ EXPORT_SYMBOL(drm_dp_downstream_id);
>   * @m: pointer for debugfs file
>   * @dpcd: DisplayPort configuration data
>   * @port_cap: port capabilities
> + * @edid: EDID
>   * @aux: DisplayPort AUX channel
>   *
>   */
>  void drm_dp_downstream_debug(struct seq_file *m,
>  			     const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> -			     const u8 port_cap[4], struct drm_dp_aux *aux)
> +			     const u8 port_cap[4],
> +			     const struct edid *edid,
> +			     struct drm_dp_aux *aux)
>  {
>  	bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] &
>  				 DP_DETAILED_CAP_INFO_AVAILABLE;
> @@ -789,7 +802,7 @@ void drm_dp_downstream_debug(struct seq_file *m,
>  				seq_printf(m, "\t\tMax TMDS clock: %d kHz\n",
> clk);
>  		}
>  
> -		bpc = drm_dp_downstream_max_bpc(dpcd, port_cap);
> +		bpc = drm_dp_downstream_max_bpc(dpcd, port_cap, edid);
>  
>  		if (bpc > 0)
>  			seq_printf(m, "\t\tMax bpc: %d\n", bpc);
> diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> index 53a0a3d9a22d..0bf31f9a8af5 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> @@ -626,6 +626,7 @@ static void intel_dp_info(struct seq_file *m,
>  {
>  	struct intel_encoder *intel_encoder =
> intel_attached_encoder(intel_connector);
>  	struct intel_dp *intel_dp = enc_to_intel_dp(intel_encoder);
> +	const struct drm_property_blob *edid = intel_connector-
> >base.edid_blob_ptr;
>  
>  	seq_printf(m, "\tDPCD rev: %x\n", intel_dp->dpcd[DP_DPCD_REV]);
>  	seq_printf(m, "\taudio support: %s\n", yesno(intel_dp->has_audio));
> @@ -633,7 +634,7 @@ static void intel_dp_info(struct seq_file *m,
>  		intel_panel_info(m, &intel_connector->panel);
>  
>  	drm_dp_downstream_debug(m, intel_dp->dpcd, intel_dp->downstream_ports,
> -				&intel_dp->aux);
> +				edid ? edid->data : NULL, &intel_dp->aux);
>  }
>  
>  static void intel_dp_mst_info(struct seq_file *m,
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c
> b/drivers/gpu/drm/i915/display/intel_dp.c
> index 2c8e82d97a34..c73b3efd84e0 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -6071,7 +6071,7 @@ intel_dp_set_edid(struct intel_dp *intel_dp)
>  
>  	intel_dp->dfp.max_bpc =
>  		drm_dp_downstream_max_bpc(intel_dp->dpcd,
> -					  intel_dp->downstream_ports);
> +					  intel_dp->downstream_ports, edid);
>  
>  	drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] DFP max bpc %d\n",
>  		    connector->base.base.id, connector->base.name,
> diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
> index 4f946826dfce..6218de1294c1 100644
> --- a/include/drm/drm_dp_helper.h
> +++ b/include/drm/drm_dp_helper.h
> @@ -1646,10 +1646,14 @@ bool drm_dp_downstream_is_tmds(const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
>  int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
>  				const u8 port_cap[4]);
>  int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> -			      const u8 port_cap[4]);
> +			      const u8 port_cap[4],
> +			      const struct edid *edid);
>  int drm_dp_downstream_id(struct drm_dp_aux *aux, char id[6]);
> -void drm_dp_downstream_debug(struct seq_file *m, const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
> -			     const u8 port_cap[4], struct drm_dp_aux *aux);
> +void drm_dp_downstream_debug(struct seq_file *m,
> +			     const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> +			     const u8 port_cap[4],
> +			     const struct edid *edid,
> +			     struct drm_dp_aux *aux);
>  enum drm_mode_subconnector
>  drm_dp_subconnector_type(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
>  			 const u8 port_cap[4]);
-- 
Cheers,
	Lyude Paul (she/her)
	Software Engineer at Red Hat

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Intel-gfx] [PATCH v2 07/18] drm/dp: Pimp drm_dp_downstream_max_bpc()
@ 2020-09-08 17:51     ` Lyude Paul
  0 siblings, 0 replies; 76+ messages in thread
From: Lyude Paul @ 2020-09-08 17:51 UTC (permalink / raw)
  To: Ville Syrjala, dri-devel; +Cc: intel-gfx

On Fri, 2020-09-04 at 14:53 +0300, Ville Syrjala wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Deal with more cases in drm_dp_downstream_max_bpc():
> - DPCD 1.0 -> assume 8bpc for non-DP
> - DPCD 1.1+ DP (or DP++ with DP sink) -> allow anything
> - DPCD 1.1+ TMDS -> check the caps, assume 8bpc if the value is crap
> - anything else -> assume 8bpc
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/drm_dp_helper.c               | 69 +++++++++++--------
>  .../drm/i915/display/intel_display_debugfs.c  |  3 +-
>  drivers/gpu/drm/i915/display/intel_dp.c       |  2 +-
>  include/drm/drm_dp_helper.h                   | 10 ++-
>  4 files changed, 51 insertions(+), 33 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_dp_helper.c
> b/drivers/gpu/drm/drm_dp_helper.c
> index 0fcb94f7dbe5..ab87209c25d8 100644
> --- a/drivers/gpu/drm/drm_dp_helper.c
> +++ b/drivers/gpu/drm/drm_dp_helper.c
> @@ -653,36 +653,44 @@ int drm_dp_downstream_max_clock(const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
>  EXPORT_SYMBOL(drm_dp_downstream_max_clock);
>  
>  /**
> - * drm_dp_downstream_max_bpc() - extract branch device max
> - *                               bits per component
> - * @dpcd: DisplayPort configuration data
> - * @port_cap: port capabilities
> - *
> - * See also:
> - * drm_dp_read_downstream_info()
> - * drm_dp_downstream_max_clock()
> - *
> - * Returns: Max bpc on success or 0 if max bpc not defined
> - */
> +  * drm_dp_downstream_max_bpc() - extract downstream facing port max
> +  *                               bits per component
> +  * @dpcd: DisplayPort configuration data
> +  * @port_cap: downstream facing port capabilities
> +  * @edid: EDID
> +  *
> +  * Returns max bpc on success or 0 if max bpc not defined
> +  */
>  int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> -			      const u8 port_cap[4])
> +			      const u8 port_cap[4],
> +			      const struct edid *edid)
>  {
> -	int type = port_cap[0] & DP_DS_PORT_TYPE_MASK;
> -	bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> -		DP_DETAILED_CAP_INFO_AVAILABLE;
> -	int bpc;
> -
> -	if (!detailed_cap_info)

I don't think we can drop this check. There's a somewhat surprising blurb
about downstream port caps in the DP 2.0 spec (section 5.3.3.1):

   In addition, the adapter shall set the Detailed Capabilities Info registers
   (DPCD Addresses 00080h through 0008Fh) to show all the downstream types,
   including DFP 0. Either one or four bytes are used, per DFP type
   indication. Therefore, up to 16 (with 1-byte descriptor) or four (with 4-
   byte descriptor) DFP capabilities can be stored.

I've never once actually seen a sink do this, but this does mean it's
technically possible tthat if we don't check the detailed caps bit then we
might end up reading another port's DFP type instead of max_bpc info. Note
though that we can make the assumption the four byte version of the field is
used for DP 1.4+

> +	if (!drm_dp_is_branch(dpcd))
>  		return 0;
>  
> -	switch (type) {
> -	case DP_DS_PORT_TYPE_VGA:
> -	case DP_DS_PORT_TYPE_DVI:
> -	case DP_DS_PORT_TYPE_HDMI:
> +	if (dpcd[DP_DPCD_REV] < 0x11) {
> +		switch (dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> DP_DWN_STRM_PORT_TYPE_MASK) {
> +		case DP_DWN_STRM_PORT_TYPE_DP:
> +			return 0;
> +		default:
> +			return 8;
> +		}
> +	}
> +
> +	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
> +	case DP_DS_PORT_TYPE_DP:
> +		return 0;
>  	case DP_DS_PORT_TYPE_DP_DUALMODE:
> -		bpc = port_cap[2] & DP_DS_MAX_BPC_MASK;
> +		if (is_edid_digital_input_dp(edid))
> +			return 0;
> +		fallthrough;
> +	case DP_DS_PORT_TYPE_HDMI:
> +	case DP_DS_PORT_TYPE_DVI:
> +	case DP_DS_PORT_TYPE_VGA:
> +		if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
> +			return 8;
>  
> -		switch (bpc) {
> +		switch (port_cap[2] & DP_DS_MAX_BPC_MASK) {
>  		case DP_DS_8BPC:
>  			return 8;
>  		case DP_DS_10BPC:
> @@ -691,10 +699,12 @@ int drm_dp_downstream_max_bpc(const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
>  			return 12;
>  		case DP_DS_16BPC:
>  			return 16;
> +		default:
> +			return 8;
>  		}
> -		fallthrough;
> +		break;
>  	default:
> -		return 0;
> +		return 8;
>  	}
>  }
>  EXPORT_SYMBOL(drm_dp_downstream_max_bpc);
> @@ -717,12 +727,15 @@ EXPORT_SYMBOL(drm_dp_downstream_id);
>   * @m: pointer for debugfs file
>   * @dpcd: DisplayPort configuration data
>   * @port_cap: port capabilities
> + * @edid: EDID
>   * @aux: DisplayPort AUX channel
>   *
>   */
>  void drm_dp_downstream_debug(struct seq_file *m,
>  			     const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> -			     const u8 port_cap[4], struct drm_dp_aux *aux)
> +			     const u8 port_cap[4],
> +			     const struct edid *edid,
> +			     struct drm_dp_aux *aux)
>  {
>  	bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] &
>  				 DP_DETAILED_CAP_INFO_AVAILABLE;
> @@ -789,7 +802,7 @@ void drm_dp_downstream_debug(struct seq_file *m,
>  				seq_printf(m, "\t\tMax TMDS clock: %d kHz\n",
> clk);
>  		}
>  
> -		bpc = drm_dp_downstream_max_bpc(dpcd, port_cap);
> +		bpc = drm_dp_downstream_max_bpc(dpcd, port_cap, edid);
>  
>  		if (bpc > 0)
>  			seq_printf(m, "\t\tMax bpc: %d\n", bpc);
> diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> index 53a0a3d9a22d..0bf31f9a8af5 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> @@ -626,6 +626,7 @@ static void intel_dp_info(struct seq_file *m,
>  {
>  	struct intel_encoder *intel_encoder =
> intel_attached_encoder(intel_connector);
>  	struct intel_dp *intel_dp = enc_to_intel_dp(intel_encoder);
> +	const struct drm_property_blob *edid = intel_connector-
> >base.edid_blob_ptr;
>  
>  	seq_printf(m, "\tDPCD rev: %x\n", intel_dp->dpcd[DP_DPCD_REV]);
>  	seq_printf(m, "\taudio support: %s\n", yesno(intel_dp->has_audio));
> @@ -633,7 +634,7 @@ static void intel_dp_info(struct seq_file *m,
>  		intel_panel_info(m, &intel_connector->panel);
>  
>  	drm_dp_downstream_debug(m, intel_dp->dpcd, intel_dp->downstream_ports,
> -				&intel_dp->aux);
> +				edid ? edid->data : NULL, &intel_dp->aux);
>  }
>  
>  static void intel_dp_mst_info(struct seq_file *m,
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c
> b/drivers/gpu/drm/i915/display/intel_dp.c
> index 2c8e82d97a34..c73b3efd84e0 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -6071,7 +6071,7 @@ intel_dp_set_edid(struct intel_dp *intel_dp)
>  
>  	intel_dp->dfp.max_bpc =
>  		drm_dp_downstream_max_bpc(intel_dp->dpcd,
> -					  intel_dp->downstream_ports);
> +					  intel_dp->downstream_ports, edid);
>  
>  	drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] DFP max bpc %d\n",
>  		    connector->base.base.id, connector->base.name,
> diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
> index 4f946826dfce..6218de1294c1 100644
> --- a/include/drm/drm_dp_helper.h
> +++ b/include/drm/drm_dp_helper.h
> @@ -1646,10 +1646,14 @@ bool drm_dp_downstream_is_tmds(const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
>  int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
>  				const u8 port_cap[4]);
>  int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> -			      const u8 port_cap[4]);
> +			      const u8 port_cap[4],
> +			      const struct edid *edid);
>  int drm_dp_downstream_id(struct drm_dp_aux *aux, char id[6]);
> -void drm_dp_downstream_debug(struct seq_file *m, const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
> -			     const u8 port_cap[4], struct drm_dp_aux *aux);
> +void drm_dp_downstream_debug(struct seq_file *m,
> +			     const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> +			     const u8 port_cap[4],
> +			     const struct edid *edid,
> +			     struct drm_dp_aux *aux);
>  enum drm_mode_subconnector
>  drm_dp_subconnector_type(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
>  			 const u8 port_cap[4]);
-- 
Cheers,
	Lyude Paul (she/her)
	Software Engineer at Red Hat

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v2 08/18] drm/dp: Redo drm_dp_downstream_max_clock() as drm_dp_downstream_max_dotclock()
  2020-09-04 11:53   ` [Intel-gfx] " Ville Syrjala
@ 2020-09-08 17:56     ` Lyude Paul
  -1 siblings, 0 replies; 76+ messages in thread
From: Lyude Paul @ 2020-09-08 17:56 UTC (permalink / raw)
  To: Ville Syrjala, dri-devel; +Cc: intel-gfx

BTW - we started using drm_dp_downstream_max_clock() in nouveau, so you'll
need to update the function call there too.

On Fri, 2020-09-04 at 14:53 +0300, Ville Syrjala wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> We want to differentiate between the DFP dotclock and TMDS clock
> limits. Let's convert the current thing to just give us the
> dotclock limit.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/drm_dp_helper.c         | 46 +++++++++----------------
>  drivers/gpu/drm/i915/display/intel_dp.c |  4 +--
>  include/drm/drm_dp_helper.h             |  4 +--
>  3 files changed, 20 insertions(+), 34 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_dp_helper.c
> b/drivers/gpu/drm/drm_dp_helper.c
> index ab87209c25d8..822a30e609ef 100644
> --- a/drivers/gpu/drm/drm_dp_helper.c
> +++ b/drivers/gpu/drm/drm_dp_helper.c
> @@ -616,41 +616,32 @@ int drm_dp_read_downstream_info(struct drm_dp_aux
> *aux,
>  EXPORT_SYMBOL(drm_dp_read_downstream_info);
>  
>  /**
> - * drm_dp_downstream_max_clock() - extract branch device max
> - *                                 pixel rate for legacy VGA
> - *                                 converter or max TMDS clock
> - *                                 rate for others
> + * drm_dp_downstream_max_dotclock() - extract downstream facing port max
> dot clock
>   * @dpcd: DisplayPort configuration data
>   * @port_cap: port capabilities
>   *
> - * See also:
> - * drm_dp_read_downstream_info()
> - * drm_dp_downstream_max_bpc()
> - *
> - * Returns: Max clock in kHz on success or 0 if max clock not defined
> + * Returns downstream facing port max dot clock in kHz on success,
> + * or 0 if max clock not defined
>   */
> -int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> -				const u8 port_cap[4])
> +int drm_dp_downstream_max_dotclock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> +				   const u8 port_cap[4])
>  {
> -	int type = port_cap[0] & DP_DS_PORT_TYPE_MASK;
> -	bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> -		DP_DETAILED_CAP_INFO_AVAILABLE;
> +	if (!drm_dp_is_branch(dpcd))
> +		return 0;
>  
> -	if (!detailed_cap_info)
> +	if (dpcd[DP_DPCD_REV] < 0x11)
>  		return 0;
>  
> -	switch (type) {
> +	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
>  	case DP_DS_PORT_TYPE_VGA:
> -		return port_cap[1] * 8 * 1000;
> -	case DP_DS_PORT_TYPE_DVI:
> -	case DP_DS_PORT_TYPE_HDMI:
> -	case DP_DS_PORT_TYPE_DP_DUALMODE:
> -		return port_cap[1] * 2500;
> +		if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
> +			return 0;
> +		return port_cap[1] * 8000;
>  	default:
>  		return 0;
>  	}
>  }
> -EXPORT_SYMBOL(drm_dp_downstream_max_clock);
> +EXPORT_SYMBOL(drm_dp_downstream_max_dotclock);
>  
>  /**
>    * drm_dp_downstream_max_bpc() - extract downstream facing port max
> @@ -793,14 +784,9 @@ void drm_dp_downstream_debug(struct seq_file *m,
>  		seq_printf(m, "\t\tSW: %d.%d\n", rev[0], rev[1]);
>  
>  	if (detailed_cap_info) {
> -		clk = drm_dp_downstream_max_clock(dpcd, port_cap);
> -
> -		if (clk > 0) {
> -			if (type == DP_DS_PORT_TYPE_VGA)
> -				seq_printf(m, "\t\tMax dot clock: %d kHz\n",
> clk);
> -			else
> -				seq_printf(m, "\t\tMax TMDS clock: %d kHz\n",
> clk);
> -		}
> +		clk = drm_dp_downstream_max_dotclock(dpcd, port_cap);
> +		if (clk > 0)
> +			seq_printf(m, "\t\tMax dot clock: %d kHz\n", clk);
>  
>  		bpc = drm_dp_downstream_max_bpc(dpcd, port_cap, edid);
>  
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c
> b/drivers/gpu/drm/i915/display/intel_dp.c
> index c73b3efd84e0..8f4aee35c203 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -261,8 +261,8 @@ intel_dp_downstream_max_dotclock(struct intel_dp
> *intel_dp)
>  	if (type != DP_DS_PORT_TYPE_VGA)
>  		return max_dotclk;
>  
> -	ds_max_dotclk = drm_dp_downstream_max_clock(intel_dp->dpcd,
> -						    intel_dp-
> >downstream_ports);
> +	ds_max_dotclk = drm_dp_downstream_max_dotclock(intel_dp->dpcd,
> +						       intel_dp-
> >downstream_ports);
>  
>  	if (ds_max_dotclk != 0)
>  		max_dotclk = min(max_dotclk, ds_max_dotclk);
> diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
> index 6218de1294c1..19bc04207788 100644
> --- a/include/drm/drm_dp_helper.h
> +++ b/include/drm/drm_dp_helper.h
> @@ -1643,8 +1643,8 @@ bool drm_dp_downstream_is_type(const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
>  bool drm_dp_downstream_is_tmds(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
>  			       const u8 port_cap[4],
>  			       const struct edid *edid);
> -int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> -				const u8 port_cap[4]);
> +int drm_dp_downstream_max_dotclock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> +				   const u8 port_cap[4]);
>  int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
>  			      const u8 port_cap[4],
>  			      const struct edid *edid);
-- 
Cheers,
	Lyude Paul (she/her)
	Software Engineer at Red Hat

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Intel-gfx] [PATCH v2 08/18] drm/dp: Redo drm_dp_downstream_max_clock() as drm_dp_downstream_max_dotclock()
@ 2020-09-08 17:56     ` Lyude Paul
  0 siblings, 0 replies; 76+ messages in thread
From: Lyude Paul @ 2020-09-08 17:56 UTC (permalink / raw)
  To: Ville Syrjala, dri-devel; +Cc: intel-gfx

BTW - we started using drm_dp_downstream_max_clock() in nouveau, so you'll
need to update the function call there too.

On Fri, 2020-09-04 at 14:53 +0300, Ville Syrjala wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> We want to differentiate between the DFP dotclock and TMDS clock
> limits. Let's convert the current thing to just give us the
> dotclock limit.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/drm_dp_helper.c         | 46 +++++++++----------------
>  drivers/gpu/drm/i915/display/intel_dp.c |  4 +--
>  include/drm/drm_dp_helper.h             |  4 +--
>  3 files changed, 20 insertions(+), 34 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_dp_helper.c
> b/drivers/gpu/drm/drm_dp_helper.c
> index ab87209c25d8..822a30e609ef 100644
> --- a/drivers/gpu/drm/drm_dp_helper.c
> +++ b/drivers/gpu/drm/drm_dp_helper.c
> @@ -616,41 +616,32 @@ int drm_dp_read_downstream_info(struct drm_dp_aux
> *aux,
>  EXPORT_SYMBOL(drm_dp_read_downstream_info);
>  
>  /**
> - * drm_dp_downstream_max_clock() - extract branch device max
> - *                                 pixel rate for legacy VGA
> - *                                 converter or max TMDS clock
> - *                                 rate for others
> + * drm_dp_downstream_max_dotclock() - extract downstream facing port max
> dot clock
>   * @dpcd: DisplayPort configuration data
>   * @port_cap: port capabilities
>   *
> - * See also:
> - * drm_dp_read_downstream_info()
> - * drm_dp_downstream_max_bpc()
> - *
> - * Returns: Max clock in kHz on success or 0 if max clock not defined
> + * Returns downstream facing port max dot clock in kHz on success,
> + * or 0 if max clock not defined
>   */
> -int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> -				const u8 port_cap[4])
> +int drm_dp_downstream_max_dotclock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> +				   const u8 port_cap[4])
>  {
> -	int type = port_cap[0] & DP_DS_PORT_TYPE_MASK;
> -	bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> -		DP_DETAILED_CAP_INFO_AVAILABLE;
> +	if (!drm_dp_is_branch(dpcd))
> +		return 0;
>  
> -	if (!detailed_cap_info)
> +	if (dpcd[DP_DPCD_REV] < 0x11)
>  		return 0;
>  
> -	switch (type) {
> +	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
>  	case DP_DS_PORT_TYPE_VGA:
> -		return port_cap[1] * 8 * 1000;
> -	case DP_DS_PORT_TYPE_DVI:
> -	case DP_DS_PORT_TYPE_HDMI:
> -	case DP_DS_PORT_TYPE_DP_DUALMODE:
> -		return port_cap[1] * 2500;
> +		if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
> +			return 0;
> +		return port_cap[1] * 8000;
>  	default:
>  		return 0;
>  	}
>  }
> -EXPORT_SYMBOL(drm_dp_downstream_max_clock);
> +EXPORT_SYMBOL(drm_dp_downstream_max_dotclock);
>  
>  /**
>    * drm_dp_downstream_max_bpc() - extract downstream facing port max
> @@ -793,14 +784,9 @@ void drm_dp_downstream_debug(struct seq_file *m,
>  		seq_printf(m, "\t\tSW: %d.%d\n", rev[0], rev[1]);
>  
>  	if (detailed_cap_info) {
> -		clk = drm_dp_downstream_max_clock(dpcd, port_cap);
> -
> -		if (clk > 0) {
> -			if (type == DP_DS_PORT_TYPE_VGA)
> -				seq_printf(m, "\t\tMax dot clock: %d kHz\n",
> clk);
> -			else
> -				seq_printf(m, "\t\tMax TMDS clock: %d kHz\n",
> clk);
> -		}
> +		clk = drm_dp_downstream_max_dotclock(dpcd, port_cap);
> +		if (clk > 0)
> +			seq_printf(m, "\t\tMax dot clock: %d kHz\n", clk);
>  
>  		bpc = drm_dp_downstream_max_bpc(dpcd, port_cap, edid);
>  
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c
> b/drivers/gpu/drm/i915/display/intel_dp.c
> index c73b3efd84e0..8f4aee35c203 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -261,8 +261,8 @@ intel_dp_downstream_max_dotclock(struct intel_dp
> *intel_dp)
>  	if (type != DP_DS_PORT_TYPE_VGA)
>  		return max_dotclk;
>  
> -	ds_max_dotclk = drm_dp_downstream_max_clock(intel_dp->dpcd,
> -						    intel_dp-
> >downstream_ports);
> +	ds_max_dotclk = drm_dp_downstream_max_dotclock(intel_dp->dpcd,
> +						       intel_dp-
> >downstream_ports);
>  
>  	if (ds_max_dotclk != 0)
>  		max_dotclk = min(max_dotclk, ds_max_dotclk);
> diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
> index 6218de1294c1..19bc04207788 100644
> --- a/include/drm/drm_dp_helper.h
> +++ b/include/drm/drm_dp_helper.h
> @@ -1643,8 +1643,8 @@ bool drm_dp_downstream_is_type(const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
>  bool drm_dp_downstream_is_tmds(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
>  			       const u8 port_cap[4],
>  			       const struct edid *edid);
> -int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> -				const u8 port_cap[4]);
> +int drm_dp_downstream_max_dotclock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> +				   const u8 port_cap[4]);
>  int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
>  			      const u8 port_cap[4],
>  			      const struct edid *edid);
-- 
Cheers,
	Lyude Paul (she/her)
	Software Engineer at Red Hat

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v2 10/18] drm/dp: Add drm_dp_downstream_{min,max}_tmds_clock()
  2020-09-04 11:53   ` [Intel-gfx] " Ville Syrjala
@ 2020-09-08 18:04     ` Lyude Paul
  -1 siblings, 0 replies; 76+ messages in thread
From: Lyude Paul @ 2020-09-08 18:04 UTC (permalink / raw)
  To: Ville Syrjala, dri-devel; +Cc: intel-gfx

On Fri, 2020-09-04 at 14:53 +0300, Ville Syrjala wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Add helpers to get the TMDS clock limits for HDMI/DVI downstream
> facing ports.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/drm_dp_helper.c | 116 ++++++++++++++++++++++++++++++++
>  include/drm/drm_dp_helper.h     |   6 ++
>  2 files changed, 122 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_dp_helper.c
> b/drivers/gpu/drm/drm_dp_helper.c
> index 822a30e609ef..f567428f2aef 100644
> --- a/drivers/gpu/drm/drm_dp_helper.c
> +++ b/drivers/gpu/drm/drm_dp_helper.c
> @@ -643,6 +643,114 @@ int drm_dp_downstream_max_dotclock(const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
>  }
>  EXPORT_SYMBOL(drm_dp_downstream_max_dotclock);
>  
> +/**
> + * drm_dp_downstream_max_tmds_clock() - extract downstream facing port max
> TMDS clock
> + * @dpcd: DisplayPort configuration data
> + * @port_cap: port capabilities
> + * @edid: EDID
> + *
> + * Returns HDMI/DVI downstream facing port max TMDS clock in kHz on
> success,
> + * or 0 if max TMDS clock not defined
> + */
> +int drm_dp_downstream_max_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> +				     const u8 port_cap[4],
> +				     const struct edid *edid)
> +{
> +	if (!drm_dp_is_branch(dpcd))
> +		return 0;
> +
> +	if (dpcd[DP_DPCD_REV] < 0x11) {
> +		switch (dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> DP_DWN_STRM_PORT_TYPE_MASK) {
> +		case DP_DWN_STRM_PORT_TYPE_TMDS:
> +			return 165000;
> +		default:
> +			return 0;
> +		}
> +	}
> +
> +	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
> +	case DP_DS_PORT_TYPE_DP_DUALMODE:
> +		if (is_edid_digital_input_dp(edid))
> +			return 0;
> +		/*
> +		 * It's left up to the driver to check the
> +		 * DP dual mode adapter's max TMDS clock.
> +		 *
> +		 * Unfortunatley it looks like branch devices
> +		 * may not fordward that the DP dual mode i2c
> +		 * access so we just usually get i2c nak :(
> +		 */
> +		fallthrough;
> +	case DP_DS_PORT_TYPE_HDMI:
> +		 /*
> +		  * We should perhaps assume 165 MHz when detailed cap
> +		  * info is not available. But looks like many typical
> +		  * branch devices fall into that category and so we'd
> +		  * probably end up with users complaining that they can't
> +		  * get high resolution modes with their favorite dongle.
> +		  *
> +		  * So let's limit to 300 MHz instead since DPCD 1.4
> +		  * HDMI 2.0 DFPs are required to have the detailed cap
> +		  * info. So it's more likely we're dealing with a HDMI 1.4
> +		  * compatible* device here.
> +		  */
> +		if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
> +			return 300000;
> +		return port_cap[1] * 2500;
> +	case DP_DS_PORT_TYPE_DVI:
> +		if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
> +			return 165000;
> +		/* FIXME what to do about DVI dual link? */
> +		return port_cap[1] * 2500;
> +	default:
> +		return 0;
> +	}
> +}
> +EXPORT_SYMBOL(drm_dp_downstream_max_tmds_clock);
> +
> +/**
> + * drm_dp_downstream_min_tmds_clock() - extract downstream facing port min
> TMDS clock
> + * @dpcd: DisplayPort configuration data
> + * @port_cap: port capabilities
> + * @edid: EDID
> + *
> + * Returns HDMI/DVI downstream facing port min TMDS clock in kHz on
> success,
> + * or 0 if max TMDS clock not defined

s/max/min/

Also, I would assume if callers are interested in min they're also interested
in max and vice versa, would it maybe make sense to combine the min/max
functions here?

Also, we should probably note the existence of this function in the max
dotclock functions and vice-versa
> + */
> +int drm_dp_downstream_min_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> +				     const u8 port_cap[4],
> +				     const struct edid *edid)
> +{
> +	if (!drm_dp_is_branch(dpcd))
> +		return 0;
> +
> +	if (dpcd[DP_DPCD_REV] < 0x11) {
> +		switch (dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> DP_DWN_STRM_PORT_TYPE_MASK) {
> +		case DP_DWN_STRM_PORT_TYPE_TMDS:
> +			return 25000;
> +		default:
> +			return 0;
> +		}
> +	}
> +
> +	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
> +	case DP_DS_PORT_TYPE_DP_DUALMODE:
> +		if (is_edid_digital_input_dp(edid))
> +			return 0;
> +		fallthrough;
> +	case DP_DS_PORT_TYPE_DVI:
> +	case DP_DS_PORT_TYPE_HDMI:
> +		/*
> +		 * Unclear whether the protocol converter could
> +		 * utilize pixel replication. Assume it won't.
> +		 */
> +		return 25000;
> +	default:
> +		return 0;
> +	}
> +}
> +EXPORT_SYMBOL(drm_dp_downstream_min_tmds_clock);
> +
>  /**
>    * drm_dp_downstream_max_bpc() - extract downstream facing port max
>    *                               bits per component
> @@ -788,6 +896,14 @@ void drm_dp_downstream_debug(struct seq_file *m,
>  		if (clk > 0)
>  			seq_printf(m, "\t\tMax dot clock: %d kHz\n", clk);
>  
> +		clk = drm_dp_downstream_max_tmds_clock(dpcd, port_cap, edid);
> +		if (clk > 0)
> +			seq_printf(m, "\t\tMax TMDS clock: %d kHz\n", clk);
> +
> +		clk = drm_dp_downstream_min_tmds_clock(dpcd, port_cap, edid);
> +		if (clk > 0)
> +			seq_printf(m, "\t\tMin TMDS clock: %d kHz\n", clk);
> +
>  		bpc = drm_dp_downstream_max_bpc(dpcd, port_cap, edid);
>  
>  		if (bpc > 0)
> diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
> index 19bc04207788..6812a3e0de8d 100644
> --- a/include/drm/drm_dp_helper.h
> +++ b/include/drm/drm_dp_helper.h
> @@ -1645,6 +1645,12 @@ bool drm_dp_downstream_is_tmds(const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
>  			       const struct edid *edid);
>  int drm_dp_downstream_max_dotclock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
>  				   const u8 port_cap[4]);
> +int drm_dp_downstream_max_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> +				     const u8 port_cap[4],
> +				     const struct edid *edid);
> +int drm_dp_downstream_min_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> +				     const u8 port_cap[4],
> +				     const struct edid *edid);
>  int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
>  			      const u8 port_cap[4],
>  			      const struct edid *edid);
-- 
Cheers,
	Lyude Paul (she/her)
	Software Engineer at Red Hat

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Intel-gfx] [PATCH v2 10/18] drm/dp: Add drm_dp_downstream_{min, max}_tmds_clock()
@ 2020-09-08 18:04     ` Lyude Paul
  0 siblings, 0 replies; 76+ messages in thread
From: Lyude Paul @ 2020-09-08 18:04 UTC (permalink / raw)
  To: Ville Syrjala, dri-devel; +Cc: intel-gfx

On Fri, 2020-09-04 at 14:53 +0300, Ville Syrjala wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Add helpers to get the TMDS clock limits for HDMI/DVI downstream
> facing ports.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/drm_dp_helper.c | 116 ++++++++++++++++++++++++++++++++
>  include/drm/drm_dp_helper.h     |   6 ++
>  2 files changed, 122 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_dp_helper.c
> b/drivers/gpu/drm/drm_dp_helper.c
> index 822a30e609ef..f567428f2aef 100644
> --- a/drivers/gpu/drm/drm_dp_helper.c
> +++ b/drivers/gpu/drm/drm_dp_helper.c
> @@ -643,6 +643,114 @@ int drm_dp_downstream_max_dotclock(const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
>  }
>  EXPORT_SYMBOL(drm_dp_downstream_max_dotclock);
>  
> +/**
> + * drm_dp_downstream_max_tmds_clock() - extract downstream facing port max
> TMDS clock
> + * @dpcd: DisplayPort configuration data
> + * @port_cap: port capabilities
> + * @edid: EDID
> + *
> + * Returns HDMI/DVI downstream facing port max TMDS clock in kHz on
> success,
> + * or 0 if max TMDS clock not defined
> + */
> +int drm_dp_downstream_max_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> +				     const u8 port_cap[4],
> +				     const struct edid *edid)
> +{
> +	if (!drm_dp_is_branch(dpcd))
> +		return 0;
> +
> +	if (dpcd[DP_DPCD_REV] < 0x11) {
> +		switch (dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> DP_DWN_STRM_PORT_TYPE_MASK) {
> +		case DP_DWN_STRM_PORT_TYPE_TMDS:
> +			return 165000;
> +		default:
> +			return 0;
> +		}
> +	}
> +
> +	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
> +	case DP_DS_PORT_TYPE_DP_DUALMODE:
> +		if (is_edid_digital_input_dp(edid))
> +			return 0;
> +		/*
> +		 * It's left up to the driver to check the
> +		 * DP dual mode adapter's max TMDS clock.
> +		 *
> +		 * Unfortunatley it looks like branch devices
> +		 * may not fordward that the DP dual mode i2c
> +		 * access so we just usually get i2c nak :(
> +		 */
> +		fallthrough;
> +	case DP_DS_PORT_TYPE_HDMI:
> +		 /*
> +		  * We should perhaps assume 165 MHz when detailed cap
> +		  * info is not available. But looks like many typical
> +		  * branch devices fall into that category and so we'd
> +		  * probably end up with users complaining that they can't
> +		  * get high resolution modes with their favorite dongle.
> +		  *
> +		  * So let's limit to 300 MHz instead since DPCD 1.4
> +		  * HDMI 2.0 DFPs are required to have the detailed cap
> +		  * info. So it's more likely we're dealing with a HDMI 1.4
> +		  * compatible* device here.
> +		  */
> +		if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
> +			return 300000;
> +		return port_cap[1] * 2500;
> +	case DP_DS_PORT_TYPE_DVI:
> +		if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
> +			return 165000;
> +		/* FIXME what to do about DVI dual link? */
> +		return port_cap[1] * 2500;
> +	default:
> +		return 0;
> +	}
> +}
> +EXPORT_SYMBOL(drm_dp_downstream_max_tmds_clock);
> +
> +/**
> + * drm_dp_downstream_min_tmds_clock() - extract downstream facing port min
> TMDS clock
> + * @dpcd: DisplayPort configuration data
> + * @port_cap: port capabilities
> + * @edid: EDID
> + *
> + * Returns HDMI/DVI downstream facing port min TMDS clock in kHz on
> success,
> + * or 0 if max TMDS clock not defined

s/max/min/

Also, I would assume if callers are interested in min they're also interested
in max and vice versa, would it maybe make sense to combine the min/max
functions here?

Also, we should probably note the existence of this function in the max
dotclock functions and vice-versa
> + */
> +int drm_dp_downstream_min_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> +				     const u8 port_cap[4],
> +				     const struct edid *edid)
> +{
> +	if (!drm_dp_is_branch(dpcd))
> +		return 0;
> +
> +	if (dpcd[DP_DPCD_REV] < 0x11) {
> +		switch (dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> DP_DWN_STRM_PORT_TYPE_MASK) {
> +		case DP_DWN_STRM_PORT_TYPE_TMDS:
> +			return 25000;
> +		default:
> +			return 0;
> +		}
> +	}
> +
> +	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
> +	case DP_DS_PORT_TYPE_DP_DUALMODE:
> +		if (is_edid_digital_input_dp(edid))
> +			return 0;
> +		fallthrough;
> +	case DP_DS_PORT_TYPE_DVI:
> +	case DP_DS_PORT_TYPE_HDMI:
> +		/*
> +		 * Unclear whether the protocol converter could
> +		 * utilize pixel replication. Assume it won't.
> +		 */
> +		return 25000;
> +	default:
> +		return 0;
> +	}
> +}
> +EXPORT_SYMBOL(drm_dp_downstream_min_tmds_clock);
> +
>  /**
>    * drm_dp_downstream_max_bpc() - extract downstream facing port max
>    *                               bits per component
> @@ -788,6 +896,14 @@ void drm_dp_downstream_debug(struct seq_file *m,
>  		if (clk > 0)
>  			seq_printf(m, "\t\tMax dot clock: %d kHz\n", clk);
>  
> +		clk = drm_dp_downstream_max_tmds_clock(dpcd, port_cap, edid);
> +		if (clk > 0)
> +			seq_printf(m, "\t\tMax TMDS clock: %d kHz\n", clk);
> +
> +		clk = drm_dp_downstream_min_tmds_clock(dpcd, port_cap, edid);
> +		if (clk > 0)
> +			seq_printf(m, "\t\tMin TMDS clock: %d kHz\n", clk);
> +
>  		bpc = drm_dp_downstream_max_bpc(dpcd, port_cap, edid);
>  
>  		if (bpc > 0)
> diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
> index 19bc04207788..6812a3e0de8d 100644
> --- a/include/drm/drm_dp_helper.h
> +++ b/include/drm/drm_dp_helper.h
> @@ -1645,6 +1645,12 @@ bool drm_dp_downstream_is_tmds(const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
>  			       const struct edid *edid);
>  int drm_dp_downstream_max_dotclock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
>  				   const u8 port_cap[4]);
> +int drm_dp_downstream_max_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> +				     const u8 port_cap[4],
> +				     const struct edid *edid);
> +int drm_dp_downstream_min_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> +				     const u8 port_cap[4],
> +				     const struct edid *edid);
>  int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
>  			      const u8 port_cap[4],
>  			      const struct edid *edid);
-- 
Cheers,
	Lyude Paul (she/her)
	Software Engineer at Red Hat

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v2 10/18] drm/dp: Add drm_dp_downstream_{min,max}_tmds_clock()
  2020-09-04 11:53   ` [Intel-gfx] " Ville Syrjala
@ 2020-09-08 18:08     ` Lyude Paul
  -1 siblings, 0 replies; 76+ messages in thread
From: Lyude Paul @ 2020-09-08 18:08 UTC (permalink / raw)
  To: Ville Syrjala, dri-devel; +Cc: intel-gfx

On Fri, 2020-09-04 at 14:53 +0300, Ville Syrjala wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Add helpers to get the TMDS clock limits for HDMI/DVI downstream
> facing ports.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/drm_dp_helper.c | 116 ++++++++++++++++++++++++++++++++
>  include/drm/drm_dp_helper.h     |   6 ++
>  2 files changed, 122 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_dp_helper.c
> b/drivers/gpu/drm/drm_dp_helper.c
> index 822a30e609ef..f567428f2aef 100644
> --- a/drivers/gpu/drm/drm_dp_helper.c
> +++ b/drivers/gpu/drm/drm_dp_helper.c
> @@ -643,6 +643,114 @@ int drm_dp_downstream_max_dotclock(const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
>  }
>  EXPORT_SYMBOL(drm_dp_downstream_max_dotclock);
>  
> +/**
> + * drm_dp_downstream_max_tmds_clock() - extract downstream facing port max
> TMDS clock
> + * @dpcd: DisplayPort configuration data
> + * @port_cap: port capabilities
> + * @edid: EDID
> + *
> + * Returns HDMI/DVI downstream facing port max TMDS clock in kHz on
> success,
> + * or 0 if max TMDS clock not defined
> + */
> +int drm_dp_downstream_max_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> +				     const u8 port_cap[4],
> +				     const struct edid *edid)
> +{
> +	if (!drm_dp_is_branch(dpcd))
> +		return 0;
> +
> +	if (dpcd[DP_DPCD_REV] < 0x11) {
> +		switch (dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> DP_DWN_STRM_PORT_TYPE_MASK) {
> +		case DP_DWN_STRM_PORT_TYPE_TMDS:
> +			return 165000;
> +		default:
> +			return 0;
> +		}
> +	}
> +
> +	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
> +	case DP_DS_PORT_TYPE_DP_DUALMODE:
> +		if (is_edid_digital_input_dp(edid))
> +			return 0;
> +		/*
> +		 * It's left up to the driver to check the
> +		 * DP dual mode adapter's max TMDS clock.
> +		 *
> +		 * Unfortunatley it looks like branch devices
> +		 * may not fordward that the DP dual mode i2c
> +		 * access so we just usually get i2c nak :(
> +		 */
> +		fallthrough;
> +	case DP_DS_PORT_TYPE_HDMI:
> +		 /*
> +		  * We should perhaps assume 165 MHz when detailed cap
> +		  * info is not available. But looks like many typical
> +		  * branch devices fall into that category and so we'd
> +		  * probably end up with users complaining that they can't
> +		  * get high resolution modes with their favorite dongle.
> +		  *
> +		  * So let's limit to 300 MHz instead since DPCD 1.4
> +		  * HDMI 2.0 DFPs are required to have the detailed cap
> +		  * info. So it's more likely we're dealing with a HDMI 1.4
> +		  * compatible* device here.

Forgot to mention - not directly related to this series, there's some hidden
i2c bits that I think can also be probed for this sort of information on
passive adapters, I know amdgpu actually supports this. I wonder how many of
them also apply to older active adapters...

> +		  */
> +		if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
> +			return 300000;
> +		return port_cap[1] * 2500;
> +	case DP_DS_PORT_TYPE_DVI:
> +		if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
> +			return 165000;
> +		/* FIXME what to do about DVI dual link? */
> +		return port_cap[1] * 2500;
> +	default:
> +		return 0;
> +	}
> +}
> +EXPORT_SYMBOL(drm_dp_downstream_max_tmds_clock);
> +
> +/**
> + * drm_dp_downstream_min_tmds_clock() - extract downstream facing port min
> TMDS clock
> + * @dpcd: DisplayPort configuration data
> + * @port_cap: port capabilities
> + * @edid: EDID
> + *
> + * Returns HDMI/DVI downstream facing port min TMDS clock in kHz on
> success,
> + * or 0 if max TMDS clock not defined
> + */
> +int drm_dp_downstream_min_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> +				     const u8 port_cap[4],
> +				     const struct edid *edid)
> +{
> +	if (!drm_dp_is_branch(dpcd))
> +		return 0;
> +
> +	if (dpcd[DP_DPCD_REV] < 0x11) {
> +		switch (dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> DP_DWN_STRM_PORT_TYPE_MASK) {
> +		case DP_DWN_STRM_PORT_TYPE_TMDS:
> +			return 25000;
> +		default:
> +			return 0;
> +		}
> +	}
> +
> +	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
> +	case DP_DS_PORT_TYPE_DP_DUALMODE:
> +		if (is_edid_digital_input_dp(edid))
> +			return 0;
> +		fallthrough;
> +	case DP_DS_PORT_TYPE_DVI:
> +	case DP_DS_PORT_TYPE_HDMI:
> +		/*
> +		 * Unclear whether the protocol converter could
> +		 * utilize pixel replication. Assume it won't.
> +		 */
> +		return 25000;
> +	default:
> +		return 0;
> +	}
> +}
> +EXPORT_SYMBOL(drm_dp_downstream_min_tmds_clock);
> +
>  /**
>    * drm_dp_downstream_max_bpc() - extract downstream facing port max
>    *                               bits per component
> @@ -788,6 +896,14 @@ void drm_dp_downstream_debug(struct seq_file *m,
>  		if (clk > 0)
>  			seq_printf(m, "\t\tMax dot clock: %d kHz\n", clk);
>  
> +		clk = drm_dp_downstream_max_tmds_clock(dpcd, port_cap, edid);
> +		if (clk > 0)
> +			seq_printf(m, "\t\tMax TMDS clock: %d kHz\n", clk);
> +
> +		clk = drm_dp_downstream_min_tmds_clock(dpcd, port_cap, edid);
> +		if (clk > 0)
> +			seq_printf(m, "\t\tMin TMDS clock: %d kHz\n", clk);
> +
>  		bpc = drm_dp_downstream_max_bpc(dpcd, port_cap, edid);
>  
>  		if (bpc > 0)
> diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
> index 19bc04207788..6812a3e0de8d 100644
> --- a/include/drm/drm_dp_helper.h
> +++ b/include/drm/drm_dp_helper.h
> @@ -1645,6 +1645,12 @@ bool drm_dp_downstream_is_tmds(const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
>  			       const struct edid *edid);
>  int drm_dp_downstream_max_dotclock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
>  				   const u8 port_cap[4]);
> +int drm_dp_downstream_max_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> +				     const u8 port_cap[4],
> +				     const struct edid *edid);
> +int drm_dp_downstream_min_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> +				     const u8 port_cap[4],
> +				     const struct edid *edid);
>  int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
>  			      const u8 port_cap[4],
>  			      const struct edid *edid);
-- 
Cheers,
	Lyude Paul (she/her)
	Software Engineer at Red Hat

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Intel-gfx] [PATCH v2 10/18] drm/dp: Add drm_dp_downstream_{min, max}_tmds_clock()
@ 2020-09-08 18:08     ` Lyude Paul
  0 siblings, 0 replies; 76+ messages in thread
From: Lyude Paul @ 2020-09-08 18:08 UTC (permalink / raw)
  To: Ville Syrjala, dri-devel; +Cc: intel-gfx

On Fri, 2020-09-04 at 14:53 +0300, Ville Syrjala wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Add helpers to get the TMDS clock limits for HDMI/DVI downstream
> facing ports.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/drm_dp_helper.c | 116 ++++++++++++++++++++++++++++++++
>  include/drm/drm_dp_helper.h     |   6 ++
>  2 files changed, 122 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_dp_helper.c
> b/drivers/gpu/drm/drm_dp_helper.c
> index 822a30e609ef..f567428f2aef 100644
> --- a/drivers/gpu/drm/drm_dp_helper.c
> +++ b/drivers/gpu/drm/drm_dp_helper.c
> @@ -643,6 +643,114 @@ int drm_dp_downstream_max_dotclock(const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
>  }
>  EXPORT_SYMBOL(drm_dp_downstream_max_dotclock);
>  
> +/**
> + * drm_dp_downstream_max_tmds_clock() - extract downstream facing port max
> TMDS clock
> + * @dpcd: DisplayPort configuration data
> + * @port_cap: port capabilities
> + * @edid: EDID
> + *
> + * Returns HDMI/DVI downstream facing port max TMDS clock in kHz on
> success,
> + * or 0 if max TMDS clock not defined
> + */
> +int drm_dp_downstream_max_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> +				     const u8 port_cap[4],
> +				     const struct edid *edid)
> +{
> +	if (!drm_dp_is_branch(dpcd))
> +		return 0;
> +
> +	if (dpcd[DP_DPCD_REV] < 0x11) {
> +		switch (dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> DP_DWN_STRM_PORT_TYPE_MASK) {
> +		case DP_DWN_STRM_PORT_TYPE_TMDS:
> +			return 165000;
> +		default:
> +			return 0;
> +		}
> +	}
> +
> +	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
> +	case DP_DS_PORT_TYPE_DP_DUALMODE:
> +		if (is_edid_digital_input_dp(edid))
> +			return 0;
> +		/*
> +		 * It's left up to the driver to check the
> +		 * DP dual mode adapter's max TMDS clock.
> +		 *
> +		 * Unfortunatley it looks like branch devices
> +		 * may not fordward that the DP dual mode i2c
> +		 * access so we just usually get i2c nak :(
> +		 */
> +		fallthrough;
> +	case DP_DS_PORT_TYPE_HDMI:
> +		 /*
> +		  * We should perhaps assume 165 MHz when detailed cap
> +		  * info is not available. But looks like many typical
> +		  * branch devices fall into that category and so we'd
> +		  * probably end up with users complaining that they can't
> +		  * get high resolution modes with their favorite dongle.
> +		  *
> +		  * So let's limit to 300 MHz instead since DPCD 1.4
> +		  * HDMI 2.0 DFPs are required to have the detailed cap
> +		  * info. So it's more likely we're dealing with a HDMI 1.4
> +		  * compatible* device here.

Forgot to mention - not directly related to this series, there's some hidden
i2c bits that I think can also be probed for this sort of information on
passive adapters, I know amdgpu actually supports this. I wonder how many of
them also apply to older active adapters...

> +		  */
> +		if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
> +			return 300000;
> +		return port_cap[1] * 2500;
> +	case DP_DS_PORT_TYPE_DVI:
> +		if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
> +			return 165000;
> +		/* FIXME what to do about DVI dual link? */
> +		return port_cap[1] * 2500;
> +	default:
> +		return 0;
> +	}
> +}
> +EXPORT_SYMBOL(drm_dp_downstream_max_tmds_clock);
> +
> +/**
> + * drm_dp_downstream_min_tmds_clock() - extract downstream facing port min
> TMDS clock
> + * @dpcd: DisplayPort configuration data
> + * @port_cap: port capabilities
> + * @edid: EDID
> + *
> + * Returns HDMI/DVI downstream facing port min TMDS clock in kHz on
> success,
> + * or 0 if max TMDS clock not defined
> + */
> +int drm_dp_downstream_min_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> +				     const u8 port_cap[4],
> +				     const struct edid *edid)
> +{
> +	if (!drm_dp_is_branch(dpcd))
> +		return 0;
> +
> +	if (dpcd[DP_DPCD_REV] < 0x11) {
> +		switch (dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> DP_DWN_STRM_PORT_TYPE_MASK) {
> +		case DP_DWN_STRM_PORT_TYPE_TMDS:
> +			return 25000;
> +		default:
> +			return 0;
> +		}
> +	}
> +
> +	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
> +	case DP_DS_PORT_TYPE_DP_DUALMODE:
> +		if (is_edid_digital_input_dp(edid))
> +			return 0;
> +		fallthrough;
> +	case DP_DS_PORT_TYPE_DVI:
> +	case DP_DS_PORT_TYPE_HDMI:
> +		/*
> +		 * Unclear whether the protocol converter could
> +		 * utilize pixel replication. Assume it won't.
> +		 */
> +		return 25000;
> +	default:
> +		return 0;
> +	}
> +}
> +EXPORT_SYMBOL(drm_dp_downstream_min_tmds_clock);
> +
>  /**
>    * drm_dp_downstream_max_bpc() - extract downstream facing port max
>    *                               bits per component
> @@ -788,6 +896,14 @@ void drm_dp_downstream_debug(struct seq_file *m,
>  		if (clk > 0)
>  			seq_printf(m, "\t\tMax dot clock: %d kHz\n", clk);
>  
> +		clk = drm_dp_downstream_max_tmds_clock(dpcd, port_cap, edid);
> +		if (clk > 0)
> +			seq_printf(m, "\t\tMax TMDS clock: %d kHz\n", clk);
> +
> +		clk = drm_dp_downstream_min_tmds_clock(dpcd, port_cap, edid);
> +		if (clk > 0)
> +			seq_printf(m, "\t\tMin TMDS clock: %d kHz\n", clk);
> +
>  		bpc = drm_dp_downstream_max_bpc(dpcd, port_cap, edid);
>  
>  		if (bpc > 0)
> diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
> index 19bc04207788..6812a3e0de8d 100644
> --- a/include/drm/drm_dp_helper.h
> +++ b/include/drm/drm_dp_helper.h
> @@ -1645,6 +1645,12 @@ bool drm_dp_downstream_is_tmds(const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
>  			       const struct edid *edid);
>  int drm_dp_downstream_max_dotclock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
>  				   const u8 port_cap[4]);
> +int drm_dp_downstream_max_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> +				     const u8 port_cap[4],
> +				     const struct edid *edid);
> +int drm_dp_downstream_min_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> +				     const u8 port_cap[4],
> +				     const struct edid *edid);
>  int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
>  			      const u8 port_cap[4],
>  			      const struct edid *edid);
-- 
Cheers,
	Lyude Paul (she/her)
	Software Engineer at Red Hat

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v2 12/18] drm/i915: Configure DP 1.3+ protocol converted HDMI mode
  2020-09-04 11:53   ` [Intel-gfx] " Ville Syrjala
@ 2020-09-08 18:11     ` Lyude Paul
  -1 siblings, 0 replies; 76+ messages in thread
From: Lyude Paul @ 2020-09-08 18:11 UTC (permalink / raw)
  To: Ville Syrjala, dri-devel; +Cc: intel-gfx

On Fri, 2020-09-04 at 14:53 +0300, Ville Syrjala wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> DP 1.3 adds some extra control knobs for DP->HDMI protocol conversion.
> Let's use that to configure the "HDMI mode" (ie. infoframes vs. not)
> based on the capabilities of the sink.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_ddi.c |  1 +
>  drivers/gpu/drm/i915/display/intel_dp.c  | 23 +++++++++++++++++++++++
>  drivers/gpu/drm/i915/display/intel_dp.h  |  1 +
>  3 files changed, 25 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c
> b/drivers/gpu/drm/i915/display/intel_ddi.c
> index 28ff85493f25..9adba0d0b4aa 100644
> --- a/drivers/gpu/drm/i915/display/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/display/intel_ddi.c
> @@ -3470,6 +3470,7 @@ static void hsw_ddi_pre_enable_dp(struct
> intel_atomic_state *state,
>  	intel_ddi_init_dp_buf_reg(encoder);
>  	if (!is_mst)
>  		intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
> +	intel_dp_configure_protocol_converter(intel_dp);
>  	intel_dp_sink_set_decompression_state(intel_dp, crtc_state,
>  					      true);
>  	intel_dp_sink_set_fec_ready(intel_dp, crtc_state);
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c
> b/drivers/gpu/drm/i915/display/intel_dp.c
> index a703e4659e47..047449253a54 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -3792,6 +3792,28 @@ static void intel_dp_enable_port(struct intel_dp
> *intel_dp,
>  	intel_de_posting_read(dev_priv, intel_dp->output_reg);
>  }
>  
> +void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
> +	u8 tmp;
> +
> +	if (intel_dp->dpcd[DP_DPCD_REV] < 0x13)
> +		return;
> +
> +	if (!drm_dp_is_branch(intel_dp->dpcd))
> +		return;
> +
> +	tmp = intel_dp->has_hdmi_sink ?
> +		DP_HDMI_DVI_OUTPUT_CONFIG : 0;
> +
> +	if (drm_dp_dpcd_writeb(&intel_dp->aux,
> +			       DP_PROTOCOL_CONVERTER_CONTROL_0, tmp) <= 0)
> +		drm_dbg_kms(&i915->drm, "Failed to set protocol converter HDMI
> mode to %s\n",
> +			    enableddisabled(intel_dp->has_hdmi_sink));
> +
> +	/* TODO: configure YCbCr 4:2:2/4:2:0 conversion */
> +}

Maybe add a DP helper for this while we're at it? Up to you

> +
>  static void intel_enable_dp(struct intel_atomic_state *state,
>  			    struct intel_encoder *encoder,
>  			    const struct intel_crtc_state *pipe_config,
> @@ -3829,6 +3851,7 @@ static void intel_enable_dp(struct intel_atomic_state
> *state,
>  	}
>  
>  	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
> +	intel_dp_configure_protocol_converter(intel_dp);
>  	intel_dp_start_link_train(intel_dp);
>  	intel_dp_stop_link_train(intel_dp);
>  
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.h
> b/drivers/gpu/drm/i915/display/intel_dp.h
> index ec5688a21f66..08a1c0aa8b94 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.h
> +++ b/drivers/gpu/drm/i915/display/intel_dp.h
> @@ -51,6 +51,7 @@ int intel_dp_get_link_train_fallback_values(struct
> intel_dp *intel_dp,
>  int intel_dp_retrain_link(struct intel_encoder *encoder,
>  			  struct drm_modeset_acquire_ctx *ctx);
>  void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode);
> +void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp);
>  void intel_dp_sink_set_decompression_state(struct intel_dp *intel_dp,
>  					   const struct intel_crtc_state
> *crtc_state,
>  					   bool enable);
-- 
Cheers,
	Lyude Paul (she/her)
	Software Engineer at Red Hat

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Intel-gfx] [PATCH v2 12/18] drm/i915: Configure DP 1.3+ protocol converted HDMI mode
@ 2020-09-08 18:11     ` Lyude Paul
  0 siblings, 0 replies; 76+ messages in thread
From: Lyude Paul @ 2020-09-08 18:11 UTC (permalink / raw)
  To: Ville Syrjala, dri-devel; +Cc: intel-gfx

On Fri, 2020-09-04 at 14:53 +0300, Ville Syrjala wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> DP 1.3 adds some extra control knobs for DP->HDMI protocol conversion.
> Let's use that to configure the "HDMI mode" (ie. infoframes vs. not)
> based on the capabilities of the sink.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_ddi.c |  1 +
>  drivers/gpu/drm/i915/display/intel_dp.c  | 23 +++++++++++++++++++++++
>  drivers/gpu/drm/i915/display/intel_dp.h  |  1 +
>  3 files changed, 25 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c
> b/drivers/gpu/drm/i915/display/intel_ddi.c
> index 28ff85493f25..9adba0d0b4aa 100644
> --- a/drivers/gpu/drm/i915/display/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/display/intel_ddi.c
> @@ -3470,6 +3470,7 @@ static void hsw_ddi_pre_enable_dp(struct
> intel_atomic_state *state,
>  	intel_ddi_init_dp_buf_reg(encoder);
>  	if (!is_mst)
>  		intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
> +	intel_dp_configure_protocol_converter(intel_dp);
>  	intel_dp_sink_set_decompression_state(intel_dp, crtc_state,
>  					      true);
>  	intel_dp_sink_set_fec_ready(intel_dp, crtc_state);
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c
> b/drivers/gpu/drm/i915/display/intel_dp.c
> index a703e4659e47..047449253a54 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -3792,6 +3792,28 @@ static void intel_dp_enable_port(struct intel_dp
> *intel_dp,
>  	intel_de_posting_read(dev_priv, intel_dp->output_reg);
>  }
>  
> +void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
> +	u8 tmp;
> +
> +	if (intel_dp->dpcd[DP_DPCD_REV] < 0x13)
> +		return;
> +
> +	if (!drm_dp_is_branch(intel_dp->dpcd))
> +		return;
> +
> +	tmp = intel_dp->has_hdmi_sink ?
> +		DP_HDMI_DVI_OUTPUT_CONFIG : 0;
> +
> +	if (drm_dp_dpcd_writeb(&intel_dp->aux,
> +			       DP_PROTOCOL_CONVERTER_CONTROL_0, tmp) <= 0)
> +		drm_dbg_kms(&i915->drm, "Failed to set protocol converter HDMI
> mode to %s\n",
> +			    enableddisabled(intel_dp->has_hdmi_sink));
> +
> +	/* TODO: configure YCbCr 4:2:2/4:2:0 conversion */
> +}

Maybe add a DP helper for this while we're at it? Up to you

> +
>  static void intel_enable_dp(struct intel_atomic_state *state,
>  			    struct intel_encoder *encoder,
>  			    const struct intel_crtc_state *pipe_config,
> @@ -3829,6 +3851,7 @@ static void intel_enable_dp(struct intel_atomic_state
> *state,
>  	}
>  
>  	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
> +	intel_dp_configure_protocol_converter(intel_dp);
>  	intel_dp_start_link_train(intel_dp);
>  	intel_dp_stop_link_train(intel_dp);
>  
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.h
> b/drivers/gpu/drm/i915/display/intel_dp.h
> index ec5688a21f66..08a1c0aa8b94 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.h
> +++ b/drivers/gpu/drm/i915/display/intel_dp.h
> @@ -51,6 +51,7 @@ int intel_dp_get_link_train_fallback_values(struct
> intel_dp *intel_dp,
>  int intel_dp_retrain_link(struct intel_encoder *encoder,
>  			  struct drm_modeset_acquire_ctx *ctx);
>  void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode);
> +void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp);
>  void intel_dp_sink_set_decompression_state(struct intel_dp *intel_dp,
>  					   const struct intel_crtc_state
> *crtc_state,
>  					   bool enable);
-- 
Cheers,
	Lyude Paul (she/her)
	Software Engineer at Red Hat

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v2 13/18] drm/dp: Add drm_dp_downstream_mode()
  2020-09-04 11:53   ` [Intel-gfx] " Ville Syrjala
@ 2020-09-08 18:13     ` Lyude Paul
  -1 siblings, 0 replies; 76+ messages in thread
From: Lyude Paul @ 2020-09-08 18:13 UTC (permalink / raw)
  To: Ville Syrjala, dri-devel; +Cc: intel-gfx

On Fri, 2020-09-04 at 14:53 +0300, Ville Syrjala wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> The downstream facing port caps in the DPCD can give us a hint
> as to what kind of display mode the sink can use if it doesn't
> have an EDID. Use that information to pick a suitable mode.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/drm_dp_helper.c | 54 +++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/drm_edid.c      | 19 ++++++++++++
>  include/drm/drm_dp_helper.h     | 12 ++++++++
>  include/drm/drm_edid.h          |  4 +++
>  4 files changed, 89 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_dp_helper.c
> b/drivers/gpu/drm/drm_dp_helper.c
> index f567428f2aef..0d5e9bcf11d0 100644
> --- a/drivers/gpu/drm/drm_dp_helper.c
> +++ b/drivers/gpu/drm/drm_dp_helper.c
> @@ -808,6 +808,60 @@ int drm_dp_downstream_max_bpc(const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
>  }
>  EXPORT_SYMBOL(drm_dp_downstream_max_bpc);
>  
> +/**
> + * drm_dp_downstream_mode() - return a mode for downstream facing port
> + * @dpcd: DisplayPort configuration data
> + * @port_cap: port capabilities
> + *
> + * Provides a suitable mode for downstream facing ports without EDID.
> + *
> + * Returns a new drm_display_mode on success or NULL on failure
> + */
> +struct drm_display_mode *
> +drm_dp_downstream_mode(struct drm_device *dev,
> +		       const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> +		       const u8 port_cap[4])
> +
> +{
> +	u8 vic;
> +
> +	if (!drm_dp_is_branch(dpcd))
> +		return NULL;
> +
> +	if (dpcd[DP_DPCD_REV] < 0x11)
> +		return NULL;
> +
> +	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
> +	case DP_DS_PORT_TYPE_NON_EDID:
> +		switch (port_cap[0] & DP_DS_NON_EDID_MASK) {
> +		case DP_DS_NON_EDID_720x480i_60:
> +			vic = 6;
> +			break;
> +		case DP_DS_NON_EDID_720x480i_50:
> +			vic = 21;
> +			break;
> +		case DP_DS_NON_EDID_1920x1080i_60:
> +			vic = 5;
> +			break;
> +		case DP_DS_NON_EDID_1920x1080i_50:
> +			vic = 20;
> +			break;
> +		case DP_DS_NON_EDID_1280x720_60:
> +			vic = 4;
> +			break;
> +		case DP_DS_NON_EDID_1280x720_50:
> +			vic = 19;
> +			break;
> +		default:
> +			return NULL;
> +		}
> +		return drm_display_mode_from_cea_vic(dev, vic);
> +	default:
> +		return NULL;
> +	}
> +}
> +EXPORT_SYMBOL(drm_dp_downstream_mode);
> +
>  /**
>   * drm_dp_downstream_id() - identify branch device
>   * @aux: DisplayPort AUX channel
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index 6840f0530a38..b9419fed6c28 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -3738,6 +3738,25 @@ drm_add_cmdb_modes(struct drm_connector *connector,
> u8 svd)
>  	bitmap_set(hdmi->y420_cmdb_modes, vic, 1);
>  }
>  
> +struct drm_display_mode *
> +drm_display_mode_from_cea_vic(struct drm_device *dev,
> +			      u8 video_code)
> +{
> +	const struct drm_display_mode *cea_mode;
> +	struct drm_display_mode *newmode;
> +
> +	cea_mode = cea_mode_for_vic(video_code);
> +	if (!cea_mode)
> +		return NULL;
> +
> +	newmode = drm_mode_duplicate(dev, cea_mode);
> +	if (!newmode)
> +		return NULL;
> +
> +	return newmode;
> +}
> +EXPORT_SYMBOL(drm_display_mode_from_cea_vic);

Forgot the kdocs

> +
>  static int
>  do_cea_modes(struct drm_connector *connector, const u8 *db, u8 len)
>  {
> diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
> index 6812a3e0de8d..fbba4a0f7366 100644
> --- a/include/drm/drm_dp_helper.h
> +++ b/include/drm/drm_dp_helper.h
> @@ -28,6 +28,8 @@
>  #include <linux/types.h>
>  #include <drm/drm_connector.h>
>  
> +struct drm_device;
> +
>  /*
>   * Unless otherwise noted, all values are from the DP 1.1a spec.  Note that
>   * DP and DPCD versions are independent.  Differences from 1.0 are not
> noted,
> @@ -385,6 +387,13 @@
>  # define DP_DS_PORT_TYPE_DP_DUALMODE        5
>  # define DP_DS_PORT_TYPE_WIRELESS           6
>  # define DP_DS_PORT_HPD			    (1 << 3)
> +# define DP_DS_NON_EDID_MASK		    (0xf << 4)
> +# define DP_DS_NON_EDID_720x480i_60	    (1 << 4)
> +# define DP_DS_NON_EDID_720x480i_50	    (2 << 4)
> +# define DP_DS_NON_EDID_1920x1080i_60	    (3 << 4)
> +# define DP_DS_NON_EDID_1920x1080i_50	    (4 << 4)
> +# define DP_DS_NON_EDID_1280x720_60	    (5 << 4)
> +# define DP_DS_NON_EDID_1280x720_50	    (7 << 4)
>  /* offset 1 for VGA is maximum megapixels per second / 8 */
>  /* offset 1 for DVI/HDMI is maximum TMDS clock in Mbps / 2.5 */
>  /* offset 2 for VGA/DVI/HDMI */
> @@ -1654,6 +1663,9 @@ int drm_dp_downstream_min_tmds_clock(const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
>  int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
>  			      const u8 port_cap[4],
>  			      const struct edid *edid);
> +struct drm_display_mode *drm_dp_downstream_mode(struct drm_device *dev,
> +						const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
> +						const u8 port_cap[4]);
>  int drm_dp_downstream_id(struct drm_dp_aux *aux, char id[6]);
>  void drm_dp_downstream_debug(struct seq_file *m,
>  			     const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
> index cfa4f5af49af..b27a0e2169c8 100644
> --- a/include/drm/drm_edid.h
> +++ b/include/drm/drm_edid.h
> @@ -517,4 +517,8 @@ 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);
> +struct drm_display_mode *
> +drm_display_mode_from_cea_vic(struct drm_device *dev,
> +			      u8 video_code);
> +
>  #endif /* __DRM_EDID_H__ */
-- 
Cheers,
	Lyude Paul (she/her)
	Software Engineer at Red Hat

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Intel-gfx] [PATCH v2 13/18] drm/dp: Add drm_dp_downstream_mode()
@ 2020-09-08 18:13     ` Lyude Paul
  0 siblings, 0 replies; 76+ messages in thread
From: Lyude Paul @ 2020-09-08 18:13 UTC (permalink / raw)
  To: Ville Syrjala, dri-devel; +Cc: intel-gfx

On Fri, 2020-09-04 at 14:53 +0300, Ville Syrjala wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> The downstream facing port caps in the DPCD can give us a hint
> as to what kind of display mode the sink can use if it doesn't
> have an EDID. Use that information to pick a suitable mode.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/drm_dp_helper.c | 54 +++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/drm_edid.c      | 19 ++++++++++++
>  include/drm/drm_dp_helper.h     | 12 ++++++++
>  include/drm/drm_edid.h          |  4 +++
>  4 files changed, 89 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_dp_helper.c
> b/drivers/gpu/drm/drm_dp_helper.c
> index f567428f2aef..0d5e9bcf11d0 100644
> --- a/drivers/gpu/drm/drm_dp_helper.c
> +++ b/drivers/gpu/drm/drm_dp_helper.c
> @@ -808,6 +808,60 @@ int drm_dp_downstream_max_bpc(const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
>  }
>  EXPORT_SYMBOL(drm_dp_downstream_max_bpc);
>  
> +/**
> + * drm_dp_downstream_mode() - return a mode for downstream facing port
> + * @dpcd: DisplayPort configuration data
> + * @port_cap: port capabilities
> + *
> + * Provides a suitable mode for downstream facing ports without EDID.
> + *
> + * Returns a new drm_display_mode on success or NULL on failure
> + */
> +struct drm_display_mode *
> +drm_dp_downstream_mode(struct drm_device *dev,
> +		       const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> +		       const u8 port_cap[4])
> +
> +{
> +	u8 vic;
> +
> +	if (!drm_dp_is_branch(dpcd))
> +		return NULL;
> +
> +	if (dpcd[DP_DPCD_REV] < 0x11)
> +		return NULL;
> +
> +	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
> +	case DP_DS_PORT_TYPE_NON_EDID:
> +		switch (port_cap[0] & DP_DS_NON_EDID_MASK) {
> +		case DP_DS_NON_EDID_720x480i_60:
> +			vic = 6;
> +			break;
> +		case DP_DS_NON_EDID_720x480i_50:
> +			vic = 21;
> +			break;
> +		case DP_DS_NON_EDID_1920x1080i_60:
> +			vic = 5;
> +			break;
> +		case DP_DS_NON_EDID_1920x1080i_50:
> +			vic = 20;
> +			break;
> +		case DP_DS_NON_EDID_1280x720_60:
> +			vic = 4;
> +			break;
> +		case DP_DS_NON_EDID_1280x720_50:
> +			vic = 19;
> +			break;
> +		default:
> +			return NULL;
> +		}
> +		return drm_display_mode_from_cea_vic(dev, vic);
> +	default:
> +		return NULL;
> +	}
> +}
> +EXPORT_SYMBOL(drm_dp_downstream_mode);
> +
>  /**
>   * drm_dp_downstream_id() - identify branch device
>   * @aux: DisplayPort AUX channel
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index 6840f0530a38..b9419fed6c28 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -3738,6 +3738,25 @@ drm_add_cmdb_modes(struct drm_connector *connector,
> u8 svd)
>  	bitmap_set(hdmi->y420_cmdb_modes, vic, 1);
>  }
>  
> +struct drm_display_mode *
> +drm_display_mode_from_cea_vic(struct drm_device *dev,
> +			      u8 video_code)
> +{
> +	const struct drm_display_mode *cea_mode;
> +	struct drm_display_mode *newmode;
> +
> +	cea_mode = cea_mode_for_vic(video_code);
> +	if (!cea_mode)
> +		return NULL;
> +
> +	newmode = drm_mode_duplicate(dev, cea_mode);
> +	if (!newmode)
> +		return NULL;
> +
> +	return newmode;
> +}
> +EXPORT_SYMBOL(drm_display_mode_from_cea_vic);

Forgot the kdocs

> +
>  static int
>  do_cea_modes(struct drm_connector *connector, const u8 *db, u8 len)
>  {
> diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
> index 6812a3e0de8d..fbba4a0f7366 100644
> --- a/include/drm/drm_dp_helper.h
> +++ b/include/drm/drm_dp_helper.h
> @@ -28,6 +28,8 @@
>  #include <linux/types.h>
>  #include <drm/drm_connector.h>
>  
> +struct drm_device;
> +
>  /*
>   * Unless otherwise noted, all values are from the DP 1.1a spec.  Note that
>   * DP and DPCD versions are independent.  Differences from 1.0 are not
> noted,
> @@ -385,6 +387,13 @@
>  # define DP_DS_PORT_TYPE_DP_DUALMODE        5
>  # define DP_DS_PORT_TYPE_WIRELESS           6
>  # define DP_DS_PORT_HPD			    (1 << 3)
> +# define DP_DS_NON_EDID_MASK		    (0xf << 4)
> +# define DP_DS_NON_EDID_720x480i_60	    (1 << 4)
> +# define DP_DS_NON_EDID_720x480i_50	    (2 << 4)
> +# define DP_DS_NON_EDID_1920x1080i_60	    (3 << 4)
> +# define DP_DS_NON_EDID_1920x1080i_50	    (4 << 4)
> +# define DP_DS_NON_EDID_1280x720_60	    (5 << 4)
> +# define DP_DS_NON_EDID_1280x720_50	    (7 << 4)
>  /* offset 1 for VGA is maximum megapixels per second / 8 */
>  /* offset 1 for DVI/HDMI is maximum TMDS clock in Mbps / 2.5 */
>  /* offset 2 for VGA/DVI/HDMI */
> @@ -1654,6 +1663,9 @@ int drm_dp_downstream_min_tmds_clock(const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
>  int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
>  			      const u8 port_cap[4],
>  			      const struct edid *edid);
> +struct drm_display_mode *drm_dp_downstream_mode(struct drm_device *dev,
> +						const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
> +						const u8 port_cap[4]);
>  int drm_dp_downstream_id(struct drm_dp_aux *aux, char id[6]);
>  void drm_dp_downstream_debug(struct seq_file *m,
>  			     const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
> index cfa4f5af49af..b27a0e2169c8 100644
> --- a/include/drm/drm_edid.h
> +++ b/include/drm/drm_edid.h
> @@ -517,4 +517,8 @@ 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);
> +struct drm_display_mode *
> +drm_display_mode_from_cea_vic(struct drm_device *dev,
> +			      u8 video_code);
> +
>  #endif /* __DRM_EDID_H__ */
-- 
Cheers,
	Lyude Paul (she/her)
	Software Engineer at Red Hat

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v2 17/18] drm/dp: Add helpers for DFP YCbCr 4:2:0 handling
  2020-09-04 11:53   ` [Intel-gfx] " Ville Syrjala
@ 2020-09-08 18:15     ` Lyude Paul
  -1 siblings, 0 replies; 76+ messages in thread
From: Lyude Paul @ 2020-09-08 18:15 UTC (permalink / raw)
  To: Ville Syrjala, dri-devel; +Cc: intel-gfx

On Fri, 2020-09-04 at 14:53 +0300, Ville Syrjala wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Add helpers to determine whether the DFP supports
> YCbCr 4:2:0 passthrough or YCbCr 4:4:4->4:2:0 conversion.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/drm_dp_helper.c | 44 +++++++++++++++++++++++++++++++++
>  include/drm/drm_dp_helper.h     |  8 ++++++
>  2 files changed, 52 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_dp_helper.c
> b/drivers/gpu/drm/drm_dp_helper.c
> index 0d5e9bcf11d0..dc68e10aa1fd 100644
> --- a/drivers/gpu/drm/drm_dp_helper.c
> +++ b/drivers/gpu/drm/drm_dp_helper.c
> @@ -808,6 +808,50 @@ int drm_dp_downstream_max_bpc(const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
>  }
>  EXPORT_SYMBOL(drm_dp_downstream_max_bpc);
>  
> +bool drm_dp_downstream_420_passthrough(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> +				       const u8 port_cap[4])
> +{
> +	if (!drm_dp_is_branch(dpcd))
> +		return false;
> +
> +	if (dpcd[DP_DPCD_REV] < 0x13)
> +		return false;
> +
> +	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
> +	case DP_DS_PORT_TYPE_DP:
> +		return true;
> +	case DP_DS_PORT_TYPE_HDMI:
> +		if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
> +			return false;
> +
> +		return port_cap[3] & DP_DS_HDMI_YCBCR420_PASS_THROUGH;
> +	default:
> +		return false;
> +	}
> +}
> +EXPORT_SYMBOL(drm_dp_downstream_420_passthrough);

Forgot the kdocs again

> +
> +bool drm_dp_downstream_444_to_420_conversion(const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
> +					     const u8 port_cap[4])
> +{
> +	if (!drm_dp_is_branch(dpcd))
> +		return false;
> +
> +	if (dpcd[DP_DPCD_REV] < 0x13)
> +		return false;
> +
> +	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
> +	case DP_DS_PORT_TYPE_HDMI:
> +		if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
> +			return false;
> +
> +		return port_cap[3] & DP_DS_HDMI_YCBCR444_TO_420_CONV;
> +	default:
> +		return false;
> +	}
> +}
> +EXPORT_SYMBOL(drm_dp_downstream_444_to_420_conversion);
> +
>  /**
>   * drm_dp_downstream_mode() - return a mode for downstream facing port
>   * @dpcd: DisplayPort configuration data
> diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
> index fbba4a0f7366..c9f2851904d0 100644
> --- a/include/drm/drm_dp_helper.h
> +++ b/include/drm/drm_dp_helper.h
> @@ -407,6 +407,10 @@ struct drm_device;
>  # define DP_DS_DVI_HIGH_COLOR_DEPTH	    (1 << 2)
>  /* offset 3 for HDMI */
>  # define DP_DS_HDMI_FRAME_SEQ_TO_FRAME_PACK (1 << 0)
> +# define DP_DS_HDMI_YCBCR422_PASS_THROUGH   (1 << 1)
> +# define DP_DS_HDMI_YCBCR420_PASS_THROUGH   (1 << 2)
> +# define DP_DS_HDMI_YCBCR444_TO_422_CONV    (1 << 3)
> +# define DP_DS_HDMI_YCBCR444_TO_420_CONV    (1 << 4)
>  
>  #define DP_MAX_DOWNSTREAM_PORTS		    0x10
>  
> @@ -1663,6 +1667,10 @@ int drm_dp_downstream_min_tmds_clock(const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
>  int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
>  			      const u8 port_cap[4],
>  			      const struct edid *edid);
> +bool drm_dp_downstream_420_passthrough(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> +				       const u8 port_cap[4]);
> +bool drm_dp_downstream_444_to_420_conversion(const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
> +					     const u8 port_cap[4]);
>  struct drm_display_mode *drm_dp_downstream_mode(struct drm_device *dev,
>  						const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
>  						const u8 port_cap[4]);
-- 
Cheers,
	Lyude Paul (she/her)
	Software Engineer at Red Hat

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Intel-gfx] [PATCH v2 17/18] drm/dp: Add helpers for DFP YCbCr 4:2:0 handling
@ 2020-09-08 18:15     ` Lyude Paul
  0 siblings, 0 replies; 76+ messages in thread
From: Lyude Paul @ 2020-09-08 18:15 UTC (permalink / raw)
  To: Ville Syrjala, dri-devel; +Cc: intel-gfx

On Fri, 2020-09-04 at 14:53 +0300, Ville Syrjala wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Add helpers to determine whether the DFP supports
> YCbCr 4:2:0 passthrough or YCbCr 4:4:4->4:2:0 conversion.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/drm_dp_helper.c | 44 +++++++++++++++++++++++++++++++++
>  include/drm/drm_dp_helper.h     |  8 ++++++
>  2 files changed, 52 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_dp_helper.c
> b/drivers/gpu/drm/drm_dp_helper.c
> index 0d5e9bcf11d0..dc68e10aa1fd 100644
> --- a/drivers/gpu/drm/drm_dp_helper.c
> +++ b/drivers/gpu/drm/drm_dp_helper.c
> @@ -808,6 +808,50 @@ int drm_dp_downstream_max_bpc(const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
>  }
>  EXPORT_SYMBOL(drm_dp_downstream_max_bpc);
>  
> +bool drm_dp_downstream_420_passthrough(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> +				       const u8 port_cap[4])
> +{
> +	if (!drm_dp_is_branch(dpcd))
> +		return false;
> +
> +	if (dpcd[DP_DPCD_REV] < 0x13)
> +		return false;
> +
> +	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
> +	case DP_DS_PORT_TYPE_DP:
> +		return true;
> +	case DP_DS_PORT_TYPE_HDMI:
> +		if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
> +			return false;
> +
> +		return port_cap[3] & DP_DS_HDMI_YCBCR420_PASS_THROUGH;
> +	default:
> +		return false;
> +	}
> +}
> +EXPORT_SYMBOL(drm_dp_downstream_420_passthrough);

Forgot the kdocs again

> +
> +bool drm_dp_downstream_444_to_420_conversion(const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
> +					     const u8 port_cap[4])
> +{
> +	if (!drm_dp_is_branch(dpcd))
> +		return false;
> +
> +	if (dpcd[DP_DPCD_REV] < 0x13)
> +		return false;
> +
> +	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
> +	case DP_DS_PORT_TYPE_HDMI:
> +		if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
> +			return false;
> +
> +		return port_cap[3] & DP_DS_HDMI_YCBCR444_TO_420_CONV;
> +	default:
> +		return false;
> +	}
> +}
> +EXPORT_SYMBOL(drm_dp_downstream_444_to_420_conversion);
> +
>  /**
>   * drm_dp_downstream_mode() - return a mode for downstream facing port
>   * @dpcd: DisplayPort configuration data
> diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
> index fbba4a0f7366..c9f2851904d0 100644
> --- a/include/drm/drm_dp_helper.h
> +++ b/include/drm/drm_dp_helper.h
> @@ -407,6 +407,10 @@ struct drm_device;
>  # define DP_DS_DVI_HIGH_COLOR_DEPTH	    (1 << 2)
>  /* offset 3 for HDMI */
>  # define DP_DS_HDMI_FRAME_SEQ_TO_FRAME_PACK (1 << 0)
> +# define DP_DS_HDMI_YCBCR422_PASS_THROUGH   (1 << 1)
> +# define DP_DS_HDMI_YCBCR420_PASS_THROUGH   (1 << 2)
> +# define DP_DS_HDMI_YCBCR444_TO_422_CONV    (1 << 3)
> +# define DP_DS_HDMI_YCBCR444_TO_420_CONV    (1 << 4)
>  
>  #define DP_MAX_DOWNSTREAM_PORTS		    0x10
>  
> @@ -1663,6 +1667,10 @@ int drm_dp_downstream_min_tmds_clock(const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
>  int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
>  			      const u8 port_cap[4],
>  			      const struct edid *edid);
> +bool drm_dp_downstream_420_passthrough(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> +				       const u8 port_cap[4]);
> +bool drm_dp_downstream_444_to_420_conversion(const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
> +					     const u8 port_cap[4]);
>  struct drm_display_mode *drm_dp_downstream_mode(struct drm_device *dev,
>  						const u8
> dpcd[DP_RECEIVER_CAP_SIZE],
>  						const u8 port_cap[4]);
-- 
Cheers,
	Lyude Paul (she/her)
	Software Engineer at Red Hat

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v2 00/18] drm/i915: Pimp DP DFP handling
  2020-09-04 11:53 ` [Intel-gfx] " Ville Syrjala
@ 2020-09-08 18:34   ` Lyude Paul
  -1 siblings, 0 replies; 76+ messages in thread
From: Lyude Paul @ 2020-09-08 18:34 UTC (permalink / raw)
  To: Ville Syrjala, dri-devel; +Cc: intel-gfx

With the nitpicks addressed (note there were a couple of other spots where we
wanted to use Return: in the kdocs, but I didn't bother pointing all of them
out), all but patch 07 is:

Reviewed-by: Lyude Paul <lyude@redhat.com>

On Fri, 2020-09-04 at 14:53 +0300, Ville Syrjala wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Attempt to deal with DP downstream facing ports (DFP) more
> thoroughly. This involves reading more of the port caps
> and dealing with various clock/bpc limitations.
> 
> And we try to enable YCbCr 444->420 conversion for HDMI DFPs
> which could allow some 4k displays to actually use 4k on
> pre-icl hardware (which doesn't have native 420 output),
> assuming we don't run into some other hardware limits.
> 
> I dropped my earlier patches to also hook in the DP dual mode
> adapter probing since sadly I've not actually seen a DP->DP++
> dongle that passes through the i2c traffic for those.
> 
> Only pimped the SST side of things. Not sure what would
> be required to get it all working for MST.
> 
> Ville Syrjälä (18):
>   drm/dp: Dump downstream facing port caps
>   drm/i915/lspcon: Do not send infoframes to non-HDMI sinks
>   drm/dp: Define protocol converter DPCD registers
>   drm/dp: Define more downstream facing port caps
>   drm/i915: Reworkd DFP max bpc handling
>   drm/dp: Add helpers to identify downstream facing port types
>   drm/dp: Pimp drm_dp_downstream_max_bpc()
>   drm/dp: Redo drm_dp_downstream_max_clock() as
>     drm_dp_downstream_max_dotclock()
>   drm/i915: Reworkd DP DFP clock handling
>   drm/dp: Add drm_dp_downstream_{min,max}_tmds_clock()
>   drm/i915: Deal with TMDS DFP clock limits
>   drm/i915: Configure DP 1.3+ protocol converted HDMI mode
>   drm/dp: Add drm_dp_downstream_mode()
>   drm/i915: Handle downstream facing ports w/o EDID
>   drm/i915: Extract intel_hdmi_has_audio()
>   drm/i915: DP->HDMI TMDS clock limits vs. deep color
>   drm/dp: Add helpers for DFP YCbCr 4:2:0 handling
>   drm/i915: Do YCbCr 444->420 conversion via DP protocol converters
> 
>  drivers/gpu/drm/drm_dp_helper.c               | 382 +++++++++++++++---
>  drivers/gpu/drm/drm_edid.c                    |  19 +
>  drivers/gpu/drm/i915/display/intel_ddi.c      |  11 +-
>  .../drm/i915/display/intel_display_debugfs.c  |   3 +-
>  .../drm/i915/display/intel_display_types.h    |   9 +
>  drivers/gpu/drm/i915/display/intel_dp.c       | 304 +++++++++++---
>  drivers/gpu/drm/i915/display/intel_dp.h       |   1 +
>  drivers/gpu/drm/i915/display/intel_hdmi.c     |  82 ++--
>  drivers/gpu/drm/i915/display/intel_hdmi.h     |   2 +
>  include/drm/drm_dp_helper.h                   |  63 ++-
>  include/drm/drm_edid.h                        |   4 +
>  11 files changed, 738 insertions(+), 142 deletions(-)
> 
-- 
Cheers,
	Lyude Paul (she/her)
	Software Engineer at Red Hat

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Intel-gfx] [PATCH v2 00/18] drm/i915: Pimp DP DFP handling
@ 2020-09-08 18:34   ` Lyude Paul
  0 siblings, 0 replies; 76+ messages in thread
From: Lyude Paul @ 2020-09-08 18:34 UTC (permalink / raw)
  To: Ville Syrjala, dri-devel; +Cc: intel-gfx

With the nitpicks addressed (note there were a couple of other spots where we
wanted to use Return: in the kdocs, but I didn't bother pointing all of them
out), all but patch 07 is:

Reviewed-by: Lyude Paul <lyude@redhat.com>

On Fri, 2020-09-04 at 14:53 +0300, Ville Syrjala wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Attempt to deal with DP downstream facing ports (DFP) more
> thoroughly. This involves reading more of the port caps
> and dealing with various clock/bpc limitations.
> 
> And we try to enable YCbCr 444->420 conversion for HDMI DFPs
> which could allow some 4k displays to actually use 4k on
> pre-icl hardware (which doesn't have native 420 output),
> assuming we don't run into some other hardware limits.
> 
> I dropped my earlier patches to also hook in the DP dual mode
> adapter probing since sadly I've not actually seen a DP->DP++
> dongle that passes through the i2c traffic for those.
> 
> Only pimped the SST side of things. Not sure what would
> be required to get it all working for MST.
> 
> Ville Syrjälä (18):
>   drm/dp: Dump downstream facing port caps
>   drm/i915/lspcon: Do not send infoframes to non-HDMI sinks
>   drm/dp: Define protocol converter DPCD registers
>   drm/dp: Define more downstream facing port caps
>   drm/i915: Reworkd DFP max bpc handling
>   drm/dp: Add helpers to identify downstream facing port types
>   drm/dp: Pimp drm_dp_downstream_max_bpc()
>   drm/dp: Redo drm_dp_downstream_max_clock() as
>     drm_dp_downstream_max_dotclock()
>   drm/i915: Reworkd DP DFP clock handling
>   drm/dp: Add drm_dp_downstream_{min,max}_tmds_clock()
>   drm/i915: Deal with TMDS DFP clock limits
>   drm/i915: Configure DP 1.3+ protocol converted HDMI mode
>   drm/dp: Add drm_dp_downstream_mode()
>   drm/i915: Handle downstream facing ports w/o EDID
>   drm/i915: Extract intel_hdmi_has_audio()
>   drm/i915: DP->HDMI TMDS clock limits vs. deep color
>   drm/dp: Add helpers for DFP YCbCr 4:2:0 handling
>   drm/i915: Do YCbCr 444->420 conversion via DP protocol converters
> 
>  drivers/gpu/drm/drm_dp_helper.c               | 382 +++++++++++++++---
>  drivers/gpu/drm/drm_edid.c                    |  19 +
>  drivers/gpu/drm/i915/display/intel_ddi.c      |  11 +-
>  .../drm/i915/display/intel_display_debugfs.c  |   3 +-
>  .../drm/i915/display/intel_display_types.h    |   9 +
>  drivers/gpu/drm/i915/display/intel_dp.c       | 304 +++++++++++---
>  drivers/gpu/drm/i915/display/intel_dp.h       |   1 +
>  drivers/gpu/drm/i915/display/intel_hdmi.c     |  82 ++--
>  drivers/gpu/drm/i915/display/intel_hdmi.h     |   2 +
>  include/drm/drm_dp_helper.h                   |  63 ++-
>  include/drm/drm_edid.h                        |   4 +
>  11 files changed, 738 insertions(+), 142 deletions(-)
> 
-- 
Cheers,
	Lyude Paul (she/her)
	Software Engineer at Red Hat

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v2 10/18] drm/dp: Add drm_dp_downstream_{min,max}_tmds_clock()
  2020-09-08 18:08     ` [Intel-gfx] [PATCH v2 10/18] drm/dp: Add drm_dp_downstream_{min, max}_tmds_clock() Lyude Paul
@ 2020-09-10 13:55       ` Ville Syrjälä
  -1 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjälä @ 2020-09-10 13:55 UTC (permalink / raw)
  To: Lyude Paul; +Cc: intel-gfx, dri-devel

On Tue, Sep 08, 2020 at 02:08:17PM -0400, Lyude Paul wrote:
> On Fri, 2020-09-04 at 14:53 +0300, Ville Syrjala wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > Add helpers to get the TMDS clock limits for HDMI/DVI downstream
> > facing ports.
> > 
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/drm_dp_helper.c | 116 ++++++++++++++++++++++++++++++++
> >  include/drm/drm_dp_helper.h     |   6 ++
> >  2 files changed, 122 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/drm_dp_helper.c
> > b/drivers/gpu/drm/drm_dp_helper.c
> > index 822a30e609ef..f567428f2aef 100644
> > --- a/drivers/gpu/drm/drm_dp_helper.c
> > +++ b/drivers/gpu/drm/drm_dp_helper.c
> > @@ -643,6 +643,114 @@ int drm_dp_downstream_max_dotclock(const u8
> > dpcd[DP_RECEIVER_CAP_SIZE],
> >  }
> >  EXPORT_SYMBOL(drm_dp_downstream_max_dotclock);
> >  
> > +/**
> > + * drm_dp_downstream_max_tmds_clock() - extract downstream facing port max
> > TMDS clock
> > + * @dpcd: DisplayPort configuration data
> > + * @port_cap: port capabilities
> > + * @edid: EDID
> > + *
> > + * Returns HDMI/DVI downstream facing port max TMDS clock in kHz on
> > success,
> > + * or 0 if max TMDS clock not defined
> > + */
> > +int drm_dp_downstream_max_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > +				     const u8 port_cap[4],
> > +				     const struct edid *edid)
> > +{
> > +	if (!drm_dp_is_branch(dpcd))
> > +		return 0;
> > +
> > +	if (dpcd[DP_DPCD_REV] < 0x11) {
> > +		switch (dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> > DP_DWN_STRM_PORT_TYPE_MASK) {
> > +		case DP_DWN_STRM_PORT_TYPE_TMDS:
> > +			return 165000;
> > +		default:
> > +			return 0;
> > +		}
> > +	}
> > +
> > +	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
> > +	case DP_DS_PORT_TYPE_DP_DUALMODE:
> > +		if (is_edid_digital_input_dp(edid))
> > +			return 0;
> > +		/*
> > +		 * It's left up to the driver to check the
> > +		 * DP dual mode adapter's max TMDS clock.
> > +		 *
> > +		 * Unfortunatley it looks like branch devices
> > +		 * may not fordward that the DP dual mode i2c
> > +		 * access so we just usually get i2c nak :(
> > +		 */
> > +		fallthrough;
> > +	case DP_DS_PORT_TYPE_HDMI:
> > +		 /*
> > +		  * We should perhaps assume 165 MHz when detailed cap
> > +		  * info is not available. But looks like many typical
> > +		  * branch devices fall into that category and so we'd
> > +		  * probably end up with users complaining that they can't
> > +		  * get high resolution modes with their favorite dongle.
> > +		  *
> > +		  * So let's limit to 300 MHz instead since DPCD 1.4
> > +		  * HDMI 2.0 DFPs are required to have the detailed cap
> > +		  * info. So it's more likely we're dealing with a HDMI 1.4
> > +		  * compatible* device here.
> 
> Forgot to mention - not directly related to this series, there's some hidden
> i2c bits that I think can also be probed for this sort of information on
> passive adapters, I know amdgpu actually supports this. I wonder how many of
> them also apply to older active adapters...

Something other than the normal DP dual mode stuff?

-- 
Ville Syrjälä
Intel
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Intel-gfx] [PATCH v2 10/18] drm/dp: Add drm_dp_downstream_{min, max}_tmds_clock()
@ 2020-09-10 13:55       ` Ville Syrjälä
  0 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjälä @ 2020-09-10 13:55 UTC (permalink / raw)
  To: Lyude Paul; +Cc: intel-gfx, dri-devel

On Tue, Sep 08, 2020 at 02:08:17PM -0400, Lyude Paul wrote:
> On Fri, 2020-09-04 at 14:53 +0300, Ville Syrjala wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > Add helpers to get the TMDS clock limits for HDMI/DVI downstream
> > facing ports.
> > 
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/drm_dp_helper.c | 116 ++++++++++++++++++++++++++++++++
> >  include/drm/drm_dp_helper.h     |   6 ++
> >  2 files changed, 122 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/drm_dp_helper.c
> > b/drivers/gpu/drm/drm_dp_helper.c
> > index 822a30e609ef..f567428f2aef 100644
> > --- a/drivers/gpu/drm/drm_dp_helper.c
> > +++ b/drivers/gpu/drm/drm_dp_helper.c
> > @@ -643,6 +643,114 @@ int drm_dp_downstream_max_dotclock(const u8
> > dpcd[DP_RECEIVER_CAP_SIZE],
> >  }
> >  EXPORT_SYMBOL(drm_dp_downstream_max_dotclock);
> >  
> > +/**
> > + * drm_dp_downstream_max_tmds_clock() - extract downstream facing port max
> > TMDS clock
> > + * @dpcd: DisplayPort configuration data
> > + * @port_cap: port capabilities
> > + * @edid: EDID
> > + *
> > + * Returns HDMI/DVI downstream facing port max TMDS clock in kHz on
> > success,
> > + * or 0 if max TMDS clock not defined
> > + */
> > +int drm_dp_downstream_max_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > +				     const u8 port_cap[4],
> > +				     const struct edid *edid)
> > +{
> > +	if (!drm_dp_is_branch(dpcd))
> > +		return 0;
> > +
> > +	if (dpcd[DP_DPCD_REV] < 0x11) {
> > +		switch (dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> > DP_DWN_STRM_PORT_TYPE_MASK) {
> > +		case DP_DWN_STRM_PORT_TYPE_TMDS:
> > +			return 165000;
> > +		default:
> > +			return 0;
> > +		}
> > +	}
> > +
> > +	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
> > +	case DP_DS_PORT_TYPE_DP_DUALMODE:
> > +		if (is_edid_digital_input_dp(edid))
> > +			return 0;
> > +		/*
> > +		 * It's left up to the driver to check the
> > +		 * DP dual mode adapter's max TMDS clock.
> > +		 *
> > +		 * Unfortunatley it looks like branch devices
> > +		 * may not fordward that the DP dual mode i2c
> > +		 * access so we just usually get i2c nak :(
> > +		 */
> > +		fallthrough;
> > +	case DP_DS_PORT_TYPE_HDMI:
> > +		 /*
> > +		  * We should perhaps assume 165 MHz when detailed cap
> > +		  * info is not available. But looks like many typical
> > +		  * branch devices fall into that category and so we'd
> > +		  * probably end up with users complaining that they can't
> > +		  * get high resolution modes with their favorite dongle.
> > +		  *
> > +		  * So let's limit to 300 MHz instead since DPCD 1.4
> > +		  * HDMI 2.0 DFPs are required to have the detailed cap
> > +		  * info. So it's more likely we're dealing with a HDMI 1.4
> > +		  * compatible* device here.
> 
> Forgot to mention - not directly related to this series, there's some hidden
> i2c bits that I think can also be probed for this sort of information on
> passive adapters, I know amdgpu actually supports this. I wonder how many of
> them also apply to older active adapters...

Something other than the normal DP dual mode stuff?

-- 
Ville Syrjälä
Intel
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v2 07/18] drm/dp: Pimp drm_dp_downstream_max_bpc()
  2020-09-08 17:51     ` [Intel-gfx] " Lyude Paul
@ 2020-09-10 14:46       ` Ville Syrjälä
  -1 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjälä @ 2020-09-10 14:46 UTC (permalink / raw)
  To: Lyude Paul; +Cc: intel-gfx, dri-devel

On Tue, Sep 08, 2020 at 01:51:56PM -0400, Lyude Paul wrote:
> On Fri, 2020-09-04 at 14:53 +0300, Ville Syrjala wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > Deal with more cases in drm_dp_downstream_max_bpc():
> > - DPCD 1.0 -> assume 8bpc for non-DP
> > - DPCD 1.1+ DP (or DP++ with DP sink) -> allow anything
> > - DPCD 1.1+ TMDS -> check the caps, assume 8bpc if the value is crap
> > - anything else -> assume 8bpc
> > 
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/drm_dp_helper.c               | 69 +++++++++++--------
> >  .../drm/i915/display/intel_display_debugfs.c  |  3 +-
> >  drivers/gpu/drm/i915/display/intel_dp.c       |  2 +-
> >  include/drm/drm_dp_helper.h                   | 10 ++-
> >  4 files changed, 51 insertions(+), 33 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/drm_dp_helper.c
> > b/drivers/gpu/drm/drm_dp_helper.c
> > index 0fcb94f7dbe5..ab87209c25d8 100644
> > --- a/drivers/gpu/drm/drm_dp_helper.c
> > +++ b/drivers/gpu/drm/drm_dp_helper.c
> > @@ -653,36 +653,44 @@ int drm_dp_downstream_max_clock(const u8
> > dpcd[DP_RECEIVER_CAP_SIZE],
> >  EXPORT_SYMBOL(drm_dp_downstream_max_clock);
> >  
> >  /**
> > - * drm_dp_downstream_max_bpc() - extract branch device max
> > - *                               bits per component
> > - * @dpcd: DisplayPort configuration data
> > - * @port_cap: port capabilities
> > - *
> > - * See also:
> > - * drm_dp_read_downstream_info()
> > - * drm_dp_downstream_max_clock()
> > - *
> > - * Returns: Max bpc on success or 0 if max bpc not defined
> > - */
> > +  * drm_dp_downstream_max_bpc() - extract downstream facing port max
> > +  *                               bits per component
> > +  * @dpcd: DisplayPort configuration data
> > +  * @port_cap: downstream facing port capabilities
> > +  * @edid: EDID
> > +  *
> > +  * Returns max bpc on success or 0 if max bpc not defined
> > +  */
> >  int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > -			      const u8 port_cap[4])
> > +			      const u8 port_cap[4],
> > +			      const struct edid *edid)
> >  {
> > -	int type = port_cap[0] & DP_DS_PORT_TYPE_MASK;
> > -	bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> > -		DP_DETAILED_CAP_INFO_AVAILABLE;
> > -	int bpc;
> > -
> > -	if (!detailed_cap_info)
> 
> I don't think we can drop this check. There's a somewhat surprising blurb
> about downstream port caps in the DP 2.0 spec (section 5.3.3.1):
> 
>    In addition, the adapter shall set the Detailed Capabilities Info registers
>    (DPCD Addresses 00080h through 0008Fh) to show all the downstream types,
>    including DFP 0. Either one or four bytes are used, per DFP type
>    indication. Therefore, up to 16 (with 1-byte descriptor) or four (with 4-
>    byte descriptor) DFP capabilities can be stored.
> 
> I've never once actually seen a sink do this, but this does mean it's
> technically possible tthat if we don't check the detailed caps bit then we
> might end up reading another port's DFP type instead of max_bpc info. Note
> though that we can make the assumption the four byte version of the field is
> used for DP 1.4+

The check is now ...


> 
> > +	if (!drm_dp_is_branch(dpcd))
> >  		return 0;
> >  
> > -	switch (type) {
> > -	case DP_DS_PORT_TYPE_VGA:
> > -	case DP_DS_PORT_TYPE_DVI:
> > -	case DP_DS_PORT_TYPE_HDMI:
> > +	if (dpcd[DP_DPCD_REV] < 0x11) {
> > +		switch (dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> > DP_DWN_STRM_PORT_TYPE_MASK) {
> > +		case DP_DWN_STRM_PORT_TYPE_DP:
> > +			return 0;
> > +		default:
> > +			return 8;
> > +		}
> > +	}
> > +
> > +	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
> > +	case DP_DS_PORT_TYPE_DP:
> > +		return 0;
> >  	case DP_DS_PORT_TYPE_DP_DUALMODE:
> > -		bpc = port_cap[2] & DP_DS_MAX_BPC_MASK;
> > +		if (is_edid_digital_input_dp(edid))
> > +			return 0;
> > +		fallthrough;
> > +	case DP_DS_PORT_TYPE_HDMI:
> > +	case DP_DS_PORT_TYPE_DVI:
> > +	case DP_DS_PORT_TYPE_VGA:
> > +		if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> > DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
> > +			return 8;

... here


> >  
> > -		switch (bpc) {
> > +		switch (port_cap[2] & DP_DS_MAX_BPC_MASK) {
> >  		case DP_DS_8BPC:
> >  			return 8;
> >  		case DP_DS_10BPC:
> > @@ -691,10 +699,12 @@ int drm_dp_downstream_max_bpc(const u8
> > dpcd[DP_RECEIVER_CAP_SIZE],
> >  			return 12;
> >  		case DP_DS_16BPC:
> >  			return 16;
> > +		default:
> > +			return 8;
> >  		}
> > -		fallthrough;
> > +		break;
> >  	default:
> > -		return 0;
> > +		return 8;
> >  	}
> >  }
> >  EXPORT_SYMBOL(drm_dp_downstream_max_bpc);
> > @@ -717,12 +727,15 @@ EXPORT_SYMBOL(drm_dp_downstream_id);
> >   * @m: pointer for debugfs file
> >   * @dpcd: DisplayPort configuration data
> >   * @port_cap: port capabilities
> > + * @edid: EDID
> >   * @aux: DisplayPort AUX channel
> >   *
> >   */
> >  void drm_dp_downstream_debug(struct seq_file *m,
> >  			     const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > -			     const u8 port_cap[4], struct drm_dp_aux *aux)
> > +			     const u8 port_cap[4],
> > +			     const struct edid *edid,
> > +			     struct drm_dp_aux *aux)
> >  {
> >  	bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> >  				 DP_DETAILED_CAP_INFO_AVAILABLE;
> > @@ -789,7 +802,7 @@ void drm_dp_downstream_debug(struct seq_file *m,
> >  				seq_printf(m, "\t\tMax TMDS clock: %d kHz\n",
> > clk);
> >  		}
> >  
> > -		bpc = drm_dp_downstream_max_bpc(dpcd, port_cap);
> > +		bpc = drm_dp_downstream_max_bpc(dpcd, port_cap, edid);
> >  
> >  		if (bpc > 0)
> >  			seq_printf(m, "\t\tMax bpc: %d\n", bpc);
> > diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> > b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> > index 53a0a3d9a22d..0bf31f9a8af5 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> > +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> > @@ -626,6 +626,7 @@ static void intel_dp_info(struct seq_file *m,
> >  {
> >  	struct intel_encoder *intel_encoder =
> > intel_attached_encoder(intel_connector);
> >  	struct intel_dp *intel_dp = enc_to_intel_dp(intel_encoder);
> > +	const struct drm_property_blob *edid = intel_connector-
> > >base.edid_blob_ptr;
> >  
> >  	seq_printf(m, "\tDPCD rev: %x\n", intel_dp->dpcd[DP_DPCD_REV]);
> >  	seq_printf(m, "\taudio support: %s\n", yesno(intel_dp->has_audio));
> > @@ -633,7 +634,7 @@ static void intel_dp_info(struct seq_file *m,
> >  		intel_panel_info(m, &intel_connector->panel);
> >  
> >  	drm_dp_downstream_debug(m, intel_dp->dpcd, intel_dp->downstream_ports,
> > -				&intel_dp->aux);
> > +				edid ? edid->data : NULL, &intel_dp->aux);
> >  }
> >  
> >  static void intel_dp_mst_info(struct seq_file *m,
> > diff --git a/drivers/gpu/drm/i915/display/intel_dp.c
> > b/drivers/gpu/drm/i915/display/intel_dp.c
> > index 2c8e82d97a34..c73b3efd84e0 100644
> > --- a/drivers/gpu/drm/i915/display/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> > @@ -6071,7 +6071,7 @@ intel_dp_set_edid(struct intel_dp *intel_dp)
> >  
> >  	intel_dp->dfp.max_bpc =
> >  		drm_dp_downstream_max_bpc(intel_dp->dpcd,
> > -					  intel_dp->downstream_ports);
> > +					  intel_dp->downstream_ports, edid);
> >  
> >  	drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] DFP max bpc %d\n",
> >  		    connector->base.base.id, connector->base.name,
> > diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
> > index 4f946826dfce..6218de1294c1 100644
> > --- a/include/drm/drm_dp_helper.h
> > +++ b/include/drm/drm_dp_helper.h
> > @@ -1646,10 +1646,14 @@ bool drm_dp_downstream_is_tmds(const u8
> > dpcd[DP_RECEIVER_CAP_SIZE],
> >  int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> >  				const u8 port_cap[4]);
> >  int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > -			      const u8 port_cap[4]);
> > +			      const u8 port_cap[4],
> > +			      const struct edid *edid);
> >  int drm_dp_downstream_id(struct drm_dp_aux *aux, char id[6]);
> > -void drm_dp_downstream_debug(struct seq_file *m, const u8
> > dpcd[DP_RECEIVER_CAP_SIZE],
> > -			     const u8 port_cap[4], struct drm_dp_aux *aux);
> > +void drm_dp_downstream_debug(struct seq_file *m,
> > +			     const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > +			     const u8 port_cap[4],
> > +			     const struct edid *edid,
> > +			     struct drm_dp_aux *aux);
> >  enum drm_mode_subconnector
> >  drm_dp_subconnector_type(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> >  			 const u8 port_cap[4]);
> -- 
> Cheers,
> 	Lyude Paul (she/her)
> 	Software Engineer at Red Hat

-- 
Ville Syrjälä
Intel
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Intel-gfx] [PATCH v2 07/18] drm/dp: Pimp drm_dp_downstream_max_bpc()
@ 2020-09-10 14:46       ` Ville Syrjälä
  0 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjälä @ 2020-09-10 14:46 UTC (permalink / raw)
  To: Lyude Paul; +Cc: intel-gfx, dri-devel

On Tue, Sep 08, 2020 at 01:51:56PM -0400, Lyude Paul wrote:
> On Fri, 2020-09-04 at 14:53 +0300, Ville Syrjala wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > Deal with more cases in drm_dp_downstream_max_bpc():
> > - DPCD 1.0 -> assume 8bpc for non-DP
> > - DPCD 1.1+ DP (or DP++ with DP sink) -> allow anything
> > - DPCD 1.1+ TMDS -> check the caps, assume 8bpc if the value is crap
> > - anything else -> assume 8bpc
> > 
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/drm_dp_helper.c               | 69 +++++++++++--------
> >  .../drm/i915/display/intel_display_debugfs.c  |  3 +-
> >  drivers/gpu/drm/i915/display/intel_dp.c       |  2 +-
> >  include/drm/drm_dp_helper.h                   | 10 ++-
> >  4 files changed, 51 insertions(+), 33 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/drm_dp_helper.c
> > b/drivers/gpu/drm/drm_dp_helper.c
> > index 0fcb94f7dbe5..ab87209c25d8 100644
> > --- a/drivers/gpu/drm/drm_dp_helper.c
> > +++ b/drivers/gpu/drm/drm_dp_helper.c
> > @@ -653,36 +653,44 @@ int drm_dp_downstream_max_clock(const u8
> > dpcd[DP_RECEIVER_CAP_SIZE],
> >  EXPORT_SYMBOL(drm_dp_downstream_max_clock);
> >  
> >  /**
> > - * drm_dp_downstream_max_bpc() - extract branch device max
> > - *                               bits per component
> > - * @dpcd: DisplayPort configuration data
> > - * @port_cap: port capabilities
> > - *
> > - * See also:
> > - * drm_dp_read_downstream_info()
> > - * drm_dp_downstream_max_clock()
> > - *
> > - * Returns: Max bpc on success or 0 if max bpc not defined
> > - */
> > +  * drm_dp_downstream_max_bpc() - extract downstream facing port max
> > +  *                               bits per component
> > +  * @dpcd: DisplayPort configuration data
> > +  * @port_cap: downstream facing port capabilities
> > +  * @edid: EDID
> > +  *
> > +  * Returns max bpc on success or 0 if max bpc not defined
> > +  */
> >  int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > -			      const u8 port_cap[4])
> > +			      const u8 port_cap[4],
> > +			      const struct edid *edid)
> >  {
> > -	int type = port_cap[0] & DP_DS_PORT_TYPE_MASK;
> > -	bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> > -		DP_DETAILED_CAP_INFO_AVAILABLE;
> > -	int bpc;
> > -
> > -	if (!detailed_cap_info)
> 
> I don't think we can drop this check. There's a somewhat surprising blurb
> about downstream port caps in the DP 2.0 spec (section 5.3.3.1):
> 
>    In addition, the adapter shall set the Detailed Capabilities Info registers
>    (DPCD Addresses 00080h through 0008Fh) to show all the downstream types,
>    including DFP 0. Either one or four bytes are used, per DFP type
>    indication. Therefore, up to 16 (with 1-byte descriptor) or four (with 4-
>    byte descriptor) DFP capabilities can be stored.
> 
> I've never once actually seen a sink do this, but this does mean it's
> technically possible tthat if we don't check the detailed caps bit then we
> might end up reading another port's DFP type instead of max_bpc info. Note
> though that we can make the assumption the four byte version of the field is
> used for DP 1.4+

The check is now ...


> 
> > +	if (!drm_dp_is_branch(dpcd))
> >  		return 0;
> >  
> > -	switch (type) {
> > -	case DP_DS_PORT_TYPE_VGA:
> > -	case DP_DS_PORT_TYPE_DVI:
> > -	case DP_DS_PORT_TYPE_HDMI:
> > +	if (dpcd[DP_DPCD_REV] < 0x11) {
> > +		switch (dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> > DP_DWN_STRM_PORT_TYPE_MASK) {
> > +		case DP_DWN_STRM_PORT_TYPE_DP:
> > +			return 0;
> > +		default:
> > +			return 8;
> > +		}
> > +	}
> > +
> > +	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
> > +	case DP_DS_PORT_TYPE_DP:
> > +		return 0;
> >  	case DP_DS_PORT_TYPE_DP_DUALMODE:
> > -		bpc = port_cap[2] & DP_DS_MAX_BPC_MASK;
> > +		if (is_edid_digital_input_dp(edid))
> > +			return 0;
> > +		fallthrough;
> > +	case DP_DS_PORT_TYPE_HDMI:
> > +	case DP_DS_PORT_TYPE_DVI:
> > +	case DP_DS_PORT_TYPE_VGA:
> > +		if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> > DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
> > +			return 8;

... here


> >  
> > -		switch (bpc) {
> > +		switch (port_cap[2] & DP_DS_MAX_BPC_MASK) {
> >  		case DP_DS_8BPC:
> >  			return 8;
> >  		case DP_DS_10BPC:
> > @@ -691,10 +699,12 @@ int drm_dp_downstream_max_bpc(const u8
> > dpcd[DP_RECEIVER_CAP_SIZE],
> >  			return 12;
> >  		case DP_DS_16BPC:
> >  			return 16;
> > +		default:
> > +			return 8;
> >  		}
> > -		fallthrough;
> > +		break;
> >  	default:
> > -		return 0;
> > +		return 8;
> >  	}
> >  }
> >  EXPORT_SYMBOL(drm_dp_downstream_max_bpc);
> > @@ -717,12 +727,15 @@ EXPORT_SYMBOL(drm_dp_downstream_id);
> >   * @m: pointer for debugfs file
> >   * @dpcd: DisplayPort configuration data
> >   * @port_cap: port capabilities
> > + * @edid: EDID
> >   * @aux: DisplayPort AUX channel
> >   *
> >   */
> >  void drm_dp_downstream_debug(struct seq_file *m,
> >  			     const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > -			     const u8 port_cap[4], struct drm_dp_aux *aux)
> > +			     const u8 port_cap[4],
> > +			     const struct edid *edid,
> > +			     struct drm_dp_aux *aux)
> >  {
> >  	bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> >  				 DP_DETAILED_CAP_INFO_AVAILABLE;
> > @@ -789,7 +802,7 @@ void drm_dp_downstream_debug(struct seq_file *m,
> >  				seq_printf(m, "\t\tMax TMDS clock: %d kHz\n",
> > clk);
> >  		}
> >  
> > -		bpc = drm_dp_downstream_max_bpc(dpcd, port_cap);
> > +		bpc = drm_dp_downstream_max_bpc(dpcd, port_cap, edid);
> >  
> >  		if (bpc > 0)
> >  			seq_printf(m, "\t\tMax bpc: %d\n", bpc);
> > diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> > b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> > index 53a0a3d9a22d..0bf31f9a8af5 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> > +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> > @@ -626,6 +626,7 @@ static void intel_dp_info(struct seq_file *m,
> >  {
> >  	struct intel_encoder *intel_encoder =
> > intel_attached_encoder(intel_connector);
> >  	struct intel_dp *intel_dp = enc_to_intel_dp(intel_encoder);
> > +	const struct drm_property_blob *edid = intel_connector-
> > >base.edid_blob_ptr;
> >  
> >  	seq_printf(m, "\tDPCD rev: %x\n", intel_dp->dpcd[DP_DPCD_REV]);
> >  	seq_printf(m, "\taudio support: %s\n", yesno(intel_dp->has_audio));
> > @@ -633,7 +634,7 @@ static void intel_dp_info(struct seq_file *m,
> >  		intel_panel_info(m, &intel_connector->panel);
> >  
> >  	drm_dp_downstream_debug(m, intel_dp->dpcd, intel_dp->downstream_ports,
> > -				&intel_dp->aux);
> > +				edid ? edid->data : NULL, &intel_dp->aux);
> >  }
> >  
> >  static void intel_dp_mst_info(struct seq_file *m,
> > diff --git a/drivers/gpu/drm/i915/display/intel_dp.c
> > b/drivers/gpu/drm/i915/display/intel_dp.c
> > index 2c8e82d97a34..c73b3efd84e0 100644
> > --- a/drivers/gpu/drm/i915/display/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> > @@ -6071,7 +6071,7 @@ intel_dp_set_edid(struct intel_dp *intel_dp)
> >  
> >  	intel_dp->dfp.max_bpc =
> >  		drm_dp_downstream_max_bpc(intel_dp->dpcd,
> > -					  intel_dp->downstream_ports);
> > +					  intel_dp->downstream_ports, edid);
> >  
> >  	drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] DFP max bpc %d\n",
> >  		    connector->base.base.id, connector->base.name,
> > diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
> > index 4f946826dfce..6218de1294c1 100644
> > --- a/include/drm/drm_dp_helper.h
> > +++ b/include/drm/drm_dp_helper.h
> > @@ -1646,10 +1646,14 @@ bool drm_dp_downstream_is_tmds(const u8
> > dpcd[DP_RECEIVER_CAP_SIZE],
> >  int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> >  				const u8 port_cap[4]);
> >  int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > -			      const u8 port_cap[4]);
> > +			      const u8 port_cap[4],
> > +			      const struct edid *edid);
> >  int drm_dp_downstream_id(struct drm_dp_aux *aux, char id[6]);
> > -void drm_dp_downstream_debug(struct seq_file *m, const u8
> > dpcd[DP_RECEIVER_CAP_SIZE],
> > -			     const u8 port_cap[4], struct drm_dp_aux *aux);
> > +void drm_dp_downstream_debug(struct seq_file *m,
> > +			     const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > +			     const u8 port_cap[4],
> > +			     const struct edid *edid,
> > +			     struct drm_dp_aux *aux);
> >  enum drm_mode_subconnector
> >  drm_dp_subconnector_type(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> >  			 const u8 port_cap[4]);
> -- 
> Cheers,
> 	Lyude Paul (she/her)
> 	Software Engineer at Red Hat

-- 
Ville Syrjälä
Intel
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v2 07/18] drm/dp: Pimp drm_dp_downstream_max_bpc()
  2020-09-10 14:46       ` [Intel-gfx] " Ville Syrjälä
@ 2020-09-10 19:40         ` Lyude Paul
  -1 siblings, 0 replies; 76+ messages in thread
From: Lyude Paul @ 2020-09-10 19:40 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, dri-devel

On Thu, 2020-09-10 at 17:46 +0300, Ville Syrjälä wrote:
> On Tue, Sep 08, 2020 at 01:51:56PM -0400, Lyude Paul wrote:
> > On Fri, 2020-09-04 at 14:53 +0300, Ville Syrjala wrote:
> > > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > 
> > > Deal with more cases in drm_dp_downstream_max_bpc():
> > > - DPCD 1.0 -> assume 8bpc for non-DP
> > > - DPCD 1.1+ DP (or DP++ with DP sink) -> allow anything
> > > - DPCD 1.1+ TMDS -> check the caps, assume 8bpc if the value is crap
> > > - anything else -> assume 8bpc
> > > 
> > > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > ---
> > >  drivers/gpu/drm/drm_dp_helper.c               | 69 +++++++++++--------
> > >  .../drm/i915/display/intel_display_debugfs.c  |  3 +-
> > >  drivers/gpu/drm/i915/display/intel_dp.c       |  2 +-
> > >  include/drm/drm_dp_helper.h                   | 10 ++-
> > >  4 files changed, 51 insertions(+), 33 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/drm_dp_helper.c
> > > b/drivers/gpu/drm/drm_dp_helper.c
> > > index 0fcb94f7dbe5..ab87209c25d8 100644
> > > --- a/drivers/gpu/drm/drm_dp_helper.c
> > > +++ b/drivers/gpu/drm/drm_dp_helper.c
> > > @@ -653,36 +653,44 @@ int drm_dp_downstream_max_clock(const u8
> > > dpcd[DP_RECEIVER_CAP_SIZE],
> > >  EXPORT_SYMBOL(drm_dp_downstream_max_clock);
> > >  
> > >  /**
> > > - * drm_dp_downstream_max_bpc() - extract branch device max
> > > - *                               bits per component
> > > - * @dpcd: DisplayPort configuration data
> > > - * @port_cap: port capabilities
> > > - *
> > > - * See also:
> > > - * drm_dp_read_downstream_info()
> > > - * drm_dp_downstream_max_clock()
> > > - *
> > > - * Returns: Max bpc on success or 0 if max bpc not defined
> > > - */
> > > +  * drm_dp_downstream_max_bpc() - extract downstream facing port max
> > > +  *                               bits per component
> > > +  * @dpcd: DisplayPort configuration data
> > > +  * @port_cap: downstream facing port capabilities
> > > +  * @edid: EDID
> > > +  *
> > > +  * Returns max bpc on success or 0 if max bpc not defined
> > > +  */
> > >  int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > > -			      const u8 port_cap[4])
> > > +			      const u8 port_cap[4],
> > > +			      const struct edid *edid)
> > >  {
> > > -	int type = port_cap[0] & DP_DS_PORT_TYPE_MASK;
> > > -	bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> > > -		DP_DETAILED_CAP_INFO_AVAILABLE;
> > > -	int bpc;
> > > -
> > > -	if (!detailed_cap_info)
> > 
> > I don't think we can drop this check. There's a somewhat surprising blurb
> > about downstream port caps in the DP 2.0 spec (section 5.3.3.1):
> > 
> >    In addition, the adapter shall set the Detailed Capabilities Info
> > registers
> >    (DPCD Addresses 00080h through 0008Fh) to show all the downstream types,
> >    including DFP 0. Either one or four bytes are used, per DFP type
> >    indication. Therefore, up to 16 (with 1-byte descriptor) or four (with 4-
> >    byte descriptor) DFP capabilities can be stored.
> > 
> > I've never once actually seen a sink do this, but this does mean it's
> > technically possible tthat if we don't check the detailed caps bit then we
> > might end up reading another port's DFP type instead of max_bpc info. Note
> > though that we can make the assumption the four byte version of the field is
> > used for DP 1.4+
> 
> The check is now ...
> 
> 
> > > +	if (!drm_dp_is_branch(dpcd))
> > >  		return 0;
> > >  
> > > -	switch (type) {
> > > -	case DP_DS_PORT_TYPE_VGA:
> > > -	case DP_DS_PORT_TYPE_DVI:
> > > -	case DP_DS_PORT_TYPE_HDMI:
> > > +	if (dpcd[DP_DPCD_REV] < 0x11) {
> > > +		switch (dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> > > DP_DWN_STRM_PORT_TYPE_MASK) {
> > > +		case DP_DWN_STRM_PORT_TYPE_DP:
> > > +			return 0;
> > > +		default:
> > > +			return 8;
> > > +		}
> > > +	}
> > > +
> > > +	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
> > > +	case DP_DS_PORT_TYPE_DP:
> > > +		return 0;
> > >  	case DP_DS_PORT_TYPE_DP_DUALMODE:
> > > -		bpc = port_cap[2] & DP_DS_MAX_BPC_MASK;
> > > +		if (is_edid_digital_input_dp(edid))
> > > +			return 0;
> > > +		fallthrough;
> > > +	case DP_DS_PORT_TYPE_HDMI:
> > > +	case DP_DS_PORT_TYPE_DVI:
> > > +	case DP_DS_PORT_TYPE_VGA:
> > > +		if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> > > DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
> > > +			return 8;
> 
> ... here

Ah-missed that! R-b'd by me then :)
> 
> 
> > >  
> > > -		switch (bpc) {
> > > +		switch (port_cap[2] & DP_DS_MAX_BPC_MASK) {
> > >  		case DP_DS_8BPC:
> > >  			return 8;
> > >  		case DP_DS_10BPC:
> > > @@ -691,10 +699,12 @@ int drm_dp_downstream_max_bpc(const u8
> > > dpcd[DP_RECEIVER_CAP_SIZE],
> > >  			return 12;
> > >  		case DP_DS_16BPC:
> > >  			return 16;
> > > +		default:
> > > +			return 8;
> > >  		}
> > > -		fallthrough;
> > > +		break;
> > >  	default:
> > > -		return 0;
> > > +		return 8;
> > >  	}
> > >  }
> > >  EXPORT_SYMBOL(drm_dp_downstream_max_bpc);
> > > @@ -717,12 +727,15 @@ EXPORT_SYMBOL(drm_dp_downstream_id);
> > >   * @m: pointer for debugfs file
> > >   * @dpcd: DisplayPort configuration data
> > >   * @port_cap: port capabilities
> > > + * @edid: EDID
> > >   * @aux: DisplayPort AUX channel
> > >   *
> > >   */
> > >  void drm_dp_downstream_debug(struct seq_file *m,
> > >  			     const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > > -			     const u8 port_cap[4], struct drm_dp_aux *aux)
> > > +			     const u8 port_cap[4],
> > > +			     const struct edid *edid,
> > > +			     struct drm_dp_aux *aux)
> > >  {
> > >  	bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> > >  				 DP_DETAILED_CAP_INFO_AVAILABLE;
> > > @@ -789,7 +802,7 @@ void drm_dp_downstream_debug(struct seq_file *m,
> > >  				seq_printf(m, "\t\tMax TMDS clock: %d kHz\n",
> > > clk);
> > >  		}
> > >  
> > > -		bpc = drm_dp_downstream_max_bpc(dpcd, port_cap);
> > > +		bpc = drm_dp_downstream_max_bpc(dpcd, port_cap, edid);
> > >  
> > >  		if (bpc > 0)
> > >  			seq_printf(m, "\t\tMax bpc: %d\n", bpc);
> > > diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> > > b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> > > index 53a0a3d9a22d..0bf31f9a8af5 100644
> > > --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> > > +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> > > @@ -626,6 +626,7 @@ static void intel_dp_info(struct seq_file *m,
> > >  {
> > >  	struct intel_encoder *intel_encoder =
> > > intel_attached_encoder(intel_connector);
> > >  	struct intel_dp *intel_dp = enc_to_intel_dp(intel_encoder);
> > > +	const struct drm_property_blob *edid = intel_connector-
> > > > base.edid_blob_ptr;
> > >  
> > >  	seq_printf(m, "\tDPCD rev: %x\n", intel_dp->dpcd[DP_DPCD_REV]);
> > >  	seq_printf(m, "\taudio support: %s\n", yesno(intel_dp->has_audio));
> > > @@ -633,7 +634,7 @@ static void intel_dp_info(struct seq_file *m,
> > >  		intel_panel_info(m, &intel_connector->panel);
> > >  
> > >  	drm_dp_downstream_debug(m, intel_dp->dpcd, intel_dp->downstream_ports,
> > > -				&intel_dp->aux);
> > > +				edid ? edid->data : NULL, &intel_dp->aux);
> > >  }
> > >  
> > >  static void intel_dp_mst_info(struct seq_file *m,
> > > diff --git a/drivers/gpu/drm/i915/display/intel_dp.c
> > > b/drivers/gpu/drm/i915/display/intel_dp.c
> > > index 2c8e82d97a34..c73b3efd84e0 100644
> > > --- a/drivers/gpu/drm/i915/display/intel_dp.c
> > > +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> > > @@ -6071,7 +6071,7 @@ intel_dp_set_edid(struct intel_dp *intel_dp)
> > >  
> > >  	intel_dp->dfp.max_bpc =
> > >  		drm_dp_downstream_max_bpc(intel_dp->dpcd,
> > > -					  intel_dp->downstream_ports);
> > > +					  intel_dp->downstream_ports, edid);
> > >  
> > >  	drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] DFP max bpc %d\n",
> > >  		    connector->base.base.id, connector->base.name,
> > > diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
> > > index 4f946826dfce..6218de1294c1 100644
> > > --- a/include/drm/drm_dp_helper.h
> > > +++ b/include/drm/drm_dp_helper.h
> > > @@ -1646,10 +1646,14 @@ bool drm_dp_downstream_is_tmds(const u8
> > > dpcd[DP_RECEIVER_CAP_SIZE],
> > >  int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > >  				const u8 port_cap[4]);
> > >  int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > > -			      const u8 port_cap[4]);
> > > +			      const u8 port_cap[4],
> > > +			      const struct edid *edid);
> > >  int drm_dp_downstream_id(struct drm_dp_aux *aux, char id[6]);
> > > -void drm_dp_downstream_debug(struct seq_file *m, const u8
> > > dpcd[DP_RECEIVER_CAP_SIZE],
> > > -			     const u8 port_cap[4], struct drm_dp_aux *aux);
> > > +void drm_dp_downstream_debug(struct seq_file *m,
> > > +			     const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > > +			     const u8 port_cap[4],
> > > +			     const struct edid *edid,
> > > +			     struct drm_dp_aux *aux);
> > >  enum drm_mode_subconnector
> > >  drm_dp_subconnector_type(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > >  			 const u8 port_cap[4]);
> > -- 
> > Cheers,
> > 	Lyude Paul (she/her)
> > 	Software Engineer at Red Hat
-- 
Sincerely,
      Lyude Paul (she/her)
      Software Engineer at Red Hat

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Intel-gfx] [PATCH v2 07/18] drm/dp: Pimp drm_dp_downstream_max_bpc()
@ 2020-09-10 19:40         ` Lyude Paul
  0 siblings, 0 replies; 76+ messages in thread
From: Lyude Paul @ 2020-09-10 19:40 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, dri-devel

On Thu, 2020-09-10 at 17:46 +0300, Ville Syrjälä wrote:
> On Tue, Sep 08, 2020 at 01:51:56PM -0400, Lyude Paul wrote:
> > On Fri, 2020-09-04 at 14:53 +0300, Ville Syrjala wrote:
> > > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > 
> > > Deal with more cases in drm_dp_downstream_max_bpc():
> > > - DPCD 1.0 -> assume 8bpc for non-DP
> > > - DPCD 1.1+ DP (or DP++ with DP sink) -> allow anything
> > > - DPCD 1.1+ TMDS -> check the caps, assume 8bpc if the value is crap
> > > - anything else -> assume 8bpc
> > > 
> > > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > ---
> > >  drivers/gpu/drm/drm_dp_helper.c               | 69 +++++++++++--------
> > >  .../drm/i915/display/intel_display_debugfs.c  |  3 +-
> > >  drivers/gpu/drm/i915/display/intel_dp.c       |  2 +-
> > >  include/drm/drm_dp_helper.h                   | 10 ++-
> > >  4 files changed, 51 insertions(+), 33 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/drm_dp_helper.c
> > > b/drivers/gpu/drm/drm_dp_helper.c
> > > index 0fcb94f7dbe5..ab87209c25d8 100644
> > > --- a/drivers/gpu/drm/drm_dp_helper.c
> > > +++ b/drivers/gpu/drm/drm_dp_helper.c
> > > @@ -653,36 +653,44 @@ int drm_dp_downstream_max_clock(const u8
> > > dpcd[DP_RECEIVER_CAP_SIZE],
> > >  EXPORT_SYMBOL(drm_dp_downstream_max_clock);
> > >  
> > >  /**
> > > - * drm_dp_downstream_max_bpc() - extract branch device max
> > > - *                               bits per component
> > > - * @dpcd: DisplayPort configuration data
> > > - * @port_cap: port capabilities
> > > - *
> > > - * See also:
> > > - * drm_dp_read_downstream_info()
> > > - * drm_dp_downstream_max_clock()
> > > - *
> > > - * Returns: Max bpc on success or 0 if max bpc not defined
> > > - */
> > > +  * drm_dp_downstream_max_bpc() - extract downstream facing port max
> > > +  *                               bits per component
> > > +  * @dpcd: DisplayPort configuration data
> > > +  * @port_cap: downstream facing port capabilities
> > > +  * @edid: EDID
> > > +  *
> > > +  * Returns max bpc on success or 0 if max bpc not defined
> > > +  */
> > >  int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > > -			      const u8 port_cap[4])
> > > +			      const u8 port_cap[4],
> > > +			      const struct edid *edid)
> > >  {
> > > -	int type = port_cap[0] & DP_DS_PORT_TYPE_MASK;
> > > -	bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> > > -		DP_DETAILED_CAP_INFO_AVAILABLE;
> > > -	int bpc;
> > > -
> > > -	if (!detailed_cap_info)
> > 
> > I don't think we can drop this check. There's a somewhat surprising blurb
> > about downstream port caps in the DP 2.0 spec (section 5.3.3.1):
> > 
> >    In addition, the adapter shall set the Detailed Capabilities Info
> > registers
> >    (DPCD Addresses 00080h through 0008Fh) to show all the downstream types,
> >    including DFP 0. Either one or four bytes are used, per DFP type
> >    indication. Therefore, up to 16 (with 1-byte descriptor) or four (with 4-
> >    byte descriptor) DFP capabilities can be stored.
> > 
> > I've never once actually seen a sink do this, but this does mean it's
> > technically possible tthat if we don't check the detailed caps bit then we
> > might end up reading another port's DFP type instead of max_bpc info. Note
> > though that we can make the assumption the four byte version of the field is
> > used for DP 1.4+
> 
> The check is now ...
> 
> 
> > > +	if (!drm_dp_is_branch(dpcd))
> > >  		return 0;
> > >  
> > > -	switch (type) {
> > > -	case DP_DS_PORT_TYPE_VGA:
> > > -	case DP_DS_PORT_TYPE_DVI:
> > > -	case DP_DS_PORT_TYPE_HDMI:
> > > +	if (dpcd[DP_DPCD_REV] < 0x11) {
> > > +		switch (dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> > > DP_DWN_STRM_PORT_TYPE_MASK) {
> > > +		case DP_DWN_STRM_PORT_TYPE_DP:
> > > +			return 0;
> > > +		default:
> > > +			return 8;
> > > +		}
> > > +	}
> > > +
> > > +	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
> > > +	case DP_DS_PORT_TYPE_DP:
> > > +		return 0;
> > >  	case DP_DS_PORT_TYPE_DP_DUALMODE:
> > > -		bpc = port_cap[2] & DP_DS_MAX_BPC_MASK;
> > > +		if (is_edid_digital_input_dp(edid))
> > > +			return 0;
> > > +		fallthrough;
> > > +	case DP_DS_PORT_TYPE_HDMI:
> > > +	case DP_DS_PORT_TYPE_DVI:
> > > +	case DP_DS_PORT_TYPE_VGA:
> > > +		if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> > > DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
> > > +			return 8;
> 
> ... here

Ah-missed that! R-b'd by me then :)
> 
> 
> > >  
> > > -		switch (bpc) {
> > > +		switch (port_cap[2] & DP_DS_MAX_BPC_MASK) {
> > >  		case DP_DS_8BPC:
> > >  			return 8;
> > >  		case DP_DS_10BPC:
> > > @@ -691,10 +699,12 @@ int drm_dp_downstream_max_bpc(const u8
> > > dpcd[DP_RECEIVER_CAP_SIZE],
> > >  			return 12;
> > >  		case DP_DS_16BPC:
> > >  			return 16;
> > > +		default:
> > > +			return 8;
> > >  		}
> > > -		fallthrough;
> > > +		break;
> > >  	default:
> > > -		return 0;
> > > +		return 8;
> > >  	}
> > >  }
> > >  EXPORT_SYMBOL(drm_dp_downstream_max_bpc);
> > > @@ -717,12 +727,15 @@ EXPORT_SYMBOL(drm_dp_downstream_id);
> > >   * @m: pointer for debugfs file
> > >   * @dpcd: DisplayPort configuration data
> > >   * @port_cap: port capabilities
> > > + * @edid: EDID
> > >   * @aux: DisplayPort AUX channel
> > >   *
> > >   */
> > >  void drm_dp_downstream_debug(struct seq_file *m,
> > >  			     const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > > -			     const u8 port_cap[4], struct drm_dp_aux *aux)
> > > +			     const u8 port_cap[4],
> > > +			     const struct edid *edid,
> > > +			     struct drm_dp_aux *aux)
> > >  {
> > >  	bool detailed_cap_info = dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> > >  				 DP_DETAILED_CAP_INFO_AVAILABLE;
> > > @@ -789,7 +802,7 @@ void drm_dp_downstream_debug(struct seq_file *m,
> > >  				seq_printf(m, "\t\tMax TMDS clock: %d kHz\n",
> > > clk);
> > >  		}
> > >  
> > > -		bpc = drm_dp_downstream_max_bpc(dpcd, port_cap);
> > > +		bpc = drm_dp_downstream_max_bpc(dpcd, port_cap, edid);
> > >  
> > >  		if (bpc > 0)
> > >  			seq_printf(m, "\t\tMax bpc: %d\n", bpc);
> > > diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> > > b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> > > index 53a0a3d9a22d..0bf31f9a8af5 100644
> > > --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> > > +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> > > @@ -626,6 +626,7 @@ static void intel_dp_info(struct seq_file *m,
> > >  {
> > >  	struct intel_encoder *intel_encoder =
> > > intel_attached_encoder(intel_connector);
> > >  	struct intel_dp *intel_dp = enc_to_intel_dp(intel_encoder);
> > > +	const struct drm_property_blob *edid = intel_connector-
> > > > base.edid_blob_ptr;
> > >  
> > >  	seq_printf(m, "\tDPCD rev: %x\n", intel_dp->dpcd[DP_DPCD_REV]);
> > >  	seq_printf(m, "\taudio support: %s\n", yesno(intel_dp->has_audio));
> > > @@ -633,7 +634,7 @@ static void intel_dp_info(struct seq_file *m,
> > >  		intel_panel_info(m, &intel_connector->panel);
> > >  
> > >  	drm_dp_downstream_debug(m, intel_dp->dpcd, intel_dp->downstream_ports,
> > > -				&intel_dp->aux);
> > > +				edid ? edid->data : NULL, &intel_dp->aux);
> > >  }
> > >  
> > >  static void intel_dp_mst_info(struct seq_file *m,
> > > diff --git a/drivers/gpu/drm/i915/display/intel_dp.c
> > > b/drivers/gpu/drm/i915/display/intel_dp.c
> > > index 2c8e82d97a34..c73b3efd84e0 100644
> > > --- a/drivers/gpu/drm/i915/display/intel_dp.c
> > > +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> > > @@ -6071,7 +6071,7 @@ intel_dp_set_edid(struct intel_dp *intel_dp)
> > >  
> > >  	intel_dp->dfp.max_bpc =
> > >  		drm_dp_downstream_max_bpc(intel_dp->dpcd,
> > > -					  intel_dp->downstream_ports);
> > > +					  intel_dp->downstream_ports, edid);
> > >  
> > >  	drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] DFP max bpc %d\n",
> > >  		    connector->base.base.id, connector->base.name,
> > > diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
> > > index 4f946826dfce..6218de1294c1 100644
> > > --- a/include/drm/drm_dp_helper.h
> > > +++ b/include/drm/drm_dp_helper.h
> > > @@ -1646,10 +1646,14 @@ bool drm_dp_downstream_is_tmds(const u8
> > > dpcd[DP_RECEIVER_CAP_SIZE],
> > >  int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > >  				const u8 port_cap[4]);
> > >  int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > > -			      const u8 port_cap[4]);
> > > +			      const u8 port_cap[4],
> > > +			      const struct edid *edid);
> > >  int drm_dp_downstream_id(struct drm_dp_aux *aux, char id[6]);
> > > -void drm_dp_downstream_debug(struct seq_file *m, const u8
> > > dpcd[DP_RECEIVER_CAP_SIZE],
> > > -			     const u8 port_cap[4], struct drm_dp_aux *aux);
> > > +void drm_dp_downstream_debug(struct seq_file *m,
> > > +			     const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > > +			     const u8 port_cap[4],
> > > +			     const struct edid *edid,
> > > +			     struct drm_dp_aux *aux);
> > >  enum drm_mode_subconnector
> > >  drm_dp_subconnector_type(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > >  			 const u8 port_cap[4]);
> > -- 
> > Cheers,
> > 	Lyude Paul (she/her)
> > 	Software Engineer at Red Hat
-- 
Sincerely,
      Lyude Paul (she/her)
      Software Engineer at Red Hat

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v2 10/18] drm/dp: Add drm_dp_downstream_{min,max}_tmds_clock()
  2020-09-10 13:55       ` [Intel-gfx] [PATCH v2 10/18] drm/dp: Add drm_dp_downstream_{min, max}_tmds_clock() Ville Syrjälä
@ 2020-09-10 19:40         ` Lyude Paul
  -1 siblings, 0 replies; 76+ messages in thread
From: Lyude Paul @ 2020-09-10 19:40 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, dri-devel

On Thu, 2020-09-10 at 16:55 +0300, Ville Syrjälä wrote:
> On Tue, Sep 08, 2020 at 02:08:17PM -0400, Lyude Paul wrote:
> > On Fri, 2020-09-04 at 14:53 +0300, Ville Syrjala wrote:
> > > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > 
> > > Add helpers to get the TMDS clock limits for HDMI/DVI downstream
> > > facing ports.
> > > 
> > > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > ---
> > >  drivers/gpu/drm/drm_dp_helper.c | 116 ++++++++++++++++++++++++++++++++
> > >  include/drm/drm_dp_helper.h     |   6 ++
> > >  2 files changed, 122 insertions(+)
> > > 
> > > diff --git a/drivers/gpu/drm/drm_dp_helper.c
> > > b/drivers/gpu/drm/drm_dp_helper.c
> > > index 822a30e609ef..f567428f2aef 100644
> > > --- a/drivers/gpu/drm/drm_dp_helper.c
> > > +++ b/drivers/gpu/drm/drm_dp_helper.c
> > > @@ -643,6 +643,114 @@ int drm_dp_downstream_max_dotclock(const u8
> > > dpcd[DP_RECEIVER_CAP_SIZE],
> > >  }
> > >  EXPORT_SYMBOL(drm_dp_downstream_max_dotclock);
> > >  
> > > +/**
> > > + * drm_dp_downstream_max_tmds_clock() - extract downstream facing port
> > > max
> > > TMDS clock
> > > + * @dpcd: DisplayPort configuration data
> > > + * @port_cap: port capabilities
> > > + * @edid: EDID
> > > + *
> > > + * Returns HDMI/DVI downstream facing port max TMDS clock in kHz on
> > > success,
> > > + * or 0 if max TMDS clock not defined
> > > + */
> > > +int drm_dp_downstream_max_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > > +				     const u8 port_cap[4],
> > > +				     const struct edid *edid)
> > > +{
> > > +	if (!drm_dp_is_branch(dpcd))
> > > +		return 0;
> > > +
> > > +	if (dpcd[DP_DPCD_REV] < 0x11) {
> > > +		switch (dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> > > DP_DWN_STRM_PORT_TYPE_MASK) {
> > > +		case DP_DWN_STRM_PORT_TYPE_TMDS:
> > > +			return 165000;
> > > +		default:
> > > +			return 0;
> > > +		}
> > > +	}
> > > +
> > > +	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
> > > +	case DP_DS_PORT_TYPE_DP_DUALMODE:
> > > +		if (is_edid_digital_input_dp(edid))
> > > +			return 0;
> > > +		/*
> > > +		 * It's left up to the driver to check the
> > > +		 * DP dual mode adapter's max TMDS clock.
> > > +		 *
> > > +		 * Unfortunatley it looks like branch devices
> > > +		 * may not fordward that the DP dual mode i2c
> > > +		 * access so we just usually get i2c nak :(
> > > +		 */
> > > +		fallthrough;
> > > +	case DP_DS_PORT_TYPE_HDMI:
> > > +		 /*
> > > +		  * We should perhaps assume 165 MHz when detailed cap
> > > +		  * info is not available. But looks like many typical
> > > +		  * branch devices fall into that category and so we'd
> > > +		  * probably end up with users complaining that they can't
> > > +		  * get high resolution modes with their favorite dongle.
> > > +		  *
> > > +		  * So let's limit to 300 MHz instead since DPCD 1.4
> > > +		  * HDMI 2.0 DFPs are required to have the detailed cap
> > > +		  * info. So it's more likely we're dealing with a HDMI 1.4
> > > +		  * compatible* device here.
> > 
> > Forgot to mention - not directly related to this series, there's some hidden
> > i2c bits that I think can also be probed for this sort of information on
> > passive adapters, I know amdgpu actually supports this. I wonder how many of
> > them also apply to older active adapters...
> 
> Something other than the normal DP dual mode stuff?
Actually that -may- have been what I was thinking of but I'm not sure, I'd
probably need to look through DAL to find out
> 
-- 
Sincerely,
      Lyude Paul (she/her)
      Software Engineer at Red Hat

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Intel-gfx] [PATCH v2 10/18] drm/dp: Add drm_dp_downstream_{min, max}_tmds_clock()
@ 2020-09-10 19:40         ` Lyude Paul
  0 siblings, 0 replies; 76+ messages in thread
From: Lyude Paul @ 2020-09-10 19:40 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, dri-devel

On Thu, 2020-09-10 at 16:55 +0300, Ville Syrjälä wrote:
> On Tue, Sep 08, 2020 at 02:08:17PM -0400, Lyude Paul wrote:
> > On Fri, 2020-09-04 at 14:53 +0300, Ville Syrjala wrote:
> > > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > 
> > > Add helpers to get the TMDS clock limits for HDMI/DVI downstream
> > > facing ports.
> > > 
> > > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > ---
> > >  drivers/gpu/drm/drm_dp_helper.c | 116 ++++++++++++++++++++++++++++++++
> > >  include/drm/drm_dp_helper.h     |   6 ++
> > >  2 files changed, 122 insertions(+)
> > > 
> > > diff --git a/drivers/gpu/drm/drm_dp_helper.c
> > > b/drivers/gpu/drm/drm_dp_helper.c
> > > index 822a30e609ef..f567428f2aef 100644
> > > --- a/drivers/gpu/drm/drm_dp_helper.c
> > > +++ b/drivers/gpu/drm/drm_dp_helper.c
> > > @@ -643,6 +643,114 @@ int drm_dp_downstream_max_dotclock(const u8
> > > dpcd[DP_RECEIVER_CAP_SIZE],
> > >  }
> > >  EXPORT_SYMBOL(drm_dp_downstream_max_dotclock);
> > >  
> > > +/**
> > > + * drm_dp_downstream_max_tmds_clock() - extract downstream facing port
> > > max
> > > TMDS clock
> > > + * @dpcd: DisplayPort configuration data
> > > + * @port_cap: port capabilities
> > > + * @edid: EDID
> > > + *
> > > + * Returns HDMI/DVI downstream facing port max TMDS clock in kHz on
> > > success,
> > > + * or 0 if max TMDS clock not defined
> > > + */
> > > +int drm_dp_downstream_max_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > > +				     const u8 port_cap[4],
> > > +				     const struct edid *edid)
> > > +{
> > > +	if (!drm_dp_is_branch(dpcd))
> > > +		return 0;
> > > +
> > > +	if (dpcd[DP_DPCD_REV] < 0x11) {
> > > +		switch (dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> > > DP_DWN_STRM_PORT_TYPE_MASK) {
> > > +		case DP_DWN_STRM_PORT_TYPE_TMDS:
> > > +			return 165000;
> > > +		default:
> > > +			return 0;
> > > +		}
> > > +	}
> > > +
> > > +	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
> > > +	case DP_DS_PORT_TYPE_DP_DUALMODE:
> > > +		if (is_edid_digital_input_dp(edid))
> > > +			return 0;
> > > +		/*
> > > +		 * It's left up to the driver to check the
> > > +		 * DP dual mode adapter's max TMDS clock.
> > > +		 *
> > > +		 * Unfortunatley it looks like branch devices
> > > +		 * may not fordward that the DP dual mode i2c
> > > +		 * access so we just usually get i2c nak :(
> > > +		 */
> > > +		fallthrough;
> > > +	case DP_DS_PORT_TYPE_HDMI:
> > > +		 /*
> > > +		  * We should perhaps assume 165 MHz when detailed cap
> > > +		  * info is not available. But looks like many typical
> > > +		  * branch devices fall into that category and so we'd
> > > +		  * probably end up with users complaining that they can't
> > > +		  * get high resolution modes with their favorite dongle.
> > > +		  *
> > > +		  * So let's limit to 300 MHz instead since DPCD 1.4
> > > +		  * HDMI 2.0 DFPs are required to have the detailed cap
> > > +		  * info. So it's more likely we're dealing with a HDMI 1.4
> > > +		  * compatible* device here.
> > 
> > Forgot to mention - not directly related to this series, there's some hidden
> > i2c bits that I think can also be probed for this sort of information on
> > passive adapters, I know amdgpu actually supports this. I wonder how many of
> > them also apply to older active adapters...
> 
> Something other than the normal DP dual mode stuff?
Actually that -may- have been what I was thinking of but I'm not sure, I'd
probably need to look through DAL to find out
> 
-- 
Sincerely,
      Lyude Paul (she/her)
      Software Engineer at Red Hat

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v2 10/18] drm/dp: Add drm_dp_downstream_{min,max}_tmds_clock()
  2020-09-08 18:04     ` [Intel-gfx] [PATCH v2 10/18] drm/dp: Add drm_dp_downstream_{min, max}_tmds_clock() Lyude Paul
@ 2020-09-17 12:46       ` Ville Syrjälä
  -1 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjälä @ 2020-09-17 12:46 UTC (permalink / raw)
  To: Lyude Paul; +Cc: intel-gfx, dri-devel

On Tue, Sep 08, 2020 at 02:04:56PM -0400, Lyude Paul wrote:
> On Fri, 2020-09-04 at 14:53 +0300, Ville Syrjala wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > Add helpers to get the TMDS clock limits for HDMI/DVI downstream
> > facing ports.
> > 
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/drm_dp_helper.c | 116 ++++++++++++++++++++++++++++++++
> >  include/drm/drm_dp_helper.h     |   6 ++
> >  2 files changed, 122 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/drm_dp_helper.c
> > b/drivers/gpu/drm/drm_dp_helper.c
> > index 822a30e609ef..f567428f2aef 100644
> > --- a/drivers/gpu/drm/drm_dp_helper.c
> > +++ b/drivers/gpu/drm/drm_dp_helper.c
> > @@ -643,6 +643,114 @@ int drm_dp_downstream_max_dotclock(const u8
> > dpcd[DP_RECEIVER_CAP_SIZE],
> >  }
> >  EXPORT_SYMBOL(drm_dp_downstream_max_dotclock);
> >  
> > +/**
> > + * drm_dp_downstream_max_tmds_clock() - extract downstream facing port max
> > TMDS clock
> > + * @dpcd: DisplayPort configuration data
> > + * @port_cap: port capabilities
> > + * @edid: EDID
> > + *
> > + * Returns HDMI/DVI downstream facing port max TMDS clock in kHz on
> > success,
> > + * or 0 if max TMDS clock not defined
> > + */
> > +int drm_dp_downstream_max_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > +				     const u8 port_cap[4],
> > +				     const struct edid *edid)
> > +{
> > +	if (!drm_dp_is_branch(dpcd))
> > +		return 0;
> > +
> > +	if (dpcd[DP_DPCD_REV] < 0x11) {
> > +		switch (dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> > DP_DWN_STRM_PORT_TYPE_MASK) {
> > +		case DP_DWN_STRM_PORT_TYPE_TMDS:
> > +			return 165000;
> > +		default:
> > +			return 0;
> > +		}
> > +	}
> > +
> > +	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
> > +	case DP_DS_PORT_TYPE_DP_DUALMODE:
> > +		if (is_edid_digital_input_dp(edid))
> > +			return 0;
> > +		/*
> > +		 * It's left up to the driver to check the
> > +		 * DP dual mode adapter's max TMDS clock.
> > +		 *
> > +		 * Unfortunatley it looks like branch devices
> > +		 * may not fordward that the DP dual mode i2c
> > +		 * access so we just usually get i2c nak :(
> > +		 */
> > +		fallthrough;
> > +	case DP_DS_PORT_TYPE_HDMI:
> > +		 /*
> > +		  * We should perhaps assume 165 MHz when detailed cap
> > +		  * info is not available. But looks like many typical
> > +		  * branch devices fall into that category and so we'd
> > +		  * probably end up with users complaining that they can't
> > +		  * get high resolution modes with their favorite dongle.
> > +		  *
> > +		  * So let's limit to 300 MHz instead since DPCD 1.4
> > +		  * HDMI 2.0 DFPs are required to have the detailed cap
> > +		  * info. So it's more likely we're dealing with a HDMI 1.4
> > +		  * compatible* device here.
> > +		  */
> > +		if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> > DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
> > +			return 300000;
> > +		return port_cap[1] * 2500;
> > +	case DP_DS_PORT_TYPE_DVI:
> > +		if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> > DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
> > +			return 165000;
> > +		/* FIXME what to do about DVI dual link? */
> > +		return port_cap[1] * 2500;
> > +	default:
> > +		return 0;
> > +	}
> > +}
> > +EXPORT_SYMBOL(drm_dp_downstream_max_tmds_clock);
> > +
> > +/**
> > + * drm_dp_downstream_min_tmds_clock() - extract downstream facing port min
> > TMDS clock
> > + * @dpcd: DisplayPort configuration data
> > + * @port_cap: port capabilities
> > + * @edid: EDID
> > + *
> > + * Returns HDMI/DVI downstream facing port min TMDS clock in kHz on
> > success,
> > + * or 0 if max TMDS clock not defined
> 
> s/max/min/
> 
> Also, I would assume if callers are interested in min they're also interested
> in max and vice versa, would it maybe make sense to combine the min/max
> functions here?

Returning multiple things in C requires ugly stuff, so I try to avoid
it.

-- 
Ville Syrjälä
Intel
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Intel-gfx] [PATCH v2 10/18] drm/dp: Add drm_dp_downstream_{min, max}_tmds_clock()
@ 2020-09-17 12:46       ` Ville Syrjälä
  0 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjälä @ 2020-09-17 12:46 UTC (permalink / raw)
  To: Lyude Paul; +Cc: intel-gfx, dri-devel

On Tue, Sep 08, 2020 at 02:04:56PM -0400, Lyude Paul wrote:
> On Fri, 2020-09-04 at 14:53 +0300, Ville Syrjala wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > Add helpers to get the TMDS clock limits for HDMI/DVI downstream
> > facing ports.
> > 
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/drm_dp_helper.c | 116 ++++++++++++++++++++++++++++++++
> >  include/drm/drm_dp_helper.h     |   6 ++
> >  2 files changed, 122 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/drm_dp_helper.c
> > b/drivers/gpu/drm/drm_dp_helper.c
> > index 822a30e609ef..f567428f2aef 100644
> > --- a/drivers/gpu/drm/drm_dp_helper.c
> > +++ b/drivers/gpu/drm/drm_dp_helper.c
> > @@ -643,6 +643,114 @@ int drm_dp_downstream_max_dotclock(const u8
> > dpcd[DP_RECEIVER_CAP_SIZE],
> >  }
> >  EXPORT_SYMBOL(drm_dp_downstream_max_dotclock);
> >  
> > +/**
> > + * drm_dp_downstream_max_tmds_clock() - extract downstream facing port max
> > TMDS clock
> > + * @dpcd: DisplayPort configuration data
> > + * @port_cap: port capabilities
> > + * @edid: EDID
> > + *
> > + * Returns HDMI/DVI downstream facing port max TMDS clock in kHz on
> > success,
> > + * or 0 if max TMDS clock not defined
> > + */
> > +int drm_dp_downstream_max_tmds_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE],
> > +				     const u8 port_cap[4],
> > +				     const struct edid *edid)
> > +{
> > +	if (!drm_dp_is_branch(dpcd))
> > +		return 0;
> > +
> > +	if (dpcd[DP_DPCD_REV] < 0x11) {
> > +		switch (dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> > DP_DWN_STRM_PORT_TYPE_MASK) {
> > +		case DP_DWN_STRM_PORT_TYPE_TMDS:
> > +			return 165000;
> > +		default:
> > +			return 0;
> > +		}
> > +	}
> > +
> > +	switch (port_cap[0] & DP_DS_PORT_TYPE_MASK) {
> > +	case DP_DS_PORT_TYPE_DP_DUALMODE:
> > +		if (is_edid_digital_input_dp(edid))
> > +			return 0;
> > +		/*
> > +		 * It's left up to the driver to check the
> > +		 * DP dual mode adapter's max TMDS clock.
> > +		 *
> > +		 * Unfortunatley it looks like branch devices
> > +		 * may not fordward that the DP dual mode i2c
> > +		 * access so we just usually get i2c nak :(
> > +		 */
> > +		fallthrough;
> > +	case DP_DS_PORT_TYPE_HDMI:
> > +		 /*
> > +		  * We should perhaps assume 165 MHz when detailed cap
> > +		  * info is not available. But looks like many typical
> > +		  * branch devices fall into that category and so we'd
> > +		  * probably end up with users complaining that they can't
> > +		  * get high resolution modes with their favorite dongle.
> > +		  *
> > +		  * So let's limit to 300 MHz instead since DPCD 1.4
> > +		  * HDMI 2.0 DFPs are required to have the detailed cap
> > +		  * info. So it's more likely we're dealing with a HDMI 1.4
> > +		  * compatible* device here.
> > +		  */
> > +		if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> > DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
> > +			return 300000;
> > +		return port_cap[1] * 2500;
> > +	case DP_DS_PORT_TYPE_DVI:
> > +		if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] &
> > DP_DETAILED_CAP_INFO_AVAILABLE) == 0)
> > +			return 165000;
> > +		/* FIXME what to do about DVI dual link? */
> > +		return port_cap[1] * 2500;
> > +	default:
> > +		return 0;
> > +	}
> > +}
> > +EXPORT_SYMBOL(drm_dp_downstream_max_tmds_clock);
> > +
> > +/**
> > + * drm_dp_downstream_min_tmds_clock() - extract downstream facing port min
> > TMDS clock
> > + * @dpcd: DisplayPort configuration data
> > + * @port_cap: port capabilities
> > + * @edid: EDID
> > + *
> > + * Returns HDMI/DVI downstream facing port min TMDS clock in kHz on
> > success,
> > + * or 0 if max TMDS clock not defined
> 
> s/max/min/
> 
> Also, I would assume if callers are interested in min they're also interested
> in max and vice versa, would it maybe make sense to combine the min/max
> functions here?

Returning multiple things in C requires ugly stuff, so I try to avoid
it.

-- 
Ville Syrjälä
Intel
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v2 00/18] drm/i915: Pimp DP DFP handling
  2020-09-08 18:34   ` [Intel-gfx] " Lyude Paul
  (?)
@ 2020-09-17 16:11       ` Ville Syrjälä
  -1 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjälä @ 2020-09-17 16:11 UTC (permalink / raw)
  To: Lyude Paul
  Cc: nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
	intel-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW, Ben Skeggs,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

On Tue, Sep 08, 2020 at 02:34:24PM -0400, Lyude Paul wrote:
> With the nitpicks addressed (note there were a couple of other spots where we
> wanted to use Return: in the kdocs, but I didn't bother pointing all of them
> out), all but patch 07 is:
> 
> Reviewed-by: Lyude Paul <lyude-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>

Thanks for the review. I fixed up the missing/bad docs and 
pushed the lot to drm-intel-next-queued (with Daniel's irc ack).

PS.
Had to s/drm_dp_downstream_max_clock/drm_dp_downstream_max_dotclock/
in nouveau_dp.c to keep it in a buildable shape. I hope I didn't step
on too many toes with this...

-- 
Ville Syrjälä
Intel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [PATCH v2 00/18] drm/i915: Pimp DP DFP handling
@ 2020-09-17 16:11       ` Ville Syrjälä
  0 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjälä @ 2020-09-17 16:11 UTC (permalink / raw)
  To: Lyude Paul; +Cc: nouveau, intel-gfx, Ben Skeggs, dri-devel, Daniel Vetter

On Tue, Sep 08, 2020 at 02:34:24PM -0400, Lyude Paul wrote:
> With the nitpicks addressed (note there were a couple of other spots where we
> wanted to use Return: in the kdocs, but I didn't bother pointing all of them
> out), all but patch 07 is:
> 
> Reviewed-by: Lyude Paul <lyude@redhat.com>

Thanks for the review. I fixed up the missing/bad docs and 
pushed the lot to drm-intel-next-queued (with Daniel's irc ack).

PS.
Had to s/drm_dp_downstream_max_clock/drm_dp_downstream_max_dotclock/
in nouveau_dp.c to keep it in a buildable shape. I hope I didn't step
on too many toes with this...

-- 
Ville Syrjälä
Intel
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 76+ messages in thread

* Re: [Intel-gfx] [PATCH v2 00/18] drm/i915: Pimp DP DFP handling
@ 2020-09-17 16:11       ` Ville Syrjälä
  0 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjälä @ 2020-09-17 16:11 UTC (permalink / raw)
  To: Lyude Paul; +Cc: nouveau, intel-gfx, Ben Skeggs, dri-devel, Daniel Vetter

On Tue, Sep 08, 2020 at 02:34:24PM -0400, Lyude Paul wrote:
> With the nitpicks addressed (note there were a couple of other spots where we
> wanted to use Return: in the kdocs, but I didn't bother pointing all of them
> out), all but patch 07 is:
> 
> Reviewed-by: Lyude Paul <lyude@redhat.com>

Thanks for the review. I fixed up the missing/bad docs and 
pushed the lot to drm-intel-next-queued (with Daniel's irc ack).

PS.
Had to s/drm_dp_downstream_max_clock/drm_dp_downstream_max_dotclock/
in nouveau_dp.c to keep it in a buildable shape. I hope I didn't step
on too many toes with this...

-- 
Ville Syrjälä
Intel
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 76+ messages in thread

end of thread, other threads:[~2020-09-17 16:11 UTC | newest]

Thread overview: 76+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-04 11:53 [PATCH v2 00/18] drm/i915: Pimp DP DFP handling Ville Syrjala
2020-09-04 11:53 ` [Intel-gfx] " Ville Syrjala
2020-09-04 11:53 ` [PATCH v2 01/18] drm/dp: Dump downstream facing port caps Ville Syrjala
2020-09-04 11:53   ` [Intel-gfx] " Ville Syrjala
2020-09-04 11:53 ` [PATCH v2 02/18] drm/i915/lspcon: Do not send infoframes to non-HDMI sinks Ville Syrjala
2020-09-04 11:53   ` [Intel-gfx] " Ville Syrjala
2020-09-04 11:53 ` [PATCH v2 03/18] drm/dp: Define protocol converter DPCD registers Ville Syrjala
2020-09-04 11:53   ` [Intel-gfx] " Ville Syrjala
2020-09-04 11:53 ` [PATCH v2 04/18] drm/dp: Define more downstream facing port caps Ville Syrjala
2020-09-04 11:53   ` [Intel-gfx] " Ville Syrjala
2020-09-04 11:53 ` [PATCH v2 05/18] drm/i915: Reworkd DFP max bpc handling Ville Syrjala
2020-09-04 11:53   ` [Intel-gfx] " Ville Syrjala
2020-09-04 11:53 ` [PATCH v2 06/18] drm/dp: Add helpers to identify downstream facing port types Ville Syrjala
2020-09-04 11:53   ` [Intel-gfx] " Ville Syrjala
2020-09-08 17:30   ` Lyude Paul
2020-09-08 17:30     ` [Intel-gfx] " Lyude Paul
2020-09-04 11:53 ` [PATCH v2 07/18] drm/dp: Pimp drm_dp_downstream_max_bpc() Ville Syrjala
2020-09-04 11:53   ` [Intel-gfx] " Ville Syrjala
2020-09-08 17:32   ` Lyude Paul
2020-09-08 17:32     ` [Intel-gfx] " Lyude Paul
2020-09-08 17:51   ` Lyude Paul
2020-09-08 17:51     ` [Intel-gfx] " Lyude Paul
2020-09-10 14:46     ` Ville Syrjälä
2020-09-10 14:46       ` [Intel-gfx] " Ville Syrjälä
2020-09-10 19:40       ` Lyude Paul
2020-09-10 19:40         ` [Intel-gfx] " Lyude Paul
2020-09-04 11:53 ` [PATCH v2 08/18] drm/dp: Redo drm_dp_downstream_max_clock() as drm_dp_downstream_max_dotclock() Ville Syrjala
2020-09-04 11:53   ` [Intel-gfx] " Ville Syrjala
2020-09-08 17:56   ` Lyude Paul
2020-09-08 17:56     ` [Intel-gfx] " Lyude Paul
2020-09-04 11:53 ` [PATCH v2 09/18] drm/i915: Reworkd DP DFP clock handling Ville Syrjala
2020-09-04 11:53   ` [Intel-gfx] " Ville Syrjala
2020-09-04 11:53 ` [PATCH v2 10/18] drm/dp: Add drm_dp_downstream_{min, max}_tmds_clock() Ville Syrjala
2020-09-04 11:53   ` [Intel-gfx] " Ville Syrjala
2020-09-08 18:04   ` [PATCH v2 10/18] drm/dp: Add drm_dp_downstream_{min,max}_tmds_clock() Lyude Paul
2020-09-08 18:04     ` [Intel-gfx] [PATCH v2 10/18] drm/dp: Add drm_dp_downstream_{min, max}_tmds_clock() Lyude Paul
2020-09-17 12:46     ` [PATCH v2 10/18] drm/dp: Add drm_dp_downstream_{min,max}_tmds_clock() Ville Syrjälä
2020-09-17 12:46       ` [Intel-gfx] [PATCH v2 10/18] drm/dp: Add drm_dp_downstream_{min, max}_tmds_clock() Ville Syrjälä
2020-09-08 18:08   ` [PATCH v2 10/18] drm/dp: Add drm_dp_downstream_{min,max}_tmds_clock() Lyude Paul
2020-09-08 18:08     ` [Intel-gfx] [PATCH v2 10/18] drm/dp: Add drm_dp_downstream_{min, max}_tmds_clock() Lyude Paul
2020-09-10 13:55     ` [PATCH v2 10/18] drm/dp: Add drm_dp_downstream_{min,max}_tmds_clock() Ville Syrjälä
2020-09-10 13:55       ` [Intel-gfx] [PATCH v2 10/18] drm/dp: Add drm_dp_downstream_{min, max}_tmds_clock() Ville Syrjälä
2020-09-10 19:40       ` [PATCH v2 10/18] drm/dp: Add drm_dp_downstream_{min,max}_tmds_clock() Lyude Paul
2020-09-10 19:40         ` [Intel-gfx] [PATCH v2 10/18] drm/dp: Add drm_dp_downstream_{min, max}_tmds_clock() Lyude Paul
2020-09-04 11:53 ` [PATCH v2 11/18] drm/i915: Deal with TMDS DFP clock limits Ville Syrjala
2020-09-04 11:53   ` [Intel-gfx] " Ville Syrjala
2020-09-04 11:53 ` [PATCH v2 12/18] drm/i915: Configure DP 1.3+ protocol converted HDMI mode Ville Syrjala
2020-09-04 11:53   ` [Intel-gfx] " Ville Syrjala
2020-09-08 18:11   ` Lyude Paul
2020-09-08 18:11     ` [Intel-gfx] " Lyude Paul
2020-09-04 11:53 ` [PATCH v2 13/18] drm/dp: Add drm_dp_downstream_mode() Ville Syrjala
2020-09-04 11:53   ` [Intel-gfx] " Ville Syrjala
2020-09-08 18:13   ` Lyude Paul
2020-09-08 18:13     ` [Intel-gfx] " Lyude Paul
2020-09-04 11:53 ` [PATCH v2 14/18] drm/i915: Handle downstream facing ports w/o EDID Ville Syrjala
2020-09-04 11:53   ` [Intel-gfx] " Ville Syrjala
2020-09-04 11:53 ` [PATCH v2 15/18] drm/i915: Extract intel_hdmi_has_audio() Ville Syrjala
2020-09-04 11:53   ` [Intel-gfx] " Ville Syrjala
2020-09-04 11:53 ` [PATCH v2 16/18] drm/i915: DP->HDMI TMDS clock limits vs. deep color Ville Syrjala
2020-09-04 11:53   ` [Intel-gfx] " Ville Syrjala
2020-09-04 11:53 ` [PATCH v2 17/18] drm/dp: Add helpers for DFP YCbCr 4:2:0 handling Ville Syrjala
2020-09-04 11:53   ` [Intel-gfx] " Ville Syrjala
2020-09-08 18:15   ` Lyude Paul
2020-09-08 18:15     ` [Intel-gfx] " Lyude Paul
2020-09-04 11:53 ` [PATCH v2 18/18] drm/i915: Do YCbCr 444->420 conversion via DP protocol converters Ville Syrjala
2020-09-04 11:53   ` [Intel-gfx] " Ville Syrjala
2020-09-04 13:06 ` [Intel-gfx] ✗ Fi.CI.SPARSE: warning for drm/i915: Pimp DP DFP handling (rev2) Patchwork
2020-09-04 13:21 ` [Intel-gfx] ✓ Fi.CI.BAT: success " Patchwork
2020-09-04 20:09 ` [PATCH v2 00/18] drm/i915: Pimp DP DFP handling Lyude Paul
2020-09-04 20:09   ` [Intel-gfx] " Lyude Paul
2020-09-04 21:32 ` [Intel-gfx] ✗ Fi.CI.IGT: failure for drm/i915: Pimp DP DFP handling (rev2) Patchwork
2020-09-08 18:34 ` [PATCH v2 00/18] drm/i915: Pimp DP DFP handling Lyude Paul
2020-09-08 18:34   ` [Intel-gfx] " Lyude Paul
     [not found]   ` <fa772231854424f2b4edc69e23b0edd924695e6c.camel-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2020-09-17 16:11     ` Ville Syrjälä
2020-09-17 16:11       ` [Intel-gfx] " Ville Syrjälä
2020-09-17 16:11       ` Ville Syrjälä

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.