All of lore.kernel.org
 help / color / mirror / Atom feed
* [RESEND-CI v4 00/15] HDMI YCBCR output handling in DRM layer
@ 2017-06-21 10:33 Shashank Sharma
  2017-06-21 10:33 ` [RESEND-CI v4 01/15] drm: add HDMI 2.0 VIC support for AVI info-frames Shashank Sharma
                   ` (14 more replies)
  0 siblings, 15 replies; 58+ messages in thread
From: Shashank Sharma @ 2017-06-21 10:33 UTC (permalink / raw)
  To: dri-devel, intel-gfx, ville.syrjala

This patch series adds support for YCBCR HDMI output handling in DRM layer.
The main aim of this patch series was to handle YCBCR 4:2:0 output for
HDMI 2.0 displays. But while providing a framework to handle non-RGB
outputs, support for YCBCR 4:4:4 and 4:2:2 was also added.

First 2 patches, complete the CEA mode-db in drm driver, by adding
new 4k modes. Current CEA mode-db contains 64 modes only (VIC 1-64),
whereas CEA-861-F defined VICs up to 107, including 4k modes, from VIC range
93-107. First patch makes sure that inclusion of these modes doesn't break
existing HDMI 1.4 monitors, across various drivers.

Next 3 patches focus on parsing new YCBCR 4:2:0 EDID blocks, and adding
YCBCR 4:2:0 modes in connector (only for connectors who declare themselves
as HDMI 2.0 compliant during init)

Next 6 patch create a property (hdmi_output_format) and add the framework
to handle the HDMI output type defined in the property. There are also some
helper functions provided, to help with the YCBCR HDMI output, like adding
deep color information, set color space and get the appropriate YCBCR output
based on source + sink capabilities.

A User can set the HDMI output property, and select the desired output
from YCBCR 4:4:4, 4:2:2 or 4:2:0. A driver can use framework's helper
functions to check if this source + sink + mode combination can drive
the desired output, or what would be the best suitable output.

By default the value of the property is default RGB, so if you don't
set the property, there is no change in the regular functionality of
an existing source.

More details are available with respective patches.

Last 6 patches add the I915 core implementation of the HDMI output handling.
This patch series was tested with a GLK device, ACER S277HK monitor and
ASTRO VA-1844A HDMI analyzer.

V3: Added a new patch to introduce YCBCR_420_allowed identifier.
V4: Added a new patch to re-sequence sink info parsing befor CEA modes.
V4-RESEND-CI: Added V5 for patch 7, to fix CI regression, no
	      change elsewhere.

Shashank Sharma (15):
  drm: add HDMI 2.0 VIC support for AVI info-frames
  drm: add YCBCR 420 capability identifier
  drm/edid: Complete CEA modedb(VIC 1-107)
  drm/edid: parse YCBCR 420 videomodes from EDID
  drm/edid: parse ycbcr 420 deep color information
  drm/edid: parse sink information before CEA blocks
  drm: create hdmi output property
  drm: set output colorspace in AVI infoframe
  drm: add helper functions for YCBCR output handling
  drm/i915: add compute-config for YCBCR outputs
  drm/i915: prepare scaler for YCBCR420 modeset
  drm/i915: prepare pipe for YCBCR output
  drm/i915: prepare csc unit for YCBCR HDMI output
  drm/i915: set colorspace for ycbcr outputs
  drm/i915/glk: set HDMI 2.0 identifier

 drivers/gpu/drm/amd/amdgpu/dce_v10_0.c    |   2 +-
 drivers/gpu/drm/amd/amdgpu/dce_v11_0.c    |   2 +-
 drivers/gpu/drm/amd/amdgpu/dce_v8_0.c     |   2 +-
 drivers/gpu/drm/bridge/analogix-anx78xx.c |   3 +-
 drivers/gpu/drm/bridge/sii902x.c          |   2 +-
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c |   2 +-
 drivers/gpu/drm/drm_atomic.c              |   4 +
 drivers/gpu/drm/drm_atomic_helper.c       |   4 +
 drivers/gpu/drm/drm_connector.c           |  32 +++
 drivers/gpu/drm/drm_edid.c                | 462 +++++++++++++++++++++++++++++-
 drivers/gpu/drm/drm_modes.c               | 307 ++++++++++++++++++++
 drivers/gpu/drm/exynos/exynos_hdmi.c      |   2 +-
 drivers/gpu/drm/i2c/tda998x_drv.c         |   2 +-
 drivers/gpu/drm/i915/i915_reg.h           |   3 +
 drivers/gpu/drm/i915/intel_atomic.c       |   6 +
 drivers/gpu/drm/i915/intel_color.c        |  47 ++-
 drivers/gpu/drm/i915/intel_display.c      |  68 +++++
 drivers/gpu/drm/i915/intel_drv.h          |  13 +-
 drivers/gpu/drm/i915/intel_hdmi.c         | 131 ++++++++-
 drivers/gpu/drm/i915/intel_panel.c        |   3 +-
 drivers/gpu/drm/i915/intel_sdvo.c         |   3 +-
 drivers/gpu/drm/mediatek/mtk_hdmi.c       |   2 +-
 drivers/gpu/drm/omapdrm/omap_encoder.c    |   3 +-
 drivers/gpu/drm/radeon/radeon_audio.c     |   2 +-
 drivers/gpu/drm/rockchip/inno_hdmi.c      |   2 +-
 drivers/gpu/drm/sti/sti_hdmi.c            |   2 +-
 drivers/gpu/drm/tegra/hdmi.c              |   2 +-
 drivers/gpu/drm/tegra/sor.c               |   2 +-
 drivers/gpu/drm/vc4/vc4_hdmi.c            |   2 +-
 drivers/gpu/drm/zte/zx_hdmi.c             |   2 +-
 include/drm/drm_connector.h               |  50 ++++
 include/drm/drm_edid.h                    |  14 +-
 include/drm/drm_mode_config.h             |   5 +
 include/drm/drm_modes.h                   |   5 +
 34 files changed, 1159 insertions(+), 34 deletions(-)

-- 
2.7.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 58+ messages in thread

* [RESEND-CI v4 01/15] drm: add HDMI 2.0 VIC support for AVI info-frames
  2017-06-21 10:33 [RESEND-CI v4 00/15] HDMI YCBCR output handling in DRM layer Shashank Sharma
@ 2017-06-21 10:33 ` Shashank Sharma
  2017-06-21 13:41   ` Neil Armstrong
  2017-06-30 11:54   ` Ville Syrjälä
  2017-06-21 10:34 ` [RESEND-CI v4 02/15] drm: add YCBCR 420 capability identifier Shashank Sharma
                   ` (13 subsequent siblings)
  14 siblings, 2 replies; 58+ messages in thread
From: Shashank Sharma @ 2017-06-21 10:33 UTC (permalink / raw)
  To: dri-devel, intel-gfx, ville.syrjala
  Cc: Jose Abreu, Alex Deucher, Daniel Vetter

HDMI 1.4b support the CEA video modes as per range of CEA-861-D (VIC 1-64).
For any other mode, the VIC filed in AVI infoframes should be 0.
HDMI 2.0 sinks, support video modes range as per CEA-861-F spec, which is
extended to (VIC 1-107).

This patch adds a bool input variable, which indicates if the connected
sink is a HDMI 2.0 sink or not. This will make sure that we don't pass a
HDMI 2.0 VIC to a HDMI 1.4 sink.

This patch touches all drm drivers, who are callers of this function
drm_hdmi_avi_infoframe_from_display_mode but to make sure there is
no change in current behavior, is_hdmi2 is kept as false.

In case of I915 driver, this patch:
- checks if the connected display is HDMI 2.0.
- HDMI infoframes carry one of this two type of information:
	- VIC for 4K modes for HDMI 1.4 sinks
	- S3D information for S3D modes
  As CEA-861-F has already defined VICs for 4K videomodes, this
  patch doesn't allow sending HDMI infoframes for HDMI 2.0 sinks,
  until the mode is 3D.

Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
Cc: Jose Abreu <jose.abreu@synopsys.com>
Cc: Andrzej Hajda <a.hajda@samsung.com>
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: Daniel Vetter <daniel.vetter@intel.com>

PS: This patch touches a few lines in few files, which were
already above 80 char, so checkpatch gives 80 char warning again.
- gpu/drm/omapdrm/omap_encoder.c
- gpu/drm/i915/intel_sdvo.c

V2: Rebase, Added r-b from Andrzej
V3: Addressed review comment from Ville:
	- Do not send VICs in both AVI-IF and HDMI-IF
	  send only one of it.

Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
---
 drivers/gpu/drm/amd/amdgpu/dce_v10_0.c    |  2 +-
 drivers/gpu/drm/amd/amdgpu/dce_v11_0.c    |  2 +-
 drivers/gpu/drm/amd/amdgpu/dce_v8_0.c     |  2 +-
 drivers/gpu/drm/bridge/analogix-anx78xx.c |  3 ++-
 drivers/gpu/drm/bridge/sii902x.c          |  2 +-
 drivers/gpu/drm/bridge/synopsys/dw-hdmi.c |  2 +-
 drivers/gpu/drm/drm_edid.c                | 12 +++++++++++-
 drivers/gpu/drm/exynos/exynos_hdmi.c      |  2 +-
 drivers/gpu/drm/i2c/tda998x_drv.c         |  2 +-
 drivers/gpu/drm/i915/intel_hdmi.c         | 17 ++++++++++++++++-
 drivers/gpu/drm/i915/intel_sdvo.c         |  3 ++-
 drivers/gpu/drm/mediatek/mtk_hdmi.c       |  2 +-
 drivers/gpu/drm/omapdrm/omap_encoder.c    |  3 ++-
 drivers/gpu/drm/radeon/radeon_audio.c     |  2 +-
 drivers/gpu/drm/rockchip/inno_hdmi.c      |  2 +-
 drivers/gpu/drm/sti/sti_hdmi.c            |  2 +-
 drivers/gpu/drm/tegra/hdmi.c              |  2 +-
 drivers/gpu/drm/tegra/sor.c               |  2 +-
 drivers/gpu/drm/vc4/vc4_hdmi.c            |  2 +-
 drivers/gpu/drm/zte/zx_hdmi.c             |  2 +-
 include/drm/drm_edid.h                    |  3 ++-
 21 files changed, 50 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
index 3c62c45..4923ddc 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
@@ -1864,7 +1864,7 @@ static void dce_v10_0_afmt_setmode(struct drm_encoder *encoder,
 	dce_v10_0_audio_write_sad_regs(encoder);
 	dce_v10_0_audio_write_latency_fields(encoder, mode);
 
-	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
+	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
 	if (err < 0) {
 		DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
 		return;
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
index c8ed0fa..4101684 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
@@ -1848,7 +1848,7 @@ static void dce_v11_0_afmt_setmode(struct drm_encoder *encoder,
 	dce_v11_0_audio_write_sad_regs(encoder);
 	dce_v11_0_audio_write_latency_fields(encoder, mode);
 
-	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
+	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
 	if (err < 0) {
 		DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
 		return;
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
index 3e90c19..a7f6b32 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
@@ -1747,7 +1747,7 @@ static void dce_v8_0_afmt_setmode(struct drm_encoder *encoder,
 	dce_v8_0_audio_write_sad_regs(encoder);
 	dce_v8_0_audio_write_latency_fields(encoder, mode);
 
-	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
+	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
 	if (err < 0) {
 		DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
 		return;
diff --git a/drivers/gpu/drm/bridge/analogix-anx78xx.c b/drivers/gpu/drm/bridge/analogix-anx78xx.c
index 9006578..a083211 100644
--- a/drivers/gpu/drm/bridge/analogix-anx78xx.c
+++ b/drivers/gpu/drm/bridge/analogix-anx78xx.c
@@ -1097,7 +1097,8 @@ static void anx78xx_bridge_mode_set(struct drm_bridge *bridge,
 
 	mutex_lock(&anx78xx->lock);
 
-	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, adjusted_mode);
+	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, adjusted_mode,
+						       false);
 	if (err) {
 		DRM_ERROR("Failed to setup AVI infoframe: %d\n", err);
 		goto unlock;
diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c
index 9b87067..3dc40f6 100644
--- a/drivers/gpu/drm/bridge/sii902x.c
+++ b/drivers/gpu/drm/bridge/sii902x.c
@@ -269,7 +269,7 @@ static void sii902x_bridge_mode_set(struct drm_bridge *bridge,
 	if (ret)
 		return;
 
-	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame, adj);
+	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame, adj, false);
 	if (ret < 0) {
 		DRM_ERROR("couldn't fill AVI infoframe\n");
 		return;
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index ead1124..0b0c9de 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -1317,7 +1317,7 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
 	u8 val;
 
 	/* Initialise info frame from DRM mode */
-	drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
+	drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
 
 	if (hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format))
 		frame.colorspace = HDMI_COLORSPACE_YUV444;
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 2e55599..d312fe1 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -4334,12 +4334,14 @@ EXPORT_SYMBOL(drm_set_preferred_mode);
  *                                              data from a DRM display mode
  * @frame: HDMI AVI infoframe
  * @mode: DRM display mode
+ * @is_hdmi2_sink: Sink is HDMI 2.0 compliant
  *
  * Return: 0 on success or a negative error code on failure.
  */
 int
 drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
-					 const struct drm_display_mode *mode)
+					 const struct drm_display_mode *mode,
+					 bool is_hdmi2_sink)
 {
 	int err;
 
@@ -4355,6 +4357,14 @@ drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
 
 	frame->video_code = drm_match_cea_mode(mode);
 
+	/*
+	 * HDMI 1.4 VIC range: 1 <= VIC <= 64 (CEA-861-D) but
+	 * HDMI 2.0 VIC range: 1 <= VIC <= 107 (CEA-861-F). So we
+	 * have to make sure we dont break HDMI 1.4 sinks.
+	 */
+	if (!is_hdmi2_sink && frame->video_code > 64)
+		frame->video_code = 0;
+
 	frame->picture_aspect = HDMI_PICTURE_ASPECT_NONE;
 
 	/*
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 06bfbe4..c953927 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -784,7 +784,7 @@ static void hdmi_reg_infoframes(struct hdmi_context *hdata)
 	}
 
 	ret = drm_hdmi_avi_infoframe_from_display_mode(&frm.avi,
-			&hdata->current_mode);
+			&hdata->current_mode, false);
 	if (!ret)
 		ret = hdmi_avi_infoframe_pack(&frm.avi, buf, sizeof(buf));
 	if (ret > 0) {
diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
index 86f47e1..d1e7ac5 100644
--- a/drivers/gpu/drm/i2c/tda998x_drv.c
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -712,7 +712,7 @@ tda998x_write_avi(struct tda998x_priv *priv, struct drm_display_mode *mode)
 {
 	union hdmi_infoframe frame;
 
-	drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
+	drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
 	frame.avi.quantization_range = HDMI_QUANTIZATION_RANGE_FULL;
 
 	tda998x_write_if(priv, DIP_IF_FLAGS_IF2, REG_IF2_HB0, &frame);
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index ec0779a..170abc4 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -459,11 +459,14 @@ static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder,
 	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
 	const struct drm_display_mode *adjusted_mode =
 		&crtc_state->base.adjusted_mode;
+	struct drm_connector *connector = &intel_hdmi->attached_connector->base;
+	bool is_hdmi2_sink = connector->display_info.hdmi.scdc.supported;
 	union hdmi_infoframe frame;
 	int ret;
 
 	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
-						       adjusted_mode);
+						       adjusted_mode,
+						       is_hdmi2_sink);
 	if (ret < 0) {
 		DRM_ERROR("couldn't fill AVI infoframe\n");
 		return;
@@ -816,6 +819,8 @@ static void hsw_set_infoframes(struct drm_encoder *encoder,
 {
 	struct drm_i915_private *dev_priv = to_i915(encoder->dev);
 	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+	struct drm_hdmi_info *hdmi = &conn_state->connector->display_info.hdmi;
+	const struct drm_display_mode *mode = &crtc_state->base.adjusted_mode;
 	i915_reg_t reg = HSW_TVIDEO_DIP_CTL(crtc_state->cpu_transcoder);
 	u32 val = I915_READ(reg);
 
@@ -839,6 +844,16 @@ static void hsw_set_infoframes(struct drm_encoder *encoder,
 
 	intel_hdmi_set_avi_infoframe(encoder, crtc_state);
 	intel_hdmi_set_spd_infoframe(encoder, crtc_state);
+
+	/*
+	 * CEA-861-F added new VICs for 4k video modes, due to which
+	 * HDMI 2.0 sinks need HDMI IF only for S3D information (Not for
+	 * 4k VICs). So for a HDMI 2.0 sink, if the video mode is not 3D,
+	 * don't bother sending HDMI IF.
+	 */
+	if (hdmi->scdc.supported && !(mode->flags & DRM_MODE_FLAG_3D_MASK))
+		return;
+
 	intel_hdmi_set_hdmi_infoframe(encoder, crtc_state);
 }
 
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index f4329d2..737076e 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -996,7 +996,8 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo,
 	ssize_t len;
 
 	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
-						       &pipe_config->base.adjusted_mode);
+						       &pipe_config->base.adjusted_mode,
+						       false);
 	if (ret < 0) {
 		DRM_ERROR("couldn't fill AVI infoframe\n");
 		return false;
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
index 0a4ffd7..5c0d024 100644
--- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
@@ -975,7 +975,7 @@ static int mtk_hdmi_setup_avi_infoframe(struct mtk_hdmi *hdmi,
 	u8 buffer[17];
 	ssize_t err;
 
-	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
+	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
 	if (err < 0) {
 		dev_err(hdmi->dev,
 			"Failed to get AVI infoframe from mode: %zd\n", err);
diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c b/drivers/gpu/drm/omapdrm/omap_encoder.c
index 86c977b..624f5b5 100644
--- a/drivers/gpu/drm/omapdrm/omap_encoder.c
+++ b/drivers/gpu/drm/omapdrm/omap_encoder.c
@@ -85,7 +85,8 @@ static void omap_encoder_mode_set(struct drm_encoder *encoder,
 	if (hdmi_mode && dssdev->driver->set_hdmi_infoframe) {
 		struct hdmi_avi_infoframe avi;
 
-		r = drm_hdmi_avi_infoframe_from_display_mode(&avi, adjusted_mode);
+		r = drm_hdmi_avi_infoframe_from_display_mode(&avi, adjusted_mode,
+							     false);
 		if (r == 0)
 			dssdev->driver->set_hdmi_infoframe(dssdev, &avi);
 	}
diff --git a/drivers/gpu/drm/radeon/radeon_audio.c b/drivers/gpu/drm/radeon/radeon_audio.c
index aaacac1..770e31f 100644
--- a/drivers/gpu/drm/radeon/radeon_audio.c
+++ b/drivers/gpu/drm/radeon/radeon_audio.c
@@ -516,7 +516,7 @@ static int radeon_audio_set_avi_packet(struct drm_encoder *encoder,
 	if (!connector)
 		return -EINVAL;
 
-	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
+	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
 	if (err < 0) {
 		DRM_ERROR("failed to setup AVI infoframe: %d\n", err);
 		return err;
diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c
index 7d9b75e..7149968 100644
--- a/drivers/gpu/drm/rockchip/inno_hdmi.c
+++ b/drivers/gpu/drm/rockchip/inno_hdmi.c
@@ -294,7 +294,7 @@ static int inno_hdmi_config_video_avi(struct inno_hdmi *hdmi,
 	union hdmi_infoframe frame;
 	int rc;
 
-	rc = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
+	rc = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
 
 	if (hdmi->hdmi_data.enc_out_format == HDMI_COLORSPACE_YUV444)
 		frame.avi.colorspace = HDMI_COLORSPACE_YUV444;
diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
index a59c95a..dbc6a19 100644
--- a/drivers/gpu/drm/sti/sti_hdmi.c
+++ b/drivers/gpu/drm/sti/sti_hdmi.c
@@ -434,7 +434,7 @@ static int hdmi_avi_infoframe_config(struct sti_hdmi *hdmi)
 
 	DRM_DEBUG_DRIVER("\n");
 
-	ret = drm_hdmi_avi_infoframe_from_display_mode(&infoframe, mode);
+	ret = drm_hdmi_avi_infoframe_from_display_mode(&infoframe, mode, false);
 	if (ret < 0) {
 		DRM_ERROR("failed to setup AVI infoframe: %d\n", ret);
 		return ret;
diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c
index cda0491..718d8db 100644
--- a/drivers/gpu/drm/tegra/hdmi.c
+++ b/drivers/gpu/drm/tegra/hdmi.c
@@ -734,7 +734,7 @@ static void tegra_hdmi_setup_avi_infoframe(struct tegra_hdmi *hdmi,
 	u8 buffer[17];
 	ssize_t err;
 
-	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
+	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
 	if (err < 0) {
 		dev_err(hdmi->dev, "failed to setup AVI infoframe: %zd\n", err);
 		return;
diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c
index a8f5289..fb2709c 100644
--- a/drivers/gpu/drm/tegra/sor.c
+++ b/drivers/gpu/drm/tegra/sor.c
@@ -1904,7 +1904,7 @@ tegra_sor_hdmi_setup_avi_infoframe(struct tegra_sor *sor,
 	value &= ~INFOFRAME_CTRL_ENABLE;
 	tegra_sor_writel(sor, value, SOR_HDMI_AVI_INFOFRAME_CTRL);
 
-	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
+	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
 	if (err < 0) {
 		dev_err(sor->dev, "failed to setup AVI infoframe: %d\n", err);
 		return err;
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index ed63d4e..406d6d8 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -395,7 +395,7 @@ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
 	union hdmi_infoframe frame;
 	int ret;
 
-	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
+	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
 	if (ret < 0) {
 		DRM_ERROR("couldn't fill AVI infoframe\n");
 		return;
diff --git a/drivers/gpu/drm/zte/zx_hdmi.c b/drivers/gpu/drm/zte/zx_hdmi.c
index 0df7366..7e834e3 100644
--- a/drivers/gpu/drm/zte/zx_hdmi.c
+++ b/drivers/gpu/drm/zte/zx_hdmi.c
@@ -124,7 +124,7 @@ static int zx_hdmi_config_video_avi(struct zx_hdmi *hdmi,
 	union hdmi_infoframe frame;
 	int ret;
 
-	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
+	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
 	if (ret) {
 		DRM_DEV_ERROR(hdmi->dev, "failed to get avi infoframe: %d\n",
 			      ret);
diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
index 7b9f48b..89c0062 100644
--- a/include/drm/drm_edid.h
+++ b/include/drm/drm_edid.h
@@ -343,7 +343,8 @@ drm_load_edid_firmware(struct drm_connector *connector)
 
 int
 drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
-					 const struct drm_display_mode *mode);
+					 const struct drm_display_mode *mode,
+					 bool is_hdmi2_sink);
 int
 drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame,
 					    const struct drm_display_mode *mode);
-- 
2.7.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 58+ messages in thread

* [RESEND-CI v4 02/15] drm: add YCBCR 420 capability identifier
  2017-06-21 10:33 [RESEND-CI v4 00/15] HDMI YCBCR output handling in DRM layer Shashank Sharma
  2017-06-21 10:33 ` [RESEND-CI v4 01/15] drm: add HDMI 2.0 VIC support for AVI info-frames Shashank Sharma
@ 2017-06-21 10:34 ` Shashank Sharma
  2017-06-21 13:42   ` Neil Armstrong
  2017-06-21 10:34 ` [RESEND-CI v4 03/15] drm/edid: Complete CEA modedb(VIC 1-107) Shashank Sharma
                   ` (12 subsequent siblings)
  14 siblings, 1 reply; 58+ messages in thread
From: Shashank Sharma @ 2017-06-21 10:34 UTC (permalink / raw)
  To: dri-devel, intel-gfx, ville.syrjala

This patch adds a bool variable (ycbcr_420_allowed) in the drm connector
structure. While handling the EDID from HDMI 2.0 sinks, its important to
know if the source is capable of handling YCBCR 420 outputs or not, so that
a lot of work can be done/bypassed based on this information. One such
example is adding YCBCR420 only modes.

If the driver knows that this source is not HDMI 2.0 capable, it will
not add YCBCR420-only modes while adding EDID modes, and will prevent
any runtime modeset failures.

This variable will be initialized from I915 driver in the next patch
and will be used in the EDID handling for HDMI 2.0 specific features,
in this same series.

V3: introduced the new variable
V4: changed variable name from is_hdmi2_src to ycbcr_420_allowed (Ville)

Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
---
 include/drm/drm_connector.h | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index d8bb25f..7493fd3 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -728,6 +728,15 @@ struct drm_connector {
 	bool interlace_allowed;
 	bool doublescan_allowed;
 	bool stereo_allowed;
+
+	/**
+	 * @ycbcr_420_allowed : This bool indicates if this connector is
+	 * capable of handling YCBCR 420 output. While parsing the EDID
+	 * blocks, its very helpful to know, if the source is capable of
+	 * handling YCBCR 420 outputs.
+	 */
+	bool ycbcr_420_allowed;
+
 	/**
 	 * @registered: Is this connector exposed (registered) with userspace?
 	 * Protected by @mutex.
-- 
2.7.4

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

^ permalink raw reply related	[flat|nested] 58+ messages in thread

* [RESEND-CI v4 03/15] drm/edid: Complete CEA modedb(VIC 1-107)
  2017-06-21 10:33 [RESEND-CI v4 00/15] HDMI YCBCR output handling in DRM layer Shashank Sharma
  2017-06-21 10:33 ` [RESEND-CI v4 01/15] drm: add HDMI 2.0 VIC support for AVI info-frames Shashank Sharma
  2017-06-21 10:34 ` [RESEND-CI v4 02/15] drm: add YCBCR 420 capability identifier Shashank Sharma
@ 2017-06-21 10:34 ` Shashank Sharma
  2017-06-21 13:42   ` Neil Armstrong
  2017-06-27 11:32   ` Ville Syrjälä
  2017-06-21 10:34 ` [RESEND-CI v4 04/15] drm/edid: parse YCBCR 420 videomodes from EDID Shashank Sharma
                   ` (11 subsequent siblings)
  14 siblings, 2 replies; 58+ messages in thread
From: Shashank Sharma @ 2017-06-21 10:34 UTC (permalink / raw)
  To: dri-devel, intel-gfx, ville.syrjala
  Cc: Jose Abreu, Andrzej Hajda, Alex Deucher, Harry Wentland

CEA-861-F specs defines new video modes to be used with
HDMI 2.0 EDIDs. The VIC range has been extended from 1-64 to
1-107.

Our existing CEA modedb contains only 64 modes (VIC=1 to VIC=64). Now
to be able to parse new CEA modes using the existing methods, we have
to complete the modedb (VIC=65 onwards).

This patch adds:
- Timings for existing CEA video modes (from VIC=65 till VIC=92)
- Newly added 4k modes (from VIC=93 to VIC=107).

The patch was originaly discussed and reviewed here:
https://patchwork.freedesktop.org/patch/135810/

Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
Cc: Jose Abreu <Jose.Abreu@synopsys.com>
Cc: Andrzej Hajda <a.hajda@samsung.com>
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: Harry Wentland <harry.wentland@amd.com>

V2: Rebase
V3: Rebase
V4: Added native bit handling as per CEA-861-F spec (Ville)

Reviewed-by: Jose Abreu <Jose.Abreu@synopsys.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Acked-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
---
 drivers/gpu/drm/drm_edid.c | 227 ++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 226 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index d312fe1..e2d1b30 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -1006,6 +1006,221 @@ static const struct drm_display_mode edid_cea_modes[] = {
 		   2492, 2640, 0, 1080, 1084, 1089, 1125, 0,
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
 	 .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
+	/* 65 - 1280x720@24Hz */
+	{ DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 59400, 1280, 3040,
+		   3080, 3300, 0, 720, 725, 730, 750, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	  .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+	/* 66 - 1280x720@25Hz */
+	{ DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 3700,
+		   3740, 3960, 0, 720, 725, 730, 750, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	  .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+	/* 67 - 1280x720@30Hz */
+	{ DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 3040,
+		   3080, 3300, 0, 720, 725, 730, 750, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	  .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+	/* 68 - 1280x720@50Hz */
+	{ DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 1720,
+		   1760, 1980, 0, 720, 725, 730, 750, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	  .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+	/* 69 - 1280x720@60Hz */
+	{ DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 1390,
+		   1430, 1650, 0, 720, 725, 730, 750, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	  .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+	/* 70 - 1280x720@100Hz */
+	{ DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 148500, 1280, 1720,
+		   1760, 1980, 0, 720, 725, 730, 750, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	  .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+	/* 71 - 1280x720@120Hz */
+	{ DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 148500, 1280, 1390,
+		   1430, 1650, 0, 720, 725, 730, 750, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	  .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+	/* 72 - 1920x1080@24Hz */
+	{ DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2558,
+		   2602, 2750, 0, 1080, 1084, 1089, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	  .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+	/* 73 - 1920x1080@25Hz */
+	{ DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2448,
+		   2492, 2640, 0, 1080, 1084, 1089, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	  .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+	/* 74 - 1920x1080@30Hz */
+	{ DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2008,
+		   2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	  .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+	/* 75 - 1920x1080@50Hz */
+	{ DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2448,
+		   2492, 2640, 0, 1080, 1084, 1089, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	  .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+	/* 76 - 1920x1080@60Hz */
+	{ DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2008,
+		   2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	  .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+	/* 77 - 1920x1080@100Hz */
+	{ DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 297000, 1920, 2448,
+		   2492, 2640, 0, 1080, 1084, 1094, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	 .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+	/* 78 - 1920x1080@120Hz */
+	{ DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 297000, 1920, 2008,
+		   2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	 .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+	/* 79 - 1680x720@24Hz */
+	{ DRM_MODE("1680x720", DRM_MODE_TYPE_DRIVER, 59400, 1680, 3040,
+		3080, 3300, 0, 720, 725, 730, 750, 0,
+		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	.vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+	/* 80 - 1680x720@25Hz */
+	{ DRM_MODE("1680x720", DRM_MODE_TYPE_DRIVER, 59400, 1680, 2908,
+		2948, 3168, 0, 720, 725, 730, 750, 0,
+		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	.vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+	/* 81 - 1680x720@30Hz */
+	{ DRM_MODE("1680x720", DRM_MODE_TYPE_DRIVER, 59400, 1680, 2380,
+		2420, 2640, 0, 720, 725, 730, 750, 0,
+		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	.vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+	/* 82 - 1680x720@50Hz */
+	{ DRM_MODE("1680x720", DRM_MODE_TYPE_DRIVER, 82500, 1680, 1940,
+		1980, 2200, 0, 720, 725, 730, 750, 0,
+		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	.vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+	/* 83 - 1680x720@60Hz */
+	{ DRM_MODE("1680x720", DRM_MODE_TYPE_DRIVER, 99000, 1680, 1940,
+		1980, 2200, 0, 720, 725, 730, 750, 0,
+		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	.vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+	/* 84 - 1680x720@100Hz */
+	{ DRM_MODE("1680x720", DRM_MODE_TYPE_DRIVER, 165000, 1680, 1740,
+		1780, 2000, 0, 720, 725, 730, 825, 0,
+		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	.vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+	/* 85 - 1680x720@120Hz */
+	{ DRM_MODE("1680x720", DRM_MODE_TYPE_DRIVER, 198000, 1680, 1740,
+		1780, 2000, 0, 720, 725, 730, 825, 0,
+		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	.vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+	/* 86 - 2560x1080@24Hz */
+	{ DRM_MODE("2560x1080", DRM_MODE_TYPE_DRIVER, 99000, 2560, 3558,
+		3602, 3750, 0, 1080, 1084, 1089, 1100, 0,
+		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	.vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+	/* 87 - 2560x1080@25Hz */
+	{ DRM_MODE("2560x1080", DRM_MODE_TYPE_DRIVER, 90000, 2560, 3008,
+		3052, 3200, 0, 1080, 1084, 1089, 1125, 0,
+		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	.vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+	/* 88 - 2560x1080@30Hz */
+	{ DRM_MODE("2560x1080", DRM_MODE_TYPE_DRIVER, 118800, 2560, 3328,
+		3372, 3520, 0, 1080, 1084, 1089, 1125, 0,
+		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	.vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+	/* 89 - 2560x1080@50Hz */
+	{ DRM_MODE("2560x1080", DRM_MODE_TYPE_DRIVER, 185625, 2560, 3108,
+		3152, 3300, 0, 1080, 1084, 1089, 1125, 0,
+		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	.vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+	/* 90 - 2560x1080@60Hz */
+	{ DRM_MODE("2560x1080", DRM_MODE_TYPE_DRIVER, 198000, 2560, 2808,
+		2852, 3000, 0, 1080, 1084, 1089, 1100, 0,
+		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	.vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+	/* 91 - 2560x1080@100Hz */
+	{ DRM_MODE("2560x1080", DRM_MODE_TYPE_DRIVER, 371250, 2560, 2778,
+		2822, 2970, 0, 1080, 1084, 1089, 1250, 0,
+		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	.vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+	/* 92 - 2560x1080@120Hz */
+	{ DRM_MODE("2560x1080", DRM_MODE_TYPE_DRIVER, 495000, 2560, 3108,
+		3152, 3300, 0, 1080, 1084, 1089, 1250, 0,
+		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	.vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
+	/* 93 - 3840x2160p@24Hz 16:9 */
+	{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 5116,
+		5204, 5500, 0, 2160, 2168, 2178, 2250, 0,
+		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	.vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9,},
+	/* 94 - 3840x2160p@25Hz 16:9 */
+	{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 4896,
+		4984, 5280, 0, 2160, 2168, 2178, 2250, 0,
+		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	.vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9},
+	/* 95 - 3840x2160p@30Hz 16:9 */
+	{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 4016,
+		4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
+		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	.vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9},
+	/* 96 - 3840x2160p@50Hz 16:9 */
+	{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 4896,
+		4984, 5280, 0, 2160, 2168, 2178, 2250, 0,
+		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	.vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9},
+	/* 97 - 3840x2160p@60Hz 16:9 */
+	{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 4016,
+		4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
+		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	.vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9},
+	/* 98 - 4096x2160p@24Hz 256:135 */
+	{ DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 297000, 4096, 5116,
+		5204, 5500, 0, 2160, 2168, 2178, 2250, 0,
+		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	.vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135},
+	/* 99 - 4096x2160p@25Hz 256:135 */
+	{ DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 297000, 4096, 5064,
+		5152, 5280, 0, 2160, 2168, 2178, 2250, 0,
+		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	.vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135},
+	/* 100 - 4096x2160p@30Hz 256:135 */
+	{ DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 297000, 4096, 4184,
+		4272, 4400, 0, 2160, 2168, 2178, 2250, 0,
+		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	.vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135},
+	/* 101 - 4096x2160p@50Hz 256:135 */
+	{ DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 594000, 4096, 5064,
+		5152, 5280, 0, 2160, 2168, 2178, 2250, 0,
+		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	.vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135},
+	/* 102 - 4096x2160p@60Hz 256:135 */
+	{ DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 594000, 4096, 4184,
+		4272, 4400, 0, 2160, 2168, 2178, 2250, 0,
+		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	.vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135},
+	/* 103 - 3840x2160p@24Hz 64:27 */
+	{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 5116,
+		5204, 5500, 0, 2160, 2168, 2178, 2250, 0,
+		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	.vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27},
+	/* 104 - 3840x2160p@25Hz 64:27 */
+	{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 4016,
+		4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
+		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	.vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27},
+	/* 105 - 3840x2160p@30Hz 64:27 */
+	{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 4016,
+		4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
+		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	.vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27},
+	/* 106 - 3840x2160p@50Hz 64:27 */
+	{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 4896,
+		4984, 5280, 0, 2160, 2168, 2178, 2250, 0,
+		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	.vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27},
+	/* 107 - 3840x2160p@60Hz 64:27 */
+	{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 4016,
+		4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
+		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+	.vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27},
 };
 
 /*
@@ -2902,6 +3117,16 @@ add_alternate_cea_modes(struct drm_connector *connector, struct edid *edid)
 	return modes;
 }
 
+static u8 svd_to_vic(u8 svd)
+{
+
+	/* 0-6 bit vic, 7th bit native mode indicator */
+	if (((svd >= 1) && (svd <= 64)) || ((svd >= 129) && (svd <= 192)))
+		return svd & 127;
+
+	return svd;
+}
+
 static struct drm_display_mode *
 drm_display_mode_from_vic_index(struct drm_connector *connector,
 				const u8 *video_db, u8 video_len,
@@ -2915,7 +3140,7 @@ drm_display_mode_from_vic_index(struct drm_connector *connector,
 		return NULL;
 
 	/* CEA modes are numbered 1..127 */
-	vic = (video_db[video_index] & 127);
+	vic = svd_to_vic(video_db[video_index]);
 	if (!drm_valid_cea_vic(vic))
 		return NULL;
 
-- 
2.7.4

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

^ permalink raw reply related	[flat|nested] 58+ messages in thread

* [RESEND-CI v4 04/15] drm/edid: parse YCBCR 420 videomodes from EDID
  2017-06-21 10:33 [RESEND-CI v4 00/15] HDMI YCBCR output handling in DRM layer Shashank Sharma
                   ` (2 preceding siblings ...)
  2017-06-21 10:34 ` [RESEND-CI v4 03/15] drm/edid: Complete CEA modedb(VIC 1-107) Shashank Sharma
@ 2017-06-21 10:34 ` Shashank Sharma
  2017-06-27 11:52   ` Ville Syrjälä
  2017-06-21 10:34 ` [RESEND-CI v4 05/15] drm/edid: parse ycbcr 420 deep color information Shashank Sharma
                   ` (10 subsequent siblings)
  14 siblings, 1 reply; 58+ messages in thread
From: Shashank Sharma @ 2017-06-21 10:34 UTC (permalink / raw)
  To: dri-devel, intel-gfx, ville.syrjala; +Cc: Jose Abreu

HDMI 2.0 spec adds support for YCBCR420 sub-sampled output.
CEA-861-F adds two new blocks in EDID's CEA extension blocks,
to provide information about sink's YCBCR420 output capabilities.

These blocks are:

- YCBCR420vdb(YCBCR 420 video data block):
This block contains VICs of video modes, which can be sopported only
in YCBCR420 output mode (Not in RGB/YCBCR444/422. Its like a normal
SVD block, valid for YCBCR420 modes only.

- YCBCR420cmdb(YCBCR 420 capability map data block):
This block gives information about video modes which can support
YCBCR420 output mode also (along with RGB,YCBCR444/422 etc) This
block contains a bitmap index of normal svd videomodes, which can
support YCBCR420 output too.
So if bit 0 from first vcb byte is set, first video mode in the svd
list can support YCBCR420 output too. Bit 1 means second video mode
from svd list can support YCBCR420 output too, and so on.

This patch adds two bitmaps in display's hdmi_info structure, one each
for VCB and VDB modes. If the source is HDMI 2.0 capable, this patch
adds:
- VDB modes (YCBCR 420 only modes) in connector's mode list, also makes
  an entry in the vdb_bitmap per vic.
- VCB modes (YCBCR 420 also modes) only entry in the vcb_bitmap.

Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
Cc: Jose Abreu <joabreu@synopsys.com>
Cc: Emil Velikov <emil.l.velikov@gmail.com>

V2: Addressed
    Review comments from Emil:
    - Use 1ULL<<i instead of 1<<i to make sure the output is 64bit.
    - Use the suggested method for updating dbmap.
    - Add documentation for YCBCR420_vcb_map to fix kbuild warning.

    Review comments from Ville:
    - Do not expose the YCBCR420 flags in uabi layer, keep it internal.
    - Save a map of YCBCR420 modes for future reference.
    - Check db length before trying to parse extended tag.
    - Add a warning if there are > 64 modes in capability map block.
    - Use y420cmdb in function names and macros while dealing with vcb
      to be aligned with spec.
    - Move the display information parsing block ahead of mode parsing
      blocks.

V3: Addressed design/review comments from Ville
    - Do not add flags in video modes, else we have to expose them to user
    - There should not be a UABI change, and kernel should detect the
      choice of the output based on type of mode, and the bitmaps.
    - Use standard bitops from kernel bitmap header, instead of calculating
      bit positions manually.

V4: Addressed review comments from Ville:
    - s/ycbcr_420_vdb/y420vdb
    - s/ycbcr_420_vcb/y420cmdb
    - Be less verbose on description of do_y420vdb_modes
    - Move newmode variable in the loop scope.
    - Use svd_to_vic() to get a VIC, instead of 0x7f
    - Remove bitmap description for CMDB modes & VDB modes
    - Dont add connector->ycbcr_420_allowed check for cmdb modes
    - Remove 'len' variable, in is_y420cmdb function, which is used
      only once
    - Add length check in is_y420vdb function
    - Remove unnecessary if (!db) check in function parse_y420cmdb_bitmap
    - Do not add print about YCBCR 420 modes
    - Fix indentation in few places
    - Move ycbcr420_dc_modes in next patch, where its used
    - Add a separate patch for movement of drm_add_display_info()

Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
---
 drivers/gpu/drm/drm_edid.c  | 157 +++++++++++++++++++++++++++++++++++++++++++-
 include/drm/drm_connector.h |  20 ++++++
 2 files changed, 174 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index e2d1b30..8c7e73b 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -2781,7 +2781,9 @@ add_detailed_modes(struct drm_connector *connector, struct edid *edid,
 #define VIDEO_BLOCK     0x02
 #define VENDOR_BLOCK    0x03
 #define SPEAKER_BLOCK	0x04
-#define VIDEO_CAPABILITY_BLOCK	0x07
+#define VIDEO_CAPABILITY_BLOCK 0x07
+#define VIDEO_DATA_BLOCK_420	0x0E
+#define VIDEO_CAP_BLOCK_Y420CMDB 0x0F
 #define EDID_BASIC_AUDIO	(1 << 6)
 #define EDID_CEA_YCRCB444	(1 << 5)
 #define EDID_CEA_YCRCB422	(1 << 4)
@@ -3153,15 +3155,79 @@ drm_display_mode_from_vic_index(struct drm_connector *connector,
 	return newmode;
 }
 
+/*
+ * do_y420vdb_modes - Parse YCBCR 420 only modes
+ * @connector: connector corresponding to the HDMI sink
+ * @svds: start of the data block of CEA YCBCR 420 VDB
+ * @len: length of the CEA YCBCR 420 VDB
+ *
+ * Parse the CEA-861-F YCBCR 420 Video Data Block (Y420VDB)
+ * which contains modes which can be supported in YCBCR 420
+ * output format only.
+ */
+static int do_y420vdb_modes(struct drm_connector *connector,
+				   const u8 *svds, u8 svds_len)
+{
+	int modes = 0, i;
+	struct drm_device *dev = connector->dev;
+	struct drm_display_info *info = &connector->display_info;
+	struct drm_hdmi_info *hdmi = &info->hdmi;
+
+	for (i = 0; i < svds_len; i++) {
+		u8 vic = svd_to_vic(svds[i]);
+		struct drm_display_mode *newmode;
+
+		newmode = drm_mode_duplicate(dev, &edid_cea_modes[vic]);
+		if (!newmode)
+			break;
+		bitmap_set(hdmi->y420_vdb_modes, vic, 1);
+		drm_mode_probed_add(connector, newmode);
+		modes++;
+	}
+
+	if (modes > 0)
+		info->color_formats |= DRM_COLOR_FORMAT_YCRCB420;
+	return modes;
+}
+
+/*
+ * drm_add_cmdb_modes - Add a YCBCR 420 mode into bitmap
+ * @connector: connector corresponding to the HDMI sink
+ * @vic: CEA vic for the video mode to be added in the map
+ *
+ * Makes an entry for a videomode in the YCBCR 420 bitmap
+ */
+static void
+drm_add_cmdb_modes(struct drm_connector *connector, u8 svd)
+{
+	u8 vic = svd_to_vic(svd);
+	struct drm_hdmi_info *hdmi = &connector->display_info.hdmi;
+
+	bitmap_set(hdmi->y420_cmdb_modes, vic, 1);
+}
+
 static int
 do_cea_modes(struct drm_connector *connector, const u8 *db, u8 len)
 {
 	int i, modes = 0;
+	struct drm_hdmi_info *hdmi = &connector->display_info.hdmi;
 
 	for (i = 0; i < len; i++) {
 		struct drm_display_mode *mode;
 		mode = drm_display_mode_from_vic_index(connector, db, len, i);
 		if (mode) {
+			/*
+			 * YCBCR420 capability block contains a bitmap which
+			 * gives the index of CEA modes from CEA VDB, which
+			 * can support YCBCR 420 sampling output also (apart
+			 * from RGB/YCBCR444 etc).
+			 * For example, if the bit 0 in bitmap is set,
+			 * first mode in VDB can support YCBCR420 output too.
+			 * Add YCBCR420 modes only if sink is HDMI 2.0 capable.
+			 */
+			if (test_bit(i, &hdmi->y420_cmdb_map))
+				drm_add_cmdb_modes(connector, db[i]);
+
 			drm_mode_probed_add(connector, mode);
 			modes++;
 		}
@@ -3437,6 +3503,12 @@ do_hdmi_vsdb_modes(struct drm_connector *connector, const u8 *db, u8 len,
 }
 
 static int
+cea_db_extended_tag(const u8 *db)
+{
+	return db[1];
+}
+
+static int
 cea_db_payload_len(const u8 *db)
 {
 	return db[0] & 0x1f;
@@ -3497,9 +3569,78 @@ static bool cea_db_is_hdmi_forum_vsdb(const u8 *db)
 	return oui == HDMI_FORUM_IEEE_OUI;
 }
 
+static bool cea_db_is_y420cmdb(const u8 *db)
+{
+
+	if (cea_db_tag(db) != VIDEO_CAPABILITY_BLOCK)
+		return false;
+
+	if (!cea_db_payload_len(db))
+		return false;
+
+	if (cea_db_extended_tag(db) != VIDEO_CAP_BLOCK_Y420CMDB)
+		return false;
+
+	return true;
+}
+
+static bool cea_db_is_y420vdb(const u8 *db)
+{
+	if (cea_db_tag(db) != VIDEO_CAPABILITY_BLOCK)
+		return false;
+
+	if (!cea_db_payload_len(db))
+		return false;
+
+	if (cea_db_extended_tag(db) != VIDEO_DATA_BLOCK_420)
+		return false;
+
+	return true;
+}
+
 #define for_each_cea_db(cea, i, start, end) \
 	for ((i) = (start); (i) < (end) && (i) + cea_db_payload_len(&(cea)[(i)]) < (end); (i) += cea_db_payload_len(&(cea)[(i)]) + 1)
 
+static void drm_parse_y420cmdb_bitmap(struct drm_connector *connector,
+				     const u8 *db)
+{
+	struct drm_display_info *info = &connector->display_info;
+	struct drm_hdmi_info *hdmi = &info->hdmi;
+	u8 map_len = cea_db_payload_len(db) - 1;
+	u8 count;
+	u64 map = 0;
+
+	if (map_len == 0) {
+		/* All CEA modes support ycbcr420 sampling also.*/
+		hdmi->y420_cmdb_map = U64_MAX;
+		info->color_formats |= DRM_COLOR_FORMAT_YCRCB420;
+		return;
+	}
+
+	/*
+	 * This map indicates which of the existing CEA block modes
+	 * from VDB can support YCBCR420 output too. So if bit=0 is
+	 * set, first mode from VDB can support YCBCR420 output too.
+	 * We will parse and keep this map, before parsing VDB itself
+	 * to avoid going through the same block again and again.
+	 *
+	 * Spec is not clear about max possible size of this block.
+	 * Clamping max bitmap block size at 8 bytes. Every byte can
+	 * address 8 CEA modes, in this way this map can address
+	 * 8*8 = first 64 SVDs.
+	 */
+	if (WARN_ON_ONCE(map_len > 8))
+		map_len = 8;
+
+	for (count = 0; count < map_len; count++)
+		map |= (u64)db[2 + count] << (8 * count);
+
+	if (map)
+		info->color_formats |= DRM_COLOR_FORMAT_YCRCB420;
+
+	hdmi->y420_cmdb_map = map;
+}
+
 static int
 add_cea_modes(struct drm_connector *connector, struct edid *edid)
 {
@@ -3522,10 +3663,17 @@ add_cea_modes(struct drm_connector *connector, struct edid *edid)
 				video = db + 1;
 				video_len = dbl;
 				modes += do_cea_modes(connector, video, dbl);
-			}
-			else if (cea_db_is_hdmi_vsdb(db)) {
+			} else if (cea_db_is_hdmi_vsdb(db)) {
 				hdmi = db;
 				hdmi_len = dbl;
+			} else if (cea_db_is_y420vdb(db) &&
+				   connector->ycbcr_420_allowed) {
+				const u8 *vdb420 = &db[2];
+
+				/* Add 4:2:0(only) modes present in EDID */
+				modes += do_y420vdb_modes(connector,
+							  vdb420,
+							  dbl - 1);
 			}
 		}
 	}
@@ -4206,6 +4354,8 @@ static void drm_parse_cea_ext(struct drm_connector *connector,
 			drm_parse_hdmi_vsdb_video(connector, db);
 		if (cea_db_is_hdmi_forum_vsdb(db))
 			drm_parse_hdmi_forum_vsdb(connector, db);
+		if (cea_db_is_y420cmdb(db))
+			drm_parse_y420cmdb_bitmap(connector, db);
 	}
 }
 
@@ -4460,6 +4610,7 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
 	num_modes += add_cea_modes(connector, edid);
 	num_modes += add_alternate_cea_modes(connector, edid);
 	num_modes += add_displayid_detailed_modes(connector, edid);
+
 	if (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF)
 		num_modes += add_inferred_modes(connector, edid);
 
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 7493fd3..ce2212d 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -137,6 +137,25 @@ struct drm_scdc {
 struct drm_hdmi_info {
 	/** @scdc: sink's scdc support and capabilities */
 	struct drm_scdc scdc;
+
+	/**
+	 * @y420_vdb_modes: bitmap of modes which can support ycbcr420
+	 * output only (not normal RGB/YCBCR444/422 outputs). There are total
+	 * 107 VICs defined by CEA-861-F spec, so the size is 128 bits to map
+	 * upto 128 VICs;
+	 */
+	unsigned long y420_vdb_modes[BITS_TO_LONGS(128)];
+
+	/**
+	 * @y420_cmdb_modes: bitmap of modes which can support ycbcr420
+	 * output also, along with normal HDMI outputs. There are total 107
+	 * VICs defined by CEA-861-F spec, so the size is 128 bits to map upto
+	 * 128 VICs;
+	 */
+	unsigned long y420_cmdb_modes[BITS_TO_LONGS(128)];
+
+	/** @y420_cmdb_map: bitmap of SVD index, to extraxt vcb modes */
+	unsigned long y420_cmdb_map;
 };
 
 /**
@@ -200,6 +219,7 @@ struct drm_display_info {
 #define DRM_COLOR_FORMAT_RGB444		(1<<0)
 #define DRM_COLOR_FORMAT_YCRCB444	(1<<1)
 #define DRM_COLOR_FORMAT_YCRCB422	(1<<2)
+#define DRM_COLOR_FORMAT_YCRCB420	(1<<3)
 
 	/**
 	 * @color_formats: HDMI Color formats, selects between RGB and YCrCb
-- 
2.7.4

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

^ permalink raw reply related	[flat|nested] 58+ messages in thread

* [RESEND-CI v4 05/15] drm/edid: parse ycbcr 420 deep color information
  2017-06-21 10:33 [RESEND-CI v4 00/15] HDMI YCBCR output handling in DRM layer Shashank Sharma
                   ` (3 preceding siblings ...)
  2017-06-21 10:34 ` [RESEND-CI v4 04/15] drm/edid: parse YCBCR 420 videomodes from EDID Shashank Sharma
@ 2017-06-21 10:34 ` Shashank Sharma
  2017-06-27 11:53   ` Ville Syrjälä
  2017-06-21 10:34 ` [RESEND-CI v4 06/15] drm/edid: parse sink information before CEA blocks Shashank Sharma
                   ` (9 subsequent siblings)
  14 siblings, 1 reply; 58+ messages in thread
From: Shashank Sharma @ 2017-06-21 10:34 UTC (permalink / raw)
  To: dri-devel, intel-gfx, ville.syrjala; +Cc: Jose Abreu

CEA-861-F spec adds ycbcr420 deep color support information
in hf-vsdb block. This patch extends the existing hf-vsdb parsing
function by adding parsing of ycbcr420 deep color support from the
EDID and adding it into display information stored.

V2: Rebase
V3: Rebase
V4: Moved definition of y420_dc_modes into this patch, where its used
    (Ville)

Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Jose Abreu <joabreu@synopsys.com>
Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
---
 drivers/gpu/drm/drm_edid.c  | 15 +++++++++++++++
 include/drm/drm_connector.h |  3 +++
 include/drm/drm_edid.h      |  5 +++++
 3 files changed, 23 insertions(+)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 8c7e73b..b4583f6 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -4196,6 +4196,19 @@ drm_default_rgb_quant_range(const struct drm_display_mode *mode)
 }
 EXPORT_SYMBOL(drm_default_rgb_quant_range);
 
+static void drm_parse_ycbcr420_deep_color_info(struct drm_connector *connector,
+					     const u8 *db)
+{
+	struct drm_hdmi_info *info = &connector->display_info.hdmi;
+
+	if (db[7] & DRM_EDID_YCBCR420_DC_48)
+		info->y420_dc_modes |= DRM_EDID_YCBCR420_DC_48;
+	if (db[7] & DRM_EDID_YCBCR420_DC_36)
+		info->y420_dc_modes |= DRM_EDID_YCBCR420_DC_36;
+	if (db[7] & DRM_EDID_YCBCR420_DC_30)
+		info->y420_dc_modes |= DRM_EDID_YCBCR420_DC_30;
+}
+
 static void drm_parse_hdmi_forum_vsdb(struct drm_connector *connector,
 				 const u8 *hf_vsdb)
 {
@@ -4236,6 +4249,8 @@ static void drm_parse_hdmi_forum_vsdb(struct drm_connector *connector,
 				scdc->scrambling.low_rates = true;
 		}
 	}
+
+	drm_parse_ycbcr420_deep_color_info(connector, hf_vsdb);
 }
 
 static void drm_parse_hdmi_deep_color_info(struct drm_connector *connector,
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index ce2212d..1305fe9 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -156,6 +156,9 @@ struct drm_hdmi_info {
 
 	/** @y420_cmdb_map: bitmap of SVD index, to extraxt vcb modes */
 	unsigned long y420_cmdb_map;
+
+	/** @y420_dc_modes: bitmap of deep color support index */
+	u8 y420_dc_modes;
 };
 
 /**
diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
index 89c0062..d4ff17c 100644
--- a/include/drm/drm_edid.h
+++ b/include/drm/drm_edid.h
@@ -213,6 +213,11 @@ struct detailed_timing {
 #define DRM_EDID_HDMI_DC_30               (1 << 4)
 #define DRM_EDID_HDMI_DC_Y444             (1 << 3)
 
+/* YCBCR 420 deep color modes */
+#define DRM_EDID_YCBCR420_DC_48		  (1 << 6)
+#define DRM_EDID_YCBCR420_DC_36		  (1 << 5)
+#define DRM_EDID_YCBCR420_DC_30		  (1 << 4)
+
 /* ELD Header Block */
 #define DRM_ELD_HEADER_BLOCK_SIZE	4
 
-- 
2.7.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 58+ messages in thread

* [RESEND-CI v4 06/15] drm/edid: parse sink information before CEA blocks
  2017-06-21 10:33 [RESEND-CI v4 00/15] HDMI YCBCR output handling in DRM layer Shashank Sharma
                   ` (4 preceding siblings ...)
  2017-06-21 10:34 ` [RESEND-CI v4 05/15] drm/edid: parse ycbcr 420 deep color information Shashank Sharma
@ 2017-06-21 10:34 ` Shashank Sharma
  2017-06-27 11:55   ` Ville Syrjälä
  2017-06-21 10:34 ` [RESEND-CI v4 08/15] drm: set output colorspace in AVI infoframe Shashank Sharma
                   ` (8 subsequent siblings)
  14 siblings, 1 reply; 58+ messages in thread
From: Shashank Sharma @ 2017-06-21 10:34 UTC (permalink / raw)
  To: dri-devel, intel-gfx, ville.syrjala

CEA-861-F adds ycbcr capability map block, for HDMI 2.0 sinks.
This block contains a map of indexes of CEA modes, which can
support YCBCR 420 output also. To avoid multiple parsing of same
CEA block, let's parse the sink information and get this map, before
parsing CEA modes.

This patch moves the call to drm_add_display_info function, before the
mode parsing block.

Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
---
 drivers/gpu/drm/drm_edid.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index b4583f6..42934b2 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -4605,6 +4605,13 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
 	quirks = edid_get_quirks(edid);
 
 	/*
+	 * CEA-861-F adds ycbcr capability map block, for HDMI 2.0 sinks.
+	 * To avoid multiple parsing of same block, lets parse that map
+	 * from sink info, before parsing CEA modes.
+	 */
+	drm_add_display_info(connector, edid);
+
+	/*
 	 * EDID spec says modes should be preferred in this order:
 	 * - preferred detailed mode
 	 * - other detailed modes from base block
@@ -4632,8 +4639,6 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
 	if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75))
 		edid_fixup_preferred(connector, quirks);
 
-	drm_add_display_info(connector, edid);
-
 	if (quirks & EDID_QUIRK_FORCE_6BPC)
 		connector->display_info.bpc = 6;
 
-- 
2.7.4

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

^ permalink raw reply related	[flat|nested] 58+ messages in thread

* [RESEND-CI v4 08/15] drm: set output colorspace in AVI infoframe
  2017-06-21 10:33 [RESEND-CI v4 00/15] HDMI YCBCR output handling in DRM layer Shashank Sharma
                   ` (5 preceding siblings ...)
  2017-06-21 10:34 ` [RESEND-CI v4 06/15] drm/edid: parse sink information before CEA blocks Shashank Sharma
@ 2017-06-21 10:34 ` Shashank Sharma
  2017-06-21 10:34 ` [RESEND-CI v4 09/15] drm: add helper functions for YCBCR output handling Shashank Sharma
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 58+ messages in thread
From: Shashank Sharma @ 2017-06-21 10:34 UTC (permalink / raw)
  To: dri-devel, intel-gfx, ville.syrjala; +Cc: Jose Abreu

HDMI source must set output colorspace information in AVI
infoframes, so that the sink can decode upcoming frames
accordingly.

As this patch series is adding support for HDMI output modes
other than RGB, this patch adds a function in DRM layer, to
add the output colorspace information in the AVI infoframes.

V2: Rebase
V3: Rebase

Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
Cc: Jose Abreu <Jose.Abreu@synopsys.com>
Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
---
 drivers/gpu/drm/drm_edid.c | 40 ++++++++++++++++++++++++++++++++++++++++
 include/drm/drm_edid.h     |  5 +++++
 2 files changed, 45 insertions(+)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 42934b2..edba190 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -4782,6 +4782,46 @@ drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
 EXPORT_SYMBOL(drm_hdmi_avi_infoframe_from_display_mode);
 
 /**
+ * drm_hdmi_avi_infoframe_set_colorspace - fill an HDMI AVI infoframe with
+ * colorspace data of the output type
+ *
+ * @frame: HDMI AVI infoframe
+ * @mode: DRM display mode
+ * @hdmi_output: HDMI output colorspace
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+int
+drm_hdmi_avi_infoframe_set_colorspace(struct hdmi_avi_infoframe *frame,
+					 const struct drm_display_mode *mode,
+					 enum drm_hdmi_output_type hdmi_output)
+{
+	switch (hdmi_output) {
+	case DRM_HDMI_OUTPUT_YCBCR444:
+		frame->colorspace = HDMI_COLORSPACE_YUV444;
+		break;
+	case DRM_HDMI_OUTPUT_YCBCR422:
+		frame->colorspace = HDMI_COLORSPACE_YUV422;
+		break;
+	case DRM_HDMI_OUTPUT_YCBCR420:
+		frame->colorspace = HDMI_COLORSPACE_YUV420;
+		frame->pixel_repeat = 0;
+		break;
+	case DRM_HDMI_OUTPUT_DEFAULT_RGB:
+		frame->colorspace = HDMI_COLORSPACE_RGB;
+		break;
+	case DRM_HDMI_OUTPUT_YCBCR_HQ:
+	case DRM_HDMI_OUTPUT_YCBCR_LQ:
+	case DRM_HDMI_OUTPUT_INVALID:
+		DRM_ERROR("Invalid HDMI output type\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_hdmi_avi_infoframe_set_colorspace);
+
+/**
  * drm_hdmi_avi_infoframe_quant_range() - fill the HDMI AVI infoframe
  *                                        quantization range information
  * @frame: HDMI AVI infoframe
diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
index d4ff17c..3ea833f 100644
--- a/include/drm/drm_edid.h
+++ b/include/drm/drm_edid.h
@@ -329,6 +329,7 @@ struct cea_sad {
 struct drm_encoder;
 struct drm_connector;
 struct drm_display_mode;
+enum drm_hdmi_output_type;
 
 void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid);
 int drm_edid_to_sad(struct edid *edid, struct cea_sad **sads);
@@ -351,6 +352,10 @@ drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
 					 const struct drm_display_mode *mode,
 					 bool is_hdmi2_sink);
 int
+drm_hdmi_avi_infoframe_set_colorspace(struct hdmi_avi_infoframe *frame,
+					 const struct drm_display_mode *mode,
+					 enum drm_hdmi_output_type hdmi_output);
+int
 drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame,
 					    const struct drm_display_mode *mode);
 void
-- 
2.7.4

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

^ permalink raw reply related	[flat|nested] 58+ messages in thread

* [RESEND-CI v4 09/15] drm: add helper functions for YCBCR output handling
  2017-06-21 10:33 [RESEND-CI v4 00/15] HDMI YCBCR output handling in DRM layer Shashank Sharma
                   ` (6 preceding siblings ...)
  2017-06-21 10:34 ` [RESEND-CI v4 08/15] drm: set output colorspace in AVI infoframe Shashank Sharma
@ 2017-06-21 10:34 ` Shashank Sharma
  2017-06-22  7:05   ` [Intel-gfx] " Daniel Vetter
  2017-06-21 10:34 ` [RESEND-CI v4 10/15] drm/i915: add compute-config for YCBCR outputs Shashank Sharma
                   ` (6 subsequent siblings)
  14 siblings, 1 reply; 58+ messages in thread
From: Shashank Sharma @ 2017-06-21 10:34 UTC (permalink / raw)
  To: dri-devel, intel-gfx, ville.syrjala; +Cc: Jose Abreu

This patch adds set of helper functions for YCBCR HDMI output
handling. These functions provide functionality like:
- check if a given video mode is YCBCR 420 only mode.
- check if a given video mode is YCBCR 420 mode.
- get the highest subsamled ycbcr output.
- get the lowest subsamled ycbcr output.
- check if a given source and sink combination can support any
  YCBCR HDMI output.
- check if a given source and sink combination can support a particular
  YCBCR HDMI output.

Currently all these helpers are kept static, and only one wrapper function
is exposed to callers, which is "drm_find_hdmi_output_type". This function
takes inputs as current mode, user preference and src + sink capabilities,
and provides the most suitable HDMI output format to match all of these
inputs.

This wrapper function will be used in next few patches in this
series from I915 driver.

V2: Added YCBCR functions as helpers in DRM layer, instead of
    keeping it in I915 layer.
V3: Added handling for YCBCR-420 only modes too.
V4: EXPORT_SYMBOL(drm_find_hdmi_output_type)

Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
Cc: Jose Abreu <Jose.Abreu@synopsys.com>
Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
---
 drivers/gpu/drm/drm_edid.c  |   2 +-
 drivers/gpu/drm/drm_modes.c | 307 ++++++++++++++++++++++++++++++++++++++++++++
 include/drm/drm_edid.h      |   1 +
 include/drm/drm_modes.h     |   5 +
 4 files changed, 314 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index edba190..2f8810a 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -2949,7 +2949,7 @@ u8 drm_match_cea_mode(const struct drm_display_mode *to_match)
 }
 EXPORT_SYMBOL(drm_match_cea_mode);
 
-static bool drm_valid_cea_vic(u8 vic)
+bool drm_valid_cea_vic(u8 vic)
 {
 	return vic > 0 && vic < ARRAY_SIZE(edid_cea_modes);
 }
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index f2493b9..09e6b10 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -1576,3 +1576,310 @@ int drm_mode_convert_umode(struct drm_display_mode *out,
 out:
 	return ret;
 }
+
+/**
+ * drm_mode_is_420_only - if a given videomode can be only supported in YCBCR420
+ * output format
+ *
+ * @connector: drm connector under action.
+ * @mode: video mode to be tested.
+ *
+ * Returns:
+ * true if the mode can support YCBCR420 output
+ * false if not.
+ */
+static bool drm_mode_is_420_only(struct drm_display_info *display,
+			struct drm_display_mode *mode)
+{
+	u8 vic = drm_match_cea_mode(mode);
+
+	/*
+	 * Requirements of a 420_only mode:
+	 * must be a valid cea mode
+	 * entry in 420_only bitmap
+	 */
+	if (!drm_valid_cea_vic(vic))
+		return false;
+
+	return test_bit(vic, display->hdmi.y420_vdb_modes);
+}
+
+/**
+ * drm_mode_is_420_also - if a given videomode can be supported in YCBCR420
+ * output format also (along with RGB/YCBCR444/422)
+ *
+ * @display: display under action.
+ * @mode: video mode to be tested.
+ *
+ * Returns:
+ * true if the mode can support YCBCR420 output
+ * false if not.
+ */
+static bool drm_mode_is_420_also(struct drm_display_info *display,
+			struct drm_display_mode *mode)
+{
+	u8 vic = drm_match_cea_mode(mode);
+
+	/*
+	 * Requirements of a 420_also mode:
+	 * must be a valid cea mode
+	 * entry in 420_also bitmap
+	 */
+	if (!drm_valid_cea_vic(vic))
+		return false;
+
+	return test_bit(vic, display->hdmi.y420_cmdb_modes);
+}
+
+
+static bool drm_mode_is_420(struct drm_display_info *display,
+			struct drm_display_mode *mode)
+{
+	return drm_mode_is_420_only(display, mode) ||
+			drm_mode_is_420_also(display, mode);
+}
+
+/**
+ * drm_can_support_this_ycbcr_output - can a given source and sink combination
+ * support a particular YCBCR output type.
+ *
+ * @display: sink information.
+ * @mode: video mode from modeset
+ * @type: enum indicating YCBCR output type
+ * @source_outputs: bitmap of source supported HDMI output formats.
+ *
+ * Returns:
+ * true on success.
+ * false on failure.
+ */
+static bool drm_can_support_this_ycbcr_output(struct drm_display_info *display,
+					struct drm_display_mode *mode,
+					enum drm_hdmi_output_type type,
+					u32 source_outputs)
+{
+	/* YCBCR420 output support can be per mode basis */
+	if (type == DRM_HDMI_OUTPUT_YCBCR420 &&
+		!drm_mode_is_420(display, mode))
+		return false;
+
+	return display->color_formats & source_outputs & type;
+}
+
+/**
+ * drm_can_support_ycbcr_output - can a given source and sink combination
+ * support any YCBCR outputs ?
+ *
+ * @display: sink information.
+ * @source_outputs: bitmap of source supported HDMI output formats.
+ *
+ * Returns:
+ * true on success.
+ * false on failure.
+ */
+static bool drm_can_support_ycbcr_output(struct drm_display_info *display,
+					u32 source_outputs)
+{
+	u32 supported_formats;
+
+	if (!source_outputs || !display->color_formats) {
+		DRM_DEBUG_KMS("Source/Sink doesn't support any output ?\n");
+		return DRM_HDMI_OUTPUT_INVALID;
+	}
+
+	/* Get the common supported fromats between source and sink */
+	supported_formats = display->color_formats & source_outputs;
+	if (!supported_formats || (supported_formats ==
+		DRM_COLOR_FORMAT_RGB444)) {
+		DRM_ERROR("No common YCBCR formats between source and sink\n");
+		return false;
+	}
+
+	DRM_DEBUG_KMS("Src and Sink combination can support YCBCR output\n");
+	return true;
+}
+
+/**
+ * drm_get_highest_quality_ycbcr_supported - get the ycbcr output mode
+ * with highest subsampling rate
+ * @display: struct drm_display_info from current connector
+ * @mode: video mode from modeset
+ * @source_output_map: bitmap of supported HDMI output modes from source
+ *
+ * Finds the best possible ycbcr output mode (based on subsampling), for the
+ * given source and sink combination.
+ *
+ * Returns:
+ * enum corresponding to best output mode on success.
+ * DRM_HDMI_OUTPUT_INVALID on failure.
+ */
+static enum drm_hdmi_output_type
+drm_get_highest_quality_ycbcr_supported(struct drm_display_info *display,
+					struct drm_display_mode *mode,
+					u32 source_output_map)
+{
+	enum drm_hdmi_output_type output = DRM_HDMI_OUTPUT_INVALID;
+	u32 supported_formats = source_output_map & display->color_formats;
+
+	/*
+	 * Get the ycbcr output with the highest possible subsampling rate.
+	 * Preference should go as:
+	 * ycbcr 444
+	 * ycbcr 422
+	 * ycbcr 420
+	 */
+	if (supported_formats & DRM_COLOR_FORMAT_YCRCB444)
+		output = DRM_COLOR_FORMAT_YCRCB444;
+	else if (supported_formats & DRM_COLOR_FORMAT_YCRCB422)
+		output = DRM_COLOR_FORMAT_YCRCB422;
+	else if (supported_formats & DRM_COLOR_FORMAT_YCRCB420 &&
+			drm_mode_is_420(display, mode))
+		output = DRM_COLOR_FORMAT_YCRCB420;
+
+	DRM_DEBUG_KMS("Highest subsampled YCBCR mode supported is %s\n",
+			drm_get_hdmi_output_name(supported_formats));
+	return output;
+}
+
+/**
+ * drm_get_lowest_quality_ycbcr_supported - get the ycbcr output mode
+ * with lowest subsampling rate
+ * @display: struct drm_display_info from current connector
+ * @mode: video mode from modeset
+ * @source_output_map: bitmap of supported HDMI output modes from source
+ *
+ * Finds the lowest possible ycbcr output mode (based on subsampling), for the
+ * given source and sink combination.
+ *
+ * Returns:
+ * enum corresponding to best output mode on success.
+ * DRM_HDMI_OUTPUT_INVALID on failure.
+ */
+static enum drm_hdmi_output_type
+drm_get_lowest_quality_ycbcr_supported(struct drm_display_info *display,
+					struct drm_display_mode *mode,
+					u32 source_output_map)
+{
+	enum drm_hdmi_output_type output = DRM_HDMI_OUTPUT_INVALID;
+	u32 supported_formats = source_output_map & display->color_formats;
+
+	/*
+	 * Get the ycbcr output with the lowest possible subsampling rate.
+	 * Preference should go as:
+	 * ycbcr 420
+	 * ycbcr 422
+	 * ycbcr 444
+	 */
+	if (supported_formats & DRM_COLOR_FORMAT_YCRCB420 &&
+		drm_mode_is_420(display, mode))
+		output = DRM_HDMI_OUTPUT_YCBCR420;
+	else if (display->color_formats & DRM_COLOR_FORMAT_YCRCB422)
+		output = DRM_HDMI_OUTPUT_YCBCR422;
+	else if (display->color_formats & DRM_COLOR_FORMAT_YCRCB444)
+		output = DRM_HDMI_OUTPUT_YCBCR420;
+
+	DRM_DEBUG_KMS("Lowest subsampled YCBCR mode supported is %s\n",
+			drm_get_hdmi_output_name(supported_formats));
+	return output;
+}
+
+/**
+ * drm_find_hdmi_output_type - get the most suitable output
+ * Find the best suitable HDMI output considering source capability,
+ * sink capability and user's choice (expressed in form of drm property)
+ *
+ * @connector: drm connector in action
+ * @mode: video mode under modeset
+ * @type: user's choice for preferred mode, set via drm property
+ *	"hdmi_output_format"
+ * @src_output_cap: bitmap of source's supported outputs formats
+ *	src_output_cap = (1 << DRM_COLOR_FORMAT_RGB444) means source
+ *	supports RGB444
+ *	src_output_cap = (1 << DRM_COLOR_FORMAT_YCRCB444) means source
+ *	supports YUV444, and so on.
+ *
+ * Returns:
+ * enum corresponding to best suitable output type on success.
+ * DRM_HDMI_OUTPUT_INVALID on failure.
+ */
+enum drm_hdmi_output_type
+drm_find_hdmi_output_type(struct drm_connector *connector,
+				struct drm_display_mode *mode,
+				enum drm_hdmi_output_type type,
+				u32 src_output_cap)
+{
+	bool ret;
+	struct drm_display_info *info = &connector->display_info;
+	bool mode_is_420_only = drm_mode_is_420_only(info, mode);
+
+	/*
+	 * If the preferred output is not set to YCBCR by user, and the mode
+	 * doesn't force us to drive YCBCR420 output, respect the user
+	 * preference for the output type. But if the mode is 420_only, we will
+	 * be force to drive YCBCR420 output.
+	 */
+	if (!mode_is_420_only) {
+		if (type == DRM_HDMI_OUTPUT_DEFAULT_RGB)
+			return DRM_HDMI_OUTPUT_DEFAULT_RGB;
+	} else {
+		type = DRM_HDMI_OUTPUT_YCBCR420;
+		DRM_DEBUG_KMS("Got a 420 only mode(%s)\n", mode->name);
+	}
+
+	/* If  this src + sink combination can support any YCBCR output */
+	ret = drm_can_support_ycbcr_output(info, src_output_cap);
+	if (!ret) {
+		DRM_ERROR("No supported YCBCR output\n");
+		return DRM_HDMI_OUTPUT_INVALID;
+	}
+
+	switch (type) {
+	case DRM_HDMI_OUTPUT_YCBCR_HQ:
+		type = drm_get_highest_quality_ycbcr_supported(info, mode,
+								src_output_cap);
+		break;
+
+	case DRM_HDMI_OUTPUT_YCBCR_LQ:
+		type = drm_get_lowest_quality_ycbcr_supported(info, mode,
+								src_output_cap);
+		break;
+
+	case DRM_HDMI_OUTPUT_YCBCR420:
+		ret = drm_mode_is_420(info, mode);
+		if (!ret) {
+			DRM_ERROR("Mode %s doesn't support 420 output\n",
+				   mode->name);
+			type = DRM_HDMI_OUTPUT_INVALID;
+		}
+
+		break;
+
+	/* Below cases are just to satisfy checkpatch's AI */
+	case DRM_HDMI_OUTPUT_DEFAULT_RGB:
+	case DRM_HDMI_OUTPUT_YCBCR444:
+	case DRM_HDMI_OUTPUT_YCBCR422:
+		break;
+
+	default:
+		type = DRM_HDMI_OUTPUT_INVALID;
+	}
+
+	if (type == DRM_HDMI_OUTPUT_INVALID) {
+		DRM_ERROR("Can't support mode %s in YCBCR format\n",
+				mode->name);
+		return DRM_HDMI_OUTPUT_INVALID;
+	}
+
+	/* Test if this src/sink/mode combination can support selected output */
+	ret = drm_can_support_this_ycbcr_output(info, mode, type,
+						src_output_cap);
+	if (!ret) {
+		DRM_ERROR("Output %s can't be supported\n",
+					drm_get_hdmi_output_name(type));
+		return DRM_HDMI_OUTPUT_INVALID;
+	}
+
+	DRM_DEBUG_KMS("Best supported output is: %s\n",
+			drm_get_hdmi_output_name(type));
+	return type;
+}
+EXPORT_SYMBOL(drm_find_hdmi_output_type);
diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
index 3ea833f..483f668 100644
--- a/include/drm/drm_edid.h
+++ b/include/drm/drm_edid.h
@@ -468,6 +468,7 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid);
 
 u8 drm_match_cea_mode(const struct drm_display_mode *to_match);
 enum hdmi_picture_aspect drm_get_cea_aspect_ratio(const u8 video_code);
+bool drm_valid_cea_vic(u8 vic);
 bool drm_detect_hdmi_monitor(struct edid *edid);
 bool drm_detect_monitor_audio(struct edid *edid);
 bool drm_rgb_quant_range_selectable(struct edid *edid);
diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h
index 94ac771..3c237e1 100644
--- a/include/drm/drm_modes.h
+++ b/include/drm/drm_modes.h
@@ -451,6 +451,11 @@ int drm_mode_convert_umode(struct drm_display_mode *out,
 void drm_mode_probed_add(struct drm_connector *connector, struct drm_display_mode *mode);
 void drm_mode_debug_printmodeline(const struct drm_display_mode *mode);
 
+enum drm_hdmi_output_type
+drm_find_hdmi_output_type(struct drm_connector *connector,
+			  struct drm_display_mode *mode,
+			  enum drm_hdmi_output_type type,
+			  u32 src_output_cap);
 struct drm_display_mode *drm_cvt_mode(struct drm_device *dev,
 				      int hdisplay, int vdisplay, int vrefresh,
 				      bool reduced, bool interlaced,
-- 
2.7.4

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

^ permalink raw reply related	[flat|nested] 58+ messages in thread

* [RESEND-CI v4 10/15] drm/i915: add compute-config for YCBCR outputs
  2017-06-21 10:33 [RESEND-CI v4 00/15] HDMI YCBCR output handling in DRM layer Shashank Sharma
                   ` (7 preceding siblings ...)
  2017-06-21 10:34 ` [RESEND-CI v4 09/15] drm: add helper functions for YCBCR output handling Shashank Sharma
@ 2017-06-21 10:34 ` Shashank Sharma
  2017-06-21 10:34 ` [RESEND-CI v4 11/15] drm/i915: prepare scaler for YCBCR420 modeset Shashank Sharma
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 58+ messages in thread
From: Shashank Sharma @ 2017-06-21 10:34 UTC (permalink / raw)
  To: dri-devel, intel-gfx, ville.syrjala
  Cc: Ander Conselvan De Oliveira, Daniel Vetter

This patch checks encoder level support for HDMI YCBCR outputs.
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.

V2: Split the patch into two, kept helper functions in DRM layer.
V3: Changed the compute_config function based on new DRM API.
V4: Rebase

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    | 93 ++++++++++++++++++++++++++++++++++--
 3 files changed, 94 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index f9bf0d5..da29536 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -11930,6 +11930,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 1727350..38fe56c 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -780,6 +780,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 170abc4..22da5cd 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -1317,7 +1317,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);
@@ -1329,6 +1330,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.
@@ -1342,6 +1353,12 @@ static bool hdmi_12bpc_possible(struct intel_crtc_state *crtc_state)
 		if (connector_state->crtc != crtc_state->base.crtc)
 			continue;
 
+		if (hdmi_out == DRM_HDMI_OUTPUT_YCBCR420) {
+			if (!(info->hdmi.y420_dc_modes &
+					DRM_EDID_YCBCR420_DC_36))
+				return false;
+		}
+
 		if ((info->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_36) == 0)
 			return false;
 	}
@@ -1354,6 +1371,65 @@ static bool hdmi_12bpc_possible(struct intel_crtc_state *crtc_state)
 	return true;
 }
 
+static u8
+intel_hdmi_get_src_output_support(struct drm_connector *connector)
+{
+	struct drm_i915_private *dev_priv = connector->dev->dev_private;
+	u8 supported_outputs = DRM_COLOR_FORMAT_RGB444;
+
+	if (dev_priv->info.gen < 7)
+		return supported_outputs;
+
+	/* Gen 7 and above support HDMI 1.4b outputs */
+	supported_outputs |= (DRM_COLOR_FORMAT_YCRCB444 |
+				DRM_COLOR_FORMAT_YCRCB422);
+
+	if (IS_GEMINILAKE(dev_priv))
+		supported_outputs |= DRM_COLOR_FORMAT_YCRCB420;
+
+	return supported_outputs;
+}
+
+static 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_mode *mode = &config->base.adjusted_mode;
+	enum drm_hdmi_output_type type = conn_state->hdmi_output;
+	u8 src_output_cap = intel_hdmi_get_src_output_support(connector);
+
+	/*
+	 * Can we support any YCBCR output based on these parameters ?
+	 * current source capabilities +
+	 * current sink capabilities +
+	 * given video mode +
+	 * current user's choice for HDMI output (from connector property)
+	 */
+	type = drm_find_hdmi_output_type(connector, mode, type, src_output_cap);
+	if ((type == DRM_HDMI_OUTPUT_INVALID) ||
+		(type == DRM_HDMI_OUTPUT_DEFAULT_RGB)) {
+		DRM_DEBUG_KMS("Can't support YCBCR output\n");
+		return type;
+	}
+
+	if (type == DRM_HDMI_OUTPUT_YCBCR420) {
+
+		/* YCBCR420 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;
+
+	}
+
+	/* Encoder is capable of this output, lets commit to CRTC */
+	config->hdmi_output = type;
+	DRM_DEBUG_KMS("HDMI output: %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)
@@ -1361,13 +1437,15 @@ 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_scdc *scdc = &connector->display_info.hdmi.scdc;
 	struct intel_digital_connector_state *intel_conn_state =
 		to_intel_digital_connector_state(conn_state);
 	int clock_8bpc = pipe_config->base.adjusted_mode.crtc_clock;
 	int clock_12bpc = clock_8bpc * 3 / 2;
 	int desired_bpp;
 	bool force_dvi = intel_conn_state->force_audio == HDMI_AUDIO_OFF_DVI;
+	enum drm_hdmi_output_type hdmi_out = conn_state->hdmi_output;
 
 	pipe_config->has_hdmi_sink = !force_dvi && intel_hdmi->has_hdmi_sink;
 
@@ -1391,6 +1469,15 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
 		clock_12bpc *= 2;
 	}
 
+	/* Check if YCBCR HDMI output handling is required */
+	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;
 
@@ -1410,7 +1497,7 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
 	 */
 	if (pipe_config->pipe_bpp > 8*3 && pipe_config->has_hdmi_sink && !force_dvi &&
 	    hdmi_port_clock_valid(intel_hdmi, clock_12bpc, true, force_dvi) == 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

^ permalink raw reply related	[flat|nested] 58+ messages in thread

* [RESEND-CI v4 11/15] drm/i915: prepare scaler for YCBCR420 modeset
  2017-06-21 10:33 [RESEND-CI v4 00/15] HDMI YCBCR output handling in DRM layer Shashank Sharma
                   ` (8 preceding siblings ...)
  2017-06-21 10:34 ` [RESEND-CI v4 10/15] drm/i915: add compute-config for YCBCR outputs Shashank Sharma
@ 2017-06-21 10:34 ` Shashank Sharma
  2017-06-27 12:16   ` Ander Conselvan De Oliveira
  2017-06-21 10:34 ` [RESEND-CI v4 12/15] drm/i915: prepare pipe for YCBCR output Shashank Sharma
                   ` (4 subsequent siblings)
  14 siblings, 1 reply; 58+ messages in thread
From: Shashank Sharma @ 2017-06-21 10:34 UTC (permalink / raw)
  To: dri-devel, intel-gfx, ville.syrjala; +Cc: Ander Conselvan De Oliveira

To get a YCBCR420 output from intel platforms, we need one
scaler to scale down YCBCR444 samples to YCBCR420 samples.

This patch:
- Does scaler allocation for HDMI ycbcr420 outputs.
- Programs PIPE_MISC register for ycbcr420 output.
- Adds a new scaler user "HDMI output" to plug-into existing
  scaler framework. This output type is identified using bit
  30 of the scaler users bitmap.

V2: rebase
V3: rebase
V4: rebase

Cc: Ville Syrjala <ville.syrjala@linux.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_atomic.c  |  6 ++++++
 drivers/gpu/drm/i915/intel_display.c | 26 ++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h     | 10 +++++++++-
 drivers/gpu/drm/i915/intel_hdmi.c    | 10 ++++++++++
 drivers/gpu/drm/i915/intel_panel.c   |  3 ++-
 5 files changed, 53 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index 36d4e63..a8c9ac5 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -264,6 +264,12 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv,
 
 			/* panel fitter case: assign as a crtc scaler */
 			scaler_id = &scaler_state->scaler_id;
+		} else if (i == SKL_HDMI_OUTPUT_INDEX) {
+			name = "HDMI-OUTPUT";
+			idx = intel_crtc->base.base.id;
+
+			/* hdmi output case: needs a pipe scaler */
+			scaler_id = &scaler_state->scaler_id;
 		} else {
 			name = "PLANE";
 
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index da29536..983f581 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -4626,6 +4626,11 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
 	 */
 	need_scaling = src_w != dst_w || src_h != dst_h;
 
+	if (crtc_state->hdmi_output == DRM_HDMI_OUTPUT_YCBCR420
+		&& scaler_user == SKL_HDMI_OUTPUT_INDEX)
+		/* YCBCR 444 -> 420 conversion needs a scaler */
+		need_scaling = true;
+
 	/*
 	 * if plane is being disabled or scaler is no more required or force detach
 	 *  - free scaler binded to this plane/crtc
@@ -4673,6 +4678,26 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
 }
 
 /**
+ * skl_update_scaler_hdmi_output - Stages update to scaler state for HDMI.
+ * HDMI YCBCR 420 output needs a scaler, for downsampling.
+ *
+ * @state: crtc's scaler state
+ *
+ * Return
+ *     0 - scaler_usage updated successfully
+ *    error - requested scaling cannot be supported or other error condition
+ */
+int skl_update_scaler_crtc_hdmi_output(struct intel_crtc_state *state)
+{
+	const struct drm_display_mode *mode = &state->base.adjusted_mode;
+
+	return skl_update_scaler(state, !state->base.active,
+		SKL_HDMI_OUTPUT_INDEX, &state->scaler_state.scaler_id,
+		state->pipe_src_w, state->pipe_src_h,
+		mode->crtc_hdisplay, mode->crtc_vdisplay);
+}
+
+/**
  * skl_update_scaler_crtc - Stages update to scaler state for a given crtc.
  *
  * @state: crtc's scaler state
@@ -8058,6 +8083,7 @@ static void haswell_set_pipemisc(struct drm_crtc *crtc)
 {
 	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	enum drm_hdmi_output_type hdmi_out = intel_crtc->config->hdmi_output;
 
 	if (IS_BROADWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 9) {
 		u32 val = 0;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 38fe56c..2206aa8 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -471,7 +471,8 @@ struct intel_crtc_scaler_state {
 	 *
 	 *     If a bit is set, a user is using a scaler.
 	 *     Here user can be a plane or crtc as defined below:
-	 *       bits 0-30 - plane (bit position is index from drm_plane_index)
+	 *       bits 0-29 - plane (bit position is index from drm_plane_index)
+	 *       bit 30    - hdmi output
 	 *       bit 31    - crtc
 	 *
 	 * Instead of creating a new index to cover planes and crtc, using
@@ -484,6 +485,12 @@ struct intel_crtc_scaler_state {
 	 * avilability.
 	 */
 #define SKL_CRTC_INDEX 31
+
+	/*
+	 * HDMI YCBCR 420 output consume a scaler. So adding a user
+	 * for HDMI output 420 requirement.
+	 */
+#define SKL_HDMI_OUTPUT_INDEX 30
 	unsigned scaler_users;
 
 	/* scaler used by crtc for panel fitting purpose */
@@ -1481,6 +1488,7 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode,
 				 struct intel_crtc_state *pipe_config);
 
 int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state);
+int skl_update_scaler_crtc_hdmi_output(struct intel_crtc_state *state);
 int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state);
 
 static inline u32 intel_plane_ggtt_offset(const struct intel_plane_state *state)
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 22da5cd..8d5aa1e 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -1415,6 +1415,7 @@ intel_hdmi_compute_ycbcr_config(struct drm_connector_state *conn_state,
 	}
 
 	if (type == DRM_HDMI_OUTPUT_YCBCR420) {
+		struct intel_crtc *intel_crtc = to_intel_crtc(conn_state->crtc);
 
 		/* YCBCR420 TMDS rate requirement is half the pixel clock */
 		config->hdmi_output = DRM_HDMI_OUTPUT_YCBCR420;
@@ -1422,6 +1423,15 @@ intel_hdmi_compute_ycbcr_config(struct drm_connector_state *conn_state,
 		*clock_12bpc /= 2;
 		*clock_8bpc /= 2;
 
+		/* YCBCR 420 output conversion needs a scaler */
+		if (skl_update_scaler_crtc_hdmi_output(config)) {
+			DRM_ERROR("Scaler allocation for output failed\n");
+			return DRM_HDMI_OUTPUT_INVALID;
+		}
+
+		/* Bind this scaler to pipe */
+		intel_pch_panel_fitting(intel_crtc, config,
+					DRM_MODE_SCALE_FULLSCREEN);
 	}
 
 	/* Encoder is capable of this output, lets commit to CRTC */
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index 96c2cbd..b6a32c4 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -110,7 +110,8 @@ intel_pch_panel_fitting(struct intel_crtc *intel_crtc,
 
 	/* Native modes don't need fitting */
 	if (adjusted_mode->crtc_hdisplay == pipe_config->pipe_src_w &&
-	    adjusted_mode->crtc_vdisplay == pipe_config->pipe_src_h)
+	    adjusted_mode->crtc_vdisplay == pipe_config->pipe_src_h &&
+	    pipe_config->hdmi_output != DRM_HDMI_OUTPUT_YCBCR420)
 		goto done;
 
 	switch (fitting_mode) {
-- 
2.7.4

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

^ permalink raw reply related	[flat|nested] 58+ messages in thread

* [RESEND-CI v4 12/15] drm/i915: prepare pipe for YCBCR output
  2017-06-21 10:33 [RESEND-CI v4 00/15] HDMI YCBCR output handling in DRM layer Shashank Sharma
                   ` (9 preceding siblings ...)
  2017-06-21 10:34 ` [RESEND-CI v4 11/15] drm/i915: prepare scaler for YCBCR420 modeset Shashank Sharma
@ 2017-06-21 10:34 ` Shashank Sharma
  2017-06-21 10:34 ` [RESEND-CI v4 13/15] drm/i915: prepare csc unit for YCBCR HDMI output Shashank Sharma
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 58+ messages in thread
From: Shashank Sharma @ 2017-06-21 10:34 UTC (permalink / raw)
  To: dri-devel, intel-gfx, ville.syrjala
  Cc: Daniel Vetter, Ander Conselvan De Oliveira

To get HDMI YCBCR420 output, the PIPEMISC register should be
programmed to:
- Generate YCBCR output (bit 11)
- In case of YCBCR420 outputs, it should be programmed in full
  blend mode to use the scaler in 5x3 ratio (bits 26 and 27)

This patch:
- Adds definition of these bits.
- Programs PIPEMISC for YCBCR outputs.

V2: rebase
V3: rebase
V4: rebase

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

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 88e4707..77921ec 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -5196,6 +5196,9 @@ enum {
 
 #define _PIPE_MISC_A			0x70030
 #define _PIPE_MISC_B			0x71030
+#define   PIPEMISC_YCBCR420_ENABLE	(1<<27)
+#define   PIPEMISC_YCBCR420_MODE_BLEND	(1<<26)
+#define   PIPEMISC_OUTPUT_YCBCR		(1<<11)
 #define   PIPEMISC_DITHER_BPC_MASK	(7<<5)
 #define   PIPEMISC_DITHER_8_BPC		(0<<5)
 #define   PIPEMISC_DITHER_10_BPC	(1<<5)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 983f581..71fd19e 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -8109,6 +8109,15 @@ static void haswell_set_pipemisc(struct drm_crtc *crtc)
 		if (intel_crtc->config->dither)
 			val |= PIPEMISC_DITHER_ENABLE | PIPEMISC_DITHER_TYPE_SP;
 
+		if (hdmi_out > DRM_HDMI_OUTPUT_DEFAULT_RGB) {
+			val |= PIPEMISC_OUTPUT_YCBCR;
+
+			if (hdmi_out == DRM_HDMI_OUTPUT_YCBCR420) {
+				val |= PIPEMISC_YCBCR420_ENABLE |
+				       PIPEMISC_YCBCR420_MODE_BLEND;
+			}
+		}
+
 		I915_WRITE(PIPEMISC(intel_crtc->pipe), val);
 	}
 }
-- 
2.7.4

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

^ permalink raw reply related	[flat|nested] 58+ messages in thread

* [RESEND-CI v4 13/15] drm/i915: prepare csc unit for YCBCR HDMI output
  2017-06-21 10:33 [RESEND-CI v4 00/15] HDMI YCBCR output handling in DRM layer Shashank Sharma
                   ` (10 preceding siblings ...)
  2017-06-21 10:34 ` [RESEND-CI v4 12/15] drm/i915: prepare pipe for YCBCR output Shashank Sharma
@ 2017-06-21 10:34 ` Shashank Sharma
  2017-06-29 12:08   ` Ander Conselvan De Oliveira
  2017-06-21 10:34 ` [RESEND-CI v4 14/15] drm/i915: set colorspace for ycbcr outputs Shashank Sharma
                   ` (2 subsequent siblings)
  14 siblings, 1 reply; 58+ messages in thread
From: Shashank Sharma @ 2017-06-21 10:34 UTC (permalink / raw)
  To: dri-devel, intel-gfx, ville.syrjala
  Cc: Ander Conselvan De Oliveira, Daniel Vetter

To support ycbcr HDMI output, we need a pipe CSC block to
do the RGB->YCBCR conversion, as the blender output is in RGB.

Current Intel platforms have only one pipe CSC unit, so
we can either do color correction using it, or we can perform
RGB->YCBCR conversion.

This function adds a csc handler, to perform RGB->YCBCR conversion
as per recommended spec values.

V2: Rebase
V3: Rebase
V4: Rebase

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_color.c   | 47 +++++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/i915/intel_display.c | 32 ++++++++++++++++++++++++
 2 files changed, 78 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_color.c b/drivers/gpu/drm/i915/intel_color.c
index 306c6b0..12d5f21 100644
--- a/drivers/gpu/drm/i915/intel_color.c
+++ b/drivers/gpu/drm/i915/intel_color.c
@@ -41,6 +41,19 @@
 
 #define LEGACY_LUT_LENGTH		(sizeof(struct drm_color_lut) * 256)
 
+/* Post offset values for RGB->YCBCR conversion */
+#define POSTOFF_RGB_TO_YUV_HI 0x800
+#define POSTOFF_RGB_TO_YUV_ME 0x100
+#define POSTOFF_RGB_TO_YUV_LO 0x800
+
+/* Direct spec values for RGB->YUV conversion matrix */
+#define CSC_RGB_TO_YUV_RU_GU 0x2ba809d8
+#define CSC_RGB_TO_YUV_BU 0x37e80000
+#define CSC_RGB_TO_YUV_RY_GY 0x1e089cc0
+#define CSC_RGB_TO_YUV_BY 0xb5280000
+#define CSC_RGB_TO_YUV_RV_GV 0xbce89ad8
+#define CSC_RGB_TO_YUV_BV 0x1e080000
+
 /*
  * Extract the CSC coefficient from a CTM coefficient (in U32.32 fixed point
  * format). This macro takes the coefficient we want transformed and the
@@ -91,6 +104,35 @@ static void ctm_mult_by_limited(uint64_t *result, int64_t *input)
 	}
 }
 
+void i9xx_load_ycbcr_conversion_matrix(struct intel_crtc *intel_crtc)
+{
+	int pipe = intel_crtc->pipe;
+	struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
+
+	/* We don't use high values for conversion */
+	I915_WRITE(PIPE_CSC_PREOFF_HI(pipe), 0);
+	I915_WRITE(PIPE_CSC_PREOFF_ME(pipe), 0);
+	I915_WRITE(PIPE_CSC_PREOFF_LO(pipe), 0);
+
+	/* Program direct spec values for RGB to YCBCR conversion matrix */
+	I915_WRITE(PIPE_CSC_COEFF_RU_GU(pipe), CSC_RGB_TO_YUV_RU_GU);
+	I915_WRITE(PIPE_CSC_COEFF_BU(pipe), CSC_RGB_TO_YUV_BU);
+
+	I915_WRITE(PIPE_CSC_COEFF_RY_GY(pipe), CSC_RGB_TO_YUV_RY_GY);
+	I915_WRITE(PIPE_CSC_COEFF_BY(pipe), CSC_RGB_TO_YUV_BY);
+
+	I915_WRITE(PIPE_CSC_COEFF_RV_GV(pipe), CSC_RGB_TO_YUV_RV_GV);
+	I915_WRITE(PIPE_CSC_COEFF_BV(pipe), CSC_RGB_TO_YUV_BV);
+
+	/* Spec postoffset values */
+	I915_WRITE(PIPE_CSC_POSTOFF_HI(pipe), POSTOFF_RGB_TO_YUV_HI);
+	I915_WRITE(PIPE_CSC_POSTOFF_ME(pipe), POSTOFF_RGB_TO_YUV_ME);
+	I915_WRITE(PIPE_CSC_POSTOFF_LO(pipe), POSTOFF_RGB_TO_YUV_LO);
+
+	/* CSC mode before gamma */
+	I915_WRITE(PIPE_CSC_MODE(pipe), 0);
+}
+
 /* Set up the pipe CSC unit. */
 static void i9xx_load_csc_matrix(struct drm_crtc_state *crtc_state)
 {
@@ -101,7 +143,10 @@ static void i9xx_load_csc_matrix(struct drm_crtc_state *crtc_state)
 	uint16_t coeffs[9] = { 0, };
 	struct intel_crtc_state *intel_crtc_state = to_intel_crtc_state(crtc_state);
 
-	if (crtc_state->ctm) {
+	if (intel_crtc_state->hdmi_output > DRM_HDMI_OUTPUT_DEFAULT_RGB) {
+		i9xx_load_ycbcr_conversion_matrix(intel_crtc);
+		return;
+	} else if (crtc_state->ctm) {
 		struct drm_color_ctm *ctm =
 			(struct drm_color_ctm *)crtc_state->ctm->data;
 		uint64_t input[9] = { 0, };
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 71fd19e..96ff2a0 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6261,6 +6261,29 @@ static void intel_crtc_compute_pixel_rate(struct intel_crtc_state *crtc_state)
 			ilk_pipe_pixel_rate(crtc_state);
 }
 
+static int intel_crtc_ycbcr_config(struct intel_crtc_state *state)
+{
+	struct drm_crtc_state *drm_state = &state->base;
+	struct drm_i915_private *dev_priv = to_i915(drm_state->crtc->dev);
+
+	/* YCBCR420 is supported only in HDMI 2.0 controllers */
+	if ((state->hdmi_output == DRM_HDMI_OUTPUT_YCBCR420) &&
+		!IS_GEMINILAKE(dev_priv)) {
+		DRM_ERROR("YCBCR420 output is not supported\n");
+		return -EINVAL;
+	}
+
+	/* We need CSC for output conversion from RGB->YCBCR */
+	if (drm_state->ctm) {
+		DRM_ERROR("YCBCR output and CTM is not possible together\n");
+		return -EINVAL;
+	}
+
+	DRM_DEBUG_DRIVER("Output %s can be supported\n",
+			 drm_get_hdmi_output_name(state->hdmi_output));
+	return 0;
+}
+
 static int intel_crtc_compute_config(struct intel_crtc *crtc,
 				     struct intel_crtc_state *pipe_config)
 {
@@ -6290,6 +6313,14 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
 		return -EINVAL;
 	}
 
+	/* YCBCR output check */
+	if (pipe_config->hdmi_output > DRM_HDMI_OUTPUT_DEFAULT_RGB) {
+		if (intel_crtc_ycbcr_config(pipe_config)) {
+			DRM_ERROR("Cant enable HDMI YCBCR output\n");
+			return -EINVAL;
+		}
+	}
+
 	/*
 	 * Pipe horizontal size must be even in:
 	 * - DVO ganged mode
@@ -11658,6 +11689,7 @@ intel_modeset_pipe_config(struct drm_crtc *crtc,
 			DRM_DEBUG_KMS("Encoder config failure\n");
 			goto fail;
 		}
+
 	}
 
 	/* Set default port clock if not overwritten by the encoder. Needs to be
-- 
2.7.4

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

^ permalink raw reply related	[flat|nested] 58+ messages in thread

* [RESEND-CI v4 14/15] drm/i915: set colorspace for ycbcr outputs
  2017-06-21 10:33 [RESEND-CI v4 00/15] HDMI YCBCR output handling in DRM layer Shashank Sharma
                   ` (11 preceding siblings ...)
  2017-06-21 10:34 ` [RESEND-CI v4 13/15] drm/i915: prepare csc unit for YCBCR HDMI output Shashank Sharma
@ 2017-06-21 10:34 ` Shashank Sharma
  2017-06-21 10:34 ` [RESEND-CI v4 15/15] drm/i915/glk: set HDMI 2.0 identifier Shashank Sharma
  2017-06-21 10:34 ` [PATCH v5 7/7] drm: create hdmi output property Shashank Sharma
  14 siblings, 0 replies; 58+ messages in thread
From: Shashank Sharma @ 2017-06-21 10:34 UTC (permalink / raw)
  To: dri-devel, intel-gfx, ville.syrjala; +Cc: Ander Conselvan De Oliveira

When HDMI output is other than RGB, we have to load the
corresponding colorspace of output mode. This patch fills
the colorspace of AVI infoframe as per the HDMI output mode.

V2: Rebase
V3: Rebase
V4: Rebase

Cc: Ville Syrjala <ville.syrjala@linux.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_hdmi.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 8d5aa1e..3bd9af3 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -472,6 +472,14 @@ static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder,
 		return;
 	}
 
+	ret = drm_hdmi_avi_infoframe_set_colorspace(&frame.avi,
+						    adjusted_mode,
+						    crtc_state->hdmi_output);
+	if (ret < 0) {
+		DRM_ERROR("couldn't fill AVI colorspace\n");
+		return;
+	}
+
 	drm_hdmi_avi_infoframe_quant_range(&frame.avi, adjusted_mode,
 					   crtc_state->limited_color_range ?
 					   HDMI_QUANTIZATION_RANGE_LIMITED :
-- 
2.7.4

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

^ permalink raw reply related	[flat|nested] 58+ messages in thread

* [RESEND-CI v4 15/15] drm/i915/glk: set HDMI 2.0 identifier
  2017-06-21 10:33 [RESEND-CI v4 00/15] HDMI YCBCR output handling in DRM layer Shashank Sharma
                   ` (12 preceding siblings ...)
  2017-06-21 10:34 ` [RESEND-CI v4 14/15] drm/i915: set colorspace for ycbcr outputs Shashank Sharma
@ 2017-06-21 10:34 ` Shashank Sharma
  2017-06-30 12:07   ` [Intel-gfx] " Ander Conselvan De Oliveira
  2017-06-21 10:34 ` [PATCH v5 7/7] drm: create hdmi output property Shashank Sharma
  14 siblings, 1 reply; 58+ messages in thread
From: Shashank Sharma @ 2017-06-21 10:34 UTC (permalink / raw)
  To: dri-devel, intel-gfx, ville.syrjala

This patch sets the is_hdmi2_src identifier in drm connector
for GLK platform. GLK contains a native HDMI 2.0 controller.
This identifier will help the EDID handling functions to save
lot of work which is specific to HDMI 2.0 sources.

V3: Added this patch
V4: Rebase

Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
---
 drivers/gpu/drm/i915/intel_hdmi.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 3bd9af3..0d9d088 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -1979,6 +1979,9 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
 	connector->doublescan_allowed = 0;
 	connector->stereo_allowed = 1;
 
+	if (IS_GEMINILAKE(dev_priv))
+		connector->ycbcr_420_allowed = true;
+
 	intel_hdmi->ddc_bus = intel_hdmi_ddc_pin(dev_priv, port);
 
 	switch (port) {
-- 
2.7.4

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

^ permalink raw reply related	[flat|nested] 58+ messages in thread

* [PATCH v5 7/7] drm: create hdmi output property
  2017-06-21 10:33 [RESEND-CI v4 00/15] HDMI YCBCR output handling in DRM layer Shashank Sharma
                   ` (13 preceding siblings ...)
  2017-06-21 10:34 ` [RESEND-CI v4 15/15] drm/i915/glk: set HDMI 2.0 identifier Shashank Sharma
@ 2017-06-21 10:34 ` Shashank Sharma
  2017-06-22  7:14   ` [Intel-gfx] " Daniel Vetter
  2017-06-27 12:14   ` Ville Syrjälä
  14 siblings, 2 replies; 58+ messages in thread
From: Shashank Sharma @ 2017-06-21 10:34 UTC (permalink / raw)
  To: dri-devel, intel-gfx, ville.syrjala; +Cc: Daniel Vetter, Jose Abreu

HDMI displays can support various output types, based on
the color space and subsampling type. The possible
outputs from a HDMI 2.0 monitor could be:
 - RGB
 - YCBCR 444
 - YCBCR 422
 - YCBCR 420

This patch adds a drm property "hdmi_output_format", using which,
a user can specify its preference, for the HDMI output type. The
output type enums are similar to the mentioned outputs above. To
handle various subsampling of YCBCR output types, this property
allows two special cases:
 - DRM_HDMI_OUTPUT_YCBCR_HQ
   This indicates preferred output should be YCBCR output, with highest
   subsampling rate by the source/sink, which can be typically:
 	- ycbcr444
 	- ycbcr422
 	- ycbcr420
 - DRM_HDMI_OUTPUT_YCBCR_LQ
   This indicates preferred output should be YCBCR output, with lowest
   subsampling rate supported by source/sink, which can be:
 	- ycbcr420
 	- ycbcr422
 	- ycbcr444

Default value of the property is set to 0 = RGB, so no changes if you
dont set the property.

PS: While doing modeset for YCBCR 420 only modes, this property is
    ignored, as those timings can be supported only in YCBCR 420
    output mode.

V2: Added description for the new variable to address build warning
V3: Rebase
V4: Rebase
V5: Added get_property counterpart to fix IGT BAT failures

Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
Cc: Jose Abreu <joabreu@synopsys.com>
Cc: Daniel Vetter <daniel.vetter@intel.com>
Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
---
 drivers/gpu/drm/drm_atomic.c        |  4 ++++
 drivers/gpu/drm/drm_atomic_helper.c |  4 ++++
 drivers/gpu/drm/drm_connector.c     | 32 ++++++++++++++++++++++++++++++++
 include/drm/drm_connector.h         | 18 ++++++++++++++++++
 include/drm/drm_mode_config.h       |  5 +++++
 5 files changed, 63 insertions(+)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 77dcef0..ea90f8e 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -1192,6 +1192,8 @@ int drm_atomic_connector_set_property(struct drm_connector *connector,
 		state->picture_aspect_ratio = val;
 	} else if (property == connector->scaling_mode_property) {
 		state->scaling_mode = val;
+	} else if (property == config->hdmi_output_property) {
+		state->hdmi_output = val;
 	} else if (connector->funcs->atomic_set_property) {
 		return connector->funcs->atomic_set_property(connector,
 				state, property, val);
@@ -1272,6 +1274,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector,
 		*val = state->picture_aspect_ratio;
 	} else if (property == connector->scaling_mode_property) {
 		*val = state->scaling_mode;
+	} else if (property == config->hdmi_output_property) {
+		*val = state->hdmi_output;
 	} else if (connector->funcs->atomic_get_property) {
 		return connector->funcs->atomic_get_property(connector,
 				state, property, val);
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 86d3093..1356b3f 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -637,6 +637,10 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
 			if (old_connector_state->link_status !=
 			    new_connector_state->link_status)
 				new_crtc_state->connectors_changed = true;
+
+			if (old_connector_state->hdmi_output !=
+			    new_connector_state->hdmi_output)
+				new_crtc_state->connectors_changed = true;
 		}
 
 		if (funcs->atomic_check)
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 5cd61af..f3c5928 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -227,6 +227,11 @@ int drm_connector_init(struct drm_device *dev,
 					      config->edid_property,
 					      0);
 
+	if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL)
+		drm_object_attach_property(&connector->base,
+					   config->hdmi_output_property,
+					   0);
+
 	drm_object_attach_property(&connector->base,
 				      config->dpms_property, 0);
 
@@ -617,6 +622,26 @@ static const struct drm_prop_enum_list drm_link_status_enum_list[] = {
 };
 DRM_ENUM_NAME_FN(drm_get_link_status_name, drm_link_status_enum_list)
 
+static const struct drm_prop_enum_list drm_hdmi_output_enum_list[] = {
+	{ DRM_HDMI_OUTPUT_DEFAULT_RGB, "output_rgb" },
+	{ DRM_HDMI_OUTPUT_YCBCR444, "output_ycbcr444" },
+	{ DRM_HDMI_OUTPUT_YCBCR422, "output_ycbcr422" },
+	{ DRM_HDMI_OUTPUT_YCBCR420, "output_ycbcr420" },
+	{ DRM_HDMI_OUTPUT_YCBCR_HQ, "output_ycbcr_high_subsampling" },
+	{ DRM_HDMI_OUTPUT_YCBCR_LQ, "output_ycbcr_low_subsampling" },
+	{ DRM_HDMI_OUTPUT_INVALID, "invalid_output" },
+};
+
+/**
+ * drm_get_hdmi_output_name - return a string for a given hdmi output enum
+ * @type: enum of output type
+ */
+const char *drm_get_hdmi_output_name(enum drm_hdmi_output_type type)
+{
+	return drm_hdmi_output_enum_list[type].name;
+}
+EXPORT_SYMBOL(drm_get_hdmi_output_name);
+
 /**
  * drm_display_info_set_bus_formats - set the supported bus formats
  * @info: display info to store bus formats in
@@ -789,6 +814,13 @@ int drm_connector_create_standard_properties(struct drm_device *dev)
 		return -ENOMEM;
 	dev->mode_config.link_status_property = prop;
 
+	prop = drm_property_create_enum(dev, 0, "hdmi_output_format",
+					drm_hdmi_output_enum_list,
+					ARRAY_SIZE(drm_hdmi_output_enum_list));
+	if (!prop)
+		return -ENOMEM;
+	dev->mode_config.hdmi_output_property = prop;
+
 	return 0;
 }
 
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 1305fe9..5ba1f32 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -321,6 +321,17 @@ struct drm_tv_connector_state {
 	unsigned int hue;
 };
 
+/* HDMI output pixel format */
+enum drm_hdmi_output_type {
+	DRM_HDMI_OUTPUT_DEFAULT_RGB, /* default RGB */
+	DRM_HDMI_OUTPUT_YCBCR444, /* YCBCR 444 */
+	DRM_HDMI_OUTPUT_YCBCR422, /* YCBCR 422 */
+	DRM_HDMI_OUTPUT_YCBCR420, /* YCBCR 420 */
+	DRM_HDMI_OUTPUT_YCBCR_HQ, /* Highest subsampled YUV */
+	DRM_HDMI_OUTPUT_YCBCR_LQ, /* Lowest subsampled YUV */
+	DRM_HDMI_OUTPUT_INVALID, /* Guess what ? */
+};
+
 /**
  * struct drm_connector_state - mutable connector state
  * @connector: backpointer to the connector
@@ -365,6 +376,12 @@ struct drm_connector_state {
 	 * upscaling, mostly used for built-in panels.
 	 */
 	unsigned int scaling_mode;
+
+	/**
+	 * @hdmi_output: Connector property to control the
+	 * HDMI output mode (RGB/YCBCR444/422/420).
+	 */
+	enum drm_hdmi_output_type hdmi_output;
 };
 
 /**
@@ -993,6 +1010,7 @@ static inline void drm_connector_unreference(struct drm_connector *connector)
 
 const char *drm_get_connector_status_name(enum drm_connector_status status);
 const char *drm_get_subpixel_order_name(enum subpixel_order order);
+const char *drm_get_hdmi_output_name(enum drm_hdmi_output_type type);
 const char *drm_get_dpms_name(int val);
 const char *drm_get_dvi_i_subconnector_name(int val);
 const char *drm_get_dvi_i_select_name(int val);
diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h
index 4298171..1887261 100644
--- a/include/drm/drm_mode_config.h
+++ b/include/drm/drm_mode_config.h
@@ -740,6 +740,11 @@ struct drm_mode_config {
 	 * the position of the output on the host's screen.
 	 */
 	struct drm_property *suggested_y_property;
+	/**
+	 * @hdmi_output_property: output pixel format from HDMI display
+	 * Default is set for RGB
+	 */
+	struct drm_property *hdmi_output_property;
 
 	/* dumb ioctl parameters */
 	uint32_t preferred_depth, prefer_shadow;
-- 
2.7.4

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

^ permalink raw reply related	[flat|nested] 58+ messages in thread

* Re: [RESEND-CI v4 01/15] drm: add HDMI 2.0 VIC support for AVI info-frames
  2017-06-21 10:33 ` [RESEND-CI v4 01/15] drm: add HDMI 2.0 VIC support for AVI info-frames Shashank Sharma
@ 2017-06-21 13:41   ` Neil Armstrong
  2017-06-30 11:54   ` Ville Syrjälä
  1 sibling, 0 replies; 58+ messages in thread
From: Neil Armstrong @ 2017-06-21 13:41 UTC (permalink / raw)
  To: Shashank Sharma, dri-devel, intel-gfx, ville.syrjala
  Cc: Jose Abreu, Alex Deucher, Daniel Vetter

On 06/21/2017 12:33 PM, Shashank Sharma wrote:
> HDMI 1.4b support the CEA video modes as per range of CEA-861-D (VIC 1-64).
> For any other mode, the VIC filed in AVI infoframes should be 0.
> HDMI 2.0 sinks, support video modes range as per CEA-861-F spec, which is
> extended to (VIC 1-107).
> 
> This patch adds a bool input variable, which indicates if the connected
> sink is a HDMI 2.0 sink or not. This will make sure that we don't pass a
> HDMI 2.0 VIC to a HDMI 1.4 sink.
> 
> This patch touches all drm drivers, who are callers of this function
> drm_hdmi_avi_infoframe_from_display_mode but to make sure there is
> no change in current behavior, is_hdmi2 is kept as false.
> 
> In case of I915 driver, this patch:
> - checks if the connected display is HDMI 2.0.
> - HDMI infoframes carry one of this two type of information:
> 	- VIC for 4K modes for HDMI 1.4 sinks
> 	- S3D information for S3D modes
>   As CEA-861-F has already defined VICs for 4K videomodes, this
>   patch doesn't allow sending HDMI infoframes for HDMI 2.0 sinks,
>   until the mode is 3D.
> 
> Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
> Cc: Jose Abreu <jose.abreu@synopsys.com>
> Cc: Andrzej Hajda <a.hajda@samsung.com>
> Cc: Alex Deucher <alexander.deucher@amd.com>
> Cc: Daniel Vetter <daniel.vetter@intel.com>
> 
> PS: This patch touches a few lines in few files, which were
> already above 80 char, so checkpatch gives 80 char warning again.
> - gpu/drm/omapdrm/omap_encoder.c
> - gpu/drm/i915/intel_sdvo.c
> 
> V2: Rebase, Added r-b from Andrzej
> V3: Addressed review comment from Ville:
> 	- Do not send VICs in both AVI-IF and HDMI-IF
> 	  send only one of it.
> 
> Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
> ---
>  drivers/gpu/drm/amd/amdgpu/dce_v10_0.c    |  2 +-
>  drivers/gpu/drm/amd/amdgpu/dce_v11_0.c    |  2 +-
>  drivers/gpu/drm/amd/amdgpu/dce_v8_0.c     |  2 +-
>  drivers/gpu/drm/bridge/analogix-anx78xx.c |  3 ++-
>  drivers/gpu/drm/bridge/sii902x.c          |  2 +-
>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.c |  2 +-
>  drivers/gpu/drm/drm_edid.c                | 12 +++++++++++-
>  drivers/gpu/drm/exynos/exynos_hdmi.c      |  2 +-
>  drivers/gpu/drm/i2c/tda998x_drv.c         |  2 +-
>  drivers/gpu/drm/i915/intel_hdmi.c         | 17 ++++++++++++++++-
>  drivers/gpu/drm/i915/intel_sdvo.c         |  3 ++-
>  drivers/gpu/drm/mediatek/mtk_hdmi.c       |  2 +-
>  drivers/gpu/drm/omapdrm/omap_encoder.c    |  3 ++-
>  drivers/gpu/drm/radeon/radeon_audio.c     |  2 +-
>  drivers/gpu/drm/rockchip/inno_hdmi.c      |  2 +-
>  drivers/gpu/drm/sti/sti_hdmi.c            |  2 +-
>  drivers/gpu/drm/tegra/hdmi.c              |  2 +-
>  drivers/gpu/drm/tegra/sor.c               |  2 +-
>  drivers/gpu/drm/vc4/vc4_hdmi.c            |  2 +-
>  drivers/gpu/drm/zte/zx_hdmi.c             |  2 +-
>  include/drm/drm_edid.h                    |  3 ++-
>  21 files changed, 50 insertions(+), 21 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
> index 3c62c45..4923ddc 100644
> --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
> @@ -1864,7 +1864,7 @@ static void dce_v10_0_afmt_setmode(struct drm_encoder *encoder,
>  	dce_v10_0_audio_write_sad_regs(encoder);
>  	dce_v10_0_audio_write_latency_fields(encoder, mode);
>  
> -	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
> +	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
>  	if (err < 0) {
>  		DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
>  		return;
> diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
> index c8ed0fa..4101684 100644
> --- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
> @@ -1848,7 +1848,7 @@ static void dce_v11_0_afmt_setmode(struct drm_encoder *encoder,
>  	dce_v11_0_audio_write_sad_regs(encoder);
>  	dce_v11_0_audio_write_latency_fields(encoder, mode);
>  
> -	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
> +	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
>  	if (err < 0) {
>  		DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
>  		return;
> diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
> index 3e90c19..a7f6b32 100644
> --- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
> @@ -1747,7 +1747,7 @@ static void dce_v8_0_afmt_setmode(struct drm_encoder *encoder,
>  	dce_v8_0_audio_write_sad_regs(encoder);
>  	dce_v8_0_audio_write_latency_fields(encoder, mode);
>  
> -	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
> +	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
>  	if (err < 0) {
>  		DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
>  		return;
> diff --git a/drivers/gpu/drm/bridge/analogix-anx78xx.c b/drivers/gpu/drm/bridge/analogix-anx78xx.c
> index 9006578..a083211 100644
> --- a/drivers/gpu/drm/bridge/analogix-anx78xx.c
> +++ b/drivers/gpu/drm/bridge/analogix-anx78xx.c
> @@ -1097,7 +1097,8 @@ static void anx78xx_bridge_mode_set(struct drm_bridge *bridge,
>  
>  	mutex_lock(&anx78xx->lock);
>  
> -	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, adjusted_mode);
> +	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, adjusted_mode,
> +						       false);
>  	if (err) {
>  		DRM_ERROR("Failed to setup AVI infoframe: %d\n", err);
>  		goto unlock;
> diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c
> index 9b87067..3dc40f6 100644
> --- a/drivers/gpu/drm/bridge/sii902x.c
> +++ b/drivers/gpu/drm/bridge/sii902x.c
> @@ -269,7 +269,7 @@ static void sii902x_bridge_mode_set(struct drm_bridge *bridge,
>  	if (ret)
>  		return;
>  
> -	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame, adj);
> +	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame, adj, false);
>  	if (ret < 0) {
>  		DRM_ERROR("couldn't fill AVI infoframe\n");
>  		return;
> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> index ead1124..0b0c9de 100644
> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> @@ -1317,7 +1317,7 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
>  	u8 val;
>  
>  	/* Initialise info frame from DRM mode */
> -	drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
> +	drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
>  
>  	if (hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format))
>  		frame.colorspace = HDMI_COLORSPACE_YUV444;
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index 2e55599..d312fe1 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -4334,12 +4334,14 @@ EXPORT_SYMBOL(drm_set_preferred_mode);
>   *                                              data from a DRM display mode
>   * @frame: HDMI AVI infoframe
>   * @mode: DRM display mode
> + * @is_hdmi2_sink: Sink is HDMI 2.0 compliant
>   *
>   * Return: 0 on success or a negative error code on failure.
>   */
>  int
>  drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
> -					 const struct drm_display_mode *mode)
> +					 const struct drm_display_mode *mode,
> +					 bool is_hdmi2_sink)
>  {
>  	int err;
>  
> @@ -4355,6 +4357,14 @@ drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
>  
>  	frame->video_code = drm_match_cea_mode(mode);
>  
> +	/*
> +	 * HDMI 1.4 VIC range: 1 <= VIC <= 64 (CEA-861-D) but
> +	 * HDMI 2.0 VIC range: 1 <= VIC <= 107 (CEA-861-F). So we
> +	 * have to make sure we dont break HDMI 1.4 sinks.
> +	 */
> +	if (!is_hdmi2_sink && frame->video_code > 64)
> +		frame->video_code = 0;
> +
>  	frame->picture_aspect = HDMI_PICTURE_ASPECT_NONE;
>  
>  	/*
> diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
> index 06bfbe4..c953927 100644
> --- a/drivers/gpu/drm/exynos/exynos_hdmi.c
> +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
> @@ -784,7 +784,7 @@ static void hdmi_reg_infoframes(struct hdmi_context *hdata)
>  	}
>  
>  	ret = drm_hdmi_avi_infoframe_from_display_mode(&frm.avi,
> -			&hdata->current_mode);
> +			&hdata->current_mode, false);
>  	if (!ret)
>  		ret = hdmi_avi_infoframe_pack(&frm.avi, buf, sizeof(buf));
>  	if (ret > 0) {
> diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
> index 86f47e1..d1e7ac5 100644
> --- a/drivers/gpu/drm/i2c/tda998x_drv.c
> +++ b/drivers/gpu/drm/i2c/tda998x_drv.c
> @@ -712,7 +712,7 @@ tda998x_write_avi(struct tda998x_priv *priv, struct drm_display_mode *mode)
>  {
>  	union hdmi_infoframe frame;
>  
> -	drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
> +	drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
>  	frame.avi.quantization_range = HDMI_QUANTIZATION_RANGE_FULL;
>  
>  	tda998x_write_if(priv, DIP_IF_FLAGS_IF2, REG_IF2_HB0, &frame);
> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> index ec0779a..170abc4 100644
> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> @@ -459,11 +459,14 @@ static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder,
>  	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
>  	const struct drm_display_mode *adjusted_mode =
>  		&crtc_state->base.adjusted_mode;
> +	struct drm_connector *connector = &intel_hdmi->attached_connector->base;
> +	bool is_hdmi2_sink = connector->display_info.hdmi.scdc.supported;
>  	union hdmi_infoframe frame;
>  	int ret;
>  
>  	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
> -						       adjusted_mode);
> +						       adjusted_mode,
> +						       is_hdmi2_sink);
>  	if (ret < 0) {
>  		DRM_ERROR("couldn't fill AVI infoframe\n");
>  		return;
> @@ -816,6 +819,8 @@ static void hsw_set_infoframes(struct drm_encoder *encoder,
>  {
>  	struct drm_i915_private *dev_priv = to_i915(encoder->dev);
>  	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
> +	struct drm_hdmi_info *hdmi = &conn_state->connector->display_info.hdmi;
> +	const struct drm_display_mode *mode = &crtc_state->base.adjusted_mode;
>  	i915_reg_t reg = HSW_TVIDEO_DIP_CTL(crtc_state->cpu_transcoder);
>  	u32 val = I915_READ(reg);
>  
> @@ -839,6 +844,16 @@ static void hsw_set_infoframes(struct drm_encoder *encoder,
>  
>  	intel_hdmi_set_avi_infoframe(encoder, crtc_state);
>  	intel_hdmi_set_spd_infoframe(encoder, crtc_state);
> +
> +	/*
> +	 * CEA-861-F added new VICs for 4k video modes, due to which
> +	 * HDMI 2.0 sinks need HDMI IF only for S3D information (Not for
> +	 * 4k VICs). So for a HDMI 2.0 sink, if the video mode is not 3D,
> +	 * don't bother sending HDMI IF.
> +	 */
> +	if (hdmi->scdc.supported && !(mode->flags & DRM_MODE_FLAG_3D_MASK))
> +		return;
> +
>  	intel_hdmi_set_hdmi_infoframe(encoder, crtc_state);
>  }
>  
> diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
> index f4329d2..737076e 100644
> --- a/drivers/gpu/drm/i915/intel_sdvo.c
> +++ b/drivers/gpu/drm/i915/intel_sdvo.c
> @@ -996,7 +996,8 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo,
>  	ssize_t len;
>  
>  	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
> -						       &pipe_config->base.adjusted_mode);
> +						       &pipe_config->base.adjusted_mode,
> +						       false);
>  	if (ret < 0) {
>  		DRM_ERROR("couldn't fill AVI infoframe\n");
>  		return false;
> diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> index 0a4ffd7..5c0d024 100644
> --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> @@ -975,7 +975,7 @@ static int mtk_hdmi_setup_avi_infoframe(struct mtk_hdmi *hdmi,
>  	u8 buffer[17];
>  	ssize_t err;
>  
> -	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
> +	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
>  	if (err < 0) {
>  		dev_err(hdmi->dev,
>  			"Failed to get AVI infoframe from mode: %zd\n", err);
> diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c b/drivers/gpu/drm/omapdrm/omap_encoder.c
> index 86c977b..624f5b5 100644
> --- a/drivers/gpu/drm/omapdrm/omap_encoder.c
> +++ b/drivers/gpu/drm/omapdrm/omap_encoder.c
> @@ -85,7 +85,8 @@ static void omap_encoder_mode_set(struct drm_encoder *encoder,
>  	if (hdmi_mode && dssdev->driver->set_hdmi_infoframe) {
>  		struct hdmi_avi_infoframe avi;
>  
> -		r = drm_hdmi_avi_infoframe_from_display_mode(&avi, adjusted_mode);
> +		r = drm_hdmi_avi_infoframe_from_display_mode(&avi, adjusted_mode,
> +							     false);
>  		if (r == 0)
>  			dssdev->driver->set_hdmi_infoframe(dssdev, &avi);
>  	}
> diff --git a/drivers/gpu/drm/radeon/radeon_audio.c b/drivers/gpu/drm/radeon/radeon_audio.c
> index aaacac1..770e31f 100644
> --- a/drivers/gpu/drm/radeon/radeon_audio.c
> +++ b/drivers/gpu/drm/radeon/radeon_audio.c
> @@ -516,7 +516,7 @@ static int radeon_audio_set_avi_packet(struct drm_encoder *encoder,
>  	if (!connector)
>  		return -EINVAL;
>  
> -	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
> +	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
>  	if (err < 0) {
>  		DRM_ERROR("failed to setup AVI infoframe: %d\n", err);
>  		return err;
> diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c
> index 7d9b75e..7149968 100644
> --- a/drivers/gpu/drm/rockchip/inno_hdmi.c
> +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c
> @@ -294,7 +294,7 @@ static int inno_hdmi_config_video_avi(struct inno_hdmi *hdmi,
>  	union hdmi_infoframe frame;
>  	int rc;
>  
> -	rc = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
> +	rc = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
>  
>  	if (hdmi->hdmi_data.enc_out_format == HDMI_COLORSPACE_YUV444)
>  		frame.avi.colorspace = HDMI_COLORSPACE_YUV444;
> diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
> index a59c95a..dbc6a19 100644
> --- a/drivers/gpu/drm/sti/sti_hdmi.c
> +++ b/drivers/gpu/drm/sti/sti_hdmi.c
> @@ -434,7 +434,7 @@ static int hdmi_avi_infoframe_config(struct sti_hdmi *hdmi)
>  
>  	DRM_DEBUG_DRIVER("\n");
>  
> -	ret = drm_hdmi_avi_infoframe_from_display_mode(&infoframe, mode);
> +	ret = drm_hdmi_avi_infoframe_from_display_mode(&infoframe, mode, false);
>  	if (ret < 0) {
>  		DRM_ERROR("failed to setup AVI infoframe: %d\n", ret);
>  		return ret;
> diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c
> index cda0491..718d8db 100644
> --- a/drivers/gpu/drm/tegra/hdmi.c
> +++ b/drivers/gpu/drm/tegra/hdmi.c
> @@ -734,7 +734,7 @@ static void tegra_hdmi_setup_avi_infoframe(struct tegra_hdmi *hdmi,
>  	u8 buffer[17];
>  	ssize_t err;
>  
> -	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
> +	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
>  	if (err < 0) {
>  		dev_err(hdmi->dev, "failed to setup AVI infoframe: %zd\n", err);
>  		return;
> diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c
> index a8f5289..fb2709c 100644
> --- a/drivers/gpu/drm/tegra/sor.c
> +++ b/drivers/gpu/drm/tegra/sor.c
> @@ -1904,7 +1904,7 @@ tegra_sor_hdmi_setup_avi_infoframe(struct tegra_sor *sor,
>  	value &= ~INFOFRAME_CTRL_ENABLE;
>  	tegra_sor_writel(sor, value, SOR_HDMI_AVI_INFOFRAME_CTRL);
>  
> -	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
> +	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
>  	if (err < 0) {
>  		dev_err(sor->dev, "failed to setup AVI infoframe: %d\n", err);
>  		return err;
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index ed63d4e..406d6d8 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -395,7 +395,7 @@ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
>  	union hdmi_infoframe frame;
>  	int ret;
>  
> -	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
> +	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
>  	if (ret < 0) {
>  		DRM_ERROR("couldn't fill AVI infoframe\n");
>  		return;
> diff --git a/drivers/gpu/drm/zte/zx_hdmi.c b/drivers/gpu/drm/zte/zx_hdmi.c
> index 0df7366..7e834e3 100644
> --- a/drivers/gpu/drm/zte/zx_hdmi.c
> +++ b/drivers/gpu/drm/zte/zx_hdmi.c
> @@ -124,7 +124,7 @@ static int zx_hdmi_config_video_avi(struct zx_hdmi *hdmi,
>  	union hdmi_infoframe frame;
>  	int ret;
>  
> -	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
> +	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
>  	if (ret) {
>  		DRM_DEV_ERROR(hdmi->dev, "failed to get avi infoframe: %d\n",
>  			      ret);
> diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
> index 7b9f48b..89c0062 100644
> --- a/include/drm/drm_edid.h
> +++ b/include/drm/drm_edid.h
> @@ -343,7 +343,8 @@ drm_load_edid_firmware(struct drm_connector *connector)
>  
>  int
>  drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
> -					 const struct drm_display_mode *mode);
> +					 const struct drm_display_mode *mode,
> +					 bool is_hdmi2_sink);
>  int
>  drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame,
>  					    const struct drm_display_mode *mode);
> 

Reviewed-by: Neil Armstrong <narmstrong@baylibre.com>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [RESEND-CI v4 02/15] drm: add YCBCR 420 capability identifier
  2017-06-21 10:34 ` [RESEND-CI v4 02/15] drm: add YCBCR 420 capability identifier Shashank Sharma
@ 2017-06-21 13:42   ` Neil Armstrong
  0 siblings, 0 replies; 58+ messages in thread
From: Neil Armstrong @ 2017-06-21 13:42 UTC (permalink / raw)
  To: Shashank Sharma, dri-devel, intel-gfx, ville.syrjala

On 06/21/2017 12:34 PM, Shashank Sharma wrote:
> This patch adds a bool variable (ycbcr_420_allowed) in the drm connector
> structure. While handling the EDID from HDMI 2.0 sinks, its important to
> know if the source is capable of handling YCBCR 420 outputs or not, so that
> a lot of work can be done/bypassed based on this information. One such
> example is adding YCBCR420 only modes.
> 
> If the driver knows that this source is not HDMI 2.0 capable, it will
> not add YCBCR420-only modes while adding EDID modes, and will prevent
> any runtime modeset failures.
> 
> This variable will be initialized from I915 driver in the next patch
> and will be used in the EDID handling for HDMI 2.0 specific features,
> in this same series.
> 
> V3: introduced the new variable
> V4: changed variable name from is_hdmi2_src to ycbcr_420_allowed (Ville)
> 
> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
> ---
>  include/drm/drm_connector.h | 9 +++++++++
>  1 file changed, 9 insertions(+)
> 
> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> index d8bb25f..7493fd3 100644
> --- a/include/drm/drm_connector.h
> +++ b/include/drm/drm_connector.h
> @@ -728,6 +728,15 @@ struct drm_connector {
>  	bool interlace_allowed;
>  	bool doublescan_allowed;
>  	bool stereo_allowed;
> +
> +	/**
> +	 * @ycbcr_420_allowed : This bool indicates if this connector is
> +	 * capable of handling YCBCR 420 output. While parsing the EDID
> +	 * blocks, its very helpful to know, if the source is capable of
> +	 * handling YCBCR 420 outputs.
> +	 */
> +	bool ycbcr_420_allowed;
> +
>  	/**
>  	 * @registered: Is this connector exposed (registered) with userspace?
>  	 * Protected by @mutex.
> 

Reviewed-by: Neil Armstrong <narmstrong@baylibre.com>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [RESEND-CI v4 03/15] drm/edid: Complete CEA modedb(VIC 1-107)
  2017-06-21 10:34 ` [RESEND-CI v4 03/15] drm/edid: Complete CEA modedb(VIC 1-107) Shashank Sharma
@ 2017-06-21 13:42   ` Neil Armstrong
  2017-06-27 11:32   ` Ville Syrjälä
  1 sibling, 0 replies; 58+ messages in thread
From: Neil Armstrong @ 2017-06-21 13:42 UTC (permalink / raw)
  To: Shashank Sharma, dri-devel, intel-gfx, ville.syrjala
  Cc: Jose Abreu, Alex Deucher

On 06/21/2017 12:34 PM, Shashank Sharma wrote:
> CEA-861-F specs defines new video modes to be used with
> HDMI 2.0 EDIDs. The VIC range has been extended from 1-64 to
> 1-107.
> 
> Our existing CEA modedb contains only 64 modes (VIC=1 to VIC=64). Now
> to be able to parse new CEA modes using the existing methods, we have
> to complete the modedb (VIC=65 onwards).
> 
> This patch adds:
> - Timings for existing CEA video modes (from VIC=65 till VIC=92)
> - Newly added 4k modes (from VIC=93 to VIC=107).
> 
> The patch was originaly discussed and reviewed here:
> https://patchwork.freedesktop.org/patch/135810/
> 
> Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
> Cc: Jose Abreu <Jose.Abreu@synopsys.com>
> Cc: Andrzej Hajda <a.hajda@samsung.com>
> Cc: Alex Deucher <alexander.deucher@amd.com>
> Cc: Harry Wentland <harry.wentland@amd.com>
> 
> V2: Rebase
> V3: Rebase
> V4: Added native bit handling as per CEA-861-F spec (Ville)
> 
> Reviewed-by: Jose Abreu <Jose.Abreu@synopsys.com>
> Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
> Acked-by: Harry Wentland <harry.wentland@amd.com>
> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
> ---
>  drivers/gpu/drm/drm_edid.c | 227 ++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 226 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index d312fe1..e2d1b30 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -1006,6 +1006,221 @@ static const struct drm_display_mode edid_cea_modes[] = {
>  		   2492, 2640, 0, 1080, 1084, 1089, 1125, 0,
>  		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
>  	 .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
> +	/* 65 - 1280x720@24Hz */
> +	{ DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 59400, 1280, 3040,
> +		   3080, 3300, 0, 720, 725, 730, 750, 0,
> +		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	  .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
> +	/* 66 - 1280x720@25Hz */
> +	{ DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 3700,
> +		   3740, 3960, 0, 720, 725, 730, 750, 0,
> +		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	  .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
> +	/* 67 - 1280x720@30Hz */
> +	{ DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 3040,
> +		   3080, 3300, 0, 720, 725, 730, 750, 0,
> +		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	  .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
> +	/* 68 - 1280x720@50Hz */
> +	{ DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 1720,
> +		   1760, 1980, 0, 720, 725, 730, 750, 0,
> +		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	  .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
> +	/* 69 - 1280x720@60Hz */
> +	{ DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 1390,
> +		   1430, 1650, 0, 720, 725, 730, 750, 0,
> +		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	  .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
> +	/* 70 - 1280x720@100Hz */
> +	{ DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 148500, 1280, 1720,
> +		   1760, 1980, 0, 720, 725, 730, 750, 0,
> +		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	  .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
> +	/* 71 - 1280x720@120Hz */
> +	{ DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 148500, 1280, 1390,
> +		   1430, 1650, 0, 720, 725, 730, 750, 0,
> +		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	  .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
> +	/* 72 - 1920x1080@24Hz */
> +	{ DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2558,
> +		   2602, 2750, 0, 1080, 1084, 1089, 1125, 0,
> +		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	  .vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
> +	/* 73 - 1920x1080@25Hz */
> +	{ DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2448,
> +		   2492, 2640, 0, 1080, 1084, 1089, 1125, 0,
> +		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	  .vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
> +	/* 74 - 1920x1080@30Hz */
> +	{ DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2008,
> +		   2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
> +		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	  .vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
> +	/* 75 - 1920x1080@50Hz */
> +	{ DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2448,
> +		   2492, 2640, 0, 1080, 1084, 1089, 1125, 0,
> +		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	  .vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
> +	/* 76 - 1920x1080@60Hz */
> +	{ DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2008,
> +		   2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
> +		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	  .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
> +	/* 77 - 1920x1080@100Hz */
> +	{ DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 297000, 1920, 2448,
> +		   2492, 2640, 0, 1080, 1084, 1094, 1125, 0,
> +		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	 .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
> +	/* 78 - 1920x1080@120Hz */
> +	{ DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 297000, 1920, 2008,
> +		   2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
> +		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	 .vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
> +	/* 79 - 1680x720@24Hz */
> +	{ DRM_MODE("1680x720", DRM_MODE_TYPE_DRIVER, 59400, 1680, 3040,
> +		3080, 3300, 0, 720, 725, 730, 750, 0,
> +		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	.vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
> +	/* 80 - 1680x720@25Hz */
> +	{ DRM_MODE("1680x720", DRM_MODE_TYPE_DRIVER, 59400, 1680, 2908,
> +		2948, 3168, 0, 720, 725, 730, 750, 0,
> +		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	.vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
> +	/* 81 - 1680x720@30Hz */
> +	{ DRM_MODE("1680x720", DRM_MODE_TYPE_DRIVER, 59400, 1680, 2380,
> +		2420, 2640, 0, 720, 725, 730, 750, 0,
> +		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	.vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
> +	/* 82 - 1680x720@50Hz */
> +	{ DRM_MODE("1680x720", DRM_MODE_TYPE_DRIVER, 82500, 1680, 1940,
> +		1980, 2200, 0, 720, 725, 730, 750, 0,
> +		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	.vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
> +	/* 83 - 1680x720@60Hz */
> +	{ DRM_MODE("1680x720", DRM_MODE_TYPE_DRIVER, 99000, 1680, 1940,
> +		1980, 2200, 0, 720, 725, 730, 750, 0,
> +		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	.vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
> +	/* 84 - 1680x720@100Hz */
> +	{ DRM_MODE("1680x720", DRM_MODE_TYPE_DRIVER, 165000, 1680, 1740,
> +		1780, 2000, 0, 720, 725, 730, 825, 0,
> +		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	.vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
> +	/* 85 - 1680x720@120Hz */
> +	{ DRM_MODE("1680x720", DRM_MODE_TYPE_DRIVER, 198000, 1680, 1740,
> +		1780, 2000, 0, 720, 725, 730, 825, 0,
> +		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	.vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
> +	/* 86 - 2560x1080@24Hz */
> +	{ DRM_MODE("2560x1080", DRM_MODE_TYPE_DRIVER, 99000, 2560, 3558,
> +		3602, 3750, 0, 1080, 1084, 1089, 1100, 0,
> +		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	.vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
> +	/* 87 - 2560x1080@25Hz */
> +	{ DRM_MODE("2560x1080", DRM_MODE_TYPE_DRIVER, 90000, 2560, 3008,
> +		3052, 3200, 0, 1080, 1084, 1089, 1125, 0,
> +		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	.vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
> +	/* 88 - 2560x1080@30Hz */
> +	{ DRM_MODE("2560x1080", DRM_MODE_TYPE_DRIVER, 118800, 2560, 3328,
> +		3372, 3520, 0, 1080, 1084, 1089, 1125, 0,
> +		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	.vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
> +	/* 89 - 2560x1080@50Hz */
> +	{ DRM_MODE("2560x1080", DRM_MODE_TYPE_DRIVER, 185625, 2560, 3108,
> +		3152, 3300, 0, 1080, 1084, 1089, 1125, 0,
> +		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	.vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
> +	/* 90 - 2560x1080@60Hz */
> +	{ DRM_MODE("2560x1080", DRM_MODE_TYPE_DRIVER, 198000, 2560, 2808,
> +		2852, 3000, 0, 1080, 1084, 1089, 1100, 0,
> +		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	.vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
> +	/* 91 - 2560x1080@100Hz */
> +	{ DRM_MODE("2560x1080", DRM_MODE_TYPE_DRIVER, 371250, 2560, 2778,
> +		2822, 2970, 0, 1080, 1084, 1089, 1250, 0,
> +		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	.vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
> +	/* 92 - 2560x1080@120Hz */
> +	{ DRM_MODE("2560x1080", DRM_MODE_TYPE_DRIVER, 495000, 2560, 3108,
> +		3152, 3300, 0, 1080, 1084, 1089, 1250, 0,
> +		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	.vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
> +	/* 93 - 3840x2160p@24Hz 16:9 */
> +	{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 5116,
> +		5204, 5500, 0, 2160, 2168, 2178, 2250, 0,
> +		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	.vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9,},
> +	/* 94 - 3840x2160p@25Hz 16:9 */
> +	{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 4896,
> +		4984, 5280, 0, 2160, 2168, 2178, 2250, 0,
> +		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	.vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9},
> +	/* 95 - 3840x2160p@30Hz 16:9 */
> +	{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 4016,
> +		4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
> +		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	.vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9},
> +	/* 96 - 3840x2160p@50Hz 16:9 */
> +	{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 4896,
> +		4984, 5280, 0, 2160, 2168, 2178, 2250, 0,
> +		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	.vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9},
> +	/* 97 - 3840x2160p@60Hz 16:9 */
> +	{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 4016,
> +		4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
> +		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	.vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9},
> +	/* 98 - 4096x2160p@24Hz 256:135 */
> +	{ DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 297000, 4096, 5116,
> +		5204, 5500, 0, 2160, 2168, 2178, 2250, 0,
> +		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	.vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135},
> +	/* 99 - 4096x2160p@25Hz 256:135 */
> +	{ DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 297000, 4096, 5064,
> +		5152, 5280, 0, 2160, 2168, 2178, 2250, 0,
> +		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	.vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135},
> +	/* 100 - 4096x2160p@30Hz 256:135 */
> +	{ DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 297000, 4096, 4184,
> +		4272, 4400, 0, 2160, 2168, 2178, 2250, 0,
> +		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	.vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135},
> +	/* 101 - 4096x2160p@50Hz 256:135 */
> +	{ DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 594000, 4096, 5064,
> +		5152, 5280, 0, 2160, 2168, 2178, 2250, 0,
> +		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	.vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135},
> +	/* 102 - 4096x2160p@60Hz 256:135 */
> +	{ DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 594000, 4096, 4184,
> +		4272, 4400, 0, 2160, 2168, 2178, 2250, 0,
> +		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	.vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135},
> +	/* 103 - 3840x2160p@24Hz 64:27 */
> +	{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 5116,
> +		5204, 5500, 0, 2160, 2168, 2178, 2250, 0,
> +		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	.vrefresh = 24, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27},
> +	/* 104 - 3840x2160p@25Hz 64:27 */
> +	{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 4016,
> +		4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
> +		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	.vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27},
> +	/* 105 - 3840x2160p@30Hz 64:27 */
> +	{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 4016,
> +		4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
> +		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	.vrefresh = 30, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27},
> +	/* 106 - 3840x2160p@50Hz 64:27 */
> +	{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 4896,
> +		4984, 5280, 0, 2160, 2168, 2178, 2250, 0,
> +		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	.vrefresh = 50, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27},
> +	/* 107 - 3840x2160p@60Hz 64:27 */
> +	{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 4016,
> +		4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
> +		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	.vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27},
>  };
>  
>  /*
> @@ -2902,6 +3117,16 @@ add_alternate_cea_modes(struct drm_connector *connector, struct edid *edid)
>  	return modes;
>  }
>  
> +static u8 svd_to_vic(u8 svd)
> +{
> +
> +	/* 0-6 bit vic, 7th bit native mode indicator */
> +	if (((svd >= 1) && (svd <= 64)) || ((svd >= 129) && (svd <= 192)))
> +		return svd & 127;
> +
> +	return svd;
> +}
> +
>  static struct drm_display_mode *
>  drm_display_mode_from_vic_index(struct drm_connector *connector,
>  				const u8 *video_db, u8 video_len,
> @@ -2915,7 +3140,7 @@ drm_display_mode_from_vic_index(struct drm_connector *connector,
>  		return NULL;
>  
>  	/* CEA modes are numbered 1..127 */
> -	vic = (video_db[video_index] & 127);
> +	vic = svd_to_vic(video_db[video_index]);
>  	if (!drm_valid_cea_vic(vic))
>  		return NULL;
>  
> 

Reviewed-by: Neil Armstrong <narmstrong@baylibre.com>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [Intel-gfx] [RESEND-CI v4 09/15] drm: add helper functions for YCBCR output handling
  2017-06-21 10:34 ` [RESEND-CI v4 09/15] drm: add helper functions for YCBCR output handling Shashank Sharma
@ 2017-06-22  7:05   ` Daniel Vetter
  2017-06-22  9:42     ` Sharma, Shashank
  0 siblings, 1 reply; 58+ messages in thread
From: Daniel Vetter @ 2017-06-22  7:05 UTC (permalink / raw)
  To: Shashank Sharma; +Cc: Jose Abreu, intel-gfx, dri-devel

On Wed, Jun 21, 2017 at 04:04:06PM +0530, Shashank Sharma wrote:
> This patch adds set of helper functions for YCBCR HDMI output
> handling. These functions provide functionality like:
> - check if a given video mode is YCBCR 420 only mode.
> - check if a given video mode is YCBCR 420 mode.
> - get the highest subsamled ycbcr output.
> - get the lowest subsamled ycbcr output.
> - check if a given source and sink combination can support any
>   YCBCR HDMI output.
> - check if a given source and sink combination can support a particular
>   YCBCR HDMI output.
> 
> Currently all these helpers are kept static, and only one wrapper function
> is exposed to callers, which is "drm_find_hdmi_output_type". This function
> takes inputs as current mode, user preference and src + sink capabilities,
> and provides the most suitable HDMI output format to match all of these
> inputs.
> 
> This wrapper function will be used in next few patches in this
> series from I915 driver.
> 
> V2: Added YCBCR functions as helpers in DRM layer, instead of
>     keeping it in I915 layer.
> V3: Added handling for YCBCR-420 only modes too.
> V4: EXPORT_SYMBOL(drm_find_hdmi_output_type)
> 
> Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
> Cc: Jose Abreu <Jose.Abreu@synopsys.com>
> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>

Not sure why you mark the series as RESEND-CI when not everything is
reviewed yet. Anyway, stumbled over this, some comments below.

> ---
>  drivers/gpu/drm/drm_edid.c  |   2 +-
>  drivers/gpu/drm/drm_modes.c | 307 ++++++++++++++++++++++++++++++++++++++++++++
>  include/drm/drm_edid.h      |   1 +
>  include/drm/drm_modes.h     |   5 +
>  4 files changed, 314 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index edba190..2f8810a 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -2949,7 +2949,7 @@ u8 drm_match_cea_mode(const struct drm_display_mode *to_match)
>  }
>  EXPORT_SYMBOL(drm_match_cea_mode);
>  
> -static bool drm_valid_cea_vic(u8 vic)
> +bool drm_valid_cea_vic(u8 vic)
>  {
>  	return vic > 0 && vic < ARRAY_SIZE(edid_cea_modes);
>  }
> diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
> index f2493b9..09e6b10 100644
> --- a/drivers/gpu/drm/drm_modes.c
> +++ b/drivers/gpu/drm/drm_modes.c
> @@ -1576,3 +1576,310 @@ int drm_mode_convert_umode(struct drm_display_mode *out,
>  out:
>  	return ret;
>  }
> +
> +/**
> + * drm_mode_is_420_only - if a given videomode can be only supported in YCBCR420
> + * output format
> + *
> + * @connector: drm connector under action.
> + * @mode: video mode to be tested.
> + *
> + * Returns:
> + * true if the mode can support YCBCR420 output
> + * false if not.
> + */

For static functions we generally don't ever document them using
kernel-doc. And within the drm core generally only the functions exported
to driver (i.e. relevant for driver authors) are fully documented.
Especially for such small helpers, if you need docs the function name
isn't descriptive enough. I'd remove them all (except the one kerneldoc
for the exported function).

On function naming itself, the usual pattern is

object_prefix_verb_stuff

In your case here all the helpers check against limits in
drm_display_info, so I'd go with

drm_display_info_is_420_only|also_mode
drm_display_supports_ycbcr_mode
drm_display_supports_ycbcr
(can_support is a bit tedious, supports is shorter)

Those are all bikesheds, but for the main exported function I think it
matters. I'll discuss that below.


> +static bool drm_mode_is_420_only(struct drm_display_info *display,
> +			struct drm_display_mode *mode)
> +{
> +	u8 vic = drm_match_cea_mode(mode);
> +
> +	/*
> +	 * Requirements of a 420_only mode:
> +	 * must be a valid cea mode
> +	 * entry in 420_only bitmap
> +	 */
> +	if (!drm_valid_cea_vic(vic))
> +		return false;
> +
> +	return test_bit(vic, display->hdmi.y420_vdb_modes);
> +}
> +
> +/**
> + * drm_mode_is_420_also - if a given videomode can be supported in YCBCR420
> + * output format also (along with RGB/YCBCR444/422)
> + *
> + * @display: display under action.
> + * @mode: video mode to be tested.
> + *
> + * Returns:
> + * true if the mode can support YCBCR420 output
> + * false if not.
> + */
> +static bool drm_mode_is_420_also(struct drm_display_info *display,
> +			struct drm_display_mode *mode)
> +{
> +	u8 vic = drm_match_cea_mode(mode);
> +
> +	/*
> +	 * Requirements of a 420_also mode:
> +	 * must be a valid cea mode
> +	 * entry in 420_also bitmap
> +	 */
> +	if (!drm_valid_cea_vic(vic))
> +		return false;
> +
> +	return test_bit(vic, display->hdmi.y420_cmdb_modes);
> +}
> +
> +
> +static bool drm_mode_is_420(struct drm_display_info *display,
> +			struct drm_display_mode *mode)
> +{
> +	return drm_mode_is_420_only(display, mode) ||
> +			drm_mode_is_420_also(display, mode);
> +}
> +
> +/**
> + * drm_can_support_this_ycbcr_output - can a given source and sink combination
> + * support a particular YCBCR output type.
> + *
> + * @display: sink information.
> + * @mode: video mode from modeset
> + * @type: enum indicating YCBCR output type
> + * @source_outputs: bitmap of source supported HDMI output formats.
> + *
> + * Returns:
> + * true on success.
> + * false on failure.
> + */
> +static bool drm_can_support_this_ycbcr_output(struct drm_display_info *display,
> +					struct drm_display_mode *mode,
> +					enum drm_hdmi_output_type type,
> +					u32 source_outputs)
> +{
> +	/* YCBCR420 output support can be per mode basis */
> +	if (type == DRM_HDMI_OUTPUT_YCBCR420 &&
> +		!drm_mode_is_420(display, mode))
> +		return false;
> +
> +	return display->color_formats & source_outputs & type;
> +}
> +
> +/**
> + * drm_can_support_ycbcr_output - can a given source and sink combination
> + * support any YCBCR outputs ?
> + *
> + * @display: sink information.
> + * @source_outputs: bitmap of source supported HDMI output formats.
> + *
> + * Returns:
> + * true on success.
> + * false on failure.
> + */
> +static bool drm_can_support_ycbcr_output(struct drm_display_info *display,
> +					u32 source_outputs)
> +{
> +	u32 supported_formats;
> +
> +	if (!source_outputs || !display->color_formats) {
> +		DRM_DEBUG_KMS("Source/Sink doesn't support any output ?\n");
> +		return DRM_HDMI_OUTPUT_INVALID;
> +	}
> +
> +	/* Get the common supported fromats between source and sink */
> +	supported_formats = display->color_formats & source_outputs;
> +	if (!supported_formats || (supported_formats ==
> +		DRM_COLOR_FORMAT_RGB444)) {
> +		DRM_ERROR("No common YCBCR formats between source and sink\n");
> +		return false;
> +	}
> +
> +	DRM_DEBUG_KMS("Src and Sink combination can support YCBCR output\n");
> +	return true;
> +}
> +
> +/**
> + * drm_get_highest_quality_ycbcr_supported - get the ycbcr output mode
> + * with highest subsampling rate
> + * @display: struct drm_display_info from current connector
> + * @mode: video mode from modeset
> + * @source_output_map: bitmap of supported HDMI output modes from source
> + *
> + * Finds the best possible ycbcr output mode (based on subsampling), for the
> + * given source and sink combination.
> + *
> + * Returns:
> + * enum corresponding to best output mode on success.
> + * DRM_HDMI_OUTPUT_INVALID on failure.
> + */
> +static enum drm_hdmi_output_type
> +drm_get_highest_quality_ycbcr_supported(struct drm_display_info *display,
> +					struct drm_display_mode *mode,
> +					u32 source_output_map)
> +{
> +	enum drm_hdmi_output_type output = DRM_HDMI_OUTPUT_INVALID;
> +	u32 supported_formats = source_output_map & display->color_formats;
> +
> +	/*
> +	 * Get the ycbcr output with the highest possible subsampling rate.
> +	 * Preference should go as:
> +	 * ycbcr 444
> +	 * ycbcr 422
> +	 * ycbcr 420
> +	 */
> +	if (supported_formats & DRM_COLOR_FORMAT_YCRCB444)
> +		output = DRM_COLOR_FORMAT_YCRCB444;
> +	else if (supported_formats & DRM_COLOR_FORMAT_YCRCB422)
> +		output = DRM_COLOR_FORMAT_YCRCB422;
> +	else if (supported_formats & DRM_COLOR_FORMAT_YCRCB420 &&
> +			drm_mode_is_420(display, mode))
> +		output = DRM_COLOR_FORMAT_YCRCB420;
> +
> +	DRM_DEBUG_KMS("Highest subsampled YCBCR mode supported is %s\n",
> +			drm_get_hdmi_output_name(supported_formats));
> +	return output;
> +}
> +
> +/**
> + * drm_get_lowest_quality_ycbcr_supported - get the ycbcr output mode
> + * with lowest subsampling rate
> + * @display: struct drm_display_info from current connector
> + * @mode: video mode from modeset
> + * @source_output_map: bitmap of supported HDMI output modes from source
> + *
> + * Finds the lowest possible ycbcr output mode (based on subsampling), for the
> + * given source and sink combination.
> + *
> + * Returns:
> + * enum corresponding to best output mode on success.
> + * DRM_HDMI_OUTPUT_INVALID on failure.
> + */
> +static enum drm_hdmi_output_type
> +drm_get_lowest_quality_ycbcr_supported(struct drm_display_info *display,
> +					struct drm_display_mode *mode,
> +					u32 source_output_map)
> +{
> +	enum drm_hdmi_output_type output = DRM_HDMI_OUTPUT_INVALID;
> +	u32 supported_formats = source_output_map & display->color_formats;
> +
> +	/*
> +	 * Get the ycbcr output with the lowest possible subsampling rate.
> +	 * Preference should go as:
> +	 * ycbcr 420
> +	 * ycbcr 422
> +	 * ycbcr 444
> +	 */
> +	if (supported_formats & DRM_COLOR_FORMAT_YCRCB420 &&
> +		drm_mode_is_420(display, mode))
> +		output = DRM_HDMI_OUTPUT_YCBCR420;
> +	else if (display->color_formats & DRM_COLOR_FORMAT_YCRCB422)
> +		output = DRM_HDMI_OUTPUT_YCBCR422;
> +	else if (display->color_formats & DRM_COLOR_FORMAT_YCRCB444)
> +		output = DRM_HDMI_OUTPUT_YCBCR420;
> +
> +	DRM_DEBUG_KMS("Lowest subsampled YCBCR mode supported is %s\n",
> +			drm_get_hdmi_output_name(supported_formats));
> +	return output;
> +}
> +
> +/**
> + * drm_find_hdmi_output_type - get the most suitable output
> + * Find the best suitable HDMI output considering source capability,
> + * sink capability and user's choice (expressed in form of drm property)
> + *
> + * @connector: drm connector in action
> + * @mode: video mode under modeset
> + * @type: user's choice for preferred mode, set via drm property
> + *	"hdmi_output_format"
> + * @src_output_cap: bitmap of source's supported outputs formats
> + *	src_output_cap = (1 << DRM_COLOR_FORMAT_RGB444) means source
> + *	supports RGB444
> + *	src_output_cap = (1 << DRM_COLOR_FORMAT_YCRCB444) means source
> + *	supports YUV444, and so on.

You should explain in 1-2 sentences what exactly this function does, and
when a driver should use it. Just documenting the input/output stuff
doesn't make the kerneldoc all that useful.

> + *
> + * Returns:
> + * enum corresponding to best suitable output type on success.
> + * DRM_HDMI_OUTPUT_INVALID on failure.
> + */
> +enum drm_hdmi_output_type
> +drm_find_hdmi_output_type(struct drm_connector *connector,
> +				struct drm_display_mode *mode,
> +				enum drm_hdmi_output_type type,
> +				u32 src_output_cap)
> +{
> +	bool ret;
> +	struct drm_display_info *info = &connector->display_info;

Imo you should pass the display_info, not connector, to this function. For
consistency. I'm also not sure we should place this in here, since
drm_display_info is in drm_connector.h (but maybe that's just misplaced
and perhaps we should move it to drm_modes.h). I wouldn't bother with
moving it, but we definitely need a consistent prefix for exported
functiosn. Since drm_display_info_set_bus_formats() already exists, I
think the interface here should be:


enum drm_hdmi_output_type
drm_display_info_hdmi_output_type(struct drm_display_info *display_info,
				  struct drm_display_mode *mode,
				  enum drm_hdmi_output_type type,
				  u32 src_output_cap)

You can also drop the _find_ (sometimes we also call it compute e.g. in i915
modeset code), since computing stuff is implied.

Cheers, Daniel


> +	bool mode_is_420_only = drm_mode_is_420_only(info, mode);
> +
> +	/*
> +	 * If the preferred output is not set to YCBCR by user, and the mode
> +	 * doesn't force us to drive YCBCR420 output, respect the user
> +	 * preference for the output type. But if the mode is 420_only, we will
> +	 * be force to drive YCBCR420 output.
> +	 */
> +	if (!mode_is_420_only) {
> +		if (type == DRM_HDMI_OUTPUT_DEFAULT_RGB)
> +			return DRM_HDMI_OUTPUT_DEFAULT_RGB;
> +	} else {
> +		type = DRM_HDMI_OUTPUT_YCBCR420;
> +		DRM_DEBUG_KMS("Got a 420 only mode(%s)\n", mode->name);
> +	}
> +
> +	/* If  this src + sink combination can support any YCBCR output */
> +	ret = drm_can_support_ycbcr_output(info, src_output_cap);
> +	if (!ret) {
> +		DRM_ERROR("No supported YCBCR output\n");
> +		return DRM_HDMI_OUTPUT_INVALID;
> +	}
> +
> +	switch (type) {
> +	case DRM_HDMI_OUTPUT_YCBCR_HQ:
> +		type = drm_get_highest_quality_ycbcr_supported(info, mode,
> +								src_output_cap);
> +		break;
> +
> +	case DRM_HDMI_OUTPUT_YCBCR_LQ:
> +		type = drm_get_lowest_quality_ycbcr_supported(info, mode,
> +								src_output_cap);
> +		break;
> +
> +	case DRM_HDMI_OUTPUT_YCBCR420:
> +		ret = drm_mode_is_420(info, mode);
> +		if (!ret) {
> +			DRM_ERROR("Mode %s doesn't support 420 output\n",
> +				   mode->name);
> +			type = DRM_HDMI_OUTPUT_INVALID;
> +		}
> +
> +		break;
> +
> +	/* Below cases are just to satisfy checkpatch's AI */
> +	case DRM_HDMI_OUTPUT_DEFAULT_RGB:
> +	case DRM_HDMI_OUTPUT_YCBCR444:
> +	case DRM_HDMI_OUTPUT_YCBCR422:
> +		break;
> +
> +	default:
> +		type = DRM_HDMI_OUTPUT_INVALID;
> +	}
> +
> +	if (type == DRM_HDMI_OUTPUT_INVALID) {
> +		DRM_ERROR("Can't support mode %s in YCBCR format\n",
> +				mode->name);
> +		return DRM_HDMI_OUTPUT_INVALID;
> +	}
> +
> +	/* Test if this src/sink/mode combination can support selected output */
> +	ret = drm_can_support_this_ycbcr_output(info, mode, type,
> +						src_output_cap);
> +	if (!ret) {
> +		DRM_ERROR("Output %s can't be supported\n",
> +					drm_get_hdmi_output_name(type));
> +		return DRM_HDMI_OUTPUT_INVALID;
> +	}
> +
> +	DRM_DEBUG_KMS("Best supported output is: %s\n",
> +			drm_get_hdmi_output_name(type));
> +	return type;
> +}
> +EXPORT_SYMBOL(drm_find_hdmi_output_type);
> diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
> index 3ea833f..483f668 100644
> --- a/include/drm/drm_edid.h
> +++ b/include/drm/drm_edid.h
> @@ -468,6 +468,7 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid);
>  
>  u8 drm_match_cea_mode(const struct drm_display_mode *to_match);
>  enum hdmi_picture_aspect drm_get_cea_aspect_ratio(const u8 video_code);
> +bool drm_valid_cea_vic(u8 vic);
>  bool drm_detect_hdmi_monitor(struct edid *edid);
>  bool drm_detect_monitor_audio(struct edid *edid);
>  bool drm_rgb_quant_range_selectable(struct edid *edid);
> diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h
> index 94ac771..3c237e1 100644
> --- a/include/drm/drm_modes.h
> +++ b/include/drm/drm_modes.h
> @@ -451,6 +451,11 @@ int drm_mode_convert_umode(struct drm_display_mode *out,
>  void drm_mode_probed_add(struct drm_connector *connector, struct drm_display_mode *mode);
>  void drm_mode_debug_printmodeline(const struct drm_display_mode *mode);
>  
> +enum drm_hdmi_output_type
> +drm_find_hdmi_output_type(struct drm_connector *connector,
> +			  struct drm_display_mode *mode,
> +			  enum drm_hdmi_output_type type,
> +			  u32 src_output_cap);
>  struct drm_display_mode *drm_cvt_mode(struct drm_device *dev,
>  				      int hdisplay, int vdisplay, int vrefresh,
>  				      bool reduced, bool interlaced,
> -- 
> 2.7.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [Intel-gfx] [PATCH v5 7/7] drm: create hdmi output property
  2017-06-21 10:34 ` [PATCH v5 7/7] drm: create hdmi output property Shashank Sharma
@ 2017-06-22  7:14   ` Daniel Vetter
  2017-06-22  8:33     ` Sharma, Shashank
  2017-06-27 12:14   ` Ville Syrjälä
  1 sibling, 1 reply; 58+ messages in thread
From: Daniel Vetter @ 2017-06-22  7:14 UTC (permalink / raw)
  To: Shashank Sharma; +Cc: Daniel Vetter, intel-gfx, Jose Abreu, dri-devel

On Wed, Jun 21, 2017 at 04:04:13PM +0530, Shashank Sharma wrote:
> HDMI displays can support various output types, based on
> the color space and subsampling type. The possible
> outputs from a HDMI 2.0 monitor could be:
>  - RGB
>  - YCBCR 444
>  - YCBCR 422
>  - YCBCR 420
> 
> This patch adds a drm property "hdmi_output_format", using which,
> a user can specify its preference, for the HDMI output type. The
> output type enums are similar to the mentioned outputs above. To
> handle various subsampling of YCBCR output types, this property
> allows two special cases:
>  - DRM_HDMI_OUTPUT_YCBCR_HQ
>    This indicates preferred output should be YCBCR output, with highest
>    subsampling rate by the source/sink, which can be typically:
>  	- ycbcr444
>  	- ycbcr422
>  	- ycbcr420
>  - DRM_HDMI_OUTPUT_YCBCR_LQ
>    This indicates preferred output should be YCBCR output, with lowest
>    subsampling rate supported by source/sink, which can be:
>  	- ycbcr420
>  	- ycbcr422
>  	- ycbcr444
> 
> Default value of the property is set to 0 = RGB, so no changes if you
> dont set the property.
> 
> PS: While doing modeset for YCBCR 420 only modes, this property is
>     ignored, as those timings can be supported only in YCBCR 420
>     output mode.
> 
> V2: Added description for the new variable to address build warning
> V3: Rebase
> V4: Rebase
> V5: Added get_property counterpart to fix IGT BAT failures
> 
> Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
> Cc: Jose Abreu <joabreu@synopsys.com>
> Cc: Daniel Vetter <daniel.vetter@intel.com>
> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>

Two comments on this:

- The kerneldoc for this new property is missing, see
  https://dri.freedesktop.org/docs/drm/gpu/drm-kms.html#kms-properties for
  what that should look like. I think a new section for HDMI properties
  might be good. For the text itself just take your commit message and
  make sure it formats correctly when building the kernel documentation.

- Putting a HDMI-specific property into the set of standard properties
  feels rather wrong, we already have functions to e.g. create tv or dvi-i
  properties. I think it'd be much better to maybe have a function to
  create all the HDMI properties. I'd would be really lovely if we could
  document the other HDMI properties like broadcast mode while at it too.

- The property values should be limited to what the driver can support, I
  guess that would mean limiting the available ycbcr modes? Or does all
  our hw support all the modes, including 420 (on the sink side)?

Thanks, Daniel
> ---
>  drivers/gpu/drm/drm_atomic.c        |  4 ++++
>  drivers/gpu/drm/drm_atomic_helper.c |  4 ++++
>  drivers/gpu/drm/drm_connector.c     | 32 ++++++++++++++++++++++++++++++++
>  include/drm/drm_connector.h         | 18 ++++++++++++++++++
>  include/drm/drm_mode_config.h       |  5 +++++
>  5 files changed, 63 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
> index 77dcef0..ea90f8e 100644
> --- a/drivers/gpu/drm/drm_atomic.c
> +++ b/drivers/gpu/drm/drm_atomic.c
> @@ -1192,6 +1192,8 @@ int drm_atomic_connector_set_property(struct drm_connector *connector,
>  		state->picture_aspect_ratio = val;
>  	} else if (property == connector->scaling_mode_property) {
>  		state->scaling_mode = val;
> +	} else if (property == config->hdmi_output_property) {
> +		state->hdmi_output = val;
>  	} else if (connector->funcs->atomic_set_property) {
>  		return connector->funcs->atomic_set_property(connector,
>  				state, property, val);
> @@ -1272,6 +1274,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector,
>  		*val = state->picture_aspect_ratio;
>  	} else if (property == connector->scaling_mode_property) {
>  		*val = state->scaling_mode;
> +	} else if (property == config->hdmi_output_property) {
> +		*val = state->hdmi_output;
>  	} else if (connector->funcs->atomic_get_property) {
>  		return connector->funcs->atomic_get_property(connector,
>  				state, property, val);
> diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
> index 86d3093..1356b3f 100644
> --- a/drivers/gpu/drm/drm_atomic_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_helper.c
> @@ -637,6 +637,10 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
>  			if (old_connector_state->link_status !=
>  			    new_connector_state->link_status)
>  				new_crtc_state->connectors_changed = true;
> +
> +			if (old_connector_state->hdmi_output !=
> +			    new_connector_state->hdmi_output)
> +				new_crtc_state->connectors_changed = true;
>  		}
>  
>  		if (funcs->atomic_check)
> diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
> index 5cd61af..f3c5928 100644
> --- a/drivers/gpu/drm/drm_connector.c
> +++ b/drivers/gpu/drm/drm_connector.c
> @@ -227,6 +227,11 @@ int drm_connector_init(struct drm_device *dev,
>  					      config->edid_property,
>  					      0);
>  
> +	if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL)
> +		drm_object_attach_property(&connector->base,
> +					   config->hdmi_output_property,
> +					   0);
> +
>  	drm_object_attach_property(&connector->base,
>  				      config->dpms_property, 0);
>  
> @@ -617,6 +622,26 @@ static const struct drm_prop_enum_list drm_link_status_enum_list[] = {
>  };
>  DRM_ENUM_NAME_FN(drm_get_link_status_name, drm_link_status_enum_list)
>  
> +static const struct drm_prop_enum_list drm_hdmi_output_enum_list[] = {
> +	{ DRM_HDMI_OUTPUT_DEFAULT_RGB, "output_rgb" },
> +	{ DRM_HDMI_OUTPUT_YCBCR444, "output_ycbcr444" },
> +	{ DRM_HDMI_OUTPUT_YCBCR422, "output_ycbcr422" },
> +	{ DRM_HDMI_OUTPUT_YCBCR420, "output_ycbcr420" },
> +	{ DRM_HDMI_OUTPUT_YCBCR_HQ, "output_ycbcr_high_subsampling" },
> +	{ DRM_HDMI_OUTPUT_YCBCR_LQ, "output_ycbcr_low_subsampling" },
> +	{ DRM_HDMI_OUTPUT_INVALID, "invalid_output" },
> +};
> +
> +/**
> + * drm_get_hdmi_output_name - return a string for a given hdmi output enum
> + * @type: enum of output type
> + */
> +const char *drm_get_hdmi_output_name(enum drm_hdmi_output_type type)
> +{
> +	return drm_hdmi_output_enum_list[type].name;
> +}
> +EXPORT_SYMBOL(drm_get_hdmi_output_name);
> +
>  /**
>   * drm_display_info_set_bus_formats - set the supported bus formats
>   * @info: display info to store bus formats in
> @@ -789,6 +814,13 @@ int drm_connector_create_standard_properties(struct drm_device *dev)
>  		return -ENOMEM;
>  	dev->mode_config.link_status_property = prop;
>  
> +	prop = drm_property_create_enum(dev, 0, "hdmi_output_format",
> +					drm_hdmi_output_enum_list,
> +					ARRAY_SIZE(drm_hdmi_output_enum_list));
> +	if (!prop)
> +		return -ENOMEM;
> +	dev->mode_config.hdmi_output_property = prop;
> +
>  	return 0;
>  }
>  
> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> index 1305fe9..5ba1f32 100644
> --- a/include/drm/drm_connector.h
> +++ b/include/drm/drm_connector.h
> @@ -321,6 +321,17 @@ struct drm_tv_connector_state {
>  	unsigned int hue;
>  };
>  
> +/* HDMI output pixel format */
> +enum drm_hdmi_output_type {
> +	DRM_HDMI_OUTPUT_DEFAULT_RGB, /* default RGB */
> +	DRM_HDMI_OUTPUT_YCBCR444, /* YCBCR 444 */
> +	DRM_HDMI_OUTPUT_YCBCR422, /* YCBCR 422 */
> +	DRM_HDMI_OUTPUT_YCBCR420, /* YCBCR 420 */
> +	DRM_HDMI_OUTPUT_YCBCR_HQ, /* Highest subsampled YUV */
> +	DRM_HDMI_OUTPUT_YCBCR_LQ, /* Lowest subsampled YUV */
> +	DRM_HDMI_OUTPUT_INVALID, /* Guess what ? */
> +};
> +
>  /**
>   * struct drm_connector_state - mutable connector state
>   * @connector: backpointer to the connector
> @@ -365,6 +376,12 @@ struct drm_connector_state {
>  	 * upscaling, mostly used for built-in panels.
>  	 */
>  	unsigned int scaling_mode;
> +
> +	/**
> +	 * @hdmi_output: Connector property to control the
> +	 * HDMI output mode (RGB/YCBCR444/422/420).
> +	 */
> +	enum drm_hdmi_output_type hdmi_output;
>  };
>  
>  /**
> @@ -993,6 +1010,7 @@ static inline void drm_connector_unreference(struct drm_connector *connector)
>  
>  const char *drm_get_connector_status_name(enum drm_connector_status status);
>  const char *drm_get_subpixel_order_name(enum subpixel_order order);
> +const char *drm_get_hdmi_output_name(enum drm_hdmi_output_type type);
>  const char *drm_get_dpms_name(int val);
>  const char *drm_get_dvi_i_subconnector_name(int val);
>  const char *drm_get_dvi_i_select_name(int val);
> diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h
> index 4298171..1887261 100644
> --- a/include/drm/drm_mode_config.h
> +++ b/include/drm/drm_mode_config.h
> @@ -740,6 +740,11 @@ struct drm_mode_config {
>  	 * the position of the output on the host's screen.
>  	 */
>  	struct drm_property *suggested_y_property;
> +	/**
> +	 * @hdmi_output_property: output pixel format from HDMI display
> +	 * Default is set for RGB
> +	 */
> +	struct drm_property *hdmi_output_property;
>  
>  	/* dumb ioctl parameters */
>  	uint32_t preferred_depth, prefer_shadow;
> -- 
> 2.7.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v5 7/7] drm: create hdmi output property
  2017-06-22  7:14   ` [Intel-gfx] " Daniel Vetter
@ 2017-06-22  8:33     ` Sharma, Shashank
  2017-06-23  9:20       ` [Intel-gfx] " Daniel Vetter
  0 siblings, 1 reply; 58+ messages in thread
From: Sharma, Shashank @ 2017-06-22  8:33 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Daniel Vetter, intel-gfx, Jose Abreu, dri-devel

Thanks for the review, Daniel.

My comments inline.

Regards
Shashank
On 6/22/2017 12:44 PM, Daniel Vetter wrote:
> On Wed, Jun 21, 2017 at 04:04:13PM +0530, Shashank Sharma wrote:
>> HDMI displays can support various output types, based on
>> the color space and subsampling type. The possible
>> outputs from a HDMI 2.0 monitor could be:
>>   - RGB
>>   - YCBCR 444
>>   - YCBCR 422
>>   - YCBCR 420
>>
>> This patch adds a drm property "hdmi_output_format", using which,
>> a user can specify its preference, for the HDMI output type. The
>> output type enums are similar to the mentioned outputs above. To
>> handle various subsampling of YCBCR output types, this property
>> allows two special cases:
>>   - DRM_HDMI_OUTPUT_YCBCR_HQ
>>     This indicates preferred output should be YCBCR output, with highest
>>     subsampling rate by the source/sink, which can be typically:
>>   	- ycbcr444
>>   	- ycbcr422
>>   	- ycbcr420
>>   - DRM_HDMI_OUTPUT_YCBCR_LQ
>>     This indicates preferred output should be YCBCR output, with lowest
>>     subsampling rate supported by source/sink, which can be:
>>   	- ycbcr420
>>   	- ycbcr422
>>   	- ycbcr444
>>
>> Default value of the property is set to 0 = RGB, so no changes if you
>> dont set the property.
>>
>> PS: While doing modeset for YCBCR 420 only modes, this property is
>>      ignored, as those timings can be supported only in YCBCR 420
>>      output mode.
>>
>> V2: Added description for the new variable to address build warning
>> V3: Rebase
>> V4: Rebase
>> V5: Added get_property counterpart to fix IGT BAT failures
>>
>> Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
>> Cc: Jose Abreu <joabreu@synopsys.com>
>> Cc: Daniel Vetter <daniel.vetter@intel.com>
>> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
> Two comments on this:
>
> - The kerneldoc for this new property is missing, see
>    https://dri.freedesktop.org/docs/drm/gpu/drm-kms.html#kms-properties for
>    what that should look like. I think a new section for HDMI properties
>    might be good. For the text itself just take your commit message and
>    make sure it formats correctly when building the kernel documentation.
Thanks for pointing this out, I will add the doc.
> - Putting a HDMI-specific property into the set of standard properties
>    feels rather wrong, we already have functions to e.g. create tv or dvi-i
>    properties. I think it'd be much better to maybe have a function to
>    create all the HDMI properties. I'd would be really lovely if we could
>    document the other HDMI properties like broadcast mode while at it too.
Sure, let see see what can I do here.
> - The property values should be limited to what the driver can support, I
>    guess that would mean limiting the available ycbcr modes? Or does all
>    our hw support all the modes, including 420 (on the sink side)?
This property is targeted at DRM layer, so naturally its for all the HWs 
along with Intel HW, so it serves a big range.
All our HDMI 1.4 sources support RGB444, and after this series, can 
support YCBCR444.
All HDMI 2.0 sources should support YCBCR420, but they can declare this 
using a bool variable which I added in patch 3 (ycbcr420_allowed)
As we are targeting both HDMI 1.4 as well as HDMI 2.0 (Src and Sink), as 
a whole we are covering all options.

- Shashank
> Thanks, Daniel
>> ---
>>   drivers/gpu/drm/drm_atomic.c        |  4 ++++
>>   drivers/gpu/drm/drm_atomic_helper.c |  4 ++++
>>   drivers/gpu/drm/drm_connector.c     | 32 ++++++++++++++++++++++++++++++++
>>   include/drm/drm_connector.h         | 18 ++++++++++++++++++
>>   include/drm/drm_mode_config.h       |  5 +++++
>>   5 files changed, 63 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
>> index 77dcef0..ea90f8e 100644
>> --- a/drivers/gpu/drm/drm_atomic.c
>> +++ b/drivers/gpu/drm/drm_atomic.c
>> @@ -1192,6 +1192,8 @@ int drm_atomic_connector_set_property(struct drm_connector *connector,
>>   		state->picture_aspect_ratio = val;
>>   	} else if (property == connector->scaling_mode_property) {
>>   		state->scaling_mode = val;
>> +	} else if (property == config->hdmi_output_property) {
>> +		state->hdmi_output = val;
>>   	} else if (connector->funcs->atomic_set_property) {
>>   		return connector->funcs->atomic_set_property(connector,
>>   				state, property, val);
>> @@ -1272,6 +1274,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector,
>>   		*val = state->picture_aspect_ratio;
>>   	} else if (property == connector->scaling_mode_property) {
>>   		*val = state->scaling_mode;
>> +	} else if (property == config->hdmi_output_property) {
>> +		*val = state->hdmi_output;
>>   	} else if (connector->funcs->atomic_get_property) {
>>   		return connector->funcs->atomic_get_property(connector,
>>   				state, property, val);
>> diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
>> index 86d3093..1356b3f 100644
>> --- a/drivers/gpu/drm/drm_atomic_helper.c
>> +++ b/drivers/gpu/drm/drm_atomic_helper.c
>> @@ -637,6 +637,10 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
>>   			if (old_connector_state->link_status !=
>>   			    new_connector_state->link_status)
>>   				new_crtc_state->connectors_changed = true;
>> +
>> +			if (old_connector_state->hdmi_output !=
>> +			    new_connector_state->hdmi_output)
>> +				new_crtc_state->connectors_changed = true;
>>   		}
>>   
>>   		if (funcs->atomic_check)
>> diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
>> index 5cd61af..f3c5928 100644
>> --- a/drivers/gpu/drm/drm_connector.c
>> +++ b/drivers/gpu/drm/drm_connector.c
>> @@ -227,6 +227,11 @@ int drm_connector_init(struct drm_device *dev,
>>   					      config->edid_property,
>>   					      0);
>>   
>> +	if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL)
>> +		drm_object_attach_property(&connector->base,
>> +					   config->hdmi_output_property,
>> +					   0);
>> +
>>   	drm_object_attach_property(&connector->base,
>>   				      config->dpms_property, 0);
>>   
>> @@ -617,6 +622,26 @@ static const struct drm_prop_enum_list drm_link_status_enum_list[] = {
>>   };
>>   DRM_ENUM_NAME_FN(drm_get_link_status_name, drm_link_status_enum_list)
>>   
>> +static const struct drm_prop_enum_list drm_hdmi_output_enum_list[] = {
>> +	{ DRM_HDMI_OUTPUT_DEFAULT_RGB, "output_rgb" },
>> +	{ DRM_HDMI_OUTPUT_YCBCR444, "output_ycbcr444" },
>> +	{ DRM_HDMI_OUTPUT_YCBCR422, "output_ycbcr422" },
>> +	{ DRM_HDMI_OUTPUT_YCBCR420, "output_ycbcr420" },
>> +	{ DRM_HDMI_OUTPUT_YCBCR_HQ, "output_ycbcr_high_subsampling" },
>> +	{ DRM_HDMI_OUTPUT_YCBCR_LQ, "output_ycbcr_low_subsampling" },
>> +	{ DRM_HDMI_OUTPUT_INVALID, "invalid_output" },
>> +};
>> +
>> +/**
>> + * drm_get_hdmi_output_name - return a string for a given hdmi output enum
>> + * @type: enum of output type
>> + */
>> +const char *drm_get_hdmi_output_name(enum drm_hdmi_output_type type)
>> +{
>> +	return drm_hdmi_output_enum_list[type].name;
>> +}
>> +EXPORT_SYMBOL(drm_get_hdmi_output_name);
>> +
>>   /**
>>    * drm_display_info_set_bus_formats - set the supported bus formats
>>    * @info: display info to store bus formats in
>> @@ -789,6 +814,13 @@ int drm_connector_create_standard_properties(struct drm_device *dev)
>>   		return -ENOMEM;
>>   	dev->mode_config.link_status_property = prop;
>>   
>> +	prop = drm_property_create_enum(dev, 0, "hdmi_output_format",
>> +					drm_hdmi_output_enum_list,
>> +					ARRAY_SIZE(drm_hdmi_output_enum_list));
>> +	if (!prop)
>> +		return -ENOMEM;
>> +	dev->mode_config.hdmi_output_property = prop;
>> +
>>   	return 0;
>>   }
>>   
>> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
>> index 1305fe9..5ba1f32 100644
>> --- a/include/drm/drm_connector.h
>> +++ b/include/drm/drm_connector.h
>> @@ -321,6 +321,17 @@ struct drm_tv_connector_state {
>>   	unsigned int hue;
>>   };
>>   
>> +/* HDMI output pixel format */
>> +enum drm_hdmi_output_type {
>> +	DRM_HDMI_OUTPUT_DEFAULT_RGB, /* default RGB */
>> +	DRM_HDMI_OUTPUT_YCBCR444, /* YCBCR 444 */
>> +	DRM_HDMI_OUTPUT_YCBCR422, /* YCBCR 422 */
>> +	DRM_HDMI_OUTPUT_YCBCR420, /* YCBCR 420 */
>> +	DRM_HDMI_OUTPUT_YCBCR_HQ, /* Highest subsampled YUV */
>> +	DRM_HDMI_OUTPUT_YCBCR_LQ, /* Lowest subsampled YUV */
>> +	DRM_HDMI_OUTPUT_INVALID, /* Guess what ? */
>> +};
>> +
>>   /**
>>    * struct drm_connector_state - mutable connector state
>>    * @connector: backpointer to the connector
>> @@ -365,6 +376,12 @@ struct drm_connector_state {
>>   	 * upscaling, mostly used for built-in panels.
>>   	 */
>>   	unsigned int scaling_mode;
>> +
>> +	/**
>> +	 * @hdmi_output: Connector property to control the
>> +	 * HDMI output mode (RGB/YCBCR444/422/420).
>> +	 */
>> +	enum drm_hdmi_output_type hdmi_output;
>>   };
>>   
>>   /**
>> @@ -993,6 +1010,7 @@ static inline void drm_connector_unreference(struct drm_connector *connector)
>>   
>>   const char *drm_get_connector_status_name(enum drm_connector_status status);
>>   const char *drm_get_subpixel_order_name(enum subpixel_order order);
>> +const char *drm_get_hdmi_output_name(enum drm_hdmi_output_type type);
>>   const char *drm_get_dpms_name(int val);
>>   const char *drm_get_dvi_i_subconnector_name(int val);
>>   const char *drm_get_dvi_i_select_name(int val);
>> diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h
>> index 4298171..1887261 100644
>> --- a/include/drm/drm_mode_config.h
>> +++ b/include/drm/drm_mode_config.h
>> @@ -740,6 +740,11 @@ struct drm_mode_config {
>>   	 * the position of the output on the host's screen.
>>   	 */
>>   	struct drm_property *suggested_y_property;
>> +	/**
>> +	 * @hdmi_output_property: output pixel format from HDMI display
>> +	 * Default is set for RGB
>> +	 */
>> +	struct drm_property *hdmi_output_property;
>>   
>>   	/* dumb ioctl parameters */
>>   	uint32_t preferred_depth, prefer_shadow;
>> -- 
>> 2.7.4
>>
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx@lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [Intel-gfx] [RESEND-CI v4 09/15] drm: add helper functions for YCBCR output handling
  2017-06-22  7:05   ` [Intel-gfx] " Daniel Vetter
@ 2017-06-22  9:42     ` Sharma, Shashank
  2017-06-23  9:12       ` Daniel Vetter
  0 siblings, 1 reply; 58+ messages in thread
From: Sharma, Shashank @ 2017-06-22  9:42 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Jose Abreu, intel-gfx, dri-devel

Regards

Shashank


On 6/22/2017 12:35 PM, Daniel Vetter wrote:
> On Wed, Jun 21, 2017 at 04:04:06PM +0530, Shashank Sharma wrote:
>> This patch adds set of helper functions for YCBCR HDMI output
>> handling. These functions provide functionality like:
>> - check if a given video mode is YCBCR 420 only mode.
>> - check if a given video mode is YCBCR 420 mode.
>> - get the highest subsamled ycbcr output.
>> - get the lowest subsamled ycbcr output.
>> - check if a given source and sink combination can support any
>>    YCBCR HDMI output.
>> - check if a given source and sink combination can support a particular
>>    YCBCR HDMI output.
>>
>> Currently all these helpers are kept static, and only one wrapper function
>> is exposed to callers, which is "drm_find_hdmi_output_type". This function
>> takes inputs as current mode, user preference and src + sink capabilities,
>> and provides the most suitable HDMI output format to match all of these
>> inputs.
>>
>> This wrapper function will be used in next few patches in this
>> series from I915 driver.
>>
>> V2: Added YCBCR functions as helpers in DRM layer, instead of
>>      keeping it in I915 layer.
>> V3: Added handling for YCBCR-420 only modes too.
>> V4: EXPORT_SYMBOL(drm_find_hdmi_output_type)
>>
>> Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
>> Cc: Jose Abreu <Jose.Abreu@synopsys.com>
>> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
> Not sure why you mark the series as RESEND-CI when not everything is
> reviewed yet. Anyway, stumbled over this, some comments below.
The previous patch set caused some failures on BAT, spoke to Jani S and 
Tomi, and we decided to send another patch set with fix, but added this 
tag, so that reviewers should not get confuse.
But doesn't look like it worked smoothly :-)
>> ---
>>   drivers/gpu/drm/drm_edid.c  |   2 +-
>>   drivers/gpu/drm/drm_modes.c | 307 ++++++++++++++++++++++++++++++++++++++++++++
>>   include/drm/drm_edid.h      |   1 +
>>   include/drm/drm_modes.h     |   5 +
>>   4 files changed, 314 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
>> index edba190..2f8810a 100644
>> --- a/drivers/gpu/drm/drm_edid.c
>> +++ b/drivers/gpu/drm/drm_edid.c
>> @@ -2949,7 +2949,7 @@ u8 drm_match_cea_mode(const struct drm_display_mode *to_match)
>>   }
>>   EXPORT_SYMBOL(drm_match_cea_mode);
>>   
>> -static bool drm_valid_cea_vic(u8 vic)
>> +bool drm_valid_cea_vic(u8 vic)
>>   {
>>   	return vic > 0 && vic < ARRAY_SIZE(edid_cea_modes);
>>   }
>> diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
>> index f2493b9..09e6b10 100644
>> --- a/drivers/gpu/drm/drm_modes.c
>> +++ b/drivers/gpu/drm/drm_modes.c
>> @@ -1576,3 +1576,310 @@ int drm_mode_convert_umode(struct drm_display_mode *out,
>>   out:
>>   	return ret;
>>   }
>> +
>> +/**
>> + * drm_mode_is_420_only - if a given videomode can be only supported in YCBCR420
>> + * output format
>> + *
>> + * @connector: drm connector under action.
>> + * @mode: video mode to be tested.
>> + *
>> + * Returns:
>> + * true if the mode can support YCBCR420 output
>> + * false if not.
>> + */
> For static functions we generally don't ever document them using
> kernel-doc. And within the drm core generally only the functions exported
> to driver (i.e. relevant for driver authors) are fully documented.
> Especially for such small helpers, if you need docs the function name
> isn't descriptive enough. I'd remove them all (except the one kerneldoc
> for the exported function).
Two reasons:
- These are absolutely new functions and reviewers might want to 
understand design and usages well.
- I am expecting these functions get used directly from few drivers 
soon, and be non-static soon.

In any case, is there anything called 'harm with more doc' .. ? I have 
always heard other way around :-)
> On function naming itself, the usual pattern is
>
> object_prefix_verb_stuff
>
> In your case here all the helpers check against limits in
> drm_display_info, so I'd go with
>
> drm_display_info_is_420_only|also_mode
> drm_display_supports_ycbcr_mode
> drm_display_supports_ycbcr
> (can_support is a bit tedious, supports is shorter)
>
> Those are all bikesheds, but for the main exported function I think it
> matters. I'll discuss that below.
Why not, makes sense ...
>
>
>> +static bool drm_mode_is_420_only(struct drm_display_info *display,
>> +			struct drm_display_mode *mode)
>> +{
>> +	u8 vic = drm_match_cea_mode(mode);
>> +
>> +	/*
>> +	 * Requirements of a 420_only mode:
>> +	 * must be a valid cea mode
>> +	 * entry in 420_only bitmap
>> +	 */
>> +	if (!drm_valid_cea_vic(vic))
>> +		return false;
>> +
>> +	return test_bit(vic, display->hdmi.y420_vdb_modes);
>> +}
>> +
>> +/**
>> + * drm_mode_is_420_also - if a given videomode can be supported in YCBCR420
>> + * output format also (along with RGB/YCBCR444/422)
>> + *
>> + * @display: display under action.
>> + * @mode: video mode to be tested.
>> + *
>> + * Returns:
>> + * true if the mode can support YCBCR420 output
>> + * false if not.
>> + */
>> +static bool drm_mode_is_420_also(struct drm_display_info *display,
>> +			struct drm_display_mode *mode)
>> +{
>> +	u8 vic = drm_match_cea_mode(mode);
>> +
>> +	/*
>> +	 * Requirements of a 420_also mode:
>> +	 * must be a valid cea mode
>> +	 * entry in 420_also bitmap
>> +	 */
>> +	if (!drm_valid_cea_vic(vic))
>> +		return false;
>> +
>> +	return test_bit(vic, display->hdmi.y420_cmdb_modes);
>> +}
>> +
>> +
>> +static bool drm_mode_is_420(struct drm_display_info *display,
>> +			struct drm_display_mode *mode)
>> +{
>> +	return drm_mode_is_420_only(display, mode) ||
>> +			drm_mode_is_420_also(display, mode);
>> +}
>> +
>> +/**
>> + * drm_can_support_this_ycbcr_output - can a given source and sink combination
>> + * support a particular YCBCR output type.
>> + *
>> + * @display: sink information.
>> + * @mode: video mode from modeset
>> + * @type: enum indicating YCBCR output type
>> + * @source_outputs: bitmap of source supported HDMI output formats.
>> + *
>> + * Returns:
>> + * true on success.
>> + * false on failure.
>> + */
>> +static bool drm_can_support_this_ycbcr_output(struct drm_display_info *display,
>> +					struct drm_display_mode *mode,
>> +					enum drm_hdmi_output_type type,
>> +					u32 source_outputs)
>> +{
>> +	/* YCBCR420 output support can be per mode basis */
>> +	if (type == DRM_HDMI_OUTPUT_YCBCR420 &&
>> +		!drm_mode_is_420(display, mode))
>> +		return false;
>> +
>> +	return display->color_formats & source_outputs & type;
>> +}
>> +
>> +/**
>> + * drm_can_support_ycbcr_output - can a given source and sink combination
>> + * support any YCBCR outputs ?
>> + *
>> + * @display: sink information.
>> + * @source_outputs: bitmap of source supported HDMI output formats.
>> + *
>> + * Returns:
>> + * true on success.
>> + * false on failure.
>> + */
>> +static bool drm_can_support_ycbcr_output(struct drm_display_info *display,
>> +					u32 source_outputs)
>> +{
>> +	u32 supported_formats;
>> +
>> +	if (!source_outputs || !display->color_formats) {
>> +		DRM_DEBUG_KMS("Source/Sink doesn't support any output ?\n");
>> +		return DRM_HDMI_OUTPUT_INVALID;
>> +	}
>> +
>> +	/* Get the common supported fromats between source and sink */
>> +	supported_formats = display->color_formats & source_outputs;
>> +	if (!supported_formats || (supported_formats ==
>> +		DRM_COLOR_FORMAT_RGB444)) {
>> +		DRM_ERROR("No common YCBCR formats between source and sink\n");
>> +		return false;
>> +	}
>> +
>> +	DRM_DEBUG_KMS("Src and Sink combination can support YCBCR output\n");
>> +	return true;
>> +}
>> +
>> +/**
>> + * drm_get_highest_quality_ycbcr_supported - get the ycbcr output mode
>> + * with highest subsampling rate
>> + * @display: struct drm_display_info from current connector
>> + * @mode: video mode from modeset
>> + * @source_output_map: bitmap of supported HDMI output modes from source
>> + *
>> + * Finds the best possible ycbcr output mode (based on subsampling), for the
>> + * given source and sink combination.
>> + *
>> + * Returns:
>> + * enum corresponding to best output mode on success.
>> + * DRM_HDMI_OUTPUT_INVALID on failure.
>> + */
>> +static enum drm_hdmi_output_type
>> +drm_get_highest_quality_ycbcr_supported(struct drm_display_info *display,
>> +					struct drm_display_mode *mode,
>> +					u32 source_output_map)
>> +{
>> +	enum drm_hdmi_output_type output = DRM_HDMI_OUTPUT_INVALID;
>> +	u32 supported_formats = source_output_map & display->color_formats;
>> +
>> +	/*
>> +	 * Get the ycbcr output with the highest possible subsampling rate.
>> +	 * Preference should go as:
>> +	 * ycbcr 444
>> +	 * ycbcr 422
>> +	 * ycbcr 420
>> +	 */
>> +	if (supported_formats & DRM_COLOR_FORMAT_YCRCB444)
>> +		output = DRM_COLOR_FORMAT_YCRCB444;
>> +	else if (supported_formats & DRM_COLOR_FORMAT_YCRCB422)
>> +		output = DRM_COLOR_FORMAT_YCRCB422;
>> +	else if (supported_formats & DRM_COLOR_FORMAT_YCRCB420 &&
>> +			drm_mode_is_420(display, mode))
>> +		output = DRM_COLOR_FORMAT_YCRCB420;
>> +
>> +	DRM_DEBUG_KMS("Highest subsampled YCBCR mode supported is %s\n",
>> +			drm_get_hdmi_output_name(supported_formats));
>> +	return output;
>> +}
>> +
>> +/**
>> + * drm_get_lowest_quality_ycbcr_supported - get the ycbcr output mode
>> + * with lowest subsampling rate
>> + * @display: struct drm_display_info from current connector
>> + * @mode: video mode from modeset
>> + * @source_output_map: bitmap of supported HDMI output modes from source
>> + *
>> + * Finds the lowest possible ycbcr output mode (based on subsampling), for the
>> + * given source and sink combination.
>> + *
>> + * Returns:
>> + * enum corresponding to best output mode on success.
>> + * DRM_HDMI_OUTPUT_INVALID on failure.
>> + */
>> +static enum drm_hdmi_output_type
>> +drm_get_lowest_quality_ycbcr_supported(struct drm_display_info *display,
>> +					struct drm_display_mode *mode,
>> +					u32 source_output_map)
>> +{
>> +	enum drm_hdmi_output_type output = DRM_HDMI_OUTPUT_INVALID;
>> +	u32 supported_formats = source_output_map & display->color_formats;
>> +
>> +	/*
>> +	 * Get the ycbcr output with the lowest possible subsampling rate.
>> +	 * Preference should go as:
>> +	 * ycbcr 420
>> +	 * ycbcr 422
>> +	 * ycbcr 444
>> +	 */
>> +	if (supported_formats & DRM_COLOR_FORMAT_YCRCB420 &&
>> +		drm_mode_is_420(display, mode))
>> +		output = DRM_HDMI_OUTPUT_YCBCR420;
>> +	else if (display->color_formats & DRM_COLOR_FORMAT_YCRCB422)
>> +		output = DRM_HDMI_OUTPUT_YCBCR422;
>> +	else if (display->color_formats & DRM_COLOR_FORMAT_YCRCB444)
>> +		output = DRM_HDMI_OUTPUT_YCBCR420;
>> +
>> +	DRM_DEBUG_KMS("Lowest subsampled YCBCR mode supported is %s\n",
>> +			drm_get_hdmi_output_name(supported_formats));
>> +	return output;
>> +}
>> +
>> +/**
>> + * drm_find_hdmi_output_type - get the most suitable output
>> + * Find the best suitable HDMI output considering source capability,
>> + * sink capability and user's choice (expressed in form of drm property)
>> + *
>> + * @connector: drm connector in action
>> + * @mode: video mode under modeset
>> + * @type: user's choice for preferred mode, set via drm property
>> + *	"hdmi_output_format"
>> + * @src_output_cap: bitmap of source's supported outputs formats
>> + *	src_output_cap = (1 << DRM_COLOR_FORMAT_RGB444) means source
>> + *	supports RGB444
>> + *	src_output_cap = (1 << DRM_COLOR_FORMAT_YCRCB444) means source
>> + *	supports YUV444, and so on.
> You should explain in 1-2 sentences what exactly this function does, and
> when a driver should use it. Just documenting the input/output stuff
> doesn't make the kerneldoc all that useful.
Did you miss the first 3 lines above ?
"get the most suitable output.
Find the best suitable HDMI output considering source capability, sink 
capability and user's choice (expressed in form of drm property)"
Or you mean that's not enough ?
>
>> + *
>> + * Returns:
>> + * enum corresponding to best suitable output type on success.
>> + * DRM_HDMI_OUTPUT_INVALID on failure.
>> + */
>> +enum drm_hdmi_output_type
>> +drm_find_hdmi_output_type(struct drm_connector *connector,
>> +				struct drm_display_mode *mode,
>> +				enum drm_hdmi_output_type type,
>> +				u32 src_output_cap)
>> +{
>> +	bool ret;
>> +	struct drm_display_info *info = &connector->display_info;
> Imo you should pass the display_info, not connector, to this function. For
> consistency.
Sure, can be done.
> I'm also not sure we should place this in here, since
> drm_display_info is in drm_connector.h (but maybe that's just misplaced
> and perhaps we should move it to drm_modes.h). I wouldn't bother with
> moving it, but we definitely need a consistent prefix for exported
> functiosn. Since drm_display_info_set_bus_formats() already exists, I
> think the interface here should be:
>
>
> enum drm_hdmi_output_type
> drm_display_info_hdmi_output_type(struct drm_display_info *display_info,
> 				  struct drm_display_mode *mode,
> 				  enum drm_hdmi_output_type type,
> 				  u32 src_output_cap)
>
> You can also drop the _find_ (sometimes we also call it compute e.g. in i915
> modeset code), since computing stuff is implied.
Sure, I like the compute idea too.
- Shashank
> Cheers, Daniel
>
>
>> +	bool mode_is_420_only = drm_mode_is_420_only(info, mode);
>> +
>> +	/*
>> +	 * If the preferred output is not set to YCBCR by user, and the mode
>> +	 * doesn't force us to drive YCBCR420 output, respect the user
>> +	 * preference for the output type. But if the mode is 420_only, we will
>> +	 * be force to drive YCBCR420 output.
>> +	 */
>> +	if (!mode_is_420_only) {
>> +		if (type == DRM_HDMI_OUTPUT_DEFAULT_RGB)
>> +			return DRM_HDMI_OUTPUT_DEFAULT_RGB;
>> +	} else {
>> +		type = DRM_HDMI_OUTPUT_YCBCR420;
>> +		DRM_DEBUG_KMS("Got a 420 only mode(%s)\n", mode->name);
>> +	}
>> +
>> +	/* If  this src + sink combination can support any YCBCR output */
>> +	ret = drm_can_support_ycbcr_output(info, src_output_cap);
>> +	if (!ret) {
>> +		DRM_ERROR("No supported YCBCR output\n");
>> +		return DRM_HDMI_OUTPUT_INVALID;
>> +	}
>> +
>> +	switch (type) {
>> +	case DRM_HDMI_OUTPUT_YCBCR_HQ:
>> +		type = drm_get_highest_quality_ycbcr_supported(info, mode,
>> +								src_output_cap);
>> +		break;
>> +
>> +	case DRM_HDMI_OUTPUT_YCBCR_LQ:
>> +		type = drm_get_lowest_quality_ycbcr_supported(info, mode,
>> +								src_output_cap);
>> +		break;
>> +
>> +	case DRM_HDMI_OUTPUT_YCBCR420:
>> +		ret = drm_mode_is_420(info, mode);
>> +		if (!ret) {
>> +			DRM_ERROR("Mode %s doesn't support 420 output\n",
>> +				   mode->name);
>> +			type = DRM_HDMI_OUTPUT_INVALID;
>> +		}
>> +
>> +		break;
>> +
>> +	/* Below cases are just to satisfy checkpatch's AI */
>> +	case DRM_HDMI_OUTPUT_DEFAULT_RGB:
>> +	case DRM_HDMI_OUTPUT_YCBCR444:
>> +	case DRM_HDMI_OUTPUT_YCBCR422:
>> +		break;
>> +
>> +	default:
>> +		type = DRM_HDMI_OUTPUT_INVALID;
>> +	}
>> +
>> +	if (type == DRM_HDMI_OUTPUT_INVALID) {
>> +		DRM_ERROR("Can't support mode %s in YCBCR format\n",
>> +				mode->name);
>> +		return DRM_HDMI_OUTPUT_INVALID;
>> +	}
>> +
>> +	/* Test if this src/sink/mode combination can support selected output */
>> +	ret = drm_can_support_this_ycbcr_output(info, mode, type,
>> +						src_output_cap);
>> +	if (!ret) {
>> +		DRM_ERROR("Output %s can't be supported\n",
>> +					drm_get_hdmi_output_name(type));
>> +		return DRM_HDMI_OUTPUT_INVALID;
>> +	}
>> +
>> +	DRM_DEBUG_KMS("Best supported output is: %s\n",
>> +			drm_get_hdmi_output_name(type));
>> +	return type;
>> +}
>> +EXPORT_SYMBOL(drm_find_hdmi_output_type);
>> diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
>> index 3ea833f..483f668 100644
>> --- a/include/drm/drm_edid.h
>> +++ b/include/drm/drm_edid.h
>> @@ -468,6 +468,7 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid);
>>   
>>   u8 drm_match_cea_mode(const struct drm_display_mode *to_match);
>>   enum hdmi_picture_aspect drm_get_cea_aspect_ratio(const u8 video_code);
>> +bool drm_valid_cea_vic(u8 vic);
>>   bool drm_detect_hdmi_monitor(struct edid *edid);
>>   bool drm_detect_monitor_audio(struct edid *edid);
>>   bool drm_rgb_quant_range_selectable(struct edid *edid);
>> diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h
>> index 94ac771..3c237e1 100644
>> --- a/include/drm/drm_modes.h
>> +++ b/include/drm/drm_modes.h
>> @@ -451,6 +451,11 @@ int drm_mode_convert_umode(struct drm_display_mode *out,
>>   void drm_mode_probed_add(struct drm_connector *connector, struct drm_display_mode *mode);
>>   void drm_mode_debug_printmodeline(const struct drm_display_mode *mode);
>>   
>> +enum drm_hdmi_output_type
>> +drm_find_hdmi_output_type(struct drm_connector *connector,
>> +			  struct drm_display_mode *mode,
>> +			  enum drm_hdmi_output_type type,
>> +			  u32 src_output_cap);
>>   struct drm_display_mode *drm_cvt_mode(struct drm_device *dev,
>>   				      int hdisplay, int vdisplay, int vrefresh,
>>   				      bool reduced, bool interlaced,
>> -- 
>> 2.7.4
>>
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx@lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/intel-gfx

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [RESEND-CI v4 09/15] drm: add helper functions for YCBCR output handling
  2017-06-22  9:42     ` Sharma, Shashank
@ 2017-06-23  9:12       ` Daniel Vetter
  2017-06-23 10:01         ` [Intel-gfx] " Sharma, Shashank
  0 siblings, 1 reply; 58+ messages in thread
From: Daniel Vetter @ 2017-06-23  9:12 UTC (permalink / raw)
  To: Sharma, Shashank; +Cc: Jose Abreu, intel-gfx, dri-devel

On Thu, Jun 22, 2017 at 11:42 AM, Sharma, Shashank
<shashank.sharma@intel.com> wrote:
>> You should explain in 1-2 sentences what exactly this function does, and
>> when a driver should use it. Just documenting the input/output stuff
>> doesn't make the kerneldoc all that useful.
>
> Did you miss the first 3 lines above ?
> "get the most suitable output.
> Find the best suitable HDMI output considering source capability, sink
> capability and user's choice (expressed in form of drm property)"
> Or you mean that's not enough ?

Indeed. Usually I sort the paramaters first, then the text. There
should also be an empty line before the text starts. Would be great if
you can do that since you'll respin anyway.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [Intel-gfx] [PATCH v5 7/7] drm: create hdmi output property
  2017-06-22  8:33     ` Sharma, Shashank
@ 2017-06-23  9:20       ` Daniel Vetter
  2017-06-23 10:05         ` Sharma, Shashank
  0 siblings, 1 reply; 58+ messages in thread
From: Daniel Vetter @ 2017-06-23  9:20 UTC (permalink / raw)
  To: Sharma, Shashank; +Cc: Daniel Vetter, intel-gfx, Jose Abreu, dri-devel

On Thu, Jun 22, 2017 at 10:33 AM, Sharma, Shashank
<shashank.sharma@intel.com> wrote:
>> - The property values should be limited to what the driver can support, I
>>    guess that would mean limiting the available ycbcr modes? Or does all
>>    our hw support all the modes, including 420 (on the sink side)?
>
> This property is targeted at DRM layer, so naturally its for all the HWs
> along with Intel HW, so it serves a big range.
> All our HDMI 1.4 sources support RGB444, and after this series, can support
> YCBCR444.
> All HDMI 2.0 sources should support YCBCR420, but they can declare this
> using a bool variable which I added in patch 3 (ycbcr420_allowed)
> As we are targeting both HDMI 1.4 as well as HDMI 2.0 (Src and Sink), as a
> whole we are covering all options.

Yes, we need to define values for everything, since it's a generic
property. But for a given driver imo we should only allow the values
that are actually supported. An example would be the rotation
property, which supporsts X/Y-mirror and rotation by 90° steps. But on
a given i915 platform we only register support for the stuff the
driver/hw can do, e.g. pre-gen9 do not register 90/270° rotation. I
think we should do the same here. See
drm_plane_create_rotation_property(), specifically the
supported_rotations parameter.

Cheers, Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [Intel-gfx] [RESEND-CI v4 09/15] drm: add helper functions for YCBCR output handling
  2017-06-23  9:12       ` Daniel Vetter
@ 2017-06-23 10:01         ` Sharma, Shashank
  0 siblings, 0 replies; 58+ messages in thread
From: Sharma, Shashank @ 2017-06-23 10:01 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Jose Abreu, intel-gfx, dri-devel

Regards

Shashank


On 6/23/2017 2:42 PM, Daniel Vetter wrote:
> On Thu, Jun 22, 2017 at 11:42 AM, Sharma, Shashank
> <shashank.sharma@intel.com> wrote:
>>> You should explain in 1-2 sentences what exactly this function does, and
>>> when a driver should use it. Just documenting the input/output stuff
>>> doesn't make the kerneldoc all that useful.
>> Did you miss the first 3 lines above ?
>> "get the most suitable output.
>> Find the best suitable HDMI output considering source capability, sink
>> capability and user's choice (expressed in form of drm property)"
>> Or you mean that's not enough ?
> Indeed. Usually I sort the paramaters first, then the text. There
> should also be an empty line before the text starts. Would be great if
> you can do that since you'll respin anyway.
Sure, not a problem.
- Shashank
> -Daniel

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [Intel-gfx] [PATCH v5 7/7] drm: create hdmi output property
  2017-06-23  9:20       ` [Intel-gfx] " Daniel Vetter
@ 2017-06-23 10:05         ` Sharma, Shashank
  2017-06-23 10:28           ` Daniel Vetter
  0 siblings, 1 reply; 58+ messages in thread
From: Sharma, Shashank @ 2017-06-23 10:05 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Daniel Vetter, intel-gfx, Jose Abreu, dri-devel

Regards

Shashank


On 6/23/2017 2:50 PM, Daniel Vetter wrote:
> On Thu, Jun 22, 2017 at 10:33 AM, Sharma, Shashank
> <shashank.sharma@intel.com> wrote:
>>> - The property values should be limited to what the driver can support, I
>>>     guess that would mean limiting the available ycbcr modes? Or does all
>>>     our hw support all the modes, including 420 (on the sink side)?
>> This property is targeted at DRM layer, so naturally its for all the HWs
>> along with Intel HW, so it serves a big range.
>> All our HDMI 1.4 sources support RGB444, and after this series, can support
>> YCBCR444.
>> All HDMI 2.0 sources should support YCBCR420, but they can declare this
>> using a bool variable which I added in patch 3 (ycbcr420_allowed)
>> As we are targeting both HDMI 1.4 as well as HDMI 2.0 (Src and Sink), as a
>> whole we are covering all options.
> Yes, we need to define values for everything, since it's a generic
> property. But for a given driver imo we should only allow the values
> that are actually supported. An example would be the rotation
> property, which supporsts X/Y-mirror and rotation by 90° steps. But on
> a given i915 platform we only register support for the stuff the
> driver/hw can do, e.g. pre-gen9 do not register 90/270° rotation. I
> think we should do the same here. See
> drm_plane_create_rotation_property(), specifically the
> supported_rotations parameter.
Ah, I got your point now, and its valid.
If you see the I915 level handlers of YCBCR functions (added in patch 
10) they are taking care of blocking
anything which is not supported by driver for this platform, based on:
- The source capability
- The sink capability
- User preference of the property.
So on a whole, set of Intel platforms cover all the values of property, 
but at driver level we make sure to allow only what is suitable for this 
source + sink combination.
- Shashank
>
> Cheers, Daniel

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [Intel-gfx] [PATCH v5 7/7] drm: create hdmi output property
  2017-06-23 10:05         ` Sharma, Shashank
@ 2017-06-23 10:28           ` Daniel Vetter
  0 siblings, 0 replies; 58+ messages in thread
From: Daniel Vetter @ 2017-06-23 10:28 UTC (permalink / raw)
  To: Sharma, Shashank; +Cc: intel-gfx, dri-devel, Jose Abreu, Daniel Vetter

On Fri, Jun 23, 2017 at 03:35:30PM +0530, Sharma, Shashank wrote:
> Regards
> 
> Shashank
> 
> 
> On 6/23/2017 2:50 PM, Daniel Vetter wrote:
> > On Thu, Jun 22, 2017 at 10:33 AM, Sharma, Shashank
> > <shashank.sharma@intel.com> wrote:
> > > > - The property values should be limited to what the driver can support, I
> > > >     guess that would mean limiting the available ycbcr modes? Or does all
> > > >     our hw support all the modes, including 420 (on the sink side)?
> > > This property is targeted at DRM layer, so naturally its for all the HWs
> > > along with Intel HW, so it serves a big range.
> > > All our HDMI 1.4 sources support RGB444, and after this series, can support
> > > YCBCR444.
> > > All HDMI 2.0 sources should support YCBCR420, but they can declare this
> > > using a bool variable which I added in patch 3 (ycbcr420_allowed)
> > > As we are targeting both HDMI 1.4 as well as HDMI 2.0 (Src and Sink), as a
> > > whole we are covering all options.
> > Yes, we need to define values for everything, since it's a generic
> > property. But for a given driver imo we should only allow the values
> > that are actually supported. An example would be the rotation
> > property, which supporsts X/Y-mirror and rotation by 90° steps. But on
> > a given i915 platform we only register support for the stuff the
> > driver/hw can do, e.g. pre-gen9 do not register 90/270° rotation. I
> > think we should do the same here. See
> > drm_plane_create_rotation_property(), specifically the
> > supported_rotations parameter.
> Ah, I got your point now, and its valid.
> If you see the I915 level handlers of YCBCR functions (added in patch 10)
> they are taking care of blocking
> anything which is not supported by driver for this platform, based on:
> - The source capability
> - The sink capability
> - User preference of the property.

Yeah, runtime checks are needed on top (sometimes at least). But if we
can't support a given mode for a given sink then we should take that into
account when registering the property. Otherwise userspace tries stuff
that can never succeed, which isn't a big problem with the TEST_ONLY
atomic mode, just a bit silly.
-Daniel

> So on a whole, set of Intel platforms cover all the values of property, but
> at driver level we make sure to allow only what is suitable for this source
> + sink combination.
> - Shashank
> > 
> > Cheers, Daniel
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [RESEND-CI v4 03/15] drm/edid: Complete CEA modedb(VIC 1-107)
  2017-06-21 10:34 ` [RESEND-CI v4 03/15] drm/edid: Complete CEA modedb(VIC 1-107) Shashank Sharma
  2017-06-21 13:42   ` Neil Armstrong
@ 2017-06-27 11:32   ` Ville Syrjälä
  2017-06-30  5:11     ` Sharma, Shashank
  1 sibling, 1 reply; 58+ messages in thread
From: Ville Syrjälä @ 2017-06-27 11:32 UTC (permalink / raw)
  To: Shashank Sharma
  Cc: Jose Abreu, intel-gfx, Andrzej Hajda, dri-devel, Alex Deucher,
	Harry Wentland

On Wed, Jun 21, 2017 at 04:04:01PM +0530, Shashank Sharma wrote:
> CEA-861-F specs defines new video modes to be used with
> HDMI 2.0 EDIDs. The VIC range has been extended from 1-64 to
> 1-107.
> 
> Our existing CEA modedb contains only 64 modes (VIC=1 to VIC=64). Now
> to be able to parse new CEA modes using the existing methods, we have
> to complete the modedb (VIC=65 onwards).
> 
> This patch adds:
> - Timings for existing CEA video modes (from VIC=65 till VIC=92)
> - Newly added 4k modes (from VIC=93 to VIC=107).
> 
> The patch was originaly discussed and reviewed here:
> https://patchwork.freedesktop.org/patch/135810/
> 
> Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
> Cc: Jose Abreu <Jose.Abreu@synopsys.com>
> Cc: Andrzej Hajda <a.hajda@samsung.com>
> Cc: Alex Deucher <alexander.deucher@amd.com>
> Cc: Harry Wentland <harry.wentland@amd.com>
> 
> V2: Rebase
> V3: Rebase
> V4: Added native bit handling as per CEA-861-F spec (Ville)
> 
> Reviewed-by: Jose Abreu <Jose.Abreu@synopsys.com>
> Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
> Acked-by: Harry Wentland <harry.wentland@amd.com>
> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
> ---
>  drivers/gpu/drm/drm_edid.c | 227 ++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 226 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index d312fe1..e2d1b30 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -1006,6 +1006,221 @@ static const struct drm_display_mode edid_cea_modes[] = {
>  		   2492, 2640, 0, 1080, 1084, 1089, 1125, 0,
>  		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
>  	 .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
...
> +	/* 77 - 1920x1080@100Hz */
> +	{ DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 297000, 1920, 2448,
> +		   2492, 2640, 0, 1080, 1084, 1094, 1125, 0,
> +		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	 .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
...
> +	/* 104 - 3840x2160p@25Hz 64:27 */
> +	{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 4016,
> +		4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
> +		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
> +	.vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27},

https://lists.freedesktop.org/archives/dri-devel/2016-November/122669.html

> @@ -2902,6 +3117,16 @@ add_alternate_cea_modes(struct drm_connector *connector, struct edid *edid)
>  	return modes;
>  }
>  
> +static u8 svd_to_vic(u8 svd)
> +{
> +
> +	/* 0-6 bit vic, 7th bit native mode indicator */
> +	if (((svd >= 1) && (svd <= 64)) || ((svd >= 129) && (svd <= 192)))

Too many parentheses. lgtm otherwise.

> +		return svd & 127;
> +
> +	return svd;
> +}
> +
>  static struct drm_display_mode *
>  drm_display_mode_from_vic_index(struct drm_connector *connector,
>  				const u8 *video_db, u8 video_len,
> @@ -2915,7 +3140,7 @@ drm_display_mode_from_vic_index(struct drm_connector *connector,
>  		return NULL;
>  
>  	/* CEA modes are numbered 1..127 */
> -	vic = (video_db[video_index] & 127);
> +	vic = svd_to_vic(video_db[video_index]);
>  	if (!drm_valid_cea_vic(vic))
>  		return NULL;
>  
> -- 
> 2.7.4

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [RESEND-CI v4 04/15] drm/edid: parse YCBCR 420 videomodes from EDID
  2017-06-21 10:34 ` [RESEND-CI v4 04/15] drm/edid: parse YCBCR 420 videomodes from EDID Shashank Sharma
@ 2017-06-27 11:52   ` Ville Syrjälä
  2017-06-30  5:17     ` Sharma, Shashank
  0 siblings, 1 reply; 58+ messages in thread
From: Ville Syrjälä @ 2017-06-27 11:52 UTC (permalink / raw)
  To: Shashank Sharma; +Cc: intel-gfx, Jose Abreu, Emil Velikov, dri-devel

On Wed, Jun 21, 2017 at 04:04:02PM +0530, Shashank Sharma wrote:
> HDMI 2.0 spec adds support for YCBCR420 sub-sampled output.
> CEA-861-F adds two new blocks in EDID's CEA extension blocks,
> to provide information about sink's YCBCR420 output capabilities.
> 
> These blocks are:
> 
> - YCBCR420vdb(YCBCR 420 video data block):
> This block contains VICs of video modes, which can be sopported only
> in YCBCR420 output mode (Not in RGB/YCBCR444/422. Its like a normal
> SVD block, valid for YCBCR420 modes only.
> 
> - YCBCR420cmdb(YCBCR 420 capability map data block):
> This block gives information about video modes which can support
> YCBCR420 output mode also (along with RGB,YCBCR444/422 etc) This
> block contains a bitmap index of normal svd videomodes, which can
> support YCBCR420 output too.
> So if bit 0 from first vcb byte is set, first video mode in the svd
> list can support YCBCR420 output too. Bit 1 means second video mode
> from svd list can support YCBCR420 output too, and so on.
> 
> This patch adds two bitmaps in display's hdmi_info structure, one each
> for VCB and VDB modes. If the source is HDMI 2.0 capable, this patch
> adds:
> - VDB modes (YCBCR 420 only modes) in connector's mode list, also makes
>   an entry in the vdb_bitmap per vic.
> - VCB modes (YCBCR 420 also modes) only entry in the vcb_bitmap.
> 
> Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
> Cc: Jose Abreu <joabreu@synopsys.com>
> Cc: Emil Velikov <emil.l.velikov@gmail.com>
> 
> V2: Addressed
>     Review comments from Emil:
>     - Use 1ULL<<i instead of 1<<i to make sure the output is 64bit.
>     - Use the suggested method for updating dbmap.
>     - Add documentation for YCBCR420_vcb_map to fix kbuild warning.
> 
>     Review comments from Ville:
>     - Do not expose the YCBCR420 flags in uabi layer, keep it internal.
>     - Save a map of YCBCR420 modes for future reference.
>     - Check db length before trying to parse extended tag.
>     - Add a warning if there are > 64 modes in capability map block.
>     - Use y420cmdb in function names and macros while dealing with vcb
>       to be aligned with spec.
>     - Move the display information parsing block ahead of mode parsing
>       blocks.
> 
> V3: Addressed design/review comments from Ville
>     - Do not add flags in video modes, else we have to expose them to user
>     - There should not be a UABI change, and kernel should detect the
>       choice of the output based on type of mode, and the bitmaps.
>     - Use standard bitops from kernel bitmap header, instead of calculating
>       bit positions manually.
> 
> V4: Addressed review comments from Ville:
>     - s/ycbcr_420_vdb/y420vdb
>     - s/ycbcr_420_vcb/y420cmdb
>     - Be less verbose on description of do_y420vdb_modes
>     - Move newmode variable in the loop scope.
>     - Use svd_to_vic() to get a VIC, instead of 0x7f
>     - Remove bitmap description for CMDB modes & VDB modes
>     - Dont add connector->ycbcr_420_allowed check for cmdb modes
>     - Remove 'len' variable, in is_y420cmdb function, which is used
>       only once
>     - Add length check in is_y420vdb function
>     - Remove unnecessary if (!db) check in function parse_y420cmdb_bitmap
>     - Do not add print about YCBCR 420 modes
>     - Fix indentation in few places
>     - Move ycbcr420_dc_modes in next patch, where its used
>     - Add a separate patch for movement of drm_add_display_info()
> 
> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
> ---
>  drivers/gpu/drm/drm_edid.c  | 157 +++++++++++++++++++++++++++++++++++++++++++-
>  include/drm/drm_connector.h |  20 ++++++
>  2 files changed, 174 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index e2d1b30..8c7e73b 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -2781,7 +2781,9 @@ add_detailed_modes(struct drm_connector *connector, struct edid *edid,
>  #define VIDEO_BLOCK     0x02
>  #define VENDOR_BLOCK    0x03
>  #define SPEAKER_BLOCK	0x04
> -#define VIDEO_CAPABILITY_BLOCK	0x07
> +#define VIDEO_CAPABILITY_BLOCK 0x07
> +#define VIDEO_DATA_BLOCK_420	0x0E
> +#define VIDEO_CAP_BLOCK_Y420CMDB 0x0F
>  #define EDID_BASIC_AUDIO	(1 << 6)
>  #define EDID_CEA_YCRCB444	(1 << 5)
>  #define EDID_CEA_YCRCB422	(1 << 4)
> @@ -3153,15 +3155,79 @@ drm_display_mode_from_vic_index(struct drm_connector *connector,
>  	return newmode;
>  }
>  
> +/*
> + * do_y420vdb_modes - Parse YCBCR 420 only modes
> + * @connector: connector corresponding to the HDMI sink
> + * @svds: start of the data block of CEA YCBCR 420 VDB
> + * @len: length of the CEA YCBCR 420 VDB
> + *
> + * Parse the CEA-861-F YCBCR 420 Video Data Block (Y420VDB)
> + * which contains modes which can be supported in YCBCR 420
> + * output format only.
> + */
> +static int do_y420vdb_modes(struct drm_connector *connector,
> +				   const u8 *svds, u8 svds_len)
> +{
> +	int modes = 0, i;
> +	struct drm_device *dev = connector->dev;
> +	struct drm_display_info *info = &connector->display_info;
> +	struct drm_hdmi_info *hdmi = &info->hdmi;
> +
> +	for (i = 0; i < svds_len; i++) {
> +		u8 vic = svd_to_vic(svds[i]);
> +		struct drm_display_mode *newmode;
> +
> +		newmode = drm_mode_duplicate(dev, &edid_cea_modes[vic]);
> +		if (!newmode)
> +			break;
> +		bitmap_set(hdmi->y420_vdb_modes, vic, 1);
> +		drm_mode_probed_add(connector, newmode);
> +		modes++;
> +	}
> +
> +	if (modes > 0)
> +		info->color_formats |= DRM_COLOR_FORMAT_YCRCB420;
> +	return modes;
> +}
> +
> +/*
> + * drm_add_cmdb_modes - Add a YCBCR 420 mode into bitmap
> + * @connector: connector corresponding to the HDMI sink
> + * @vic: CEA vic for the video mode to be added in the map
> + *
> + * Makes an entry for a videomode in the YCBCR 420 bitmap
> + */
> +static void
> +drm_add_cmdb_modes(struct drm_connector *connector, u8 svd)
> +{
> +	u8 vic = svd_to_vic(svd);
> +	struct drm_hdmi_info *hdmi = &connector->display_info.hdmi;
> +
> +	bitmap_set(hdmi->y420_cmdb_modes, vic, 1);
> +}
> +
>  static int
>  do_cea_modes(struct drm_connector *connector, const u8 *db, u8 len)
>  {
>  	int i, modes = 0;
> +	struct drm_hdmi_info *hdmi = &connector->display_info.hdmi;
>  
>  	for (i = 0; i < len; i++) {
>  		struct drm_display_mode *mode;
>  		mode = drm_display_mode_from_vic_index(connector, db, len, i);
>  		if (mode) {
> +			/*
> +			 * YCBCR420 capability block contains a bitmap which
> +			 * gives the index of CEA modes from CEA VDB, which
> +			 * can support YCBCR 420 sampling output also (apart
> +			 * from RGB/YCBCR444 etc).
> +			 * For example, if the bit 0 in bitmap is set,
> +			 * first mode in VDB can support YCBCR420 output too.
> +			 * Add YCBCR420 modes only if sink is HDMI 2.0 capable.
> +			 */
> +			if (test_bit(i, &hdmi->y420_cmdb_map))
> +				drm_add_cmdb_modes(connector, db[i]);
> +
>  			drm_mode_probed_add(connector, mode);
>  			modes++;
>  		}
> @@ -3437,6 +3503,12 @@ do_hdmi_vsdb_modes(struct drm_connector *connector, const u8 *db, u8 len,
>  }
>  
>  static int
> +cea_db_extended_tag(const u8 *db)
> +{
> +	return db[1];
> +}
> +
> +static int
>  cea_db_payload_len(const u8 *db)
>  {
>  	return db[0] & 0x1f;
> @@ -3497,9 +3569,78 @@ static bool cea_db_is_hdmi_forum_vsdb(const u8 *db)
>  	return oui == HDMI_FORUM_IEEE_OUI;
>  }
>  
> +static bool cea_db_is_y420cmdb(const u8 *db)
> +{
> +
> +	if (cea_db_tag(db) != VIDEO_CAPABILITY_BLOCK)

Still would like to see that patch to clean up the current extended tag
usage...

> +		return false;
> +
> +	if (!cea_db_payload_len(db))
> +		return false;
> +
> +	if (cea_db_extended_tag(db) != VIDEO_CAP_BLOCK_Y420CMDB)
> +		return false;
> +
> +	return true;
> +}
> +
> +static bool cea_db_is_y420vdb(const u8 *db)
> +{
> +	if (cea_db_tag(db) != VIDEO_CAPABILITY_BLOCK)
> +		return false;
> +
> +	if (!cea_db_payload_len(db))
> +		return false;
> +
> +	if (cea_db_extended_tag(db) != VIDEO_DATA_BLOCK_420)
> +		return false;
> +
> +	return true;
> +}
> +
>  #define for_each_cea_db(cea, i, start, end) \
>  	for ((i) = (start); (i) < (end) && (i) + cea_db_payload_len(&(cea)[(i)]) < (end); (i) += cea_db_payload_len(&(cea)[(i)]) + 1)
>  
> +static void drm_parse_y420cmdb_bitmap(struct drm_connector *connector,
> +				     const u8 *db)
> +{
> +	struct drm_display_info *info = &connector->display_info;
> +	struct drm_hdmi_info *hdmi = &info->hdmi;
> +	u8 map_len = cea_db_payload_len(db) - 1;
> +	u8 count;
> +	u64 map = 0;
> +
> +	if (map_len == 0) {
> +		/* All CEA modes support ycbcr420 sampling also.*/
> +		hdmi->y420_cmdb_map = U64_MAX;
> +		info->color_formats |= DRM_COLOR_FORMAT_YCRCB420;
> +		return;
> +	}
> +
> +	/*
> +	 * This map indicates which of the existing CEA block modes
> +	 * from VDB can support YCBCR420 output too. So if bit=0 is
> +	 * set, first mode from VDB can support YCBCR420 output too.
> +	 * We will parse and keep this map, before parsing VDB itself
> +	 * to avoid going through the same block again and again.
> +	 *
> +	 * Spec is not clear about max possible size of this block.
> +	 * Clamping max bitmap block size at 8 bytes. Every byte can
> +	 * address 8 CEA modes, in this way this map can address
> +	 * 8*8 = first 64 SVDs.
> +	 */
> +	if (WARN_ON_ONCE(map_len > 8))
> +		map_len = 8;
> +
> +	for (count = 0; count < map_len; count++)
> +		map |= (u64)db[2 + count] << (8 * count);
> +
> +	if (map)
> +		info->color_formats |= DRM_COLOR_FORMAT_YCRCB420;
> +
> +	hdmi->y420_cmdb_map = map;
> +}
> +
>  static int
>  add_cea_modes(struct drm_connector *connector, struct edid *edid)
>  {
> @@ -3522,10 +3663,17 @@ add_cea_modes(struct drm_connector *connector, struct edid *edid)
>  				video = db + 1;
>  				video_len = dbl;
>  				modes += do_cea_modes(connector, video, dbl);
> -			}
> -			else if (cea_db_is_hdmi_vsdb(db)) {
> +			} else if (cea_db_is_hdmi_vsdb(db)) {
>  				hdmi = db;
>  				hdmi_len = dbl;
> +			} else if (cea_db_is_y420vdb(db) &&
> +				   connector->ycbcr_420_allowed) {
> +				const u8 *vdb420 = &db[2];
> +
> +				/* Add 4:2:0(only) modes present in EDID */
> +				modes += do_y420vdb_modes(connector,
> +							  vdb420,
> +							  dbl - 1);
>  			}
>  		}
>  	}
> @@ -4206,6 +4354,8 @@ static void drm_parse_cea_ext(struct drm_connector *connector,
>  			drm_parse_hdmi_vsdb_video(connector, db);
>  		if (cea_db_is_hdmi_forum_vsdb(db))
>  			drm_parse_hdmi_forum_vsdb(connector, db);
> +		if (cea_db_is_y420cmdb(db))
> +			drm_parse_y420cmdb_bitmap(connector, db);
>  	}
>  }
>  
> @@ -4460,6 +4610,7 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
>  	num_modes += add_cea_modes(connector, edid);
>  	num_modes += add_alternate_cea_modes(connector, edid);
>  	num_modes += add_displayid_detailed_modes(connector, edid);
> +
>  	if (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF)
>  		num_modes += add_inferred_modes(connector, edid);
>  
> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> index 7493fd3..ce2212d 100644
> --- a/include/drm/drm_connector.h
> +++ b/include/drm/drm_connector.h
> @@ -137,6 +137,25 @@ struct drm_scdc {
>  struct drm_hdmi_info {
>  	/** @scdc: sink's scdc support and capabilities */
>  	struct drm_scdc scdc;
> +
> +	/**
> +	 * @y420_vdb_modes: bitmap of modes which can support ycbcr420
> +	 * output only (not normal RGB/YCBCR444/422 outputs). There are total
> +	 * 107 VICs defined by CEA-861-F spec, so the size is 128 bits to map
> +	 * upto 128 VICs;
> +	 */
> +	unsigned long y420_vdb_modes[BITS_TO_LONGS(128)];
> +
> +	/**
> +	 * @y420_cmdb_modes: bitmap of modes which can support ycbcr420
> +	 * output also, along with normal HDMI outputs. There are total 107
> +	 * VICs defined by CEA-861-F spec, so the size is 128 bits to map upto
> +	 * 128 VICs;
> +	 */
> +	unsigned long y420_cmdb_modes[BITS_TO_LONGS(128)];
> +
> +	/** @y420_cmdb_map: bitmap of SVD index, to extraxt vcb modes */
> +	unsigned long y420_cmdb_map;

u64, otherwise it's busted on 32bit machines.

Mostl this looks pretty good. I think the main problem is the lack of
mode validation that would reject the 4:2:0 only modes if not supported
by the driver/device. I guess that's in a later patch? If so we need to
reorder the series a bit to avoid regeressions.

>  };
>  
>  /**
> @@ -200,6 +219,7 @@ struct drm_display_info {
>  #define DRM_COLOR_FORMAT_RGB444		(1<<0)
>  #define DRM_COLOR_FORMAT_YCRCB444	(1<<1)
>  #define DRM_COLOR_FORMAT_YCRCB422	(1<<2)
> +#define DRM_COLOR_FORMAT_YCRCB420	(1<<3)
>  
>  	/**
>  	 * @color_formats: HDMI Color formats, selects between RGB and YCrCb
> -- 
> 2.7.4

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [RESEND-CI v4 05/15] drm/edid: parse ycbcr 420 deep color information
  2017-06-21 10:34 ` [RESEND-CI v4 05/15] drm/edid: parse ycbcr 420 deep color information Shashank Sharma
@ 2017-06-27 11:53   ` Ville Syrjälä
  2017-06-30  5:20     ` Sharma, Shashank
  0 siblings, 1 reply; 58+ messages in thread
From: Ville Syrjälä @ 2017-06-27 11:53 UTC (permalink / raw)
  To: Shashank Sharma; +Cc: intel-gfx, Jose Abreu, dri-devel

On Wed, Jun 21, 2017 at 04:04:03PM +0530, Shashank Sharma wrote:
> CEA-861-F spec adds ycbcr420 deep color support information
> in hf-vsdb block. This patch extends the existing hf-vsdb parsing
> function by adding parsing of ycbcr420 deep color support from the
> EDID and adding it into display information stored.
> 
> V2: Rebase
> V3: Rebase
> V4: Moved definition of y420_dc_modes into this patch, where its used
>     (Ville)
> 
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Jose Abreu <joabreu@synopsys.com>
> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
> ---
>  drivers/gpu/drm/drm_edid.c  | 15 +++++++++++++++
>  include/drm/drm_connector.h |  3 +++
>  include/drm/drm_edid.h      |  5 +++++
>  3 files changed, 23 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index 8c7e73b..b4583f6 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -4196,6 +4196,19 @@ drm_default_rgb_quant_range(const struct drm_display_mode *mode)
>  }
>  EXPORT_SYMBOL(drm_default_rgb_quant_range);
>  
> +static void drm_parse_ycbcr420_deep_color_info(struct drm_connector *connector,
> +					     const u8 *db)
> +{
> +	struct drm_hdmi_info *info = &connector->display_info.hdmi;
> +
> +	if (db[7] & DRM_EDID_YCBCR420_DC_48)
> +		info->y420_dc_modes |= DRM_EDID_YCBCR420_DC_48;
> +	if (db[7] & DRM_EDID_YCBCR420_DC_36)
> +		info->y420_dc_modes |= DRM_EDID_YCBCR420_DC_36;
> +	if (db[7] & DRM_EDID_YCBCR420_DC_30)
> +		info->y420_dc_modes |= DRM_EDID_YCBCR420_DC_30;

y420_dc_modes = db[7] & (...);

will do if you plan to just copy the bits over.

> +}
> +
>  static void drm_parse_hdmi_forum_vsdb(struct drm_connector *connector,
>  				 const u8 *hf_vsdb)
>  {
> @@ -4236,6 +4249,8 @@ static void drm_parse_hdmi_forum_vsdb(struct drm_connector *connector,
>  				scdc->scrambling.low_rates = true;
>  		}
>  	}
> +
> +	drm_parse_ycbcr420_deep_color_info(connector, hf_vsdb);
>  }
>  
>  static void drm_parse_hdmi_deep_color_info(struct drm_connector *connector,
> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> index ce2212d..1305fe9 100644
> --- a/include/drm/drm_connector.h
> +++ b/include/drm/drm_connector.h
> @@ -156,6 +156,9 @@ struct drm_hdmi_info {
>  
>  	/** @y420_cmdb_map: bitmap of SVD index, to extraxt vcb modes */
>  	unsigned long y420_cmdb_map;
> +
> +	/** @y420_dc_modes: bitmap of deep color support index */
> +	u8 y420_dc_modes;
>  };
>  
>  /**
> diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
> index 89c0062..d4ff17c 100644
> --- a/include/drm/drm_edid.h
> +++ b/include/drm/drm_edid.h
> @@ -213,6 +213,11 @@ struct detailed_timing {
>  #define DRM_EDID_HDMI_DC_30               (1 << 4)
>  #define DRM_EDID_HDMI_DC_Y444             (1 << 3)
>  
> +/* YCBCR 420 deep color modes */
> +#define DRM_EDID_YCBCR420_DC_48		  (1 << 6)
> +#define DRM_EDID_YCBCR420_DC_36		  (1 << 5)
> +#define DRM_EDID_YCBCR420_DC_30		  (1 << 4)
> +
>  /* ELD Header Block */
>  #define DRM_ELD_HEADER_BLOCK_SIZE	4
>  
> -- 
> 2.7.4

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [RESEND-CI v4 06/15] drm/edid: parse sink information before CEA blocks
  2017-06-21 10:34 ` [RESEND-CI v4 06/15] drm/edid: parse sink information before CEA blocks Shashank Sharma
@ 2017-06-27 11:55   ` Ville Syrjälä
  2017-06-30  5:22     ` Sharma, Shashank
  0 siblings, 1 reply; 58+ messages in thread
From: Ville Syrjälä @ 2017-06-27 11:55 UTC (permalink / raw)
  To: Shashank Sharma; +Cc: intel-gfx, dri-devel

On Wed, Jun 21, 2017 at 04:04:04PM +0530, Shashank Sharma wrote:
> CEA-861-F adds ycbcr capability map block, for HDMI 2.0 sinks.
> This block contains a map of indexes of CEA modes, which can
> support YCBCR 420 output also. To avoid multiple parsing of same
> CEA block, let's parse the sink information and get this map, before
> parsing CEA modes.
> 
> This patch moves the call to drm_add_display_info function, before the
> mode parsing block.
> 
> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
> ---
>  drivers/gpu/drm/drm_edid.c | 9 +++++++--
>  1 file changed, 7 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index b4583f6..42934b2 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -4605,6 +4605,13 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
>  	quirks = edid_get_quirks(edid);
>  
>  	/*
> +	 * CEA-861-F adds ycbcr capability map block, for HDMI 2.0 sinks.
> +	 * To avoid multiple parsing of same block, lets parse that map
> +	 * from sink info, before parsing CEA modes.
> +	 */
> +	drm_add_display_info(connector, edid);
> +

This patch should come before the 4:2:0 mode parsing, no?

Otherwise I think this should be fine so
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

> +	/*
>  	 * EDID spec says modes should be preferred in this order:
>  	 * - preferred detailed mode
>  	 * - other detailed modes from base block
> @@ -4632,8 +4639,6 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
>  	if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75))
>  		edid_fixup_preferred(connector, quirks);
>  
> -	drm_add_display_info(connector, edid);
> -
>  	if (quirks & EDID_QUIRK_FORCE_6BPC)
>  		connector->display_info.bpc = 6;
>  
> -- 
> 2.7.4

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v5 7/7] drm: create hdmi output property
  2017-06-21 10:34 ` [PATCH v5 7/7] drm: create hdmi output property Shashank Sharma
  2017-06-22  7:14   ` [Intel-gfx] " Daniel Vetter
@ 2017-06-27 12:14   ` Ville Syrjälä
  2017-06-30  5:43     ` Sharma, Shashank
  1 sibling, 1 reply; 58+ messages in thread
From: Ville Syrjälä @ 2017-06-27 12:14 UTC (permalink / raw)
  To: Shashank Sharma; +Cc: Daniel Vetter, intel-gfx, Jose Abreu, dri-devel

On Wed, Jun 21, 2017 at 04:04:13PM +0530, Shashank Sharma wrote:
> HDMI displays can support various output types, based on
> the color space and subsampling type. The possible
> outputs from a HDMI 2.0 monitor could be:
>  - RGB
>  - YCBCR 444
>  - YCBCR 422
>  - YCBCR 420
> 
> This patch adds a drm property "hdmi_output_format", using which,
> a user can specify its preference, for the HDMI output type. The
> output type enums are similar to the mentioned outputs above. To
> handle various subsampling of YCBCR output types, this property
> allows two special cases:
>  - DRM_HDMI_OUTPUT_YCBCR_HQ
>    This indicates preferred output should be YCBCR output, with highest
>    subsampling rate by the source/sink, which can be typically:
>  	- ycbcr444
>  	- ycbcr422
>  	- ycbcr420
>  - DRM_HDMI_OUTPUT_YCBCR_LQ
>    This indicates preferred output should be YCBCR output, with lowest
>    subsampling rate supported by source/sink, which can be:
>  	- ycbcr420
>  	- ycbcr422
>  	- ycbcr444

I think we'll eventually need something more thorough than this to
allow full control over the AVI infoframe/MSA MISC/VSC SDP colormietry
stuff.

So I think we need to control at least these things:
- max bpc (some people seem to have some real needs to avoid deep color)
- rgb->ycbcr conversion (yes/no)
- ycbcr subsampling for the conversion and infoframe
- ycbcr encoding for the conversion and infoframe
- infoframe colorimetry

I've not really figured out how we'll tie all that together in a way
that doesn't get super confusing.

One idea might be that the infoframe stuff is totally independent of
the rest (ie. we'll define just an enum property for the infoframe
stuff in say this way:
"Automatic", "sRGB", "AdobeRGB", "YCbCr BT.601 4:2:2",
"xvYCC709 4:4:4", etc.

So none of the YCbCr output properties would actually affect the
infoframe unless the user has selected the default "Automatic" mode.
That should allow the user to output any kind of data through the pipe
in a pass through fashion (or with manually set up gamma/degamma/csc).
And configuring the inforame property would not affect the data passing
through the pipe in any way.

But I probably need to think more about this. So for now I think I'll
just want to get the automagic "use YCbCr 4:2:0 if we must" thing
working without any new properties getting in the way. We just have
to keep in mind that this automagic conversion thing must still work
when we add some properties, but I think that can generally be achieved
with some "Automatic" default property values.

> 
> Default value of the property is set to 0 = RGB, so no changes if you
> dont set the property.
> 
> PS: While doing modeset for YCBCR 420 only modes, this property is
>     ignored, as those timings can be supported only in YCBCR 420
>     output mode.
> 
> V2: Added description for the new variable to address build warning
> V3: Rebase
> V4: Rebase
> V5: Added get_property counterpart to fix IGT BAT failures
> 
> Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
> Cc: Jose Abreu <joabreu@synopsys.com>
> Cc: Daniel Vetter <daniel.vetter@intel.com>
> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
> ---
>  drivers/gpu/drm/drm_atomic.c        |  4 ++++
>  drivers/gpu/drm/drm_atomic_helper.c |  4 ++++
>  drivers/gpu/drm/drm_connector.c     | 32 ++++++++++++++++++++++++++++++++
>  include/drm/drm_connector.h         | 18 ++++++++++++++++++
>  include/drm/drm_mode_config.h       |  5 +++++
>  5 files changed, 63 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
> index 77dcef0..ea90f8e 100644
> --- a/drivers/gpu/drm/drm_atomic.c
> +++ b/drivers/gpu/drm/drm_atomic.c
> @@ -1192,6 +1192,8 @@ int drm_atomic_connector_set_property(struct drm_connector *connector,
>  		state->picture_aspect_ratio = val;
>  	} else if (property == connector->scaling_mode_property) {
>  		state->scaling_mode = val;
> +	} else if (property == config->hdmi_output_property) {
> +		state->hdmi_output = val;
>  	} else if (connector->funcs->atomic_set_property) {
>  		return connector->funcs->atomic_set_property(connector,
>  				state, property, val);
> @@ -1272,6 +1274,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector,
>  		*val = state->picture_aspect_ratio;
>  	} else if (property == connector->scaling_mode_property) {
>  		*val = state->scaling_mode;
> +	} else if (property == config->hdmi_output_property) {
> +		*val = state->hdmi_output;
>  	} else if (connector->funcs->atomic_get_property) {
>  		return connector->funcs->atomic_get_property(connector,
>  				state, property, val);
> diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
> index 86d3093..1356b3f 100644
> --- a/drivers/gpu/drm/drm_atomic_helper.c
> +++ b/drivers/gpu/drm/drm_atomic_helper.c
> @@ -637,6 +637,10 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
>  			if (old_connector_state->link_status !=
>  			    new_connector_state->link_status)
>  				new_crtc_state->connectors_changed = true;
> +
> +			if (old_connector_state->hdmi_output !=
> +			    new_connector_state->hdmi_output)
> +				new_crtc_state->connectors_changed = true;
>  		}
>  
>  		if (funcs->atomic_check)
> diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
> index 5cd61af..f3c5928 100644
> --- a/drivers/gpu/drm/drm_connector.c
> +++ b/drivers/gpu/drm/drm_connector.c
> @@ -227,6 +227,11 @@ int drm_connector_init(struct drm_device *dev,
>  					      config->edid_property,
>  					      0);
>  
> +	if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL)
> +		drm_object_attach_property(&connector->base,
> +					   config->hdmi_output_property,
> +					   0);
> +
>  	drm_object_attach_property(&connector->base,
>  				      config->dpms_property, 0);
>  
> @@ -617,6 +622,26 @@ static const struct drm_prop_enum_list drm_link_status_enum_list[] = {
>  };
>  DRM_ENUM_NAME_FN(drm_get_link_status_name, drm_link_status_enum_list)
>  
> +static const struct drm_prop_enum_list drm_hdmi_output_enum_list[] = {
> +	{ DRM_HDMI_OUTPUT_DEFAULT_RGB, "output_rgb" },
> +	{ DRM_HDMI_OUTPUT_YCBCR444, "output_ycbcr444" },
> +	{ DRM_HDMI_OUTPUT_YCBCR422, "output_ycbcr422" },
> +	{ DRM_HDMI_OUTPUT_YCBCR420, "output_ycbcr420" },
> +	{ DRM_HDMI_OUTPUT_YCBCR_HQ, "output_ycbcr_high_subsampling" },
> +	{ DRM_HDMI_OUTPUT_YCBCR_LQ, "output_ycbcr_low_subsampling" },
> +	{ DRM_HDMI_OUTPUT_INVALID, "invalid_output" },
> +};
> +
> +/**
> + * drm_get_hdmi_output_name - return a string for a given hdmi output enum
> + * @type: enum of output type
> + */
> +const char *drm_get_hdmi_output_name(enum drm_hdmi_output_type type)
> +{
> +	return drm_hdmi_output_enum_list[type].name;
> +}
> +EXPORT_SYMBOL(drm_get_hdmi_output_name);
> +
>  /**
>   * drm_display_info_set_bus_formats - set the supported bus formats
>   * @info: display info to store bus formats in
> @@ -789,6 +814,13 @@ int drm_connector_create_standard_properties(struct drm_device *dev)
>  		return -ENOMEM;
>  	dev->mode_config.link_status_property = prop;
>  
> +	prop = drm_property_create_enum(dev, 0, "hdmi_output_format",
> +					drm_hdmi_output_enum_list,
> +					ARRAY_SIZE(drm_hdmi_output_enum_list));
> +	if (!prop)
> +		return -ENOMEM;
> +	dev->mode_config.hdmi_output_property = prop;
> +
>  	return 0;
>  }
>  
> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> index 1305fe9..5ba1f32 100644
> --- a/include/drm/drm_connector.h
> +++ b/include/drm/drm_connector.h
> @@ -321,6 +321,17 @@ struct drm_tv_connector_state {
>  	unsigned int hue;
>  };
>  
> +/* HDMI output pixel format */
> +enum drm_hdmi_output_type {
> +	DRM_HDMI_OUTPUT_DEFAULT_RGB, /* default RGB */
> +	DRM_HDMI_OUTPUT_YCBCR444, /* YCBCR 444 */
> +	DRM_HDMI_OUTPUT_YCBCR422, /* YCBCR 422 */
> +	DRM_HDMI_OUTPUT_YCBCR420, /* YCBCR 420 */
> +	DRM_HDMI_OUTPUT_YCBCR_HQ, /* Highest subsampled YUV */
> +	DRM_HDMI_OUTPUT_YCBCR_LQ, /* Lowest subsampled YUV */
> +	DRM_HDMI_OUTPUT_INVALID, /* Guess what ? */
> +};
> +
>  /**
>   * struct drm_connector_state - mutable connector state
>   * @connector: backpointer to the connector
> @@ -365,6 +376,12 @@ struct drm_connector_state {
>  	 * upscaling, mostly used for built-in panels.
>  	 */
>  	unsigned int scaling_mode;
> +
> +	/**
> +	 * @hdmi_output: Connector property to control the
> +	 * HDMI output mode (RGB/YCBCR444/422/420).
> +	 */
> +	enum drm_hdmi_output_type hdmi_output;
>  };
>  
>  /**
> @@ -993,6 +1010,7 @@ static inline void drm_connector_unreference(struct drm_connector *connector)
>  
>  const char *drm_get_connector_status_name(enum drm_connector_status status);
>  const char *drm_get_subpixel_order_name(enum subpixel_order order);
> +const char *drm_get_hdmi_output_name(enum drm_hdmi_output_type type);
>  const char *drm_get_dpms_name(int val);
>  const char *drm_get_dvi_i_subconnector_name(int val);
>  const char *drm_get_dvi_i_select_name(int val);
> diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h
> index 4298171..1887261 100644
> --- a/include/drm/drm_mode_config.h
> +++ b/include/drm/drm_mode_config.h
> @@ -740,6 +740,11 @@ struct drm_mode_config {
>  	 * the position of the output on the host's screen.
>  	 */
>  	struct drm_property *suggested_y_property;
> +	/**
> +	 * @hdmi_output_property: output pixel format from HDMI display
> +	 * Default is set for RGB
> +	 */
> +	struct drm_property *hdmi_output_property;
>  
>  	/* dumb ioctl parameters */
>  	uint32_t preferred_depth, prefer_shadow;
> -- 
> 2.7.4

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [RESEND-CI v4 11/15] drm/i915: prepare scaler for YCBCR420 modeset
  2017-06-21 10:34 ` [RESEND-CI v4 11/15] drm/i915: prepare scaler for YCBCR420 modeset Shashank Sharma
@ 2017-06-27 12:16   ` Ander Conselvan De Oliveira
  2017-06-30  5:50     ` Sharma, Shashank
  0 siblings, 1 reply; 58+ messages in thread
From: Ander Conselvan De Oliveira @ 2017-06-27 12:16 UTC (permalink / raw)
  To: Shashank Sharma, dri-devel, intel-gfx, ville.syrjala

On Wed, 2017-06-21 at 16:04 +0530, Shashank Sharma wrote:
> To get a YCBCR420 output from intel platforms, we need one
> scaler to scale down YCBCR444 samples to YCBCR420 samples.
> 
> This patch:
> - Does scaler allocation for HDMI ycbcr420 outputs.
> - Programs PIPE_MISC register for ycbcr420 output.
> - Adds a new scaler user "HDMI output" to plug-into existing
>   scaler framework. This output type is identified using bit
>   30 of the scaler users bitmap.
> 
> V2: rebase
> V3: rebase
> V4: rebase
> 
> Cc: Ville Syrjala <ville.syrjala@linux.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_atomic.c  |  6 ++++++
>  drivers/gpu/drm/i915/intel_display.c | 26 ++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_drv.h     | 10 +++++++++-
>  drivers/gpu/drm/i915/intel_hdmi.c    | 10 ++++++++++
>  drivers/gpu/drm/i915/intel_panel.c   |  3 ++-
>  5 files changed, 53 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
> index 36d4e63..a8c9ac5 100644
> --- a/drivers/gpu/drm/i915/intel_atomic.c
> +++ b/drivers/gpu/drm/i915/intel_atomic.c
> @@ -264,6 +264,12 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv,
>  
>  			/* panel fitter case: assign as a crtc scaler */
>  			scaler_id = &scaler_state->scaler_id;
> +		} else if (i == SKL_HDMI_OUTPUT_INDEX) {
> +			name = "HDMI-OUTPUT";
> +			idx = intel_crtc->base.base.id;
> +
> +			/* hdmi output case: needs a pipe scaler */
> +			scaler_id = &scaler_state->scaler_id;
>  		} else {
>  			name = "PLANE";
>  
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index da29536..983f581 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -4626,6 +4626,11 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
>  	 */
>  	need_scaling = src_w != dst_w || src_h != dst_h;
>  
> +	if (crtc_state->hdmi_output == DRM_HDMI_OUTPUT_YCBCR420
> +		&& scaler_user == SKL_HDMI_OUTPUT_INDEX)

Is it really necessary to check for both? If it is, what's the point of creating
SKL_HDMI_OUTPUT_INDEX?


> +		/* YCBCR 444 -> 420 conversion needs a scaler */
> +		need_scaling = true;
> +
>  	/*
>  	 * if plane is being disabled or scaler is no more required or force detach
>  	 *  - free scaler binded to this plane/crtc
> @@ -4673,6 +4678,26 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
>  }
>  
>  /**
> + * skl_update_scaler_hdmi_output - Stages update to scaler state for HDMI.
> + * HDMI YCBCR 420 output needs a scaler, for downsampling.
> + *
> + * @state: crtc's scaler state
> + *
> + * Return
> + *     0 - scaler_usage updated successfully
> + *    error - requested scaling cannot be supported or other error condition
> + */
> +int skl_update_scaler_crtc_hdmi_output(struct intel_crtc_state *state)
> +{
> +	const struct drm_display_mode *mode = &state->base.adjusted_mode;
> +
> +	return skl_update_scaler(state, !state->base.active,
> +		SKL_HDMI_OUTPUT_INDEX, &state->scaler_state.scaler_id,
> +		state->pipe_src_w, state->pipe_src_h,
> +		mode->crtc_hdisplay, mode->crtc_vdisplay);
> +}
> +
> +/**
>   * skl_update_scaler_crtc - Stages update to scaler state for a given crtc.
>   *
>   * @state: crtc's scaler state
> @@ -8058,6 +8083,7 @@ static void haswell_set_pipemisc(struct drm_crtc *crtc)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
>  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> +	enum drm_hdmi_output_type hdmi_out = intel_crtc->config->hdmi_output;
>  
>  	if (IS_BROADWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 9) {
>  		u32 val = 0;
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 38fe56c..2206aa8 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -471,7 +471,8 @@ struct intel_crtc_scaler_state {
>  	 *
>  	 *     If a bit is set, a user is using a scaler.
>  	 *     Here user can be a plane or crtc as defined below:
> -	 *       bits 0-30 - plane (bit position is index from drm_plane_index)
> +	 *       bits 0-29 - plane (bit position is index from drm_plane_index)
> +	 *       bit 30    - hdmi output
>  	 *       bit 31    - crtc
>  	 *
>  	 * Instead of creating a new index to cover planes and crtc, using
> @@ -484,6 +485,12 @@ struct intel_crtc_scaler_state {
>  	 * avilability.
>  	 */
>  #define SKL_CRTC_INDEX 31
> +
> +	/*
> +	 * HDMI YCBCR 420 output consume a scaler. So adding a user
> +	 * for HDMI output 420 requirement.
> +	 */
> +#define SKL_HDMI_OUTPUT_INDEX 30

I'm not convinced about this. The scaler is still used as a pipe scaler and the
patch even adds a call intel_pch_panel_fitting().

>  	unsigned scaler_users;
>  
>  	/* scaler used by crtc for panel fitting purpose */
> @@ -1481,6 +1488,7 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode,
>  				 struct intel_crtc_state *pipe_config);
>  
>  int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state);
> +int skl_update_scaler_crtc_hdmi_output(struct intel_crtc_state *state);
>  int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state);
>  
>  static inline u32 intel_plane_ggtt_offset(const struct intel_plane_state *state)
> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> index 22da5cd..8d5aa1e 100644
> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> @@ -1415,6 +1415,7 @@ intel_hdmi_compute_ycbcr_config(struct drm_connector_state *conn_state,
>  	}
>  
>  	if (type == DRM_HDMI_OUTPUT_YCBCR420) {
> +		struct intel_crtc *intel_crtc = to_intel_crtc(conn_state->crtc);
>  
>  		/* YCBCR420 TMDS rate requirement is half the pixel clock */
>  		config->hdmi_output = DRM_HDMI_OUTPUT_YCBCR420;
> @@ -1422,6 +1423,15 @@ intel_hdmi_compute_ycbcr_config(struct drm_connector_state *conn_state,
>  		*clock_12bpc /= 2;
>  		*clock_8bpc /= 2;
>  
> +		/* YCBCR 420 output conversion needs a scaler */
> +		if (skl_update_scaler_crtc_hdmi_output(config)) {
> +			DRM_ERROR("Scaler allocation for output failed\n");
> +			return DRM_HDMI_OUTPUT_INVALID;
> +		}
> +
> +		/* Bind this scaler to pipe */
> +		intel_pch_panel_fitting(intel_crtc, config,
> +					DRM_MODE_SCALE_FULLSCREEN);
>  	}
>  
>  	/* Encoder is capable of this output, lets commit to CRTC */
> diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
> index 96c2cbd..b6a32c4 100644
> --- a/drivers/gpu/drm/i915/intel_panel.c
> +++ b/drivers/gpu/drm/i915/intel_panel.c
> @@ -110,7 +110,8 @@ intel_pch_panel_fitting(struct intel_crtc *intel_crtc,
>  
>  	/* Native modes don't need fitting */
>  	if (adjusted_mode->crtc_hdisplay == pipe_config->pipe_src_w &&
> -	    adjusted_mode->crtc_vdisplay == pipe_config->pipe_src_h)
> +	    adjusted_mode->crtc_vdisplay == pipe_config->pipe_src_h &&
> +	    pipe_config->hdmi_output != DRM_HDMI_OUTPUT_YCBCR420)

I don't like that the knowledge that YCBCR420 needs the scaler is spread
everywhere, including this function that should only deal with panel fitting. I
would rather add a force parameter to intel_pch_panel_fitting() and
skl_update_scaler() that would mean setup the scaler even if looks like it's not
necessary. That way the hdmi code would just call them with force enabled,
without sprinkling "hdmi_output == YCBCR420" everywhere.

Ander

>  		goto done;
>  
>  	switch (fitting_mode) {
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [RESEND-CI v4 13/15] drm/i915: prepare csc unit for YCBCR HDMI output
  2017-06-21 10:34 ` [RESEND-CI v4 13/15] drm/i915: prepare csc unit for YCBCR HDMI output Shashank Sharma
@ 2017-06-29 12:08   ` Ander Conselvan De Oliveira
  2017-06-30  6:03     ` Sharma, Shashank
  0 siblings, 1 reply; 58+ messages in thread
From: Ander Conselvan De Oliveira @ 2017-06-29 12:08 UTC (permalink / raw)
  To: Shashank Sharma, dri-devel, intel-gfx, ville.syrjala; +Cc: Daniel Vetter

On Wed, 2017-06-21 at 16:04 +0530, Shashank Sharma wrote:
> To support ycbcr HDMI output, we need a pipe CSC block to
> do the RGB->YCBCR conversion, as the blender output is in RGB.
> 
> Current Intel platforms have only one pipe CSC unit, so
> we can either do color correction using it, or we can perform
> RGB->YCBCR conversion.
> 
> This function adds a csc handler, to perform RGB->YCBCR conversion
> as per recommended spec values.

Please do a full reference to the "spec", including name, version and relevant
section.

> 
> V2: Rebase
> V3: Rebase
> V4: Rebase
> 
> 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_color.c   | 47 +++++++++++++++++++++++++++++++++++-
>  drivers/gpu/drm/i915/intel_display.c | 32 ++++++++++++++++++++++++
>  2 files changed, 78 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_color.c b/drivers/gpu/drm/i915/intel_color.c
> index 306c6b0..12d5f21 100644
> --- a/drivers/gpu/drm/i915/intel_color.c
> +++ b/drivers/gpu/drm/i915/intel_color.c
> @@ -41,6 +41,19 @@
>  
>  #define LEGACY_LUT_LENGTH		(sizeof(struct drm_color_lut) * 256)
>  
> +/* Post offset values for RGB->YCBCR conversion */
> +#define POSTOFF_RGB_TO_YUV_HI 0x800
> +#define POSTOFF_RGB_TO_YUV_ME 0x100
> +#define POSTOFF_RGB_TO_YUV_LO 0x800
> +
> +/* Direct spec values for RGB->YUV conversion matrix */
> +#define CSC_RGB_TO_YUV_RU_GU 0x2ba809d8
> +#define CSC_RGB_TO_YUV_BU 0x37e80000
> +#define CSC_RGB_TO_YUV_RY_GY 0x1e089cc0
> +#define CSC_RGB_TO_YUV_BY 0xb5280000
> +#define CSC_RGB_TO_YUV_RV_GV 0xbce89ad8
> +#define CSC_RGB_TO_YUV_BV 0x1e080000
> +

Not a big fan or hardcoding this in the register format. We already have the
code for converting a number to the right format for the register in
i915_load_csc_matrix(). I think it would make more sense to extract the code
that actually writes the matrix out of that function, so it would just
unconditionally use a matrix and coefficients passed as arguments. Then the
values above would be defined in the format expected for this new function.

>  /*
>   * Extract the CSC coefficient from a CTM coefficient (in U32.32 fixed point
>   * format). This macro takes the coefficient we want transformed and the
> @@ -91,6 +104,35 @@ static void ctm_mult_by_limited(uint64_t *result, int64_t *input)
>  	}
>  }
>  
> +void i9xx_load_ycbcr_conversion_matrix(struct intel_crtc *intel_crtc)
> +{
> +	int pipe = intel_crtc->pipe;
> +	struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
> +
> +	/* We don't use high values for conversion */
> +	I915_WRITE(PIPE_CSC_PREOFF_HI(pipe), 0);
> +	I915_WRITE(PIPE_CSC_PREOFF_ME(pipe), 0);
> +	I915_WRITE(PIPE_CSC_PREOFF_LO(pipe), 0);
> +
> +	/* Program direct spec values for RGB to YCBCR conversion matrix */
> +	I915_WRITE(PIPE_CSC_COEFF_RU_GU(pipe), CSC_RGB_TO_YUV_RU_GU);
> +	I915_WRITE(PIPE_CSC_COEFF_BU(pipe), CSC_RGB_TO_YUV_BU);
> +
> +	I915_WRITE(PIPE_CSC_COEFF_RY_GY(pipe), CSC_RGB_TO_YUV_RY_GY);
> +	I915_WRITE(PIPE_CSC_COEFF_BY(pipe), CSC_RGB_TO_YUV_BY);
> +
> +	I915_WRITE(PIPE_CSC_COEFF_RV_GV(pipe), CSC_RGB_TO_YUV_RV_GV);
> +	I915_WRITE(PIPE_CSC_COEFF_BV(pipe), CSC_RGB_TO_YUV_BV);
> +
> +	/* Spec postoffset values */
> +	I915_WRITE(PIPE_CSC_POSTOFF_HI(pipe), POSTOFF_RGB_TO_YUV_HI);
> +	I915_WRITE(PIPE_CSC_POSTOFF_ME(pipe), POSTOFF_RGB_TO_YUV_ME);
> +	I915_WRITE(PIPE_CSC_POSTOFF_LO(pipe), POSTOFF_RGB_TO_YUV_LO);
> +
> +	/* CSC mode before gamma */
> +	I915_WRITE(PIPE_CSC_MODE(pipe), 0);
> +}
> +
>  /* Set up the pipe CSC unit. */
>  static void i9xx_load_csc_matrix(struct drm_crtc_state *crtc_state)
>  {
> @@ -101,7 +143,10 @@ static void i9xx_load_csc_matrix(struct drm_crtc_state *crtc_state)
>  	uint16_t coeffs[9] = { 0, };
>  	struct intel_crtc_state *intel_crtc_state = to_intel_crtc_state(crtc_state);
>  
> -	if (crtc_state->ctm) {
> +	if (intel_crtc_state->hdmi_output > DRM_HDMI_OUTPUT_DEFAULT_RGB) {
> +		i9xx_load_ycbcr_conversion_matrix(intel_crtc);
> +		return;
> +	} else if (crtc_state->ctm) {

Hmm, I'm not sure this is the right place to check for this condition. I mean,
we shouldn't allow the modeset to happen in this case.

>  		struct drm_color_ctm *ctm =
>  			(struct drm_color_ctm *)crtc_state->ctm->data;
>  		uint64_t input[9] = { 0, };
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 71fd19e..96ff2a0 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -6261,6 +6261,29 @@ static void intel_crtc_compute_pixel_rate(struct intel_crtc_state *crtc_state)
>  			ilk_pipe_pixel_rate(crtc_state);
>  }
>  
> +static int intel_crtc_ycbcr_config(struct intel_crtc_state *state)
> +{
> +	struct drm_crtc_state *drm_state = &state->base;
> +	struct drm_i915_private *dev_priv = to_i915(drm_state->crtc->dev);
> +
> +	/* YCBCR420 is supported only in HDMI 2.0 controllers */
> +	if ((state->hdmi_output == DRM_HDMI_OUTPUT_YCBCR420) &&
> +		!IS_GEMINILAKE(dev_priv)) {
> +		DRM_ERROR("YCBCR420 output is not supported\n");
> +		return -EINVAL;
> +	}
> +
> +	/* We need CSC for output conversion from RGB->YCBCR */
> +	if (drm_state->ctm) {
> +		DRM_ERROR("YCBCR output and CTM is not possible together\n");
> +		return -EINVAL;
> +	}

Hmm, ok, that's checked here.

> +
> +	DRM_DEBUG_DRIVER("Output %s can be supported\n",
> +			 drm_get_hdmi_output_name(state->hdmi_output));
> +	return 0;
> +}
> +
>  static int intel_crtc_compute_config(struct intel_crtc *crtc,
>  				     struct intel_crtc_state *pipe_config)
>  {
> @@ -6290,6 +6313,14 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
>  		return -EINVAL;
>  	}
>  
> +	/* YCBCR output check */
> +	if (pipe_config->hdmi_output > DRM_HDMI_OUTPUT_DEFAULT_RGB) {
> +		if (intel_crtc_ycbcr_config(pipe_config)) {

You could combine both ifs. Or, even better, just move the first check into the
caller. I think it would be better to keep it all in one place. I was a bit
unsure if function did the right thing until I saw how it was called.

> +			DRM_ERROR("Cant enable HDMI YCBCR output\n");
> +			return -EINVAL;
> +		}
> +	}
> +
>  	/*
>  	 * Pipe horizontal size must be even in:
>  	 * - DVO ganged mode
> @@ -11658,6 +11689,7 @@ intel_modeset_pipe_config(struct drm_crtc *crtc,
>  			DRM_DEBUG_KMS("Encoder config failure\n");
>  			goto fail;
>  		}
> +

No need for this.


Ander

>  	}
>  
>  	/* Set default port clock if not overwritten by the encoder. Needs to be
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [RESEND-CI v4 03/15] drm/edid: Complete CEA modedb(VIC 1-107)
  2017-06-27 11:32   ` Ville Syrjälä
@ 2017-06-30  5:11     ` Sharma, Shashank
  0 siblings, 0 replies; 58+ messages in thread
From: Sharma, Shashank @ 2017-06-30  5:11 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Jose Abreu, intel-gfx, dri-devel, Alex Deucher

Regards

Shashank


On 6/27/2017 5:02 PM, Ville Syrjälä wrote:
> On Wed, Jun 21, 2017 at 04:04:01PM +0530, Shashank Sharma wrote:
>> CEA-861-F specs defines new video modes to be used with
>> HDMI 2.0 EDIDs. The VIC range has been extended from 1-64 to
>> 1-107.
>>
>> Our existing CEA modedb contains only 64 modes (VIC=1 to VIC=64). Now
>> to be able to parse new CEA modes using the existing methods, we have
>> to complete the modedb (VIC=65 onwards).
>>
>> This patch adds:
>> - Timings for existing CEA video modes (from VIC=65 till VIC=92)
>> - Newly added 4k modes (from VIC=93 to VIC=107).
>>
>> The patch was originaly discussed and reviewed here:
>> https://patchwork.freedesktop.org/patch/135810/
>>
>> Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
>> Cc: Jose Abreu <Jose.Abreu@synopsys.com>
>> Cc: Andrzej Hajda <a.hajda@samsung.com>
>> Cc: Alex Deucher <alexander.deucher@amd.com>
>> Cc: Harry Wentland <harry.wentland@amd.com>
>>
>> V2: Rebase
>> V3: Rebase
>> V4: Added native bit handling as per CEA-861-F spec (Ville)
>>
>> Reviewed-by: Jose Abreu <Jose.Abreu@synopsys.com>
>> Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
>> Acked-by: Harry Wentland <harry.wentland@amd.com>
>> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
>> ---
>>   drivers/gpu/drm/drm_edid.c | 227 ++++++++++++++++++++++++++++++++++++++++++++-
>>   1 file changed, 226 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
>> index d312fe1..e2d1b30 100644
>> --- a/drivers/gpu/drm/drm_edid.c
>> +++ b/drivers/gpu/drm/drm_edid.c
>> @@ -1006,6 +1006,221 @@ static const struct drm_display_mode edid_cea_modes[] = {
>>   		   2492, 2640, 0, 1080, 1084, 1089, 1125, 0,
>>   		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
>>   	 .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
> ...
>> +	/* 77 - 1920x1080@100Hz */
>> +	{ DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 297000, 1920, 2448,
>> +		   2492, 2640, 0, 1080, 1084, 1094, 1125, 0,
>> +		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
>> +	 .vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
> ...
>> +	/* 104 - 3840x2160p@25Hz 64:27 */
>> +	{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 4016,
>> +		4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
>> +		DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
>> +	.vrefresh = 25, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27},
> https://lists.freedesktop.org/archives/dri-devel/2016-November/122669.html
Ok, looks like I missed this one while reformatting the patches, thanks 
for reminder.
Will cross check as per your script output.
>> @@ -2902,6 +3117,16 @@ add_alternate_cea_modes(struct drm_connector *connector, struct edid *edid)
>>   	return modes;
>>   }
>>   
>> +static u8 svd_to_vic(u8 svd)
>> +{
>> +
>> +	/* 0-6 bit vic, 7th bit native mode indicator */
>> +	if (((svd >= 1) && (svd <= 64)) || ((svd >= 129) && (svd <= 192)))
> Too many parentheses. lgtm otherwise.
Got it.

- Shashank
>> +		return svd & 127;
>> +
>> +	return svd;
>> +}
>> +
>>   static struct drm_display_mode *
>>   drm_display_mode_from_vic_index(struct drm_connector *connector,
>>   				const u8 *video_db, u8 video_len,
>> @@ -2915,7 +3140,7 @@ drm_display_mode_from_vic_index(struct drm_connector *connector,
>>   		return NULL;
>>   
>>   	/* CEA modes are numbered 1..127 */
>> -	vic = (video_db[video_index] & 127);
>> +	vic = svd_to_vic(video_db[video_index]);
>>   	if (!drm_valid_cea_vic(vic))
>>   		return NULL;
>>   
>> -- 
>> 2.7.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [RESEND-CI v4 04/15] drm/edid: parse YCBCR 420 videomodes from EDID
  2017-06-27 11:52   ` Ville Syrjälä
@ 2017-06-30  5:17     ` Sharma, Shashank
  2017-06-30 11:58       ` Ville Syrjälä
  0 siblings, 1 reply; 58+ messages in thread
From: Sharma, Shashank @ 2017-06-30  5:17 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, Jose Abreu, dri-devel

Regards

Shashank


On 6/27/2017 5:22 PM, Ville Syrjälä wrote:
> On Wed, Jun 21, 2017 at 04:04:02PM +0530, Shashank Sharma wrote:
>> HDMI 2.0 spec adds support for YCBCR420 sub-sampled output.
>> CEA-861-F adds two new blocks in EDID's CEA extension blocks,
>> to provide information about sink's YCBCR420 output capabilities.
>>
>> These blocks are:
>>
>> - YCBCR420vdb(YCBCR 420 video data block):
>> This block contains VICs of video modes, which can be sopported only
>> in YCBCR420 output mode (Not in RGB/YCBCR444/422. Its like a normal
>> SVD block, valid for YCBCR420 modes only.
>>
>> - YCBCR420cmdb(YCBCR 420 capability map data block):
>> This block gives information about video modes which can support
>> YCBCR420 output mode also (along with RGB,YCBCR444/422 etc) This
>> block contains a bitmap index of normal svd videomodes, which can
>> support YCBCR420 output too.
>> So if bit 0 from first vcb byte is set, first video mode in the svd
>> list can support YCBCR420 output too. Bit 1 means second video mode
>> from svd list can support YCBCR420 output too, and so on.
>>
>> This patch adds two bitmaps in display's hdmi_info structure, one each
>> for VCB and VDB modes. If the source is HDMI 2.0 capable, this patch
>> adds:
>> - VDB modes (YCBCR 420 only modes) in connector's mode list, also makes
>>    an entry in the vdb_bitmap per vic.
>> - VCB modes (YCBCR 420 also modes) only entry in the vcb_bitmap.
>>
>> Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
>> Cc: Jose Abreu <joabreu@synopsys.com>
>> Cc: Emil Velikov <emil.l.velikov@gmail.com>
>>
>> V2: Addressed
>>      Review comments from Emil:
>>      - Use 1ULL<<i instead of 1<<i to make sure the output is 64bit.
>>      - Use the suggested method for updating dbmap.
>>      - Add documentation for YCBCR420_vcb_map to fix kbuild warning.
>>
>>      Review comments from Ville:
>>      - Do not expose the YCBCR420 flags in uabi layer, keep it internal.
>>      - Save a map of YCBCR420 modes for future reference.
>>      - Check db length before trying to parse extended tag.
>>      - Add a warning if there are > 64 modes in capability map block.
>>      - Use y420cmdb in function names and macros while dealing with vcb
>>        to be aligned with spec.
>>      - Move the display information parsing block ahead of mode parsing
>>        blocks.
>>
>> V3: Addressed design/review comments from Ville
>>      - Do not add flags in video modes, else we have to expose them to user
>>      - There should not be a UABI change, and kernel should detect the
>>        choice of the output based on type of mode, and the bitmaps.
>>      - Use standard bitops from kernel bitmap header, instead of calculating
>>        bit positions manually.
>>
>> V4: Addressed review comments from Ville:
>>      - s/ycbcr_420_vdb/y420vdb
>>      - s/ycbcr_420_vcb/y420cmdb
>>      - Be less verbose on description of do_y420vdb_modes
>>      - Move newmode variable in the loop scope.
>>      - Use svd_to_vic() to get a VIC, instead of 0x7f
>>      - Remove bitmap description for CMDB modes & VDB modes
>>      - Dont add connector->ycbcr_420_allowed check for cmdb modes
>>      - Remove 'len' variable, in is_y420cmdb function, which is used
>>        only once
>>      - Add length check in is_y420vdb function
>>      - Remove unnecessary if (!db) check in function parse_y420cmdb_bitmap
>>      - Do not add print about YCBCR 420 modes
>>      - Fix indentation in few places
>>      - Move ycbcr420_dc_modes in next patch, where its used
>>      - Add a separate patch for movement of drm_add_display_info()
>>
>> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
>> ---
>>   drivers/gpu/drm/drm_edid.c  | 157 +++++++++++++++++++++++++++++++++++++++++++-
>>   include/drm/drm_connector.h |  20 ++++++
>>   2 files changed, 174 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
>> index e2d1b30..8c7e73b 100644
>> --- a/drivers/gpu/drm/drm_edid.c
>> +++ b/drivers/gpu/drm/drm_edid.c
>> @@ -2781,7 +2781,9 @@ add_detailed_modes(struct drm_connector *connector, struct edid *edid,
>>   #define VIDEO_BLOCK     0x02
>>   #define VENDOR_BLOCK    0x03
>>   #define SPEAKER_BLOCK	0x04
>> -#define VIDEO_CAPABILITY_BLOCK	0x07
>> +#define VIDEO_CAPABILITY_BLOCK 0x07
>> +#define VIDEO_DATA_BLOCK_420	0x0E
>> +#define VIDEO_CAP_BLOCK_Y420CMDB 0x0F
>>   #define EDID_BASIC_AUDIO	(1 << 6)
>>   #define EDID_CEA_YCRCB444	(1 << 5)
>>   #define EDID_CEA_YCRCB422	(1 << 4)
>> @@ -3153,15 +3155,79 @@ drm_display_mode_from_vic_index(struct drm_connector *connector,
>>   	return newmode;
>>   }
>>   
>> +/*
>> + * do_y420vdb_modes - Parse YCBCR 420 only modes
>> + * @connector: connector corresponding to the HDMI sink
>> + * @svds: start of the data block of CEA YCBCR 420 VDB
>> + * @len: length of the CEA YCBCR 420 VDB
>> + *
>> + * Parse the CEA-861-F YCBCR 420 Video Data Block (Y420VDB)
>> + * which contains modes which can be supported in YCBCR 420
>> + * output format only.
>> + */
>> +static int do_y420vdb_modes(struct drm_connector *connector,
>> +				   const u8 *svds, u8 svds_len)
>> +{
>> +	int modes = 0, i;
>> +	struct drm_device *dev = connector->dev;
>> +	struct drm_display_info *info = &connector->display_info;
>> +	struct drm_hdmi_info *hdmi = &info->hdmi;
>> +
>> +	for (i = 0; i < svds_len; i++) {
>> +		u8 vic = svd_to_vic(svds[i]);
>> +		struct drm_display_mode *newmode;
>> +
>> +		newmode = drm_mode_duplicate(dev, &edid_cea_modes[vic]);
>> +		if (!newmode)
>> +			break;
>> +		bitmap_set(hdmi->y420_vdb_modes, vic, 1);
>> +		drm_mode_probed_add(connector, newmode);
>> +		modes++;
>> +	}
>> +
>> +	if (modes > 0)
>> +		info->color_formats |= DRM_COLOR_FORMAT_YCRCB420;
>> +	return modes;
>> +}
>> +
>> +/*
>> + * drm_add_cmdb_modes - Add a YCBCR 420 mode into bitmap
>> + * @connector: connector corresponding to the HDMI sink
>> + * @vic: CEA vic for the video mode to be added in the map
>> + *
>> + * Makes an entry for a videomode in the YCBCR 420 bitmap
>> + */
>> +static void
>> +drm_add_cmdb_modes(struct drm_connector *connector, u8 svd)
>> +{
>> +	u8 vic = svd_to_vic(svd);
>> +	struct drm_hdmi_info *hdmi = &connector->display_info.hdmi;
>> +
>> +	bitmap_set(hdmi->y420_cmdb_modes, vic, 1);
>> +}
>> +
>>   static int
>>   do_cea_modes(struct drm_connector *connector, const u8 *db, u8 len)
>>   {
>>   	int i, modes = 0;
>> +	struct drm_hdmi_info *hdmi = &connector->display_info.hdmi;
>>   
>>   	for (i = 0; i < len; i++) {
>>   		struct drm_display_mode *mode;
>>   		mode = drm_display_mode_from_vic_index(connector, db, len, i);
>>   		if (mode) {
>> +			/*
>> +			 * YCBCR420 capability block contains a bitmap which
>> +			 * gives the index of CEA modes from CEA VDB, which
>> +			 * can support YCBCR 420 sampling output also (apart
>> +			 * from RGB/YCBCR444 etc).
>> +			 * For example, if the bit 0 in bitmap is set,
>> +			 * first mode in VDB can support YCBCR420 output too.
>> +			 * Add YCBCR420 modes only if sink is HDMI 2.0 capable.
>> +			 */
>> +			if (test_bit(i, &hdmi->y420_cmdb_map))
>> +				drm_add_cmdb_modes(connector, db[i]);
>> +
>>   			drm_mode_probed_add(connector, mode);
>>   			modes++;
>>   		}
>> @@ -3437,6 +3503,12 @@ do_hdmi_vsdb_modes(struct drm_connector *connector, const u8 *db, u8 len,
>>   }
>>   
>>   static int
>> +cea_db_extended_tag(const u8 *db)
>> +{
>> +	return db[1];
>> +}
>> +
>> +static int
>>   cea_db_payload_len(const u8 *db)
>>   {
>>   	return db[0] & 0x1f;
>> @@ -3497,9 +3569,78 @@ static bool cea_db_is_hdmi_forum_vsdb(const u8 *db)
>>   	return oui == HDMI_FORUM_IEEE_OUI;
>>   }
>>   
>> +static bool cea_db_is_y420cmdb(const u8 *db)
>> +{
>> +
>> +	if (cea_db_tag(db) != VIDEO_CAPABILITY_BLOCK)
> Still would like to see that patch to clean up the current extended tag
> usage...
Yep, its on the way, running a bit loaded.
>> +		return false;
>> +
>> +	if (!cea_db_payload_len(db))
>> +		return false;
>> +
>> +	if (cea_db_extended_tag(db) != VIDEO_CAP_BLOCK_Y420CMDB)
>> +		return false;
>> +
>> +	return true;
>> +}
>> +
>> +static bool cea_db_is_y420vdb(const u8 *db)
>> +{
>> +	if (cea_db_tag(db) != VIDEO_CAPABILITY_BLOCK)
>> +		return false;
>> +
>> +	if (!cea_db_payload_len(db))
>> +		return false;
>> +
>> +	if (cea_db_extended_tag(db) != VIDEO_DATA_BLOCK_420)
>> +		return false;
>> +
>> +	return true;
>> +}
>> +
>>   #define for_each_cea_db(cea, i, start, end) \
>>   	for ((i) = (start); (i) < (end) && (i) + cea_db_payload_len(&(cea)[(i)]) < (end); (i) += cea_db_payload_len(&(cea)[(i)]) + 1)
>>   
>> +static void drm_parse_y420cmdb_bitmap(struct drm_connector *connector,
>> +				     const u8 *db)
>> +{
>> +	struct drm_display_info *info = &connector->display_info;
>> +	struct drm_hdmi_info *hdmi = &info->hdmi;
>> +	u8 map_len = cea_db_payload_len(db) - 1;
>> +	u8 count;
>> +	u64 map = 0;
>> +
>> +	if (map_len == 0) {
>> +		/* All CEA modes support ycbcr420 sampling also.*/
>> +		hdmi->y420_cmdb_map = U64_MAX;
>> +		info->color_formats |= DRM_COLOR_FORMAT_YCRCB420;
>> +		return;
>> +	}
>> +
>> +	/*
>> +	 * This map indicates which of the existing CEA block modes
>> +	 * from VDB can support YCBCR420 output too. So if bit=0 is
>> +	 * set, first mode from VDB can support YCBCR420 output too.
>> +	 * We will parse and keep this map, before parsing VDB itself
>> +	 * to avoid going through the same block again and again.
>> +	 *
>> +	 * Spec is not clear about max possible size of this block.
>> +	 * Clamping max bitmap block size at 8 bytes. Every byte can
>> +	 * address 8 CEA modes, in this way this map can address
>> +	 * 8*8 = first 64 SVDs.
>> +	 */
>> +	if (WARN_ON_ONCE(map_len > 8))
>> +		map_len = 8;
>> +
>> +	for (count = 0; count < map_len; count++)
>> +		map |= (u64)db[2 + count] << (8 * count);
>> +
>> +	if (map)
>> +		info->color_formats |= DRM_COLOR_FORMAT_YCRCB420;
>> +
>> +	hdmi->y420_cmdb_map = map;
>> +}
>> +
>>   static int
>>   add_cea_modes(struct drm_connector *connector, struct edid *edid)
>>   {
>> @@ -3522,10 +3663,17 @@ add_cea_modes(struct drm_connector *connector, struct edid *edid)
>>   				video = db + 1;
>>   				video_len = dbl;
>>   				modes += do_cea_modes(connector, video, dbl);
>> -			}
>> -			else if (cea_db_is_hdmi_vsdb(db)) {
>> +			} else if (cea_db_is_hdmi_vsdb(db)) {
>>   				hdmi = db;
>>   				hdmi_len = dbl;
>> +			} else if (cea_db_is_y420vdb(db) &&
>> +				   connector->ycbcr_420_allowed) {
>> +				const u8 *vdb420 = &db[2];
>> +
>> +				/* Add 4:2:0(only) modes present in EDID */
>> +				modes += do_y420vdb_modes(connector,
>> +							  vdb420,
>> +							  dbl - 1);
>>   			}
>>   		}
>>   	}
>> @@ -4206,6 +4354,8 @@ static void drm_parse_cea_ext(struct drm_connector *connector,
>>   			drm_parse_hdmi_vsdb_video(connector, db);
>>   		if (cea_db_is_hdmi_forum_vsdb(db))
>>   			drm_parse_hdmi_forum_vsdb(connector, db);
>> +		if (cea_db_is_y420cmdb(db))
>> +			drm_parse_y420cmdb_bitmap(connector, db);
>>   	}
>>   }
>>   
>> @@ -4460,6 +4610,7 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
>>   	num_modes += add_cea_modes(connector, edid);
>>   	num_modes += add_alternate_cea_modes(connector, edid);
>>   	num_modes += add_displayid_detailed_modes(connector, edid);
>> +
>>   	if (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF)
>>   		num_modes += add_inferred_modes(connector, edid);
>>   
>> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
>> index 7493fd3..ce2212d 100644
>> --- a/include/drm/drm_connector.h
>> +++ b/include/drm/drm_connector.h
>> @@ -137,6 +137,25 @@ struct drm_scdc {
>>   struct drm_hdmi_info {
>>   	/** @scdc: sink's scdc support and capabilities */
>>   	struct drm_scdc scdc;
>> +
>> +	/**
>> +	 * @y420_vdb_modes: bitmap of modes which can support ycbcr420
>> +	 * output only (not normal RGB/YCBCR444/422 outputs). There are total
>> +	 * 107 VICs defined by CEA-861-F spec, so the size is 128 bits to map
>> +	 * upto 128 VICs;
>> +	 */
>> +	unsigned long y420_vdb_modes[BITS_TO_LONGS(128)];
>> +
>> +	/**
>> +	 * @y420_cmdb_modes: bitmap of modes which can support ycbcr420
>> +	 * output also, along with normal HDMI outputs. There are total 107
>> +	 * VICs defined by CEA-861-F spec, so the size is 128 bits to map upto
>> +	 * 128 VICs;
>> +	 */
>> +	unsigned long y420_cmdb_modes[BITS_TO_LONGS(128)];
>> +
>> +	/** @y420_cmdb_map: bitmap of SVD index, to extraxt vcb modes */
>> +	unsigned long y420_cmdb_map;
> u64, otherwise it's busted on 32bit machines.
Got it.
>
> Mostl this looks pretty good. I think the main problem is the lack of
> mode validation that would reject the 4:2:0 only modes if not supported
> by the driver/device. I guess that's in a later patch?
Yep, its the next patch in the series.
>   If so we need to
> reorder the series a bit to avoid regeressions.
That patch uses parameters added in this patch, to detect the 4:2:0 only 
modes. So cant make it before this patch.
Let me see what best can I do on the reordering.

- Shashank
>>   };
>>   
>>   /**
>> @@ -200,6 +219,7 @@ struct drm_display_info {
>>   #define DRM_COLOR_FORMAT_RGB444		(1<<0)
>>   #define DRM_COLOR_FORMAT_YCRCB444	(1<<1)
>>   #define DRM_COLOR_FORMAT_YCRCB422	(1<<2)
>> +#define DRM_COLOR_FORMAT_YCRCB420	(1<<3)
>>   
>>   	/**
>>   	 * @color_formats: HDMI Color formats, selects between RGB and YCrCb
>> -- 
>> 2.7.4

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

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [RESEND-CI v4 05/15] drm/edid: parse ycbcr 420 deep color information
  2017-06-27 11:53   ` Ville Syrjälä
@ 2017-06-30  5:20     ` Sharma, Shashank
  0 siblings, 0 replies; 58+ messages in thread
From: Sharma, Shashank @ 2017-06-30  5:20 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, Jose Abreu, dri-devel

Regards

Shashank


On 6/27/2017 5:23 PM, Ville Syrjälä wrote:
> On Wed, Jun 21, 2017 at 04:04:03PM +0530, Shashank Sharma wrote:
>> CEA-861-F spec adds ycbcr420 deep color support information
>> in hf-vsdb block. This patch extends the existing hf-vsdb parsing
>> function by adding parsing of ycbcr420 deep color support from the
>> EDID and adding it into display information stored.
>>
>> V2: Rebase
>> V3: Rebase
>> V4: Moved definition of y420_dc_modes into this patch, where its used
>>      (Ville)
>>
>> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> Cc: Jose Abreu <joabreu@synopsys.com>
>> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
>> ---
>>   drivers/gpu/drm/drm_edid.c  | 15 +++++++++++++++
>>   include/drm/drm_connector.h |  3 +++
>>   include/drm/drm_edid.h      |  5 +++++
>>   3 files changed, 23 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
>> index 8c7e73b..b4583f6 100644
>> --- a/drivers/gpu/drm/drm_edid.c
>> +++ b/drivers/gpu/drm/drm_edid.c
>> @@ -4196,6 +4196,19 @@ drm_default_rgb_quant_range(const struct drm_display_mode *mode)
>>   }
>>   EXPORT_SYMBOL(drm_default_rgb_quant_range);
>>   
>> +static void drm_parse_ycbcr420_deep_color_info(struct drm_connector *connector,
>> +					     const u8 *db)
>> +{
>> +	struct drm_hdmi_info *info = &connector->display_info.hdmi;
>> +
>> +	if (db[7] & DRM_EDID_YCBCR420_DC_48)
>> +		info->y420_dc_modes |= DRM_EDID_YCBCR420_DC_48;
>> +	if (db[7] & DRM_EDID_YCBCR420_DC_36)
>> +		info->y420_dc_modes |= DRM_EDID_YCBCR420_DC_36;
>> +	if (db[7] & DRM_EDID_YCBCR420_DC_30)
>> +		info->y420_dc_modes |= DRM_EDID_YCBCR420_DC_30;
> y420_dc_modes = db[7] & (...);
>
> will do if you plan to just copy the bits over.
Yep, that's a good idea.
Shashank
>> +}
>> +
>>   static void drm_parse_hdmi_forum_vsdb(struct drm_connector *connector,
>>   				 const u8 *hf_vsdb)
>>   {
>> @@ -4236,6 +4249,8 @@ static void drm_parse_hdmi_forum_vsdb(struct drm_connector *connector,
>>   				scdc->scrambling.low_rates = true;
>>   		}
>>   	}
>> +
>> +	drm_parse_ycbcr420_deep_color_info(connector, hf_vsdb);
>>   }
>>   
>>   static void drm_parse_hdmi_deep_color_info(struct drm_connector *connector,
>> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
>> index ce2212d..1305fe9 100644
>> --- a/include/drm/drm_connector.h
>> +++ b/include/drm/drm_connector.h
>> @@ -156,6 +156,9 @@ struct drm_hdmi_info {
>>   
>>   	/** @y420_cmdb_map: bitmap of SVD index, to extraxt vcb modes */
>>   	unsigned long y420_cmdb_map;
>> +
>> +	/** @y420_dc_modes: bitmap of deep color support index */
>> +	u8 y420_dc_modes;
>>   };
>>   
>>   /**
>> diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
>> index 89c0062..d4ff17c 100644
>> --- a/include/drm/drm_edid.h
>> +++ b/include/drm/drm_edid.h
>> @@ -213,6 +213,11 @@ struct detailed_timing {
>>   #define DRM_EDID_HDMI_DC_30               (1 << 4)
>>   #define DRM_EDID_HDMI_DC_Y444             (1 << 3)
>>   
>> +/* YCBCR 420 deep color modes */
>> +#define DRM_EDID_YCBCR420_DC_48		  (1 << 6)
>> +#define DRM_EDID_YCBCR420_DC_36		  (1 << 5)
>> +#define DRM_EDID_YCBCR420_DC_30		  (1 << 4)
>> +
>>   /* ELD Header Block */
>>   #define DRM_ELD_HEADER_BLOCK_SIZE	4
>>   
>> -- 
>> 2.7.4

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

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [RESEND-CI v4 06/15] drm/edid: parse sink information before CEA blocks
  2017-06-27 11:55   ` Ville Syrjälä
@ 2017-06-30  5:22     ` Sharma, Shashank
  2017-06-30 11:46       ` Ville Syrjälä
  0 siblings, 1 reply; 58+ messages in thread
From: Sharma, Shashank @ 2017-06-30  5:22 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, dri-devel

Regards

Shashank


On 6/27/2017 5:25 PM, Ville Syrjälä wrote:
> On Wed, Jun 21, 2017 at 04:04:04PM +0530, Shashank Sharma wrote:
>> CEA-861-F adds ycbcr capability map block, for HDMI 2.0 sinks.
>> This block contains a map of indexes of CEA modes, which can
>> support YCBCR 420 output also. To avoid multiple parsing of same
>> CEA block, let's parse the sink information and get this map, before
>> parsing CEA modes.
>>
>> This patch moves the call to drm_add_display_info function, before the
>> mode parsing block.
>>
>> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
>> ---
>>   drivers/gpu/drm/drm_edid.c | 9 +++++++--
>>   1 file changed, 7 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
>> index b4583f6..42934b2 100644
>> --- a/drivers/gpu/drm/drm_edid.c
>> +++ b/drivers/gpu/drm/drm_edid.c
>> @@ -4605,6 +4605,13 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
>>   	quirks = edid_get_quirks(edid);
>>   
>>   	/*
>> +	 * CEA-861-F adds ycbcr capability map block, for HDMI 2.0 sinks.
>> +	 * To avoid multiple parsing of same block, lets parse that map
>> +	 * from sink info, before parsing CEA modes.
>> +	 */
>> +	drm_add_display_info(connector, edid);
>> +
> This patch should come before the 4:2:0 mode parsing, no?
Dint you ask me to move it later (in the previous series comments), for 
git-bisect regression type of changes ?
> Otherwise I think this should be fine so
> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Thanks.
>
>> +	/*
>>   	 * EDID spec says modes should be preferred in this order:
>>   	 * - preferred detailed mode
>>   	 * - other detailed modes from base block
>> @@ -4632,8 +4639,6 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
>>   	if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75))
>>   		edid_fixup_preferred(connector, quirks);
>>   
>> -	drm_add_display_info(connector, edid);
>> -
>>   	if (quirks & EDID_QUIRK_FORCE_6BPC)
>>   		connector->display_info.bpc = 6;
>>   
>> -- 
>> 2.7.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [PATCH v5 7/7] drm: create hdmi output property
  2017-06-27 12:14   ` Ville Syrjälä
@ 2017-06-30  5:43     ` Sharma, Shashank
  0 siblings, 0 replies; 58+ messages in thread
From: Sharma, Shashank @ 2017-06-30  5:43 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: Daniel Vetter, intel-gfx, Jose Abreu, dri-devel

Regards

Shashank


On 6/27/2017 5:44 PM, Ville Syrjälä wrote:
> On Wed, Jun 21, 2017 at 04:04:13PM +0530, Shashank Sharma wrote:
>> HDMI displays can support various output types, based on
>> the color space and subsampling type. The possible
>> outputs from a HDMI 2.0 monitor could be:
>>   - RGB
>>   - YCBCR 444
>>   - YCBCR 422
>>   - YCBCR 420
>>
>> This patch adds a drm property "hdmi_output_format", using which,
>> a user can specify its preference, for the HDMI output type. The
>> output type enums are similar to the mentioned outputs above. To
>> handle various subsampling of YCBCR output types, this property
>> allows two special cases:
>>   - DRM_HDMI_OUTPUT_YCBCR_HQ
>>     This indicates preferred output should be YCBCR output, with highest
>>     subsampling rate by the source/sink, which can be typically:
>>   	- ycbcr444
>>   	- ycbcr422
>>   	- ycbcr420
>>   - DRM_HDMI_OUTPUT_YCBCR_LQ
>>     This indicates preferred output should be YCBCR output, with lowest
>>     subsampling rate supported by source/sink, which can be:
>>   	- ycbcr420
>>   	- ycbcr422
>>   	- ycbcr444
> I think we'll eventually need something more thorough than this to
> allow full control over the AVI infoframe/MSA MISC/VSC SDP colormietry
> stuff.
>
> So I think we need to control at least these things:
> - max bpc (some people seem to have some real needs to avoid deep color)
> - rgb->ycbcr conversion (yes/no)
> - ycbcr subsampling for the conversion and infoframe
> - ycbcr encoding for the conversion and infoframe
> - infoframe colorimetry
>
> I've not really figured out how we'll tie all that together in a way
> that doesn't get super confusing.
I think we will over complicate stuff, if we try to address everything 
in this same series. My high level vision for the
work was:
- Let this series just deals with HDMI output, and handles the output 
color model only, using the AVI IF (which is being handled already in 
the next patch)
- The BT2020 patch series will (should) take care of everything which is 
related to output color spaces (including AVI IF)
As this series deals with stuff which comes into picture post blending, 
it should focus on just the output color model and sub-sampling, which 
its doing
using the HDMI_OUTPUT property introduced.
But at the same time I agree, that max_bpc is something we should 
introduce at the DRM level, instead of keeping it at driver level.
>
> One idea might be that the infoframe stuff is totally independent of
> the rest (ie. we'll define just an enum property for the infoframe
> stuff in say this way:
> "Automatic", "sRGB", "AdobeRGB", "YCbCr BT.601 4:2:2",
> "xvYCC709 4:4:4", etc.
> So none of the YCbCr output properties would actually affect the
> infoframe unless the user has selected the default "Automatic" mode.
> That should allow the user to output any kind of data through the pipe
> in a pass through fashion (or with manually set up gamma/degamma/csc).
> And configuring the inforame property would not affect the data passing
> through the pipe in any way.
>
> But I probably need to think more about this. So for now I think I'll
> just want to get the automagic "use YCbCr 4:2:0 if we must" thing
> working without any new properties getting in the way. We just have
> to keep in mind that this automagic conversion thing must still work
> when we add some properties, but I think that can generally be achieved
> with some "Automatic" default property values.
Ok, I think I am getting the bigger picture now. Yes, I agree, it would 
be pretty cool to have something
like this, which makes pipe completely independent in terms of what it 
can produce vs what it is
informing via IF. But need to really sit and think about this well.

- Shashank
>
>> Default value of the property is set to 0 = RGB, so no changes if you
>> dont set the property.
>>
>> PS: While doing modeset for YCBCR 420 only modes, this property is
>>      ignored, as those timings can be supported only in YCBCR 420
>>      output mode.
>>
>> V2: Added description for the new variable to address build warning
>> V3: Rebase
>> V4: Rebase
>> V5: Added get_property counterpart to fix IGT BAT failures
>>
>> Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
>> Cc: Jose Abreu <joabreu@synopsys.com>
>> Cc: Daniel Vetter <daniel.vetter@intel.com>
>> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
>> ---
>>   drivers/gpu/drm/drm_atomic.c        |  4 ++++
>>   drivers/gpu/drm/drm_atomic_helper.c |  4 ++++
>>   drivers/gpu/drm/drm_connector.c     | 32 ++++++++++++++++++++++++++++++++
>>   include/drm/drm_connector.h         | 18 ++++++++++++++++++
>>   include/drm/drm_mode_config.h       |  5 +++++
>>   5 files changed, 63 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
>> index 77dcef0..ea90f8e 100644
>> --- a/drivers/gpu/drm/drm_atomic.c
>> +++ b/drivers/gpu/drm/drm_atomic.c
>> @@ -1192,6 +1192,8 @@ int drm_atomic_connector_set_property(struct drm_connector *connector,
>>   		state->picture_aspect_ratio = val;
>>   	} else if (property == connector->scaling_mode_property) {
>>   		state->scaling_mode = val;
>> +	} else if (property == config->hdmi_output_property) {
>> +		state->hdmi_output = val;
>>   	} else if (connector->funcs->atomic_set_property) {
>>   		return connector->funcs->atomic_set_property(connector,
>>   				state, property, val);
>> @@ -1272,6 +1274,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector,
>>   		*val = state->picture_aspect_ratio;
>>   	} else if (property == connector->scaling_mode_property) {
>>   		*val = state->scaling_mode;
>> +	} else if (property == config->hdmi_output_property) {
>> +		*val = state->hdmi_output;
>>   	} else if (connector->funcs->atomic_get_property) {
>>   		return connector->funcs->atomic_get_property(connector,
>>   				state, property, val);
>> diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
>> index 86d3093..1356b3f 100644
>> --- a/drivers/gpu/drm/drm_atomic_helper.c
>> +++ b/drivers/gpu/drm/drm_atomic_helper.c
>> @@ -637,6 +637,10 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
>>   			if (old_connector_state->link_status !=
>>   			    new_connector_state->link_status)
>>   				new_crtc_state->connectors_changed = true;
>> +
>> +			if (old_connector_state->hdmi_output !=
>> +			    new_connector_state->hdmi_output)
>> +				new_crtc_state->connectors_changed = true;
>>   		}
>>   
>>   		if (funcs->atomic_check)
>> diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
>> index 5cd61af..f3c5928 100644
>> --- a/drivers/gpu/drm/drm_connector.c
>> +++ b/drivers/gpu/drm/drm_connector.c
>> @@ -227,6 +227,11 @@ int drm_connector_init(struct drm_device *dev,
>>   					      config->edid_property,
>>   					      0);
>>   
>> +	if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL)
>> +		drm_object_attach_property(&connector->base,
>> +					   config->hdmi_output_property,
>> +					   0);
>> +
>>   	drm_object_attach_property(&connector->base,
>>   				      config->dpms_property, 0);
>>   
>> @@ -617,6 +622,26 @@ static const struct drm_prop_enum_list drm_link_status_enum_list[] = {
>>   };
>>   DRM_ENUM_NAME_FN(drm_get_link_status_name, drm_link_status_enum_list)
>>   
>> +static const struct drm_prop_enum_list drm_hdmi_output_enum_list[] = {
>> +	{ DRM_HDMI_OUTPUT_DEFAULT_RGB, "output_rgb" },
>> +	{ DRM_HDMI_OUTPUT_YCBCR444, "output_ycbcr444" },
>> +	{ DRM_HDMI_OUTPUT_YCBCR422, "output_ycbcr422" },
>> +	{ DRM_HDMI_OUTPUT_YCBCR420, "output_ycbcr420" },
>> +	{ DRM_HDMI_OUTPUT_YCBCR_HQ, "output_ycbcr_high_subsampling" },
>> +	{ DRM_HDMI_OUTPUT_YCBCR_LQ, "output_ycbcr_low_subsampling" },
>> +	{ DRM_HDMI_OUTPUT_INVALID, "invalid_output" },
>> +};
>> +
>> +/**
>> + * drm_get_hdmi_output_name - return a string for a given hdmi output enum
>> + * @type: enum of output type
>> + */
>> +const char *drm_get_hdmi_output_name(enum drm_hdmi_output_type type)
>> +{
>> +	return drm_hdmi_output_enum_list[type].name;
>> +}
>> +EXPORT_SYMBOL(drm_get_hdmi_output_name);
>> +
>>   /**
>>    * drm_display_info_set_bus_formats - set the supported bus formats
>>    * @info: display info to store bus formats in
>> @@ -789,6 +814,13 @@ int drm_connector_create_standard_properties(struct drm_device *dev)
>>   		return -ENOMEM;
>>   	dev->mode_config.link_status_property = prop;
>>   
>> +	prop = drm_property_create_enum(dev, 0, "hdmi_output_format",
>> +					drm_hdmi_output_enum_list,
>> +					ARRAY_SIZE(drm_hdmi_output_enum_list));
>> +	if (!prop)
>> +		return -ENOMEM;
>> +	dev->mode_config.hdmi_output_property = prop;
>> +
>>   	return 0;
>>   }
>>   
>> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
>> index 1305fe9..5ba1f32 100644
>> --- a/include/drm/drm_connector.h
>> +++ b/include/drm/drm_connector.h
>> @@ -321,6 +321,17 @@ struct drm_tv_connector_state {
>>   	unsigned int hue;
>>   };
>>   
>> +/* HDMI output pixel format */
>> +enum drm_hdmi_output_type {
>> +	DRM_HDMI_OUTPUT_DEFAULT_RGB, /* default RGB */
>> +	DRM_HDMI_OUTPUT_YCBCR444, /* YCBCR 444 */
>> +	DRM_HDMI_OUTPUT_YCBCR422, /* YCBCR 422 */
>> +	DRM_HDMI_OUTPUT_YCBCR420, /* YCBCR 420 */
>> +	DRM_HDMI_OUTPUT_YCBCR_HQ, /* Highest subsampled YUV */
>> +	DRM_HDMI_OUTPUT_YCBCR_LQ, /* Lowest subsampled YUV */
>> +	DRM_HDMI_OUTPUT_INVALID, /* Guess what ? */
>> +};
>> +
>>   /**
>>    * struct drm_connector_state - mutable connector state
>>    * @connector: backpointer to the connector
>> @@ -365,6 +376,12 @@ struct drm_connector_state {
>>   	 * upscaling, mostly used for built-in panels.
>>   	 */
>>   	unsigned int scaling_mode;
>> +
>> +	/**
>> +	 * @hdmi_output: Connector property to control the
>> +	 * HDMI output mode (RGB/YCBCR444/422/420).
>> +	 */
>> +	enum drm_hdmi_output_type hdmi_output;
>>   };
>>   
>>   /**
>> @@ -993,6 +1010,7 @@ static inline void drm_connector_unreference(struct drm_connector *connector)
>>   
>>   const char *drm_get_connector_status_name(enum drm_connector_status status);
>>   const char *drm_get_subpixel_order_name(enum subpixel_order order);
>> +const char *drm_get_hdmi_output_name(enum drm_hdmi_output_type type);
>>   const char *drm_get_dpms_name(int val);
>>   const char *drm_get_dvi_i_subconnector_name(int val);
>>   const char *drm_get_dvi_i_select_name(int val);
>> diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h
>> index 4298171..1887261 100644
>> --- a/include/drm/drm_mode_config.h
>> +++ b/include/drm/drm_mode_config.h
>> @@ -740,6 +740,11 @@ struct drm_mode_config {
>>   	 * the position of the output on the host's screen.
>>   	 */
>>   	struct drm_property *suggested_y_property;
>> +	/**
>> +	 * @hdmi_output_property: output pixel format from HDMI display
>> +	 * Default is set for RGB
>> +	 */
>> +	struct drm_property *hdmi_output_property;
>>   
>>   	/* dumb ioctl parameters */
>>   	uint32_t preferred_depth, prefer_shadow;
>> -- 
>> 2.7.4

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

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [RESEND-CI v4 11/15] drm/i915: prepare scaler for YCBCR420 modeset
  2017-06-27 12:16   ` Ander Conselvan De Oliveira
@ 2017-06-30  5:50     ` Sharma, Shashank
  2017-06-30 11:34       ` Ander Conselvan De Oliveira
  0 siblings, 1 reply; 58+ messages in thread
From: Sharma, Shashank @ 2017-06-30  5:50 UTC (permalink / raw)
  To: Ander Conselvan De Oliveira, dri-devel, intel-gfx, ville.syrjala

Regards

Shashank


On 6/27/2017 5:46 PM, Ander Conselvan De Oliveira wrote:
> On Wed, 2017-06-21 at 16:04 +0530, Shashank Sharma wrote:
>> To get a YCBCR420 output from intel platforms, we need one
>> scaler to scale down YCBCR444 samples to YCBCR420 samples.
>>
>> This patch:
>> - Does scaler allocation for HDMI ycbcr420 outputs.
>> - Programs PIPE_MISC register for ycbcr420 output.
>> - Adds a new scaler user "HDMI output" to plug-into existing
>>    scaler framework. This output type is identified using bit
>>    30 of the scaler users bitmap.
>>
>> V2: rebase
>> V3: rebase
>> V4: rebase
>>
>> Cc: Ville Syrjala <ville.syrjala@linux.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_atomic.c  |  6 ++++++
>>   drivers/gpu/drm/i915/intel_display.c | 26 ++++++++++++++++++++++++++
>>   drivers/gpu/drm/i915/intel_drv.h     | 10 +++++++++-
>>   drivers/gpu/drm/i915/intel_hdmi.c    | 10 ++++++++++
>>   drivers/gpu/drm/i915/intel_panel.c   |  3 ++-
>>   5 files changed, 53 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
>> index 36d4e63..a8c9ac5 100644
>> --- a/drivers/gpu/drm/i915/intel_atomic.c
>> +++ b/drivers/gpu/drm/i915/intel_atomic.c
>> @@ -264,6 +264,12 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv,
>>   
>>   			/* panel fitter case: assign as a crtc scaler */
>>   			scaler_id = &scaler_state->scaler_id;
>> +		} else if (i == SKL_HDMI_OUTPUT_INDEX) {
>> +			name = "HDMI-OUTPUT";
>> +			idx = intel_crtc->base.base.id;
>> +
>> +			/* hdmi output case: needs a pipe scaler */
>> +			scaler_id = &scaler_state->scaler_id;
>>   		} else {
>>   			name = "PLANE";
>>   
>> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
>> index da29536..983f581 100644
>> --- a/drivers/gpu/drm/i915/intel_display.c
>> +++ b/drivers/gpu/drm/i915/intel_display.c
>> @@ -4626,6 +4626,11 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
>>   	 */
>>   	need_scaling = src_w != dst_w || src_h != dst_h;
>>   
>> +	if (crtc_state->hdmi_output == DRM_HDMI_OUTPUT_YCBCR420
>> +		&& scaler_user == SKL_HDMI_OUTPUT_INDEX)
> Is it really necessary to check for both? If it is, what's the point of creating
> SKL_HDMI_OUTPUT_INDEX?
Yes, else this will affect scaler update for planes, as this function 
gets called to update the plane scalers too, at that time the output 
will be still valid (as its at CRTC level), but the
scaler user would be different.
>
>> +		/* YCBCR 444 -> 420 conversion needs a scaler */
>> +		need_scaling = true;
>> +
>>   	/*
>>   	 * if plane is being disabled or scaler is no more required or force detach
>>   	 *  - free scaler binded to this plane/crtc
>> @@ -4673,6 +4678,26 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
>>   }
>>   
>>   /**
>> + * skl_update_scaler_hdmi_output - Stages update to scaler state for HDMI.
>> + * HDMI YCBCR 420 output needs a scaler, for downsampling.
>> + *
>> + * @state: crtc's scaler state
>> + *
>> + * Return
>> + *     0 - scaler_usage updated successfully
>> + *    error - requested scaling cannot be supported or other error condition
>> + */
>> +int skl_update_scaler_crtc_hdmi_output(struct intel_crtc_state *state)
>> +{
>> +	const struct drm_display_mode *mode = &state->base.adjusted_mode;
>> +
>> +	return skl_update_scaler(state, !state->base.active,
>> +		SKL_HDMI_OUTPUT_INDEX, &state->scaler_state.scaler_id,
>> +		state->pipe_src_w, state->pipe_src_h,
>> +		mode->crtc_hdisplay, mode->crtc_vdisplay);
>> +}
>> +
>> +/**
>>    * skl_update_scaler_crtc - Stages update to scaler state for a given crtc.
>>    *
>>    * @state: crtc's scaler state
>> @@ -8058,6 +8083,7 @@ static void haswell_set_pipemisc(struct drm_crtc *crtc)
>>   {
>>   	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
>>   	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>> +	enum drm_hdmi_output_type hdmi_out = intel_crtc->config->hdmi_output;
>>   
>>   	if (IS_BROADWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 9) {
>>   		u32 val = 0;
>> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
>> index 38fe56c..2206aa8 100644
>> --- a/drivers/gpu/drm/i915/intel_drv.h
>> +++ b/drivers/gpu/drm/i915/intel_drv.h
>> @@ -471,7 +471,8 @@ struct intel_crtc_scaler_state {
>>   	 *
>>   	 *     If a bit is set, a user is using a scaler.
>>   	 *     Here user can be a plane or crtc as defined below:
>> -	 *       bits 0-30 - plane (bit position is index from drm_plane_index)
>> +	 *       bits 0-29 - plane (bit position is index from drm_plane_index)
>> +	 *       bit 30    - hdmi output
>>   	 *       bit 31    - crtc
>>   	 *
>>   	 * Instead of creating a new index to cover planes and crtc, using
>> @@ -484,6 +485,12 @@ struct intel_crtc_scaler_state {
>>   	 * avilability.
>>   	 */
>>   #define SKL_CRTC_INDEX 31
>> +
>> +	/*
>> +	 * HDMI YCBCR 420 output consume a scaler. So adding a user
>> +	 * for HDMI output 420 requirement.
>> +	 */
>> +#define SKL_HDMI_OUTPUT_INDEX 30
> I'm not convinced about this. The scaler is still used as a pipe scaler and the
> patch even adds a call intel_pch_panel_fitting().
This is a special mode usage of scalar defined in the bspec, when we 
want to run the scalar into 5x3 auto mode for YCBCR444->YCBCR420 scale down.
It can be used only when the PIPE_MISC is also programmed to act 
accordingly. So this is different from using it as a panel fitter, and 
that's why added
a new scalar user all together.
>
>>   	unsigned scaler_users;
>>   
>>   	/* scaler used by crtc for panel fitting purpose */
>> @@ -1481,6 +1488,7 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode,
>>   				 struct intel_crtc_state *pipe_config);
>>   
>>   int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state);
>> +int skl_update_scaler_crtc_hdmi_output(struct intel_crtc_state *state);
>>   int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state);
>>   
>>   static inline u32 intel_plane_ggtt_offset(const struct intel_plane_state *state)
>> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
>> index 22da5cd..8d5aa1e 100644
>> --- a/drivers/gpu/drm/i915/intel_hdmi.c
>> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
>> @@ -1415,6 +1415,7 @@ intel_hdmi_compute_ycbcr_config(struct drm_connector_state *conn_state,
>>   	}
>>   
>>   	if (type == DRM_HDMI_OUTPUT_YCBCR420) {
>> +		struct intel_crtc *intel_crtc = to_intel_crtc(conn_state->crtc);
>>   
>>   		/* YCBCR420 TMDS rate requirement is half the pixel clock */
>>   		config->hdmi_output = DRM_HDMI_OUTPUT_YCBCR420;
>> @@ -1422,6 +1423,15 @@ intel_hdmi_compute_ycbcr_config(struct drm_connector_state *conn_state,
>>   		*clock_12bpc /= 2;
>>   		*clock_8bpc /= 2;
>>   
>> +		/* YCBCR 420 output conversion needs a scaler */
>> +		if (skl_update_scaler_crtc_hdmi_output(config)) {
>> +			DRM_ERROR("Scaler allocation for output failed\n");
>> +			return DRM_HDMI_OUTPUT_INVALID;
>> +		}
>> +
>> +		/* Bind this scaler to pipe */
>> +		intel_pch_panel_fitting(intel_crtc, config,
>> +					DRM_MODE_SCALE_FULLSCREEN);
>>   	}
>>   
>>   	/* Encoder is capable of this output, lets commit to CRTC */
>> diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
>> index 96c2cbd..b6a32c4 100644
>> --- a/drivers/gpu/drm/i915/intel_panel.c
>> +++ b/drivers/gpu/drm/i915/intel_panel.c
>> @@ -110,7 +110,8 @@ intel_pch_panel_fitting(struct intel_crtc *intel_crtc,
>>   
>>   	/* Native modes don't need fitting */
>>   	if (adjusted_mode->crtc_hdisplay == pipe_config->pipe_src_w &&
>> -	    adjusted_mode->crtc_vdisplay == pipe_config->pipe_src_h)
>> +	    adjusted_mode->crtc_vdisplay == pipe_config->pipe_src_h &&
>> +	    pipe_config->hdmi_output != DRM_HDMI_OUTPUT_YCBCR420)
> I don't like that the knowledge that YCBCR420 needs the scaler is spread
> everywhere, including this function that should only deal with panel fitting. I
> would rather add a force parameter to intel_pch_panel_fitting() and
> skl_update_scaler() that would mean setup the scaler even if looks like it's not
> necessary. That way the hdmi code would just call them with force enabled,
> without sprinkling "hdmi_output == YCBCR420" everywhere.
As explained in the comment above, its special case usage of pipe 
scalar, and that's why being checked specifically.

- Shashank
>
> Ander
>
>>   		goto done;
>>   
>>   	switch (fitting_mode) {

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

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [RESEND-CI v4 13/15] drm/i915: prepare csc unit for YCBCR HDMI output
  2017-06-29 12:08   ` Ander Conselvan De Oliveira
@ 2017-06-30  6:03     ` Sharma, Shashank
  2017-06-30 10:57       ` Ander Conselvan De Oliveira
  0 siblings, 1 reply; 58+ messages in thread
From: Sharma, Shashank @ 2017-06-30  6:03 UTC (permalink / raw)
  To: Ander Conselvan De Oliveira, dri-devel, intel-gfx, ville.syrjala
  Cc: Daniel Vetter

Regards

Shashank


On 6/29/2017 5:38 PM, Ander Conselvan De Oliveira wrote:
> On Wed, 2017-06-21 at 16:04 +0530, Shashank Sharma wrote:
>> To support ycbcr HDMI output, we need a pipe CSC block to
>> do the RGB->YCBCR conversion, as the blender output is in RGB.
>>
>> Current Intel platforms have only one pipe CSC unit, so
>> we can either do color correction using it, or we can perform
>> RGB->YCBCR conversion.
>>
>> This function adds a csc handler, to perform RGB->YCBCR conversion
>> as per recommended spec values.
> Please do a full reference to the "spec", including name, version and relevant
> section.
Sure, will add more details.
>> V2: Rebase
>> V3: Rebase
>> V4: Rebase
>>
>> 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_color.c   | 47 +++++++++++++++++++++++++++++++++++-
>>   drivers/gpu/drm/i915/intel_display.c | 32 ++++++++++++++++++++++++
>>   2 files changed, 78 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/i915/intel_color.c b/drivers/gpu/drm/i915/intel_color.c
>> index 306c6b0..12d5f21 100644
>> --- a/drivers/gpu/drm/i915/intel_color.c
>> +++ b/drivers/gpu/drm/i915/intel_color.c
>> @@ -41,6 +41,19 @@
>>   
>>   #define LEGACY_LUT_LENGTH		(sizeof(struct drm_color_lut) * 256)
>>   
>> +/* Post offset values for RGB->YCBCR conversion */
>> +#define POSTOFF_RGB_TO_YUV_HI 0x800
>> +#define POSTOFF_RGB_TO_YUV_ME 0x100
>> +#define POSTOFF_RGB_TO_YUV_LO 0x800
>> +
>> +/* Direct spec values for RGB->YUV conversion matrix */
>> +#define CSC_RGB_TO_YUV_RU_GU 0x2ba809d8
>> +#define CSC_RGB_TO_YUV_BU 0x37e80000
>> +#define CSC_RGB_TO_YUV_RY_GY 0x1e089cc0
>> +#define CSC_RGB_TO_YUV_BY 0xb5280000
>> +#define CSC_RGB_TO_YUV_RV_GV 0xbce89ad8
>> +#define CSC_RGB_TO_YUV_BV 0x1e080000
>> +
> Not a big fan or hardcoding this in the register format. We already have the
> code for converting a number to the right format for the register in
> i915_load_csc_matrix(). I think it would make more sense to extract the code
> that actually writes the matrix out of that function, so it would just
> unconditionally use a matrix and coefficients passed as arguments. Then the
> values above would be defined in the format expected for this new function.
Actually I had a small discussion on this with Ville, and we think that 
the current CSC multiplication code is not correct.
So if CTM and limited color range is applied together, we might not be 
getting the right values. So not planning to
reuse that code. I think while sending the BT2020 patches, we will add a 
fix for that part too, but right now not working on it.
>>   /*
>>    * Extract the CSC coefficient from a CTM coefficient (in U32.32 fixed point
>>    * format). This macro takes the coefficient we want transformed and the
>> @@ -91,6 +104,35 @@ static void ctm_mult_by_limited(uint64_t *result, int64_t *input)
>>   	}
>>   }
>>   
>> +void i9xx_load_ycbcr_conversion_matrix(struct intel_crtc *intel_crtc)
>> +{
>> +	int pipe = intel_crtc->pipe;
>> +	struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
>> +
>> +	/* We don't use high values for conversion */
>> +	I915_WRITE(PIPE_CSC_PREOFF_HI(pipe), 0);
>> +	I915_WRITE(PIPE_CSC_PREOFF_ME(pipe), 0);
>> +	I915_WRITE(PIPE_CSC_PREOFF_LO(pipe), 0);
>> +
>> +	/* Program direct spec values for RGB to YCBCR conversion matrix */
>> +	I915_WRITE(PIPE_CSC_COEFF_RU_GU(pipe), CSC_RGB_TO_YUV_RU_GU);
>> +	I915_WRITE(PIPE_CSC_COEFF_BU(pipe), CSC_RGB_TO_YUV_BU);
>> +
>> +	I915_WRITE(PIPE_CSC_COEFF_RY_GY(pipe), CSC_RGB_TO_YUV_RY_GY);
>> +	I915_WRITE(PIPE_CSC_COEFF_BY(pipe), CSC_RGB_TO_YUV_BY);
>> +
>> +	I915_WRITE(PIPE_CSC_COEFF_RV_GV(pipe), CSC_RGB_TO_YUV_RV_GV);
>> +	I915_WRITE(PIPE_CSC_COEFF_BV(pipe), CSC_RGB_TO_YUV_BV);
>> +
>> +	/* Spec postoffset values */
>> +	I915_WRITE(PIPE_CSC_POSTOFF_HI(pipe), POSTOFF_RGB_TO_YUV_HI);
>> +	I915_WRITE(PIPE_CSC_POSTOFF_ME(pipe), POSTOFF_RGB_TO_YUV_ME);
>> +	I915_WRITE(PIPE_CSC_POSTOFF_LO(pipe), POSTOFF_RGB_TO_YUV_LO);
>> +
>> +	/* CSC mode before gamma */
>> +	I915_WRITE(PIPE_CSC_MODE(pipe), 0);
>> +}
>> +
>>   /* Set up the pipe CSC unit. */
>>   static void i9xx_load_csc_matrix(struct drm_crtc_state *crtc_state)
>>   {
>> @@ -101,7 +143,10 @@ static void i9xx_load_csc_matrix(struct drm_crtc_state *crtc_state)
>>   	uint16_t coeffs[9] = { 0, };
>>   	struct intel_crtc_state *intel_crtc_state = to_intel_crtc_state(crtc_state);
>>   
>> -	if (crtc_state->ctm) {
>> +	if (intel_crtc_state->hdmi_output > DRM_HDMI_OUTPUT_DEFAULT_RGB) {
>> +		i9xx_load_ycbcr_conversion_matrix(intel_crtc);
>> +		return;
>> +	} else if (crtc_state->ctm) {
> Hmm, I'm not sure this is the right place to check for this condition. I mean,
> we shouldn't allow the modeset to happen in this case.
If you please have a look at the intel_crtc_compute_ycbcr_config check 
added in this patch, that's doing the same.
Its not allowing HDMI output conversion and pipe level CTM at the same 
time.
>
>>   		struct drm_color_ctm *ctm =
>>   			(struct drm_color_ctm *)crtc_state->ctm->data;
>>   		uint64_t input[9] = { 0, };
>> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
>> index 71fd19e..96ff2a0 100644
>> --- a/drivers/gpu/drm/i915/intel_display.c
>> +++ b/drivers/gpu/drm/i915/intel_display.c
>> @@ -6261,6 +6261,29 @@ static void intel_crtc_compute_pixel_rate(struct intel_crtc_state *crtc_state)
>>   			ilk_pipe_pixel_rate(crtc_state);
>>   }
>>   
>> +static int intel_crtc_ycbcr_config(struct intel_crtc_state *state)
>> +{
>> +	struct drm_crtc_state *drm_state = &state->base;
>> +	struct drm_i915_private *dev_priv = to_i915(drm_state->crtc->dev);
>> +
>> +	/* YCBCR420 is supported only in HDMI 2.0 controllers */
>> +	if ((state->hdmi_output == DRM_HDMI_OUTPUT_YCBCR420) &&
>> +		!IS_GEMINILAKE(dev_priv)) {
>> +		DRM_ERROR("YCBCR420 output is not supported\n");
>> +		return -EINVAL;
>> +	}
>> +
>> +	/* We need CSC for output conversion from RGB->YCBCR */
>> +	if (drm_state->ctm) {
>> +		DRM_ERROR("YCBCR output and CTM is not possible together\n");
>> +		return -EINVAL;
>> +	}
> Hmm, ok, that's checked here.
:-)
>> +
>> +	DRM_DEBUG_DRIVER("Output %s can be supported\n",
>> +			 drm_get_hdmi_output_name(state->hdmi_output));
>> +	return 0;
>> +}
>> +
>>   static int intel_crtc_compute_config(struct intel_crtc *crtc,
>>   				     struct intel_crtc_state *pipe_config)
>>   {
>> @@ -6290,6 +6313,14 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
>>   		return -EINVAL;
>>   	}
>>   
>> +	/* YCBCR output check */
>> +	if (pipe_config->hdmi_output > DRM_HDMI_OUTPUT_DEFAULT_RGB) {
>> +		if (intel_crtc_ycbcr_config(pipe_config)) {
> You could combine both ifs. Or, even better, just move the first check into the
> caller. I think it would be better to keep it all in one place. I was a bit
> unsure if function did the right thing until I saw how it was called.
Ok, sure.
>
>> +			DRM_ERROR("Cant enable HDMI YCBCR output\n");
>> +			return -EINVAL;
>> +		}
>> +	}
>> +
>>   	/*
>>   	 * Pipe horizontal size must be even in:
>>   	 * - DVO ganged mode
>> @@ -11658,6 +11689,7 @@ intel_modeset_pipe_config(struct drm_crtc *crtc,
>>   			DRM_DEBUG_KMS("Encoder config failure\n");
>>   			goto fail;
>>   		}
>> +
> No need for this.
Got it.
>
>
> Ander
>
>>   	}
>>   
>>   	/* Set default port clock if not overwritten by the encoder. Needs to be

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [RESEND-CI v4 13/15] drm/i915: prepare csc unit for YCBCR HDMI output
  2017-06-30  6:03     ` Sharma, Shashank
@ 2017-06-30 10:57       ` Ander Conselvan De Oliveira
  0 siblings, 0 replies; 58+ messages in thread
From: Ander Conselvan De Oliveira @ 2017-06-30 10:57 UTC (permalink / raw)
  To: Sharma, Shashank, dri-devel, intel-gfx, ville.syrjala; +Cc: Daniel Vetter

On Fri, 2017-06-30 at 11:33 +0530, Sharma, Shashank wrote:
> Regards
> 
> Shashank
> 
> 
> On 6/29/2017 5:38 PM, Ander Conselvan De Oliveira wrote:
> > On Wed, 2017-06-21 at 16:04 +0530, Shashank Sharma wrote:
> > > To support ycbcr HDMI output, we need a pipe CSC block to
> > > do the RGB->YCBCR conversion, as the blender output is in RGB.
> > > 
> > > Current Intel platforms have only one pipe CSC unit, so
> > > we can either do color correction using it, or we can perform
> > > RGB->YCBCR conversion.
> > > 
> > > This function adds a csc handler, to perform RGB->YCBCR conversion
> > > as per recommended spec values.
> > 
> > Please do a full reference to the "spec", including name, version and relevant
> > section.
> 
> Sure, will add more details.
> > > V2: Rebase
> > > V3: Rebase
> > > V4: Rebase
> > > 
> > > 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_color.c   | 47 +++++++++++++++++++++++++++++++++++-
> > >   drivers/gpu/drm/i915/intel_display.c | 32 ++++++++++++++++++++++++
> > >   2 files changed, 78 insertions(+), 1 deletion(-)
> > > 
> > > diff --git a/drivers/gpu/drm/i915/intel_color.c b/drivers/gpu/drm/i915/intel_color.c
> > > index 306c6b0..12d5f21 100644
> > > --- a/drivers/gpu/drm/i915/intel_color.c
> > > +++ b/drivers/gpu/drm/i915/intel_color.c
> > > @@ -41,6 +41,19 @@
> > >   
> > >   #define LEGACY_LUT_LENGTH		(sizeof(struct drm_color_lut) * 256)
> > >   
> > > +/* Post offset values for RGB->YCBCR conversion */
> > > +#define POSTOFF_RGB_TO_YUV_HI 0x800
> > > +#define POSTOFF_RGB_TO_YUV_ME 0x100
> > > +#define POSTOFF_RGB_TO_YUV_LO 0x800
> > > +
> > > +/* Direct spec values for RGB->YUV conversion matrix */
> > > +#define CSC_RGB_TO_YUV_RU_GU 0x2ba809d8
> > > +#define CSC_RGB_TO_YUV_BU 0x37e80000
> > > +#define CSC_RGB_TO_YUV_RY_GY 0x1e089cc0
> > > +#define CSC_RGB_TO_YUV_BY 0xb5280000
> > > +#define CSC_RGB_TO_YUV_RV_GV 0xbce89ad8
> > > +#define CSC_RGB_TO_YUV_BV 0x1e080000
> > > +
> > 
> > Not a big fan or hardcoding this in the register format. We already have the
> > code for converting a number to the right format for the register in
> > i915_load_csc_matrix(). I think it would make more sense to extract the code
> > that actually writes the matrix out of that function, so it would just
> > unconditionally use a matrix and coefficients passed as arguments. Then the
> > values above would be defined in the format expected for this new function.
> 
> Actually I had a small discussion on this with Ville, and we think that 
> the current CSC multiplication code is not correct.
> So if CTM and limited color range is applied together, we might not be 
> getting the right values. So not planning to
> reuse that code. I think while sending the BT2020 patches, we will add a 
> fix for that part too, but right now not working on it.

I wasn't talking about the matrix multiplication, but creating a function to
write any given matrix into the CSC. That way, the above could be hardcoded in a
more human readable format.

This issue is independent from fixing the matrix multiplication. I'm talking
specifically about the code below:

		/*
                 * Convert fixed point S31.32 input to format supported by the
                 * hardware.
                 */
                for (i = 0; i < ARRAY_SIZE(coeffs); i++) {
                        uint64_t abs_coeff = ((1ULL << 63) - 1) & input[i];

                        /*
                         * Clamp input value to min/max supported by
                         * hardware.
                         */
                        abs_coeff = clamp_val(abs_coeff, 0, CTM_COEFF_4_0 - 1);

                        /* sign bit */
                        if (CTM_COEFF_NEGATIVE(input[i]))
                                coeffs[i] |= 1 << 15;

                        if (abs_coeff < CTM_COEFF_0_125)
                                coeffs[i] |= (3 << 12) |
                                        I9XX_CSC_COEFF_FP(abs_coeff, 12);
                        else if (abs_coeff < CTM_COEFF_0_25)
                                coeffs[i] |= (2 << 12) |
                                        I9XX_CSC_COEFF_FP(abs_coeff, 11);
                        else if (abs_coeff < CTM_COEFF_0_5)
                                coeffs[i] |= (1 << 12) |
                                        I9XX_CSC_COEFF_FP(abs_coeff, 10);
                        else if (abs_coeff < CTM_COEFF_1_0)
                                coeffs[i] |= I9XX_CSC_COEFF_FP(abs_coeff, 9);
                        else if (abs_coeff < CTM_COEFF_2_0)
                                coeffs[i] |= (7 << 12) |
                                        I9XX_CSC_COEFF_FP(abs_coeff, 8);
                        else
                                coeffs[i] |= (6 << 12) |
                                        I9XX_CSC_COEFF_FP(abs_coeff, 7);
		}

I'd like to see that and the code that writes the registers reused instead of duplicated.

Ander

> > >   /*
> > >    * Extract the CSC coefficient from a CTM coefficient (in U32.32 fixed point
> > >    * format). This macro takes the coefficient we want transformed and the
> > > @@ -91,6 +104,35 @@ static void ctm_mult_by_limited(uint64_t *result, int64_t *input)
> > >   	}
> > >   }
> > >   
> > > +void i9xx_load_ycbcr_conversion_matrix(struct intel_crtc *intel_crtc)
> > > +{
> > > +	int pipe = intel_crtc->pipe;
> > > +	struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
> > > +
> > > +	/* We don't use high values for conversion */
> > > +	I915_WRITE(PIPE_CSC_PREOFF_HI(pipe), 0);
> > > +	I915_WRITE(PIPE_CSC_PREOFF_ME(pipe), 0);
> > > +	I915_WRITE(PIPE_CSC_PREOFF_LO(pipe), 0);
> > > +
> > > +	/* Program direct spec values for RGB to YCBCR conversion matrix */
> > > +	I915_WRITE(PIPE_CSC_COEFF_RU_GU(pipe), CSC_RGB_TO_YUV_RU_GU);
> > > +	I915_WRITE(PIPE_CSC_COEFF_BU(pipe), CSC_RGB_TO_YUV_BU);
> > > +
> > > +	I915_WRITE(PIPE_CSC_COEFF_RY_GY(pipe), CSC_RGB_TO_YUV_RY_GY);
> > > +	I915_WRITE(PIPE_CSC_COEFF_BY(pipe), CSC_RGB_TO_YUV_BY);
> > > +
> > > +	I915_WRITE(PIPE_CSC_COEFF_RV_GV(pipe), CSC_RGB_TO_YUV_RV_GV);
> > > +	I915_WRITE(PIPE_CSC_COEFF_BV(pipe), CSC_RGB_TO_YUV_BV);
> > > +
> > > +	/* Spec postoffset values */
> > > +	I915_WRITE(PIPE_CSC_POSTOFF_HI(pipe), POSTOFF_RGB_TO_YUV_HI);
> > > +	I915_WRITE(PIPE_CSC_POSTOFF_ME(pipe), POSTOFF_RGB_TO_YUV_ME);
> > > +	I915_WRITE(PIPE_CSC_POSTOFF_LO(pipe), POSTOFF_RGB_TO_YUV_LO);
> > > +
> > > +	/* CSC mode before gamma */
> > > +	I915_WRITE(PIPE_CSC_MODE(pipe), 0);
> > > +}
> > > +
> > >   /* Set up the pipe CSC unit. */
> > >   static void i9xx_load_csc_matrix(struct drm_crtc_state *crtc_state)
> > >   {
> > > @@ -101,7 +143,10 @@ static void i9xx_load_csc_matrix(struct drm_crtc_state *crtc_state)
> > >   	uint16_t coeffs[9] = { 0, };
> > >   	struct intel_crtc_state *intel_crtc_state = to_intel_crtc_state(crtc_state);
> > >   
> > > -	if (crtc_state->ctm) {
> > > +	if (intel_crtc_state->hdmi_output > DRM_HDMI_OUTPUT_DEFAULT_RGB) {
> > > +		i9xx_load_ycbcr_conversion_matrix(intel_crtc);
> > > +		return;
> > > +	} else if (crtc_state->ctm) {
> > 
> > Hmm, I'm not sure this is the right place to check for this condition. I mean,
> > we shouldn't allow the modeset to happen in this case.
> 
> If you please have a look at the intel_crtc_compute_ycbcr_config check 
> added in this patch, that's doing the same.
> Its not allowing HDMI output conversion and pipe level CTM at the same 
> time.
> > 
> > >   		struct drm_color_ctm *ctm =
> > >   			(struct drm_color_ctm *)crtc_state->ctm->data;
> > >   		uint64_t input[9] = { 0, };
> > > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > > index 71fd19e..96ff2a0 100644
> > > --- a/drivers/gpu/drm/i915/intel_display.c
> > > +++ b/drivers/gpu/drm/i915/intel_display.c
> > > @@ -6261,6 +6261,29 @@ static void intel_crtc_compute_pixel_rate(struct intel_crtc_state *crtc_state)
> > >   			ilk_pipe_pixel_rate(crtc_state);
> > >   }
> > >   
> > > +static int intel_crtc_ycbcr_config(struct intel_crtc_state *state)
> > > +{
> > > +	struct drm_crtc_state *drm_state = &state->base;
> > > +	struct drm_i915_private *dev_priv = to_i915(drm_state->crtc->dev);
> > > +
> > > +	/* YCBCR420 is supported only in HDMI 2.0 controllers */
> > > +	if ((state->hdmi_output == DRM_HDMI_OUTPUT_YCBCR420) &&
> > > +		!IS_GEMINILAKE(dev_priv)) {
> > > +		DRM_ERROR("YCBCR420 output is not supported\n");
> > > +		return -EINVAL;
> > > +	}
> > > +
> > > +	/* We need CSC for output conversion from RGB->YCBCR */
> > > +	if (drm_state->ctm) {
> > > +		DRM_ERROR("YCBCR output and CTM is not possible together\n");
> > > +		return -EINVAL;
> > > +	}
> > 
> > Hmm, ok, that's checked here.
> 
> :-)
> > > +
> > > +	DRM_DEBUG_DRIVER("Output %s can be supported\n",
> > > +			 drm_get_hdmi_output_name(state->hdmi_output));
> > > +	return 0;
> > > +}
> > > +
> > >   static int intel_crtc_compute_config(struct intel_crtc *crtc,
> > >   				     struct intel_crtc_state *pipe_config)
> > >   {
> > > @@ -6290,6 +6313,14 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
> > >   		return -EINVAL;
> > >   	}
> > >   
> > > +	/* YCBCR output check */
> > > +	if (pipe_config->hdmi_output > DRM_HDMI_OUTPUT_DEFAULT_RGB) {
> > > +		if (intel_crtc_ycbcr_config(pipe_config)) {
> > 
> > You could combine both ifs. Or, even better, just move the first check into the
> > caller. I think it would be better to keep it all in one place. I was a bit
> > unsure if function did the right thing until I saw how it was called.
> 
> Ok, sure.
> > 
> > > +			DRM_ERROR("Cant enable HDMI YCBCR output\n");
> > > +			return -EINVAL;
> > > +		}
> > > +	}
> > > +
> > >   	/*
> > >   	 * Pipe horizontal size must be even in:
> > >   	 * - DVO ganged mode
> > > @@ -11658,6 +11689,7 @@ intel_modeset_pipe_config(struct drm_crtc *crtc,
> > >   			DRM_DEBUG_KMS("Encoder config failure\n");
> > >   			goto fail;
> > >   		}
> > > +
> > 
> > No need for this.
> 
> Got it.
> > 
> > 
> > Ander
> > 
> > >   	}
> > >   
> > >   	/* Set default port clock if not overwritten by the encoder. Needs to be
> 
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [RESEND-CI v4 11/15] drm/i915: prepare scaler for YCBCR420 modeset
  2017-06-30  5:50     ` Sharma, Shashank
@ 2017-06-30 11:34       ` Ander Conselvan De Oliveira
  2017-06-30 11:59         ` Sharma, Shashank
  0 siblings, 1 reply; 58+ messages in thread
From: Ander Conselvan De Oliveira @ 2017-06-30 11:34 UTC (permalink / raw)
  To: Sharma, Shashank, dri-devel, intel-gfx, ville.syrjala

On Fri, 2017-06-30 at 11:20 +0530, Sharma, Shashank wrote:
> Regards
> 
> Shashank
> 
> 
> On 6/27/2017 5:46 PM, Ander Conselvan De Oliveira wrote:
> > On Wed, 2017-06-21 at 16:04 +0530, Shashank Sharma wrote:
> > > To get a YCBCR420 output from intel platforms, we need one
> > > scaler to scale down YCBCR444 samples to YCBCR420 samples.
> > > 
> > > This patch:
> > > - Does scaler allocation for HDMI ycbcr420 outputs.
> > > - Programs PIPE_MISC register for ycbcr420 output.
> > > - Adds a new scaler user "HDMI output" to plug-into existing
> > >    scaler framework. This output type is identified using bit
> > >    30 of the scaler users bitmap.
> > > 
> > > V2: rebase
> > > V3: rebase
> > > V4: rebase
> > > 
> > > Cc: Ville Syrjala <ville.syrjala@linux.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_atomic.c  |  6 ++++++
> > >   drivers/gpu/drm/i915/intel_display.c | 26 ++++++++++++++++++++++++++
> > >   drivers/gpu/drm/i915/intel_drv.h     | 10 +++++++++-
> > >   drivers/gpu/drm/i915/intel_hdmi.c    | 10 ++++++++++
> > >   drivers/gpu/drm/i915/intel_panel.c   |  3 ++-
> > >   5 files changed, 53 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
> > > index 36d4e63..a8c9ac5 100644
> > > --- a/drivers/gpu/drm/i915/intel_atomic.c
> > > +++ b/drivers/gpu/drm/i915/intel_atomic.c
> > > @@ -264,6 +264,12 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv,
> > >   
> > >   			/* panel fitter case: assign as a crtc scaler */
> > >   			scaler_id = &scaler_state->scaler_id;
> > > +		} else if (i == SKL_HDMI_OUTPUT_INDEX) {
> > > +			name = "HDMI-OUTPUT";
> > > +			idx = intel_crtc->base.base.id;
> > > +
> > > +			/* hdmi output case: needs a pipe scaler */
> > > +			scaler_id = &scaler_state->scaler_id;
> > >   		} else {
> > >   			name = "PLANE";
> > >   
> > > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > > index da29536..983f581 100644
> > > --- a/drivers/gpu/drm/i915/intel_display.c
> > > +++ b/drivers/gpu/drm/i915/intel_display.c
> > > @@ -4626,6 +4626,11 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
> > >   	 */
> > >   	need_scaling = src_w != dst_w || src_h != dst_h;
> > >   
> > > +	if (crtc_state->hdmi_output == DRM_HDMI_OUTPUT_YCBCR420
> > > +		&& scaler_user == SKL_HDMI_OUTPUT_INDEX)
> > 
> > Is it really necessary to check for both? If it is, what's the point of creating
> > SKL_HDMI_OUTPUT_INDEX?
> 
> Yes, else this will affect scaler update for planes, as this function 
> gets called to update the plane scalers too, at that time the output 
> will be still valid (as its at CRTC level), but the
> scaler user would be different.

Right, so there is a need to check for scaler_user == HDMI_OUTPUT. But then
wouldn't it be a bug if hdmi_output != YCBCR420 ?  Point is, if the caller asked
for a HDMI_OUTPUT scaler hopefully it knows what its doing, no need to second
guess it.

> > 
> > > +		/* YCBCR 444 -> 420 conversion needs a scaler */
> > > +		need_scaling = true;
> > > +
> > >   	/*
> > >   	 * if plane is being disabled or scaler is no more required or force detach
> > >   	 *  - free scaler binded to this plane/crtc
> > > @@ -4673,6 +4678,26 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
> > >   }
> > >   
> > >   /**
> > > + * skl_update_scaler_hdmi_output - Stages update to scaler state for HDMI.
> > > + * HDMI YCBCR 420 output needs a scaler, for downsampling.
> > > + *
> > > + * @state: crtc's scaler state
> > > + *
> > > + * Return
> > > + *     0 - scaler_usage updated successfully
> > > + *    error - requested scaling cannot be supported or other error condition
> > > + */
> > > +int skl_update_scaler_crtc_hdmi_output(struct intel_crtc_state *state)
> > > +{
> > > +	const struct drm_display_mode *mode = &state->base.adjusted_mode;
> > > +
> > > +	return skl_update_scaler(state, !state->base.active,
> > > +		SKL_HDMI_OUTPUT_INDEX, &state->scaler_state.scaler_id,
> > > +		state->pipe_src_w, state->pipe_src_h,
> > > +		mode->crtc_hdisplay, mode->crtc_vdisplay);
> > > +}
> > > +
> > > +/**
> > >    * skl_update_scaler_crtc - Stages update to scaler state for a given crtc.
> > >    *
> > >    * @state: crtc's scaler state
> > > @@ -8058,6 +8083,7 @@ static void haswell_set_pipemisc(struct drm_crtc *crtc)
> > >   {
> > >   	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
> > >   	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> > > +	enum drm_hdmi_output_type hdmi_out = intel_crtc->config->hdmi_output;
> > >   
> > >   	if (IS_BROADWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 9) {
> > >   		u32 val = 0;
> > > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > > index 38fe56c..2206aa8 100644
> > > --- a/drivers/gpu/drm/i915/intel_drv.h
> > > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > > @@ -471,7 +471,8 @@ struct intel_crtc_scaler_state {
> > >   	 *
> > >   	 *     If a bit is set, a user is using a scaler.
> > >   	 *     Here user can be a plane or crtc as defined below:
> > > -	 *       bits 0-30 - plane (bit position is index from drm_plane_index)
> > > +	 *       bits 0-29 - plane (bit position is index from drm_plane_index)
> > > +	 *       bit 30    - hdmi output
> > >   	 *       bit 31    - crtc
> > >   	 *
> > >   	 * Instead of creating a new index to cover planes and crtc, using
> > > @@ -484,6 +485,12 @@ struct intel_crtc_scaler_state {
> > >   	 * avilability.
> > >   	 */
> > >   #define SKL_CRTC_INDEX 31
> > > +
> > > +	/*
> > > +	 * HDMI YCBCR 420 output consume a scaler. So adding a user
> > > +	 * for HDMI output 420 requirement.
> > > +	 */
> > > +#define SKL_HDMI_OUTPUT_INDEX 30
> > 
> > I'm not convinced about this. The scaler is still used as a pipe scaler and the
> > patch even adds a call intel_pch_panel_fitting().
> 
> This is a special mode usage of scalar defined in the bspec, when we 
> want to run the scalar into 5x3 auto mode for YCBCR444->YCBCR420 scale down.
> It can be used only when the PIPE_MISC is also programmed to act 
> accordingly. So this is different from using it as a panel fitter, and 
> that's why added
> a new scalar user all together.
> > 
> > >   	unsigned scaler_users;
> > >   
> > >   	/* scaler used by crtc for panel fitting purpose */
> > > @@ -1481,6 +1488,7 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode,
> > >   				 struct intel_crtc_state *pipe_config);
> > >   
> > >   int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state);
> > > +int skl_update_scaler_crtc_hdmi_output(struct intel_crtc_state *state);
> > >   int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state);
> > >   
> > >   static inline u32 intel_plane_ggtt_offset(const struct intel_plane_state *state)
> > > diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> > > index 22da5cd..8d5aa1e 100644
> > > --- a/drivers/gpu/drm/i915/intel_hdmi.c
> > > +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> > > @@ -1415,6 +1415,7 @@ intel_hdmi_compute_ycbcr_config(struct drm_connector_state *conn_state,
> > >   	}
> > >   
> > >   	if (type == DRM_HDMI_OUTPUT_YCBCR420) {
> > > +		struct intel_crtc *intel_crtc = to_intel_crtc(conn_state->crtc);
> > >   
> > >   		/* YCBCR420 TMDS rate requirement is half the pixel clock */
> > >   		config->hdmi_output = DRM_HDMI_OUTPUT_YCBCR420;
> > > @@ -1422,6 +1423,15 @@ intel_hdmi_compute_ycbcr_config(struct drm_connector_state *conn_state,
> > >   		*clock_12bpc /= 2;
> > >   		*clock_8bpc /= 2;
> > >   
> > > +		/* YCBCR 420 output conversion needs a scaler */
> > > +		if (skl_update_scaler_crtc_hdmi_output(config)) {
> > > +			DRM_ERROR("Scaler allocation for output failed\n");
> > > +			return DRM_HDMI_OUTPUT_INVALID;
> > > +		}
> > > +
> > > +		/* Bind this scaler to pipe */
> > > +		intel_pch_panel_fitting(intel_crtc, config,
> > > +					DRM_MODE_SCALE_FULLSCREEN);
> > >   	}
> > >   
> > >   	/* Encoder is capable of this output, lets commit to CRTC */
> > > diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
> > > index 96c2cbd..b6a32c4 100644
> > > --- a/drivers/gpu/drm/i915/intel_panel.c
> > > +++ b/drivers/gpu/drm/i915/intel_panel.c
> > > @@ -110,7 +110,8 @@ intel_pch_panel_fitting(struct intel_crtc *intel_crtc,
> > >   
> > >   	/* Native modes don't need fitting */
> > >   	if (adjusted_mode->crtc_hdisplay == pipe_config->pipe_src_w &&
> > > -	    adjusted_mode->crtc_vdisplay == pipe_config->pipe_src_h)
> > > +	    adjusted_mode->crtc_vdisplay == pipe_config->pipe_src_h &&
> > > +	    pipe_config->hdmi_output != DRM_HDMI_OUTPUT_YCBCR420)
> > 
> > I don't like that the knowledge that YCBCR420 needs the scaler is spread
> > everywhere, including this function that should only deal with panel fitting. I
> > would rather add a force parameter to intel_pch_panel_fitting() and
> > skl_update_scaler() that would mean setup the scaler even if looks like it's not
> > necessary. That way the hdmi code would just call them with force enabled,
> > without sprinkling "hdmi_output == YCBCR420" everywhere.
> 
> As explained in the comment above, its special case usage of pipe 
> scalar, and that's why being checked specifically.

I'm still not convinced about this. If this is a special scaler mode that is not
panel fitting, then this should definitely not touch a function in
intel_panel.c, specially one with "panel fitting" in the name.

My point is, if this is panel fitting, then it should use panel fitting code
without special casing. If it isn't, then it should have its own code paths. But
this patch just creates a blurry line where the panel fitting code needs to be
special cased for when the HDMI output is YCBCR420 and we are *not* actually
doing panel fitting.


Ander

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [RESEND-CI v4 06/15] drm/edid: parse sink information before CEA blocks
  2017-06-30  5:22     ` Sharma, Shashank
@ 2017-06-30 11:46       ` Ville Syrjälä
  2017-06-30 12:01         ` Sharma, Shashank
  0 siblings, 1 reply; 58+ messages in thread
From: Ville Syrjälä @ 2017-06-30 11:46 UTC (permalink / raw)
  To: Sharma, Shashank; +Cc: intel-gfx, dri-devel

On Fri, Jun 30, 2017 at 10:52:54AM +0530, Sharma, Shashank wrote:
> Regards
> 
> Shashank
> 
> 
> On 6/27/2017 5:25 PM, Ville Syrjälä wrote:
> > On Wed, Jun 21, 2017 at 04:04:04PM +0530, Shashank Sharma wrote:
> >> CEA-861-F adds ycbcr capability map block, for HDMI 2.0 sinks.
> >> This block contains a map of indexes of CEA modes, which can
> >> support YCBCR 420 output also. To avoid multiple parsing of same
> >> CEA block, let's parse the sink information and get this map, before
> >> parsing CEA modes.
> >>
> >> This patch moves the call to drm_add_display_info function, before the
> >> mode parsing block.
> >>
> >> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
> >> ---
> >>   drivers/gpu/drm/drm_edid.c | 9 +++++++--
> >>   1 file changed, 7 insertions(+), 2 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> >> index b4583f6..42934b2 100644
> >> --- a/drivers/gpu/drm/drm_edid.c
> >> +++ b/drivers/gpu/drm/drm_edid.c
> >> @@ -4605,6 +4605,13 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
> >>   	quirks = edid_get_quirks(edid);
> >>   
> >>   	/*
> >> +	 * CEA-861-F adds ycbcr capability map block, for HDMI 2.0 sinks.
> >> +	 * To avoid multiple parsing of same block, lets parse that map
> >> +	 * from sink info, before parsing CEA modes.
> >> +	 */
> >> +	drm_add_display_info(connector, edid);
> >> +
> > This patch should come before the 4:2:0 mode parsing, no?
> Dint you ask me to move it later (in the previous series comments), for 
> git-bisect regression type of changes ?

I wanted it split out to help with bisecting. It should be early in the
series because otherwise the rest makes no sense. And I suppose we should
be able to push this in on its own right now. Just need a CI run for it,
so maybe resesnd just this patch on its own.

> > Otherwise I think this should be fine so
> > Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Thanks.
> >
> >> +	/*
> >>   	 * EDID spec says modes should be preferred in this order:
> >>   	 * - preferred detailed mode
> >>   	 * - other detailed modes from base block
> >> @@ -4632,8 +4639,6 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
> >>   	if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75))
> >>   		edid_fixup_preferred(connector, quirks);
> >>   
> >> -	drm_add_display_info(connector, edid);
> >> -
> >>   	if (quirks & EDID_QUIRK_FORCE_6BPC)
> >>   		connector->display_info.bpc = 6;
> >>   
> >> -- 
> >> 2.7.4

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [RESEND-CI v4 01/15] drm: add HDMI 2.0 VIC support for AVI info-frames
  2017-06-21 10:33 ` [RESEND-CI v4 01/15] drm: add HDMI 2.0 VIC support for AVI info-frames Shashank Sharma
  2017-06-21 13:41   ` Neil Armstrong
@ 2017-06-30 11:54   ` Ville Syrjälä
  2017-07-03  9:06     ` Sharma, Shashank
  1 sibling, 1 reply; 58+ messages in thread
From: Ville Syrjälä @ 2017-06-30 11:54 UTC (permalink / raw)
  To: Shashank Sharma
  Cc: Jose Abreu, intel-gfx, dri-devel, Alex Deucher, Daniel Vetter

On Wed, Jun 21, 2017 at 04:03:59PM +0530, Shashank Sharma wrote:
> HDMI 1.4b support the CEA video modes as per range of CEA-861-D (VIC 1-64).
> For any other mode, the VIC filed in AVI infoframes should be 0.
> HDMI 2.0 sinks, support video modes range as per CEA-861-F spec, which is
> extended to (VIC 1-107).
> 
> This patch adds a bool input variable, which indicates if the connected
> sink is a HDMI 2.0 sink or not. This will make sure that we don't pass a
> HDMI 2.0 VIC to a HDMI 1.4 sink.
> 
> This patch touches all drm drivers, who are callers of this function
> drm_hdmi_avi_infoframe_from_display_mode but to make sure there is
> no change in current behavior, is_hdmi2 is kept as false.
> 
> In case of I915 driver, this patch:
> - checks if the connected display is HDMI 2.0.
> - HDMI infoframes carry one of this two type of information:
> 	- VIC for 4K modes for HDMI 1.4 sinks
> 	- S3D information for S3D modes
>   As CEA-861-F has already defined VICs for 4K videomodes, this
>   patch doesn't allow sending HDMI infoframes for HDMI 2.0 sinks,
>   until the mode is 3D.
> 
> Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
> Cc: Jose Abreu <jose.abreu@synopsys.com>
> Cc: Andrzej Hajda <a.hajda@samsung.com>
> Cc: Alex Deucher <alexander.deucher@amd.com>
> Cc: Daniel Vetter <daniel.vetter@intel.com>
> 
> PS: This patch touches a few lines in few files, which were
> already above 80 char, so checkpatch gives 80 char warning again.
> - gpu/drm/omapdrm/omap_encoder.c
> - gpu/drm/i915/intel_sdvo.c
> 
> V2: Rebase, Added r-b from Andrzej
> V3: Addressed review comment from Ville:
> 	- Do not send VICs in both AVI-IF and HDMI-IF
> 	  send only one of it.
> 
> Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
> ---
>  drivers/gpu/drm/amd/amdgpu/dce_v10_0.c    |  2 +-
>  drivers/gpu/drm/amd/amdgpu/dce_v11_0.c    |  2 +-
>  drivers/gpu/drm/amd/amdgpu/dce_v8_0.c     |  2 +-
>  drivers/gpu/drm/bridge/analogix-anx78xx.c |  3 ++-
>  drivers/gpu/drm/bridge/sii902x.c          |  2 +-
>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.c |  2 +-
>  drivers/gpu/drm/drm_edid.c                | 12 +++++++++++-
>  drivers/gpu/drm/exynos/exynos_hdmi.c      |  2 +-
>  drivers/gpu/drm/i2c/tda998x_drv.c         |  2 +-
>  drivers/gpu/drm/i915/intel_hdmi.c         | 17 ++++++++++++++++-
>  drivers/gpu/drm/i915/intel_sdvo.c         |  3 ++-
>  drivers/gpu/drm/mediatek/mtk_hdmi.c       |  2 +-
>  drivers/gpu/drm/omapdrm/omap_encoder.c    |  3 ++-
>  drivers/gpu/drm/radeon/radeon_audio.c     |  2 +-
>  drivers/gpu/drm/rockchip/inno_hdmi.c      |  2 +-
>  drivers/gpu/drm/sti/sti_hdmi.c            |  2 +-
>  drivers/gpu/drm/tegra/hdmi.c              |  2 +-
>  drivers/gpu/drm/tegra/sor.c               |  2 +-
>  drivers/gpu/drm/vc4/vc4_hdmi.c            |  2 +-
>  drivers/gpu/drm/zte/zx_hdmi.c             |  2 +-
>  include/drm/drm_edid.h                    |  3 ++-
>  21 files changed, 50 insertions(+), 21 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
> index 3c62c45..4923ddc 100644
> --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
> @@ -1864,7 +1864,7 @@ static void dce_v10_0_afmt_setmode(struct drm_encoder *encoder,
>  	dce_v10_0_audio_write_sad_regs(encoder);
>  	dce_v10_0_audio_write_latency_fields(encoder, mode);
>  
> -	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
> +	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
>  	if (err < 0) {
>  		DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
>  		return;
> diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
> index c8ed0fa..4101684 100644
> --- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
> @@ -1848,7 +1848,7 @@ static void dce_v11_0_afmt_setmode(struct drm_encoder *encoder,
>  	dce_v11_0_audio_write_sad_regs(encoder);
>  	dce_v11_0_audio_write_latency_fields(encoder, mode);
>  
> -	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
> +	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
>  	if (err < 0) {
>  		DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
>  		return;
> diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
> index 3e90c19..a7f6b32 100644
> --- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
> @@ -1747,7 +1747,7 @@ static void dce_v8_0_afmt_setmode(struct drm_encoder *encoder,
>  	dce_v8_0_audio_write_sad_regs(encoder);
>  	dce_v8_0_audio_write_latency_fields(encoder, mode);
>  
> -	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
> +	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
>  	if (err < 0) {
>  		DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
>  		return;
> diff --git a/drivers/gpu/drm/bridge/analogix-anx78xx.c b/drivers/gpu/drm/bridge/analogix-anx78xx.c
> index 9006578..a083211 100644
> --- a/drivers/gpu/drm/bridge/analogix-anx78xx.c
> +++ b/drivers/gpu/drm/bridge/analogix-anx78xx.c
> @@ -1097,7 +1097,8 @@ static void anx78xx_bridge_mode_set(struct drm_bridge *bridge,
>  
>  	mutex_lock(&anx78xx->lock);
>  
> -	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, adjusted_mode);
> +	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, adjusted_mode,
> +						       false);
>  	if (err) {
>  		DRM_ERROR("Failed to setup AVI infoframe: %d\n", err);
>  		goto unlock;
> diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c
> index 9b87067..3dc40f6 100644
> --- a/drivers/gpu/drm/bridge/sii902x.c
> +++ b/drivers/gpu/drm/bridge/sii902x.c
> @@ -269,7 +269,7 @@ static void sii902x_bridge_mode_set(struct drm_bridge *bridge,
>  	if (ret)
>  		return;
>  
> -	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame, adj);
> +	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame, adj, false);
>  	if (ret < 0) {
>  		DRM_ERROR("couldn't fill AVI infoframe\n");
>  		return;
> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> index ead1124..0b0c9de 100644
> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> @@ -1317,7 +1317,7 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
>  	u8 val;
>  
>  	/* Initialise info frame from DRM mode */
> -	drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
> +	drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
>  
>  	if (hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format))
>  		frame.colorspace = HDMI_COLORSPACE_YUV444;
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index 2e55599..d312fe1 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -4334,12 +4334,14 @@ EXPORT_SYMBOL(drm_set_preferred_mode);
>   *                                              data from a DRM display mode
>   * @frame: HDMI AVI infoframe
>   * @mode: DRM display mode
> + * @is_hdmi2_sink: Sink is HDMI 2.0 compliant
>   *
>   * Return: 0 on success or a negative error code on failure.
>   */
>  int
>  drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
> -					 const struct drm_display_mode *mode)
> +					 const struct drm_display_mode *mode,
> +					 bool is_hdmi2_sink)
>  {
>  	int err;
>  
> @@ -4355,6 +4357,14 @@ drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
>  
>  	frame->video_code = drm_match_cea_mode(mode);
>  
> +	/*
> +	 * HDMI 1.4 VIC range: 1 <= VIC <= 64 (CEA-861-D) but
> +	 * HDMI 2.0 VIC range: 1 <= VIC <= 107 (CEA-861-F). So we
> +	 * have to make sure we dont break HDMI 1.4 sinks.
> +	 */
> +	if (!is_hdmi2_sink && frame->video_code > 64)
> +		frame->video_code = 0;
> +
>  	frame->picture_aspect = HDMI_PICTURE_ASPECT_NONE;
>  
>  	/*
> diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
> index 06bfbe4..c953927 100644
> --- a/drivers/gpu/drm/exynos/exynos_hdmi.c
> +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
> @@ -784,7 +784,7 @@ static void hdmi_reg_infoframes(struct hdmi_context *hdata)
>  	}
>  
>  	ret = drm_hdmi_avi_infoframe_from_display_mode(&frm.avi,
> -			&hdata->current_mode);
> +			&hdata->current_mode, false);
>  	if (!ret)
>  		ret = hdmi_avi_infoframe_pack(&frm.avi, buf, sizeof(buf));
>  	if (ret > 0) {
> diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
> index 86f47e1..d1e7ac5 100644
> --- a/drivers/gpu/drm/i2c/tda998x_drv.c
> +++ b/drivers/gpu/drm/i2c/tda998x_drv.c
> @@ -712,7 +712,7 @@ tda998x_write_avi(struct tda998x_priv *priv, struct drm_display_mode *mode)
>  {
>  	union hdmi_infoframe frame;
>  
> -	drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
> +	drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
>  	frame.avi.quantization_range = HDMI_QUANTIZATION_RANGE_FULL;
>  
>  	tda998x_write_if(priv, DIP_IF_FLAGS_IF2, REG_IF2_HB0, &frame);
> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> index ec0779a..170abc4 100644
> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> @@ -459,11 +459,14 @@ static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder,
>  	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
>  	const struct drm_display_mode *adjusted_mode =
>  		&crtc_state->base.adjusted_mode;
> +	struct drm_connector *connector = &intel_hdmi->attached_connector->base;
> +	bool is_hdmi2_sink = connector->display_info.hdmi.scdc.supported;
>  	union hdmi_infoframe frame;
>  	int ret;
>  
>  	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
> -						       adjusted_mode);
> +						       adjusted_mode,
> +						       is_hdmi2_sink);
>  	if (ret < 0) {
>  		DRM_ERROR("couldn't fill AVI infoframe\n");
>  		return;
> @@ -816,6 +819,8 @@ static void hsw_set_infoframes(struct drm_encoder *encoder,
>  {
>  	struct drm_i915_private *dev_priv = to_i915(encoder->dev);
>  	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
> +	struct drm_hdmi_info *hdmi = &conn_state->connector->display_info.hdmi;
> +	const struct drm_display_mode *mode = &crtc_state->base.adjusted_mode;
>  	i915_reg_t reg = HSW_TVIDEO_DIP_CTL(crtc_state->cpu_transcoder);
>  	u32 val = I915_READ(reg);
>  
> @@ -839,6 +844,16 @@ static void hsw_set_infoframes(struct drm_encoder *encoder,
>  
>  	intel_hdmi_set_avi_infoframe(encoder, crtc_state);
>  	intel_hdmi_set_spd_infoframe(encoder, crtc_state);
> +
> +	/*
> +	 * CEA-861-F added new VICs for 4k video modes, due to which
> +	 * HDMI 2.0 sinks need HDMI IF only for S3D information (Not for
> +	 * 4k VICs). So for a HDMI 2.0 sink, if the video mode is not 3D,
> +	 * don't bother sending HDMI IF.
> +	 */
> +	if (hdmi->scdc.supported && !(mode->flags & DRM_MODE_FLAG_3D_MASK))
> +		return;

That doesn't look like the rigth place for this check.

Also I think we still want to send the vendor specific infoframe always,
if for no other reason that to get extra testing for the code. We just
need to select whether we should be sending the old or the new one.

> +
>  	intel_hdmi_set_hdmi_infoframe(encoder, crtc_state);
>  }
>  
> diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
> index f4329d2..737076e 100644
> --- a/drivers/gpu/drm/i915/intel_sdvo.c
> +++ b/drivers/gpu/drm/i915/intel_sdvo.c
> @@ -996,7 +996,8 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo,
>  	ssize_t len;
>  
>  	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
> -						       &pipe_config->base.adjusted_mode);
> +						       &pipe_config->base.adjusted_mode,
> +						       false);
>  	if (ret < 0) {
>  		DRM_ERROR("couldn't fill AVI infoframe\n");
>  		return false;
> diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> index 0a4ffd7..5c0d024 100644
> --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> @@ -975,7 +975,7 @@ static int mtk_hdmi_setup_avi_infoframe(struct mtk_hdmi *hdmi,
>  	u8 buffer[17];
>  	ssize_t err;
>  
> -	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
> +	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
>  	if (err < 0) {
>  		dev_err(hdmi->dev,
>  			"Failed to get AVI infoframe from mode: %zd\n", err);
> diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c b/drivers/gpu/drm/omapdrm/omap_encoder.c
> index 86c977b..624f5b5 100644
> --- a/drivers/gpu/drm/omapdrm/omap_encoder.c
> +++ b/drivers/gpu/drm/omapdrm/omap_encoder.c
> @@ -85,7 +85,8 @@ static void omap_encoder_mode_set(struct drm_encoder *encoder,
>  	if (hdmi_mode && dssdev->driver->set_hdmi_infoframe) {
>  		struct hdmi_avi_infoframe avi;
>  
> -		r = drm_hdmi_avi_infoframe_from_display_mode(&avi, adjusted_mode);
> +		r = drm_hdmi_avi_infoframe_from_display_mode(&avi, adjusted_mode,
> +							     false);
>  		if (r == 0)
>  			dssdev->driver->set_hdmi_infoframe(dssdev, &avi);
>  	}
> diff --git a/drivers/gpu/drm/radeon/radeon_audio.c b/drivers/gpu/drm/radeon/radeon_audio.c
> index aaacac1..770e31f 100644
> --- a/drivers/gpu/drm/radeon/radeon_audio.c
> +++ b/drivers/gpu/drm/radeon/radeon_audio.c
> @@ -516,7 +516,7 @@ static int radeon_audio_set_avi_packet(struct drm_encoder *encoder,
>  	if (!connector)
>  		return -EINVAL;
>  
> -	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
> +	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
>  	if (err < 0) {
>  		DRM_ERROR("failed to setup AVI infoframe: %d\n", err);
>  		return err;
> diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c
> index 7d9b75e..7149968 100644
> --- a/drivers/gpu/drm/rockchip/inno_hdmi.c
> +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c
> @@ -294,7 +294,7 @@ static int inno_hdmi_config_video_avi(struct inno_hdmi *hdmi,
>  	union hdmi_infoframe frame;
>  	int rc;
>  
> -	rc = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
> +	rc = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
>  
>  	if (hdmi->hdmi_data.enc_out_format == HDMI_COLORSPACE_YUV444)
>  		frame.avi.colorspace = HDMI_COLORSPACE_YUV444;
> diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
> index a59c95a..dbc6a19 100644
> --- a/drivers/gpu/drm/sti/sti_hdmi.c
> +++ b/drivers/gpu/drm/sti/sti_hdmi.c
> @@ -434,7 +434,7 @@ static int hdmi_avi_infoframe_config(struct sti_hdmi *hdmi)
>  
>  	DRM_DEBUG_DRIVER("\n");
>  
> -	ret = drm_hdmi_avi_infoframe_from_display_mode(&infoframe, mode);
> +	ret = drm_hdmi_avi_infoframe_from_display_mode(&infoframe, mode, false);
>  	if (ret < 0) {
>  		DRM_ERROR("failed to setup AVI infoframe: %d\n", ret);
>  		return ret;
> diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c
> index cda0491..718d8db 100644
> --- a/drivers/gpu/drm/tegra/hdmi.c
> +++ b/drivers/gpu/drm/tegra/hdmi.c
> @@ -734,7 +734,7 @@ static void tegra_hdmi_setup_avi_infoframe(struct tegra_hdmi *hdmi,
>  	u8 buffer[17];
>  	ssize_t err;
>  
> -	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
> +	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
>  	if (err < 0) {
>  		dev_err(hdmi->dev, "failed to setup AVI infoframe: %zd\n", err);
>  		return;
> diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c
> index a8f5289..fb2709c 100644
> --- a/drivers/gpu/drm/tegra/sor.c
> +++ b/drivers/gpu/drm/tegra/sor.c
> @@ -1904,7 +1904,7 @@ tegra_sor_hdmi_setup_avi_infoframe(struct tegra_sor *sor,
>  	value &= ~INFOFRAME_CTRL_ENABLE;
>  	tegra_sor_writel(sor, value, SOR_HDMI_AVI_INFOFRAME_CTRL);
>  
> -	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
> +	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
>  	if (err < 0) {
>  		dev_err(sor->dev, "failed to setup AVI infoframe: %d\n", err);
>  		return err;
> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> index ed63d4e..406d6d8 100644
> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> @@ -395,7 +395,7 @@ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
>  	union hdmi_infoframe frame;
>  	int ret;
>  
> -	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
> +	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
>  	if (ret < 0) {
>  		DRM_ERROR("couldn't fill AVI infoframe\n");
>  		return;
> diff --git a/drivers/gpu/drm/zte/zx_hdmi.c b/drivers/gpu/drm/zte/zx_hdmi.c
> index 0df7366..7e834e3 100644
> --- a/drivers/gpu/drm/zte/zx_hdmi.c
> +++ b/drivers/gpu/drm/zte/zx_hdmi.c
> @@ -124,7 +124,7 @@ static int zx_hdmi_config_video_avi(struct zx_hdmi *hdmi,
>  	union hdmi_infoframe frame;
>  	int ret;
>  
> -	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
> +	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
>  	if (ret) {
>  		DRM_DEV_ERROR(hdmi->dev, "failed to get avi infoframe: %d\n",
>  			      ret);
> diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
> index 7b9f48b..89c0062 100644
> --- a/include/drm/drm_edid.h
> +++ b/include/drm/drm_edid.h
> @@ -343,7 +343,8 @@ drm_load_edid_firmware(struct drm_connector *connector)
>  
>  int
>  drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
> -					 const struct drm_display_mode *mode);
> +					 const struct drm_display_mode *mode,
> +					 bool is_hdmi2_sink);
>  int
>  drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame,
>  					    const struct drm_display_mode *mode);
> -- 
> 2.7.4

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [RESEND-CI v4 04/15] drm/edid: parse YCBCR 420 videomodes from EDID
  2017-06-30  5:17     ` Sharma, Shashank
@ 2017-06-30 11:58       ` Ville Syrjälä
  2017-06-30 12:08         ` Sharma, Shashank
  0 siblings, 1 reply; 58+ messages in thread
From: Ville Syrjälä @ 2017-06-30 11:58 UTC (permalink / raw)
  To: Sharma, Shashank; +Cc: intel-gfx, Jose Abreu, dri-devel

On Fri, Jun 30, 2017 at 10:47:48AM +0530, Sharma, Shashank wrote:
> Regards
> 
> Shashank
> 
> 
> On 6/27/2017 5:22 PM, Ville Syrjälä wrote:
> > On Wed, Jun 21, 2017 at 04:04:02PM +0530, Shashank Sharma wrote:
> >> HDMI 2.0 spec adds support for YCBCR420 sub-sampled output.
> >> CEA-861-F adds two new blocks in EDID's CEA extension blocks,
> >> to provide information about sink's YCBCR420 output capabilities.
> >>
> >> These blocks are:
> >>
> >> - YCBCR420vdb(YCBCR 420 video data block):
> >> This block contains VICs of video modes, which can be sopported only
> >> in YCBCR420 output mode (Not in RGB/YCBCR444/422. Its like a normal
> >> SVD block, valid for YCBCR420 modes only.
> >>
> >> - YCBCR420cmdb(YCBCR 420 capability map data block):
> >> This block gives information about video modes which can support
> >> YCBCR420 output mode also (along with RGB,YCBCR444/422 etc) This
> >> block contains a bitmap index of normal svd videomodes, which can
> >> support YCBCR420 output too.
> >> So if bit 0 from first vcb byte is set, first video mode in the svd
> >> list can support YCBCR420 output too. Bit 1 means second video mode
> >> from svd list can support YCBCR420 output too, and so on.
> >>
> >> This patch adds two bitmaps in display's hdmi_info structure, one each
> >> for VCB and VDB modes. If the source is HDMI 2.0 capable, this patch
> >> adds:
> >> - VDB modes (YCBCR 420 only modes) in connector's mode list, also makes
> >>    an entry in the vdb_bitmap per vic.
> >> - VCB modes (YCBCR 420 also modes) only entry in the vcb_bitmap.
> >>
> >> Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
> >> Cc: Jose Abreu <joabreu@synopsys.com>
> >> Cc: Emil Velikov <emil.l.velikov@gmail.com>
> >>
> >> V2: Addressed
> >>      Review comments from Emil:
> >>      - Use 1ULL<<i instead of 1<<i to make sure the output is 64bit.
> >>      - Use the suggested method for updating dbmap.
> >>      - Add documentation for YCBCR420_vcb_map to fix kbuild warning.
> >>
> >>      Review comments from Ville:
> >>      - Do not expose the YCBCR420 flags in uabi layer, keep it internal.
> >>      - Save a map of YCBCR420 modes for future reference.
> >>      - Check db length before trying to parse extended tag.
> >>      - Add a warning if there are > 64 modes in capability map block.
> >>      - Use y420cmdb in function names and macros while dealing with vcb
> >>        to be aligned with spec.
> >>      - Move the display information parsing block ahead of mode parsing
> >>        blocks.
> >>
> >> V3: Addressed design/review comments from Ville
> >>      - Do not add flags in video modes, else we have to expose them to user
> >>      - There should not be a UABI change, and kernel should detect the
> >>        choice of the output based on type of mode, and the bitmaps.
> >>      - Use standard bitops from kernel bitmap header, instead of calculating
> >>        bit positions manually.
> >>
> >> V4: Addressed review comments from Ville:
> >>      - s/ycbcr_420_vdb/y420vdb
> >>      - s/ycbcr_420_vcb/y420cmdb
> >>      - Be less verbose on description of do_y420vdb_modes
> >>      - Move newmode variable in the loop scope.
> >>      - Use svd_to_vic() to get a VIC, instead of 0x7f
> >>      - Remove bitmap description for CMDB modes & VDB modes
> >>      - Dont add connector->ycbcr_420_allowed check for cmdb modes
> >>      - Remove 'len' variable, in is_y420cmdb function, which is used
> >>        only once
> >>      - Add length check in is_y420vdb function
> >>      - Remove unnecessary if (!db) check in function parse_y420cmdb_bitmap
> >>      - Do not add print about YCBCR 420 modes
> >>      - Fix indentation in few places
> >>      - Move ycbcr420_dc_modes in next patch, where its used
> >>      - Add a separate patch for movement of drm_add_display_info()
> >>
> >> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
> >> ---
> >>   drivers/gpu/drm/drm_edid.c  | 157 +++++++++++++++++++++++++++++++++++++++++++-
> >>   include/drm/drm_connector.h |  20 ++++++
> >>   2 files changed, 174 insertions(+), 3 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> >> index e2d1b30..8c7e73b 100644
> >> --- a/drivers/gpu/drm/drm_edid.c
> >> +++ b/drivers/gpu/drm/drm_edid.c
> >> @@ -2781,7 +2781,9 @@ add_detailed_modes(struct drm_connector *connector, struct edid *edid,
> >>   #define VIDEO_BLOCK     0x02
> >>   #define VENDOR_BLOCK    0x03
> >>   #define SPEAKER_BLOCK	0x04
> >> -#define VIDEO_CAPABILITY_BLOCK	0x07
> >> +#define VIDEO_CAPABILITY_BLOCK 0x07
> >> +#define VIDEO_DATA_BLOCK_420	0x0E
> >> +#define VIDEO_CAP_BLOCK_Y420CMDB 0x0F
> >>   #define EDID_BASIC_AUDIO	(1 << 6)
> >>   #define EDID_CEA_YCRCB444	(1 << 5)
> >>   #define EDID_CEA_YCRCB422	(1 << 4)
> >> @@ -3153,15 +3155,79 @@ drm_display_mode_from_vic_index(struct drm_connector *connector,
> >>   	return newmode;
> >>   }
> >>   
> >> +/*
> >> + * do_y420vdb_modes - Parse YCBCR 420 only modes
> >> + * @connector: connector corresponding to the HDMI sink
> >> + * @svds: start of the data block of CEA YCBCR 420 VDB
> >> + * @len: length of the CEA YCBCR 420 VDB
> >> + *
> >> + * Parse the CEA-861-F YCBCR 420 Video Data Block (Y420VDB)
> >> + * which contains modes which can be supported in YCBCR 420
> >> + * output format only.
> >> + */
> >> +static int do_y420vdb_modes(struct drm_connector *connector,
> >> +				   const u8 *svds, u8 svds_len)
> >> +{
> >> +	int modes = 0, i;
> >> +	struct drm_device *dev = connector->dev;
> >> +	struct drm_display_info *info = &connector->display_info;
> >> +	struct drm_hdmi_info *hdmi = &info->hdmi;
> >> +
> >> +	for (i = 0; i < svds_len; i++) {
> >> +		u8 vic = svd_to_vic(svds[i]);
> >> +		struct drm_display_mode *newmode;
> >> +
> >> +		newmode = drm_mode_duplicate(dev, &edid_cea_modes[vic]);
> >> +		if (!newmode)
> >> +			break;
> >> +		bitmap_set(hdmi->y420_vdb_modes, vic, 1);
> >> +		drm_mode_probed_add(connector, newmode);
> >> +		modes++;
> >> +	}
> >> +
> >> +	if (modes > 0)
> >> +		info->color_formats |= DRM_COLOR_FORMAT_YCRCB420;
> >> +	return modes;
> >> +}
> >> +
> >> +/*
> >> + * drm_add_cmdb_modes - Add a YCBCR 420 mode into bitmap
> >> + * @connector: connector corresponding to the HDMI sink
> >> + * @vic: CEA vic for the video mode to be added in the map
> >> + *
> >> + * Makes an entry for a videomode in the YCBCR 420 bitmap
> >> + */
> >> +static void
> >> +drm_add_cmdb_modes(struct drm_connector *connector, u8 svd)
> >> +{
> >> +	u8 vic = svd_to_vic(svd);
> >> +	struct drm_hdmi_info *hdmi = &connector->display_info.hdmi;
> >> +
> >> +	bitmap_set(hdmi->y420_cmdb_modes, vic, 1);
> >> +}
> >> +
> >>   static int
> >>   do_cea_modes(struct drm_connector *connector, const u8 *db, u8 len)
> >>   {
> >>   	int i, modes = 0;
> >> +	struct drm_hdmi_info *hdmi = &connector->display_info.hdmi;
> >>   
> >>   	for (i = 0; i < len; i++) {
> >>   		struct drm_display_mode *mode;
> >>   		mode = drm_display_mode_from_vic_index(connector, db, len, i);
> >>   		if (mode) {
> >> +			/*
> >> +			 * YCBCR420 capability block contains a bitmap which
> >> +			 * gives the index of CEA modes from CEA VDB, which
> >> +			 * can support YCBCR 420 sampling output also (apart
> >> +			 * from RGB/YCBCR444 etc).
> >> +			 * For example, if the bit 0 in bitmap is set,
> >> +			 * first mode in VDB can support YCBCR420 output too.
> >> +			 * Add YCBCR420 modes only if sink is HDMI 2.0 capable.
> >> +			 */
> >> +			if (test_bit(i, &hdmi->y420_cmdb_map))
> >> +				drm_add_cmdb_modes(connector, db[i]);
> >> +
> >>   			drm_mode_probed_add(connector, mode);
> >>   			modes++;
> >>   		}
> >> @@ -3437,6 +3503,12 @@ do_hdmi_vsdb_modes(struct drm_connector *connector, const u8 *db, u8 len,
> >>   }
> >>   
> >>   static int
> >> +cea_db_extended_tag(const u8 *db)
> >> +{
> >> +	return db[1];
> >> +}
> >> +
> >> +static int
> >>   cea_db_payload_len(const u8 *db)
> >>   {
> >>   	return db[0] & 0x1f;
> >> @@ -3497,9 +3569,78 @@ static bool cea_db_is_hdmi_forum_vsdb(const u8 *db)
> >>   	return oui == HDMI_FORUM_IEEE_OUI;
> >>   }
> >>   
> >> +static bool cea_db_is_y420cmdb(const u8 *db)
> >> +{
> >> +
> >> +	if (cea_db_tag(db) != VIDEO_CAPABILITY_BLOCK)
> > Still would like to see that patch to clean up the current extended tag
> > usage...
> Yep, its on the way, running a bit loaded.
> >> +		return false;
> >> +
> >> +	if (!cea_db_payload_len(db))
> >> +		return false;
> >> +
> >> +	if (cea_db_extended_tag(db) != VIDEO_CAP_BLOCK_Y420CMDB)
> >> +		return false;
> >> +
> >> +	return true;
> >> +}
> >> +
> >> +static bool cea_db_is_y420vdb(const u8 *db)
> >> +{
> >> +	if (cea_db_tag(db) != VIDEO_CAPABILITY_BLOCK)
> >> +		return false;
> >> +
> >> +	if (!cea_db_payload_len(db))
> >> +		return false;
> >> +
> >> +	if (cea_db_extended_tag(db) != VIDEO_DATA_BLOCK_420)
> >> +		return false;
> >> +
> >> +	return true;
> >> +}
> >> +
> >>   #define for_each_cea_db(cea, i, start, end) \
> >>   	for ((i) = (start); (i) < (end) && (i) + cea_db_payload_len(&(cea)[(i)]) < (end); (i) += cea_db_payload_len(&(cea)[(i)]) + 1)
> >>   
> >> +static void drm_parse_y420cmdb_bitmap(struct drm_connector *connector,
> >> +				     const u8 *db)
> >> +{
> >> +	struct drm_display_info *info = &connector->display_info;
> >> +	struct drm_hdmi_info *hdmi = &info->hdmi;
> >> +	u8 map_len = cea_db_payload_len(db) - 1;
> >> +	u8 count;
> >> +	u64 map = 0;
> >> +
> >> +	if (map_len == 0) {
> >> +		/* All CEA modes support ycbcr420 sampling also.*/
> >> +		hdmi->y420_cmdb_map = U64_MAX;
> >> +		info->color_formats |= DRM_COLOR_FORMAT_YCRCB420;
> >> +		return;
> >> +	}
> >> +
> >> +	/*
> >> +	 * This map indicates which of the existing CEA block modes
> >> +	 * from VDB can support YCBCR420 output too. So if bit=0 is
> >> +	 * set, first mode from VDB can support YCBCR420 output too.
> >> +	 * We will parse and keep this map, before parsing VDB itself
> >> +	 * to avoid going through the same block again and again.
> >> +	 *
> >> +	 * Spec is not clear about max possible size of this block.
> >> +	 * Clamping max bitmap block size at 8 bytes. Every byte can
> >> +	 * address 8 CEA modes, in this way this map can address
> >> +	 * 8*8 = first 64 SVDs.
> >> +	 */
> >> +	if (WARN_ON_ONCE(map_len > 8))
> >> +		map_len = 8;
> >> +
> >> +	for (count = 0; count < map_len; count++)
> >> +		map |= (u64)db[2 + count] << (8 * count);
> >> +
> >> +	if (map)
> >> +		info->color_formats |= DRM_COLOR_FORMAT_YCRCB420;
> >> +
> >> +	hdmi->y420_cmdb_map = map;
> >> +}
> >> +
> >>   static int
> >>   add_cea_modes(struct drm_connector *connector, struct edid *edid)
> >>   {
> >> @@ -3522,10 +3663,17 @@ add_cea_modes(struct drm_connector *connector, struct edid *edid)
> >>   				video = db + 1;
> >>   				video_len = dbl;
> >>   				modes += do_cea_modes(connector, video, dbl);
> >> -			}
> >> -			else if (cea_db_is_hdmi_vsdb(db)) {
> >> +			} else if (cea_db_is_hdmi_vsdb(db)) {
> >>   				hdmi = db;
> >>   				hdmi_len = dbl;
> >> +			} else if (cea_db_is_y420vdb(db) &&
> >> +				   connector->ycbcr_420_allowed) {
> >> +				const u8 *vdb420 = &db[2];
> >> +
> >> +				/* Add 4:2:0(only) modes present in EDID */
> >> +				modes += do_y420vdb_modes(connector,
> >> +							  vdb420,
> >> +							  dbl - 1);
> >>   			}
> >>   		}
> >>   	}
> >> @@ -4206,6 +4354,8 @@ static void drm_parse_cea_ext(struct drm_connector *connector,
> >>   			drm_parse_hdmi_vsdb_video(connector, db);
> >>   		if (cea_db_is_hdmi_forum_vsdb(db))
> >>   			drm_parse_hdmi_forum_vsdb(connector, db);
> >> +		if (cea_db_is_y420cmdb(db))
> >> +			drm_parse_y420cmdb_bitmap(connector, db);
> >>   	}
> >>   }
> >>   
> >> @@ -4460,6 +4610,7 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
> >>   	num_modes += add_cea_modes(connector, edid);
> >>   	num_modes += add_alternate_cea_modes(connector, edid);
> >>   	num_modes += add_displayid_detailed_modes(connector, edid);
> >> +
> >>   	if (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF)
> >>   		num_modes += add_inferred_modes(connector, edid);
> >>   
> >> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> >> index 7493fd3..ce2212d 100644
> >> --- a/include/drm/drm_connector.h
> >> +++ b/include/drm/drm_connector.h
> >> @@ -137,6 +137,25 @@ struct drm_scdc {
> >>   struct drm_hdmi_info {
> >>   	/** @scdc: sink's scdc support and capabilities */
> >>   	struct drm_scdc scdc;
> >> +
> >> +	/**
> >> +	 * @y420_vdb_modes: bitmap of modes which can support ycbcr420
> >> +	 * output only (not normal RGB/YCBCR444/422 outputs). There are total
> >> +	 * 107 VICs defined by CEA-861-F spec, so the size is 128 bits to map
> >> +	 * upto 128 VICs;
> >> +	 */
> >> +	unsigned long y420_vdb_modes[BITS_TO_LONGS(128)];
> >> +
> >> +	/**
> >> +	 * @y420_cmdb_modes: bitmap of modes which can support ycbcr420
> >> +	 * output also, along with normal HDMI outputs. There are total 107
> >> +	 * VICs defined by CEA-861-F spec, so the size is 128 bits to map upto
> >> +	 * 128 VICs;
> >> +	 */
> >> +	unsigned long y420_cmdb_modes[BITS_TO_LONGS(128)];
> >> +
> >> +	/** @y420_cmdb_map: bitmap of SVD index, to extraxt vcb modes */
> >> +	unsigned long y420_cmdb_map;
> > u64, otherwise it's busted on 32bit machines.
> Got it.
> >
> > Mostl this looks pretty good. I think the main problem is the lack of
> > mode validation that would reject the 4:2:0 only modes if not supported
> > by the driver/device. I guess that's in a later patch?
> Yep, its the next patch in the series.

The only thing the next patch does is set up the y420_dc_modes, but it
doesn't use that for anything, and neither does it filter anything. I
can't find any mode filtering patch actually.

> >   If so we need to
> > reorder the series a bit to avoid regeressions.
> That patch uses parameters added in this patch, to detect the 4:2:0 only 
> modes. So cant make it before this patch.
> Let me see what best can I do on the reordering.
> 
> - Shashank
> >>   };
> >>   
> >>   /**
> >> @@ -200,6 +219,7 @@ struct drm_display_info {
> >>   #define DRM_COLOR_FORMAT_RGB444		(1<<0)
> >>   #define DRM_COLOR_FORMAT_YCRCB444	(1<<1)
> >>   #define DRM_COLOR_FORMAT_YCRCB422	(1<<2)
> >> +#define DRM_COLOR_FORMAT_YCRCB420	(1<<3)
> >>   
> >>   	/**
> >>   	 * @color_formats: HDMI Color formats, selects between RGB and YCrCb
> >> -- 
> >> 2.7.4

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [RESEND-CI v4 11/15] drm/i915: prepare scaler for YCBCR420 modeset
  2017-06-30 11:34       ` Ander Conselvan De Oliveira
@ 2017-06-30 11:59         ` Sharma, Shashank
  2017-06-30 14:15           ` Ander Conselvan De Oliveira
  0 siblings, 1 reply; 58+ messages in thread
From: Sharma, Shashank @ 2017-06-30 11:59 UTC (permalink / raw)
  To: Ander Conselvan De Oliveira, dri-devel, intel-gfx, ville.syrjala

Regards

Shashank


On 6/30/2017 5:04 PM, Ander Conselvan De Oliveira wrote:
> On Fri, 2017-06-30 at 11:20 +0530, Sharma, Shashank wrote:
>> Regards
>>
>> Shashank
>>
>>
>> On 6/27/2017 5:46 PM, Ander Conselvan De Oliveira wrote:
>>> On Wed, 2017-06-21 at 16:04 +0530, Shashank Sharma wrote:
>>>> To get a YCBCR420 output from intel platforms, we need one
>>>> scaler to scale down YCBCR444 samples to YCBCR420 samples.
>>>>
>>>> This patch:
>>>> - Does scaler allocation for HDMI ycbcr420 outputs.
>>>> - Programs PIPE_MISC register for ycbcr420 output.
>>>> - Adds a new scaler user "HDMI output" to plug-into existing
>>>>     scaler framework. This output type is identified using bit
>>>>     30 of the scaler users bitmap.
>>>>
>>>> V2: rebase
>>>> V3: rebase
>>>> V4: rebase
>>>>
>>>> Cc: Ville Syrjala <ville.syrjala@linux.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_atomic.c  |  6 ++++++
>>>>    drivers/gpu/drm/i915/intel_display.c | 26 ++++++++++++++++++++++++++
>>>>    drivers/gpu/drm/i915/intel_drv.h     | 10 +++++++++-
>>>>    drivers/gpu/drm/i915/intel_hdmi.c    | 10 ++++++++++
>>>>    drivers/gpu/drm/i915/intel_panel.c   |  3 ++-
>>>>    5 files changed, 53 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
>>>> index 36d4e63..a8c9ac5 100644
>>>> --- a/drivers/gpu/drm/i915/intel_atomic.c
>>>> +++ b/drivers/gpu/drm/i915/intel_atomic.c
>>>> @@ -264,6 +264,12 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv,
>>>>    
>>>>    			/* panel fitter case: assign as a crtc scaler */
>>>>    			scaler_id = &scaler_state->scaler_id;
>>>> +		} else if (i == SKL_HDMI_OUTPUT_INDEX) {
>>>> +			name = "HDMI-OUTPUT";
>>>> +			idx = intel_crtc->base.base.id;
>>>> +
>>>> +			/* hdmi output case: needs a pipe scaler */
>>>> +			scaler_id = &scaler_state->scaler_id;
>>>>    		} else {
>>>>    			name = "PLANE";
>>>>    
>>>> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
>>>> index da29536..983f581 100644
>>>> --- a/drivers/gpu/drm/i915/intel_display.c
>>>> +++ b/drivers/gpu/drm/i915/intel_display.c
>>>> @@ -4626,6 +4626,11 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
>>>>    	 */
>>>>    	need_scaling = src_w != dst_w || src_h != dst_h;
>>>>    
>>>> +	if (crtc_state->hdmi_output == DRM_HDMI_OUTPUT_YCBCR420
>>>> +		&& scaler_user == SKL_HDMI_OUTPUT_INDEX)
>>> Is it really necessary to check for both? If it is, what's the point of creating
>>> SKL_HDMI_OUTPUT_INDEX?
>> Yes, else this will affect scaler update for planes, as this function
>> gets called to update the plane scalers too, at that time the output
>> will be still valid (as its at CRTC level), but the
>> scaler user would be different.
> Right, so there is a need to check for scaler_user == HDMI_OUTPUT. But then
> wouldn't it be a bug if hdmi_output != YCBCR420 ?  Point is, if the caller asked
> for a HDMI_OUTPUT scaler hopefully it knows what its doing, no need to second
> guess it.
skl_update_scaler function gets called for all the users, which are:
- panel fitter
- all the planes
- newly added user hdmi_output
what about the case (assume) when we have handled hdmi_output and now we 
are handling for a plane, which doesnt need scaling.

in this case, the code will look like:
if (crtc_state->hdmi_output == DRM_HDMI_OUTPUT_YCBCR420)
       need_scaling = true /* which is wrong, as this function call is 
for plane scalar, and scaler_user = scaler */

if (crtc_state->hdmi_output == DRM_HDMI_OUTPUT_YCBCR420 &&
     scaler_user == HDMI_OUT)
     need_scaling = true /* this is correct, as I want to consume scalar only when both the conditions are true.

>>>> +		/* YCBCR 444 -> 420 conversion needs a scaler */
>>>> +		need_scaling = true;
>>>> +
>>>>    	/*
>>>>    	 * if plane is being disabled or scaler is no more required or force detach
>>>>    	 *  - free scaler binded to this plane/crtc
>>>> @@ -4673,6 +4678,26 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
>>>>    }
>>>>    
>>>>    /**
>>>> + * skl_update_scaler_hdmi_output - Stages update to scaler state for HDMI.
>>>> + * HDMI YCBCR 420 output needs a scaler, for downsampling.
>>>> + *
>>>> + * @state: crtc's scaler state
>>>> + *
>>>> + * Return
>>>> + *     0 - scaler_usage updated successfully
>>>> + *    error - requested scaling cannot be supported or other error condition
>>>> + */
>>>> +int skl_update_scaler_crtc_hdmi_output(struct intel_crtc_state *state)
>>>> +{
>>>> +	const struct drm_display_mode *mode = &state->base.adjusted_mode;
>>>> +
>>>> +	return skl_update_scaler(state, !state->base.active,
>>>> +		SKL_HDMI_OUTPUT_INDEX, &state->scaler_state.scaler_id,
>>>> +		state->pipe_src_w, state->pipe_src_h,
>>>> +		mode->crtc_hdisplay, mode->crtc_vdisplay);
>>>> +}
>>>> +
>>>> +/**
>>>>     * skl_update_scaler_crtc - Stages update to scaler state for a given crtc.
>>>>     *
>>>>     * @state: crtc's scaler state
>>>> @@ -8058,6 +8083,7 @@ static void haswell_set_pipemisc(struct drm_crtc *crtc)
>>>>    {
>>>>    	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
>>>>    	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>>>> +	enum drm_hdmi_output_type hdmi_out = intel_crtc->config->hdmi_output;
>>>>    
>>>>    	if (IS_BROADWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 9) {
>>>>    		u32 val = 0;
>>>> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
>>>> index 38fe56c..2206aa8 100644
>>>> --- a/drivers/gpu/drm/i915/intel_drv.h
>>>> +++ b/drivers/gpu/drm/i915/intel_drv.h
>>>> @@ -471,7 +471,8 @@ struct intel_crtc_scaler_state {
>>>>    	 *
>>>>    	 *     If a bit is set, a user is using a scaler.
>>>>    	 *     Here user can be a plane or crtc as defined below:
>>>> -	 *       bits 0-30 - plane (bit position is index from drm_plane_index)
>>>> +	 *       bits 0-29 - plane (bit position is index from drm_plane_index)
>>>> +	 *       bit 30    - hdmi output
>>>>    	 *       bit 31    - crtc
>>>>    	 *
>>>>    	 * Instead of creating a new index to cover planes and crtc, using
>>>> @@ -484,6 +485,12 @@ struct intel_crtc_scaler_state {
>>>>    	 * avilability.
>>>>    	 */
>>>>    #define SKL_CRTC_INDEX 31
>>>> +
>>>> +	/*
>>>> +	 * HDMI YCBCR 420 output consume a scaler. So adding a user
>>>> +	 * for HDMI output 420 requirement.
>>>> +	 */
>>>> +#define SKL_HDMI_OUTPUT_INDEX 30
>>> I'm not convinced about this. The scaler is still used as a pipe scaler and the
>>> patch even adds a call intel_pch_panel_fitting().
>> This is a special mode usage of scalar defined in the bspec, when we
>> want to run the scalar into 5x3 auto mode for YCBCR444->YCBCR420 scale down.
>> It can be used only when the PIPE_MISC is also programmed to act
>> accordingly. So this is different from using it as a panel fitter, and
>> that's why added
>> a new scalar user all together.
>>>>    	unsigned scaler_users;
>>>>    
>>>>    	/* scaler used by crtc for panel fitting purpose */
>>>> @@ -1481,6 +1488,7 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode,
>>>>    				 struct intel_crtc_state *pipe_config);
>>>>    
>>>>    int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state);
>>>> +int skl_update_scaler_crtc_hdmi_output(struct intel_crtc_state *state);
>>>>    int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state);
>>>>    
>>>>    static inline u32 intel_plane_ggtt_offset(const struct intel_plane_state *state)
>>>> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
>>>> index 22da5cd..8d5aa1e 100644
>>>> --- a/drivers/gpu/drm/i915/intel_hdmi.c
>>>> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
>>>> @@ -1415,6 +1415,7 @@ intel_hdmi_compute_ycbcr_config(struct drm_connector_state *conn_state,
>>>>    	}
>>>>    
>>>>    	if (type == DRM_HDMI_OUTPUT_YCBCR420) {
>>>> +		struct intel_crtc *intel_crtc = to_intel_crtc(conn_state->crtc);
>>>>    
>>>>    		/* YCBCR420 TMDS rate requirement is half the pixel clock */
>>>>    		config->hdmi_output = DRM_HDMI_OUTPUT_YCBCR420;
>>>> @@ -1422,6 +1423,15 @@ intel_hdmi_compute_ycbcr_config(struct drm_connector_state *conn_state,
>>>>    		*clock_12bpc /= 2;
>>>>    		*clock_8bpc /= 2;
>>>>    
>>>> +		/* YCBCR 420 output conversion needs a scaler */
>>>> +		if (skl_update_scaler_crtc_hdmi_output(config)) {
>>>> +			DRM_ERROR("Scaler allocation for output failed\n");
>>>> +			return DRM_HDMI_OUTPUT_INVALID;
>>>> +		}
>>>> +
>>>> +		/* Bind this scaler to pipe */
>>>> +		intel_pch_panel_fitting(intel_crtc, config,
>>>> +					DRM_MODE_SCALE_FULLSCREEN);
>>>>    	}
>>>>    
>>>>    	/* Encoder is capable of this output, lets commit to CRTC */
>>>> diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
>>>> index 96c2cbd..b6a32c4 100644
>>>> --- a/drivers/gpu/drm/i915/intel_panel.c
>>>> +++ b/drivers/gpu/drm/i915/intel_panel.c
>>>> @@ -110,7 +110,8 @@ intel_pch_panel_fitting(struct intel_crtc *intel_crtc,
>>>>    
>>>>    	/* Native modes don't need fitting */
>>>>    	if (adjusted_mode->crtc_hdisplay == pipe_config->pipe_src_w &&
>>>> -	    adjusted_mode->crtc_vdisplay == pipe_config->pipe_src_h)
>>>> +	    adjusted_mode->crtc_vdisplay == pipe_config->pipe_src_h &&
>>>> +	    pipe_config->hdmi_output != DRM_HDMI_OUTPUT_YCBCR420)
>>> I don't like that the knowledge that YCBCR420 needs the scaler is spread
>>> everywhere, including this function that should only deal with panel fitting. I
>>> would rather add a force parameter to intel_pch_panel_fitting() and
>>> skl_update_scaler() that would mean setup the scaler even if looks like it's not
>>> necessary. That way the hdmi code would just call them with force enabled,
>>> without sprinkling "hdmi_output == YCBCR420" everywhere.
>> As explained in the comment above, its special case usage of pipe
>> scalar, and that's why being checked specifically.
> I'm still not convinced about this. If this is a special scaler mode that is not
> panel fitting, then this should definitely not touch a function in
> intel_panel.c, specially one with "panel fitting" in the name.
>
> My point is, if this is panel fitting, then it should use panel fitting code
> without special casing. If it isn't, then it should have its own code paths. But
> this patch just creates a blurry line where the panel fitting code needs to be
> special cased for when the HDMI output is YCBCR420 and we are *not* actually
> doing panel fitting.
My understanding of the code is (please correct me if that's not) that 
any pipe scalar usages we are keeping it at
panel_fitting level, whereas any plane level stuff is called 
plane_scalar. As this new user was a usage of pipe_scalar
with a special configuration and setting, I accommodated the code in 
panel fitter level. We can also create new code
for it, but that would be unnecessary duplication of code which does the 
same thing, isn't it ?
For this usage, we just need to attach a pipe scalar, and then program 
the PIPEMISC (which we do in crtc->mode_set). Do you
think its any good reason for write a new code path altogether ?

- Shashank
>
> Ander
>

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

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [RESEND-CI v4 06/15] drm/edid: parse sink information before CEA blocks
  2017-06-30 11:46       ` Ville Syrjälä
@ 2017-06-30 12:01         ` Sharma, Shashank
  0 siblings, 0 replies; 58+ messages in thread
From: Sharma, Shashank @ 2017-06-30 12:01 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, dri-devel

Regards

Shashank


On 6/30/2017 5:16 PM, Ville Syrjälä wrote:
> On Fri, Jun 30, 2017 at 10:52:54AM +0530, Sharma, Shashank wrote:
>> Regards
>>
>> Shashank
>>
>>
>> On 6/27/2017 5:25 PM, Ville Syrjälä wrote:
>>> On Wed, Jun 21, 2017 at 04:04:04PM +0530, Shashank Sharma wrote:
>>>> CEA-861-F adds ycbcr capability map block, for HDMI 2.0 sinks.
>>>> This block contains a map of indexes of CEA modes, which can
>>>> support YCBCR 420 output also. To avoid multiple parsing of same
>>>> CEA block, let's parse the sink information and get this map, before
>>>> parsing CEA modes.
>>>>
>>>> This patch moves the call to drm_add_display_info function, before the
>>>> mode parsing block.
>>>>
>>>> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
>>>> ---
>>>>    drivers/gpu/drm/drm_edid.c | 9 +++++++--
>>>>    1 file changed, 7 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
>>>> index b4583f6..42934b2 100644
>>>> --- a/drivers/gpu/drm/drm_edid.c
>>>> +++ b/drivers/gpu/drm/drm_edid.c
>>>> @@ -4605,6 +4605,13 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
>>>>    	quirks = edid_get_quirks(edid);
>>>>    
>>>>    	/*
>>>> +	 * CEA-861-F adds ycbcr capability map block, for HDMI 2.0 sinks.
>>>> +	 * To avoid multiple parsing of same block, lets parse that map
>>>> +	 * from sink info, before parsing CEA modes.
>>>> +	 */
>>>> +	drm_add_display_info(connector, edid);
>>>> +
>>> This patch should come before the 4:2:0 mode parsing, no?
>> Dint you ask me to move it later (in the previous series comments), for
>> git-bisect regression type of changes ?
> I wanted it split out to help with bisecting. It should be early in the
> series because otherwise the rest makes no sense. And I suppose we should
> be able to push this in on its own right now. Just need a CI run for it,
> so maybe resesnd just this patch on its own.
Ok, got it.
- Shashank
>>> Otherwise I think this should be fine so
>>> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> Thanks.
>>>> +	/*
>>>>    	 * EDID spec says modes should be preferred in this order:
>>>>    	 * - preferred detailed mode
>>>>    	 * - other detailed modes from base block
>>>> @@ -4632,8 +4639,6 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
>>>>    	if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75))
>>>>    		edid_fixup_preferred(connector, quirks);
>>>>    
>>>> -	drm_add_display_info(connector, edid);
>>>> -
>>>>    	if (quirks & EDID_QUIRK_FORCE_6BPC)
>>>>    		connector->display_info.bpc = 6;
>>>>    
>>>> -- 
>>>> 2.7.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [Intel-gfx] [RESEND-CI v4 15/15] drm/i915/glk: set HDMI 2.0 identifier
  2017-06-21 10:34 ` [RESEND-CI v4 15/15] drm/i915/glk: set HDMI 2.0 identifier Shashank Sharma
@ 2017-06-30 12:07   ` Ander Conselvan De Oliveira
  2017-06-30 12:17     ` Sharma, Shashank
  0 siblings, 1 reply; 58+ messages in thread
From: Ander Conselvan De Oliveira @ 2017-06-30 12:07 UTC (permalink / raw)
  To: Shashank Sharma, dri-devel, intel-gfx, ville.syrjala

On Wed, 2017-06-21 at 16:04 +0530, Shashank Sharma wrote:
> This patch sets the is_hdmi2_src identifier in drm connector
> for GLK platform. GLK contains a native HDMI 2.0 controller.
> This identifier will help the EDID handling functions to save
> lot of work which is specific to HDMI 2.0 sources.
> 
> V3: Added this patch
> V4: Rebase
> 
> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>

This and patches 12 and 14 look fine to me. I'm not sure about the patch split,
maybe they should be squashed together in the end? And perhaps patch 10 and 13
too if the refactor I proposed are separate prep patches. But anyway, you can
use

Reviewed-by: Ander Conselvan de Oliveira <conselvan2@gmail.com>

on those if you want.


> ---
>  drivers/gpu/drm/i915/intel_hdmi.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> index 3bd9af3..0d9d088 100644
> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> @@ -1979,6 +1979,9 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
>  	connector->doublescan_allowed = 0;
>  	connector->stereo_allowed = 1;
>  
> +	if (IS_GEMINILAKE(dev_priv))
> +		connector->ycbcr_420_allowed = true;
> +
>  	intel_hdmi->ddc_bus = intel_hdmi_ddc_pin(dev_priv, port);
>  
>  	switch (port) {
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [RESEND-CI v4 04/15] drm/edid: parse YCBCR 420 videomodes from EDID
  2017-06-30 11:58       ` Ville Syrjälä
@ 2017-06-30 12:08         ` Sharma, Shashank
  0 siblings, 0 replies; 58+ messages in thread
From: Sharma, Shashank @ 2017-06-30 12:08 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, Jose Abreu, dri-devel

Regards

Shashank


On 6/30/2017 5:28 PM, Ville Syrjälä wrote:
> On Fri, Jun 30, 2017 at 10:47:48AM +0530, Sharma, Shashank wrote:
>> Regards
>>
>> Shashank
>>
>>
>> On 6/27/2017 5:22 PM, Ville Syrjälä wrote:
>>> On Wed, Jun 21, 2017 at 04:04:02PM +0530, Shashank Sharma wrote:
>>>> HDMI 2.0 spec adds support for YCBCR420 sub-sampled output.
>>>> CEA-861-F adds two new blocks in EDID's CEA extension blocks,
>>>> to provide information about sink's YCBCR420 output capabilities.
>>>>
>>>> These blocks are:
>>>>
>>>> - YCBCR420vdb(YCBCR 420 video data block):
>>>> This block contains VICs of video modes, which can be sopported only
>>>> in YCBCR420 output mode (Not in RGB/YCBCR444/422. Its like a normal
>>>> SVD block, valid for YCBCR420 modes only.
>>>>
>>>> - YCBCR420cmdb(YCBCR 420 capability map data block):
>>>> This block gives information about video modes which can support
>>>> YCBCR420 output mode also (along with RGB,YCBCR444/422 etc) This
>>>> block contains a bitmap index of normal svd videomodes, which can
>>>> support YCBCR420 output too.
>>>> So if bit 0 from first vcb byte is set, first video mode in the svd
>>>> list can support YCBCR420 output too. Bit 1 means second video mode
>>>> from svd list can support YCBCR420 output too, and so on.
>>>>
>>>> This patch adds two bitmaps in display's hdmi_info structure, one each
>>>> for VCB and VDB modes. If the source is HDMI 2.0 capable, this patch
>>>> adds:
>>>> - VDB modes (YCBCR 420 only modes) in connector's mode list, also makes
>>>>     an entry in the vdb_bitmap per vic.
>>>> - VCB modes (YCBCR 420 also modes) only entry in the vcb_bitmap.
>>>>
>>>> Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
>>>> Cc: Jose Abreu <joabreu@synopsys.com>
>>>> Cc: Emil Velikov <emil.l.velikov@gmail.com>
>>>>
>>>> V2: Addressed
>>>>       Review comments from Emil:
>>>>       - Use 1ULL<<i instead of 1<<i to make sure the output is 64bit.
>>>>       - Use the suggested method for updating dbmap.
>>>>       - Add documentation for YCBCR420_vcb_map to fix kbuild warning.
>>>>
>>>>       Review comments from Ville:
>>>>       - Do not expose the YCBCR420 flags in uabi layer, keep it internal.
>>>>       - Save a map of YCBCR420 modes for future reference.
>>>>       - Check db length before trying to parse extended tag.
>>>>       - Add a warning if there are > 64 modes in capability map block.
>>>>       - Use y420cmdb in function names and macros while dealing with vcb
>>>>         to be aligned with spec.
>>>>       - Move the display information parsing block ahead of mode parsing
>>>>         blocks.
>>>>
>>>> V3: Addressed design/review comments from Ville
>>>>       - Do not add flags in video modes, else we have to expose them to user
>>>>       - There should not be a UABI change, and kernel should detect the
>>>>         choice of the output based on type of mode, and the bitmaps.
>>>>       - Use standard bitops from kernel bitmap header, instead of calculating
>>>>         bit positions manually.
>>>>
>>>> V4: Addressed review comments from Ville:
>>>>       - s/ycbcr_420_vdb/y420vdb
>>>>       - s/ycbcr_420_vcb/y420cmdb
>>>>       - Be less verbose on description of do_y420vdb_modes
>>>>       - Move newmode variable in the loop scope.
>>>>       - Use svd_to_vic() to get a VIC, instead of 0x7f
>>>>       - Remove bitmap description for CMDB modes & VDB modes
>>>>       - Dont add connector->ycbcr_420_allowed check for cmdb modes
>>>>       - Remove 'len' variable, in is_y420cmdb function, which is used
>>>>         only once
>>>>       - Add length check in is_y420vdb function
>>>>       - Remove unnecessary if (!db) check in function parse_y420cmdb_bitmap
>>>>       - Do not add print about YCBCR 420 modes
>>>>       - Fix indentation in few places
>>>>       - Move ycbcr420_dc_modes in next patch, where its used
>>>>       - Add a separate patch for movement of drm_add_display_info()
>>>>
>>>> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
>>>> ---
>>>>    drivers/gpu/drm/drm_edid.c  | 157 +++++++++++++++++++++++++++++++++++++++++++-
>>>>    include/drm/drm_connector.h |  20 ++++++
>>>>    2 files changed, 174 insertions(+), 3 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
>>>> index e2d1b30..8c7e73b 100644
>>>> --- a/drivers/gpu/drm/drm_edid.c
>>>> +++ b/drivers/gpu/drm/drm_edid.c
>>>> @@ -2781,7 +2781,9 @@ add_detailed_modes(struct drm_connector *connector, struct edid *edid,
>>>>    #define VIDEO_BLOCK     0x02
>>>>    #define VENDOR_BLOCK    0x03
>>>>    #define SPEAKER_BLOCK	0x04
>>>> -#define VIDEO_CAPABILITY_BLOCK	0x07
>>>> +#define VIDEO_CAPABILITY_BLOCK 0x07
>>>> +#define VIDEO_DATA_BLOCK_420	0x0E
>>>> +#define VIDEO_CAP_BLOCK_Y420CMDB 0x0F
>>>>    #define EDID_BASIC_AUDIO	(1 << 6)
>>>>    #define EDID_CEA_YCRCB444	(1 << 5)
>>>>    #define EDID_CEA_YCRCB422	(1 << 4)
>>>> @@ -3153,15 +3155,79 @@ drm_display_mode_from_vic_index(struct drm_connector *connector,
>>>>    	return newmode;
>>>>    }
>>>>    
>>>> +/*
>>>> + * do_y420vdb_modes - Parse YCBCR 420 only modes
>>>> + * @connector: connector corresponding to the HDMI sink
>>>> + * @svds: start of the data block of CEA YCBCR 420 VDB
>>>> + * @len: length of the CEA YCBCR 420 VDB
>>>> + *
>>>> + * Parse the CEA-861-F YCBCR 420 Video Data Block (Y420VDB)
>>>> + * which contains modes which can be supported in YCBCR 420
>>>> + * output format only.
>>>> + */
>>>> +static int do_y420vdb_modes(struct drm_connector *connector,
>>>> +				   const u8 *svds, u8 svds_len)
>>>> +{
>>>> +	int modes = 0, i;
>>>> +	struct drm_device *dev = connector->dev;
>>>> +	struct drm_display_info *info = &connector->display_info;
>>>> +	struct drm_hdmi_info *hdmi = &info->hdmi;
>>>> +
>>>> +	for (i = 0; i < svds_len; i++) {
>>>> +		u8 vic = svd_to_vic(svds[i]);
>>>> +		struct drm_display_mode *newmode;
>>>> +
>>>> +		newmode = drm_mode_duplicate(dev, &edid_cea_modes[vic]);
>>>> +		if (!newmode)
>>>> +			break;
>>>> +		bitmap_set(hdmi->y420_vdb_modes, vic, 1);
>>>> +		drm_mode_probed_add(connector, newmode);
>>>> +		modes++;
>>>> +	}
>>>> +
>>>> +	if (modes > 0)
>>>> +		info->color_formats |= DRM_COLOR_FORMAT_YCRCB420;
>>>> +	return modes;
>>>> +}
>>>> +
>>>> +/*
>>>> + * drm_add_cmdb_modes - Add a YCBCR 420 mode into bitmap
>>>> + * @connector: connector corresponding to the HDMI sink
>>>> + * @vic: CEA vic for the video mode to be added in the map
>>>> + *
>>>> + * Makes an entry for a videomode in the YCBCR 420 bitmap
>>>> + */
>>>> +static void
>>>> +drm_add_cmdb_modes(struct drm_connector *connector, u8 svd)
>>>> +{
>>>> +	u8 vic = svd_to_vic(svd);
>>>> +	struct drm_hdmi_info *hdmi = &connector->display_info.hdmi;
>>>> +
>>>> +	bitmap_set(hdmi->y420_cmdb_modes, vic, 1);
>>>> +}
>>>> +
>>>>    static int
>>>>    do_cea_modes(struct drm_connector *connector, const u8 *db, u8 len)
>>>>    {
>>>>    	int i, modes = 0;
>>>> +	struct drm_hdmi_info *hdmi = &connector->display_info.hdmi;
>>>>    
>>>>    	for (i = 0; i < len; i++) {
>>>>    		struct drm_display_mode *mode;
>>>>    		mode = drm_display_mode_from_vic_index(connector, db, len, i);
>>>>    		if (mode) {
>>>> +			/*
>>>> +			 * YCBCR420 capability block contains a bitmap which
>>>> +			 * gives the index of CEA modes from CEA VDB, which
>>>> +			 * can support YCBCR 420 sampling output also (apart
>>>> +			 * from RGB/YCBCR444 etc).
>>>> +			 * For example, if the bit 0 in bitmap is set,
>>>> +			 * first mode in VDB can support YCBCR420 output too.
>>>> +			 * Add YCBCR420 modes only if sink is HDMI 2.0 capable.
>>>> +			 */
>>>> +			if (test_bit(i, &hdmi->y420_cmdb_map))
>>>> +				drm_add_cmdb_modes(connector, db[i]);
>>>> +
>>>>    			drm_mode_probed_add(connector, mode);
>>>>    			modes++;
>>>>    		}
>>>> @@ -3437,6 +3503,12 @@ do_hdmi_vsdb_modes(struct drm_connector *connector, const u8 *db, u8 len,
>>>>    }
>>>>    
>>>>    static int
>>>> +cea_db_extended_tag(const u8 *db)
>>>> +{
>>>> +	return db[1];
>>>> +}
>>>> +
>>>> +static int
>>>>    cea_db_payload_len(const u8 *db)
>>>>    {
>>>>    	return db[0] & 0x1f;
>>>> @@ -3497,9 +3569,78 @@ static bool cea_db_is_hdmi_forum_vsdb(const u8 *db)
>>>>    	return oui == HDMI_FORUM_IEEE_OUI;
>>>>    }
>>>>    
>>>> +static bool cea_db_is_y420cmdb(const u8 *db)
>>>> +{
>>>> +
>>>> +	if (cea_db_tag(db) != VIDEO_CAPABILITY_BLOCK)
>>> Still would like to see that patch to clean up the current extended tag
>>> usage...
>> Yep, its on the way, running a bit loaded.
>>>> +		return false;
>>>> +
>>>> +	if (!cea_db_payload_len(db))
>>>> +		return false;
>>>> +
>>>> +	if (cea_db_extended_tag(db) != VIDEO_CAP_BLOCK_Y420CMDB)
>>>> +		return false;
>>>> +
>>>> +	return true;
>>>> +}
>>>> +
>>>> +static bool cea_db_is_y420vdb(const u8 *db)
>>>> +{
>>>> +	if (cea_db_tag(db) != VIDEO_CAPABILITY_BLOCK)
>>>> +		return false;
>>>> +
>>>> +	if (!cea_db_payload_len(db))
>>>> +		return false;
>>>> +
>>>> +	if (cea_db_extended_tag(db) != VIDEO_DATA_BLOCK_420)
>>>> +		return false;
>>>> +
>>>> +	return true;
>>>> +}
>>>> +
>>>>    #define for_each_cea_db(cea, i, start, end) \
>>>>    	for ((i) = (start); (i) < (end) && (i) + cea_db_payload_len(&(cea)[(i)]) < (end); (i) += cea_db_payload_len(&(cea)[(i)]) + 1)
>>>>    
>>>> +static void drm_parse_y420cmdb_bitmap(struct drm_connector *connector,
>>>> +				     const u8 *db)
>>>> +{
>>>> +	struct drm_display_info *info = &connector->display_info;
>>>> +	struct drm_hdmi_info *hdmi = &info->hdmi;
>>>> +	u8 map_len = cea_db_payload_len(db) - 1;
>>>> +	u8 count;
>>>> +	u64 map = 0;
>>>> +
>>>> +	if (map_len == 0) {
>>>> +		/* All CEA modes support ycbcr420 sampling also.*/
>>>> +		hdmi->y420_cmdb_map = U64_MAX;
>>>> +		info->color_formats |= DRM_COLOR_FORMAT_YCRCB420;
>>>> +		return;
>>>> +	}
>>>> +
>>>> +	/*
>>>> +	 * This map indicates which of the existing CEA block modes
>>>> +	 * from VDB can support YCBCR420 output too. So if bit=0 is
>>>> +	 * set, first mode from VDB can support YCBCR420 output too.
>>>> +	 * We will parse and keep this map, before parsing VDB itself
>>>> +	 * to avoid going through the same block again and again.
>>>> +	 *
>>>> +	 * Spec is not clear about max possible size of this block.
>>>> +	 * Clamping max bitmap block size at 8 bytes. Every byte can
>>>> +	 * address 8 CEA modes, in this way this map can address
>>>> +	 * 8*8 = first 64 SVDs.
>>>> +	 */
>>>> +	if (WARN_ON_ONCE(map_len > 8))
>>>> +		map_len = 8;
>>>> +
>>>> +	for (count = 0; count < map_len; count++)
>>>> +		map |= (u64)db[2 + count] << (8 * count);
>>>> +
>>>> +	if (map)
>>>> +		info->color_formats |= DRM_COLOR_FORMAT_YCRCB420;
>>>> +
>>>> +	hdmi->y420_cmdb_map = map;
>>>> +}
>>>> +
>>>>    static int
>>>>    add_cea_modes(struct drm_connector *connector, struct edid *edid)
>>>>    {
>>>> @@ -3522,10 +3663,17 @@ add_cea_modes(struct drm_connector *connector, struct edid *edid)
>>>>    				video = db + 1;
>>>>    				video_len = dbl;
>>>>    				modes += do_cea_modes(connector, video, dbl);
>>>> -			}
>>>> -			else if (cea_db_is_hdmi_vsdb(db)) {
>>>> +			} else if (cea_db_is_hdmi_vsdb(db)) {
>>>>    				hdmi = db;
>>>>    				hdmi_len = dbl;
>>>> +			} else if (cea_db_is_y420vdb(db) &&
>>>> +				   connector->ycbcr_420_allowed) {
>>>> +				const u8 *vdb420 = &db[2];
>>>> +
>>>> +				/* Add 4:2:0(only) modes present in EDID */
>>>> +				modes += do_y420vdb_modes(connector,
>>>> +							  vdb420,
>>>> +							  dbl - 1);
>>>>    			}
>>>>    		}
>>>>    	}
>>>> @@ -4206,6 +4354,8 @@ static void drm_parse_cea_ext(struct drm_connector *connector,
>>>>    			drm_parse_hdmi_vsdb_video(connector, db);
>>>>    		if (cea_db_is_hdmi_forum_vsdb(db))
>>>>    			drm_parse_hdmi_forum_vsdb(connector, db);
>>>> +		if (cea_db_is_y420cmdb(db))
>>>> +			drm_parse_y420cmdb_bitmap(connector, db);
>>>>    	}
>>>>    }
>>>>    
>>>> @@ -4460,6 +4610,7 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
>>>>    	num_modes += add_cea_modes(connector, edid);
>>>>    	num_modes += add_alternate_cea_modes(connector, edid);
>>>>    	num_modes += add_displayid_detailed_modes(connector, edid);
>>>> +
>>>>    	if (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF)
>>>>    		num_modes += add_inferred_modes(connector, edid);
>>>>    
>>>> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
>>>> index 7493fd3..ce2212d 100644
>>>> --- a/include/drm/drm_connector.h
>>>> +++ b/include/drm/drm_connector.h
>>>> @@ -137,6 +137,25 @@ struct drm_scdc {
>>>>    struct drm_hdmi_info {
>>>>    	/** @scdc: sink's scdc support and capabilities */
>>>>    	struct drm_scdc scdc;
>>>> +
>>>> +	/**
>>>> +	 * @y420_vdb_modes: bitmap of modes which can support ycbcr420
>>>> +	 * output only (not normal RGB/YCBCR444/422 outputs). There are total
>>>> +	 * 107 VICs defined by CEA-861-F spec, so the size is 128 bits to map
>>>> +	 * upto 128 VICs;
>>>> +	 */
>>>> +	unsigned long y420_vdb_modes[BITS_TO_LONGS(128)];
>>>> +
>>>> +	/**
>>>> +	 * @y420_cmdb_modes: bitmap of modes which can support ycbcr420
>>>> +	 * output also, along with normal HDMI outputs. There are total 107
>>>> +	 * VICs defined by CEA-861-F spec, so the size is 128 bits to map upto
>>>> +	 * 128 VICs;
>>>> +	 */
>>>> +	unsigned long y420_cmdb_modes[BITS_TO_LONGS(128)];
>>>> +
>>>> +	/** @y420_cmdb_map: bitmap of SVD index, to extraxt vcb modes */
>>>> +	unsigned long y420_cmdb_map;
>>> u64, otherwise it's busted on 32bit machines.
>> Got it.
>>> Mostl this looks pretty good. I think the main problem is the lack of
>>> mode validation that would reject the 4:2:0 only modes if not supported
>>> by the driver/device. I guess that's in a later patch?
>> Yep, its the next patch in the series.
> The only thing the next patch does is set up the y420_dc_modes, but it
> doesn't use that for anything, and neither does it filter anything. I
> can't find any mode filtering patch actually.
Perhaps I misunderstood your question. If you are asking for the patch, 
in which you asked to remove the
420_only modes, at connector_probe level (instead of blocking the read 
of 420_only modes based on connector->y420_allowed),
its being prepared now. It should be available with V5.

- Shashank
>>>    If so we need to
>>> reorder the series a bit to avoid regeressions.
>> That patch uses parameters added in this patch, to detect the 4:2:0 only
>> modes. So cant make it before this patch.
>> Let me see what best can I do on the reordering.
>>
>> - Shashank
>>>>    };
>>>>    
>>>>    /**
>>>> @@ -200,6 +219,7 @@ struct drm_display_info {
>>>>    #define DRM_COLOR_FORMAT_RGB444		(1<<0)
>>>>    #define DRM_COLOR_FORMAT_YCRCB444	(1<<1)
>>>>    #define DRM_COLOR_FORMAT_YCRCB422	(1<<2)
>>>> +#define DRM_COLOR_FORMAT_YCRCB420	(1<<3)
>>>>    
>>>>    	/**
>>>>    	 * @color_formats: HDMI Color formats, selects between RGB and YCrCb
>>>> -- 
>>>> 2.7.4

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

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [RESEND-CI v4 15/15] drm/i915/glk: set HDMI 2.0 identifier
  2017-06-30 12:07   ` [Intel-gfx] " Ander Conselvan De Oliveira
@ 2017-06-30 12:17     ` Sharma, Shashank
  2017-06-30 13:28       ` [Intel-gfx] " Ander Conselvan De Oliveira
  0 siblings, 1 reply; 58+ messages in thread
From: Sharma, Shashank @ 2017-06-30 12:17 UTC (permalink / raw)
  To: Ander Conselvan De Oliveira, dri-devel, intel-gfx, ville.syrjala

Regards

Shashank


On 6/30/2017 5:37 PM, Ander Conselvan De Oliveira wrote:
> On Wed, 2017-06-21 at 16:04 +0530, Shashank Sharma wrote:
>> This patch sets the is_hdmi2_src identifier in drm connector
>> for GLK platform. GLK contains a native HDMI 2.0 controller.
>> This identifier will help the EDID handling functions to save
>> lot of work which is specific to HDMI 2.0 sources.
>>
>> V3: Added this patch
>> V4: Rebase
>>
>> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
> This and patches 12 and 14 look fine to me. I'm not sure about the patch split,
> maybe they should be squashed together in the end? And perhaps patch 10 and 13
> too if the refactor I proposed are separate prep patches.
In fact this is exactly how I prepared at the first place, keeping all 
the crtc/pipe level changes together.
But then I thought the patch might be touching too many things, and 
might be too big or complex for
review, that's why I had split into 3-4 small patches :-)
>   But anyway, you can
> use
>
> Reviewed-by: Ander Conselvan de Oliveira <conselvan2@gmail.com>
>
> on those if you want.
Thanks, I guess this applies for 12,14,10,13 and 15 (with a separate 
patch for CSC coeff handling).
Please correct me if I misunderstood.

- Shashank
>
>
>> ---
>>   drivers/gpu/drm/i915/intel_hdmi.c | 3 +++
>>   1 file changed, 3 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
>> index 3bd9af3..0d9d088 100644
>> --- a/drivers/gpu/drm/i915/intel_hdmi.c
>> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
>> @@ -1979,6 +1979,9 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
>>   	connector->doublescan_allowed = 0;
>>   	connector->stereo_allowed = 1;
>>   
>> +	if (IS_GEMINILAKE(dev_priv))
>> +		connector->ycbcr_420_allowed = true;
>> +
>>   	intel_hdmi->ddc_bus = intel_hdmi_ddc_pin(dev_priv, port);
>>   
>>   	switch (port) {

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

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [Intel-gfx] [RESEND-CI v4 15/15] drm/i915/glk: set HDMI 2.0 identifier
  2017-06-30 12:17     ` Sharma, Shashank
@ 2017-06-30 13:28       ` Ander Conselvan De Oliveira
  0 siblings, 0 replies; 58+ messages in thread
From: Ander Conselvan De Oliveira @ 2017-06-30 13:28 UTC (permalink / raw)
  To: Sharma, Shashank, dri-devel, intel-gfx, ville.syrjala

On Fri, 2017-06-30 at 17:47 +0530, Sharma, Shashank wrote:
> Regards
> 
> Shashank
> 
> 
> On 6/30/2017 5:37 PM, Ander Conselvan De Oliveira wrote:
> > On Wed, 2017-06-21 at 16:04 +0530, Shashank Sharma wrote:
> > > This patch sets the is_hdmi2_src identifier in drm connector
> > > for GLK platform. GLK contains a native HDMI 2.0 controller.
> > > This identifier will help the EDID handling functions to save
> > > lot of work which is specific to HDMI 2.0 sources.
> > > 
> > > V3: Added this patch
> > > V4: Rebase
> > > 
> > > Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
> > 
> > This and patches 12 and 14 look fine to me. I'm not sure about the patch split,
> > maybe they should be squashed together in the end? And perhaps patch 10 and 13
> > too if the refactor I proposed are separate prep patches.
> 
> In fact this is exactly how I prepared at the first place, keeping all 
> the crtc/pipe level changes together.
> But then I thought the patch might be touching too many things, and 
> might be too big or complex for
> review, that's why I had split into 3-4 small patches :-)
> >   But anyway, you can
> > use
> > 
> > Reviewed-by: Ander Conselvan de Oliveira <conselvan2@gmail.com>
> > 
> > on those if you want.
> 
> Thanks, I guess this applies for 12,14,10,13 and 15 (with a separate 
> patch for CSC coeff handling).
> Please correct me if I misunderstood.

This applies to 12, 14 and 15.

Ander

> 
> - Shashank
> > 
> > 
> > > ---
> > >   drivers/gpu/drm/i915/intel_hdmi.c | 3 +++
> > >   1 file changed, 3 insertions(+)
> > > 
> > > diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> > > index 3bd9af3..0d9d088 100644
> > > --- a/drivers/gpu/drm/i915/intel_hdmi.c
> > > +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> > > @@ -1979,6 +1979,9 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
> > >   	connector->doublescan_allowed = 0;
> > >   	connector->stereo_allowed = 1;
> > >   
> > > +	if (IS_GEMINILAKE(dev_priv))
> > > +		connector->ycbcr_420_allowed = true;
> > > +
> > >   	intel_hdmi->ddc_bus = intel_hdmi_ddc_pin(dev_priv, port);
> > >   
> > >   	switch (port) {
> 
> 
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [RESEND-CI v4 11/15] drm/i915: prepare scaler for YCBCR420 modeset
  2017-06-30 11:59         ` Sharma, Shashank
@ 2017-06-30 14:15           ` Ander Conselvan De Oliveira
  2017-06-30 14:27             ` Sharma, Shashank
  0 siblings, 1 reply; 58+ messages in thread
From: Ander Conselvan De Oliveira @ 2017-06-30 14:15 UTC (permalink / raw)
  To: Sharma, Shashank, dri-devel, intel-gfx, ville.syrjala

On Fri, 2017-06-30 at 17:29 +0530, Sharma, Shashank wrote:
> Regards
> 
> Shashank
> 
> 
> On 6/30/2017 5:04 PM, Ander Conselvan De Oliveira wrote:
> > On Fri, 2017-06-30 at 11:20 +0530, Sharma, Shashank wrote:
> > > Regards
> > > 
> > > Shashank
> > > 
> > > 
> > > On 6/27/2017 5:46 PM, Ander Conselvan De Oliveira wrote:
> > > > On Wed, 2017-06-21 at 16:04 +0530, Shashank Sharma wrote:
> > > > > To get a YCBCR420 output from intel platforms, we need one
> > > > > scaler to scale down YCBCR444 samples to YCBCR420 samples.
> > > > > 
> > > > > This patch:
> > > > > - Does scaler allocation for HDMI ycbcr420 outputs.
> > > > > - Programs PIPE_MISC register for ycbcr420 output.
> > > > > - Adds a new scaler user "HDMI output" to plug-into existing
> > > > >     scaler framework. This output type is identified using bit
> > > > >     30 of the scaler users bitmap.
> > > > > 
> > > > > V2: rebase
> > > > > V3: rebase
> > > > > V4: rebase
> > > > > 
> > > > > Cc: Ville Syrjala <ville.syrjala@linux.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_atomic.c  |  6 ++++++
> > > > >    drivers/gpu/drm/i915/intel_display.c | 26 ++++++++++++++++++++++++++
> > > > >    drivers/gpu/drm/i915/intel_drv.h     | 10 +++++++++-
> > > > >    drivers/gpu/drm/i915/intel_hdmi.c    | 10 ++++++++++
> > > > >    drivers/gpu/drm/i915/intel_panel.c   |  3 ++-
> > > > >    5 files changed, 53 insertions(+), 2 deletions(-)
> > > > > 
> > > > > diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
> > > > > index 36d4e63..a8c9ac5 100644
> > > > > --- a/drivers/gpu/drm/i915/intel_atomic.c
> > > > > +++ b/drivers/gpu/drm/i915/intel_atomic.c
> > > > > @@ -264,6 +264,12 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv,
> > > > >    
> > > > >    			/* panel fitter case: assign as a crtc scaler */
> > > > >    			scaler_id = &scaler_state->scaler_id;
> > > > > +		} else if (i == SKL_HDMI_OUTPUT_INDEX) {
> > > > > +			name = "HDMI-OUTPUT";
> > > > > +			idx = intel_crtc->base.base.id;
> > > > > +
> > > > > +			/* hdmi output case: needs a pipe scaler */
> > > > > +			scaler_id = &scaler_state->scaler_id;
> > > > >    		} else {
> > > > >    			name = "PLANE";
> > > > >    
> > > > > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > > > > index da29536..983f581 100644
> > > > > --- a/drivers/gpu/drm/i915/intel_display.c
> > > > > +++ b/drivers/gpu/drm/i915/intel_display.c
> > > > > @@ -4626,6 +4626,11 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
> > > > >    	 */
> > > > >    	need_scaling = src_w != dst_w || src_h != dst_h;
> > > > >    
> > > > > +	if (crtc_state->hdmi_output == DRM_HDMI_OUTPUT_YCBCR420
> > > > > +		&& scaler_user == SKL_HDMI_OUTPUT_INDEX)
> > > > 
> > > > Is it really necessary to check for both? If it is, what's the point of creating
> > > > SKL_HDMI_OUTPUT_INDEX?
> > > 
> > > Yes, else this will affect scaler update for planes, as this function
> > > gets called to update the plane scalers too, at that time the output
> > > will be still valid (as its at CRTC level), but the
> > > scaler user would be different.
> > 
> > Right, so there is a need to check for scaler_user == HDMI_OUTPUT. But then
> > wouldn't it be a bug if hdmi_output != YCBCR420 ?  Point is, if the caller asked
> > for a HDMI_OUTPUT scaler hopefully it knows what its doing, no need to second
> > guess it.
> 
> skl_update_scaler function gets called for all the users, which are:
> - panel fitter
> - all the planes
> - newly added user hdmi_output
> what about the case (assume) when we have handled hdmi_output and now we 
> are handling for a plane, which doesnt need scaling.
> 
> in this case, the code will look like:
> if (crtc_state->hdmi_output == DRM_HDMI_OUTPUT_YCBCR420)
>        need_scaling = true /* which is wrong, as this function call is 
> for plane scalar, and scaler_user = scaler */
> 
> if (crtc_state->hdmi_output == DRM_HDMI_OUTPUT_YCBCR420 &&
>      scaler_user == HDMI_OUT)
>      need_scaling = true /* this is correct, as I want to consume scalar only when both the conditions are true.


I meant to do just

	if (scaler_user == SKL_HDMI_OUTPUT_INDEX)
		...;

I failed to notice the ambiguity in abbreviating to just HDMI_OUTPUT. But the
caller shouldn't request it if it doesn't need it, right?

> 
> > > > > +		/* YCBCR 444 -> 420 conversion needs a scaler */
> > > > > +		need_scaling = true;
> > > > > +
> > > > >    	/*
> > > > >    	 * if plane is being disabled or scaler is no more required or force detach
> > > > >    	 *  - free scaler binded to this plane/crtc
> > > > > @@ -4673,6 +4678,26 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
> > > > >    }
> > > > >    
> > > > >    /**
> > > > > + * skl_update_scaler_hdmi_output - Stages update to scaler state for HDMI.
> > > > > + * HDMI YCBCR 420 output needs a scaler, for downsampling.
> > > > > + *
> > > > > + * @state: crtc's scaler state
> > > > > + *
> > > > > + * Return
> > > > > + *     0 - scaler_usage updated successfully
> > > > > + *    error - requested scaling cannot be supported or other error condition
> > > > > + */
> > > > > +int skl_update_scaler_crtc_hdmi_output(struct intel_crtc_state *state)
> > > > > +{
> > > > > +	const struct drm_display_mode *mode = &state->base.adjusted_mode;
> > > > > +
> > > > > +	return skl_update_scaler(state, !state->base.active,
> > > > > +		SKL_HDMI_OUTPUT_INDEX, &state->scaler_state.scaler_id,
> > > > > +		state->pipe_src_w, state->pipe_src_h,
> > > > > +		mode->crtc_hdisplay, mode->crtc_vdisplay);
> > > > > +}
> > > > > +
> > > > > +/**
> > > > >     * skl_update_scaler_crtc - Stages update to scaler state for a given crtc.
> > > > >     *
> > > > >     * @state: crtc's scaler state
> > > > > @@ -8058,6 +8083,7 @@ static void haswell_set_pipemisc(struct drm_crtc *crtc)
> > > > >    {
> > > > >    	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
> > > > >    	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> > > > > +	enum drm_hdmi_output_type hdmi_out = intel_crtc->config->hdmi_output;
> > > > >    
> > > > >    	if (IS_BROADWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 9) {
> > > > >    		u32 val = 0;
> > > > > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > > > > index 38fe56c..2206aa8 100644
> > > > > --- a/drivers/gpu/drm/i915/intel_drv.h
> > > > > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > > > > @@ -471,7 +471,8 @@ struct intel_crtc_scaler_state {
> > > > >    	 *
> > > > >    	 *     If a bit is set, a user is using a scaler.
> > > > >    	 *     Here user can be a plane or crtc as defined below:
> > > > > -	 *       bits 0-30 - plane (bit position is index from drm_plane_index)
> > > > > +	 *       bits 0-29 - plane (bit position is index from drm_plane_index)
> > > > > +	 *       bit 30    - hdmi output
> > > > >    	 *       bit 31    - crtc
> > > > >    	 *
> > > > >    	 * Instead of creating a new index to cover planes and crtc, using
> > > > > @@ -484,6 +485,12 @@ struct intel_crtc_scaler_state {
> > > > >    	 * avilability.
> > > > >    	 */
> > > > >    #define SKL_CRTC_INDEX 31
> > > > > +
> > > > > +	/*
> > > > > +	 * HDMI YCBCR 420 output consume a scaler. So adding a user
> > > > > +	 * for HDMI output 420 requirement.
> > > > > +	 */
> > > > > +#define SKL_HDMI_OUTPUT_INDEX 30
> > > > 
> > > > I'm not convinced about this. The scaler is still used as a pipe scaler and the
> > > > patch even adds a call intel_pch_panel_fitting().
> > > 
> > > This is a special mode usage of scalar defined in the bspec, when we
> > > want to run the scalar into 5x3 auto mode for YCBCR444->YCBCR420 scale down.
> > > It can be used only when the PIPE_MISC is also programmed to act
> > > accordingly. So this is different from using it as a panel fitter, and
> > > that's why added
> > > a new scalar user all together.
> > > > >    	unsigned scaler_users;
> > > > >    
> > > > >    	/* scaler used by crtc for panel fitting purpose */
> > > > > @@ -1481,6 +1488,7 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode,
> > > > >    				 struct intel_crtc_state *pipe_config);
> > > > >    
> > > > >    int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state);
> > > > > +int skl_update_scaler_crtc_hdmi_output(struct intel_crtc_state *state);
> > > > >    int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state);
> > > > >    
> > > > >    static inline u32 intel_plane_ggtt_offset(const struct intel_plane_state *state)
> > > > > diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> > > > > index 22da5cd..8d5aa1e 100644
> > > > > --- a/drivers/gpu/drm/i915/intel_hdmi.c
> > > > > +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> > > > > @@ -1415,6 +1415,7 @@ intel_hdmi_compute_ycbcr_config(struct drm_connector_state *conn_state,
> > > > >    	}
> > > > >    
> > > > >    	if (type == DRM_HDMI_OUTPUT_YCBCR420) {
> > > > > +		struct intel_crtc *intel_crtc = to_intel_crtc(conn_state->crtc);
> > > > >    
> > > > >    		/* YCBCR420 TMDS rate requirement is half the pixel clock */
> > > > >    		config->hdmi_output = DRM_HDMI_OUTPUT_YCBCR420;
> > > > > @@ -1422,6 +1423,15 @@ intel_hdmi_compute_ycbcr_config(struct drm_connector_state *conn_state,
> > > > >    		*clock_12bpc /= 2;
> > > > >    		*clock_8bpc /= 2;
> > > > >    
> > > > > +		/* YCBCR 420 output conversion needs a scaler */
> > > > > +		if (skl_update_scaler_crtc_hdmi_output(config)) {
> > > > > +			DRM_ERROR("Scaler allocation for output failed\n");
> > > > > +			return DRM_HDMI_OUTPUT_INVALID;
> > > > > +		}
> > > > > +
> > > > > +		/* Bind this scaler to pipe */
> > > > > +		intel_pch_panel_fitting(intel_crtc, config,
> > > > > +					DRM_MODE_SCALE_FULLSCREEN);
> > > > >    	}
> > > > >    
> > > > >    	/* Encoder is capable of this output, lets commit to CRTC */
> > > > > diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
> > > > > index 96c2cbd..b6a32c4 100644
> > > > > --- a/drivers/gpu/drm/i915/intel_panel.c
> > > > > +++ b/drivers/gpu/drm/i915/intel_panel.c
> > > > > @@ -110,7 +110,8 @@ intel_pch_panel_fitting(struct intel_crtc *intel_crtc,
> > > > >    
> > > > >    	/* Native modes don't need fitting */
> > > > >    	if (adjusted_mode->crtc_hdisplay == pipe_config->pipe_src_w &&
> > > > > -	    adjusted_mode->crtc_vdisplay == pipe_config->pipe_src_h)
> > > > > +	    adjusted_mode->crtc_vdisplay == pipe_config->pipe_src_h &&
> > > > > +	    pipe_config->hdmi_output != DRM_HDMI_OUTPUT_YCBCR420)
> > > > 
> > > > I don't like that the knowledge that YCBCR420 needs the scaler is spread
> > > > everywhere, including this function that should only deal with panel fitting. I
> > > > would rather add a force parameter to intel_pch_panel_fitting() and
> > > > skl_update_scaler() that would mean setup the scaler even if looks like it's not
> > > > necessary. That way the hdmi code would just call them with force enabled,
> > > > without sprinkling "hdmi_output == YCBCR420" everywhere.
> > > 
> > > As explained in the comment above, its special case usage of pipe
> > > scalar, and that's why being checked specifically.
> > 
> > I'm still not convinced about this. If this is a special scaler mode that is not
> > panel fitting, then this should definitely not touch a function in
> > intel_panel.c, specially one with "panel fitting" in the name.
> > 
> > My point is, if this is panel fitting, then it should use panel fitting code
> > without special casing. If it isn't, then it should have its own code paths. But
> > this patch just creates a blurry line where the panel fitting code needs to be
> > special cased for when the HDMI output is YCBCR420 and we are *not* actually
> > doing panel fitting.
> 
> My understanding of the code is (please correct me if that's not) that 
> any pipe scalar usages we are keeping it at
> panel_fitting level, whereas any plane level stuff is called 
> plane_scalar. As this new user was a usage of pipe_scalar
> with a special configuration and setting, I accommodated the code in 
> panel fitter level. We can also create new code
> for it, but that would be unnecessary duplication of code which does the 
> same thing, isn't it ?

The code as it is in this patch asks for something called an HDMI_OUTPUT scaler,
and then when it is time to enable it, it asks the panel fitter to be enabled.
Notice the inconsistency?

I like to either call it a panel fitter and treat it as panel fitter, or call it
a new type of scaler and have a proper interface for it. I don't think the
current solution reused much of the code anyway. The relevant part from
intel_pch_panel_fitting() is

        case DRM_MODE_SCALE_FULLSCREEN:                                                                            
                x = y = 0;                                                                                         
                width = adjusted_mode->crtc_hdisplay;                                                              
                height = adjusted_mode->crtc_vdisplay;                                                             
                break;                                                                                             

        pipe_config->pch_pfit.pos = (x << 16) | y;
	pipe_config->pch_pfit.size = (width << 16) | height;
	pipe_config->pch_pfit.enabled = pipe_config->pch_pfit.size != 0;

. The other part is recycling the call to skylake_pfit_enable() in
haswell_crtc_enable(). That call is just scaler register programming, basically:

	if (... pch_pfit.enabled) {
		...
                id = scaler_state->scaler_id;                                                                      
                I915_WRITE(SKL_PS_CTRL(pipe, id), PS_SCALER_EN |                                                   
                        PS_FILTER_MEDIUM | scaler_state->scalers[id].mode);                                        
                I915_WRITE(SKL_PS_WIN_POS(pipe, id), crtc->config->pch_pfit.pos);
                I915_WRITE(SKL_PS_WIN_SZ(pipe, id), crtc->config->pch_pfit.size);
	}

I think the issue here is that there isn't a good layer of abstraction between
"skylake" panel fitting and the scalers. It would probably be much better if the
register programming logic for them would be in a scaler_enable() function since
that is duplicated here and there. It would probably be good to have a proper
struct scaler that we can pass to certain functions too.

Anyway, I think the scaler interface could be improved in general. I'm not
saying it should be done as part of this patch, but at the same time I'd like to
avoid creating an even bigger mess to sort out in the future. To sum it up, I'd
be equaly fine with either of the proposals below:

- find a way to not have a special HDMI OUTPUT scaler and reuse the panel
fitting code completely, without sprinkling checks for YCBCR420 into it;
- create a new path for the new type of scaler, completely independent of panel
fitting.

Anything else makes it unclear which part of the code is responsible for what,
which I believe is a bad thing.

Ander

> For this usage, we just need to attach a pipe scalar, and then program 
> the PIPEMISC (which we do in crtc->mode_set). Do you
> think its any good reason for write a new code path altogether ?
> 
> - Shashank
> > 
> > Ander
> > 
> 
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [RESEND-CI v4 11/15] drm/i915: prepare scaler for YCBCR420 modeset
  2017-06-30 14:15           ` Ander Conselvan De Oliveira
@ 2017-06-30 14:27             ` Sharma, Shashank
  0 siblings, 0 replies; 58+ messages in thread
From: Sharma, Shashank @ 2017-06-30 14:27 UTC (permalink / raw)
  To: Ander Conselvan De Oliveira, dri-devel, intel-gfx, ville.syrjala

Regards

Shashank


On 6/30/2017 7:45 PM, Ander Conselvan De Oliveira wrote:
> On Fri, 2017-06-30 at 17:29 +0530, Sharma, Shashank wrote:
>> Regards
>>
>> Shashank
>>
>>
>> On 6/30/2017 5:04 PM, Ander Conselvan De Oliveira wrote:
>>> On Fri, 2017-06-30 at 11:20 +0530, Sharma, Shashank wrote:
>>>> Regards
>>>>
>>>> Shashank
>>>>
>>>>
>>>> On 6/27/2017 5:46 PM, Ander Conselvan De Oliveira wrote:
>>>>> On Wed, 2017-06-21 at 16:04 +0530, Shashank Sharma wrote:
>>>>>> To get a YCBCR420 output from intel platforms, we need one
>>>>>> scaler to scale down YCBCR444 samples to YCBCR420 samples.
>>>>>>
>>>>>> This patch:
>>>>>> - Does scaler allocation for HDMI ycbcr420 outputs.
>>>>>> - Programs PIPE_MISC register for ycbcr420 output.
>>>>>> - Adds a new scaler user "HDMI output" to plug-into existing
>>>>>>      scaler framework. This output type is identified using bit
>>>>>>      30 of the scaler users bitmap.
>>>>>>
>>>>>> V2: rebase
>>>>>> V3: rebase
>>>>>> V4: rebase
>>>>>>
>>>>>> Cc: Ville Syrjala <ville.syrjala@linux.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_atomic.c  |  6 ++++++
>>>>>>     drivers/gpu/drm/i915/intel_display.c | 26 ++++++++++++++++++++++++++
>>>>>>     drivers/gpu/drm/i915/intel_drv.h     | 10 +++++++++-
>>>>>>     drivers/gpu/drm/i915/intel_hdmi.c    | 10 ++++++++++
>>>>>>     drivers/gpu/drm/i915/intel_panel.c   |  3 ++-
>>>>>>     5 files changed, 53 insertions(+), 2 deletions(-)
>>>>>>
>>>>>> diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
>>>>>> index 36d4e63..a8c9ac5 100644
>>>>>> --- a/drivers/gpu/drm/i915/intel_atomic.c
>>>>>> +++ b/drivers/gpu/drm/i915/intel_atomic.c
>>>>>> @@ -264,6 +264,12 @@ int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv,
>>>>>>     
>>>>>>     			/* panel fitter case: assign as a crtc scaler */
>>>>>>     			scaler_id = &scaler_state->scaler_id;
>>>>>> +		} else if (i == SKL_HDMI_OUTPUT_INDEX) {
>>>>>> +			name = "HDMI-OUTPUT";
>>>>>> +			idx = intel_crtc->base.base.id;
>>>>>> +
>>>>>> +			/* hdmi output case: needs a pipe scaler */
>>>>>> +			scaler_id = &scaler_state->scaler_id;
>>>>>>     		} else {
>>>>>>     			name = "PLANE";
>>>>>>     
>>>>>> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
>>>>>> index da29536..983f581 100644
>>>>>> --- a/drivers/gpu/drm/i915/intel_display.c
>>>>>> +++ b/drivers/gpu/drm/i915/intel_display.c
>>>>>> @@ -4626,6 +4626,11 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
>>>>>>     	 */
>>>>>>     	need_scaling = src_w != dst_w || src_h != dst_h;
>>>>>>     
>>>>>> +	if (crtc_state->hdmi_output == DRM_HDMI_OUTPUT_YCBCR420
>>>>>> +		&& scaler_user == SKL_HDMI_OUTPUT_INDEX)
>>>>> Is it really necessary to check for both? If it is, what's the point of creating
>>>>> SKL_HDMI_OUTPUT_INDEX?
>>>> Yes, else this will affect scaler update for planes, as this function
>>>> gets called to update the plane scalers too, at that time the output
>>>> will be still valid (as its at CRTC level), but the
>>>> scaler user would be different.
>>> Right, so there is a need to check for scaler_user == HDMI_OUTPUT. But then
>>> wouldn't it be a bug if hdmi_output != YCBCR420 ?  Point is, if the caller asked
>>> for a HDMI_OUTPUT scaler hopefully it knows what its doing, no need to second
>>> guess it.
>> skl_update_scaler function gets called for all the users, which are:
>> - panel fitter
>> - all the planes
>> - newly added user hdmi_output
>> what about the case (assume) when we have handled hdmi_output and now we
>> are handling for a plane, which doesnt need scaling.
>>
>> in this case, the code will look like:
>> if (crtc_state->hdmi_output == DRM_HDMI_OUTPUT_YCBCR420)
>>         need_scaling = true /* which is wrong, as this function call is
>> for plane scalar, and scaler_user = scaler */
>>
>> if (crtc_state->hdmi_output == DRM_HDMI_OUTPUT_YCBCR420 &&
>>       scaler_user == HDMI_OUT)
>>       need_scaling = true /* this is correct, as I want to consume scalar only when both the conditions are true.
>
> I meant to do just
>
> 	if (scaler_user == SKL_HDMI_OUTPUT_INDEX)
> 		...;
>
> I failed to notice the ambiguity in abbreviating to just HDMI_OUTPUT. But the
> caller shouldn't request it if it doesn't need it, right?
I agree, I dont see a reason why not !
Will do the needful.

Regards
Shashank
>>>>>> +		/* YCBCR 444 -> 420 conversion needs a scaler */
>>>>>> +		need_scaling = true;
>>>>>> +
>>>>>>     	/*
>>>>>>     	 * if plane is being disabled or scaler is no more required or force detach
>>>>>>     	 *  - free scaler binded to this plane/crtc
>>>>>> @@ -4673,6 +4678,26 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
>>>>>>     }
>>>>>>     
>>>>>>     /**
>>>>>> + * skl_update_scaler_hdmi_output - Stages update to scaler state for HDMI.
>>>>>> + * HDMI YCBCR 420 output needs a scaler, for downsampling.
>>>>>> + *
>>>>>> + * @state: crtc's scaler state
>>>>>> + *
>>>>>> + * Return
>>>>>> + *     0 - scaler_usage updated successfully
>>>>>> + *    error - requested scaling cannot be supported or other error condition
>>>>>> + */
>>>>>> +int skl_update_scaler_crtc_hdmi_output(struct intel_crtc_state *state)
>>>>>> +{
>>>>>> +	const struct drm_display_mode *mode = &state->base.adjusted_mode;
>>>>>> +
>>>>>> +	return skl_update_scaler(state, !state->base.active,
>>>>>> +		SKL_HDMI_OUTPUT_INDEX, &state->scaler_state.scaler_id,
>>>>>> +		state->pipe_src_w, state->pipe_src_h,
>>>>>> +		mode->crtc_hdisplay, mode->crtc_vdisplay);
>>>>>> +}
>>>>>> +
>>>>>> +/**
>>>>>>      * skl_update_scaler_crtc - Stages update to scaler state for a given crtc.
>>>>>>      *
>>>>>>      * @state: crtc's scaler state
>>>>>> @@ -8058,6 +8083,7 @@ static void haswell_set_pipemisc(struct drm_crtc *crtc)
>>>>>>     {
>>>>>>     	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
>>>>>>     	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>>>>>> +	enum drm_hdmi_output_type hdmi_out = intel_crtc->config->hdmi_output;
>>>>>>     
>>>>>>     	if (IS_BROADWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 9) {
>>>>>>     		u32 val = 0;
>>>>>> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
>>>>>> index 38fe56c..2206aa8 100644
>>>>>> --- a/drivers/gpu/drm/i915/intel_drv.h
>>>>>> +++ b/drivers/gpu/drm/i915/intel_drv.h
>>>>>> @@ -471,7 +471,8 @@ struct intel_crtc_scaler_state {
>>>>>>     	 *
>>>>>>     	 *     If a bit is set, a user is using a scaler.
>>>>>>     	 *     Here user can be a plane or crtc as defined below:
>>>>>> -	 *       bits 0-30 - plane (bit position is index from drm_plane_index)
>>>>>> +	 *       bits 0-29 - plane (bit position is index from drm_plane_index)
>>>>>> +	 *       bit 30    - hdmi output
>>>>>>     	 *       bit 31    - crtc
>>>>>>     	 *
>>>>>>     	 * Instead of creating a new index to cover planes and crtc, using
>>>>>> @@ -484,6 +485,12 @@ struct intel_crtc_scaler_state {
>>>>>>     	 * avilability.
>>>>>>     	 */
>>>>>>     #define SKL_CRTC_INDEX 31
>>>>>> +
>>>>>> +	/*
>>>>>> +	 * HDMI YCBCR 420 output consume a scaler. So adding a user
>>>>>> +	 * for HDMI output 420 requirement.
>>>>>> +	 */
>>>>>> +#define SKL_HDMI_OUTPUT_INDEX 30
>>>>> I'm not convinced about this. The scaler is still used as a pipe scaler and the
>>>>> patch even adds a call intel_pch_panel_fitting().
>>>> This is a special mode usage of scalar defined in the bspec, when we
>>>> want to run the scalar into 5x3 auto mode for YCBCR444->YCBCR420 scale down.
>>>> It can be used only when the PIPE_MISC is also programmed to act
>>>> accordingly. So this is different from using it as a panel fitter, and
>>>> that's why added
>>>> a new scalar user all together.
>>>>>>     	unsigned scaler_users;
>>>>>>     
>>>>>>     	/* scaler used by crtc for panel fitting purpose */
>>>>>> @@ -1481,6 +1488,7 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode,
>>>>>>     				 struct intel_crtc_state *pipe_config);
>>>>>>     
>>>>>>     int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state);
>>>>>> +int skl_update_scaler_crtc_hdmi_output(struct intel_crtc_state *state);
>>>>>>     int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state);
>>>>>>     
>>>>>>     static inline u32 intel_plane_ggtt_offset(const struct intel_plane_state *state)
>>>>>> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
>>>>>> index 22da5cd..8d5aa1e 100644
>>>>>> --- a/drivers/gpu/drm/i915/intel_hdmi.c
>>>>>> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
>>>>>> @@ -1415,6 +1415,7 @@ intel_hdmi_compute_ycbcr_config(struct drm_connector_state *conn_state,
>>>>>>     	}
>>>>>>     
>>>>>>     	if (type == DRM_HDMI_OUTPUT_YCBCR420) {
>>>>>> +		struct intel_crtc *intel_crtc = to_intel_crtc(conn_state->crtc);
>>>>>>     
>>>>>>     		/* YCBCR420 TMDS rate requirement is half the pixel clock */
>>>>>>     		config->hdmi_output = DRM_HDMI_OUTPUT_YCBCR420;
>>>>>> @@ -1422,6 +1423,15 @@ intel_hdmi_compute_ycbcr_config(struct drm_connector_state *conn_state,
>>>>>>     		*clock_12bpc /= 2;
>>>>>>     		*clock_8bpc /= 2;
>>>>>>     
>>>>>> +		/* YCBCR 420 output conversion needs a scaler */
>>>>>> +		if (skl_update_scaler_crtc_hdmi_output(config)) {
>>>>>> +			DRM_ERROR("Scaler allocation for output failed\n");
>>>>>> +			return DRM_HDMI_OUTPUT_INVALID;
>>>>>> +		}
>>>>>> +
>>>>>> +		/* Bind this scaler to pipe */
>>>>>> +		intel_pch_panel_fitting(intel_crtc, config,
>>>>>> +					DRM_MODE_SCALE_FULLSCREEN);
>>>>>>     	}
>>>>>>     
>>>>>>     	/* Encoder is capable of this output, lets commit to CRTC */
>>>>>> diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
>>>>>> index 96c2cbd..b6a32c4 100644
>>>>>> --- a/drivers/gpu/drm/i915/intel_panel.c
>>>>>> +++ b/drivers/gpu/drm/i915/intel_panel.c
>>>>>> @@ -110,7 +110,8 @@ intel_pch_panel_fitting(struct intel_crtc *intel_crtc,
>>>>>>     
>>>>>>     	/* Native modes don't need fitting */
>>>>>>     	if (adjusted_mode->crtc_hdisplay == pipe_config->pipe_src_w &&
>>>>>> -	    adjusted_mode->crtc_vdisplay == pipe_config->pipe_src_h)
>>>>>> +	    adjusted_mode->crtc_vdisplay == pipe_config->pipe_src_h &&
>>>>>> +	    pipe_config->hdmi_output != DRM_HDMI_OUTPUT_YCBCR420)
>>>>> I don't like that the knowledge that YCBCR420 needs the scaler is spread
>>>>> everywhere, including this function that should only deal with panel fitting. I
>>>>> would rather add a force parameter to intel_pch_panel_fitting() and
>>>>> skl_update_scaler() that would mean setup the scaler even if looks like it's not
>>>>> necessary. That way the hdmi code would just call them with force enabled,
>>>>> without sprinkling "hdmi_output == YCBCR420" everywhere.
>>>> As explained in the comment above, its special case usage of pipe
>>>> scalar, and that's why being checked specifically.
>>> I'm still not convinced about this. If this is a special scaler mode that is not
>>> panel fitting, then this should definitely not touch a function in
>>> intel_panel.c, specially one with "panel fitting" in the name.
>>>
>>> My point is, if this is panel fitting, then it should use panel fitting code
>>> without special casing. If it isn't, then it should have its own code paths. But
>>> this patch just creates a blurry line where the panel fitting code needs to be
>>> special cased for when the HDMI output is YCBCR420 and we are *not* actually
>>> doing panel fitting.
>> My understanding of the code is (please correct me if that's not) that
>> any pipe scalar usages we are keeping it at
>> panel_fitting level, whereas any plane level stuff is called
>> plane_scalar. As this new user was a usage of pipe_scalar
>> with a special configuration and setting, I accommodated the code in
>> panel fitter level. We can also create new code
>> for it, but that would be unnecessary duplication of code which does the
>> same thing, isn't it ?
> The code as it is in this patch asks for something called an HDMI_OUTPUT scaler,
> and then when it is time to enable it, it asks the panel fitter to be enabled.
> Notice the inconsistency?
>
> I like to either call it a panel fitter and treat it as panel fitter, or call it
> a new type of scaler and have a proper interface for it. I don't think the
> current solution reused much of the code anyway. The relevant part from
> intel_pch_panel_fitting() is
>
>          case DRM_MODE_SCALE_FULLSCREEN:
>                  x = y = 0;
>                  width = adjusted_mode->crtc_hdisplay;
>                  height = adjusted_mode->crtc_vdisplay;
>                  break;
>
>          pipe_config->pch_pfit.pos = (x << 16) | y;
> 	pipe_config->pch_pfit.size = (width << 16) | height;
> 	pipe_config->pch_pfit.enabled = pipe_config->pch_pfit.size != 0;
>
> . The other part is recycling the call to skylake_pfit_enable() in
> haswell_crtc_enable(). That call is just scaler register programming, basically:
>
> 	if (... pch_pfit.enabled) {
> 		...
>                  id = scaler_state->scaler_id;
>                  I915_WRITE(SKL_PS_CTRL(pipe, id), PS_SCALER_EN |
>                          PS_FILTER_MEDIUM | scaler_state->scalers[id].mode);
>                  I915_WRITE(SKL_PS_WIN_POS(pipe, id), crtc->config->pch_pfit.pos);
>                  I915_WRITE(SKL_PS_WIN_SZ(pipe, id), crtc->config->pch_pfit.size);
> 	}
>
> I think the issue here is that there isn't a good layer of abstraction between
> "skylake" panel fitting and the scalers. It would probably be much better if the
> register programming logic for them would be in a scaler_enable() function since
> that is duplicated here and there. It would probably be good to have a proper
> struct scaler that we can pass to certain functions too.
>
> Anyway, I think the scaler interface could be improved in general. I'm not
> saying it should be done as part of this patch, but at the same time I'd like to
> avoid creating an even bigger mess to sort out in the future. To sum it up, I'd
> be equaly fine with either of the proposals below:
>
> - find a way to not have a special HDMI OUTPUT scaler and reuse the panel
> fitting code completely, without sprinkling checks for YCBCR420 into it;
> - create a new path for the new type of scaler, completely independent of panel
> fitting.
>
> Anything else makes it unclear which part of the code is responsible for what,
> which I believe is a bad thing.
>
> Ander
>
>> For this usage, we just need to attach a pipe scalar, and then program
>> the PIPEMISC (which we do in crtc->mode_set). Do you
>> think its any good reason for write a new code path altogether ?
>>
>> - Shashank
>>> Ander
>>>
>>

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

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [RESEND-CI v4 01/15] drm: add HDMI 2.0 VIC support for AVI info-frames
  2017-06-30 11:54   ` Ville Syrjälä
@ 2017-07-03  9:06     ` Sharma, Shashank
  2017-07-03  9:57       ` Ville Syrjälä
  0 siblings, 1 reply; 58+ messages in thread
From: Sharma, Shashank @ 2017-07-03  9:06 UTC (permalink / raw)
  To: Ville Syrjälä
  Cc: Jose Abreu, intel-gfx, dri-devel, Alex Deucher, Daniel Vetter

Regards

Shashank


On 6/30/2017 5:24 PM, Ville Syrjälä wrote:
> On Wed, Jun 21, 2017 at 04:03:59PM +0530, Shashank Sharma wrote:
>> HDMI 1.4b support the CEA video modes as per range of CEA-861-D (VIC 1-64).
>> For any other mode, the VIC filed in AVI infoframes should be 0.
>> HDMI 2.0 sinks, support video modes range as per CEA-861-F spec, which is
>> extended to (VIC 1-107).
>>
>> This patch adds a bool input variable, which indicates if the connected
>> sink is a HDMI 2.0 sink or not. This will make sure that we don't pass a
>> HDMI 2.0 VIC to a HDMI 1.4 sink.
>>
>> This patch touches all drm drivers, who are callers of this function
>> drm_hdmi_avi_infoframe_from_display_mode but to make sure there is
>> no change in current behavior, is_hdmi2 is kept as false.
>>
>> In case of I915 driver, this patch:
>> - checks if the connected display is HDMI 2.0.
>> - HDMI infoframes carry one of this two type of information:
>> 	- VIC for 4K modes for HDMI 1.4 sinks
>> 	- S3D information for S3D modes
>>    As CEA-861-F has already defined VICs for 4K videomodes, this
>>    patch doesn't allow sending HDMI infoframes for HDMI 2.0 sinks,
>>    until the mode is 3D.
>>
>> Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
>> Cc: Jose Abreu <jose.abreu@synopsys.com>
>> Cc: Andrzej Hajda <a.hajda@samsung.com>
>> Cc: Alex Deucher <alexander.deucher@amd.com>
>> Cc: Daniel Vetter <daniel.vetter@intel.com>
>>
>> PS: This patch touches a few lines in few files, which were
>> already above 80 char, so checkpatch gives 80 char warning again.
>> - gpu/drm/omapdrm/omap_encoder.c
>> - gpu/drm/i915/intel_sdvo.c
>>
>> V2: Rebase, Added r-b from Andrzej
>> V3: Addressed review comment from Ville:
>> 	- Do not send VICs in both AVI-IF and HDMI-IF
>> 	  send only one of it.
>>
>> Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
>> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
>> ---
>>   drivers/gpu/drm/amd/amdgpu/dce_v10_0.c    |  2 +-
>>   drivers/gpu/drm/amd/amdgpu/dce_v11_0.c    |  2 +-
>>   drivers/gpu/drm/amd/amdgpu/dce_v8_0.c     |  2 +-
>>   drivers/gpu/drm/bridge/analogix-anx78xx.c |  3 ++-
>>   drivers/gpu/drm/bridge/sii902x.c          |  2 +-
>>   drivers/gpu/drm/bridge/synopsys/dw-hdmi.c |  2 +-
>>   drivers/gpu/drm/drm_edid.c                | 12 +++++++++++-
>>   drivers/gpu/drm/exynos/exynos_hdmi.c      |  2 +-
>>   drivers/gpu/drm/i2c/tda998x_drv.c         |  2 +-
>>   drivers/gpu/drm/i915/intel_hdmi.c         | 17 ++++++++++++++++-
>>   drivers/gpu/drm/i915/intel_sdvo.c         |  3 ++-
>>   drivers/gpu/drm/mediatek/mtk_hdmi.c       |  2 +-
>>   drivers/gpu/drm/omapdrm/omap_encoder.c    |  3 ++-
>>   drivers/gpu/drm/radeon/radeon_audio.c     |  2 +-
>>   drivers/gpu/drm/rockchip/inno_hdmi.c      |  2 +-
>>   drivers/gpu/drm/sti/sti_hdmi.c            |  2 +-
>>   drivers/gpu/drm/tegra/hdmi.c              |  2 +-
>>   drivers/gpu/drm/tegra/sor.c               |  2 +-
>>   drivers/gpu/drm/vc4/vc4_hdmi.c            |  2 +-
>>   drivers/gpu/drm/zte/zx_hdmi.c             |  2 +-
>>   include/drm/drm_edid.h                    |  3 ++-
>>   21 files changed, 50 insertions(+), 21 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
>> index 3c62c45..4923ddc 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
>> +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
>> @@ -1864,7 +1864,7 @@ static void dce_v10_0_afmt_setmode(struct drm_encoder *encoder,
>>   	dce_v10_0_audio_write_sad_regs(encoder);
>>   	dce_v10_0_audio_write_latency_fields(encoder, mode);
>>   
>> -	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
>> +	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
>>   	if (err < 0) {
>>   		DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
>>   		return;
>> diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
>> index c8ed0fa..4101684 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
>> +++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
>> @@ -1848,7 +1848,7 @@ static void dce_v11_0_afmt_setmode(struct drm_encoder *encoder,
>>   	dce_v11_0_audio_write_sad_regs(encoder);
>>   	dce_v11_0_audio_write_latency_fields(encoder, mode);
>>   
>> -	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
>> +	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
>>   	if (err < 0) {
>>   		DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
>>   		return;
>> diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
>> index 3e90c19..a7f6b32 100644
>> --- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
>> +++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
>> @@ -1747,7 +1747,7 @@ static void dce_v8_0_afmt_setmode(struct drm_encoder *encoder,
>>   	dce_v8_0_audio_write_sad_regs(encoder);
>>   	dce_v8_0_audio_write_latency_fields(encoder, mode);
>>   
>> -	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
>> +	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
>>   	if (err < 0) {
>>   		DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
>>   		return;
>> diff --git a/drivers/gpu/drm/bridge/analogix-anx78xx.c b/drivers/gpu/drm/bridge/analogix-anx78xx.c
>> index 9006578..a083211 100644
>> --- a/drivers/gpu/drm/bridge/analogix-anx78xx.c
>> +++ b/drivers/gpu/drm/bridge/analogix-anx78xx.c
>> @@ -1097,7 +1097,8 @@ static void anx78xx_bridge_mode_set(struct drm_bridge *bridge,
>>   
>>   	mutex_lock(&anx78xx->lock);
>>   
>> -	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, adjusted_mode);
>> +	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, adjusted_mode,
>> +						       false);
>>   	if (err) {
>>   		DRM_ERROR("Failed to setup AVI infoframe: %d\n", err);
>>   		goto unlock;
>> diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c
>> index 9b87067..3dc40f6 100644
>> --- a/drivers/gpu/drm/bridge/sii902x.c
>> +++ b/drivers/gpu/drm/bridge/sii902x.c
>> @@ -269,7 +269,7 @@ static void sii902x_bridge_mode_set(struct drm_bridge *bridge,
>>   	if (ret)
>>   		return;
>>   
>> -	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame, adj);
>> +	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame, adj, false);
>>   	if (ret < 0) {
>>   		DRM_ERROR("couldn't fill AVI infoframe\n");
>>   		return;
>> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
>> index ead1124..0b0c9de 100644
>> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
>> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
>> @@ -1317,7 +1317,7 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
>>   	u8 val;
>>   
>>   	/* Initialise info frame from DRM mode */
>> -	drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
>> +	drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
>>   
>>   	if (hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format))
>>   		frame.colorspace = HDMI_COLORSPACE_YUV444;
>> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
>> index 2e55599..d312fe1 100644
>> --- a/drivers/gpu/drm/drm_edid.c
>> +++ b/drivers/gpu/drm/drm_edid.c
>> @@ -4334,12 +4334,14 @@ EXPORT_SYMBOL(drm_set_preferred_mode);
>>    *                                              data from a DRM display mode
>>    * @frame: HDMI AVI infoframe
>>    * @mode: DRM display mode
>> + * @is_hdmi2_sink: Sink is HDMI 2.0 compliant
>>    *
>>    * Return: 0 on success or a negative error code on failure.
>>    */
>>   int
>>   drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
>> -					 const struct drm_display_mode *mode)
>> +					 const struct drm_display_mode *mode,
>> +					 bool is_hdmi2_sink)
>>   {
>>   	int err;
>>   
>> @@ -4355,6 +4357,14 @@ drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
>>   
>>   	frame->video_code = drm_match_cea_mode(mode);
>>   
>> +	/*
>> +	 * HDMI 1.4 VIC range: 1 <= VIC <= 64 (CEA-861-D) but
>> +	 * HDMI 2.0 VIC range: 1 <= VIC <= 107 (CEA-861-F). So we
>> +	 * have to make sure we dont break HDMI 1.4 sinks.
>> +	 */
>> +	if (!is_hdmi2_sink && frame->video_code > 64)
>> +		frame->video_code = 0;
>> +
>>   	frame->picture_aspect = HDMI_PICTURE_ASPECT_NONE;
>>   
>>   	/*
>> diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
>> index 06bfbe4..c953927 100644
>> --- a/drivers/gpu/drm/exynos/exynos_hdmi.c
>> +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
>> @@ -784,7 +784,7 @@ static void hdmi_reg_infoframes(struct hdmi_context *hdata)
>>   	}
>>   
>>   	ret = drm_hdmi_avi_infoframe_from_display_mode(&frm.avi,
>> -			&hdata->current_mode);
>> +			&hdata->current_mode, false);
>>   	if (!ret)
>>   		ret = hdmi_avi_infoframe_pack(&frm.avi, buf, sizeof(buf));
>>   	if (ret > 0) {
>> diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
>> index 86f47e1..d1e7ac5 100644
>> --- a/drivers/gpu/drm/i2c/tda998x_drv.c
>> +++ b/drivers/gpu/drm/i2c/tda998x_drv.c
>> @@ -712,7 +712,7 @@ tda998x_write_avi(struct tda998x_priv *priv, struct drm_display_mode *mode)
>>   {
>>   	union hdmi_infoframe frame;
>>   
>> -	drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
>> +	drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
>>   	frame.avi.quantization_range = HDMI_QUANTIZATION_RANGE_FULL;
>>   
>>   	tda998x_write_if(priv, DIP_IF_FLAGS_IF2, REG_IF2_HB0, &frame);
>> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
>> index ec0779a..170abc4 100644
>> --- a/drivers/gpu/drm/i915/intel_hdmi.c
>> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
>> @@ -459,11 +459,14 @@ static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder,
>>   	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
>>   	const struct drm_display_mode *adjusted_mode =
>>   		&crtc_state->base.adjusted_mode;
>> +	struct drm_connector *connector = &intel_hdmi->attached_connector->base;
>> +	bool is_hdmi2_sink = connector->display_info.hdmi.scdc.supported;
>>   	union hdmi_infoframe frame;
>>   	int ret;
>>   
>>   	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
>> -						       adjusted_mode);
>> +						       adjusted_mode,
>> +						       is_hdmi2_sink);
>>   	if (ret < 0) {
>>   		DRM_ERROR("couldn't fill AVI infoframe\n");
>>   		return;
>> @@ -816,6 +819,8 @@ static void hsw_set_infoframes(struct drm_encoder *encoder,
>>   {
>>   	struct drm_i915_private *dev_priv = to_i915(encoder->dev);
>>   	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
>> +	struct drm_hdmi_info *hdmi = &conn_state->connector->display_info.hdmi;
>> +	const struct drm_display_mode *mode = &crtc_state->base.adjusted_mode;
>>   	i915_reg_t reg = HSW_TVIDEO_DIP_CTL(crtc_state->cpu_transcoder);
>>   	u32 val = I915_READ(reg);
>>   
>> @@ -839,6 +844,16 @@ static void hsw_set_infoframes(struct drm_encoder *encoder,
>>   
>>   	intel_hdmi_set_avi_infoframe(encoder, crtc_state);
>>   	intel_hdmi_set_spd_infoframe(encoder, crtc_state);
>> +
>> +	/*
>> +	 * CEA-861-F added new VICs for 4k video modes, due to which
>> +	 * HDMI 2.0 sinks need HDMI IF only for S3D information (Not for
>> +	 * 4k VICs). So for a HDMI 2.0 sink, if the video mode is not 3D,
>> +	 * don't bother sending HDMI IF.
>> +	 */
>> +	if (hdmi->scdc.supported && !(mode->flags & DRM_MODE_FLAG_3D_MASK))
>> +		return;
> That doesn't look like the rigth place for this check.
>
> Also I think we still want to send the vendor specific infoframe always,
> if for no other reason that to get extra testing for the code. We just
> need to select whether we should be sending the old or the new one.
I think in the previous review comments, this is what you asked to do:
send HDMI 2.0 VIC only in one place, either in AVI IF or HDMI IF, not both.

Now,  HDMI IF contains only two piece of information (from the code):
  frame->vic = vic (for HDMI 1.4 4k HDMI modes)
  or
  frame->s3d_strucrt = s3d_structure_from_display_mode()

So if its a HDMI 2.0 monitor && we don't want to send s3d_info, then 
there is nothing in the frame right ?

- Shashank
>> +
>>   	intel_hdmi_set_hdmi_infoframe(encoder, crtc_state);
>>   }
>>   
>> diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
>> index f4329d2..737076e 100644
>> --- a/drivers/gpu/drm/i915/intel_sdvo.c
>> +++ b/drivers/gpu/drm/i915/intel_sdvo.c
>> @@ -996,7 +996,8 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo,
>>   	ssize_t len;
>>   
>>   	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
>> -						       &pipe_config->base.adjusted_mode);
>> +						       &pipe_config->base.adjusted_mode,
>> +						       false);
>>   	if (ret < 0) {
>>   		DRM_ERROR("couldn't fill AVI infoframe\n");
>>   		return false;
>> diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
>> index 0a4ffd7..5c0d024 100644
>> --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
>> +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
>> @@ -975,7 +975,7 @@ static int mtk_hdmi_setup_avi_infoframe(struct mtk_hdmi *hdmi,
>>   	u8 buffer[17];
>>   	ssize_t err;
>>   
>> -	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
>> +	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
>>   	if (err < 0) {
>>   		dev_err(hdmi->dev,
>>   			"Failed to get AVI infoframe from mode: %zd\n", err);
>> diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c b/drivers/gpu/drm/omapdrm/omap_encoder.c
>> index 86c977b..624f5b5 100644
>> --- a/drivers/gpu/drm/omapdrm/omap_encoder.c
>> +++ b/drivers/gpu/drm/omapdrm/omap_encoder.c
>> @@ -85,7 +85,8 @@ static void omap_encoder_mode_set(struct drm_encoder *encoder,
>>   	if (hdmi_mode && dssdev->driver->set_hdmi_infoframe) {
>>   		struct hdmi_avi_infoframe avi;
>>   
>> -		r = drm_hdmi_avi_infoframe_from_display_mode(&avi, adjusted_mode);
>> +		r = drm_hdmi_avi_infoframe_from_display_mode(&avi, adjusted_mode,
>> +							     false);
>>   		if (r == 0)
>>   			dssdev->driver->set_hdmi_infoframe(dssdev, &avi);
>>   	}
>> diff --git a/drivers/gpu/drm/radeon/radeon_audio.c b/drivers/gpu/drm/radeon/radeon_audio.c
>> index aaacac1..770e31f 100644
>> --- a/drivers/gpu/drm/radeon/radeon_audio.c
>> +++ b/drivers/gpu/drm/radeon/radeon_audio.c
>> @@ -516,7 +516,7 @@ static int radeon_audio_set_avi_packet(struct drm_encoder *encoder,
>>   	if (!connector)
>>   		return -EINVAL;
>>   
>> -	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
>> +	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
>>   	if (err < 0) {
>>   		DRM_ERROR("failed to setup AVI infoframe: %d\n", err);
>>   		return err;
>> diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c
>> index 7d9b75e..7149968 100644
>> --- a/drivers/gpu/drm/rockchip/inno_hdmi.c
>> +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c
>> @@ -294,7 +294,7 @@ static int inno_hdmi_config_video_avi(struct inno_hdmi *hdmi,
>>   	union hdmi_infoframe frame;
>>   	int rc;
>>   
>> -	rc = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
>> +	rc = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
>>   
>>   	if (hdmi->hdmi_data.enc_out_format == HDMI_COLORSPACE_YUV444)
>>   		frame.avi.colorspace = HDMI_COLORSPACE_YUV444;
>> diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
>> index a59c95a..dbc6a19 100644
>> --- a/drivers/gpu/drm/sti/sti_hdmi.c
>> +++ b/drivers/gpu/drm/sti/sti_hdmi.c
>> @@ -434,7 +434,7 @@ static int hdmi_avi_infoframe_config(struct sti_hdmi *hdmi)
>>   
>>   	DRM_DEBUG_DRIVER("\n");
>>   
>> -	ret = drm_hdmi_avi_infoframe_from_display_mode(&infoframe, mode);
>> +	ret = drm_hdmi_avi_infoframe_from_display_mode(&infoframe, mode, false);
>>   	if (ret < 0) {
>>   		DRM_ERROR("failed to setup AVI infoframe: %d\n", ret);
>>   		return ret;
>> diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c
>> index cda0491..718d8db 100644
>> --- a/drivers/gpu/drm/tegra/hdmi.c
>> +++ b/drivers/gpu/drm/tegra/hdmi.c
>> @@ -734,7 +734,7 @@ static void tegra_hdmi_setup_avi_infoframe(struct tegra_hdmi *hdmi,
>>   	u8 buffer[17];
>>   	ssize_t err;
>>   
>> -	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
>> +	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
>>   	if (err < 0) {
>>   		dev_err(hdmi->dev, "failed to setup AVI infoframe: %zd\n", err);
>>   		return;
>> diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c
>> index a8f5289..fb2709c 100644
>> --- a/drivers/gpu/drm/tegra/sor.c
>> +++ b/drivers/gpu/drm/tegra/sor.c
>> @@ -1904,7 +1904,7 @@ tegra_sor_hdmi_setup_avi_infoframe(struct tegra_sor *sor,
>>   	value &= ~INFOFRAME_CTRL_ENABLE;
>>   	tegra_sor_writel(sor, value, SOR_HDMI_AVI_INFOFRAME_CTRL);
>>   
>> -	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
>> +	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
>>   	if (err < 0) {
>>   		dev_err(sor->dev, "failed to setup AVI infoframe: %d\n", err);
>>   		return err;
>> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
>> index ed63d4e..406d6d8 100644
>> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
>> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
>> @@ -395,7 +395,7 @@ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
>>   	union hdmi_infoframe frame;
>>   	int ret;
>>   
>> -	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
>> +	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
>>   	if (ret < 0) {
>>   		DRM_ERROR("couldn't fill AVI infoframe\n");
>>   		return;
>> diff --git a/drivers/gpu/drm/zte/zx_hdmi.c b/drivers/gpu/drm/zte/zx_hdmi.c
>> index 0df7366..7e834e3 100644
>> --- a/drivers/gpu/drm/zte/zx_hdmi.c
>> +++ b/drivers/gpu/drm/zte/zx_hdmi.c
>> @@ -124,7 +124,7 @@ static int zx_hdmi_config_video_avi(struct zx_hdmi *hdmi,
>>   	union hdmi_infoframe frame;
>>   	int ret;
>>   
>> -	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
>> +	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
>>   	if (ret) {
>>   		DRM_DEV_ERROR(hdmi->dev, "failed to get avi infoframe: %d\n",
>>   			      ret);
>> diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
>> index 7b9f48b..89c0062 100644
>> --- a/include/drm/drm_edid.h
>> +++ b/include/drm/drm_edid.h
>> @@ -343,7 +343,8 @@ drm_load_edid_firmware(struct drm_connector *connector)
>>   
>>   int
>>   drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
>> -					 const struct drm_display_mode *mode);
>> +					 const struct drm_display_mode *mode,
>> +					 bool is_hdmi2_sink);
>>   int
>>   drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame,
>>   					    const struct drm_display_mode *mode);
>> -- 
>> 2.7.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [RESEND-CI v4 01/15] drm: add HDMI 2.0 VIC support for AVI info-frames
  2017-07-03  9:06     ` Sharma, Shashank
@ 2017-07-03  9:57       ` Ville Syrjälä
  2017-07-03 11:24         ` Sharma, Shashank
  0 siblings, 1 reply; 58+ messages in thread
From: Ville Syrjälä @ 2017-07-03  9:57 UTC (permalink / raw)
  To: Sharma, Shashank
  Cc: Jose Abreu, intel-gfx, dri-devel, Alex Deucher, Daniel Vetter

On Mon, Jul 03, 2017 at 02:36:58PM +0530, Sharma, Shashank wrote:
> Regards
> 
> Shashank
> 
> 
> On 6/30/2017 5:24 PM, Ville Syrjälä wrote:
> > On Wed, Jun 21, 2017 at 04:03:59PM +0530, Shashank Sharma wrote:
> >> HDMI 1.4b support the CEA video modes as per range of CEA-861-D (VIC 1-64).
> >> For any other mode, the VIC filed in AVI infoframes should be 0.
> >> HDMI 2.0 sinks, support video modes range as per CEA-861-F spec, which is
> >> extended to (VIC 1-107).
> >>
> >> This patch adds a bool input variable, which indicates if the connected
> >> sink is a HDMI 2.0 sink or not. This will make sure that we don't pass a
> >> HDMI 2.0 VIC to a HDMI 1.4 sink.
> >>
> >> This patch touches all drm drivers, who are callers of this function
> >> drm_hdmi_avi_infoframe_from_display_mode but to make sure there is
> >> no change in current behavior, is_hdmi2 is kept as false.
> >>
> >> In case of I915 driver, this patch:
> >> - checks if the connected display is HDMI 2.0.
> >> - HDMI infoframes carry one of this two type of information:
> >> 	- VIC for 4K modes for HDMI 1.4 sinks
> >> 	- S3D information for S3D modes
> >>    As CEA-861-F has already defined VICs for 4K videomodes, this
> >>    patch doesn't allow sending HDMI infoframes for HDMI 2.0 sinks,
> >>    until the mode is 3D.
> >>
> >> Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
> >> Cc: Jose Abreu <jose.abreu@synopsys.com>
> >> Cc: Andrzej Hajda <a.hajda@samsung.com>
> >> Cc: Alex Deucher <alexander.deucher@amd.com>
> >> Cc: Daniel Vetter <daniel.vetter@intel.com>
> >>
> >> PS: This patch touches a few lines in few files, which were
> >> already above 80 char, so checkpatch gives 80 char warning again.
> >> - gpu/drm/omapdrm/omap_encoder.c
> >> - gpu/drm/i915/intel_sdvo.c
> >>
> >> V2: Rebase, Added r-b from Andrzej
> >> V3: Addressed review comment from Ville:
> >> 	- Do not send VICs in both AVI-IF and HDMI-IF
> >> 	  send only one of it.
> >>
> >> Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
> >> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
> >> ---
> >>   drivers/gpu/drm/amd/amdgpu/dce_v10_0.c    |  2 +-
> >>   drivers/gpu/drm/amd/amdgpu/dce_v11_0.c    |  2 +-
> >>   drivers/gpu/drm/amd/amdgpu/dce_v8_0.c     |  2 +-
> >>   drivers/gpu/drm/bridge/analogix-anx78xx.c |  3 ++-
> >>   drivers/gpu/drm/bridge/sii902x.c          |  2 +-
> >>   drivers/gpu/drm/bridge/synopsys/dw-hdmi.c |  2 +-
> >>   drivers/gpu/drm/drm_edid.c                | 12 +++++++++++-
> >>   drivers/gpu/drm/exynos/exynos_hdmi.c      |  2 +-
> >>   drivers/gpu/drm/i2c/tda998x_drv.c         |  2 +-
> >>   drivers/gpu/drm/i915/intel_hdmi.c         | 17 ++++++++++++++++-
> >>   drivers/gpu/drm/i915/intel_sdvo.c         |  3 ++-
> >>   drivers/gpu/drm/mediatek/mtk_hdmi.c       |  2 +-
> >>   drivers/gpu/drm/omapdrm/omap_encoder.c    |  3 ++-
> >>   drivers/gpu/drm/radeon/radeon_audio.c     |  2 +-
> >>   drivers/gpu/drm/rockchip/inno_hdmi.c      |  2 +-
> >>   drivers/gpu/drm/sti/sti_hdmi.c            |  2 +-
> >>   drivers/gpu/drm/tegra/hdmi.c              |  2 +-
> >>   drivers/gpu/drm/tegra/sor.c               |  2 +-
> >>   drivers/gpu/drm/vc4/vc4_hdmi.c            |  2 +-
> >>   drivers/gpu/drm/zte/zx_hdmi.c             |  2 +-
> >>   include/drm/drm_edid.h                    |  3 ++-
> >>   21 files changed, 50 insertions(+), 21 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
> >> index 3c62c45..4923ddc 100644
> >> --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
> >> +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
> >> @@ -1864,7 +1864,7 @@ static void dce_v10_0_afmt_setmode(struct drm_encoder *encoder,
> >>   	dce_v10_0_audio_write_sad_regs(encoder);
> >>   	dce_v10_0_audio_write_latency_fields(encoder, mode);
> >>   
> >> -	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
> >> +	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
> >>   	if (err < 0) {
> >>   		DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
> >>   		return;
> >> diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
> >> index c8ed0fa..4101684 100644
> >> --- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
> >> +++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
> >> @@ -1848,7 +1848,7 @@ static void dce_v11_0_afmt_setmode(struct drm_encoder *encoder,
> >>   	dce_v11_0_audio_write_sad_regs(encoder);
> >>   	dce_v11_0_audio_write_latency_fields(encoder, mode);
> >>   
> >> -	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
> >> +	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
> >>   	if (err < 0) {
> >>   		DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
> >>   		return;
> >> diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
> >> index 3e90c19..a7f6b32 100644
> >> --- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
> >> +++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
> >> @@ -1747,7 +1747,7 @@ static void dce_v8_0_afmt_setmode(struct drm_encoder *encoder,
> >>   	dce_v8_0_audio_write_sad_regs(encoder);
> >>   	dce_v8_0_audio_write_latency_fields(encoder, mode);
> >>   
> >> -	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
> >> +	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
> >>   	if (err < 0) {
> >>   		DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
> >>   		return;
> >> diff --git a/drivers/gpu/drm/bridge/analogix-anx78xx.c b/drivers/gpu/drm/bridge/analogix-anx78xx.c
> >> index 9006578..a083211 100644
> >> --- a/drivers/gpu/drm/bridge/analogix-anx78xx.c
> >> +++ b/drivers/gpu/drm/bridge/analogix-anx78xx.c
> >> @@ -1097,7 +1097,8 @@ static void anx78xx_bridge_mode_set(struct drm_bridge *bridge,
> >>   
> >>   	mutex_lock(&anx78xx->lock);
> >>   
> >> -	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, adjusted_mode);
> >> +	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, adjusted_mode,
> >> +						       false);
> >>   	if (err) {
> >>   		DRM_ERROR("Failed to setup AVI infoframe: %d\n", err);
> >>   		goto unlock;
> >> diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c
> >> index 9b87067..3dc40f6 100644
> >> --- a/drivers/gpu/drm/bridge/sii902x.c
> >> +++ b/drivers/gpu/drm/bridge/sii902x.c
> >> @@ -269,7 +269,7 @@ static void sii902x_bridge_mode_set(struct drm_bridge *bridge,
> >>   	if (ret)
> >>   		return;
> >>   
> >> -	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame, adj);
> >> +	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame, adj, false);
> >>   	if (ret < 0) {
> >>   		DRM_ERROR("couldn't fill AVI infoframe\n");
> >>   		return;
> >> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> >> index ead1124..0b0c9de 100644
> >> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> >> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> >> @@ -1317,7 +1317,7 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
> >>   	u8 val;
> >>   
> >>   	/* Initialise info frame from DRM mode */
> >> -	drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
> >> +	drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
> >>   
> >>   	if (hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format))
> >>   		frame.colorspace = HDMI_COLORSPACE_YUV444;
> >> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> >> index 2e55599..d312fe1 100644
> >> --- a/drivers/gpu/drm/drm_edid.c
> >> +++ b/drivers/gpu/drm/drm_edid.c
> >> @@ -4334,12 +4334,14 @@ EXPORT_SYMBOL(drm_set_preferred_mode);
> >>    *                                              data from a DRM display mode
> >>    * @frame: HDMI AVI infoframe
> >>    * @mode: DRM display mode
> >> + * @is_hdmi2_sink: Sink is HDMI 2.0 compliant
> >>    *
> >>    * Return: 0 on success or a negative error code on failure.
> >>    */
> >>   int
> >>   drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
> >> -					 const struct drm_display_mode *mode)
> >> +					 const struct drm_display_mode *mode,
> >> +					 bool is_hdmi2_sink)
> >>   {
> >>   	int err;
> >>   
> >> @@ -4355,6 +4357,14 @@ drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
> >>   
> >>   	frame->video_code = drm_match_cea_mode(mode);
> >>   
> >> +	/*
> >> +	 * HDMI 1.4 VIC range: 1 <= VIC <= 64 (CEA-861-D) but
> >> +	 * HDMI 2.0 VIC range: 1 <= VIC <= 107 (CEA-861-F). So we
> >> +	 * have to make sure we dont break HDMI 1.4 sinks.
> >> +	 */
> >> +	if (!is_hdmi2_sink && frame->video_code > 64)
> >> +		frame->video_code = 0;
> >> +
> >>   	frame->picture_aspect = HDMI_PICTURE_ASPECT_NONE;
> >>   
> >>   	/*
> >> diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
> >> index 06bfbe4..c953927 100644
> >> --- a/drivers/gpu/drm/exynos/exynos_hdmi.c
> >> +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
> >> @@ -784,7 +784,7 @@ static void hdmi_reg_infoframes(struct hdmi_context *hdata)
> >>   	}
> >>   
> >>   	ret = drm_hdmi_avi_infoframe_from_display_mode(&frm.avi,
> >> -			&hdata->current_mode);
> >> +			&hdata->current_mode, false);
> >>   	if (!ret)
> >>   		ret = hdmi_avi_infoframe_pack(&frm.avi, buf, sizeof(buf));
> >>   	if (ret > 0) {
> >> diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
> >> index 86f47e1..d1e7ac5 100644
> >> --- a/drivers/gpu/drm/i2c/tda998x_drv.c
> >> +++ b/drivers/gpu/drm/i2c/tda998x_drv.c
> >> @@ -712,7 +712,7 @@ tda998x_write_avi(struct tda998x_priv *priv, struct drm_display_mode *mode)
> >>   {
> >>   	union hdmi_infoframe frame;
> >>   
> >> -	drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
> >> +	drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
> >>   	frame.avi.quantization_range = HDMI_QUANTIZATION_RANGE_FULL;
> >>   
> >>   	tda998x_write_if(priv, DIP_IF_FLAGS_IF2, REG_IF2_HB0, &frame);
> >> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> >> index ec0779a..170abc4 100644
> >> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> >> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> >> @@ -459,11 +459,14 @@ static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder,
> >>   	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
> >>   	const struct drm_display_mode *adjusted_mode =
> >>   		&crtc_state->base.adjusted_mode;
> >> +	struct drm_connector *connector = &intel_hdmi->attached_connector->base;
> >> +	bool is_hdmi2_sink = connector->display_info.hdmi.scdc.supported;
> >>   	union hdmi_infoframe frame;
> >>   	int ret;
> >>   
> >>   	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
> >> -						       adjusted_mode);
> >> +						       adjusted_mode,
> >> +						       is_hdmi2_sink);
> >>   	if (ret < 0) {
> >>   		DRM_ERROR("couldn't fill AVI infoframe\n");
> >>   		return;
> >> @@ -816,6 +819,8 @@ static void hsw_set_infoframes(struct drm_encoder *encoder,
> >>   {
> >>   	struct drm_i915_private *dev_priv = to_i915(encoder->dev);
> >>   	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
> >> +	struct drm_hdmi_info *hdmi = &conn_state->connector->display_info.hdmi;
> >> +	const struct drm_display_mode *mode = &crtc_state->base.adjusted_mode;
> >>   	i915_reg_t reg = HSW_TVIDEO_DIP_CTL(crtc_state->cpu_transcoder);
> >>   	u32 val = I915_READ(reg);
> >>   
> >> @@ -839,6 +844,16 @@ static void hsw_set_infoframes(struct drm_encoder *encoder,
> >>   
> >>   	intel_hdmi_set_avi_infoframe(encoder, crtc_state);
> >>   	intel_hdmi_set_spd_infoframe(encoder, crtc_state);
> >> +
> >> +	/*
> >> +	 * CEA-861-F added new VICs for 4k video modes, due to which
> >> +	 * HDMI 2.0 sinks need HDMI IF only for S3D information (Not for
> >> +	 * 4k VICs). So for a HDMI 2.0 sink, if the video mode is not 3D,
> >> +	 * don't bother sending HDMI IF.
> >> +	 */
> >> +	if (hdmi->scdc.supported && !(mode->flags & DRM_MODE_FLAG_3D_MASK))
> >> +		return;
> > That doesn't look like the rigth place for this check.
> >
> > Also I think we still want to send the vendor specific infoframe always,
> > if for no other reason that to get extra testing for the code. We just
> > need to select whether we should be sending the old or the new one.
> I think in the previous review comments, this is what you asked to do:
> send HDMI 2.0 VIC only in one place, either in AVI IF or HDMI IF, not both.

Yes, the VIC. I didn't say anything about not sending any infoframe.

> 
> Now,  HDMI IF contains only two piece of information (from the code):
>   frame->vic = vic (for HDMI 1.4 4k HDMI modes)
>   or
>   frame->s3d_strucrt = s3d_structure_from_display_mode()
> 
> So if its a HDMI 2.0 monitor && we don't want to send s3d_info, then 
> there is nothing in the frame right ?

Not sending any infoframe means a change in current behaviour which we
may not want. It also means we don't treat HDMI 2.0 and 1.x sinks
equally since for 1.x sinks we always send the infoframe.

And appendix F of the spec seems to be telling us that there are
sinks out there that don't properly switch from 3D to 2D when the source
stops sending the old infoframe. Hence it seems like a good idea to
always send it. They speak about HDMI 1.4 sinks specifically, but I
wouldn't be surprised if similar problems crop up in 2.0 sinks as well.

In fact I think it would have been nice if they had just totally
replaced the old infoframe with the new one, and allowed us to always
just send the new infoframe. But the spec specifically says that we
have to use the old infoframe if possible :(

> 
> - Shashank
> >> +
> >>   	intel_hdmi_set_hdmi_infoframe(encoder, crtc_state);
> >>   }
> >>   
> >> diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
> >> index f4329d2..737076e 100644
> >> --- a/drivers/gpu/drm/i915/intel_sdvo.c
> >> +++ b/drivers/gpu/drm/i915/intel_sdvo.c
> >> @@ -996,7 +996,8 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo,
> >>   	ssize_t len;
> >>   
> >>   	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
> >> -						       &pipe_config->base.adjusted_mode);
> >> +						       &pipe_config->base.adjusted_mode,
> >> +						       false);
> >>   	if (ret < 0) {
> >>   		DRM_ERROR("couldn't fill AVI infoframe\n");
> >>   		return false;
> >> diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> >> index 0a4ffd7..5c0d024 100644
> >> --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
> >> +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
> >> @@ -975,7 +975,7 @@ static int mtk_hdmi_setup_avi_infoframe(struct mtk_hdmi *hdmi,
> >>   	u8 buffer[17];
> >>   	ssize_t err;
> >>   
> >> -	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
> >> +	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
> >>   	if (err < 0) {
> >>   		dev_err(hdmi->dev,
> >>   			"Failed to get AVI infoframe from mode: %zd\n", err);
> >> diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c b/drivers/gpu/drm/omapdrm/omap_encoder.c
> >> index 86c977b..624f5b5 100644
> >> --- a/drivers/gpu/drm/omapdrm/omap_encoder.c
> >> +++ b/drivers/gpu/drm/omapdrm/omap_encoder.c
> >> @@ -85,7 +85,8 @@ static void omap_encoder_mode_set(struct drm_encoder *encoder,
> >>   	if (hdmi_mode && dssdev->driver->set_hdmi_infoframe) {
> >>   		struct hdmi_avi_infoframe avi;
> >>   
> >> -		r = drm_hdmi_avi_infoframe_from_display_mode(&avi, adjusted_mode);
> >> +		r = drm_hdmi_avi_infoframe_from_display_mode(&avi, adjusted_mode,
> >> +							     false);
> >>   		if (r == 0)
> >>   			dssdev->driver->set_hdmi_infoframe(dssdev, &avi);
> >>   	}
> >> diff --git a/drivers/gpu/drm/radeon/radeon_audio.c b/drivers/gpu/drm/radeon/radeon_audio.c
> >> index aaacac1..770e31f 100644
> >> --- a/drivers/gpu/drm/radeon/radeon_audio.c
> >> +++ b/drivers/gpu/drm/radeon/radeon_audio.c
> >> @@ -516,7 +516,7 @@ static int radeon_audio_set_avi_packet(struct drm_encoder *encoder,
> >>   	if (!connector)
> >>   		return -EINVAL;
> >>   
> >> -	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
> >> +	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
> >>   	if (err < 0) {
> >>   		DRM_ERROR("failed to setup AVI infoframe: %d\n", err);
> >>   		return err;
> >> diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c
> >> index 7d9b75e..7149968 100644
> >> --- a/drivers/gpu/drm/rockchip/inno_hdmi.c
> >> +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c
> >> @@ -294,7 +294,7 @@ static int inno_hdmi_config_video_avi(struct inno_hdmi *hdmi,
> >>   	union hdmi_infoframe frame;
> >>   	int rc;
> >>   
> >> -	rc = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
> >> +	rc = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
> >>   
> >>   	if (hdmi->hdmi_data.enc_out_format == HDMI_COLORSPACE_YUV444)
> >>   		frame.avi.colorspace = HDMI_COLORSPACE_YUV444;
> >> diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
> >> index a59c95a..dbc6a19 100644
> >> --- a/drivers/gpu/drm/sti/sti_hdmi.c
> >> +++ b/drivers/gpu/drm/sti/sti_hdmi.c
> >> @@ -434,7 +434,7 @@ static int hdmi_avi_infoframe_config(struct sti_hdmi *hdmi)
> >>   
> >>   	DRM_DEBUG_DRIVER("\n");
> >>   
> >> -	ret = drm_hdmi_avi_infoframe_from_display_mode(&infoframe, mode);
> >> +	ret = drm_hdmi_avi_infoframe_from_display_mode(&infoframe, mode, false);
> >>   	if (ret < 0) {
> >>   		DRM_ERROR("failed to setup AVI infoframe: %d\n", ret);
> >>   		return ret;
> >> diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c
> >> index cda0491..718d8db 100644
> >> --- a/drivers/gpu/drm/tegra/hdmi.c
> >> +++ b/drivers/gpu/drm/tegra/hdmi.c
> >> @@ -734,7 +734,7 @@ static void tegra_hdmi_setup_avi_infoframe(struct tegra_hdmi *hdmi,
> >>   	u8 buffer[17];
> >>   	ssize_t err;
> >>   
> >> -	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
> >> +	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
> >>   	if (err < 0) {
> >>   		dev_err(hdmi->dev, "failed to setup AVI infoframe: %zd\n", err);
> >>   		return;
> >> diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c
> >> index a8f5289..fb2709c 100644
> >> --- a/drivers/gpu/drm/tegra/sor.c
> >> +++ b/drivers/gpu/drm/tegra/sor.c
> >> @@ -1904,7 +1904,7 @@ tegra_sor_hdmi_setup_avi_infoframe(struct tegra_sor *sor,
> >>   	value &= ~INFOFRAME_CTRL_ENABLE;
> >>   	tegra_sor_writel(sor, value, SOR_HDMI_AVI_INFOFRAME_CTRL);
> >>   
> >> -	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
> >> +	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
> >>   	if (err < 0) {
> >>   		dev_err(sor->dev, "failed to setup AVI infoframe: %d\n", err);
> >>   		return err;
> >> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
> >> index ed63d4e..406d6d8 100644
> >> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
> >> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
> >> @@ -395,7 +395,7 @@ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
> >>   	union hdmi_infoframe frame;
> >>   	int ret;
> >>   
> >> -	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
> >> +	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
> >>   	if (ret < 0) {
> >>   		DRM_ERROR("couldn't fill AVI infoframe\n");
> >>   		return;
> >> diff --git a/drivers/gpu/drm/zte/zx_hdmi.c b/drivers/gpu/drm/zte/zx_hdmi.c
> >> index 0df7366..7e834e3 100644
> >> --- a/drivers/gpu/drm/zte/zx_hdmi.c
> >> +++ b/drivers/gpu/drm/zte/zx_hdmi.c
> >> @@ -124,7 +124,7 @@ static int zx_hdmi_config_video_avi(struct zx_hdmi *hdmi,
> >>   	union hdmi_infoframe frame;
> >>   	int ret;
> >>   
> >> -	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
> >> +	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
> >>   	if (ret) {
> >>   		DRM_DEV_ERROR(hdmi->dev, "failed to get avi infoframe: %d\n",
> >>   			      ret);
> >> diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
> >> index 7b9f48b..89c0062 100644
> >> --- a/include/drm/drm_edid.h
> >> +++ b/include/drm/drm_edid.h
> >> @@ -343,7 +343,8 @@ drm_load_edid_firmware(struct drm_connector *connector)
> >>   
> >>   int
> >>   drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
> >> -					 const struct drm_display_mode *mode);
> >> +					 const struct drm_display_mode *mode,
> >> +					 bool is_hdmi2_sink);
> >>   int
> >>   drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame,
> >>   					    const struct drm_display_mode *mode);
> >> -- 
> >> 2.7.4

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: [RESEND-CI v4 01/15] drm: add HDMI 2.0 VIC support for AVI info-frames
  2017-07-03  9:57       ` Ville Syrjälä
@ 2017-07-03 11:24         ` Sharma, Shashank
  0 siblings, 0 replies; 58+ messages in thread
From: Sharma, Shashank @ 2017-07-03 11:24 UTC (permalink / raw)
  To: Ville Syrjälä
  Cc: Jose Abreu, intel-gfx, dri-devel, Alex Deucher, Daniel Vetter

Regards

Shashank


On 7/3/2017 3:27 PM, Ville Syrjälä wrote:
> On Mon, Jul 03, 2017 at 02:36:58PM +0530, Sharma, Shashank wrote:
>> Regards
>>
>> Shashank
>>
>>
>> On 6/30/2017 5:24 PM, Ville Syrjälä wrote:
>>> On Wed, Jun 21, 2017 at 04:03:59PM +0530, Shashank Sharma wrote:
>>>> HDMI 1.4b support the CEA video modes as per range of CEA-861-D (VIC 1-64).
>>>> For any other mode, the VIC filed in AVI infoframes should be 0.
>>>> HDMI 2.0 sinks, support video modes range as per CEA-861-F spec, which is
>>>> extended to (VIC 1-107).
>>>>
>>>> This patch adds a bool input variable, which indicates if the connected
>>>> sink is a HDMI 2.0 sink or not. This will make sure that we don't pass a
>>>> HDMI 2.0 VIC to a HDMI 1.4 sink.
>>>>
>>>> This patch touches all drm drivers, who are callers of this function
>>>> drm_hdmi_avi_infoframe_from_display_mode but to make sure there is
>>>> no change in current behavior, is_hdmi2 is kept as false.
>>>>
>>>> In case of I915 driver, this patch:
>>>> - checks if the connected display is HDMI 2.0.
>>>> - HDMI infoframes carry one of this two type of information:
>>>> 	- VIC for 4K modes for HDMI 1.4 sinks
>>>> 	- S3D information for S3D modes
>>>>     As CEA-861-F has already defined VICs for 4K videomodes, this
>>>>     patch doesn't allow sending HDMI infoframes for HDMI 2.0 sinks,
>>>>     until the mode is 3D.
>>>>
>>>> Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
>>>> Cc: Jose Abreu <jose.abreu@synopsys.com>
>>>> Cc: Andrzej Hajda <a.hajda@samsung.com>
>>>> Cc: Alex Deucher <alexander.deucher@amd.com>
>>>> Cc: Daniel Vetter <daniel.vetter@intel.com>
>>>>
>>>> PS: This patch touches a few lines in few files, which were
>>>> already above 80 char, so checkpatch gives 80 char warning again.
>>>> - gpu/drm/omapdrm/omap_encoder.c
>>>> - gpu/drm/i915/intel_sdvo.c
>>>>
>>>> V2: Rebase, Added r-b from Andrzej
>>>> V3: Addressed review comment from Ville:
>>>> 	- Do not send VICs in both AVI-IF and HDMI-IF
>>>> 	  send only one of it.
>>>>
>>>> Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
>>>> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
>>>> ---
>>>>    drivers/gpu/drm/amd/amdgpu/dce_v10_0.c    |  2 +-
>>>>    drivers/gpu/drm/amd/amdgpu/dce_v11_0.c    |  2 +-
>>>>    drivers/gpu/drm/amd/amdgpu/dce_v8_0.c     |  2 +-
>>>>    drivers/gpu/drm/bridge/analogix-anx78xx.c |  3 ++-
>>>>    drivers/gpu/drm/bridge/sii902x.c          |  2 +-
>>>>    drivers/gpu/drm/bridge/synopsys/dw-hdmi.c |  2 +-
>>>>    drivers/gpu/drm/drm_edid.c                | 12 +++++++++++-
>>>>    drivers/gpu/drm/exynos/exynos_hdmi.c      |  2 +-
>>>>    drivers/gpu/drm/i2c/tda998x_drv.c         |  2 +-
>>>>    drivers/gpu/drm/i915/intel_hdmi.c         | 17 ++++++++++++++++-
>>>>    drivers/gpu/drm/i915/intel_sdvo.c         |  3 ++-
>>>>    drivers/gpu/drm/mediatek/mtk_hdmi.c       |  2 +-
>>>>    drivers/gpu/drm/omapdrm/omap_encoder.c    |  3 ++-
>>>>    drivers/gpu/drm/radeon/radeon_audio.c     |  2 +-
>>>>    drivers/gpu/drm/rockchip/inno_hdmi.c      |  2 +-
>>>>    drivers/gpu/drm/sti/sti_hdmi.c            |  2 +-
>>>>    drivers/gpu/drm/tegra/hdmi.c              |  2 +-
>>>>    drivers/gpu/drm/tegra/sor.c               |  2 +-
>>>>    drivers/gpu/drm/vc4/vc4_hdmi.c            |  2 +-
>>>>    drivers/gpu/drm/zte/zx_hdmi.c             |  2 +-
>>>>    include/drm/drm_edid.h                    |  3 ++-
>>>>    21 files changed, 50 insertions(+), 21 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
>>>> index 3c62c45..4923ddc 100644
>>>> --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
>>>> +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
>>>> @@ -1864,7 +1864,7 @@ static void dce_v10_0_afmt_setmode(struct drm_encoder *encoder,
>>>>    	dce_v10_0_audio_write_sad_regs(encoder);
>>>>    	dce_v10_0_audio_write_latency_fields(encoder, mode);
>>>>    
>>>> -	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
>>>> +	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
>>>>    	if (err < 0) {
>>>>    		DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
>>>>    		return;
>>>> diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
>>>> index c8ed0fa..4101684 100644
>>>> --- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
>>>> +++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
>>>> @@ -1848,7 +1848,7 @@ static void dce_v11_0_afmt_setmode(struct drm_encoder *encoder,
>>>>    	dce_v11_0_audio_write_sad_regs(encoder);
>>>>    	dce_v11_0_audio_write_latency_fields(encoder, mode);
>>>>    
>>>> -	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
>>>> +	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
>>>>    	if (err < 0) {
>>>>    		DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
>>>>    		return;
>>>> diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
>>>> index 3e90c19..a7f6b32 100644
>>>> --- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
>>>> +++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
>>>> @@ -1747,7 +1747,7 @@ static void dce_v8_0_afmt_setmode(struct drm_encoder *encoder,
>>>>    	dce_v8_0_audio_write_sad_regs(encoder);
>>>>    	dce_v8_0_audio_write_latency_fields(encoder, mode);
>>>>    
>>>> -	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
>>>> +	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
>>>>    	if (err < 0) {
>>>>    		DRM_ERROR("failed to setup AVI infoframe: %zd\n", err);
>>>>    		return;
>>>> diff --git a/drivers/gpu/drm/bridge/analogix-anx78xx.c b/drivers/gpu/drm/bridge/analogix-anx78xx.c
>>>> index 9006578..a083211 100644
>>>> --- a/drivers/gpu/drm/bridge/analogix-anx78xx.c
>>>> +++ b/drivers/gpu/drm/bridge/analogix-anx78xx.c
>>>> @@ -1097,7 +1097,8 @@ static void anx78xx_bridge_mode_set(struct drm_bridge *bridge,
>>>>    
>>>>    	mutex_lock(&anx78xx->lock);
>>>>    
>>>> -	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, adjusted_mode);
>>>> +	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, adjusted_mode,
>>>> +						       false);
>>>>    	if (err) {
>>>>    		DRM_ERROR("Failed to setup AVI infoframe: %d\n", err);
>>>>    		goto unlock;
>>>> diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c
>>>> index 9b87067..3dc40f6 100644
>>>> --- a/drivers/gpu/drm/bridge/sii902x.c
>>>> +++ b/drivers/gpu/drm/bridge/sii902x.c
>>>> @@ -269,7 +269,7 @@ static void sii902x_bridge_mode_set(struct drm_bridge *bridge,
>>>>    	if (ret)
>>>>    		return;
>>>>    
>>>> -	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame, adj);
>>>> +	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame, adj, false);
>>>>    	if (ret < 0) {
>>>>    		DRM_ERROR("couldn't fill AVI infoframe\n");
>>>>    		return;
>>>> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
>>>> index ead1124..0b0c9de 100644
>>>> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
>>>> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
>>>> @@ -1317,7 +1317,7 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
>>>>    	u8 val;
>>>>    
>>>>    	/* Initialise info frame from DRM mode */
>>>> -	drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
>>>> +	drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
>>>>    
>>>>    	if (hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format))
>>>>    		frame.colorspace = HDMI_COLORSPACE_YUV444;
>>>> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
>>>> index 2e55599..d312fe1 100644
>>>> --- a/drivers/gpu/drm/drm_edid.c
>>>> +++ b/drivers/gpu/drm/drm_edid.c
>>>> @@ -4334,12 +4334,14 @@ EXPORT_SYMBOL(drm_set_preferred_mode);
>>>>     *                                              data from a DRM display mode
>>>>     * @frame: HDMI AVI infoframe
>>>>     * @mode: DRM display mode
>>>> + * @is_hdmi2_sink: Sink is HDMI 2.0 compliant
>>>>     *
>>>>     * Return: 0 on success or a negative error code on failure.
>>>>     */
>>>>    int
>>>>    drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
>>>> -					 const struct drm_display_mode *mode)
>>>> +					 const struct drm_display_mode *mode,
>>>> +					 bool is_hdmi2_sink)
>>>>    {
>>>>    	int err;
>>>>    
>>>> @@ -4355,6 +4357,14 @@ drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
>>>>    
>>>>    	frame->video_code = drm_match_cea_mode(mode);
>>>>    
>>>> +	/*
>>>> +	 * HDMI 1.4 VIC range: 1 <= VIC <= 64 (CEA-861-D) but
>>>> +	 * HDMI 2.0 VIC range: 1 <= VIC <= 107 (CEA-861-F). So we
>>>> +	 * have to make sure we dont break HDMI 1.4 sinks.
>>>> +	 */
>>>> +	if (!is_hdmi2_sink && frame->video_code > 64)
>>>> +		frame->video_code = 0;
>>>> +
>>>>    	frame->picture_aspect = HDMI_PICTURE_ASPECT_NONE;
>>>>    
>>>>    	/*
>>>> diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
>>>> index 06bfbe4..c953927 100644
>>>> --- a/drivers/gpu/drm/exynos/exynos_hdmi.c
>>>> +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
>>>> @@ -784,7 +784,7 @@ static void hdmi_reg_infoframes(struct hdmi_context *hdata)
>>>>    	}
>>>>    
>>>>    	ret = drm_hdmi_avi_infoframe_from_display_mode(&frm.avi,
>>>> -			&hdata->current_mode);
>>>> +			&hdata->current_mode, false);
>>>>    	if (!ret)
>>>>    		ret = hdmi_avi_infoframe_pack(&frm.avi, buf, sizeof(buf));
>>>>    	if (ret > 0) {
>>>> diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
>>>> index 86f47e1..d1e7ac5 100644
>>>> --- a/drivers/gpu/drm/i2c/tda998x_drv.c
>>>> +++ b/drivers/gpu/drm/i2c/tda998x_drv.c
>>>> @@ -712,7 +712,7 @@ tda998x_write_avi(struct tda998x_priv *priv, struct drm_display_mode *mode)
>>>>    {
>>>>    	union hdmi_infoframe frame;
>>>>    
>>>> -	drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
>>>> +	drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
>>>>    	frame.avi.quantization_range = HDMI_QUANTIZATION_RANGE_FULL;
>>>>    
>>>>    	tda998x_write_if(priv, DIP_IF_FLAGS_IF2, REG_IF2_HB0, &frame);
>>>> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
>>>> index ec0779a..170abc4 100644
>>>> --- a/drivers/gpu/drm/i915/intel_hdmi.c
>>>> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
>>>> @@ -459,11 +459,14 @@ static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder,
>>>>    	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
>>>>    	const struct drm_display_mode *adjusted_mode =
>>>>    		&crtc_state->base.adjusted_mode;
>>>> +	struct drm_connector *connector = &intel_hdmi->attached_connector->base;
>>>> +	bool is_hdmi2_sink = connector->display_info.hdmi.scdc.supported;
>>>>    	union hdmi_infoframe frame;
>>>>    	int ret;
>>>>    
>>>>    	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
>>>> -						       adjusted_mode);
>>>> +						       adjusted_mode,
>>>> +						       is_hdmi2_sink);
>>>>    	if (ret < 0) {
>>>>    		DRM_ERROR("couldn't fill AVI infoframe\n");
>>>>    		return;
>>>> @@ -816,6 +819,8 @@ static void hsw_set_infoframes(struct drm_encoder *encoder,
>>>>    {
>>>>    	struct drm_i915_private *dev_priv = to_i915(encoder->dev);
>>>>    	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
>>>> +	struct drm_hdmi_info *hdmi = &conn_state->connector->display_info.hdmi;
>>>> +	const struct drm_display_mode *mode = &crtc_state->base.adjusted_mode;
>>>>    	i915_reg_t reg = HSW_TVIDEO_DIP_CTL(crtc_state->cpu_transcoder);
>>>>    	u32 val = I915_READ(reg);
>>>>    
>>>> @@ -839,6 +844,16 @@ static void hsw_set_infoframes(struct drm_encoder *encoder,
>>>>    
>>>>    	intel_hdmi_set_avi_infoframe(encoder, crtc_state);
>>>>    	intel_hdmi_set_spd_infoframe(encoder, crtc_state);
>>>> +
>>>> +	/*
>>>> +	 * CEA-861-F added new VICs for 4k video modes, due to which
>>>> +	 * HDMI 2.0 sinks need HDMI IF only for S3D information (Not for
>>>> +	 * 4k VICs). So for a HDMI 2.0 sink, if the video mode is not 3D,
>>>> +	 * don't bother sending HDMI IF.
>>>> +	 */
>>>> +	if (hdmi->scdc.supported && !(mode->flags & DRM_MODE_FLAG_3D_MASK))
>>>> +		return;
>>> That doesn't look like the rigth place for this check.
>>>
>>> Also I think we still want to send the vendor specific infoframe always,
>>> if for no other reason that to get extra testing for the code. We just
>>> need to select whether we should be sending the old or the new one.
>> I think in the previous review comments, this is what you asked to do:
>> send HDMI 2.0 VIC only in one place, either in AVI IF or HDMI IF, not both.
> Yes, the VIC. I didn't say anything about not sending any infoframe.
>
>> Now,  HDMI IF contains only two piece of information (from the code):
>>    frame->vic = vic (for HDMI 1.4 4k HDMI modes)
>>    or
>>    frame->s3d_strucrt = s3d_structure_from_display_mode()
>>
>> So if its a HDMI 2.0 monitor && we don't want to send s3d_info, then
>> there is nothing in the frame right ?
> Not sending any infoframe means a change in current behaviour which we
> may not want. It also means we don't treat HDMI 2.0 and 1.x sinks
> equally since for 1.x sinks we always send the infoframe.
>
> And appendix F of the spec seems to be telling us that there are
> sinks out there that don't properly switch from 3D to 2D when the source
> stops sending the old infoframe. Hence it seems like a good idea to
> always send it. They speak about HDMI 1.4 sinks specifically, but I
> wouldn't be surprised if similar problems crop up in 2.0 sinks as well.
>
> In fact I think it would have been nice if they had just totally
> replaced the old infoframe with the new one, and allowed us to always
> just send the new infoframe. But the spec specifically says that we
> have to use the old infoframe if possible :(
So should I remove this check, and keep things going as it was ?
- Shashank
>> - Shashank
>>>> +
>>>>    	intel_hdmi_set_hdmi_infoframe(encoder, crtc_state);
>>>>    }
>>>>    
>>>> diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
>>>> index f4329d2..737076e 100644
>>>> --- a/drivers/gpu/drm/i915/intel_sdvo.c
>>>> +++ b/drivers/gpu/drm/i915/intel_sdvo.c
>>>> @@ -996,7 +996,8 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo,
>>>>    	ssize_t len;
>>>>    
>>>>    	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
>>>> -						       &pipe_config->base.adjusted_mode);
>>>> +						       &pipe_config->base.adjusted_mode,
>>>> +						       false);
>>>>    	if (ret < 0) {
>>>>    		DRM_ERROR("couldn't fill AVI infoframe\n");
>>>>    		return false;
>>>> diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
>>>> index 0a4ffd7..5c0d024 100644
>>>> --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
>>>> +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
>>>> @@ -975,7 +975,7 @@ static int mtk_hdmi_setup_avi_infoframe(struct mtk_hdmi *hdmi,
>>>>    	u8 buffer[17];
>>>>    	ssize_t err;
>>>>    
>>>> -	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
>>>> +	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
>>>>    	if (err < 0) {
>>>>    		dev_err(hdmi->dev,
>>>>    			"Failed to get AVI infoframe from mode: %zd\n", err);
>>>> diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c b/drivers/gpu/drm/omapdrm/omap_encoder.c
>>>> index 86c977b..624f5b5 100644
>>>> --- a/drivers/gpu/drm/omapdrm/omap_encoder.c
>>>> +++ b/drivers/gpu/drm/omapdrm/omap_encoder.c
>>>> @@ -85,7 +85,8 @@ static void omap_encoder_mode_set(struct drm_encoder *encoder,
>>>>    	if (hdmi_mode && dssdev->driver->set_hdmi_infoframe) {
>>>>    		struct hdmi_avi_infoframe avi;
>>>>    
>>>> -		r = drm_hdmi_avi_infoframe_from_display_mode(&avi, adjusted_mode);
>>>> +		r = drm_hdmi_avi_infoframe_from_display_mode(&avi, adjusted_mode,
>>>> +							     false);
>>>>    		if (r == 0)
>>>>    			dssdev->driver->set_hdmi_infoframe(dssdev, &avi);
>>>>    	}
>>>> diff --git a/drivers/gpu/drm/radeon/radeon_audio.c b/drivers/gpu/drm/radeon/radeon_audio.c
>>>> index aaacac1..770e31f 100644
>>>> --- a/drivers/gpu/drm/radeon/radeon_audio.c
>>>> +++ b/drivers/gpu/drm/radeon/radeon_audio.c
>>>> @@ -516,7 +516,7 @@ static int radeon_audio_set_avi_packet(struct drm_encoder *encoder,
>>>>    	if (!connector)
>>>>    		return -EINVAL;
>>>>    
>>>> -	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
>>>> +	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
>>>>    	if (err < 0) {
>>>>    		DRM_ERROR("failed to setup AVI infoframe: %d\n", err);
>>>>    		return err;
>>>> diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c
>>>> index 7d9b75e..7149968 100644
>>>> --- a/drivers/gpu/drm/rockchip/inno_hdmi.c
>>>> +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c
>>>> @@ -294,7 +294,7 @@ static int inno_hdmi_config_video_avi(struct inno_hdmi *hdmi,
>>>>    	union hdmi_infoframe frame;
>>>>    	int rc;
>>>>    
>>>> -	rc = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
>>>> +	rc = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
>>>>    
>>>>    	if (hdmi->hdmi_data.enc_out_format == HDMI_COLORSPACE_YUV444)
>>>>    		frame.avi.colorspace = HDMI_COLORSPACE_YUV444;
>>>> diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
>>>> index a59c95a..dbc6a19 100644
>>>> --- a/drivers/gpu/drm/sti/sti_hdmi.c
>>>> +++ b/drivers/gpu/drm/sti/sti_hdmi.c
>>>> @@ -434,7 +434,7 @@ static int hdmi_avi_infoframe_config(struct sti_hdmi *hdmi)
>>>>    
>>>>    	DRM_DEBUG_DRIVER("\n");
>>>>    
>>>> -	ret = drm_hdmi_avi_infoframe_from_display_mode(&infoframe, mode);
>>>> +	ret = drm_hdmi_avi_infoframe_from_display_mode(&infoframe, mode, false);
>>>>    	if (ret < 0) {
>>>>    		DRM_ERROR("failed to setup AVI infoframe: %d\n", ret);
>>>>    		return ret;
>>>> diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c
>>>> index cda0491..718d8db 100644
>>>> --- a/drivers/gpu/drm/tegra/hdmi.c
>>>> +++ b/drivers/gpu/drm/tegra/hdmi.c
>>>> @@ -734,7 +734,7 @@ static void tegra_hdmi_setup_avi_infoframe(struct tegra_hdmi *hdmi,
>>>>    	u8 buffer[17];
>>>>    	ssize_t err;
>>>>    
>>>> -	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
>>>> +	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
>>>>    	if (err < 0) {
>>>>    		dev_err(hdmi->dev, "failed to setup AVI infoframe: %zd\n", err);
>>>>    		return;
>>>> diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c
>>>> index a8f5289..fb2709c 100644
>>>> --- a/drivers/gpu/drm/tegra/sor.c
>>>> +++ b/drivers/gpu/drm/tegra/sor.c
>>>> @@ -1904,7 +1904,7 @@ tegra_sor_hdmi_setup_avi_infoframe(struct tegra_sor *sor,
>>>>    	value &= ~INFOFRAME_CTRL_ENABLE;
>>>>    	tegra_sor_writel(sor, value, SOR_HDMI_AVI_INFOFRAME_CTRL);
>>>>    
>>>> -	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
>>>> +	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
>>>>    	if (err < 0) {
>>>>    		dev_err(sor->dev, "failed to setup AVI infoframe: %d\n", err);
>>>>    		return err;
>>>> diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
>>>> index ed63d4e..406d6d8 100644
>>>> --- a/drivers/gpu/drm/vc4/vc4_hdmi.c
>>>> +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
>>>> @@ -395,7 +395,7 @@ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder)
>>>>    	union hdmi_infoframe frame;
>>>>    	int ret;
>>>>    
>>>> -	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
>>>> +	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
>>>>    	if (ret < 0) {
>>>>    		DRM_ERROR("couldn't fill AVI infoframe\n");
>>>>    		return;
>>>> diff --git a/drivers/gpu/drm/zte/zx_hdmi.c b/drivers/gpu/drm/zte/zx_hdmi.c
>>>> index 0df7366..7e834e3 100644
>>>> --- a/drivers/gpu/drm/zte/zx_hdmi.c
>>>> +++ b/drivers/gpu/drm/zte/zx_hdmi.c
>>>> @@ -124,7 +124,7 @@ static int zx_hdmi_config_video_avi(struct zx_hdmi *hdmi,
>>>>    	union hdmi_infoframe frame;
>>>>    	int ret;
>>>>    
>>>> -	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
>>>> +	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
>>>>    	if (ret) {
>>>>    		DRM_DEV_ERROR(hdmi->dev, "failed to get avi infoframe: %d\n",
>>>>    			      ret);
>>>> diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
>>>> index 7b9f48b..89c0062 100644
>>>> --- a/include/drm/drm_edid.h
>>>> +++ b/include/drm/drm_edid.h
>>>> @@ -343,7 +343,8 @@ drm_load_edid_firmware(struct drm_connector *connector)
>>>>    
>>>>    int
>>>>    drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
>>>> -					 const struct drm_display_mode *mode);
>>>> +					 const struct drm_display_mode *mode,
>>>> +					 bool is_hdmi2_sink);
>>>>    int
>>>>    drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame,
>>>>    					    const struct drm_display_mode *mode);
>>>> -- 
>>>> 2.7.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 58+ messages in thread

end of thread, other threads:[~2017-07-03 11:24 UTC | newest]

Thread overview: 58+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-06-21 10:33 [RESEND-CI v4 00/15] HDMI YCBCR output handling in DRM layer Shashank Sharma
2017-06-21 10:33 ` [RESEND-CI v4 01/15] drm: add HDMI 2.0 VIC support for AVI info-frames Shashank Sharma
2017-06-21 13:41   ` Neil Armstrong
2017-06-30 11:54   ` Ville Syrjälä
2017-07-03  9:06     ` Sharma, Shashank
2017-07-03  9:57       ` Ville Syrjälä
2017-07-03 11:24         ` Sharma, Shashank
2017-06-21 10:34 ` [RESEND-CI v4 02/15] drm: add YCBCR 420 capability identifier Shashank Sharma
2017-06-21 13:42   ` Neil Armstrong
2017-06-21 10:34 ` [RESEND-CI v4 03/15] drm/edid: Complete CEA modedb(VIC 1-107) Shashank Sharma
2017-06-21 13:42   ` Neil Armstrong
2017-06-27 11:32   ` Ville Syrjälä
2017-06-30  5:11     ` Sharma, Shashank
2017-06-21 10:34 ` [RESEND-CI v4 04/15] drm/edid: parse YCBCR 420 videomodes from EDID Shashank Sharma
2017-06-27 11:52   ` Ville Syrjälä
2017-06-30  5:17     ` Sharma, Shashank
2017-06-30 11:58       ` Ville Syrjälä
2017-06-30 12:08         ` Sharma, Shashank
2017-06-21 10:34 ` [RESEND-CI v4 05/15] drm/edid: parse ycbcr 420 deep color information Shashank Sharma
2017-06-27 11:53   ` Ville Syrjälä
2017-06-30  5:20     ` Sharma, Shashank
2017-06-21 10:34 ` [RESEND-CI v4 06/15] drm/edid: parse sink information before CEA blocks Shashank Sharma
2017-06-27 11:55   ` Ville Syrjälä
2017-06-30  5:22     ` Sharma, Shashank
2017-06-30 11:46       ` Ville Syrjälä
2017-06-30 12:01         ` Sharma, Shashank
2017-06-21 10:34 ` [RESEND-CI v4 08/15] drm: set output colorspace in AVI infoframe Shashank Sharma
2017-06-21 10:34 ` [RESEND-CI v4 09/15] drm: add helper functions for YCBCR output handling Shashank Sharma
2017-06-22  7:05   ` [Intel-gfx] " Daniel Vetter
2017-06-22  9:42     ` Sharma, Shashank
2017-06-23  9:12       ` Daniel Vetter
2017-06-23 10:01         ` [Intel-gfx] " Sharma, Shashank
2017-06-21 10:34 ` [RESEND-CI v4 10/15] drm/i915: add compute-config for YCBCR outputs Shashank Sharma
2017-06-21 10:34 ` [RESEND-CI v4 11/15] drm/i915: prepare scaler for YCBCR420 modeset Shashank Sharma
2017-06-27 12:16   ` Ander Conselvan De Oliveira
2017-06-30  5:50     ` Sharma, Shashank
2017-06-30 11:34       ` Ander Conselvan De Oliveira
2017-06-30 11:59         ` Sharma, Shashank
2017-06-30 14:15           ` Ander Conselvan De Oliveira
2017-06-30 14:27             ` Sharma, Shashank
2017-06-21 10:34 ` [RESEND-CI v4 12/15] drm/i915: prepare pipe for YCBCR output Shashank Sharma
2017-06-21 10:34 ` [RESEND-CI v4 13/15] drm/i915: prepare csc unit for YCBCR HDMI output Shashank Sharma
2017-06-29 12:08   ` Ander Conselvan De Oliveira
2017-06-30  6:03     ` Sharma, Shashank
2017-06-30 10:57       ` Ander Conselvan De Oliveira
2017-06-21 10:34 ` [RESEND-CI v4 14/15] drm/i915: set colorspace for ycbcr outputs Shashank Sharma
2017-06-21 10:34 ` [RESEND-CI v4 15/15] drm/i915/glk: set HDMI 2.0 identifier Shashank Sharma
2017-06-30 12:07   ` [Intel-gfx] " Ander Conselvan De Oliveira
2017-06-30 12:17     ` Sharma, Shashank
2017-06-30 13:28       ` [Intel-gfx] " Ander Conselvan De Oliveira
2017-06-21 10:34 ` [PATCH v5 7/7] drm: create hdmi output property Shashank Sharma
2017-06-22  7:14   ` [Intel-gfx] " Daniel Vetter
2017-06-22  8:33     ` Sharma, Shashank
2017-06-23  9:20       ` [Intel-gfx] " Daniel Vetter
2017-06-23 10:05         ` Sharma, Shashank
2017-06-23 10:28           ` Daniel Vetter
2017-06-27 12:14   ` Ville Syrjälä
2017-06-30  5:43     ` Sharma, Shashank

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.