From: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> 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@xxxxxxxxxxxxxxx> --- 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 --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; -- 2.21.0 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx