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_precomp.h"
28 #define _GC_OBJ_ZONE gcvZONE_VG
30 /******************************************************************************\
31 ******************************* gckKERNEL API Code ******************************
32 \******************************************************************************/
34 /*******************************************************************************
36 ** gckKERNEL_Construct
38 ** Construct a new gckKERNEL object.
43 ** Pointer to an gckOS object.
45 ** IN gctPOINTER Context
46 ** Pointer to a driver defined context.
51 ** Pointer to a variable that will hold the pointer to the gckKERNEL
54 gceSTATUS
gckVGKERNEL_Construct(
56 IN gctPOINTER Context
,
57 IN gckKERNEL inKernel
,
58 OUT gckVGKERNEL
* Kernel
62 gckVGKERNEL kernel
= gcvNULL
;
64 gcmkHEADER_ARG("Os=0x%x Context=0x%x", Os
, Context
);
65 /* Verify the arguments. */
66 gcmkVERIFY_OBJECT(Os
, gcvOBJ_OS
);
67 gcmkVERIFY_ARGUMENT(Kernel
!= gcvNULL
);
71 /* Allocate the gckKERNEL object. */
72 gcmkERR_BREAK(gckOS_Allocate(
74 sizeof(struct _gckVGKERNEL
),
75 (gctPOINTER
*) &kernel
78 /* Initialize the gckKERNEL object. */
79 kernel
->object
.type
= gcvOBJ_KERNEL
;
81 kernel
->context
= Context
;
82 kernel
->hardware
= gcvNULL
;
83 kernel
->interrupt
= gcvNULL
;
84 kernel
->command
= gcvNULL
;
85 kernel
->mmu
= gcvNULL
;
86 kernel
->kernel
= inKernel
;
88 /* Construct the gckVGHARDWARE object. */
89 gcmkERR_BREAK(gckVGHARDWARE_Construct(
93 /* Set pointer to gckKERNEL object in gckVGHARDWARE object. */
94 kernel
->hardware
->kernel
= kernel
;
96 /* Construct the gckVGINTERRUPT object. */
97 gcmkERR_BREAK(gckVGINTERRUPT_Construct(
98 kernel
, &kernel
->interrupt
101 /* Construct the gckVGCOMMAND object. */
102 gcmkERR_BREAK(gckVGCOMMAND_Construct(
103 kernel
, gcmKB2BYTES(8), gcmKB2BYTES(2), &kernel
->command
106 /* Construct the gckVGMMU object. */
107 gcmkERR_BREAK(gckVGMMU_Construct(
108 kernel
, gcmKB2BYTES(32), &kernel
->mmu
111 /* Return pointer to the gckKERNEL object. */
120 if (kernel
!= gcvNULL
)
122 if (kernel
->mmu
!= gcvNULL
)
124 gcmkVERIFY_OK(gckVGMMU_Destroy(kernel
->mmu
));
127 if (kernel
->command
!= gcvNULL
)
129 gcmkVERIFY_OK(gckVGCOMMAND_Destroy(kernel
->command
));
132 if (kernel
->interrupt
!= gcvNULL
)
134 gcmkVERIFY_OK(gckVGINTERRUPT_Destroy(kernel
->interrupt
));
137 if (kernel
->hardware
!= gcvNULL
)
139 gcmkVERIFY_OK(gckVGHARDWARE_Destroy(kernel
->hardware
));
142 gcmkVERIFY_OK(gckOS_Free(Os
, kernel
));
149 /*******************************************************************************
153 ** Destroy an gckKERNEL object.
158 ** Pointer to an gckKERNEL object to destroy.
164 gceSTATUS
gckVGKERNEL_Destroy(
165 IN gckVGKERNEL Kernel
170 gcmkHEADER_ARG("Kernel=0x%x", Kernel
);
172 /* Verify the arguments. */
173 gcmkVERIFY_OBJECT(Kernel
, gcvOBJ_KERNEL
);
177 /* Destroy the gckVGMMU object. */
178 if (Kernel
->mmu
!= gcvNULL
)
180 gcmkERR_BREAK(gckVGMMU_Destroy(Kernel
->mmu
));
181 Kernel
->mmu
= gcvNULL
;
184 /* Destroy the gckVGCOMMAND object. */
185 if (Kernel
->command
!= gcvNULL
)
187 gcmkERR_BREAK(gckVGCOMMAND_Destroy(Kernel
->command
));
188 Kernel
->command
= gcvNULL
;
191 /* Destroy the gckVGINTERRUPT object. */
192 if (Kernel
->interrupt
!= gcvNULL
)
194 gcmkERR_BREAK(gckVGINTERRUPT_Destroy(Kernel
->interrupt
));
195 Kernel
->interrupt
= gcvNULL
;
198 /* Destroy the gckVGHARDWARE object. */
199 if (Kernel
->hardware
!= gcvNULL
)
201 gcmkERR_BREAK(gckVGHARDWARE_Destroy(Kernel
->hardware
));
202 Kernel
->hardware
= gcvNULL
;
205 /* Mark the gckKERNEL object as unknown. */
206 Kernel
->object
.type
= gcvOBJ_UNKNOWN
;
208 /* Free the gckKERNEL object. */
209 gcmkERR_BREAK(gckOS_Free(Kernel
->os
, Kernel
));
219 /*******************************************************************************
221 ** gckKERNEL_AllocateLinearMemory
223 ** Function walks all required memory pools and allocates the requested
224 ** amount of video memory.
229 ** Pointer to an gckKERNEL object.
232 ** Pointer the desired memory pool.
235 ** Number of bytes to allocate.
237 ** gctSIZE_T Alignment
238 ** Required buffer alignment.
246 ** Pointer to the actual pool where the memory was allocated.
248 ** gcuVIDMEM_NODE_PTR * Node
252 gckKERNEL_AllocateLinearMemory(
254 IN OUT gcePOOL
* Pool
,
256 IN gctSIZE_T Alignment
,
257 IN gceSURF_TYPE Type
,
258 OUT gcuVIDMEM_NODE_PTR
* Node
263 gckVIDMEM videoMemory
;
265 /* Get initial pool. */
266 switch (pool
= *Pool
)
268 case gcvPOOL_DEFAULT
:
270 pool
= gcvPOOL_LOCAL_INTERNAL
;
273 case gcvPOOL_UNIFIED
:
274 pool
= gcvPOOL_SYSTEM
;
283 /* Verify the number of bytes to allocate. */
286 status
= gcvSTATUS_INVALID_ARGUMENT
;
290 if (pool
== gcvPOOL_VIRTUAL
)
292 /* Create a gcuVIDMEM_NODE for virtual memory. */
293 gcmkERR_BREAK(gckVIDMEM_ConstructVirtual(Kernel
, gcvFALSE
, Bytes
, Node
));
301 /* Get pointer to gckVIDMEM object for pool. */
302 status
= gckKERNEL_GetVideoMemoryPool(Kernel
, pool
, &videoMemory
);
304 if (status
== gcvSTATUS_OK
)
306 /* Allocate memory. */
307 status
= gckVIDMEM_AllocateLinear(videoMemory
,
313 if (status
== gcvSTATUS_OK
)
315 /* Memory allocated. */
321 if (pool
== gcvPOOL_LOCAL_INTERNAL
)
323 /* Advance to external memory. */
324 pool
= gcvPOOL_LOCAL_EXTERNAL
;
326 else if (pool
== gcvPOOL_LOCAL_EXTERNAL
)
328 /* Advance to contiguous system memory. */
329 pool
= gcvPOOL_SYSTEM
;
331 else if (pool
== gcvPOOL_SYSTEM
)
333 /* Advance to virtual memory. */
334 pool
= gcvPOOL_VIRTUAL
;
342 /* Loop only for multiple selection pools. */
343 while ((*Pool
== gcvPOOL_DEFAULT
)
344 || (*Pool
== gcvPOOL_LOCAL
)
345 || (*Pool
== gcvPOOL_UNIFIED
)
348 if (gcmIS_SUCCESS(status
))
350 /* Return pool used for allocation. */
358 /*******************************************************************************
360 ** gckKERNEL_Dispatch
362 ** Dispatch a command received from the user HAL layer.
367 ** Pointer to an gckKERNEL object.
369 ** gcsHAL_INTERFACE * Interface
370 ** Pointer to a gcsHAL_INTERFACE structure that defines the command to
375 ** gcsHAL_INTERFACE * Interface
376 ** Pointer to a gcsHAL_INTERFACE structure that receives any data to be
379 gceSTATUS
gckVGKERNEL_Dispatch(
382 IN OUT gcsHAL_INTERFACE
* Interface
386 gcsHAL_INTERFACE
* kernelInterface
= Interface
;
387 gcuVIDMEM_NODE_PTR node
;
390 gcmkHEADER_ARG("Kernel=0x%x Interface=0x%x ", Kernel
, Interface
);
392 /* Verify the arguments. */
393 gcmkVERIFY_OBJECT(Kernel
, gcvOBJ_KERNEL
);
394 gcmkVERIFY_ARGUMENT(Interface
!= gcvNULL
);
396 gcmkONERROR(gckOS_GetProcessID(&processID
));
398 /* Dispatch on command. */
399 switch (Interface
->command
)
401 case gcvHAL_QUERY_VIDEO_MEMORY
:
402 /* Query video memory size. */
403 gcmkERR_BREAK(gckKERNEL_QueryVideoMemory(
404 Kernel
, kernelInterface
408 case gcvHAL_QUERY_CHIP_IDENTITY
:
409 /* Query chip identity. */
410 gcmkERR_BREAK(gckVGHARDWARE_QueryChipIdentity(
411 Kernel
->vg
->hardware
,
412 &kernelInterface
->u
.QueryChipIdentity
.chipModel
,
413 &kernelInterface
->u
.QueryChipIdentity
.chipRevision
,
414 &kernelInterface
->u
.QueryChipIdentity
.chipFeatures
,
415 &kernelInterface
->u
.QueryChipIdentity
.chipMinorFeatures
,
416 &kernelInterface
->u
.QueryChipIdentity
.chipMinorFeatures2
420 case gcvHAL_QUERY_COMMAND_BUFFER
:
421 /* Query command buffer information. */
422 gcmkERR_BREAK(gckKERNEL_QueryCommandBuffer(
424 &kernelInterface
->u
.QueryCommandBuffer
.information
427 case gcvHAL_ALLOCATE_NON_PAGED_MEMORY
:
428 /* Allocate non-paged memory. */
429 gcmkERR_BREAK(gckOS_AllocateContiguous(
432 &kernelInterface
->u
.AllocateNonPagedMemory
.bytes
,
433 &kernelInterface
->u
.AllocateNonPagedMemory
.physical
,
434 &kernelInterface
->u
.AllocateNonPagedMemory
.logical
438 case gcvHAL_FREE_NON_PAGED_MEMORY
:
439 /* Free non-paged memory. */
440 gcmkERR_BREAK(gckOS_FreeNonPagedMemory(
442 kernelInterface
->u
.AllocateNonPagedMemory
.bytes
,
443 kernelInterface
->u
.AllocateNonPagedMemory
.physical
,
444 kernelInterface
->u
.AllocateNonPagedMemory
.logical
448 case gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY
:
449 /* Allocate contiguous memory. */
450 gcmkERR_BREAK(gckOS_AllocateContiguous(
453 &kernelInterface
->u
.AllocateNonPagedMemory
.bytes
,
454 &kernelInterface
->u
.AllocateNonPagedMemory
.physical
,
455 &kernelInterface
->u
.AllocateNonPagedMemory
.logical
459 case gcvHAL_FREE_CONTIGUOUS_MEMORY
:
460 /* Free contiguous memory. */
461 gcmkERR_BREAK(gckOS_FreeContiguous(
463 kernelInterface
->u
.AllocateNonPagedMemory
.physical
,
464 kernelInterface
->u
.AllocateNonPagedMemory
.logical
,
465 kernelInterface
->u
.AllocateNonPagedMemory
.bytes
469 case gcvHAL_ALLOCATE_VIDEO_MEMORY
:
472 gctUINT32 bitsPerPixel
;
475 /* Align width and height to tiles. */
476 gcmkERR_BREAK(gckVGHARDWARE_AlignToTile(
477 Kernel
->vg
->hardware
,
478 kernelInterface
->u
.AllocateVideoMemory
.type
,
479 &kernelInterface
->u
.AllocateVideoMemory
.width
,
480 &kernelInterface
->u
.AllocateVideoMemory
.height
483 /* Convert format into bytes per pixel and bytes per tile. */
484 gcmkERR_BREAK(gckVGHARDWARE_ConvertFormat(
485 Kernel
->vg
->hardware
,
486 kernelInterface
->u
.AllocateVideoMemory
.format
,
491 /* Compute number of bits for the allocation. */
493 = kernelInterface
->u
.AllocateVideoMemory
.width
494 * kernelInterface
->u
.AllocateVideoMemory
.height
495 * kernelInterface
->u
.AllocateVideoMemory
.depth
498 /* Compute number of bytes for the allocation. */
499 bytes
= gcmALIGN(bits
, 8) / 8;
501 /* Allocate memory. */
502 gcmkERR_BREAK(gckKERNEL_AllocateLinearMemory(
504 &kernelInterface
->u
.AllocateVideoMemory
.pool
,
507 kernelInterface
->u
.AllocateVideoMemory
.type
,
508 &kernelInterface
->u
.AllocateVideoMemory
.node
513 case gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY
:
514 /* Allocate memory. */
515 gcmkERR_BREAK(gckKERNEL_AllocateLinearMemory(
517 &kernelInterface
->u
.AllocateLinearVideoMemory
.pool
,
518 kernelInterface
->u
.AllocateLinearVideoMemory
.bytes
,
519 kernelInterface
->u
.AllocateLinearVideoMemory
.alignment
,
520 kernelInterface
->u
.AllocateLinearVideoMemory
.type
,
521 &kernelInterface
->u
.AllocateLinearVideoMemory
.node
525 case gcvHAL_FREE_VIDEO_MEMORY
:
526 /* Free video memory. */
527 gcmkERR_BREAK(gckVIDMEM_Free(
528 Interface
->u
.FreeVideoMemory
.node
532 case gcvHAL_MAP_MEMORY
:
534 gcmkERR_BREAK(gckKERNEL_MapMemory(
536 kernelInterface
->u
.MapMemory
.physical
,
537 kernelInterface
->u
.MapMemory
.bytes
,
538 &kernelInterface
->u
.MapMemory
.logical
542 case gcvHAL_UNMAP_MEMORY
:
544 gcmkERR_BREAK(gckKERNEL_UnmapMemory(
546 kernelInterface
->u
.MapMemory
.physical
,
547 kernelInterface
->u
.MapMemory
.bytes
,
548 kernelInterface
->u
.MapMemory
.logical
552 case gcvHAL_MAP_USER_MEMORY
:
553 /* Map user memory to DMA. */
554 gcmkERR_BREAK(gckOS_MapUserMemory(
556 kernelInterface
->u
.MapUserMemory
.memory
,
557 kernelInterface
->u
.MapUserMemory
.size
,
558 &kernelInterface
->u
.MapUserMemory
.info
,
559 &kernelInterface
->u
.MapUserMemory
.address
563 case gcvHAL_UNMAP_USER_MEMORY
:
564 /* Unmap user memory. */
565 gcmkERR_BREAK(gckOS_UnmapUserMemory(
567 kernelInterface
->u
.UnmapUserMemory
.memory
,
568 kernelInterface
->u
.UnmapUserMemory
.size
,
569 kernelInterface
->u
.UnmapUserMemory
.info
,
570 kernelInterface
->u
.UnmapUserMemory
.address
573 case gcvHAL_LOCK_VIDEO_MEMORY
:
574 /* Lock video memory. */
576 gckVIDMEM_Lock(Kernel
,
577 Interface
->u
.LockVideoMemory
.node
,
579 &Interface
->u
.LockVideoMemory
.address
));
581 node
= Interface
->u
.LockVideoMemory
.node
;
582 if (node
->VidMem
.memory
->object
.type
== gcvOBJ_VIDMEM
)
584 /* Map video memory address into user space. */
586 if (node
->VidMem
.logical
== gcvNULL
)
589 gckKERNEL_MapVideoMemory(Kernel
,
591 Interface
->u
.LockVideoMemory
.address
,
594 &node
->VidMem
.logical
));
597 Interface
->u
.LockVideoMemory
.memory
= node
->VidMem
.logical
;
600 gckKERNEL_MapVideoMemoryEx(Kernel
,
603 Interface
->u
.LockVideoMemory
.address
,
604 &Interface
->u
.LockVideoMemory
.memory
));
609 Interface
->u
.LockVideoMemory
.memory
= node
->Virtual
.logical
;
612 status
= gcvSTATUS_OK
;
616 /* Return logical address as physical address. */
617 Interface
->u
.LockVideoMemory
.address
=
618 gcmPTR2INT(Interface
->u
.LockVideoMemory
.memory
);
622 case gcvHAL_UNLOCK_VIDEO_MEMORY
:
623 /* Unlock video memory. */
624 node
= Interface
->u
.UnlockVideoMemory
.node
;
627 /* Save node information before it disappears. */
628 if (node
->VidMem
.memory
->object
.type
== gcvOBJ_VIDMEM
)
635 logical
= node
->Virtual
.logical
;
636 bytes
= node
->Virtual
.bytes
;
640 /* Unlock video memory. */
642 gckVIDMEM_Unlock(Kernel
,
644 Interface
->u
.UnlockVideoMemory
.type
,
645 &Interface
->u
.UnlockVideoMemory
.asynchroneous
));
648 /* Flush the translation cache for virtual surfaces. */
649 if (logical
!= gcvNULL
)
651 gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(Kernel
,
658 case gcvHAL_USER_SIGNAL
:
659 /* Dispatch depends on the user signal subcommands. */
660 switch(Interface
->u
.UserSignal
.command
)
662 case gcvUSER_SIGNAL_CREATE
:
663 /* Create a signal used in the user space. */
665 gckOS_CreateUserSignal(Kernel
->os
,
666 Interface
->u
.UserSignal
.manualReset
,
667 &Interface
->u
.UserSignal
.id
));
670 gckKERNEL_AddProcessDB(Kernel
,
671 processID
, gcvDB_SIGNAL
,
672 gcmINT2PTR(Interface
->u
.UserSignal
.id
),
677 case gcvUSER_SIGNAL_DESTROY
:
678 /* Destroy the signal. */
680 gckOS_DestroyUserSignal(Kernel
->os
,
681 Interface
->u
.UserSignal
.id
));
683 gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
685 processID
, gcvDB_SIGNAL
,
686 gcmINT2PTR(Interface
->u
.UserSignal
.id
)));
689 case gcvUSER_SIGNAL_SIGNAL
:
690 /* Signal the signal. */
692 gckOS_SignalUserSignal(Kernel
->os
,
693 Interface
->u
.UserSignal
.id
,
694 Interface
->u
.UserSignal
.state
));
697 case gcvUSER_SIGNAL_WAIT
:
698 /* Wait on the signal. */
699 status
= gckOS_WaitUserSignal(Kernel
->os
,
700 Interface
->u
.UserSignal
.id
,
701 Interface
->u
.UserSignal
.wait
);
705 /* Invalid user signal command. */
706 gcmkERR_BREAK(gcvSTATUS_INVALID_ARGUMENT
);
711 /* Commit a command and context buffer. */
712 gcmkERR_BREAK(gckVGCOMMAND_Commit(
714 kernelInterface
->u
.VGCommit
.context
,
715 kernelInterface
->u
.VGCommit
.queue
,
716 kernelInterface
->u
.VGCommit
.entryCount
,
717 kernelInterface
->u
.VGCommit
.taskTable
721 kernelInterface
->u
.Version
.major
= gcvVERSION_MAJOR
;
722 kernelInterface
->u
.Version
.minor
= gcvVERSION_MINOR
;
723 kernelInterface
->u
.Version
.patch
= gcvVERSION_PATCH
;
724 kernelInterface
->u
.Version
.build
= gcvVERSION_BUILD
;
725 status
= gcvSTATUS_OK
;
728 case gcvHAL_GET_BASE_ADDRESS
:
729 /* Get base address. */
731 gckOS_GetBaseAddress(Kernel
->os
,
732 &kernelInterface
->u
.GetBaseAddress
.baseAddress
));
735 /* Invalid command. */
736 status
= gcvSTATUS_INVALID_ARGUMENT
;
741 kernelInterface
->status
= status
;
745 /* Return the status. */
749 /*******************************************************************************
751 ** gckKERNEL_QueryCommandBuffer
753 ** Query command buffer attributes.
758 ** Pointer to an gckVGHARDWARE object.
762 ** gcsCOMMAND_BUFFER_INFO_PTR Information
763 ** Pointer to the information structure to receive buffer attributes.
766 gckKERNEL_QueryCommandBuffer(
768 OUT gcsCOMMAND_BUFFER_INFO_PTR Information
773 gcmkHEADER_ARG("Kernel=0x%x *Pool=0x%x",
774 Kernel
, Information
);
775 /* Verify the arguments. */
776 gcmkVERIFY_OBJECT(Kernel
, gcvOBJ_KERNEL
);
778 /* Get the information. */
779 status
= gckVGCOMMAND_QueryCommandBuffer(Kernel
->vg
->command
, Information
);
786 #endif /* gcdENABLE_VG */