All of lore.kernel.org
 help / color / mirror / Atom feed
From: Shashank Sharma <shashank.sharma@intel.com>
To: dri-devel@lists.freedesktop.org, intel-gfx@lists.freedesktop.org
Cc: Ander Conselvan De Oliveira
	<ander.conselvan.de.oliveira@intel.com>,
	Daniel Vetter <daniel.vetter@intel.com>
Subject: [PATCH 08/11] drm/i915: handle ycbcr outputs
Date: Fri,  7 Apr 2017 19:39:25 +0300	[thread overview]
Message-ID: <1491583168-20042-9-git-send-email-shashank.sharma@intel.com> (raw)
In-Reply-To: <1491583168-20042-1-git-send-email-shashank.sharma@intel.com>

This patch adds support for HDMI ycbcr outputs in i915 layer.
HDMI output mode is a connector property, this patch checks if
source and sink can support the HDMI output type selected by user.
And if they both can, it commits the hdmi output type into crtc state,
for further staging in driver.

Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
Cc: Daniel Vetter <daniel.vetter@intel.com>
Cc: Ander Conselvan De Oliveira <ander.conselvan.de.oliveira@intel.com>
Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |   1 +
 drivers/gpu/drm/i915/intel_drv.h     |   3 +
 drivers/gpu/drm/i915/intel_hdmi.c    | 161 ++++++++++++++++++++++++++++++++++-
 3 files changed, 162 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index b6b40cd..fc43a28 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -11705,6 +11705,7 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv,
 	PIPE_CONF_CHECK_I(hdmi_scrambling);
 	PIPE_CONF_CHECK_I(hdmi_high_tmds_clock_ratio);
 	PIPE_CONF_CHECK_I(has_infoframe);
