1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include <linux/dma-buf.h>
21#include <linux/module.h>
22#include <linux/ramfs.h>
23#include <linux/shmem_fs.h>
24#include "zocl_drv.h"
25#include <drm/drmP.h>
26#include <drm/drm_gem.h>
27#include <linux/zocl_ioctl.h>
28
29#define ZOCL_DRIVER_NAME "zocl"
30#define ZOCL_DRIVER_DESC "Zynq BO manager"
31#define ZOCL_DRIVER_DATE "20161024"
32#define ZOCL_DRIVER_MAJOR 2016
33#define ZOCL_DRIVER_MINOR 3
34#define ZOCL_DRIVER_PATCHLEVEL 1
35#define ZOCL_FILE_PAGE_OFFSET 0x00100000
36
37#ifndef VM_RESERVED
38#define VM_RESERVED (VM_DONTEXPAND | VM_DONTDUMP)
39#endif
40
41static const struct vm_operations_struct reg_physical_vm_ops = {
42#ifdef CONFIG_HAVE_IOREMAP_PROT
43 .access = generic_access_phys,
44#endif
45};
46
47static int zocl_drm_load(struct drm_device *drm, unsigned long flags)
48{
49 struct platform_device *pdev;
50 struct resource *res;
51 struct drm_zocl_dev *zdev;
52 void __iomem *map;
53
54 pdev = to_platform_device(drm->dev);
55 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
56 map = devm_ioremap_resource(&pdev->dev, res);
57 if (IS_ERR(map)) {
58 DRM_ERROR("Failed to map registers: %ld\n", PTR_ERR(map));
59 return PTR_ERR(map);
60 }
61
62 zdev = devm_kzalloc(drm->dev, sizeof(*zdev), GFP_KERNEL);
63 if (!zdev)
64 return -ENOMEM;
65
66 zdev->ddev = drm;
67 drm->dev_private = zdev;
68 zdev->regs = map;
69 zdev->res_start = res->start;
70 zdev->res_len = resource_size(res);
71 platform_set_drvdata(pdev, zdev);
72
73 return 0;
74}
75
76static int zocl_drm_unload(struct drm_device *drm)
77{
78 return 0;
79}
80
81static void zocl_free_object(struct drm_gem_object *obj)
82{
83 struct drm_zocl_bo *zocl_obj = to_zocl_bo(obj);
84
85 DRM_INFO("Freeing BO\n");
86 zocl_describe(zocl_obj);
87 drm_gem_cma_free_object(obj);
88}
89
90static int zocl_mmap(struct file *filp, struct vm_area_struct *vma)
91{
92 struct drm_file *priv = filp->private_data;
93 struct drm_device *dev = priv->minor->dev;
94 struct drm_zocl_dev *zdev = dev->dev_private;
95 unsigned long vsize;
96 int rc;
97
98
99
100
101 if (likely(vma->vm_pgoff >= ZOCL_FILE_PAGE_OFFSET))
102 return drm_gem_cma_mmap(filp, vma);
103
104 if (vma->vm_pgoff != 0)
105 return -EINVAL;
106
107 vsize = vma->vm_end - vma->vm_start;
108 if (vsize > zdev->res_len)
109 return -EINVAL;
110
111 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
112 vma->vm_flags |= VM_IO;
113 vma->vm_flags |= VM_RESERVED;
114
115 vma->vm_ops = ®_physical_vm_ops;
116 rc = io_remap_pfn_range(vma, vma->vm_start,
117 zdev->res_start >> PAGE_SHIFT,
118 vsize, vma->vm_page_prot);
119
120 return rc;
121}
122
123static const struct drm_ioctl_desc zocl_ioctls[] = {
124 DRM_IOCTL_DEF_DRV(ZOCL_CREATE_BO, zocl_create_bo_ioctl,
125 DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
126 DRM_IOCTL_DEF_DRV(ZOCL_MAP_BO, zocl_map_bo_ioctl,
127 DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
128 DRM_IOCTL_DEF_DRV(ZOCL_SYNC_BO, zocl_sync_bo_ioctl,
129 DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
130 DRM_IOCTL_DEF_DRV(ZOCL_INFO_BO, zocl_info_bo_ioctl,
131 DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
132 DRM_IOCTL_DEF_DRV(ZOCL_PWRITE_BO, zocl_pwrite_bo_ioctl,
133 DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
134 DRM_IOCTL_DEF_DRV(ZOCL_PREAD_BO, zocl_pread_bo_ioctl,
135 DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
136};
137
138static const struct file_operations zocl_driver_fops = {
139 .owner = THIS_MODULE,
140 .open = drm_open,
141 .mmap = zocl_mmap,
142 .poll = drm_poll,
143 .read = drm_read,
144 .unlocked_ioctl = drm_ioctl,
145 .release = drm_release,
146};
147
148static struct drm_driver zocl_driver = {
149 .driver_features = DRIVER_GEM | DRIVER_PRIME |
150 DRIVER_RENDER,
151 .load = zocl_drm_load,
152 .unload = zocl_drm_unload,
153 .gem_free_object = zocl_free_object,
154 .gem_vm_ops = &drm_gem_cma_vm_ops,
155 .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
156 .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
157 .gem_prime_import = drm_gem_prime_import,
158 .gem_prime_export = drm_gem_prime_export,
159 .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
160 .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
161 .gem_prime_vmap = drm_gem_cma_prime_vmap,
162 .gem_prime_vunmap = drm_gem_cma_prime_vunmap,
163 .gem_prime_mmap = drm_gem_cma_prime_mmap,
164 .ioctls = zocl_ioctls,
165 .num_ioctls = ARRAY_SIZE(zocl_ioctls),
166 .fops = &zocl_driver_fops,
167 .name = ZOCL_DRIVER_NAME,
168 .desc = ZOCL_DRIVER_DESC,
169 .date = ZOCL_DRIVER_DATE,
170 .major = ZOCL_DRIVER_MAJOR,
171 .minor = ZOCL_DRIVER_MINOR,
172 .patchlevel = ZOCL_DRIVER_PATCHLEVEL,
173};
174
175
176static int zocl_drm_platform_probe(struct platform_device *pdev)
177{
178 return drm_platform_init(&zocl_driver, pdev);
179}
180
181
182static int zocl_drm_platform_remove(struct platform_device *pdev)
183{
184 struct drm_zocl_dev *zdev = platform_get_drvdata(pdev);
185
186 if (zdev->ddev) {
187 drm_dev_unregister(zdev->ddev);
188 drm_dev_unref(zdev->ddev);
189 }
190
191 return 0;
192}
193
194static const struct of_device_id zocl_drm_of_match[] = {
195 { .compatible = "xlnx,zocl", },
196 { },
197};
198MODULE_DEVICE_TABLE(of, zocl_drm_of_match);
199
200static struct platform_driver zocl_drm_private_driver = {
201 .probe = zocl_drm_platform_probe,
202 .remove = zocl_drm_platform_remove,
203 .driver = {
204 .name = "zocl-drm",
205 .of_match_table = zocl_drm_of_match,
206 },
207};
208
209module_platform_driver(zocl_drm_private_driver);
210
211MODULE_VERSION(__stringify(ZOCL_DRIVER_MAJOR) "."
212 __stringify(ZOCL_DRIVER_MINOR) "."
213 __stringify(ZOCL_DRIVER_PATCHLEVEL));
214
215MODULE_DESCRIPTION(ZOCL_DRIVER_DESC);
216MODULE_AUTHOR("Sonal Santan <sonal.santan@xilinx.com>");
217MODULE_LICENSE("GPL");
218