ENGR00156850 gpu-viv: add gpu-viv driver source
[wandboard.git] / drivers / mxc / gpu-viv / hal / os / linux / kernel / gc_hal_kernel_driver.c
bloba826b2438a7362ac6ea321a9c1b99ac205f9ab42
1 /****************************************************************************
3 * Copyright (C) 2005 - 2011 by Vivante Corp.
4 * Copyright (C) 2011 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 *****************************************************************************/
25 #include <linux/device.h>
26 #include <linux/slab.h>
27 #include <mach/viv_gpu.h>
29 #include "gc_hal_kernel_linux.h"
30 #include "gc_hal_driver.h"
32 #if USE_PLATFORM_DRIVER
33 # include <linux/platform_device.h>
34 #endif
36 #ifdef CONFIG_PXA_DVFM
37 # include <mach/dvfm.h>
38 # include <mach/pxa3xx_dvfm.h>
39 #endif
42 /* Zone used for header/footer. */
43 #define _GC_OBJ_ZONE gcvZONE_DRIVER
45 MODULE_DESCRIPTION("Vivante Graphics Driver");
46 MODULE_LICENSE("GPL");
48 static struct class* gpuClass;
50 static gckGALDEVICE galDevice;
52 static int major = 199;
53 module_param(major, int, 0644);
55 static int irqLine = -1;
56 module_param(irqLine, int, 0644);
58 static long registerMemBase = 0x80000000;
59 module_param(registerMemBase, long, 0644);
61 static ulong registerMemSize = 256 << 10;
62 module_param(registerMemSize, ulong, 0644);
64 static int irqLine2D = -1;
65 module_param(irqLine2D, int, 0644);
67 static long registerMemBase2D = 0x00000000;
68 module_param(registerMemBase2D, long, 0644);
70 static ulong registerMemSize2D = 256 << 10;
71 module_param(registerMemSize2D, ulong, 0644);
73 static int irqLineVG = -1;
74 module_param(irqLineVG, int, 0644);
76 static long registerMemBaseVG = 0x00000000;
77 module_param(registerMemBaseVG, long, 0644);
79 static ulong registerMemSizeVG = 256 << 10;
80 module_param(registerMemSizeVG, ulong, 0644);
82 static long contiguousSize = 4 << 20;
83 module_param(contiguousSize, long, 0644);
85 static ulong contiguousBase = 0;
86 module_param(contiguousBase, ulong, 0644);
88 static long bankSize = 32 << 20;
89 module_param(bankSize, long, 0644);
91 static int fastClear = -1;
92 module_param(fastClear, int, 0644);
94 static int compression = -1;
95 module_param(compression, int, 0644);
97 static int signal = 48;
98 module_param(signal, int, 0644);
100 static ulong baseAddress = 0;
101 module_param(baseAddress, ulong, 0644);
103 static ulong physSize = 0;
104 module_param(physSize, ulong, 0644);
106 static int showArgs = 0;
107 module_param(showArgs, int, 0644);
109 #if ENABLE_GPU_CLOCK_BY_DRIVER
110 unsigned long coreClock = 156000000;
111 module_param(coreClock, ulong, 0644);
112 #endif
114 static struct clk * clk_3d_core;
115 static struct clk * clk_3d_shader;
116 static struct clk * clk_2d_core;
118 static int drv_open(
119 struct inode* inode,
120 struct file* filp
123 static int drv_release(
124 struct inode* inode,
125 struct file* filp
128 static long drv_ioctl(
129 struct file* filp,
130 unsigned int ioctlCode,
131 unsigned long arg
134 static int drv_mmap(
135 struct file* filp,
136 struct vm_area_struct* vma
139 static struct file_operations driver_fops =
141 .open = drv_open,
142 .release = drv_release,
143 .unlocked_ioctl = drv_ioctl,
144 .mmap = drv_mmap,
147 int drv_open(
148 struct inode* inode,
149 struct file* filp
152 gceSTATUS status;
153 gctBOOL attached = gcvFALSE;
154 gcsHAL_PRIVATE_DATA_PTR data = gcvNULL;
155 gctINT i;
157 gcmkHEADER_ARG("inode=0x%08X filp=0x%08X", inode, filp);
159 if (filp == gcvNULL)
161 gcmkTRACE_ZONE(
162 gcvLEVEL_ERROR, gcvZONE_DRIVER,
163 "%s(%d): filp is NULL\n",
164 __FUNCTION__, __LINE__
167 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
170 data = kmalloc(sizeof(gcsHAL_PRIVATE_DATA), GFP_KERNEL);
172 if (data == gcvNULL)
174 gcmkTRACE_ZONE(
175 gcvLEVEL_ERROR, gcvZONE_DRIVER,
176 "%s(%d): private_data is NULL\n",
177 __FUNCTION__, __LINE__
180 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
183 data->device = galDevice;
184 data->mappedMemory = gcvNULL;
185 data->contiguousLogical = gcvNULL;
186 gcmkONERROR(gckOS_GetProcessID(&data->pidOpen));
188 /* Attached the process. */
189 for (i = 0; i < gcdCORE_COUNT; i++)
191 if (galDevice->kernels[i] != gcvNULL)
193 gcmkONERROR(gckKERNEL_AttachProcess(galDevice->kernels[i], gcvTRUE));
196 attached = gcvTRUE;
198 if (!galDevice->contiguousMapped)
200 gcmkONERROR(gckOS_MapMemory(
201 galDevice->os,
202 galDevice->contiguousPhysical,
203 galDevice->contiguousSize,
204 &data->contiguousLogical
208 filp->private_data = data;
210 /* Success. */
211 gcmkFOOTER_NO();
212 return 0;
214 OnError:
215 if (data != gcvNULL)
217 if (data->contiguousLogical != gcvNULL)
219 gcmkVERIFY_OK(gckOS_UnmapMemory(
220 galDevice->os,
221 galDevice->contiguousPhysical,
222 galDevice->contiguousSize,
223 data->contiguousLogical
227 kfree(data);
230 if (attached)
232 for (i = 0; i < gcdCORE_COUNT; i++)
234 if (galDevice->kernels[i] != gcvNULL)
236 gcmkVERIFY_OK(gckKERNEL_AttachProcess(galDevice->kernels[i], gcvFALSE));
241 gcmkFOOTER();
242 return -ENOTTY;
245 int drv_release(
246 struct inode* inode,
247 struct file* filp
250 gceSTATUS status;
251 gcsHAL_PRIVATE_DATA_PTR data;
252 gckGALDEVICE device;
253 gctINT i;
255 gcmkHEADER_ARG("inode=0x%08X filp=0x%08X", inode, filp);
257 if (filp == gcvNULL)
259 gcmkTRACE_ZONE(
260 gcvLEVEL_ERROR, gcvZONE_DRIVER,
261 "%s(%d): filp is NULL\n",
262 __FUNCTION__, __LINE__
265 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
268 data = filp->private_data;
270 if (data == gcvNULL)
272 gcmkTRACE_ZONE(
273 gcvLEVEL_ERROR, gcvZONE_DRIVER,
274 "%s(%d): private_data is NULL\n",
275 __FUNCTION__, __LINE__
278 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
281 device = data->device;
283 if (device == gcvNULL)
285 gcmkTRACE_ZONE(
286 gcvLEVEL_ERROR, gcvZONE_DRIVER,
287 "%s(%d): device is NULL\n",
288 __FUNCTION__, __LINE__
291 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
294 if (!device->contiguousMapped)
296 if (data->contiguousLogical != gcvNULL)
298 gctUINT32 processID;
299 gcmkVERIFY_OK(gckOS_GetProcessID(&processID));
300 gcmkONERROR(gckOS_UnmapMemoryEx(
301 galDevice->os,
302 galDevice->contiguousPhysical,
303 galDevice->contiguousSize,
304 data->contiguousLogical,
305 data->pidOpen
308 for (i = 0; i < gcdCORE_COUNT; i++)
310 if (galDevice->kernels[i] != gcvNULL)
312 gcmkVERIFY_OK(
313 gckKERNEL_RemoveProcessDB(galDevice->kernels[i],
314 processID, gcvDB_MAP_MEMORY,
315 data->contiguousLogical));
319 data->contiguousLogical = gcvNULL;
323 /* A process gets detached. */
324 for (i = 0; i < gcdCORE_COUNT; i++)
326 if (galDevice->kernels[i] != gcvNULL)
328 gcmkONERROR(gckKERNEL_AttachProcessEx(galDevice->kernels[i], gcvFALSE, data->pidOpen));
332 kfree(data);
333 filp->private_data = NULL;
335 /* Success. */
336 gcmkFOOTER_NO();
337 return 0;
339 OnError:
340 gcmkFOOTER();
341 return -ENOTTY;
344 long drv_ioctl(
345 struct file* filp,
346 unsigned int ioctlCode,
347 unsigned long arg
350 gceSTATUS status;
351 gcsHAL_INTERFACE iface;
352 gctUINT32 copyLen;
353 DRIVER_ARGS drvArgs;
354 gckGALDEVICE device;
355 gcsHAL_PRIVATE_DATA_PTR data;
356 gctINT32 i, count;
358 gcmkHEADER_ARG(
359 "filp=0x%08X ioctlCode=0x%08X arg=0x%08X",
360 filp, ioctlCode, arg
363 if (filp == gcvNULL)
365 gcmkTRACE_ZONE(
366 gcvLEVEL_ERROR, gcvZONE_DRIVER,
367 "%s(%d): filp is NULL\n",
368 __FUNCTION__, __LINE__
371 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
374 data = filp->private_data;
376 if (data == gcvNULL)
378 gcmkTRACE_ZONE(
379 gcvLEVEL_ERROR, gcvZONE_DRIVER,
380 "%s(%d): private_data is NULL\n",
381 __FUNCTION__, __LINE__
384 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
387 device = data->device;
389 if (device == gcvNULL)
391 gcmkTRACE_ZONE(
392 gcvLEVEL_ERROR, gcvZONE_DRIVER,
393 "%s(%d): device is NULL\n",
394 __FUNCTION__, __LINE__
397 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
400 if ((ioctlCode != IOCTL_GCHAL_INTERFACE)
401 && (ioctlCode != IOCTL_GCHAL_KERNEL_INTERFACE)
404 gcmkTRACE_ZONE(
405 gcvLEVEL_ERROR, gcvZONE_DRIVER,
406 "%s(%d): unknown command %d\n",
407 __FUNCTION__, __LINE__,
408 ioctlCode
411 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
414 /* Get the drvArgs. */
415 copyLen = copy_from_user(
416 &drvArgs, (void *) arg, sizeof(DRIVER_ARGS)
419 if (copyLen != 0)
421 gcmkTRACE_ZONE(
422 gcvLEVEL_ERROR, gcvZONE_DRIVER,
423 "%s(%d): error copying of the input arguments.\n",
424 __FUNCTION__, __LINE__
427 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
430 /* Now bring in the gcsHAL_INTERFACE structure. */
431 if ((drvArgs.InputBufferSize != sizeof(gcsHAL_INTERFACE))
432 || (drvArgs.OutputBufferSize != sizeof(gcsHAL_INTERFACE))
435 gcmkTRACE_ZONE(
436 gcvLEVEL_ERROR, gcvZONE_DRIVER,
437 "%s(%d): input or/and output structures are invalid.\n",
438 __FUNCTION__, __LINE__
441 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
444 copyLen = copy_from_user(
445 &iface, drvArgs.InputBuffer, sizeof(gcsHAL_INTERFACE)
448 if (copyLen != 0)
450 gcmkTRACE_ZONE(
451 gcvLEVEL_ERROR, gcvZONE_DRIVER,
452 "%s(%d): error copying of input HAL interface.\n",
453 __FUNCTION__, __LINE__
456 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
459 if (iface.command == gcvHAL_CHIP_INFO)
461 count = 0;
462 for (i = 0; i < gcdCORE_COUNT; i++)
464 if (device->kernels[i] != gcvNULL)
466 #if gcdENABLE_VG
467 if (i == gcvCORE_VG)
469 iface.u.ChipInfo.types[count] = gcvHARDWARE_VG;
471 else
472 #endif
474 gcmkVERIFY_OK(gckHARDWARE_GetType(device->kernels[i]->hardware,
475 &iface.u.ChipInfo.types[count]));
477 count++;
481 iface.u.ChipInfo.count = count;
482 status = gcvSTATUS_OK;
484 else
486 if (iface.hardwareType < 0 || iface.hardwareType > 7)
488 gcmkTRACE_ZONE(
489 gcvLEVEL_ERROR, gcvZONE_DRIVER,
490 "%s(%d): unknown hardwareType %d\n",
491 __FUNCTION__, __LINE__,
492 iface.hardwareType
495 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
498 #if gcdENABLE_VG
499 if (device->coreMapping[iface.hardwareType] == gcvCORE_VG)
501 status = gckVGKERNEL_Dispatch(device->kernels[gcvCORE_VG],
502 (ioctlCode == IOCTL_GCHAL_INTERFACE),
503 &iface);
505 else
506 #endif
508 status = gckKERNEL_Dispatch(device->kernels[device->coreMapping[iface.hardwareType]],
509 (ioctlCode == IOCTL_GCHAL_INTERFACE),
510 &iface);
514 if (gcmIS_SUCCESS(status) && (iface.command == gcvHAL_LOCK_VIDEO_MEMORY))
516 /* Special case for mapped memory. */
517 if ((data->mappedMemory != gcvNULL)
518 && (iface.u.LockVideoMemory.node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
521 /* Compute offset into mapped memory. */
522 gctUINT32 offset
523 = (gctUINT8 *) iface.u.LockVideoMemory.memory
524 - (gctUINT8 *) device->contiguousBase;
526 /* Compute offset into user-mapped region. */
527 iface.u.LockVideoMemory.memory =
528 (gctUINT8 *) data->mappedMemory + offset;
532 /* Copy data back to the user. */
533 copyLen = copy_to_user(
534 drvArgs.OutputBuffer, &iface, sizeof(gcsHAL_INTERFACE)
537 if (copyLen != 0)
539 gcmkTRACE_ZONE(
540 gcvLEVEL_ERROR, gcvZONE_DRIVER,
541 "%s(%d): error copying of output HAL interface.\n",
542 __FUNCTION__, __LINE__
545 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
548 /* Success. */
549 gcmkFOOTER_NO();
550 return 0;
552 OnError:
553 gcmkFOOTER();
554 return -ENOTTY;
557 static int drv_mmap(
558 struct file* filp,
559 struct vm_area_struct* vma
562 gceSTATUS status;
563 gcsHAL_PRIVATE_DATA_PTR data;
564 gckGALDEVICE device;
566 gcmkHEADER_ARG("filp=0x%08X vma=0x%08X", filp, vma);
568 if (filp == gcvNULL)
570 gcmkTRACE_ZONE(
571 gcvLEVEL_ERROR, gcvZONE_DRIVER,
572 "%s(%d): filp is NULL\n",
573 __FUNCTION__, __LINE__
576 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
579 data = filp->private_data;
581 if (data == gcvNULL)
583 gcmkTRACE_ZONE(
584 gcvLEVEL_ERROR, gcvZONE_DRIVER,
585 "%s(%d): private_data is NULL\n",
586 __FUNCTION__, __LINE__
589 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
592 device = data->device;
594 if (device == gcvNULL)
596 gcmkTRACE_ZONE(
597 gcvLEVEL_ERROR, gcvZONE_DRIVER,
598 "%s(%d): device is NULL\n",
599 __FUNCTION__, __LINE__
602 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
605 #if !gcdPAGED_MEMORY_CACHEABLE
606 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
607 vma->vm_flags |= VM_IO | VM_DONTCOPY | VM_DONTEXPAND;
608 #endif
609 vma->vm_pgoff = 0;
611 if (device->contiguousMapped)
613 unsigned long size = vma->vm_end - vma->vm_start;
615 int ret = io_remap_pfn_range(
616 vma,
617 vma->vm_start,
618 (gctUINT32) device->contiguousPhysical >> PAGE_SHIFT,
619 size,
620 vma->vm_page_prot
623 if (ret != 0)
625 gcmkTRACE_ZONE(
626 gcvLEVEL_ERROR, gcvZONE_DRIVER,
627 "%s(%d): io_remap_pfn_range failed %d\n",
628 __FUNCTION__, __LINE__,
632 data->mappedMemory = gcvNULL;
634 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
637 data->mappedMemory = (gctPOINTER) vma->vm_start;
640 /* Success. */
641 gcmkFOOTER_NO();
642 return 0;
644 OnError:
645 gcmkFOOTER();
646 return -ENOTTY;
650 #if !USE_PLATFORM_DRIVER
651 static int __init drv_init(void)
652 #else
653 static int drv_init(void)
654 #endif
656 int ret;
657 int result = -EINVAL;
658 gceSTATUS status;
659 gckGALDEVICE device = gcvNULL;
660 struct class* device_class = gcvNULL;
662 gcmkHEADER();
664 #if ENABLE_GPU_CLOCK_BY_DRIVER && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28))
666 # if 0
667 struct clk * clk;
669 clk = clk_get(NULL, "GCCLK");
671 if (IS_ERR(clk))
673 gcmkTRACE_ZONE(
674 gcvLEVEL_ERROR, gcvZONE_DRIVER,
675 "%s(%d): clk get error: %d\n",
676 __FUNCTION__, __LINE__,
677 PTR_ERR(clk)
680 result = -ENODEV;
681 gcmkONERROR(gcvSTATUS_GENERIC_IO);
685 * APMU_GC_156M, APMU_GC_312M, APMU_GC_PLL2, APMU_GC_PLL2_DIV2 currently.
686 * Use the 2X clock.
688 if (clk_set_rate(clk, coreClock * 2))
690 gcmkTRACE_ZONE(
691 gcvLEVEL_ERROR, gcvZONE_DRIVER,
692 "%s(%d): Failed to set core clock.\n",
693 __FUNCTION__, __LINE__
696 result = -EAGAIN;
697 gcmkONERROR(gcvSTATUS_GENERIC_IO);
700 clk_enable(clk);
702 #if defined(CONFIG_PXA_DVFM) && (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
703 gc_pwr(1);
704 # endif
705 # else
706 if (irqLine != -1) {
707 clk_3d_core = clk_get(NULL, "gpu3d_clk");
708 if (!IS_ERR(clk_3d_core)) {
709 clk_3d_shader = clk_get(NULL, "gpu3d_shader_clk");
710 if (!IS_ERR(clk_3d_shader)) {
711 clk_enable(clk_3d_core);
712 clk_enable(clk_3d_shader);
713 } else {
714 irqLine = -1;
715 clk_put(clk_3d_core);
716 clk_3d_core = NULL;
717 clk_3d_shader = NULL;
718 printk(KERN_ERR "galcore: clk_get gpu3d_shader_clk failed, disable 3d!\n");
720 } else {
721 irqLine = -1;
722 clk_3d_core = NULL;
723 printk(KERN_ERR "galcore: clk_get gpu3d_clk failed, disable 3d!\n");
726 if ((irqLine2D != -1) || (irqLineVG != -1)) {
727 clk_2d_core = clk_get(NULL, "gpu2d_clk");
728 if (IS_ERR(clk_2d_core)) {
729 irqLine2D = -1;
730 irqLineVG = -1;
731 clk_2d_core = NULL;
732 printk(KERN_ERR "galcore: clk_get 2d clock failed, disable 2d/vg!\n");
733 } else {
734 clk_enable(clk_2d_core);
737 # endif
739 #endif
741 if (showArgs)
743 printk("galcore options:\n");
744 printk(" irqLine = %d\n", irqLine);
745 printk(" registerMemBase = 0x%08lX\n", registerMemBase);
746 printk(" registerMemSize = 0x%08lX\n", registerMemSize);
748 if (irqLine2D != -1)
750 printk(" irqLine2D = %d\n", irqLine2D);
751 printk(" registerMemBase2D = 0x%08lX\n", registerMemBase2D);
752 printk(" registerMemSize2D = 0x%08lX\n", registerMemSize2D);
755 if (irqLineVG != -1)
757 printk(" irqLineVG = %d\n", irqLineVG);
758 printk(" registerMemBaseVG = 0x%08lX\n", registerMemBaseVG);
759 printk(" registerMemSizeVG = 0x%08lX\n", registerMemSizeVG);
762 printk(" contiguousSize = %ld\n", contiguousSize);
763 printk(" contiguousBase = 0x%08lX\n", contiguousBase);
764 printk(" bankSize = 0x%08lX\n", bankSize);
765 printk(" fastClear = %d\n", fastClear);
766 printk(" compression = %d\n", compression);
767 printk(" signal = %d\n", signal);
768 printk(" baseAddress = 0x%08lX\n", baseAddress);
769 printk(" physSize = 0x%08lX\n", physSize);
770 #if ENABLE_GPU_CLOCK_BY_DRIVER
771 printk(" coreClock = %lu\n", coreClock);
772 #endif
775 /* Create the GAL device. */
776 gcmkONERROR(gckGALDEVICE_Construct(
777 irqLine,
778 registerMemBase, registerMemSize,
779 irqLine2D,
780 registerMemBase2D, registerMemSize2D,
781 irqLineVG,
782 registerMemBaseVG, registerMemSizeVG,
783 contiguousBase, contiguousSize,
784 bankSize, fastClear, compression, baseAddress, physSize, signal,
785 &device
788 /* Start the GAL device. */
789 gcmkONERROR(gckGALDEVICE_Start(device));
791 if ((physSize != 0)
792 && (device->kernels[gcvCORE_MAJOR] != gcvNULL)
793 && (device->kernels[gcvCORE_MAJOR]->hardware->mmuVersion != 0))
795 status = gckMMU_Enable(device->kernels[gcvCORE_MAJOR]->mmu, baseAddress, physSize);
796 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
797 "Enable new MMU: status=%d\n", status);
799 if ((device->kernels[gcvCORE_2D] != gcvNULL)
800 && (device->kernels[gcvCORE_2D]->hardware->mmuVersion != 0))
802 status = gckMMU_Enable(device->kernels[gcvCORE_2D]->mmu, baseAddress, physSize);
803 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
804 "Enable new MMU for 2D: status=%d\n", status);
807 /* Reset the base address */
808 device->baseAddress = 0;
811 /* Register the character device. */
812 ret = register_chrdev(major, DRV_NAME, &driver_fops);
814 if (ret < 0)
816 gcmkTRACE_ZONE(
817 gcvLEVEL_ERROR, gcvZONE_DRIVER,
818 "%s(%d): Could not allocate major number for mmap.\n",
819 __FUNCTION__, __LINE__
822 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
825 if (major == 0)
827 major = ret;
830 /* Create the device class. */
831 device_class = class_create(THIS_MODULE, "graphics_class");
833 if (IS_ERR(device_class))
835 gcmkTRACE_ZONE(
836 gcvLEVEL_ERROR, gcvZONE_DRIVER,
837 "%s(%d): Failed to create the class.\n",
838 __FUNCTION__, __LINE__
841 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
844 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
845 device_create(device_class, NULL, MKDEV(major, 0), NULL, "galcore");
846 #else
847 device_create(device_class, NULL, MKDEV(major, 0), "galcore");
848 #endif
850 galDevice = device;
851 gpuClass = device_class;
853 gcmkTRACE_ZONE(
854 gcvLEVEL_INFO, gcvZONE_DRIVER,
855 "%s(%d): irqLine=%d, contiguousSize=%lu, memBase=0x%lX\n",
856 __FUNCTION__, __LINE__,
857 irqLine, contiguousSize, registerMemBase
860 /* Success. */
861 gcmkFOOTER_NO();
862 return 0;
864 OnError:
865 /* Roll back. */
866 if (device_class != gcvNULL)
868 device_destroy(device_class, MKDEV(major, 0));
869 class_destroy(device_class);
872 if (device != gcvNULL)
874 gcmkVERIFY_OK(gckGALDEVICE_Stop(device));
875 gcmkVERIFY_OK(gckGALDEVICE_Destroy(device));
878 gcmkFOOTER();
879 return result;
882 #if !USE_PLATFORM_DRIVER
883 static void __exit drv_exit(void)
884 #else
885 static void drv_exit(void)
886 #endif
888 gcmkHEADER();
890 gcmkASSERT(gpuClass != gcvNULL);
891 device_destroy(gpuClass, MKDEV(major, 0));
892 class_destroy(gpuClass);
894 unregister_chrdev(major, DRV_NAME);
896 gcmkVERIFY_OK(gckGALDEVICE_Stop(galDevice));
897 gcmkVERIFY_OK(gckGALDEVICE_Destroy(galDevice));
899 #if ENABLE_GPU_CLOCK_BY_DRIVER && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
901 # if 0
902 struct clk * clk = NULL;
904 #if defined(CONFIG_PXA_DVFM) && (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
905 gc_pwr(0);
906 #endif
907 clk = clk_get(NULL, "GCCLK");
908 clk_disable(clk);
909 # else
910 if (clk_3d_core) {
911 clk_disable(clk_3d_core);
912 clk_put(clk_3d_core);
913 clk_3d_core = NULL;
915 if (clk_3d_shader) {
916 clk_disable(clk_3d_shader);
917 clk_put(clk_3d_shader);
918 clk_3d_shader = NULL;
920 if (clk_2d_core) {
921 clk_disable(clk_2d_core);
922 clk_put(clk_2d_core);
923 clk_2d_core = NULL;
925 # endif
927 #endif
929 gcmkFOOTER_NO();
932 #if !USE_PLATFORM_DRIVER
933 module_init(drv_init);
934 module_exit(drv_exit);
935 #else
937 #ifdef CONFIG_DOVE_GPU
938 # define DEVICE_NAME "dove_gpu"
939 #else
940 # define DEVICE_NAME "galcore"
941 #endif
943 static int __devinit gpu_probe(struct platform_device *pdev)
945 int ret = -ENODEV;
946 struct resource* res;
947 struct viv_gpu_platform_data *pdata;
949 gcmkHEADER();
951 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq_3d");
952 if (res)
953 irqLine = res->start;
955 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iobase_3d");
956 if (res)
958 registerMemBase = res->start;
959 registerMemSize = res->end - res->start + 1;
962 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq_2d");
963 if (res)
964 irqLine2D = res->start;
966 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iobase_2d");
967 if (res)
969 registerMemBase2D = res->start;
970 registerMemSize2D = res->end - res->start + 1;
973 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq_vg");
974 if (res)
975 irqLineVG = res->start;
977 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iobase_vg");
978 if (res)
980 registerMemBaseVG = res->start;
981 registerMemSizeVG = res->end - res->start + 1;
984 pdata = pdev->dev.platform_data;
985 if (pdata) {
986 contiguousBase = pdata->reserved_mem_base;
987 contiguousSize = pdata->reserved_mem_size;
990 ret = drv_init();
992 if (!ret)
994 platform_set_drvdata(pdev, galDevice);
996 gcmkFOOTER_NO();
997 return ret;
1000 gcmkFOOTER_ARG(KERN_INFO "Failed to register gpu driver: %d\n", ret);
1001 return ret;
1004 static int __devinit gpu_remove(struct platform_device *pdev)
1006 gcmkHEADER();
1007 drv_exit();
1008 gcmkFOOTER_NO();
1009 return 0;
1012 static int __devinit gpu_suspend(struct platform_device *dev, pm_message_t state)
1014 gceSTATUS status;
1015 gckGALDEVICE device;
1016 gctINT i;
1018 device = platform_get_drvdata(dev);
1020 for (i = 0; i < gcdCORE_COUNT; i++)
1022 if (device->kernels[i] != gcvNULL)
1024 #if gcdENABLE_VG
1025 if (i != gcvCORE_VG)
1026 #endif
1028 status = gckHARDWARE_SetPowerManagementState(device->kernels[i]->hardware, gcvPOWER_OFF);
1030 if (gcmIS_ERROR(status))
1032 return -1;
1038 return 0;
1041 static int __devinit gpu_resume(struct platform_device *dev)
1043 gceSTATUS status;
1044 gckGALDEVICE device;
1045 gctINT i;
1047 device = platform_get_drvdata(dev);
1049 for (i = 0; i < gcdCORE_COUNT; i++)
1051 if (device->kernels[i] != gcvNULL)
1053 #if gcdENABLE_VG
1054 if (i != gcvCORE_VG)
1055 #endif
1057 status = gckHARDWARE_SetPowerManagementState(device->kernels[i]->hardware, gcvPOWER_ON);
1059 if (gcmIS_ERROR(status))
1061 return -1;
1067 return 0;
1070 static struct platform_driver gpu_driver = {
1071 .probe = gpu_probe,
1072 .remove = gpu_remove,
1074 .suspend = gpu_suspend,
1075 .resume = gpu_resume,
1077 .driver = {
1078 .name = DEVICE_NAME,
1082 #if 0 /*CONFIG_DOVE_GPU*/
1083 static struct resource gpu_resources[] = {
1085 .name = "gpu_irq",
1086 .flags = IORESOURCE_IRQ,
1089 .name = "gpu_base",
1090 .flags = IORESOURCE_MEM,
1093 .name = "gpu_mem",
1094 .flags = IORESOURCE_MEM,
1098 static struct platform_device * gpu_device;
1099 #endif
1101 static int __init gpu_init(void)
1103 int ret = 0;
1105 #if 0 /*ndef CONFIG_DOVE_GPU*/
1106 gpu_resources[0].start = gpu_resources[0].end = irqLine;
1108 gpu_resources[1].start = registerMemBase;
1109 gpu_resources[1].end = registerMemBase + registerMemSize - 1;
1111 gpu_resources[2].start = contiguousBase;
1112 gpu_resources[2].end = contiguousBase + contiguousSize - 1;
1114 /* Allocate device */
1115 gpu_device = platform_device_alloc(DEVICE_NAME, -1);
1116 if (!gpu_device)
1118 printk(KERN_ERR "galcore: platform_device_alloc failed.\n");
1119 ret = -ENOMEM;
1120 goto out;
1123 /* Insert resource */
1124 ret = platform_device_add_resources(gpu_device, gpu_resources, 3);
1125 if (ret)
1127 printk(KERN_ERR "galcore: platform_device_add_resources failed.\n");
1128 goto put_dev;
1131 /* Add device */
1132 ret = platform_device_add(gpu_device);
1133 if (ret)
1135 printk(KERN_ERR "galcore: platform_device_add failed.\n");
1136 goto put_dev;
1138 #endif
1140 ret = platform_driver_register(&gpu_driver);
1141 if (!ret)
1143 goto out;
1146 #if 0 /*ndef CONFIG_DOVE_GPU*/
1147 platform_device_del(gpu_device);
1148 put_dev:
1149 platform_device_put(gpu_device);
1150 #endif
1152 out:
1153 return ret;
1156 static void __exit gpu_exit(void)
1158 platform_driver_unregister(&gpu_driver);
1159 #if 0 /*ndef CONFIG_DOVE_GPU*/
1160 platform_device_unregister(gpu_device);
1161 #endif
1164 module_init(gpu_init);
1165 module_exit(gpu_exit);
1167 #endif