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>
28 #include <linux/mman.h>
29 #include <linux/slab.h>
31 #define _GC_OBJ_ZONE gcvZONE_DEVICE
34 static struct dove_gpio_irq_handler gc500_handle
;
37 /******************************************************************************\
38 *************************** Memory Allocation Wrappers *************************
39 \******************************************************************************/
43 IN gckGALDEVICE Device
,
45 OUT gctPOINTER
*Logical
,
46 OUT gctPHYS_ADDR
*Physical
,
47 OUT gctUINT32
*PhysAddr
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
63 *PhysAddr
= ((PLINUX_MDL
)*Physical
)->dmaHandle
- Device
->baseAddress
;
67 "*Logical=0x%x *Physical=0x%x *PhysAddr=0x%08x",
68 *Logical
, *Physical
, *PhysAddr
80 IN gckGALDEVICE Device
,
81 IN gctPOINTER Logical
,
82 IN gctPHYS_ADDR Physical
)
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
102 /******************************************************************************\
103 ******************************* Interrupt Handler ******************************
104 \******************************************************************************/
105 static irqreturn_t
isrRoutine(int irq
, void *ctxt
)
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
]);
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",
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);
153 gckKERNEL_Notify(device
->kernels
[gcvCORE_MAJOR
], gcvNOTIFY_INTERRUPT
, gcvFALSE
);
157 static irqreturn_t
isrRoutine2D(int irq
, void *ctxt
)
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
]);
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",
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);
205 gckKERNEL_Notify(device
->kernels
[gcvCORE_2D
], gcvNOTIFY_INTERRUPT
, gcvFALSE
);
209 static irqreturn_t
isrRoutineVG(int irq
, void *ctxt
)
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
)
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",
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);
255 gckKERNEL_Notify(device
->kernels
[gcvCORE_VG
], gcvNOTIFY_INTERRUPT
, gcvFALSE
);
259 #if gcdPOWEROFF_TIMEOUT
263 static int threadRoutinePM(void *ctxt
)
265 gckGALDEVICE device
= (gckGALDEVICE
) ctxt
;
266 gckHARDWARE hardware
= device
->kernels
[gcvCORE_MAJOR
]->hardware
;
267 gceCHIPPOWERSTATE state
;
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);
289 gckHARDWARE_SetPowerManagementState(
291 gcvPOWER_OFF_TIMEOUT
));
293 /* relax cpu 200 ms before retry */
294 gckOS_Delay(device
->os
, 200);
297 gckHARDWARE_QueryPowerManagementState(hardware
, &state
));
299 while (state
== gcvPOWER_IDLE
);
304 /******************************************************************************\
305 ******************************* gckGALDEVICE Code ******************************
306 \******************************************************************************/
308 /*******************************************************************************
310 ** gckGALDEVICE_Construct
318 ** gckGALDEVICE * Device
319 ** Pointer to a variable receiving the gckGALDEVICE object pointer on
323 gckGALDEVICE_Construct(
325 IN gctUINT32 RegisterMemBase
,
326 IN gctSIZE_T RegisterMemSize
,
328 IN gctUINT32 RegisterMemBase2D
,
329 IN gctSIZE_T RegisterMemSize2D
,
331 IN gctUINT32 RegisterMemBaseVG
,
332 IN gctSIZE_T RegisterMemSizeVG
,
333 IN gctUINT32 ContiguousBase
,
334 IN gctSIZE_T ContiguousSize
,
335 IN gctSIZE_T BankSize
,
337 IN gctINT Compression
,
338 IN gctUINT32 PhysBaseAddr
,
339 IN gctUINT32 PhysSize
,
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
;
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
);
372 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY
);
375 memset(device
, 0, sizeof(struct _gckGALDEVICE
));
379 device
->requestedRegisterMemBases
[gcvCORE_MAJOR
] = RegisterMemBase
;
380 device
->requestedRegisterMemSizes
[gcvCORE_MAJOR
] = RegisterMemSize
;
385 device
->requestedRegisterMemBases
[gcvCORE_2D
] = RegisterMemBase2D
;
386 device
->requestedRegisterMemSizes
[gcvCORE_2D
] = RegisterMemSize2D
;
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. */
406 mem_region
= request_mem_region(
407 physical
, device
->requestedRegisterMemSizes
[i
], "galcore register region"
410 if (mem_region
== gcvNULL
)
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
)
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
];
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
));
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
,
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
));
486 device
->kernels
[gcvCORE_MAJOR
] = gcvNULL
;
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
)
503 gcvLEVEL_ERROR
, gcvZONE_DRIVER
,
504 "%s(%d): Unexpected hardware type: %d\n",
505 __FUNCTION__
, __LINE__
,
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
;
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
,
533 #if COMMAND_PROCESSOR_VERSION == 1
534 /* Start the command queue. */
535 gcmkONERROR(gckCOMMAND_Start(device
->kernels
[gcvCORE_2D
]->command
));
540 device
->kernels
[gcvCORE_2D
] = gcvNULL
;
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
;
561 device
->coreMapping
[gcvHARDWARE_VG
] = gcvCORE_VG
;
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
);
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
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(
633 internalBaseAddress
, device
->internalSize
, internalAlignment
,
634 0, &device
->internalVidMem
637 if (gcmIS_ERROR(status
))
639 /* Error, disable internal heap. */
640 device
->internalSize
= 0;
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(
663 externalBaseAddress
, device
->externalSize
, externalAlignment
,
664 0, &device
->externalVidMem
667 if (gcmIS_ERROR(status
))
669 /* Error, disable internal heap. */
670 device
->externalSize
= 0;
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(
700 device
->contiguousSize
,
701 &device
->contiguousBase
,
702 &device
->contiguousPhysical
,
706 if (gcmIS_SUCCESS(status
))
708 status
= gckVIDMEM_Construct(
710 physAddr
| device
->systemMemoryBaseAddress
,
711 device
->contiguousSize
,
714 &device
->contiguousVidMem
717 if (gcmIS_SUCCESS(status
))
722 gcmkONERROR(_FreeMemory(
724 device
->contiguousBase
,
725 device
->contiguousPhysical
728 device
->contiguousBase
= gcvNULL
;
729 device
->contiguousPhysical
= gcvNULL
;
732 if (device
->contiguousSize
<= (4 << 20))
734 device
->contiguousSize
= 0;
738 device
->contiguousSize
-= (4 << 20);
744 /* Create the contiguous memory heap. */
745 status
= gckVIDMEM_Construct(
747 (ContiguousBase
- device
->baseAddress
) | device
->systemMemoryBaseAddress
,
750 &device
->contiguousVidMem
753 if (gcmIS_ERROR(status
))
755 /* Error, disable contiguous memory pool. */
756 device
->contiguousVidMem
= gcvNULL
;
757 device
->contiguousSize
= 0;
761 mem_region
= request_mem_region(
762 ContiguousBase
, ContiguousSize
, "galcore managed memory"
765 if (mem_region
== gcvNULL
)
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
);
784 = (gctPOINTER
) ioremap_nocache(ContiguousBase
, ContiguousSize
);
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. */
804 gcmkFOOTER_ARG("*Device=0x%x", * Device
);
809 gcmkVERIFY_OK(gckGALDEVICE_Destroy(device
));
815 /*******************************************************************************
817 ** gckGALDEVICE_Destroy
834 gckGALDEVICE_Destroy(
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
);
896 gcmkONERROR(_FreeMemory(
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. */
958 /*******************************************************************************
960 ** gckGALDEVICE_Setup_ISR
962 ** Start the ISR routine.
966 ** gckGALDEVICE Device
967 ** Pointer to an gckGALDEVICE object.
976 ** Setup successfully.
977 ** gcvSTATUS_GENERIC_IO
981 gckGALDEVICE_Setup_ISR(
982 IN gckGALDEVICE Device
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. */
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
1010 Device
->irqLines
[gcvCORE_MAJOR
], isrRoutine
, IRQF_DISABLED
,
1011 "galcore interrupt service", Device
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
;
1031 return gcvSTATUS_OK
;
1039 gckGALDEVICE_Setup_ISR_2D(
1040 IN gckGALDEVICE Device
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. */
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
1068 Device
->irqLines
[gcvCORE_2D
], isrRoutine2D
, IRQF_DISABLED
,
1069 "galcore interrupt service for 2D", Device
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
;
1089 return gcvSTATUS_OK
;
1097 gckGALDEVICE_Setup_ISR_VG(
1098 IN gckGALDEVICE Device
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. */
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
1126 Device
->irqLines
[gcvCORE_VG
], isrRoutineVG
, IRQF_DISABLED
,
1127 "galcore interrupt service for 2D", Device
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
;
1147 return gcvSTATUS_OK
;
1154 /*******************************************************************************
1156 ** gckGALDEVICE_Release_ISR
1158 ** Release the irq line.
1162 ** gckGALDEVICE Device
1163 ** Pointer to an gckGALDEVICE object.
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
])
1186 dove_gpio_free(DOVE_GPIO0_7
, "galcore interrupt service");
1188 free_irq(Device
->irqLines
[gcvCORE_MAJOR
], Device
);
1191 Device
->isrInitializeds
[gcvCORE_MAJOR
] = gcvFALSE
;
1195 return gcvSTATUS_OK
;
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
])
1211 dove_gpio_free(DOVE_GPIO0_7
, "galcore interrupt service");
1213 free_irq(Device
->irqLines
[gcvCORE_2D
], Device
);
1216 Device
->isrInitializeds
[gcvCORE_2D
] = gcvFALSE
;
1220 return gcvSTATUS_OK
;
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
])
1236 dove_gpio_free(DOVE_GPIO0_7
, "galcore interrupt service");
1238 free_irq(Device
->irqLines
[gcvCORE_VG
], Device
);
1241 Device
->isrInitializeds
[gcvCORE_VG
] = gcvFALSE
;
1245 return gcvSTATUS_OK
;
1248 /*******************************************************************************
1250 ** gckGALDEVICE_Start_Threads
1252 ** Start the daemon threads.
1256 ** gckGALDEVICE Device
1257 ** Pointer to an gckGALDEVICE object.
1266 ** Start successfully.
1267 ** gcvSTATUS_GENERIC_IO
1271 gckGALDEVICE_Start_Threads(
1272 IN gckGALDEVICE Device
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");
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");
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
;
1321 if (Device
->kernels
[gcvCORE_2D
] != gcvNULL
)
1323 /* Start the kernel thread. */
1324 task
= kthread_run(threadRoutine2D
, Device
, "galcore daemon thread for 2D");
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
;
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");
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
;
1366 Device
->threadInitializeds
[gcvCORE_VG
] = gcvFALSE
;
1370 return gcvSTATUS_OK
;
1377 /*******************************************************************************
1379 ** gckGALDEVICE_Stop_Threads
1381 ** Stop the gal device, including the following actions: stop the daemon
1382 ** thread, release the irq.
1386 ** gckGALDEVICE Device
1387 ** Pointer to an gckGALDEVICE object.
1398 gckGALDEVICE_Stop_Threads(
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
;
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.
1449 ** gckGALDEVICE Device
1450 ** Pointer to an gckGALDEVICE object.
1459 ** Start successfully.
1463 IN gckGALDEVICE Device
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
));
1502 return gcvSTATUS_OK
;
1509 /*******************************************************************************
1511 ** gckGALDEVICE_Stop
1513 ** Stop the gal device, including the following actions: stop the daemon
1514 ** thread, release the irq.
1518 ** gckGALDEVICE Device
1519 ** Pointer to an gckGALDEVICE object.
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
));
1572 return gcvSTATUS_OK
;