diff mbox series

[13/15] drm/i915: Expose margin properties on ilk+ HDMI

Message ID 20190904162625.15048-14-ville.syrjala@linux.intel.com (mailing list archive)
State New, archived
Headers show
Series drm/i915: Expose margin connector properties for underscan | expand

Commit Message

Ville Syrjala Sept. 4, 2019, 4:26 p.m. UTC
From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Add support for underscan by exposing the margin properties on
ilk+ HDMI ports. This can be useful with silly TVs that won't
let you disable overscanning.

We limit this to ilk+ only because the gmch style panel fitter
doesn't really have the flexibility we need.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=29723
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_atomic.c |  4 +++
 drivers/gpu/drm/i915/display/intel_hdmi.c   | 17 +++++++++---
 drivers/gpu/drm/i915/display/intel_panel.c  | 29 ++++++++++++++++-----
 3 files changed, 41 insertions(+), 9 deletions(-)
diff mbox series

Patch

diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c
index d3fb75bb9eb1..6764e32a4b53 100644
--- a/drivers/gpu/drm/i915/display/intel_atomic.c
+++ b/drivers/gpu/drm/i915/display/intel_atomic.c
@@ -145,6 +145,10 @@  int intel_digital_connector_atomic_check(struct drm_connector *conn,
 	    new_conn_state->base.picture_aspect_ratio != old_conn_state->base.picture_aspect_ratio ||
 	    new_conn_state->base.content_type != old_conn_state->base.content_type ||
 	    new_conn_state->base.scaling_mode != old_conn_state->base.scaling_mode ||
+	    new_conn_state->base.tv.margins.left != old_conn_state->base.tv.margins.left ||
+	    new_conn_state->base.tv.margins.right != old_conn_state->base.tv.margins.right ||
+	    new_conn_state->base.tv.margins.top != old_conn_state->base.tv.margins.top ||
+	    new_conn_state->base.tv.margins.bottom != old_conn_state->base.tv.margins.bottom ||
 	    !blob_equal(new_conn_state->base.hdr_output_metadata,
 			old_conn_state->base.hdr_output_metadata))
 		crtc_state->mode_changed = true;
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
index 7bacd9b135eb..287d370f8111 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -732,6 +732,8 @@  intel_hdmi_compute_avi_infoframe(struct intel_encoder *encoder,
 
 	drm_hdmi_avi_infoframe_content_type(frame, conn_state);
 
+	drm_hdmi_avi_infoframe_bars(frame, conn_state);
+
 	/* TODO: handle pixel repetition for YCBCR420 outputs */
 
 	ret = hdmi_avi_infoframe_check(frame);
@@ -2275,13 +2277,13 @@  intel_hdmi_ycbcr420_config(struct intel_crtc_state *crtc_state,
 		return 0;
 
 	if (!connector->ycbcr_420_allowed) {
-		DRM_ERROR("Platform doesn't support YCBCR420 output\n");
+		DRM_DEBUG_KMS("Platform doesn't support YCBCR420 output\n");
 		return -EINVAL;
 	}
 
 	crtc_state->output_format = INTEL_OUTPUT_FORMAT_YCBCR420;
 
-	return intel_pch_panel_fitting(crtc_state, conn_state);
+	return 0;
 }
 
 static int intel_hdmi_port_clock(int clock, int bpc)
@@ -2395,6 +2397,12 @@  int intel_hdmi_compute_config(struct intel_encoder *encoder,
 	if (ret)
 		return ret;
 
+	if (!HAS_GMCH(dev_priv)) {
+		ret = intel_pch_panel_fitting(pipe_config, conn_state);
+		if (ret)
+			return ret;
+	}
+
 	if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv))
 		pipe_config->has_pch_encoder = true;
 
@@ -2834,8 +2842,11 @@  intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *c
 		drm_object_attach_property(&connector->base,
 			connector->dev->mode_config.hdr_output_metadata_property, 0);
 
-	if (!HAS_GMCH(dev_priv))
+	if (!HAS_GMCH(dev_priv)) {
 		drm_connector_attach_max_bpc_property(connector, 8, 12);
+		drm_mode_create_tv_margin_properties(&dev_priv->drm);
+		drm_connector_attach_tv_margin_properties(connector);
+	}
 }
 
 /*
diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c
index f64fa73587ef..57f9bc808f93 100644
--- a/drivers/gpu/drm/i915/display/intel_panel.c
+++ b/drivers/gpu/drm/i915/display/intel_panel.c
@@ -181,12 +181,30 @@  int intel_pch_panel_fitting(struct intel_crtc_state *crtc_state,
 	int scaling_mode = conn_state->scaling_mode;
 	int x, y, width, height;
 
+	x = conn_state->tv.margins.left;
+	y = conn_state->tv.margins.top;
+
+	width = adjusted_mode->crtc_hdisplay -
+		conn_state->tv.margins.left -
+		conn_state->tv.margins.right;
+	height = adjusted_mode->crtc_vdisplay -
+		conn_state->tv.margins.top -
+		conn_state->tv.margins.bottom;
+
+	if (width <= 0 || height <= 0)
+		return -EINVAL;
+
 	/* Native modes don't need fitting */
-	if (adjusted_mode->crtc_hdisplay == crtc_state->pipe_src_w &&
-	    adjusted_mode->crtc_vdisplay == crtc_state->pipe_src_h &&
+	if (x == 0 && y == 0 &&
+	    width == crtc_state->pipe_src_w &&
+	    height == crtc_state->pipe_src_h &&
 	    crtc_state->output_format != INTEL_OUTPUT_FORMAT_YCBCR420)
 		return 0;
 
+	/*
+	 * FIXME: margins and scaling_mode are implemented
+	 * in a mutually exclusive way for the time being.
+	 */
 	switch (scaling_mode) {
 	case DRM_MODE_SCALE_CENTER:
 		width = crtc_state->pipe_src_w;
@@ -224,16 +242,15 @@  int intel_pch_panel_fitting(struct intel_crtc_state *crtc_state,
 		}
 		break;
 
-	case DRM_MODE_SCALE_NONE:
-		WARN_ON(adjusted_mode->crtc_hdisplay != crtc_state->pipe_src_w);
-		WARN_ON(adjusted_mode->crtc_vdisplay != crtc_state->pipe_src_h);
-		/* fall through */
 	case DRM_MODE_SCALE_FULLSCREEN:
 		x = y = 0;
 		width = adjusted_mode->crtc_hdisplay;
 		height = adjusted_mode->crtc_vdisplay;
 		break;
 
+	case DRM_MODE_SCALE_NONE:
+		break;
+
 	default:
 		MISSING_CASE(scaling_mode);
 		return -EINVAL;