[Intel-gfx] [PATCH 5/9] drm/i915/sdvo: Implement limited color range for SDVO HDMI properly

Imre Deak imre.deak at intel.com
Thu Jul 9 10:51:44 UTC 2020


On Wed, Jan 08, 2020 at 08:12:38PM +0200, Ville Syrjala wrote:
> From: Ville Syrjälä <ville.syrjala at linux.intel.com>
> 
> The SDVO/HDMI port register limited color range bit can only be used
> with TMDS encoding and not SDVO encoding, ie. to be used only when
> using the port as a HDMI port as opposed to a SDVO port. The SDVO
> spec does have a note that some GMCHs might allow that, but gen4
> bspec vehemently disagrees. I suppose on ILK+ it might work since
> the color range handling is on the CPU side rather than on the PCH
> side, so there is no clear linkage between the TMDS vs. SDVO
> encoding and color range. Alas, I have no hardware to test that
> theory.
> 
> To implement limited color range support for SDVO->HDMI we need to
> ask the SDVO device to do the range compression. Do so, but first
> check if the device even supports the colorimetry selection.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>

Reviewed-by: Imre Deak <imre.deak at intel.com>

> ---
>  drivers/gpu/drm/i915/display/intel_display.c |  3 +-
>  drivers/gpu/drm/i915/display/intel_hdmi.c    |  4 +-
>  drivers/gpu/drm/i915/display/intel_hdmi.h    |  2 +
>  drivers/gpu/drm/i915/display/intel_sdvo.c    | 62 ++++++++++++--------
>  4 files changed, 45 insertions(+), 26 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index 59c375879186..7ef1f209acc4 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -9888,7 +9888,8 @@ static void ilk_set_pipeconf(const struct intel_crtc_state *crtc_state)
>  	WARN_ON(crtc_state->limited_color_range &&
>  		crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB);
>  
> -	if (crtc_state->limited_color_range)
> +	if (crtc_state->limited_color_range &&
> +	    !intel_crtc_has_type(crtc_state, INTEL_OUTPUT_SDVO))
>  		val |= PIPECONF_COLOR_RANGE_SELECT;
>  
>  	if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB)
> diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
> index 1659cff91426..85c5f840a0fc 100644
> --- a/drivers/gpu/drm/i915/display/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
> @@ -2375,8 +2375,8 @@ static int intel_hdmi_compute_clock(struct intel_encoder *encoder,
>  	return 0;
>  }
>  
> -static bool intel_hdmi_limited_color_range(const struct intel_crtc_state *crtc_state,
> -					   const struct drm_connector_state *conn_state)
> +bool intel_hdmi_limited_color_range(const struct intel_crtc_state *crtc_state,
> +				    const struct drm_connector_state *conn_state)
>  {
>  	const struct intel_digital_connector_state *intel_conn_state =
>  		to_intel_digital_connector_state(conn_state);
> diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.h b/drivers/gpu/drm/i915/display/intel_hdmi.h
> index cf1ea5427639..c5f59c20f1e8 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,
>  			  const struct intel_crtc_state *crtc_state,
>  			  enum hdmi_infoframe_type type,
>  			  union hdmi_infoframe *frame);
> +bool intel_hdmi_limited_color_range(const struct intel_crtc_state *crtc_state,
> +				    const struct drm_connector_state *conn_state);
>  
>  #endif /* __INTEL_HDMI_H__ */
> diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c
> index 2d2c5e1c7e7c..a0bbd728aa54 100644
> --- a/drivers/gpu/drm/i915/display/intel_sdvo.c
> +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c
> @@ -95,6 +95,8 @@ struct intel_sdvo {
>  	 */
>  	struct intel_sdvo_caps caps;
>  
> +	u8 colorimetry_cap;
> +
>  	/* Pixel clock limitations reported by the SDVO device, in kHz */
>  	int pixel_clock_min, pixel_clock_max;
>  
> @@ -1271,6 +1273,18 @@ static bool intel_has_hdmi_sink(struct intel_sdvo *sdvo,
>  		READ_ONCE(to_intel_digital_connector_state(conn_state)->force_audio) != HDMI_AUDIO_OFF_DVI;
>  }
>  
> +static bool intel_sdvo_limited_color_range(struct intel_encoder *encoder,
> +					   const struct intel_crtc_state *crtc_state,
> +					   const struct drm_connector_state *conn_state)
> +{
> +	struct intel_sdvo *intel_sdvo = to_sdvo(encoder);
> +
> +	if ((intel_sdvo->colorimetry_cap & SDVO_COLORIMETRY_RGB220) == 0)
> +		return false;
> +
> +	return intel_hdmi_limited_color_range(crtc_state, conn_state);
> +}
> +
>  static int intel_sdvo_compute_config(struct intel_encoder *encoder,
>  				     struct intel_crtc_state *pipe_config,
>  				     struct drm_connector_state *conn_state)
> @@ -1336,21 +1350,9 @@ static int intel_sdvo_compute_config(struct intel_encoder *encoder,
>  				intel_sdvo_state->base.force_audio == HDMI_AUDIO_ON;
>  	}
>  
> -	if (intel_sdvo_state->base.broadcast_rgb == INTEL_BROADCAST_RGB_AUTO) {
> -		/*
> -		 * See CEA-861-E - 5.1 Default Encoding Parameters
> -		 *
> -		 * FIXME: This bit is only valid when using TMDS encoding and 8
> -		 * bit per color mode.
> -		 */
> -		if (pipe_config->has_hdmi_sink &&
> -		    drm_match_cea_mode(adjusted_mode) > 1)
> -			pipe_config->limited_color_range = true;
> -	} else {
> -		if (pipe_config->has_hdmi_sink &&
> -		    intel_sdvo_state->base.broadcast_rgb == INTEL_BROADCAST_RGB_LIMITED)
> -			pipe_config->limited_color_range = true;
> -	}
> +	pipe_config->limited_color_range =
> +		intel_sdvo_limited_color_range(encoder, pipe_config,
> +					       conn_state);
>  
>  	/* Clock computation needs to happen after pixel multiplier. */
>  	if (IS_TV(intel_sdvo_connector))
> @@ -1487,6 +1489,8 @@ static void intel_sdvo_pre_enable(struct intel_encoder *intel_encoder,
>  	if (crtc_state->has_hdmi_sink) {
>  		intel_sdvo_set_encode(intel_sdvo, SDVO_ENCODE_HDMI);
>  		intel_sdvo_set_colorimetry(intel_sdvo,
> +					   crtc_state->limited_color_range ?
> +					   SDVO_COLORIMETRY_RGB220 :
>  					   SDVO_COLORIMETRY_RGB256);
>  		intel_sdvo_set_avi_infoframe(intel_sdvo, crtc_state);
>  	} else
> @@ -1520,8 +1524,6 @@ static void intel_sdvo_pre_enable(struct intel_encoder *intel_encoder,
>  		/* The real mode polarity is set by the SDVO commands, using
>  		 * struct intel_sdvo_dtd. */
>  		sdvox = SDVO_VSYNC_ACTIVE_HIGH | SDVO_HSYNC_ACTIVE_HIGH;
> -		if (!HAS_PCH_SPLIT(dev_priv) && crtc_state->limited_color_range)
> -			sdvox |= HDMI_COLOR_RANGE_16_235;
>  		if (INTEL_GEN(dev_priv) < 5)
>  			sdvox |= SDVO_BORDER_ENABLE;
>  	} else {
> @@ -1678,8 +1680,11 @@ static void intel_sdvo_get_config(struct intel_encoder *encoder,
>  	     "SDVO pixel multiplier mismatch, port: %i, encoder: %i\n",
>  	     pipe_config->pixel_multiplier, encoder_pixel_multiplier);
>  
> -	if (sdvox & HDMI_COLOR_RANGE_16_235)
> -		pipe_config->limited_color_range = true;
> +	if (intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_COLORIMETRY,
> +				 &val, 1)) {
> +		if (val == SDVO_COLORIMETRY_RGB220)
> +			pipe_config->limited_color_range = true;
> +	}
>  
>  	if (intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_AUDIO_STAT,
>  				 &val, 1)) {
> @@ -1898,6 +1903,17 @@ static bool intel_sdvo_get_capabilities(struct intel_sdvo *intel_sdvo, struct in
>  	return true;
>  }
>  
> +static u8 intel_sdvo_get_colorimetry_cap(struct intel_sdvo *intel_sdvo)
> +{
> +	u8 cap;
> +
> +	if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_COLORIMETRY_CAP,
> +				  &cap, sizeof(cap)))
> +		return SDVO_COLORIMETRY_RGB256;
> +
> +	return cap;
> +}
> +
>  static u16 intel_sdvo_get_hotplug_support(struct intel_sdvo *intel_sdvo)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(intel_sdvo->base.base.dev);
> @@ -2654,12 +2670,9 @@ static void
>  intel_sdvo_add_hdmi_properties(struct intel_sdvo *intel_sdvo,
>  			       struct intel_sdvo_connector *connector)
>  {
> -	struct drm_i915_private *dev_priv = to_i915(connector->base.base.dev);
> -
>  	intel_attach_force_audio_property(&connector->base.base);
> -	if (INTEL_GEN(dev_priv) >= 4 && IS_MOBILE(dev_priv)) {
> +	if (intel_sdvo->colorimetry_cap & SDVO_COLORIMETRY_RGB220)
>  		intel_attach_broadcast_rgb_property(&connector->base.base);
> -	}
>  	intel_attach_aspect_ratio_property(&connector->base.base);
>  }
>  
> @@ -3298,6 +3311,9 @@ bool intel_sdvo_init(struct drm_i915_private *dev_priv,
>  	if (!intel_sdvo_get_capabilities(intel_sdvo, &intel_sdvo->caps))
>  		goto err;
>  
> +	intel_sdvo->colorimetry_cap =
> +		intel_sdvo_get_colorimetry_cap(intel_sdvo);
> +
>  	if (intel_sdvo_output_setup(intel_sdvo,
>  				    intel_sdvo->caps.output_flags) != true) {
>  		DRM_DEBUG_KMS("SDVO output failed to setup on %s\n",
> -- 
> 2.24.1
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx


More information about the Intel-gfx mailing list