aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/cdv/pvr/services4/system/unified/sysconfig.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/cdv/pvr/services4/system/unified/sysconfig.c')
-rw-r--r--drivers/staging/cdv/pvr/services4/system/unified/sysconfig.c1022
1 files changed, 1022 insertions, 0 deletions
diff --git a/drivers/staging/cdv/pvr/services4/system/unified/sysconfig.c b/drivers/staging/cdv/pvr/services4/system/unified/sysconfig.c
new file mode 100644
index 000000000000..86db7433a168
--- /dev/null
+++ b/drivers/staging/cdv/pvr/services4/system/unified/sysconfig.c
@@ -0,0 +1,1022 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 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/pci.h"
+
+#include "sgxdefs.h"
+#include "services_headers.h"
+#include "kerneldisplay.h"
+#include "oemfuncs.h"
+#include "sgxinfo.h"
+#include "sgxinfokm.h"
+#include "pdump_km.h"
+#include "syslocal.h"
+#include "env_data.h"
+#include "psb_drv.h"
+#include "psb_powermgmt.h"
+#include "sys_pvr_drm_export.h"
+#include "msvdx_power.h"
+
+
+/* Graphics MSI address and data region in PCIx */
+#define MRST_PCIx_MSI_ADDR_LOC 0x94
+#define MRST_PCIx_MSI_DATA_LOC 0x98
+
+#define SYS_SGX_CLOCK_SPEED (400000000)
+#define SYS_SGX_HWRECOVERY_TIMEOUT_FREQ (100)
+#define SYS_SGX_PDS_TIMER_FREQ (1000)
+#define SYS_SGX_ACTIVE_POWER_LATENCY_MS (5)
+
+#define DRI_DRM_STATIC
+SYS_DATA* gpsSysData = (SYS_DATA*)IMG_NULL;
+SYS_DATA gsSysData;
+
+static SYS_SPECIFIC_DATA gsSysSpecificData;
+
+IMG_UINT32 gui32SGXDeviceID;
+extern IMG_UINT32 gui32MRSTDisplayDeviceID;
+IMG_UINT32 gui32MRSTMSVDXDeviceID;
+IMG_UINT32 gui32MRSTTOPAZDeviceID;
+
+static SGX_DEVICE_MAP gsSGXDeviceMap;
+extern struct drm_device *gpDrmDevice;
+
+static PVRSRV_DEVICE_NODE *gpsSGXDevNode;
+
+IMG_CPU_VIRTADDR gsPoulsboRegsCPUVaddr;
+
+IMG_CPU_VIRTADDR gsPoulsboDisplayRegsCPUVaddr;
+
+extern struct pci_dev *gpsPVRLDMDev;
+
+#define POULSBO_ADDR_RANGE_INDEX (MMADR_INDEX - 4)
+#define POULSBO_HP_ADDR_RANGE_INDEX (GMADR_INDEX - 4)
+static PVRSRV_ERROR PCIInitDev(SYS_DATA *psSysData)
+{
+ SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
+ IMG_UINT32 ui32MaxOffset = POULSBO_MAX_OFFSET;
+
+ if (!IS_CDV(gpDrmDevice))
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PCIInitDev: Device not supported"));
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+ }
+
+ psSysSpecData->hSGXPCI = OSPCISetDev((IMG_VOID *)psSysSpecData->psPCIDev, 0);
+ ui32MaxOffset = PSB_POULSBO_MAX_OFFSET;
+
+ if (!psSysSpecData->hSGXPCI)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PCIInitDev: Failed to acquire PCI device"));
+ return PVRSRV_ERROR_PCI_DEVICE_NOT_FOUND;
+ }
+
+ SYS_SPECIFIC_DATA_SET(psSysSpecData, SYS_SPECIFIC_DATA_PCI_ACQUIRE_DEV);
+
+ PVR_TRACE(("PCI memory region: %x to %x", OSPCIAddrRangeStart(psSysSpecData->hSGXPCI, POULSBO_ADDR_RANGE_INDEX), OSPCIAddrRangeEnd(psSysSpecData->hSGXPCI, POULSBO_ADDR_RANGE_INDEX)));
+#if defined(SGX_FEATURE_HOST_PORT)
+ PVR_TRACE(("Host Port region: %x to %x", OSPCIAddrRangeStart(psSysSpecData->hSGXPCI, POULSBO_HP_ADDR_RANGE_INDEX), OSPCIAddrRangeEnd(psSysSpecData->hSGXPCI, POULSBO_HP_ADDR_RANGE_INDEX)));
+#endif
+
+ if (OSPCIAddrRangeLen(psSysSpecData->hSGXPCI, POULSBO_ADDR_RANGE_INDEX) < ui32MaxOffset)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PCIInitDev: Device memory region isn't big enough"));
+ return PVRSRV_ERROR_PCI_REGION_TOO_SMALL;
+ }
+
+
+ if (OSPCIRequestAddrRange(psSysSpecData->hSGXPCI, POULSBO_ADDR_RANGE_INDEX) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PCIInitDev: Device memory region not available"));
+ return PVRSRV_ERROR_PCI_REGION_UNAVAILABLE;
+
+ }
+ SYS_SPECIFIC_DATA_SET(psSysSpecData, SYS_SPECIFIC_DATA_PCI_REQUEST_SGX_ADDR_RANGE);
+
+#if defined(SGX_FEATURE_HOST_PORT)
+
+ if (OSPCIRequestAddrRange(psSysSpecData->hSGXPCI, POULSBO_HP_ADDR_RANGE_INDEX) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PCIInitDev: Host Port region not available"));
+ return PVRSRV_ERROR_PCI_REGION_UNAVAILABLE;
+ }
+ SYS_SPECIFIC_DATA_SET(psSysSpecData, SYS_SPECIFIC_DATA_PCI_REQUEST_HOST_PORT_RANGE);
+#endif
+ return PVRSRV_OK;
+}
+
+static IMG_VOID PCIDeInitDev(SYS_DATA *psSysData)
+{
+ SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
+
+ if (SYS_SPECIFIC_DATA_TEST(psSysSpecData, SYS_SPECIFIC_DATA_PCI_REQUEST_SGX_ADDR_RANGE))
+ {
+ OSPCIReleaseAddrRange(psSysSpecData->hSGXPCI, POULSBO_ADDR_RANGE_INDEX);
+ }
+#if defined(SGX_FEATURE_HOST_PORT)
+ if (SYS_SPECIFIC_DATA_TEST(psSysSpecData, SYS_SPECIFIC_DATA_PCI_REQUEST_HOST_PORT_RANGE))
+ {
+ OSPCIReleaseAddrRange(psSysSpecData->hSGXPCI, POULSBO_HP_ADDR_RANGE_INDEX);
+ }
+#endif
+ if (SYS_SPECIFIC_DATA_TEST(psSysSpecData, SYS_SPECIFIC_DATA_PCI_ACQUIRE_DEV))
+ {
+ OSPCIReleaseDev(psSysSpecData->hSGXPCI);
+ }
+}
+static PVRSRV_ERROR SysLocateDevices(SYS_DATA *psSysData)
+{
+ IMG_UINT32 ui32BaseAddr = 0;
+ IMG_UINT32 ui32IRQ = 0;
+
+#if defined(SGX_FEATURE_HOST_PORT)
+ IMG_UINT32 ui32HostPortAddr = 0;
+#endif
+ SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+ struct drm_psb_private *dev_priv = (struct drm_psb_private *) gpDrmDevice->dev_private;
+#endif
+
+ ui32BaseAddr = OSPCIAddrRangeStart(psSysSpecData->hSGXPCI, POULSBO_ADDR_RANGE_INDEX);
+#if defined(SGX_FEATURE_HOST_PORT)
+ ui32HostPortAddr = OSPCIAddrRangeStart(psSysSpecData->hSGXPCI, POULSBO_HP_ADDR_RANGE_INDEX);
+#endif
+ if (OSPCIIRQ(psSysSpecData->hSGXPCI, &ui32IRQ) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysLocateDevices: Couldn't get IRQ"));
+ return PVRSRV_ERROR_INVALID_DEVICE;
+ }
+
+ PVR_TRACE(("ui32BaseAddr: %08X", ui32BaseAddr));
+#if defined(SGX_FEATURE_HOST_PORT)
+ PVR_TRACE(("ui32HostPortAddr: %08X", ui32HostPortAddr));
+#endif
+ PVR_TRACE(("IRQ: %d", ui32IRQ));
+
+
+ gsSGXDeviceMap.ui32Flags = 0x0;
+ gsSGXDeviceMap.ui32IRQ = ui32IRQ;
+
+
+ gsSGXDeviceMap.sRegsSysPBase.uiAddr = ui32BaseAddr + (IS_CDV(gpDrmDevice) ? SGX_REGS_OFFSET : PSB_SGX_REGS_OFFSET);
+ gsSGXDeviceMap.sRegsCpuPBase = SysSysPAddrToCpuPAddr(gsSGXDeviceMap.sRegsSysPBase);
+ gsSGXDeviceMap.ui32RegsSize = SGX_REG_SIZE;
+
+#if defined(SGX_FEATURE_HOST_PORT)
+
+ gsSGXDeviceMap.ui32Flags = SGX_HOSTPORT_PRESENT;
+ gsSGXDeviceMap.sHPSysPBase.uiAddr = ui32HostPortAddr;
+ gsSGXDeviceMap.sHPCpuPBase = SysSysPAddrToCpuPAddr(gsSGXDeviceMap.sHPSysPBase);
+ if (IS_CDV(gpDrmDevice) )
+ gsSGXDeviceMap.ui32HPSize = SYS_SGX_HP_SIZE;
+ else
+ gsSGXDeviceMap.ui32HPSize = PSB_SYS_SGX_HP_SIZE;
+#endif
+
+#if defined(MRST_SLAVEPORT)
+
+ gsSGXDeviceMap.sSPSysPBase.uiAddr = ui32BaseAddr + MRST_SGX_SP_OFFSET;
+ gsSGXDeviceMap.sSPCpuPBase = SysSysPAddrToCpuPAddr(gsSGXDeviceMap.sSPSysPBase);
+ gsSGXDeviceMap.ui32SPSize = SGX_SP_SIZE;
+#endif
+
+
+
+ gsSGXDeviceMap.sLocalMemSysPBase.uiAddr = 0;
+ gsSGXDeviceMap.sLocalMemDevPBase.uiAddr = 0;
+ gsSGXDeviceMap.sLocalMemCpuPBase.uiAddr = 0;
+ gsSGXDeviceMap.ui32LocalMemSize = 0;
+
+
+ {
+ IMG_SYS_PHYADDR sPoulsboRegsCpuPBase;
+ sPoulsboRegsCpuPBase.uiAddr = ui32BaseAddr + POULSBO_REGS_OFFSET;
+ gsPoulsboRegsCPUVaddr = OSMapPhysToLin(SysSysPAddrToCpuPAddr(sPoulsboRegsCpuPBase),
+ POULSBO_REG_SIZE,
+ PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+ IMG_NULL);
+
+ sPoulsboRegsCpuPBase.uiAddr = ui32BaseAddr + POULSBO_DISPLAY_REGS_OFFSET;
+ gsPoulsboDisplayRegsCPUVaddr = OSMapPhysToLin(SysSysPAddrToCpuPAddr(sPoulsboRegsCpuPBase),
+ POULSBO_DISPLAY_REG_SIZE,
+ PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+ IMG_NULL);
+ }
+
+#if defined(PDUMP)
+ {
+
+ static IMG_CHAR pszPDumpDevName[] = "SGXMEM";
+ gsSGXDeviceMap.pszPDumpDevName = pszPDumpDevName;
+ }
+#endif
+
+ return PVRSRV_OK;
+}
+
+
+#define VERSION_STR_MAX_LEN_TEMPLATE "SGX revision = 000.000.000"
+static PVRSRV_ERROR SysCreateVersionString(SYS_DATA *psSysData)
+{
+ IMG_UINT32 ui32MaxStrLen;
+ PVRSRV_ERROR eError;
+ IMG_INT32 i32Count;
+ IMG_CHAR *pszVersionString;
+ IMG_UINT32 ui32SGXRevision = 0;
+ IMG_VOID *pvSGXRegs;
+
+ pvSGXRegs = OSMapPhysToLin(gsSGXDeviceMap.sRegsCpuPBase,
+ gsSGXDeviceMap.ui32RegsSize,
+ PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+ IMG_NULL);
+
+ if (pvSGXRegs != IMG_NULL)
+ {
+ ui32SGXRevision = OSReadHWReg(pvSGXRegs, EUR_CR_CORE_REVISION);
+ OSUnMapPhysToLin(pvSGXRegs,
+ gsSGXDeviceMap.ui32RegsSize,
+ PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+ IMG_NULL);
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysCreateVersionString: Couldn't map SGX registers"));
+ }
+
+ ui32MaxStrLen = OSStringLength(VERSION_STR_MAX_LEN_TEMPLATE);
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32MaxStrLen + 1,
+ (IMG_PVOID *)&pszVersionString,
+ IMG_NULL,
+ "Version String");
+ if(eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ i32Count = OSSNPrintf(pszVersionString, ui32MaxStrLen + 1,
+ "SGX revision = %u.%u.%u",
+ (IMG_UINT)((ui32SGXRevision & EUR_CR_CORE_REVISION_MAJOR_MASK)
+ >> EUR_CR_CORE_REVISION_MAJOR_SHIFT),
+ (IMG_UINT)((ui32SGXRevision & EUR_CR_CORE_REVISION_MINOR_MASK)
+ >> EUR_CR_CORE_REVISION_MINOR_SHIFT),
+ (IMG_UINT)((ui32SGXRevision & EUR_CR_CORE_REVISION_MAINTENANCE_MASK)
+ >> EUR_CR_CORE_REVISION_MAINTENANCE_SHIFT)
+ );
+ if(i32Count == -1)
+ {
+ ui32MaxStrLen = OSStringLength(VERSION_STR_MAX_LEN_TEMPLATE);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32MaxStrLen + 1,
+ pszVersionString,
+ IMG_NULL);
+
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psSysData->pszVersionString = pszVersionString;
+
+ return PVRSRV_OK;
+}
+
+static IMG_VOID SysFreeVersionString(SYS_DATA *psSysData)
+{
+ if(psSysData->pszVersionString)
+ {
+ IMG_UINT32 ui32MaxStrLen;
+ ui32MaxStrLen = OSStringLength(VERSION_STR_MAX_LEN_TEMPLATE);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32MaxStrLen+1,
+ psSysData->pszVersionString,
+ IMG_NULL);
+ psSysData->pszVersionString = IMG_NULL;
+ }
+}
+
+PVRSRV_ERROR SysInitialise(IMG_VOID)
+{
+ IMG_UINT32 i = 0;
+ PVRSRV_ERROR eError;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ SGX_TIMING_INFORMATION* psTimingInfo;
+
+ gpsSysData = &gsSysData;
+ OSMemSet(gpsSysData, 0, sizeof(SYS_DATA));
+
+ gpsSysData->pvSysSpecificData = &gsSysSpecificData;
+ gsSysSpecificData.ui32SysSpecificData = 0;
+
+ PVR_ASSERT(gpsPVRLDMDev != IMG_NULL);
+ gsSysSpecificData.psPCIDev = gpsPVRLDMDev;
+
+ eError = OSInitEnvData(&gpsSysData->pvEnvSpecificData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to setup env structure"));
+ SysDeinitialise(gpsSysData);
+ gpsSysData = IMG_NULL;
+ return eError;
+ }
+
+
+ psTimingInfo = &gsSGXDeviceMap.sTimingInfo;
+ psTimingInfo->ui32CoreClockSpeed = SYS_SGX_CLOCK_SPEED;
+ psTimingInfo->ui32HWRecoveryFreq = SYS_SGX_HWRECOVERY_TIMEOUT_FREQ;
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+ psTimingInfo->bEnableActivePM = (drm_psb_ospm != 0);
+ /*printk(KERN_ERR "SGX APM is %s\n", (drm_psb_ospm != 0)? "enabled":"disabled"); */
+#else
+ psTimingInfo->bEnableActivePM = IMG_FALSE;
+#endif
+ psTimingInfo->ui32ActivePowManLatencyms = SYS_SGX_ACTIVE_POWER_LATENCY_MS;
+ psTimingInfo->ui32uKernelFreq = SYS_SGX_PDS_TIMER_FREQ;
+
+ eError = PCIInitDev(gpsSysData);
+ if (eError != PVRSRV_OK)
+ {
+ SysDeinitialise(gpsSysData);
+ gpsSysData = IMG_NULL;
+ return eError;
+ }
+
+ gpsSysData->ui32NumDevices = SYS_DEVICE_COUNT;
+
+
+ for(i=0; i<SYS_DEVICE_COUNT; i++)
+ {
+ gpsSysData->sDeviceID[i].uiID = i;
+ gpsSysData->sDeviceID[i].bInUse = IMG_FALSE;
+ }
+
+ gpsSysData->psDeviceNodeList = IMG_NULL;
+ gpsSysData->psQueueList = IMG_NULL;
+
+ eError = SysInitialiseCommon(gpsSysData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed in SysInitialiseCommon"));
+ SysDeinitialise(gpsSysData);
+ gpsSysData = IMG_NULL;
+ return eError;
+ }
+
+
+
+
+
+ eError = SysLocateDevices(gpsSysData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to locate devices"));
+ SysDeinitialise(gpsSysData);
+ gpsSysData = IMG_NULL;
+ return eError;
+ }
+
+
+
+
+ eError = PVRSRVRegisterDevice(gpsSysData, SGXRegisterDevice,
+ DEVICE_SGX_INTERRUPT, &gui32SGXDeviceID);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to register device!"));
+ SysDeinitialise(gpsSysData);
+ gpsSysData = IMG_NULL;
+ return eError;
+ }
+
+
+ /* register MSVDX, with 0 interrupt bit, no interrupt will be served */
+ eError = PVRSRVRegisterDevice(gpsSysData, MSVDXRegisterDevice,
+ DEVICE_MSVDX_INTERRUPT, &gui32MRSTMSVDXDeviceID);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to register MSVDXdevice!"));
+ SysDeinitialise(gpsSysData);
+ gpsSysData = IMG_NULL;
+ return eError;
+ }
+
+ psDeviceNode = gpsSysData->psDeviceNodeList;
+
+ while(psDeviceNode)
+ {
+
+ switch(psDeviceNode->sDevId.eDeviceType)
+ {
+ case PVRSRV_DEVICE_TYPE_SGX:
+ {
+ DEVICE_MEMORY_INFO *psDevMemoryInfo;
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+
+
+ psDeviceNode->psLocalDevMemArena = IMG_NULL;
+
+
+ psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+ psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
+
+
+ for(i=0; i<psDevMemoryInfo->ui32HeapCount; i++)
+ {
+ psDeviceMemoryHeap[i].ui32Attribs |= PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG;
+#ifdef OEM_CUSTOMISE
+
+#endif
+ }
+
+ gpsSGXDevNode = psDeviceNode;
+ break;
+ }
+ case PVRSRV_DEVICE_TYPE_MSVDX:
+ /* nothing need to do here */
+ break;
+ case PVRSRV_DEVICE_TYPE_TOPAZ:
+ break;
+ default:
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to find SGX device node!"));
+ return PVRSRV_ERROR_INIT_FAILURE;
+ }
+ }
+
+
+ psDeviceNode = psDeviceNode->psNext;
+ }
+
+ PDUMPINIT();
+ SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_PDUMP_INIT);
+
+
+ eError = PVRSRVInitialiseDevice (gui32SGXDeviceID);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to initialise device!"));
+ SysDeinitialise(gpsSysData);
+ gpsSysData = IMG_NULL;
+ return eError;
+ }
+ SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_SGX_INITIALISED);
+
+ eError = PVRSRVInitialiseDevice (gui32MRSTMSVDXDeviceID);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to initialise device!"));
+ SysDeinitialise(gpsSysData);
+ gpsSysData = IMG_NULL;
+ return eError;
+ }
+
+ if (0)
+ {
+ eError = PVRSRVInitialiseDevice (gui32MRSTTOPAZDeviceID);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to initialise device!"));
+ SysDeinitialise(gpsSysData);
+ gpsSysData = IMG_NULL;
+ return eError;
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR SysFinalise(IMG_VOID)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ eError = OSInstallMISR(gpsSysData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysFinalise: OSInstallMISR failed"));
+ return eError;
+ }
+ SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_MISR_INSTALLED);
+
+ eError = SysCreateVersionString(gpsSysData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to create a system version string"));
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_WARNING, "SysFinalise: Version string: %s", gpsSysData->pszVersionString));
+ }
+
+ return eError;
+}
+
+PVRSRV_ERROR SysDeinitialise (SYS_DATA *psSysData)
+{
+ PVRSRV_ERROR eError;
+
+ SYS_SPECIFIC_DATA *psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
+
+ if (SYS_SPECIFIC_DATA_TEST(psSysSpecData, SYS_SPECIFIC_DATA_MISR_INSTALLED))
+ {
+ eError = OSUninstallMISR(psSysData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysDeinitialise: OSUninstallMISR failed"));
+ return eError;
+ }
+ }
+
+ if (SYS_SPECIFIC_DATA_TEST(psSysSpecData, SYS_SPECIFIC_DATA_SGX_INITIALISED))
+ {
+
+ eError = PVRSRVDeinitialiseDevice(gui32SGXDeviceID);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysDeinitialise: failed to de-init the device"));
+ return eError;
+ }
+ }
+
+ SysFreeVersionString(psSysData);
+
+ PCIDeInitDev(psSysData);
+
+ eError = OSDeInitEnvData(psSysData->pvEnvSpecificData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysDeinitialise: failed to de-init env structure"));
+ return eError;
+ }
+
+ SysDeinitialiseCommon(gpsSysData);
+
+
+ OSUnMapPhysToLin(gsPoulsboRegsCPUVaddr,
+ POULSBO_REG_SIZE,
+ PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+ IMG_NULL);
+
+ OSUnMapPhysToLin(gsPoulsboDisplayRegsCPUVaddr,
+ POULSBO_DISPLAY_REG_SIZE,
+ PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+ IMG_NULL);
+
+ if (SYS_SPECIFIC_DATA_TEST(psSysSpecData, SYS_SPECIFIC_DATA_PDUMP_INIT))
+ {
+ PDUMPDEINIT();
+ }
+
+ gpsSysData = IMG_NULL;
+
+ return PVRSRV_OK;
+}
+
+IMG_UINT32 SysGetInterruptSource(SYS_DATA* psSysData,
+ PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVR_UNREFERENCED_PARAMETER(psSysData);
+ PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+
+ return 0;
+}
+
+IMG_VOID SysClearInterrupts(SYS_DATA* psSysData, IMG_UINT32 ui32ClearBits)
+{
+ PVR_UNREFERENCED_PARAMETER(psSysData);
+ PVR_UNREFERENCED_PARAMETER(ui32ClearBits);
+}
+
+
+PVRSRV_ERROR SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_VOID **ppvDeviceMap)
+{
+ switch(eDeviceType)
+ {
+ case PVRSRV_DEVICE_TYPE_SGX:
+ {
+
+ *ppvDeviceMap = (IMG_VOID*)&gsSGXDeviceMap;
+ break;
+ }
+ default:
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysGetDeviceMemoryMap: unsupported device type"));
+ }
+ }
+ return PVRSRV_OK;
+}
+
+
+IMG_DEV_PHYADDR SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_CPU_PHYADDR CpuPAddr)
+{
+ IMG_DEV_PHYADDR DevPAddr;
+
+ PVR_UNREFERENCED_PARAMETER(eDeviceType);
+
+
+ DevPAddr.uiAddr = CpuPAddr.uiAddr;
+
+ return DevPAddr;
+}
+
+
+IMG_CPU_PHYADDR SysSysPAddrToCpuPAddr (IMG_SYS_PHYADDR sys_paddr)
+{
+ IMG_CPU_PHYADDR cpu_paddr;
+
+
+ cpu_paddr.uiAddr = sys_paddr.uiAddr;
+ return cpu_paddr;
+}
+
+IMG_SYS_PHYADDR SysCpuPAddrToSysPAddr (IMG_CPU_PHYADDR cpu_paddr)
+{
+ IMG_SYS_PHYADDR sys_paddr;
+
+
+ sys_paddr.uiAddr = cpu_paddr.uiAddr;
+ return sys_paddr;
+}
+
+
+IMG_DEV_PHYADDR SysSysPAddrToDevPAddr (PVRSRV_DEVICE_TYPE eDeviceType, IMG_SYS_PHYADDR SysPAddr)
+{
+ IMG_DEV_PHYADDR DevPAddr;
+
+ PVR_UNREFERENCED_PARAMETER(eDeviceType);
+
+
+ DevPAddr.uiAddr = SysPAddr.uiAddr;
+
+ return DevPAddr;
+}
+
+
+IMG_SYS_PHYADDR SysDevPAddrToSysPAddr (PVRSRV_DEVICE_TYPE eDeviceType, IMG_DEV_PHYADDR DevPAddr)
+{
+ IMG_SYS_PHYADDR SysPAddr;
+
+ PVR_UNREFERENCED_PARAMETER(eDeviceType);
+
+
+ SysPAddr.uiAddr = DevPAddr.uiAddr;
+
+ return SysPAddr;
+}
+
+
+IMG_VOID SysRegisterExternalDevice(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+
+ psDeviceNode->ui32SOCInterruptBit = DEVICE_DISP_INTERRUPT;
+}
+
+
+IMG_VOID SysRemoveExternalDevice(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+}
+
+PVRSRV_ERROR SysOEMFunction ( IMG_UINT32 ui32ID,
+ IMG_VOID *pvIn,
+ IMG_UINT32 ulInSize,
+ IMG_VOID *pvOut,
+ IMG_UINT32 ulOutSize)
+{
+ PVR_UNREFERENCED_PARAMETER(ulInSize);
+ PVR_UNREFERENCED_PARAMETER(pvIn);
+
+ return PVRSRV_ERROR_INVALID_PARAMS;
+}
+
+
+static PVRSRV_ERROR SysMapInRegisters(IMG_VOID)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNodeList;
+
+ psDeviceNodeList = gpsSysData->psDeviceNodeList;
+
+ while (psDeviceNodeList)
+ {
+ switch(psDeviceNodeList->sDevId.eDeviceType)
+ {
+ case PVRSRV_DEVICE_TYPE_SGX:
+ {
+ PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNodeList->pvDevice;
+
+ if (SYS_SPECIFIC_DATA_TEST(&gsSysSpecificData, SYS_SPECIFIC_DATA_PM_UNMAP_SGX_REGS))
+ {
+ psDevInfo->pvRegsBaseKM = OSMapPhysToLin(gsSGXDeviceMap.sRegsCpuPBase,
+ gsSGXDeviceMap.ui32RegsSize,
+ PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+ IMG_NULL);
+
+ if (!psDevInfo->pvRegsBaseKM)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysMapInRegisters : Failed to map in SGX registers\n"));
+ return PVRSRV_ERROR_BAD_MAPPING;
+ }
+ SYS_SPECIFIC_DATA_CLEAR(&gsSysSpecificData, SYS_SPECIFIC_DATA_PM_UNMAP_SGX_REGS);
+ }
+ psDevInfo->ui32RegSize = gsSGXDeviceMap.ui32RegsSize;
+ psDevInfo->sRegsPhysBase = gsSGXDeviceMap.sRegsSysPBase;
+
+#if defined(SGX_FEATURE_HOST_PORT)
+ if (gsSGXDeviceMap.ui32Flags & SGX_HOSTPORT_PRESENT)
+ {
+ if (SYS_SPECIFIC_DATA_TEST(&gsSysSpecificData, SYS_SPECIFIC_DATA_PM_UNMAP_SGX_HP))
+ {
+
+ psDevInfo->pvHostPortBaseKM = OSMapPhysToLin(gsSGXDeviceMap.sHPCpuPBase,
+ gsSGXDeviceMap.ui32HPSize,
+ PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+ IMG_NULL);
+ if (!psDevInfo->pvHostPortBaseKM)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysMapInRegisters : Failed to map in host port\n"));
+ return PVRSRV_ERROR_BAD_MAPPING;
+ }
+ SYS_SPECIFIC_DATA_CLEAR(&gsSysSpecificData, SYS_SPECIFIC_DATA_PM_UNMAP_SGX_HP);
+ }
+ psDevInfo->ui32HPSize = gsSGXDeviceMap.ui32HPSize;
+ psDevInfo->sHPSysPAddr = gsSGXDeviceMap.sHPSysPBase;
+ }
+#endif
+ break;
+ }
+ default:
+ break;
+ }
+ psDeviceNodeList = psDeviceNodeList->psNext;
+ }
+
+ return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR SysUnmapRegisters(IMG_VOID)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNodeList;
+
+ psDeviceNodeList = gpsSysData->psDeviceNodeList;
+
+ while (psDeviceNodeList)
+ {
+ switch (psDeviceNodeList->sDevId.eDeviceType)
+ {
+ case PVRSRV_DEVICE_TYPE_SGX:
+ {
+ PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNodeList->pvDevice;
+
+ if (psDevInfo->pvRegsBaseKM)
+ {
+ OSUnMapPhysToLin(psDevInfo->pvRegsBaseKM,
+ gsSGXDeviceMap.ui32RegsSize,
+ PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+ IMG_NULL);
+
+ SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_PM_UNMAP_SGX_REGS);
+ }
+
+ psDevInfo->pvRegsBaseKM = IMG_NULL;
+ psDevInfo->ui32RegSize = 0;
+ psDevInfo->sRegsPhysBase.uiAddr = 0;
+
+#if defined(SGX_FEATURE_HOST_PORT)
+ if (gsSGXDeviceMap.ui32Flags & SGX_HOSTPORT_PRESENT)
+ {
+
+ if (psDevInfo->pvHostPortBaseKM)
+ {
+ OSUnMapPhysToLin(psDevInfo->pvHostPortBaseKM,
+ gsSGXDeviceMap.ui32HPSize,
+ PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+ IMG_NULL);
+
+ SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_PM_UNMAP_SGX_HP);
+
+ psDevInfo->pvHostPortBaseKM = IMG_NULL;
+ }
+
+ psDevInfo->ui32HPSize = 0;
+ psDevInfo->sHPSysPAddr.uiAddr = 0;
+ }
+#endif
+ break;
+ }
+ default:
+ break;
+ }
+ psDeviceNodeList = psDeviceNodeList->psNext;
+ }
+
+ OSUnMapPhysToLin(gsPoulsboRegsCPUVaddr,
+ POULSBO_REG_SIZE,
+ PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+ IMG_NULL);
+
+
+ OSUnMapPhysToLin(gsPoulsboDisplayRegsCPUVaddr,
+ POULSBO_DISPLAY_REG_SIZE,
+ PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+ IMG_NULL);
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR SysSystemPrePowerState(PVRSRV_SYS_POWER_STATE eNewPowerState)
+{
+ PVRSRV_ERROR eError= PVRSRV_OK;
+ PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)(gsSysSpecificData.hSGXPCI);
+
+ if (eNewPowerState != gpsSysData->eCurrentPowerState)
+ {
+ if ((eNewPowerState == PVRSRV_SYS_POWER_STATE_D3) &&
+ (gpsSysData->eCurrentPowerState < PVRSRV_SYS_POWER_STATE_D3))
+ {
+ SysUnmapRegisters();
+
+ //Save some pci state that won't get saved properly by pci_save_state()
+ pci_read_config_dword(psPVRPCI->psPCIDev, 0x5C, &gsSysSpecificData.saveBSM);
+ pci_read_config_dword(psPVRPCI->psPCIDev, 0xFC, &gsSysSpecificData.saveVBT);
+ pci_read_config_dword(psPVRPCI->psPCIDev, MRST_PCIx_MSI_ADDR_LOC, &gsSysSpecificData.msi_addr);
+ pci_read_config_dword(psPVRPCI->psPCIDev, MRST_PCIx_MSI_DATA_LOC, &gsSysSpecificData.msi_data);
+ }
+ }
+
+ return eError;
+}
+
+PVRSRV_ERROR SysSystemPostPowerState(PVRSRV_SYS_POWER_STATE eNewPowerState)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)(gsSysSpecificData.hSGXPCI);
+
+ if (eNewPowerState != gpsSysData->eCurrentPowerState)
+ {
+ if ((gpsSysData->eCurrentPowerState == PVRSRV_SYS_POWER_STATE_D3) &&
+ (eNewPowerState < PVRSRV_SYS_POWER_STATE_D3))
+ {
+ //Restore some pci state that will not have gotten restored properly by pci_restore_state()
+ pci_write_config_dword(psPVRPCI->psPCIDev, 0x5c, gsSysSpecificData.saveBSM);
+ pci_write_config_dword(psPVRPCI->psPCIDev, 0xFC, gsSysSpecificData.saveVBT);
+ pci_write_config_dword(psPVRPCI->psPCIDev, MRST_PCIx_MSI_ADDR_LOC, gsSysSpecificData.msi_addr);
+ pci_write_config_dword(psPVRPCI->psPCIDev, MRST_PCIx_MSI_DATA_LOC, gsSysSpecificData.msi_data);
+
+ eError = SysLocateDevices(gpsSysData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysSystemPostPowerState: Failed to locate devices"));
+ return eError;
+ }
+
+ eError = SysMapInRegisters();
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysSystemPostPowerState: Failed to map in registers"));
+ return eError;
+ }
+ }
+ }
+ return eError;
+}
+
+
+PVRSRV_ERROR SysDevicePrePowerState(IMG_UINT32 ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+ if ((eNewPowerState != eCurrentPowerState) &&
+ (eNewPowerState == PVRSRV_DEV_POWER_STATE_OFF))
+ {
+ if (ui32DeviceIndex == gui32SGXDeviceID)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"SysDevicePrePowerState: Remove SGX power"));
+ psb_irq_uninstall_islands(gpDrmDevice, OSPM_GRAPHICS_ISLAND);
+ /* XXX don't power off SGX on Cedartrail, windows driver guy said don't
+ * need that. -- zhenyu */
+ /* ospm_power_island_down(OSPM_GRAPHICS_ISLAND); */
+ }
+#if 1
+ else if (ui32DeviceIndex == gui32MRSTMSVDXDeviceID)
+ {
+ ospm_power_island_down(OSPM_VIDEO_DEC_ISLAND);
+#if 0
+ ospm_power_using_hw_end(OSPM_VIDEO_DEC_ISLAND);
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+#endif
+ }
+ else if (ui32DeviceIndex == gui32MRSTTOPAZDeviceID)
+ {
+ ospm_power_island_down(OSPM_VIDEO_ENC_ISLAND);
+ }
+#if 0
+ ospm_power_using_hw_end(OSPM_VIDEO_ENC_ISLAND);
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+#endif
+#endif
+ }
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR SysDevicePostPowerState(IMG_UINT32 ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+ if ((eNewPowerState != eCurrentPowerState) &&
+ (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_OFF))
+ {
+ if (ui32DeviceIndex == gui32SGXDeviceID)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"SysDevicePrePowerState: Restore SGX power"));
+ /* XXX we don't power off SGX on Cedartrail */
+ /* ospm_power_island_up(OSPM_GRAPHICS_ISLAND); */
+ }
+#if 1
+ else if (ui32DeviceIndex == gui32MRSTMSVDXDeviceID)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"SysDevicePrePowerState: Restore MSVDX power"));
+ ospm_power_island_up(OSPM_VIDEO_DEC_ISLAND);
+#if 0
+ if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, true))
+ {
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ if (!ospm_power_using_hw_begin(OSPM_VIDEO_DEC_ISLAND, true))
+ {
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+
+ return PVRSRV_ERROR_GENERIC;
+ }
+#endif
+ }
+ else if (ui32DeviceIndex == gui32MRSTTOPAZDeviceID)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"SysDevicePrePowerState: Restore TOPAZ power"));
+
+ ospm_power_island_up(OSPM_VIDEO_ENC_ISLAND);
+#if 0
+ if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, true))
+ {
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ if (!ospm_power_using_hw_begin(OSPM_VIDEO_ENC_ISLAND, true))
+ {
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+
+ return PVRSRV_ERROR_GENERIC;
+ }
+#endif
+ }
+#endif
+ }
+
+ return PVRSRV_OK;
+}
+
+int SYSPVRServiceSGXInterrupt(struct drm_device *dev)
+{
+ IMG_BOOL bStatus = IMG_FALSE;
+
+ PVR_UNREFERENCED_PARAMETER(dev);
+
+ if (gpsSGXDevNode != IMG_NULL)
+ {
+ bStatus = (*gpsSGXDevNode->pfnDeviceISR)(gpsSGXDevNode->pvISRData);
+ if (bStatus)
+ {
+ OSScheduleMISR((IMG_VOID *)gpsSGXDevNode->psSysData);
+ }
+ }
+
+ return bStatus ? 1 : 0;
+}