From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 886F23E6DED for ; Thu, 23 Apr 2026 10:19:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776939568; cv=none; b=LBpUss0780oEDLbOmaIPlTywHLykf8sCz8wwvEhjWYKx2L7e/UbtmeJrVLVjFZX1XbAG7tbzZ4yVPYVLnBbJ1vmMlj3HC6k3OgTt9svFdcr0F36MnOEbUmKbbg89pN7UiXJbobFyQAAR0sfA2ri5WFtoDI/gBL5MZU59IwaPpx8= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776939568; c=relaxed/simple; bh=LmSJHcwz813jKS8EI1LfN67TzI4VaJK7ypQYNHNj0a0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=K6ngrrmZM5BztVg3EuzKi7/xuvp5qbXygm5KlIedCM7HZt5Xzqq3MRITeVpWaVe1mOs0hEdD000cjPIiCZYqUJckJuHts3nEziO8kDVF+QxxGk12NRstKTA6cgDBidbVqyC3Nl6+Xfvf6Fo+tZtiLWr6qSplFazeHx4kRVwZlpE= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=CnZsVTvx; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="CnZsVTvx" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A7D76C2BCB6; Thu, 23 Apr 2026 10:19:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1776939568; bh=LmSJHcwz813jKS8EI1LfN67TzI4VaJK7ypQYNHNj0a0=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=CnZsVTvx1gPnEQeFjuGknezRzB2bog1Np0l/W5GDqlsm2SQMMFCrlwIIC3SNddU84 FHfn6QQcau+/wp26Mgyk8DReTD2I5fjUpmi1NHXXm7EAvggWCDNCXHgP+w1W9h431A nGEJ+Csofe/79PGx+gg/Gl7IEzeFMyrTPnH6AJyYC2cVy1j8A5JrIkKtaSB1UfkyGK SerCyNIEdcglcmXxRtydNvFBjZLxwHvg3OCGGQRm/RfMexl1NqXbmwyT1GmRIi6ncA Uy1hBreXazWmHg0pahylLF9ukrm5wkLsRmIDtwhW9Td4DQWMuYOwiwMYgpQgvx6aye rauHJBL2EzdOQ== From: Maxime Ripard Date: Thu, 23 Apr 2026 12:18:33 +0200 Subject: [PATCH v2 20/28] drm/atomic_state_helper: Provide comparison macros Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20260423-drm-state-readout-v2-20-8549f87cb978@kernel.org> References: <20260423-drm-state-readout-v2-0-8549f87cb978@kernel.org> In-Reply-To: <20260423-drm-state-readout-v2-0-8549f87cb978@kernel.org> To: Maarten Lankhorst , Thomas Zimmermann , David Airlie , Simona Vetter , Andrzej Hajda , Neil Armstrong , Robert Foss , Laurent Pinchart , Jonas Karlman , Jernej Skrabec , Jyri Sarha , Tomi Valkeinen Cc: Devarsh Thakkar , dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, Maxime Ripard X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=10409; i=mripard@kernel.org; h=from:subject:message-id; bh=LmSJHcwz813jKS8EI1LfN67TzI4VaJK7ypQYNHNj0a0=; b=owGbwMvMwCmsHn9OcpHtvjLG02pJDJkvP354v+LDzLkzJf+XlWaccQxaxMBnIm9zZ3XVrF3VT G7r6wJkO6ayMAhzMsiKKbI8kQk7vbx9cZWD/cofMHNYmUCGMHBxCsBEkp4z1vCLmyj+qFFMz9L/ XPN8lvyv2p+m3nt91v38eC7pfTjLmqwzH7el373kaPRvUuLL1zEpcoz1hWK6f5+dzzevjNrOuyB lf+26s9azJ1+99uLS6t3n6nkZbkYnLS5l+mS50/LuA+U/U7+6AQA= X-Developer-Key: i=mripard@kernel.org; a=openpgp; fpr=BE5675C37E818C8B5764241C254BCFC56BF6CE8D In order to make the implementation of atomic_compare_state easier and reduce the boilerplate, introduce a set of STATE_CHECK_* macros to compare state field values depending on their type. Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_atomic_sro_helper.c | 30 +++++ include/drm/drm_atomic_sro_helper.h | 219 ++++++++++++++++++++++++++++++++ 2 files changed, 249 insertions(+) diff --git a/drivers/gpu/drm/drm_atomic_sro_helper.c b/drivers/gpu/drm/drm_atomic_sro_helper.c index 367d9bb7e442..b6411bfdba78 100644 --- a/drivers/gpu/drm/drm_atomic_sro_helper.c +++ b/drivers/gpu/drm/drm_atomic_sro_helper.c @@ -403,5 +403,35 @@ int drm_atomic_helper_sro_readout_state(struct drm_device *dev) drm_atomic_sro_state_free(state); return 0; } EXPORT_SYMBOL(drm_atomic_helper_sro_readout_state); + +/** + * drm_atomic_helper_print_state_mismatch - report a state comparison mismatch + * @p: printer to report through + * @name: human-readable name of the object (e.g. plane or CRTC name) + * @field: name of the mismatching field + * @format: printf-style format string describing the mismatch + * + * Helper used by atomic_sro_compare_state implementations and the + * STATE_CHECK_* macros to report a field-level mismatch between the + * committed state and the state read back from hardware. + */ +void __printf(4, 5) +drm_atomic_helper_print_state_mismatch(struct drm_printer *p, + const char *name, + const char *field, + const char *format, ...) +{ + struct va_format vaf; + va_list args; + + va_start(args, format); + vaf.fmt = format; + vaf.va = &args; + + drm_printf(p, "%s configuration mismatch in %s %pV\n", name, field, &vaf); + + va_end(args); +} +EXPORT_SYMBOL(drm_atomic_helper_print_state_mismatch); diff --git a/include/drm/drm_atomic_sro_helper.h b/include/drm/drm_atomic_sro_helper.h index a42ed8136a49..db5d62ac0db9 100644 --- a/include/drm/drm_atomic_sro_helper.h +++ b/include/drm/drm_atomic_sro_helper.h @@ -1,12 +1,15 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ #ifndef DRM_ATOMIC_SRO_HELPER_H_ #define DRM_ATOMIC_SRO_HELPER_H_ +#include + struct drm_atomic_sro_state; struct drm_device; +struct drm_printer; int drm_atomic_helper_sro_readout_planes_state(struct drm_device *dev, struct drm_atomic_sro_state *state); int @@ -23,6 +26,222 @@ drm_atomic_helper_sro_readout_private_objs_state(struct drm_device *dev, struct drm_atomic_sro_state *state); struct drm_atomic_sro_state * drm_atomic_helper_sro_build_state(struct drm_device *dev); int drm_atomic_helper_sro_readout_state(struct drm_device *dev); +void __printf(4, 5) +drm_atomic_helper_print_state_mismatch(struct drm_printer *p, + const char *name, + const char *field, + const char *format, ...); + +#define STATE_CHECK_BOOL(r, p, n, sa, sb, f) \ + do { \ + static_assert(__same_type(sa->f, sb->f), \ + __stringify(f) " field types don't match"); \ + static_assert(__same_type(sa->f, bool), \ + __stringify(name) " is not a bool"); \ + if (sa->f != sb->f) { \ + drm_atomic_helper_print_state_mismatch(p, \ + n, \ + __stringify(f), \ + "expected %s, got %s", \ + str_yes_no(sa->f), \ + str_yes_no(sb->f)); \ + r = false; \ + } \ + } while (0) + +#define STATE_CHECK_DISPLAY_MODE(r, p, n, sa, sb, f) \ + do { \ + static_assert(__same_type(sa->f, sb->f), \ + __stringify(f) " field types don't match"); \ + static_assert(__same_type(sa->f, struct drm_display_mode), \ + __stringify(name) " is not a drm_display_mode structure"); \ + if (!drm_mode_equal(&sa->f, &sb->f)) { \ + drm_atomic_helper_print_state_mismatch(p, \ + n, \ + __stringify(f), \ + "expected " DRM_MODE_FMT ", got " DRM_MODE_FMT, \ + DRM_MODE_ARG(&sa->f), \ + DRM_MODE_ARG(&sb->f)); \ + r = false; \ + } \ + } while (0) + +#define STATE_CHECK_INFOFRAME(r, p, n, sa, sb, f) \ + do { \ + static_assert(__same_type(sa->f, sb->f), \ + __stringify(f) " field types don't match"); \ + static_assert(__same_type(sa->f, union hdmi_infoframe), \ + __stringify(name) " is not an hdmi_infoframe union"); \ + if (memcmp(&sa->f, &sb->f, sizeof(union hdmi_infoframe))) { \ + drm_atomic_helper_print_state_mismatch(p, \ + n, \ + __stringify(f), \ + "infoframes don't match"); \ + r = false; \ + } \ + } while (0) + +#define STATE_CHECK_FORMAT_INFO(r, p, n, sa, sb, f) \ + do { \ + static_assert(__same_type(sa->f, sb->f), \ + __stringify(f) " field types don't match"); \ + static_assert(__same_type(sa->f, const struct drm_format_info *), \ + __stringify(name) " is not a drm_format_info pointer"); \ + if (sa->f != sb->f) { \ + drm_atomic_helper_print_state_mismatch(p, \ + n, \ + __stringify(f), \ + "expected %p4cc, got %p4cc", \ + &sa->f->format, \ + &sb->f->format); \ + r = false; \ + } \ + } while (0) + +#define STATE_CHECK_PROPERTY_BLOB(r, p, n, sa, sb, f) \ + do { \ + static_assert(__same_type(sa->f, sb->f), \ + __stringify(f) " field types don't match"); \ + static_assert(__same_type(sa->f, struct drm_property_blob *), \ + __stringify(name) " is not a drm_property_blob pointer"); \ + if (sa->f != sb->f && \ + ((sa->f->length != sb->f->length) || \ + memcmp(sa->f->data, sb->f->data, sa->f->length))) { \ + drm_atomic_helper_print_state_mismatch(p, \ + n, \ + __stringify(f), \ + "blobs don't match"); \ + r = false; \ + } \ + } while (0) + +#define STATE_CHECK_PTR(r, p, n, sa, sb, f) \ + do { \ + static_assert(__same_type(sa->f, sb->f), \ + __stringify(f) " field types don't match"); \ + if (sa->f != sb->f) { \ + drm_atomic_helper_print_state_mismatch(p, \ + n, \ + __stringify(f), \ + "expected %p, got %p", \ + sa->f, sb->f); \ + r = false; \ + } \ + } while (0) + +#define STATE_CHECK_S32(r, p, n, sa, sb, f) \ + do { \ + static_assert(__same_type(sa->f, sb->f), \ + __stringify(f) " field types don't match"); \ + static_assert(__same_type(sa->f, (s32)0), \ + __stringify(name) " is not an s32"); \ + if (sa->f != sb->f) { \ + drm_atomic_helper_print_state_mismatch(p, \ + n, \ + __stringify(f), \ + "expected %u, got %u", \ + sa->f, sb->f); \ + r = false; \ + } \ + } while (0) + +#define STATE_CHECK_S32_X(r, p, n, sa, sb, f) \ + do { \ + static_assert(__same_type(sa->f, sb->f), \ + __stringify(f) " field types don't match"); \ + static_assert(__same_type(sa->f, (s32)0), \ + __stringify(name) " is not an s32"); \ + if (sa->f != sb->f) { \ + drm_atomic_helper_print_state_mismatch(p, \ + n, \ + __stringify(f), \ + "expected %x, got %x", \ + sa->f, sb->f); \ + r = false; \ + } \ + } while (0) + +#define STATE_CHECK_U16(r, p, n, sa, sb, f) \ + do { \ + static_assert(__same_type(sa->f, sb->f), \ + __stringify(f) " field types don't match"); \ + static_assert(__same_type(sa->f, (u16)0), \ + __stringify(name) " is not a u16"); \ + if (sa->f != sb->f) { \ + drm_atomic_helper_print_state_mismatch(p, \ + n, \ + __stringify(f), \ + "expected %u, got %u", \ + sa->f, sb->f); \ + r = false; \ + } \ + } while (0) + +#define STATE_CHECK_U32(r, p, n, sa, sb, f) \ + do { \ + static_assert(__same_type(sa->f, sb->f), \ + __stringify(f) " field types don't match"); \ + static_assert(__same_type(sa->f, (u32)0), \ + __stringify(name) " is not a u32"); \ + if (sa->f != sb->f) { \ + drm_atomic_helper_print_state_mismatch(p, \ + n, \ + __stringify(f), \ + "expected %u, got %u", \ + sa->f, sb->f); \ + r = false; \ + } \ + } while (0) + +#define STATE_CHECK_U32_16_16(r, p, n, sa, sb, f) \ + do { \ + static_assert(__same_type(sa->f, sb->f), \ + __stringify(f) " field types don't match"); \ + static_assert(__same_type(sa->f, (u32)0), \ + __stringify(name) " is not a u32"); \ + if (sa->f != sb->f) { \ + drm_atomic_helper_print_state_mismatch(p, \ + n, \ + __stringify(f), \ + "expected %d.%06u, got %d.%06u", \ + sa->f >> 16, ((sa->f && 0xffff) * 15625) >> 10, \ + sb->f >> 16, ((sb->f && 0xffff) * 15625) >> 10); \ + r = false; \ + } \ + } while (0) + +#define STATE_CHECK_U32_X(r, p, n, sa, sb, f) \ + do { \ + static_assert(__same_type(sa->f, sb->f), \ + __stringify(f) " field types don't match"); \ + static_assert(__same_type(sa->f, (u32)0), \ + __stringify(name) " is not a u32"); \ + if (sa->f != sb->f) { \ + drm_atomic_helper_print_state_mismatch(p, \ + n, \ + __stringify(f), \ + "expected %08x, got %08x", \ + sa->f, sb->f); \ + r = false; \ + } \ + } while (0) + +#define STATE_CHECK_U64(r, p, n, sa, sb, f) \ + do { \ + static_assert(__same_type(sa->f, sb->f), \ + __stringify(f) " field types don't match"); \ + static_assert(__same_type(sa->f, (u64)0), \ + __stringify(name) " is not a u64"); \ + if (sa->f != sb->f) { \ + drm_atomic_helper_print_state_mismatch(p, \ + n, \ + __stringify(f), \ + "expected %llu, got %llu", \ + sa->f, sb->f); \ + r = false; \ + } \ + } while (0) + #endif /* DRM_ATOMIC_SRO_HELPER_H_ */ -- 2.53.0