ENGR00156850 gpu-viv: add gpu-viv driver source
[wandboard.git] / drivers / mxc / gpu-viv / hal / os / linux / kernel / gc_hal_kernel_device.c
blobfb4ccc56860dfe5ffd0af85cd0af05e81a43af63
1 /****************************************************************************
3 * Copyright (C) 2005 - 2011 by Vivante Corp.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the license, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *****************************************************************************/
24 #include "gc_hal_kernel_linux.h"
25 #include <linux/pagemap.h>
26 #include <linux/seq_file.h>
27 #include <linux/mm.h>
28 #include <linux/mman.h>
29 #include <linux/slab.h>
31 #define _GC_OBJ_ZONE gcvZONE_DEVICE
33 #ifdef FLAREON
34 static struct dove_gpio_irq_handler gc500_handle;
35 #endif
37 /******************************************************************************\
38 *************************** Memory Allocation Wrappers *************************
39 \******************************************************************************/
41 static gceSTATUS
42 _AllocateMemory(
43 IN gckGALDEVICE Device,
44 IN gctSIZE_T Bytes,
45 OUT gctPOINTER *Logical,
46 OUT gctPHYS_ADDR *Physical,
47 OUT gctUINT32 *PhysAddr
50 gceSTATUS status;
52 gcmkHEADER_ARG("Device=0x%x Bytes=%lu", Device, Bytes);
54 gcmkVERIFY_ARGUMENT(Device != NULL);
55 gcmkVERIFY_ARGUMENT(Logical != NULL);
56 gcmkVERIFY_ARGUMENT(Physical != NULL);
57 gcmkVERIFY_ARGUMENT(PhysAddr != NULL);
59 gcmkONERROR(gckOS_AllocateContiguous(
60 Device->os, gcvFALSE, &Bytes, Physical, Logical
61 ));
63 *PhysAddr = ((PLINUX_MDL)*Physical)->dmaHandle - Device->baseAddress;
65 /* Success. */
66 gcmkFOOTER_ARG(
67 "*Logical=0x%x *Physical=0x%x *PhysAddr=0x%08x",
68 *Logical, *Physical, *PhysAddr
71 return gcvSTATUS_OK;
73 OnError:
74 gcmkFOOTER();
75 return status;
78 static gceSTATUS
79 _FreeMemory(
80 IN gckGALDEVICE Device,
81 IN gctPOINTER Logical,
82 IN gctPHYS_ADDR Physical)
84 gceSTATUS status;
86 gcmkHEADER_ARG("Device=0x%x Logical=0x%x Physical=0x%x",
87 Device, Logical, Physical);
89 gcmkVERIFY_ARGUMENT(Device != NULL);
91 status = gckOS_FreeContiguous(
92 Device->os, Physical, Logical,
93 ((PLINUX_MDL) Physical)->numPages * PAGE_SIZE
96 gcmkFOOTER();
97 return status;
102 /******************************************************************************\
103 ******************************* Interrupt Handler ******************************
104 \******************************************************************************/
105 static irqreturn_t isrRoutine(int irq, void *ctxt)
107 gceSTATUS status;
108 gckGALDEVICE device;
110 device = (gckGALDEVICE) ctxt;
112 /* Call kernel interrupt notification. */
113 status = gckKERNEL_Notify(device->kernels[gcvCORE_MAJOR], gcvNOTIFY_INTERRUPT, gcvTRUE);
115 if (gcmIS_SUCCESS(status))
117 device->dataReadys[gcvCORE_MAJOR] = gcvTRUE;
119 up(&device->semas[gcvCORE_MAJOR]);
121 return IRQ_HANDLED;
124 return IRQ_NONE;
127 static int threadRoutine(void *ctxt)
129 gckGALDEVICE device = (gckGALDEVICE) ctxt;
131 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
132 "Starting isr Thread with extension=%p",
133 device);
135 for (;;)
137 static int down;
139 down = down_interruptible(&device->semas[gcvCORE_MAJOR]);
140 device->dataReadys[gcvCORE_MAJOR] = gcvFALSE;
142 if (device->killThread == gcvTRUE)
144 /* The daemon exits. */
145 while (!kthread_should_stop())
147 gckOS_Delay(device->os, 1);
150 return 0;
153 gckKERNEL_Notify(device->kernels[gcvCORE_MAJOR], gcvNOTIFY_INTERRUPT, gcvFALSE);
157 static irqreturn_t isrRoutine2D(int irq, void *ctxt)
159 gceSTATUS status;
160 gckGALDEVICE device;
162 device = (gckGALDEVICE) ctxt;
164 /* Call kernel interrupt notification. */
165 status = gckKERNEL_Notify(device->kernels[gcvCORE_2D], gcvNOTIFY_INTERRUPT, gcvTRUE);
167 if (gcmIS_SUCCESS(status))
169 device->dataReadys[gcvCORE_2D] = gcvTRUE;
171 up(&device->semas[gcvCORE_2D]);
173 return IRQ_HANDLED;
176 return IRQ_NONE;
179 static int threadRoutine2D(void *ctxt)
181 gckGALDEVICE device = (gckGALDEVICE) ctxt;
183 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
184 "Starting isr Thread with extension=%p",
185 device);
187 for (;;)
189 static int down;
191 down = down_interruptible(&device->semas[gcvCORE_2D]);
192 device->dataReadys[gcvCORE_2D] = gcvFALSE;
194 if (device->killThread == gcvTRUE)
196 /* The daemon exits. */
197 while (!kthread_should_stop())
199 gckOS_Delay(device->os, 1);
202 return 0;
205 gckKERNEL_Notify(device->kernels[gcvCORE_2D], gcvNOTIFY_INTERRUPT, gcvFALSE);
209 static irqreturn_t isrRoutineVG(int irq, void *ctxt)
211 #if gcdENABLE_VG
212 gceSTATUS status;
213 gckGALDEVICE device;
215 device = (gckGALDEVICE) ctxt;
217 /* Serve the interrupt. */
218 status = gckVGINTERRUPT_Enque(device->kernels[gcvCORE_VG]->vg->interrupt);
220 /* Determine the return value. */
221 return (status == gcvSTATUS_NOT_OUR_INTERRUPT)
222 ? IRQ_RETVAL(0)
223 : IRQ_RETVAL(1);
224 #else
225 return IRQ_NONE;
226 #endif
229 static int threadRoutineVG(void *ctxt)
231 gckGALDEVICE device = (gckGALDEVICE) ctxt;
233 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
234 "Starting isr Thread with extension=%p",
235 device);
237 for (;;)
239 static int down;
241 down = down_interruptible(&device->semas[gcvCORE_VG]);
242 device->dataReadys[gcvCORE_VG] = gcvFALSE;
244 if (device->killThread == gcvTRUE)
246 /* The daemon exits. */
247 while (!kthread_should_stop())
249 gckOS_Delay(device->os, 1);
252 return 0;
255 gckKERNEL_Notify(device->kernels[gcvCORE_VG], gcvNOTIFY_INTERRUPT, gcvFALSE);
259 #if gcdPOWEROFF_TIMEOUT
261 ** PM Thread Routine
263 static int threadRoutinePM(void *ctxt)
265 gckGALDEVICE device = (gckGALDEVICE) ctxt;
266 gckHARDWARE hardware = device->kernels[gcvCORE_MAJOR]->hardware;
267 gceCHIPPOWERSTATE state;
269 for(;;)
271 /* wait for idle */
272 gcmkVERIFY_OK(
273 gckOS_AcquireMutex(device->os, hardware->powerOffSema, gcvINFINITE));
275 /* We try to power off every 200 ms, until GPU is not idle */
278 if (device->killThread == gcvTRUE)
280 /* The daemon exits. */
281 while (!kthread_should_stop())
283 gckOS_Delay(device->os, 1);
285 return 0;
288 gcmkVERIFY_OK(
289 gckHARDWARE_SetPowerManagementState(
290 hardware,
291 gcvPOWER_OFF_TIMEOUT));
293 /* relax cpu 200 ms before retry */
294 gckOS_Delay(device->os, 200);
296 gcmkVERIFY_OK(
297 gckHARDWARE_QueryPowerManagementState(hardware, &state));
299 while (state == gcvPOWER_IDLE);
302 #endif
304 /******************************************************************************\
305 ******************************* gckGALDEVICE Code ******************************
306 \******************************************************************************/
308 /*******************************************************************************
310 ** gckGALDEVICE_Construct
312 ** Constructor.
314 ** INPUT:
316 ** OUTPUT:
318 ** gckGALDEVICE * Device
319 ** Pointer to a variable receiving the gckGALDEVICE object pointer on
320 ** success.
322 gceSTATUS
323 gckGALDEVICE_Construct(
324 IN gctINT IrqLine,
325 IN gctUINT32 RegisterMemBase,
326 IN gctSIZE_T RegisterMemSize,
327 IN gctINT IrqLine2D,
328 IN gctUINT32 RegisterMemBase2D,
329 IN gctSIZE_T RegisterMemSize2D,
330 IN gctINT IrqLineVG,
331 IN gctUINT32 RegisterMemBaseVG,
332 IN gctSIZE_T RegisterMemSizeVG,
333 IN gctUINT32 ContiguousBase,
334 IN gctSIZE_T ContiguousSize,
335 IN gctSIZE_T BankSize,
336 IN gctINT FastClear,
337 IN gctINT Compression,
338 IN gctUINT32 PhysBaseAddr,
339 IN gctUINT32 PhysSize,
340 IN gctINT Signal,
341 OUT gckGALDEVICE *Device
344 gctUINT32 internalBaseAddress = 0, internalAlignment = 0;
345 gctUINT32 externalBaseAddress = 0, externalAlignment = 0;
346 gctUINT32 horizontalTileSize, verticalTileSize;
347 struct resource* mem_region;
348 gctUINT32 physAddr;
349 gctUINT32 physical;
350 gckGALDEVICE device;
351 gceSTATUS status;
352 gctINT32 i;
353 gceHARDWARE_TYPE type;
354 gckDB sharedDB = gcvNULL;
356 gcmkHEADER_ARG("IrqLine=%d RegisterMemBase=0x%08x RegisterMemSize=%u "
357 "IrqLine2D=%d RegisterMemBase2D=0x%08x RegisterMemSize2D=%u "
358 "IrqLineVG=%d RegisterMemBaseVG=0x%08x RegisterMemSizeVG=%u "
359 "ContiguousBase=0x%08x ContiguousSize=%lu BankSize=%lu "
360 "FastClear=%d Compression=%d PhysBaseAddr=0x%x PhysSize=%d Signal=%d",
361 IrqLine, RegisterMemBase, RegisterMemSize,
362 IrqLine2D, RegisterMemBase2D, RegisterMemSize2D,
363 IrqLineVG, RegisterMemBaseVG, RegisterMemSizeVG,
364 ContiguousBase, ContiguousSize, BankSize, FastClear, Compression,
365 PhysBaseAddr, PhysSize, Signal);
367 /* Allocate device structure. */
368 device = kmalloc(sizeof(struct _gckGALDEVICE), GFP_KERNEL);
370 if (!device)
372 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
375 memset(device, 0, sizeof(struct _gckGALDEVICE));
377 if (IrqLine != -1)
379 device->requestedRegisterMemBases[gcvCORE_MAJOR] = RegisterMemBase;
380 device->requestedRegisterMemSizes[gcvCORE_MAJOR] = RegisterMemSize;
383 if (IrqLine2D != -1)
385 device->requestedRegisterMemBases[gcvCORE_2D] = RegisterMemBase2D;
386 device->requestedRegisterMemSizes[gcvCORE_2D] = RegisterMemSize2D;
389 if (IrqLineVG != -1)
391 device->requestedRegisterMemBases[gcvCORE_VG] = RegisterMemBaseVG;
392 device->requestedRegisterMemSizes[gcvCORE_VG] = RegisterMemSizeVG;
395 device->requestedContiguousBase = 0;
396 device->requestedContiguousSize = 0;
399 for (i = 0; i < gcdCORE_COUNT; i++)
401 physical = device->requestedRegisterMemBases[i];
403 /* Set up register memory region. */
404 if (physical != 0)
406 mem_region = request_mem_region(
407 physical, device->requestedRegisterMemSizes[i], "galcore register region"
410 if (mem_region == gcvNULL)
412 gcmkTRACE_ZONE(
413 gcvLEVEL_ERROR, gcvZONE_DRIVER,
414 "%s(%d): Failed to claim %lu bytes @ 0x%08X\n",
415 __FUNCTION__, __LINE__,
416 physical, device->requestedRegisterMemSizes[i]
419 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
422 device->registerBases[i] = (gctPOINTER) ioremap_nocache(
423 physical, device->requestedRegisterMemSizes[i]);
425 if (device->registerBases[i] == gcvNULL)
427 gcmkTRACE_ZONE(
428 gcvLEVEL_ERROR, gcvZONE_DRIVER,
429 "%s(%d): Unable to map %ld bytes @ 0x%08X\n",
430 __FUNCTION__, __LINE__,
431 physical, device->requestedRegisterMemSizes[i]
434 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
437 physical += device->requestedRegisterMemSizes[i];
439 else
441 device->registerBases[i] = gcvNULL;
445 /* Set the base address */
446 device->baseAddress = PhysBaseAddr;
448 /* Construct the gckOS object. */
449 gcmkONERROR(gckOS_Construct(device, &device->os));
451 if (IrqLine != -1)
453 /* Construct the gckKERNEL object. */
454 gcmkONERROR(gckKERNEL_Construct(
455 device->os, gcvCORE_MAJOR, device,
456 gcvNULL, &device->kernels[gcvCORE_MAJOR]));
458 sharedDB = device->kernels[gcvCORE_MAJOR]->db;
460 /* Initialize core mapping */
461 for (i = 0; i < 8; i++)
463 device->coreMapping[i] = gcvCORE_MAJOR;
466 /* Setup the ISR manager. */
467 gcmkONERROR(gckHARDWARE_SetIsrManager(
468 device->kernels[gcvCORE_MAJOR]->hardware,
469 (gctISRMANAGERFUNC) gckGALDEVICE_Setup_ISR,
470 (gctISRMANAGERFUNC) gckGALDEVICE_Release_ISR,
471 device
474 gcmkONERROR(gckHARDWARE_SetFastClear(
475 device->kernels[gcvCORE_MAJOR]->hardware, FastClear, Compression
479 #if COMMAND_PROCESSOR_VERSION == 1
480 /* Start the command queue. */
481 gcmkONERROR(gckCOMMAND_Start(device->kernels[gcvCORE_MAJOR]->command));
482 #endif
484 else
486 device->kernels[gcvCORE_MAJOR] = gcvNULL;
489 if (IrqLine2D != -1)
491 gcmkONERROR(gckKERNEL_Construct(
492 device->os, gcvCORE_2D, device,
493 sharedDB, &device->kernels[gcvCORE_2D]));
495 if (sharedDB == gcvNULL) sharedDB = device->kernels[gcvCORE_2D]->db;
497 /* Verify the hardware type */
498 gcmkONERROR(gckHARDWARE_GetType(device->kernels[gcvCORE_2D]->hardware, &type));
500 if (type != gcvHARDWARE_2D)
502 gcmkTRACE_ZONE(
503 gcvLEVEL_ERROR, gcvZONE_DRIVER,
504 "%s(%d): Unexpected hardware type: %d\n",
505 __FUNCTION__, __LINE__,
506 type
509 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
512 /* Initialize core mapping */
513 if (device->kernels[gcvCORE_MAJOR] == gcvNULL)
515 for (i = 0; i < 8; i++)
517 device->coreMapping[i] = gcvCORE_2D;
520 else
522 device->coreMapping[gcvHARDWARE_2D] = gcvCORE_2D;
525 /* Setup the ISR manager. */
526 gcmkONERROR(gckHARDWARE_SetIsrManager(
527 device->kernels[gcvCORE_2D]->hardware,
528 (gctISRMANAGERFUNC) gckGALDEVICE_Setup_ISR_2D,
529 (gctISRMANAGERFUNC) gckGALDEVICE_Release_ISR_2D,
530 device
533 #if COMMAND_PROCESSOR_VERSION == 1
534 /* Start the command queue. */
535 gcmkONERROR(gckCOMMAND_Start(device->kernels[gcvCORE_2D]->command));
536 #endif
538 else
540 device->kernels[gcvCORE_2D] = gcvNULL;
543 if (IrqLineVG != -1)
545 #if gcdENABLE_VG
546 gcmkONERROR(gckKERNEL_Construct(
547 device->os, gcvCORE_VG, device,
548 sharedDB, &device->kernels[gcvCORE_VG]));
549 /* Initialize core mapping */
550 if (device->kernels[gcvCORE_MAJOR] == gcvNULL
551 && device->kernels[gcvCORE_2D] == gcvNULL
554 for (i = 0; i < 8; i++)
556 device->coreMapping[i] = gcvCORE_VG;
559 else
561 device->coreMapping[gcvHARDWARE_VG] = gcvCORE_VG;
564 #endif
566 else
568 device->kernels[gcvCORE_VG] = gcvNULL;
571 /* Initialize the ISR. */
572 device->irqLines[gcvCORE_MAJOR] = IrqLine;
573 device->irqLines[gcvCORE_2D] = IrqLine2D;
574 device->irqLines[gcvCORE_VG] = IrqLineVG;
576 /* Initialize the kernel thread semaphores. */
577 for (i = 0; i < gcdCORE_COUNT; i++)
579 if (device->irqLines[i] != -1) sema_init(&device->semas[i], 0);
582 device->signal = Signal;
584 for (i = 0; i < gcdCORE_COUNT; i++)
586 if (device->kernels[i] != gcvNULL) break;
589 if (i == gcdCORE_COUNT) gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
591 #if gcdENABLE_VG
592 if (i == gcvCORE_VG)
594 /* Query the ceiling of the system memory. */
595 gcmkONERROR(gckVGHARDWARE_QuerySystemMemory(
596 device->kernels[i]->vg->hardware,
597 &device->systemMemorySize,
598 &device->systemMemoryBaseAddress
600 /* query the amount of video memory */
601 gcmkONERROR(gckVGHARDWARE_QueryMemory(
602 device->kernels[i]->vg->hardware,
603 &device->internalSize, &internalBaseAddress, &internalAlignment,
604 &device->externalSize, &externalBaseAddress, &externalAlignment,
605 &horizontalTileSize, &verticalTileSize
608 else
609 #endif
611 /* Query the ceiling of the system memory. */
612 gcmkONERROR(gckHARDWARE_QuerySystemMemory(
613 device->kernels[i]->hardware,
614 &device->systemMemorySize,
615 &device->systemMemoryBaseAddress
618 /* query the amount of video memory */
619 gcmkONERROR(gckHARDWARE_QueryMemory(
620 device->kernels[i]->hardware,
621 &device->internalSize, &internalBaseAddress, &internalAlignment,
622 &device->externalSize, &externalBaseAddress, &externalAlignment,
623 &horizontalTileSize, &verticalTileSize
628 /* Set up the internal memory region. */
629 if (device->internalSize > 0)
631 status = gckVIDMEM_Construct(
632 device->os,
633 internalBaseAddress, device->internalSize, internalAlignment,
634 0, &device->internalVidMem
637 if (gcmIS_ERROR(status))
639 /* Error, disable internal heap. */
640 device->internalSize = 0;
642 else
644 /* Map internal memory. */
645 device->internalLogical
646 = (gctPOINTER) ioremap_nocache(physical, device->internalSize);
648 if (device->internalLogical == gcvNULL)
650 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
653 device->internalPhysical = (gctPHYS_ADDR) physical;
654 physical += device->internalSize;
658 if (device->externalSize > 0)
660 /* create the external memory heap */
661 status = gckVIDMEM_Construct(
662 device->os,
663 externalBaseAddress, device->externalSize, externalAlignment,
664 0, &device->externalVidMem
667 if (gcmIS_ERROR(status))
669 /* Error, disable internal heap. */
670 device->externalSize = 0;
672 else
674 /* Map external memory. */
675 device->externalLogical
676 = (gctPOINTER) ioremap_nocache(physical, device->externalSize);
678 if (device->externalLogical == gcvNULL)
680 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
683 device->externalPhysical = (gctPHYS_ADDR) physical;
684 physical += device->externalSize;
688 /* set up the contiguous memory */
689 device->contiguousSize = ContiguousSize;
691 if (ContiguousSize > 0)
693 if (ContiguousBase == 0)
695 while (device->contiguousSize > 0)
697 /* Allocate contiguous memory. */
698 status = _AllocateMemory(
699 device,
700 device->contiguousSize,
701 &device->contiguousBase,
702 &device->contiguousPhysical,
703 &physAddr
706 if (gcmIS_SUCCESS(status))
708 status = gckVIDMEM_Construct(
709 device->os,
710 physAddr | device->systemMemoryBaseAddress,
711 device->contiguousSize,
713 BankSize,
714 &device->contiguousVidMem
717 if (gcmIS_SUCCESS(status))
719 break;
722 gcmkONERROR(_FreeMemory(
723 device,
724 device->contiguousBase,
725 device->contiguousPhysical
728 device->contiguousBase = gcvNULL;
729 device->contiguousPhysical = gcvNULL;
732 if (device->contiguousSize <= (4 << 20))
734 device->contiguousSize = 0;
736 else
738 device->contiguousSize -= (4 << 20);
742 else
744 /* Create the contiguous memory heap. */
745 status = gckVIDMEM_Construct(
746 device->os,
747 (ContiguousBase - device->baseAddress) | device->systemMemoryBaseAddress,
748 ContiguousSize,
749 64, BankSize,
750 &device->contiguousVidMem
753 if (gcmIS_ERROR(status))
755 /* Error, disable contiguous memory pool. */
756 device->contiguousVidMem = gcvNULL;
757 device->contiguousSize = 0;
759 else
761 mem_region = request_mem_region(
762 ContiguousBase, ContiguousSize, "galcore managed memory"
765 if (mem_region == gcvNULL)
767 gcmkTRACE_ZONE(
768 gcvLEVEL_ERROR, gcvZONE_DRIVER,
769 "%s(%d): Failed to claim %ld bytes @ 0x%08X\n",
770 __FUNCTION__, __LINE__,
771 ContiguousSize, ContiguousBase
774 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
777 device->requestedContiguousBase = ContiguousBase;
778 device->requestedContiguousSize = ContiguousSize;
780 device->contiguousBase
781 #if gcdPAGED_MEMORY_CACHEABLE
782 = (gctPOINTER) ioremap_cached(ContiguousBase, ContiguousSize);
783 #else
784 = (gctPOINTER) ioremap_nocache(ContiguousBase, ContiguousSize);
785 #endif
786 if (device->contiguousBase == gcvNULL)
788 device->contiguousVidMem = gcvNULL;
789 device->contiguousSize = 0;
791 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
794 device->contiguousPhysical = (gctPHYS_ADDR) ContiguousBase;
795 device->contiguousSize = ContiguousSize;
796 device->contiguousMapped = gcvTRUE;
801 /* Return pointer to the device. */
802 * Device = device;
804 gcmkFOOTER_ARG("*Device=0x%x", * Device);
805 return gcvSTATUS_OK;
807 OnError:
808 /* Roll back. */
809 gcmkVERIFY_OK(gckGALDEVICE_Destroy(device));
811 gcmkFOOTER();
812 return status;
815 /*******************************************************************************
817 ** gckGALDEVICE_Destroy
819 ** Class destructor.
821 ** INPUT:
823 ** Nothing.
825 ** OUTPUT:
827 ** Nothing.
829 ** RETURNS:
831 ** Nothing.
833 gceSTATUS
834 gckGALDEVICE_Destroy(
835 gckGALDEVICE Device)
837 gctINT i;
838 gceSTATUS status = gcvSTATUS_OK;
840 gcmkHEADER_ARG("Device=0x%x", Device);
842 if (Device != gcvNULL)
844 for (i = 0; i < gcdCORE_COUNT; i++)
846 if (Device->kernels[i] != gcvNULL)
848 /* Destroy the gckKERNEL object. */
849 gcmkVERIFY_OK(gckKERNEL_Destroy(Device->kernels[i]));
850 Device->kernels[i] = gcvNULL;
855 if (Device->internalLogical != gcvNULL)
857 /* Unmap the internal memory. */
858 iounmap(Device->internalLogical);
859 Device->internalLogical = gcvNULL;
862 if (Device->internalVidMem != gcvNULL)
864 /* Destroy the internal heap. */
865 gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->internalVidMem));
866 Device->internalVidMem = gcvNULL;
871 if (Device->externalLogical != gcvNULL)
873 /* Unmap the external memory. */
874 iounmap(Device->externalLogical);
875 Device->externalLogical = gcvNULL;
878 if (Device->externalVidMem != gcvNULL)
880 /* destroy the external heap */
881 gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->externalVidMem));
882 Device->externalVidMem = gcvNULL;
887 if (Device->contiguousBase != gcvNULL)
889 if (Device->contiguousMapped)
891 /* Unmap the contiguous memory. */
892 iounmap(Device->contiguousBase);
894 else
896 gcmkONERROR(_FreeMemory(
897 Device,
898 Device->contiguousBase,
899 Device->contiguousPhysical
903 if (Device->requestedContiguousBase != 0)
905 release_mem_region(Device->requestedContiguousBase, Device->requestedContiguousSize);
908 Device->contiguousBase = gcvNULL;
909 Device->contiguousPhysical = gcvNULL;
910 Device->requestedContiguousBase = 0;
911 Device->requestedContiguousSize = 0;
914 if (Device->contiguousVidMem != gcvNULL)
916 /* Destroy the contiguous heap. */
917 gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->contiguousVidMem));
918 Device->contiguousVidMem = gcvNULL;
922 for (i = 0; i < gcdCORE_COUNT; i++)
924 if (Device->registerBases[i] != gcvNULL)
926 /* Unmap register memory. */
927 iounmap(Device->registerBases[i]);
928 if (Device->requestedRegisterMemBases[i] != 0)
930 release_mem_region(Device->requestedRegisterMemBases[i], Device->requestedRegisterMemSizes[i]);
933 Device->registerBases[i] = gcvNULL;
934 Device->requestedRegisterMemBases[i] = 0;
935 Device->requestedRegisterMemSizes[i] = 0;
939 /* Destroy the gckOS object. */
940 if (Device->os != gcvNULL)
942 gcmkVERIFY_OK(gckOS_Destroy(Device->os));
943 Device->os = gcvNULL;
946 /* Free the device. */
947 kfree(Device);
950 gcmkFOOTER_NO();
951 return gcvSTATUS_OK;
953 OnError:
954 gcmkFOOTER();
955 return status;
958 /*******************************************************************************
960 ** gckGALDEVICE_Setup_ISR
962 ** Start the ISR routine.
964 ** INPUT:
966 ** gckGALDEVICE Device
967 ** Pointer to an gckGALDEVICE object.
969 ** OUTPUT:
971 ** Nothing.
973 ** RETURNS:
975 ** gcvSTATUS_OK
976 ** Setup successfully.
977 ** gcvSTATUS_GENERIC_IO
978 ** Setup failed.
980 gceSTATUS
981 gckGALDEVICE_Setup_ISR(
982 IN gckGALDEVICE Device
985 gceSTATUS status;
986 gctINT ret;
988 gcmkHEADER_ARG("Device=0x%x", Device);
990 gcmkVERIFY_ARGUMENT(Device != NULL);
992 if (Device->irqLines[gcvCORE_MAJOR] < 0)
994 gcmkONERROR(gcvSTATUS_GENERIC_IO);
997 /* Hook up the isr based on the irq line. */
998 #ifdef FLAREON
999 gc500_handle.dev_name = "galcore interrupt service";
1000 gc500_handle.dev_id = Device;
1001 gc500_handle.handler = isrRoutine;
1002 gc500_handle.intr_gen = GPIO_INTR_LEVEL_TRIGGER;
1003 gc500_handle.intr_trig = GPIO_TRIG_HIGH_LEVEL;
1005 ret = dove_gpio_request(
1006 DOVE_GPIO0_7, &gc500_handle
1008 #else
1009 ret = request_irq(
1010 Device->irqLines[gcvCORE_MAJOR], isrRoutine, IRQF_DISABLED,
1011 "galcore interrupt service", Device
1013 #endif
1015 if (ret != 0)
1017 gcmkTRACE_ZONE(
1018 gcvLEVEL_ERROR, gcvZONE_DRIVER,
1019 "%s(%d): Could not register irq line %d (error=%d)\n",
1020 __FUNCTION__, __LINE__,
1021 Device->irqLines[gcvCORE_MAJOR], ret
1024 gcmkONERROR(gcvSTATUS_GENERIC_IO);
1027 /* Mark ISR as initialized. */
1028 Device->isrInitializeds[gcvCORE_MAJOR] = gcvTRUE;
1030 gcmkFOOTER_NO();
1031 return gcvSTATUS_OK;
1033 OnError:
1034 gcmkFOOTER();
1035 return status;
1038 gceSTATUS
1039 gckGALDEVICE_Setup_ISR_2D(
1040 IN gckGALDEVICE Device
1043 gceSTATUS status;
1044 gctINT ret;
1046 gcmkHEADER_ARG("Device=0x%x", Device);
1048 gcmkVERIFY_ARGUMENT(Device != NULL);
1050 if (Device->irqLines[gcvCORE_2D] < 0)
1052 gcmkONERROR(gcvSTATUS_GENERIC_IO);
1055 /* Hook up the isr based on the irq line. */
1056 #ifdef FLAREON
1057 gc500_handle.dev_name = "galcore interrupt service";
1058 gc500_handle.dev_id = Device;
1059 gc500_handle.handler = isrRoutine2D;
1060 gc500_handle.intr_gen = GPIO_INTR_LEVEL_TRIGGER;
1061 gc500_handle.intr_trig = GPIO_TRIG_HIGH_LEVEL;
1063 ret = dove_gpio_request(
1064 DOVE_GPIO0_7, &gc500_handle
1066 #else
1067 ret = request_irq(
1068 Device->irqLines[gcvCORE_2D], isrRoutine2D, IRQF_DISABLED,
1069 "galcore interrupt service for 2D", Device
1071 #endif
1073 if (ret != 0)
1075 gcmkTRACE_ZONE(
1076 gcvLEVEL_ERROR, gcvZONE_DRIVER,
1077 "%s(%d): Could not register irq line %d (error=%d)\n",
1078 __FUNCTION__, __LINE__,
1079 Device->irqLines[gcvCORE_2D], ret
1082 gcmkONERROR(gcvSTATUS_GENERIC_IO);
1085 /* Mark ISR as initialized. */
1086 Device->isrInitializeds[gcvCORE_2D] = gcvTRUE;
1088 gcmkFOOTER_NO();
1089 return gcvSTATUS_OK;
1091 OnError:
1092 gcmkFOOTER();
1093 return status;
1096 gceSTATUS
1097 gckGALDEVICE_Setup_ISR_VG(
1098 IN gckGALDEVICE Device
1101 gceSTATUS status;
1102 gctINT ret;
1104 gcmkHEADER_ARG("Device=0x%x", Device);
1106 gcmkVERIFY_ARGUMENT(Device != NULL);
1108 if (Device->irqLines[gcvCORE_VG] < 0)
1110 gcmkONERROR(gcvSTATUS_GENERIC_IO);
1113 /* Hook up the isr based on the irq line. */
1114 #ifdef FLAREON
1115 gc500_handle.dev_name = "galcore interrupt service";
1116 gc500_handle.dev_id = Device;
1117 gc500_handle.handler = isrRoutineVG;
1118 gc500_handle.intr_gen = GPIO_INTR_LEVEL_TRIGGER;
1119 gc500_handle.intr_trig = GPIO_TRIG_HIGH_LEVEL;
1121 ret = dove_gpio_request(
1122 DOVE_GPIO0_7, &gc500_handle
1124 #else
1125 ret = request_irq(
1126 Device->irqLines[gcvCORE_VG], isrRoutineVG, IRQF_DISABLED,
1127 "galcore interrupt service for 2D", Device
1129 #endif
1131 if (ret != 0)
1133 gcmkTRACE_ZONE(
1134 gcvLEVEL_ERROR, gcvZONE_DRIVER,
1135 "%s(%d): Could not register irq line %d (error=%d)\n",
1136 __FUNCTION__, __LINE__,
1137 Device->irqLines[gcvCORE_VG], ret
1140 gcmkONERROR(gcvSTATUS_GENERIC_IO);
1143 /* Mark ISR as initialized. */
1144 Device->isrInitializeds[gcvCORE_VG] = gcvTRUE;
1146 gcmkFOOTER_NO();
1147 return gcvSTATUS_OK;
1149 OnError:
1150 gcmkFOOTER();
1151 return status;
1154 /*******************************************************************************
1156 ** gckGALDEVICE_Release_ISR
1158 ** Release the irq line.
1160 ** INPUT:
1162 ** gckGALDEVICE Device
1163 ** Pointer to an gckGALDEVICE object.
1165 ** OUTPUT:
1167 ** Nothing.
1169 ** RETURNS:
1171 ** Nothing.
1173 gceSTATUS
1174 gckGALDEVICE_Release_ISR(
1175 IN gckGALDEVICE Device
1178 gcmkHEADER_ARG("Device=0x%x", Device);
1180 gcmkVERIFY_ARGUMENT(Device != NULL);
1182 /* release the irq */
1183 if (Device->isrInitializeds[gcvCORE_MAJOR])
1185 #ifdef FLAREON
1186 dove_gpio_free(DOVE_GPIO0_7, "galcore interrupt service");
1187 #else
1188 free_irq(Device->irqLines[gcvCORE_MAJOR], Device);
1189 #endif
1191 Device->isrInitializeds[gcvCORE_MAJOR] = gcvFALSE;
1194 gcmkFOOTER_NO();
1195 return gcvSTATUS_OK;
1198 gceSTATUS
1199 gckGALDEVICE_Release_ISR_2D(
1200 IN gckGALDEVICE Device
1203 gcmkHEADER_ARG("Device=0x%x", Device);
1205 gcmkVERIFY_ARGUMENT(Device != NULL);
1207 /* release the irq */
1208 if (Device->isrInitializeds[gcvCORE_2D])
1210 #ifdef FLAREON
1211 dove_gpio_free(DOVE_GPIO0_7, "galcore interrupt service");
1212 #else
1213 free_irq(Device->irqLines[gcvCORE_2D], Device);
1214 #endif
1216 Device->isrInitializeds[gcvCORE_2D] = gcvFALSE;
1219 gcmkFOOTER_NO();
1220 return gcvSTATUS_OK;
1223 gceSTATUS
1224 gckGALDEVICE_Release_ISR_VG(
1225 IN gckGALDEVICE Device
1228 gcmkHEADER_ARG("Device=0x%x", Device);
1230 gcmkVERIFY_ARGUMENT(Device != NULL);
1232 /* release the irq */
1233 if (Device->isrInitializeds[gcvCORE_VG])
1235 #ifdef FLAREON
1236 dove_gpio_free(DOVE_GPIO0_7, "galcore interrupt service");
1237 #else
1238 free_irq(Device->irqLines[gcvCORE_VG], Device);
1239 #endif
1241 Device->isrInitializeds[gcvCORE_VG] = gcvFALSE;
1244 gcmkFOOTER_NO();
1245 return gcvSTATUS_OK;
1248 /*******************************************************************************
1250 ** gckGALDEVICE_Start_Threads
1252 ** Start the daemon threads.
1254 ** INPUT:
1256 ** gckGALDEVICE Device
1257 ** Pointer to an gckGALDEVICE object.
1259 ** OUTPUT:
1261 ** Nothing.
1263 ** RETURNS:
1265 ** gcvSTATUS_OK
1266 ** Start successfully.
1267 ** gcvSTATUS_GENERIC_IO
1268 ** Start failed.
1270 gceSTATUS
1271 gckGALDEVICE_Start_Threads(
1272 IN gckGALDEVICE Device
1275 gceSTATUS status;
1276 struct task_struct * task;
1278 gcmkHEADER_ARG("Device=0x%x", Device);
1280 gcmkVERIFY_ARGUMENT(Device != NULL);
1282 if (Device->kernels[gcvCORE_MAJOR] != gcvNULL)
1284 /* Start the kernel thread. */
1285 task = kthread_run(threadRoutine, Device, "galcore daemon thread");
1287 if (IS_ERR(task))
1289 gcmkTRACE_ZONE(
1290 gcvLEVEL_ERROR, gcvZONE_DRIVER,
1291 "%s(%d): Could not start the kernel thread.\n",
1292 __FUNCTION__, __LINE__
1295 gcmkONERROR(gcvSTATUS_GENERIC_IO);
1298 Device->threadCtxts[gcvCORE_MAJOR] = task;
1299 Device->threadInitializeds[gcvCORE_MAJOR] = gcvTRUE;
1301 #if gcdPOWEROFF_TIMEOUT
1302 /* Start the kernel thread. */
1303 task = kthread_run(threadRoutinePM, Device, "galcore pm thread");
1305 if (IS_ERR(task))
1307 gcmkTRACE_ZONE(
1308 gcvLEVEL_ERROR, gcvZONE_DRIVER,
1309 "%s(%d): Could not start the kernel thread.\n",
1310 __FUNCTION__, __LINE__
1313 gcmkONERROR(gcvSTATUS_GENERIC_IO);
1316 Device->pmThreadCtxts = task;
1317 Device->pmThreadInitializeds = gcvTRUE;
1318 #endif
1321 if (Device->kernels[gcvCORE_2D] != gcvNULL)
1323 /* Start the kernel thread. */
1324 task = kthread_run(threadRoutine2D, Device, "galcore daemon thread for 2D");
1326 if (IS_ERR(task))
1328 gcmkTRACE_ZONE(
1329 gcvLEVEL_ERROR, gcvZONE_DRIVER,
1330 "%s(%d): Could not start the kernel thread.\n",
1331 __FUNCTION__, __LINE__
1334 gcmkONERROR(gcvSTATUS_GENERIC_IO);
1337 Device->threadCtxts[gcvCORE_2D] = task;
1338 Device->threadInitializeds[gcvCORE_2D] = gcvTRUE;
1340 else
1342 Device->threadInitializeds[gcvCORE_2D] = gcvFALSE;
1345 if (Device->kernels[gcvCORE_VG] != gcvNULL)
1347 /* Start the kernel thread. */
1348 task = kthread_run(threadRoutineVG, Device, "galcore daemon thread for VG");
1350 if (IS_ERR(task))
1352 gcmkTRACE_ZONE(
1353 gcvLEVEL_ERROR, gcvZONE_DRIVER,
1354 "%s(%d): Could not start the kernel thread.\n",
1355 __FUNCTION__, __LINE__
1358 gcmkONERROR(gcvSTATUS_GENERIC_IO);
1361 Device->threadCtxts[gcvCORE_VG] = task;
1362 Device->threadInitializeds[gcvCORE_VG] = gcvTRUE;
1364 else
1366 Device->threadInitializeds[gcvCORE_VG] = gcvFALSE;
1369 gcmkFOOTER_NO();
1370 return gcvSTATUS_OK;
1372 OnError:
1373 gcmkFOOTER();
1374 return status;
1377 /*******************************************************************************
1379 ** gckGALDEVICE_Stop_Threads
1381 ** Stop the gal device, including the following actions: stop the daemon
1382 ** thread, release the irq.
1384 ** INPUT:
1386 ** gckGALDEVICE Device
1387 ** Pointer to an gckGALDEVICE object.
1389 ** OUTPUT:
1391 ** Nothing.
1393 ** RETURNS:
1395 ** Nothing.
1397 gceSTATUS
1398 gckGALDEVICE_Stop_Threads(
1399 gckGALDEVICE Device
1402 gctINT i;
1404 gcmkHEADER_ARG("Device=0x%x", Device);
1406 gcmkVERIFY_ARGUMENT(Device != NULL);
1408 for (i = 0; i < gcdCORE_COUNT; i++)
1410 /* Stop the kernel threads. */
1411 if (Device->threadInitializeds[i])
1413 Device->killThread = gcvTRUE;
1414 up(&Device->semas[i]);
1416 kthread_stop(Device->threadCtxts[i]);
1417 Device->threadCtxts[i] = gcvNULL;
1418 Device->threadInitializeds[i] = gcvFALSE;
1422 #if gcdPOWEROFF_TIMEOUT
1423 /* Stop the kernel threads. */
1424 if (Device->pmThreadInitializeds)
1426 gckHARDWARE hardware = Device->kernels[gcvCORE_MAJOR]->hardware;
1427 Device->killThread = gcvTRUE;
1428 gckOS_ReleaseSemaphore(Device->os, hardware->powerOffSema);
1430 kthread_stop(Device->pmThreadCtxts);
1431 Device->pmThreadCtxts = gcvNULL;
1432 Device->pmThreadInitializeds = gcvFALSE;
1434 #endif
1436 gcmkFOOTER_NO();
1437 return gcvSTATUS_OK;
1440 /*******************************************************************************
1442 ** gckGALDEVICE_Start
1444 ** Start the gal device, including the following actions: setup the isr routine
1445 ** and start the daemoni thread.
1447 ** INPUT:
1449 ** gckGALDEVICE Device
1450 ** Pointer to an gckGALDEVICE object.
1452 ** OUTPUT:
1454 ** Nothing.
1456 ** RETURNS:
1458 ** gcvSTATUS_OK
1459 ** Start successfully.
1461 gceSTATUS
1462 gckGALDEVICE_Start(
1463 IN gckGALDEVICE Device
1466 gceSTATUS status;
1468 gcmkHEADER_ARG("Device=0x%x", Device);
1470 /* Start the kernel thread. */
1471 gcmkONERROR(gckGALDEVICE_Start_Threads(Device));
1473 if (Device->kernels[gcvCORE_MAJOR] != gcvNULL)
1475 /* Setup the ISR routine. */
1476 gcmkONERROR(gckGALDEVICE_Setup_ISR(Device));
1478 /* Switch to SUSPEND power state. */
1479 gcmkONERROR(gckHARDWARE_SetPowerManagementState(
1480 Device->kernels[gcvCORE_MAJOR]->hardware, gcvPOWER_SUSPEND_ATPOWERON
1484 if (Device->kernels[gcvCORE_2D] != gcvNULL)
1486 /* Setup the ISR routine. */
1487 gcmkONERROR(gckGALDEVICE_Setup_ISR_2D(Device));
1489 /* Switch to SUSPEND power state. */
1490 gcmkONERROR(gckHARDWARE_SetPowerManagementState(
1491 Device->kernels[gcvCORE_2D]->hardware, gcvPOWER_SUSPEND_ATPOWERON
1495 if (Device->kernels[gcvCORE_VG] != gcvNULL)
1497 /* Setup the ISR routine. */
1498 gcmkONERROR(gckGALDEVICE_Setup_ISR_VG(Device));
1501 gcmkFOOTER_NO();
1502 return gcvSTATUS_OK;
1504 OnError:
1505 gcmkFOOTER();
1506 return status;
1509 /*******************************************************************************
1511 ** gckGALDEVICE_Stop
1513 ** Stop the gal device, including the following actions: stop the daemon
1514 ** thread, release the irq.
1516 ** INPUT:
1518 ** gckGALDEVICE Device
1519 ** Pointer to an gckGALDEVICE object.
1521 ** OUTPUT:
1523 ** Nothing.
1525 ** RETURNS:
1527 ** Nothing.
1529 gceSTATUS
1530 gckGALDEVICE_Stop(
1531 gckGALDEVICE Device
1534 gceSTATUS status;
1536 gcmkHEADER_ARG("Device=0x%x", Device);
1538 gcmkVERIFY_ARGUMENT(Device != NULL);
1540 if (Device->kernels[gcvCORE_MAJOR] != gcvNULL)
1542 /* Switch to OFF power state. */
1543 gcmkONERROR(gckHARDWARE_SetPowerManagementState(
1544 Device->kernels[gcvCORE_MAJOR]->hardware, gcvPOWER_OFF
1547 /* Remove the ISR routine. */
1548 gcmkONERROR(gckGALDEVICE_Release_ISR(Device));
1551 if (Device->kernels[gcvCORE_2D] != gcvNULL)
1553 /* Setup the ISR routine. */
1554 gcmkONERROR(gckGALDEVICE_Release_ISR_2D(Device));
1556 /* Switch to OFF power state. */
1557 gcmkONERROR(gckHARDWARE_SetPowerManagementState(
1558 Device->kernels[gcvCORE_2D]->hardware, gcvPOWER_OFF
1562 if (Device->kernels[gcvCORE_VG] != gcvNULL)
1564 /* Setup the ISR routine. */
1565 gcmkONERROR(gckGALDEVICE_Release_ISR_VG(Device));
1568 /* Stop the kernel thread. */
1569 gcmkONERROR(gckGALDEVICE_Stop_Threads(Device));
1571 gcmkFOOTER_NO();
1572 return gcvSTATUS_OK;
1574 OnError:
1575 gcmkFOOTER();
1576 return status;