blob: 9edee40becc025f965fde4184428ffbd2569003d [file] [log] [blame]
/**********************************************************************
*
* Copyright (C) Imagination Technologies Ltd. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful but, except
* as otherwise stated in writing, 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 St - Fifth Floor, Boston, MA 02110-1301 USA.
*
* The full GNU General Public License is included in this distribution in
* the file called "COPYING".
*
* Contact Information:
* Imagination Technologies Ltd. <gpl-support@imgtec.com>
* Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
*
******************************************************************************/
#include <linux/version.h>
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))
#ifndef AUTOCONF_INCLUDED
#include <linux/config.h>
#endif
#endif
#if defined(SUPPORT_DRI_DRM) && !defined(SUPPORT_DRI_DRM_PLUGIN)
#define PVR_MOD_STATIC
#else
#if defined(LDM_PLATFORM)
#define PVR_LDM_PLATFORM_MODULE
#define PVR_LDM_MODULE
#else
#if defined(LDM_PCI)
#define PVR_LDM_PCI_MODULE
#define PVR_LDM_MODULE
#endif
#endif
#define PVR_MOD_STATIC static
#endif
#if defined(PVR_LDM_PLATFORM_PRE_REGISTERED)
#if !defined(NO_HARDWARE)
#define PVR_USE_PRE_REGISTERED_PLATFORM_DEV
#endif
#endif
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/proc_fs.h>
#if defined(SUPPORT_DRI_DRM)
#include <drm/drmP.h>
#if defined(PVR_SECURE_DRM_AUTH_EXPORT)
#include "env_perproc.h"
#endif
#endif
#if defined(PVR_LDM_PLATFORM_MODULE)
#include <linux/platform_device.h>
#endif
#if defined(PVR_LDM_PCI_MODULE)
#include <linux/pci.h>
#endif
#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL)
#include <asm/uaccess.h>
#endif
#if defined(PVR_LDM_MODULE) || defined(PVR_DRI_DRM_PLATFORM_DEV)
#include <asm/atomic.h>
#endif
#include "img_defs.h"
#include "services.h"
#include "kerneldisplay.h"
#include "kernelbuffer.h"
#include "syscommon.h"
#include "pvrmmap.h"
#include "mutils.h"
#include "mm.h"
#include "mmap.h"
#include "mutex.h"
#include "pvr_debug.h"
#include "srvkm.h"
#include "perproc.h"
#include "handle.h"
#include "pvr_bridge_km.h"
#include "proc.h"
#include "pvrmodule.h"
#include "private_data.h"
#include "lock.h"
#include "linkage.h"
#include "buffer_manager.h"
#if defined(SUPPORT_DRI_DRM)
#include "pvr_drm.h"
#endif
#if defined(PVR_LDM_MODULE)
#define DRVNAME PVR_LDM_DRIVER_REGISTRATION_NAME
#endif
#define DEVNAME PVRSRV_MODNAME
#if defined(SUPPORT_DRI_DRM)
#define PRIVATE_DATA(pFile) ((pFile)->driver_priv)
#else
#define PRIVATE_DATA(pFile) ((pFile)->private_data)
#endif
MODULE_SUPPORTED_DEVICE(DEVNAME);
#if defined(PVRSRV_NEED_PVR_DPF)
#include <linux/moduleparam.h>
extern IMG_UINT32 gPVRDebugLevel;
module_param(gPVRDebugLevel, uint, 0644);
MODULE_PARM_DESC(gPVRDebugLevel, "Sets the level of debug output (default 0x7)");
#endif
#if defined(CONFIG_SGX_DVFS_MODE_NONE)
#define DEFAULT_IDLE_MODE 0
#elif defined(CONFIG_SGX_DVFS_MODE_LINEAR)
#define DEFAULT_IDLE_MODE 1
#elif defined(CONFIG_SGX_DVFS_MODE_OPTIMIZED)
#define DEFAULT_IDLE_MODE 2
#else
#error "sgx ide mode not defined"
#endif
bool sgx_idle_logging = false;
module_param(sgx_idle_logging, bool, 0644);
uint sgx_idle_mode = DEFAULT_IDLE_MODE;
module_param(sgx_idle_mode, uint, 0644);
uint sgx_idle_timeout = CONFIG_SGX_DVFS_IDLE_TIMEOUT * NSEC_PER_USEC;
module_param(sgx_idle_timeout, uint, 0644);
uint sgx_apm_latency = SYS_SGX_ACTIVE_POWER_LATENCY_MS;
module_param(sgx_apm_latency, uint, 0644);
#if defined(CONFIG_ION_OMAP)
#include <linux/ion.h>
#include <linux/omap_ion.h>
extern struct ion_device *omap_ion_device;
struct ion_client *gpsIONClient;
EXPORT_SYMBOL(gpsIONClient);
#endif
EXPORT_SYMBOL(PVRGetDisplayClassJTable);
EXPORT_SYMBOL(PVRGetBufferClassJTable);
#if defined(PVR_LDM_MODULE) && !defined(SUPPORT_DRI_DRM)
static struct class *psPvrClass;
#endif
#if !defined(SUPPORT_DRI_DRM)
static int AssignedMajorNumber;
static int PVRSRVOpen(struct inode* pInode, struct file* pFile);
static int PVRSRVRelease(struct inode* pInode, struct file* pFile);
static struct file_operations pvrsrv_fops =
{
.owner=THIS_MODULE,
.unlocked_ioctl = PVRSRV_BridgeDispatchKM,
.open=PVRSRVOpen,
.release=PVRSRVRelease,
.mmap=PVRMMap,
};
#endif
PVRSRV_LINUX_MUTEX gPVRSRVLock;
IMG_UINT32 gui32ReleasePID;
#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL)
static IMG_UINT32 gPVRPowerLevel;
#endif
#if defined(PVR_LDM_MODULE)
#if defined(PVR_LDM_PLATFORM_MODULE)
#define LDM_DEV struct platform_device
#define LDM_DRV struct platform_driver
#endif
#if defined(PVR_LDM_PCI_MODULE)
#define LDM_DEV struct pci_dev
#define LDM_DRV struct pci_driver
#endif
#if defined(PVR_LDM_PLATFORM_MODULE)
static int PVRSRVDriverRemove(LDM_DEV *device);
static int PVRSRVDriverProbe(LDM_DEV *device);
#endif
#if defined(PVR_LDM_PCI_MODULE)
static void PVRSRVDriverRemove(LDM_DEV *device);
static int PVRSRVDriverProbe(LDM_DEV *device, const struct pci_device_id *id);
#endif
static int PVRSRVDriverSuspend(LDM_DEV *device, pm_message_t state);
static void PVRSRVDriverShutdown(LDM_DEV *device);
static int PVRSRVDriverResume(LDM_DEV *device);
#if defined(PVR_LDM_PCI_MODULE)
struct pci_device_id powervr_id_table[] __devinitdata = {
{PCI_DEVICE(SYS_SGX_DEV_VENDOR_ID, SYS_SGX_DEV_DEVICE_ID)},
#if defined (SYS_SGX_DEV1_DEVICE_ID)
{PCI_DEVICE(SYS_SGX_DEV_VENDOR_ID, SYS_SGX_DEV1_DEVICE_ID)},
#endif
{0}
};
MODULE_DEVICE_TABLE(pci, powervr_id_table);
#endif
#if defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV)
static struct platform_device_id powervr_id_table[] __devinitdata = {
{SYS_SGX_DEV_NAME, 0},
{}
};
#endif
static LDM_DRV powervr_driver = {
#if defined(PVR_LDM_PLATFORM_MODULE)
.driver = {
.name = DRVNAME,
},
#endif
#if defined(PVR_LDM_PCI_MODULE)
.name = DRVNAME,
#endif
#if defined(PVR_LDM_PCI_MODULE) || defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV)
.id_table = powervr_id_table,
#endif
.probe = PVRSRVDriverProbe,
#if defined(PVR_LDM_PLATFORM_MODULE)
.remove = PVRSRVDriverRemove,
#endif
#if defined(PVR_LDM_PCI_MODULE)
.remove = __devexit_p(PVRSRVDriverRemove),
#endif
.suspend = PVRSRVDriverSuspend,
.resume = PVRSRVDriverResume,
.shutdown = PVRSRVDriverShutdown,
};
LDM_DEV *gpsPVRLDMDev;
#if defined(MODULE) && defined(PVR_LDM_PLATFORM_MODULE) && \
!defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV)
static void PVRSRVDeviceRelease(struct device unref__ *pDevice)
{
}
static struct platform_device powervr_device = {
.name = DEVNAME,
.id = -1,
.dev = {
.release = PVRSRVDeviceRelease
}
};
#endif
#if defined(PVR_LDM_PLATFORM_MODULE)
static int PVRSRVDriverProbe(LDM_DEV *pDevice)
#endif
#if defined(PVR_LDM_PCI_MODULE)
static int __devinit PVRSRVDriverProbe(LDM_DEV *pDevice, const struct pci_device_id *id)
#endif
{
SYS_DATA *psSysData;
PVR_TRACE(("PVRSRVDriverProbe(pDevice=%p)", pDevice));
#if 0
if (PerDeviceSysInitialise((IMG_PVOID)pDevice) != PVRSRV_OK)
{
return -EINVAL;
}
#endif
psSysData = SysAcquireDataNoCheck();
if (psSysData == IMG_NULL)
{
gpsPVRLDMDev = pDevice;
if (SysInitialise() != PVRSRV_OK)
{
return -ENODEV;
}
}
#if defined(CONFIG_ION_OMAP)
gpsIONClient = ion_client_create(omap_ion_device,
1 << ION_HEAP_TYPE_CARVEOUT |
1 << OMAP_ION_HEAP_TYPE_TILER,
"pvr");
if (IS_ERR_OR_NULL(gpsIONClient))
{
PVR_DPF((PVR_DBG_ERROR, "PVRSRVDriverProbe: Couldn't create ion client"));
return PTR_ERR(gpsIONClient);
}
#endif
return 0;
}
#if defined (PVR_LDM_PLATFORM_MODULE)
static int PVRSRVDriverRemove(LDM_DEV *pDevice)
#endif
#if defined(PVR_LDM_PCI_MODULE)
static void __devexit PVRSRVDriverRemove(LDM_DEV *pDevice)
#endif
{
SYS_DATA *psSysData;
PVR_TRACE(("PVRSRVDriverRemove(pDevice=%p)", pDevice));
#if defined(CONFIG_ION_OMAP)
ion_client_destroy(gpsIONClient);
gpsIONClient = IMG_NULL;
#endif
SysAcquireData(&psSysData);
#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL)
if (gPVRPowerLevel != 0)
{
if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D0) == PVRSRV_OK)
{
gPVRPowerLevel = 0;
}
}
#endif
(void) SysDeinitialise(psSysData);
gpsPVRLDMDev = IMG_NULL;
#if 0
if (PerDeviceSysDeInitialise((IMG_PVOID)pDevice) != PVRSRV_OK)
{
return -EINVAL;
}
#endif
#if defined (PVR_LDM_PLATFORM_MODULE)
return 0;
#endif
#if defined (PVR_LDM_PCI_MODULE)
return;
#endif
}
#endif
#if defined(PVR_LDM_MODULE) || defined(PVR_DRI_DRM_PLATFORM_DEV)
#if defined(SUPPORT_DRI_DRM) && !defined(PVR_DRI_DRM_PLATFORM_DEV) && \
!defined(SUPPORT_DRI_DRM_PLUGIN)
void PVRSRVDriverShutdown(struct drm_device *pDevice)
#else
PVR_MOD_STATIC void PVRSRVDriverShutdown(LDM_DEV *pDevice)
#endif
{
static atomic_t sDriverIsShutdown = ATOMIC_INIT(1);
PVR_TRACE(("PVRSRVDriverShutdown(pDevice=%p)", pDevice));
if (atomic_dec_and_test(&sDriverIsShutdown))
{
LinuxLockMutex(&gPVRSRVLock);
(void) PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D3);
}
}
#endif
#if defined(PVR_LDM_MODULE) || defined(SUPPORT_DRI_DRM)
#if defined(SUPPORT_DRI_DRM) && !defined(PVR_DRI_DRM_PLATFORM_DEV) && \
!defined(SUPPORT_DRI_DRM_PLUGIN)
int PVRSRVDriverSuspend(struct drm_device *pDevice, pm_message_t state)
#else
PVR_MOD_STATIC int PVRSRVDriverSuspend(LDM_DEV *pDevice, pm_message_t state)
#endif
{
#if !(defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL) && !defined(SUPPORT_DRI_DRM))
PVR_TRACE(( "PVRSRVDriverSuspend(pDevice=%p)", pDevice));
if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D3) != PVRSRV_OK)
{
return -EINVAL;
}
#endif
return 0;
}
#if defined(SUPPORT_DRI_DRM) && !defined(PVR_DRI_DRM_PLATFORM_DEV) && \
!defined(SUPPORT_DRI_DRM_PLUGIN)
int PVRSRVDriverResume(struct drm_device *pDevice)
#else
PVR_MOD_STATIC int PVRSRVDriverResume(LDM_DEV *pDevice)
#endif
{
#if !(defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL) && !defined(SUPPORT_DRI_DRM))
PVR_TRACE(("PVRSRVDriverResume(pDevice=%p)", pDevice));
if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D0) != PVRSRV_OK)
{
return -EINVAL;
}
#endif
return 0;
}
#endif
#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL) && !defined(SUPPORT_DRI_DRM)
IMG_INT PVRProcSetPowerLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT32 count, IMG_VOID *data)
{
IMG_CHAR data_buffer[2];
IMG_UINT32 PVRPowerLevel;
if (count != sizeof(data_buffer))
{
return -EINVAL;
}
else
{
if (copy_from_user(data_buffer, buffer, count))
return -EINVAL;
if (data_buffer[count - 1] != '\n')
return -EINVAL;
PVRPowerLevel = data_buffer[0] - '0';
if (PVRPowerLevel != gPVRPowerLevel)
{
if (PVRPowerLevel != 0)
{
if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D3) != PVRSRV_OK)
{
return -EINVAL;
}
}
else
{
if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D0) != PVRSRV_OK)
{
return -EINVAL;
}
}
gPVRPowerLevel = PVRPowerLevel;
}
}
return (count);
}
void ProcSeqShowPowerLevel(struct seq_file *sfile,void* el)
{
seq_printf(sfile, "%lu\n", gPVRPowerLevel);
}
#endif
#if defined(SUPPORT_DRI_DRM)
int PVRSRVOpen(struct drm_device unref__ *dev, struct drm_file *pFile)
#else
static int PVRSRVOpen(struct inode unref__ * pInode, struct file *pFile)
#endif
{
PVRSRV_FILE_PRIVATE_DATA *psPrivateData;
IMG_HANDLE hBlockAlloc;
int iRet = -ENOMEM;
PVRSRV_ERROR eError;
IMG_UINT32 ui32PID;
#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc;
#endif
LinuxLockMutex(&gPVRSRVLock);
ui32PID = OSGetCurrentProcessIDKM();
if (PVRSRVProcessConnect(ui32PID, 0) != PVRSRV_OK)
goto err_unlock;
#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
psEnvPerProc = PVRSRVPerProcessPrivateData(ui32PID);
if (psEnvPerProc == IMG_NULL)
{
PVR_DPF((PVR_DBG_ERROR, "%s: No per-process private data", __FUNCTION__));
goto err_unlock;
}
#endif
eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
sizeof(PVRSRV_FILE_PRIVATE_DATA),
(IMG_PVOID *)&psPrivateData,
&hBlockAlloc,
"File Private Data");
if(eError != PVRSRV_OK)
goto err_unlock;
#if defined (SUPPORT_SID_INTERFACE)
psPrivateData->hKernelMemInfo = 0;
#else
psPrivateData->hKernelMemInfo = NULL;
#endif
#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
psPrivateData->psDRMFile = pFile;
list_add_tail(&psPrivateData->sDRMAuthListItem, &psEnvPerProc->sDRMAuthListHead);
#endif
psPrivateData->ui32OpenPID = ui32PID;
psPrivateData->hBlockAlloc = hBlockAlloc;
PRIVATE_DATA(pFile) = psPrivateData;
iRet = 0;
err_unlock:
LinuxUnLockMutex(&gPVRSRVLock);
return iRet;
}
#if defined(SUPPORT_DRI_DRM)
void PVRSRVRelease(void *pvPrivData)
#else
static int PVRSRVRelease(struct inode unref__ * pInode, struct file *pFile)
#endif
{
PVRSRV_FILE_PRIVATE_DATA *psPrivateData;
int err = 0;
LinuxLockMutex(&gPVRSRVLock);
#if defined(SUPPORT_DRI_DRM)
psPrivateData = (PVRSRV_FILE_PRIVATE_DATA *)pvPrivData;
#else
psPrivateData = PRIVATE_DATA(pFile);
#endif
if (psPrivateData != IMG_NULL)
{
#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
list_del(&psPrivateData->sDRMAuthListItem);
#endif
if(psPrivateData->hKernelMemInfo)
{
PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
if(PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
(IMG_PVOID *)&psKernelMemInfo,
psPrivateData->hKernelMemInfo,
PVRSRV_HANDLE_TYPE_MEM_INFO) != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR, "%s: Failed to look up export handle", __FUNCTION__));
err = -EFAULT;
goto err_unlock;
}
if (psKernelMemInfo->sShareMemWorkaround.bInUse)
{
BM_XProcIndexRelease(psKernelMemInfo->sShareMemWorkaround.ui32ShareIndex);
}
if(FreeMemCallBackCommon(psKernelMemInfo, 0,
PVRSRV_FREE_CALLBACK_ORIGIN_EXTERNAL) != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR, "%s: FreeMemCallBackCommon failed", __FUNCTION__));
err = -EFAULT;
goto err_unlock;
}
}
gui32ReleasePID = psPrivateData->ui32OpenPID;
PVRSRVProcessDisconnect(psPrivateData->ui32OpenPID);
gui32ReleasePID = 0;
OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
sizeof(PVRSRV_FILE_PRIVATE_DATA),
psPrivateData, psPrivateData->hBlockAlloc);
#if !defined(SUPPORT_DRI_DRM)
PRIVATE_DATA(pFile) = IMG_NULL;
#endif
}
err_unlock:
LinuxUnLockMutex(&gPVRSRVLock);
#if defined(SUPPORT_DRI_DRM)
return;
#else
return err;
#endif
}
#if defined(SUPPORT_DRI_DRM)
int PVRCore_Init(void)
#else
static int __init PVRCore_Init(void)
#endif
{
int error;
#if !defined(PVR_LDM_MODULE)
PVRSRV_ERROR eError;
#else
#if !defined(SUPPORT_DRI_DRM)
struct device *psDev;
#endif
#endif
#if !defined(SUPPORT_DRI_DRM)
PVRDPFInit();
#endif
PVR_TRACE(("PVRCore_Init"));
LinuxInitMutex(&gPVRSRVLock);
if (CreateProcEntries ())
{
error = -ENOMEM;
return error;
}
if (PVROSFuncInit() != PVRSRV_OK)
{
error = -ENOMEM;
goto init_failed;
}
PVRLinuxMUtilsInit();
if(LinuxMMInit() != PVRSRV_OK)
{
error = -ENOMEM;
goto init_failed;
}
LinuxBridgeInit();
PVRMMapInit();
#if defined(PVR_LDM_MODULE)
#if defined(PVR_LDM_PLATFORM_MODULE) || defined(SUPPORT_DRI_DRM_PLUGIN)
if ((error = platform_driver_register(&powervr_driver)) != 0)
{
PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to register platform driver (%d)", error));
goto init_failed;
}
#if defined(MODULE) && !defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV)
if ((error = platform_device_register(&powervr_device)) != 0)
{
platform_driver_unregister(&powervr_driver);
PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to register platform device (%d)", error));
goto init_failed;
}
#endif
#endif
#if defined(PVR_LDM_PCI_MODULE)
if ((error = pci_register_driver(&powervr_driver)) != 0)
{
PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to register PCI driver (%d)", error));
goto init_failed;
}
#endif
#endif
#if !defined(PVR_LDM_MODULE)
if ((eError = SysInitialise()) != PVRSRV_OK)
{
error = -ENODEV;
#if defined(TCF_REV) && (TCF_REV == 110)
if(eError == PVRSRV_ERROR_NOT_SUPPORTED)
{
printk("\nAtlas wrapper (FPGA image) version mismatch");
error = -ENODEV;
}
#endif
goto init_failed;
}
#endif
#if !defined(SUPPORT_DRI_DRM)
AssignedMajorNumber = register_chrdev(0, DEVNAME, &pvrsrv_fops);
if (AssignedMajorNumber <= 0)
{
PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to get major number"));
error = -EBUSY;
goto sys_deinit;
}
PVR_TRACE(("PVRCore_Init: major device %d", AssignedMajorNumber));
#if defined(PVR_LDM_MODULE)
psPvrClass = class_create(THIS_MODULE, "pvr");
if (IS_ERR(psPvrClass))
{
PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to create class (%ld)", PTR_ERR(psPvrClass)));
error = -EBUSY;
goto unregister_device;
}
psDev = device_create(psPvrClass, NULL, MKDEV(AssignedMajorNumber, 0),
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,26))
NULL,
#endif
DEVNAME);
if (IS_ERR(psDev))
{
PVR_DPF((PVR_DBG_ERROR, "PVRCore_Init: unable to create device (%ld)", PTR_ERR(psDev)));
error = -EBUSY;
goto destroy_class;
}
#endif
#endif
return 0;
#if !defined(SUPPORT_DRI_DRM)
#if defined(PVR_LDM_MODULE)
destroy_class:
class_destroy(psPvrClass);
unregister_device:
unregister_chrdev((IMG_UINT)AssignedMajorNumber, DEVNAME);
#endif
sys_deinit:
#endif
#if defined(PVR_LDM_MODULE)
#if defined(PVR_LDM_PCI_MODULE)
pci_unregister_driver(&powervr_driver);
#endif
#if defined (PVR_LDM_PLATFORM_MODULE)
#if defined(MODULE) && !defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV)
platform_device_unregister(&powervr_device);
#endif
platform_driver_unregister(&powervr_driver);
#endif
#else
{
SYS_DATA *psSysData;
psSysData = SysAcquireDataNoCheck();
if (psSysData != IMG_NULL)
{
(void) SysDeinitialise(psSysData);
}
}
#endif
init_failed:
PVRMMapCleanup();
LinuxMMCleanup();
LinuxBridgeDeInit();
PVROSFuncDeInit();
RemoveProcEntries();
return error;
}
#if defined(SUPPORT_DRI_DRM)
void PVRCore_Cleanup(void)
#else
static void __exit PVRCore_Cleanup(void)
#endif
{
#if !defined(PVR_LDM_MODULE)
SYS_DATA *psSysData;
#endif
PVR_TRACE(("PVRCore_Cleanup"));
#if !defined(PVR_LDM_MODULE)
SysAcquireData(&psSysData);
#endif
#if !defined(SUPPORT_DRI_DRM)
#if defined(PVR_LDM_MODULE)
device_destroy(psPvrClass, MKDEV(AssignedMajorNumber, 0));
class_destroy(psPvrClass);
#endif
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22))
if (
#endif
unregister_chrdev((IMG_UINT)AssignedMajorNumber, DEVNAME)
#if !(LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22))
;
#else
)
{
PVR_DPF((PVR_DBG_ERROR," can't unregister device major %d", AssignedMajorNumber));
}
#endif
#endif
#if defined(PVR_LDM_MODULE)
#if defined(PVR_LDM_PCI_MODULE)
pci_unregister_driver(&powervr_driver);
#endif
#if defined (PVR_LDM_PLATFORM_MODULE)
#if defined(MODULE) && !defined(PVR_USE_PRE_REGISTERED_PLATFORM_DEV)
platform_device_unregister(&powervr_device);
#endif
platform_driver_unregister(&powervr_driver);
#endif
#else
#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL)
if (gPVRPowerLevel != 0)
{
if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D0) == PVRSRV_OK)
{
gPVRPowerLevel = 0;
}
}
#endif
(void) SysDeinitialise(psSysData);
#endif
PVRMMapCleanup();
LinuxMMCleanup();
LinuxBridgeDeInit();
PVROSFuncDeInit();
RemoveProcEntries();
PVR_TRACE(("PVRCore_Cleanup: unloading"));
}
#if !defined(SUPPORT_DRI_DRM)
module_init(PVRCore_Init);
module_exit(PVRCore_Cleanup);
#endif