brintos

brintos / linux-shallow public Read only

0
0
Text · 9.6 KiB · 04a6b8c Raw
359 lines · c
1// SPDX-License-Identifier: GPL-2.02 3#include <drm/drm_atomic.h>4#include <drm/drm_atomic_helper.h>5#include <drm/drm_drv.h>6#include <drm/drm_edid.h>7#include <drm/drm_fourcc.h>8#include <drm/drm_kunit_helpers.h>9#include <drm/drm_managed.h>10 11#include <kunit/device.h>12#include <kunit/resource.h>13 14#include <linux/device.h>15#include <linux/platform_device.h>16 17#define KUNIT_DEVICE_NAME	"drm-kunit-mock-device"18 19static const struct drm_mode_config_funcs drm_mode_config_funcs = {20	.atomic_check	= drm_atomic_helper_check,21	.atomic_commit	= drm_atomic_helper_commit,22};23 24/**25 * drm_kunit_helper_alloc_device - Allocate a mock device for a KUnit test26 * @test: The test context object27 *28 * This allocates a fake struct &device to create a mock for a KUnit29 * test. The device will also be bound to a fake driver. It will thus be30 * able to leverage the usual infrastructure and most notably the31 * device-managed resources just like a "real" device.32 *33 * Resources will be cleaned up automatically, but the removal can be34 * forced using @drm_kunit_helper_free_device.35 *36 * Returns:37 * A pointer to the new device, or an ERR_PTR() otherwise.38 */39struct device *drm_kunit_helper_alloc_device(struct kunit *test)40{41	return kunit_device_register(test, KUNIT_DEVICE_NAME);42}43EXPORT_SYMBOL_GPL(drm_kunit_helper_alloc_device);44 45/**46 * drm_kunit_helper_free_device - Frees a mock device47 * @test: The test context object48 * @dev: The device to free49 *50 * Frees a device allocated with drm_kunit_helper_alloc_device().51 */52void drm_kunit_helper_free_device(struct kunit *test, struct device *dev)53{54	kunit_device_unregister(test, dev);55}56EXPORT_SYMBOL_GPL(drm_kunit_helper_free_device);57 58struct drm_device *59__drm_kunit_helper_alloc_drm_device_with_driver(struct kunit *test,60						struct device *dev,61						size_t size, size_t offset,62						const struct drm_driver *driver)63{64	struct drm_device *drm;65	void *container;66	int ret;67 68	container = __devm_drm_dev_alloc(dev, driver, size, offset);69	if (IS_ERR(container))70		return ERR_CAST(container);71 72	drm = container + offset;73	drm->mode_config.funcs = &drm_mode_config_funcs;74 75	ret = drmm_mode_config_init(drm);76	if (ret)77		return ERR_PTR(ret);78 79	return drm;80}81EXPORT_SYMBOL_GPL(__drm_kunit_helper_alloc_drm_device_with_driver);82 83static void action_drm_release_context(void *ptr)84{85	struct drm_modeset_acquire_ctx *ctx = ptr;86 87	drm_modeset_drop_locks(ctx);88	drm_modeset_acquire_fini(ctx);89}90 91/**92 * drm_kunit_helper_acquire_ctx_alloc - Allocates an acquire context93 * @test: The test context object94 *95 * Allocates and initializes a modeset acquire context.96 *97 * The context is tied to the kunit test context, so we must not call98 * drm_modeset_acquire_fini() on it, it will be done so automatically.99 *100 * Returns:101 * An ERR_PTR on error, a pointer to the newly allocated context otherwise102 */103struct drm_modeset_acquire_ctx *104drm_kunit_helper_acquire_ctx_alloc(struct kunit *test)105{106	struct drm_modeset_acquire_ctx *ctx;107	int ret;108 109	ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);110	KUNIT_ASSERT_NOT_NULL(test, ctx);111 112	drm_modeset_acquire_init(ctx, 0);113 114	ret = kunit_add_action_or_reset(test,115					action_drm_release_context,116					ctx);117	if (ret)118		return ERR_PTR(ret);119 120	return ctx;121}122EXPORT_SYMBOL_GPL(drm_kunit_helper_acquire_ctx_alloc);123 124static void kunit_action_drm_atomic_state_put(void *ptr)125{126	struct drm_atomic_state *state = ptr;127 128	drm_atomic_state_put(state);129}130 131/**132 * drm_kunit_helper_atomic_state_alloc - Allocates an atomic state133 * @test: The test context object134 * @drm: The device to alloc the state for135 * @ctx: Locking context for that atomic update136 *137 * Allocates a empty atomic state.138 *139 * The state is tied to the kunit test context, so we must not call140 * drm_atomic_state_put() on it, it will be done so automatically.141 *142 * Returns:143 * An ERR_PTR on error, a pointer to the newly allocated state otherwise144 */145struct drm_atomic_state *146drm_kunit_helper_atomic_state_alloc(struct kunit *test,147				    struct drm_device *drm,148				    struct drm_modeset_acquire_ctx *ctx)149{150	struct drm_atomic_state *state;151	int ret;152 153	state = drm_atomic_state_alloc(drm);154	if (!state)155		return ERR_PTR(-ENOMEM);156 157	ret = kunit_add_action_or_reset(test,158					kunit_action_drm_atomic_state_put,159					state);160	if (ret)161		return ERR_PTR(ret);162 163	state->acquire_ctx = ctx;164 165	return state;166}167EXPORT_SYMBOL_GPL(drm_kunit_helper_atomic_state_alloc);168 169static const uint32_t default_plane_formats[] = {170	DRM_FORMAT_XRGB8888,171};172 173static const uint64_t default_plane_modifiers[] = {174	DRM_FORMAT_MOD_LINEAR,175	DRM_FORMAT_MOD_INVALID176};177 178static const struct drm_plane_helper_funcs default_plane_helper_funcs = {179};180 181static const struct drm_plane_funcs default_plane_funcs = {182	.atomic_destroy_state	= drm_atomic_helper_plane_destroy_state,183	.atomic_duplicate_state	= drm_atomic_helper_plane_duplicate_state,184	.reset			= drm_atomic_helper_plane_reset,185};186 187/**188 * drm_kunit_helper_create_primary_plane - Creates a mock primary plane for a KUnit test189 * @test: The test context object190 * @drm: The device to alloc the plane for191 * @funcs: Callbacks for the new plane. Optional.192 * @helper_funcs: Helpers callbacks for the new plane. Optional.193 * @formats: array of supported formats (DRM_FORMAT\_\*). Optional.194 * @num_formats: number of elements in @formats195 * @modifiers: array of struct drm_format modifiers terminated by196 *             DRM_FORMAT_MOD_INVALID. Optional.197 *198 * This allocates and initializes a mock struct &drm_plane meant to be199 * part of a mock device for a KUnit test.200 *201 * Resources will be cleaned up automatically.202 *203 * @funcs will default to the default helpers implementations.204 * @helper_funcs will default to an empty implementation. @formats will205 * default to XRGB8888 only. @modifiers will default to a linear206 * modifier only.207 *208 * Returns:209 * A pointer to the new plane, or an ERR_PTR() otherwise.210 */211struct drm_plane *212drm_kunit_helper_create_primary_plane(struct kunit *test,213				      struct drm_device *drm,214				      const struct drm_plane_funcs *funcs,215				      const struct drm_plane_helper_funcs *helper_funcs,216				      const uint32_t *formats,217				      unsigned int num_formats,218				      const uint64_t *modifiers)219{220	struct drm_plane *plane;221 222	if (!funcs)223		funcs = &default_plane_funcs;224 225	if (!helper_funcs)226		helper_funcs = &default_plane_helper_funcs;227 228	if (!formats || !num_formats) {229		formats = default_plane_formats;230		num_formats = ARRAY_SIZE(default_plane_formats);231	}232 233	if (!modifiers)234		modifiers = default_plane_modifiers;235 236	plane = __drmm_universal_plane_alloc(drm,237					     sizeof(struct drm_plane), 0,238					     0,239					     funcs,240					     formats,241					     num_formats,242					     default_plane_modifiers,243					     DRM_PLANE_TYPE_PRIMARY,244					     NULL);245	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane);246 247	drm_plane_helper_add(plane, helper_funcs);248 249	return plane;250}251EXPORT_SYMBOL_GPL(drm_kunit_helper_create_primary_plane);252 253static const struct drm_crtc_helper_funcs default_crtc_helper_funcs = {254};255 256static const struct drm_crtc_funcs default_crtc_funcs = {257	.atomic_destroy_state   = drm_atomic_helper_crtc_destroy_state,258	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,259	.reset                  = drm_atomic_helper_crtc_reset,260};261 262/**263 * drm_kunit_helper_create_crtc - Creates a mock CRTC for a KUnit test264 * @test: The test context object265 * @drm: The device to alloc the plane for266 * @primary: Primary plane for CRTC267 * @cursor: Cursor plane for CRTC. Optional.268 * @funcs: Callbacks for the new plane. Optional.269 * @helper_funcs: Helpers callbacks for the new plane. Optional.270 *271 * This allocates and initializes a mock struct &drm_crtc meant to be272 * part of a mock device for a KUnit test.273 *274 * Resources will be cleaned up automatically.275 *276 * @funcs will default to the default helpers implementations.277 * @helper_funcs will default to an empty implementation.278 *279 * Returns:280 * A pointer to the new CRTC, or an ERR_PTR() otherwise.281 */282struct drm_crtc *283drm_kunit_helper_create_crtc(struct kunit *test,284			     struct drm_device *drm,285			     struct drm_plane *primary,286			     struct drm_plane *cursor,287			     const struct drm_crtc_funcs *funcs,288			     const struct drm_crtc_helper_funcs *helper_funcs)289{290	struct drm_crtc *crtc;291	int ret;292 293	if (!funcs)294		funcs = &default_crtc_funcs;295 296	if (!helper_funcs)297		helper_funcs = &default_crtc_helper_funcs;298 299	crtc = drmm_kzalloc(drm, sizeof(*crtc), GFP_KERNEL);300	KUNIT_ASSERT_NOT_NULL(test, crtc);301 302	ret = drmm_crtc_init_with_planes(drm, crtc,303					 primary,304					 cursor,305					 funcs,306					 NULL);307	KUNIT_ASSERT_EQ(test, ret, 0);308 309	drm_crtc_helper_add(crtc, helper_funcs);310 311	return crtc;312}313EXPORT_SYMBOL_GPL(drm_kunit_helper_create_crtc);314 315static void kunit_action_drm_mode_destroy(void *ptr)316{317	struct drm_display_mode *mode = ptr;318 319	drm_mode_destroy(NULL, mode);320}321 322/**323 * drm_kunit_display_mode_from_cea_vic() - return a mode for CEA VIC324					   for a KUnit test325 * @test: The test context object326 * @dev: DRM device327 * @video_code: CEA VIC of the mode328 *329 * Creates a new mode matching the specified CEA VIC for a KUnit test.330 *331 * Resources will be cleaned up automatically.332 *333 * Returns: A new drm_display_mode on success or NULL on failure334 */335struct drm_display_mode *336drm_kunit_display_mode_from_cea_vic(struct kunit *test, struct drm_device *dev,337				    u8 video_code)338{339	struct drm_display_mode *mode;340	int ret;341 342	mode = drm_display_mode_from_cea_vic(dev, video_code);343	if (!mode)344		return NULL;345 346	ret = kunit_add_action_or_reset(test,347					kunit_action_drm_mode_destroy,348					mode);349	if (ret)350		return NULL;351 352	return mode;353}354EXPORT_SYMBOL_GPL(drm_kunit_display_mode_from_cea_vic);355 356MODULE_AUTHOR("Maxime Ripard <maxime@cerno.tech>");357MODULE_DESCRIPTION("KUnit test suite helper functions");358MODULE_LICENSE("GPL");359