]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_probe.c
Revert "net: phy: Set the driver when registering an MDIO bus device"
[karo-tx-linux.git] / drivers / mxc / gpu-viv / hal / os / linux / kernel / gc_hal_kernel_probe.c
1 /****************************************************************************
2 *
3 *    Copyright (C) 2005 - 2014 by Vivante Corp.
4 *
5 *    This program is free software; you can redistribute it and/or modify
6 *    it under the terms of the GNU General Public License as published by
7 *    the Free Software Foundation; either version 2 of the license, or
8 *    (at your option) any later version.
9 *
10 *    This program is distributed in the hope that it will be useful,
11 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 *    GNU General Public License for more details.
14 *
15 *    You should have received a copy of the GNU General Public License
16 *    along with this program; if not write to the Free Software
17 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 *****************************************************************************/
20
21
22 #include <linux/device.h>
23 #include <linux/slab.h>
24
25 #include "gc_hal_kernel_linux.h"
26 #include "gc_hal_driver.h"
27
28 #if USE_PLATFORM_DRIVER
29 #   include <linux/platform_device.h>
30 #endif
31
32 #ifdef CONFIG_PXA_DVFM
33 #   include <mach/dvfm.h>
34 #   include <mach/pxa3xx_dvfm.h>
35 #endif
36
37
38 /* Zone used for header/footer. */
39 #define _GC_OBJ_ZONE    gcvZONE_DRIVER
40
41 MODULE_DESCRIPTION("Vivante Graphics Driver");
42 MODULE_LICENSE("GPL");
43
44 static struct class* gpuClass;
45
46 static gcsPLATFORM platform;
47
48 static gckGALDEVICE galDevice;
49
50 static uint major = 199;
51 module_param(major, uint, 0644);
52
53 #if gcdMULTI_GPU || gcdMULTI_GPU_AFFINITY
54 static int irqLine3D0 = -1;
55 module_param(irqLine3D0, int, 0644);
56
57 static ulong registerMemBase3D0 = 0;
58 module_param(registerMemBase3D0, ulong, 0644);
59
60 static ulong registerMemSize3D0 = 2 << 10;
61 module_param(registerMemSize3D0, ulong, 0644);
62
63 static int irqLine3D1 = -1;
64 module_param(irqLine3D1, int, 0644);
65
66 static ulong registerMemBase3D1 = 0;
67 module_param(registerMemBase3D1, ulong, 0644);
68
69 static ulong registerMemSize3D1 = 2 << 10;
70 module_param(registerMemSize3D1, ulong, 0644);
71 #else
72 static int irqLine = -1;
73 module_param(irqLine, int, 0644);
74
75 static ulong registerMemBase = 0x80000000;
76 module_param(registerMemBase, ulong, 0644);
77
78 static ulong registerMemSize = 2 << 10;
79 module_param(registerMemSize, ulong, 0644);
80 #endif
81
82 static int irqLine2D = -1;
83 module_param(irqLine2D, int, 0644);
84
85 static ulong registerMemBase2D = 0x00000000;
86 module_param(registerMemBase2D, ulong, 0644);
87
88 static ulong registerMemSize2D = 2 << 10;
89 module_param(registerMemSize2D, ulong, 0644);
90
91 static int irqLineVG = -1;
92 module_param(irqLineVG, int, 0644);
93
94 static ulong registerMemBaseVG = 0x00000000;
95 module_param(registerMemBaseVG, ulong, 0644);
96
97 static ulong registerMemSizeVG = 2 << 10;
98 module_param(registerMemSizeVG, ulong, 0644);
99
100 #ifndef gcdDEFAULT_CONTIGUOUS_SIZE
101 #define gcdDEFAULT_CONTIGUOUS_SIZE (4 << 20)
102 #endif
103 static ulong contiguousSize = gcdDEFAULT_CONTIGUOUS_SIZE;
104 module_param(contiguousSize, ulong, 0644);
105
106 static ulong contiguousBase = 0;
107 module_param(contiguousBase, ulong, 0644);
108
109 static ulong bankSize = 0;
110 module_param(bankSize, ulong, 0644);
111
112 static int fastClear = -1;
113 module_param(fastClear, int, 0644);
114
115 static int compression = -1;
116 module_param(compression, int, 0644);
117
118 static int powerManagement = -1;
119 module_param(powerManagement, int, 0644);
120
121 static int gpuProfiler = 0;
122 module_param(gpuProfiler, int, 0644);
123
124 static int signal = 48;
125 module_param(signal, int, 0644);
126
127 static ulong baseAddress = 0;
128 module_param(baseAddress, ulong, 0644);
129
130 static ulong physSize = 0;
131 module_param(physSize, ulong, 0644);
132
133 static uint logFileSize = 0;
134 module_param(logFileSize,uint, 0644);
135
136 static uint recovery = 1;
137 module_param(recovery, uint, 0644);
138 MODULE_PARM_DESC(recovery, "Recover GPU from stuck (1: Enable, 0: Disable)");
139
140 /* Middle needs about 40KB buffer, Maximal may need more than 200KB buffer. */
141 static uint stuckDump = 1;
142 module_param(stuckDump, uint, 0644);
143 MODULE_PARM_DESC(stuckDump, "Level of stuck dump content (1: Minimal, 2: Middle, 3: Maximal)");
144
145 static int showArgs = 0;
146 module_param(showArgs, int, 0644);
147
148 static int mmu = 1;
149 module_param(mmu, int, 0644);
150
151 static int gpu3DMinClock = 1;
152
153 static int contiguousRequested = 0;
154
155 static int drv_open(
156     struct inode* inode,
157     struct file* filp
158     );
159
160 static int drv_release(
161     struct inode* inode,
162     struct file* filp
163     );
164
165 static long drv_ioctl(
166     struct file* filp,
167     unsigned int ioctlCode,
168     unsigned long arg
169     );
170
171 static int drv_mmap(
172     struct file* filp,
173     struct vm_area_struct* vma
174     );
175
176 static struct file_operations driver_fops =
177 {
178     .owner      = THIS_MODULE,
179     .open       = drv_open,
180     .release    = drv_release,
181     .unlocked_ioctl = drv_ioctl,
182 #ifdef HAVE_COMPAT_IOCTL
183     .compat_ioctl = drv_ioctl,
184 #endif
185     .mmap       = drv_mmap,
186 };
187
188 void
189 _UpdateModuleParam(
190     gcsMODULE_PARAMETERS *Param
191     )
192 {
193 #if gcdMULTI_GPU || gcdMULTI_GPU_AFFINITY
194 #else
195     irqLine           = Param->irqLine ;
196     registerMemBase   = Param->registerMemBase;
197     registerMemSize   = Param->registerMemSize;
198 #endif
199     irqLine2D         = Param->irqLine2D      ;
200     registerMemBase2D = Param->registerMemBase2D;
201     registerMemSize2D = Param->registerMemSize2D;
202     irqLineVG         = Param->irqLineVG;
203     registerMemBaseVG = Param->registerMemBaseVG;
204     registerMemSizeVG = Param->registerMemSizeVG;
205     contiguousSize    = Param->contiguousSize;
206     contiguousBase    = Param->contiguousBase;
207     bankSize          = Param->bankSize;
208     fastClear         = Param->fastClear;
209     compression       = Param->compression;
210     powerManagement   = Param->powerManagement;
211     gpuProfiler       = Param->gpuProfiler;
212     signal            = Param->signal;
213     baseAddress       = Param->baseAddress;
214     physSize          = Param->physSize;
215     logFileSize       = Param->logFileSize;
216     recovery          = Param->recovery;
217     stuckDump         = Param->stuckDump;
218     showArgs          = Param->showArgs;
219     contiguousRequested = Param->contiguousRequested;
220     gpu3DMinClock     = Param->gpu3DMinClock;
221 }
222
223 void
224 gckOS_DumpParam(
225     void
226     )
227 {
228     printk("Galcore options:\n");
229 #if gcdMULTI_GPU || gcdMULTI_GPU_AFFINITY
230     printk("  irqLine3D0         = %d\n",      irqLine3D0);
231     printk("  registerMemBase3D0 = 0x%08lX\n", registerMemBase3D0);
232     printk("  registerMemSize3D0 = 0x%08lX\n", registerMemSize3D0);
233
234     if (irqLine3D1 != -1)
235     {
236         printk("  irqLine3D1         = %d\n",      irqLine3D1);
237         printk("  registerMemBase3D1 = 0x%08lX\n", registerMemBase3D1);
238         printk("  registerMemSize3D1 = 0x%08lX\n", registerMemSize3D1);
239     }
240 #else
241     printk("  irqLine           = %d\n",      irqLine);
242     printk("  registerMemBase   = 0x%08lX\n", registerMemBase);
243     printk("  registerMemSize   = 0x%08lX\n", registerMemSize);
244 #endif
245
246     if (irqLine2D != -1)
247     {
248         printk("  irqLine2D         = %d\n",      irqLine2D);
249         printk("  registerMemBase2D = 0x%08lX\n", registerMemBase2D);
250         printk("  registerMemSize2D = 0x%08lX\n", registerMemSize2D);
251     }
252
253     if (irqLineVG != -1)
254     {
255         printk("  irqLineVG         = %d\n",      irqLineVG);
256         printk("  registerMemBaseVG = 0x%08lX\n", registerMemBaseVG);
257         printk("  registerMemSizeVG = 0x%08lX\n", registerMemSizeVG);
258     }
259
260     printk("  contiguousSize    = %ld\n",     contiguousSize);
261     printk("  contiguousBase    = 0x%08lX\n", contiguousBase);
262     printk("  bankSize          = 0x%08lX\n", bankSize);
263     printk("  fastClear         = %d\n",      fastClear);
264     printk("  compression       = %d\n",      compression);
265     printk("  signal            = %d\n",      signal);
266     printk("  powerManagement   = %d\n",      powerManagement);
267     printk("  baseAddress       = 0x%08lX\n", baseAddress);
268     printk("  physSize          = 0x%08lX\n", physSize);
269     printk("  logFileSize       = %d KB \n",  logFileSize);
270     printk("  recovery          = %d\n",      recovery);
271     printk("  stuckDump         = %d\n",      stuckDump);
272     printk("  gpuProfiler       = %d\n",      gpuProfiler);
273 }
274
275 int drv_open(
276     struct inode* inode,
277     struct file* filp
278     )
279 {
280     gceSTATUS status;
281     gctBOOL attached = gcvFALSE;
282     gcsHAL_PRIVATE_DATA_PTR data = gcvNULL;
283     gctINT i;
284
285     gcmkHEADER_ARG("inode=0x%08X filp=0x%08X", inode, filp);
286
287     if (filp == gcvNULL)
288     {
289         gcmkTRACE_ZONE(
290             gcvLEVEL_ERROR, gcvZONE_DRIVER,
291             "%s(%d): filp is NULL\n",
292             __FUNCTION__, __LINE__
293             );
294
295         gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
296     }
297
298     data = kmalloc(sizeof(gcsHAL_PRIVATE_DATA), GFP_KERNEL | __GFP_NOWARN);
299
300     if (data == gcvNULL)
301     {
302         gcmkTRACE_ZONE(
303             gcvLEVEL_ERROR, gcvZONE_DRIVER,
304             "%s(%d): private_data is NULL\n",
305             __FUNCTION__, __LINE__
306             );
307
308         gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
309     }
310
311     data->device             = galDevice;
312     data->mappedMemory       = gcvNULL;
313     data->contiguousLogical  = gcvNULL;
314     gcmkONERROR(gckOS_GetProcessID(&data->pidOpen));
315
316     /* Attached the process. */
317     for (i = 0; i < gcdMAX_GPU_COUNT; i++)
318     {
319         if (galDevice->kernels[i] != gcvNULL)
320         {
321             gcmkONERROR(gckKERNEL_AttachProcess(galDevice->kernels[i], gcvTRUE));
322         }
323     }
324     attached = gcvTRUE;
325
326     if (!galDevice->contiguousMapped)
327     {
328         if (galDevice->contiguousPhysical != gcvNULL)
329         {
330             gcmkONERROR(gckOS_MapMemory(
331                 galDevice->os,
332                 galDevice->contiguousPhysical,
333                 galDevice->contiguousSize,
334                 &data->contiguousLogical
335                 ));
336         }
337     }
338
339     filp->private_data = data;
340
341     /* Success. */
342     gcmkFOOTER_NO();
343     return 0;
344
345 OnError:
346     if (data != gcvNULL)
347     {
348         if (data->contiguousLogical != gcvNULL)
349         {
350             gcmkVERIFY_OK(gckOS_UnmapMemory(
351                 galDevice->os,
352                 galDevice->contiguousPhysical,
353                 galDevice->contiguousSize,
354                 data->contiguousLogical
355                 ));
356         }
357
358         kfree(data);
359     }
360
361     if (attached)
362     {
363         for (i = 0; i < gcdMAX_GPU_COUNT; i++)
364         {
365             if (galDevice->kernels[i] != gcvNULL)
366             {
367                 gcmkVERIFY_OK(gckKERNEL_AttachProcess(galDevice->kernels[i], gcvFALSE));
368             }
369         }
370     }
371
372     gcmkFOOTER();
373     return -ENOTTY;
374 }
375
376 int drv_release(
377     struct inode* inode,
378     struct file* filp
379     )
380 {
381     gceSTATUS status;
382     gcsHAL_PRIVATE_DATA_PTR data;
383     gckGALDEVICE device;
384     gctINT i;
385
386     gcmkHEADER_ARG("inode=0x%08X filp=0x%08X", inode, filp);
387
388     if (filp == gcvNULL)
389     {
390         gcmkTRACE_ZONE(
391             gcvLEVEL_ERROR, gcvZONE_DRIVER,
392             "%s(%d): filp is NULL\n",
393             __FUNCTION__, __LINE__
394             );
395
396         gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
397     }
398
399     data = filp->private_data;
400
401     if (data == gcvNULL)
402     {
403         gcmkTRACE_ZONE(
404             gcvLEVEL_ERROR, gcvZONE_DRIVER,
405             "%s(%d): private_data is NULL\n",
406             __FUNCTION__, __LINE__
407             );
408
409         gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
410     }
411
412     device = data->device;
413
414     if (device == gcvNULL)
415     {
416         gcmkTRACE_ZONE(
417             gcvLEVEL_ERROR, gcvZONE_DRIVER,
418             "%s(%d): device is NULL\n",
419             __FUNCTION__, __LINE__
420             );
421
422         gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
423     }
424
425     if (!device->contiguousMapped)
426     {
427         if (data->contiguousLogical != gcvNULL)
428         {
429             gcmkONERROR(gckOS_UnmapMemoryEx(
430                 galDevice->os,
431                 galDevice->contiguousPhysical,
432                 galDevice->contiguousSize,
433                 data->contiguousLogical,
434                 data->pidOpen
435                 ));
436
437             data->contiguousLogical = gcvNULL;
438         }
439     }
440
441     /* A process gets detached. */
442     for (i = 0; i < gcdMAX_GPU_COUNT; i++)
443     {
444         if (galDevice->kernels[i] != gcvNULL)
445         {
446             gcmkONERROR(gckKERNEL_AttachProcessEx(galDevice->kernels[i], gcvFALSE, data->pidOpen));
447         }
448     }
449
450     kfree(data);
451     filp->private_data = NULL;
452
453     /* Success. */
454     gcmkFOOTER_NO();
455     return 0;
456
457 OnError:
458     gcmkFOOTER();
459     return -ENOTTY;
460 }
461
462 long drv_ioctl(
463     struct file* filp,
464     unsigned int ioctlCode,
465     unsigned long arg
466     )
467 {
468     gceSTATUS status;
469     gcsHAL_INTERFACE iface;
470     gctUINT32 copyLen;
471     DRIVER_ARGS drvArgs;
472     gckGALDEVICE device;
473     gcsHAL_PRIVATE_DATA_PTR data;
474     gctINT32 i, count;
475     gckVIDMEM_NODE nodeObject;
476
477     gcmkHEADER_ARG(
478         "filp=0x%08X ioctlCode=0x%08X arg=0x%08X",
479         filp, ioctlCode, arg
480         );
481
482     if (filp == gcvNULL)
483     {
484         gcmkTRACE_ZONE(
485             gcvLEVEL_ERROR, gcvZONE_DRIVER,
486             "%s(%d): filp is NULL\n",
487             __FUNCTION__, __LINE__
488             );
489
490         gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
491     }
492
493     data = filp->private_data;
494
495     if (data == gcvNULL)
496     {
497         gcmkTRACE_ZONE(
498             gcvLEVEL_ERROR, gcvZONE_DRIVER,
499             "%s(%d): private_data is NULL\n",
500             __FUNCTION__, __LINE__
501             );
502
503         gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
504     }
505
506     device = data->device;
507
508     if (device == gcvNULL)
509     {
510         gcmkTRACE_ZONE(
511             gcvLEVEL_ERROR, gcvZONE_DRIVER,
512             "%s(%d): device is NULL\n",
513             __FUNCTION__, __LINE__
514             );
515
516         gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
517     }
518
519     if ((ioctlCode != IOCTL_GCHAL_INTERFACE)
520     &&  (ioctlCode != IOCTL_GCHAL_KERNEL_INTERFACE)
521     )
522     {
523         gcmkTRACE_ZONE(
524             gcvLEVEL_ERROR, gcvZONE_DRIVER,
525             "%s(%d): unknown command %d\n",
526             __FUNCTION__, __LINE__,
527             ioctlCode
528             );
529
530         gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
531     }
532
533     /* Get the drvArgs. */
534     copyLen = copy_from_user(
535         &drvArgs, (void *) arg, sizeof(DRIVER_ARGS)
536         );
537
538     if (copyLen != 0)
539     {
540         gcmkTRACE_ZONE(
541             gcvLEVEL_ERROR, gcvZONE_DRIVER,
542             "%s(%d): error copying of the input arguments.\n",
543             __FUNCTION__, __LINE__
544             );
545
546         gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
547     }
548
549     /* Now bring in the gcsHAL_INTERFACE structure. */
550     if ((drvArgs.InputBufferSize  != sizeof(gcsHAL_INTERFACE))
551     ||  (drvArgs.OutputBufferSize != sizeof(gcsHAL_INTERFACE))
552     )
553     {
554         gcmkTRACE_ZONE(
555             gcvLEVEL_ERROR, gcvZONE_DRIVER,
556             "%s(%d): input or/and output structures are invalid.\n",
557             __FUNCTION__, __LINE__
558             );
559
560         gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
561     }
562
563     copyLen = copy_from_user(
564         &iface, gcmUINT64_TO_PTR(drvArgs.InputBuffer), sizeof(gcsHAL_INTERFACE)
565         );
566
567     if (copyLen != 0)
568     {
569         gcmkTRACE_ZONE(
570             gcvLEVEL_ERROR, gcvZONE_DRIVER,
571             "%s(%d): error copying of input HAL interface.\n",
572             __FUNCTION__, __LINE__
573             );
574
575         gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
576     }
577
578     if (iface.command == gcvHAL_CHIP_INFO)
579     {
580         count = 0;
581         for (i = 0; i < gcdMAX_GPU_COUNT; i++)
582         {
583             if (device->kernels[i] != gcvNULL)
584             {
585 #if gcdENABLE_VG
586                 if (i == gcvCORE_VG)
587                 {
588                     iface.u.ChipInfo.types[count] = gcvHARDWARE_VG;
589                 }
590                 else
591 #endif
592                 {
593                     gcmkVERIFY_OK(gckHARDWARE_GetType(device->kernels[i]->hardware,
594                                                       &iface.u.ChipInfo.types[count]));
595                 }
596                 count++;
597             }
598         }
599
600         iface.u.ChipInfo.count = count;
601         iface.status = status = gcvSTATUS_OK;
602     }
603     else
604     {
605         if (iface.hardwareType > 7)
606         {
607             gcmkTRACE_ZONE(
608                 gcvLEVEL_ERROR, gcvZONE_DRIVER,
609                 "%s(%d): unknown hardwareType %d\n",
610                 __FUNCTION__, __LINE__,
611                 iface.hardwareType
612                 );
613
614             gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
615         }
616
617 #if gcdENABLE_VG
618         if (device->coreMapping[iface.hardwareType] == gcvCORE_VG)
619         {
620             status = gckVGKERNEL_Dispatch(device->kernels[gcvCORE_VG],
621                                         (ioctlCode == IOCTL_GCHAL_INTERFACE),
622                                         &iface);
623         }
624         else
625 #endif
626         {
627             status = gckKERNEL_Dispatch(device->kernels[device->coreMapping[iface.hardwareType]],
628                                         (ioctlCode == IOCTL_GCHAL_INTERFACE),
629                                         &iface);
630         }
631     }
632
633     /* Redo system call after pending signal is handled. */
634     if (status == gcvSTATUS_INTERRUPTED)
635     {
636         gcmkFOOTER();
637         return -ERESTARTSYS;
638     }
639
640     if (gcmIS_SUCCESS(status) && (iface.command == gcvHAL_LOCK_VIDEO_MEMORY))
641     {
642         gcuVIDMEM_NODE_PTR node;
643         gctUINT32 processID;
644
645         gckOS_GetProcessID(&processID);
646
647         gcmkONERROR(gckVIDMEM_HANDLE_Lookup(device->kernels[device->coreMapping[iface.hardwareType]],
648                                 processID,
649                                 (gctUINT32)iface.u.LockVideoMemory.node,
650                                 &nodeObject));
651         node = nodeObject->node;
652
653         /* Special case for mapped memory. */
654         if ((data->mappedMemory != gcvNULL)
655         &&  (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
656         )
657         {
658             /* Compute offset into mapped memory. */
659             gctUINT32 offset
660                 = (gctUINT8 *) gcmUINT64_TO_PTR(iface.u.LockVideoMemory.memory)
661                 - (gctUINT8 *) device->contiguousBase;
662
663             /* Compute offset into user-mapped region. */
664             iface.u.LockVideoMemory.memory =
665                 gcmPTR_TO_UINT64((gctUINT8 *) data->mappedMemory + offset);
666         }
667     }
668
669     /* Copy data back to the user. */
670     copyLen = copy_to_user(
671         gcmUINT64_TO_PTR(drvArgs.OutputBuffer), &iface, sizeof(gcsHAL_INTERFACE)
672         );
673
674     if (copyLen != 0)
675     {
676         gcmkTRACE_ZONE(
677             gcvLEVEL_ERROR, gcvZONE_DRIVER,
678             "%s(%d): error copying of output HAL interface.\n",
679             __FUNCTION__, __LINE__
680             );
681
682         gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
683     }
684
685     /* Success. */
686     gcmkFOOTER_NO();
687     return 0;
688
689 OnError:
690     gcmkFOOTER();
691     return -ENOTTY;
692 }
693
694 static int drv_mmap(
695     struct file* filp,
696     struct vm_area_struct* vma
697     )
698 {
699     gceSTATUS status = gcvSTATUS_OK;
700     gcsHAL_PRIVATE_DATA_PTR data;
701     gckGALDEVICE device;
702
703     gcmkHEADER_ARG("filp=0x%08X vma=0x%08X", filp, vma);
704
705     if (filp == gcvNULL)
706     {
707         gcmkTRACE_ZONE(
708             gcvLEVEL_ERROR, gcvZONE_DRIVER,
709             "%s(%d): filp is NULL\n",
710             __FUNCTION__, __LINE__
711             );
712
713         gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
714     }
715
716     data = filp->private_data;
717
718     if (data == gcvNULL)
719     {
720         gcmkTRACE_ZONE(
721             gcvLEVEL_ERROR, gcvZONE_DRIVER,
722             "%s(%d): private_data is NULL\n",
723             __FUNCTION__, __LINE__
724             );
725
726         gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
727     }
728
729     device = data->device;
730
731     if (device == gcvNULL)
732     {
733         gcmkTRACE_ZONE(
734             gcvLEVEL_ERROR, gcvZONE_DRIVER,
735             "%s(%d): device is NULL\n",
736             __FUNCTION__, __LINE__
737             );
738
739         gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
740     }
741
742 #if !gcdPAGED_MEMORY_CACHEABLE
743     vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
744     vma->vm_flags    |= gcdVM_FLAGS;
745 #endif
746     vma->vm_pgoff     = 0;
747
748     if (device->contiguousMapped)
749     {
750         unsigned long size = vma->vm_end - vma->vm_start;
751         int ret = 0;
752
753         if (size > device->contiguousSize)
754         {
755             gcmkTRACE_ZONE(
756                 gcvLEVEL_ERROR, gcvZONE_DRIVER,
757                 "%s(%d): Invalid mapping size.\n",
758                 __FUNCTION__, __LINE__
759                 );
760
761             gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
762         }
763
764         ret = io_remap_pfn_range(
765             vma,
766             vma->vm_start,
767             device->requestedContiguousBase >> PAGE_SHIFT,
768             size,
769             vma->vm_page_prot
770             );
771
772         if (ret != 0)
773         {
774             gcmkTRACE_ZONE(
775                 gcvLEVEL_ERROR, gcvZONE_DRIVER,
776                 "%s(%d): io_remap_pfn_range failed %d\n",
777                 __FUNCTION__, __LINE__,
778                 ret
779                 );
780
781             data->mappedMemory = gcvNULL;
782
783             gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
784         }
785
786         data->mappedMemory = (gctPOINTER) vma->vm_start;
787
788         /* Success. */
789         gcmkFOOTER_NO();
790         return 0;
791     }
792
793 OnError:
794     gcmkFOOTER();
795     return -ENOTTY;
796 }
797
798
799 #if !USE_PLATFORM_DRIVER
800 static int __init drv_init(void)
801 #else
802 static int drv_init(void)
803 #endif
804 {
805     int ret;
806     int result = -EINVAL;
807     gceSTATUS status;
808     gckGALDEVICE device = gcvNULL;
809     struct class* device_class = gcvNULL;
810
811     gcsDEVICE_CONSTRUCT_ARGS args = {
812         .recovery           = recovery,
813         .stuckDump          = stuckDump,
814         .gpu3DMinClock      = gpu3DMinClock,
815         .contiguousRequested = contiguousRequested,
816         .platform           = &platform,
817         .mmu                = mmu,
818     };
819
820     gcmkHEADER();
821
822     printk(KERN_INFO "Galcore version %d.%d.%d.%d\n",
823         gcvVERSION_MAJOR, gcvVERSION_MINOR, gcvVERSION_PATCH, gcvVERSION_BUILD);
824
825 #if !VIVANTE_PROFILER_PM
826     /* when enable gpu profiler, we need to turn off gpu powerMangement */
827     if (gpuProfiler)
828     {
829         powerManagement = 0;
830     }
831 #endif
832
833     if (showArgs)
834     {
835         gckOS_DumpParam();
836     }
837
838     if (logFileSize != 0)
839     {
840         gckDEBUGFS_Initialize();
841     }
842
843     /* Create the GAL device. */
844     status = gckGALDEVICE_Construct(
845 #if gcdMULTI_GPU || gcdMULTI_GPU_AFFINITY
846         irqLine3D0,
847         registerMemBase3D0, registerMemSize3D0,
848         irqLine3D1,
849         registerMemBase3D1, registerMemSize3D1,
850 #else
851         irqLine,
852         registerMemBase, registerMemSize,
853 #endif
854         irqLine2D,
855         registerMemBase2D, registerMemSize2D,
856         irqLineVG,
857         registerMemBaseVG, registerMemSizeVG,
858         contiguousBase, contiguousSize,
859         bankSize, fastClear, compression, baseAddress, physSize, signal,
860         logFileSize,
861         powerManagement,
862         gpuProfiler,
863         &args,
864         &device
865     );
866
867     if (gcmIS_ERROR(status))
868     {
869         gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
870                        "%s(%d): Failed to create the GAL device: status=%d\n",
871                        __FUNCTION__, __LINE__, status);
872
873         goto OnError;
874     }
875
876     /* Start the GAL device. */
877     gcmkONERROR(gckGALDEVICE_Start(device));
878
879     if ((physSize != 0)
880        && (device->kernels[gcvCORE_MAJOR] != gcvNULL)
881        && (device->kernels[gcvCORE_MAJOR]->hardware->mmuVersion != 0))
882     {
883         /* Reset the base address */
884         device->baseAddress = 0;
885     }
886
887     /* Register the character device. */
888     ret = register_chrdev(major, DEVICE_NAME, &driver_fops);
889
890     if (ret < 0)
891     {
892         gcmkTRACE_ZONE(
893             gcvLEVEL_ERROR, gcvZONE_DRIVER,
894             "%s(%d): Could not allocate major number for mmap.\n",
895             __FUNCTION__, __LINE__
896             );
897
898         gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
899     }
900
901     if (major == 0)
902     {
903         major = ret;
904     }
905
906     /* Create the device class. */
907     device_class = class_create(THIS_MODULE, "graphics_class");
908
909     if (IS_ERR(device_class))
910     {
911         gcmkTRACE_ZONE(
912             gcvLEVEL_ERROR, gcvZONE_DRIVER,
913             "%s(%d): Failed to create the class.\n",
914             __FUNCTION__, __LINE__
915             );
916
917         gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
918     }
919
920 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
921     device_create(device_class, NULL, MKDEV(major, 0), NULL, DEVICE_NAME);
922 #else
923     device_create(device_class, NULL, MKDEV(major, 0), DEVICE_NAME);
924 #endif
925
926     galDevice = device;
927     gpuClass  = device_class;
928
929 #if gcdMULTI_GPU || gcdMULTI_GPU_AFFINITY
930     gcmkTRACE_ZONE(
931         gcvLEVEL_INFO, gcvZONE_DRIVER,
932         "%s(%d): irqLine3D0=%d, contiguousSize=%lu, memBase3D0=0x%lX\n",
933         __FUNCTION__, __LINE__,
934         irqLine3D0, contiguousSize, registerMemBase3D0
935         );
936 #else
937     gcmkTRACE_ZONE(
938         gcvLEVEL_INFO, gcvZONE_DRIVER,
939         "%s(%d): irqLine=%d, contiguousSize=%lu, memBase=0x%lX\n",
940         __FUNCTION__, __LINE__,
941         irqLine, contiguousSize, registerMemBase
942         );
943 #endif
944
945     /* Success. */
946     gcmkFOOTER_NO();
947     return 0;
948
949 OnError:
950     /* Roll back. */
951     if (device_class != gcvNULL)
952     {
953         device_destroy(device_class, MKDEV(major, 0));
954         class_destroy(device_class);
955     }
956
957     if (device != gcvNULL)
958     {
959         gcmkVERIFY_OK(gckGALDEVICE_Stop(device));
960         gcmkVERIFY_OK(gckGALDEVICE_Destroy(device));
961     }
962
963     gcmkFOOTER();
964     return result;
965 }
966
967 #if !USE_PLATFORM_DRIVER
968 static void __exit drv_exit(void)
969 #else
970 static void drv_exit(void)
971 #endif
972 {
973     gcmkHEADER();
974
975     gcmkASSERT(gpuClass != gcvNULL);
976     device_destroy(gpuClass, MKDEV(major, 0));
977     class_destroy(gpuClass);
978
979     unregister_chrdev(major, DEVICE_NAME);
980
981     gcmkVERIFY_OK(gckGALDEVICE_Stop(galDevice));
982     gcmkVERIFY_OK(gckGALDEVICE_Destroy(galDevice));
983
984     if(gckDEBUGFS_IsEnabled())
985     {
986         gckDEBUGFS_Terminate();
987     }
988
989     gcmkFOOTER_NO();
990 }
991
992 #if !USE_PLATFORM_DRIVER
993     module_init(drv_init);
994     module_exit(drv_exit);
995 #else
996
997 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
998 static int gpu_probe(struct platform_device *pdev)
999 #else
1000 static int __devinit gpu_probe(struct platform_device *pdev)
1001 #endif
1002 {
1003     int ret = -ENODEV;
1004     gcsMODULE_PARAMETERS moduleParam = {
1005 #if gcdMULTI_GPU || gcdMULTI_GPU_AFFINITY
1006 #else
1007         .irqLine            = irqLine,
1008         .registerMemBase    = registerMemBase,
1009         .registerMemSize    = registerMemSize,
1010 #endif
1011         .irqLine2D          = irqLine2D,
1012         .registerMemBase2D  = registerMemBase2D,
1013         .registerMemSize2D  = registerMemSize2D,
1014         .irqLineVG          = irqLineVG,
1015         .registerMemBaseVG  = registerMemBaseVG,
1016         .registerMemSizeVG  = registerMemSizeVG,
1017         .contiguousSize     = contiguousSize,
1018         .contiguousBase     = contiguousBase,
1019         .bankSize           = bankSize,
1020         .fastClear          = fastClear,
1021         .compression        = compression,
1022         .powerManagement    = powerManagement,
1023         .gpuProfiler        = gpuProfiler,
1024         .signal             = signal,
1025         .baseAddress        = baseAddress,
1026         .physSize           = physSize,
1027         .logFileSize        = logFileSize,
1028         .recovery           = recovery,
1029         .stuckDump          = stuckDump,
1030         .showArgs           = showArgs,
1031         .gpu3DMinClock      = gpu3DMinClock,
1032     };
1033
1034     gcmkHEADER();
1035
1036     platform.device = pdev;
1037
1038     if (platform.ops->getPower)
1039     {
1040         if (gcmIS_ERROR(platform.ops->getPower(&platform)))
1041         {
1042             gcmkFOOTER_NO();
1043             return ret;
1044         }
1045     }
1046
1047     if (platform.ops->adjustParam)
1048     {
1049         /* Override default module param. */
1050         platform.ops->adjustParam(&platform, &moduleParam);
1051
1052         /* Update module param because drv_init() uses them directly. */
1053         _UpdateModuleParam(&moduleParam);
1054     }
1055
1056     ret = drv_init();
1057
1058     if (!ret)
1059     {
1060         platform_set_drvdata(pdev, galDevice);
1061
1062         gcmkFOOTER_NO();
1063         return ret;
1064     }
1065
1066     gcmkFOOTER_ARG(KERN_INFO "Failed to register gpu driver: %d\n", ret);
1067     return ret;
1068 }
1069
1070 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
1071 static int gpu_remove(struct platform_device *pdev)
1072 #else
1073 static int __devexit gpu_remove(struct platform_device *pdev)
1074 #endif
1075 {
1076     gcmkHEADER();
1077
1078     drv_exit();
1079
1080     if (platform.ops->putPower)
1081     {
1082         platform.ops->putPower(&platform);
1083     }
1084
1085     gcmkFOOTER_NO();
1086     return 0;
1087 }
1088
1089 static int gpu_suspend(struct platform_device *dev, pm_message_t state)
1090 {
1091     gceSTATUS status;
1092     gckGALDEVICE device;
1093     gctINT i;
1094
1095     device = platform_get_drvdata(dev);
1096
1097     if (!device)
1098     {
1099         return -1;
1100     }
1101
1102     for (i = 0; i < gcdMAX_GPU_COUNT; i++)
1103     {
1104         if (device->kernels[i] != gcvNULL)
1105         {
1106             /* Store states. */
1107 #if gcdENABLE_VG
1108             if (i == gcvCORE_VG)
1109             {
1110                 status = gckVGHARDWARE_QueryPowerManagementState(device->kernels[i]->vg->hardware, &device->statesStored[i]);
1111             }
1112             else
1113 #endif
1114             {
1115                 status = gckHARDWARE_QueryPowerManagementState(device->kernels[i]->hardware, &device->statesStored[i]);
1116             }
1117
1118             if (gcmIS_ERROR(status))
1119             {
1120                 return -1;
1121             }
1122
1123 #if gcdENABLE_VG
1124             if (i == gcvCORE_VG)
1125             {
1126                 status = gckVGHARDWARE_SetPowerManagementState(device->kernels[i]->vg->hardware, gcvPOWER_OFF);
1127             }
1128             else
1129 #endif
1130             {
1131                 status = gckHARDWARE_SetPowerManagementState(device->kernels[i]->hardware, gcvPOWER_OFF);
1132             }
1133
1134             if (gcmIS_ERROR(status))
1135             {
1136                 return -1;
1137             }
1138
1139         }
1140     }
1141
1142     return 0;
1143 }
1144
1145 static int gpu_resume(struct platform_device *dev)
1146 {
1147     gceSTATUS status;
1148     gckGALDEVICE device;
1149     gctINT i;
1150     gceCHIPPOWERSTATE   statesStored;
1151
1152     device = platform_get_drvdata(dev);
1153
1154     if (!device)
1155     {
1156         return -1;
1157     }
1158
1159     for (i = 0; i < gcdMAX_GPU_COUNT; i++)
1160     {
1161         if (device->kernels[i] != gcvNULL)
1162         {
1163 #if gcdENABLE_VG
1164             if (i == gcvCORE_VG)
1165             {
1166                 status = gckVGHARDWARE_SetPowerManagementState(device->kernels[i]->vg->hardware, gcvPOWER_ON);
1167             }
1168             else
1169 #endif
1170             {
1171                 status = gckHARDWARE_SetPowerManagementState(device->kernels[i]->hardware, gcvPOWER_ON);
1172             }
1173
1174             if (gcmIS_ERROR(status))
1175             {
1176                 return -1;
1177             }
1178
1179             /* Convert global state to crossponding internal state. */
1180             switch(device->statesStored[i])
1181             {
1182             case gcvPOWER_OFF:
1183                 statesStored = gcvPOWER_OFF_BROADCAST;
1184                 break;
1185             case gcvPOWER_IDLE:
1186                 statesStored = gcvPOWER_IDLE_BROADCAST;
1187                 break;
1188             case gcvPOWER_SUSPEND:
1189                 statesStored = gcvPOWER_SUSPEND_BROADCAST;
1190                 break;
1191             case gcvPOWER_ON:
1192                 statesStored = gcvPOWER_ON_AUTO;
1193                 break;
1194             default:
1195                 statesStored = device->statesStored[i];
1196                 break;
1197             }
1198
1199             /* Restore states. */
1200 #if gcdENABLE_VG
1201             if (i == gcvCORE_VG)
1202             {
1203                 status = gckVGHARDWARE_SetPowerManagementState(device->kernels[i]->vg->hardware, statesStored);
1204             }
1205             else
1206 #endif
1207             {
1208                 status = gckHARDWARE_SetPowerManagementState(device->kernels[i]->hardware, statesStored);
1209             }
1210
1211             if (gcmIS_ERROR(status))
1212             {
1213                 return -1;
1214             }
1215         }
1216     }
1217
1218     return 0;
1219 }
1220
1221 #if defined(CONFIG_PM) && LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
1222 #ifdef CONFIG_PM_SLEEP
1223 static int gpu_system_suspend(struct device *dev)
1224 {
1225     pm_message_t state={0};
1226     return gpu_suspend(to_platform_device(dev), state);
1227 }
1228
1229 static int gpu_system_resume(struct device *dev)
1230 {
1231     return gpu_resume(to_platform_device(dev));
1232 }
1233 #endif
1234
1235 static const struct dev_pm_ops gpu_pm_ops = {
1236     SET_SYSTEM_SLEEP_PM_OPS(gpu_system_suspend, gpu_system_resume)
1237 };
1238 #endif
1239
1240 static struct platform_driver gpu_driver = {
1241     .probe      = gpu_probe,
1242 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
1243     .remove     = gpu_remove,
1244 #else
1245     .remove     = __devexit_p(gpu_remove),
1246 #endif
1247
1248     .suspend    = gpu_suspend,
1249     .resume     = gpu_resume,
1250
1251     .driver     = {
1252         .name   = DEVICE_NAME,
1253 #if defined(CONFIG_PM) && LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
1254         .pm     = &gpu_pm_ops,
1255 #endif
1256     }
1257 };
1258
1259 static int __init gpu_init(void)
1260 {
1261     int ret = 0;
1262
1263     memset(&platform, 0, sizeof(gcsPLATFORM));
1264
1265     gckPLATFORM_QueryOperations(&platform.ops);
1266
1267     if (platform.ops == gcvNULL)
1268     {
1269         printk(KERN_ERR "galcore: No platform specific operations.\n");
1270         ret = -ENODEV;
1271         goto out;
1272     }
1273
1274     if (platform.ops->allocPriv)
1275     {
1276         /* Allocate platform private data. */
1277         if (gcmIS_ERROR(platform.ops->allocPriv(&platform)))
1278         {
1279             ret = -ENOMEM;
1280             goto out;
1281         }
1282     }
1283
1284     if (platform.ops->needAddDevice
1285      && platform.ops->needAddDevice(&platform))
1286     {
1287         /* Allocate device */
1288         platform.device = platform_device_alloc(DEVICE_NAME, -1);
1289         if (!platform.device)
1290         {
1291             printk(KERN_ERR "galcore: platform_device_alloc failed.\n");
1292             ret = -ENOMEM;
1293             goto out;
1294         }
1295
1296         /* Add device */
1297         ret = platform_device_add(platform.device);
1298         if (ret)
1299         {
1300             printk(KERN_ERR "galcore: platform_device_add failed.\n");
1301             goto put_dev;
1302         }
1303     }
1304
1305     platform.driver = &gpu_driver;
1306
1307     if (platform.ops->adjustDriver)
1308     {
1309         /* Override default platform_driver struct. */
1310         platform.ops->adjustDriver(&platform);
1311     }
1312
1313     ret = platform_driver_register(&gpu_driver);
1314     if (!ret)
1315     {
1316         goto out;
1317     }
1318
1319     platform_device_del(platform.device);
1320 put_dev:
1321     platform_device_put(platform.device);
1322
1323 out:
1324     return ret;
1325 }
1326
1327 static void __exit gpu_exit(void)
1328 {
1329     platform_driver_unregister(&gpu_driver);
1330
1331     if (platform.ops->needAddDevice
1332      && platform.ops->needAddDevice(&platform))
1333     {
1334         platform_device_unregister(platform.device);
1335     }
1336
1337     if (platform.priv)
1338     {
1339         /* Free platform private data. */
1340         platform.ops->freePriv(&platform);
1341     }
1342 }
1343
1344 module_init(gpu_init);
1345 module_exit(gpu_exit);
1346
1347 #endif