中间层

struct drm_driver

底层 driver

xxx_drv.c

首先初始化一个struct drm_driver

DEFINE_DRM_GEM_DMA_FOPS(fops);

static const struct drm_driver mxsfb_driver = {
	.driver_features	= DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
	DRM_GEM_DMA_DRIVER_OPS,
	.fops	= &fops,
	.name	= "mxsfb-drm",
	.desc	= "MXSFB Controller DRM",
	.date	= "20160824",
	.major	= 1,
	.minor	= 0,
};

其中.driver_feature支持的属性有:

enum drm_driver_feature {

	DRIVER_GEM = BIT(0), // GEM 内存管理,一般都需要选上
	DRIVER_MODESET = BIT(1), // KMS, kernel mode setting
	DRIVER_RENDER = BIT(3), // dedicated render node
	DRIVER_ATOMIC = BIT(4), // 支持所有modesetting userspace API。
	DRIVER_SYNCOBJ = BIT(5), // 支持&drm_syncobj,用来主动同步
	DRIVER_SYNCOBJ_TIMELINE = BIT(6),
	DRIVER_COMPUTE_ACCEL = BIT(7), // 支持compute acceleration。和DRIVER_RENDER,DRIVER_MODESET选项互斥,如果同时支持modeset和compute_accel那么就需要实现两个driver。
	DRIVER_GEM_GPUVA = BIT(8), // 支持user定义的GPU VA bindings for GEM objects
	DRIVER_CURSOR_HOTSPOT = BIT(9), // 支持cursor hotspot information
	// 下面这些都是legacy driver的属性
	DRIVER_USE_AGP = BIT(25), // AGP support, 不清楚作用,已不使用
	DRIVER_LEGACY = BIT(26), // 使用shadow attach的legacy driver,已淘汰
	DRIVER_PCI_DMA = BIT(27), // Legacy PCI DMA supprot, 已不使用
	DRIVER_SG = BIT(28), // Legacy scatter/gather DMA support, 已不使用
	DRIVER_HAVE_DMA	= BIT(29), // Legacy DMA support, 已不使用
	DRIVER_HAVE_IRQ	= BIT(30), // Legacy irq support, 已不使用
};

在 driver probe 函数中调用devm_drm_dev_alloc()函数分配struct drm_device空间,drm_dev_alloc()中又会调用drm_dev_init()来进行一系列初始化struct drm_device

static int mxsfb_probe(struct platform_device *pdev)
{
	struct drm_device *drm;

	// 初始化drm_device,填充一些common的成员
	// 用devm_drm_dev_alloc代替
	drm_dev_alloc(&mxsfb_driver, &pdev->dev);

	// device_get_match_data获取of_device_id中对应的.data
	// 底层driver初始化,填充drm_device一些和具体driver相关的成员
	mxsfb_load(drm, device_get_match_data(&pdev->dev));

	// drm_device初始化完成后调用
	drm_dev_register(drm, 0);

	drm_fbdev_dma_setup(drm, 32);
}

static int mxsfb_load(struct drm_device *drm,
		      const struct mxsfb_devdata *devdata)
{
	drmm_mode_config_init(drm);
	mxsfb_kms_init(mxsfb);
	drm_vblank_init(drm, drm->mode_config.num_crtc);

	drm_crtc_vblank_off(&mxsfb->crtc);
	mxsfb_attach_bridge(mxsfb);

	drm_mode_config_reset(drm);
	drm_kms_helper_poll_init(drm);
	drm_helper_hpd_irq_event(drm);
}

xxx_kms.c

int mxsfb_kms_init(struct mxsfb_drm_private *mxsfb)
{
	// 初始化primary plane
	drm_plane_helper_add(&mxsfb->planes.primary,
				&mxsfb_plane_primary_helper_funcs);
	drm_universal_plane_init(mxsfb->drm, &mxsfb->planes.primary, 1,
				       &mxsfb_plane_funcs,
				       mxsfb_primary_plane_formats,
				       ARRAY_SIZE(mxsfb_primary_plane_formats),
				       mxsfb_modifiers, DRM_PLANE_TYPE_PRIMARY,
				       NULL);
	// 初始化overlay plane
	...

	//
}