diff options
author | Xianzhong <xianzhong.li@nxp.com> | 2018-04-23 18:58:00 +0800 |
---|---|---|
committer | Jason Liu <jason.hui.liu@nxp.com> | 2019-02-12 10:31:17 +0800 |
commit | 6b10e9c063b82fa47fb3807f0fe74647ff37233c (patch) | |
tree | 6f61a99764d0e35bb5763bbc9de24df3fb550135 /drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.c | |
parent | 95e6e2c6500c1c29e3c4d9b08bd9c909f86887e6 (diff) |
MGS-3705-2 gpu: add 6.2.4.p1 driver for 4.14 kernel
integrate 6.2.4.p1 driver and enable gpu build config,
fix 4.14 linux kernel build break in gpu-viv driver.
source branch: gpu-viv6/fsl_6.2.4.p1
source commit: 8aa3fcbcad9f51441b768bb41ce5c2686f7f143f
Signed-off-by: Xianzhong <xianzhong.li@nxp.com>
Diffstat (limited to 'drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.c')
-rw-r--r-- | drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.c | 643 |
1 files changed, 643 insertions, 0 deletions
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.c new file mode 100644 index 000000000000..93a914c9d79a --- /dev/null +++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_vg.c @@ -0,0 +1,643 @@ +/**************************************************************************** +* +* The MIT License (MIT) +* +* Copyright (c) 2014 - 2018 Vivante Corporation +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +* DEALINGS IN THE SOFTWARE. +* +***************************************************************************** +* +* The GPL License (GPL) +* +* Copyright (C) 2014 - 2018 Vivante Corporation +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software Foundation, +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +* +***************************************************************************** +* +* Note: This software is released under dual MIT and GPL licenses. A +* recipient may use this file under the terms of either the MIT license or +* GPL License. If you wish to use only one license not the other, you can +* indicate your decision by deleting one of the above license notices in your +* version of this file. +* +*****************************************************************************/ + + +#include "gc_hal_kernel_precomp.h" + +#if gcdENABLE_VG + +#define _GC_OBJ_ZONE gcvZONE_VG + +/******************************************************************************\ +******************************* gckKERNEL API Code ****************************** +\******************************************************************************/ + +/******************************************************************************* +** +** gckKERNEL_Construct +** +** Construct a new gckKERNEL object. +** +** INPUT: +** +** gckOS Os +** Pointer to an gckOS object. +** +** IN gctPOINTER Context +** Pointer to a driver defined context. +** +** OUTPUT: +** +** gckKERNEL * Kernel +** Pointer to a variable that will hold the pointer to the gckKERNEL +** object. +*/ +gceSTATUS gckVGKERNEL_Construct( + IN gckOS Os, + IN gctPOINTER Context, + IN gckKERNEL inKernel, + OUT gckVGKERNEL * Kernel + ) +{ + gceSTATUS status; + gckVGKERNEL kernel = gcvNULL; + + gcmkHEADER_ARG("Os=0x%x Context=0x%x", Os, Context); + /* Verify the arguments. */ + gcmkVERIFY_OBJECT(Os, gcvOBJ_OS); + gcmkVERIFY_ARGUMENT(Kernel != gcvNULL); + + do + { + /* Allocate the gckKERNEL object. */ + gcmkERR_BREAK(gckOS_Allocate( + Os, + sizeof(struct _gckVGKERNEL), + (gctPOINTER *) &kernel + )); + + /* Initialize the gckKERNEL object. */ + kernel->object.type = gcvOBJ_KERNEL; + kernel->os = Os; + kernel->context = Context; + kernel->hardware = gcvNULL; + kernel->interrupt = gcvNULL; + kernel->command = gcvNULL; + kernel->mmu = gcvNULL; + kernel->kernel = inKernel; + + /* Construct the gckVGHARDWARE object. */ + gcmkERR_BREAK(gckVGHARDWARE_Construct( + Os, &kernel->hardware + )); + + /* Set pointer to gckKERNEL object in gckVGHARDWARE object. */ + kernel->hardware->kernel = kernel; + + /* Construct the gckVGINTERRUPT object. */ + gcmkERR_BREAK(gckVGINTERRUPT_Construct( + kernel, &kernel->interrupt + )); + + /* Construct the gckVGCOMMAND object. */ + gcmkERR_BREAK(gckVGCOMMAND_Construct( + kernel, gcmKB2BYTES(8), gcmKB2BYTES(2), &kernel->command + )); + + /* Construct the gckVGMMU object. */ + gcmkERR_BREAK(gckVGMMU_Construct( + kernel, gcmKB2BYTES(gcdGC355_VGMMU_MEMORY_SIZE_KB), &kernel->mmu + )); + + /* Return pointer to the gckKERNEL object. */ + *Kernel = kernel; + + gcmkFOOTER_ARG("*Kernel=0x%x", *Kernel); + /* Success. */ + return gcvSTATUS_OK; + } + while (gcvFALSE); + + /* Roll back. */ + if (kernel != gcvNULL) + { + if (kernel->mmu != gcvNULL) + { + gcmkVERIFY_OK(gckVGMMU_Destroy(kernel->mmu)); + } + + if (kernel->command != gcvNULL) + { + gcmkVERIFY_OK(gckVGCOMMAND_Destroy(kernel->command)); + } + + if (kernel->interrupt != gcvNULL) + { + gcmkVERIFY_OK(gckVGINTERRUPT_Destroy(kernel->interrupt)); + } + + if (kernel->hardware != gcvNULL) + { + gcmkVERIFY_OK(gckVGHARDWARE_Destroy(kernel->hardware)); + } + + gcmkVERIFY_OK(gckOS_Free(Os, kernel)); + } + + gcmkFOOTER(); + /* Return status. */ + return status; +} + +/******************************************************************************* +** +** gckKERNEL_Destroy +** +** Destroy an gckKERNEL object. +** +** INPUT: +** +** gckKERNEL Kernel +** Pointer to an gckKERNEL object to destroy. +** +** OUTPUT: +** +** Nothing. +*/ +gceSTATUS gckVGKERNEL_Destroy( + IN gckVGKERNEL Kernel + ) +{ + gceSTATUS status; + + gcmkHEADER_ARG("Kernel=0x%x", Kernel); + + /* Verify the arguments. */ + gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL); + + do + { + /* Destroy the gckVGMMU object. */ + if (Kernel->mmu != gcvNULL) + { + gcmkERR_BREAK(gckVGMMU_Destroy(Kernel->mmu)); + Kernel->mmu = gcvNULL; + } + + /* Destroy the gckVGCOMMAND object. */ + if (Kernel->command != gcvNULL) + { + gcmkERR_BREAK(gckVGCOMMAND_Destroy(Kernel->command)); + Kernel->command = gcvNULL; + } + + /* Destroy the gckVGINTERRUPT object. */ + if (Kernel->interrupt != gcvNULL) + { + gcmkERR_BREAK(gckVGINTERRUPT_Destroy(Kernel->interrupt)); + Kernel->interrupt = gcvNULL; + } + + /* Destroy the gckVGHARDWARE object. */ + if (Kernel->hardware != gcvNULL) + { + gcmkERR_BREAK(gckVGHARDWARE_Destroy(Kernel->hardware)); + Kernel->hardware = gcvNULL; + } + + /* Mark the gckKERNEL object as unknown. */ + Kernel->object.type = gcvOBJ_UNKNOWN; + + /* Free the gckKERNEL object. */ + gcmkERR_BREAK(gckOS_Free(Kernel->os, Kernel)); + } + while (gcvFALSE); + + gcmkFOOTER(); + + /* Return status. */ + return status; +} + +/******************************************************************************* +** +** gckKERNEL_Dispatch +** +** Dispatch a command received from the user HAL layer. +** +** INPUT: +** +** gckKERNEL Kernel +** Pointer to an gckKERNEL object. +** +** gcsHAL_INTERFACE * Interface +** Pointer to a gcsHAL_INTERFACE structure that defines the command to +** be dispatched. +** +** OUTPUT: +** +** gcsHAL_INTERFACE * Interface +** Pointer to a gcsHAL_INTERFACE structure that receives any data to be +** returned. +*/ +gceSTATUS gckVGKERNEL_Dispatch( + IN gckKERNEL Kernel, + IN gctBOOL FromUser, + IN OUT gcsHAL_INTERFACE * Interface + ) +{ + gceSTATUS status; + gcsHAL_INTERFACE * kernelInterface = Interface; + gctUINT32 processID; + gckKERNEL kernel = Kernel; + gctPHYS_ADDR physical = gcvNULL; + gctPOINTER logical = gcvNULL; + gctSIZE_T bytes = 0; + gctBOOL powerMutexAcquired = gcvFALSE; + + gcmkHEADER_ARG("Kernel=0x%x Interface=0x%x ", Kernel, Interface); + + /* Verify the arguments. */ + gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL); + gcmkVERIFY_ARGUMENT(Interface != gcvNULL); + + gcmkONERROR(gckOS_GetProcessID(&processID)); + + /* Dispatch on command. */ + switch (Interface->command) + { + case gcvHAL_QUERY_CHIP_IDENTITY: + /* Query chip identity. */ + gcmkERR_BREAK(gckVGHARDWARE_QueryChipIdentity( + Kernel->vg->hardware, + &kernelInterface->u.QueryChipIdentity.chipModel, + &kernelInterface->u.QueryChipIdentity.chipRevision, + &kernelInterface->u.QueryChipIdentity.productID, + &kernelInterface->u.QueryChipIdentity.ecoID, + &kernelInterface->u.QueryChipIdentity.customerID, + &kernelInterface->u.QueryChipIdentity.chipFeatures, + &kernelInterface->u.QueryChipIdentity.chipMinorFeatures, + &kernelInterface->u.QueryChipIdentity.chipMinorFeatures2 + )); + break; + + case gcvHAL_QUERY_COMMAND_BUFFER: + /* Query command buffer information. */ + gcmkERR_BREAK(gckKERNEL_QueryCommandBuffer( + Kernel, + &kernelInterface->u.QueryCommandBuffer.information + )); + break; + + case gcvHAL_ALLOCATE_NON_PAGED_MEMORY: + bytes = (gctSIZE_T) kernelInterface->u.AllocateNonPagedMemory.bytes; + /* Allocate non-paged memory. */ + gcmkERR_BREAK(gckOS_AllocateNonPagedMemory( + Kernel->os, + gcvTRUE, + &bytes, + &physical, + &logical + )); + + kernelInterface->u.AllocateNonPagedMemory.bytes = bytes; + kernelInterface->u.AllocateNonPagedMemory.logical = gcmPTR_TO_UINT64(logical); + kernelInterface->u.AllocateNonPagedMemory.physical = gcmPTR_TO_NAME(physical); + break; + + case gcvHAL_FREE_NON_PAGED_MEMORY: + physical = gcmNAME_TO_PTR(kernelInterface->u.FreeNonPagedMemory.physical); + + /* Unmap user logical out of physical memory first. */ + gcmkERR_BREAK(gckOS_UnmapUserLogical( + Kernel->os, + physical, + (gctSIZE_T) kernelInterface->u.FreeNonPagedMemory.bytes, + gcmUINT64_TO_PTR(kernelInterface->u.FreeNonPagedMemory.logical))); + + + /* Free non-paged memory. */ + gcmkERR_BREAK(gckOS_FreeNonPagedMemory( + Kernel->os, + (gctSIZE_T) kernelInterface->u.FreeNonPagedMemory.bytes, + physical, + gcmUINT64_TO_PTR(kernelInterface->u.FreeNonPagedMemory.logical) + )); + + gcmRELEASE_NAME(kernelInterface->u.FreeNonPagedMemory.physical); + break; + + case gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY: + bytes = (gctSIZE_T) kernelInterface->u.AllocateContiguousMemory.bytes; + /* Allocate contiguous memory. */ + gcmkERR_BREAK(gckOS_AllocateContiguous( + Kernel->os, + gcvTRUE, + &bytes, + &physical, + &logical + )); + + kernelInterface->u.AllocateContiguousMemory.bytes = bytes; + kernelInterface->u.AllocateContiguousMemory.logical = gcmPTR_TO_UINT64(logical); + kernelInterface->u.AllocateContiguousMemory.physical = gcmPTR_TO_NAME(physical); + break; + + case gcvHAL_FREE_CONTIGUOUS_MEMORY: + physical = gcmNAME_TO_PTR(kernelInterface->u.FreeContiguousMemory.physical); + /* Unmap user logical out of physical memory first. */ + gcmkERR_BREAK(gckOS_UnmapUserLogical( + Kernel->os, + physical, + (gctSIZE_T) kernelInterface->u.FreeContiguousMemory.bytes, + gcmUINT64_TO_PTR(kernelInterface->u.FreeContiguousMemory.logical) + )); + + /* Free contiguous memory. */ + gcmkERR_BREAK(gckOS_FreeContiguous( + Kernel->os, + physical, + gcmUINT64_TO_PTR(kernelInterface->u.FreeContiguousMemory.logical), + (gctSIZE_T) kernelInterface->u.FreeContiguousMemory.bytes + )); + + gcmRELEASE_NAME(kernelInterface->u.FreeContiguousMemory.physical); + break; + + case gcvHAL_ALLOCATE_VIDEO_MEMORY: + gcmkERR_BREAK(gcvSTATUS_NOT_SUPPORTED); + break; + + case gcvHAL_MAP_MEMORY: + /* Map memory. */ + gcmkERR_BREAK(gckKERNEL_MapMemory( + Kernel, + gcmINT2PTR(kernelInterface->u.MapMemory.physical), + (gctSIZE_T) kernelInterface->u.MapMemory.bytes, + &logical + )); + kernelInterface->u.MapMemory.logical = gcmPTR_TO_UINT64(logical); + break; + + case gcvHAL_UNMAP_MEMORY: + /* Unmap memory. */ + gcmkERR_BREAK(gckKERNEL_UnmapMemory( + Kernel, + gcmINT2PTR(kernelInterface->u.MapMemory.physical), + (gctSIZE_T) kernelInterface->u.MapMemory.bytes, + gcmUINT64_TO_PTR(kernelInterface->u.MapMemory.logical), + processID + )); + break; + + case gcvHAL_MAP_USER_MEMORY: + + gcmkONERROR(gcvSTATUS_NOT_SUPPORTED); + + break; + + case gcvHAL_UNMAP_USER_MEMORY: + + gcmkONERROR(gcvSTATUS_NOT_SUPPORTED); + + break; + + case gcvHAL_LOCK_VIDEO_MEMORY: + gcmkONERROR(gckKERNEL_LockVideoMemory(Kernel, gcvCORE_VG, processID, FromUser, Interface)); + break; + + case gcvHAL_BOTTOM_HALF_UNLOCK_VIDEO_MEMORY: + gcmkERR_BREAK(gckKERNEL_BottomHalfUnlockVideoMemory(Kernel, processID, + kernelInterface->u.BottomHalfUnlockVideoMemory.node)); + break; + + case gcvHAL_USER_SIGNAL: +#if !USE_NEW_LINUX_SIGNAL + /* Dispatch depends on the user signal subcommands. */ + switch(Interface->u.UserSignal.command) + { + case gcvUSER_SIGNAL_CREATE: + /* Create a signal used in the user space. */ + gcmkERR_BREAK( + gckOS_CreateUserSignal(Kernel->os, + Interface->u.UserSignal.manualReset, + &Interface->u.UserSignal.id)); + + gcmkVERIFY_OK( + gckKERNEL_AddProcessDB(Kernel, + processID, gcvDB_SIGNAL, + gcmINT2PTR(Interface->u.UserSignal.id), + gcvNULL, + 0)); + break; + + case gcvUSER_SIGNAL_DESTROY: + gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB( + Kernel, + processID, gcvDB_SIGNAL, + gcmINT2PTR(Interface->u.UserSignal.id))); + + /* Destroy the signal. */ + gcmkERR_BREAK( + gckOS_DestroyUserSignal(Kernel->os, + Interface->u.UserSignal.id)); + + break; + + case gcvUSER_SIGNAL_SIGNAL: + /* Signal the signal. */ + gcmkERR_BREAK( + gckOS_SignalUserSignal(Kernel->os, + Interface->u.UserSignal.id, + Interface->u.UserSignal.state)); + break; + + case gcvUSER_SIGNAL_WAIT: + /* Wait on the signal. */ + status = gckOS_WaitUserSignal(Kernel->os, + Interface->u.UserSignal.id, + Interface->u.UserSignal.wait); + break; + + default: + /* Invalid user signal command. */ + gcmkERR_BREAK(gcvSTATUS_INVALID_ARGUMENT); + } +#endif + break; + + case gcvHAL_COMMIT: + /* Commit a command and context buffer. */ + gcmkERR_BREAK(gckVGCOMMAND_Commit( + Kernel->vg->command, + gcmUINT64_TO_PTR(kernelInterface->u.VGCommit.context), + gcmUINT64_TO_PTR(kernelInterface->u.VGCommit.queue), + kernelInterface->u.VGCommit.entryCount, + gcmUINT64_TO_PTR(kernelInterface->u.VGCommit.taskTable) + )); + break; + + case gcvHAL_GET_BASE_ADDRESS: + /* Get base address. */ + gcmkONERROR( + gckOS_GetBaseAddress(Kernel->os, + &Interface->u.GetBaseAddress.baseAddress)); + break; + + case gcvHAL_EVENT_COMMIT: + gcmkERR_BREAK(gcvSTATUS_NOT_SUPPORTED); + break; + case gcvHAL_READ_REGISTER: +#if gcdREGISTER_ACCESS_FROM_USER + { + gceCHIPPOWERSTATE power; + + gcmkONERROR(gckOS_AcquireMutex(Kernel->os, Kernel->vg->hardware->powerMutex, gcvINFINITE)); + powerMutexAcquired = gcvTRUE; + gcmkONERROR(gckVGHARDWARE_QueryPowerManagementState(Kernel->vg->hardware, + &power)); + if (power == gcvPOWER_ON) + { + /* Read a register. */ + gcmkONERROR(gckOS_ReadRegisterEx( + Kernel->os, + Kernel->core, + Interface->u.ReadRegisterData.address, + &Interface->u.ReadRegisterData.data)); + } + else + { + /* Chip is in power-state. */ + Interface->u.ReadRegisterData.data = 0; + status = gcvSTATUS_CHIP_NOT_READY; + } + gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->vg->hardware->powerMutex)); + powerMutexAcquired = gcvFALSE; + } +#else + /* No access from user land to read registers. */ + Interface->u.ReadRegisterData.data = 0; + status = gcvSTATUS_NOT_SUPPORTED; +#endif + break; + + case gcvHAL_WRITE_REGISTER: +#if gcdREGISTER_ACCESS_FROM_USER + { + gceCHIPPOWERSTATE power; + + gcmkONERROR(gckOS_AcquireMutex(Kernel->os, Kernel->vg->hardware->powerMutex, gcvINFINITE)); + powerMutexAcquired = gcvTRUE; + gcmkONERROR(gckVGHARDWARE_QueryPowerManagementState(Kernel->vg->hardware, + &power)); + if (power == gcvPOWER_ON) + { + /* Write a register. */ + gcmkONERROR( + gckOS_WriteRegisterEx(Kernel->os, + Kernel->core, + Interface->u.WriteRegisterData.address, + Interface->u.WriteRegisterData.data)); + } + else + { + /* Chip is in power-state. */ + Interface->u.WriteRegisterData.data = 0; + status = gcvSTATUS_CHIP_NOT_READY; + } + gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->vg->hardware->powerMutex)); + powerMutexAcquired = gcvFALSE; + } +#else + /* No access from user land to write registers. */ + status = gcvSTATUS_NOT_SUPPORTED; +#endif + break; + default: + /* Invalid command, try gckKERNEL_Dispatch */ + status = gckKERNEL_Dispatch(Kernel, gcvNULL, gcvTRUE, Interface); + } + +OnError: + /* Save status. */ + kernelInterface->status = status; + if (powerMutexAcquired == gcvTRUE) + { + gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->vg->hardware->powerMutex)); + } + + gcmkFOOTER(); + + /* Return the status. */ + return status; +} + +/******************************************************************************* +** +** gckKERNEL_QueryCommandBuffer +** +** Query command buffer attributes. +** +** INPUT: +** +** gckKERNEL Kernel +** Pointer to an gckVGHARDWARE object. +** +** OUTPUT: +** +** gcsCOMMAND_BUFFER_INFO_PTR Information +** Pointer to the information structure to receive buffer attributes. +*/ +gceSTATUS +gckKERNEL_QueryCommandBuffer( + IN gckKERNEL Kernel, + OUT gcsCOMMAND_BUFFER_INFO_PTR Information + ) +{ + gceSTATUS status; + + gcmkHEADER_ARG("Kernel=0x%x *Pool=0x%x", + Kernel, Information); + /* Verify the arguments. */ + gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL); + + /* Get the information. */ + status = gckVGCOMMAND_QueryCommandBuffer(Kernel->vg->command, Information); + + gcmkFOOTER(); + /* Return status. */ + return status; +} + +#endif /* gcdENABLE_VG */ |