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 <[email protected]> --- 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 d492aebda119..f6d7d65103bb 100644 --- a/drivers/gpu/drm/drm_atomic_sro_helper.c +++ b/drivers/gpu/drm/drm_atomic_sro_helper.c @@ -402,5 +402,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 <linux/string_choices.h> + 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.54.0
