Complete analysis of DRM CRTC of graphic display system

catalogue

  1. Working principle and significance of CRTC
  2. Initialization and function of CRTC module

0. Introduction

CRTC under DRM represents RGB data pipeline from & DRM_ The plane receives the pixel data and mixes them together and transmits them to the lower level display device DRM_ encoder. By & DRM_ display_ Mode controls timing.


KMS through drm_crtc_init_with_planes() register & struct DRM_ CRTC and initialize the CRTC module.

Through drm_crtc_helper_add() registers the functions provided by CRTC, for example, the traditional mode configuration & DRM_ crtc_ funcs.set_ Config, configure the plane configuration, and configure the gamma coefficient.

These configuration methods are not recommended at present, and struct DRM should be used_ crtc_ FuncS to implement the above functions.

1. Working principle and significance of CRTC

CRTC is at the core of DRM structure, which abstracts the timing control part of graph display processor into CRTC. Therefore, SoC manufacturers will develop CRTC codes according to the characteristics of their graphic display processors, including configuration of resolution, depth, polarity, porch, refresh rate, etc.


The DRM in the kernel abstracts the meaning of the CRTC module:

  • Unify and coordinate the control of map display output among FB, DRM and user space code
  • The configuration right of the graphic display mode is recycled to the kernel space to avoid the kernel panic caused by the user space code directly controlling the graphic display controller
  • The graph display output pause and recovery related code implemented in kernel space can easily call the configuration function of graph display controller

On December 29, 2008, Dave Airlie will DRM_ The CRTC. C code was submitted to the kernel version 2.6.28. At that time, the popularity of DRM was not as high as it is now.

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
new file mode 100644
index 0000000000000..2e880240477e3
--- /dev/null
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -0,0 +1,2497 @@

2. Initialization and function of CRTC module

Both plan and CRTC are abstracted from the graph display processor, and plan is relied on when initializing CRTC. Therefore, the common practice is to put the initialization of the two together.

static int mixer_bind(struct device *dev, struct device *manager, void *data)
{
  ...

		ret = exynos_plane_init(drm_dev, &ctx->planes[i], i,
					&plane_configs[i]);
		if (ret)
			return ret;
	}

	exynos_plane = &ctx->planes[DEFAULT_WIN];
	ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
			EXYNOS_DISPLAY_TYPE_HDMI, &mixer_crtc_ops, ctx);
	...
}


CRTC provides data structures for two types of function functions

  • struct drm_crtc_funcs
    It is mainly used to control CRTC
  • struct drm_crtc_helper_funcs
    Intermediate auxiliary code required when configuring CRTC related modules

include/drm/drm_crtc.h

struct drm_crtc_funcs {
	void (*reset)(struct drm_crtc *crtc);
	int (*cursor_set)(struct drm_crtc *crtc, struct drm_file *file_priv,
			  uint32_t handle, uint32_t width, uint32_t height);
	int (*cursor_set2)(struct drm_crtc *crtc, struct drm_file *file_priv,
			   uint32_t handle, uint32_t width, uint32_t height,
			   int32_t hot_x, int32_t hot_y);
	int (*cursor_move)(struct drm_crtc *crtc, int x, int y);
	int (*gamma_set)(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,
			 uint32_t size,
			 struct drm_modeset_acquire_ctx *ctx);
	void (*destroy)(struct drm_crtc *crtc);
	int (*set_config)(struct drm_mode_set *set,
			  struct drm_modeset_acquire_ctx *ctx);
	int (*page_flip)(struct drm_crtc *crtc,
			 struct drm_framebuffer *fb,
			 struct drm_pending_vblank_event *event,
			 uint32_t flags,
			 struct drm_modeset_acquire_ctx *ctx);
	int (*page_flip_target)(struct drm_crtc *crtc,
				struct drm_framebuffer *fb,
				struct drm_pending_vblank_event *event,
				uint32_t flags, uint32_t target,
				struct drm_modeset_acquire_ctx *ctx);
	int (*set_property)(struct drm_crtc *crtc,
			    struct drm_property *property, uint64_t val);
	struct drm_crtc_state *(*atomic_duplicate_state)(struct drm_crtc *crtc);
	void (*atomic_destroy_state)(struct drm_crtc *crtc,
				     struct drm_crtc_state *state);

	int (*atomic_set_property)(struct drm_crtc *crtc,
				   struct drm_crtc_state *state,
				   struct drm_property *property,
				   uint64_t val);
	int (*atomic_get_property)(struct drm_crtc *crtc,
				   const struct drm_crtc_state *state,
				   struct drm_property *property,
				   uint64_t *val);
	int (*late_register)(struct drm_crtc *crtc);
	void (*early_unregister)(struct drm_crtc *crtc);
	int (*set_crc_source)(struct drm_crtc *crtc, const char *source);
	int (*verify_crc_source)(struct drm_crtc *crtc, const char *source,
				 size_t *values_cnt);
	const char *const *(*get_crc_sources)(struct drm_crtc *crtc,
					      size_t *count);
	void (*atomic_print_state)(struct drm_printer *p,
				   const struct drm_crtc_state *state);
	u32 (*get_vblank_counter)(struct drm_crtc *crtc);
	int (*enable_vblank)(struct drm_crtc *crtc);
	void (*disable_vblank)(struct drm_crtc *crtc);
};

