From patchwork Thu Oct 13 13:19:04 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Maxime Ripard X-Patchwork-Id: 13006034 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 28C09C4332F for ; Thu, 13 Oct 2022 13:21:58 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id CB29C10E8EF; Thu, 13 Oct 2022 13:20:01 +0000 (UTC) Received: from new3-smtp.messagingengine.com (new3-smtp.messagingengine.com [66.111.4.229]) by gabe.freedesktop.org (Postfix) with ESMTPS id 25F6E10E8EE; Thu, 13 Oct 2022 13:19:46 +0000 (UTC) Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailnew.nyi.internal (Postfix) with ESMTP id 86C31580363; Thu, 13 Oct 2022 09:19:45 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute3.internal (MEProxy); Thu, 13 Oct 2022 09:19:45 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cerno.tech; h=cc :cc:content-transfer-encoding:content-type:date:date:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:sender:subject:subject:to:to; s=fm3; t=1665667185; x= 1665674385; bh=2iMl0izJCO/+o3472qA/Bs19V2GmOxBXYaItDhGdjlY=; b=I RO0uEv8oXlqxQ/BxwGrUqFyZvxlUd03NE3NzB+wKx9bgSef1NsVGXGlSRVK49YVL qxP/266dW8BXv8VVk8hw+feU3kfapb05OUNv+I3L1ikhyccV/2jObw7wRUy5mYJY bGfgNg3szt++h7njVNJKo9zrdGOhhKzBzPmzmMQnozXCBwwqzhJROuxEmSK2HrEH /b4ePWqqom1IYfzfsysVDSn1ajykTJ5ER0dOhPe2H00Myrw7/jBVEBAu9q989coL vfoAsjaMHHN8CIe4qLH7+Fj/+SPtQO4V+hRccHz3s9iVEMCq4zAg4HhrvjZoTILC 2OEaykMpdO5OPa/OjULIQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:sender:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm3; t=1665667185; x= 1665674385; bh=2iMl0izJCO/+o3472qA/Bs19V2GmOxBXYaItDhGdjlY=; b=R QuH6peORrgwKOVQ3ubfcBEe8r3KOB6XhEDEXsA0zG27Gtlvqabuut0uuMn9F8Wwe WEdqDQ3iYMI15152V/MPmBVw2O0MoSSkh3ly9Bp/rbnioUiZTf8wckmUiGsYpgSn EBXm11p/VFNXzxngAGzRNFtXLaWv72uCiPAh1PajExqOwbL1mbZIVN7xvp9jHB4x J963LmTSgApH/XuGMjpWeV3W+ZAJES+fLUlxXPT7/qnC13AUCkXVKcDPdcf0kJwQ V1/Ejw2Ipig0JQMRLlWckvXiZtoWmAv9Sra/zpZbd82TScYdWr6YcUXNcqVYnA3a cYcKX6v9DpsyqOVFsPx9g== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvfedrfeektddgieehucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephfffufgggfgtkfhfjgfvvefosehtkeertdertdejnecuhfhrohhmpeforgig ihhmvgcutfhiphgrrhguuceomhgrgihimhgvsegtvghrnhhordhtvggthheqnecuggftrf grthhtvghrnhepvdfgveejhfdtteevvefhleeiueeutefgvdegveekgedujeffgeffgfet tdellefhnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrhhomh epmhgrgihimhgvsegtvghrnhhordhtvggthh X-ME-Proxy: Feedback-ID: i8771445c:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Thu, 13 Oct 2022 09:19:44 -0400 (EDT) From: Maxime Ripard Date: Thu, 13 Oct 2022 15:19:04 +0200 Subject: [PATCH v5 20/22] drm/vc4: vec: Convert to the new TV mode property MIME-Version: 1.0 Message-Id: <20220728-rpi-analog-tv-properties-v5-20-d841cc64fe4b@cerno.tech> References: <20220728-rpi-analog-tv-properties-v5-0-d841cc64fe4b@cerno.tech> In-Reply-To: <20220728-rpi-analog-tv-properties-v5-0-d841cc64fe4b@cerno.tech> To: Karol Herbst , Jani Nikula , Tvrtko Ursulin , Daniel Vetter , Maarten Lankhorst , David Airlie , Joonas Lahtinen , Lyude Paul , Maxime Ripard , Emma Anholt , Chen-Yu Tsai , Samuel Holland , Ben Skeggs , Thomas Zimmermann , Rodrigo Vivi , Jernej Skrabec X-Mailer: b4 0.11.0-dev-7da52 X-Developer-Signature: v=1; a=openpgp-sha256; l=9855; i=maxime@cerno.tech; h=from:subject:message-id; bh=5VPlasEhOSLJuI/cwZQa5WDmU05XD3lZAKObeZePG7w=; b=owGbwMvMwCX2+D1vfrpE4FHG02pJDMkeAu5ygpsL7f/sOFTzUzt4KQuz9KbGRsG7N60rDV6+ads/ c/PEjlIWBjEuBlkxRZYYYfMlcadmve5k45sHM4eVCWQIAxenAEzk/iVGhmlrvj4+YvHW9Mxeh6ftL2 UuTdt2s3WK9rzbggby01eflytn+MMVk5Rr3/uy9NQy1gecx3xvlyReuCC8JeXf6ncNb3WikpkA X-Developer-Key: i=maxime@cerno.tech; a=openpgp; fpr=BE5675C37E818C8B5764241C254BCFC56BF6CE8D X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?unknown-8bit?q?Dom_Cobley_=3Cdom=40raspberrypi=2Ecom=3E=2C_Dave_Steven?= =?unknown-8bit?q?son_=3Cdave=2Estevenson=40raspberrypi=2Ecom=3E=2C_Phil_Elw?= =?unknown-8bit?q?ell_=3Cphil=40raspberrypi=2Ecom=3E=2C_nouveau=40lists=2Efr?= =?unknown-8bit?q?eedesktop=2Eorg=2C_intel-gfx=40lists=2Efreedesktop=2Eorg?= =?unknown-8bit?q?=2C_linux-kernel=40vger=2Ekernel=2Eorg=2C_dri-devel=40list?= =?unknown-8bit?q?s=2Efreedesktop=2Eorg=2C_Mateusz_Kwiatkowski_=3Ckfyatek+pu?= =?unknown-8bit?q?blicgit=40gmail=2Ecom=3E=2C_Hans_de_Goede_=3Chdegoede=40re?= =?unknown-8bit?q?dhat=2Ecom=3E=2C_Noralf_Tr=C3=B8nnes_=3Cnoralf=40tronnes?= =?unknown-8bit?q?=2Eorg=3E=2C_Geert_Uytterhoeven_=3Cgeert=40linux-m68k=2Eor?= =?unknown-8bit?q?g=3E=2C_Maxime_Ripard_=3Cmaxime=40cerno=2Etech=3E=2C_linux?= =?unknown-8bit?q?-sunxi=40lists=2Elinux=2Edev=2C_linux-arm-kernel=40lists?= =?unknown-8bit?q?=2Einfradead=2Eorg?= Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" Now that the core can deal fine with analog TV modes, let's convert the vc4 VEC driver to leverage those new features. We've added some backward compatibility to support the old TV mode property and translate it into the new TV norm property. We're also making use of the new analog TV atomic_check helper to make sure we trigger a modeset whenever the TV mode is updated. Acked-by: Noralf Trønnes Signed-off-by: Maxime Ripard --- Changes in v5: - Renamed tv_mode_names into legacy_tv_mode_names Changes in v4: - Removed the count variable in .get_modes --- drivers/gpu/drm/vc4/vc4_vec.c | 193 +++++++++++++++++++++++++++++++----------- 1 file changed, 145 insertions(+), 48 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c index 1fcb7baf874e..456689b45849 100644 --- a/drivers/gpu/drm/vc4/vc4_vec.c +++ b/drivers/gpu/drm/vc4/vc4_vec.c @@ -172,6 +172,8 @@ struct vc4_vec { struct clk *clock; + struct drm_property *legacy_tv_mode_property; + struct debugfs_regset32 regset; }; @@ -184,6 +186,12 @@ encoder_to_vc4_vec(struct drm_encoder *encoder) return container_of(encoder, struct vc4_vec, encoder.base); } +static inline struct vc4_vec * +connector_to_vc4_vec(struct drm_connector *connector) +{ + return container_of(connector, struct vc4_vec, connector); +} + enum vc4_vec_tv_mode_id { VC4_VEC_TV_MODE_NTSC, VC4_VEC_TV_MODE_NTSC_J, @@ -192,7 +200,7 @@ enum vc4_vec_tv_mode_id { }; struct vc4_vec_tv_mode { - const struct drm_display_mode *mode; + unsigned int mode; u32 config0; u32 config1; u32 custom_freq; @@ -225,43 +233,51 @@ static const struct debugfs_reg32 vec_regs[] = { VC4_REG32(VEC_DAC_MISC), }; -static const struct drm_display_mode ntsc_mode = { - DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 13500, - 720, 720 + 14, 720 + 14 + 64, 720 + 14 + 64 + 60, 0, - 480, 480 + 7, 480 + 7 + 6, 525, 0, - DRM_MODE_FLAG_INTERLACE) -}; - -static const struct drm_display_mode pal_mode = { - DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 13500, - 720, 720 + 20, 720 + 20 + 64, 720 + 20 + 64 + 60, 0, - 576, 576 + 4, 576 + 4 + 6, 625, 0, - DRM_MODE_FLAG_INTERLACE) -}; - static const struct vc4_vec_tv_mode vc4_vec_tv_modes[] = { - [VC4_VEC_TV_MODE_NTSC] = { - .mode = &ntsc_mode, + { + .mode = DRM_MODE_TV_MODE_NTSC, .config0 = VEC_CONFIG0_NTSC_STD | VEC_CONFIG0_PDEN, .config1 = VEC_CONFIG1_C_CVBS_CVBS, }, - [VC4_VEC_TV_MODE_NTSC_J] = { - .mode = &ntsc_mode, + { + .mode = DRM_MODE_TV_MODE_NTSC_J, .config0 = VEC_CONFIG0_NTSC_STD, .config1 = VEC_CONFIG1_C_CVBS_CVBS, }, - [VC4_VEC_TV_MODE_PAL] = { - .mode = &pal_mode, + { + .mode = DRM_MODE_TV_MODE_PAL, .config0 = VEC_CONFIG0_PAL_BDGHI_STD, .config1 = VEC_CONFIG1_C_CVBS_CVBS, }, - [VC4_VEC_TV_MODE_PAL_M] = { - .mode = &ntsc_mode, + { + .mode = DRM_MODE_TV_MODE_PAL_M, .config0 = VEC_CONFIG0_PAL_M_STD, .config1 = VEC_CONFIG1_C_CVBS_CVBS, }, }; +static inline const struct vc4_vec_tv_mode * +vc4_vec_tv_mode_lookup(unsigned int mode) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(vc4_vec_tv_modes); i++) { + const struct vc4_vec_tv_mode *tv_mode = &vc4_vec_tv_modes[i]; + + if (tv_mode->mode == mode) + return tv_mode; + } + + return NULL; +} + +static const struct drm_prop_enum_list legacy_tv_mode_names[] = { + { VC4_VEC_TV_MODE_NTSC, "NTSC", }, + { VC4_VEC_TV_MODE_NTSC_J, "NTSC-J", }, + { VC4_VEC_TV_MODE_PAL, "PAL", }, + { VC4_VEC_TV_MODE_PAL_M, "PAL-M", }, +}; + static enum drm_connector_status vc4_vec_connector_detect(struct drm_connector *connector, bool force) { @@ -276,19 +292,96 @@ static void vc4_vec_connector_reset(struct drm_connector *connector) static int vc4_vec_connector_get_modes(struct drm_connector *connector) { - struct drm_connector_state *state = connector->state; struct drm_display_mode *mode; - mode = drm_mode_duplicate(connector->dev, - vc4_vec_tv_modes[state->tv.legacy_mode].mode); + mode = drm_mode_analog_ntsc_480i(connector->dev); if (!mode) { DRM_ERROR("Failed to create a new display mode\n"); return -ENOMEM; } + mode->type |= DRM_MODE_TYPE_PREFERRED; drm_mode_probed_add(connector, mode); - return 1; + mode = drm_mode_analog_pal_576i(connector->dev); + if (!mode) { + DRM_ERROR("Failed to create a new display mode\n"); + return -ENOMEM; + } + + drm_mode_probed_add(connector, mode); + + return 2; +} + +static int +vc4_vec_connector_set_property(struct drm_connector *connector, + struct drm_connector_state *state, + struct drm_property *property, + uint64_t val) +{ + struct vc4_vec *vec = connector_to_vc4_vec(connector); + + if (property != vec->legacy_tv_mode_property) + return -EINVAL; + + switch (val) { + case VC4_VEC_TV_MODE_NTSC: + state->tv.mode = DRM_MODE_TV_MODE_NTSC; + break; + + case VC4_VEC_TV_MODE_NTSC_J: + state->tv.mode = DRM_MODE_TV_MODE_NTSC_J; + break; + + case VC4_VEC_TV_MODE_PAL: + state->tv.mode = DRM_MODE_TV_MODE_PAL; + break; + + case VC4_VEC_TV_MODE_PAL_M: + state->tv.mode = DRM_MODE_TV_MODE_PAL_M; + break; + + default: + return -EINVAL; + } + + return 0; +} + +static int +vc4_vec_connector_get_property(struct drm_connector *connector, + const struct drm_connector_state *state, + struct drm_property *property, + uint64_t *val) +{ + struct vc4_vec *vec = connector_to_vc4_vec(connector); + + if (property != vec->legacy_tv_mode_property) + return -EINVAL; + + switch (state->tv.mode) { + case DRM_MODE_TV_MODE_NTSC: + *val = VC4_VEC_TV_MODE_NTSC; + break; + + case DRM_MODE_TV_MODE_NTSC_J: + *val = VC4_VEC_TV_MODE_NTSC_J; + break; + + case DRM_MODE_TV_MODE_PAL: + *val = VC4_VEC_TV_MODE_PAL; + break; + + case DRM_MODE_TV_MODE_PAL_M: + *val = VC4_VEC_TV_MODE_PAL_M; + break; + + default: + return -EINVAL; + } + + return 0; } static const struct drm_connector_funcs vc4_vec_connector_funcs = { @@ -297,15 +390,19 @@ static const struct drm_connector_funcs vc4_vec_connector_funcs = { .reset = vc4_vec_connector_reset, .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, + .atomic_get_property = vc4_vec_connector_get_property, + .atomic_set_property = vc4_vec_connector_set_property, }; static const struct drm_connector_helper_funcs vc4_vec_connector_helper_funcs = { + .atomic_check = drm_atomic_helper_connector_tv_check, .get_modes = vc4_vec_connector_get_modes, }; static int vc4_vec_connector_init(struct drm_device *dev, struct vc4_vec *vec) { struct drm_connector *connector = &vec->connector; + struct drm_property *prop; int ret; connector->interlace_allowed = true; @@ -318,8 +415,17 @@ static int vc4_vec_connector_init(struct drm_device *dev, struct vc4_vec *vec) drm_connector_helper_add(connector, &vc4_vec_connector_helper_funcs); drm_object_attach_property(&connector->base, - dev->mode_config.legacy_tv_mode_property, - VC4_VEC_TV_MODE_NTSC); + dev->mode_config.tv_mode_property, + DRM_MODE_TV_MODE_NTSC); + + prop = drm_property_create_enum(dev, 0, "mode", + legacy_tv_mode_names, + ARRAY_SIZE(legacy_tv_mode_names)); + if (!prop) + return -ENOMEM; + vec->legacy_tv_mode_property = prop; + + drm_object_attach_property(&connector->base, prop, VC4_VEC_TV_MODE_NTSC); drm_connector_attach_encoder(connector, &vec->encoder.base); @@ -366,13 +472,16 @@ static void vc4_vec_encoder_enable(struct drm_encoder *encoder, struct drm_connector *connector = &vec->connector; struct drm_connector_state *conn_state = drm_atomic_get_new_connector_state(state, connector); - const struct vc4_vec_tv_mode *tv_mode = - &vc4_vec_tv_modes[conn_state->tv.legacy_mode]; + const struct vc4_vec_tv_mode *tv_mode; int idx, ret; if (!drm_dev_enter(drm, &idx)) return; + tv_mode = vc4_vec_tv_mode_lookup(conn_state->tv.mode); + if (!tv_mode) + goto err_dev_exit; + ret = pm_runtime_get_sync(&vec->pdev->dev); if (ret < 0) { DRM_ERROR("Failed to retain power domain: %d\n", ret); @@ -454,13 +563,6 @@ static int vc4_vec_encoder_atomic_check(struct drm_encoder *encoder, struct drm_connector_state *conn_state) { const struct drm_display_mode *mode = &crtc_state->adjusted_mode; - const struct vc4_vec_tv_mode *vec_mode; - - vec_mode = &vc4_vec_tv_modes[conn_state->tv.legacy_mode]; - - if (conn_state->crtc && - !drm_mode_equal(vec_mode->mode, &crtc_state->adjusted_mode)) - return -EINVAL; if (mode->crtc_hdisplay % 4) return -EINVAL; @@ -554,13 +656,6 @@ static const struct of_device_id vc4_vec_dt_match[] = { { /* sentinel */ }, }; -static const char * const tv_mode_names[] = { - [VC4_VEC_TV_MODE_NTSC] = "NTSC", - [VC4_VEC_TV_MODE_NTSC_J] = "NTSC-J", - [VC4_VEC_TV_MODE_PAL] = "PAL", - [VC4_VEC_TV_MODE_PAL_M] = "PAL-M", -}; - static int vc4_vec_bind(struct device *dev, struct device *master, void *data) { struct platform_device *pdev = to_platform_device(dev); @@ -568,9 +663,11 @@ static int vc4_vec_bind(struct device *dev, struct device *master, void *data) struct vc4_vec *vec; int ret; - ret = drm_mode_create_tv_properties_legacy(drm, - ARRAY_SIZE(tv_mode_names), - tv_mode_names); + ret = drm_mode_create_tv_properties(drm, + BIT(DRM_MODE_TV_MODE_NTSC) | + BIT(DRM_MODE_TV_MODE_NTSC_J) | + BIT(DRM_MODE_TV_MODE_PAL) | + BIT(DRM_MODE_TV_MODE_PAL_M)); if (ret) return ret;