From mboxrd@z Thu Jan 1 00:00:00 1970 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 CBA82CD5BD1 for ; Tue, 26 May 2026 16:47:15 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 0D73610E720; Tue, 26 May 2026 16:47:15 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=kernel.org header.i=@kernel.org header.b="kuFoo3O8"; dkim-atps=neutral Received: from sea.source.kernel.org (sea.source.kernel.org [172.234.252.31]) by gabe.freedesktop.org (Postfix) with ESMTPS id 3627910E720; Tue, 26 May 2026 16:47:12 +0000 (UTC) Received: from smtp.kernel.org (quasi.space.kernel.org [100.103.45.18]) by sea.source.kernel.org (Postfix) with ESMTP id 17E904321A; Tue, 26 May 2026 16:47:12 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3C2D91F00A3F; Tue, 26 May 2026 16:47:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1779814032; bh=YVd/1WhGwRypYnaVWi4R06/xFOEvMXU+alOysERPHRk=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=kuFoo3O8zsEHoN5QXKy4DGVo71Np0UBtkJij1HSNM5ItaOiMKruDf5hzsJDfElPR0 6QAVqsZv0AFH5cx+jeyxIBnmM8cppqJy/N0JCVEI7aomagHSLjhKIbFU9mNINIrDwa w2rxly6bvBut6tEZUx9He83B7YeGLNqncgueVSToB12acB8cMdNdOuQyN1l6RwYDoV na7Dgn97F65X8MLOKISUT82bonNBJtXdtZHgFDu/7OZ1yqPgKGsciw49FxsPVd2Oj/ 4TGYwReqwbvK7BE6xuKEbazwKuFl1atdHuTkzA8z+kEZNvPecu4lILb/lVA8449pY3 7dSJUuHzFAK0A== From: Maxime Ripard Date: Tue, 26 May 2026 18:46:28 +0200 Subject: [PATCH v6 16/19] drm/mode-config: Create drm_mode_config_create_initial_state() MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20260526-drm-mode-config-init-v6-16-852346394200@kernel.org> References: <20260526-drm-mode-config-init-v6-0-852346394200@kernel.org> In-Reply-To: <20260526-drm-mode-config-init-v6-0-852346394200@kernel.org> To: Maarten Lankhorst , Thomas Zimmermann , David Airlie , Simona Vetter , Jonathan Corbet , Shuah Khan , Dmitry Baryshkov , Jyri Sarha , Tomi Valkeinen , Andrzej Hajda , Neil Armstrong , Robert Foss , Laurent Pinchart , Jonas Karlman , Jernej Skrabec , Simon Ser , Harry Wentland , Melissa Wen , Sebastian Wick , Alex Hung , Jani Nikula , Rodrigo Vivi , Joonas Lahtinen , Tvrtko Ursulin , Chen-Yu Tsai , Samuel Holland , Dave Stevenson , =?utf-8?q?Ma=C3=ADra_Canal?= , Raspberry Pi Kernel Maintenance Cc: dri-devel@lists.freedesktop.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Daniel Stone , intel-gfx@lists.freedesktop.org, intel-xe@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, Maxime Ripard , Laurent Pinchart X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=6231; i=mripard@kernel.org; h=from:subject:message-id; bh=cYjI8QYvkKuK5SIyJNpOUPUh8YDmbmoEcur+ZgsP/9E=; b=owGbwMvMwCmsHn9OcpHtvjLG02pJDFmi52Kd3C7WyHnq/j7tv6XWNk32g3bbR0VX8xtv9+xQK mZtZXfomMrCIMzJICumyPJEJuz08vbFVQ72K3/AzGFlAhnCwMUpABPZzsJY79e1bt3hmElfOyMd G19bfV7GuFRyebdz3o57r7/zmB0yZH4nqn90E9e8qrJNdosD/0o0MDb0TUjxMwg4/s/d3XGVy2P zA8y3NSKfebwvynpfzbT3juN8wa3T/nyw0dixuNOh9fD1MwsB X-Developer-Key: i=mripard@kernel.org; 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: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" drm_mode_config_reset() can be used to create the initial state, but also to return to the initial state, when doing a suspend/resume cycle for example. It also affects both the software and the hardware, and drivers can choose to reset the hardware as well. Most will just create an empty state and the synchronisation between hardware and software states will effectively be done when the first commit is done. That dual role can be harmful, since some objects do need to be initialized but also need to be preserved across a suspend/resume cycle. drm_private_obj are such objects for example. Thus, create another helper for drivers to call to initialize their state when the driver is loaded, so we can make drm_mode_config_reset() only about handling suspend/resume and similar. Reviewed-by: Dmitry Baryshkov Reviewed-by: Laurent Pinchart Reviewed-by: Thomas Zimmermann Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_atomic.c | 12 +++++- drivers/gpu/drm/drm_mode_config.c | 89 +++++++++++++++++++++++++++++++++++++++ include/drm/drm_mode_config.h | 1 + 3 files changed, 100 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 3c5714481ad2..796de2bbcb0c 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -58,12 +58,20 @@ * object states are allocated when preparing the update and kept alive * as long as they are active in the device. * * Their respective lifetimes are: * - * - at reset time, the object reset implementation allocates a new - * default state and stores it in the object state pointer. + * - at driver initialization time, the driver calls + * drm_mode_config_create_initial_state() to allocate an initial, + * pristine, state for each object and stores it in the objects state + * pointer. Historically, this was one of drm_mode_config_reset() job, + * so one might still encounter it in a driver. + * + * - When resuming from suspend, drm_mode_config_reset() resets the + * software and hardware state to a known default and stores it in the + * object's state pointer. Not all objects are affected by + * drm_mode_config_reset() though. * * - whenever a new update is needed: * * + drm_atomic_commit_alloc() allocates a new &drm_atomic_commit * instance. diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c index 9d240817f8b6..f432f485a914 100644 --- a/drivers/gpu/drm/drm_mode_config.c +++ b/drivers/gpu/drm/drm_mode_config.c @@ -21,10 +21,11 @@ */ #include #include +#include #include #include #include #include #include @@ -314,10 +315,98 @@ void drm_mode_config_reset(struct drm_device *dev) } drm_connector_list_iter_end(&conn_iter); } EXPORT_SYMBOL(drm_mode_config_reset); +/** + * drm_mode_config_create_initial_state - Allocates the initial state + * @dev: drm device + * + * This functions creates the initial state for all the objects. Drivers + * can use this in e.g. probe to initialize their software state. + * + * It has two main differences with drm_mode_config_reset(): the reset() + * hooks aren't called and thus the hardware will be left untouched, but + * also the &drm_private_obj structures will be initialized as opposed + * to drm_mode_config_reset() that skips them. + * + * Returns: 0 on success, negative error value on failure. + */ +int drm_mode_config_create_initial_state(struct drm_device *dev) +{ + struct drm_crtc *crtc; + struct drm_colorop *colorop; + struct drm_plane *plane; + struct drm_connector *connector; + struct drm_connector_list_iter conn_iter; + struct drm_private_obj *privobj; + int ret; + + drm_for_each_privobj(privobj, dev) { + struct drm_private_state *privobj_state; + + if (privobj->state) + continue; + + if (!privobj->funcs->atomic_create_state) + continue; + + privobj_state = privobj->funcs->atomic_create_state(privobj); + if (IS_ERR(privobj_state)) + return PTR_ERR(privobj_state); + + privobj->state = privobj_state; + } + + drm_for_each_colorop(colorop, dev) { + struct drm_colorop_state *colorop_state; + + if (colorop->state) + continue; + + colorop_state = drm_atomic_helper_colorop_create_state(colorop); + if (IS_ERR(colorop_state)) + return PTR_ERR(colorop_state); + + colorop->state = colorop_state; + } + + drm_for_each_plane(plane, dev) { + if (plane->state) + continue; + + ret = drm_mode_config_plane_create_state(plane); + if (ret) + return ret; + } + + drm_for_each_crtc(crtc, dev) { + if (crtc->state) + continue; + + ret = drm_mode_config_crtc_create_state(crtc); + if (ret) + return ret; + } + + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { + if (connector->state) + continue; + + ret = drm_mode_config_connector_create_state(connector); + if (ret) { + drm_connector_list_iter_end(&conn_iter); + return ret; + } + } + drm_connector_list_iter_end(&conn_iter); + + return 0; +} +EXPORT_SYMBOL(drm_mode_config_create_initial_state); + /* * Global properties */ static const struct drm_prop_enum_list drm_plane_type_enum_list[] = { { DRM_PLANE_TYPE_OVERLAY, "Overlay" }, diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h index e584652ddf67..d8f5b7e9673e 100644 --- a/include/drm/drm_mode_config.h +++ b/include/drm/drm_mode_config.h @@ -1005,9 +1005,10 @@ int __must_check drmm_mode_config_init(struct drm_device *dev); static inline int drm_mode_config_init(struct drm_device *dev) { return drmm_mode_config_init(dev); } +int drm_mode_config_create_initial_state(struct drm_device *dev); void drm_mode_config_reset(struct drm_device *dev); void drm_mode_config_cleanup(struct drm_device *dev); #endif -- 2.54.0