include/drm/drm_modeset_helper_vtables.h

struct drm_crtc_helper_funcs {
	void (*dpms)(struct drm_crtc *crtc, int mode);
	void (*prepare)(struct drm_crtc *crtc);
	void (*commit)(struct drm_crtc *crtc);
	enum drm_mode_status (*mode_valid)(struct drm_crtc *crtc,
					   const struct drm_display_mode *mode);
	bool (*mode_fixup)(struct drm_crtc *crtc,
			   const struct drm_display_mode *mode,
			   struct drm_display_mode *adjusted_mode);
	int (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode,
			struct drm_display_mode *adjusted_mode, int x, int y,
			struct drm_framebuffer *old_fb);
	void (*mode_set_nofb)(struct drm_crtc *crtc);
	int (*mode_set_base)(struct drm_crtc *crtc, int x, int y,
			     struct drm_framebuffer *old_fb);
	int (*mode_set_base_atomic)(struct drm_crtc *crtc,
				    struct drm_framebuffer *fb, int x, int y,
				    enum mode_set_atomic);
	void (*disable)(struct drm_crtc *crtc);
	int (*atomic_check)(struct drm_crtc *crtc,
			    struct drm_crtc_state *state);
	void (*atomic_begin)(struct drm_crtc *crtc,
			     struct drm_crtc_state *old_crtc_state);
	void (*atomic_flush)(struct drm_crtc *crtc,
			     struct drm_crtc_state *old_crtc_state);
	void (*atomic_enable)(struct drm_crtc *crtc,
			      struct drm_crtc_state *old_crtc_state);
	void (*atomic_disable)(struct drm_crtc *crtc,
			       struct drm_crtc_state *old_crtc_state);
};

The SoC manufacturer implements the hook function in the above data structure as required, for example:

static const struct drm_crtc_funcs exynos_crtc_funcs = {
	.set_config	= drm_atomic_helper_set_config,
	.page_flip	= drm_atomic_helper_page_flip,
	.destroy	= exynos_drm_crtc_destroy,
	.reset = drm_atomic_helper_crtc_reset,
	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
	.enable_vblank = exynos_drm_crtc_enable_vblank,
	.disable_vblank = exynos_drm_crtc_disable_vblank,
};
static const struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = {
	.mode_valid	= exynos_crtc_mode_valid,
	.mode_fixup	= exynos_crtc_mode_fixup,
	.atomic_check	= exynos_crtc_atomic_check,
	.atomic_begin	= exynos_crtc_atomic_begin,
	.atomic_flush	= exynos_crtc_atomic_flush,
	.atomic_enable	= exynos_drm_crtc_atomic_enable,
	.atomic_disable	= exynos_drm_crtc_atomic_disable,
};

DRM recommends that the function provided by CRTC is based on ATOMIC. This has two benefits:

  • increase of efficiency
    When multiple plans need to update parameters, they can be submitted uniformly after all plan parameters are updated
  • Does not affect display
    If the parameter update fails, the commit operation can be omitted, and the display device outputs the graphic display data according to the original parameters

CRTC mode configuration

static const struct drm_ioctl_desc drm_ioctls[] = {
  ...
  DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER),
  ...
};

In the ubuntu system, simply verify the image display and output based on DRM, and reconfirm what functions CRTC has realized
Command line:

echo 0xf > /sys/module/drm/parameters/debug

./tests/modetest/modetest -M vmwgfx -D 0 -a -s 34@36:1280x960  -P 32@36:1280x960 -Ftiles

dmesg

The output image is as follows:

After canceling the image output, check the log through dmesg, and only the key parts are intercepted, including the functions that CRTC should realize.

[46312.678360] [drm:drm_vblank_enable [drm]] enabling vblank on crtc 0, ret: -22

[46312.728218] [drm:drm_ioctl [drm]] pid=1036, dev=0xe200, auth=1, DRM_IOCTL_MODE_SETCRTC
[46312.728238] [drm:drm_mode_setcrtc [drm]] [CRTC:36:crtc-0]

[46312.728593] [drm:drm_calc_timestamping_constants [drm]] crtc 36: hwmode: htotal 1737, vtotal 1011, vdisplay 861

[46312.729432] [drm:vmw_du_crtc_gamma_set [vmwgfx]] 0 r/g/b = 0x0000 / 0x0000 / 0x0000

[46416.541769] [drm:drm_ioctl [drm]] pid=94191, dev=0xe200, auth=1, DRM_IOCTL_MODE_GETCRTC

Keywords: Linux gpu

Added by aconite on Mon, 13 Sep 2021 05:52:17 +0300