Takashi Iwai a48e6b
From 43cb86799ff03e9819c07f37f72f80f8246ad7ed Mon Sep 17 00:00:00 2001
Takashi Iwai a48e6b
From: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Takashi Iwai a48e6b
Date: Sun, 8 Dec 2019 18:18:31 +0100
Takashi Iwai a48e6b
Subject: [PATCH] drm: meson: venc: cvbs: fix CVBS mode matching
Takashi Iwai a48e6b
Git-commit: 43cb86799ff03e9819c07f37f72f80f8246ad7ed
Takashi Iwai a48e6b
Patch-mainline: v5.5-rc2
Takashi Iwai a48e6b
References: bsc#1051510
Takashi Iwai a48e6b
Takashi Iwai a48e6b
With commit 222ec1618c3ace ("drm: Add aspect ratio parsing in DRM
Takashi Iwai a48e6b
layer") the drm core started honoring the picture_aspect_ratio field
Takashi Iwai a48e6b
when comparing two drm_display_modes. Prior to that it was ignored.
Takashi Iwai a48e6b
When the CVBS encoder driver was initially submitted there was no aspect
Takashi Iwai a48e6b
ratio check.
Takashi Iwai a48e6b
Takashi Iwai a48e6b
Switch from drm_mode_equal() to drm_mode_match() without
Takashi Iwai a48e6b
DRM_MODE_MATCH_ASPECT_RATIO to fix "kmscube" and X.org output using the
Takashi Iwai a48e6b
CVBS connector. When (for example) kmscube sets the output mode when
Takashi Iwai a48e6b
using the CVBS connector it passes HDMI_PICTURE_ASPECT_NONE, making the
Takashi Iwai a48e6b
drm_mode_equal() fail as it include the aspect ratio.
Takashi Iwai a48e6b
Takashi Iwai a48e6b
Prior to this patch kmscube reported:
Takashi Iwai a48e6b
  failed to set mode: Invalid argument
Takashi Iwai a48e6b
Takashi Iwai a48e6b
The CVBS mode checking in the sun4i (drivers/gpu/drm/sun4i/sun4i_tv.c
Takashi Iwai a48e6b
sun4i_tv_mode_to_drm_mode) and ZTE (drivers/gpu/drm/zte/zx_tvenc.c
Takashi Iwai a48e6b
tvenc_mode_{pal,ntsc}) drivers don't set the "picture_aspect_ratio" at
Takashi Iwai a48e6b
all. The Meson VPU driver does not rely on the aspect ratio for the CVBS
Takashi Iwai a48e6b
output so we can safely decouple it from the hdmi_picture_aspect
Takashi Iwai a48e6b
setting.
Takashi Iwai a48e6b
Takashi Iwai a48e6b
Cc: <stable@vger.kernel.org>
Takashi Iwai a48e6b
Fixes: 222ec1618c3ace ("drm: Add aspect ratio parsing in DRM layer")
Takashi Iwai a48e6b
Fixes: bbbe775ec5b5da ("drm: Add support for Amlogic Meson Graphic Controller")
Takashi Iwai a48e6b
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Takashi Iwai a48e6b
Acked-by: Neil Armstrong <narmstrong@baylibre.com>
Takashi Iwai a48e6b
[narmstrong: squashed with drm: meson: venc: cvbs: deduplicate the meson_cvbs_mode lookup code]
Takashi Iwai a48e6b
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
Takashi Iwai a48e6b
Link: https://patchwork.freedesktop.org/patch/msgid/20191208171832.1064772-3-martin.blumenstingl@googlemail.com
Takashi Iwai a48e6b
Acked-by: Takashi Iwai <tiwai@suse.de>
Takashi Iwai a48e6b
Takashi Iwai a48e6b
---
Takashi Iwai a48e6b
 drivers/gpu/drm/meson/meson_venc_cvbs.c | 48 ++++++++++++++++++---------------
Takashi Iwai a48e6b
 1 file changed, 27 insertions(+), 21 deletions(-)
Takashi Iwai a48e6b
Takashi Iwai a48e6b
diff --git a/drivers/gpu/drm/meson/meson_venc_cvbs.c b/drivers/gpu/drm/meson/meson_venc_cvbs.c
Takashi Iwai a48e6b
index 9ab27aecfcf3..1bd6b6d15ffb 100644
Takashi Iwai a48e6b
--- a/drivers/gpu/drm/meson/meson_venc_cvbs.c
Takashi Iwai a48e6b
+++ b/drivers/gpu/drm/meson/meson_venc_cvbs.c
Takashi Iwai a48e6b
@@ -64,6 +64,25 @@ struct meson_cvbs_mode meson_cvbs_modes[MESON_CVBS_MODES_COUNT] = {
Takashi Iwai a48e6b
 	},
Takashi Iwai a48e6b
 };
Takashi Iwai a48e6b
 
