diff options
Diffstat (limited to 'drivers/gpu/pvr/services4/srvkm/env/linux/pvr_drm.c')
-rw-r--r-- | drivers/gpu/pvr/services4/srvkm/env/linux/pvr_drm.c | 808 |
1 files changed, 808 insertions, 0 deletions
diff --git a/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_drm.c b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_drm.c new file mode 100644 index 000000000000..9e6b92c39954 --- /dev/null +++ b/drivers/gpu/pvr/services4/srvkm/env/linux/pvr_drm.c | |||
@@ -0,0 +1,808 @@ | |||
1 | /*************************************************************************/ /*! | ||
2 | @Title PowerVR drm driver | ||
3 | @Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved | ||
4 | @Description linux module setup | ||
5 | @License Dual MIT/GPLv2 | ||
6 | |||
7 | The contents of this file are subject to the MIT license as set out below. | ||
8 | |||
9 | Permission is hereby granted, free of charge, to any person obtaining a copy | ||
10 | of this software and associated documentation files (the "Software"), to deal | ||
11 | in the Software without restriction, including without limitation the rights | ||
12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
13 | copies of the Software, and to permit persons to whom the Software is | ||
14 | furnished to do so, subject to the following conditions: | ||
15 | |||
16 | The above copyright notice and this permission notice shall be included in | ||
17 | all copies or substantial portions of the Software. | ||
18 | |||
19 | Alternatively, the contents of this file may be used under the terms of | ||
20 | the GNU General Public License Version 2 ("GPL") in which case the provisions | ||
21 | of GPL are applicable instead of those above. | ||
22 | |||
23 | If you wish to allow use of your version of this file only under the terms of | ||
24 | GPL, and not to allow others to use your version of this file under the terms | ||
25 | of the MIT license, indicate your decision by deleting the provisions above | ||
26 | and replace them with the notice and other provisions required by GPL as set | ||
27 | out in the file called "GPL-COPYING" included in this distribution. If you do | ||
28 | not delete the provisions above, a recipient may use your version of this file | ||
29 | under the terms of either the MIT license or GPL. | ||
30 | |||
31 | This License is also included in this distribution in the file called | ||
32 | "MIT-COPYING". | ||
33 | |||
34 | EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS | ||
35 | PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING | ||
36 | BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR | ||
37 | PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR | ||
38 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | ||
39 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
40 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
41 | */ /**************************************************************************/ | ||
42 | #if defined(SUPPORT_DRI_DRM) | ||
43 | |||
44 | #include <linux/version.h> | ||
45 | |||
46 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)) | ||
47 | #ifndef AUTOCONF_INCLUDED | ||
48 | #include <linux/config.h> | ||
49 | #endif | ||
50 | #endif | ||
51 | |||
52 | #include <linux/init.h> | ||
53 | #include <linux/kernel.h> | ||
54 | #include <linux/module.h> | ||
55 | #include <linux/fs.h> | ||
56 | #include <linux/proc_fs.h> | ||
57 | #include <linux/sched.h> | ||
58 | #include <asm/ioctl.h> | ||
59 | #include <drm/drmP.h> | ||
60 | #include <drm/drm.h> | ||
61 | |||
62 | #include "img_defs.h" | ||
63 | #include "services.h" | ||
64 | #include "kerneldisplay.h" | ||
65 | #include "kernelbuffer.h" | ||
66 | #include "syscommon.h" | ||
67 | #include "pvrmmap.h" | ||
68 | #include "mm.h" | ||
69 | #include "mmap.h" | ||
70 | #include "mutex.h" | ||
71 | #include "pvr_debug.h" | ||
72 | #include "srvkm.h" | ||
73 | #include "perproc.h" | ||
74 | #include "handle.h" | ||
75 | #include "pvr_bridge_km.h" | ||
76 | #include "pvr_bridge.h" | ||
77 | #include "pvrmodule.h" | ||
78 | #include "pvrversion.h" | ||
79 | #include "lock.h" | ||
80 | #include "linkage.h" | ||
81 | #include "pvr_drm.h" | ||
82 | |||
83 | #if defined(PVR_DRI_DRM_NOT_PCI) | ||
84 | #include "pvr_drm_mod.h" | ||
85 | #endif | ||
86 | |||
87 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0)) | ||
88 | #define DRM_ARRAY_SIZE(x) ARRAY_SIZE(x) | ||
89 | #endif | ||
90 | |||
91 | #if (defined(PVR_LDM_PLATFORM_PRE_REGISTERED) || defined(PVR_LDM_DEVICE_TREE)) && !defined(NO_HARDWARE) | ||
92 | #define PVR_USE_PRE_REGISTERED_PLATFORM_DEV | ||
93 | #endif | ||
94 | |||
95 | #if defined(PVR_LDM_DEVICE_TREE) && !defined(NO_HARDWARE) | ||
96 | #define PVR_USE_DEVICE_TREE | ||
97 | #endif | ||
98 | |||
99 | #if (defined(PVR_DRI_DRM_PLATFORM_DEV) && !defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV)) || defined(NO_HARDWARE) | ||
100 | #define PVR_DRM_NAME SYS_SGX_DEV_NAME | ||
101 | #else | ||
102 | #define PVR_DRM_NAME PVRSRV_MODNAME | ||
103 | #endif | ||
104 | |||
105 | #define PVR_DRM_DESC "Imagination Technologies PVR DRM" | ||
106 | |||
107 | #define PVR_DRM_DATE "20110701" | ||
108 | |||
109 | #if defined(PVR_DRI_DRM_PLATFORM_DEV) && !defined(SUPPORT_DRI_DRM_PLUGIN) | ||
110 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)) | ||
111 | #define PVR_NEW_STYLE_DRM_PLATFORM_DEV | ||
112 | #else | ||
113 | #define PVR_OLD_STYLE_DRM_PLATFORM_DEV | ||
114 | #endif | ||
115 | #endif | ||
116 | |||
117 | /* | ||
118 | * Prior to Linux 2.6.36, we couldn't do the release processing in post close | ||
119 | * when workqueues were being used, because drm_release held the big kernel | ||
120 | * lock (BKL) when it called post close. | ||
121 | * If the resman needs to wait for processing being done by a workqueue, | ||
122 | * that processing won't complete whilst the lock is held by another thread, | ||
123 | * as the workqueue won't get scheduled. | ||
124 | */ | ||
125 | #undef PVR_DRI_DRM_USE_POST_CLOSE | ||
126 | #if (defined(SUPPORT_DRI_DRM_EXT) && !defined(PVR_LINUX_USING_WORKQUEUES)) || \ | ||
127 | (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)) | ||
128 | #define PVR_DRI_DRM_USE_POST_CLOSE | ||
129 | #endif | ||
130 | |||
131 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,12,0)) | ||
132 | #define PVR_DRM_DRIVER_RENDER DRIVER_RENDER | ||
133 | #define PVR_DRM_RENDER_ALLOW DRM_RENDER_ALLOW | ||
134 | #else | ||
135 | #define PVR_DRM_DRIVER_RENDER 0 | ||
136 | #define PVR_DRM_RENDER_ALLOW 0 | ||
137 | #endif | ||
138 | |||
139 | DECLARE_WAIT_QUEUE_HEAD(sWaitForInit); | ||
140 | |||
141 | #if defined(SUPPORT_DRM_MODESET) | ||
142 | static struct drm_driver sPVRDrmDriver; | ||
143 | #endif | ||
144 | |||
145 | /* Once bInitComplete and bInitFailed are set, they stay set */ | ||
146 | IMG_BOOL bInitComplete; | ||
147 | IMG_BOOL bInitFailed; | ||
148 | |||
149 | #if !defined(PVR_DRI_DRM_NOT_PCI) && !defined(SUPPORT_DRI_DRM_PLUGIN) | ||
150 | #if defined(PVR_DRI_DRM_PLATFORM_DEV) | ||
151 | #if defined(PVR_NEW_STYLE_DRM_PLATFORM_DEV) && !defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV) | ||
152 | static struct platform_device *psPlatDev; | ||
153 | #endif | ||
154 | struct platform_device *gpsPVRLDMDev; | ||
155 | #else | ||
156 | struct pci_dev *gpsPVRLDMDev; | ||
157 | #endif | ||
158 | #endif | ||
159 | |||
160 | struct drm_device *gpsPVRDRMDev; | ||
161 | |||
162 | #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,24)) | ||
163 | #error "Linux kernel version 2.6.25 or later required for PVR DRM support" | ||
164 | #endif | ||
165 | |||
166 | #define PVR_DRM_FILE struct drm_file * | ||
167 | |||
168 | #if !defined(SUPPORT_DRI_DRM_EXT) && !defined(SUPPORT_DRI_DRM_PLUGIN) | ||
169 | #if defined(PVR_USE_DEVICE_TREE) | ||
170 | static struct of_device_id asPlatIdList[] = { | ||
171 | { | ||
172 | .compatible = SYS_SGX_DEV_NAME | ||
173 | }, | ||
174 | {} | ||
175 | }; | ||
176 | MODULE_DEVICE_TABLE(of, asPlatIdList); | ||
177 | #else | ||
178 | #if defined(PVR_DRI_DRM_PLATFORM_DEV) | ||
179 | static struct platform_device_id asPlatIdList[] = { | ||
180 | {SYS_SGX_DEV_NAME, 0}, | ||
181 | {} | ||
182 | }; | ||
183 | #else /* defined(PVR_DRI_DRM_PLATFORM_DEV) */ | ||
184 | static struct pci_device_id asPciIdList[] = { | ||
185 | #if defined(PVR_DRI_DRM_NOT_PCI) | ||
186 | {1, 1, 1, 1, 0, 0, 0}, | ||
187 | #else /* defined(PVR_DRI_DRM_NOT_PCI) */ | ||
188 | {SYS_SGX_DEV_VENDOR_ID, SYS_SGX_DEV_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | ||
189 | #if defined(SYS_SGX_DEV1_DEVICE_ID) | ||
190 | {SYS_SGX_DEV_VENDOR_ID, SYS_SGX_DEV1_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | ||
191 | #endif /* defined(SYS_SGX_DEV1_DEVICE_ID) */ | ||
192 | #endif /* defined(PVR_DRI_DRM_NOT_PCI) */ | ||
193 | {0} | ||
194 | }; | ||
195 | #endif /* defined(PVR_DRI_DRM_PLATFORM_DEV) */ | ||
196 | #endif /* defined(PVR_DEVICE_TREE) */ | ||
197 | #endif /* !defined(SUPPORT_DRI_DRM_EXT) */ | ||
198 | |||
199 | struct device * | ||
200 | PVRLDMGetDevice(void) | ||
201 | { | ||
202 | return gpsPVRDRMDev->dev; | ||
203 | } | ||
204 | |||
205 | DRI_DRM_STATIC int | ||
206 | PVRSRVDrmLoad(struct drm_device *dev, unsigned long flags) | ||
207 | { | ||
208 | int iRes = 0; | ||
209 | |||
210 | PVR_TRACE(("PVRSRVDrmLoad")); | ||
211 | |||
212 | gpsPVRDRMDev = dev; | ||
213 | #if !defined(PVR_DRI_DRM_NOT_PCI) && !defined(SUPPORT_DRI_DRM_PLUGIN) | ||
214 | #if defined(PVR_DRI_DRM_PLATFORM_DEV) | ||
215 | gpsPVRLDMDev = dev->platformdev; | ||
216 | #else | ||
217 | gpsPVRLDMDev = dev->pdev; | ||
218 | #endif | ||
219 | #endif | ||
220 | |||
221 | #if defined(PDUMP) | ||
222 | iRes = dbgdrv_init(); | ||
223 | if (iRes != 0) | ||
224 | { | ||
225 | goto exit; | ||
226 | } | ||
227 | #endif | ||
228 | /* Module initialisation */ | ||
229 | iRes = PVRCore_Init(); | ||
230 | if (iRes != 0) | ||
231 | { | ||
232 | goto exit_dbgdrv_cleanup; | ||
233 | } | ||
234 | |||
235 | #if defined(DISPLAY_CONTROLLER) | ||
236 | iRes = PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Init)(dev); | ||
237 | if (iRes != 0) | ||
238 | { | ||
239 | goto exit_pvrcore_cleanup; | ||
240 | } | ||
241 | #endif | ||
242 | goto exit; | ||
243 | |||
244 | #if defined(DISPLAY_CONTROLLER) | ||
245 | exit_pvrcore_cleanup: | ||
246 | PVRCore_Cleanup(); | ||
247 | #endif | ||
248 | exit_dbgdrv_cleanup: | ||
249 | #if defined(PDUMP) | ||
250 | dbgdrv_cleanup(); | ||
251 | #endif | ||
252 | exit: | ||
253 | if (iRes != 0) | ||
254 | { | ||
255 | bInitFailed = IMG_TRUE; | ||
256 | } | ||
257 | bInitComplete = IMG_TRUE; | ||
258 | |||
259 | wake_up_interruptible(&sWaitForInit); | ||
260 | |||
261 | return iRes; | ||
262 | } | ||
263 | |||
264 | DRI_DRM_STATIC int | ||
265 | PVRSRVDrmUnload(struct drm_device *dev) | ||
266 | { | ||
267 | PVR_TRACE(("PVRSRVDrmUnload")); | ||
268 | |||
269 | #if defined(DISPLAY_CONTROLLER) | ||
270 | PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Cleanup)(dev); | ||
271 | #endif | ||
272 | |||
273 | PVRCore_Cleanup(); | ||
274 | |||
275 | #if defined(PDUMP) | ||
276 | dbgdrv_cleanup(); | ||
277 | #endif | ||
278 | |||
279 | return 0; | ||
280 | } | ||
281 | |||
282 | DRI_DRM_STATIC int | ||
283 | PVRSRVDrmOpen(struct drm_device *dev, struct drm_file *file) | ||
284 | { | ||
285 | while (!bInitComplete) | ||
286 | { | ||
287 | DEFINE_WAIT(sWait); | ||
288 | |||
289 | prepare_to_wait(&sWaitForInit, &sWait, TASK_INTERRUPTIBLE); | ||
290 | |||
291 | if (!bInitComplete) | ||
292 | { | ||
293 | PVR_TRACE(("%s: Waiting for module initialisation to complete", __FUNCTION__)); | ||
294 | |||
295 | schedule(); | ||
296 | } | ||
297 | |||
298 | finish_wait(&sWaitForInit, &sWait); | ||
299 | |||
300 | if (signal_pending(current)) | ||
301 | { | ||
302 | return -ERESTARTSYS; | ||
303 | } | ||
304 | } | ||
305 | |||
306 | if (bInitFailed) | ||
307 | { | ||
308 | PVR_DPF((PVR_DBG_ERROR, "%s: Module initialisation failed", __FUNCTION__)); | ||
309 | return -EINVAL; | ||
310 | } | ||
311 | |||
312 | return PVRSRVOpen(dev, file); | ||
313 | } | ||
314 | |||
315 | #if defined(PVR_DRI_DRM_USE_POST_CLOSE) || defined(SUPPORT_DRI_DRM_PLUGIN) | ||
316 | #if defined(SUPPORT_DRI_DRM_PLUGIN) | ||
317 | DRI_DRM_STATIC int | ||
318 | PVRSRVDrmRelease(struct drm_device *dev, struct drm_file *file) | ||
319 | #else | ||
320 | DRI_DRM_STATIC void | ||
321 | PVRSRVDrmPostClose(struct drm_device *dev, struct drm_file *file) | ||
322 | #endif | ||
323 | { | ||
324 | PVRSRVRelease(file->driver_priv); | ||
325 | |||
326 | file->driver_priv = NULL; | ||
327 | |||
328 | #if defined(SUPPORT_DRI_DRM_PLUGIN) | ||
329 | return 0; | ||
330 | #endif | ||
331 | } | ||
332 | #else | ||
333 | DRI_DRM_STATIC int | ||
334 | PVRSRVDrmRelease(struct inode *inode, struct file *filp) | ||
335 | { | ||
336 | struct drm_file *file_priv = filp->private_data; | ||
337 | void *psDriverPriv = file_priv->driver_priv; | ||
338 | int ret; | ||
339 | |||
340 | ret = drm_release(inode, filp); | ||
341 | |||
342 | if (ret != 0) | ||
343 | { | ||
344 | /* | ||
345 | * An error means drm_release didn't call drm_lastclose, | ||
346 | * but it will have freed file_priv. | ||
347 | */ | ||
348 | PVR_DPF((PVR_DBG_ERROR, "%s : drm_release failed: %d", | ||
349 | __FUNCTION__, ret)); | ||
350 | } | ||
351 | |||
352 | PVRSRVRelease(psDriverPriv); | ||
353 | |||
354 | return 0; | ||
355 | } | ||
356 | #endif | ||
357 | |||
358 | DRI_DRM_STATIC int | ||
359 | PVRDRMIsMaster(struct drm_device *dev, void *arg, struct drm_file *pFile) | ||
360 | { | ||
361 | return 0; | ||
362 | } | ||
363 | |||
364 | #if defined(SUPPORT_DRI_DRM_EXT) | ||
365 | int | ||
366 | PVRDRM_Dummy_ioctl(struct drm_device *dev, void *arg, struct drm_file *pFile) | ||
367 | { | ||
368 | return 0; | ||
369 | } | ||
370 | #endif | ||
371 | |||
372 | DRI_DRM_STATIC int | ||
373 | PVRDRMUnprivCmd(struct drm_device *dev, void *arg, struct drm_file *pFile) | ||
374 | { | ||
375 | int ret = 0; | ||
376 | |||
377 | LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE); | ||
378 | |||
379 | if (arg == NULL) | ||
380 | { | ||
381 | ret = -EFAULT; | ||
382 | } | ||
383 | else | ||
384 | { | ||
385 | drm_pvr_unpriv_cmd *psArgs = (drm_pvr_unpriv_cmd *)arg; | ||
386 | |||
387 | switch (psArgs->cmd) | ||
388 | { | ||
389 | case PVR_DRM_UNPRIV_INIT_SUCCESFUL: | ||
390 | psArgs->res = PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL) ? 1 : 0; | ||
391 | break; | ||
392 | |||
393 | default: | ||
394 | ret = -EFAULT; | ||
395 | } | ||
396 | |||
397 | } | ||
398 | |||
399 | LinuxUnLockMutex(&gPVRSRVLock); | ||
400 | |||
401 | return ret; | ||
402 | } | ||
403 | |||
404 | #if defined(DISPLAY_CONTROLLER) && defined(PVR_DISPLAY_CONTROLLER_DRM_IOCTL) | ||
405 | static int | ||
406 | PVRDRM_Display_ioctl(struct drm_device *dev, void *arg, struct drm_file *pFile) | ||
407 | { | ||
408 | int res; | ||
409 | |||
410 | LinuxLockMutexNested(&gPVRSRVLock, PVRSRV_LOCK_CLASS_BRIDGE); | ||
411 | |||
412 | res = PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Ioctl)(dev, arg, pFile); | ||
413 | |||
414 | LinuxUnLockMutex(&gPVRSRVLock); | ||
415 | |||
416 | return res; | ||
417 | } | ||
418 | #endif | ||
419 | |||
420 | #if defined(SUPPORT_DRM_MODESET) | ||
421 | static int | ||
422 | PVRSRVPciProbe(struct pci_dev *dev, const struct pci_device_id *id) | ||
423 | { | ||
424 | PVR_TRACE(("PVRSRVPciProbe")); | ||
425 | |||
426 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)) | ||
427 | return drm_get_pci_dev(dev, id, &sPVRDrmDriver); | ||
428 | #else | ||
429 | return drm_get_dev(dev, id, &sPVRDrmDriver); | ||
430 | #endif | ||
431 | } | ||
432 | |||
433 | static void | ||
434 | PVRSRVPciRemove(struct pci_dev *dev) | ||
435 | { | ||
436 | struct drm_device *psDrmDev; | ||
437 | |||
438 | PVR_TRACE(("PVRSRVPciRemove")); | ||
439 | |||
440 | psDrmDev = pci_get_drvdata(dev); | ||
441 | drm_put_dev(psDrmDev); | ||
442 | } | ||
443 | #endif | ||
444 | |||
445 | /* | ||
446 | * For Linux 2.6.33 and above, the DRM ioctl entry point is of the unlocked | ||
447 | * variety. The big kernel lock is still taken for ioctls, unless | ||
448 | * the DRM_UNLOCKED flag is set. If you revise one of the driver specific | ||
449 | * ioctls, or add a new one, consider whether the gPVRSRVLock mutex needs | ||
450 | * to be taken. | ||
451 | */ | ||
452 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33)) | ||
453 | #define PVR_DRM_FOPS_IOCTL .unlocked_ioctl | ||
454 | #define PVR_DRM_UNLOCKED DRM_UNLOCKED | ||
455 | #else | ||
456 | #define PVR_DRM_FOPS_IOCTL .ioctl | ||
457 | #define PVR_DRM_UNLOCKED 0 | ||
458 | #endif | ||
459 | |||
460 | #if !defined(DRM_IOCTL_DEF_DRV) | ||
461 | #define DRM_IOCTL_DEF_DRV(ioctl, _func, _flags) DRM_IOCTL_DEF(DRM_##ioctl, _func, _flags) | ||
462 | #endif | ||
463 | |||
464 | #if !defined(SUPPORT_DRI_DRM_EXT) | ||
465 | struct drm_ioctl_desc sPVRDrmIoctls[] = { | ||
466 | DRM_IOCTL_DEF_DRV(PVR_SRVKM, PVRSRV_BridgeDispatchKM, PVR_DRM_RENDER_ALLOW | PVR_DRM_UNLOCKED), | ||
467 | DRM_IOCTL_DEF_DRV(PVR_IS_MASTER, PVRDRMIsMaster, PVR_DRM_RENDER_ALLOW | DRM_MASTER | PVR_DRM_UNLOCKED), | ||
468 | DRM_IOCTL_DEF_DRV(PVR_UNPRIV, PVRDRMUnprivCmd, PVR_DRM_RENDER_ALLOW | PVR_DRM_UNLOCKED), | ||
469 | #if defined(PDUMP) | ||
470 | DRM_IOCTL_DEF_DRV(PVR_DBGDRV, dbgdrv_ioctl, PVR_DRM_RENDER_ALLOW | PVR_DRM_UNLOCKED), | ||
471 | #endif | ||
472 | #if defined(DISPLAY_CONTROLLER) && defined(PVR_DISPLAY_CONTROLLER_DRM_IOCTL) | ||
473 | DRM_IOCTL_DEF_DRV(PVR_DISP, PVRDRM_Display_ioctl, DRM_MASTER | PVR_DRM_UNLOCKED) | ||
474 | #endif | ||
475 | }; | ||
476 | |||
477 | #if !defined(SUPPORT_DRI_DRM_PLUGIN) | ||
478 | static int pvr_max_ioctl = DRM_ARRAY_SIZE(sPVRDrmIoctls); | ||
479 | #endif | ||
480 | |||
481 | #if defined(PVR_DRI_DRM_PLATFORM_DEV) && !defined(SUPPORT_DRI_DRM_EXT) && \ | ||
482 | !defined(SUPPORT_DRI_DRM_PLUGIN) | ||
483 | static int PVRSRVDrmProbe(struct platform_device *pDevice); | ||
484 | static int PVRSRVDrmRemove(struct platform_device *pDevice); | ||
485 | #endif /* defined(PVR_DRI_DRM_PLATFORM_DEV) && !defined(SUPPORT_DRI_DRM_EXT) */ | ||
486 | |||
487 | #if defined(SUPPORT_DRI_DRM_PLUGIN) | ||
488 | static PVRSRV_DRM_PLUGIN sPVRDrmPlugin = | ||
489 | { | ||
490 | .name = PVR_DRM_NAME, | ||
491 | |||
492 | .open = PVRSRVDrmOpen, | ||
493 | .load = PVRSRVDrmLoad, | ||
494 | .unload = PVRSRVDrmUnload, | ||
495 | |||
496 | .release = PVRSRVDrmRelease, | ||
497 | |||
498 | .mmap = PVRMMap, | ||
499 | |||
500 | .ioctls = sPVRDrmIoctls, | ||
501 | .num_ioctls = DRM_ARRAY_SIZE(sPVRDrmIoctls), | ||
502 | .ioctl_start = 0 | ||
503 | }; | ||
504 | #else /* defined(SUPPORT_DRI_DRM_PLUGIN) */ | ||
505 | |||
506 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)) | ||
507 | #if defined(CONFIG_COMPAT) | ||
508 | static long pvr_compat_ioctl(struct file *file, unsigned int cmd, | ||
509 | unsigned long arg) | ||
510 | { | ||
511 | unsigned int nr = DRM_IOCTL_NR(cmd); | ||
512 | |||
513 | if (nr < DRM_COMMAND_BASE) | ||
514 | { | ||
515 | return drm_compat_ioctl(file, cmd, arg); | ||
516 | } | ||
517 | |||
518 | return drm_ioctl(file, cmd, arg); | ||
519 | } | ||
520 | #endif /* defined(CONFIG_COMPAT) */ | ||
521 | |||
522 | static const struct file_operations sPVRFileOps = | ||
523 | { | ||
524 | .owner = THIS_MODULE, | ||
525 | .open = drm_open, | ||
526 | #if defined(PVR_DRI_DRM_USE_POST_CLOSE) | ||
527 | .release = drm_release, | ||
528 | #else | ||
529 | .release = PVRSRVDrmRelease, | ||
530 | #endif | ||
531 | PVR_DRM_FOPS_IOCTL = drm_ioctl, | ||
532 | #if defined(CONFIG_COMPAT) | ||
533 | .compat_ioctl = pvr_compat_ioctl, | ||
534 | #endif | ||
535 | .mmap = PVRMMap, | ||
536 | .poll = drm_poll, | ||
537 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,12,0)) | ||
538 | .fasync = drm_fasync, | ||
539 | #endif | ||
540 | }; | ||
541 | #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)) */ | ||
542 | |||
543 | static struct drm_driver sPVRDrmDriver = | ||
544 | { | ||
545 | .driver_features = PVR_DRM_DRIVER_RENDER | ||
546 | #if defined(PVR_OLD_STYLE_DRM_PLATFORM_DEV) | ||
547 | | DRIVER_USE_PLATFORM_DEVICE | ||
548 | #endif | ||
549 | , | ||
550 | .dev_priv_size = 0, | ||
551 | .load = PVRSRVDrmLoad, | ||
552 | .unload = PVRSRVDrmUnload, | ||
553 | .open = PVRSRVDrmOpen, | ||
554 | #if defined(PVR_DRI_DRM_USE_POST_CLOSE) | ||
555 | .postclose = PVRSRVDrmPostClose, | ||
556 | #endif | ||
557 | #if !defined(PVR_DRI_DRM_PLATFORM_DEV) && !defined(SUPPORT_DRM_MODESET) | ||
558 | .suspend = PVRSRVDriverSuspend, | ||
559 | .resume = PVRSRVDriverResume, | ||
560 | #endif | ||
561 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)) | ||
562 | .get_map_ofs = drm_core_get_map_ofs, | ||
563 | .get_reg_ofs = drm_core_get_reg_ofs, | ||
564 | #endif | ||
565 | .ioctls = sPVRDrmIoctls, | ||
566 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)) | ||
567 | .fops = &sPVRFileOps, | ||
568 | #else | ||
569 | .fops = | ||
570 | { | ||
571 | .owner = THIS_MODULE, | ||
572 | .open = drm_open, | ||
573 | #if defined(PVR_DRI_DRM_USE_POST_CLOSE) | ||
574 | .release = drm_release, | ||
575 | #else | ||
576 | .release = PVRSRVDrmRelease, | ||
577 | #endif | ||
578 | PVR_DRM_FOPS_IOCTL = drm_ioctl, | ||
579 | .mmap = PVRMMap, | ||
580 | .poll = drm_poll, | ||
581 | .fasync = drm_fasync, | ||
582 | }, | ||
583 | #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)) */ | ||
584 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39)) | ||
585 | #if defined(PVR_OLD_STYLE_DRM_PLATFORM_DEV) | ||
586 | .platform_driver = | ||
587 | { | ||
588 | .id_table = asPlatIdList, | ||
589 | .driver = | ||
590 | { | ||
591 | .name = PVR_DRM_NAME, | ||
592 | }, | ||
593 | .probe = PVRSRVDrmProbe, | ||
594 | .remove = PVRSRVDrmRemove, | ||
595 | .suspend = PVRSRVDriverSuspend, | ||
596 | .resume = PVRSRVDriverResume, | ||
597 | .shutdown = PVRSRVDriverShutdown, | ||
598 | }, | ||
599 | #else | ||
600 | .pci_driver = | ||
601 | { | ||
602 | .name = PVR_DRM_NAME, | ||
603 | .id_table = asPciIdList, | ||
604 | #if defined(SUPPORT_DRM_MODESET) | ||
605 | .probe = PVRSRVPciProbe, | ||
606 | .remove = PVRSRVPciRemove, | ||
607 | .suspend = PVRSRVDriverSuspend, | ||
608 | .resume = PVRSRVDriverResume, | ||
609 | #endif | ||
610 | }, | ||
611 | #endif | ||
612 | #endif | ||
613 | |||
614 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(4,5,0)) | ||
615 | #if defined(LDM_PLATFORM) | ||
616 | .set_busid = drm_platform_set_busid, | ||
617 | #else | ||
618 | #if defined(LDM_PCI) | ||
619 | .set_busid = drm_pci_set_busid, | ||
620 | #else | ||
621 | #error "LDM_PLATFORM or LDM_PCI must be set" | ||
622 | #endif | ||
623 | #endif | ||
624 | #endif | ||
625 | .name = "pvr", | ||
626 | .desc = PVR_DRM_DESC, | ||
627 | .date = PVR_DRM_DATE, | ||
628 | .major = PVRVERSION_MAJ, | ||
629 | .minor = PVRVERSION_MIN, | ||
630 | .patchlevel = PVRVERSION_BUILD, | ||
631 | }; | ||
632 | |||
633 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)) && !defined(PVR_DRI_DRM_PLATFORM_DEV) | ||
634 | static struct pci_driver sPVRPCIDriver = | ||
635 | { | ||
636 | .name = PVR_DRM_NAME, | ||
637 | .id_table = asPciIdList, | ||
638 | #if defined(SUPPORT_DRM_MODESET) | ||
639 | .probe = PVRSRVPciProbe, | ||
640 | .remove = PVRSRVPciRemove, | ||
641 | .suspend = PVRSRVDriverSuspend, | ||
642 | .resume = PVRSRVDriverResume, | ||
643 | #endif | ||
644 | }; | ||
645 | #endif | ||
646 | |||
647 | #if defined(PVR_NEW_STYLE_DRM_PLATFORM_DEV) | ||
648 | #if !defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV) | ||
649 | static struct platform_device_info sPVRPlatDeviceInfo = { | ||
650 | .name = PVR_DRM_NAME, | ||
651 | .id = -1, | ||
652 | .dma_mask = DMA_BIT_MASK(32) | ||
653 | }; | ||
654 | #endif | ||
655 | |||
656 | static struct platform_driver sPVRPlatDriver = | ||
657 | { | ||
658 | #if !defined(PVR_USE_DEVICE_TREE) | ||
659 | .id_table = asPlatIdList, | ||
660 | #endif | ||
661 | .driver = | ||
662 | { | ||
663 | .name = PVR_DRM_NAME, | ||
664 | #if defined(PVR_USE_DEVICE_TREE) | ||
665 | .of_match_table = asPlatIdList, | ||
666 | #endif | ||
667 | }, | ||
668 | .probe = PVRSRVDrmProbe, | ||
669 | .remove = PVRSRVDrmRemove, | ||
670 | .suspend = PVRSRVDriverSuspend, | ||
671 | .resume = PVRSRVDriverResume, | ||
672 | .shutdown = PVRSRVDriverShutdown, | ||
673 | }; | ||
674 | #endif | ||
675 | |||
676 | #endif /* defined(SUPPORT_DRI_DRM_PLUGIN) */ | ||
677 | |||
678 | #if defined(PVR_DRI_DRM_PLATFORM_DEV) && !defined(SUPPORT_DRI_DRM_EXT) && \ | ||
679 | !defined(SUPPORT_DRI_DRM_PLUGIN) | ||
680 | static int | ||
681 | PVRSRVDrmProbe(struct platform_device *pDevice) | ||
682 | { | ||
683 | PVR_TRACE(("PVRSRVDrmProbe")); | ||
684 | |||
685 | #if defined(PVR_NEW_STYLE_DRM_PLATFORM_DEV) | ||
686 | gpsPVRLDMDev = pDevice; | ||
687 | |||
688 | return drm_platform_init(&sPVRDrmDriver, gpsPVRLDMDev); | ||
689 | #else | ||
690 | return drm_get_platform_dev(pDevice, &sPVRDrmDriver); | ||
691 | #endif | ||
692 | } | ||
693 | |||
694 | static int | ||
695 | PVRSRVDrmRemove(struct platform_device *pDevice) | ||
696 | { | ||
697 | PVR_TRACE(("PVRSRVDrmRemove")); | ||
698 | |||
699 | #if defined(PVR_NEW_STYLE_DRM_PLATFORM_DEV) && (LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0)) | ||
700 | drm_platform_exit(&sPVRDrmDriver, gpsPVRLDMDev); | ||
701 | #else | ||
702 | drm_put_dev(gpsPVRDRMDev); | ||
703 | #endif | ||
704 | return 0; | ||
705 | } | ||
706 | #endif | ||
707 | |||
708 | static int __init PVRSRVDrmInit(void) | ||
709 | { | ||
710 | int iRes; | ||
711 | #if !defined(SUPPORT_DRI_DRM_PLUGIN) | ||
712 | sPVRDrmDriver.num_ioctls = pvr_max_ioctl; | ||
713 | #endif | ||
714 | |||
715 | #if defined(SUPPORT_DRM_MODESET) | ||
716 | sPVRDrmDriver.driver_features |= DRIVER_MODESET; | ||
717 | #endif | ||
718 | |||
719 | /* Must come before attempting to print anything via Services */ | ||
720 | PVRDPFInit(); | ||
721 | |||
722 | #if defined(PVR_NEW_STYLE_DRM_PLATFORM_DEV) | ||
723 | iRes = platform_driver_register(&sPVRPlatDriver); | ||
724 | #if !defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV) | ||
725 | if (iRes == 0) | ||
726 | { | ||
727 | psPlatDev = platform_device_register_full(&sPVRPlatDeviceInfo); | ||
728 | if (IS_ERR(psPlatDev)) | ||
729 | { | ||
730 | iRes = PTR_ERR(psPlatDev); | ||
731 | psPlatDev = NULL; | ||
732 | platform_driver_unregister(&sPVRPlatDriver); | ||
733 | } | ||
734 | } | ||
735 | #endif | ||
736 | #else /* defined(PVR_NEW_STYLE_DRM_PLATFORM_DEV) */ | ||
737 | #if defined(SUPPORT_DRI_DRM_PLUGIN) | ||
738 | iRes = SysDRMRegisterPlugin(&sPVRDrmPlugin); | ||
739 | #else /* defined(SUPPORT_DRI_DRM_PLUGIN) */ | ||
740 | #if defined(PVR_DRI_DRM_NOT_PCI) | ||
741 | iRes = drm_pvr_dev_add(); | ||
742 | if (iRes != 0) | ||
743 | { | ||
744 | return iRes; | ||
745 | } | ||
746 | #endif | ||
747 | |||
748 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)) | ||
749 | #if defined(PVR_DRI_DRM_PLATFORM_DEV) | ||
750 | iRes = drm_platform_init(&sPVRDrmDriver, gpsPVRLDMDev); | ||
751 | #else | ||
752 | iRes = drm_pci_init(&sPVRDrmDriver, &sPVRPCIDriver); | ||
753 | #endif | ||
754 | #else /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)) */ | ||
755 | iRes = drm_init(&sPVRDrmDriver); | ||
756 | #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)) */ | ||
757 | |||
758 | #if defined(PVR_DRI_DRM_NOT_PCI) | ||
759 | if (iRes != 0) | ||
760 | { | ||
761 | drm_pvr_dev_remove(); | ||
762 | } | ||
763 | #endif | ||
764 | #endif /* defined(SUPPORT_DRI_DRM_PLUGIN) */ | ||
765 | #endif /* defined(PVR_NEW_STYLE_DRM_PLATFORM_DEV) */ | ||
766 | return iRes; | ||
767 | } | ||
768 | |||
769 | static void __exit PVRSRVDrmExit(void) | ||
770 | { | ||
771 | #if defined(PVR_NEW_STYLE_DRM_PLATFORM_DEV) | ||
772 | #if !defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV) | ||
773 | platform_device_unregister(psPlatDev); | ||
774 | #endif | ||
775 | platform_driver_unregister(&sPVRPlatDriver); | ||
776 | #else /* defined(PVR_NEW_STYLE_DRM_PLATFORM_DEV) */ | ||
777 | #if defined(SUPPORT_DRI_DRM_PLUGIN) | ||
778 | SysDRMUnregisterPlugin(&sPVRDrmPlugin); | ||
779 | #else /* defined(SUPPORT_DRI_DRM_PLUGIN) */ | ||
780 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)) | ||
781 | #if defined(PVR_DRI_DRM_PLATFORM_DEV) | ||
782 | drm_platform_exit(&sPVRDrmDriver, gpsPVRLDMDev); | ||
783 | #else | ||
784 | drm_pci_exit(&sPVRDrmDriver, &sPVRPCIDriver); | ||
785 | #endif | ||
786 | #else /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)) */ | ||
787 | drm_exit(&sPVRDrmDriver); | ||
788 | #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)) */ | ||
789 | |||
790 | #if defined(PVR_DRI_DRM_NOT_PCI) | ||
791 | drm_pvr_dev_remove(); | ||
792 | #endif | ||
793 | #endif /* defined(SUPPORT_DRI_DRM_PLUGIN) */ | ||
794 | #endif /* defined(PVR_NEW_STYLE_DRM_PLATFORM_DEV) */ | ||
795 | } | ||
796 | |||
797 | /* | ||
798 | * These macro calls define the initialisation and removal functions of the | ||
799 | * driver. Although they are prefixed `module_', they apply when compiling | ||
800 | * statically as well; in both cases they define the function the kernel will | ||
801 | * run to start/stop the driver. | ||
802 | */ | ||
803 | module_init(PVRSRVDrmInit); | ||
804 | module_exit(PVRSRVDrmExit); | ||
805 | #endif /* !defined(SUPPORT_DRI_DRM_EXT) */ | ||
806 | #endif /* defined(SUPPORT_DRI_DRM) */ | ||
807 | |||
808 | |||