1 /****************************************************************************
3 * Copyright (C) 2005 - 2013 by Vivante Corp.
4 * Copyright (C) 2011-2012 Freescale Semiconductor, Inc.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the license, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 *****************************************************************************/
23 #include <linux/device.h>
24 #include <linux/slab.h>
25 #include <linux/notifier.h>
26 #include "gc_hal_kernel_linux.h"
27 #include "gc_hal_driver.h"
29 #if USE_PLATFORM_DRIVER
30 # include <linux/platform_device.h>
33 #ifdef CONFIG_PXA_DVFM
34 # include <mach/dvfm.h>
35 # include <mach/pxa3xx_dvfm.h>
39 #ifdef CONFIG_ANDROID_RESERVED_MEMORY_ACCOUNT
40 # include <linux/resmem_account.h>
41 # include <linux/kernel.h>
42 # include <linux/mm.h>
43 # include <linux/oom.h>
44 # include <linux/sched.h>
45 # include <linux/notifier.h>
47 struct task_struct *lowmem_deathpending;
50 task_notify_func(struct notifier_block *self, unsigned long val, void *data);
52 static struct notifier_block task_nb = {
53 .notifier_call = task_notify_func,
57 task_notify_func(struct notifier_block *self, unsigned long val, void *data)
59 struct task_struct *task = data;
61 if (task == lowmem_deathpending)
62 lowmem_deathpending = NULL;
68 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
69 #include <mach/viv_gpu.h>
71 #include <linux/pm_runtime.h>
72 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
73 #include <mach/busfreq.h>
75 #include <linux/reset.h>
78 /* Zone used for header/footer. */
79 #define _GC_OBJ_ZONE gcvZONE_DRIVER
81 #if gcdENABLE_FSCALE_VAL_ADJUST
82 extern int register_thermal_notifier(struct notifier_block *nb);
83 extern int unregister_thermal_notifier(struct notifier_block *nb);
86 MODULE_DESCRIPTION("Vivante Graphics Driver");
87 MODULE_LICENSE("GPL");
89 static struct class* gpuClass;
91 static gckGALDEVICE galDevice;
93 static uint major = 199;
94 module_param(major, uint, 0644);
96 static int irqLine = -1;
97 module_param(irqLine, int, 0644);
99 static ulong registerMemBase = 0x80000000;
100 module_param(registerMemBase, ulong, 0644);
102 static ulong registerMemSize = 2 << 10;
103 module_param(registerMemSize, ulong, 0644);
105 static int irqLine2D = -1;
106 module_param(irqLine2D, int, 0644);
108 static ulong registerMemBase2D = 0x00000000;
109 module_param(registerMemBase2D, ulong, 0644);
111 static ulong registerMemSize2D = 2 << 10;
112 module_param(registerMemSize2D, ulong, 0644);
114 static int irqLineVG = -1;
115 module_param(irqLineVG, int, 0644);
117 static ulong registerMemBaseVG = 0x00000000;
118 module_param(registerMemBaseVG, ulong, 0644);
120 static ulong registerMemSizeVG = 2 << 10;
121 module_param(registerMemSizeVG, ulong, 0644);
123 #if gcdENABLE_FSCALE_VAL_ADJUST
124 static ulong contiguousSize = 128 << 20;
126 static ulong contiguousSize = 4 << 20;
128 module_param(contiguousSize, ulong, 0644);
130 static ulong contiguousBase = 0;
131 module_param(contiguousBase, ulong, 0644);
133 static ulong bankSize = 0;
134 module_param(bankSize, ulong, 0644);
136 static int fastClear = -1;
137 module_param(fastClear, int, 0644);
139 static int compression = -1;
140 module_param(compression, int, 0644);
142 static int powerManagement = 1;
143 module_param(powerManagement, int, 0644);
145 static int signal = 48;
146 module_param(signal, int, 0644);
148 static ulong baseAddress = 0;
149 module_param(baseAddress, ulong, 0644);
151 static ulong physSize = 0;
152 module_param(physSize, ulong, 0644);
154 static uint logFileSize=0;
155 module_param(logFileSize,uint, 0644);
157 static int showArgs = 0;
158 module_param(showArgs, int, 0644);
160 int gpu3DMinClock = 0;
161 module_param(gpu3DMinClock, int, 0644);
163 #if ENABLE_GPU_CLOCK_BY_DRIVER
164 unsigned long coreClock = 156000000;
165 module_param(coreClock, ulong, 0644);
173 static int drv_release(
178 static long drv_ioctl(
180 unsigned int ioctlCode,
186 struct vm_area_struct* vma
189 static struct file_operations driver_fops =
191 .owner = THIS_MODULE,
193 .release = drv_release,
194 .unlocked_ioctl = drv_ioctl,
195 #ifdef HAVE_COMPAT_IOCTL
196 .compat_ioctl = drv_ioctl,
201 #ifdef CONFIG_ANDROID_RESERVED_MEMORY_ACCOUNT
202 static size_t viv_gpu_resmem_query(struct task_struct *p, struct reserved_memory_account *m);
203 static struct reserved_memory_account viv_gpu_resmem_handler = {
205 .get_page_used_by_process = viv_gpu_resmem_query,
208 size_t viv_gpu_resmem_query(struct task_struct *p, struct reserved_memory_account *m)
210 gcuDATABASE_INFO info;
211 unsigned int processid = p->pid;
212 gckKERNEL gpukernel = m->data;
214 /* ignore error happens in this api. */
215 if (gckKERNEL_QueryProcessDB(gpukernel, processid, false, gcvDB_VIDEO_MEMORY, &info) != gcvSTATUS_OK)
218 /* we return pages. */
219 if (info.counters.bytes > 0)
220 return info.counters.bytes / PAGE_SIZE;
231 gctBOOL attached = gcvFALSE;
232 gcsHAL_PRIVATE_DATA_PTR data = gcvNULL;
235 gcmkHEADER_ARG("inode=0x%08X filp=0x%08X", inode, filp);
240 gcvLEVEL_ERROR, gcvZONE_DRIVER,
241 "%s(%d): filp is NULL\n",
242 __FUNCTION__, __LINE__
245 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
248 data = kmalloc(sizeof(gcsHAL_PRIVATE_DATA), GFP_KERNEL | __GFP_NOWARN);
253 gcvLEVEL_ERROR, gcvZONE_DRIVER,
254 "%s(%d): private_data is NULL\n",
255 __FUNCTION__, __LINE__
258 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
261 data->device = galDevice;
262 data->mappedMemory = gcvNULL;
263 data->contiguousLogical = gcvNULL;
264 gcmkONERROR(gckOS_GetProcessID(&data->pidOpen));
266 /* Attached the process. */
267 for (i = 0; i < gcdMAX_GPU_COUNT; i++)
269 if (galDevice->kernels[i] != gcvNULL)
271 gcmkONERROR(gckKERNEL_AttachProcess(galDevice->kernels[i], gcvTRUE));
276 if (!galDevice->contiguousMapped)
278 gcmkONERROR(gckOS_MapMemory(
280 galDevice->contiguousPhysical,
281 galDevice->contiguousSize,
282 &data->contiguousLogical
286 filp->private_data = data;
295 if (data->contiguousLogical != gcvNULL)
297 gcmkVERIFY_OK(gckOS_UnmapMemory(
299 galDevice->contiguousPhysical,
300 galDevice->contiguousSize,
301 data->contiguousLogical
310 for (i = 0; i < gcdMAX_GPU_COUNT; i++)
312 if (galDevice->kernels[i] != gcvNULL)
314 gcmkVERIFY_OK(gckKERNEL_AttachProcess(galDevice->kernels[i], gcvFALSE));
329 gcsHAL_PRIVATE_DATA_PTR data;
333 gcmkHEADER_ARG("inode=0x%08X filp=0x%08X", inode, filp);
338 gcvLEVEL_ERROR, gcvZONE_DRIVER,
339 "%s(%d): filp is NULL\n",
340 __FUNCTION__, __LINE__
343 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
346 data = filp->private_data;
351 gcvLEVEL_ERROR, gcvZONE_DRIVER,
352 "%s(%d): private_data is NULL\n",
353 __FUNCTION__, __LINE__
356 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
359 device = data->device;
361 if (device == gcvNULL)
364 gcvLEVEL_ERROR, gcvZONE_DRIVER,
365 "%s(%d): device is NULL\n",
366 __FUNCTION__, __LINE__
369 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
372 if (!device->contiguousMapped)
374 if (data->contiguousLogical != gcvNULL)
376 gcmkONERROR(gckOS_UnmapMemoryEx(
378 galDevice->contiguousPhysical,
379 galDevice->contiguousSize,
380 data->contiguousLogical,
384 data->contiguousLogical = gcvNULL;
388 /* A process gets detached. */
389 for (i = 0; i < gcdMAX_GPU_COUNT; i++)
391 if (galDevice->kernels[i] != gcvNULL)
393 gcmkONERROR(gckKERNEL_AttachProcessEx(galDevice->kernels[i], gcvFALSE, data->pidOpen));
398 filp->private_data = NULL;
411 unsigned int ioctlCode,
416 gcsHAL_INTERFACE iface;
420 gcsHAL_PRIVATE_DATA_PTR data;
424 "filp=0x%08X ioctlCode=0x%08X arg=0x%08X",
431 gcvLEVEL_ERROR, gcvZONE_DRIVER,
432 "%s(%d): filp is NULL\n",
433 __FUNCTION__, __LINE__
436 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
439 data = filp->private_data;
444 gcvLEVEL_ERROR, gcvZONE_DRIVER,
445 "%s(%d): private_data is NULL\n",
446 __FUNCTION__, __LINE__
449 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
452 device = data->device;
454 if (device == gcvNULL)
457 gcvLEVEL_ERROR, gcvZONE_DRIVER,
458 "%s(%d): device is NULL\n",
459 __FUNCTION__, __LINE__
462 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
465 if ((ioctlCode != IOCTL_GCHAL_INTERFACE)
466 && (ioctlCode != IOCTL_GCHAL_KERNEL_INTERFACE)
470 gcvLEVEL_ERROR, gcvZONE_DRIVER,
471 "%s(%d): unknown command %d\n",
472 __FUNCTION__, __LINE__,
476 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
479 /* Get the drvArgs. */
480 copyLen = copy_from_user(
481 &drvArgs, (void *) arg, sizeof(DRIVER_ARGS)
487 gcvLEVEL_ERROR, gcvZONE_DRIVER,
488 "%s(%d): error copying of the input arguments.\n",
489 __FUNCTION__, __LINE__
492 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
495 /* Now bring in the gcsHAL_INTERFACE structure. */
496 if ((drvArgs.InputBufferSize != sizeof(gcsHAL_INTERFACE))
497 || (drvArgs.OutputBufferSize != sizeof(gcsHAL_INTERFACE))
501 gcvLEVEL_ERROR, gcvZONE_DRIVER,
502 "%s(%d): input or/and output structures are invalid.\n",
503 __FUNCTION__, __LINE__
506 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
509 copyLen = copy_from_user(
510 &iface, gcmUINT64_TO_PTR(drvArgs.InputBuffer), sizeof(gcsHAL_INTERFACE)
516 gcvLEVEL_ERROR, gcvZONE_DRIVER,
517 "%s(%d): error copying of input HAL interface.\n",
518 __FUNCTION__, __LINE__
521 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
524 if (iface.command == gcvHAL_CHIP_INFO)
527 for (i = 0; i < gcdMAX_GPU_COUNT; i++)
529 if (device->kernels[i] != gcvNULL)
534 iface.u.ChipInfo.types[count] = gcvHARDWARE_VG;
539 gcmkVERIFY_OK(gckHARDWARE_GetType(device->kernels[i]->hardware,
540 &iface.u.ChipInfo.types[count]));
546 iface.u.ChipInfo.count = count;
547 iface.status = status = gcvSTATUS_OK;
551 if (iface.hardwareType < 0 || iface.hardwareType > 7)
554 gcvLEVEL_ERROR, gcvZONE_DRIVER,
555 "%s(%d): unknown hardwareType %d\n",
556 __FUNCTION__, __LINE__,
560 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
564 if (device->coreMapping[iface.hardwareType] == gcvCORE_VG)
566 status = gckVGKERNEL_Dispatch(device->kernels[gcvCORE_VG],
567 (ioctlCode == IOCTL_GCHAL_INTERFACE),
573 status = gckKERNEL_Dispatch(device->kernels[device->coreMapping[iface.hardwareType]],
574 (ioctlCode == IOCTL_GCHAL_INTERFACE),
579 /* Redo system call after pending signal is handled. */
580 if (status == gcvSTATUS_INTERRUPTED)
586 if (gcmIS_SUCCESS(status) && (iface.command == gcvHAL_LOCK_VIDEO_MEMORY))
588 gcuVIDMEM_NODE_PTR node = gcmUINT64_TO_PTR(iface.u.LockVideoMemory.node);
589 /* Special case for mapped memory. */
590 if ((data->mappedMemory != gcvNULL)
591 && (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
594 /* Compute offset into mapped memory. */
596 = (gctUINT8 *) gcmUINT64_TO_PTR(iface.u.LockVideoMemory.memory)
597 - (gctUINT8 *) device->contiguousBase;
599 /* Compute offset into user-mapped region. */
600 iface.u.LockVideoMemory.memory =
601 gcmPTR_TO_UINT64((gctUINT8 *) data->mappedMemory + offset);
605 /* Copy data back to the user. */
606 copyLen = copy_to_user(
607 gcmUINT64_TO_PTR(drvArgs.OutputBuffer), &iface, sizeof(gcsHAL_INTERFACE)
613 gcvLEVEL_ERROR, gcvZONE_DRIVER,
614 "%s(%d): error copying of output HAL interface.\n",
615 __FUNCTION__, __LINE__
618 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
632 struct vm_area_struct* vma
635 gceSTATUS status = gcvSTATUS_OK;
636 gcsHAL_PRIVATE_DATA_PTR data;
639 gcmkHEADER_ARG("filp=0x%08X vma=0x%08X", filp, vma);
644 gcvLEVEL_ERROR, gcvZONE_DRIVER,
645 "%s(%d): filp is NULL\n",
646 __FUNCTION__, __LINE__
649 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
652 data = filp->private_data;
657 gcvLEVEL_ERROR, gcvZONE_DRIVER,
658 "%s(%d): private_data is NULL\n",
659 __FUNCTION__, __LINE__
662 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
665 device = data->device;
667 if (device == gcvNULL)
670 gcvLEVEL_ERROR, gcvZONE_DRIVER,
671 "%s(%d): device is NULL\n",
672 __FUNCTION__, __LINE__
675 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
678 #if !gcdPAGED_MEMORY_CACHEABLE
679 vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
680 vma->vm_flags |= gcdVM_FLAGS;
684 if (device->contiguousMapped)
686 unsigned long size = vma->vm_end - vma->vm_start;
689 if (size > device->contiguousSize)
692 gcvLEVEL_ERROR, gcvZONE_DRIVER,
693 "%s(%d): Invalid mapping size.\n",
694 __FUNCTION__, __LINE__
697 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
700 ret = io_remap_pfn_range(
703 device->requestedContiguousBase >> PAGE_SHIFT,
711 gcvLEVEL_ERROR, gcvZONE_DRIVER,
712 "%s(%d): io_remap_pfn_range failed %d\n",
713 __FUNCTION__, __LINE__,
717 data->mappedMemory = gcvNULL;
719 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
722 data->mappedMemory = (gctPOINTER) vma->vm_start;
736 #if !USE_PLATFORM_DRIVER
737 static int __init drv_init(void)
739 static int drv_init(struct device *pdev)
743 int result = -EINVAL;
745 gckGALDEVICE device = gcvNULL;
746 struct class* device_class = gcvNULL;
750 #if ENABLE_GPU_CLOCK_BY_DRIVER && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28))
755 clk = clk_get(NULL, "GCCLK");
760 gcvLEVEL_ERROR, gcvZONE_DRIVER,
761 "%s(%d): clk get error: %d\n",
762 __FUNCTION__, __LINE__,
767 gcmkONERROR(gcvSTATUS_GENERIC_IO);
771 * APMU_GC_156M, APMU_GC_312M, APMU_GC_PLL2, APMU_GC_PLL2_DIV2 currently.
774 if (clk_set_rate(clk, coreClock * 2))
777 gcvLEVEL_ERROR, gcvZONE_DRIVER,
778 "%s(%d): Failed to set core clock.\n",
779 __FUNCTION__, __LINE__
783 gcmkONERROR(gcvSTATUS_GENERIC_IO);
788 #if defined(CONFIG_PXA_DVFM) && (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
795 printk(KERN_INFO "Galcore version %d.%d.%d.%d\n",
796 gcvVERSION_MAJOR, gcvVERSION_MINOR, gcvVERSION_PATCH, gcvVERSION_BUILD);
800 printk("galcore options:\n");
801 printk(" irqLine = %d\n", irqLine);
802 printk(" registerMemBase = 0x%08lX\n", registerMemBase);
803 printk(" registerMemSize = 0x%08lX\n", registerMemSize);
807 printk(" irqLine2D = %d\n", irqLine2D);
808 printk(" registerMemBase2D = 0x%08lX\n", registerMemBase2D);
809 printk(" registerMemSize2D = 0x%08lX\n", registerMemSize2D);
814 printk(" irqLineVG = %d\n", irqLineVG);
815 printk(" registerMemBaseVG = 0x%08lX\n", registerMemBaseVG);
816 printk(" registerMemSizeVG = 0x%08lX\n", registerMemSizeVG);
819 printk(" contiguousSize = %ld\n", contiguousSize);
820 printk(" contiguousBase = 0x%08lX\n", contiguousBase);
821 printk(" bankSize = 0x%08lX\n", bankSize);
822 printk(" fastClear = %d\n", fastClear);
823 printk(" compression = %d\n", compression);
824 printk(" signal = %d\n", signal);
825 printk(" baseAddress = 0x%08lX\n", baseAddress);
826 printk(" physSize = 0x%08lX\n", physSize);
827 printk(" logFileSize = %d KB \n", logFileSize);
828 printk(" powerManagement = %d\n", powerManagement);
829 #if ENABLE_GPU_CLOCK_BY_DRIVER
830 printk(" coreClock = %lu\n", coreClock);
836 gckDebugFileSystemInitialize();
839 /* Create the GAL device. */
840 gcmkONERROR(gckGALDEVICE_Construct(
842 registerMemBase, registerMemSize,
844 registerMemBase2D, registerMemSize2D,
846 registerMemBaseVG, registerMemSizeVG,
847 contiguousBase, contiguousSize,
848 bankSize, fastClear, compression, baseAddress, physSize, signal,
855 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
856 device->pool = dev_get_drvdata(pdev);
859 /* Start the GAL device. */
860 gcmkONERROR(gckGALDEVICE_Start(device));
863 && (device->kernels[gcvCORE_MAJOR] != gcvNULL)
864 && (device->kernels[gcvCORE_MAJOR]->hardware->mmuVersion != 0))
866 status = gckMMU_Enable(device->kernels[gcvCORE_MAJOR]->mmu, baseAddress, physSize);
867 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
868 "Enable new MMU: status=%d\n", status);
870 if ((device->kernels[gcvCORE_2D] != gcvNULL)
871 && (device->kernels[gcvCORE_2D]->hardware->mmuVersion != 0))
873 status = gckMMU_Enable(device->kernels[gcvCORE_2D]->mmu, baseAddress, physSize);
874 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
875 "Enable new MMU for 2D: status=%d\n", status);
878 /* Reset the base address */
879 device->baseAddress = 0;
882 #ifdef CONFIG_ANDROID_RESERVED_MEMORY_ACCOUNT
883 task_free_register(&task_nb);
884 viv_gpu_resmem_handler.data = device->kernels[gcvCORE_MAJOR];
885 register_reserved_memory_account(&viv_gpu_resmem_handler);
889 /* Register the character device. */
890 ret = register_chrdev(major, DRV_NAME, &driver_fops);
895 gcvLEVEL_ERROR, gcvZONE_DRIVER,
896 "%s(%d): Could not allocate major number for mmap.\n",
897 __FUNCTION__, __LINE__
900 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
908 /* Create the device class. */
909 device_class = class_create(THIS_MODULE, "graphics_class");
911 if (IS_ERR(device_class))
914 gcvLEVEL_ERROR, gcvZONE_DRIVER,
915 "%s(%d): Failed to create the class.\n",
916 __FUNCTION__, __LINE__
919 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
922 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
923 device_create(device_class, NULL, MKDEV(major, 0), NULL, "galcore");
925 device_create(device_class, NULL, MKDEV(major, 0), "galcore");
929 gpuClass = device_class;
932 gcvLEVEL_INFO, gcvZONE_DRIVER,
933 "%s(%d): irqLine=%d, contiguousSize=%lu, memBase=0x%lX\n",
934 __FUNCTION__, __LINE__,
935 irqLine, contiguousSize, registerMemBase
944 if (device_class != gcvNULL)
946 device_destroy(device_class, MKDEV(major, 0));
947 class_destroy(device_class);
950 if (device != gcvNULL)
952 gcmkVERIFY_OK(gckGALDEVICE_Stop(device));
953 gcmkVERIFY_OK(gckGALDEVICE_Destroy(device));
960 #if !USE_PLATFORM_DRIVER
961 static void __exit drv_exit(void)
963 static void drv_exit(void)
968 #ifdef CONFIG_ANDROID_RESERVED_MEMORY_ACCOUNT
969 task_free_unregister(&task_nb);
970 unregister_reserved_memory_account(&viv_gpu_resmem_handler);
973 gcmkASSERT(gpuClass != gcvNULL);
974 device_destroy(gpuClass, MKDEV(major, 0));
975 class_destroy(gpuClass);
977 unregister_chrdev(major, DRV_NAME);
979 gcmkVERIFY_OK(gckGALDEVICE_Stop(galDevice));
980 gcmkVERIFY_OK(gckGALDEVICE_Destroy(galDevice));
982 if(gckDebugFileSystemIsEnabled())
984 gckDebugFileSystemTerminate();
987 #if ENABLE_GPU_CLOCK_BY_DRIVER && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
990 struct clk * clk = NULL;
992 #if defined(CONFIG_PXA_DVFM) && (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
995 clk = clk_get(NULL, "GCCLK");
1004 #if !USE_PLATFORM_DRIVER
1005 module_init(drv_init);
1006 module_exit(drv_exit);
1009 #ifdef CONFIG_DOVE_GPU
1010 # define DEVICE_NAME "dove_gpu"
1012 # define DEVICE_NAME "galcore"
1015 #if gcdENABLE_FSCALE_VAL_ADJUST
1016 static int thermal_hot_pm_notify(struct notifier_block *nb, unsigned long event,
1019 static gctUINT orgFscale, minFscale, maxFscale;
1020 static gctBOOL bAlreadyTooHot = gcvFALSE;
1021 gckHARDWARE hardware = galDevice->kernels[gcvCORE_MAJOR]->hardware;
1023 if (event && !bAlreadyTooHot) {
1024 gckHARDWARE_GetFscaleValue(hardware,&orgFscale,&minFscale, &maxFscale);
1025 gckHARDWARE_SetFscaleValue(hardware, minFscale);
1026 bAlreadyTooHot = gcvTRUE;
1027 gckOS_Print("System is too hot. GPU3D will work at %d/64 clock.\n", minFscale);
1028 } else if (!event && bAlreadyTooHot) {
1029 gckHARDWARE_SetFscaleValue(hardware, orgFscale);
1030 gckOS_Print("Hot alarm is canceled. GPU3D clock will return to %d/64\n", orgFscale);
1031 bAlreadyTooHot = gcvFALSE;
1036 static struct notifier_block thermal_hot_pm_notifier = {
1037 .notifier_call = thermal_hot_pm_notify,
1043 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
1044 static int gpu_probe(struct platform_device *pdev)
1046 static int __devinit gpu_probe(struct platform_device *pdev)
1050 struct resource* res;
1051 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
1052 struct contiguous_mem_pool *pool;
1053 struct reset_control *rstc;
1054 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
1055 struct device_node *dn =pdev->dev.of_node;
1058 struct viv_gpu_platform_data *pdata;
1062 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phys_baseaddr");
1064 baseAddress = res->start;
1066 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq_3d");
1068 irqLine = res->start;
1070 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iobase_3d");
1073 registerMemBase = res->start;
1074 registerMemSize = res->end - res->start + 1;
1077 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq_2d");
1079 irqLine2D = res->start;
1081 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iobase_2d");
1084 registerMemBase2D = res->start;
1085 registerMemSize2D = res->end - res->start + 1;
1088 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq_vg");
1090 irqLineVG = res->start;
1092 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iobase_vg");
1095 registerMemBaseVG = res->start;
1096 registerMemSizeVG = res->end - res->start + 1;
1099 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
1100 pool = devm_kzalloc(&pdev->dev, sizeof(*pool), GFP_KERNEL);
1103 pool->size = contiguousSize;
1104 init_dma_attrs(&pool->attrs);
1105 dma_set_attr(DMA_ATTR_WRITE_COMBINE, &pool->attrs);
1106 pool->virt = dma_alloc_attrs(&pdev->dev, pool->size, &pool->phys,
1107 GFP_KERNEL, &pool->attrs);
1109 dev_err(&pdev->dev, "Failed to allocate contiguous memory\n");
1112 contiguousBase = pool->phys;
1113 dev_set_drvdata(&pdev->dev, pool);
1114 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
1115 prop = of_get_property(dn, "contiguousbase", NULL);
1117 contiguousBase = *prop;
1118 of_property_read_u32(dn,"contiguoussize", (u32 *)&contiguousSize);
1120 pdata = pdev->dev.platform_data;
1122 contiguousBase = pdata->reserved_mem_base;
1123 contiguousSize = pdata->reserved_mem_size;
1126 if (contiguousSize == 0)
1127 gckOS_Print("Warning: No contiguous memory is reserverd for gpu.!\n ");
1128 ret = drv_init(&pdev->dev);
1132 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
1133 rstc = devm_reset_control_get(&pdev->dev, "gpu3d");
1134 galDevice->rstc[gcvCORE_MAJOR] = IS_ERR(rstc) ? NULL : rstc;
1136 rstc = devm_reset_control_get(&pdev->dev, "gpu2d");
1137 galDevice->rstc[gcvCORE_2D] = IS_ERR(rstc) ? NULL : rstc;
1139 rstc = devm_reset_control_get(&pdev->dev, "gpuvg");
1140 galDevice->rstc[gcvCORE_VG] = IS_ERR(rstc) ? NULL : rstc;
1142 platform_set_drvdata(pdev, galDevice);
1144 #if gcdENABLE_FSCALE_VAL_ADJUST
1145 if(galDevice->kernels[gcvCORE_MAJOR])
1146 register_thermal_notifier(&thermal_hot_pm_notifier);
1151 #if gcdENABLE_FSCALE_VAL_ADJUST
1152 unregister_thermal_notifier(&thermal_hot_pm_notifier);
1154 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
1155 dma_free_attrs(&pdev->dev, pool->size, pool->virt, pool->phys,
1158 gcmkFOOTER_ARG(KERN_INFO "Failed to register gpu driver: %d\n", ret);
1162 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
1163 static int gpu_remove(struct platform_device *pdev)
1165 static int __devexit gpu_remove(struct platform_device *pdev)
1168 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
1169 gckGALDEVICE device = platform_get_drvdata(pdev);
1170 struct contiguous_mem_pool *pool = device->pool;
1173 #if gcdENABLE_FSCALE_VAL_ADJUST
1174 if(galDevice->kernels[gcvCORE_MAJOR])
1175 unregister_thermal_notifier(&thermal_hot_pm_notifier);
1178 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
1179 dma_free_attrs(&pdev->dev, pool->size, pool->virt, pool->phys,
1186 static int gpu_suspend(struct platform_device *dev, pm_message_t state)
1189 gckGALDEVICE device;
1192 device = platform_get_drvdata(dev);
1194 for (i = 0; i < gcdMAX_GPU_COUNT; i++)
1196 if (device->kernels[i] != gcvNULL)
1200 if (i == gcvCORE_VG)
1202 status = gckVGHARDWARE_QueryPowerManagementState(device->kernels[i]->vg->hardware, &device->statesStored[i]);
1207 status = gckHARDWARE_QueryPowerManagementState(device->kernels[i]->hardware, &device->statesStored[i]);
1210 if (gcmIS_ERROR(status))
1216 if (i == gcvCORE_VG)
1218 status = gckVGHARDWARE_SetPowerManagementState(device->kernels[i]->vg->hardware, gcvPOWER_OFF);
1223 status = gckHARDWARE_SetPowerManagementState(device->kernels[i]->hardware, gcvPOWER_OFF);
1225 if (gcmIS_ERROR(status))
1236 static int gpu_resume(struct platform_device *dev)
1239 gckGALDEVICE device;
1241 gceCHIPPOWERSTATE statesStored;
1243 device = platform_get_drvdata(dev);
1245 for (i = 0; i < gcdMAX_GPU_COUNT; i++)
1247 if (device->kernels[i] != gcvNULL)
1250 if (i == gcvCORE_VG)
1252 status = gckVGHARDWARE_SetPowerManagementState(device->kernels[i]->vg->hardware, gcvPOWER_ON);
1257 status = gckHARDWARE_SetPowerManagementState(device->kernels[i]->hardware, gcvPOWER_ON);
1260 if (gcmIS_ERROR(status))
1265 /* Convert global state to crossponding internal state. */
1266 switch(device->statesStored[i])
1269 statesStored = gcvPOWER_OFF_BROADCAST;
1272 statesStored = gcvPOWER_IDLE_BROADCAST;
1274 case gcvPOWER_SUSPEND:
1275 statesStored = gcvPOWER_SUSPEND_BROADCAST;
1278 statesStored = gcvPOWER_ON_AUTO;
1281 statesStored = device->statesStored[i];
1285 /* Restore states. */
1287 if (i == gcvCORE_VG)
1289 status = gckVGHARDWARE_SetPowerManagementState(device->kernels[i]->vg->hardware, statesStored);
1294 status = gckHARDWARE_SetPowerManagementState(device->kernels[i]->hardware, statesStored);
1297 if (gcmIS_ERROR(status))
1307 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
1308 static const struct of_device_id mxs_gpu_dt_ids[] = {
1309 { .compatible = "fsl,imx6q-gpu", },
1312 MODULE_DEVICE_TABLE(of, mxs_gpu_dt_ids);
1315 static int gpu_runtime_suspend(struct device *dev)
1317 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
1318 release_bus_freq(BUS_FREQ_HIGH);
1323 static int gpu_runtime_resume(struct device *dev)
1325 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
1326 request_bus_freq(BUS_FREQ_HIGH);
1331 static int gpu_system_suspend(struct device *dev)
1333 pm_message_t state={0};
1334 return gpu_suspend(to_platform_device(dev), state);
1337 static int gpu_system_resume(struct device *dev)
1339 return gpu_resume(to_platform_device(dev));
1342 static const struct dev_pm_ops gpu_pm_ops = {
1343 SET_RUNTIME_PM_OPS(gpu_runtime_suspend, gpu_runtime_resume, NULL)
1344 SET_SYSTEM_SLEEP_PM_OPS(gpu_system_suspend, gpu_system_resume)
1349 static struct platform_driver gpu_driver = {
1351 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
1352 .remove = gpu_remove,
1354 .remove = __devexit_p(gpu_remove),
1357 .suspend = gpu_suspend,
1358 .resume = gpu_resume,
1361 .name = DEVICE_NAME,
1362 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
1363 .of_match_table = mxs_gpu_dt_ids,
1371 #if 0 /*CONFIG_DOVE_GPU*/
1372 static struct resource gpu_resources[] = {
1375 .flags = IORESOURCE_IRQ,
1379 .flags = IORESOURCE_MEM,
1383 .flags = IORESOURCE_MEM,
1387 static struct platform_device * gpu_device;
1390 static int __init gpu_init(void)
1394 #if 0 /*ndef CONFIG_DOVE_GPU*/
1395 gpu_resources[0].start = gpu_resources[0].end = irqLine;
1397 gpu_resources[1].start = registerMemBase;
1398 gpu_resources[1].end = registerMemBase + registerMemSize - 1;
1400 gpu_resources[2].start = contiguousBase;
1401 gpu_resources[2].end = contiguousBase + contiguousSize - 1;
1403 /* Allocate device */
1404 gpu_device = platform_device_alloc(DEVICE_NAME, -1);
1407 printk(KERN_ERR "galcore: platform_device_alloc failed.\n");
1412 /* Insert resource */
1413 ret = platform_device_add_resources(gpu_device, gpu_resources, 3);
1416 printk(KERN_ERR "galcore: platform_device_add_resources failed.\n");
1421 ret = platform_device_add(gpu_device);
1424 printk(KERN_ERR "galcore: platform_device_add failed.\n");
1429 ret = platform_driver_register(&gpu_driver);
1435 #if 0 /*ndef CONFIG_DOVE_GPU*/
1436 platform_device_del(gpu_device);
1438 platform_device_put(gpu_device);
1445 static void __exit gpu_exit(void)
1447 platform_driver_unregister(&gpu_driver);
1448 #if 0 /*ndef CONFIG_DOVE_GPU*/
1449 platform_device_unregister(gpu_device);
1453 module_init(gpu_init);
1454 module_exit(gpu_exit);