Takashi Iwai a48e6b
+static const struct meson_cvbs_mode *
Takashi Iwai a48e6b
+meson_cvbs_get_mode(const struct drm_display_mode *req_mode)
Takashi Iwai a48e6b
+{
Takashi Iwai a48e6b
+	int i;
Takashi Iwai a48e6b
+
Takashi Iwai a48e6b
+	for (i = 0; i < MESON_CVBS_MODES_COUNT; ++i) {
Takashi Iwai a48e6b
+		struct meson_cvbs_mode *meson_mode = &meson_cvbs_modes[i];
Takashi Iwai a48e6b
+
Takashi Iwai a48e6b
+		if (drm_mode_match(req_mode, &meson_mode->mode,
Takashi Iwai a48e6b
+				   DRM_MODE_MATCH_TIMINGS |
Takashi Iwai a48e6b
+				   DRM_MODE_MATCH_CLOCK |
Takashi Iwai a48e6b
+				   DRM_MODE_MATCH_FLAGS |
Takashi Iwai a48e6b
+				   DRM_MODE_MATCH_3D_FLAGS))
Takashi Iwai a48e6b
+			return meson_mode;
Takashi Iwai a48e6b
+	}
Takashi Iwai a48e6b
+
Takashi Iwai a48e6b
+	return NULL;
Takashi Iwai a48e6b
+}
Takashi Iwai a48e6b
+
Takashi Iwai a48e6b
 /* Connector */
Takashi Iwai a48e6b
 
Takashi Iwai a48e6b
 static void meson_cvbs_connector_destroy(struct drm_connector *connector)
Takashi Iwai a48e6b
@@ -136,14 +155,8 @@ static int meson_venc_cvbs_encoder_atomic_check(struct drm_encoder *encoder,
Takashi Iwai a48e6b
 					struct drm_crtc_state *crtc_state,
Takashi Iwai a48e6b
 					struct drm_connector_state *conn_state)
Takashi Iwai a48e6b
 {
Takashi Iwai a48e6b
-	int i;
Takashi Iwai a48e6b
-
Takashi Iwai a48e6b
-	for (i = 0; i < MESON_CVBS_MODES_COUNT; ++i) {
Takashi Iwai a48e6b
-		struct meson_cvbs_mode *meson_mode = &meson_cvbs_modes[i];
Takashi Iwai a48e6b
-
Takashi Iwai a48e6b
-		if (drm_mode_equal(&crtc_state->mode, &meson_mode->mode))
Takashi Iwai a48e6b
-			return 0;
Takashi Iwai a48e6b
-	}
Takashi Iwai a48e6b
+	if (meson_cvbs_get_mode(&crtc_state->mode))
Takashi Iwai a48e6b
+		return 0;
Takashi Iwai a48e6b
 
Takashi Iwai a48e6b
 	return -EINVAL;
Takashi Iwai a48e6b
 }
Takashi Iwai a48e6b
@@ -191,24 +204,17 @@ static void meson_venc_cvbs_encoder_mode_set(struct drm_encoder *encoder,
Takashi Iwai a48e6b
 				   struct drm_display_mode *mode,
Takashi Iwai a48e6b
 				   struct drm_display_mode *adjusted_mode)
Takashi Iwai a48e6b
 {
Takashi Iwai a48e6b
+	const struct meson_cvbs_mode *meson_mode = meson_cvbs_get_mode(mode);
Takashi Iwai a48e6b
 	struct meson_venc_cvbs *meson_venc_cvbs =
Takashi Iwai a48e6b
 					encoder_to_meson_venc_cvbs(encoder);
Takashi Iwai a48e6b
 	struct meson_drm *priv = meson_venc_cvbs->priv;
Takashi Iwai a48e6b
-	int i;
Takashi Iwai a48e6b
 
Takashi Iwai a48e6b
-	for (i = 0; i < MESON_CVBS_MODES_COUNT; ++i) {
Takashi Iwai a48e6b
-		struct meson_cvbs_mode *meson_mode = &meson_cvbs_modes[i];
Takashi Iwai a48e6b
+	if (meson_mode) {
Takashi Iwai a48e6b
+		meson_venci_cvbs_mode_set(priv, meson_mode->enci);
Takashi Iwai a48e6b
 
Takashi Iwai a48e6b
-		if (drm_mode_equal(mode, &meson_mode->mode)) {
Takashi Iwai a48e6b
-			meson_venci_cvbs_mode_set(priv,
Takashi Iwai a48e6b
-						  meson_mode->enci);
Takashi Iwai a48e6b
-
Takashi Iwai a48e6b
-			/* Setup 27MHz vclk2 for ENCI and VDAC */
Takashi Iwai a48e6b
-			meson_vclk_setup(priv, MESON_VCLK_TARGET_CVBS,
Takashi Iwai a48e6b
-					 MESON_VCLK_CVBS, MESON_VCLK_CVBS,
Takashi Iwai a48e6b
-					 MESON_VCLK_CVBS, true);
Takashi Iwai a48e6b
-			break;
Takashi Iwai a48e6b
-		}
Takashi Iwai a48e6b
+		/* Setup 27MHz vclk2 for ENCI and VDAC */
Takashi Iwai a48e6b
+		meson_vclk_setup(priv, MESON_VCLK_TARGET_CVBS, MESON_VCLK_CVBS,
Takashi Iwai a48e6b
+				 MESON_VCLK_CVBS, MESON_VCLK_CVBS, true);
Takashi Iwai a48e6b
 	}
Takashi Iwai a48e6b
 }
Takashi Iwai a48e6b
 
Takashi Iwai a48e6b
-- 
Takashi Iwai a48e6b
2.16.4
Takashi Iwai a48e6b