diff options
Diffstat (limited to 'drivers/mxc/amd-gpu/common/gsl_driver.c')
-rw-r--r-- | drivers/mxc/amd-gpu/common/gsl_driver.c | 329 |
1 files changed, 329 insertions, 0 deletions
diff --git a/drivers/mxc/amd-gpu/common/gsl_driver.c b/drivers/mxc/amd-gpu/common/gsl_driver.c new file mode 100644 index 000000000000..b8c5170a1425 --- /dev/null +++ b/drivers/mxc/amd-gpu/common/gsl_driver.c @@ -0,0 +1,329 @@ +/* Copyright (c) 2008-2010, Advanced Micro Devices. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * 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. + * + */ + +#include "gsl.h" +#include "gsl_hal.h" + + +////////////////////////////////////////////////////////////////////////////// +// defines +////////////////////////////////////////////////////////////////////////////// +#define GSL_PROCESSID_NONE 0x00000000 + +#define GSL_DRVFLAGS_EXTERNAL 0x10000000 +#define GSL_DRVFLAGS_INTERNAL 0x20000000 + + +////////////////////////////////////////////////////////////////////////////// +// globals +////////////////////////////////////////////////////////////////////////////// +#ifndef KGSL_USER_MODE +static gsl_flags_t gsl_driver_initialized = 0; +gsl_driver_t gsl_driver; +#else +extern gsl_flags_t gsl_driver_initialized; +extern gsl_driver_t gsl_driver; +#endif + + +////////////////////////////////////////////////////////////////////////////// +// functions +////////////////////////////////////////////////////////////////////////////// + +int +kgsl_driver_init0(gsl_flags_t flags, gsl_flags_t flags_debug) +{ + int status = GSL_SUCCESS; + + if (!(gsl_driver_initialized & GSL_FLAGS_INITIALIZED0)) + { +#ifdef GSL_LOG + // Uncomment these to enable logging. + //kgsl_log_init(); + //kgsl_log_open_stdout( KGSL_LOG_GROUP_ALL | KGSL_LOG_LEVEL_ALL | KGSL_LOG_TIMESTAMP + // | KGSL_LOG_THREAD_ID | KGSL_LOG_PROCESS_ID ); + //kgsl_log_open_file( "c:\\kgsl_log.txt", KGSL_LOG_GROUP_ALL | KGSL_LOG_LEVEL_ALL | KGSL_LOG_TIMESTAMP + // | KGSL_LOG_THREAD_ID | KGSL_LOG_PROCESS_ID ); +#endif + kos_memset(&gsl_driver, 0, sizeof(gsl_driver_t)); + + GSL_API_MUTEX_CREATE(); + } + +#ifdef _DEBUG + // set debug flags on every entry, and prior to hal initialization + gsl_driver.flags_debug |= flags_debug; +#else + (void) flags_debug; // unref formal parameter +#endif // _DEBUG + + + KGSL_DEBUG(GSL_DBGFLAGS_DUMPX, + { + KGSL_DEBUG_DUMPX_OPEN("dumpx.tb", 0); + KGSL_DEBUG_DUMPX( BB_DUMP_ENABLE, 0, 0, 0, " "); + }); + + KGSL_DEBUG_TBDUMP_OPEN("tbdump.txt"); + + if (!(gsl_driver_initialized & GSL_FLAGS_INITIALIZED0)) + { + GSL_API_MUTEX_LOCK(); + + // init hal + status = kgsl_hal_init(); + + if (status == GSL_SUCCESS) + { + gsl_driver_initialized |= flags; + gsl_driver_initialized |= GSL_FLAGS_INITIALIZED0; + } + + GSL_API_MUTEX_UNLOCK(); + } + + return (status); +} + +//---------------------------------------------------------------------------- + +int +kgsl_driver_close0(gsl_flags_t flags) +{ + int status = GSL_SUCCESS; + + if ((gsl_driver_initialized & GSL_FLAGS_INITIALIZED0) && (gsl_driver_initialized & flags)) + { + GSL_API_MUTEX_LOCK(); + + // close hall + status = kgsl_hal_close(); + + GSL_API_MUTEX_UNLOCK(); + + GSL_API_MUTEX_FREE(); + +#ifdef GSL_LOG + kgsl_log_close(); +#endif + + gsl_driver_initialized &= ~flags; + gsl_driver_initialized &= ~GSL_FLAGS_INITIALIZED0; + + KGSL_DEBUG(GSL_DBGFLAGS_DUMPX, + { + KGSL_DEBUG_DUMPX_CLOSE(); + }); + + KGSL_DEBUG_TBDUMP_CLOSE(); + } + + return (status); +} + +//---------------------------------------------------------------------------- + +KGSL_API int +kgsl_driver_init() +{ + // only an external (platform specific device driver) component should call this + + return(kgsl_driver_init0(GSL_DRVFLAGS_EXTERNAL, 0)); +} + +//---------------------------------------------------------------------------- + +KGSL_API int +kgsl_driver_close() +{ + // only an external (platform specific device driver) component should call this + + return(kgsl_driver_close0(GSL_DRVFLAGS_EXTERNAL)); +} + +//---------------------------------------------------------------------------- + +KGSL_API int +kgsl_driver_entry(gsl_flags_t flags) +{ + int status = GSL_FAILURE; + int index, i; + unsigned int pid; + + if (kgsl_driver_init0(GSL_DRVFLAGS_INTERNAL, flags) != GSL_SUCCESS) + { + return (GSL_FAILURE); + } + + kgsl_log_write( KGSL_LOG_GROUP_DRIVER | KGSL_LOG_LEVEL_TRACE, "--> int kgsl_driver_entry( gsl_flags_t flags=%d )\n", flags ); + + GSL_API_MUTEX_LOCK(); + + pid = GSL_CALLER_PROCESSID_GET(); + + // if caller process has not already opened access + status = kgsl_driver_getcallerprocessindex(pid, &index); + if (status != GSL_SUCCESS) + { + // then, add caller pid to process table + status = kgsl_driver_getcallerprocessindex(GSL_PROCESSID_NONE, &index); + if (status == GSL_SUCCESS) + { + gsl_driver.callerprocess[index] = pid; + gsl_driver.refcnt++; + } + } + + if (status == GSL_SUCCESS) + { + if (!(gsl_driver_initialized & GSL_FLAGS_INITIALIZED)) + { + // init memory apertures + status = kgsl_sharedmem_init(&gsl_driver.shmem); + if (status == GSL_SUCCESS) + { + // init devices + status = GSL_FAILURE; + for (i = 0; i < GSL_DEVICE_MAX; i++) + { + if (kgsl_device_init(&gsl_driver.device[i], (gsl_deviceid_t)(i + 1)) == GSL_SUCCESS) { + status = GSL_SUCCESS; + } + } + } + + if (status == GSL_SUCCESS) + { + gsl_driver_initialized |= GSL_FLAGS_INITIALIZED; + } + } + + // walk through process attach callbacks + if (status == GSL_SUCCESS) + { + for (i = 0; i < GSL_DEVICE_MAX; i++) + { + status = kgsl_device_attachcallback(&gsl_driver.device[i], pid); + if (status != GSL_SUCCESS) + { + break; + } + } + } + + // if something went wrong + if (status != GSL_SUCCESS) + { + // then, remove caller pid from process table + if (kgsl_driver_getcallerprocessindex(pid, &index) == GSL_SUCCESS) + { + gsl_driver.callerprocess[index] = GSL_PROCESSID_NONE; + gsl_driver.refcnt--; + } + } + } + + GSL_API_MUTEX_UNLOCK(); + + kgsl_log_write( KGSL_LOG_GROUP_DRIVER | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_driver_entry. Return value: %B\n", status ); + + return (status); +} + +//---------------------------------------------------------------------------- + +int +kgsl_driver_exit0(unsigned int pid) +{ + int status = GSL_SUCCESS; + int index, i; + + GSL_API_MUTEX_LOCK(); + + if (gsl_driver_initialized & GSL_FLAGS_INITIALIZED) + { + if (kgsl_driver_getcallerprocessindex(pid, &index) == GSL_SUCCESS) + { + // walk through process detach callbacks + for (i = 0; i < GSL_DEVICE_MAX; i++) + { + // Empty the freememqueue of this device + kgsl_cmdstream_memqueue_drain(&gsl_driver.device[i]); + + // Detach callback + status = kgsl_device_detachcallback(&gsl_driver.device[i], pid); + if (status != GSL_SUCCESS) + { + break; + } + } + + // last running caller process + if (gsl_driver.refcnt - 1 == 0) + { + // close devices + for (i = 0; i < GSL_DEVICE_MAX; i++) + { + kgsl_device_close(&gsl_driver.device[i]); + } + + // shutdown memory apertures + kgsl_sharedmem_close(&gsl_driver.shmem); + + gsl_driver_initialized &= ~GSL_FLAGS_INITIALIZED; + } + + // remove caller pid from process table + gsl_driver.callerprocess[index] = GSL_PROCESSID_NONE; + gsl_driver.refcnt--; + } + } + + GSL_API_MUTEX_UNLOCK(); + + if (!(gsl_driver_initialized & GSL_FLAGS_INITIALIZED)) + { + kgsl_driver_close0(GSL_DRVFLAGS_INTERNAL); + } + + return (status); +} + +//---------------------------------------------------------------------------- + +KGSL_API int +kgsl_driver_exit(void) +{ + int status; + + kgsl_log_write( KGSL_LOG_GROUP_DRIVER | KGSL_LOG_LEVEL_TRACE, "--> int kgsl_driver_exit()\n" ); + + status = kgsl_driver_exit0(GSL_CALLER_PROCESSID_GET()); + + kgsl_log_write( KGSL_LOG_GROUP_DRIVER | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_driver_exit(). Return value: %B\n", status ); + + return (status); +} + +//---------------------------------------------------------------------------- + +KGSL_API int +kgsl_driver_destroy(unsigned int pid) +{ + return (kgsl_driver_exit0(pid)); +} |