All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/20] YCBCR 4:2:0 handling for LSPCON
@ 2017-07-10 11:18 Shashank Sharma
  2017-07-10 11:18 ` [PATCH 01/20] drm: handle HDMI 2.0 VICs in AVI info-frames Shashank Sharma
                   ` (20 more replies)
  0 siblings, 21 replies; 76+ messages in thread
From: Shashank Sharma @ 2017-07-10 11:18 UTC (permalink / raw)
  To: intel-gfx, dri-devel

LSPCON is a DP->HDMI active dongle, enumerated as DP dual
mode adapter on Intel GEN9 platforms. It's provided by two
different vendors
        - Mega Chips America (MCA)
        - Parade Technologies (Parade)

In order to support YCBCR 4:2:0 outputs, these are the essential
steps:
        - Convert HDMI output format from RGB to YCBCR 4:4:4.
        - Set appropriate color space in AVI infoframes.
        - Write AVI infoframes to vendor specific AUX registers.

This patch series adds 5 patches, to accommodate above steps and
enable YCBCR 4:2:0 output for LSPCON based HDMI displays. As this
series is dependent on HDMI 2.0 YCBCR 4:2:0 framework, it also
contains 15 patches from HDMI 2.0 YCBCR 4:2:0 series too, which are
published and reviewed as a separate series here:
https://patchwork.freedesktop.org/series/26973/

Requesting reviewers to review only last 5 patches, starting from
patch 15, which are:
  drm: add function to read vendor OUI
  drm/i915: check LSPCON vendor OUI
  drm/i915: YCBCR 420 support for LSPCON
  drm/i915: Move AVI infoframe function to DDI layer
  drm/i915: write AVI infoframes for LSPCON

Shashank Sharma (20):
  drm: handle HDMI 2.0 VICs in AVI info-frames
  drm/edid: complete CEA modedb(VIC 1-107)
  drm/edid: parse sink information before CEA blocks
  drm/edid: cleanup patch for CEA extended-tag macro
  drm/edid: parse YCBCR420 videomodes from EDID
  drm: add helper to validate YCBCR420 modes
  drm/edid: parse ycbcr 420 deep color information
  drm: set output colorspace in AVI infoframe
  drm: add helper functions for YCBCR420 handling
  drm/i915: add config function for YCBCR420 outputs
  drm/i915: prepare scaler for YCBCR420 modeset
  drm/i915: prepare pipe for YCBCR420 output
  drm/i915: prepare csc unit for YCBCR420 output
  drm/i915: set colorspace for YCBCR420 outputs
  drm/i915/glk: set HDMI 2.0 identifier
  drm: add function to read vendor OUI
  drm/i915: check LSPCON vendor OUI
  drm/i915: YCBCR 420 support for LSPCON
  drm/i915: Move AVI infoframe function to DDI layer
  drm/i915: write AVI infoframes for LSPCON

 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_v6_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_dp_dual_mode_helper.c |  24 ++
 drivers/gpu/drm/drm_edid.c                | 469 +++++++++++++++++++++++++++++-
 drivers/gpu/drm/drm_modes.c               | 102 +++++++
 drivers/gpu/drm/drm_probe_helper.c        |   4 +
 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_ddi.c          |  97 +++++-
 drivers/gpu/drm/i915/intel_display.c      |  52 ++++
 drivers/gpu/drm/i915/intel_dp.c           |  16 +-
 drivers/gpu/drm/i915/intel_drv.h          |  51 +++-
 drivers/gpu/drm/i915/intel_hdmi.c         |  97 +++---
 drivers/gpu/drm/i915/intel_lspcon.c       | 216 ++++++++++++++
 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/msm/hdmi/hdmi_bridge.c    |   2 +-
 drivers/gpu/drm/nouveau/nv50_display.c    |   3 +-
 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/sun4i/sun4i_hdmi_enc.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               |  32 ++
 include/drm/drm_dp_dual_mode_helper.h     |   4 +-
 include/drm/drm_edid.h                    |  17 +-
 include/drm/drm_modes.h                   |  11 +
 40 files changed, 1218 insertions(+), 81 deletions(-)

-- 
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] 76+ messages in thread

* [PATCH 01/20] drm: handle HDMI 2.0 VICs in AVI info-frames
  2017-07-10 11:18 [PATCH 00/20] YCBCR 4:2:0 handling for LSPCON Shashank Sharma
@ 2017-07-10 11:18 ` Shashank Sharma
  2017-07-10 11:18 ` [PATCH 02/20] drm/edid: complete CEA modedb(VIC 1-107) Shashank Sharma
                   ` (19 subsequent siblings)
  20 siblings, 0 replies; 76+ messages in thread
From: Shashank Sharma @ 2017-07-10 11:18 UTC (permalink / raw)
  To: intel-gfx, dri-devel

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.

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.
V4: Rebase
V5: Added r-b from Neil.
    Addressed review comments from Ville
    - Do not block HDMI vendor IF, instead check for VIC while
      handling AVI infoframes
V6: Rebase

Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
Reviewed-by: Neil Armstrong <narmstrong@baylibre.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_v6_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                | 26 +++++++++++++++++++++++++-
 drivers/gpu/drm/exynos/exynos_hdmi.c      |  2 +-
 drivers/gpu/drm/i2c/tda998x_drv.c         |  2 +-
 drivers/gpu/drm/i915/intel_hdmi.c         |  5 ++++-
 drivers/gpu/drm/i915/intel_sdvo.c         |  3 ++-
 drivers/gpu/drm/mediatek/mtk_hdmi.c       |  2 +-
 drivers/gpu/drm/msm/hdmi/hdmi_bridge.c    |  2 +-
 drivers/gpu/drm/nouveau/nv50_display.c    |  3 ++-
 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/sun4i/sun4i_hdmi_enc.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 ++-
 25 files changed, 57 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
index 9f78c03..aff1f48 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
@@ -1867,7 +1867,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 4bcf01d..2df650d 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
@@ -1851,7 +1851,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_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
index fd134a4..0c3891f 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
@@ -1597,7 +1597,7 @@ static void dce_v6_0_audio_set_avi_infoframe(struct drm_encoder *encoder,
 	ssize_t err;
 	u32 tmp;
 
-	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 a9e8695..c164bef 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
@@ -1750,7 +1750,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..0667b07 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,28 @@ 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;
+
+	/*
+	 * HDMI spec says if a mode is found in HDMI 1.4b 4K modes
+	 * we should send its VIC in vendor infoframes, else send the
+	 * VIC in AVI infoframes. Lets check if this mode is present in
+	 * HDMI 1.4b 4K modes
+	 */
+	if (frame->video_code) {
+		u8 vendor_if_vic = drm_match_hdmi_mode(mode);
+		bool is_s3d = mode->flags & DRM_MODE_FLAG_3D_MASK;
+
+		if (drm_valid_hdmi_vic(vendor_if_vic) && !is_s3d)
+			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..cc0d100 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;
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index f902922..e58a47d 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/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
index ae40e71..13ac822 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
@@ -97,7 +97,7 @@ static void msm_hdmi_config_avi_infoframe(struct hdmi *hdmi)
 	u32 val;
 	int len;
 
-	drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
+	drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
 
 	len = hdmi_infoframe_pack(&frame, buffer, sizeof(buffer));
 	if (len < 0) {
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 42a85c1..5f71e30 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -2762,7 +2762,8 @@ nv50_hdmi_enable(struct drm_encoder *encoder, struct drm_display_mode *mode)
 	if (!drm_detect_hdmi_monitor(nv_connector->edid))
 		return;
 
-	ret = drm_hdmi_avi_infoframe_from_display_mode(&avi_frame.avi, mode);
+	ret = drm_hdmi_avi_infoframe_from_display_mode(&avi_frame.avi, mode,
+						       false);
 	if (!ret) {
 		/* We have an AVI InfoFrame, populate it to the display */
 		args.pwr.avi_infoframe_length
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/sun4i/sun4i_hdmi_enc.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
index d3398f62..83b7a2a 100644
--- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
@@ -52,7 +52,7 @@ static int sun4i_hdmi_setup_avi_infoframes(struct sun4i_hdmi *hdmi,
 	u8 buffer[17];
 	int i, ret;
 
-	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
+	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode, false);
 	if (ret < 0) {
 		DRM_ERROR("Failed to get infoframes from mode\n");
 		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] 76+ messages in thread

* [PATCH 02/20] drm/edid: complete CEA modedb(VIC 1-107)
  2017-07-10 11:18 [PATCH 00/20] YCBCR 4:2:0 handling for LSPCON Shashank Sharma
  2017-07-10 11:18 ` [PATCH 01/20] drm: handle HDMI 2.0 VICs in AVI info-frames Shashank Sharma
@ 2017-07-10 11:18 ` Shashank Sharma
  2017-07-12 17:18   ` Ville Syrjälä
  2017-07-10 11:18 ` [PATCH 03/20] drm/edid: parse sink information before CEA blocks Shashank Sharma
                   ` (18 subsequent siblings)
  20 siblings, 1 reply; 76+ messages in thread
From: Shashank Sharma @ 2017-07-10 11:18 UTC (permalink / raw)
  To: intel-gfx, dri-devel

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/

V2: Rebase
V3: Rebase
V4: Added native bit handling as per CEA-861-F spec (Ville)
V5: Fix timings for VIC 77:1920x1080 and 104:3840x2160p (Ville)
    Remove unnecessary paranthesis from function svd_to_vic (Ville)
    Added r-b (Neil)

Reviewed-by: Jose Abreu <Jose.Abreu@synopsys.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Reviewed-by: Neil Armstrong <narmstrong@baylibre.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 0667b07..b879662 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, 1089, 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, 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_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] 76+ messages in thread

* [PATCH 03/20] drm/edid: parse sink information before CEA blocks
  2017-07-10 11:18 [PATCH 00/20] YCBCR 4:2:0 handling for LSPCON Shashank Sharma
  2017-07-10 11:18 ` [PATCH 01/20] drm: handle HDMI 2.0 VICs in AVI info-frames Shashank Sharma
  2017-07-10 11:18 ` [PATCH 02/20] drm/edid: complete CEA modedb(VIC 1-107) Shashank Sharma
@ 2017-07-10 11:18 ` Shashank Sharma
  2017-07-10 11:18 ` [PATCH 04/20] drm/edid: cleanup patch for CEA extended-tag macro Shashank Sharma
                   ` (17 subsequent siblings)
  20 siblings, 0 replies; 76+ messages in thread
From: Shashank Sharma @ 2017-07-10 11:18 UTC (permalink / raw)
  To: intel-gfx, dri-devel

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.

V4: Introduced new patch in the series
V5: Move this patch before 4:2:0 parsing patch (ville)
    Added r-b from Ville

Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
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 b879662..274356d 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -4440,6 +4440,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
@@ -4466,8 +4473,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] 76+ messages in thread

* [PATCH 04/20] drm/edid: cleanup patch for CEA extended-tag macro
  2017-07-10 11:18 [PATCH 00/20] YCBCR 4:2:0 handling for LSPCON Shashank Sharma
                   ` (2 preceding siblings ...)
  2017-07-10 11:18 ` [PATCH 03/20] drm/edid: parse sink information before CEA blocks Shashank Sharma
@ 2017-07-10 11:18 ` Shashank Sharma
  2017-07-10 11:18 ` [PATCH 05/20] drm/edid: parse YCBCR420 videomodes from EDID Shashank Sharma
                   ` (16 subsequent siblings)
  20 siblings, 0 replies; 76+ messages in thread
From: Shashank Sharma @ 2017-07-10 11:18 UTC (permalink / raw)
  To: intel-gfx, dri-devel

CEA-861-F introduces extended tag codes for EDID extension blocks,
which indicates the actual type of the data block. The code for
using exteded tag is 0x7, whereas in the existing code, the
corresponding macro is named as "VIDEO_CAPABILITY_BLOCK"

This patch renames the macro and usages from "VIDEO_CAPABILITY_BLOCK"
to "USE_EXTENDED_TAG"

V2: Add extended tag code check for video capabilitiy block (ville)
V3: Ville:
	- Use suggested names for macros
	- Check the block length first, before checking the extended tag
V4: Fix commit message (David)
V5: Introduced this patch into HDMI-YCBCR-output series
V6: Rebase

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

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 274356d..9a07f42 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -2781,7 +2781,8 @@ 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 USE_EXTENDED_TAG 0x07
+#define EXT_VIDEO_CAPABILITY_BLOCK 0x00
 #define EDID_BASIC_AUDIO	(1 << 6)
 #define EDID_CEA_YCRCB444	(1 << 5)
 #define EDID_CEA_YCRCB422	(1 << 4)
@@ -3443,6 +3444,12 @@ cea_db_payload_len(const u8 *db)
 }
 
 static int
+cea_db_extended_tag(const u8 *db)
+{
+	return db[1];
+}
+
+static int
 cea_db_tag(const u8 *db)
 {
 	return db[0] >> 5;
@@ -4018,8 +4025,10 @@ bool drm_rgb_quant_range_selectable(struct edid *edid)
 		return false;
 
 	for_each_cea_db(edid_ext, i, start, end) {
-		if (cea_db_tag(&edid_ext[i]) == VIDEO_CAPABILITY_BLOCK &&
-		    cea_db_payload_len(&edid_ext[i]) == 2) {
+		if (cea_db_tag(&edid_ext[i]) == USE_EXTENDED_TAG &&
+		    cea_db_payload_len(&edid_ext[i]) == 2 &&
+		    cea_db_extended_tag(&edid_ext[i]) ==
+			EXT_VIDEO_CAPABILITY_BLOCK) {
 			DRM_DEBUG_KMS("CEA VCDB 0x%02x\n", edid_ext[i + 2]);
 			return edid_ext[i + 2] & EDID_CEA_VCDB_QS;
 		}
-- 
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] 76+ messages in thread

* [PATCH 05/20] drm/edid: parse YCBCR420 videomodes from EDID
  2017-07-10 11:18 [PATCH 00/20] YCBCR 4:2:0 handling for LSPCON Shashank Sharma
                   ` (3 preceding siblings ...)
  2017-07-10 11:18 ` [PATCH 04/20] drm/edid: cleanup patch for CEA extended-tag macro Shashank Sharma
@ 2017-07-10 11:18 ` Shashank Sharma
  2017-07-10 11:18 ` [PATCH 06/20] drm: add helper to validate YCBCR420 modes Shashank Sharma
                   ` (15 subsequent siblings)
  20 siblings, 0 replies; 76+ messages in thread
From: Shashank Sharma @ 2017-07-10 11:18 UTC (permalink / raw)
  To: intel-gfx, dri-devel

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.

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()

V5: Addressed review comments from Ville:
    - Add the patch which cleans up the current EXTENDED_TAG usage
    - Make y420_cmdb_map u64
    - Do not block ycbcr420 modes while parsing the EDID, rather
      add a separate helper function to prune ycbcr420-only modes from
      connector's probed modes.

V6: Rebase

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

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 9a07f42..10dab62 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -2783,6 +2783,8 @@ add_detailed_modes(struct drm_connector *connector, struct edid *edid,
 #define SPEAKER_BLOCK	0x04
 #define USE_EXTENDED_TAG 0x07
 #define EXT_VIDEO_CAPABILITY_BLOCK 0x00
+#define EXT_VIDEO_DATA_BLOCK_420	0x0E
+#define EXT_VIDEO_CAP_BLOCK_Y420CMDB 0x0F
 #define EDID_BASIC_AUDIO	(1 << 6)
 #define EDID_CEA_YCRCB444	(1 << 5)
 #define EDID_CEA_YCRCB422	(1 << 4)
@@ -3154,15 +3156,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 (hdmi->y420_cmdb_map & (1 << i))
+				drm_add_cmdb_modes(connector, db[i]);
+
 			drm_mode_probed_add(connector, mode);
 			modes++;
 		}
@@ -3504,9 +3570,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) != USE_EXTENDED_TAG)
+		return false;
+
+	if (!cea_db_payload_len(db))
+		return false;
+
+	if (cea_db_extended_tag(db) != EXT_VIDEO_CAP_BLOCK_Y420CMDB)
+		return false;
+
+	return true;
+}
+
+static bool cea_db_is_y420vdb(const u8 *db)
+{
+	if (cea_db_tag(db) != USE_EXTENDED_TAG)
+		return false;
+
+	if (!cea_db_payload_len(db))
+		return false;
+
+	if (cea_db_extended_tag(db) != EXT_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)
 {
@@ -3529,10 +3664,16 @@ 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)) {
+				const u8 *vdb420 = &db[2];
+
+				/* Add 4:2:0(only) modes present in EDID */
+				modes += do_y420vdb_modes(connector,
+							  vdb420,
+							  dbl - 1);
 			}
 		}
 	}
@@ -4215,6 +4356,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);
 	}
 }
 
@@ -4476,6 +4619,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 ae5b7dc..b3af8e3 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -135,6 +135,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 */
+	u64 y420_cmdb_map;
 };
 
 /**
@@ -198,6 +217,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

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

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

* [PATCH 06/20] drm: add helper to validate YCBCR420 modes
  2017-07-10 11:18 [PATCH 00/20] YCBCR 4:2:0 handling for LSPCON Shashank Sharma
                   ` (4 preceding siblings ...)
  2017-07-10 11:18 ` [PATCH 05/20] drm/edid: parse YCBCR420 videomodes from EDID Shashank Sharma
@ 2017-07-10 11:18 ` Shashank Sharma
  2017-07-12 17:18   ` Ville Syrjälä
  2017-07-10 11:18 ` [PATCH 07/20] drm/edid: parse ycbcr 420 deep color information Shashank Sharma
                   ` (14 subsequent siblings)
  20 siblings, 1 reply; 76+ messages in thread
From: Shashank Sharma @ 2017-07-10 11:18 UTC (permalink / raw)
  To: intel-gfx, dri-devel

YCBCR420 modes are supported only on HDMI 2.0 capable sources.
This patch adds:
- A drm helper to validate YCBCR420-only mode on a particular
  connector. This function will help pruning the YCBCR420-only
  modes from the connector's modelist.
- 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 YCBCR420 output, so that no
  YCBCR 420 modes will be listed for sources which can't handle it.
  A driver should set this variable if it wants to see YCBCR420 modes
  in the modedb.

V5: Introduced the patch in series.
V5-resend: Squashed two patches (validate YCBCR420 and add YCBCR420
	   identifier)

Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
---
 drivers/gpu/drm/drm_edid.c         |  3 ++-
 drivers/gpu/drm/drm_modes.c        | 28 ++++++++++++++++++++++++++++
 drivers/gpu/drm/drm_probe_helper.c |  4 ++++
 include/drm/drm_connector.h        |  9 +++++++++
 include/drm/drm_edid.h             |  1 +
 include/drm/drm_modes.h            |  5 +++++
 6 files changed, 49 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 10dab62..44be128 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -2950,10 +2950,11 @@ 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);
 }
+EXPORT_SYMBOL(drm_valid_cea_vic);
 
 /**
  * drm_get_cea_aspect_ratio - get the picture aspect ratio corresponding to
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index f2493b9..3b53c8e3 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -1083,6 +1083,34 @@ drm_mode_validate_size(const struct drm_display_mode *mode,
 }
 EXPORT_SYMBOL(drm_mode_validate_size);
 
+/**
+ * drm_mode_ycbcr420_only - add 'ycbcr420-only' modes only when allowed
+ * @mode: mode to check
+ * @connector: drm connector under action
+ *
+ * This function is a helper which can be used to filter out any YCBCR420
+ * only mode, when the source doesn't support it.
+ *
+ * Returns:
+ * The mode status
+ */
+enum drm_mode_status
+drm_mode_validate_ycbcr420(const struct drm_display_mode *mode,
+			   struct drm_connector *connector)
+{
+	u8 vic = drm_match_cea_mode(mode);
+	enum drm_mode_status status = MODE_OK;
+	struct drm_hdmi_info *hdmi = &connector->display_info.hdmi;
+
+	if (drm_valid_cea_vic(vic) && test_bit(vic, hdmi->y420_vdb_modes)) {
+		if (!connector->ycbcr_420_allowed)
+			status = MODE_NO_420;
+	}
+
+	return status;
+}
+EXPORT_SYMBOL(drm_mode_validate_ycbcr420);
+
 #define MODE_STATUS(status) [MODE_ ## status + 3] = #status
 
 static const char * const drm_mode_status_names[] = {
diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
index 00e6832..904966c 100644
--- a/drivers/gpu/drm/drm_probe_helper.c
+++ b/drivers/gpu/drm/drm_probe_helper.c
@@ -528,6 +528,10 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
 		if (mode->status == MODE_OK)
 			mode->status = drm_mode_validate_pipeline(mode,
 								  connector);
+
+		if (mode->status == MODE_OK)
+			mode->status = drm_mode_validate_ycbcr420(mode,
+								  connector);
 	}
 
 prune:
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index b3af8e3..225e092 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -746,6 +746,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.
diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
index 89c0062..b55b2a7 100644
--- a/include/drm/drm_edid.h
+++ b/include/drm/drm_edid.h
@@ -477,4 +477,5 @@ void drm_edid_get_monitor_name(struct edid *edid, char *name,
 struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
 					   int hsize, int vsize, int fresh,
 					   bool rb);
+bool drm_valid_cea_vic(u8 vic);
 #endif /* __DRM_EDID_H__ */
diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h
index 94ac771..f8a1268 100644
--- a/include/drm/drm_modes.h
+++ b/include/drm/drm_modes.h
@@ -80,6 +80,7 @@ struct videomode;
  * @MODE_ONE_SIZE: only one resolution is supported
  * @MODE_NO_REDUCED: monitor doesn't accept reduced blanking
  * @MODE_NO_STEREO: stereo modes not supported
+ * @MODE_NO_420: ycbcr 420 modes not supported
  * @MODE_STALE: mode has become stale
  * @MODE_BAD: unspecified reason
  * @MODE_ERROR: error condition
@@ -124,6 +125,7 @@ enum drm_mode_status {
 	MODE_ONE_SIZE,
 	MODE_NO_REDUCED,
 	MODE_NO_STEREO,
+	MODE_NO_420,
 	MODE_STALE = -3,
 	MODE_BAD = -2,
 	MODE_ERROR = -1
@@ -496,6 +498,9 @@ bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1,
 enum drm_mode_status drm_mode_validate_basic(const struct drm_display_mode *mode);
 enum drm_mode_status drm_mode_validate_size(const struct drm_display_mode *mode,
 					    int maxX, int maxY);
+enum drm_mode_status
+drm_mode_validate_ycbcr420(const struct drm_display_mode *mode,
+			   struct drm_connector *connector);
 void drm_mode_prune_invalid(struct drm_device *dev,
 			    struct list_head *mode_list, bool verbose);
 void drm_mode_sort(struct list_head *mode_list);
-- 
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] 76+ messages in thread

* [PATCH 07/20] drm/edid: parse ycbcr 420 deep color information
  2017-07-10 11:18 [PATCH 00/20] YCBCR 4:2:0 handling for LSPCON Shashank Sharma
                   ` (5 preceding siblings ...)
  2017-07-10 11:18 ` [PATCH 06/20] drm: add helper to validate YCBCR420 modes Shashank Sharma
@ 2017-07-10 11:18 ` Shashank Sharma
  2017-07-12 17:18   ` Ville Syrjälä
  2017-07-10 11:18 ` [PATCH 08/20] drm: set output colorspace in AVI infoframe Shashank Sharma
                   ` (13 subsequent siblings)
  20 siblings, 1 reply; 76+ messages in thread
From: Shashank Sharma @ 2017-07-10 11:18 UTC (permalink / raw)
  To: intel-gfx, dri-devel

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)
V5: Optimize function, if(conditions) not reqd (Ville)
V6: Rebase

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

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 44be128..944a28f 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -4199,6 +4199,16 @@ 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)
+{
+	u8 dc_mask;
+	struct drm_hdmi_info *hdmi = &connector->display_info.hdmi;
+
+	dc_mask = db[7] & DRM_EDID_YCBCR420_DC_MASK;
+	hdmi->y420_dc_modes |= dc_mask;
+}
+
 static void drm_parse_hdmi_forum_vsdb(struct drm_connector *connector,
 				 const u8 *hf_vsdb)
 {
@@ -4239,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 225e092..4bc0882 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -154,6 +154,9 @@ struct drm_hdmi_info {
 
 	/** @y420_cmdb_map: bitmap of SVD index, to extraxt vcb modes */
 	u64 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 b55b2a7..aa58146 100644
--- a/include/drm/drm_edid.h
+++ b/include/drm/drm_edid.h
@@ -213,6 +213,14 @@ 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)
+#define DRM_EDID_YCBCR420_DC_MASK (DRM_EDID_YCBCR420_DC_48 | \
+				    DRM_EDID_YCBCR420_DC_36 | \
+				    DRM_EDID_YCBCR420_DC_30)
+
 /* 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] 76+ messages in thread

* [PATCH 08/20] drm: set output colorspace in AVI infoframe
  2017-07-10 11:18 [PATCH 00/20] YCBCR 4:2:0 handling for LSPCON Shashank Sharma
                   ` (6 preceding siblings ...)
  2017-07-10 11:18 ` [PATCH 07/20] drm/edid: parse ycbcr 420 deep color information Shashank Sharma
@ 2017-07-10 11:18 ` Shashank Sharma
  2017-07-12 17:17   ` Ville Syrjälä
  2017-07-10 11:18 ` [PATCH 09/20] drm: add helper functions for YCBCR420 handling Shashank Sharma
                   ` (12 subsequent siblings)
  20 siblings, 1 reply; 76+ messages in thread
From: Shashank Sharma @ 2017-07-10 11:18 UTC (permalink / raw)
  To: intel-gfx, dri-devel

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

This patch adds a function to add the output colorspace
information in the AVI infoframes.

V2: Rebase
V3: Rebase
V4: Rebase
V5: Rebase
V6: Made patch independent of HDMI output type.

Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
---
 drivers/gpu/drm/drm_edid.c | 29 +++++++++++++++++++++++++++++
 include/drm/drm_edid.h     |  5 +++++
 2 files changed, 34 insertions(+)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 944a28f..cede86e 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -4796,6 +4796,35 @@ 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 hdmi_colorspace colorspace)
+{
+	if (colorspace > HDMI_COLORSPACE_YUV420 ||
+		colorspace < HDMI_COLORSPACE_RGB) {
+		DRM_ERROR("Invalid color space type\n");
+		return -EINVAL;
+	}
+
+	frame->colorspace = colorspace;
+	if (colorspace == HDMI_COLORSPACE_YUV420)
+		frame->pixel_repeat = 0;
+
+	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 aa58146..b79e0cb 100644
--- a/include/drm/drm_edid.h
+++ b/include/drm/drm_edid.h
@@ -332,6 +332,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);
@@ -354,6 +355,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 hdmi_colorspace colorspace);
+int
 drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame,
 					    const struct drm_display_mode *mode);
 void
-- 
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] 76+ messages in thread

* [PATCH 09/20] drm: add helper functions for YCBCR420 handling
  2017-07-10 11:18 [PATCH 00/20] YCBCR 4:2:0 handling for LSPCON Shashank Sharma
                   ` (7 preceding siblings ...)
  2017-07-10 11:18 ` [PATCH 08/20] drm: set output colorspace in AVI infoframe Shashank Sharma
@ 2017-07-10 11:18 ` Shashank Sharma
  2017-07-12 17:17   ` Ville Syrjälä
  2017-07-10 11:18 ` [PATCH 10/20] drm/i915: add config function for YCBCR420 outputs Shashank Sharma
                   ` (11 subsequent siblings)
  20 siblings, 1 reply; 76+ messages in thread
From: Shashank Sharma @ 2017-07-10 11:18 UTC (permalink / raw)
  To: intel-gfx, dri-devel

This patch adds helper functions for YCBCR 420 handling.
These functions do:
- check if a given video mode is YCBCR 420 only mode.
- check if a given video mode is YCBCR 420 also mode.

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)
V5: Addressed review comments from Danvet:
    - %s/drm_find_hdmi_output_type/drm_display_info_hdmi_output_type
    - %s/drm_can_support_ycbcr_output/drm_display_supports_ycbcr_output
    - %s/drm_can_support_this_ycbcr_output/
		drm_display_supports_this_ycbcr_output
    - pass drm_display_info instead of drm_connector for consistency
    - For drm_get_highest_quality_ycbcr_supported doc, move the variable
      description above, and then the function description.
V6: Add only YCBCR420 helpers (Ville)

Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
---
 drivers/gpu/drm/drm_modes.c | 74 +++++++++++++++++++++++++++++++++++++++++++++
 include/drm/drm_modes.h     |  6 ++++
 2 files changed, 80 insertions(+)

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 3b53c8e3..61c82a38 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -1604,3 +1604,77 @@ 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 be supported in YCBCR420 format
+ * false if not.
+ */
+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);
+}
+EXPORT_SYMBOL(drm_mode_is_420_only);
+
+/**
+ * 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 be support YCBCR420 format
+ * false if not.
+ */
+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);
+}
+EXPORT_SYMBOL(drm_mode_is_420_also);
+/**
+ * drm_mode_is_420 - if a given videomode can be supported in YCBCR420
+ * output format
+ *
+ * @display: display under action.
+ * @mode: video mode to be tested.
+ *
+ * Returns:
+ * true if the mode can be supported in YCBCR420 format
+ * false if not.
+ */
+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);
+}
+EXPORT_SYMBOL(drm_mode_is_420);
diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h
index f8a1268..980db27 100644
--- a/include/drm/drm_modes.h
+++ b/include/drm/drm_modes.h
@@ -452,6 +452,12 @@ int drm_mode_convert_umode(struct drm_display_mode *out,
 			   const struct drm_mode_modeinfo *in);
 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);
+bool drm_mode_is_420_only(struct drm_display_info *display,
+			struct drm_display_mode *mode);
+bool drm_mode_is_420_also(struct drm_display_info *display,
+			struct drm_display_mode *mode);
+bool drm_mode_is_420(struct drm_display_info *display,
+			struct drm_display_mode *mode);
 
 struct drm_display_mode *drm_cvt_mode(struct drm_device *dev,
 				      int hdisplay, int vdisplay, int vrefresh,
-- 
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] 76+ messages in thread

* [PATCH 10/20] drm/i915: add config function for YCBCR420 outputs
  2017-07-10 11:18 [PATCH 00/20] YCBCR 4:2:0 handling for LSPCON Shashank Sharma
                   ` (8 preceding siblings ...)
  2017-07-10 11:18 ` [PATCH 09/20] drm: add helper functions for YCBCR420 handling Shashank Sharma
@ 2017-07-10 11:18 ` Shashank Sharma
  2017-07-12 17:17   ` Ville Syrjälä
  2017-07-10 11:18 ` [PATCH 11/20] drm/i915: prepare scaler for YCBCR420 modeset Shashank Sharma
                   ` (10 subsequent siblings)
  20 siblings, 1 reply; 76+ messages in thread
From: Shashank Sharma @ 2017-07-10 11:18 UTC (permalink / raw)
  To: intel-gfx, dri-devel

This patch checks encoder level support for YCBCR420 outputs.
The logic goes as simple as this:
If the input mode is YCBCR420-only mode: prepare HDMI for
YCBCR420 output, else continue with RGB output mode.

It checks if the mode is YCBCR420 and source can support this
output then it marks the ycbcr_420 output indicator 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
V5: Rebase
V6: Check and handle YCBCR420-only modes, discard the property
    based approach (Ville)

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

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 4e03ca6..01900e1 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(ycbcr420);
 
 	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 d17a324..592243b 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 */
+	bool ycbcr420;
 };
 
 struct intel_crtc {
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index cc0d100..276d916 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -1305,7 +1305,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,
+				bool output_ycbcr420)
 {
 	struct drm_i915_private *dev_priv =
 		to_i915(crtc_state->base.crtc->dev);
@@ -1330,6 +1331,13 @@ static bool hdmi_12bpc_possible(struct intel_crtc_state *crtc_state)
 		if (connector_state->crtc != crtc_state->base.crtc)
 			continue;
 
+		if (output_ycbcr420) {
+			const struct drm_hdmi_info *hdmi = &info->hdmi;
+
+			if (!(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;
 	}
@@ -1342,6 +1350,25 @@ static bool hdmi_12bpc_possible(struct intel_crtc_state *crtc_state)
 	return true;
 }
 
+static bool
+intel_hdmi_ycbcr420_config(struct drm_connector *connector,
+			       struct intel_crtc_state *config,
+			       int *clock_12bpc, int *clock_8bpc)
+{
+
+	if (!connector->ycbcr_420_allowed) {
+		DRM_ERROR("Platform doesn't support YCBCR420 output\n");
+		return false;
+	}
+
+	/* YCBCR420 TMDS rate requirement is half the pixel clock */
+	config->port_clock /= 2;
+	*clock_12bpc /= 2;
+	*clock_8bpc /= 2;
+	config->ycbcr420 = true;
+	return true;
+}
+
 bool intel_hdmi_compute_config(struct intel_encoder *encoder,
 			       struct intel_crtc_state *pipe_config,
 			       struct drm_connector_state *conn_state)
@@ -1349,7 +1376,8 @@ 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;
@@ -1379,6 +1407,14 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
 		clock_12bpc *= 2;
 	}
 
+	if (drm_mode_is_420_only(&connector->display_info, adjusted_mode)) {
+		if (!intel_hdmi_ycbcr420_config(connector, pipe_config,
+						&clock_12bpc, &clock_8bpc)) {
+			DRM_ERROR("Can't support YCBCR420 output\n");
+			return false;
+		}
+	}
+
 	if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv))
 		pipe_config->has_pch_encoder = true;
 
@@ -1398,7 +1434,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, pipe_config->ycbcr420)) {
 		DRM_DEBUG_KMS("picking bpc to 12 for HDMI output\n");
 		desired_bpp = 12*3;
 
-- 
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] 76+ messages in thread

* [PATCH 11/20] drm/i915: prepare scaler for YCBCR420 modeset
  2017-07-10 11:18 [PATCH 00/20] YCBCR 4:2:0 handling for LSPCON Shashank Sharma
                   ` (9 preceding siblings ...)
  2017-07-10 11:18 ` [PATCH 10/20] drm/i915: add config function for YCBCR420 outputs Shashank Sharma
@ 2017-07-10 11:18 ` Shashank Sharma
  2017-07-12 17:17   ` Ville Syrjälä
  2017-07-10 11:18 ` [PATCH 12/20] drm/i915: prepare pipe for YCBCR420 output Shashank Sharma
                   ` (9 subsequent siblings)
  20 siblings, 1 reply; 76+ messages in thread
From: Shashank Sharma @ 2017-07-10 11:18 UTC (permalink / raw)
  To: intel-gfx, dri-devel

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
V5: addressed review comments from Ander:
    - No need to check both scaler_user && hdmi_output.
      Check for scaler_user is enough.
Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
---
 drivers/gpu/drm/i915/intel_atomic.c  |  6 ++++++
 drivers/gpu/drm/i915/intel_display.c | 23 +++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h     | 10 +++++++++-
 drivers/gpu/drm/i915/intel_hdmi.c    | 12 ++++++++++++
 drivers/gpu/drm/i915/intel_panel.c   |  3 ++-
 5 files changed, 52 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index 36d4e63..040d111 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_420_OUTPUT_INDEX) {
+			name = "YCBCR420-OUTPUT";
+			idx = intel_crtc->base.base.id;
+
+			/* YCBCR420 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 01900e1..c56081e 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -4621,6 +4621,9 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
 	 */
 	need_scaling = src_w != dst_w || src_h != dst_h;
 
+	if (scaler_user == SKL_420_OUTPUT_INDEX)
+		need_scaling = true;
+
 	/*
 	 * if plane is being disabled or scaler is no more required or force detach
 	 *  - free scaler binded to this plane/crtc
@@ -4668,6 +4671,26 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
 }
 
 /**
+ * skl_update_scaler_crtc_420_output - Stages update to scaler state
+ * for YCBCR420 which 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_420_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_420_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
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 592243b..68b4fba 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
+
+	/*
+	 * YCBCR 420 output consume a scaler. So adding a user
+	 * for 420 output requirement.
+	 */
+#define SKL_420_OUTPUT_INDEX 30
 	unsigned scaler_users;
 
 	/* scaler used by crtc for panel fitting purpose */
@@ -1483,6 +1490,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_420_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 276d916..9e8d784 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -1355,6 +1355,7 @@ intel_hdmi_ycbcr420_config(struct drm_connector *connector,
 			       struct intel_crtc_state *config,
 			       int *clock_12bpc, int *clock_8bpc)
 {
+	struct intel_crtc *intel_crtc = to_intel_crtc(config->base.crtc);
 
 	if (!connector->ycbcr_420_allowed) {
 		DRM_ERROR("Platform doesn't support YCBCR420 output\n");
@@ -1366,6 +1367,17 @@ intel_hdmi_ycbcr420_config(struct drm_connector *connector,
 	*clock_12bpc /= 2;
 	*clock_8bpc /= 2;
 	config->ycbcr420 = true;
+
+	/* YCBCR 420 output conversion needs a scaler */
+	if (skl_update_scaler_crtc_420_output(config)) {
+		DRM_ERROR("Scaler allocation for output failed\n");
+		return false;
+	}
+
+	/* Bind this scaler to pipe */
+	intel_pch_panel_fitting(intel_crtc, config,
+				DRM_MODE_SCALE_FULLSCREEN);
+
 	return true;
 }
 
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index 96c2cbd..fd2e081 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->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] 76+ messages in thread

* [PATCH 12/20] drm/i915: prepare pipe for YCBCR420 output
  2017-07-10 11:18 [PATCH 00/20] YCBCR 4:2:0 handling for LSPCON Shashank Sharma
                   ` (10 preceding siblings ...)
  2017-07-10 11:18 ` [PATCH 11/20] drm/i915: prepare scaler for YCBCR420 modeset Shashank Sharma
@ 2017-07-10 11:18 ` Shashank Sharma
  2017-07-10 11:18 ` [PATCH 13/20] drm/i915: prepare csc unit " Shashank Sharma
                   ` (8 subsequent siblings)
  20 siblings, 0 replies; 76+ messages in thread
From: Shashank Sharma @ 2017-07-10 11:18 UTC (permalink / raw)
  To: intel-gfx, dri-devel

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 YCBCR420 outputs.

V2: rebase
V3: rebase
V4: rebase
V5: added r-b from Ander
V6: Handle only YCBCR420 outputs (ville)

Reviewed-by: Ander Conselvan de Oliveira <conselvan2@gmail.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 | 7 +++++++
 2 files changed, 10 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 64cc674..5aea2a9 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -5227,6 +5227,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 c56081e..b4a6415 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -8081,6 +8081,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);
+	struct intel_crtc_state *config = intel_crtc->config;
 
 	if (IS_BROADWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 9) {
 		u32 val = 0;
@@ -8106,6 +8107,12 @@ static void haswell_set_pipemisc(struct drm_crtc *crtc)
 		if (intel_crtc->config->dither)
 			val |= PIPEMISC_DITHER_ENABLE | PIPEMISC_DITHER_TYPE_SP;
 
+		if (config->ycbcr420) {
+			val |= PIPEMISC_OUTPUT_YCBCR |
+				PIPEMISC_YCBCR420_ENABLE |
+				PIPEMISC_YCBCR420_MODE_BLEND;
+		}
+
 		I915_WRITE(PIPEMISC(intel_crtc->pipe), val);
 	}
 }
-- 
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] 76+ messages in thread

* [PATCH 13/20] drm/i915: prepare csc unit for YCBCR420 output
  2017-07-10 11:18 [PATCH 00/20] YCBCR 4:2:0 handling for LSPCON Shashank Sharma
                   ` (11 preceding siblings ...)
  2017-07-10 11:18 ` [PATCH 12/20] drm/i915: prepare pipe for YCBCR420 output Shashank Sharma
@ 2017-07-10 11:18 ` Shashank Sharma
  2017-07-12 17:17   ` Ville Syrjälä
  2017-07-10 11:18 ` [PATCH 14/20] drm/i915: set colorspace for YCBCR420 outputs Shashank Sharma
                   ` (7 subsequent siblings)
  20 siblings, 1 reply; 76+ messages in thread
From: Shashank Sharma @ 2017-07-10 11:18 UTC (permalink / raw)
  To: intel-gfx, dri-devel

To support ycbcr output, we need a pipe CSC block to do
RGB->YCBCR conversion.

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, which uses recommended bspec
values to perform RGB->YCBCR conversion (target color space BT709)

V2: Rebase
V3: Rebase
V4: Rebase
V5: Addressed review comments from Ander
    - Remove extra line added in the patch
    - Add the spec details in the commit message
    - Combine two if(cond) while calling intel_crtc_compute_config
V6: Handle YCBCR420 outputs only (Ville)

Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
---
 drivers/gpu/drm/i915/intel_color.c   | 47 +++++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/i915/intel_display.c | 17 +++++++++++++
 2 files changed, 63 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_color.c b/drivers/gpu/drm/i915/intel_color.c
index 306c6b0..8a5d211 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->ycbcr420) {
+		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 b4a6415..c5ff568 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6288,6 +6288,23 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
 		return -EINVAL;
 	}
 
+	/* YCBCR420 feasibility check */
+	if (pipe_config->ycbcr420) {
+		struct drm_crtc_state *drm_state = &pipe_config->base;
+
+		/*
+		 * There is only one pipe CSC unit per pipe, and we need that
+		 * for output conversion from RGB->YCBCR. So if CTM is already
+		 * applied we can't support YCBCR420 output.
+		 */
+		if (drm_state->ctm) {
+			DRM_ERROR("YCBCR420 and CTM is not possible\n");
+			return -EINVAL;
+		}
+
+		DRM_DEBUG_KMS("YCBCR420 output is possible from CRTC\n");
+	}
+
 	/*
 	 * Pipe horizontal size must be even in:
 	 * - DVO ganged 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] 76+ messages in thread

* [PATCH 14/20] drm/i915: set colorspace for YCBCR420 outputs
  2017-07-10 11:18 [PATCH 00/20] YCBCR 4:2:0 handling for LSPCON Shashank Sharma
                   ` (12 preceding siblings ...)
  2017-07-10 11:18 ` [PATCH 13/20] drm/i915: prepare csc unit " Shashank Sharma
@ 2017-07-10 11:18 ` Shashank Sharma
  2017-07-10 11:18 ` [PATCH 15/20] drm/i915/glk: set HDMI 2.0 identifier Shashank Sharma
                   ` (6 subsequent siblings)
  20 siblings, 0 replies; 76+ messages in thread
From: Shashank Sharma @ 2017-07-10 11:18 UTC (permalink / raw)
  To: intel-gfx, dri-devel

When output colorspace is YCBCR420, we have to load the
corresponding colorspace in AVI infoframe. This patch fills
the colorspace of AVI infoframe as per the output mode.

V2: Rebase
V3: Rebase
V4: Rebase
V5: Added r-b from Ander
V6: Checking RGB/YCBCR420 output only (Ville)

Reviewed-by: Ander Conselvan de Oliveira <conselvan2@gmail.com>
Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
---
 drivers/gpu/drm/i915/intel_hdmi.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 9e8d784..2524ac4 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -461,6 +461,7 @@ static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder,
 		&crtc_state->base.adjusted_mode;
 	struct drm_connector *connector = &intel_hdmi->attached_connector->base;
 	bool is_hdmi2_sink = connector->display_info.hdmi.scdc.supported;
+	enum hdmi_colorspace colorspace = HDMI_COLORSPACE_RGB;
 	union hdmi_infoframe frame;
 	int ret;
 
@@ -472,6 +473,17 @@ static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder,
 		return;
 	}
 
+	if (crtc_state->ycbcr420)
+		colorspace = HDMI_COLORSPACE_YUV420;
+
+	ret = drm_hdmi_avi_infoframe_set_colorspace(&frame.avi,
+						    adjusted_mode,
+						    colorspace);
+	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

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

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

* [PATCH 15/20] drm/i915/glk: set HDMI 2.0 identifier
  2017-07-10 11:18 [PATCH 00/20] YCBCR 4:2:0 handling for LSPCON Shashank Sharma
                   ` (13 preceding siblings ...)
  2017-07-10 11:18 ` [PATCH 14/20] drm/i915: set colorspace for YCBCR420 outputs Shashank Sharma
@ 2017-07-10 11:18 ` Shashank Sharma
  2017-07-10 11:18 ` [PATCH 16/20] drm: add function to read vendor OUI Shashank Sharma
                   ` (5 subsequent siblings)
  20 siblings, 0 replies; 76+ messages in thread
From: Shashank Sharma @ 2017-07-10 11:18 UTC (permalink / raw)
  To: intel-gfx, dri-devel

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
V4: Rebase
V5: Added r-b from Ander
V6: Rebase

Reviewed-by: Ander Conselvan de Oliveira <conselvan2@gmail.com>
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 2524ac4..d1b1efc 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -1922,6 +1922,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

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

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

* [PATCH 16/20] drm: add function to read vendor OUI
  2017-07-10 11:18 [PATCH 00/20] YCBCR 4:2:0 handling for LSPCON Shashank Sharma
                   ` (14 preceding siblings ...)
  2017-07-10 11:18 ` [PATCH 15/20] drm/i915/glk: set HDMI 2.0 identifier Shashank Sharma
@ 2017-07-10 11:18 ` Shashank Sharma
  2017-07-12 17:15   ` Ville Syrjälä
  2017-07-10 11:18 ` [PATCH 17/20] drm/i915: check LSPCON " Shashank Sharma
                   ` (4 subsequent siblings)
  20 siblings, 1 reply; 76+ messages in thread
From: Shashank Sharma @ 2017-07-10 11:18 UTC (permalink / raw)
  To: intel-gfx, dri-devel

This patch adds a helper function in DP dual mode layer to
read the vendor's IEEE OUI signature from a Dual mode adapter.
This will be used to differentiate between different LSPCON
vendors, to address their custom programming requirements.

Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Imre Deak <imre.deak@intel.com>
Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
---
 drivers/gpu/drm/drm_dp_dual_mode_helper.c | 24 ++++++++++++++++++++++++
 include/drm/drm_dp_dual_mode_helper.h     |  4 +++-
 2 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_dp_dual_mode_helper.c b/drivers/gpu/drm/drm_dp_dual_mode_helper.c
index 80e62f6..0b890dc 100644
--- a/drivers/gpu/drm/drm_dp_dual_mode_helper.c
+++ b/drivers/gpu/drm/drm_dp_dual_mode_helper.c
@@ -396,6 +396,30 @@ const char *drm_dp_get_dual_mode_type_name(enum drm_dp_dual_mode_type type)
 EXPORT_SYMBOL(drm_dp_get_dual_mode_type_name);
 
 /**
+ * drm_lspcon_get_vendor_oui: match vendor OUI signature
+ * @adapter: i2c adapter under action
+ * @vendor_id = 3 bytes of vendor OUI signature, LSB=lower byte
+ *
+ * Returns:
+ * Vendor OUI id if got one, 0 if not
+ */
+uint32_t drm_lspcon_get_vendor_oui(struct i2c_adapter *adapter)
+{
+	uint8_t sign[3] = {0, };
+	uint32_t oui = 0;
+
+	if (drm_dp_dual_mode_read(adapter, DP_DUAL_MODE_LSPCON_OUI_OFFSET,
+						sign, 3)) {
+		DRM_ERROR("Can't identify vendor sign\n");
+		return 0;
+	}
+
+	oui = (sign[0] << 16) | (sign[1] << 8) | sign[2];
+	return oui;
+}
+EXPORT_SYMBOL(drm_lspcon_get_vendor_oui);
+
+/**
  * drm_lspcon_get_mode: Get LSPCON's current mode of operation by
  * reading offset (0x80, 0x41)
  * @adapter: I2C-over-aux adapter
diff --git a/include/drm/drm_dp_dual_mode_helper.h b/include/drm/drm_dp_dual_mode_helper.h
index 4c42db8..f81b526 100644
--- a/include/drm/drm_dp_dual_mode_helper.h
+++ b/include/drm/drm_dp_dual_mode_helper.h
@@ -60,7 +60,8 @@
 /* LSPCON specific registers, defined by MCA */
 #define DP_DUAL_MODE_LSPCON_MODE_CHANGE		0x40
 #define DP_DUAL_MODE_LSPCON_CURRENT_MODE		0x41
-#define  DP_DUAL_MODE_LSPCON_MODE_PCON			0x1
+#define DP_DUAL_MODE_LSPCON_MODE_PCON			0x1
+#define DP_DUAL_MODE_LSPCON_OUI_OFFSET			0x11
 
 struct i2c_adapter;
 
@@ -116,4 +117,5 @@ int drm_lspcon_get_mode(struct i2c_adapter *adapter,
 			enum drm_lspcon_mode *current_mode);
 int drm_lspcon_set_mode(struct i2c_adapter *adapter,
 			enum drm_lspcon_mode reqd_mode);
+uint32_t drm_lspcon_get_vendor_oui(struct i2c_adapter *adapter);
 #endif
-- 
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] 76+ messages in thread

* [PATCH 17/20] drm/i915: check LSPCON vendor OUI
  2017-07-10 11:18 [PATCH 00/20] YCBCR 4:2:0 handling for LSPCON Shashank Sharma
                   ` (15 preceding siblings ...)
  2017-07-10 11:18 ` [PATCH 16/20] drm: add function to read vendor OUI Shashank Sharma
@ 2017-07-10 11:18 ` Shashank Sharma
  2017-07-10 11:18 ` [PATCH 18/20] drm/i915: YCBCR 420 support for LSPCON Shashank Sharma
                   ` (3 subsequent siblings)
  20 siblings, 0 replies; 76+ messages in thread
From: Shashank Sharma @ 2017-07-10 11:18 UTC (permalink / raw)
  To: intel-gfx, dri-devel

Intel LSPCON chip is provided by 2 vendors:
- Megachips America (MCA)
- Parade technologies (Parade tech)

Its important to know the vendor of this chip, as the address to
write AVI infoframes is different for those two.

This patch reads the vendor OUI signature, and marks into LSPCON
encoder structure for future usages.

Cc: Imre Deak <imre.deak@intel.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
---
 drivers/gpu/drm/i915/intel_drv.h    |  6 ++++++
 drivers/gpu/drm/i915/intel_lspcon.c | 24 ++++++++++++++++++++++++
 2 files changed, 30 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 68b4fba..ed04de9 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1063,9 +1063,15 @@ struct intel_dp {
 	struct intel_dp_compliance compliance;
 };
 
+enum lspcon_vendor {
+	LSPCON_VENDOR_MCA,
+	LSPCON_VENDOR_PARADE
+};
+
 struct intel_lspcon {
 	bool active;
 	enum drm_lspcon_mode mode;
+	enum lspcon_vendor vendor;
 };
 
 struct intel_digital_port {
diff --git a/drivers/gpu/drm/i915/intel_lspcon.c b/drivers/gpu/drm/i915/intel_lspcon.c
index 5abef482..a350d79 100644
--- a/drivers/gpu/drm/i915/intel_lspcon.c
+++ b/drivers/gpu/drm/i915/intel_lspcon.c
@@ -27,6 +27,10 @@
 #include <drm/drm_dp_dual_mode_helper.h>
 #include "intel_drv.h"
 
+/* LSPCON OUI Vendor ID(signatures) */
+#define LSPCON_VENDOR_PARADE_OUI 0x001CF8
+#define LSPCON_VENDOR_MCA_OUI 0x0060AD
+
 static struct intel_dp *lspcon_to_intel_dp(struct intel_lspcon *lspcon)
 {
 	struct intel_digital_port *dig_port =
@@ -136,6 +140,7 @@ static bool lspcon_probe(struct intel_lspcon *lspcon)
 	enum drm_dp_dual_mode_type adaptor_type;
 	struct i2c_adapter *adapter = &lspcon_to_intel_dp(lspcon)->aux.ddc;
 	enum drm_lspcon_mode expected_mode;
+	uint32_t vendor_oui;
 
 	expected_mode = lspcon_wake_native_aux_ch(lspcon) ?
 			DRM_LSPCON_MODE_PCON : DRM_LSPCON_MODE_LS;
@@ -151,6 +156,25 @@ static bool lspcon_probe(struct intel_lspcon *lspcon)
 	/* Yay ... got a LSPCON device */
 	DRM_DEBUG_KMS("LSPCON detected\n");
 	lspcon->mode = lspcon_wait_mode(lspcon, expected_mode);
+
+	/* Check if this is a Parade LSPCON or MCA LSPCON */
+	vendor_oui = drm_lspcon_get_vendor_oui(adapter);
+	switch (vendor_oui) {
+	case LSPCON_VENDOR_MCA_OUI:
+		lspcon->vendor = LSPCON_VENDOR_MCA;
+		DRM_DEBUG_KMS("Vendor: Mega Chips\n");
+		break;
+
+	case LSPCON_VENDOR_PARADE_OUI:
+		lspcon->vendor = LSPCON_VENDOR_PARADE;
+		DRM_DEBUG_KMS("Vendor: Parade Tech\n");
+		break;
+
+	default:
+		DRM_ERROR("Can't read OUI /Invalid OUI\n");
+		return false;
+	}
+
 	lspcon->active = true;
 	return true;
 }
-- 
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] 76+ messages in thread

* [PATCH 18/20] drm/i915: YCBCR 420 support for LSPCON
  2017-07-10 11:18 [PATCH 00/20] YCBCR 4:2:0 handling for LSPCON Shashank Sharma
                   ` (16 preceding siblings ...)
  2017-07-10 11:18 ` [PATCH 17/20] drm/i915: check LSPCON " Shashank Sharma
@ 2017-07-10 11:18 ` Shashank Sharma
  2017-07-12 17:15   ` Ville Syrjälä
  2017-07-10 11:18 ` [PATCH 19/20] drm/i915: Move AVI infoframe function to DDI layer Shashank Sharma
                   ` (2 subsequent siblings)
  20 siblings, 1 reply; 76+ messages in thread
From: Shashank Sharma @ 2017-07-10 11:18 UTC (permalink / raw)
  To: intel-gfx, dri-devel

LSPCON chips support YCBCR420 outputs. To be able to get
YCBCR420 output from LSPCON chip, the source should:
- Generate YCBCR444 HDMI output
- Set AVI infoframes for a YCBCR420 output.

LSPCON FW gets the information from AVI infoframes, and generates
YCBCR420 output from a YCBCR444 input. This patch adds the necessary
changes to drive YCBCR420 output from LSPCON based HDMI output.

Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Imre Deak <imre.deak@intel.com>
Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 10 +++++++---
 drivers/gpu/drm/i915/intel_dp.c      | 16 +++++++++++++++-
 drivers/gpu/drm/i915/intel_drv.h     | 20 +++++++++++++++++---
 drivers/gpu/drm/i915/intel_hdmi.c    |  7 +++++--
 drivers/gpu/drm/i915/intel_lspcon.c  | 17 +++++++++++++++++
 5 files changed, 61 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index c5ff568..c3c7b31 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -8125,9 +8125,11 @@ static void haswell_set_pipemisc(struct drm_crtc *crtc)
 			val |= PIPEMISC_DITHER_ENABLE | PIPEMISC_DITHER_TYPE_SP;
 
 		if (config->ycbcr420) {
-			val |= PIPEMISC_OUTPUT_YCBCR |
-				PIPEMISC_YCBCR420_ENABLE |
-				PIPEMISC_YCBCR420_MODE_BLEND;
+			val |= PIPEMISC_OUTPUT_YCBCR;
+
+			if (!config->lspcon_active)
+				val |= PIPEMISC_YCBCR420_ENABLE |
+					PIPEMISC_YCBCR420_MODE_BLEND;
 		}
 
 		I915_WRITE(PIPEMISC(intel_crtc->pipe), val);
@@ -14205,11 +14207,13 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)
 		 * DDI_BUF_CTL_A or SFUSE_STRAP registers, find another way to
 		 * detect the ports.
 		 */
+
 		intel_ddi_init(dev_priv, PORT_A);
 		intel_ddi_init(dev_priv, PORT_B);
 		intel_ddi_init(dev_priv, PORT_C);
 
 		intel_dsi_init(dev_priv);
+
 	} else if (HAS_DDI(dev_priv)) {
 		int found;
 
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 67bc8a7a..1690aa9 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1614,7 +1614,9 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 	struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
 	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
-	enum port port = dp_to_dig_port(intel_dp)->port;
+	struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base);
+	enum port port = dig_port->port;
+	struct intel_lspcon *lspcon = &dig_port->lspcon;
 	struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->base.crtc);
 	struct intel_connector *intel_connector = intel_dp->attached_connector;
 	struct intel_digital_connector_state *intel_conn_state =
@@ -1635,6 +1637,18 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 	common_len = intel_dp_common_len_rate_limit(intel_dp,
 						    intel_dp->max_link_rate);
 
+	/* LSPCON needs special handling to drive YCBCR420 outputs */
+	if (lspcon->active) {
+		struct drm_connector *connector = &intel_connector->base;
+		int clock_8bpc = pipe_config->base.adjusted_mode.crtc_clock;
+		int clock_12bpc = clock_8bpc * 3 / 2;
+
+		pipe_config->lspcon_active = true;
+		pipe_config->ycbcr420 = lspcon_ycbcr420_config(connector,
+					     pipe_config, &clock_12bpc,
+					     &clock_8bpc);
+	}
+
 	/* No common link rates between source and sink */
 	WARN_ON(common_len <= 0);
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index ed04de9..40d56f2 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -790,6 +790,9 @@ struct intel_crtc_state {
 
 	/* HDMI output type */
 	bool ycbcr420;
+
+	/* LSPCON is active on port */
+	bool lspcon_active;
 };
 
 struct intel_crtc {
@@ -1205,6 +1208,12 @@ static inline struct intel_dp *enc_to_intel_dp(struct drm_encoder *encoder)
 	return &enc_to_dig_port(encoder)->dp;
 }
 
+static inline struct intel_lspcon *
+enc_to_intel_lspcon(struct drm_encoder *encoder)
+{
+	return &enc_to_dig_port(encoder)->lspcon;
+}
+
 static inline struct intel_digital_port *
 dp_to_dig_port(struct intel_dp *intel_dp)
 {
@@ -1675,14 +1684,16 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
 			       struct intel_connector *intel_connector);
 struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder);
 bool intel_hdmi_compute_config(struct intel_encoder *encoder,
-			       struct intel_crtc_state *pipe_config,
-			       struct drm_connector_state *conn_state);
+				struct intel_crtc_state *pipe_config,
+				struct drm_connector_state *conn_state);
 void intel_hdmi_handle_sink_scrambling(struct intel_encoder *intel_encoder,
 				       struct drm_connector *connector,
 				       bool high_tmds_clock_ratio,
 				       bool scrambling);
 void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable);
-
+bool intel_hdmi_ycbcr420_config(struct drm_connector *connector,
+				struct intel_crtc_state *config,
+				int *clock_12bpc, int *clock_8bpc);
 
 /* intel_lvds.c */
 void intel_lvds_init(struct drm_i915_private *dev_priv);
@@ -2003,6 +2014,9 @@ void intel_color_load_luts(struct drm_crtc_state *crtc_state);
 bool lspcon_init(struct intel_digital_port *intel_dig_port);
 void lspcon_resume(struct intel_lspcon *lspcon);
 void lspcon_wait_pcon_mode(struct intel_lspcon *lspcon);
+bool lspcon_ycbcr420_config(struct drm_connector *connector,
+			    struct intel_crtc_state *config,
+			    int *clock_12bpc, int *clock_8bpc);
 
 /* intel_pipe_crc.c */
 int intel_pipe_crc_create(struct drm_minor *minor);
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index d1b1efc..a08ab99 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -1362,8 +1362,7 @@ static bool hdmi_12bpc_possible(struct intel_crtc_state *crtc_state,
 	return true;
 }
 
-static bool
-intel_hdmi_ycbcr420_config(struct drm_connector *connector,
+bool intel_hdmi_ycbcr420_config(struct drm_connector *connector,
 			       struct intel_crtc_state *config,
 			       int *clock_12bpc, int *clock_8bpc)
 {
@@ -1380,6 +1379,10 @@ intel_hdmi_ycbcr420_config(struct drm_connector *connector,
 	*clock_8bpc /= 2;
 	config->ycbcr420 = true;
 
+	/* LSPCON doesn't need scaler for YCBCR420 output */
+	if (config->lspcon_active)
+		return true;
+
 	/* YCBCR 420 output conversion needs a scaler */
 	if (skl_update_scaler_crtc_420_output(config)) {
 		DRM_ERROR("Scaler allocation for output failed\n");
diff --git a/drivers/gpu/drm/i915/intel_lspcon.c b/drivers/gpu/drm/i915/intel_lspcon.c
index a350d79..f611b6d 100644
--- a/drivers/gpu/drm/i915/intel_lspcon.c
+++ b/drivers/gpu/drm/i915/intel_lspcon.c
@@ -202,6 +202,21 @@ static void lspcon_resume_in_pcon_wa(struct intel_lspcon *lspcon)
 	DRM_DEBUG_KMS("LSPCON DP descriptor mismatch after resume\n");
 }
 
+bool lspcon_ycbcr420_config(struct drm_connector *connector,
+			    struct intel_crtc_state *config,
+			    int *clock_12bpc, int *clock_8bpc)
+{
+	struct drm_display_info *info = &connector->display_info;
+	struct drm_display_mode *mode = &config->base.adjusted_mode;
+
+	if (drm_mode_is_420_only(info, mode)) {
+		return intel_hdmi_ycbcr420_config(connector, config,
+					  clock_12bpc, clock_8bpc);
+	}
+
+	return false;
+}
+
 void lspcon_resume(struct intel_lspcon *lspcon)
 {
 	enum drm_lspcon_mode expected_mode;
@@ -233,6 +248,7 @@ bool lspcon_init(struct intel_digital_port *intel_dig_port)
 	struct intel_lspcon *lspcon = &intel_dig_port->lspcon;
 	struct drm_device *dev = intel_dig_port->base.base.dev;
 	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_connector *connector = &dp->attached_connector->base;
 
 	if (!IS_GEN9(dev_priv)) {
 		DRM_ERROR("LSPCON is supported on GEN9 only\n");
@@ -264,6 +280,7 @@ bool lspcon_init(struct intel_digital_port *intel_dig_port)
 		return false;
 	}
 
+	connector->ycbcr_420_allowed = true;
 	drm_dp_read_desc(&dp->aux, &dp->desc, drm_dp_is_branch(dp->dpcd));
 
 	DRM_DEBUG_KMS("Success: LSPCON init\n");
-- 
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] 76+ messages in thread

* [PATCH 19/20] drm/i915: Move AVI infoframe function to DDI layer
  2017-07-10 11:18 [PATCH 00/20] YCBCR 4:2:0 handling for LSPCON Shashank Sharma
                   ` (17 preceding siblings ...)
  2017-07-10 11:18 ` [PATCH 18/20] drm/i915: YCBCR 420 support for LSPCON Shashank Sharma
@ 2017-07-10 11:18 ` Shashank Sharma
  2017-07-12 17:15   ` Ville Syrjälä
  2017-07-10 11:18 ` [PATCH 20/20] drm/i915: write AVI infoframes for LSPCON Shashank Sharma
  2017-07-10 11:38 ` ✓ Fi.CI.BAT: success for YCBCR 4:2:0 handling " Patchwork
  20 siblings, 1 reply; 76+ messages in thread
From: Shashank Sharma @ 2017-07-10 11:18 UTC (permalink / raw)
  To: intel-gfx, dri-devel

We have an existing function to prepare AVI infoframes for HDMI,
this patch moves that function from HDMI layer, to DDI layer, so
that we can reuse the function for DP(LSPCON) displays too.

This patch:
- Moves the intel_hdmi_set_avi_infoframes function in ddi layer.
- Adds code to accommodate LSPCON in the same function.
- Links this function as AVI infoframe setup function for LSPCON.

Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Imre Deak <imre.deak@intel.com>
Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
---
 drivers/gpu/drm/i915/intel_ddi.c    | 89 ++++++++++++++++++++++++++++++++++---
 drivers/gpu/drm/i915/intel_drv.h    |  9 ++++
 drivers/gpu/drm/i915/intel_hdmi.c   | 52 +++-------------------
 drivers/gpu/drm/i915/intel_lspcon.c |  1 +
 4 files changed, 99 insertions(+), 52 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 80e96f1..f691710 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -2003,8 +2003,76 @@ static void intel_ddi_clk_select(struct intel_encoder *encoder,
 	}
 }
 
+void intel_ddi_set_avi_infoframe(struct drm_encoder *encoder,
+				  const struct intel_crtc_state *crtc_state)
+{
+	int ret;
+	union hdmi_infoframe frame;
+	struct drm_connector *connector;
+	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+	const struct drm_display_mode *adjusted_mode =
+					&crtc_state->base.adjusted_mode;
+	enum intel_output_type type = to_intel_encoder(encoder)->type;
+	bool is_hdmi2_sink = false;
+	bool rgb_qrange_selectable = false;
+	enum hdmi_colorspace colorspace = crtc_state->ycbcr420 ?
+					  HDMI_COLORSPACE_YUV420 :
+					  HDMI_COLORSPACE_RGB;
+	bool rgb_qrange_limited =  crtc_state->limited_color_range ?
+					HDMI_QUANTIZATION_RANGE_LIMITED :
+					HDMI_QUANTIZATION_RANGE_FULL;
+
+	switch (type) {
+	case INTEL_OUTPUT_HDMI:
+		connector = &intel_hdmi->attached_connector->base;
+		is_hdmi2_sink = connector->display_info.hdmi.scdc.supported;
+		rgb_qrange_selectable = intel_hdmi->rgb_quant_range_selectable;
+		break;
+
+	case INTEL_OUTPUT_DP:
+		/* We are here means its a LSPCON device, still be paranoid */
+		if (!crtc_state->lspcon_active) {
+			DRM_ERROR("No LSPCON, why am I here ?\n");
+			return;
+		}
+
+		connector = &intel_dp->attached_connector->base;
+		is_hdmi2_sink = connector->display_info.hdmi.scdc.supported;
+		if (crtc_state->ycbcr420)
+			rgb_qrange_limited = true;
+		break;
+
+	default:
+		DRM_ERROR("No other encoder allowed\n");
+		return;
+	}
+
+	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
+						       adjusted_mode,
+						       is_hdmi2_sink);
+	if (ret < 0) {
+		DRM_ERROR("couldn't fill AVI infoframe\n");
+		return;
+	}
+
+	ret = drm_hdmi_avi_infoframe_set_colorspace(&frame.avi,
+						    adjusted_mode,
+						    colorspace);
+	if (ret < 0) {
+		DRM_ERROR("couldn't fill AVI colorspace\n");
+		return;
+	}
+
+	drm_hdmi_avi_infoframe_quant_range(&frame.avi, adjusted_mode,
+					   rgb_qrange_limited,
+					   rgb_qrange_selectable);
+
+	intel_write_infoframe(encoder, crtc_state, &frame);
+}
+
 static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder,
-				    int link_rate, uint32_t lane_count,
+				    const struct intel_crtc_state *pipe_config,
 				    struct intel_shared_dpll *pll,
 				    bool link_mst)
 {
@@ -2012,6 +2080,8 @@ static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder,
 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 	enum port port = intel_ddi_get_encoder_port(encoder);
 	struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base);
+	int link_rate = pipe_config->port_clock;
+	uint32_t lane_count = pipe_config->lane_count;
 
 	WARN_ON(link_mst && (port == PORT_A || port == PORT_E));
 
@@ -2030,6 +2100,14 @@ static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder,
 	intel_dp_start_link_train(intel_dp);
 	if (port != PORT_A || INTEL_GEN(dev_priv) >= 9)
 		intel_dp_stop_link_train(intel_dp);
+
+	if (pipe_config->lspcon_active) {
+		struct drm_encoder *drm_encoder = &encoder->base;
+		struct intel_lspcon *lspcon = enc_to_intel_lspcon(drm_encoder);
+
+		if (lspcon->set_infoframes)
+			lspcon->set_infoframes(&encoder->base, pipe_config);
+	}
 }
 
 static void intel_ddi_pre_enable_hdmi(struct intel_encoder *encoder,
@@ -2072,8 +2150,7 @@ static void intel_ddi_pre_enable(struct intel_encoder *encoder,
 
 	if (type == INTEL_OUTPUT_DP || type == INTEL_OUTPUT_EDP) {
 		intel_ddi_pre_enable_dp(encoder,
-					pipe_config->port_clock,
-					pipe_config->lane_count,
+					pipe_config,
 					pipe_config->shared_dpll,
 					intel_crtc_has_type(pipe_config,
 							    INTEL_OUTPUT_DP_MST));
@@ -2628,17 +2705,17 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
 	}
 
 	if (init_lspcon) {
-		if (lspcon_init(intel_dig_port))
-			/* TODO: handle hdmi info frame part */
+		if (lspcon_init(intel_dig_port)) {
 			DRM_DEBUG_KMS("LSPCON init success on port %c\n",
 				port_name(port));
-		else
+		} else {
 			/*
 			 * LSPCON init faied, but DP init was success, so
 			 * lets try to drive as DP++ port.
 			 */
 			DRM_ERROR("LSPCON init failed on port %c\n",
 				port_name(port));
+		}
 	}
 
 	return;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 40d56f2..fad9a53 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1075,6 +1075,10 @@ struct intel_lspcon {
 	bool active;
 	enum drm_lspcon_mode mode;
 	enum lspcon_vendor vendor;
+
+	/* AVI IF setup function for LSPCON */
+	void (*set_infoframes)(struct drm_encoder *encoder,
+				const struct intel_crtc_state *crtc_state);
 };
 
 struct intel_digital_port {
@@ -1320,6 +1324,8 @@ u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder);
 
 unsigned int intel_fb_align_height(const struct drm_framebuffer *fb,
 				   int plane, unsigned int height);
+void intel_ddi_set_avi_infoframe(struct drm_encoder *encoder,
+				 const struct intel_crtc_state *crtc_state);
 
 /* intel_audio.c */
 void intel_init_audio_hooks(struct drm_i915_private *dev_priv);
@@ -1690,6 +1696,9 @@ void intel_hdmi_handle_sink_scrambling(struct intel_encoder *intel_encoder,
 				       struct drm_connector *connector,
 				       bool high_tmds_clock_ratio,
 				       bool scrambling);
+void intel_write_infoframe(struct drm_encoder *encoder,
+			    const struct intel_crtc_state *crtc_state,
+			    union hdmi_infoframe *frame);
 void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable);
 bool intel_hdmi_ycbcr420_config(struct drm_connector *connector,
 				struct intel_crtc_state *config,
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index a08ab99..7cab86a 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -430,7 +430,7 @@ static bool hsw_infoframe_enabled(struct drm_encoder *encoder,
  * trick them by giving an offset into the buffer and moving back the header
  * bytes by one.
  */
-static void intel_write_infoframe(struct drm_encoder *encoder,
+void intel_write_infoframe(struct drm_encoder *encoder,
 				  const struct intel_crtc_state *crtc_state,
 				  union hdmi_infoframe *frame)
 {
@@ -453,46 +453,6 @@ static void intel_write_infoframe(struct drm_encoder *encoder,
 	intel_hdmi->write_infoframe(encoder, crtc_state, frame->any.type, buffer, len);
 }
 
-static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder,
-					 const struct intel_crtc_state *crtc_state)
-{
-	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;
-	enum hdmi_colorspace colorspace = HDMI_COLORSPACE_RGB;
-	union hdmi_infoframe frame;
-	int ret;
-
-	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
-						       adjusted_mode,
-						       is_hdmi2_sink);
-	if (ret < 0) {
-		DRM_ERROR("couldn't fill AVI infoframe\n");
-		return;
-	}
-
-	if (crtc_state->ycbcr420)
-		colorspace = HDMI_COLORSPACE_YUV420;
-
-	ret = drm_hdmi_avi_infoframe_set_colorspace(&frame.avi,
-						    adjusted_mode,
-						    colorspace);
-	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 :
-					   HDMI_QUANTIZATION_RANGE_FULL,
-					   intel_hdmi->rgb_quant_range_selectable);
-
-	intel_write_infoframe(encoder, crtc_state, &frame);
-}
-
 static void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder,
 					 const struct intel_crtc_state *crtc_state)
 {
@@ -582,7 +542,7 @@ static void g4x_set_infoframes(struct drm_encoder *encoder,
 	I915_WRITE(reg, val);
 	POSTING_READ(reg);
 
-	intel_hdmi_set_avi_infoframe(encoder, crtc_state);
+	intel_ddi_set_avi_infoframe(encoder, crtc_state);
 	intel_hdmi_set_spd_infoframe(encoder, crtc_state);
 	intel_hdmi_set_hdmi_infoframe(encoder, crtc_state);
 }
@@ -723,7 +683,7 @@ static void ibx_set_infoframes(struct drm_encoder *encoder,
 	I915_WRITE(reg, val);
 	POSTING_READ(reg);
 
-	intel_hdmi_set_avi_infoframe(encoder, crtc_state);
+	intel_ddi_set_avi_infoframe(encoder, crtc_state);
 	intel_hdmi_set_spd_infoframe(encoder, crtc_state);
 	intel_hdmi_set_hdmi_infoframe(encoder, crtc_state);
 }
@@ -766,7 +726,7 @@ static void cpt_set_infoframes(struct drm_encoder *encoder,
 	I915_WRITE(reg, val);
 	POSTING_READ(reg);
 
-	intel_hdmi_set_avi_infoframe(encoder, crtc_state);
+	intel_ddi_set_avi_infoframe(encoder, crtc_state);
 	intel_hdmi_set_spd_infoframe(encoder, crtc_state);
 	intel_hdmi_set_hdmi_infoframe(encoder, crtc_state);
 }
@@ -819,7 +779,7 @@ static void vlv_set_infoframes(struct drm_encoder *encoder,
 	I915_WRITE(reg, val);
 	POSTING_READ(reg);
 
-	intel_hdmi_set_avi_infoframe(encoder, crtc_state);
+	intel_ddi_set_avi_infoframe(encoder, crtc_state);
 	intel_hdmi_set_spd_infoframe(encoder, crtc_state);
 	intel_hdmi_set_hdmi_infoframe(encoder, crtc_state);
 }
@@ -852,7 +812,7 @@ static void hsw_set_infoframes(struct drm_encoder *encoder,
 	I915_WRITE(reg, val);
 	POSTING_READ(reg);
 
-	intel_hdmi_set_avi_infoframe(encoder, crtc_state);
+	intel_ddi_set_avi_infoframe(encoder, crtc_state);
 	intel_hdmi_set_spd_infoframe(encoder, crtc_state);
 	intel_hdmi_set_hdmi_infoframe(encoder, crtc_state);
 }
diff --git a/drivers/gpu/drm/i915/intel_lspcon.c b/drivers/gpu/drm/i915/intel_lspcon.c
index f611b6d..53ddd39 100644
--- a/drivers/gpu/drm/i915/intel_lspcon.c
+++ b/drivers/gpu/drm/i915/intel_lspcon.c
@@ -281,6 +281,7 @@ bool lspcon_init(struct intel_digital_port *intel_dig_port)
 	}
 
 	connector->ycbcr_420_allowed = true;
+	lspcon->set_infoframes = intel_ddi_set_avi_infoframe;
 	drm_dp_read_desc(&dp->aux, &dp->desc, drm_dp_is_branch(dp->dpcd));
 
 	DRM_DEBUG_KMS("Success: LSPCON init\n");
-- 
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] 76+ messages in thread

* [PATCH 20/20] drm/i915: write AVI infoframes for LSPCON
  2017-07-10 11:18 [PATCH 00/20] YCBCR 4:2:0 handling for LSPCON Shashank Sharma
                   ` (18 preceding siblings ...)
  2017-07-10 11:18 ` [PATCH 19/20] drm/i915: Move AVI infoframe function to DDI layer Shashank Sharma
@ 2017-07-10 11:18 ` Shashank Sharma
  2017-07-12 17:24   ` Ville Syrjälä
  2017-07-10 11:38 ` ✓ Fi.CI.BAT: success for YCBCR 4:2:0 handling " Patchwork
  20 siblings, 1 reply; 76+ messages in thread
From: Shashank Sharma @ 2017-07-10 11:18 UTC (permalink / raw)
  To: intel-gfx, dri-devel

LSPCON chips can't pick the HDMI AVI infoframes from direct link.
In order to pass AVI infoframes from display controller to LSPCON,
we have to write infoframe packets into vendor specified AUX address.

Also, LSPCON vendors provide AUX offsets, to inform the LSPCON
chip that the AVI IF packets are written, so that the firmware
can pick it up and apply.

This patch adds function to write AVI infoframes for both MCA as
well as Parade Tech LSPCON chips. These two vendors provide different
methods for writing infoframes, so this patch contains two different
functions, one for each.

Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Imre Deak <imre.deak@intel.com>
Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
---
 drivers/gpu/drm/i915/intel_ddi.c    |   8 ++
 drivers/gpu/drm/i915/intel_drv.h    |   3 +
 drivers/gpu/drm/i915/intel_lspcon.c | 174 ++++++++++++++++++++++++++++++++++++
 3 files changed, 185 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index f691710..944d9d5 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -2068,6 +2068,14 @@ void intel_ddi_set_avi_infoframe(struct drm_encoder *encoder,
 					   rgb_qrange_limited,
 					   rgb_qrange_selectable);
 
+	if (crtc_state->lspcon_active) {
+		struct intel_lspcon *lspcon = enc_to_intel_lspcon(encoder);
+
+		/* LSPCON writes infoframes via AUX */
+		lspcon->write_infoframe(encoder, crtc_state, &frame);
+		return;
+	}
+
 	intel_write_infoframe(encoder, crtc_state, &frame);
 }
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index fad9a53..3e686d2 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1079,6 +1079,9 @@ struct intel_lspcon {
 	/* AVI IF setup function for LSPCON */
 	void (*set_infoframes)(struct drm_encoder *encoder,
 				const struct intel_crtc_state *crtc_state);
+	void (*write_infoframe)(struct drm_encoder *encoder,
+				const struct intel_crtc_state *crtc_state,
+				union hdmi_infoframe *frame);
 };
 
 struct intel_digital_port {
diff --git a/drivers/gpu/drm/i915/intel_lspcon.c b/drivers/gpu/drm/i915/intel_lspcon.c
index 53ddd39..01fddf7 100644
--- a/drivers/gpu/drm/i915/intel_lspcon.c
+++ b/drivers/gpu/drm/i915/intel_lspcon.c
@@ -31,6 +31,18 @@
 #define LSPCON_VENDOR_PARADE_OUI 0x001CF8
 #define LSPCON_VENDOR_MCA_OUI 0x0060AD
 
+/* AUX addresses to write AVI IF into */
+#define LSPCON_MCA_AVI_IF_WRITE_OFFSET 0x5C0
+#define LSPCON_MCA_AVI_IF_CTRL 0x5DF
+#define  LSPCON_MCA_AVI_IF_KICKOFF (1 << 0)
+#define  LSPCON_MCA_AVI_IF_HANDLED (1 << 1)
+
+#define LSPCON_PARADE_AVI_IF_WRITE_OFFSET 0x516
+#define LSPCON_PARADE_AVI_IF_CTRL 0x51E
+#define  LSPCON_PARADE_AVI_IF_KICKOFF (1 << 7)
+#define LSPCON_PARADE_AVI_IF_STATUS 0x51F
+#define  LSPCON_PARADE_AVI_IF_HANDLED (2 << 6)
+
 static struct intel_dp *lspcon_to_intel_dp(struct intel_lspcon *lspcon)
 {
 	struct intel_digital_port *dig_port =
@@ -217,6 +229,167 @@ bool lspcon_ycbcr420_config(struct drm_connector *connector,
 	return false;
 }
 
+static bool _lspcon_write_infoframe_parade(struct drm_dp_aux *aux,
+					   uint8_t *buffer, ssize_t len)
+{
+	u8 avi_if_ctrl;
+	u8 avi_if_status;
+	u8 count = 0;
+	u8 retry = 5;
+	u8 avi_buf[8] = {0, };
+	uint16_t reg;
+	ssize_t ret;
+
+	while (count++ < 4) {
+
+		do {
+			/* Is LSPCON FW ready */
+			reg = LSPCON_PARADE_AVI_IF_CTRL;
+			ret = drm_dp_dpcd_read(aux, reg, &avi_if_ctrl, 1);
+			if (ret < 0) {
+				DRM_ERROR("DPCD read failed, add:0x%x\n", reg);
+				return false;
+			}
+
+			if (avi_if_ctrl & LSPCON_PARADE_AVI_IF_KICKOFF)
+				break;
+			usleep_range(100, 200);
+		} while (--retry);
+
+		if (!(avi_if_ctrl & LSPCON_PARADE_AVI_IF_KICKOFF)) {
+			DRM_ERROR("LSPCON FW not ready for infoframes\n");
+			return false;
+		}
+
+		/*
+		 * AVI Infoframe contains 31 bytes of data:
+		 *	HB0 to HB2   (3 bytes header)
+		 *	PB0 to PB27 (28 bytes data)
+		 * As per Parade spec, while sending first block (8bytes),
+		 * byte 0 is kept for request token no, and byte1 - byte7
+		 * contain frame data. So we have to pack frame like this:
+		 *	first block of 8 bytes: <token> <HB0-HB2> <PB0-PB3>
+		 *	next 3 blocks: <PB4-PB27>
+		 */
+		if (count)
+			memcpy(avi_buf, buffer + count * 8 - 1, 8);
+		else {
+			avi_buf[0] = 1;
+			memcpy(&avi_buf[1], buffer, 7);
+		}
+
+		/* Write 8 bytes of data at a time */
+		reg = LSPCON_PARADE_AVI_IF_WRITE_OFFSET;
+		ret = drm_dp_dpcd_write(aux, reg, avi_buf, 8);
+		if (ret < 0) {
+			DRM_ERROR("DPCD write failed, add:0x%x\n", reg);
+			return false;
+		}
+
+		/*
+		 * While sending a block of 8 byes, we need to inform block
+		 * number to FW, by programming bits[1:0] of ctrl reg with
+		 * block number
+		 */
+		avi_if_ctrl = 0x80 + count;
+		reg = LSPCON_PARADE_AVI_IF_CTRL;
+		ret = drm_dp_dpcd_write(aux, reg, &avi_if_ctrl, 1);
+		if (ret < 0) {
+			DRM_ERROR("DPCD write failed, add:0x%x\n", reg);
+			return false;
+		}
+	}
+
+	/* Check LSPCON FW status */
+	reg = LSPCON_PARADE_AVI_IF_STATUS;
+	ret = drm_dp_dpcd_read(aux, reg, &avi_if_status, 1);
+	if (ret < 0) {
+		DRM_ERROR("DPCD write failed, address 0x%x\n", reg);
+		return false;
+	}
+
+	if (avi_if_status & LSPCON_PARADE_AVI_IF_HANDLED)
+		DRM_DEBUG_KMS("AVI IF handled by FW\n");
+
+	return true;
+}
+
+static bool _lspcon_write_infoframe_mca(struct drm_dp_aux *aux,
+					uint8_t *buffer, ssize_t len)
+{
+	int ret;
+	uint32_t val = 0;
+	uint16_t reg;
+	uint8_t *data = buffer;
+
+	reg = LSPCON_MCA_AVI_IF_WRITE_OFFSET;
+	while (val < len) {
+		ret = drm_dp_dpcd_write(aux, reg, data, 1);
+		if (ret < 0) {
+			DRM_ERROR("DPCD write failed, add:0x%x\n", reg);
+			return false;
+		}
+		val++; reg++; data++;
+	}
+
+	val = 0;
+	reg = LSPCON_MCA_AVI_IF_CTRL;
+	ret = drm_dp_dpcd_read(aux, reg, &val, 1);
+	if (ret < 0) {
+		DRM_ERROR("DPCD read failed, address 0x%x\n", reg);
+		return false;
+	}
+
+	/* Indicate LSPCON chip about infoframe, clear bit 1 and set bit 0 */
+	val &= ~LSPCON_MCA_AVI_IF_HANDLED;
+	val |= LSPCON_MCA_AVI_IF_KICKOFF;
+
+	ret = drm_dp_dpcd_write(aux, reg, &val, 1);
+	if (ret < 0) {
+		DRM_ERROR("DPCD read failed, address 0x%x\n", reg);
+		return false;
+	}
+
+	val = 0;
+	ret = drm_dp_dpcd_read(aux, reg, &val, 1);
+	if (ret < 0) {
+		DRM_ERROR("DPCD read failed, address 0x%x\n", reg);
+		return false;
+	}
+
+	if (val == LSPCON_MCA_AVI_IF_HANDLED)
+		DRM_DEBUG_KMS("AVI IF handled by FW\n");
+
+	return true;
+}
+
+void lspcon_write_infoframe(struct drm_encoder *encoder,
+				  const struct intel_crtc_state *crtc_state,
+				  union hdmi_infoframe *frame)
+{
+	bool ret;
+	ssize_t len;
+	uint8_t buf[VIDEO_DIP_DATA_SIZE];
+	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+	struct intel_lspcon *lspcon = enc_to_intel_lspcon(encoder);
+
+	len = hdmi_infoframe_pack(frame, buf, sizeof(buf));
+	if (len < 0) {
+		DRM_ERROR("Failed to pack AVI IF\n");
+		return;
+	}
+
+	if (lspcon->vendor == LSPCON_VENDOR_MCA)
+		ret = _lspcon_write_infoframe_mca(&intel_dp->aux, buf, len);
+	else
+		ret = _lspcon_write_infoframe_parade(&intel_dp->aux, buf, len);
+
+	if (!ret)
+		DRM_ERROR("Failed to write AVI infoframes\n");
+	else
+		DRM_DEBUG_DRIVER("AVI infoframes updated successfully\n");
+}
+
 void lspcon_resume(struct intel_lspcon *lspcon)
 {
 	enum drm_lspcon_mode expected_mode;
@@ -282,6 +455,7 @@ bool lspcon_init(struct intel_digital_port *intel_dig_port)
 
 	connector->ycbcr_420_allowed = true;
 	lspcon->set_infoframes = intel_ddi_set_avi_infoframe;
+	lspcon->write_infoframe = lspcon_write_infoframe;
 	drm_dp_read_desc(&dp->aux, &dp->desc, drm_dp_is_branch(dp->dpcd));
 
 	DRM_DEBUG_KMS("Success: LSPCON init\n");
-- 
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] 76+ messages in thread

* ✓ Fi.CI.BAT: success for YCBCR 4:2:0 handling for LSPCON
  2017-07-10 11:18 [PATCH 00/20] YCBCR 4:2:0 handling for LSPCON Shashank Sharma
                   ` (19 preceding siblings ...)
  2017-07-10 11:18 ` [PATCH 20/20] drm/i915: write AVI infoframes for LSPCON Shashank Sharma
@ 2017-07-10 11:38 ` Patchwork
  20 siblings, 0 replies; 76+ messages in thread
From: Patchwork @ 2017-07-10 11:38 UTC (permalink / raw)
  To: Shashank Sharma; +Cc: intel-gfx

== Series Details ==

Series: YCBCR 4:2:0 handling for LSPCON
URL   : https://patchwork.freedesktop.org/series/27061/
State : success

== Summary ==

Series 27061v1 YCBCR 4:2:0 handling for LSPCON
https://patchwork.freedesktop.org/api/1.0/series/27061/revisions/1/mbox/

Test gem_exec_suspend:
        Subgroup basic-s4-devices:
                dmesg-warn -> PASS       (fi-kbl-r) fdo#100125
Test kms_flip:
        Subgroup basic-flip-vs-modeset:
                skip       -> PASS       (fi-skl-x1585l)
Test kms_pipe_crc_basic:
        Subgroup hang-read-crc-pipe-a:
                dmesg-warn -> PASS       (fi-pnv-d510) fdo#101597 +1
        Subgroup suspend-read-crc-pipe-b:
                dmesg-warn -> PASS       (fi-byt-n2820) fdo#101705

fdo#100125 https://bugs.freedesktop.org/show_bug.cgi?id=100125
fdo#101597 https://bugs.freedesktop.org/show_bug.cgi?id=101597
fdo#101705 https://bugs.freedesktop.org/show_bug.cgi?id=101705

fi-bdw-5557u     total:279  pass:268  dwarn:0   dfail:0   fail:0   skip:11  time:438s
fi-blb-e6850     total:279  pass:224  dwarn:1   dfail:0   fail:0   skip:54  time:362s
fi-bsw-n3050     total:279  pass:243  dwarn:0   dfail:0   fail:0   skip:36  time:529s
fi-bxt-j4205     total:279  pass:260  dwarn:0   dfail:0   fail:0   skip:19  time:512s
fi-byt-j1900     total:279  pass:254  dwarn:1   dfail:0   fail:0   skip:24  time:494s
fi-byt-n2820     total:279  pass:251  dwarn:0   dfail:0   fail:0   skip:28  time:482s
fi-glk-2a        total:279  pass:260  dwarn:0   dfail:0   fail:0   skip:19  time:596s
fi-hsw-4770      total:279  pass:263  dwarn:0   dfail:0   fail:0   skip:16  time:435s
fi-hsw-4770r     total:279  pass:263  dwarn:0   dfail:0   fail:0   skip:16  time:413s
fi-ilk-650       total:279  pass:229  dwarn:0   dfail:0   fail:0   skip:50  time:424s
fi-ivb-3520m     total:279  pass:261  dwarn:0   dfail:0   fail:0   skip:18  time:492s
fi-ivb-3770      total:279  pass:261  dwarn:0   dfail:0   fail:0   skip:18  time:483s
fi-kbl-7500u     total:279  pass:261  dwarn:0   dfail:0   fail:0   skip:18  time:462s
fi-kbl-7560u     total:279  pass:268  dwarn:1   dfail:0   fail:0   skip:10  time:574s
fi-kbl-r         total:279  pass:261  dwarn:0   dfail:0   fail:0   skip:18  time:580s
fi-pnv-d510      total:279  pass:223  dwarn:1   dfail:0   fail:0   skip:55  time:562s
fi-skl-6260u     total:279  pass:269  dwarn:0   dfail:0   fail:0   skip:10  time:474s
fi-skl-6700hq    total:279  pass:262  dwarn:0   dfail:0   fail:0   skip:17  time:585s
fi-skl-6700k     total:279  pass:257  dwarn:4   dfail:0   fail:0   skip:18  time:464s
fi-skl-6770hq    total:279  pass:269  dwarn:0   dfail:0   fail:0   skip:10  time:484s
fi-skl-gvtdvm    total:279  pass:266  dwarn:0   dfail:0   fail:0   skip:13  time:438s
fi-skl-x1585l    total:279  pass:269  dwarn:0   dfail:0   fail:0   skip:10  time:483s
fi-snb-2520m     total:279  pass:251  dwarn:0   dfail:0   fail:0   skip:28  time:543s
fi-snb-2600      total:279  pass:250  dwarn:0   dfail:0   fail:0   skip:29  time:405s
fi-bdw-gvtdvm failed to collect. IGT log at Patchwork_5153/fi-bdw-gvtdvm/igt.log

7b5049971e17069e7c1d97b82a3bca274e44f201 drm-tip: 2017y-07m-10d-08h-36m-55s UTC integration manifest
d21cd67 drm/i915: add config function for YCBCR420 outputs
249efed drm: add helper functions for YCBCR420 handling
29c2761 drm: set output colorspace in AVI infoframe
d9966a4 drm/edid: parse ycbcr 420 deep color information
e384e21 drm: add helper to validate YCBCR420 modes
999a0df drm/edid: parse YCBCR420 videomodes from EDID
a89318e drm/edid: cleanup patch for CEA extended-tag macro
094ff4a drm/edid: parse sink information before CEA blocks
45fb3ca drm/edid: complete CEA modedb(VIC 1-107)
a4aa1ce drm: handle HDMI 2.0 VICs in AVI info-frames

== Logs ==

For more details see: https://intel-gfx-ci.01.org/CI/Patchwork_5153/
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 19/20] drm/i915: Move AVI infoframe function to DDI layer
  2017-07-10 11:18 ` [PATCH 19/20] drm/i915: Move AVI infoframe function to DDI layer Shashank Sharma
@ 2017-07-12 17:15   ` Ville Syrjälä
  2017-07-13  4:58     ` Sharma, Shashank
  0 siblings, 1 reply; 76+ messages in thread
From: Ville Syrjälä @ 2017-07-12 17:15 UTC (permalink / raw)
  To: Shashank Sharma; +Cc: intel-gfx, dri-devel

On Mon, Jul 10, 2017 at 04:48:47PM +0530, Shashank Sharma wrote:
> We have an existing function to prepare AVI infoframes for HDMI,
> this patch moves that function from HDMI layer, to DDI layer, so
> that we can reuse the function for DP(LSPCON) displays too.
> 
> This patch:
> - Moves the intel_hdmi_set_avi_infoframes function in ddi layer.
> - Adds code to accommodate LSPCON in the same function.
> - Links this function as AVI infoframe setup function for LSPCON.
> 
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Imre Deak <imre.deak@intel.com>
> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_ddi.c    | 89 ++++++++++++++++++++++++++++++++++---
>  drivers/gpu/drm/i915/intel_drv.h    |  9 ++++
>  drivers/gpu/drm/i915/intel_hdmi.c   | 52 +++-------------------
>  drivers/gpu/drm/i915/intel_lspcon.c |  1 +
>  4 files changed, 99 insertions(+), 52 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> index 80e96f1..f691710 100644
> --- a/drivers/gpu/drm/i915/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/intel_ddi.c
> @@ -2003,8 +2003,76 @@ static void intel_ddi_clk_select(struct intel_encoder *encoder,
>  	}
>  }
>  
> +void intel_ddi_set_avi_infoframe(struct drm_encoder *encoder,
> +				  const struct intel_crtc_state *crtc_state)

NAK. Please look at my 'move infoframe stuff into intel_dig_port' series
if you need infoframes with DP. IIRC you already reviewed part of that.

> +{
> +	int ret;
> +	union hdmi_infoframe frame;
> +	struct drm_connector *connector;
> +	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
> +	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> +	const struct drm_display_mode *adjusted_mode =
> +					&crtc_state->base.adjusted_mode;
> +	enum intel_output_type type = to_intel_encoder(encoder)->type;
> +	bool is_hdmi2_sink = false;
> +	bool rgb_qrange_selectable = false;
> +	enum hdmi_colorspace colorspace = crtc_state->ycbcr420 ?
> +					  HDMI_COLORSPACE_YUV420 :
> +					  HDMI_COLORSPACE_RGB;
> +	bool rgb_qrange_limited =  crtc_state->limited_color_range ?
> +					HDMI_QUANTIZATION_RANGE_LIMITED :
> +					HDMI_QUANTIZATION_RANGE_FULL;
> +
> +	switch (type) {
> +	case INTEL_OUTPUT_HDMI:
> +		connector = &intel_hdmi->attached_connector->base;
> +		is_hdmi2_sink = connector->display_info.hdmi.scdc.supported;
> +		rgb_qrange_selectable = intel_hdmi->rgb_quant_range_selectable;
> +		break;
> +
> +	case INTEL_OUTPUT_DP:
> +		/* We are here means its a LSPCON device, still be paranoid */
> +		if (!crtc_state->lspcon_active) {
> +			DRM_ERROR("No LSPCON, why am I here ?\n");
> +			return;
> +		}
> +
> +		connector = &intel_dp->attached_connector->base;
> +		is_hdmi2_sink = connector->display_info.hdmi.scdc.supported;
> +		if (crtc_state->ycbcr420)
> +			rgb_qrange_limited = true;
> +		break;
> +
> +	default:
> +		DRM_ERROR("No other encoder allowed\n");
> +		return;
> +	}
> +
> +	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
> +						       adjusted_mode,
> +						       is_hdmi2_sink);
> +	if (ret < 0) {
> +		DRM_ERROR("couldn't fill AVI infoframe\n");
> +		return;
> +	}
> +
> +	ret = drm_hdmi_avi_infoframe_set_colorspace(&frame.avi,
> +						    adjusted_mode,
> +						    colorspace);
> +	if (ret < 0) {
> +		DRM_ERROR("couldn't fill AVI colorspace\n");
> +		return;
> +	}
> +
> +	drm_hdmi_avi_infoframe_quant_range(&frame.avi, adjusted_mode,
> +					   rgb_qrange_limited,
> +					   rgb_qrange_selectable);
> +
> +	intel_write_infoframe(encoder, crtc_state, &frame);
> +}
> +
>  static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder,
> -				    int link_rate, uint32_t lane_count,
> +				    const struct intel_crtc_state *pipe_config,
>  				    struct intel_shared_dpll *pll,
>  				    bool link_mst)
>  {
> @@ -2012,6 +2080,8 @@ static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder,
>  	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>  	enum port port = intel_ddi_get_encoder_port(encoder);
>  	struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base);
> +	int link_rate = pipe_config->port_clock;
> +	uint32_t lane_count = pipe_config->lane_count;
>  
>  	WARN_ON(link_mst && (port == PORT_A || port == PORT_E));
>  
> @@ -2030,6 +2100,14 @@ static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder,
>  	intel_dp_start_link_train(intel_dp);
>  	if (port != PORT_A || INTEL_GEN(dev_priv) >= 9)
>  		intel_dp_stop_link_train(intel_dp);
> +
> +	if (pipe_config->lspcon_active) {
> +		struct drm_encoder *drm_encoder = &encoder->base;
> +		struct intel_lspcon *lspcon = enc_to_intel_lspcon(drm_encoder);
> +
> +		if (lspcon->set_infoframes)
> +			lspcon->set_infoframes(&encoder->base, pipe_config);
> +	}
>  }
>  
>  static void intel_ddi_pre_enable_hdmi(struct intel_encoder *encoder,
> @@ -2072,8 +2150,7 @@ static void intel_ddi_pre_enable(struct intel_encoder *encoder,
>  
>  	if (type == INTEL_OUTPUT_DP || type == INTEL_OUTPUT_EDP) {
>  		intel_ddi_pre_enable_dp(encoder,
> -					pipe_config->port_clock,
> -					pipe_config->lane_count,
> +					pipe_config,
>  					pipe_config->shared_dpll,
>  					intel_crtc_has_type(pipe_config,
>  							    INTEL_OUTPUT_DP_MST));
> @@ -2628,17 +2705,17 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
>  	}
>  
>  	if (init_lspcon) {
> -		if (lspcon_init(intel_dig_port))
> -			/* TODO: handle hdmi info frame part */
> +		if (lspcon_init(intel_dig_port)) {
>  			DRM_DEBUG_KMS("LSPCON init success on port %c\n",
>  				port_name(port));
> -		else
> +		} else {
>  			/*
>  			 * LSPCON init faied, but DP init was success, so
>  			 * lets try to drive as DP++ port.
>  			 */
>  			DRM_ERROR("LSPCON init failed on port %c\n",
>  				port_name(port));
> +		}
>  	}
>  
>  	return;
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 40d56f2..fad9a53 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1075,6 +1075,10 @@ struct intel_lspcon {
>  	bool active;
>  	enum drm_lspcon_mode mode;
>  	enum lspcon_vendor vendor;
> +
> +	/* AVI IF setup function for LSPCON */
> +	void (*set_infoframes)(struct drm_encoder *encoder,
> +				const struct intel_crtc_state *crtc_state);
>  };
>  
>  struct intel_digital_port {
> @@ -1320,6 +1324,8 @@ u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder);
>  
>  unsigned int intel_fb_align_height(const struct drm_framebuffer *fb,
>  				   int plane, unsigned int height);
> +void intel_ddi_set_avi_infoframe(struct drm_encoder *encoder,
> +				 const struct intel_crtc_state *crtc_state);
>  
>  /* intel_audio.c */
>  void intel_init_audio_hooks(struct drm_i915_private *dev_priv);
> @@ -1690,6 +1696,9 @@ void intel_hdmi_handle_sink_scrambling(struct intel_encoder *intel_encoder,
>  				       struct drm_connector *connector,
>  				       bool high_tmds_clock_ratio,
>  				       bool scrambling);
> +void intel_write_infoframe(struct drm_encoder *encoder,
> +			    const struct intel_crtc_state *crtc_state,
> +			    union hdmi_infoframe *frame);
>  void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable);
>  bool intel_hdmi_ycbcr420_config(struct drm_connector *connector,
>  				struct intel_crtc_state *config,
> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> index a08ab99..7cab86a 100644
> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> @@ -430,7 +430,7 @@ static bool hsw_infoframe_enabled(struct drm_encoder *encoder,
>   * trick them by giving an offset into the buffer and moving back the header
>   * bytes by one.
>   */
> -static void intel_write_infoframe(struct drm_encoder *encoder,
> +void intel_write_infoframe(struct drm_encoder *encoder,
>  				  const struct intel_crtc_state *crtc_state,
>  				  union hdmi_infoframe *frame)
>  {
> @@ -453,46 +453,6 @@ static void intel_write_infoframe(struct drm_encoder *encoder,
>  	intel_hdmi->write_infoframe(encoder, crtc_state, frame->any.type, buffer, len);
>  }
>  
> -static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder,
> -					 const struct intel_crtc_state *crtc_state)
> -{
> -	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;
> -	enum hdmi_colorspace colorspace = HDMI_COLORSPACE_RGB;
> -	union hdmi_infoframe frame;
> -	int ret;
> -
> -	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
> -						       adjusted_mode,
> -						       is_hdmi2_sink);
> -	if (ret < 0) {
> -		DRM_ERROR("couldn't fill AVI infoframe\n");
> -		return;
> -	}
> -
> -	if (crtc_state->ycbcr420)
> -		colorspace = HDMI_COLORSPACE_YUV420;
> -
> -	ret = drm_hdmi_avi_infoframe_set_colorspace(&frame.avi,
> -						    adjusted_mode,
> -						    colorspace);
> -	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 :
> -					   HDMI_QUANTIZATION_RANGE_FULL,
> -					   intel_hdmi->rgb_quant_range_selectable);
> -
> -	intel_write_infoframe(encoder, crtc_state, &frame);
> -}
> -
>  static void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder,
>  					 const struct intel_crtc_state *crtc_state)
>  {
> @@ -582,7 +542,7 @@ static void g4x_set_infoframes(struct drm_encoder *encoder,
>  	I915_WRITE(reg, val);
>  	POSTING_READ(reg);
>  
> -	intel_hdmi_set_avi_infoframe(encoder, crtc_state);
> +	intel_ddi_set_avi_infoframe(encoder, crtc_state);
>  	intel_hdmi_set_spd_infoframe(encoder, crtc_state);
>  	intel_hdmi_set_hdmi_infoframe(encoder, crtc_state);
>  }
> @@ -723,7 +683,7 @@ static void ibx_set_infoframes(struct drm_encoder *encoder,
>  	I915_WRITE(reg, val);
>  	POSTING_READ(reg);
>  
> -	intel_hdmi_set_avi_infoframe(encoder, crtc_state);
> +	intel_ddi_set_avi_infoframe(encoder, crtc_state);
>  	intel_hdmi_set_spd_infoframe(encoder, crtc_state);
>  	intel_hdmi_set_hdmi_infoframe(encoder, crtc_state);
>  }
> @@ -766,7 +726,7 @@ static void cpt_set_infoframes(struct drm_encoder *encoder,
>  	I915_WRITE(reg, val);
>  	POSTING_READ(reg);
>  
> -	intel_hdmi_set_avi_infoframe(encoder, crtc_state);
> +	intel_ddi_set_avi_infoframe(encoder, crtc_state);
>  	intel_hdmi_set_spd_infoframe(encoder, crtc_state);
>  	intel_hdmi_set_hdmi_infoframe(encoder, crtc_state);
>  }
> @@ -819,7 +779,7 @@ static void vlv_set_infoframes(struct drm_encoder *encoder,
>  	I915_WRITE(reg, val);
>  	POSTING_READ(reg);
>  
> -	intel_hdmi_set_avi_infoframe(encoder, crtc_state);
> +	intel_ddi_set_avi_infoframe(encoder, crtc_state);
>  	intel_hdmi_set_spd_infoframe(encoder, crtc_state);
>  	intel_hdmi_set_hdmi_infoframe(encoder, crtc_state);
>  }
> @@ -852,7 +812,7 @@ static void hsw_set_infoframes(struct drm_encoder *encoder,
>  	I915_WRITE(reg, val);
>  	POSTING_READ(reg);
>  
> -	intel_hdmi_set_avi_infoframe(encoder, crtc_state);
> +	intel_ddi_set_avi_infoframe(encoder, crtc_state);
>  	intel_hdmi_set_spd_infoframe(encoder, crtc_state);
>  	intel_hdmi_set_hdmi_infoframe(encoder, crtc_state);
>  }
> diff --git a/drivers/gpu/drm/i915/intel_lspcon.c b/drivers/gpu/drm/i915/intel_lspcon.c
> index f611b6d..53ddd39 100644
> --- a/drivers/gpu/drm/i915/intel_lspcon.c
> +++ b/drivers/gpu/drm/i915/intel_lspcon.c
> @@ -281,6 +281,7 @@ bool lspcon_init(struct intel_digital_port *intel_dig_port)
>  	}
>  
>  	connector->ycbcr_420_allowed = true;
> +	lspcon->set_infoframes = intel_ddi_set_avi_infoframe;
>  	drm_dp_read_desc(&dp->aux, &dp->desc, drm_dp_is_branch(dp->dpcd));
>  
>  	DRM_DEBUG_KMS("Success: LSPCON init\n");
> -- 
> 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] 76+ messages in thread

* Re: [PATCH 18/20] drm/i915: YCBCR 420 support for LSPCON
  2017-07-10 11:18 ` [PATCH 18/20] drm/i915: YCBCR 420 support for LSPCON Shashank Sharma
@ 2017-07-12 17:15   ` Ville Syrjälä
  2017-07-13  5:02     ` Sharma, Shashank
  0 siblings, 1 reply; 76+ messages in thread
From: Ville Syrjälä @ 2017-07-12 17:15 UTC (permalink / raw)
  To: Shashank Sharma; +Cc: intel-gfx, dri-devel

On Mon, Jul 10, 2017 at 04:48:46PM +0530, Shashank Sharma wrote:
> LSPCON chips support YCBCR420 outputs. To be able to get
> YCBCR420 output from LSPCON chip, the source should:
> - Generate YCBCR444 HDMI output
> - Set AVI infoframes for a YCBCR420 output.
> 
> LSPCON FW gets the information from AVI infoframes, and generates
> YCBCR420 output from a YCBCR444 input. This patch adds the necessary
> changes to drive YCBCR420 output from LSPCON based HDMI output.
> 
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Imre Deak <imre.deak@intel.com>
> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 10 +++++++---
>  drivers/gpu/drm/i915/intel_dp.c      | 16 +++++++++++++++-
>  drivers/gpu/drm/i915/intel_drv.h     | 20 +++++++++++++++++---
>  drivers/gpu/drm/i915/intel_hdmi.c    |  7 +++++--
>  drivers/gpu/drm/i915/intel_lspcon.c  | 17 +++++++++++++++++
>  5 files changed, 61 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index c5ff568..c3c7b31 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -8125,9 +8125,11 @@ static void haswell_set_pipemisc(struct drm_crtc *crtc)
>  			val |= PIPEMISC_DITHER_ENABLE | PIPEMISC_DITHER_TYPE_SP;
>  
>  		if (config->ycbcr420) {
> -			val |= PIPEMISC_OUTPUT_YCBCR |
> -				PIPEMISC_YCBCR420_ENABLE |
> -				PIPEMISC_YCBCR420_MODE_BLEND;
> +			val |= PIPEMISC_OUTPUT_YCBCR;
> +
> +			if (!config->lspcon_active)
> +				val |= PIPEMISC_YCBCR420_ENABLE |
> +					PIPEMISC_YCBCR420_MODE_BLEND;
>  		}
>  
>  		I915_WRITE(PIPEMISC(intel_crtc->pipe), val);
> @@ -14205,11 +14207,13 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)
>  		 * DDI_BUF_CTL_A or SFUSE_STRAP registers, find another way to
>  		 * detect the ports.
>  		 */
> +
>  		intel_ddi_init(dev_priv, PORT_A);
>  		intel_ddi_init(dev_priv, PORT_B);
>  		intel_ddi_init(dev_priv, PORT_C);
>  
>  		intel_dsi_init(dev_priv);
> +
>  	} else if (HAS_DDI(dev_priv)) {
>  		int found;
>  
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 67bc8a7a..1690aa9 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -1614,7 +1614,9 @@ intel_dp_compute_config(struct intel_encoder *encoder,
>  	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>  	struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
>  	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
> -	enum port port = dp_to_dig_port(intel_dp)->port;
> +	struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base);
> +	enum port port = dig_port->port;
> +	struct intel_lspcon *lspcon = &dig_port->lspcon;
>  	struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->base.crtc);
>  	struct intel_connector *intel_connector = intel_dp->attached_connector;
>  	struct intel_digital_connector_state *intel_conn_state =
> @@ -1635,6 +1637,18 @@ intel_dp_compute_config(struct intel_encoder *encoder,
>  	common_len = intel_dp_common_len_rate_limit(intel_dp,
>  						    intel_dp->max_link_rate);
>  
> +	/* LSPCON needs special handling to drive YCBCR420 outputs */
> +	if (lspcon->active) {
> +		struct drm_connector *connector = &intel_connector->base;
> +		int clock_8bpc = pipe_config->base.adjusted_mode.crtc_clock;
> +		int clock_12bpc = clock_8bpc * 3 / 2;
> +
> +		pipe_config->lspcon_active = true;
> +		pipe_config->ycbcr420 = lspcon_ycbcr420_config(connector,
> +					     pipe_config, &clock_12bpc,
> +					     &clock_8bpc);

All this clock stuff here seems pointless. So I'd just replace this
stuff with the straightforward 'pipe_config->ycbcr420 = mode_needs_420';

> +	}
> +
>  	/* No common link rates between source and sink */
>  	WARN_ON(common_len <= 0);
>  
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index ed04de9..40d56f2 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -790,6 +790,9 @@ struct intel_crtc_state {
>  
>  	/* HDMI output type */
>  	bool ycbcr420;
> +
> +	/* LSPCON is active on port */
> +	bool lspcon_active;
>  };
>  
>  struct intel_crtc {
> @@ -1205,6 +1208,12 @@ static inline struct intel_dp *enc_to_intel_dp(struct drm_encoder *encoder)
>  	return &enc_to_dig_port(encoder)->dp;
>  }
>  
> +static inline struct intel_lspcon *
> +enc_to_intel_lspcon(struct drm_encoder *encoder)
> +{
> +	return &enc_to_dig_port(encoder)->lspcon;
> +}
> +
>  static inline struct intel_digital_port *
>  dp_to_dig_port(struct intel_dp *intel_dp)
>  {
> @@ -1675,14 +1684,16 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
>  			       struct intel_connector *intel_connector);
>  struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder);
>  bool intel_hdmi_compute_config(struct intel_encoder *encoder,
> -			       struct intel_crtc_state *pipe_config,
> -			       struct drm_connector_state *conn_state);
> +				struct intel_crtc_state *pipe_config,
> +				struct drm_connector_state *conn_state);
>  void intel_hdmi_handle_sink_scrambling(struct intel_encoder *intel_encoder,
>  				       struct drm_connector *connector,
>  				       bool high_tmds_clock_ratio,
>  				       bool scrambling);
>  void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable);
> -
> +bool intel_hdmi_ycbcr420_config(struct drm_connector *connector,
> +				struct intel_crtc_state *config,
> +				int *clock_12bpc, int *clock_8bpc);
>  
>  /* intel_lvds.c */
>  void intel_lvds_init(struct drm_i915_private *dev_priv);
> @@ -2003,6 +2014,9 @@ void intel_color_load_luts(struct drm_crtc_state *crtc_state);
>  bool lspcon_init(struct intel_digital_port *intel_dig_port);
>  void lspcon_resume(struct intel_lspcon *lspcon);
>  void lspcon_wait_pcon_mode(struct intel_lspcon *lspcon);
> +bool lspcon_ycbcr420_config(struct drm_connector *connector,
> +			    struct intel_crtc_state *config,
> +			    int *clock_12bpc, int *clock_8bpc);
>  
>  /* intel_pipe_crc.c */
>  int intel_pipe_crc_create(struct drm_minor *minor);
> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> index d1b1efc..a08ab99 100644
> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> @@ -1362,8 +1362,7 @@ static bool hdmi_12bpc_possible(struct intel_crtc_state *crtc_state,
>  	return true;
>  }
>  
> -static bool
> -intel_hdmi_ycbcr420_config(struct drm_connector *connector,
> +bool intel_hdmi_ycbcr420_config(struct drm_connector *connector,
>  			       struct intel_crtc_state *config,
>  			       int *clock_12bpc, int *clock_8bpc)
>  {
> @@ -1380,6 +1379,10 @@ intel_hdmi_ycbcr420_config(struct drm_connector *connector,
>  	*clock_8bpc /= 2;
>  	config->ycbcr420 = true;
>  
> +	/* LSPCON doesn't need scaler for YCBCR420 output */
> +	if (config->lspcon_active)
> +		return true;
> +
>  	/* YCBCR 420 output conversion needs a scaler */
>  	if (skl_update_scaler_crtc_420_output(config)) {
>  		DRM_ERROR("Scaler allocation for output failed\n");
> diff --git a/drivers/gpu/drm/i915/intel_lspcon.c b/drivers/gpu/drm/i915/intel_lspcon.c
> index a350d79..f611b6d 100644
> --- a/drivers/gpu/drm/i915/intel_lspcon.c
> +++ b/drivers/gpu/drm/i915/intel_lspcon.c
> @@ -202,6 +202,21 @@ static void lspcon_resume_in_pcon_wa(struct intel_lspcon *lspcon)
>  	DRM_DEBUG_KMS("LSPCON DP descriptor mismatch after resume\n");
>  }
>  
> +bool lspcon_ycbcr420_config(struct drm_connector *connector,
> +			    struct intel_crtc_state *config,
> +			    int *clock_12bpc, int *clock_8bpc)
> +{
> +	struct drm_display_info *info = &connector->display_info;
> +	struct drm_display_mode *mode = &config->base.adjusted_mode;
> +
> +	if (drm_mode_is_420_only(info, mode)) {
> +		return intel_hdmi_ycbcr420_config(connector, config,
> +					  clock_12bpc, clock_8bpc);
> +	}
> +
> +	return false;
> +}
> +
>  void lspcon_resume(struct intel_lspcon *lspcon)
>  {
>  	enum drm_lspcon_mode expected_mode;
> @@ -233,6 +248,7 @@ bool lspcon_init(struct intel_digital_port *intel_dig_port)
>  	struct intel_lspcon *lspcon = &intel_dig_port->lspcon;
>  	struct drm_device *dev = intel_dig_port->base.base.dev;
>  	struct drm_i915_private *dev_priv = to_i915(dev);
> +	struct drm_connector *connector = &dp->attached_connector->base;
>  
>  	if (!IS_GEN9(dev_priv)) {
>  		DRM_ERROR("LSPCON is supported on GEN9 only\n");
> @@ -264,6 +280,7 @@ bool lspcon_init(struct intel_digital_port *intel_dig_port)
>  		return false;
>  	}
>  
> +	connector->ycbcr_420_allowed = true;
>  	drm_dp_read_desc(&dp->aux, &dp->desc, drm_dp_is_branch(dp->dpcd));
>  
>  	DRM_DEBUG_KMS("Success: LSPCON init\n");
> -- 
> 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] 76+ messages in thread

* Re: [PATCH 16/20] drm: add function to read vendor OUI
  2017-07-10 11:18 ` [PATCH 16/20] drm: add function to read vendor OUI Shashank Sharma
@ 2017-07-12 17:15   ` Ville Syrjälä
  2017-07-13  5:04     ` Sharma, Shashank
  0 siblings, 1 reply; 76+ messages in thread
From: Ville Syrjälä @ 2017-07-12 17:15 UTC (permalink / raw)
  To: Shashank Sharma; +Cc: intel-gfx, dri-devel

On Mon, Jul 10, 2017 at 04:48:44PM +0530, Shashank Sharma wrote:
> This patch adds a helper function in DP dual mode layer to
> read the vendor's IEEE OUI signature from a Dual mode adapter.
> This will be used to differentiate between different LSPCON
> vendors, to address their custom programming requirements.

Can't we just read it from DPCD instead?

> 
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Imre Deak <imre.deak@intel.com>
> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
> ---
>  drivers/gpu/drm/drm_dp_dual_mode_helper.c | 24 ++++++++++++++++++++++++
>  include/drm/drm_dp_dual_mode_helper.h     |  4 +++-
>  2 files changed, 27 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/drm_dp_dual_mode_helper.c b/drivers/gpu/drm/drm_dp_dual_mode_helper.c
> index 80e62f6..0b890dc 100644
> --- a/drivers/gpu/drm/drm_dp_dual_mode_helper.c
> +++ b/drivers/gpu/drm/drm_dp_dual_mode_helper.c
> @@ -396,6 +396,30 @@ const char *drm_dp_get_dual_mode_type_name(enum drm_dp_dual_mode_type type)
>  EXPORT_SYMBOL(drm_dp_get_dual_mode_type_name);
>  
>  /**
> + * drm_lspcon_get_vendor_oui: match vendor OUI signature
> + * @adapter: i2c adapter under action
> + * @vendor_id = 3 bytes of vendor OUI signature, LSB=lower byte
> + *
> + * Returns:
> + * Vendor OUI id if got one, 0 if not
> + */
> +uint32_t drm_lspcon_get_vendor_oui(struct i2c_adapter *adapter)
> +{
> +	uint8_t sign[3] = {0, };
> +	uint32_t oui = 0;
> +
> +	if (drm_dp_dual_mode_read(adapter, DP_DUAL_MODE_LSPCON_OUI_OFFSET,
> +						sign, 3)) {
> +		DRM_ERROR("Can't identify vendor sign\n");
> +		return 0;
> +	}
> +
> +	oui = (sign[0] << 16) | (sign[1] << 8) | sign[2];
> +	return oui;
> +}
> +EXPORT_SYMBOL(drm_lspcon_get_vendor_oui);
> +
> +/**
>   * drm_lspcon_get_mode: Get LSPCON's current mode of operation by
>   * reading offset (0x80, 0x41)
>   * @adapter: I2C-over-aux adapter
> diff --git a/include/drm/drm_dp_dual_mode_helper.h b/include/drm/drm_dp_dual_mode_helper.h
> index 4c42db8..f81b526 100644
> --- a/include/drm/drm_dp_dual_mode_helper.h
> +++ b/include/drm/drm_dp_dual_mode_helper.h
> @@ -60,7 +60,8 @@
>  /* LSPCON specific registers, defined by MCA */
>  #define DP_DUAL_MODE_LSPCON_MODE_CHANGE		0x40
>  #define DP_DUAL_MODE_LSPCON_CURRENT_MODE		0x41
> -#define  DP_DUAL_MODE_LSPCON_MODE_PCON			0x1
> +#define DP_DUAL_MODE_LSPCON_MODE_PCON			0x1
> +#define DP_DUAL_MODE_LSPCON_OUI_OFFSET			0x11
>  
>  struct i2c_adapter;
>  
> @@ -116,4 +117,5 @@ int drm_lspcon_get_mode(struct i2c_adapter *adapter,
>  			enum drm_lspcon_mode *current_mode);
>  int drm_lspcon_set_mode(struct i2c_adapter *adapter,
>  			enum drm_lspcon_mode reqd_mode);
> +uint32_t drm_lspcon_get_vendor_oui(struct i2c_adapter *adapter);
>  #endif
> -- 
> 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] 76+ messages in thread

* Re: [PATCH 08/20] drm: set output colorspace in AVI infoframe
  2017-07-10 11:18 ` [PATCH 08/20] drm: set output colorspace in AVI infoframe Shashank Sharma
@ 2017-07-12 17:17   ` Ville Syrjälä
  2017-07-13  5:07     ` Sharma, Shashank
  0 siblings, 1 reply; 76+ messages in thread
From: Ville Syrjälä @ 2017-07-12 17:17 UTC (permalink / raw)
  To: Shashank Sharma; +Cc: intel-gfx, dri-devel

On Mon, Jul 10, 2017 at 04:48:36PM +0530, Shashank Sharma wrote:
> A source must set output colorspace information in AVI
> infoframes, so that the sink can decode upcoming frames
> accordingly.
> 
> This patch adds a function to add the output colorspace
> information in the AVI infoframes.
> 
> V2: Rebase
> V3: Rebase
> V4: Rebase
> V5: Rebase
> V6: Made patch independent of HDMI output type.
> 
> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
> ---
>  drivers/gpu/drm/drm_edid.c | 29 +++++++++++++++++++++++++++++
>  include/drm/drm_edid.h     |  5 +++++
>  2 files changed, 34 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index 944a28f..cede86e 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -4796,6 +4796,35 @@ 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 hdmi_colorspace colorspace)
> +{
> +	if (colorspace > HDMI_COLORSPACE_YUV420 ||
> +		colorspace < HDMI_COLORSPACE_RGB) {
> +		DRM_ERROR("Invalid color space type\n");
> +		return -EINVAL;
> +	}

Seems overly defensive. I'd say that if someone insists on writing
buggy code just let them do it.

> +
> +	frame->colorspace = colorspace;
> +	if (colorspace == HDMI_COLORSPACE_YUV420)
> +		frame->pixel_repeat = 0;

Most VICs don't allow pixel repeat in 444/etc. either, and we don't
protect against that. So this looks like pretty pointless check in
this form.

So IMO just drop this entire patch and just assign frame->colorspace in
the driver.

> +
> +	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 aa58146..b79e0cb 100644
> --- a/include/drm/drm_edid.h
> +++ b/include/drm/drm_edid.h
> @@ -332,6 +332,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);
> @@ -354,6 +355,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 hdmi_colorspace colorspace);
> +int
>  drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame,
>  					    const struct drm_display_mode *mode);
>  void
> -- 
> 2.7.4
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
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] 76+ messages in thread

* Re: [PATCH 13/20] drm/i915: prepare csc unit for YCBCR420 output
  2017-07-10 11:18 ` [PATCH 13/20] drm/i915: prepare csc unit " Shashank Sharma
@ 2017-07-12 17:17   ` Ville Syrjälä
  2017-07-13  5:14     ` Sharma, Shashank
  0 siblings, 1 reply; 76+ messages in thread
From: Ville Syrjälä @ 2017-07-12 17:17 UTC (permalink / raw)
  To: Shashank Sharma; +Cc: intel-gfx, dri-devel

On Mon, Jul 10, 2017 at 04:48:41PM +0530, Shashank Sharma wrote:
> To support ycbcr output, we need a pipe CSC block to do
> RGB->YCBCR conversion.
> 
> 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, which uses recommended bspec
> values to perform RGB->YCBCR conversion (target color space BT709)
> 
> V2: Rebase
> V3: Rebase
> V4: Rebase
> V5: Addressed review comments from Ander
>     - Remove extra line added in the patch
>     - Add the spec details in the commit message
>     - Combine two if(cond) while calling intel_crtc_compute_config
> V6: Handle YCBCR420 outputs only (Ville)
> 
> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_color.c   | 47 +++++++++++++++++++++++++++++++++++-
>  drivers/gpu/drm/i915/intel_display.c | 17 +++++++++++++
>  2 files changed, 63 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_color.c b/drivers/gpu/drm/i915/intel_color.c
> index 306c6b0..8a5d211 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 */

Are these BT.601 or BT.709 or something else?

> +#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

IIRC Ander didn't like these, and neither do I. I'd much prefer to reuse
the code we alreayd have for dealing with the CSC. Except I think that's
pretty broken in places so I guess we can go with this for now and try
to clean up the color management stuff later.

> +
>  /*
>   * 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 */

I don't understand what this comment is trying so say.

> +	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->ycbcr420) {
> +		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 b4a6415..c5ff568 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -6288,6 +6288,23 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
>  		return -EINVAL;
>  	}
>  
> +	/* YCBCR420 feasibility check */
> +	if (pipe_config->ycbcr420) {
> +		struct drm_crtc_state *drm_state = &pipe_config->base;
> +
> +		/*
> +		 * There is only one pipe CSC unit per pipe, and we need that
> +		 * for output conversion from RGB->YCBCR. So if CTM is already
> +		 * applied we can't support YCBCR420 output.
> +		 */
> +		if (drm_state->ctm) {
> +			DRM_ERROR("YCBCR420 and CTM is not possible\n");

DRM_DEBUG_KMS

> +			return -EINVAL;
> +		}
> +
> +		DRM_DEBUG_KMS("YCBCR420 output is possible from CRTC\n");

Seems like a fairly pointless debug print.

> +	}
> +
>  	/*
>  	 * Pipe horizontal size must be even in:
>  	 * - DVO ganged mode
> -- 
> 2.7.4
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
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] 76+ messages in thread

* Re: [PATCH 11/20] drm/i915: prepare scaler for YCBCR420 modeset
  2017-07-10 11:18 ` [PATCH 11/20] drm/i915: prepare scaler for YCBCR420 modeset Shashank Sharma
@ 2017-07-12 17:17   ` Ville Syrjälä
  2017-07-13  5:21     ` Sharma, Shashank
  0 siblings, 1 reply; 76+ messages in thread
From: Ville Syrjälä @ 2017-07-12 17:17 UTC (permalink / raw)
  To: Shashank Sharma; +Cc: intel-gfx, dri-devel

On Mon, Jul 10, 2017 at 04:48:39PM +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
> V5: addressed review comments from Ander:
>     - No need to check both scaler_user && hdmi_output.
>       Check for scaler_user is enough.
> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_atomic.c  |  6 ++++++
>  drivers/gpu/drm/i915/intel_display.c | 23 +++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_drv.h     | 10 +++++++++-
>  drivers/gpu/drm/i915/intel_hdmi.c    | 12 ++++++++++++
>  drivers/gpu/drm/i915/intel_panel.c   |  3 ++-
>  5 files changed, 52 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
> index 36d4e63..040d111 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_420_OUTPUT_INDEX) {

I think Ander already said that we should just tie this into the normal
pfit pipe scaler user. I agree. Having to users doesn't actually make
sense because there can be only one pipe scaler, and if we want to do
scaled 4:2:0 output then we anyway need to handle both cases
simultaneosly.

> +			name = "YCBCR420-OUTPUT";
> +			idx = intel_crtc->base.base.id;
> +
> +			/* YCBCR420 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 01900e1..c56081e 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -4621,6 +4621,9 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
>  	 */
>  	need_scaling = src_w != dst_w || src_h != dst_h;
>  
> +	if (scaler_user == SKL_420_OUTPUT_INDEX)
> +		need_scaling = true;
> +
>  	/*
>  	 * if plane is being disabled or scaler is no more required or force detach
>  	 *  - free scaler binded to this plane/crtc
> @@ -4668,6 +4671,26 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
>  }
>  
>  /**
> + * skl_update_scaler_crtc_420_output - Stages update to scaler state
> + * for YCBCR420 which 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_420_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_420_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
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 592243b..68b4fba 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
> +
> +	/*
> +	 * YCBCR 420 output consume a scaler. So adding a user
> +	 * for 420 output requirement.
> +	 */
> +#define SKL_420_OUTPUT_INDEX 30
>  	unsigned scaler_users;
>  
>  	/* scaler used by crtc for panel fitting purpose */
> @@ -1483,6 +1490,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_420_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 276d916..9e8d784 100644
> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> @@ -1355,6 +1355,7 @@ intel_hdmi_ycbcr420_config(struct drm_connector *connector,
>  			       struct intel_crtc_state *config,
>  			       int *clock_12bpc, int *clock_8bpc)
>  {
> +	struct intel_crtc *intel_crtc = to_intel_crtc(config->base.crtc);
>  
>  	if (!connector->ycbcr_420_allowed) {
>  		DRM_ERROR("Platform doesn't support YCBCR420 output\n");
> @@ -1366,6 +1367,17 @@ intel_hdmi_ycbcr420_config(struct drm_connector *connector,
>  	*clock_12bpc /= 2;
>  	*clock_8bpc /= 2;
>  	config->ycbcr420 = true;
> +
> +	/* YCBCR 420 output conversion needs a scaler */
> +	if (skl_update_scaler_crtc_420_output(config)) {
> +		DRM_ERROR("Scaler allocation for output failed\n");
> +		return false;
> +	}
> +
> +	/* Bind this scaler to pipe */
> +	intel_pch_panel_fitting(intel_crtc, config,
> +				DRM_MODE_SCALE_FULLSCREEN);
> +
>  	return true;
>  }
>  
> diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
> index 96c2cbd..fd2e081 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->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

-- 
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] 76+ messages in thread

* Re: [PATCH 10/20] drm/i915: add config function for YCBCR420 outputs
  2017-07-10 11:18 ` [PATCH 10/20] drm/i915: add config function for YCBCR420 outputs Shashank Sharma
@ 2017-07-12 17:17   ` Ville Syrjälä
  2017-07-13  5:26     ` Sharma, Shashank
  0 siblings, 1 reply; 76+ messages in thread
From: Ville Syrjälä @ 2017-07-12 17:17 UTC (permalink / raw)
  To: Shashank Sharma; +Cc: intel-gfx, dri-devel

On Mon, Jul 10, 2017 at 04:48:38PM +0530, Shashank Sharma wrote:
> This patch checks encoder level support for YCBCR420 outputs.
> The logic goes as simple as this:
> If the input mode is YCBCR420-only mode: prepare HDMI for
> YCBCR420 output, else continue with RGB output mode.
> 
> It checks if the mode is YCBCR420 and source can support this
> output then it marks the ycbcr_420 output indicator 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
> V5: Rebase
> V6: Check and handle YCBCR420-only modes, discard the property
>     based approach (Ville)
> 
> 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    | 42 +++++++++++++++++++++++++++++++++---
>  3 files changed, 43 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 4e03ca6..01900e1 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(ycbcr420);
>  
>  	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 d17a324..592243b 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 */
> +	bool ycbcr420;
>  };
>  
>  struct intel_crtc {
> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> index cc0d100..276d916 100644
> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> @@ -1305,7 +1305,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,
> +				bool output_ycbcr420)

You alreayd have the crtc state, so no need to pass that stuff
separately.

>  {
>  	struct drm_i915_private *dev_priv =
>  		to_i915(crtc_state->base.crtc->dev);
> @@ -1330,6 +1331,13 @@ static bool hdmi_12bpc_possible(struct intel_crtc_state *crtc_state)
>  		if (connector_state->crtc != crtc_state->base.crtc)
>  			continue;
>  
> +		if (output_ycbcr420) {
> +			const struct drm_hdmi_info *hdmi = &info->hdmi;
> +
> +			if (!(hdmi->y420_dc_modes & DRM_EDID_YCBCR420_DC_36))
> +				return false;
> +		}
> +

else?

>  		if ((info->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_36) == 0)
>  			return false;
>  	}
> @@ -1342,6 +1350,25 @@ static bool hdmi_12bpc_possible(struct intel_crtc_state *crtc_state)
>  	return true;
>  }
>  
> +static bool
> +intel_hdmi_ycbcr420_config(struct drm_connector *connector,
> +			       struct intel_crtc_state *config,
> +			       int *clock_12bpc, int *clock_8bpc)
> +{
> +
> +	if (!connector->ycbcr_420_allowed) {
> +		DRM_ERROR("Platform doesn't support YCBCR420 output\n");
> +		return false;
> +	}
> +
> +	/* YCBCR420 TMDS rate requirement is half the pixel clock */
> +	config->port_clock /= 2;
> +	*clock_12bpc /= 2;
> +	*clock_8bpc /= 2;
> +	config->ycbcr420 = true;
> +	return true;
> +}
> +
>  bool intel_hdmi_compute_config(struct intel_encoder *encoder,
>  			       struct intel_crtc_state *pipe_config,
>  			       struct drm_connector_state *conn_state)
> @@ -1349,7 +1376,8 @@ 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;
> @@ -1379,6 +1407,14 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
>  		clock_12bpc *= 2;
>  	}
>  
> +	if (drm_mode_is_420_only(&connector->display_info, adjusted_mode)) {
> +		if (!intel_hdmi_ycbcr420_config(connector, pipe_config,
> +						&clock_12bpc, &clock_8bpc)) {
> +			DRM_ERROR("Can't support YCBCR420 output\n");
> +			return false;
> +		}
> +	}
> +
>  	if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv))
>  		pipe_config->has_pch_encoder = true;
>  
> @@ -1398,7 +1434,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, pipe_config->ycbcr420)) {
>  		DRM_DEBUG_KMS("picking bpc to 12 for HDMI output\n");
>  		desired_bpp = 12*3;
>  
> -- 
> 2.7.4
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
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] 76+ messages in thread

* Re: [PATCH 09/20] drm: add helper functions for YCBCR420 handling
  2017-07-10 11:18 ` [PATCH 09/20] drm: add helper functions for YCBCR420 handling Shashank Sharma
@ 2017-07-12 17:17   ` Ville Syrjälä
  2017-07-13  5:27     ` Sharma, Shashank
  0 siblings, 1 reply; 76+ messages in thread
From: Ville Syrjälä @ 2017-07-12 17:17 UTC (permalink / raw)
  To: Shashank Sharma; +Cc: intel-gfx, dri-devel

On Mon, Jul 10, 2017 at 04:48:37PM +0530, Shashank Sharma wrote:
> This patch adds helper functions for YCBCR 420 handling.
> These functions do:
> - check if a given video mode is YCBCR 420 only mode.
> - check if a given video mode is YCBCR 420 also mode.
> 
> 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)
> V5: Addressed review comments from Danvet:
>     - %s/drm_find_hdmi_output_type/drm_display_info_hdmi_output_type
>     - %s/drm_can_support_ycbcr_output/drm_display_supports_ycbcr_output
>     - %s/drm_can_support_this_ycbcr_output/
> 		drm_display_supports_this_ycbcr_output
>     - pass drm_display_info instead of drm_connector for consistency
>     - For drm_get_highest_quality_ycbcr_supported doc, move the variable
>       description above, and then the function description.
> V6: Add only YCBCR420 helpers (Ville)
> 
> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
> ---
>  drivers/gpu/drm/drm_modes.c | 74 +++++++++++++++++++++++++++++++++++++++++++++
>  include/drm/drm_modes.h     |  6 ++++
>  2 files changed, 80 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
> index 3b53c8e3..61c82a38 100644
> --- a/drivers/gpu/drm/drm_modes.c
> +++ b/drivers/gpu/drm/drm_modes.c
> @@ -1604,3 +1604,77 @@ 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 be supported in YCBCR420 format
> + * false if not.
> + */
> +bool drm_mode_is_420_only(struct drm_display_info *display,
> +			struct drm_display_mode *mode)

Both should be const. Indentation looks busted.

> +{
> +	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;

More unnecessary checks.

> +
> +	return test_bit(vic, display->hdmi.y420_vdb_modes);
> +}
> +EXPORT_SYMBOL(drm_mode_is_420_only);
> +
> +/**
> + * 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 be support YCBCR420 format
> + * false if not.
> + */
> +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);
> +}
> +EXPORT_SYMBOL(drm_mode_is_420_also);
> +/**
> + * drm_mode_is_420 - if a given videomode can be supported in YCBCR420
> + * output format
> + *
> + * @display: display under action.
> + * @mode: video mode to be tested.
> + *
> + * Returns:
> + * true if the mode can be supported in YCBCR420 format
> + * false if not.
> + */
> +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);
> +}
> +EXPORT_SYMBOL(drm_mode_is_420);
> diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h
> index f8a1268..980db27 100644
> --- a/include/drm/drm_modes.h
> +++ b/include/drm/drm_modes.h
> @@ -452,6 +452,12 @@ int drm_mode_convert_umode(struct drm_display_mode *out,
>  			   const struct drm_mode_modeinfo *in);
>  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);
> +bool drm_mode_is_420_only(struct drm_display_info *display,
> +			struct drm_display_mode *mode);
> +bool drm_mode_is_420_also(struct drm_display_info *display,
> +			struct drm_display_mode *mode);
> +bool drm_mode_is_420(struct drm_display_info *display,
> +			struct drm_display_mode *mode);
>  
>  struct drm_display_mode *drm_cvt_mode(struct drm_device *dev,
>  				      int hdisplay, int vdisplay, int vrefresh,
> -- 
> 2.7.4
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
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] 76+ messages in thread

* Re: [PATCH 06/20] drm: add helper to validate YCBCR420 modes
  2017-07-10 11:18 ` [PATCH 06/20] drm: add helper to validate YCBCR420 modes Shashank Sharma
@ 2017-07-12 17:18   ` Ville Syrjälä
  2017-07-13  5:32     ` Sharma, Shashank
  0 siblings, 1 reply; 76+ messages in thread
From: Ville Syrjälä @ 2017-07-12 17:18 UTC (permalink / raw)
  To: Shashank Sharma; +Cc: intel-gfx, dri-devel

On Mon, Jul 10, 2017 at 04:48:34PM +0530, Shashank Sharma wrote:
> YCBCR420 modes are supported only on HDMI 2.0 capable sources.
> This patch adds:
> - A drm helper to validate YCBCR420-only mode on a particular
>   connector. This function will help pruning the YCBCR420-only
>   modes from the connector's modelist.
> - 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 YCBCR420 output, so that no
>   YCBCR 420 modes will be listed for sources which can't handle it.
>   A driver should set this variable if it wants to see YCBCR420 modes
>   in the modedb.
> 
> V5: Introduced the patch in series.
> V5-resend: Squashed two patches (validate YCBCR420 and add YCBCR420
> 	   identifier)
> 
> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
> ---
>  drivers/gpu/drm/drm_edid.c         |  3 ++-
>  drivers/gpu/drm/drm_modes.c        | 28 ++++++++++++++++++++++++++++
>  drivers/gpu/drm/drm_probe_helper.c |  4 ++++
>  include/drm/drm_connector.h        |  9 +++++++++
>  include/drm/drm_edid.h             |  1 +
>  include/drm/drm_modes.h            |  5 +++++
>  6 files changed, 49 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index 10dab62..44be128 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -2950,10 +2950,11 @@ 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);
>  }
> +EXPORT_SYMBOL(drm_valid_cea_vic);
>  
>  /**
>   * drm_get_cea_aspect_ratio - get the picture aspect ratio corresponding to
> diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
> index f2493b9..3b53c8e3 100644
> --- a/drivers/gpu/drm/drm_modes.c
> +++ b/drivers/gpu/drm/drm_modes.c
> @@ -1083,6 +1083,34 @@ drm_mode_validate_size(const struct drm_display_mode *mode,
>  }
>  EXPORT_SYMBOL(drm_mode_validate_size);
>  
> +/**
> + * drm_mode_ycbcr420_only - add 'ycbcr420-only' modes only when allowed
> + * @mode: mode to check
> + * @connector: drm connector under action
> + *
> + * This function is a helper which can be used to filter out any YCBCR420
> + * only mode, when the source doesn't support it.
> + *
> + * Returns:
> + * The mode status
> + */
> +enum drm_mode_status
> +drm_mode_validate_ycbcr420(const struct drm_display_mode *mode,
> +			   struct drm_connector *connector)
> +{
> +	u8 vic = drm_match_cea_mode(mode);
> +	enum drm_mode_status status = MODE_OK;
> +	struct drm_hdmi_info *hdmi = &connector->display_info.hdmi;
> +
> +	if (drm_valid_cea_vic(vic) && test_bit(vic, hdmi->y420_vdb_modes)) {

Still think the valid check is pointless. Skipping that would also avoid
having to make the function non-static (the EXPORT_SYMBOL there seems
unnecessary either way).

> +		if (!connector->ycbcr_420_allowed)
> +			status = MODE_NO_420;
> +	}
> +
> +	return status;
> +}
> +EXPORT_SYMBOL(drm_mode_validate_ycbcr420);
> +
>  #define MODE_STATUS(status) [MODE_ ## status + 3] = #status
>  
>  static const char * const drm_mode_status_names[] = {

^
This thing needs to be updated as well.

> diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
> index 00e6832..904966c 100644
> --- a/drivers/gpu/drm/drm_probe_helper.c
> +++ b/drivers/gpu/drm/drm_probe_helper.c
> @@ -528,6 +528,10 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
>  		if (mode->status == MODE_OK)
>  			mode->status = drm_mode_validate_pipeline(mode,
>  								  connector);
> +
> +		if (mode->status == MODE_OK)
> +			mode->status = drm_mode_validate_ycbcr420(mode,
> +								  connector);
>  	}
>  
>  prune:
> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> index b3af8e3..225e092 100644
> --- a/include/drm/drm_connector.h
> +++ b/include/drm/drm_connector.h
> @@ -746,6 +746,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.
> diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
> index 89c0062..b55b2a7 100644
> --- a/include/drm/drm_edid.h
> +++ b/include/drm/drm_edid.h
> @@ -477,4 +477,5 @@ void drm_edid_get_monitor_name(struct edid *edid, char *name,
>  struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
>  					   int hsize, int vsize, int fresh,
>  					   bool rb);
> +bool drm_valid_cea_vic(u8 vic);
>  #endif /* __DRM_EDID_H__ */
> diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h
> index 94ac771..f8a1268 100644
> --- a/include/drm/drm_modes.h
> +++ b/include/drm/drm_modes.h
> @@ -80,6 +80,7 @@ struct videomode;
>   * @MODE_ONE_SIZE: only one resolution is supported
>   * @MODE_NO_REDUCED: monitor doesn't accept reduced blanking
>   * @MODE_NO_STEREO: stereo modes not supported
> + * @MODE_NO_420: ycbcr 420 modes not supported
>   * @MODE_STALE: mode has become stale
>   * @MODE_BAD: unspecified reason
>   * @MODE_ERROR: error condition
> @@ -124,6 +125,7 @@ enum drm_mode_status {
>  	MODE_ONE_SIZE,
>  	MODE_NO_REDUCED,
>  	MODE_NO_STEREO,
> +	MODE_NO_420,
>  	MODE_STALE = -3,
>  	MODE_BAD = -2,
>  	MODE_ERROR = -1
> @@ -496,6 +498,9 @@ bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1,
>  enum drm_mode_status drm_mode_validate_basic(const struct drm_display_mode *mode);
>  enum drm_mode_status drm_mode_validate_size(const struct drm_display_mode *mode,
>  					    int maxX, int maxY);
> +enum drm_mode_status
> +drm_mode_validate_ycbcr420(const struct drm_display_mode *mode,
> +			   struct drm_connector *connector);
>  void drm_mode_prune_invalid(struct drm_device *dev,
>  			    struct list_head *mode_list, bool verbose);
>  void drm_mode_sort(struct list_head *mode_list);
> -- 
> 2.7.4
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
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] 76+ messages in thread

* Re: [PATCH 07/20] drm/edid: parse ycbcr 420 deep color information
  2017-07-10 11:18 ` [PATCH 07/20] drm/edid: parse ycbcr 420 deep color information Shashank Sharma
@ 2017-07-12 17:18   ` Ville Syrjälä
  2017-07-13  5:33     ` Sharma, Shashank
  0 siblings, 1 reply; 76+ messages in thread
From: Ville Syrjälä @ 2017-07-12 17:18 UTC (permalink / raw)
  To: Shashank Sharma; +Cc: intel-gfx, dri-devel

On Mon, Jul 10, 2017 at 04:48:35PM +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)
> V5: Optimize function, if(conditions) not reqd (Ville)
> V6: Rebase
> 
> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
> ---
>  drivers/gpu/drm/drm_edid.c  | 12 ++++++++++++
>  include/drm/drm_connector.h |  3 +++
>  include/drm/drm_edid.h      |  8 ++++++++
>  3 files changed, 23 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index 44be128..944a28f 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -4199,6 +4199,16 @@ 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)
> +{
> +	u8 dc_mask;
> +	struct drm_hdmi_info *hdmi = &connector->display_info.hdmi;
> +
> +	dc_mask = db[7] & DRM_EDID_YCBCR420_DC_MASK;
> +	hdmi->y420_dc_modes |= dc_mask;
> +}
> +
>  static void drm_parse_hdmi_forum_vsdb(struct drm_connector *connector,
>  				 const u8 *hf_vsdb)
>  {
> @@ -4239,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 225e092..4bc0882 100644
> --- a/include/drm/drm_connector.h
> +++ b/include/drm/drm_connector.h
> @@ -154,6 +154,9 @@ struct drm_hdmi_info {
>  
>  	/** @y420_cmdb_map: bitmap of SVD index, to extraxt vcb modes */
>  	u64 y420_cmdb_map;
> +
> +	/** @y420_dc_modes: bitmap of deep color support index */
> +	u8 y420_dc_modes;

Pls put it next to the other dc u8 stuff.

>  };
>  
>  /**
> diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
> index b55b2a7..aa58146 100644
> --- a/include/drm/drm_edid.h
> +++ b/include/drm/drm_edid.h
> @@ -213,6 +213,14 @@ 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)
> +#define DRM_EDID_YCBCR420_DC_MASK (DRM_EDID_YCBCR420_DC_48 | \
> +				    DRM_EDID_YCBCR420_DC_36 | \
> +				    DRM_EDID_YCBCR420_DC_30)
> +
>  /* 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

-- 
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] 76+ messages in thread

* Re: [PATCH 02/20] drm/edid: complete CEA modedb(VIC 1-107)
  2017-07-10 11:18 ` [PATCH 02/20] drm/edid: complete CEA modedb(VIC 1-107) Shashank Sharma
@ 2017-07-12 17:18   ` Ville Syrjälä
  2017-07-13  5:38     ` Sharma, Shashank
  0 siblings, 1 reply; 76+ messages in thread
From: Ville Syrjälä @ 2017-07-12 17:18 UTC (permalink / raw)
  To: Shashank Sharma; +Cc: intel-gfx, dri-devel

On Mon, Jul 10, 2017 at 04:48:30PM +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/
> 
> V2: Rebase
> V3: Rebase
> V4: Added native bit handling as per CEA-861-F spec (Ville)
> V5: Fix timings for VIC 77:1920x1080 and 104:3840x2160p (Ville)
>     Remove unnecessary paranthesis from function svd_to_vic (Ville)
>     Added r-b (Neil)
> 
> Reviewed-by: Jose Abreu <Jose.Abreu@synopsys.com>
> Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
> Reviewed-by: Neil Armstrong <narmstrong@baylibre.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 0667b07..b879662 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, 1089, 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, },

Indentation looks broken starting from this mode. Pls fix your editor.
Otherwise lgtm.

> +	/* 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, 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_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
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
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] 76+ messages in thread

* Re: [PATCH 20/20] drm/i915: write AVI infoframes for LSPCON
  2017-07-10 11:18 ` [PATCH 20/20] drm/i915: write AVI infoframes for LSPCON Shashank Sharma
@ 2017-07-12 17:24   ` Ville Syrjälä
  2017-07-13  5:41     ` Sharma, Shashank
  0 siblings, 1 reply; 76+ messages in thread
From: Ville Syrjälä @ 2017-07-12 17:24 UTC (permalink / raw)
  To: Shashank Sharma; +Cc: intel-gfx, dri-devel

On Mon, Jul 10, 2017 at 04:48:48PM +0530, Shashank Sharma wrote:
> LSPCON chips can't pick the HDMI AVI infoframes from direct link.
> In order to pass AVI infoframes from display controller to LSPCON,
> we have to write infoframe packets into vendor specified AUX address.
> 
> Also, LSPCON vendors provide AUX offsets, to inform the LSPCON
> chip that the AVI IF packets are written, so that the firmware
> can pick it up and apply.
> 
> This patch adds function to write AVI infoframes for both MCA as
> well as Parade Tech LSPCON chips. These two vendors provide different
> methods for writing infoframes, so this patch contains two different
> functions, one for each.

Seems to me that we should also be checking the receiver cap for the
444->420 conversion support, and enable it in the PROTOCOL_CONVERTER
DPCD register. Or are these LSPCON things even ignoring that part of the
spec?

> 
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Imre Deak <imre.deak@intel.com>
> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_ddi.c    |   8 ++
>  drivers/gpu/drm/i915/intel_drv.h    |   3 +
>  drivers/gpu/drm/i915/intel_lspcon.c | 174 ++++++++++++++++++++++++++++++++++++
>  3 files changed, 185 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> index f691710..944d9d5 100644
> --- a/drivers/gpu/drm/i915/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/intel_ddi.c
> @@ -2068,6 +2068,14 @@ void intel_ddi_set_avi_infoframe(struct drm_encoder *encoder,
>  					   rgb_qrange_limited,
>  					   rgb_qrange_selectable);
>  
> +	if (crtc_state->lspcon_active) {
> +		struct intel_lspcon *lspcon = enc_to_intel_lspcon(encoder);
> +
> +		/* LSPCON writes infoframes via AUX */
> +		lspcon->write_infoframe(encoder, crtc_state, &frame);
> +		return;
> +	}
> +
>  	intel_write_infoframe(encoder, crtc_state, &frame);
>  }
>  
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index fad9a53..3e686d2 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1079,6 +1079,9 @@ struct intel_lspcon {
>  	/* AVI IF setup function for LSPCON */
>  	void (*set_infoframes)(struct drm_encoder *encoder,
>  				const struct intel_crtc_state *crtc_state);
> +	void (*write_infoframe)(struct drm_encoder *encoder,
> +				const struct intel_crtc_state *crtc_state,
> +				union hdmi_infoframe *frame);
>  };
>  
>  struct intel_digital_port {
> diff --git a/drivers/gpu/drm/i915/intel_lspcon.c b/drivers/gpu/drm/i915/intel_lspcon.c
> index 53ddd39..01fddf7 100644
> --- a/drivers/gpu/drm/i915/intel_lspcon.c
> +++ b/drivers/gpu/drm/i915/intel_lspcon.c
> @@ -31,6 +31,18 @@
>  #define LSPCON_VENDOR_PARADE_OUI 0x001CF8
>  #define LSPCON_VENDOR_MCA_OUI 0x0060AD
>  
> +/* AUX addresses to write AVI IF into */
> +#define LSPCON_MCA_AVI_IF_WRITE_OFFSET 0x5C0
> +#define LSPCON_MCA_AVI_IF_CTRL 0x5DF
> +#define  LSPCON_MCA_AVI_IF_KICKOFF (1 << 0)
> +#define  LSPCON_MCA_AVI_IF_HANDLED (1 << 1)
> +
> +#define LSPCON_PARADE_AVI_IF_WRITE_OFFSET 0x516
> +#define LSPCON_PARADE_AVI_IF_CTRL 0x51E
> +#define  LSPCON_PARADE_AVI_IF_KICKOFF (1 << 7)
> +#define LSPCON_PARADE_AVI_IF_STATUS 0x51F
> +#define  LSPCON_PARADE_AVI_IF_HANDLED (2 << 6)
> +
>  static struct intel_dp *lspcon_to_intel_dp(struct intel_lspcon *lspcon)
>  {
>  	struct intel_digital_port *dig_port =
> @@ -217,6 +229,167 @@ bool lspcon_ycbcr420_config(struct drm_connector *connector,
>  	return false;
>  }
>  
> +static bool _lspcon_write_infoframe_parade(struct drm_dp_aux *aux,
> +					   uint8_t *buffer, ssize_t len)
> +{
> +	u8 avi_if_ctrl;
> +	u8 avi_if_status;
> +	u8 count = 0;
> +	u8 retry = 5;
> +	u8 avi_buf[8] = {0, };
> +	uint16_t reg;
> +	ssize_t ret;
> +
> +	while (count++ < 4) {
> +
> +		do {
> +			/* Is LSPCON FW ready */
> +			reg = LSPCON_PARADE_AVI_IF_CTRL;
> +			ret = drm_dp_dpcd_read(aux, reg, &avi_if_ctrl, 1);
> +			if (ret < 0) {
> +				DRM_ERROR("DPCD read failed, add:0x%x\n", reg);
> +				return false;
> +			}
> +
> +			if (avi_if_ctrl & LSPCON_PARADE_AVI_IF_KICKOFF)
> +				break;
> +			usleep_range(100, 200);
> +		} while (--retry);
> +
> +		if (!(avi_if_ctrl & LSPCON_PARADE_AVI_IF_KICKOFF)) {
> +			DRM_ERROR("LSPCON FW not ready for infoframes\n");
> +			return false;
> +		}
> +
> +		/*
> +		 * AVI Infoframe contains 31 bytes of data:
> +		 *	HB0 to HB2   (3 bytes header)
> +		 *	PB0 to PB27 (28 bytes data)
> +		 * As per Parade spec, while sending first block (8bytes),
> +		 * byte 0 is kept for request token no, and byte1 - byte7
> +		 * contain frame data. So we have to pack frame like this:
> +		 *	first block of 8 bytes: <token> <HB0-HB2> <PB0-PB3>
> +		 *	next 3 blocks: <PB4-PB27>
> +		 */
> +		if (count)
> +			memcpy(avi_buf, buffer + count * 8 - 1, 8);
> +		else {
> +			avi_buf[0] = 1;
> +			memcpy(&avi_buf[1], buffer, 7);
> +		}
> +
> +		/* Write 8 bytes of data at a time */
> +		reg = LSPCON_PARADE_AVI_IF_WRITE_OFFSET;
> +		ret = drm_dp_dpcd_write(aux, reg, avi_buf, 8);
> +		if (ret < 0) {
> +			DRM_ERROR("DPCD write failed, add:0x%x\n", reg);
> +			return false;
> +		}
> +
> +		/*
> +		 * While sending a block of 8 byes, we need to inform block
> +		 * number to FW, by programming bits[1:0] of ctrl reg with
> +		 * block number
> +		 */
> +		avi_if_ctrl = 0x80 + count;
> +		reg = LSPCON_PARADE_AVI_IF_CTRL;
> +		ret = drm_dp_dpcd_write(aux, reg, &avi_if_ctrl, 1);
> +		if (ret < 0) {
> +			DRM_ERROR("DPCD write failed, add:0x%x\n", reg);
> +			return false;
> +		}
> +	}
> +
> +	/* Check LSPCON FW status */
> +	reg = LSPCON_PARADE_AVI_IF_STATUS;
> +	ret = drm_dp_dpcd_read(aux, reg, &avi_if_status, 1);
> +	if (ret < 0) {
> +		DRM_ERROR("DPCD write failed, address 0x%x\n", reg);
> +		return false;
> +	}
> +
> +	if (avi_if_status & LSPCON_PARADE_AVI_IF_HANDLED)
> +		DRM_DEBUG_KMS("AVI IF handled by FW\n");
> +
> +	return true;
> +}
> +
> +static bool _lspcon_write_infoframe_mca(struct drm_dp_aux *aux,
> +					uint8_t *buffer, ssize_t len)
> +{
> +	int ret;
> +	uint32_t val = 0;
> +	uint16_t reg;
> +	uint8_t *data = buffer;
> +
> +	reg = LSPCON_MCA_AVI_IF_WRITE_OFFSET;
> +	while (val < len) {
> +		ret = drm_dp_dpcd_write(aux, reg, data, 1);
> +		if (ret < 0) {
> +			DRM_ERROR("DPCD write failed, add:0x%x\n", reg);
> +			return false;
> +		}
> +		val++; reg++; data++;
> +	}
> +
> +	val = 0;
> +	reg = LSPCON_MCA_AVI_IF_CTRL;
> +	ret = drm_dp_dpcd_read(aux, reg, &val, 1);
> +	if (ret < 0) {
> +		DRM_ERROR("DPCD read failed, address 0x%x\n", reg);
> +		return false;
> +	}
> +
> +	/* Indicate LSPCON chip about infoframe, clear bit 1 and set bit 0 */
> +	val &= ~LSPCON_MCA_AVI_IF_HANDLED;
> +	val |= LSPCON_MCA_AVI_IF_KICKOFF;
> +
> +	ret = drm_dp_dpcd_write(aux, reg, &val, 1);
> +	if (ret < 0) {
> +		DRM_ERROR("DPCD read failed, address 0x%x\n", reg);
> +		return false;
> +	}
> +
> +	val = 0;
> +	ret = drm_dp_dpcd_read(aux, reg, &val, 1);
> +	if (ret < 0) {
> +		DRM_ERROR("DPCD read failed, address 0x%x\n", reg);
> +		return false;
> +	}
> +
> +	if (val == LSPCON_MCA_AVI_IF_HANDLED)
> +		DRM_DEBUG_KMS("AVI IF handled by FW\n");
> +
> +	return true;
> +}
> +
> +void lspcon_write_infoframe(struct drm_encoder *encoder,
> +				  const struct intel_crtc_state *crtc_state,
> +				  union hdmi_infoframe *frame)
> +{
> +	bool ret;
> +	ssize_t len;
> +	uint8_t buf[VIDEO_DIP_DATA_SIZE];
> +	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> +	struct intel_lspcon *lspcon = enc_to_intel_lspcon(encoder);
> +
> +	len = hdmi_infoframe_pack(frame, buf, sizeof(buf));
> +	if (len < 0) {
> +		DRM_ERROR("Failed to pack AVI IF\n");
> +		return;
> +	}
> +
> +	if (lspcon->vendor == LSPCON_VENDOR_MCA)
> +		ret = _lspcon_write_infoframe_mca(&intel_dp->aux, buf, len);
> +	else
> +		ret = _lspcon_write_infoframe_parade(&intel_dp->aux, buf, len);
> +
> +	if (!ret)
> +		DRM_ERROR("Failed to write AVI infoframes\n");
> +	else
> +		DRM_DEBUG_DRIVER("AVI infoframes updated successfully\n");
> +}
> +
>  void lspcon_resume(struct intel_lspcon *lspcon)
>  {
>  	enum drm_lspcon_mode expected_mode;
> @@ -282,6 +455,7 @@ bool lspcon_init(struct intel_digital_port *intel_dig_port)
>  
>  	connector->ycbcr_420_allowed = true;
>  	lspcon->set_infoframes = intel_ddi_set_avi_infoframe;
> +	lspcon->write_infoframe = lspcon_write_infoframe;
>  	drm_dp_read_desc(&dp->aux, &dp->desc, drm_dp_is_branch(dp->dpcd));
>  
>  	DRM_DEBUG_KMS("Success: LSPCON init\n");
> -- 
> 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] 76+ messages in thread

* Re: [PATCH 19/20] drm/i915: Move AVI infoframe function to DDI layer
  2017-07-12 17:15   ` Ville Syrjälä
@ 2017-07-13  4:58     ` Sharma, Shashank
  2017-07-13 13:10       ` Ville Syrjälä
  0 siblings, 1 reply; 76+ messages in thread
From: Sharma, Shashank @ 2017-07-13  4:58 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, dri-devel

Thanks for the review, Ville.

My comments, inline.

Regards
Shashank
On 7/12/2017 10:45 PM, Ville Syrjälä wrote:
> On Mon, Jul 10, 2017 at 04:48:47PM +0530, Shashank Sharma wrote:
>> We have an existing function to prepare AVI infoframes for HDMI,
>> this patch moves that function from HDMI layer, to DDI layer, so
>> that we can reuse the function for DP(LSPCON) displays too.
>>
>> This patch:
>> - Moves the intel_hdmi_set_avi_infoframes function in ddi layer.
>> - Adds code to accommodate LSPCON in the same function.
>> - Links this function as AVI infoframe setup function for LSPCON.
>>
>> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> Cc: Imre Deak <imre.deak@intel.com>
>> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
>> ---
>>   drivers/gpu/drm/i915/intel_ddi.c    | 89 ++++++++++++++++++++++++++++++++++---
>>   drivers/gpu/drm/i915/intel_drv.h    |  9 ++++
>>   drivers/gpu/drm/i915/intel_hdmi.c   | 52 +++-------------------
>>   drivers/gpu/drm/i915/intel_lspcon.c |  1 +
>>   4 files changed, 99 insertions(+), 52 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
>> index 80e96f1..f691710 100644
>> --- a/drivers/gpu/drm/i915/intel_ddi.c
>> +++ b/drivers/gpu/drm/i915/intel_ddi.c
>> @@ -2003,8 +2003,76 @@ static void intel_ddi_clk_select(struct intel_encoder *encoder,
>>   	}
>>   }
>>   
>> +void intel_ddi_set_avi_infoframe(struct drm_encoder *encoder,
>> +				  const struct intel_crtc_state *crtc_state)
> NAK. Please look at my 'move infoframe stuff into intel_dig_port' series
> if you need infoframes with DP. IIRC you already reviewed part of that.
Oh, looks like we were thinking in the same direction :).
Sure, I will look for the whole patch series, and will re-use that code 
in LSPCON/DP AVI IF series.
Also, do let me know if you need review for those !

- Shashank
>> +{
>> +	int ret;
>> +	union hdmi_infoframe frame;
>> +	struct drm_connector *connector;
>> +	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
>> +	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
>> +	const struct drm_display_mode *adjusted_mode =
>> +					&crtc_state->base.adjusted_mode;
>> +	enum intel_output_type type = to_intel_encoder(encoder)->type;
>> +	bool is_hdmi2_sink = false;
>> +	bool rgb_qrange_selectable = false;
>> +	enum hdmi_colorspace colorspace = crtc_state->ycbcr420 ?
>> +					  HDMI_COLORSPACE_YUV420 :
>> +					  HDMI_COLORSPACE_RGB;
>> +	bool rgb_qrange_limited =  crtc_state->limited_color_range ?
>> +					HDMI_QUANTIZATION_RANGE_LIMITED :
>> +					HDMI_QUANTIZATION_RANGE_FULL;
>> +
>> +	switch (type) {
>> +	case INTEL_OUTPUT_HDMI:
>> +		connector = &intel_hdmi->attached_connector->base;
>> +		is_hdmi2_sink = connector->display_info.hdmi.scdc.supported;
>> +		rgb_qrange_selectable = intel_hdmi->rgb_quant_range_selectable;
>> +		break;
>> +
>> +	case INTEL_OUTPUT_DP:
>> +		/* We are here means its a LSPCON device, still be paranoid */
>> +		if (!crtc_state->lspcon_active) {
>> +			DRM_ERROR("No LSPCON, why am I here ?\n");
>> +			return;
>> +		}
>> +
>> +		connector = &intel_dp->attached_connector->base;
>> +		is_hdmi2_sink = connector->display_info.hdmi.scdc.supported;
>> +		if (crtc_state->ycbcr420)
>> +			rgb_qrange_limited = true;
>> +		break;
>> +
>> +	default:
>> +		DRM_ERROR("No other encoder allowed\n");
>> +		return;
>> +	}
>> +
>> +	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
>> +						       adjusted_mode,
>> +						       is_hdmi2_sink);
>> +	if (ret < 0) {
>> +		DRM_ERROR("couldn't fill AVI infoframe\n");
>> +		return;
>> +	}
>> +
>> +	ret = drm_hdmi_avi_infoframe_set_colorspace(&frame.avi,
>> +						    adjusted_mode,
>> +						    colorspace);
>> +	if (ret < 0) {
>> +		DRM_ERROR("couldn't fill AVI colorspace\n");
>> +		return;
>> +	}
>> +
>> +	drm_hdmi_avi_infoframe_quant_range(&frame.avi, adjusted_mode,
>> +					   rgb_qrange_limited,
>> +					   rgb_qrange_selectable);
>> +
>> +	intel_write_infoframe(encoder, crtc_state, &frame);
>> +}
>> +
>>   static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder,
>> -				    int link_rate, uint32_t lane_count,
>> +				    const struct intel_crtc_state *pipe_config,
>>   				    struct intel_shared_dpll *pll,
>>   				    bool link_mst)
>>   {
>> @@ -2012,6 +2080,8 @@ static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder,
>>   	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>>   	enum port port = intel_ddi_get_encoder_port(encoder);
>>   	struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base);
>> +	int link_rate = pipe_config->port_clock;
>> +	uint32_t lane_count = pipe_config->lane_count;
>>   
>>   	WARN_ON(link_mst && (port == PORT_A || port == PORT_E));
>>   
>> @@ -2030,6 +2100,14 @@ static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder,
>>   	intel_dp_start_link_train(intel_dp);
>>   	if (port != PORT_A || INTEL_GEN(dev_priv) >= 9)
>>   		intel_dp_stop_link_train(intel_dp);
>> +
>> +	if (pipe_config->lspcon_active) {
>> +		struct drm_encoder *drm_encoder = &encoder->base;
>> +		struct intel_lspcon *lspcon = enc_to_intel_lspcon(drm_encoder);
>> +
>> +		if (lspcon->set_infoframes)
>> +			lspcon->set_infoframes(&encoder->base, pipe_config);
>> +	}
>>   }
>>   
>>   static void intel_ddi_pre_enable_hdmi(struct intel_encoder *encoder,
>> @@ -2072,8 +2150,7 @@ static void intel_ddi_pre_enable(struct intel_encoder *encoder,
>>   
>>   	if (type == INTEL_OUTPUT_DP || type == INTEL_OUTPUT_EDP) {
>>   		intel_ddi_pre_enable_dp(encoder,
>> -					pipe_config->port_clock,
>> -					pipe_config->lane_count,
>> +					pipe_config,
>>   					pipe_config->shared_dpll,
>>   					intel_crtc_has_type(pipe_config,
>>   							    INTEL_OUTPUT_DP_MST));
>> @@ -2628,17 +2705,17 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
>>   	}
>>   
>>   	if (init_lspcon) {
>> -		if (lspcon_init(intel_dig_port))
>> -			/* TODO: handle hdmi info frame part */
>> +		if (lspcon_init(intel_dig_port)) {
>>   			DRM_DEBUG_KMS("LSPCON init success on port %c\n",
>>   				port_name(port));
>> -		else
>> +		} else {
>>   			/*
>>   			 * LSPCON init faied, but DP init was success, so
>>   			 * lets try to drive as DP++ port.
>>   			 */
>>   			DRM_ERROR("LSPCON init failed on port %c\n",
>>   				port_name(port));
>> +		}
>>   	}
>>   
>>   	return;
>> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
>> index 40d56f2..fad9a53 100644
>> --- a/drivers/gpu/drm/i915/intel_drv.h
>> +++ b/drivers/gpu/drm/i915/intel_drv.h
>> @@ -1075,6 +1075,10 @@ struct intel_lspcon {
>>   	bool active;
>>   	enum drm_lspcon_mode mode;
>>   	enum lspcon_vendor vendor;
>> +
>> +	/* AVI IF setup function for LSPCON */
>> +	void (*set_infoframes)(struct drm_encoder *encoder,
>> +				const struct intel_crtc_state *crtc_state);
>>   };
>>   
>>   struct intel_digital_port {
>> @@ -1320,6 +1324,8 @@ u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder);
>>   
>>   unsigned int intel_fb_align_height(const struct drm_framebuffer *fb,
>>   				   int plane, unsigned int height);
>> +void intel_ddi_set_avi_infoframe(struct drm_encoder *encoder,
>> +				 const struct intel_crtc_state *crtc_state);
>>   
>>   /* intel_audio.c */
>>   void intel_init_audio_hooks(struct drm_i915_private *dev_priv);
>> @@ -1690,6 +1696,9 @@ void intel_hdmi_handle_sink_scrambling(struct intel_encoder *intel_encoder,
>>   				       struct drm_connector *connector,
>>   				       bool high_tmds_clock_ratio,
>>   				       bool scrambling);
>> +void intel_write_infoframe(struct drm_encoder *encoder,
>> +			    const struct intel_crtc_state *crtc_state,
>> +			    union hdmi_infoframe *frame);
>>   void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable);
>>   bool intel_hdmi_ycbcr420_config(struct drm_connector *connector,
>>   				struct intel_crtc_state *config,
>> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
>> index a08ab99..7cab86a 100644
>> --- a/drivers/gpu/drm/i915/intel_hdmi.c
>> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
>> @@ -430,7 +430,7 @@ static bool hsw_infoframe_enabled(struct drm_encoder *encoder,
>>    * trick them by giving an offset into the buffer and moving back the header
>>    * bytes by one.
>>    */
>> -static void intel_write_infoframe(struct drm_encoder *encoder,
>> +void intel_write_infoframe(struct drm_encoder *encoder,
>>   				  const struct intel_crtc_state *crtc_state,
>>   				  union hdmi_infoframe *frame)
>>   {
>> @@ -453,46 +453,6 @@ static void intel_write_infoframe(struct drm_encoder *encoder,
>>   	intel_hdmi->write_infoframe(encoder, crtc_state, frame->any.type, buffer, len);
>>   }
>>   
>> -static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder,
>> -					 const struct intel_crtc_state *crtc_state)
>> -{
>> -	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;
>> -	enum hdmi_colorspace colorspace = HDMI_COLORSPACE_RGB;
>> -	union hdmi_infoframe frame;
>> -	int ret;
>> -
>> -	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
>> -						       adjusted_mode,
>> -						       is_hdmi2_sink);
>> -	if (ret < 0) {
>> -		DRM_ERROR("couldn't fill AVI infoframe\n");
>> -		return;
>> -	}
>> -
>> -	if (crtc_state->ycbcr420)
>> -		colorspace = HDMI_COLORSPACE_YUV420;
>> -
>> -	ret = drm_hdmi_avi_infoframe_set_colorspace(&frame.avi,
>> -						    adjusted_mode,
>> -						    colorspace);
>> -	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 :
>> -					   HDMI_QUANTIZATION_RANGE_FULL,
>> -					   intel_hdmi->rgb_quant_range_selectable);
>> -
>> -	intel_write_infoframe(encoder, crtc_state, &frame);
>> -}
>> -
>>   static void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder,
>>   					 const struct intel_crtc_state *crtc_state)
>>   {
>> @@ -582,7 +542,7 @@ static void g4x_set_infoframes(struct drm_encoder *encoder,
>>   	I915_WRITE(reg, val);
>>   	POSTING_READ(reg);
>>   
>> -	intel_hdmi_set_avi_infoframe(encoder, crtc_state);
>> +	intel_ddi_set_avi_infoframe(encoder, crtc_state);
>>   	intel_hdmi_set_spd_infoframe(encoder, crtc_state);
>>   	intel_hdmi_set_hdmi_infoframe(encoder, crtc_state);
>>   }
>> @@ -723,7 +683,7 @@ static void ibx_set_infoframes(struct drm_encoder *encoder,
>>   	I915_WRITE(reg, val);
>>   	POSTING_READ(reg);
>>   
>> -	intel_hdmi_set_avi_infoframe(encoder, crtc_state);
>> +	intel_ddi_set_avi_infoframe(encoder, crtc_state);
>>   	intel_hdmi_set_spd_infoframe(encoder, crtc_state);
>>   	intel_hdmi_set_hdmi_infoframe(encoder, crtc_state);
>>   }
>> @@ -766,7 +726,7 @@ static void cpt_set_infoframes(struct drm_encoder *encoder,
>>   	I915_WRITE(reg, val);
>>   	POSTING_READ(reg);
>>   
>> -	intel_hdmi_set_avi_infoframe(encoder, crtc_state);
>> +	intel_ddi_set_avi_infoframe(encoder, crtc_state);
>>   	intel_hdmi_set_spd_infoframe(encoder, crtc_state);
>>   	intel_hdmi_set_hdmi_infoframe(encoder, crtc_state);
>>   }
>> @@ -819,7 +779,7 @@ static void vlv_set_infoframes(struct drm_encoder *encoder,
>>   	I915_WRITE(reg, val);
>>   	POSTING_READ(reg);
>>   
>> -	intel_hdmi_set_avi_infoframe(encoder, crtc_state);
>> +	intel_ddi_set_avi_infoframe(encoder, crtc_state);
>>   	intel_hdmi_set_spd_infoframe(encoder, crtc_state);
>>   	intel_hdmi_set_hdmi_infoframe(encoder, crtc_state);
>>   }
>> @@ -852,7 +812,7 @@ static void hsw_set_infoframes(struct drm_encoder *encoder,
>>   	I915_WRITE(reg, val);
>>   	POSTING_READ(reg);
>>   
>> -	intel_hdmi_set_avi_infoframe(encoder, crtc_state);
>> +	intel_ddi_set_avi_infoframe(encoder, crtc_state);
>>   	intel_hdmi_set_spd_infoframe(encoder, crtc_state);
>>   	intel_hdmi_set_hdmi_infoframe(encoder, crtc_state);
>>   }
>> diff --git a/drivers/gpu/drm/i915/intel_lspcon.c b/drivers/gpu/drm/i915/intel_lspcon.c
>> index f611b6d..53ddd39 100644
>> --- a/drivers/gpu/drm/i915/intel_lspcon.c
>> +++ b/drivers/gpu/drm/i915/intel_lspcon.c
>> @@ -281,6 +281,7 @@ bool lspcon_init(struct intel_digital_port *intel_dig_port)
>>   	}
>>   
>>   	connector->ycbcr_420_allowed = true;
>> +	lspcon->set_infoframes = intel_ddi_set_avi_infoframe;
>>   	drm_dp_read_desc(&dp->aux, &dp->desc, drm_dp_is_branch(dp->dpcd));
>>   
>>   	DRM_DEBUG_KMS("Success: LSPCON init\n");
>> -- 
>> 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] 76+ messages in thread

* Re: [PATCH 18/20] drm/i915: YCBCR 420 support for LSPCON
  2017-07-12 17:15   ` Ville Syrjälä
@ 2017-07-13  5:02     ` Sharma, Shashank
  2017-07-13 13:13       ` Ville Syrjälä
  0 siblings, 1 reply; 76+ messages in thread
From: Sharma, Shashank @ 2017-07-13  5:02 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, dri-devel

Regards

Shashank


On 7/12/2017 10:45 PM, Ville Syrjälä wrote:
> On Mon, Jul 10, 2017 at 04:48:46PM +0530, Shashank Sharma wrote:
>> LSPCON chips support YCBCR420 outputs. To be able to get
>> YCBCR420 output from LSPCON chip, the source should:
>> - Generate YCBCR444 HDMI output
>> - Set AVI infoframes for a YCBCR420 output.
>>
>> LSPCON FW gets the information from AVI infoframes, and generates
>> YCBCR420 output from a YCBCR444 input. This patch adds the necessary
>> changes to drive YCBCR420 output from LSPCON based HDMI output.
>>
>> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> Cc: Imre Deak <imre.deak@intel.com>
>> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
>> ---
>>   drivers/gpu/drm/i915/intel_display.c | 10 +++++++---
>>   drivers/gpu/drm/i915/intel_dp.c      | 16 +++++++++++++++-
>>   drivers/gpu/drm/i915/intel_drv.h     | 20 +++++++++++++++++---
>>   drivers/gpu/drm/i915/intel_hdmi.c    |  7 +++++--
>>   drivers/gpu/drm/i915/intel_lspcon.c  | 17 +++++++++++++++++
>>   5 files changed, 61 insertions(+), 9 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
>> index c5ff568..c3c7b31 100644
>> --- a/drivers/gpu/drm/i915/intel_display.c
>> +++ b/drivers/gpu/drm/i915/intel_display.c
>> @@ -8125,9 +8125,11 @@ static void haswell_set_pipemisc(struct drm_crtc *crtc)
>>   			val |= PIPEMISC_DITHER_ENABLE | PIPEMISC_DITHER_TYPE_SP;
>>   
>>   		if (config->ycbcr420) {
>> -			val |= PIPEMISC_OUTPUT_YCBCR |
>> -				PIPEMISC_YCBCR420_ENABLE |
>> -				PIPEMISC_YCBCR420_MODE_BLEND;
>> +			val |= PIPEMISC_OUTPUT_YCBCR;
>> +
>> +			if (!config->lspcon_active)
>> +				val |= PIPEMISC_YCBCR420_ENABLE |
>> +					PIPEMISC_YCBCR420_MODE_BLEND;
>>   		}
>>   
>>   		I915_WRITE(PIPEMISC(intel_crtc->pipe), val);
>> @@ -14205,11 +14207,13 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)
>>   		 * DDI_BUF_CTL_A or SFUSE_STRAP registers, find another way to
>>   		 * detect the ports.
>>   		 */
>> +
>>   		intel_ddi_init(dev_priv, PORT_A);
>>   		intel_ddi_init(dev_priv, PORT_B);
>>   		intel_ddi_init(dev_priv, PORT_C);
>>   
>>   		intel_dsi_init(dev_priv);
>> +
>>   	} else if (HAS_DDI(dev_priv)) {
>>   		int found;
>>   
>> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
>> index 67bc8a7a..1690aa9 100644
>> --- a/drivers/gpu/drm/i915/intel_dp.c
>> +++ b/drivers/gpu/drm/i915/intel_dp.c
>> @@ -1614,7 +1614,9 @@ intel_dp_compute_config(struct intel_encoder *encoder,
>>   	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>>   	struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
>>   	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
>> -	enum port port = dp_to_dig_port(intel_dp)->port;
>> +	struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base);
>> +	enum port port = dig_port->port;
>> +	struct intel_lspcon *lspcon = &dig_port->lspcon;
>>   	struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->base.crtc);
>>   	struct intel_connector *intel_connector = intel_dp->attached_connector;
>>   	struct intel_digital_connector_state *intel_conn_state =
>> @@ -1635,6 +1637,18 @@ intel_dp_compute_config(struct intel_encoder *encoder,
>>   	common_len = intel_dp_common_len_rate_limit(intel_dp,
>>   						    intel_dp->max_link_rate);
>>   
>> +	/* LSPCON needs special handling to drive YCBCR420 outputs */
>> +	if (lspcon->active) {
>> +		struct drm_connector *connector = &intel_connector->base;
>> +		int clock_8bpc = pipe_config->base.adjusted_mode.crtc_clock;
>> +		int clock_12bpc = clock_8bpc * 3 / 2;
>> +
>> +		pipe_config->lspcon_active = true;
>> +		pipe_config->ycbcr420 = lspcon_ycbcr420_config(connector,
>> +					     pipe_config, &clock_12bpc,
>> +					     &clock_8bpc);
> All this clock stuff here seems pointless. So I'd just replace this
> stuff with the straightforward 'pipe_config->ycbcr420 = mode_needs_420';
pipe_config->ycbcr_420 = true means we have committed into state that we 
can support this mode in YCBCR420.
But for that, we need to check connector->ycbcr420_allowed too.
Also, when the mode is 420, we need to half the clock_8bpc and clock_12bpc.

This whole stuff is happening into lspcon_ycbcr420_config function 
(which internally re-use hdmi_ycncr420_config from HDMI 2.0 series).
That's why the call is important.
>> +	}
>> +
>>   	/* No common link rates between source and sink */
>>   	WARN_ON(common_len <= 0);
>>   
>> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
>> index ed04de9..40d56f2 100644
>> --- a/drivers/gpu/drm/i915/intel_drv.h
>> +++ b/drivers/gpu/drm/i915/intel_drv.h
>> @@ -790,6 +790,9 @@ struct intel_crtc_state {
>>   
>>   	/* HDMI output type */
>>   	bool ycbcr420;
>> +
>> +	/* LSPCON is active on port */
>> +	bool lspcon_active;
>>   };
>>   
>>   struct intel_crtc {
>> @@ -1205,6 +1208,12 @@ static inline struct intel_dp *enc_to_intel_dp(struct drm_encoder *encoder)
>>   	return &enc_to_dig_port(encoder)->dp;
>>   }
>>   
>> +static inline struct intel_lspcon *
>> +enc_to_intel_lspcon(struct drm_encoder *encoder)
>> +{
>> +	return &enc_to_dig_port(encoder)->lspcon;
>> +}
>> +
>>   static inline struct intel_digital_port *
>>   dp_to_dig_port(struct intel_dp *intel_dp)
>>   {
>> @@ -1675,14 +1684,16 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
>>   			       struct intel_connector *intel_connector);
>>   struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder);
>>   bool intel_hdmi_compute_config(struct intel_encoder *encoder,
>> -			       struct intel_crtc_state *pipe_config,
>> -			       struct drm_connector_state *conn_state);
>> +				struct intel_crtc_state *pipe_config,
>> +				struct drm_connector_state *conn_state);
>>   void intel_hdmi_handle_sink_scrambling(struct intel_encoder *intel_encoder,
>>   				       struct drm_connector *connector,
>>   				       bool high_tmds_clock_ratio,
>>   				       bool scrambling);
>>   void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable);
>> -
>> +bool intel_hdmi_ycbcr420_config(struct drm_connector *connector,
>> +				struct intel_crtc_state *config,
>> +				int *clock_12bpc, int *clock_8bpc);
>>   
>>   /* intel_lvds.c */
>>   void intel_lvds_init(struct drm_i915_private *dev_priv);
>> @@ -2003,6 +2014,9 @@ void intel_color_load_luts(struct drm_crtc_state *crtc_state);
>>   bool lspcon_init(struct intel_digital_port *intel_dig_port);
>>   void lspcon_resume(struct intel_lspcon *lspcon);
>>   void lspcon_wait_pcon_mode(struct intel_lspcon *lspcon);
>> +bool lspcon_ycbcr420_config(struct drm_connector *connector,
>> +			    struct intel_crtc_state *config,
>> +			    int *clock_12bpc, int *clock_8bpc);
>>   
>>   /* intel_pipe_crc.c */
>>   int intel_pipe_crc_create(struct drm_minor *minor);
>> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
>> index d1b1efc..a08ab99 100644
>> --- a/drivers/gpu/drm/i915/intel_hdmi.c
>> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
>> @@ -1362,8 +1362,7 @@ static bool hdmi_12bpc_possible(struct intel_crtc_state *crtc_state,
>>   	return true;
>>   }
>>   
>> -static bool
>> -intel_hdmi_ycbcr420_config(struct drm_connector *connector,
>> +bool intel_hdmi_ycbcr420_config(struct drm_connector *connector,
>>   			       struct intel_crtc_state *config,
>>   			       int *clock_12bpc, int *clock_8bpc)
>>   {
>> @@ -1380,6 +1379,10 @@ intel_hdmi_ycbcr420_config(struct drm_connector *connector,
>>   	*clock_8bpc /= 2;
>>   	config->ycbcr420 = true;
>>   
>> +	/* LSPCON doesn't need scaler for YCBCR420 output */
>> +	if (config->lspcon_active)
>> +		return true;
>> +
>>   	/* YCBCR 420 output conversion needs a scaler */
>>   	if (skl_update_scaler_crtc_420_output(config)) {
>>   		DRM_ERROR("Scaler allocation for output failed\n");
>> diff --git a/drivers/gpu/drm/i915/intel_lspcon.c b/drivers/gpu/drm/i915/intel_lspcon.c
>> index a350d79..f611b6d 100644
>> --- a/drivers/gpu/drm/i915/intel_lspcon.c
>> +++ b/drivers/gpu/drm/i915/intel_lspcon.c
>> @@ -202,6 +202,21 @@ static void lspcon_resume_in_pcon_wa(struct intel_lspcon *lspcon)
>>   	DRM_DEBUG_KMS("LSPCON DP descriptor mismatch after resume\n");
>>   }
>>   
>> +bool lspcon_ycbcr420_config(struct drm_connector *connector,
>> +			    struct intel_crtc_state *config,
>> +			    int *clock_12bpc, int *clock_8bpc)
>> +{
>> +	struct drm_display_info *info = &connector->display_info;
>> +	struct drm_display_mode *mode = &config->base.adjusted_mode;
>> +
>> +	if (drm_mode_is_420_only(info, mode)) {
>> +		return intel_hdmi_ycbcr420_config(connector, config,
>> +					  clock_12bpc, clock_8bpc);
>> +	}
>> +
>> +	return false;
>> +}
>> +
>>   void lspcon_resume(struct intel_lspcon *lspcon)
>>   {
>>   	enum drm_lspcon_mode expected_mode;
>> @@ -233,6 +248,7 @@ bool lspcon_init(struct intel_digital_port *intel_dig_port)
>>   	struct intel_lspcon *lspcon = &intel_dig_port->lspcon;
>>   	struct drm_device *dev = intel_dig_port->base.base.dev;
>>   	struct drm_i915_private *dev_priv = to_i915(dev);
>> +	struct drm_connector *connector = &dp->attached_connector->base;
>>   
>>   	if (!IS_GEN9(dev_priv)) {
>>   		DRM_ERROR("LSPCON is supported on GEN9 only\n");
>> @@ -264,6 +280,7 @@ bool lspcon_init(struct intel_digital_port *intel_dig_port)
>>   		return false;
>>   	}
>>   
>> +	connector->ycbcr_420_allowed = true;
>>   	drm_dp_read_desc(&dp->aux, &dp->desc, drm_dp_is_branch(dp->dpcd));
>>   
>>   	DRM_DEBUG_KMS("Success: LSPCON init\n");
>> -- 
>> 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] 76+ messages in thread

* Re: [PATCH 16/20] drm: add function to read vendor OUI
  2017-07-12 17:15   ` Ville Syrjälä
@ 2017-07-13  5:04     ` Sharma, Shashank
  2017-07-13 12:37       ` Ville Syrjälä
  0 siblings, 1 reply; 76+ messages in thread
From: Sharma, Shashank @ 2017-07-13  5:04 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, dri-devel

Regads

Shashank


On 7/12/2017 10:45 PM, Ville Syrjälä wrote:
> On Mon, Jul 10, 2017 at 04:48:44PM +0530, Shashank Sharma wrote:
>> This patch adds a helper function in DP dual mode layer to
>> read the vendor's IEEE OUI signature from a Dual mode adapter.
>> This will be used to differentiate between different LSPCON
>> vendors, to address their custom programming requirements.
> Can't we just read it from DPCD instead?
You are right, as we have DPCD cached, we can do it from DPCD too, and 
in fact that was my first implementation.
But then I thought what if some driver doesn't cache DPCD, so thought it 
would be good to have a helper function
to check this out.
If you think DPCD would be a better idea, I need not to touch DRM layer 
at all, and this will be only I915 implementation.

- Shashank
>
>> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> Cc: Imre Deak <imre.deak@intel.com>
>> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
>> ---
>>   drivers/gpu/drm/drm_dp_dual_mode_helper.c | 24 ++++++++++++++++++++++++
>>   include/drm/drm_dp_dual_mode_helper.h     |  4 +++-
>>   2 files changed, 27 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/drm_dp_dual_mode_helper.c b/drivers/gpu/drm/drm_dp_dual_mode_helper.c
>> index 80e62f6..0b890dc 100644
>> --- a/drivers/gpu/drm/drm_dp_dual_mode_helper.c
>> +++ b/drivers/gpu/drm/drm_dp_dual_mode_helper.c
>> @@ -396,6 +396,30 @@ const char *drm_dp_get_dual_mode_type_name(enum drm_dp_dual_mode_type type)
>>   EXPORT_SYMBOL(drm_dp_get_dual_mode_type_name);
>>   
>>   /**
>> + * drm_lspcon_get_vendor_oui: match vendor OUI signature
>> + * @adapter: i2c adapter under action
>> + * @vendor_id = 3 bytes of vendor OUI signature, LSB=lower byte
>> + *
>> + * Returns:
>> + * Vendor OUI id if got one, 0 if not
>> + */
>> +uint32_t drm_lspcon_get_vendor_oui(struct i2c_adapter *adapter)
>> +{
>> +	uint8_t sign[3] = {0, };
>> +	uint32_t oui = 0;
>> +
>> +	if (drm_dp_dual_mode_read(adapter, DP_DUAL_MODE_LSPCON_OUI_OFFSET,
>> +						sign, 3)) {
>> +		DRM_ERROR("Can't identify vendor sign\n");
>> +		return 0;
>> +	}
>> +
>> +	oui = (sign[0] << 16) | (sign[1] << 8) | sign[2];
>> +	return oui;
>> +}
>> +EXPORT_SYMBOL(drm_lspcon_get_vendor_oui);
>> +
>> +/**
>>    * drm_lspcon_get_mode: Get LSPCON's current mode of operation by
>>    * reading offset (0x80, 0x41)
>>    * @adapter: I2C-over-aux adapter
>> diff --git a/include/drm/drm_dp_dual_mode_helper.h b/include/drm/drm_dp_dual_mode_helper.h
>> index 4c42db8..f81b526 100644
>> --- a/include/drm/drm_dp_dual_mode_helper.h
>> +++ b/include/drm/drm_dp_dual_mode_helper.h
>> @@ -60,7 +60,8 @@
>>   /* LSPCON specific registers, defined by MCA */
>>   #define DP_DUAL_MODE_LSPCON_MODE_CHANGE		0x40
>>   #define DP_DUAL_MODE_LSPCON_CURRENT_MODE		0x41
>> -#define  DP_DUAL_MODE_LSPCON_MODE_PCON			0x1
>> +#define DP_DUAL_MODE_LSPCON_MODE_PCON			0x1
>> +#define DP_DUAL_MODE_LSPCON_OUI_OFFSET			0x11
>>   
>>   struct i2c_adapter;
>>   
>> @@ -116,4 +117,5 @@ int drm_lspcon_get_mode(struct i2c_adapter *adapter,
>>   			enum drm_lspcon_mode *current_mode);
>>   int drm_lspcon_set_mode(struct i2c_adapter *adapter,
>>   			enum drm_lspcon_mode reqd_mode);
>> +uint32_t drm_lspcon_get_vendor_oui(struct i2c_adapter *adapter);
>>   #endif
>> -- 
>> 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] 76+ messages in thread

* Re: [PATCH 08/20] drm: set output colorspace in AVI infoframe
  2017-07-12 17:17   ` Ville Syrjälä
@ 2017-07-13  5:07     ` Sharma, Shashank
  2017-07-13 12:35       ` Ville Syrjälä
  0 siblings, 1 reply; 76+ messages in thread
From: Sharma, Shashank @ 2017-07-13  5:07 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, dri-devel

Regards

Shashank


On 7/12/2017 10:47 PM, Ville Syrjälä wrote:
> On Mon, Jul 10, 2017 at 04:48:36PM +0530, Shashank Sharma wrote:
>> A source must set output colorspace information in AVI
>> infoframes, so that the sink can decode upcoming frames
>> accordingly.
>>
>> This patch adds a function to add the output colorspace
>> information in the AVI infoframes.
>>
>> V2: Rebase
>> V3: Rebase
>> V4: Rebase
>> V5: Rebase
>> V6: Made patch independent of HDMI output type.
>>
>> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
>> ---
>>   drivers/gpu/drm/drm_edid.c | 29 +++++++++++++++++++++++++++++
>>   include/drm/drm_edid.h     |  5 +++++
>>   2 files changed, 34 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
>> index 944a28f..cede86e 100644
>> --- a/drivers/gpu/drm/drm_edid.c
>> +++ b/drivers/gpu/drm/drm_edid.c
>> @@ -4796,6 +4796,35 @@ 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 hdmi_colorspace colorspace)
>> +{
>> +	if (colorspace > HDMI_COLORSPACE_YUV420 ||
>> +		colorspace < HDMI_COLORSPACE_RGB) {
>> +		DRM_ERROR("Invalid color space type\n");
>> +		return -EINVAL;
>> +	}
> Seems overly defensive. I'd say that if someone insists on writing
> buggy code just let them do it.
:) yep can be done, you know, its a new implementation, don't want to 
create unnecessary noise so being
a bit defensive :)
>> +
>> +	frame->colorspace = colorspace;
>> +	if (colorspace == HDMI_COLORSPACE_YUV420)
>> +		frame->pixel_repeat = 0;
> Most VICs don't allow pixel repeat in 444/etc. either, and we don't
> protect against that. So this looks like pretty pointless check in
> this form.
>
> So IMO just drop this entire patch and just assign frame->colorspace in
> the driver.
Actually YCBCR420 section of spec specifically calls out for not 
allowing repetition, also, when I tested this on a
HDMI 2.0 analyzer, if was giving a AVI IF failure on pixel_repeat not 0, 
so IMHO it would be a good idea to keep
this and get the tests passing.

- Shashank
>> +
>> +	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 aa58146..b79e0cb 100644
>> --- a/include/drm/drm_edid.h
>> +++ b/include/drm/drm_edid.h
>> @@ -332,6 +332,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);
>> @@ -354,6 +355,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 hdmi_colorspace colorspace);
>> +int
>>   drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame,
>>   					    const struct drm_display_mode *mode);
>>   void
>> -- 
>> 2.7.4
>>
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel@lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

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

* Re: [PATCH 13/20] drm/i915: prepare csc unit for YCBCR420 output
  2017-07-12 17:17   ` Ville Syrjälä
@ 2017-07-13  5:14     ` Sharma, Shashank
  2017-07-13 12:50       ` Ville Syrjälä
  0 siblings, 1 reply; 76+ messages in thread
From: Sharma, Shashank @ 2017-07-13  5:14 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, dri-devel

Regards

Shashank


On 7/12/2017 10:47 PM, Ville Syrjälä wrote:
> On Mon, Jul 10, 2017 at 04:48:41PM +0530, Shashank Sharma wrote:
>> To support ycbcr output, we need a pipe CSC block to do
>> RGB->YCBCR conversion.
>>
>> 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, which uses recommended bspec
>> values to perform RGB->YCBCR conversion (target color space BT709)
>>
>> V2: Rebase
>> V3: Rebase
>> V4: Rebase
>> V5: Addressed review comments from Ander
>>      - Remove extra line added in the patch
>>      - Add the spec details in the commit message
>>      - Combine two if(cond) while calling intel_crtc_compute_config
>> V6: Handle YCBCR420 outputs only (Ville)
>>
>> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
>> ---
>>   drivers/gpu/drm/i915/intel_color.c   | 47 +++++++++++++++++++++++++++++++++++-
>>   drivers/gpu/drm/i915/intel_display.c | 17 +++++++++++++
>>   2 files changed, 63 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/i915/intel_color.c b/drivers/gpu/drm/i915/intel_color.c
>> index 306c6b0..8a5d211 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 */
> Are these BT.601 or BT.709 or something else?
I thought I added some comment mentioning this being BT 709, but looks 
like dealing with too many paptches :)
Will add those details.
>> +#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
> IIRC Ander didn't like these, and neither do I. I'd much prefer to reuse
> the code we alreayd have for dealing with the CSC. Except I think that's
> pretty broken in places so I guess we can go with this for now and try
> to clean up the color management stuff later.
Yes, that was the plan. I was planning to fix the complete CSC cleanup 
stuff in a separate patch, but as that needs much
of validation before we can merge it, I added in a bottom half. I will 
send a patch for the same soon.
>> +
>>   /*
>>    * 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 */
> I don't understand what this comment is trying so say.
Yeah, it should have been "we dont use pre-offsets 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->ycbcr420) {
>> +		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 b4a6415..c5ff568 100644
>> --- a/drivers/gpu/drm/i915/intel_display.c
>> +++ b/drivers/gpu/drm/i915/intel_display.c
>> @@ -6288,6 +6288,23 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
>>   		return -EINVAL;
>>   	}
>>   
>> +	/* YCBCR420 feasibility check */
>> +	if (pipe_config->ycbcr420) {
>> +		struct drm_crtc_state *drm_state = &pipe_config->base;
>> +
>> +		/*
>> +		 * There is only one pipe CSC unit per pipe, and we need that
>> +		 * for output conversion from RGB->YCBCR. So if CTM is already
>> +		 * applied we can't support YCBCR420 output.
>> +		 */
>> +		if (drm_state->ctm) {
>> +			DRM_ERROR("YCBCR420 and CTM is not possible\n");
> DRM_DEBUG_KMS
We are failing an atomic_check(), shouldn't this be highlighted ?
>
>> +			return -EINVAL;
>> +		}
>> +
>> +		DRM_DEBUG_KMS("YCBCR420 output is possible from CRTC\n");
> Seems like a fairly pointless debug print.
Yeah, ok.
- Shashank
>> +	}
>> +
>>   	/*
>>   	 * Pipe horizontal size must be even in:
>>   	 * - DVO ganged mode
>> -- 
>> 2.7.4
>>
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel@lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

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

* Re: [PATCH 11/20] drm/i915: prepare scaler for YCBCR420 modeset
  2017-07-12 17:17   ` Ville Syrjälä
@ 2017-07-13  5:21     ` Sharma, Shashank
  2017-07-13 12:52       ` [Intel-gfx] " Ville Syrjälä
  0 siblings, 1 reply; 76+ messages in thread
From: Sharma, Shashank @ 2017-07-13  5:21 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, dri-devel

Regards

Shashank


On 7/12/2017 10:47 PM, Ville Syrjälä wrote:
> On Mon, Jul 10, 2017 at 04:48:39PM +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
>> V5: addressed review comments from Ander:
>>      - No need to check both scaler_user && hdmi_output.
>>        Check for scaler_user is enough.
>> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
>> ---
>>   drivers/gpu/drm/i915/intel_atomic.c  |  6 ++++++
>>   drivers/gpu/drm/i915/intel_display.c | 23 +++++++++++++++++++++++
>>   drivers/gpu/drm/i915/intel_drv.h     | 10 +++++++++-
>>   drivers/gpu/drm/i915/intel_hdmi.c    | 12 ++++++++++++
>>   drivers/gpu/drm/i915/intel_panel.c   |  3 ++-
>>   5 files changed, 52 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
>> index 36d4e63..040d111 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_420_OUTPUT_INDEX) {
> I think Ander already said that we should just tie this into the normal
> pfit pipe scaler user. I agree. Having to users doesn't actually make
> sense because there can be only one pipe scaler, and if we want to do
> scaled 4:2:0 output then we anyway need to handle both cases
> simultaneosly.
I thought our idea of having a separate scalar user was a good one, 
because, this gives additional information
how and why the scalar is being used. Also, we dont program the other 
scaling factors in this case, but we get
the scaling profile set using PIPEMISC. So I would prefer to have this 
as a special case or separate user, but you
can think about this, and let me know.

- Shashank
>
>> +			name = "YCBCR420-OUTPUT";
>> +			idx = intel_crtc->base.base.id;
>> +
>> +			/* YCBCR420 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 01900e1..c56081e 100644
>> --- a/drivers/gpu/drm/i915/intel_display.c
>> +++ b/drivers/gpu/drm/i915/intel_display.c
>> @@ -4621,6 +4621,9 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
>>   	 */
>>   	need_scaling = src_w != dst_w || src_h != dst_h;
>>   
>> +	if (scaler_user == SKL_420_OUTPUT_INDEX)
>> +		need_scaling = true;
>> +
>>   	/*
>>   	 * if plane is being disabled or scaler is no more required or force detach
>>   	 *  - free scaler binded to this plane/crtc
>> @@ -4668,6 +4671,26 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
>>   }
>>   
>>   /**
>> + * skl_update_scaler_crtc_420_output - Stages update to scaler state
>> + * for YCBCR420 which 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_420_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_420_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
>> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
>> index 592243b..68b4fba 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
>> +
>> +	/*
>> +	 * YCBCR 420 output consume a scaler. So adding a user
>> +	 * for 420 output requirement.
>> +	 */
>> +#define SKL_420_OUTPUT_INDEX 30
>>   	unsigned scaler_users;
>>   
>>   	/* scaler used by crtc for panel fitting purpose */
>> @@ -1483,6 +1490,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_420_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 276d916..9e8d784 100644
>> --- a/drivers/gpu/drm/i915/intel_hdmi.c
>> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
>> @@ -1355,6 +1355,7 @@ intel_hdmi_ycbcr420_config(struct drm_connector *connector,
>>   			       struct intel_crtc_state *config,
>>   			       int *clock_12bpc, int *clock_8bpc)
>>   {
>> +	struct intel_crtc *intel_crtc = to_intel_crtc(config->base.crtc);
>>   
>>   	if (!connector->ycbcr_420_allowed) {
>>   		DRM_ERROR("Platform doesn't support YCBCR420 output\n");
>> @@ -1366,6 +1367,17 @@ intel_hdmi_ycbcr420_config(struct drm_connector *connector,
>>   	*clock_12bpc /= 2;
>>   	*clock_8bpc /= 2;
>>   	config->ycbcr420 = true;
>> +
>> +	/* YCBCR 420 output conversion needs a scaler */
>> +	if (skl_update_scaler_crtc_420_output(config)) {
>> +		DRM_ERROR("Scaler allocation for output failed\n");
>> +		return false;
>> +	}
>> +
>> +	/* Bind this scaler to pipe */
>> +	intel_pch_panel_fitting(intel_crtc, config,
>> +				DRM_MODE_SCALE_FULLSCREEN);
>> +
>>   	return true;
>>   }
>>   
>> diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
>> index 96c2cbd..fd2e081 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->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

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

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

* Re: [PATCH 10/20] drm/i915: add config function for YCBCR420 outputs
  2017-07-12 17:17   ` Ville Syrjälä
@ 2017-07-13  5:26     ` Sharma, Shashank
  2017-07-13 12:53       ` Ville Syrjälä
  0 siblings, 1 reply; 76+ messages in thread
From: Sharma, Shashank @ 2017-07-13  5:26 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, dri-devel

Regards

Shashank


On 7/12/2017 10:47 PM, Ville Syrjälä wrote:
> On Mon, Jul 10, 2017 at 04:48:38PM +0530, Shashank Sharma wrote:
>> This patch checks encoder level support for YCBCR420 outputs.
>> The logic goes as simple as this:
>> If the input mode is YCBCR420-only mode: prepare HDMI for
>> YCBCR420 output, else continue with RGB output mode.
>>
>> It checks if the mode is YCBCR420 and source can support this
>> output then it marks the ycbcr_420 output indicator 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
>> V5: Rebase
>> V6: Check and handle YCBCR420-only modes, discard the property
>>      based approach (Ville)
>>
>> 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    | 42 +++++++++++++++++++++++++++++++++---
>>   3 files changed, 43 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
>> index 4e03ca6..01900e1 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(ycbcr420);
>>   
>>   	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 d17a324..592243b 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 */
>> +	bool ycbcr420;
>>   };
>>   
>>   struct intel_crtc {
>> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
>> index cc0d100..276d916 100644
>> --- a/drivers/gpu/drm/i915/intel_hdmi.c
>> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
>> @@ -1305,7 +1305,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,
>> +				bool output_ycbcr420)
> You alreayd have the crtc state, so no need to pass that stuff
> separately.
Ah, this was dumb, thanks !
>>   {
>>   	struct drm_i915_private *dev_priv =
>>   		to_i915(crtc_state->base.crtc->dev);
>> @@ -1330,6 +1331,13 @@ static bool hdmi_12bpc_possible(struct intel_crtc_state *crtc_state)
>>   		if (connector_state->crtc != crtc_state->base.crtc)
>>   			continue;
>>   
>> +		if (output_ycbcr420) {
>> +			const struct drm_hdmi_info *hdmi = &info->hdmi;
>> +
>> +			if (!(hdmi->y420_dc_modes & DRM_EDID_YCBCR420_DC_36))
>> +				return false;
>> +		}
>> +
> else?
Oops, needs an else { break;}

- Shashank
>
>>   		if ((info->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_36) == 0)
>>   			return false;
>>   	}
>> @@ -1342,6 +1350,25 @@ static bool hdmi_12bpc_possible(struct intel_crtc_state *crtc_state)
>>   	return true;
>>   }
>>   
>> +static bool
>> +intel_hdmi_ycbcr420_config(struct drm_connector *connector,
>> +			       struct intel_crtc_state *config,
>> +			       int *clock_12bpc, int *clock_8bpc)
>> +{
>> +
>> +	if (!connector->ycbcr_420_allowed) {
>> +		DRM_ERROR("Platform doesn't support YCBCR420 output\n");
>> +		return false;
>> +	}
>> +
>> +	/* YCBCR420 TMDS rate requirement is half the pixel clock */
>> +	config->port_clock /= 2;
>> +	*clock_12bpc /= 2;
>> +	*clock_8bpc /= 2;
>> +	config->ycbcr420 = true;
>> +	return true;
>> +}
>> +
>>   bool intel_hdmi_compute_config(struct intel_encoder *encoder,
>>   			       struct intel_crtc_state *pipe_config,
>>   			       struct drm_connector_state *conn_state)
>> @@ -1349,7 +1376,8 @@ 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;
>> @@ -1379,6 +1407,14 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
>>   		clock_12bpc *= 2;
>>   	}
>>   
>> +	if (drm_mode_is_420_only(&connector->display_info, adjusted_mode)) {
>> +		if (!intel_hdmi_ycbcr420_config(connector, pipe_config,
>> +						&clock_12bpc, &clock_8bpc)) {
>> +			DRM_ERROR("Can't support YCBCR420 output\n");
>> +			return false;
>> +		}
>> +	}
>> +
>>   	if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv))
>>   		pipe_config->has_pch_encoder = true;
>>   
>> @@ -1398,7 +1434,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, pipe_config->ycbcr420)) {
>>   		DRM_DEBUG_KMS("picking bpc to 12 for HDMI output\n");
>>   		desired_bpp = 12*3;
>>   
>> -- 
>> 2.7.4
>>
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel@lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

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

* Re: [PATCH 09/20] drm: add helper functions for YCBCR420 handling
  2017-07-12 17:17   ` Ville Syrjälä
@ 2017-07-13  5:27     ` Sharma, Shashank
  0 siblings, 0 replies; 76+ messages in thread
From: Sharma, Shashank @ 2017-07-13  5:27 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, dri-devel

Regards

Shashank


On 7/12/2017 10:47 PM, Ville Syrjälä wrote:
> On Mon, Jul 10, 2017 at 04:48:37PM +0530, Shashank Sharma wrote:
>> This patch adds helper functions for YCBCR 420 handling.
>> These functions do:
>> - check if a given video mode is YCBCR 420 only mode.
>> - check if a given video mode is YCBCR 420 also mode.
>>
>> 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)
>> V5: Addressed review comments from Danvet:
>>      - %s/drm_find_hdmi_output_type/drm_display_info_hdmi_output_type
>>      - %s/drm_can_support_ycbcr_output/drm_display_supports_ycbcr_output
>>      - %s/drm_can_support_this_ycbcr_output/
>> 		drm_display_supports_this_ycbcr_output
>>      - pass drm_display_info instead of drm_connector for consistency
>>      - For drm_get_highest_quality_ycbcr_supported doc, move the variable
>>        description above, and then the function description.
>> V6: Add only YCBCR420 helpers (Ville)
>>
>> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
>> ---
>>   drivers/gpu/drm/drm_modes.c | 74 +++++++++++++++++++++++++++++++++++++++++++++
>>   include/drm/drm_modes.h     |  6 ++++
>>   2 files changed, 80 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
>> index 3b53c8e3..61c82a38 100644
>> --- a/drivers/gpu/drm/drm_modes.c
>> +++ b/drivers/gpu/drm/drm_modes.c
>> @@ -1604,3 +1604,77 @@ 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 be supported in YCBCR420 format
>> + * false if not.
>> + */
>> +bool drm_mode_is_420_only(struct drm_display_info *display,
>> +			struct drm_display_mode *mode)
> Both should be const. Indentation looks busted.
Agree.
>> +{
>> +	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;
> More unnecessary checks.
Ok.
Shashank
>> +
>> +	return test_bit(vic, display->hdmi.y420_vdb_modes);
>> +}
>> +EXPORT_SYMBOL(drm_mode_is_420_only);
>> +
>> +/**
>> + * 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 be support YCBCR420 format
>> + * false if not.
>> + */
>> +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);
>> +}
>> +EXPORT_SYMBOL(drm_mode_is_420_also);
>> +/**
>> + * drm_mode_is_420 - if a given videomode can be supported in YCBCR420
>> + * output format
>> + *
>> + * @display: display under action.
>> + * @mode: video mode to be tested.
>> + *
>> + * Returns:
>> + * true if the mode can be supported in YCBCR420 format
>> + * false if not.
>> + */
>> +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);
>> +}
>> +EXPORT_SYMBOL(drm_mode_is_420);
>> diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h
>> index f8a1268..980db27 100644
>> --- a/include/drm/drm_modes.h
>> +++ b/include/drm/drm_modes.h
>> @@ -452,6 +452,12 @@ int drm_mode_convert_umode(struct drm_display_mode *out,
>>   			   const struct drm_mode_modeinfo *in);
>>   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);
>> +bool drm_mode_is_420_only(struct drm_display_info *display,
>> +			struct drm_display_mode *mode);
>> +bool drm_mode_is_420_also(struct drm_display_info *display,
>> +			struct drm_display_mode *mode);
>> +bool drm_mode_is_420(struct drm_display_info *display,
>> +			struct drm_display_mode *mode);
>>   
>>   struct drm_display_mode *drm_cvt_mode(struct drm_device *dev,
>>   				      int hdisplay, int vdisplay, int vrefresh,
>> -- 
>> 2.7.4
>>
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel@lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

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

* Re: [PATCH 06/20] drm: add helper to validate YCBCR420 modes
  2017-07-12 17:18   ` Ville Syrjälä
@ 2017-07-13  5:32     ` Sharma, Shashank
  2017-07-13 12:31       ` Ville Syrjälä
  0 siblings, 1 reply; 76+ messages in thread
From: Sharma, Shashank @ 2017-07-13  5:32 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, dri-devel

Regards

Shashank


On 7/12/2017 10:48 PM, Ville Syrjälä wrote:
> On Mon, Jul 10, 2017 at 04:48:34PM +0530, Shashank Sharma wrote:
>> YCBCR420 modes are supported only on HDMI 2.0 capable sources.
>> This patch adds:
>> - A drm helper to validate YCBCR420-only mode on a particular
>>    connector. This function will help pruning the YCBCR420-only
>>    modes from the connector's modelist.
>> - 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 YCBCR420 output, so that no
>>    YCBCR 420 modes will be listed for sources which can't handle it.
>>    A driver should set this variable if it wants to see YCBCR420 modes
>>    in the modedb.
>>
>> V5: Introduced the patch in series.
>> V5-resend: Squashed two patches (validate YCBCR420 and add YCBCR420
>> 	   identifier)
>>
>> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
>> ---
>>   drivers/gpu/drm/drm_edid.c         |  3 ++-
>>   drivers/gpu/drm/drm_modes.c        | 28 ++++++++++++++++++++++++++++
>>   drivers/gpu/drm/drm_probe_helper.c |  4 ++++
>>   include/drm/drm_connector.h        |  9 +++++++++
>>   include/drm/drm_edid.h             |  1 +
>>   include/drm/drm_modes.h            |  5 +++++
>>   6 files changed, 49 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
>> index 10dab62..44be128 100644
>> --- a/drivers/gpu/drm/drm_edid.c
>> +++ b/drivers/gpu/drm/drm_edid.c
>> @@ -2950,10 +2950,11 @@ 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);
>>   }
>> +EXPORT_SYMBOL(drm_valid_cea_vic);
>>   
>>   /**
>>    * drm_get_cea_aspect_ratio - get the picture aspect ratio corresponding to
>> diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
>> index f2493b9..3b53c8e3 100644
>> --- a/drivers/gpu/drm/drm_modes.c
>> +++ b/drivers/gpu/drm/drm_modes.c
>> @@ -1083,6 +1083,34 @@ drm_mode_validate_size(const struct drm_display_mode *mode,
>>   }
>>   EXPORT_SYMBOL(drm_mode_validate_size);
>>   
>> +/**
>> + * drm_mode_ycbcr420_only - add 'ycbcr420-only' modes only when allowed
>> + * @mode: mode to check
>> + * @connector: drm connector under action
>> + *
>> + * This function is a helper which can be used to filter out any YCBCR420
>> + * only mode, when the source doesn't support it.
>> + *
>> + * Returns:
>> + * The mode status
>> + */
>> +enum drm_mode_status
>> +drm_mode_validate_ycbcr420(const struct drm_display_mode *mode,
>> +			   struct drm_connector *connector)
>> +{
>> +	u8 vic = drm_match_cea_mode(mode);
>> +	enum drm_mode_status status = MODE_OK;
>> +	struct drm_hdmi_info *hdmi = &connector->display_info.hdmi;
>> +
>> +	if (drm_valid_cea_vic(vic) && test_bit(vic, hdmi->y420_vdb_modes)) {
> Still think the valid check is pointless.
I still think that we should only pass valid CEA VIC to VDB check, but 
Ok, I will remove that.
>   Skipping that would also avoid
> having to make the function non-static
Ok
> (the EXPORT_SYMBOL there seems
> unnecessary either way).
Why ?
>
>> +		if (!connector->ycbcr_420_allowed)
>> +			status = MODE_NO_420;
>> +	}
>> +
>> +	return status;
>> +}
>> +EXPORT_SYMBOL(drm_mode_validate_ycbcr420);
>> +
>>   #define MODE_STATUS(status) [MODE_ ## status + 3] = #status
>>   
>>   static const char * const drm_mode_status_names[] = {
> ^
> This thing needs to be updated as well.
Oh sorry, good catch.
- Shashank
>> diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
>> index 00e6832..904966c 100644
>> --- a/drivers/gpu/drm/drm_probe_helper.c
>> +++ b/drivers/gpu/drm/drm_probe_helper.c
>> @@ -528,6 +528,10 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
>>   		if (mode->status == MODE_OK)
>>   			mode->status = drm_mode_validate_pipeline(mode,
>>   								  connector);
>> +
>> +		if (mode->status == MODE_OK)
>> +			mode->status = drm_mode_validate_ycbcr420(mode,
>> +								  connector);
>>   	}
>>   
>>   prune:
>> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
>> index b3af8e3..225e092 100644
>> --- a/include/drm/drm_connector.h
>> +++ b/include/drm/drm_connector.h
>> @@ -746,6 +746,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.
>> diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
>> index 89c0062..b55b2a7 100644
>> --- a/include/drm/drm_edid.h
>> +++ b/include/drm/drm_edid.h
>> @@ -477,4 +477,5 @@ void drm_edid_get_monitor_name(struct edid *edid, char *name,
>>   struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
>>   					   int hsize, int vsize, int fresh,
>>   					   bool rb);
>> +bool drm_valid_cea_vic(u8 vic);
>>   #endif /* __DRM_EDID_H__ */
>> diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h
>> index 94ac771..f8a1268 100644
>> --- a/include/drm/drm_modes.h
>> +++ b/include/drm/drm_modes.h
>> @@ -80,6 +80,7 @@ struct videomode;
>>    * @MODE_ONE_SIZE: only one resolution is supported
>>    * @MODE_NO_REDUCED: monitor doesn't accept reduced blanking
>>    * @MODE_NO_STEREO: stereo modes not supported
>> + * @MODE_NO_420: ycbcr 420 modes not supported
>>    * @MODE_STALE: mode has become stale
>>    * @MODE_BAD: unspecified reason
>>    * @MODE_ERROR: error condition
>> @@ -124,6 +125,7 @@ enum drm_mode_status {
>>   	MODE_ONE_SIZE,
>>   	MODE_NO_REDUCED,
>>   	MODE_NO_STEREO,
>> +	MODE_NO_420,
>>   	MODE_STALE = -3,
>>   	MODE_BAD = -2,
>>   	MODE_ERROR = -1
>> @@ -496,6 +498,9 @@ bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1,
>>   enum drm_mode_status drm_mode_validate_basic(const struct drm_display_mode *mode);
>>   enum drm_mode_status drm_mode_validate_size(const struct drm_display_mode *mode,
>>   					    int maxX, int maxY);
>> +enum drm_mode_status
>> +drm_mode_validate_ycbcr420(const struct drm_display_mode *mode,
>> +			   struct drm_connector *connector);
>>   void drm_mode_prune_invalid(struct drm_device *dev,
>>   			    struct list_head *mode_list, bool verbose);
>>   void drm_mode_sort(struct list_head *mode_list);
>> -- 
>> 2.7.4
>>
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel@lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

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

* Re: [PATCH 07/20] drm/edid: parse ycbcr 420 deep color information
  2017-07-12 17:18   ` Ville Syrjälä
@ 2017-07-13  5:33     ` Sharma, Shashank
  0 siblings, 0 replies; 76+ messages in thread
From: Sharma, Shashank @ 2017-07-13  5:33 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, dri-devel

Regards

Shashank


On 7/12/2017 10:48 PM, Ville Syrjälä wrote:
> On Mon, Jul 10, 2017 at 04:48:35PM +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)
>> V5: Optimize function, if(conditions) not reqd (Ville)
>> V6: Rebase
>>
>> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
>> ---
>>   drivers/gpu/drm/drm_edid.c  | 12 ++++++++++++
>>   include/drm/drm_connector.h |  3 +++
>>   include/drm/drm_edid.h      |  8 ++++++++
>>   3 files changed, 23 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
>> index 44be128..944a28f 100644
>> --- a/drivers/gpu/drm/drm_edid.c
>> +++ b/drivers/gpu/drm/drm_edid.c
>> @@ -4199,6 +4199,16 @@ 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)
>> +{
>> +	u8 dc_mask;
>> +	struct drm_hdmi_info *hdmi = &connector->display_info.hdmi;
>> +
>> +	dc_mask = db[7] & DRM_EDID_YCBCR420_DC_MASK;
>> +	hdmi->y420_dc_modes |= dc_mask;
>> +}
>> +
>>   static void drm_parse_hdmi_forum_vsdb(struct drm_connector *connector,
>>   				 const u8 *hf_vsdb)
>>   {
>> @@ -4239,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 225e092..4bc0882 100644
>> --- a/include/drm/drm_connector.h
>> +++ b/include/drm/drm_connector.h
>> @@ -154,6 +154,9 @@ struct drm_hdmi_info {
>>   
>>   	/** @y420_cmdb_map: bitmap of SVD index, to extraxt vcb modes */
>>   	u64 y420_cmdb_map;
>> +
>> +	/** @y420_dc_modes: bitmap of deep color support index */
>> +	u8 y420_dc_modes;
> Pls put it next to the other dc u8 stuff.
Ok.

- Shashank
>>   };
>>   
>>   /**
>> diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
>> index b55b2a7..aa58146 100644
>> --- a/include/drm/drm_edid.h
>> +++ b/include/drm/drm_edid.h
>> @@ -213,6 +213,14 @@ 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)
>> +#define DRM_EDID_YCBCR420_DC_MASK (DRM_EDID_YCBCR420_DC_48 | \
>> +				    DRM_EDID_YCBCR420_DC_36 | \
>> +				    DRM_EDID_YCBCR420_DC_30)
>> +
>>   /* 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

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

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

* Re: [PATCH 02/20] drm/edid: complete CEA modedb(VIC 1-107)
  2017-07-12 17:18   ` Ville Syrjälä
@ 2017-07-13  5:38     ` Sharma, Shashank
  0 siblings, 0 replies; 76+ messages in thread
From: Sharma, Shashank @ 2017-07-13  5:38 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, dri-devel

Regards

Shashank


On 7/12/2017 10:48 PM, Ville Syrjälä wrote:
> On Mon, Jul 10, 2017 at 04:48:30PM +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/
>>
>> V2: Rebase
>> V3: Rebase
>> V4: Added native bit handling as per CEA-861-F spec (Ville)
>> V5: Fix timings for VIC 77:1920x1080 and 104:3840x2160p (Ville)
>>      Remove unnecessary paranthesis from function svd_to_vic (Ville)
>>      Added r-b (Neil)
>>
>> Reviewed-by: Jose Abreu <Jose.Abreu@synopsys.com>
>> Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
>> Reviewed-by: Neil Armstrong <narmstrong@baylibre.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 0667b07..b879662 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, 1089, 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, },
> Indentation looks broken starting from this mode. Pls fix your editor.
> Otherwise lgtm.
Ok,

- Shashank
>> +	/* 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, 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_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
>>
>> _______________________________________________
>> dri-devel mailing list
>> dri-devel@lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

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

* Re: [PATCH 20/20] drm/i915: write AVI infoframes for LSPCON
  2017-07-12 17:24   ` Ville Syrjälä
@ 2017-07-13  5:41     ` Sharma, Shashank
  2017-07-13 12:27       ` Ville Syrjälä
  0 siblings, 1 reply; 76+ messages in thread
From: Sharma, Shashank @ 2017-07-13  5:41 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, dri-devel

Regards

Shashank


On 7/12/2017 10:54 PM, Ville Syrjälä wrote:
> On Mon, Jul 10, 2017 at 04:48:48PM +0530, Shashank Sharma wrote:
>> LSPCON chips can't pick the HDMI AVI infoframes from direct link.
>> In order to pass AVI infoframes from display controller to LSPCON,
>> we have to write infoframe packets into vendor specified AUX address.
>>
>> Also, LSPCON vendors provide AUX offsets, to inform the LSPCON
>> chip that the AVI IF packets are written, so that the firmware
>> can pick it up and apply.
>>
>> This patch adds function to write AVI infoframes for both MCA as
>> well as Parade Tech LSPCON chips. These two vendors provide different
>> methods for writing infoframes, so this patch contains two different
>> functions, one for each.
> Seems to me that we should also be checking the receiver cap for the
> 444->420 conversion support, and enable it in the PROTOCOL_CONVERTER
> DPCD register. Or are these LSPCON things even ignoring that part of the
> spec?
Yes, LSPCON just needs the YCBCR444 input, and info frames for 420, and 
it would take care of
444->420 conversion in FW. Also, its a part of LSPCON specs, that it has 
to have 420 output capability.

- Shashank
>
>> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> Cc: Imre Deak <imre.deak@intel.com>
>> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
>> ---
>>   drivers/gpu/drm/i915/intel_ddi.c    |   8 ++
>>   drivers/gpu/drm/i915/intel_drv.h    |   3 +
>>   drivers/gpu/drm/i915/intel_lspcon.c | 174 ++++++++++++++++++++++++++++++++++++
>>   3 files changed, 185 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
>> index f691710..944d9d5 100644
>> --- a/drivers/gpu/drm/i915/intel_ddi.c
>> +++ b/drivers/gpu/drm/i915/intel_ddi.c
>> @@ -2068,6 +2068,14 @@ void intel_ddi_set_avi_infoframe(struct drm_encoder *encoder,
>>   					   rgb_qrange_limited,
>>   					   rgb_qrange_selectable);
>>   
>> +	if (crtc_state->lspcon_active) {
>> +		struct intel_lspcon *lspcon = enc_to_intel_lspcon(encoder);
>> +
>> +		/* LSPCON writes infoframes via AUX */
>> +		lspcon->write_infoframe(encoder, crtc_state, &frame);
>> +		return;
>> +	}
>> +
>>   	intel_write_infoframe(encoder, crtc_state, &frame);
>>   }
>>   
>> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
>> index fad9a53..3e686d2 100644
>> --- a/drivers/gpu/drm/i915/intel_drv.h
>> +++ b/drivers/gpu/drm/i915/intel_drv.h
>> @@ -1079,6 +1079,9 @@ struct intel_lspcon {
>>   	/* AVI IF setup function for LSPCON */
>>   	void (*set_infoframes)(struct drm_encoder *encoder,
>>   				const struct intel_crtc_state *crtc_state);
>> +	void (*write_infoframe)(struct drm_encoder *encoder,
>> +				const struct intel_crtc_state *crtc_state,
>> +				union hdmi_infoframe *frame);
>>   };
>>   
>>   struct intel_digital_port {
>> diff --git a/drivers/gpu/drm/i915/intel_lspcon.c b/drivers/gpu/drm/i915/intel_lspcon.c
>> index 53ddd39..01fddf7 100644
>> --- a/drivers/gpu/drm/i915/intel_lspcon.c
>> +++ b/drivers/gpu/drm/i915/intel_lspcon.c
>> @@ -31,6 +31,18 @@
>>   #define LSPCON_VENDOR_PARADE_OUI 0x001CF8
>>   #define LSPCON_VENDOR_MCA_OUI 0x0060AD
>>   
>> +/* AUX addresses to write AVI IF into */
>> +#define LSPCON_MCA_AVI_IF_WRITE_OFFSET 0x5C0
>> +#define LSPCON_MCA_AVI_IF_CTRL 0x5DF
>> +#define  LSPCON_MCA_AVI_IF_KICKOFF (1 << 0)
>> +#define  LSPCON_MCA_AVI_IF_HANDLED (1 << 1)
>> +
>> +#define LSPCON_PARADE_AVI_IF_WRITE_OFFSET 0x516
>> +#define LSPCON_PARADE_AVI_IF_CTRL 0x51E
>> +#define  LSPCON_PARADE_AVI_IF_KICKOFF (1 << 7)
>> +#define LSPCON_PARADE_AVI_IF_STATUS 0x51F
>> +#define  LSPCON_PARADE_AVI_IF_HANDLED (2 << 6)
>> +
>>   static struct intel_dp *lspcon_to_intel_dp(struct intel_lspcon *lspcon)
>>   {
>>   	struct intel_digital_port *dig_port =
>> @@ -217,6 +229,167 @@ bool lspcon_ycbcr420_config(struct drm_connector *connector,
>>   	return false;
>>   }
>>   
>> +static bool _lspcon_write_infoframe_parade(struct drm_dp_aux *aux,
>> +					   uint8_t *buffer, ssize_t len)
>> +{
>> +	u8 avi_if_ctrl;
>> +	u8 avi_if_status;
>> +	u8 count = 0;
>> +	u8 retry = 5;
>> +	u8 avi_buf[8] = {0, };
>> +	uint16_t reg;
>> +	ssize_t ret;
>> +
>> +	while (count++ < 4) {
>> +
>> +		do {
>> +			/* Is LSPCON FW ready */
>> +			reg = LSPCON_PARADE_AVI_IF_CTRL;
>> +			ret = drm_dp_dpcd_read(aux, reg, &avi_if_ctrl, 1);
>> +			if (ret < 0) {
>> +				DRM_ERROR("DPCD read failed, add:0x%x\n", reg);
>> +				return false;
>> +			}
>> +
>> +			if (avi_if_ctrl & LSPCON_PARADE_AVI_IF_KICKOFF)
>> +				break;
>> +			usleep_range(100, 200);
>> +		} while (--retry);
>> +
>> +		if (!(avi_if_ctrl & LSPCON_PARADE_AVI_IF_KICKOFF)) {
>> +			DRM_ERROR("LSPCON FW not ready for infoframes\n");
>> +			return false;
>> +		}
>> +
>> +		/*
>> +		 * AVI Infoframe contains 31 bytes of data:
>> +		 *	HB0 to HB2   (3 bytes header)
>> +		 *	PB0 to PB27 (28 bytes data)
>> +		 * As per Parade spec, while sending first block (8bytes),
>> +		 * byte 0 is kept for request token no, and byte1 - byte7
>> +		 * contain frame data. So we have to pack frame like this:
>> +		 *	first block of 8 bytes: <token> <HB0-HB2> <PB0-PB3>
>> +		 *	next 3 blocks: <PB4-PB27>
>> +		 */
>> +		if (count)
>> +			memcpy(avi_buf, buffer + count * 8 - 1, 8);
>> +		else {
>> +			avi_buf[0] = 1;
>> +			memcpy(&avi_buf[1], buffer, 7);
>> +		}
>> +
>> +		/* Write 8 bytes of data at a time */
>> +		reg = LSPCON_PARADE_AVI_IF_WRITE_OFFSET;
>> +		ret = drm_dp_dpcd_write(aux, reg, avi_buf, 8);
>> +		if (ret < 0) {
>> +			DRM_ERROR("DPCD write failed, add:0x%x\n", reg);
>> +			return false;
>> +		}
>> +
>> +		/*
>> +		 * While sending a block of 8 byes, we need to inform block
>> +		 * number to FW, by programming bits[1:0] of ctrl reg with
>> +		 * block number
>> +		 */
>> +		avi_if_ctrl = 0x80 + count;
>> +		reg = LSPCON_PARADE_AVI_IF_CTRL;
>> +		ret = drm_dp_dpcd_write(aux, reg, &avi_if_ctrl, 1);
>> +		if (ret < 0) {
>> +			DRM_ERROR("DPCD write failed, add:0x%x\n", reg);
>> +			return false;
>> +		}
>> +	}
>> +
>> +	/* Check LSPCON FW status */
>> +	reg = LSPCON_PARADE_AVI_IF_STATUS;
>> +	ret = drm_dp_dpcd_read(aux, reg, &avi_if_status, 1);
>> +	if (ret < 0) {
>> +		DRM_ERROR("DPCD write failed, address 0x%x\n", reg);
>> +		return false;
>> +	}
>> +
>> +	if (avi_if_status & LSPCON_PARADE_AVI_IF_HANDLED)
>> +		DRM_DEBUG_KMS("AVI IF handled by FW\n");
>> +
>> +	return true;
>> +}
>> +
>> +static bool _lspcon_write_infoframe_mca(struct drm_dp_aux *aux,
>> +					uint8_t *buffer, ssize_t len)
>> +{
>> +	int ret;
>> +	uint32_t val = 0;
>> +	uint16_t reg;
>> +	uint8_t *data = buffer;
>> +
>> +	reg = LSPCON_MCA_AVI_IF_WRITE_OFFSET;
>> +	while (val < len) {
>> +		ret = drm_dp_dpcd_write(aux, reg, data, 1);
>> +		if (ret < 0) {
>> +			DRM_ERROR("DPCD write failed, add:0x%x\n", reg);
>> +			return false;
>> +		}
>> +		val++; reg++; data++;
>> +	}
>> +
>> +	val = 0;
>> +	reg = LSPCON_MCA_AVI_IF_CTRL;
>> +	ret = drm_dp_dpcd_read(aux, reg, &val, 1);
>> +	if (ret < 0) {
>> +		DRM_ERROR("DPCD read failed, address 0x%x\n", reg);
>> +		return false;
>> +	}
>> +
>> +	/* Indicate LSPCON chip about infoframe, clear bit 1 and set bit 0 */
>> +	val &= ~LSPCON_MCA_AVI_IF_HANDLED;
>> +	val |= LSPCON_MCA_AVI_IF_KICKOFF;
>> +
>> +	ret = drm_dp_dpcd_write(aux, reg, &val, 1);
>> +	if (ret < 0) {
>> +		DRM_ERROR("DPCD read failed, address 0x%x\n", reg);
>> +		return false;
>> +	}
>> +
>> +	val = 0;
>> +	ret = drm_dp_dpcd_read(aux, reg, &val, 1);
>> +	if (ret < 0) {
>> +		DRM_ERROR("DPCD read failed, address 0x%x\n", reg);
>> +		return false;
>> +	}
>> +
>> +	if (val == LSPCON_MCA_AVI_IF_HANDLED)
>> +		DRM_DEBUG_KMS("AVI IF handled by FW\n");
>> +
>> +	return true;
>> +}
>> +
>> +void lspcon_write_infoframe(struct drm_encoder *encoder,
>> +				  const struct intel_crtc_state *crtc_state,
>> +				  union hdmi_infoframe *frame)
>> +{
>> +	bool ret;
>> +	ssize_t len;
>> +	uint8_t buf[VIDEO_DIP_DATA_SIZE];
>> +	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
>> +	struct intel_lspcon *lspcon = enc_to_intel_lspcon(encoder);
>> +
>> +	len = hdmi_infoframe_pack(frame, buf, sizeof(buf));
>> +	if (len < 0) {
>> +		DRM_ERROR("Failed to pack AVI IF\n");
>> +		return;
>> +	}
>> +
>> +	if (lspcon->vendor == LSPCON_VENDOR_MCA)
>> +		ret = _lspcon_write_infoframe_mca(&intel_dp->aux, buf, len);
>> +	else
>> +		ret = _lspcon_write_infoframe_parade(&intel_dp->aux, buf, len);
>> +
>> +	if (!ret)
>> +		DRM_ERROR("Failed to write AVI infoframes\n");
>> +	else
>> +		DRM_DEBUG_DRIVER("AVI infoframes updated successfully\n");
>> +}
>> +
>>   void lspcon_resume(struct intel_lspcon *lspcon)
>>   {
>>   	enum drm_lspcon_mode expected_mode;
>> @@ -282,6 +455,7 @@ bool lspcon_init(struct intel_digital_port *intel_dig_port)
>>   
>>   	connector->ycbcr_420_allowed = true;
>>   	lspcon->set_infoframes = intel_ddi_set_avi_infoframe;
>> +	lspcon->write_infoframe = lspcon_write_infoframe;
>>   	drm_dp_read_desc(&dp->aux, &dp->desc, drm_dp_is_branch(dp->dpcd));
>>   
>>   	DRM_DEBUG_KMS("Success: LSPCON init\n");
>> -- 
>> 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] 76+ messages in thread

* Re: [PATCH 20/20] drm/i915: write AVI infoframes for LSPCON
  2017-07-13  5:41     ` Sharma, Shashank
@ 2017-07-13 12:27       ` Ville Syrjälä
  2017-07-13 12:39         ` Sharma, Shashank
  0 siblings, 1 reply; 76+ messages in thread
From: Ville Syrjälä @ 2017-07-13 12:27 UTC (permalink / raw)
  To: Sharma, Shashank; +Cc: intel-gfx, dri-devel

On Thu, Jul 13, 2017 at 11:11:53AM +0530, Sharma, Shashank wrote:
> Regards
> 
> Shashank
> 
> 
> On 7/12/2017 10:54 PM, Ville Syrjälä wrote:
> > On Mon, Jul 10, 2017 at 04:48:48PM +0530, Shashank Sharma wrote:
> >> LSPCON chips can't pick the HDMI AVI infoframes from direct link.
> >> In order to pass AVI infoframes from display controller to LSPCON,
> >> we have to write infoframe packets into vendor specified AUX address.
> >>
> >> Also, LSPCON vendors provide AUX offsets, to inform the LSPCON
> >> chip that the AVI IF packets are written, so that the firmware
> >> can pick it up and apply.
> >>
> >> This patch adds function to write AVI infoframes for both MCA as
> >> well as Parade Tech LSPCON chips. These two vendors provide different
> >> methods for writing infoframes, so this patch contains two different
> >> functions, one for each.
> > Seems to me that we should also be checking the receiver cap for the
> > 444->420 conversion support, and enable it in the PROTOCOL_CONVERTER
> > DPCD register. Or are these LSPCON things even ignoring that part of the
> > spec?
> Yes, LSPCON just needs the YCBCR444 input, and info frames for 420, and 
> it would take care of
> 444->420 conversion in FW.

So it snoops the AVI infoframe we write to it to figure out that it has
to do the 444->420 downsampling?

> Also, its a part of LSPCON specs, that it has 
> to have 420 output capability.
> 
> - Shashank
> >
> >> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >> Cc: Imre Deak <imre.deak@intel.com>
> >> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
> >> ---
> >>   drivers/gpu/drm/i915/intel_ddi.c    |   8 ++
> >>   drivers/gpu/drm/i915/intel_drv.h    |   3 +
> >>   drivers/gpu/drm/i915/intel_lspcon.c | 174 ++++++++++++++++++++++++++++++++++++
> >>   3 files changed, 185 insertions(+)
> >>
> >> diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> >> index f691710..944d9d5 100644
> >> --- a/drivers/gpu/drm/i915/intel_ddi.c
> >> +++ b/drivers/gpu/drm/i915/intel_ddi.c
> >> @@ -2068,6 +2068,14 @@ void intel_ddi_set_avi_infoframe(struct drm_encoder *encoder,
> >>   					   rgb_qrange_limited,
> >>   					   rgb_qrange_selectable);
> >>   
> >> +	if (crtc_state->lspcon_active) {
> >> +		struct intel_lspcon *lspcon = enc_to_intel_lspcon(encoder);
> >> +
> >> +		/* LSPCON writes infoframes via AUX */
> >> +		lspcon->write_infoframe(encoder, crtc_state, &frame);
> >> +		return;
> >> +	}
> >> +
> >>   	intel_write_infoframe(encoder, crtc_state, &frame);
> >>   }
> >>   
> >> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> >> index fad9a53..3e686d2 100644
> >> --- a/drivers/gpu/drm/i915/intel_drv.h
> >> +++ b/drivers/gpu/drm/i915/intel_drv.h
> >> @@ -1079,6 +1079,9 @@ struct intel_lspcon {
> >>   	/* AVI IF setup function for LSPCON */
> >>   	void (*set_infoframes)(struct drm_encoder *encoder,
> >>   				const struct intel_crtc_state *crtc_state);
> >> +	void (*write_infoframe)(struct drm_encoder *encoder,
> >> +				const struct intel_crtc_state *crtc_state,
> >> +				union hdmi_infoframe *frame);
> >>   };
> >>   
> >>   struct intel_digital_port {
> >> diff --git a/drivers/gpu/drm/i915/intel_lspcon.c b/drivers/gpu/drm/i915/intel_lspcon.c
> >> index 53ddd39..01fddf7 100644
> >> --- a/drivers/gpu/drm/i915/intel_lspcon.c
> >> +++ b/drivers/gpu/drm/i915/intel_lspcon.c
> >> @@ -31,6 +31,18 @@
> >>   #define LSPCON_VENDOR_PARADE_OUI 0x001CF8
> >>   #define LSPCON_VENDOR_MCA_OUI 0x0060AD
> >>   
> >> +/* AUX addresses to write AVI IF into */
> >> +#define LSPCON_MCA_AVI_IF_WRITE_OFFSET 0x5C0
> >> +#define LSPCON_MCA_AVI_IF_CTRL 0x5DF
> >> +#define  LSPCON_MCA_AVI_IF_KICKOFF (1 << 0)
> >> +#define  LSPCON_MCA_AVI_IF_HANDLED (1 << 1)
> >> +
> >> +#define LSPCON_PARADE_AVI_IF_WRITE_OFFSET 0x516
> >> +#define LSPCON_PARADE_AVI_IF_CTRL 0x51E
> >> +#define  LSPCON_PARADE_AVI_IF_KICKOFF (1 << 7)
> >> +#define LSPCON_PARADE_AVI_IF_STATUS 0x51F
> >> +#define  LSPCON_PARADE_AVI_IF_HANDLED (2 << 6)
> >> +
> >>   static struct intel_dp *lspcon_to_intel_dp(struct intel_lspcon *lspcon)
> >>   {
> >>   	struct intel_digital_port *dig_port =
> >> @@ -217,6 +229,167 @@ bool lspcon_ycbcr420_config(struct drm_connector *connector,
> >>   	return false;
> >>   }
> >>   
> >> +static bool _lspcon_write_infoframe_parade(struct drm_dp_aux *aux,
> >> +					   uint8_t *buffer, ssize_t len)
> >> +{
> >> +	u8 avi_if_ctrl;
> >> +	u8 avi_if_status;
> >> +	u8 count = 0;
> >> +	u8 retry = 5;
> >> +	u8 avi_buf[8] = {0, };
> >> +	uint16_t reg;
> >> +	ssize_t ret;
> >> +
> >> +	while (count++ < 4) {
> >> +
> >> +		do {
> >> +			/* Is LSPCON FW ready */
> >> +			reg = LSPCON_PARADE_AVI_IF_CTRL;
> >> +			ret = drm_dp_dpcd_read(aux, reg, &avi_if_ctrl, 1);
> >> +			if (ret < 0) {
> >> +				DRM_ERROR("DPCD read failed, add:0x%x\n", reg);
> >> +				return false;
> >> +			}
> >> +
> >> +			if (avi_if_ctrl & LSPCON_PARADE_AVI_IF_KICKOFF)
> >> +				break;
> >> +			usleep_range(100, 200);
> >> +		} while (--retry);
> >> +
> >> +		if (!(avi_if_ctrl & LSPCON_PARADE_AVI_IF_KICKOFF)) {
> >> +			DRM_ERROR("LSPCON FW not ready for infoframes\n");
> >> +			return false;
> >> +		}
> >> +
> >> +		/*
> >> +		 * AVI Infoframe contains 31 bytes of data:
> >> +		 *	HB0 to HB2   (3 bytes header)
> >> +		 *	PB0 to PB27 (28 bytes data)
> >> +		 * As per Parade spec, while sending first block (8bytes),
> >> +		 * byte 0 is kept for request token no, and byte1 - byte7
> >> +		 * contain frame data. So we have to pack frame like this:
> >> +		 *	first block of 8 bytes: <token> <HB0-HB2> <PB0-PB3>
> >> +		 *	next 3 blocks: <PB4-PB27>
> >> +		 */
> >> +		if (count)
> >> +			memcpy(avi_buf, buffer + count * 8 - 1, 8);
> >> +		else {
> >> +			avi_buf[0] = 1;
> >> +			memcpy(&avi_buf[1], buffer, 7);
> >> +		}
> >> +
> >> +		/* Write 8 bytes of data at a time */
> >> +		reg = LSPCON_PARADE_AVI_IF_WRITE_OFFSET;
> >> +		ret = drm_dp_dpcd_write(aux, reg, avi_buf, 8);
> >> +		if (ret < 0) {
> >> +			DRM_ERROR("DPCD write failed, add:0x%x\n", reg);
> >> +			return false;
> >> +		}
> >> +
> >> +		/*
> >> +		 * While sending a block of 8 byes, we need to inform block
> >> +		 * number to FW, by programming bits[1:0] of ctrl reg with
> >> +		 * block number
> >> +		 */
> >> +		avi_if_ctrl = 0x80 + count;
> >> +		reg = LSPCON_PARADE_AVI_IF_CTRL;
> >> +		ret = drm_dp_dpcd_write(aux, reg, &avi_if_ctrl, 1);
> >> +		if (ret < 0) {
> >> +			DRM_ERROR("DPCD write failed, add:0x%x\n", reg);
> >> +			return false;
> >> +		}
> >> +	}
> >> +
> >> +	/* Check LSPCON FW status */
> >> +	reg = LSPCON_PARADE_AVI_IF_STATUS;
> >> +	ret = drm_dp_dpcd_read(aux, reg, &avi_if_status, 1);
> >> +	if (ret < 0) {
> >> +		DRM_ERROR("DPCD write failed, address 0x%x\n", reg);
> >> +		return false;
> >> +	}
> >> +
> >> +	if (avi_if_status & LSPCON_PARADE_AVI_IF_HANDLED)
> >> +		DRM_DEBUG_KMS("AVI IF handled by FW\n");
> >> +
> >> +	return true;
> >> +}
> >> +
> >> +static bool _lspcon_write_infoframe_mca(struct drm_dp_aux *aux,
> >> +					uint8_t *buffer, ssize_t len)
> >> +{
> >> +	int ret;
> >> +	uint32_t val = 0;
> >> +	uint16_t reg;
> >> +	uint8_t *data = buffer;
> >> +
> >> +	reg = LSPCON_MCA_AVI_IF_WRITE_OFFSET;
> >> +	while (val < len) {
> >> +		ret = drm_dp_dpcd_write(aux, reg, data, 1);
> >> +		if (ret < 0) {
> >> +			DRM_ERROR("DPCD write failed, add:0x%x\n", reg);
> >> +			return false;
> >> +		}
> >> +		val++; reg++; data++;
> >> +	}
> >> +
> >> +	val = 0;
> >> +	reg = LSPCON_MCA_AVI_IF_CTRL;
> >> +	ret = drm_dp_dpcd_read(aux, reg, &val, 1);
> >> +	if (ret < 0) {
> >> +		DRM_ERROR("DPCD read failed, address 0x%x\n", reg);
> >> +		return false;
> >> +	}
> >> +
> >> +	/* Indicate LSPCON chip about infoframe, clear bit 1 and set bit 0 */
> >> +	val &= ~LSPCON_MCA_AVI_IF_HANDLED;
> >> +	val |= LSPCON_MCA_AVI_IF_KICKOFF;
> >> +
> >> +	ret = drm_dp_dpcd_write(aux, reg, &val, 1);
> >> +	if (ret < 0) {
> >> +		DRM_ERROR("DPCD read failed, address 0x%x\n", reg);
> >> +		return false;
> >> +	}
> >> +
> >> +	val = 0;
> >> +	ret = drm_dp_dpcd_read(aux, reg, &val, 1);
> >> +	if (ret < 0) {
> >> +		DRM_ERROR("DPCD read failed, address 0x%x\n", reg);
> >> +		return false;
> >> +	}
> >> +
> >> +	if (val == LSPCON_MCA_AVI_IF_HANDLED)
> >> +		DRM_DEBUG_KMS("AVI IF handled by FW\n");
> >> +
> >> +	return true;
> >> +}
> >> +
> >> +void lspcon_write_infoframe(struct drm_encoder *encoder,
> >> +				  const struct intel_crtc_state *crtc_state,
> >> +				  union hdmi_infoframe *frame)
> >> +{
> >> +	bool ret;
> >> +	ssize_t len;
> >> +	uint8_t buf[VIDEO_DIP_DATA_SIZE];
> >> +	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> >> +	struct intel_lspcon *lspcon = enc_to_intel_lspcon(encoder);
> >> +
> >> +	len = hdmi_infoframe_pack(frame, buf, sizeof(buf));
> >> +	if (len < 0) {
> >> +		DRM_ERROR("Failed to pack AVI IF\n");
> >> +		return;
> >> +	}
> >> +
> >> +	if (lspcon->vendor == LSPCON_VENDOR_MCA)
> >> +		ret = _lspcon_write_infoframe_mca(&intel_dp->aux, buf, len);
> >> +	else
> >> +		ret = _lspcon_write_infoframe_parade(&intel_dp->aux, buf, len);
> >> +
> >> +	if (!ret)
> >> +		DRM_ERROR("Failed to write AVI infoframes\n");
> >> +	else
> >> +		DRM_DEBUG_DRIVER("AVI infoframes updated successfully\n");
> >> +}
> >> +
> >>   void lspcon_resume(struct intel_lspcon *lspcon)
> >>   {
> >>   	enum drm_lspcon_mode expected_mode;
> >> @@ -282,6 +455,7 @@ bool lspcon_init(struct intel_digital_port *intel_dig_port)
> >>   
> >>   	connector->ycbcr_420_allowed = true;
> >>   	lspcon->set_infoframes = intel_ddi_set_avi_infoframe;
> >> +	lspcon->write_infoframe = lspcon_write_infoframe;
> >>   	drm_dp_read_desc(&dp->aux, &dp->desc, drm_dp_is_branch(dp->dpcd));
> >>   
> >>   	DRM_DEBUG_KMS("Success: LSPCON init\n");
> >> -- 
> >> 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] 76+ messages in thread

* Re: [PATCH 06/20] drm: add helper to validate YCBCR420 modes
  2017-07-13  5:32     ` Sharma, Shashank
@ 2017-07-13 12:31       ` Ville Syrjälä
  2017-07-13 12:42         ` Sharma, Shashank
  0 siblings, 1 reply; 76+ messages in thread
From: Ville Syrjälä @ 2017-07-13 12:31 UTC (permalink / raw)
  To: Sharma, Shashank; +Cc: intel-gfx, dri-devel

On Thu, Jul 13, 2017 at 11:02:18AM +0530, Sharma, Shashank wrote:
> Regards
> 
> Shashank
> 
> 
> On 7/12/2017 10:48 PM, Ville Syrjälä wrote:
> > On Mon, Jul 10, 2017 at 04:48:34PM +0530, Shashank Sharma wrote:
> >> YCBCR420 modes are supported only on HDMI 2.0 capable sources.
> >> This patch adds:
> >> - A drm helper to validate YCBCR420-only mode on a particular
> >>    connector. This function will help pruning the YCBCR420-only
> >>    modes from the connector's modelist.
> >> - 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 YCBCR420 output, so that no
> >>    YCBCR 420 modes will be listed for sources which can't handle it.
> >>    A driver should set this variable if it wants to see YCBCR420 modes
> >>    in the modedb.
> >>
> >> V5: Introduced the patch in series.
> >> V5-resend: Squashed two patches (validate YCBCR420 and add YCBCR420
> >> 	   identifier)
> >>
> >> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
> >> ---
> >>   drivers/gpu/drm/drm_edid.c         |  3 ++-
> >>   drivers/gpu/drm/drm_modes.c        | 28 ++++++++++++++++++++++++++++
> >>   drivers/gpu/drm/drm_probe_helper.c |  4 ++++
> >>   include/drm/drm_connector.h        |  9 +++++++++
> >>   include/drm/drm_edid.h             |  1 +
> >>   include/drm/drm_modes.h            |  5 +++++
> >>   6 files changed, 49 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> >> index 10dab62..44be128 100644
> >> --- a/drivers/gpu/drm/drm_edid.c
> >> +++ b/drivers/gpu/drm/drm_edid.c
> >> @@ -2950,10 +2950,11 @@ 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);
> >>   }
> >> +EXPORT_SYMBOL(drm_valid_cea_vic);
> >>   
> >>   /**
> >>    * drm_get_cea_aspect_ratio - get the picture aspect ratio corresponding to
> >> diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
> >> index f2493b9..3b53c8e3 100644
> >> --- a/drivers/gpu/drm/drm_modes.c
> >> +++ b/drivers/gpu/drm/drm_modes.c
> >> @@ -1083,6 +1083,34 @@ drm_mode_validate_size(const struct drm_display_mode *mode,
> >>   }
> >>   EXPORT_SYMBOL(drm_mode_validate_size);
> >>   
> >> +/**
> >> + * drm_mode_ycbcr420_only - add 'ycbcr420-only' modes only when allowed
> >> + * @mode: mode to check
> >> + * @connector: drm connector under action
> >> + *
> >> + * This function is a helper which can be used to filter out any YCBCR420
> >> + * only mode, when the source doesn't support it.
> >> + *
> >> + * Returns:
> >> + * The mode status
> >> + */
> >> +enum drm_mode_status
> >> +drm_mode_validate_ycbcr420(const struct drm_display_mode *mode,
> >> +			   struct drm_connector *connector)
> >> +{
> >> +	u8 vic = drm_match_cea_mode(mode);
> >> +	enum drm_mode_status status = MODE_OK;
> >> +	struct drm_hdmi_info *hdmi = &connector->display_info.hdmi;
> >> +
> >> +	if (drm_valid_cea_vic(vic) && test_bit(vic, hdmi->y420_vdb_modes)) {
> > Still think the valid check is pointless.
> I still think that we should only pass valid CEA VIC to VDB check, but 
> Ok, I will remove that.
> >   Skipping that would also avoid
> > having to make the function non-static
> Ok
> > (the EXPORT_SYMBOL there seems
> > unnecessary either way).
> Why ?

It's all in the same module AFAICS.

Oh, and the patch ordering here still looks potentially problematic. We
should add the 420 mode validation before we start adding the 420 modes.
Otherwise anyone bisecting through this may get a black/corrupted screen
if they have a monitor with "420 only" modes.

> >
> >> +		if (!connector->ycbcr_420_allowed)
> >> +			status = MODE_NO_420;
> >> +	}
> >> +
> >> +	return status;
> >> +}
> >> +EXPORT_SYMBOL(drm_mode_validate_ycbcr420);
> >> +
> >>   #define MODE_STATUS(status) [MODE_ ## status + 3] = #status
> >>   
> >>   static const char * const drm_mode_status_names[] = {
> > ^
> > This thing needs to be updated as well.
> Oh sorry, good catch.
> - Shashank
> >> diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
> >> index 00e6832..904966c 100644
> >> --- a/drivers/gpu/drm/drm_probe_helper.c
> >> +++ b/drivers/gpu/drm/drm_probe_helper.c
> >> @@ -528,6 +528,10 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
> >>   		if (mode->status == MODE_OK)
> >>   			mode->status = drm_mode_validate_pipeline(mode,
> >>   								  connector);
> >> +
> >> +		if (mode->status == MODE_OK)
> >> +			mode->status = drm_mode_validate_ycbcr420(mode,
> >> +								  connector);
> >>   	}
> >>   
> >>   prune:
> >> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> >> index b3af8e3..225e092 100644
> >> --- a/include/drm/drm_connector.h
> >> +++ b/include/drm/drm_connector.h
> >> @@ -746,6 +746,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.
> >> diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
> >> index 89c0062..b55b2a7 100644
> >> --- a/include/drm/drm_edid.h
> >> +++ b/include/drm/drm_edid.h
> >> @@ -477,4 +477,5 @@ void drm_edid_get_monitor_name(struct edid *edid, char *name,
> >>   struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
> >>   					   int hsize, int vsize, int fresh,
> >>   					   bool rb);
> >> +bool drm_valid_cea_vic(u8 vic);
> >>   #endif /* __DRM_EDID_H__ */
> >> diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h
> >> index 94ac771..f8a1268 100644
> >> --- a/include/drm/drm_modes.h
> >> +++ b/include/drm/drm_modes.h
> >> @@ -80,6 +80,7 @@ struct videomode;
> >>    * @MODE_ONE_SIZE: only one resolution is supported
> >>    * @MODE_NO_REDUCED: monitor doesn't accept reduced blanking
> >>    * @MODE_NO_STEREO: stereo modes not supported
> >> + * @MODE_NO_420: ycbcr 420 modes not supported
> >>    * @MODE_STALE: mode has become stale
> >>    * @MODE_BAD: unspecified reason
> >>    * @MODE_ERROR: error condition
> >> @@ -124,6 +125,7 @@ enum drm_mode_status {
> >>   	MODE_ONE_SIZE,
> >>   	MODE_NO_REDUCED,
> >>   	MODE_NO_STEREO,
> >> +	MODE_NO_420,
> >>   	MODE_STALE = -3,
> >>   	MODE_BAD = -2,
> >>   	MODE_ERROR = -1
> >> @@ -496,6 +498,9 @@ bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1,
> >>   enum drm_mode_status drm_mode_validate_basic(const struct drm_display_mode *mode);
> >>   enum drm_mode_status drm_mode_validate_size(const struct drm_display_mode *mode,
> >>   					    int maxX, int maxY);
> >> +enum drm_mode_status
> >> +drm_mode_validate_ycbcr420(const struct drm_display_mode *mode,
> >> +			   struct drm_connector *connector);
> >>   void drm_mode_prune_invalid(struct drm_device *dev,
> >>   			    struct list_head *mode_list, bool verbose);
> >>   void drm_mode_sort(struct list_head *mode_list);
> >> -- 
> >> 2.7.4
> >>
> >> _______________________________________________
> >> dri-devel mailing list
> >> dri-devel@lists.freedesktop.org
> >> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
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] 76+ messages in thread

* Re: [PATCH 08/20] drm: set output colorspace in AVI infoframe
  2017-07-13  5:07     ` Sharma, Shashank
@ 2017-07-13 12:35       ` Ville Syrjälä
  2017-07-13 12:49         ` Sharma, Shashank
  0 siblings, 1 reply; 76+ messages in thread
From: Ville Syrjälä @ 2017-07-13 12:35 UTC (permalink / raw)
  To: Sharma, Shashank; +Cc: intel-gfx, dri-devel

On Thu, Jul 13, 2017 at 10:37:53AM +0530, Sharma, Shashank wrote:
> Regards
> 
> Shashank
> 
> 
> On 7/12/2017 10:47 PM, Ville Syrjälä wrote:
> > On Mon, Jul 10, 2017 at 04:48:36PM +0530, Shashank Sharma wrote:
> >> A source must set output colorspace information in AVI
> >> infoframes, so that the sink can decode upcoming frames
> >> accordingly.
> >>
> >> This patch adds a function to add the output colorspace
> >> information in the AVI infoframes.
> >>
> >> V2: Rebase
> >> V3: Rebase
> >> V4: Rebase
> >> V5: Rebase
> >> V6: Made patch independent of HDMI output type.
> >>
> >> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
> >> ---
> >>   drivers/gpu/drm/drm_edid.c | 29 +++++++++++++++++++++++++++++
> >>   include/drm/drm_edid.h     |  5 +++++
> >>   2 files changed, 34 insertions(+)
> >>
> >> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> >> index 944a28f..cede86e 100644
> >> --- a/drivers/gpu/drm/drm_edid.c
> >> +++ b/drivers/gpu/drm/drm_edid.c
> >> @@ -4796,6 +4796,35 @@ 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 hdmi_colorspace colorspace)
> >> +{
> >> +	if (colorspace > HDMI_COLORSPACE_YUV420 ||
> >> +		colorspace < HDMI_COLORSPACE_RGB) {
> >> +		DRM_ERROR("Invalid color space type\n");
> >> +		return -EINVAL;
> >> +	}
> > Seems overly defensive. I'd say that if someone insists on writing
> > buggy code just let them do it.
> :) yep can be done, you know, its a new implementation, don't want to 
> create unnecessary noise so being
> a bit defensive :)
> >> +
> >> +	frame->colorspace = colorspace;
> >> +	if (colorspace == HDMI_COLORSPACE_YUV420)
> >> +		frame->pixel_repeat = 0;
> > Most VICs don't allow pixel repeat in 444/etc. either, and we don't
> > protect against that. So this looks like pretty pointless check in
> > this form.
> >
> > So IMO just drop this entire patch and just assign frame->colorspace in
> > the driver.
> Actually YCBCR420 section of spec specifically calls out for not 
> allowing repetition, also, when I tested this on a
> HDMI 2.0 analyzer, if was giving a AVI IF failure on pixel_repeat not 0, 
> so IMHO it would be a good idea to keep
> this and get the tests passing.

That's just papering over bugs elsewhere. If we can't use pixel repeat
with a specific mode, then we should have rejected that mode much earlier.

> 
> - Shashank
> >> +
> >> +	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 aa58146..b79e0cb 100644
> >> --- a/include/drm/drm_edid.h
> >> +++ b/include/drm/drm_edid.h
> >> @@ -332,6 +332,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);
> >> @@ -354,6 +355,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 hdmi_colorspace colorspace);
> >> +int
> >>   drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame,
> >>   					    const struct drm_display_mode *mode);
> >>   void
> >> -- 
> >> 2.7.4
> >>
> >> _______________________________________________
> >> dri-devel mailing list
> >> dri-devel@lists.freedesktop.org
> >> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
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] 76+ messages in thread

* Re: [PATCH 16/20] drm: add function to read vendor OUI
  2017-07-13  5:04     ` Sharma, Shashank
@ 2017-07-13 12:37       ` Ville Syrjälä
  2017-07-13 12:50         ` Sharma, Shashank
  0 siblings, 1 reply; 76+ messages in thread
From: Ville Syrjälä @ 2017-07-13 12:37 UTC (permalink / raw)
  To: Sharma, Shashank; +Cc: intel-gfx, dri-devel

On Thu, Jul 13, 2017 at 10:34:26AM +0530, Sharma, Shashank wrote:
> Regads
> 
> Shashank
> 
> 
> On 7/12/2017 10:45 PM, Ville Syrjälä wrote:
> > On Mon, Jul 10, 2017 at 04:48:44PM +0530, Shashank Sharma wrote:
> >> This patch adds a helper function in DP dual mode layer to
> >> read the vendor's IEEE OUI signature from a Dual mode adapter.
> >> This will be used to differentiate between different LSPCON
> >> vendors, to address their custom programming requirements.
> > Can't we just read it from DPCD instead?
> You are right, as we have DPCD cached, we can do it from DPCD too, and 
> in fact that was my first implementation.
> But then I thought what if some driver doesn't cache DPCD, so thought it 
> would be good to have a helper function
> to check this out.
> If you think DPCD would be a better idea, I need not to touch DRM layer 
> at all, and this will be only I915 implementation.

Yeah, less code seems like a good thing. I think we might even have that
OUI stuff already read out and cached for other purposes.

> 
> - Shashank
> >
> >> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >> Cc: Imre Deak <imre.deak@intel.com>
> >> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
> >> ---
> >>   drivers/gpu/drm/drm_dp_dual_mode_helper.c | 24 ++++++++++++++++++++++++
> >>   include/drm/drm_dp_dual_mode_helper.h     |  4 +++-
> >>   2 files changed, 27 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/drivers/gpu/drm/drm_dp_dual_mode_helper.c b/drivers/gpu/drm/drm_dp_dual_mode_helper.c
> >> index 80e62f6..0b890dc 100644
> >> --- a/drivers/gpu/drm/drm_dp_dual_mode_helper.c
> >> +++ b/drivers/gpu/drm/drm_dp_dual_mode_helper.c
> >> @@ -396,6 +396,30 @@ const char *drm_dp_get_dual_mode_type_name(enum drm_dp_dual_mode_type type)
> >>   EXPORT_SYMBOL(drm_dp_get_dual_mode_type_name);
> >>   
> >>   /**
> >> + * drm_lspcon_get_vendor_oui: match vendor OUI signature
> >> + * @adapter: i2c adapter under action
> >> + * @vendor_id = 3 bytes of vendor OUI signature, LSB=lower byte
> >> + *
> >> + * Returns:
> >> + * Vendor OUI id if got one, 0 if not
> >> + */
> >> +uint32_t drm_lspcon_get_vendor_oui(struct i2c_adapter *adapter)
> >> +{
> >> +	uint8_t sign[3] = {0, };
> >> +	uint32_t oui = 0;
> >> +
> >> +	if (drm_dp_dual_mode_read(adapter, DP_DUAL_MODE_LSPCON_OUI_OFFSET,
> >> +						sign, 3)) {
> >> +		DRM_ERROR("Can't identify vendor sign\n");
> >> +		return 0;
> >> +	}
> >> +
> >> +	oui = (sign[0] << 16) | (sign[1] << 8) | sign[2];
> >> +	return oui;
> >> +}
> >> +EXPORT_SYMBOL(drm_lspcon_get_vendor_oui);
> >> +
> >> +/**
> >>    * drm_lspcon_get_mode: Get LSPCON's current mode of operation by
> >>    * reading offset (0x80, 0x41)
> >>    * @adapter: I2C-over-aux adapter
> >> diff --git a/include/drm/drm_dp_dual_mode_helper.h b/include/drm/drm_dp_dual_mode_helper.h
> >> index 4c42db8..f81b526 100644
> >> --- a/include/drm/drm_dp_dual_mode_helper.h
> >> +++ b/include/drm/drm_dp_dual_mode_helper.h
> >> @@ -60,7 +60,8 @@
> >>   /* LSPCON specific registers, defined by MCA */
> >>   #define DP_DUAL_MODE_LSPCON_MODE_CHANGE		0x40
> >>   #define DP_DUAL_MODE_LSPCON_CURRENT_MODE		0x41
> >> -#define  DP_DUAL_MODE_LSPCON_MODE_PCON			0x1
> >> +#define DP_DUAL_MODE_LSPCON_MODE_PCON			0x1
> >> +#define DP_DUAL_MODE_LSPCON_OUI_OFFSET			0x11
> >>   
> >>   struct i2c_adapter;
> >>   
> >> @@ -116,4 +117,5 @@ int drm_lspcon_get_mode(struct i2c_adapter *adapter,
> >>   			enum drm_lspcon_mode *current_mode);
> >>   int drm_lspcon_set_mode(struct i2c_adapter *adapter,
> >>   			enum drm_lspcon_mode reqd_mode);
> >> +uint32_t drm_lspcon_get_vendor_oui(struct i2c_adapter *adapter);
> >>   #endif
> >> -- 
> >> 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] 76+ messages in thread

* Re: [PATCH 20/20] drm/i915: write AVI infoframes for LSPCON
  2017-07-13 12:27       ` Ville Syrjälä
@ 2017-07-13 12:39         ` Sharma, Shashank
  2017-07-13 12:55           ` Ville Syrjälä
  0 siblings, 1 reply; 76+ messages in thread
From: Sharma, Shashank @ 2017-07-13 12:39 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, dri-devel

Regards

Shashank


On 7/13/2017 5:57 PM, Ville Syrjälä wrote:
> On Thu, Jul 13, 2017 at 11:11:53AM +0530, Sharma, Shashank wrote:
>> Regards
>>
>> Shashank
>>
>>
>> On 7/12/2017 10:54 PM, Ville Syrjälä wrote:
>>> On Mon, Jul 10, 2017 at 04:48:48PM +0530, Shashank Sharma wrote:
>>>> LSPCON chips can't pick the HDMI AVI infoframes from direct link.
>>>> In order to pass AVI infoframes from display controller to LSPCON,
>>>> we have to write infoframe packets into vendor specified AUX address.
>>>>
>>>> Also, LSPCON vendors provide AUX offsets, to inform the LSPCON
>>>> chip that the AVI IF packets are written, so that the firmware
>>>> can pick it up and apply.
>>>>
>>>> This patch adds function to write AVI infoframes for both MCA as
>>>> well as Parade Tech LSPCON chips. These two vendors provide different
>>>> methods for writing infoframes, so this patch contains two different
>>>> functions, one for each.
>>> Seems to me that we should also be checking the receiver cap for the
>>> 444->420 conversion support, and enable it in the PROTOCOL_CONVERTER
>>> DPCD register. Or are these LSPCON things even ignoring that part of the
>>> spec?
>> Yes, LSPCON just needs the YCBCR444 input, and info frames for 420, and
>> it would take care of
>> 444->420 conversion in FW.
> So it snoops the AVI infoframe we write to it to figure out that it has
> to do the 444->420 downsampling?
Yes, that's exactly what it does.
- Shashank
>> Also, its a part of LSPCON specs, that it has
>> to have 420 output capability.
>>
>> - Shashank
>>>> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>>> Cc: Imre Deak <imre.deak@intel.com>
>>>> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
>>>> ---
>>>>    drivers/gpu/drm/i915/intel_ddi.c    |   8 ++
>>>>    drivers/gpu/drm/i915/intel_drv.h    |   3 +
>>>>    drivers/gpu/drm/i915/intel_lspcon.c | 174 ++++++++++++++++++++++++++++++++++++
>>>>    3 files changed, 185 insertions(+)
>>>>
>>>> diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
>>>> index f691710..944d9d5 100644
>>>> --- a/drivers/gpu/drm/i915/intel_ddi.c
>>>> +++ b/drivers/gpu/drm/i915/intel_ddi.c
>>>> @@ -2068,6 +2068,14 @@ void intel_ddi_set_avi_infoframe(struct drm_encoder *encoder,
>>>>    					   rgb_qrange_limited,
>>>>    					   rgb_qrange_selectable);
>>>>    
>>>> +	if (crtc_state->lspcon_active) {
>>>> +		struct intel_lspcon *lspcon = enc_to_intel_lspcon(encoder);
>>>> +
>>>> +		/* LSPCON writes infoframes via AUX */
>>>> +		lspcon->write_infoframe(encoder, crtc_state, &frame);
>>>> +		return;
>>>> +	}
>>>> +
>>>>    	intel_write_infoframe(encoder, crtc_state, &frame);
>>>>    }
>>>>    
>>>> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
>>>> index fad9a53..3e686d2 100644
>>>> --- a/drivers/gpu/drm/i915/intel_drv.h
>>>> +++ b/drivers/gpu/drm/i915/intel_drv.h
>>>> @@ -1079,6 +1079,9 @@ struct intel_lspcon {
>>>>    	/* AVI IF setup function for LSPCON */
>>>>    	void (*set_infoframes)(struct drm_encoder *encoder,
>>>>    				const struct intel_crtc_state *crtc_state);
>>>> +	void (*write_infoframe)(struct drm_encoder *encoder,
>>>> +				const struct intel_crtc_state *crtc_state,
>>>> +				union hdmi_infoframe *frame);
>>>>    };
>>>>    
>>>>    struct intel_digital_port {
>>>> diff --git a/drivers/gpu/drm/i915/intel_lspcon.c b/drivers/gpu/drm/i915/intel_lspcon.c
>>>> index 53ddd39..01fddf7 100644
>>>> --- a/drivers/gpu/drm/i915/intel_lspcon.c
>>>> +++ b/drivers/gpu/drm/i915/intel_lspcon.c
>>>> @@ -31,6 +31,18 @@
>>>>    #define LSPCON_VENDOR_PARADE_OUI 0x001CF8
>>>>    #define LSPCON_VENDOR_MCA_OUI 0x0060AD
>>>>    
>>>> +/* AUX addresses to write AVI IF into */
>>>> +#define LSPCON_MCA_AVI_IF_WRITE_OFFSET 0x5C0
>>>> +#define LSPCON_MCA_AVI_IF_CTRL 0x5DF
>>>> +#define  LSPCON_MCA_AVI_IF_KICKOFF (1 << 0)
>>>> +#define  LSPCON_MCA_AVI_IF_HANDLED (1 << 1)
>>>> +
>>>> +#define LSPCON_PARADE_AVI_IF_WRITE_OFFSET 0x516
>>>> +#define LSPCON_PARADE_AVI_IF_CTRL 0x51E
>>>> +#define  LSPCON_PARADE_AVI_IF_KICKOFF (1 << 7)
>>>> +#define LSPCON_PARADE_AVI_IF_STATUS 0x51F
>>>> +#define  LSPCON_PARADE_AVI_IF_HANDLED (2 << 6)
>>>> +
>>>>    static struct intel_dp *lspcon_to_intel_dp(struct intel_lspcon *lspcon)
>>>>    {
>>>>    	struct intel_digital_port *dig_port =
>>>> @@ -217,6 +229,167 @@ bool lspcon_ycbcr420_config(struct drm_connector *connector,
>>>>    	return false;
>>>>    }
>>>>    
>>>> +static bool _lspcon_write_infoframe_parade(struct drm_dp_aux *aux,
>>>> +					   uint8_t *buffer, ssize_t len)
>>>> +{
>>>> +	u8 avi_if_ctrl;
>>>> +	u8 avi_if_status;
>>>> +	u8 count = 0;
>>>> +	u8 retry = 5;
>>>> +	u8 avi_buf[8] = {0, };
>>>> +	uint16_t reg;
>>>> +	ssize_t ret;
>>>> +
>>>> +	while (count++ < 4) {
>>>> +
>>>> +		do {
>>>> +			/* Is LSPCON FW ready */
>>>> +			reg = LSPCON_PARADE_AVI_IF_CTRL;
>>>> +			ret = drm_dp_dpcd_read(aux, reg, &avi_if_ctrl, 1);
>>>> +			if (ret < 0) {
>>>> +				DRM_ERROR("DPCD read failed, add:0x%x\n", reg);
>>>> +				return false;
>>>> +			}
>>>> +
>>>> +			if (avi_if_ctrl & LSPCON_PARADE_AVI_IF_KICKOFF)
>>>> +				break;
>>>> +			usleep_range(100, 200);
>>>> +		} while (--retry);
>>>> +
>>>> +		if (!(avi_if_ctrl & LSPCON_PARADE_AVI_IF_KICKOFF)) {
>>>> +			DRM_ERROR("LSPCON FW not ready for infoframes\n");
>>>> +			return false;
>>>> +		}
>>>> +
>>>> +		/*
>>>> +		 * AVI Infoframe contains 31 bytes of data:
>>>> +		 *	HB0 to HB2   (3 bytes header)
>>>> +		 *	PB0 to PB27 (28 bytes data)
>>>> +		 * As per Parade spec, while sending first block (8bytes),
>>>> +		 * byte 0 is kept for request token no, and byte1 - byte7
>>>> +		 * contain frame data. So we have to pack frame like this:
>>>> +		 *	first block of 8 bytes: <token> <HB0-HB2> <PB0-PB3>
>>>> +		 *	next 3 blocks: <PB4-PB27>
>>>> +		 */
>>>> +		if (count)
>>>> +			memcpy(avi_buf, buffer + count * 8 - 1, 8);
>>>> +		else {
>>>> +			avi_buf[0] = 1;
>>>> +			memcpy(&avi_buf[1], buffer, 7);
>>>> +		}
>>>> +
>>>> +		/* Write 8 bytes of data at a time */
>>>> +		reg = LSPCON_PARADE_AVI_IF_WRITE_OFFSET;
>>>> +		ret = drm_dp_dpcd_write(aux, reg, avi_buf, 8);
>>>> +		if (ret < 0) {
>>>> +			DRM_ERROR("DPCD write failed, add:0x%x\n", reg);
>>>> +			return false;
>>>> +		}
>>>> +
>>>> +		/*
>>>> +		 * While sending a block of 8 byes, we need to inform block
>>>> +		 * number to FW, by programming bits[1:0] of ctrl reg with
>>>> +		 * block number
>>>> +		 */
>>>> +		avi_if_ctrl = 0x80 + count;
>>>> +		reg = LSPCON_PARADE_AVI_IF_CTRL;
>>>> +		ret = drm_dp_dpcd_write(aux, reg, &avi_if_ctrl, 1);
>>>> +		if (ret < 0) {
>>>> +			DRM_ERROR("DPCD write failed, add:0x%x\n", reg);
>>>> +			return false;
>>>> +		}
>>>> +	}
>>>> +
>>>> +	/* Check LSPCON FW status */
>>>> +	reg = LSPCON_PARADE_AVI_IF_STATUS;
>>>> +	ret = drm_dp_dpcd_read(aux, reg, &avi_if_status, 1);
>>>> +	if (ret < 0) {
>>>> +		DRM_ERROR("DPCD write failed, address 0x%x\n", reg);
>>>> +		return false;
>>>> +	}
>>>> +
>>>> +	if (avi_if_status & LSPCON_PARADE_AVI_IF_HANDLED)
>>>> +		DRM_DEBUG_KMS("AVI IF handled by FW\n");
>>>> +
>>>> +	return true;
>>>> +}
>>>> +
>>>> +static bool _lspcon_write_infoframe_mca(struct drm_dp_aux *aux,
>>>> +					uint8_t *buffer, ssize_t len)
>>>> +{
>>>> +	int ret;
>>>> +	uint32_t val = 0;
>>>> +	uint16_t reg;
>>>> +	uint8_t *data = buffer;
>>>> +
>>>> +	reg = LSPCON_MCA_AVI_IF_WRITE_OFFSET;
>>>> +	while (val < len) {
>>>> +		ret = drm_dp_dpcd_write(aux, reg, data, 1);
>>>> +		if (ret < 0) {
>>>> +			DRM_ERROR("DPCD write failed, add:0x%x\n", reg);
>>>> +			return false;
>>>> +		}
>>>> +		val++; reg++; data++;
>>>> +	}
>>>> +
>>>> +	val = 0;
>>>> +	reg = LSPCON_MCA_AVI_IF_CTRL;
>>>> +	ret = drm_dp_dpcd_read(aux, reg, &val, 1);
>>>> +	if (ret < 0) {
>>>> +		DRM_ERROR("DPCD read failed, address 0x%x\n", reg);
>>>> +		return false;
>>>> +	}
>>>> +
>>>> +	/* Indicate LSPCON chip about infoframe, clear bit 1 and set bit 0 */
>>>> +	val &= ~LSPCON_MCA_AVI_IF_HANDLED;
>>>> +	val |= LSPCON_MCA_AVI_IF_KICKOFF;
>>>> +
>>>> +	ret = drm_dp_dpcd_write(aux, reg, &val, 1);
>>>> +	if (ret < 0) {
>>>> +		DRM_ERROR("DPCD read failed, address 0x%x\n", reg);
>>>> +		return false;
>>>> +	}
>>>> +
>>>> +	val = 0;
>>>> +	ret = drm_dp_dpcd_read(aux, reg, &val, 1);
>>>> +	if (ret < 0) {
>>>> +		DRM_ERROR("DPCD read failed, address 0x%x\n", reg);
>>>> +		return false;
>>>> +	}
>>>> +
>>>> +	if (val == LSPCON_MCA_AVI_IF_HANDLED)
>>>> +		DRM_DEBUG_KMS("AVI IF handled by FW\n");
>>>> +
>>>> +	return true;
>>>> +}
>>>> +
>>>> +void lspcon_write_infoframe(struct drm_encoder *encoder,
>>>> +				  const struct intel_crtc_state *crtc_state,
>>>> +				  union hdmi_infoframe *frame)
>>>> +{
>>>> +	bool ret;
>>>> +	ssize_t len;
>>>> +	uint8_t buf[VIDEO_DIP_DATA_SIZE];
>>>> +	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
>>>> +	struct intel_lspcon *lspcon = enc_to_intel_lspcon(encoder);
>>>> +
>>>> +	len = hdmi_infoframe_pack(frame, buf, sizeof(buf));
>>>> +	if (len < 0) {
>>>> +		DRM_ERROR("Failed to pack AVI IF\n");
>>>> +		return;
>>>> +	}
>>>> +
>>>> +	if (lspcon->vendor == LSPCON_VENDOR_MCA)
>>>> +		ret = _lspcon_write_infoframe_mca(&intel_dp->aux, buf, len);
>>>> +	else
>>>> +		ret = _lspcon_write_infoframe_parade(&intel_dp->aux, buf, len);
>>>> +
>>>> +	if (!ret)
>>>> +		DRM_ERROR("Failed to write AVI infoframes\n");
>>>> +	else
>>>> +		DRM_DEBUG_DRIVER("AVI infoframes updated successfully\n");
>>>> +}
>>>> +
>>>>    void lspcon_resume(struct intel_lspcon *lspcon)
>>>>    {
>>>>    	enum drm_lspcon_mode expected_mode;
>>>> @@ -282,6 +455,7 @@ bool lspcon_init(struct intel_digital_port *intel_dig_port)
>>>>    
>>>>    	connector->ycbcr_420_allowed = true;
>>>>    	lspcon->set_infoframes = intel_ddi_set_avi_infoframe;
>>>> +	lspcon->write_infoframe = lspcon_write_infoframe;
>>>>    	drm_dp_read_desc(&dp->aux, &dp->desc, drm_dp_is_branch(dp->dpcd));
>>>>    
>>>>    	DRM_DEBUG_KMS("Success: LSPCON init\n");
>>>> -- 
>>>> 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] 76+ messages in thread

* Re: [PATCH 06/20] drm: add helper to validate YCBCR420 modes
  2017-07-13 12:31       ` Ville Syrjälä
@ 2017-07-13 12:42         ` Sharma, Shashank
  2017-07-13 13:00           ` Ville Syrjälä
  0 siblings, 1 reply; 76+ messages in thread
From: Sharma, Shashank @ 2017-07-13 12:42 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, dri-devel

Regards

Shashank


On 7/13/2017 6:01 PM, Ville Syrjälä wrote:
> On Thu, Jul 13, 2017 at 11:02:18AM +0530, Sharma, Shashank wrote:
>> Regards
>>
>> Shashank
>>
>>
>> On 7/12/2017 10:48 PM, Ville Syrjälä wrote:
>>> On Mon, Jul 10, 2017 at 04:48:34PM +0530, Shashank Sharma wrote:
>>>> YCBCR420 modes are supported only on HDMI 2.0 capable sources.
>>>> This patch adds:
>>>> - A drm helper to validate YCBCR420-only mode on a particular
>>>>     connector. This function will help pruning the YCBCR420-only
>>>>     modes from the connector's modelist.
>>>> - 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 YCBCR420 output, so that no
>>>>     YCBCR 420 modes will be listed for sources which can't handle it.
>>>>     A driver should set this variable if it wants to see YCBCR420 modes
>>>>     in the modedb.
>>>>
>>>> V5: Introduced the patch in series.
>>>> V5-resend: Squashed two patches (validate YCBCR420 and add YCBCR420
>>>> 	   identifier)
>>>>
>>>> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
>>>> ---
>>>>    drivers/gpu/drm/drm_edid.c         |  3 ++-
>>>>    drivers/gpu/drm/drm_modes.c        | 28 ++++++++++++++++++++++++++++
>>>>    drivers/gpu/drm/drm_probe_helper.c |  4 ++++
>>>>    include/drm/drm_connector.h        |  9 +++++++++
>>>>    include/drm/drm_edid.h             |  1 +
>>>>    include/drm/drm_modes.h            |  5 +++++
>>>>    6 files changed, 49 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
>>>> index 10dab62..44be128 100644
>>>> --- a/drivers/gpu/drm/drm_edid.c
>>>> +++ b/drivers/gpu/drm/drm_edid.c
>>>> @@ -2950,10 +2950,11 @@ 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);
>>>>    }
>>>> +EXPORT_SYMBOL(drm_valid_cea_vic);
>>>>    
>>>>    /**
>>>>     * drm_get_cea_aspect_ratio - get the picture aspect ratio corresponding to
>>>> diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
>>>> index f2493b9..3b53c8e3 100644
>>>> --- a/drivers/gpu/drm/drm_modes.c
>>>> +++ b/drivers/gpu/drm/drm_modes.c
>>>> @@ -1083,6 +1083,34 @@ drm_mode_validate_size(const struct drm_display_mode *mode,
>>>>    }
>>>>    EXPORT_SYMBOL(drm_mode_validate_size);
>>>>    
>>>> +/**
>>>> + * drm_mode_ycbcr420_only - add 'ycbcr420-only' modes only when allowed
>>>> + * @mode: mode to check
>>>> + * @connector: drm connector under action
>>>> + *
>>>> + * This function is a helper which can be used to filter out any YCBCR420
>>>> + * only mode, when the source doesn't support it.
>>>> + *
>>>> + * Returns:
>>>> + * The mode status
>>>> + */
>>>> +enum drm_mode_status
>>>> +drm_mode_validate_ycbcr420(const struct drm_display_mode *mode,
>>>> +			   struct drm_connector *connector)
>>>> +{
>>>> +	u8 vic = drm_match_cea_mode(mode);
>>>> +	enum drm_mode_status status = MODE_OK;
>>>> +	struct drm_hdmi_info *hdmi = &connector->display_info.hdmi;
>>>> +
>>>> +	if (drm_valid_cea_vic(vic) && test_bit(vic, hdmi->y420_vdb_modes)) {
>>> Still think the valid check is pointless.
>> I still think that we should only pass valid CEA VIC to VDB check, but
>> Ok, I will remove that.
>>>    Skipping that would also avoid
>>> having to make the function non-static
>> Ok
>>> (the EXPORT_SYMBOL there seems
>>> unnecessary either way).
>> Why ?
> It's all in the same module AFAICS.
>
> Oh, and the patch ordering here still looks potentially problematic. We
> should add the 420 mode validation before we start adding the 420 modes.
> Otherwise anyone bisecting through this may get a black/corrupted screen
> if they have a monitor with "420 only" modes.
Actually, the 420 mode validation patch uses 420_only bitmap, which is 
added in add_420_modes patch.
So I can't put this patch before other one (you reviewed that sequence 
once, and found that).
- Shashank
>>>> +		if (!connector->ycbcr_420_allowed)
>>>> +			status = MODE_NO_420;
>>>> +	}
>>>> +
>>>> +	return status;
>>>> +}
>>>> +EXPORT_SYMBOL(drm_mode_validate_ycbcr420);
>>>> +
>>>>    #define MODE_STATUS(status) [MODE_ ## status + 3] = #status
>>>>    
>>>>    static const char * const drm_mode_status_names[] = {
>>> ^
>>> This thing needs to be updated as well.
>> Oh sorry, good catch.
>> - Shashank
>>>> diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
>>>> index 00e6832..904966c 100644
>>>> --- a/drivers/gpu/drm/drm_probe_helper.c
>>>> +++ b/drivers/gpu/drm/drm_probe_helper.c
>>>> @@ -528,6 +528,10 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
>>>>    		if (mode->status == MODE_OK)
>>>>    			mode->status = drm_mode_validate_pipeline(mode,
>>>>    								  connector);
>>>> +
>>>> +		if (mode->status == MODE_OK)
>>>> +			mode->status = drm_mode_validate_ycbcr420(mode,
>>>> +								  connector);
>>>>    	}
>>>>    
>>>>    prune:
>>>> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
>>>> index b3af8e3..225e092 100644
>>>> --- a/include/drm/drm_connector.h
>>>> +++ b/include/drm/drm_connector.h
>>>> @@ -746,6 +746,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.
>>>> diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
>>>> index 89c0062..b55b2a7 100644
>>>> --- a/include/drm/drm_edid.h
>>>> +++ b/include/drm/drm_edid.h
>>>> @@ -477,4 +477,5 @@ void drm_edid_get_monitor_name(struct edid *edid, char *name,
>>>>    struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
>>>>    					   int hsize, int vsize, int fresh,
>>>>    					   bool rb);
>>>> +bool drm_valid_cea_vic(u8 vic);
>>>>    #endif /* __DRM_EDID_H__ */
>>>> diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h
>>>> index 94ac771..f8a1268 100644
>>>> --- a/include/drm/drm_modes.h
>>>> +++ b/include/drm/drm_modes.h
>>>> @@ -80,6 +80,7 @@ struct videomode;
>>>>     * @MODE_ONE_SIZE: only one resolution is supported
>>>>     * @MODE_NO_REDUCED: monitor doesn't accept reduced blanking
>>>>     * @MODE_NO_STEREO: stereo modes not supported
>>>> + * @MODE_NO_420: ycbcr 420 modes not supported
>>>>     * @MODE_STALE: mode has become stale
>>>>     * @MODE_BAD: unspecified reason
>>>>     * @MODE_ERROR: error condition
>>>> @@ -124,6 +125,7 @@ enum drm_mode_status {
>>>>    	MODE_ONE_SIZE,
>>>>    	MODE_NO_REDUCED,
>>>>    	MODE_NO_STEREO,
>>>> +	MODE_NO_420,
>>>>    	MODE_STALE = -3,
>>>>    	MODE_BAD = -2,
>>>>    	MODE_ERROR = -1
>>>> @@ -496,6 +498,9 @@ bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1,
>>>>    enum drm_mode_status drm_mode_validate_basic(const struct drm_display_mode *mode);
>>>>    enum drm_mode_status drm_mode_validate_size(const struct drm_display_mode *mode,
>>>>    					    int maxX, int maxY);
>>>> +enum drm_mode_status
>>>> +drm_mode_validate_ycbcr420(const struct drm_display_mode *mode,
>>>> +			   struct drm_connector *connector);
>>>>    void drm_mode_prune_invalid(struct drm_device *dev,
>>>>    			    struct list_head *mode_list, bool verbose);
>>>>    void drm_mode_sort(struct list_head *mode_list);
>>>> -- 
>>>> 2.7.4
>>>>
>>>> _______________________________________________
>>>> dri-devel mailing list
>>>> dri-devel@lists.freedesktop.org
>>>> https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

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

* Re: [PATCH 08/20] drm: set output colorspace in AVI infoframe
  2017-07-13 12:35       ` Ville Syrjälä
@ 2017-07-13 12:49         ` Sharma, Shashank
  2017-07-13 13:03           ` Ville Syrjälä
  0 siblings, 1 reply; 76+ messages in thread
From: Sharma, Shashank @ 2017-07-13 12:49 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, dri-devel

Regards

Shashank


On 7/13/2017 6:05 PM, Ville Syrjälä wrote:
> On Thu, Jul 13, 2017 at 10:37:53AM +0530, Sharma, Shashank wrote:
>> Regards
>>
>> Shashank
>>
>>
>> On 7/12/2017 10:47 PM, Ville Syrjälä wrote:
>>> On Mon, Jul 10, 2017 at 04:48:36PM +0530, Shashank Sharma wrote:
>>>> A source must set output colorspace information in AVI
>>>> infoframes, so that the sink can decode upcoming frames
>>>> accordingly.
>>>>
>>>> This patch adds a function to add the output colorspace
>>>> information in the AVI infoframes.
>>>>
>>>> V2: Rebase
>>>> V3: Rebase
>>>> V4: Rebase
>>>> V5: Rebase
>>>> V6: Made patch independent of HDMI output type.
>>>>
>>>> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
>>>> ---
>>>>    drivers/gpu/drm/drm_edid.c | 29 +++++++++++++++++++++++++++++
>>>>    include/drm/drm_edid.h     |  5 +++++
>>>>    2 files changed, 34 insertions(+)
>>>>
>>>> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
>>>> index 944a28f..cede86e 100644
>>>> --- a/drivers/gpu/drm/drm_edid.c
>>>> +++ b/drivers/gpu/drm/drm_edid.c
>>>> @@ -4796,6 +4796,35 @@ 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 hdmi_colorspace colorspace)
>>>> +{
>>>> +	if (colorspace > HDMI_COLORSPACE_YUV420 ||
>>>> +		colorspace < HDMI_COLORSPACE_RGB) {
>>>> +		DRM_ERROR("Invalid color space type\n");
>>>> +		return -EINVAL;
>>>> +	}
>>> Seems overly defensive. I'd say that if someone insists on writing
>>> buggy code just let them do it.
>> :) yep can be done, you know, its a new implementation, don't want to
>> create unnecessary noise so being
>> a bit defensive :)
>>>> +
>>>> +	frame->colorspace = colorspace;
>>>> +	if (colorspace == HDMI_COLORSPACE_YUV420)
>>>> +		frame->pixel_repeat = 0;
>>> Most VICs don't allow pixel repeat in 444/etc. either, and we don't
>>> protect against that. So this looks like pretty pointless check in
>>> this form.
>>>
>>> So IMO just drop this entire patch and just assign frame->colorspace in
>>> the driver.
>> Actually YCBCR420 section of spec specifically calls out for not
>> allowing repetition, also, when I tested this on a
>> HDMI 2.0 analyzer, if was giving a AVI IF failure on pixel_repeat not 0,
>> so IMHO it would be a good idea to keep
>> this and get the tests passing.
> That's just papering over bugs elsewhere. If we can't use pixel repeat
> with a specific mode, then we should have rejected that mode much earlier.
I dint get this point, HDMI 2.0 spec section 7.1 says "when YCBCR420 
encoding is active, pixel repetition is not allowed" and
pixel repetition field should be set to = 0, in AVI IF.  This seems to 
be like - if you are displaying YCBCR420, set PR=0 regardless of
mode, isn't it ?

- Shashank
>> - Shashank
>>>> +
>>>> +	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 aa58146..b79e0cb 100644
>>>> --- a/include/drm/drm_edid.h
>>>> +++ b/include/drm/drm_edid.h
>>>> @@ -332,6 +332,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);
>>>> @@ -354,6 +355,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 hdmi_colorspace colorspace);
>>>> +int
>>>>    drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame,
>>>>    					    const struct drm_display_mode *mode);
>>>>    void
>>>> -- 
>>>> 2.7.4
>>>>
>>>> _______________________________________________
>>>> dri-devel mailing list
>>>> dri-devel@lists.freedesktop.org
>>>> https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

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

* Re: [PATCH 16/20] drm: add function to read vendor OUI
  2017-07-13 12:37       ` Ville Syrjälä
@ 2017-07-13 12:50         ` Sharma, Shashank
  0 siblings, 0 replies; 76+ messages in thread
From: Sharma, Shashank @ 2017-07-13 12:50 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, dri-devel

Regards

Shashank


On 7/13/2017 6:07 PM, Ville Syrjälä wrote:
> On Thu, Jul 13, 2017 at 10:34:26AM +0530, Sharma, Shashank wrote:
>> Regads
>>
>> Shashank
>>
>>
>> On 7/12/2017 10:45 PM, Ville Syrjälä wrote:
>>> On Mon, Jul 10, 2017 at 04:48:44PM +0530, Shashank Sharma wrote:
>>>> This patch adds a helper function in DP dual mode layer to
>>>> read the vendor's IEEE OUI signature from a Dual mode adapter.
>>>> This will be used to differentiate between different LSPCON
>>>> vendors, to address their custom programming requirements.
>>> Can't we just read it from DPCD instead?
>> You are right, as we have DPCD cached, we can do it from DPCD too, and
>> in fact that was my first implementation.
>> But then I thought what if some driver doesn't cache DPCD, so thought it
>> would be good to have a helper function
>> to check this out.
>> If you think DPCD would be a better idea, I need not to touch DRM layer
>> at all, and this will be only I915 implementation.
> Yeah, less code seems like a good thing. I think we might even have that
> OUI stuff already read out and cached for other purposes.
Sure, then, I will extract OUI and cache it in a variable.
- Shashank
>> - Shashank
>>>> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>>> Cc: Imre Deak <imre.deak@intel.com>
>>>> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
>>>> ---
>>>>    drivers/gpu/drm/drm_dp_dual_mode_helper.c | 24 ++++++++++++++++++++++++
>>>>    include/drm/drm_dp_dual_mode_helper.h     |  4 +++-
>>>>    2 files changed, 27 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/drm_dp_dual_mode_helper.c b/drivers/gpu/drm/drm_dp_dual_mode_helper.c
>>>> index 80e62f6..0b890dc 100644
>>>> --- a/drivers/gpu/drm/drm_dp_dual_mode_helper.c
>>>> +++ b/drivers/gpu/drm/drm_dp_dual_mode_helper.c
>>>> @@ -396,6 +396,30 @@ const char *drm_dp_get_dual_mode_type_name(enum drm_dp_dual_mode_type type)
>>>>    EXPORT_SYMBOL(drm_dp_get_dual_mode_type_name);
>>>>    
>>>>    /**
>>>> + * drm_lspcon_get_vendor_oui: match vendor OUI signature
>>>> + * @adapter: i2c adapter under action
>>>> + * @vendor_id = 3 bytes of vendor OUI signature, LSB=lower byte
>>>> + *
>>>> + * Returns:
>>>> + * Vendor OUI id if got one, 0 if not
>>>> + */
>>>> +uint32_t drm_lspcon_get_vendor_oui(struct i2c_adapter *adapter)
>>>> +{
>>>> +	uint8_t sign[3] = {0, };
>>>> +	uint32_t oui = 0;
>>>> +
>>>> +	if (drm_dp_dual_mode_read(adapter, DP_DUAL_MODE_LSPCON_OUI_OFFSET,
>>>> +						sign, 3)) {
>>>> +		DRM_ERROR("Can't identify vendor sign\n");
>>>> +		return 0;
>>>> +	}
>>>> +
>>>> +	oui = (sign[0] << 16) | (sign[1] << 8) | sign[2];
>>>> +	return oui;
>>>> +}
>>>> +EXPORT_SYMBOL(drm_lspcon_get_vendor_oui);
>>>> +
>>>> +/**
>>>>     * drm_lspcon_get_mode: Get LSPCON's current mode of operation by
>>>>     * reading offset (0x80, 0x41)
>>>>     * @adapter: I2C-over-aux adapter
>>>> diff --git a/include/drm/drm_dp_dual_mode_helper.h b/include/drm/drm_dp_dual_mode_helper.h
>>>> index 4c42db8..f81b526 100644
>>>> --- a/include/drm/drm_dp_dual_mode_helper.h
>>>> +++ b/include/drm/drm_dp_dual_mode_helper.h
>>>> @@ -60,7 +60,8 @@
>>>>    /* LSPCON specific registers, defined by MCA */
>>>>    #define DP_DUAL_MODE_LSPCON_MODE_CHANGE		0x40
>>>>    #define DP_DUAL_MODE_LSPCON_CURRENT_MODE		0x41
>>>> -#define  DP_DUAL_MODE_LSPCON_MODE_PCON			0x1
>>>> +#define DP_DUAL_MODE_LSPCON_MODE_PCON			0x1
>>>> +#define DP_DUAL_MODE_LSPCON_OUI_OFFSET			0x11
>>>>    
>>>>    struct i2c_adapter;
>>>>    
>>>> @@ -116,4 +117,5 @@ int drm_lspcon_get_mode(struct i2c_adapter *adapter,
>>>>    			enum drm_lspcon_mode *current_mode);
>>>>    int drm_lspcon_set_mode(struct i2c_adapter *adapter,
>>>>    			enum drm_lspcon_mode reqd_mode);
>>>> +uint32_t drm_lspcon_get_vendor_oui(struct i2c_adapter *adapter);
>>>>    #endif
>>>> -- 
>>>> 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] 76+ messages in thread

* Re: [PATCH 13/20] drm/i915: prepare csc unit for YCBCR420 output
  2017-07-13  5:14     ` Sharma, Shashank
@ 2017-07-13 12:50       ` Ville Syrjälä
  2017-07-13 12:53         ` Sharma, Shashank
  0 siblings, 1 reply; 76+ messages in thread
From: Ville Syrjälä @ 2017-07-13 12:50 UTC (permalink / raw)
  To: Sharma, Shashank; +Cc: intel-gfx, dri-devel

On Thu, Jul 13, 2017 at 10:44:51AM +0530, Sharma, Shashank wrote:
> Regards
> 
> Shashank
> 
> 
> On 7/12/2017 10:47 PM, Ville Syrjälä wrote:
> > On Mon, Jul 10, 2017 at 04:48:41PM +0530, Shashank Sharma wrote:
> >> To support ycbcr output, we need a pipe CSC block to do
> >> RGB->YCBCR conversion.
> >>
> >> 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, which uses recommended bspec
> >> values to perform RGB->YCBCR conversion (target color space BT709)
> >>
> >> V2: Rebase
> >> V3: Rebase
> >> V4: Rebase
> >> V5: Addressed review comments from Ander
> >>      - Remove extra line added in the patch
> >>      - Add the spec details in the commit message
> >>      - Combine two if(cond) while calling intel_crtc_compute_config
> >> V6: Handle YCBCR420 outputs only (Ville)
> >>
> >> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
> >> ---
> >>   drivers/gpu/drm/i915/intel_color.c   | 47 +++++++++++++++++++++++++++++++++++-
> >>   drivers/gpu/drm/i915/intel_display.c | 17 +++++++++++++
> >>   2 files changed, 63 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/drivers/gpu/drm/i915/intel_color.c b/drivers/gpu/drm/i915/intel_color.c
> >> index 306c6b0..8a5d211 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 */
> > Are these BT.601 or BT.709 or something else?
> I thought I added some comment mentioning this being BT 709, but looks 
> like dealing with too many paptches :)
> Will add those details.
> >> +#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
> > IIRC Ander didn't like these, and neither do I. I'd much prefer to reuse
> > the code we alreayd have for dealing with the CSC. Except I think that's
> > pretty broken in places so I guess we can go with this for now and try
> > to clean up the color management stuff later.
> Yes, that was the plan. I was planning to fix the complete CSC cleanup 
> stuff in a separate patch, but as that needs much
> of validation before we can merge it, I added in a bottom half. I will 
> send a patch for the same soon.
> >> +
> >>   /*
> >>    * 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 */
> > I don't understand what this comment is trying so say.
> Yeah, it should have been "we dont use pre-offsets for conversion"

I think that's very obvious from the code. So no need for comment IMO.

> >
> >> +	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 */

In fact pretty much all the comments in this patch seem redundant.
Comments should explain why we do something, if necessary. They
should not just transcribe the actual code into words.

> >> +	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->ycbcr420) {
> >> +		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 b4a6415..c5ff568 100644
> >> --- a/drivers/gpu/drm/i915/intel_display.c
> >> +++ b/drivers/gpu/drm/i915/intel_display.c
> >> @@ -6288,6 +6288,23 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
> >>   		return -EINVAL;
> >>   	}
> >>   
> >> +	/* YCBCR420 feasibility check */
> >> +	if (pipe_config->ycbcr420) {
> >> +		struct drm_crtc_state *drm_state = &pipe_config->base;
> >> +
> >> +		/*
> >> +		 * There is only one pipe CSC unit per pipe, and we need that
> >> +		 * for output conversion from RGB->YCBCR. So if CTM is already
> >> +		 * applied we can't support YCBCR420 output.
> >> +		 */
> >> +		if (drm_state->ctm) {
> >> +			DRM_ERROR("YCBCR420 and CTM is not possible\n");
> > DRM_DEBUG_KMS
> We are failing an atomic_check(), shouldn't this be highlighted ?

No. Any user can trigger this at will, and we don't want to spam dmesg
with user triggerable errors. If you'll look around you'll see pretty
much all error cases in the modeset paths use DRM_DEBUG_KMS/ATOMIC
rather than DRM_ERROR. DRM_ERROR/etc. should be reserved for cases where
the error wasn't caused by the user but rather eg. due to failing
hardware.

> >
> >> +			return -EINVAL;
> >> +		}
> >> +
> >> +		DRM_DEBUG_KMS("YCBCR420 output is possible from CRTC\n");
> > Seems like a fairly pointless debug print.
> Yeah, ok.
> - Shashank
> >> +	}
> >> +
> >>   	/*
> >>   	 * Pipe horizontal size must be even in:
> >>   	 * - DVO ganged mode
> >> -- 
> >> 2.7.4
> >>
> >> _______________________________________________
> >> dri-devel mailing list
> >> dri-devel@lists.freedesktop.org
> >> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
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] 76+ messages in thread

* Re: [Intel-gfx] [PATCH 11/20] drm/i915: prepare scaler for YCBCR420 modeset
  2017-07-13  5:21     ` Sharma, Shashank
@ 2017-07-13 12:52       ` Ville Syrjälä
  2017-07-13 12:57         ` Sharma, Shashank
  0 siblings, 1 reply; 76+ messages in thread
From: Ville Syrjälä @ 2017-07-13 12:52 UTC (permalink / raw)
  To: Sharma, Shashank; +Cc: intel-gfx, dri-devel

On Thu, Jul 13, 2017 at 10:51:04AM +0530, Sharma, Shashank wrote:
> Regards
> 
> Shashank
> 
> 
> On 7/12/2017 10:47 PM, Ville Syrjälä wrote:
> > On Mon, Jul 10, 2017 at 04:48:39PM +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
> >> V5: addressed review comments from Ander:
> >>      - No need to check both scaler_user && hdmi_output.
> >>        Check for scaler_user is enough.
> >> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
> >> ---
> >>   drivers/gpu/drm/i915/intel_atomic.c  |  6 ++++++
> >>   drivers/gpu/drm/i915/intel_display.c | 23 +++++++++++++++++++++++
> >>   drivers/gpu/drm/i915/intel_drv.h     | 10 +++++++++-
> >>   drivers/gpu/drm/i915/intel_hdmi.c    | 12 ++++++++++++
> >>   drivers/gpu/drm/i915/intel_panel.c   |  3 ++-
> >>   5 files changed, 52 insertions(+), 2 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
> >> index 36d4e63..040d111 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_420_OUTPUT_INDEX) {
> > I think Ander already said that we should just tie this into the normal
> > pfit pipe scaler user. I agree. Having to users doesn't actually make
> > sense because there can be only one pipe scaler, and if we want to do
> > scaled 4:2:0 output then we anyway need to handle both cases
> > simultaneosly.
> I thought our idea of having a separate scalar user was a good one, 
> because, this gives additional information
> how and why the scalar is being used. Also, we dont program the other 
> scaling factors in this case, but we get
> the scaling profile set using PIPEMISC. So I would prefer to have this 
> as a special case or separate user, but you
> can think about this, and let me know.

Eventually we'll want scaling and 420 at the same time. So a separate
user just doesn't work.

> 
> - Shashank
> >
> >> +			name = "YCBCR420-OUTPUT";
> >> +			idx = intel_crtc->base.base.id;
> >> +
> >> +			/* YCBCR420 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 01900e1..c56081e 100644
> >> --- a/drivers/gpu/drm/i915/intel_display.c
> >> +++ b/drivers/gpu/drm/i915/intel_display.c
> >> @@ -4621,6 +4621,9 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
> >>   	 */
> >>   	need_scaling = src_w != dst_w || src_h != dst_h;
> >>   
> >> +	if (scaler_user == SKL_420_OUTPUT_INDEX)
> >> +		need_scaling = true;
> >> +
> >>   	/*
> >>   	 * if plane is being disabled or scaler is no more required or force detach
> >>   	 *  - free scaler binded to this plane/crtc
> >> @@ -4668,6 +4671,26 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
> >>   }
> >>   
> >>   /**
> >> + * skl_update_scaler_crtc_420_output - Stages update to scaler state
> >> + * for YCBCR420 which 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_420_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_420_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
> >> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> >> index 592243b..68b4fba 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
> >> +
> >> +	/*
> >> +	 * YCBCR 420 output consume a scaler. So adding a user
> >> +	 * for 420 output requirement.
> >> +	 */
> >> +#define SKL_420_OUTPUT_INDEX 30
> >>   	unsigned scaler_users;
> >>   
> >>   	/* scaler used by crtc for panel fitting purpose */
> >> @@ -1483,6 +1490,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_420_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 276d916..9e8d784 100644
> >> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> >> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> >> @@ -1355,6 +1355,7 @@ intel_hdmi_ycbcr420_config(struct drm_connector *connector,
> >>   			       struct intel_crtc_state *config,
> >>   			       int *clock_12bpc, int *clock_8bpc)
> >>   {
> >> +	struct intel_crtc *intel_crtc = to_intel_crtc(config->base.crtc);
> >>   
> >>   	if (!connector->ycbcr_420_allowed) {
> >>   		DRM_ERROR("Platform doesn't support YCBCR420 output\n");
> >> @@ -1366,6 +1367,17 @@ intel_hdmi_ycbcr420_config(struct drm_connector *connector,
> >>   	*clock_12bpc /= 2;
> >>   	*clock_8bpc /= 2;
> >>   	config->ycbcr420 = true;
> >> +
> >> +	/* YCBCR 420 output conversion needs a scaler */
> >> +	if (skl_update_scaler_crtc_420_output(config)) {
> >> +		DRM_ERROR("Scaler allocation for output failed\n");
> >> +		return false;
> >> +	}
> >> +
> >> +	/* Bind this scaler to pipe */
> >> +	intel_pch_panel_fitting(intel_crtc, config,
> >> +				DRM_MODE_SCALE_FULLSCREEN);
> >> +
> >>   	return true;
> >>   }
> >>   
> >> diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
> >> index 96c2cbd..fd2e081 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->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

-- 
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] 76+ messages in thread

* Re: [PATCH 10/20] drm/i915: add config function for YCBCR420 outputs
  2017-07-13  5:26     ` Sharma, Shashank
@ 2017-07-13 12:53       ` Ville Syrjälä
  2017-07-13 13:01         ` Sharma, Shashank
  0 siblings, 1 reply; 76+ messages in thread
From: Ville Syrjälä @ 2017-07-13 12:53 UTC (permalink / raw)
  To: Sharma, Shashank; +Cc: intel-gfx, dri-devel

On Thu, Jul 13, 2017 at 10:56:06AM +0530, Sharma, Shashank wrote:
> Regards
> 
> Shashank
> 
> 
> On 7/12/2017 10:47 PM, Ville Syrjälä wrote:
> > On Mon, Jul 10, 2017 at 04:48:38PM +0530, Shashank Sharma wrote:
> >> This patch checks encoder level support for YCBCR420 outputs.
> >> The logic goes as simple as this:
> >> If the input mode is YCBCR420-only mode: prepare HDMI for
> >> YCBCR420 output, else continue with RGB output mode.
> >>
> >> It checks if the mode is YCBCR420 and source can support this
> >> output then it marks the ycbcr_420 output indicator 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
> >> V5: Rebase
> >> V6: Check and handle YCBCR420-only modes, discard the property
> >>      based approach (Ville)
> >>
> >> 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    | 42 +++++++++++++++++++++++++++++++++---
> >>   3 files changed, 43 insertions(+), 3 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> >> index 4e03ca6..01900e1 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(ycbcr420);
> >>   
> >>   	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 d17a324..592243b 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 */
> >> +	bool ycbcr420;
> >>   };
> >>   
> >>   struct intel_crtc {
> >> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> >> index cc0d100..276d916 100644
> >> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> >> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> >> @@ -1305,7 +1305,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,
> >> +				bool output_ycbcr420)
> > You alreayd have the crtc state, so no need to pass that stuff
> > separately.
> Ah, this was dumb, thanks !
> >>   {
> >>   	struct drm_i915_private *dev_priv =
> >>   		to_i915(crtc_state->base.crtc->dev);
> >> @@ -1330,6 +1331,13 @@ static bool hdmi_12bpc_possible(struct intel_crtc_state *crtc_state)
> >>   		if (connector_state->crtc != crtc_state->base.crtc)
> >>   			continue;
> >>   
> >> +		if (output_ycbcr420) {
> >> +			const struct drm_hdmi_info *hdmi = &info->hdmi;
> >> +
> >> +			if (!(hdmi->y420_dc_modes & DRM_EDID_YCBCR420_DC_36))
> >> +				return false;
> >> +		}
> >> +
> > else?
> Oops, needs an else { break;}

I was thinking 'else if ...'

> 
> - Shashank
> >
> >>   		if ((info->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_36) == 0)
> >>   			return false;
> >>   	}
> >> @@ -1342,6 +1350,25 @@ static bool hdmi_12bpc_possible(struct intel_crtc_state *crtc_state)
> >>   	return true;
> >>   }
> >>   
> >> +static bool
> >> +intel_hdmi_ycbcr420_config(struct drm_connector *connector,
> >> +			       struct intel_crtc_state *config,
> >> +			       int *clock_12bpc, int *clock_8bpc)
> >> +{
> >> +
> >> +	if (!connector->ycbcr_420_allowed) {
> >> +		DRM_ERROR("Platform doesn't support YCBCR420 output\n");
> >> +		return false;
> >> +	}
> >> +
> >> +	/* YCBCR420 TMDS rate requirement is half the pixel clock */
> >> +	config->port_clock /= 2;
> >> +	*clock_12bpc /= 2;
> >> +	*clock_8bpc /= 2;
> >> +	config->ycbcr420 = true;
> >> +	return true;
> >> +}
> >> +
> >>   bool intel_hdmi_compute_config(struct intel_encoder *encoder,
> >>   			       struct intel_crtc_state *pipe_config,
> >>   			       struct drm_connector_state *conn_state)
> >> @@ -1349,7 +1376,8 @@ 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;
> >> @@ -1379,6 +1407,14 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
> >>   		clock_12bpc *= 2;
> >>   	}
> >>   
> >> +	if (drm_mode_is_420_only(&connector->display_info, adjusted_mode)) {
> >> +		if (!intel_hdmi_ycbcr420_config(connector, pipe_config,
> >> +						&clock_12bpc, &clock_8bpc)) {
> >> +			DRM_ERROR("Can't support YCBCR420 output\n");
> >> +			return false;
> >> +		}
> >> +	}
> >> +
> >>   	if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv))
> >>   		pipe_config->has_pch_encoder = true;
> >>   
> >> @@ -1398,7 +1434,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, pipe_config->ycbcr420)) {
> >>   		DRM_DEBUG_KMS("picking bpc to 12 for HDMI output\n");
> >>   		desired_bpp = 12*3;
> >>   
> >> -- 
> >> 2.7.4
> >>
> >> _______________________________________________
> >> dri-devel mailing list
> >> dri-devel@lists.freedesktop.org
> >> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
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] 76+ messages in thread

* Re: [PATCH 13/20] drm/i915: prepare csc unit for YCBCR420 output
  2017-07-13 12:50       ` Ville Syrjälä
@ 2017-07-13 12:53         ` Sharma, Shashank
  0 siblings, 0 replies; 76+ messages in thread
From: Sharma, Shashank @ 2017-07-13 12:53 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, dri-devel

Regards

Shashank


On 7/13/2017 6:20 PM, Ville Syrjälä wrote:
> On Thu, Jul 13, 2017 at 10:44:51AM +0530, Sharma, Shashank wrote:
>> Regards
>>
>> Shashank
>>
>>
>> On 7/12/2017 10:47 PM, Ville Syrjälä wrote:
>>> On Mon, Jul 10, 2017 at 04:48:41PM +0530, Shashank Sharma wrote:
>>>> To support ycbcr output, we need a pipe CSC block to do
>>>> RGB->YCBCR conversion.
>>>>
>>>> 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, which uses recommended bspec
>>>> values to perform RGB->YCBCR conversion (target color space BT709)
>>>>
>>>> V2: Rebase
>>>> V3: Rebase
>>>> V4: Rebase
>>>> V5: Addressed review comments from Ander
>>>>       - Remove extra line added in the patch
>>>>       - Add the spec details in the commit message
>>>>       - Combine two if(cond) while calling intel_crtc_compute_config
>>>> V6: Handle YCBCR420 outputs only (Ville)
>>>>
>>>> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
>>>> ---
>>>>    drivers/gpu/drm/i915/intel_color.c   | 47 +++++++++++++++++++++++++++++++++++-
>>>>    drivers/gpu/drm/i915/intel_display.c | 17 +++++++++++++
>>>>    2 files changed, 63 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/i915/intel_color.c b/drivers/gpu/drm/i915/intel_color.c
>>>> index 306c6b0..8a5d211 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 */
>>> Are these BT.601 or BT.709 or something else?
>> I thought I added some comment mentioning this being BT 709, but looks
>> like dealing with too many paptches :)
>> Will add those details.
>>>> +#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
>>> IIRC Ander didn't like these, and neither do I. I'd much prefer to reuse
>>> the code we alreayd have for dealing with the CSC. Except I think that's
>>> pretty broken in places so I guess we can go with this for now and try
>>> to clean up the color management stuff later.
>> Yes, that was the plan. I was planning to fix the complete CSC cleanup
>> stuff in a separate patch, but as that needs much
>> of validation before we can merge it, I added in a bottom half. I will
>> send a patch for the same soon.
>>>> +
>>>>    /*
>>>>     * 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 */
>>> I don't understand what this comment is trying so say.
>> Yeah, it should have been "we dont use pre-offsets for conversion"
> I think that's very obvious from the code. So no need for comment IMO.
Ok.
>>>> +	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 */
> In fact pretty much all the comments in this patch seem redundant.
> Comments should explain why we do something, if necessary. They
> should not just transcribe the actual code into words.
Ok.
>>>> +	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->ycbcr420) {
>>>> +		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 b4a6415..c5ff568 100644
>>>> --- a/drivers/gpu/drm/i915/intel_display.c
>>>> +++ b/drivers/gpu/drm/i915/intel_display.c
>>>> @@ -6288,6 +6288,23 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
>>>>    		return -EINVAL;
>>>>    	}
>>>>    
>>>> +	/* YCBCR420 feasibility check */
>>>> +	if (pipe_config->ycbcr420) {
>>>> +		struct drm_crtc_state *drm_state = &pipe_config->base;
>>>> +
>>>> +		/*
>>>> +		 * There is only one pipe CSC unit per pipe, and we need that
>>>> +		 * for output conversion from RGB->YCBCR. So if CTM is already
>>>> +		 * applied we can't support YCBCR420 output.
>>>> +		 */
>>>> +		if (drm_state->ctm) {
>>>> +			DRM_ERROR("YCBCR420 and CTM is not possible\n");
>>> DRM_DEBUG_KMS
>> We are failing an atomic_check(), shouldn't this be highlighted ?
> No. Any user can trigger this at will, and we don't want to spam dmesg
> with user triggerable errors. If you'll look around you'll see pretty
> much all error cases in the modeset paths use DRM_DEBUG_KMS/ATOMIC
> rather than DRM_ERROR. DRM_ERROR/etc. should be reserved for cases where
> the error wasn't caused by the user but rather eg. due to failing
> hardware.
Ok, got it.
- Shashank
>>>> +			return -EINVAL;
>>>> +		}
>>>> +
>>>> +		DRM_DEBUG_KMS("YCBCR420 output is possible from CRTC\n");
>>> Seems like a fairly pointless debug print.
>> Yeah, ok.
>> - Shashank
>>>> +	}
>>>> +
>>>>    	/*
>>>>    	 * Pipe horizontal size must be even in:
>>>>    	 * - DVO ganged mode
>>>> -- 
>>>> 2.7.4
>>>>
>>>> _______________________________________________
>>>> dri-devel mailing list
>>>> dri-devel@lists.freedesktop.org
>>>> https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

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

* Re: [PATCH 20/20] drm/i915: write AVI infoframes for LSPCON
  2017-07-13 12:39         ` Sharma, Shashank
@ 2017-07-13 12:55           ` Ville Syrjälä
  2017-07-13 13:10             ` Sharma, Shashank
  0 siblings, 1 reply; 76+ messages in thread
From: Ville Syrjälä @ 2017-07-13 12:55 UTC (permalink / raw)
  To: Sharma, Shashank; +Cc: intel-gfx, dri-devel

On Thu, Jul 13, 2017 at 06:09:53PM +0530, Sharma, Shashank wrote:
> Regards
> 
> Shashank
> 
> 
> On 7/13/2017 5:57 PM, Ville Syrjälä wrote:
> > On Thu, Jul 13, 2017 at 11:11:53AM +0530, Sharma, Shashank wrote:
> >> Regards
> >>
> >> Shashank
> >>
> >>
> >> On 7/12/2017 10:54 PM, Ville Syrjälä wrote:
> >>> On Mon, Jul 10, 2017 at 04:48:48PM +0530, Shashank Sharma wrote:
> >>>> LSPCON chips can't pick the HDMI AVI infoframes from direct link.
> >>>> In order to pass AVI infoframes from display controller to LSPCON,
> >>>> we have to write infoframe packets into vendor specified AUX address.
> >>>>
> >>>> Also, LSPCON vendors provide AUX offsets, to inform the LSPCON
> >>>> chip that the AVI IF packets are written, so that the firmware
> >>>> can pick it up and apply.
> >>>>
> >>>> This patch adds function to write AVI infoframes for both MCA as
> >>>> well as Parade Tech LSPCON chips. These two vendors provide different
> >>>> methods for writing infoframes, so this patch contains two different
> >>>> functions, one for each.
> >>> Seems to me that we should also be checking the receiver cap for the
> >>> 444->420 conversion support, and enable it in the PROTOCOL_CONVERTER
> >>> DPCD register. Or are these LSPCON things even ignoring that part of the
> >>> spec?
> >> Yes, LSPCON just needs the YCBCR444 input, and info frames for 420, and
> >> it would take care of
> >> 444->420 conversion in FW.
> > So it snoops the AVI infoframe we write to it to figure out that it has
> > to do the 444->420 downsampling?
> Yes, that's exactly what it does.

Can you add a comment somewhere appropriate to make that clear.
Otherwise people might wonder why we're not enabling the downsampling at
all.

Does LSPCON then not even implement the PROTOCOL_CONVERTER DCPD
registers?

Can you send the spec for this stuff my way? What I have now doesn't
document any DPCD registers.

> - Shashank
> >> Also, its a part of LSPCON specs, that it has
> >> to have 420 output capability.
> >>
> >> - Shashank
> >>>> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >>>> Cc: Imre Deak <imre.deak@intel.com>
> >>>> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
> >>>> ---
> >>>>    drivers/gpu/drm/i915/intel_ddi.c    |   8 ++
> >>>>    drivers/gpu/drm/i915/intel_drv.h    |   3 +
> >>>>    drivers/gpu/drm/i915/intel_lspcon.c | 174 ++++++++++++++++++++++++++++++++++++
> >>>>    3 files changed, 185 insertions(+)
> >>>>
> >>>> diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> >>>> index f691710..944d9d5 100644
> >>>> --- a/drivers/gpu/drm/i915/intel_ddi.c
> >>>> +++ b/drivers/gpu/drm/i915/intel_ddi.c
> >>>> @@ -2068,6 +2068,14 @@ void intel_ddi_set_avi_infoframe(struct drm_encoder *encoder,
> >>>>    					   rgb_qrange_limited,
> >>>>    					   rgb_qrange_selectable);
> >>>>    
> >>>> +	if (crtc_state->lspcon_active) {
> >>>> +		struct intel_lspcon *lspcon = enc_to_intel_lspcon(encoder);
> >>>> +
> >>>> +		/* LSPCON writes infoframes via AUX */
> >>>> +		lspcon->write_infoframe(encoder, crtc_state, &frame);
> >>>> +		return;
> >>>> +	}
> >>>> +
> >>>>    	intel_write_infoframe(encoder, crtc_state, &frame);
> >>>>    }
> >>>>    
> >>>> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> >>>> index fad9a53..3e686d2 100644
> >>>> --- a/drivers/gpu/drm/i915/intel_drv.h
> >>>> +++ b/drivers/gpu/drm/i915/intel_drv.h
> >>>> @@ -1079,6 +1079,9 @@ struct intel_lspcon {
> >>>>    	/* AVI IF setup function for LSPCON */
> >>>>    	void (*set_infoframes)(struct drm_encoder *encoder,
> >>>>    				const struct intel_crtc_state *crtc_state);
> >>>> +	void (*write_infoframe)(struct drm_encoder *encoder,
> >>>> +				const struct intel_crtc_state *crtc_state,
> >>>> +				union hdmi_infoframe *frame);
> >>>>    };
> >>>>    
> >>>>    struct intel_digital_port {
> >>>> diff --git a/drivers/gpu/drm/i915/intel_lspcon.c b/drivers/gpu/drm/i915/intel_lspcon.c
> >>>> index 53ddd39..01fddf7 100644
> >>>> --- a/drivers/gpu/drm/i915/intel_lspcon.c
> >>>> +++ b/drivers/gpu/drm/i915/intel_lspcon.c
> >>>> @@ -31,6 +31,18 @@
> >>>>    #define LSPCON_VENDOR_PARADE_OUI 0x001CF8
> >>>>    #define LSPCON_VENDOR_MCA_OUI 0x0060AD
> >>>>    
> >>>> +/* AUX addresses to write AVI IF into */
> >>>> +#define LSPCON_MCA_AVI_IF_WRITE_OFFSET 0x5C0
> >>>> +#define LSPCON_MCA_AVI_IF_CTRL 0x5DF
> >>>> +#define  LSPCON_MCA_AVI_IF_KICKOFF (1 << 0)
> >>>> +#define  LSPCON_MCA_AVI_IF_HANDLED (1 << 1)
> >>>> +
> >>>> +#define LSPCON_PARADE_AVI_IF_WRITE_OFFSET 0x516
> >>>> +#define LSPCON_PARADE_AVI_IF_CTRL 0x51E
> >>>> +#define  LSPCON_PARADE_AVI_IF_KICKOFF (1 << 7)
> >>>> +#define LSPCON_PARADE_AVI_IF_STATUS 0x51F
> >>>> +#define  LSPCON_PARADE_AVI_IF_HANDLED (2 << 6)
> >>>> +
> >>>>    static struct intel_dp *lspcon_to_intel_dp(struct intel_lspcon *lspcon)
> >>>>    {
> >>>>    	struct intel_digital_port *dig_port =
> >>>> @@ -217,6 +229,167 @@ bool lspcon_ycbcr420_config(struct drm_connector *connector,
> >>>>    	return false;
> >>>>    }
> >>>>    
> >>>> +static bool _lspcon_write_infoframe_parade(struct drm_dp_aux *aux,
> >>>> +					   uint8_t *buffer, ssize_t len)
> >>>> +{
> >>>> +	u8 avi_if_ctrl;
> >>>> +	u8 avi_if_status;
> >>>> +	u8 count = 0;
> >>>> +	u8 retry = 5;
> >>>> +	u8 avi_buf[8] = {0, };
> >>>> +	uint16_t reg;
> >>>> +	ssize_t ret;
> >>>> +
> >>>> +	while (count++ < 4) {
> >>>> +
> >>>> +		do {
> >>>> +			/* Is LSPCON FW ready */
> >>>> +			reg = LSPCON_PARADE_AVI_IF_CTRL;
> >>>> +			ret = drm_dp_dpcd_read(aux, reg, &avi_if_ctrl, 1);
> >>>> +			if (ret < 0) {
> >>>> +				DRM_ERROR("DPCD read failed, add:0x%x\n", reg);
> >>>> +				return false;
> >>>> +			}
> >>>> +
> >>>> +			if (avi_if_ctrl & LSPCON_PARADE_AVI_IF_KICKOFF)
> >>>> +				break;
> >>>> +			usleep_range(100, 200);
> >>>> +		} while (--retry);
> >>>> +
> >>>> +		if (!(avi_if_ctrl & LSPCON_PARADE_AVI_IF_KICKOFF)) {
> >>>> +			DRM_ERROR("LSPCON FW not ready for infoframes\n");
> >>>> +			return false;
> >>>> +		}
> >>>> +
> >>>> +		/*
> >>>> +		 * AVI Infoframe contains 31 bytes of data:
> >>>> +		 *	HB0 to HB2   (3 bytes header)
> >>>> +		 *	PB0 to PB27 (28 bytes data)
> >>>> +		 * As per Parade spec, while sending first block (8bytes),
> >>>> +		 * byte 0 is kept for request token no, and byte1 - byte7
> >>>> +		 * contain frame data. So we have to pack frame like this:
> >>>> +		 *	first block of 8 bytes: <token> <HB0-HB2> <PB0-PB3>
> >>>> +		 *	next 3 blocks: <PB4-PB27>
> >>>> +		 */
> >>>> +		if (count)
> >>>> +			memcpy(avi_buf, buffer + count * 8 - 1, 8);
> >>>> +		else {
> >>>> +			avi_buf[0] = 1;
> >>>> +			memcpy(&avi_buf[1], buffer, 7);
> >>>> +		}
> >>>> +
> >>>> +		/* Write 8 bytes of data at a time */
> >>>> +		reg = LSPCON_PARADE_AVI_IF_WRITE_OFFSET;
> >>>> +		ret = drm_dp_dpcd_write(aux, reg, avi_buf, 8);
> >>>> +		if (ret < 0) {
> >>>> +			DRM_ERROR("DPCD write failed, add:0x%x\n", reg);
> >>>> +			return false;
> >>>> +		}
> >>>> +
> >>>> +		/*
> >>>> +		 * While sending a block of 8 byes, we need to inform block
> >>>> +		 * number to FW, by programming bits[1:0] of ctrl reg with
> >>>> +		 * block number
> >>>> +		 */
> >>>> +		avi_if_ctrl = 0x80 + count;
> >>>> +		reg = LSPCON_PARADE_AVI_IF_CTRL;
> >>>> +		ret = drm_dp_dpcd_write(aux, reg, &avi_if_ctrl, 1);
> >>>> +		if (ret < 0) {
> >>>> +			DRM_ERROR("DPCD write failed, add:0x%x\n", reg);
> >>>> +			return false;
> >>>> +		}
> >>>> +	}
> >>>> +
> >>>> +	/* Check LSPCON FW status */
> >>>> +	reg = LSPCON_PARADE_AVI_IF_STATUS;
> >>>> +	ret = drm_dp_dpcd_read(aux, reg, &avi_if_status, 1);
> >>>> +	if (ret < 0) {
> >>>> +		DRM_ERROR("DPCD write failed, address 0x%x\n", reg);
> >>>> +		return false;
> >>>> +	}
> >>>> +
> >>>> +	if (avi_if_status & LSPCON_PARADE_AVI_IF_HANDLED)
> >>>> +		DRM_DEBUG_KMS("AVI IF handled by FW\n");
> >>>> +
> >>>> +	return true;
> >>>> +}
> >>>> +
> >>>> +static bool _lspcon_write_infoframe_mca(struct drm_dp_aux *aux,
> >>>> +					uint8_t *buffer, ssize_t len)
> >>>> +{
> >>>> +	int ret;
> >>>> +	uint32_t val = 0;
> >>>> +	uint16_t reg;
> >>>> +	uint8_t *data = buffer;
> >>>> +
> >>>> +	reg = LSPCON_MCA_AVI_IF_WRITE_OFFSET;
> >>>> +	while (val < len) {
> >>>> +		ret = drm_dp_dpcd_write(aux, reg, data, 1);
> >>>> +		if (ret < 0) {
> >>>> +			DRM_ERROR("DPCD write failed, add:0x%x\n", reg);
> >>>> +			return false;
> >>>> +		}
> >>>> +		val++; reg++; data++;
> >>>> +	}
> >>>> +
> >>>> +	val = 0;
> >>>> +	reg = LSPCON_MCA_AVI_IF_CTRL;
> >>>> +	ret = drm_dp_dpcd_read(aux, reg, &val, 1);
> >>>> +	if (ret < 0) {
> >>>> +		DRM_ERROR("DPCD read failed, address 0x%x\n", reg);
> >>>> +		return false;
> >>>> +	}
> >>>> +
> >>>> +	/* Indicate LSPCON chip about infoframe, clear bit 1 and set bit 0 */
> >>>> +	val &= ~LSPCON_MCA_AVI_IF_HANDLED;
> >>>> +	val |= LSPCON_MCA_AVI_IF_KICKOFF;
> >>>> +
> >>>> +	ret = drm_dp_dpcd_write(aux, reg, &val, 1);
> >>>> +	if (ret < 0) {
> >>>> +		DRM_ERROR("DPCD read failed, address 0x%x\n", reg);
> >>>> +		return false;
> >>>> +	}
> >>>> +
> >>>> +	val = 0;
> >>>> +	ret = drm_dp_dpcd_read(aux, reg, &val, 1);
> >>>> +	if (ret < 0) {
> >>>> +		DRM_ERROR("DPCD read failed, address 0x%x\n", reg);
> >>>> +		return false;
> >>>> +	}
> >>>> +
> >>>> +	if (val == LSPCON_MCA_AVI_IF_HANDLED)
> >>>> +		DRM_DEBUG_KMS("AVI IF handled by FW\n");
> >>>> +
> >>>> +	return true;
> >>>> +}
> >>>> +
> >>>> +void lspcon_write_infoframe(struct drm_encoder *encoder,
> >>>> +				  const struct intel_crtc_state *crtc_state,
> >>>> +				  union hdmi_infoframe *frame)
> >>>> +{
> >>>> +	bool ret;
> >>>> +	ssize_t len;
> >>>> +	uint8_t buf[VIDEO_DIP_DATA_SIZE];
> >>>> +	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> >>>> +	struct intel_lspcon *lspcon = enc_to_intel_lspcon(encoder);
> >>>> +
> >>>> +	len = hdmi_infoframe_pack(frame, buf, sizeof(buf));
> >>>> +	if (len < 0) {
> >>>> +		DRM_ERROR("Failed to pack AVI IF\n");
> >>>> +		return;
> >>>> +	}
> >>>> +
> >>>> +	if (lspcon->vendor == LSPCON_VENDOR_MCA)
> >>>> +		ret = _lspcon_write_infoframe_mca(&intel_dp->aux, buf, len);
> >>>> +	else
> >>>> +		ret = _lspcon_write_infoframe_parade(&intel_dp->aux, buf, len);
> >>>> +
> >>>> +	if (!ret)
> >>>> +		DRM_ERROR("Failed to write AVI infoframes\n");
> >>>> +	else
> >>>> +		DRM_DEBUG_DRIVER("AVI infoframes updated successfully\n");
> >>>> +}
> >>>> +
> >>>>    void lspcon_resume(struct intel_lspcon *lspcon)
> >>>>    {
> >>>>    	enum drm_lspcon_mode expected_mode;
> >>>> @@ -282,6 +455,7 @@ bool lspcon_init(struct intel_digital_port *intel_dig_port)
> >>>>    
> >>>>    	connector->ycbcr_420_allowed = true;
> >>>>    	lspcon->set_infoframes = intel_ddi_set_avi_infoframe;
> >>>> +	lspcon->write_infoframe = lspcon_write_infoframe;
> >>>>    	drm_dp_read_desc(&dp->aux, &dp->desc, drm_dp_is_branch(dp->dpcd));
> >>>>    
> >>>>    	DRM_DEBUG_KMS("Success: LSPCON init\n");
> >>>> -- 
> >>>> 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] 76+ messages in thread

* Re: [PATCH 11/20] drm/i915: prepare scaler for YCBCR420 modeset
  2017-07-13 12:52       ` [Intel-gfx] " Ville Syrjälä
@ 2017-07-13 12:57         ` Sharma, Shashank
  2017-07-13 13:05           ` Ville Syrjälä
  0 siblings, 1 reply; 76+ messages in thread
From: Sharma, Shashank @ 2017-07-13 12:57 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, dri-devel

Regards

Shashank


On 7/13/2017 6:22 PM, Ville Syrjälä wrote:
> On Thu, Jul 13, 2017 at 10:51:04AM +0530, Sharma, Shashank wrote:
>> Regards
>>
>> Shashank
>>
>>
>> On 7/12/2017 10:47 PM, Ville Syrjälä wrote:
>>> On Mon, Jul 10, 2017 at 04:48:39PM +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
>>>> V5: addressed review comments from Ander:
>>>>       - No need to check both scaler_user && hdmi_output.
>>>>         Check for scaler_user is enough.
>>>> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
>>>> ---
>>>>    drivers/gpu/drm/i915/intel_atomic.c  |  6 ++++++
>>>>    drivers/gpu/drm/i915/intel_display.c | 23 +++++++++++++++++++++++
>>>>    drivers/gpu/drm/i915/intel_drv.h     | 10 +++++++++-
>>>>    drivers/gpu/drm/i915/intel_hdmi.c    | 12 ++++++++++++
>>>>    drivers/gpu/drm/i915/intel_panel.c   |  3 ++-
>>>>    5 files changed, 52 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
>>>> index 36d4e63..040d111 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_420_OUTPUT_INDEX) {
>>> I think Ander already said that we should just tie this into the normal
>>> pfit pipe scaler user. I agree. Having to users doesn't actually make
>>> sense because there can be only one pipe scaler, and if we want to do
>>> scaled 4:2:0 output then we anyway need to handle both cases
>>> simultaneosly.
>> I thought our idea of having a separate scalar user was a good one,
>> because, this gives additional information
>> how and why the scalar is being used. Also, we dont program the other
>> scaling factors in this case, but we get
>> the scaling profile set using PIPEMISC. So I would prefer to have this
>> as a special case or separate user, but you
>> can think about this, and let me know.
> Eventually we'll want scaling and 420 at the same time. So a separate
> user just doesn't work.
Ok, I was just following the design, which we discussed during F2F. I 
will remove this user then.
- Shashank
>> - Shashank
>>>> +			name = "YCBCR420-OUTPUT";
>>>> +			idx = intel_crtc->base.base.id;
>>>> +
>>>> +			/* YCBCR420 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 01900e1..c56081e 100644
>>>> --- a/drivers/gpu/drm/i915/intel_display.c
>>>> +++ b/drivers/gpu/drm/i915/intel_display.c
>>>> @@ -4621,6 +4621,9 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
>>>>    	 */
>>>>    	need_scaling = src_w != dst_w || src_h != dst_h;
>>>>    
>>>> +	if (scaler_user == SKL_420_OUTPUT_INDEX)
>>>> +		need_scaling = true;
>>>> +
>>>>    	/*
>>>>    	 * if plane is being disabled or scaler is no more required or force detach
>>>>    	 *  - free scaler binded to this plane/crtc
>>>> @@ -4668,6 +4671,26 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
>>>>    }
>>>>    
>>>>    /**
>>>> + * skl_update_scaler_crtc_420_output - Stages update to scaler state
>>>> + * for YCBCR420 which 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_420_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_420_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
>>>> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
>>>> index 592243b..68b4fba 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
>>>> +
>>>> +	/*
>>>> +	 * YCBCR 420 output consume a scaler. So adding a user
>>>> +	 * for 420 output requirement.
>>>> +	 */
>>>> +#define SKL_420_OUTPUT_INDEX 30
>>>>    	unsigned scaler_users;
>>>>    
>>>>    	/* scaler used by crtc for panel fitting purpose */
>>>> @@ -1483,6 +1490,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_420_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 276d916..9e8d784 100644
>>>> --- a/drivers/gpu/drm/i915/intel_hdmi.c
>>>> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
>>>> @@ -1355,6 +1355,7 @@ intel_hdmi_ycbcr420_config(struct drm_connector *connector,
>>>>    			       struct intel_crtc_state *config,
>>>>    			       int *clock_12bpc, int *clock_8bpc)
>>>>    {
>>>> +	struct intel_crtc *intel_crtc = to_intel_crtc(config->base.crtc);
>>>>    
>>>>    	if (!connector->ycbcr_420_allowed) {
>>>>    		DRM_ERROR("Platform doesn't support YCBCR420 output\n");
>>>> @@ -1366,6 +1367,17 @@ intel_hdmi_ycbcr420_config(struct drm_connector *connector,
>>>>    	*clock_12bpc /= 2;
>>>>    	*clock_8bpc /= 2;
>>>>    	config->ycbcr420 = true;
>>>> +
>>>> +	/* YCBCR 420 output conversion needs a scaler */
>>>> +	if (skl_update_scaler_crtc_420_output(config)) {
>>>> +		DRM_ERROR("Scaler allocation for output failed\n");
>>>> +		return false;
>>>> +	}
>>>> +
>>>> +	/* Bind this scaler to pipe */
>>>> +	intel_pch_panel_fitting(intel_crtc, config,
>>>> +				DRM_MODE_SCALE_FULLSCREEN);
>>>> +
>>>>    	return true;
>>>>    }
>>>>    
>>>> diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
>>>> index 96c2cbd..fd2e081 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->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

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

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

* Re: [PATCH 06/20] drm: add helper to validate YCBCR420 modes
  2017-07-13 12:42         ` Sharma, Shashank
@ 2017-07-13 13:00           ` Ville Syrjälä
  2017-07-13 13:12             ` Sharma, Shashank
  0 siblings, 1 reply; 76+ messages in thread
From: Ville Syrjälä @ 2017-07-13 13:00 UTC (permalink / raw)
  To: Sharma, Shashank; +Cc: intel-gfx, dri-devel

On Thu, Jul 13, 2017 at 06:12:50PM +0530, Sharma, Shashank wrote:
> Regards
> 
> Shashank
> 
> 
> On 7/13/2017 6:01 PM, Ville Syrjälä wrote:
> > On Thu, Jul 13, 2017 at 11:02:18AM +0530, Sharma, Shashank wrote:
> >> Regards
> >>
> >> Shashank
> >>
> >>
> >> On 7/12/2017 10:48 PM, Ville Syrjälä wrote:
> >>> On Mon, Jul 10, 2017 at 04:48:34PM +0530, Shashank Sharma wrote:
> >>>> YCBCR420 modes are supported only on HDMI 2.0 capable sources.
> >>>> This patch adds:
> >>>> - A drm helper to validate YCBCR420-only mode on a particular
> >>>>     connector. This function will help pruning the YCBCR420-only
> >>>>     modes from the connector's modelist.
> >>>> - 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 YCBCR420 output, so that no
> >>>>     YCBCR 420 modes will be listed for sources which can't handle it.
> >>>>     A driver should set this variable if it wants to see YCBCR420 modes
> >>>>     in the modedb.
> >>>>
> >>>> V5: Introduced the patch in series.
> >>>> V5-resend: Squashed two patches (validate YCBCR420 and add YCBCR420
> >>>> 	   identifier)
> >>>>
> >>>> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
> >>>> ---
> >>>>    drivers/gpu/drm/drm_edid.c         |  3 ++-
> >>>>    drivers/gpu/drm/drm_modes.c        | 28 ++++++++++++++++++++++++++++
> >>>>    drivers/gpu/drm/drm_probe_helper.c |  4 ++++
> >>>>    include/drm/drm_connector.h        |  9 +++++++++
> >>>>    include/drm/drm_edid.h             |  1 +
> >>>>    include/drm/drm_modes.h            |  5 +++++
> >>>>    6 files changed, 49 insertions(+), 1 deletion(-)
> >>>>
> >>>> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> >>>> index 10dab62..44be128 100644
> >>>> --- a/drivers/gpu/drm/drm_edid.c
> >>>> +++ b/drivers/gpu/drm/drm_edid.c
> >>>> @@ -2950,10 +2950,11 @@ 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);
> >>>>    }
> >>>> +EXPORT_SYMBOL(drm_valid_cea_vic);
> >>>>    
> >>>>    /**
> >>>>     * drm_get_cea_aspect_ratio - get the picture aspect ratio corresponding to
> >>>> diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
> >>>> index f2493b9..3b53c8e3 100644
> >>>> --- a/drivers/gpu/drm/drm_modes.c
> >>>> +++ b/drivers/gpu/drm/drm_modes.c
> >>>> @@ -1083,6 +1083,34 @@ drm_mode_validate_size(const struct drm_display_mode *mode,
> >>>>    }
> >>>>    EXPORT_SYMBOL(drm_mode_validate_size);
> >>>>    
> >>>> +/**
> >>>> + * drm_mode_ycbcr420_only - add 'ycbcr420-only' modes only when allowed
> >>>> + * @mode: mode to check
> >>>> + * @connector: drm connector under action
> >>>> + *
> >>>> + * This function is a helper which can be used to filter out any YCBCR420
> >>>> + * only mode, when the source doesn't support it.
> >>>> + *
> >>>> + * Returns:
> >>>> + * The mode status
> >>>> + */
> >>>> +enum drm_mode_status
> >>>> +drm_mode_validate_ycbcr420(const struct drm_display_mode *mode,
> >>>> +			   struct drm_connector *connector)
> >>>> +{
> >>>> +	u8 vic = drm_match_cea_mode(mode);
> >>>> +	enum drm_mode_status status = MODE_OK;
> >>>> +	struct drm_hdmi_info *hdmi = &connector->display_info.hdmi;
> >>>> +
> >>>> +	if (drm_valid_cea_vic(vic) && test_bit(vic, hdmi->y420_vdb_modes)) {
> >>> Still think the valid check is pointless.
> >> I still think that we should only pass valid CEA VIC to VDB check, but
> >> Ok, I will remove that.
> >>>    Skipping that would also avoid
> >>> having to make the function non-static
> >> Ok
> >>> (the EXPORT_SYMBOL there seems
> >>> unnecessary either way).
> >> Why ?
> > It's all in the same module AFAICS.
> >
> > Oh, and the patch ordering here still looks potentially problematic. We
> > should add the 420 mode validation before we start adding the 420 modes.
> > Otherwise anyone bisecting through this may get a black/corrupted screen
> > if they have a monitor with "420 only" modes.
> Actually, the 420 mode validation patch uses 420_only bitmap, which is 
> added in add_420_modes patch.
> So I can't put this patch before other one (you reviewed that sequence 
> once, and found that).

I guess then you just need to add the bitmap already in the validation
patch.

An alternative would be just squash the patches, but that seems a bit
drastic, and probably would mix up too many things in one patch.

> - Shashank
> >>>> +		if (!connector->ycbcr_420_allowed)
> >>>> +			status = MODE_NO_420;
> >>>> +	}
> >>>> +
> >>>> +	return status;
> >>>> +}
> >>>> +EXPORT_SYMBOL(drm_mode_validate_ycbcr420);
> >>>> +
> >>>>    #define MODE_STATUS(status) [MODE_ ## status + 3] = #status
> >>>>    
> >>>>    static const char * const drm_mode_status_names[] = {
> >>> ^
> >>> This thing needs to be updated as well.
> >> Oh sorry, good catch.
> >> - Shashank
> >>>> diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
> >>>> index 00e6832..904966c 100644
> >>>> --- a/drivers/gpu/drm/drm_probe_helper.c
> >>>> +++ b/drivers/gpu/drm/drm_probe_helper.c
> >>>> @@ -528,6 +528,10 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
> >>>>    		if (mode->status == MODE_OK)
> >>>>    			mode->status = drm_mode_validate_pipeline(mode,
> >>>>    								  connector);
> >>>> +
> >>>> +		if (mode->status == MODE_OK)
> >>>> +			mode->status = drm_mode_validate_ycbcr420(mode,
> >>>> +								  connector);
> >>>>    	}
> >>>>    
> >>>>    prune:
> >>>> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> >>>> index b3af8e3..225e092 100644
> >>>> --- a/include/drm/drm_connector.h
> >>>> +++ b/include/drm/drm_connector.h
> >>>> @@ -746,6 +746,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.
> >>>> diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
> >>>> index 89c0062..b55b2a7 100644
> >>>> --- a/include/drm/drm_edid.h
> >>>> +++ b/include/drm/drm_edid.h
> >>>> @@ -477,4 +477,5 @@ void drm_edid_get_monitor_name(struct edid *edid, char *name,
> >>>>    struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
> >>>>    					   int hsize, int vsize, int fresh,
> >>>>    					   bool rb);
> >>>> +bool drm_valid_cea_vic(u8 vic);
> >>>>    #endif /* __DRM_EDID_H__ */
> >>>> diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h
> >>>> index 94ac771..f8a1268 100644
> >>>> --- a/include/drm/drm_modes.h
> >>>> +++ b/include/drm/drm_modes.h
> >>>> @@ -80,6 +80,7 @@ struct videomode;
> >>>>     * @MODE_ONE_SIZE: only one resolution is supported
> >>>>     * @MODE_NO_REDUCED: monitor doesn't accept reduced blanking
> >>>>     * @MODE_NO_STEREO: stereo modes not supported
> >>>> + * @MODE_NO_420: ycbcr 420 modes not supported
> >>>>     * @MODE_STALE: mode has become stale
> >>>>     * @MODE_BAD: unspecified reason
> >>>>     * @MODE_ERROR: error condition
> >>>> @@ -124,6 +125,7 @@ enum drm_mode_status {
> >>>>    	MODE_ONE_SIZE,
> >>>>    	MODE_NO_REDUCED,
> >>>>    	MODE_NO_STEREO,
> >>>> +	MODE_NO_420,
> >>>>    	MODE_STALE = -3,
> >>>>    	MODE_BAD = -2,
> >>>>    	MODE_ERROR = -1
> >>>> @@ -496,6 +498,9 @@ bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1,
> >>>>    enum drm_mode_status drm_mode_validate_basic(const struct drm_display_mode *mode);
> >>>>    enum drm_mode_status drm_mode_validate_size(const struct drm_display_mode *mode,
> >>>>    					    int maxX, int maxY);
> >>>> +enum drm_mode_status
> >>>> +drm_mode_validate_ycbcr420(const struct drm_display_mode *mode,
> >>>> +			   struct drm_connector *connector);
> >>>>    void drm_mode_prune_invalid(struct drm_device *dev,
> >>>>    			    struct list_head *mode_list, bool verbose);
> >>>>    void drm_mode_sort(struct list_head *mode_list);
> >>>> -- 
> >>>> 2.7.4
> >>>>
> >>>> _______________________________________________
> >>>> dri-devel mailing list
> >>>> dri-devel@lists.freedesktop.org
> >>>> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
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] 76+ messages in thread

* Re: [PATCH 10/20] drm/i915: add config function for YCBCR420 outputs
  2017-07-13 12:53       ` Ville Syrjälä
@ 2017-07-13 13:01         ` Sharma, Shashank
  2017-07-13 13:26           ` Ville Syrjälä
  0 siblings, 1 reply; 76+ messages in thread
From: Sharma, Shashank @ 2017-07-13 13:01 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, dri-devel

Regards

Shashank


On 7/13/2017 6:23 PM, Ville Syrjälä wrote:
> On Thu, Jul 13, 2017 at 10:56:06AM +0530, Sharma, Shashank wrote:
>> Regards
>>
>> Shashank
>>
>>
>> On 7/12/2017 10:47 PM, Ville Syrjälä wrote:
>>> On Mon, Jul 10, 2017 at 04:48:38PM +0530, Shashank Sharma wrote:
>>>> This patch checks encoder level support for YCBCR420 outputs.
>>>> The logic goes as simple as this:
>>>> If the input mode is YCBCR420-only mode: prepare HDMI for
>>>> YCBCR420 output, else continue with RGB output mode.
>>>>
>>>> It checks if the mode is YCBCR420 and source can support this
>>>> output then it marks the ycbcr_420 output indicator 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
>>>> V5: Rebase
>>>> V6: Check and handle YCBCR420-only modes, discard the property
>>>>       based approach (Ville)
>>>>
>>>> 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    | 42 +++++++++++++++++++++++++++++++++---
>>>>    3 files changed, 43 insertions(+), 3 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
>>>> index 4e03ca6..01900e1 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(ycbcr420);
>>>>    
>>>>    	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 d17a324..592243b 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 */
>>>> +	bool ycbcr420;
>>>>    };
>>>>    
>>>>    struct intel_crtc {
>>>> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
>>>> index cc0d100..276d916 100644
>>>> --- a/drivers/gpu/drm/i915/intel_hdmi.c
>>>> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
>>>> @@ -1305,7 +1305,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,
>>>> +				bool output_ycbcr420)
>>> You alreayd have the crtc state, so no need to pass that stuff
>>> separately.
>> Ah, this was dumb, thanks !
>>>>    {
>>>>    	struct drm_i915_private *dev_priv =
>>>>    		to_i915(crtc_state->base.crtc->dev);
>>>> @@ -1330,6 +1331,13 @@ static bool hdmi_12bpc_possible(struct intel_crtc_state *crtc_state)
>>>>    		if (connector_state->crtc != crtc_state->base.crtc)
>>>>    			continue;
>>>>    
>>>> +		if (output_ycbcr420) {
>>>> +			const struct drm_hdmi_info *hdmi = &info->hdmi;
>>>> +
>>>> +			if (!(hdmi->y420_dc_modes & DRM_EDID_YCBCR420_DC_36))
>>>> +				return false;
>>>> +		}
>>>> +
>>> else?
>> Oops, needs an else { break;}
> I was thinking 'else if ...'
Do we need else if for 12 BPC case, I was thinking of:
if (!hdmi->y420_dc_modes & DRM_EDID_YCBCR420_DC_36)
        /* 12 BPC Y420 not possible */
        return false;
else
       /* output is going to be 420, and 12BPC is possible, so break the 
loop */
       break;

This will also allow the code to go through the WAR Added below.
- Shashank
>
>> - Shashank
>>>>    		if ((info->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_36) == 0)
>>>>    			return false;
>>>>    	}
>>>> @@ -1342,6 +1350,25 @@ static bool hdmi_12bpc_possible(struct intel_crtc_state *crtc_state)
>>>>    	return true;
>>>>    }
>>>>    
>>>> +static bool
>>>> +intel_hdmi_ycbcr420_config(struct drm_connector *connector,
>>>> +			       struct intel_crtc_state *config,
>>>> +			       int *clock_12bpc, int *clock_8bpc)
>>>> +{
>>>> +
>>>> +	if (!connector->ycbcr_420_allowed) {
>>>> +		DRM_ERROR("Platform doesn't support YCBCR420 output\n");
>>>> +		return false;
>>>> +	}
>>>> +
>>>> +	/* YCBCR420 TMDS rate requirement is half the pixel clock */
>>>> +	config->port_clock /= 2;
>>>> +	*clock_12bpc /= 2;
>>>> +	*clock_8bpc /= 2;
>>>> +	config->ycbcr420 = true;
>>>> +	return true;
>>>> +}
>>>> +
>>>>    bool intel_hdmi_compute_config(struct intel_encoder *encoder,
>>>>    			       struct intel_crtc_state *pipe_config,
>>>>    			       struct drm_connector_state *conn_state)
>>>> @@ -1349,7 +1376,8 @@ 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;
>>>> @@ -1379,6 +1407,14 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
>>>>    		clock_12bpc *= 2;
>>>>    	}
>>>>    
>>>> +	if (drm_mode_is_420_only(&connector->display_info, adjusted_mode)) {
>>>> +		if (!intel_hdmi_ycbcr420_config(connector, pipe_config,
>>>> +						&clock_12bpc, &clock_8bpc)) {
>>>> +			DRM_ERROR("Can't support YCBCR420 output\n");
>>>> +			return false;
>>>> +		}
>>>> +	}
>>>> +
>>>>    	if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv))
>>>>    		pipe_config->has_pch_encoder = true;
>>>>    
>>>> @@ -1398,7 +1434,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, pipe_config->ycbcr420)) {
>>>>    		DRM_DEBUG_KMS("picking bpc to 12 for HDMI output\n");
>>>>    		desired_bpp = 12*3;
>>>>    
>>>> -- 
>>>> 2.7.4
>>>>
>>>> _______________________________________________
>>>> dri-devel mailing list
>>>> dri-devel@lists.freedesktop.org
>>>> https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

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

* Re: [PATCH 08/20] drm: set output colorspace in AVI infoframe
  2017-07-13 12:49         ` Sharma, Shashank
@ 2017-07-13 13:03           ` Ville Syrjälä
  2017-07-13 13:15             ` Sharma, Shashank
  0 siblings, 1 reply; 76+ messages in thread
From: Ville Syrjälä @ 2017-07-13 13:03 UTC (permalink / raw)
  To: Sharma, Shashank; +Cc: intel-gfx, dri-devel

On Thu, Jul 13, 2017 at 06:19:01PM +0530, Sharma, Shashank wrote:
> Regards
> 
> Shashank
> 
> 
> On 7/13/2017 6:05 PM, Ville Syrjälä wrote:
> > On Thu, Jul 13, 2017 at 10:37:53AM +0530, Sharma, Shashank wrote:
> >> Regards
> >>
> >> Shashank
> >>
> >>
> >> On 7/12/2017 10:47 PM, Ville Syrjälä wrote:
> >>> On Mon, Jul 10, 2017 at 04:48:36PM +0530, Shashank Sharma wrote:
> >>>> A source must set output colorspace information in AVI
> >>>> infoframes, so that the sink can decode upcoming frames
> >>>> accordingly.
> >>>>
> >>>> This patch adds a function to add the output colorspace
> >>>> information in the AVI infoframes.
> >>>>
> >>>> V2: Rebase
> >>>> V3: Rebase
> >>>> V4: Rebase
> >>>> V5: Rebase
> >>>> V6: Made patch independent of HDMI output type.
> >>>>
> >>>> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
> >>>> ---
> >>>>    drivers/gpu/drm/drm_edid.c | 29 +++++++++++++++++++++++++++++
> >>>>    include/drm/drm_edid.h     |  5 +++++
> >>>>    2 files changed, 34 insertions(+)
> >>>>
> >>>> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> >>>> index 944a28f..cede86e 100644
> >>>> --- a/drivers/gpu/drm/drm_edid.c
> >>>> +++ b/drivers/gpu/drm/drm_edid.c
> >>>> @@ -4796,6 +4796,35 @@ 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 hdmi_colorspace colorspace)
> >>>> +{
> >>>> +	if (colorspace > HDMI_COLORSPACE_YUV420 ||
> >>>> +		colorspace < HDMI_COLORSPACE_RGB) {
> >>>> +		DRM_ERROR("Invalid color space type\n");
> >>>> +		return -EINVAL;
> >>>> +	}
> >>> Seems overly defensive. I'd say that if someone insists on writing
> >>> buggy code just let them do it.
> >> :) yep can be done, you know, its a new implementation, don't want to
> >> create unnecessary noise so being
> >> a bit defensive :)
> >>>> +
> >>>> +	frame->colorspace = colorspace;
> >>>> +	if (colorspace == HDMI_COLORSPACE_YUV420)
> >>>> +		frame->pixel_repeat = 0;
> >>> Most VICs don't allow pixel repeat in 444/etc. either, and we don't
> >>> protect against that. So this looks like pretty pointless check in
> >>> this form.
> >>>
> >>> So IMO just drop this entire patch and just assign frame->colorspace in
> >>> the driver.
> >> Actually YCBCR420 section of spec specifically calls out for not
> >> allowing repetition, also, when I tested this on a
> >> HDMI 2.0 analyzer, if was giving a AVI IF failure on pixel_repeat not 0,
> >> so IMHO it would be a good idea to keep
> >> this and get the tests passing.
> > That's just papering over bugs elsewhere. If we can't use pixel repeat
> > with a specific mode, then we should have rejected that mode much earlier.
> I dint get this point, HDMI 2.0 spec section 7.1 says "when YCBCR420 
> encoding is active, pixel repetition is not allowed" and
> pixel repetition field should be set to = 0, in AVI IF.  This seems to 
> be like - if you are displaying YCBCR420, set PR=0 regardless of
> mode, isn't it ?

If the mode requires pixel repeat to meet the minimum clock requirement,
then we can't just not do pixel repeat. That would violate the spec in
other ways, and IIRC we couldn't even generate a low enough clock for
it.

> 
> - Shashank
> >> - Shashank
> >>>> +
> >>>> +	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 aa58146..b79e0cb 100644
> >>>> --- a/include/drm/drm_edid.h
> >>>> +++ b/include/drm/drm_edid.h
> >>>> @@ -332,6 +332,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);
> >>>> @@ -354,6 +355,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 hdmi_colorspace colorspace);
> >>>> +int
> >>>>    drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame,
> >>>>    					    const struct drm_display_mode *mode);
> >>>>    void
> >>>> -- 
> >>>> 2.7.4
> >>>>
> >>>> _______________________________________________
> >>>> dri-devel mailing list
> >>>> dri-devel@lists.freedesktop.org
> >>>> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
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] 76+ messages in thread

* Re: [PATCH 11/20] drm/i915: prepare scaler for YCBCR420 modeset
  2017-07-13 12:57         ` Sharma, Shashank
@ 2017-07-13 13:05           ` Ville Syrjälä
  0 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjälä @ 2017-07-13 13:05 UTC (permalink / raw)
  To: Sharma, Shashank; +Cc: intel-gfx, dri-devel

On Thu, Jul 13, 2017 at 06:27:04PM +0530, Sharma, Shashank wrote:
> Regards
> 
> Shashank
> 
> 
> On 7/13/2017 6:22 PM, Ville Syrjälä wrote:
> > On Thu, Jul 13, 2017 at 10:51:04AM +0530, Sharma, Shashank wrote:
> >> Regards
> >>
> >> Shashank
> >>
> >>
> >> On 7/12/2017 10:47 PM, Ville Syrjälä wrote:
> >>> On Mon, Jul 10, 2017 at 04:48:39PM +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
> >>>> V5: addressed review comments from Ander:
> >>>>       - No need to check both scaler_user && hdmi_output.
> >>>>         Check for scaler_user is enough.
> >>>> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
> >>>> ---
> >>>>    drivers/gpu/drm/i915/intel_atomic.c  |  6 ++++++
> >>>>    drivers/gpu/drm/i915/intel_display.c | 23 +++++++++++++++++++++++
> >>>>    drivers/gpu/drm/i915/intel_drv.h     | 10 +++++++++-
> >>>>    drivers/gpu/drm/i915/intel_hdmi.c    | 12 ++++++++++++
> >>>>    drivers/gpu/drm/i915/intel_panel.c   |  3 ++-
> >>>>    5 files changed, 52 insertions(+), 2 deletions(-)
> >>>>
> >>>> diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
> >>>> index 36d4e63..040d111 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_420_OUTPUT_INDEX) {
> >>> I think Ander already said that we should just tie this into the normal
> >>> pfit pipe scaler user. I agree. Having to users doesn't actually make
> >>> sense because there can be only one pipe scaler, and if we want to do
> >>> scaled 4:2:0 output then we anyway need to handle both cases
> >>> simultaneosly.
> >> I thought our idea of having a separate scalar user was a good one,
> >> because, this gives additional information
> >> how and why the scalar is being used. Also, we dont program the other
> >> scaling factors in this case, but we get
> >> the scaling profile set using PIPEMISC. So I would prefer to have this
> >> as a special case or separate user, but you
> >> can think about this, and let me know.
> > Eventually we'll want scaling and 420 at the same time. So a separate
> > user just doesn't work.
> Ok, I was just following the design, which we discussed during F2F. I 
> will remove this user then.

Yeah. Sorry for the ping-pong, I guess I didn't think this through
fully back then.

> - Shashank
> >> - Shashank
> >>>> +			name = "YCBCR420-OUTPUT";
> >>>> +			idx = intel_crtc->base.base.id;
> >>>> +
> >>>> +			/* YCBCR420 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 01900e1..c56081e 100644
> >>>> --- a/drivers/gpu/drm/i915/intel_display.c
> >>>> +++ b/drivers/gpu/drm/i915/intel_display.c
> >>>> @@ -4621,6 +4621,9 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
> >>>>    	 */
> >>>>    	need_scaling = src_w != dst_w || src_h != dst_h;
> >>>>    
> >>>> +	if (scaler_user == SKL_420_OUTPUT_INDEX)
> >>>> +		need_scaling = true;
> >>>> +
> >>>>    	/*
> >>>>    	 * if plane is being disabled or scaler is no more required or force detach
> >>>>    	 *  - free scaler binded to this plane/crtc
> >>>> @@ -4668,6 +4671,26 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
> >>>>    }
> >>>>    
> >>>>    /**
> >>>> + * skl_update_scaler_crtc_420_output - Stages update to scaler state
> >>>> + * for YCBCR420 which 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_420_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_420_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
> >>>> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> >>>> index 592243b..68b4fba 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
> >>>> +
> >>>> +	/*
> >>>> +	 * YCBCR 420 output consume a scaler. So adding a user
> >>>> +	 * for 420 output requirement.
> >>>> +	 */
> >>>> +#define SKL_420_OUTPUT_INDEX 30
> >>>>    	unsigned scaler_users;
> >>>>    
> >>>>    	/* scaler used by crtc for panel fitting purpose */
> >>>> @@ -1483,6 +1490,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_420_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 276d916..9e8d784 100644
> >>>> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> >>>> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> >>>> @@ -1355,6 +1355,7 @@ intel_hdmi_ycbcr420_config(struct drm_connector *connector,
> >>>>    			       struct intel_crtc_state *config,
> >>>>    			       int *clock_12bpc, int *clock_8bpc)
> >>>>    {
> >>>> +	struct intel_crtc *intel_crtc = to_intel_crtc(config->base.crtc);
> >>>>    
> >>>>    	if (!connector->ycbcr_420_allowed) {
> >>>>    		DRM_ERROR("Platform doesn't support YCBCR420 output\n");
> >>>> @@ -1366,6 +1367,17 @@ intel_hdmi_ycbcr420_config(struct drm_connector *connector,
> >>>>    	*clock_12bpc /= 2;
> >>>>    	*clock_8bpc /= 2;
> >>>>    	config->ycbcr420 = true;
> >>>> +
> >>>> +	/* YCBCR 420 output conversion needs a scaler */
> >>>> +	if (skl_update_scaler_crtc_420_output(config)) {
> >>>> +		DRM_ERROR("Scaler allocation for output failed\n");
> >>>> +		return false;
> >>>> +	}
> >>>> +
> >>>> +	/* Bind this scaler to pipe */
> >>>> +	intel_pch_panel_fitting(intel_crtc, config,
> >>>> +				DRM_MODE_SCALE_FULLSCREEN);
> >>>> +
> >>>>    	return true;
> >>>>    }
> >>>>    
> >>>> diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
> >>>> index 96c2cbd..fd2e081 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->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

-- 
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] 76+ messages in thread

* Re: [PATCH 19/20] drm/i915: Move AVI infoframe function to DDI layer
  2017-07-13  4:58     ` Sharma, Shashank
@ 2017-07-13 13:10       ` Ville Syrjälä
  0 siblings, 0 replies; 76+ messages in thread
From: Ville Syrjälä @ 2017-07-13 13:10 UTC (permalink / raw)
  To: Sharma, Shashank; +Cc: intel-gfx, dri-devel

On Thu, Jul 13, 2017 at 10:28:00AM +0530, Sharma, Shashank wrote:
> Thanks for the review, Ville.
> 
> My comments, inline.
> 
> Regards
> Shashank
> On 7/12/2017 10:45 PM, Ville Syrjälä wrote:
> > On Mon, Jul 10, 2017 at 04:48:47PM +0530, Shashank Sharma wrote:
> >> We have an existing function to prepare AVI infoframes for HDMI,
> >> this patch moves that function from HDMI layer, to DDI layer, so
> >> that we can reuse the function for DP(LSPCON) displays too.
> >>
> >> This patch:
> >> - Moves the intel_hdmi_set_avi_infoframes function in ddi layer.
> >> - Adds code to accommodate LSPCON in the same function.
> >> - Links this function as AVI infoframe setup function for LSPCON.
> >>
> >> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >> Cc: Imre Deak <imre.deak@intel.com>
> >> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
> >> ---
> >>   drivers/gpu/drm/i915/intel_ddi.c    | 89 ++++++++++++++++++++++++++++++++++---
> >>   drivers/gpu/drm/i915/intel_drv.h    |  9 ++++
> >>   drivers/gpu/drm/i915/intel_hdmi.c   | 52 +++-------------------
> >>   drivers/gpu/drm/i915/intel_lspcon.c |  1 +
> >>   4 files changed, 99 insertions(+), 52 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> >> index 80e96f1..f691710 100644
> >> --- a/drivers/gpu/drm/i915/intel_ddi.c
> >> +++ b/drivers/gpu/drm/i915/intel_ddi.c
> >> @@ -2003,8 +2003,76 @@ static void intel_ddi_clk_select(struct intel_encoder *encoder,
> >>   	}
> >>   }
> >>   
> >> +void intel_ddi_set_avi_infoframe(struct drm_encoder *encoder,
> >> +				  const struct intel_crtc_state *crtc_state)
> > NAK. Please look at my 'move infoframe stuff into intel_dig_port' series
> > if you need infoframes with DP. IIRC you already reviewed part of that.
> Oh, looks like we were thinking in the same direction :).
> Sure, I will look for the whole patch series, and will re-use that code 
> in LSPCON/DP AVI IF series.
> Also, do let me know if you need review for those !

Please do review if you can. I was also hoping for some review
from people in the PSR front but that didn't happen so probably
no one else is looking at those patches anymore.

> 
> - Shashank
> >> +{
> >> +	int ret;
> >> +	union hdmi_infoframe frame;
> >> +	struct drm_connector *connector;
> >> +	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
> >> +	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> >> +	const struct drm_display_mode *adjusted_mode =
> >> +					&crtc_state->base.adjusted_mode;
> >> +	enum intel_output_type type = to_intel_encoder(encoder)->type;
> >> +	bool is_hdmi2_sink = false;
> >> +	bool rgb_qrange_selectable = false;
> >> +	enum hdmi_colorspace colorspace = crtc_state->ycbcr420 ?
> >> +					  HDMI_COLORSPACE_YUV420 :
> >> +					  HDMI_COLORSPACE_RGB;
> >> +	bool rgb_qrange_limited =  crtc_state->limited_color_range ?
> >> +					HDMI_QUANTIZATION_RANGE_LIMITED :
> >> +					HDMI_QUANTIZATION_RANGE_FULL;
> >> +
> >> +	switch (type) {
> >> +	case INTEL_OUTPUT_HDMI:
> >> +		connector = &intel_hdmi->attached_connector->base;
> >> +		is_hdmi2_sink = connector->display_info.hdmi.scdc.supported;
> >> +		rgb_qrange_selectable = intel_hdmi->rgb_quant_range_selectable;
> >> +		break;
> >> +
> >> +	case INTEL_OUTPUT_DP:
> >> +		/* We are here means its a LSPCON device, still be paranoid */
> >> +		if (!crtc_state->lspcon_active) {
> >> +			DRM_ERROR("No LSPCON, why am I here ?\n");
> >> +			return;
> >> +		}
> >> +
> >> +		connector = &intel_dp->attached_connector->base;
> >> +		is_hdmi2_sink = connector->display_info.hdmi.scdc.supported;
> >> +		if (crtc_state->ycbcr420)
> >> +			rgb_qrange_limited = true;
> >> +		break;
> >> +
> >> +	default:
> >> +		DRM_ERROR("No other encoder allowed\n");
> >> +		return;
> >> +	}
> >> +
> >> +	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
> >> +						       adjusted_mode,
> >> +						       is_hdmi2_sink);
> >> +	if (ret < 0) {
> >> +		DRM_ERROR("couldn't fill AVI infoframe\n");
> >> +		return;
> >> +	}
> >> +
> >> +	ret = drm_hdmi_avi_infoframe_set_colorspace(&frame.avi,
> >> +						    adjusted_mode,
> >> +						    colorspace);
> >> +	if (ret < 0) {
> >> +		DRM_ERROR("couldn't fill AVI colorspace\n");
> >> +		return;
> >> +	}
> >> +
> >> +	drm_hdmi_avi_infoframe_quant_range(&frame.avi, adjusted_mode,
> >> +					   rgb_qrange_limited,
> >> +					   rgb_qrange_selectable);
> >> +
> >> +	intel_write_infoframe(encoder, crtc_state, &frame);
> >> +}
> >> +
> >>   static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder,
> >> -				    int link_rate, uint32_t lane_count,
> >> +				    const struct intel_crtc_state *pipe_config,
> >>   				    struct intel_shared_dpll *pll,
> >>   				    bool link_mst)
> >>   {
> >> @@ -2012,6 +2080,8 @@ static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder,
> >>   	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> >>   	enum port port = intel_ddi_get_encoder_port(encoder);
> >>   	struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base);
> >> +	int link_rate = pipe_config->port_clock;
> >> +	uint32_t lane_count = pipe_config->lane_count;
> >>   
> >>   	WARN_ON(link_mst && (port == PORT_A || port == PORT_E));
> >>   
> >> @@ -2030,6 +2100,14 @@ static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder,
> >>   	intel_dp_start_link_train(intel_dp);
> >>   	if (port != PORT_A || INTEL_GEN(dev_priv) >= 9)
> >>   		intel_dp_stop_link_train(intel_dp);
> >> +
> >> +	if (pipe_config->lspcon_active) {
> >> +		struct drm_encoder *drm_encoder = &encoder->base;
> >> +		struct intel_lspcon *lspcon = enc_to_intel_lspcon(drm_encoder);
> >> +
> >> +		if (lspcon->set_infoframes)
> >> +			lspcon->set_infoframes(&encoder->base, pipe_config);
> >> +	}
> >>   }
> >>   
> >>   static void intel_ddi_pre_enable_hdmi(struct intel_encoder *encoder,
> >> @@ -2072,8 +2150,7 @@ static void intel_ddi_pre_enable(struct intel_encoder *encoder,
> >>   
> >>   	if (type == INTEL_OUTPUT_DP || type == INTEL_OUTPUT_EDP) {
> >>   		intel_ddi_pre_enable_dp(encoder,
> >> -					pipe_config->port_clock,
> >> -					pipe_config->lane_count,
> >> +					pipe_config,
> >>   					pipe_config->shared_dpll,
> >>   					intel_crtc_has_type(pipe_config,
> >>   							    INTEL_OUTPUT_DP_MST));
> >> @@ -2628,17 +2705,17 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
> >>   	}
> >>   
> >>   	if (init_lspcon) {
> >> -		if (lspcon_init(intel_dig_port))
> >> -			/* TODO: handle hdmi info frame part */
> >> +		if (lspcon_init(intel_dig_port)) {
> >>   			DRM_DEBUG_KMS("LSPCON init success on port %c\n",
> >>   				port_name(port));
> >> -		else
> >> +		} else {
> >>   			/*
> >>   			 * LSPCON init faied, but DP init was success, so
> >>   			 * lets try to drive as DP++ port.
> >>   			 */
> >>   			DRM_ERROR("LSPCON init failed on port %c\n",
> >>   				port_name(port));
> >> +		}
> >>   	}
> >>   
> >>   	return;
> >> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> >> index 40d56f2..fad9a53 100644
> >> --- a/drivers/gpu/drm/i915/intel_drv.h
> >> +++ b/drivers/gpu/drm/i915/intel_drv.h
> >> @@ -1075,6 +1075,10 @@ struct intel_lspcon {
> >>   	bool active;
> >>   	enum drm_lspcon_mode mode;
> >>   	enum lspcon_vendor vendor;
> >> +
> >> +	/* AVI IF setup function for LSPCON */
> >> +	void (*set_infoframes)(struct drm_encoder *encoder,
> >> +				const struct intel_crtc_state *crtc_state);
> >>   };
> >>   
> >>   struct intel_digital_port {
> >> @@ -1320,6 +1324,8 @@ u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder);
> >>   
> >>   unsigned int intel_fb_align_height(const struct drm_framebuffer *fb,
> >>   				   int plane, unsigned int height);
> >> +void intel_ddi_set_avi_infoframe(struct drm_encoder *encoder,
> >> +				 const struct intel_crtc_state *crtc_state);
> >>   
> >>   /* intel_audio.c */
> >>   void intel_init_audio_hooks(struct drm_i915_private *dev_priv);
> >> @@ -1690,6 +1696,9 @@ void intel_hdmi_handle_sink_scrambling(struct intel_encoder *intel_encoder,
> >>   				       struct drm_connector *connector,
> >>   				       bool high_tmds_clock_ratio,
> >>   				       bool scrambling);
> >> +void intel_write_infoframe(struct drm_encoder *encoder,
> >> +			    const struct intel_crtc_state *crtc_state,
> >> +			    union hdmi_infoframe *frame);
> >>   void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable);
> >>   bool intel_hdmi_ycbcr420_config(struct drm_connector *connector,
> >>   				struct intel_crtc_state *config,
> >> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> >> index a08ab99..7cab86a 100644
> >> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> >> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> >> @@ -430,7 +430,7 @@ static bool hsw_infoframe_enabled(struct drm_encoder *encoder,
> >>    * trick them by giving an offset into the buffer and moving back the header
> >>    * bytes by one.
> >>    */
> >> -static void intel_write_infoframe(struct drm_encoder *encoder,
> >> +void intel_write_infoframe(struct drm_encoder *encoder,
> >>   				  const struct intel_crtc_state *crtc_state,
> >>   				  union hdmi_infoframe *frame)
> >>   {
> >> @@ -453,46 +453,6 @@ static void intel_write_infoframe(struct drm_encoder *encoder,
> >>   	intel_hdmi->write_infoframe(encoder, crtc_state, frame->any.type, buffer, len);
> >>   }
> >>   
> >> -static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder,
> >> -					 const struct intel_crtc_state *crtc_state)
> >> -{
> >> -	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;
> >> -	enum hdmi_colorspace colorspace = HDMI_COLORSPACE_RGB;
> >> -	union hdmi_infoframe frame;
> >> -	int ret;
> >> -
> >> -	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
> >> -						       adjusted_mode,
> >> -						       is_hdmi2_sink);
> >> -	if (ret < 0) {
> >> -		DRM_ERROR("couldn't fill AVI infoframe\n");
> >> -		return;
> >> -	}
> >> -
> >> -	if (crtc_state->ycbcr420)
> >> -		colorspace = HDMI_COLORSPACE_YUV420;
> >> -
> >> -	ret = drm_hdmi_avi_infoframe_set_colorspace(&frame.avi,
> >> -						    adjusted_mode,
> >> -						    colorspace);
> >> -	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 :
> >> -					   HDMI_QUANTIZATION_RANGE_FULL,
> >> -					   intel_hdmi->rgb_quant_range_selectable);
> >> -
> >> -	intel_write_infoframe(encoder, crtc_state, &frame);
> >> -}
> >> -
> >>   static void intel_hdmi_set_spd_infoframe(struct drm_encoder *encoder,
> >>   					 const struct intel_crtc_state *crtc_state)
> >>   {
> >> @@ -582,7 +542,7 @@ static void g4x_set_infoframes(struct drm_encoder *encoder,
> >>   	I915_WRITE(reg, val);
> >>   	POSTING_READ(reg);
> >>   
> >> -	intel_hdmi_set_avi_infoframe(encoder, crtc_state);
> >> +	intel_ddi_set_avi_infoframe(encoder, crtc_state);
> >>   	intel_hdmi_set_spd_infoframe(encoder, crtc_state);
> >>   	intel_hdmi_set_hdmi_infoframe(encoder, crtc_state);
> >>   }
> >> @@ -723,7 +683,7 @@ static void ibx_set_infoframes(struct drm_encoder *encoder,
> >>   	I915_WRITE(reg, val);
> >>   	POSTING_READ(reg);
> >>   
> >> -	intel_hdmi_set_avi_infoframe(encoder, crtc_state);
> >> +	intel_ddi_set_avi_infoframe(encoder, crtc_state);
> >>   	intel_hdmi_set_spd_infoframe(encoder, crtc_state);
> >>   	intel_hdmi_set_hdmi_infoframe(encoder, crtc_state);
> >>   }
> >> @@ -766,7 +726,7 @@ static void cpt_set_infoframes(struct drm_encoder *encoder,
> >>   	I915_WRITE(reg, val);
> >>   	POSTING_READ(reg);
> >>   
> >> -	intel_hdmi_set_avi_infoframe(encoder, crtc_state);
> >> +	intel_ddi_set_avi_infoframe(encoder, crtc_state);
> >>   	intel_hdmi_set_spd_infoframe(encoder, crtc_state);
> >>   	intel_hdmi_set_hdmi_infoframe(encoder, crtc_state);
> >>   }
> >> @@ -819,7 +779,7 @@ static void vlv_set_infoframes(struct drm_encoder *encoder,
> >>   	I915_WRITE(reg, val);
> >>   	POSTING_READ(reg);
> >>   
> >> -	intel_hdmi_set_avi_infoframe(encoder, crtc_state);
> >> +	intel_ddi_set_avi_infoframe(encoder, crtc_state);
> >>   	intel_hdmi_set_spd_infoframe(encoder, crtc_state);
> >>   	intel_hdmi_set_hdmi_infoframe(encoder, crtc_state);
> >>   }
> >> @@ -852,7 +812,7 @@ static void hsw_set_infoframes(struct drm_encoder *encoder,
> >>   	I915_WRITE(reg, val);
> >>   	POSTING_READ(reg);
> >>   
> >> -	intel_hdmi_set_avi_infoframe(encoder, crtc_state);
> >> +	intel_ddi_set_avi_infoframe(encoder, crtc_state);
> >>   	intel_hdmi_set_spd_infoframe(encoder, crtc_state);
> >>   	intel_hdmi_set_hdmi_infoframe(encoder, crtc_state);
> >>   }
> >> diff --git a/drivers/gpu/drm/i915/intel_lspcon.c b/drivers/gpu/drm/i915/intel_lspcon.c
> >> index f611b6d..53ddd39 100644
> >> --- a/drivers/gpu/drm/i915/intel_lspcon.c
> >> +++ b/drivers/gpu/drm/i915/intel_lspcon.c
> >> @@ -281,6 +281,7 @@ bool lspcon_init(struct intel_digital_port *intel_dig_port)
> >>   	}
> >>   
> >>   	connector->ycbcr_420_allowed = true;
> >> +	lspcon->set_infoframes = intel_ddi_set_avi_infoframe;
> >>   	drm_dp_read_desc(&dp->aux, &dp->desc, drm_dp_is_branch(dp->dpcd));
> >>   
> >>   	DRM_DEBUG_KMS("Success: LSPCON init\n");
> >> -- 
> >> 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] 76+ messages in thread

* Re: [PATCH 20/20] drm/i915: write AVI infoframes for LSPCON
  2017-07-13 12:55           ` Ville Syrjälä
@ 2017-07-13 13:10             ` Sharma, Shashank
  2017-07-13 13:19               ` Ville Syrjälä
  0 siblings, 1 reply; 76+ messages in thread
From: Sharma, Shashank @ 2017-07-13 13:10 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, dri-devel


[-- Attachment #1.1: Type: text/plain, Size: 11906 bytes --]

Regards

Shashank


On 7/13/2017 6:25 PM, Ville Syrjälä wrote:
> On Thu, Jul 13, 2017 at 06:09:53PM +0530, Sharma, Shashank wrote:
>> Regards
>>
>> Shashank
>>
>>
>> On 7/13/2017 5:57 PM, Ville Syrjälä wrote:
>>> On Thu, Jul 13, 2017 at 11:11:53AM +0530, Sharma, Shashank wrote:
>>>> Regards
>>>>
>>>> Shashank
>>>>
>>>>
>>>> On 7/12/2017 10:54 PM, Ville Syrjälä wrote:
>>>>> On Mon, Jul 10, 2017 at 04:48:48PM +0530, Shashank Sharma wrote:
>>>>>> LSPCON chips can't pick the HDMI AVI infoframes from direct link.
>>>>>> In order to pass AVI infoframes from display controller to LSPCON,
>>>>>> we have to write infoframe packets into vendor specified AUX address.
>>>>>>
>>>>>> Also, LSPCON vendors provide AUX offsets, to inform the LSPCON
>>>>>> chip that the AVI IF packets are written, so that the firmware
>>>>>> can pick it up and apply.
>>>>>>
>>>>>> This patch adds function to write AVI infoframes for both MCA as
>>>>>> well as Parade Tech LSPCON chips. These two vendors provide different
>>>>>> methods for writing infoframes, so this patch contains two different
>>>>>> functions, one for each.
>>>>> Seems to me that we should also be checking the receiver cap for the
>>>>> 444->420 conversion support, and enable it in the PROTOCOL_CONVERTER
>>>>> DPCD register. Or are these LSPCON things even ignoring that part of the
>>>>> spec?
>>>> Yes, LSPCON just needs the YCBCR444 input, and info frames for 420, and
>>>> it would take care of
>>>> 444->420 conversion in FW.
>>> So it snoops the AVI infoframe we write to it to figure out that it has
>>> to do the 444->420 downsampling?
>> Yes, that's exactly what it does.
> Can you add a comment somewhere appropriate to make that clear.
> Otherwise people might wonder why we're not enabling the downsampling at
> all.
>
> Does LSPCON then not even implement the PROTOCOL_CONVERTER DCPD
> registers?
>
> Can you send the spec for this stuff my way? What I have now doesn't
> document any DPCD registers.
Actually I also don't have a document/spec which describes this. This is 
kind of knowledge sharing from people who
had design discussions with MCA/PARADE vendors on how to implement 
LSPCON specs and features.
Typically LSPCON firmware parses the AVI IF packets, and does the 
scaling down from 444->420. That's why
we are writing the AVI IF at custom AUX location.

I have added this description in patch 18's text, which talks about the 
steps to get a YCBCR420 output from LSPCON.
It says:

LSPCON chips support YCBCR420 outputs. To be able to get
YCBCR420 output from LSPCON chip, the source should:
- Generate YCBCR444 HDMI output
- Set AVI infoframes for a YCBCR420 output.

And added this small comment in 420_config:
+ /* LSPCON doesn't need scaler for YCBCR420 output */
+ if (config->lspcon_active)
+ return true;
+

But probably I should discreetly mention that LSPCON doesn't need a scalar somehow.

- Shashank

>> - Shashank
>>>> Also, its a part of LSPCON specs, that it has
>>>> to have 420 output capability.
>>>>
>>>> - Shashank
>>>>>> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>>>>> Cc: Imre Deak <imre.deak@intel.com>
>>>>>> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
>>>>>> ---
>>>>>>     drivers/gpu/drm/i915/intel_ddi.c    |   8 ++
>>>>>>     drivers/gpu/drm/i915/intel_drv.h    |   3 +
>>>>>>     drivers/gpu/drm/i915/intel_lspcon.c | 174 ++++++++++++++++++++++++++++++++++++
>>>>>>     3 files changed, 185 insertions(+)
>>>>>>
>>>>>> diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
>>>>>> index f691710..944d9d5 100644
>>>>>> --- a/drivers/gpu/drm/i915/intel_ddi.c
>>>>>> +++ b/drivers/gpu/drm/i915/intel_ddi.c
>>>>>> @@ -2068,6 +2068,14 @@ void intel_ddi_set_avi_infoframe(struct drm_encoder *encoder,
>>>>>>     					   rgb_qrange_limited,
>>>>>>     					   rgb_qrange_selectable);
>>>>>>     
>>>>>> +	if (crtc_state->lspcon_active) {
>>>>>> +		struct intel_lspcon *lspcon = enc_to_intel_lspcon(encoder);
>>>>>> +
>>>>>> +		/* LSPCON writes infoframes via AUX */
>>>>>> +		lspcon->write_infoframe(encoder, crtc_state, &frame);
>>>>>> +		return;
>>>>>> +	}
>>>>>> +
>>>>>>     	intel_write_infoframe(encoder, crtc_state, &frame);
>>>>>>     }
>>>>>>     
>>>>>> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
>>>>>> index fad9a53..3e686d2 100644
>>>>>> --- a/drivers/gpu/drm/i915/intel_drv.h
>>>>>> +++ b/drivers/gpu/drm/i915/intel_drv.h
>>>>>> @@ -1079,6 +1079,9 @@ struct intel_lspcon {
>>>>>>     	/* AVI IF setup function for LSPCON */
>>>>>>     	void (*set_infoframes)(struct drm_encoder *encoder,
>>>>>>     				const struct intel_crtc_state *crtc_state);
>>>>>> +	void (*write_infoframe)(struct drm_encoder *encoder,
>>>>>> +				const struct intel_crtc_state *crtc_state,
>>>>>> +				union hdmi_infoframe *frame);
>>>>>>     };
>>>>>>     
>>>>>>     struct intel_digital_port {
>>>>>> diff --git a/drivers/gpu/drm/i915/intel_lspcon.c b/drivers/gpu/drm/i915/intel_lspcon.c
>>>>>> index 53ddd39..01fddf7 100644
>>>>>> --- a/drivers/gpu/drm/i915/intel_lspcon.c
>>>>>> +++ b/drivers/gpu/drm/i915/intel_lspcon.c
>>>>>> @@ -31,6 +31,18 @@
>>>>>>     #define LSPCON_VENDOR_PARADE_OUI 0x001CF8
>>>>>>     #define LSPCON_VENDOR_MCA_OUI 0x0060AD
>>>>>>     
>>>>>> +/* AUX addresses to write AVI IF into */
>>>>>> +#define LSPCON_MCA_AVI_IF_WRITE_OFFSET 0x5C0
>>>>>> +#define LSPCON_MCA_AVI_IF_CTRL 0x5DF
>>>>>> +#define  LSPCON_MCA_AVI_IF_KICKOFF (1 << 0)
>>>>>> +#define  LSPCON_MCA_AVI_IF_HANDLED (1 << 1)
>>>>>> +
>>>>>> +#define LSPCON_PARADE_AVI_IF_WRITE_OFFSET 0x516
>>>>>> +#define LSPCON_PARADE_AVI_IF_CTRL 0x51E
>>>>>> +#define  LSPCON_PARADE_AVI_IF_KICKOFF (1 << 7)
>>>>>> +#define LSPCON_PARADE_AVI_IF_STATUS 0x51F
>>>>>> +#define  LSPCON_PARADE_AVI_IF_HANDLED (2 << 6)
>>>>>> +
>>>>>>     static struct intel_dp *lspcon_to_intel_dp(struct intel_lspcon *lspcon)
>>>>>>     {
>>>>>>     	struct intel_digital_port *dig_port =
>>>>>> @@ -217,6 +229,167 @@ bool lspcon_ycbcr420_config(struct drm_connector *connector,
>>>>>>     	return false;
>>>>>>     }
>>>>>>     
>>>>>> +static bool _lspcon_write_infoframe_parade(struct drm_dp_aux *aux,
>>>>>> +					   uint8_t *buffer, ssize_t len)
>>>>>> +{
>>>>>> +	u8 avi_if_ctrl;
>>>>>> +	u8 avi_if_status;
>>>>>> +	u8 count = 0;
>>>>>> +	u8 retry = 5;
>>>>>> +	u8 avi_buf[8] = {0, };
>>>>>> +	uint16_t reg;
>>>>>> +	ssize_t ret;
>>>>>> +
>>>>>> +	while (count++ < 4) {
>>>>>> +
>>>>>> +		do {
>>>>>> +			/* Is LSPCON FW ready */
>>>>>> +			reg = LSPCON_PARADE_AVI_IF_CTRL;
>>>>>> +			ret = drm_dp_dpcd_read(aux, reg, &avi_if_ctrl, 1);
>>>>>> +			if (ret < 0) {
>>>>>> +				DRM_ERROR("DPCD read failed, add:0x%x\n", reg);
>>>>>> +				return false;
>>>>>> +			}
>>>>>> +
>>>>>> +			if (avi_if_ctrl & LSPCON_PARADE_AVI_IF_KICKOFF)
>>>>>> +				break;
>>>>>> +			usleep_range(100, 200);
>>>>>> +		} while (--retry);
>>>>>> +
>>>>>> +		if (!(avi_if_ctrl & LSPCON_PARADE_AVI_IF_KICKOFF)) {
>>>>>> +			DRM_ERROR("LSPCON FW not ready for infoframes\n");
>>>>>> +			return false;
>>>>>> +		}
>>>>>> +
>>>>>> +		/*
>>>>>> +		 * AVI Infoframe contains 31 bytes of data:
>>>>>> +		 *	HB0 to HB2   (3 bytes header)
>>>>>> +		 *	PB0 to PB27 (28 bytes data)
>>>>>> +		 * As per Parade spec, while sending first block (8bytes),
>>>>>> +		 * byte 0 is kept for request token no, and byte1 - byte7
>>>>>> +		 * contain frame data. So we have to pack frame like this:
>>>>>> +		 *	first block of 8 bytes: <token> <HB0-HB2> <PB0-PB3>
>>>>>> +		 *	next 3 blocks: <PB4-PB27>
>>>>>> +		 */
>>>>>> +		if (count)
>>>>>> +			memcpy(avi_buf, buffer + count * 8 - 1, 8);
>>>>>> +		else {
>>>>>> +			avi_buf[0] = 1;
>>>>>> +			memcpy(&avi_buf[1], buffer, 7);
>>>>>> +		}
>>>>>> +
>>>>>> +		/* Write 8 bytes of data at a time */
>>>>>> +		reg = LSPCON_PARADE_AVI_IF_WRITE_OFFSET;
>>>>>> +		ret = drm_dp_dpcd_write(aux, reg, avi_buf, 8);
>>>>>> +		if (ret < 0) {
>>>>>> +			DRM_ERROR("DPCD write failed, add:0x%x\n", reg);
>>>>>> +			return false;
>>>>>> +		}
>>>>>> +
>>>>>> +		/*
>>>>>> +		 * While sending a block of 8 byes, we need to inform block
>>>>>> +		 * number to FW, by programming bits[1:0] of ctrl reg with
>>>>>> +		 * block number
>>>>>> +		 */
>>>>>> +		avi_if_ctrl = 0x80 + count;
>>>>>> +		reg = LSPCON_PARADE_AVI_IF_CTRL;
>>>>>> +		ret = drm_dp_dpcd_write(aux, reg, &avi_if_ctrl, 1);
>>>>>> +		if (ret < 0) {
>>>>>> +			DRM_ERROR("DPCD write failed, add:0x%x\n", reg);
>>>>>> +			return false;
>>>>>> +		}
>>>>>> +	}
>>>>>> +
>>>>>> +	/* Check LSPCON FW status */
>>>>>> +	reg = LSPCON_PARADE_AVI_IF_STATUS;
>>>>>> +	ret = drm_dp_dpcd_read(aux, reg, &avi_if_status, 1);
>>>>>> +	if (ret < 0) {
>>>>>> +		DRM_ERROR("DPCD write failed, address 0x%x\n", reg);
>>>>>> +		return false;
>>>>>> +	}
>>>>>> +
>>>>>> +	if (avi_if_status & LSPCON_PARADE_AVI_IF_HANDLED)
>>>>>> +		DRM_DEBUG_KMS("AVI IF handled by FW\n");
>>>>>> +
>>>>>> +	return true;
>>>>>> +}
>>>>>> +
>>>>>> +static bool _lspcon_write_infoframe_mca(struct drm_dp_aux *aux,
>>>>>> +					uint8_t *buffer, ssize_t len)
>>>>>> +{
>>>>>> +	int ret;
>>>>>> +	uint32_t val = 0;
>>>>>> +	uint16_t reg;
>>>>>> +	uint8_t *data = buffer;
>>>>>> +
>>>>>> +	reg = LSPCON_MCA_AVI_IF_WRITE_OFFSET;
>>>>>> +	while (val < len) {
>>>>>> +		ret = drm_dp_dpcd_write(aux, reg, data, 1);
>>>>>> +		if (ret < 0) {
>>>>>> +			DRM_ERROR("DPCD write failed, add:0x%x\n", reg);
>>>>>> +			return false;
>>>>>> +		}
>>>>>> +		val++; reg++; data++;
>>>>>> +	}
>>>>>> +
>>>>>> +	val = 0;
>>>>>> +	reg = LSPCON_MCA_AVI_IF_CTRL;
>>>>>> +	ret = drm_dp_dpcd_read(aux, reg, &val, 1);
>>>>>> +	if (ret < 0) {
>>>>>> +		DRM_ERROR("DPCD read failed, address 0x%x\n", reg);
>>>>>> +		return false;
>>>>>> +	}
>>>>>> +
>>>>>> +	/* Indicate LSPCON chip about infoframe, clear bit 1 and set bit 0 */
>>>>>> +	val &= ~LSPCON_MCA_AVI_IF_HANDLED;
>>>>>> +	val |= LSPCON_MCA_AVI_IF_KICKOFF;
>>>>>> +
>>>>>> +	ret = drm_dp_dpcd_write(aux, reg, &val, 1);
>>>>>> +	if (ret < 0) {
>>>>>> +		DRM_ERROR("DPCD read failed, address 0x%x\n", reg);
>>>>>> +		return false;
>>>>>> +	}
>>>>>> +
>>>>>> +	val = 0;
>>>>>> +	ret = drm_dp_dpcd_read(aux, reg, &val, 1);
>>>>>> +	if (ret < 0) {
>>>>>> +		DRM_ERROR("DPCD read failed, address 0x%x\n", reg);
>>>>>> +		return false;
>>>>>> +	}
>>>>>> +
>>>>>> +	if (val == LSPCON_MCA_AVI_IF_HANDLED)
>>>>>> +		DRM_DEBUG_KMS("AVI IF handled by FW\n");
>>>>>> +
>>>>>> +	return true;
>>>>>> +}
>>>>>> +
>>>>>> +void lspcon_write_infoframe(struct drm_encoder *encoder,
>>>>>> +				  const struct intel_crtc_state *crtc_state,
>>>>>> +				  union hdmi_infoframe *frame)
>>>>>> +{
>>>>>> +	bool ret;
>>>>>> +	ssize_t len;
>>>>>> +	uint8_t buf[VIDEO_DIP_DATA_SIZE];
>>>>>> +	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
>>>>>> +	struct intel_lspcon *lspcon = enc_to_intel_lspcon(encoder);
>>>>>> +
>>>>>> +	len = hdmi_infoframe_pack(frame, buf, sizeof(buf));
>>>>>> +	if (len < 0) {
>>>>>> +		DRM_ERROR("Failed to pack AVI IF\n");
>>>>>> +		return;
>>>>>> +	}
>>>>>> +
>>>>>> +	if (lspcon->vendor == LSPCON_VENDOR_MCA)
>>>>>> +		ret = _lspcon_write_infoframe_mca(&intel_dp->aux, buf, len);
>>>>>> +	else
>>>>>> +		ret = _lspcon_write_infoframe_parade(&intel_dp->aux, buf, len);
>>>>>> +
>>>>>> +	if (!ret)
>>>>>> +		DRM_ERROR("Failed to write AVI infoframes\n");
>>>>>> +	else
>>>>>> +		DRM_DEBUG_DRIVER("AVI infoframes updated successfully\n");
>>>>>> +}
>>>>>> +
>>>>>>     void lspcon_resume(struct intel_lspcon *lspcon)
>>>>>>     {
>>>>>>     	enum drm_lspcon_mode expected_mode;
>>>>>> @@ -282,6 +455,7 @@ bool lspcon_init(struct intel_digital_port *intel_dig_port)
>>>>>>     
>>>>>>     	connector->ycbcr_420_allowed = true;
>>>>>>     	lspcon->set_infoframes = intel_ddi_set_avi_infoframe;
>>>>>> +	lspcon->write_infoframe = lspcon_write_infoframe;
>>>>>>     	drm_dp_read_desc(&dp->aux, &dp->desc, drm_dp_is_branch(dp->dpcd));
>>>>>>     
>>>>>>     	DRM_DEBUG_KMS("Success: LSPCON init\n");
>>>>>> -- 
>>>>>> 2.7.4


[-- Attachment #1.2: Type: text/html, Size: 13024 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

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

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

* Re: [PATCH 06/20] drm: add helper to validate YCBCR420 modes
  2017-07-13 13:00           ` Ville Syrjälä
@ 2017-07-13 13:12             ` Sharma, Shashank
  0 siblings, 0 replies; 76+ messages in thread
From: Sharma, Shashank @ 2017-07-13 13:12 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, dri-devel

On 7/13/2017 6:30 PM, Ville Syrjälä wrote:

> I guess then you just need to add the bitmap already in the validation
> patch.
>
> An alternative would be just squash the patches, but that seems a bit
> drastic, and probably would mix up too many things in one patch.
Ok then, I will introduce this bitmap in the validation patch, and move 
if before.
- Shashank
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 18/20] drm/i915: YCBCR 420 support for LSPCON
  2017-07-13  5:02     ` Sharma, Shashank
@ 2017-07-13 13:13       ` Ville Syrjälä
  2017-07-13 13:17         ` Sharma, Shashank
  0 siblings, 1 reply; 76+ messages in thread
From: Ville Syrjälä @ 2017-07-13 13:13 UTC (permalink / raw)
  To: Sharma, Shashank; +Cc: intel-gfx, dri-devel

On Thu, Jul 13, 2017 at 10:32:00AM +0530, Sharma, Shashank wrote:
> Regards
> 
> Shashank
> 
> 
> On 7/12/2017 10:45 PM, Ville Syrjälä wrote:
> > On Mon, Jul 10, 2017 at 04:48:46PM +0530, Shashank Sharma wrote:
> >> LSPCON chips support YCBCR420 outputs. To be able to get
> >> YCBCR420 output from LSPCON chip, the source should:
> >> - Generate YCBCR444 HDMI output
> >> - Set AVI infoframes for a YCBCR420 output.
> >>
> >> LSPCON FW gets the information from AVI infoframes, and generates
> >> YCBCR420 output from a YCBCR444 input. This patch adds the necessary
> >> changes to drive YCBCR420 output from LSPCON based HDMI output.
> >>
> >> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >> Cc: Imre Deak <imre.deak@intel.com>
> >> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
> >> ---
> >>   drivers/gpu/drm/i915/intel_display.c | 10 +++++++---
> >>   drivers/gpu/drm/i915/intel_dp.c      | 16 +++++++++++++++-
> >>   drivers/gpu/drm/i915/intel_drv.h     | 20 +++++++++++++++++---
> >>   drivers/gpu/drm/i915/intel_hdmi.c    |  7 +++++--
> >>   drivers/gpu/drm/i915/intel_lspcon.c  | 17 +++++++++++++++++
> >>   5 files changed, 61 insertions(+), 9 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> >> index c5ff568..c3c7b31 100644
> >> --- a/drivers/gpu/drm/i915/intel_display.c
> >> +++ b/drivers/gpu/drm/i915/intel_display.c
> >> @@ -8125,9 +8125,11 @@ static void haswell_set_pipemisc(struct drm_crtc *crtc)
> >>   			val |= PIPEMISC_DITHER_ENABLE | PIPEMISC_DITHER_TYPE_SP;
> >>   
> >>   		if (config->ycbcr420) {
> >> -			val |= PIPEMISC_OUTPUT_YCBCR |
> >> -				PIPEMISC_YCBCR420_ENABLE |
> >> -				PIPEMISC_YCBCR420_MODE_BLEND;
> >> +			val |= PIPEMISC_OUTPUT_YCBCR;
> >> +
> >> +			if (!config->lspcon_active)
> >> +				val |= PIPEMISC_YCBCR420_ENABLE |
> >> +					PIPEMISC_YCBCR420_MODE_BLEND;
> >>   		}
> >>   
> >>   		I915_WRITE(PIPEMISC(intel_crtc->pipe), val);
> >> @@ -14205,11 +14207,13 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)
> >>   		 * DDI_BUF_CTL_A or SFUSE_STRAP registers, find another way to
> >>   		 * detect the ports.
> >>   		 */
> >> +
> >>   		intel_ddi_init(dev_priv, PORT_A);
> >>   		intel_ddi_init(dev_priv, PORT_B);
> >>   		intel_ddi_init(dev_priv, PORT_C);
> >>   
> >>   		intel_dsi_init(dev_priv);
> >> +
> >>   	} else if (HAS_DDI(dev_priv)) {
> >>   		int found;
> >>   
> >> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> >> index 67bc8a7a..1690aa9 100644
> >> --- a/drivers/gpu/drm/i915/intel_dp.c
> >> +++ b/drivers/gpu/drm/i915/intel_dp.c
> >> @@ -1614,7 +1614,9 @@ intel_dp_compute_config(struct intel_encoder *encoder,
> >>   	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> >>   	struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
> >>   	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
> >> -	enum port port = dp_to_dig_port(intel_dp)->port;
> >> +	struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base);
> >> +	enum port port = dig_port->port;
> >> +	struct intel_lspcon *lspcon = &dig_port->lspcon;
> >>   	struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->base.crtc);
> >>   	struct intel_connector *intel_connector = intel_dp->attached_connector;
> >>   	struct intel_digital_connector_state *intel_conn_state =
> >> @@ -1635,6 +1637,18 @@ intel_dp_compute_config(struct intel_encoder *encoder,
> >>   	common_len = intel_dp_common_len_rate_limit(intel_dp,
> >>   						    intel_dp->max_link_rate);
> >>   
> >> +	/* LSPCON needs special handling to drive YCBCR420 outputs */
> >> +	if (lspcon->active) {
> >> +		struct drm_connector *connector = &intel_connector->base;
> >> +		int clock_8bpc = pipe_config->base.adjusted_mode.crtc_clock;
> >> +		int clock_12bpc = clock_8bpc * 3 / 2;
> >> +
> >> +		pipe_config->lspcon_active = true;
> >> +		pipe_config->ycbcr420 = lspcon_ycbcr420_config(connector,
> >> +					     pipe_config, &clock_12bpc,
> >> +					     &clock_8bpc);
> > All this clock stuff here seems pointless. So I'd just replace this
> > stuff with the straightforward 'pipe_config->ycbcr420 = mode_needs_420';
> pipe_config->ycbcr_420 = true means we have committed into state that we 
> can support this mode in YCBCR420.
> But for that, we need to check connector->ycbcr420_allowed too.
> Also, when the mode is 420, we need to half the clock_8bpc and clock_12bpc.

We don't use those clocks with DP. You've just added them here because
the function call requires them as parameters. 

Also the function call is actually doing the wrong thing for DP
by halving port_clock.

> 
> This whole stuff is happening into lspcon_ycbcr420_config function 
> (which internally re-use hdmi_ycncr420_config from HDMI 2.0 series).
> That's why the call is important.
> >> +	}
> >> +
> >>   	/* No common link rates between source and sink */
> >>   	WARN_ON(common_len <= 0);
> >>   
> >> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> >> index ed04de9..40d56f2 100644
> >> --- a/drivers/gpu/drm/i915/intel_drv.h
> >> +++ b/drivers/gpu/drm/i915/intel_drv.h
> >> @@ -790,6 +790,9 @@ struct intel_crtc_state {
> >>   
> >>   	/* HDMI output type */
> >>   	bool ycbcr420;
> >> +
> >> +	/* LSPCON is active on port */
> >> +	bool lspcon_active;
> >>   };
> >>   
> >>   struct intel_crtc {
> >> @@ -1205,6 +1208,12 @@ static inline struct intel_dp *enc_to_intel_dp(struct drm_encoder *encoder)
> >>   	return &enc_to_dig_port(encoder)->dp;
> >>   }
> >>   
> >> +static inline struct intel_lspcon *
> >> +enc_to_intel_lspcon(struct drm_encoder *encoder)
> >> +{
> >> +	return &enc_to_dig_port(encoder)->lspcon;
> >> +}
> >> +
> >>   static inline struct intel_digital_port *
> >>   dp_to_dig_port(struct intel_dp *intel_dp)
> >>   {
> >> @@ -1675,14 +1684,16 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
> >>   			       struct intel_connector *intel_connector);
> >>   struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder);
> >>   bool intel_hdmi_compute_config(struct intel_encoder *encoder,
> >> -			       struct intel_crtc_state *pipe_config,
> >> -			       struct drm_connector_state *conn_state);
> >> +				struct intel_crtc_state *pipe_config,
> >> +				struct drm_connector_state *conn_state);
> >>   void intel_hdmi_handle_sink_scrambling(struct intel_encoder *intel_encoder,
> >>   				       struct drm_connector *connector,
> >>   				       bool high_tmds_clock_ratio,
> >>   				       bool scrambling);
> >>   void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable);
> >> -
> >> +bool intel_hdmi_ycbcr420_config(struct drm_connector *connector,
> >> +				struct intel_crtc_state *config,
> >> +				int *clock_12bpc, int *clock_8bpc);
> >>   
> >>   /* intel_lvds.c */
> >>   void intel_lvds_init(struct drm_i915_private *dev_priv);
> >> @@ -2003,6 +2014,9 @@ void intel_color_load_luts(struct drm_crtc_state *crtc_state);
> >>   bool lspcon_init(struct intel_digital_port *intel_dig_port);
> >>   void lspcon_resume(struct intel_lspcon *lspcon);
> >>   void lspcon_wait_pcon_mode(struct intel_lspcon *lspcon);
> >> +bool lspcon_ycbcr420_config(struct drm_connector *connector,
> >> +			    struct intel_crtc_state *config,
> >> +			    int *clock_12bpc, int *clock_8bpc);
> >>   
> >>   /* intel_pipe_crc.c */
> >>   int intel_pipe_crc_create(struct drm_minor *minor);
> >> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> >> index d1b1efc..a08ab99 100644
> >> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> >> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> >> @@ -1362,8 +1362,7 @@ static bool hdmi_12bpc_possible(struct intel_crtc_state *crtc_state,
> >>   	return true;
> >>   }
> >>   
> >> -static bool
> >> -intel_hdmi_ycbcr420_config(struct drm_connector *connector,
> >> +bool intel_hdmi_ycbcr420_config(struct drm_connector *connector,
> >>   			       struct intel_crtc_state *config,
> >>   			       int *clock_12bpc, int *clock_8bpc)
> >>   {
> >> @@ -1380,6 +1379,10 @@ intel_hdmi_ycbcr420_config(struct drm_connector *connector,
> >>   	*clock_8bpc /= 2;
> >>   	config->ycbcr420 = true;
> >>   
> >> +	/* LSPCON doesn't need scaler for YCBCR420 output */
> >> +	if (config->lspcon_active)
> >> +		return true;
> >> +
> >>   	/* YCBCR 420 output conversion needs a scaler */
> >>   	if (skl_update_scaler_crtc_420_output(config)) {
> >>   		DRM_ERROR("Scaler allocation for output failed\n");
> >> diff --git a/drivers/gpu/drm/i915/intel_lspcon.c b/drivers/gpu/drm/i915/intel_lspcon.c
> >> index a350d79..f611b6d 100644
> >> --- a/drivers/gpu/drm/i915/intel_lspcon.c
> >> +++ b/drivers/gpu/drm/i915/intel_lspcon.c
> >> @@ -202,6 +202,21 @@ static void lspcon_resume_in_pcon_wa(struct intel_lspcon *lspcon)
> >>   	DRM_DEBUG_KMS("LSPCON DP descriptor mismatch after resume\n");
> >>   }
> >>   
> >> +bool lspcon_ycbcr420_config(struct drm_connector *connector,
> >> +			    struct intel_crtc_state *config,
> >> +			    int *clock_12bpc, int *clock_8bpc)
> >> +{
> >> +	struct drm_display_info *info = &connector->display_info;
> >> +	struct drm_display_mode *mode = &config->base.adjusted_mode;
> >> +
> >> +	if (drm_mode_is_420_only(info, mode)) {
> >> +		return intel_hdmi_ycbcr420_config(connector, config,
> >> +					  clock_12bpc, clock_8bpc);
> >> +	}
> >> +
> >> +	return false;
> >> +}
> >> +
> >>   void lspcon_resume(struct intel_lspcon *lspcon)
> >>   {
> >>   	enum drm_lspcon_mode expected_mode;
> >> @@ -233,6 +248,7 @@ bool lspcon_init(struct intel_digital_port *intel_dig_port)
> >>   	struct intel_lspcon *lspcon = &intel_dig_port->lspcon;
> >>   	struct drm_device *dev = intel_dig_port->base.base.dev;
> >>   	struct drm_i915_private *dev_priv = to_i915(dev);
> >> +	struct drm_connector *connector = &dp->attached_connector->base;
> >>   
> >>   	if (!IS_GEN9(dev_priv)) {
> >>   		DRM_ERROR("LSPCON is supported on GEN9 only\n");
> >> @@ -264,6 +280,7 @@ bool lspcon_init(struct intel_digital_port *intel_dig_port)
> >>   		return false;
> >>   	}
> >>   
> >> +	connector->ycbcr_420_allowed = true;
> >>   	drm_dp_read_desc(&dp->aux, &dp->desc, drm_dp_is_branch(dp->dpcd));
> >>   
> >>   	DRM_DEBUG_KMS("Success: LSPCON init\n");
> >> -- 
> >> 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] 76+ messages in thread

* Re: [PATCH 08/20] drm: set output colorspace in AVI infoframe
  2017-07-13 13:03           ` Ville Syrjälä
@ 2017-07-13 13:15             ` Sharma, Shashank
  0 siblings, 0 replies; 76+ messages in thread
From: Sharma, Shashank @ 2017-07-13 13:15 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, dri-devel

On 7/13/2017 6:33 PM, Ville Syrjälä wrote:

> If the mode requires pixel repeat to meet the minimum clock requirement,
> then we can't just not do pixel repeat. That would violate the spec in
> other ways, and IIRC we couldn't even generate a low enough clock for
> it.
The YCBCR420 modes I am seeing on several EDIDs, are 4K modes, and they 
typically need a clock of
594/2 = 297Mhz, is that too low ?
- Shashank
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [PATCH 18/20] drm/i915: YCBCR 420 support for LSPCON
  2017-07-13 13:13       ` Ville Syrjälä
@ 2017-07-13 13:17         ` Sharma, Shashank
  0 siblings, 0 replies; 76+ messages in thread
From: Sharma, Shashank @ 2017-07-13 13:17 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, dri-devel

On 7/13/2017 6:43 PM, Ville Syrjälä wrote:

> We don't use those clocks with DP. You've just added them here because
> the function call requires them as parameters.
>
> Also the function call is actually doing the wrong thing for DP
> by halving port_clock.
Ah, missed that part. Thanks for letting me know, I will modify this 
accordingly.
- Shashank
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 20/20] drm/i915: write AVI infoframes for LSPCON
  2017-07-13 13:10             ` Sharma, Shashank
@ 2017-07-13 13:19               ` Ville Syrjälä
  2017-07-13 13:21                 ` Sharma, Shashank
  0 siblings, 1 reply; 76+ messages in thread
From: Ville Syrjälä @ 2017-07-13 13:19 UTC (permalink / raw)
  To: Sharma, Shashank; +Cc: intel-gfx, dri-devel

On Thu, Jul 13, 2017 at 06:40:36PM +0530, Sharma, Shashank wrote:
> Regards
> 
> Shashank
> 
> 
> On 7/13/2017 6:25 PM, Ville Syrjälä wrote:
> > On Thu, Jul 13, 2017 at 06:09:53PM +0530, Sharma, Shashank wrote:
> >> Regards
> >>
> >> Shashank
> >>
> >>
> >> On 7/13/2017 5:57 PM, Ville Syrjälä wrote:
> >>> On Thu, Jul 13, 2017 at 11:11:53AM +0530, Sharma, Shashank wrote:
> >>>> Regards
> >>>>
> >>>> Shashank
> >>>>
> >>>>
> >>>> On 7/12/2017 10:54 PM, Ville Syrjälä wrote:
> >>>>> On Mon, Jul 10, 2017 at 04:48:48PM +0530, Shashank Sharma wrote:
> >>>>>> LSPCON chips can't pick the HDMI AVI infoframes from direct link.
> >>>>>> In order to pass AVI infoframes from display controller to LSPCON,
> >>>>>> we have to write infoframe packets into vendor specified AUX address.
> >>>>>>
> >>>>>> Also, LSPCON vendors provide AUX offsets, to inform the LSPCON
> >>>>>> chip that the AVI IF packets are written, so that the firmware
> >>>>>> can pick it up and apply.
> >>>>>>
> >>>>>> This patch adds function to write AVI infoframes for both MCA as
> >>>>>> well as Parade Tech LSPCON chips. These two vendors provide different
> >>>>>> methods for writing infoframes, so this patch contains two different
> >>>>>> functions, one for each.
> >>>>> Seems to me that we should also be checking the receiver cap for the
> >>>>> 444->420 conversion support, and enable it in the PROTOCOL_CONVERTER
> >>>>> DPCD register. Or are these LSPCON things even ignoring that part of the
> >>>>> spec?
> >>>> Yes, LSPCON just needs the YCBCR444 input, and info frames for 420, and
> >>>> it would take care of
> >>>> 444->420 conversion in FW.
> >>> So it snoops the AVI infoframe we write to it to figure out that it has
> >>> to do the 444->420 downsampling?
> >> Yes, that's exactly what it does.
> > Can you add a comment somewhere appropriate to make that clear.
> > Otherwise people might wonder why we're not enabling the downsampling at
> > all.
> >
> > Does LSPCON then not even implement the PROTOCOL_CONVERTER DCPD
> > registers?
> >
> > Can you send the spec for this stuff my way? What I have now doesn't
> > document any DPCD registers.
> Actually I also don't have a document/spec which describes this. This is 
> kind of knowledge sharing from people who
> had design discussions with MCA/PARADE vendors on how to implement 
> LSPCON specs and features.

So there are no specs at all? That's no way to do things. As is, no
one can actually review this code without experimenting with the
hardware themselves.

> Typically LSPCON firmware parses the AVI IF packets, and does the 
> scaling down from 444->420. That's why
> we are writing the AVI IF at custom AUX location.
> 
> I have added this description in patch 18's text, which talks about the 
> steps to get a YCBCR420 output from LSPCON.
> It says:
> 
> LSPCON chips support YCBCR420 outputs. To be able to get
> YCBCR420 output from LSPCON chip, the source should:
> - Generate YCBCR444 HDMI output
> - Set AVI infoframes for a YCBCR420 output.
> 
> And added this small comment in 420_config:
> + /* LSPCON doesn't need scaler for YCBCR420 output */
> + if (config->lspcon_active)
> + return true;
> +
> 
> But probably I should discreetly mention that LSPCON doesn't need a scalar somehow.

Yeah something like this perhaps:
"We send 4:4:4 data to LSPCON which performs the 4:4:4->4:2:0
 downsampling or us, hence we don't need a pipe scaler."

> 
> - Shashank
> 
> >> - Shashank
> >>>> Also, its a part of LSPCON specs, that it has
> >>>> to have 420 output capability.
> >>>>
> >>>> - Shashank
> >>>>>> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >>>>>> Cc: Imre Deak <imre.deak@intel.com>
> >>>>>> Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
> >>>>>> ---
> >>>>>>     drivers/gpu/drm/i915/intel_ddi.c    |   8 ++
> >>>>>>     drivers/gpu/drm/i915/intel_drv.h    |   3 +
> >>>>>>     drivers/gpu/drm/i915/intel_lspcon.c | 174 ++++++++++++++++++++++++++++++++++++
> >>>>>>     3 files changed, 185 insertions(+)
> >>>>>>
> >>>>>> diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> >>>>>> index f691710..944d9d5 100644
> >>>>>> --- a/drivers/gpu/drm/i915/intel_ddi.c
> >>>>>> +++ b/drivers/gpu/drm/i915/intel_ddi.c
> >>>>>> @@ -2068,6 +2068,14 @@ void intel_ddi_set_avi_infoframe(struct drm_encoder *encoder,
> >>>>>>     					   rgb_qrange_limited,
> >>>>>>     					   rgb_qrange_selectable);
> >>>>>>     
> >>>>>> +	if (crtc_state->lspcon_active) {
> >>>>>> +		struct intel_lspcon *lspcon = enc_to_intel_lspcon(encoder);
> >>>>>> +
> >>>>>> +		/* LSPCON writes infoframes via AUX */
> >>>>>> +		lspcon->write_infoframe(encoder, crtc_state, &frame);
> >>>>>> +		return;
> >>>>>> +	}
> >>>>>> +
> >>>>>>     	intel_write_infoframe(encoder, crtc_state, &frame);
> >>>>>>     }
> >>>>>>     
> >>>>>> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> >>>>>> index fad9a53..3e686d2 100644
> >>>>>> --- a/drivers/gpu/drm/i915/intel_drv.h
> >>>>>> +++ b/drivers/gpu/drm/i915/intel_drv.h
> >>>>>> @@ -1079,6 +1079,9 @@ struct intel_lspcon {
> >>>>>>     	/* AVI IF setup function for LSPCON */
> >>>>>>     	void (*set_infoframes)(struct drm_encoder *encoder,
> >>>>>>     				const struct intel_crtc_state *crtc_state);
> >>>>>> +	void (*write_infoframe)(struct drm_encoder *encoder,
> >>>>>> +				const struct intel_crtc_state *crtc_state,
> >>>>>> +				union hdmi_infoframe *frame);
> >>>>>>     };
> >>>>>>     
> >>>>>>     struct intel_digital_port {
> >>>>>> diff --git a/drivers/gpu/drm/i915/intel_lspcon.c b/drivers/gpu/drm/i915/intel_lspcon.c
> >>>>>> index 53ddd39..01fddf7 100644
> >>>>>> --- a/drivers/gpu/drm/i915/intel_lspcon.c
> >>>>>> +++ b/drivers/gpu/drm/i915/intel_lspcon.c
> >>>>>> @@ -31,6 +31,18 @@
> >>>>>>     #define LSPCON_VENDOR_PARADE_OUI 0x001CF8
> >>>>>>     #define LSPCON_VENDOR_MCA_OUI 0x0060AD
> >>>>>>     
> >>>>>> +/* AUX addresses to write AVI IF into */
> >>>>>> +#define LSPCON_MCA_AVI_IF_WRITE_OFFSET 0x5C0
> >>>>>> +#define LSPCON_MCA_AVI_IF_CTRL 0x5DF
> >>>>>> +#define  LSPCON_MCA_AVI_IF_KICKOFF (1 << 0)
> >>>>>> +#define  LSPCON_MCA_AVI_IF_HANDLED (1 << 1)
> >>>>>> +
> >>>>>> +#define LSPCON_PARADE_AVI_IF_WRITE_OFFSET 0x516
> >>>>>> +#define LSPCON_PARADE_AVI_IF_CTRL 0x51E
> >>>>>> +#define  LSPCON_PARADE_AVI_IF_KICKOFF (1 << 7)
> >>>>>> +#define LSPCON_PARADE_AVI_IF_STATUS 0x51F
> >>>>>> +#define  LSPCON_PARADE_AVI_IF_HANDLED (2 << 6)
> >>>>>> +
> >>>>>>     static struct intel_dp *lspcon_to_intel_dp(struct intel_lspcon *lspcon)
> >>>>>>     {
> >>>>>>     	struct intel_digital_port *dig_port =
> >>>>>> @@ -217,6 +229,167 @@ bool lspcon_ycbcr420_config(struct drm_connector *connector,
> >>>>>>     	return false;
> >>>>>>     }
> >>>>>>     
> >>>>>> +static bool _lspcon_write_infoframe_parade(struct drm_dp_aux *aux,
> >>>>>> +					   uint8_t *buffer, ssize_t len)
> >>>>>> +{
> >>>>>> +	u8 avi_if_ctrl;
> >>>>>> +	u8 avi_if_status;
> >>>>>> +	u8 count = 0;
> >>>>>> +	u8 retry = 5;
> >>>>>> +	u8 avi_buf[8] = {0, };
> >>>>>> +	uint16_t reg;
> >>>>>> +	ssize_t ret;
> >>>>>> +
> >>>>>> +	while (count++ < 4) {
> >>>>>> +
> >>>>>> +		do {
> >>>>>> +			/* Is LSPCON FW ready */
> >>>>>> +			reg = LSPCON_PARADE_AVI_IF_CTRL;
> >>>>>> +			ret = drm_dp_dpcd_read(aux, reg, &avi_if_ctrl, 1);
> >>>>>> +			if (ret < 0) {
> >>>>>> +				DRM_ERROR("DPCD read failed, add:0x%x\n", reg);
> >>>>>> +				return false;
> >>>>>> +			}
> >>>>>> +
> >>>>>> +			if (avi_if_ctrl & LSPCON_PARADE_AVI_IF_KICKOFF)
> >>>>>> +				break;
> >>>>>> +			usleep_range(100, 200);
> >>>>>> +		} while (--retry);
> >>>>>> +
> >>>>>> +		if (!(avi_if_ctrl & LSPCON_PARADE_AVI_IF_KICKOFF)) {
> >>>>>> +			DRM_ERROR("LSPCON FW not ready for infoframes\n");
> >>>>>> +			return false;
> >>>>>> +		}
> >>>>>> +
> >>>>>> +		/*
> >>>>>> +		 * AVI Infoframe contains 31 bytes of data:
> >>>>>> +		 *	HB0 to HB2   (3 bytes header)
> >>>>>> +		 *	PB0 to PB27 (28 bytes data)
> >>>>>> +		 * As per Parade spec, while sending first block (8bytes),
> >>>>>> +		 * byte 0 is kept for request token no, and byte1 - byte7
> >>>>>> +		 * contain frame data. So we have to pack frame like this:
> >>>>>> +		 *	first block of 8 bytes: <token> <HB0-HB2> <PB0-PB3>
> >>>>>> +		 *	next 3 blocks: <PB4-PB27>
> >>>>>> +		 */
> >>>>>> +		if (count)
> >>>>>> +			memcpy(avi_buf, buffer + count * 8 - 1, 8);
> >>>>>> +		else {
> >>>>>> +			avi_buf[0] = 1;
> >>>>>> +			memcpy(&avi_buf[1], buffer, 7);
> >>>>>> +		}
> >>>>>> +
> >>>>>> +		/* Write 8 bytes of data at a time */
> >>>>>> +		reg = LSPCON_PARADE_AVI_IF_WRITE_OFFSET;
> >>>>>> +		ret = drm_dp_dpcd_write(aux, reg, avi_buf, 8);
> >>>>>> +		if (ret < 0) {
> >>>>>> +			DRM_ERROR("DPCD write failed, add:0x%x\n", reg);
> >>>>>> +			return false;
> >>>>>> +		}
> >>>>>> +
> >>>>>> +		/*
> >>>>>> +		 * While sending a block of 8 byes, we need to inform block
> >>>>>> +		 * number to FW, by programming bits[1:0] of ctrl reg with
> >>>>>> +		 * block number
> >>>>>> +		 */
> >>>>>> +		avi_if_ctrl = 0x80 + count;
> >>>>>> +		reg = LSPCON_PARADE_AVI_IF_CTRL;
> >>>>>> +		ret = drm_dp_dpcd_write(aux, reg, &avi_if_ctrl, 1);
> >>>>>> +		if (ret < 0) {
> >>>>>> +			DRM_ERROR("DPCD write failed, add:0x%x\n", reg);
> >>>>>> +			return false;
> >>>>>> +		}
> >>>>>> +	}
> >>>>>> +
> >>>>>> +	/* Check LSPCON FW status */
> >>>>>> +	reg = LSPCON_PARADE_AVI_IF_STATUS;
> >>>>>> +	ret = drm_dp_dpcd_read(aux, reg, &avi_if_status, 1);
> >>>>>> +	if (ret < 0) {
> >>>>>> +		DRM_ERROR("DPCD write failed, address 0x%x\n", reg);
> >>>>>> +		return false;
> >>>>>> +	}
> >>>>>> +
> >>>>>> +	if (avi_if_status & LSPCON_PARADE_AVI_IF_HANDLED)
> >>>>>> +		DRM_DEBUG_KMS("AVI IF handled by FW\n");
> >>>>>> +
> >>>>>> +	return true;
> >>>>>> +}
> >>>>>> +
> >>>>>> +static bool _lspcon_write_infoframe_mca(struct drm_dp_aux *aux,
> >>>>>> +					uint8_t *buffer, ssize_t len)
> >>>>>> +{
> >>>>>> +	int ret;
> >>>>>> +	uint32_t val = 0;
> >>>>>> +	uint16_t reg;
> >>>>>> +	uint8_t *data = buffer;
> >>>>>> +
> >>>>>> +	reg = LSPCON_MCA_AVI_IF_WRITE_OFFSET;
> >>>>>> +	while (val < len) {
> >>>>>> +		ret = drm_dp_dpcd_write(aux, reg, data, 1);
> >>>>>> +		if (ret < 0) {
> >>>>>> +			DRM_ERROR("DPCD write failed, add:0x%x\n", reg);
> >>>>>> +			return false;
> >>>>>> +		}
> >>>>>> +		val++; reg++; data++;
> >>>>>> +	}
> >>>>>> +
> >>>>>> +	val = 0;
> >>>>>> +	reg = LSPCON_MCA_AVI_IF_CTRL;
> >>>>>> +	ret = drm_dp_dpcd_read(aux, reg, &val, 1);
> >>>>>> +	if (ret < 0) {
> >>>>>> +		DRM_ERROR("DPCD read failed, address 0x%x\n", reg);
> >>>>>> +		return false;
> >>>>>> +	}
> >>>>>> +
> >>>>>> +	/* Indicate LSPCON chip about infoframe, clear bit 1 and set bit 0 */
> >>>>>> +	val &= ~LSPCON_MCA_AVI_IF_HANDLED;
> >>>>>> +	val |= LSPCON_MCA_AVI_IF_KICKOFF;
> >>>>>> +
> >>>>>> +	ret = drm_dp_dpcd_write(aux, reg, &val, 1);
> >>>>>> +	if (ret < 0) {
> >>>>>> +		DRM_ERROR("DPCD read failed, address 0x%x\n", reg);
> >>>>>> +		return false;
> >>>>>> +	}
> >>>>>> +
> >>>>>> +	val = 0;
> >>>>>> +	ret = drm_dp_dpcd_read(aux, reg, &val, 1);
> >>>>>> +	if (ret < 0) {
> >>>>>> +		DRM_ERROR("DPCD read failed, address 0x%x\n", reg);
> >>>>>> +		return false;
> >>>>>> +	}
> >>>>>> +
> >>>>>> +	if (val == LSPCON_MCA_AVI_IF_HANDLED)
> >>>>>> +		DRM_DEBUG_KMS("AVI IF handled by FW\n");
> >>>>>> +
> >>>>>> +	return true;
> >>>>>> +}
> >>>>>> +
> >>>>>> +void lspcon_write_infoframe(struct drm_encoder *encoder,
> >>>>>> +				  const struct intel_crtc_state *crtc_state,
> >>>>>> +				  union hdmi_infoframe *frame)
> >>>>>> +{
> >>>>>> +	bool ret;
> >>>>>> +	ssize_t len;
> >>>>>> +	uint8_t buf[VIDEO_DIP_DATA_SIZE];
> >>>>>> +	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> >>>>>> +	struct intel_lspcon *lspcon = enc_to_intel_lspcon(encoder);
> >>>>>> +
> >>>>>> +	len = hdmi_infoframe_pack(frame, buf, sizeof(buf));
> >>>>>> +	if (len < 0) {
> >>>>>> +		DRM_ERROR("Failed to pack AVI IF\n");
> >>>>>> +		return;
> >>>>>> +	}
> >>>>>> +
> >>>>>> +	if (lspcon->vendor == LSPCON_VENDOR_MCA)
> >>>>>> +		ret = _lspcon_write_infoframe_mca(&intel_dp->aux, buf, len);
> >>>>>> +	else
> >>>>>> +		ret = _lspcon_write_infoframe_parade(&intel_dp->aux, buf, len);
> >>>>>> +
> >>>>>> +	if (!ret)
> >>>>>> +		DRM_ERROR("Failed to write AVI infoframes\n");
> >>>>>> +	else
> >>>>>> +		DRM_DEBUG_DRIVER("AVI infoframes updated successfully\n");
> >>>>>> +}
> >>>>>> +
> >>>>>>     void lspcon_resume(struct intel_lspcon *lspcon)
> >>>>>>     {
> >>>>>>     	enum drm_lspcon_mode expected_mode;
> >>>>>> @@ -282,6 +455,7 @@ bool lspcon_init(struct intel_digital_port *intel_dig_port)
> >>>>>>     
> >>>>>>     	connector->ycbcr_420_allowed = true;
> >>>>>>     	lspcon->set_infoframes = intel_ddi_set_avi_infoframe;
> >>>>>> +	lspcon->write_infoframe = lspcon_write_infoframe;
> >>>>>>     	drm_dp_read_desc(&dp->aux, &dp->desc, drm_dp_is_branch(dp->dpcd));
> >>>>>>     
> >>>>>>     	DRM_DEBUG_KMS("Success: LSPCON init\n");
> >>>>>> -- 
> >>>>>> 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] 76+ messages in thread

* Re: [PATCH 20/20] drm/i915: write AVI infoframes for LSPCON
  2017-07-13 13:19               ` Ville Syrjälä
@ 2017-07-13 13:21                 ` Sharma, Shashank
  0 siblings, 0 replies; 76+ messages in thread
From: Sharma, Shashank @ 2017-07-13 13:21 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, dri-devel

On 7/13/2017 6:49 PM, Ville Syrjälä wrote:

> Yeah something like this perhaps:
> "We send 4:4:4 data to LSPCON which performs the 4:4:4->4:2:0
>   downsampling or us, hence we don't need a pipe scaler."
Seems good ! Will add this.
- Shashank
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 10/20] drm/i915: add config function for YCBCR420 outputs
  2017-07-13 13:01         ` Sharma, Shashank
@ 2017-07-13 13:26           ` Ville Syrjälä
  2017-07-13 13:35             ` Sharma, Shashank
  0 siblings, 1 reply; 76+ messages in thread
From: Ville Syrjälä @ 2017-07-13 13:26 UTC (permalink / raw)
  To: Sharma, Shashank; +Cc: intel-gfx, dri-devel

On Thu, Jul 13, 2017 at 06:31:25PM +0530, Sharma, Shashank wrote:
> Regards
> 
> Shashank
> 
> 
> On 7/13/2017 6:23 PM, Ville Syrjälä wrote:
> > On Thu, Jul 13, 2017 at 10:56:06AM +0530, Sharma, Shashank wrote:
> >> Regards
> >>
> >> Shashank
> >>
> >>
> >> On 7/12/2017 10:47 PM, Ville Syrjälä wrote:
> >>> On Mon, Jul 10, 2017 at 04:48:38PM +0530, Shashank Sharma wrote:
> >>>> This patch checks encoder level support for YCBCR420 outputs.
> >>>> The logic goes as simple as this:
> >>>> If the input mode is YCBCR420-only mode: prepare HDMI for
> >>>> YCBCR420 output, else continue with RGB output mode.
> >>>>
> >>>> It checks if the mode is YCBCR420 and source can support this
> >>>> output then it marks the ycbcr_420 output indicator 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
> >>>> V5: Rebase
> >>>> V6: Check and handle YCBCR420-only modes, discard the property
> >>>>       based approach (Ville)
> >>>>
> >>>> 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    | 42 +++++++++++++++++++++++++++++++++---
> >>>>    3 files changed, 43 insertions(+), 3 deletions(-)
> >>>>
> >>>> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> >>>> index 4e03ca6..01900e1 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(ycbcr420);
> >>>>    
> >>>>    	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 d17a324..592243b 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 */
> >>>> +	bool ycbcr420;
> >>>>    };
> >>>>    
> >>>>    struct intel_crtc {
> >>>> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> >>>> index cc0d100..276d916 100644
> >>>> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> >>>> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> >>>> @@ -1305,7 +1305,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,
> >>>> +				bool output_ycbcr420)
> >>> You alreayd have the crtc state, so no need to pass that stuff
> >>> separately.
> >> Ah, this was dumb, thanks !
> >>>>    {
> >>>>    	struct drm_i915_private *dev_priv =
> >>>>    		to_i915(crtc_state->base.crtc->dev);
> >>>> @@ -1330,6 +1331,13 @@ static bool hdmi_12bpc_possible(struct intel_crtc_state *crtc_state)
> >>>>    		if (connector_state->crtc != crtc_state->base.crtc)
> >>>>    			continue;
> >>>>    
> >>>> +		if (output_ycbcr420) {
> >>>> +			const struct drm_hdmi_info *hdmi = &info->hdmi;
> >>>> +
> >>>> +			if (!(hdmi->y420_dc_modes & DRM_EDID_YCBCR420_DC_36))
> >>>> +				return false;
> >>>> +		}
> >>>> +
> >>> else?
> >> Oops, needs an else { break;}
> > I was thinking 'else if ...'
> Do we need else if for 12 BPC case, I was thinking of:
> if (!hdmi->y420_dc_modes & DRM_EDID_YCBCR420_DC_36)
>         /* 12 BPC Y420 not possible */
>         return false;
> else
>        /* output is going to be 420, and 12BPC is possible, so break the 
> loop */
>        break;
> 
> This will also allow the code to go through the WAR Added below.

We don't want breaks in the loop. It's meant to go through all the
connectors for the crtc. Granted on modern platforms there can only be
one, but IMO assuming that just makes the whole thing look confusing.
It's much clearer IMO if we do 

if (420) {
	check 420 dc modes;
} else {
	check 444 dc modes;
}

> - Shashank
> >
> >> - Shashank
> >>>>    		if ((info->edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_36) == 0)
> >>>>    			return false;
> >>>>    	}
> >>>> @@ -1342,6 +1350,25 @@ static bool hdmi_12bpc_possible(struct intel_crtc_state *crtc_state)
> >>>>    	return true;
> >>>>    }
> >>>>    
> >>>> +static bool
> >>>> +intel_hdmi_ycbcr420_config(struct drm_connector *connector,
> >>>> +			       struct intel_crtc_state *config,
> >>>> +			       int *clock_12bpc, int *clock_8bpc)
> >>>> +{
> >>>> +
> >>>> +	if (!connector->ycbcr_420_allowed) {
> >>>> +		DRM_ERROR("Platform doesn't support YCBCR420 output\n");
> >>>> +		return false;
> >>>> +	}
> >>>> +
> >>>> +	/* YCBCR420 TMDS rate requirement is half the pixel clock */
> >>>> +	config->port_clock /= 2;
> >>>> +	*clock_12bpc /= 2;
> >>>> +	*clock_8bpc /= 2;
> >>>> +	config->ycbcr420 = true;
> >>>> +	return true;
> >>>> +}
> >>>> +
> >>>>    bool intel_hdmi_compute_config(struct intel_encoder *encoder,
> >>>>    			       struct intel_crtc_state *pipe_config,
> >>>>    			       struct drm_connector_state *conn_state)
> >>>> @@ -1349,7 +1376,8 @@ 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;
> >>>> @@ -1379,6 +1407,14 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
> >>>>    		clock_12bpc *= 2;
> >>>>    	}
> >>>>    
> >>>> +	if (drm_mode_is_420_only(&connector->display_info, adjusted_mode)) {
> >>>> +		if (!intel_hdmi_ycbcr420_config(connector, pipe_config,
> >>>> +						&clock_12bpc, &clock_8bpc)) {
> >>>> +			DRM_ERROR("Can't support YCBCR420 output\n");
> >>>> +			return false;
> >>>> +		}
> >>>> +	}
> >>>> +
> >>>>    	if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv))
> >>>>    		pipe_config->has_pch_encoder = true;
> >>>>    
> >>>> @@ -1398,7 +1434,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, pipe_config->ycbcr420)) {
> >>>>    		DRM_DEBUG_KMS("picking bpc to 12 for HDMI output\n");
> >>>>    		desired_bpp = 12*3;
> >>>>    
> >>>> -- 
> >>>> 2.7.4
> >>>>
> >>>> _______________________________________________
> >>>> dri-devel mailing list
> >>>> dri-devel@lists.freedesktop.org
> >>>> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
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] 76+ messages in thread

* Re: [PATCH 10/20] drm/i915: add config function for YCBCR420 outputs
  2017-07-13 13:26           ` Ville Syrjälä
@ 2017-07-13 13:35             ` Sharma, Shashank
  2017-07-13 14:10               ` Ville Syrjälä
  0 siblings, 1 reply; 76+ messages in thread
From: Sharma, Shashank @ 2017-07-13 13:35 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, dri-devel

On 7/13/2017 6:56 PM, Ville Syrjälä wrote:

> We don't want breaks in the loop. It's meant to go through all the
> connectors for the crtc. Granted on modern platforms there can only be
> one, but IMO assuming that just makes the whole thing look confusing.
> It's much clearer IMO if we do
>
> if (420) {
> 	check 420 dc modes;
> } else {
> 	check 444 dc modes;
> }
I dint want to add another loop for the 420 stuff, hence was reusing the 
existing loop.
Now, my steps were:
- If there is a CRTC match, I got the right CRTC.
- On this CRTC, if YCBCR420 output is enabled, I should just check 
DRM_EDID_YCBCR420_DC_36
    for 420_12BPC, so if it supports DRM_EDID_YCBCR420_DC_36 say yes, 
else no.
- But I also want to go through the WAR condition below, added for GLK. 
So I can't return from here.

Do you prefer me adding another loop just for YCBCR420 ?

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

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

* Re: [PATCH 10/20] drm/i915: add config function for YCBCR420 outputs
  2017-07-13 13:35             ` Sharma, Shashank
@ 2017-07-13 14:10               ` Ville Syrjälä
  2017-07-13 14:17                 ` Sharma, Shashank
  0 siblings, 1 reply; 76+ messages in thread
From: Ville Syrjälä @ 2017-07-13 14:10 UTC (permalink / raw)
  To: Sharma, Shashank; +Cc: intel-gfx, dri-devel

On Thu, Jul 13, 2017 at 07:05:12PM +0530, Sharma, Shashank wrote:
> On 7/13/2017 6:56 PM, Ville Syrjälä wrote:
> 
> > We don't want breaks in the loop. It's meant to go through all the
> > connectors for the crtc. Granted on modern platforms there can only be
> > one, but IMO assuming that just makes the whole thing look confusing.
> > It's much clearer IMO if we do
> >
> > if (420) {
> > 	check 420 dc modes;
> > } else {
> > 	check 444 dc modes;
> > }
> I dint want to add another loop for the 420 stuff, hence was reusing the 
> existing loop.

What I mean is

 for_each() {
 	...
+	if (420) {
+		if (!420_dc)
+			return false;
+	} else {
		if (!444_dc)
			return false;
+	}
 }

> Now, my steps were:
> - If there is a CRTC match, I got the right CRTC.
> - On this CRTC, if YCBCR420 output is enabled, I should just check 
> DRM_EDID_YCBCR420_DC_36
>     for 420_12BPC, so if it supports DRM_EDID_YCBCR420_DC_36 say yes, 
> else no.
> - But I also want to go through the WAR condition below, added for GLK. 
> So I can't return from here.
> 
> Do you prefer me adding another loop just for YCBCR420 ?
> 
> - Shashank

-- 
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] 76+ messages in thread

* Re: [PATCH 10/20] drm/i915: add config function for YCBCR420 outputs
  2017-07-13 14:10               ` Ville Syrjälä
@ 2017-07-13 14:17                 ` Sharma, Shashank
  0 siblings, 0 replies; 76+ messages in thread
From: Sharma, Shashank @ 2017-07-13 14:17 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx, dri-devel

On 7/13/2017 7:40 PM, Ville Syrjälä wrote:

> What I mean is
>
>   for_each() {
>   	...
> +	if (420) {
> +		if (!420_dc)
> +			return false;
> +	} else {
> 		if (!444_dc)
> 			return false;
> +	}
>   }
Got it, Thanks !
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

end of thread, other threads:[~2017-07-13 14:17 UTC | newest]

Thread overview: 76+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-07-10 11:18 [PATCH 00/20] YCBCR 4:2:0 handling for LSPCON Shashank Sharma
2017-07-10 11:18 ` [PATCH 01/20] drm: handle HDMI 2.0 VICs in AVI info-frames Shashank Sharma
2017-07-10 11:18 ` [PATCH 02/20] drm/edid: complete CEA modedb(VIC 1-107) Shashank Sharma
2017-07-12 17:18   ` Ville Syrjälä
2017-07-13  5:38     ` Sharma, Shashank
2017-07-10 11:18 ` [PATCH 03/20] drm/edid: parse sink information before CEA blocks Shashank Sharma
2017-07-10 11:18 ` [PATCH 04/20] drm/edid: cleanup patch for CEA extended-tag macro Shashank Sharma
2017-07-10 11:18 ` [PATCH 05/20] drm/edid: parse YCBCR420 videomodes from EDID Shashank Sharma
2017-07-10 11:18 ` [PATCH 06/20] drm: add helper to validate YCBCR420 modes Shashank Sharma
2017-07-12 17:18   ` Ville Syrjälä
2017-07-13  5:32     ` Sharma, Shashank
2017-07-13 12:31       ` Ville Syrjälä
2017-07-13 12:42         ` Sharma, Shashank
2017-07-13 13:00           ` Ville Syrjälä
2017-07-13 13:12             ` Sharma, Shashank
2017-07-10 11:18 ` [PATCH 07/20] drm/edid: parse ycbcr 420 deep color information Shashank Sharma
2017-07-12 17:18   ` Ville Syrjälä
2017-07-13  5:33     ` Sharma, Shashank
2017-07-10 11:18 ` [PATCH 08/20] drm: set output colorspace in AVI infoframe Shashank Sharma
2017-07-12 17:17   ` Ville Syrjälä
2017-07-13  5:07     ` Sharma, Shashank
2017-07-13 12:35       ` Ville Syrjälä
2017-07-13 12:49         ` Sharma, Shashank
2017-07-13 13:03           ` Ville Syrjälä
2017-07-13 13:15             ` Sharma, Shashank
2017-07-10 11:18 ` [PATCH 09/20] drm: add helper functions for YCBCR420 handling Shashank Sharma
2017-07-12 17:17   ` Ville Syrjälä
2017-07-13  5:27     ` Sharma, Shashank
2017-07-10 11:18 ` [PATCH 10/20] drm/i915: add config function for YCBCR420 outputs Shashank Sharma
2017-07-12 17:17   ` Ville Syrjälä
2017-07-13  5:26     ` Sharma, Shashank
2017-07-13 12:53       ` Ville Syrjälä
2017-07-13 13:01         ` Sharma, Shashank
2017-07-13 13:26           ` Ville Syrjälä
2017-07-13 13:35             ` Sharma, Shashank
2017-07-13 14:10               ` Ville Syrjälä
2017-07-13 14:17                 ` Sharma, Shashank
2017-07-10 11:18 ` [PATCH 11/20] drm/i915: prepare scaler for YCBCR420 modeset Shashank Sharma
2017-07-12 17:17   ` Ville Syrjälä
2017-07-13  5:21     ` Sharma, Shashank
2017-07-13 12:52       ` [Intel-gfx] " Ville Syrjälä
2017-07-13 12:57         ` Sharma, Shashank
2017-07-13 13:05           ` Ville Syrjälä
2017-07-10 11:18 ` [PATCH 12/20] drm/i915: prepare pipe for YCBCR420 output Shashank Sharma
2017-07-10 11:18 ` [PATCH 13/20] drm/i915: prepare csc unit " Shashank Sharma
2017-07-12 17:17   ` Ville Syrjälä
2017-07-13  5:14     ` Sharma, Shashank
2017-07-13 12:50       ` Ville Syrjälä
2017-07-13 12:53         ` Sharma, Shashank
2017-07-10 11:18 ` [PATCH 14/20] drm/i915: set colorspace for YCBCR420 outputs Shashank Sharma
2017-07-10 11:18 ` [PATCH 15/20] drm/i915/glk: set HDMI 2.0 identifier Shashank Sharma
2017-07-10 11:18 ` [PATCH 16/20] drm: add function to read vendor OUI Shashank Sharma
2017-07-12 17:15   ` Ville Syrjälä
2017-07-13  5:04     ` Sharma, Shashank
2017-07-13 12:37       ` Ville Syrjälä
2017-07-13 12:50         ` Sharma, Shashank
2017-07-10 11:18 ` [PATCH 17/20] drm/i915: check LSPCON " Shashank Sharma
2017-07-10 11:18 ` [PATCH 18/20] drm/i915: YCBCR 420 support for LSPCON Shashank Sharma
2017-07-12 17:15   ` Ville Syrjälä
2017-07-13  5:02     ` Sharma, Shashank
2017-07-13 13:13       ` Ville Syrjälä
2017-07-13 13:17         ` Sharma, Shashank
2017-07-10 11:18 ` [PATCH 19/20] drm/i915: Move AVI infoframe function to DDI layer Shashank Sharma
2017-07-12 17:15   ` Ville Syrjälä
2017-07-13  4:58     ` Sharma, Shashank
2017-07-13 13:10       ` Ville Syrjälä
2017-07-10 11:18 ` [PATCH 20/20] drm/i915: write AVI infoframes for LSPCON Shashank Sharma
2017-07-12 17:24   ` Ville Syrjälä
2017-07-13  5:41     ` Sharma, Shashank
2017-07-13 12:27       ` Ville Syrjälä
2017-07-13 12:39         ` Sharma, Shashank
2017-07-13 12:55           ` Ville Syrjälä
2017-07-13 13:10             ` Sharma, Shashank
2017-07-13 13:19               ` Ville Syrjälä
2017-07-13 13:21                 ` Sharma, Shashank
2017-07-10 11:38 ` ✓ Fi.CI.BAT: success for YCBCR 4:2:0 handling " Patchwork

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.