]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.c
84a3c5e61ed6188dcfb0cba7db4b385fdf68b890
[karo-tx-linux.git] / drivers / mxc / gpu-viv / hal / os / linux / kernel / gc_hal_kernel_device.c
1 /****************************************************************************
2 *
3 *    Copyright (C) 2005 - 2013 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 "gc_hal_kernel_linux.h"
23 #include <linux/pagemap.h>
24 #include <linux/seq_file.h>
25 #include <linux/mm.h>
26 #include <linux/mman.h>
27 #include <linux/slab.h>
28 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
29 #include <mach/hardware.h>
30 #endif
31 #include <linux/pm_runtime.h>
32
33 #define _GC_OBJ_ZONE    gcvZONE_DEVICE
34
35 #define DEBUG_FILE                      "galcore_trace"
36 #define PARENT_FILE             "gpu"
37
38
39 #ifdef FLAREON
40     static struct dove_gpio_irq_handler gc500_handle;
41 #endif
42
43 #define gcmIS_CORE_PRESENT(Device, Core) (Device->irqLines[Core] > 0)
44
45 /******************************************************************************\
46 *************************** Memory Allocation Wrappers *************************
47 \******************************************************************************/
48
49 static gceSTATUS
50 _AllocateMemory(
51     IN gckGALDEVICE Device,
52     IN gctSIZE_T Bytes,
53     OUT gctPOINTER *Logical,
54     OUT gctPHYS_ADDR *Physical,
55     OUT gctUINT32 *PhysAddr
56     )
57 {
58     gceSTATUS status;
59
60     gcmkHEADER_ARG("Device=0x%x Bytes=%lu", Device, Bytes);
61
62     gcmkVERIFY_ARGUMENT(Device != NULL);
63     gcmkVERIFY_ARGUMENT(Logical != NULL);
64     gcmkVERIFY_ARGUMENT(Physical != NULL);
65     gcmkVERIFY_ARGUMENT(PhysAddr != NULL);
66
67     gcmkONERROR(gckOS_AllocateContiguous(
68         Device->os, gcvFALSE, &Bytes, Physical, Logical
69         ));
70
71     *PhysAddr = ((PLINUX_MDL)*Physical)->dmaHandle - Device->baseAddress;
72
73     /* Success. */
74     gcmkFOOTER_ARG(
75         "*Logical=0x%x *Physical=0x%x *PhysAddr=0x%08x",
76         *Logical, *Physical, *PhysAddr
77         );
78
79     return gcvSTATUS_OK;
80
81 OnError:
82     gcmkFOOTER();
83     return status;
84 }
85
86 static gceSTATUS
87 _FreeMemory(
88     IN gckGALDEVICE Device,
89     IN gctPOINTER Logical,
90     IN gctPHYS_ADDR Physical)
91 {
92     gceSTATUS status;
93
94     gcmkHEADER_ARG("Device=0x%x Logical=0x%x Physical=0x%x",
95                    Device, Logical, Physical);
96
97     gcmkVERIFY_ARGUMENT(Device != NULL);
98
99     status = gckOS_FreeContiguous(
100         Device->os, Physical, Logical,
101         ((PLINUX_MDL) Physical)->numPages * PAGE_SIZE
102         );
103
104     gcmkFOOTER();
105     return status;
106 }
107
108
109
110 /******************************************************************************\
111 ******************************* Interrupt Handler ******************************
112 \******************************************************************************/
113 static irqreturn_t isrRoutine(int irq, void *ctxt)
114 {
115     gceSTATUS status;
116     gckGALDEVICE device;
117
118     device = (gckGALDEVICE) ctxt;
119
120     /* Call kernel interrupt notification. */
121     status = gckKERNEL_Notify(device->kernels[gcvCORE_MAJOR], gcvNOTIFY_INTERRUPT, gcvTRUE);
122
123     if (gcmIS_SUCCESS(status))
124     {
125         device->dataReadys[gcvCORE_MAJOR] = gcvTRUE;
126
127         up(&device->semas[gcvCORE_MAJOR]);
128
129         return IRQ_HANDLED;
130     }
131
132     return IRQ_NONE;
133 }
134
135 static int threadRoutine(void *ctxt)
136 {
137     gckGALDEVICE device = (gckGALDEVICE) ctxt;
138
139     gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
140                    "Starting isr Thread with extension=%p",
141                    device);
142
143     for (;;)
144     {
145         static int down;
146
147         down = down_interruptible(&device->semas[gcvCORE_MAJOR]);
148         if (down); /*To make gcc 4.6 happye*/
149         device->dataReadys[gcvCORE_MAJOR] = gcvFALSE;
150
151         if (device->killThread == gcvTRUE)
152         {
153             /* The daemon exits. */
154             while (!kthread_should_stop())
155             {
156                 gckOS_Delay(device->os, 1);
157             }
158
159             return 0;
160         }
161
162         gckKERNEL_Notify(device->kernels[gcvCORE_MAJOR], gcvNOTIFY_INTERRUPT, gcvFALSE);
163     }
164 }
165
166 static irqreturn_t isrRoutine2D(int irq, void *ctxt)
167 {
168     gceSTATUS status;
169     gckGALDEVICE device;
170
171     device = (gckGALDEVICE) ctxt;
172
173     /* Call kernel interrupt notification. */
174     status = gckKERNEL_Notify(device->kernels[gcvCORE_2D], gcvNOTIFY_INTERRUPT, gcvTRUE);
175
176     if (gcmIS_SUCCESS(status))
177     {
178         device->dataReadys[gcvCORE_2D] = gcvTRUE;
179
180         up(&device->semas[gcvCORE_2D]);
181
182         return IRQ_HANDLED;
183     }
184
185     return IRQ_NONE;
186 }
187
188 static int threadRoutine2D(void *ctxt)
189 {
190     gckGALDEVICE device = (gckGALDEVICE) ctxt;
191
192     gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
193                    "Starting isr Thread with extension=%p",
194                    device);
195
196     for (;;)
197     {
198         static int down;
199
200         down = down_interruptible(&device->semas[gcvCORE_2D]);
201         if (down); /*To make gcc 4.6 happye*/
202         device->dataReadys[gcvCORE_2D] = gcvFALSE;
203
204         if (device->killThread == gcvTRUE)
205         {
206             /* The daemon exits. */
207             while (!kthread_should_stop())
208             {
209                 gckOS_Delay(device->os, 1);
210             }
211
212             return 0;
213         }
214
215         gckKERNEL_Notify(device->kernels[gcvCORE_2D], gcvNOTIFY_INTERRUPT, gcvFALSE);
216     }
217 }
218
219 static irqreturn_t isrRoutineVG(int irq, void *ctxt)
220 {
221 #if gcdENABLE_VG
222     gceSTATUS status;
223     gckGALDEVICE device;
224
225     device = (gckGALDEVICE) ctxt;
226
227         /* Serve the interrupt. */
228         status = gckVGINTERRUPT_Enque(device->kernels[gcvCORE_VG]->vg->interrupt);
229
230         /* Determine the return value. */
231         return (status == gcvSTATUS_NOT_OUR_INTERRUPT)
232                 ? IRQ_RETVAL(0)
233                 : IRQ_RETVAL(1);
234 #else
235     return IRQ_NONE;
236 #endif
237 }
238
239 static int threadRoutineVG(void *ctxt)
240 {
241     gckGALDEVICE device = (gckGALDEVICE) ctxt;
242
243     gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
244                    "Starting isr Thread with extension=%p",
245                    device);
246
247     for (;;)
248     {
249         static int down;
250
251         down = down_interruptible(&device->semas[gcvCORE_VG]);
252         if (down); /*To make gcc 4.6 happye*/
253         device->dataReadys[gcvCORE_VG] = gcvFALSE;
254
255         if (device->killThread == gcvTRUE)
256         {
257             /* The daemon exits. */
258             while (!kthread_should_stop())
259             {
260                 gckOS_Delay(device->os, 1);
261             }
262
263             return 0;
264         }
265
266         gckKERNEL_Notify(device->kernels[gcvCORE_VG], gcvNOTIFY_INTERRUPT, gcvFALSE);
267     }
268 }
269
270 /******************************************************************************\
271 ******************************* gckGALDEVICE Code ******************************
272 \******************************************************************************/
273
274 /*******************************************************************************
275 **
276 **  gckGALDEVICE_Construct
277 **
278 **  Constructor.
279 **
280 **  INPUT:
281 **
282 **  OUTPUT:
283 **
284 **      gckGALDEVICE * Device
285 **          Pointer to a variable receiving the gckGALDEVICE object pointer on
286 **          success.
287 */
288 gceSTATUS
289 gckGALDEVICE_Construct(
290     IN gctINT IrqLine,
291     IN gctUINT32 RegisterMemBase,
292     IN gctSIZE_T RegisterMemSize,
293     IN gctINT IrqLine2D,
294     IN gctUINT32 RegisterMemBase2D,
295     IN gctSIZE_T RegisterMemSize2D,
296     IN gctINT IrqLineVG,
297     IN gctUINT32 RegisterMemBaseVG,
298     IN gctSIZE_T RegisterMemSizeVG,
299     IN gctUINT32 ContiguousBase,
300     IN gctSIZE_T ContiguousSize,
301     IN gctSIZE_T BankSize,
302     IN gctINT FastClear,
303     IN gctINT Compression,
304     IN gctUINT32 PhysBaseAddr,
305     IN gctUINT32 PhysSize,
306     IN gctINT Signal,
307     IN gctUINT LogFileSize,
308     IN struct device *pdev,
309     IN gctINT PowerManagement,
310     OUT gckGALDEVICE *Device
311     )
312 {
313     gctUINT32 internalBaseAddress = 0, internalAlignment = 0;
314     gctUINT32 externalBaseAddress = 0, externalAlignment = 0;
315     gctUINT32 horizontalTileSize, verticalTileSize;
316     struct resource* mem_region;
317     gctUINT32 physAddr;
318     gctUINT32 physical;
319     gckGALDEVICE device;
320     gceSTATUS status;
321     gctINT32 i;
322     gceHARDWARE_TYPE type;
323     gckDB sharedDB = gcvNULL;
324     gckKERNEL kernel = gcvNULL;
325
326     gcmkHEADER_ARG("IrqLine=%d RegisterMemBase=0x%08x RegisterMemSize=%u "
327                    "IrqLine2D=%d RegisterMemBase2D=0x%08x RegisterMemSize2D=%u "
328                    "IrqLineVG=%d RegisterMemBaseVG=0x%08x RegisterMemSizeVG=%u "
329                    "ContiguousBase=0x%08x ContiguousSize=%lu BankSize=%lu "
330                    "FastClear=%d Compression=%d PhysBaseAddr=0x%x PhysSize=%d Signal=%d",
331                    IrqLine, RegisterMemBase, RegisterMemSize,
332                    IrqLine2D, RegisterMemBase2D, RegisterMemSize2D,
333                    IrqLineVG, RegisterMemBaseVG, RegisterMemSizeVG,
334                    ContiguousBase, ContiguousSize, BankSize, FastClear, Compression,
335                    PhysBaseAddr, PhysSize, Signal);
336
337     /* Allocate device structure. */
338     device = kmalloc(sizeof(struct _gckGALDEVICE), GFP_KERNEL | __GFP_NOWARN);
339
340     if (!device)
341     {
342         gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
343     }
344
345     memset(device, 0, sizeof(struct _gckGALDEVICE));
346
347    device->dbgnode = gcvNULL;
348    if(LogFileSize != 0)
349    {
350         if(gckDebugFileSystemCreateNode(LogFileSize,PARENT_FILE,DEBUG_FILE,&(device->dbgnode)) != 0)
351         {
352                 gcmkTRACE_ZONE(
353                 gcvLEVEL_ERROR, gcvZONE_DRIVER,
354                 "%s(%d): Failed to create  the debug file system  %s/%s \n",
355                 __FUNCTION__, __LINE__,
356                 PARENT_FILE, DEBUG_FILE
357                 );
358         }
359         else
360         {
361                 /*Everything is OK*/
362                 gckDebugFileSystemSetCurrentNode(device->dbgnode);
363         }
364     }
365 #ifdef CONFIG_PM
366     /*Init runtime pm for gpu*/
367     pm_runtime_enable(pdev);
368     device->pmdev = pdev;
369 #endif
370
371 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
372     /*get gpu regulator*/
373     device->gpu_regulator = regulator_get(pdev, "cpu_vddgpu");
374     if (IS_ERR(device->gpu_regulator)) {
375         gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
376                 "%s(%d): Failed to get gpu regulator  %s/%s \n",
377                 __FUNCTION__, __LINE__,
378                 PARENT_FILE, DEBUG_FILE);
379         gcmkONERROR(gcvSTATUS_NOT_FOUND);
380     }
381 #endif
382     /*Initialize the clock structure*/
383     if (IrqLine != -1) {
384         device->clk_3d_core = clk_get(pdev, "gpu3d_clk");
385         if (!IS_ERR(device->clk_3d_core)) {
386 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
387             if (cpu_is_mx6q()) {
388                     device->clk_3d_shader = clk_get(pdev, "gpu3d_shader_clk");
389                     if (IS_ERR(device->clk_3d_shader)) {
390                         IrqLine = -1;
391                         clk_put(device->clk_3d_core);
392                         device->clk_3d_core = NULL;
393                         device->clk_3d_shader = NULL;
394                         gckOS_Print("galcore: clk_get gpu3d_shader_clk failed, disable 3d!\n");
395                     }
396                   }
397 #else
398                     device->clk_3d_axi = clk_get(pdev, "gpu3d_axi_clk");
399                     device->clk_3d_shader = clk_get(pdev, "gpu3d_shader_clk");
400                     if (IS_ERR(device->clk_3d_shader)) {
401                         IrqLine = -1;
402                         clk_put(device->clk_3d_core);
403                         device->clk_3d_core = NULL;
404                         device->clk_3d_shader = NULL;
405                         gckOS_Print("galcore: clk_get gpu3d_shader_clk failed, disable 3d!\n");
406                     }
407 #endif
408         } else {
409             IrqLine = -1;
410             device->clk_3d_core = NULL;
411             gckOS_Print("galcore: clk_get gpu3d_clk failed, disable 3d!\n");
412         }
413     }
414     if ((IrqLine2D != -1) || (IrqLineVG != -1)) {
415         device->clk_2d_core = clk_get(pdev, "gpu2d_clk");
416         if (IS_ERR(device->clk_2d_core)) {
417             IrqLine2D = -1;
418             IrqLineVG = -1;
419             device->clk_2d_core = NULL;
420             gckOS_Print("galcore: clk_get 2d core clock failed, disable 2d/vg!\n");
421         } else {
422             if (IrqLine2D != -1) {
423                 device->clk_2d_axi = clk_get(pdev, "gpu2d_axi_clk");
424                 if (IS_ERR(device->clk_2d_axi)) {
425                     device->clk_2d_axi = NULL;
426                     IrqLine2D = -1;
427                     gckOS_Print("galcore: clk_get 2d axi clock failed, disable 2d\n");
428                 }
429             }
430             if (IrqLineVG != -1) {
431                 device->clk_vg_axi = clk_get(pdev, "openvg_axi_clk");
432                 if (IS_ERR(device->clk_vg_axi)) {
433                     IrqLineVG = -1;
434                         device->clk_vg_axi = NULL;
435                         gckOS_Print("galcore: clk_get vg clock failed, disable vg!\n");
436                 }
437             }
438         }
439     }
440
441     if (IrqLine != -1)
442     {
443         device->requestedRegisterMemBases[gcvCORE_MAJOR]    = RegisterMemBase;
444         device->requestedRegisterMemSizes[gcvCORE_MAJOR]    = RegisterMemSize;
445     }
446
447     if (IrqLine2D != -1)
448     {
449         device->requestedRegisterMemBases[gcvCORE_2D]       = RegisterMemBase2D;
450         device->requestedRegisterMemSizes[gcvCORE_2D]       = RegisterMemSize2D;
451     }
452
453     if (IrqLineVG != -1)
454     {
455         device->requestedRegisterMemBases[gcvCORE_VG]       = RegisterMemBaseVG;
456         device->requestedRegisterMemSizes[gcvCORE_VG]       = RegisterMemSizeVG;
457     }
458
459     device->requestedContiguousBase  = 0;
460     device->requestedContiguousSize  = 0;
461
462
463     for (i = 0; i < gcdMAX_GPU_COUNT; i++)
464     {
465         physical = device->requestedRegisterMemBases[i];
466
467         /* Set up register memory region. */
468         if (physical != 0)
469         {
470             mem_region = request_mem_region(
471                 physical, device->requestedRegisterMemSizes[i], "galcore register region"
472                 );
473
474             if (mem_region == gcvNULL)
475             {
476                 gcmkTRACE_ZONE(
477                     gcvLEVEL_ERROR, gcvZONE_DRIVER,
478                     "%s(%d): Failed to claim %lu bytes @ 0x%08X\n",
479                     __FUNCTION__, __LINE__,
480                     physical, device->requestedRegisterMemSizes[i]
481                     );
482
483                 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
484             }
485
486             device->registerBases[i] = (gctPOINTER) ioremap_nocache(
487                 physical, device->requestedRegisterMemSizes[i]);
488
489             if (device->registerBases[i] == gcvNULL)
490             {
491                 gcmkTRACE_ZONE(
492                     gcvLEVEL_ERROR, gcvZONE_DRIVER,
493                     "%s(%d): Unable to map %ld bytes @ 0x%08X\n",
494                     __FUNCTION__, __LINE__,
495                     physical, device->requestedRegisterMemSizes[i]
496                     );
497
498                 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
499             }
500
501             physical += device->requestedRegisterMemSizes[i];
502         }
503         else
504         {
505             device->registerBases[i] = gcvNULL;
506         }
507     }
508
509     /* Set the base address */
510     device->baseAddress = PhysBaseAddr;
511
512     /* Construct the gckOS object. */
513     gcmkONERROR(gckOS_Construct(device, &device->os));
514
515     if (IrqLine != -1)
516     {
517         /* Construct the gckKERNEL object. */
518         gcmkONERROR(gckKERNEL_Construct(
519             device->os, gcvCORE_MAJOR, device,
520             gcvNULL, &device->kernels[gcvCORE_MAJOR]));
521
522         sharedDB = device->kernels[gcvCORE_MAJOR]->db;
523
524         /* Initialize core mapping */
525         for (i = 0; i < 8; i++)
526         {
527             device->coreMapping[i] = gcvCORE_MAJOR;
528         }
529
530         /* Setup the ISR manager. */
531         gcmkONERROR(gckHARDWARE_SetIsrManager(
532             device->kernels[gcvCORE_MAJOR]->hardware,
533             (gctISRMANAGERFUNC) gckGALDEVICE_Setup_ISR,
534             (gctISRMANAGERFUNC) gckGALDEVICE_Release_ISR,
535             device
536             ));
537
538         gcmkONERROR(gckHARDWARE_SetFastClear(
539             device->kernels[gcvCORE_MAJOR]->hardware, FastClear, Compression
540             ));
541
542         gcmkONERROR(gckHARDWARE_SetPowerManagement(
543             device->kernels[gcvCORE_MAJOR]->hardware, PowerManagement
544             ));
545
546 #if COMMAND_PROCESSOR_VERSION == 1
547         /* Start the command queue. */
548         gcmkONERROR(gckCOMMAND_Start(device->kernels[gcvCORE_MAJOR]->command));
549 #endif
550     }
551     else
552     {
553         device->kernels[gcvCORE_MAJOR] = gcvNULL;
554     }
555
556     if (IrqLine2D != -1)
557     {
558         gcmkONERROR(gckKERNEL_Construct(
559             device->os, gcvCORE_2D, device,
560             sharedDB, &device->kernels[gcvCORE_2D]));
561
562         if (sharedDB == gcvNULL) sharedDB = device->kernels[gcvCORE_2D]->db;
563
564         /* Verify the hardware type */
565         gcmkONERROR(gckHARDWARE_GetType(device->kernels[gcvCORE_2D]->hardware, &type));
566
567         if (type != gcvHARDWARE_2D)
568         {
569             gcmkTRACE_ZONE(
570                 gcvLEVEL_ERROR, gcvZONE_DRIVER,
571                 "%s(%d): Unexpected hardware type: %d\n",
572                 __FUNCTION__, __LINE__,
573                 type
574                 );
575
576             gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
577         }
578
579         /* Initialize core mapping */
580         if (device->kernels[gcvCORE_MAJOR] == gcvNULL)
581         {
582             for (i = 0; i < 8; i++)
583             {
584                 device->coreMapping[i] = gcvCORE_2D;
585             }
586         }
587         else
588         {
589             device->coreMapping[gcvHARDWARE_2D] = gcvCORE_2D;
590         }
591
592         /* Setup the ISR manager. */
593         gcmkONERROR(gckHARDWARE_SetIsrManager(
594             device->kernels[gcvCORE_2D]->hardware,
595             (gctISRMANAGERFUNC) gckGALDEVICE_Setup_ISR_2D,
596             (gctISRMANAGERFUNC) gckGALDEVICE_Release_ISR_2D,
597             device
598             ));
599
600         gcmkONERROR(gckHARDWARE_SetPowerManagement(
601             device->kernels[gcvCORE_2D]->hardware, PowerManagement
602             ));
603
604 #if COMMAND_PROCESSOR_VERSION == 1
605         /* Start the command queue. */
606         gcmkONERROR(gckCOMMAND_Start(device->kernels[gcvCORE_2D]->command));
607 #endif
608     }
609     else
610     {
611         device->kernels[gcvCORE_2D] = gcvNULL;
612     }
613
614     if (IrqLineVG != -1)
615     {
616 #if gcdENABLE_VG
617         gcmkONERROR(gckKERNEL_Construct(
618             device->os, gcvCORE_VG, device,
619             sharedDB, &device->kernels[gcvCORE_VG]));
620         /* Initialize core mapping */
621         if (device->kernels[gcvCORE_MAJOR] == gcvNULL
622             && device->kernels[gcvCORE_2D] == gcvNULL
623             )
624         {
625             for (i = 0; i < 8; i++)
626             {
627                 device->coreMapping[i] = gcvCORE_VG;
628             }
629         }
630         else
631         {
632             device->coreMapping[gcvHARDWARE_VG] = gcvCORE_VG;
633         }
634
635
636         gcmkONERROR(gckVGHARDWARE_SetPowerManagement(
637             device->kernels[gcvCORE_VG]->vg->hardware,
638             PowerManagement
639             ));
640 #endif
641     }
642     else
643     {
644         device->kernels[gcvCORE_VG] = gcvNULL;
645     }
646
647     /* Initialize the ISR. */
648     device->irqLines[gcvCORE_MAJOR] = IrqLine;
649     device->irqLines[gcvCORE_2D]    = IrqLine2D;
650     device->irqLines[gcvCORE_VG]    = IrqLineVG;
651
652     /* Initialize the kernel thread semaphores. */
653     for (i = 0; i < gcdMAX_GPU_COUNT; i++)
654     {
655         if (device->irqLines[i] != -1) sema_init(&device->semas[i], 0);
656     }
657
658     device->signal = Signal;
659
660     for (i = 0; i < gcdMAX_GPU_COUNT; i++)
661     {
662         if (device->kernels[i] != gcvNULL) break;
663     }
664
665     if (i == gcdMAX_GPU_COUNT)
666         {
667                 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
668         }
669
670 #if gcdENABLE_VG
671     if (i == gcvCORE_VG)
672     {
673         /* Query the ceiling of the system memory. */
674         gcmkONERROR(gckVGHARDWARE_QuerySystemMemory(
675                 device->kernels[i]->vg->hardware,
676                 &device->systemMemorySize,
677                 &device->systemMemoryBaseAddress
678                 ));
679             /* query the amount of video memory */
680         gcmkONERROR(gckVGHARDWARE_QueryMemory(
681             device->kernels[i]->vg->hardware,
682             &device->internalSize, &internalBaseAddress, &internalAlignment,
683             &device->externalSize, &externalBaseAddress, &externalAlignment,
684             &horizontalTileSize, &verticalTileSize
685             ));
686     }
687     else
688 #endif
689     {
690         /* Query the ceiling of the system memory. */
691         gcmkONERROR(gckHARDWARE_QuerySystemMemory(
692                 device->kernels[i]->hardware,
693                 &device->systemMemorySize,
694                 &device->systemMemoryBaseAddress
695                 ));
696
697             /* query the amount of video memory */
698         gcmkONERROR(gckHARDWARE_QueryMemory(
699             device->kernels[i]->hardware,
700             &device->internalSize, &internalBaseAddress, &internalAlignment,
701             &device->externalSize, &externalBaseAddress, &externalAlignment,
702             &horizontalTileSize, &verticalTileSize
703             ));
704     }
705
706
707     /* Grab the first availiable kernel */
708     for (i = 0; i < gcdMAX_GPU_COUNT; i++)
709     {
710         if (device->irqLines[i] != -1)
711         {
712             kernel = device->kernels[i];
713             break;
714         }
715     }
716
717     /* Set up the internal memory region. */
718     if (device->internalSize > 0)
719     {
720         status = gckVIDMEM_Construct(
721             device->os,
722             internalBaseAddress, device->internalSize, internalAlignment,
723             0, &device->internalVidMem
724             );
725
726         if (gcmIS_ERROR(status))
727         {
728             /* Error, disable internal heap. */
729             device->internalSize = 0;
730         }
731         else
732         {
733             /* Map internal memory. */
734             device->internalLogical
735                 = (gctPOINTER) ioremap_nocache(physical, device->internalSize);
736
737             if (device->internalLogical == gcvNULL)
738             {
739                 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
740             }
741
742             device->internalPhysical = (gctPHYS_ADDR)(gctUINTPTR_T) physical;
743             device->internalPhysicalName = gcmPTR_TO_NAME(device->internalPhysical);
744             physical += device->internalSize;
745         }
746     }
747
748     if (device->externalSize > 0)
749     {
750         /* create the external memory heap */
751         status = gckVIDMEM_Construct(
752             device->os,
753             externalBaseAddress, device->externalSize, externalAlignment,
754             0, &device->externalVidMem
755             );
756
757         if (gcmIS_ERROR(status))
758         {
759             /* Error, disable internal heap. */
760             device->externalSize = 0;
761         }
762         else
763         {
764             /* Map external memory. */
765             device->externalLogical
766                 = (gctPOINTER) ioremap_nocache(physical, device->externalSize);
767
768             if (device->externalLogical == gcvNULL)
769             {
770                 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
771             }
772
773             device->externalPhysical = (gctPHYS_ADDR)(gctUINTPTR_T) physical;
774             device->externalPhysicalName = gcmPTR_TO_NAME(device->externalPhysical);
775             physical += device->externalSize;
776         }
777     }
778
779     /* set up the contiguous memory */
780     device->contiguousSize = ContiguousSize;
781
782     if (ContiguousSize > 0)
783     {
784         if (ContiguousBase == 0)
785         {
786             while (device->contiguousSize > 0)
787             {
788                 /* Allocate contiguous memory. */
789                 status = _AllocateMemory(
790                     device,
791                     device->contiguousSize,
792                     &device->contiguousBase,
793                     &device->contiguousPhysical,
794                     &physAddr
795                     );
796
797                 if (gcmIS_SUCCESS(status))
798                 {
799                     device->contiguousPhysicalName = gcmPTR_TO_NAME(device->contiguousPhysical);
800                     status = gckVIDMEM_Construct(
801                         device->os,
802                         physAddr | device->systemMemoryBaseAddress,
803                         device->contiguousSize,
804                         64,
805                         BankSize,
806                         &device->contiguousVidMem
807                         );
808
809                     if (gcmIS_SUCCESS(status))
810                     {
811                         break;
812                     }
813
814                     gcmkONERROR(_FreeMemory(
815                         device,
816                         device->contiguousBase,
817                         device->contiguousPhysical
818                         ));
819
820                     gcmRELEASE_NAME(device->contiguousPhysicalName);
821                     device->contiguousBase     = gcvNULL;
822                     device->contiguousPhysical = gcvNULL;
823                 }
824
825                 if (device->contiguousSize <= (4 << 20))
826                 {
827                     device->contiguousSize = 0;
828                 }
829                 else
830                 {
831                     device->contiguousSize -= (4 << 20);
832                 }
833             }
834         }
835         else
836         {
837             /* Create the contiguous memory heap. */
838             status = gckVIDMEM_Construct(
839                 device->os,
840                 ContiguousBase | device->systemMemoryBaseAddress,
841                 ContiguousSize,
842                 64, BankSize,
843                 &device->contiguousVidMem
844                 );
845
846             if (gcmIS_ERROR(status))
847             {
848                 /* Error, disable contiguous memory pool. */
849                 device->contiguousVidMem = gcvNULL;
850                 device->contiguousSize   = 0;
851             }
852             else
853             {
854 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
855                 mem_region = request_mem_region(
856                     ContiguousBase, ContiguousSize, "galcore managed memory"
857                     );
858
859                 if (mem_region == gcvNULL)
860                 {
861                     gcmkTRACE_ZONE(
862                         gcvLEVEL_ERROR, gcvZONE_DRIVER,
863                         "%s(%d): Failed to claim %ld bytes @ 0x%08X\n",
864                         __FUNCTION__, __LINE__,
865                         ContiguousSize, ContiguousBase
866                         );
867
868                     gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
869                 }
870 #endif
871
872                 device->requestedContiguousBase  = ContiguousBase;
873                 device->requestedContiguousSize  = ContiguousSize;
874
875 #if !gcdDYNAMIC_MAP_RESERVED_MEMORY && gcdENABLE_VG
876                 if (gcmIS_CORE_PRESENT(device, gcvCORE_VG))
877                 {
878                     device->contiguousBase
879 #if gcdPAGED_MEMORY_CACHEABLE
880                         = (gctPOINTER) ioremap_cached(ContiguousBase, ContiguousSize);
881 #else
882                         = (gctPOINTER) ioremap_nocache(ContiguousBase, ContiguousSize);
883 #endif
884                     if (device->contiguousBase == gcvNULL)
885                     {
886                         device->contiguousVidMem = gcvNULL;
887                         device->contiguousSize = 0;
888
889                         gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
890                     }
891                 }
892 #endif
893
894                 device->contiguousPhysical = gcvNULL;
895                 device->contiguousPhysicalName = 0;
896                 device->contiguousSize     = ContiguousSize;
897                 device->contiguousMapped   = gcvTRUE;
898             }
899         }
900     }
901
902     /* Return pointer to the device. */
903     * Device = device;
904
905     gcmkFOOTER_ARG("*Device=0x%x", * Device);
906     return gcvSTATUS_OK;
907
908 OnError:
909     /* Roll back. */
910     gcmkVERIFY_OK(gckGALDEVICE_Destroy(device));
911
912     gcmkFOOTER();
913     return status;
914 }
915
916 /*******************************************************************************
917 **
918 **  gckGALDEVICE_Destroy
919 **
920 **  Class destructor.
921 **
922 **  INPUT:
923 **
924 **      Nothing.
925 **
926 **  OUTPUT:
927 **
928 **      Nothing.
929 **
930 **  RETURNS:
931 **
932 **      Nothing.
933 */
934 gceSTATUS
935 gckGALDEVICE_Destroy(
936     gckGALDEVICE Device)
937 {
938     gctINT i;
939     gceSTATUS status = gcvSTATUS_OK;
940     gckKERNEL kernel = gcvNULL;
941
942     gcmkHEADER_ARG("Device=0x%x", Device);
943
944     if (Device != gcvNULL)
945     {
946         /* Grab the first availiable kernel */
947         for (i = 0; i < gcdMAX_GPU_COUNT; i++)
948         {
949             if (Device->irqLines[i] != -1)
950             {
951                 kernel = Device->kernels[i];
952                 break;
953             }
954         }
955         if (Device->internalPhysicalName != 0)
956         {
957             gcmRELEASE_NAME(Device->internalPhysicalName);
958             Device->internalPhysicalName = 0;
959         }
960         if (Device->externalPhysicalName != 0)
961         {
962             gcmRELEASE_NAME(Device->externalPhysicalName);
963             Device->externalPhysicalName = 0;
964         }
965         if (Device->contiguousPhysicalName != 0)
966         {
967             gcmRELEASE_NAME(Device->contiguousPhysicalName);
968             Device->contiguousPhysicalName = 0;
969         }
970
971
972         for (i = 0; i < gcdMAX_GPU_COUNT; i++)
973         {
974             if (Device->kernels[i] != gcvNULL)
975             {
976                 /* Destroy the gckKERNEL object. */
977                 gcmkVERIFY_OK(gckKERNEL_Destroy(Device->kernels[i]));
978                 Device->kernels[i] = gcvNULL;
979             }
980         }
981
982         {
983             if (Device->internalLogical != gcvNULL)
984             {
985                 /* Unmap the internal memory. */
986                 iounmap(Device->internalLogical);
987                 Device->internalLogical = gcvNULL;
988             }
989
990             if (Device->internalVidMem != gcvNULL)
991             {
992                 /* Destroy the internal heap. */
993                 gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->internalVidMem));
994                 Device->internalVidMem = gcvNULL;
995             }
996         }
997
998         {
999             if (Device->externalLogical != gcvNULL)
1000             {
1001                 /* Unmap the external memory. */
1002                 iounmap(Device->externalLogical);
1003                 Device->externalLogical = gcvNULL;
1004             }
1005
1006             if (Device->externalVidMem != gcvNULL)
1007             {
1008                 /* destroy the external heap */
1009                 gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->externalVidMem));
1010                 Device->externalVidMem = gcvNULL;
1011             }
1012         }
1013
1014         {
1015             if (Device->contiguousBase != gcvNULL)
1016             {
1017                 if (Device->contiguousMapped)
1018                 {
1019 #if !gcdDYNAMIC_MAP_RESERVED_MEMORY && gcdENABLE_VG
1020                     if (Device->contiguousBase)
1021                     {
1022                         /* Unmap the contiguous memory. */
1023                         iounmap(Device->contiguousBase);
1024                     }
1025 #endif
1026                 }
1027                 else
1028                 {
1029                     gcmkONERROR(_FreeMemory(
1030                         Device,
1031                         Device->contiguousBase,
1032                         Device->contiguousPhysical
1033                         ));
1034                 }
1035
1036                 Device->contiguousBase     = gcvNULL;
1037                 Device->contiguousPhysical = gcvNULL;
1038             }
1039
1040             if (Device->requestedContiguousBase != 0)
1041             {
1042                 release_mem_region(Device->requestedContiguousBase, Device->requestedContiguousSize);
1043                 Device->requestedContiguousBase = 0;
1044                 Device->requestedContiguousSize = 0;
1045             }
1046
1047             if (Device->contiguousVidMem != gcvNULL)
1048             {
1049                 /* Destroy the contiguous heap. */
1050                 gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->contiguousVidMem));
1051                 Device->contiguousVidMem = gcvNULL;
1052             }
1053         }
1054
1055         {
1056             if(gckDebugFileSystemIsEnabled())
1057             {
1058                  gckDebugFileSystemFreeNode(Device->dbgnode);
1059                  kfree(Device->dbgnode);
1060                  Device->dbgnode = gcvNULL;
1061             }
1062         }
1063
1064         for (i = 0; i < gcdMAX_GPU_COUNT; i++)
1065         {
1066             if (Device->registerBases[i] != gcvNULL)
1067             {
1068                 /* Unmap register memory. */
1069                 iounmap(Device->registerBases[i]);
1070                             if (Device->requestedRegisterMemBases[i] != 0)
1071                             {
1072                                     release_mem_region(Device->requestedRegisterMemBases[i], Device->requestedRegisterMemSizes[i]);
1073                             }
1074
1075                 Device->registerBases[i] = gcvNULL;
1076                 Device->requestedRegisterMemBases[i] = 0;
1077                 Device->requestedRegisterMemSizes[i] = 0;
1078             }
1079         }
1080
1081         /*Disable clock*/
1082 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
1083         if (Device->clk_3d_axi) {
1084            clk_put(Device->clk_3d_axi);
1085            Device->clk_3d_axi = NULL;
1086         }
1087 #endif
1088         if (Device->clk_3d_core) {
1089            clk_put(Device->clk_3d_core);
1090            Device->clk_3d_core = NULL;
1091         }
1092         if (Device->clk_3d_shader) {
1093            clk_put(Device->clk_3d_shader);
1094            Device->clk_3d_shader = NULL;
1095         }
1096         if (Device->clk_2d_core) {
1097            clk_put(Device->clk_2d_core);
1098            Device->clk_2d_core = NULL;
1099         }
1100         if (Device->clk_2d_axi) {
1101            clk_put(Device->clk_2d_axi);
1102            Device->clk_2d_axi = NULL;
1103         }
1104         if (Device->clk_vg_axi) {
1105            clk_put(Device->clk_vg_axi);
1106            Device->clk_vg_axi = NULL;
1107         }
1108
1109 #ifdef CONFIG_PM
1110         if(Device->pmdev)
1111             pm_runtime_disable(Device->pmdev);
1112 #endif
1113
1114 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
1115         if (Device->gpu_regulator) {
1116            regulator_put(Device->gpu_regulator);
1117            Device->gpu_regulator = NULL;
1118         }
1119 #endif
1120
1121         /* Destroy the gckOS object. */
1122         if (Device->os != gcvNULL)
1123         {
1124             gcmkVERIFY_OK(gckOS_Destroy(Device->os));
1125             Device->os = gcvNULL;
1126         }
1127
1128         /* Free the device. */
1129         kfree(Device);
1130     }
1131
1132     gcmkFOOTER_NO();
1133     return gcvSTATUS_OK;
1134
1135 OnError:
1136     gcmkFOOTER();
1137     return status;
1138 }
1139
1140 /*******************************************************************************
1141 **
1142 **  gckGALDEVICE_Setup_ISR
1143 **
1144 **  Start the ISR routine.
1145 **
1146 **  INPUT:
1147 **
1148 **      gckGALDEVICE Device
1149 **          Pointer to an gckGALDEVICE object.
1150 **
1151 **  OUTPUT:
1152 **
1153 **      Nothing.
1154 **
1155 **  RETURNS:
1156 **
1157 **      gcvSTATUS_OK
1158 **          Setup successfully.
1159 **      gcvSTATUS_GENERIC_IO
1160 **          Setup failed.
1161 */
1162 gceSTATUS
1163 gckGALDEVICE_Setup_ISR(
1164     IN gckGALDEVICE Device
1165     )
1166 {
1167     gceSTATUS status;
1168     gctINT ret;
1169
1170     gcmkHEADER_ARG("Device=0x%x", Device);
1171
1172     gcmkVERIFY_ARGUMENT(Device != NULL);
1173
1174     if (Device->irqLines[gcvCORE_MAJOR] < 0)
1175     {
1176         gcmkONERROR(gcvSTATUS_GENERIC_IO);
1177     }
1178
1179     /* Hook up the isr based on the irq line. */
1180 #ifdef FLAREON
1181     gc500_handle.dev_name  = "galcore interrupt service";
1182     gc500_handle.dev_id    = Device;
1183     gc500_handle.handler   = isrRoutine;
1184     gc500_handle.intr_gen  = GPIO_INTR_LEVEL_TRIGGER;
1185     gc500_handle.intr_trig = GPIO_TRIG_HIGH_LEVEL;
1186
1187     ret = dove_gpio_request(
1188         DOVE_GPIO0_7, &gc500_handle
1189         );
1190 #else
1191     ret = request_irq(
1192         Device->irqLines[gcvCORE_MAJOR], isrRoutine, IRQF_DISABLED,
1193         "galcore interrupt service", Device
1194         );
1195 #endif
1196
1197     if (ret != 0)
1198     {
1199         gcmkTRACE_ZONE(
1200             gcvLEVEL_ERROR, gcvZONE_DRIVER,
1201             "%s(%d): Could not register irq line %d (error=%d)\n",
1202             __FUNCTION__, __LINE__,
1203             Device->irqLines[gcvCORE_MAJOR], ret
1204             );
1205
1206         gcmkONERROR(gcvSTATUS_GENERIC_IO);
1207     }
1208
1209     /* Mark ISR as initialized. */
1210     Device->isrInitializeds[gcvCORE_MAJOR] = gcvTRUE;
1211
1212     gcmkFOOTER_NO();
1213     return gcvSTATUS_OK;
1214
1215 OnError:
1216     gcmkFOOTER();
1217     return status;
1218 }
1219
1220 gceSTATUS
1221 gckGALDEVICE_Setup_ISR_2D(
1222     IN gckGALDEVICE Device
1223     )
1224 {
1225     gceSTATUS status;
1226     gctINT ret;
1227
1228     gcmkHEADER_ARG("Device=0x%x", Device);
1229
1230     gcmkVERIFY_ARGUMENT(Device != NULL);
1231
1232     if (Device->irqLines[gcvCORE_2D] < 0)
1233     {
1234         gcmkONERROR(gcvSTATUS_GENERIC_IO);
1235     }
1236
1237     /* Hook up the isr based on the irq line. */
1238 #ifdef FLAREON
1239     gc500_handle.dev_name  = "galcore interrupt service";
1240     gc500_handle.dev_id    = Device;
1241     gc500_handle.handler   = isrRoutine2D;
1242     gc500_handle.intr_gen  = GPIO_INTR_LEVEL_TRIGGER;
1243     gc500_handle.intr_trig = GPIO_TRIG_HIGH_LEVEL;
1244
1245     ret = dove_gpio_request(
1246         DOVE_GPIO0_7, &gc500_handle
1247         );
1248 #else
1249     ret = request_irq(
1250         Device->irqLines[gcvCORE_2D], isrRoutine2D, IRQF_DISABLED,
1251         "galcore interrupt service for 2D", Device
1252         );
1253 #endif
1254
1255     if (ret != 0)
1256     {
1257         gcmkTRACE_ZONE(
1258             gcvLEVEL_ERROR, gcvZONE_DRIVER,
1259             "%s(%d): Could not register irq line %d (error=%d)\n",
1260             __FUNCTION__, __LINE__,
1261             Device->irqLines[gcvCORE_2D], ret
1262             );
1263
1264         gcmkONERROR(gcvSTATUS_GENERIC_IO);
1265     }
1266
1267     /* Mark ISR as initialized. */
1268     Device->isrInitializeds[gcvCORE_2D] = gcvTRUE;
1269
1270     gcmkFOOTER_NO();
1271     return gcvSTATUS_OK;
1272
1273 OnError:
1274     gcmkFOOTER();
1275     return status;
1276 }
1277
1278 gceSTATUS
1279 gckGALDEVICE_Setup_ISR_VG(
1280     IN gckGALDEVICE Device
1281     )
1282 {
1283     gceSTATUS status;
1284     gctINT ret;
1285
1286     gcmkHEADER_ARG("Device=0x%x", Device);
1287
1288     gcmkVERIFY_ARGUMENT(Device != NULL);
1289
1290     if (Device->irqLines[gcvCORE_VG] < 0)
1291     {
1292         gcmkONERROR(gcvSTATUS_GENERIC_IO);
1293     }
1294
1295     /* Hook up the isr based on the irq line. */
1296 #ifdef FLAREON
1297     gc500_handle.dev_name  = "galcore interrupt service";
1298     gc500_handle.dev_id    = Device;
1299     gc500_handle.handler   = isrRoutineVG;
1300     gc500_handle.intr_gen  = GPIO_INTR_LEVEL_TRIGGER;
1301     gc500_handle.intr_trig = GPIO_TRIG_HIGH_LEVEL;
1302
1303     ret = dove_gpio_request(
1304         DOVE_GPIO0_7, &gc500_handle
1305         );
1306 #else
1307     ret = request_irq(
1308         Device->irqLines[gcvCORE_VG], isrRoutineVG, IRQF_DISABLED,
1309         "galcore interrupt service for 2D", Device
1310         );
1311 #endif
1312
1313     if (ret != 0)
1314     {
1315         gcmkTRACE_ZONE(
1316             gcvLEVEL_ERROR, gcvZONE_DRIVER,
1317             "%s(%d): Could not register irq line %d (error=%d)\n",
1318             __FUNCTION__, __LINE__,
1319             Device->irqLines[gcvCORE_VG], ret
1320             );
1321
1322         gcmkONERROR(gcvSTATUS_GENERIC_IO);
1323     }
1324
1325     /* Mark ISR as initialized. */
1326     Device->isrInitializeds[gcvCORE_VG] = gcvTRUE;
1327
1328     gcmkFOOTER_NO();
1329     return gcvSTATUS_OK;
1330
1331 OnError:
1332     gcmkFOOTER();
1333     return status;
1334 }
1335
1336 /*******************************************************************************
1337 **
1338 **  gckGALDEVICE_Release_ISR
1339 **
1340 **  Release the irq line.
1341 **
1342 **  INPUT:
1343 **
1344 **      gckGALDEVICE Device
1345 **          Pointer to an gckGALDEVICE object.
1346 **
1347 **  OUTPUT:
1348 **
1349 **      Nothing.
1350 **
1351 **  RETURNS:
1352 **
1353 **      Nothing.
1354 */
1355 gceSTATUS
1356 gckGALDEVICE_Release_ISR(
1357     IN gckGALDEVICE Device
1358     )
1359 {
1360     gcmkHEADER_ARG("Device=0x%x", Device);
1361
1362     gcmkVERIFY_ARGUMENT(Device != NULL);
1363
1364     /* release the irq */
1365     if (Device->isrInitializeds[gcvCORE_MAJOR])
1366     {
1367 #ifdef FLAREON
1368         dove_gpio_free(DOVE_GPIO0_7, "galcore interrupt service");
1369 #else
1370         free_irq(Device->irqLines[gcvCORE_MAJOR], Device);
1371 #endif
1372
1373             Device->isrInitializeds[gcvCORE_MAJOR] = gcvFALSE;
1374     }
1375
1376     gcmkFOOTER_NO();
1377     return gcvSTATUS_OK;
1378 }
1379
1380 gceSTATUS
1381 gckGALDEVICE_Release_ISR_2D(
1382     IN gckGALDEVICE Device
1383     )
1384 {
1385     gcmkHEADER_ARG("Device=0x%x", Device);
1386
1387     gcmkVERIFY_ARGUMENT(Device != NULL);
1388
1389     /* release the irq */
1390     if (Device->isrInitializeds[gcvCORE_2D])
1391     {
1392 #ifdef FLAREON
1393         dove_gpio_free(DOVE_GPIO0_7, "galcore interrupt service");
1394 #else
1395         free_irq(Device->irqLines[gcvCORE_2D], Device);
1396 #endif
1397
1398             Device->isrInitializeds[gcvCORE_2D] = gcvFALSE;
1399     }
1400
1401     gcmkFOOTER_NO();
1402     return gcvSTATUS_OK;
1403 }
1404
1405 gceSTATUS
1406 gckGALDEVICE_Release_ISR_VG(
1407     IN gckGALDEVICE Device
1408     )
1409 {
1410     gcmkHEADER_ARG("Device=0x%x", Device);
1411
1412     gcmkVERIFY_ARGUMENT(Device != NULL);
1413
1414     /* release the irq */
1415     if (Device->isrInitializeds[gcvCORE_VG])
1416     {
1417 #ifdef FLAREON
1418         dove_gpio_free(DOVE_GPIO0_7, "galcore interrupt service");
1419 #else
1420         free_irq(Device->irqLines[gcvCORE_VG], Device);
1421 #endif
1422
1423             Device->isrInitializeds[gcvCORE_VG] = gcvFALSE;
1424     }
1425
1426     gcmkFOOTER_NO();
1427     return gcvSTATUS_OK;
1428 }
1429
1430 /*******************************************************************************
1431 **
1432 **  gckGALDEVICE_Start_Threads
1433 **
1434 **  Start the daemon threads.
1435 **
1436 **  INPUT:
1437 **
1438 **      gckGALDEVICE Device
1439 **          Pointer to an gckGALDEVICE object.
1440 **
1441 **  OUTPUT:
1442 **
1443 **      Nothing.
1444 **
1445 **  RETURNS:
1446 **
1447 **      gcvSTATUS_OK
1448 **          Start successfully.
1449 **      gcvSTATUS_GENERIC_IO
1450 **          Start failed.
1451 */
1452 gceSTATUS
1453 gckGALDEVICE_Start_Threads(
1454     IN gckGALDEVICE Device
1455     )
1456 {
1457     gceSTATUS status;
1458     struct task_struct * task;
1459
1460     gcmkHEADER_ARG("Device=0x%x", Device);
1461
1462     gcmkVERIFY_ARGUMENT(Device != NULL);
1463
1464     if (Device->kernels[gcvCORE_MAJOR] != gcvNULL)
1465     {
1466         /* Start the kernel thread. */
1467         task = kthread_run(threadRoutine, Device, "galcore daemon thread");
1468
1469         if (IS_ERR(task))
1470         {
1471             gcmkTRACE_ZONE(
1472                 gcvLEVEL_ERROR, gcvZONE_DRIVER,
1473                 "%s(%d): Could not start the kernel thread.\n",
1474                 __FUNCTION__, __LINE__
1475                 );
1476
1477             gcmkONERROR(gcvSTATUS_GENERIC_IO);
1478         }
1479
1480         Device->threadCtxts[gcvCORE_MAJOR]          = task;
1481         Device->threadInitializeds[gcvCORE_MAJOR]   = gcvTRUE;
1482     }
1483
1484     if (Device->kernels[gcvCORE_2D] != gcvNULL)
1485     {
1486         /* Start the kernel thread. */
1487         task = kthread_run(threadRoutine2D, Device, "galcore daemon thread for 2D");
1488
1489         if (IS_ERR(task))
1490         {
1491             gcmkTRACE_ZONE(
1492                 gcvLEVEL_ERROR, gcvZONE_DRIVER,
1493                 "%s(%d): Could not start the kernel thread.\n",
1494                 __FUNCTION__, __LINE__
1495                 );
1496
1497             gcmkONERROR(gcvSTATUS_GENERIC_IO);
1498         }
1499
1500         Device->threadCtxts[gcvCORE_2D]         = task;
1501         Device->threadInitializeds[gcvCORE_2D]  = gcvTRUE;
1502     }
1503     else
1504     {
1505         Device->threadInitializeds[gcvCORE_2D]  = gcvFALSE;
1506     }
1507
1508     if (Device->kernels[gcvCORE_VG] != gcvNULL)
1509     {
1510         /* Start the kernel thread. */
1511         task = kthread_run(threadRoutineVG, Device, "galcore daemon thread for VG");
1512
1513         if (IS_ERR(task))
1514         {
1515             gcmkTRACE_ZONE(
1516                 gcvLEVEL_ERROR, gcvZONE_DRIVER,
1517                 "%s(%d): Could not start the kernel thread.\n",
1518                 __FUNCTION__, __LINE__
1519                 );
1520
1521             gcmkONERROR(gcvSTATUS_GENERIC_IO);
1522         }
1523
1524         Device->threadCtxts[gcvCORE_VG]         = task;
1525         Device->threadInitializeds[gcvCORE_VG]  = gcvTRUE;
1526     }
1527     else
1528     {
1529         Device->threadInitializeds[gcvCORE_VG]  = gcvFALSE;
1530     }
1531
1532     gcmkFOOTER_NO();
1533     return gcvSTATUS_OK;
1534
1535 OnError:
1536     gcmkFOOTER();
1537     return status;
1538 }
1539
1540 /*******************************************************************************
1541 **
1542 **  gckGALDEVICE_Stop_Threads
1543 **
1544 **  Stop the gal device, including the following actions: stop the daemon
1545 **  thread, release the irq.
1546 **
1547 **  INPUT:
1548 **
1549 **      gckGALDEVICE Device
1550 **          Pointer to an gckGALDEVICE object.
1551 **
1552 **  OUTPUT:
1553 **
1554 **      Nothing.
1555 **
1556 **  RETURNS:
1557 **
1558 **      Nothing.
1559 */
1560 gceSTATUS
1561 gckGALDEVICE_Stop_Threads(
1562     gckGALDEVICE Device
1563     )
1564 {
1565     gctINT i;
1566
1567     gcmkHEADER_ARG("Device=0x%x", Device);
1568
1569     gcmkVERIFY_ARGUMENT(Device != NULL);
1570
1571     for (i = 0; i < gcdMAX_GPU_COUNT; i++)
1572     {
1573         /* Stop the kernel threads. */
1574         if (Device->threadInitializeds[i])
1575         {
1576             Device->killThread = gcvTRUE;
1577             up(&Device->semas[i]);
1578
1579             kthread_stop(Device->threadCtxts[i]);
1580             Device->threadCtxts[i]        = gcvNULL;
1581             Device->threadInitializeds[i] = gcvFALSE;
1582         }
1583     }
1584
1585     gcmkFOOTER_NO();
1586     return gcvSTATUS_OK;
1587 }
1588
1589 /*******************************************************************************
1590 **
1591 **  gckGALDEVICE_Start
1592 **
1593 **  Start the gal device, including the following actions: setup the isr routine
1594 **  and start the daemoni thread.
1595 **
1596 **  INPUT:
1597 **
1598 **      gckGALDEVICE Device
1599 **          Pointer to an gckGALDEVICE object.
1600 **
1601 **  OUTPUT:
1602 **
1603 **      Nothing.
1604 **
1605 **  RETURNS:
1606 **
1607 **      gcvSTATUS_OK
1608 **          Start successfully.
1609 */
1610 gceSTATUS
1611 gckGALDEVICE_Start(
1612     IN gckGALDEVICE Device
1613     )
1614 {
1615     gceSTATUS status;
1616
1617     gcmkHEADER_ARG("Device=0x%x", Device);
1618
1619     /* Start the kernel thread. */
1620     gcmkONERROR(gckGALDEVICE_Start_Threads(Device));
1621
1622     if (Device->kernels[gcvCORE_MAJOR] != gcvNULL)
1623     {
1624         /* Setup the ISR routine. */
1625         gcmkONERROR(gckGALDEVICE_Setup_ISR(Device));
1626
1627         /* Switch to SUSPEND power state. */
1628         gcmkONERROR(gckHARDWARE_SetPowerManagementState(
1629             Device->kernels[gcvCORE_MAJOR]->hardware, gcvPOWER_OFF_BROADCAST
1630             ));
1631     }
1632
1633     if (Device->kernels[gcvCORE_2D] != gcvNULL)
1634     {
1635         /* Setup the ISR routine. */
1636         gcmkONERROR(gckGALDEVICE_Setup_ISR_2D(Device));
1637
1638         /* Switch to SUSPEND power state. */
1639         gcmkONERROR(gckHARDWARE_SetPowerManagementState(
1640             Device->kernels[gcvCORE_2D]->hardware, gcvPOWER_OFF_BROADCAST
1641             ));
1642     }
1643
1644     if (Device->kernels[gcvCORE_VG] != gcvNULL)
1645     {
1646         /* Setup the ISR routine. */
1647         gcmkONERROR(gckGALDEVICE_Setup_ISR_VG(Device));
1648
1649         /* Switch to SUSPEND power state. */
1650         gcmkONERROR(gckVGHARDWARE_SetPowerManagementState(
1651             Device->kernels[gcvCORE_VG]->vg->hardware, gcvPOWER_OFF_BROADCAST
1652             ));
1653     }
1654
1655     gcmkFOOTER_NO();
1656     return gcvSTATUS_OK;
1657
1658 OnError:
1659     gcmkFOOTER();
1660     return status;
1661 }
1662
1663 /*******************************************************************************
1664 **
1665 **  gckGALDEVICE_Stop
1666 **
1667 **  Stop the gal device, including the following actions: stop the daemon
1668 **  thread, release the irq.
1669 **
1670 **  INPUT:
1671 **
1672 **      gckGALDEVICE Device
1673 **          Pointer to an gckGALDEVICE object.
1674 **
1675 **  OUTPUT:
1676 **
1677 **      Nothing.
1678 **
1679 **  RETURNS:
1680 **
1681 **      Nothing.
1682 */
1683 gceSTATUS
1684 gckGALDEVICE_Stop(
1685     gckGALDEVICE Device
1686     )
1687 {
1688     gceSTATUS status;
1689
1690     gcmkHEADER_ARG("Device=0x%x", Device);
1691
1692     gcmkVERIFY_ARGUMENT(Device != NULL);
1693
1694     if (Device->kernels[gcvCORE_MAJOR] != gcvNULL)
1695     {
1696         /* Switch to OFF power state. */
1697         gcmkONERROR(gckHARDWARE_SetPowerManagementState(
1698             Device->kernels[gcvCORE_MAJOR]->hardware, gcvPOWER_OFF
1699             ));
1700
1701         /* Remove the ISR routine. */
1702         gcmkONERROR(gckGALDEVICE_Release_ISR(Device));
1703     }
1704
1705     if (Device->kernels[gcvCORE_2D] != gcvNULL)
1706     {
1707         /* Setup the ISR routine. */
1708         gcmkONERROR(gckGALDEVICE_Release_ISR_2D(Device));
1709
1710         /* Switch to OFF power state. */
1711         gcmkONERROR(gckHARDWARE_SetPowerManagementState(
1712             Device->kernels[gcvCORE_2D]->hardware, gcvPOWER_OFF
1713             ));
1714     }
1715
1716     if (Device->kernels[gcvCORE_VG] != gcvNULL)
1717     {
1718         /* Setup the ISR routine. */
1719         gcmkONERROR(gckGALDEVICE_Release_ISR_VG(Device));
1720
1721 #if gcdENABLE_VG
1722         /* Switch to OFF power state. */
1723         gcmkONERROR(gckVGHARDWARE_SetPowerManagementState(
1724             Device->kernels[gcvCORE_VG]->vg->hardware, gcvPOWER_OFF
1725             ));
1726 #endif
1727     }
1728
1729     /* Stop the kernel thread. */
1730     gcmkONERROR(gckGALDEVICE_Stop_Threads(Device));
1731
1732     gcmkFOOTER_NO();
1733     return gcvSTATUS_OK;
1734
1735 OnError:
1736     gcmkFOOTER();
1737     return status;
1738 }