+	PIPE_CONF_CHECK_I(hdmi_output);
 
 	PIPE_CONF_CHECK_I(has_audio);
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 43ea748..98902d4 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -738,6 +738,9 @@ struct intel_crtc_state {
 
 	/* HDMI High TMDS char rate ratio */
 	bool hdmi_high_tmds_clock_ratio;
+
+	/* HDMI output type */
+	enum drm_hdmi_output_type hdmi_output;
 };
 
 struct intel_crtc {
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 76d9e0d..40d3414 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -1301,7 +1301,8 @@ intel_hdmi_mode_valid(struct drm_connector *connector,
 	return status;
 }
 
-static bool hdmi_12bpc_possible(struct intel_crtc_state *crtc_state)
+static bool hdmi_12bpc_possible(struct intel_crtc_state *crtc_state,
+				enum drm_hdmi_output_type hdmi_out)
 {
 	struct drm_i915_private *dev_priv =
 		to_i915(crtc_state->base.crtc->dev);
@@ -1313,6 +1314,16 @@ static bool hdmi_12bpc_possible(struct intel_crtc_state *crtc_state)
 	if (HAS_GMCH_DISPLAY(dev_priv))
 		return false;
 
+	if (hdmi_out == DRM_HDMI_OUTPUT_YCBCR422) {
+		/*
+		 * HDMI spec says YCBCR422 is 12bpc, but its not a deep
+		 * color format. So respect the spec, and not allow this
+		 * to be deep color
+		 */
+		DRM_DEBUG_KMS("Not allowing deep color for YCBCR422 output\n");
+		return false;
+	}
+
 	/*
 	 * HDMI 12bpc affects the clocks, so it's only possible
 	 * when not cloning with other encoder types.
@@ -1333,6 +1344,136 @@ static bool hdmi_12bpc_possible(struct intel_crtc_state *crtc_state)
 	return true;
 }
 
+static inline
+bool _check_ycbcr_mode_support(struct drm_display_mode *mode)
+{
+	return mode->flags & DRM_MODE_FLAG_420_MASK;
+}
+
+static inline
+bool _check_ycbcr_sink_support(struct drm_display_info *display,
+			       enum drm_hdmi_output_type type)
+{
+	return display->color_formats & type;
+}
+
+static inline enum drm_hdmi_output_type
+_get_highest_quality_ycbcr_supported(struct drm_display_info *display,
+			   struct drm_display_mode *mode)
+{
+	/*
+	 * Get the ycbcr output with the highest possible subsampling rate.
+	 * Preference should go as:
+	 * ycbcr 444
+	 * ycbcr 422
+	 * ycbcr 420
+	 */
+	if (display->color_formats & DRM_COLOR_FORMAT_YCRCB444)
+		return DRM_HDMI_OUTPUT_YCBCR444;
+	else if (display->color_formats & DRM_COLOR_FORMAT_YCRCB422)
+		return DRM_HDMI_OUTPUT_YCBCR422;
+	else if (display->color_formats & DRM_COLOR_FORMAT_YCRCB420 &&
+			_check_ycbcr_mode_support(mode))
+		return DRM_HDMI_OUTPUT_YCBCR420;
+	else {
+		DRM_ERROR("Sink does't support any YCBCR output\n");
+		return DRM_HDMI_OUTPUT_INVALID;
+	}
+}
+
+static inline enum drm_hdmi_output_type
+_get_lowest_quality_ycbcr_supported(struct drm_display_info *display,
+			  struct drm_display_mode *mode)
+{
+	/*
+	 * Get the ycbcr output with the lowest possible subsampling rate.
+	 * Preference should go as:
+	 * ycbcr 420
+	 * ycbcr 422
+	 * ycbcr 444
+	 */
+	if (display->color_formats & DRM_COLOR_FORMAT_YCRCB420 &&
+		_check_ycbcr_mode_support(mode))
+		return DRM_HDMI_OUTPUT_YCBCR420;
+	else if (display->color_formats & DRM_COLOR_FORMAT_YCRCB422)
+		return DRM_HDMI_OUTPUT_YCBCR422;
+	else if (display->color_formats & DRM_COLOR_FORMAT_YCRCB444)
+		return DRM_HDMI_OUTPUT_YCBCR420;
+	else {
+		DRM_ERROR("Sink does't support any YCBCR output\n");
+		return DRM_HDMI_OUTPUT_INVALID;
+	}
+}
+
+static inline enum drm_hdmi_output_type
+intel_hdmi_compute_ycbcr_config(struct drm_connector_state *conn_state,
+			       struct intel_crtc_state *config,
+			       int *clock_12bpc, int *clock_8bpc)
+{
+	struct drm_connector *connector = conn_state->connector;
+	struct drm_display_info *info = &connector->display_info;
+	struct drm_display_mode *mode = &config->base.adjusted_mode;
+	enum drm_hdmi_output_type type = conn_state->hdmi_output;
+
+	if (type == DRM_HDMI_OUTPUT_YCBCR_HQ) {
+		type = _get_highest_quality_ycbcr_supported(info, mode);
+		if (type == DRM_HDMI_OUTPUT_INVALID) {
+			DRM_ERROR("Can't support mode %s in YCBCR format\n",
+				  mode->name);
+			return DRM_HDMI_OUTPUT_INVALID;
+		}
+	} else if (type == DRM_HDMI_OUTPUT_YCBCR_LQ) {
+		type = _get_lowest_quality_ycbcr_supported(info, mode);
+		if (type == DRM_HDMI_OUTPUT_INVALID) {
+			DRM_ERROR("Can't support mode %s in YCBCR format\n",
+				  mode->name);
+			return DRM_HDMI_OUTPUT_INVALID;
+		}
+	} else if (!_check_ycbcr_sink_support(info, type)) {
+		DRM_ERROR("Sink doesn't support output mode %s\n",
+			  drm_get_hdmi_output_name(type));
+		return DRM_HDMI_OUTPUT_INVALID;
+	}
+
+	/* Now deal with the preferred and supported output */
+	switch (type) {
+	case DRM_HDMI_OUTPUT_YCBCR420:
+		/*
+		 * Sinks can support ycbcr420 output on a mode-by-mode
+		 * basis, so check if this mode is supported as 420 output
+		 * mode.
+		 */
+		if (!_check_ycbcr_mode_support(mode)) {
+			DRM_ERROR("Sink cant support %s output with %s mode\n",
+				  drm_get_hdmi_output_name(type),
+				  mode->name);
+			return DRM_HDMI_OUTPUT_INVALID;
+		}
+
+		/* ycbcr 420 TMDS rate requirement is half the pixel clock */
+		config->hdmi_output = DRM_HDMI_OUTPUT_YCBCR420;
+		config->port_clock /= 2;
+		*clock_12bpc /= 2;
+		*clock_8bpc /= 2;
+		break;
+
+	case DRM_HDMI_OUTPUT_YCBCR422:
+	case DRM_HDMI_OUTPUT_YCBCR444:
+		break;
+
+	case DRM_HDMI_OUTPUT_INVALID:
+	default:
+		DRM_ERROR("Invalid YCBCR output\n");
+		return DRM_HDMI_OUTPUT_INVALID;
+	}
+
+	/* Encoder is capable of this output, lets commit to CRTC */
+	config->hdmi_output = type;
+	DRM_DEBUG_KMS("HDMI output type is %s\n",
+		      drm_get_hdmi_output_name(type));
+	return type;
+}
+
 bool intel_hdmi_compute_config(struct intel_encoder *encoder,
 			       struct intel_crtc_state *pipe_config,
 			       struct drm_connector_state *conn_state)
@@ -1340,7 +1481,10 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
 	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 	struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
-	struct drm_scdc *scdc = &conn_state->connector->display_info.hdmi.scdc;
+	struct drm_connector *connector = conn_state->connector;
+	struct drm_display_info *info = &connector->display_info;
+	struct drm_scdc *scdc = &info->hdmi.scdc;
+	enum drm_hdmi_output_type hdmi_out = conn_state->hdmi_output;
 	int clock_8bpc = pipe_config->base.adjusted_mode.crtc_clock;
 	int clock_12bpc = clock_8bpc * 3 / 2;
 	int desired_bpp;
@@ -1367,6 +1511,17 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
 		clock_12bpc *= 2;
 	}
 
