| /********************************************************************** |
| * |
| * 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 |
| |
| #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" |
| |
| #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 |
| { |
| PVR_TRACE(("PVRSRVDriverShutdown(pDevice=%p)", pDevice)); |
| |
| (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(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 |