1 /****************************************************************************
3 * Copyright (C) 2005 - 2014 by Vivante Corp.
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.
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.
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.
19 *****************************************************************************/
22 #include <linux/device.h>
23 #include <linux/slab.h>
25 #include "gc_hal_kernel_linux.h"
26 #include "gc_hal_driver.h"
28 #if USE_PLATFORM_DRIVER
29 # include <linux/platform_device.h>
32 #ifdef CONFIG_PXA_DVFM
33 # include <mach/dvfm.h>
34 # include <mach/pxa3xx_dvfm.h>
38 /* Zone used for header/footer. */
39 #define _GC_OBJ_ZONE gcvZONE_DRIVER
41 MODULE_DESCRIPTION("Vivante Graphics Driver");
42 MODULE_LICENSE("GPL");
44 static struct class* gpuClass;
46 static gcsPLATFORM platform;
48 static gckGALDEVICE galDevice;
50 static uint major = 199;
51 module_param(major, uint, 0644);
53 #if gcdMULTI_GPU || gcdMULTI_GPU_AFFINITY
54 static int irqLine3D0 = -1;
55 module_param(irqLine3D0, int, 0644);
57 static ulong registerMemBase3D0 = 0;
58 module_param(registerMemBase3D0, ulong, 0644);
60 static ulong registerMemSize3D0 = 2 << 10;
61 module_param(registerMemSize3D0, ulong, 0644);
63 static int irqLine3D1 = -1;
64 module_param(irqLine3D1, int, 0644);
66 static ulong registerMemBase3D1 = 0;
67 module_param(registerMemBase3D1, ulong, 0644);
69 static ulong registerMemSize3D1 = 2 << 10;
70 module_param(registerMemSize3D1, ulong, 0644);
72 static int irqLine = -1;
73 module_param(irqLine, int, 0644);
75 static ulong registerMemBase = 0x80000000;
76 module_param(registerMemBase, ulong, 0644);
78 static ulong registerMemSize = 2 << 10;
79 module_param(registerMemSize, ulong, 0644);
82 static int irqLine2D = -1;
83 module_param(irqLine2D, int, 0644);
85 static ulong registerMemBase2D = 0x00000000;
86 module_param(registerMemBase2D, ulong, 0644);
88 static ulong registerMemSize2D = 2 << 10;
89 module_param(registerMemSize2D, ulong, 0644);
91 static int irqLineVG = -1;
92 module_param(irqLineVG, int, 0644);
94 static ulong registerMemBaseVG = 0x00000000;
95 module_param(registerMemBaseVG, ulong, 0644);
97 static ulong registerMemSizeVG = 2 << 10;
98 module_param(registerMemSizeVG, ulong, 0644);
100 #ifndef gcdDEFAULT_CONTIGUOUS_SIZE
101 #define gcdDEFAULT_CONTIGUOUS_SIZE (4 << 20)
103 static ulong contiguousSize = gcdDEFAULT_CONTIGUOUS_SIZE;
104 module_param(contiguousSize, ulong, 0644);
106 static ulong contiguousBase = 0;
107 module_param(contiguousBase, ulong, 0644);
109 static ulong bankSize = 0;
110 module_param(bankSize, ulong, 0644);
112 static int fastClear = -1;
113 module_param(fastClear, int, 0644);
115 static int compression = -1;
116 module_param(compression, int, 0644);
118 static int powerManagement = -1;
119 module_param(powerManagement, int, 0644);
121 static int gpuProfiler = 0;
122 module_param(gpuProfiler, int, 0644);
124 static int signal = 48;
125 module_param(signal, int, 0644);
127 static ulong baseAddress = 0;
128 module_param(baseAddress, ulong, 0644);
130 static ulong physSize = 0;
131 module_param(physSize, ulong, 0644);
133 static uint logFileSize = 0;
134 module_param(logFileSize,uint, 0644);
136 static uint recovery = 1;
137 module_param(recovery, uint, 0644);
138 MODULE_PARM_DESC(recovery, "Recover GPU from stuck (1: Enable, 0: Disable)");
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)");
145 static int showArgs = 0;
146 module_param(showArgs, int, 0644);
149 module_param(mmu, int, 0644);
151 static int gpu3DMinClock = 1;
153 static int contiguousRequested = 0;
160 static int drv_release(
165 static long drv_ioctl(
167 unsigned int ioctlCode,
173 struct vm_area_struct* vma
176 static struct file_operations driver_fops =
178 .owner = THIS_MODULE,
180 .release = drv_release,
181 .unlocked_ioctl = drv_ioctl,
182 #ifdef HAVE_COMPAT_IOCTL
183 .compat_ioctl = drv_ioctl,
190 gcsMODULE_PARAMETERS *Param
193 #if gcdMULTI_GPU || gcdMULTI_GPU_AFFINITY
195 irqLine = Param->irqLine ;
196 registerMemBase = Param->registerMemBase;
197 registerMemSize = Param->registerMemSize;
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;
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);
234 if (irqLine3D1 != -1)
236 printk(" irqLine3D1 = %d\n", irqLine3D1);
237 printk(" registerMemBase3D1 = 0x%08lX\n", registerMemBase3D1);
238 printk(" registerMemSize3D1 = 0x%08lX\n", registerMemSize3D1);
241 printk(" irqLine = %d\n", irqLine);
242 printk(" registerMemBase = 0x%08lX\n", registerMemBase);
243 printk(" registerMemSize = 0x%08lX\n", registerMemSize);
248 printk(" irqLine2D = %d\n", irqLine2D);
249 printk(" registerMemBase2D = 0x%08lX\n", registerMemBase2D);
250 printk(" registerMemSize2D = 0x%08lX\n", registerMemSize2D);
255 printk(" irqLineVG = %d\n", irqLineVG);
256 printk(" registerMemBaseVG = 0x%08lX\n", registerMemBaseVG);
257 printk(" registerMemSizeVG = 0x%08lX\n", registerMemSizeVG);
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);
281 gctBOOL attached = gcvFALSE;
282 gcsHAL_PRIVATE_DATA_PTR data = gcvNULL;
285 gcmkHEADER_ARG("inode=0x%08X filp=0x%08X", inode, filp);
290 gcvLEVEL_ERROR, gcvZONE_DRIVER,
291 "%s(%d): filp is NULL\n",
292 __FUNCTION__, __LINE__
295 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
298 data = kmalloc(sizeof(gcsHAL_PRIVATE_DATA), GFP_KERNEL | __GFP_NOWARN);
303 gcvLEVEL_ERROR, gcvZONE_DRIVER,
304 "%s(%d): private_data is NULL\n",
305 __FUNCTION__, __LINE__
308 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
311 data->device = galDevice;
312 data->mappedMemory = gcvNULL;
313 data->contiguousLogical = gcvNULL;
314 gcmkONERROR(gckOS_GetProcessID(&data->pidOpen));
316 /* Attached the process. */
317 for (i = 0; i < gcdMAX_GPU_COUNT; i++)
319 if (galDevice->kernels[i] != gcvNULL)
321 gcmkONERROR(gckKERNEL_AttachProcess(galDevice->kernels[i], gcvTRUE));
326 if (!galDevice->contiguousMapped)
328 if (galDevice->contiguousPhysical != gcvNULL)
330 gcmkONERROR(gckOS_MapMemory(
332 galDevice->contiguousPhysical,
333 galDevice->contiguousSize,
334 &data->contiguousLogical
339 filp->private_data = data;
348 if (data->contiguousLogical != gcvNULL)
350 gcmkVERIFY_OK(gckOS_UnmapMemory(
352 galDevice->contiguousPhysical,
353 galDevice->contiguousSize,
354 data->contiguousLogical
363 for (i = 0; i < gcdMAX_GPU_COUNT; i++)
365 if (galDevice->kernels[i] != gcvNULL)
367 gcmkVERIFY_OK(gckKERNEL_AttachProcess(galDevice->kernels[i], gcvFALSE));
382 gcsHAL_PRIVATE_DATA_PTR data;
386 gcmkHEADER_ARG("inode=0x%08X filp=0x%08X", inode, filp);
391 gcvLEVEL_ERROR, gcvZONE_DRIVER,
392 "%s(%d): filp is NULL\n",
393 __FUNCTION__, __LINE__
396 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
399 data = filp->private_data;
404 gcvLEVEL_ERROR, gcvZONE_DRIVER,
405 "%s(%d): private_data is NULL\n",
406 __FUNCTION__, __LINE__
409 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
412 device = data->device;
414 if (device == gcvNULL)
417 gcvLEVEL_ERROR, gcvZONE_DRIVER,
418 "%s(%d): device is NULL\n",
419 __FUNCTION__, __LINE__
422 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
425 if (!device->contiguousMapped)
427 if (data->contiguousLogical != gcvNULL)
429 gcmkONERROR(gckOS_UnmapMemoryEx(
431 galDevice->contiguousPhysical,
432 galDevice->contiguousSize,
433 data->contiguousLogical,
437 data->contiguousLogical = gcvNULL;
441 /* A process gets detached. */
442 for (i = 0; i < gcdMAX_GPU_COUNT; i++)
444 if (galDevice->kernels[i] != gcvNULL)
446 gcmkONERROR(gckKERNEL_AttachProcessEx(galDevice->kernels[i], gcvFALSE, data->pidOpen));
451 filp->private_data = NULL;
464 unsigned int ioctlCode,
469 gcsHAL_INTERFACE iface;
473 gcsHAL_PRIVATE_DATA_PTR data;
475 gckVIDMEM_NODE nodeObject;
478 "filp=0x%08X ioctlCode=0x%08X arg=0x%08X",
485 gcvLEVEL_ERROR, gcvZONE_DRIVER,
486 "%s(%d): filp is NULL\n",
487 __FUNCTION__, __LINE__
490 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
493 data = filp->private_data;
498 gcvLEVEL_ERROR, gcvZONE_DRIVER,
499 "%s(%d): private_data is NULL\n",
500 __FUNCTION__, __LINE__
503 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
506 device = data->device;
508 if (device == gcvNULL)
511 gcvLEVEL_ERROR, gcvZONE_DRIVER,
512 "%s(%d): device is NULL\n",
513 __FUNCTION__, __LINE__
516 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
519 if ((ioctlCode != IOCTL_GCHAL_INTERFACE)
520 && (ioctlCode != IOCTL_GCHAL_KERNEL_INTERFACE)
524 gcvLEVEL_ERROR, gcvZONE_DRIVER,
525 "%s(%d): unknown command %d\n",
526 __FUNCTION__, __LINE__,
530 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
533 /* Get the drvArgs. */
534 copyLen = copy_from_user(
535 &drvArgs, (void *) arg, sizeof(DRIVER_ARGS)
541 gcvLEVEL_ERROR, gcvZONE_DRIVER,
542 "%s(%d): error copying of the input arguments.\n",
543 __FUNCTION__, __LINE__
546 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
549 /* Now bring in the gcsHAL_INTERFACE structure. */
550 if ((drvArgs.InputBufferSize != sizeof(gcsHAL_INTERFACE))
551 || (drvArgs.OutputBufferSize != sizeof(gcsHAL_INTERFACE))
555 gcvLEVEL_ERROR, gcvZONE_DRIVER,
556 "%s(%d): input or/and output structures are invalid.\n",
557 __FUNCTION__, __LINE__
560 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
563 copyLen = copy_from_user(
564 &iface, gcmUINT64_TO_PTR(drvArgs.InputBuffer), sizeof(gcsHAL_INTERFACE)
570 gcvLEVEL_ERROR, gcvZONE_DRIVER,
571 "%s(%d): error copying of input HAL interface.\n",
572 __FUNCTION__, __LINE__
575 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
578 if (iface.command == gcvHAL_CHIP_INFO)
581 for (i = 0; i < gcdMAX_GPU_COUNT; i++)
583 if (device->kernels[i] != gcvNULL)
588 iface.u.ChipInfo.types[count] = gcvHARDWARE_VG;
593 gcmkVERIFY_OK(gckHARDWARE_GetType(device->kernels[i]->hardware,
594 &iface.u.ChipInfo.types[count]));
600 iface.u.ChipInfo.count = count;
601 iface.status = status = gcvSTATUS_OK;
605 if (iface.hardwareType > 7)
608 gcvLEVEL_ERROR, gcvZONE_DRIVER,
609 "%s(%d): unknown hardwareType %d\n",
610 __FUNCTION__, __LINE__,
614 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
618 if (device->coreMapping[iface.hardwareType] == gcvCORE_VG)
620 status = gckVGKERNEL_Dispatch(device->kernels[gcvCORE_VG],
621 (ioctlCode == IOCTL_GCHAL_INTERFACE),
627 status = gckKERNEL_Dispatch(device->kernels[device->coreMapping[iface.hardwareType]],
628 (ioctlCode == IOCTL_GCHAL_INTERFACE),
633 /* Redo system call after pending signal is handled. */
634 if (status == gcvSTATUS_INTERRUPTED)
640 if (gcmIS_SUCCESS(status) && (iface.command == gcvHAL_LOCK_VIDEO_MEMORY))
642 gcuVIDMEM_NODE_PTR node;
645 gckOS_GetProcessID(&processID);
647 gcmkONERROR(gckVIDMEM_HANDLE_Lookup(device->kernels[device->coreMapping[iface.hardwareType]],
649 (gctUINT32)iface.u.LockVideoMemory.node,
651 node = nodeObject->node;
653 /* Special case for mapped memory. */
654 if ((data->mappedMemory != gcvNULL)
655 && (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
658 /* Compute offset into mapped memory. */
660 = (gctUINT8 *) gcmUINT64_TO_PTR(iface.u.LockVideoMemory.memory)
661 - (gctUINT8 *) device->contiguousBase;
663 /* Compute offset into user-mapped region. */
664 iface.u.LockVideoMemory.memory =
665 gcmPTR_TO_UINT64((gctUINT8 *) data->mappedMemory + offset);
669 /* Copy data back to the user. */
670 copyLen = copy_to_user(
671 gcmUINT64_TO_PTR(drvArgs.OutputBuffer), &iface, sizeof(gcsHAL_INTERFACE)
677 gcvLEVEL_ERROR, gcvZONE_DRIVER,
678 "%s(%d): error copying of output HAL interface.\n",
679 __FUNCTION__, __LINE__
682 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
696 struct vm_area_struct* vma
699 gceSTATUS status = gcvSTATUS_OK;
700 gcsHAL_PRIVATE_DATA_PTR data;
703 gcmkHEADER_ARG("filp=0x%08X vma=0x%08X", filp, vma);
708 gcvLEVEL_ERROR, gcvZONE_DRIVER,
709 "%s(%d): filp is NULL\n",
710 __FUNCTION__, __LINE__
713 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
716 data = filp->private_data;
721 gcvLEVEL_ERROR, gcvZONE_DRIVER,
722 "%s(%d): private_data is NULL\n",
723 __FUNCTION__, __LINE__
726 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
729 device = data->device;
731 if (device == gcvNULL)
734 gcvLEVEL_ERROR, gcvZONE_DRIVER,
735 "%s(%d): device is NULL\n",
736 __FUNCTION__, __LINE__
739 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
742 #if !gcdPAGED_MEMORY_CACHEABLE
743 vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
744 vma->vm_flags |= gcdVM_FLAGS;
748 if (device->contiguousMapped)
750 unsigned long size = vma->vm_end - vma->vm_start;
753 if (size > device->contiguousSize)
756 gcvLEVEL_ERROR, gcvZONE_DRIVER,
757 "%s(%d): Invalid mapping size.\n",
758 __FUNCTION__, __LINE__
761 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
764 ret = io_remap_pfn_range(
767 device->requestedContiguousBase >> PAGE_SHIFT,
775 gcvLEVEL_ERROR, gcvZONE_DRIVER,
776 "%s(%d): io_remap_pfn_range failed %d\n",
777 __FUNCTION__, __LINE__,
781 data->mappedMemory = gcvNULL;
783 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
786 data->mappedMemory = (gctPOINTER) vma->vm_start;
799 #if !USE_PLATFORM_DRIVER
800 static int __init drv_init(void)
802 static int drv_init(void)
806 int result = -EINVAL;
808 gckGALDEVICE device = gcvNULL;
809 struct class* device_class = gcvNULL;
811 gcsDEVICE_CONSTRUCT_ARGS args = {
812 .recovery = recovery,
813 .stuckDump = stuckDump,
814 .gpu3DMinClock = gpu3DMinClock,
815 .contiguousRequested = contiguousRequested,
816 .platform = &platform,
822 printk(KERN_INFO "Galcore version %d.%d.%d.%d\n",
823 gcvVERSION_MAJOR, gcvVERSION_MINOR, gcvVERSION_PATCH, gcvVERSION_BUILD);
825 #if !VIVANTE_PROFILER_PM
826 /* when enable gpu profiler, we need to turn off gpu powerMangement */
838 if (logFileSize != 0)
840 gckDEBUGFS_Initialize();
843 /* Create the GAL device. */
844 status = gckGALDEVICE_Construct(
845 #if gcdMULTI_GPU || gcdMULTI_GPU_AFFINITY
847 registerMemBase3D0, registerMemSize3D0,
849 registerMemBase3D1, registerMemSize3D1,
852 registerMemBase, registerMemSize,
855 registerMemBase2D, registerMemSize2D,
857 registerMemBaseVG, registerMemSizeVG,
858 contiguousBase, contiguousSize,
859 bankSize, fastClear, compression, baseAddress, physSize, signal,
867 if (gcmIS_ERROR(status))
869 gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
870 "%s(%d): Failed to create the GAL device: status=%d\n",
871 __FUNCTION__, __LINE__, status);
876 /* Start the GAL device. */
877 gcmkONERROR(gckGALDEVICE_Start(device));
880 && (device->kernels[gcvCORE_MAJOR] != gcvNULL)
881 && (device->kernels[gcvCORE_MAJOR]->hardware->mmuVersion != 0))
883 /* Reset the base address */
884 device->baseAddress = 0;
887 /* Register the character device. */
888 ret = register_chrdev(major, DEVICE_NAME, &driver_fops);
893 gcvLEVEL_ERROR, gcvZONE_DRIVER,
894 "%s(%d): Could not allocate major number for mmap.\n",
895 __FUNCTION__, __LINE__
898 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
906 /* Create the device class. */
907 device_class = class_create(THIS_MODULE, "graphics_class");
909 if (IS_ERR(device_class))
912 gcvLEVEL_ERROR, gcvZONE_DRIVER,
913 "%s(%d): Failed to create the class.\n",
914 __FUNCTION__, __LINE__
917 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
920 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
921 device_create(device_class, NULL, MKDEV(major, 0), NULL, DEVICE_NAME);
923 device_create(device_class, NULL, MKDEV(major, 0), DEVICE_NAME);
927 gpuClass = device_class;
929 #if gcdMULTI_GPU || gcdMULTI_GPU_AFFINITY
931 gcvLEVEL_INFO, gcvZONE_DRIVER,
932 "%s(%d): irqLine3D0=%d, contiguousSize=%lu, memBase3D0=0x%lX\n",
933 __FUNCTION__, __LINE__,
934 irqLine3D0, contiguousSize, registerMemBase3D0
938 gcvLEVEL_INFO, gcvZONE_DRIVER,
939 "%s(%d): irqLine=%d, contiguousSize=%lu, memBase=0x%lX\n",
940 __FUNCTION__, __LINE__,
941 irqLine, contiguousSize, registerMemBase
951 if (device_class != gcvNULL)
953 device_destroy(device_class, MKDEV(major, 0));
954 class_destroy(device_class);
957 if (device != gcvNULL)
959 gcmkVERIFY_OK(gckGALDEVICE_Stop(device));
960 gcmkVERIFY_OK(gckGALDEVICE_Destroy(device));
967 #if !USE_PLATFORM_DRIVER
968 static void __exit drv_exit(void)
970 static void drv_exit(void)
975 gcmkASSERT(gpuClass != gcvNULL);
976 device_destroy(gpuClass, MKDEV(major, 0));
977 class_destroy(gpuClass);
979 unregister_chrdev(major, DEVICE_NAME);
981 gcmkVERIFY_OK(gckGALDEVICE_Stop(galDevice));
982 gcmkVERIFY_OK(gckGALDEVICE_Destroy(galDevice));
984 if(gckDEBUGFS_IsEnabled())
986 gckDEBUGFS_Terminate();
992 #if !USE_PLATFORM_DRIVER
993 module_init(drv_init);
994 module_exit(drv_exit);
997 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
998 static int gpu_probe(struct platform_device *pdev)
1000 static int __devinit gpu_probe(struct platform_device *pdev)
1004 gcsMODULE_PARAMETERS moduleParam = {
1005 #if gcdMULTI_GPU || gcdMULTI_GPU_AFFINITY
1008 .registerMemBase = registerMemBase,
1009 .registerMemSize = registerMemSize,
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,
1025 .baseAddress = baseAddress,
1026 .physSize = physSize,
1027 .logFileSize = logFileSize,
1028 .recovery = recovery,
1029 .stuckDump = stuckDump,
1030 .showArgs = showArgs,
1031 .gpu3DMinClock = gpu3DMinClock,
1036 platform.device = pdev;
1038 if (platform.ops->getPower)
1040 if (gcmIS_ERROR(platform.ops->getPower(&platform)))
1047 if (platform.ops->adjustParam)
1049 /* Override default module param. */
1050 platform.ops->adjustParam(&platform, &moduleParam);
1052 /* Update module param because drv_init() uses them directly. */
1053 _UpdateModuleParam(&moduleParam);
1060 platform_set_drvdata(pdev, galDevice);
1066 gcmkFOOTER_ARG(KERN_INFO "Failed to register gpu driver: %d\n", ret);
1070 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
1071 static int gpu_remove(struct platform_device *pdev)
1073 static int __devexit gpu_remove(struct platform_device *pdev)
1080 if (platform.ops->putPower)
1082 platform.ops->putPower(&platform);
1089 static int gpu_suspend(struct platform_device *dev, pm_message_t state)
1092 gckGALDEVICE device;
1095 device = platform_get_drvdata(dev);
1102 for (i = 0; i < gcdMAX_GPU_COUNT; i++)
1104 if (device->kernels[i] != gcvNULL)
1108 if (i == gcvCORE_VG)
1110 status = gckVGHARDWARE_QueryPowerManagementState(device->kernels[i]->vg->hardware, &device->statesStored[i]);
1115 status = gckHARDWARE_QueryPowerManagementState(device->kernels[i]->hardware, &device->statesStored[i]);
1118 if (gcmIS_ERROR(status))
1124 if (i == gcvCORE_VG)
1126 status = gckVGHARDWARE_SetPowerManagementState(device->kernels[i]->vg->hardware, gcvPOWER_OFF);
1131 status = gckHARDWARE_SetPowerManagementState(device->kernels[i]->hardware, gcvPOWER_OFF);
1134 if (gcmIS_ERROR(status))
1145 static int gpu_resume(struct platform_device *dev)
1148 gckGALDEVICE device;
1150 gceCHIPPOWERSTATE statesStored;
1152 device = platform_get_drvdata(dev);
1159 for (i = 0; i < gcdMAX_GPU_COUNT; i++)
1161 if (device->kernels[i] != gcvNULL)
1164 if (i == gcvCORE_VG)
1166 status = gckVGHARDWARE_SetPowerManagementState(device->kernels[i]->vg->hardware, gcvPOWER_ON);
1171 status = gckHARDWARE_SetPowerManagementState(device->kernels[i]->hardware, gcvPOWER_ON);
1174 if (gcmIS_ERROR(status))
1179 /* Convert global state to crossponding internal state. */
1180 switch(device->statesStored[i])
1183 statesStored = gcvPOWER_OFF_BROADCAST;
1186 statesStored = gcvPOWER_IDLE_BROADCAST;
1188 case gcvPOWER_SUSPEND:
1189 statesStored = gcvPOWER_SUSPEND_BROADCAST;
1192 statesStored = gcvPOWER_ON_AUTO;
1195 statesStored = device->statesStored[i];
1199 /* Restore states. */
1201 if (i == gcvCORE_VG)
1203 status = gckVGHARDWARE_SetPowerManagementState(device->kernels[i]->vg->hardware, statesStored);
1208 status = gckHARDWARE_SetPowerManagementState(device->kernels[i]->hardware, statesStored);
1211 if (gcmIS_ERROR(status))
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)
1225 pm_message_t state={0};
1226 return gpu_suspend(to_platform_device(dev), state);
1229 static int gpu_system_resume(struct device *dev)
1231 return gpu_resume(to_platform_device(dev));
1235 static const struct dev_pm_ops gpu_pm_ops = {
1236 SET_SYSTEM_SLEEP_PM_OPS(gpu_system_suspend, gpu_system_resume)
1240 static struct platform_driver gpu_driver = {
1242 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
1243 .remove = gpu_remove,
1245 .remove = __devexit_p(gpu_remove),
1248 .suspend = gpu_suspend,
1249 .resume = gpu_resume,
1252 .name = DEVICE_NAME,
1253 #if defined(CONFIG_PM) && LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
1259 static int __init gpu_init(void)
1263 memset(&platform, 0, sizeof(gcsPLATFORM));
1265 gckPLATFORM_QueryOperations(&platform.ops);
1267 if (platform.ops == gcvNULL)
1269 printk(KERN_ERR "galcore: No platform specific operations.\n");
1274 if (platform.ops->allocPriv)
1276 /* Allocate platform private data. */
1277 if (gcmIS_ERROR(platform.ops->allocPriv(&platform)))
1284 if (platform.ops->needAddDevice
1285 && platform.ops->needAddDevice(&platform))
1287 /* Allocate device */
1288 platform.device = platform_device_alloc(DEVICE_NAME, -1);
1289 if (!platform.device)
1291 printk(KERN_ERR "galcore: platform_device_alloc failed.\n");
1297 ret = platform_device_add(platform.device);
1300 printk(KERN_ERR "galcore: platform_device_add failed.\n");
1305 platform.driver = &gpu_driver;
1307 if (platform.ops->adjustDriver)
1309 /* Override default platform_driver struct. */
1310 platform.ops->adjustDriver(&platform);
1313 ret = platform_driver_register(&gpu_driver);
1319 platform_device_del(platform.device);
1321 platform_device_put(platform.device);
1327 static void __exit gpu_exit(void)
1329 platform_driver_unregister(&gpu_driver);
1331 if (platform.ops->needAddDevice
1332 && platform.ops->needAddDevice(&platform))
1334 platform_device_unregister(platform.device);
1339 /* Free platform private data. */
1340 platform.ops->freePriv(&platform);
1344 module_init(gpu_init);
1345 module_exit(gpu_exit);