mirror of
				https://github.com/Ysurac/openmptcprouter.git
				synced 2025-03-09 15:40:20 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			183 lines
		
	
	
	
		
			6.5 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			183 lines
		
	
	
	
		
			6.5 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
From 7b66d84478c9dec27ca47c9fc0644e524c536570 Mon Sep 17 00:00:00 2001
 | 
						|
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
 | 
						|
Date: Mon, 14 Nov 2022 19:32:10 +0000
 | 
						|
Subject: [PATCH 559/726] drm/vc4: hdmi: Add property to allow manual config of
 | 
						|
 RGB or YCbCr
 | 
						|
 | 
						|
Add a custom property "Output format" that allows the overriding
 | 
						|
of the default colourspace choice in the way that the old
 | 
						|
firmware hdmi_pixel_encoding property did. If the chosen format is not
 | 
						|
supported, then it will still drop back to the older behaviour.
 | 
						|
 | 
						|
This won't be acceptable to upstream, but it adds back the missing
 | 
						|
functionality of hdmi_pixel_encoding.
 | 
						|
 | 
						|
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
 | 
						|
---
 | 
						|
 drivers/gpu/drm/vc4/vc4_hdmi.c | 60 ++++++++++++++++++++++++++++++++++
 | 
						|
 drivers/gpu/drm/vc4/vc4_hdmi.h |  8 +++++
 | 
						|
 2 files changed, 68 insertions(+)
 | 
						|
 | 
						|
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
 | 
						|
index cfdde90fd090..9fbe5d380046 100644
 | 
						|
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
 | 
						|
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
 | 
						|