+	/* YCBCR HDMI output */
+	if (hdmi_out > DRM_HDMI_OUTPUT_DEFAULT_RGB) {
+		hdmi_out = intel_hdmi_compute_ycbcr_config(conn_state,
+						   pipe_config, &clock_12bpc,
+						   &clock_8bpc);
+		if (hdmi_out == DRM_HDMI_OUTPUT_INVALID) {
+			DRM_ERROR("Can't support desired HDMI output\n");
+			return false;
+		}
+	}
+
 	if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv))
 		pipe_config->has_pch_encoder = true;
 
@@ -1381,7 +1536,7 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
 	 */
 	if (pipe_config->pipe_bpp > 8*3 && pipe_config->has_hdmi_sink &&
 	    hdmi_port_clock_valid(intel_hdmi, clock_12bpc, true) == MODE_OK &&
-	    hdmi_12bpc_possible(pipe_config)) {
+	    hdmi_12bpc_possible(pipe_config, hdmi_out)) {
 		DRM_DEBUG_KMS("picking bpc to 12 for HDMI output\n");
 		desired_bpp = 12*3;
 
-- 
2.7.4

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

  parent reply	other threads:[~2017-04-07 16:39 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-04-07 16:39 [PATCH 00/11] HDMI YCBCR output handling in DRM layer Shashank Sharma
2017-04-07 16:39 ` [PATCH 01/11] drm: Add HDMI 2.0 VIC support for AVI info-frames Shashank Sharma
2017-04-10  9:47   ` Andrzej Hajda
2017-04-19 16:02     ` Sharma, Shashank
2017-04-07 16:39 ` [PATCH 02/11] drm/edid: Complete CEA modedb(VIC 1-107) Shashank Sharma
2017-05-08 16:22   ` Ville Syrjälä
2017-05-08 16:44     ` Sharma, Shashank
2017-04-07 16:39 ` [PATCH 03/11] drm: parse ycbcr 420 vdb block Shashank Sharma
2017-05-08 16:24   ` Ville Syrjälä
2017-05-08 16:41     ` Sharma, Shashank
2017-05-08 17:09       ` Ville Syrjälä
2017-05-09  8:34         ` Sharma, Shashank
2017-05-09 15:28           ` Ville Syrjälä
2017-05-10  5:01             ` Sharma, Shashank
2017-04-07 16:39 ` [PATCH 04/11] drm: parse ycbcr420 vcb block Shashank Sharma
2017-04-08 15:14   ` kbuild test robot
2017-04-08 17:43   ` Emil Velikov
2017-04-19 16:04     ` Sharma, Shashank
2017-05-08 16:58   ` Ville Syrjälä
2017-05-09  8:19     ` Sharma, Shashank
2017-04-07 16:39 ` [PATCH 05/11] drm: parse ycbcr 420 deep color information Shashank Sharma
2017-04-08 18:29   ` kbuild test robot
2017-04-07 16:39 ` [PATCH 06/11] drm: create hdmi output property Shashank Sharma
2017-04-08 20:53   ` kbuild test robot
2017-04-12  9:58   ` Jose Abreu
2017-04-19 15:50     ` Sharma, Shashank
2017-04-07 16:39 ` [PATCH 07/11] drm: set output colorspace in AVI infoframe Shashank Sharma
2017-04-12  9:49   ` Jose Abreu
2017-04-19 15:55     ` Sharma, Shashank
2017-04-07 16:39 ` Shashank Sharma [this message]
2017-04-07 16:39 ` [PATCH 09/11] drm/i915: handle csc for ycbcr HDMI output Shashank Sharma
2017-04-07 16:39 ` [PATCH 10/11] drm/i915: prepare ycbcr420 modeset Shashank Sharma
2017-04-07 16:39 ` [PATCH 11/11] drm/i915: set colorspace for ycbcr outputs Shashank Sharma
2017-04-07 17:41 ` ✓ Fi.CI.BAT: success for HDMI YCBCR output handling in DRM layer Patchwork

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1491583168-20042-9-git-send-email-shashank.sharma@intel.com \
    --to=shashank.sharma@intel.com \
    --cc=ander.conselvan.de.oliveira@intel.com \
    --cc=daniel.vetter@intel.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=intel-gfx@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.