#include <linux/dma-buf.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/shmem_fs.h>
#include <linux/vmalloc.h>
#include <drm/drm_drv.h>
#include <drm/drm_file.h>
#include <drm/drm_gem_shmem_helper.h>
#include <drm/drm_ioctl.h>
#include <drm/drm_managed.h>
#include <drm/drm_prime.h>
#include "vgem_drv.h"
#define DRIVER_NAME "vgem"
#define DRIVER_DESC "Virtual GEM provider"
#define DRIVER_DATE "20120112"
#define DRIVER_MAJOR 1
#define DRIVER_MINOR 0
static struct vgem_device {
struct drm_device drm;
struct platform_device *platform;
} *vgem_device;
static int vgem_open(struct drm_device *dev, struct drm_file *file)
{
struct vgem_file *vfile;
int ret;
vfile = kzalloc(sizeof(*vfile), GFP_KERNEL);
if (!vfile)
return -ENOMEM;
file->driver_priv = vfile;
ret = vgem_fence_open(vfile);
if (ret) {
kfree(vfile);
return ret;
}
return 0;
}
static void vgem_postclose(struct drm_device *dev, struct drm_file *file)
{
struct vgem_file *vfile = file->driver_priv;
vgem_fence_close(vfile);
kfree(vfile);
}
static struct drm_ioctl_desc vgem_ioctls[] = {
DRM_IOCTL_DEF_DRV(VGEM_FENCE_ATTACH, vgem_fence_attach_ioctl, DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(VGEM_FENCE_SIGNAL, vgem_fence_signal_ioctl, DRM_RENDER_ALLOW),
};
DEFINE_DRM_GEM_FOPS(vgem_driver_fops);
static struct drm_gem_object *vgem_gem_create_object(struct drm_device *dev, size_t size)
{
struct drm_gem_shmem_object *obj;
obj = kzalloc(sizeof(*obj), GFP_KERNEL);
if (!obj)
return ERR_PTR(-ENOMEM);
obj->map_wc = true;
return &obj->base;
}
static const struct drm_driver vgem_driver = {
.driver_features = DRIVER_GEM | DRIVER_RENDER,
.open = vgem_open,
.postclose = vgem_postclose,
.ioctls = vgem_ioctls,
.num_ioctls = ARRAY_SIZE(vgem_ioctls),
.fops = &vgem_driver_fops,
DRM_GEM_SHMEM_DRIVER_OPS,
.gem_create_object = vgem_gem_create_object,
.name = DRIVER_NAME,
.desc = DRIVER_DESC,
.date = DRIVER_DATE,
.major = DRIVER_MAJOR,
.minor = DRIVER_MINOR,
};
static int __init vgem_init(void)
{
int ret;
struct platform_device *pdev;
pdev = platform_device_register_simple("vgem", -1, NULL, 0);
if (IS_ERR(pdev))
return PTR_ERR(pdev);
if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL)) {
ret = -ENOMEM;
goto out_unregister;
}
dma_coerce_mask_and_coherent(&pdev->dev,
DMA_BIT_MASK(64));
vgem_device = devm_drm_dev_alloc(&pdev->dev, &vgem_driver,
struct vgem_device, drm);
if (IS_ERR(vgem_device)) {
ret = PTR_ERR(vgem_device);
goto out_devres;
}
vgem_device->platform = pdev;
ret = drm_dev_register(&vgem_device->drm, 0);
if (ret)
goto out_devres;
return 0;
out_devres:
devres_release_group(&pdev->dev, NULL);
out_unregister:
platform_device_unregister(pdev);
return ret;
}
static void __exit vgem_exit(void)
{
struct platform_device *pdev = vgem_device->platform;
drm_dev_unregister(&vgem_device->drm);
devres_release_group(&pdev->dev, NULL);
platform_device_unregister(pdev);
}
module_init(vgem_init);
module_exit(vgem_exit);
MODULE_AUTHOR("Red Hat, Inc.");
MODULE_AUTHOR("Intel Corporation");
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL and additional rights"