@@ -556,6 +556,7 @@ static int vc4_hdmi_connector_atomic_check(struct drm_connector *connector,
 | 
						|
 
 | 
						|
 	if (old_state->colorspace != new_state->colorspace ||
 | 
						|
 	    old_vc4_state->broadcast_rgb != new_vc4_state->broadcast_rgb ||
 | 
						|
+	    old_vc4_state->requested_output_format != new_vc4_state->requested_output_format ||
 | 
						|
 	    !drm_connector_atomic_hdr_metadata_equal(old_state, new_state)) {
 | 
						|
 		struct drm_crtc_state *crtc_state;
 | 
						|
 
 | 
						|
@@ -590,6 +591,8 @@ int vc4_hdmi_connector_get_property(struct drm_connector *connector,
 | 
						|
 
 | 
						|
 	if (property == vc4_hdmi->broadcast_rgb_property) {
 | 
						|
 		*val = vc4_conn_state->broadcast_rgb;
 | 
						|
+	} else if (property == vc4_hdmi->output_format_property) {
 | 
						|
+		*val = vc4_conn_state->requested_output_format;
 | 
						|
 	} else {
 | 
						|
 		DRM_DEBUG_ATOMIC("Unknown property [PROP:%d:%s]\n",
 | 
						|
 				 property->base.id, property->name);
 | 
						|
@@ -621,6 +624,9 @@ int vc4_hdmi_connector_set_property(struct drm_connector *connector,
 | 
						|
 	if (property == vc4_hdmi->broadcast_rgb_property) {
 | 
						|
 		vc4_conn_state->broadcast_rgb = val;
 | 
						|
 		return 0;
 | 
						|
+	} else if (property == vc4_hdmi->output_format_property) {
 | 
						|
+		vc4_conn_state->requested_output_format = val;
 | 
						|
+		return 0;
 | 
						|
 	}
 | 
						|
 
 | 
						|
 	DRM_DEBUG_ATOMIC("Unknown property [PROP:%d:%s]\n",
 | 
						|
@@ -664,6 +670,7 @@ vc4_hdmi_connector_duplicate_state(struct drm_connector *connector)
 | 
						|
 	new_state->tmds_char_rate = vc4_state->tmds_char_rate;
 | 
						|
 	new_state->output_bpc = vc4_state->output_bpc;
 | 
						|
 	new_state->output_format = vc4_state->output_format;
 | 
						|
+	new_state->requested_output_format = vc4_state->requested_output_format;
 | 
						|
 	new_state->broadcast_rgb = vc4_state->broadcast_rgb;
 | 
						|
 	__drm_atomic_helper_connector_duplicate_state(connector, &new_state->base);
 | 
						|
 
 | 
						|
@@ -711,6 +718,33 @@ vc4_hdmi_attach_broadcast_rgb_property(struct drm_device *dev,
 | 
						|
 	drm_object_attach_property(&vc4_hdmi->connector.base, prop, 0);
 | 
						|
 }
 | 
						|
 
 | 
						|
+static const struct drm_prop_enum_list output_format_names[] = {
 | 
						|
+	{ VC4_HDMI_OUTPUT_AUTO, "Automatic" },
 | 
						|
+	{ VC4_HDMI_OUTPUT_RGB, "RGB" },
 | 
						|
+	{ VC4_HDMI_OUTPUT_YUV422, "YCbCr 4:2:2" },
 | 
						|
+	{ VC4_HDMI_OUTPUT_YUV444, "YCbCr 4:4:4" },
 | 
						|
+};
 | 
						|
+
 | 
						|
+static void
 | 
						|
+vc4_hdmi_attach_output_format_property(struct drm_device *dev,
 | 
						|
+				       struct vc4_hdmi *vc4_hdmi)
 | 
						|
+{
 | 
						|
+	struct drm_property *prop = vc4_hdmi->output_format_property;
 | 
						|
+
 | 
						|
+	if (!prop) {
 | 
						|
+		prop = drm_property_create_enum(dev, DRM_MODE_PROP_ENUM,
 | 
						|
+						"Output format",
 | 
						|
+						output_format_names,
 | 
						|
+						ARRAY_SIZE(output_format_names));
 | 
						|
+		if (!prop)
 | 
						|
+			return;
 | 
						|
+
 | 
						|
+		vc4_hdmi->output_format_property = prop;
 | 
						|
+	}
 | 
						|
+
 | 
						|
+	drm_object_attach_property(&vc4_hdmi->connector.base, prop, 0);
 | 
						|
+}
 | 
						|
+
 | 
						|
 static int vc4_hdmi_connector_init(struct drm_device *dev,
 | 
						|
 				   struct vc4_hdmi *vc4_hdmi)
 | 
						|
 {
 | 
						|
@@ -758,6 +792,7 @@ static int vc4_hdmi_connector_init(struct drm_device *dev,
 | 
						|
 		drm_connector_attach_hdr_output_metadata_property(connector);
 | 
						|
 
 | 
						|
 	vc4_hdmi_attach_broadcast_rgb_property(dev, vc4_hdmi);
 | 
						|
+	vc4_hdmi_attach_output_format_property(dev, vc4_hdmi);
 | 
						|
 
 | 
						|
 	drm_connector_attach_encoder(connector, encoder);
 | 
						|
 
 | 
						|
@@ -1895,6 +1930,11 @@ static void vc4_hdmi_encoder_atomic_mode_set(struct drm_encoder *encoder,
 | 
						|
 	vc4_hdmi->broadcast_rgb = vc4_state->broadcast_rgb;
 | 
						|
 	vc4_hdmi->output_bpc = vc4_state->output_bpc;
 | 
						|
 	vc4_hdmi->output_format = vc4_state->output_format;
 | 
						|
+	vc4_hdmi->requested_output_format = vc4_state->requested_output_format;
 | 
						|
+	vc4_hdmi->broadcast_rgb = vc4_state->broadcast_rgb;
 | 
						|
+	memcpy(&vc4_hdmi->saved_adjusted_mode,
 | 
						|
+	       &crtc_state->adjusted_mode,
 | 
						|
+	       sizeof(vc4_hdmi->saved_adjusted_mode));
 | 
						|
 	mutex_unlock(&vc4_hdmi->mutex);
 | 
						|
 }
 | 
						|
 
 | 
						|
@@ -2056,6 +2096,26 @@ vc4_hdmi_encoder_compute_format(const struct vc4_hdmi *vc4_hdmi,
 | 
						|
 	const struct drm_display_info *info = &connector->display_info;
 | 
						|
 	unsigned int format;
 | 
						|
 
 | 
						|
+	if (vc4_state->requested_output_format != VC4_HDMI_OUTPUT_AUTO) {
 | 
						|
+		drm_dbg(dev, "Trying with user requested output %u\n",
 | 
						|
+			vc4_state->requested_output_format);
 | 
						|
+
 | 
						|
+		format = vc4_state->requested_output_format;
 | 
						|
+		if (vc4_hdmi_sink_supports_format_bpc(vc4_hdmi, info, mode,
 | 
						|
+						      format, bpc)) {
 | 
						|
+			int ret;
 | 
						|
+
 | 
						|
+			ret = vc4_hdmi_encoder_compute_clock(vc4_hdmi, vc4_state,
 | 
						|
+							     mode, bpc, format);
 | 
						|
+			if (!ret) {
 | 
						|
+				vc4_state->output_format = format;
 | 
						|
+				return 0;
 | 
						|
+			}
 | 
						|
+		}
 | 
						|
+
 | 
						|
+		return -EINVAL;
 | 
						|
+	}
 | 
						|
+
 | 
						|
 	drm_dbg(dev, "Trying with an RGB output\n");
 | 
						|
 
 | 
						|
 	format = VC4_HDMI_OUTPUT_RGB;
 | 
						|
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
 | 
						|
index 268ce4122090..8d0bf52f55e7 100644
 | 
						|
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
 | 
						|
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
 | 
						|
@@ -111,6 +111,7 @@ struct vc4_hdmi_audio {
 | 
						|
 };
 | 
						|
 
 | 
						|
 enum vc4_hdmi_output_format {
 | 
						|
+	VC4_HDMI_OUTPUT_AUTO,
 | 
						|
 	VC4_HDMI_OUTPUT_RGB,
 | 
						|
 	VC4_HDMI_OUTPUT_YUV422,
 | 
						|
 	VC4_HDMI_OUTPUT_YUV444,
 | 
						|
@@ -130,6 +131,7 @@ struct vc4_hdmi {
 | 
						|
 	struct delayed_work scrambling_work;
 | 
						|
 
 | 
						|
 	struct drm_property *broadcast_rgb_property;
 | 
						|
+	struct drm_property *output_format_property;
 | 
						|
 
 | 
						|
 	struct i2c_adapter *ddc;
 | 
						|
 	void __iomem *hdmicore_regs;
 | 
						|
@@ -223,6 +225,11 @@ struct vc4_hdmi {
 | 
						|
 	 * for use outside of KMS hooks. Protected by @mutex.
 | 
						|
 	 */
 | 
						|
 	enum vc4_hdmi_output_format output_format;
 | 
						|
+	/**
 | 
						|
+	 * @requested_output_format: Copy of @vc4_connector_state.requested_output_format
 | 
						|
+	 * for use outside of KMS hooks. Protected by @mutex.
 | 
						|
+	 */
 | 
						|
+	enum vc4_hdmi_output_format requested_output_format;
 | 
						|
 
 | 
						|
 	/**
 | 
						|
 	 * @broadcast_rgb: Copy of @vc4_connector_state.broadcast_rgb
 | 
						|
@@ -249,6 +256,7 @@ struct vc4_hdmi_connector_state {
 | 
						|
 	unsigned long long		tmds_char_rate;
 | 
						|
 	unsigned int 			output_bpc;
 | 
						|
 	enum vc4_hdmi_output_format	output_format;
 | 
						|
+	enum vc4_hdmi_output_format	requested_output_format;
 | 
						|
 	int				broadcast_rgb;
 | 
						|
 };
 | 
						|
 
 | 
						|
-- 
 | 
						|
2.33.1
 | 
						|
 |