source "drivers/staging/gma500/Kconfig"
+source "drivers/staging/mrst/Kconfig"
+
source "drivers/staging/altera-stapl/Kconfig"
source "drivers/staging/mei/Kconfig"
obj-$(CONFIG_TOUCHSCREEN_CLEARPAD_TM1217) += cptm1217/
obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4) += ste_rmi4/
obj-$(CONFIG_DRM_PSB) += gma500/
+obj-$(CONFIG_DRM_INTEL_MID) += mrst/
obj-$(CONFIG_INTEL_MEI) += mei/
obj-$(CONFIG_MFD_NVEC) += nvec/
obj-$(CONFIG_DRM_INTEL_MID) += mrst/
--- /dev/null
+# HACK: These are intermediate files in PVR driver build.
+*.medfield.c
+*.mrst.c
--- /dev/null
+#
+# Drm device configuration
+#
+# This driver provides support for the
+# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
+#
+
+config DRM_INTEL_MID
+ tristate "Intel Moorestown/Medfield (load along with IMG driver)"
+ depends on DRM && PCI
+ select FB_CFB_COPYAREA
+ select FB_CFB_FILLRECT
+ select FB_CFB_IMAGEBLIT
+ select DRM_KMS_HELPER
+ select DRM_TTM
+ help
+ xxxxxxxxxxxxxxxxxxxxxxxxxx
+
+choice
+ prompt "Build IMG kernel service as "
+ depends on DRM_INTEL_MID
+ default DRM_MID_RELEASE
+
+config DRM_MID_RELEASE
+ bool "Release"
+ depends on DRM_INTEL_MID
+ help
+ Build IMG kernel services as release
+
+config DRM_MID_DEBUG
+ bool "Debug"
+ depends on DRM_INTEL_MID
+ help
+ Build IMG kernel services as debug
+
+endchoice
+
+config DRM_MDFLD
+ tristate "Intel Medfield"
+ depends on DRM_INTEL_MID && PCI
+ select FB_CFB_COPYAREA
+ select FB_CFB_FILLRECT
+ select FB_CFB_IMAGEBLIT
+ select DRM_KMS_HELPER
+ help
+ Choose this option if you have a Medfield platform.
+ If M is selected the module will be called mid_gfx.
+
+config MDFLD_DSI_DSR
+ bool "Support DSI Fullscreen Display Self Refreshment "
+ depends on DRM_MDFLD && !MDFLD_DSI_DPU
+ default y
+ help
+ Choose this option if you have a Type1 MIPI panel.
+
+config MDFLD_DSI_DPU
+ bool "Support DSI Display Partial Update"
+ depends on DRM_MDFLD
+ default n
+ help
+ xxxxxx
+
+config MDFD_DUAL_MIPI
+ bool "SUPPORT_DUAL_MIPI_DISPLAYS"
+ depends on DRM_MDFLD
+ default n
+ help
+ xxxxxx
+
+config MDFD_HDMI
+ bool "SUPPORT_HDMI_DISPLAY"
+ depends on DRM_MDFLD
+ default n
+ help
+ xxxxxx
+
+config MDFD_GL3
+ bool "Enable GL3 Cache for GUNIT"
+ depends on DRM_MDFLD
+ default n
+ help
+ xxxxxx
+
+config PVR_TRACE_CMD
+ depends on DRM_INTEL_MID
+ bool "Enable GPU command tracing"
+ default n
+ help
+ This will enable a lightweight tracer of commands submitted
+ to the GPU.
+
+ Besides the command type the trace output will provide the
+ timestamp, id and name of the submitting process and a
+ a snapshots of the synchronization counters related to the
+ given command.
+
+ The trace can help for example in debugging dead-lock
+ situations caused by circular lock dependencies.
+
+config PVR_TRACE_CMD_BUF_SHIFT
+ int "Command tracing buf size"
+ range 1 10
+ default 3
+ depends on PVR_TRACE_CMD
+ help
+ Select the number of pages (as a power of 2) set aside for
+ the command trace buffer.
+ Examples:
+ 1 -> 4kB
+ 3 -> 32kB
+ 10 -> 4MB
--- /dev/null
+obj-$(CONFIG_DRM_MDFLD) += medfield/
+obj-$(CONFIG_DRM_MRST) += moorestown/
--- /dev/null
+
+SOURCE
+
+This driver is a forward port of the Poulsbo/Langwell/Penwell SGX graphics and
+display controller drivers from 2.6.37 to 3.0-rc-something.
+
+The starting point was the meego-kernel-branch-mrst-k37 branch on [1]. The
+commits touching drivers/staging/mrst directory were exported to patches using:
+
+$ git format-patch -1000 meego-kernel-branch-mrst-k37 -- drivers/staging/mrst
+
+Note that the above filters out the changes outside drivers/staging/mrst.
+
+The patches were then applied on top of the MID repository [2]. Possibly due to
+rebases in the original tree [1] there were some conflicts that were
+resolved. In the end, this did not report any diff:
+
+$ git diff meego-kernel-branch-mrst-k37 -- drivers/staging/mrst
+
+After this, the build problems were fixed one by one.
+
+
+TODO
+
+* Make it work.
+
+* Continuous: Merge [2] (and thus Linus' tree) here as it is updated.
+
+* Review the hacked up quick fixes to build problems.
+
+* Possibly update the DDK version.
+
+* Merge the diverged and polished drivers/staging/gma500 back with this driver.
+
+* Finally: Backport the combined drivers and hardware adaptation to desired
+ kernel version.
+
+
+NOTES
+
+There is arch/x86/configs/medfield_pvr_defconfig known to work. It excludes the
+drivers/staging/gma500 driver as long as the drivers have not been merged.
+
+
+REFERENCES
+
+[1] git://gfx-build.fm.intel.com/kernel.git
+[2] git://git.kernel.org/pub/scm/linux/kernel/git/alan/linux-3.0-mid-ref.git
--- /dev/null
+/***************************************************************************
+ *
+ * Copyright © 2010 Intel 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 (including the next
+ * paragraph) 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.
+ *
+ ******************************************************************************/
+
+#if defined(__linux__)
+#include <linux/string.h>
+#else
+#include <string.h>
+#endif
+
+#include "bufferclass_video.h"
+#include "bufferclass_video_linux.h"
+
+#define VBUFFERCLASS_DEVICE_NAME "Video Bufferclass Device"
+#define CBUFFERCLASS_DEVICE_NAME "Camera Bufferclass Device"
+
+static void *gpvAnchorVideo[BC_VIDEO_DEVICE_MAX_ID];
+
+static void *gpcAnchor;
+static PFN_BC_GET_PVRJTABLE pfnGetPVRJTable = IMG_NULL;
+
+BC_VIDEO_DEVINFO *
+GetAnchorPtr(int id)
+{
+ BC_VIDEO_DEVINFO *AnchorPtr = NULL;
+ if (id < BC_VIDEO_DEVICE_MAX_ID)
+ AnchorPtr = gpvAnchorVideo[id];
+ else if (id == BC_CAMERA_DEVICEID)
+ AnchorPtr = gpcAnchor;
+ return AnchorPtr;
+}
+
+static void
+SetAnchorPtr(BC_VIDEO_DEVINFO * psDevInfo, int id)
+{
+ if (id < BC_VIDEO_DEVICE_MAX_ID)
+ gpvAnchorVideo[id] = (void *) psDevInfo;
+ else if (id == BC_CAMERA_DEVICEID)
+ gpcAnchor = (void *) psDevInfo;
+}
+
+static PVRSRV_ERROR
+OpenVBCDevice(IMG_UINT32 uDeviceID, IMG_HANDLE * phDevice)
+{
+ BC_VIDEO_DEVINFO *psDevInfo;
+ int id;
+ *phDevice = NULL;
+ for (id = 0; id < BC_VIDEO_DEVICE_MAX_ID; id++) {
+ psDevInfo = GetAnchorPtr(id);
+ if (psDevInfo != NULL && psDevInfo->ulDeviceID == uDeviceID) {
+ *phDevice = (IMG_HANDLE) psDevInfo;
+ break;
+ }
+ }
+
+ return (PVRSRV_OK);
+}
+
+static PVRSRV_ERROR OpenCBCDevice(IMG_UINT32 uDeviceID, IMG_HANDLE *phDevice)
+{
+ BC_VIDEO_DEVINFO *psDevInfo;
+
+ UNREFERENCED_PARAMETER(uDeviceID);
+ psDevInfo = GetAnchorPtr(BC_CAMERA_DEVICEID);
+
+ *phDevice = (IMG_HANDLE)psDevInfo;
+
+ return (PVRSRV_OK);
+}
+
+static PVRSRV_ERROR
+CloseBCDevice(IMG_UINT32 uDeviceID, IMG_HANDLE hDevice)
+{
+ UNREFERENCED_PARAMETER(uDeviceID);
+ UNREFERENCED_PARAMETER(hDevice);
+
+ return (PVRSRV_OK);
+}
+
+static PVRSRV_ERROR
+GetBCBuffer(IMG_HANDLE hDevice,
+ IMG_UINT32 ui32BufferNumber,
+ PVRSRV_SYNC_DATA * psSyncData, IMG_HANDLE * phBuffer)
+{
+ BC_VIDEO_DEVINFO *psDevInfo;
+
+ if (!hDevice || !phBuffer) {
+ return (PVRSRV_ERROR_INVALID_PARAMS);
+ }
+
+ psDevInfo = (BC_VIDEO_DEVINFO *) hDevice;
+
+ if (ui32BufferNumber < psDevInfo->sBufferInfo.ui32BufferCount) {
+ psDevInfo->psSystemBuffer[ui32BufferNumber].psSyncData = psSyncData;
+ *phBuffer = (IMG_HANDLE) & psDevInfo->psSystemBuffer[ui32BufferNumber];
+ } else {
+ return (PVRSRV_ERROR_INVALID_PARAMS);
+ }
+
+ return (PVRSRV_OK);
+}
+
+static PVRSRV_ERROR
+GetBCInfo(IMG_HANDLE hDevice, BUFFER_INFO * psBCInfo)
+{
+ BC_VIDEO_DEVINFO *psDevInfo;
+
+ if (!hDevice || !psBCInfo) {
+ return (PVRSRV_ERROR_INVALID_PARAMS);
+ }
+
+ psDevInfo = (BC_VIDEO_DEVINFO *) hDevice;
+
+ *psBCInfo = psDevInfo->sBufferInfo;
+
+ return (PVRSRV_OK);
+}
+
+static PVRSRV_ERROR
+GetBCBufferAddr(IMG_HANDLE hDevice,
+ IMG_HANDLE hBuffer,
+ IMG_SYS_PHYADDR ** ppsSysAddr,
+ IMG_UINT32 * pui32ByteSize,
+ IMG_VOID ** ppvCpuVAddr,
+ IMG_HANDLE * phOSMapInfo,
+ IMG_BOOL * pbIsContiguous, IMG_UINT32 * pui32TilingStride)
+{
+ BC_VIDEO_BUFFER *psBuffer;
+
+ UNREFERENCED_PARAMETER(pui32TilingStride);
+ if (!hDevice || !hBuffer || !ppsSysAddr || !pui32ByteSize) {
+ return (PVRSRV_ERROR_INVALID_PARAMS);
+ }
+
+ psBuffer = (BC_VIDEO_BUFFER *) hBuffer;
+
+ *ppvCpuVAddr = psBuffer->sCPUVAddr;
+
+ *phOSMapInfo = IMG_NULL;
+ *pui32ByteSize = (IMG_UINT32) psBuffer->ulSize;
+
+ *ppsSysAddr = psBuffer->psSysAddr;
+ *pbIsContiguous = psBuffer->is_conti_addr;
+
+ return (PVRSRV_OK);
+}
+
+
+BCE_ERROR
+BC_Video_Register(int id)
+{
+ BC_VIDEO_DEVINFO *psDevInfo;
+
+ psDevInfo = GetAnchorPtr(id);
+
+ if (psDevInfo == NULL) {
+ psDevInfo =
+ (BC_VIDEO_DEVINFO *) BCAllocKernelMem(sizeof(BC_VIDEO_DEVINFO));
+
+ if (!psDevInfo) {
+ return (BCE_ERROR_OUT_OF_MEMORY);
+ }
+
+ SetAnchorPtr((void *) psDevInfo, id);
+
+ psDevInfo->ulRefCount = 0;
+
+ if (BCOpenPVRServices(&psDevInfo->hPVRServices) != BCE_OK) {
+ return (BCE_ERROR_INIT_FAILURE);
+ }
+ if (BCGetLibFuncAddr
+ (psDevInfo->hPVRServices, "PVRGetBufferClassJTable",
+ &pfnGetPVRJTable) != BCE_OK) {
+ return (BCE_ERROR_INIT_FAILURE);
+ }
+
+ if (!(*pfnGetPVRJTable)(&psDevInfo->sPVRJTable)) {
+ return (BCE_ERROR_INIT_FAILURE);
+ }
+
+ psDevInfo->ulNumBuffers = 0;
+
+ psDevInfo->sBufferInfo.pixelformat = PVRSRV_PIXEL_FORMAT_UNKNOWN;
+ psDevInfo->sBufferInfo.ui32Width = 0;
+ psDevInfo->sBufferInfo.ui32Height = 0;
+ psDevInfo->sBufferInfo.ui32ByteStride = 0;
+ psDevInfo->sBufferInfo.ui32BufferDeviceID = id;
+ psDevInfo->sBufferInfo.ui32Flags = 0;
+ psDevInfo->sBufferInfo.ui32BufferCount =
+ (IMG_UINT32) psDevInfo->ulNumBuffers;
+
+ if (id < BC_VIDEO_DEVICE_MAX_ID) {
+ strncpy(psDevInfo->sBufferInfo.szDeviceName,
+ VBUFFERCLASS_DEVICE_NAME, MAX_BUFFER_DEVICE_NAME_SIZE);
+ psDevInfo->sBCJTable.pfnOpenBCDevice = OpenVBCDevice;
+ } else if (id == BC_CAMERA_DEVICEID) {
+ strncpy(psDevInfo->sBufferInfo.szDeviceName,
+ CBUFFERCLASS_DEVICE_NAME, MAX_BUFFER_DEVICE_NAME_SIZE);
+ psDevInfo->sBCJTable.pfnOpenBCDevice = OpenCBCDevice;
+ }
+
+ psDevInfo->sBCJTable.ui32TableSize =
+ sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE);
+ psDevInfo->sBCJTable.pfnCloseBCDevice = CloseBCDevice;
+ psDevInfo->sBCJTable.pfnGetBCBuffer = GetBCBuffer;
+ psDevInfo->sBCJTable.pfnGetBCInfo = GetBCInfo;
+ psDevInfo->sBCJTable.pfnGetBufferAddr = GetBCBufferAddr;
+
+ if (psDevInfo->sPVRJTable.
+ pfnPVRSRVRegisterBCDevice(&psDevInfo->sBCJTable,
+ &psDevInfo->ulDeviceID) != PVRSRV_OK) {
+ return (BCE_ERROR_DEVICE_REGISTER_FAILED);
+ }
+ }
+
+ psDevInfo->ulRefCount++;
+
+ return (BCE_OK);
+}
+
+BCE_ERROR
+BC_Video_Unregister(int id)
+{
+ BC_VIDEO_DEVINFO *psDevInfo;
+
+ psDevInfo = GetAnchorPtr(id);
+
+ if (psDevInfo == NULL) {
+ return (BCE_ERROR_GENERIC);
+ }
+
+ psDevInfo->ulRefCount--;
+
+ if (psDevInfo->ulRefCount == 0) {
+ PVRSRV_BC_BUFFER2SRV_KMJTABLE *psJTable = &psDevInfo->sPVRJTable;
+
+ if (psJTable->pfnPVRSRVRemoveBCDevice(psDevInfo->ulDeviceID) !=
+ PVRSRV_OK) {
+ return (BCE_ERROR_GENERIC);
+ }
+
+ if (BCClosePVRServices(psDevInfo->hPVRServices) != BCE_OK) {
+ psDevInfo->hPVRServices = NULL;
+ return (BCE_ERROR_GENERIC);
+ }
+
+ if (psDevInfo->psSystemBuffer) {
+ BCFreeKernelMem(psDevInfo->psSystemBuffer);
+ }
+
+ BCFreeKernelMem(psDevInfo);
+
+ SetAnchorPtr(NULL, id);
+ }
+ return (BCE_OK);
+}
+
+BCE_ERROR
+BC_Video_Init(int id)
+{
+ BCE_ERROR eError;
+
+ eError = BC_Video_Register(id);
+ if (eError != BCE_OK) {
+ return eError;
+ }
+
+ return (BCE_OK);
+}
+
+BCE_ERROR
+BC_Video_Deinit(int id)
+{
+ BCE_ERROR eError;
+
+ BC_DestroyBuffers(id);
+
+ eError = BC_Video_Unregister(id);
+ if (eError != BCE_OK) {
+ return eError;
+ }
+
+ return (BCE_OK);
+}
--- /dev/null
+/**********************************************************************
+ *
+ * Copyright © 2010 Intel 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 (including the next
+ * paragraph) 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.
+ *
+ ******************************************************************************/
+
+#ifndef __BC_VIDEO_H__
+#define __BC_VIDEO_H__
+
+#include "img_defs.h"
+#include "servicesext.h"
+#include "kernelbuffer.h"
+#include <kernel.h>
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+ enum BC_memory
+ {
+ BC_MEMORY_MMAP = 1,
+ BC_MEMORY_USERPTR = 2,
+ };
+
+ /*
+ * the following types are tested for fourcc in struct bc_buf_params_t
+ * NV12
+ * UYVY
+ * RGB565 - not tested yet
+ * YUYV
+ */
+ typedef struct bc_buf_params {
+ int count; /*number of buffers, [in/out] */
+ int width; /*buffer width in pixel, multiple of 8 or 32 */
+ int height; /*buffer height in pixel */
+ int stride;
+ unsigned int fourcc; /*buffer pixel format */
+ enum BC_memory type;
+ } bc_buf_params_t;
+
+ extern IMG_IMPORT IMG_BOOL
+ PVRGetBufferClassJTable(PVRSRV_BC_BUFFER2SRV_KMJTABLE * psJTable);
+
+#define BC_VIDEO_DEVICE_MAX_ID 5
+#define BC_CAMERA_DEVICEID 8
+
+ typedef void *BCE_HANDLE;
+
+ typedef enum tag_bce_bool {
+ BCE_FALSE = 0,
+ BCE_TRUE = 1,
+ } BCE_BOOL, *BCE_PBOOL;
+
+ typedef struct BC_VIDEO_BUFFER_TAG {
+ unsigned long ulSize;
+ BCE_HANDLE hMemHandle;
+
+ IMG_SYS_PHYADDR *psSysAddr;
+
+ IMG_CPU_VIRTADDR sCPUVAddr;
+ PVRSRV_SYNC_DATA *psSyncData;
+
+ struct BC_VIDEO_BUFFER_TAG *psNext;
+ int sBufferHandle;
+ IMG_BOOL is_conti_addr;
+ } BC_VIDEO_BUFFER;
+
+ typedef struct BC_VIDEO_DEVINFO_TAG {
+ IMG_UINT32 ulDeviceID;
+
+ BC_VIDEO_BUFFER *psSystemBuffer;
+
+ unsigned long ulNumBuffers;
+
+ PVRSRV_BC_BUFFER2SRV_KMJTABLE sPVRJTable;
+
+ PVRSRV_BC_SRV2BUFFER_KMJTABLE sBCJTable;
+
+ BCE_HANDLE hPVRServices;
+
+ unsigned long ulRefCount;
+
+ BUFFER_INFO sBufferInfo;
+ enum BC_memory buf_type;
+ } BC_VIDEO_DEVINFO;
+
+ typedef enum _BCE_ERROR_ {
+ BCE_OK = 0,
+ BCE_ERROR_GENERIC = 1,
+ BCE_ERROR_OUT_OF_MEMORY = 2,
+ BCE_ERROR_TOO_FEW_BUFFERS = 3,
+ BCE_ERROR_INVALID_PARAMS = 4,
+ BCE_ERROR_INIT_FAILURE = 5,
+ BCE_ERROR_CANT_REGISTER_CALLBACK = 6,
+ BCE_ERROR_INVALID_DEVICE = 7,
+ BCE_ERROR_DEVICE_REGISTER_FAILED = 8,
+ BCE_ERROR_NO_PRIMARY = 9
+ } BCE_ERROR;
+
+#ifndef UNREFERENCED_PARAMETER
+#define UNREFERENCED_PARAMETER(param) (param) = (param)
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+ BCE_ERROR BC_Video_Register(int id);
+ BCE_ERROR BC_Video_Unregister(int id);
+ BCE_ERROR BC_Video_Buffers_Create(int id);
+ BCE_ERROR BC_Video_Buffers_Destroy(int id);
+ BCE_ERROR BC_Video_Init(int id);
+ BCE_ERROR BC_Video_Deinit(int id);
+
+ BCE_ERROR BCOpenPVRServices(BCE_HANDLE * phPVRServices);
+ BCE_ERROR BCClosePVRServices(BCE_HANDLE hPVRServices);
+
+ void *BCAllocKernelMem(unsigned long ulSize);
+ void BCFreeKernelMem(void *pvMem);
+
+ BCE_ERROR BCAllocDiscontigMemory(unsigned long ulSize,
+ BCE_HANDLE unref__ * phMemHandle,
+ IMG_CPU_VIRTADDR * pLinAddr,
+ IMG_SYS_PHYADDR ** ppPhysAddr);
+
+ void BCFreeDiscontigMemory(unsigned long ulSize,
+ BCE_HANDLE unref__ hMemHandle,
+ IMG_CPU_VIRTADDR LinAddr,
+ IMG_SYS_PHYADDR * pPhysAddr);
+
+ IMG_SYS_PHYADDR CpuPAddrToSysPAddrBC(IMG_CPU_PHYADDR cpu_paddr);
+ IMG_CPU_PHYADDR SysPAddrToCpuPAddrBC(IMG_SYS_PHYADDR sys_paddr);
+
+ void *MapPhysAddr(IMG_SYS_PHYADDR sSysAddr, unsigned long ulSize);
+ void UnMapPhysAddr(void *pvAddr, unsigned long ulSize);
+
+ BCE_ERROR BCGetLibFuncAddr(BCE_HANDLE hExtDrv, char *szFunctionName,
+ PFN_BC_GET_PVRJTABLE * ppfnFuncTable);
+ BC_VIDEO_DEVINFO *GetAnchorPtr(int id);
+ int GetBufferCount(unsigned int *puiBufferCount, int id);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
--- /dev/null
+/****************************************************************************
+ *
+ * Copyright © 2010 Intel 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 (including the next
+ * paragraph) 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.
+ *
+ ******************************************************************************/
+
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+#if defined(LMA)
+#include <linux/pci.h>
+#else
+#include <linux/dma-mapping.h>
+#endif
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include "psb_drv.h"
+#include "ttm/ttm_bo_api.h"
+#include "ttm/ttm_placement.h"
+#include "ttm/ttm_object.h"
+
+#include "bufferclass_video.h"
+#include "bufferclass_video_linux.h"
+#include "pvrmodule.h"
+#include "sys_pvr_drm_export.h"
+
+#define DEVNAME "bc_video"
+#define DRVNAME DEVNAME
+
+#if defined(BCE_USE_SET_MEMORY)
+#undef BCE_USE_SET_MEMORY
+#endif
+
+#if defined(__i386__) && defined(SUPPORT_LINUX_X86_PAT) && defined(SUPPORT_LINUX_X86_WRITECOMBINE)
+#include <asm/cacheflush.h>
+#define BCE_USE_SET_MEMORY
+#endif
+
+unsigned int bc_video_id_usage[BC_VIDEO_DEVICE_MAX_ID];
+
+MODULE_SUPPORTED_DEVICE(DEVNAME);
+
+int FillBuffer(unsigned int uiBufferIndex);
+
+#if defined(LDM_PLATFORM) || defined(LDM_PCI)
+static struct class *psPvrClass;
+#endif
+
+static int AssignedMajorNumber;
+
+#define unref__ __attribute__ ((unused))
+
+#if defined(LMA)
+#define PVR_BUFFERCLASS_MEMOFFSET (220 * 1024 * 1024)
+#define PVR_BUFFERCLASS_MEMSIZE (4 * 1024 * 1024)
+
+unsigned long g_ulMemBase = 0;
+unsigned long g_ulMemCurrent = 0;
+
+#define VENDOR_ID_PVR 0x1010
+#define DEVICE_ID_PVR 0x1CF1
+
+#define PVR_MEM_PCI_BASENUM 2
+#endif
+
+#define file_to_id(file) (iminor(file->f_path.dentry->d_inode))
+
+int
+BC_Video_ModInit(void)
+{
+ int i, j;
+ /*LDM_PCI is defined, while LDM_PLATFORM and LMA are not defined.*/
+#if defined(LDM_PLATFORM) || defined(LDM_PCI)
+ struct device *psDev;
+#endif
+
+#if defined(LMA)
+ struct pci_dev *psPCIDev;
+ int error;
+#endif
+
+#if defined(LMA)
+ psPCIDev = pci_get_device(VENDOR_ID_PVR, DEVICE_ID_PVR, NULL);
+ if (psPCIDev == NULL) {
+ printk(KERN_ERR DRVNAME
+ ": BC_Video_ModInit: pci_get_device failed\n");
+ goto ExitError;
+ }
+
+ if ((error = pci_enable_device(psPCIDev)) != 0) {
+ printk(KERN_ERR DRVNAME
+ ": BC_Video_ModInit: pci_enable_device failed (%d)\n", error);
+ goto ExitError;
+ }
+#endif
+
+#if defined(DEBUG)
+ printk(KERN_ERR DRVNAME ": BC_Video_ModInit: major device %d\n",
+ AssignedMajorNumber);
+#endif
+
+#if defined(LDM_PLATFORM) || defined(LDM_PCI)
+ psPvrClass = class_create(THIS_MODULE, "bc_video");
+ if (IS_ERR(psPvrClass)) {
+ printk(KERN_ERR DRVNAME
+ ": BC_Video_ModInit: unable to create class (%ld)",
+ PTR_ERR(psPvrClass));
+ goto ExitUnregister;
+ }
+
+ psDev = device_create(psPvrClass, NULL, MKDEV(AssignedMajorNumber, 0),
+ NULL, DEVNAME);
+ if (IS_ERR(psDev)) {
+ printk(KERN_ERR DRVNAME
+ ": BC_Video_ModInit: unable to create device (%ld)",
+ PTR_ERR(psDev));
+ goto ExitDestroyClass;
+ }
+#endif
+
+#if defined(LMA)
+ g_ulMemBase =
+ pci_resource_start(psPCIDev,
+ PVR_MEM_PCI_BASENUM) + PVR_BUFFERCLASS_MEMOFFSET;
+#endif
+
+ for (i = 0; i < BC_VIDEO_DEVICE_MAX_ID; i++) {
+ bc_video_id_usage[i] = 0;
+ if (BC_Video_Init(i) != BCE_OK) {
+ printk(KERN_ERR DRVNAME
+ ": BC_Video_ModInit: can't init video bc device %d.\n", i);
+ for (j = i; j >= 0; j--) {
+ BC_Video_Deinit(j);
+ }
+ goto ExitUnregister;
+ }
+ }
+
+ if (BC_Video_Init(BC_CAMERA_DEVICEID) != BCE_OK) {
+ for (i = BC_VIDEO_DEVICE_MAX_ID - 1; i >= 0; i--) {
+ BC_Video_Deinit(i);
+ }
+ BC_Video_Deinit(BC_CAMERA_DEVICEID);
+ printk(KERN_ERR DRVNAME ": BC_Camera_ModInit: can't init device\n");
+ goto ExitUnregister;
+ }
+
+#if defined(LMA)
+ pci_disable_device(psPCIDev);
+#endif
+
+ return 0;
+
+#if defined(LDM_PLATFORM) || defined(LDM_PCI)
+ExitDestroyClass:
+ class_destroy(psPvrClass);
+#endif
+ExitUnregister:
+ unregister_chrdev(AssignedMajorNumber, DEVNAME);
+ //ExitDisable:
+#if defined(LMA)
+ pci_disable_device(psPCIDev);
+ExitError:
+#endif
+ return -EBUSY;
+}
+
+int
+BC_Video_ModCleanup(void)
+{
+ int i;
+#if defined(LDM_PLATFORM) || defined(LDM_PCI)
+ device_destroy(psPvrClass, MKDEV(AssignedMajorNumber, 0));
+ class_destroy(psPvrClass);
+#endif
+
+ for (i = 0; i < BC_VIDEO_DEVICE_MAX_ID; i++) {
+ if (BC_Video_Deinit(i) != BCE_OK) {
+ printk(KERN_ERR DRVNAME
+ ": BC_Video_ModCleanup: can't deinit video device %d.\n",
+ i);
+ return -1;
+ }
+ }
+
+ if (BC_Video_Deinit(BC_CAMERA_DEVICEID) != BCE_OK) {
+ printk(KERN_ERR DRVNAME
+ ": BC_Camera_ModCleanup: can't deinit device\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+void *
+BCAllocKernelMem(unsigned long ulSize)
+{
+ return kmalloc(ulSize, GFP_KERNEL);
+}
+
+void
+BCFreeKernelMem(void *pvMem)
+{
+ kfree(pvMem);
+}
+
+#define RANGE_TO_PAGES(range) (((range) + (PAGE_SIZE - 1)) >> PAGE_SHIFT)
+#define VMALLOC_TO_PAGE_PHYS(vAddr) page_to_phys(vmalloc_to_page(vAddr))
+
+BCE_ERROR
+BCAllocDiscontigMemory(unsigned long ulSize,
+ BCE_HANDLE unref__ * phMemHandle,
+ IMG_CPU_VIRTADDR * pLinAddr,
+ IMG_SYS_PHYADDR ** ppPhysAddr)
+{
+ unsigned long ulPages = RANGE_TO_PAGES(ulSize);
+ IMG_SYS_PHYADDR *pPhysAddr;
+ unsigned long ulPage;
+ IMG_CPU_VIRTADDR LinAddr;
+
+ LinAddr =
+ __vmalloc(ulSize, GFP_KERNEL | __GFP_HIGHMEM,
+ pgprot_noncached(PAGE_KERNEL));
+ if (!LinAddr) {
+ return BCE_ERROR_OUT_OF_MEMORY;
+ }
+
+ pPhysAddr = kmalloc(ulPages * sizeof(IMG_SYS_PHYADDR), GFP_KERNEL);
+ if (!pPhysAddr) {
+ vfree(LinAddr);
+ return BCE_ERROR_OUT_OF_MEMORY;
+ }
+
+ *pLinAddr = LinAddr;
+
+ for (ulPage = 0; ulPage < ulPages; ulPage++) {
+ pPhysAddr[ulPage].uiAddr = VMALLOC_TO_PAGE_PHYS(LinAddr);
+
+ LinAddr += PAGE_SIZE;
+ }
+
+ *ppPhysAddr = pPhysAddr;
+
+ return BCE_OK;
+}
+
+void
+BCFreeDiscontigMemory(unsigned long ulSize,
+ BCE_HANDLE unref__ hMemHandle,
+ IMG_CPU_VIRTADDR LinAddr, IMG_SYS_PHYADDR * pPhysAddr)
+{
+ kfree(pPhysAddr);
+
+ vfree(LinAddr);
+}
+
+static BCE_ERROR
+BCAllocContigMemory(unsigned long ulSize,
+ BCE_HANDLE unref__ * phMemHandle,
+ IMG_CPU_VIRTADDR * pLinAddr, IMG_CPU_PHYADDR * pPhysAddr)
+{
+#if defined(LMA)
+ void *pvLinAddr;
+
+
+ if (g_ulMemCurrent + ulSize >= PVR_BUFFERCLASS_MEMSIZE) {
+ return (BCE_ERROR_OUT_OF_MEMORY);
+ }
+
+ pvLinAddr = ioremap(g_ulMemBase + g_ulMemCurrent, ulSize);
+
+ if (pvLinAddr) {
+ pPhysAddr->uiAddr = g_ulMemBase + g_ulMemCurrent;
+ *pLinAddr = pvLinAddr;
+
+ g_ulMemCurrent += ulSize;
+ return (BCE_OK);
+ }
+ return (BCE_ERROR_OUT_OF_MEMORY);
+#else
+#if defined(BCE_USE_SET_MEMORY)
+ void *pvLinAddr;
+ unsigned long ulAlignedSize = PAGE_ALIGN(ulSize);
+ int iPages = (int)(ulAlignedSize >> PAGE_SHIFT);
+ int iError;
+
+ pvLinAddr = kmalloc(ulAlignedSize, GFP_KERNEL);
+ BUG_ON(((unsigned long) pvLinAddr) & ~PAGE_MASK);
+
+ iError = set_memory_wc((unsigned long) pvLinAddr, iPages);
+ if (iError != 0) {
+ printk(KERN_ERR DRVNAME
+ ": BCAllocContigMemory: set_memory_wc failed (%d)\n", iError);
+ return (BCE_ERROR_OUT_OF_MEMORY);
+ }
+
+ pPhysAddr->uiAddr = virt_to_phys(pvLinAddr);
+ *pLinAddr = pvLinAddr;
+
+ return (BCE_OK);
+#else
+ dma_addr_t dma;
+ void *pvLinAddr;
+
+ pvLinAddr = dma_alloc_coherent(NULL, ulSize, &dma, GFP_KERNEL);
+ if (pvLinAddr == NULL) {
+ return (BCE_ERROR_OUT_OF_MEMORY);
+ }
+
+ pPhysAddr->uiAddr = dma;
+ *pLinAddr = pvLinAddr;
+
+ return (BCE_OK);
+#endif
+#endif
+}
+
+static void
+BCFreeContigMemory(unsigned long ulSize,
+ BCE_HANDLE unref__ hMemHandle,
+ IMG_CPU_VIRTADDR LinAddr, IMG_CPU_PHYADDR PhysAddr)
+{
+#if defined(LMA)
+ g_ulMemCurrent -= ulSize;
+ iounmap(LinAddr);
+#else
+#if defined(BCE_USE_SET_MEMORY)
+ unsigned long ulAlignedSize = PAGE_ALIGN(ulSize);
+ int iError;
+ int iPages = (int)(ulAlignedSize >> PAGE_SHIFT);
+
+ iError = set_memory_wb((unsigned long) LinAddr, iPages);
+ if (iError != 0) {
+ printk(KERN_ERR DRVNAME
+ ": BCFreeContigMemory: set_memory_wb failed (%d)\n", iError);
+ }
+ kfree(LinAddr);
+#else
+ dma_free_coherent(NULL, ulSize, LinAddr, (dma_addr_t) PhysAddr.uiAddr);
+#endif
+#endif
+}
+
+IMG_SYS_PHYADDR
+CpuPAddrToSysPAddrBC(IMG_CPU_PHYADDR cpu_paddr)
+{
+ IMG_SYS_PHYADDR sys_paddr;
+ sys_paddr.uiAddr = cpu_paddr.uiAddr;
+ return sys_paddr;
+}
+
+IMG_CPU_PHYADDR
+SysPAddrToCpuPAddrBC(IMG_SYS_PHYADDR sys_paddr)
+{
+ IMG_CPU_PHYADDR cpu_paddr;
+ cpu_paddr.uiAddr = sys_paddr.uiAddr;
+ return cpu_paddr;
+}
+
+BCE_ERROR
+BCOpenPVRServices(BCE_HANDLE * phPVRServices)
+{
+ *phPVRServices = 0;
+ return (BCE_OK);
+}
+
+
+BCE_ERROR
+BCClosePVRServices(BCE_HANDLE unref__ hPVRServices)
+{
+ return (BCE_OK);
+}
+
+BCE_ERROR
+BCGetLibFuncAddr(BCE_HANDLE unref__ hExtDrv, char *szFunctionName,
+ PFN_BC_GET_PVRJTABLE * ppfnFuncTable)
+{
+ if (strcmp("PVRGetBufferClassJTable", szFunctionName) != 0) {
+ return (BCE_ERROR_INVALID_PARAMS);
+ }
+
+ *ppfnFuncTable = PVRGetBufferClassJTable;
+
+ return (BCE_OK);
+}
+
+static int
+BC_CreateBuffers(int id, bc_buf_params_t * p, IMG_BOOL is_conti_addr)
+{
+ BC_VIDEO_DEVINFO *psDevInfo;
+ IMG_UINT32 i, stride, size;
+ PVRSRV_PIXEL_FORMAT pixel_fmt;
+
+ if (p->count <= 0)
+ return -EINVAL;
+
+ if (p->width <= 1 || p->height <= 1)
+ return -EINVAL;
+
+ switch (p->fourcc) {
+ case BC_PIX_FMT_NV12:
+ pixel_fmt = PVRSRV_PIXEL_FORMAT_NV12;
+ break;
+ case BC_PIX_FMT_UYVY:
+ pixel_fmt = PVRSRV_PIXEL_FORMAT_FOURCC_ORG_UYVY;
+ break;
+ case BC_PIX_FMT_RGB565:
+ pixel_fmt = PVRSRV_PIXEL_FORMAT_RGB565;
+ p->stride = p->stride << 1; /* stride for RGB from user space is uncorrect */
+ break;
+ case BC_PIX_FMT_YUYV:
+ pixel_fmt = PVRSRV_PIXEL_FORMAT_FOURCC_ORG_YUYV;
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
+
+ stride = p->stride;
+
+ if (p->type != BC_MEMORY_MMAP && p->type != BC_MEMORY_USERPTR)
+ return -EINVAL;
+
+ if ((psDevInfo = GetAnchorPtr(id)) == IMG_NULL)
+ return -ENODEV;
+
+ if (psDevInfo->ulNumBuffers)
+ BC_DestroyBuffers(id);
+
+ psDevInfo->buf_type = p->type;
+ psDevInfo->psSystemBuffer =
+ BCAllocKernelMem(sizeof(BC_VIDEO_BUFFER) * p->count);
+
+ if (!psDevInfo->psSystemBuffer)
+ return -ENOMEM;
+
+ memset(psDevInfo->psSystemBuffer, 0, sizeof(BC_VIDEO_BUFFER) * p->count);
+ size = p->height * stride;
+ if (pixel_fmt == PVRSRV_PIXEL_FORMAT_NV12)
+ size += (stride >> 1) * (p->height >> 1) << 1;
+
+ for (i = 0; i < p->count; i++) {
+ IMG_SYS_PHYADDR *pPhysAddr;
+ psDevInfo->ulNumBuffers++;
+ psDevInfo->psSystemBuffer[i].ulSize = size;
+ psDevInfo->psSystemBuffer[i].psSyncData = IMG_NULL;
+
+ /*for discontig buffers, allocate memory for pPhysAddr */
+ psDevInfo->psSystemBuffer[i].is_conti_addr = is_conti_addr;
+ if (is_conti_addr) {
+ pPhysAddr = BCAllocKernelMem(1 * sizeof(IMG_SYS_PHYADDR));
+ if (!pPhysAddr) {
+ return BCE_ERROR_OUT_OF_MEMORY;
+ }
+ memset(pPhysAddr, 0, 1 * sizeof(IMG_SYS_PHYADDR));
+ } else {
+ unsigned long ulPages = RANGE_TO_PAGES(size);
+ pPhysAddr = BCAllocKernelMem(ulPages * sizeof(IMG_SYS_PHYADDR));
+ if (!pPhysAddr) {
+ return BCE_ERROR_OUT_OF_MEMORY;
+ }
+ memset(pPhysAddr, 0, ulPages * sizeof(IMG_SYS_PHYADDR));
+ }
+ psDevInfo->psSystemBuffer[i].psSysAddr = pPhysAddr;
+ }
+ p->count = psDevInfo->ulNumBuffers;
+
+ psDevInfo->sBufferInfo.ui32BufferCount = psDevInfo->ulNumBuffers;
+ psDevInfo->sBufferInfo.pixelformat = pixel_fmt;
+ psDevInfo->sBufferInfo.ui32Width = p->width;
+ psDevInfo->sBufferInfo.ui32Height = p->height;
+ psDevInfo->sBufferInfo.ui32ByteStride = stride;
+ psDevInfo->sBufferInfo.ui32BufferDeviceID = id;
+ psDevInfo->sBufferInfo.ui32Flags = PVRSRV_BC_FLAGS_YUVCSC_FULL_RANGE |
+ PVRSRV_BC_FLAGS_YUVCSC_BT601;
+ return 0;
+}
+
+int
+BC_DestroyBuffers(int id)
+{
+ BC_VIDEO_DEVINFO *psDevInfo;
+ IMG_UINT32 i;
+ if ((psDevInfo = GetAnchorPtr(id)) == IMG_NULL)
+ return -ENODEV;
+
+ if (!psDevInfo->ulNumBuffers)
+ return 0;
+
+ for (i = 0; i < psDevInfo->ulNumBuffers; i++)
+ BCFreeKernelMem(psDevInfo->psSystemBuffer[i].psSysAddr);
+
+ BCFreeKernelMem(psDevInfo->psSystemBuffer);
+
+ psDevInfo->ulNumBuffers = 0;
+ psDevInfo->sBufferInfo.pixelformat = PVRSRV_PIXEL_FORMAT_UNKNOWN;
+ psDevInfo->sBufferInfo.ui32Width = 0;
+ psDevInfo->sBufferInfo.ui32Height = 0;
+ psDevInfo->sBufferInfo.ui32ByteStride = 0;
+ psDevInfo->sBufferInfo.ui32BufferDeviceID = id;
+ psDevInfo->sBufferInfo.ui32Flags = 0;
+ psDevInfo->sBufferInfo.ui32BufferCount = psDevInfo->ulNumBuffers;
+
+ return 0;
+}
+
+int
+GetBufferCount(unsigned int *puiBufferCount, int id)
+{
+ BC_VIDEO_DEVINFO *psDevInfo = GetAnchorPtr(id);
+
+ if (psDevInfo == IMG_NULL) {
+ return -1;
+ }
+
+ *puiBufferCount = (unsigned int) psDevInfo->sBufferInfo.ui32BufferCount;
+
+ return 0;
+}
+
+int
+BC_Video_Bridge(struct drm_device *dev, IMG_VOID * arg,
+ struct drm_file *file_priv)
+{
+ int err = -EFAULT;
+
+ BC_VIDEO_DEVINFO *devinfo;
+ int i;
+ BC_Video_ioctl_package *psBridge = (BC_Video_ioctl_package *) arg;
+ int command = psBridge->ioctl_cmd;
+ int id = 0;
+
+ if (command == BC_Video_ioctl_request_buffers) {
+ for (i = 0; i < BC_VIDEO_DEVICE_MAX_ID; i++) {
+ if (bc_video_id_usage[i] == 0) {
+ bc_video_id_usage[i] = 1;
+ id = i;
+ break;
+ }
+ }
+ if (i == BC_VIDEO_DEVICE_MAX_ID) {
+ printk(KERN_ERR DRVNAME
+ " : Does you really need to run more than 5 video simulateously.\n");
+ return -1;
+ } else
+ psb_fpriv(file_priv)->bcd_index = id;
+ } else
+ id = psBridge->device_id;
+
+ if ((devinfo = GetAnchorPtr(id)) == IMG_NULL)
+ return -ENODEV;
+
+ switch (command) {
+ case BC_Video_ioctl_get_buffer_count: {
+ if (GetBufferCount(&psBridge->outputparam, id) == -1) {
+ printk(KERN_ERR DRVNAME
+ " : GetBufferCount error in BC_Video_Bridge.\n");
+ return err;
+ }
+ return 0;
+ break;
+ }
+ case BC_Video_ioctl_get_buffer_index: {
+ int idx;
+ BC_VIDEO_BUFFER *buffer;
+
+ for (idx = 0; idx < devinfo->ulNumBuffers; idx++) {
+ buffer = &devinfo->psSystemBuffer[idx];
+
+ if (psBridge->inputparam == buffer->sBufferHandle) {
+ psBridge->outputparam = idx;
+ return 0;
+ }
+ }
+ printk(KERN_ERR DRVNAME ": BCIOGET_BUFFERIDX- buffer not found\n");
+ return -EINVAL;
+ break;
+ }
+ case BC_Video_ioctl_request_buffers: {
+ bc_buf_params_t p;
+ if (copy_from_user
+ (&p, (void __user *)(psBridge->inputparam), sizeof(p))) {
+ printk(KERN_ERR " : failed to copy inputparam to kernel.\n");
+ return -EFAULT;
+ }
+ psBridge->outputparam = id;
+ return BC_CreateBuffers(id, &p, IMG_FALSE);
+ break;
+ }
+ case BC_Video_ioctl_set_buffer_phyaddr: {
+ bc_buf_ptr_t p;
+ struct ttm_buffer_object *bo = NULL;
+ struct ttm_tt *ttm = NULL;
+ struct ttm_object_file *tfile = psb_fpriv(file_priv)->tfile;
+
+ if (copy_from_user
+ (&p, (void __user *)(psBridge->inputparam), sizeof(p))) {
+ printk(KERN_ERR DRVNAME
+ " : failed to copy inputparam to kernel.\n");
+ return -EFAULT;
+ }
+
+ if (p.index >= devinfo->ulNumBuffers || !p.handle) {
+ printk(KERN_ERR DRVNAME
+ " : index big than NumBuffers or p.handle is NULL.\n");
+ return -EINVAL;
+ }
+
+ bo = ttm_buffer_object_lookup(tfile, p.handle);
+ if (unlikely(bo == NULL)) {
+ printk(KERN_ERR DRVNAME
+ " : Could not find buffer object for setstatus.\n");
+ return -EINVAL;
+ }
+ ttm = bo->ttm;
+
+ devinfo->psSystemBuffer[p.index].sCPUVAddr = NULL;
+ devinfo->psSystemBuffer[p.index].sBufferHandle = p.handle;
+ for (i = 0; i < ttm->num_pages; i++) {
+ if (ttm->pages[i] == NULL) {
+ printk(KERN_ERR " : Debug: the page is NULL.\n");
+ return -EINVAL;
+ }
+ devinfo->psSystemBuffer[p.index].psSysAddr[i].uiAddr =
+ page_to_pfn(ttm->pages[i]) << PAGE_SHIFT;
+ }
+ if (bo)
+ ttm_bo_unref(&bo);
+ return 0;
+ break;
+ }
+ case BC_Video_ioctl_release_buffer_device: {
+ bc_video_id_usage[id] = 0;
+
+ BC_DestroyBuffers(id);
+ return 0;
+ break;
+ }
+ case BC_Video_ioctl_alloc_buffer: {
+ bc_buf_ptr_t p;
+ IMG_VOID *pvBuf;
+ IMG_UINT32 ui32Size;
+ IMG_UINT32 ulPagesNumber;
+ IMG_UINT32 ulCounter;
+ BUFFER_INFO *bufferInfo;
+
+ if (copy_from_user
+ (&p, (void __user *)(psBridge->inputparam), sizeof(p))) {
+ printk(KERN_ERR DRVNAME
+ " : failed to copy inputparam to kernel.\n");
+ return -EFAULT;
+ }
+
+ if (p.index >= devinfo->ulNumBuffers) {
+ printk(KERN_ERR DRVNAME " : index big than NumBuffers.\n");
+ return -EINVAL;
+ }
+
+ bufferInfo = &(devinfo->sBufferInfo);
+ if (bufferInfo->pixelformat != PVRSRV_PIXEL_FORMAT_NV12) {
+ printk(KERN_ERR DRVNAME
+ " : BC_Video_ioctl_alloc_buffer only support NV12 format.\n");
+ return -EINVAL;
+ }
+ ui32Size = bufferInfo->ui32Height * bufferInfo->ui32ByteStride;
+ ui32Size +=
+ (bufferInfo->ui32ByteStride >> 1) *
+ (bufferInfo->ui32Height >> 1) << 1;
+
+ pvBuf =
+ __vmalloc(ui32Size, GFP_KERNEL | __GFP_HIGHMEM,
+ __pgprot((pgprot_val(PAGE_KERNEL) & ~_PAGE_CACHE_MASK)
+ | _PAGE_CACHE_WC));
+ if (pvBuf == NULL) {
+ printk(KERN_ERR DRVNAME
+ " : Failed to allocate %d bytes buffer.\n", ui32Size);
+ return -EINVAL;
+ }
+ devinfo->psSystemBuffer[p.index].sCPUVAddr = pvBuf;
+ devinfo->psSystemBuffer[p.index].sBufferHandle = 0;
+
+ ulPagesNumber = (ui32Size + PAGE_SIZE - 1) / PAGE_SIZE;
+ i = 0;
+
+ for (ulCounter = 0; ulCounter < ui32Size; ulCounter += PAGE_SIZE) {
+ devinfo->psSystemBuffer[p.index].psSysAddr[i++].uiAddr =
+ vmalloc_to_pfn(pvBuf + ulCounter) << PAGE_SHIFT;
+ }
+
+ if (p.handle) {
+ printk(KERN_ERR DRVNAME
+ " : fill data %d bytes from user space 0x%x.\n", ui32Size,
+ (int) p.handle);
+ if (copy_from_user(pvBuf, (void __user *) p.handle, ui32Size)) {
+ printk(KERN_ERR DRVNAME
+ " : failed to copy inputparam to kernel.\n");
+ return -EFAULT;
+ }
+
+ }
+ psBridge->outputparam = (int) pvBuf;
+
+ return 0;
+ break;
+ }
+ case BC_Video_ioctl_free_buffer: {
+ bc_buf_ptr_t p;
+
+ if (copy_from_user
+ (&p, (void __user *)(psBridge->inputparam), sizeof(p))) {
+ printk(KERN_ERR DRVNAME
+ " : failed to copy inputparam to kernel.\n");
+ return -EFAULT;
+ }
+
+ vfree(devinfo->psSystemBuffer[p.index].sCPUVAddr);
+ return 0;
+ break;
+ }
+ default:
+ return err;
+ }
+
+ return 0;
+}
+
+static int
+BC_Camera_Bridge(BC_Video_ioctl_package * psBridge, unsigned long pAddr)
+{
+ int err = -EFAULT;
+
+ BC_VIDEO_DEVINFO *devinfo;
+ int id = BC_CAMERA_DEVICEID;
+ int command = psBridge->ioctl_cmd;
+
+ if ((devinfo = GetAnchorPtr(BC_CAMERA_DEVICEID)) == IMG_NULL)
+ return -ENODEV;
+
+ switch (command) {
+ case BC_Video_ioctl_get_buffer_count: {
+ if (GetBufferCount(&psBridge->outputparam, id) == -1) {
+ printk(KERN_ERR DRVNAME
+ " : GetBufferCount error in BC_Video_Bridge.\n");
+ return err;
+ }
+ return 0;
+ break;
+ }
+ case BC_Video_ioctl_get_buffer_index: {
+ int idx;
+ BC_VIDEO_BUFFER *buffer;
+
+ for (idx = 0; idx < devinfo->ulNumBuffers; idx++) {
+ buffer = &devinfo->psSystemBuffer[idx];
+
+ if (psBridge->inputparam == buffer->sBufferHandle) {
+ psBridge->outputparam = idx;
+ return 0;
+ }
+ }
+ printk(KERN_ERR DRVNAME ": BCIOGET_BUFFERIDX- buffer not found\n");
+ return -EINVAL;
+ break;
+ }
+ case BC_Video_ioctl_request_buffers: {
+ bc_buf_params_t p;
+ memcpy(&p, (void *)(psBridge->inputparam), sizeof(p));
+ return BC_CreateBuffers(id, &p, IMG_TRUE);
+ break;
+ }
+ case BC_Video_ioctl_set_buffer_phyaddr: {
+ bc_buf_ptr_t p;
+
+ memcpy(&p, (void *)(psBridge->inputparam), sizeof(p));
+ if (p.index >= devinfo->ulNumBuffers) {
+ printk(KERN_ERR DRVNAME " : index big than NumBuffers\n");
+ return -EINVAL;
+ }
+
+ /* Get the physical address of each frame */
+ devinfo->psSystemBuffer[p.index].psSysAddr[0].uiAddr =
+ pAddr +
+ p.index * PAGE_ALIGN(devinfo->psSystemBuffer[p.index].ulSize);
+
+ return 0;
+ break;
+ }
+ default:
+ return err;
+ }
+
+ return 0;
+}
--- /dev/null
+/*****************************************************************************
+ *
+ * Copyright © 2010 Intel 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 (including the next
+ * paragraph) 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.
+ *
+ ******************************************************************************/
+
+#ifndef __BC_VIDEO_LINUX_H__
+#define __BC_VIDEO_LINUX_H__
+
+#include <linux/ioctl.h>
+#include "bufferclass_video.h"
+
+#define BC_FOURCC(a,b,c,d) \
+ ((unsigned long) ((a) | (b)<<8 | (c)<<16 | (d)<<24))
+
+#define BC_PIX_FMT_NV12 BC_FOURCC('N', 'V', '1', '2') /*YUV 4:2:0 */
+#define BC_PIX_FMT_UYVY BC_FOURCC('U', 'Y', 'V', 'Y') /*YUV 4:2:2 */
+#define BC_PIX_FMT_YUYV BC_FOURCC('Y', 'U', 'Y', 'V') /*YUV 4:2:2 */
+#define BC_PIX_FMT_RGB565 BC_FOURCC('R', 'G', 'B', 'P') /*RGB 5:6:5 */
+
+typedef struct BC_Video_ioctl_package_TAG {
+ int ioctl_cmd;
+ int device_id;
+ int inputparam;
+ int outputparam;
+} BC_Video_ioctl_package;
+
+typedef struct bc_buf_ptr {
+ unsigned int index;
+ int size;
+ unsigned long pa;
+ unsigned long handle;
+} bc_buf_ptr_t;
+
+#define BC_Video_ioctl_fill_buffer 0
+#define BC_Video_ioctl_get_buffer_count 1
+#define BC_Video_ioctl_get_buffer_phyaddr 2 /*get physical address by index */
+#define BC_Video_ioctl_get_buffer_index 3 /*get index by physical address */
+#define BC_Video_ioctl_request_buffers 4
+#define BC_Video_ioctl_set_buffer_phyaddr 5
+#define BC_Video_ioctl_release_buffer_device 6
+
+#define BC_Video_ioctl_alloc_buffer 7
+#define BC_Video_ioctl_free_buffer 8
+
+int BC_DestroyBuffers(int id);
+
+extern unsigned int bc_video_id_usage[BC_VIDEO_DEVICE_MAX_ID];
+
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2010 Intel 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 (including the next
+ * paragraph) 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.
+ *
+ * Authors:
+ * Thomas Eaton <thomas.g.eaton@intel.com>
+ * Scott Rowe <scott.m.rowe@intel.com>
+*/
+
+
+#ifndef HDMI_H
+#define HDMI_H
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_edid.h>
+
+#include "mdfld_output.h"
+
+void hdmi_init(struct drm_device* dev);
+
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2010 Intel 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, sublicensen
+ * 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 (including the next
+ * paragraph) 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.
+ *
+ * Authors:
+ * Thomas Eaton <thomas.g.eaton@intel.com>
+ * Scott Rowe <scott.m.rowe@intel.com>
+*/
+
+
+#ifndef TMD_VID_H
+#define TMD_VID_H
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_edid.h>
+
+#include "mdfld_output.h"
+
+void tmd_vid_init(struct drm_device* dev, struct panel_funcs* p_funcs);
+
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2010 Intel 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, sublicensen
+ * 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 (including the next
+ * paragraph) 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.
+ *
+ * Authors:
+ * Thomas Eaton <thomas.g.eaton@intel.com>
+ * Scott Rowe <scott.m.rowe@intel.com>
+*/
+
+
+
+#ifndef TPO_CMD_H
+#define TPO_CMD_H
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_edid.h>
+
+#include "mdfld_output.h"
+
+void tpo_cmd_init(struct drm_device* dev, struct panel_funcs* p_funcs);
+
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2010 Intel 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, sublicensen
+ * 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 (including the next
+ * paragraph) 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.
+ *
+ * Authors:
+ * Thomas Eaton <thomas.g.eaton@intel.com>
+ * Scott Rowe <scott.m.rowe@intel.com>
+*/
+
+
+#ifndef TPO_VID_H
+#define TPO_VID_H
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_edid.h>
+
+#include "mdfld_output.h"
+
+void tpo_vid_init(struct drm_device* dev, struct panel_funcs* p_funcs);
+
+#endif
--- /dev/null
+/*
+ * Copyright © 2010 Intel 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 (including the next
+ * paragraph) 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.
+ *
+ * Authors:
+ * jim liu <jim.liu@intel.com>
+ * Jackie Li<yaodong.li@intel.com>
+ */
+
+#include "mdfld_dsi_dbi.h"
+#include "mdfld_dsi_dbi_dpu.h"
+#include "mdfld_dsi_pkg_sender.h"
+
+#include "psb_powermgmt.h"
+
+static int enter_dsr;
+struct mdfld_dsi_dbi_output *gdbi_output;
+
+#define MDFLD_DSR_MAX_IDLE_COUNT 2
+#define MDFLD_DSI_MAX_RETURN_PACKET_SIZE 512
+
+/**
+ * set refreshing area
+ */
+int mdfld_dsi_dbi_update_area(struct mdfld_dsi_dbi_output * dbi_output,
+ u16 x1, u16 y1, u16 x2, u16 y2)
+{
+ struct mdfld_dsi_pkg_sender * sender =
+ mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base);
+ u8 param[5];
+ int err;
+
+ if(!sender) {
+ DRM_ERROR("Cannot get PKG sender\n");
+ return -EINVAL;
+ }
+
+ /*set column*/
+ param[0] = DCS_SET_COLUMN_ADDRESS;
+ param[1] = x1 >> 8;
+ param[2] = x1;
+ param[3] = x2 >> 8;
+ param[4] = x2;
+
+ err = mdfld_dsi_send_mcs_long(sender, param, 5, true);
+ if(err) {
+ DRM_ERROR("DCS_SET_COLUMN_ADDRESS sent failed\n");
+ goto err_out;
+ }
+
+ /*set page*/
+ param[0] = DCS_SET_PAGE_ADDRESS;
+ param[1] = y1 >> 8;
+ param[2] = y1;
+ param[3] = y2 >> 8;
+ param[4] = y2;
+
+ err = mdfld_dsi_send_mcs_long(sender, param, 5, true);
+ if(err) {
+ DRM_ERROR("DCS_SET_PAGE_ADDRESS sent failed\n");
+ goto err_out;
+ }
+
+ /*update screen*/
+ err = mdfld_dsi_write_mem_start(sender);
+ if(err) {
+ DRM_ERROR("DCS_WRITE_MEM_START sent failed\n");
+ goto err_out;
+ }
+
+err_out:
+ return err;
+}
+
+/**
+ * set panel's power state
+ */
+int mdfld_dsi_dbi_update_power(struct mdfld_dsi_dbi_output * dbi_output, int mode)
+{
+ struct drm_device * dev = dbi_output->dev;
+ struct drm_psb_private * dev_priv = dev->dev_private;
+ struct mdfld_dsi_pkg_sender * sender =
+ mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base);
+ u32 err = 0;
+
+ if(!sender) {
+ DRM_ERROR("Cannot get PKG sender\n");
+ return -EINVAL;
+ }
+
+ if(mode == DRM_MODE_DPMS_ON) {
+ /*exit sleep mode*/
+ err = mdfld_dsi_send_mcs_short(sender, DCS_EXIT_SLEEP_MODE,
+ 0, 0, true);
+ if (err) {
+ DRM_ERROR("DCS 0x%x sent failed\n",
+ DCS_EXIT_SLEEP_MODE);
+ goto power_err;
+ }
+
+ /*set display on*/
+ err = mdfld_dsi_send_mcs_short(sender, DCS_SET_DISPLAY_ON,
+ 0, 0, true);
+ if (err) {
+ DRM_ERROR("DCS 0x%x sent failed\n",
+ DCS_SET_DISPLAY_ON);
+ goto power_err;
+ }
+
+ /* set tear effect on */
+ err = mdfld_dsi_send_mcs_short(sender, DCS_SET_TEAR_ON,
+ 0, 1, true);
+ if (err) {
+ DRM_ERROR("DCS 0x%x sent failed\n", DCS_SET_TEAR_ON);
+ goto power_err;
+ }
+
+ /**
+ * FIXME: remove this later
+ */
+ err = mdfld_dsi_write_mem_start(sender);
+ if (err) {
+ DRM_ERROR("DCS 0x%x sent failed\n",
+ DCS_WRITE_MEM_START);
+ goto power_err;
+ }
+ } else {
+ /*set tear effect off */
+ err = mdfld_dsi_send_mcs_short(sender, DCS_SET_TEAR_OFF,
+ 0, 0, true);
+ if (err) {
+ DRM_ERROR("DCS 0x%x sent failed\n", set_tear_off);
+ goto power_err;
+ }
+
+ /*set display off*/
+ err = mdfld_dsi_send_mcs_short(sender, DCS_SET_DISPLAY_OFF,
+ 0, 0, true);
+ if (err) {
+ DRM_ERROR("DCS 0x%x sent failed\n",
+ DCS_SET_DISPLAY_OFF);
+ goto power_err;
+ }
+
+ /*enter sleep mode*/
+ err = mdfld_dsi_send_mcs_short(sender, DCS_ENTER_SLEEP_MODE,
+ 0, 0, true);
+ if (err) {
+ DRM_ERROR("DCS 0x%x sent failed\n",
+ DCS_ENTER_SLEEP_MODE);
+ goto power_err;
+ }
+ }
+
+power_err:
+ return err;
+}
+
+/**
+ * Enter DSR
+ */
+void mdfld_dsi_dbi_enter_dsr (struct mdfld_dsi_dbi_output * dbi_output, int pipe)
+{
+ u32 reg_val;
+ struct drm_device * dev = dbi_output->dev;
+ struct drm_psb_private * dev_priv = dev->dev_private;
+ struct drm_crtc * crtc = dbi_output->base.base.crtc;
+ struct psb_intel_crtc * psb_crtc = (crtc) ? to_psb_intel_crtc(crtc) : NULL;
+ u32 dpll_reg = MRST_DPLL_A;
+ u32 pipeconf_reg = PIPEACONF;
+ u32 dspcntr_reg = DSPACNTR;
+ u32 dspbase_reg = DSPABASE;
+ u32 dspsurf_reg = DSPASURF;
+
+ PSB_DEBUG_ENTRY(" \n");
+
+ if(!dbi_output)
+ return;
+
+ gdbi_output = dbi_output;
+ if((dbi_output->mode_flags & MODE_SETTING_ON_GOING) ||
+ (psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING))
+ return;
+
+ if(pipe == 2) {
+ dpll_reg = MRST_DPLL_A;
+ pipeconf_reg = PIPECCONF;
+ dspcntr_reg = DSPCCNTR;
+ dspbase_reg = MDFLD_DSPCBASE;
+ dspsurf_reg = DSPCSURF;
+ }
+
+ if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) {
+ DRM_ERROR("hw begin failed\n");
+ return;
+ }
+
+ /*disable te interrupts. */
+ mdfld_disable_te(dev, pipe);
+
+ /*disable plane*/
+ reg_val = REG_READ(dspcntr_reg);
+ if(!(reg_val & DISPLAY_PLANE_ENABLE)) {
+ REG_WRITE(dspcntr_reg, reg_val & ~DISPLAY_PLANE_ENABLE);
+ REG_READ(dspcntr_reg);
+ }
+
+ /*disable pipe*/
+ reg_val = REG_READ(pipeconf_reg);
+ if(!(reg_val & DISPLAY_PLANE_ENABLE)) {
+ reg_val &= ~DISPLAY_PLANE_ENABLE;
+ reg_val |= (PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF);
+ REG_WRITE(pipeconf_reg, reg_val);
+ REG_READ(pipeconf_reg);
+ mdfldWaitForPipeDisable(dev, pipe);
+ }
+
+ /*disable DPLL*/
+ reg_val = REG_READ(dpll_reg);
+ if(!(reg_val & DPLL_VCO_ENABLE)) {
+ reg_val &= ~DPLL_VCO_ENABLE;
+ REG_WRITE(dpll_reg, reg_val);
+ REG_READ(dpll_reg);
+ udelay(500);
+ }
+
+ /*gate power of DSI DPLL*/
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+
+ /*update mode state to IN_DSR*/
+ dbi_output->mode_flags |= MODE_SETTING_IN_DSR;
+
+ if(pipe == 2){
+ enter_dsr = 1;
+#ifdef CONFIG_PM_RUNTIME
+ pm_schedule_suspend(&dev->pdev->dev, gfxrtdelay);
+#endif
+ }
+}
+
+#ifndef CONFIG_MDFLD_DSI_DPU
+static void mdfld_dbi_output_exit_dsr (struct mdfld_dsi_dbi_output * dbi_output, int pipe)
+{
+ struct drm_device * dev = dbi_output->dev;
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_crtc * crtc = dbi_output->base.base.crtc;
+ struct psb_intel_crtc * psb_crtc = (crtc) ? to_psb_intel_crtc(crtc) : NULL;
+ u32 reg_val;
+ u32 dpll_reg = MRST_DPLL_A;
+ u32 pipeconf_reg = PIPEACONF;
+ u32 dspcntr_reg = DSPACNTR;
+
+ /*if mode setting on-going, back off*/
+ if((dbi_output->mode_flags & MODE_SETTING_ON_GOING) ||
+ (psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING))
+ return;
+
+ if(pipe == 2) {
+ dpll_reg = MRST_DPLL_A;
+ pipeconf_reg = PIPECCONF;
+ dspcntr_reg = DSPCCNTR;
+ }
+
+ if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) {
+ DRM_ERROR("hw begin failed\n");
+ return;
+ }
+
+ /*enable DPLL*/
+ reg_val = REG_READ(dpll_reg);
+ if(!(reg_val & DPLL_VCO_ENABLE)) {
+
+ if(reg_val & MDFLD_PWR_GATE_EN) {
+ reg_val &= ~MDFLD_PWR_GATE_EN;
+ REG_WRITE(dpll_reg, reg_val);
+ REG_READ(dpll_reg);
+ udelay(500);
+ }
+
+ reg_val |= DPLL_VCO_ENABLE;
+ REG_WRITE(dpll_reg, reg_val);
+ REG_READ(dpll_reg);
+ udelay(500);
+
+ /*add timeout*/
+ while (!(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) {
+ cpu_relax();
+ }
+ }
+
+ /*enable pipe*/
+ reg_val = REG_READ(pipeconf_reg);
+ if(!(reg_val & PIPEACONF_ENABLE)) {
+ reg_val |= PIPEACONF_ENABLE;
+ REG_WRITE(pipeconf_reg, reg_val);
+ REG_READ(pipeconf_reg);
+ udelay(500);
+ mdfldWaitForPipeEnable(dev, pipe);
+ }
+
+ /*enable plane*/
+ reg_val = REG_READ(dspcntr_reg);
+ if(!(reg_val & DISPLAY_PLANE_ENABLE)) {
+ reg_val |= DISPLAY_PLANE_ENABLE;
+ REG_WRITE(dspcntr_reg, reg_val);
+ REG_READ(dspcntr_reg);
+ udelay(500);
+ }
+
+ /*enable TE interrupt on this pipe*/
+ mdfld_enable_te(dev, pipe);
+
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+
+ /*clean IN_DSR flag*/
+ dbi_output->mode_flags &= ~MODE_SETTING_IN_DSR;
+}
+
+/**
+ * Exit from DSR
+ */
+void mdfld_dsi_dbi_exit_dsr(struct drm_device *dev, u32 update_src)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct mdfld_dbi_dsr_info * dsr_info = dev_priv->dbi_dsr_info;
+ struct mdfld_dsi_dbi_output ** dbi_output;
+ int i;
+ int pipe;
+
+ PSB_DEBUG_ENTRY("\n");
+
+ dbi_output = dsr_info->dbi_outputs;
+
+#ifdef CONFIG_PM_RUNTIME
+ if(drm_psb_ospm && !enable_gfx_rtpm) {
+// pm_runtime_allow(&gpDrmDevice->pdev->dev);
+ schedule_delayed_work(&dev_priv->rtpm_work, 30 * 1000);
+ }
+#endif
+
+ /*for each output, exit dsr*/
+ for(i=0; i<dsr_info->dbi_output_num; i++) {
+ /*if panel has been turned off, skip*/
+ if (!dbi_output[i] || !dbi_output[i]->dbi_panel_on)
+ continue;
+
+ pipe = dbi_output[i]->channel_num ? 2 : 0;
+ enter_dsr = 0;
+ mdfld_dbi_output_exit_dsr(dbi_output[i], pipe);
+ }
+
+ dev_priv->dsr_fb_update |= update_src;
+}
+
+static bool mdfld_dbi_is_in_dsr(struct drm_device * dev)
+{
+ if(REG_READ(MRST_DPLL_A) & DPLL_VCO_ENABLE)
+ return false;
+ if((REG_READ(PIPEACONF) & PIPEACONF_ENABLE) ||
+ (REG_READ(PIPECCONF) & PIPEACONF_ENABLE))
+ return false;
+ if((REG_READ(DSPACNTR) & DISPLAY_PLANE_ENABLE) ||
+ (REG_READ(DSPCCNTR) & DISPLAY_PLANE_ENABLE))
+ return false;
+
+ return true;
+}
+
+/* Perodically update dbi panel */
+void mdfld_dbi_update_panel (struct drm_device *dev, int pipe)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info;
+ struct mdfld_dsi_dbi_output **dbi_outputs;
+ struct mdfld_dsi_dbi_output *dbi_output;
+ int i;
+ int can_enter_dsr = 0;
+ int enter_dsr = 0;
+ u32 damage_mask = 0;
+
+ dbi_outputs = dsr_info->dbi_outputs;
+ dbi_output = pipe ? dbi_outputs[1] : dbi_outputs[0];
+
+ if (!dbi_output)
+ return;
+
+ if (pipe == 0)
+ damage_mask = dev_priv->dsr_fb_update & MDFLD_DSR_DAMAGE_MASK_0;
+ else if (pipe == 2)
+ damage_mask = dev_priv->dsr_fb_update & MDFLD_DSR_DAMAGE_MASK_2;
+ else
+ return;
+
+ /*if FB is damaged and panel is on update on-panel FB*/
+ if (damage_mask && dbi_output->dbi_panel_on) {
+ dbi_output->dsr_fb_update_done = false;
+
+ if (dbi_output->p_funcs->update_fb)
+ dbi_output->p_funcs->update_fb(dbi_output, pipe);
+
+ if (dev_priv->b_dsr_enable && dbi_output->dsr_fb_update_done)
+ dev_priv->dsr_fb_update &= ~damage_mask;
+
+ /*clean IN_DSR flag*/
+ dbi_output->mode_flags &= ~MODE_SETTING_IN_DSR;
+
+ dbi_output->dsr_idle_count = 0;
+
+ } else {
+ dbi_output->dsr_idle_count++;
+ }
+
+ switch (dsr_info->dbi_output_num) {
+ case 1:
+ if (dbi_output->dsr_idle_count > MDFLD_DSR_MAX_IDLE_COUNT)
+ can_enter_dsr = 1;
+ break;
+ case 2:
+ if (dbi_outputs[0]->dsr_idle_count > MDFLD_DSR_MAX_IDLE_COUNT
+ && dbi_outputs[1]->dsr_idle_count > MDFLD_DSR_MAX_IDLE_COUNT)
+ can_enter_dsr = 1;
+ break;
+ default:
+ DRM_ERROR("Wrong DBI output number\n");
+ can_enter_dsr = 0;
+ }
+
+ /*try to enter DSR*/
+ if (can_enter_dsr) {
+ for(i=0; i<dsr_info->dbi_output_num; i++) {
+ if (!mdfld_dbi_is_in_dsr(dev) && dbi_outputs[i] &&
+ !(dbi_outputs[i]->mode_flags & MODE_SETTING_ON_GOING)) {
+ mdfld_dsi_dbi_enter_dsr(dbi_outputs[i],
+ dbi_outputs[i]->channel_num ? 2 : 0);
+#if 0
+ enter_dsr = 1;
+ printk(KERN_ALERT "%s: enter_dsr = 1 \n", __func__);
+#endif
+ }
+ }
+ /*schedule rpm suspend after gfxrtdelay*/
+#ifdef CONFIG_PM_RUNTIME
+ if(!dev_priv->rpm_enabled
+ || !enter_dsr
+ // || (REG_READ(HDMIB_CONTROL) & HDMIB_PORT_EN)
+ || pm_schedule_suspend(&dev->pdev->dev, gfxrtdelay))
+ PSB_DEBUG_ENTRY("Runtime PM schedule suspend failed, rpm %d\n", dev_priv->rpm_enabled);
+#endif
+ }
+}
+
+int mdfld_dbi_dsr_init(struct drm_device * dev)
+{
+ struct drm_psb_private * dev_priv = dev->dev_private;
+ struct mdfld_dbi_dsr_info * dsr_info = dev_priv->dbi_dsr_info;
+
+ if(!dsr_info || IS_ERR(dsr_info)) {
+ dsr_info = kzalloc(sizeof(struct mdfld_dbi_dsr_info), GFP_KERNEL);
+ if(!dsr_info) {
+ DRM_ERROR("No memory\n");
+ return -ENOMEM;
+ }
+
+ dev_priv->dbi_dsr_info = dsr_info;
+ }
+
+ PSB_DEBUG_ENTRY("successfully\n");
+
+ return 0;
+}
+
+void mdfld_dbi_dsr_exit(struct drm_device * dev)
+{
+ struct drm_psb_private * dev_priv = dev->dev_private;
+ struct mdfld_dbi_dsr_info * dsr_info = dev_priv->dbi_dsr_info;
+
+ if(!dsr_info) {
+ return;
+ }
+
+ /*free dsr info*/
+ kfree(dsr_info);
+
+ dev_priv->dbi_dsr_info = NULL;
+}
+#endif
+
+void mdfld_dsi_controller_dbi_init(struct mdfld_dsi_config * dsi_config, int pipe)
+{
+ struct drm_device * dev = dsi_config->dev;
+ int lane_count = dsi_config->lane_count;
+ u32 val = 0;
+
+ PSB_DEBUG_ENTRY("Init DBI interface on pipe %d...\n", pipe);
+
+ /*un-ready device*/
+ REG_WRITE(MIPI_DEVICE_READY_REG(pipe), 0x00000000);
+
+ /*init dsi adapter before kicking off*/
+ REG_WRITE(MIPI_CTRL_REG(pipe), 0x00000018);
+
+ /*TODO: figure out how to setup these registers*/
+ REG_WRITE(MIPI_DPHY_PARAM_REG(pipe), 0x150c3408);
+ REG_WRITE(MIPI_CLK_LANE_SWITCH_TIME_CNT_REG(pipe), 0x000a0014);
+ REG_WRITE(MIPI_DBI_BW_CTRL_REG(pipe), 0x00000400);
+ REG_WRITE(MIPI_DBI_FIFO_THROTTLE_REG(pipe), 0x00000001);
+ REG_WRITE(MIPI_HS_LS_DBI_ENABLE_REG(pipe), 0x00000000);
+
+ /*enable all interrupts*/
+ REG_WRITE(MIPI_INTR_EN_REG(pipe), 0xffffffff);
+ /*max value: 20 clock cycles of txclkesc*/
+ REG_WRITE(MIPI_TURN_AROUND_TIMEOUT_REG(pipe), 0x0000001f);
+ /*min 21 txclkesc, max: ffffh*/
+ REG_WRITE(MIPI_DEVICE_RESET_TIMER_REG(pipe), 0x0000ffff);
+ /*min: 7d0 max: 4e20*/
+ REG_WRITE(MIPI_INIT_COUNT_REG(pipe), 0x00000fa0);
+
+ /* set up max return packet size */
+ REG_WRITE(MIPI_MAX_RETURN_PACK_SIZE_REG(pipe),
+ MDFLD_DSI_MAX_RETURN_PACKET_SIZE);
+
+ /*set up func_prg*/
+ val |= lane_count;
+ val |= (dsi_config->channel_num << DSI_DBI_VIRT_CHANNEL_OFFSET);
+ val |= DSI_DBI_COLOR_FORMAT_OPTION2;
+ REG_WRITE(MIPI_DSI_FUNC_PRG_REG(pipe), val);
+
+ REG_WRITE(MIPI_HS_TX_TIMEOUT_REG(pipe), 0x3fffff);
+ REG_WRITE(MIPI_LP_RX_TIMEOUT_REG(pipe), 0xffff);
+
+ /*de-assert dbi_stall when half of DBI FIFO is empty*/
+ //REG_WRITE((MIPIA_DBI_FIFO_THROTTLE_REG + reg_offset), 0x00000000);
+
+ REG_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT_REG(pipe), 0x46);
+ REG_WRITE(MIPI_EOT_DISABLE_REG(pipe), 0x00000000);
+ REG_WRITE(MIPI_LP_BYTECLK_REG(pipe), 0x00000004);
+ REG_WRITE(MIPI_DEVICE_READY_REG(pipe), 0x00000001);
+}
+
+#if 0
+/*DBI encoder helper funcs*/
+static const struct drm_encoder_helper_funcs mdfld_dsi_dbi_helper_funcs = {
+ .dpms = mdfld_dsi_dbi_dpms,
+ .mode_fixup = mdfld_dsi_dbi_mode_fixup,
+ .prepare = mdfld_dsi_dbi_prepare,
+ .mode_set = mdfld_dsi_dbi_mode_set,
+ .commit = mdfld_dsi_dbi_commit,
+};
+
+/*DBI encoder funcs*/
+static const struct drm_encoder_funcs mdfld_dsi_dbi_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
+#endif
+
+/*
+ * Init DSI DBI encoder.
+ * Allocate an mdfld_dsi_encoder and attach it to given @dsi_connector
+ * return pointer of newly allocated DBI encoder, NULL on error
+ */
+struct mdfld_dsi_encoder * mdfld_dsi_dbi_init(struct drm_device * dev,
+ struct mdfld_dsi_connector * dsi_connector,
+ struct panel_funcs* p_funcs)
+{
+ struct drm_psb_private * dev_priv = (struct drm_psb_private *)dev->dev_private;
+ struct mdfld_dsi_dbi_output * dbi_output = NULL;
+ struct mdfld_dsi_config * dsi_config;
+ struct drm_connector * connector = NULL;
+ struct drm_encoder * encoder = NULL;
+ struct drm_display_mode * fixed_mode = NULL;
+ struct psb_gtt * pg = dev_priv ? (dev_priv->pg) : NULL;
+
+#ifdef CONFIG_MDFLD_DSI_DPU
+ struct mdfld_dbi_dpu_info * dpu_info = dev_priv ? (dev_priv->dbi_dpu_info) : NULL;
+#else
+ struct mdfld_dbi_dsr_info * dsr_info = dev_priv ? (dev_priv->dbi_dsr_info) : NULL;
+#endif
+ u32 data = 0;
+ int pipe;
+ int ret;
+
+ PSB_DEBUG_ENTRY("\n");
+
+ if (!pg || !dsi_connector || !p_funcs) {
+ DRM_ERROR("Invalid parameters\n");
+ return NULL;
+ }
+
+ dsi_config = mdfld_dsi_get_config(dsi_connector);
+ pipe = dsi_connector->pipe;
+
+ /*panel hard-reset*/
+ if (p_funcs->reset) {
+ ret = p_funcs->reset(pipe);
+ if (ret) {
+ DRM_ERROR("Panel %d hard-reset failed\n", pipe);
+ return NULL;
+ }
+ }
+
+ /*panel drvIC init*/
+ if (p_funcs->drv_ic_init)
+ p_funcs->drv_ic_init(dsi_config, pipe);
+
+ /*panel power mode detect*/
+ ret = mdfld_dsi_get_power_mode(dsi_config, &data, true);
+ if (ret) {
+ DRM_ERROR("Panel %d get power mode failed\n", pipe);
+
+ dsi_connector->status = connector_status_disconnected;
+ } else {
+ DRM_INFO("pipe %d power mode 0x%x\n", pipe, data);
+
+ dsi_connector->status = connector_status_connected;
+ }
+
+ /*TODO: get panel info from DDB*/
+
+ dbi_output = kzalloc(sizeof(struct mdfld_dsi_dbi_output), GFP_KERNEL);
+ if(!dbi_output) {
+ DRM_ERROR("No memory\n");
+ return NULL;
+ }
+
+ if(dsi_connector->pipe == 0) {
+ dbi_output->channel_num = 0;
+ dev_priv->dbi_output = dbi_output;
+ } else if (dsi_connector->pipe == 2) {
+ dbi_output->channel_num = 1;
+ dev_priv->dbi_output2 = dbi_output;
+ } else {
+ DRM_ERROR("only support 2 DSI outputs\n");
+ goto out_err1;
+ }
+
+ dbi_output->dev = dev;
+ dbi_output->p_funcs = p_funcs;
+
+ /*get fixed mode*/
+ fixed_mode = dsi_config->fixed_mode;
+
+ dbi_output->panel_fixed_mode = fixed_mode;
+
+ /*create drm encoder object*/
+ connector = &dsi_connector->base.base;
+ encoder = &dbi_output->base.base;
+ drm_encoder_init(dev,
+ encoder,
+ p_funcs->encoder_funcs,
+ DRM_MODE_ENCODER_LVDS);
+ drm_encoder_helper_add( encoder,
+ p_funcs->encoder_helper_funcs);
+
+ /*attach to given connector*/
+ drm_mode_connector_attach_encoder(connector, encoder);
+
+ /*set possible crtcs and clones*/
+ if(dsi_connector->pipe) {
+ encoder->possible_crtcs = (1 << 2);
+ encoder->possible_clones = (1 << 1);
+ } else {
+ encoder->possible_crtcs = (1 << 0);
+ encoder->possible_clones = (1 << 0);
+ }
+
+ dev_priv->dsr_fb_update = 0;
+ dev_priv->b_dsr_enable = false;
+
+ dbi_output->first_boot = true;
+ dbi_output->mode_flags = MODE_SETTING_IN_ENCODER;
+
+#ifdef CONFIG_MDFLD_DSI_DPU
+ /*add this output to dpu_info*/
+
+ if (dsi_connector->status == connector_status_connected) {
+ if (dsi_connector->pipe == 0)
+ dpu_info->dbi_outputs[0] = dbi_output;
+ else
+ dpu_info->dbi_outputs[1] = dbi_output;
+
+ dpu_info->dbi_output_num++;
+ }
+
+#else /*CONFIG_MDFLD_DSI_DPU*/
+ if (dsi_connector->status == connector_status_connected) {
+ /*add this output to dsr_info*/
+ if (dsi_connector->pipe == 0)
+ dsr_info->dbi_outputs[0] = dbi_output;
+ else
+ dsr_info->dbi_outputs[1] = dbi_output;
+
+ dsr_info->dbi_output_num++;
+ }
+#endif
+
+ PSB_DEBUG_ENTRY("successfully\n");
+
+ return &dbi_output->base;
+
+out_err1:
+ if(dbi_output) {
+ kfree(dbi_output);
+ }
+
+ return NULL;
+}
--- /dev/null
+/*
+ * Copyright © 2010 Intel 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 (including the next
+ * paragraph) 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.
+ *
+ * Authors:
+ * jim liu <jim.liu@intel.com>
+ * Jackie Li<yaodong.li@intel.com>
+ */
+
+#ifndef __MDFLD_DSI_DBI_H__
+#define __MDFLD_DSI_DBI_H__
+
+#include <linux/backlight.h>
+#include <linux/version.h>
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_edid.h>
+
+#include "psb_drv.h"
+#include "psb_intel_drv.h"
+#include "psb_intel_reg.h"
+#include "psb_powermgmt.h"
+
+#include "mdfld_dsi_output.h"
+#include "mdfld_output.h"
+
+/*
+ * DBI encoder which inherits from mdfld_dsi_encoder
+ */
+struct mdfld_dsi_dbi_output {
+ struct mdfld_dsi_encoder base;
+
+ struct drm_display_mode * panel_fixed_mode;
+
+ u8 last_cmd;
+
+ u8 lane_count;
+
+ u8 channel_num;
+
+ struct drm_device * dev;
+
+ /*backlight operations*/
+
+ u32 dsr_idle_count;
+ bool dsr_fb_update_done;
+
+ /*mode setting flags*/
+ u32 mode_flags;
+
+ /*panel status*/
+ bool dbi_panel_on;
+ bool first_boot;
+ struct panel_funcs* p_funcs;
+};
+
+#define MDFLD_DSI_DBI_OUTPUT(dsi_encoder) container_of(dsi_encoder, struct mdfld_dsi_dbi_output, base)
+
+struct mdfld_dbi_dsr_info {
+ int dbi_output_num;
+ struct mdfld_dsi_dbi_output * dbi_outputs[2];
+
+ u32 dsr_idle_count;
+};
+
+#define DBI_CB_TIMEOUT_COUNT 0xffff
+
+/*offsets*/
+#define CMD_MEM_ADDR_OFFSET 0
+
+#define CMD_DATA_SRC_SYSTEM_MEM 0
+#define CMD_DATA_SRC_PIPE 1
+
+static inline int mdfld_dsi_dbi_fifo_ready(struct mdfld_dsi_dbi_output * dbi_output)
+{
+ struct drm_device * dev = dbi_output->dev;
+ u32 retry = DBI_CB_TIMEOUT_COUNT;
+ int pipe = dbi_output->channel_num == 1 ? 2 : 0;
+ int ret = 0;
+
+ /*query the dbi fifo status*/
+ retry = DBI_CB_TIMEOUT_COUNT;
+ while(retry--) {
+ if (REG_READ(MIPI_GEN_FIFO_STAT_REG(pipe)) & BIT(27))
+ break;
+ }
+
+ if(!retry) {
+ DRM_ERROR("Timeout waiting for DBI FIFO empty\n");
+ ret = -EAGAIN;
+ }
+
+ return ret;
+}
+
+static inline int mdfld_dsi_dbi_cmd_sent(struct mdfld_dsi_dbi_output * dbi_output)
+{
+ struct drm_device * dev = dbi_output->dev;
+ u32 retry = DBI_CB_TIMEOUT_COUNT;
+ int pipe = dbi_output->channel_num == 1 ? 2 : 0;
+ int ret = 0;
+
+ /*query the command execution status*/
+ while(retry--) {
+ if (!(REG_READ(MIPI_CMD_ADD_REG(pipe)) & BIT(0)))
+ break;
+ }
+
+ if(!retry) {
+ DRM_ERROR("Timeout waiting for DBI Command status\n");
+ ret = -EAGAIN;
+ }
+
+ return ret;
+}
+
+static inline int mdfld_dsi_dbi_cb_ready(struct mdfld_dsi_dbi_output * dbi_output)
+{
+ int ret = 0;
+
+ /*query the command execution status*/
+ ret = mdfld_dsi_dbi_cmd_sent(dbi_output);
+ if(ret) {
+ DRM_ERROR("Perpheral is busy\n");
+ ret = -EAGAIN;
+ }
+ /*query the dbi fifo status*/
+ ret = mdfld_dsi_dbi_fifo_ready(dbi_output);
+ if(ret) {
+ DRM_ERROR("DBI FIFO is not empty\n");
+ ret = -EAGAIN;
+ }
+
+ return ret;
+}
+
+/*export functions*/
+extern void mdfld_dsi_dbi_output_init(struct drm_device * dev, struct psb_intel_mode_device * mode_dev, int pipe);
+extern void mdfld_dsi_dbi_exit_dsr (struct drm_device *dev, u32 update_src);
+extern void mdfld_dsi_dbi_enter_dsr (struct mdfld_dsi_dbi_output * dbi_output, int pipe);
+extern int mdfld_dbi_dsr_init(struct drm_device * dev);
+extern void mdfld_dbi_dsr_exit(struct drm_device * dev);
+extern struct mdfld_dsi_encoder * mdfld_dsi_dbi_init(struct drm_device * dev,
+ struct mdfld_dsi_connector * dsi_connector,
+ struct panel_funcs* p_funcs);
+extern int mdfld_dsi_dbi_update_area(struct mdfld_dsi_dbi_output * dbi_output, u16 x1, u16 y1, u16 x2, u16 y2);
+extern int mdfld_dsi_dbi_update_power(struct mdfld_dsi_dbi_output * dbi_output, int mode);
+extern void mdfld_dsi_controller_dbi_init(struct mdfld_dsi_config * dsi_config, int pipe);
+
+extern struct mdfld_dsi_dbi_output *gdbi_output;
+
+#endif /*__MDFLD_DSI_DBI_H__*/
--- /dev/null
+/*
+ * Copyright © 2010 Intel 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 (including the next
+ * paragraph) 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.
+ *
+ * Authors:
+ * jim liu <jim.liu@intel.com>
+ * Jackie Li<yaodong.li@intel.com>
+ */
+
+ #include "mdfld_dsi_dbi_dpu.h"
+ #include "mdfld_dsi_dbi.h"
+
+/**
+ * NOTE: all mdlfd_x_damage funcs should be called by holding dpu_update_lock
+ */
+static int mdfld_cursor_damage(struct mdfld_dbi_dpu_info * dpu_info,
+ mdfld_plane_t plane,
+ struct psb_drm_dpu_rect * damaged_rect)
+{
+ int x, y;
+ int new_x, new_y;
+ struct psb_drm_dpu_rect * rect;
+ struct psb_drm_dpu_rect * pipe_rect;
+ int cursor_size;
+ struct mdfld_cursor_info * cursor;
+ mdfld_plane_t fb_plane;
+
+ if(plane == MDFLD_CURSORA) {
+ cursor = &dpu_info->cursors[0];
+ x = dpu_info->cursors[0].x;
+ y = dpu_info->cursors[0].y;
+ cursor_size = dpu_info->cursors[0].size;
+ pipe_rect = &dpu_info->damage_pipea;
+ fb_plane = MDFLD_PLANEA;
+ } else {
+ cursor = &dpu_info->cursors[1];
+ x = dpu_info->cursors[1].x;
+ y = dpu_info->cursors[1].y;
+ cursor_size = dpu_info->cursors[1].size;
+ pipe_rect = &dpu_info->damage_pipec;
+ fb_plane = MDFLD_PLANEC;
+ }
+ new_x = damaged_rect->x;
+ new_y = damaged_rect->y;
+
+ if((x == new_x) && (y == new_y)) {
+ return 0;
+ }
+
+ rect = &dpu_info->damaged_rects[plane];
+
+ /*move to right*/
+ if(new_x >= x) {
+ if(new_y > y) {
+ rect->x = x;
+ rect->y = y;
+ rect->width = (new_x + cursor_size) - x;
+ rect->height = (new_y + cursor_size) - y;
+ goto cursor_out;
+ } else {
+ rect->x = x;
+ rect->y = new_y;
+ rect->width = (new_x + cursor_size) - x;
+ rect->height = (y - new_y);
+ goto cursor_out;
+ }
+ } else {
+ if(new_y > y) {
+ rect->x = new_x;
+ rect->y = y;
+ rect->width = (x + cursor_size) - new_x;
+ rect->height = new_y - y;
+ goto cursor_out;
+ } else {
+ rect->x = new_x;
+ rect->y = new_y;
+ rect->width = (x + cursor_size) - new_x;
+ rect->height = (y + cursor_size) - new_y;
+ }
+ }
+cursor_out:
+ if(new_x < 0) {
+ cursor->x = 0;
+ } else if (new_x > 864) {
+ cursor->x = 864;
+ } else {
+ cursor->x = new_x;
+ }
+
+ if(new_y < 0) {
+ cursor->y = 0;
+ } else if (new_y > 480) {
+ cursor->y = 480;
+ } else {
+ cursor->y = new_y;
+ }
+
+ /**
+ * FIXME: this is a workaround for cursor plane update, remove it later!
+ */
+ rect->x = 0;
+ rect->y = 0;
+ rect->width = 864;
+ rect->height = 480;
+
+ mdfld_check_boundary(dpu_info, rect);
+
+ mdfld_dpu_region_extent(pipe_rect, rect);
+
+ /*update pending status of dpu_info*/
+ dpu_info->pending |= (1 << plane);
+
+ /*update fb panel as well*/
+ dpu_info->pending |= (1 << fb_plane);
+
+ return 0;
+}
+
+static int mdfld_fb_damage(struct mdfld_dbi_dpu_info * dpu_info,
+ mdfld_plane_t plane,
+ struct psb_drm_dpu_rect * damaged_rect)
+{
+ struct psb_drm_dpu_rect * rect;
+
+ if(plane == MDFLD_PLANEA) {
+ rect = &dpu_info->damage_pipea;
+ } else {
+ rect = &dpu_info->damage_pipec;
+ }
+ mdfld_check_boundary(dpu_info, damaged_rect);
+
+ /*add fb damage area to this pipe*/
+ mdfld_dpu_region_extent(rect, damaged_rect);
+
+ /*update pending status of dpu_info*/
+ dpu_info->pending |= (1 << plane);
+ return 0;
+}
+
+/*do nothing here, right now*/
+static int mdfld_overlay_damage(struct mdfld_dbi_dpu_info * dpu_info,
+ mdfld_plane_t plane,
+ struct psb_drm_dpu_rect * damaged_rect)
+{
+ PSB_DEBUG_ENTRY("\n");
+
+ return 0;
+}
+
+int mdfld_dbi_dpu_report_damage(struct drm_device * dev,
+ mdfld_plane_t plane,
+ struct psb_drm_dpu_rect * rect)
+{
+ struct drm_psb_private * dev_priv = dev->dev_private;
+ struct mdfld_dbi_dpu_info * dpu_info = dev_priv->dbi_dpu_info;
+ int ret = 0;
+
+ /*request lock*/
+ spin_lock(&dpu_info->dpu_update_lock);
+
+ switch(plane) {
+ case MDFLD_PLANEA:
+ case MDFLD_PLANEC:
+ mdfld_fb_damage(dpu_info, plane, rect);
+ break;
+ case MDFLD_CURSORA:
+ case MDFLD_CURSORC:
+ mdfld_cursor_damage(dpu_info, plane, rect);
+ break;
+ case MDFLD_OVERLAYA:
+ case MDFLD_OVERLAYC:
+ mdfld_overlay_damage(dpu_info, plane, rect);
+ break;
+ default:
+ DRM_ERROR("Invalid plane type %d\n", plane);
+ ret = -EINVAL;
+ }
+
+ spin_unlock(&dpu_info->dpu_update_lock);
+ return ret;
+}
+
+int mdfld_dbi_dpu_report_fullscreen_damage(struct drm_device * dev)
+{
+ struct drm_psb_private * dev_priv;
+ struct mdfld_dbi_dpu_info * dpu_info;
+ struct mdfld_dsi_config * dsi_config;
+ struct psb_drm_dpu_rect rect;
+ int i;
+
+ if(!dev) {
+ DRM_ERROR("Invalid parameter\n");
+ return -EINVAL;
+ }
+
+ dev_priv = dev->dev_private;
+ dpu_info = dev_priv ? dev_priv->dbi_dpu_info : NULL;
+
+ if(!dpu_info) {
+ DRM_ERROR("No dpu info found\n");
+ return -EINVAL;
+ }
+
+ for(i=0; i<dpu_info->dbi_output_num; i++) {
+ dsi_config = dev_priv->dsi_configs[i];
+ if(dsi_config) {
+ rect.x = rect.y = 0;
+ rect.width = dsi_config->fixed_mode->hdisplay;
+ rect.height = dsi_config->fixed_mode->vdisplay;
+ mdfld_dbi_dpu_report_damage(dev,
+ i ? (MDFLD_PLANEC) : (MDFLD_PLANEA),
+ &rect);
+
+ }
+ }
+
+ /*exit DSR state*/
+ mdfld_dpu_exit_dsr(dev);
+
+ return 0;
+}
+
+
+int mdfld_dsi_dbi_dsr_off(struct drm_device * dev, struct psb_drm_dpu_rect * rect)
+{
+ struct drm_psb_private * dev_priv = dev->dev_private;
+ struct mdfld_dbi_dpu_info * dpu_info = dev_priv->dbi_dpu_info;
+
+ mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEA, rect);
+
+ /*if dual display mode*/
+ if(dpu_info->dbi_output_num == 2)
+ mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEC, rect);
+
+ /*force dsi to exit DSR mode*/
+ mdfld_dpu_exit_dsr(dev);
+
+ return 0;
+}
+
+static void mdfld_dpu_cursor_plane_flush(struct mdfld_dbi_dpu_info * dpu_info,
+ mdfld_plane_t plane)
+{
+ struct drm_device * dev = dpu_info->dev;
+ u32 curpos_reg = CURAPOS;
+ u32 curbase_reg = CURABASE;
+ u32 curcntr_reg = CURACNTR;
+ struct mdfld_cursor_info * cursor = &dpu_info->cursors[0];
+
+ if(plane == MDFLD_CURSORC) {
+ curpos_reg = CURCPOS;
+ curbase_reg = CURCBASE;
+ curcntr_reg = CURCCNTR;
+ cursor = &dpu_info->cursors[1];
+ }
+
+ REG_WRITE(curcntr_reg, REG_READ(curcntr_reg));
+ REG_WRITE(curpos_reg, (((cursor->x & CURSOR_POS_MASK) << CURSOR_X_SHIFT) | ((cursor->y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT)));
+ REG_WRITE(curbase_reg, REG_READ(curbase_reg));
+}
+
+static void mdfld_dpu_fb_plane_flush(struct mdfld_dbi_dpu_info * dpu_info,
+ mdfld_plane_t plane)
+{
+ u32 pipesrc_reg = PIPEASRC;
+ u32 dspsize_reg = DSPASIZE;
+ u32 dspoff_reg = DSPALINOFF;
+ u32 dspsurf_reg = DSPASURF;
+ u32 dspstride_reg = DSPASTRIDE;
+ u32 stride;
+ struct psb_drm_dpu_rect * rect = &dpu_info->damage_pipea;
+ struct drm_device * dev = dpu_info->dev;
+
+ if(plane == MDFLD_PLANEC) {
+ pipesrc_reg = PIPECSRC;
+ dspsize_reg = DSPCSIZE;
+ dspoff_reg = DSPCLINOFF;
+ dspsurf_reg = DSPCSURF;
+ dspstride_reg = DSPCSTRIDE;
+
+ rect = &dpu_info->damage_pipec;
+ }
+
+ stride = REG_READ(dspstride_reg);
+ /*FIXME: should I do the pipe src update here?*/
+ REG_WRITE(pipesrc_reg, ((rect->width -1) << 16) | (rect->height -1));
+ /*flush plane*/
+ REG_WRITE(dspsize_reg, ((rect->height-1) << 16) | (rect->width - 1));
+ REG_WRITE(dspoff_reg, ((rect->x * 4) + (rect->y * stride)));
+ REG_WRITE(dspsurf_reg, REG_READ(dspsurf_reg));
+
+ /**
+ * TODO: wait for flip finished and restore the pipesrc reg,
+ * or cursor will be show at a wrong position
+ */
+}
+
+static void mdfld_dpu_overlay_plane_flush(struct mdfld_dbi_dpu_info * dpu_info,
+ mdfld_plane_t plane)
+{
+ PSB_DEBUG_ENTRY("\n");
+}
+
+/**
+ * TODO: we are still in dbi normal mode now, will try to use partial mode later.
+ */
+static int mdfld_dbi_prepare_cb(struct mdfld_dsi_dbi_output * dbi_output,
+ struct mdfld_dbi_dpu_info * dpu_info, int pipe)
+{
+ u8 * cb_addr = (u8 *)dbi_output->dbi_cb_addr;
+ u32 * index;
+ struct psb_drm_dpu_rect * rect = pipe ? (&dpu_info->damage_pipec) : (&dpu_info->damage_pipea);
+
+ /*FIXME: lock command buffer, this may lead to a dead lock, we've already hold the dpu_update_lock*/
+ if(!spin_trylock(&dbi_output->cb_lock)) {
+ DRM_ERROR("lock command buffer failed, try again\n");
+ return -EAGAIN;
+ }
+
+ index = &dbi_output->cb_write;
+
+ if(*index) {
+ DRM_ERROR("DBI command buffer unclean\n");
+ return -EAGAIN;
+ }
+
+ /*column address*/
+ *(cb_addr + ((*index)++)) = set_column_address;
+ *(cb_addr + ((*index)++)) = rect->x >> 8;
+ *(cb_addr + ((*index)++)) = rect->x;
+ *(cb_addr + ((*index)++)) = (rect->x + rect->width -1) >> 8;
+ *(cb_addr + ((*index)++)) = (rect->x + rect->width -1);
+
+ *index = 8;
+
+ /*page address*/
+ *(cb_addr + ((*index)++)) = set_page_addr;
+ *(cb_addr + ((*index)++)) = rect->y >> 8;
+ *(cb_addr + ((*index)++)) = rect->y;
+ *(cb_addr + ((*index)++)) = (rect->y + rect->height - 1) >> 8;
+ *(cb_addr + ((*index)++)) = (rect->y + rect->height -1 );
+
+ *index = 16;
+
+ /*write memory*/
+ *(cb_addr + ((*index)++)) = write_mem_start;
+
+ return 0;
+}
+
+static int mdfld_dbi_flush_cb(struct mdfld_dsi_dbi_output * dbi_output, int pipe)
+{
+ u32 cmd_phy = dbi_output->dbi_cb_phy;
+ u32 * index = &dbi_output->cb_write;
+ struct drm_device * dev = dbi_output->dev;
+
+ if(*index == 0 || !dbi_output) {
+ return 0;
+ }
+
+ REG_WRITE(MIPI_CMD_LEN_REG(pipe), 0x010505);
+ REG_WRITE(MIPI_CMD_ADD_REG(pipe), cmd_phy | BIT(0) | BIT(1));
+
+ *index = 0;
+
+ /*FIXME: unlock command buffer*/
+ spin_unlock(&dbi_output->cb_lock);
+
+ return 0;
+}
+
+static int mdfld_dpu_update_pipe(struct mdfld_dsi_dbi_output * dbi_output,
+ struct mdfld_dbi_dpu_info * dpu_info, int pipe)
+{
+ struct drm_device * dev = dbi_output->dev;
+ struct drm_psb_private * dev_priv = dev->dev_private;
+ mdfld_plane_t cursor_plane = MDFLD_CURSORA;
+ mdfld_plane_t fb_plane = MDFLD_PLANEA;
+ mdfld_plane_t overlay_plane = MDFLD_OVERLAYA;
+ int ret = 0;
+ u32 plane_mask = MDFLD_PIPEA_PLANE_MASK;
+
+ /*damaged rects on this pipe*/
+ if(pipe) {
+ cursor_plane = MDFLD_CURSORC;
+ fb_plane = MDFLD_PLANEC;
+ overlay_plane = MDFLD_OVERLAYC;
+ plane_mask = MDFLD_PIPEC_PLANE_MASK;
+ }
+
+ /*update cursor which assigned to @pipe*/
+ if(dpu_info->pending & (1 << cursor_plane))
+ mdfld_dpu_cursor_plane_flush(dpu_info, cursor_plane);
+
+ /*update fb which assigned to @pipe*/
+ if(dpu_info->pending & (1 << fb_plane))
+ mdfld_dpu_fb_plane_flush(dpu_info, fb_plane);
+
+ /*TODO: update overlay*/
+ if(dpu_info->pending & (1 << overlay_plane))
+ mdfld_dpu_overlay_plane_flush(dpu_info, overlay_plane);
+
+ /*flush damage area to panel fb*/
+ if(dpu_info->pending & plane_mask) {
+ ret = mdfld_dbi_prepare_cb(dbi_output, dpu_info, pipe);
+
+ /**
+ * TODO: remove b_dsr_enable later,
+ * added it so that text console could boot smoothly
+ */
+ /*clean pending flags on this pipe*/
+ if(!ret && dev_priv->b_dsr_enable) {
+ dpu_info->pending &= ~plane_mask;
+
+ /*reset overlay pipe damage rect*/
+ mdfld_dpu_init_damage(dpu_info, pipe);
+ }
+ }
+
+ return ret;
+}
+
+static int mdfld_dpu_update_fb(struct drm_device * dev) {
+ struct drm_crtc * crtc;
+ struct psb_intel_crtc * psb_crtc;
+ struct mdfld_dsi_dbi_output ** dbi_output;
+ struct drm_psb_private * dev_priv = dev->dev_private;
+ struct mdfld_dbi_dpu_info * dpu_info = dev_priv->dbi_dpu_info;
+ bool pipe_updated[2];
+ unsigned long irq_flags;
+ u32 dpll_reg = MRST_DPLL_A;
+ u32 dspcntr_reg = DSPACNTR;
+ u32 pipeconf_reg = PIPEACONF;
+ u32 dsplinoff_reg = DSPALINOFF;
+ u32 dspsurf_reg = DSPASURF;
+ int pipe;
+ int i;
+ int ret;
+
+ dbi_output = dpu_info->dbi_outputs;
+ pipe_updated[0] = pipe_updated[1] = false;
+
+ if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, true))
+ return -EAGAIN;
+
+ /*try to prevent any new damage reports*/
+ if(!spin_trylock_irqsave(&dpu_info->dpu_update_lock, irq_flags)) {
+ return -EAGAIN;
+ }
+
+ for(i=0; i<dpu_info->dbi_output_num; i++) {
+ crtc = dbi_output[i]->base.base.crtc;
+ psb_crtc = (crtc) ? to_psb_intel_crtc(crtc) : NULL;
+
+ pipe = dbi_output[i]->channel_num ? 2 : 0;
+
+ if(pipe == 2) {
+ dspcntr_reg = DSPCCNTR;
+ pipeconf_reg = PIPECCONF;
+ dsplinoff_reg = DSPCLINOFF;
+ dspsurf_reg = DSPCSURF;
+ }
+
+ if (!(REG_READ(MIPI_GEN_FIFO_STAT_REG(pipe)) & BIT(27)) ||
+ !(REG_READ(dpll_reg) & DPLL_VCO_ENABLE) ||
+ !(REG_READ(dspcntr_reg) & DISPLAY_PLANE_ENABLE) ||
+ !(REG_READ(pipeconf_reg) & DISPLAY_PLANE_ENABLE)) {
+ PSB_DEBUG_ENTRY("DBI FIFO is busy, DSI %d state %x\n",
+ pipe,
+ REG_READ(MIPI_INTR_STAT_REG(pipe)));
+ continue;
+ }
+
+ /*if dbi output is in a exclusive state, pipe change won't be updated*/
+ if(dbi_output[i]->dbi_panel_on &&
+ !(dbi_output[i]->mode_flags & MODE_SETTING_ON_GOING) &&
+ !(psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING) &&
+ !(dbi_output[i]->mode_flags & MODE_SETTING_IN_DSR)) {
+ ret = mdfld_dpu_update_pipe(dbi_output[i], dpu_info, dbi_output[i]->channel_num ? 2 : 0);
+ if(!ret) {
+ pipe_updated[i] = true;
+ }
+ }
+ }
+
+ for(i=0; i<dpu_info->dbi_output_num; i++) {
+ if(pipe_updated[i]) {
+ mdfld_dbi_flush_cb(dbi_output[i], dbi_output[i]->channel_num ? 2 : 0);
+ }
+ }
+
+ spin_unlock_irqrestore(&dpu_info->dpu_update_lock, irq_flags);
+
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+
+ return 0;
+}
+
+static int __mdfld_dbi_exit_dsr(struct mdfld_dsi_dbi_output * dbi_output, int pipe)
+{
+ struct drm_device * dev = dbi_output->dev;
+ struct drm_crtc * crtc = dbi_output->base.base.crtc;
+ struct psb_intel_crtc * psb_crtc = (crtc) ? to_psb_intel_crtc(crtc) : NULL;
+ u32 reg_val;
+ u32 dpll_reg = MRST_DPLL_A;
+ u32 pipeconf_reg = PIPEACONF;
+ u32 dspcntr_reg = DSPACNTR;
+ u32 dspbase_reg = DSPABASE;
+ u32 dspsurf_reg = DSPASURF;
+
+ PSB_DEBUG_ENTRY("\n");
+
+ if(!dbi_output) {
+ return 0;
+ }
+
+ /*if mode setting on-going, back off*/
+ if((dbi_output->mode_flags & MODE_SETTING_ON_GOING) ||
+ (psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING))
+ return -EAGAIN;
+
+ if(pipe == 2) {
+ dpll_reg = MRST_DPLL_A;
+ pipeconf_reg = PIPECCONF;
+ dspcntr_reg = DSPCCNTR;
+ dspbase_reg = MDFLD_DSPCBASE;
+ dspsurf_reg = DSPCSURF;
+ }
+
+ if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, true))
+ return -EAGAIN;
+
+ /*enable DPLL*/
+ reg_val = REG_READ(dpll_reg);
+ if(!(reg_val & DPLL_VCO_ENABLE)) {
+
+ if(reg_val & MDFLD_PWR_GATE_EN) {
+ reg_val &= ~MDFLD_PWR_GATE_EN;
+ REG_WRITE(dpll_reg, reg_val);
+ REG_READ(dpll_reg);
+ udelay(500);
+ }
+
+ reg_val |= DPLL_VCO_ENABLE;
+ REG_WRITE(dpll_reg, reg_val);
+ REG_READ(dpll_reg);
+ udelay(500);
+
+ /*FIXME: add timeout*/
+ while (!(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK));
+ }
+
+ /*enable pipe*/
+ reg_val = REG_READ(pipeconf_reg);
+ if(!(reg_val & PIPEACONF_ENABLE)) {
+ reg_val |= PIPEACONF_ENABLE;
+ REG_WRITE(pipeconf_reg, reg_val);
+ REG_READ(pipeconf_reg);
+ udelay(500);
+ mdfldWaitForPipeEnable(dev, pipe);
+ }
+
+ /*enable plane*/
+ reg_val = REG_READ(dspcntr_reg);
+ if(!(reg_val & DISPLAY_PLANE_ENABLE)) {
+ reg_val |= DISPLAY_PLANE_ENABLE;
+ REG_WRITE(dspcntr_reg, reg_val);
+ REG_READ(dspcntr_reg);
+ udelay(500);
+ }
+
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+
+ /*clean IN_DSR flag*/
+ dbi_output->mode_flags &= ~MODE_SETTING_IN_DSR;
+
+ return 0;
+}
+
+int mdfld_dpu_exit_dsr(struct drm_device * dev)
+{
+ struct mdfld_dsi_dbi_output ** dbi_output;
+ struct drm_psb_private * dev_priv = dev->dev_private;
+ struct mdfld_dbi_dpu_info * dpu_info = dev_priv->dbi_dpu_info;
+ int i;
+ int pipe;
+
+ dbi_output = dpu_info->dbi_outputs;
+
+ for(i=0; i<dpu_info->dbi_output_num; i++) {
+ /*if this output is not in DSR mode, don't call exit dsr*/
+ if(dbi_output[i]->mode_flags & MODE_SETTING_IN_DSR) {
+ __mdfld_dbi_exit_dsr(dbi_output[i], dbi_output[i]->channel_num ? 2 : 0);
+ }
+ }
+
+ /*enable te interrupt*/
+ for (i = 0; i < dpu_info->dbi_output_num; i++) {
+ /*if this output is not in DSR mode, don't call exit dsr*/
+ pipe = dbi_output[i]->channel_num ? 2 : 0;
+ if (dbi_output[i]->dbi_panel_on && pipe) {
+ mdfld_disable_te(dev, 0);
+ mdfld_enable_te(dev, 2);
+ } else if (dbi_output[i]->dbi_panel_on && !pipe) {
+ mdfld_disable_te(dev, 2);
+ mdfld_enable_te(dev, 0);
+ }
+ }
+
+ return 0;
+
+}
+
+static int mdfld_dpu_enter_dsr(struct drm_device * dev)
+{
+ struct drm_psb_private * dev_priv = dev->dev_private;
+ struct mdfld_dbi_dpu_info * dpu_info = dev_priv->dbi_dpu_info;
+ struct mdfld_dsi_dbi_output ** dbi_output;
+ int i;
+
+ PSB_DEBUG_ENTRY("\n");
+
+ dbi_output = dpu_info->dbi_outputs;
+
+ for(i=0; i<dpu_info->dbi_output_num; i++) {
+ /*if output is off or already in DSR state, don't enter again*/
+ if(dbi_output[i]->dbi_panel_on &&
+ !(dbi_output[i]->mode_flags & MODE_SETTING_IN_DSR)) {
+ mdfld_dsi_dbi_enter_dsr(dbi_output[i], dbi_output[i]->channel_num ? 2 : 0);
+ }
+ }
+
+ return 0;
+}
+
+static void mdfld_dbi_dpu_timer_func(unsigned long data)
+{
+ struct drm_device * dev = (struct drm_device *)data;
+ struct drm_psb_private * dev_priv = dev->dev_private;
+ struct mdfld_dbi_dpu_info * dpu_info = dev_priv->dbi_dpu_info;
+ struct timer_list * dpu_timer = &dpu_info->dpu_timer;
+ unsigned long flags;
+
+ if(dpu_info->pending) {
+ dpu_info->idle_count = 0;
+
+ /*update panel fb with damaged area*/
+ mdfld_dpu_update_fb(dev);
+ } else {
+ dpu_info->idle_count++;
+ }
+
+ if(dpu_info->idle_count >= MDFLD_MAX_IDLE_COUNT) {
+ /*enter dsr*/
+ mdfld_dpu_enter_dsr(dev);
+
+ /*stop timer by return*/
+ return;
+ }
+
+ spin_lock_irqsave(&dpu_info->dpu_timer_lock, flags);
+ if(!timer_pending(dpu_timer)){
+ dpu_timer->expires = jiffies + MDFLD_DSR_DELAY;
+ add_timer(dpu_timer);
+ }
+ spin_unlock_irqrestore(&dpu_info->dpu_timer_lock, flags);
+}
+
+void mdfld_dpu_update_panel(struct drm_device * dev)
+{
+ struct drm_psb_private * dev_priv = dev->dev_private;
+ struct mdfld_dbi_dpu_info * dpu_info = dev_priv->dbi_dpu_info;
+
+ if(dpu_info->pending) {
+ dpu_info->idle_count = 0;
+
+ /*update panel fb with damaged area*/
+ mdfld_dpu_update_fb(dev);
+ } else {
+ dpu_info->idle_count++;
+ }
+
+ if(dpu_info->idle_count >= MDFLD_MAX_IDLE_COUNT) {
+ /*enter dsr*/
+ mdfld_dpu_enter_dsr(dev);
+ }
+}
+
+static int mdfld_dbi_dpu_timer_init(struct drm_device * dev, struct mdfld_dbi_dpu_info * dpu_info)
+{
+ struct timer_list * dpu_timer = &dpu_info->dpu_timer;
+ unsigned long flags;
+
+ PSB_DEBUG_ENTRY("\n");
+
+ spin_lock_init(&dpu_info->dpu_timer_lock);
+ spin_lock_irqsave(&dpu_info->dpu_timer_lock, flags);
+
+ init_timer(dpu_timer);
+
+ dpu_timer->data = (unsigned long)dev;
+ dpu_timer->function = mdfld_dbi_dpu_timer_func;
+ dpu_timer->expires = jiffies + MDFLD_DSR_DELAY;
+
+ spin_unlock_irqrestore(&dpu_info->dpu_timer_lock, flags);
+
+ PSB_DEBUG_ENTRY("successfully\n");
+
+ return 0;
+}
+
+int mdfld_dbi_dpu_init(struct drm_device * dev)
+{
+ struct drm_psb_private * dev_priv = dev->dev_private;
+ struct mdfld_dbi_dpu_info * dpu_info = dev_priv->dbi_dpu_info;
+
+ if(!dpu_info || IS_ERR(dpu_info)) {
+ dpu_info = kzalloc(sizeof(struct mdfld_dbi_dpu_info), GFP_KERNEL);
+ if(!dpu_info) {
+ DRM_ERROR("No memory\n");
+ return -ENOMEM;
+ }
+
+ dev_priv->dbi_dpu_info = dpu_info;
+ }
+
+ dpu_info->dev = dev;
+
+ dpu_info->cursors[0].size = MDFLD_CURSOR_SIZE;
+ dpu_info->cursors[1].size = MDFLD_CURSOR_SIZE;
+
+ /*init dpu_update_lock*/
+ spin_lock_init(&dpu_info->dpu_update_lock);
+
+ /*init dpu refresh timer*/
+ mdfld_dbi_dpu_timer_init(dev, dpu_info);
+
+ /*init pipe damage area*/
+ mdfld_dpu_init_damage(dpu_info, 0);
+ mdfld_dpu_init_damage(dpu_info, 2);
+
+ PSB_DEBUG_ENTRY("successfully\n");
+
+ return 0;
+}
+
+void mdfld_dbi_dpu_exit(struct drm_device * dev)
+{
+ struct drm_psb_private * dev_priv = dev->dev_private;
+ struct mdfld_dbi_dpu_info * dpu_info = dev_priv->dbi_dpu_info;
+
+ if(!dpu_info) {
+ return;
+ }
+
+ /*delete dpu timer*/
+ del_timer_sync(&dpu_info->dpu_timer);
+
+ /*free dpu info*/
+ kfree(dpu_info);
+
+ dev_priv->dbi_dpu_info = NULL;
+}
+
+
--- /dev/null
+/*
+ * Copyright © 2010 Intel 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 (including the next
+ * paragraph) 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.
+ *
+ * Authors:
+ * jim liu <jim.liu@intel.com>
+ * Jackie Li<yaodong.li@intel.com>
+ */
+
+#ifndef __MDFLD_DSI_DBI_DPU_H__
+#define __MDFLD_DSI_DBI_DPU_H__
+
+#include "mdfld_dsi_dbi.h"
+
+typedef enum {
+ MDFLD_PLANEA,
+ MDFLD_PLANEC,
+ MDFLD_CURSORA,
+ MDFLD_CURSORC,
+ MDFLD_OVERLAYA,
+ MDFLD_OVERLAYC,
+ MDFLD_PLANE_NUM,
+} mdfld_plane_t;
+
+#define MDFLD_PIPEA_PLANE_MASK 0x15
+#define MDFLD_PIPEC_PLANE_MASK 0x2A
+
+struct mdfld_cursor_info {
+ int x, y;
+ int size;
+};
+
+#define MDFLD_CURSOR_SIZE 64
+
+/**
+ * enter DSR mode if screen has no update for 2 frames.
+ * TODO: export this as a configuration variable.
+ * (or what's the PRD for this?)
+ */
+#define MDFLD_MAX_IDLE_COUNT 2
+
+struct mdfld_dbi_dpu_info {
+ struct drm_device * dev;
+ /*lock*/
+ spinlock_t dpu_update_lock;
+
+ /*cursor postion*/
+ struct mdfld_cursor_info cursors[2];
+
+ /*damaged area for each plane*/
+ struct psb_drm_dpu_rect damaged_rects[MDFLD_PLANE_NUM];
+
+ /*final damaged area*/
+ struct psb_drm_dpu_rect damage_pipea;
+ struct psb_drm_dpu_rect damage_pipec;
+
+ /*pending*/
+ u32 pending;
+
+ /*dpu timer*/
+ struct timer_list dpu_timer;
+ spinlock_t dpu_timer_lock;
+
+ /*dpu idle count*/
+ u32 idle_count;
+
+ /*dsi outputs*/
+ struct mdfld_dsi_dbi_output * dbi_outputs[2];
+ int dbi_output_num;
+};
+
+static inline int mdfld_dpu_region_extent(struct psb_drm_dpu_rect * origin,
+ struct psb_drm_dpu_rect * rect)
+{
+ int x1, y1, x2, y2;
+
+ /*PSB_DEBUG_ENTRY("rect (%d, %d, %d, %d)\n", rect->x, rect->y, rect->width, rect->height);*/
+
+ x1 = origin->x + origin->width;
+ y1 = origin->y + origin->height;
+
+ x2 = rect->x + rect->width;
+ y2 = rect->y + rect->height;
+
+ origin->x = min(origin->x, rect->x);
+ origin->y = min(origin->y, rect->y);
+ origin->width = max(x1, x2) - origin->x;
+ origin->height = max(y1, y2) - origin->y;
+
+ return 0;
+}
+
+static inline void mdfld_check_boundary(struct mdfld_dbi_dpu_info * dpu_info,
+ struct psb_drm_dpu_rect * rect)
+{
+ if(rect->x < 0)
+ rect->x = 0;
+ if(rect->y < 0)
+ rect->y = 0;
+
+ if((rect->x + rect->width) > 864) {
+ rect->width = 864 - rect->x;
+ }
+
+ if((rect->y + rect->height) > 480) {
+ rect->height = 480 - rect->height;
+ }
+
+ if(!rect->width)
+ rect->width = 1;
+ if(!rect->height)
+ rect->height = 1;
+}
+
+static inline void mdfld_dpu_init_damage(struct mdfld_dbi_dpu_info * dpu_info, int pipe) {
+ struct psb_drm_dpu_rect * rect;
+
+ if(pipe == 0) {
+ rect = &dpu_info->damage_pipea;
+ } else {
+ rect = &dpu_info->damage_pipec;
+ }
+
+ rect->x = 864;
+ rect->y = 480;
+ rect->width = -864;
+ rect->height = -480;
+}
+
+extern int mdfld_dsi_dbi_dsr_off(struct drm_device * dev, struct psb_drm_dpu_rect * rect);
+extern int mdfld_dbi_dpu_report_damage(struct drm_device * dev,
+ mdfld_plane_t plane,
+ struct psb_drm_dpu_rect * rect);
+extern int mdfld_dbi_dpu_report_fullscreen_damage(struct drm_device * dev);
+extern int mdfld_dpu_exit_dsr(struct drm_device * dev);
+extern int mdfld_dbi_dpu_init(struct drm_device * dev);
+extern void mdfld_dbi_dpu_exit(struct drm_device * dev);
+extern void mdfld_dpu_update_panel(struct drm_device * dev);
+
+#endif /*__MDFLD_DSI_DBI_DPU_H__*/
--- /dev/null
+/*
+ * Copyright © 2010 Intel 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 (including the next
+ * paragraph) 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.
+ *
+ * Authors:
+ * jim liu <jim.liu@intel.com>
+ * Jackie Li<yaodong.li@intel.com>
+ */
+
+#include "mdfld_dsi_dpi.h"
+#include "mdfld_output.h"
+#include "mdfld_dsi_pkg_sender.h"
+#include "psb_powermgmt.h"
+#include "psb_drv.h"
+#include "tc35876x-dsi-lvds.h"
+
+static void mdfld_dsi_dpi_shut_down(struct mdfld_dsi_dpi_output *output, int pipe);
+static bool dsi_device_ready = true; /* for TC35876X */
+
+static void mdfld_wait_for_HS_DATA_FIFO(struct drm_device *dev, u32 pipe)
+{
+ u32 gen_fifo_stat_reg = MIPI_GEN_FIFO_STAT_REG(pipe);
+ int timeout = 0;
+
+ udelay(500);
+
+ /* This will time out after approximately 2+ seconds */
+ while ((timeout < 20000) && (REG_READ(gen_fifo_stat_reg) & DSI_FIFO_GEN_HS_DATA_FULL)) {
+ udelay(100);
+ timeout++;
+ }
+
+ if (timeout == 20000)
+ DRM_INFO("MIPI: HS Data FIFO was never cleared!\n");
+}
+
+static void mdfld_wait_for_HS_CTRL_FIFO(struct drm_device *dev, u32 pipe)
+{
+ u32 gen_fifo_stat_reg = MIPI_GEN_FIFO_STAT_REG(pipe);
+ int timeout = 0;
+
+ udelay(500);
+
+ /* This will time out after approximately 2+ seconds */
+ while ((timeout < 20000) && (REG_READ(gen_fifo_stat_reg) & DSI_FIFO_GEN_HS_CTRL_FULL)) {
+ udelay(100);
+ timeout++;
+ }
+ if (timeout == 20000)
+ DRM_INFO("MIPI: HS CMD FIFO was never cleared!\n");
+}
+
+static void mdfld_wait_for_DPI_CTRL_FIFO(struct drm_device *dev, u32 pipe)
+{
+ u32 gen_fifo_stat_reg = MIPI_GEN_FIFO_STAT_REG(pipe);
+ int timeout = 0;
+
+ udelay(500);
+
+ /* This will time out after approximately 2+ seconds */
+ while ((timeout < 20000) && ((REG_READ(gen_fifo_stat_reg) & DPI_FIFO_EMPTY)
+ != DPI_FIFO_EMPTY)) {
+ udelay(100);
+ timeout++;
+ }
+
+ if (timeout == 20000)
+ DRM_INFO("MIPI: DPI FIFO was never cleared!\n");
+}
+
+static void mdfld_wait_for_SPL_PKG_SENT(struct drm_device *dev, u32 pipe)
+{
+ u32 intr_stat_reg = MIPI_INTR_STAT_REG(pipe);
+ int timeout = 0;
+
+ udelay(500);
+
+ /* This will time out after approximately 2+ seconds */
+ while ((timeout < 20000) && (!(REG_READ(intr_stat_reg) & DSI_INTR_STATE_SPL_PKG_SENT))) {
+ udelay(100);
+ timeout++;
+ }
+
+ if (timeout == 20000)
+ DRM_INFO("MIPI: SPL_PKT_SENT_INTERRUPT was not sent successfully!\n");
+}
+
+/* For TC35876X */
+static void mdfld_wait_for_PIPEA_DISABLE(struct drm_device *dev, u32 pipe)
+{
+ u32 pipeconf_reg = PIPEACONF;
+ int timeout = 0;
+
+ if (pipe == 2)
+ pipeconf_reg = PIPECCONF;
+
+ udelay(500);
+
+ /* This will time out after approximately 2+ seconds */
+ while ((timeout < 20000) && (REG_READ(pipeconf_reg) & 0x40000000)) {
+ udelay(100);
+ timeout++;
+ }
+
+ if (timeout == 20000)
+ DRM_INFO("MIPI: PIPE was not disabled!\n");
+}
+
+static void dsi_set_device_ready_state(struct drm_device *dev, int state,
+ int pipe)
+{
+ printk(KERN_ALERT "[DISPLAY TRK] %s: state = %d, pipe = %d\n", __func__, state, pipe);
+
+ REG_WRITE(MIPI_DEVICE_READY_REG(pipe), state ? BIT(0) : 0);
+}
+
+static void dsi_set_pipe_plane_enable_state(struct drm_device *dev, int state, int pipe)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ u32 pipeconf_reg = PIPEACONF;
+ u32 dspcntr_reg = DSPACNTR;
+
+ u32 pipeconf = dev_priv->pipeconf;
+ u32 dspcntr = dev_priv->dspcntr;
+ u32 mipi = MIPI_PORT_EN | PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX;
+
+ printk(KERN_ALERT "[DISPLAY TRK] %s: state = %d, pipe = %d\n", __func__, state, pipe);
+
+ if (pipe) {
+ pipeconf_reg = PIPECCONF;
+ dspcntr_reg = DSPCCNTR;
+ } else {
+ mipi &= (~0x03);
+ }
+
+ if (state) {
+
+ /*Set up pipe */
+ REG_WRITE(pipeconf_reg, pipeconf);
+
+ /*Set up display plane */
+ REG_WRITE(dspcntr_reg, dspcntr);
+ } else {
+ /*Disable PIPE */
+ REG_WRITE(pipeconf_reg, 0);
+ mdfld_wait_for_PIPEA_DISABLE(dev, pipe);
+ mdfld_wait_for_DPI_CTRL_FIFO(dev, pipe);
+
+ }
+}
+
+static void mdfld_dsi_configure_down(struct mdfld_dsi_encoder * dsi_encoder, int pipe)
+{
+ struct mdfld_dsi_dpi_output * dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_encoder);
+ struct mdfld_dsi_config * dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder);
+ struct drm_device * dev = dsi_config->dev;
+ struct drm_psb_private * dev_priv = dev->dev_private;
+
+ printk(KERN_ALERT "[DISPLAY TRK] Enter %s\n", __func__);
+
+ if (!dev_priv->dpi_panel_on) {
+ printk(KERN_ALERT "[DISPLAY] %s: DPI Panel is Already Off\n", __func__);
+ return;
+ }
+ tc35876x_set_bridge_reset_state(1);
+ dsi_set_pipe_plane_enable_state(dev, 0, pipe); //Disable pipe and plane
+
+ mdfld_dsi_dpi_shut_down(dpi_output, pipe); //Send shut down command
+
+ dsi_set_device_ready_state(dev, 0, pipe); //Clear device ready state
+
+ dev_priv->dpi_panel_on = false;
+}
+
+static void mdfld_dsi_configure_up(struct mdfld_dsi_encoder * dsi_encoder, int pipe)
+{
+ struct mdfld_dsi_dpi_output * dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_encoder);
+ struct mdfld_dsi_config * dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder);
+ struct drm_device * dev = dsi_config->dev;
+ struct drm_psb_private * dev_priv = dev->dev_private;
+
+ printk(KERN_ALERT "[DISPLAY TRK] Enter %s\n", __func__);
+
+ if (dev_priv->dpi_panel_on) {
+ printk(KERN_ALERT "[DISPLAY] %s: DPI Panel is Already On\n", __func__);
+ return;
+ }
+
+ /* For resume path sequence */
+ mdfld_dsi_dpi_shut_down(dpi_output, pipe);
+ dsi_set_device_ready_state(dev, 0, pipe); //Clear Device Ready Bit
+
+ dsi_set_device_ready_state(dev, 1, pipe); //Set device ready state
+ tc35876x_set_bridge_reset_state(0);
+ tc35876x_configure_lvds_bridge(dev);
+ mdfld_dsi_dpi_turn_on(dpi_output, pipe); //Send turn on command
+ dsi_set_pipe_plane_enable_state(dev, 1, pipe); //Enable plane and pipe
+
+ dev_priv->dpi_panel_on = true;
+}
+/* End for TC35876X */
+
+/* ************************************************************************* *\
+ * FUNCTION: mdfld_dsi_tpo_ic_init
+ *
+ * DESCRIPTION: This function is called only by mrst_dsi_mode_set and
+ * restore_display_registers. since this function does not
+ * acquire the mutex, it is important that the calling function
+ * does!
+\* ************************************************************************* */
+static void mdfld_dsi_tpo_ic_init(struct mdfld_dsi_config * dsi_config, u32 pipe)
+{
+ struct drm_device * dev = dsi_config->dev;
+ u32 dcsChannelNumber = dsi_config->channel_num;
+ u32 gen_data_reg = MIPI_HS_GEN_DATA_REG(pipe);
+ u32 gen_ctrl_reg = MIPI_HS_GEN_CTRL_REG(pipe);
+ u32 gen_ctrl_val = GEN_LONG_WRITE;
+
+ DRM_INFO("Enter mrst init TPO MIPI display.\n");
+
+ gen_ctrl_val |= dcsChannelNumber << DCS_CHANNEL_NUMBER_POS;
+
+ /* Flip page order */
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x00008036);
+ mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+ REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x02 << WORD_COUNTS_POS));
+
+ /* 0xF0 */
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x005a5af0);
+ mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+ REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
+
+ /* Write protection key */
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x005a5af1);
+ mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+ REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
+
+ /* 0xFC */
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x005a5afc);
+ mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+ REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
+
+ /* 0xB7 */
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x770000b7);
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x00000044);
+ mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+ REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x05 << WORD_COUNTS_POS));
+
+ /* 0xB6 */
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x000a0ab6);
+ mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+ REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
+
+ /* 0xF2 */
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x081010f2);
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x4a070708);
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x000000c5);
+ mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+ REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS));
+
+ /* 0xF8 */
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x024003f8);
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x01030a04);
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x0e020220);
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x00000004);
+ mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+ REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x0d << WORD_COUNTS_POS));
+
+ /* 0xE2 */
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x398fc3e2);
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x0000916f);
+ mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+ REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x06 << WORD_COUNTS_POS));
+
+ /* 0xB0 */
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x000000b0);
+ mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+ REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x02 << WORD_COUNTS_POS));
+
+ /* 0xF4 */
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x240242f4);
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x78ee2002);
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x2a071050);
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x507fee10);
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x10300710);
+ mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+ REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x14 << WORD_COUNTS_POS));
+
+ /* 0xBA */
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x19fe07ba);
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x101c0a31);
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x00000010);
+ mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+ REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS));
+
+ /* 0xBB */
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x28ff07bb);
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x24280a31);
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x00000034);
+ mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+ REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS));
+
+ /* 0xFB */
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x535d05fb);
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x1b1a2130);
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x221e180e);
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x131d2120);
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x535d0508);
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x1c1a2131);
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x231f160d);
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x111b2220);
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x535c2008);
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x1f1d2433);
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x2c251a10);
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x2c34372d);
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x00000023);
+ mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+ REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x31 << WORD_COUNTS_POS));
+
+ /* 0xFA */
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x525c0bfa);
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x1c1c232f);
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x2623190e);
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x18212625);
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x545d0d0e);
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x1e1d2333);
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x26231a10);
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x1a222725);
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x545d280f);
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x21202635);
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x31292013);
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x31393d33);
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x00000029);
+ mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+ REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x31 << WORD_COUNTS_POS));
+
+ /* Set DM */
+ mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+ REG_WRITE(gen_data_reg, 0x000100f7);
+ mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+ REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
+}
+
+static u16 mdfld_dsi_dpi_to_byte_clock_count(int pixel_clock_count, int num_lane, int bpp)
+{
+ return (u16)((pixel_clock_count * bpp) / (num_lane * 8));
+}
+
+/*
+ * Calculate the dpi time basing on a given drm mode @mode
+ * return 0 on success.
+ * FIXME: I was using proposed mode value for calculation, may need to
+ * use crtc mode values later
+ */
+int mdfld_dsi_dpi_timing_calculation(struct drm_display_mode * mode,
+ struct mdfld_dsi_dpi_timing * dpi_timing,
+ int num_lane, int bpp)
+{
+ int pclk_hsync, pclk_hfp, pclk_hbp, pclk_hactive;
+ int pclk_vsync, pclk_vfp, pclk_vbp, pclk_vactive;
+
+ if(!mode || !dpi_timing) {
+ DRM_ERROR("Invalid parameter\n");
+ return -EINVAL;
+ }
+
+ PSB_DEBUG_ENTRY("pclk %d, hdisplay %d, hsync_start %d, hsync_end %d, htotal %d\n",
+ mode->clock, mode->hdisplay, mode->hsync_start,
+ mode->hsync_end, mode->htotal);
+ PSB_DEBUG_ENTRY("vdisplay %d, vsync_start %d, vsync_end %d, vtotal %d\n",
+ mode->vdisplay, mode->vsync_start,
+ mode->vsync_end, mode->vtotal);
+
+ pclk_hactive = mode->hdisplay;
+ pclk_hfp = mode->hsync_start - mode->hdisplay;
+ pclk_hsync = mode->hsync_end - mode->hsync_start;
+ pclk_hbp = mode->htotal - mode->hsync_end;
+
+ pclk_vactive = mode->vdisplay;
+ pclk_vfp = mode->vsync_start - mode->vdisplay;
+ pclk_vsync = mode->vsync_end - mode->vsync_start;
+ pclk_vbp = mode->vtotal - mode->vsync_end;
+
+ /*
+ * byte clock counts were calculated by following formula
+ * bclock_count = pclk_count * bpp / num_lane / 8
+ */
+ dpi_timing->hsync_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_hsync, num_lane, bpp);
+ dpi_timing->hbp_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_hbp, num_lane, bpp);
+ dpi_timing->hfp_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_hfp, num_lane, bpp);
+ dpi_timing->hactive_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_hactive, num_lane, bpp);
+ dpi_timing->vsync_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_vsync, num_lane, bpp);
+ dpi_timing->vbp_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_vbp, num_lane, bpp);
+ dpi_timing->vfp_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_vfp, num_lane, bpp);
+
+ PSB_DEBUG_ENTRY("DPI timings: %d, %d, %d, %d, %d, %d, %d\n",
+ dpi_timing->hsync_count, dpi_timing->hbp_count,
+ dpi_timing->hfp_count, dpi_timing->hactive_count,
+ dpi_timing->vsync_count, dpi_timing->vbp_count,
+ dpi_timing->vfp_count);
+
+ return 0;
+}
+
+void mdfld_dsi_dpi_controller_init(struct mdfld_dsi_config * dsi_config, int pipe)
+{
+ struct drm_device * dev = dsi_config->dev;
+ int lane_count = dsi_config->lane_count;
+ struct mdfld_dsi_dpi_timing dpi_timing;
+ struct drm_display_mode * mode = dsi_config->mode;
+ u32 val = 0;
+
+ PSB_DEBUG_ENTRY("Init DPI interface on pipe %d...\n", pipe);
+
+ /*un-ready device*/
+ REG_WRITE(MIPI_DEVICE_READY_REG(pipe), 0x00000000);
+
+ /*init dsi adapter before kicking off*/
+ REG_WRITE(MIPI_CTRL_REG(pipe), 0x00000018);
+
+ /*enable all interrupts*/
+ REG_WRITE(MIPI_INTR_EN_REG(pipe), 0xffffffff);
+
+ /*set up func_prg*/
+ val |= lane_count;
+ val |= dsi_config->channel_num << DSI_DPI_VIRT_CHANNEL_OFFSET;
+
+ switch(dsi_config->bpp) {
+ case 16:
+ val |= DSI_DPI_COLOR_FORMAT_RGB565;
+ break;
+ case 18:
+ val |= DSI_DPI_COLOR_FORMAT_RGB666;
+ break;
+ case 24:
+ val |= DSI_DPI_COLOR_FORMAT_RGB888;
+ break;
+ default:
+ DRM_ERROR("unsupported color format, bpp = %d\n", dsi_config->bpp);
+ }
+ REG_WRITE(MIPI_DSI_FUNC_PRG_REG(pipe), val);
+
+ REG_WRITE(MIPI_HS_TX_TIMEOUT_REG(pipe),
+ (mode->vtotal * mode->htotal * dsi_config->bpp / (8 * lane_count)) & DSI_HS_TX_TIMEOUT_MASK);
+ REG_WRITE(MIPI_LP_RX_TIMEOUT_REG(pipe), 0xffff & DSI_LP_RX_TIMEOUT_MASK);
+
+ /*max value: 20 clock cycles of txclkesc*/
+ REG_WRITE(MIPI_TURN_AROUND_TIMEOUT_REG(pipe), 0x14 & DSI_TURN_AROUND_TIMEOUT_MASK);
+
+ /*min 21 txclkesc, max: ffffh*/
+ REG_WRITE(MIPI_DEVICE_RESET_TIMER_REG(pipe), 0xffff & DSI_RESET_TIMER_MASK);
+
+ REG_WRITE(MIPI_DPI_RESOLUTION_REG(pipe), mode->vdisplay << 16 | mode->hdisplay);
+
+ /*set DPI timing registers*/
+ mdfld_dsi_dpi_timing_calculation(mode, &dpi_timing, dsi_config->lane_count, dsi_config->bpp);
+
+ REG_WRITE(MIPI_HSYNC_COUNT_REG(pipe), dpi_timing.hsync_count & DSI_DPI_TIMING_MASK);
+ REG_WRITE(MIPI_HBP_COUNT_REG(pipe), dpi_timing.hbp_count & DSI_DPI_TIMING_MASK);
+ REG_WRITE(MIPI_HFP_COUNT_REG(pipe), dpi_timing.hfp_count & DSI_DPI_TIMING_MASK);
+ REG_WRITE(MIPI_HACTIVE_COUNT_REG(pipe), dpi_timing.hactive_count & DSI_DPI_TIMING_MASK);
+ REG_WRITE(MIPI_VSYNC_COUNT_REG(pipe), dpi_timing.vsync_count & DSI_DPI_TIMING_MASK);
+ REG_WRITE(MIPI_VBP_COUNT_REG(pipe), dpi_timing.vbp_count & DSI_DPI_TIMING_MASK);
+ REG_WRITE(MIPI_VFP_COUNT_REG(pipe), dpi_timing.vfp_count & DSI_DPI_TIMING_MASK);
+
+ REG_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT_REG(pipe), 0x46);
+
+ /*min: 7d0 max: 4e20*/
+ REG_WRITE(MIPI_INIT_COUNT_REG(pipe), 0x000007d0);
+
+ /*set up video mode*/
+ val = 0;
+ val = dsi_config->video_mode | DSI_DPI_COMPLETE_LAST_LINE;
+ REG_WRITE(MIPI_VIDEO_MODE_FORMAT_REG(pipe), val);
+
+ REG_WRITE(MIPI_EOT_DISABLE_REG(pipe), 0x00000000);
+
+ REG_WRITE(MIPI_LP_BYTECLK_REG(pipe), 0x00000004);
+
+ /*TODO: figure out how to setup these registers*/
+ if (get_panel_type(dev, pipe) == TC35876X)
+ REG_WRITE(MIPI_DPHY_PARAM_REG(pipe), 0x2A0c6008);
+ else
+ REG_WRITE(MIPI_DPHY_PARAM_REG(pipe), 0x150c3408);
+
+ REG_WRITE(MIPI_CLK_LANE_SWITCH_TIME_CNT_REG(pipe), (0xa << 16) | 0x14);
+
+ if (get_panel_type(dev, pipe) == TC35876X)
+ tc35876x_set_bridge_reset_state(0); /*Pull High Reset */
+
+ /*set device ready*/
+ REG_WRITE(MIPI_DEVICE_READY_REG(pipe), 0x00000001);
+}
+
+void mdfld_dsi_dpi_turn_on(struct mdfld_dsi_dpi_output * output, int pipe)
+{
+ struct drm_device * dev = output->dev;
+ /* struct drm_psb_private * dev_priv = dev->dev_private; */
+
+ PSB_DEBUG_ENTRY("pipe %d panel state %d\n", pipe, output->panel_on);
+
+ if(output->panel_on)
+ return;
+
+ /* clear special packet sent bit */
+ if (REG_READ(MIPI_INTR_STAT_REG(pipe)) & DSI_INTR_STATE_SPL_PKG_SENT)
+ REG_WRITE(MIPI_INTR_STAT_REG(pipe), DSI_INTR_STATE_SPL_PKG_SENT);
+
+ /*send turn on package*/
+ REG_WRITE(MIPI_DPI_CONTROL_REG(pipe), DSI_DPI_CTRL_HS_TURN_ON);
+
+ /*wait for SPL_PKG_SENT interrupt*/
+ mdfld_wait_for_SPL_PKG_SENT(dev, pipe);
+
+ if (REG_READ(MIPI_INTR_STAT_REG(pipe)) & DSI_INTR_STATE_SPL_PKG_SENT)
+ REG_WRITE(MIPI_INTR_STAT_REG(pipe), DSI_INTR_STATE_SPL_PKG_SENT);
+
+ output->panel_on = 1;
+
+ /* FIXME the following is disabled to WA the X slow start issue for TMD panel */
+ /* if(pipe == 2) */
+ /* dev_priv->dpi_panel_on2 = true; */
+ /* else if (pipe == 0) */
+ /* dev_priv->dpi_panel_on = true; */
+}
+
+static void mdfld_dsi_dpi_shut_down(struct mdfld_dsi_dpi_output * output, int pipe)
+{
+ struct drm_device * dev = output->dev;
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ /* struct drm_psb_private * dev_priv = dev->dev_private; */
+
+ PSB_DEBUG_ENTRY("pipe %d panel state %d\n", pipe, output->panel_on);
+
+ /*if output is on, or mode setting didn't happen, ignore this*/
+ if((!output->panel_on) || output->first_boot) {
+ output->first_boot = 0;
+ return;
+ }
+
+ /* Wait for dpi fifo to empty */
+ mdfld_wait_for_DPI_CTRL_FIFO(dev, pipe);
+
+ /* Clear the special packet interrupt bit if set */
+ if (REG_READ(MIPI_INTR_STAT_REG(pipe)) & DSI_INTR_STATE_SPL_PKG_SENT)
+ REG_WRITE(MIPI_INTR_STAT_REG(pipe), DSI_INTR_STATE_SPL_PKG_SENT);
+
+ if (REG_READ(MIPI_DPI_CONTROL_REG(pipe)) == DSI_DPI_CTRL_HS_SHUTDOWN) {
+ PSB_DEBUG_ENTRY("try to send the same package again, abort!");
+ goto shutdown_out;
+ }
+
+ REG_WRITE(MIPI_DPI_CONTROL_REG(pipe), DSI_DPI_CTRL_HS_SHUTDOWN);
+
+shutdown_out:
+ output->panel_on = 0;
+ output->first_boot = 0;
+
+ /* FIXME the following is disabled to WA the X slow start issue for TMD panel */
+ /* if(pipe == 2) */
+ /* dev_priv->dpi_panel_on2 = false; */
+ /* else if (pipe == 0) */
+ /* dev_priv->dpi_panel_on = false; */
+
+#ifdef CONFIG_PM_RUNTIME
+ if (drm_psb_ospm && !enable_gfx_rtpm) {
+// pm_runtime_allow(&gpDrmDevice->pdev->dev);
+ schedule_delayed_work(&dev_priv->rtpm_work, 30 * 1000);
+ }
+
+ if (enable_gfx_rtpm)
+ pm_schedule_suspend(&dev->pdev->dev, gfxrtdelay);
+#endif
+ return;
+}
+
+static void mdfld_dsi_dpi_set_power(struct drm_encoder * encoder, bool on)
+{
+ struct mdfld_dsi_encoder * dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+ struct mdfld_dsi_dpi_output * dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_encoder);
+ struct mdfld_dsi_config * dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder);
+ int pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder);
+ struct drm_device * dev = dsi_config->dev;
+ struct drm_psb_private * dev_priv = dev->dev_private;
+ u32 pipeconf_reg = PIPEACONF;
+
+ PSB_DEBUG_ENTRY("set power %s on pipe %d\n", on ? "On" : "Off", pipe);
+
+ if (pipe)
+ pipeconf_reg = PIPECCONF;
+
+ /*start up display island if it was shutdown*/
+ if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON))
+ return;
+
+ if(on) {
+ if (get_panel_type(dev, pipe) == TMD_VID) {
+ mdfld_dsi_dpi_turn_on(dpi_output, pipe);
+ } else if (get_panel_type(dev, pipe) == TC35876X) {
+ if (dsi_device_ready) {
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+ return;
+ }
+
+ mdfld_dsi_configure_up(dsi_encoder, pipe);
+ dsi_device_ready = true;
+ } else {
+ /*enable mipi port*/
+ REG_WRITE(MIPI_PORT_CONTROL(pipe),
+ REG_READ(MIPI_PORT_CONTROL(pipe)) | BIT(31));
+ REG_READ(MIPI_PORT_CONTROL(pipe));
+
+ mdfld_dsi_dpi_turn_on(dpi_output, pipe);
+ mdfld_dsi_tpo_ic_init(dsi_config, pipe);
+ }
+
+ if(pipe == 2) {
+ dev_priv->dpi_panel_on2 = true;
+ }
+ else {
+ dev_priv->dpi_panel_on = true;
+ }
+
+ } else {
+ if (get_panel_type(dev, pipe) == TMD_VID) {
+ mdfld_dsi_dpi_shut_down(dpi_output, pipe);
+ } else if (get_panel_type(dev, pipe) == TC35876X) {
+ if (!dsi_device_ready) {
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+ return;
+ }
+
+ mdfld_dsi_configure_down(dsi_encoder, pipe);
+ dsi_device_ready = false;
+ } else {
+ mdfld_dsi_dpi_shut_down(dpi_output, pipe);
+
+ /*disable mipi port*/
+ REG_WRITE(MIPI_PORT_CONTROL(pipe),
+ REG_READ(MIPI_PORT_CONTROL(pipe)) & ~BIT(31));
+ REG_READ(MIPI_PORT_CONTROL(pipe));
+ }
+
+ if(pipe == 2) {
+ dev_priv->dpi_panel_on2 = false;
+ }
+ else {
+ dev_priv->dpi_panel_on = false;
+ }
+
+ }
+
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+}
+
+void mdfld_dsi_dpi_dpms(struct drm_encoder *encoder, int mode)
+{
+ PSB_DEBUG_ENTRY("%s \n", (mode == DRM_MODE_DPMS_ON ? "on":"off"));
+
+ if (mode == DRM_MODE_DPMS_ON) {
+ mdfld_dsi_dpi_set_power(encoder, true);
+ gbdispstatus = true;
+ } else {
+ mdfld_dsi_dpi_set_power(encoder, false);
+ gbdispstatus = false;
+#ifdef CONFIG_PM_RUNTIME
+ if (enable_gfx_rtpm)
+ pm_schedule_suspend(&gpDrmDevice->pdev->dev, gfxrtdelay);
+#endif
+ }
+
+ return;
+}
+
+bool mdfld_dsi_dpi_mode_fixup(struct drm_encoder * encoder,
+ struct drm_display_mode * mode,
+ struct drm_display_mode * adjusted_mode)
+{
+ struct mdfld_dsi_encoder * dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+ struct mdfld_dsi_config * dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder);
+ struct drm_display_mode * fixed_mode = dsi_config->fixed_mode;
+
+ PSB_DEBUG_ENTRY("\n");
+
+ if(fixed_mode) {
+ adjusted_mode->hdisplay = fixed_mode->hdisplay;
+ adjusted_mode->hsync_start = fixed_mode->hsync_start;
+ adjusted_mode->hsync_end = fixed_mode->hsync_end;
+ adjusted_mode->htotal = fixed_mode->htotal;
+ adjusted_mode->vdisplay = fixed_mode->vdisplay;
+ adjusted_mode->vsync_start = fixed_mode->vsync_start;
+ adjusted_mode->vsync_end = fixed_mode->vsync_end;
+ adjusted_mode->vtotal = fixed_mode->vtotal;
+ adjusted_mode->clock = fixed_mode->clock;
+ drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
+ }
+
+ return true;
+}
+
+void mdfld_dsi_dpi_prepare(struct drm_encoder * encoder)
+{
+ PSB_DEBUG_ENTRY("\n");
+
+ mdfld_dsi_dpi_set_power(encoder, false);
+}
+
+void mdfld_dsi_dpi_commit(struct drm_encoder * encoder)
+{
+ PSB_DEBUG_ENTRY("\n");
+
+ mdfld_dsi_dpi_set_power(encoder, true);
+}
+
+/* For TC35876X */
+/* This functionality was implemented in FW in iCDK */
+/* But removed in DV0 and later. So need to add here. */
+static void mipi_set_properties(struct mdfld_dsi_config *dsi_config, int pipe)
+{
+ struct drm_device *dev = dsi_config->dev;
+
+ printk(KERN_ALERT "[DISPLAY] Enter %s\n", __func__);
+
+ REG_WRITE(MIPI_CTRL_REG(pipe), 0x00000018);
+ REG_WRITE(MIPI_INTR_EN_REG(pipe), 0xffffffff);
+ REG_WRITE(MIPI_HS_TX_TIMEOUT_REG(pipe), 0xffffff);
+ REG_WRITE(MIPI_LP_RX_TIMEOUT_REG(pipe), 0xffffff);
+ REG_WRITE(MIPI_TURN_AROUND_TIMEOUT_REG(pipe), 0x14);
+ REG_WRITE(MIPI_DEVICE_RESET_TIMER_REG(pipe), 0xff);
+ REG_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT_REG(pipe), 0x25);
+ REG_WRITE(MIPI_INIT_COUNT_REG(pipe), 0xf0);
+ REG_WRITE(MIPI_EOT_DISABLE_REG(pipe), 0x00000000);
+ REG_WRITE(MIPI_LP_BYTECLK_REG(pipe), 0x00000004);
+ REG_WRITE(MIPI_DBI_BW_CTRL_REG(pipe), 0x00000820);
+ REG_WRITE(MIPI_CLK_LANE_SWITCH_TIME_CNT_REG(pipe), (0xa << 16) | 0x14);
+}
+
+static void mdfld_mipi_set_video_timing(struct mdfld_dsi_config *dsi_config,
+ int pipe)
+{
+ struct drm_device *dev = dsi_config->dev;
+ struct mdfld_dsi_dpi_timing dpi_timing;
+ struct drm_display_mode *mode = dsi_config->mode;
+
+ printk(KERN_ALERT "[DISPLAY] Enter %s\n", __func__);
+
+ mdfld_dsi_dpi_timing_calculation(mode, &dpi_timing,
+ dsi_config->lane_count,
+ dsi_config->bpp);
+
+ REG_WRITE(MIPI_DPI_RESOLUTION_REG(pipe),
+ mode->vdisplay << 16 | mode->hdisplay);
+ REG_WRITE(MIPI_HSYNC_COUNT_REG(pipe),
+ dpi_timing.hsync_count & DSI_DPI_TIMING_MASK);
+ REG_WRITE(MIPI_HBP_COUNT_REG(pipe),
+ dpi_timing.hbp_count & DSI_DPI_TIMING_MASK);
+ REG_WRITE(MIPI_HFP_COUNT_REG(pipe),
+ dpi_timing.hfp_count & DSI_DPI_TIMING_MASK);
+ REG_WRITE(MIPI_HACTIVE_COUNT_REG(pipe),
+ dpi_timing.hactive_count & DSI_DPI_TIMING_MASK);
+ REG_WRITE(MIPI_VSYNC_COUNT_REG(pipe),
+ dpi_timing.vsync_count & DSI_DPI_TIMING_MASK);
+ REG_WRITE(MIPI_VBP_COUNT_REG(pipe),
+ dpi_timing.vbp_count & DSI_DPI_TIMING_MASK);
+ REG_WRITE(MIPI_VFP_COUNT_REG(pipe),
+ dpi_timing.vfp_count & DSI_DPI_TIMING_MASK);
+}
+
+static void mdfld_mipi_config(struct mdfld_dsi_config *dsi_config, int pipe)
+{
+ struct drm_device *dev = dsi_config->dev;
+ int lane_count = dsi_config->lane_count;
+
+ printk(KERN_ALERT "[DISPLAY] Enter %s\n", __func__);
+
+ if (pipe) {
+ REG_WRITE(MIPI_PORT_CONTROL(0), 0x00000002);
+ REG_WRITE(MIPI_PORT_CONTROL(2), 0x80000000);
+ } else {
+ REG_WRITE(MIPI_PORT_CONTROL(0), 0x80010000);
+ REG_WRITE(MIPI_PORT_CONTROL(2), 0x00);
+ }
+
+ REG_WRITE(MIPI_DPHY_PARAM_REG(pipe), 0x150A600F);
+ REG_WRITE(MIPI_VIDEO_MODE_FORMAT_REG(pipe), 0x0000000F);
+
+ /* lane_count = 3 */
+ REG_WRITE(MIPI_DSI_FUNC_PRG_REG(pipe), 0x00000200 | lane_count);
+
+ mdfld_mipi_set_video_timing(dsi_config, pipe);
+}
+
+static void mdfld_set_pipe_timing(struct mdfld_dsi_config *dsi_config, int pipe)
+{
+ struct drm_device *dev = dsi_config->dev;
+ struct drm_display_mode *mode = dsi_config->mode;
+
+ printk(KERN_ALERT "[DISPLAY] Enter %s\n", __func__);
+
+ REG_WRITE(HTOTAL_A, ((mode->htotal - 1) << 16) | (mode->hdisplay - 1));
+ REG_WRITE(HBLANK_A, ((mode->htotal - 1) << 16) | (mode->hdisplay - 1));
+ REG_WRITE(HSYNC_A,
+ ((mode->hsync_end - 1) << 16) | (mode->hsync_start - 1));
+
+ REG_WRITE(VTOTAL_A, ((mode->vtotal - 1) << 16) | (mode->vdisplay - 1));
+ REG_WRITE(VBLANK_A, ((mode->vtotal - 1) << 16) | (mode->vdisplay - 1));
+ REG_WRITE(VSYNC_A,
+ ((mode->vsync_end - 1) << 16) | (mode->vsync_start - 1));
+
+ REG_WRITE(PIPEASRC,
+ ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
+}
+/* End for TC35876X */
+
+void mdfld_dsi_dpi_mode_set(struct drm_encoder * encoder,
+ struct drm_display_mode * mode,
+ struct drm_display_mode * adjusted_mode)
+{
+ struct mdfld_dsi_encoder * dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+ struct mdfld_dsi_dpi_output * dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_encoder);
+ struct mdfld_dsi_config * dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder);
+ struct drm_device * dev = dsi_config->dev;
+ struct drm_psb_private * dev_priv = dev->dev_private;
+ int pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder);
+
+ u32 pipeconf_reg = PIPEACONF;
+ u32 dspcntr_reg = DSPACNTR;
+
+ u32 pipeconf = dev_priv->pipeconf;
+ u32 dspcntr = dev_priv->dspcntr;
+ u32 mipi = MIPI_PORT_EN | PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX;
+
+ PSB_DEBUG_ENTRY("set mode %dx%d on pipe %d", mode->hdisplay, mode->vdisplay, pipe);
+
+ if(pipe) {
+ pipeconf_reg = PIPECCONF;
+ dspcntr_reg = DSPCCNTR;
+ } else {
+ if (get_panel_type(dev, pipe) == TC35876X)
+ mipi &= (~0x03); /* Use all four lanes */
+ else
+ mipi |= 2;
+ }
+
+ /*start up display island if it was shutdown*/
+ if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON))
+ return;
+
+ if (get_panel_type(dev, pipe) == TC35876X) {
+ /*
+ * The following logic is required to reset the bridge and
+ * configure. This also starts the DSI clock at 200MHz.
+ */
+ int timeout = 0;
+
+ tc35876x_set_bridge_reset_state(0); /*Pull High Reset */
+ tc35876x_toshiba_bridge_panel_on();
+ udelay(100);
+ /* Now start the DSI clock */
+ REG_WRITE(MRST_DPLL_A, 0x00);
+ REG_WRITE(MRST_FPA0, 0xC1);
+ REG_WRITE(MRST_DPLL_A, 0x00800000);
+ udelay(500);
+ REG_WRITE(MRST_DPLL_A, 0x80800000);
+ /*Wait for DSI PLL to lock */
+ while ((timeout < 20000) && !(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) {
+ udelay(150);
+ timeout++;
+ }
+ if (timeout == 20000)
+ printk(KERN_ALERT "[DISPLAY] DSI PLL Locked timeout\n");
+ REG_WRITE(MIPI_DPHY_PARAM_REG(pipe), 0x2A0c6008);
+
+ mipi_set_properties(dsi_config, pipe);
+ mdfld_mipi_config(dsi_config, pipe);
+ mdfld_set_pipe_timing(dsi_config, pipe);
+
+ REG_WRITE(DSPABASE, 0x00);
+ REG_WRITE(DSPASTRIDE, (mode->hdisplay * 4));
+ REG_WRITE(DSPASIZE,
+ ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1));
+
+ REG_WRITE(DSPACNTR, 0x98000000);
+ REG_WRITE(DSPASURF, 0x00);
+
+ REG_WRITE(VGACNTRL, 0x80000000);
+ REG_WRITE(DEVICE_READY_REG, 0x00000001);
+
+ REG_WRITE(MIPI_PORT_CONTROL(pipe), 0x80810000);
+ }
+
+ /*set up mipi port FIXME: do at init time */
+ REG_WRITE(MIPI_PORT_CONTROL(pipe), mipi);
+ REG_READ(MIPI_PORT_CONTROL(pipe));
+
+ if (get_panel_type(dev, pipe) == TMD_VID) {
+ /* NOP */
+ } else if (get_panel_type(dev, pipe) == TC35876X) {
+ /* set up DSI controller DPI interface */
+ mdfld_dsi_dpi_controller_init(dsi_config, pipe);
+
+ /* Configure MIPI Bridge and Panel */
+ tc35876x_configure_lvds_bridge(dev);
+ dsi_device_ready = true;
+ dev_priv->dpi_panel_on = true;
+ } else {
+ /*turn on DPI interface*/
+ mdfld_dsi_dpi_turn_on(dpi_output, pipe);
+ }
+
+ /*set up pipe*/
+ REG_WRITE(pipeconf_reg, pipeconf);
+ REG_READ(pipeconf_reg);
+
+ /*set up display plane*/
+ REG_WRITE(dspcntr_reg, dspcntr);
+ REG_READ(dspcntr_reg);
+
+ msleep(20); /* FIXME: this should wait for vblank */
+
+ PSB_DEBUG_ENTRY("State %x, power %d\n", REG_READ(MIPI_INTR_STAT_REG(pipe)),
+ dpi_output->panel_on);
+
+ if (get_panel_type(dev, pipe) == TMD_VID) {
+ /* NOP */
+ } else if (get_panel_type(dev, pipe) == TC35876X) {
+ mdfld_dsi_dpi_turn_on(dpi_output, pipe);
+ } else {
+ /* init driver ic */
+ mdfld_dsi_tpo_ic_init(dsi_config, pipe);
+ /*init backlight*/
+ mdfld_dsi_brightness_init(dsi_config, pipe);
+ }
+
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+}
+
+/*
+ * Init DSI DPI encoder.
+ * Allocate an mdfld_dsi_encoder and attach it to given @dsi_connector
+ * return pointer of newly allocated DPI encoder, NULL on error
+ */
+struct mdfld_dsi_encoder * mdfld_dsi_dpi_init(struct drm_device * dev,
+ struct mdfld_dsi_connector * dsi_connector,
+ struct panel_funcs* p_funcs)
+{
+ struct mdfld_dsi_dpi_output * dpi_output = NULL;
+ struct mdfld_dsi_config * dsi_config;
+ struct drm_connector * connector = NULL;
+ struct drm_encoder * encoder = NULL;
+ struct drm_display_mode * fixed_mode = NULL;
+ int pipe;
+ u32 data;
+ int ret;
+
+ PSB_DEBUG_ENTRY("\n");
+
+ if (!dsi_connector || !p_funcs) {
+ DRM_ERROR("Invalid parameters\n");
+ return NULL;
+ }
+
+ pipe = dsi_connector->pipe;
+
+ if (get_panel_type(dev, pipe) != TC35876X) {
+ dsi_config = mdfld_dsi_get_config(dsi_connector);
+
+ /* panel hard-reset */
+ if (p_funcs->reset) {
+ ret = p_funcs->reset(pipe);
+ if (ret) {
+ DRM_ERROR("Panel %d hard-reset failed\n", pipe);
+ return NULL;
+ }
+ }
+
+ /* panel drvIC init */
+ if (p_funcs->drv_ic_init)
+ p_funcs->drv_ic_init(dsi_config, pipe);
+
+ /* panel power mode detect */
+ ret = mdfld_dsi_get_power_mode(dsi_config, &data, false);
+ if (ret) {
+ DRM_ERROR("Panel %d get power mode failed\n", pipe);
+ dsi_connector->status = connector_status_disconnected;
+ } else {
+ DRM_INFO("pipe %d power mode 0x%x\n", pipe, data);
+ dsi_connector->status = connector_status_connected;
+ }
+ }
+
+ dpi_output = kzalloc(sizeof(struct mdfld_dsi_dpi_output), GFP_KERNEL);
+ if(!dpi_output) {
+ DRM_ERROR("No memory\n");
+ return NULL;
+ }
+
+ if(dsi_connector->pipe)
+ dpi_output->panel_on = 0;
+ else
+ dpi_output->panel_on = 0;
+
+
+ dpi_output->dev = dev;
+ if (get_panel_type(dev, pipe) != TC35876X)
+ dpi_output->p_funcs = p_funcs;
+ dpi_output->first_boot = 1;
+
+ /*get fixed mode*/
+ dsi_config = mdfld_dsi_get_config(dsi_connector);
+ fixed_mode = dsi_config->fixed_mode;
+
+ /*create drm encoder object*/
+ connector = &dsi_connector->base.base;
+ encoder = &dpi_output->base.base;
+ drm_encoder_init(dev,
+ encoder,
+ p_funcs->encoder_funcs,
+ DRM_MODE_ENCODER_LVDS);
+ drm_encoder_helper_add(encoder,
+ p_funcs->encoder_helper_funcs);
+
+ /*attach to given connector*/
+ drm_mode_connector_attach_encoder(connector, encoder);
+
+ /*set possible crtcs and clones*/
+ if(dsi_connector->pipe) {
+ encoder->possible_crtcs = (1 << 2);
+ encoder->possible_clones = (1 << 1);
+ } else {
+ encoder->possible_crtcs = (1 << 0);
+ encoder->possible_clones = (1 << 0);
+ }
+
+ if (get_panel_type(dev, pipe) == TC35876X) {
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ dev_priv->dpi_panel_on = false;
+ }
+
+ PSB_DEBUG_ENTRY("successfully\n");
+
+ return &dpi_output->base;
+}
--- /dev/null
+/*
+ * Copyright © 2010 Intel 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 (including the next
+ * paragraph) 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.
+ *
+ * Authors:
+ * jim liu <jim.liu@intel.com>
+ * Jackie Li<yaodong.li@intel.com>
+ */
+
+#ifndef __MDFLD_DSI_DPI_H__
+#define __MDFLD_DSI_DPI_H__
+
+#include "mdfld_dsi_output.h"
+#include "mdfld_output.h"
+
+struct mdfld_dsi_dpi_timing {
+ u16 hsync_count;
+ u16 hbp_count;
+ u16 hfp_count;
+ u16 hactive_count;
+ u16 vsync_count;
+ u16 vbp_count;
+ u16 vfp_count;
+};
+
+struct mdfld_dsi_dpi_output {
+ struct mdfld_dsi_encoder base;
+ struct drm_device *dev;
+
+ int panel_on;
+ int first_boot;
+
+ struct panel_funcs *p_funcs;
+};
+
+#define MDFLD_DSI_DPI_OUTPUT(dsi_encoder) container_of(dsi_encoder, struct mdfld_dsi_dpi_output, base)
+
+/*export functions*/
+extern int mdfld_dsi_dpi_timing_calculation(struct drm_display_mode * mode,
+ struct mdfld_dsi_dpi_timing * dpi_timing,
+ int num_lane, int bpp);
+extern struct mdfld_dsi_encoder * mdfld_dsi_dpi_init(struct drm_device * dev,
+ struct mdfld_dsi_connector * dsi_connector,
+ struct panel_funcs* p_funcs);
+
+/*MDFLD DPI helper functions*/
+extern void mdfld_dsi_dpi_dpms(struct drm_encoder *encoder, int mode);
+extern bool mdfld_dsi_dpi_mode_fixup(struct drm_encoder * encoder,
+ struct drm_display_mode * mode,
+ struct drm_display_mode * adjusted_mode);
+extern void mdfld_dsi_dpi_prepare(struct drm_encoder * encoder);
+extern void mdfld_dsi_dpi_commit(struct drm_encoder * encoder);
+extern void mdfld_dsi_dpi_mode_set(struct drm_encoder * encoder,
+ struct drm_display_mode * mode,
+ struct drm_display_mode * adjusted_mode);
+extern void mdfld_dsi_dpi_turn_on(struct mdfld_dsi_dpi_output * output,
+ int pipe);
+extern void mdfld_dsi_dpi_controller_init(struct mdfld_dsi_config * dsi_config, int pipe);
+#endif /*__MDFLD_DSI_DPI_H__*/
--- /dev/null
+/*
+ * Copyright © 2010 Intel 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 (including the next
+ * paragraph) 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.
+ *
+ * Authors:
+ * jim liu <jim.liu@intel.com>
+ * Jackie Li<yaodong.li@intel.com>
+ */
+
+#include "mdfld_dsi_output.h"
+#include "mdfld_dsi_dbi.h"
+#include "mdfld_dsi_dpi.h"
+#include "mdfld_output.h"
+#include "mdfld_dsi_pkg_sender.h"
+#include <linux/pm_runtime.h>
+#include <asm/intel_scu_ipc.h>
+
+#define MDFLD_DSI_BRIGHTNESS_MAX_LEVEL 100
+
+/* get the CABC LABC from command line. */
+static int CABC_control = 1;
+static int LABC_control = 1;
+
+#ifdef MODULE
+module_param (CABC_control, int, 0644);
+module_param (LABC_control, int, 0644);
+#else
+static int __init parse_CABC_control(char *arg)
+{
+ /* CABC control can be passed in as a cmdline parameter */
+ /* to enable this feature add CABC=1 to cmdline */
+ /* to disable this feature add CABC=0 to cmdline */
+ if (!arg)
+ return -EINVAL;
+
+ if (!strcasecmp(arg, "0"))
+ CABC_control = 0;
+ else if (!strcasecmp (arg, "1"))
+ CABC_control = 1;
+
+ return 0;
+}
+early_param ("CABC", parse_CABC_control);
+
+static int __init parse_LABC_control(char *arg)
+{
+ /* LABC control can be passed in as a cmdline parameter */
+ /* to enable this feature add LABC=1 to cmdline */
+ /* to disable this feature add LABC=0 to cmdline */
+ if (!arg)
+ return -EINVAL;
+
+ if (!strcasecmp(arg, "0"))
+ LABC_control = 0;
+ else if (!strcasecmp (arg, "1"))
+ LABC_control = 1;
+
+ return 0;
+}
+early_param ("LABC", parse_LABC_control);
+#endif
+
+/**
+ * make these MCS command global
+ * we don't need 'movl' everytime we send them.
+ * FIXME: these datas were provided by OEM, we should get them from GCT.
+ **/
+/* FIXME: make the below data u8 instead of u32; note byte order! */
+static u32 mdfld_dbi_mcs_hysteresis[] = {
+ 0x42000f57, 0x8c006400, 0xff00bf00, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x38000aff, 0x82005000, 0xff00ab00, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x000000ff,
+};
+
+static u32 mdfld_dbi_mcs_display_profile[] = {
+ 0x50281450, 0x0000c882, 0x00000000, 0x00000000,
+ 0x00000000,
+};
+
+static u32 mdfld_dbi_mcs_kbbc_profile[] = {
+ 0x00ffcc60, 0x00000000, 0x00000000, 0x00000000,
+};
+
+static u32 mdfld_dbi_mcs_gamma_profile[] = {
+ 0x81111158, 0x88888888, 0x88888888,
+};
+
+/**
+ * Check and see if the generic control or data buffer is empty and ready.
+ */
+void mdfld_dsi_gen_fifo_ready (struct drm_device *dev, u32 gen_fifo_stat_reg, u32 fifo_stat)
+{
+ u32 GEN_BF_time_out_count = 0;
+
+ /* Check MIPI Adatper command registers */
+ for (GEN_BF_time_out_count = 0; GEN_BF_time_out_count < GEN_FB_TIME_OUT; GEN_BF_time_out_count++)
+ {
+ if ((REG_READ(gen_fifo_stat_reg) & fifo_stat) == fifo_stat)
+ break;
+ udelay (100);
+ }
+
+ if (GEN_BF_time_out_count == GEN_FB_TIME_OUT)
+ DRM_ERROR("mdfld_dsi_gen_fifo_ready, Timeout. gen_fifo_stat_reg = 0x%x. \n", gen_fifo_stat_reg);
+}
+
+/**
+ * Manage the DSI MIPI keyboard and display brightness.
+ * FIXME: this is exported to OSPM code. should work out an specific
+ * display interface to OSPM.
+ */
+#define PWM0_CLK_DIV 64000
+#define PWM0CLKDIV0 0x62
+#define PWM0CLKDIV1 0x61
+static void tc35876x_brightness_init(struct mdfld_dsi_config *dsi_config,
+ int pipe)
+{
+ int ret;
+
+ printk(KERN_ALERT "[DISPLAY] %s\n", __func__);
+
+ /* Set PWM frequency to 300 Hz = (19.2*1000*1000)/64000 */
+ ret = intel_scu_ipc_iowrite8(PWM0CLKDIV0, PWM0_CLK_DIV & 0xff);
+ ret |= intel_scu_ipc_iowrite8(PWM0CLKDIV1, (PWM0_CLK_DIV >> 8) & 0xff);
+ if (ret)
+ printk(KERN_ERR "[DISPLAY] %s: ipc write fail\n", __func__);
+}
+
+void mdfld_dsi_brightness_init (struct mdfld_dsi_config * dsi_config, int pipe)
+{
+ struct mdfld_dsi_pkg_sender * sender = mdfld_dsi_get_pkg_sender(dsi_config);
+ struct drm_device * dev = sender->dev;
+ struct drm_psb_private * dev_priv = dev->dev_private;
+ u32 gen_ctrl_val;
+
+ if (get_panel_type(dev, pipe) == TC35876X) {
+ tc35876x_brightness_init(dsi_config, pipe);
+ return;
+ }
+
+ if(!sender) {
+ DRM_ERROR("No sender found\n");
+ }
+ /* Set default display backlight value to 85% (0xd8)*/
+ mdfld_dsi_send_mcs_short(sender, write_display_brightness, 0xd8, 1,
+ true);
+
+ /* Set minimum brightness setting of CABC function to 20% (0x33)*/
+ mdfld_dsi_send_mcs_short(sender, write_cabc_min_bright, 0x33, 1, true);
+
+ /* FIXME: make the below data u8 instead of u32; note byte order! */
+
+ /* write hysteresis values */
+ mdfld_dsi_send_mcs_long(sender, (u8 *) mdfld_dbi_mcs_hysteresis,
+ sizeof(mdfld_dbi_mcs_hysteresis), true);
+ /* write display profile values */
+ mdfld_dsi_send_mcs_long(sender, (u8 *) mdfld_dbi_mcs_display_profile,
+ sizeof(mdfld_dbi_mcs_display_profile), true);
+ /* write KBBC profile values */
+ mdfld_dsi_send_mcs_long(sender, (u8 *) mdfld_dbi_mcs_kbbc_profile,
+ sizeof(mdfld_dbi_mcs_kbbc_profile), true);
+ /* write gamma setting */
+ mdfld_dsi_send_mcs_long(sender, (u8 *) mdfld_dbi_mcs_gamma_profile,
+ sizeof(mdfld_dbi_mcs_gamma_profile), true);
+
+ /* Enable backlight or/and LABC */
+ gen_ctrl_val = BRIGHT_CNTL_BLOCK_ON | DISPLAY_DIMMING_ON| BACKLIGHT_ON;
+ if (LABC_control == 1 || CABC_control == 1)
+ gen_ctrl_val |= DISPLAY_DIMMING_ON| DISPLAY_BRIGHTNESS_AUTO | GAMMA_AUTO;
+
+ if (LABC_control == 1)
+ gen_ctrl_val |= AMBIENT_LIGHT_SENSE_ON;
+
+ dev_priv->mipi_ctrl_display = gen_ctrl_val;
+
+ mdfld_dsi_send_mcs_short(sender, write_ctrl_display, (u8)gen_ctrl_val,
+ 1, true);
+
+ if (CABC_control == 0)
+ return;
+
+ mdfld_dsi_send_mcs_short(sender, write_ctrl_cabc, UI_IMAGE, 1, true);
+}
+
+/**
+ * Manage the mipi display brightness.
+ * TODO: refine this interface later
+ */
+#define BACKLIGHT_DUTY_FACTOR 0x63
+#define MIN_BACKLIGHT_DUTY_FACTOR 0x10
+#define PWM0DUTYCYCLE 0x67
+static void tc35876x_brightness_control(struct drm_device *dev, int pipe,
+ int level)
+{
+ int ret;
+ int duty_val;
+
+ duty_val = min(MIN_BACKLIGHT_DUTY_FACTOR,
+ level * BACKLIGHT_DUTY_FACTOR / MDFLD_DSI_BRIGHTNESS_MAX_LEVEL);
+
+ printk(KERN_ALERT "[DISPLAY] %s: level = %d, duty_val = %d\n", __func__,
+ level, duty_val);
+
+ ret = intel_scu_ipc_iowrite8(PWM0DUTYCYCLE, duty_val);
+ if (ret)
+ printk(KERN_ERR "[DISPLAY] %s: ipc write fail\n", __func__);
+}
+
+void mdfld_dsi_brightness_control (struct drm_device *dev, int pipe, int level)
+{
+ struct mdfld_dsi_pkg_sender * sender;
+ struct drm_psb_private * dev_priv;
+ struct mdfld_dsi_config * dsi_config;
+ u32 gen_ctrl_val = 0;
+ enum panel_type p_type = TMD_VID;
+
+ if (get_panel_type(dev, pipe) == TC35876X) {
+ tc35876x_brightness_control(dev, pipe, level);
+ return;
+ }
+
+ if(!dev || (pipe != 0 && pipe != 2)) {
+ DRM_ERROR("Invalid parameter\n");
+ return;
+ }
+
+ p_type = get_panel_type(dev, 0);
+
+ dev_priv = dev->dev_private;
+
+ if(pipe)
+ dsi_config = dev_priv->dsi_configs[1];
+ else
+ dsi_config = dev_priv->dsi_configs[0];
+
+ sender = mdfld_dsi_get_pkg_sender(dsi_config);
+
+ if(!sender) {
+ DRM_ERROR("No sender found\n");
+ return;
+ }
+
+ gen_ctrl_val = ((level * 0xff) / MDFLD_DSI_BRIGHTNESS_MAX_LEVEL) & 0xff;
+
+ PSB_DEBUG_ENTRY("pipe = %d, gen_ctrl_val = %d. \n", pipe, gen_ctrl_val);
+
+ if(p_type == TMD_VID || p_type == TMD_CMD){
+ /* Set display backlight value */
+ mdfld_dsi_send_mcs_short(sender, tmd_write_display_brightness,
+ (u8)gen_ctrl_val, 1, true);
+ } else {
+ /* Set display backlight value */
+ mdfld_dsi_send_mcs_short(sender, write_display_brightness,
+ (u8)gen_ctrl_val, 1, true);
+
+ /* Enable backlight control */
+ if (level == 0)
+ gen_ctrl_val = 0;
+ else
+ gen_ctrl_val = dev_priv->mipi_ctrl_display;
+
+ mdfld_dsi_send_mcs_short(sender, write_ctrl_display,
+ (u8)gen_ctrl_val, 1, true);
+ }
+}
+
+/*
+ * shut down DSI controller
+ */
+static void mdfld_dsi_controller_shutdown(struct mdfld_dsi_config * dsi_config, int pipe)
+{
+ struct drm_device * dev;
+ int retry = 100;
+
+ PSB_DEBUG_ENTRY("shutting down DSI controller on pipe %d... dsi_config %p\n", pipe, dsi_config);
+
+ if(!dsi_config) {
+ DRM_ERROR("Invalid parameter\n");
+ return;
+ }
+
+ dev = dsi_config->dev;
+
+ if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) {
+ DRM_ERROR("hw begin failed\n");
+ return;
+ }
+
+ if (!(REG_READ(MIPI_DEVICE_READY_REG(pipe)) & DSI_DEVICE_READY))
+ goto shutdown_out;
+
+ /*send shut down package, clean packet send bit first*/
+ if (REG_READ(MIPI_INTR_STAT_REG(pipe)) & DSI_INTR_STATE_SPL_PKG_SENT) {
+ REG_WRITE(MIPI_INTR_STAT_REG(pipe),
+ (REG_READ(MIPI_INTR_STAT_REG(pipe)) | DSI_INTR_STATE_SPL_PKG_SENT));
+ }
+
+ /*send shut down package in HS*/
+ REG_WRITE(MIPI_DPI_CONTROL_REG(pipe), DSI_DPI_CTRL_HS_SHUTDOWN);
+
+
+ /*
+ * make sure shut down is sent.
+ * FIXME: add max retry counter
+ */
+ while (!(REG_READ(MIPI_INTR_STAT_REG(pipe)) & DSI_INTR_STATE_SPL_PKG_SENT)) {
+ retry--;
+
+ if(!retry) {
+ PSB_DEBUG_ENTRY("timeout\n");
+ break;
+ }
+ }
+
+ /*sleep 1 ms to ensure shutdown finished*/
+ msleep(100);
+
+ /*un-ready device*/
+ REG_WRITE(MIPI_DEVICE_READY_REG(pipe),
+ (REG_READ(MIPI_DEVICE_READY_REG(pipe)) & ~DSI_DEVICE_READY));
+
+shutdown_out:
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+}
+
+static void mdfld_dsi_controller_startup(struct mdfld_dsi_config * dsi_config, int pipe)
+{
+ struct drm_device * dev;
+ int retry = 100;
+
+ PSB_DEBUG_ENTRY("starting up DSI controller on pipe %d...\n", pipe);
+
+ if(!dsi_config) {
+ DRM_ERROR("Invalid parameter\n");
+ return;
+ }
+
+ dev = dsi_config->dev;
+
+ if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) {
+ DRM_ERROR("hw begin failed\n");
+ return;
+ }
+
+ if ((REG_READ(MIPI_DEVICE_READY_REG(pipe)) & DSI_DEVICE_READY))
+ goto startup_out;
+
+ /*if config DPI, turn on DPI interface*/
+ if(dsi_config->type == MDFLD_DSI_ENCODER_DPI) {
+ if (REG_READ(MIPI_INTR_STAT_REG(pipe)) & DSI_INTR_STATE_SPL_PKG_SENT) {
+ REG_WRITE(MIPI_INTR_STAT_REG(pipe), DSI_INTR_STATE_SPL_PKG_SENT);
+ }
+
+ REG_WRITE(MIPI_DPI_CONTROL_REG(pipe), DSI_DPI_CTRL_HS_TURN_ON);
+
+ /*
+ * make sure shut down is sent.
+ * FIXME: add max retry counter
+ */
+ while (!(REG_READ(MIPI_INTR_STAT_REG(pipe)) & DSI_INTR_STATE_SPL_PKG_SENT)) {
+ retry--;
+ if(!retry) {
+ PSB_DEBUG_ENTRY("timeout\n");
+ break;
+ }
+ }
+
+ msleep(100);
+ }
+
+ /*set device ready*/
+ REG_WRITE(MIPI_DEVICE_READY_REG(pipe),
+ REG_READ(MIPI_DEVICE_READY_REG(pipe)) | DSI_DEVICE_READY);
+
+startup_out:
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+}
+
+static int mdfld_dsi_get_panel_status(struct mdfld_dsi_config *dsi_config,
+ u8 dcs, u32 *data, bool hs)
+{
+ struct mdfld_dsi_pkg_sender *sender
+ = mdfld_dsi_get_pkg_sender(dsi_config);
+
+ if (!sender || !data) {
+ DRM_ERROR("Invalid parameter\n");
+ return -EINVAL;
+ }
+
+ return mdfld_dsi_read_mcs(sender, dcs, data, 1, hs);
+}
+
+int mdfld_dsi_get_power_mode(struct mdfld_dsi_config *dsi_config, u32 *mode,
+ bool hs)
+{
+ if (!dsi_config || !mode) {
+ DRM_ERROR("Invalid parameter\n");
+ return -EINVAL;
+ }
+
+ return mdfld_dsi_get_panel_status(dsi_config, 0x0a, mode, hs);
+}
+
+int mdfld_dsi_get_diagnostic_result(struct mdfld_dsi_config *dsi_config,
+ u32 *result, bool hs)
+{
+ if (!dsi_config || !result) {
+ DRM_ERROR("Invalid parameter\n");
+ return -EINVAL;
+ }
+
+ return mdfld_dsi_get_panel_status(dsi_config, 0x0f, result, hs);
+}
+
+/*
+ * NOTE: this function was used by OSPM.
+ * TODO: will be removed later, should work out display interfaces for OSPM
+ */
+void mdfld_dsi_controller_init(struct mdfld_dsi_config * dsi_config, int pipe)
+{
+ if(!dsi_config || ((pipe != 0) && (pipe != 2))) {
+ DRM_ERROR("Invalid parameters\n");
+ return;
+ }
+
+ if (dsi_config->type == MDFLD_DSI_ENCODER_DPI)
+ mdfld_dsi_dpi_controller_init(dsi_config, pipe);
+ else if (dsi_config->type == MDFLD_DSI_ENCODER_DBI)
+ mdfld_dsi_controller_dbi_init(dsi_config, pipe);
+ else
+ DRM_ERROR("Bad DSI encoder type\n");
+}
+
+static void mdfld_dsi_connector_save(struct drm_connector * connector)
+{
+ PSB_DEBUG_ENTRY("\n");
+}
+
+static void mdfld_dsi_connector_restore(struct drm_connector * connector)
+{
+ PSB_DEBUG_ENTRY("\n");
+}
+
+/* FIXME: start using the force parameter */
+static enum drm_connector_status
+mdfld_dsi_connector_detect(struct drm_connector *connector, bool force)
+{
+ struct psb_intel_output *psb_output
+ = to_psb_intel_output(connector);
+ struct mdfld_dsi_connector *dsi_connector
+ = MDFLD_DSI_CONNECTOR(psb_output);
+
+ PSB_DEBUG_ENTRY("\n");
+
+ return dsi_connector->status;
+}
+
+static int mdfld_dsi_connector_set_property(struct drm_connector * connector,
+ struct drm_property * property,
+ uint64_t value)
+{
+ struct drm_encoder * encoder = connector->encoder;
+ struct backlight_device * psb_bd;
+
+ PSB_DEBUG_ENTRY("\n");
+
+ if (!strcmp(property->name, "scaling mode") && encoder) {
+ struct psb_intel_crtc * psb_crtc = to_psb_intel_crtc(encoder->crtc);
+ bool bTransitionFromToCentered;
+ uint64_t curValue;
+
+ if (!psb_crtc)
+ goto set_prop_error;
+
+ switch (value) {
+ case DRM_MODE_SCALE_FULLSCREEN:
+ break;
+ case DRM_MODE_SCALE_NO_SCALE:
+ break;
+ case DRM_MODE_SCALE_ASPECT:
+ break;
+ default:
+ goto set_prop_error;
+ }
+
+ if (drm_connector_property_get_value(connector, property, &curValue))
+ goto set_prop_error;
+
+ if (curValue == value)
+ goto set_prop_done;
+
+ if (drm_connector_property_set_value(connector, property, value))
+ goto set_prop_error;
+
+ bTransitionFromToCentered = (curValue == DRM_MODE_SCALE_NO_SCALE) ||
+ (value == DRM_MODE_SCALE_NO_SCALE);
+
+ if (psb_crtc->saved_mode.hdisplay != 0 &&
+ psb_crtc->saved_mode.vdisplay != 0) {
+ if (bTransitionFromToCentered) {
+ if (!drm_crtc_helper_set_mode(encoder->crtc, &psb_crtc->saved_mode,
+ encoder->crtc->x, encoder->crtc->y, encoder->crtc->fb))
+ goto set_prop_error;
+ } else {
+ struct drm_encoder_helper_funcs *pEncHFuncs = encoder->helper_private;
+ pEncHFuncs->mode_set(encoder, &psb_crtc->saved_mode,
+ &psb_crtc->saved_adjusted_mode);
+ }
+ }
+ } else if (!strcmp(property->name, "backlight") && encoder) {
+ PSB_DEBUG_ENTRY("backlight level = %d\n", (int)value);
+ if (drm_connector_property_set_value(connector, property, value))
+ goto set_prop_error;
+ else {
+ PSB_DEBUG_ENTRY("set brightness to %d", (int)value);
+ psb_bd = psb_get_backlight_device();
+ if(psb_bd) {
+ psb_bd->props.brightness = value;
+ psb_set_brightness(psb_bd);
+ }
+ }
+ }
+set_prop_done:
+ return 0;
+set_prop_error:
+ return -1;
+}
+
+static void mdfld_dsi_connector_destroy(struct drm_connector * connector)
+{
+ struct psb_intel_output * psb_output = to_psb_intel_output(connector);
+ struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output);
+ struct mdfld_dsi_pkg_sender * sender;
+
+ PSB_DEBUG_ENTRY("\n");
+
+ if(!dsi_connector) {
+ return;
+ }
+
+ drm_sysfs_connector_remove(connector);
+ drm_connector_cleanup(connector);
+
+ sender = dsi_connector->pkg_sender;
+
+ mdfld_dsi_pkg_sender_destroy(sender);
+
+ kfree(dsi_connector);
+}
+
+static int mdfld_dsi_connector_get_modes(struct drm_connector * connector)
+{
+ struct psb_intel_output * psb_output = to_psb_intel_output(connector);
+ struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output);
+ struct mdfld_dsi_config * dsi_config = mdfld_dsi_get_config(dsi_connector);
+ struct drm_display_mode * fixed_mode = dsi_config->fixed_mode;
+ struct drm_display_mode * dup_mode = NULL;
+ struct drm_device * dev = connector->dev;
+
+ PSB_DEBUG_ENTRY("\n");
+
+ connector->display_info.min_vfreq = 0;
+ connector->display_info.max_vfreq = 200;
+ connector->display_info.min_hfreq = 0;
+ connector->display_info.max_hfreq = 200;
+
+ if(fixed_mode) {
+ PSB_DEBUG_ENTRY("fixed_mode %dx%d\n", fixed_mode->hdisplay, fixed_mode->vdisplay);
+
+ dup_mode = drm_mode_duplicate(dev, fixed_mode);
+ drm_mode_probed_add(connector, dup_mode);
+ return 1;
+ }
+
+ DRM_ERROR("Didn't get any modes!\n");
+
+ return 0;
+}
+
+static int mdfld_dsi_connector_mode_valid(struct drm_connector * connector, struct drm_display_mode * mode)
+{
+ struct psb_intel_output * psb_output = to_psb_intel_output(connector);
+ struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output);
+ struct mdfld_dsi_config * dsi_config = mdfld_dsi_get_config(dsi_connector);
+ struct drm_display_mode * fixed_mode = dsi_config->fixed_mode;
+
+ PSB_DEBUG_ENTRY("mode %p, fixed mode %p\n", mode, fixed_mode);
+
+ if(mode->flags & DRM_MODE_FLAG_DBLSCAN)
+ return MODE_NO_DBLESCAN;
+
+ if(mode->flags & DRM_MODE_FLAG_INTERLACE)
+ return MODE_NO_INTERLACE;
+
+ /**
+ * FIXME: current DC has no fitting unit, reject any mode setting request
+ * will figure out a way to do up-scaling(pannel fitting) later.
+ **/
+ if(fixed_mode) {
+ if(mode->hdisplay != fixed_mode->hdisplay)
+ return MODE_PANEL;
+
+ if(mode->vdisplay != fixed_mode->vdisplay)
+ return MODE_PANEL;
+ }
+
+ PSB_DEBUG_ENTRY("ok\n");
+
+ return MODE_OK;
+}
+
+static void mdfld_dsi_connector_dpms(struct drm_connector *connector, int mode)
+{
+#ifdef CONFIG_PM_RUNTIME
+ struct drm_device * dev = connector->dev;
+ struct drm_psb_private * dev_priv = dev->dev_private;
+ bool panel_on, panel_on2;
+#endif
+
+ if (mode == connector->dpms)
+ return;
+
+ /*first, execute dpms*/
+
+ drm_helper_connector_dpms(connector, mode);
+
+#ifdef CONFIG_PM_RUNTIME
+ if(is_panel_vid_or_cmd(dev)) {
+ /*DPI panel*/
+ panel_on = dev_priv->dpi_panel_on;
+ panel_on2 = dev_priv->dpi_panel_on2;
+ } else {
+ /*DBI panel*/
+ panel_on = dev_priv->dbi_panel_on;
+ panel_on2 = dev_priv->dbi_panel_on2;
+ }
+
+ /*then check all display panels + monitors status*/
+ /* Make sure that the Display (B) sub-system status isn't i3 when
+ * R/W the DC register, otherwise "Fabric error" issue would occur
+ * during S0i3 state. */
+ if(!panel_on && !panel_on2 && !(REG_READ(HDMIB_CONTROL) & HDMIB_PORT_EN)) {
+ /*request rpm idle*/
+ if(dev_priv->rpm_enabled) {
+ pm_request_idle(&dev->pdev->dev);
+ }
+ }
+
+ /**
+ * if rpm wasn't enabled yet, try to allow it
+ * FIXME: won't enable rpm for DPI since DPI
+ * CRTC setting is a little messy now.
+ * Enable it later!
+ */
+#if 0
+ if(!dev_priv->rpm_enabled && !is_panel_vid_or_cmd(dev))
+ ospm_runtime_pm_allow(dev);
+#endif
+#endif
+}
+
+static struct drm_encoder * mdfld_dsi_connector_best_encoder(struct drm_connector * connector)
+{
+ struct psb_intel_output * psb_output = to_psb_intel_output(connector);
+ struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output);
+ struct mdfld_dsi_config * dsi_config = mdfld_dsi_get_config(dsi_connector);
+ struct mdfld_dsi_encoder * encoder = NULL;
+
+ PSB_DEBUG_ENTRY("config type %d\n", dsi_config->type);
+
+ if(dsi_config->type == MDFLD_DSI_ENCODER_DBI)
+ encoder = dsi_config->encoders[MDFLD_DSI_ENCODER_DBI];
+ else if (dsi_config->type == MDFLD_DSI_ENCODER_DPI)
+ encoder = dsi_config->encoders[MDFLD_DSI_ENCODER_DPI];
+
+ PSB_DEBUG_ENTRY("get encoder %p\n", encoder);
+
+ if(!encoder) {
+ DRM_ERROR("Invalid encoder for type %d\n", dsi_config->type);
+ return NULL;
+ }
+
+ dsi_config->encoder = encoder;
+
+ return &encoder->base;
+}
+
+/*DSI connector funcs*/
+static const struct drm_connector_funcs mdfld_dsi_connector_funcs = {
+ .dpms = /*drm_helper_connector_dpms*/mdfld_dsi_connector_dpms,
+ .save = mdfld_dsi_connector_save,
+ .restore = mdfld_dsi_connector_restore,
+ .detect = mdfld_dsi_connector_detect,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .set_property = mdfld_dsi_connector_set_property,
+ .destroy = mdfld_dsi_connector_destroy,
+};
+
+/*DSI connector helper funcs*/
+static const struct drm_connector_helper_funcs mdfld_dsi_connector_helper_funcs = {
+ .get_modes = mdfld_dsi_connector_get_modes,
+ .mode_valid = mdfld_dsi_connector_mode_valid,
+ .best_encoder = mdfld_dsi_connector_best_encoder,
+};
+
+static int mdfld_dsi_get_default_config(struct drm_device * dev,
+ struct mdfld_dsi_config * config, int pipe)
+{
+ if(!dev || !config) {
+ DRM_ERROR("Invalid parameters");
+ return -EINVAL;
+ }
+
+ config->bpp = 24;
+ config->type = is_panel_vid_or_cmd(dev);
+ if (get_panel_type(dev, pipe) == TC35876X)
+ config->lane_count = 4;
+ else
+ config->lane_count = 2;
+ config->channel_num = 0;
+ /*NOTE: video mode is ignored when type is MDFLD_DSI_ENCODER_DBI*/
+ if (get_panel_type(dev, pipe) == TMD_VID) {
+ config->video_mode = MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_PULSE;
+ } else if (get_panel_type(dev, pipe) == TC35876X) {
+ config->video_mode = MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_EVENTS;
+ } else {
+ config->video_mode = MDFLD_DSI_VIDEO_BURST_MODE;
+ }
+
+ return 0;
+}
+
+/*
+ * Returns the panel fixed mode from configuration.
+ */
+static struct drm_display_mode *
+mdfld_dsi_get_configuration_mode(struct mdfld_dsi_config * dsi_config, int pipe)
+{
+ struct drm_device *dev = dsi_config->dev;
+ struct drm_display_mode *mode;
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) dev->dev_private;
+ struct mrst_timing_info *ti = &dev_priv->gct_data.DTD;
+ bool use_gct = false;
+
+ PSB_DEBUG_ENTRY("\n");
+
+ mode = kzalloc(sizeof(*mode), GFP_KERNEL);
+ if (!mode)
+ return NULL;
+
+ if (use_gct) {
+ PSB_DEBUG_ENTRY("gct find MIPI panel. \n");
+
+ mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo;
+ mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo;
+ mode->hsync_start = mode->hdisplay + \
+ ((ti->hsync_offset_hi << 8) | \
+ ti->hsync_offset_lo);
+ mode->hsync_end = mode->hsync_start + \
+ ((ti->hsync_pulse_width_hi << 8) | \
+ ti->hsync_pulse_width_lo);
+ mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \
+ ti->hblank_lo);
+ mode->vsync_start = \
+ mode->vdisplay + ((ti->vsync_offset_hi << 8) | \
+ ti->vsync_offset_lo);
+ mode->vsync_end = \
+ mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \
+ ti->vsync_pulse_width_lo);
+ mode->vtotal = mode->vdisplay + \
+ ((ti->vblank_hi << 8) | ti->vblank_lo);
+ mode->clock = ti->pixel_clock * 10;
+
+ PSB_DEBUG_ENTRY("hdisplay is %d\n", mode->hdisplay);
+ PSB_DEBUG_ENTRY("vdisplay is %d\n", mode->vdisplay);
+ PSB_DEBUG_ENTRY("HSS is %d\n", mode->hsync_start);
+ PSB_DEBUG_ENTRY("HSE is %d\n", mode->hsync_end);
+ PSB_DEBUG_ENTRY("htotal is %d\n", mode->htotal);
+ PSB_DEBUG_ENTRY("VSS is %d\n", mode->vsync_start);
+ PSB_DEBUG_ENTRY("VSE is %d\n", mode->vsync_end);
+ PSB_DEBUG_ENTRY("vtotal is %d\n", mode->vtotal);
+ PSB_DEBUG_ENTRY("clock is %d\n", mode->clock);
+ } else {
+ if(dsi_config->type == MDFLD_DSI_ENCODER_DPI) {
+ if (get_panel_type(dev, pipe) == TMD_VID) {
+ mode->hdisplay = 480;
+ mode->vdisplay = 854;
+ mode->hsync_start = 487;
+ mode->hsync_end = 490;
+ mode->htotal = 499;
+ mode->vsync_start = 861;
+ mode->vsync_end = 865;
+ mode->vtotal = 873;
+ mode->clock = 33264;
+ } else {
+ mode->hdisplay = 864;
+ mode->vdisplay = 480;
+ mode->hsync_start = 873;
+ mode->hsync_end = 876;
+ mode->htotal = 887;
+ mode->vsync_start = 487;
+ mode->vsync_end = 490;
+ mode->vtotal = 499;
+ mode->clock = 33264;
+ }
+ } else if(dsi_config->type == MDFLD_DSI_ENCODER_DBI) {
+ mode->hdisplay = 864;
+ mode->vdisplay = 480;
+ mode->hsync_start = 872;
+ mode->hsync_end = 876;
+ mode->htotal = 884;
+ mode->vsync_start = 482;
+ mode->vsync_end = 494;
+ mode->vtotal = 486;
+ mode->clock = 25777;
+
+ }
+ }
+
+ drm_mode_set_name(mode);
+ drm_mode_set_crtcinfo(mode, 0);
+
+ mode->type |= DRM_MODE_TYPE_PREFERRED;
+
+ return mode;
+}
+
+int mdfld_dsi_panel_reset(int pipe)
+{
+ unsigned gpio;
+ int ret = 0;
+
+ switch (pipe) {
+ case 0:
+ gpio = 128;
+ break;
+ case 2:
+ gpio = 34;
+ break;
+ default:
+ DRM_ERROR("Invalid output\n");
+ return -EINVAL;
+ }
+
+ ret = gpio_request(gpio, "gfx");
+ if (ret) {
+ DRM_ERROR("gpio_rqueset failed\n");
+ return ret;
+ }
+
+ ret = gpio_direction_output(gpio, 1);
+ if (ret) {
+ DRM_ERROR("gpio_direction_output failed\n");
+ goto gpio_error;
+ }
+
+ gpio_get_value(128);
+
+gpio_error:
+ if (gpio_is_valid(gpio))
+ gpio_free(gpio);
+
+ PSB_DEBUG_ENTRY("Panel reset done\n");
+
+ return ret;
+}
+
+/*
+ * MIPI output init
+ * @dev drm device
+ * @pipe pipe number. 0 or 2
+ * @config
+ *
+ * Do the initialization of a MIPI output, including create DRM mode objects
+ * initialization of DSI output on @pipe
+ */
+void mdfld_dsi_output_init(struct drm_device * dev,
+ int pipe,
+ struct mdfld_dsi_config * config,
+ struct panel_funcs* p_cmd_funcs,
+ struct panel_funcs* p_vid_funcs)
+{
+ struct mdfld_dsi_config * dsi_config;
+ struct mdfld_dsi_connector * dsi_connector;
+ struct psb_intel_output * psb_output;
+ struct drm_connector * connector;
+ struct mdfld_dsi_encoder * encoder;
+ struct drm_psb_private * dev_priv = dev->dev_private;
+ struct panel_info dsi_panel_info;
+ u32 width_mm, height_mm;
+
+ PSB_DEBUG_ENTRY("init DSI output on pipe %d\n", pipe);
+
+ if(!dev || ((pipe != 0) && (pipe != 2))) {
+ DRM_ERROR("Invalid parameter\n");
+ return;
+ }
+
+ /*create a new connetor*/
+ dsi_connector = kzalloc(sizeof(struct mdfld_dsi_connector), GFP_KERNEL);
+ if(!dsi_connector) {
+ DRM_ERROR("No memory");
+ return;
+ }
+
+ dsi_connector->pipe = pipe;
+
+ /*set DSI config*/
+ if(config) {
+ dsi_config = config;
+ } else {
+ dsi_config = kzalloc(sizeof(struct mdfld_dsi_config), GFP_KERNEL);
+ if(!dsi_config) {
+ DRM_ERROR("cannot allocate memory for DSI config\n");
+ goto dsi_init_err0;
+ }
+
+ mdfld_dsi_get_default_config(dev, dsi_config, pipe);
+ }
+
+ dsi_connector->private = dsi_config;
+
+ dsi_config->changed = 1;
+ dsi_config->dev = dev;
+
+ /*init fixed mode basing on DSI config type*/
+ if(dsi_config->type == MDFLD_DSI_ENCODER_DBI) {
+ dsi_config->fixed_mode = p_cmd_funcs->get_config_mode(dev);
+ if(p_cmd_funcs->get_panel_info(dev, pipe, &dsi_panel_info))
+ goto dsi_init_err0;
+ } else if(dsi_config->type == MDFLD_DSI_ENCODER_DPI) {
+ dsi_config->fixed_mode = p_vid_funcs->get_config_mode(dev);
+ if(p_vid_funcs->get_panel_info(dev, pipe, &dsi_panel_info))
+ goto dsi_init_err0;
+ }
+
+ width_mm = dsi_panel_info.width_mm;
+ height_mm = dsi_panel_info.height_mm;
+
+ dsi_config->mode = dsi_config->fixed_mode;
+ dsi_config->connector = dsi_connector;
+
+ if(!dsi_config->fixed_mode) {
+ DRM_ERROR("No pannel fixed mode was found\n");
+ goto dsi_init_err0;
+ }
+
+ if(pipe && dev_priv->dsi_configs[0]) {
+ dsi_config->dvr_ic_inited = 0;
+ dev_priv->dsi_configs[1] = dsi_config;
+ } else if(pipe == 0) {
+ dsi_config->dvr_ic_inited = 1;
+ dev_priv->dsi_configs[0] = dsi_config;
+ } else {
+ DRM_ERROR("Trying to init MIPI1 before MIPI0\n");
+ goto dsi_init_err0;
+ }
+
+ /*init drm connector object*/
+ psb_output = &dsi_connector->base;
+
+ psb_output->type = (pipe == 0) ? INTEL_OUTPUT_MIPI : INTEL_OUTPUT_MIPI2;
+
+ connector = &psb_output->base;
+ drm_connector_init(dev, connector, &mdfld_dsi_connector_funcs, DRM_MODE_CONNECTOR_LVDS);
+ drm_connector_helper_add(connector, &mdfld_dsi_connector_helper_funcs);
+
+ connector->display_info.subpixel_order = SubPixelHorizontalRGB;
+ connector->display_info.width_mm = width_mm;
+ connector->display_info.height_mm = height_mm;
+ connector->interlace_allowed = false;
+ connector->doublescan_allowed = false;
+
+ /*attach properties*/
+ drm_connector_attach_property(connector, dev->mode_config.scaling_mode_property, DRM_MODE_SCALE_FULLSCREEN);
+ drm_connector_attach_property(connector, dev_priv->backlight_property, MDFLD_DSI_BRIGHTNESS_MAX_LEVEL);
+
+ /*init DSI package sender on this output*/
+ if (mdfld_dsi_pkg_sender_init(dsi_connector, pipe)) {
+ DRM_ERROR("Package Sender initialization failed on pipe %d\n", pipe);
+ goto dsi_init_err0;
+ }
+
+ /*create DBI & DPI encoders*/
+ if(p_cmd_funcs) {
+ encoder = mdfld_dsi_dbi_init(dev, dsi_connector, p_cmd_funcs);
+ if(!encoder) {
+ DRM_ERROR("Create DBI encoder failed\n");
+ goto dsi_init_err1;
+ }
+ encoder->private = dsi_config;
+ dsi_config->encoders[MDFLD_DSI_ENCODER_DBI] = encoder;
+ }
+
+ if(p_vid_funcs) {
+ encoder = mdfld_dsi_dpi_init(dev, dsi_connector, p_vid_funcs);
+ if(!encoder) {
+ DRM_ERROR("Create DPI encoder failed\n");
+ goto dsi_init_err1;
+ }
+ encoder->private = dsi_config;
+ dsi_config->encoders[MDFLD_DSI_ENCODER_DPI] = encoder;
+ }
+
+ drm_sysfs_connector_add(connector);
+
+ PSB_DEBUG_ENTRY("successfully\n");
+ return;
+
+ /*TODO: add code to destroy outputs on error*/
+dsi_init_err1:
+ /*destroy sender*/
+ mdfld_dsi_pkg_sender_destroy(dsi_connector->pkg_sender);
+
+ drm_connector_cleanup(connector);
+
+ if(dsi_config->fixed_mode)
+ kfree(dsi_config->fixed_mode);
+ if(dsi_config)
+ kfree(dsi_config);
+dsi_init_err0:
+ if(dsi_connector) {
+ kfree(dsi_connector);
+ }
+}
--- /dev/null
+/*
+ * Copyright © 2010 Intel 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 (including the next
+ * paragraph) 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.
+ *
+ * Authors:
+ * jim liu <jim.liu@intel.com>
+ * Jackie Li<yaodong.li@intel.com>
+ */
+
+#ifndef __MDFLD_DSI_OUTPUT_H__
+#define __MDFLD_DSI_OUTPUT_H__
+
+#include <linux/backlight.h>
+#include <linux/version.h>
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_edid.h>
+
+#include "psb_drv.h"
+#include "psb_intel_drv.h"
+#include "psb_intel_reg.h"
+#include "psb_powermgmt.h"
+#include "mdfld_output.h"
+
+#include <asm/mrst.h>
+
+
+#ifdef DEBUG
+#define CHECK_PIPE(pipe) ({ \
+ const typeof(pipe) __pipe = (pipe); \
+ BUG_ON(__pipe != 0 && __pipe != 2); \
+ __pipe; })
+#else
+#define CHECK_PIPE(pipe) (pipe)
+#endif
+
+/*
+ * Actual MIPIA->MIPIC reg offset is 0x800, value 0x400 is valid for 0 and 2
+ */
+#define REG_OFFSET(pipe) (CHECK_PIPE(pipe) * 0x400)
+
+/* mdfld DSI controller registers */
+#define MIPI_DEVICE_READY_REG(pipe) (0xb000 + REG_OFFSET(pipe))
+#define MIPI_INTR_STAT_REG(pipe) (0xb004 + REG_OFFSET(pipe))
+#define MIPI_INTR_EN_REG(pipe) (0xb008 + REG_OFFSET(pipe))
+#define MIPI_DSI_FUNC_PRG_REG(pipe) (0xb00c + REG_OFFSET(pipe))
+#define MIPI_HS_TX_TIMEOUT_REG(pipe) (0xb010 + REG_OFFSET(pipe))
+#define MIPI_LP_RX_TIMEOUT_REG(pipe) (0xb014 + REG_OFFSET(pipe))
+#define MIPI_TURN_AROUND_TIMEOUT_REG(pipe) (0xb018 + REG_OFFSET(pipe))
+#define MIPI_DEVICE_RESET_TIMER_REG(pipe) (0xb01c + REG_OFFSET(pipe))
+#define MIPI_DPI_RESOLUTION_REG(pipe) (0xb020 + REG_OFFSET(pipe))
+#define MIPI_DBI_FIFO_THROTTLE_REG(pipe) (0xb024 + REG_OFFSET(pipe))
+#define MIPI_HSYNC_COUNT_REG(pipe) (0xb028 + REG_OFFSET(pipe))
+#define MIPI_HBP_COUNT_REG(pipe) (0xb02c + REG_OFFSET(pipe))
+#define MIPI_HFP_COUNT_REG(pipe) (0xb030 + REG_OFFSET(pipe))
+#define MIPI_HACTIVE_COUNT_REG(pipe) (0xb034 + REG_OFFSET(pipe))
+#define MIPI_VSYNC_COUNT_REG(pipe) (0xb038 + REG_OFFSET(pipe))
+#define MIPI_VBP_COUNT_REG(pipe) (0xb03c + REG_OFFSET(pipe))
+#define MIPI_VFP_COUNT_REG(pipe) (0xb040 + REG_OFFSET(pipe))
+#define MIPI_HIGH_LOW_SWITCH_COUNT_REG(pipe) (0xb044 + REG_OFFSET(pipe))
+#define MIPI_DPI_CONTROL_REG(pipe) (0xb048 + REG_OFFSET(pipe))
+#define MIPI_DPI_DATA_REG(pipe) (0xb04c + REG_OFFSET(pipe))
+#define MIPI_INIT_COUNT_REG(pipe) (0xb050 + REG_OFFSET(pipe))
+#define MIPI_MAX_RETURN_PACK_SIZE_REG(pipe) (0xb054 + REG_OFFSET(pipe))
+#define MIPI_VIDEO_MODE_FORMAT_REG(pipe) (0xb058 + REG_OFFSET(pipe))
+#define MIPI_EOT_DISABLE_REG(pipe) (0xb05c + REG_OFFSET(pipe))
+#define MIPI_LP_BYTECLK_REG(pipe) (0xb060 + REG_OFFSET(pipe))
+#define MIPI_LP_GEN_DATA_REG(pipe) (0xb064 + REG_OFFSET(pipe))
+#define MIPI_HS_GEN_DATA_REG(pipe) (0xb068 + REG_OFFSET(pipe))
+#define MIPI_LP_GEN_CTRL_REG(pipe) (0xb06c + REG_OFFSET(pipe))
+#define MIPI_HS_GEN_CTRL_REG(pipe) (0xb070 + REG_OFFSET(pipe))
+#define MIPI_GEN_FIFO_STAT_REG(pipe) (0xb074 + REG_OFFSET(pipe))
+#define MIPI_HS_LS_DBI_ENABLE_REG(pipe) (0xb078 + REG_OFFSET(pipe))
+#define MIPI_DPHY_PARAM_REG(pipe) (0xb080 + REG_OFFSET(pipe))
+#define MIPI_DBI_BW_CTRL_REG(pipe) (0xb084 + REG_OFFSET(pipe))
+#define MIPI_CLK_LANE_SWITCH_TIME_CNT_REG(pipe) (0xb088 + REG_OFFSET(pipe))
+
+#define MIPI_CTRL_REG(pipe) (0xb104 + REG_OFFSET(pipe))
+#define MIPI_DATA_ADD_REG(pipe) (0xb108 + REG_OFFSET(pipe))
+#define MIPI_DATA_LEN_REG(pipe) (0xb10c + REG_OFFSET(pipe))
+#define MIPI_CMD_ADD_REG(pipe) (0xb110 + REG_OFFSET(pipe))
+#define MIPI_CMD_LEN_REG(pipe) (0xb114 + REG_OFFSET(pipe))
+
+/* non-uniform reg offset */
+#define MIPI_PORT_CONTROL(pipe) (CHECK_PIPE(pipe) ? MIPI_C : MIPI)
+
+#define DSI_DEVICE_READY (0x1)
+#define DSI_POWER_STATE_ULPS_ENTER (0x2 << 1)
+#define DSI_POWER_STATE_ULPS_EXIT (0x1 << 1)
+#define DSI_POWER_STATE_ULPS_OFFSET (0x1)
+
+
+#define DSI_ONE_DATA_LANE (0x1)
+#define DSI_TWO_DATA_LANE (0x2)
+#define DSI_THREE_DATA_LANE (0X3)
+#define DSI_FOUR_DATA_LANE (0x4)
+#define DSI_DPI_VIRT_CHANNEL_OFFSET (0x3)
+#define DSI_DBI_VIRT_CHANNEL_OFFSET (0x5)
+#define DSI_DPI_COLOR_FORMAT_RGB565 (0x01 << 7)
+#define DSI_DPI_COLOR_FORMAT_RGB666 (0x02 << 7)
+#define DSI_DPI_COLOR_FORMAT_RGB666_UNPACK (0x03 << 7)
+#define DSI_DPI_COLOR_FORMAT_RGB888 (0x04 << 7)
+#define DSI_DBI_COLOR_FORMAT_OPTION2 (0x05 << 13)
+
+#define DSI_INTR_STATE_RXSOTERROR BIT(0)
+
+#define DSI_INTR_STATE_SPL_PKG_SENT BIT(30)
+#define DSI_INTR_STATE_TE BIT(31)
+
+#define DSI_HS_TX_TIMEOUT_MASK (0xffffff)
+
+#define DSI_LP_RX_TIMEOUT_MASK (0xffffff)
+
+#define DSI_TURN_AROUND_TIMEOUT_MASK (0x3f)
+
+#define DSI_RESET_TIMER_MASK (0xffff)
+
+#define DSI_DBI_FIFO_WM_HALF (0x0)
+#define DSI_DBI_FIFO_WM_QUARTER (0x1)
+#define DSI_DBI_FIFO_WM_LOW (0x2)
+
+#define DSI_DPI_TIMING_MASK (0xffff)
+
+#define DSI_INIT_TIMER_MASK (0xffff)
+
+#define DSI_DBI_RETURN_PACK_SIZE_MASK (0x3ff)
+
+#define DSI_LP_BYTECLK_MASK (0x0ffff)
+
+#define DSI_HS_CTRL_GEN_SHORT_W0 (0x03)
+#define DSI_HS_CTRL_GEN_SHORT_W1 (0x13)
+#define DSI_HS_CTRL_GEN_SHORT_W2 (0x23)
+#define DSI_HS_CTRL_GEN_R0 (0x04)
+#define DSI_HS_CTRL_GEN_R1 (0x14)
+#define DSI_HS_CTRL_GEN_R2 (0x24)
+#define DSI_HS_CTRL_GEN_LONG_W (0x29)
+#define DSI_HS_CTRL_MCS_SHORT_W0 (0x05)
+#define DSI_HS_CTRL_MCS_SHORT_W1 (0x15)
+#define DSI_HS_CTRL_MCS_R0 (0x06)
+#define DSI_HS_CTRL_MCS_LONG_W (0x39)
+#define DSI_HS_CTRL_VC_OFFSET (0x06)
+#define DSI_HS_CTRL_WC_OFFSET (0x08)
+
+#define DSI_FIFO_GEN_HS_DATA_FULL BIT(0)
+#define DSI_FIFO_GEN_HS_DATA_HALF_EMPTY BIT(1)
+#define DSI_FIFO_GEN_HS_DATA_EMPTY BIT(2)
+#define DSI_FIFO_GEN_LP_DATA_FULL BIT(8)
+#define DSI_FIFO_GEN_LP_DATA_HALF_EMPTY BIT(9)
+#define DSI_FIFO_GEN_LP_DATA_EMPTY BIT(10)
+#define DSI_FIFO_GEN_HS_CTRL_FULL BIT(16)
+#define DSI_FIFO_GEN_HS_CTRL_HALF_EMPTY BIT(17)
+#define DSI_FIFO_GEN_HS_CTRL_EMPTY BIT(18)
+#define DSI_FIFO_GEN_LP_CTRL_FULL BIT(24)
+#define DSI_FIFO_GEN_LP_CTRL_HALF_EMPTY BIT(25)
+#define DSI_FIFO_GEN_LP_CTRL_EMPTY BIT(26)
+#define DSI_FIFO_DBI_EMPTY BIT(27)
+#define DSI_FIFO_DPI_EMPTY BIT(28)
+
+#define DSI_DBI_HS_LP_SWITCH_MASK (0x1)
+
+#define DSI_HS_LP_SWITCH_COUNTER_OFFSET (0x0)
+#define DSI_LP_HS_SWITCH_COUNTER_OFFSET (0x16)
+
+#define DSI_DPI_CTRL_HS_SHUTDOWN (0x00000001)
+#define DSI_DPI_CTRL_HS_TURN_ON (0x00000002)
+
+/*dsi power modes*/
+#define DSI_POWER_MODE_DISPLAY_ON BIT(2)
+#define DSI_POWER_MODE_NORMAL_ON BIT(3)
+#define DSI_POWER_MODE_SLEEP_OUT BIT(4)
+#define DSI_POWER_MODE_PARTIAL_ON BIT(5)
+#define DSI_POWER_MODE_IDLE_ON BIT(6)
+
+typedef enum {
+ MDFLD_DSI_ENCODER_DBI = 0,
+ MDFLD_DSI_ENCODER_DPI,
+} mdfld_dsi_encoder_t;
+
+enum {
+ MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_PULSE = 1,
+ MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_EVENTS = 2,
+ MDFLD_DSI_VIDEO_BURST_MODE = 3,
+};
+
+#define DSI_DPI_COMPLETE_LAST_LINE BIT(2)
+#define DSI_DPI_DISABLE_BTA BIT(3)
+
+struct mdfld_dsi_connector_state {
+ u32 mipi_ctrl_reg;
+};
+
+struct mdfld_dsi_encoder_state {
+
+};
+
+struct mdfld_dsi_connector {
+ /*
+ * This is ugly, but I have to use connector in it! :-(
+ * FIXME: use drm_connector instead.
+ */
+ struct psb_intel_output base;
+
+ int pipe;
+ void * private;
+ void * pkg_sender;
+
+ /*connection status*/
+ enum drm_connector_status status;
+};
+
+struct mdfld_dsi_encoder {
+ struct drm_encoder base;
+ void * private;
+};
+
+/*
+ * DSI config, consists of one DSI connector, two DSI encoders.
+ * DRM will pick up on DSI encoder basing on differents configs.
+ */
+struct mdfld_dsi_config {
+ struct drm_device * dev;
+ struct drm_display_mode * fixed_mode;
+ struct drm_display_mode * mode;
+
+ struct mdfld_dsi_connector * connector;
+ struct mdfld_dsi_encoder * encoders[DRM_CONNECTOR_MAX_ENCODER];
+ struct mdfld_dsi_encoder * encoder;
+
+ int changed;
+
+ int bpp;
+ mdfld_dsi_encoder_t type;
+ int lane_count;
+ /*Virtual channel number for this encoder*/
+ int channel_num;
+ /*video mode configure*/
+ int video_mode;
+
+ int dvr_ic_inited;
+};
+
+#define MDFLD_DSI_CONNECTOR(psb_output) \
+ (container_of(psb_output, struct mdfld_dsi_connector, base))
+
+#define MDFLD_DSI_ENCODER(encoder) \
+ (container_of(encoder, struct mdfld_dsi_encoder, base))
+
+static inline struct mdfld_dsi_config *
+ mdfld_dsi_get_config(struct mdfld_dsi_connector * connector)
+{
+ if(!connector) {
+ return NULL;
+ }
+
+ return (struct mdfld_dsi_config *)connector->private;
+}
+
+static inline void * mdfld_dsi_get_pkg_sender(struct mdfld_dsi_config * config)
+{
+ struct mdfld_dsi_connector * dsi_connector;
+
+ if(!config)
+ return NULL;
+
+ dsi_connector = config->connector;
+
+ if(!dsi_connector)
+ return NULL;
+
+ return dsi_connector->pkg_sender;
+}
+
+static inline struct mdfld_dsi_config *
+ mdfld_dsi_encoder_get_config(struct mdfld_dsi_encoder * encoder)
+{
+ if(!encoder)
+ return NULL;
+ return (struct mdfld_dsi_config *)encoder->private;
+}
+
+static inline struct mdfld_dsi_connector *
+ mdfld_dsi_encoder_get_connector(struct mdfld_dsi_encoder * encoder)
+{
+ struct mdfld_dsi_config * config;
+
+ if(!encoder)
+ return NULL;
+
+ config = mdfld_dsi_encoder_get_config(encoder);
+ if(!config)
+ return NULL;
+
+ return config->connector;
+}
+
+static inline void * mdfld_dsi_encoder_get_pkg_sender(struct mdfld_dsi_encoder * encoder)
+{
+ struct mdfld_dsi_config * dsi_config;
+
+ dsi_config = mdfld_dsi_encoder_get_config(encoder);
+ if(!dsi_config)
+ return NULL;
+
+ return mdfld_dsi_get_pkg_sender(dsi_config);
+}
+
+static inline int mdfld_dsi_encoder_get_pipe(struct mdfld_dsi_encoder * encoder)
+{
+ struct mdfld_dsi_connector * connector;
+
+ if(!encoder)
+ return -1;
+
+ connector = mdfld_dsi_encoder_get_connector(encoder);
+ if(!connector)
+ return -1;
+
+ return connector->pipe;
+}
+
+/*Export functions*/
+extern void mdfld_dsi_gen_fifo_ready (struct drm_device *dev, u32 gen_fifo_stat_reg, u32 fifo_stat);
+extern void mdfld_dsi_brightness_init (struct mdfld_dsi_config * dsi_config, int pipe);
+extern void mdfld_dsi_brightness_control (struct drm_device *dev, int pipe, int level);
+extern void mdfld_dsi_output_init(struct drm_device * dev,
+ int pipe,
+ struct mdfld_dsi_config * config,
+ struct panel_funcs * p_cmd_funcs,
+ struct panel_funcs * p_vid_funcs);
+extern void mdfld_dsi_controller_init(struct mdfld_dsi_config * dsi_config, int pipe);
+
+extern int mdfld_dsi_get_power_mode(struct mdfld_dsi_config *dsi_config,
+ u32 *mode, bool hs);
+extern int mdfld_dsi_get_diagnostic_result(struct mdfld_dsi_config *dsi_config,
+ u32 *result, bool hs);
+extern int mdfld_dsi_panel_reset(int pipe);
+
+#endif /*__MDFLD_DSI_OUTPUT_H__*/
--- /dev/null
+/*
+ * Copyright © 2010 Intel 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 (including the next
+ * paragraph) 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.
+ *
+ * Authors:
+ * Jackie Li<yaodong.li@intel.com>
+ */
+
+#include <linux/freezer.h>
+
+#include "mdfld_dsi_output.h"
+#include "mdfld_dsi_pkg_sender.h"
+#include "mdfld_dsi_dbi.h"
+#include "mdfld_dsi_dpi.h"
+
+#define FLD_MASK(start, end) (((1 << ((start) - (end) + 1)) - 1) << (end))
+#define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end))
+#define FLD_GET(val, start, end) (((val) & FLD_MASK(start, end)) >> (end))
+#define FLD_MOD(orig, val, start, end) \
+ (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end))
+
+#define MDFLD_DSI_DBI_FIFO_TIMEOUT 100
+#define MDFLD_DSI_READ_MAX_COUNT 5000
+
+enum data_type {
+ DSI_DT_GENERIC_SHORT_WRITE_0 = 0x03,
+ DSI_DT_GENERIC_SHORT_WRITE_1 = 0x13,
+ DSI_DT_GENERIC_SHORT_WRITE_2 = 0x23,
+ DSI_DT_GENERIC_READ_0 = 0x04,
+ DSI_DT_GENERIC_READ_1 = 0x14,
+ DSI_DT_GENERIC_READ_2 = 0x24,
+ DSI_DT_GENERIC_LONG_WRITE = 0x29,
+ DSI_DT_DCS_SHORT_WRITE_0 = 0x05,
+ DSI_DT_DCS_SHORT_WRITE_1 = 0x15,
+ DSI_DT_DCS_READ = 0x06,
+ DSI_DT_DCS_LONG_WRITE = 0x39,
+};
+
+enum {
+ MDFLD_DSI_PANEL_MODE_SLEEP = 0x1,
+};
+
+enum {
+ MDFLD_DSI_PKG_SENDER_FREE = 0x0,
+ MDFLD_DSI_PKG_SENDER_BUSY = 0x1,
+};
+
+static const char * dsi_errors[] = {
+ "RX SOT Error",
+ "RX SOT Sync Error",
+ "RX EOT Sync Error",
+ "RX Escape Mode Entry Error",
+ "RX LP TX Sync Error",
+ "RX HS Receive Timeout Error",
+ "RX False Control Error",
+ "RX ECC Single Bit Error",
+ "RX ECC Multibit Error",
+ "RX Checksum Error",
+ "RX DSI Data Type Not Recognised",
+ "RX DSI VC ID Invalid",
+ "TX False Control Error",
+ "TX ECC Single Bit Error",
+ "TX ECC Multibit Error",
+ "TX Checksum Error",
+ "TX DSI Data Type Not Recognised",
+ "TX DSI VC ID invalid",
+ "High Contention",
+ "Low contention",
+ "DPI FIFO Under run",
+ "HS TX Timeout",
+ "LP RX Timeout",
+ "Turn Around ACK Timeout",
+ "ACK With No Error",
+ "RX Invalid TX Length",
+ "RX Prot Violation",
+ "HS Generic Write FIFO Full",
+ "LP Generic Write FIFO Full",
+ "Generic Read Data Avail"
+ "Special Packet Sent",
+ "Tearing Effect",
+};
+
+static inline int wait_for_gen_fifo_empty(struct mdfld_dsi_pkg_sender * sender,
+ u32 mask)
+{
+ struct drm_device * dev = sender->dev;
+ u32 gen_fifo_stat_reg = sender->mipi_gen_fifo_stat_reg;
+ int retry = 0xffff;
+
+ while(retry--) {
+ if((mask & REG_READ(gen_fifo_stat_reg)) == mask)
+ return 0;
+ udelay(100);
+ }
+
+ DRM_ERROR("fifo is NOT empty 0x%08x\n", REG_READ(gen_fifo_stat_reg));
+ return -EIO;
+}
+
+static int wait_for_all_fifos_empty(struct mdfld_dsi_pkg_sender * sender)
+{
+ return wait_for_gen_fifo_empty(sender, (BIT(2) | BIT(10) | BIT(18) | BIT(26) | BIT(27) | BIT(28)));
+}
+
+static int wait_for_lp_fifos_empty(struct mdfld_dsi_pkg_sender * sender)
+{
+ return wait_for_gen_fifo_empty(sender, (BIT(10) | BIT(26)));
+}
+
+static int wait_for_hs_fifos_empty(struct mdfld_dsi_pkg_sender * sender)
+{
+ return wait_for_gen_fifo_empty(sender, (BIT(2) | BIT(18)));
+}
+
+static int wait_for_dbi_fifo_empty(struct mdfld_dsi_pkg_sender * sender)
+{
+ return wait_for_gen_fifo_empty(sender, (BIT(27)));
+}
+
+static int handle_dsi_error(struct mdfld_dsi_pkg_sender * sender, u32 mask)
+{
+ u32 intr_stat_reg = sender->mipi_intr_stat_reg;
+ struct drm_device * dev = sender->dev;
+
+ PSB_DEBUG_ENTRY("Handling error 0x%08x\n", mask);
+
+ switch(mask) {
+ case BIT(0):
+ case BIT(1):
+ case BIT(2):
+ case BIT(3):
+ case BIT(4):
+ case BIT(5):
+ case BIT(6):
+ case BIT(7):
+ case BIT(8):
+ case BIT(9):
+ case BIT(10):
+ case BIT(11):
+ case BIT(12):
+ case BIT(13):
+ PSB_DEBUG_ENTRY("No Action required\n");
+ break;
+ case BIT(14):
+ /*wait for all fifo empty*/
+ /*wait_for_all_fifos_empty(sender)*/;
+ break;
+ case BIT(15):
+ PSB_DEBUG_ENTRY("No Action required\n");
+ break;
+ case BIT(16):
+ break;
+ case BIT(17):
+ break;
+ case BIT(18):
+ case BIT(19):
+ PSB_DEBUG_ENTRY("High/Low contention detected\n");
+ /*wait for contention recovery time*/
+ /*mdelay(10);*/
+ /*wait for all fifo empty*/
+ if(0) wait_for_all_fifos_empty(sender);
+ break;
+ case BIT(20):
+ PSB_DEBUG_ENTRY("No Action required\n");
+ break;
+ case BIT(21):
+ /*wait for all fifo empty*/
+ /*wait_for_all_fifos_empty(sender);*/
+ break;
+ case BIT(22):
+ break;
+ case BIT(23):
+ case BIT(24):
+ case BIT(25):
+ case BIT(26):
+ case BIT(27):
+ PSB_DEBUG_ENTRY("HS Gen fifo full\n");
+ REG_WRITE(intr_stat_reg, mask);
+ wait_for_hs_fifos_empty(sender);
+ break;
+ case BIT(28):
+ PSB_DEBUG_ENTRY("LP Gen fifo full\n");
+ REG_WRITE(intr_stat_reg, mask);
+ wait_for_lp_fifos_empty(sender);
+ break;
+ case BIT(29):
+ case BIT(30):
+ case BIT(31):
+ PSB_DEBUG_ENTRY("No Action required\n");
+ break;
+ }
+
+ if(mask & REG_READ(intr_stat_reg)) {
+ PSB_DEBUG_ENTRY("Cannot clean interrupt 0x%08x\n", mask);
+ }
+
+ return 0;
+}
+
+static int dsi_error_handler(struct mdfld_dsi_pkg_sender * sender)
+{
+ struct drm_device * dev = sender->dev;
+ u32 intr_stat_reg = sender->mipi_intr_stat_reg;
+ u32 mask;
+ u32 intr_stat;
+ int i;
+ int err = 0;
+
+ intr_stat = REG_READ(intr_stat_reg);
+
+ for(i=0; i<32; i++) {
+ mask = (0x00000001UL) << i;
+ if(intr_stat & mask) {
+ PSB_DEBUG_ENTRY("[DSI]: %s\n", dsi_errors[i]);
+ err = handle_dsi_error(sender, mask);
+ if(err)
+ DRM_ERROR("Cannot handle error\n");
+ }
+ }
+
+ return err;
+}
+
+static inline int dbi_cmd_sent(struct mdfld_dsi_pkg_sender * sender)
+{
+ struct drm_device * dev = sender->dev;
+ u32 retry = 0xffff;
+ u32 dbi_cmd_addr_reg = sender->mipi_cmd_addr_reg;
+ int ret = 0;
+
+ /*query the command execution status*/
+ while(retry--) {
+ if(!(REG_READ(dbi_cmd_addr_reg) & BIT(0)))
+ break;
+ }
+
+ if(!retry) {
+ DRM_ERROR("Timeout waiting for DBI Command status\n");
+ ret = -EAGAIN;
+ }
+
+ return ret;
+}
+
+static int send_short_pkg(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
+ u8 cmd, u8 param, bool hs)
+{
+ struct drm_device * dev = sender->dev;
+ u32 ctrl_reg;
+ u32 val;
+ u8 virtual_channel = 0;
+
+ if (hs) {
+ ctrl_reg = sender->mipi_hs_gen_ctrl_reg;
+
+ /* FIXME: wait_for_hs_fifos_empty(sender); */
+ } else {
+ ctrl_reg = sender->mipi_lp_gen_ctrl_reg;
+
+ /* FIXME: wait_for_lp_fifos_empty(sender); */
+ }
+
+ val = FLD_VAL(param, 23, 16) | FLD_VAL(cmd, 15, 8) |
+ FLD_VAL(virtual_channel, 7, 6) | FLD_VAL(data_type, 5, 0);
+
+ REG_WRITE(ctrl_reg, val);
+
+ return 0;
+}
+
+static int send_long_pkg(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
+ u8 *data, int len, bool hs)
+{
+ struct drm_device * dev = sender->dev;
+ u32 ctrl_reg;
+ u32 data_reg;
+ u32 val;
+ u8 *p;
+ u8 b1, b2, b3, b4;
+ u8 virtual_channel = 0;
+ int i;
+
+ if (hs) {
+ ctrl_reg = sender->mipi_hs_gen_ctrl_reg;
+ data_reg = sender->mipi_hs_gen_data_reg;
+
+ /* FIXME: wait_for_hs_fifos_empty(sender); */
+ } else {
+ ctrl_reg = sender->mipi_lp_gen_ctrl_reg;
+ data_reg = sender->mipi_lp_gen_data_reg;
+
+ /* FIXME: wait_for_lp_fifos_empty(sender); */
+ }
+
+ p = data;
+ for (i = 0; i < len / 4; i++) {
+ b1 = *p++;
+ b2 = *p++;
+ b3 = *p++;
+ b4 = *p++;
+
+ REG_WRITE(data_reg, b4 << 24 | b3 << 16 | b2 << 8 | b1);
+ }
+
+ i = len % 4;
+ if (i) {
+ b1 = 0; b2 = 0; b3 = 0;
+
+ switch (i) {
+ case 3:
+ b1 = *p++;
+ b2 = *p++;
+ b3 = *p++;
+ break;
+ case 2:
+ b1 = *p++;
+ b2 = *p++;
+ break;
+ case 1:
+ b1 = *p++;
+ break;
+ }
+
+ REG_WRITE(data_reg, b3 << 16 | b2 << 8 | b1);
+ }
+
+ val = FLD_VAL(len, 23, 8) | FLD_VAL(virtual_channel, 7, 6) |
+ FLD_VAL(data_type, 5, 0);
+
+ REG_WRITE(ctrl_reg, val);
+
+ return 0;
+}
+
+static int send_pkg_prepare(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
+ u8 *data, u16 len)
+{
+ u8 cmd;
+
+ PSB_DEBUG_ENTRY("Prepare to Send type 0x%x pkg\n", data_type);
+
+ switch (data_type) {
+ case DSI_DT_DCS_SHORT_WRITE_0:
+ case DSI_DT_DCS_SHORT_WRITE_1:
+ case DSI_DT_DCS_LONG_WRITE:
+ cmd = *data;
+ break;
+ default:
+ return 0;
+ }
+
+ /*this prevents other package sending while doing msleep*/
+ sender->status = MDFLD_DSI_PKG_SENDER_BUSY;
+
+ /*wait for 120 milliseconds in case exit_sleep_mode just be sent*/
+ if (unlikely(cmd == DCS_ENTER_SLEEP_MODE)) {
+ /*TODO: replace it with msleep later*/
+ mdelay(120);
+ }
+
+ if (unlikely(cmd == DCS_EXIT_SLEEP_MODE)) {
+ /*TODO: replace it with msleep later*/
+ mdelay(120);
+ }
+
+ return 0;
+}
+
+static int send_pkg_done(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
+ u8 *data, u16 len)
+{
+ u8 cmd;
+
+ PSB_DEBUG_ENTRY("Sent type 0x%x pkg\n", data_type);
+
+ switch (data_type) {
+ case DSI_DT_DCS_SHORT_WRITE_0:
+ case DSI_DT_DCS_SHORT_WRITE_1:
+ case DSI_DT_DCS_LONG_WRITE:
+ cmd = *data;
+ break;
+ default:
+ return 0;
+ }
+
+ /*update panel status*/
+ if (unlikely(cmd == DCS_ENTER_SLEEP_MODE)) {
+ sender->panel_mode |= MDFLD_DSI_PANEL_MODE_SLEEP;
+ /*TODO: replace it with msleep later*/
+ mdelay(120);
+ } else if (unlikely(cmd == DCS_EXIT_SLEEP_MODE)) {
+ sender->panel_mode &= ~MDFLD_DSI_PANEL_MODE_SLEEP;
+ /*TODO: replace it with msleep later*/
+ mdelay(120);
+ } else if (unlikely(cmd == DCS_SOFT_RESET)) {
+ /*TODO: replace it with msleep later*/
+ mdelay(5);
+ }
+
+ sender->status = MDFLD_DSI_PKG_SENDER_FREE;
+
+ return 0;
+
+}
+
+static int send_pkg(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
+ u8 *data, u16 len, bool hs)
+{
+ int ret;
+
+ /*handle DSI error*/
+ ret = dsi_error_handler(sender);
+ if (ret) {
+ DRM_ERROR("Error handling failed\n");
+ return -EAGAIN;
+ }
+
+ /* send pkg */
+ PSB_DEBUG_ENTRY("Sending type 0x%x pkg\n", data_type);
+
+ if (sender->status == MDFLD_DSI_PKG_SENDER_BUSY) {
+ DRM_ERROR("sender is busy\n");
+ return -EAGAIN;
+ }
+
+ ret = send_pkg_prepare(sender, data_type, data, len);
+ if (ret) {
+ DRM_ERROR("send_pkg_prepare error\n");
+ return ret;
+ }
+
+ switch (data_type) {
+ case DSI_DT_GENERIC_SHORT_WRITE_0:
+ case DSI_DT_GENERIC_SHORT_WRITE_1:
+ case DSI_DT_GENERIC_SHORT_WRITE_2:
+ case DSI_DT_GENERIC_READ_0:
+ case DSI_DT_GENERIC_READ_1:
+ case DSI_DT_GENERIC_READ_2:
+ case DSI_DT_DCS_SHORT_WRITE_0:
+ case DSI_DT_DCS_SHORT_WRITE_1:
+ case DSI_DT_DCS_READ:
+ ret = send_short_pkg(sender, data_type, data[0], data[1], hs);
+ break;
+ case DSI_DT_GENERIC_LONG_WRITE:
+ case DSI_DT_DCS_LONG_WRITE:
+ ret = send_long_pkg(sender, data_type, data, len, hs);
+ break;
+ }
+
+ send_pkg_done(sender, data_type, data, len);
+
+ /*FIXME: should I query complete and fifo empty here?*/
+
+ return ret;
+}
+
+static int mdfld_dbi_cb_init(struct mdfld_dsi_pkg_sender * sender, struct psb_gtt * pg, int pipe) {
+ uint32_t phy;
+ void __iomem *virt_addr = NULL;
+
+ switch(pipe) {
+ case 0:
+ phy = pg->gtt_phys_start - 0x1000;
+ break;
+ case 2:
+ phy = pg->gtt_phys_start - 0x800;
+ break;
+ default:
+ DRM_ERROR("Unsupported channel\n");
+ return -EINVAL;
+ }
+
+ /*mapping*/
+ virt_addr = ioremap_nocache(phy, 0x800);
+ if(!virt_addr) {
+ DRM_ERROR("Map DBI command buffer error\n");
+ return -ENOMEM;
+ }
+
+ sender->dbi_cb_phy = phy;
+ sender->dbi_cb_addr = virt_addr;
+
+ PSB_DEBUG_ENTRY("DBI command buffer initailized. phy %x, addr %p\n", phy, virt_addr);
+
+ return 0;
+}
+
+static void mdfld_dbi_cb_destroy(struct mdfld_dsi_pkg_sender * sender) {
+ PSB_DEBUG_ENTRY("\n");
+
+ if(sender && sender->dbi_cb_addr)
+ iounmap(sender->dbi_cb_addr);
+}
+
+int mdfld_dsi_send_mcs_long(struct mdfld_dsi_pkg_sender *sender, u8 *data,
+ u32 len, bool hs)
+{
+ unsigned long flags;
+
+ if (!sender || !data || !len) {
+ DRM_ERROR("Invalid parameters\n");
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&sender->lock, flags);
+ send_pkg(sender, DSI_DT_DCS_LONG_WRITE, data, len, hs);
+ spin_unlock_irqrestore(&sender->lock, flags);
+
+ return 0;
+}
+
+int mdfld_dsi_send_mcs_short(struct mdfld_dsi_pkg_sender *sender, u8 cmd,
+ u8 param, u8 param_num, bool hs)
+{
+ u8 data[2];
+ unsigned long flags;
+ u8 data_type;
+
+ if (!sender) {
+ DRM_ERROR("Invalid parameter\n");
+ return -EINVAL;
+ }
+
+ data[0] = cmd;
+
+ if (param_num) {
+ data_type = DSI_DT_DCS_SHORT_WRITE_1;
+ data[1] = param;
+ } else {
+ data_type = DSI_DT_DCS_SHORT_WRITE_0;
+ data[1] = 0;
+ }
+
+ spin_lock_irqsave(&sender->lock, flags);
+ send_pkg(sender, data_type, data, sizeof(data), hs);
+ spin_unlock_irqrestore(&sender->lock, flags);
+
+ return 0;
+}
+
+int mdfld_dsi_send_gen_short(struct mdfld_dsi_pkg_sender *sender, u8 param0,
+ u8 param1, u8 param_num, bool hs)
+{
+ u8 data[2];
+ unsigned long flags;
+ u8 data_type;
+
+ if (!sender || param_num < 0 || param_num > 2) {
+ DRM_ERROR("Invalid parameter\n");
+ return -EINVAL;
+ }
+
+ switch (param_num) {
+ case 0:
+ data_type = DSI_DT_GENERIC_SHORT_WRITE_0;
+ data[0] = 0;
+ data[1] = 0;
+ break;
+ case 1:
+ data_type = DSI_DT_GENERIC_SHORT_WRITE_1;
+ data[0] = param0;
+ data[1] = 0;
+ break;
+ case 2:
+ data_type = DSI_DT_GENERIC_SHORT_WRITE_2;
+ data[0] = param0;
+ data[1] = param1;
+ break;
+ }
+
+ spin_lock_irqsave(&sender->lock, flags);
+ send_pkg(sender, data_type, data, sizeof(data), hs);
+ spin_unlock_irqrestore(&sender->lock, flags);
+
+ return 0;
+}
+
+int mdfld_dsi_send_gen_long(struct mdfld_dsi_pkg_sender *sender, u8 *data,
+ u32 len, bool hs)
+{
+ unsigned long flags;
+
+ if (!sender || !data || !len) {
+ DRM_ERROR("Invalid parameters\n");
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&sender->lock, flags);
+ send_pkg(sender, DSI_DT_GENERIC_LONG_WRITE, data, len, hs);
+ spin_unlock_irqrestore(&sender->lock, flags);
+
+ return 0;
+}
+
+static int __read_panel_data(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
+ u8 *data, u16 len, u32 *data_out, u16 len_out, bool hs)
+{
+ unsigned long flags;
+ struct drm_device *dev = sender->dev;
+ int i;
+ u32 gen_data_reg;
+ int retry = MDFLD_DSI_READ_MAX_COUNT;
+
+ if (!sender || !data_out || !len_out) {
+ DRM_ERROR("Invalid parameters\n");
+ return -EINVAL;
+ }
+
+ /**
+ * do reading.
+ * 0) send out generic read request
+ * 1) polling read data avail interrupt
+ * 2) read data
+ */
+ spin_lock_irqsave(&sender->lock, flags);
+
+ REG_WRITE(sender->mipi_intr_stat_reg, BIT(29));
+
+ if ((REG_READ(sender->mipi_intr_stat_reg) & BIT(29)))
+ DRM_ERROR("Can NOT clean read data valid interrupt\n");
+
+ /*send out read request*/
+ send_pkg(sender, data_type, data, len, hs);
+
+ /*polling read data avail interrupt*/
+ while (retry && !(REG_READ(sender->mipi_intr_stat_reg) & BIT(29))) {
+ udelay(100);
+ retry--;
+ }
+
+ if (!retry) {
+ spin_unlock_irqrestore(&sender->lock, flags);
+ return -ETIMEDOUT;
+ }
+
+ REG_WRITE(sender->mipi_intr_stat_reg, BIT(29));
+
+ /*read data*/
+ if (hs)
+ gen_data_reg = sender->mipi_hs_gen_data_reg;
+ else
+ gen_data_reg = sender->mipi_lp_gen_data_reg;
+
+ for (i = 0; i < len_out; i++)
+ *(data_out + i) = REG_READ(gen_data_reg);
+
+ spin_unlock_irqrestore(&sender->lock, flags);
+
+ return 0;
+}
+
+static int mdfld_dsi_read_gen(struct mdfld_dsi_pkg_sender *sender, u8 param0,
+ u8 param1, u8 param_num, u32 *data, u16 len, bool hs)
+{
+ u8 data_type;
+ u8 cmd[2];
+
+ switch (param_num) {
+ case 0:
+ data_type = DSI_DT_GENERIC_READ_0;
+ cmd[0] = 0;
+ cmd[1] = 0;
+ break;
+ case 1:
+ data_type = DSI_DT_GENERIC_READ_1;
+ cmd[0] = param0;
+ cmd[1] = 0;
+ break;
+ case 2:
+ data_type = DSI_DT_GENERIC_READ_2;
+ cmd[0] = param0;
+ cmd[1] = param1;
+ break;
+ default:
+ DRM_ERROR("Invalid parameters\n");
+ return -EINVAL;
+ }
+
+ return __read_panel_data(sender, data_type, cmd, sizeof(cmd),
+ data, len, hs);
+}
+
+int mdfld_dsi_read_mcs(struct mdfld_dsi_pkg_sender *sender, u8 cmd,
+ u32 *data, u16 len, bool hs)
+{
+ if (!sender || !data || !len) {
+ DRM_ERROR("Invalid parameters\n");
+ return -EINVAL;
+ }
+
+ return __read_panel_data(sender, DSI_DT_DCS_READ, &cmd, 1,
+ data, len, hs);
+}
+
+int mdfld_dsi_write_mem_start(struct mdfld_dsi_pkg_sender *sender)
+{
+ struct drm_device *dev = sender->dev;
+ u32 index = 0;
+ u8 *cb = (u8 *)sender->dbi_cb_addr;
+ int retry;
+
+ if (!sender) {
+ DRM_ERROR("Invalid parameter\n");
+ return -EINVAL;
+ }
+
+ if (!sender->dbi_pkg_support) {
+ DRM_ERROR("No DBI pkg sending on this sender\n");
+ return -ENOTSUPP;
+ }
+
+ if (!spin_trylock(&sender->lock))
+ return -EAGAIN;
+
+ /**
+ * query whether DBI FIFO is empty,
+ * if not wait it becoming empty
+ */
+ retry = MDFLD_DSI_DBI_FIFO_TIMEOUT;
+ while (retry && !(REG_READ(sender->mipi_gen_fifo_stat_reg) & BIT(27))) {
+ udelay(500);
+ retry--;
+ }
+
+ /*if DBI FIFO timeout, drop this frame*/
+ if (!retry) {
+ spin_unlock(&sender->lock);
+ return 0;
+ }
+
+ *(cb + (index++)) = write_mem_start;
+
+ REG_WRITE(sender->mipi_cmd_len_reg, 1);
+ REG_WRITE(sender->mipi_cmd_addr_reg, sender->dbi_cb_phy | BIT(0) | BIT(1));
+
+ retry = MDFLD_DSI_DBI_FIFO_TIMEOUT;
+ while (retry && (REG_READ(sender->mipi_cmd_addr_reg) & BIT(0))) {
+ udelay(1);
+ retry--;
+ }
+
+ spin_unlock(&sender->lock);
+
+ return 0;
+}
+
+int mdfld_dsi_pkg_sender_init(struct mdfld_dsi_connector * dsi_connector, int pipe)
+{
+ int ret;
+ struct mdfld_dsi_pkg_sender * pkg_sender;
+ struct mdfld_dsi_config * dsi_config = mdfld_dsi_get_config(dsi_connector);
+ struct drm_device * dev = dsi_config->dev;
+ struct drm_psb_private * dev_priv = dev->dev_private;
+ struct psb_gtt * pg = dev_priv->pg;
+ u32 mipi_val = 0;
+
+ PSB_DEBUG_ENTRY("\n");
+
+ if(!dsi_connector) {
+ DRM_ERROR("Invalid parameter\n");
+ return -EINVAL;
+ }
+
+ pkg_sender = dsi_connector->pkg_sender;
+
+ if(!pkg_sender || IS_ERR(pkg_sender)) {
+ pkg_sender = kzalloc(sizeof(struct mdfld_dsi_pkg_sender), GFP_KERNEL);
+ if(!pkg_sender) {
+ DRM_ERROR("Create DSI pkg sender failed\n");
+ return -ENOMEM;
+ }
+
+ dsi_connector->pkg_sender = (void *)pkg_sender;
+ }
+
+ pkg_sender->dev = dev;
+ pkg_sender->dsi_connector = dsi_connector;
+ pkg_sender->pipe = pipe;
+ pkg_sender->pkg_num = 0;
+ pkg_sender->panel_mode = 0;
+ pkg_sender->status = MDFLD_DSI_PKG_SENDER_FREE;
+
+ /*int dbi command buffer*/
+ if(dsi_config->type == MDFLD_DSI_ENCODER_DBI) {
+ pkg_sender->dbi_pkg_support = 1;
+ ret = mdfld_dbi_cb_init(pkg_sender, pg, pipe);
+ if(ret) {
+ DRM_ERROR("DBI command buffer map failed\n");
+ goto mapping_err;
+ }
+ }
+
+ /*init regs*/
+ if(pipe == 0) {
+ pkg_sender->dpll_reg = MRST_DPLL_A;
+ pkg_sender->dspcntr_reg = DSPACNTR;
+ pkg_sender->pipeconf_reg = PIPEACONF;
+ pkg_sender->dsplinoff_reg = DSPALINOFF;
+ pkg_sender->dspsurf_reg = DSPASURF;
+ pkg_sender->pipestat_reg = PIPEASTAT;
+ } else if (pipe == 2) {
+ pkg_sender->dpll_reg = MRST_DPLL_A;
+ pkg_sender->dspcntr_reg = DSPCCNTR;
+ pkg_sender->pipeconf_reg = PIPECCONF;
+ pkg_sender->dsplinoff_reg = DSPCLINOFF;
+ pkg_sender->dspsurf_reg = DSPCSURF;
+ pkg_sender->pipestat_reg = PIPECSTAT;
+ }
+
+ pkg_sender->mipi_intr_stat_reg = MIPI_INTR_STAT_REG(pipe);
+ pkg_sender->mipi_lp_gen_data_reg = MIPI_LP_GEN_DATA_REG(pipe);
+ pkg_sender->mipi_hs_gen_data_reg = MIPI_HS_GEN_DATA_REG(pipe);
+ pkg_sender->mipi_lp_gen_ctrl_reg = MIPI_LP_GEN_CTRL_REG(pipe);
+ pkg_sender->mipi_hs_gen_ctrl_reg = MIPI_HS_GEN_CTRL_REG(pipe);
+ pkg_sender->mipi_gen_fifo_stat_reg = MIPI_GEN_FIFO_STAT_REG(pipe);
+ pkg_sender->mipi_data_addr_reg = MIPI_DATA_ADD_REG(pipe);
+ pkg_sender->mipi_data_len_reg = MIPI_DATA_LEN_REG(pipe);
+ pkg_sender->mipi_cmd_addr_reg = MIPI_CMD_ADD_REG(pipe);
+ pkg_sender->mipi_cmd_len_reg = MIPI_CMD_LEN_REG(pipe);
+
+ /*init lock*/
+ spin_lock_init(&pkg_sender->lock);
+
+ if (get_panel_type(dev, pipe) != TC35876X) {
+ /**
+ * For video mode, don't enable DPI timing output here,
+ * will init the DPI timing output during mode setting.
+ */
+ if (dsi_config->type == MDFLD_DSI_ENCODER_DPI)
+ mipi_val = PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX;
+ else if (dsi_config->type == MDFLD_DSI_ENCODER_DBI)
+ mipi_val = PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX
+ | TE_TRIGGER_GPIO_PIN;
+ else
+ DRM_ERROR("Bad DSI encoder type\n");
+
+ if (pipe == 0)
+ mipi_val |= 0x2;
+
+ REG_WRITE(MIPI_PORT_CONTROL(pipe), mipi_val);
+ REG_READ(MIPI_PORT_CONTROL(pipe));
+
+ /* do dsi controller init */
+ mdfld_dsi_controller_init(dsi_config, pipe);
+ }
+
+ PSB_DEBUG_ENTRY("initialized\n");
+
+ return 0;
+
+mapping_err:
+ kfree(pkg_sender);
+ dsi_connector->pkg_sender = NULL;
+
+ return ret;
+}
+
+void mdfld_dsi_pkg_sender_destroy(struct mdfld_dsi_pkg_sender * sender)
+{
+ if(!sender || IS_ERR(sender))
+ return;
+
+ /*free mapped command buffer*/
+ mdfld_dbi_cb_destroy(sender);
+
+ /*free*/
+ kfree(sender);
+
+ PSB_DEBUG_ENTRY("destroyed\n");
+}
+
+
--- /dev/null
+/*
+ * Copyright © 2010 Intel 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 (including the next
+ * paragraph) 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.
+ *
+ * Authors:
+ * Jackie Li<yaodong.li@intel.com>
+ */
+#ifndef __MDFLD_DSI_PKG_SENDER_H__
+#define __MDFLD_DSI_PKG_SENDER_H__
+
+#include <linux/kthread.h>
+
+#define MDFLD_MAX_DCS_PARAM 8
+
+struct mdfld_dsi_pkg_sender {
+ struct drm_device * dev;
+ struct mdfld_dsi_connector * dsi_connector;
+ u32 status;
+
+ u32 panel_mode;
+
+ int pipe;
+
+ spinlock_t lock;
+
+ u32 pkg_num;
+
+ int dbi_pkg_support;
+
+ u32 dbi_cb_phy;
+ void __iomem *dbi_cb_addr;
+
+ /*registers*/
+ u32 dpll_reg;
+ u32 dspcntr_reg;
+ u32 pipeconf_reg;
+ u32 pipestat_reg;
+ u32 dsplinoff_reg;
+ u32 dspsurf_reg;
+
+ u32 mipi_intr_stat_reg;
+ u32 mipi_lp_gen_data_reg;
+ u32 mipi_hs_gen_data_reg;
+ u32 mipi_lp_gen_ctrl_reg;
+ u32 mipi_hs_gen_ctrl_reg;
+ u32 mipi_gen_fifo_stat_reg;
+ u32 mipi_data_addr_reg;
+ u32 mipi_data_len_reg;
+ u32 mipi_cmd_addr_reg;
+ u32 mipi_cmd_len_reg;
+};
+
+/*DCS definitions*/
+#define DCS_SOFT_RESET 0x01
+#define DCS_ENTER_SLEEP_MODE 0x10
+#define DCS_EXIT_SLEEP_MODE 0x11
+#define DCS_SET_DISPLAY_OFF 0x28
+#define DCS_SET_DISPLAY_ON 0x29
+#define DCS_SET_COLUMN_ADDRESS 0x2a
+#define DCS_SET_PAGE_ADDRESS 0x2b
+#define DCS_WRITE_MEM_START 0x2c
+#define DCS_SET_TEAR_OFF 0x34
+#define DCS_SET_TEAR_ON 0x35
+
+extern int mdfld_dsi_pkg_sender_init(struct mdfld_dsi_connector * dsi_connector, int pipe);
+extern void mdfld_dsi_pkg_sender_destroy(struct mdfld_dsi_pkg_sender * sender);
+int mdfld_dsi_write_mem_start(struct mdfld_dsi_pkg_sender *sender);
+int mdfld_dsi_send_mcs_short(struct mdfld_dsi_pkg_sender *sender, u8 cmd,
+ u8 param, u8 param_num, bool hs);
+int mdfld_dsi_send_mcs_long(struct mdfld_dsi_pkg_sender *sender, u8 *data,
+ u32 len, bool hs);
+int mdfld_dsi_send_gen_short(struct mdfld_dsi_pkg_sender *sender, u8 param0,
+ u8 param1, u8 param_num, bool hs);
+int mdfld_dsi_send_gen_long(struct mdfld_dsi_pkg_sender *sender, u8 *data,
+ u32 len, bool hs);
+
+/*read interfaces*/
+int mdfld_dsi_read_mcs(struct mdfld_dsi_pkg_sender *sender, u8 cmd,
+ u32 *data, u16 len, bool hs);
+
+#endif
--- /dev/null
+/*
+ * Copyright © 2010 Intel 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 (including the next
+ * paragraph) 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.
+ *
+ * Authors:
+ * Jim Bish <jim.bish@@intel.com>
+ */
+
+#ifdef CONFIG_MDFD_GL3
+
+#include "mdfld_gl3.h"
+#include "psb_powermgmt.h"
+
+void gl3_enable(void)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) gpDrmDevice->dev_private;
+
+ PSB_DEBUG_ENTRY("gl3_enable called on platform %x\n", dev_priv->platform_rev_id);
+ if (!ospm_power_using_hw_begin(OSPM_GRAPHICS_ISLAND, true))
+ return;
+ MDFLD_GL3_WRITE(MDFLD_GL3_ENABLE_CACHE, MDFLD_GL3_CONTROL);
+ PSB_DEBUG_GENERAL("gl3 cache enabled with mask %x\n",
+ MDFLD_GL3_ENABLE_CACHE);
+ ospm_power_using_hw_end(OSPM_GRAPHICS_ISLAND);
+}
+
+void gl3_disable(void)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) gpDrmDevice->dev_private;
+
+ PSB_DEBUG_ENTRY("gl3_disable called on platform %x\n", dev_priv->platform_rev_id);
+ if (!ospm_power_using_hw_begin(OSPM_GRAPHICS_ISLAND, true))
+ return;
+ MDFLD_GL3_WRITE(MDFLD_GL3_DISABLE_CACHE, MDFLD_GL3_CONTROL);
+ PSB_DEBUG_GENERAL("gl3 cache disabled with mask %x\n",
+ MDFLD_GL3_DISABLE_CACHE);
+ ospm_power_using_hw_end(OSPM_GRAPHICS_ISLAND);
+}
+
+void gl3_invalidate(void)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) gpDrmDevice->dev_private;
+
+ PSB_DEBUG_ENTRY("gl3_invalidate called on platform %x\n", dev_priv->platform_rev_id);
+ if (!ospm_power_using_hw_begin(OSPM_GRAPHICS_ISLAND, true))
+ return;
+ // Invalidate the cache
+ MDFLD_GL3_WRITE(MDFLD_GL3_INVALIDATE_CACHE, MDFLD_GL3_CONTROL);
+ PSB_DEBUG_GENERAL("gl3 cache invalidated with mask %x\n",
+ MDFLD_GL3_INVALIDATE_CACHE);
+ ospm_power_using_hw_end(OSPM_GRAPHICS_ISLAND);
+}
+
+void gl3_flush(void)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) gpDrmDevice->dev_private;
+
+ PSB_DEBUG_ENTRY("gl3_flush called on platform %x\n", dev_priv->platform_rev_id);
+ if (!ospm_power_using_hw_begin(OSPM_GRAPHICS_ISLAND, true))
+ return;
+ // Flush the cache
+ MDFLD_GL3_WRITE(MDFLD_GL3_FLUSH_CACHE, MDFLD_GL3_CONTROL);
+ PSB_DEBUG_GENERAL("gl3 cache flushed with mask %x\n",
+ MDFLD_GL3_FLUSH_CACHE);
+ ospm_power_using_hw_end(OSPM_GRAPHICS_ISLAND);
+}
+
+void gl3_reset(void)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) gpDrmDevice->dev_private;
+
+ PSB_DEBUG_ENTRY("gl3_reset called on platform %x\n", dev_priv->platform_rev_id);
+ if (!ospm_power_using_hw_begin(OSPM_GRAPHICS_ISLAND, true))
+ return;
+ // Reset the cache
+ MDFLD_GL3_WRITE(MDFLD_GL3_SOFT_RESET_ENABLE, MDFLD_GL3_G_CONTROL);
+ PSB_DEBUG_GENERAL("gl3 cache soft reset with mas %x\n",
+ MDFLD_GL3_SOFT_RESET_ENABLE);
+ ospm_power_using_hw_end(OSPM_GRAPHICS_ISLAND);
+}
+
+#endif /* CONFIG_MDFD_GL3 */
--- /dev/null
+/*
+ * Copyright © 2010 Intel 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 (including the next
+ * paragraph) 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.
+ *
+ * Authors:
+ * Jim Bish <jim.bish@intel.com>
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include "psb_drm.h"
+#include "psb_drv.h"
+#include "psb_fb.h"
+#include "psb_reg.h"
+#include "psb_intel_reg.h"
+#include "psb_msvdx.h"
+#include "pnw_topaz.h"
+#include <drm/drm_pciids.h>
+#include "pvr_drm_shared.h"
+#include "psb_powermgmt.h"
+#include <linux/cpu.h>
+#include <linux/notifier.h>
+#include <linux/spinlock.h>
+#include <linux/pm_runtime.h>
+
+#ifdef CONFIG_MDFD_GL3
+
+/*
+ * GL3 Control
+ */
+
+#define MDFLD_GCL_CR_CTL2 0xB0000
+#define MDFLD_GCL_ERR_ADDR 0xB0004 /* address at location is the address that had the error */
+#define MDFLD_GCL_ERR_STATUS 0xB0008
+
+#define MDFLD_IMG_MASK 0x20A8 /* unmask bit 21 to get GL3 interrupts */
+/*
+ * GL3 registers and bits
+ */
+
+#define MDFLD_GL3_CONTROL 0x2100
+#define MDFLD_GL3_USE_WRT_INVAL 0x2104
+#define MDFLD_GL3_STATUS 0x2108
+#define MDFLD_GL3_G_CONTROL 0x20FC
+#define MDFLD_GL3_SOFT_RESET_ENABLE (1<<4)
+
+#define MDFLD_GL3_DISABLE (1<<31)
+#define MDFLD_GL3_BYP_PREQ2_USSE3 (1<<29)
+#define MDLFD_GL3_BYP_PREQ2_USSE2 (1<<28)
+#define MDFLD_GL3_BYP_PREQ2_PDS (1<<27)
+#define MDFLD_GL3_BYP_PREQ2_USEC (1<<26)
+#define MDFLD_GL3_FLUSH (1<<25)
+#define MDFLD_GL3_FLUSH_CTL (1<<24)
+#define MDFLD_GL3_BYP_CPU_COH (1<<23)
+#define MDFLD_GL3_BYP_VED (1<<21)
+#define MDFLD_GL3_BYP_VEC (1<<20)
+#define MDFLD_GL3_BYP_GFX (1<<19)
+#define MDFLD_GL3_BYP_PREQ1_USE1 (1<<18)
+#define MDFLD_GL3_BYP_PREQ1_USE0 (1<<17)
+#define MDFLD_GL3_BYP_PREQ1_ISPZ (1<<16)
+#define MDFLD_GL3_BYP_PREQ1_ISPP (1<<15)
+#define MDFLD_GL3_BYP_PREQ1_TSPP (1<<14)
+#define MDFLD_GL3_BYP_PREQ1_PBE (1<<13)
+#define MDFLD_GL3_BYP_PREQ1_VDM (1<<12)
+#define MDFLD_GL3_BYP_PREQ1_TA (1<<11)
+#define MDFLD_GL3_BYP_PREQ1_MADD (1<<10)
+#define MDFLD_GL3_BYP_PREQ1_MMU (1<<9)
+#define MDFLD_GL3_USE_INVAL_REQ_USSE3 (1<<8)
+#define MDFLD_GL3_USE_INVAL_REQ_USSE2 (1<<7)
+#define MDFLD_GL3_USE_INVAL_REQ_USSE1 (1<<6)
+#define MDFLD_GL3_USE_INVAL_REQ_USSE0 (1<<5)
+#define MDFLD_GL3_BYP_WR (1<<4)
+#define MDFLD_GL3_IGN_VED_HINT (1<<3)
+#define MDFLD_GL3_IGN_VEC_HINT (1<<2)
+#define MDFLD_GL3_INVALIDATE (1<<1)
+#define MDFLD_GL3_PAUSE (1)
+
+/*
+ * GL3 Masks
+ */
+
+#define MDFLD_GL3_ENABLE_CACHE (MDFLD_GL3_BYP_PREQ2_USSE3 | MDLFD_GL3_BYP_PREQ2_USSE2 | \
+ MDFLD_GL3_BYP_PREQ1_USE1 | MDFLD_GL3_BYP_PREQ1_USE0 | \
+ MDFLD_GL3_BYP_VED | MDFLD_GL3_BYP_VEC | \
+ MDFLD_GL3_BYP_PREQ1_ISPZ | MDFLD_GL3_BYP_PREQ1_PBE | MDFLD_GL3_BYP_PREQ1_VDM | \
+ MDFLD_GL3_BYP_PREQ1_TA | MDFLD_GL3_BYP_PREQ1_MMU | MDFLD_GL3_USE_INVAL_REQ_USSE3 | \
+ MDFLD_GL3_USE_INVAL_REQ_USSE2 | MDFLD_GL3_USE_INVAL_REQ_USSE1 | MDFLD_GL3_USE_INVAL_REQ_USSE0 | \
+ MDFLD_GL3_IGN_VEC_HINT)
+
+#define MDFLD_GL3_INVALIDATE_CACHE (MDFLD_GL3_ENABLE_CACHE | MDFLD_GL3_INVALIDATE)
+
+#define MDFLD_GL3_FLUSH_CACHE (MDFLD_GL3_ENABLE_CACHE | MDFLD_GL3_FLUSH)
+
+#define MDFLD_GL3_DISABLE_CACHE (MDFLD_GL3_ENABLE_CACHE | MDFLD_GL3_DISABLE)
+
+// GL3
+#define MDFLD_GL3_WRITE(_val, _offs ) \
+ iowrite32(_val, dev_priv->gl3_reg + (_offs))
+#define MDFLD_GL3_READ(_offs) \
+ ioread32(dev_priv->gl3_reg + (_offs))
+
+void gl3_enable(void);
+void gl3_invalidate(void);
+void gl3_flush(void);
+void gl3_reset(void);
+void gl3_disable(void);
+
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2010, Intel Corporation.
+ *
+ * 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 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.
+ *
+ * Authors:
+ * jim liu <jim.liu@intel.com>
+ */
+
+
+#ifndef MDFLD_HDCP_H
+#define MDFLD_HDCP_H
+
+#define MAX_HDCP_DEVICES 127
+#define KSV_SIZE 5
+#define V_SIZE 20
+
+#define HDCP_MAX_RETRY_STATUS 1500
+
+#define HDCP_100MS_DELAY 100 //
+
+typedef struct _hdcp_priv_data {
+ int enabled;
+ int drmFD;
+ int output_id;
+} hdcp_priv_data_t;
+
+typedef struct _sqword {
+ union {
+ unsigned long long quad_part;//ULONGLONG QuadPart;
+ struct {
+ unsigned long low_part;
+ unsigned long high_part;
+ } u;
+ struct {
+ uint8_t byte[8];
+ };
+ };
+} sqword_t;
+
+// A quadword size member
+//
+typedef struct _hqword {
+ union {
+ struct {
+ uint64_t major_part: 40; // lower 40 bits
+ uint64_t unused1: 24;
+ };
+ struct {
+ unsigned major_part_low: 32; // lower 32 bits
+ unsigned major_part_high: 8; // lower bits
+ unsigned unused2: 24;
+ };
+ struct {
+ uint8_t byte[8];
+ };
+ };
+} hqword_t;
+
+// HDCP related definitions are kept here for common usability between
+// Integrated and External SDVO based HDCP operations
+//I2C Address for HDCP cummnication with Receiver
+#define RX_ADDRESS 0x74000000 // HDCP Port I2C Address (Single Link)
+ // shifted for call back function
+
+//I2C Subaddress Defines - As per the HDCP Spec
+// Downstream spec does not specify which is MSB and LSB?
+#define RX_BKSV_0 0x00 // BKSV[7:0]
+#define RX_BKSV_1 0x01 // BKSV[15:8]
+#define RX_BKSV_2 0x02 // BKSV[23:16]
+#define RX_BKSV_3 0x03 // BKSV[31:24]
+#define RX_BKSV_4 0x04 // BKSV[39:32]
+#define RX_RI_HIGH 0x08 // Ri'[7:0]
+#define RX_RI_LOW 0x09 // Ri'[15:8]
+#define RX_AKSV_0 0x10 // AKSV[7:0]
+#define RX_AKSV_1 0x11 // AKSV[15:8]
+#define RX_AKSV_2 0x12 // AKSV[23:16]
+#define RX_AKSV_3 0x13 // AKSV[31:24]
+#define RX_AKSV_4 0x14 // AKSV[39:32]... write this byte last
+#define RX_AINFO 0x15 // Receiver register to inform it to enable 1.1 features
+#define RX_AN_0 0x18 // An[7:0]
+#define RX_AN_1 0x19 // An[15:8]
+#define RX_AN_2 0x1A // An[23:16]
+#define RX_AN_3 0x1B // An[31:24]
+#define RX_AN_4 0x1C // An[39:32]
+#define RX_AN_5 0x1D // An[47:40]
+#define RX_AN_6 0x1E // An[55:48]
+#define RX_AN_7 0x1F // An[63:56]
+#define RX_VPRIME_H0_0 0x20 // V'[7:0]
+#define RX_VPRIME_H0_1 0x21 // V'[15:8]
+#define RX_VPRIME_H0_2 0x22 // V'[23:16]
+#define RX_VPRIME_H0_3 0x23 // V'[31:24]
+#define RX_VPRIME_H1_0 0x24 // V'[39:32]
+#define RX_VPRIME_H1_1 0x25 // V'[47:40]
+#define RX_VPRIME_H1_2 0x26 // V'[55:48]
+#define RX_VPRIME_H1_3 0x27 // V'[63:56]
+#define RX_VPRIME_H2_0 0x28 // V'[71:64]
+#define RX_VPRIME_H2_1 0x29 // V'[79:72]
+#define RX_VPRIME_H2_2 0x2A // V'[87:80]
+#define RX_VPRIME_H2_3 0x2B // V'[95:88]
+#define RX_VPRIME_H3_0 0x2C // V'[103:96]
+#define RX_VPRIME_H3_1 0x2D // V'[111:104]
+#define RX_VPRIME_H3_2 0x2E // V'[119:112]
+#define RX_VPRIME_H3_3 0x2F // V'[127:120]
+#define RX_VPRIME_H4_0 0x30 // V'[135:128]
+#define RX_VPRIME_H4_1 0x31 // V'[143:136]
+#define RX_VPRIME_H4_2 0x32 // V'[151:144]
+#define RX_VPRIME_H4_3 0x33 // V'[159:152]
+#define RX_BCAPS 0x40 // [7] RSVD, [6] Repeater, [5] Ready, [4] Fast, [3:2] RSVD, [1] Features, [0] Fast_reauthentication
+#define RX_BSTATUS_0 0x41 // [7] MAX_DEVS_EXCEEDED, [6:0] DEVICE_COUNT
+#define RX_BSTATUS_1 0x42 // [15:14] RSVD, [13] HDMI_RSVD, [12] HDMI_MODE, [11] MAX_CASCADE_EXCEEDED, [10:8] DEPTH
+#define RX_KSV_FIFO 0x43
+
+typedef enum _mdfld_hdcp_rx_data_type_enum {
+ RX_TYPE_BKSV_DATA = 0,
+ RX_TYPE_BCAPS = 1,
+ RX_TYPE_BSTATUS = 2,
+ RX_TYPE_REPEATER_KSV_LIST = 3,
+ RX_TYPE_REPEATER_PRIME_V = 4,
+ RX_TYPE_RI_DATA = 5,
+ RX_TYPE_BINFO = 6
+} mdfld_hdcp_rx_data_type_en;
+
+typedef struct _hdcp_bstatus {
+ unsigned device_count : 7; // [6:0] Total Number of Receiver Devices (excluding repeaters) attached
+ unsigned max_devices_exceeded : 1; // [7] Topology Error. Greater than 127 devices attached
+ unsigned repeater_depth : 3; // [10:8] Repeater depth
+ unsigned max_cascade_exceeded : 1; // [11] Topology Error. Greater than 7 levels of Repeater attached
+ unsigned reserved : 20; // [31:12] Reserved for future expansion
+} hdcp_bstatus_t;
+
+//
+// BCAPS
+//
+typedef union _hdcp_rx_bcaps
+{
+ uint8_t value;
+ struct {
+ uint8_t fast_reauthantication : 1; // bit 0
+ uint8_t b1_1features_supported : 1; // bit 1
+ uint8_t reserved : 2; // bi 3:2
+ uint8_t fast_transfer : 1; // bit 4 ( TRUE = transfer speed at 400 kHz FALSE = transfer speed at 100 Khz)
+ uint8_t ksv_fifo_ready : 1; // bit 5
+ uint8_t is_reapeater : 1; // bit 6
+ uint8_t reserved1 : 1; // bit 7
+ };
+}hdcp_rx_bcaps_t;
+
+//
+// BSTATUS
+//
+typedef union _hdcp_rx_bstatus
+{
+ uint16_t value;
+ struct {
+ uint16_t device_count : 7; // bit 6:0
+ uint16_t max_devs_exceeded : 1; // bit 7
+ uint16_t depth : 3; // bit 10:8
+ uint16_t max_cascade_exceeded : 1; // bit 11
+ uint16_t rx_in_hdmi_mode : 1; // bit 12
+ uint16_t rserved : 3; // bit 15:13
+ };
+}hdcp_rx_bstatus_t;
+
+// HDCP authentication step
+typedef enum _hdcp_authentication_step {
+ HDCP_AUTHENTICATION_STEP_NONE = 0,
+ HDCP_AUTHENTICATION_STEP_1 = 1,
+ HDCP_AUTHENTICATION_STEP_2 = 2,
+} hdcp_authentication_step_t;
+
+// KSV_GET
+typedef struct _aksv_get {
+ uint8_t uc_aksv[CP_HDCP_KEY_SELECTION_VECTOR_SIZE];
+} aksv_get_t;
+
+int hdcp_init(void **data, int drmFD, int output_id);
+int hdcp_uninit(void * data);
+#endif /* MDFLD_HDCP_H */
--- /dev/null
+/*
+ * Copyright (c) 2010, Intel Corporation.
+ *
+ * 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 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.
+ *
+ * Authors:
+ * jim liu <jim.liu@intel.com>
+ */
+
+
+#ifndef MDFLD_HDCP_IF_H
+#define MDFLD_HDCP_IF_H
+
+// Constants
+#define CP_HDCP_KEY_SELECTION_VECTOR_SIZE 5
+
+// Protection level (HDCP)
+typedef enum _cp_protection_level_hdcp {
+ CP_PROTECTION_LEVEL_HDCP_OFF = 0,
+ CP_PROTECTION_LEVEL_HDCP_ON = 1,
+} cp_protection_level_hdcp_t;
+
+// Protection type
+typedef enum _cp_protection_type {
+ CP_PROTECTION_TYPE_UNKNOWN = 0x80000000,
+ CP_PROTECTION_TYPE_NONE = 0x00000000,
+ CP_PROTECTION_TYPE_HDCP = 0x00000001,
+ CP_PROTECTION_TYPE_MASK = 0x80000001,
+} cp_protection_type_t;
+
+typedef enum _cp_status {
+ STATUS_UNSUCCESSFUL = 0x80000000,
+ STATUS_SUCCESS = 0x00000000,
+ STATUS_NOT_SUPPORTED = 0x00000001,
+ STATUS_INVALID_DEVICE_REQUEST = 0x00000002,
+ STATUS_REVOKED_HDCP_DEVICE_ATTACHED = 0x00000003,
+ STATUS_DATA_ERROR = 0x00000004,
+ STATUS_PENDING = 0x00000005,
+ STATUS_INVALID_PARAMETER = 0x00000006,
+} cp_status_t;
+
+// KSV
+typedef struct _ksv_t {
+ uint8_t ab_ksv[CP_HDCP_KEY_SELECTION_VECTOR_SIZE];
+} ksv_t;
+
+// HDCP
+typedef struct _hdcp_data {
+ uint32_t ksv_list_length; // Length of the revoked KSV list (set)
+ //ksv_t aksv; // KSV of attached device
+ //ksv_t bksv; // KSV of attached device
+ ksv_t * ksv_list; // List of revoked KSVs (set)
+ int perform_second_step; // True when the second authentication step is requested (get)
+ int is_repeater; // True when a repeater is attached to the connector (get and set)
+} hdcp_data_t;
+
+// CP Parameters
+typedef struct _cp_parameters {
+ uint32_t protect_type_mask; // Protection type mask (get and set)
+ uint32_t level; // Protection level (get and set)
+ hdcp_data_t hdcp; // HDCP specific data (get and set)
+} cp_parameters_t;
+
+extern uint32_t hdcp_set_cp_data(cp_parameters_t* cp);
+extern uint32_t hdcp_get_cp_data(cp_parameters_t* cp);
+void mdfld_hdcp_init(struct mid_intel_hdmi_priv *p_hdmi_priv);
+
+#endif /* MDFLD_HDCP_IF_H */
--- /dev/null
+/*
+ * Copyright (c) 2010, Intel Corporation.
+ *
+ * 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 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.
+ *
+ * Authors:
+ * jim liu <jim.liu@intel.com>
+ */
+
+#ifndef MDFLD_HDCP_REG_H
+#define MDFLD_HDCP_REG_H
+
+/* Integrated HDMI specific registers */
+
+#define RESERVED2(x,y) x##y
+#define RESERVED1(x,y) RESERVED2(x,y)
+#define RANDOMNUMBER __LINE__ // __COUNTER__
+#define UNIQUENAME(ValueName) RESERVED1(ValueName, RANDOMNUMBER)
+
+/* TBD: This may change when tested on actual system */
+#define HDCP_MAX_RI_QUERY_COUNT 4
+#define HDCP_MAX_NUM_DWORDS 4 //128 bits
+#define HDCP_MAX_RANDOMNUM_LENGTH 2 //In DWORD => 64 bits
+#define HDCP_MAX_RETRY_DISABLE 2
+/*All sizes are defined in bytes */
+#define HDCP_SIZEOF_AKSV 8
+#define HDCP_SIZEOF_BKSV 8
+#define HDCP_SIZEOF_AN 5
+#define HDCP_SIZEOF_RI 2
+#define HDCP_ENCRYPTED_KEY_SIZE 12 //Akeys, IV and MAC
+#define HDCP_NUM_AKEYS 40
+#define HDCP_NEXT_RI_FRAME 126
+#define HDCP_MAX_RANDOM_NUM_SIZE 4//in dwords
+
+#define HDCP_CONVERT_BIG_ENDIAN(x) (((x&0x000000ff)<<24)|\
+ ((x&0x0000ff00)<<8)|\
+ ((x&0x00ff0000)>>8)|\
+ ((x&0xff000000)>>24))
+
+#define HDCP_MAX_AN_RETRY 100
+
+#define HDCP_AN_LO_INDEX 0
+#define HDCP_AN_HI_INDEX 1
+
+static uint32_t hdcp_invalid_an_list[6][2] =
+{
+ {0x881cf9e4, 0x38155bf4},
+ {0xb0e81640, 0xb5cac2ec},
+ {0x514fa3e7, 0x5bbb3806},
+ {0xd1b4923a, 0x6172afbb},
+ {0x0c16fd1c, 0x1b28baf5},
+ {0x00000000, 0x00000000}
+};
+
+/* HDMI HDCP Regs */
+/* HDCP config */
+
+typedef enum _mdfld_hdcp_config_enum {
+ HDCP_Off = 0,
+ HDCP_CAPTURE_AN = 1,
+ HDCP_DECRYPT_KEYS = 2,
+ HDCP_AUTHENTICATE_AND_ENCRYPT = 3,
+ HDCP_UNIQUE_MCH_ID = 5,
+ HDCP_ENCRYPT_KEYS = 6,
+ HDCP_CYPHER_CHECK_MODE = 7
+} mdfld_hdcp_config_en;
+
+#define MDFLD_HDCP_CONFIG_REG 0x61400
+ #define MDFLD_HDCP_CONFIG_PRESERVED_BITS BITRANGE(3,31)
+typedef union _mdfld_hdcp_config {
+ uint32_t value;
+
+ struct{
+ uint32_t hdcp_config : 3; //bit 2:0; uses HDCP_CONFIGURATION_EN
+ uint32_t UNIQUENAME(Reserved): 29;//bit 3:31
+ };
+} mdfld_hdcp_config_t;
+
+
+/* HDCP_STATUS */
+
+#define MDFLD_HDCP_STATUS_REG 0x61448
+ #define MDFLD_HDCP_STATUS_PRESERVED_BITS BITRANGE(24,31)
+typedef union _mdfld_hdcp_status {
+ uint32_t value;
+
+ struct{
+ uint32_t ainfo : 8; //Bit 7:0
+ uint32_t frame_count : 8; //Bit 15:8
+ uint32_t cipher_hdcp_status : 1; //Bit 16
+ uint32_t cipher_an_status : 1; //Bit 17
+ uint32_t cipher_ri_ready_status : 1; //Bit 18
+ uint32_t cipher_ri_match_status : 1; //Bit 19
+ uint32_t cipher_encrypting_status : 1; //Bit 20
+ uint32_t cipher_ready_for_encryption : 1; //Bit 21
+ uint32_t cipher_mch_id_ready : 1; //Bit 22
+ uint32_t cipher_mac_status : 1; //Bit 23
+ uint32_t UNIQUENAME(Reserved) : 8; //Bit 31:24
+ };
+} mdfld_hdcp_status_t;
+
+
+/* HDCP_RI */
+#define MDFLD_HDCP_RECEIVER_RI_REG 0x61418
+ #define MDFLD_HDCP_RECEIVER_RI_PRESERVED_BITS BITRANGE(16,31)
+typedef union _mdfld_hdcp_receiver_ri {
+ uint32_t value;
+
+ struct{
+ uint32_t ri : 16; //bit 15:0
+ uint32_t UNIQUENAME(Reserved) : 16; //bit 31:16
+ };
+} mdfld_hdcp_receiver_ri_t;
+
+
+/* HDCP_BKSV_HI */
+#define MDFLD_HDCP_BKSV_HI_REG 0x6140C
+ #define MDFLD_HDCP_BKSV_HI_PRESERVED_BITS BITRANGE(8,31)
+typedef union _mdfld_hdcp_bksv_hi {
+ uint32_t value;
+
+ struct{
+ uint32_t bksv_hi : 8; //bit 7:0
+ uint32_t UNIQUENAME(Reserved) : 24; //bit 31:8
+ };
+} mdfld_hdcp_bksv_hi_t;
+
+
+/* HDCP_AKEY_HI */
+#define MDFLD_HDCP_AKEY_HI_REG 0x61424
+ #define MDFLD_HDCP_AKEY_HI_PRESERVED_BITS BITRANGE(20,31)
+typedef union _mdfld_hdcp_akey_hi {
+ uint32_t value;
+
+ struct{
+ uint32_t akey_hi : 20; //bit 7:0
+ uint32_t UNIQUENAME(Reserved) : 12; //bit 31:8
+ };
+} mdfld_hdcp_akey_hi_t;
+
+
+
+/* HDCP_REP: Repeator specific register definitions */
+
+/* Repeater Control register */
+typedef enum _mdfld_hdcp_repeater_status_enum {
+ HDCP_REPEATER_STATUS_IDLE = 0,
+ HDCP_REPEATER_STATUS_BUSY = 1,
+ HDCP_REPEATER_STATUS_RDY_NEXT_DATA = 2,
+ HDCP_REPEATER_STATUS_COMPLETE_NO_MATCH = 4,
+ HDCP_REPEATER_STATUS_COMPLETE_MATCH = 12
+} mdfld_hdcp_repeater_status_en;
+
+typedef enum _mdfld_hdcp_repeater_ctrl_enum {
+ HDCP_REPEATER_CTRL_IDLE = 0,
+ HDCP_REPEATER_32BIT_TEXT_IP = 1,
+ HDCP_REPEATER_COMPLETE_SHA1 = 2,
+ HDCP_REPEATER_24BIT_TEXT_8BIT_MO_IP = 4,
+ HDCP_REPEATER_16BIT_TEXT_16BIT_MO_IP = 5,
+ HDCP_REPEATER_8BIT_TEXT_24BIT_MO_IP = 6,
+ HDCP_REPEATER_32BIT_MO_IP = 7
+} mdfld_hdcp_repeater_ctrl_en;
+
+#define MDFLD_HDCP_REP_REG 0x61444
+ #define MDFLD_HDCP_REP_PRESERVED_BITS BITRANGE(8,31)
+typedef union _mdfld_hdcp_rep {
+ uint32_t value;
+
+ struct{
+ uint32_t repeater_present : 1; //bit 0
+ uint32_t repeater_control : 3; //bit 3:1
+ uint32_t UNIQUENAME(Reserved) : 12; //bit 15:4 BUN#: 07ww44#1
+ const uint32_t repeater_status : 4; //bit 19:16
+ uint32_t UNIQUENAME(Reserved) : 12;//bit 31:20
+ };
+} mdfld_hdcp_rep_t;
+
+/* HDCP_BKSV_HI */
+#define MDFLD_HDCP_AKSV_HI_REG 0x61450
+ #define MDFLD_HDCP_AKSV_HI_PRESERVED_BITS BITRANGE(8,31)
+typedef union _mdfld_hdcp_aksv_hi {
+ uint32_t value;
+
+ struct{
+ uint32_t aksv_hi : 8; //bit 7:0
+ uint32_t UNIQUENAME(Reserved) : 24; //bit 31:8
+ };
+} mdfld_hdcp_aksv_hi_t;
+
+typedef union _mdfld_hdcp_aksv {
+ uint8_t byte[8];
+
+ struct {
+ uint32_t low;
+ mdfld_hdcp_aksv_hi_t hi;
+ } aksv;
+} mdfld_hdcp_aksv_t;
+
+/* These holds part of the hash result from the receiver used for repeaters */
+#define MDFLD_HDCP_VPRIME_H0 0x6142C
+#define MDFLD_HDCP_VPRIME_H1 0x61430
+#define MDFLD_HDCP_VPRIME_H2 0x61434
+#define MDFLD_HDCP_VPRIME_H3 0x61438
+#define MDFLD_HDCP_VPRIME_H4 0x6143C
+
+#define MDFLD_HDCP_SHA1_IN 0x61440
+
+
+
+/* Define of registers that don't need register definitions */
+#define MDFLD_HDCP_INIT_REG 0x61404
+#define MDFLD_HDCP_AN_LOW_REG 0x61410
+#define MDFLD_HDCP_AN_HI_REG 0x61414
+#define MDFLD_HDCP_BKSV_LOW_REG 0x61408
+#define MDFLD_HDCP_AKSV_LOW_REG 0x61454
+/* Akey registers */
+#define MDFLD_HDCP_AKEY_LO_REG 0x6141C
+#define MDFLD_HDCP_AKEY_MED_REG 0x61420
+
+#endif /* MDFLD_HDCP_REG_H */
--- /dev/null
+/*
+ * Copyright (c) 2010, Intel Corporation.
+ *
+ * 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 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.
+ *
+ * Authors:
+ * jim liu <jim.liu@intel.com>
+ */
+
+#include <drm/drmP.h>
+#include "psb_drv.h"
+#include "psb_intel_reg.h"
+#include "psb_intel_hdmi_reg.h"
+#include "psb_intel_hdmi_edid.h"
+#include "psb_intel_hdmi.h"
+#include "mdfld_hdmi_audio_if.h"
+
+
+/*
+ * Audio register range 0x69000 to 0x69117
+ */
+
+#define IS_HDMI_AUDIO_REG(reg) ((reg >= 0x69000) && (reg < 0x69118))
+
+/*
+ *
+ */
+static struct mid_intel_hdmi_priv *hdmi_priv;
+
+void mdfld_hdmi_audio_init(struct mid_intel_hdmi_priv *p_hdmi_priv)
+{
+ hdmi_priv = p_hdmi_priv;
+}
+
+/**
+ * mdfld_hdmi_audio_write:
+ * used to write into display controller HDMI audio registers.
+ *
+ */
+static int mdfld_hdmi_audio_write (uint32_t reg, uint32_t val)
+{
+ struct drm_device *dev = hdmi_priv->dev;
+ int ret = 0;
+
+ if (IS_HDMI_AUDIO_REG(reg)) {
+ REG_WRITE(reg, val);
+ } else {
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+/**
+ * mdfld_hdmi_audio_read:
+ * used to get the register value read from display controller HDMI audio registers.
+ *
+ */
+static int mdfld_hdmi_audio_read (uint32_t reg, uint32_t *val)
+{
+ struct drm_device *dev = hdmi_priv->dev;
+ int ret = 0;
+
+ if (IS_HDMI_AUDIO_REG(reg)) {
+ *val = REG_READ(reg);
+ } else {
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+/**
+ * mdfld_hdmi_audio_rmw:
+ * used to update the masked bits in display controller HDMI audio registers .
+ *
+ */
+static int mdfld_hdmi_audio_rmw (uint32_t reg, uint32_t val, uint32_t mask)
+{
+ struct drm_device *dev = hdmi_priv->dev;
+ int ret = 0;
+ uint32_t val_tmp = 0;
+
+ if (IS_HDMI_AUDIO_REG(reg)) {
+ val_tmp = (val & mask) | (REG_READ(reg) & ~mask);
+ REG_WRITE(reg, val_tmp);
+ } else {
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+/**
+ * mdfld_hdmi_audio_get_caps:
+ * used to return the HDMI audio capabilities.
+ * e.g. resolution, frame rate.
+ */
+static int mdfld_hdmi_audio_get_caps (enum had_caps_list get_element, void *capabilities) {
+ struct drm_device *dev = hdmi_priv->dev;
+ struct drm_psb_private *dev_priv = (struct drm_psb_private *) dev->dev_private;
+ int ret = 0;
+
+ PSB_DEBUG_ENTRY("\n");
+
+ switch (get_element) {
+ case HAD_GET_ELD:
+ memcpy(capabilities, &(hdmi_priv->eeld), sizeof(hdmi_eeld_t));
+ break;
+ case HAD_GET_SAMPLING_FREQ:
+ memcpy(capabilities, &(dev_priv->tmds_clock_khz), sizeof(uint32_t));
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+/**
+ * mdfld_hdmi_audio_set_caps:
+ * used to set the HDMI audio capabilities.
+ * e.g. Audio INT.
+ */
+static int mdfld_hdmi_audio_set_caps (enum had_caps_list set_element, void *capabilties) {
+ struct drm_device *dev = hdmi_priv->dev;
+ struct drm_psb_private *dev_priv = (struct drm_psb_private *) dev->dev_private;
+ int ret = 0;
+ u32 hdmib;
+ u32 int_masks = 0;
+
+ PSB_DEBUG_ENTRY("\n");
+
+ switch (set_element) {
+ case HAD_SET_ENABLE_AUDIO:
+ hdmib = REG_READ(hdmi_priv->hdmib_reg);
+
+ if ((hdmib & HDMIB_PORT_EN) && hdmi_priv->has_hdmi_sink)
+ hdmib |= HDMI_AUDIO_ENABLE;
+
+ REG_WRITE(hdmi_priv->hdmib_reg, hdmib);
+ REG_READ(hdmi_priv->hdmib_reg);
+ break;
+ case HAD_SET_DISABLE_AUDIO:
+ hdmib = REG_READ(hdmi_priv->hdmib_reg) & ~HDMI_AUDIO_ENABLE;
+ REG_WRITE(hdmi_priv->hdmib_reg, hdmib);
+ REG_READ(hdmi_priv->hdmib_reg);
+ break;
+ case HAD_SET_ENABLE_AUDIO_INT:
+ if (*((u32*)capabilties) & HDMI_AUDIO_UNDERRUN)
+ int_masks |= PIPE_HDMI_AUDIO_UNDERRUN;
+
+ if (*((u32*)capabilties) & HDMI_AUDIO_BUFFER_DONE)
+ int_masks |= PIPE_HDMI_AUDIO_BUFFER_DONE;
+
+ if (dev_priv->hdmi_audio_interrupt_mask != int_masks) {
+ dev_priv->hdmi_audio_interrupt_mask |= int_masks;
+ mdfld_irq_enable_hdmi_audio(dev);
+ }
+
+ break;
+ case HAD_SET_DISABLE_AUDIO_INT:
+ if (*((u32*)capabilties) & HDMI_AUDIO_UNDERRUN)
+ int_masks |= PIPE_HDMI_AUDIO_UNDERRUN;
+
+ if (*((u32*)capabilties) & HDMI_AUDIO_BUFFER_DONE)
+ int_masks |= PIPE_HDMI_AUDIO_BUFFER_DONE;
+
+ if (dev_priv->hdmi_audio_interrupt_mask & int_masks) {
+ dev_priv->hdmi_audio_interrupt_mask &= ~int_masks;
+
+ if (dev_priv->hdmi_audio_interrupt_mask)
+ mdfld_irq_enable_hdmi_audio(dev);
+ else
+ mdfld_irq_disable_hdmi_audio(dev);
+ }
+
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+static struct hdmi_audio_registers_ops mdfld_hdmi_audio_reg_ops = {
+ .hdmi_audio_read_register = mdfld_hdmi_audio_read,
+ .hdmi_audio_write_register = mdfld_hdmi_audio_write,
+ .hdmi_audio_read_modify = mdfld_hdmi_audio_rmw,
+};
+
+static struct hdmi_audio_query_set_ops mdfld_hdmi_audio_get_set_ops = {
+ .hdmi_audio_get_caps = mdfld_hdmi_audio_get_caps,
+ .hdmi_audio_set_caps = mdfld_hdmi_audio_set_caps,
+};
+
+int intel_hdmi_audio_query_capabilities (had_event_call_back audio_callbacks, struct hdmi_audio_registers_ops *reg_ops,struct hdmi_audio_query_set_ops *query_ops) {
+ struct drm_device *dev = hdmi_priv->dev;
+ struct drm_psb_private *dev_priv = (struct drm_psb_private *) dev->dev_private;
+ int ret = 0;
+
+ reg_ops->hdmi_audio_read_register = (mdfld_hdmi_audio_reg_ops.hdmi_audio_read_register);
+ reg_ops->hdmi_audio_write_register = (mdfld_hdmi_audio_reg_ops.hdmi_audio_write_register);
+ reg_ops->hdmi_audio_read_modify = (mdfld_hdmi_audio_reg_ops.hdmi_audio_read_modify);
+ query_ops->hdmi_audio_get_caps = mdfld_hdmi_audio_get_set_ops.hdmi_audio_get_caps;
+ query_ops->hdmi_audio_set_caps = mdfld_hdmi_audio_get_set_ops.hdmi_audio_set_caps;
+
+#if 0
+ *reg_ops = &mdfld_hdmi_audio_reg_ops;
+ *query_ops = &mdfld_hdmi_audio_get_set_ops;
+#endif
+ dev_priv->mdfld_had_event_callbacks = audio_callbacks;
+
+ return ret;
+}
+
+int display_register(struct snd_intel_had_interface *driver, void * had_data)
+{
+ struct drm_device *dev = hdmi_priv->dev;
+ struct drm_psb_private *dev_priv = (struct drm_psb_private *) dev->dev_private;
+ dev_priv->had_pvt_data = had_data;
+ dev_priv->had_interface = driver;
+ return 0;
+}
+
+#if 0
+EXPORT_SYMBOL(intel_hdmi_audio_query_capabilities);
+EXPORT_SYMBOL(display_register);
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2010, Intel Corporation.
+ *
+ * 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 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.
+ *
+ * Authors:
+ * jim liu <jim.liu@intel.com>
+ */
+
+
+#ifndef MDFLD_HDMI_AUDIO_IF_H
+#define MDFLD_HDMI_AUDIO_IF_H
+
+#include "psb_intel_hdmi.h"
+
+/* HDMI AUDIO INTERRUPT TYPE */
+#define HDMI_AUDIO_UNDERRUN (1UL<<0)
+#define HDMI_AUDIO_BUFFER_DONE (1UL<<1)
+
+enum had_caps_list {
+ HAD_GET_ELD = 1,
+ HAD_GET_SAMPLING_FREQ,
+ HAD_GET_DISPLAY_RATE,
+ HAD_GET_HDCP_STATUS,
+ HAD_GET_AUDIO_STATUS,
+ HAD_SET_ENABLE_AUDIO,
+ HAD_SET_DISABLE_AUDIO,
+ HAD_SET_ENABLE_AUDIO_INT,
+ HAD_SET_DISABLE_AUDIO_INT,
+ OTHERS_TBD,
+};
+
+enum had_event_type {
+ HAD_EVENT_HOT_PLUG = 1,
+ HAD_EVENT_HOT_UNPLUG,
+ HAD_EVENT_MODE_CHANGING,
+ HAD_EVENT_PM_CHANGING,
+ HAD_EVENT_AUDIO_BUFFER_DONE,
+ HAD_EVENT_AUDIO_BUFFER_UNDERRUN,
+};
+
+/**
+ * HDMI Display Controller Audio Interface
+ *
+ */
+typedef int (*had_event_call_back)(enum had_event_type event_type, void * ctxt_info);
+
+struct hdmi_audio_registers_ops{
+ int (*hdmi_audio_read_register)(uint32_t reg_addr, uint32_t *data);
+ int (*hdmi_audio_write_register) (uint32_t reg_addr, uint32_t data);
+ int (*hdmi_audio_read_modify)(uint32_t reg_addr, uint32_t data, uint32_t mask);
+};
+
+struct hdmi_audio_query_set_ops{
+ int (*hdmi_audio_get_caps)(enum had_caps_list query_element , void *capabilties);
+ int (*hdmi_audio_set_caps)(enum had_caps_list set_element , void *capabilties);
+};
+
+typedef struct pm_event {
+ int event;
+} pm_event_t;
+struct snd_intel_had_interface {
+ const char *name;
+ int (*probe) (void *had_data,
+ const int card_id);
+ void (*disconnect) (void *had_data);
+ int (*suspend) (void *had_data, pm_event_t event);
+ int (*resume) (void *had_data);
+
+};
+
+extern int intel_hdmi_audio_query_capabilities (had_event_call_back audio_callbacks, struct hdmi_audio_registers_ops *reg_ops,struct hdmi_audio_query_set_ops *query_ops);
+extern int display_register(struct snd_intel_had_interface *driver,void * had_data);
+
+void mdfld_hdmi_audio_init(struct mid_intel_hdmi_priv *p_hdmi_priv);
+
+#endif /* MDFLD_HDMI_AUDIO_IF_H */
--- /dev/null
+/*
+ * Copyright (c) 2010, Intel Corporation.
+ *
+ * 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 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.
+ *
+ * Authors:
+ * jim liu <jim.liu@intel.com>
+ */
+
+#include <drm/drmP.h>
+#include "psb_drv.h"
+#include "psb_intel_reg.h"
+#include "psb_intel_hdmi_reg.h"
+#include "psb_intel_hdmi.h"
+#include "mdfld_hdcp_if.h"
+#include "mdfld_hdcp_reg.h"
+#include "mdfld_hdcp.h"
+
+
+/*
+ *
+ */
+static struct mid_intel_hdmi_priv *hdmi_priv;
+
+void mdfld_hdcp_init(struct mid_intel_hdmi_priv *p_hdmi_priv)
+{
+ hdmi_priv = p_hdmi_priv;
+}
+
+/*
+ * IsValidBKSV:
+ * Checks if the BKSV is valid or not.
+ * A valid BKSV is one that contains 20 0's and 20 1's
+ *
+ */
+static int hdcp_is_valid_bksv(uint8_t* buffer,uint32_t size)
+{
+ uint8_t count = 0;
+ int i =0;
+ uint8_t bksv = 0;
+ uint8_t bit = 0;
+ int ret = 0;
+
+ if(buffer == NULL || size != CP_HDCP_KEY_SELECTION_VECTOR_SIZE)
+ return ret;
+
+ while(i<CP_HDCP_KEY_SELECTION_VECTOR_SIZE)
+ {
+ bksv=buffer[i];
+ while(bksv !=0)
+ {
+ bit = (bksv) & 0x01;
+ if(bit)
+ count++;
+ bksv = bksv >> 1;
+ }
+ i++;
+ }
+
+ if(count == 20)
+ ret = 1;
+
+ return ret;
+}
+
+/*
+ * Gets the current status of HDCP
+ *
+ */
+static int hdcp_is_enabled(void)
+{
+ struct drm_device *dev = hdmi_priv->dev;
+ mdfld_hdcp_status_t hdcp_status = {0};
+ int ret = 0;
+
+ if(hdmi_priv->is_hdcp_supported)
+ {
+ hdcp_status.value = REG_READ(MDFLD_HDCP_STATUS_REG);
+ ret = hdcp_status.cipher_hdcp_status;
+ }
+
+ return ret;
+}
+
+#define HDCP_PRIMARY_I2C_ADDR 0x74
+/*
+ *
+ * Read HDCP device data from i2c link
+ *
+ */
+static int read_hdcp_port_data(uint8_t offset, uint8_t* buffer, int size)
+{
+ struct i2c_msg msgs[] = {
+ {
+ .addr = HDCP_PRIMARY_I2C_ADDR,
+ .flags = 0,
+ .len = 1,
+ .buf = &offset,
+ }, {
+ .addr = HDCP_PRIMARY_I2C_ADDR,
+ .flags = I2C_M_RD,
+ .len = size,
+ .buf = buffer,
+ }
+ };
+
+ if (i2c_transfer(hdmi_priv->hdmi_i2c_adapter, msgs, 2) == 2)
+ return 1;
+
+ return 0;
+}
+
+/* Read device status from i2c link */
+static int read_hdcp_port(uint32_t read_request_type, uint8_t *buffer, int size)
+{
+ int more_blocks_to_read = 0;
+ uint32_t block_offset=0;
+ int ret = 1;
+ uint8_t offset = 0;
+
+ while(1)
+ {
+ switch(read_request_type)
+ {
+ case RX_TYPE_BSTATUS:
+ offset = RX_BSTATUS_0;
+ break;
+ case RX_TYPE_RI_DATA:
+ offset = RX_RI_HIGH;
+ break;
+ case RX_TYPE_BCAPS:
+ offset = RX_BCAPS;
+ break;
+ case RX_TYPE_REPEATER_KSV_LIST:
+ offset = RX_KSV_FIFO;
+ break;
+ case RX_TYPE_BKSV_DATA:
+ offset = RX_BKSV_0;
+ break;
+ case RX_TYPE_REPEATER_PRIME_V:
+ {
+ offset = block_offset + RX_VPRIME_H0_0;
+ buffer += block_offset;
+ size = 4;
+ if(offset < RX_VPRIME_H4_0)
+ {
+ more_blocks_to_read = 1;
+ block_offset += 4;
+ }
+ }
+ break;
+ default:
+ ret = 0;
+ break;
+ }
+
+ if(ret)
+ {
+ if(!read_hdcp_port_data(offset, buffer, size))
+ {
+ //I2C access failed
+ ret = 0;
+ break;
+ }
+
+ //Check whether more blocks are to be read
+ if(!more_blocks_to_read)
+ {
+ break;
+ }
+ else
+ {
+ more_blocks_to_read = 0;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ return ret;
+}
+
+/* write to HDCP device through i2c link */
+static int write_hdcp_port(uint8_t offset, uint8_t *buffer, int size)
+{
+ struct i2c_msg msgs[] = {
+ {
+ .addr = HDCP_PRIMARY_I2C_ADDR,
+ .flags = 0,
+ .len = 1,
+ .buf = &offset,
+ }, {
+ .addr = HDCP_PRIMARY_I2C_ADDR,
+ .flags = 0,
+ .len = size,
+ .buf = buffer,
+ }
+ };
+
+ if (i2c_transfer(hdmi_priv->hdmi_i2c_adapter, msgs, 2) == 2)
+ return 1;
+
+ return 0;
+}
+
+/*
+ *
+ * UpdateRepeaterState : Enables/Disables Repeater
+ *
+ */
+static int hdcp_update_repeater_state(int enable)
+{
+ struct drm_device *dev = hdmi_priv->dev;
+ mdfld_hdcp_rep_t hdcp_rep_ctrl_reg;
+ hdcp_rep_ctrl_reg.value = REG_READ(MDFLD_HDCP_REP_REG);
+ hdcp_rep_ctrl_reg.repeater_present = enable;
+
+ REG_WRITE(MDFLD_HDCP_REP_REG,hdcp_rep_ctrl_reg.value);
+ return 1;
+
+}
+
+/*
+ * EnableHDCP : Enables/Disables HDCP
+ *
+ */
+static int hdcp_enable(int enable)
+{
+ struct drm_device *dev = hdmi_priv->dev;
+ mdfld_hdcp_config_t config;
+ mdfld_hdcp_receiver_ri_t receivers_ri;
+ mdfld_hdcp_status_t status;
+ mdfld_hdcp_rep_t hdcp_repeater;
+ uint32_t max_retry = 0;
+ sqword_t hw_an;
+ sqword_t hw_aksv;
+ sqword_t hw_bksv;
+ uint8_t bcaps=0;
+ uint32_t rx_ri = 0;
+ int ret = 0;
+
+ if(enable == 0)
+ {
+ config.value = REG_READ(MDFLD_HDCP_CONFIG_REG);
+ config.hdcp_config = HDCP_Off;
+ REG_WRITE(MDFLD_HDCP_CONFIG_REG,config.value);
+
+ //Check the status of cipher till it get's turned off
+ // Bug #2808007-Delay required is one frame period.
+ // waiting for 2 VBlanks provides this amount of delay
+ max_retry = 0;
+ status.value = REG_READ(MDFLD_HDCP_STATUS_REG);
+ while((status.cipher_hdcp_status || status.cipher_encrypting_status) && max_retry< HDCP_MAX_RETRY_DISABLE)
+ {
+ psb_intel_wait_for_vblank(dev);
+ status.value = REG_READ(MDFLD_HDCP_STATUS_REG);
+ max_retry++;
+ }
+
+ // Check for cipher time out
+ if(status.cipher_hdcp_status || status.cipher_encrypting_status)
+ {
+ ret = 0;
+ return ret;
+ }
+
+ // clear the repeater specfic bits and set the repeater to idle
+ hdcp_repeater.value = REG_READ(MDFLD_HDCP_REP_REG);
+ hdcp_repeater.repeater_present = 0;
+ hdcp_repeater.repeater_control = HDCP_REPEATER_CTRL_IDLE;
+ REG_WRITE(MDFLD_HDCP_REP_REG, hdcp_repeater.value);
+
+ max_retry = HDCP_MAX_RETRY_STATUS;//tbd: not yet finalized
+ while(max_retry--)
+ {
+ hdcp_repeater.value = REG_READ(MDFLD_HDCP_REP_REG);
+
+ if(hdcp_repeater.repeater_status == HDCP_REPEATER_STATUS_IDLE)
+ {
+ ret = 1;
+ break;
+ }
+ }
+
+ // Check for cipher time out
+ if(max_retry == 0)
+ {
+ ret = 0;
+ return 0;
+ }
+
+ // Clear the Ri' register
+ // This is a HW issue because of which the Ri' status bit in HDCP_STATUS
+ // register doesn't get cleared.
+ // refer ro https://vthsd.fm.intel.com/hsd/cantiga/sighting/default.aspx?sighting_id=304464
+ // for details
+ REG_WRITE(MDFLD_HDCP_RECEIVER_RI_REG, 0);
+
+ //Disable the port on which HDCP is enabled
+ REG_WRITE(hdmi_priv->hdmib_reg, REG_READ(hdmi_priv->hdmib_reg) & ~HDMIB_HDCP_PORT);
+ }
+ else
+ {
+ //Generate An
+ config.value = REG_READ(MDFLD_HDCP_CONFIG_REG);
+
+ if (config.hdcp_config != HDCP_Off) {
+ config.hdcp_config = HDCP_Off;
+ REG_WRITE(MDFLD_HDCP_CONFIG_REG, config.value);
+ }
+
+ /* used the jiffies as a random number. */
+ REG_WRITE(MDFLD_HDCP_INIT_REG, (uint32_t) jiffies);
+ REG_WRITE(MDFLD_HDCP_INIT_REG, (uint32_t) (jiffies >> 1));
+ udelay (10);
+
+ config.hdcp_config = HDCP_CAPTURE_AN;
+ REG_WRITE(MDFLD_HDCP_CONFIG_REG, config.value);
+
+ //check the status of cipher before reading an
+ max_retry = HDCP_MAX_RETRY_STATUS;//tbd: not yet finalized
+ while(max_retry--)
+ {
+ status.value = REG_READ(MDFLD_HDCP_STATUS_REG);
+ if(status.cipher_an_status)
+ {
+ ret = 1;
+ break;
+ }
+ }
+
+ config.hdcp_config = HDCP_Off;
+ REG_WRITE(MDFLD_HDCP_CONFIG_REG, config.value);
+
+ if(max_retry == 0)
+ return 0;//Cipher timeout, was not able to generate An :(
+
+ //Read An
+ hw_an.u.low_part = REG_READ(MDFLD_HDCP_AN_LOW_REG);
+ hw_an.u.high_part = REG_READ(MDFLD_HDCP_AN_HI_REG);
+
+ hw_aksv.u.low_part = REG_READ(MDFLD_HDCP_AKSV_LOW_REG);
+ hw_aksv.u.high_part = REG_READ(MDFLD_HDCP_AKSV_HI_REG);
+ //stHdcpParams.hwAksv.MajorPart_Low = 0x0361f714;//test data
+ //stHdcpParams.hwAksv.MajorPart_High = 0xb7;
+
+ //write An
+ ret = write_hdcp_port(RX_AN_0, hw_an.byte, 8);
+ if(!ret)
+ return 0;
+
+ //write Aksv
+ ret = write_hdcp_port(RX_AKSV_0, hw_aksv.byte, 5);
+ if(!ret)
+ return 0;
+
+ //Read the Bksv from receiver
+ ret =read_hdcp_port(RX_TYPE_BKSV_DATA, &hw_bksv.byte[0], 5);
+ if(ret)
+ {
+ // Validate BKSV
+ ret = hdcp_is_valid_bksv(&hw_bksv.byte[0], 5);
+ }
+
+ if(!ret)
+ return 0;
+
+ //read the BCaps
+ ret = read_hdcp_port(RX_TYPE_BCAPS, &bcaps, 1);
+ if(!ret)
+ return 0;
+
+ // set repeater bit if receiver connected is a repeater
+ if(bcaps & BIT(6))
+ {
+ hdcp_update_repeater_state(1);
+ }
+
+ //Write the BKsv into the encoder
+ REG_WRITE(MDFLD_HDCP_BKSV_LOW_REG, hw_bksv.u.low_part);
+ REG_WRITE(MDFLD_HDCP_BKSV_HI_REG, hw_bksv.u.high_part);
+
+
+ //enable HDCP on this port
+ REG_WRITE(hdmi_priv->hdmib_reg, REG_READ(hdmi_priv->hdmib_reg) | HDMIB_HDCP_PORT);
+
+ //TBD :Check the bStatus, for repeater and set HDCP_REP[1]
+ //Set HDCP_CONFIG to 011 = Authenticate and encrypt
+ config.hdcp_config = HDCP_AUTHENTICATE_AND_ENCRYPT;
+ REG_WRITE(MDFLD_HDCP_CONFIG_REG, config.value);
+
+
+ //At this point of time the Km is created
+
+ //Wait for Ri ready
+ max_retry = HDCP_MAX_RETRY_STATUS;//TBD: Not yet finalized
+ while(max_retry--)
+ {
+ status.value = REG_READ(MDFLD_HDCP_STATUS_REG);
+ if(status.cipher_ri_ready_status)
+ break;
+ }
+
+ if(max_retry == 0)
+ return 0;//Cipher timeout, was not able to generate An :(
+
+ //Compare the R0 and Ri
+ //Read the Ri' of reciever
+ ret = read_hdcp_port(RX_TYPE_RI_DATA, (uint8_t*)&rx_ri, 2);
+ if(!ret)
+ return 0;
+
+ //TBD:Have some delay before reading the Ri'
+ //Right now using 100 ms, as per the HDCP spec(Refer HDCP SAS for details)
+ mdelay(HDCP_100MS_DELAY);
+
+ //update the HDCP_Ri' register and read the status reg for confrmation
+ receivers_ri.value = REG_READ(MDFLD_HDCP_RECEIVER_RI_REG);
+ receivers_ri.ri = rx_ri;
+ REG_WRITE(MDFLD_HDCP_RECEIVER_RI_REG, receivers_ri.value);
+
+ status.value = REG_READ(MDFLD_HDCP_STATUS_REG);
+
+ //SoftbiosDebugMessage(DBG_CRITICAL,"R Prime = %x\n",dwRxRi);
+ //SoftbiosDebugMessage(DBG_CRITICAL,"HDCP_STATUS = %x\n",stStatus.value);
+ ret = status.cipher_ri_match_status;
+ /*if(GEN4INTHDCPCONTROLLER_HasInterruptOccured(pThis,ePort) == TRUE)
+ {
+ bRet = 0;
+ }*/
+ }
+
+ if(!ret)
+ {
+ //TODO: SoftbiosDebugMessage(DBG_CRITICAL," EnableHDCP failed \n");
+ }
+
+ return ret;
+}
+
+/*
+To obtain receiver specific data. The request type
+is from mdfld_hdcp_rx_data_type_en
+*/
+static int hdcp_get_receiver_data(uint8_t* buffer, uint32_t size, uint32_t rx_data_type)
+{
+ int ret = 0;
+
+ if(buffer)
+ {
+ memset(buffer, 0, size);
+ //Get the Data from reciever
+ ret = read_hdcp_port(rx_data_type, buffer, size);
+ }
+
+ // Validate BKSV and Check if its Valid.
+ if(RX_TYPE_BKSV_DATA == rx_data_type)
+ {
+ ret = hdcp_is_valid_bksv(buffer, size);
+ }
+
+ return ret;
+}
+
+/*
+ *
+ * WaitForNextDataReady : Function Waits for enryption ready
+ *
+ */
+static int hdcp_wait_for_next_data_ready(void)
+{
+ struct drm_device *dev = hdmi_priv->dev;
+ mdfld_hdcp_rep_t hdcp_rep_reg;
+ uint32_t i = 0;
+ int ret = 0;
+
+ for(i=0;i<HDCP_MAX_RETRY_STATUS;i++)
+ {
+ hdcp_rep_reg.value = REG_READ(MDFLD_HDCP_REP_REG);
+
+ if(HDCP_REPEATER_STATUS_RDY_NEXT_DATA == hdcp_rep_reg.repeater_status)
+ {
+ ret = 1;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+/*
+ *
+ * CompareVPrime : This routine compares the vprime
+ * obtained from receiver with the one generated in
+ * transmitter.
+ *
+ */
+static int hdcp_compare_v_prime(uint32_t* buffer_repeater_v_prime, uint8_t size_in_dword)
+{
+ struct drm_device *dev = hdmi_priv->dev;
+ uint32_t value = 0;
+ uint8_t* buffer = (uint8_t*)buffer_repeater_v_prime;
+ int ret = 0;
+ mdfld_hdcp_rep_t hdcp_rep_ctrl_reg;
+ uint32_t i = 0;
+
+ //TBD: To be implemented as part of repeater implementation
+ //Set the repeater's vprime in GMCH
+
+ if(size_in_dword == KSV_SIZE)
+ {
+ memcpy(&value,buffer,4);
+ REG_WRITE(MDFLD_HDCP_VPRIME_H0,value);
+
+ buffer += 4;
+ memcpy(&value,buffer,4);
+ REG_WRITE(MDFLD_HDCP_VPRIME_H1,value);
+
+ buffer += 4;
+ memcpy(&value,buffer,4);
+ REG_WRITE(MDFLD_HDCP_VPRIME_H2,value);
+
+ buffer += 4;
+ memcpy(&value,buffer,4);
+ REG_WRITE(MDFLD_HDCP_VPRIME_H3,value);
+
+ buffer += 4;
+ memcpy(&value,buffer,4);
+ REG_WRITE(MDFLD_HDCP_VPRIME_H4,value);
+
+ if(!hdcp_wait_for_next_data_ready())
+ return 0;
+
+ // Set HDCP_REP to do the comparison
+ // Start transmitter's V calculation
+ hdcp_rep_ctrl_reg.value = REG_READ(MDFLD_HDCP_REP_REG);
+ hdcp_rep_ctrl_reg.repeater_control = HDCP_REPEATER_COMPLETE_SHA1;
+ REG_WRITE(MDFLD_HDCP_REP_REG, hdcp_rep_ctrl_reg.value);
+
+ for(i=0;i<HDCP_MAX_RETRY_STATUS;i++)
+ {
+ hdcp_rep_ctrl_reg.value = REG_READ(MDFLD_HDCP_REP_REG);
+
+ switch(hdcp_rep_ctrl_reg.repeater_status)
+ {
+ case HDCP_REPEATER_STATUS_COMPLETE_MATCH :
+ ret = 1;
+ break;
+ case HDCP_REPEATER_STATUS_COMPLETE_NO_MATCH :
+ ret = 0;
+ break;
+ case HDCP_REPEATER_STATUS_IDLE :
+ //Should not happen
+ ret = 0;
+ break;
+ //default: Not needed
+ }
+
+ if(hdcp_rep_ctrl_reg.repeater_status != HDCP_REPEATER_STATUS_BUSY)
+ {
+ break;
+ }
+ }
+
+ }
+ else
+ {
+ ret = 0;
+ }
+
+ return ret;
+}
+
+/*
+ *
+ * ComputeTransmitterV : This routine computes transmitter's V prime.
+ * As per HDCP spec 1.3 for HDMI/DVI the BStatus register contains data specific to repeater
+ * sink topology in case sink is a repeater. The same interface is used by HDCP over display port
+ * in which case BInfo contains the relevant data. The variable wBTopologyData represents Bstatus
+ * for HDMI/DVI and BInfo for Display Port
+ *
+ */
+static int hdcp_compute_transmitter_v(ksv_t *ksv_list, uint32_t ksv_list_entries, uint16_t b_topology_data)
+{
+ struct drm_device *dev = hdmi_priv->dev;
+ uint32_t num_devices = ksv_list_entries;
+// uint32_t lower_num_bytes_for_sha = 0, upper_num_bytes_for_sha = 0; // This has to be in mutiple of 512 bits
+ uint32_t lower_num_bytes_for_sha = 0;
+ uint32_t num_pad_bytes = 0;
+ uint8_t *buffer = NULL;
+ uint8_t *temp_buffer = NULL;
+ mdfld_hdcp_rep_t hdcp_rep_ctrl_reg;
+ uint32_t value = 0;
+ int ret = 1;
+ uint32_t i = 0;
+ uint32_t rem_text_data = 0, num_mo_bytes_left = 8;
+ uint8_t* temp_data_ptr = NULL;
+ sqword_t buffer_len;
+ uint32_t temp_data = 0;
+
+ //Clear SHA hash generator for new V calculation and set the repeater to idle state
+ REG_WRITE(MDFLD_HDCP_SHA1_IN, 0);
+ hdcp_rep_ctrl_reg.value = REG_READ(MDFLD_HDCP_REP_REG);
+ hdcp_rep_ctrl_reg.repeater_control = HDCP_REPEATER_CTRL_IDLE;
+ REG_WRITE(MDFLD_HDCP_REP_REG,hdcp_rep_ctrl_reg.value);
+ for(i=0; i<HDCP_MAX_RETRY_STATUS; i++)
+ {
+ hdcp_rep_ctrl_reg.value = REG_READ(MDFLD_HDCP_REP_REG);
+ if(HDCP_REPEATER_CTRL_IDLE == hdcp_rep_ctrl_reg.repeater_status)
+ {
+ ret = 1;
+ break;
+ }
+ }
+ if(i == HDCP_MAX_RETRY_STATUS)
+ {
+ return 0;
+ }
+
+ // Start the SHA buffer creation
+ //To find the number of pad bytes
+ num_pad_bytes = (64 - (ksv_list_entries*KSV_SIZE + 18)%64);
+
+ // Get the number of bytes for SHA
+ lower_num_bytes_for_sha = KSV_SIZE*num_devices + 18 + num_pad_bytes;//multiple of 64 bytes
+
+ buffer = (uint8_t*)kzalloc(lower_num_bytes_for_sha, GFP_KERNEL);
+
+ if(buffer)
+ {
+ //1. Copy the KSV buffer
+ //Note:The data is in little endian format
+ temp_buffer = buffer;
+ memcpy((void*)temp_buffer,(void*)ksv_list,num_devices*KSV_SIZE);
+ temp_buffer += num_devices*KSV_SIZE;
+
+ //2. Copy the b_topology_data
+ memcpy((void*)temp_buffer,(void*)&b_topology_data,2);
+ //The bstatus is copied in little endian format
+ temp_buffer +=2;
+
+ //3. Offset the pointer buffer by 8 bytes
+ // These 8 bytes are zeroed and are place holdes for Mo
+ temp_buffer +=8;
+
+ //4. Pad the buffer with extra bytes
+ // No need to pad the begining of padding bytes by adding
+ // 0x80. HW automatically appends the same while creating
+ // the buffer.
+ //*temp_buffer = (BYTE)0x80;
+ //temp_buffer++;
+ for(i=0;i<num_pad_bytes;i++)
+ {
+ *temp_buffer = (uint8_t)0x00;
+ temp_buffer++;
+ }
+
+ //5. Construct the length byte
+ buffer_len.quad_part = (unsigned long long)(ksv_list_entries*KSV_SIZE + 2 + 8)*8;
+ temp_data_ptr = (uint8_t*)&buffer_len.quad_part;
+ // Store it in big endian form
+ for(i=1; i<=8; i++)
+ {
+ *temp_buffer = *(temp_data_ptr + 8-i);
+ temp_buffer++;
+ }
+
+ //5.Write a random 64 bit value to the buffer
+ //memcpy(temp_buffer,&upper_num_bytes_for_sha,4);
+ //temp_buffer += 4;
+ //memcpy(temp_buffer,&lower_num_bytes_for_sha,4);
+
+ //Now write the data into the SHA
+ temp_buffer = buffer;
+ for(i=0; i<(KSV_SIZE*num_devices + 2)/4; i++)
+ {
+ hdcp_rep_ctrl_reg.value = REG_READ(MDFLD_HDCP_REP_REG);
+ hdcp_rep_ctrl_reg.repeater_control = HDCP_REPEATER_32BIT_TEXT_IP;
+ REG_WRITE(MDFLD_HDCP_REP_REG,hdcp_rep_ctrl_reg.value);
+
+ //As per HDCP spec sample SHA is in little endian format. But the
+ //data fed to the cipher needs to be in big endian format for it
+ //to compute it correctly
+ memcpy(&value,temp_buffer,4);
+ value = HDCP_CONVERT_BIG_ENDIAN(value);
+ REG_WRITE(MDFLD_HDCP_SHA1_IN, value);
+ temp_buffer += 4;
+
+ if(!hdcp_wait_for_next_data_ready())
+ return 0;
+ }
+
+ //Write the remaining text data with M0
+ //BUN#: 07ww44#1: text input must be aligned to LSB of the SHA1
+ //in register when inputting partial text and partial M0
+ rem_text_data = (KSV_SIZE*num_devices + 2)%4;
+ if(rem_text_data)
+ {
+ // Update the no of Mo bytes
+ num_mo_bytes_left = num_mo_bytes_left - (4-rem_text_data);
+
+ if(!hdcp_wait_for_next_data_ready())
+ return 0;
+
+ hdcp_rep_ctrl_reg.value = REG_READ(MDFLD_HDCP_REP_REG);
+ switch(rem_text_data)
+ {
+ case 1:
+ hdcp_rep_ctrl_reg.repeater_control = HDCP_REPEATER_8BIT_TEXT_24BIT_MO_IP;
+ break;
+ case 2:
+ hdcp_rep_ctrl_reg.repeater_control = HDCP_REPEATER_16BIT_TEXT_16BIT_MO_IP;
+ break;
+ case 3:
+ hdcp_rep_ctrl_reg.repeater_control = HDCP_REPEATER_24BIT_TEXT_8BIT_MO_IP;
+ break;
+ default:
+ ret = 0;
+ }
+
+ if(!ret)
+ return ret;
+
+ REG_WRITE(MDFLD_HDCP_REP_REG,hdcp_rep_ctrl_reg.value);
+ memcpy(&value,temp_buffer,4);
+
+ // swap the text data in big endian format leaving the Mo data as it is.
+ // As per the bun the LSB should contain the data in big endian format.
+ // since the M0 specfic data is all zeros while it's fed to the cipher.
+ // Those bit don't need to be modified
+ temp_data = 0;
+ for(i=0; i<rem_text_data; i++)
+ {
+ temp_data |= ((value & 0xff<<(i*8))>>(i*8))<<((rem_text_data - i-1)*8);
+ }
+ REG_WRITE(MDFLD_HDCP_SHA1_IN, temp_data);
+ temp_buffer += 4;
+ }
+
+ //Write 4 bytes of Mo
+ if(!hdcp_wait_for_next_data_ready())
+ return 0;
+
+ hdcp_rep_ctrl_reg.value = REG_READ(MDFLD_HDCP_REP_REG);
+ hdcp_rep_ctrl_reg.repeater_control = HDCP_REPEATER_32BIT_MO_IP;
+ REG_WRITE(MDFLD_HDCP_REP_REG,hdcp_rep_ctrl_reg.value);
+ memcpy(&value,temp_buffer,4);
+ REG_WRITE(MDFLD_HDCP_SHA1_IN, value);
+ temp_buffer += 4;
+ num_mo_bytes_left -= 4;
+
+ if(num_mo_bytes_left)
+ {
+ // The remaining Mo + padding bytes need to be added
+ num_pad_bytes = num_pad_bytes - (4-num_mo_bytes_left);
+
+ //Write 4 bytes of Mo
+ if(!hdcp_wait_for_next_data_ready())
+ return 0;
+
+ hdcp_rep_ctrl_reg.value = REG_READ(MDFLD_HDCP_REP_REG);
+ switch(num_mo_bytes_left)
+ {
+ case 1:
+ hdcp_rep_ctrl_reg.repeater_control = HDCP_REPEATER_24BIT_TEXT_8BIT_MO_IP;
+ break;
+ case 2:
+ hdcp_rep_ctrl_reg.repeater_control = HDCP_REPEATER_16BIT_TEXT_16BIT_MO_IP;
+ break;
+ case 3:
+ hdcp_rep_ctrl_reg.repeater_control = HDCP_REPEATER_8BIT_TEXT_24BIT_MO_IP;
+ break;
+ default:
+ // should never happen
+ ret = 0;
+ }
+
+ if(!ret)
+ return ret;
+
+ REG_WRITE(MDFLD_HDCP_REP_REG,hdcp_rep_ctrl_reg.value);
+ memcpy(&value,temp_buffer,4);
+ //BUN#:07ww44#1
+ temp_data = 0;
+ for(i=0; i<rem_text_data; i++)
+ {
+ temp_data |= ((value & 0xff<<(i*8))>>(i*8))<<((rem_text_data - i-1)*8);
+ }
+ REG_WRITE(MDFLD_HDCP_SHA1_IN, value);
+ temp_buffer += 4;
+ num_mo_bytes_left = 0;
+ }
+
+ //Write the remaining no of bytes
+ // Remaining data = remaining padding data + 64 bits of length data
+ rem_text_data = num_pad_bytes + 8;
+
+ if(rem_text_data%4)
+ {
+ //Should not happen
+ return 0;
+ }
+
+ for(i=0;i<rem_text_data/4;i++)
+ {
+ REG_WRITE(MDFLD_HDCP_SHA1_IN,temp_data);
+ if(!hdcp_wait_for_next_data_ready())
+ return 0;
+
+ hdcp_rep_ctrl_reg.value = REG_READ(MDFLD_HDCP_REP_REG);
+ hdcp_rep_ctrl_reg.repeater_control = HDCP_REPEATER_32BIT_TEXT_IP;
+ REG_WRITE(MDFLD_HDCP_REP_REG,hdcp_rep_ctrl_reg.value);
+ memcpy(&value,temp_buffer,4);
+ // do the Big endian conversion
+ value = HDCP_CONVERT_BIG_ENDIAN(value);
+ REG_WRITE(MDFLD_HDCP_SHA1_IN, value);
+ temp_buffer += 4;
+ }
+ kfree(buffer);
+
+ ret = 1;
+ }
+ else
+ {
+ return 0;
+ }
+
+ return ret;
+}
+
+/*
+ *
+ * SetHDCPEncryptionLevel:
+ *
+ */
+static uint32_t hdcp_set_encryption_level(cp_parameters_t* cp)
+{
+ uint32_t ret = STATUS_UNSUCCESSFUL;
+ int hdcp_enabled = 0;
+ uint32_t ksv_length = 0;
+ ksv_t bksv;
+
+ //Get the hdcp configuration of the port
+ if(hdmi_priv->is_hdcp_supported)
+ {
+ hdcp_enabled = hdcp_is_enabled();
+ if(((cp->level == CP_PROTECTION_LEVEL_HDCP_OFF)&&(!hdcp_enabled))||
+ ((cp->level == CP_PROTECTION_LEVEL_HDCP_ON)&&hdcp_enabled))
+ {
+ ret = STATUS_SUCCESS;
+ }
+
+ if(ret == STATUS_UNSUCCESSFUL)
+ {
+ //Turn off HDCP
+ if (hdcp_enable(0))
+ ret = STATUS_SUCCESS;
+
+ if((cp->level != CP_PROTECTION_LEVEL_HDCP_OFF) && (ret == STATUS_SUCCESS))
+ {
+ // Check if a Revoked device is attached
+ if(cp->hdcp.ksv_list_length)
+ {
+ //Get the current set of BKSV's from the
+ if(hdcp_get_receiver_data((uint8_t*)bksv.ab_ksv, CP_HDCP_KEY_SELECTION_VECTOR_SIZE, RX_TYPE_BKSV_DATA))
+ {
+ for(ksv_length = 0; ksv_length<cp->hdcp.ksv_list_length; ksv_length++)
+ {
+ if(!memcmp(&bksv,
+ &cp->hdcp.ksv_list[ksv_length],
+ CP_HDCP_KEY_SELECTION_VECTOR_SIZE))
+ {
+ ret = STATUS_REVOKED_HDCP_DEVICE_ATTACHED;
+ break;
+
+ }
+ }
+ }
+ }
+
+
+ if(ret == STATUS_SUCCESS)
+ {
+ //Activate the link layer
+ ret = hdcp_enable(1);
+ }
+
+ }
+ }
+ }
+ return ret;
+}
+
+/*
+ *
+ * GetMaxSupportedAttachedDevices: Returns the
+ * max no attached devices supported on repeater
+ *
+ */
+static uint16_t hdcp_get_max_supported_attached_devices(void)
+{
+ //currently return 128 as specified by the HDCP spec
+ return MAX_HDCP_DEVICES;
+}
+
+/*
+ *
+ * ActivateRepeater: Activates reciver mode
+ *
+ */
+static uint32_t hdcp_activate_repeater(cp_parameters_t* cp)
+{
+ uint32_t ret = STATUS_UNSUCCESSFUL;
+ uint16_t device_count = 0;
+ uint16_t get_max_device_supported = 0;
+ uint8_t* ksv_list=NULL;//[MAX_HDCP_DEVICES] = {0};// * KSV_SIZE] = { 0 };
+ uint16_t i = 0, j = 0, k = 0;
+ uint32_t repeater_prime_v[5];
+ hdcp_rx_bcaps_t b_caps;
+ hdcp_rx_bstatus_t b_status;
+ //TBD: TO be enabled for OPM - Vista
+
+ // Init bcaps
+ b_caps.value = 0;
+ b_status.value = 0;
+
+ for(i = 0; i<5; i++)
+ repeater_prime_v[i] = 0;
+
+ for(i=0;i<1;i++)
+ {
+ ksv_list = (uint8_t*)kzalloc(MAX_HDCP_DEVICES*KSV_SIZE, GFP_KERNEL);
+
+ if(!ksv_list)
+ {
+ ret = STATUS_UNSUCCESSFUL;
+ break;
+ }
+
+ //get the receiver bcaps
+ hdcp_get_receiver_data(&b_caps.value, 1, RX_TYPE_BCAPS);
+
+ // Check for repeater caps
+ if(!(b_caps.is_reapeater))
+ {
+ ret = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ // Check if the KSV FIFO is ready
+ if(!(b_caps.ksv_fifo_ready))
+ {
+ // The HDCP repeater is not yet ready to return a KSV list.
+ // Per HDCP spec, the repeater has 5 seconds from when KSVs are exchanged
+ // in the first part of the authentication protocol (HDCPActivateLink)
+ // to be ready to report out downstream KSVs.
+ ret = STATUS_PENDING;
+ break;
+ }
+
+ //Read repeater's Bstatus
+ hdcp_get_receiver_data((uint8_t*)&b_status.value, 2, RX_TYPE_BSTATUS);
+
+ // check if max dev limit is exceeded
+ if(b_status.max_devs_exceeded)
+ {
+ ret = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ // Check for topology error. This happens when
+ // more then seven levels of video repeater have been cascaded.
+ if(b_status.max_cascade_exceeded)
+ {
+ ret = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ device_count = b_status.device_count;
+ if(device_count == 0)
+ {
+ ret = STATUS_SUCCESS;
+ break;
+ }
+
+ get_max_device_supported = hdcp_get_max_supported_attached_devices();
+
+ if(device_count > get_max_device_supported)
+ {
+ ret = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ // Update the cipher saying sink supports repeater capabilities
+ if(!hdcp_update_repeater_state(1))
+ {
+ ret = STATUS_UNSUCCESSFUL;
+ break;
+ }
+
+ // Read the KSV list from the repeater
+ if(!hdcp_get_receiver_data(ksv_list, device_count * KSV_SIZE, RX_TYPE_REPEATER_KSV_LIST))
+ {
+ ret = STATUS_UNSUCCESSFUL;
+ break;
+ }
+
+ for(j=0; j<device_count; j++)
+ {
+ for(k=0; k<cp->hdcp.ksv_list_length; k++)
+ {
+ if(0==memcmp(&ksv_list[j* KSV_SIZE], &cp->hdcp.ksv_list[k], CP_HDCP_KEY_SELECTION_VECTOR_SIZE))
+ {
+ ret = STATUS_REVOKED_HDCP_DEVICE_ATTACHED;
+ break;
+ }
+ }
+ }
+
+ if(!hdcp_compute_transmitter_v((ksv_t *)ksv_list,device_count,b_status.value))
+ {
+ ret = STATUS_UNSUCCESSFUL;
+ break;
+ }
+
+ //Get the HDCP receiver's V' value (20 bytes in size)
+ if(!hdcp_get_receiver_data((uint8_t*)repeater_prime_v, KSV_SIZE*4, RX_TYPE_REPEATER_PRIME_V))
+ {
+ ret = STATUS_UNSUCCESSFUL;
+ break;
+ }
+
+
+ if(!hdcp_compare_v_prime(repeater_prime_v, KSV_SIZE))
+ {
+ //set hdcp encryption level to 0
+ hdcp_update_repeater_state(0);
+ hdcp_enable(0);
+ ret = STATUS_UNSUCCESSFUL;
+ }
+ else
+ {
+ ret = STATUS_SUCCESS;
+ }
+ }
+
+ if(ksv_list)
+ {
+ kfree(ksv_list);
+ ksv_list = NULL;
+ }
+
+
+ return ret;
+}
+
+/*
+ * IsHDCPRepeater : Reads the caps register and informs
+ * whether the received is a repeater
+ *
+ */
+static int hdcp_is_repeater(int *is_repeater)
+{
+ int ret = 0;
+ hdcp_rx_bcaps_t b_caps;
+
+ //Init
+ b_caps.value = 0;
+
+ ret = hdcp_get_receiver_data(&b_caps.value, 1, RX_TYPE_BCAPS);
+ if(ret)
+ {
+ *is_repeater = b_caps.is_reapeater;
+ }
+
+ return ret;
+}
+
+/* Get's the current link status */
+static int hdcp_get_link_status(void)
+{
+ struct drm_device *dev = hdmi_priv->dev;
+ int ret = 0;
+ uint32_t rx_ri = 0;
+ mdfld_hdcp_receiver_ri_t receivers_ri;
+ mdfld_hdcp_status_t status;
+ uint32_t max_count = 0;
+
+ max_count = HDCP_MAX_RI_QUERY_COUNT;
+ while(max_count)
+ {
+ max_count--;
+
+ //Read the Ri' of reciever
+ ret = read_hdcp_port(RX_TYPE_RI_DATA,(uint8_t*)&rx_ri,2);
+ if(!ret)
+ break; // I2C access failed
+
+ //update the HDCP_Ri' register and read the status reg for cofrmation
+ receivers_ri.value = REG_READ(MDFLD_HDCP_RECEIVER_RI_REG);
+ receivers_ri.ri = rx_ri;
+ REG_WRITE(MDFLD_HDCP_RECEIVER_RI_REG, receivers_ri.value);
+
+ status.value = REG_READ(MDFLD_HDCP_STATUS_REG);
+
+ ret = status.cipher_ri_match_status;
+ if(ret)
+ {
+ //Ri and Ri' matches, hence reciver is a authentic one :)
+ break;
+ }
+ else
+ {
+ //The Ri changes every 128th frame.Hence if the Ri check fails
+ //that means the sink has updated the Ri value and that can happen
+ //every 128th frame. In that case we wait for the next frame count.
+ //Wait should be around 16 ms.
+ while((status.frame_count&HDCP_NEXT_RI_FRAME) == HDCP_NEXT_RI_FRAME)
+ {
+ status.value = REG_READ(MDFLD_HDCP_STATUS_REG);
+ }
+ }
+ }
+
+ return ret;
+}
+
+/*
+ *
+ * GetHDCPEncryptionLevel:
+ *
+ */
+static void hdcp_get_encryption_level(cp_parameters_t* cp)
+{
+
+ if(hdcp_is_enabled())
+ {
+ cp->level = CP_PROTECTION_LEVEL_HDCP_ON;
+ }
+ else
+ {
+ cp->level = CP_PROTECTION_LEVEL_HDCP_OFF;
+ }
+
+ return ;
+}
+
+/*
+ *
+ * GetCPData: Get Content protection Data
+ * based upon the request from CP
+ *
+ */
+uint32_t hdcp_get_cp_data(cp_parameters_t* cp)
+{
+ uint32_t ret = STATUS_SUCCESS;
+ int is_repeater = 0;
+
+ if((cp->protect_type_mask & CP_PROTECTION_TYPE_HDCP))
+ {
+ //Check whether HDCP is on
+ hdcp_get_encryption_level(cp);
+
+ if (cp->level != CP_PROTECTION_LEVEL_HDCP_OFF)
+ {
+ // see if the link is valid, do it by authenticating
+ if(!hdcp_get_link_status())
+ {
+ // Encryption setting failed; swtich off the encryption
+ cp->level = CP_PROTECTION_LEVEL_HDCP_OFF;
+ hdcp_set_encryption_level(cp);
+ ret = STATUS_UNSUCCESSFUL;
+ }
+ }
+ //else
+ //{
+ //HDCP is off
+ //}
+#if 0 //Don't need this for client
+ //Get the BKSv and repeater status. This has to be returned irrespective of
+ //HDCP is ON or Not
+ if(!hdcp_get_receiver_data((uint8_t*)(cp->hdcp.bksv.ab_ksv), CP_HDCP_KEY_SELECTION_VECTOR_SIZE, RX_TYPE_BKSV_DATA))
+ {
+ cp->hdcp.is_repeater = 0;
+ memset(&(cp->hdcp.bksv), 0, CP_HDCP_KEY_SELECTION_VECTOR_SIZE);
+ ret = STATUS_DATA_ERROR;
+ }
+ else
+ {
+ // This is via opregion. This will return all zeros in production mode
+ // Get the AKSV
+ if(hdcp_get_aksv(&aksv))
+ {
+ memcpy(cp->hdcp.aksv.ab_ksv, aksv.uc_aksv, CP_HDCP_KEY_SELECTION_VECTOR_SIZE);
+ }
+ else // if failed return all zeros
+ {
+ memset(&cp->hdcp.aksv, 0, CP_HDCP_KEY_SELECTION_VECTOR_SIZE);
+ }
+ }
+#endif
+ if(ret != STATUS_DATA_ERROR)
+ {
+ if(hdcp_is_repeater(&is_repeater))
+ {
+ cp->hdcp.is_repeater = is_repeater;
+ }
+ else
+ {
+ cp->hdcp.is_repeater = 0;
+ ret = STATUS_DATA_ERROR;
+ }
+ }
+ }
+#if 0
+ else if(cp->protect_type_mask == CP_PROTECTION_TYPE_NONE)// report repeater capability+BKSV for this mask
+ {
+ if(!hdcp_get_receiver_data((uint8_t*)(cp->hdcp.bksv.ab_ksv), CP_HDCP_KEY_SELECTION_VECTOR_SIZE, RX_TYPE_BKSV_DATA))
+ {
+ cp->hdcp.is_repeater = 0;
+ memset(&(cp->hdcp.bksv), 0, CP_HDCP_KEY_SELECTION_VECTOR_SIZE);
+ }
+ else if(hdcp_is_repeater( &is_repeater))
+ {
+ cp->hdcp.is_repeater = is_repeater;
+ }
+ else
+ {
+ cp->hdcp.is_repeater = 0;
+ }
+
+ // Get the AKSV
+ if(hdcp_get_aksv(&aksv))
+ {
+ memcpy(cp->hdcp.aksv.ab_ksv, aksv.uc_aksv, CP_HDCP_KEY_SELECTION_VECTOR_SIZE);
+ }
+ else // if failed return all zeros
+ {
+ memset(&cp->hdcp.aksv, 0, CP_HDCP_KEY_SELECTION_VECTOR_SIZE);
+ }
+ }
+#endif
+ else //Invalid mask
+ {
+ //assert(0);
+
+ cp->hdcp.is_repeater = 0;
+ //memset(&(cp->hdcp.bksv), 0, CP_HDCP_KEY_SELECTION_VECTOR_SIZE);
+ }
+
+ //Note this data needs to be sent irrespective of any unsupported mask
+ if(ret == STATUS_SUCCESS)
+ {
+ cp->protect_type_mask |= CP_PROTECTION_TYPE_HDCP;
+ }
+
+ return ret;
+}
+
+/*
+ *
+ * SetCPData: Enables/Disables Content protection
+ * based upon the request from CP
+ *
+ */
+uint32_t hdcp_set_cp_data(cp_parameters_t* cp)
+{
+ uint32_t ret = STATUS_UNSUCCESSFUL;
+ int is_repeater = 0;
+
+ if(cp->protect_type_mask & CP_PROTECTION_TYPE_HDCP)
+ {
+ // Get Receiver's repeater status
+ // Note:- Reporting back Repeater status in SetCP Data.
+ // This is because the analyzer for CTS, acts as repeater only
+ // when the test is running, so notifying this back to opm in
+ // SetProtectionLevel.
+ if(hdcp_is_repeater(&is_repeater))
+ {
+ cp->hdcp.is_repeater = is_repeater;
+ }
+
+ // Second step flag is if Repeater support needs to be enabled
+ if(cp->hdcp.perform_second_step)
+ {
+ ret = hdcp_activate_repeater(cp);
+ if((ret != STATUS_SUCCESS) && (ret != STATUS_PENDING))
+ {
+ // Encryption setting failed; switch off the encryption
+ cp->level = CP_PROTECTION_LEVEL_HDCP_OFF;
+ hdcp_set_encryption_level(cp);
+ }
+ }
+ else
+ {
+ ret = hdcp_set_encryption_level(cp);
+
+ if(ret != STATUS_SUCCESS)
+ {
+ // Encryption setting failed; swtich off the encryption
+ cp->level = CP_PROTECTION_LEVEL_HDCP_OFF;
+ hdcp_set_encryption_level(cp);
+ }
+ }
+
+ if(ret == STATUS_SUCCESS)
+ {
+#if 0 //Do need this for client
+ // read the bksv
+ if(!hdcp_get_receiver_data((uint8_t*)(cp->hdcp.bksv.ab_ksv), CP_HDCP_KEY_SELECTION_VECTOR_SIZE, RX_TYPE_BKSV_DATA))
+ {
+ cp->hdcp.is_repeater = 0;
+ memset(&(cp->hdcp.bksv), 0, CP_HDCP_KEY_SELECTION_VECTOR_SIZE);
+ }
+ else
+ {
+ // read aksv
+ if(hdcp_get_aksv(&aksv))
+ {
+ memcpy(cp->hdcp.aksv.ab_ksv,aksv.uc_aksv, CP_HDCP_KEY_SELECTION_VECTOR_SIZE);
+ }
+ else // if failed return all zeros
+ {
+ memset(&cp->hdcp.aksv, 0, CP_HDCP_KEY_SELECTION_VECTOR_SIZE);
+ }
+ }
+#endif
+ cp->protect_type_mask |= CP_PROTECTION_TYPE_HDCP;
+ }
+ }
+ else
+ {
+ // No other calls are handled
+ return STATUS_SUCCESS;
+ }
+
+ return ret;
+}
--- /dev/null
+/*
+ * Copyright © 2010 Intel 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 (including the next
+ * paragraph) 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.
+ *
+ * Authors:
+ * Jim Liu <jim.liu@intel.com>
+ */
+
+#include "mdfld_msic.h"
+#include <drm/drmP.h>
+#include "psb_drv.h"
+#include "psb_intel_hdmi.h"
+#include <asm/intel_scu_ipc.h>
+
+#define SRAM_MSIC_VRINT_ADDR 0xFFFF7FCB
+static u8 __iomem *sram_vreg_addr;
+/*
+ *
+ */
+static struct mid_intel_hdmi_priv *hdmi_priv;
+
+void mdfld_msic_init(struct mid_intel_hdmi_priv *p_hdmi_priv)
+{
+ hdmi_priv = p_hdmi_priv;
+}
+
+/**
+ * hpd_notify_um
+ */
+void hpd_notify_um (void)
+{
+ struct drm_device *dev = hdmi_priv ? hdmi_priv->dev : NULL;
+ struct drm_psb_private *dev_priv = psb_priv(dev);
+ struct pci_dev *pdev = NULL;
+ struct device *ddev = NULL;
+ struct kobject *kobj = NULL;
+
+ if (dev)
+ PSB_DEBUG_ENTRY("\n");
+
+ dev_priv->hdmi_done_reading_edid = false;
+
+ /*find handle to drm kboject*/
+ if(dev == NULL){
+ DRM_ERROR("%s: dev == NULL. \n", __FUNCTION__);
+ return;
+ }
+ pdev = dev->pdev;
+
+ if(pdev == NULL){
+ DRM_ERROR("%s: pdev == NULL. \n", __FUNCTION__);
+ return;
+ }
+ ddev = &pdev->dev;
+
+ if(ddev == NULL){
+ DRM_ERROR("%s: ddev == NULL. \n", __FUNCTION__);
+ return;
+ }
+ kobj = &ddev->kobj;
+
+ if(kobj == NULL){
+ DRM_ERROR("%s: kobj == NULL. \n", __FUNCTION__);
+ return;
+ }
+
+ if (dev_priv->psb_hotplug_state) {
+ DRM_INFO("%s: HPD interrupt. \n", __FUNCTION__);
+ psb_hotplug_notify_change_um("hpd_hdmi", dev_priv->psb_hotplug_state);
+ } else {
+ DRM_ERROR("%s: Hotplug comm layer isn't initialized! \n", __FUNCTION__);
+ }
+
+ return;
+}
+
+/**
+ * msic_vreg_handler
+ */
+static irqreturn_t msic_vreg_handler(int irq, void *dev_id)
+{
+ struct drm_device *dev = hdmi_priv ? hdmi_priv->dev : NULL;
+ struct drm_psb_private *dev_priv = psb_priv(dev);
+ u8 data = 0;
+
+ /* Need to add lock later.*/
+
+ /* Read VREG interrupt status register */
+ if (sram_vreg_addr)
+ data = readb(sram_vreg_addr);
+ else
+ DRM_ERROR("%s: sram_vreg_addr = %p\n", __FUNCTION__, sram_vreg_addr);
+
+ if (dev)
+ PSB_DEBUG_ENTRY("data = 0x%x.\n", data);
+
+ /* handle HDMI HPD interrupts. */
+ if (data & HDMI_HPD_STATUS) {
+ DRM_INFO("%s: HPD interrupt. data = 0x%x. \n", __FUNCTION__, data);
+
+ if (dev_priv->xserver_start)
+ hpd_notify_um();
+ }
+
+ /* handle other msic vreq interrupts when necessary. */
+
+ return IRQ_HANDLED;
+}
+
+/**
+ * msic_probe
+ */
+static int __devinit msic_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ struct drm_device *dev = hdmi_priv ? hdmi_priv->dev : NULL;
+ int ret = 0;
+
+ if (dev)
+ PSB_DEBUG_ENTRY("\n");
+
+ /* enable msic hdmi device */
+ ret = pci_enable_device(pdev);
+
+ if (!ret) {
+
+ if (pdev->device == MSIC_PCI_DEVICE_ID) {
+ sram_vreg_addr = ioremap_nocache(SRAM_MSIC_VRINT_ADDR, 0x2);
+ ret = request_irq(pdev->irq, msic_vreg_handler, IRQF_SHARED, "msic_hdmi_driver",(void *)&hdmi_priv);
+ } else
+ DRM_ERROR("%s: pciid = 0x%x is not msic_hdmi pciid. \n", __FUNCTION__, pdev->device);
+
+ if (!ret) {
+#if 0 /* #ifdef CONFIG_X86_MRST may still be necessary*/
+ u8 data = 0;
+
+ /* clear HDMI HPD */
+ intel_scu_ipc_ioread8(MSIC_VRINT_STATUS, &data);
+ intel_scu_ipc_iowrite8(MSIC_VRINT_STATUS, data);
+
+ /* clear MSIC first level VREG interrupt. */
+ intel_scu_ipc_ioread8(MSIC_IRQLVL1_STATUS, &data);
+ data &= VREG_STATUS;
+ intel_scu_ipc_iowrite8(MSIC_IRQLVL1_STATUS, data);
+
+ /* enable HDMI HPD */
+ intel_scu_ipc_ioread8(MSIC_VRINT_MASK, &data);
+ data &= ~HDMI_HPD_MASK;
+ intel_scu_ipc_iowrite8(MSIC_VRINT_MASK, data);
+
+ /* enable MSIC first level VREG interrupt. */
+ intel_scu_ipc_ioread8(MSIC_IRQLVL1_MASK, &data);
+ data &= ~VREG_MASK;
+ intel_scu_ipc_iowrite8(MSIC_IRQLVL1_MASK, data);
+ /* Enable and handle other msic vreq interrupts when necessary. */
+#endif
+ } else {
+ pci_dev_put(pdev);
+ DRM_ERROR("%s: request_irq failed. ret = 0x%x. \n", __FUNCTION__, ret);
+ }
+ }
+
+ return ret;
+}
+
+static struct pci_device_id msic_pci_id_list[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, MSIC_PCI_DEVICE_ID) },
+ { 0 }
+};
+
+/*MODULE_DEVICE_TABLE(pci, msic_pci_id_list);*/
+
+
+/* field for registering driver to PCI device */
+static struct pci_driver msic_pci_driver = {
+ .name = "msic_hdmi_driver",
+ .id_table = msic_pci_id_list,
+ .probe = msic_probe
+};
+
+/**
+ * msic_regsiter_driver - register the msic hdmi device to PCI system.
+ */
+int msic_regsiter_driver(void)
+{
+ return pci_register_driver(&msic_pci_driver);
+}
+
+/**
+ * msic_unregsiter_driver - unregister the msic hdmi device from PCI system.
+ */
+int msic_unregister_driver(void)
+{
+ if (!sram_vreg_addr) {
+ iounmap(sram_vreg_addr);
+ sram_vreg_addr = NULL;
+ }
+ pci_unregister_driver(&msic_pci_driver);
+ return 0;
+}
--- /dev/null
+/*
+ * Copyright © 2010 Intel 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 (including the next
+ * paragraph) 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.
+ *
+ * Authors:
+ * Jim Liu <jim.liu@intel.com>
+ */
+
+#ifndef MDFLD_MSIC_H
+#define MDFLD_MSIC_H
+
+#include "psb_intel_hdmi.h"
+
+#define MSIC_PCI_DEVICE_ID 0x831
+
+int msic_regsiter_driver(void);
+int msic_unregister_driver(void);
+extern void hpd_notify_um (void);
+void mdfld_msic_init(struct mid_intel_hdmi_priv *p_hdmi_priv);
+
+#endif /* MDFLD_MSIC_H */
--- /dev/null
+/*
+ * Copyright (c) 2010 Intel 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, sublicensen
+ * 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 (including the next
+ * paragraph) 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.
+ *
+ * Authors:
+ * Thomas Eaton <thomas.g.eaton@intel.com>
+ * Scott Rowe <scott.m.rowe@intel.com>
+*/
+
+#include <linux/init.h>
+#include "mdfld_output.h"
+#include "mdfld_dsi_dbi.h"
+#include "mdfld_dsi_dpi.h"
+#include "mdfld_dsi_output.h"
+
+#include "displays/tpo_cmd.h"
+#include "displays/tpo_vid.h"
+#include "displays/tmd_vid.h"
+#include "displays/hdmi.h"
+#include "tc35876x-dsi-lvds.h"
+
+enum panel_type get_panel_type(struct drm_device *dev, int pipe)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) dev->dev_private;
+
+ return dev_priv->panel_id;
+}
+
+int is_panel_vid_or_cmd(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) dev->dev_private;
+
+ int ret = 0;
+ switch(dev_priv->panel_id) {
+ case TMD_VID:
+ case TPO_VID:
+ case TC35876X:
+ ret = MDFLD_DSI_ENCODER_DPI;
+ break;
+ case TMD_CMD:
+ case TPO_CMD:
+ default:
+ ret = MDFLD_DSI_ENCODER_DBI;
+ break;
+ }
+ return ret;
+}
+
+void mdfld_output_init(struct drm_device* dev)
+{
+ enum panel_type p_type1, p_type2;
+
+ /* MIPI panel 1 */
+ p_type1 = get_panel_type(dev, 0);
+ init_panel(dev, 0, p_type1);
+
+#ifdef CONFIG_MDFD_DUAL_MIPI
+ /* MIPI panel 2 */
+ p_type2 = get_panel_type(dev, 2);
+ init_panel(dev, 2, p_type2);
+#endif
+
+#ifdef CONFIG_MDFD_HDMI
+ /* HDMI panel */
+ init_panel(dev, 0, HDMI);
+#endif
+}
+
+void init_panel(struct drm_device* dev, int mipi_pipe, enum panel_type p_type)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) dev->dev_private;
+ struct panel_funcs * p_cmd_funcs = NULL;
+ struct panel_funcs * p_vid_funcs = NULL;
+
+ p_cmd_funcs = kzalloc(sizeof(struct panel_funcs), GFP_KERNEL);
+ p_vid_funcs = kzalloc(sizeof(struct panel_funcs), GFP_KERNEL);
+
+ switch (p_type) {
+ case TPO_CMD:
+ tpo_cmd_init(dev, p_cmd_funcs);
+ mdfld_dsi_output_init(dev, mipi_pipe, NULL, p_cmd_funcs, NULL);
+ break;
+ case TPO_VID:
+ tpo_vid_init(dev, p_vid_funcs);
+ mdfld_dsi_output_init(dev, mipi_pipe, NULL, NULL, p_vid_funcs);
+ break;
+ case TMD_CMD:
+ /*tmd_cmd_init(dev, p_cmd_funcs);*/
+ mdfld_dsi_output_init(dev, mipi_pipe, NULL, p_cmd_funcs, NULL);
+ break;
+ case TC35876X:
+ tc35876x_bridge_init();
+ /* fallthrough */
+ case TMD_VID:
+ tmd_vid_init(dev, p_vid_funcs);
+ mdfld_dsi_output_init(dev, mipi_pipe, NULL, NULL, p_vid_funcs);
+ break;
+ case TPO: /*TPO panel supports both cmd & vid interfaces*/
+ tpo_cmd_init(dev, p_cmd_funcs);
+ tpo_vid_init(dev, p_vid_funcs);
+ mdfld_dsi_output_init(dev, mipi_pipe, NULL, p_cmd_funcs, p_vid_funcs);
+ break;
+ case TMD:
+ break;
+ case HDMI:
+ /*hdmi_init(dev);*/
+ printk(KERN_ALERT "GFX: Initializing HDMI");
+ mdfld_hdmi_init(dev, &dev_priv->mode_dev);
+ /*hdmi_output_init(dev);*/
+ break;
+ default:
+ break;
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2010 Intel 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, sublicensen
+ * 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 (including the next
+ * paragraph) 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.
+ *
+ * Authors:
+ * Thomas Eaton <thomas.g.eaton@intel.com>
+ * Scott Rowe <scott.m.rowe@intel.com>
+*/
+
+
+
+#ifndef MDFLD_OUTPUT_H
+#define MDFLD_OUTPUT_H
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_edid.h>
+
+#include "psb_drv.h"
+
+#define TPO_PANEL_WIDTH 84
+#define TPO_PANEL_HEIGHT 46
+#define TMD_PANEL_WIDTH 39
+#define TMD_PANEL_HEIGHT 71
+
+struct mdfld_dsi_config;
+
+struct panel_info {
+ u32 width_mm;
+ u32 height_mm;
+
+ /*other infos*/
+};
+
+struct panel_funcs {
+ const struct drm_encoder_funcs* encoder_funcs;
+ const struct drm_encoder_helper_funcs* encoder_helper_funcs;
+ struct drm_display_mode* (*get_config_mode)(struct drm_device*);
+ void (*update_fb)(struct mdfld_dsi_dbi_output*, int);
+ int (*get_panel_info)(struct drm_device *, int, struct panel_info *);
+ int (*reset)(int pipe);
+ void (*drv_ic_init)(struct mdfld_dsi_config *dsi_config, int pipe);
+};
+
+void mdfld_output_init(struct drm_device* dev);
+
+void init_panel(struct drm_device* dev, int mipi_pipe, enum panel_type p_type);
+enum panel_type get_panel_type(struct drm_device *dev, int pipe);
+int is_panel_vid_or_cmd(struct drm_device *dev);
+
+
+#endif
+
+
--- /dev/null
+/*
+ * psb backlight using HAL
+ *
+ * Copyright (c) 2009, Intel Corporation.
+ *
+ * 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 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.
+ *
+ * Authors: Eric Knopp
+ *
+ */
+
+#include <linux/backlight.h>
+#include <linux/version.h>
+#include <asm/intel_scu_ipc.h>
+#include "psb_drv.h"
+#include "psb_intel_reg.h"
+#include "psb_intel_drv.h"
+#include "psb_powermgmt.h"
+#include "mdfld_dsi_dbi.h"
+
+#define MRST_BLC_MAX_PWM_REG_FREQ 0xFFFF
+#define BLC_PWM_PRECISION_FACTOR 100 /* 10000000 */
+#define BLC_PWM_FREQ_CALC_CONSTANT 32
+#define MHz 1000000
+#define BRIGHTNESS_MIN_LEVEL 1
+#define BRIGHTNESS_MAX_LEVEL 100
+#define BRIGHTNESS_MASK 0xFF
+#define BLC_POLARITY_NORMAL 0
+#define BLC_POLARITY_INVERSE 1
+#define BLC_ADJUSTMENT_MAX 100
+
+#define PSB_BLC_PWM_PRECISION_FACTOR 10
+#define PSB_BLC_MAX_PWM_REG_FREQ 0xFFFE
+#define PSB_BLC_MIN_PWM_REG_FREQ 0x2
+
+#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
+#define PSB_BACKLIGHT_PWM_CTL_SHIFT (16)
+
+static int psb_brightness;
+static struct backlight_device *psb_backlight_device;
+
+int psb_set_brightness(struct backlight_device *bd)
+{
+ struct drm_device *dev = (struct drm_device *)bl_get_data(psb_backlight_device);
+ struct drm_psb_private *dev_priv = (struct drm_psb_private *) dev->dev_private;
+ int level = bd->props.brightness;
+
+ DRM_DEBUG_DRIVER("backlight level set to %d\n", level);
+
+ /* Perform value bounds checking */
+ if (level < BRIGHTNESS_MIN_LEVEL)
+ level = BRIGHTNESS_MIN_LEVEL;
+
+ if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
+ OSPM_UHB_ONLY_IF_ON)) {
+ u32 adjusted_level = 0;
+
+ /*
+ * Adjust the backlight level with the percent in
+ * dev_priv->blc_adj2
+ */
+ adjusted_level = level * dev_priv->blc_adj2;
+ adjusted_level = adjusted_level / BLC_ADJUSTMENT_MAX;
+
+#ifndef CONFIG_MDFLD_DSI_DPU
+ if((!(dev_priv->dsr_fb_update & MDFLD_DSR_MIPI_CONTROL)) &&
+ (dev_priv->dbi_panel_on || dev_priv->dbi_panel_on2)){
+ mdfld_dsi_dbi_exit_dsr(dev,MDFLD_DSR_MIPI_CONTROL);
+ PSB_DEBUG_ENTRY("Out of DSR before set brightness to %d.\n",adjusted_level);
+ }
+#endif
+ if (get_panel_type(dev, 0) == TC35876X) {
+ mdfld_dsi_brightness_control(dev, 0, adjusted_level);
+ } else {
+ if (dev_priv->dbi_panel_on || dev_priv->dpi_panel_on)
+ mdfld_dsi_brightness_control(dev, 0,
+ adjusted_level);
+ }
+
+ if ((dev_priv->dbi_panel_on2) || (dev_priv->dpi_panel_on2))
+ mdfld_dsi_brightness_control(dev, 2, adjusted_level);
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+ }
+
+ /* cache the brightness for later use */
+ psb_brightness = level;
+ return 0;
+}
+
+int psb_get_brightness(struct backlight_device *bd)
+{
+ DRM_DEBUG_DRIVER("brightness = 0x%x \n", psb_brightness);
+
+ /* return locally cached var instead of HW read (due to DPST etc.) */
+ return psb_brightness;
+}
+
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+static struct backlight_ops psb_ops = {
+ .get_brightness = psb_get_brightness,
+ .update_status = psb_set_brightness,
+};
+
+static int device_backlight_init(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = (struct drm_psb_private *)
+ dev->dev_private;
+
+ dev_priv->blc_adj1 = BLC_ADJUSTMENT_MAX;
+ dev_priv->blc_adj2 = BLC_ADJUSTMENT_MAX;
+
+ return 0;
+}
+#endif
+
+int psb_backlight_init(struct drm_device *dev)
+{
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+ struct drm_psb_private *dev_priv = (struct drm_psb_private *) dev->dev_private;
+ struct backlight_properties props;
+ uint8_t data = 0;
+ int ret = 0;
+
+ dev_priv->b_pmic_backlight = false;
+
+ memset(&props, 0, sizeof(struct backlight_properties));
+ props.max_brightness = BRIGHTNESS_MAX_LEVEL;
+ props.type = BACKLIGHT_PLATFORM;
+ psb_backlight_device = backlight_device_register("psb-bl", NULL, (void *)dev, &psb_ops, &props);
+
+ if (IS_ERR(psb_backlight_device))
+ return PTR_ERR(psb_backlight_device);
+
+ if ((ret = device_backlight_init(dev)) != 0)
+ return ret;
+
+ psb_backlight_device->props.brightness = BRIGHTNESS_MAX_LEVEL;
+ psb_backlight_device->props.max_brightness = BRIGHTNESS_MAX_LEVEL;
+ if (dev_priv->b_pmic_backlight) {
+ intel_scu_ipc_ioread8(0x28, &data);
+ dev_priv->saveBKLTCNT = data;
+ intel_scu_ipc_ioread8(0x29, &data);
+ dev_priv->saveBKLTREQ = data;
+ intel_scu_ipc_ioread8(0x2A, &data);
+ dev_priv->saveBKLTBRTL = data;
+ }
+ backlight_update_status(psb_backlight_device);
+#endif
+ return 0;
+}
+
+void psb_backlight_exit(void)
+{
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+ psb_backlight_device->props.brightness = 0;
+ backlight_update_status(psb_backlight_device);
+ backlight_device_unregister(psb_backlight_device);
+#endif
+ return;
+}
+
+struct backlight_device * psb_get_backlight_device(void)
+{
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+ return psb_backlight_device;
+#endif
+ return NULL;
+}
--- /dev/null
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * 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 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.
+ *
+ * Authors:
+ * James C. Gualario <james.c.gualario@intel.com>
+ *
+ */
+
+#include "psb_umevents.h"
+#include "psb_dpst.h"
+/**
+ * inform the kernel of the work to be performed and related function.
+ *
+ */
+static DECLARE_WORK(dpst_dev_change_work, &psb_dpst_dev_change_wq);
+/**
+ * psb_dpst_notify_change_um - notify user mode of hotplug changes
+ *
+ * @name: name of event to notify user mode of change to
+ * @state: dpst state struct to get workqueue from
+ *
+ */
+int psb_dpst_notify_change_um(enum dpst_event_enum event,
+ struct dpst_state *state)
+{
+ if (state == NULL)
+ return IRQ_HANDLED;
+
+ state->dpst_change_wq_data.dev_name_arry_rw_status
+ [state->dpst_change_wq_data.dev_name_write] =
+ DRM_DPST_READY_TO_READ;
+ state->dpst_change_wq_data.dpst_events
+ [state->dpst_change_wq_data.dev_name_write] =
+ event;
+ if (state->dpst_change_wq_data.dev_name_read_write_wrap_ack == 1)
+ state->dpst_change_wq_data.dev_name_read_write_wrap_ack = 0;
+ state->dpst_change_wq_data.dev_name_write++;
+ if (state->dpst_change_wq_data.dev_name_write ==
+ state->dpst_change_wq_data.dev_name_read) {
+ state->dpst_change_wq_data.dev_name_write--;
+ return IRQ_NONE;
+ }
+ if (state->dpst_change_wq_data.dev_name_write >
+ DRM_DPST_RING_DEPTH_MAX) {
+ state->dpst_change_wq_data.dev_name_write = 0;
+ state->dpst_change_wq_data.dev_name_write_wrap = 1;
+ }
+ state->dpst_change_wq_data.hotplug_dev_list = state->list;
+ queue_work(state->dpst_wq, &(state->dpst_change_wq_data.work));
+ return IRQ_HANDLED;
+}
+/*EXPORT_SYMBOL(psb_dpst_notify_change_um); */
+/**
+ *
+ * psb_dpst_create_and_notify_um - create and notify user mode of new dev
+ *
+ * @name: name to give for new event / device
+ * @state: dpst state instaces to associate event with
+ *
+ */
+struct umevent_obj *psb_dpst_create_and_notify_um(const char *name,
+ struct dpst_state *state)
+{
+ return psb_create_umevent_obj(name, state->list);
+
+}
+/*EXPORT_SYMBOL(psb_dpst_create_and_notify_um); */
+/**
+ * psb_dpst_device_pool_create_and_init - make new hotplug device pool
+ *
+ * @parent_kobj - parent kobject to associate dpst kset with
+ * @state - dpst state instance to associate list with
+ *
+ */
+struct umevent_list *psb_dpst_device_pool_create_and_init(
+ struct kobject *parent_kobj,
+ struct dpst_state *state)
+{
+ struct umevent_list *new_hotplug_dev_list = NULL;
+ new_hotplug_dev_list = psb_umevent_create_list();
+ if (new_hotplug_dev_list)
+ psb_umevent_init(parent_kobj, new_hotplug_dev_list,
+ "psb_dpst");
+
+ state->dpst_wq = create_singlethread_workqueue("dpst-wq");
+
+ if (!state->dpst_wq)
+ return NULL;
+
+ INIT_WORK(&state->dpst_change_wq_data.work, psb_dpst_dev_change_wq);
+
+ state->dpst_change_wq_data.dev_name_read = 0;
+ state->dpst_change_wq_data.dev_name_write = 0;
+ state->dpst_change_wq_data.dev_name_write_wrap = 0;
+ state->dpst_change_wq_data.dev_name_read_write_wrap_ack = 0;
+
+ memset(&(state->dpst_change_wq_data.dev_name_arry_rw_status[0]),
+ 0, sizeof(int)*DRM_DPST_RING_DEPTH);
+
+ return new_hotplug_dev_list;
+}
+/*EXPORT_SYMBOL(psb_dpst_device_pool_create_and_init); */
+/**
+ * psb_dpst_init - init dpst subsystem
+ * @parent_kobj - parent kobject to associate dpst state with
+ *
+ */
+struct dpst_state *psb_dpst_init(struct kobject *parent_kobj)
+{
+ struct dpst_state *state;
+ struct umevent_obj *working_umevent;
+
+ state = kzalloc(sizeof(struct dpst_state), GFP_KERNEL);
+ state->list = NULL;
+ state->list = psb_dpst_device_pool_create_and_init(
+ parent_kobj,
+ state);
+ working_umevent =
+ psb_dpst_create_and_notify_um("init",
+ state);
+ state->dpst_change_wq_data.dev_umevent_arry
+ [DPST_EVENT_INIT_COMPLETE] = &(working_umevent->head);
+ working_umevent =
+ psb_dpst_create_and_notify_um("hist_int",
+ state);
+ state->dpst_change_wq_data.dev_umevent_arry
+ [DPST_EVENT_HIST_INTERRUPT] = &(working_umevent->head);
+ working_umevent =
+ psb_dpst_create_and_notify_um("term",
+ state);
+ state->dpst_change_wq_data.dev_umevent_arry
+ [DPST_EVENT_TERMINATE] = &(working_umevent->head);
+ working_umevent =
+ psb_dpst_create_and_notify_um("phase_done",
+ state);
+ state->dpst_change_wq_data.dev_umevent_arry
+ [DPST_EVENT_PHASE_COMPLETE] = &(working_umevent->head);
+
+ return state;
+}
+/*EXPORT_SYMBOL(psb_dpst_init); */
+/**
+ * psb_dpst_device_pool_destroy - destroy all dpst related resources
+ *
+ * @state: dpst state instance to destroy
+ *
+ */
+void psb_dpst_device_pool_destroy(struct dpst_state *state)
+{
+ int i;
+ struct umevent_list *list;
+ struct umevent_obj *umevent_test;
+ list = state->list;
+ flush_workqueue(state->dpst_wq);
+ destroy_workqueue(state->dpst_wq);
+ for (i = 0; i < DRM_DPST_MAX_NUM_EVENTS; i++) {
+ umevent_test = list_entry(
+ (state->dpst_change_wq_data.dev_umevent_arry[i]),
+ struct umevent_obj, head);
+ state->dpst_change_wq_data.dev_umevent_arry[i] = NULL;
+ }
+ psb_umevent_cleanup(list);
+ kfree(state);
+}
+/*EXPORT_SYMBOL(psb_dpst_device_pool_destroy); */
+/**
+ * psb_dpst_dev_change_wq - change workqueue implementation
+ *
+ * @work: work struct to use for kernel scheduling
+ *
+ */
+void psb_dpst_dev_change_wq(struct work_struct *work)
+{
+ struct dpst_disp_workqueue_data *wq_data;
+ int curr_event_index;
+ wq_data = to_dpst_disp_workqueue_data(work);
+ if (wq_data->dev_name_write_wrap == 1) {
+ wq_data->dev_name_read_write_wrap_ack = 1;
+ wq_data->dev_name_write_wrap = 0;
+ while (wq_data->dev_name_read != DRM_DPST_RING_DEPTH_MAX) {
+ if (wq_data->dev_name_arry_rw_status
+ [wq_data->dev_name_read] ==
+ DRM_DPST_READY_TO_READ) {
+ wq_data->dev_name_arry_rw_status
+ [wq_data->dev_name_read] =
+ DRM_DPST_READ_COMPLETE;
+ curr_event_index = wq_data->dpst_events
+ [wq_data->dev_name_read];
+ psb_umevent_notify_change_gfxsock
+ (list_entry(
+ (wq_data->dev_umevent_arry
+ [curr_event_index]),
+ struct umevent_obj, head),
+ DRM_DPST_SOCKET_GROUP_ID);
+ }
+ wq_data->dev_name_read++;
+ }
+ wq_data->dev_name_read = 0;
+ while (wq_data->dev_name_read < wq_data->dev_name_write-1) {
+ if (wq_data->dev_name_arry_rw_status
+ [wq_data->dev_name_read] ==
+ DRM_DPST_READY_TO_READ) {
+ wq_data->dev_name_arry_rw_status
+ [wq_data->dev_name_read] =
+ DRM_DPST_READ_COMPLETE;
+ curr_event_index = wq_data->dpst_events
+ [wq_data->dev_name_read];
+ psb_umevent_notify_change_gfxsock
+ (list_entry(
+ (wq_data->dev_umevent_arry
+ [curr_event_index]),
+ struct umevent_obj, head),
+ DRM_DPST_SOCKET_GROUP_ID);
+ }
+ wq_data->dev_name_read++;
+ }
+ } else {
+ while (wq_data->dev_name_read < wq_data->dev_name_write) {
+ if (wq_data->dev_name_arry_rw_status
+ [wq_data->dev_name_read] ==
+ DRM_DPST_READY_TO_READ) {
+ wq_data->dev_name_arry_rw_status
+ [wq_data->dev_name_read] =
+ DRM_DPST_READ_COMPLETE;
+ curr_event_index = wq_data->dpst_events
+ [wq_data->dev_name_read];
+ psb_umevent_notify_change_gfxsock
+ (list_entry(
+ (wq_data->dev_umevent_arry
+ [curr_event_index]),
+ struct umevent_obj, head),
+ DRM_DPST_SOCKET_GROUP_ID);
+ }
+ wq_data->dev_name_read++;
+ }
+ }
+ if (wq_data->dev_name_read > DRM_DPST_RING_DEPTH_MAX)
+ wq_data->dev_name_read = 0;
+}
+/*EXPORT_SYMBOL(psb_dpst_dev_change_wq); */
--- /dev/null
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * 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 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.
+ *
+ * Authors:
+ * James C. Gualario <james.c.gualario@intel.com>
+ *
+ */
+
+#ifndef _PSB_DPST_H_
+#define _PSB_DPST_H_
+/**
+ * required includes
+ *
+ */
+#include "psb_umevents.h"
+/**
+ * dpst event enumeration
+ *
+ */
+enum dpst_event_enum {
+ DPST_EVENT_INIT_COMPLETE,
+ DPST_EVENT_HIST_INTERRUPT,
+ DPST_EVENT_TERMINATE,
+ DPST_EVENT_PHASE_COMPLETE,
+ DPST_MAX_EVENT
+};
+/**
+ * dpst specific defines
+ *
+ */
+#define DRM_DPST_RING_DEPTH 256
+#define DRM_DPST_RING_DEPTH_MAX (DRM_DPST_RING_DEPTH-1)
+#define DRM_DPST_READY_TO_READ 1
+#define DRM_DPST_READ_COMPLETE 2
+#define DRM_DPST_MAX_NUM_EVENTS (DPST_MAX_EVENT)
+/**
+ * dpst workqueue data struct.
+ */
+struct dpst_disp_workqueue_data {
+ struct work_struct work;
+ const char *dev_name;
+ int dev_name_write;
+ int dev_name_read;
+ int dev_name_write_wrap;
+ int dev_name_read_write_wrap_ack;
+ enum dpst_event_enum dpst_events[DRM_DPST_RING_DEPTH];
+ int dev_name_arry_rw_status[DRM_DPST_RING_DEPTH];
+ struct umevent_list *hotplug_dev_list;
+ struct list_head *dev_umevent_arry[DRM_DPST_MAX_NUM_EVENTS];
+};
+/**
+ * dpst state structure
+ *
+ */
+struct dpst_state {
+ struct workqueue_struct *dpst_wq;
+ struct dpst_disp_workqueue_data dpst_change_wq_data;
+ struct umevent_list *list;
+};
+/**
+ * main interface function prototytpes for dpst support.
+ *
+ */
+extern struct dpst_state *psb_dpst_init(struct kobject *parent_kobj);
+extern int psb_dpst_notify_change_um(enum dpst_event_enum event,
+ struct dpst_state *state);
+extern struct umevent_obj *psb_dpst_create_and_notify_um(const char *name,
+ struct dpst_state *state);
+extern struct umevent_list *psb_dpst_device_pool_create_and_init(
+ struct kobject *parent_kobj,
+ struct dpst_state *state);
+extern void psb_dpst_device_pool_destroy(struct dpst_state *state);
+/**
+ * to go back and forth between work struct and workqueue data
+ *
+ */
+#define to_dpst_disp_workqueue_data(x) \
+ container_of(x, struct dpst_disp_workqueue_data, work)
+
+/**
+ * function prototypes for workqueue implementation
+ *
+ */
+extern void psb_dpst_dev_change_wq(struct work_struct *work);
+#endif
--- /dev/null
+/**************************************************************************
+ * Copyright (c) 2007, Intel Corporation.
+ * All Rights Reserved.
+ * Copyright (c) 2008, Tungsten Graphics Inc. Cedar Park, TX., USA.
+ * 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 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.
+ *
+ **************************************************************************/
+
+#ifndef _PSB_DRM_H_
+#define _PSB_DRM_H_
+
+#if defined(__linux__) && !defined(__KERNEL__)
+#include<stdint.h>
+#include <linux/types.h>
+#include "drm_mode.h"
+#endif
+
+#include "psb_ttm_fence_user.h"
+#include "psb_ttm_placement_user.h"
+
+/*
+ * Menlow/MRST graphics driver package version
+ * a.b.c.xxxx
+ * a - Product Family: 5 - Linux
+ * b - Major Release Version: 0 - non-Gallium (Unbuntu);
+ * 1 - Gallium (Moblin2)
+ * c - Hotfix Release
+ * xxxx - Graphics internal build #
+ */
+#define PSB_PACKAGE_VERSION "5.3.0.32L.0047"
+
+#define DRM_PSB_SAREA_MAJOR 0
+#define DRM_PSB_SAREA_MINOR 2
+#define PSB_FIXED_SHIFT 16
+
+#define PSB_NUM_PIPE 3
+
+/*
+ * Public memory types.
+ */
+
+#define DRM_PSB_MEM_MMU TTM_PL_PRIV1
+#define DRM_PSB_FLAG_MEM_MMU TTM_PL_FLAG_PRIV1
+
+#define TTM_PL_CI TTM_PL_PRIV0
+#define TTM_PL_FLAG_CI TTM_PL_FLAG_PRIV0
+
+#define TTM_PL_RAR TTM_PL_PRIV2
+#define TTM_PL_FLAG_RAR TTM_PL_FLAG_PRIV2
+
+typedef int32_t psb_fixed;
+typedef uint32_t psb_ufixed;
+
+static inline int32_t psb_int_to_fixed(int a)
+{
+ return a * (1 << PSB_FIXED_SHIFT);
+}
+
+static inline uint32_t psb_unsigned_to_ufixed(unsigned int a)
+{
+ return a << PSB_FIXED_SHIFT;
+}
+
+/*Status of the command sent to the gfx device.*/
+typedef enum {
+ DRM_CMD_SUCCESS,
+ DRM_CMD_FAILED,
+ DRM_CMD_HANG
+} drm_cmd_status_t;
+
+struct drm_psb_scanout {
+ uint32_t buffer_id; /* DRM buffer object ID */
+ uint32_t rotation; /* Rotation as in RR_rotation definitions */
+ uint32_t stride; /* Buffer stride in bytes */
+ uint32_t depth; /* Buffer depth in bits (NOT) bpp */
+ uint32_t width; /* Buffer width in pixels */
+ uint32_t height; /* Buffer height in lines */
+ int32_t transform[3][3]; /* Buffer composite transform */
+ /* (scaling, rot, reflect) */
+};
+
+#define DRM_PSB_SAREA_OWNERS 16
+#define DRM_PSB_SAREA_OWNER_2D 0
+#define DRM_PSB_SAREA_OWNER_3D 1
+
+#define DRM_PSB_SAREA_SCANOUTS 3
+
+struct drm_psb_sarea {
+ /* Track changes of this data structure */
+
+ uint32_t major;
+ uint32_t minor;
+
+ /* Last context to touch part of hw */
+ uint32_t ctx_owners[DRM_PSB_SAREA_OWNERS];
+
+ /* Definition of front- and rotated buffers */
+ uint32_t num_scanouts;
+ struct drm_psb_scanout scanouts[DRM_PSB_SAREA_SCANOUTS];
+
+ int planeA_x;
+ int planeA_y;
+ int planeA_w;
+ int planeA_h;
+ int planeB_x;
+ int planeB_y;
+ int planeB_w;
+ int planeB_h;
+ /* Number of active scanouts */
+ uint32_t num_active_scanouts;
+};
+
+#define PSB_RELOC_MAGIC 0x67676767
+#define PSB_RELOC_SHIFT_MASK 0x0000FFFF
+#define PSB_RELOC_SHIFT_SHIFT 0
+#define PSB_RELOC_ALSHIFT_MASK 0xFFFF0000
+#define PSB_RELOC_ALSHIFT_SHIFT 16
+
+#define PSB_RELOC_OP_OFFSET 0 /* Offset of the indicated
+ * buffer
+ */
+
+struct drm_psb_reloc {
+ uint32_t reloc_op;
+ uint32_t where; /* offset in destination buffer */
+ uint32_t buffer; /* Buffer reloc applies to */
+ uint32_t mask; /* Destination format: */
+ uint32_t shift; /* Destination format: */
+ uint32_t pre_add; /* Destination format: */
+ uint32_t background; /* Destination add */
+ uint32_t dst_buffer; /* Destination buffer. Index into buffer_list */
+ uint32_t arg0; /* Reloc-op dependant */
+ uint32_t arg1;
+};
+
+
+#define PSB_GPU_ACCESS_READ (1ULL << 32)
+#define PSB_GPU_ACCESS_WRITE (1ULL << 33)
+#define PSB_GPU_ACCESS_MASK (PSB_GPU_ACCESS_READ | PSB_GPU_ACCESS_WRITE)
+
+#define PSB_BO_FLAG_COMMAND (1ULL << 52)
+
+#define PSB_ENGINE_2D 0
+#define PSB_ENGINE_VIDEO 1
+#define LNC_ENGINE_ENCODE 5
+
+/*
+ * For this fence class we have a couple of
+ * fence types.
+ */
+
+#define _PSB_FENCE_EXE_SHIFT 0
+#define _PSB_FENCE_FEEDBACK_SHIFT 4
+
+#define _PSB_FENCE_TYPE_EXE (1 << _PSB_FENCE_EXE_SHIFT)
+#define _PSB_FENCE_TYPE_FEEDBACK (1 << _PSB_FENCE_FEEDBACK_SHIFT)
+
+#define PSB_NUM_ENGINES 6
+
+
+#define PSB_FEEDBACK_OP_VISTEST (1 << 0)
+
+struct drm_psb_extension_rep {
+ int32_t exists;
+ uint32_t driver_ioctl_offset;
+ uint32_t sarea_offset;
+ uint32_t major;
+ uint32_t minor;
+ uint32_t pl;
+};
+
+#define DRM_PSB_EXT_NAME_LEN 128
+
+union drm_psb_extension_arg {
+ char extension[DRM_PSB_EXT_NAME_LEN];
+ struct drm_psb_extension_rep rep;
+};
+
+struct psb_validate_req {
+ uint64_t set_flags;
+ uint64_t clear_flags;
+ uint64_t next;
+ uint64_t presumed_gpu_offset;
+ uint32_t buffer_handle;
+ uint32_t presumed_flags;
+ uint32_t group;
+ uint32_t pad64;
+};
+
+struct psb_validate_rep {
+ uint64_t gpu_offset;
+ uint32_t placement;
+ uint32_t fence_type_mask;
+};
+
+#define PSB_USE_PRESUMED (1 << 0)
+
+struct psb_validate_arg {
+ int handled;
+ int ret;
+ union {
+ struct psb_validate_req req;
+ struct psb_validate_rep rep;
+ } d;
+};
+
+
+#define DRM_PSB_FENCE_NO_USER (1 << 0)
+
+struct psb_ttm_fence_rep {
+ uint32_t handle;
+ uint32_t fence_class;
+ uint32_t fence_type;
+ uint32_t signaled_types;
+ uint32_t error;
+};
+
+typedef struct drm_psb_cmdbuf_arg {
+ uint64_t buffer_list; /* List of buffers to validate */
+ uint64_t clip_rects; /* See i915 counterpart */
+ uint64_t scene_arg;
+ uint64_t fence_arg;
+
+ uint32_t ta_flags;
+
+ uint32_t ta_handle; /* TA reg-value pairs */
+ uint32_t ta_offset;
+ uint32_t ta_size;
+
+ uint32_t oom_handle;
+ uint32_t oom_offset;
+ uint32_t oom_size;
+
+ uint32_t cmdbuf_handle; /* 2D Command buffer object or, */
+ uint32_t cmdbuf_offset; /* rasterizer reg-value pairs */
+ uint32_t cmdbuf_size;
+
+ uint32_t reloc_handle; /* Reloc buffer object */
+ uint32_t reloc_offset;
+ uint32_t num_relocs;
+
+ int32_t damage; /* Damage front buffer with cliprects */
+ /* Not implemented yet */
+ uint32_t fence_flags;
+ uint32_t engine;
+
+ /*
+ * Feedback;
+ */
+
+ uint32_t feedback_ops;
+ uint32_t feedback_handle;
+ uint32_t feedback_offset;
+ uint32_t feedback_breakpoints;
+ uint32_t feedback_size;
+} drm_psb_cmdbuf_arg_t;
+
+typedef struct drm_psb_pageflip_arg {
+ uint32_t flip_offset;
+ uint32_t stride;
+} drm_psb_pageflip_arg_t;
+
+typedef enum {
+ LNC_VIDEO_DEVICE_INFO,
+ LNC_VIDEO_GETPARAM_RAR_INFO,
+ LNC_VIDEO_GETPARAM_CI_INFO,
+ LNC_VIDEO_GETPARAM_RAR_HANDLER_OFFSET,
+ LNC_VIDEO_FRAME_SKIP,
+ IMG_VIDEO_DECODE_STATUS,
+ IMG_VIDEO_NEW_CONTEXT,
+ IMG_VIDEO_RM_CONTEXT,
+ IMG_VIDEO_MB_ERROR
+} lnc_getparam_key_t;
+
+struct drm_lnc_video_getparam_arg {
+ lnc_getparam_key_t key;
+ uint64_t arg; /* argument pointer */
+ uint64_t value; /* feed back pointer */
+};
+
+
+/*
+ * Feedback components:
+ */
+
+/*
+ * Vistest component. The number of these in the feedback buffer
+ * equals the number of vistest breakpoints + 1.
+ * This is currently the only feedback component.
+ */
+
+struct drm_psb_vistest {
+ uint32_t vt[8];
+};
+
+struct drm_psb_sizes_arg {
+ uint32_t ta_mem_size;
+ uint32_t mmu_size;
+ uint32_t pds_size;
+ uint32_t rastgeom_size;
+ uint32_t tt_size;
+ uint32_t vram_size;
+};
+
+struct drm_psb_hist_status_arg {
+ uint32_t buf[32];
+};
+
+struct drm_psb_dpst_lut_arg {
+ uint8_t lut[256];
+ int output_id;
+};
+
+struct mrst_timing_info {
+ uint16_t pixel_clock;
+ uint8_t hactive_lo;
+ uint8_t hblank_lo;
+ uint8_t hblank_hi:4;
+ uint8_t hactive_hi:4;
+ uint8_t vactive_lo;
+ uint8_t vblank_lo;
+ uint8_t vblank_hi:4;
+ uint8_t vactive_hi:4;
+ uint8_t hsync_offset_lo;
+ uint8_t hsync_pulse_width_lo;
+ uint8_t vsync_pulse_width_lo:4;
+ uint8_t vsync_offset_lo:4;
+ uint8_t vsync_pulse_width_hi:2;
+ uint8_t vsync_offset_hi:2;
+ uint8_t hsync_pulse_width_hi:2;
+ uint8_t hsync_offset_hi:2;
+ uint8_t width_mm_lo;
+ uint8_t height_mm_lo;
+ uint8_t height_mm_hi:4;
+ uint8_t width_mm_hi:4;
+ uint8_t hborder;
+ uint8_t vborder;
+ uint8_t unknown0:1;
+ uint8_t hsync_positive:1;
+ uint8_t vsync_positive:1;
+ uint8_t separate_sync:2;
+ uint8_t stereo:1;
+ uint8_t unknown6:1;
+ uint8_t interlaced:1;
+} __attribute__((packed));
+
+struct gct_r10_timing_info {
+ uint16_t pixel_clock;
+ uint32_t hactive_lo:8;
+ uint32_t hactive_hi:4;
+ uint32_t hblank_lo:8;
+ uint32_t hblank_hi:4;
+ uint32_t hsync_offset_lo:8;
+ uint16_t hsync_offset_hi:2;
+ uint16_t hsync_pulse_width_lo:8;
+ uint16_t hsync_pulse_width_hi:2;
+ uint16_t hsync_positive:1;
+ uint16_t rsvd_1:3;
+ uint8_t vactive_lo:8;
+ uint16_t vactive_hi:4;
+ uint16_t vblank_lo:8;
+ uint16_t vblank_hi:4;
+ uint16_t vsync_offset_lo:4;
+ uint16_t vsync_offset_hi:2;
+ uint16_t vsync_pulse_width_lo:4;
+ uint16_t vsync_pulse_width_hi:2;
+ uint16_t vsync_positive:1;
+ uint16_t rsvd_2:3;
+} __attribute__((packed));
+
+struct mrst_panel_descriptor_v1{
+ uint32_t Panel_Port_Control; /* 1 dword, Register 0x61180 if LVDS */
+ /* 0x61190 if MIPI */
+ uint32_t Panel_Power_On_Sequencing;/*1 dword,Register 0x61208,*/
+ uint32_t Panel_Power_Off_Sequencing;/*1 dword,Register 0x6120C,*/
+ uint32_t Panel_Power_Cycle_Delay_and_Reference_Divisor;/* 1 dword */
+ /* Register 0x61210 */
+ struct mrst_timing_info DTD;/*18 bytes, Standard definition */
+ uint16_t Panel_Backlight_Inverter_Descriptor;/* 16 bits, as follows */
+ /* Bit 0, Frequency, 15 bits,0 - 32767Hz */
+ /* Bit 15, Polarity, 1 bit, 0: Normal, 1: Inverted */
+ uint16_t Panel_MIPI_Display_Descriptor;
+ /*16 bits, Defined as follows: */
+ /* if MIPI, 0x0000 if LVDS */
+ /* Bit 0, Type, 2 bits, */
+ /* 0: Type-1, */
+ /* 1: Type-2, */
+ /* 2: Type-3, */
+ /* 3: Type-4 */
+ /* Bit 2, Pixel Format, 4 bits */
+ /* Bit0: 16bpp (not supported in LNC), */
+ /* Bit1: 18bpp loosely packed, */
+ /* Bit2: 18bpp packed, */
+ /* Bit3: 24bpp */
+ /* Bit 6, Reserved, 2 bits, 00b */
+ /* Bit 8, Minimum Supported Frame Rate, 6 bits, 0 - 63Hz */
+ /* Bit 14, Reserved, 2 bits, 00b */
+} __attribute__ ((packed));
+
+struct mrst_panel_descriptor_v2{
+ uint32_t Panel_Port_Control; /* 1 dword, Register 0x61180 if LVDS */
+ /* 0x61190 if MIPI */
+ uint32_t Panel_Power_On_Sequencing;/*1 dword,Register 0x61208,*/
+ uint32_t Panel_Power_Off_Sequencing;/*1 dword,Register 0x6120C,*/
+ uint8_t Panel_Power_Cycle_Delay_and_Reference_Divisor;/* 1 byte */
+ /* Register 0x61210 */
+ struct mrst_timing_info DTD;/*18 bytes, Standard definition */
+ uint16_t Panel_Backlight_Inverter_Descriptor;/*16 bits, as follows*/
+ /*Bit 0, Frequency, 16 bits, 0 - 32767Hz*/
+ uint8_t Panel_Initial_Brightness;/* [7:0] 0 - 100% */
+ /*Bit 7, Polarity, 1 bit,0: Normal, 1: Inverted*/
+ uint16_t Panel_MIPI_Display_Descriptor;
+ /*16 bits, Defined as follows: */
+ /* if MIPI, 0x0000 if LVDS */
+ /* Bit 0, Type, 2 bits, */
+ /* 0: Type-1, */
+ /* 1: Type-2, */
+ /* 2: Type-3, */
+ /* 3: Type-4 */
+ /* Bit 2, Pixel Format, 4 bits */
+ /* Bit0: 16bpp (not supported in LNC), */
+ /* Bit1: 18bpp loosely packed, */
+ /* Bit2: 18bpp packed, */
+ /* Bit3: 24bpp */
+ /* Bit 6, Reserved, 2 bits, 00b */
+ /* Bit 8, Minimum Supported Frame Rate, 6 bits, 0 - 63Hz */
+ /* Bit 14, Reserved, 2 bits, 00b */
+} __attribute__ ((packed));
+
+union mrst_panel_rx{
+ struct{
+ uint16_t NumberOfLanes:2; /*Num of Lanes, 2 bits,0 = 1 lane,*/
+ /* 1 = 2 lanes, 2 = 3 lanes, 3 = 4 lanes. */
+ uint16_t MaxLaneFreq:3; /* 0: 100MHz, 1: 200MHz, 2: 300MHz, */
+ /*3: 400MHz, 4: 500MHz, 5: 600MHz, 6: 700MHz, 7: 800MHz.*/
+ uint16_t SupportedVideoTransferMode:2; /*0: Non-burst only */
+ /* 1: Burst and non-burst */
+ /* 2/3: Reserved */
+ uint16_t HSClkBehavior:1; /*0: Continuous, 1: Non-continuous*/
+ uint16_t DuoDisplaySupport:1; /*1 bit,0: No, 1: Yes*/
+ uint16_t ECC_ChecksumCapabilities:1;/*1 bit,0: No, 1: Yes*/
+ uint16_t BidirectionalCommunication:1;/*1 bit,0: No, 1: Yes */
+ uint16_t Rsvd:5;/*5 bits,00000b */
+ } panelrx;
+ uint16_t panel_receiver;
+} __attribute__ ((packed));
+
+struct gct_ioctl_arg{
+ uint8_t bpi; /* boot panel index, number of panel used during boot */
+ uint8_t pt; /* panel type, 4 bit field, 0=lvds, 1=mipi */
+ struct mrst_timing_info DTD; /* timing info for the selected panel */
+ uint32_t Panel_Port_Control;
+ uint32_t PP_On_Sequencing;/*1 dword,Register 0x61208,*/
+ uint32_t PP_Off_Sequencing;/*1 dword,Register 0x6120C,*/
+ uint32_t PP_Cycle_Delay;
+ uint16_t Panel_Backlight_Inverter_Descriptor;
+ uint16_t Panel_MIPI_Display_Descriptor;
+} __attribute__ ((packed));
+
+struct mrst_vbt{
+ char Signature[4]; /*4 bytes,"$GCT" */
+ uint8_t Revision; /*1 byte */
+ uint8_t Size; /*1 byte */
+ uint8_t Checksum; /*1 byte,Calculated*/
+ void *mrst_gct;
+} __attribute__ ((packed));
+
+struct mrst_gct_v1{ /* expect this table to change per customer request*/
+ union{ /*8 bits,Defined as follows: */
+ struct{
+ uint8_t PanelType:4; /*4 bits, Bit field for panels*/
+ /* 0 - 3: 0 = LVDS, 1 = MIPI*/
+ /*2 bits,Specifies which of the*/
+ uint8_t BootPanelIndex:2;
+ /* 4 panels to use by default*/
+ uint8_t BootMIPI_DSI_RxIndex:2;/*Specifies which of*/
+ /* the 4 MIPI DSI receivers to use*/
+ } PD;
+ uint8_t PanelDescriptor;
+ };
+ struct mrst_panel_descriptor_v1 panel[4];/*panel descrs,38 bytes each*/
+ union mrst_panel_rx panelrx[4]; /* panel receivers*/
+} __attribute__ ((packed));
+
+struct mrst_gct_v2{ /* expect this table to change per customer request*/
+ union{ /*8 bits,Defined as follows: */
+ struct{
+ uint8_t PanelType:4; /*4 bits, Bit field for panels*/
+ /* 0 - 3: 0 = LVDS, 1 = MIPI*/
+ /*2 bits,Specifies which of the*/
+ uint8_t BootPanelIndex:2;
+ /* 4 panels to use by default*/
+ uint8_t BootMIPI_DSI_RxIndex:2;/*Specifies which of*/
+ /* the 4 MIPI DSI receivers to use*/
+ } PD;
+ uint8_t PanelDescriptor;
+ };
+ struct mrst_panel_descriptor_v2 panel[4];/*panel descrs,38 bytes each*/
+ union mrst_panel_rx panelrx[4]; /* panel receivers*/
+} __attribute__ ((packed));
+
+#define PSB_DC_CRTC_SAVE 0x01
+#define PSB_DC_CRTC_RESTORE 0x02
+#define PSB_DC_OUTPUT_SAVE 0x04
+#define PSB_DC_OUTPUT_RESTORE 0x08
+#define PSB_DC_CRTC_MASK 0x03
+#define PSB_DC_OUTPUT_MASK 0x0C
+
+struct drm_psb_dc_state_arg {
+ uint32_t flags;
+ uint32_t obj_id;
+};
+
+struct drm_psb_mode_operation_arg {
+ uint32_t obj_id;
+ uint16_t operation;
+ struct drm_mode_modeinfo mode;
+ void *data;
+};
+
+struct drm_psb_stolen_memory_arg {
+ uint32_t base;
+ uint32_t size;
+};
+
+/*Display Register Bits*/
+#define REGRWBITS_PFIT_CONTROLS (1 << 0)
+#define REGRWBITS_PFIT_AUTOSCALE_RATIOS (1 << 1)
+#define REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS (1 << 2)
+#define REGRWBITS_PIPEASRC (1 << 3)
+#define REGRWBITS_PIPEBSRC (1 << 4)
+#define REGRWBITS_VTOTAL_A (1 << 5)
+#define REGRWBITS_VTOTAL_B (1 << 6)
+#define REGRWBITS_DSPACNTR (1 << 8)
+#define REGRWBITS_DSPBCNTR (1 << 9)
+#define REGRWBITS_DSPCCNTR (1 << 10)
+
+/*Overlay Register Bits*/
+#define OV_REGRWBITS_OVADD (1 << 0)
+#define OV_REGRWBITS_OGAM_ALL (1 << 1)
+
+#define OVC_REGRWBITS_OVADD (1 << 2)
+#define OVC_REGRWBITS_OGAM_ALL (1 << 3)
+
+struct drm_psb_register_rw_arg {
+ uint32_t b_force_hw_on;
+
+ uint32_t display_read_mask;
+ uint32_t display_write_mask;
+
+ struct {
+ uint32_t pfit_controls;
+ uint32_t pfit_autoscale_ratios;
+ uint32_t pfit_programmed_scale_ratios;
+ uint32_t pipeasrc;
+ uint32_t pipebsrc;
+ uint32_t vtotal_a;
+ uint32_t vtotal_b;
+ uint32_t dspcntr_a;
+ uint32_t dspcntr_b;
+ } display;
+
+ uint32_t overlay_read_mask;
+ uint32_t overlay_write_mask;
+
+ struct {
+ uint32_t OVADD;
+ uint32_t OGAMC0;
+ uint32_t OGAMC1;
+ uint32_t OGAMC2;
+ uint32_t OGAMC3;
+ uint32_t OGAMC4;
+ uint32_t OGAMC5;
+ uint32_t IEP_ENABLED;
+ uint32_t IEP_BLE_MINMAX;
+ uint32_t IEP_BSSCC_CONTROL;
+ uint32_t b_wait_vblank;
+ } overlay;
+
+ uint32_t sprite_enable_mask;
+ uint32_t sprite_disable_mask;
+
+ struct {
+ uint32_t dspa_control;
+ uint32_t dspa_key_value;
+ uint32_t dspa_key_mask;
+ uint32_t dspc_control;
+ uint32_t dspc_stride;
+ uint32_t dspc_position;
+ uint32_t dspc_linear_offset;
+ uint32_t dspc_size;
+ uint32_t dspc_surface;
+ } sprite;
+
+ uint32_t subpicture_enable_mask;
+ uint32_t subpicture_disable_mask;
+};
+
+struct psb_gtt_mapping_arg {
+ void *hKernelMemInfo;
+ uint32_t offset_pages;
+};
+
+struct drm_psb_getpageaddrs_arg {
+ uint32_t handle;
+ unsigned long *page_addrs;
+ unsigned long gtt_offset;
+};
+
+
+#define MAX_SLICES_PER_PICTURE 72
+typedef struct drm_psb_msvdx_decode_status {
+ uint32_t fw_status;
+ uint32_t num_error_slice;
+ int32_t start_error_mb_list[MAX_SLICES_PER_PICTURE];
+ int32_t end_error_mb_list[MAX_SLICES_PER_PICTURE];
+ int32_t slice_missing_or_error[MAX_SLICES_PER_PICTURE];
+} drm_psb_msvdx_decode_status_t;
+
+/* Controlling the kernel modesetting buffers */
+
+#define DRM_PSB_KMS_OFF 0x00
+#define DRM_PSB_KMS_ON 0x01
+#define DRM_PSB_VT_LEAVE 0x02
+#define DRM_PSB_VT_ENTER 0x03
+#define DRM_PSB_EXTENSION 0x06
+#define DRM_PSB_SIZES 0x07
+#define DRM_PSB_FUSE_REG 0x08
+#define DRM_PSB_VBT 0x09
+#define DRM_PSB_DC_STATE 0x0A
+#define DRM_PSB_ADB 0x0B
+#define DRM_PSB_MODE_OPERATION 0x0C
+#define DRM_PSB_STOLEN_MEMORY 0x0D
+#define DRM_PSB_REGISTER_RW 0x0E
+#define DRM_PSB_GTT_MAP 0x0F
+#define DRM_PSB_GTT_UNMAP 0x10
+#define DRM_PSB_GETPAGEADDRS 0x11
+/**
+ * NOTE: Add new commands here, but increment
+ * the values below and increment their
+ * corresponding defines where they're
+ * defined elsewhere.
+ */
+#define DRM_PVR_RESERVED1 0x12
+#define DRM_PVR_RESERVED2 0x13
+#define DRM_PVR_RESERVED3 0x14
+#define DRM_PVR_RESERVED4 0x15
+#define DRM_PVR_RESERVED5 0x16
+
+#define DRM_PSB_HIST_ENABLE 0x17
+#define DRM_PSB_HIST_STATUS 0x18
+#define DRM_PSB_UPDATE_GUARD 0x19
+#define DRM_PSB_INIT_COMM 0x1A
+#define DRM_PSB_DPST 0x1B
+#define DRM_PSB_GAMMA 0x1C
+#define DRM_PSB_DPST_BL 0x1D
+
+#define DRM_PVR_RESERVED6 0x1E
+
+#define DRM_PSB_GET_PIPE_FROM_CRTC_ID 0x1F
+#define DRM_PSB_DPU_QUERY 0x20
+#define DRM_PSB_DPU_DSR_ON 0x21
+#define DRM_PSB_DPU_DSR_OFF 0x22
+
+#define DRM_PSB_DSR_ENABLE 0xfffffffe
+#define DRM_PSB_DSR_DISABLE 0xffffffff
+
+struct psb_drm_dpu_rect {
+ int x, y;
+ int width, height;
+};
+
+struct drm_psb_drv_dsr_off_arg {
+ int screen;
+ struct psb_drm_dpu_rect damage_rect;
+};
+
+
+struct drm_psb_dev_info_arg {
+ uint32_t num_use_attribute_registers;
+};
+#define DRM_PSB_DEVINFO 0x01
+
+#define PSB_MODE_OPERATION_MODE_VALID 0x01
+#define PSB_MODE_OPERATION_SET_DC_BASE 0x02
+
+struct drm_psb_get_pipe_from_crtc_id_arg {
+ /** ID of CRTC being requested **/
+ uint32_t crtc_id;
+
+ /** pipe of requested CRTC **/
+ uint32_t pipe;
+};
+
+#endif
--- /dev/null
+/**************************************************************************
+ * Copyright (c) 2007, Intel Corporation.
+ * All Rights Reserved.
+ * Copyright (c) 2008, Tungsten Graphics, Inc. Cedar Park, TX., USA.
+ * 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 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.
+ *
+ **************************************************************************/
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include "psb_drm.h"
+#include "psb_drv.h"
+#include "psb_fb.h"
+#include "psb_reg.h"
+#include "psb_intel_reg.h"
+#include "psb_msvdx.h"
+#include "pnw_topaz.h"
+#include <drm/drm_pciids.h>
+#include "pvr_drm_shared.h"
+#include "psb_powermgmt.h"
+#include "img_types.h"
+#include <linux/cpu.h>
+#include <linux/dmi.h>
+#include <linux/notifier.h>
+#include <linux/spinlock.h>
+#include <linux/pm_runtime.h>
+
+#include "mdfld_dsi_dbi.h"
+#ifdef CONFIG_MDFLD_DSI_DPU
+#include "mdfld_dsi_dbi_dpu.h"
+#endif
+
+#ifdef CONFIG_MDFD_GL3
+#include "mdfld_gl3.h"
+#endif
+
+#ifdef CONFIG_MDFD_HDMI
+#include "mdfld_msic.h"
+#endif
+#include "psb_intel_hdmi.h"
+
+/*IMG headers*/
+#include "pvr_drm_shared.h"
+#include "img_types.h"
+#include "pvr_bridge.h"
+#include "linkage.h"
+
+#include "bufferclass_video_linux.h"
+
+int drm_psb_debug;
+/*EXPORT_SYMBOL(drm_psb_debug); */
+static int drm_psb_trap_pagefaults;
+
+int drm_psb_disable_vsync = 1;
+int drm_psb_no_fb;
+int drm_psb_force_pipeb;
+int drm_msvdx_pmpolicy = PSB_PMPOLICY_POWERDOWN;
+int drm_psb_cpurelax = 0;
+int drm_psb_udelaydivider = 1;
+int drm_psb_udelaymultiplier = 1;
+int drm_topaz_pmpolicy = PSB_PMPOLICY_NOPM;
+int drm_topaz_sbuswa;
+int drm_psb_ospm = 1;
+int drm_psb_gl3_enable = 1;
+int drm_psb_topaz_clockgating = 0;
+#ifdef CONFIG_PM_RUNTIME
+int gfxrtdelay = 0;
+#endif
+static int PanelID = GCT_DETECT;
+char HDMI_EDID[HDMI_MONITOR_NAME_LENGTH];
+
+static int psb_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
+
+MODULE_PARM_DESC(debug, "Enable debug output");
+MODULE_PARM_DESC(no_fb, "Disable FBdev");
+MODULE_PARM_DESC(trap_pagefaults, "Error and reset on MMU pagefaults");
+MODULE_PARM_DESC(disable_vsync, "Disable vsync interrupts");
+MODULE_PARM_DESC(force_pipeb, "Forces PIPEB to become primary fb");
+MODULE_PARM_DESC(ta_mem_size, "TA memory size in kiB");
+MODULE_PARM_DESC(ospm, "switch for ospm support");
+MODULE_PARM_DESC(gl3_enabled, "Enable GL3 cache");
+MODULE_PARM_DESC(rtpm, "Specifies Runtime PM delay for GFX");
+MODULE_PARM_DESC(msvdx_pmpolicy, "msvdx power management policy btw frames");
+MODULE_PARM_DESC(topaz_pmpolicy, "topaz power managerment policy btw frames");
+MODULE_PARM_DESC(topaz_sbuswa, "WA for topaz sysbus write");
+MODULE_PARM_DESC(PanelID, "Panel info for querying");
+MODULE_PARM_DESC(hdmi_edid, "EDID info for HDMI monitor");
+MODULE_PARM_DESC(cpu_relax, "replace udelay with cpurelax for video");
+MODULE_PARM_DESC(udelay_multiplier, "the multiplier of the usec of video udelay");
+MODULE_PARM_DESC(udelay_divider, "the divider of the usec of video udelay");
+
+module_param_named(debug, drm_psb_debug, int, 0600);
+module_param_named(no_fb, drm_psb_no_fb, int, 0600);
+module_param_named(trap_pagefaults, drm_psb_trap_pagefaults, int, 0600);
+module_param_named(force_pipeb, drm_psb_force_pipeb, int, 0600);
+module_param_named(msvdx_pmpolicy, drm_msvdx_pmpolicy, int, 0600);
+module_param_named(cpu_relax, drm_psb_cpurelax, int, 0600);
+module_param_named(udelay_multiplier, drm_psb_udelaymultiplier, int, 0600);
+module_param_named(udelay_divider, drm_psb_udelaydivider, int, 0600);
+module_param_named(topaz_pmpolicy, drm_topaz_pmpolicy, int, 0600);
+module_param_named(topaz_sbuswa, drm_topaz_sbuswa, int, 0600);
+module_param_named(ospm, drm_psb_ospm, int, 0600);
+module_param_named(gl3_enabled, drm_psb_gl3_enable, int, 0600);
+#ifdef CONFIG_PM_RUNTIME
+module_param_named(rtpm, gfxrtdelay, int, 0600);
+#endif
+module_param_named(topaz_clockgating, drm_psb_topaz_clockgating, int, 0600);
+module_param_named(PanelID, PanelID, int, 0600);
+module_param_string(hdmi_edid, HDMI_EDID, 20, 0600);
+#ifndef MODULE
+/* Make ospm configurable via cmdline firstly, and others can be enabled if needed. */
+static int __init config_ospm(char *arg)
+{
+ /* ospm turn on/off control can be passed in as a cmdline parameter */
+ /* to enable this feature add ospm=1 to cmdline */
+ /* to disable this feature add ospm=0 to cmdline */
+ if (!arg)
+ return -EINVAL;
+
+ if (!strcasecmp(arg, "0"))
+ drm_psb_ospm = 0;
+ else if (!strcasecmp(arg, "1"))
+ drm_psb_ospm = 1;
+
+ return 0;
+}
+static int __init config_gl3(char *arg)
+{
+ if (!arg)
+ return -EINVAL;
+
+ if (!strcasecmp(arg, "0"))
+ drm_psb_gl3_enable = 0;
+ else if (!strcasecmp(arg, "1"))
+ drm_psb_gl3_enable = 1;
+
+ return 0;
+}
+early_param("ospm", config_ospm);
+early_param("gl3_enabled", config_gl3);
+#endif
+
+static struct pci_device_id pciidlist[] = {
+#ifdef SGX535
+ {0x8086, 0x4100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100},
+ {0x8086, 0x4101, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100},
+ {0x8086, 0x4102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100},
+ {0x8086, 0x4103, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100},
+ {0x8086, 0x4104, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100},
+ {0x8086, 0x4105, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100},
+ {0x8086, 0x4106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100},
+ {0x8086, 0x4107, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100},
+#endif
+#ifdef SGX540
+ {0x8086, 0x0130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MDFLD_0130},
+ {0x8086, 0x0131, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MDFLD_0130},
+ {0x8086, 0x0132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MDFLD_0130},
+ {0x8086, 0x0133, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MDFLD_0130},
+ {0x8086, 0x0134, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MDFLD_0130},
+ {0x8086, 0x0135, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MDFLD_0130},
+ {0x8086, 0x0136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MDFLD_0130},
+ {0x8086, 0x0137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MDFLD_0130},
+#endif
+ {0, 0, 0}
+};
+
+MODULE_DEVICE_TABLE(pci, pciidlist);
+/*
+ * Standard IOCTLs.
+ */
+
+#define DRM_IOCTL_PSB_KMS_OFF \
+ DRM_IO(DRM_PSB_KMS_OFF + DRM_COMMAND_BASE)
+#define DRM_IOCTL_PSB_KMS_ON \
+ DRM_IO(DRM_PSB_KMS_ON + DRM_COMMAND_BASE)
+#define DRM_IOCTL_PSB_VT_LEAVE \
+ DRM_IO(DRM_PSB_VT_LEAVE + DRM_COMMAND_BASE)
+#define DRM_IOCTL_PSB_VT_ENTER \
+ DRM_IO(DRM_PSB_VT_ENTER + DRM_COMMAND_BASE)
+#define DRM_IOCTL_PSB_EXTENSION \
+ DRM_IOWR(DRM_PSB_EXTENSION + DRM_COMMAND_BASE, \
+ union drm_psb_extension_arg)
+#define DRM_IOCTL_PSB_SIZES \
+ DRM_IOR(DRM_PSB_SIZES + DRM_COMMAND_BASE, \
+ struct drm_psb_sizes_arg)
+#define DRM_IOCTL_PSB_FUSE_REG \
+ DRM_IOWR(DRM_PSB_FUSE_REG + DRM_COMMAND_BASE, uint32_t)
+#define DRM_IOCTL_PSB_VBT \
+ DRM_IOWR(DRM_PSB_VBT + DRM_COMMAND_BASE, \
+ struct gct_ioctl_arg)
+#define DRM_IOCTL_PSB_DC_STATE \
+ DRM_IOW(DRM_PSB_DC_STATE + DRM_COMMAND_BASE, \
+ struct drm_psb_dc_state_arg)
+#define DRM_IOCTL_PSB_ADB \
+ DRM_IOWR(DRM_PSB_ADB + DRM_COMMAND_BASE, uint32_t)
+#define DRM_IOCTL_PSB_MODE_OPERATION \
+ DRM_IOWR(DRM_PSB_MODE_OPERATION + DRM_COMMAND_BASE, \
+ struct drm_psb_mode_operation_arg)
+#define DRM_IOCTL_PSB_STOLEN_MEMORY \
+ DRM_IOWR(DRM_PSB_STOLEN_MEMORY + DRM_COMMAND_BASE, \
+ struct drm_psb_stolen_memory_arg)
+#define DRM_IOCTL_PSB_REGISTER_RW \
+ DRM_IOWR(DRM_PSB_REGISTER_RW + DRM_COMMAND_BASE, \
+ struct drm_psb_register_rw_arg)
+#define DRM_IOCTL_PSB_GTT_MAP \
+ DRM_IOWR(DRM_PSB_GTT_MAP + DRM_COMMAND_BASE, \
+ struct psb_gtt_mapping_arg)
+#define DRM_IOCTL_PSB_GTT_UNMAP \
+ DRM_IOW(DRM_PSB_GTT_UNMAP + DRM_COMMAND_BASE, \
+ struct psb_gtt_mapping_arg)
+#define DRM_IOCTL_PSB_GETPAGEADDRS \
+ DRM_IOWR(DRM_COMMAND_BASE + DRM_PSB_GETPAGEADDRS,\
+ struct drm_psb_getpageaddrs_arg)
+#define DRM_IOCTL_PSB_HIST_ENABLE \
+ DRM_IOWR(DRM_PSB_HIST_ENABLE + DRM_COMMAND_BASE, \
+ uint32_t)
+#define DRM_IOCTL_PSB_HIST_STATUS \
+ DRM_IOWR(DRM_PSB_HIST_STATUS + DRM_COMMAND_BASE, \
+ struct drm_psb_hist_status_arg)
+#define DRM_IOCTL_PSB_UPDATE_GUARD \
+ DRM_IOWR(DRM_PSB_UPDATE_GUARD + DRM_COMMAND_BASE, \
+ uint32_t)
+#define DRM_IOCTL_PSB_INIT_COMM \
+ DRM_IOWR(DRM_PSB_INIT_COMM + DRM_COMMAND_BASE, \
+ uint32_t)
+#define DRM_IOCTL_PSB_DPST \
+ DRM_IOWR(DRM_PSB_DPST + DRM_COMMAND_BASE, \
+ uint32_t)
+#define DRM_IOCTL_PSB_GAMMA \
+ DRM_IOWR(DRM_PSB_GAMMA + DRM_COMMAND_BASE, \
+ struct drm_psb_dpst_lut_arg)
+#define DRM_IOCTL_PSB_DPST_BL \
+ DRM_IOWR(DRM_PSB_DPST_BL + DRM_COMMAND_BASE, \
+ uint32_t)
+#define DRM_IOCTL_PSB_GET_PIPE_FROM_CRTC_ID \
+ DRM_IOWR(DRM_PSB_GET_PIPE_FROM_CRTC_ID + DRM_COMMAND_BASE, \
+ struct drm_psb_get_pipe_from_crtc_id_arg)
+
+/*pvr ioctls*/
+#define PVR_DRM_SRVKM_IOCTL \
+ DRM_IOW(DRM_COMMAND_BASE + PVR_DRM_SRVKM_CMD, \
+ PVRSRV_BRIDGE_PACKAGE)
+#define PVR_DRM_DISP_IOCTL \
+ DRM_IO(DRM_COMMAND_BASE + PVR_DRM_DISP_CMD)
+#define PVR_DRM_BC_IOCTL \
+ DRM_IO(DRM_COMMAND_BASE + PVR_DRM_BC_CMD)
+#define PVR_DRM_IS_MASTER_IOCTL \
+ DRM_IO(DRM_COMMAND_BASE + PVR_DRM_IS_MASTER_CMD)
+#define PVR_DRM_UNPRIV_IOCTL \
+ DRM_IOWR(DRM_COMMAND_BASE + PVR_DRM_UNPRIV_CMD, \
+ IMG_UINT32)
+#if defined(PDUMP)
+#define PVR_DRM_DBGDRV_IOCTL \
+ DRM_IOW(DRM_COMMAND_BASE + PVR_DRM_DBGDRV_CMD, IOCTL_PACKAGE)
+#endif
+
+/*DPU/DSR stuff*/
+#define DRM_IOCRL_PSB_DPU_QUERY DRM_IOR(DRM_PSB_DPU_QUERY + DRM_COMMAND_BASE, IMG_UINT32)
+#define DRM_IOCRL_PSB_DPU_DSR_ON DRM_IOW(DRM_PSB_DPU_DSR_ON + DRM_COMMAND_BASE, IMG_UINT32)
+#define DRM_IOCRL_PSB_DPU_DSR_OFF DRM_IOW(DRM_PSB_DPU_DSR_OFF + DRM_COMMAND_BASE, struct drm_psb_drv_dsr_off_arg)
+
+/*
+ * TTM execbuf extension.
+ */
+#if defined(PDUMP)
+#define DRM_PSB_CMDBUF (PVR_DRM_DBGDRV_CMD + 1)
+#else
+#define DRM_PSB_CMDBUF (DRM_PSB_DPU_DSR_OFF + 1)
+/* #define DRM_PSB_CMDBUF (DRM_PSB_DPST_BL + 1) */
+#endif
+
+#define DRM_PSB_SCENE_UNREF (DRM_PSB_CMDBUF + 1)
+#define DRM_IOCTL_PSB_CMDBUF \
+ DRM_IOW(DRM_PSB_CMDBUF + DRM_COMMAND_BASE, \
+ struct drm_psb_cmdbuf_arg)
+/*
+ * TTM placement user extension.
+ */
+
+#define DRM_PSB_PLACEMENT_OFFSET (DRM_PSB_SCENE_UNREF + 1)
+
+#define DRM_PSB_TTM_PL_CREATE (TTM_PL_CREATE + DRM_PSB_PLACEMENT_OFFSET)
+#define DRM_PSB_TTM_PL_REFERENCE (TTM_PL_REFERENCE + DRM_PSB_PLACEMENT_OFFSET)
+#define DRM_PSB_TTM_PL_UNREF (TTM_PL_UNREF + DRM_PSB_PLACEMENT_OFFSET)
+#define DRM_PSB_TTM_PL_SYNCCPU (TTM_PL_SYNCCPU + DRM_PSB_PLACEMENT_OFFSET)
+#define DRM_PSB_TTM_PL_WAITIDLE (TTM_PL_WAITIDLE + DRM_PSB_PLACEMENT_OFFSET)
+#define DRM_PSB_TTM_PL_SETSTATUS (TTM_PL_SETSTATUS + DRM_PSB_PLACEMENT_OFFSET)
+#define DRM_PSB_TTM_PL_CREATE_UB (TTM_PL_CREATE_UB + DRM_PSB_PLACEMENT_OFFSET)
+
+/*
+ * TTM fence extension.
+ */
+
+#define DRM_PSB_FENCE_OFFSET (DRM_PSB_TTM_PL_CREATE_UB + 1)
+#define DRM_PSB_TTM_FENCE_SIGNALED (TTM_FENCE_SIGNALED + DRM_PSB_FENCE_OFFSET)
+#define DRM_PSB_TTM_FENCE_FINISH (TTM_FENCE_FINISH + DRM_PSB_FENCE_OFFSET)
+#define DRM_PSB_TTM_FENCE_UNREF (TTM_FENCE_UNREF + DRM_PSB_FENCE_OFFSET)
+
+#define DRM_PSB_FLIP (DRM_PSB_TTM_FENCE_UNREF + 1) /*20*/
+/* PSB video extension */
+#define DRM_LNC_VIDEO_GETPARAM (DRM_PSB_FLIP + 1)
+
+/*BC_VIDEO ioctl*/
+#define DRM_BUFFER_CLASS_VIDEO (DRM_LNC_VIDEO_GETPARAM + 1) /*0x32*/
+
+#define DRM_IOCTL_PSB_TTM_PL_CREATE \
+ DRM_IOWR(DRM_COMMAND_BASE + DRM_PSB_TTM_PL_CREATE,\
+ union ttm_pl_create_arg)
+#define DRM_IOCTL_PSB_TTM_PL_REFERENCE \
+ DRM_IOWR(DRM_COMMAND_BASE + DRM_PSB_TTM_PL_REFERENCE,\
+ union ttm_pl_reference_arg)
+#define DRM_IOCTL_PSB_TTM_PL_UNREF \
+ DRM_IOW(DRM_COMMAND_BASE + DRM_PSB_TTM_PL_UNREF,\
+ struct ttm_pl_reference_req)
+#define DRM_IOCTL_PSB_TTM_PL_SYNCCPU \
+ DRM_IOW(DRM_COMMAND_BASE + DRM_PSB_TTM_PL_SYNCCPU,\
+ struct ttm_pl_synccpu_arg)
+#define DRM_IOCTL_PSB_TTM_PL_WAITIDLE \
+ DRM_IOW(DRM_COMMAND_BASE + DRM_PSB_TTM_PL_WAITIDLE,\
+ struct ttm_pl_waitidle_arg)
+#define DRM_IOCTL_PSB_TTM_PL_SETSTATUS \
+ DRM_IOWR(DRM_COMMAND_BASE + DRM_PSB_TTM_PL_SETSTATUS,\
+ union ttm_pl_setstatus_arg)
+#define DRM_IOCTL_PSB_TTM_PL_CREATE_UB \
+ DRM_IOWR(DRM_COMMAND_BASE + DRM_PSB_TTM_PL_CREATE_UB,\
+ union ttm_pl_create_ub_arg)
+#define DRM_IOCTL_PSB_TTM_FENCE_SIGNALED \
+ DRM_IOWR(DRM_COMMAND_BASE + DRM_PSB_TTM_FENCE_SIGNALED, \
+ union ttm_fence_signaled_arg)
+#define DRM_IOCTL_PSB_TTM_FENCE_FINISH \
+ DRM_IOWR(DRM_COMMAND_BASE + DRM_PSB_TTM_FENCE_FINISH, \
+ union ttm_fence_finish_arg)
+#define DRM_IOCTL_PSB_TTM_FENCE_UNREF \
+ DRM_IOW(DRM_COMMAND_BASE + DRM_PSB_TTM_FENCE_UNREF, \
+ struct ttm_fence_unref_arg)
+#define DRM_IOCTL_PSB_FLIP \
+ DRM_IOWR(DRM_COMMAND_BASE + DRM_PSB_FLIP, \
+ struct drm_psb_pageflip_arg)
+#define DRM_IOCTL_LNC_VIDEO_GETPARAM \
+ DRM_IOWR(DRM_COMMAND_BASE + DRM_LNC_VIDEO_GETPARAM, \
+ struct drm_lnc_video_getparam_arg)
+
+/*bc_video ioctl*/
+#define DRM_IOCTL_BUFFER_CLASS_VIDEO \
+ DRM_IOWR(DRM_COMMAND_BASE + DRM_BUFFER_CLASS_VIDEO, \
+ BC_Video_ioctl_package)
+
+static int psb_vt_leave_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+static int psb_vt_enter_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+static int psb_sizes_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+static int psb_fuse_reg_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+static int psb_vbt_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+static int psb_dc_state_ioctl(struct drm_device *dev, void * data,
+ struct drm_file *file_priv);
+static int psb_adb_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+static int psb_mode_operation_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+static int psb_stolen_memory_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+static int psb_register_rw_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+static int psb_hist_enable_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+static int psb_hist_status_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+static int psb_update_guard_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+static int psb_init_comm_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+static int psb_dpst_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+static int psb_gamma_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+static int psb_dpu_query_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+static int psb_dpu_dsr_on_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+
+static int psb_dpu_dsr_off_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+
+#define PSB_IOCTL_DEF(ioctl, func, flags) \
+ [DRM_IOCTL_NR(ioctl) - DRM_COMMAND_BASE] = {ioctl, flags, func}
+
+static struct drm_ioctl_desc psb_ioctls[] = {
+ PSB_IOCTL_DEF(DRM_IOCTL_PSB_KMS_OFF, psbfb_kms_off_ioctl,
+ DRM_ROOT_ONLY),
+ PSB_IOCTL_DEF(DRM_IOCTL_PSB_KMS_ON,
+ psbfb_kms_on_ioctl,
+ DRM_ROOT_ONLY),
+ PSB_IOCTL_DEF(DRM_IOCTL_PSB_VT_LEAVE, psb_vt_leave_ioctl,
+ DRM_ROOT_ONLY),
+ PSB_IOCTL_DEF(DRM_IOCTL_PSB_VT_ENTER,
+ psb_vt_enter_ioctl,
+ DRM_ROOT_ONLY),
+ PSB_IOCTL_DEF(DRM_IOCTL_PSB_EXTENSION, psb_extension_ioctl, DRM_AUTH),
+ PSB_IOCTL_DEF(DRM_IOCTL_PSB_SIZES, psb_sizes_ioctl, DRM_AUTH),
+ PSB_IOCTL_DEF(DRM_IOCTL_PSB_FUSE_REG, psb_fuse_reg_ioctl, DRM_AUTH),
+ PSB_IOCTL_DEF(DRM_IOCTL_PSB_VBT, psb_vbt_ioctl, DRM_AUTH),
+ PSB_IOCTL_DEF(DRM_IOCTL_PSB_DC_STATE, psb_dc_state_ioctl, DRM_AUTH),
+ PSB_IOCTL_DEF(DRM_IOCTL_PSB_ADB, psb_adb_ioctl, DRM_AUTH),
+ PSB_IOCTL_DEF(DRM_IOCTL_PSB_MODE_OPERATION, psb_mode_operation_ioctl,
+ DRM_AUTH),
+ PSB_IOCTL_DEF(DRM_IOCTL_PSB_STOLEN_MEMORY, psb_stolen_memory_ioctl,
+ DRM_AUTH),
+ PSB_IOCTL_DEF(DRM_IOCTL_PSB_REGISTER_RW, psb_register_rw_ioctl,
+ DRM_AUTH),
+ PSB_IOCTL_DEF(DRM_IOCTL_PSB_GTT_MAP,
+ psb_gtt_map_meminfo_ioctl,
+ DRM_AUTH),
+ PSB_IOCTL_DEF(DRM_IOCTL_PSB_GTT_UNMAP,
+ psb_gtt_unmap_meminfo_ioctl,
+ DRM_AUTH),
+ PSB_IOCTL_DEF(DRM_IOCTL_PSB_GETPAGEADDRS,
+ psb_getpageaddrs_ioctl,
+ DRM_AUTH),
+ PSB_IOCTL_DEF(PVR_DRM_SRVKM_IOCTL, PVRSRV_BridgeDispatchKM, 0),
+ PSB_IOCTL_DEF(PVR_DRM_DISP_IOCTL, PVRDRM_Dummy_ioctl, 0),
+ PSB_IOCTL_DEF(PVR_DRM_BC_IOCTL, PVRDRM_Dummy_ioctl, 0),
+ PSB_IOCTL_DEF(PVR_DRM_IS_MASTER_IOCTL, PVRDRMIsMaster, DRM_MASTER),
+ PSB_IOCTL_DEF(PVR_DRM_UNPRIV_IOCTL, PVRDRMUnprivCmd, 0),
+ PSB_IOCTL_DEF(DRM_IOCTL_PSB_HIST_ENABLE,
+ psb_hist_enable_ioctl,
+ DRM_AUTH),
+ PSB_IOCTL_DEF(DRM_IOCTL_PSB_HIST_STATUS,
+ psb_hist_status_ioctl,
+ DRM_AUTH),
+ PSB_IOCTL_DEF(DRM_IOCTL_PSB_UPDATE_GUARD, psb_update_guard_ioctl, DRM_AUTH),
+ PSB_IOCTL_DEF(DRM_IOCTL_PSB_INIT_COMM, psb_init_comm_ioctl, DRM_AUTH),
+ PSB_IOCTL_DEF(DRM_IOCTL_PSB_DPST, psb_dpst_ioctl, DRM_AUTH),
+ PSB_IOCTL_DEF(DRM_IOCTL_PSB_GAMMA, psb_gamma_ioctl, DRM_AUTH),
+ PSB_IOCTL_DEF(DRM_IOCTL_PSB_DPST_BL, psb_dpst_bl_ioctl, DRM_AUTH),
+ PSB_IOCTL_DEF(DRM_IOCTL_PSB_GET_PIPE_FROM_CRTC_ID, psb_intel_get_pipe_from_crtc_id, 0),
+#if defined(PDUMP)
+ PSB_IOCTL_DEF(PVR_DRM_DBGDRV_IOCTL, SYSPVRDBGDrivIoctl, 0),
+#endif
+ PSB_IOCTL_DEF(DRM_IOCTL_PSB_CMDBUF, psb_cmdbuf_ioctl, DRM_AUTH),
+ PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_PL_CREATE, psb_pl_create_ioctl,
+ DRM_AUTH),
+ PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_PL_REFERENCE, psb_pl_reference_ioctl,
+ DRM_AUTH),
+ PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_PL_UNREF, psb_pl_unref_ioctl,
+ DRM_AUTH),
+ PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_PL_SYNCCPU, psb_pl_synccpu_ioctl,
+ DRM_AUTH),
+ PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_PL_WAITIDLE, psb_pl_waitidle_ioctl,
+ DRM_AUTH),
+ PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_PL_SETSTATUS, psb_pl_setstatus_ioctl,
+ DRM_AUTH),
+ PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_PL_CREATE_UB, psb_pl_ub_create_ioctl,
+ DRM_AUTH),
+ PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_FENCE_SIGNALED,
+ psb_fence_signaled_ioctl, DRM_AUTH),
+ PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_FENCE_FINISH, psb_fence_finish_ioctl,
+ DRM_AUTH),
+ PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_FENCE_UNREF, psb_fence_unref_ioctl,
+ DRM_AUTH),
+ /*to be removed later */
+ /*PSB_IOCTL_DEF(DRM_IOCTL_PSB_FLIP, psb_page_flip, DRM_AUTH),*/
+ PSB_IOCTL_DEF(DRM_IOCTL_LNC_VIDEO_GETPARAM,
+ lnc_video_getparam, DRM_AUTH),
+ PSB_IOCTL_DEF(DRM_IOCTL_BUFFER_CLASS_VIDEO,
+ BC_Video_Bridge, DRM_AUTH),
+ PSB_IOCTL_DEF(DRM_IOCRL_PSB_DPU_QUERY, psb_dpu_query_ioctl,
+ DRM_AUTH),
+ PSB_IOCTL_DEF(DRM_IOCRL_PSB_DPU_DSR_ON, psb_dpu_dsr_on_ioctl,
+ DRM_AUTH),
+ PSB_IOCTL_DEF(DRM_IOCRL_PSB_DPU_DSR_OFF, psb_dpu_dsr_off_ioctl,
+ DRM_AUTH)
+};
+
+static void psb_set_uopt(struct drm_psb_uopt *uopt)
+{
+ return;
+}
+
+static void psb_lastclose(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) dev->dev_private;
+
+ return;
+
+ if (!dev->dev_private)
+ return;
+
+ mutex_lock(&dev_priv->cmdbuf_mutex);
+ if (dev_priv->context.buffers) {
+ vfree(dev_priv->context.buffers);
+ dev_priv->context.buffers = NULL;
+ }
+ mutex_unlock(&dev_priv->cmdbuf_mutex);
+}
+
+static void psb_do_takedown(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) dev->dev_private;
+ struct ttm_bo_device *bdev = &dev_priv->bdev;
+
+
+ if (dev_priv->have_mem_mmu) {
+ ttm_bo_clean_mm(bdev, DRM_PSB_MEM_MMU);
+ dev_priv->have_mem_mmu = 0;
+ }
+
+ if (dev_priv->have_tt) {
+ ttm_bo_clean_mm(bdev, TTM_PL_TT);
+ dev_priv->have_tt = 0;
+ }
+
+ if (dev_priv->have_camera) {
+ ttm_bo_clean_mm(bdev, TTM_PL_CI);
+ dev_priv->have_camera = 0;
+ }
+ if (dev_priv->have_rar) {
+ ttm_bo_clean_mm(bdev, TTM_PL_RAR);
+ dev_priv->have_rar = 0;
+ }
+
+ psb_msvdx_uninit(dev);
+ pnw_topaz_uninit(dev);
+}
+
+#define FB_REG06 0xD0810600
+#define FB_TOPAZ_DISABLE BIT(0)
+#define FB_MIPI_DISABLE BIT(11)
+#define FB_REG09 0xD0810900
+#define FB_SKU_MASK (BIT(12)|BIT(13)|BIT(14))
+#define FB_SKU_SHIFT 12
+#define FB_SKU_100 0
+#define FB_SKU_100L 1
+#define FB_SKU_83 2
+#if 1 /* FIXME remove it after PO */
+#define FB_GFX_CLK_DIVIDE_MASK (BIT(20)|BIT(21)|BIT(22))
+#define FB_GFX_CLK_DIVIDE_SHIFT 20
+#define FB_VED_CLK_DIVIDE_MASK (BIT(23)|BIT(24))
+#define FB_VED_CLK_DIVIDE_SHIFT 23
+#define FB_VEC_CLK_DIVIDE_MASK (BIT(25)|BIT(26))
+#define FB_VEC_CLK_DIVIDE_SHIFT 25
+#endif /* FIXME remove it after PO */
+
+
+void mrst_get_fuse_settings(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
+ uint32_t fuse_value = 0;
+ uint32_t fuse_value_tmp = 0;
+
+ pci_write_config_dword(pci_root, 0xD0, FB_REG06);
+ pci_read_config_dword(pci_root, 0xD4, &fuse_value);
+
+ dev_priv->iLVDS_enable = 0;
+
+ DRM_INFO("internal display is %s\n",
+ dev_priv->iLVDS_enable ? "LVDS display" : "MIPI display");
+
+ /*prevent Runtime suspend at start*/
+ if (dev_priv->iLVDS_enable) {
+ dev_priv->is_lvds_on = true;
+ dev_priv->is_mipi_on = false;
+ } else {
+ dev_priv->is_mipi_on = true;
+ dev_priv->is_lvds_on = false;
+ }
+
+ if (dev_priv->dev->pci_device == PCI_ID_TOPAZ_DISABLED)
+ dev_priv->topaz_disabled = 1;
+ else
+ dev_priv->topaz_disabled = 0;
+
+ dev_priv->video_device_fuse = fuse_value;
+
+ DRM_INFO("topaz is %s\n",
+ dev_priv->topaz_disabled ? "disabled" : "enabled");
+
+ pci_write_config_dword(pci_root, 0xD0, FB_REG09);
+ pci_read_config_dword(pci_root, 0xD4, &fuse_value);
+
+ DRM_INFO("SKU values is 0x%x. \n", fuse_value);
+ fuse_value_tmp = (fuse_value & FB_SKU_MASK) >> FB_SKU_SHIFT;
+
+ dev_priv->fuse_reg_value = fuse_value;
+
+ switch (fuse_value_tmp) {
+ case FB_SKU_100:
+ dev_priv->core_freq = 200;
+ break;
+ case FB_SKU_100L:
+ dev_priv->core_freq = 100;
+ break;
+ case FB_SKU_83:
+ dev_priv->core_freq = 166;
+ break;
+ default:
+ DRM_ERROR("Invalid SKU values, SKU value = 0x%08x\n", fuse_value_tmp);
+ dev_priv->core_freq = 0;
+ }
+ DRM_INFO("LNC core clk is %dMHz.\n", dev_priv->core_freq);
+
+#if 1 /* FIXME remove it after PO */
+ fuse_value_tmp =
+ (fuse_value & FB_GFX_CLK_DIVIDE_MASK) >> FB_GFX_CLK_DIVIDE_SHIFT;
+
+ switch (fuse_value_tmp) {
+ case 0:
+ DRM_INFO("Gfx clk : core clk = 1:1. \n");
+ break;
+ case 1:
+ DRM_INFO("Gfx clk : core clk = 4:3. \n");
+ break;
+ case 2:
+ DRM_INFO("Gfx clk : core clk = 8:5. \n");
+ break;
+ case 3:
+ DRM_INFO("Gfx clk : core clk = 2:1. \n");
+ break;
+ case 4:
+ DRM_INFO("Gfx clk : core clk = 16:7. \n");
+ break;
+ case 5:
+ DRM_INFO("Gfx clk : core clk = 8:3. \n");
+ break;
+ case 6:
+ DRM_INFO("Gfx clk : core clk = 16:5. \n");
+ break;
+ case 7:
+ DRM_INFO("Gfx clk : core clk = 4:1. \n");
+ break;
+ default:
+ DRM_ERROR("Invalid GFX CLK DIVIDE values, value = 0x%08x\n",
+ fuse_value_tmp);
+ }
+
+ fuse_value_tmp =
+ (fuse_value & FB_VED_CLK_DIVIDE_MASK) >> FB_VED_CLK_DIVIDE_SHIFT;
+
+ switch (fuse_value_tmp) {
+ case 0:
+ DRM_INFO("Ved clk : core clk = 1:1. \n");
+ break;
+ case 1:
+ DRM_INFO("Ved clk : core clk = 4:3. \n");
+ break;
+ case 2:
+ DRM_INFO("Ved clk : core clk = 8:5. \n");
+ break;
+ case 3:
+ DRM_INFO("Ved clk : core clk = 2:1. \n");
+ break;
+ default:
+ DRM_ERROR("Invalid VED CLK DIVIDE values, value = 0x%08x\n",
+ fuse_value_tmp);
+ }
+
+ fuse_value_tmp =
+ (fuse_value & FB_VEC_CLK_DIVIDE_MASK) >> FB_VEC_CLK_DIVIDE_SHIFT;
+
+ switch (fuse_value_tmp) {
+ case 0:
+ DRM_INFO("Vec clk : core clk = 1:1. \n");
+ break;
+ case 1:
+ DRM_INFO("Vec clk : core clk = 4:3. \n");
+ break;
+ case 2:
+ DRM_INFO("Vec clk : core clk = 8:5. \n");
+ break;
+ case 3:
+ DRM_INFO("Vec clk : core clk = 2:1. \n");
+ break;
+ default:
+ DRM_ERROR("Invalid VEC CLK DIVIDE values, value = 0x%08x\n",
+ fuse_value_tmp);
+ }
+#endif /* FIXME remove it after PO */
+
+#if KSEL_BYPASS_83_100_ENABLE
+ dev_priv->ksel = KSEL_BYPASS_83_100;
+#endif /* KSEL_BYPASS_83_100_ENABLE */
+
+#if KSEL_CRYSTAL_19_ENABLED
+ dev_priv->ksel = KSEL_CRYSTAL_19;
+#endif /* KSEL_CRYSTAL_19_ENABLED */
+
+ return;
+}
+
+bool mid_get_pci_revID(struct drm_psb_private *dev_priv)
+{
+ uint32_t platform_rev_id = 0;
+ struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0));
+
+ /*get the revison ID, B0:D2:F0;0x08 */
+ pci_read_config_dword(pci_gfx_root, 0x08, &platform_rev_id);
+ dev_priv->platform_rev_id = (uint8_t) platform_rev_id;
+ pci_dev_put(pci_gfx_root);
+ PSB_DEBUG_ENTRY("platform_rev_id is %x\n", dev_priv->platform_rev_id);
+
+ return true;
+}
+
+bool mrst_get_vbt_data(struct drm_psb_private *dev_priv)
+{
+ struct mrst_vbt *pVBT = &dev_priv->vbt_data;
+ u32 platform_config_address;
+ u16 new_size;
+ u8 *pVBT_virtual;
+ u8 bpi;
+ u8 number_desc = 0;
+ struct mrst_timing_info *dp_ti = &dev_priv->gct_data.DTD;
+ struct gct_r10_timing_info ti;
+ void *pGCT;
+ struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0));
+
+ /*get the address of the platform config vbt, B0:D2:F0;0xFC */
+ pci_read_config_dword(pci_gfx_root, 0xFC, &platform_config_address);
+ pci_dev_put(pci_gfx_root);
+ DRM_INFO("drm platform config address is %x\n",
+ platform_config_address);
+
+ /* check for platform config address == 0. */
+ /* this means fw doesn't support vbt */
+
+ if (platform_config_address == 0) {
+ pVBT->Size = 0;
+ return false;
+ }
+
+ /* get the virtual address of the vbt */
+ pVBT_virtual = ioremap(platform_config_address, sizeof(*pVBT));
+
+ memcpy(pVBT, pVBT_virtual, sizeof(*pVBT));
+ iounmap(pVBT_virtual); /* Free virtual address space */
+
+ printk(KERN_ALERT "GCT Revision is %x\n", pVBT->Revision);
+
+ switch (pVBT->Revision) {
+ case 0:
+ pVBT->mrst_gct = NULL;
+ pVBT->mrst_gct = \
+ ioremap(platform_config_address + sizeof(*pVBT) - 4,
+ pVBT->Size - sizeof(*pVBT) + 4);
+ pGCT = pVBT->mrst_gct;
+ bpi = ((struct mrst_gct_v1 *)pGCT)->PD.BootPanelIndex;
+ dev_priv->gct_data.bpi = bpi;
+ dev_priv->gct_data.pt =
+ ((struct mrst_gct_v1 *)pGCT)->PD.PanelType;
+ memcpy(&dev_priv->gct_data.DTD,
+ &((struct mrst_gct_v1 *)pGCT)->panel[bpi].DTD,
+ sizeof(struct mrst_timing_info));
+ dev_priv->gct_data.Panel_Port_Control =
+ ((struct mrst_gct_v1 *)pGCT)->panel[bpi].Panel_Port_Control;
+ dev_priv->gct_data.Panel_MIPI_Display_Descriptor =
+ ((struct mrst_gct_v1 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor;
+ break;
+ case 1:
+ pVBT->mrst_gct = NULL;
+ pVBT->mrst_gct = \
+ ioremap(platform_config_address + sizeof(*pVBT) - 4,
+ pVBT->Size - sizeof(*pVBT) + 4);
+ pGCT = pVBT->mrst_gct;
+ bpi = ((struct mrst_gct_v2 *)pGCT)->PD.BootPanelIndex;
+ dev_priv->gct_data.bpi = bpi;
+ dev_priv->gct_data.pt =
+ ((struct mrst_gct_v2 *)pGCT)->PD.PanelType;
+ memcpy(&dev_priv->gct_data.DTD,
+ &((struct mrst_gct_v2 *)pGCT)->panel[bpi].DTD,
+ sizeof(struct mrst_timing_info));
+ dev_priv->gct_data.Panel_Port_Control =
+ ((struct mrst_gct_v2 *)pGCT)->panel[bpi].Panel_Port_Control;
+ dev_priv->gct_data.Panel_MIPI_Display_Descriptor =
+ ((struct mrst_gct_v2 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor;
+ break;
+ case 0x10:
+ /*header definition changed from rev 01 (v2) to rev 10h. */
+ /*so, some values have changed location*/
+ new_size = pVBT->Checksum; /*checksum contains lo size byte*/
+ /*LSB of mrst_gct contains hi size byte*/
+ new_size |= ((0xff & (unsigned int)pVBT->mrst_gct)) << 8;
+
+ pVBT->Checksum = pVBT->Size; /*size contains the checksum*/
+ if (new_size > 0xff)
+ pVBT->Size = 0xff; /*restrict size to 255*/
+ else
+ pVBT->Size = new_size;
+
+ /* number of descriptors defined in the GCT */
+ number_desc = ((0xff00 & (unsigned int)pVBT->mrst_gct)) >> 8;
+ bpi = ((0xff0000 & (unsigned int)pVBT->mrst_gct)) >> 16;
+ pVBT->mrst_gct = NULL;
+ pVBT->mrst_gct = \
+ ioremap(platform_config_address + GCT_R10_HEADER_SIZE,
+ GCT_R10_DISPLAY_DESC_SIZE * number_desc);
+ pGCT = pVBT->mrst_gct;
+ pGCT = (u8 *)pGCT + (bpi * GCT_R10_DISPLAY_DESC_SIZE);
+ dev_priv->gct_data.bpi = bpi; /*save boot panel id*/
+
+ /*copy the GCT display timings into a temp structure*/
+ memcpy(&ti, pGCT, sizeof(struct gct_r10_timing_info));
+
+ /*now copy the temp struct into the dev_priv->gct_data*/
+ dp_ti->pixel_clock = ti.pixel_clock;
+ dp_ti->hactive_hi = ti.hactive_hi;
+ dp_ti->hactive_lo = ti.hactive_lo;
+ dp_ti->hblank_hi = ti.hblank_hi;
+ dp_ti->hblank_lo = ti.hblank_lo;
+ dp_ti->hsync_offset_hi = ti.hsync_offset_hi;
+ dp_ti->hsync_offset_lo = ti.hsync_offset_lo;
+ dp_ti->hsync_pulse_width_hi = ti.hsync_pulse_width_hi;
+ dp_ti->hsync_pulse_width_lo = ti.hsync_pulse_width_lo;
+ dp_ti->vactive_hi = ti.vactive_hi;
+ dp_ti->vactive_lo = ti.vactive_lo;
+ dp_ti->vblank_hi = ti.vblank_hi;
+ dp_ti->vblank_lo = ti.vblank_lo;
+ dp_ti->vsync_offset_hi = ti.vsync_offset_hi;
+ dp_ti->vsync_offset_lo = ti.vsync_offset_lo;
+ dp_ti->vsync_pulse_width_hi = ti.vsync_pulse_width_hi;
+ dp_ti->vsync_pulse_width_lo = ti.vsync_pulse_width_lo;
+
+ /*mov the MIPI_Display_Descriptor data from GCT to dev priv*/
+ dev_priv->gct_data.Panel_MIPI_Display_Descriptor =
+ *((u8 *)pGCT + 0x0d);
+ dev_priv->gct_data.Panel_MIPI_Display_Descriptor |=
+ (*((u8 *)pGCT + 0x0e)) << 8;
+ break;
+ default:
+ printk(KERN_ALERT "Unknown revision of GCT!\n");
+ pVBT->Size = 0;
+ return false;
+ }
+
+ if (PanelID == GCT_DETECT) {
+ if (dev_priv->gct_data.bpi == 0) {
+ PSB_DEBUG_ENTRY("[GFX] TMD Panel Detected.\n");
+ dev_priv->panel_id = TMD_VID;
+ PanelID = TMD_VID;
+ } else {
+ PSB_DEBUG_ENTRY("[GFX] Default Panel (TPO)\n");
+ dev_priv->panel_id = TPO_CMD;
+ PanelID = TPO_CMD;
+ }
+ } else {
+ PSB_DEBUG_ENTRY("[GFX] Panel Parameter Passed in through cmd line\n");
+ dev_priv->panel_id = PanelID;
+ }
+
+ return true;
+}
+
+static int psb_do_init(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) dev->dev_private;
+ struct ttm_bo_device *bdev = &dev_priv->bdev;
+ struct psb_gtt *pg = dev_priv->pg;
+
+ uint32_t stolen_gtt;
+ uint32_t tt_start;
+ uint32_t tt_pages;
+
+ int ret = -ENOMEM;
+
+
+ /*
+ * Initialize sequence numbers for the different command
+ * submission mechanisms.
+ */
+
+ dev_priv->sequence[PSB_ENGINE_2D] = 0;
+ dev_priv->sequence[PSB_ENGINE_VIDEO] = 1;
+ dev_priv->sequence[LNC_ENGINE_ENCODE] = 0;
+
+ if (pg->mmu_gatt_start & 0x0FFFFFFF) {
+ DRM_ERROR("Gatt must be 256M aligned. This is a bug.\n");
+ ret = -EINVAL;
+ goto out_err;
+ }
+
+ stolen_gtt = (pg->stolen_size >> PAGE_SHIFT) * 4;
+ stolen_gtt = (stolen_gtt + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ stolen_gtt =
+ (stolen_gtt < pg->gtt_pages) ? stolen_gtt : pg->gtt_pages;
+
+ dev_priv->gatt_free_offset = pg->mmu_gatt_start +
+ (stolen_gtt << PAGE_SHIFT) * 1024;
+
+ if (1 || drm_debug) {
+ uint32_t core_id = PSB_RSGX32(PSB_CR_CORE_ID);
+ uint32_t core_rev = PSB_RSGX32(PSB_CR_CORE_REVISION);
+ DRM_INFO("SGX core id = 0x%08x\n", core_id);
+ DRM_INFO("SGX core rev major = 0x%02x, minor = 0x%02x\n",
+ (core_rev & _PSB_CC_REVISION_MAJOR_MASK) >>
+ _PSB_CC_REVISION_MAJOR_SHIFT,
+ (core_rev & _PSB_CC_REVISION_MINOR_MASK) >>
+ _PSB_CC_REVISION_MINOR_SHIFT);
+ DRM_INFO
+ ("SGX core rev maintenance = 0x%02x, designer = 0x%02x\n",
+ (core_rev & _PSB_CC_REVISION_MAINTENANCE_MASK) >>
+ _PSB_CC_REVISION_MAINTENANCE_SHIFT,
+ (core_rev & _PSB_CC_REVISION_DESIGNER_MASK) >>
+ _PSB_CC_REVISION_DESIGNER_SHIFT);
+ }
+
+ spin_lock_init(&dev_priv->irqmask_lock);
+
+ tt_pages = (pg->gatt_pages < PSB_TT_PRIV0_PLIMIT) ?
+ pg->gatt_pages : PSB_TT_PRIV0_PLIMIT;
+ tt_start = dev_priv->gatt_free_offset - pg->mmu_gatt_start;
+ tt_pages -= tt_start >> PAGE_SHIFT;
+ dev_priv->sizes.ta_mem_size = 0;
+
+ /* TT region managed by TTM. */
+ if (!ttm_bo_init_mm(bdev, TTM_PL_TT,
+ pg->gatt_pages -
+ (pg->ci_start >> PAGE_SHIFT) -
+ ((dev_priv->ci_region_size + dev_priv->rar_region_size)
+ >> PAGE_SHIFT))) {
+
+ dev_priv->have_tt = 1;
+ dev_priv->sizes.tt_size =
+ (tt_pages << PAGE_SHIFT) / (1024 * 1024) / 2;
+ }
+
+ if (!ttm_bo_init_mm(bdev,
+ DRM_PSB_MEM_MMU,
+ PSB_MEM_TT_START >> PAGE_SHIFT)) {
+ dev_priv->have_mem_mmu = 1;
+ dev_priv->sizes.mmu_size =
+ PSB_MEM_TT_START / (1024 * 1024);
+ }
+
+
+ PSB_DEBUG_INIT("Init MSVDX\n");
+ psb_msvdx_init(dev);
+
+ PSB_DEBUG_INIT("Init Topaz\n");
+ /* for sku100L and sku100M, VEC is disabled in fuses */
+ pnw_topaz_init(dev);
+
+ return 0;
+out_err:
+ psb_do_takedown(dev);
+ return ret;
+}
+
+static int psb_driver_unload(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) dev->dev_private;
+
+ /*Fristly, unload pvr driver*/
+ PVRSRVDrmUnload(dev);
+
+ /*TODO: destroy DSR/DPU infos here*/
+ psb_backlight_exit(); /*writes minimum value to backlight HW reg */
+
+ if (drm_psb_no_fb == 0)
+ psb_modeset_cleanup(dev);
+
+ if (dev_priv) {
+ psb_do_takedown(dev);
+
+ if (dev_priv->pf_pd) {
+ psb_mmu_free_pagedir(dev_priv->pf_pd);
+ dev_priv->pf_pd = NULL;
+ }
+ if (dev_priv->mmu) {
+ struct psb_gtt *pg = dev_priv->pg;
+
+ down_read(&pg->sem);
+ psb_mmu_remove_pfn_sequence(
+ psb_mmu_get_default_pd
+ (dev_priv->mmu),
+ pg->mmu_gatt_start,
+ pg->vram_stolen_size >> PAGE_SHIFT);
+ if (pg->ci_stolen_size != 0)
+ psb_mmu_remove_pfn_sequence(
+ psb_mmu_get_default_pd
+ (dev_priv->mmu),
+ pg->ci_start,
+ pg->ci_stolen_size >> PAGE_SHIFT);
+ if (pg->rar_stolen_size != 0)
+ psb_mmu_remove_pfn_sequence(
+ psb_mmu_get_default_pd
+ (dev_priv->mmu),
+ pg->rar_start,
+ pg->rar_stolen_size >> PAGE_SHIFT);
+ up_read(&pg->sem);
+ psb_mmu_driver_takedown(dev_priv->mmu);
+ dev_priv->mmu = NULL;
+ }
+ psb_gtt_takedown(dev_priv->pg, 1);
+ if (dev_priv->scratch_page) {
+ __free_page(dev_priv->scratch_page);
+ dev_priv->scratch_page = NULL;
+ }
+ if (dev_priv->has_bo_device) {
+ ttm_bo_device_release(&dev_priv->bdev);
+ dev_priv->has_bo_device = 0;
+ }
+ if (dev_priv->has_fence_device) {
+ ttm_fence_device_release(&dev_priv->fdev);
+ dev_priv->has_fence_device = 0;
+ }
+ if (dev_priv->vdc_reg) {
+ iounmap(dev_priv->vdc_reg);
+ dev_priv->vdc_reg = NULL;
+ }
+ if (dev_priv->sgx_reg) {
+ iounmap(dev_priv->sgx_reg);
+ dev_priv->sgx_reg = NULL;
+ }
+#ifdef CONFIG_MDFD_GL3
+ iounmap(dev_priv->gl3_reg);
+ dev_priv->gl3_reg = NULL;
+#endif
+
+ if (dev_priv->msvdx_reg) {
+ iounmap(dev_priv->msvdx_reg);
+ dev_priv->msvdx_reg = NULL;
+ }
+
+ if (dev_priv->topaz_reg) {
+ iounmap(dev_priv->topaz_reg);
+ dev_priv->topaz_reg = NULL;
+ }
+
+ if (dev_priv->tdev)
+ ttm_object_device_release(&dev_priv->tdev);
+
+ if (dev_priv->has_global)
+ psb_ttm_global_release(dev_priv);
+
+ kfree(dev_priv);
+ dev->dev_private = NULL;
+ }
+
+ ospm_power_uninit();
+
+ return 0;
+}
+
+static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
+{
+ struct drm_psb_private *dev_priv;
+ struct ttm_bo_device *bdev;
+ unsigned long resource_start;
+ struct psb_gtt *pg;
+ unsigned long irqflags;
+ int ret = -ENOMEM;
+ uint32_t tt_pages;
+ struct pci_dev *pdev;
+ struct device *ddev;
+ struct kobject *kobj;
+
+ DRM_INFO("psb - %s\n", PSB_PACKAGE_VERSION);
+
+ dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
+ if (dev_priv == NULL)
+ return -ENOMEM;
+
+ DRM_INFO("Run drivers on Medfield platform!\n");
+
+ INIT_LIST_HEAD(&dev_priv->video_ctx);
+
+ dev_priv->num_pipe = 3;
+
+ /*init DPST umcomm to NULL*/
+ dev_priv->psb_dpst_state = NULL;
+ dev_priv->psb_hotplug_state = NULL;
+ dev_priv->hdmi_done_reading_edid = false;
+ dev_priv->xserver_start = false;
+
+ dev_priv->dev = dev;
+ bdev = &dev_priv->bdev;
+
+ ret = psb_ttm_global_init(dev_priv);
+ if (unlikely(ret != 0))
+ goto out_err;
+ dev_priv->has_global = 1;
+
+ dev_priv->tdev = ttm_object_device_init
+ (dev_priv->mem_global_ref.object, PSB_OBJECT_HASH_ORDER);
+ if (unlikely(dev_priv->tdev == NULL))
+ goto out_err;
+
+ mutex_init(&dev_priv->temp_mem);
+ mutex_init(&dev_priv->cmdbuf_mutex);
+ mutex_init(&dev_priv->reset_mutex);
+ INIT_LIST_HEAD(&dev_priv->context.validate_list);
+ INIT_LIST_HEAD(&dev_priv->context.kern_validate_list);
+
+ mutex_init(&dev_priv->dsr_mutex);
+
+ spin_lock_init(&dev_priv->reloc_lock);
+
+ DRM_INIT_WAITQUEUE(&dev_priv->rel_mapped_queue);
+
+ dev->dev_private = (void *) dev_priv;
+ dev_priv->chipset = chipset;
+ psb_set_uopt(&dev_priv->uopt);
+
+ PSB_DEBUG_GENERAL("Init scheduler\n");
+ psb_scheduler_init(dev, &dev_priv->scheduler);
+
+
+ PSB_DEBUG_INIT("Mapping MMIO\n");
+ resource_start = pci_resource_start(dev->pdev, PSB_MMIO_RESOURCE);
+
+ dev_priv->msvdx_reg = ioremap(resource_start + MRST_MSVDX_OFFSET,
+ PSB_MSVDX_SIZE);
+
+ if (!dev_priv->msvdx_reg)
+ goto out_err;
+
+ dev_priv->topaz_reg = ioremap(resource_start + PNW_TOPAZ_OFFSET,
+ PNW_TOPAZ_SIZE);
+ if (!dev_priv->topaz_reg)
+ goto out_err;
+
+ dev_priv->vdc_reg =
+ ioremap(resource_start + PSB_VDC_OFFSET, PSB_VDC_SIZE);
+ if (!dev_priv->vdc_reg)
+ goto out_err;
+
+ dev_priv->sgx_reg = ioremap(resource_start + MRST_SGX_OFFSET,
+ PSB_SGX_SIZE);
+
+ if (!dev_priv->sgx_reg)
+ goto out_err;
+
+ mrst_get_fuse_settings(dev);
+ mrst_get_vbt_data(dev_priv);
+ mid_get_pci_revID(dev_priv);
+
+#ifdef CONFIG_MDFD_GL3
+ // GL3
+ dev_priv->gl3_reg = ioremap(resource_start + MDFLD_GL3_OFFSET,
+ MDFLD_GL3_SIZE);
+#endif
+
+ PSB_DEBUG_INIT("Init TTM fence and BO driver\n");
+
+ /* Init OSPM support */
+ ospm_power_init(dev);
+
+ ret = psb_ttm_fence_device_init(&dev_priv->fdev);
+ if (unlikely(ret != 0))
+ goto out_err;
+
+ /* For VXD385 DE2.x firmware support 16bit fence value */
+ dev_priv->fdev.fence_class[PSB_ENGINE_VIDEO].wrap_diff = (1 << 14);
+ dev_priv->fdev.fence_class[PSB_ENGINE_VIDEO].flush_diff = (1 << 13);
+ dev_priv->fdev.fence_class[PSB_ENGINE_VIDEO].sequence_mask = 0x0000ffff;
+
+ dev_priv->has_fence_device = 1;
+ ret = ttm_bo_device_init(bdev,
+ dev_priv->bo_global_ref.ref.object,
+ &psb_ttm_bo_driver,
+ DRM_PSB_FILE_PAGE_OFFSET, false);
+ if (unlikely(ret != 0))
+ goto out_err;
+ dev_priv->has_bo_device = 1;
+ ttm_lock_init(&dev_priv->ttm_lock);
+
+ ret = -ENOMEM;
+
+ dev_priv->scratch_page = alloc_page(GFP_DMA32 | __GFP_ZERO);
+ if (!dev_priv->scratch_page)
+ goto out_err;
+
+ set_pages_uc(dev_priv->scratch_page, 1);
+
+ dev_priv->pg = psb_gtt_alloc(dev);
+ if (!dev_priv->pg)
+ goto out_err;
+
+ ret = psb_gtt_init(dev_priv->pg, 0);
+ if (ret)
+ goto out_err;
+
+ ret = psb_gtt_mm_init(dev_priv->pg);
+ if (ret)
+ goto out_err;
+
+ dev_priv->mmu = psb_mmu_driver_init((void *)0,
+ drm_psb_trap_pagefaults, 0,
+ dev_priv);
+ if (!dev_priv->mmu)
+ goto out_err;
+
+ pg = dev_priv->pg;
+
+ tt_pages = (pg->gatt_pages < PSB_TT_PRIV0_PLIMIT) ?
+ (pg->gatt_pages) : PSB_TT_PRIV0_PLIMIT;
+
+ /* CI/RAR use the lower half of TT. */
+ pg->ci_start = (tt_pages / 2) << PAGE_SHIFT;
+ pg->rar_start = pg->ci_start + pg->ci_stolen_size;
+
+
+ /*
+ * Make MSVDX/TOPAZ MMU aware of the CI stolen memory area.
+ */
+ if (dev_priv->pg->ci_stolen_size != 0) {
+ down_read(&pg->sem);
+ ret = psb_mmu_insert_pfn_sequence(psb_mmu_get_default_pd
+ (dev_priv->mmu),
+ dev_priv->ci_region_start >> PAGE_SHIFT,
+ pg->mmu_gatt_start + pg->ci_start,
+ pg->ci_stolen_size >> PAGE_SHIFT, 0);
+ up_read(&pg->sem);
+ if (ret)
+ goto out_err;
+ }
+
+ /*
+ * Make MSVDX/TOPAZ MMU aware of the rar stolen memory area.
+ */
+ if (dev_priv->pg->rar_stolen_size != 0) {
+ down_read(&pg->sem);
+ ret = psb_mmu_insert_pfn_sequence(
+ psb_mmu_get_default_pd(dev_priv->mmu),
+ dev_priv->rar_region_start >> PAGE_SHIFT,
+ pg->mmu_gatt_start + pg->rar_start,
+ pg->rar_stolen_size >> PAGE_SHIFT, 0);
+ up_read(&pg->sem);
+ if (ret)
+ goto out_err;
+ }
+
+ dev_priv->pf_pd = psb_mmu_alloc_pd(dev_priv->mmu, 1, 0);
+ if (!dev_priv->pf_pd)
+ goto out_err;
+
+ psb_mmu_set_pd_context(psb_mmu_get_default_pd(dev_priv->mmu), 0);
+ psb_mmu_set_pd_context(dev_priv->pf_pd, 1);
+
+ spin_lock_init(&dev_priv->sequence_lock);
+
+ PSB_DEBUG_INIT("Begin to init MSVDX/Topaz\n");
+
+ ret = psb_do_init(dev);
+ if (ret)
+ return ret;
+
+ ret = drm_vblank_init(dev, dev_priv->num_pipe);
+ if (ret)
+ goto out_err;
+
+ /*
+ * Install interrupt handlers prior to powering off SGX or else we will
+ * crash.
+ */
+ dev_priv->vdc_irq_mask = 0;
+ dev_priv->pipestat[0] = 0;
+ dev_priv->pipestat[1] = 0;
+ dev_priv->pipestat[2] = 0;
+ spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
+ PSB_WVDC32(0x00000000, PSB_INT_ENABLE_R);
+ PSB_WVDC32(0xFFFFFFFF, PSB_INT_MASK_R);
+ spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+ if (drm_core_check_feature(dev, DRIVER_MODESET))
+ drm_irq_install(dev);
+
+ dev->vblank_disable_allowed = 1;
+
+ dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
+
+ dev->driver->get_vblank_counter = psb_get_vblank_counter;
+
+#ifdef CONFIG_MDFLD_DSI_DPU
+ /*init dpu info*/
+ mdfld_dbi_dpu_init(dev);
+#else
+ mdfld_dbi_dsr_init(dev);
+#endif /*CONFIG_MDFLD_DSI_DPU*/
+ INIT_WORK(&dev_priv->te_work, mdfld_te_handler_work);
+
+ /*must be after mrst_get_fuse_settings()*/
+ ret = psb_backlight_init(dev);
+ if (ret)
+ return ret;
+
+ if (drm_psb_no_fb == 0) {
+ psb_modeset_init(dev);
+ psb_fbdev_init(dev);
+ drm_kms_helper_poll_init(dev);
+ }
+
+ /* initialize HDMI Hotplug interrupt forwarding
+ * notifications for user mode
+ */
+
+ /*find handle to drm kboject*/
+ pdev = dev->pdev;
+ ddev = &pdev->dev;
+ kobj = &ddev->kobj;
+
+ dev_priv->psb_hotplug_state = psb_hotplug_init(kobj);
+
+ // GL3
+#ifdef CONFIG_MDFD_GL3
+ if (drm_psb_gl3_enable)
+ gl3_enable();
+#endif
+
+ /*Intel drm driver load is done, continue doing pvr load*/
+ DRM_DEBUG("Pvr driver load\n");
+
+ return PVRSRVDrmLoad(dev, chipset);
+out_err:
+ psb_driver_unload(dev);
+ return ret;
+}
+
+int psb_driver_device_is_agp(struct drm_device *dev)
+{
+ return 0;
+}
+
+int psb_extension_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ union drm_psb_extension_arg *arg = data;
+ struct drm_psb_extension_rep *rep = &arg->rep;
+
+ if (strcmp(arg->extension, "psb_ttm_placement_alphadrop") == 0) {
+ rep->exists = 1;
+ rep->driver_ioctl_offset = DRM_PSB_PLACEMENT_OFFSET;
+ rep->sarea_offset = 0;
+ rep->major = 1;
+ rep->minor = 0;
+ rep->pl = 0;
+ return 0;
+ }
+ if (strcmp(arg->extension, "psb_ttm_fence_alphadrop") == 0) {
+ rep->exists = 1;
+ rep->driver_ioctl_offset = DRM_PSB_FENCE_OFFSET;
+ rep->sarea_offset = 0;
+ rep->major = 1;
+ rep->minor = 0;
+ rep->pl = 0;
+ return 0;
+ }
+ if (strcmp(arg->extension, "psb_ttm_execbuf_alphadrop") == 0) {
+ rep->exists = 1;
+ rep->driver_ioctl_offset = DRM_PSB_CMDBUF;
+ rep->sarea_offset = 0;
+ rep->major = 1;
+ rep->minor = 0;
+ rep->pl = 0;
+ return 0;
+ }
+
+ /*return the page flipping ioctl offset*/
+ if (strcmp(arg->extension, "psb_page_flipping_alphadrop") == 0) {
+ rep->exists = 1;
+ rep->driver_ioctl_offset = DRM_PSB_FLIP;
+ rep->sarea_offset = 0;
+ rep->major = 1;
+ rep->minor = 0;
+ rep->pl = 0;
+ return 0;
+ }
+
+ /* return the video rar offset */
+ if (strcmp(arg->extension, "lnc_video_getparam") == 0) {
+ rep->exists = 1;
+ rep->driver_ioctl_offset = DRM_LNC_VIDEO_GETPARAM;
+ rep->sarea_offset = 0;
+ rep->major = 1;
+ rep->minor = 0;
+ rep->pl = 0;
+ return 0;
+ }
+
+ rep->exists = 0;
+ return 0;
+}
+
+static int psb_vt_leave_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_psb_private *dev_priv = psb_priv(dev);
+ struct ttm_bo_device *bdev = &dev_priv->bdev;
+#if 0 /* see REVISIT below */
+ struct ttm_mem_type_manager *man;
+ int clean;
+#endif
+ int ret;
+
+ ret = ttm_vt_lock(&dev_priv->ttm_lock, 1,
+ psb_fpriv(file_priv)->tfile);
+ if (unlikely(ret != 0))
+ return ret;
+
+ ret = ttm_bo_evict_mm(bdev, TTM_PL_TT);
+ if (unlikely(ret != 0))
+ goto out_unlock;
+
+
+#if 0
+ /*
+ * REVISIT: struct ttm_mem_type_manager no longer has manager field, but
+ * this has not been resolved, because the code only prints an
+ * informational message.
+ */
+ man = &bdev->man[TTM_PL_TT];
+ /*spin_lock(&bdev->lru_lock);*///lru_lock is removed from upstream TTM
+ clean = drm_mm_clean(&man->manager);
+ /*spin_unlock(&bdev->lru_lock);*/
+ if (unlikely(!clean))
+ DRM_INFO("Warning: GATT was not clean after VT switch.\n");
+#endif
+
+ ttm_bo_swapout_all(&dev_priv->bdev);
+
+ return 0;
+out_unlock:
+ (void) ttm_vt_unlock(&dev_priv->ttm_lock);
+ return ret;
+}
+
+static int psb_vt_enter_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_psb_private *dev_priv = psb_priv(dev);
+ return ttm_vt_unlock(&dev_priv->ttm_lock);
+}
+
+static int psb_sizes_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_psb_private *dev_priv = psb_priv(dev);
+ struct drm_psb_sizes_arg *arg =
+ (struct drm_psb_sizes_arg *) data;
+
+ *arg = dev_priv->sizes;
+ return 0;
+}
+
+static int psb_fuse_reg_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_psb_private *dev_priv = psb_priv(dev);
+ uint32_t *arg = data;
+
+ *arg = dev_priv->fuse_reg_value;
+ return 0;
+}
+static int psb_vbt_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_psb_private *dev_priv = psb_priv(dev);
+ struct gct_ioctl_arg *pGCT = data;
+
+ memcpy(pGCT, &dev_priv->gct_data, sizeof(*pGCT));
+
+ return 0;
+}
+
+static int psb_dc_state_ioctl(struct drm_device *dev, void * data,
+ struct drm_file *file_priv)
+{
+ return 0;
+}
+
+static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_psb_private *dev_priv = psb_priv(dev);
+ uint32_t *arg = data;
+ dev_priv->blc_adj2 = *arg;
+
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+ struct backlight_device bd;
+
+ bd.props.brightness = psb_get_brightness(&bd);
+ psb_set_brightness(&bd);
+#endif
+ return 0;
+}
+
+static int psb_adb_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_psb_private *dev_priv = psb_priv(dev);
+ uint32_t *arg = data;
+ dev_priv->blc_adj1 = *arg;
+
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+ struct backlight_device bd;
+
+ bd.props.brightness = psb_get_brightness(&bd);
+ psb_set_brightness(&bd);
+#endif
+ return 0;
+}
+
+static int psb_hist_enable_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ u32 irqCtrl = 0;
+ struct drm_psb_private *dev_priv = psb_priv(dev);
+ struct dpst_guardband guardband_reg;
+ struct dpst_ie_histogram_control ie_hist_cont_reg;
+ uint32_t *enable = data;
+
+ if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) {
+ return 0;
+ }
+
+ if (*enable == 1) {
+ ie_hist_cont_reg.data = PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL);
+ ie_hist_cont_reg.ie_pipe_assignment = 0;
+ ie_hist_cont_reg.histogram_mode_select = DPST_YUV_LUMA_MODE;
+ ie_hist_cont_reg.ie_histogram_enable = 1;
+ PSB_WVDC32(ie_hist_cont_reg.data, HISTOGRAM_LOGIC_CONTROL);
+
+ guardband_reg.data = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
+ guardband_reg.interrupt_enable = 1;
+ guardband_reg.interrupt_status = 1;
+ PSB_WVDC32(guardband_reg.data, HISTOGRAM_INT_CONTROL);
+
+ irqCtrl = PSB_RVDC32(PIPEASTAT);
+ PSB_WVDC32(irqCtrl | PIPE_DPST_EVENT_ENABLE, PIPEASTAT);
+ /* Wait for two vblanks */
+ } else {
+ guardband_reg.data = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
+ guardband_reg.interrupt_enable = 0;
+ guardband_reg.interrupt_status = 1;
+ PSB_WVDC32(guardband_reg.data, HISTOGRAM_INT_CONTROL);
+
+ ie_hist_cont_reg.data = PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL);
+ ie_hist_cont_reg.ie_histogram_enable = 0;
+ PSB_WVDC32(ie_hist_cont_reg.data, HISTOGRAM_LOGIC_CONTROL);
+
+ irqCtrl = PSB_RVDC32(PIPEASTAT);
+ irqCtrl &= ~PIPE_DPST_EVENT_ENABLE;
+ PSB_WVDC32(irqCtrl, PIPEASTAT);
+ }
+
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+
+ return 0;
+}
+
+static int psb_hist_status_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_psb_private *dev_priv = psb_priv(dev);
+ struct drm_psb_hist_status_arg *hist_status = data;
+ uint32_t *arg = hist_status->buf;
+ u32 iedbr_reg_data = 0;
+ struct dpst_ie_histogram_control ie_hist_cont_reg;
+ u32 i;
+ int dpst3_bin_threshold_count = 0;
+ uint32_t blm_hist_ctl = HISTOGRAM_LOGIC_CONTROL;
+ uint32_t iebdr_reg = HISTOGRAM_BIN_DATA;
+ uint32_t segvalue_max_22_bit = 0x3fffff;
+ uint32_t iedbr_busy_bit = 0x80000000;
+ int dpst3_bin_count = 32;
+
+ if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_ONLY_IF_ON)) {
+ return 0;
+ }
+
+ ie_hist_cont_reg.data = PSB_RVDC32(blm_hist_ctl);
+ ie_hist_cont_reg.bin_reg_func_select = dpst3_bin_threshold_count;
+ ie_hist_cont_reg.bin_reg_index = 0;
+
+ PSB_WVDC32(ie_hist_cont_reg.data, blm_hist_ctl);
+
+ for (i = 0; i < dpst3_bin_count; i++) {
+ iedbr_reg_data = PSB_RVDC32(iebdr_reg);
+
+ if (!(iedbr_reg_data & iedbr_busy_bit)) {
+ arg[i] = iedbr_reg_data & segvalue_max_22_bit;
+ } else {
+ i = 0;
+ ie_hist_cont_reg.data = PSB_RVDC32(blm_hist_ctl);
+ ie_hist_cont_reg.bin_reg_index = 0;
+ PSB_WVDC32(ie_hist_cont_reg.data, blm_hist_ctl);
+ }
+ }
+
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+
+ return 0;
+}
+
+static int psb_init_comm_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_psb_private *dev_priv = psb_priv(dev);
+ struct pci_dev *pdev = NULL;
+ struct device *ddev = NULL;
+ struct kobject *kobj = NULL;
+ uint32_t *arg = data;
+
+ if (*arg == 1) {
+ /*find handle to drm kboject*/
+ pdev = dev->pdev;
+ ddev = &pdev->dev;
+ kobj = &ddev->kobj;
+
+ if (dev_priv->psb_dpst_state == NULL) {
+ /*init dpst kmum comms*/
+ dev_priv->psb_dpst_state = psb_dpst_init(kobj);
+ } else {
+ printk(KERN_ALERT "DPST already initialized\n");
+ }
+
+ psb_irq_enable_dpst(dev);
+ psb_dpst_notify_change_um(DPST_EVENT_INIT_COMPLETE,
+ dev_priv->psb_dpst_state);
+ } else {
+ /*hotplug and dpst destroy examples*/
+ psb_irq_disable_dpst(dev);
+ psb_dpst_notify_change_um(DPST_EVENT_TERMINATE,
+ dev_priv->psb_dpst_state);
+ psb_dpst_device_pool_destroy(dev_priv->psb_dpst_state);
+ dev_priv->psb_dpst_state = NULL;
+ }
+ return 0;
+}
+
+/* return the current mode to the dpst module */
+static int psb_dpst_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_psb_private *dev_priv = psb_priv(dev);
+ uint32_t *arg = data;
+ uint32_t x;
+ uint32_t y;
+ uint32_t reg;
+
+ if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_ONLY_IF_ON)) {
+ return 0;
+ }
+
+ reg = PSB_RVDC32(PIPEASRC);
+
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+
+ /* horizontal is the left 16 bits */
+ x = reg >> 16;
+ /* vertical is the right 16 bits */
+ y = reg & 0x0000ffff;
+
+ /* the values are the image size minus one */
+ x += 1;
+ y += 1;
+
+ *arg = (x << 16) | y;
+
+ return 0;
+}
+static int psb_gamma_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_psb_dpst_lut_arg *lut_arg = data;
+ struct drm_mode_object *obj;
+ struct drm_crtc *crtc;
+ struct drm_connector *connector;
+ struct psb_intel_crtc *psb_intel_crtc;
+ int i = 0;
+ int32_t obj_id;
+
+ obj_id = lut_arg->output_id;
+ obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_CONNECTOR);
+ if (!obj) {
+ DRM_DEBUG("Invalid Connector object.\n");
+ return -EINVAL;
+ }
+
+ connector = obj_to_connector(obj);
+ crtc = connector->encoder->crtc;
+ psb_intel_crtc = to_psb_intel_crtc(crtc);
+
+ for (i = 0; i < 256; i++)
+ psb_intel_crtc->lut_adj[i] = lut_arg->lut[i];
+
+ psb_intel_crtc_load_lut(crtc);
+
+ return 0;
+}
+
+static int psb_update_guard_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_psb_private *dev_priv = psb_priv(dev);
+ struct dpst_guardband* input = (struct dpst_guardband*) data;
+ struct dpst_guardband reg_data;
+
+ if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_ONLY_IF_ON)) {
+ return 0;
+ }
+
+ reg_data.data = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
+ reg_data.guardband = input->guardband;
+ reg_data.guardband_interrupt_delay = input->guardband_interrupt_delay;
+ /* printk(KERN_ALERT "guardband = %u\ninterrupt delay = %u\n",
+ reg_data.guardband, reg_data.guardband_interrupt_delay); */
+ PSB_WVDC32(reg_data.data, HISTOGRAM_INT_CONTROL);
+
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+
+ return 0;
+}
+
+static int psb_mode_operation_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ uint32_t obj_id;
+ uint16_t op;
+ struct drm_mode_modeinfo *umode;
+ struct drm_display_mode *mode = NULL;
+ struct drm_psb_mode_operation_arg *arg;
+ struct drm_mode_object *obj;
+ struct drm_connector *connector;
+ struct drm_framebuffer * drm_fb;
+ struct psb_framebuffer * psb_fb;
+ struct drm_connector_helper_funcs *connector_funcs;
+ int ret = 0;
+ int resp = MODE_OK;
+ struct drm_psb_private *dev_priv = psb_priv(dev);
+
+ arg = (struct drm_psb_mode_operation_arg *)data;
+ obj_id = arg->obj_id;
+ op = arg->operation;
+
+ switch (op) {
+ case PSB_MODE_OPERATION_SET_DC_BASE:
+ obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_FB);
+ if (!obj) {
+ DRM_ERROR("Invalid FB id %d\n", obj_id);
+ return -EINVAL;
+ }
+
+ drm_fb = obj_to_fb(obj);
+ psb_fb = to_psb_fb(drm_fb);
+
+ if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
+ OSPM_UHB_ONLY_IF_ON)) {
+ REG_WRITE(DSPASURF, psb_fb->offset);
+ REG_READ(DSPASURF);
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+ } else {
+ dev_priv->saveDSPASURF = psb_fb->offset;
+ }
+
+ return 0;
+ case PSB_MODE_OPERATION_MODE_VALID:
+ umode = &arg->mode;
+
+ mutex_lock(&dev->mode_config.mutex);
+
+ obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_CONNECTOR);
+ if (!obj) {
+ ret = -EINVAL;
+ goto mode_op_out;
+ }
+
+ connector = obj_to_connector(obj);
+
+ mode = drm_mode_create(dev);
+ if (!mode) {
+ ret = -ENOMEM;
+ goto mode_op_out;
+ }
+
+ /* drm_crtc_convert_umode(mode, umode); */
+ {
+ mode->clock = umode->clock;
+ mode->hdisplay = umode->hdisplay;
+ mode->hsync_start = umode->hsync_start;
+ mode->hsync_end = umode->hsync_end;
+ mode->htotal = umode->htotal;
+ mode->hskew = umode->hskew;
+ mode->vdisplay = umode->vdisplay;
+ mode->vsync_start = umode->vsync_start;
+ mode->vsync_end = umode->vsync_end;
+ mode->vtotal = umode->vtotal;
+ mode->vscan = umode->vscan;
+ mode->vrefresh = umode->vrefresh;
+ mode->flags = umode->flags;
+ mode->type = umode->type;
+ strncpy(mode->name, umode->name, DRM_DISPLAY_MODE_LEN);
+ mode->name[DRM_DISPLAY_MODE_LEN-1] = 0;
+ }
+
+ connector_funcs = (struct drm_connector_helper_funcs *)
+ connector->helper_private;
+
+ if (connector_funcs->mode_valid) {
+ resp = connector_funcs->mode_valid(connector, mode);
+ arg->data = (void *)resp;
+ }
+
+ /*do some clean up work*/
+ if (mode) {
+ drm_mode_destroy(dev, mode);
+ }
+mode_op_out:
+ mutex_unlock(&dev->mode_config.mutex);
+ return ret;
+
+ default:
+ DRM_DEBUG("Unsupported psb mode operation");
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+static int psb_stolen_memory_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_psb_private *dev_priv = psb_priv(dev);
+ struct drm_psb_stolen_memory_arg *arg = data;
+
+ arg->base = dev_priv->pg->stolen_base;
+ arg->size = dev_priv->pg->vram_stolen_size;
+
+ return 0;
+}
+
+static int psb_dpu_query_ioctl(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ IMG_INT *data = (IMG_INT*)arg;
+ DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private;
+
+ int panel_type;
+
+ DRM_INFO("dsr query. \n");
+
+ dev_priv->xserver_start = true;
+ panel_type = is_panel_vid_or_cmd(dev);
+
+ if (panel_type == MDFLD_DSI_ENCODER_DPI) {
+ DRM_INFO("DSI panel is working in video mode\n");
+ dev_priv->b_dsr_enable = false;
+ *data = 0;
+ return 0;
+ }
+
+#if defined(CONFIG_MDFLD_DSI_DSR)
+ dev_priv->b_dsr_enable = true;
+ *data = MDFLD_DSR_RR | MDFLD_DSR_FULLSCREEN;
+#elif defined(CONFIG_MDFLD_DSI_DPU)
+ dev_priv->b_dsr_enable = true;
+ *data = MDFLD_DSR_RR | MDFLD_DPU_ENABLE;
+#else /*DBI panel but DSR was not defined*/
+ DRM_INFO("DSR is disabled by kernel configuration.\n");
+
+ dev_priv->b_dsr_enable = false;
+ *data = 0;
+#endif /*CONFIG_MDFLD_DSI_DSR*/
+ return 0;
+}
+
+static int psb_dpu_dsr_on_ioctl(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ u32 * param = (u32 *)arg;
+ struct drm_psb_private * dev_priv =
+ (struct drm_psb_private *)dev->dev_private;
+ int panel_type;
+
+ panel_type = is_panel_vid_or_cmd(dev);
+
+ if (panel_type == MDFLD_DSI_ENCODER_DPI) {
+ DRM_INFO("DSI panel is working in video mode\n");
+ dev_priv->b_dsr_enable = false;
+ return 0;
+ }
+
+ if (!param) {
+ DRM_ERROR("Invalid parameter\n");
+ return -EINVAL;
+ }
+
+ PSB_DEBUG_ENTRY("dsr kick in. param 0x%08x\n", *param);
+
+ if (*param == DRM_PSB_DSR_DISABLE) {
+ PSB_DEBUG_ENTRY("DSR is turned off\n");
+ dev_priv->b_dsr_enable = false;
+#if defined(CONFIG_MDFLD_DSI_DPU)
+ mdfld_dbi_dpu_report_fullscreen_damage(dev);
+#elif defined(CONFIG_MDFLD_DSI_DSR)
+ mdfld_dsi_dbi_exit_dsr(dev, MDFLD_DSR_2D_3D);
+#endif
+ return 0;
+ } else if (*param == DRM_PSB_DSR_ENABLE) {
+ PSB_DEBUG_ENTRY("DSR is turned on\n");
+#if defined(CONFIG_MDFLD_DSI_DPU) || defined(CONFIG_MDFLD_DSI_DSR)
+ dev_priv->b_dsr_enable = true;
+#endif
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int psb_dpu_dsr_off_ioctl(struct drm_device *dev, void *arg,
+ struct drm_file *file_priv)
+{
+ static int pipe = 0;
+#if defined(CONFIG_MDFLD_DSI_DPU)
+ struct drm_psb_drv_dsr_off_arg *dsr_off_arg = (struct drm_psb_drv_dsr_off_arg *) arg;
+ struct psb_drm_dpu_rect rect = dsr_off_arg->damage_rect;
+
+ return mdfld_dsi_dbi_dsr_off(dev, &rect);
+#elif defined(CONFIG_MDFLD_DSI_DSR)
+ struct drm_psb_private * dev_priv =
+ (struct drm_psb_private *)dev->dev_private;
+
+ pipe++;
+
+ if ((dev_priv->dsr_fb_update & MDFLD_DSR_2D_3D) != MDFLD_DSR_2D_3D) {
+ mdfld_dsi_dbi_exit_dsr(dev, MDFLD_DSR_2D_3D);
+ }
+
+ if (pipe > 0) {
+ pipe = 0;
+ if (gdbi_output) {
+ dev_priv->b_dsr_enable = true;
+ mdfld_dsi_dbi_enter_dsr(gdbi_output, 1);
+ mdfld_dsi_dbi_enter_dsr(gdbi_output, 2);
+ }
+ }
+
+#endif
+ return 0;
+}
+
+static int psb_register_rw_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_psb_private *dev_priv = psb_priv(dev);
+ struct drm_psb_register_rw_arg *arg = data;
+ unsigned int iep_ble_status;
+ unsigned long iep_timeout;
+ UHBUsage usage =
+ arg->b_force_hw_on ? OSPM_UHB_FORCE_POWER_ON : OSPM_UHB_ONLY_IF_ON;
+
+ if (arg->display_write_mask != 0) {
+ if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, usage)) {
+ if (arg->display_write_mask & REGRWBITS_PFIT_CONTROLS)
+ PSB_WVDC32(arg->display.pfit_controls,
+ PFIT_CONTROL);
+ if (arg->display_write_mask &
+ REGRWBITS_PFIT_AUTOSCALE_RATIOS)
+ PSB_WVDC32(arg->display.pfit_autoscale_ratios,
+ PFIT_AUTO_RATIOS);
+ if (arg->display_write_mask &
+ REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS)
+ PSB_WVDC32(
+ arg->display.pfit_programmed_scale_ratios,
+ PFIT_PGM_RATIOS);
+ if (arg->display_write_mask & REGRWBITS_PIPEASRC)
+ PSB_WVDC32(arg->display.pipeasrc,
+ PIPEASRC);
+ if (arg->display_write_mask & REGRWBITS_PIPEBSRC)
+ PSB_WVDC32(arg->display.pipebsrc,
+ PIPEBSRC);
+ if (arg->display_write_mask & REGRWBITS_VTOTAL_A)
+ PSB_WVDC32(arg->display.vtotal_a,
+ VTOTAL_A);
+ if (arg->display_write_mask & REGRWBITS_VTOTAL_B)
+ PSB_WVDC32(arg->display.vtotal_b,
+ VTOTAL_B);
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+ } else {
+ if (arg->display_write_mask & REGRWBITS_PFIT_CONTROLS)
+ dev_priv->savePFIT_CONTROL =
+ arg->display.pfit_controls;
+ if (arg->display_write_mask &
+ REGRWBITS_PFIT_AUTOSCALE_RATIOS)
+ dev_priv->savePFIT_AUTO_RATIOS =
+ arg->display.pfit_autoscale_ratios;
+ if (arg->display_write_mask &
+ REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS)
+ dev_priv->savePFIT_PGM_RATIOS =
+ arg->display.pfit_programmed_scale_ratios;
+ if (arg->display_write_mask & REGRWBITS_PIPEASRC)
+ dev_priv->savePIPEASRC = arg->display.pipeasrc;
+ if (arg->display_write_mask & REGRWBITS_PIPEBSRC)
+ dev_priv->savePIPEBSRC = arg->display.pipebsrc;
+ if (arg->display_write_mask & REGRWBITS_VTOTAL_A)
+ dev_priv->saveVTOTAL_A = arg->display.vtotal_a;
+ if (arg->display_write_mask & REGRWBITS_VTOTAL_B)
+ dev_priv->saveVTOTAL_B = arg->display.vtotal_b;
+ }
+ }
+
+ if (arg->display_read_mask != 0) {
+ if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, usage)) {
+ if (arg->display_read_mask &
+ REGRWBITS_PFIT_CONTROLS)
+ arg->display.pfit_controls =
+ PSB_RVDC32(PFIT_CONTROL);
+ if (arg->display_read_mask &
+ REGRWBITS_PFIT_AUTOSCALE_RATIOS)
+ arg->display.pfit_autoscale_ratios =
+ PSB_RVDC32(PFIT_AUTO_RATIOS);
+ if (arg->display_read_mask &
+ REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS)
+ arg->display.pfit_programmed_scale_ratios =
+ PSB_RVDC32(PFIT_PGM_RATIOS);
+ if (arg->display_read_mask & REGRWBITS_PIPEASRC)
+ arg->display.pipeasrc = PSB_RVDC32(PIPEASRC);
+ if (arg->display_read_mask & REGRWBITS_PIPEBSRC)
+ arg->display.pipebsrc = PSB_RVDC32(PIPEBSRC);
+ if (arg->display_read_mask & REGRWBITS_VTOTAL_A)
+ arg->display.vtotal_a = PSB_RVDC32(VTOTAL_A);
+ if (arg->display_read_mask & REGRWBITS_VTOTAL_B)
+ arg->display.vtotal_b = PSB_RVDC32(VTOTAL_B);
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+ } else {
+ if (arg->display_read_mask &
+ REGRWBITS_PFIT_CONTROLS)
+ arg->display.pfit_controls =
+ dev_priv->savePFIT_CONTROL;
+ if (arg->display_read_mask &
+ REGRWBITS_PFIT_AUTOSCALE_RATIOS)
+ arg->display.pfit_autoscale_ratios =
+ dev_priv->savePFIT_AUTO_RATIOS;
+ if (arg->display_read_mask &
+ REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS)
+ arg->display.pfit_programmed_scale_ratios =
+ dev_priv->savePFIT_PGM_RATIOS;
+ if (arg->display_read_mask & REGRWBITS_PIPEASRC)
+ arg->display.pipeasrc = dev_priv->savePIPEASRC;
+ if (arg->display_read_mask & REGRWBITS_PIPEBSRC)
+ arg->display.pipebsrc = dev_priv->savePIPEBSRC;
+ if (arg->display_read_mask & REGRWBITS_VTOTAL_A)
+ arg->display.vtotal_a = dev_priv->saveVTOTAL_A;
+ if (arg->display_read_mask & REGRWBITS_VTOTAL_B)
+ arg->display.vtotal_b = dev_priv->saveVTOTAL_B;
+ }
+ }
+
+ if (arg->overlay_write_mask != 0) {
+ if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, usage)) {
+ if (arg->overlay_write_mask & OV_REGRWBITS_OGAM_ALL) {
+ PSB_WVDC32(arg->overlay.OGAMC5, OV_OGAMC5);
+ PSB_WVDC32(arg->overlay.OGAMC4, OV_OGAMC4);
+ PSB_WVDC32(arg->overlay.OGAMC3, OV_OGAMC3);
+ PSB_WVDC32(arg->overlay.OGAMC2, OV_OGAMC2);
+ PSB_WVDC32(arg->overlay.OGAMC1, OV_OGAMC1);
+ PSB_WVDC32(arg->overlay.OGAMC0, OV_OGAMC0);
+ }
+ if (arg->overlay_write_mask & OVC_REGRWBITS_OGAM_ALL) {
+ PSB_WVDC32(arg->overlay.OGAMC5, OVC_OGAMC5);
+ PSB_WVDC32(arg->overlay.OGAMC4, OVC_OGAMC4);
+ PSB_WVDC32(arg->overlay.OGAMC3, OVC_OGAMC3);
+ PSB_WVDC32(arg->overlay.OGAMC2, OVC_OGAMC2);
+ PSB_WVDC32(arg->overlay.OGAMC1, OVC_OGAMC1);
+ PSB_WVDC32(arg->overlay.OGAMC0, OVC_OGAMC0);
+ }
+
+ if (arg->overlay_write_mask & OV_REGRWBITS_OVADD) {
+ PSB_WVDC32(arg->overlay.OVADD, OV_OVADD);
+
+ if (arg->overlay.b_wait_vblank) {
+ /*Wait for 20ms.*/
+ unsigned long vblank_timeout = jiffies + HZ / 50;
+ uint32_t temp;
+ while (time_before_eq(jiffies, vblank_timeout)) {
+ temp = PSB_RVDC32(OV_DOVASTA);
+ if ((temp & (0x1 << 31)) != 0) {
+ break;
+ }
+ cpu_relax();
+ }
+ }
+
+ if ((((arg->overlay.OVADD & OV_PIPE_SELECT) >> OV_PIPE_SELECT_POS) == OV_PIPE_A)) {
+#ifndef CONFIG_MDFLD_DSI_DPU
+ mdfld_dsi_dbi_exit_dsr(dev, MDFLD_DSR_OVERLAY_0);
+#else
+ /*TODO: report overlay damage*/
+#endif
+ }
+
+ if ((((arg->overlay.OVADD & OV_PIPE_SELECT) >> OV_PIPE_SELECT_POS) == OV_PIPE_C)) {
+#ifndef CONFIG_MDFLD_DSI_DPU
+ mdfld_dsi_dbi_exit_dsr(dev, MDFLD_DSR_OVERLAY_2);
+#else
+ /*TODO: report overlay damage*/
+#endif
+ }
+
+ if (arg->overlay.IEP_ENABLED) {
+ /* VBLANK period */
+ iep_timeout = jiffies + HZ / 10;
+ do {
+ iep_ble_status = PSB_RVDC32(0x31800);
+ if (time_after_eq(jiffies, iep_timeout)) {
+ DRM_ERROR("IEP Lite timeout\n");
+ break;
+ }
+ cpu_relax();
+ } while ((iep_ble_status >> 1) != 1);
+
+ arg->overlay.IEP_BLE_MINMAX = PSB_RVDC32(0x31804);
+ arg->overlay.IEP_BSSCC_CONTROL = PSB_RVDC32(0x32000);
+ }
+ }
+ if (arg->overlay_write_mask & OVC_REGRWBITS_OVADD) {
+ PSB_WVDC32(arg->overlay.OVADD, OVC_OVADD);
+ if (arg->overlay.b_wait_vblank) {
+ /*Wait for 20ms.*/
+ unsigned long vblank_timeout = jiffies + HZ / 50;
+ uint32_t temp;
+ while (time_before_eq(jiffies, vblank_timeout)) {
+ temp = PSB_RVDC32(OVC_DOVCSTA);
+ if ((temp & (0x1 << 31)) != 0) {
+ break;
+ }
+ cpu_relax();
+ }
+ }
+ }
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+ } else {
+ if (arg->overlay_write_mask & OV_REGRWBITS_OGAM_ALL) {
+ dev_priv->saveOV_OGAMC5 = arg->overlay.OGAMC5;
+ dev_priv->saveOV_OGAMC4 = arg->overlay.OGAMC4;
+ dev_priv->saveOV_OGAMC3 = arg->overlay.OGAMC3;
+ dev_priv->saveOV_OGAMC2 = arg->overlay.OGAMC2;
+ dev_priv->saveOV_OGAMC1 = arg->overlay.OGAMC1;
+ dev_priv->saveOV_OGAMC0 = arg->overlay.OGAMC0;
+ }
+ if (arg->overlay_write_mask & OVC_REGRWBITS_OGAM_ALL) {
+ dev_priv->saveOVC_OGAMC5 = arg->overlay.OGAMC5;
+ dev_priv->saveOVC_OGAMC4 = arg->overlay.OGAMC4;
+ dev_priv->saveOVC_OGAMC3 = arg->overlay.OGAMC3;
+ dev_priv->saveOVC_OGAMC2 = arg->overlay.OGAMC2;
+ dev_priv->saveOVC_OGAMC1 = arg->overlay.OGAMC1;
+ dev_priv->saveOVC_OGAMC0 = arg->overlay.OGAMC0;
+ }
+ if (arg->overlay_write_mask & OV_REGRWBITS_OVADD)
+ dev_priv->saveOV_OVADD = arg->overlay.OVADD;
+ if (arg->overlay_write_mask & OVC_REGRWBITS_OVADD)
+ dev_priv->saveOVC_OVADD = arg->overlay.OVADD;
+ }
+ }
+
+ if (arg->overlay_read_mask != 0) {
+ if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, usage)) {
+ if (arg->overlay_read_mask & OV_REGRWBITS_OGAM_ALL) {
+ arg->overlay.OGAMC5 = PSB_RVDC32(OV_OGAMC5);
+ arg->overlay.OGAMC4 = PSB_RVDC32(OV_OGAMC4);
+ arg->overlay.OGAMC3 = PSB_RVDC32(OV_OGAMC3);
+ arg->overlay.OGAMC2 = PSB_RVDC32(OV_OGAMC2);
+ arg->overlay.OGAMC1 = PSB_RVDC32(OV_OGAMC1);
+ arg->overlay.OGAMC0 = PSB_RVDC32(OV_OGAMC0);
+ }
+ if (arg->overlay_read_mask & OVC_REGRWBITS_OGAM_ALL) {
+ arg->overlay.OGAMC5 = PSB_RVDC32(OVC_OGAMC5);
+ arg->overlay.OGAMC4 = PSB_RVDC32(OVC_OGAMC4);
+ arg->overlay.OGAMC3 = PSB_RVDC32(OVC_OGAMC3);
+ arg->overlay.OGAMC2 = PSB_RVDC32(OVC_OGAMC2);
+ arg->overlay.OGAMC1 = PSB_RVDC32(OVC_OGAMC1);
+ arg->overlay.OGAMC0 = PSB_RVDC32(OVC_OGAMC0);
+ }
+ if (arg->overlay_read_mask & OV_REGRWBITS_OVADD)
+ arg->overlay.OVADD = PSB_RVDC32(OV_OVADD);
+ if (arg->overlay_read_mask & OVC_REGRWBITS_OVADD)
+ arg->overlay.OVADD = PSB_RVDC32(OVC_OVADD);
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+ } else {
+ if (arg->overlay_read_mask & OV_REGRWBITS_OGAM_ALL) {
+ arg->overlay.OGAMC5 = dev_priv->saveOV_OGAMC5;
+ arg->overlay.OGAMC4 = dev_priv->saveOV_OGAMC4;
+ arg->overlay.OGAMC3 = dev_priv->saveOV_OGAMC3;
+ arg->overlay.OGAMC2 = dev_priv->saveOV_OGAMC2;
+ arg->overlay.OGAMC1 = dev_priv->saveOV_OGAMC1;
+ arg->overlay.OGAMC0 = dev_priv->saveOV_OGAMC0;
+ }
+ if (arg->overlay_read_mask & OVC_REGRWBITS_OGAM_ALL) {
+ arg->overlay.OGAMC5 = dev_priv->saveOVC_OGAMC5;
+ arg->overlay.OGAMC4 = dev_priv->saveOVC_OGAMC4;
+ arg->overlay.OGAMC3 = dev_priv->saveOVC_OGAMC3;
+ arg->overlay.OGAMC2 = dev_priv->saveOVC_OGAMC2;
+ arg->overlay.OGAMC1 = dev_priv->saveOVC_OGAMC1;
+ arg->overlay.OGAMC0 = dev_priv->saveOVC_OGAMC0;
+ }
+ if (arg->overlay_read_mask & OV_REGRWBITS_OVADD)
+ arg->overlay.OVADD = dev_priv->saveOV_OVADD;
+ if (arg->overlay_read_mask & OVC_REGRWBITS_OVADD)
+ arg->overlay.OVADD = dev_priv->saveOVC_OVADD;
+ }
+ }
+
+ if (arg->sprite_enable_mask != 0) {
+ if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, usage)) {
+ PSB_WVDC32(0x1F3E, DSPARB);
+ PSB_WVDC32(arg->sprite.dspa_control | PSB_RVDC32(DSPACNTR), DSPACNTR);
+ PSB_WVDC32(arg->sprite.dspa_key_value, DSPAKEYVAL);
+ PSB_WVDC32(arg->sprite.dspa_key_mask, DSPAKEYMASK);
+ PSB_WVDC32(PSB_RVDC32(DSPASURF), DSPASURF);
+ PSB_RVDC32(DSPASURF);
+ PSB_WVDC32(arg->sprite.dspc_control, DSPCCNTR);
+ PSB_WVDC32(arg->sprite.dspc_stride, DSPCSTRIDE);
+ PSB_WVDC32(arg->sprite.dspc_position, DSPCPOS);
+ PSB_WVDC32(arg->sprite.dspc_linear_offset, DSPCLINOFF);
+ PSB_WVDC32(arg->sprite.dspc_size, DSPCSIZE);
+ PSB_WVDC32(arg->sprite.dspc_surface, DSPCSURF);
+ PSB_RVDC32(DSPCSURF);
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+ }
+ }
+
+ if (arg->sprite_disable_mask != 0) {
+ if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, usage)) {
+ PSB_WVDC32(0x3F3E, DSPARB);
+ PSB_WVDC32(0x0, DSPCCNTR);
+ PSB_WVDC32(arg->sprite.dspc_surface, DSPCSURF);
+ PSB_RVDC32(DSPCSURF);
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+ }
+ }
+
+ if (arg->subpicture_enable_mask != 0) {
+ if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, usage)) {
+ uint32_t temp;
+ if (arg->subpicture_enable_mask & REGRWBITS_DSPACNTR) {
+ temp = PSB_RVDC32(DSPACNTR);
+ temp &= ~DISPPLANE_PIXFORMAT_MASK;
+ temp &= ~DISPPLANE_BOTTOM;
+ temp |= DISPPLANE_32BPP;
+ PSB_WVDC32(temp, DSPACNTR);
+
+ temp = PSB_RVDC32(DSPABASE);
+ PSB_WVDC32(temp, DSPABASE);
+ PSB_RVDC32(DSPABASE);
+ temp = PSB_RVDC32(DSPASURF);
+ PSB_WVDC32(temp, DSPASURF);
+ PSB_RVDC32(DSPASURF);
+ }
+ if (arg->subpicture_enable_mask & REGRWBITS_DSPBCNTR) {
+ temp = PSB_RVDC32(DSPBCNTR);
+ temp &= ~DISPPLANE_PIXFORMAT_MASK;
+ temp &= ~DISPPLANE_BOTTOM;
+ temp |= DISPPLANE_32BPP;
+ PSB_WVDC32(temp, DSPBCNTR);
+
+ temp = PSB_RVDC32(DSPBBASE);
+ PSB_WVDC32(temp, DSPBBASE);
+ PSB_RVDC32(DSPBBASE);
+ temp = PSB_RVDC32(DSPBSURF);
+ PSB_WVDC32(temp, DSPBSURF);
+ PSB_RVDC32(DSPBSURF);
+ }
+ if (arg->subpicture_enable_mask & REGRWBITS_DSPCCNTR) {
+ temp = PSB_RVDC32(DSPCCNTR);
+ temp &= ~DISPPLANE_PIXFORMAT_MASK;
+ temp &= ~DISPPLANE_BOTTOM;
+ temp |= DISPPLANE_32BPP;
+ PSB_WVDC32(temp, DSPCCNTR);
+
+ temp = PSB_RVDC32(DSPCBASE);
+ PSB_WVDC32(temp, DSPCBASE);
+ PSB_RVDC32(DSPCBASE);
+ temp = PSB_RVDC32(DSPCSURF);
+ PSB_WVDC32(temp, DSPCSURF);
+ PSB_RVDC32(DSPCSURF);
+ }
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+ }
+ }
+
+ if (arg->subpicture_disable_mask != 0) {
+ if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, usage)) {
+ uint32_t temp;
+ if (arg->subpicture_disable_mask & REGRWBITS_DSPACNTR) {
+ temp = PSB_RVDC32(DSPACNTR);
+ temp &= ~DISPPLANE_PIXFORMAT_MASK;
+ temp |= DISPPLANE_32BPP_NO_ALPHA;
+ PSB_WVDC32(temp, DSPACNTR);
+
+ temp = PSB_RVDC32(DSPABASE);
+ PSB_WVDC32(temp, DSPABASE);
+ PSB_RVDC32(DSPABASE);
+ temp = PSB_RVDC32(DSPASURF);
+ PSB_WVDC32(temp, DSPASURF);
+ PSB_RVDC32(DSPASURF);
+ }
+ if (arg->subpicture_disable_mask & REGRWBITS_DSPBCNTR) {
+ temp = PSB_RVDC32(DSPBCNTR);
+ temp &= ~DISPPLANE_PIXFORMAT_MASK;
+ temp |= DISPPLANE_32BPP_NO_ALPHA;
+ PSB_WVDC32(temp, DSPBCNTR);
+
+ temp = PSB_RVDC32(DSPBBASE);
+ PSB_WVDC32(temp, DSPBBASE);
+ PSB_RVDC32(DSPBBASE);
+ temp = PSB_RVDC32(DSPBSURF);
+ PSB_WVDC32(temp, DSPBSURF);
+ PSB_RVDC32(DSPBSURF);
+ }
+ if (arg->subpicture_disable_mask & REGRWBITS_DSPCCNTR) {
+ temp = PSB_RVDC32(DSPCCNTR);
+ temp &= ~DISPPLANE_PIXFORMAT_MASK;
+ temp |= DISPPLANE_32BPP_NO_ALPHA;
+ PSB_WVDC32(temp, DSPCCNTR);
+
+ temp = PSB_RVDC32(DSPCBASE);
+ PSB_WVDC32(temp, DSPCBASE);
+ PSB_RVDC32(DSPCBASE);
+ temp = PSB_RVDC32(DSPCSURF);
+ PSB_WVDC32(temp, DSPCSURF);
+ PSB_RVDC32(DSPCSURF);
+ }
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+ }
+ }
+
+ return 0;
+}
+
+static int psb_driver_open(struct drm_device *dev, struct drm_file *priv)
+{
+ DRM_DEBUG("\n");
+ return PVRSRVOpen(dev, priv);
+}
+
+static long psb_unlocked_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ struct drm_file *file_priv = filp->private_data;
+ struct drm_device *dev = file_priv->minor->dev;
+ unsigned int nr = DRM_IOCTL_NR(cmd);
+ long ret;
+
+ DRM_DEBUG("cmd = %x, nr = %x\n", cmd, nr);
+
+ /*
+ * The driver private ioctls and TTM ioctls should be
+ * thread-safe.
+ */
+
+ if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END)
+ && (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) {
+ struct drm_ioctl_desc *ioctl =
+ &psb_ioctls[nr - DRM_COMMAND_BASE];
+
+ if (unlikely(ioctl->cmd != cmd)) {
+ DRM_ERROR(
+ "Invalid drm cmnd %d ioctl->cmd %x, cmd %x\n",
+ nr - DRM_COMMAND_BASE, ioctl->cmd, cmd);
+ return -EINVAL;
+ }
+ }
+ /*
+ * Not all old drm ioctls are thread-safe.
+ */
+
+ /* FIXME: lock_kernel(); */
+ ret = drm_ioctl(filp, cmd, arg);
+ /* FIXME: unlock_kernel(); */
+ return ret;
+}
+
+static int psb_blc_proc_show(struct seq_file *seq, void *v)
+{
+ struct drm_minor *minor = (struct drm_minor *) seq->private;
+ struct drm_device *dev = minor->dev;
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) dev->dev_private;
+ int user_brightness = 0;
+ int final_brightness = 0;
+
+ user_brightness = psb_get_brightness(NULL);
+ final_brightness = (user_brightness * dev_priv->blc_adj1) / 100;
+ final_brightness = (final_brightness * dev_priv->blc_adj2) / 100;
+
+ DRM_INFO("%i\n", final_brightness);
+ seq_printf(seq, "%i\n", final_brightness);
+
+ return 0;
+}
+
+static int psb_blc_proc_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, psb_blc_proc_show, PDE(inode)->data);
+}
+
+static const struct file_operations psb_blc_proc_fops = {
+ .owner = THIS_MODULE,
+ .open = psb_blc_proc_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int psb_rtpm_read(char *buf, char **start, off_t offset, int request,
+ int *eof, void *data)
+{
+ printk(KERN_ALERT "Current Runtime PM delay for GFX: %d (ms) \n", gfxrtdelay);
+
+ return 0;
+}
+
+static int psb_rtpm_write(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ char buf[2];
+ int temp = 0;
+ if (count != sizeof(buf)) {
+ return -EINVAL;
+ } else {
+ if (copy_from_user(buf, buffer, count))
+ return -EINVAL;
+ if (buf[count-1] != '\n')
+ return -EINVAL;
+ temp = buf[0] - '0';
+ switch (temp) {
+ case 1:
+ gfxrtdelay = 10 * 1000;
+ break;
+
+ case 2:
+ gfxrtdelay = 20 * 1000;
+ break;
+ default:
+ gfxrtdelay = 30 * 1000;
+ break;
+ }
+ printk(KERN_ALERT "Runtime PM delay set for GFX: %d (ms) \n", gfxrtdelay);
+ }
+ return count;
+}
+
+static int psb_ospm_read(char *buf, char **start, off_t offset, int request,
+ int *eof, void *data)
+{
+ struct drm_minor *minor = (struct drm_minor *) data;
+ struct drm_device *dev = minor->dev;
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) dev->dev_private;
+ int len = 0;
+#ifdef OSPM_STAT
+ unsigned long on_time = 0;
+ unsigned long off_time = 0;
+#endif
+
+ *start = &buf[offset];
+ *eof = 0;
+
+ /*#ifdef SUPPORT_ACTIVE_POWER_MANAGEMENT
+ DRM_INFO("GFX D0i3: enabled ");
+ #else
+ DRM_INFO("GFX D0i3: disabled ");
+ #endif*/
+ if (drm_psb_ospm)
+ DRM_INFO("GFX D0i3: enabled ");
+ else
+ DRM_INFO("GFX D0i3: disabled ");
+
+#ifdef OSPM_STAT
+ switch (dev_priv->graphics_state) {
+ case PSB_PWR_STATE_ON:
+ DRM_INFO("GFX state:%s\n", "on");
+ break;
+ case PSB_PWR_STATE_OFF:
+ DRM_INFO("GFX state:%s\n", "off");
+ break;
+ default:
+ DRM_INFO("GFX state:%s\n", "unknown");
+ }
+
+ on_time = dev_priv->gfx_on_time * 1000 / HZ;
+ off_time = dev_priv->gfx_off_time * 1000 / HZ;
+ switch (dev_priv->graphics_state) {
+ case PSB_PWR_STATE_ON:
+ on_time += (jiffies - dev_priv->gfx_last_mode_change) * \
+ 1000 / HZ;
+ break;
+ case PSB_PWR_STATE_OFF:
+ off_time += (jiffies - dev_priv->gfx_last_mode_change) * \
+ 1000 / HZ;
+ break;
+ }
+ DRM_INFO("GFX(count/ms):\n");
+ DRM_INFO("on:%lu/%lu, off:%lu/%lu \n",
+ dev_priv->gfx_on_cnt, on_time, dev_priv->gfx_off_cnt, off_time);
+#endif
+ if (len > request + offset)
+ return request;
+ *eof = 1;
+ return len - offset;
+}
+
+
+static int psb_ospm_write(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ char buf[2];
+ if (count != sizeof(buf)) {
+ return -EINVAL;
+ } else {
+ if (copy_from_user(buf, buffer, count))
+ return -EINVAL;
+ if (buf[count-1] != '\n')
+ return -EINVAL;
+ drm_psb_ospm = buf[0] - '0';
+ printk(KERN_ALERT " SGX (D0i3) drm_psb_ospm: %d \n",
+ drm_psb_ospm);
+ /*Work around for video encode, it needs sgx always on*/
+ if (!drm_psb_ospm) {
+ ospm_power_using_hw_begin(OSPM_GRAPHICS_ISLAND, true);
+ ospm_power_using_hw_end(OSPM_GRAPHICS_ISLAND);
+ }
+ }
+ return count;
+}
+
+/*
+* use to read and write display register. and print to standard output.
+*/
+static int psb_display_register_write(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ struct drm_minor *minor = (struct drm_minor *) data;
+ struct drm_device *dev = minor->dev;
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) dev->dev_private;
+ int reg_val = 0;
+ char buf[255];
+ char op = '0';
+ int reg = 0;
+ int val = 0;
+ int counter = 0;
+
+ memset(buf, '\0', sizeof(buf));
+
+ if (count > sizeof(buf)) {
+ printk(KERN_ALERT "The input is too bigger, kernel can not handle.\n");
+ return -EINVAL;
+ } else {
+ if (copy_from_user(buf, buffer, count))
+ return -EINVAL;
+ if (buf[count-1] != '\n')
+ return -EINVAL;
+ printk(KERN_ALERT "input = %s", buf);
+ }
+
+ sscanf(buf, "%c%x%x", &op, ®, &val);
+
+ if (op != 'r' && op != 'w') {
+ printk(KERN_ALERT "The input format is not right!\n");
+ printk(KERN_ALERT "for exampe: r 70184 10 - where 10 is number of dwords\n");
+ printk(KERN_ALERT "for exampe: w 70184 123\n");
+ return -EINVAL;
+ }
+ if (reg < 0xa000 || reg > 0x720ff) {
+ printk(KERN_ALERT "the register is out of display controller registers rang.\n");
+ return -EINVAL;
+ }
+
+ if ((reg % 0x4) != 0) {
+ printk(KERN_ALERT "the register address should aligned to 4 byte.please refrence display controller specification.\n");
+ return -EINVAL;
+ }
+
+ if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
+ OSPM_UHB_FORCE_POWER_ON)) {
+ printk(KERN_ALERT "Display controller can not power on.!\n");
+ return -EPERM;
+ }
+#ifndef CONFIG_MDFLD_DSI_DPU
+ mdfld_dsi_dbi_exit_dsr(dev, MDFLD_DSR_CURSOR_0); //assume cursor move once
+#endif
+ if (op == 'r') {
+ if (!val)
+ val = 1;
+
+ for (counter = 0; counter < val; counter++) {
+ reg_val = REG_READ(reg);
+ printk(KERN_ALERT "Read :reg=0x%08x , val=0x%08x.\n", reg, reg_val);
+ reg = reg + 4;
+ }
+ }
+ if (op == 'w') {
+ reg_val = REG_READ(reg);
+ printk(KERN_ALERT "Before change:reg=0x%08x , val=0x%08x.\n", reg, reg_val);
+
+ REG_WRITE(reg, val);
+
+ reg_val = ioread32(dev_priv->vdc_reg + (reg));
+ printk(KERN_ALERT "After change:reg=0x%08x , val=0x%08x.\n", reg, reg_val);
+ }
+
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+ return count;
+}
+
+/* When a client dies:
+ * - Check for and clean up flipped page state
+ */
+void psb_driver_preclose(struct drm_device *dev, struct drm_file *priv)
+{
+}
+
+static void psb_remove(struct pci_dev *pdev)
+{
+ struct drm_device *dev = pci_get_drvdata(pdev);
+ drm_put_dev(dev);
+}
+
+#if 0
+static int psb_proc_init(struct drm_minor *minor)
+{
+ struct proc_dir_entry *ent;
+ struct proc_dir_entry *ent1;
+ struct proc_dir_entry *rtpm;
+ struct proc_dir_entry *ent_display_status;
+
+ /* register proc entry for ospm */
+ ent = create_proc_entry(OSPM_PROC_ENTRY, 0644, minor->proc_root);
+ if (ent) {
+ ent->read_proc = psb_ospm_read;
+ ent->write_proc = psb_ospm_write;
+ ent->data = (void *)minor;
+ } else {
+ printk(KERN_ALERT "GFX: Create Proc Entry for OSPM Failed.\n");
+ }
+
+ /* register proc entry for runtime PM */
+ rtpm = create_proc_entry(RTPM_PROC_ENTRY, 0644, minor->proc_root);
+ if (rtpm) {
+ rtpm->read_proc = psb_rtpm_read;
+ rtpm->write_proc = psb_rtpm_write;
+ } else {
+ printk(KERN_ALERT "GFX: Create Proc Entry for Runtime PM Failed.\n");
+ }
+
+ /* register proc entry for display register read/write */
+ ent_display_status = create_proc_entry(DISPLAY_PROC_ENTRY, 0644, minor->proc_root);
+ if (ent_display_status) {
+ ent_display_status->write_proc = psb_display_register_write;
+ ent_display_status->data = (void *)minor;
+ } else {
+ printk(KERN_ALERT "GFX: Create Proc Entry for Display Status Failed.\n");
+ }
+
+ /* register proc data for backlight */
+ ent1 = proc_create_data(BLC_PROC_ENTRY, 0, minor->proc_root, &psb_blc_proc_fops, minor);
+ if (!ent1) {
+ printk(KERN_ALERT "GFX: Create Proc Data for Backlight Failed.\n");
+ }
+
+ return 0;
+}
+
+static void psb_proc_cleanup(struct drm_minor *minor)
+{
+ remove_proc_entry(OSPM_PROC_ENTRY, minor->proc_root);
+ remove_proc_entry(RTPM_PROC_ENTRY, minor->proc_root);
+ remove_proc_entry(BLC_PROC_ENTRY, minor->proc_root);
+ remove_proc_entry(DISPLAY_PROC_ENTRY, minor->proc_root);
+ return;
+}
+#endif
+
+static const struct dev_pm_ops psb_pm_ops = {
+ .runtime_suspend = psb_runtime_suspend,
+ .runtime_resume = psb_runtime_resume,
+ .runtime_idle = psb_runtime_idle,
+};
+
+static struct drm_driver driver = {
+ .driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | \
+ DRIVER_IRQ_VBL | DRIVER_MODESET,
+ .load = psb_driver_load,
+ .unload = psb_driver_unload,
+
+ .ioctls = psb_ioctls,
+ .num_ioctls = DRM_ARRAY_SIZE(psb_ioctls),
+ .device_is_agp = psb_driver_device_is_agp,
+ .irq_preinstall = psb_irq_preinstall,
+ .irq_postinstall = psb_irq_postinstall,
+ .irq_uninstall = psb_irq_uninstall,
+ .irq_handler = psb_irq_handler,
+ .enable_vblank = psb_enable_vblank,
+ .disable_vblank = psb_disable_vblank,
+ .get_vblank_counter = psb_get_vblank_counter,
+ .firstopen = NULL,
+ .lastclose = psb_lastclose,
+ .open = psb_driver_open,
+ .postclose = PVRSRVDrmPostClose,
+ .suspend = PVRSRVDriverSuspend,
+ .resume = PVRSRVDriverResume,
+ .preclose = psb_driver_preclose,
+ .fops = {
+ .owner = THIS_MODULE,
+ .open = psb_open,
+ .release = psb_release,
+ .unlocked_ioctl = psb_unlocked_ioctl,
+ .mmap = psb_mmap,
+ .poll = drm_poll,
+ .fasync = drm_fasync,
+ .read = drm_read,
+ },
+ .name = DRIVER_NAME,
+ .desc = DRIVER_DESC,
+ .date = PSB_DRM_DRIVER_DATE,
+ .major = PSB_DRM_DRIVER_MAJOR,
+ .minor = PSB_DRM_DRIVER_MINOR,
+ .patchlevel = PSB_DRM_DRIVER_PATCHLEVEL
+ };
+
+static struct pci_driver psb_pci_driver = {
+ .name = DRIVER_NAME,
+ .id_table = pciidlist,
+ .resume = ospm_power_resume,
+ .suspend = ospm_power_suspend,
+ .probe = psb_probe,
+ .remove = psb_remove,
+#ifdef CONFIG_PM
+ .driver.pm = &psb_pm_ops,
+#endif
+};
+
+static int psb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ if (pci_enable_msi(pdev))
+ DRM_ERROR("Enable MSI failed!\n");
+ return drm_get_pci_dev(pdev, ent, &driver);
+}
+
+#ifndef MODULE
+static __init int parse_panelid(char *arg)
+{
+ /* panel ID can be passed in as a cmdline parameter */
+ /* to enable this feature add panelid=TMD to cmdline for TMD panel*/
+ if (!arg)
+ return -EINVAL;
+
+ if (!strcasecmp(arg, "TMD_CMD"))
+ PanelID = TMD_CMD;
+ else if (!strcasecmp(arg, "TPO_CMD"))
+ PanelID = TPO_CMD;
+ else if (!strcasecmp(arg, "TMD_VID"))
+ PanelID = TMD_VID;
+ else if (!strcasecmp(arg, "TPO_VID"))
+ PanelID = TPO_VID;
+ else if (!strcasecmp(arg, "TC35876X"))
+ PanelID = TC35876X;
+ else
+ PanelID = GCT_DETECT;
+
+ return 0;
+}
+early_param("panelid", parse_panelid);
+#endif
+
+#ifndef MODULE
+static __init int parse_hdmi_edid(char *arg)
+{
+ /* HDMI EDID info can be passed in as a cmdline parameter,
+ * and need to remove it after we can get EDID info via MSIC.*/
+ if ((!arg) || (strlen(arg) >= 20))
+ return -EINVAL;
+
+ strcpy(HDMI_EDID, arg);
+
+ return 0;
+}
+early_param("hdmi_edid", parse_hdmi_edid);
+#endif
+
+static int __init psb_init(void)
+{
+ int ret;
+
+#if defined(MODULE) && defined(CONFIG_NET)
+ psb_kobject_uevent_init();
+#endif
+
+ ret = SYSPVRInit();
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = drm_pci_init(&driver, &psb_pci_driver);
+ if (ret != 0) {
+ return ret;
+ }
+
+ /*init for bc_video*/
+ ret = BC_Video_ModInit();
+ if (ret != 0) {
+ return ret;
+ }
+
+#ifdef CONFIG_MDFD_HDMI
+ msic_regsiter_driver();
+#endif
+
+ return ret;
+}
+
+static void __exit psb_exit(void)
+{
+ int ret;
+ /*cleanup for bc_video*/
+ ret = BC_Video_ModCleanup();
+ if (ret != 0) {
+ return;
+ }
+#ifdef CONFIG_MDFD_HDMI
+ msic_unregister_driver();
+#endif
+ drm_pci_exit(&driver, &psb_pci_driver);
+}
+
+late_initcall(psb_init);
+module_exit(psb_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
--- /dev/null
+/**************************************************************************
+ * Copyright (c) 2007-2008, Intel Corporation.
+ * 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 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.
+ *
+ **************************************************************************/
+
+#ifndef _PSB_DRV_H_
+#define _PSB_DRV_H_
+
+#include <linux/version.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_global.h>
+#include "sys_pvr_drm_export.h"
+#include "psb_drm.h"
+#include "psb_reg.h"
+#include "psb_schedule.h"
+#include "psb_intel_drv.h"
+#include "psb_hotplug.h"
+#include "psb_dpst.h"
+#include "psb_gtt.h"
+#include "psb_powermgmt.h"
+#include "ttm/ttm_object.h"
+#include "psb_ttm_fence_driver.h"
+#include "psb_ttm_userobj_api.h"
+#include "ttm/ttm_bo_driver.h"
+#include "ttm/ttm_lock.h"
+#include "psb_irq.h"
+
+/*IMG headers*/
+#include "private_data.h"
+#include "pvr_drm.h"
+
+#include "mdfld_hdmi_audio_if.h"
+
+/*Append new drm mode definition here, align with libdrm definition*/
+#define DRM_MODE_SCALE_NO_SCALE 2
+
+extern struct ttm_bo_driver psb_ttm_bo_driver;
+
+enum {
+ CHIP_PSB_8108 = 0,
+ CHIP_PSB_8109 = 1,
+ CHIP_MRST_4100 = 2,
+ CHIP_MDFLD_0130 = 3
+};
+
+enum panel_type {
+ TPO_CMD,
+ TPO_VID,
+ TMD_CMD,
+ TMD_VID,
+ TPO,
+ TMD,
+ HDMI,
+ TC35876X,
+ GCT_DETECT
+};
+
+#define PCI_ID_TOPAZ_DISABLED 0x4101
+
+/*
+ *Hardware bugfixes
+ */
+
+#define FIX_TG_16
+#define FIX_TG_2D_CLOCKGATE
+#define OSPM_STAT
+
+#define DRIVER_NAME "pvrsrvkm"
+#define DRIVER_DESC "drm driver for the Intel GMA500"
+#define DRIVER_AUTHOR "Intel Corporation"
+#define OSPM_PROC_ENTRY "ospm"
+#define RTPM_PROC_ENTRY "rtpm"
+#define BLC_PROC_ENTRY "mrst_blc"
+#define DISPLAY_PROC_ENTRY "display_status"
+
+#define PSB_DRM_DRIVER_DATE "2009-03-10"
+#define PSB_DRM_DRIVER_MAJOR 8
+#define PSB_DRM_DRIVER_MINOR 1
+#define PSB_DRM_DRIVER_PATCHLEVEL 0
+
+/*
+ *TTM driver private offsets.
+ */
+
+#define DRM_PSB_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
+
+#define PSB_OBJECT_HASH_ORDER 13
+#define PSB_FILE_OBJECT_HASH_ORDER 12
+#define PSB_BO_HASH_ORDER 12
+
+#define PSB_VDC_OFFSET 0x00000000
+#define PSB_VDC_SIZE 0x000080000
+#define MRST_MMIO_SIZE 0x0000C0000
+#define MDFLD_MMIO_SIZE 0x000100000
+#define PSB_SGX_SIZE 0x8000
+#define PSB_SGX_OFFSET 0x00040000
+#ifdef CONFIG_MDFD_GL3
+#define MDFLD_GL3_OFFSET 0x00000000
+#define MDFLD_GL3_SIZE 0x00040000
+#endif
+#define MRST_SGX_OFFSET 0x00080000
+#define PSB_MMIO_RESOURCE 0
+#define PSB_GATT_RESOURCE 2
+#define PSB_GTT_RESOURCE 3
+#define PSB_GMCH_CTRL 0x52
+#define PSB_BSM 0x5C
+#define _PSB_GMCH_ENABLED 0x4
+#define PSB_PGETBL_CTL 0x2020
+#define _PSB_PGETBL_ENABLED 0x00000001
+#define PSB_SGX_2D_SLAVE_PORT 0x4000
+#define PSB_TT_PRIV0_LIMIT (256*1024*1024)
+#define PSB_TT_PRIV0_PLIMIT (PSB_TT_PRIV0_LIMIT >> PAGE_SHIFT)
+#define PSB_NUM_VALIDATE_BUFFERS 2048
+
+#define PSB_MEM_MMU_START 0x00000000
+#define PSB_MEM_TT_START 0xE0000000
+
+#define PSB_GL3_CACHE_CTL 0x2100
+#define PSB_GL3_CACHE_STAT 0x2108
+
+/*
+ *Flags for external memory type field.
+ */
+
+#define MRST_MSVDX_OFFSET 0x90000 /*MSVDX Base offset */
+#define PSB_MSVDX_OFFSET 0x50000 /*MSVDX Base offset */
+/* MSVDX MMIO region is 0x50000 - 0x57fff ==> 32KB */
+#define PSB_MSVDX_SIZE 0x10000
+
+#define LNC_TOPAZ_OFFSET 0xA0000
+#define PNW_TOPAZ_OFFSET 0xC0000
+#define PNW_GL3_OFFSET 0xB0000
+#define LNC_TOPAZ_SIZE 0x10000
+#define PNW_TOPAZ_SIZE 0x30000 /* PNW VXE285 has two cores */
+#define PSB_MMU_CACHED_MEMORY 0x0001 /* Bind to MMU only */
+#define PSB_MMU_RO_MEMORY 0x0002 /* MMU RO memory */
+#define PSB_MMU_WO_MEMORY 0x0004 /* MMU WO memory */
+
+/*
+ *PTE's and PDE's
+ */
+
+#define PSB_PDE_MASK 0x003FFFFF
+#define PSB_PDE_SHIFT 22
+#define PSB_PTE_SHIFT 12
+
+#define PSB_PTE_VALID 0x0001 /* PTE / PDE valid */
+#define PSB_PTE_WO 0x0002 /* Write only */
+#define PSB_PTE_RO 0x0004 /* Read only */
+#define PSB_PTE_CACHED 0x0008 /* CPU cache coherent */
+
+/*
+ *VDC registers and bits
+ */
+#define PSB_MSVDX_CLOCKGATING 0x2064
+#define PSB_TOPAZ_CLOCKGATING 0x2068
+#define PSB_HWSTAM 0x2098
+#define PSB_INSTPM 0x20C0
+#define PSB_INT_IDENTITY_R 0x20A4
+#define _MDFLD_PIPEC_EVENT_FLAG (1<<2)
+#define _MDFLD_PIPEC_VBLANK_FLAG (1<<3)
+#define _PSB_DPST_PIPEB_FLAG (1<<4)
+#define _MDFLD_PIPEB_EVENT_FLAG (1<<4)
+#define _PSB_VSYNC_PIPEB_FLAG (1<<5)
+#define _PSB_DPST_PIPEA_FLAG (1<<6)
+#define _PSB_PIPEA_EVENT_FLAG (1<<6)
+#define _PSB_VSYNC_PIPEA_FLAG (1<<7)
+#define _MDFLD_MIPIA_FLAG (1<<16)
+#define _MDFLD_MIPIC_FLAG (1<<17)
+#define _PSB_IRQ_SGX_FLAG (1<<18)
+#define _PSB_IRQ_MSVDX_FLAG (1<<19)
+#define _LNC_IRQ_TOPAZ_FLAG (1<<20)
+#ifdef CONFIG_MDFD_GL3
+#define _MDFLD_GL3_IRQ_FLAG (1<<21)
+#define _MDFLD_GL3_ECC_FLAG (1<<2) /* unrecoverable ecc error. We must flush and reset */
+#endif
+
+/* This flag includes all the display IRQ bits excepts the vblank irqs. */
+#define _MDFLD_DISP_ALL_IRQ_FLAG (_MDFLD_PIPEC_EVENT_FLAG | _MDFLD_PIPEB_EVENT_FLAG | \
+ _PSB_PIPEA_EVENT_FLAG | _PSB_VSYNC_PIPEA_FLAG | _MDFLD_MIPIA_FLAG | _MDFLD_MIPIC_FLAG)
+#define PSB_INT_IDENTITY_R 0x20A4
+#define PSB_INT_MASK_R 0x20A8
+#define PSB_INT_ENABLE_R 0x20A0
+
+#define _PSB_MMU_ER_MASK 0x0001FF00
+#define _PSB_MMU_ER_HOST (1 << 16)
+#define GPIOA 0x5010
+#define GPIOB 0x5014
+#define GPIOC 0x5018
+#define GPIOD 0x501c
+#define GPIOE 0x5020
+#define GPIOF 0x5024
+#define GPIOG 0x5028
+#define GPIOH 0x502c
+#define GPIO_CLOCK_DIR_MASK (1 << 0)
+#define GPIO_CLOCK_DIR_IN (0 << 1)
+#define GPIO_CLOCK_DIR_OUT (1 << 1)
+#define GPIO_CLOCK_VAL_MASK (1 << 2)
+#define GPIO_CLOCK_VAL_OUT (1 << 3)
+#define GPIO_CLOCK_VAL_IN (1 << 4)
+#define GPIO_CLOCK_PULLUP_DISABLE (1 << 5)
+#define GPIO_DATA_DIR_MASK (1 << 8)
+#define GPIO_DATA_DIR_IN (0 << 9)
+#define GPIO_DATA_DIR_OUT (1 << 9)
+#define GPIO_DATA_VAL_MASK (1 << 10)
+#define GPIO_DATA_VAL_OUT (1 << 11)
+#define GPIO_DATA_VAL_IN (1 << 12)
+#define GPIO_DATA_PULLUP_DISABLE (1 << 13)
+
+#define VCLK_DIVISOR_VGA0 0x6000
+#define VCLK_DIVISOR_VGA1 0x6004
+#define VCLK_POST_DIV 0x6010
+
+#define PSB_COMM_2D (PSB_ENGINE_2D << 4)
+#define PSB_COMM_3D (PSB_ENGINE_3D << 4)
+#define PSB_COMM_TA (PSB_ENGINE_TA << 4)
+#define PSB_COMM_HP (PSB_ENGINE_HP << 4)
+#define PSB_COMM_USER_IRQ (1024 >> 2)
+#define PSB_COMM_USER_IRQ_LOST (PSB_COMM_USER_IRQ + 1)
+#define PSB_COMM_FW (2048 >> 2)
+
+#define PSB_UIRQ_VISTEST 1
+#define PSB_UIRQ_OOM_REPLY 2
+#define PSB_UIRQ_FIRE_TA_REPLY 3
+#define PSB_UIRQ_FIRE_RASTER_REPLY 4
+
+#define PSB_2D_SIZE (256*1024*1024)
+#define PSB_MAX_RELOC_PAGES 1024
+
+#define PSB_LOW_REG_OFFS 0x0204
+#define PSB_HIGH_REG_OFFS 0x0600
+
+#define PSB_NUM_VBLANKS 2
+
+
+#define PSB_2D_SIZE (256*1024*1024)
+#define PSB_MAX_RELOC_PAGES 1024
+
+#define PSB_LOW_REG_OFFS 0x0204
+#define PSB_HIGH_REG_OFFS 0x0600
+
+#define PSB_NUM_VBLANKS 2
+#define PSB_WATCHDOG_DELAY (DRM_HZ * 2)
+#define PSB_LID_DELAY (DRM_HZ / 10)
+
+#define MDFLD_PNW_A0 0x00
+#define MDFLD_PNW_B0 0x04
+#define MDFLD_PNW_C0 0x08
+
+#define MDFLD_DSR_2D_3D_0 BIT(0)
+#define MDFLD_DSR_2D_3D_2 BIT(1)
+#define MDFLD_DSR_CURSOR_0 BIT(2)
+#define MDFLD_DSR_CURSOR_2 BIT(3)
+#define MDFLD_DSR_OVERLAY_0 BIT(4)
+#define MDFLD_DSR_OVERLAY_2 BIT(5)
+#define MDFLD_DSR_MIPI_CONTROL BIT(6)
+#define MDFLD_DSR_DAMAGE_MASK_0 (BIT(0) | BIT(2) | BIT(4))
+#define MDFLD_DSR_DAMAGE_MASK_2 (BIT(1) | BIT(3) | BIT(5))
+#define MDFLD_DSR_2D_3D (MDFLD_DSR_2D_3D_0 | MDFLD_DSR_2D_3D_2)
+
+#define MDFLD_DSR_RR 45
+#define MDFLD_DPU_ENABLE BIT(31)
+#define MDFLD_DSR_FULLSCREEN BIT(30)
+#define MDFLD_DSR_DELAY (DRM_HZ / MDFLD_DSR_RR)
+
+#define PSB_PWR_STATE_ON 1
+#define PSB_PWR_STATE_OFF 2
+
+#define PSB_PMPOLICY_NOPM 0
+#define PSB_PMPOLICY_CLOCKGATING 1
+#define PSB_PMPOLICY_POWERDOWN 2
+
+#define PSB_PMSTATE_POWERUP 0
+#define PSB_PMSTATE_CLOCKGATED 1
+#define PSB_PMSTATE_POWERDOWN 2
+#define PSB_PCIx_MSI_ADDR_LOC 0x94
+#define PSB_PCIx_MSI_DATA_LOC 0x98
+
+#define MDFLD_PLANE_MAX_WIDTH 2048
+#define MDFLD_PLANE_MAX_HEIGHT 2048
+
+/*
+ *User options.
+ */
+
+struct drm_psb_uopt {
+ int pad; /*keep it here in case we use it in future*/
+};
+
+/**
+ *struct psb_context
+ *
+ *@buffers: array of pre-allocated validate buffers.
+ *@used_buffers: number of buffers in @buffers array currently in use.
+ *@validate_buffer: buffers validated from user-space.
+ *@kern_validate_buffers : buffers validated from kernel-space.
+ *@fence_flags : Fence flags to be used for fence creation.
+ *
+ *This structure is used during execbuf validation.
+ */
+
+struct psb_context {
+ struct psb_validate_buffer *buffers;
+ uint32_t used_buffers;
+ struct list_head validate_list;
+ struct list_head kern_validate_list;
+ uint32_t fence_types;
+};
+
+struct psb_validate_buffer;
+
+struct psb_msvdx_cmd_queue {
+ struct list_head head;
+ void *cmd;
+ unsigned long cmd_size;
+ uint32_t sequence;
+};
+
+/* Currently defined entrypoints */
+enum VAEntrypoint {
+ VAEntrypointVLD = 1,
+ VAEntrypointIZZ = 2,
+ VAEntrypointIDCT = 3,
+ VAEntrypointMoComp = 4,
+ VAEntrypointDeblocking = 5,
+ VAEntrypointEncSlice = 6, /* slice level encode */
+ VAEntrypointEncPicture = 7 /* pictuer encode, JPEG, etc */
+};
+
+struct psb_video_ctx {
+ struct list_head head;
+ struct file *filp; /* DRM device file pointer */
+ int ctx_type; /* profile<<8|entrypoint */
+ /* todo: more context specific data for multi-context support */
+};
+
+typedef int (*pfn_vsync_handler)(struct drm_device* dev, int pipe);
+
+
+#define MODE_SETTING_IN_CRTC 0x1
+#define MODE_SETTING_IN_ENCODER 0x2
+#define MODE_SETTING_ON_GOING 0x3
+#define MODE_SETTING_IN_DSR 0x4
+#define MODE_SETTING_ENCODER_DONE 0x8
+#define GCT_R10_HEADER_SIZE 16
+#define GCT_R10_DISPLAY_DESC_SIZE 28
+
+struct drm_psb_private {
+ /*
+ * DSI info.
+ */
+ void * dbi_dsr_info;
+#ifdef CONFIG_MDFLD_DSI_DPU
+ void * dbi_dpu_info;
+#endif
+ void * dsi_configs[2];
+
+ struct work_struct te_work;
+ int te_pipe;
+
+ /*
+ *TTM Glue.
+ */
+
+ struct drm_global_reference mem_global_ref;
+ struct ttm_bo_global_ref bo_global_ref;
+ int has_global;
+
+ struct drm_device *dev;
+ struct ttm_object_device *tdev;
+ struct ttm_fence_device fdev;
+ struct ttm_bo_device bdev;
+ struct ttm_lock ttm_lock;
+ struct vm_operations_struct *ttm_vm_ops;
+ int has_fence_device;
+ int has_bo_device;
+
+ unsigned long chipset;
+
+ struct drm_psb_dev_info_arg dev_info;
+ struct drm_psb_uopt uopt;
+
+ struct psb_gtt *pg;
+
+ /*GTT Memory manager*/
+ struct psb_gtt_mm *gtt_mm;
+
+ struct page *scratch_page;
+ uint32_t sequence[PSB_NUM_ENGINES];
+ uint32_t last_sequence[PSB_NUM_ENGINES];
+ uint32_t last_submitted_seq[PSB_NUM_ENGINES];
+
+ struct psb_mmu_driver *mmu;
+ struct psb_mmu_pd *pf_pd;
+
+ uint8_t *sgx_reg;
+ uint8_t __iomem *vdc_reg;
+#ifdef CONFIG_MDFD_GL3
+ uint8_t *gl3_reg;
+#endif
+ uint32_t gatt_free_offset;
+
+ /* IMG video context */
+ struct list_head video_ctx;
+ /* Current video context */
+ struct psb_video_ctx *topaz_ctx;
+ struct psb_video_ctx *msvdx_ctx;
+ /* previous vieo context */
+ struct psb_video_ctx *last_topaz_ctx;
+ struct psb_video_ctx *last_msvdx_ctx;
+
+ /*
+ *MSVDX
+ */
+ uint8_t *msvdx_reg;
+ atomic_t msvdx_mmu_invaldc;
+ void *msvdx_private;
+
+ /*
+ *TOPAZ
+ */
+ uint8_t *topaz_reg;
+ void *topaz_private;
+ uint8_t topaz_disabled;
+ uint32_t video_device_fuse;
+ atomic_t topaz_mmu_invaldc;
+
+ /*
+ *Fencing / irq.
+ */
+
+ uint32_t vdc_irq_mask;
+ uint32_t pipestat[PSB_NUM_PIPE];
+ bool vblanksEnabledForFlips;
+
+ spinlock_t irqmask_lock;
+ spinlock_t sequence_lock;
+
+ /*
+ *Modesetting
+ */
+ struct psb_intel_mode_device mode_dev;
+
+ struct drm_crtc *plane_to_crtc_mapping[PSB_NUM_PIPE];
+ struct drm_crtc *pipe_to_crtc_mapping[PSB_NUM_PIPE];
+ uint32_t num_pipe;
+
+ /*
+ * CI share buffer
+ */
+ unsigned int ci_region_start;
+ unsigned int ci_region_size;
+
+ /*
+ * RAR share buffer;
+ */
+ unsigned int rar_region_start;
+ unsigned int rar_region_size;
+
+ /*
+ *Memory managers
+ */
+
+ int have_camera;
+ int have_rar;
+ int have_tt;
+ int have_mem_mmu;
+ struct mutex temp_mem;
+
+ /*
+ *Relocation buffer mapping.
+ */
+
+ spinlock_t reloc_lock;
+ unsigned int rel_mapped_pages;
+ wait_queue_head_t rel_mapped_queue;
+
+ /*
+ *SAREA
+ */
+ struct drm_psb_sarea *sarea_priv;
+
+ /*
+ *OSPM info
+ */
+ uint32_t ospm_base;
+ spinlock_t ospm_lock;
+
+ /*
+ * Sizes info
+ */
+
+ struct drm_psb_sizes_arg sizes;
+
+ uint32_t fuse_reg_value;
+
+ /* vbt (gct) header information*/
+ struct mrst_vbt vbt_data;
+ /* info that is stored from the gct */
+ struct gct_ioctl_arg gct_data;
+ enum panel_type panel_id;
+
+ /* pci revision id for B0:D2:F0 */
+ uint8_t platform_rev_id;
+
+ /*
+ *LVDS info
+ */
+ int backlight_duty_cycle; /* restore backlight to this value */
+ bool panel_wants_dither;
+ struct drm_display_mode *panel_fixed_mode;
+ struct drm_display_mode *lfp_lvds_vbt_mode;
+ struct drm_display_mode *sdvo_lvds_vbt_mode;
+
+ struct bdb_lvds_backlight *lvds_bl; /*LVDS backlight info from VBT*/
+ struct psb_intel_i2c_chan *lvds_i2c_bus;
+
+ /* Feature bits from the VBIOS*/
+ unsigned int int_tv_support:1;
+ unsigned int lvds_dither:1;
+ unsigned int lvds_vbt:1;
+ unsigned int int_crt_support:1;
+ unsigned int lvds_use_ssc:1;
+ int lvds_ssc_freq;
+ bool is_lvds_on;
+
+/* MRST private date start */
+/*FIXME JLIU7 need to revisit */
+ unsigned int core_freq;
+ uint32_t iLVDS_enable;
+
+ /* pipe config register value */
+ uint32_t pipeconf;
+ uint32_t pipeconf1;
+ uint32_t pipeconf2;
+
+ /* plane control register value */
+ uint32_t dspcntr;
+ uint32_t dspcntr1;
+ uint32_t dspcntr2;
+
+ /* MRST_DSI private date start */
+ struct work_struct dsi_work;
+
+ /*
+ *MRST DSI info
+ */
+
+ /* The DPI panel power on */
+ bool dpi_panel_on;
+
+ /* The DBI panel power on */
+ bool dbi_panel_on;
+
+ /* The DPI display */
+ bool dpi;
+
+ enum mipi_panel_type panel_make;
+
+ /* Set if MIPI encoder wants to control plane/pipe */
+ bool dsi_plane_pipe_control;
+
+ /* status */
+ uint32_t videoModeFormat:2;
+ uint32_t laneCount:3;
+ uint32_t channelNumber:2;
+ uint32_t status_reserved:25;
+
+ /* dual display - DPI & DBI */
+ bool dual_display;
+
+ /* HS or LP transmission */
+ bool lp_transmission;
+
+ /* configuration phase */
+ bool config_phase;
+
+ /* first boot phase */
+ bool first_boot;
+
+ bool is_mipi_on;
+
+ /* DSI clock */
+ uint32_t RRate;
+ uint32_t DDR_Clock;
+ uint32_t DDR_Clock_Calculated;
+ uint32_t ClockBits;
+
+ /* DBI Buffer pointer */
+ u32 DBI_CB_phys;
+ u8 *p_DBI_commandBuffer;
+ uint32_t DBI_CB_pointer;
+ u8 *p_DBI_dataBuffer_orig;
+ u8 *p_DBI_dataBuffer;
+ uint32_t DBI_DB_pointer;
+
+ /* DSI panel spec */
+ uint32_t pixelClock;
+ uint32_t HsyncWidth;
+ uint32_t HbackPorch;
+ uint32_t HfrontPorch;
+ uint32_t HactiveArea;
+ uint32_t VsyncWidth;
+ uint32_t VbackPorch;
+ uint32_t VfrontPorch;
+ uint32_t VactiveArea;
+ uint32_t bpp:5;
+ uint32_t Reserved:27;
+/* MRST_DSI private date end */
+
+/* MDFLD_DSI private date start */
+ /* dual display - DPI & DBI */
+ bool dual_mipi;
+ uint32_t ksel;
+ uint32_t mipi_lane_config;
+ uint32_t mipi_ctrl_display;
+ /*
+ *MRST DSI info
+ */
+ /* The DPI panel power on */
+ bool dpi_panel_on2;
+
+ /* The DBI panel power on */
+ bool dbi_panel_on2;
+
+ /* The DPI display */
+ bool dpi2;
+
+ /* status */
+ uint32_t videoModeFormat2:2;
+ uint32_t laneCount2:3;
+ uint32_t channelNumber2:2;
+ uint32_t status_reserved2:25;
+
+ /* HS or LP transmission */
+ bool lp_transmission2;
+
+ /* configuration phase */
+ bool config_phase2;
+
+ /* DSI clock */
+ uint32_t RRate2;
+ uint32_t DDR_Clock2;
+ uint32_t DDR_Clock_Calculated2;
+ uint32_t ClockBits2;
+
+ /* DBI Buffer pointer */
+ u32 DBI_CB_phys2;
+ u8 *p_DBI_commandBuffer2;
+ uint32_t DBI_CB_pointer2;
+ u8 *p_DBI_dataBuffer_orig2;
+ u8 *p_DBI_dataBuffer2;
+
+ /* DSI panel spec */
+ uint32_t pixelClock2;
+ uint32_t HsyncWidth2;
+ uint32_t HbackPorch2;
+ uint32_t HfrontPorch2;
+ uint32_t HactiveArea2;
+ uint32_t VsyncWidth2;
+ uint32_t VbackPorch2;
+ uint32_t VfrontPorch2;
+ uint32_t VactiveArea2;
+ uint32_t bpp2:5;
+ uint32_t Reserved2:27;
+ struct mdfld_dsi_dbi_output * dbi_output;
+ struct mdfld_dsi_dbi_output * dbi_output2;
+/* MDFLD_DSI private date end */
+
+#ifdef CONFIG_PM_RUNTIME
+ /*runtime PM state*/
+ int rpm_enabled;
+ struct delayed_work rtpm_work;
+#endif
+
+ /*
+ *Register state
+ */
+ uint32_t saveDSPACNTR;
+ uint32_t saveDSPBCNTR;
+ uint32_t savePIPEACONF;
+ uint32_t savePIPEBCONF;
+ uint32_t savePIPEASRC;
+ uint32_t savePIPEBSRC;
+ uint32_t saveFPA0;
+ uint32_t saveFPA1;
+ uint32_t saveDPLL_A;
+ uint32_t saveDPLL_A_MD;
+ uint32_t saveHTOTAL_A;
+ uint32_t saveHBLANK_A;
+ uint32_t saveHSYNC_A;
+ uint32_t saveVTOTAL_A;
+ uint32_t saveVBLANK_A;
+ uint32_t saveVSYNC_A;
+ uint32_t saveDSPASTRIDE;
+ uint32_t saveDSPASIZE;
+ uint32_t saveDSPAPOS;
+ uint32_t saveDSPABASE;
+ uint32_t saveDSPASURF;
+ uint32_t saveDSPASTATUS;
+ uint32_t saveFPB0;
+ uint32_t saveFPB1;
+ uint32_t saveDPLL_B;
+ uint32_t saveDPLL_B_MD;
+ uint32_t saveHTOTAL_B;
+ uint32_t saveHBLANK_B;
+ uint32_t saveHSYNC_B;
+ uint32_t saveVTOTAL_B;
+ uint32_t saveVBLANK_B;
+ uint32_t saveVSYNC_B;
+ uint32_t saveDSPBSTRIDE;
+ uint32_t saveDSPBSIZE;
+ uint32_t saveDSPBPOS;
+ uint32_t saveDSPBBASE;
+ uint32_t saveDSPBSURF;
+ uint32_t saveDSPBSTATUS;
+ uint32_t saveVCLK_DIVISOR_VGA0;
+ uint32_t saveVCLK_DIVISOR_VGA1;
+ uint32_t saveVCLK_POST_DIV;
+ uint32_t saveVGACNTRL;
+ uint32_t saveADPA;
+ uint32_t saveLVDS;
+ uint32_t saveDVOA;
+ uint32_t saveDVOB;
+ uint32_t saveDVOC;
+ uint32_t savePP_ON;
+ uint32_t savePP_OFF;
+ uint32_t savePP_CONTROL;
+ uint32_t savePP_CYCLE;
+ uint32_t savePFIT_CONTROL;
+ uint32_t savePaletteA[256];
+ uint32_t savePaletteB[256];
+ uint32_t saveBLC_PWM_CTL2;
+ uint32_t saveBLC_PWM_CTL;
+ uint32_t saveCLOCKGATING;
+ uint32_t saveDSPARB;
+ uint32_t saveDSPATILEOFF;
+ uint32_t saveDSPBTILEOFF;
+ uint32_t saveDSPAADDR;
+ uint32_t saveDSPBADDR;
+ uint32_t savePFIT_AUTO_RATIOS;
+ uint32_t savePFIT_PGM_RATIOS;
+ uint32_t savePP_ON_DELAYS;
+ uint32_t savePP_OFF_DELAYS;
+ uint32_t savePP_DIVISOR;
+ uint32_t saveBSM;
+ uint32_t saveVBT;
+ uint32_t saveBCLRPAT_A;
+ uint32_t saveBCLRPAT_B;
+ uint32_t saveDSPALINOFF;
+ uint32_t saveDSPBLINOFF;
+ uint32_t savePERF_MODE;
+ uint32_t saveDSPFW1;
+ uint32_t saveDSPFW2;
+ uint32_t saveDSPFW3;
+ uint32_t saveDSPFW4;
+ uint32_t saveDSPFW5;
+ uint32_t saveDSPFW6;
+ uint32_t saveCHICKENBIT;
+ uint32_t saveDSPACURSOR_CTRL;
+ uint32_t saveDSPBCURSOR_CTRL;
+ uint32_t saveDSPACURSOR_BASE;
+ uint32_t saveDSPBCURSOR_BASE;
+ uint32_t saveDSPACURSOR_POS;
+ uint32_t saveDSPBCURSOR_POS;
+ uint32_t save_palette_a[256];
+ uint32_t save_palette_b[256];
+ uint32_t saveOV_OVADD;
+ uint32_t saveOV_OGAMC0;
+ uint32_t saveOV_OGAMC1;
+ uint32_t saveOV_OGAMC2;
+ uint32_t saveOV_OGAMC3;
+ uint32_t saveOV_OGAMC4;
+ uint32_t saveOV_OGAMC5;
+ uint32_t saveOVC_OVADD;
+ uint32_t saveOVC_OGAMC0;
+ uint32_t saveOVC_OGAMC1;
+ uint32_t saveOVC_OGAMC2;
+ uint32_t saveOVC_OGAMC3;
+ uint32_t saveOVC_OGAMC4;
+ uint32_t saveOVC_OGAMC5;
+
+ /*
+ * extra MDFLD Register state
+ */
+ uint32_t saveHDMIPHYMISCCTL;
+ uint32_t saveHDMIB_CONTROL;
+ uint32_t saveDSPCCNTR;
+ uint32_t savePIPECCONF;
+ uint32_t savePIPECSRC;
+ uint32_t saveHTOTAL_C;
+ uint32_t saveHBLANK_C;
+ uint32_t saveHSYNC_C;
+ uint32_t saveVTOTAL_C;
+ uint32_t saveVBLANK_C;
+ uint32_t saveVSYNC_C;
+ uint32_t saveDSPCSTRIDE;
+ uint32_t saveDSPCSIZE;
+ uint32_t saveDSPCPOS;
+ uint32_t saveDSPCSURF;
+ uint32_t saveDSPCSTATUS;
+ uint32_t saveDSPCLINOFF;
+ uint32_t saveDSPCTILEOFF;
+ uint32_t saveDSPCCURSOR_CTRL;
+ uint32_t saveDSPCCURSOR_BASE;
+ uint32_t saveDSPCCURSOR_POS;
+ uint32_t save_palette_c[256];
+ uint32_t saveOV_OVADD_C;
+ uint32_t saveOV_OGAMC0_C;
+ uint32_t saveOV_OGAMC1_C;
+ uint32_t saveOV_OGAMC2_C;
+ uint32_t saveOV_OGAMC3_C;
+ uint32_t saveOV_OGAMC4_C;
+ uint32_t saveOV_OGAMC5_C;
+
+ /* DSI reg save */
+ uint32_t saveDEVICE_READY_REG;
+ uint32_t saveINTR_EN_REG;
+ uint32_t saveDSI_FUNC_PRG_REG;
+ uint32_t saveHS_TX_TIMEOUT_REG;
+ uint32_t saveLP_RX_TIMEOUT_REG;
+ uint32_t saveTURN_AROUND_TIMEOUT_REG;
+ uint32_t saveDEVICE_RESET_REG;
+ uint32_t saveDPI_RESOLUTION_REG;
+ uint32_t saveHORIZ_SYNC_PAD_COUNT_REG;
+ uint32_t saveHORIZ_BACK_PORCH_COUNT_REG;
+ uint32_t saveHORIZ_FRONT_PORCH_COUNT_REG;
+ uint32_t saveHORIZ_ACTIVE_AREA_COUNT_REG;
+ uint32_t saveVERT_SYNC_PAD_COUNT_REG;
+ uint32_t saveVERT_BACK_PORCH_COUNT_REG;
+ uint32_t saveVERT_FRONT_PORCH_COUNT_REG;
+ uint32_t saveHIGH_LOW_SWITCH_COUNT_REG;
+ uint32_t saveINIT_COUNT_REG;
+ uint32_t saveMAX_RET_PAK_REG;
+ uint32_t saveVIDEO_FMT_REG;
+ uint32_t saveEOT_DISABLE_REG;
+ uint32_t saveLP_BYTECLK_REG;
+ uint32_t saveHS_LS_DBI_ENABLE_REG;
+ uint32_t saveTXCLKESC_REG;
+ uint32_t saveDPHY_PARAM_REG;
+ uint32_t saveMIPI_CONTROL_REG;
+ uint32_t saveMIPI;
+ uint32_t saveMIPI_C;
+ void (*init_drvIC)(struct drm_device *dev);
+ void (*dsi_prePowerState)(struct drm_device *dev);
+ void (*dsi_postPowerState)(struct drm_device *dev);
+
+ /* DPST Register Save */
+ uint32_t saveHISTOGRAM_INT_CONTROL_REG;
+ uint32_t saveHISTOGRAM_LOGIC_CONTROL_REG;
+ uint32_t savePWM_CONTROL_LOGIC;
+
+ /* MSI reg save */
+
+ uint32_t msi_addr;
+ uint32_t msi_data;
+
+ /*
+ *Scheduling.
+ */
+
+ struct mutex reset_mutex;
+ struct psb_scheduler scheduler;
+ struct mutex cmdbuf_mutex;
+ /*uint32_t ta_mem_pages;
+ struct psb_ta_mem *ta_mem;
+ int force_ta_mem_load;*/
+
+ /*
+ *TODO: change this to be per drm-context.
+ */
+
+ struct psb_context context;
+
+ /*
+ *Watchdog
+ */
+
+ spinlock_t watchdog_lock;
+ struct timer_list watchdog_timer;
+ struct work_struct watchdog_wq;
+ struct work_struct msvdx_watchdog_wq;
+ struct work_struct topaz_watchdog_wq;
+ int timer_available;
+
+ uint32_t apm_reg;
+ uint16_t apm_base;
+#ifdef OSPM_STAT
+ unsigned char graphics_state;
+ unsigned long gfx_on_time;
+ unsigned long gfx_off_time;
+ unsigned long gfx_last_mode_change;
+ unsigned long gfx_on_cnt;
+ unsigned long gfx_off_cnt;
+#endif
+
+ /*to be removed later*/
+ /*int dri_page_flipping;
+ int current_page;
+#if MDFLD_HDMI_JLIU7
+ int pipe_active[3];
+#else
+ int pipe_active[2];
+#endif
+ int saved_start[2];
+ int saved_offset[2];
+ int saved_stride[2];
+
+ int flip_start[2];
+ int flip_offset[2];
+ int flip_stride[2];*/
+
+
+ /*
+ * Used for modifying backlight from
+ * xrandr -- consider removing and using HAL instead
+ */
+ struct drm_property *backlight_property;
+ uint32_t blc_adj1;
+ uint32_t blc_adj2;
+
+ /*
+ * DPST and Hotplug state
+ */
+
+ struct dpst_state *psb_dpst_state;
+ struct hotplug_state *psb_hotplug_state;
+ pfn_vsync_handler psb_vsync_handler;
+
+ struct mutex dsr_mutex;
+ bool b_dsr;
+ bool b_dsr_enable;
+ bool dsr_fb_update_done_0;
+ bool dsr_fb_update_done_2;
+ uint32_t dsr_fb_update;
+ uint32_t dsr_idle_count;
+
+ /*
+ * Flag letting us know if we have a swapchain or not (DGA)
+ */
+ uint32_t swap_chain_flag;
+
+ bool dsi_device_ready;
+ bool hdmi_done_reading_edid;
+ bool xserver_start;
+
+ uint32_t tmds_clock_khz;
+ had_event_call_back mdfld_had_event_callbacks;
+ struct snd_intel_had_interface *had_interface;
+ void *had_pvt_data;
+
+ uint32_t hdmi_audio_interrupt_mask;
+
+ /*psb fb dev*/
+ void * fbdev;
+ bool b_pmic_backlight;
+
+ /*pmic register for BL*/
+ uint8_t saveBKLTCNT;
+ uint8_t saveBKLTREQ;
+ uint8_t saveBKLTBRTL;
+};
+
+struct psb_fpriv {
+ int bcd_index;
+ struct ttm_object_file *tfile;
+};
+
+struct psb_mmu_driver;
+
+extern int drm_crtc_probe_output_modes(struct drm_device *dev, int, int);
+extern int drm_pick_crtcs(struct drm_device *dev);
+
+
+static inline struct psb_fpriv *psb_fpriv(struct drm_file *file_priv)
+{
+ PVRSRV_FILE_PRIVATE_DATA *pvr_file_priv
+ = (PVRSRV_FILE_PRIVATE_DATA *)file_priv->driver_priv;
+ return (struct psb_fpriv *) pvr_file_priv->pPriv;
+}
+
+static inline struct drm_psb_private *psb_priv(struct drm_device *dev)
+{
+ return (struct drm_psb_private *) dev->dev_private;
+}
+
+/*
+ *TTM glue. psb_ttm_glue.c
+ */
+
+extern int psb_open(struct inode *inode, struct file *filp);
+extern int psb_release(struct inode *inode, struct file *filp);
+extern int psb_mmap(struct file *filp, struct vm_area_struct *vma);
+
+extern int psb_fence_signaled_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int psb_verify_access(struct ttm_buffer_object *bo,
+ struct file *filp);
+extern ssize_t psb_ttm_read(struct file *filp, char __user *buf,
+ size_t count, loff_t *f_pos);
+extern ssize_t psb_ttm_write(struct file *filp, const char __user *buf,
+ size_t count, loff_t *f_pos);
+extern int psb_fence_finish_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int psb_fence_unref_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int psb_pl_waitidle_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int psb_pl_setstatus_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int psb_pl_synccpu_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int psb_pl_unref_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int psb_pl_reference_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int psb_pl_create_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int psb_pl_ub_create_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int psb_extension_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int psb_ttm_global_init(struct drm_psb_private *dev_priv);
+extern void psb_ttm_global_release(struct drm_psb_private *dev_priv);
+extern int psb_getpageaddrs_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+/*
+ *MMU stuff.
+ */
+
+extern struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers,
+ int trap_pagefaults,
+ int invalid_type,
+ struct drm_psb_private *dev_priv);
+extern void psb_mmu_driver_takedown(struct psb_mmu_driver *driver);
+extern struct psb_mmu_pd *psb_mmu_get_default_pd(struct psb_mmu_driver
+ *driver);
+extern void psb_mmu_mirror_gtt(struct psb_mmu_pd *pd, uint32_t mmu_offset,
+ uint32_t gtt_start, uint32_t gtt_pages);
+extern struct psb_mmu_pd *psb_mmu_alloc_pd(struct psb_mmu_driver *driver,
+ int trap_pagefaults,
+ int invalid_type);
+extern void psb_mmu_free_pagedir(struct psb_mmu_pd *pd);
+extern void psb_mmu_flush(struct psb_mmu_driver *driver, int rc_prot);
+extern void psb_mmu_remove_pfn_sequence(struct psb_mmu_pd *pd,
+ unsigned long address,
+ uint32_t num_pages);
+extern int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd,
+ uint32_t start_pfn,
+ unsigned long address,
+ uint32_t num_pages, int type);
+extern int psb_mmu_virtual_to_pfn(struct psb_mmu_pd *pd, uint32_t virtual,
+ unsigned long *pfn);
+
+/*
+ *Enable / disable MMU for different requestors.
+ */
+
+
+extern void psb_mmu_set_pd_context(struct psb_mmu_pd *pd, int hw_context);
+extern int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages,
+ unsigned long address, uint32_t num_pages,
+ uint32_t desired_tile_stride,
+ uint32_t hw_tile_stride, int type);
+extern void psb_mmu_remove_pages(struct psb_mmu_pd *pd,
+ unsigned long address, uint32_t num_pages,
+ uint32_t desired_tile_stride,
+ uint32_t hw_tile_stride);
+/*
+ *psb_sgx.c
+ */
+
+
+
+extern int psb_cmdbuf_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int psb_reg_submit(struct drm_psb_private *dev_priv,
+ uint32_t *regs, unsigned int cmds);
+
+
+extern void psb_fence_or_sync(struct drm_file *file_priv,
+ uint32_t engine,
+ uint32_t fence_types,
+ uint32_t fence_flags,
+ struct list_head *list,
+ struct psb_ttm_fence_rep *fence_arg,
+ struct ttm_fence_object **fence_p);
+
+extern void psb_gl3_global_invalidation(struct drm_device *dev);
+
+/*
+ *psb_fence.c
+ */
+
+extern void psb_fence_handler(struct drm_device *dev, uint32_t class);
+
+extern int psb_fence_emit_sequence(struct ttm_fence_device *fdev,
+ uint32_t fence_class,
+ uint32_t flags, uint32_t *sequence,
+ unsigned long *timeout_jiffies);
+extern void psb_fence_error(struct drm_device *dev,
+ uint32_t class,
+ uint32_t sequence, uint32_t type, int error);
+extern int psb_ttm_fence_device_init(struct ttm_fence_device *fdev);
+
+/* MSVDX/Topaz stuff */
+extern int psb_remove_videoctx(struct drm_psb_private *dev_priv, struct file *filp);
+
+extern int lnc_video_frameskip(struct drm_device *dev,
+ uint64_t user_pointer);
+extern int lnc_video_getparam(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int psb_try_power_down_msvdx(struct drm_device *dev);
+
+/*
+ *psb_fb.c
+ */
+extern int psbfb_probed(struct drm_device *dev);
+extern int psbfb_remove(struct drm_device *dev,
+ struct drm_framebuffer *fb);
+extern int psbfb_kms_off_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int psbfb_kms_on_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern void *psbfb_vdc_reg(struct drm_device* dev);
+
+/* modesetting */
+extern void psb_modeset_init(struct drm_device *dev);
+extern void psb_modeset_cleanup(struct drm_device *dev);
+
+/*fbdev*/
+extern int psb_fbdev_init(struct drm_device * dev);
+
+/* psb_bl.c */
+int psb_backlight_init(struct drm_device *dev);
+void psb_backlight_exit(void);
+int psb_set_brightness(struct backlight_device *bd);
+int psb_get_brightness(struct backlight_device *bd);
+struct backlight_device * psb_get_backlight_device(void);
+
+/*
+ *Debug print bits setting
+ */
+#define PSB_D_GENERAL (1 << 0)
+#define PSB_D_INIT (1 << 1)
+#define PSB_D_IRQ (1 << 2)
+#define PSB_D_ENTRY (1 << 3)
+/* debug the get H/V BP/FP count */
+#define PSB_D_HV (1 << 4)
+#define PSB_D_DBI_BF (1 << 5)
+#define PSB_D_PM (1 << 6)
+#define PSB_D_RENDER (1 << 7)
+#define PSB_D_REG (1 << 8)
+#define PSB_D_MSVDX (1 << 9)
+#define PSB_D_TOPAZ (1 << 10)
+
+#ifndef DRM_DEBUG_CODE
+/* To enable debug printout, set drm_psb_debug in psb_drv.c
+ * to any combination of above print flags.
+ */
+/* #define DRM_DEBUG_CODE 2 */
+#endif
+
+extern int drm_psb_debug;
+extern int drm_psb_no_fb;
+extern int drm_psb_disable_vsync;
+extern int drm_topaz_sbuswa;
+
+#define PSB_DEBUG_GENERAL(_fmt, _arg...) \
+ PSB_DEBUG(PSB_D_GENERAL, _fmt, ##_arg)
+#define PSB_DEBUG_INIT(_fmt, _arg...) \
+ PSB_DEBUG(PSB_D_INIT, _fmt, ##_arg)
+#define PSB_DEBUG_IRQ(_fmt, _arg...) \
+ PSB_DEBUG(PSB_D_IRQ, _fmt, ##_arg)
+#define PSB_DEBUG_ENTRY(_fmt, _arg...) \
+ PSB_DEBUG(PSB_D_ENTRY, _fmt, ##_arg)
+#define PSB_DEBUG_HV(_fmt, _arg...) \
+ PSB_DEBUG(PSB_D_HV, _fmt, ##_arg)
+#define PSB_DEBUG_DBI_BF(_fmt, _arg...) \
+ PSB_DEBUG(PSB_D_DBI_BF, _fmt, ##_arg)
+#define PSB_DEBUG_PM(_fmt, _arg...) \
+ PSB_DEBUG(PSB_D_PM, _fmt, ##_arg)
+#define PSB_DEBUG_RENDER(_fmt, _arg...) \
+ PSB_DEBUG(PSB_D_RENDER, _fmt, ##_arg)
+#define PSB_DEBUG_REG(_fmt, _arg...) \
+ PSB_DEBUG(PSB_D_REG, _fmt, ##_arg)
+#define PSB_DEBUG_MSVDX(_fmt, _arg...) \
+ PSB_DEBUG(PSB_D_MSVDX, _fmt, ##_arg)
+#define PSB_DEBUG_TOPAZ(_fmt, _arg...) \
+ PSB_DEBUG(PSB_D_TOPAZ, _fmt, ##_arg)
+
+#if DRM_DEBUG_CODE
+#define PSB_DEBUG(_flag, _fmt, _arg...) \
+ do { \
+ if (unlikely((_flag) & drm_psb_debug)) \
+ printk(KERN_DEBUG \
+ "[psb:0x%02x:%s] " _fmt , _flag, \
+ __func__ , ##_arg); \
+ } while (0)
+#else
+#define PSB_DEBUG(_fmt, _arg...) do { } while (0)
+#endif
+
+/*
+ *Utilities
+ */
+#define DRM_DRIVER_PRIVATE_T struct drm_psb_private
+
+static inline u32 MDFLD_MSG_READ32(uint port, uint offset)
+{
+ int mcr = (0x10<<24) | (port << 16) | (offset << 8);
+ uint32_t ret_val = 0;
+ struct pci_dev *pci_root = pci_get_bus_and_slot (0, 0);
+ pci_write_config_dword (pci_root, 0xD0, mcr);
+ pci_read_config_dword (pci_root, 0xD4, &ret_val);
+ pci_dev_put(pci_root);
+ return ret_val;
+}
+static inline void MDFLD_MSG_WRITE32(uint port, uint offset, u32 value)
+{
+ int mcr = (0x11<<24) | (port << 16) | (offset << 8) | 0xF0;
+ struct pci_dev *pci_root = pci_get_bus_and_slot (0, 0);
+ pci_write_config_dword (pci_root, 0xD4, value);
+ pci_write_config_dword (pci_root, 0xD0, mcr);
+ pci_dev_put(pci_root);
+}
+
+static inline uint32_t REGISTER_READ(struct drm_device *dev, uint32_t reg)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ int reg_val = ioread32(dev_priv->vdc_reg + (reg));
+ PSB_DEBUG_REG("reg = 0x%x. reg_val = 0x%x. \n", reg, reg_val);
+ return reg_val;
+}
+
+#define REG_READ(reg) REGISTER_READ(dev, (reg))
+static inline void REGISTER_WRITE(struct drm_device *dev, uint32_t reg,
+ uint32_t val)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ if ((reg < 0x70084 || reg >0x70088) && (reg < 0xa000 || reg >0xa3ff))
+ PSB_DEBUG_REG("reg = 0x%x, val = 0x%x. \n", reg, val);
+
+ iowrite32((val), dev_priv->vdc_reg + (reg));
+}
+
+#define REG_WRITE(reg, val) REGISTER_WRITE(dev, (reg), (val))
+
+static inline void REGISTER_WRITE16(struct drm_device *dev,
+ uint32_t reg, uint32_t val)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+
+ PSB_DEBUG_REG("reg = 0x%x, val = 0x%x. \n", reg, val);
+
+ iowrite16((val), dev_priv->vdc_reg + (reg));
+}
+
+#define REG_WRITE16(reg, val) REGISTER_WRITE16(dev, (reg), (val))
+
+static inline void REGISTER_WRITE8(struct drm_device *dev,
+ uint32_t reg, uint32_t val)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+
+ PSB_DEBUG_REG("reg = 0x%x, val = 0x%x. \n", reg, val);
+
+ iowrite8((val), dev_priv->vdc_reg + (reg));
+}
+
+#define REG_WRITE8(reg, val) REGISTER_WRITE8(dev, (reg), (val))
+
+#define PSB_WVDC32(_val, _offs) \
+ iowrite32(_val, dev_priv->vdc_reg + (_offs))
+#define PSB_RVDC32(_offs) \
+ ioread32(dev_priv->vdc_reg + (_offs))
+
+/* #define TRAP_SGX_PM_FAULT 1 */
+#ifdef TRAP_SGX_PM_FAULT
+#define PSB_RSGX32(_offs) \
+({ \
+ if (inl(dev_priv->apm_base + PSB_APM_STS) & 0x3) { \
+ printk(KERN_ERR "access sgx when it's off!! (READ) %s, %d\n", \
+ __FILE__, __LINE__); \
+ mdelay(1000); \
+ } \
+ ioread32(dev_priv->sgx_reg + (_offs)); \
+})
+#else
+#define PSB_RSGX32(_offs) \
+ ioread32(dev_priv->sgx_reg + (_offs))
+#endif
+
+#define MSVDX_REG_DUMP 0
+#if MSVDX_REG_DUMP
+
+#define PSB_WMSVDX32(_val, _offs) \
+ printk("MSVDX: write %08x to reg 0x%08x\n", (unsigned int)(_val), (unsigned int)(_offs));\
+ iowrite32(_val, dev_priv->msvdx_reg + (_offs))
+#define PSB_RMSVDX32(_offs) \
+ ioread32(dev_priv->msvdx_reg + (_offs))
+
+#else
+
+#define PSB_WMSVDX32(_val, _offs) \
+ iowrite32(_val, dev_priv->msvdx_reg + (_offs))
+#define PSB_RMSVDX32(_offs) \
+ ioread32(dev_priv->msvdx_reg + (_offs))
+
+#endif
+
+#define IS_PENWELL(dev) 0 /* FIXME */
+
+extern int drm_psb_ospm;
+extern int drm_psb_cpurelax;
+extern int drm_psb_udelaydivider;
+extern int drm_psb_udelaymultiplier;
+extern int drm_psb_gl3_enable;
+extern int drm_psb_topaz_clockgating;
+
+extern char HDMI_EDID[20];
+
+#ifdef CONFIG_PM_RUNTIME
+extern int gfxrtdelay;
+#endif
+
+#define PSB_UDELAY(usec) \
+do { \
+ if (drm_psb_cpurelax == 0) \
+ DRM_UDELAY(usec * drm_psb_udelaymultiplier\
+ / drm_psb_udelaydivider);\
+ else \
+ cpu_relax(); \
+} while (0)
+
+#endif
--- /dev/null
+/**************************************************************************
+ * Copyright (c) 2007, Intel Corporation.
+ * 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 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.
+ *
+ **************************************************************************/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/console.h>
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include <drm/drm_crtc.h>
+
+#include "psb_drv.h"
+#include "psb_intel_reg.h"
+#include "psb_intel_drv.h"
+#include "psb_ttm_userobj_api.h"
+#include "psb_fb.h"
+#include "psb_pvr_glue.h"
+
+#include "mdfld_dsi_dbi.h"
+#include "mdfld_dsi_output.h"
+#include "mdfld_output.h"
+
+extern int MRSTLFBHandleChangeFB(struct drm_device* dev, struct psb_framebuffer *psbfb);
+
+static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb);
+static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb,
+ struct drm_file *file_priv,
+ unsigned int *handle);
+
+static const struct drm_framebuffer_funcs psb_fb_funcs = {
+ .destroy = psb_user_framebuffer_destroy,
+ .create_handle = psb_user_framebuffer_create_handle,
+};
+
+#define CMAP_TOHW(_val, _width) ((((_val) << (_width)) + 0x7FFF - (_val)) >> 16)
+
+void *psbfb_vdc_reg(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv;
+ dev_priv = (struct drm_psb_private *) dev->dev_private;
+ return dev_priv->vdc_reg;
+}
+/*EXPORT_SYMBOL(psbfb_vdc_reg); */
+
+static int psbfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp,
+ struct fb_info *info)
+{
+ struct psb_fbdev * fbdev = info->par;
+ struct drm_framebuffer *fb = fbdev->psb_fb_helper.fb;
+ uint32_t v;
+
+ if (!fb)
+ return -ENOMEM;
+
+ if (regno > 255)
+ return 1;
+
+ red = CMAP_TOHW(red, info->var.red.length);
+ blue = CMAP_TOHW(blue, info->var.blue.length);
+ green = CMAP_TOHW(green, info->var.green.length);
+ transp = CMAP_TOHW(transp, info->var.transp.length);
+
+ v = (red << info->var.red.offset) |
+ (green << info->var.green.offset) |
+ (blue << info->var.blue.offset) |
+ (transp << info->var.transp.offset);
+
+ if (regno < 16) {
+ switch (fb->bits_per_pixel) {
+ case 16:
+ ((uint32_t *) info->pseudo_palette)[regno] = v;
+ break;
+ case 24:
+ case 32:
+ ((uint32_t *) info->pseudo_palette)[regno] = v;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static int psbfb_kms_off(struct drm_device *dev, int suspend)
+{
+ struct drm_framebuffer *fb = NULL;
+ struct psb_framebuffer * psbfb = to_psb_fb(fb);
+ DRM_DEBUG("psbfb_kms_off_ioctl\n");
+
+ mutex_lock(&dev->mode_config.mutex);
+ list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
+ struct fb_info *info = psbfb->fbdev;
+
+ if (suspend) {
+ fb_set_suspend(info, 1);
+ drm_fb_helper_blank(FB_BLANK_POWERDOWN, info);
+ }
+ }
+ mutex_unlock(&dev->mode_config.mutex);
+ return 0;
+}
+
+int psbfb_kms_off_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ int ret;
+
+ if (drm_psb_no_fb)
+ return 0;
+ console_lock();
+ ret = psbfb_kms_off(dev, 0);
+ console_unlock();
+
+ return ret;
+}
+
+static int psbfb_kms_on(struct drm_device *dev, int resume)
+{
+ struct drm_framebuffer *fb = NULL;
+ struct psb_framebuffer * psbfb = to_psb_fb(fb);
+
+ DRM_DEBUG("psbfb_kms_on_ioctl\n");
+
+ mutex_lock(&dev->mode_config.mutex);
+ list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
+ struct fb_info *info = psbfb->fbdev;
+
+ if (resume) {
+ fb_set_suspend(info, 0);
+ drm_fb_helper_blank(FB_BLANK_UNBLANK, info);
+ }
+ }
+ mutex_unlock(&dev->mode_config.mutex);
+
+ return 0;
+}
+
+int psbfb_kms_on_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ int ret;
+
+ if (drm_psb_no_fb)
+ return 0;
+ console_lock();
+ ret = psbfb_kms_on(dev, 0);
+ console_unlock();
+ drm_helper_disable_unused_functions(dev);
+ return ret;
+}
+
+static void psbfb_suspend(struct drm_device *dev)
+{
+ console_lock();
+ psbfb_kms_off(dev, 1);
+ console_unlock();
+}
+
+static void psbfb_resume(struct drm_device *dev)
+{
+ console_lock();
+ psbfb_kms_on(dev, 1);
+ console_unlock();
+ drm_helper_disable_unused_functions(dev);
+}
+
+static struct fb_ops psbfb_ops = {
+ .owner = THIS_MODULE,
+ .fb_check_var = drm_fb_helper_check_var,
+ .fb_set_par = drm_fb_helper_set_par,
+ .fb_blank = drm_fb_helper_blank,
+ .fb_setcolreg = psbfb_setcolreg,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+};
+
+static struct drm_framebuffer *psb_framebuffer_create
+ (struct drm_device *dev, struct drm_mode_fb_cmd *r,
+ void *mm_private)
+{
+ struct psb_framebuffer *fb;
+ int ret;
+
+ fb = kzalloc(sizeof(*fb), GFP_KERNEL);
+ if (!fb)
+ return NULL;
+
+ ret = drm_framebuffer_init(dev, &fb->base, &psb_fb_funcs);
+
+ if (ret)
+ goto err;
+
+ drm_helper_mode_fill_fb_struct(&fb->base, r);
+
+ fb->pvrBO = mm_private;
+
+ return &fb->base;
+
+err:
+ kfree(fb);
+ return NULL;
+}
+
+static struct drm_framebuffer *psb_user_framebuffer_create
+ (struct drm_device *dev, struct drm_file *filp,
+ struct drm_mode_fb_cmd *r)
+{
+ struct psb_framebuffer *psbfb;
+ struct drm_framebuffer *fb;
+ struct fb_info *info;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = IMG_NULL;
+ IMG_HANDLE hKernelMemInfo = (IMG_HANDLE)r->handle;
+ struct drm_psb_private *dev_priv
+ = (struct drm_psb_private *) dev->dev_private;
+ struct psb_fbdev * fbdev = dev_priv->fbdev;
+ struct psb_gtt *pg = dev_priv->pg;
+ int ret;
+ uint32_t offset;
+ uint64_t size;
+
+ ret = psb_get_meminfo_by_handle(hKernelMemInfo, &psKernelMemInfo);
+ if (ret) {
+ DRM_ERROR("Cannot get meminfo for handle 0x%x\n",
+ (IMG_UINT32)hKernelMemInfo);
+
+ return NULL;
+ }
+
+ DRM_DEBUG("Got Kernel MemInfo for handle %p\n", hKernelMemInfo);
+
+ /* JB: TODO not drop, make smarter */
+ size = psKernelMemInfo->ui32AllocSize;
+ if (size < r->height * r->pitch)
+ return NULL;
+
+ /* JB: TODO not drop, refcount buffer */
+ /* return psb_framebuffer_create(dev, r, bo); */
+
+ fb = psb_framebuffer_create(dev, r, (void *)psKernelMemInfo);
+ if (!fb) {
+ DRM_ERROR("failed to allocate fb.\n");
+ return NULL;
+ }
+
+ psbfb = to_psb_fb(fb);
+ psbfb->size = size;
+ psbfb->hKernelMemInfo = hKernelMemInfo;
+
+ DRM_DEBUG("Mapping to gtt..., KernelMemInfo %p\n", psKernelMemInfo);
+
+ /*if not VRAM, map it into tt aperture*/
+ if (psKernelMemInfo->pvLinAddrKM != pg->vram_addr) {
+ ret = psb_gtt_map_meminfo(dev, hKernelMemInfo, &offset);
+ if (ret) {
+ DRM_ERROR("map meminfo for 0x%x failed\n",
+ (IMG_UINT32)hKernelMemInfo);
+ return NULL;
+ }
+ psbfb->offset = (offset << PAGE_SHIFT);
+ } else {
+ psbfb->offset = 0;
+ }
+ info = framebuffer_alloc(0, &dev->pdev->dev);
+ if (!info)
+ return NULL;
+
+ strcpy(info->fix.id, "psbfb");
+
+ info->flags = FBINFO_DEFAULT;
+ info->fbops = &psbfb_ops;
+
+ info->fix.smem_start = dev->mode_config.fb_base;
+ info->fix.smem_len = size;
+
+ info->screen_base = psKernelMemInfo->pvLinAddrKM;
+ info->screen_size = size;
+
+ drm_fb_helper_fill_fix(info, fb->pitch, fb->depth);
+ drm_fb_helper_fill_var(info, &fbdev->psb_fb_helper, fb->width, fb->height);
+
+ info->fix.mmio_start = pci_resource_start(dev->pdev, 0);
+ info->fix.mmio_len = pci_resource_len(dev->pdev, 0);
+
+ info->pixmap.size = 64 * 1024;
+ info->pixmap.buf_align = 8;
+ info->pixmap.access_align = 32;
+ info->pixmap.flags = FB_PIXMAP_SYSTEM;
+ info->pixmap.scan_align = 1;
+
+ psbfb->fbdev = info;
+ fbdev->pfb = psbfb;
+
+ fbdev->psb_fb_helper.fb = fb;
+ fbdev->psb_fb_helper.fbdev = info;
+ MRSTLFBHandleChangeFB(dev, psbfb);
+
+ return fb;
+}
+
+static int psbfb_create(struct psb_fbdev * fbdev, struct drm_fb_helper_surface_size * sizes)
+{
+ struct drm_device * dev = fbdev->psb_fb_helper.dev;
+ struct drm_psb_private * dev_priv = (struct drm_psb_private *)dev->dev_private;
+ struct psb_gtt *pg = dev_priv->pg;
+ struct fb_info * info;
+ struct drm_framebuffer *fb;
+ struct psb_framebuffer * psbfb;
+ struct drm_mode_fb_cmd mode_cmd;
+ struct device * device = &dev->pdev->dev;
+ int size, aligned_size;
+ int ret;
+
+ mode_cmd.width = sizes->surface_width;
+ mode_cmd.height = sizes->surface_height;
+
+ mode_cmd.bpp = 32;
+ //HW requires pitch to be 64 byte aligned
+ mode_cmd.pitch = ALIGN(mode_cmd.width * ((mode_cmd.bpp + 1) / 8), 64);
+ mode_cmd.depth = 24;
+
+ size = mode_cmd.pitch * mode_cmd.height;
+ aligned_size = ALIGN(size, PAGE_SIZE);
+
+ mutex_lock(&dev->struct_mutex);
+ fb = psb_framebuffer_create(dev, &mode_cmd, NULL);
+ if (!fb) {
+ DRM_ERROR("failed to allocate fb.\n");
+ ret = -ENOMEM;
+ goto out_err0;
+ }
+ psbfb = to_psb_fb(fb);
+ psbfb->size = size;
+
+ info = framebuffer_alloc(sizeof(struct psb_fbdev), device);
+ if(!info) {
+ ret = -ENOMEM;
+ goto out_err1;
+ }
+
+ info->par = fbdev;
+
+ psbfb->fbdev = info;
+
+ fbdev->psb_fb_helper.fb = fb;
+ fbdev->psb_fb_helper.fbdev = info;
+ fbdev->pfb = psbfb;
+
+ strcpy(info->fix.id, "psbfb");
+
+ info->flags = FBINFO_DEFAULT;
+ info->fbops = &psbfb_ops;
+ info->fix.smem_start = dev->mode_config.fb_base;
+ info->fix.smem_len = size;
+ info->screen_base = (char *)pg->vram_addr;
+ info->screen_size = size;
+ memset(info->screen_base, 0, size);
+
+ drm_fb_helper_fill_fix(info, fb->pitch, fb->depth);
+ drm_fb_helper_fill_var(info, &fbdev->psb_fb_helper, sizes->fb_width, sizes->fb_height);
+
+ info->fix.mmio_start = pci_resource_start(dev->pdev, 0);
+ info->fix.mmio_len = pci_resource_len(dev->pdev, 0);
+
+ info->pixmap.size = 64 * 1024;
+ info->pixmap.buf_align = 8;
+ info->pixmap.access_align = 32;
+ info->pixmap.flags = FB_PIXMAP_SYSTEM;
+ info->pixmap.scan_align = 1;
+
+ DRM_DEBUG("fb depth is %d\n", fb->depth);
+ DRM_DEBUG(" pitch is %d\n", fb->pitch);
+
+ printk(KERN_INFO"allocated %dx%d fb\n", psbfb->base.width, psbfb->base.height);
+
+ mutex_unlock(&dev->struct_mutex);
+
+ return 0;
+out_err0:
+ fb->funcs->destroy(fb);
+out_err1:
+ mutex_unlock(&dev->struct_mutex);
+ return ret;
+}
+
+static void psbfb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, u16 blue, int regno)
+{
+ DRM_DEBUG("%s\n", __FUNCTION__);
+}
+
+static void psbfb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, u16 *blue, int regno)
+{
+ DRM_DEBUG("%s\n", __FUNCTION__);
+}
+
+static int psbfb_probe(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes)
+{
+ struct psb_fbdev * psb_fbdev = (struct psb_fbdev *)helper;
+ int new_fb = 0;
+ int ret;
+
+ DRM_DEBUG("%s\n", __FUNCTION__);
+
+ if(!helper->fb) {
+ ret = psbfb_create(psb_fbdev, sizes);
+ if(ret) {
+ return ret;
+ }
+
+ new_fb = 1;
+ }
+
+ return new_fb;
+}
+
+static struct drm_fb_helper_funcs psb_fb_helper_funcs = {
+ .gamma_set = psbfb_gamma_set,
+ .gamma_get = psbfb_gamma_get,
+ .fb_probe = psbfb_probe,
+};
+
+static int psb_fbdev_destroy(struct drm_device * dev, struct psb_fbdev * fbdev)
+{
+ struct fb_info * info;
+ struct psb_framebuffer * psbfb = fbdev->pfb;
+
+ if(fbdev->psb_fb_helper.fbdev) {
+ info = fbdev->psb_fb_helper.fbdev;
+ unregister_framebuffer(info);
+ iounmap(info->screen_base);
+ framebuffer_release(info);
+ }
+
+ drm_fb_helper_fini(&fbdev->psb_fb_helper);
+
+ drm_framebuffer_cleanup(&psbfb->base);
+
+ return 0;
+}
+
+int psb_fbdev_init(struct drm_device * dev)
+{
+ struct psb_fbdev * fbdev;
+ struct drm_psb_private * dev_priv =
+ (struct drm_psb_private *)dev->dev_private;
+ int num_crtc;
+
+ fbdev = kzalloc(sizeof(struct psb_fbdev), GFP_KERNEL);
+ if(!fbdev) {
+ DRM_ERROR("no memory\n");
+ return -ENOMEM;
+ }
+
+ dev_priv->fbdev = fbdev;
+ fbdev->psb_fb_helper.funcs = &psb_fb_helper_funcs;
+
+ /*FIXME: how many crtc will MDFL support?*/
+ num_crtc = 3;
+
+ drm_fb_helper_init(dev, &fbdev->psb_fb_helper, num_crtc, INTELFB_CONN_LIMIT);
+
+ drm_fb_helper_single_add_all_connectors(&fbdev->psb_fb_helper);
+ drm_fb_helper_initial_config(&fbdev->psb_fb_helper, 32);
+ return 0;
+}
+
+static void psb_fbdev_fini(struct drm_device * dev)
+{
+ struct drm_psb_private * dev_priv =
+ (struct drm_psb_private *)dev->dev_private;
+
+ if(!dev_priv->fbdev) {
+ return;
+ }
+
+ psb_fbdev_destroy(dev, dev_priv->fbdev);
+ kfree(dev_priv->fbdev);
+ dev_priv->fbdev = NULL;
+}
+
+static void psbfb_output_poll_changed(struct drm_device * dev)
+{
+ struct drm_psb_private * dev_priv = (struct drm_psb_private *)dev->dev_private;
+ struct psb_fbdev * fbdev = (struct psb_fbdev *)dev_priv->fbdev;
+ drm_fb_helper_hotplug_event(&fbdev->psb_fb_helper);
+}
+
+int psbfb_remove(struct drm_device *dev, struct drm_framebuffer *fb)
+{
+ struct fb_info *info;
+ struct psb_framebuffer * psbfb = to_psb_fb(fb);
+
+ if (drm_psb_no_fb)
+ return 0;
+
+ info = psbfb->fbdev;
+ psbfb->pvrBO = NULL;
+ MRSTLFBHandleChangeFB(dev, psbfb);
+
+ if (info) {
+ framebuffer_release(info);
+ }
+
+ return 0;
+}
+/*EXPORT_SYMBOL(psbfb_remove); */
+
+static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb,
+ struct drm_file *file_priv,
+ unsigned int *handle)
+{
+ /* JB: TODO currently we can't go from a bo to a handle with ttm */
+ (void) file_priv;
+ *handle = 0;
+ return 0;
+}
+
+static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb)
+{
+ struct drm_device *dev = fb->dev;
+ struct psb_framebuffer *psbfb = to_psb_fb(fb);
+
+ /*ummap gtt pages*/
+ psb_gtt_unmap_meminfo(dev, psbfb->hKernelMemInfo);
+ if (psbfb->fbdev)
+ psbfb_remove(dev, fb);
+
+ /* JB: TODO not drop, refcount buffer */
+ drm_framebuffer_cleanup(fb);
+
+ kfree(fb);
+}
+
+static const struct drm_mode_config_funcs psb_mode_funcs = {
+ .fb_create = psb_user_framebuffer_create,
+ .output_poll_changed = psbfb_output_poll_changed,
+};
+
+static int psb_create_backlight_property(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv
+ = (struct drm_psb_private *) dev->dev_private;
+ struct drm_property *backlight;
+
+ if (dev_priv->backlight_property)
+ return 0;
+
+ backlight = drm_property_create(dev,
+ DRM_MODE_PROP_RANGE,
+ "backlight",
+ 2);
+ backlight->values[0] = 0;
+ backlight->values[1] = 100;
+
+ dev_priv->backlight_property = backlight;
+
+ return 0;
+}
+
+static void psb_setup_outputs(struct drm_device *dev)
+{
+ struct drm_connector *connector;
+
+ PSB_DEBUG_ENTRY("\n");
+
+ drm_mode_create_scaling_mode_property(dev);
+
+ psb_create_backlight_property(dev);
+
+ mdfld_output_init(dev);
+
+ list_for_each_entry(connector, &dev->mode_config.connector_list,
+ head) {
+ struct psb_intel_output *psb_intel_output =
+ to_psb_intel_output(connector);
+ struct drm_encoder *encoder = &psb_intel_output->enc;
+ int crtc_mask = 0, clone_mask = 0;
+
+ /* valid crtcs */
+ switch (psb_intel_output->type) {
+ case INTEL_OUTPUT_SDVO:
+ crtc_mask = ((1 << 0) | (1 << 1));
+ clone_mask = (1 << INTEL_OUTPUT_SDVO);
+ break;
+ case INTEL_OUTPUT_LVDS:
+ PSB_DEBUG_ENTRY("LVDS. \n");
+ crtc_mask = (1 << 1);
+
+ clone_mask = (1 << INTEL_OUTPUT_LVDS);
+ break;
+ case INTEL_OUTPUT_MIPI:
+ PSB_DEBUG_ENTRY("MIPI. \n");
+ crtc_mask = (1 << 0);
+ clone_mask = (1 << INTEL_OUTPUT_MIPI);
+ break;
+ case INTEL_OUTPUT_MIPI2:
+ PSB_DEBUG_ENTRY("MIPI2. \n");
+ crtc_mask = (1 << 2);
+ clone_mask = (1 << INTEL_OUTPUT_MIPI2);
+ break;
+ case INTEL_OUTPUT_HDMI:
+ PSB_DEBUG_ENTRY("HDMI. \n");
+ crtc_mask = (1 << 1);
+ clone_mask = (1 << INTEL_OUTPUT_HDMI);
+ break;
+ }
+
+ encoder->possible_crtcs = crtc_mask;
+ encoder->possible_clones =
+ psb_intel_connector_clones(dev, clone_mask);
+
+ }
+}
+
+static void *psb_bo_from_handle(struct drm_device *dev,
+ struct drm_file *file_priv,
+ unsigned int handle)
+{
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = IMG_NULL;
+ IMG_HANDLE hKernelMemInfo = (IMG_HANDLE)handle;
+ int ret;
+
+ ret = psb_get_meminfo_by_handle(hKernelMemInfo, &psKernelMemInfo);
+ if (ret) {
+ DRM_ERROR("Cannot get meminfo for handle 0x%x\n",
+ (IMG_UINT32)hKernelMemInfo);
+ return NULL;
+ }
+
+ return (void *)psKernelMemInfo;
+}
+
+static size_t psb_bo_size(struct drm_device *dev, void *bof)
+{
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = (PVRSRV_KERNEL_MEM_INFO *)bof;
+ return (size_t)psKernelMemInfo->ui32AllocSize;
+}
+
+static size_t psb_bo_offset(struct drm_device *dev, void *bof)
+{
+ struct psb_framebuffer *psbfb
+ = (struct psb_framebuffer *)bof;
+
+ return (size_t)psbfb->offset;
+}
+
+static int psb_bo_pin_for_scanout(struct drm_device *dev, void *bo)
+{
+ return 0;
+}
+
+static int psb_bo_unpin_for_scanout(struct drm_device *dev, void *bo)
+{
+ return 0;
+}
+
+void psb_modeset_init(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) dev->dev_private;
+ struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;
+ int i;
+
+ PSB_DEBUG_ENTRY("\n");
+ /* Init mm functions */
+ mode_dev->bo_from_handle = psb_bo_from_handle;
+ mode_dev->bo_size = psb_bo_size;
+ mode_dev->bo_offset = psb_bo_offset;
+ mode_dev->bo_pin_for_scanout = psb_bo_pin_for_scanout;
+ mode_dev->bo_unpin_for_scanout = psb_bo_unpin_for_scanout;
+
+ drm_mode_config_init(dev);
+
+ dev->mode_config.min_width = 0;
+ dev->mode_config.min_height = 0;
+
+ dev->mode_config.funcs = (void *) &psb_mode_funcs;
+
+ /* set memory base */
+ /* MRST and PSB should use BAR 2*/
+ pci_read_config_dword(dev->pdev, PSB_BSM, (uint32_t *) &(dev->mode_config.fb_base));
+
+ for (i = 0; i < dev_priv->num_pipe; i++)
+ psb_intel_crtc_init(dev, i, mode_dev);
+
+ dev->mode_config.max_width = dev->mode_config.num_crtc * MDFLD_PLANE_MAX_WIDTH;
+ dev->mode_config.max_height = dev->mode_config.num_crtc * MDFLD_PLANE_MAX_HEIGHT;
+
+ psb_setup_outputs(dev);
+
+ /* setup fbs */
+ /* drm_initial_config(dev); */
+}
+
+void psb_modeset_cleanup(struct drm_device *dev)
+{
+ mutex_lock(&dev->struct_mutex);
+
+ drm_kms_helper_poll_fini(dev);
+ psb_fbdev_fini(dev);
+
+ drm_mode_config_cleanup(dev);
+
+ mutex_unlock(&dev->struct_mutex);
+}
--- /dev/null
+/*
+ * Copyright (c) 2008, Intel Corporation
+ *
+ * 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 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.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#ifndef _PSB_FB_H_
+#define _PSB_FB_H_
+
+#include <linux/version.h>
+#include <drm/drmP.h>
+#include <drm/drm_fb_helper.h>
+
+#include "psb_drv.h"
+
+/*IMG Headers*/
+#include "servicesint.h"
+
+struct psb_framebuffer {
+ struct drm_framebuffer base;
+ struct address_space *addr_space;
+ struct ttm_buffer_object *bo;
+ struct fb_info * fbdev;
+ /* struct ttm_bo_kmap_obj kmap; */
+ PVRSRV_KERNEL_MEM_INFO *pvrBO;
+ IMG_HANDLE hKernelMemInfo;
+ uint32_t size;
+ uint32_t offset;
+};
+
+struct psb_fbdev {
+ struct drm_fb_helper psb_fb_helper;
+ struct psb_framebuffer * pfb;
+};
+
+#define to_psb_fb(x) container_of(x, struct psb_framebuffer, base)
+
+
+extern int psb_intel_connector_clones(struct drm_device *dev, int type_mask);
+
+
+#endif
+
--- /dev/null
+/*
+ * Copyright (c) 2007, Intel Corporation.
+ * 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 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.
+ *
+ * Authors: Thomas Hellstrom <thomas-at-tungstengraphics.com>
+ */
+
+#include <drm/drmP.h>
+#include "psb_drv.h"
+#include "psb_pvr_glue.h"
+
+static inline uint32_t psb_gtt_mask_pte(uint32_t pfn, int type)
+{
+ uint32_t mask = PSB_PTE_VALID;
+
+ if (type & PSB_MMU_CACHED_MEMORY)
+ mask |= PSB_PTE_CACHED;
+ if (type & PSB_MMU_RO_MEMORY)
+ mask |= PSB_PTE_RO;
+ if (type & PSB_MMU_WO_MEMORY)
+ mask |= PSB_PTE_WO;
+
+ return (pfn << PAGE_SHIFT) | mask;
+}
+
+struct psb_gtt *psb_gtt_alloc(struct drm_device *dev) {
+ struct psb_gtt *tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
+
+ if (!tmp)
+ return NULL;
+
+ init_rwsem(&tmp->sem);
+ tmp->dev = dev;
+
+ return tmp;
+}
+
+void psb_gtt_takedown(struct psb_gtt *pg, int free)
+{
+ struct drm_psb_private *dev_priv = pg->dev->dev_private;
+
+ if (!pg)
+ return;
+
+ if (pg->gtt_map) {
+ iounmap(pg->gtt_map);
+ pg->gtt_map = NULL;
+ }
+ if (pg->initialized) {
+ pci_write_config_word(pg->dev->pdev, PSB_GMCH_CTRL,
+ pg->gmch_ctrl);
+ PSB_WVDC32(pg->pge_ctl, PSB_PGETBL_CTL);
+ (void) PSB_RVDC32(PSB_PGETBL_CTL);
+ }
+ if (free)
+ kfree(pg);
+}
+
+int psb_gtt_init(struct psb_gtt *pg, int resume)
+{
+ struct drm_device *dev = pg->dev;
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ unsigned gtt_pages;
+ unsigned long stolen_size, vram_stolen_size, ci_stolen_size;
+ unsigned long rar_stolen_size;
+ unsigned i, num_pages;
+ unsigned pfn_base;
+ uint32_t ci_pages, vram_pages;
+ uint32_t tt_pages;
+ uint32_t __iomem *ttm_gtt_map;
+ uint32_t dvmt_mode = 0;
+
+ int ret = 0;
+ uint32_t pte;
+
+ pci_read_config_word(dev->pdev, PSB_GMCH_CTRL, &pg->gmch_ctrl);
+ pci_write_config_word(dev->pdev, PSB_GMCH_CTRL,
+ pg->gmch_ctrl | _PSB_GMCH_ENABLED);
+
+ pg->pge_ctl = PSB_RVDC32(PSB_PGETBL_CTL);
+ PSB_WVDC32(pg->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL);
+ (void) PSB_RVDC32(PSB_PGETBL_CTL);
+
+ pg->initialized = 1;
+
+ pg->gtt_phys_start = pg->pge_ctl & PAGE_MASK;
+
+ pg->gatt_start = pci_resource_start(dev->pdev, PSB_GATT_RESOURCE);
+ /* fix me: video mmu has hw bug to access 0x0D0000000,
+ * then make gatt start at 0x0e000,0000 */
+ pg->mmu_gatt_start = PSB_MEM_TT_START;
+ pg->gtt_start = pci_resource_start(dev->pdev, PSB_GTT_RESOURCE);
+ gtt_pages =
+ pci_resource_len(dev->pdev, PSB_GTT_RESOURCE) >> PAGE_SHIFT;
+ pg->gatt_pages = pci_resource_len(dev->pdev, PSB_GATT_RESOURCE)
+ >> PAGE_SHIFT;
+
+ pci_read_config_dword(dev->pdev, PSB_BSM, &pg->stolen_base);
+ vram_stolen_size = pg->gtt_phys_start - pg->stolen_base - PAGE_SIZE;
+
+ /* CI is not included in the stolen size since the TOPAZ MMU bug */
+ ci_stolen_size = dev_priv->ci_region_size;
+ /* Don't add CI & RAR share buffer space
+ * managed by TTM to stolen_size */
+ stolen_size = vram_stolen_size;
+
+ rar_stolen_size = dev_priv->rar_region_size;
+
+ printk(KERN_INFO"GMMADR(region 0) start: 0x%08x (%dM).\n",
+ pg->gatt_start, pg->gatt_pages / 256);
+ printk(KERN_INFO"GTTADR(region 3) start: 0x%08x (can map %dM RAM), and actual RAM base 0x%08x.\n",
+ pg->gtt_start, gtt_pages * 4, pg->gtt_phys_start);
+ printk(KERN_INFO"Stole memory information \n");
+ printk(KERN_INFO" base in RAM: 0x%x \n", pg->stolen_base);
+ printk(KERN_INFO" size: %luK, calculated by (GTT RAM base) - (Stolen base), seems wrong\n",
+ vram_stolen_size / 1024);
+ dvmt_mode = (pg->gmch_ctrl >> 4) & 0x7;
+ printk(KERN_INFO" the correct size should be: %dM(dvmt mode=%d) \n",
+ (dvmt_mode == 1) ? 1 : (2 << (dvmt_mode - 1)), dvmt_mode);
+
+ if (ci_stolen_size > 0)
+ printk(KERN_INFO"CI Stole memory: RAM base = 0x%08x, size = %lu M \n",
+ dev_priv->ci_region_start,
+ ci_stolen_size / 1024 / 1024);
+ if (rar_stolen_size > 0)
+ printk(KERN_INFO"RAR Stole memory: RAM base = 0x%08x, size = %lu M \n",
+ dev_priv->rar_region_start,
+ rar_stolen_size / 1024 / 1024);
+
+ if (resume && (gtt_pages != pg->gtt_pages) &&
+ (stolen_size != pg->stolen_size)) {
+ DRM_ERROR("GTT resume error.\n");
+ ret = -EINVAL;
+ goto out_err;
+ }
+
+ pg->gtt_pages = gtt_pages;
+ pg->stolen_size = stolen_size;
+ pg->vram_stolen_size = vram_stolen_size;
+ pg->ci_stolen_size = ci_stolen_size;
+ pg->rar_stolen_size = rar_stolen_size;
+ pg->gtt_map =
+ ioremap_nocache(pg->gtt_phys_start, gtt_pages << PAGE_SHIFT);
+ if (!pg->gtt_map) {
+ DRM_ERROR("Failure to map gtt.\n");
+ ret = -ENOMEM;
+ goto out_err;
+ }
+
+ pg->vram_addr = ioremap_wc(pg->stolen_base, stolen_size);
+ if (!pg->vram_addr) {
+ DRM_ERROR("Failure to map stolen base.\n");
+ ret = -ENOMEM;
+ goto out_err;
+ }
+
+ DRM_DEBUG("vram kernel virtual address %p\n", pg->vram_addr);
+
+ tt_pages = (pg->gatt_pages < PSB_TT_PRIV0_PLIMIT) ?
+ (pg->gatt_pages) : PSB_TT_PRIV0_PLIMIT;
+
+ ttm_gtt_map = pg->gtt_map + tt_pages / 2;
+
+ /*
+ * insert vram stolen pages.
+ */
+
+ pfn_base = pg->stolen_base >> PAGE_SHIFT;
+ vram_pages = num_pages = vram_stolen_size >> PAGE_SHIFT;
+ printk(KERN_INFO"Set up %d stolen pages starting at 0x%08x, GTT offset %dK\n",
+ num_pages, pfn_base, 0);
+ for (i = 0; i < num_pages; ++i) {
+ pte = psb_gtt_mask_pte(pfn_base + i, 0);
+ iowrite32(pte, pg->gtt_map + i);
+ }
+
+ /*
+ * Init rest of gtt managed by IMG.
+ */
+ pfn_base = page_to_pfn(dev_priv->scratch_page);
+ pte = psb_gtt_mask_pte(pfn_base, 0);
+ for (; i < tt_pages / 2 - 1; ++i)
+ iowrite32(pte, pg->gtt_map + i);
+
+ /*
+ * insert CI stolen pages
+ */
+
+ pfn_base = dev_priv->ci_region_start >> PAGE_SHIFT;
+ ci_pages = num_pages = ci_stolen_size >> PAGE_SHIFT;
+ printk(KERN_INFO"Set up %d CI stolen pages starting at 0x%08x, GTT offset %dK\n",
+ num_pages, pfn_base, (ttm_gtt_map - pg->gtt_map) * 4);
+ for (i = 0; i < num_pages; ++i) {
+ pte = psb_gtt_mask_pte(pfn_base + i, 0);
+ iowrite32(pte, ttm_gtt_map + i);
+ }
+
+ /*
+ * insert RAR stolen pages
+ */
+ if (rar_stolen_size != 0) {
+ pfn_base = dev_priv->rar_region_start >> PAGE_SHIFT;
+ num_pages = rar_stolen_size >> PAGE_SHIFT;
+ printk(KERN_INFO"Set up %d RAR stolen pages starting at 0x%08x, GTT offset %dK\n",
+ num_pages, pfn_base,
+ (ttm_gtt_map - pg->gtt_map + i) * 4);
+ for (; i < num_pages + ci_pages; ++i) {
+ pte = psb_gtt_mask_pte(pfn_base + i - ci_pages, 0);
+ iowrite32(pte, ttm_gtt_map + i);
+ }
+ }
+ /*
+ * Init rest of gtt managed by TTM.
+ */
+
+ pfn_base = page_to_pfn(dev_priv->scratch_page);
+ pte = psb_gtt_mask_pte(pfn_base, 0);
+ PSB_DEBUG_INIT("Initializing the rest of a total "
+ "of %d gtt pages.\n", pg->gatt_pages);
+
+ for (; i < pg->gatt_pages - tt_pages / 2; ++i)
+ iowrite32(pte, ttm_gtt_map + i);
+ (void) ioread32(pg->gtt_map + i - 1);
+
+ return 0;
+
+out_err:
+ psb_gtt_takedown(pg, 0);
+ return ret;
+}
+
+int psb_gtt_insert_pages(struct psb_gtt *pg, struct page **pages,
+ unsigned offset_pages, unsigned num_pages,
+ unsigned desired_tile_stride,
+ unsigned hw_tile_stride, int type)
+{
+ unsigned rows = 1;
+ unsigned add;
+ unsigned row_add;
+ unsigned i;
+ unsigned j;
+ uint32_t __iomem *cur_page = NULL;
+ uint32_t pte;
+
+ if (hw_tile_stride)
+ rows = num_pages / desired_tile_stride;
+ else
+ desired_tile_stride = num_pages;
+
+ add = desired_tile_stride;
+ row_add = hw_tile_stride;
+
+ down_read(&pg->sem);
+ for (i = 0; i < rows; ++i) {
+ cur_page = pg->gtt_map + offset_pages;
+ for (j = 0; j < desired_tile_stride; ++j) {
+ pte =
+ psb_gtt_mask_pte(page_to_pfn(*pages++), type);
+ iowrite32(pte, cur_page++);
+ }
+ offset_pages += add;
+ }
+ (void) ioread32(cur_page - 1);
+ up_read(&pg->sem);
+
+ return 0;
+}
+
+static int psb_gtt_insert_phys_addresses(struct psb_gtt *pg, IMG_CPU_PHYADDR *pPhysFrames,
+ unsigned offset_pages, unsigned num_pages, int type)
+{
+ unsigned j;
+ uint32_t __iomem *cur_page = NULL;
+ uint32_t pte;
+
+ //printk("Allocatng IMG GTT mem at %x (pages %d)\n",offset_pages,num_pages);
+ down_read(&pg->sem);
+
+ cur_page = pg->gtt_map + offset_pages;
+ for (j = 0; j < num_pages; ++j) {
+ pte = psb_gtt_mask_pte((pPhysFrames++)->uiAddr >> PAGE_SHIFT, type);
+ iowrite32(pte, cur_page++);
+ //printk("PTE %d: %x/%x\n",j,(pPhysFrames-1)->uiAddr,pte);
+ }
+ (void) ioread32(cur_page - 1);
+
+ up_read(&pg->sem);
+
+ return 0;
+}
+
+int psb_gtt_remove_pages(struct psb_gtt *pg, unsigned offset_pages,
+ unsigned num_pages, unsigned desired_tile_stride,
+ unsigned hw_tile_stride, int rc_prot)
+{
+ struct drm_psb_private *dev_priv = pg->dev->dev_private;
+ unsigned rows = 1;
+ unsigned add;
+ unsigned row_add;
+ unsigned i;
+ unsigned j;
+ uint32_t __iomem *cur_page = NULL;
+ unsigned pfn_base = page_to_pfn(dev_priv->scratch_page);
+ uint32_t pte = psb_gtt_mask_pte(pfn_base, 0);
+
+ if (hw_tile_stride)
+ rows = num_pages / desired_tile_stride;
+ else
+ desired_tile_stride = num_pages;
+
+ add = desired_tile_stride;
+ row_add = hw_tile_stride;
+
+ if (rc_prot)
+ down_read(&pg->sem);
+ for (i = 0; i < rows; ++i) {
+ cur_page = pg->gtt_map + offset_pages;
+ for (j = 0; j < desired_tile_stride; ++j)
+ iowrite32(pte, cur_page++);
+
+ offset_pages += add;
+ }
+ (void) ioread32(cur_page - 1);
+ if (rc_prot)
+ up_read(&pg->sem);
+
+ return 0;
+}
+
+int psb_gtt_mm_init(struct psb_gtt *pg)
+{
+ struct psb_gtt_mm *gtt_mm;
+ struct drm_psb_private *dev_priv = pg->dev->dev_private;
+ struct drm_open_hash *ht;
+ struct drm_mm *mm;
+ int ret;
+ uint32_t tt_start;
+ uint32_t tt_size;
+
+ if (!pg || !pg->initialized) {
+ DRM_DEBUG("Invalid gtt struct\n");
+ return -EINVAL;
+ }
+
+ gtt_mm = kzalloc(sizeof(struct psb_gtt_mm), GFP_KERNEL);
+ if (!gtt_mm)
+ return -ENOMEM;
+
+ spin_lock_init(>t_mm->lock);
+
+ ht = >t_mm->hash;
+ ret = drm_ht_create(ht, 20);
+ if (ret) {
+ DRM_DEBUG("Create hash table failed(%d)\n", ret);
+ goto err_free;
+ }
+
+ tt_start = (pg->stolen_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ tt_start = (tt_start < pg->gatt_pages) ? tt_start : pg->gatt_pages;
+ tt_size = (pg->gatt_pages < PSB_TT_PRIV0_PLIMIT) ?
+ (pg->gatt_pages) : PSB_TT_PRIV0_PLIMIT;
+
+ mm = >t_mm->base;
+
+ /*will use tt_start ~ 128M for IMG TT buffers*/
+ ret = drm_mm_init(mm, tt_start, ((tt_size / 2) - tt_start));
+ if (ret) {
+ DRM_DEBUG("drm_mm_int error(%d)\n", ret);
+ goto err_mm_init;
+ }
+
+ gtt_mm->count = 0;
+
+ dev_priv->gtt_mm = gtt_mm;
+
+ DRM_INFO("PSB GTT mem manager ready, tt_start %ld, tt_size %ld pages\n",
+ (unsigned long)tt_start,
+ (unsigned long)((tt_size / 2) - tt_start));
+ return 0;
+err_mm_init:
+ drm_ht_remove(ht);
+
+err_free:
+ kfree(gtt_mm);
+ return ret;
+}
+
+/**
+ * Delete all hash entries;
+ */
+void psb_gtt_mm_takedown(void)
+{
+ return;
+}
+
+static int psb_gtt_mm_get_ht_by_pid_locked(struct psb_gtt_mm *mm,
+ u32 tgid,
+ struct psb_gtt_hash_entry **hentry)
+{
+ struct drm_hash_item *entry;
+ struct psb_gtt_hash_entry *psb_entry;
+ int ret;
+
+ ret = drm_ht_find_item(&mm->hash, tgid, &entry);
+ if (ret) {
+ DRM_DEBUG("Cannot find entry pid=%u\n", tgid);
+ return ret;
+ }
+
+ psb_entry = container_of(entry, struct psb_gtt_hash_entry, item);
+ if (!psb_entry) {
+ DRM_DEBUG("Invalid entry");
+ return -EINVAL;
+ }
+
+ *hentry = psb_entry;
+ return 0;
+}
+
+
+static int psb_gtt_mm_insert_ht_locked(struct psb_gtt_mm *mm,
+ u32 tgid,
+ struct psb_gtt_hash_entry *hentry)
+{
+ struct drm_hash_item *item;
+ int ret;
+
+ if (!hentry) {
+ DRM_DEBUG("Invalid parameters\n");
+ return -EINVAL;
+ }
+
+ item = &hentry->item;
+ item->key = tgid;
+
+ /**
+ * NOTE: drm_ht_insert_item will perform such a check
+ ret = psb_gtt_mm_get_ht_by_pid(mm, tgid, &tmp);
+ if (!ret) {
+ DRM_DEBUG("Entry already exists for pid %ld\n", tgid);
+ return -EAGAIN;
+ }
+ */
+
+ /*Insert the given entry*/
+ ret = drm_ht_insert_item(&mm->hash, item);
+ if (ret) {
+ DRM_DEBUG("Insert failure\n");
+ return ret;
+ }
+
+ mm->count++;
+
+ return 0;
+}
+
+static int psb_gtt_mm_alloc_insert_ht(struct psb_gtt_mm *mm,
+ u32 tgid,
+ struct psb_gtt_hash_entry **entry)
+{
+ struct psb_gtt_hash_entry *hentry;
+ int ret;
+
+ /*if the hentry for this tgid exists, just get it and return*/
+ spin_lock(&mm->lock);
+ ret = psb_gtt_mm_get_ht_by_pid_locked(mm, tgid, &hentry);
+ if (!ret) {
+ DRM_DEBUG("Entry for tgid %u exist, hentry %p\n",
+ tgid, hentry);
+ *entry = hentry;
+ spin_unlock(&mm->lock);
+ return 0;
+ }
+ spin_unlock(&mm->lock);
+
+ DRM_DEBUG("Entry for tgid %u doesn't exist, will create it\n", tgid);
+
+ hentry = kzalloc(sizeof(struct psb_gtt_hash_entry), GFP_KERNEL);
+ if (!hentry) {
+ DRM_DEBUG("Kmalloc failled\n");
+ return -ENOMEM;
+ }
+
+ ret = drm_ht_create(&hentry->ht, 20);
+ if (ret) {
+ DRM_DEBUG("Create hash table failed\n");
+ return ret;
+ }
+
+ spin_lock(&mm->lock);
+ ret = psb_gtt_mm_insert_ht_locked(mm, tgid, hentry);
+ spin_unlock(&mm->lock);
+
+ if (!ret)
+ *entry = hentry;
+
+ return ret;
+}
+
+static struct psb_gtt_hash_entry *
+psb_gtt_mm_remove_ht_locked(struct psb_gtt_mm *mm, u32 tgid) {
+ struct psb_gtt_hash_entry *tmp;
+ int ret;
+
+ ret = psb_gtt_mm_get_ht_by_pid_locked(mm, tgid, &tmp);
+ if (ret) {
+ DRM_DEBUG("Cannot find entry pid %u\n", tgid);
+ return NULL;
+ }
+
+ /*remove it from ht*/
+ drm_ht_remove_item(&mm->hash, &tmp->item);
+
+ mm->count--;
+
+ return tmp;
+}
+
+static int psb_gtt_mm_remove_free_ht_locked(struct psb_gtt_mm *mm, u32 tgid)
+{
+ struct psb_gtt_hash_entry *entry;
+
+ entry = psb_gtt_mm_remove_ht_locked(mm, tgid);
+
+ if (!entry) {
+ DRM_DEBUG("Invalid entry");
+ return -EINVAL;
+ }
+
+ /*delete ht*/
+ drm_ht_remove(&entry->ht);
+
+ /*free this entry*/
+ kfree(entry);
+ return 0;
+}
+
+static int
+psb_gtt_mm_get_mem_mapping_locked(struct drm_open_hash *ht,
+ u32 key,
+ struct psb_gtt_mem_mapping **hentry)
+{
+ struct drm_hash_item *entry;
+ struct psb_gtt_mem_mapping *mapping;
+ int ret;
+
+ ret = drm_ht_find_item(ht, key, &entry);
+ if (ret) {
+ DRM_DEBUG("Cannot find key %u\n", key);
+ return ret;
+ }
+
+ mapping = container_of(entry, struct psb_gtt_mem_mapping, item);
+ if (!mapping) {
+ DRM_DEBUG("Invalid entry\n");
+ return -EINVAL;
+ }
+
+ *hentry = mapping;
+ return 0;
+}
+
+static int
+psb_gtt_mm_insert_mem_mapping_locked(struct drm_open_hash *ht,
+ u32 key,
+ struct psb_gtt_mem_mapping *hentry)
+{
+ struct drm_hash_item *item;
+ struct psb_gtt_hash_entry *entry;
+ int ret;
+
+ if (!hentry) {
+ DRM_DEBUG("hentry is NULL\n");
+ return -EINVAL;
+ }
+
+ item = &hentry->item;
+ item->key = key;
+
+ ret = drm_ht_insert_item(ht, item);
+ if (ret) {
+ DRM_DEBUG("insert_item failed\n");
+ return ret;
+ }
+
+ entry = container_of(ht, struct psb_gtt_hash_entry, ht);
+ if (entry)
+ entry->count++;
+
+ return 0;
+}
+
+static int
+psb_gtt_mm_alloc_insert_mem_mapping(struct psb_gtt_mm *mm,
+ struct drm_open_hash *ht,
+ u32 key,
+ struct drm_mm_node *node,
+ struct psb_gtt_mem_mapping **entry)
+{
+ struct psb_gtt_mem_mapping *mapping;
+ int ret;
+
+ if (!node || !ht) {
+ DRM_DEBUG("parameter error\n");
+ return -EINVAL;
+ }
+
+ /*try to get this mem_map */
+ spin_lock(&mm->lock);
+ ret = psb_gtt_mm_get_mem_mapping_locked(ht, key, &mapping);
+ if (!ret) {
+ DRM_DEBUG("mapping entry for key %u exists, entry %p\n",
+ key, mapping);
+ *entry = mapping;
+ spin_unlock(&mm->lock);
+ return 0;
+ }
+ spin_unlock(&mm->lock);
+
+ DRM_DEBUG("Mapping entry for key %u doesn't exist, will create it\n",
+ key);
+
+ mapping = kzalloc(sizeof(struct psb_gtt_mem_mapping), GFP_KERNEL);
+ if (!mapping) {
+ DRM_DEBUG("kmalloc failed\n");
+ return -ENOMEM;
+ }
+
+ mapping->node = node;
+
+ spin_lock(&mm->lock);
+ ret = psb_gtt_mm_insert_mem_mapping_locked(ht, key, mapping);
+ spin_unlock(&mm->lock);
+
+ if (!ret)
+ *entry = mapping;
+
+ return ret;
+}
+
+static struct psb_gtt_mem_mapping *
+psb_gtt_mm_remove_mem_mapping_locked(struct drm_open_hash *ht, u32 key) {
+ struct psb_gtt_mem_mapping *tmp;
+ struct psb_gtt_hash_entry *entry;
+ int ret;
+
+ ret = psb_gtt_mm_get_mem_mapping_locked(ht, key, &tmp);
+ if (ret) {
+ DRM_DEBUG("Cannot find key %u\n", key);
+ return NULL;
+ }
+
+ drm_ht_remove_item(ht, &tmp->item);
+
+ entry = container_of(ht, struct psb_gtt_hash_entry, ht);
+ if (entry)
+ entry->count--;
+
+ return tmp;
+}
+
+static int psb_gtt_mm_remove_free_mem_mapping_locked(struct drm_open_hash *ht,
+ u32 key,
+ struct drm_mm_node **node)
+{
+ struct psb_gtt_mem_mapping *entry;
+
+ entry = psb_gtt_mm_remove_mem_mapping_locked(ht, key);
+ if (!entry) {
+ DRM_DEBUG("entry is NULL\n");
+ return -EINVAL;
+ }
+
+ *node = entry->node;
+
+ kfree(entry);
+ return 0;
+}
+
+static int psb_gtt_add_node(struct psb_gtt_mm *mm,
+ u32 tgid,
+ u32 key,
+ struct drm_mm_node *node,
+ struct psb_gtt_mem_mapping **entry)
+{
+ struct psb_gtt_hash_entry *hentry;
+ struct psb_gtt_mem_mapping *mapping;
+ int ret;
+
+ ret = psb_gtt_mm_alloc_insert_ht(mm, tgid, &hentry);
+ if (ret) {
+ DRM_DEBUG("alloc_insert failed\n");
+ return ret;
+ }
+
+ ret = psb_gtt_mm_alloc_insert_mem_mapping(mm,
+ &hentry->ht,
+ key,
+ node,
+ &mapping);
+ if (ret) {
+ DRM_DEBUG("mapping alloc_insert failed\n");
+ return ret;
+ }
+
+ *entry = mapping;
+
+ return 0;
+}
+
+static int psb_gtt_remove_node(struct psb_gtt_mm *mm,
+ u32 tgid,
+ u32 key,
+ struct drm_mm_node **node)
+{
+ struct psb_gtt_hash_entry *hentry;
+ struct drm_mm_node *tmp;
+ int ret;
+
+ spin_lock(&mm->lock);
+ ret = psb_gtt_mm_get_ht_by_pid_locked(mm, tgid, &hentry);
+ if (ret) {
+ DRM_DEBUG("Cannot find entry for pid %u\n", tgid);
+ spin_unlock(&mm->lock);
+ return ret;
+ }
+ spin_unlock(&mm->lock);
+
+ /*remove mapping entry*/
+ spin_lock(&mm->lock);
+ ret = psb_gtt_mm_remove_free_mem_mapping_locked(&hentry->ht,
+ key,
+ &tmp);
+ if (ret) {
+ DRM_DEBUG("remove_free failed\n");
+ spin_unlock(&mm->lock);
+ return ret;
+ }
+
+ *node = tmp;
+
+ /*check the count of mapping entry*/
+ if (!hentry->count) {
+ DRM_DEBUG("count of mapping entry is zero, tgid=%u\n", tgid);
+ psb_gtt_mm_remove_free_ht_locked(mm, tgid);
+ }
+
+ spin_unlock(&mm->lock);
+
+ return 0;
+}
+
+static int psb_gtt_mm_alloc_mem(struct psb_gtt_mm *mm,
+ uint32_t pages,
+ uint32_t align,
+ struct drm_mm_node **node)
+{
+ struct drm_mm_node *tmp_node;
+ int ret;
+
+ do {
+ ret = drm_mm_pre_get(&mm->base);
+ if (unlikely(ret)) {
+ DRM_DEBUG("drm_mm_pre_get error\n");
+ return ret;
+ }
+
+ spin_lock(&mm->lock);
+ tmp_node = drm_mm_search_free(&mm->base, pages, align, 1);
+ if (unlikely(!tmp_node)) {
+ DRM_DEBUG("No free node found\n");
+ spin_unlock(&mm->lock);
+ break;
+ }
+
+ tmp_node = drm_mm_get_block_atomic(tmp_node, pages, align);
+ spin_unlock(&mm->lock);
+ } while (!tmp_node);
+
+ if (!tmp_node) {
+ DRM_DEBUG("Node allocation failed\n");
+ return -ENOMEM;
+ }
+
+ *node = tmp_node;
+ return 0;
+}
+
+static void psb_gtt_mm_free_mem(struct psb_gtt_mm *mm, struct drm_mm_node *node)
+{
+ spin_lock(&mm->lock);
+ drm_mm_put_block(node);
+ spin_unlock(&mm->lock);
+}
+
+int psb_gtt_map_meminfo(struct drm_device *dev,
+ IMG_HANDLE hKernelMemInfo,
+ uint32_t *offset)
+{
+ struct drm_psb_private *dev_priv
+ = (struct drm_psb_private *)dev->dev_private;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ struct psb_gtt_mm *mm = dev_priv->gtt_mm;
+ struct psb_gtt *pg = dev_priv->pg;
+ uint32_t size, pages, offset_pages;
+ void *kmem;
+ struct drm_mm_node *node;
+ struct page **page_list;
+ struct psb_gtt_mem_mapping *mapping = NULL;
+ int ret;
+
+ ret = psb_get_meminfo_by_handle(hKernelMemInfo, &psKernelMemInfo);
+ if (ret) {
+ DRM_DEBUG("Cannot find kernelMemInfo handle %p\n",
+ hKernelMemInfo);
+ return -EINVAL;
+ }
+
+ DRM_DEBUG("Got psKernelMemInfo %p for handle %p\n",
+ psKernelMemInfo, hKernelMemInfo);
+
+ size = psKernelMemInfo->ui32AllocSize;
+ kmem = psKernelMemInfo->pvLinAddrKM;
+ pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+ DRM_DEBUG("KerMemInfo size %u, cpuVadr %p, pages %u, osMemHdl %p\n",
+ size, kmem, pages, psKernelMemInfo->sMemBlk.hOSMemHandle);
+
+ if (!kmem)
+ DRM_DEBUG("kmem is NULL");
+
+ /*get pages*/
+ ret = psb_get_pages_by_mem_handle(psKernelMemInfo->sMemBlk.hOSMemHandle,
+ &page_list);
+ if (ret) {
+ DRM_DEBUG("get pages error\n");
+ return ret;
+ }
+
+ DRM_DEBUG("get %u pages\n", pages);
+
+ /*alloc memory in TT apeture*/
+ ret = psb_gtt_mm_alloc_mem(mm, pages, 0, &node);
+ if (ret) {
+ DRM_DEBUG("alloc TT memory error\n");
+ goto failed_pages_alloc;
+ }
+
+ /*update psb_gtt_mm*/
+ ret = psb_gtt_add_node(mm,
+ (u32)psb_get_tgid(),
+ (u32)hKernelMemInfo,
+ node,
+ &mapping);
+ if (ret) {
+ DRM_DEBUG("add_node failed");
+ goto failed_add_node;
+ }
+
+ node = mapping->node;
+ offset_pages = node->start;
+
+ DRM_DEBUG("get free node for %u pages, offset %u pages",
+ pages, offset_pages);
+
+ /*update gtt*/
+ psb_gtt_insert_pages(pg, page_list,
+ (unsigned)offset_pages,
+ (unsigned)pages,
+ 0,
+ 0,
+ 0);
+
+ *offset = offset_pages;
+ return 0;
+
+failed_add_node:
+ psb_gtt_mm_free_mem(mm, node);
+failed_pages_alloc:
+ kfree(page_list);
+ return ret;
+}
+
+int psb_gtt_unmap_meminfo(struct drm_device *dev, IMG_HANDLE hKernelMemInfo)
+{
+ struct drm_psb_private *dev_priv
+ = (struct drm_psb_private *)dev->dev_private;
+ struct psb_gtt_mm *mm = dev_priv->gtt_mm;
+ struct psb_gtt *pg = dev_priv->pg;
+ uint32_t pages, offset_pages;
+ struct drm_mm_node *node;
+ int ret;
+
+ ret = psb_gtt_remove_node(mm,
+ (u32)psb_get_tgid(),
+ (u32)hKernelMemInfo,
+ &node);
+ if (ret) {
+ DRM_DEBUG("remove node failed\n");
+ return ret;
+ }
+
+ /*remove gtt entries*/
+ offset_pages = node->start;
+ pages = node->size;
+
+ psb_gtt_remove_pages(pg, offset_pages, pages, 0, 0, 1);
+
+
+ /*free tt node*/
+
+ psb_gtt_mm_free_mem(mm, node);
+ return 0;
+}
+
+int psb_gtt_map_meminfo_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct psb_gtt_mapping_arg *arg
+ = (struct psb_gtt_mapping_arg *)data;
+ uint32_t *offset_pages = &arg->offset_pages;
+
+ DRM_DEBUG("\n");
+
+ return psb_gtt_map_meminfo(dev, arg->hKernelMemInfo, offset_pages);
+}
+
+int psb_gtt_unmap_meminfo_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+
+ struct psb_gtt_mapping_arg *arg
+ = (struct psb_gtt_mapping_arg *)data;
+
+ DRM_DEBUG("\n");
+
+ return psb_gtt_unmap_meminfo(dev, arg->hKernelMemInfo);
+}
+
+int psb_gtt_map_pvr_memory(struct drm_device *dev,
+ unsigned int hHandle,
+ unsigned int ui32TaskId,
+ IMG_CPU_PHYADDR *pPages,
+ unsigned int ui32PagesNum,
+ unsigned int *ui32Offset)
+{
+ struct drm_psb_private * dev_priv = (struct drm_psb_private *)dev->dev_private;
+ struct psb_gtt_mm * mm = dev_priv->gtt_mm;
+ struct psb_gtt * pg = dev_priv->pg;
+
+ uint32_t size, pages, offset_pages;
+ struct drm_mm_node * node = NULL;
+ struct psb_gtt_mem_mapping * mapping = NULL;
+ int ret;
+
+ size = ui32PagesNum * PAGE_SIZE;
+ pages = 0;
+
+ /*alloc memory in TT apeture*/
+ ret = psb_gtt_mm_alloc_mem(mm, ui32PagesNum, 0, &node);
+ if (ret) {
+ DRM_DEBUG("alloc TT memory error\n");
+ goto failed_pages_alloc;
+ }
+
+ /*update psb_gtt_mm*/
+ ret = psb_gtt_add_node(mm,
+ (u32)ui32TaskId,
+ (u32)hHandle,
+ node,
+ &mapping);
+ if (ret) {
+ DRM_DEBUG("add_node failed");
+ goto failed_add_node;
+ }
+
+ node = mapping->node;
+ offset_pages = node->start;
+
+ DRM_DEBUG("get free node for %u pages, offset %u pages", pages, offset_pages);
+
+ /*update gtt*/
+ psb_gtt_insert_phys_addresses(pg, pPages, (unsigned)offset_pages, (unsigned)ui32PagesNum, 0);
+
+ *ui32Offset = offset_pages;
+ return 0;
+
+failed_add_node:
+ psb_gtt_mm_free_mem(mm, node);
+failed_pages_alloc:
+ return ret;
+}
+
+
+int psb_gtt_unmap_pvr_memory(struct drm_device *dev, unsigned int hHandle, unsigned int ui32TaskId)
+{
+ struct drm_psb_private * dev_priv = (struct drm_psb_private *)dev->dev_private;
+ struct psb_gtt_mm * mm = dev_priv->gtt_mm;
+ struct psb_gtt * pg = dev_priv->pg;
+ uint32_t pages, offset_pages;
+ struct drm_mm_node * node;
+ int ret;
+
+ ret = psb_gtt_remove_node(mm,
+ (u32)ui32TaskId,
+ (u32)hHandle,
+ &node);
+ if (ret) {
+ printk("remove node failed\n");
+ return ret;
+ }
+
+ /*remove gtt entries*/
+ offset_pages = node->start;
+ pages = node->size;
+
+ psb_gtt_remove_pages(pg, offset_pages, pages, 0, 0, 1);
+
+ /*free tt node*/
+ psb_gtt_mm_free_mem(mm, node);
+ return 0;
+}
--- /dev/null
+/**************************************************************************
+ * Copyright (c) 2007-2008, Intel Corporation.
+ * 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 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.
+ *
+ **************************************************************************/
+
+#ifndef _PSB_GTT_H_
+#define _PSB_GTT_H_
+
+#include <drm/drmP.h>
+
+#include "img_types.h"
+
+struct psb_gtt {
+ struct drm_device *dev;
+ int initialized;
+ uint32_t gatt_start;
+ uint32_t mmu_gatt_start;
+ uint32_t ci_start;
+ uint32_t rar_start;
+ uint32_t gtt_start;
+ uint32_t gtt_phys_start;
+ unsigned gtt_pages;
+ unsigned gatt_pages;
+ uint32_t stolen_base;
+ void __iomem *vram_addr;
+ uint32_t pge_ctl;
+ u16 gmch_ctrl;
+ unsigned long stolen_size;
+ unsigned long vram_stolen_size;
+ unsigned long ci_stolen_size;
+ unsigned long rar_stolen_size;
+ uint32_t __iomem *gtt_map;
+ struct rw_semaphore sem;
+};
+
+struct psb_gtt_mm {
+ struct drm_mm base;
+ struct drm_open_hash hash;
+ uint32_t count;
+ spinlock_t lock;
+};
+
+struct psb_gtt_hash_entry {
+ struct drm_open_hash ht;
+ uint32_t count;
+ struct drm_hash_item item;
+};
+
+struct psb_gtt_mem_mapping {
+ struct drm_mm_node *node;
+ struct drm_hash_item item;
+};
+
+#if 0
+/*Ioctl args*/
+struct psb_gtt_mapping_arg {
+ IMG_HANDLE hKernelMemInfo;
+};
+#endif
+
+/*Exported functions*/
+extern int psb_gtt_init(struct psb_gtt *pg, int resume);
+extern int psb_gtt_insert_pages(struct psb_gtt *pg, struct page **pages,
+ unsigned offset_pages, unsigned num_pages,
+ unsigned desired_tile_stride,
+ unsigned hw_tile_stride, int type);
+extern int psb_gtt_remove_pages(struct psb_gtt *pg, unsigned offset_pages,
+ unsigned num_pages,
+ unsigned desired_tile_stride,
+ unsigned hw_tile_stride,
+ int rc_prot);
+
+extern struct psb_gtt *psb_gtt_alloc(struct drm_device *dev);
+extern void psb_gtt_takedown(struct psb_gtt *pg, int free);
+extern int psb_gtt_map_meminfo(struct drm_device *dev,
+ IMG_HANDLE hKernelMemInfo,
+ uint32_t *offset);
+extern int psb_gtt_unmap_meminfo(struct drm_device *dev,
+ IMG_HANDLE hKernelMemInfo);
+extern int psb_gtt_map_meminfo_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int psb_gtt_unmap_meminfo_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int psb_gtt_mm_init(struct psb_gtt *pg);
+extern void psb_gtt_mm_takedown(void);
+
+extern int psb_gtt_map_pvr_memory(struct drm_device *dev,
+ unsigned int hHandle,
+ unsigned int ui32TaskId,
+ IMG_CPU_PHYADDR *pPages,
+ unsigned int ui32PagesNum,
+ unsigned int *ui32Offset);
+
+extern int psb_gtt_unmap_pvr_memory(struct drm_device *dev,
+ unsigned int hHandle,
+ unsigned int ui32TaskId);
+
+#endif
--- /dev/null
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * 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 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.
+ *
+ * Authors:
+ * James C. Gualario <james.c.gualario@intel.com>
+ *
+ */
+
+#include "psb_umevents.h"
+#include "psb_hotplug.h"
+/**
+ * inform the kernel of the work to be performed and related function.
+ *
+ */
+static DECLARE_WORK(hotplug_dev_create_work, &psb_hotplug_dev_create_wq);
+static DECLARE_WORK(hotplug_dev_remove_work, &psb_hotplug_dev_remove_wq);
+static DECLARE_WORK(hotplug_dev_change_work, &psb_hotplug_dev_change_wq);
+/**
+ * psb_hotplug_notify_change_um - notify user mode of hotplug changes
+ *
+ * @name: name of event to notify user mode of change to
+ * @state: hotplug state to search for event object in
+ *
+ */
+int psb_hotplug_notify_change_um(const char *name,
+ struct hotplug_state *state)
+{
+ strcpy(&(state->hotplug_change_wq_data.dev_name_arry
+ [state->hotplug_change_wq_data.dev_name_write][0]), name);
+ state->hotplug_change_wq_data.dev_name_arry_rw_status
+ [state->hotplug_change_wq_data.dev_name_write] =
+ DRM_HOTPLUG_READY_TO_READ;
+ if (state->hotplug_change_wq_data.dev_name_read_write_wrap_ack == 1)
+ state->hotplug_change_wq_data.dev_name_read_write_wrap_ack = 0;
+ state->hotplug_change_wq_data.dev_name_write++;
+ if (state->hotplug_change_wq_data.dev_name_write ==
+ state->hotplug_change_wq_data.dev_name_read) {
+ state->hotplug_change_wq_data.dev_name_write--;
+ return IRQ_NONE;
+ }
+ if (state->hotplug_change_wq_data.dev_name_write >
+ DRM_HOTPLUG_RING_DEPTH_MAX) {
+ state->hotplug_change_wq_data.dev_name_write = 0;
+ state->hotplug_change_wq_data.dev_name_write_wrap = 1;
+ }
+ state->hotplug_change_wq_data.hotplug_dev_list = state->list;
+ queue_work(state->hotplug_wq, &(state->hotplug_change_wq_data.work));
+ return IRQ_HANDLED;
+}
+/**
+ *
+ * psb_hotplug_create_and_notify_um - create and notify user mode of new dev
+ *
+ * @name: name to give for new event / device
+ * @state: hotplug state to track new event /device in
+ *
+ */
+int psb_hotplug_create_and_notify_um(const char *name,
+ struct hotplug_state *state)
+{
+ strcpy(&(state->hotplug_create_wq_data.dev_name_arry
+ [state->hotplug_create_wq_data.dev_name_write][0]), name);
+ state->hotplug_create_wq_data.dev_name_arry_rw_status
+ [state->hotplug_create_wq_data.dev_name_write] =
+ DRM_HOTPLUG_READY_TO_READ;
+ if (state->hotplug_create_wq_data.dev_name_read_write_wrap_ack == 1)
+ state->hotplug_create_wq_data.dev_name_read_write_wrap_ack = 0;
+ state->hotplug_create_wq_data.dev_name_write++;
+ if (state->hotplug_create_wq_data.dev_name_write ==
+ state->hotplug_create_wq_data.dev_name_read) {
+ state->hotplug_create_wq_data.dev_name_write--;
+ return IRQ_NONE;
+ }
+ if (state->hotplug_create_wq_data.dev_name_write >
+ DRM_HOTPLUG_RING_DEPTH_MAX) {
+ state->hotplug_create_wq_data.dev_name_write = 0;
+ state->hotplug_create_wq_data.dev_name_write_wrap = 1;
+ }
+ state->hotplug_create_wq_data.hotplug_dev_list = state->list;
+ queue_work(state->hotplug_wq, &(state->hotplug_create_wq_data.work));
+ return IRQ_HANDLED;
+}
+/*EXPORT_SYMBOL(psb_hotplug_create_and_notify_um); */
+/**
+ * psb_hotplug_remove_and_notify_um - remove device and notify user mode
+ *
+ * @name: name of event / device to remove
+ * @state: hotplug state to remove event / device from
+ *
+ */
+int psb_hotplug_remove_and_notify_um(const char *name,
+ struct hotplug_state *state)
+{
+ strcpy(&(state->hotplug_remove_wq_data.dev_name_arry
+ [state->hotplug_remove_wq_data.dev_name_write][0]), name);
+ state->hotplug_remove_wq_data.dev_name_arry_rw_status
+ [state->hotplug_remove_wq_data.dev_name_write] =
+ DRM_HOTPLUG_READY_TO_READ;
+ if (state->hotplug_remove_wq_data.dev_name_read_write_wrap_ack == 1)
+ state->hotplug_remove_wq_data.dev_name_read_write_wrap_ack = 0;
+ state->hotplug_remove_wq_data.dev_name_write++;
+ if (state->hotplug_remove_wq_data.dev_name_write ==
+ state->hotplug_remove_wq_data.dev_name_read) {
+ state->hotplug_remove_wq_data.dev_name_write--;
+ return IRQ_NONE;
+ }
+ if (state->hotplug_remove_wq_data.dev_name_write >
+ DRM_HOTPLUG_RING_DEPTH_MAX) {
+ state->hotplug_remove_wq_data.dev_name_write = 0;
+ state->hotplug_remove_wq_data.dev_name_write_wrap = 1;
+ }
+ state->hotplug_remove_wq_data.hotplug_dev_list = state->list;
+ queue_work(state->hotplug_wq, &(state->hotplug_remove_wq_data.work));
+ return IRQ_HANDLED;
+}
+/*EXPORT_SYMBOL(psb_hotplug_remove_and_notify_um); */
+/**
+ * psb_hotplug_device_pool_create_and_init - make new hotplug device pool
+ *
+ * @parent_kobj: parent kobject to associate hotplug kset with
+ * @state: hotplug state to assocaite workqueues with
+ *
+ */
+struct umevent_list *psb_hotplug_device_pool_create_and_init(
+ struct kobject *parent_kobj,
+ struct hotplug_state *state)
+{
+ struct umevent_list *new_hotplug_dev_list = NULL;
+
+ new_hotplug_dev_list = psb_umevent_create_list();
+ if (new_hotplug_dev_list)
+ psb_umevent_init(parent_kobj, new_hotplug_dev_list,
+ "psb_hotplug");
+
+ state->hotplug_wq = create_singlethread_workqueue("hotplug-wq");
+ if (!state->hotplug_wq)
+ return NULL;
+
+ INIT_WORK(&state->hotplug_create_wq_data.work,
+ psb_hotplug_dev_create_wq);
+ INIT_WORK(&state->hotplug_remove_wq_data.work,
+ psb_hotplug_dev_remove_wq);
+ INIT_WORK(&state->hotplug_change_wq_data.work,
+ psb_hotplug_dev_change_wq);
+
+ state->hotplug_create_wq_data.dev_name_read = 0;
+ state->hotplug_create_wq_data.dev_name_write = 0;
+ state->hotplug_create_wq_data.dev_name_write_wrap = 0;
+ state->hotplug_create_wq_data.dev_name_read_write_wrap_ack = 0;
+ memset(&(state->hotplug_create_wq_data.dev_name_arry_rw_status[0]),
+ 0, sizeof(int)*DRM_HOTPLUG_RING_DEPTH);
+
+ state->hotplug_remove_wq_data.dev_name_read = 0;
+ state->hotplug_remove_wq_data.dev_name_write = 0;
+ state->hotplug_remove_wq_data.dev_name_write_wrap = 0;
+ state->hotplug_remove_wq_data.dev_name_read_write_wrap_ack = 0;
+ memset(&(state->hotplug_remove_wq_data.dev_name_arry_rw_status[0]),
+ 0, sizeof(int)*DRM_HOTPLUG_RING_DEPTH);
+
+ state->hotplug_change_wq_data.dev_name_read = 0;
+ state->hotplug_change_wq_data.dev_name_write = 0;
+ state->hotplug_change_wq_data.dev_name_write_wrap = 0;
+ state->hotplug_change_wq_data.dev_name_read_write_wrap_ack = 0;
+ memset(&(state->hotplug_change_wq_data.dev_name_arry_rw_status[0]),
+ 0, sizeof(int)*DRM_HOTPLUG_RING_DEPTH);
+
+ return new_hotplug_dev_list;
+}
+/*EXPORT_SYMBOL(psb_hotplug_device_pool_create_and_init); */
+/**
+ *
+ * psb_hotplug_init - init hotplug subsystem
+ *
+ * @parent_kobj: parent kobject to associate hotplug state with
+ *
+ */
+struct hotplug_state *psb_hotplug_init(struct kobject *parent_kobj)
+{
+ struct hotplug_state *state;
+ state = kzalloc(sizeof(struct hotplug_state), GFP_KERNEL);
+
+ if (!state)
+ return state;
+
+ state->list = NULL;
+ state->list = psb_hotplug_device_pool_create_and_init(
+ parent_kobj,
+ state);
+
+ psb_hotplug_create_and_notify_um("hpd_hdmi", state);
+
+ return state;
+}
+/**
+ * psb_hotplug_device_pool_destroy - destroy all hotplug related resources
+ *
+ * @state: hotplug state to destroy
+ *
+ */
+void psb_hotplug_device_pool_destroy(struct hotplug_state *state)
+{
+ flush_workqueue(state->hotplug_wq);
+ destroy_workqueue(state->hotplug_wq);
+ psb_umevent_cleanup(state->list);
+ kfree(state);
+}
+/*EXPORT_SYMBOL(psb_hotplug_device_pool_destroy); */
+/**
+ * psb_hotplug_dev_create_wq - create workqueue implementation
+ *
+ * @work: work struct to use for kernel scheduling
+ *
+ */
+void psb_hotplug_dev_create_wq(struct work_struct *work)
+{
+ struct hotplug_disp_workqueue_data *wq_data;
+ struct umevent_obj *wq_working_hotplug_disp_obj;
+ wq_data = to_hotplug_disp_workqueue_data(work);
+ if (wq_data->dev_name_write_wrap == 1) {
+ wq_data->dev_name_read_write_wrap_ack = 1;
+ wq_data->dev_name_write_wrap = 0;
+ while (wq_data->dev_name_read != DRM_HOTPLUG_RING_DEPTH_MAX) {
+ if (wq_data->dev_name_arry_rw_status
+ [wq_data->dev_name_read] ==
+ DRM_HOTPLUG_READY_TO_READ) {
+ wq_working_hotplug_disp_obj =
+ psb_create_umevent_obj(
+ &wq_data->dev_name_arry
+ [wq_data->dev_name_read][0],
+ wq_data->hotplug_dev_list);
+ wq_data->dev_name_arry_rw_status
+ [wq_data->dev_name_read] =
+ DRM_HOTPLUG_READ_COMPLETE;
+ /* psb_umevent_notify
+ (wq_working_hotplug_disp_obj);*/
+ }
+ wq_data->dev_name_read++;
+ }
+ wq_data->dev_name_read = 0;
+ while (wq_data->dev_name_read < wq_data->dev_name_write-1) {
+ if (wq_data->dev_name_arry_rw_status
+ [wq_data->dev_name_read] ==
+ DRM_HOTPLUG_READY_TO_READ) {
+ wq_working_hotplug_disp_obj =
+ psb_create_umevent_obj(
+ &wq_data->dev_name_arry
+ [wq_data->dev_name_read][0],
+ wq_data->hotplug_dev_list);
+ wq_data->dev_name_arry_rw_status
+ [wq_data->dev_name_read] =
+ DRM_HOTPLUG_READ_COMPLETE;
+ /*psb_umevent_notify
+ (wq_working_hotplug_disp_obj);*/
+ }
+ wq_data->dev_name_read++;
+ }
+ } else {
+ while (wq_data->dev_name_read < wq_data->dev_name_write) {
+ if (wq_data->dev_name_arry_rw_status
+ [wq_data->dev_name_read] ==
+ DRM_HOTPLUG_READY_TO_READ) {
+ wq_working_hotplug_disp_obj =
+ psb_create_umevent_obj(
+ &wq_data->dev_name_arry
+ [wq_data->dev_name_read][0],
+ wq_data->hotplug_dev_list);
+ wq_data->dev_name_arry_rw_status
+ [wq_data->dev_name_read] =
+ DRM_HOTPLUG_READ_COMPLETE;
+ /*psb_umevent_notify
+ (wq_working_hotplug_disp_obj);*/
+ }
+ wq_data->dev_name_read++;
+ }
+ }
+ if (wq_data->dev_name_read > DRM_HOTPLUG_RING_DEPTH_MAX)
+ wq_data->dev_name_read = 0;
+}
+/*EXPORT_SYMBOL(psb_hotplug_dev_create_wq); */
+/**
+ * psb_hotplug_dev_remove_wq - remove workqueue implementation
+ *
+ * @work: work struct to use for kernel scheduling
+ *
+ */
+void psb_hotplug_dev_remove_wq(struct work_struct *work)
+{
+ struct hotplug_disp_workqueue_data *wq_data;
+ wq_data = to_hotplug_disp_workqueue_data(work);
+ if (wq_data->dev_name_write_wrap == 1) {
+ wq_data->dev_name_read_write_wrap_ack = 1;
+ wq_data->dev_name_write_wrap = 0;
+ while (wq_data->dev_name_read != DRM_HOTPLUG_RING_DEPTH_MAX) {
+ if (wq_data->dev_name_arry_rw_status
+ [wq_data->dev_name_read] ==
+ DRM_HOTPLUG_READY_TO_READ) {
+ psb_umevent_remove_from_list(
+ wq_data->hotplug_dev_list,
+ &wq_data->dev_name_arry
+ [wq_data->dev_name_read][0]);
+ wq_data->dev_name_arry_rw_status
+ [wq_data->dev_name_read] =
+ DRM_HOTPLUG_READ_COMPLETE;
+ }
+ wq_data->dev_name_read++;
+ }
+ wq_data->dev_name_read = 0;
+ while (wq_data->dev_name_read < wq_data->dev_name_write-1) {
+ if (wq_data->dev_name_arry_rw_status
+ [wq_data->dev_name_read] ==
+ DRM_HOTPLUG_READY_TO_READ) {
+ psb_umevent_remove_from_list(
+ wq_data->hotplug_dev_list,
+ &wq_data->dev_name_arry
+ [wq_data->dev_name_read][0]);
+ wq_data->dev_name_arry_rw_status
+ [wq_data->dev_name_read] =
+ DRM_HOTPLUG_READ_COMPLETE;
+ }
+ wq_data->dev_name_read++;
+ }
+ } else {
+ while (wq_data->dev_name_read < wq_data->dev_name_write) {
+ if (wq_data->dev_name_arry_rw_status
+ [wq_data->dev_name_read] ==
+ DRM_HOTPLUG_READY_TO_READ) {
+ psb_umevent_remove_from_list(
+ wq_data->hotplug_dev_list,
+ &wq_data->dev_name_arry
+ [wq_data->dev_name_read][0]);
+ wq_data->dev_name_arry_rw_status
+ [wq_data->dev_name_read] =
+ DRM_HOTPLUG_READ_COMPLETE;
+ }
+ wq_data->dev_name_read++;
+ }
+ }
+ if (wq_data->dev_name_read > DRM_HOTPLUG_RING_DEPTH_MAX)
+ wq_data->dev_name_read = 0;
+}
+/*EXPORT_SYMBOL(psb_hotplug_dev_remove_wq); */
+/**
+ * psb_hotplug_dev_change_wq - change workqueue implementation
+ *
+ * @work: work struct to use for kernel scheduling
+ *
+ */
+void psb_hotplug_dev_change_wq(struct work_struct *work)
+{
+ struct hotplug_disp_workqueue_data *wq_data;
+ struct umevent_obj *wq_working_hotplug_disp_obj;
+ wq_data = to_hotplug_disp_workqueue_data(work);
+ if (wq_data->dev_name_write_wrap == 1) {
+ wq_data->dev_name_read_write_wrap_ack = 1;
+ wq_data->dev_name_write_wrap = 0;
+ while (wq_data->dev_name_read != DRM_HOTPLUG_RING_DEPTH_MAX) {
+ if (wq_data->dev_name_arry_rw_status
+ [wq_data->dev_name_read] ==
+ DRM_HOTPLUG_READY_TO_READ) {
+ wq_data->dev_name_arry_rw_status
+ [wq_data->dev_name_read] =
+ DRM_HOTPLUG_READ_COMPLETE;
+
+ wq_working_hotplug_disp_obj =
+ psb_umevent_find_obj(
+ &wq_data->dev_name_arry
+ [wq_data->dev_name_read][0],
+ wq_data->hotplug_dev_list);
+ psb_umevent_notify_change_gfxsock
+ (wq_working_hotplug_disp_obj,
+ DRM_HOTPLUG_SOCKET_GROUP_ID);
+ }
+ wq_data->dev_name_read++;
+ }
+ wq_data->dev_name_read = 0;
+ while (wq_data->dev_name_read < wq_data->dev_name_write-1) {
+ if (wq_data->dev_name_arry_rw_status
+ [wq_data->dev_name_read] ==
+ DRM_HOTPLUG_READY_TO_READ) {
+ wq_data->dev_name_arry_rw_status
+ [wq_data->dev_name_read] =
+ DRM_HOTPLUG_READ_COMPLETE;
+
+ wq_working_hotplug_disp_obj =
+ psb_umevent_find_obj(
+ &wq_data->dev_name_arry
+ [wq_data->dev_name_read][0],
+ wq_data->hotplug_dev_list);
+ psb_umevent_notify_change_gfxsock
+ (wq_working_hotplug_disp_obj,
+ DRM_HOTPLUG_SOCKET_GROUP_ID);
+ }
+ wq_data->dev_name_read++;
+ }
+ } else {
+ while (wq_data->dev_name_read < wq_data->dev_name_write) {
+ if (wq_data->dev_name_arry_rw_status
+ [wq_data->dev_name_read] ==
+ DRM_HOTPLUG_READY_TO_READ) {
+ wq_data->dev_name_arry_rw_status
+ [wq_data->dev_name_read] =
+ DRM_HOTPLUG_READ_COMPLETE;
+
+ wq_working_hotplug_disp_obj =
+ psb_umevent_find_obj(
+ &wq_data->dev_name_arry
+ [wq_data->dev_name_read][0],
+ wq_data->hotplug_dev_list);
+ psb_umevent_notify_change_gfxsock
+ (wq_working_hotplug_disp_obj,
+ DRM_HOTPLUG_SOCKET_GROUP_ID);
+ }
+ wq_data->dev_name_read++;
+ }
+ }
+ if (wq_data->dev_name_read > DRM_HOTPLUG_RING_DEPTH_MAX)
+ wq_data->dev_name_read = 0;
+}
+/*EXPORT_SYMBOL(psb_hotplug_dev_change_wq); */
--- /dev/null
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * 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 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.
+ *
+ * Authors:
+ * James C. Gualario <james.c.gualario@intel.com>
+ *
+ */
+#ifndef _PSB_HOTPLUG_H_
+#define _PSB_HOTPLUG_H_
+/**
+ * required includes
+ *
+ */
+#include "psb_umevents.h"
+/**
+ * hotplug specific defines
+ *
+ */
+#define DRM_HOTPLUG_RING_DEPTH 256
+#define DRM_HOTPLUG_RING_DEPTH_MAX (DRM_HOTPLUG_RING_DEPTH-1)
+#define DRM_HOTPLUG_READY_TO_READ 1
+#define DRM_HOTPLUG_READ_COMPLETE 2
+/**
+ * hotplug workqueue data struct.
+ */
+struct hotplug_disp_workqueue_data {
+ struct work_struct work;
+ const char *dev_name;
+ int dev_name_write;
+ int dev_name_read;
+ int dev_name_write_wrap;
+ int dev_name_read_write_wrap_ack;
+ char dev_name_arry[DRM_HOTPLUG_RING_DEPTH][24];
+ int dev_name_arry_rw_status[DRM_HOTPLUG_RING_DEPTH];
+ struct umevent_list *hotplug_dev_list;
+};
+/**
+ * hotplug state structure
+ *
+ */
+struct hotplug_state {
+ struct workqueue_struct *hotplug_wq;
+ struct hotplug_disp_workqueue_data hotplug_remove_wq_data;
+ struct hotplug_disp_workqueue_data hotplug_create_wq_data;
+ struct hotplug_disp_workqueue_data hotplug_change_wq_data;
+ struct umevent_list *list;
+};
+/**
+ * main interface function prototytpes for hotplug support.
+ *
+ */
+struct hotplug_state *psb_hotplug_init(struct kobject *parent_kobj);
+extern int psb_hotplug_notify_change_um(const char *name,
+ struct hotplug_state *state);
+extern int psb_hotplug_create_and_notify_um(const char *name,
+ struct hotplug_state *state);
+extern int psb_hotplug_remove_and_notify_um(const char *name,
+ struct hotplug_state *state);
+extern struct umevent_list *psb_hotplug_device_pool_create_and_init(
+ struct kobject *parent_kobj,
+ struct hotplug_state *state);
+extern void psb_hotplug_device_pool_destroy(struct hotplug_state *state);
+/**
+ * to go back and forth between work strauct and workqueue data
+ *
+ */
+#define to_hotplug_disp_workqueue_data(x) \
+ container_of(x, struct hotplug_disp_workqueue_data, work)
+
+/**
+ * function prototypes for workqueue implementation
+ *
+ */
+extern void psb_hotplug_dev_create_wq(struct work_struct *work);
+extern void psb_hotplug_dev_remove_wq(struct work_struct *work);
+extern void psb_hotplug_dev_change_wq(struct work_struct *work);
+#endif
--- /dev/null
+/*
+ * Copyright © 2006-2007 Intel Corporation
+ *
+ * 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 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.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ */
+
+#include <linux/i2c.h>
+#include <linux/pm_runtime.h>
+
+#include <drm/drmP.h>
+#include "psb_fb.h"
+#include "psb_drv.h"
+#include "psb_intel_drv.h"
+#include "psb_intel_reg.h"
+#include "psb_intel_display.h"
+#include "psb_page_flip.h"
+#include "psb_powermgmt.h"
+#include "mdfld_output.h"
+
+static int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
+ struct drm_framebuffer *old_fb);
+static int mdfld_crtc_mode_set(struct drm_crtc *crtc,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode,
+ int x, int y,
+ struct drm_framebuffer *old_fb);
+static void mdfld_crtc_dpms(struct drm_crtc *crtc, int mode);
+
+struct psb_intel_clock_t {
+ /* given values */
+ int n;
+ int m1, m2;
+ int p1, p2;
+ /* derived values */
+ int dot;
+ int vco;
+ int m;
+ int p;
+};
+
+struct psb_intel_range_t {
+ int min, max;
+};
+
+/**
+ * Returns whether any output on the specified pipe is of the specified type
+ */
+bool psb_intel_pipe_has_type(struct drm_crtc *crtc, int type)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_mode_config *mode_config = &dev->mode_config;
+ struct drm_connector *l_entry;
+
+ list_for_each_entry(l_entry, &mode_config->connector_list, head) {
+ if (l_entry->encoder && l_entry->encoder->crtc == crtc) {
+ struct psb_intel_output *psb_intel_output =
+ to_psb_intel_output(l_entry);
+ if (psb_intel_output->type == type)
+ return true;
+ }
+ }
+ return false;
+}
+
+void psb_intel_wait_for_vblank(struct drm_device *dev)
+{
+ /* Wait for 20ms, i.e. one cycle at 50hz. */
+ mdelay(20);
+}
+
+static void psb_intel_crtc_prepare(struct drm_crtc *crtc)
+{
+ struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+ crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
+}
+
+static void psb_intel_crtc_commit(struct drm_crtc *crtc)
+{
+ struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+ crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
+}
+
+void psb_intel_encoder_prepare(struct drm_encoder *encoder)
+{
+ struct drm_encoder_helper_funcs *encoder_funcs =
+ encoder->helper_private;
+ /* lvds has its own version of prepare see psb_intel_lvds_prepare */
+ encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
+}
+
+void psb_intel_encoder_commit(struct drm_encoder *encoder)
+{
+ struct drm_encoder_helper_funcs *encoder_funcs =
+ encoder->helper_private;
+ /* lvds has its own version of commit see psb_intel_lvds_commit */
+ encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
+}
+
+static bool psb_intel_crtc_mode_fixup(struct drm_crtc *crtc,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ return true;
+}
+
+
+/**
+ * Return the pipe currently connected to the panel fitter,
+ * or -1 if the panel fitter is not present or not in use
+ */
+static int psb_intel_panel_fitter_pipe(struct drm_device *dev)
+{
+ u32 pfit_control;
+
+ /* i830 doesn't have a panel fitter */
+ if (IS_I830(dev))
+ return -1;
+
+ pfit_control = REG_READ(PFIT_CONTROL);
+
+ /* See if the panel fitter is in use */
+ if ((pfit_control & PFIT_ENABLE) == 0)
+ return -1;
+
+ /* 965 can place panel fitter on either pipe */
+ return (pfit_control >> 29) & 0x3;
+}
+
+/** Loads the palette/gamma unit for the CRTC with the prepared values */
+void psb_intel_crtc_load_lut(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *)dev->dev_private;
+ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+ int palreg = PALETTE_A;
+ int i;
+
+ /* The clocks have to be on to load the palette. */
+ if (!crtc->enabled)
+ return;
+
+ switch (psb_intel_crtc->pipe) {
+ case 0:
+ break;
+ case 1:
+ palreg = PALETTE_B;
+ break;
+ case 2:
+ palreg = PALETTE_C;
+ break;
+ default:
+ DRM_ERROR("Illegal Pipe Number. \n");
+ return;
+ }
+
+ if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
+ OSPM_UHB_ONLY_IF_ON)) {
+ for (i = 0; i < 256; i++) {
+ REG_WRITE(palreg + 4 * i,
+ ((psb_intel_crtc->lut_r[i] +
+ psb_intel_crtc->lut_adj[i]) << 16) |
+ ((psb_intel_crtc->lut_g[i] +
+ psb_intel_crtc->lut_adj[i]) << 8) |
+ (psb_intel_crtc->lut_b[i] +
+ psb_intel_crtc->lut_adj[i]));
+ }
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+ } else {
+ for (i = 0; i < 256; i++) {
+ dev_priv->save_palette_a[i] =
+ ((psb_intel_crtc->lut_r[i] +
+ psb_intel_crtc->lut_adj[i]) << 16) |
+ ((psb_intel_crtc->lut_g[i] +
+ psb_intel_crtc->lut_adj[i]) << 8) |
+ (psb_intel_crtc->lut_b[i] +
+ psb_intel_crtc->lut_adj[i]);
+ }
+
+ }
+}
+
+/**
+ * Save HW states of giving crtc
+ */
+static void psb_intel_crtc_save(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ /* struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *)dev->dev_private; */
+ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+ struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state;
+ int pipeA = (psb_intel_crtc->pipe == 0);
+ uint32_t paletteReg;
+ int i;
+
+ DRM_DEBUG("\n");
+
+ if (!crtc_state) {
+ DRM_DEBUG("No CRTC state found\n");
+ return;
+ }
+
+ crtc_state->saveDSPCNTR = REG_READ(pipeA ? DSPACNTR : DSPBCNTR);
+ crtc_state->savePIPECONF = REG_READ(pipeA ? PIPEACONF : PIPEBCONF);
+ crtc_state->savePIPESRC = REG_READ(pipeA ? PIPEASRC : PIPEBSRC);
+ crtc_state->saveFP0 = REG_READ(pipeA ? FPA0 : FPB0);
+ crtc_state->saveFP1 = REG_READ(pipeA ? FPA1 : FPB1);
+ crtc_state->saveDPLL = REG_READ(pipeA ? DPLL_A : DPLL_B);
+ crtc_state->saveHTOTAL = REG_READ(pipeA ? HTOTAL_A : HTOTAL_B);
+ crtc_state->saveHBLANK = REG_READ(pipeA ? HBLANK_A : HBLANK_B);
+ crtc_state->saveHSYNC = REG_READ(pipeA ? HSYNC_A : HSYNC_B);
+ crtc_state->saveVTOTAL = REG_READ(pipeA ? VTOTAL_A : VTOTAL_B);
+ crtc_state->saveVBLANK = REG_READ(pipeA ? VBLANK_A : VBLANK_B);
+ crtc_state->saveVSYNC = REG_READ(pipeA ? VSYNC_A : VSYNC_B);
+ crtc_state->saveDSPSTRIDE = REG_READ(pipeA ? DSPASTRIDE : DSPBSTRIDE);
+
+ /*NOTE: DSPSIZE DSPPOS only for psb*/
+ crtc_state->saveDSPSIZE = REG_READ(pipeA ? DSPASIZE : DSPBSIZE);
+ crtc_state->saveDSPPOS = REG_READ(pipeA ? DSPAPOS : DSPBPOS);
+
+ crtc_state->saveDSPBASE = REG_READ(pipeA ? DSPABASE : DSPBBASE);
+
+ DRM_DEBUG("(%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
+ crtc_state->saveDSPCNTR,
+ crtc_state->savePIPECONF,
+ crtc_state->savePIPESRC,
+ crtc_state->saveFP0,
+ crtc_state->saveFP1,
+ crtc_state->saveDPLL,
+ crtc_state->saveHTOTAL,
+ crtc_state->saveHBLANK,
+ crtc_state->saveHSYNC,
+ crtc_state->saveVTOTAL,
+ crtc_state->saveVBLANK,
+ crtc_state->saveVSYNC,
+ crtc_state->saveDSPSTRIDE,
+ crtc_state->saveDSPSIZE,
+ crtc_state->saveDSPPOS,
+ crtc_state->saveDSPBASE
+ );
+
+ paletteReg = pipeA ? PALETTE_A : PALETTE_B;
+ for (i = 0; i < 256; ++i)
+ crtc_state->savePalette[i] = REG_READ(paletteReg + (i << 2));
+}
+
+/**
+ * Restore HW states of giving crtc
+ */
+static void psb_intel_crtc_restore(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ /* struct drm_psb_private * dev_priv =
+ (struct drm_psb_private *)dev->dev_private; */
+ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+ struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state;
+ /* struct drm_crtc_helper_funcs * crtc_funcs = crtc->helper_private; */
+ int pipeA = (psb_intel_crtc->pipe == 0);
+ uint32_t paletteReg;
+ int i;
+
+ DRM_DEBUG("\n");
+
+ if (!crtc_state) {
+ DRM_DEBUG("No crtc state\n");
+ return;
+ }
+
+ DRM_DEBUG(
+ "current:(%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
+ REG_READ(pipeA ? DSPACNTR : DSPBCNTR),
+ REG_READ(pipeA ? PIPEACONF : PIPEBCONF),
+ REG_READ(pipeA ? PIPEASRC : PIPEBSRC),
+ REG_READ(pipeA ? FPA0 : FPB0),
+ REG_READ(pipeA ? FPA1 : FPB1),
+ REG_READ(pipeA ? DPLL_A : DPLL_B),
+ REG_READ(pipeA ? HTOTAL_A : HTOTAL_B),
+ REG_READ(pipeA ? HBLANK_A : HBLANK_B),
+ REG_READ(pipeA ? HSYNC_A : HSYNC_B),
+ REG_READ(pipeA ? VTOTAL_A : VTOTAL_B),
+ REG_READ(pipeA ? VBLANK_A : VBLANK_B),
+ REG_READ(pipeA ? VSYNC_A : VSYNC_B),
+ REG_READ(pipeA ? DSPASTRIDE : DSPBSTRIDE),
+ REG_READ(pipeA ? DSPASIZE : DSPBSIZE),
+ REG_READ(pipeA ? DSPAPOS : DSPBPOS),
+ REG_READ(pipeA ? DSPABASE : DSPBBASE)
+ );
+
+ DRM_DEBUG(
+ "saved: (%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
+ crtc_state->saveDSPCNTR,
+ crtc_state->savePIPECONF,
+ crtc_state->savePIPESRC,
+ crtc_state->saveFP0,
+ crtc_state->saveFP1,
+ crtc_state->saveDPLL,
+ crtc_state->saveHTOTAL,
+ crtc_state->saveHBLANK,
+ crtc_state->saveHSYNC,
+ crtc_state->saveVTOTAL,
+ crtc_state->saveVBLANK,
+ crtc_state->saveVSYNC,
+ crtc_state->saveDSPSTRIDE,
+ crtc_state->saveDSPSIZE,
+ crtc_state->saveDSPPOS,
+ crtc_state->saveDSPBASE
+ );
+
+ if (crtc_state->saveDPLL & DPLL_VCO_ENABLE) {
+ REG_WRITE(pipeA ? DPLL_A : DPLL_B,
+ crtc_state->saveDPLL & ~DPLL_VCO_ENABLE);
+ REG_READ(pipeA ? DPLL_A : DPLL_B);
+ DRM_DEBUG("write dpll: %x\n",
+ REG_READ(pipeA ? DPLL_A : DPLL_B));
+ udelay(150);
+ }
+
+ REG_WRITE(pipeA ? FPA0 : FPB0, crtc_state->saveFP0);
+ REG_READ(pipeA ? FPA0 : FPB0);
+
+ REG_WRITE(pipeA ? FPA1 : FPB1, crtc_state->saveFP1);
+ REG_READ(pipeA ? FPA1 : FPB1);
+
+ REG_WRITE(pipeA ? DPLL_A : DPLL_B, crtc_state->saveDPLL);
+ REG_READ(pipeA ? DPLL_A : DPLL_B);
+ udelay(150);
+
+ REG_WRITE(pipeA ? HTOTAL_A : HTOTAL_B, crtc_state->saveHTOTAL);
+ REG_WRITE(pipeA ? HBLANK_A : HBLANK_B, crtc_state->saveHBLANK);
+ REG_WRITE(pipeA ? HSYNC_A : HSYNC_B, crtc_state->saveHSYNC);
+ REG_WRITE(pipeA ? VTOTAL_A : VTOTAL_B, crtc_state->saveVTOTAL);
+ REG_WRITE(pipeA ? VBLANK_A : VBLANK_B, crtc_state->saveVBLANK);
+ REG_WRITE(pipeA ? VSYNC_A : VSYNC_B, crtc_state->saveVSYNC);
+ REG_WRITE(pipeA ? DSPASTRIDE : DSPBSTRIDE, crtc_state->saveDSPSTRIDE);
+
+ REG_WRITE(pipeA ? DSPASIZE : DSPBSIZE, crtc_state->saveDSPSIZE);
+ REG_WRITE(pipeA ? DSPAPOS : DSPBPOS, crtc_state->saveDSPPOS);
+
+ REG_WRITE(pipeA ? PIPEASRC : PIPEBSRC, crtc_state->savePIPESRC);
+ REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE);
+ REG_WRITE(pipeA ? PIPEACONF : PIPEBCONF, crtc_state->savePIPECONF);
+
+ psb_intel_wait_for_vblank(dev);
+
+ REG_WRITE(pipeA ? DSPACNTR : DSPBCNTR, crtc_state->saveDSPCNTR);
+ REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE);
+
+ psb_intel_wait_for_vblank(dev);
+
+ paletteReg = pipeA ? PALETTE_A : PALETTE_B;
+ for (i = 0; i < 256; ++i)
+ REG_WRITE(paletteReg + (i << 2), crtc_state->savePalette[i]);
+}
+
+/* FIXME: Start using the start and size parameters */
+static void psb_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red,
+ u16 *green, u16 *blue, uint32_t start,
+ uint32_t size)
+{
+ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+ int i;
+
+ if (size != 256)
+ return;
+
+ for (i = 0; i < 256; i++) {
+ psb_intel_crtc->lut_r[i] = red[i] >> 8;
+ psb_intel_crtc->lut_g[i] = green[i] >> 8;
+ psb_intel_crtc->lut_b[i] = blue[i] >> 8;
+ }
+
+ psb_intel_crtc_load_lut(crtc);
+}
+
+static void psb_intel_crtc_destroy(struct drm_crtc *crtc)
+{
+ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+
+ kfree(psb_intel_crtc->crtc_state);
+ drm_crtc_cleanup(crtc);
+ kfree(psb_intel_crtc);
+}
+
+static const struct drm_crtc_helper_funcs mdfld_helper_funcs;
+static const struct drm_crtc_funcs mdfld_intel_crtc_funcs;
+
+/*
+ * Set the default value of cursor control and base register
+ * to zero. This is a workaround for h/w defect on oaktrail
+ */
+static void psb_intel_cursor_init(struct drm_device *dev, int pipe)
+{
+ uint32_t control;
+ uint32_t base;
+
+ switch (pipe) {
+ case 0:
+ control = CURACNTR;
+ base = CURABASE;
+ break;
+ case 1:
+ control = CURBCNTR;
+ base = CURBBASE;
+ break;
+ case 2:
+ control = CURCCNTR;
+ base = CURCBASE;
+ break;
+ default:
+ return;
+ }
+
+ REG_WRITE(control, 0);
+ REG_WRITE(base, 0);
+}
+
+void psb_intel_crtc_init(struct drm_device *dev, int pipe,
+ struct psb_intel_mode_device *mode_dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct psb_intel_crtc *psb_intel_crtc;
+ int i;
+ uint16_t *r_base, *g_base, *b_base;
+
+ PSB_DEBUG_ENTRY("\n");
+
+ /* We allocate a extra array of drm_connector pointers
+ * for fbdev after the crtc */
+ psb_intel_crtc =
+ kzalloc(sizeof(struct psb_intel_crtc) +
+ (INTELFB_CONN_LIMIT * sizeof(struct drm_connector *)),
+ GFP_KERNEL);
+ if (psb_intel_crtc == NULL)
+ return;
+
+ psb_intel_crtc->crtc_state =
+ kzalloc(sizeof(struct psb_intel_crtc_state), GFP_KERNEL);
+ if (!psb_intel_crtc->crtc_state) {
+ DRM_INFO("Crtc state error: No memory\n");
+ kfree(psb_intel_crtc);
+ return;
+ }
+
+ drm_crtc_init(dev, &psb_intel_crtc->base, &mdfld_intel_crtc_funcs);
+
+ drm_mode_crtc_set_gamma_size(&psb_intel_crtc->base, 256);
+ psb_intel_crtc->pipe = pipe;
+ psb_intel_crtc->plane = pipe;
+
+ r_base = psb_intel_crtc->base.gamma_store;
+ g_base = r_base + 256;
+ b_base = g_base + 256;
+ for (i = 0; i < 256; i++) {
+ psb_intel_crtc->lut_r[i] = i;
+ psb_intel_crtc->lut_g[i] = i;
+ psb_intel_crtc->lut_b[i] = i;
+ r_base[i] = i << 8;
+ g_base[i] = i << 8;
+ b_base[i] = i << 8;
+
+ psb_intel_crtc->lut_adj[i] = 0;
+ }
+
+ psb_intel_crtc->mode_dev = mode_dev;
+ psb_intel_crtc->cursor_addr = 0;
+
+ drm_crtc_helper_add(&psb_intel_crtc->base, &mdfld_helper_funcs);
+
+ /* Setup the array of drm_connector pointer array */
+ psb_intel_crtc->mode_set.crtc = &psb_intel_crtc->base;
+ BUG_ON(pipe >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) ||
+ dev_priv->plane_to_crtc_mapping[psb_intel_crtc->plane] != NULL);
+ dev_priv->plane_to_crtc_mapping[psb_intel_crtc->plane] = &psb_intel_crtc->base;
+ dev_priv->pipe_to_crtc_mapping[psb_intel_crtc->pipe] = &psb_intel_crtc->base;
+ psb_intel_crtc->mode_set.connectors =
+ (struct drm_connector **) (psb_intel_crtc + 1);
+ psb_intel_crtc->mode_set.num_connectors = 0;
+
+ psb_intel_cursor_init(dev, pipe);
+}
+
+int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_psb_get_pipe_from_crtc_id_arg *pipe_from_crtc_id = data;
+ struct drm_mode_object *drmmode_obj;
+ struct psb_intel_crtc *crtc;
+
+ if (!dev_priv) {
+ DRM_ERROR("called with no initialization\n");
+ return -EINVAL;
+ }
+
+ drmmode_obj = drm_mode_object_find(dev, pipe_from_crtc_id->crtc_id,
+ DRM_MODE_OBJECT_CRTC);
+
+ if (!drmmode_obj) {
+ DRM_ERROR("no such CRTC id\n");
+ return -EINVAL;
+ }
+
+ crtc = to_psb_intel_crtc(obj_to_crtc(drmmode_obj));
+ pipe_from_crtc_id->pipe = crtc->pipe;
+
+ return 0;
+}
+
+int psb_intel_connector_clones(struct drm_device *dev, int type_mask)
+{
+ int index_mask = 0;
+ struct drm_connector *connector;
+ int entry = 0;
+
+ list_for_each_entry(connector, &dev->mode_config.connector_list,
+ head) {
+ struct psb_intel_output *psb_intel_output =
+ to_psb_intel_output(connector);
+ if (type_mask & (1 << psb_intel_output->type))
+ index_mask |= (1 << entry);
+ entry++;
+ }
+ return index_mask;
+}
+
+/* current intel driver doesn't take advantage of encoders
+ always give back the encoder for the connector
+*/
+struct drm_encoder *psb_intel_best_encoder(struct drm_connector *connector)
+{
+ struct psb_intel_output *psb_intel_output =
+ to_psb_intel_output(connector);
+
+ return &psb_intel_output->enc;
+}
+
+struct mrst_limit_t {
+ struct psb_intel_range_t dot, m, p1;
+};
+
+struct mrst_clock_t {
+ /* derived values */
+ int dot;
+ int m;
+ int p1;
+};
+
+#define COUNT_MAX 0x10000000
+
+static const struct drm_crtc_helper_funcs mdfld_helper_funcs = {
+ .dpms = mdfld_crtc_dpms,
+ .mode_fixup = psb_intel_crtc_mode_fixup,
+ .mode_set = mdfld_crtc_mode_set,
+ .mode_set_base = mdfld__intel_pipe_set_base,
+ .prepare = psb_intel_crtc_prepare,
+ .commit = psb_intel_crtc_commit,
+};
+
+#include "mdfld_dsi_dbi.h"
+#include "mdfld_dsi_dpi.h"
+
+#ifdef CONFIG_MDFLD_DSI_DPU
+#include "mdfld_dsi_dbi_dpu.h"
+#endif
+
+#include <linux/pm_runtime.h>
+
+void mdfldWaitForPipeDisable(struct drm_device *dev, int pipe)
+{
+ int count, temp;
+ u32 pipeconf_reg = PIPEACONF;
+
+ switch (pipe) {
+ case 0:
+ break;
+ case 1:
+ pipeconf_reg = PIPEBCONF;
+ break;
+ case 2:
+ pipeconf_reg = PIPECCONF;
+ break;
+ default:
+ DRM_ERROR("Illegal Pipe Number. \n");
+ return;
+ }
+
+ /* FIXME JLIU7_PO */
+ psb_intel_wait_for_vblank(dev);
+ return;
+
+ /* Wait for for the pipe disable to take effect. */
+ for (count = 0; count < COUNT_MAX; count++) {
+ temp = REG_READ(pipeconf_reg);
+ if ((temp & PIPEACONF_PIPE_STATE) == 0)
+ break;
+ }
+
+ PSB_DEBUG_ENTRY("cout = %d. \n", count);
+}
+
+void mdfldWaitForPipeEnable(struct drm_device *dev, int pipe)
+{
+ int count, temp;
+ u32 pipeconf_reg = PIPEACONF;
+
+ switch (pipe) {
+ case 0:
+ break;
+ case 1:
+ pipeconf_reg = PIPEBCONF;
+ break;
+ case 2:
+ pipeconf_reg = PIPECCONF;
+ break;
+ default:
+ DRM_ERROR("Illegal Pipe Number. \n");
+ return;
+ }
+
+ /* FIXME JLIU7_PO */
+ psb_intel_wait_for_vblank(dev);
+ return;
+
+ /* Wait for for the pipe enable to take effect. */
+ for (count = 0; count < COUNT_MAX; count++) {
+ temp = REG_READ(pipeconf_reg);
+ if ((temp & PIPEACONF_PIPE_STATE) == 1)
+ break;
+ }
+
+ PSB_DEBUG_ENTRY("cout = %d. \n", count);
+}
+
+
+static int mdfld_intel_crtc_cursor_set(struct drm_crtc *crtc,
+ struct drm_file *file_priv,
+ uint32_t handle,
+ uint32_t width, uint32_t height)
+{
+ struct drm_device *dev = crtc->dev;
+ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+ struct psb_intel_mode_device *mode_dev = psb_intel_crtc->mode_dev;
+ int pipe = psb_intel_crtc->pipe;
+ uint32_t control = CURACNTR;
+ uint32_t base = CURABASE;
+ uint32_t temp;
+ size_t addr = 0;
+ uint32_t page_offset;
+ size_t size;
+ void *bo;
+ int ret;
+
+ DRM_DEBUG("\n");
+
+ switch (pipe) {
+ case 0:
+ break;
+ case 1:
+ control = CURBCNTR;
+ base = CURBBASE;
+ break;
+ case 2:
+ control = CURCCNTR;
+ base = CURCBASE;
+ break;
+ default:
+ DRM_ERROR("Illegal Pipe Number. \n");
+ return -EINVAL;
+ }
+
+#if 1 /* FIXME_JLIU7 can't enalbe cursorB/C HW issue. need to remove after HW fix */
+ if (pipe != 0)
+ return 0;
+#endif
+ /* if we want to turn of the cursor ignore width and height */
+ if (!handle) {
+ DRM_DEBUG("cursor off\n");
+ /* turn off the cursor */
+ temp = 0;
+ temp |= CURSOR_MODE_DISABLE;
+
+ if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
+ OSPM_UHB_ONLY_IF_ON)) {
+ REG_WRITE(control, temp);
+ REG_WRITE(base, 0);
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+ }
+
+ /* unpin the old bo */
+ if (psb_intel_crtc->cursor_bo) {
+ mode_dev->bo_unpin_for_scanout(dev,
+ psb_intel_crtc->
+ cursor_bo);
+ psb_intel_crtc->cursor_bo = NULL;
+ }
+ return 0;
+ }
+
+ /* Currently we only support 64x64 cursors */
+ if (width != 64 || height != 64) {
+ DRM_ERROR("we currently only support 64x64 cursors\n");
+ return -EINVAL;
+ }
+
+ bo = mode_dev->bo_from_handle(dev, file_priv, handle);
+ if (!bo)
+ return -ENOENT;
+
+ ret = mode_dev->bo_pin_for_scanout(dev, bo);
+ if (ret)
+ return ret;
+ size = mode_dev->bo_size(dev, bo);
+ if (size < width * height * 4) {
+ DRM_ERROR("buffer is to small\n");
+ return -ENOMEM;
+ }
+
+ /*insert this bo into gtt*/
+// DRM_INFO("%s: map meminfo for hw cursor. handle %x, pipe = %d \n", __FUNCTION__, handle, pipe);
+
+ ret = psb_gtt_map_meminfo(dev, (IMG_HANDLE)handle, &page_offset);
+ if(ret) {
+ DRM_ERROR("Can not map meminfo to GTT. handle 0x%x\n", handle);
+ return ret;
+ }
+
+ addr = page_offset << PAGE_SHIFT;
+
+ psb_intel_crtc->cursor_addr = addr;
+
+ temp = 0;
+ /* set the pipe for the cursor */
+ temp |= (pipe << 28);
+ temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
+
+ if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_ONLY_IF_ON)) {
+ REG_WRITE(control, temp);
+ REG_WRITE(base, addr);
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+ }
+
+ /* unpin the old bo */
+ if (psb_intel_crtc->cursor_bo && psb_intel_crtc->cursor_bo != bo) {
+ mode_dev->bo_unpin_for_scanout(dev, psb_intel_crtc->cursor_bo);
+ psb_intel_crtc->cursor_bo = bo;
+ }
+
+ return 0;
+}
+
+static int mdfld_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
+{
+ struct drm_device *dev = crtc->dev;
+#ifndef CONFIG_MDFLD_DSI_DPU
+ struct drm_psb_private * dev_priv = (struct drm_psb_private *)dev->dev_private;
+#else
+ struct psb_drm_dpu_rect rect;
+#endif
+ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+ int pipe = psb_intel_crtc->pipe;
+ uint32_t pos = CURAPOS;
+ uint32_t base = CURABASE;
+ uint32_t temp = 0;
+ uint32_t addr;
+
+ switch (pipe) {
+ case 0:
+#ifndef CONFIG_MDFLD_DSI_DPU
+ if (!(dev_priv->dsr_fb_update & MDFLD_DSR_CURSOR_0))
+ mdfld_dsi_dbi_exit_dsr (dev, MDFLD_DSR_CURSOR_0);
+#else /*CONFIG_MDFLD_DSI_DPU*/
+ rect.x = x;
+ rect.y = y;
+
+ mdfld_dbi_dpu_report_damage(dev, MDFLD_CURSORA, &rect);
+ mdfld_dpu_exit_dsr(dev);
+#endif
+ break;
+ case 1:
+ pos = CURBPOS;
+ base = CURBBASE;
+ break;
+ case 2:
+#ifndef CONFIG_MDFLD_DSI_DPU
+ if (!(dev_priv->dsr_fb_update & MDFLD_DSR_CURSOR_2))
+ mdfld_dsi_dbi_exit_dsr (dev, MDFLD_DSR_CURSOR_2);
+#else /*CONFIG_MDFLD_DSI_DPU*/
+ mdfld_dbi_dpu_report_damage(dev, MDFLD_CURSORC, &rect);
+ mdfld_dpu_exit_dsr(dev);
+#endif
+ pos = CURCPOS;
+ base = CURCBASE;
+ break;
+ default:
+ DRM_ERROR("Illegal Pipe Number. \n");
+ return -EINVAL;
+ }
+
+#if 1 /* FIXME_JLIU7 can't enalbe cursorB/C HW issue. need to remove after HW fix */
+ if (pipe != 0)
+ return 0;
+#endif
+ if (x < 0) {
+ temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT);
+ x = -x;
+ }
+ if (y < 0) {
+ temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT);
+ y = -y;
+ }
+
+ temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT);
+ temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
+
+ addr = psb_intel_crtc->cursor_addr;
+
+ if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
+ OSPM_UHB_ONLY_IF_ON)) {
+ REG_WRITE(pos, temp);
+ REG_WRITE(base, addr);
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+ }
+
+ return 0;
+}
+
+static const struct drm_crtc_funcs mdfld_intel_crtc_funcs = {
+ .save = psb_intel_crtc_save,
+ .restore = psb_intel_crtc_restore,
+ .cursor_set = mdfld_intel_crtc_cursor_set,
+ .cursor_move = mdfld_intel_crtc_cursor_move,
+ .gamma_set = psb_intel_crtc_gamma_set,
+ .set_config = drm_crtc_helper_set_config,
+ .destroy = psb_intel_crtc_destroy,
+ .page_flip = psb_intel_crtc_page_flip,
+};
+
+static struct drm_device globle_dev;
+
+void mdfld__intel_plane_set_alpha(int enable)
+{
+ struct drm_device *dev = &globle_dev;
+ int dspcntr_reg = DSPACNTR;
+ u32 dspcntr;
+
+ dspcntr = REG_READ(dspcntr_reg);
+
+ if (enable) {
+ dspcntr &= ~DISPPLANE_32BPP_NO_ALPHA;
+ dspcntr |= DISPPLANE_32BPP;
+ } else {
+ dspcntr &= ~DISPPLANE_32BPP;
+ dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
+ }
+
+ REG_WRITE(dspcntr_reg, dspcntr);
+}
+
+static int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
+ struct drm_framebuffer *old_fb)
+{
+ struct drm_device *dev = crtc->dev;
+ /* struct drm_i915_master_private *master_priv; */
+ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+ struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
+ struct psb_intel_mode_device *mode_dev = psb_intel_crtc->mode_dev;
+ int pipe = psb_intel_crtc->pipe;
+ unsigned long Start, Offset;
+ int dsplinoff = DSPALINOFF;
+ int dspsurf = DSPASURF;
+ int dspstride = DSPASTRIDE;
+ int dspcntr_reg = DSPACNTR;
+ u32 dspcntr;
+ int ret = 0;
+
+ memcpy(&globle_dev, dev, sizeof(struct drm_device));
+
+ PSB_DEBUG_ENTRY("pipe = 0x%x. \n", pipe);
+
+ /* no fb bound */
+ if (!crtc->fb) {
+ PSB_DEBUG_ENTRY("No FB bound\n");
+ return 0;
+ }
+
+ switch (pipe) {
+ case 0:
+ dsplinoff = DSPALINOFF;
+ break;
+ case 1:
+ dsplinoff = DSPBLINOFF;
+ dspsurf = DSPBSURF;
+ dspstride = DSPBSTRIDE;
+ dspcntr_reg = DSPBCNTR;
+ break;
+ case 2:
+ dsplinoff = DSPCLINOFF;
+ dspsurf = DSPCSURF;
+ dspstride = DSPCSTRIDE;
+ dspcntr_reg = DSPCCNTR;
+ break;
+ default:
+ DRM_ERROR("Illegal Pipe Number. \n");
+ return -EINVAL;
+ }
+
+ if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
+ OSPM_UHB_FORCE_POWER_ON))
+ return 0;
+
+ Start = mode_dev->bo_offset(dev, psbfb);
+ Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
+
+ REG_WRITE(dspstride, crtc->fb->pitch);
+ dspcntr = REG_READ(dspcntr_reg);
+ dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
+
+ switch (crtc->fb->bits_per_pixel) {
+ case 8:
+ dspcntr |= DISPPLANE_8BPP;
+ break;
+ case 16:
+ if (crtc->fb->depth == 15)
+ dspcntr |= DISPPLANE_15_16BPP;
+ else
+ dspcntr |= DISPPLANE_16BPP;
+ break;
+ case 24:
+ case 32:
+ dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
+ break;
+ default:
+ DRM_ERROR("Unknown color depth\n");
+ ret = -EINVAL;
+ goto psb_intel_pipe_set_base_exit;
+ }
+ REG_WRITE(dspcntr_reg, dspcntr);
+
+ PSB_DEBUG_ENTRY("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y);
+
+ REG_WRITE(dsplinoff, Offset);
+ REG_READ(dsplinoff);
+ REG_WRITE(dspsurf, Start);
+ REG_READ(dspsurf);
+
+psb_intel_pipe_set_base_exit:
+
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+
+ return ret;
+}
+
+/**
+ * Disable the pipe, plane and pll.
+ *
+ */
+void mdfld_disable_crtc (struct drm_device *dev, int pipe)
+{
+ int dpll_reg = MRST_DPLL_A;
+ int dspcntr_reg = DSPACNTR;
+ int dspbase_reg = MRST_DSPABASE;
+ int pipeconf_reg = PIPEACONF;
+ u32 temp;
+
+ PSB_DEBUG_ENTRY("pipe = %d \n", pipe);
+
+
+ switch (pipe) {
+ case 0:
+ break;
+ case 1:
+ dpll_reg = MDFLD_DPLL_B;
+ dspcntr_reg = DSPBCNTR;
+ dspbase_reg = DSPBSURF;
+ pipeconf_reg = PIPEBCONF;
+ break;
+ case 2:
+ dpll_reg = MRST_DPLL_A;
+ dspcntr_reg = DSPCCNTR;
+ dspbase_reg = MDFLD_DSPCBASE;
+ pipeconf_reg = PIPECCONF;
+ break;
+ default:
+ DRM_ERROR("Illegal Pipe Number. \n");
+ return;
+ }
+
+ if (pipe != 1)
+ mdfld_dsi_gen_fifo_ready(dev, MIPI_GEN_FIFO_STAT_REG(pipe), HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY);
+
+ /* Disable display plane */
+ temp = REG_READ(dspcntr_reg);
+ if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
+ REG_WRITE(dspcntr_reg,
+ temp & ~DISPLAY_PLANE_ENABLE);
+ /* Flush the plane changes */
+ REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
+ REG_READ(dspbase_reg);
+ }
+
+ /* FIXME_JLIU7 MDFLD_PO revisit */
+ /* Wait for vblank for the disable to take effect */
+// MDFLD_PO_JLIU7 psb_intel_wait_for_vblank(dev);
+
+ /* Next, disable display pipes */
+ temp = REG_READ(pipeconf_reg);
+ if ((temp & PIPEACONF_ENABLE) != 0) {
+ temp &= ~PIPEACONF_ENABLE;
+ temp |= PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF;
+ REG_WRITE(pipeconf_reg, temp);
+ REG_READ(pipeconf_reg);
+
+ /* Wait for for the pipe disable to take effect. */
+ mdfldWaitForPipeDisable(dev, pipe);
+ }
+
+ temp = REG_READ(dpll_reg);
+ if (temp & DPLL_VCO_ENABLE) {
+ if (((pipe != 1) && !((REG_READ(PIPEACONF) | REG_READ(PIPECCONF)) & PIPEACONF_ENABLE))
+ || (pipe == 1)){
+ temp &= ~(DPLL_VCO_ENABLE);
+ REG_WRITE(dpll_reg, temp);
+ REG_READ(dpll_reg);
+ /* Wait for the clocks to turn off. */
+ /* FIXME_MDFLD PO may need more delay */
+ udelay(500);
+
+ if (!(temp & MDFLD_PWR_GATE_EN)) {
+ /* gating power of DPLL */
+ REG_WRITE(dpll_reg, temp | MDFLD_PWR_GATE_EN);
+ /* FIXME_MDFLD PO - change 500 to 1 after PO */
+ udelay(5000);
+ }
+ }
+ }
+
+}
+
+/**
+ * Sets the power management mode of the pipe and plane.
+ *
+ * This code should probably grow support for turning the cursor off and back
+ * on appropriately at the same time as we're turning the pipe off/on.
+ */
+static void mdfld_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+ struct drm_device *dev = crtc->dev;
+ DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private;
+ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+ int pipe = psb_intel_crtc->pipe;
+ int dpll_reg = MRST_DPLL_A;
+ int dspcntr_reg = DSPACNTR;
+ int dspbase_reg = MRST_DSPABASE;
+ int pipeconf_reg = PIPEACONF;
+ u32 pipestat_reg = PIPEASTAT;
+ u32 pipeconf = dev_priv->pipeconf;
+ u32 dspcntr = dev_priv->dspcntr;
+ u32 temp;
+ bool enabled;
+ int timeout = 0;
+
+ PSB_DEBUG_ENTRY("mode = %d, pipe = %d \n", mode, pipe);
+
+ /* Ignore if system is already in DSR and in suspended state. */
+ if ((gbgfxsuspended) && (gbdispstatus == false) && (mode == DRM_MODE_DPMS_OFF)) {
+#if CONFIG_PM_RUNTIME
+ if ((dev_priv->rpm_enabled) && (pipe == 1)){
+ // dev_priv->is_mipi_on = false;
+ pm_request_idle(&gpDrmDevice->pdev->dev);
+ }
+#endif
+ return;
+ } else if (mode == DRM_MODE_DPMS_ON) {
+ //do not need to set gbdispstatus=true in crtc.
+ //this will be set in encoder's DPMS callback.
+ //gbdispstatus = true;
+ }
+
+/* FIXME_JLIU7 MDFLD_PO replaced w/ the following function */
+/* mdfld_dbi_dpms (struct drm_device *dev, int pipe, bool enabled) */
+
+ switch (pipe) {
+ case 0:
+ break;
+ case 1:
+ dpll_reg = DPLL_B;
+ dspcntr_reg = DSPBCNTR;
+ dspbase_reg = MRST_DSPBBASE;
+ pipeconf_reg = PIPEBCONF;
+ pipeconf = dev_priv->pipeconf1;
+ dspcntr = dev_priv->dspcntr1;
+ dpll_reg = MDFLD_DPLL_B;
+ break;
+ case 2:
+ dpll_reg = MRST_DPLL_A;
+ dspcntr_reg = DSPCCNTR;
+ dspbase_reg = MDFLD_DSPCBASE;
+ pipeconf_reg = PIPECCONF;
+ pipestat_reg = PIPECSTAT;
+ pipeconf = dev_priv->pipeconf2;
+ dspcntr = dev_priv->dspcntr2;
+ break;
+ default:
+ DRM_ERROR("Illegal Pipe Number. \n");
+ return;
+ }
+
+ if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
+ OSPM_UHB_FORCE_POWER_ON))
+ return;
+
+ /* XXX: When our outputs are all unaware of DPMS modes other than off
+ * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
+ */
+ switch (mode) {
+ case DRM_MODE_DPMS_ON:
+ case DRM_MODE_DPMS_STANDBY:
+ case DRM_MODE_DPMS_SUSPEND:
+ /* Enable the DPLL */
+ temp = REG_READ(dpll_reg);
+
+ if ((temp & DPLL_VCO_ENABLE) == 0) {
+ /* When ungating power of DPLL, needs to wait 0.5us before enable the VCO */
+ if (temp & MDFLD_PWR_GATE_EN) {
+ temp &= ~MDFLD_PWR_GATE_EN;
+ REG_WRITE(dpll_reg, temp);
+ /* FIXME_MDFLD PO - change 500 to 1 after PO */
+ udelay(500);
+ }
+
+ REG_WRITE(dpll_reg, temp);
+ REG_READ(dpll_reg);
+ /* FIXME_MDFLD PO - change 500 to 1 after PO */
+ udelay(500);
+
+ REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
+ REG_READ(dpll_reg);
+
+ /**
+ * wait for DSI PLL to lock
+ * NOTE: only need to poll status of pipe 0 and pipe 1,
+ * since both MIPI pipes share the same PLL.
+ */
+ while ((pipe != 2) && (timeout < 20000) && !(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) {
+ udelay(150);
+ timeout ++;
+ }
+ }
+
+ /* Enable the plane */
+ temp = REG_READ(dspcntr_reg);
+ if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
+ REG_WRITE(dspcntr_reg,
+ temp | DISPLAY_PLANE_ENABLE);
+ /* Flush the plane changes */
+ REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
+ }
+
+ /* Enable the pipe */
+ temp = REG_READ(pipeconf_reg);
+ if ((temp & PIPEACONF_ENABLE) == 0) {
+ REG_WRITE(pipeconf_reg, pipeconf);
+
+ /* Wait for for the pipe enable to take effect. */
+ mdfldWaitForPipeEnable(dev, pipe);
+ }
+
+ /*workaround for sighting 3741701 Random X blank display*/
+ /*perform w/a in video mode only on pipe A or C*/
+ if ((pipe == 0 || pipe == 2) &&
+ (is_panel_vid_or_cmd(dev) == MDFLD_DSI_ENCODER_DPI)) {
+ REG_WRITE(pipestat_reg, REG_READ(pipestat_reg));
+ msleep(100);
+ if(PIPE_VBLANK_STATUS & REG_READ(pipestat_reg)) {
+ printk(KERN_ALERT "OK");
+ } else {
+ printk(KERN_ALERT "STUCK!!!!");
+ /*shutdown controller*/
+ temp = REG_READ(dspcntr_reg);
+ REG_WRITE(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE);
+ REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
+ /*mdfld_dsi_dpi_shut_down(dev, pipe);*/
+ REG_WRITE(0xb048, 1);
+ msleep(100);
+ temp = REG_READ(pipeconf_reg);
+ temp &= ~PIPEACONF_ENABLE;
+ REG_WRITE(pipeconf_reg, temp);
+ msleep(100); /*wait for pipe disable*/
+ /*printk(KERN_ALERT "70008 is %x\n", REG_READ(0x70008));
+ printk(KERN_ALERT "b074 is %x\n", REG_READ(0xb074));*/
+ REG_WRITE(MIPI_DEVICE_READY_REG(pipe), 0);
+ msleep(100);
+ printk(KERN_ALERT "70008 is %x\n", REG_READ(0x70008));
+ printk(KERN_ALERT "b074 is %x\n", REG_READ(0xb074));
+ REG_WRITE(0xb004, REG_READ(0xb004));
+ /* try to bring the controller back up again*/
+ REG_WRITE(MIPI_DEVICE_READY_REG(pipe), 1);
+ temp = REG_READ(dspcntr_reg);
+ REG_WRITE(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE);
+ REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
+ /*mdfld_dsi_dpi_turn_on(dev, pipe);*/
+ REG_WRITE(0xb048, 2);
+ msleep(100);
+ temp = REG_READ(pipeconf_reg);
+ temp |= PIPEACONF_ENABLE;
+ REG_WRITE(pipeconf_reg, temp);
+ }
+ }
+
+ psb_intel_crtc_load_lut(crtc);
+
+ /* Give the overlay scaler a chance to enable
+ if it's on this pipe */
+ /* psb_intel_crtc_dpms_video(crtc, true); TODO */
+
+ break;
+ case DRM_MODE_DPMS_OFF:
+ /* Give the overlay scaler a chance to disable
+ * if it's on this pipe */
+ /* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */
+ if (pipe != 1)
+ mdfld_dsi_gen_fifo_ready(dev, MIPI_GEN_FIFO_STAT_REG(pipe), HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY);
+
+ /* Disable the VGA plane that we never use */
+ REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
+
+ /* Disable display plane */
+ temp = REG_READ(dspcntr_reg);
+ if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
+ REG_WRITE(dspcntr_reg,
+ temp & ~DISPLAY_PLANE_ENABLE);
+ /* Flush the plane changes */
+ REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
+ REG_READ(dspbase_reg);
+ }
+
+ /* FIXME_JLIU7 MDFLD_PO revisit */
+ /* Wait for vblank for the disable to take effect */
+// MDFLD_PO_JLIU7 psb_intel_wait_for_vblank(dev);
+
+ /* Next, disable display pipes */
+ temp = REG_READ(pipeconf_reg);
+ if ((temp & PIPEACONF_ENABLE) != 0) {
+ temp &= ~PIPEACONF_ENABLE;
+ temp |= PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF;
+ REG_WRITE(pipeconf_reg, temp);
+// REG_WRITE(pipeconf_reg, 0);
+ REG_READ(pipeconf_reg);
+
+ /* Wait for for the pipe disable to take effect. */
+ mdfldWaitForPipeDisable(dev, pipe);
+ }
+
+ temp = REG_READ(dpll_reg);
+ if (temp & DPLL_VCO_ENABLE) {
+ if (((pipe != 1) && !((REG_READ(PIPEACONF) | REG_READ(PIPECCONF)) & PIPEACONF_ENABLE))
+ || (pipe == 1)){
+ temp &= ~(DPLL_VCO_ENABLE);
+ REG_WRITE(dpll_reg, temp);
+ REG_READ(dpll_reg);
+ /* Wait for the clocks to turn off. */
+ /* FIXME_MDFLD PO may need more delay */
+ udelay(500);
+#if 0 /* MDFLD_PO_JLIU7 */
+ if (!(temp & MDFLD_PWR_GATE_EN)) {
+ /* gating power of DPLL */
+ REG_WRITE(dpll_reg, temp | MDFLD_PWR_GATE_EN);
+ /* FIXME_MDFLD PO - change 500 to 1 after PO */
+ udelay(5000);
+ }
+#endif /* MDFLD_PO_JLIU7 */
+ }
+ }
+ break;
+ }
+
+ enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF;
+
+#if 0 /* JB: Add vblank support later */
+ if (enabled)
+ dev_priv->vblank_pipe |= (1 << pipe);
+ else
+ dev_priv->vblank_pipe &= ~(1 << pipe);
+#endif
+
+#if 0 /* JB: Add sarea support later */
+ if (!dev->primary->master)
+ return;
+
+ master_priv = dev->primary->master->driver_priv;
+ if (!master_priv->sarea_priv)
+ return;
+
+ switch (pipe) {
+ case 0:
+ master_priv->sarea_priv->planeA_w =
+ enabled ? crtc->mode.hdisplay : 0;
+ master_priv->sarea_priv->planeA_h =
+ enabled ? crtc->mode.vdisplay : 0;
+ break;
+ case 1:
+ master_priv->sarea_priv->planeB_w =
+ enabled ? crtc->mode.hdisplay : 0;
+ master_priv->sarea_priv->planeB_h =
+ enabled ? crtc->mode.vdisplay : 0;
+ break;
+ default:
+ DRM_ERROR("Can't update pipe %d in SAREA\n", pipe);
+ break;
+ }
+#endif
+
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+}
+
+
+#define MDFLD_LIMT_DPLL_19 0
+#define MDFLD_LIMT_DPLL_25 1
+#define MDFLD_LIMT_DPLL_83 2
+#define MDFLD_LIMT_DPLL_100 3
+#define MDFLD_LIMT_DSIPLL_19 4
+#define MDFLD_LIMT_DSIPLL_25 5
+#define MDFLD_LIMT_DSIPLL_83 6
+#define MDFLD_LIMT_DSIPLL_100 7
+
+#define MDFLD_DOT_MIN 19750 /* FIXME_MDFLD JLIU7 need to find out min & max for MDFLD */
+#define MDFLD_DOT_MAX 120000
+#define MDFLD_DPLL_M_MIN_19 113
+#define MDFLD_DPLL_M_MAX_19 155
+#define MDFLD_DPLL_P1_MIN_19 2
+#define MDFLD_DPLL_P1_MAX_19 10
+#define MDFLD_DPLL_M_MIN_25 101
+#define MDFLD_DPLL_M_MAX_25 130
+#define MDFLD_DPLL_P1_MIN_25 2
+#define MDFLD_DPLL_P1_MAX_25 10
+#define MDFLD_DPLL_M_MIN_83 64
+#define MDFLD_DPLL_M_MAX_83 64
+#define MDFLD_DPLL_P1_MIN_83 2
+#define MDFLD_DPLL_P1_MAX_83 2
+#define MDFLD_DPLL_M_MIN_100 64
+#define MDFLD_DPLL_M_MAX_100 64
+#define MDFLD_DPLL_P1_MIN_100 2
+#define MDFLD_DPLL_P1_MAX_100 2
+#define MDFLD_DSIPLL_M_MIN_19 131
+#define MDFLD_DSIPLL_M_MAX_19 175
+#define MDFLD_DSIPLL_P1_MIN_19 3
+#define MDFLD_DSIPLL_P1_MAX_19 8
+#define MDFLD_DSIPLL_M_MIN_25 97
+#define MDFLD_DSIPLL_M_MAX_25 140
+#define MDFLD_DSIPLL_P1_MIN_25 3
+#define MDFLD_DSIPLL_P1_MAX_25 9
+#define MDFLD_DSIPLL_M_MIN_83 33
+#define MDFLD_DSIPLL_M_MAX_83 92
+#define MDFLD_DSIPLL_P1_MIN_83 2
+#define MDFLD_DSIPLL_P1_MAX_83 3
+#define MDFLD_DSIPLL_M_MIN_100 97
+#define MDFLD_DSIPLL_M_MAX_100 140
+#define MDFLD_DSIPLL_P1_MIN_100 3
+#define MDFLD_DSIPLL_P1_MAX_100 9
+
+static const struct mrst_limit_t mdfld_limits[] = {
+ { /* MDFLD_LIMT_DPLL_19 */
+ .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
+ .m = {.min = MDFLD_DPLL_M_MIN_19, .max = MDFLD_DPLL_M_MAX_19},
+ .p1 = {.min = MDFLD_DPLL_P1_MIN_19, .max = MDFLD_DPLL_P1_MAX_19},
+ },
+ { /* MDFLD_LIMT_DPLL_25 */
+ .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
+ .m = {.min = MDFLD_DPLL_M_MIN_25, .max = MDFLD_DPLL_M_MAX_25},
+ .p1 = {.min = MDFLD_DPLL_P1_MIN_25, .max = MDFLD_DPLL_P1_MAX_25},
+ },
+ { /* MDFLD_LIMT_DPLL_83 */
+ .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
+ .m = {.min = MDFLD_DPLL_M_MIN_83, .max = MDFLD_DPLL_M_MAX_83},
+ .p1 = {.min = MDFLD_DPLL_P1_MIN_83, .max = MDFLD_DPLL_P1_MAX_83},
+ },
+ { /* MDFLD_LIMT_DPLL_100 */
+ .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
+ .m = {.min = MDFLD_DPLL_M_MIN_100, .max = MDFLD_DPLL_M_MAX_100},
+ .p1 = {.min = MDFLD_DPLL_P1_MIN_100, .max = MDFLD_DPLL_P1_MAX_100},
+ },
+ { /* MDFLD_LIMT_DSIPLL_19 */
+ .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
+ .m = {.min = MDFLD_DSIPLL_M_MIN_19, .max = MDFLD_DSIPLL_M_MAX_19},
+ .p1 = {.min = MDFLD_DSIPLL_P1_MIN_19, .max = MDFLD_DSIPLL_P1_MAX_19},
+ },
+ { /* MDFLD_LIMT_DSIPLL_25 */
+ .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
+ .m = {.min = MDFLD_DSIPLL_M_MIN_25, .max = MDFLD_DSIPLL_M_MAX_25},
+ .p1 = {.min = MDFLD_DSIPLL_P1_MIN_25, .max = MDFLD_DSIPLL_P1_MAX_25},
+ },
+ { /* MDFLD_LIMT_DSIPLL_83 */
+ .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
+ .m = {.min = MDFLD_DSIPLL_M_MIN_83, .max = MDFLD_DSIPLL_M_MAX_83},
+ .p1 = {.min = MDFLD_DSIPLL_P1_MIN_83, .max = MDFLD_DSIPLL_P1_MAX_83},
+ },
+ { /* MDFLD_LIMT_DSIPLL_100 */
+ .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
+ .m = {.min = MDFLD_DSIPLL_M_MIN_100, .max = MDFLD_DSIPLL_M_MAX_100},
+ .p1 = {.min = MDFLD_DSIPLL_P1_MIN_100, .max = MDFLD_DSIPLL_P1_MAX_100},
+ },
+};
+
+#define MDFLD_M_MIN 21
+#define MDFLD_M_MAX 180
+static const u32 mdfld_m_converts[] = {
+/* M configuration table from 9-bit LFSR table */
+ 224, 368, 440, 220, 366, 439, 219, 365, 182, 347, /* 21 - 30 */
+ 173, 342, 171, 85, 298, 149, 74, 37, 18, 265, /* 31 - 40 */
+ 388, 194, 353, 432, 216, 108, 310, 155, 333, 166, /* 41 - 50 */
+ 83, 41, 276, 138, 325, 162, 337, 168, 340, 170, /* 51 - 60 */
+ 341, 426, 469, 234, 373, 442, 221, 110, 311, 411, /* 61 - 70 */
+ 461, 486, 243, 377, 188, 350, 175, 343, 427, 213, /* 71 - 80 */
+ 106, 53, 282, 397, 354, 227, 113, 56, 284, 142, /* 81 - 90 */
+ 71, 35, 273, 136, 324, 418, 465, 488, 500, 506, /* 91 - 100 */
+ 253, 126, 63, 287, 399, 455, 483, 241, 376, 444, /* 101 - 110 */
+ 478, 495, 503, 251, 381, 446, 479, 239, 375, 443, /* 111 - 120 */
+ 477, 238, 119, 315, 157, 78, 295, 147, 329, 420, /* 121 - 130 */
+ 210, 105, 308, 154, 77, 38, 275, 137, 68, 290, /* 131 - 140 */
+ 145, 328, 164, 82, 297, 404, 458, 485, 498, 249, /* 141 - 150 */
+ 380, 190, 351, 431, 471, 235, 117, 314, 413, 206, /* 151 - 160 */
+ 103, 51, 25, 12, 262, 387, 193, 96, 48, 280, /* 161 - 170 */
+ 396, 198, 99, 305, 152, 76, 294, 403, 457, 228, /* 171 - 180 */
+};
+
+static const struct mrst_limit_t *mdfld_limit(struct drm_crtc *crtc)
+{
+ const struct mrst_limit_t *limit = NULL;
+ struct drm_device *dev = crtc->dev;
+ DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private;
+
+ if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI)
+ || psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI2)) {
+ if ((dev_priv->ksel == KSEL_CRYSTAL_19) || (dev_priv->ksel == KSEL_BYPASS_19))
+ limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_19];
+ else if (dev_priv->ksel == KSEL_BYPASS_25)
+ limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_25];
+ else if ((dev_priv->ksel == KSEL_BYPASS_83_100) && (dev_priv->core_freq == 166))
+ limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_83];
+ else if ((dev_priv->ksel == KSEL_BYPASS_83_100) &&
+ (dev_priv->core_freq == 100 || dev_priv->core_freq == 200))
+ limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_100];
+ } else if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) {
+ if ((dev_priv->ksel == KSEL_CRYSTAL_19) || (dev_priv->ksel == KSEL_BYPASS_19))
+ limit = &mdfld_limits[MDFLD_LIMT_DPLL_19];
+ else if (dev_priv->ksel == KSEL_BYPASS_25)
+ limit = &mdfld_limits[MDFLD_LIMT_DPLL_25];
+ else if ((dev_priv->ksel == KSEL_BYPASS_83_100) && (dev_priv->core_freq == 166))
+ limit = &mdfld_limits[MDFLD_LIMT_DPLL_83];
+ else if ((dev_priv->ksel == KSEL_BYPASS_83_100) &&
+ (dev_priv->core_freq == 100 || dev_priv->core_freq == 200))
+ limit = &mdfld_limits[MDFLD_LIMT_DPLL_100];
+ } else {
+ limit = NULL;
+ PSB_DEBUG_ENTRY("mdfld_limit Wrong display type. \n");
+ }
+
+ return limit;
+}
+
+/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */
+static void mdfld_clock(int refclk, struct mrst_clock_t *clock)
+{
+ clock->dot = (refclk * clock->m) / clock->p1;
+}
+
+/**
+ * Returns a set of divisors for the desired target clock with the given refclk,
+ * or FALSE. Divisor values are the actual divisors for
+ */
+static bool
+mdfldFindBestPLL(struct drm_crtc *crtc, int target, int refclk,
+ struct mrst_clock_t *best_clock)
+{
+ struct mrst_clock_t clock;
+ const struct mrst_limit_t *limit = mdfld_limit(crtc);
+ int err = target;
+
+ memset(best_clock, 0, sizeof(*best_clock));
+
+ PSB_DEBUG_ENTRY("mdfldFindBestPLL target = %d,"
+ "m_min = %d, m_max = %d, p_min = %d, p_max = %d. \n", target, limit->m.min, limit->m.max, limit->p1.min, limit->p1.max);
+
+ for (clock.m = limit->m.min; clock.m <= limit->m.max; clock.m++) {
+ for (clock.p1 = limit->p1.min; clock.p1 <= limit->p1.max;
+ clock.p1++) {
+ int this_err;
+
+ mdfld_clock(refclk, &clock);
+
+ this_err = abs(clock.dot - target);
+ if (this_err < err) {
+ *best_clock = clock;
+ err = this_err;
+ }
+ }
+ }
+ PSB_DEBUG_ENTRY("mdfldFindBestPLL target = %d,"
+ "m = %d, p = %d. \n", target, best_clock->m, best_clock->p1);
+ PSB_DEBUG_ENTRY("mdfldFindBestPLL err = %d.\n", err);
+
+ return err != target;
+}
+
+static int mdfld_crtc_mode_set(struct drm_crtc *crtc,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode,
+ int x, int y,
+ struct drm_framebuffer *old_fb)
+{
+ struct drm_device *dev = crtc->dev;
+ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+ DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private;
+ int pipe = psb_intel_crtc->pipe;
+ int fp_reg = MRST_FPA0;
+ int dpll_reg = MRST_DPLL_A;
+ int dspcntr_reg = DSPACNTR;
+ int pipeconf_reg = PIPEACONF;
+ int htot_reg = HTOTAL_A;
+ int hblank_reg = HBLANK_A;
+ int hsync_reg = HSYNC_A;
+ int vtot_reg = VTOTAL_A;
+ int vblank_reg = VBLANK_A;
+ int vsync_reg = VSYNC_A;
+ int dspsize_reg = DSPASIZE;
+ int dsppos_reg = DSPAPOS;
+ int pipesrc_reg = PIPEASRC;
+ u32 *pipeconf = &dev_priv->pipeconf;
+ u32 *dspcntr = &dev_priv->dspcntr;
+ int refclk = 0;
+ int clk_n = 0, clk_p2 = 0, clk_byte = 1, clk = 0, m_conv = 0, clk_tmp = 0;
+ struct mrst_clock_t clock;
+ bool ok;
+ u32 dpll = 0, fp = 0;
+ bool is_crt = false, is_lvds = false, is_tv = false;
+ bool is_mipi = false, is_mipi2 = false, is_hdmi = false;
+ struct drm_mode_config *mode_config = &dev->mode_config;
+ struct psb_intel_output *psb_intel_output = NULL;
+ uint64_t scalingType = DRM_MODE_SCALE_FULLSCREEN;
+ struct drm_encoder *encoder;
+ struct drm_connector * connector;
+ int timeout = 0;
+
+ PSB_DEBUG_ENTRY("pipe = 0x%x \n", pipe);
+
+ switch (pipe) {
+ case 0:
+ break;
+ case 1:
+ fp_reg = FPB0;
+ dpll_reg = DPLL_B;
+ dspcntr_reg = DSPBCNTR;
+ pipeconf_reg = PIPEBCONF;
+ htot_reg = HTOTAL_B;
+ hblank_reg = HBLANK_B;
+ hsync_reg = HSYNC_B;
+ vtot_reg = VTOTAL_B;
+ vblank_reg = VBLANK_B;
+ vsync_reg = VSYNC_B;
+ dspsize_reg = DSPBSIZE;
+ dsppos_reg = DSPBPOS;
+ pipesrc_reg = PIPEBSRC;
+ pipeconf = &dev_priv->pipeconf1;
+ dspcntr = &dev_priv->dspcntr1;
+ fp_reg = MDFLD_DPLL_DIV0;
+ dpll_reg = MDFLD_DPLL_B;
+ break;
+ case 2:
+ dpll_reg = MRST_DPLL_A;
+ dspcntr_reg = DSPCCNTR;
+ pipeconf_reg = PIPECCONF;
+ htot_reg = HTOTAL_C;
+ hblank_reg = HBLANK_C;
+ hsync_reg = HSYNC_C;
+ vtot_reg = VTOTAL_C;
+ vblank_reg = VBLANK_C;
+ vsync_reg = VSYNC_C;
+ dspsize_reg = DSPCSIZE;
+ dsppos_reg = DSPCPOS;
+ pipesrc_reg = PIPECSRC;
+ pipeconf = &dev_priv->pipeconf2;
+ dspcntr = &dev_priv->dspcntr2;
+ break;
+ default:
+ DRM_ERROR("Illegal Pipe Number. \n");
+ return 0;
+ }
+
+ PSB_DEBUG_ENTRY("adjusted_hdisplay = %d\n",
+ adjusted_mode->hdisplay);
+ PSB_DEBUG_ENTRY("adjusted_vdisplay = %d\n",
+ adjusted_mode->vdisplay);
+ PSB_DEBUG_ENTRY("adjusted_hsync_start = %d\n",
+ adjusted_mode->hsync_start);
+ PSB_DEBUG_ENTRY("adjusted_hsync_end = %d\n",
+ adjusted_mode->hsync_end);
+ PSB_DEBUG_ENTRY("adjusted_htotal = %d\n",
+ adjusted_mode->htotal);
+ PSB_DEBUG_ENTRY("adjusted_vsync_start = %d\n",
+ adjusted_mode->vsync_start);
+ PSB_DEBUG_ENTRY("adjusted_vsync_end = %d\n",
+ adjusted_mode->vsync_end);
+ PSB_DEBUG_ENTRY("adjusted_vtotal = %d\n",
+ adjusted_mode->vtotal);
+ PSB_DEBUG_ENTRY("adjusted_clock = %d\n",
+ adjusted_mode->clock);
+ PSB_DEBUG_ENTRY("hdisplay = %d\n",
+ mode->hdisplay);
+ PSB_DEBUG_ENTRY("vdisplay = %d\n",
+ mode->vdisplay);
+
+ if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON))
+ return 0;
+
+ memcpy(&psb_intel_crtc->saved_mode, mode, sizeof(struct drm_display_mode));
+ memcpy(&psb_intel_crtc->saved_adjusted_mode, adjusted_mode, sizeof(struct drm_display_mode));
+
+ list_for_each_entry(connector, &mode_config->connector_list, head) {
+ if(!connector)
+ continue;
+
+ encoder = connector->encoder;
+
+ if(!encoder)
+ continue;
+
+ if (encoder->crtc != crtc)
+ continue;
+
+ psb_intel_output = to_psb_intel_output(connector);
+
+ PSB_DEBUG_ENTRY("output->type = 0x%x \n", psb_intel_output->type);
+
+ switch (psb_intel_output->type) {
+ case INTEL_OUTPUT_LVDS:
+ is_lvds = true;
+ break;
+ case INTEL_OUTPUT_TVOUT:
+ is_tv = true;
+ break;
+ case INTEL_OUTPUT_ANALOG:
+ is_crt = true;
+ break;
+ case INTEL_OUTPUT_MIPI:
+ is_mipi = true;
+ break;
+ case INTEL_OUTPUT_MIPI2:
+ is_mipi2 = true;
+ break;
+ case INTEL_OUTPUT_HDMI:
+ is_hdmi = true;
+ break;
+ }
+ }
+
+ /* Disable the VGA plane that we never use */
+ REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
+
+ /* Disable the panel fitter if it was on our pipe */
+ if (psb_intel_panel_fitter_pipe(dev) == pipe)
+ REG_WRITE(PFIT_CONTROL, 0);
+
+ /* pipesrc and dspsize control the size that is scaled from,
+ * which should always be the user's requested size.
+ */
+ if (pipe == 1) {
+ /* FIXME: To make HDMI display with 864x480 (TPO), 480x864 (PYR) or 480x854 (TMD), set the sprite
+ * width/height and souce image size registers with the adjusted mode for pipe B. */
+
+ /* The defined sprite rectangle must always be completely contained within the displayable
+ * area of the screen image (frame buffer). */
+ REG_WRITE(dspsize_reg, ((MIN(mode->crtc_vdisplay, adjusted_mode->crtc_vdisplay) - 1) << 16)
+ | (MIN(mode->crtc_hdisplay, adjusted_mode->crtc_hdisplay) - 1));
+ /* Set the CRTC with encoder mode. */
+ REG_WRITE(pipesrc_reg, ((mode->crtc_hdisplay - 1) << 16)
+ | (mode->crtc_vdisplay - 1));
+ } else {
+ REG_WRITE(dspsize_reg, ((mode->crtc_vdisplay - 1) << 16) | (mode->crtc_hdisplay - 1));
+ REG_WRITE(pipesrc_reg, ((mode->crtc_hdisplay - 1) << 16) | (mode->crtc_vdisplay - 1));
+ }
+
+ REG_WRITE(dsppos_reg, 0);
+
+ if (psb_intel_output)
+ drm_connector_property_get_value(&psb_intel_output->base,
+ dev->mode_config.scaling_mode_property, &scalingType);
+
+ if (scalingType == DRM_MODE_SCALE_NO_SCALE) {
+ /*Moorestown doesn't have register support for centering so we need to
+ mess with the h/vblank and h/vsync start and ends to get centering*/
+ int offsetX = 0, offsetY = 0;
+
+ offsetX = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2;
+ offsetY = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2;
+
+ REG_WRITE(htot_reg, (mode->crtc_hdisplay - 1) |
+ ((adjusted_mode->crtc_htotal - 1) << 16));
+ REG_WRITE(vtot_reg, (mode->crtc_vdisplay - 1) |
+ ((adjusted_mode->crtc_vtotal - 1) << 16));
+ REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - offsetX - 1) |
+ ((adjusted_mode->crtc_hblank_end - offsetX - 1) << 16));
+ REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - offsetX - 1) |
+ ((adjusted_mode->crtc_hsync_end - offsetX - 1) << 16));
+ REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - offsetY - 1) |
+ ((adjusted_mode->crtc_vblank_end - offsetY - 1) << 16));
+ REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - offsetY - 1) |
+ ((adjusted_mode->crtc_vsync_end - offsetY - 1) << 16));
+ } else {
+ REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) |
+ ((adjusted_mode->crtc_htotal - 1) << 16));
+ REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) |
+ ((adjusted_mode->crtc_vtotal - 1) << 16));
+ REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) |
+ ((adjusted_mode->crtc_hblank_end - 1) << 16));
+ REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) |
+ ((adjusted_mode->crtc_hsync_end - 1) << 16));
+ REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) |
+ ((adjusted_mode->crtc_vblank_end - 1) << 16));
+ REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) |
+ ((adjusted_mode->crtc_vsync_end - 1) << 16));
+ }
+
+ /* Flush the plane changes */
+ {
+ struct drm_crtc_helper_funcs *crtc_funcs =
+ crtc->helper_private;
+ crtc_funcs->mode_set_base(crtc, x, y, old_fb);
+ }
+
+ /* setup pipeconf */
+ *pipeconf = PIPEACONF_ENABLE; /* FIXME_JLIU7 REG_READ(pipeconf_reg); */
+
+ /* Set up the display plane register */
+ *dspcntr = REG_READ(dspcntr_reg);
+ *dspcntr |= pipe << DISPPLANE_SEL_PIPE_POS;
+ *dspcntr |= DISPLAY_PLANE_ENABLE;
+/* MDFLD_PO_JLIU7 dspcntr |= DISPPLANE_BOTTOM; */
+/* MDFLD_PO_JLIU7 dspcntr |= DISPPLANE_GAMMA_ENABLE; */
+
+ if (is_mipi2)
+ {
+ goto mrst_crtc_mode_set_exit;
+ }
+/* FIXME JLIU7 Add MDFLD HDMI supports */
+/* FIXME_MDFLD JLIU7 DSIPLL clock *= 8? */
+/* FIXME_MDFLD JLIU7 need to revist for dual MIPI supports */
+ clk = adjusted_mode->clock;
+
+ if (is_hdmi) {
+ if ((dev_priv->ksel == KSEL_CRYSTAL_19) || (dev_priv->ksel == KSEL_BYPASS_19))
+ {
+ refclk = 19200;
+
+ if (is_mipi || is_mipi2)
+ {
+ clk_n = 1, clk_p2 = 8;
+ } else if (is_hdmi) {
+ clk_n = 1, clk_p2 = 10;
+ }
+ } else if (dev_priv->ksel == KSEL_BYPASS_25) {
+ refclk = 25000;
+
+ if (is_mipi || is_mipi2)
+ {
+ clk_n = 1, clk_p2 = 8;
+ } else if (is_hdmi) {
+ clk_n = 1, clk_p2 = 10;
+ }
+ } else if ((dev_priv->ksel == KSEL_BYPASS_83_100) && (dev_priv->core_freq == 166)) {
+ refclk = 83000;
+
+ if (is_mipi || is_mipi2)
+ {
+ clk_n = 4, clk_p2 = 8;
+ } else if (is_hdmi) {
+ clk_n = 4, clk_p2 = 10;
+ }
+ } else if ((dev_priv->ksel == KSEL_BYPASS_83_100) &&
+ (dev_priv->core_freq == 100 || dev_priv->core_freq == 200)) {
+ refclk = 100000;
+ if (is_mipi || is_mipi2)
+ {
+ clk_n = 4, clk_p2 = 8;
+ } else if (is_hdmi) {
+ clk_n = 4, clk_p2 = 10;
+ }
+ }
+
+ if (is_mipi)
+ clk_byte = dev_priv->bpp / 8;
+ else if (is_mipi2)
+ clk_byte = dev_priv->bpp2 / 8;
+
+ clk_tmp = clk * clk_n * clk_p2 * clk_byte;
+
+ PSB_DEBUG_ENTRY("clk = %d, clk_n = %d, clk_p2 = %d. \n", clk, clk_n, clk_p2);
+ PSB_DEBUG_ENTRY("adjusted_mode->clock = %d, clk_tmp = %d. \n", adjusted_mode->clock, clk_tmp);
+
+ ok = mdfldFindBestPLL(crtc, clk_tmp, refclk, &clock);
+ dev_priv->tmds_clock_khz = clock.dot / (clk_n * clk_p2 * clk_byte);
+
+ if (!ok) {
+#if 0 /* FIXME JLIU7 */
+ DRM_ERROR("Couldn't find PLL settings for mode!\n");
+ return;
+#endif /* FIXME JLIU7 */
+ DRM_ERROR
+ ("mdfldFindBestPLL fail in mdfld_crtc_mode_set. \n");
+ } else {
+ m_conv = mdfld_m_converts[(clock.m - MDFLD_M_MIN)];
+
+ PSB_DEBUG_ENTRY("dot clock = %d,"
+ "m = %d, p1 = %d, m_conv = %d. \n", clock.dot, clock.m,
+ clock.p1, m_conv);
+ }
+
+ dpll = REG_READ(dpll_reg);
+
+ if (dpll & DPLL_VCO_ENABLE) {
+ dpll &= ~DPLL_VCO_ENABLE;
+ REG_WRITE(dpll_reg, dpll);
+ REG_READ(dpll_reg);
+
+ /* FIXME jliu7 check the DPLL lock bit PIPEACONF[29] */
+ /* FIXME_MDFLD PO - change 500 to 1 after PO */
+ udelay(500);
+
+ /* reset M1, N1 & P1 */
+ REG_WRITE(fp_reg, 0);
+ dpll &= ~MDFLD_P1_MASK;
+ REG_WRITE(dpll_reg, dpll);
+ /* FIXME_MDFLD PO - change 500 to 1 after PO */
+ udelay(500);
+ }
+
+ /* When ungating power of DPLL, needs to wait 0.5us before enable the VCO */
+ if (dpll & MDFLD_PWR_GATE_EN) {
+ dpll &= ~MDFLD_PWR_GATE_EN;
+ REG_WRITE(dpll_reg, dpll);
+ /* FIXME_MDFLD PO - change 500 to 1 after PO */
+ udelay(500);
+ }
+
+ dpll = 0;
+
+#if 0 /* FIXME revisit later */
+ if ((dev_priv->ksel == KSEL_CRYSTAL_19) || (dev_priv->ksel == KSEL_BYPASS_19) || (dev_priv->ksel == KSEL_BYPASS_25)) {
+ dpll &= ~MDFLD_INPUT_REF_SEL;
+ } else if (dev_priv->ksel == KSEL_BYPASS_83_100) {
+ dpll |= MDFLD_INPUT_REF_SEL;
+ }
+#endif /* FIXME revisit later */
+
+ if (is_hdmi)
+ dpll |= MDFLD_VCO_SEL;
+
+ fp = (clk_n / 2) << 16;
+ fp |= m_conv;
+
+ /* compute bitmask from p1 value */
+ dpll |= (1 << (clock.p1 - 2)) << 17;
+
+#if 0 /* 1080p30 & 720p */
+ dpll = 0x00050000;
+ fp = 0x000001be;
+#endif
+#if 0 /* 480p */
+ dpll = 0x02010000;
+ fp = 0x000000d2;
+#endif
+ } else {
+#if 0 /*DBI_TPO_480x864*/
+ dpll = 0x00020000;
+ fp = 0x00000156;
+#endif /* DBI_TPO_480x864 */ /* get from spec. */
+
+ dpll = 0x00800000;
+ fp = 0x000000c1;
+}
+
+ REG_WRITE(fp_reg, fp);
+ REG_WRITE(dpll_reg, dpll);
+ /* FIXME_MDFLD PO - change 500 to 1 after PO */
+ udelay(500);
+
+ dpll |= DPLL_VCO_ENABLE;
+ REG_WRITE(dpll_reg, dpll);
+ REG_READ(dpll_reg);
+
+ /* wait for DSI PLL to lock */
+ while ((timeout < 20000) && !(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) {
+ udelay(150);
+ timeout ++;
+ }
+
+ if (is_mipi)
+ goto mrst_crtc_mode_set_exit;
+
+ PSB_DEBUG_ENTRY("is_mipi = 0x%x \n", is_mipi);
+
+ REG_WRITE(pipeconf_reg, *pipeconf);
+ REG_READ(pipeconf_reg);
+
+ /* Wait for for the pipe enable to take effect. */
+//FIXME_JLIU7 HDMI mrstWaitForPipeEnable(dev);
+
+ REG_WRITE(dspcntr_reg, *dspcntr);
+ psb_intel_wait_for_vblank(dev);
+
+mrst_crtc_mode_set_exit:
+
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+
+ return 0;
+}
--- /dev/null
+/* copyright (c) 2008, Intel Corporation
+ *
+ * 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 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.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ */
+
+#ifndef _INTEL_DISPLAY_H_
+#define _INTEL_DISPLAY_H_
+
+#include <drm/drmP.h>
+
+bool psb_intel_pipe_has_type(struct drm_crtc *crtc, int type);
+void mdfld__intel_plane_set_alpha(int enable);
+
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2009, Intel Corporation.
+ *
+ * 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 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.
+ *
+ */
+
+#ifndef __INTEL_DRV_H__
+#define __INTEL_DRV_H__
+
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <linux/gpio.h>
+
+#if 0 /* Debug HDMI */
+#include "psb_intel_hdmi_i2c.h"
+#endif
+
+/* Temp Switch */
+#define MDFLD_HDMI_JLIU7_DEBUG_1 1 /* Debug HDMI - Can't enalbe HDMI */
+#define MDFLD_HDMI_JLIU7_1080 0 /* enable & remove it after switching to IAFW v.0.28. */
+/* Must be 0 but need to be revisited afte MDFLD PO */
+#define MDFLD_GCT_JLIU7 0
+
+/* Switch - don't change before PO */
+#define MDFLD_GET_SYNC_BURST 0 /* Consider BURST_MODE when calcaulation H/V sync counts */
+/* MDFLD FEATURE SWITCHES*/
+/* MDFLD MIPI panels only one of them can be set to 1 */
+
+/* MDFLD KSEL only one of them can be set to 1 */
+#define KSEL_CRYSTAL_19_ENABLED 1
+#define KSEL_BYPASS_19_ENABLED 0
+#define KSEL_BYPASS_25_ENABLED 0
+#define KSEL_BYPASS_83_100_ENABLE 0
+
+#define KSEL_CRYSTAL_19 1
+#define KSEL_BYPASS_19 5
+#define KSEL_BYPASS_25 6
+#define KSEL_BYPASS_83_100 7
+/*
+ * MOORESTOWN defines
+ */
+#define DELAY_TIME1 2000 /* 1000 = 1ms */
+
+/*
+ * Display related stuff
+ */
+
+/* store information about an Ixxx DVO */
+/* The i830->i865 use multiple DVOs with multiple i2cs */
+/* the i915, i945 have a single sDVO i2c bus - which is different */
+#define MAX_OUTPUTS 6
+/* maximum connectors per crtcs in the mode set */
+#define INTELFB_CONN_LIMIT 4
+
+#define INTEL_I2C_BUS_DVO 1
+#define INTEL_I2C_BUS_SDVO 2
+
+/* these are outputs from the chip - integrated only
+ * external chips are via DVO or SDVO output */
+#define INTEL_OUTPUT_UNUSED 0
+#define INTEL_OUTPUT_ANALOG 1
+#define INTEL_OUTPUT_DVO 2
+#define INTEL_OUTPUT_SDVO 3
+#define INTEL_OUTPUT_LVDS 4
+#define INTEL_OUTPUT_TVOUT 5
+#define INTEL_OUTPUT_HDMI 6
+#define INTEL_OUTPUT_MIPI 7
+#define INTEL_OUTPUT_MIPI2 8
+
+#define INTEL_DVO_CHIP_NONE 0
+#define INTEL_DVO_CHIP_LVDS 1
+#define INTEL_DVO_CHIP_TMDS 2
+#define INTEL_DVO_CHIP_TVOUT 4
+
+enum mipi_panel_type {
+ NSC_800X480 = 1,
+ LGE_480X1024 = 2,
+ TPO_864X480 = 3
+};
+
+/**
+ * Hold information useally put on the device driver privates here,
+ * since it needs to be shared across multiple of devices drivers privates.
+*/
+struct psb_intel_mode_device {
+
+ /*
+ * Abstracted memory manager operations
+ */
+ void *(*bo_from_handle) (struct drm_device *dev,
+ struct drm_file *file_priv,
+ unsigned int handle);
+ size_t(*bo_size) (struct drm_device *dev, void *bo);
+ size_t(*bo_offset) (struct drm_device *dev, void *bo);
+ int (*bo_pin_for_scanout) (struct drm_device *dev, void *bo);
+ int (*bo_unpin_for_scanout) (struct drm_device *dev, void *bo);
+
+ /*
+ * Cursor
+ */
+ int cursor_needs_physical;
+
+ /*
+ * LVDS info
+ */
+ int backlight_duty_cycle; /* restore backlight to this value */
+ bool panel_wants_dither;
+ struct drm_display_mode *panel_fixed_mode;
+ struct drm_display_mode *panel_fixed_mode2;
+ struct drm_display_mode *vbt_mode; /* if any */
+
+ uint32_t saveBLC_PWM_CTL;
+};
+
+struct psb_intel_i2c_chan {
+ /* for getting at dev. private (mmio etc.) */
+ struct drm_device *drm_dev;
+ u32 reg; /* GPIO reg */
+ struct i2c_adapter adapter;
+ struct i2c_algo_bit_data algo;
+ u8 slave_addr;
+};
+
+struct psb_intel_output {
+ struct drm_connector base;
+
+ struct drm_encoder enc;
+ int type;
+#if 1 /*MDFLD_HDMI_JLIU7*/
+ struct i2c_adapter *hdmi_i2c_adapter; /* for control functions */
+#endif
+ struct psb_intel_i2c_chan *i2c_bus; /* for control functions */
+ bool load_detect_temp;
+ void *dev_priv;
+
+ struct psb_intel_mode_device *mode_dev;
+
+};
+
+struct psb_intel_crtc_state {
+ uint32_t saveDSPCNTR;
+ uint32_t savePIPECONF;
+ uint32_t savePIPESRC;
+ uint32_t saveDPLL;
+ uint32_t saveFP0;
+ uint32_t saveFP1;
+ uint32_t saveHTOTAL;
+ uint32_t saveHBLANK;
+ uint32_t saveHSYNC;
+ uint32_t saveVTOTAL;
+ uint32_t saveVBLANK;
+ uint32_t saveVSYNC;
+ uint32_t saveDSPSTRIDE;
+ uint32_t saveDSPSIZE;
+ uint32_t saveDSPPOS;
+ uint32_t saveDSPBASE;
+ uint32_t savePalette[256];
+};
+
+struct psb_intel_crtc {
+ struct drm_crtc base;
+ int pipe;
+ int plane;
+ uint32_t cursor_addr;
+ u8 lut_r[256], lut_g[256], lut_b[256];
+ u8 lut_adj[256];
+ struct psb_intel_framebuffer *fbdev_fb;
+ /* a mode_set for fbdev users on this crtc */
+ struct drm_mode_set mode_set;
+
+ /* current bo we scanout from */
+ void *scanout_bo;
+
+ /* current bo we cursor from */
+ void *cursor_bo;
+
+ struct drm_display_mode saved_mode;
+ struct drm_display_mode saved_adjusted_mode;
+
+ struct psb_intel_mode_device *mode_dev;
+
+ /*crtc mode setting flags*/
+ u32 mode_flags;
+
+ /* Saved Crtc HW states */
+ struct psb_intel_crtc_state *crtc_state;
+ void *pending_flip;
+};
+
+#define to_psb_intel_crtc(x) \
+ container_of(x, struct psb_intel_crtc, base)
+#define to_psb_intel_output(x) \
+ container_of(x, struct psb_intel_output, base)
+#define enc_to_psb_intel_output(x) \
+ container_of(x, struct psb_intel_output, enc)
+#define to_psb_intel_framebuffer(x) \
+ container_of(x, struct psb_intel_framebuffer, base)
+
+extern void psb_intel_crtc_init(struct drm_device *dev, int pipe,
+ struct psb_intel_mode_device *mode_dev);
+extern void psb_intel_crt_init(struct drm_device *dev);
+extern void psb_intel_dvo_init(struct drm_device *dev);
+extern void psb_intel_tv_init(struct drm_device *dev);
+extern void mid_dsi_init(struct drm_device *dev,
+ struct psb_intel_mode_device *mode_dev, int dsi_num);
+extern void mdfld_hdmi_init(struct drm_device *dev,
+ struct psb_intel_mode_device *mode_dev);
+extern void mdfld_wld_init(struct drm_device *dev);
+
+extern void psb_intel_crtc_load_lut(struct drm_crtc *crtc);
+extern void psb_intel_encoder_prepare(struct drm_encoder *encoder);
+extern void psb_intel_encoder_commit(struct drm_encoder *encoder);
+
+extern struct drm_encoder *psb_intel_best_encoder(struct drm_connector
+ *connector);
+
+extern void psb_intel_wait_for_vblank(struct drm_device *dev);
+extern int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern struct drm_connector *psb_intel_sdvo_find(struct drm_device *dev,
+ int sdvoB);
+extern int intelfb_probe(struct drm_device *dev);
+extern int intelfb_remove(struct drm_device *dev,
+ struct drm_framebuffer *fb);
+extern void mdfld_disable_crtc (struct drm_device *dev, int pipe);
+
+extern void mdfld_dbi_update_fb (struct drm_device *dev, int pipe);
+extern void mdfld_dbi_enter_dsr (struct drm_device *dev);
+extern void mdfld_dbi_exit_dsr (struct drm_device *dev, u32 update_src);
+extern void mdfld_dbi_update_panel (struct drm_device *dev, int pipe);
+extern void mdfld_dsi_brightness_control (struct drm_device *dev, int pipe, int level);
+extern void mdfld_dsi_gen_fifo_ready (struct drm_device *dev, u32 gen_fifo_stat_reg, u32 fifo_stat);
+extern void mdfld_dsi_dbi_CB_ready (struct drm_device *dev, u32 mipi_command_address_reg, u32 gen_fifo_stat_reg);
+extern void mdfldWaitForPipeDisable(struct drm_device *dev, int pipe);
+extern void mdfldWaitForPipeEnable(struct drm_device *dev, int pipe);
+
+#endif /* __INTEL_DRV_H__ */
--- /dev/null
+/*
+ * Copyright © 2006-2007 Intel 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 (including the next
+ * paragraph) 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.
+ *
+ * Authors:
+ * jim liu <jim.liu@intel.com>
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_edid.h>
+#include "psb_intel_drv.h"
+#include "psb_drv.h"
+#include "psb_intel_reg.h"
+#include "psb_intel_hdmi_reg.h"
+#include "psb_intel_hdmi_edid.h"
+#include "psb_intel_hdmi.h"
+#include "mdfld_dsi_output.h"
+#include "mdfld_hdmi_audio_if.h"
+#include "mdfld_msic.h"
+#include "mdfld_hdcp_if.h"
+#include <linux/pm_runtime.h>
+#include <asm/intel_scu_ipc.h>
+
+/* FIXME_MDFLD HDMI EDID supports */
+
+static char EDID_Samsung[EDID_LENGTH + HDMI_CEA_EDID_BLOCK_SIZE] =
+{
+ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x4C, 0x2D, 0x10, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x14, 0x11, 0x01, 0x03, 0x80, 0x10, 0x09, 0x8C, 0x0A, 0xE2, 0xBD, 0xA1, 0x5B, 0x4A, 0x98, 0x24,
+ 0x15, 0x47, 0x4A, 0x20, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1D, 0x00, 0x72, 0x51, 0xD0, 0x1E, 0x20, 0x6E, 0x28,
+ 0x55, 0x00, 0xA0, 0x5A, 0x00, 0x00, 0x00, 0x1E, 0x01, 0x1D, 0x00, 0xBC, 0x52, 0xD0, 0x1E, 0x20,
+ 0xB8, 0x28, 0x55, 0x40, 0xA0, 0x5A, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x31,
+ 0x3D, 0x0F, 0x2E, 0x08, 0x00, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xFC,
+ 0x00, 0x53, 0x41, 0x4D, 0x53, 0x55, 0x4E, 0x47, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0xB3,
+ 0x02, 0x03, 0x1A, 0x71, 0x46, 0x84, 0x13, 0x05, 0x14, 0x03, 0x12, 0x23, 0x09, 0x07, 0x07, 0x83,
+ 0x01, 0x00, 0x00, 0x66, 0x03, 0x0C, 0x00, 0x10, 0x00, 0x80, 0x01, 0x1D, 0x80, 0x18, 0x71, 0x1C,
+ 0x16, 0x20, 0x58, 0x2C, 0x25, 0x00, 0xA0, 0x5A, 0x00, 0x00, 0x00, 0x9E, 0x01, 0x1D, 0x80, 0xD0,
+ 0x72, 0x1C, 0x16, 0x20, 0x10, 0x2C, 0x25, 0x80, 0xA0, 0x5A, 0x00, 0x00, 0x00, 0x9E, 0x8C, 0x0A,
+ 0xD0, 0x8A, 0x20, 0xE0, 0x2D, 0x10, 0x10, 0x3E, 0x96, 0x00, 0xA0, 0x5A, 0x00, 0x00, 0x00, 0x18,
+ 0x8C, 0x0A, 0xD0, 0x90, 0x20, 0x40, 0x31, 0x20, 0x0C, 0x40, 0x55, 0x00, 0xA0, 0x5A, 0x00, 0x00,
+ 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0
+};
+
+static char EDID_Samsung_2493HM[EDID_LENGTH] =
+{
+ 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x4c, 0x2d, 0x68, 0x03, 0x34, 0x32, 0x49, 0x4b,
+ 0x0c, 0x12, 0x01, 0x03, 0x0e, 0x34, 0x20, 0xa0, 0x2a, 0xef, 0x91, 0xa3, 0x54, 0x4c, 0x9b, 0x26,
+ 0x0f, 0x50, 0x54, 0xbf, 0xef, 0x80, 0xa9, 0x40, 0x81, 0x80, 0x81, 0x40, 0x71, 0x4f, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x28, 0x3c, 0x80, 0xa0, 0x70, 0xb0, 0x23, 0x40, 0x30, 0x20,
+ 0x36, 0x00, 0x06, 0x44, 0x21, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x38, 0x4b, 0x1e,
+ 0x51, 0x11, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x53,
+ 0x79, 0x6e, 0x63, 0x4d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x0a, 0x20, 0x20, 0x00, 0x00, 0x00, 0xff,
+ 0x00, 0x48, 0x56, 0x52, 0x51, 0x33, 0x30, 0x30, 0x35, 0x35, 0x30, 0x0a, 0x20, 0x20, 0x00, 0x20
+};
+
+static char EDID_Dell[EDID_LENGTH + HDMI_CEA_EDID_BLOCK_SIZE] =
+{
+ 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x10, 0xac, 0x5d, 0xa0, 0x55, 0x36, 0x4e, 0x32,
+ 0x23, 0x14, 0x01, 0x03, 0x80, 0x35, 0x1e, 0x78, 0xee, 0xee, 0x91, 0xa3, 0x54, 0x4c, 0x99, 0x26,
+ 0x0f, 0x50, 0x54, 0xa5, 0x4b, 0x00, 0x71, 0x4f, 0x81, 0x80, 0xd1, 0xc0, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c,
+ 0x45, 0x00, 0x13, 0x2b, 0x21, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0xff, 0x00, 0x58, 0x31, 0x37,
+ 0x35, 0x52, 0x30, 0x38, 0x51, 0x32, 0x4e, 0x36, 0x55, 0x0a, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x44,
+ 0x45, 0x4c, 0x4c, 0x20, 0x53, 0x54, 0x32, 0x34, 0x31, 0x30, 0x0a, 0x20, 0x00, 0x00, 0x00, 0xfd,
+ 0x00, 0x32, 0x4c, 0x1e, 0x53, 0x11, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0x6d,
+ 0x02, 0x03, 0x1f, 0xf1, 0x4c, 0x90, 0x05, 0x04, 0x03, 0x02, 0x07, 0x16, 0x01, 0x14, 0x1f, 0x12,
+ 0x13, 0x23, 0x09, 0x07, 0x07, 0x65, 0x03, 0x0c, 0x00, 0x10, 0x00, 0x83, 0x01, 0x00, 0x00, 0x02,
+ 0x3a, 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c, 0x45, 0x00, 0x13, 0x2b, 0x21, 0x00, 0x00,
+ 0x1e, 0x01, 0x1d, 0x80, 0x18, 0x71, 0x1c, 0x16, 0x20, 0x58, 0x2c, 0x25, 0x00, 0x13, 0x2b, 0x21,
+ 0x00, 0x00, 0x9e, 0x01, 0x1d, 0x00, 0x72, 0x51, 0xd0, 0x1e, 0x20, 0x6e, 0x28, 0x55, 0x00, 0x13,
+ 0x2b, 0x21, 0x00, 0x00, 0x1e, 0x8c, 0x0a, 0xd0, 0x8a, 0x20, 0xe0, 0x2d, 0x10, 0x10, 0x3e, 0x96,
+ 0x00, 0x13, 0x2b, 0x21, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b
+};
+
+static char EDID_Toshiba_32RV525RZ[EDID_LENGTH + HDMI_CEA_EDID_BLOCK_SIZE] =
+{
+ 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x10, 0xac, 0x5d, 0xa0, 0x55, 0x36, 0x4e, 0x32,
+ 0x23, 0x14, 0x01, 0x03, 0x80, 0x35, 0x1e, 0x78, 0xee, 0xee, 0x91, 0xa3, 0x54, 0x4c, 0x99, 0x26,
+ 0x0f, 0x50, 0x54, 0xa5, 0x4b, 0x00, 0x71, 0x4f, 0x81, 0x80, 0xd1, 0xc0, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c,
+ 0x45, 0x00, 0x13, 0x2b, 0x21, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0xff, 0x00, 0x58, 0x31, 0x37,
+ 0x35, 0x52, 0x30, 0x38, 0x51, 0x32, 0x4e, 0x36, 0x55, 0x0a, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x44,
+ 0x45, 0x4c, 0x4c, 0x20, 0x53, 0x54, 0x32, 0x34, 0x31, 0x30, 0x0a, 0x20, 0x00, 0x00, 0x00, 0xfd,
+ 0x00, 0x32, 0x4c, 0x1e, 0x53, 0x11, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0x6d,
+ 0x02, 0x03, 0x1f, 0xf1, 0x4c, 0x90, 0x05, 0x04, 0x03, 0x02, 0x07, 0x16, 0x01, 0x14, 0x1f, 0x12,
+ 0x13, 0x23, 0x09, 0x07, 0x07, 0x65, 0x03, 0x0c, 0x00, 0x10, 0x00, 0x83, 0x01, 0x00, 0x00, 0x02,
+ 0x3a, 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c, 0x45, 0x00, 0x13, 0x2b, 0x21, 0x00, 0x00,
+ 0x1e, 0x01, 0x1d, 0x80, 0x18, 0x71, 0x1c, 0x16, 0x20, 0x58, 0x2c, 0x25, 0x00, 0x13, 0x2b, 0x21,
+ 0x00, 0x00, 0x9e, 0x01, 0x1d, 0x00, 0x72, 0x51, 0xd0, 0x1e, 0x20, 0x6e, 0x28, 0x55, 0x00, 0x13,
+ 0x2b, 0x21, 0x00, 0x00, 0x1e, 0x8c, 0x0a, 0xd0, 0x8a, 0x20, 0xe0, 0x2d, 0x10, 0x10, 0x3e, 0x96,
+ 0x00, 0x13, 0x2b, 0x21, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b
+};
+
+static char EDID_Toshiba_Regza[EDID_LENGTH + HDMI_CEA_EDID_BLOCK_SIZE] =
+{
+ 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x52, 0x62, 0x05, 0x02, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x11, 0x01, 0x03, 0x80, 0x69, 0x3b, 0x78, 0x0a, 0x0d, 0xc9, 0xa0, 0x57, 0x47, 0x98, 0x27,
+ 0x12, 0x48, 0x4c, 0x20, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c,
+ 0x45, 0x00, 0xc4, 0x8e, 0x21, 0x00, 0x00, 0x1e, 0x8c, 0x0a, 0xd0, 0x8a, 0x20, 0xe0, 0x2d, 0x10,
+ 0x10, 0x3e, 0x96, 0x00, 0xc4, 0x8e, 0x21, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x54,
+ 0x53, 0x42, 0x2d, 0x54, 0x56, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfd,
+ 0x00, 0x17, 0x3d, 0x0f, 0x44, 0x0f, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0x03,
+ 0x02, 0x03, 0x20, 0x77, 0x4a, 0x90, 0x05, 0x04, 0x03, 0x07, 0x02, 0x06, 0x01, 0x20, 0x22, 0x23,
+ 0x09, 0x07, 0x07, 0x6c, 0x03, 0x0c, 0x00, 0x30, 0x00, 0x00, 0x1e, 0xc0, 0x2b, 0x2b, 0x33, 0x33,
+ 0x01, 0x1d, 0x00, 0x72, 0x51, 0xd0, 0x1e, 0x20, 0x6e, 0x28, 0x55, 0x00, 0xc4, 0x8e, 0x21, 0x00,
+ 0x00, 0x1e, 0x8c, 0x0a, 0xa0, 0x14, 0x51, 0xf0, 0x16, 0x00, 0x26, 0x7c, 0x43, 0x00, 0xc4, 0x8e,
+ 0x21, 0x00, 0x00, 0x98, 0x8c, 0x0a, 0xd0, 0x8a, 0x20, 0xe0, 0x2d, 0x10, 0x10, 0x3e, 0x96, 0x00,
+ 0x13, 0x8e, 0x21, 0x00, 0x00, 0x18, 0x8c, 0x0a, 0xa0, 0x14, 0x51, 0xf0, 0x16, 0x00, 0x26, 0x7c,
+ 0x43, 0x00, 0x13, 0x8e, 0x21, 0x00, 0x00, 0x98, 0x01, 0x1d, 0x80, 0x18, 0x71, 0x1c, 0x16, 0x20,
+ 0x58, 0x2c, 0x25, 0x00, 0xc4, 0x8e, 0x21, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb3
+};
+
+static struct hdmi_edid_info mdfld_hdmi_edid[] = {
+ { HDMI_EDID_INFO("SAMSUNG", EDID_Samsung) },
+ { HDMI_EDID_INFO("SAMSUNG_2493HM", EDID_Samsung_2493HM) },
+ { HDMI_EDID_INFO("DELL", EDID_Dell) },
+ { HDMI_EDID_INFO("TOSHIBA_32RV525RZ", EDID_Toshiba_32RV525RZ) },
+ { HDMI_EDID_INFO("TOSHIBA_REGZA", EDID_Toshiba_Regza) },
+};
+
+#if 1 /*FIXME_MDFLD_HDMI remove it later */
+static void mdfld_hdmi_mode_set(struct drm_encoder *encoder,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ struct drm_device *dev = encoder->dev;
+ struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
+ struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv;
+ u32 hdmib, hdmi_phy_misc;
+
+ PSB_DEBUG_ENTRY("\n");
+
+ /* Set panel fitting. */
+ if ((adjusted_mode->hdisplay != mode->hdisplay)
+ || (adjusted_mode->vdisplay != mode->vdisplay))
+ REG_WRITE(PFIT_CONTROL, PFIT_ENABLE | PFIT_PIPE_SELECT_B);
+
+ hdmib = REG_READ(hdmi_priv->hdmib_reg) | HDMIB_PORT_EN | HDMIB_PIPE_B_SELECT | HDMIB_NULL_PACKET;
+ hdmi_phy_misc = REG_READ(HDMIPHYMISCCTL) & ~HDMI_PHY_POWER_DOWN;
+
+ REG_WRITE(HDMIPHYMISCCTL, hdmi_phy_misc);
+ REG_WRITE(hdmi_priv->hdmib_reg, hdmib);
+ REG_READ(hdmi_priv->hdmib_reg);
+}
+
+static bool mdfld_hdmi_mode_fixup(struct drm_encoder *encoder,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ struct drm_device *dev = encoder->dev;
+ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(encoder->crtc);
+ PSB_DEBUG_ENTRY("hdisplay = %d, vdisplay = %d. a_hdisplay = %d, a_vdisplay = %d.\n", mode->hdisplay, mode->vdisplay, adjusted_mode->hdisplay, adjusted_mode->vdisplay);
+
+ /* Should never happen!! */
+ if (psb_intel_crtc->pipe != 1) {
+ printk(KERN_ERR
+ "Only support HDMI on pipe B on MID \n");
+ }
+
+ /* FIXME: To make HDMI display with 1920x1080,
+ * in 864x480 (TPO), 480x864 (PYR) or 480x854 (TMD) fixed mode. */
+ if ((mode->hdisplay == 864 && mode->vdisplay == 480)
+ || (mode->hdisplay == 854 && mode->vdisplay == 480)
+ || (mode->hdisplay == 480 && mode->vdisplay == 864)
+ || (mode->hdisplay == 480 && mode->vdisplay == 854)) {
+ adjusted_mode->hdisplay = 1920;
+ adjusted_mode->htotal = 2200;
+ adjusted_mode->hsync_start = 2008;
+ adjusted_mode->hsync_end = 2052;
+ adjusted_mode->hskew = 0;
+ adjusted_mode->vdisplay = 1080;
+ adjusted_mode->vtotal = 1125;
+ adjusted_mode->vsync_start = 1084;
+ adjusted_mode->vsync_end = 1089;
+ adjusted_mode->vscan = 0;
+ adjusted_mode->clock = 148500;
+
+ /* Apply the adjusted mode to CRTC mode setting parameters. */
+ drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
+ }
+
+#if 0 /* MDFLD_HDMI_JLIU7_HACKS */
+ if (mode->hdisplay == 864 && mode->vdisplay == 480) {
+ adjusted_mode->hdisplay = 0x500;
+ adjusted_mode->htotal = 0x672;
+ adjusted_mode->hsync_start = 0x56e;
+ adjusted_mode->hsync_end = 0x596;
+ adjusted_mode->vdisplay = 0x2d0;
+ adjusted_mode->vtotal = 0x2ee;
+ adjusted_mode->vsync_start = 0x2d5;
+ adjusted_mode->vsync_end = 0x2da;
+ drm_mode_set_crtcinfo(adjusted_mode,
+ CRTC_INTERLACE_HALVE_V);
+ }
+#endif /* MDFLD_HDMI_JLIU7_HACKS */ /* Debug HDMI - Can't enalbe HDMI */
+#if 0 // MDFLD_HDMI_JLIU7_HACKS /* Debug HDMI - Can't enalbe HDMI */
+#if 1 /* 720p - Adeel */
+ adjusted_mode->hdisplay = 0x500;
+ adjusted_mode->htotal = 0x672;
+ adjusted_mode->hsync_start = 0x56e;
+ adjusted_mode->hsync_end = 0x596;
+ adjusted_mode->vdisplay = 0x2d0;
+ adjusted_mode->vtotal = 0x2ee;
+ adjusted_mode->vsync_start = 0x2d5;
+ adjusted_mode->vsync_end = 0x2da;
+#endif
+
+#if 0 /* 1080p - Brian */
+ adjusted_mode->hdisplay = 0x780;
+ adjusted_mode->htotal = 0x898;
+ adjusted_mode->hsync_start = 0x7d8;
+ adjusted_mode->hsync_end = 0x804;
+ adjusted_mode->vdisplay = 0x438;
+ adjusted_mode->vtotal = 0x464;
+ adjusted_mode->vsync_start = 0x43c;
+ adjusted_mode->vsync_end = 0x446;
+#endif
+#if 0 /* 1080p - Adeel */
+ adjusted_mode->hdisplay = 0x780;
+ adjusted_mode->htotal = 0xabe;
+ adjusted_mode->hsync_start = 0x9fe;
+ adjusted_mode->hsync_end = 0xa2a;
+ adjusted_mode->vdisplay = 0x438;
+ adjusted_mode->vtotal = 0x465;
+ adjusted_mode->vsync_start = 0x43c;
+ adjusted_mode->vsync_end = 0x441;
+#endif
+
+
+#if 0 /* 480p - Adeel */
+ adjusted_mode->hdisplay = 0x280;
+ adjusted_mode->htotal = 0x320;
+ adjusted_mode->hsync_start = 0x290;
+ adjusted_mode->hsync_end = 0x2f0;
+ adjusted_mode->vdisplay = 0x1e0;
+ adjusted_mode->vtotal = 0x20d;
+ adjusted_mode->vsync_start = 0x1ea;
+ adjusted_mode->vsync_end = 0x1ec;
+#endif
+
+#if 0 /* 480p - icdk */
+ adjusted_mode->hdisplay = 0x280;
+ adjusted_mode->htotal = 0x35a;
+ adjusted_mode->hsync_start = 0x2e0;
+ adjusted_mode->hsync_end = 0x31e;
+ adjusted_mode->vdisplay = 0x1e0;
+ adjusted_mode->vtotal = 0x20e;
+ adjusted_mode->vsync_start = 0x1ea;
+ adjusted_mode->vsync_end = 0x1ec;
+#endif
+#if 0 /* 720p - Adeel */
+ REG_WRITE(htot_reg, 0x067104ff);
+ REG_WRITE(hblank_reg, 0x067104ff);
+ REG_WRITE(hsync_reg, 0x0595056d);
+ REG_WRITE(vtot_reg, 0x02ed02cf);
+ REG_WRITE(vblank_reg, 0x02ed02cf);
+ REG_WRITE(vsync_reg, 0x02d902d4);
+#endif
+#if 0 /* 1080p - Brian */
+ REG_WRITE(htot_reg, 0x0897077f);
+ REG_WRITE(hblank_reg, 0x0897077f);
+ REG_WRITE(hsync_reg, 0x080307d7);
+ REG_WRITE(vtot_reg, 0x04630437);
+ REG_WRITE(vblank_reg, 0x04630437);
+ REG_WRITE(vsync_reg, 0x0445043b);
+#endif
+
+#if 0 /* 1080p - Adeel */
+ REG_WRITE(htot_reg, 0x0abd077f);
+ REG_WRITE(hblank_reg, 0x0abd077f);
+ REG_WRITE(hsync_reg, 0x0a2909fd);
+ REG_WRITE(vtot_reg, 0x04640437);
+ REG_WRITE(vblank_reg, 0x04640437);
+ REG_WRITE(vsync_reg, 0x0440043b);
+#endif
+
+
+#if 0 /* 480p - Adeel */
+ REG_WRITE(htot_reg, 0x031f027f);
+ REG_WRITE(hblank_reg, 0x031f027f);
+ REG_WRITE(hsync_reg, 0x02ef028f);
+ REG_WRITE(vtot_reg, 0x020c01df);
+ REG_WRITE(vblank_reg, 0x020c01df);
+ REG_WRITE(vsync_reg, 0x01eb01e9);
+#endif
+
+#if 0 /* 480p - icdk */
+ REG_WRITE(htot_reg, 0x0359027f);
+ REG_WRITE(hblank_reg, 0x0359027f);
+ REG_WRITE(hsync_reg, 0x031d02df);
+ REG_WRITE(vtot_reg, 0x020d01df);
+ REG_WRITE(vblank_reg, 0x020d01df);
+ REG_WRITE(vsync_reg, 0x01eb01e9);
+#endif
+ drm_mode_set_crtcinfo(adjusted_mode,
+ CRTC_INTERLACE_HALVE_V);
+#endif /* MDFLD_HDMI_JLIU7_HACKS */ /* Debug HDMI - Can't enalbe HDMI */
+ return true;
+}
+
+
+static void mdfld_hdmi_dpms(struct drm_encoder *encoder, int mode)
+{
+ struct drm_device *dev = encoder->dev;
+ struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
+ struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv;
+ u32 hdmib, hdmi_phy_misc;
+
+ PSB_DEBUG_ENTRY("%s \n", mode == DRM_MODE_DPMS_ON ? "on" : "off");
+
+ hdmib = REG_READ(hdmi_priv->hdmib_reg) | HDMIB_PIPE_B_SELECT | HDMIB_NULL_PACKET;
+ hdmi_phy_misc = REG_READ(HDMIPHYMISCCTL);
+
+ if (mode != DRM_MODE_DPMS_ON) {
+ REG_WRITE(hdmi_priv->hdmib_reg, hdmib & ~HDMIB_PORT_EN);
+ REG_WRITE(HDMIPHYMISCCTL, hdmi_phy_misc | HDMI_PHY_POWER_DOWN);
+ } else {
+ REG_WRITE(HDMIPHYMISCCTL, hdmi_phy_misc & ~HDMI_PHY_POWER_DOWN);
+ REG_WRITE(hdmi_priv->hdmib_reg, hdmib | HDMIB_PORT_EN);
+ }
+ REG_READ(hdmi_priv->hdmib_reg);
+}
+
+static void mdfld_hdmi_save(struct drm_connector *connector)
+{
+ struct drm_device *dev = connector->dev;
+ struct psb_intel_output *output = to_psb_intel_output(connector);
+ struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv;
+
+ PSB_DEBUG_ENTRY("\n");
+
+ hdmi_priv->save_HDMIB = REG_READ(hdmi_priv->hdmib_reg);
+}
+
+static void mdfld_hdmi_restore(struct drm_connector *connector)
+{
+ struct drm_device *dev = connector->dev;
+ struct psb_intel_output *output = to_psb_intel_output(connector);
+ struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv;
+
+ PSB_DEBUG_ENTRY("\n");
+
+ REG_WRITE(hdmi_priv->hdmib_reg, hdmi_priv->save_HDMIB);
+ REG_READ(hdmi_priv->hdmib_reg);
+}
+
+/* HDMI DIP related stuff */
+static int mdfld_hdmi_get_cached_edid_block(struct drm_connector *connector, uint32_t num_block, uint8_t *edid_block, uint32_t size)
+{
+ struct drm_display_info *displayinfo = &(connector->display_info);
+ if (num_block >= MAX_EDID_BLOCKS)
+ {
+ DRM_ERROR("mdfld_hdmi_get_cached_edid_block() - Invalid EDID block\n");
+ return 0;
+ }
+ edid_block = &displayinfo->raw_edid[EDID_BLOCK_SIZE*num_block];
+ return 1;
+}
+
+/////////////////////////////////////////////////////////////////////////
+// INTHDMIENCODER_CreateEELDPacket():
+// This function parses v1.3 base EDID and CEA-861b EDID Timing Extension
+// Version3 and creates EELD (Enhanced EDID Like Data) packet. This EELD data contains
+// audio configuration information and other details read EDID.This can also contain Vendor specific Data
+//
+/////////////////////////////////////////////////////////////////////////
+static int mdfld_hdmi_create_eeld_packet(struct drm_connector *connector)
+{
+ struct psb_intel_output *output = to_psb_intel_output(connector);
+ struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv;
+ uint8_t ucEdidBlock[128];
+ hdmi_eeld_t *pEEld = NULL;
+ baseedid_1_x_t *pEdid = NULL;
+ ce_edid_t *pCeEdid = NULL;
+ int dwNumOfBytes = 0;
+ int sizeOfCEADataBlock = 0;
+ uint8_t * pDataBlock = NULL;
+ edid_dtd_timing_t *pDTD = NULL;
+ uint8_t *pData = NULL;
+ uint8_t ucDataBlockTag = 0;
+ cea_861b_adb_t *pADB = NULL;
+ uint8_t i = 0;
+ uint8_t j = 0;
+ uint8_t * pSADBlocks = NULL;
+ uint8_t * pCurrentSADBlocks = NULL;
+ uint32_t ulNumSADBytes = 0;
+ //vsdb_byte6_to_byte8_t *pVSDB = NULL;
+ uint32_t ulIndex = 0;
+ //uint8_t b48kHzCADPresent = false;
+
+ pEEld = (hdmi_eeld_t *) &hdmi_priv->eeld;
+
+ // Fill Version info
+ pEEld->cea_edid_rev_id = HDMI_EELD_CEA_EDID_VERSION;
+ pEEld->eld_ver = HDMI_EELD_VERSION;
+
+ // Fill BaseLine ELD length
+ // This is 80 bytes as per EELD proposal
+ pEEld->baseline_eld_length = HDMI_EELD_BASELINE_DATA_LENGTH;
+
+ //Zero out EDID block buffer
+ memset(ucEdidBlock, 0, sizeof(ucEdidBlock));
+
+ // Get Extn EDID
+ if(!mdfld_hdmi_get_cached_edid_block(connector, 1, ucEdidBlock, EDID_BLOCK_SIZE))
+ {
+ return 0;
+ }
+
+ pCeEdid = (ce_edid_t *) ucEdidBlock;
+
+ //allocate memory (48 bytes) for SAD Blocks buffer
+ pSADBlocks = kcalloc(1, 48, GFP_KERNEL);
+
+ if(pSADBlocks == NULL)
+ {
+ DRM_ERROR("mdfld_hdmi_create_eld_packaet() - Failed to allocate mem for pSADBlocks\n");
+ return 0;
+ }
+
+ pCurrentSADBlocks = pSADBlocks;
+
+ // Now pull out data from CEA Extension EDID
+ // If Offset <= 4, we will not have CEA DataBlocks
+ if(pCeEdid->ucDTDOffset > CEA_EDID_HEADER_SZIE)
+ {
+ sizeOfCEADataBlock = pCeEdid->ucDTDOffset - CEA_EDID_HEADER_SZIE;
+
+ pDataBlock = (uint8_t *)pCeEdid;
+
+ // skip header (first 4 bytes) in CEA EDID Timing Extension
+ // and set pointer to start of DataBlocks collection
+ pDataBlock += CEA_EDID_HEADER_SZIE;
+
+ // General Format of CEA Data Block Collection
+ // -----------+--------------------+-----------------------------------------+
+ // |Byte# |bits5-7 | bits 0-4 |
+ // -----------|--------------------+-----------------------------------------+
+ // | 1 | Video Tag |Length = total #of video bytes following |
+ // | | Code |this byte (L1) |
+ // |--------------------+-----------------------------------------+
+ // Video | 2 | CEA Short Video Descriptor 1 |
+ // Data |--------+-----------------------------------------------------|
+ // Block | 3 | CEA Short Video Descriptor 2 |
+ // |--------+-----------------------------------------------------|
+ // | ... | ... |
+ // |--------------------------------------------------------------+
+ // | 1+L1 | CEA Short Video Descriptor L1 |
+ // -----------+--------------------+-----------------------------------------+
+ // | 2+L1 | Audio Tag |Length = total #of audio bytes following |
+ // | | Code |this byte (L2) |
+ // |--------------------+-----------------------------------------+
+ // Audio | 3+L1 | |
+ // Data |--------+ |
+ // Block | 4+L1 | CEA Short Audio Descriptor 1 |
+ // |--------+ |
+ // | 5+L1 | |
+ // |--------------------------------------------------------------+
+ // | ... | |
+ // | | |
+ // | | |
+ // | ... | |
+ // |---------------------------------------------------------------
+ // |L1+L2 | |
+ // |--------| |
+ // |1+L1+L2 | CEA Short Audio Descriptor L2/3 |
+ // |--------| |
+ // |2+L1+L2 | |
+ // -----------+--------------------------------------------------------------+
+ // |3+L1+L2 | Speaker |Length = total #of SA bytes following |
+ // | | Tag Code |this byte (L1) |
+ // Speaker |--------------------------------------------------------------+
+ // Allocation|4+L1+L2 | |
+ // Data |--------| |
+ // Block |5+L1+L2 | Speaker Allocation Data Block Payload(3 bytes) |
+ // |--------| |
+ // |6+L1+L2 | |
+ // -----------+--------------------------------------------------------------+
+ // |7+L1+L2 | VSDB Tag |Length = total #of VSDB bytes following |
+ // | | Code |this byte (L1) |
+ // Vendor |--------------------------------------------------------------+
+ // Specific |8+L1+L2 | |
+ // Data |--------| |
+ // Block |9+L1+L2 | 24-bit IEEE Registration Identifier (LSB first) |
+ // |--------| |
+ // |10+L1+L2| |
+ // |--------------------------------------------------------------+
+ // | ... | Vendor Specific Data block Payload |
+ // -----------+--------------------------------------------------------------+
+
+ while(sizeOfCEADataBlock > 0)
+ {
+ // Get the Size of CEA DataBlock in bytes and TAG
+ dwNumOfBytes = *pDataBlock & CEA_DATABLOCK_LENGTH_MASK;
+ ucDataBlockTag = (*pDataBlock & CEA_DATABLOCK_TAG_MASK) >> 5;
+
+ switch(ucDataBlockTag)
+ {
+ case CEA_AUDIO_DATABLOCK:
+ // move beyond tag/length byte
+ ++pDataBlock;
+ for (i = 0; i < (dwNumOfBytes / 3); ++i, pDataBlock += 3)
+ {
+ pADB = (cea_861b_adb_t*)pDataBlock;
+ switch(pADB->audio_format_code)
+ {
+ // uncompressed audio (Linear PCM)
+ case AUDIO_LPCM:
+ memcpy(&(hdmi_priv->lpcm_sad),pDataBlock,3);
+ //save these blocks
+ memcpy(pCurrentSADBlocks, pDataBlock, 3);
+ // move pointer in SAD blocks buffer
+ pCurrentSADBlocks += 3;
+ // update SADC field
+ pEEld->sadc += 1;
+ break;
+ // compressed audio
+ case AUDIO_AC3:
+ case AUDIO_MPEG1:
+ case AUDIO_MP3:
+ case AUDIO_MPEG2:
+ case AUDIO_AAC:
+ case AUDIO_DTS:
+ case AUDIO_ATRAC:
+ case AUDIO_OBA:
+ case AUDIO_DOLBY_DIGITAL:
+ case AUDIO_DTS_HD:
+ case AUDIO_MAT:
+ case AUDIO_DST:
+ case AUDIO_WMA_PRO:
+ //save these blocks
+ memcpy(pCurrentSADBlocks, pDataBlock, 3);
+ // move pointer in SAD blocks buffer
+ pCurrentSADBlocks += 3;
+ // update SADC field
+ pEEld->sadc += 1;
+ break;
+ }
+ }
+ break;
+
+ case CEA_VENDOR_DATABLOCK:
+ // audio wants data from 6th byte of VSDB onwards
+ //Sighting 94842:
+
+ // | Byte # | bits[7-0] |
+ // |--------------------------------------------------------------------|
+ // | 1-3 |24-bit IEEE Registration Identifier (0x000C03) |
+ // |--------------------------------------------------------------------|
+ // | 4-5 | Source Physical Address |
+ // |--------------------------------------------------------------------|
+ // | 6 |SupportsAI|DC48bit|DC36bit|Dc30bit|DCY444|Rsvd|Rsvd|DVIDual|
+ // |--------------------------------------------------------------------|
+ // | 7 | Max TMDS clock |
+ // |--------------------------------------------------------------------|
+ // | 8 |Latency_Field |I_Latency_Field| Reserved bits 5-0 |
+ // | | _Present | _Present | |
+ // |--------------------------------------------------------------------|
+ // | 9 | Video Latency |
+ // |--------------------------------------------------------------------|
+ // | 10 | Audio Latency |
+ // |--------------------------------------------------------------------|
+ // | 11 | Interlaced Video Latency |
+ // |--------------------------------------------------------------------|
+ // | 12 | Interlaced Audio Latency |
+ // |--------------------------------------------------------------------|
+
+ ++pDataBlock;
+ // move pointer to next CEA Datablock
+ pDataBlock += dwNumOfBytes;
+ break;
+
+ case CEA_SPEAKER_DATABLOCK:
+ pEEld->speaker_allocation_block = *(++pDataBlock);
+ // move pointer to next CEA Datablock
+ pDataBlock += dwNumOfBytes;
+ break;
+
+ default:
+ // Move pointer to next CEA DataBlock
+ pDataBlock += (dwNumOfBytes + 1);
+ }
+ // Decrement size of CEA DataBlock
+ sizeOfCEADataBlock -= (dwNumOfBytes + 1);
+ }
+ }
+
+ //Copy all the saved SAD blocks at the end of ELD
+ //SAD blocks should be written after the Monitor name and VSDB.
+ //See ELD definition in iHDMI.h
+ ulNumSADBytes = (pEEld->sadc) * 3; //Size of each SAD block is 3 bytes
+
+ //DCN 460119: Audio does not play on displays which do not provide SAB in EDID.
+ //Solution: Graphics driver should create a default SAB in ELD with front left and front right
+ //speakers enabled if the display supports basic audio.
+ pDataBlock = (uint8_t *)pCeEdid;
+ if((*(pDataBlock + HDMI_CEA_EXTENSION_BLOCK_BYTE_3) & HDMI_BASIC_AUDIO_SUPPORTED) && (pEEld->speaker_allocation_block == 0))
+ {
+ pEEld->flr = 1;
+ }
+ //End of DCN 460119
+
+ // zero out local buffers
+ memset(ucEdidBlock, 0, sizeof(ucEdidBlock));
+
+ // Get base EDID
+ if(!mdfld_hdmi_get_cached_edid_block(connector, 0, ucEdidBlock, EDID_BLOCK_SIZE))
+ {
+ return 0;
+ }
+
+ pEdid = (baseedid_1_x_t*) ucEdidBlock;
+ pDTD = &pEdid->DTD[1];
+
+ //Update the Manufacturer ID and Product Code here
+ memcpy(pEEld->manufacturer_id,pEdid->ManufacturerID,2);
+ memcpy(pEEld->product_id,pEdid->ProductID,2);
+
+ // Now Fill the monitor string name
+ // Search through DTD blocks, looking for monitor name
+ for (i = 0; i < MAX_BASEEDID_DTD_BLOCKS - 1; ++i, ++pDTD)
+ {
+ // Set a uint8_t pointer to DTD data
+ pData = (uint8_t *)pDTD;
+
+ // Check the Flag (the first two bytes) to determine
+ // if this block is used as descriptor
+ if (pData[0] == 0x00 && pData[1] == 0x00)
+ {
+ // And now check Data Type Tag within this descriptor
+ // Tag = 0xFC, then monitor name stored as ASCII
+ if (pData[3] == 0xFC)
+ {
+ ulIndex = 0;
+ // Copy monitor name
+ for (j = 0; (j < 13) && (pData[j+5] != 0x0A); ++j)
+ {
+ pEEld->mn_sand_sads[ulIndex] = pData[j+5];
+ ulIndex++;
+ }
+ pEEld->mnl = j;
+ break;
+ }
+ }
+ }
+
+ //Check if number of SAD Bytes > 0 and for size within limits of allowed Base line Data size as per EELD spec
+ if((ulNumSADBytes > 0) && (ulNumSADBytes <= 64))
+ {
+ //Copy the SADs immediately after the Monitor Name String
+ memcpy(&pEEld->mn_sand_sads[j], pSADBlocks, ulNumSADBytes);
+ }
+
+
+ // Header = 4, Baseline Data = 60 and Vendor (INTEL) specific = 2
+ // 4 + 60 + 2 = 66
+ hdmi_priv->hdmi_eeld_size = HDMI_EELD_SIZE;
+
+ //free the buffer allocated for SAD blocks
+ kfree(pSADBlocks);
+ pSADBlocks = NULL;
+ pCurrentSADBlocks = NULL;
+ return 1;
+}
+
+static enum drm_connector_status
+mdfld_hdmi_edid_detect(struct drm_connector *connector)
+{
+ struct drm_device *dev = connector->dev;
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *)dev->dev_private;
+ struct psb_intel_output *output = to_psb_intel_output(connector);
+ struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv;
+ struct edid *edid = NULL;
+ enum drm_connector_status status = connector_status_disconnected;
+ int i = 0;
+ int monitor_number = sizeof(mdfld_hdmi_edid) / sizeof(struct hdmi_edid_info);
+
+ PSB_DEBUG_ENTRY("\n");
+
+#if 0
+ if (!psb_intel_output->hdmi_i2c_adapter) {
+ DRM_INFO("Enter mdfld_hdmi_get_modes, i2c_adapter is NULL. \n");
+
+ /* hard-coded the HDMI_I2C_ADAPTER_ID to be 3, Should get from GCT*/
+ psb_intel_output->hdmi_i2c_adapter = i2c_get_adapter(3);
+ }
+
+ if (!psb_intel_output->hdmi_i2c_adapter) {
+ DRM_INFO("Enter mdfld_hdmi_get_modes, no valid i2c_adapter . \n");
+ return ret;
+ }
+
+ edid =
+ drm_get_edid(&psb_intel_output->base,
+ psb_intel_output->hdmi_i2c_adapter);
+
+ hdmi_priv->has_hdmi_sink = false;
+ if (edid) {
+ if (edid->input & DRM_EDID_INPUT_DIGITAL) {
+ status = connector_status_connected;
+ hdmi_priv->has_hdmi_sink = drm_detect_hdmi_monitor(edid);
+ mdfld_hdmi_create_eeld_packet(connector);
+ }
+
+ intel_output->base.display_info.raw_edid = NULL;
+ kfree(edid);
+ }
+#else
+ if ((HDMI_EDID == NULL) || (strlen(HDMI_EDID) > HDMI_MONITOR_NAME_LENGTH))
+ return status;
+
+ DRM_INFO("Detected HDMI monitor %s.\n", HDMI_EDID);
+
+ for (i = 0; i < monitor_number; i++) {
+ if (!strcasecmp(HDMI_EDID, mdfld_hdmi_edid[i].monitor_name)) {
+ edid = (struct edid *)mdfld_hdmi_edid[i].edid_info;
+ break;
+ }
+ }
+
+ if (i == monitor_number)
+ edid = (struct edid *)mdfld_hdmi_edid[monitor_number - 1].edid_info;
+
+ hdmi_priv->has_hdmi_sink = false;
+ if (edid) {
+ status = connector_status_connected;
+ hdmi_priv->has_hdmi_sink = drm_detect_hdmi_monitor(edid);
+ mdfld_hdmi_create_eeld_packet(connector);
+ }
+
+ dev_priv->hdmi_done_reading_edid = true;
+#endif
+ return status;
+}
+
+/* FIXME: start using the force parameter */
+static enum drm_connector_status mdfld_hdmi_detect(struct drm_connector
+ *connector, bool force)
+{
+ return mdfld_hdmi_edid_detect(connector);
+}
+
+static int mdfld_hdmi_set_property(struct drm_connector *connector,
+ struct drm_property *property,
+ uint64_t value)
+{
+ struct drm_encoder *pEncoder = connector->encoder;
+
+ PSB_DEBUG_ENTRY("connector info, type = %d, type_id=%d, base=0x%p, base.id=0x%x. \n", connector->connector_type, connector->connector_type_id, &connector->base, connector->base.id);
+ PSB_DEBUG_ENTRY("encoder info, base.id=%d, encoder_type=%d, dev=0x%p, base=0x%p, possible_clones=0x%x. \n", pEncoder->base.id, pEncoder->encoder_type, pEncoder->dev, &pEncoder->base, pEncoder->possible_clones);
+ PSB_DEBUG_ENTRY("encoder info, possible_crtcs=0x%x, crtc=0x%p. \n", pEncoder->possible_crtcs, pEncoder->crtc);
+
+ if (!strcmp(property->name, "scaling mode") && pEncoder) {
+ PSB_DEBUG_ENTRY("scaling mode \n");
+ } else if (!strcmp(property->name, "backlight") && pEncoder) {
+ PSB_DEBUG_ENTRY("backlight \n");
+ } else if (!strcmp(property->name, "DPMS") && pEncoder) {
+ PSB_DEBUG_ENTRY("DPMS \n");
+ }
+
+ if (!strcmp(property->name, "scaling mode") && pEncoder) {
+ struct psb_intel_crtc *pPsbCrtc = to_psb_intel_crtc(pEncoder->crtc);
+ bool bTransitionFromToCentered;
+ uint64_t curValue;
+
+ if (!pPsbCrtc)
+ goto set_prop_error;
+
+ switch (value) {
+ case DRM_MODE_SCALE_FULLSCREEN:
+ break;
+ case DRM_MODE_SCALE_NO_SCALE:
+ break;
+ case DRM_MODE_SCALE_ASPECT:
+ break;
+ default:
+ goto set_prop_error;
+ }
+
+ if (drm_connector_property_get_value(connector, property, &curValue))
+ goto set_prop_error;
+
+ if (curValue == value)
+ goto set_prop_done;
+
+ if (drm_connector_property_set_value(connector, property, value))
+ goto set_prop_error;
+
+ bTransitionFromToCentered = (curValue == DRM_MODE_SCALE_NO_SCALE) ||
+ (value == DRM_MODE_SCALE_NO_SCALE);
+
+ if (pPsbCrtc->saved_mode.hdisplay != 0 &&
+ pPsbCrtc->saved_mode.vdisplay != 0) {
+ if (bTransitionFromToCentered) {
+ if (!drm_crtc_helper_set_mode(pEncoder->crtc, &pPsbCrtc->saved_mode,
+ pEncoder->crtc->x, pEncoder->crtc->y, pEncoder->crtc->fb))
+ goto set_prop_error;
+ } else {
+ struct drm_encoder_helper_funcs *pEncHFuncs = pEncoder->helper_private;
+ pEncHFuncs->mode_set(pEncoder, &pPsbCrtc->saved_mode,
+ &pPsbCrtc->saved_adjusted_mode);
+ }
+ }
+ }
+set_prop_done:
+ return 0;
+set_prop_error:
+ return -1;
+}
+
+/**
+ * Return the list of HDMI DDC modes if available.
+ */
+static int mdfld_hdmi_get_modes(struct drm_connector *connector)
+{
+ struct psb_intel_output *psb_intel_output = to_psb_intel_output(connector);
+ struct edid *edid = NULL;
+ int ret = 0;
+#if 1 /* FIXME_JLIU7 HDMI*/
+ struct drm_device *dev = connector->dev;
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct mdfld_dsi_config *dsi_config = dev_priv->dsi_configs[0];
+ struct drm_display_mode *panel_fixed_mode = NULL;
+#endif
+ int i = 0;
+ int monitor_number = sizeof(mdfld_hdmi_edid) / sizeof(struct hdmi_edid_info);
+
+ PSB_DEBUG_ENTRY("\n");
+
+ if (dsi_config != NULL) {
+ panel_fixed_mode
+ = drm_mode_duplicate(dev, dsi_config->fixed_mode);
+ }
+
+#if 0
+ if (!psb_intel_output->hdmi_i2c_adapter) {
+ DRM_INFO("Enter mdfld_hdmi_get_modes, i2c_adapter is NULL. \n");
+
+ /* hard-coded the HDMI_I2C_ADAPTER_ID to be 3, Should get from GCT*/
+ psb_intel_output->hdmi_i2c_adapter = i2c_get_adapter(3);
+ }
+
+ if (!psb_intel_output->hdmi_i2c_adapter) {
+ DRM_INFO("Enter mdfld_hdmi_get_modes, no valid i2c_adapter . \n");
+ return ret;
+ }
+
+ edid =
+ drm_get_edid(&psb_intel_output->base,
+ psb_intel_output->hdmi_i2c_adapter);
+#else
+ edid = NULL;
+#endif
+ if (edid) {
+ drm_mode_connector_update_edid_property(&psb_intel_output->
+ base, edid);
+ ret = drm_add_edid_modes(&psb_intel_output->base, edid);
+ kfree(edid);
+ }
+#if MDFLD_HDMI_JLIU7_DEBUG_1
+ else {
+ DRM_INFO("mdfld_hdmi_get_modes, fake edid info. \n");
+#if 1 //MDFLD_HDMI_JLIU7_DEBUG_1
+ for (i = 0; i < monitor_number; i++) {
+ if (!strcasecmp(HDMI_EDID, mdfld_hdmi_edid[i].monitor_name)) {
+ edid = (struct edid *)mdfld_hdmi_edid[i].edid_info;
+ break;
+ }
+ }
+
+ if (i == monitor_number)
+ edid = (struct edid *)mdfld_hdmi_edid[monitor_number - 1].edid_info;
+
+ connector->display_info.raw_edid = (char *)edid;
+ drm_mode_connector_update_edid_property(&psb_intel_output->
+ base, edid);
+ ret = drm_add_edid_modes(&psb_intel_output->base, edid);
+#if 1 /* FIXME_JLIU7 HDMI*/
+ if (panel_fixed_mode != NULL) {
+ struct drm_display_mode *mode =
+ drm_mode_duplicate(dev, panel_fixed_mode);
+ drm_mode_probed_add(connector, mode);
+ }
+#endif /* FIXME_JLIU7 HDMI*/
+#endif /* MDFLD_HDMI_JLIU7_DEBUG_1 */
+ }
+#endif /* MDFLD_HDMI_JLIU7_DEBUG_1 */
+
+ if (ret)
+ return ret;
+
+ /* Didn't get an EDID, so
+ * Set wide sync ranges so we get all modes
+ * handed to valid_mode for checking
+ */
+ connector->display_info.min_vfreq = 0;
+ connector->display_info.max_vfreq = 200;
+ connector->display_info.min_hfreq = 0;
+ connector->display_info.max_hfreq = 200;
+
+ return 0;
+}
+
+static int mdfld_hdmi_mode_valid(struct drm_connector *connector,
+ struct drm_display_mode *mode)
+{
+
+ PSB_DEBUG_ENTRY("display info. hdisplay = %d, vdisplay = %d. \n", mode->hdisplay, mode->vdisplay);
+
+#if 0 /* MDFLD_HDMI_JLIU7_DEBUG */
+ if (mode->clock > 165000)
+ return MODE_CLOCK_HIGH;
+ if (mode->clock < 20000)
+ return MODE_CLOCK_HIGH;
+#endif /* MDFLD_HDMI_JLIU7_DEBUG */
+
+ /* just in case */
+ if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+ return MODE_NO_DBLESCAN;
+
+ /* just in case */
+ if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+ return MODE_NO_INTERLACE;
+
+#if !MDFLD_HDMI_JLIU7_1080
+ if (mode->hdisplay > 1600)
+ return MODE_PANEL;
+ if (mode->vdisplay > 1080)
+ return MODE_PANEL;
+#endif /* MDFLD_HDMI_JLIU7_1080 */
+
+ return MODE_OK;
+}
+
+static void mdfld_hdmi_connector_dpms(struct drm_connector *connector, int mode)
+{
+#ifdef CONFIG_PM_RUNTIME
+ struct drm_device * dev = connector->dev;
+ struct drm_psb_private * dev_priv = dev->dev_private;
+ bool panel_on, panel_on2;
+#endif
+ /*first, execute dpms*/
+
+ drm_helper_connector_dpms(connector, mode);
+
+#ifdef CONFIG_PM_RUNTIME
+ if(is_panel_vid_or_cmd(dev)) {
+ /*DPI panel*/
+ panel_on = dev_priv->dpi_panel_on;
+ panel_on2 = dev_priv->dpi_panel_on2;
+ } else {
+ /*DBI panel*/
+ panel_on = dev_priv->dbi_panel_on;
+ panel_on2 = dev_priv->dbi_panel_on2;
+ }
+
+ /*then check all display panels + monitors status*/
+ if(!panel_on && !panel_on2 && !(REG_READ(HDMIB_CONTROL) & HDMIB_PORT_EN)) {
+ /*request rpm idle*/
+ if(dev_priv->rpm_enabled) {
+ pm_request_idle(&dev->pdev->dev);
+ }
+ }
+
+ /**
+ * if rpm wasn't enabled yet, try to allow it
+ * FIXME: won't enable rpm for DPI since DPI
+ * CRTC setting is a little messy now.
+ * Enable it later!
+ */
+#if 0
+ if(!dev_priv->rpm_enabled && !is_panel_vid_or_cmd(dev))
+ ospm_runtime_pm_allow(dev);
+#endif
+#endif
+}
+
+/**
+ * psb_intel_lvds_destroy - unregister and free LVDS structures
+ * @connector: connector to free
+ *
+ * Unregister the DDC bus for this connector then free the driver private
+ * structure.
+ *
+ * Note: taken from psb_intel_lvds.c
+ */
+static void psb_intel_lvds_destroy(struct drm_connector *connector)
+{
+ drm_sysfs_connector_remove(connector);
+ drm_connector_cleanup(connector);
+ kfree(connector);
+}
+
+/* Note: taken from psb_intel_lvds.c */
+static void psb_intel_lvds_enc_destroy(struct drm_encoder *encoder)
+{
+ drm_encoder_cleanup(encoder);
+}
+
+/* Note: taken from psb_intel_lvds.c */
+static const struct drm_encoder_funcs psb_intel_lvds_enc_funcs = {
+ .destroy = psb_intel_lvds_enc_destroy,
+};
+
+static const struct drm_encoder_helper_funcs mdfld_hdmi_helper_funcs = {
+ .dpms = mdfld_hdmi_dpms,
+ .mode_fixup = mdfld_hdmi_mode_fixup,
+ .prepare = psb_intel_encoder_prepare,
+ .mode_set = mdfld_hdmi_mode_set,
+ .commit = psb_intel_encoder_commit,
+};
+
+static const struct drm_connector_helper_funcs
+ mdfld_hdmi_connector_helper_funcs = {
+ .get_modes = mdfld_hdmi_get_modes,
+ .mode_valid = mdfld_hdmi_mode_valid,
+ .best_encoder = psb_intel_best_encoder,
+};
+
+static const struct drm_connector_funcs mdfld_hdmi_connector_funcs = {
+ .dpms = mdfld_hdmi_connector_dpms,
+ .save = mdfld_hdmi_save,
+ .restore = mdfld_hdmi_restore,
+ .detect = mdfld_hdmi_detect,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .set_property = mdfld_hdmi_set_property,
+ .destroy = psb_intel_lvds_destroy,
+};
+
+void mdfld_hdmi_init(struct drm_device *dev,
+ struct psb_intel_mode_device *mode_dev)
+{
+#if 0
+ DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private;
+#endif
+ struct psb_intel_output *psb_intel_output;
+ struct drm_connector *connector;
+ struct drm_encoder *encoder;
+ struct mid_intel_hdmi_priv *hdmi_priv;
+
+ PSB_DEBUG_ENTRY("\n");
+
+ psb_intel_output = kzalloc(sizeof(struct psb_intel_output) +
+ sizeof(struct mid_intel_hdmi_priv), GFP_KERNEL);
+ if (!psb_intel_output)
+ return;
+
+ hdmi_priv = (struct mid_intel_hdmi_priv *)(psb_intel_output + 1);
+ psb_intel_output->mode_dev = mode_dev;
+ connector = &psb_intel_output->base;
+ encoder = &psb_intel_output->enc;
+ drm_connector_init(dev, &psb_intel_output->base,
+ &mdfld_hdmi_connector_funcs,
+ DRM_MODE_CONNECTOR_DVID);
+
+ drm_encoder_init(dev, &psb_intel_output->enc, &psb_intel_lvds_enc_funcs,
+ DRM_MODE_ENCODER_TMDS);
+
+ drm_mode_connector_attach_encoder(&psb_intel_output->base,
+ &psb_intel_output->enc);
+ psb_intel_output->type = INTEL_OUTPUT_HDMI;
+ /*FIXME: May need to get this somewhere, but CG code seems hard coded it*/
+ hdmi_priv->hdmib_reg = HDMIB_CONTROL;
+ hdmi_priv->has_hdmi_sink = false;
+ psb_intel_output->dev_priv = hdmi_priv;
+
+ drm_encoder_helper_add(encoder, &mdfld_hdmi_helper_funcs);
+ drm_connector_helper_add(connector,
+ &mdfld_hdmi_connector_helper_funcs);
+ connector->display_info.subpixel_order = SubPixelHorizontalRGB;
+ connector->interlace_allowed = false;
+ connector->doublescan_allowed = false;
+
+ drm_connector_attach_property(connector, dev->mode_config.scaling_mode_property, DRM_MODE_SCALE_FULLSCREEN);
+
+ /* hard-coded the HDMI_I2C_ADAPTER_ID to be 3, Should get from GCT*/
+ psb_intel_output->hdmi_i2c_adapter = i2c_get_adapter(3);
+
+ if (psb_intel_output->hdmi_i2c_adapter) {
+ /* HACKS_JLIU7 */
+ DRM_INFO("Enter mdfld_hdmi_init, i2c_adapter is availabe.\n");
+
+ } else {
+ printk(KERN_ALERT "No ddc adapter available!\n");
+ }
+
+ hdmi_priv->is_hdcp_supported = true;
+ hdmi_priv->hdmi_i2c_adapter = psb_intel_output->hdmi_i2c_adapter;
+ hdmi_priv->dev = dev;
+ mdfld_hdcp_init(hdmi_priv);
+ mdfld_hdmi_audio_init(hdmi_priv);
+ mdfld_msic_init(hdmi_priv);
+
+ drm_sysfs_connector_add(connector);
+ return;
+}
+#endif
--- /dev/null
+/*
+ * Copyright © 2006-2007 Intel 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 (including the next
+ * paragraph) 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.
+ *
+ * Authors:
+ * Chunfeng Zhao <chunfeng.zhao@intel.com>
+ * Jim Liu <jim.liu@intel.com>
+ */
+
+#ifndef __PSB_INTEL_HDMI_H__
+#define __PSB_INTEL_HDMI_H__
+
+#include <linux/types.h>
+#include <linux/version.h>
+
+/*
+ * HDMI Parameters
+ */
+
+/* GUID HDMI Parameters */
+#if 0
+//#ifdef DEFINE_GUID
+//#undef DEFINE_GUID
+#define DEFINE_GUID(n,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) const GUID n GUID_SECT = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}
+//#endif /* DEFINE_GUID */
+
+#define HDMI_PARAMETERS_GUID "{6FD3BE0E-80F9-4206-86B7-3714FA439634}"
+DEFINE_GUID(GUID_HDMI_PARAMETERS, 0x6fd3be0e, 0x80f9, 0x4206, 0x86, 0xb7, 0x37, 0x14, 0xfa, 0x43, 0x96, 0x34);
+
+#define AVI_INFOFRAME_GUID "{DFCB113B-E54F-49A2-B5E3-78D0C6B4F4CB}"
+DEFINE_GUID(GUID_AVI_INFOFRAME, 0xdfcb113b, 0xe54f, 0x49a2, 0xb5, 0xe3, 0x78, 0xd0, 0xc6, 0xb4, 0xf4, 0xcb);
+#endif
+
+#define HDMI_DEVICE_NAME "ABC_VEND"
+#define HDMI_DEVICE_DESC "XZ05 PC VIDEO"
+
+#define HDMI_MAX_PIXEL_REPETITION 0x04 // On Cantiga only upto 4X pixel repetition is supported
+#define HDMI_HBR_AUDIO_SAMPLE_RATE 192000 // 192kHz is the sample rate corresponding to the HBR audio formats
+#define HDMI_AUDIO_CLOCK_PACKET_RATE 1500 // Audio clock packet rate of 1.5kHz has to be considered while calculating audio BW
+
+#define HDMI_BAR_INFO_LENGTH 8 // 8 bytes of barinfo
+
+#define HDMI_MONITOR_NAME_LENGTH 20
+
+// BaseLineDataLength.
+// Total size is in multiple of 4 bytes. i.e, 80/4 = 20
+#define HDMI_EELD_BASELINE_DATA_LENGTH 0x14
+
+// Header = 4, Baseline Data = 80 and Vendor (INTEL) specific = 2 as per EELD spec
+// 4 + 80 + = 84
+#define HDMI_EELD_SIZE 84
+
+//
+// HDMI command types
+//
+typedef enum
+{
+ HDMI_COMMAND_GET,
+ HDMI_COMMAND_SET
+} hdmi_command_t;
+
+#define HDMI_AVI_FLAG_ITCONTENT 0x00800000
+#define HDMI_AVI_FLAG_RGB_QUANT_RANGE 0x00040000
+#define HDMI_AVI_FLAG_SCAN_INFO 0x00000001
+#define HDMI_AVI_FLAG_BAR_INFO 0x00000010
+//
+// CEA-861b definitions
+//
+#define HDMI_CEA_VERSION 0x00
+#define HDMI_ELD_VERSION 0x01
+#define HDMI_EELD_VERSION 0x02
+#define HDMI_BASE_ELD_SIZE 0x0E
+#define HDMI_CEA_EDID_HEADER_SIZE 0x04
+#define HDMI_EELD_CEA_EDID_VERSION 0x03
+#define HDMI_CEA_EDID_BLOCK_SIZE 128
+
+//
+//Basic Audio support definitions
+//
+
+#define HDMI_BASIC_AUDIO_SUPPORTED 0x40
+#define HDMI_CEA_EXTENSION_BLOCK_BYTE_3 3
+#define HDMI_FL_AND_FR_SPEAKERS_CONNECTED 0x1
+
+//
+// HDMI buffer/information types
+//
+typedef enum {
+ // Non-standard or non-HDMI type
+ HDMI_ELD_TYPE = 0x00, // ELD buffer type
+ HDMI_EELD_TYPE = 0x01, // EELD buffer type
+
+ // Per HDMI Spec, refer Table 2-1 in HDMI EDS
+ // or Table 5-8 in HDMI spec
+ HDMI_VS_TYPE = 0x81, // Vendor-Specific InfoFrame type
+ HDMI_AVI_TYPE = 0x82, // AVI InfoFrame type
+ HDMI_SPD_TYPE = 0x83, // SPD InfoFrame type
+ HDMI_AUDIO_TYPE = 0x84, // Audio InfoFrame type
+ HDMI_MS_TYPE = 0x85, // MPEG Source InfoFrame type
+
+ // Non-standard or non-HDMI types
+ HDMI_PR_PE_TYPE = 0x86, // Pixel Replication & Pixel Encoding(colorimetry) type
+ HDMI_AUDIO_CAPS_TYPE = 0x87, // Encoder Audio Capabilities type
+ HDMI_AUDIO_ENABLE_FLAGS_TYPE = 0x88 // Flags for enabling / disabling audio
+} hdmi_info_type_t;
+
+//
+// InfoFrame Version Information
+//
+typedef enum {
+ HDMI_VS_VERSION = 1, // Vendor-Specific InfoFrame Version 1
+ HDMI_AVI_VERSION = 1, // AVI InfoFrame Version 1
+ HDMI_AVI_VERSION2 = 2, // AVI InfoFrame Version 2
+ HDMI_SPD_VERSION = 1, // SPD InfoFrame Version 1
+ HDMI_AUDIO_VERSION = 1, // Audio InfoFrame Version 1
+ HDMI_MS_VERSION = 1 // MPEG Source InfoFrame Version 1
+} infoframe_version_t;
+
+//
+// InfoFrame Payload Length in bytes
+//
+typedef enum {
+ HDMI_VS_MAX_LENGTH = 27, // Vendor-Specific InfoFrame Payload Length, including IEEE reg ID
+ HDMI_AVI_LENGTH = 13, // AVI InfoFrame Payload Length
+ HDMI_SPD_LENGTH = 25, // SPD InfoFrame Payload Length
+ HDMI_AUDIO_LENGTH = 10, // Audio InfoFrame Payload Length
+ HDMI_MS_LENGTH = 10, // MPEG Source InfoFrame Payload Length
+ HDMI_PR_PE_LENGTH = 4, // Length of PR_PE_TYPE
+ HDMI_AUDIO_CAPS_LENGTH = 4 // Length of AUDIO_CAPS_TYPE
+} infoframe_length_t;
+
+//
+// InfoFrame TOTAL Length in bytes (includes header + payload)
+//
+typedef enum {
+ HDMI_VS_MAX_TOTAL_LENGTH = HDMI_VS_MAX_LENGTH + 4, // Max Total size of Vendor-Specific InfoFrame
+ HDMI_AVI_TOTAL_LENGTH = HDMI_AVI_LENGTH + 4, // Total size of AVI InfoFrame
+ HDMI_SPD_TOTAL_LENGTH = HDMI_SPD_LENGTH + 4, // Total size of SPD InfoFrame
+ HDMI_AUDIO_TOTAL_LENGTH = HDMI_AUDIO_LENGTH + 4, // Total size of Audio InfoFrame
+ HDMI_MS_TOTAL_LENGTH = HDMI_MS_LENGTH + 4, // Total size of MPEG Source InfoFrame
+} infoframe_total_length_t;
+
+
+//
+// Pixel Replication multipliers
+//
+typedef enum {
+ HDMI_PR_ONE = 0, // No repetition (ie., pixel sent once)
+ HDMI_PR_TWO, // Pixel sent 2 times (ie.,repeated once)
+ HDMI_PR_THREE, // Pixel sent 3 times
+ HDMI_PR_FOUR, // Pixel sent 4 times
+ HDMI_PR_FIVE, // Pixel sent 5 times
+ HDMI_PR_SIX, // Pixel sent 6 times
+ HDMI_PR_SEVEN, // Pixel sent 7 times
+ HDMI_PR_EIGHT, // Pixel sent 8 times
+ HDMI_PR_NINE, // Pixel sent 9 times
+ HDMI_PR_TEN // Pixel sent 10 times
+} hdmi_pixel_replication_t;
+
+//
+// Pixel encoding modes
+//
+//typedef typedef enum {
+ // HDMI_RGB256 = 0x01,
+ // HDMI_RGB220 = 0x02,
+ // HDMI_YCrCb422 = 0x04,
+ // HDMI_YCrCb444 = 0x08
+//}HDMI_COLORIMETRY;
+
+//
+// Pixel encoding modes
+//
+typedef enum {
+ HDMI_COLORIMETRY_RGB256 = 0x01,
+ HDMI_COLORIMETRY_RGB220 = 0x02,
+ HDMI_COLORIMETRY_YCrCb422 = 0x04,
+ HDMI_COLORIMETRY_YCrCb444 = 0x08
+} hdmi_colorimetry_t;
+
+//
+// AVI InfoFrame definitions - start
+//
+// Scan Info
+typedef enum {
+ HDMI_AVI_SCAN_NODATA = 0, // No data
+ HDMI_AVI_SCAN_OVERSCAN = 1, // Overscanned (TV)
+ HDMI_AVI_SCAN_UNDERSCAN = 2, // Underscanned (Computer)
+ HDMI_AVI_SCAN_FUTURE = 3 // Future
+} avi_scan_info_t;
+
+// Bar Info
+typedef enum {
+ HDMI_AVI_BAR_INVALID = 0, // Bar data not valid
+ HDMI_AVI_BAR_VALID_VERTICAL = 1, // Vertical Bar data valid
+ HDMI_AVI_BAR_VALID_HORIZONTAL= 2, // Horizontal Bar data valid
+ HDMI_AVI_BAR_VALID_BOTH = 3 // Vertical & Horizontal Bar data valid
+} avi_bar_info_t;
+
+// Active Format Information
+typedef enum {
+ HDMI_AVI_AFI_INVALID = 0, // No data
+ HDMI_AVI_AFI_VALID = 1 // Active Format Information valid
+} avi_fi_info_t;
+
+// AVI Pixel Encoding modes
+typedef enum {
+ HDMI_AVI_RGB_MODE = 0, // RGB pixel encoding mode
+ HDMI_AVI_YCRCB422_MODE = 1, // YCrCb 4:2:2 mode
+ HDMI_AVI_YCRCB444_MODE = 2, // YCrCb 4:4:4 mode
+ HDMI_AVI_FUTURE_MODE = 3 // Future mode
+} avi_encoding_mode_t;
+
+// AVI Active Format Aspect Ratio
+typedef enum {
+ HDMI_AVI_AFAR_SAME = 8, // same as picture aspect ratio
+ HDMI_AVI_AFAR_4_3 = 9, // 4:3 center
+ HDMI_AVI_AFAR_16_9 = 10, // 16:9 center
+ HDMI_AVI_AFAR_14_9 = 11 // 14:9 center
+} avi_afar_info_t;
+
+// AVI Picture Aspect Ratio
+typedef enum {
+ HDMI_AVI_PAR_NODATA = 0, // No Data
+ HDMI_AVI_PAR_4_3 = 1, // 4:3
+ HDMI_AVI_PAR_16_9 = 2, // 16:9
+ HDMI_AVI_PAR_FUTURE = 3 // Future
+} avi_par_info_t;
+
+// AVI Colorimetry Information
+typedef enum {
+ HDMI_AVI_COLOR_NODATA = 0, // No data
+ HDMI_AVI_COLOR_ITU601 = 1, // SMPTE 170M, ITU601
+ HDMI_AVI_COLOR_ITU709 = 2, // ITU709
+ HDMI_AVI_COLOR_FUTURE = 3 // Future
+} avi_color_info_t;
+
+// AVI Non-uniform Picture Scaling Info
+typedef enum {
+ HDMI_AVI_SCALING_NODATA = 0, // No scaling
+ HDMI_AVI_SCALING_HORIZONTAL = 1, // horizontal scaling
+ HDMI_AVI_SCALING_VERTICAL = 2, // vertical scaling
+ HDMI_AVI_SCALING_BOTH = 3 // horizontal & vertical scaling
+} avi_scaling_infp_t;
+
+// AVI RGB Quantization Range
+typedef enum {
+ HDMI_AVI_RGBQUANT_DEFAULT = 0, // Default value
+ HDMI_AVI_RGBQUANT_LIMITED = 1, // Limited Range
+ HDMI_AVI_RGBQUANT_FULL = 2, // Full Range
+ HDMI_AVI_RGBQUANT_FUTURE = 3 // Future use
+} avi_rgbquant_range_t;
+
+// AVI IT Content
+typedef enum {
+ HDMI_AVI_ITC_NODATA = 0, // No Data
+ HDMI_AVI_ITC_ITCONTENT = 1 //IT Content
+} avi_it_content_t;
+
+//
+// AVI InfoFrame definitions - end
+//
+
+//
+// SPD InfoFrame definitions - start
+//
+// SPD InfoFrame Data Byte 25, refer Table-17 in CEA-861b
+typedef enum {
+ HDMI_SPD_SRC_UNKNOWN = 0x00, // unknown
+ HDMI_SPD_SRC_DIGITAL_STB = 0x01, // Digital STB
+ HDMI_SPD_SRC_DVD = 0x02, // DVD
+ HDMI_SPD_SRC_DVHS = 0x03, // D-VHS
+ HDMI_SPD_SRC_HDD_VIDEO = 0x04, // HDD Video
+ HDMI_SPD_SRC_DVC = 0x05, // DVC
+ HDMI_SPD_SRC_DSC = 0x06, // DSC
+ HDMI_SPD_SRC_VCD = 0x07, // Video CD
+ HDMI_SPD_SRC_GAME = 0x08, // Game
+ HDMI_SPD_SRC_PC = 0x09 // PC General
+} spd_src_type_t;
+
+// SPD InfoFrame Vendor Name & Descriptor Length in bytes
+typedef enum {
+ HDMI_SPD_VNAME_LENGTH = 8, // SPD Vendor Name Length in bytes
+ HDMI_SPD_VDESC_LENGTH = 16, // SPD Vendor Descriptor Length in bytes
+} spd_namedesc_length_info_t;
+
+//
+// SPD InfoFrame definitions - end
+//
+
+//
+// InfoFrame Packet Header - generic
+//
+typedef struct _if_header {
+ uint8_t type; // InfoFrame Type
+ uint8_t version; // InfoFrame Version
+ uint8_t length; // InfoFrame Length
+ uint8_t chksum; // Checksum of the InfoFrame
+} if_header_t;
+
+//
+// AVI InfoFrame structure
+//
+typedef union _avi_if {
+ uint8_t avi_buf[HDMI_AVI_TOTAL_LENGTH];
+ #pragma pack(1)
+ struct
+ {
+ if_header_t avi_if_header; // AVI header data
+ union
+ {
+ uint8_t byte1;
+ struct
+ {
+ uint8_t scan_info:2; // scan information
+ uint8_t bar_info :2; // bar information
+ uint8_t format :1; // active format information
+ uint8_t enc_mode :2; // pixel encoding (RGB or YCrCb)
+ uint8_t b1rsvd :1; // reserved
+ };
+ };
+ union
+ {
+ uint8_t byte2;
+ struct
+ {
+ uint8_t afar :4; // Active Format Aspect Ratio
+ uint8_t par :2; // Picture Aspect Ratio
+ uint8_t colorimetry :2; // colorimetry
+ };
+ };
+ union
+ {
+ uint8_t byte3;
+ struct
+ {
+ uint8_t scaling_info :2; // Scaling information
+ uint8_t rgbquant_range :2; // RGB Quantization Range
+ uint8_t ext_colorimetry :3; //Extended Colorimetry
+ uint8_t it_content :1; //IT Content
+ };
+ };
+ union
+ {
+ uint8_t byte4;
+ struct
+ {
+ uint8_t vic :7; // Video Identification code (refer Table 13 in CEA-861b)
+ uint8_t b4rsvd :1; // reserved
+ };
+ };
+ union
+ {
+ uint8_t byte5;
+ struct
+ {
+ uint8_t pr :4; // pixel repetition (refer Table 15 in CEA-861b)
+ uint8_t b5rsvd :4; // reserved
+ };
+ };
+ uint8_t byte6; // end of top bar(lower), set to "00"
+ uint8_t byte7; // end of top bar(upper), set to "00"
+ uint8_t byte8; // start of bottom bar(lower), set to "00"
+ uint8_t byte9; // start of bottom bar(upper), set to "00"
+ uint8_t byte10; // end of left bar(lower), set to "00"
+ uint8_t byte11; // end of left bar(upper), set to "00"
+ uint8_t byte12; // start of right bar(lower), set to "00"
+ uint8_t byte13; // start of right bar(upper), set to "00"
+ };
+ #pragma pack()
+} avi_if_t;
+
+//
+// SPD InfoFrame structure
+//
+typedef union _spd_if {
+ uint8_t spd_buf[HDMI_SPD_TOTAL_LENGTH];
+ #pragma pack(1)
+ struct
+ {
+ if_header_t spd_if_header; // SPD header data
+ uint8_t name[8]; // Vendor Name, 8 characters
+ uint8_t desc[16]; // Product Description, 16 characters
+ uint8_t sdi; // Source Device Information
+ };
+ #pragma pack()
+} spd_if_t;
+
+//
+// Vendor Specific InfoFrame structure
+//
+typedef union _vs_if
+{
+ uint8_t vs_buf[HDMI_VS_MAX_TOTAL_LENGTH];
+ #pragma pack(1)
+ struct
+ {
+ if_header_t vs_if_header; // VS header data
+ uint8_t ieee_reg_id[3]; // 3-byte IEEE registration ID
+ uint8_t pay_load[24]; // Payload bytes
+ };
+ #pragma pack()
+} vs_if_t;
+
+//
+// AVI Infoframe structure for customization
+//
+
+typedef struct _avi_infoframe_custom {
+ //GUID guid; // GUID
+ int32_t command; // Command
+ int32_t flags; // Flags
+ uint32_t type_code; // Type code of AVI Infoframe
+ uint32_t version; // Version of AVI Infoframe
+ uint32_t length; // Length of AVI Info Frame
+ uint8_t r3r0_valid; // Reserved
+ uint8_t it_content; // IT Content
+ uint8_t bar_info[8]; // Reserved
+ int32_t active_format_aspect_ratio;// Reserved
+ int32_t non_uniform_scaling; // Reserved
+ int32_t rgb_ycc_indicator; // Reserved
+ int32_t ext_colorimetry; // Reserved
+ int32_t pixel_factor; // Reserved
+ int32_t bar_info_valid; // Reserved
+ int32_t colorimetry; // Reserved
+ int32_t aspect_ratio; // Reserved
+ int32_t quant_range; // Quantization Range
+ int32_t video_code; // Reserved
+ int32_t scan_info; // Scan Information
+} avi_infoframe_custom_t;
+
+
+//
+// LinearPCM Consolidated Audio Data(CAD) structure
+//
+typedef union _lpcm_cad {
+ uint8_t value;
+ struct {
+ uint8_t maxch_cp_on :3; // Max channels-1 supported with CP turned ON
+ uint8_t maxch_cp_off :3; // Max channels-1 supported with CP turned OFF
+ uint8_t sp_20bit :1; // 20-bit sample support
+ uint8_t sp_24bit :1; // 24-bit sample support
+ };
+} lpcm_cad_t;
+
+//
+// CEA Short Audio Descriptor
+//
+typedef struct _cea_861b_adb {
+#pragma pack(1)
+ union
+ {
+ uint8_t byte1;
+ struct
+ {
+ uint8_t max_channels :3; // Bits[0-2]
+ uint8_t audio_format_code :4; // Bits[3-6], see AUDIO_FORMAT_CODES
+ uint8_t b1reserved :1; // Bit[7] - reserved
+ };
+ };
+ union
+ {
+ uint8_t byte2;
+ struct
+ {
+ uint8_t sp_rate_32kHz :1; // Bit[0] sample rate = 32kHz
+ uint8_t sp_rate_44kHz :1; // Bit[1] sample rate = 44kHz
+ uint8_t sp_rate_48kHz :1; // Bit[2] sample rate = 48kHz
+ uint8_t sp_rate_88kHz :1; // Bit[3] sample rate = 88kHz
+ uint8_t sp_rate_96kHz :1; // Bit[4] sample rate = 96kHz
+ uint8_t sp_rate_176kHz :1; // Bit[5] sample rate = 176kHz
+ uint8_t sp_rate_192kHz :1; // Bit[6] sample rate = 192kHz
+ uint8_t sp_rate_b2reserved :1; // Bit[7] - reserved
+ };
+ };
+ union
+ {
+ uint8_t byte3; // maximum bit rate divided by 8kHz
+ // following is the format of 3rd byte for uncompressed(LPCM) audio
+ struct
+ {
+ uint8_t bit_rate_16bit :1; // Bit[0]
+ uint8_t bit_rate_20bit :1; // Bit[1]
+ uint8_t bit_rate_24bit :1; // Bit[2]
+ uint8_t bit_rate_b3reserved :5; // Bits[3-7]
+ };
+ };
+#pragma pack()
+}cea_861b_adb_t;
+
+//
+// Enhanced EDID Like Data aka EELD structure
+//
+typedef union _hdmi_eeld {
+ uint8_t eeld[HDMI_EELD_SIZE];
+ #pragma pack(1)
+ struct
+ {
+ // Byte[0] = ELD Version Number
+ union
+ {
+ uint8_t byte0;
+ struct
+ {
+ uint8_t reserved:3; // Reserf
+ uint8_t eld_ver:5; // ELD Version Number
+ // 00000b - reserved
+ // 00001b - first rev
+ // 00010b:11111b - reserved for future
+ };
+ };
+
+ // Byte[1] = Vendor Version Field
+ union
+ {
+ uint8_t vendor_version;
+ struct
+ {
+ uint8_t reserved1:3;
+ uint8_t veld_ver:5; // Version number of the ELD extension.
+ // This value is provisioned and unique to each vendor.
+ };
+ };
+
+ // Byte[2] = Baseline Lenght field
+ uint8_t baseline_eld_length; // Length of the Baseline structure divided by Four.
+
+ // Byte [3] = Reserved for future use
+ uint8_t byte3;
+
+ // Starting of the BaseLine EELD structure
+ // Byte[4] = Monitor Name Length
+ union
+ {
+ uint8_t byte4;
+ struct
+ {
+ uint8_t mnl:5;
+ uint8_t cea_edid_rev_id:3;
+ };
+ };
+
+ // Byte[5] = Capabilities
+ union
+ {
+ uint8_t capabilities;
+ struct
+ {
+ uint8_t hdcp:1; // Indicates HDCP support
+ uint8_t ai_support:1; // Inidcates AI support
+ uint8_t connection_type:2; // Indicates Connection type
+ // 00 - HDMI
+ // 01 - DP
+ // 10 -11 Reserved for future connection types
+ uint8_t sadc:4; // Indicates number of 3 bytes Short Audio Descriptors.
+ };
+ };
+
+ // Byte[6] = Audio Synch Delay
+ uint8_t audio_synch_delay; // Amount of time reported by the sink that the video trails audio in milliseconds.
+
+ // Byte[7] = Speaker Allocation Block
+ union
+ {
+ uint8_t speaker_allocation_block;
+ struct
+ {
+ uint8_t flr:1; // Front Left and Right channels
+ uint8_t lfe:1; // Low Frequency Effect channel
+ uint8_t fc:1; // Center transmission channel
+ uint8_t rlr:1; // Rear Left and Right channels
+ uint8_t rc:1; // Rear Center channel
+ uint8_t flrc:1; // Front left and Right of Center transmission channels
+ uint8_t rlrc:1; // Rear left and Right of Center transmission channels
+ uint8_t reserved3:1; // Reserved
+ };
+ };
+
+ // Byte[8 - 15] - 8 Byte port identification value
+ uint8_t port_id_value[8];
+
+ // Byte[16 - 17] - 2 Byte Manufacturer ID
+ uint8_t manufacturer_id[2];
+
+ // Byte[18 - 19] - 2 Byte Product ID
+ uint8_t product_id[2];
+
+ // Byte [20-83] - 64 Bytes of BaseLine Data
+ uint8_t mn_sand_sads[64]; // This will include
+ // - ASCII string of Monitor name
+ // - List of 3 byte SADs
+ // - Zero padding
+
+ // Vendor ELD Block should continue here!
+ // No Vendor ELD block defined as of now.
+ };
+ #pragma pack()
+} hdmi_eeld_t;
+
+//
+// Data structure for misc HDMI data
+//
+typedef struct _misc_hdmi_data {
+ int32_t colorimetry :4; //
+ int32_t pr :4; // pixel repetition value
+ int32_t reserved :24;// reserved bits
+} misc_hdmi_data_t;
+
+//
+// Audio capability structure
+//
+typedef struct _device_audio_caps {
+ int32_t npl_design :8; // max number of audio packets device can
+ // deliver per line
+ int32_t k0 :8; // The overhead(in pixels) per line requied
+ // by device for setting up audio packets when
+ // CP is disabled
+ int32_t k1 :8; // The overhead(in pixels) per line requied
+ // by device for setting up audio packets when
+ // CP is enabled
+ // Misc data
+ int32_t pr :4; // Pixel Replication value
+ uint32_t is_hdcp :1; // Driver, Device and Receiver support HDCP
+ uint32_t is_rptr :1; // Receiver is HDCP repeater
+ int32_t reserved :2; // reserved bits
+} device_audio_caps_t;
+
+typedef struct _audio_enable_flags {
+ uint32_t is_hdmi_display :1; //1 if HDMI display, 0 if not HDMI display
+ uint32_t is_eld_valid :1; //1 if ELD valid, 0 if ELD not valid
+ int32_t reserved1 :30;
+} audio_enable_flags_t;
+
+//
+// Data structure to exchange HDMI data through GetSetParameters interface
+//
+typedef struct _hdmi_parameters {
+ //GUID Guid;
+ hdmi_command_t command;
+ uint8_t type;
+ uint8_t size;
+ union {
+ hdmi_eeld_t eeld_buffer;
+ avi_if_t avi_infoframe;
+ spd_if_t spd_infoframe;
+ vs_if_t vs_infoframe;
+ union {
+ int32_t gen_data;
+ device_audio_caps_t audio_caps;
+ misc_hdmi_data_t misc_data;
+ audio_enable_flags_t fl_audio_enable_flags;
+ };
+ };
+} hdmi_parameters_t;
+
+//
+// Audio format codes
+//
+typedef enum {
+ AUDIO_LPCM = 0x0001, // Linear PCM (eg. IEC60958)
+ AUDIO_AC3 = 0x0002, // AC-3
+ AUDIO_MPEG1 = 0x0003, // MPEG1 (Layers 1 & 2)
+ AUDIO_MP3 = 0x0004, // MP3 (MPEG1 Layer 3)
+ AUDIO_MPEG2 = 0x0005, // MPEG2 (multichannel)
+ AUDIO_AAC = 0x0006, // AAC
+ AUDIO_DTS = 0x0007, // DTS
+ AUDIO_ATRAC = 0x0008, // ATRAC
+ AUDIO_OBA = 0x0009, // One Bit Audio
+ AUDIO_DOLBY_DIGITAL = 0x000A, // Dolby Digital
+ AUDIO_DTS_HD = 0x000B, // DTS-HD
+ AUDIO_MAT = 0x000C, // MAT (MLP)
+ AUDIO_DST = 0x000D, // DST
+ AUDIO_WMA_PRO = 0x000E // WMA Pro
+} audio_format_codes_t;
+
+//
+// Data structure for byte #6 to 8 which has fixed definition
+//
+typedef struct _vsdb_char6_to_char8
+{
+ #pragma pack(1)
+
+ union
+ {
+ uint8_t byte1;
+ struct
+ {
+ uint8_t dvi_dual :1; // Bit[0]
+ uint8_t b1reserved :2; // Bits[1-2]
+ uint8_t dcy444 :1; // Bit[3] YCBCR 4:4:4 in Deep Color modes.
+ uint8_t dc30bit :1; //Bit[4]
+ uint8_t dc36bit :1; //Bit[5]
+ uint8_t dc48bit :1; //Bit[6]
+ uint8_t supports_ai :1; // Bit[7]
+ };
+ };
+
+ uint8_t max_tmds_clock;
+
+ union
+ {
+ uint8_t byte3;
+ struct
+ {
+ uint8_t b3reserved :6; // Bit[0-5] reserved
+ uint8_t i_latency_field_present :1;// Bit[6]
+ uint8_t latency_field_present :1;// Bits[7]
+ };
+ };
+
+ #pragma pack()
+} vsdb_byte6_to_byte8_t;
+
+
+//
+// Gamut metadata structure
+//
+// Note : The data is written in big endian format
+#if 0
+// GUID for calling GBD interface
+// {EEE24BDF-6D30-40bf-9BA2-139F0FFFC797}
+#define DXVA_HDMI13_GBD_P0_GUID "{EEE24BDF-6D30-40BF-9BA2-139F0FFFC797}"
+DEFINE_GUID(GUID_DXVA_HDMI13_GBD_P0, 0xeee24bdf, 0x6d30, 0x40bf, 0x9b, 0xa2, 0x13, 0x9f, 0xf, 0xff, 0xc7, 0x97);
+#endif
+
+#define HDMI_GBD_PKT_TYPE 0x0A
+#define HDMI_GBD_P0_DATA_SIZE 27
+#define HDMI_MAX_VERTICES_DATA 25
+#define HDMI_MAX_FACET_DATA 25
+
+typedef enum {
+ VERTICES_AND_FACETS = 0,
+ RGB_MIN_MAX_RANGE = 1
+} gbd_format_flag_t;
+
+typedef enum {
+ GBD_8BIT_PRECISION = 0,
+ GBD_10BIT_PRECISION = 1,
+ GBD_12BIT_PRECISION = 2
+} gbd_color_precision_t;
+
+typedef enum {
+ RGB_BT709 = 0,
+ XVY_CC601 = 1,
+ XVY_CC709 = 2,
+ RESERVED_COLORSPACE
+} gbd_color_space_t;
+
+typedef enum {
+ MIN_RED_INDEX = 0,
+ MAX_RED_INDEX = 1,
+ MIN_GREEN_INDEX = 2,
+ MAX_GREEN_INDEX = 3,
+ MIN_BLUE_INDEX = 4,
+ MAX_BLUE_INDEX = 5,
+ MAX_RANGE_DATA_INDEX_LIMIT = 6
+} gbd_rgb_range_data_index_t;
+
+//
+// App needs to feel the data in this structure
+//
+typedef struct _gbd_p0_hdmi_1_3 {
+ uint8_t enable; // Enable/Disable GBD profile sending
+ gbd_format_flag_t format_flag; // uses GBD_FORMAT_FLAG_EN, this defines the gamut data format
+ gbd_color_precision_t color_precision; // uses GBD_COLOR_PRECISION, this is the bit precision of GBD vertex and range data
+ gbd_color_space_t color_space; // uses GBD_COLOR_SPACE_EN, this defines the color space being represented
+
+ union
+ {
+ // If bFormatFlag is 0
+ struct {
+ uint8_t facet_mode; // spec supports 0 alone right now
+ uint16_t num_vertices; // Number of vertices
+ uint16_t num_facets; // Number of faces
+
+ // For 4 vertices of 12bits size is 18
+ // Max possible with 0 facets and 28 bytes of GBD is 28-5=23 bytes
+ uint16_t vertices_data[HDMI_MAX_VERTICES_DATA]; // Vertices data representation
+ uint16_t facets_data[HDMI_MAX_FACET_DATA]; // kept it as input data but to be defined based on future spec
+ } vertices_facets_data;
+
+
+ // If eFormatFlag is 1
+ struct {
+ uint16_t rgb_primary_data[MAX_RANGE_DATA_INDEX_LIMIT];
+ } rgb_range_data;
+ };
+
+} gbd_p0_hdmi_1_3_t;
+
+#define HDMI_GBD_MAX_SEQ_NUM_INDEX 16
+
+// various GBD profiles
+typedef enum {
+ P0_PROFILE = 0,
+ P1_PROFILE = 1,
+ P2_PROFILE = 2,
+ P3_PROFILE = 3,
+ INVALID_PROFILE
+} gbd_profile_type_t;
+
+// various packet transmission options
+typedef enum {
+ INTERMEDIATE_PKT_IN_SEQ = 0,
+ FIRST_PKT_IN_SEQ = 1,
+ LAST_PKT_IN_SEQ = 2,
+ ONLY_PKT_IN_SEQ = 3
+} gbd_pkt_seq_t;
+
+//
+// Packet header defn as per HDMI spec
+//
+typedef struct _gamut_pkt_header {
+ uint8_t pkt_type; // Defines the pkt type
+ union{
+ uint8_t field_byte;
+ struct{
+ uint8_t affected_gamut_info :4; // BIT 3:0
+ uint8_t gbd_profile :3; // BIT 6:4 ; uses GBD_PROFILE_TYPE_EN
+ uint8_t next_field :1; // BIT(7)
+ };
+ };
+
+ union{
+ uint8_t gbd_seq_info;
+ struct{
+ uint8_t current_gamut_info :4; // BIT 3:0
+ uint8_t packet_seq :2; // BIT 5:4 ; use GBD_PKT_SEQ_EN
+ uint8_t reserved2 :1; // BIT 6
+ uint8_t no_current_gbd :1; // BIT 7
+ };
+ };
+} gamut_pkt_header_t;
+
+//
+// Gamut structure contains data in following format
+//
+typedef struct _gamut_metadata_struct {
+ #pragma pack(1)
+ gamut_pkt_header_t pkt_hdr; // Gamut Metadata header data
+ union
+ {
+ uint8_t byte1;
+ struct
+ {
+ uint8_t gbd_color_space :3;
+ // Note: GBD buffer is formatted based upon the color precision
+ // 8 bit precision : 1 sign bit, 2 bits of integer, 5 bits of fraction
+ // 10 bit precision : 1 sign bit, 2 bits of integer, 7 bits of fraction
+ // 12 bit precision : 1 sign bit, 2 bits of integer, 9 bits of fraction
+ uint8_t gbd_color_precision :2;
+ uint8_t reserved3 :1;
+ uint8_t facet_mode :1; // 0 - No facet info in GBD; 1 - Facet info in GBD
+ uint8_t format_flag :1; // uses GBD_FORMAT_FLAG_EN
+ };
+ };
+
+ // For P0 profile below is the syntax in which data will be filled
+ // If Format is YUV
+ // char 2 : Higher 8 bits of number of vertices
+ // char 3 : Lower 8 bits of number of vertices
+ // char 4 to VSIZE+2 : Vertex data of size VSIZE,
+ // where VSIZE = 3*number of vertices*GBD color precision/8 + 0.99999
+ // char VSIZE+3: Higher 8 bits of number of facets
+ // char VSIZE+4: Lower 8 bits of number of facets
+ // char VSIZE+5 to VSIZE+FSIZE+4 : Facet data
+ // where VSIZE = number of facet data
+ uint8_t gbd_data[HDMI_GBD_P0_DATA_SIZE]; // data will be filled
+
+ #pragma pack()
+} gamut_metadata_st_t;
+
+struct mid_intel_hdmi_priv {
+ u32 hdmib_reg;
+ u32 save_HDMIB;
+ bool has_hdmi_sink;
+ /* Should set this when detect hotplug */
+ bool hdmi_device_connected;
+ struct mdfld_hdmi_i2c *i2c_bus;
+ /* EELD packet holder*/
+ hdmi_eeld_t eeld;
+ u32 hdmi_eeld_size;
+ cea_861b_adb_t lpcm_sad;
+ bool is_hdcp_supported;
+ struct i2c_adapter *hdmi_i2c_adapter; /* for control functions */
+ struct drm_device *dev;
+};
+
+struct hdmi_edid_info {
+ char monitor_name[HDMI_MONITOR_NAME_LENGTH];
+ char *edid_info;
+};
+
+#define HDMI_EDID_INFO(nm, info) \
+ .monitor_name = nm, .edid_info = info
+
+#define MSIC_IRQLVL1_STATUS 0x02
+ #define VREG_STATUS (1 << 5)
+#define MSIC_VRINT_STATUS 0x0d
+ #define HDMI_HPD_STATUS (1 << 3)
+ #define HDMI_OCP_STATUS (1 << 2)
+ #define VR_OCP_STATUS (1 << 1)
+ #define VR_OVP_STATUS (1 << 0)
+#define MSIC_VRINT_MASK 0x1c
+ #define HDMI_HPD_MASK (1 << 3)
+ #define HDMI_OCP_MASK (1 << 2)
+ #define VR_OCP_MASK (1 << 1)
+ #define VR_OVP_MASK (1 << 0)
+#define MSIC_IRQLVL1_MASK 0x21
+ #define VREG_MASK (1 << 5)
+#define MSIC_VCC330CNT 0xd3
+ #define VCC330_OFF 0x24
+ #define VCC330_ON 0x37
+#define MSIC_VHDMICNT 0xde
+ #define VHDMI_OFF 0x25
+ #define VHDMI_ON 0xa5
+#define MSIC_HDMI_STATUS 0x281
+ #define HPD_SIGNAL_STATUS (1 << 0)
+
+#endif //__IHDMI_H__
--- /dev/null
+/*
+ * Copyright © 2006-2007 Intel 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 (including the next
+ * paragraph) 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.
+ *
+ * Authors:
+ *
+ */
+/* chunfeng.zhao@intel.com
+ */
+#ifndef PSB_INTEL_HDMI_EDID_H
+#define PSB_INTEL_HDMI_EDID_H
+
+//#include "..\\..\\Common\\Platform.h"
+
+////////////////////////////////////////////
+//
+// Max number of EDID extensions possible
+//
+////////////////////////////////////////////
+#define MAX_EDID_EXTENSIONS 254 //Max EDID blocks minus Block 0
+#define NUM_BASEEDID_STANDARD_TIMING 8
+#define MAX_BASEEDID_DTD_BLOCKS 4
+
+#define MAX_VIC_DEFINED 128
+
+// New Macros for supporting EDID 1.4
+
+// Macros for EDID Revision and Version
+#define EDID_VERSION_1 0x01
+#define EDID_REVISION_4 0x04
+
+// Macros for CVT and GTF related support in Monitor descriptor
+#define EDID14_CVT_TIMING_SUPPORTED 0x04
+#define EDID14_DEFAULT_GTF_SUPPORTED 0x00
+#define EDID14_SECONDARY_GTF_SUPPORTED 0x02
+
+// Macros for display device data block in CEA.
+#define EDID14_DISPLAY_DEVICE_DATA_TAG 0xFF
+#define EDID14_DISPLAY_DEVICE_DATA_CHILD_TAG 0x02
+#define EDID14_DISPLAY_DEVICE_DATA_LENGTH 0x20
+#define EDID14_DISPLAY_PORT_INTERFACE 0x09
+
+// Macros indicating digital interfaces supported by the display.
+#define EDID14_DVI_SUPPORTED 0x01
+#define EDID14_DISPLAY_PORT_SUPPORTED 0x05
+#define EDID14_HDMI_A_SUPPORTED 0x02
+#define EDID14_HDMI_B_SUPPORTED 0x03
+
+#define EDID14_MAX_MONITOR_DESCRIPTORS 0x03
+
+// Macros related to EDID 1.4 Color Bit Depth support
+#define EDID14_COLOR_BIT_DEPTH_UNDEFINED 0x00
+#define EDID14_SIX_BITS_PER_PRIMARY_COLOR 0x06
+#define EDID14_EIGHT_BITS_PER_PRIMARY_COLOR 0x08
+#define EDID14_TEN_BITS_PER_PRIMARY_COLOR 0x0A
+#define EDID14_TWELVE_BITS_PER_PRIMARY_COLOR 0x0C
+#define EDID14_FOURTEEN_BITS_PER_PRIMARY_COLOR 0x0E
+#define EDID14_SIXTEEN_BITS_PER_PRIMARY_COLOR 0x10
+#define EDID14_INVALID_COLOR_BIT_DEPTH 0x07
+
+// Macro for showing Color Bit Depth support for existing displays
+#define EDID_EIGHT_BITS_PER_PRIMARY_COLOR 0x08
+
+// Macro for Established Timings III Block descriptor
+#define EST_TIMINGS_III_BLOCK_TAG 0xF7
+#define EST_TIMINGS_III_BLOCK_DATA_LENGTH 0x06
+
+// Macro for indicating byte length
+#define BYTE_LENGTH 0x08
+
+////////////////////////////////////////////
+//
+// Max number of EDID Blocks
+//
+////////////////////////////////////////////
+#define MAX_EDID_BLOCKS 255 //According to E-EDID Standard doc.
+#define EDID_BLOCK_SIZE 128
+
+// Macros for EDID Revision and Version for EDID 1.3
+#define EDID_VERSION_1_3 0x01
+#define EDID_REVISION_1_3 0x03
+
+////////////////////////////////////////////
+// Base EDID header
+////////////////////////////////////////////
+static const unsigned char BASEEDID_Header[8] = {0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00};
+
+// Display Range Limits Offset Flags.
+// Applicable only from EDID 1.4 onwards
+typedef union _edid_range_limits_flags {
+ uint8_t ucRangeLimitOffsetFlags; // Range Limits Offset Flags
+ struct {
+ uint8_t ucVerticalRateOffset : 2; // Vertical Rate Offset
+ uint8_t ucHorizontalRateOffset : 2; // Horizontal Rate Offset
+ uint8_t ucReserved : 4; // Reserved.
+ };
+} edid_range_limits_flags_t;
+
+////////////////////////////////////////////
+//
+// 18-byte DTD block
+// Refer Table 3.16, 3.17 & 3.18 of
+// EDID spec
+//
+////////////////////////////////////////////
+typedef struct _edid_dtd_timing {
+#pragma pack(1)
+
+ int16_t wPixelClock; // Pixel clock / 10000
+
+ uint8_t ucHA_low; // Lower 8 bits of H. active pixels
+ uint8_t ucHBL_low; // Lower 8 bits of H. blanking
+ union {
+ uint8_t ucHAHBL_high;
+ struct {
+ uint8_t ucHBL_high : 4; // Upper 4 bits of H. blanking
+ uint8_t ucHA_high : 4; // Upper 4 bits of H. active pixels
+ };
+ };
+
+ uint8_t ucVA_low; // Lower 8 bits of V. active lines
+ uint8_t ucVBL_low; // Lower 8 bits of V. blanking
+ union {
+ uint8_t ucVAVBL_high;
+ struct {
+ uint8_t ucVBL_high : 4; // Upper 4 bits of V. blanking
+ uint8_t ucVA_high : 4; // Upper 4 bits of V. active pixels
+ };
+ };
+
+ uint8_t ucHSO_low; // Lower 8 bits of H. sync offset
+ uint8_t ucHSPW_low; // Lower 8 bits of H. sync pulse width
+ union {
+ uint8_t ucVSOVSPW_low;
+ struct {
+ uint8_t ucVSPW_low : 4; // Lower 4 bits of V. sync pulse width
+ uint8_t ucVSO_low : 4; // Lower 4 bits of V. sync offset
+ };
+ };
+ union {
+ uint8_t ucHSVS_high;
+ struct {
+ uint8_t ucVSPW_high : 2; // Upper 2 bits of V. sync pulse width
+ uint8_t ucVSO_high : 2; // Upper 2 bits of V. sync offset
+ uint8_t ucHSPW_high : 2; // Upper 2 bits of H. sync pulse width
+ uint8_t ucHSO_high : 2; // Upper 2 bits of H. sync offset
+ };
+ };
+
+ uint8_t ucHIS_low; // Lower 8 bits of H. image size in mm
+ uint8_t ucVIS_low; // Lower 8 bits of V. image size in mm
+ union {
+ uint8_t ucHISVIS_high;
+ struct {
+ uint8_t ucVIS_high : 4; // Upper 4 bits of V. image size
+ uint8_t ucHIS_high : 4; // Upper 4 bits of H. image size
+ };
+ };
+
+ uint8_t ucHBorder; // H. border in pixels
+ uint8_t ucVBorder; // V. border in pixels
+
+ union {
+ uint8_t ucFlags; // Hsync & Vsync polarity, etc. flags
+ struct {
+ uint8_t ucStereo1 : 1; // Stereo definition with bit[6:5]
+ uint8_t ucHSync_Pol : 1; // Hsync polarity (0: Neg, 1: Pos)
+ uint8_t ucVSync_Pol : 1; // Vsync polarity (0: Neg, 1: Pos)
+ uint8_t ucSync_Conf : 2; // Sync configuration
+ // 00 : Analog composite
+ // 01 : Bipolar analog composite
+ // 00 : Digital composite
+ // 00 : Digital separate
+ uint8_t ucStereo2 : 2; // Stereo definition
+ // 00 : Normal display, no stereo
+ // xx : Stereo definition with bit0
+ uint8_t ucInterlaced : 1; // Interlaced / Non-interlaced
+ // 0 : Non-interlaced
+ // 1 : Interlaced
+ };
+ };
+
+#pragma pack()
+} edid_dtd_timing_t;
+
+
+////////////////////////////////////////////
+//
+// Standard timing identification
+// Refer Table 3.15 of EDID spec
+//
+////////////////////////////////////////////
+typedef union _edid_std_timing {
+ uint16_t usStdTiming;
+
+ struct {
+#pragma pack(1)
+ uint8_t ucHActive; // (HActive/8) - 31;
+ struct {
+ uint8_t ucRefreshRate : 6; // Refresh Rate - 60
+ uint8_t ucAspectRatio : 2; // Aspect ratio (HActive/VActive)
+ // 00: 1:1 Aspect ratio
+ // 01: 4:3 Aspect ratio
+ // 10: 5:4 Aspect ratio
+ // 11: 16:9 Aspect ratio
+ };
+ };
+#pragma pack()
+
+} edid_std_timing_t;
+////////////////////////////////////////////////////////
+// Aspect Ratio def's as per Edid 1.3 Standard Timings
+////////////////////////////////////////////////////////
+#define EDID_STD_ASPECT_RATIO_16_10 0x0
+#define EDID_STD_ASPECT_RATIO_4_3 0x1
+#define EDID_STD_ASPECT_RATIO_5_4 0x2
+#define EDID_STD_ASPECT_RATIO_16_9 0x3
+
+
+////////////////////////////////////////////
+//
+// Monitor range limits
+//
+////////////////////////////////////////////
+typedef struct _monitor_range_limits {
+#pragma pack(1)
+
+ uint8_t ucMin_vert_rate; //Min Vertical Rate,in Hz
+ uint8_t ucMax_vert_rate; //Max Vertical Rate, in Hz
+ uint8_t ucMin_horz_rate; //Min Horizontal Rate, in Hz
+ uint8_t ucMax_horz_rate; //Max Horizontal Rate, in Hz
+ uint8_t ucMax_pixel_clock; //Max Pixel Clock,Value/10 Mhz
+ uint8_t ucTiming_formula_support; //00 - No Secondary Timing Formula Supported
+ //02 - Secondary GTF Curve Supported
+ //In EDID 1.4, this may indicate CVT support as well
+ //If timing_formula_support is 02
+ uint8_t ucReserved; //00h
+ uint8_t ucStart_freq; //Horizontal Freq, Value/2, KHz
+ uint8_t ucByte_C; //C*2
+ uint8_t ucLSB_M; //LSB of M Value
+ uint8_t ucMSB_M; //MSB of M Value
+ uint8_t ucByte_K; //K Value
+ uint8_t ucByte_J; //J*2
+
+#pragma pack()
+} monitor_range_limits_t;
+
+////////////////////////////////////////////
+//
+// Color point
+//
+////////////////////////////////////////////
+typedef struct _color_point {
+#pragma pack(1)
+
+ uint8_t ucWhite_point_index_number_1;
+ uint8_t ucWhite_low_bits_1;
+ uint8_t ucWhite_x_1;
+ uint8_t ucWhite_y_1;
+ uint8_t ucWhite_gamma_1;
+ uint8_t ucWhite_point_index_number_2;
+ uint8_t ucWhite_low_bits_2;
+ uint8_t ucWhite_x_2;
+ uint8_t ucWhite_y_2;
+ uint8_t ucWhite_gamma_2;
+ uint8_t ucByte_15;
+ uint8_t ucByte_16_17[2];
+
+#pragma pack()
+} color_point_t;
+
+////////////////////////////////////////////
+//
+// Monitor description descriptor
+// Refer Table 3.19 & 3.20 of EDID spec
+//
+////////////////////////////////////////////
+#define BASEEDID_MONITORSN_MDDATATYPE 0xFF
+#define BASEEDID_ASCIISTRING_MDDATATYPE 0xFE
+#define BASEEDID_MONITORRANGELIMIT_MDDATATYPE 0xFD
+#define BASEEDID_MONITORNAME_MDDATATYPE 0xFC
+#define BASEEDID_COLORPOINT_MDDATATYPE 0xFB
+#define BASEEDID_STDTIMINGS_MDDATATYPE 0xFA
+
+// Structure definition for Established Timings III monitor block
+typedef struct _est_timings_iii_block {
+#pragma pack(1)
+ // The first byte will show the VESA DMTS Standard Version.
+ // The following six bytes will have the Timings Bit Mask.
+ // Right now only 6 bytes are used for this!!!
+ // Rest is reserved.
+ uint8_t ucVesaDMTVersion; //Byte 0 indicating the VESA DMT Version.
+ uint8_t ucTimingBitMask[6];// Next 6 bytes indicating the Timing Bit Mask Bytes used in Est Timing III.
+ uint8_t bReserved[6];//Next 6 bytes are reserved
+#pragma pack()
+} est_timings_iii_block_t;
+
+typedef struct _monitor_descriptor {
+#pragma pack(1)
+
+ int16_t wFlag; // = 0000 when block is used as descriptor
+ uint8_t ucFlag0; // Reserved
+
+ uint8_t ucDataTypeTag;
+
+ uint8_t ucFlag1; // 00 for descriptor
+
+ union {
+
+ // Monitor S/N (ucDataTypeTag = FF)
+ uint8_t ucMonitorSerialNumber[13];
+
+ // ASCII string (ucDataTypeTag = FE)
+ uint8_t ucASCIIString[13];
+
+ // Monitor range limit (ucDataTypeTag = FD)
+ monitor_range_limits_t MonitorRangeLimits;
+
+ // Monitor name (ucDataTypeTag = FC)
+ uint8_t ucMonitorName[13];
+
+ // Color point (ucDataTypeTag = FB)
+ color_point_t ColorPoint;
+
+ // ESTABLISHED TIMINGS III BLOCK = F7 (Added for EDID 1.4)
+ est_timings_iii_block_t stEstTimingsIIIBlock;
+
+ // Standard timings (ucDataTypeTag = FA)
+ struct {
+ edid_std_timing_t ExtraStdTiming[6];
+ uint8_t ucFixedValueOfA0; // Should be 0xA0
+ };
+
+ // Manufacturer specific value (ucDataTypeTag = 0F-00)
+ uint8_t ucMfgSpecificData[13];
+ };
+
+#pragma pack()
+} monitor_descriptor_t;
+
+////////////////////////////////////////////
+//
+// EDID PnP ID fields
+//
+////////////////////////////////////////////
+typedef union _baseedid_pnpid {
+ uint8_t VendorProductID[10]; // Vendor / Product identification
+
+ struct {
+ uint8_t ManufacturerID[2]; // Bytes 8, 9: Manufacturer ID
+ uint8_t ProductID[2]; // Bytes 10, 11: Product ID
+ uint8_t SerialNumber[4]; // Bytes 12-15: Serial numbers
+ uint8_t WeekOfManufacture; // Byte 16: Week of manufacture
+ uint8_t YearOfManufacture; // Byte 17: Year of manufacture
+ };
+} baseedid_pnpid_t;
+
+//
+// Chromaticity structure
+// Table 3.12 of Base Block for details
+//
+typedef struct _baseedid_chromaticity_block {
+ union{
+ uint8_t RedGreenLowBits; // Byte 1
+ struct{
+ uint8_t ucGreenYLowBits : 2; // bit 1:0
+ uint8_t ucGreenXLowBits : 2; // bit 3:2
+ uint8_t ucRedYLowBits : 2; // bit 5:4
+ uint8_t ucRedXLowBits : 2; // bit 7:6
+ };
+ };
+
+ union{
+ uint8_t ucBlueWhiteLowBits; // Byte 2
+ struct{
+ uint8_t ucWhiteYLowBits : 2; // bit 1:0
+ uint8_t ucWhiteXLowBits : 2; // bit 3:2
+ uint8_t ucBlueYLowBits : 2; // bit 5:4
+ uint8_t ucBlueXLowBits : 2; // bit 7:6
+ };
+ };
+
+ uint8_t ucRedXUpperBits; // bit 9:2 Byte 3
+ uint8_t ucRedYUpperBits; // bit 9:2 Byte 4
+
+ uint8_t ucGreenXUpperBits; // bit 9:2 Byte 5
+ uint8_t ucGreenYUpperBits; // bit 9:2 Byte 6
+
+ uint8_t ucBlueXUpperBits; // bit 9:2 Byte 7
+ uint8_t ucBlueYUpperBits; // bit 9:2 Byte 8
+
+ uint8_t ucWhiteXUpperBits; // bit 9:2 Byte 9
+ uint8_t ucWhiteYUpperBits; // bit 9:2 Byte 10
+} baseedid_chromaticity_block_t;
+
+////////////////////////////////////////////
+//
+// 128-byte EDID 1.x block0 structure
+//
+////////////////////////////////////////////
+typedef struct _baseedid_1_x {
+#pragma pack(1)
+
+ //
+ // Header: 8 bytes (Table 3.3 of EDID spec)
+ char Header[8]; // EDID1.x header "0 FFh FFh FFh FFh FFh FFh 0"
+
+ //
+ // Vendor/Product ID: 10 bytes (Table 3.4, 3.5 & 3.6 of EDID spec)
+ //baseedid_pnpid_t;
+ union {
+ uint8_t VendorProductID[10]; // Vendor / Product identification
+ struct {
+ uint8_t ManufacturerID[2]; // Bytes 8, 9: Manufacturer ID
+ uint8_t ProductID[2]; // Bytes 10, 11: Product ID
+ uint8_t SerialNumber[4]; // Bytes 12-15: Serial numbers
+ uint8_t WeekOfManufacture; // Byte 16: Week of manufacture
+ uint8_t YearOfManufacture; // Byte 17: Year of manufacture
+ };
+ };
+
+ //
+ // EDID structure Version/Revision: 2 bytes (Table 3.7 of EDID spec)
+ uint8_t ucVersion; // EDID version no.
+ uint8_t ucRevision; // EDID revision no.
+
+ //
+ // Basic display parameters & features: 5 bytes (Table 3.8 of EDID spec)
+ union {
+ uint8_t ucVideoInput; // Video input definition (Refer Table 3.9 of EDID spec)
+
+ struct {
+ uint8_t ucSyncInput : 4; // Sync input supported (iff ucDigitInput = 0)
+ uint8_t ucSetup : 1; // Display setup (iff ucDigitInput = 0)
+ uint8_t ucSigLevStd : 2; // Signal level Standard (iff ucDigitInput = 0)
+
+ uint8_t ucDigitInput : 1; // 1: Digital input; 0: Analog input
+ };
+ };
+
+ // Image size (Table 3.10 of EDID spec)
+ uint8_t ucMaxHIS; // Maximum H. image size in cm
+ uint8_t ucMaxVIS; // Maximum V. image size in cm
+
+ // Gamma (display transfer characteristic)
+ uint8_t ucGamma; // Display gamma value [= (gamma*100)-100]
+
+ // Feature support (Table 3.11 of EDID spec)
+ union {
+ uint8_t ucDMPSFeature; // DPMS feature support
+
+ struct {
+ uint8_t ucGTFSupport : 1; // GTF timing support (1: Yes)
+ uint8_t ucPTM : 1; // Preferred timing is 1st DTD (1: Yes) [Must if EDID >= 1.3]
+ uint8_t ucColorSpace : 1; // Use STD color space (1:Yes) [If set ColorChars should match sRGB values in EDID spec Appendix A]
+ uint8_t ucDispType : 2; // Display type
+ // 00: Monochrome
+ // 01: R/G/B color display
+ // 10: Non R/G/B multicolor display
+ // 11: Undefined
+ uint8_t ucActiveOff : 1; // Active off (Display consumes less power/blanks out when it receives an out of range timing)
+ uint8_t ucSuspend : 1; // Suspend (Refer VESA DPMS spec)
+ uint8_t ucStandBy : 1; // Stand-by (Refer VESA DPMS spec)
+ };
+ };
+
+ //
+ // Phosphor or Filter Chromaticity: 10 bytes
+ uint8_t ColorChars[10]; // Color characteristics (Refer Table 3.12 of EDID spec)
+
+ //
+ // Established timings: 3 bytes (Table 3.14 of EDID spec)
+ union {
+ uint8_t EstTiming1;
+ struct {
+ uint8_t bSupports800x600_60 : 1;
+ uint8_t bSupports800x600_56 : 1;
+ uint8_t bSupports640x480_75 : 1;
+ uint8_t bSupports640x480_72 : 1;
+ uint8_t bSupports640x480_67 : 1;
+ uint8_t bSupports640x480_60 : 1;
+ uint8_t bSupports720x400_88 : 1;
+ uint8_t bSupports720x400_70 : 1;
+ };
+ };
+ union {
+ uint8_t EstTiming2;
+ struct {
+ uint8_t bSupports1280x1024_75 : 1;
+ uint8_t bSupports1024x768_75 : 1;
+ uint8_t bSupports1024x768_70 : 1;
+ uint8_t bSupports1024x768_60 : 1;
+ uint8_t bSupports1024x768_87i : 1;
+ uint8_t bSupports832x624_75 : 1;
+ uint8_t bSupports800x600_75 : 1;
+ uint8_t bSupports800x600_72 : 1;
+ };
+ };
+ union {
+ uint8_t MfgTimings;
+ struct {
+ uint8_t bMfgReservedTimings : 7;
+ uint8_t bSupports1152x870_75 : 1;
+ };
+ };
+
+ //
+ // Standard timings: 8 bytes (Table 3.15 of EDID spec)
+ edid_std_timing_t StdTiming[NUM_BASEEDID_STANDARD_TIMING]; // 8 Standard timing support
+
+ //
+ // Detailed timing section - 72 bytes (4*18 bytes)
+ union {
+ edid_dtd_timing_t DTD[MAX_BASEEDID_DTD_BLOCKS]; // Four DTD data blocks
+
+ monitor_descriptor_t MonitorInfo[MAX_BASEEDID_DTD_BLOCKS];
+ };
+
+ uint8_t ucNumExtBlocks; // Number of extension EDID blocks
+ uint8_t ucChecksum; // Checksum of the EDID block
+
+#pragma pack()
+} baseedid_1_x_t;
+
+////////////////////////////////////////////
+//
+// 128-byte EDID 1.4 block0 structure
+// EDID 1.4 block0 structure is different from 1.3 block0
+// Thats why this new structure has been added
+// Changes are commented in the structure itself
+//
+////////////////////////////////////////////
+typedef struct _baseedid_1_4 {
+#pragma pack(1)
+
+ //
+ // Header: 8 bytes (Table 3.3 of EDID spec)
+ char Header[8]; // EDID1.x header "0 FFh FFh FFh FFh FFh FFh 0"
+
+ //
+ // Vendor/Product ID: 10 bytes (Table 3.4, 3.5 & 3.6 of EDID spec)
+ union {
+ uint8_t VendorProductID[10]; // Vendor / Product identification
+ struct {
+ uint8_t ManufacturerID[2]; // Bytes 8, 9: Manufacturer ID
+ uint8_t ProductID[2]; // Bytes 10, 11: Product ID
+ uint8_t SerialNumber[4]; // Bytes 12-15: Serial numbers
+ uint8_t WeekOfManufacture; // Byte 16: Week of manufacture
+ uint8_t YearOfManufacture; // Byte 17: Year of manufacture
+ };
+ };
+
+ //
+ // EDID structure Version/Revision: 2 bytes (Table 3.7 of EDID spec)
+ uint8_t ucVersion; // EDID version no.
+ uint8_t ucRevision; // EDID revision no.
+
+ //
+ // Basic display parameters & features: 5 bytes (Table 3.8 of EDID spec)
+ union {
+ uint8_t ucVideoInput; // Video input definition (Refer Table 3.9 of EDID spec)
+
+ struct {
+ uint8_t ucSyncInput : 4; // Sync input supported (iff ucDigitInput = 0)
+ uint8_t ucSetup : 1; // Display setup (iff ucDigitInput = 0)
+ uint8_t ucSigLevStd : 2; // Signal level Standard (iff ucDigitInput = 0)
+
+ uint8_t ucDigitInput : 1; // 1: Digital input; 0: Analog input
+ };
+ // This structure has been introduced to reflect the changes in EDID 1.4 spec
+ // This sturcture shows new meaning of VIDEO INPUT DEFINITION when input is digital
+ struct {
+ uint8_t ucDigitalVideoInterface : 4; // Digital Video Interface Standard Supported.
+ uint8_t ucColorBitDepth : 3; // Color Bit Depth.
+ // 0 0 0 -- Color Bit Depth is undefined
+ // 0 0 1 -- 6 Bits per Primary Color
+ // 0 1 0 -- 8 Bits per Primary Color
+ // 0 1 1 -- 10 Bits per Primary Color
+ // 1 0 0 -- 12 Bits per Primary Color
+ // 1 0 1 -- 14 Bits per Primary Color
+ // 1 1 0 -- 16 Bits per Primary Color
+ // 1 1 1 -- Reserved (Do Not Use)
+ uint8_t bIsDigitalVideoSignalInterface : 1; // Bit 7
+ };
+ };
+
+ // As per the EDID spec 1.4, the following two fields can be aspect ratios as well.
+ union {
+ uint8_t ucMaxHIS; // Maximum H. image size in cm
+ uint8_t ucARLandscape; // Landscape Aspect raio as per EDID 1.4 spec
+ };
+ union {
+ uint8_t ucMaxVIS; // Maximum V. image size in cm
+ uint8_t ucARPortrait; // Portrait Aspect raio as per EDID 1.4 spec
+ };
+
+ // Gamma (display transfer characteristic)
+ uint8_t ucGamma; // Display gamma value [= (gamma*100)-100]
+
+ // Feature support (Table 3.11 of EDID spec)
+ union {
+ uint8_t ucDMPSFeature; // DPMS feature support
+
+ struct {
+ uint8_t ucContinuousDisplay : 1; // Display is continuous or non-continuous (1: Yes)
+ uint8_t ucPTM : 1; // Preferred timing mode indicates native pixel format and native RR.
+ uint8_t ucColorSpace : 1; // Use STD color space (1:Yes) [If set ColorChars should match sRGB values in EDID spec Appendix A]
+ uint8_t ucDispType : 2; // Display type
+ // 00: Monochrome
+ // 01: R/G/B color display
+ // 10: Non R/G/B multicolor display
+ // 11: Undefined
+ uint8_t ucActiveOff : 1; // Active off (Display consumes less power/blanks out when it receives an out of range timing)
+ uint8_t ucSuspend : 1; // Suspend (Refer VESA DPMS spec)
+ uint8_t ucStandBy : 1; // Stand-by (Refer VESA DPMS spec)
+ };
+
+ struct {
+ uint8_t bReserved0 : 1;
+ uint8_t bReserved1 : 1;
+ uint8_t bReserved2 : 1;
+ uint8_t ucColorEncodingFormat : 2; // Supported Color Encoding Format if Video Input is digital
+ // 00: RGB 4:4:4
+ // 01: RGB 4:4:4 & YCrCb 4:4:4
+ // 10: RGB 4:4:4 & YCrCb 4:2:2
+ // 11: RGB 4:4:4 & YCrCb 4:4:4 & YCrCb 4:2:2
+ uint8_t bReserved3 : 1;
+ uint8_t bReserved4 : 1;
+ uint8_t bReserved5 : 1;
+ };
+ };
+
+ //
+ // Phosphor or Filter Chromaticity: 10 bytes
+ uint8_t ColorChars[10]; // Color characteristics (Refer Table 3.12 of EDID spec)
+
+ //
+ // Established timings: 3 bytes (Table 3.14 of EDID spec)
+ union {
+ uint8_t EstTiming1;
+ struct {
+ uint8_t bSupports800x600_60 : 1;
+ uint8_t bSupports800x600_56 : 1;
+ uint8_t bSupports640x480_75 : 1;
+ uint8_t bSupports640x480_72 : 1;
+ uint8_t bSupports640x480_67 : 1;
+ uint8_t bSupports640x480_60 : 1;
+ uint8_t bSupports720x400_88 : 1;
+ uint8_t bSupports720x400_70 : 1;
+ };
+ };
+ union {
+ uint8_t EstTiming2;
+ struct {
+ uint8_t bSupports1280x1024_75 : 1;
+ uint8_t bSupports1024x768_75 : 1;
+ uint8_t bSupports1024x768_70 : 1;
+ uint8_t bSupports1024x768_60 : 1;
+ uint8_t bSupports1024x768_87i : 1;
+ uint8_t bSupports832x624_75 : 1;
+ uint8_t bSupports800x600_75 : 1;
+ uint8_t bSupports800x600_72 : 1;
+ };
+ };
+ union {
+ uint8_t MfgTimings;
+ struct {
+ uint8_t bMfgReservedTimings : 7;
+ uint8_t bSupports1152x870_75 : 1;
+ };
+ };
+
+ //
+ // Standard timings: 8 bytes (Table 3.15 of EDID spec)
+ edid_std_timing_t StdTiming[NUM_BASEEDID_STANDARD_TIMING]; // 8 Standard timing support
+
+ // Detailed timing section - 72 bytes (4*18 bytes)
+ // As per the new spec 1.4, the first Detailed Timing Section should contain the PREFERED TIMING BLOCK
+ edid_dtd_timing_t PreferedTimingMode;
+ // The rest 54 bytes of the Detailed Timing Section.
+ union {
+ edid_dtd_timing_t DTD[MAX_BASEEDID_DTD_BLOCKS - 1]; // Three DTD data blocks
+
+ monitor_descriptor_t MonitorInfo[MAX_BASEEDID_DTD_BLOCKS - 1]; // Three Monitor Descriptor blocks
+ };
+
+ uint8_t ucNumExtBlocks; // Number of extension EDID blocks
+ uint8_t ucChecksum; // Checksum of the EDID block
+
+#pragma pack()
+} baseedid_1_4_t;
+
+
+//*****************************************************
+//*****************************************************
+//
+// DATA STRUCTURES AND DEFINITIONS FOR CE-EXTENSION
+//
+//*****************************************************
+//*****************************************************
+
+/////////////////////////////////
+//
+//CE - Extension Block Structure
+//
+/////////////////////////////////
+typedef struct _ce_edid {
+ uint8_t ucTag;
+ uint8_t ucRevision;
+ uint8_t ucDTDOffset;
+ uint8_t ucCapabilty;
+ uint8_t data[123];
+ uint8_t ucCheckSum;
+} ce_edid_t;
+
+////////////////////////////////////////////
+//
+//CE - Video Capability Data block structure
+//
+////////////////////////////////////////////
+typedef union _video_cap_data_block {
+ uint8_t ucValue;
+ struct
+ {
+ uint8_t ucCEScanBehavior :2; // Indicates scan behavior of CE mode
+ uint8_t ucITScanBehavior :2; // Indicates scan behavior of IT mode
+ uint8_t ucPTScanBehavior :2; // Indicates scan behavior of Preferred mode
+ uint8_t ucQuantRangeSelectable :1; // Indicates if RGB Quantization Range can be overridden
+ uint8_t ucReserved :1;
+ };
+} video_cap_data_block_t;
+
+////////////////////////////////////////////
+//
+//CEA Extn Block Byte3 structure
+//
+////////////////////////////////////////////
+typedef union _cea_ext_capability {
+ uint8_t ucValue;
+ struct
+ {
+ uint8_t ucTotalNativeDTDs :4; // Total number of DTDs in extension block
+ uint8_t ucSupportsYCBCR422 :1; // Indicates support for YCBCR 4:2:2
+ uint8_t ucSupportsYCBCR444 :1; // Indicates support for YCBCR 4:4:4
+ uint8_t ucSupportsBasicAudio :1; // Indicates support for Basic audio
+ uint8_t ucUnderscansITFormats :1; // Indicates underscan behavior of IT formats
+ };
+} cea_ext_capability_t;
+
+////////////////////////////////////////////
+//
+//CE - Video Capability Data block structure
+//
+////////////////////////////////////////////
+typedef enum {
+ FORMAT_NOT_SUPPORTED = 0, // Format is not supported
+ ALWAYS_OVERSCANNED = 1, // Format is always overscanned
+ ALWAYS_UNDERSCANNED = 2, // Format is always underscanned
+ SUPPORTS_OVER_AND_UNDERSCAN = 3 // Sink supports both overscan and underscan
+} cea_scan_behavior_t;
+
+
+/////////////////////////////////
+//
+// #defines required for CE Etxn
+//
+/////////////////////////////////
+#define CEA_EXT_TAG 0x02
+#define CEA_EXT_SUPPORTED_VERSION 0x03
+#define CEA_EXT_861_REVISION 0x01
+
+#define CEA_USE_EXTENDED_TAG 0x7
+
+#define CEA_AUDIO_DATABLOCK 0x1
+#define CEA_VIDEO_DATABLOCK 0x2
+#define CEA_VENDOR_DATABLOCK 0x3
+#define CEA_SPEAKER_DATABLOCK 0x4
+#define CEA_VIDEO_CAP_DATABLOCK 0x0
+
+#define CEA_DATABLOCK_TAG_MASK 0xE0
+#define CEA_DATABLOCK_LENGTH_MASK 0x1F
+#define CEA_SHORT_VIDEO_DESCRIPTOR_CODE_MASK 0x7F
+#define CEA_NATIVE_FORMAT_BIT_MASK 0x80
+
+#define CEA_HDMI_IEEE_REG_ID 0x00000C03
+#define CEA_EDID_HEADER_SZIE 0x04
+
+// Extended Data block type
+// This bit definitions are as per CE 861-D spec
+#define CEA_COLORIMETRY_DATABLOCK 0x5
+ #define CE_COLORIMETRY_MD0_MASK BIT(0)
+ #define CE_COLORIMETRY_MD1_MASK BIT(1)
+ #define CE_COLORIMETRY_MD2_MASK BIT(3)
+#if 0
+//==================================================================================
+//==================================================================================
+// DATA Structure definitions for VTB parsing.....
+// Reference VESA Documents are VTB Extension(Release A) & CVT standard version 1.1
+//===================================================================================
+// #defines for VTB-EXT
+//===================================================================================
+
+#define VTB_EXT_TAG 0x10
+#define VTB_EXT_SUPPORTED_VERSION 0x03
+
+#define VTB_MAX_DTD_TIMINGS 6
+#define VTB_MAX_CVT_TIMINGS 40
+#define VTB_MAX_STANDARD_TIMINGS 61
+
+#define VTB_DTD_OFFSET 5
+#define VTB_DTD_SIZE 18
+#define VTB_CVT_SIZE 3
+#define VTB_ST_SIZE 2
+
+// This struct is for VTB Extension block.
+typedef struct _VTB_EXT
+{
+ uint8_t ucTag;
+ uint8_t ucVersion;
+ uint8_t ulNumDTD;
+ uint8_t ulNumCVT;
+ uint8_t ulNumST;
+ uint8_t DATA[122];
+ uint8_t ucChecksum;
+}VTB_EXT, *PVTB_EXT;
+
+// Following struct is for CVT descriptor (Version 1.1)
+typedef struct _VTB_CVT_TIMING
+{
+#pragma pack(1)
+
+ uint8_t ucVA_low; // Lower 8 bits of Vertical size. This Vsize = (vertical active lines/2)-1.
+ // Range for VA lines is 2 to 8192. CVT supprts only an even no. of active lines per frame.
+
+ union {
+ uint8_t ucVA_high_AR;
+ struct {
+
+ uint8_t ucReserved00 :2; //Bits 1-0 are reserved and set to 00h
+ uint8_t ucAspectRatio :2; // Aspect Ratio specifier bits.
+ // 00: 4:3 Aspect ratio
+ // 01: 16:9 Aspect ratio
+ // 10: 16:10 Aspect ratio
+ // 11: Undefined (Reserved)
+
+
+ uint8_t ucVA_high :4; // Upper 4 bits of Vertical Size.
+ };
+ };
+
+ union {
+ uint8_t ucRefresh_Rate_Bits;
+ struct {
+
+ uint8_t ucRR_60Hz_RB :1; // When set, indicates 60Hz support with Reduced Blanking.
+ uint8_t ucRR_85Hz :1; // || 85Hz || .
+ uint8_t ucRR_75Hz :1; // || 75Hz || .
+ uint8_t ucRR_60Hz :1; // || 60Hz || .
+ uint8_t ucRR_50Hz :1; // When set, indicates 50Hz Refrash Rate with CRT Blanking supports specified pixel format.
+ uint8_t ucPreferredRefresh_Rate :2; // Preferred Refresh Rate specifier bits.
+ // 00: 50 Hz
+ // 01: 60 Hz (this means either CRT blanking or Reduced Blanking whichever is supported.
+ // If both are supported, then RB is preferred.)
+ // 10: 75 Hz
+ // 11: 85 Hz
+
+ uint8_t ucReserved0 :1; // This bit is reserved and set to '0'.
+
+ };
+ };
+#pragma pack()
+} VTB_CVT_TIMING, *PVTB_CVT_TIMING;
+
+
+// This struct is for storing extracted Info from CVT descriptor....
+// This is defined by author.....not based on CVT specs.
+typedef struct _CVT_INFO
+{
+ ULONG ulYRes;
+ ULONG ulXRes;
+ ULONG ulRRate[5]; //As max 5 Refresh Rates can be supported.
+ BOOLEAN bRed_Blank_Req[5];
+ BOOLEAN bPreferred_RR[5]; //To set flag for Preffered RR
+ ULONG ulNumRates; //Number of Refresh rates Supported. (Max. 5)
+} CVT_INFO, *PCVT_INFO;
+#endif
+// This structure is for stroing the Display device Data retreived from CEA block
+// This is defined as per the Display Device Data Block standard.
+typedef struct _display_device_data {
+#pragma pack (1)
+ union
+ {
+ uint8_t ucTagAndLength; // Data Block Tag and Block Length. should be 0xFF
+ struct
+ {
+ uint8_t ucLength : 5;
+ uint8_t ucTag : 3;
+ };
+ };
+ uint8_t ucChildTag; // Child tag required as per CEA spec should be 0x02
+ union
+ {
+ uint8_t ucInterfaceType;
+ struct
+ {
+ uint8_t ucNumOfChannels : 4;// Number of channels supported
+ uint8_t ucInterfaceCode : 4;// Interface code
+ };
+ };
+ union
+ {
+ uint8_t ucVerAndRel;
+ struct
+ {
+ uint8_t ucRelease : 4;// Release
+ uint8_t ucVersion : 4;// Version.
+ };
+ };
+ uint8_t ucContentProtectionSuppFlag;// Flag indicating support for content protection.
+ union
+ {
+ uint16_t usClockFrequency;// Clock Frequency
+ struct
+ {
+ uint16_t usMinClockFrequency : 6; // First 6 bits indicates Min frequency
+ uint16_t usMaxClockFrequency : 10;// Next 10 bits indicates Max frequency
+ };
+ };
+ union
+ {
+ uint8_t ucNativePixelFormat[4];// Pixel Format
+ struct
+ {
+ uint8_t ucHorizontalPixelCntLower;// Lower byte value of the Horizontal pixel count
+ uint8_t ucHorizontalPixelCntUpper;// Upper byte value of the Horizontal pixel count
+ uint8_t ucVerticalPixelCntLower;// Lower byte value of the vertical pixel count
+ uint8_t ucVerticalPixelCntUpper; // Upper byte value of the vertical pixel count
+ };
+ };
+ uint8_t ucAspectRatio;// Byte indicating Aspect ratio.
+ union
+ {
+ uint8_t ucOrientationAndRotation;
+ struct
+ {
+ uint8_t ucScanDirection : 2;// Scan direction.
+ uint8_t ucZeroPixelLocation : 2;// Zero Pixel Location.
+ uint8_t ucRotationCapability : 2;// Indicates rotation capability
+ uint8_t ucDefaultOrientation : 2;// Default Orientation.
+ };
+ };
+ uint8_t ucSubPixelInfo;// Sub-Pixle Information.
+ uint8_t ucHorizontalPitch;// Horizontal Pitch
+ uint8_t ucVerticalPitch;// Vertical Pitch
+ union
+ {
+ uint8_t ucMiscDisplayCapabilities;
+ struct
+ {
+ uint8_t bReserved : 3;
+ uint8_t ucDeinterlacing : 1;// indicates deinterlacing support
+ uint8_t ucOverdriverNotRecommended : 1;
+ uint8_t ucDirectDrive : 1;// indicates DirectDrive support
+ uint8_t ucDithering : 2;// indicates Dithering support.
+ };
+ };
+ union
+ {
+ uint8_t ucAudioFlags;// Flags indicating Audio details
+ struct
+ {
+ uint8_t bReserved1 : 4;
+ uint8_t ucAudioInputOverride : 1;// Indicates Audio Input Override
+ uint8_t ucSeparateAudioInputs : 1;// Indicates Separate Audio Inputs
+ uint8_t ucAudioInputOnVideoInterface : 1;// Shows whether Audio input is through the video interface.
+ };
+ };
+ union
+ {
+ uint8_t ucAudioDelayFlags; // Audio Delay Flags
+ struct
+ {
+ uint8_t ucAudioDelay : 7;// Absolute offset between the audio and video signals.
+ uint8_t ucAudioSign : 1;// Indicates positive or negative delay.
+ };
+ };
+ union
+ {
+ uint8_t ucFrameRateAndModeConversion;
+ struct
+ {
+ uint8_t ucFrameRateRange : 6;//Device Frame rate Range
+ uint8_t ucFrameRateConversion : 2;//00 � No dedicated rate conversion hardware is provided;
+ //01 � The display provides a single frame buffer
+ //10 � The display provides double-buffering
+ //11- The display provides frame-rate conversion involving interframe interpolation
+ };
+ };
+ uint8_t ucDeviceNativeRate;// Device Native Frame rate
+ union
+ {
+ uint8_t ucColorBitDepth;// Color bit depth
+ struct
+ {
+ uint8_t ucDisplayDeviceColBitDepth : 4; // Color bit depth of the display device
+ uint8_t ucInterfaceColBitDepth : 4;// color bit depth supported by the interface.h
+ };
+ };
+ uint8_t ucAddPrimaryChromaticities[8];// Additional Primary Chromaticities.
+ union
+ {
+ uint8_t ucResponseTimeFlags;
+ struct
+ {
+ uint8_t ucResponseTime : 7;// Time for transition.
+ uint8_t ucBlackToWhite : 1;// if 1, then transition from black to white
+ // if 0, then transition from white to black
+ };
+ };
+ union
+ {
+ uint8_t ucOverscanInformation;
+ struct
+ {
+ uint8_t ucVerticalPercentage : 4;// Percentage of Overscan in vertical direction.
+ uint8_t ucHorizontalPercentage : 4;// Percentage of Overscan in horizontal direction.
+ };
+ };
+#pragma pack()
+} display_device_data_t;
+
+//=========================================================================
+//=========================================================================
+// #defines for Block Map Ext.
+//=========================================================================
+//=========================================================================
+#define BLOCK_MAP_EXT_TAG 0xF0
+
+#endif // EDIDSTRUCTS_H
--- /dev/null
+/*
+ * Copyright © 2006-2007 Intel 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 (including the next
+ * paragraph) 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.
+ *
+ * Authors:
+ *
+ */
+/* chunfeng.zhao@intel.com
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#if 0 /* FIXME_JLIU7 HDMI */
+#include "psb_intel_hdmi_i2c.h"
+
+#define MDFLD_HDMI_I2C_ADAPTER_ID 3
+
+static int hdmi_i2c_open(struct i2c_client *c, void *data)
+{
+ /*Do nothing for now, may need to add sync code? */
+ return 0;
+}
+
+static int hdmi_i2c_close(struct i2c_client *c, void *data)
+{
+ /*Do nothing for now, may need to add sync code? */
+ return 0;
+}
+
+static char hdmi_i2c_read_byte_data(struct i2c_client *c, unsigned char adr)
+{
+ return i2c_smbus_read_byte_data(c, adr);
+}
+
+static int hdmi_i2c_write_byte_data(struct i2c_client *c, unsigned char adr, unsigned char data)
+{
+ return i2c_smbus_write_byte_data(c, adr, data);
+}
+
+static int hdmi_i2c_read_data(struct i2c_adapter * adapter, unsigned char adr, unsigned char * data, int size)
+{
+ struct i2c_msg msg = {
+ .addr = adr,.flags = I2C_M_RD,.buf = data,.len = size
+ };
+ return i2c_transfer(adapter, &msg, 1);
+}
+
+static int hdmi_i2c_write_data(struct i2c_adapter * adapter, unsigned char adr, unsigned char *data, int size)
+{
+ struct i2c_msg msg = {
+ .addr = adr,.flags = 0,.buf = data,.len = size
+ };
+ return i2c_transfer(adapter, &msg, 1);
+}
+
+static struct i2c_adapter * hdmi_i2c_get_adapter(struct i2c_client *c)
+{
+ /* For HDMI if not plugged in, then i2c core may not create the client driver */
+ /* Should use the adapter directly */
+ if(c)
+ return c->adapter;
+ else
+ return i2c_get_adapter(MDFLD_HDMI_I2C_ADAPTER_ID);
+}
+
+static struct mdfld_hdmi_i2c hdmi_i2c_bus = {
+ .open = hdmi_i2c_open,
+ .close = hdmi_i2c_close,
+ .read_byte_data = hdmi_i2c_read_byte_data,
+ .write_byte_data = hdmi_i2c_write_byte_data,
+ .read_data = hdmi_i2c_read_data,
+ .write_data = hdmi_i2c_write_data,
+ .get_adapter = hdmi_i2c_get_adapter,
+};
+
+struct mdfld_hdmi_i2c * hdmi_i2c_init()
+{
+ return &hdmi_i2c_bus;
+}
+
+/*
+ * * i2c addresses to scan
+ * 0x28 is from 0x50 >> 1 to remove first bit for ddc address
+ * 0x39 is from 0x73 >> 1 for HDCP address
+ * */
+static unsigned short normal_i2c[] = {0x28, 0x39, I2C_CLIENT_END};
+I2C_CLIENT_INSMOD;
+
+/* Each client has this additional data */
+struct mdfld_hdmi_i2c_data {
+ struct semaphore data_lock;
+ int data;
+};
+
+static const struct i2c_device_id mdfld_hdmi_id[] = {
+ {"mdfld_hdmi", 0},
+ {}
+};
+
+static int mdfld_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ return 0;
+}
+
+/* This function is called by i2c_detect */
+static int mdfld_detect(struct i2c_client *client, int kind,
+ struct i2c_board_info *info)
+{
+ struct i2c_adapter *adapter = client->adapter;
+ struct mdfld_hdmi_i2c_data *data = NULL;
+ int err = 0;
+
+ /* HDMI i2c is i2c3 with id = 3 */
+ if (adapter->id !=3) {
+ err = -ENODEV;
+ goto error;
+ }
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+ err = -ENODEV;
+ goto error;
+ }
+
+ data = kmalloc(sizeof(*data), GFP_KERNEL);
+ if (!data) {
+ err = -ENOMEM;
+ goto error;
+ }
+
+ memset(data, 0x00, sizeof(*data));
+
+ i2c_set_clientdata(client, data);
+
+ if (client->addr == 0xA0)
+ hdmi_i2c_bus.ddc_client = client;
+ else
+ hdmi_i2c_bus.hdcp_client = client;
+
+ return 0;
+
+error:
+ if(data != NULL) kfree(data);
+ return err;
+}
+
+static int mdfld_remove(struct i2c_client *client)
+{
+ struct mdfld_hdmi_i2c_data *data = i2c_get_clientdata(client);
+ kfree(data);
+ return 0;
+}
+
+/* This is the driver that will be inserted */
+static struct i2c_driver mdfld_hdmi_i2c_driver = {
+ .driver = {
+ .name = "mdfld_hdmi",
+ },
+ .probe = mdfld_probe,
+ .remove = mdfld_remove,
+ .id_table = mdfld_hdmi_id,
+
+ .class = I2C_CLASS_DDC,
+ .detect = mdfld_detect,
+ .address_data = &addr_data,
+};
+
+
+static int __init mdfld_i2c_init(void)
+{
+ hdmi_i2c_bus.ddc_client = NULL;
+ hdmi_i2c_bus.hdcp_client = NULL;
+
+ return i2c_add_driver(&mdfld_hdmi_i2c_driver);
+}
+
+static void __exit mdfld_i2c_exit(void)
+{
+ i2c_del_driver(&mdfld_hdmi_i2c_driver);
+}
+
+
+MODULE_AUTHOR("Chunfeng Zhao <chunfeng.zhao@intel.com>");
+MODULE_DESCRIPTION("mdfld hdmi i2c client driver");
+MODULE_LICENSE("GPL");
+
+module_init(mdfld_i2c_init);
+module_exit(mdfld_i2c_exit);
+#endif /* FIXME_JLIU7 HDMI */
--- /dev/null
+#ifndef PSB_INTEL_HDMI_I2C_H
+#define PSB_INTEL_HDMI_I2C_H
+
+#if 0 /* FIXME_JLIU7 HDMI */
+struct mdfld_hdmi_i2c {
+ struct i2c_client *ddc_client;
+ struct i2c_client *hdcp_client;
+ int (*open) (struct i2c_client *, void *);
+ int (*close) (struct i2c_client *, void *);
+ char (*read_byte_data)(struct i2c_client *, unsigned char adr);
+ int (*write_byte_data)(struct i2c_client *, unsigned char adr, unsigned char data);
+ int (*read_data)(struct i2c_adapter * adapter, unsigned char adr, unsigned char * data, int size);
+ int (*write_data)(struct i2c_adapter * adapter, unsigned char adr, unsigned char *data, int size);
+ struct i2c_adapter * (*get_adapter)(struct i2c_client *c);
+ struct mutex lock;
+};
+
+extern struct mdfld_hdmi_i2c * hdmi_i2c_init(void);
+
+#endif /* FIXME_JLIU7 HDMI */
+#endif
--- /dev/null
+/*
+ * Copyright © 2006-2007 Intel 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 (including the next
+ * paragraph) 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.
+ *
+ * Authors:
+ *
+ */
+/* chunfeng.zhao@intel.com
+ */
+
+#ifndef PSB_INTEL_HDMI_REG_H
+#define PSB_INTEL_HDMI_REG_H
+
+//////////////////////////////////////////
+//
+// Integrated HDMI specific registers
+//
+/////////////////////////////////////////
+
+#define RESERVED2(x,y) x##y
+#define RESERVED1(x,y) RESERVED2(x,y)
+#define RANDOMNUMBER __LINE__ // __COUNTER__
+#define UNIQUENAME(ValueName) RESERVED1(ValueName, RANDOMNUMBER)
+
+/** Requird for HDMI operation */
+#define HDMI_NULL_PACKETS_DURING_VSYNC (1 << 9)
+#define HDMI_BORDER_ENABLE (1 << 7)
+#define HDMI_AUDIO_ENABLE (1 << 6)
+/** New with 965, default is to be set */
+#define HDMI_VSYNC_ACTIVE_HIGH (1 << 4)
+/** New with 965, default is to be set */
+#define HDMI_HSYNC_ACTIVE_HIGH (1 << 3)
+#define HDMIB_PCIE_CONCURRENCY (1 << 3)
+#define HDMI_DETECTED (1 << 2)
+/* Bits to be preserved when writing */
+#if 0
+#define HDMIB_PRESERVE_MASK ((1 << 17) | (1 << 16) | (1 << 14) | (1 << 26))
+#define HDMIC_PRESERVE_MASK ((1 << 17) | (1 << 26))
+#endif
+//
+//AUDIO configuration register
+//
+#define MDFLD_AUD_CONFIG_REG 0x69000
+ #define MDFLD_AUD_CONFIG_REG_RESERVED_BITS BITRANGE(31,25)
+typedef union _mdfld_aud_config {
+ uint32_t value;
+
+ struct
+ {
+ const uint32_t disable_ncts : 1; //Bit 0
+ uint32_t lay_out : 1; //Bit 1 (0 - layout 0 1 - layout 1)
+ uint32_t format : 2; /*Bit [3:2]
+ * 00 - l-PCM or IEC 61937
+ * 01 - High bit rate IEC 61937 stream packet)
+ * 10 - Not supported
+ * 11 - Not supported
+ */
+ uint32_t num_audio_ch : 2; /*Bit [5:4]
+ * 00 - 2 channels(stereo)
+ * 01 - 3 or 4 channels
+ * 10 - 5 or 6 channels
+ * 11 - 7 or 8 channels
+ */
+ uint32_t UNIQUENAME(Reserved) : 1; //Bit 6
+ uint32_t b_bit_enabled : 1; /* Bit 7 (0 - B bit set only for sub-packet 0
+ * 1 - B bit set for all valid sub packet)
+ */
+ uint32_t sample_flat_bit : 1; //Bit 8
+ uint32_t validity_bit : 1; //Bit 9 (1 - set V bit in sub-frame 0 - clear V bit(debugging, testing))
+ uint32_t user_bit : 1; //Bit 10 (1 - set U bit in sub frame 0 - clear U bit(default)
+ uint32_t underrun_packet_bit : 1; //Bit 11 (1 - send underrun packet 0 - send null packet)
+ uint32_t UNIQUENAME(Reserved) : 20; //Bit [31:12]
+ };
+} mdfld_aud_config_t;
+
+//
+// Audio control state register
+//
+#define MDFLD_AUD_CNTL_ST_REG 0x69060
+ #define MDFLD_AUD_CNTL_ST_RESERVED_BITS (BITRANGE(14,4) | BITRANGE(31,25))
+// Note => DIP : Data Island Packet
+typedef union _mdfld_aud_cntl {
+ uint32_t value;
+
+ struct
+ {
+ uint32_t dip_ram_access_address :4; // bit 3:0
+ uint32_t UNIQUENAME(Reserved) :11; // bit 14:4
+ uint32_t cp_ready :1; // bit 15
+ uint32_t video_dip_trans_freq :2; // bit 17:16
+ uint32_t dip_buffer_index :3; // bit 20:18
+ uint32_t enable_dip_type :4; // bit 24:21
+ uint32_t UNIQUENAME(Reserved) :7; // bit 31:25
+ };
+
+} mdfld_aud_cntl_t;
+
+
+// HDMI Audio Data Island Packet Data
+//
+#define MDFLD_HDMI_AUDPAC_DATA_REG 0x69114
+
+typedef union _mdfld_hdmi_audpac_data {
+ uint32_t value;
+
+ struct
+ {
+ uint32_t audio_dip_data :32; // bit 31:0
+ };
+} mdfld_hdmi_audpac_data_t;
+
+#endif // PSB_INTEL_HDMI_REG_H
--- /dev/null
+/*
+ * Copyright (c) 2009, Intel Corporation.
+ *
+ * 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 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.
+ */
+#ifndef __PSB_INTEL_REG_H__
+#define __PSB_INTEL_REG_H__
+
+#define BLC_PWM_CTL 0x61254
+#define BLC_PWM_CTL2 0x61250
+#define BLC_PWM_CTL_C 0x62254
+#define BLC_PWM_CTL2_C 0x62250
+#define BACKLIGHT_MODULATION_FREQ_SHIFT (17)
+/**
+ * This is the most significant 15 bits of the number of backlight cycles in a
+ * complete cycle of the modulated backlight control.
+ *
+ * The actual value is this field multiplied by two.
+ */
+#define BACKLIGHT_MODULATION_FREQ_MASK (0x7fff << 17)
+#define BLM_LEGACY_MODE (1 << 16)
+/**
+ * This is the number of cycles out of the backlight modulation cycle for which
+ * the backlight is on.
+ *
+ * This field must be no greater than the number of cycles in the complete
+ * backlight modulation cycle.
+ */
+#define BACKLIGHT_DUTY_CYCLE_SHIFT (0)
+#define BACKLIGHT_DUTY_CYCLE_MASK (0xffff)
+
+#define I915_GCFGC 0xf0
+#define I915_LOW_FREQUENCY_ENABLE (1 << 7)
+#define I915_DISPLAY_CLOCK_190_200_MHZ (0 << 4)
+#define I915_DISPLAY_CLOCK_333_MHZ (4 << 4)
+#define I915_DISPLAY_CLOCK_MASK (7 << 4)
+
+#define I855_HPLLCC 0xc0
+#define I855_CLOCK_CONTROL_MASK (3 << 0)
+#define I855_CLOCK_133_200 (0 << 0)
+#define I855_CLOCK_100_200 (1 << 0)
+#define I855_CLOCK_100_133 (2 << 0)
+#define I855_CLOCK_166_250 (3 << 0)
+
+/* I830 CRTC registers */
+#define HTOTAL_A 0x60000
+#define HBLANK_A 0x60004
+#define HSYNC_A 0x60008
+#define VTOTAL_A 0x6000c
+#define VBLANK_A 0x60010
+#define VSYNC_A 0x60014
+#define PIPEASRC 0x6001c
+#define BCLRPAT_A 0x60020
+#define VSYNCSHIFT_A 0x60028
+
+#define HTOTAL_B 0x61000
+#define HBLANK_B 0x61004
+#define HSYNC_B 0x61008
+#define VTOTAL_B 0x6100c
+#define VBLANK_B 0x61010
+#define VSYNC_B 0x61014
+#define PIPEBSRC 0x6101c
+#define BCLRPAT_B 0x61020
+#define VSYNCSHIFT_B 0x61028
+
+#define HTOTAL_C 0x62000
+#define HBLANK_C 0x62004
+#define HSYNC_C 0x62008
+#define VTOTAL_C 0x6200c
+#define VBLANK_C 0x62010
+#define VSYNC_C 0x62014
+#define PIPECSRC 0x6201c
+#define BCLRPAT_C 0x62020
+#define VSYNCSHIFT_C 0x62028
+
+#define PP_STATUS 0x61200
+# define PP_ON (1 << 31)
+/**
+ * Indicates that all dependencies of the panel are on:
+ *
+ * - PLL enabled
+ * - pipe enabled
+ * - LVDS/DVOB/DVOC on
+ */
+# define PP_READY (1 << 30)
+# define PP_SEQUENCE_NONE (0 << 28)
+# define PP_SEQUENCE_ON (1 << 28)
+# define PP_SEQUENCE_OFF (2 << 28)
+# define PP_SEQUENCE_MASK 0x30000000
+#define PP_CONTROL 0x61204
+# define POWER_TARGET_ON (1 << 0)
+
+#define LVDSPP_ON 0x61208
+#define LVDSPP_OFF 0x6120c
+#define PP_CYCLE 0x61210
+
+#define PFIT_CONTROL 0x61230
+# define PFIT_ENABLE (1 << 31)
+# define PFIT_PIPE_MASK (3 << 29)
+# define PFIT_PIPE_SHIFT 29
+# define PFIT_PIPE_SELECT_A (0 << PFIT_PIPE_SHIFT)
+# define PFIT_PIPE_SELECT_B (1 << PFIT_PIPE_SHIFT)
+# define PFIT_PIPE_SELECT_C (2 << PFIT_PIPE_SHIFT)
+# define PFIT_PIPE_SELECT_D (3 << PFIT_PIPE_SHIFT)
+# define PFIT_SCALING_MODE_PILLARBOX (1 << 27)
+# define PFIT_SCALING_MODE_LETTERBOX (3 << 26)
+# define VERT_INTERP_DISABLE (0 << 10)
+# define VERT_INTERP_BILINEAR (1 << 10)
+# define VERT_INTERP_MASK (3 << 10)
+# define VERT_AUTO_SCALE (1 << 9)
+# define HORIZ_INTERP_DISABLE (0 << 6)
+# define HORIZ_INTERP_BILINEAR (1 << 6)
+# define HORIZ_INTERP_MASK (3 << 6)
+# define HORIZ_AUTO_SCALE (1 << 5)
+# define PANEL_8TO6_DITHER_ENABLE (1 << 3)
+
+#define PFIT_PGM_RATIOS 0x61234
+# define PFIT_VERT_SCALE_MASK 0xfff00000
+# define PFIT_HORIZ_SCALE_MASK 0x0000fff0
+
+#define PFIT_AUTO_RATIOS 0x61238
+
+
+#define DPLL_A 0x06014
+#define DPLL_B 0x06018
+# define DPLL_VCO_ENABLE (1 << 31)
+# define DPLL_DVO_HIGH_SPEED (1 << 30)
+# define DPLL_SYNCLOCK_ENABLE (1 << 29)
+# define DPLL_VGA_MODE_DIS (1 << 28)
+# define DPLLB_MODE_DAC_SERIAL (1 << 26) /* i915 */
+# define DPLLB_MODE_LVDS (2 << 26) /* i915 */
+# define DPLL_MODE_MASK (3 << 26)
+# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10 (0 << 24) /* i915 */
+# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 (1 << 24) /* i915 */
+# define DPLLB_LVDS_P2_CLOCK_DIV_14 (0 << 24) /* i915 */
+# define DPLLB_LVDS_P2_CLOCK_DIV_7 (1 << 24) /* i915 */
+# define DPLL_P2_CLOCK_DIV_MASK 0x03000000 /* i915 */
+# define DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */
+/**
+ * The i830 generation, in DAC/serial mode, defines p1 as two plus this
+ * bitfield, or just 2 if PLL_P1_DIVIDE_BY_TWO is set.
+ */
+# define DPLL_FPA01_P1_POST_DIV_MASK_I830 0x001f0000
+/**
+ * The i830 generation, in LVDS mode, defines P1 as the bit number set within
+ * this field (only one bit may be set).
+ */
+# define DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS 0x003f0000
+# define DPLL_FPA01_P1_POST_DIV_SHIFT 16
+# define PLL_P2_DIVIDE_BY_4 (1 << 23) /* i830, required
+ * in DVO non-gang */
+# define PLL_P1_DIVIDE_BY_TWO (1 << 21) /* i830 */
+# define PLL_REF_INPUT_DREFCLK (0 << 13)
+# define PLL_REF_INPUT_TVCLKINA (1 << 13) /* i830 */
+# define PLL_REF_INPUT_TVCLKINBC (2 << 13) /* SDVO
+ * TVCLKIN */
+# define PLLB_REF_INPUT_SPREADSPECTRUMIN (3 << 13)
+# define PLL_REF_INPUT_MASK (3 << 13)
+# define PLL_LOAD_PULSE_PHASE_SHIFT 9
+/*
+ * Parallel to Serial Load Pulse phase selection.
+ * Selects the phase for the 10X DPLL clock for the PCIe
+ * digital display port. The range is 4 to 13; 10 or more
+ * is just a flip delay. The default is 6
+ */
+# define PLL_LOAD_PULSE_PHASE_MASK (0xf << PLL_LOAD_PULSE_PHASE_SHIFT)
+# define DISPLAY_RATE_SELECT_FPA1 (1 << 8)
+
+/**
+ * SDVO multiplier for 945G/GM. Not used on 965.
+ *
+ * \sa DPLL_MD_UDI_MULTIPLIER_MASK
+ */
+# define SDVO_MULTIPLIER_MASK 0x000000ff
+# define SDVO_MULTIPLIER_SHIFT_HIRES 4
+# define SDVO_MULTIPLIER_SHIFT_VGA 0
+
+/** @defgroup DPLL_MD
+ * @{
+ */
+/** Pipe A SDVO/UDI clock multiplier/divider register for G965. */
+#define DPLL_A_MD 0x0601c
+/** Pipe B SDVO/UDI clock multiplier/divider register for G965. */
+#define DPLL_B_MD 0x06020
+/**
+ * UDI pixel divider, controlling how many pixels are stuffed into a packet.
+ *
+ * Value is pixels minus 1. Must be set to 1 pixel for SDVO.
+ */
+# define DPLL_MD_UDI_DIVIDER_MASK 0x3f000000
+# define DPLL_MD_UDI_DIVIDER_SHIFT 24
+/** UDI pixel divider for VGA, same as DPLL_MD_UDI_DIVIDER_MASK. */
+# define DPLL_MD_VGA_UDI_DIVIDER_MASK 0x003f0000
+# define DPLL_MD_VGA_UDI_DIVIDER_SHIFT 16
+/**
+ * SDVO/UDI pixel multiplier.
+ *
+ * SDVO requires that the bus clock rate be between 1 and 2 Ghz, and the bus
+ * clock rate is 10 times the DPLL clock. At low resolution/refresh rate
+ * modes, the bus rate would be below the limits, so SDVO allows for stuffing
+ * dummy bytes in the datastream at an increased clock rate, with both sides of
+ * the link knowing how many bytes are fill.
+ *
+ * So, for a mode with a dotclock of 65Mhz, we would want to double the clock
+ * rate to 130Mhz to get a bus rate of 1.30Ghz. The DPLL clock rate would be
+ * set to 130Mhz, and the SDVO multiplier set to 2x in this register and
+ * through an SDVO command.
+ *
+ * This register field has values of multiplication factor minus 1, with
+ * a maximum multiplier of 5 for SDVO.
+ */
+# define DPLL_MD_UDI_MULTIPLIER_MASK 0x00003f00
+# define DPLL_MD_UDI_MULTIPLIER_SHIFT 8
+/** SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK.
+ * This best be set to the default value (3) or the CRT won't work. No,
+ * I don't entirely understand what this does...
+ */
+# define DPLL_MD_VGA_UDI_MULTIPLIER_MASK 0x0000003f
+# define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT 0
+/** @} */
+
+#define DPLL_TEST 0x606c
+# define DPLLB_TEST_SDVO_DIV_1 (0 << 22)
+# define DPLLB_TEST_SDVO_DIV_2 (1 << 22)
+# define DPLLB_TEST_SDVO_DIV_4 (2 << 22)
+# define DPLLB_TEST_SDVO_DIV_MASK (3 << 22)
+# define DPLLB_TEST_N_BYPASS (1 << 19)
+# define DPLLB_TEST_M_BYPASS (1 << 18)
+# define DPLLB_INPUT_BUFFER_ENABLE (1 << 16)
+# define DPLLA_TEST_N_BYPASS (1 << 3)
+# define DPLLA_TEST_M_BYPASS (1 << 2)
+# define DPLLA_INPUT_BUFFER_ENABLE (1 << 0)
+
+#define ADPA 0x61100
+#define ADPA_DAC_ENABLE (1<<31)
+#define ADPA_DAC_DISABLE 0
+#define ADPA_PIPE_SELECT_MASK (1<<30)
+#define ADPA_PIPE_A_SELECT 0
+#define ADPA_PIPE_B_SELECT (1<<30)
+#define ADPA_USE_VGA_HVPOLARITY (1<<15)
+#define ADPA_SETS_HVPOLARITY 0
+#define ADPA_VSYNC_CNTL_DISABLE (1<<11)
+#define ADPA_VSYNC_CNTL_ENABLE 0
+#define ADPA_HSYNC_CNTL_DISABLE (1<<10)
+#define ADPA_HSYNC_CNTL_ENABLE 0
+#define ADPA_VSYNC_ACTIVE_HIGH (1<<4)
+#define ADPA_VSYNC_ACTIVE_LOW 0
+#define ADPA_HSYNC_ACTIVE_HIGH (1<<3)
+#define ADPA_HSYNC_ACTIVE_LOW 0
+
+#define FPA0 0x06040
+#define FPA1 0x06044
+#define FPB0 0x06048
+#define FPB1 0x0604c
+# define FP_N_DIV_MASK 0x003f0000
+# define FP_N_DIV_SHIFT 16
+# define FP_M1_DIV_MASK 0x00003f00
+# define FP_M1_DIV_SHIFT 8
+# define FP_M2_DIV_MASK 0x0000003f
+# define FP_M2_DIV_SHIFT 0
+
+
+#define PORT_HOTPLUG_EN 0x61110
+# define SDVOB_HOTPLUG_INT_EN (1 << 26)
+# define SDVOC_HOTPLUG_INT_EN (1 << 25)
+# define TV_HOTPLUG_INT_EN (1 << 18)
+# define CRT_HOTPLUG_INT_EN (1 << 9)
+# define CRT_HOTPLUG_FORCE_DETECT (1 << 3)
+
+#define PORT_HOTPLUG_STAT 0x61114
+# define CRT_HOTPLUG_INT_STATUS (1 << 11)
+# define TV_HOTPLUG_INT_STATUS (1 << 10)
+# define CRT_HOTPLUG_MONITOR_MASK (3 << 8)
+# define CRT_HOTPLUG_MONITOR_COLOR (3 << 8)
+# define CRT_HOTPLUG_MONITOR_MONO (2 << 8)
+# define CRT_HOTPLUG_MONITOR_NONE (0 << 8)
+# define SDVOC_HOTPLUG_INT_STATUS (1 << 7)
+# define SDVOB_HOTPLUG_INT_STATUS (1 << 6)
+
+#define SDVOB 0x61140
+#define SDVOC 0x61160
+#define SDVO_ENABLE (1 << 31)
+#define SDVO_PIPE_B_SELECT (1 << 30)
+#define SDVO_STALL_SELECT (1 << 29)
+#define SDVO_INTERRUPT_ENABLE (1 << 26)
+/**
+ * 915G/GM SDVO pixel multiplier.
+ *
+ * Programmed value is multiplier - 1, up to 5x.
+ *
+ * \sa DPLL_MD_UDI_MULTIPLIER_MASK
+ */
+#define SDVO_PORT_MULTIPLY_MASK (7 << 23)
+#define SDVO_PORT_MULTIPLY_SHIFT 23
+#define SDVO_PHASE_SELECT_MASK (15 << 19)
+#define SDVO_PHASE_SELECT_DEFAULT (6 << 19)
+#define SDVO_CLOCK_OUTPUT_INVERT (1 << 18)
+#define SDVOC_GANG_MODE (1 << 16)
+#define SDVO_BORDER_ENABLE (1 << 7)
+#define SDVOB_PCIE_CONCURRENCY (1 << 3)
+#define SDVO_DETECTED (1 << 2)
+/* Bits to be preserved when writing */
+#define SDVOB_PRESERVE_MASK ((1 << 17) | (1 << 16) | (1 << 14))
+#define SDVOC_PRESERVE_MASK (1 << 17)
+
+/** @defgroup LVDS
+ * @{
+ */
+/**
+ * This register controls the LVDS output enable, pipe selection, and data
+ * format selection.
+ *
+ * All of the clock/data pairs are force powered down by power sequencing.
+ */
+#define LVDS 0x61180
+/**
+ * Enables the LVDS port. This bit must be set before DPLLs are enabled, as
+ * the DPLL semantics change when the LVDS is assigned to that pipe.
+ */
+# define LVDS_PORT_EN (1 << 31)
+/** Selects pipe B for LVDS data. Must be set on pre-965. */
+# define LVDS_PIPEB_SELECT (1 << 30)
+
+/** Turns on border drawing to allow centered display. */
+# define LVDS_BORDER_EN (1 << 15)
+
+/**
+ * Enables the A0-A2 data pairs and CLKA, containing 18 bits of color data per
+ * pixel.
+ */
+# define LVDS_A0A2_CLKA_POWER_MASK (3 << 8)
+# define LVDS_A0A2_CLKA_POWER_DOWN (0 << 8)
+# define LVDS_A0A2_CLKA_POWER_UP (3 << 8)
+/**
+ * Controls the A3 data pair, which contains the additional LSBs for 24 bit
+ * mode. Only enabled if LVDS_A0A2_CLKA_POWER_UP also indicates it should be
+ * on.
+ */
+# define LVDS_A3_POWER_MASK (3 << 6)
+# define LVDS_A3_POWER_DOWN (0 << 6)
+# define LVDS_A3_POWER_UP (3 << 6)
+/**
+ * Controls the CLKB pair. This should only be set when LVDS_B0B3_POWER_UP
+ * is set.
+ */
+# define LVDS_CLKB_POWER_MASK (3 << 4)
+# define LVDS_CLKB_POWER_DOWN (0 << 4)
+# define LVDS_CLKB_POWER_UP (3 << 4)
+
+/**
+ * Controls the B0-B3 data pairs. This must be set to match the DPLL p2
+ * setting for whether we are in dual-channel mode. The B3 pair will
+ * additionally only be powered up when LVDS_A3_POWER_UP is set.
+ */
+# define LVDS_B0B3_POWER_MASK (3 << 2)
+# define LVDS_B0B3_POWER_DOWN (0 << 2)
+# define LVDS_B0B3_POWER_UP (3 << 2)
+
+#define PIPEACONF 0x70008
+#define PIPEACONF_ENABLE (1<<31)
+#define PIPEACONF_DISABLE 0
+#define PIPEACONF_DOUBLE_WIDE (1<<30)
+#define PIPECONF_ACTIVE (1<<30)
+#define I965_PIPECONF_ACTIVE (1<<30)
+#define PIPECONF_DSIPLL_LOCK (1<<29)
+#define PIPEACONF_SINGLE_WIDE 0
+#define PIPEACONF_PIPE_UNLOCKED 0
+#define PIPEACONF_DSR (1<<26)
+#define PIPEACONF_PIPE_LOCKED (1<<25)
+#define PIPEACONF_PALETTE 0
+#define PIPECONF_FORCE_BORDER (1<<25)
+#define PIPEACONF_GAMMA (1<<24)
+#define PIPECONF_PROGRESSIVE (0 << 21)
+#define PIPECONF_INTERLACE_W_FIELD_INDICATION (6 << 21)
+#define PIPECONF_INTERLACE_FIELD_0_ONLY (7 << 21)
+#define PIPECONF_PLANE_OFF (1<<19)
+#define PIPECONF_CURSOR_OFF (1<<18)
+
+
+#define PIPEBCONF 0x71008
+#define PIPEBCONF_ENABLE (1<<31)
+#define PIPEBCONF_DISABLE 0
+#define PIPEBCONF_DOUBLE_WIDE (1<<30)
+#define PIPEBCONF_DISABLE 0
+#define PIPEBCONF_GAMMA (1<<24)
+#define PIPEBCONF_PALETTE 0
+
+#define PIPECCONF 0x72008
+
+#define PIPEBGCMAXRED 0x71010
+#define PIPEBGCMAXGREEN 0x71014
+#define PIPEBGCMAXBLUE 0x71018
+
+#define PIPEASTAT 0x70024
+#define PIPEBSTAT 0x71024
+#define PIPECSTAT 0x72024
+#define PIPE_VBLANK_INTERRUPT_STATUS (1UL<<1)
+#define PIPE_START_VBLANK_INTERRUPT_STATUS (1UL<<2)
+#define PIPE_VBLANK_CLEAR (1 << 1)
+#define PIPE_VBLANK_STATUS (1 << 1)
+#define PIPE_TE_STATUS (1UL<<6)
+#define PIPE_DPST_EVENT_STATUS (1UL<<7)
+#define PIPE_VSYNC_CLEAR (1UL<<9)
+#define PIPE_VSYNC_STATUS (1UL<<9)
+#define PIPE_HDMI_AUDIO_UNDERRUN_STATUS (1UL<<10)
+#define PIPE_HDMI_AUDIO_BUFFER_DONE_STATUS (1UL<<11)
+#define PIPE_VBLANK_INTERRUPT_ENABLE (1UL<<17)
+#define PIPE_START_VBLANK_INTERRUPT_ENABLE (1UL<<18)
+#define PIPE_TE_ENABLE (1UL<<22)
+#define PIPE_DPST_EVENT_ENABLE (1UL<<23)
+#define PIPE_VSYNC_ENABL (1UL<<25)
+#define PIPE_HDMI_AUDIO_UNDERRUN (1UL<<26)
+#define PIPE_HDMI_AUDIO_BUFFER_DONE (1UL<<27)
+#define PIPE_HDMI_AUDIO_INT_MASK (PIPE_HDMI_AUDIO_UNDERRUN | PIPE_HDMI_AUDIO_BUFFER_DONE)
+#define PIPE_EVENT_MASK (BIT(29)|BIT(28)|BIT(27)|BIT(26)|BIT(24)|BIT(23)|BIT(22)|BIT(21)|BIT(20)|BIT(16))
+#define PIPE_VBLANK_MASK (BIT(25)|BIT(24)|BIT(18)|BIT(17))
+#define HISTOGRAM_INT_CONTROL 0x61268
+#define HISTOGRAM_BIN_DATA 0X61264
+#define HISTOGRAM_LOGIC_CONTROL 0x61260
+#define PWM_CONTROL_LOGIC 0x61250
+#define PIPE_HOTPLUG_INTERRUPT_STATUS (1UL<<10)
+#define HISTOGRAM_INTERRUPT_ENABLE (1UL<<31)
+#define HISTOGRAM_LOGIC_ENABLE (1UL<<31)
+#define PWM_LOGIC_ENABLE (1UL<<31)
+#define PWM_PHASEIN_ENABLE (1UL<<25)
+#define PWM_PHASEIN_INT_ENABLE (1UL<<24)
+#define PWM_PHASEIN_VB_COUNT 0x00001f00
+#define PWM_PHASEIN_INC 0x0000001f
+#define HISTOGRAM_INT_CTRL_CLEAR (1UL<<30)
+#define DPST_YUV_LUMA_MODE 0
+
+struct dpst_ie_histogram_control {
+ union {
+ uint32_t data;
+ struct {
+ uint32_t bin_reg_index:7;
+ uint32_t reserved:4;
+ uint32_t bin_reg_func_select:1;
+ uint32_t sync_to_phase_in:1;
+ uint32_t alt_enhancement_mode:2;
+ uint32_t reserved1:1;
+ uint32_t sync_to_phase_in_count:8;
+ uint32_t histogram_mode_select:1;
+ uint32_t reserved2:4;
+ uint32_t ie_pipe_assignment:1;
+ uint32_t ie_mode_table_enabled:1;
+ uint32_t ie_histogram_enable:1;
+ };
+ };
+};
+
+struct dpst_guardband {
+ union {
+ uint32_t data;
+ struct {
+ uint32_t guardband:22;
+ uint32_t guardband_interrupt_delay:8;
+ uint32_t interrupt_status:1;
+ uint32_t interrupt_enable:1;
+ };
+ };
+};
+
+#define PIPEAFRAMEHIGH 0x70040
+#define PIPEAFRAMEPIXEL 0x70044
+#define PIPEBFRAMEHIGH 0x71040
+#define PIPEBFRAMEPIXEL 0x71044
+#define PIPECFRAMEHIGH 0x72040
+#define PIPECFRAMEPIXEL 0x72044
+#define PIPE_FRAME_HIGH_MASK 0x0000ffff
+#define PIPE_FRAME_HIGH_SHIFT 0
+#define PIPE_FRAME_LOW_MASK 0xff000000
+#define PIPE_FRAME_LOW_SHIFT 24
+#define PIPE_PIXEL_MASK 0x00ffffff
+#define PIPE_PIXEL_SHIFT 0
+
+#define DSPARB 0x70030
+#define DSPFW1 0x70034
+#define DSPFW2 0x70038
+#define DSPFW3 0x7003c
+#define DSPFW4 0x70050
+#define DSPFW5 0x70054
+#define DSPFW6 0x70058
+#define DSPCHICKENBIT 0x70400
+#define DSPACNTR 0x70180
+#define DSPBCNTR 0x71180
+#define DSPCCNTR 0x72180
+#define DISPLAY_PLANE_ENABLE (1<<31)
+#define DISPLAY_PLANE_DISABLE 0
+#define DISPPLANE_GAMMA_ENABLE (1<<30)
+#define DISPPLANE_GAMMA_DISABLE 0
+#define DISPPLANE_PIXFORMAT_MASK (0xf<<26)
+#define DISPPLANE_8BPP (0x2<<26)
+#define DISPPLANE_15_16BPP (0x4<<26)
+#define DISPPLANE_16BPP (0x5<<26)
+#define DISPPLANE_32BPP_NO_ALPHA (0x6<<26)
+#define DISPPLANE_32BPP (0x7<<26)
+#define DISPPLANE_STEREO_ENABLE (1<<25)
+#define DISPPLANE_STEREO_DISABLE 0
+#define DISPPLANE_SEL_PIPE_MASK (1<<24)
+#define DISPPLANE_SEL_PIPE_POS 24
+#define DISPPLANE_SEL_PIPE_A 0
+#define DISPPLANE_SEL_PIPE_B (1<<24)
+#define DISPPLANE_SRC_KEY_ENABLE (1<<22)
+#define DISPPLANE_SRC_KEY_DISABLE 0
+#define DISPPLANE_LINE_DOUBLE (1<<20)
+#define DISPPLANE_NO_LINE_DOUBLE 0
+#define DISPPLANE_STEREO_POLARITY_FIRST 0
+#define DISPPLANE_STEREO_POLARITY_SECOND (1<<18)
+/* plane B only */
+#define DISPPLANE_ALPHA_TRANS_ENABLE (1<<15)
+#define DISPPLANE_ALPHA_TRANS_DISABLE 0
+#define DISPPLANE_SPRITE_ABOVE_DISPLAYA 0
+#define DISPPLANE_SPRITE_ABOVE_OVERLAY (1)
+#define DISPPLANE_BOTTOM (4)
+
+#define DSPABASE 0x70184
+#define DSPALINOFF 0x70184
+#define DSPASTRIDE 0x70188
+
+#define DSPBBASE 0x71184
+#define DSPBLINOFF 0X71184
+#define DSPBADDR DSPBBASE
+#define DSPBSTRIDE 0x71188
+
+#define DSPCBASE 0x72184
+#define DSPCLINOFF 0x72184
+#define DSPCSTRIDE 0x72188
+
+#define DSPAKEYVAL 0x70194
+#define DSPAKEYMASK 0x70198
+
+#define DSPAPOS 0x7018C /* reserved */
+#define DSPASIZE 0x70190
+#define DSPBPOS 0x7118C
+#define DSPBSIZE 0x71190
+#define DSPCPOS 0x7218C
+#define DSPCSIZE 0x72190
+
+#define DSPASURF 0x7019C
+#define DSPATILEOFF 0x701A4
+
+#define DSPBSURF 0x7119C
+#define DSPBTILEOFF 0x711A4
+
+#define DSPCSURF 0x7219C
+#define DSPCTILEOFF 0x721A4
+#define DSPCKEYMAXVAL 0x721A0
+#define DSPCKEYMINVAL 0x72194
+#define DSPCKEYMSK 0x72198
+
+#define VGACNTRL 0x71400
+# define VGA_DISP_DISABLE (1 << 31)
+# define VGA_2X_MODE (1 << 30)
+# define VGA_PIPE_B_SELECT (1 << 29)
+
+/*
+ * Overlay registers
+ */
+#define OV_C_OFFSET 0x08000
+#define OV_OVADD 0x30000
+#define OV_DOVASTA 0x30008
+# define OV_PIPE_SELECT (BIT(6)|BIT(7))
+# define OV_PIPE_SELECT_POS 6
+# define OV_PIPE_A 0
+# define OV_PIPE_C 1
+#define OV_OGAMC5 0x30010
+#define OV_OGAMC4 0x30014
+#define OV_OGAMC3 0x30018
+#define OV_OGAMC2 0x3001C
+#define OV_OGAMC1 0x30020
+#define OV_OGAMC0 0x30024
+#define OVC_OVADD 0x38000
+#define OVC_DOVCSTA 0x38008
+#define OVC_OGAMC5 0x38010
+#define OVC_OGAMC4 0x38014
+#define OVC_OGAMC3 0x38018
+#define OVC_OGAMC2 0x3801C
+#define OVC_OGAMC1 0x38020
+#define OVC_OGAMC0 0x38024
+
+/*
+ * Some BIOS scratch area registers. The 845 (and 830?) store the amount
+ * of video memory available to the BIOS in SWF1.
+ */
+#define SWF0 0x71410
+#define SWF1 0x71414
+#define SWF2 0x71418
+#define SWF3 0x7141c
+#define SWF4 0x71420
+#define SWF5 0x71424
+#define SWF6 0x71428
+
+/*
+ * 855 scratch registers.
+ */
+#define SWF00 0x70410
+#define SWF01 0x70414
+#define SWF02 0x70418
+#define SWF03 0x7041c
+#define SWF04 0x70420
+#define SWF05 0x70424
+#define SWF06 0x70428
+
+#define SWF10 SWF0
+#define SWF11 SWF1
+#define SWF12 SWF2
+#define SWF13 SWF3
+#define SWF14 SWF4
+#define SWF15 SWF5
+#define SWF16 SWF6
+
+#define SWF30 0x72414
+#define SWF31 0x72418
+#define SWF32 0x7241c
+
+
+/*
+ * Palette registers
+ */
+#define PALETTE_A 0x0a000
+#define PALETTE_B 0x0a800
+#define PALETTE_C 0x0ac00
+
+#define IS_I830(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82830_CGC)
+#define IS_845G(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82845G_IG)
+#define IS_I85X(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82855GM_IG)
+#define IS_I855(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82855GM_IG)
+#define IS_I865G(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82865_IG)
+
+
+/* || dev->pci_device == PCI_DEVICE_ID_INTELPCI_CHIP_E7221_G) */
+#define IS_I915G(dev) (dev->pci_device == PCI_DEVICE_ID_INTEL_82915G_IG)
+#define IS_I915GM(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82915GM_IG)
+#define IS_I945G(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82945G_IG)
+#define IS_I945GM(dev) ((dev)->pci_device == PCI_DEVICE_ID_INTEL_82945GM_IG)
+
+#define IS_I965G(dev) ((dev)->pci_device == 0x2972 || \
+ (dev)->pci_device == 0x2982 || \
+ (dev)->pci_device == 0x2992 || \
+ (dev)->pci_device == 0x29A2 || \
+ (dev)->pci_device == 0x2A02 || \
+ (dev)->pci_device == 0x2A12)
+
+#define IS_I965GM(dev) ((dev)->pci_device == 0x2A02)
+
+#define IS_G33(dev) ((dev)->pci_device == 0x29C2 || \
+ (dev)->pci_device == 0x29B2 || \
+ (dev)->pci_device == 0x29D2)
+
+#define IS_I9XX(dev) (IS_I915G(dev) || IS_I915GM(dev) || IS_I945G(dev) || \
+ IS_I945GM(dev) || IS_I965G(dev))
+
+#define IS_MOBILE(dev) (IS_I830(dev) || IS_I85X(dev) || IS_I915GM(dev) || \
+ IS_I945GM(dev) || IS_I965GM(dev))
+
+/* Cursor A & B regs */
+#define CURACNTR 0x70080
+#define CURSOR_MODE_DISABLE 0x00
+#define CURSOR_MODE_64_32B_AX 0x07
+#define CURSOR_MODE_64_ARGB_AX ((1 << 5) | CURSOR_MODE_64_32B_AX)
+#define MCURSOR_GAMMA_ENABLE (1 << 26)
+#define CURABASE 0x70084
+#define CURAPOS 0x70088
+#define CURSOR_POS_MASK 0x007FF
+#define CURSOR_POS_SIGN 0x8000
+#define CURSOR_X_SHIFT 0
+#define CURSOR_Y_SHIFT 16
+#define CURBCNTR 0x700c0
+#define CURBBASE 0x700c4
+#define CURBPOS 0x700c8
+#define CURCCNTR 0x700e0
+#define CURCBASE 0x700e4
+#define CURCPOS 0x700e8
+
+/*
+ * Interrupt Registers
+ */
+#define IER 0x020a0
+#define IIR 0x020a4
+#define IMR 0x020a8
+#define ISR 0x020ac
+
+/*
+ * MOORESTOWN delta registers
+ */
+#define MRST_DPLL_A 0x0f014
+#define MDFLD_DPLL_B 0x0f018
+#define MDFLD_INPUT_REF_SEL (1 << 14)
+#define MDFLD_VCO_SEL (1 << 16)
+#define DPLLA_MODE_LVDS (2 << 26) /* mrst */
+#define MDFLD_PLL_LATCHEN (1 << 28)
+#define MDFLD_PWR_GATE_EN (1 << 30)
+#define MDFLD_P1_MASK (0x1FF << 17)
+#define MRST_FPA0 0x0f040
+#define MRST_FPA1 0x0f044
+#define MDFLD_DPLL_DIV0 0x0f048
+#define MDFLD_DPLL_DIV1 0x0f04c
+#define MRST_PERF_MODE 0x020f4
+
+/* MEDFIELD HDMI registers */
+#define HDMIPHYMISCCTL 0x61134
+# define HDMI_PHY_POWER_DOWN 0x7f
+#define HDMIB_CONTROL 0x61140
+# define HDMIB_PORT_EN (1 << 31)
+# define HDMIB_PIPE_B_SELECT (1 << 30)
+# define HDMIB_NULL_PACKET (1 << 9)
+#define HDMIB_HDCP_PORT (1 << 5)
+
+/* #define LVDS 0x61180 */
+# define MRST_PANEL_8TO6_DITHER_ENABLE (1 << 25)
+# define MRST_PANEL_24_DOT_1_FORMAT (1 << 24)
+# define LVDS_A3_POWER_UP_0_OUTPUT (1 << 6)
+
+#define MIPI 0x61190
+#define MIPI_C 0x62190
+# define MIPI_PORT_EN (1 << 31)
+/** Turns on border drawing to allow centered display. */
+# define SEL_FLOPPED_HSTX (1 << 23)
+# define PASS_FROM_SPHY_TO_AFE (1 << 16)
+# define MIPI_BORDER_EN (1 << 15)
+# define MIPIA_3LANE_MIPIC_1LANE 0x1
+# define MIPIA_2LANE_MIPIC_2LANE 0x2
+# define TE_TRIGGER_DSI_PROTOCOL (1 << 2)
+# define TE_TRIGGER_GPIO_PIN (1 << 3)
+#define MIPI_TE_COUNT 0x61194
+
+/* #define PP_CONTROL 0x61204 */
+# define POWER_DOWN_ON_RESET (1 << 1)
+
+/* #define PFIT_CONTROL 0x61230 */
+# define PFIT_PIPE_SELECT (3 << 29)
+# define PFIT_PIPE_SELECT_SHIFT (29)
+
+/* #define BLC_PWM_CTL 0x61254 */
+#define MRST_BACKLIGHT_MODULATION_FREQ_SHIFT (16)
+#define MRST_BACKLIGHT_MODULATION_FREQ_MASK (0xffff << 16)
+
+/* #define PIPEACONF 0x70008 */
+#define PIPEACONF_PIPE_STATE (1<<30)
+/* #define DSPACNTR 0x70180 */
+#if 0 /*FIXME JLIU7 need to define the following */
+1000 = 32 - bit RGBX(10 : 10 : 10 : 2)
+pixel format.Ignore alpha.1010 = BGRX 10 : 10 : 10 : 2 1100 = 64 - bit RGBX
+(16 : 16 : 16 : 16) 16 bit floating point pixel format.
+Ignore alpha.1110 = 32 - bit RGBX(8 : 8 : 8 : 8) pixel format.
+ Ignore
+ alpha.
+#endif /*FIXME JLIU7 need to define the following */
+
+#define MRST_DSPABASE 0x7019c
+#define MRST_DSPBBASE 0x7119c
+#define MDFLD_DSPCBASE 0x7219c
+
+/*
+ * MOORESTOWN reserved registers
+ */
+#if 0
+#define DSPAPOS 0x7018C /* reserved */
+#define DSPASIZE 0x70190
+#endif
+/*
+ * Moorestown registers.
+ */
+/*===========================================================================
+; MIPI IP registers
+;--------------------------------------------------------------------------*/
+#define MIPIC_REG_OFFSET 0x800
+#define DEVICE_READY_REG 0xb000
+#define LP_OUTPUT_HOLD BIT(16)
+#define EXIT_ULPS_DEV_READY 0x3
+#define LP_OUTPUT_HOLD_RELEASE 0x810000
+# define ENTERING_ULPS (2 << 1)
+# define EXITING_ULPS (1 << 1)
+# define ULPS_MASK (3 << 1)
+# define BUS_POSSESSION (1 << 3)
+#define INTR_STAT_REG 0xb004
+#define RX_SOT_ERROR BIT(0)
+#define RX_SOT_SYNC_ERROR BIT(1)
+#define RX_ESCAPE_MODE_ENTRY_ERROR BIT(3)
+#define RX_LP_TX_SYNC_ERROR BIT(4)
+#define RX_HS_RECEIVE_TIMEOUT_ERROR BIT(5)
+#define RX_FALSE_CONTROL_ERROR BIT(6)
+#define RX_ECC_SINGLE_BIT_ERROR BIT(7)
+#define RX_ECC_MULTI_BIT_ERROR BIT(8)
+#define RX_CHECKSUM_ERROR BIT(9)
+#define RX_DSI_DATA_TYPE_NOT_RECOGNIZED BIT(10)
+#define RX_DSI_VC_ID_INVALID BIT(11)
+#define TX_FALSE_CONTROL_ERROR BIT(12)
+#define TX_ECC_SINGLE_BIT_ERROR BIT(13)
+#define TX_ECC_MULTI_BIT_ERROR BIT(14)
+#define TX_CHECKSUM_ERROR BIT(15)
+#define TX_DSI_DATA_TYPE_NOT_RECOGNIZED BIT(16)
+#define TX_DSI_VC_ID_INVALID BIT(17)
+#define HIGH_CONTENTION BIT(18)
+#define LOW_CONTENTION BIT(19)
+#define DPI_FIFO_UNDER_RUN BIT(20)
+#define HS_TX_TIMEOUT BIT(21)
+#define LP_RX_TIMEOUT BIT(22)
+#define TURN_AROUND_ACK_TIMEOUT BIT(23)
+#define ACK_WITH_NO_ERROR BIT(24)
+#define HS_GENERIC_WR_FIFO_FULL BIT(27)
+#define LP_GENERIC_WR_FIFO_FULL BIT(28)
+#define SPL_PKT_SENT BIT(30)
+#define INTR_EN_REG 0xb008
+#define DSI_FUNC_PRG_REG 0xb00c
+#define DPI_CHANNEL_NUMBER_POS 0x03
+#define DBI_CHANNEL_NUMBER_POS 0x05
+#define FMT_DPI_POS 0x07
+#define FMT_DBI_POS 0x0A
+#define DBI_DATA_WIDTH_POS 0x0D
+/* DPI PIXEL FORMATS */
+#define RGB_565_FMT 0x01 /* RGB 565 FORMAT */
+#define RGB_666_FMT 0x02 /* RGB 666 FORMAT */
+#define LRGB_666_FMT 0x03 /* RGB LOOSELY PACKED
+ * 666 FORMAT
+ */
+#define RGB_888_FMT 0x04 /* RGB 888 FORMAT */
+#define VIRTUAL_CHANNEL_NUMBER_0 0x00 /* Virtual channel 0 */
+#define VIRTUAL_CHANNEL_NUMBER_1 0x01 /* Virtual channel 1 */
+#define VIRTUAL_CHANNEL_NUMBER_2 0x02 /* Virtual channel 2 */
+#define VIRTUAL_CHANNEL_NUMBER_3 0x03 /* Virtual channel 3 */
+#define DBI_NOT_SUPPORTED 0x00 /* command mode
+ * is not supported
+ */
+#define DBI_DATA_WIDTH_16BIT 0x01 /* 16 bit data */
+#define DBI_DATA_WIDTH_9BIT 0x02 /* 9 bit data */
+#define DBI_DATA_WIDTH_8BIT 0x03 /* 8 bit data */
+#define DBI_DATA_WIDTH_OPT1 0x04 /* option 1 */
+#define DBI_DATA_WIDTH_OPT2 0x05 /* option 2 */
+#define HS_TX_TIMEOUT_REG 0xb010
+#define LP_RX_TIMEOUT_REG 0xb014
+#define TURN_AROUND_TIMEOUT_REG 0xb018
+#define DEVICE_RESET_REG 0xb01C
+#define DPI_RESOLUTION_REG 0xb020
+#define RES_V_POS 0x10
+#define DBI_RESOLUTION_REG 0xb024 /* Reserved for MDFLD */
+#define HORIZ_SYNC_PAD_COUNT_REG 0xb028
+#define HORIZ_BACK_PORCH_COUNT_REG 0xb02C
+#define HORIZ_FRONT_PORCH_COUNT_REG 0xb030
+#define HORIZ_ACTIVE_AREA_COUNT_REG 0xb034
+#define VERT_SYNC_PAD_COUNT_REG 0xb038
+#define VERT_BACK_PORCH_COUNT_REG 0xb03c
+#define VERT_FRONT_PORCH_COUNT_REG 0xb040
+#define HIGH_LOW_SWITCH_COUNT_REG 0xb044
+#define DPI_CONTROL_REG 0xb048
+#define DPI_SHUT_DOWN BIT(0)
+#define DPI_TURN_ON BIT(1)
+#define DPI_COLOR_MODE_ON BIT(2)
+#define DPI_COLOR_MODE_OFF BIT(3)
+#define DPI_BACK_LIGHT_ON BIT(4)
+#define DPI_BACK_LIGHT_OFF BIT(5)
+#define DPI_LP BIT(6)
+#define DPI_DATA_REG 0xb04c
+#define DPI_BACK_LIGHT_ON_DATA 0x07
+#define DPI_BACK_LIGHT_OFF_DATA 0x17
+#define INIT_COUNT_REG 0xb050
+#define MAX_RET_PAK_REG 0xb054
+#define VIDEO_FMT_REG 0xb058
+#define COMPLETE_LAST_PCKT BIT(2)
+#define EOT_DISABLE_REG 0xb05c
+#define ENABLE_CLOCK_STOPPING BIT(1)
+#define LP_BYTECLK_REG 0xb060
+#define LP_GEN_DATA_REG 0xb064
+#define HS_GEN_DATA_REG 0xb068
+#define LP_GEN_CTRL_REG 0xb06C
+#define HS_GEN_CTRL_REG 0xb070
+#define DCS_CHANNEL_NUMBER_POS 0x06
+#define MCS_COMMANDS_POS 0x8
+#define WORD_COUNTS_POS 0x8
+#define MCS_PARAMETER_POS 0x10
+#define GEN_FIFO_STAT_REG 0xb074
+#define HS_DATA_FIFO_FULL BIT(0)
+#define HS_DATA_FIFO_HALF_EMPTY BIT(1)
+#define HS_DATA_FIFO_EMPTY BIT(2)
+#define LP_DATA_FIFO_FULL BIT(8)
+#define LP_DATA_FIFO_HALF_EMPTY BIT(9)
+#define LP_DATA_FIFO_EMPTY BIT(10)
+#define HS_CTRL_FIFO_FULL BIT(16)
+#define HS_CTRL_FIFO_HALF_EMPTY BIT(17)
+#define HS_CTRL_FIFO_EMPTY BIT(18)
+#define LP_CTRL_FIFO_FULL BIT(24)
+#define LP_CTRL_FIFO_HALF_EMPTY BIT(25)
+#define LP_CTRL_FIFO_EMPTY BIT(26)
+#define DBI_FIFO_EMPTY BIT(27)
+#define DPI_FIFO_EMPTY BIT(28)
+#define HS_LS_DBI_ENABLE_REG 0xb078
+#define TXCLKESC_REG 0xb07c
+#define DPHY_PARAM_REG 0xb080
+#define DBI_BW_CTRL_REG 0xb084
+#define CLK_LANE_SWT_REG 0xb088
+/*===========================================================================
+; MIPI Adapter registers
+;--------------------------------------------------------------------------*/
+#define MIPI_CONTROL_REG 0xb104
+#define MIPI_2X_CLOCK_BITS (BIT(0) | BIT(1))
+#define MIPI_DATA_ADDRESS_REG 0xb108
+#define MIPI_DATA_LENGTH_REG 0xb10C
+#define MIPI_COMMAND_ADDRESS_REG 0xb110
+#define MIPI_COMMAND_LENGTH_REG 0xb114
+#define MIPI_READ_DATA_RETURN_REG0 0xb118
+#define MIPI_READ_DATA_RETURN_REG1 0xb11C
+#define MIPI_READ_DATA_RETURN_REG2 0xb120
+#define MIPI_READ_DATA_RETURN_REG3 0xb124
+#define MIPI_READ_DATA_RETURN_REG4 0xb128
+#define MIPI_READ_DATA_RETURN_REG5 0xb12C
+#define MIPI_READ_DATA_RETURN_REG6 0xb130
+#define MIPI_READ_DATA_RETURN_REG7 0xb134
+#define MIPI_READ_DATA_VALID_REG 0xb138
+/* DBI COMMANDS */
+#define soft_reset 0x01
+/* ************************************************************************* *\
+The display module performs a software reset.
+Registers are written with their SW Reset default values.
+\* ************************************************************************* */
+#define get_power_mode 0x0a
+/* ************************************************************************* *\
+The display module returns the current power mode
+\* ************************************************************************* */
+#define get_address_mode 0x0b
+/* ************************************************************************* *\
+The display module returns the current status.
+\* ************************************************************************* */
+#define get_pixel_format 0x0c
+/* ************************************************************************* *\
+This command gets the pixel format for the RGB image data
+used by the interface.
+\* ************************************************************************* */
+#define get_display_mode 0x0d
+/* ************************************************************************* *\
+The display module returns the Display Image Mode status.
+\* ************************************************************************* */
+#define get_signal_mode 0x0e
+/* ************************************************************************* *\
+The display module returns the Display Signal Mode.
+\* ************************************************************************* */
+#define get_diagnostic_result 0x0f
+/* ************************************************************************* *\
+The display module returns the self-diagnostic results following
+a Sleep Out command.
+\* ************************************************************************* */
+#define enter_sleep_mode 0x10
+/* ************************************************************************* *\
+This command causes the display module to enter the Sleep mode.
+In this mode, all unnecessary blocks inside the display module are disabled
+except interface communication. This is the lowest power mode
+the display module supports.
+\* ************************************************************************* */
+#define exit_sleep_mode 0x11
+/* ************************************************************************* *\
+This command causes the display module to exit Sleep mode.
+All blocks inside the display module are enabled.
+\* ************************************************************************* */
+#define enter_partial_mode 0x12
+/* ************************************************************************* *\
+This command causes the display module to enter the Partial Display Mode.
+The Partial Display Mode window is described by the set_partial_area command.
+\* ************************************************************************* */
+#define enter_normal_mode 0x13
+/* ************************************************************************* *\
+This command causes the display module to enter the Normal mode.
+Normal Mode is defined as Partial Display mode and Scroll mode are off
+\* ************************************************************************* */
+#define exit_invert_mode 0x20
+/* ************************************************************************* *\
+This command causes the display module to stop inverting the image data on
+the display device. The frame memory contents remain unchanged.
+No status bits are changed.
+\* ************************************************************************* */
+#define enter_invert_mode 0x21
+/* ************************************************************************* *\
+This command causes the display module to invert the image data only on
+the display device. The frame memory contents remain unchanged.
+No status bits are changed.
+\* ************************************************************************* */
+#define set_gamma_curve 0x26
+/* ************************************************************************* *\
+This command selects the desired gamma curve for the display device.
+Four fixed gamma curves are defined in section DCS spec.
+\* ************************************************************************* */
+#define set_display_off 0x28
+/* ************************************************************************* *\
+This command causes the display module to stop displaying the image data
+on the display device. The frame memory contents remain unchanged.
+No status bits are changed.
+\* ************************************************************************* */
+#define set_display_on 0x29
+/* ************************************************************************* *\
+This command causes the display module to start displaying the image data
+on the display device. The frame memory contents remain unchanged.
+No status bits are changed.
+\* ************************************************************************* */
+#define set_column_address 0x2a
+/* ************************************************************************* *\
+This command defines the column extent of the frame memory accessed by the
+hostprocessor with the read_memory_continue and write_memory_continue commands.
+No status bits are changed.
+\* ************************************************************************* */
+#define set_page_addr 0x2b
+/* ************************************************************************* *\
+This command defines the page extent of the frame memory accessed by the host
+processor with the write_memory_continue and read_memory_continue command.
+No status bits are changed.
+\* ************************************************************************* */
+#define write_mem_start 0x2c
+/* ************************************************************************* *\
+This command transfers image data from the host processor to the display
+module s frame memory starting at the pixel location specified by
+preceding set_column_address and set_page_address commands.
+\* ************************************************************************* */
+#define set_partial_area 0x30
+/* ************************************************************************* *\
+This command defines the Partial Display mode s display area.
+There are two parameters associated with
+this command, the first defines the Start Row (SR) and the second the End Row
+(ER). SR and ER refer to the Frame Memory Line Pointer.
+\* ************************************************************************* */
+#define set_scroll_area 0x33
+/* ************************************************************************* *\
+This command defines the display modules Vertical Scrolling Area.
+\* ************************************************************************* */
+#define set_tear_off 0x34
+/* ************************************************************************* *\
+This command turns off the display modules Tearing Effect output signal on
+the TE signal line.
+\* ************************************************************************* */
+#define set_tear_on 0x35
+/* ************************************************************************* *\
+This command turns on the display modules Tearing Effect output signal
+on the TE signal line.
+\* ************************************************************************* */
+#define set_address_mode 0x36
+/* ************************************************************************* *\
+This command sets the data order for transfers from the host processor to
+display modules frame memory,bits B[7:5] and B3, and from the display
+modules frame memory to the display device, bits B[2:0] and B4.
+\* ************************************************************************* */
+#define set_scroll_start 0x37
+/* ************************************************************************* *\
+This command sets the start of the vertical scrolling area in the frame memory.
+The vertical scrolling area is fully defined when this command is used with
+the set_scroll_area command The set_scroll_start command has one parameter,
+the Vertical Scroll Pointer. The VSP defines the line in the frame memory
+that is written to the display device as the first line of the vertical
+scroll area.
+\* ************************************************************************* */
+#define exit_idle_mode 0x38
+/* ************************************************************************* *\
+This command causes the display module to exit Idle mode.
+\* ************************************************************************* */
+#define enter_idle_mode 0x39
+/* ************************************************************************* *\
+This command causes the display module to enter Idle Mode.
+In Idle Mode, color expression is reduced. Colors are shown on the display
+device using the MSB of each of the R, G and B color components in the frame
+memory
+\* ************************************************************************* */
+#define set_pixel_format 0x3a
+/* ************************************************************************* *\
+This command sets the pixel format for the RGB image data used by the interface.
+Bits D[6:4] DPI Pixel Format Definition
+Bits D[2:0] DBI Pixel Format Definition
+Bits D7 and D3 are not used.
+\* ************************************************************************* */
+ #define DCS_PIXEL_FORMAT_3bbp 0x1
+ #define DCS_PIXEL_FORMAT_8bbp 0x2
+ #define DCS_PIXEL_FORMAT_12bbp 0x3
+ #define DCS_PIXEL_FORMAT_16bbp 0x5
+ #define DCS_PIXEL_FORMAT_18bbp 0x6
+ #define DCS_PIXEL_FORMAT_24bbp 0x7
+#define write_mem_cont 0x3c
+/* ************************************************************************* *\
+This command transfers image data from the host processor to the display
+module's frame memory continuing from the pixel location following the
+previous write_memory_continue or write_memory_start command.
+\* ************************************************************************* */
+#define set_tear_scanline 0x44
+/* ************************************************************************* *\
+This command turns on the display modules Tearing Effect output signal on the
+TE signal line when the display module reaches line N.
+\* ************************************************************************* */
+#define get_scanline 0x45
+/* ************************************************************************* *\
+The display module returns the current scanline, N, used to update the
+display device. The total number of scanlines on a display device is
+defined as VSYNC + VBP + VACT + VFP.The first scanline is defined as
+the first line of V Sync and is denoted as Line 0.
+When in Sleep Mode, the value returned by get_scanline is undefined.
+\* ************************************************************************* */
+
+/* MCS or Generic COMMANDS */
+/* MCS/generic data type */
+#define GEN_SHORT_WRITE_0 0x03 /* generic short write, no parameters */
+#define GEN_SHORT_WRITE_1 0x13 /* generic short write, 1 parameters */
+#define GEN_SHORT_WRITE_2 0x23 /* generic short write, 2 parameters */
+#define GEN_READ_0 0x04 /* generic read, no parameters */
+#define GEN_READ_1 0x14 /* generic read, 1 parameters */
+#define GEN_READ_2 0x24 /* generic read, 2 parameters */
+#define GEN_LONG_WRITE 0x29 /* generic long write */
+#define MCS_SHORT_WRITE_0 0x05 /* MCS short write, no parameters */
+#define MCS_SHORT_WRITE_1 0x15 /* MCS short write, 1 parameters */
+#define MCS_READ 0x06 /* MCS read, no parameters */
+#define MCS_LONG_WRITE 0x39 /* MCS long write */
+/* MCS/generic commands */
+/*****TPO MCS**********/
+#define write_display_profile 0x50
+#define write_display_brightness 0x51
+#define write_ctrl_display 0x53
+#define write_ctrl_cabc 0x55
+ #define UI_IMAGE 0x01
+ #define STILL_IMAGE 0x02
+ #define MOVING_IMAGE 0x03
+#define write_hysteresis 0x57
+#define write_gamma_setting 0x58
+#define write_cabc_min_bright 0x5e
+#define write_kbbc_profile 0x60
+/*****TMD MCS**************/
+#define tmd_write_display_brightness 0x8c
+
+/* ************************************************************************* *\
+This command is used to control ambient light, panel backlight brightness and
+gamma settings.
+\* ************************************************************************* */
+#define BRIGHT_CNTL_BLOCK_ON BIT(5)
+#define AMBIENT_LIGHT_SENSE_ON BIT(4)
+#define DISPLAY_DIMMING_ON BIT(3)
+#define BACKLIGHT_ON BIT(2)
+#define DISPLAY_BRIGHTNESS_AUTO BIT(1)
+#define GAMMA_AUTO BIT(0)
+
+/* DCS Interface Pixel Formats */
+#define DCS_PIXEL_FORMAT_3BPP 0x1
+#define DCS_PIXEL_FORMAT_8BPP 0x2
+#define DCS_PIXEL_FORMAT_12BPP 0x3
+#define DCS_PIXEL_FORMAT_16BPP 0x5
+#define DCS_PIXEL_FORMAT_18BPP 0x6
+#define DCS_PIXEL_FORMAT_24BPP 0x7
+/* ONE PARAMETER READ DATA */
+#define addr_mode_data 0xfc
+#define diag_res_data 0x00
+#define disp_mode_data 0x23
+#define pxl_fmt_data 0x77
+#define pwr_mode_data 0x74
+#define sig_mode_data 0x00
+/* TWO PARAMETERS READ DATA */
+#define scanline_data1 0xff
+#define scanline_data2 0xff
+#define NON_BURST_MODE_SYNC_PULSE 0x01 /* Non Burst Mode
+ * with Sync Pulse
+ */
+#define NON_BURST_MODE_SYNC_EVENTS 0x02 /* Non Burst Mode
+ * with Sync events
+ */
+#define BURST_MODE 0x03 /* Burst Mode */
+#define DBI_COMMAND_BUFFER_SIZE 0x240 /* 0x32 */ /* 0x120 */ /* Allocate at least
+ * 0x100 Byte with 32
+ * byte alignment
+ */
+#define DBI_DATA_BUFFER_SIZE 0x120 /* Allocate at least
+ * 0x100 Byte with 32
+ * byte alignment
+ */
+#define DBI_CB_TIME_OUT 0xFFFF
+#define GEN_FB_TIME_OUT 2000
+#define ALIGNMENT_32BYTE_MASK (~(BIT(0)|BIT(1)|BIT(2)|BIT(3)|BIT(4)))
+#define SKU_83 0x01
+#define SKU_100 0x02
+#define SKU_100L 0x04
+#define SKU_BYPASS 0x08
+#if 0
+/* ************************************************************************* *\
+DSI command data structure
+\* ************************************************************************* */
+union DSI_LONG_PACKET_HEADER {
+ u32 DSI_longPacketHeader;
+ struct {
+ u8 dataID;
+ u16 wordCount;
+ u8 ECC;
+ };
+#if 0 /*FIXME JLIU7 */
+ struct {
+ u8 DT:6;
+ u8 VC:2;
+ };
+#endif /*FIXME JLIU7 */
+};
+
+union MIPI_ADPT_CMD_LNG_REG {
+ u32 commnadLengthReg;
+ struct {
+ u8 command0;
+ u8 command1;
+ u8 command2;
+ u8 command3;
+ };
+};
+
+struct SET_COLUMN_ADDRESS_DATA {
+ u8 command;
+ u16 SC; /* Start Column */
+ u16 EC; /* End Column */
+};
+
+struct SET_PAGE_ADDRESS_DATA {
+ u8 command;
+ u16 SP; /* Start Page */
+ u16 EP; /* End Page */
+};
+#endif
+
+#endif
--- /dev/null
+/**************************************************************************
+ * Copyright (c) 2007, Intel Corporation.
+ * 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 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.
+ *
+ * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ * develop this driver.
+ *
+ **************************************************************************/
+/*
+ */
+
+#include <drm/drmP.h>
+#include "psb_drv.h"
+#include "psb_page_flip.h"
+#include "psb_reg.h"
+#include "psb_msvdx.h"
+#include "pnw_topaz.h"
+#include "psb_intel_reg.h"
+#include "psb_powermgmt.h"
+
+#include "mdfld_dsi_dbi_dpu.h"
+
+#ifdef CONFIG_MDFD_GL3
+#include "mdfld_gl3.h"
+#endif
+
+/*
+ * inline functions
+ */
+
+static inline u32
+psb_pipestat(int pipe)
+{
+ if (pipe == 0)
+ return PIPEASTAT;
+ if (pipe == 1)
+ return PIPEBSTAT;
+ if (pipe == 2)
+ return PIPECSTAT;
+ BUG();
+}
+
+static inline u32
+mid_pipe_event(int pipe)
+{
+ if (pipe == 0)
+ return _PSB_PIPEA_EVENT_FLAG;
+ if (pipe == 1)
+ return _MDFLD_PIPEB_EVENT_FLAG;
+ if (pipe == 2)
+ return _MDFLD_PIPEC_EVENT_FLAG;
+ BUG();
+}
+
+static inline u32
+mid_pipe_vsync(int pipe)
+{
+ if (pipe == 0)
+ return _PSB_VSYNC_PIPEA_FLAG;
+ if (pipe == 1)
+ return _PSB_VSYNC_PIPEB_FLAG;
+ if (pipe == 2)
+ return _MDFLD_PIPEC_VBLANK_FLAG;
+ BUG();
+}
+
+static inline u32
+mid_pipeconf(int pipe)
+{
+ if (pipe == 0)
+ return PIPEACONF;
+ if (pipe == 1)
+ return PIPEBCONF;
+ if (pipe == 2)
+ return PIPECCONF;
+ BUG();
+}
+
+void
+psb_enable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask)
+{
+ if ((dev_priv->pipestat[pipe] & mask) != mask) {
+ u32 reg = psb_pipestat(pipe);
+ dev_priv->pipestat[pipe] |= mask;
+ /* Enable the interrupt, clear any pending status */
+ if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_ONLY_IF_ON)) {
+ u32 writeVal = PSB_RVDC32(reg);
+ writeVal |= (mask | (mask >> 16));
+ PSB_WVDC32(writeVal, reg);
+ (void) PSB_RVDC32(reg);
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+ }
+ }
+}
+
+void
+psb_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask)
+{
+ if ((dev_priv->pipestat[pipe] & mask) != 0) {
+ u32 reg = psb_pipestat(pipe);
+ dev_priv->pipestat[pipe] &= ~mask;
+ if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_ONLY_IF_ON)) {
+ u32 writeVal = PSB_RVDC32(reg);
+ writeVal &= ~mask;
+ PSB_WVDC32(writeVal, reg);
+ (void) PSB_RVDC32(reg);
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+ }
+ }
+}
+
+static void
+mid_enable_pipe_event(struct drm_psb_private *dev_priv, int pipe)
+{
+ if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_ONLY_IF_ON)) {
+ u32 pipe_event = mid_pipe_event(pipe);
+ dev_priv->vdc_irq_mask |= pipe_event;
+ PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
+ PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+ }
+}
+
+static void
+mid_disable_pipe_event(struct drm_psb_private *dev_priv, int pipe)
+{
+ if (dev_priv->pipestat[pipe] == 0) {
+ if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_ONLY_IF_ON)) {
+ u32 pipe_event = mid_pipe_event(pipe);
+ dev_priv->vdc_irq_mask &= ~pipe_event;
+ PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
+ PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+ }
+ }
+}
+
+/**
+ * Display controller interrupt handler for vsync/vblank.
+ *
+ */
+static void mid_vblank_handler(struct drm_device *dev, uint32_t pipe)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) dev->dev_private;
+ struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
+#if 0 /* FIXME_JLIU7 revisit it*/
+ uint32_t *vbl_received = &dev->vbl_received;
+
+ switch (pipe) {
+ case 0:
+ break;
+ case 1:
+ vbl_received = &dev->vbl_received1;
+ break;
+ case 2:
+ vbl_received = &dev->vbl_received2;
+ break;
+ default:
+ DRM_ERROR("%s, invalded pipe. \n", __FUNCTION__);
+ return;
+ }
+
+
+#ifdef PSB_FIXME
+ atomic_inc(vbl_received);
+#endif
+#endif /* FIXME_JLIU7 revisit it*/
+
+ /**
+ * Using TE interrupt for B0 + command mode panels
+ */
+ if (!is_panel_vid_or_cmd(dev))
+ return;
+
+ drm_handle_vblank(dev, pipe);
+ if (dev_priv->psb_vsync_handler != NULL)
+ (*dev_priv->psb_vsync_handler)(dev, pipe);
+
+ psb_intel_crtc_process_vblank(crtc);
+}
+
+/**
+ * Display controller interrupt handler for pipe hdmi audio underrun.
+ *
+ */
+static void mdfld_pipe_hdmi_audio_underrun(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) dev->dev_private;
+
+ if (dev_priv->mdfld_had_event_callbacks)
+ (*dev_priv->mdfld_had_event_callbacks)(HAD_EVENT_AUDIO_BUFFER_UNDERRUN, NULL);
+}
+
+/**
+ * Display controller interrupt handler for pipe hdmi audio buffer done.
+ *
+ */
+static void mdfld_pipe_hdmi_audio_buffer_done(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) dev->dev_private;
+
+ if (dev_priv->mdfld_had_event_callbacks)
+ (*dev_priv->mdfld_had_event_callbacks)(HAD_EVENT_AUDIO_BUFFER_DONE, dev_priv->had_pvt_data);
+}
+
+void mdfld_te_handler_work(struct work_struct *work)
+{
+ struct drm_psb_private *dev_priv =
+ container_of(work, struct drm_psb_private, te_work);
+ int pipe = dev_priv->te_pipe;
+ struct drm_device *dev = dev_priv->dev;
+
+#ifdef CONFIG_MDFD_DSI_DPU
+ mdfld_dpu_update_panel(dev);
+#else
+ mdfld_dbi_update_panel(dev, pipe);
+#endif
+
+ /**
+ * Both MIPI panels shares the same system frame buffer
+ * only need to unblock X when the primary panel's TE happens.
+ * FIXME: how to avoid tearing on MIPI1???
+ */
+ if (pipe == 0) {
+ drm_handle_vblank(dev, pipe);
+
+ if (dev_priv->psb_vsync_handler != NULL)
+ (*dev_priv->psb_vsync_handler)(dev, pipe);
+ }
+}
+/**
+ * Display controller interrupt handler for pipe event.
+ *
+ */
+#define WAIT_STATUS_CLEAR_LOOP_COUNT 0xffff
+static void mid_pipe_event_handler(struct drm_device *dev, uint32_t pipe)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) dev->dev_private;
+
+ uint32_t pipe_stat_val = 0;
+ uint32_t pipe_stat_reg = psb_pipestat(pipe);
+ uint32_t pipe_enable = dev_priv->pipestat[pipe];
+ uint32_t pipe_status = dev_priv->pipestat[pipe] >> 16;
+ uint32_t i = 0;
+ unsigned long irq_flags;
+
+ spin_lock_irqsave(&dev_priv->irqmask_lock, irq_flags);
+
+ pipe_stat_val = PSB_RVDC32(pipe_stat_reg);
+ pipe_stat_val &= pipe_enable | pipe_status;
+ pipe_stat_val &= pipe_stat_val >> 16;
+
+ spin_unlock_irqrestore(&dev_priv->irqmask_lock, irq_flags);
+
+ /* clear the 2nd level interrupt status bits */
+ /**
+ * FIXME: shouldn't use while loop here. However, the interrupt
+ * status 'sticky' bits cannot be cleared by setting '1' to that
+ * bit once...
+ */
+ for (i = 0; i < WAIT_STATUS_CLEAR_LOOP_COUNT; i ++) {
+ PSB_WVDC32(PSB_RVDC32(pipe_stat_reg), pipe_stat_reg);
+ (void) PSB_RVDC32(pipe_stat_reg);
+
+ if ((PSB_RVDC32(pipe_stat_reg) & pipe_status) == 0)
+ break;
+ }
+
+ if (i == WAIT_STATUS_CLEAR_LOOP_COUNT)
+ DRM_ERROR("%s, can't clear the status bits in pipe_stat_reg, its value = 0x%x. \n",
+ __FUNCTION__, PSB_RVDC32(pipe_stat_reg));
+
+ if ((pipe_stat_val & PIPE_DPST_EVENT_STATUS) &&
+ (dev_priv->psb_dpst_state != NULL)) {
+ uint32_t pwm_reg = 0;
+ uint32_t hist_reg = 0;
+ u32 irqCtrl = 0;
+ struct dpst_guardband guardband_reg;
+ struct dpst_ie_histogram_control ie_hist_cont_reg;
+
+ hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
+
+ /* Determine if this is histogram or pwm interrupt */
+ if (hist_reg & HISTOGRAM_INT_CTRL_CLEAR) {
+ /* Notify UM of histogram interrupt */
+ psb_dpst_notify_change_um(DPST_EVENT_HIST_INTERRUPT,
+ dev_priv->psb_dpst_state);
+
+ /* disable dpst interrupts */
+ guardband_reg.data = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
+ guardband_reg.interrupt_enable = 0;
+ guardband_reg.interrupt_status = 1;
+ PSB_WVDC32(guardband_reg.data, HISTOGRAM_INT_CONTROL);
+
+ ie_hist_cont_reg.data = PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL);
+ ie_hist_cont_reg.ie_histogram_enable = 0;
+ PSB_WVDC32(ie_hist_cont_reg.data, HISTOGRAM_LOGIC_CONTROL);
+
+ irqCtrl = PSB_RVDC32(PIPEASTAT);
+ irqCtrl &= ~PIPE_DPST_EVENT_ENABLE;
+ PSB_WVDC32(irqCtrl, PIPEASTAT);
+ }
+ pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
+ if ((pwm_reg & PWM_PHASEIN_INT_ENABLE) &&
+ !(pwm_reg & PWM_PHASEIN_ENABLE)) {
+ /* Notify UM of the phase complete */
+ psb_dpst_notify_change_um(DPST_EVENT_PHASE_COMPLETE,
+ dev_priv->psb_dpst_state);
+
+ /* Temporarily get phase mngr ready to generate
+ * another interrupt until this can be moved to
+ * user mode */
+ /* PSB_WVDC32(pwm_reg | 0x80010100 | PWM_PHASEIN_ENABLE,
+ PWM_CONTROL_LOGIC); */
+ }
+ }
+
+ if (pipe_stat_val & PIPE_VBLANK_STATUS) {
+ mid_vblank_handler(dev, pipe);
+ }
+
+ if (pipe_stat_val & PIPE_TE_STATUS) {
+ dev_priv->te_pipe = pipe;
+ schedule_work(&dev_priv->te_work);
+ }
+
+ if (pipe_stat_val & PIPE_HDMI_AUDIO_UNDERRUN_STATUS) {
+ mdfld_pipe_hdmi_audio_underrun(dev);
+ }
+
+ if (pipe_stat_val & PIPE_HDMI_AUDIO_BUFFER_DONE_STATUS) {
+ mdfld_pipe_hdmi_audio_buffer_done(dev);
+ }
+}
+
+/**
+ * Display controller interrupt handler.
+ */
+static void psb_vdc_interrupt(struct drm_device *dev, uint32_t vdc_stat)
+{
+
+ if (vdc_stat & _PSB_PIPEA_EVENT_FLAG) {
+ mid_pipe_event_handler(dev, 0);
+ }
+
+ if (vdc_stat & _MDFLD_PIPEB_EVENT_FLAG) {
+ mid_pipe_event_handler(dev, 1);
+ }
+
+ if (vdc_stat & _MDFLD_PIPEC_EVENT_FLAG) {
+ mid_pipe_event_handler(dev, 2);
+ }
+
+ if (vdc_stat & _MDFLD_MIPIA_FLAG) {
+ /* mid_mipi_event_handler(dev, 0); */
+ }
+
+ if (vdc_stat & _MDFLD_MIPIC_FLAG) {
+ /* mid_mipi_event_handler(dev, 2); */
+ }
+}
+
+/**
+ * Medfield Gl3 Cache interrupt handler.
+ */
+#ifdef CONFIG_MDFD_GL3
+static void mdfld_gl3_interrupt(struct drm_device *dev, uint32_t vdc_stat)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) dev->dev_private;
+ uint32_t gl3_err_status = 0;
+
+ gl3_err_status = MDFLD_GL3_READ(MDFLD_GCL_ERR_STATUS);
+ if (gl3_err_status & _MDFLD_GL3_ECC_FLAG) {
+ gl3_flush();
+ gl3_reset();
+ }
+
+ dev_priv->vdc_irq_mask &= ~_MDFLD_GL3_IRQ_FLAG;
+ PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
+ PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
+
+}
+#endif
+
+
+irqreturn_t psb_irq_handler(DRM_IRQ_ARGS)
+{
+ struct drm_device *dev = (struct drm_device *) arg;
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) dev->dev_private;
+
+ uint32_t vdc_stat, dsp_int = 0, sgx_int = 0, msvdx_int = 0, topaz_int = 0;
+ int handled = 0;
+ unsigned long irq_flags;
+
+#ifdef CONFIG_MDFD_GL3
+ uint32_t gl3_int = 0;
+#endif
+
+ /* PSB_DEBUG_ENTRY("\n"); */
+
+ spin_lock_irqsave(&dev_priv->irqmask_lock, irq_flags);
+
+ vdc_stat = PSB_RVDC32(PSB_INT_IDENTITY_R);
+
+ if (vdc_stat & _MDFLD_DISP_ALL_IRQ_FLAG) {
+ PSB_DEBUG_IRQ("Got DISP interrupt\n");
+ dsp_int = 1;
+ }
+
+ if (vdc_stat & _PSB_IRQ_SGX_FLAG) {
+ PSB_DEBUG_IRQ("Got SGX interrupt\n");
+ sgx_int = 1;
+ }
+ if (vdc_stat & _PSB_IRQ_MSVDX_FLAG) {
+ PSB_DEBUG_IRQ("Got MSVDX interrupt\n");
+ msvdx_int = 1;
+ }
+
+ if (vdc_stat & _LNC_IRQ_TOPAZ_FLAG) {
+ PSB_DEBUG_IRQ("Got TOPAX interrupt\n");
+ topaz_int = 1;
+ }
+
+#ifdef CONFIG_MDFD_GL3
+ if (vdc_stat & _MDFLD_GL3_IRQ_FLAG) {
+ PSB_DEBUG_IRQ("Got GL3 interrupt\n");
+ gl3_int = 1;
+ }
+#endif
+
+ vdc_stat &= dev_priv->vdc_irq_mask;
+ spin_unlock_irqrestore(&dev_priv->irqmask_lock, irq_flags);
+
+ if (dsp_int && ospm_power_is_hw_on(OSPM_DISPLAY_ISLAND)) {
+ psb_vdc_interrupt(dev, vdc_stat);
+ handled = 1;
+ }
+
+ if (msvdx_int) {
+ psb_msvdx_interrupt(dev);
+ handled = 1;
+ }
+
+ if (topaz_int) {
+ pnw_topaz_interrupt(dev);
+ handled = 1;
+ }
+
+ if (sgx_int) {
+ if (SYSPVRServiceSGXInterrupt(dev) != 0)
+ handled = 1;
+ }
+
+#ifdef CONFIG_MDFD_GL3
+ if (gl3_int) {
+ mdfld_gl3_interrupt(dev, vdc_stat);
+ handled = 1;
+ }
+#endif
+
+ PSB_WVDC32(vdc_stat, PSB_INT_IDENTITY_R);
+ (void) PSB_RVDC32(PSB_INT_IDENTITY_R);
+ DRM_READMEMORYBARRIER();
+
+ if (!handled)
+ return IRQ_NONE;
+
+ return IRQ_HANDLED;
+}
+
+void psb_irq_preinstall(struct drm_device *dev)
+{
+ psb_irq_preinstall_islands(dev, OSPM_ALL_ISLANDS);
+}
+
+/**
+ * FIXME: should I remove display irq enable here??
+ */
+void psb_irq_preinstall_islands(struct drm_device *dev, int hw_islands)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) dev->dev_private;
+ unsigned long irqflags;
+
+ PSB_DEBUG_ENTRY("\n");
+
+ spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
+
+ if (hw_islands & OSPM_DISPLAY_ISLAND) {
+ if (ospm_power_is_hw_on(OSPM_DISPLAY_ISLAND)) {
+ if (dev->vblank_enabled[0])
+ dev_priv->vdc_irq_mask |= _PSB_PIPEA_EVENT_FLAG;
+ if (dev->vblank_enabled[1])
+ dev_priv->vdc_irq_mask |= _MDFLD_PIPEB_EVENT_FLAG;
+ if (dev->vblank_enabled[2])
+ dev_priv->vdc_irq_mask |= _MDFLD_PIPEC_EVENT_FLAG;
+ }
+ }
+ if (hw_islands & OSPM_GRAPHICS_ISLAND) {
+ dev_priv->vdc_irq_mask |= _PSB_IRQ_SGX_FLAG;
+#ifdef CONFIG_MDFD_GL3
+ dev_priv->vdc_irq_mask |= _MDFLD_GL3_IRQ_FLAG;
+#endif
+ }
+
+ if (hw_islands & OSPM_VIDEO_DEC_ISLAND)
+ if (ospm_power_is_hw_on(OSPM_VIDEO_DEC_ISLAND))
+ dev_priv->vdc_irq_mask |= _PSB_IRQ_MSVDX_FLAG;
+
+ if (hw_islands & OSPM_VIDEO_ENC_ISLAND)
+ if (ospm_power_is_hw_on(OSPM_VIDEO_ENC_ISLAND))
+ dev_priv->vdc_irq_mask |= _LNC_IRQ_TOPAZ_FLAG;
+
+ /*This register is safe even if display island is off*/
+ PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
+
+ spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+}
+
+int psb_irq_postinstall(struct drm_device *dev)
+{
+ return psb_irq_postinstall_islands(dev, OSPM_ALL_ISLANDS);
+}
+
+int psb_irq_postinstall_islands(struct drm_device *dev, int hw_islands)
+{
+
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) dev->dev_private;
+ unsigned long irqflags;
+
+ PSB_DEBUG_ENTRY("\n");
+
+ spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
+
+ /*This register is safe even if display island is off*/
+ PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
+
+ if (hw_islands & OSPM_DISPLAY_ISLAND) {
+ if (true/*powermgmt_is_hw_on(dev->pdev, PSB_DISPLAY_ISLAND)*/) {
+ if (dev->vblank_enabled[0])
+ psb_enable_pipestat(dev_priv, 0,
+ PIPE_VBLANK_INTERRUPT_ENABLE);
+ else
+ psb_disable_pipestat(dev_priv, 0,
+ PIPE_VBLANK_INTERRUPT_ENABLE);
+
+ if (dev->vblank_enabled[1])
+ psb_enable_pipestat(dev_priv, 1,
+ PIPE_VBLANK_INTERRUPT_ENABLE);
+ else
+ psb_disable_pipestat(dev_priv, 1,
+ PIPE_VBLANK_INTERRUPT_ENABLE);
+
+ if (dev->vblank_enabled[2])
+ psb_enable_pipestat(dev_priv, 2,
+ PIPE_VBLANK_INTERRUPT_ENABLE);
+ else
+ psb_disable_pipestat(dev_priv, 2,
+ PIPE_VBLANK_INTERRUPT_ENABLE);
+ }
+ }
+
+ if (!dev_priv->topaz_disabled)
+ if (hw_islands & OSPM_VIDEO_ENC_ISLAND)
+ if (ospm_power_is_hw_on(OSPM_VIDEO_ENC_ISLAND))
+ pnw_topaz_enableirq(dev);
+
+ if (hw_islands & OSPM_VIDEO_DEC_ISLAND)
+ if (true/*powermgmt_is_hw_on(dev->pdev, PSB_VIDEO_DEC_ISLAND)*/)
+ psb_msvdx_enableirq(dev);
+
+ spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+
+ return 0;
+}
+
+void psb_irq_uninstall(struct drm_device *dev)
+{
+ psb_irq_uninstall_islands(dev, OSPM_ALL_ISLANDS);
+}
+
+void psb_irq_uninstall_islands(struct drm_device *dev, int hw_islands)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) dev->dev_private;
+ unsigned long irqflags;
+
+ PSB_DEBUG_ENTRY("\n");
+
+ spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
+
+ if (hw_islands & OSPM_DISPLAY_ISLAND) {
+ if (true/*powermgmt_is_hw_on(dev->pdev, PSB_DISPLAY_ISLAND)*/) {
+ if (dev->vblank_enabled[0])
+ psb_disable_pipestat(dev_priv, 0,
+ PIPE_VBLANK_INTERRUPT_ENABLE);
+
+ if (dev->vblank_enabled[1])
+ psb_disable_pipestat(dev_priv, 1,
+ PIPE_VBLANK_INTERRUPT_ENABLE);
+
+ if (dev->vblank_enabled[2])
+ psb_disable_pipestat(dev_priv, 2,
+ PIPE_VBLANK_INTERRUPT_ENABLE);
+ }
+ dev_priv->vdc_irq_mask &= _PSB_IRQ_SGX_FLAG |
+ _PSB_IRQ_MSVDX_FLAG |
+ _LNC_IRQ_TOPAZ_FLAG;
+#ifdef CONFIG_MDFD_GL3
+ dev_priv->vdc_irq_mask &= _MDFLD_GL3_IRQ_FLAG;
+#endif
+ }
+ /*TODO: remove follwoing code*/
+ if (hw_islands & OSPM_GRAPHICS_ISLAND) {
+ dev_priv->vdc_irq_mask &= ~_PSB_IRQ_SGX_FLAG;
+#ifdef CONFIG_MDFD_GL3
+ dev_priv->vdc_irq_mask &= ~_MDFLD_GL3_IRQ_FLAG;
+#endif
+ }
+
+ if (hw_islands & OSPM_VIDEO_DEC_ISLAND)
+ dev_priv->vdc_irq_mask &= ~_PSB_IRQ_MSVDX_FLAG;
+
+ if (hw_islands & OSPM_VIDEO_ENC_ISLAND)
+ dev_priv->vdc_irq_mask &= ~_LNC_IRQ_TOPAZ_FLAG;
+
+ /*These two registers are safe even if display island is off*/
+ PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
+ PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
+
+ wmb();
+
+ /*This register is safe even if display island is off*/
+ PSB_WVDC32(PSB_RVDC32(PSB_INT_IDENTITY_R), PSB_INT_IDENTITY_R);
+
+ if (!dev_priv->topaz_disabled)
+ if (hw_islands & OSPM_VIDEO_ENC_ISLAND)
+ if (ospm_power_is_hw_on(OSPM_VIDEO_ENC_ISLAND))
+ pnw_topaz_disableirq(dev);
+ if (hw_islands & OSPM_VIDEO_DEC_ISLAND)
+ if (ospm_power_is_hw_on(OSPM_VIDEO_DEC_ISLAND))
+ psb_msvdx_disableirq(dev);
+
+ spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+}
+
+void psb_irq_turn_on_dpst(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) dev->dev_private;
+ u32 hist_reg;
+ u32 pwm_reg;
+
+ if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_ONLY_IF_ON)) {
+ PSB_WVDC32(BIT(31), HISTOGRAM_LOGIC_CONTROL);
+ hist_reg = PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL);
+ PSB_WVDC32(BIT(31), HISTOGRAM_INT_CONTROL);
+ hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
+
+ PSB_WVDC32(0x80010100, PWM_CONTROL_LOGIC);
+ pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
+ PSB_WVDC32(pwm_reg | PWM_PHASEIN_ENABLE | PWM_PHASEIN_INT_ENABLE,
+ PWM_CONTROL_LOGIC);
+ pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
+
+ psb_enable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE);
+
+ hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
+ PSB_WVDC32(hist_reg | HISTOGRAM_INT_CTRL_CLEAR, HISTOGRAM_INT_CONTROL);
+ pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
+ PSB_WVDC32(pwm_reg | 0x80010100 | PWM_PHASEIN_ENABLE, PWM_CONTROL_LOGIC);
+
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+ }
+}
+
+int psb_irq_enable_dpst(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) dev->dev_private;
+ unsigned long irqflags;
+
+ PSB_DEBUG_ENTRY("\n");
+
+ spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
+
+ /* enable DPST */
+ mid_enable_pipe_event(dev_priv, 0);
+ psb_irq_turn_on_dpst(dev);
+
+ spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+ return 0;
+}
+
+void psb_irq_turn_off_dpst(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) dev->dev_private;
+ u32 hist_reg;
+ u32 pwm_reg;
+
+ if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_ONLY_IF_ON)) {
+ PSB_WVDC32(0x00000000, HISTOGRAM_INT_CONTROL);
+ hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
+
+ psb_disable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE);
+
+ pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
+ PSB_WVDC32(pwm_reg & !(PWM_PHASEIN_INT_ENABLE), PWM_CONTROL_LOGIC);
+ pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
+
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+ }
+}
+
+int psb_irq_disable_dpst(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) dev->dev_private;
+ unsigned long irqflags;
+
+ PSB_DEBUG_ENTRY("\n");
+
+ spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
+
+ mid_disable_pipe_event(dev_priv, 0);
+ psb_irq_turn_off_dpst(dev);
+
+ spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+
+ return 0;
+}
+
+#ifdef PSB_FIXME
+static int psb_vblank_do_wait(struct drm_device *dev,
+ unsigned int *sequence, atomic_t *counter)
+{
+ unsigned int cur_vblank;
+ int ret = 0;
+ DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
+ (((cur_vblank = atomic_read(counter))
+ - *sequence) <= (1 << 23)));
+ *sequence = cur_vblank;
+
+ return ret;
+}
+#endif
+
+/*
+ * It is used to enable VBLANK interrupt
+ */
+int psb_enable_vblank(struct drm_device *dev, int pipe)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) dev->dev_private;
+ unsigned long irqflags;
+ uint32_t reg_val = 0;
+ uint32_t pipeconf_reg = mid_pipeconf(pipe);
+
+ PSB_DEBUG_ENTRY("\n");
+
+ if (!is_panel_vid_or_cmd(dev))
+ return mdfld_enable_te(dev, pipe);
+
+ if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_ONLY_IF_ON)) {
+ reg_val = REG_READ(pipeconf_reg);
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+ }
+
+ if (!(reg_val & PIPEACONF_ENABLE))
+ return -EINVAL;
+
+ spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
+
+ drm_psb_disable_vsync = 0;
+ mid_enable_pipe_event(dev_priv, pipe);
+ psb_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE);
+
+ spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+
+ return 0;
+}
+
+/*
+ * It is used to disable VBLANK interrupt
+ */
+void psb_disable_vblank(struct drm_device *dev, int pipe)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) dev->dev_private;
+ unsigned long irqflags;
+
+ PSB_DEBUG_ENTRY("\n");
+
+ if (!is_panel_vid_or_cmd(dev))
+ mdfld_disable_te(dev, pipe);
+
+ spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
+
+ drm_psb_disable_vsync = 1;
+ mid_disable_pipe_event(dev_priv, pipe);
+ psb_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE);
+
+ spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+}
+
+/* Called from drm generic code, passed a 'crtc', which
+ * we use as a pipe index
+ */
+u32 psb_get_vblank_counter(struct drm_device *dev, int pipe)
+{
+ uint32_t high_frame = PIPEAFRAMEHIGH;
+ uint32_t low_frame = PIPEAFRAMEPIXEL;
+ uint32_t pipeconf_reg = PIPEACONF;
+ uint32_t reg_val = 0;
+ uint32_t high1 = 0, high2 = 0, low = 0, count = 0;
+
+ switch (pipe) {
+ case 0:
+ break;
+ case 1:
+ high_frame = PIPEBFRAMEHIGH;
+ low_frame = PIPEBFRAMEPIXEL;
+ pipeconf_reg = PIPEBCONF;
+ break;
+ case 2:
+ high_frame = PIPECFRAMEHIGH;
+ low_frame = PIPECFRAMEPIXEL;
+ pipeconf_reg = PIPECCONF;
+ break;
+ default:
+ DRM_ERROR("%s, invalded pipe. \n", __FUNCTION__);
+ return 0;
+ }
+
+ if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, false))
+ return 0;
+
+ reg_val = REG_READ(pipeconf_reg);
+
+ if (!(reg_val & PIPEACONF_ENABLE)) {
+ DRM_ERROR("trying to get vblank count for disabled pipe %d\n", pipe);
+ goto psb_get_vblank_counter_exit;
+ }
+
+ /*
+ * High & low register fields aren't synchronized, so make sure
+ * we get a low value that's stable across two reads of the high
+ * register.
+ */
+ do {
+ high1 = ((REG_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
+ PIPE_FRAME_HIGH_SHIFT);
+ low = ((REG_READ(low_frame) & PIPE_FRAME_LOW_MASK) >>
+ PIPE_FRAME_LOW_SHIFT);
+ high2 = ((REG_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
+ PIPE_FRAME_HIGH_SHIFT);
+ } while (high1 != high2);
+
+ count = (high1 << 8) | low;
+
+psb_get_vblank_counter_exit:
+
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+
+ return count;
+}
+
+/*
+ * It is used to enable TE interrupt
+ */
+int mdfld_enable_te(struct drm_device *dev, int pipe)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) dev->dev_private;
+ unsigned long irqflags;
+ uint32_t reg_val = 0;
+ uint32_t pipeconf_reg = mid_pipeconf(pipe);
+
+ PSB_DEBUG_ENTRY("pipe = %d, \n", pipe);
+
+ if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_ONLY_IF_ON)) {
+ reg_val = REG_READ(pipeconf_reg);
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+ }
+
+ if (!(reg_val & PIPEACONF_ENABLE))
+ return -EINVAL;
+
+ spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
+
+ mid_enable_pipe_event(dev_priv, pipe);
+ psb_enable_pipestat(dev_priv, pipe, PIPE_TE_ENABLE);
+
+ spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+
+ return 0;
+}
+
+/*
+ * It is used to disable TE interrupt
+ */
+void mdfld_disable_te(struct drm_device *dev, int pipe)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) dev->dev_private;
+ unsigned long irqflags;
+
+ PSB_DEBUG_ENTRY("\n");
+
+ if (!dev_priv->b_dsr_enable)
+ return;
+
+ spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
+
+ mid_disable_pipe_event(dev_priv, pipe);
+ psb_disable_pipestat(dev_priv, pipe, PIPE_TE_ENABLE);
+
+ spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+}
+
+int mdfld_irq_enable_hdmi_audio(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) dev->dev_private;
+ unsigned long irqflags;
+ u32 reg_val = 0, mask = 0;
+
+ if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_ONLY_IF_ON)) {
+ reg_val = REG_READ(PIPEBCONF);
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+ }
+
+ if (!(reg_val & PIPEACONF_ENABLE))
+ return -EINVAL;
+
+ spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
+
+ /* enable HDMI audio interrupt*/
+ mid_enable_pipe_event(dev_priv, 1);
+ dev_priv->pipestat[1] &= ~PIPE_HDMI_AUDIO_INT_MASK;
+ mask = dev_priv->hdmi_audio_interrupt_mask;
+ psb_enable_pipestat(dev_priv, 1, mask);
+
+ spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+ return 0;
+}
+
+int mdfld_irq_disable_hdmi_audio(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) dev->dev_private;
+ unsigned long irqflags;
+
+ spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
+
+ mid_disable_pipe_event(dev_priv, 1);
+ psb_disable_pipestat(dev_priv, 1, PIPE_HDMI_AUDIO_INT_MASK);
+
+ spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+ return 0;
+}
--- /dev/null
+/**************************************************************************
+ * Copyright (c) 2009, Intel Corporation.
+ * 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 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.
+ *
+ * Authors:
+ * Benjamin Defnet <benjamin.r.defnet@intel.com>
+ * Rajesh Poornachandran <rajesh.poornachandran@intel.com>
+ *
+ **************************************************************************/
+
+#ifndef _PSB_IRQ_H_
+#define _PSB_IRQ_H_
+
+#include <drm/drmP.h>
+#include "psb_drv.h"
+
+void psb_irq_preinstall(struct drm_device *dev);
+int psb_irq_postinstall(struct drm_device *dev);
+void psb_irq_uninstall(struct drm_device *dev);
+irqreturn_t psb_irq_handler(DRM_IRQ_ARGS);
+
+void psb_irq_preinstall_islands(struct drm_device *dev, int hw_islands);
+int psb_irq_postinstall_islands(struct drm_device *dev, int hw_islands);
+void psb_irq_uninstall_islands(struct drm_device *dev, int hw_islands);
+
+int psb_irq_enable_dpst(struct drm_device *dev);
+int psb_irq_disable_dpst(struct drm_device *dev);
+void psb_irq_turn_on_dpst(struct drm_device *dev);
+void psb_irq_turn_off_dpst(struct drm_device *dev);
+int psb_enable_vblank(struct drm_device *dev, int pipe);
+void psb_disable_vblank(struct drm_device *dev, int pipe);
+u32 psb_get_vblank_counter(struct drm_device *dev, int pipe);
+
+void psb_enable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask);
+void psb_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask);
+
+int mdfld_enable_te(struct drm_device *dev, int pipe);
+void mdfld_disable_te(struct drm_device *dev, int pipe);
+int mdfld_irq_enable_hdmi_audio(struct drm_device *dev);
+int mdfld_irq_disable_hdmi_audio(struct drm_device *dev);
+void psb_te_timer_func(unsigned long data);
+void mdfld_te_handler_work(struct work_struct *te_work);
+
+#endif /* _PSB_IRQ_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2011, Intel Corporation.
+ *
+ * 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 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.
+ *
+ * Authors:
+ * Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
+ * Pauli Nieminen <pauli.nieminen@intel.com>
+ *
+ */
+
+#include <linux/spinlock.h>
+#include <linux/list.h>
+
+#include <drm/drmP.h>
+#include "psb_fb.h"
+#include "psb_intel_reg.h"
+#include "psb_page_flip.h"
+#include "psb_pvr_glue.h"
+
+#include "mdfld_output.h"
+#include "mdfld_dsi_output.h"
+
+#if defined(CONFIG_MDFLD_DUAL_DSI_DPU)
+#include "mdfld_dsi_dbi_dpu.h"
+#elif defined(CONFIG_MDFLD_DSI_DSR)
+#include "mdfld_dsi_dbi.h"
+#endif
+
+struct pending_flip {
+ struct drm_crtc *crtc;
+ struct drm_pending_vblank_event *event;
+ PVRSRV_KERNEL_MEM_INFO *old_mem_info;
+ uint32_t offset;
+};
+
+static void
+send_page_flip_event(struct drm_device *dev, int pipe,
+ struct pending_flip *pending_flip)
+{
+ struct drm_pending_vblank_event *e;
+ struct timeval now;
+ struct drm_file *file_priv;
+ unsigned long flags;
+
+ spin_lock_irqsave(&dev->event_lock, flags);
+
+ if (pending_flip->event) {
+ file_priv = e->base.file_priv;
+ e = pending_flip->event;
+ do_gettimeofday(&now);
+ e->event.sequence = drm_vblank_count(dev, pipe);
+ e->event.tv_sec = now.tv_sec;
+ e->event.tv_usec = now.tv_usec;
+ list_add_tail(&e->base.link,
+ &e->base.file_priv->event_list);
+ wake_up_interruptible(&e->base.file_priv->event_wait);
+ }
+
+ spin_unlock_irqrestore(&dev->event_lock, flags);
+}
+
+static void
+write_scanout_regs(struct pending_flip *pending_flip, uint32_t offset)
+{
+ struct drm_device *dev = pending_flip->crtc->dev;
+ struct psb_intel_crtc *psb_intel_crtc =
+ to_psb_intel_crtc(pending_flip->crtc);
+
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) dev->dev_private;
+ int reg_offset;
+
+ switch (psb_intel_crtc->pipe) {
+ case 0:
+ reg_offset = DSPASURF;
+ break;
+ case 1:
+ reg_offset = DSPBSURF;
+ break;
+ case 2:
+ reg_offset = DSPCSURF;
+ break;
+ }
+
+ if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
+ OSPM_UHB_FORCE_POWER_ON))
+ return;
+
+ iowrite32(offset, dev_priv->vdc_reg + reg_offset);
+
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+}
+
+static void
+increase_read_ops_pending(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+ psKernelMemInfo->psKernelSyncInfo->psSyncData->ui32ReadOpsPending++;
+}
+
+static void
+increase_read_ops_completed(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+ psKernelMemInfo->psKernelSyncInfo->psSyncData->ui32ReadOpsComplete++;
+}
+
+static PVRSRV_KERNEL_MEM_INFO *
+get_fb_meminfo(struct drm_framebuffer *fb)
+{
+ struct psb_framebuffer *psbfb = to_psb_fb(fb);
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+ if (psb_get_meminfo_by_handle(psbfb->hKernelMemInfo, &psKernelMemInfo))
+ return NULL;
+
+ return psKernelMemInfo;
+}
+
+static void
+psb_intel_flip_complete(struct pending_flip *pending_flip)
+{
+ if (pending_flip) {
+ struct drm_crtc *crtc = pending_flip->crtc;
+ struct drm_device *dev = crtc->dev;
+ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+ int pipe = psb_intel_crtc->pipe;
+
+ send_page_flip_event(dev, pipe, pending_flip);
+ drm_vblank_put(dev, pipe);
+ increase_read_ops_completed(pending_flip->old_mem_info);
+ PVRSRVScheduleDeviceCallbacks();
+
+ kfree(pending_flip);
+ }
+}
+
+void
+psb_intel_crtc_process_vblank(struct drm_crtc *crtc)
+{
+ struct pending_flip *pending_flip = NULL;
+ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+
+ pending_flip = xchg(&psb_intel_crtc->pending_flip, NULL);
+
+ psb_intel_flip_complete(pending_flip);
+}
+
+static void
+sync_callback(void *data)
+{
+ struct pending_flip *pending_flip = data;
+
+ struct drm_crtc* crtc = pending_flip->crtc;
+ struct drm_device *dev = crtc->dev;
+ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+
+ write_scanout_regs(pending_flip, pending_flip->offset);
+
+ pending_flip = xchg(&psb_intel_crtc->pending_flip, pending_flip);
+
+ drm_vblank_get(dev, psb_intel_crtc->pipe);
+
+ psb_intel_flip_complete(pending_flip);
+}
+
+int
+psb_intel_crtc_page_flip(struct drm_crtc *crtc,
+ struct drm_framebuffer *fb,
+ struct drm_pending_vblank_event *event)
+{
+ struct psb_framebuffer *psbfb = to_psb_fb(fb);
+ PVRSRV_KERNEL_MEM_INFO *new_fb_mem_info, *current_fb_mem_info;
+ struct pending_flip *new_pending_flip;
+ int ret;
+
+ if (psb_get_meminfo_by_handle(psbfb->hKernelMemInfo, &new_fb_mem_info))
+ return -EINVAL;
+
+ new_pending_flip = kmalloc(sizeof *new_pending_flip, GFP_KERNEL);
+ if (!new_pending_flip)
+ return -ENOMEM;
+
+ new_pending_flip->crtc = crtc;
+ new_pending_flip->event = event;
+ new_pending_flip->offset = psbfb->offset;
+
+ current_fb_mem_info = get_fb_meminfo(crtc->fb);
+
+ crtc->fb = fb;
+
+ BUG_ON(!current_fb_mem_info);
+ new_pending_flip->old_mem_info = current_fb_mem_info;
+
+ increase_read_ops_pending(current_fb_mem_info);
+
+ ret = PVRSRVCallbackOnSync(new_fb_mem_info->psKernelSyncInfo,
+ PVRSRV_SYNC_WRITE, sync_callback,
+ new_pending_flip);
+ if (ret < 0)
+ kfree(new_pending_flip);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Copyright (c) 2011, Intel Corporation.
+ *
+ * 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 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.
+ *
+ * Authors:
+ * Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
+ *
+ */
+
+#ifndef _PSB_PAGE_FLIP_H_
+#define _PSB_PAGE_FLIP_H_
+
+void psb_intel_crtc_process_vblank(struct drm_crtc *crtc);
+int psb_intel_crtc_page_flip(struct drm_crtc *crtc,
+ struct drm_framebuffer *fb,
+ struct drm_pending_vblank_event *event);
+
+#endif /* _PSB_PAGE_FLIP_H_ */
--- /dev/null
+/**************************************************************************
+ * Copyright (c) 2009, Intel Corporation.
+ * All Rights Reserved.
+
+ * 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 (including the next
+ * paragraph) 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.
+ *
+ * Authors:
+ * Benjamin Defnet <benjamin.r.defnet@intel.com>
+ * Rajesh Poornachandran <rajesh.poornachandran@intel.com>
+ *
+ */
+#include "psb_powermgmt.h"
+#include "psb_drv.h"
+#include "psb_intel_reg.h"
+#include "psb_msvdx.h"
+#include "pnw_topaz.h"
+#include <linux/mutex.h>
+#include "mdfld_dsi_dbi.h"
+#include "mdfld_dsi_dbi_dpu.h"
+#include <asm/intel_scu_ipc.h>
+
+#undef OSPM_GFX_DPK
+
+extern IMG_UINT32 gui32SGXDeviceID;
+extern IMG_UINT32 gui32MRSTDisplayDeviceID;
+extern IMG_UINT32 gui32MRSTMSVDXDeviceID;
+extern IMG_UINT32 gui32MRSTTOPAZDeviceID;
+
+struct drm_device *gpDrmDevice = NULL;
+static struct mutex g_ospm_mutex;
+static bool gbSuspendInProgress = false;
+static bool gbResumeInProgress = false;
+static int g_hw_power_status_mask;
+static atomic_t g_display_access_count;
+static atomic_t g_graphics_access_count;
+static atomic_t g_videoenc_access_count;
+static atomic_t g_videodec_access_count;
+
+void ospm_power_island_up(int hw_islands);
+void ospm_power_island_down(int hw_islands);
+static bool gbSuspended = false;
+bool gbgfxsuspended = false;
+bool gbdispstatus = true;
+
+
+#ifdef CONFIG_PM_RUNTIME
+int enable_gfx_rtpm = 0;
+
+void psb_runtimepm_wq_handler(struct work_struct *work)
+{
+ struct drm_psb_private * dev_priv = gpDrmDevice->dev_private;
+
+ if(drm_psb_ospm && !enable_gfx_rtpm) {
+ printk(KERN_ALERT "Enable GFX runtime_pm \n");
+
+ dev_priv->rpm_enabled = 1;
+
+ enable_gfx_rtpm = 1;
+
+ pm_runtime_enable(&gpDrmDevice->pdev->dev);
+ pm_runtime_set_active(&gpDrmDevice->pdev->dev);
+
+ pm_runtime_allow(&gpDrmDevice->pdev->dev);
+ }
+}
+#endif
+
+
+#if 1
+static int ospm_runtime_check_msvdx_hw_busy(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+ int ret = 1;
+
+ if (!ospm_power_is_hw_on(OSPM_VIDEO_DEC_ISLAND)) {
+ //printk(KERN_ALERT "%s VIDEO DEC HW is not on\n", __func__);
+ ret = -1;
+ goto out;
+ }
+
+ msvdx_priv->msvdx_hw_busy = REG_READ(0x20D0) & (0x1 << 9);
+ if (psb_check_msvdx_idle(dev)) {
+ //printk(KERN_ALERT "%s video decode hw busy\n", __func__);
+ ret = 1;
+ } else {
+ //printk(KERN_ALERT "%s video decode hw idle\n", __func__);
+ ret = 0;
+ }
+out:
+ return ret;
+}
+
+static int ospm_runtime_check_topaz_hw_busy(struct drm_device *dev)
+{
+ //struct drm_psb_private *dev_priv = dev->dev_private;
+ //struct topaz_private *topaz_priv = dev_priv->topaz_private;
+ int ret = 1;
+
+ if (!ospm_power_is_hw_on(OSPM_VIDEO_ENC_ISLAND)) {
+ //printk(KERN_ALERT "%s VIDEO ENC HW is not on\n", __func__);
+ ret = -1;
+ goto out;
+ }
+
+ //topaz_priv->topaz_hw_busy = REG_READ(0x20D0) & (0x1 << 11);
+
+ if (pnw_check_topaz_idle(dev)) {
+ //printk(KERN_ALERT "%s video encode hw busy %d\n", __func__,
+ // topaz_priv->topaz_hw_busy);
+ ret = 1;
+ } else {
+ //printk(KERN_ALERT "%s video encode hw idle\n", __func__);
+ ret = 0;
+ }
+out:
+ return ret;
+}
+
+static int ospm_runtime_pm_msvdx_suspend(struct drm_device *dev)
+{
+ int ret = 0;
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+
+ //printk(KERN_ALERT "enter %s\n", __func__);
+
+ if (!ospm_power_is_hw_on(OSPM_VIDEO_DEC_ISLAND)) {
+ //printk(KERN_ALERT "%s VIDEO DEC HW is not on\n", __func__);
+ goto out;
+ }
+
+ if (atomic_read(&g_videodec_access_count)) {
+ //printk(KERN_ALERT "%s videodec access count exit\n", __func__);
+ ret = -1;
+ goto out;
+ }
+
+ msvdx_priv->msvdx_hw_busy = REG_READ(0x20D0) & (0x1 << 9);
+ if (psb_check_msvdx_idle(dev)) {
+ //printk(KERN_ALERT "%s video decode hw busy exit\n", __func__);
+ ret = -2;
+ goto out;
+ }
+
+ MSVDX_NEW_PMSTATE(dev, msvdx_priv, PSB_PMSTATE_POWERDOWN);
+ psb_irq_uninstall_islands(gpDrmDevice, OSPM_VIDEO_DEC_ISLAND);
+ psb_msvdx_save_context(dev);
+ ospm_power_island_down(OSPM_VIDEO_DEC_ISLAND);
+ //printk(KERN_ALERT "%s done\n", __func__);
+out:
+ return ret;
+}
+
+static int ospm_runtime_pm_msvdx_resume(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+
+ //printk(KERN_ALERT "ospm_runtime_pm_msvdx_resume\n");
+
+ MSVDX_NEW_PMSTATE(dev, msvdx_priv, PSB_PMSTATE_POWERUP);
+
+ psb_msvdx_restore_context(dev);
+
+ return 0;
+}
+
+static int ospm_runtime_pm_topaz_suspend(struct drm_device *dev)
+{
+ int ret = 0;
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct pnw_topaz_private *pnw_topaz_priv = dev_priv->topaz_private;
+ struct psb_video_ctx *pos, *n;
+ int encode_ctx = 0, encode_running = 0;
+
+ //printk(KERN_ALERT "enter %s\n", __func__);
+ list_for_each_entry_safe(pos, n, &dev_priv->video_ctx, head) {
+ int entrypoint = pos->ctx_type & 0xff;
+ if (entrypoint == VAEntrypointEncSlice ||
+ entrypoint == VAEntrypointEncPicture) {
+ encode_ctx = 1;
+ break;
+ }
+ }
+
+ /* have encode context, but not started, or is just closed */
+ if (encode_ctx && dev_priv->topaz_ctx)
+ encode_running = 1;
+
+ if (encode_ctx)
+ PSB_DEBUG_PM("Topaz: has encode context, running=%d\n",
+ encode_running);
+ else
+ PSB_DEBUG_PM("Topaz: no encode context\n");
+
+ if (!ospm_power_is_hw_on(OSPM_VIDEO_ENC_ISLAND)) {
+ //printk(KERN_ALERT "%s VIDEO ENC HW is not on\n", __func__);
+ goto out;
+ }
+
+ if (atomic_read(&g_videoenc_access_count)) {
+ //printk(KERN_ALERT "%s videoenc access count exit\n", __func__);
+ ret = -1;
+ goto out;
+ }
+
+ if (pnw_check_topaz_idle(dev)) {
+ //printk(KERN_ALERT "%s video encode hw busy exit\n", __func__);
+ ret = -2;
+ goto out;
+ }
+
+ psb_irq_uninstall_islands(gpDrmDevice, OSPM_VIDEO_ENC_ISLAND);
+
+ if (encode_running) /* has encode session running */
+ pnw_topaz_save_mtx_state(gpDrmDevice);
+ PNW_TOPAZ_NEW_PMSTATE(dev, pnw_topaz_priv, PSB_PMSTATE_POWERDOWN);
+
+ ospm_power_island_down(OSPM_VIDEO_ENC_ISLAND);
+ //printk(KERN_ALERT "%s done\n", __func__);
+out:
+ return ret;
+}
+
+static int ospm_runtime_pm_topaz_resume(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct pnw_topaz_private *pnw_topaz_priv = dev_priv->topaz_private;
+ struct psb_video_ctx *pos, *n;
+ int encode_ctx = 0, encode_running = 0;
+
+ //printk(KERN_ALERT "ospm_runtime_pm_topaz_resume\n");
+ list_for_each_entry_safe(pos, n, &dev_priv->video_ctx, head) {
+ int entrypoint = pos->ctx_type & 0xff;
+ if (entrypoint == VAEntrypointEncSlice ||
+ entrypoint == VAEntrypointEncPicture) {
+ encode_ctx = 1;
+ break;
+ }
+ }
+
+ /* have encode context, but not started, or is just closed */
+ if (encode_ctx && dev_priv->topaz_ctx)
+ encode_running = 1;
+
+ if (encode_ctx)
+ PSB_DEBUG_PM("Topaz: has encode context, running=%d\n",
+ encode_running);
+ else
+ PSB_DEBUG_PM("Topaz: no encode running\n");
+
+ if (encode_running) { /* has encode session running */
+ psb_irq_uninstall_islands(gpDrmDevice, OSPM_VIDEO_ENC_ISLAND);
+ pnw_topaz_restore_mtx_state(gpDrmDevice);
+ }
+ PNW_TOPAZ_NEW_PMSTATE(dev, pnw_topaz_priv, PSB_PMSTATE_POWERUP);
+
+ return 0;
+}
+#endif
+
+#ifdef FIX_OSPM_POWER_DOWN
+void ospm_apm_power_down_msvdx(struct drm_device *dev)
+{
+ return;
+ mutex_lock(&g_ospm_mutex);
+
+ if (atomic_read(&g_videodec_access_count))
+ goto out;
+ if (psb_check_msvdx_idle(dev))
+ goto out;
+
+ gbSuspendInProgress = true;
+ psb_msvdx_save_context(dev);
+#ifdef FIXME_MRST_VIDEO_DEC
+ ospm_power_island_down(OSPM_VIDEO_DEC_ISLAND);
+#endif
+ gbSuspendInProgress = false;
+out:
+ mutex_unlock(&g_ospm_mutex);
+ return;
+}
+
+void ospm_apm_power_down_topaz(struct drm_device *dev)
+{
+ return; /* todo for OSPM */
+
+ mutex_lock(&g_ospm_mutex);
+
+ if (atomic_read(&g_videoenc_access_count))
+ goto out;
+ if (lnc_check_topaz_idle(dev))
+ goto out;
+
+ gbSuspendInProgress = true;
+ lnc_topaz_save_mtx_state(dev);
+ ospm_power_island_down(OSPM_VIDEO_ENC_ISLAND);
+ gbSuspendInProgress = false;
+out:
+ mutex_unlock(&g_ospm_mutex);
+ return;
+}
+#else
+void ospm_apm_power_down_msvdx(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+
+ mutex_lock(&g_ospm_mutex);
+ if (!ospm_power_is_hw_on(OSPM_VIDEO_DEC_ISLAND))
+ goto out;
+
+ if (atomic_read(&g_videodec_access_count))
+ goto out;
+ if (psb_check_msvdx_idle(dev))
+ goto out;
+
+ gbSuspendInProgress = true;
+ psb_msvdx_save_context(dev);
+ ospm_power_island_down(OSPM_VIDEO_DEC_ISLAND);
+ gbSuspendInProgress = false;
+ MSVDX_NEW_PMSTATE(dev, msvdx_priv, PSB_PMSTATE_POWERDOWN);
+out:
+ mutex_unlock(&g_ospm_mutex);
+ return;
+}
+
+void ospm_apm_power_down_topaz(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct pnw_topaz_private *pnw_topaz_priv = dev_priv->topaz_private;
+
+ mutex_lock(&g_ospm_mutex);
+
+ if (!ospm_power_is_hw_on(OSPM_VIDEO_ENC_ISLAND))
+ goto out;
+ if (atomic_read(&g_videoenc_access_count))
+ goto out;
+ if (pnw_check_topaz_idle(dev))
+ goto out;
+
+ gbSuspendInProgress = true;
+ psb_irq_uninstall_islands(dev, OSPM_VIDEO_ENC_ISLAND);
+ pnw_topaz_save_mtx_state(gpDrmDevice);
+ PNW_TOPAZ_NEW_PMSTATE(dev, pnw_topaz_priv, PSB_PMSTATE_POWERDOWN);
+
+ ospm_power_island_down(OSPM_VIDEO_ENC_ISLAND);
+ gbSuspendInProgress = false;
+out:
+ mutex_unlock(&g_ospm_mutex);
+ return;
+}
+#endif
+/*
+ * ospm_power_init
+ *
+ * Description: Initialize this ospm power management module
+ */
+void ospm_power_init(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = (struct drm_psb_private *)dev->dev_private;
+
+ gpDrmDevice = dev;
+
+ dev_priv->apm_reg = MDFLD_MSG_READ32(PSB_PUNIT_PORT, PSB_APMBA);
+ dev_priv->ospm_base = MDFLD_MSG_READ32(PSB_PUNIT_PORT, PSB_OSPMBA);
+
+ dev_priv->apm_base = dev_priv->apm_reg & 0xffff;
+ dev_priv->ospm_base &= 0xffff;
+
+ mutex_init(&g_ospm_mutex);
+ g_hw_power_status_mask = OSPM_ALL_ISLANDS;
+ atomic_set(&g_display_access_count, 0);
+ atomic_set(&g_graphics_access_count, 0);
+ atomic_set(&g_videoenc_access_count, 0);
+ atomic_set(&g_videodec_access_count, 0);
+
+#ifdef OSPM_STAT
+ dev_priv->graphics_state = PSB_PWR_STATE_ON;
+ dev_priv->gfx_last_mode_change = jiffies;
+ dev_priv->gfx_on_time = 0;
+ dev_priv->gfx_off_time = 0;
+#endif
+
+ spin_lock_init(&dev_priv->ospm_lock);
+
+#ifdef CONFIG_PM_RUNTIME
+ INIT_DELAYED_WORK(&dev_priv->rtpm_work, psb_runtimepm_wq_handler);
+#endif
+
+ return;
+}
+
+/*
+ * ospm_power_uninit
+ *
+ * Description: Uninitialize this ospm power management module
+ */
+void ospm_power_uninit(void)
+{
+ mutex_destroy(&g_ospm_mutex);
+ pm_runtime_forbid(&gpDrmDevice->pdev->dev);
+ pm_runtime_get_noresume(&gpDrmDevice->pdev->dev);
+}
+
+
+/*
+ * save_display_registers
+ *
+ * Description: We are going to suspend so save current display
+ * register state.
+ */
+static int save_display_registers(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_crtc * crtc;
+ struct drm_connector * connector;
+
+ /* Display arbitration control + watermarks */
+ dev_priv->saveDSPARB = PSB_RVDC32(DSPARB);
+ dev_priv->saveDSPFW1 = PSB_RVDC32(DSPFW1);
+ dev_priv->saveDSPFW2 = PSB_RVDC32(DSPFW2);
+ dev_priv->saveDSPFW3 = PSB_RVDC32(DSPFW3);
+ dev_priv->saveDSPFW4 = PSB_RVDC32(DSPFW4);
+ dev_priv->saveDSPFW5 = PSB_RVDC32(DSPFW5);
+ dev_priv->saveDSPFW6 = PSB_RVDC32(DSPFW6);
+ dev_priv->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT);
+
+ /*save crtc and output state*/
+ mutex_lock(&dev->mode_config.mutex);
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ if (drm_helper_crtc_in_use(crtc)) {
+ crtc->funcs->save(crtc);
+ }
+ }
+
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+ connector->funcs->save(connector);
+ }
+ mutex_unlock(&dev->mode_config.mutex);
+
+ /* Interrupt state */
+ /*
+ * Handled in psb_irq.c
+ */
+
+ return 0;
+}
+
+/*
+ * restore_display_registers
+ *
+ * Description: We are going to resume so restore display register state.
+ */
+static int restore_display_registers(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_crtc * crtc;
+ struct drm_connector * connector;
+
+ /* Display arbitration + watermarks */
+ PSB_WVDC32(dev_priv->saveDSPARB, DSPARB);
+ PSB_WVDC32(dev_priv->saveDSPFW1, DSPFW1);
+ PSB_WVDC32(dev_priv->saveDSPFW2, DSPFW2);
+ PSB_WVDC32(dev_priv->saveDSPFW3, DSPFW3);
+ PSB_WVDC32(dev_priv->saveDSPFW4, DSPFW4);
+ PSB_WVDC32(dev_priv->saveDSPFW5, DSPFW5);
+ PSB_WVDC32(dev_priv->saveDSPFW6, DSPFW6);
+ PSB_WVDC32(dev_priv->saveCHICKENBIT, DSPCHICKENBIT);
+
+ /*make sure VGA plane is off. it initializes to on after reset!*/
+ PSB_WVDC32(0x80000000, VGACNTRL);
+
+ mutex_lock(&dev->mode_config.mutex);
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ if (drm_helper_crtc_in_use(crtc))
+ crtc->funcs->restore(crtc);
+ }
+
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+ connector->funcs->restore(connector);
+ }
+ mutex_unlock(&dev->mode_config.mutex);
+
+ /*Interrupt state*/
+ /*
+ * Handled in psb_irq.c
+ */
+
+ return 0;
+}
+/*
+ * mdfld_save_display_registers
+ *
+ * Description: We are going to suspend so save current display
+ * register state.
+ *
+ * Notes: FIXME_JLIU7 need to add the support for DPI MIPI & HDMI audio
+ */
+static int mdfld_save_display_registers(struct drm_device *dev, int pipe)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ int i;
+
+ /* regester */
+ u32 dpll_reg = MRST_DPLL_A;
+ u32 fp_reg = MRST_FPA0;
+ u32 pipeconf_reg = PIPEACONF;
+ u32 htot_reg = HTOTAL_A;
+ u32 hblank_reg = HBLANK_A;
+ u32 hsync_reg = HSYNC_A;
+ u32 vtot_reg = VTOTAL_A;
+ u32 vblank_reg = VBLANK_A;
+ u32 vsync_reg = VSYNC_A;
+ u32 pipesrc_reg = PIPEASRC;
+ u32 dspstride_reg = DSPASTRIDE;
+ u32 dsplinoff_reg = DSPALINOFF;
+ u32 dsptileoff_reg = DSPATILEOFF;
+ u32 dspsize_reg = DSPASIZE;
+ u32 dsppos_reg = DSPAPOS;
+ u32 dspsurf_reg = DSPASURF;
+ u32 mipi_reg = MIPI;
+ u32 dspcntr_reg = DSPACNTR;
+ u32 dspstatus_reg = PIPEASTAT;
+ u32 palette_reg = PALETTE_A;
+
+ /* pointer to values */
+ u32 *dpll_val = &dev_priv->saveDPLL_A;
+ u32 *fp_val = &dev_priv->saveFPA0;
+ u32 *pipeconf_val = &dev_priv->savePIPEACONF;
+ u32 *htot_val = &dev_priv->saveHTOTAL_A;
+ u32 *hblank_val = &dev_priv->saveHBLANK_A;
+ u32 *hsync_val = &dev_priv->saveHSYNC_A;
+ u32 *vtot_val = &dev_priv->saveVTOTAL_A;
+ u32 *vblank_val = &dev_priv->saveVBLANK_A;
+ u32 *vsync_val = &dev_priv->saveVSYNC_A;
+ u32 *pipesrc_val = &dev_priv->savePIPEASRC;
+ u32 *dspstride_val = &dev_priv->saveDSPASTRIDE;
+ u32 *dsplinoff_val = &dev_priv->saveDSPALINOFF;
+ u32 *dsptileoff_val = &dev_priv->saveDSPATILEOFF;
+ u32 *dspsize_val = &dev_priv->saveDSPASIZE;
+ u32 *dsppos_val = &dev_priv->saveDSPAPOS;
+ u32 *dspsurf_val = &dev_priv->saveDSPASURF;
+ u32 *mipi_val = &dev_priv->saveMIPI;
+ u32 *dspcntr_val = &dev_priv->saveDSPACNTR;
+ u32 *dspstatus_val = &dev_priv->saveDSPASTATUS;
+ u32 *palette_val = dev_priv->save_palette_a;
+ PSB_DEBUG_ENTRY("\n");
+
+ switch (pipe) {
+ case 0:
+ break;
+ case 1:
+ /* regester */
+ dpll_reg = MDFLD_DPLL_B;
+ fp_reg = MDFLD_DPLL_DIV0;
+ pipeconf_reg = PIPEBCONF;
+ htot_reg = HTOTAL_B;
+ hblank_reg = HBLANK_B;
+ hsync_reg = HSYNC_B;
+ vtot_reg = VTOTAL_B;
+ vblank_reg = VBLANK_B;
+ vsync_reg = VSYNC_B;
+ pipesrc_reg = PIPEBSRC;
+ dspstride_reg = DSPBSTRIDE;
+ dsplinoff_reg = DSPBLINOFF;
+ dsptileoff_reg = DSPBTILEOFF;
+ dspsize_reg = DSPBSIZE;
+ dsppos_reg = DSPBPOS;
+ dspsurf_reg = DSPBSURF;
+ dspcntr_reg = DSPBCNTR;
+ dspstatus_reg = PIPEBSTAT;
+ palette_reg = PALETTE_B;
+
+ /* values */
+ dpll_val = &dev_priv->saveDPLL_B;
+ fp_val = &dev_priv->saveFPB0;
+ pipeconf_val = &dev_priv->savePIPEBCONF;
+ htot_val = &dev_priv->saveHTOTAL_B;
+ hblank_val = &dev_priv->saveHBLANK_B;
+ hsync_val = &dev_priv->saveHSYNC_B;
+ vtot_val = &dev_priv->saveVTOTAL_B;
+ vblank_val = &dev_priv->saveVBLANK_B;
+ vsync_val = &dev_priv->saveVSYNC_B;
+ pipesrc_val = &dev_priv->savePIPEBSRC;
+ dspstride_val = &dev_priv->saveDSPBSTRIDE;
+ dsplinoff_val = &dev_priv->saveDSPBLINOFF;
+ dsptileoff_val = &dev_priv->saveDSPBTILEOFF;
+ dspsize_val = &dev_priv->saveDSPBSIZE;
+ dsppos_val = &dev_priv->saveDSPBPOS;
+ dspsurf_val = &dev_priv->saveDSPBSURF;
+ dspcntr_val = &dev_priv->saveDSPBCNTR;
+ dspstatus_val = &dev_priv->saveDSPBSTATUS;
+ palette_val = dev_priv->save_palette_b;
+ break;
+ case 2:
+ /* regester */
+ pipeconf_reg = PIPECCONF;
+ htot_reg = HTOTAL_C;
+ hblank_reg = HBLANK_C;
+ hsync_reg = HSYNC_C;
+ vtot_reg = VTOTAL_C;
+ vblank_reg = VBLANK_C;
+ vsync_reg = VSYNC_C;
+ pipesrc_reg = PIPECSRC;
+ dspstride_reg = DSPCSTRIDE;
+ dsplinoff_reg = DSPCLINOFF;
+ dsptileoff_reg = DSPCTILEOFF;
+ dspsize_reg = DSPCSIZE;
+ dsppos_reg = DSPCPOS;
+ dspsurf_reg = DSPCSURF;
+ mipi_reg = MIPI_C;
+ dspcntr_reg = DSPCCNTR;
+ dspstatus_reg = PIPECSTAT;
+ palette_reg = PALETTE_C;
+
+ /* pointer to values */
+ pipeconf_val = &dev_priv->savePIPECCONF;
+ htot_val = &dev_priv->saveHTOTAL_C;
+ hblank_val = &dev_priv->saveHBLANK_C;
+ hsync_val = &dev_priv->saveHSYNC_C;
+ vtot_val = &dev_priv->saveVTOTAL_C;
+ vblank_val = &dev_priv->saveVBLANK_C;
+ vsync_val = &dev_priv->saveVSYNC_C;
+ pipesrc_val = &dev_priv->savePIPECSRC;
+ dspstride_val = &dev_priv->saveDSPCSTRIDE;
+ dsplinoff_val = &dev_priv->saveDSPCLINOFF;
+ dsptileoff_val = &dev_priv->saveDSPCTILEOFF;
+ dspsize_val = &dev_priv->saveDSPCSIZE;
+ dsppos_val = &dev_priv->saveDSPCPOS;
+ dspsurf_val = &dev_priv->saveDSPCSURF;
+ mipi_val = &dev_priv->saveMIPI_C;
+ dspcntr_val = &dev_priv->saveDSPCCNTR;
+ dspstatus_val = &dev_priv->saveDSPCSTATUS;
+ palette_val = dev_priv->save_palette_c;
+ break;
+ default:
+ DRM_ERROR("%s, invalid pipe number. \n", __FUNCTION__);
+ return -EINVAL;
+ }
+
+ /* Pipe & plane A info */
+ *dpll_val = PSB_RVDC32(dpll_reg);
+ *fp_val = PSB_RVDC32(fp_reg);
+ *pipeconf_val = PSB_RVDC32(pipeconf_reg);
+ *htot_val = PSB_RVDC32(htot_reg);
+ *hblank_val = PSB_RVDC32(hblank_reg);
+ *hsync_val = PSB_RVDC32(hsync_reg);
+ *vtot_val = PSB_RVDC32(vtot_reg);
+ *vblank_val = PSB_RVDC32(vblank_reg);
+ *vsync_val = PSB_RVDC32(vsync_reg);
+ *pipesrc_val = PSB_RVDC32(pipesrc_reg);
+ *dspstride_val = PSB_RVDC32(dspstride_reg);
+ *dsplinoff_val = PSB_RVDC32(dsplinoff_reg);
+ *dsptileoff_val = PSB_RVDC32(dsptileoff_reg);
+ *dspsize_val = PSB_RVDC32(dspsize_reg);
+ *dsppos_val = PSB_RVDC32(dsppos_reg);
+ *dspsurf_val = PSB_RVDC32(dspsurf_reg);
+ *dspcntr_val = PSB_RVDC32(dspcntr_reg);
+ *dspstatus_val = PSB_RVDC32(dspstatus_reg);
+
+ /*save palette (gamma) */
+ for (i = 0; i < 256; i++)
+ palette_val[i] = PSB_RVDC32(palette_reg + (i << 2));
+
+ if (pipe == 1) {
+ dev_priv->savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL);
+ dev_priv->savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS);
+
+ dev_priv->saveHDMIPHYMISCCTL = PSB_RVDC32(HDMIPHYMISCCTL);
+ dev_priv->saveHDMIB_CONTROL = PSB_RVDC32(HDMIB_CONTROL);
+ return 0;
+ }
+
+ *mipi_val = PSB_RVDC32(mipi_reg);
+ return 0;
+}
+/*
+ * mdfld_save_cursor_overlay_registers
+ *
+ * Description: We are going to suspend so save current cursor and overlay display
+ * register state.
+ */
+static int mdfld_save_cursor_overlay_registers(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+
+ /*save cursor regs*/
+ dev_priv->saveDSPACURSOR_CTRL = PSB_RVDC32(CURACNTR);
+ dev_priv->saveDSPACURSOR_BASE = PSB_RVDC32(CURABASE);
+ dev_priv->saveDSPACURSOR_POS = PSB_RVDC32(CURAPOS);
+
+ dev_priv->saveDSPBCURSOR_CTRL = PSB_RVDC32(CURBCNTR);
+ dev_priv->saveDSPBCURSOR_BASE = PSB_RVDC32(CURBBASE);
+ dev_priv->saveDSPBCURSOR_POS = PSB_RVDC32(CURBPOS);
+
+ dev_priv->saveDSPCCURSOR_CTRL = PSB_RVDC32(CURCCNTR);
+ dev_priv->saveDSPCCURSOR_BASE = PSB_RVDC32(CURCBASE);
+ dev_priv->saveDSPCCURSOR_POS = PSB_RVDC32(CURCPOS);
+
+ /* HW overlay */
+ dev_priv->saveOV_OVADD = PSB_RVDC32(OV_OVADD);
+ dev_priv->saveOV_OGAMC0 = PSB_RVDC32(OV_OGAMC0);
+ dev_priv->saveOV_OGAMC1 = PSB_RVDC32(OV_OGAMC1);
+ dev_priv->saveOV_OGAMC2 = PSB_RVDC32(OV_OGAMC2);
+ dev_priv->saveOV_OGAMC3 = PSB_RVDC32(OV_OGAMC3);
+ dev_priv->saveOV_OGAMC4 = PSB_RVDC32(OV_OGAMC4);
+ dev_priv->saveOV_OGAMC5 = PSB_RVDC32(OV_OGAMC5);
+
+ dev_priv->saveOV_OVADD_C = PSB_RVDC32(OV_OVADD + OV_C_OFFSET);
+ dev_priv->saveOV_OGAMC0_C = PSB_RVDC32(OV_OGAMC0 + OV_C_OFFSET);
+ dev_priv->saveOV_OGAMC1_C = PSB_RVDC32(OV_OGAMC1 + OV_C_OFFSET);
+ dev_priv->saveOV_OGAMC2_C = PSB_RVDC32(OV_OGAMC2 + OV_C_OFFSET);
+ dev_priv->saveOV_OGAMC3_C = PSB_RVDC32(OV_OGAMC3 + OV_C_OFFSET);
+ dev_priv->saveOV_OGAMC4_C = PSB_RVDC32(OV_OGAMC4 + OV_C_OFFSET);
+ dev_priv->saveOV_OGAMC5_C = PSB_RVDC32(OV_OGAMC5 + OV_C_OFFSET);
+
+ return 0;
+}
+/*
+ * mdfld_restore_display_registers
+ *
+ * Description: We are going to resume so restore display register state.
+ *
+ * Notes: FIXME_JLIU7 need to add the support for DPI MIPI & HDMI audio
+ */
+static int mdfld_restore_display_registers(struct drm_device *dev, int pipe)
+{
+ //to get panel out of ULPS mode.
+ u32 temp = 0;
+ u32 device_ready_reg = DEVICE_READY_REG;
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct mdfld_dsi_dbi_output * dsi_output = dev_priv->dbi_output;
+ struct mdfld_dsi_config * dsi_config = NULL;
+ u32 i = 0;
+ u32 dpll = 0;
+ u32 timeout = 0;
+
+ /* regester */
+ u32 dpll_reg = MRST_DPLL_A;
+ u32 fp_reg = MRST_FPA0;
+ u32 pipeconf_reg = PIPEACONF;
+ u32 htot_reg = HTOTAL_A;
+ u32 hblank_reg = HBLANK_A;
+ u32 hsync_reg = HSYNC_A;
+ u32 vtot_reg = VTOTAL_A;
+ u32 vblank_reg = VBLANK_A;
+ u32 vsync_reg = VSYNC_A;
+ u32 pipesrc_reg = PIPEASRC;
+ u32 dspstride_reg = DSPASTRIDE;
+ u32 dsplinoff_reg = DSPALINOFF;
+ u32 dsptileoff_reg = DSPATILEOFF;
+ u32 dspsize_reg = DSPASIZE;
+ u32 dsppos_reg = DSPAPOS;
+ u32 dspsurf_reg = DSPASURF;
+ u32 dspstatus_reg = PIPEASTAT;
+ u32 mipi_reg = MIPI;
+ u32 dspcntr_reg = DSPACNTR;
+ u32 palette_reg = PALETTE_A;
+
+ /* values */
+ u32 dpll_val = dev_priv->saveDPLL_A & ~DPLL_VCO_ENABLE;
+ u32 fp_val = dev_priv->saveFPA0;
+ u32 pipeconf_val = dev_priv->savePIPEACONF;
+ u32 htot_val = dev_priv->saveHTOTAL_A;
+ u32 hblank_val = dev_priv->saveHBLANK_A;
+ u32 hsync_val = dev_priv->saveHSYNC_A;
+ u32 vtot_val = dev_priv->saveVTOTAL_A;
+ u32 vblank_val = dev_priv->saveVBLANK_A;
+ u32 vsync_val = dev_priv->saveVSYNC_A;
+ u32 pipesrc_val = dev_priv->savePIPEASRC;
+ u32 dspstride_val = dev_priv->saveDSPASTRIDE;
+ u32 dsplinoff_val = dev_priv->saveDSPALINOFF;
+ u32 dsptileoff_val = dev_priv->saveDSPATILEOFF;
+ u32 dspsize_val = dev_priv->saveDSPASIZE;
+ u32 dsppos_val = dev_priv->saveDSPAPOS;
+ u32 dspsurf_val = dev_priv->saveDSPASURF;
+ u32 dspstatus_val = dev_priv->saveDSPASTATUS;
+ u32 mipi_val = dev_priv->saveMIPI;
+ u32 dspcntr_val = dev_priv->saveDSPACNTR;
+ u32 *palette_val = dev_priv->save_palette_a;
+ PSB_DEBUG_ENTRY("\n");
+
+ switch (pipe) {
+ case 0:
+ dsi_config = dev_priv->dsi_configs[0];
+ break;
+ case 1:
+ /* regester */
+ dpll_reg = MDFLD_DPLL_B;
+ fp_reg = MDFLD_DPLL_DIV0;
+ pipeconf_reg = PIPEBCONF;
+ htot_reg = HTOTAL_B;
+ hblank_reg = HBLANK_B;
+ hsync_reg = HSYNC_B;
+ vtot_reg = VTOTAL_B;
+ vblank_reg = VBLANK_B;
+ vsync_reg = VSYNC_B;
+ pipesrc_reg = PIPEBSRC;
+ dspstride_reg = DSPBSTRIDE;
+ dsplinoff_reg = DSPBLINOFF;
+ dsptileoff_reg = DSPBTILEOFF;
+ dspsize_reg = DSPBSIZE;
+ dsppos_reg = DSPBPOS;
+ dspsurf_reg = DSPBSURF;
+ dspcntr_reg = DSPBCNTR;
+ dspstatus_reg = PIPEBSTAT;
+ palette_reg = PALETTE_B;
+
+ /* values */
+ dpll_val = dev_priv->saveDPLL_B & ~DPLL_VCO_ENABLE;
+ fp_val = dev_priv->saveFPB0;
+ pipeconf_val = dev_priv->savePIPEBCONF;
+ htot_val = dev_priv->saveHTOTAL_B;
+ hblank_val = dev_priv->saveHBLANK_B;
+ hsync_val = dev_priv->saveHSYNC_B;
+ vtot_val = dev_priv->saveVTOTAL_B;
+ vblank_val = dev_priv->saveVBLANK_B;
+ vsync_val = dev_priv->saveVSYNC_B;
+ pipesrc_val = dev_priv->savePIPEBSRC;
+ dspstride_val = dev_priv->saveDSPBSTRIDE;
+ dsplinoff_val = dev_priv->saveDSPBLINOFF;
+ dsptileoff_val = dev_priv->saveDSPBTILEOFF;
+ dspsize_val = dev_priv->saveDSPBSIZE;
+ dsppos_val = dev_priv->saveDSPBPOS;
+ dspsurf_val = dev_priv->saveDSPBSURF;
+ dspcntr_val = dev_priv->saveDSPBCNTR;
+ dspstatus_val = dev_priv->saveDSPBSTATUS;
+ palette_val = dev_priv->save_palette_b;
+ break;
+ case 2:
+ dsi_output = dev_priv->dbi_output2;
+
+ /* regester */
+ pipeconf_reg = PIPECCONF;
+ htot_reg = HTOTAL_C;
+ hblank_reg = HBLANK_C;
+ hsync_reg = HSYNC_C;
+ vtot_reg = VTOTAL_C;
+ vblank_reg = VBLANK_C;
+ vsync_reg = VSYNC_C;
+ pipesrc_reg = PIPECSRC;
+ dspstride_reg = DSPCSTRIDE;
+ dsplinoff_reg = DSPCLINOFF;
+ dsptileoff_reg = DSPCTILEOFF;
+ dspsize_reg = DSPCSIZE;
+ dsppos_reg = DSPCPOS;
+ dspsurf_reg = DSPCSURF;
+ mipi_reg = MIPI_C;
+ dspcntr_reg = DSPCCNTR;
+ dspstatus_reg = PIPECSTAT;
+ palette_reg = PALETTE_C;
+
+ /* values */
+ pipeconf_val = dev_priv->savePIPECCONF;
+ htot_val = dev_priv->saveHTOTAL_C;
+ hblank_val = dev_priv->saveHBLANK_C;
+ hsync_val = dev_priv->saveHSYNC_C;
+ vtot_val = dev_priv->saveVTOTAL_C;
+ vblank_val = dev_priv->saveVBLANK_C;
+ vsync_val = dev_priv->saveVSYNC_C;
+ pipesrc_val = dev_priv->savePIPECSRC;
+ dspstride_val = dev_priv->saveDSPCSTRIDE;
+ dsplinoff_val = dev_priv->saveDSPCLINOFF;
+ dsptileoff_val = dev_priv->saveDSPCTILEOFF;
+ dspsize_val = dev_priv->saveDSPCSIZE;
+ dsppos_val = dev_priv->saveDSPCPOS;
+ dspsurf_val = dev_priv->saveDSPCSURF;
+ mipi_val = dev_priv->saveMIPI_C;
+ dspcntr_val = dev_priv->saveDSPCCNTR;
+ dspstatus_val = dev_priv->saveDSPCSTATUS;
+ palette_val = dev_priv->save_palette_c;
+
+ dsi_config = dev_priv->dsi_configs[1];
+ break;
+ default:
+ DRM_ERROR("%s, invalid pipe number. \n", __FUNCTION__);
+ return -EINVAL;
+ }
+
+ /*make sure VGA plane is off. it initializes to on after reset!*/
+ PSB_WVDC32(0x80000000, VGACNTRL);
+
+ if (pipe == 1) {
+ PSB_WVDC32(dpll_val & ~DPLL_VCO_ENABLE, dpll_reg);
+ PSB_RVDC32(dpll_reg);
+
+ PSB_WVDC32(fp_val, fp_reg);
+ } else {
+
+ dpll = PSB_RVDC32(dpll_reg);
+
+ if (!(dpll & DPLL_VCO_ENABLE)) {
+
+ /* When ungating power of DPLL, needs to wait 0.5us before enable the VCO */
+ if (dpll & MDFLD_PWR_GATE_EN) {
+ dpll &= ~MDFLD_PWR_GATE_EN;
+ PSB_WVDC32(dpll, dpll_reg);
+ /* FIXME_MDFLD PO - change 500 to 1 after PO */
+ udelay(500);
+ }
+
+ PSB_WVDC32(fp_val, fp_reg);
+ PSB_WVDC32(dpll_val, dpll_reg);
+ /* FIXME_MDFLD PO - change 500 to 1 after PO */
+ udelay(500);
+
+ dpll_val |= DPLL_VCO_ENABLE;
+ PSB_WVDC32(dpll_val, dpll_reg);
+ PSB_RVDC32(dpll_reg);
+
+ /* wait for DSI PLL to lock */
+ while ((timeout < 20000) && !(PSB_RVDC32(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) {
+ udelay(150);
+ timeout ++;
+ }
+
+ if (timeout == 20000) {
+ DRM_ERROR("%s, can't lock DSIPLL. \n", __FUNCTION__);
+ return -EINVAL;
+ }
+ }
+ }
+ /* Restore mode */
+ PSB_WVDC32(htot_val, htot_reg);
+ PSB_WVDC32(hblank_val, hblank_reg);
+ PSB_WVDC32(hsync_val, hsync_reg);
+ PSB_WVDC32(vtot_val, vtot_reg);
+ PSB_WVDC32(vblank_val, vblank_reg);
+ PSB_WVDC32(vsync_val, vsync_reg);
+ PSB_WVDC32(pipesrc_val, pipesrc_reg);
+ PSB_WVDC32(dspstatus_val, dspstatus_reg);
+
+ /*set up the plane*/
+ PSB_WVDC32(dspstride_val, dspstride_reg);
+ PSB_WVDC32(dsplinoff_val, dsplinoff_reg);
+ PSB_WVDC32(dsptileoff_val, dsptileoff_reg);
+ PSB_WVDC32(dspsize_val, dspsize_reg);
+ PSB_WVDC32(dsppos_val, dsppos_reg);
+ PSB_WVDC32(dspsurf_val, dspsurf_reg);
+
+ if (pipe == 1) {
+ /* restore palette (gamma) */
+ /*DRM_UDELAY(50000); */
+ for (i = 0; i < 256; i++)
+ PSB_WVDC32(palette_val[i], palette_reg + (i << 2));
+
+ PSB_WVDC32(dev_priv->savePFIT_CONTROL, PFIT_CONTROL);
+ PSB_WVDC32(dev_priv->savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS);
+
+ /*TODO: resume HDMI port */
+
+ /*TODO: resume pipe*/
+
+ /*enable the plane*/
+ PSB_WVDC32(dspcntr_val & ~DISPLAY_PLANE_ENABLE, dspcntr_reg);
+
+ return 0;
+ }
+
+ /*set up pipe related registers*/
+ PSB_WVDC32(mipi_val, mipi_reg);
+
+ /*setup MIPI adapter + MIPI IP registers*/
+ if (dsi_config)
+ mdfld_dsi_controller_init(dsi_config, pipe);
+
+ if (in_atomic() || in_interrupt())
+ mdelay(20);
+ else
+ msleep(20);
+
+ /*enable the plane*/
+ PSB_WVDC32(dspcntr_val, dspcntr_reg);
+
+ if (in_atomic() || in_interrupt())
+ mdelay(20);
+ else
+ msleep(20);
+
+ /* LP Hold Release */
+ temp = REG_READ(mipi_reg);
+ temp |= LP_OUTPUT_HOLD_RELEASE;
+ REG_WRITE(mipi_reg, temp);
+ mdelay(1);
+
+
+ /* Set DSI host to exit from Utra Low Power State */
+ temp = REG_READ(device_ready_reg);
+ temp &= ~ULPS_MASK;
+ temp |= 0x3;
+ temp |= EXIT_ULPS_DEV_READY;
+ REG_WRITE(device_ready_reg, temp);
+ mdelay(1);
+
+ temp = REG_READ(device_ready_reg);
+ temp &= ~ULPS_MASK;
+ temp |= EXITING_ULPS;
+ REG_WRITE(device_ready_reg, temp);
+ mdelay(1);
+
+ /*enable the pipe*/
+ PSB_WVDC32(pipeconf_val, pipeconf_reg);
+
+ /* restore palette (gamma) */
+ /*DRM_UDELAY(50000); */
+ for (i = 0; i < 256; i++)
+ PSB_WVDC32(palette_val[i], palette_reg + (i << 2));
+
+ return 0;
+}
+
+/*
+ * mdfld_restore_cursor_overlay_registers
+ *
+ * Description: We are going to resume so restore cursor and overlay register state.
+ */
+static int mdfld_restore_cursor_overlay_registers(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+
+ /*Enable Cursor A*/
+ PSB_WVDC32(dev_priv->saveDSPACURSOR_CTRL, CURACNTR);
+ PSB_WVDC32(dev_priv->saveDSPACURSOR_POS, CURAPOS);
+ PSB_WVDC32(dev_priv->saveDSPACURSOR_BASE, CURABASE);
+
+ PSB_WVDC32(dev_priv->saveDSPBCURSOR_CTRL, CURBCNTR);
+ PSB_WVDC32(dev_priv->saveDSPBCURSOR_POS, CURBPOS);
+ PSB_WVDC32(dev_priv->saveDSPBCURSOR_BASE, CURBBASE);
+
+ PSB_WVDC32(dev_priv->saveDSPCCURSOR_CTRL, CURCCNTR);
+ PSB_WVDC32(dev_priv->saveDSPCCURSOR_POS, CURCPOS);
+ PSB_WVDC32(dev_priv->saveDSPCCURSOR_BASE, CURCBASE);
+
+ /* restore HW overlay */
+ PSB_WVDC32(dev_priv->saveOV_OVADD, OV_OVADD);
+ PSB_WVDC32(dev_priv->saveOV_OGAMC0, OV_OGAMC0);
+ PSB_WVDC32(dev_priv->saveOV_OGAMC1, OV_OGAMC1);
+ PSB_WVDC32(dev_priv->saveOV_OGAMC2, OV_OGAMC2);
+ PSB_WVDC32(dev_priv->saveOV_OGAMC3, OV_OGAMC3);
+ PSB_WVDC32(dev_priv->saveOV_OGAMC4, OV_OGAMC4);
+ PSB_WVDC32(dev_priv->saveOV_OGAMC5, OV_OGAMC5);
+
+ PSB_WVDC32(dev_priv->saveOV_OVADD_C, OV_OVADD + OV_C_OFFSET);
+ PSB_WVDC32(dev_priv->saveOV_OGAMC0_C, OV_OGAMC0 + OV_C_OFFSET);
+ PSB_WVDC32(dev_priv->saveOV_OGAMC1_C, OV_OGAMC1 + OV_C_OFFSET);
+ PSB_WVDC32(dev_priv->saveOV_OGAMC2_C, OV_OGAMC2 + OV_C_OFFSET);
+ PSB_WVDC32(dev_priv->saveOV_OGAMC3_C, OV_OGAMC3 + OV_C_OFFSET);
+ PSB_WVDC32(dev_priv->saveOV_OGAMC4_C, OV_OGAMC4 + OV_C_OFFSET);
+ PSB_WVDC32(dev_priv->saveOV_OGAMC5_C, OV_OGAMC5 + OV_C_OFFSET);
+
+ return 0;
+}
+
+/*
+ * mdfld_save_display
+ *
+ * Description: Save display status before DPMS OFF for RuntimePM
+ */
+static void mdfld_save_display(struct drm_device *dev)
+{
+#ifdef OSPM_GFX_DPK
+ printk(KERN_ALERT "ospm_save_display\n");
+#endif
+ mdfld_save_cursor_overlay_registers(dev);
+
+ mdfld_save_display_registers(dev, 0);
+
+ mdfld_save_display_registers(dev, 2);
+}
+/*
+ * powermgmt_suspend_display
+ *
+ * Description: Suspend the display hardware saving state and disabling
+ * as necessary.
+ */
+static void ospm_suspend_display(struct drm_device *dev)
+{
+ //to put panel into ULPS mode.
+ u32 temp = 0;
+ u32 device_ready_reg = DEVICE_READY_REG;
+ u32 mipi_reg = MIPI;
+
+#ifdef OSPM_GFX_DPK
+ printk(KERN_ALERT "%s \n", __func__);
+#endif
+ if (!(g_hw_power_status_mask & OSPM_DISPLAY_ISLAND))
+ return;
+
+ mdfld_save_cursor_overlay_registers(dev);
+
+ mdfld_save_display_registers(dev, 0);
+ mdfld_save_display_registers(dev, 2);
+ mdfld_save_display_registers(dev, 1);
+
+ mdfld_disable_crtc(dev, 0);
+ mdfld_disable_crtc(dev, 2);
+ mdfld_disable_crtc(dev, 1);
+
+ /* Put the panel in ULPS mode for S0ix. */
+ temp = REG_READ(device_ready_reg);
+ temp &= ~ULPS_MASK;
+ temp |= ENTERING_ULPS;
+ REG_WRITE(device_ready_reg, temp);
+
+ //LP Hold
+ temp = REG_READ(mipi_reg);
+ temp &= ~LP_OUTPUT_HOLD;
+ REG_WRITE(mipi_reg, temp);
+ mdelay(1);
+
+ ospm_power_island_down(OSPM_DISPLAY_ISLAND);
+}
+
+/*
+ * ospm_resume_display
+ *
+ * Description: Resume the display hardware restoring state and enabling
+ * as necessary.
+ */
+static void ospm_resume_display(struct pci_dev *pdev)
+{
+ struct drm_device *dev = pci_get_drvdata(pdev);
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct psb_gtt *pg = dev_priv->pg;
+
+#ifdef OSPM_GFX_DPK
+ printk(KERN_ALERT "%s \n", __func__);
+#endif
+ if (g_hw_power_status_mask & OSPM_DISPLAY_ISLAND)
+ return;
+
+ /* turn on the display power island */
+ ospm_power_island_up(OSPM_DISPLAY_ISLAND);
+
+ PSB_WVDC32(pg->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL);
+ pci_write_config_word(pdev, PSB_GMCH_CTRL,
+ pg->gmch_ctrl | _PSB_GMCH_ENABLED);
+
+ /* Don't reinitialize the GTT as it is unnecessary. The gtt is
+ * stored in memory so it will automatically be restored. All
+ * we need to do is restore the PGETBL_CTL which we already do
+ * above.
+ */
+ /*psb_gtt_init(dev_priv->pg, 1);*/
+
+ mdfld_restore_display_registers(dev, 1);
+ mdfld_restore_display_registers(dev, 0);
+ mdfld_restore_display_registers(dev, 2);
+ mdfld_restore_cursor_overlay_registers(dev);
+}
+
+#if 1
+/*
+ * ospm_suspend_pci
+ *
+ * Description: Suspend the pci device saving state and disabling
+ * as necessary.
+ */
+static void ospm_suspend_pci(struct pci_dev *pdev)
+{
+ struct drm_device *dev = pci_get_drvdata(pdev);
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ int bsm, vbt;
+
+ if (gbSuspended)
+ return;
+
+#ifdef OSPM_GFX_DPK
+ printk(KERN_ALERT "ospm_suspend_pci\n");
+#endif
+
+#ifdef CONFIG_MDFD_GL3
+ /* Power off GL3 after all GFX sub-systems are powered off. */
+ gl3_invalidate();
+ ospm_power_island_down(OSPM_GL3_CACHE_ISLAND);
+#endif
+
+ pci_save_state(pdev);
+ pci_read_config_dword(pdev, 0x5C, &bsm);
+ dev_priv->saveBSM = bsm;
+ pci_read_config_dword(pdev, 0xFC, &vbt);
+ dev_priv->saveVBT = vbt;
+ pci_read_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, &dev_priv->msi_addr);
+ pci_read_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, &dev_priv->msi_data);
+
+ pci_disable_device(pdev);
+ pci_set_power_state(pdev, PCI_D3hot);
+
+ gbSuspended = true;
+ gbgfxsuspended = true;
+}
+
+/*
+ * ospm_resume_pci
+ *
+ * Description: Resume the pci device restoring state and enabling
+ * as necessary.
+ */
+static bool ospm_resume_pci(struct pci_dev *pdev)
+{
+ struct drm_device *dev = pci_get_drvdata(pdev);
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ int ret = 0;
+
+ if (!gbSuspended)
+ return true;
+
+#ifdef OSPM_GFX_DPK
+ printk(KERN_ALERT "ospm_resume_pci\n");
+#endif
+
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+ pci_write_config_dword(pdev, 0x5c, dev_priv->saveBSM);
+ pci_write_config_dword(pdev, 0xFC, dev_priv->saveVBT);
+ /* retoring MSI address and data in PCIx space */
+ pci_write_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, dev_priv->msi_addr);
+ pci_write_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, dev_priv->msi_data);
+ ret = pci_enable_device(pdev);
+
+ if (ret != 0)
+ printk(KERN_ALERT "ospm_resume_pci: pci_enable_device failed: %d\n", ret);
+ else
+ gbSuspended = false;
+
+#ifdef CONFIG_MDFD_GL3
+ if (!ret) {
+ // Powerup GL3 - can be used by any GFX-sub-system.
+ ospm_power_island_up(OSPM_GL3_CACHE_ISLAND);
+
+ }
+#endif
+
+ return !gbSuspended;
+}
+#endif
+/*
+ * ospm_power_suspend
+ *
+ * Description: OSPM is telling our driver to suspend so save state
+ * and power down all hardware.
+ */
+int ospm_power_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ int ret = 0;
+ int graphics_access_count;
+ int videoenc_access_count;
+ int videodec_access_count;
+ int display_access_count;
+ bool suspend_pci = true;
+
+ if (gbSuspendInProgress || gbResumeInProgress) {
+#ifdef OSPM_GFX_DPK
+ printk(KERN_ALERT "OSPM_GFX_DPK: %s system BUSY \n", __func__);
+#endif
+ return -EBUSY;
+ }
+
+ mutex_lock(&g_ospm_mutex);
+
+ if (!gbSuspended) {
+ graphics_access_count = atomic_read(&g_graphics_access_count);
+ videoenc_access_count = atomic_read(&g_videoenc_access_count);
+ videodec_access_count = atomic_read(&g_videodec_access_count);
+ display_access_count = atomic_read(&g_display_access_count);
+
+ if (graphics_access_count ||
+ videoenc_access_count ||
+ videodec_access_count ||
+ display_access_count)
+ ret = -EBUSY;
+
+ if (!ret) {
+ gbSuspendInProgress = true;
+
+ psb_irq_uninstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND);
+ ospm_suspend_display(gpDrmDevice);
+#if 1
+ /* FIXME: video driver support for Linux Runtime PM */
+ if (ospm_runtime_pm_msvdx_suspend(gpDrmDevice) != 0) {
+ suspend_pci = false;
+ }
+
+ if (ospm_runtime_pm_topaz_suspend(gpDrmDevice) != 0) {
+ suspend_pci = false;
+ }
+
+#endif
+ if (suspend_pci == true) {
+ ospm_suspend_pci(pdev);
+ }
+ gbSuspendInProgress = false;
+ } else {
+ printk(KERN_ALERT "ospm_power_suspend: device busy: graphics %d videoenc %d videodec %d display %d\n", graphics_access_count, videoenc_access_count, videodec_access_count, display_access_count);
+ }
+ }
+
+
+ mutex_unlock(&g_ospm_mutex);
+ return ret;
+}
+
+/*
+ * ospm_power_island_up
+ *
+ * Description: Restore power to the specified island(s) (powergating)
+ */
+void ospm_power_island_up(int hw_islands)
+{
+ u32 pwr_cnt = 0;
+ u32 pwr_sts = 0;
+ u32 pwr_mask = 0;
+ u32 cnt = 0;
+ unsigned long flags;
+ struct drm_psb_private *dev_priv = (struct drm_psb_private *) gpDrmDevice->dev_private;
+
+ if (hw_islands & (OSPM_GRAPHICS_ISLAND | OSPM_VIDEO_ENC_ISLAND |
+ OSPM_VIDEO_DEC_ISLAND | OSPM_GL3_CACHE_ISLAND |
+ OSPM_ISP_ISLAND)) {
+ spin_lock_irqsave(&dev_priv->ospm_lock, flags);
+ pwr_cnt = inl(dev_priv->apm_base + PSB_APM_CMD);
+
+ pwr_mask = 0;
+
+
+ if (hw_islands & OSPM_GRAPHICS_ISLAND) {
+ pwr_cnt &= ~PSB_PWRGT_GFX_MASK;
+ pwr_mask |= PSB_PWRGT_GFX_MASK;
+#ifdef OSPM_STAT
+ if (dev_priv->graphics_state == PSB_PWR_STATE_OFF) {
+ dev_priv->gfx_off_time += (jiffies - dev_priv->gfx_last_mode_change) * 1000 / HZ;
+ dev_priv->gfx_last_mode_change = jiffies;
+ dev_priv->graphics_state = PSB_PWR_STATE_ON;
+ dev_priv->gfx_on_cnt++;
+ }
+#endif
+ }
+ if (hw_islands & OSPM_GL3_CACHE_ISLAND) {
+ pwr_cnt &= ~PSB_PWRGT_GL3_MASK;
+ pwr_mask |= PSB_PWRGT_GL3_MASK;
+ }
+ if (hw_islands & OSPM_VIDEO_ENC_ISLAND) {
+ pwr_cnt &= ~PSB_PWRGT_VID_ENC_MASK;
+ pwr_mask |= PSB_PWRGT_VID_ENC_MASK;
+ }
+ if (hw_islands & OSPM_VIDEO_DEC_ISLAND) {
+ pwr_cnt &= ~PSB_PWRGT_VID_DEC_MASK;
+ pwr_mask |= PSB_PWRGT_VID_DEC_MASK;
+ }
+ if (hw_islands & OSPM_ISP_ISLAND) {
+ pwr_cnt &= ~PSB_PWRGT_ISP_MASK;
+ pwr_mask |= PSB_PWRGT_ISP_MASK;
+ }
+
+ outl(pwr_cnt, dev_priv->apm_base + PSB_APM_CMD);
+ spin_unlock_irqrestore(&dev_priv->ospm_lock, flags);
+
+ while (true) {
+ pwr_sts = inl(dev_priv->apm_base + PSB_APM_STS);
+ if ((pwr_sts & pwr_mask) == 0)
+ break;
+ else
+ udelay(10);
+ cnt++;
+ if (cnt > 1000) {
+ printk(KERN_ALERT "%s: STUCK in INFINITE LOOP - failing on islands:0x%x\n", __func__, hw_islands);
+ cnt = 0;
+ }
+ }
+ }
+ if (hw_islands & OSPM_DISPLAY_ISLAND) {
+
+ pwr_mask = MDFLD_PWRGT_DISPLAY_CNTR;
+
+ spin_lock_irqsave(&dev_priv->ospm_lock, flags);
+ pwr_cnt = inl(dev_priv->ospm_base + PSB_PM_SSC);
+ pwr_cnt &= ~pwr_mask;
+ outl(pwr_cnt, (dev_priv->ospm_base + PSB_PM_SSC));
+ spin_unlock_irqrestore(&dev_priv->ospm_lock, flags);
+
+ pwr_mask = MDFLD_PWRGT_DISPLAY_STS_B0;
+
+ cnt = 0;
+ while (true) {
+ pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS);
+ if ((pwr_sts & pwr_mask) == 0)
+ break;
+ else
+ udelay(10);
+ cnt++;
+ if (cnt > 1000) {
+ printk(KERN_ALERT "%s: STUCK in INFINITE LOOP - failing on DISPLAY \n", __func__);
+ cnt = 0;
+ }
+ }
+ }
+
+ g_hw_power_status_mask |= hw_islands;
+}
+
+/*
+ * ospm_power_resume
+ */
+int ospm_power_resume(struct pci_dev *pdev)
+{
+ if (gbSuspendInProgress || gbResumeInProgress) {
+#ifdef OSPM_GFX_DPK
+ printk(KERN_ALERT "OSPM_GFX_DPK: %s hw_island: Suspend || gbResumeInProgress!!!! \n", __func__);
+#endif
+ return 0;
+ }
+
+ mutex_lock(&g_ospm_mutex);
+
+#ifdef OSPM_GFX_DPK
+ printk(KERN_ALERT "OSPM_GFX_DPK: ospm_power_resume \n");
+#endif
+
+ gbResumeInProgress = true;
+
+ ospm_resume_pci(pdev);
+
+ ospm_resume_display(gpDrmDevice->pdev);
+ psb_irq_preinstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND);
+ psb_irq_postinstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND);
+
+ gbResumeInProgress = false;
+
+ mutex_unlock(&g_ospm_mutex);
+
+ return 0;
+}
+
+
+/*
+ * ospm_power_island_down
+ *
+ * Description: Cut power to the specified island(s) (powergating)
+ */
+void ospm_power_island_down(int islands)
+{
+ u32 pwr_cnt = 0;
+ u32 pwr_mask = 0;
+ u32 pwr_sts = 0;
+ u32 cnt = 0;
+ unsigned long flags;
+ struct drm_psb_private *dev_priv = (struct drm_psb_private *) gpDrmDevice->dev_private;
+
+ g_hw_power_status_mask &= ~islands;
+
+ if (islands & OSPM_GRAPHICS_ISLAND) {
+ pwr_cnt |= PSB_PWRGT_GFX_MASK;
+ pwr_mask |= PSB_PWRGT_GFX_MASK;
+#ifdef OSPM_STAT
+ if (dev_priv->graphics_state == PSB_PWR_STATE_ON) {
+ dev_priv->gfx_on_time += (jiffies - dev_priv->gfx_last_mode_change) * 1000 / HZ;
+ dev_priv->gfx_last_mode_change = jiffies;
+ dev_priv->graphics_state = PSB_PWR_STATE_OFF;
+ dev_priv->gfx_off_cnt++;
+ }
+#endif
+ }
+ if (islands & OSPM_GL3_CACHE_ISLAND) {
+ pwr_cnt |= PSB_PWRGT_GL3_MASK;
+ pwr_mask |= PSB_PWRGT_GL3_MASK;
+ }
+ if (islands & OSPM_VIDEO_ENC_ISLAND) {
+ pwr_cnt |= PSB_PWRGT_VID_ENC_MASK;
+ pwr_mask |= PSB_PWRGT_VID_ENC_MASK;
+ }
+ if (islands & OSPM_VIDEO_DEC_ISLAND) {
+ pwr_cnt |= PSB_PWRGT_VID_DEC_MASK;
+ pwr_mask |= PSB_PWRGT_VID_DEC_MASK;
+ }
+ if (islands & OSPM_ISP_ISLAND) {
+ pwr_cnt |= PSB_PWRGT_ISP_MASK;
+ pwr_mask |= PSB_PWRGT_ISP_MASK;
+ }
+ if (pwr_cnt) {
+ spin_lock_irqsave(&dev_priv->ospm_lock, flags);
+ pwr_cnt |= inl(dev_priv->apm_base);
+ outl(pwr_cnt, dev_priv->apm_base + PSB_APM_CMD);
+ spin_unlock_irqrestore(&dev_priv->ospm_lock, flags);
+
+ while (true) {
+ pwr_sts = inl(dev_priv->apm_base + PSB_APM_STS);
+ if ((pwr_sts & pwr_mask) == pwr_mask)
+ break;
+ else
+ udelay(10);
+ cnt++;
+ if (cnt > 1000) {
+ printk(KERN_ALERT "%s: STUCK in INFINITE LOOP - failing on islands:0x%x\n", __func__, islands);
+ cnt = 0;
+ }
+ }
+ }
+ if (islands & OSPM_DISPLAY_ISLAND) {
+
+ pwr_mask = MDFLD_PWRGT_DISPLAY_CNTR;
+
+ outl(pwr_mask, (dev_priv->ospm_base + PSB_PM_SSC));
+
+ pwr_mask = MDFLD_PWRGT_DISPLAY_STS_B0;
+
+ cnt = 0;
+ while (true) {
+ pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS);
+ if ((pwr_sts & pwr_mask) == pwr_mask)
+ break;
+ else
+ udelay(10);
+ cnt++;
+ if (cnt > 1000) {
+ printk(KERN_ALERT "%s: STUCK in INFINITE LOOP - failing on Display island\n", __func__);
+ cnt = 0;
+ }
+ }
+ }
+}
+
+
+/*
+ * ospm_power_is_hw_on
+ *
+ * Description: do an instantaneous check for if the specified islands
+ * are on. Only use this in cases where you know the g_state_change_mutex
+ * is already held such as in irq install/uninstall. Otherwise, use
+ * ospm_power_using_hw_begin().
+ */
+bool ospm_power_is_hw_on(int hw_islands)
+{
+ return ((g_hw_power_status_mask & hw_islands) == hw_islands) ? true : false;
+}
+
+/*
+ * ospm_power_using_hw_begin
+ *
+ * Description: Notify PowerMgmt module that you will be accessing the
+ * specified island's hw so don't power it off. If force_on is true,
+ * this will power on the specified island if it is off.
+ * Otherwise, this will return false and the caller is expected to not
+ * access the hw.
+ *
+ * NOTE *** If this is called from and interrupt handler or other atomic
+ * context, then it will return false if we are in the middle of a
+ * power state transition and the caller will be expected to handle that
+ * even if force_on is set to true.
+ */
+bool ospm_power_using_hw_begin(int hw_island, UHBUsage usage)
+{
+ bool ret = true;
+ bool island_is_off = false;
+ bool b_atomic = (in_interrupt() || in_atomic());
+ bool locked = true;
+ struct pci_dev *pdev = gpDrmDevice->pdev;
+ IMG_UINT32 deviceID = 0;
+ bool force_on = usage ? true : false;
+
+#ifdef CONFIG_PM_RUNTIME
+ /* increment pm_runtime_refcount */
+ pm_runtime_get(&pdev->dev);
+#endif
+
+ /*quick path, not 100% race safe, but should be enough comapre to current other code in this file */
+ if (!force_on) {
+ if (hw_island & (OSPM_ALL_ISLANDS & ~g_hw_power_status_mask)) {
+#ifdef CONFIG_PM_RUNTIME
+ /* decrement pm_runtime_refcount */
+ pm_runtime_put(&pdev->dev);
+#endif
+ return false;
+ } else {
+ locked = false;
+ goto increase_count;
+ }
+ }
+
+ if (!b_atomic)
+ mutex_lock(&g_ospm_mutex);
+
+ island_is_off = hw_island & (OSPM_ALL_ISLANDS & ~g_hw_power_status_mask);
+
+ if (b_atomic && (gbSuspendInProgress || gbResumeInProgress || gbSuspended) && force_on && island_is_off)
+ ret = false;
+
+ if (ret && island_is_off && !force_on)
+ ret = false;
+
+ if (ret && island_is_off && force_on) {
+ gbResumeInProgress = true;
+
+ ret = ospm_resume_pci(pdev);
+
+ if (ret) {
+ switch (hw_island) {
+ case OSPM_DISPLAY_ISLAND:
+ deviceID = gui32MRSTDisplayDeviceID;
+ ospm_resume_display(pdev);
+ psb_irq_preinstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND);
+ psb_irq_postinstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND);
+ break;
+ case OSPM_GRAPHICS_ISLAND:
+ deviceID = gui32SGXDeviceID;
+ ospm_power_island_up(OSPM_GRAPHICS_ISLAND);
+ psb_irq_preinstall_islands(gpDrmDevice, OSPM_GRAPHICS_ISLAND);
+ psb_irq_postinstall_islands(gpDrmDevice, OSPM_GRAPHICS_ISLAND);
+ break;
+#if 1
+ case OSPM_VIDEO_DEC_ISLAND:
+ if (!ospm_power_is_hw_on(OSPM_DISPLAY_ISLAND)) {
+ //printk(KERN_ALERT "%s power on display for video decode use\n", __func__);
+ deviceID = gui32MRSTDisplayDeviceID;
+ ospm_resume_display(pdev);
+ psb_irq_preinstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND);
+ psb_irq_postinstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND);
+ } else {
+ //printk(KERN_ALERT "%s display is already on for video decode use\n", __func__);
+ }
+
+ if (!ospm_power_is_hw_on(OSPM_VIDEO_DEC_ISLAND)) {
+ //printk(KERN_ALERT "%s power on video decode\n", __func__);
+ deviceID = gui32MRSTMSVDXDeviceID;
+ ospm_power_island_up(OSPM_VIDEO_DEC_ISLAND);
+ ospm_runtime_pm_msvdx_resume(gpDrmDevice);
+ psb_irq_preinstall_islands(gpDrmDevice, OSPM_VIDEO_DEC_ISLAND);
+ psb_irq_postinstall_islands(gpDrmDevice, OSPM_VIDEO_DEC_ISLAND);
+ } else {
+ //printk(KERN_ALERT "%s video decode is already on\n", __func__);
+ }
+
+ break;
+ case OSPM_VIDEO_ENC_ISLAND:
+ if (!ospm_power_is_hw_on(OSPM_DISPLAY_ISLAND)) {
+ //printk(KERN_ALERT "%s power on display for video encode\n", __func__);
+ deviceID = gui32MRSTDisplayDeviceID;
+ ospm_resume_display(pdev);
+ psb_irq_preinstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND);
+ psb_irq_postinstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND);
+ } else {
+ //printk(KERN_ALERT "%s display is already on for video encode use\n", __func__);
+ }
+
+ if (!ospm_power_is_hw_on(OSPM_VIDEO_ENC_ISLAND)) {
+ //printk(KERN_ALERT "%s power on video encode\n", __func__);
+ deviceID = gui32MRSTTOPAZDeviceID;
+ ospm_power_island_up(OSPM_VIDEO_ENC_ISLAND);
+ ospm_runtime_pm_topaz_resume(gpDrmDevice);
+ psb_irq_preinstall_islands(gpDrmDevice, OSPM_VIDEO_ENC_ISLAND);
+ psb_irq_postinstall_islands(gpDrmDevice, OSPM_VIDEO_ENC_ISLAND);
+ } else {
+ //printk(KERN_ALERT "%s video decode is already on\n", __func__);
+ }
+#endif
+ break;
+
+ default:
+ printk(KERN_ALERT "%s unknown island !!!! \n", __func__);
+ break;
+ }
+
+ }
+
+ if (!ret)
+ printk(KERN_ALERT "ospm_power_using_hw_begin: forcing on %d failed\n", hw_island);
+
+ gbResumeInProgress = false;
+ }
+increase_count:
+ if (ret) {
+ switch (hw_island) {
+ case OSPM_GRAPHICS_ISLAND:
+ atomic_inc(&g_graphics_access_count);
+ break;
+ case OSPM_VIDEO_ENC_ISLAND:
+ atomic_inc(&g_videoenc_access_count);
+ break;
+ case OSPM_VIDEO_DEC_ISLAND:
+ atomic_inc(&g_videodec_access_count);
+ break;
+ case OSPM_DISPLAY_ISLAND:
+ atomic_inc(&g_display_access_count);
+ break;
+ }
+ } else {
+#ifdef CONFIG_PM_RUNTIME
+ /* decrement pm_runtime_refcount */
+ pm_runtime_put(&pdev->dev);
+#endif
+ }
+
+ if (!b_atomic && locked)
+ mutex_unlock(&g_ospm_mutex);
+
+ return ret;
+}
+
+
+/*
+ * ospm_power_using_hw_end
+ *
+ * Description: Notify PowerMgmt module that you are done accessing the
+ * specified island's hw so feel free to power it off. Note that this
+ * function doesn't actually power off the islands.
+ */
+void ospm_power_using_hw_end(int hw_island)
+{
+ switch (hw_island) {
+ case OSPM_GRAPHICS_ISLAND:
+ atomic_dec(&g_graphics_access_count);
+ break;
+ case OSPM_VIDEO_ENC_ISLAND:
+ atomic_dec(&g_videoenc_access_count);
+ break;
+ case OSPM_VIDEO_DEC_ISLAND:
+ atomic_dec(&g_videodec_access_count);
+ break;
+ case OSPM_DISPLAY_ISLAND:
+ atomic_dec(&g_display_access_count);
+ break;
+ }
+
+ //decrement runtime pm ref count
+ pm_runtime_put(&gpDrmDevice->pdev->dev);
+
+ WARN_ON(atomic_read(&g_graphics_access_count) < 0);
+ WARN_ON(atomic_read(&g_videoenc_access_count) < 0);
+ WARN_ON(atomic_read(&g_videodec_access_count) < 0);
+ WARN_ON(atomic_read(&g_display_access_count) < 0);
+}
+
+int ospm_runtime_pm_allow(struct drm_device * dev)
+{
+ struct drm_psb_private * dev_priv = dev->dev_private;
+ bool panel_on, panel_on2;
+
+ PSB_DEBUG_ENTRY("%s\n", __FUNCTION__);
+
+#ifdef OSPM_GFX_DPK
+ printk(KERN_ALERT "OSPM_GFX_DPK: %s \n", __func__);
+#endif
+ if (dev_priv->rpm_enabled)
+ return 0;
+
+ if (is_panel_vid_or_cmd(dev)) {
+ /*DPI panel*/
+ panel_on = dev_priv->dpi_panel_on;
+ panel_on2 = dev_priv->dpi_panel_on2;
+ } else {
+ /*DBI panel*/
+ panel_on = dev_priv->dbi_panel_on;
+ panel_on2 = dev_priv->dbi_panel_on2;
+ }
+
+ if (panel_on && panel_on2) {
+ pm_runtime_allow(&dev->pdev->dev);
+ dev_priv->rpm_enabled = 1;
+ DRM_INFO("Runtime PM enabled\n");
+ }
+
+ return 0;
+}
+
+void ospm_runtime_pm_forbid(struct drm_device * dev)
+{
+ struct drm_psb_private * dev_priv = dev->dev_private;
+
+ DRM_INFO("%s\n", __FUNCTION__);
+
+#ifdef OSPM_GFX_DPK
+ printk(KERN_ALERT "OSPM_GFX_DPK: %s \n", __func__);
+#endif
+
+ pm_runtime_forbid(&dev->pdev->dev);
+ dev_priv->rpm_enabled = 0;
+}
+
+int psb_runtime_suspend(struct device *dev)
+{
+ pm_message_t state;
+ int ret = 0;
+ state.event = 0;
+
+#ifdef OSPM_GFX_DPK
+ printk(KERN_ALERT "OSPM_GFX_DPK: %s \n", __func__);
+#endif
+ if (atomic_read(&g_graphics_access_count) || atomic_read(&g_videoenc_access_count)
+ || (gbdispstatus == true)
+ || atomic_read(&g_videodec_access_count) || atomic_read(&g_display_access_count)){
+#ifdef OSPM_GFX_DPK
+ printk(KERN_ALERT "OSPM_GFX_DPK: GFX: %d VEC: %d VED: %d DC: %d DSR: (N/A) \n", atomic_read(&g_graphics_access_count),
+ atomic_read(&g_videoenc_access_count), atomic_read(&g_videodec_access_count), atomic_read(&g_display_access_count));
+#endif
+ return -EBUSY;
+ }
+ else
+ ret = ospm_power_suspend(gpDrmDevice->pdev, state);
+
+ return ret;
+}
+
+int psb_runtime_resume(struct device *dev)
+{
+ //Notify HDMI Audio sub-system about the resume.
+#ifdef CONFIG_SND_INTELMID_HDMI_AUDIO
+ struct drm_psb_private* dev_priv = gpDrmDevice->dev_private;
+
+ if (dev_priv->had_pvt_data)
+ dev_priv->had_interface->resume(dev_priv->had_pvt_data);
+#endif
+ /*Nop for GFX*/
+ return 0;
+}
+
+int psb_runtime_idle(struct device *dev)
+{
+#ifdef CONFIG_SND_INTELMID_HDMI_AUDIO
+ struct drm_psb_private* dev_priv = gpDrmDevice->dev_private;
+ int hdmi_audio_busy = 0;
+ pm_event_t hdmi_audio_event;
+#endif
+
+#if 1
+ int msvdx_hw_busy = 0;
+ int topaz_hw_busy = 0;
+
+ msvdx_hw_busy = ospm_runtime_check_msvdx_hw_busy(gpDrmDevice);
+ topaz_hw_busy = ospm_runtime_check_topaz_hw_busy(gpDrmDevice);
+#endif
+
+#ifdef CONFIG_SND_INTELMID_HDMI_AUDIO
+ if(dev_priv->had_pvt_data){
+ hdmi_audio_event.event = 0;
+ hdmi_audio_busy = dev_priv->had_interface->suspend(dev_priv->had_pvt_data, hdmi_audio_event);
+ }
+#endif
+ /*printk (KERN_ALERT "lvds:%d,mipi:%d\n", dev_priv->is_lvds_on, dev_priv->is_mipi_on);*/
+ if (atomic_read(&g_graphics_access_count) || atomic_read(&g_videoenc_access_count)
+ || atomic_read(&g_videodec_access_count) || atomic_read(&g_display_access_count)
+ || (gbdispstatus == true)
+#ifdef CONFIG_SND_INTELMID_HDMI_AUDIO
+ || hdmi_audio_busy
+#endif
+
+#if 1
+ || (msvdx_hw_busy == 1)
+ || (topaz_hw_busy == 1))
+#else
+ )
+#endif
+ return 1;
+ else
+ return 0;
+}
+
--- /dev/null
+/**************************************************************************
+ * Copyright (c) 2009, Intel Corporation.
+ * All Rights Reserved.
+
+ * 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 (including the next
+ * paragraph) 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.
+ *
+ * Authors:
+ * Benjamin Defnet <benjamin.r.defnet@intel.com>
+ * Rajesh Poornachandran <rajesh.poornachandran@intel.com>
+ *
+ */
+#ifndef _PSB_POWERMGMT_H_
+#define _PSB_POWERMGMT_H_
+
+#include <linux/pci.h>
+#include <drm/drmP.h>
+#ifdef CONFIG_PM_RUNTIME
+#include <linux/pm_runtime.h>
+#endif
+
+#define OSPM_GRAPHICS_ISLAND 0x1
+#define OSPM_VIDEO_ENC_ISLAND 0x2
+#define OSPM_VIDEO_DEC_ISLAND 0x4
+#define OSPM_DISPLAY_ISLAND 0x8
+#define OSPM_GL3_CACHE_ISLAND 0x10
+#define OSPM_ISP_ISLAND 0x20
+#define OSPM_ALL_ISLANDS 0x3f
+
+/* IPC message and command defines used to enable/disable mipi panel voltages */
+#define IPC_MSG_PANEL_ON_OFF 0xE9
+#define IPC_CMD_PANEL_ON 1
+#define IPC_CMD_PANEL_OFF 0
+
+typedef enum _UHBUsage
+{
+ OSPM_UHB_ONLY_IF_ON = 0,
+ OSPM_UHB_FORCE_POWER_ON,
+} UHBUsage;
+
+//extern int psb_check_msvdx_idle(struct drm_device *dev);
+//extern int lnc_check_topaz_idle(struct drm_device *dev);
+/* Use these functions to power down video HW for D0i3 purpose */
+void ospm_apm_power_down_msvdx(struct drm_device *dev);
+void ospm_apm_power_down_topaz(struct drm_device *dev);
+
+void ospm_power_init(struct drm_device *dev);
+void ospm_power_uninit(void);
+
+
+/*
+ * OSPM will call these functions
+ */
+int ospm_power_suspend(struct pci_dev *pdev, pm_message_t state);
+int ospm_power_resume(struct pci_dev *pdev);
+
+/*
+ * These are the functions the driver should use to wrap all hw access
+ * (i.e. register reads and writes)
+ */
+bool ospm_power_using_hw_begin(int hw_island, UHBUsage usage);
+void ospm_power_using_hw_end(int hw_island);
+
+/*
+ * Use this function to do an instantaneous check for if the hw is on.
+ * Only use this in cases where you know the g_state_change_mutex
+ * is already held such as in irq install/uninstall and you need to
+ * prevent a deadlock situation. Otherwise use ospm_power_using_hw_begin().
+ */
+bool ospm_power_is_hw_on(int hw_islands);
+
+/*
+ * Power up/down different hw component rails/islands
+ */
+void ospm_power_island_down(int hw_islands);
+void ospm_power_island_up(int hw_islands);
+/*
+ * GFX-Runtime PM callbacks
+ */
+int psb_runtime_suspend(struct device *dev);
+int psb_runtime_resume(struct device *dev);
+int psb_runtime_idle(struct device *dev);
+int ospm_runtime_pm_allow(struct drm_device * dev);
+void ospm_runtime_pm_forbid(struct drm_device * dev);
+
+#ifdef CONFIG_PM_RUNTIME
+void psb_runtimepm_wq_handler(struct work_struct *work);
+#endif
+
+extern struct drm_device *gpDrmDevice;
+extern bool gbgfxsuspended;
+extern bool gbdispstatus;
+#ifdef CONFIG_PM_RUNTIME
+extern int enable_gfx_rtpm;
+#endif
+
+#endif /*_PSB_POWERMGMT_H_*/
--- /dev/null
+/*
+ * Copyright (c) 2009, Intel Corporation.
+ *
+ * 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 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.
+ *
+ */
+
+#include "psb_pvr_glue.h"
+
+/**
+ * FIXME: should NOT use these file under env/linux directly
+ */
+#include "mm.h"
+
+int psb_get_meminfo_by_handle(IMG_HANDLE hKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO **ppsKernelMemInfo)
+{
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = IMG_NULL;
+ PVRSRV_PER_PROCESS_DATA *psPerProc = IMG_NULL;
+ PVRSRV_ERROR eError;
+
+ psPerProc = PVRSRVPerProcessData(OSGetCurrentProcessIDKM());
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID *)&psKernelMemInfo,
+ hKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK) {
+ DRM_ERROR("Cannot find kernel meminfo for handle 0x%x\n",
+ (IMG_UINT32)hKernelMemInfo);
+ return -EINVAL;
+ }
+
+ *ppsKernelMemInfo = psKernelMemInfo;
+
+ DRM_DEBUG("Got Kernel MemInfo for handle %p\n", hKernelMemInfo);
+
+ return 0;
+}
+
+IMG_UINT32 psb_get_tgid(void)
+{
+ return OSGetCurrentProcessIDKM();
+}
+
+int psb_get_pages_by_mem_handle(IMG_HANDLE hOSMemHandle, struct page ***pages)
+{
+ LinuxMemArea *psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+ struct page **page_list;
+
+ if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_ALLOC_PAGES) {
+ DRM_ERROR("MemArea type is not LINUX_MEM_AREA_ALLOC_PAGES\n");
+ return -EINVAL;
+ }
+
+ page_list = psLinuxMemArea->uData.sPageList.pvPageList;
+ if (!page_list) {
+ DRM_DEBUG("Page List is NULL\n");
+ return -ENOMEM;
+ }
+
+ *pages = page_list;
+ return 0;
+}
--- /dev/null
+/*
+ * Copyright (c) 2009, Intel Corporation.
+ *
+ * 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 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.
+ *
+ */
+
+#include "psb_drv.h"
+#include "services_headers.h"
+
+extern int psb_get_meminfo_by_handle(IMG_HANDLE hKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO **ppsKernelMemInfo);
+extern IMG_UINT32 psb_get_tgid(void);
+extern int psb_get_pages_by_mem_handle(IMG_HANDLE hOSMemHandle,
+ struct page ***pages);
--- /dev/null
+/**************************************************************************
+ *
+ * Copyright (c) (2005-2007) Imagination Technologies Limited.
+ * Copyright (c) 2007, Intel Corporation.
+ * 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 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..
+ *
+ **************************************************************************/
+
+#ifndef _PSB_REG_H_
+#define _PSB_REG_H_
+
+#define PSB_CR_CLKGATECTL 0x0000
+#define _PSB_C_CLKGATECTL_AUTO_MAN_REG (1 << 24)
+#define _PSB_C_CLKGATECTL_USE_CLKG_SHIFT (20)
+#define _PSB_C_CLKGATECTL_USE_CLKG_MASK (0x3 << 20)
+#define _PSB_C_CLKGATECTL_DPM_CLKG_SHIFT (16)
+#define _PSB_C_CLKGATECTL_DPM_CLKG_MASK (0x3 << 16)
+#define _PSB_C_CLKGATECTL_TA_CLKG_SHIFT (12)
+#define _PSB_C_CLKGATECTL_TA_CLKG_MASK (0x3 << 12)
+#define _PSB_C_CLKGATECTL_TSP_CLKG_SHIFT (8)
+#define _PSB_C_CLKGATECTL_TSP_CLKG_MASK (0x3 << 8)
+#define _PSB_C_CLKGATECTL_ISP_CLKG_SHIFT (4)
+#define _PSB_C_CLKGATECTL_ISP_CLKG_MASK (0x3 << 4)
+#define _PSB_C_CLKGATECTL_2D_CLKG_SHIFT (0)
+#define _PSB_C_CLKGATECTL_2D_CLKG_MASK (0x3 << 0)
+#define _PSB_C_CLKGATECTL_CLKG_ENABLED (0)
+#define _PSB_C_CLKGATECTL_CLKG_DISABLED (1)
+#define _PSB_C_CLKGATECTL_CLKG_AUTO (2)
+
+#define PSB_CR_CORE_ID 0x0010
+#define _PSB_CC_ID_ID_SHIFT (16)
+#define _PSB_CC_ID_ID_MASK (0xFFFF << 16)
+#define _PSB_CC_ID_CONFIG_SHIFT (0)
+#define _PSB_CC_ID_CONFIG_MASK (0xFFFF << 0)
+
+#define PSB_CR_CORE_REVISION 0x0014
+#define _PSB_CC_REVISION_DESIGNER_SHIFT (24)
+#define _PSB_CC_REVISION_DESIGNER_MASK (0xFF << 24)
+#define _PSB_CC_REVISION_MAJOR_SHIFT (16)
+#define _PSB_CC_REVISION_MAJOR_MASK (0xFF << 16)
+#define _PSB_CC_REVISION_MINOR_SHIFT (8)
+#define _PSB_CC_REVISION_MINOR_MASK (0xFF << 8)
+#define _PSB_CC_REVISION_MAINTENANCE_SHIFT (0)
+#define _PSB_CC_REVISION_MAINTENANCE_MASK (0xFF << 0)
+
+#define PSB_CR_DESIGNER_REV_FIELD1 0x0018
+
+#define PSB_CR_SOFT_RESET 0x0080
+#define _PSB_CS_RESET_TSP_RESET (1 << 6)
+#define _PSB_CS_RESET_ISP_RESET (1 << 5)
+#define _PSB_CS_RESET_USE_RESET (1 << 4)
+#define _PSB_CS_RESET_TA_RESET (1 << 3)
+#define _PSB_CS_RESET_DPM_RESET (1 << 2)
+#define _PSB_CS_RESET_TWOD_RESET (1 << 1)
+#define _PSB_CS_RESET_BIF_RESET (1 << 0)
+
+#define PSB_CR_DESIGNER_REV_FIELD2 0x001C
+
+#define PSB_CR_EVENT_HOST_ENABLE2 0x0110
+
+#define PSB_CR_EVENT_STATUS2 0x0118
+
+#define PSB_CR_EVENT_HOST_CLEAR2 0x0114
+#define _PSB_CE2_BIF_REQUESTER_FAULT (1 << 4)
+
+#define PSB_CR_EVENT_STATUS 0x012C
+
+#define PSB_CR_EVENT_HOST_ENABLE 0x0130
+
+#define PSB_CR_EVENT_HOST_CLEAR 0x0134
+#define _PSB_CE_MASTER_INTERRUPT (1 << 31)
+#define _PSB_CE_TA_DPM_FAULT (1 << 28)
+#define _PSB_CE_TWOD_COMPLETE (1 << 27)
+#define _PSB_CE_DPM_OUT_OF_MEMORY_ZLS (1 << 25)
+#define _PSB_CE_DPM_TA_MEM_FREE (1 << 24)
+#define _PSB_CE_PIXELBE_END_RENDER (1 << 18)
+#define _PSB_CE_SW_EVENT (1 << 14)
+#define _PSB_CE_TA_FINISHED (1 << 13)
+#define _PSB_CE_TA_TERMINATE (1 << 12)
+#define _PSB_CE_DPM_REACHED_MEM_THRESH (1 << 3)
+#define _PSB_CE_DPM_OUT_OF_MEMORY_GBL (1 << 2)
+#define _PSB_CE_DPM_OUT_OF_MEMORY_MT (1 << 1)
+#define _PSB_CE_DPM_3D_MEM_FREE (1 << 0)
+
+
+#define PSB_USE_OFFSET_MASK 0x0007FFFF
+#define PSB_USE_OFFSET_SIZE (PSB_USE_OFFSET_MASK + 1)
+#define PSB_CR_USE_CODE_BASE0 0x0A0C
+#define PSB_CR_USE_CODE_BASE1 0x0A10
+#define PSB_CR_USE_CODE_BASE2 0x0A14
+#define PSB_CR_USE_CODE_BASE3 0x0A18
+#define PSB_CR_USE_CODE_BASE4 0x0A1C
+#define PSB_CR_USE_CODE_BASE5 0x0A20
+#define PSB_CR_USE_CODE_BASE6 0x0A24
+#define PSB_CR_USE_CODE_BASE7 0x0A28
+#define PSB_CR_USE_CODE_BASE8 0x0A2C
+#define PSB_CR_USE_CODE_BASE9 0x0A30
+#define PSB_CR_USE_CODE_BASE10 0x0A34
+#define PSB_CR_USE_CODE_BASE11 0x0A38
+#define PSB_CR_USE_CODE_BASE12 0x0A3C
+#define PSB_CR_USE_CODE_BASE13 0x0A40
+#define PSB_CR_USE_CODE_BASE14 0x0A44
+#define PSB_CR_USE_CODE_BASE15 0x0A48
+#define PSB_CR_USE_CODE_BASE(_i) (0x0A0C + ((_i) << 2))
+#define _PSB_CUC_BASE_DM_SHIFT (25)
+#define _PSB_CUC_BASE_DM_MASK (0x3 << 25)
+#define _PSB_CUC_BASE_ADDR_SHIFT (0) /* 1024-bit aligned address? */
+#define _PSB_CUC_BASE_ADDR_ALIGNSHIFT (7)
+#define _PSB_CUC_BASE_ADDR_MASK (0x1FFFFFF << 0)
+#define _PSB_CUC_DM_VERTEX (0)
+#define _PSB_CUC_DM_PIXEL (1)
+#define _PSB_CUC_DM_RESERVED (2)
+#define _PSB_CUC_DM_EDM (3)
+
+#define PSB_CR_PDS_EXEC_BASE 0x0AB8
+#define _PSB_CR_PDS_EXEC_BASE_ADDR_SHIFT (20) /* 1MB aligned address */
+#define _PSB_CR_PDS_EXEC_BASE_ADDR_ALIGNSHIFT (20)
+
+#define PSB_CR_EVENT_KICKER 0x0AC4
+#define _PSB_CE_KICKER_ADDRESS_SHIFT (4) /* 128-bit aligned address */
+
+#define PSB_CR_EVENT_KICK 0x0AC8
+#define _PSB_CE_KICK_NOW (1 << 0)
+
+
+#define PSB_CR_BIF_DIR_LIST_BASE1 0x0C38
+
+#define PSB_CR_BIF_CTRL 0x0C00
+#define _PSB_CB_CTRL_CLEAR_FAULT (1 << 4)
+#define _PSB_CB_CTRL_INVALDC (1 << 3)
+#define _PSB_CB_CTRL_FLUSH (1 << 2)
+
+#define PSB_CR_BIF_INT_STAT 0x0C04
+
+#define PSB_CR_BIF_FAULT 0x0C08
+#define _PSB_CBI_STAT_PF_N_RW (1 << 14)
+#define _PSB_CBI_STAT_FAULT_SHIFT (0)
+#define _PSB_CBI_STAT_FAULT_MASK (0x3FFF << 0)
+#define _PSB_CBI_STAT_FAULT_CACHE (1 << 1)
+#define _PSB_CBI_STAT_FAULT_TA (1 << 2)
+#define _PSB_CBI_STAT_FAULT_VDM (1 << 3)
+#define _PSB_CBI_STAT_FAULT_2D (1 << 4)
+#define _PSB_CBI_STAT_FAULT_PBE (1 << 5)
+#define _PSB_CBI_STAT_FAULT_TSP (1 << 6)
+#define _PSB_CBI_STAT_FAULT_ISP (1 << 7)
+#define _PSB_CBI_STAT_FAULT_USSEPDS (1 << 8)
+#define _PSB_CBI_STAT_FAULT_HOST (1 << 9)
+
+#define PSB_CR_BIF_BANK0 0x0C78
+
+#define PSB_CR_BIF_BANK1 0x0C7C
+
+#define PSB_CR_BIF_DIR_LIST_BASE0 0x0C84
+
+#define PSB_CR_BIF_TWOD_REQ_BASE 0x0C88
+#define PSB_CR_BIF_3D_REQ_BASE 0x0CAC
+
+#define PSB_CR_2D_SOCIF 0x0E18
+#define _PSB_C2_SOCIF_FREESPACE_SHIFT (0)
+#define _PSB_C2_SOCIF_FREESPACE_MASK (0xFF << 0)
+#define _PSB_C2_SOCIF_EMPTY (0x80 << 0)
+
+#define PSB_CR_2D_BLIT_STATUS 0x0E04
+#define _PSB_C2B_STATUS_BUSY (1 << 24)
+#define _PSB_C2B_STATUS_COMPLETE_SHIFT (0)
+#define _PSB_C2B_STATUS_COMPLETE_MASK (0xFFFFFF << 0)
+
+/*
+ * 2D defs.
+ */
+
+/*
+ * 2D Slave Port Data : Block Header's Object Type
+ */
+
+#define PSB_2D_CLIP_BH (0x00000000)
+#define PSB_2D_PAT_BH (0x10000000)
+#define PSB_2D_CTRL_BH (0x20000000)
+#define PSB_2D_SRC_OFF_BH (0x30000000)
+#define PSB_2D_MASK_OFF_BH (0x40000000)
+#define PSB_2D_RESERVED1_BH (0x50000000)
+#define PSB_2D_RESERVED2_BH (0x60000000)
+#define PSB_2D_FENCE_BH (0x70000000)
+#define PSB_2D_BLIT_BH (0x80000000)
+#define PSB_2D_SRC_SURF_BH (0x90000000)
+#define PSB_2D_DST_SURF_BH (0xA0000000)
+#define PSB_2D_PAT_SURF_BH (0xB0000000)
+#define PSB_2D_SRC_PAL_BH (0xC0000000)
+#define PSB_2D_PAT_PAL_BH (0xD0000000)
+#define PSB_2D_MASK_SURF_BH (0xE0000000)
+#define PSB_2D_FLUSH_BH (0xF0000000)
+
+/*
+ * Clip Definition block (PSB_2D_CLIP_BH)
+ */
+#define PSB_2D_CLIPCOUNT_MAX (1)
+#define PSB_2D_CLIPCOUNT_MASK (0x00000000)
+#define PSB_2D_CLIPCOUNT_CLRMASK (0xFFFFFFFF)
+#define PSB_2D_CLIPCOUNT_SHIFT (0)
+/* clip rectangle min & max */
+#define PSB_2D_CLIP_XMAX_MASK (0x00FFF000)
+#define PSB_2D_CLIP_XMAX_CLRMASK (0xFF000FFF)
+#define PSB_2D_CLIP_XMAX_SHIFT (12)
+#define PSB_2D_CLIP_XMIN_MASK (0x00000FFF)
+#define PSB_2D_CLIP_XMIN_CLRMASK (0x00FFF000)
+#define PSB_2D_CLIP_XMIN_SHIFT (0)
+/* clip rectangle offset */
+#define PSB_2D_CLIP_YMAX_MASK (0x00FFF000)
+#define PSB_2D_CLIP_YMAX_CLRMASK (0xFF000FFF)
+#define PSB_2D_CLIP_YMAX_SHIFT (12)
+#define PSB_2D_CLIP_YMIN_MASK (0x00000FFF)
+#define PSB_2D_CLIP_YMIN_CLRMASK (0x00FFF000)
+#define PSB_2D_CLIP_YMIN_SHIFT (0)
+
+/*
+ * Pattern Control (PSB_2D_PAT_BH)
+ */
+#define PSB_2D_PAT_HEIGHT_MASK (0x0000001F)
+#define PSB_2D_PAT_HEIGHT_SHIFT (0)
+#define PSB_2D_PAT_WIDTH_MASK (0x000003E0)
+#define PSB_2D_PAT_WIDTH_SHIFT (5)
+#define PSB_2D_PAT_YSTART_MASK (0x00007C00)
+#define PSB_2D_PAT_YSTART_SHIFT (10)
+#define PSB_2D_PAT_XSTART_MASK (0x000F8000)
+#define PSB_2D_PAT_XSTART_SHIFT (15)
+
+/*
+ * 2D Control block (PSB_2D_CTRL_BH)
+ */
+/* Present Flags */
+#define PSB_2D_SRCCK_CTRL (0x00000001)
+#define PSB_2D_DSTCK_CTRL (0x00000002)
+#define PSB_2D_ALPHA_CTRL (0x00000004)
+/* Colour Key Colour (SRC/DST)*/
+#define PSB_2D_CK_COL_MASK (0xFFFFFFFF)
+#define PSB_2D_CK_COL_CLRMASK (0x00000000)
+#define PSB_2D_CK_COL_SHIFT (0)
+/* Colour Key Mask (SRC/DST)*/
+#define PSB_2D_CK_MASK_MASK (0xFFFFFFFF)
+#define PSB_2D_CK_MASK_CLRMASK (0x00000000)
+#define PSB_2D_CK_MASK_SHIFT (0)
+/* Alpha Control (Alpha/RGB)*/
+#define PSB_2D_GBLALPHA_MASK (0x000FF000)
+#define PSB_2D_GBLALPHA_CLRMASK (0xFFF00FFF)
+#define PSB_2D_GBLALPHA_SHIFT (12)
+#define PSB_2D_SRCALPHA_OP_MASK (0x00700000)
+#define PSB_2D_SRCALPHA_OP_CLRMASK (0xFF8FFFFF)
+#define PSB_2D_SRCALPHA_OP_SHIFT (20)
+#define PSB_2D_SRCALPHA_OP_ONE (0x00000000)
+#define PSB_2D_SRCALPHA_OP_SRC (0x00100000)
+#define PSB_2D_SRCALPHA_OP_DST (0x00200000)
+#define PSB_2D_SRCALPHA_OP_SG (0x00300000)
+#define PSB_2D_SRCALPHA_OP_DG (0x00400000)
+#define PSB_2D_SRCALPHA_OP_GBL (0x00500000)
+#define PSB_2D_SRCALPHA_OP_ZERO (0x00600000)
+#define PSB_2D_SRCALPHA_INVERT (0x00800000)
+#define PSB_2D_SRCALPHA_INVERT_CLR (0xFF7FFFFF)
+#define PSB_2D_DSTALPHA_OP_MASK (0x07000000)
+#define PSB_2D_DSTALPHA_OP_CLRMASK (0xF8FFFFFF)
+#define PSB_2D_DSTALPHA_OP_SHIFT (24)
+#define PSB_2D_DSTALPHA_OP_ONE (0x00000000)
+#define PSB_2D_DSTALPHA_OP_SRC (0x01000000)
+#define PSB_2D_DSTALPHA_OP_DST (0x02000000)
+#define PSB_2D_DSTALPHA_OP_SG (0x03000000)
+#define PSB_2D_DSTALPHA_OP_DG (0x04000000)
+#define PSB_2D_DSTALPHA_OP_GBL (0x05000000)
+#define PSB_2D_DSTALPHA_OP_ZERO (0x06000000)
+#define PSB_2D_DSTALPHA_INVERT (0x08000000)
+#define PSB_2D_DSTALPHA_INVERT_CLR (0xF7FFFFFF)
+
+#define PSB_2D_PRE_MULTIPLICATION_ENABLE (0x10000000)
+#define PSB_2D_PRE_MULTIPLICATION_CLRMASK (0xEFFFFFFF)
+#define PSB_2D_ZERO_SOURCE_ALPHA_ENABLE (0x20000000)
+#define PSB_2D_ZERO_SOURCE_ALPHA_CLRMASK (0xDFFFFFFF)
+
+/*
+ *Source Offset (PSB_2D_SRC_OFF_BH)
+ */
+#define PSB_2D_SRCOFF_XSTART_MASK ((0x00000FFF) << 12)
+#define PSB_2D_SRCOFF_XSTART_SHIFT (12)
+#define PSB_2D_SRCOFF_YSTART_MASK (0x00000FFF)
+#define PSB_2D_SRCOFF_YSTART_SHIFT (0)
+
+/*
+ * Mask Offset (PSB_2D_MASK_OFF_BH)
+ */
+#define PSB_2D_MASKOFF_XSTART_MASK ((0x00000FFF) << 12)
+#define PSB_2D_MASKOFF_XSTART_SHIFT (12)
+#define PSB_2D_MASKOFF_YSTART_MASK (0x00000FFF)
+#define PSB_2D_MASKOFF_YSTART_SHIFT (0)
+
+/*
+ * 2D Fence (see PSB_2D_FENCE_BH): bits 0:27 are ignored
+ */
+
+/*
+ *Blit Rectangle (PSB_2D_BLIT_BH)
+ */
+
+#define PSB_2D_ROT_MASK (3<<25)
+#define PSB_2D_ROT_CLRMASK (~PSB_2D_ROT_MASK)
+#define PSB_2D_ROT_NONE (0<<25)
+#define PSB_2D_ROT_90DEGS (1<<25)
+#define PSB_2D_ROT_180DEGS (2<<25)
+#define PSB_2D_ROT_270DEGS (3<<25)
+
+#define PSB_2D_COPYORDER_MASK (3<<23)
+#define PSB_2D_COPYORDER_CLRMASK (~PSB_2D_COPYORDER_MASK)
+#define PSB_2D_COPYORDER_TL2BR (0<<23)
+#define PSB_2D_COPYORDER_BR2TL (1<<23)
+#define PSB_2D_COPYORDER_TR2BL (2<<23)
+#define PSB_2D_COPYORDER_BL2TR (3<<23)
+
+#define PSB_2D_DSTCK_CLRMASK (0xFF9FFFFF)
+#define PSB_2D_DSTCK_DISABLE (0x00000000)
+#define PSB_2D_DSTCK_PASS (0x00200000)
+#define PSB_2D_DSTCK_REJECT (0x00400000)
+
+#define PSB_2D_SRCCK_CLRMASK (0xFFE7FFFF)
+#define PSB_2D_SRCCK_DISABLE (0x00000000)
+#define PSB_2D_SRCCK_PASS (0x00080000)
+#define PSB_2D_SRCCK_REJECT (0x00100000)
+
+#define PSB_2D_CLIP_ENABLE (0x00040000)
+
+#define PSB_2D_ALPHA_ENABLE (0x00020000)
+
+#define PSB_2D_PAT_CLRMASK (0xFFFEFFFF)
+#define PSB_2D_PAT_MASK (0x00010000)
+#define PSB_2D_USE_PAT (0x00010000)
+#define PSB_2D_USE_FILL (0x00000000)
+/*
+ * Tungsten Graphics note on rop codes: If rop A and rop B are
+ * identical, the mask surface will not be read and need not be
+ * set up.
+ */
+
+#define PSB_2D_ROP3B_MASK (0x0000FF00)
+#define PSB_2D_ROP3B_CLRMASK (0xFFFF00FF)
+#define PSB_2D_ROP3B_SHIFT (8)
+/* rop code A */
+#define PSB_2D_ROP3A_MASK (0x000000FF)
+#define PSB_2D_ROP3A_CLRMASK (0xFFFFFF00)
+#define PSB_2D_ROP3A_SHIFT (0)
+
+#define PSB_2D_ROP4_MASK (0x0000FFFF)
+/*
+ * DWORD0: (Only pass if Pattern control == Use Fill Colour)
+ * Fill Colour RGBA8888
+ */
+#define PSB_2D_FILLCOLOUR_MASK (0xFFFFFFFF)
+#define PSB_2D_FILLCOLOUR_SHIFT (0)
+/*
+ * DWORD1: (Always Present)
+ * X Start (Dest)
+ * Y Start (Dest)
+ */
+#define PSB_2D_DST_XSTART_MASK (0x00FFF000)
+#define PSB_2D_DST_XSTART_CLRMASK (0xFF000FFF)
+#define PSB_2D_DST_XSTART_SHIFT (12)
+#define PSB_2D_DST_YSTART_MASK (0x00000FFF)
+#define PSB_2D_DST_YSTART_CLRMASK (0xFFFFF000)
+#define PSB_2D_DST_YSTART_SHIFT (0)
+/*
+ * DWORD2: (Always Present)
+ * X Size (Dest)
+ * Y Size (Dest)
+ */
+#define PSB_2D_DST_XSIZE_MASK (0x00FFF000)
+#define PSB_2D_DST_XSIZE_CLRMASK (0xFF000FFF)
+#define PSB_2D_DST_XSIZE_SHIFT (12)
+#define PSB_2D_DST_YSIZE_MASK (0x00000FFF)
+#define PSB_2D_DST_YSIZE_CLRMASK (0xFFFFF000)
+#define PSB_2D_DST_YSIZE_SHIFT (0)
+
+/*
+ * Source Surface (PSB_2D_SRC_SURF_BH)
+ */
+/*
+ * WORD 0
+ */
+
+#define PSB_2D_SRC_FORMAT_MASK (0x00078000)
+#define PSB_2D_SRC_1_PAL (0x00000000)
+#define PSB_2D_SRC_2_PAL (0x00008000)
+#define PSB_2D_SRC_4_PAL (0x00010000)
+#define PSB_2D_SRC_8_PAL (0x00018000)
+#define PSB_2D_SRC_8_ALPHA (0x00020000)
+#define PSB_2D_SRC_4_ALPHA (0x00028000)
+#define PSB_2D_SRC_332RGB (0x00030000)
+#define PSB_2D_SRC_4444ARGB (0x00038000)
+#define PSB_2D_SRC_555RGB (0x00040000)
+#define PSB_2D_SRC_1555ARGB (0x00048000)
+#define PSB_2D_SRC_565RGB (0x00050000)
+#define PSB_2D_SRC_0888ARGB (0x00058000)
+#define PSB_2D_SRC_8888ARGB (0x00060000)
+#define PSB_2D_SRC_8888UYVY (0x00068000)
+#define PSB_2D_SRC_RESERVED (0x00070000)
+#define PSB_2D_SRC_1555ARGB_LOOKUP (0x00078000)
+
+
+#define PSB_2D_SRC_STRIDE_MASK (0x00007FFF)
+#define PSB_2D_SRC_STRIDE_CLRMASK (0xFFFF8000)
+#define PSB_2D_SRC_STRIDE_SHIFT (0)
+/*
+ * WORD 1 - Base Address
+ */
+#define PSB_2D_SRC_ADDR_MASK (0x0FFFFFFC)
+#define PSB_2D_SRC_ADDR_CLRMASK (0x00000003)
+#define PSB_2D_SRC_ADDR_SHIFT (2)
+#define PSB_2D_SRC_ADDR_ALIGNSHIFT (2)
+
+/*
+ * Pattern Surface (PSB_2D_PAT_SURF_BH)
+ */
+/*
+ * WORD 0
+ */
+
+#define PSB_2D_PAT_FORMAT_MASK (0x00078000)
+#define PSB_2D_PAT_1_PAL (0x00000000)
+#define PSB_2D_PAT_2_PAL (0x00008000)
+#define PSB_2D_PAT_4_PAL (0x00010000)
+#define PSB_2D_PAT_8_PAL (0x00018000)
+#define PSB_2D_PAT_8_ALPHA (0x00020000)
+#define PSB_2D_PAT_4_ALPHA (0x00028000)
+#define PSB_2D_PAT_332RGB (0x00030000)
+#define PSB_2D_PAT_4444ARGB (0x00038000)
+#define PSB_2D_PAT_555RGB (0x00040000)
+#define PSB_2D_PAT_1555ARGB (0x00048000)
+#define PSB_2D_PAT_565RGB (0x00050000)
+#define PSB_2D_PAT_0888ARGB (0x00058000)
+#define PSB_2D_PAT_8888ARGB (0x00060000)
+
+#define PSB_2D_PAT_STRIDE_MASK (0x00007FFF)
+#define PSB_2D_PAT_STRIDE_CLRMASK (0xFFFF8000)
+#define PSB_2D_PAT_STRIDE_SHIFT (0)
+/*
+ * WORD 1 - Base Address
+ */
+#define PSB_2D_PAT_ADDR_MASK (0x0FFFFFFC)
+#define PSB_2D_PAT_ADDR_CLRMASK (0x00000003)
+#define PSB_2D_PAT_ADDR_SHIFT (2)
+#define PSB_2D_PAT_ADDR_ALIGNSHIFT (2)
+
+/*
+ * Destination Surface (PSB_2D_DST_SURF_BH)
+ */
+/*
+ * WORD 0
+ */
+
+#define PSB_2D_DST_FORMAT_MASK (0x00078000)
+#define PSB_2D_DST_332RGB (0x00030000)
+#define PSB_2D_DST_4444ARGB (0x00038000)
+#define PSB_2D_DST_555RGB (0x00040000)
+#define PSB_2D_DST_1555ARGB (0x00048000)
+#define PSB_2D_DST_565RGB (0x00050000)
+#define PSB_2D_DST_0888ARGB (0x00058000)
+#define PSB_2D_DST_8888ARGB (0x00060000)
+#define PSB_2D_DST_8888AYUV (0x00070000)
+
+#define PSB_2D_DST_STRIDE_MASK (0x00007FFF)
+#define PSB_2D_DST_STRIDE_CLRMASK (0xFFFF8000)
+#define PSB_2D_DST_STRIDE_SHIFT (0)
+/*
+ * WORD 1 - Base Address
+ */
+#define PSB_2D_DST_ADDR_MASK (0x0FFFFFFC)
+#define PSB_2D_DST_ADDR_CLRMASK (0x00000003)
+#define PSB_2D_DST_ADDR_SHIFT (2)
+#define PSB_2D_DST_ADDR_ALIGNSHIFT (2)
+
+/*
+ * Mask Surface (PSB_2D_MASK_SURF_BH)
+ */
+/*
+ * WORD 0
+ */
+#define PSB_2D_MASK_STRIDE_MASK (0x00007FFF)
+#define PSB_2D_MASK_STRIDE_CLRMASK (0xFFFF8000)
+#define PSB_2D_MASK_STRIDE_SHIFT (0)
+/*
+ * WORD 1 - Base Address
+ */
+#define PSB_2D_MASK_ADDR_MASK (0x0FFFFFFC)
+#define PSB_2D_MASK_ADDR_CLRMASK (0x00000003)
+#define PSB_2D_MASK_ADDR_SHIFT (2)
+#define PSB_2D_MASK_ADDR_ALIGNSHIFT (2)
+
+/*
+ * Source Palette (PSB_2D_SRC_PAL_BH)
+ */
+
+#define PSB_2D_SRCPAL_ADDR_SHIFT (0)
+#define PSB_2D_SRCPAL_ADDR_CLRMASK (0xF0000007)
+#define PSB_2D_SRCPAL_ADDR_MASK (0x0FFFFFF8)
+#define PSB_2D_SRCPAL_BYTEALIGN (1024)
+
+/*
+ * Pattern Palette (PSB_2D_PAT_PAL_BH)
+ */
+
+#define PSB_2D_PATPAL_ADDR_SHIFT (0)
+#define PSB_2D_PATPAL_ADDR_CLRMASK (0xF0000007)
+#define PSB_2D_PATPAL_ADDR_MASK (0x0FFFFFF8)
+#define PSB_2D_PATPAL_BYTEALIGN (1024)
+
+/*
+ * Rop3 Codes (2 LS bytes)
+ */
+
+#define PSB_2D_ROP3_SRCCOPY (0xCCCC)
+#define PSB_2D_ROP3_PATCOPY (0xF0F0)
+#define PSB_2D_ROP3_WHITENESS (0xFFFF)
+#define PSB_2D_ROP3_BLACKNESS (0x0000)
+#define PSB_2D_ROP3_SRC (0xCC)
+#define PSB_2D_ROP3_PAT (0xF0)
+#define PSB_2D_ROP3_DST (0xAA)
+
+
+/*
+ * Sizes.
+ */
+
+#define PSB_SCENE_HW_COOKIE_SIZE 16
+#define PSB_TA_MEM_HW_COOKIE_SIZE 16
+
+/*
+ * Scene stuff.
+ */
+
+#define PSB_NUM_HW_SCENES 2
+
+/*
+ * Scheduler completion actions.
+ */
+
+#define PSB_RASTER_BLOCK 0
+#define PSB_RASTER 1
+#define PSB_RETURN 2
+#define PSB_TA 3
+
+
+/*Power management*/
+#define PSB_PUNIT_PORT 0x04
+#define PSB_OSPMBA 0x78
+#define PSB_APMBA 0x7a
+#define PSB_APM_CMD 0x0
+#define PSB_APM_STS 0x04
+#define PSB_PWRGT_VID_ENC_MASK 0x30
+#define PSB_PWRGT_VID_DEC_MASK 0xc
+#define PSB_PWRGT_GL3_MASK 0xc0
+
+#define PSB_PM_SSC 0x20
+#define PSB_PM_SSS 0x30
+#define PSB_PWRGT_DISPLAY_MASK 0xc /*on a different BA than video/gfx*/
+#define MDFLD_PWRGT_DISPLAY_A_CNTR 0x0000000c
+#define MDFLD_PWRGT_DISPLAY_B_CNTR 0x0000c000
+#define MDFLD_PWRGT_DISPLAY_C_CNTR 0x00030000
+#define MDFLD_PWRGT_DISP_MIPI_CNTR 0x000c0000
+#define MDFLD_PWRGT_DISPLAY_CNTR (MDFLD_PWRGT_DISPLAY_A_CNTR | MDFLD_PWRGT_DISPLAY_B_CNTR | MDFLD_PWRGT_DISPLAY_C_CNTR | MDFLD_PWRGT_DISP_MIPI_CNTR)// 0x000fc00c
+// Display SSS register bits are different in A0 vs. B0
+#define PSB_PWRGT_ISP_MASK 0xc00
+#define PSB_PWRGT_GFX_MASK 0x3
+#define MDFLD_PWRGT_DISPLAY_A_STS 0x000000c0
+#define MDFLD_PWRGT_DISPLAY_B_STS 0x00000300
+#define MDFLD_PWRGT_DISPLAY_C_STS 0x00000c00
+#define MDFLD_PWRGT_DISPLAY_A_STS_B0 0x0000000c
+#define MDFLD_PWRGT_DISPLAY_B_STS_B0 0x0000c000
+#define MDFLD_PWRGT_DISPLAY_C_STS_B0 0x00030000
+#define MDFLD_PWRGT_DISP_MIPI_STS 0x000c0000
+#define MDFLD_PWRGT_DISPLAY_STS_A0 (MDFLD_PWRGT_DISPLAY_A_STS | MDFLD_PWRGT_DISPLAY_B_STS | MDFLD_PWRGT_DISPLAY_C_STS | MDFLD_PWRGT_DISP_MIPI_STS)// 0x000fc00c
+#define MDFLD_PWRGT_DISPLAY_STS_B0 (MDFLD_PWRGT_DISPLAY_A_STS_B0 | MDFLD_PWRGT_DISPLAY_B_STS_B0 | MDFLD_PWRGT_DISPLAY_C_STS_B0 | MDFLD_PWRGT_DISP_MIPI_STS)// 0x000fc00c
+#endif
--- /dev/null
+/**************************************************************************
+ * Copyright (c) 2007, Intel Corporation.
+ *
+ * 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 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.
+ *
+ * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
+ **************************************************************************/
+
+#include <drm/drmP.h>
+#include "psb_drv.h"
+#include "psb_reg.h"
+#include "psb_intel_reg.h"
+#include "psb_msvdx.h"
+#include "pnw_topaz.h"
+#include <linux/spinlock.h>
+
+void psb_msvdx_flush_cmd_queue(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct psb_msvdx_cmd_queue *msvdx_cmd;
+ struct list_head *list, *next;
+ struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+
+ /*Flush the msvdx cmd queue and signal all fences in the queue */
+ list_for_each_safe(list, next, &msvdx_priv->msvdx_queue) {
+ msvdx_cmd =
+ list_entry(list, struct psb_msvdx_cmd_queue, head);
+ PSB_DEBUG_GENERAL("MSVDXQUE: flushing sequence:%d\n",
+ msvdx_cmd->sequence);
+ msvdx_priv->msvdx_current_sequence = msvdx_cmd->sequence;
+ psb_fence_error(dev, PSB_ENGINE_VIDEO,
+ msvdx_priv->msvdx_current_sequence,
+ _PSB_FENCE_TYPE_EXE, DRM_CMD_HANG);
+ list_del(list);
+ kfree(msvdx_cmd->cmd);
+ kfree(msvdx_cmd
+ );
+ }
+}
--- /dev/null
+/**************************************************************************
+ * Copyright (c) 2007, Intel Corporation.
+ *
+ * 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 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.
+ *
+ * Authors: Thomas Hellstrom <thomas-at-tungstengraphics.com>
+ **************************************************************************/
+
+#include <drm/drmP.h>
+#include "psb_drm.h"
+#include "psb_drv.h"
+#include "psb_reg.h"
+#include "ttm/ttm_execbuf_util.h"
+
+
+static void psb_powerdown_topaz(struct work_struct *work)
+{
+ struct psb_scheduler *scheduler =
+ container_of(work, struct psb_scheduler, topaz_suspend_wq.work);
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) scheduler->dev->dev_private;
+
+ if (!dev_priv->topaz_disabled) {
+ if (!mutex_trylock(&scheduler->topaz_power_mutex))
+ return;
+
+ ospm_apm_power_down_topaz(scheduler->dev);
+ mutex_unlock(&scheduler->topaz_power_mutex);
+ }
+}
+
+static void psb_powerdown_msvdx(struct work_struct *work)
+{
+ struct psb_scheduler *scheduler =
+ container_of(work, struct psb_scheduler, msvdx_suspend_wq.work);
+
+ if (!mutex_trylock(&scheduler->msvdx_power_mutex))
+ return;
+
+ psb_try_power_down_msvdx(scheduler->dev);
+ mutex_unlock(&scheduler->msvdx_power_mutex);
+}
+
+int psb_scheduler_init(struct drm_device *dev,
+ struct psb_scheduler *scheduler)
+{
+ memset(scheduler, 0, sizeof(*scheduler));
+ scheduler->dev = dev;
+ mutex_init(&scheduler->topaz_power_mutex);
+ mutex_init(&scheduler->msvdx_power_mutex);
+
+ INIT_DELAYED_WORK(&scheduler->topaz_suspend_wq,
+ &psb_powerdown_topaz);
+ INIT_DELAYED_WORK(&scheduler->msvdx_suspend_wq,
+ &psb_powerdown_msvdx);
+
+ return 0;
+}
+
--- /dev/null
+/**************************************************************************
+ * Copyright (c) 2007, Intel Corporation.
+ *
+ * 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 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.
+ *
+ * Authors: Thomas Hellstrom <thomas-at-tungstengraphics.com>
+ **************************************************************************/
+#ifndef _PSB_SCHEDULE_H_
+#define _PSB_SCHEDULE_H_
+
+#include <drm/drmP.h>
+
+struct psb_context;
+
+enum psb_task_type {
+ psb_flip_task
+};
+
+struct drm_psb_private;
+
+/*struct psb_scheduler_seq {
+ uint32_t sequence;
+ int reported;
+};*/
+
+struct psb_scheduler {
+ struct drm_device *dev;
+ /*struct psb_scheduler_seq seq[_PSB_ENGINE_TA_FENCE_TYPES];
+ struct psb_hw_scene hs[PSB_NUM_HW_SCENES];
+ struct mutex task_wq_mutex;*/
+ struct mutex topaz_power_mutex;
+ struct mutex msvdx_power_mutex;
+ /*spinlock_t lock;
+ struct list_head hw_scenes;
+ struct list_head ta_queue;
+ struct list_head raster_queue;
+ struct list_head hp_raster_queue;
+ struct list_head task_done_queue;
+ struct psb_task *current_task[PSB_SCENE_NUM_ENGINES];
+ struct psb_task *feedback_task;
+ int ta_state;
+ struct psb_hw_scene *pending_hw_scene;
+ uint32_t pending_hw_scene_seq;
+ struct delayed_work wq*/;
+ struct delayed_work topaz_suspend_wq;
+ struct delayed_work msvdx_suspend_wq;
+ /*struct psb_scene_pool *pool;
+ uint32_t idle_count;
+ int idle;
+ wait_queue_head_t idle_queue;
+ unsigned long ta_end_jiffies;
+ unsigned long total_ta_jiffies;
+ unsigned long raster_end_jiffies;
+ unsigned long total_raster_jiffies;*/
+};
+
+/*#define PSB_RF_FIRE_TA (1 << 0)
+#define PSB_RF_OOM (1 << 1)
+#define PSB_RF_OOM_REPLY (1 << 2)
+#define PSB_RF_TERMINATE (1 << 3)
+#define PSB_RF_TA_DONE (1 << 4)
+#define PSB_RF_FIRE_RASTER (1 << 5)
+#define PSB_RF_RASTER_DONE (1 << 6)
+#define PSB_RF_DEALLOC (1 << 7)
+*/
+
+extern int psb_scheduler_init(struct drm_device *dev,
+ struct psb_scheduler *scheduler);
+
+#endif
--- /dev/null
+/**************************************************************************
+ * Copyright (c) 2007, Intel Corporation.
+ * All Rights Reserved.
+ * Copyright (c) 2008, Tungsten Graphics, Inc. Cedar Park, TX. USA.
+ * 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 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.
+ *
+ **************************************************************************/
+
+#include <drm/drmP.h>
+#include "psb_drv.h"
+#include "psb_drm.h"
+#include "psb_reg.h"
+#include "psb_msvdx.h"
+#include "pnw_topaz.h"
+#include "ttm/ttm_bo_api.h"
+#include "ttm/ttm_execbuf_util.h"
+#include "psb_ttm_userobj_api.h"
+#include "ttm/ttm_placement.h"
+#include "psb_intel_reg.h"
+#include "psb_powermgmt.h"
+
+
+static inline int psb_same_page(unsigned long offset,
+ unsigned long offset2)
+{
+ return (offset & PAGE_MASK) == (offset2 & PAGE_MASK);
+}
+
+static inline unsigned long psb_offset_end(unsigned long offset,
+ unsigned long end)
+{
+ offset = (offset + PAGE_SIZE) & PAGE_MASK;
+ return (end < offset) ? end : offset;
+}
+
+static void psb_idle_engine(struct drm_device *dev, int engine);
+
+struct psb_dstbuf_cache {
+ unsigned int dst;
+ struct ttm_buffer_object *dst_buf;
+ unsigned long dst_offset;
+ uint32_t *dst_page;
+ unsigned int dst_page_offset;
+ struct ttm_bo_kmap_obj dst_kmap;
+ bool dst_is_iomem;
+};
+
+struct psb_validate_buffer {
+ struct ttm_validate_buffer base;
+ struct psb_validate_req req;
+ int ret;
+ struct psb_validate_arg __user *user_val_arg;
+ uint32_t flags;
+ uint32_t offset;
+ int po_correct;
+};
+
+static int psb_check_presumed(struct psb_validate_req *req,
+ struct ttm_buffer_object *bo,
+ struct psb_validate_arg __user *data,
+ int *presumed_ok)
+{
+ struct psb_validate_req __user *user_req = &(data->d.req);
+
+ *presumed_ok = 0;
+
+ if (bo->mem.mem_type == TTM_PL_SYSTEM) {
+ *presumed_ok = 1;
+ return 0;
+ }
+
+ if (unlikely(!(req->presumed_flags & PSB_USE_PRESUMED)))
+ return 0;
+
+ if (bo->offset == req->presumed_gpu_offset) {
+ *presumed_ok = 1;
+ return 0;
+ }
+
+ return __put_user(req->presumed_flags & ~PSB_USE_PRESUMED,
+ &user_req->presumed_flags);
+}
+
+
+static void psb_unreference_buffers(struct psb_context *context)
+{
+ struct ttm_validate_buffer *entry, *next;
+ struct psb_validate_buffer *vbuf;
+ struct list_head *list = &context->validate_list;
+
+ list_for_each_entry_safe(entry, next, list, head) {
+ vbuf =
+ container_of(entry, struct psb_validate_buffer, base);
+ list_del(&entry->head);
+ ttm_bo_unref(&entry->bo);
+ }
+
+ list = &context->kern_validate_list;
+
+ list_for_each_entry_safe(entry, next, list, head) {
+ vbuf =
+ container_of(entry, struct psb_validate_buffer, base);
+ list_del(&entry->head);
+ ttm_bo_unref(&entry->bo);
+ }
+}
+
+
+static int psb_lookup_validate_buffer(struct drm_file *file_priv,
+ uint64_t data,
+ struct psb_validate_buffer *item)
+{
+ struct ttm_object_file *tfile = psb_fpriv(file_priv)->tfile;
+
+ item->user_val_arg =
+ (struct psb_validate_arg __user *)(unsigned long) data;
+
+ if (unlikely(copy_from_user(&item->req, &item->user_val_arg->d.req,
+ sizeof(item->req)) != 0)) {
+ DRM_ERROR("Lookup copy fault.\n");
+ return -EFAULT;
+ }
+
+ item->base.bo =
+ ttm_buffer_object_lookup(tfile, item->req.buffer_handle);
+
+ if (unlikely(item->base.bo == NULL)) {
+ DRM_ERROR("Bo lookup fault.\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int psb_reference_buffers(struct drm_file *file_priv,
+ uint64_t data,
+ struct psb_context *context)
+{
+ struct psb_validate_buffer *item;
+ int ret;
+
+ while (likely(data != 0)) {
+ if (unlikely(context->used_buffers >=
+ PSB_NUM_VALIDATE_BUFFERS)) {
+ DRM_ERROR("Too many buffers "
+ "on validate list.\n");
+ ret = -EINVAL;
+ goto out_err0;
+ }
+
+ item = &context->buffers[context->used_buffers];
+
+ ret = psb_lookup_validate_buffer(file_priv, data, item);
+ if (unlikely(ret != 0))
+ goto out_err0;
+
+ item->base.reserved = 0;
+ list_add_tail(&item->base.head, &context->validate_list);
+ context->used_buffers++;
+ data = item->req.next;
+ }
+ return 0;
+
+out_err0:
+ psb_unreference_buffers(context);
+ return ret;
+}
+
+static int
+psb_placement_fence_type(struct ttm_buffer_object *bo,
+ uint64_t set_val_flags,
+ uint64_t clr_val_flags,
+ uint32_t new_fence_class,
+ uint32_t *new_fence_type)
+{
+ int ret;
+ uint32_t n_fence_type;
+ /*
+ uint32_t set_flags = set_val_flags & 0xFFFFFFFF;
+ uint32_t clr_flags = clr_val_flags & 0xFFFFFFFF;
+ */
+ struct ttm_fence_object *old_fence;
+ uint32_t old_fence_type;
+ struct ttm_placement placement;
+
+ if (unlikely
+ (!(set_val_flags &
+ (PSB_GPU_ACCESS_READ | PSB_GPU_ACCESS_WRITE)))) {
+ DRM_ERROR
+ ("GPU access type (read / write) is not indicated.\n");
+ return -EINVAL;
+ }
+
+ /* User space driver doesn't set any TTM placement flags in set_val_flags or clr_val_flags */
+ placement.num_placement = 0;/* FIXME */
+ placement.num_busy_placement = 0;
+ placement.fpfn = 0;
+ placement.lpfn = 0;
+ ret = psb_ttm_bo_check_placement(bo, &placement);
+ if (unlikely(ret != 0))
+ return ret;
+
+ switch (new_fence_class) {
+ default:
+ n_fence_type = _PSB_FENCE_TYPE_EXE;
+ }
+
+ *new_fence_type = n_fence_type;
+ old_fence = (struct ttm_fence_object *) bo->sync_obj;
+ old_fence_type = (uint32_t)(unsigned long) bo->sync_obj_arg;
+
+ if (old_fence && ((new_fence_class != old_fence->fence_class) ||
+ ((n_fence_type ^ old_fence_type) &
+ old_fence_type))) {
+ ret = ttm_bo_wait(bo, 0, 1, 0);
+ if (unlikely(ret != 0))
+ return ret;
+ }
+ /*
+ bo->proposed_flags = (bo->proposed_flags | set_flags)
+ & ~clr_flags & TTM_PL_MASK_MEMTYPE;
+ */
+ return 0;
+}
+
+static int psb_validate_buffer_list(struct drm_file *file_priv,
+ uint32_t fence_class,
+ struct psb_context *context,
+ int *po_correct)
+{
+ struct psb_validate_buffer *item;
+ struct ttm_buffer_object *bo;
+ int ret;
+ struct psb_validate_req *req;
+ uint32_t fence_types = 0;
+ uint32_t cur_fence_type;
+ struct ttm_validate_buffer *entry;
+ struct list_head *list = &context->validate_list;
+ struct ttm_placement placement;
+ uint32_t flags;
+
+ *po_correct = 1;
+
+ list_for_each_entry(entry, list, head) {
+ item =
+ container_of(entry, struct psb_validate_buffer, base);
+ bo = entry->bo;
+ item->ret = 0;
+ req = &item->req;
+
+ spin_lock(&bo->bdev->fence_lock);
+ ret = psb_placement_fence_type(bo,
+ req->set_flags,
+ req->clear_flags,
+ fence_class,
+ &cur_fence_type);
+ if (unlikely(ret != 0))
+ goto out_err_unlock;
+
+ flags = item->req.pad64 | TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED;
+ placement.num_placement = 1;
+ placement.placement = &flags;
+ placement.num_busy_placement = 0;
+ placement.fpfn = 0;
+ placement.lpfn = 0;
+ /*
+ ret = ttm_bo_validate(bo, &placement, 1, 0, 0);
+ if (unlikely(ret != 0))
+ goto out_err_unlock;
+ */
+ fence_types |= cur_fence_type;
+ entry->new_sync_obj_arg = (void *)
+ (unsigned long) cur_fence_type;
+
+ item->offset = bo->offset;
+ item->flags = bo->mem.placement;
+ spin_unlock(&bo->bdev->fence_lock);
+
+ ret =
+ psb_check_presumed(&item->req, bo, item->user_val_arg,
+ &item->po_correct);
+ if (unlikely(ret != 0))
+ goto out_err;
+
+ if (unlikely(!item->po_correct))
+ *po_correct = 0;
+
+ item++;
+ }
+
+ context->fence_types |= fence_types;
+
+ return 0;
+out_err_unlock:
+ spin_unlock(&bo->bdev->fence_lock);
+out_err:
+ item->ret = ret;
+ return ret;
+}
+
+static void psb_clear_dstbuf_cache(struct psb_dstbuf_cache *dst_cache)
+{
+ if (dst_cache->dst_page) {
+ ttm_bo_kunmap(&dst_cache->dst_kmap);
+ dst_cache->dst_page = NULL;
+ }
+ dst_cache->dst_buf = NULL;
+ dst_cache->dst = ~0;
+}
+
+static int psb_update_dstbuf_cache(struct psb_dstbuf_cache *dst_cache,
+ struct psb_validate_buffer *buffers,
+ unsigned int dst,
+ unsigned long dst_offset)
+{
+ int ret;
+
+ PSB_DEBUG_GENERAL("Destination buffer is %d.\n", dst);
+
+ if (unlikely(dst != dst_cache->dst || NULL == dst_cache->dst_buf)) {
+ psb_clear_dstbuf_cache(dst_cache);
+ dst_cache->dst = dst;
+ dst_cache->dst_buf = buffers[dst].base.bo;
+ }
+
+ if (unlikely
+ (dst_offset > dst_cache->dst_buf->num_pages * PAGE_SIZE)) {
+ DRM_ERROR("Relocation destination out of bounds.\n");
+ return -EINVAL;
+ }
+
+ if (!psb_same_page(dst_cache->dst_offset, dst_offset) ||
+ NULL == dst_cache->dst_page) {
+ if (NULL != dst_cache->dst_page) {
+ ttm_bo_kunmap(&dst_cache->dst_kmap);
+ dst_cache->dst_page = NULL;
+ }
+
+ ret =
+ ttm_bo_kmap(dst_cache->dst_buf,
+ dst_offset >> PAGE_SHIFT, 1,
+ &dst_cache->dst_kmap);
+ if (ret) {
+ DRM_ERROR("Could not map destination buffer for "
+ "relocation.\n");
+ return ret;
+ }
+
+ dst_cache->dst_page =
+ ttm_kmap_obj_virtual(&dst_cache->dst_kmap,
+ &dst_cache->dst_is_iomem);
+ dst_cache->dst_offset = dst_offset & PAGE_MASK;
+ dst_cache->dst_page_offset = dst_cache->dst_offset >> 2;
+ }
+ return 0;
+}
+
+static int psb_apply_reloc(struct drm_psb_private *dev_priv,
+ uint32_t fence_class,
+ const struct drm_psb_reloc *reloc,
+ struct psb_validate_buffer *buffers,
+ int num_buffers,
+ struct psb_dstbuf_cache *dst_cache,
+ int no_wait, int interruptible)
+{
+ uint32_t val;
+ uint32_t background;
+ unsigned int index;
+ int ret;
+ unsigned int shift;
+ unsigned int align_shift;
+ struct ttm_buffer_object *reloc_bo;
+
+
+ PSB_DEBUG_GENERAL("Reloc type %d\n"
+ "\t where 0x%04x\n"
+ "\t buffer 0x%04x\n"
+ "\t mask 0x%08x\n"
+ "\t shift 0x%08x\n"
+ "\t pre_add 0x%08x\n"
+ "\t background 0x%08x\n"
+ "\t dst_buffer 0x%08x\n"
+ "\t arg0 0x%08x\n"
+ "\t arg1 0x%08x\n",
+ reloc->reloc_op,
+ reloc->where,
+ reloc->buffer,
+ reloc->mask,
+ reloc->shift,
+ reloc->pre_add,
+ reloc->background,
+ reloc->dst_buffer, reloc->arg0, reloc->arg1);
+
+ if (unlikely(reloc->buffer >= num_buffers)) {
+ DRM_ERROR("Illegal relocation buffer %d.\n",
+ reloc->buffer);
+ return -EINVAL;
+ }
+
+ if (buffers[reloc->buffer].po_correct)
+ return 0;
+
+ if (unlikely(reloc->dst_buffer >= num_buffers)) {
+ DRM_ERROR
+ ("Illegal destination buffer for relocation %d.\n",
+ reloc->dst_buffer);
+ return -EINVAL;
+ }
+
+ ret =
+ psb_update_dstbuf_cache(dst_cache, buffers, reloc->dst_buffer,
+ reloc->where << 2);
+ if (ret)
+ return ret;
+
+ reloc_bo = buffers[reloc->buffer].base.bo;
+
+ if (unlikely(reloc->pre_add > (reloc_bo->num_pages << PAGE_SHIFT))) {
+ DRM_ERROR("Illegal relocation offset add.\n");
+ return -EINVAL;
+ }
+
+ switch (reloc->reloc_op) {
+ case PSB_RELOC_OP_OFFSET:
+ val = reloc_bo->offset + reloc->pre_add;
+ break;
+ default:
+ DRM_ERROR("Unimplemented relocation.\n");
+ return -EINVAL;
+ }
+
+ shift =
+ (reloc->shift & PSB_RELOC_SHIFT_MASK) >> PSB_RELOC_SHIFT_SHIFT;
+ align_shift =
+ (reloc->
+ shift & PSB_RELOC_ALSHIFT_MASK) >> PSB_RELOC_ALSHIFT_SHIFT;
+
+ val = ((val >> align_shift) << shift);
+ index = reloc->where - dst_cache->dst_page_offset;
+
+ background = reloc->background;
+ val = (background & ~reloc->mask) | (val & reloc->mask);
+ dst_cache->dst_page[index] = val;
+
+ PSB_DEBUG_GENERAL("Reloc buffer %d index 0x%08x, value 0x%08x\n",
+ reloc->dst_buffer, index,
+ dst_cache->dst_page[index]);
+
+ return 0;
+}
+
+static int psb_ok_to_map_reloc(struct drm_psb_private *dev_priv,
+ unsigned int num_pages)
+{
+ int ret = 0;
+
+ spin_lock(&dev_priv->reloc_lock);
+ if (dev_priv->rel_mapped_pages + num_pages <= PSB_MAX_RELOC_PAGES) {
+ dev_priv->rel_mapped_pages += num_pages;
+ ret = 1;
+ }
+ spin_unlock(&dev_priv->reloc_lock);
+ return ret;
+}
+
+static int psb_fixup_relocs(struct drm_file *file_priv,
+ uint32_t fence_class,
+ unsigned int num_relocs,
+ unsigned int reloc_offset,
+ uint32_t reloc_handle,
+ struct psb_context *context,
+ int no_wait, int interruptible)
+{
+ struct drm_device *dev = file_priv->minor->dev;
+ struct ttm_object_file *tfile = psb_fpriv(file_priv)->tfile;
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) dev->dev_private;
+ struct ttm_buffer_object *reloc_buffer = NULL;
+ unsigned int reloc_num_pages;
+ unsigned int reloc_first_page;
+ unsigned int reloc_last_page;
+ struct psb_dstbuf_cache dst_cache;
+ struct drm_psb_reloc *reloc;
+ struct ttm_bo_kmap_obj reloc_kmap;
+ bool reloc_is_iomem;
+ int count;
+ int ret = 0;
+ int registered = 0;
+ uint32_t num_buffers = context->used_buffers;
+
+ if (num_relocs == 0)
+ return 0;
+
+ memset(&dst_cache, 0, sizeof(dst_cache));
+ memset(&reloc_kmap, 0, sizeof(reloc_kmap));
+
+ reloc_buffer = ttm_buffer_object_lookup(tfile, reloc_handle);
+ if (!reloc_buffer)
+ goto out;
+
+ if (unlikely(atomic_read(&reloc_buffer->reserved) != 1)) {
+ DRM_ERROR("Relocation buffer was not on validate list.\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ reloc_first_page = reloc_offset >> PAGE_SHIFT;
+ reloc_last_page =
+ (reloc_offset +
+ num_relocs * sizeof(struct drm_psb_reloc)) >> PAGE_SHIFT;
+ reloc_num_pages = reloc_last_page - reloc_first_page + 1;
+ reloc_offset &= ~PAGE_MASK;
+
+ if (reloc_num_pages > PSB_MAX_RELOC_PAGES) {
+ DRM_ERROR("Relocation buffer is too large\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ DRM_WAIT_ON(ret, dev_priv->rel_mapped_queue, 3 * DRM_HZ,
+ (registered =
+ psb_ok_to_map_reloc(dev_priv, reloc_num_pages)));
+
+ if (ret == -EINTR) {
+ ret = -ERESTART;
+ goto out;
+ }
+ if (ret) {
+ DRM_ERROR("Error waiting for space to map "
+ "relocation buffer.\n");
+ goto out;
+ }
+
+ ret = ttm_bo_kmap(reloc_buffer, reloc_first_page,
+ reloc_num_pages, &reloc_kmap);
+
+ if (ret) {
+ DRM_ERROR("Could not map relocation buffer.\n"
+ "\tReloc buffer id 0x%08x.\n"
+ "\tReloc first page %d.\n"
+ "\tReloc num pages %d.\n",
+ reloc_handle, reloc_first_page, reloc_num_pages);
+ goto out;
+ }
+
+ reloc = (struct drm_psb_reloc *)
+ ((unsigned long)
+ ttm_kmap_obj_virtual(&reloc_kmap,
+ &reloc_is_iomem) + reloc_offset);
+
+ for (count = 0; count < num_relocs; ++count) {
+ ret = psb_apply_reloc(dev_priv, fence_class,
+ reloc, context->buffers,
+ num_buffers, &dst_cache,
+ no_wait, interruptible);
+ if (ret)
+ goto out1;
+ reloc++;
+ }
+
+out1:
+ ttm_bo_kunmap(&reloc_kmap);
+out:
+ if (registered) {
+ spin_lock(&dev_priv->reloc_lock);
+ dev_priv->rel_mapped_pages -= reloc_num_pages;
+ spin_unlock(&dev_priv->reloc_lock);
+ DRM_WAKEUP(&dev_priv->rel_mapped_queue);
+ }
+
+ psb_clear_dstbuf_cache(&dst_cache);
+ if (reloc_buffer)
+ ttm_bo_unref(&reloc_buffer);
+ return ret;
+}
+
+void psb_fence_or_sync(struct drm_file *file_priv,
+ uint32_t engine,
+ uint32_t fence_types,
+ uint32_t fence_flags,
+ struct list_head *list,
+ struct psb_ttm_fence_rep *fence_arg,
+ struct ttm_fence_object **fence_p)
+{
+ struct drm_device *dev = file_priv->minor->dev;
+ struct drm_psb_private *dev_priv = psb_priv(dev);
+ struct ttm_fence_device *fdev = &dev_priv->fdev;
+ int ret;
+ struct ttm_fence_object *fence;
+ struct ttm_object_file *tfile = psb_fpriv(file_priv)->tfile;
+ uint32_t handle;
+
+ ret = ttm_fence_user_create(fdev, tfile,
+ engine, fence_types,
+ TTM_FENCE_FLAG_EMIT, &fence, &handle);
+ if (ret) {
+
+ /*
+ * Fence creation failed.
+ * Fall back to synchronous operation and idle the engine.
+ */
+
+ psb_idle_engine(dev, engine);
+ if (!(fence_flags & DRM_PSB_FENCE_NO_USER)) {
+
+ /*
+ * Communicate to user-space that
+ * fence creation has failed and that
+ * the engine is idle.
+ */
+
+ fence_arg->handle = ~0;
+ fence_arg->error = ret;
+ }
+
+ ttm_eu_backoff_reservation(list);
+ if (fence_p)
+ *fence_p = NULL;
+ return;
+ }
+
+ ttm_eu_fence_buffer_objects(list, fence);
+ if (!(fence_flags & DRM_PSB_FENCE_NO_USER)) {
+ struct ttm_fence_info info = ttm_fence_get_info(fence);
+ fence_arg->handle = handle;
+ fence_arg->fence_class = ttm_fence_class(fence);
+ fence_arg->fence_type = ttm_fence_types(fence);
+ fence_arg->signaled_types = info.signaled_types;
+ fence_arg->error = 0;
+ } else {
+ ret =
+ ttm_ref_object_base_unref(tfile, handle,
+ ttm_fence_type);
+ BUG_ON(ret);
+ }
+
+ if (fence_p)
+ *fence_p = fence;
+ else if (fence)
+ ttm_fence_object_unref(&fence);
+}
+
+
+#if 0
+static int psb_dump_page(struct ttm_buffer_object *bo,
+ unsigned int page_offset, unsigned int num)
+{
+ struct ttm_bo_kmap_obj kmobj;
+ int is_iomem;
+ uint32_t *p;
+ int ret;
+ unsigned int i;
+
+ ret = ttm_bo_kmap(bo, page_offset, 1, &kmobj);
+ if (ret)
+ return ret;
+
+ p = ttm_kmap_obj_virtual(&kmobj, &is_iomem);
+ for (i = 0; i < num; ++i)
+ PSB_DEBUG_GENERAL("0x%04x: 0x%08x\n", i, *p++);
+
+ ttm_bo_kunmap(&kmobj);
+ return 0;
+}
+#endif
+
+static void psb_idle_engine(struct drm_device *dev, int engine)
+{
+ /*Fix me add video engile support*/
+ return;
+}
+
+static int psb_handle_copyback(struct drm_device *dev,
+ struct psb_context *context,
+ int ret)
+{
+ int err = ret;
+ struct ttm_validate_buffer *entry;
+ struct psb_validate_arg arg;
+ struct list_head *list = &context->validate_list;
+
+ if (ret) {
+ ttm_eu_backoff_reservation(list);
+ ttm_eu_backoff_reservation(&context->kern_validate_list);
+ }
+
+
+ if (ret != -EAGAIN && ret != -EINTR && ret != -ERESTART) {
+ list_for_each_entry(entry, list, head) {
+ struct psb_validate_buffer *vbuf =
+ container_of(entry, struct psb_validate_buffer,
+ base);
+ arg.handled = 1;
+ arg.ret = vbuf->ret;
+ if (!arg.ret) {
+ struct ttm_buffer_object *bo = entry->bo;
+ spin_lock(&bo->bdev->fence_lock);
+ arg.d.rep.gpu_offset = bo->offset;
+ arg.d.rep.placement = bo->mem.placement;
+ arg.d.rep.fence_type_mask =
+ (uint32_t)(unsigned long)
+ entry->new_sync_obj_arg;
+ spin_unlock(&bo->bdev->fence_lock);
+ }
+
+ if (__copy_to_user(vbuf->user_val_arg,
+ &arg, sizeof(arg)))
+ err = -EFAULT;
+
+ if (arg.ret)
+ break;
+ }
+ }
+
+ return err;
+}
+
+int psb_cmdbuf_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_psb_cmdbuf_arg *arg = data;
+ int ret = 0;
+ struct ttm_object_file *tfile = psb_fpriv(file_priv)->tfile;
+ struct ttm_buffer_object *cmd_buffer = NULL;
+ struct psb_ttm_fence_rep fence_arg;
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *)file_priv->minor->dev->dev_private;
+ struct psb_video_ctx *pos, *n;
+ int engine;
+ int po_correct;
+ struct psb_context *context;
+ unsigned num_buffers;
+
+ ((struct msvdx_private*)dev_priv->msvdx_private)->tfile = tfile;
+ num_buffers = PSB_NUM_VALIDATE_BUFFERS;
+
+ ret = ttm_read_lock(&dev_priv->ttm_lock, true);
+ if (unlikely(ret != 0))
+ return ret;
+
+ if (arg->engine == PSB_ENGINE_VIDEO) {
+ if (!ospm_power_using_hw_begin(OSPM_VIDEO_DEC_ISLAND,
+ OSPM_UHB_FORCE_POWER_ON))
+ return -EBUSY;
+ } else if (arg->engine == LNC_ENGINE_ENCODE) {
+ if (dev_priv->topaz_disabled)
+ return -ENODEV;
+
+ if (!ospm_power_using_hw_begin(OSPM_VIDEO_ENC_ISLAND,
+ OSPM_UHB_FORCE_POWER_ON))
+ return -EBUSY;
+ }
+
+
+ ret = mutex_lock_interruptible(&dev_priv->cmdbuf_mutex);
+ if (unlikely(ret != 0))
+ goto out_err0;
+
+
+ context = &dev_priv->context;
+ context->used_buffers = 0;
+ context->fence_types = 0;
+ BUG_ON(!list_empty(&context->validate_list));
+ BUG_ON(!list_empty(&context->kern_validate_list));
+
+ if (unlikely(context->buffers == NULL)) {
+ context->buffers = vmalloc(PSB_NUM_VALIDATE_BUFFERS *
+ sizeof(*context->buffers));
+ if (unlikely(context->buffers == NULL)) {
+ ret = -ENOMEM;
+ goto out_err1;
+ }
+ }
+
+ ret = psb_reference_buffers(file_priv,
+ arg->buffer_list,
+ context);
+
+ if (unlikely(ret != 0))
+ goto out_err1;
+
+ ret = ttm_eu_reserve_buffers(&context->validate_list);
+ if (unlikely(ret != 0))
+ goto out_err2;
+
+ engine = arg->engine;
+ ret = psb_validate_buffer_list(file_priv, engine,
+ context, &po_correct);
+ if (unlikely(ret != 0))
+ goto out_err3;
+
+ if (!po_correct) {
+ ret = psb_fixup_relocs(file_priv, engine, arg->num_relocs,
+ arg->reloc_offset,
+ arg->reloc_handle, context, 0, 1);
+ if (unlikely(ret != 0))
+ goto out_err3;
+
+ }
+
+ cmd_buffer = ttm_buffer_object_lookup(tfile, arg->cmdbuf_handle);
+ if (unlikely(cmd_buffer == NULL)) {
+ ret = -EINVAL;
+ goto out_err4;
+ }
+
+ list_for_each_entry_safe(pos, n, &dev_priv->video_ctx, head) {
+ if (pos->filp == file_priv->filp) {
+ int entrypoint = pos->ctx_type & 0xff;
+
+ PSB_DEBUG_GENERAL("Video:commands for profile %d, entrypoint %d",
+ (pos->ctx_type >> 8), (pos->ctx_type & 0xff));
+
+ if (entrypoint == VAEntrypointEncSlice ||
+ entrypoint == VAEntrypointEncPicture)
+ dev_priv->topaz_ctx = pos;
+ else
+ dev_priv->msvdx_ctx = pos;
+
+ break;
+ }
+ }
+
+ switch (arg->engine) {
+ case PSB_ENGINE_VIDEO:
+ if (arg->cmdbuf_size == (16 + 32)) {
+ /* Identify deblock msg cmdbuf */
+ /* according to cmdbuf_size */
+ struct ttm_bo_kmap_obj cmd_kmap;
+ struct ttm_buffer_object *deblock;
+ uint32_t *cmd;
+ bool is_iomem;
+
+ /* write regIO BO's address after deblcok msg */
+ ret = ttm_bo_kmap(cmd_buffer, 0, 1, &cmd_kmap);
+ if (unlikely(ret != 0))
+ goto out_err4;
+ cmd = (uint32_t *)(ttm_kmap_obj_virtual(&cmd_kmap,
+ &is_iomem) + 16);
+ deblock = ttm_buffer_object_lookup(tfile,
+ (uint32_t)(*cmd));
+ *cmd = (uint32_t)deblock;
+ ttm_bo_unref(&deblock); /* FIXME Should move this to interrupt handler? */
+ ttm_bo_kunmap(&cmd_kmap);
+ }
+
+ ret = psb_cmdbuf_video(file_priv, &context->validate_list,
+ context->fence_types, arg,
+ cmd_buffer, &fence_arg);
+
+ if (unlikely(ret != 0))
+ goto out_err4;
+ break;
+ case LNC_ENGINE_ENCODE:
+ ret = pnw_cmdbuf_video(file_priv, &context->validate_list,
+ context->fence_types, arg,
+ cmd_buffer, &fence_arg);
+
+ if (unlikely(ret != 0))
+ goto out_err4;
+ break;
+
+
+ default:
+ DRM_ERROR
+ ("Unimplemented command submission mechanism (%x).\n",
+ arg->engine);
+ ret = -EINVAL;
+ goto out_err4;
+ }
+
+ if (!(arg->fence_flags & DRM_PSB_FENCE_NO_USER)) {
+ ret = copy_to_user((void __user *)
+ ((unsigned long) arg->fence_arg),
+ &fence_arg, sizeof(fence_arg));
+ }
+
+out_err4:
+ if (cmd_buffer)
+ ttm_bo_unref(&cmd_buffer);
+out_err3:
+ ret = psb_handle_copyback(dev, context, ret);
+out_err2:
+ psb_unreference_buffers(context);
+out_err1:
+ mutex_unlock(&dev_priv->cmdbuf_mutex);
+out_err0:
+ ttm_read_unlock(&dev_priv->ttm_lock);
+
+ if (arg->engine == PSB_ENGINE_VIDEO)
+ ospm_power_using_hw_end(OSPM_VIDEO_DEC_ISLAND);
+
+ if (arg->engine == LNC_ENGINE_ENCODE)
+ ospm_power_using_hw_end(OSPM_VIDEO_ENC_ISLAND);
+
+ return ret;
+}
+
+void psb_gl3_global_invalidation(struct drm_device *dev)
+{
+#ifdef CONFIG_MDFD_GL3
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ uint32_t gl3_ctl;
+ /* uint32_t poll_count = 0x1000, gl3_stat; */
+
+ /* IS there a way to avoid multiple invalidation simultaneously? Maybe a ATOM value */
+
+ gl3_ctl = PSB_RVDC32(PSB_GL3_CACHE_CTL);
+ /* gl3_ctl = PSB_RVDC32(0xb0000); */
+ /* printk("gl3_invalidation: GCL_CR_CTL2 is 0x%08x\n", gl3_ctl); */
+
+ PSB_WVDC32(gl3_ctl | 0x2, PSB_GL3_CACHE_CTL);
+
+#if 0
+ while (poll_count) {
+ gl3_stat = PSB_RVDC32(PSB_GL3_CACHE_STAT);
+ if (gl3_stat & 0x1) {
+ PSB_WVDC32(gl3_stat | 0x1, PSB_GL3_CACHE_STAT); /* Frome D.Will : write 1 to Inval_done bit to clear it */
+ return;
+ }
+ cpu_relax();
+ poll_count--;
+ }
+
+ DRM_ERROR("Invalidation GL3 timeout\n");
+#endif
+#endif
+}
--- /dev/null
+/*
+ * Copyright (c) 2009, Intel Corporation.
+ *
+ * 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 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.
+ *
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004 Novell, Inc. All rights reserved.
+ * Copyright (C) 2004 IBM, Inc. All rights reserved.
+ * Copyright (C) 2009 Intel Corporation. All rights reserved.
+ *
+ * Licensed under the GNU GPL v2.
+ *
+ * Authors:
+ * Robert Love <rml@novell.com>
+ * Kay Sievers <kay.sievers@vrfy.org>
+ * Arjan van de Ven <arjanv@redhat.com>
+ * Greg Kroah-Hartman <greg@kroah.com>
+ *
+ * Notes:
+ * Adapted from existing kobj event socket code to enable
+ * mutlicast usermode communication for gfx driver to mutiple
+ * usermode threads via different socket broadcast groups.
+ * Original kobject uevent code does not allow for different
+ * broadcast groups. Due to the frequency of usermode events
+ * generated by some gfx subsystems it is necessary to open
+ * a new dedicated socket with multicast group support. In
+ * the future it is hoped that this code can be removed
+ * and either a new netlink protocol type added for graphics
+ * or conversely to simply enable group routing to be leveraged
+ * on the existing kobject uevent infrastructure.
+ */
+
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/kobject.h>
+#include <linux/module.h>
+#include <linux/socket.h>
+#include <linux/skbuff.h>
+#include <linux/netlink.h>
+#include <net/sock.h>
+#include "psb_umevents.h"
+
+#define NETLINK_PSB_KOBJECT_UEVENT 31
+
+static u64 psb_uevent_seqnum;
+static char psb_uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH;
+static DEFINE_SPINLOCK(sequence_lock);
+#if defined(CONFIG_NET)
+static struct sock *uevent_sock;
+#endif
+
+/* the strings here must match the enum in include/linux/kobject.h */
+static const char *psb_kobject_actions[] = {
+ [KOBJ_ADD] = "add",
+ [KOBJ_REMOVE] = "remove",
+ [KOBJ_CHANGE] = "change",
+ [KOBJ_MOVE] = "move",
+ [KOBJ_ONLINE] = "online",
+ [KOBJ_OFFLINE] = "offline",
+};
+
+/**
+ * kobject_action_type - translate action string to numeric type
+ *
+ * @buf: buffer containing the action string, newline is ignored
+ * @len: length of buffer
+ * @type: pointer to the location to store the action type
+ *
+ * Returns 0 if the action string was recognized.
+ */
+int psb_kobject_action_type(const char *buf, size_t count,
+ enum kobject_action *type)
+{
+ enum kobject_action action;
+ int ret = -EINVAL;
+
+ if (count && (buf[count-1] == '\n' || buf[count-1] == '\0'))
+ count--;
+
+ if (!count)
+ goto out;
+
+ for (action = 0; action < ARRAY_SIZE(psb_kobject_actions); action++) {
+ if (strncmp(psb_kobject_actions[action], buf, count) != 0)
+ continue;
+ if (psb_kobject_actions[action][count] != '\0')
+ continue;
+ *type = action;
+ ret = 0;
+ break;
+ }
+out:
+ return ret;
+}
+
+/**
+ * psb_kobject_uevent_env - send an uevent with environmental data
+ *
+ * @action: action that is happening
+ * @kobj: struct kobject that the action is happening to
+ * @envp_ext: pointer to environmental data
+ *
+ * Returns 0 if kobject_uevent() is completed with success or the
+ * corresponding error when it fails.
+ */
+int psb_kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
+ char *envp_ext[], int dst_group_id)
+{
+ struct kobj_uevent_env *env;
+ const char *action_string = psb_kobject_actions[action];
+ const char *devpath = NULL;
+ const char *subsystem;
+ struct kobject *top_kobj;
+ struct kset *kset;
+ struct kset_uevent_ops *uevent_ops;
+ u64 seq;
+ int i = 0;
+ int retval = 0;
+
+ pr_debug("kobject: '%s' (%p): %s\n",
+ kobject_name(kobj), kobj, __func__);
+
+ /* search the kset we belong to */
+ top_kobj = kobj;
+ while (!top_kobj->kset && top_kobj->parent)
+ top_kobj = top_kobj->parent;
+
+ if (!top_kobj->kset) {
+ pr_debug("kobject: '%s' (%p): %s: attempted to send uevent "
+ "without kset!\n", kobject_name(kobj), kobj,
+ __func__);
+ return -EINVAL;
+ }
+
+ kset = top_kobj->kset;
+ uevent_ops = (struct kset_uevent_ops *)kset->uevent_ops;
+
+ /* skip the event, if uevent_suppress is set*/
+ if (kobj->uevent_suppress) {
+ pr_debug("kobject: '%s' (%p): %s: uevent_suppress "
+ "caused the event to drop!\n",
+ kobject_name(kobj), kobj, __func__);
+ return 0;
+ }
+ /* skip the event, if the filter returns zero. */
+ if (uevent_ops && uevent_ops->filter)
+ if (!uevent_ops->filter(kset, kobj)) {
+ pr_debug("kobject: '%s' (%p): %s: filter function "
+ "caused the event to drop!\n",
+ kobject_name(kobj), kobj, __func__);
+ return 0;
+ }
+
+ /* originating subsystem */
+ if (uevent_ops && uevent_ops->name)
+ subsystem = uevent_ops->name(kset, kobj);
+ else
+ subsystem = kobject_name(&kset->kobj);
+ if (!subsystem) {
+ pr_debug("kobject: '%s' (%p): %s: unset subsystem caused the "
+ "event to drop!\n", kobject_name(kobj), kobj,
+ __func__);
+ return 0;
+ }
+
+ /* environment buffer */
+ env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL);
+ if (!env)
+ return -ENOMEM;
+
+ /* complete object path */
+ devpath = kobject_get_path(kobj, GFP_KERNEL);
+ if (!devpath) {
+ retval = -ENOENT;
+ goto exit;
+ }
+
+ /* default keys */
+ retval = add_uevent_var(env, "ACTION=%s", action_string);
+ if (retval)
+ goto exit;
+ retval = add_uevent_var(env, "DEVPATH=%s", devpath);
+ if (retval)
+ goto exit;
+ retval = add_uevent_var(env, "SUBSYSTEM=%s", subsystem);
+ if (retval)
+ goto exit;
+
+ /* keys passed in from the caller */
+ if (envp_ext) {
+ for (i = 0; envp_ext[i]; i++) {
+ retval = add_uevent_var(env, "%s", envp_ext[i]);
+ if (retval)
+ goto exit;
+ }
+ }
+
+ /* let the kset specific function add its stuff */
+ if (uevent_ops && uevent_ops->uevent) {
+ retval = uevent_ops->uevent(kset, kobj, env);
+ if (retval) {
+ pr_debug("kobject: '%s' (%p): %s: uevent() returned "
+ "%d\n", kobject_name(kobj), kobj,
+ __func__, retval);
+ goto exit;
+ }
+ }
+
+ /*
+ * Mark "add" and "remove" events in the object to ensure proper
+ * events to userspace during automatic cleanup. If the object did
+ * send an "add" event, "remove" will automatically generated by
+ * the core, if not already done by the caller.
+ */
+ if (action == KOBJ_ADD)
+ kobj->state_add_uevent_sent = 1;
+ else if (action == KOBJ_REMOVE)
+ kobj->state_remove_uevent_sent = 1;
+
+ /* we will send an event, so request a new sequence number */
+ spin_lock(&sequence_lock);
+ seq = ++psb_uevent_seqnum;
+ spin_unlock(&sequence_lock);
+ retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)seq);
+ if (retval)
+ goto exit;
+
+#if defined(CONFIG_NET)
+ /* send netlink message */
+ if (uevent_sock) {
+ struct sk_buff *skb;
+ size_t len;
+
+ /* allocate message with the maximum possible size */
+ len = strlen(action_string) + strlen(devpath) + 2;
+ skb = alloc_skb(len + env->buflen, GFP_KERNEL);
+ if (skb) {
+ char *scratch;
+
+ /* add header */
+ scratch = skb_put(skb, len);
+ sprintf(scratch, "%s@%s", action_string, devpath);
+
+ /* copy keys to our continuous event payload buffer */
+ for (i = 0; i < env->envp_idx; i++) {
+ len = strlen(env->envp[i]) + 1;
+ scratch = skb_put(skb, len);
+ strcpy(scratch, env->envp[i]);
+ }
+
+ NETLINK_CB(skb).dst_group = dst_group_id;
+ retval = netlink_broadcast(uevent_sock, skb, 0,
+ dst_group_id,
+ GFP_KERNEL);
+
+ /* ENOBUFS should be handled in userspace */
+ if (retval == -ENOBUFS)
+ retval = 0;
+ } else
+ retval = -ENOMEM;
+ }
+#endif
+
+ /* call psb_uevent_helper, usually only enabled during early boot */
+ if (psb_uevent_helper[0]) {
+ char *argv[3];
+
+ argv[0] = psb_uevent_helper;
+ argv[1] = (char *)subsystem;
+ argv[2] = NULL;
+ retval = add_uevent_var(env, "HOME=/");
+ if (retval)
+ goto exit;
+ retval = add_uevent_var(env,
+ "PATH=/sbin:/bin:/usr/sbin:/usr/bin");
+ if (retval)
+ goto exit;
+
+ retval = call_usermodehelper(argv[0], argv,
+ env->envp, UMH_WAIT_EXEC);
+ }
+
+exit:
+ kfree(devpath);
+ kfree(env);
+ return retval;
+}
+/*EXPORT_SYMBOL_GPL(psb_kobject_uevent_env); */
+
+/**
+ * psb_kobject_uevent - notify userspace by ending an uevent
+ *
+ * @action: action that is happening
+ * @kobj: struct kobject that the action is happening to
+ *
+ * Returns 0 if psb_kobject_uevent() is completed with success or the
+ * corresponding error when it fails.
+ */
+int psb_kobject_uevent(struct kobject *kobj, enum kobject_action action,
+ int dst_group_id)
+{
+ return psb_kobject_uevent_env(kobj, action, NULL, dst_group_id);
+}
+/*EXPORT_SYMBOL_GPL(psb_kobject_uevent); */
+
+/**
+ * psb_add_uevent_var - add key value string to the environment buffer
+ * @env: environment buffer structure
+ * @format: printf format for the key=value pair
+ *
+ * Returns 0 if environment variable was added successfully or -ENOMEM
+ * if no space was available.
+ */
+int psb_add_uevent_var(struct kobj_uevent_env *env, const char *format, ...)
+{
+ va_list args;
+ int len;
+
+ if (env->envp_idx >= ARRAY_SIZE(env->envp)) {
+ WARN(1, KERN_ERR "psb_add_uevent_var: too many keys\n");
+ return -ENOMEM;
+ }
+
+ va_start(args, format);
+ len = vsnprintf(&env->buf[env->buflen],
+ sizeof(env->buf) - env->buflen,
+ format, args);
+ va_end(args);
+
+ if (len >= (sizeof(env->buf) - env->buflen)) {
+ WARN(1,
+ KERN_ERR "psb_add_uevent_var: buffer size too small\n");
+ return -ENOMEM;
+ }
+
+ env->envp[env->envp_idx++] = &env->buf[env->buflen];
+ env->buflen += len + 1;
+ return 0;
+}
+/*EXPORT_SYMBOL_GPL(psb_add_uevent_var);*/
+
+#if defined(CONFIG_NET)
+int __init psb_kobject_uevent_init(void)
+{
+ /* This should be the 15, but 3 seems to work better. Why? WHY!? */
+ /* uevent_sock = netlink_kernel_create(&init_net,
+ NETLINK_PSB_KOBJECT_UEVENT,
+ DRM_GFX_SOCKET_GROUPS,
+ NULL, NULL, THIS_MODULE); */
+ uevent_sock = netlink_kernel_create(&init_net,
+ NETLINK_PSB_KOBJECT_UEVENT,
+ 0x3, /* 3 is for hotplug & dpst */
+ NULL, NULL, THIS_MODULE);
+
+ if (!uevent_sock) {
+ printk(KERN_ERR "psb_kobject_uevent: failed create socket!\n");
+ return -ENODEV;
+ }
+ netlink_set_nonroot(NETLINK_PSB_KOBJECT_UEVENT, NL_NONROOT_RECV);
+
+ return 0;
+}
+
+#ifndef MODULE
+postcore_initcall(psb_kobject_uevent_init);
+#endif
+
+#endif
--- /dev/null
+/*
+ * Copyright © 2009 Intel Corporation
+ *
+ * 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 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.
+ *
+ * Authors:
+ * James C. Gualario <james.c.gualario@intel.com>
+ *
+ */
+#include "psb_umevents.h"
+/**
+ * define sysfs operations supported by umevent objects.
+ *
+ */
+static struct sysfs_ops umevent_obj_sysfs_ops = {
+ .show = psb_umevent_attr_show,
+ .store = psb_umevent_attr_store,
+};
+/**
+ * define the data attributes we will expose through sysfs.
+ *
+ */
+static struct umevent_attribute data_0 =
+ __ATTR(data_0_val, 0666, psb_umevent_attr_show_imp,
+ psb_umevent_attr_store_imp);
+static struct umevent_attribute data_1 =
+ __ATTR(data_1_val, 0666, psb_umevent_attr_show_imp,
+ psb_umevent_attr_store_imp);
+static struct umevent_attribute data_2 =
+ __ATTR(data_2_val, 0666, psb_umevent_attr_show_imp,
+ psb_umevent_attr_store_imp);
+static struct umevent_attribute data_3 =
+ __ATTR(data_3_val, 0666, psb_umevent_attr_show_imp,
+ psb_umevent_attr_store_imp);
+static struct umevent_attribute data_4 =
+ __ATTR(data_4_val, 0666, psb_umevent_attr_show_imp,
+ psb_umevent_attr_store_imp);
+static struct umevent_attribute data_5 =
+ __ATTR(data_5_val, 0666, psb_umevent_attr_show_imp,
+ psb_umevent_attr_store_imp);
+static struct umevent_attribute data_6 =
+ __ATTR(data_6_val, 0666, psb_umevent_attr_show_imp,
+ psb_umevent_attr_store_imp);
+static struct umevent_attribute data_7 =
+ __ATTR(data_7_val, 0666, psb_umevent_attr_show_imp,
+ psb_umevent_attr_store_imp);
+/**
+ * define the structure used to seed our ktype.
+ *
+ */
+static struct attribute *umevent_obj_default_attrs[] = {
+ &data_0.attr,
+ &data_1.attr,
+ &data_2.attr,
+ &data_3.attr,
+ &data_4.attr,
+ &data_5.attr,
+ &data_6.attr,
+ &data_7.attr,
+ NULL, /* need to NULL terminate the list of attributes */
+};
+/**
+ * specify the ktype for our kobjects.
+ *
+ */
+static struct kobj_type umevent_obj_ktype = {
+ .sysfs_ops = &umevent_obj_sysfs_ops,
+ .release = psb_umevent_obj_release,
+ .default_attrs = umevent_obj_default_attrs,
+};
+/**
+ * psb_umevent_attr_show - default kobject show function
+ *
+ * @kobj: kobject associated with the show operation
+ * @attr: attribute being requested
+ * @buf: pointer to the return buffer
+ *
+ */
+ssize_t psb_umevent_attr_show(struct kobject *kobj,
+ struct attribute *attr,
+ char *buf)
+{
+ struct umevent_attribute *attribute;
+ struct umevent_obj *any_umevent_obj;
+ attribute = to_umevent_attr(attr);
+ any_umevent_obj = to_umevent_obj(kobj);
+ if (!attribute->show)
+ return -EIO;
+
+ return attribute->show(any_umevent_obj, attribute, buf);
+}
+/**
+ * psb_umevent_attr_store - default kobject store function
+ *
+ * @kobj: kobject associated with the store operation
+ * @attr: attribute being requested
+ * @buf: input data to write to attribute
+ * @len: character count
+ *
+ */
+ssize_t psb_umevent_attr_store(struct kobject *kobj,
+ struct attribute *attr,
+ const char *buf, size_t len)
+{
+ struct umevent_attribute *attribute;
+ struct umevent_obj *any_umevent_obj;
+ attribute = to_umevent_attr(attr);
+ any_umevent_obj = to_umevent_obj(kobj);
+ if (!attribute->store)
+ return -EIO;
+
+ return attribute->store(any_umevent_obj, attribute, buf, len);
+}
+/**
+ * psb_umevent_obj_release - kobject release funtion
+ *
+ * @kobj: kobject to be released.
+ */
+void psb_umevent_obj_release(struct kobject *kobj)
+{
+ struct umevent_obj *any_umevent_obj;
+ any_umevent_obj = to_umevent_obj(kobj);
+ kfree(any_umevent_obj);
+}
+/**
+ * psb_umevent_attr_show_imp - attribute show implementation
+ *
+ * @any_umevent_obj: kobject managed data to read from
+ * @attr: attribute being requested
+ * @buf: pointer to the return buffer
+ *
+ */
+ssize_t psb_umevent_attr_show_imp(struct umevent_obj
+ *any_umevent_obj,
+ struct umevent_attribute *attr,
+ char *buf)
+{
+ int var;
+
+ if (strcmp(attr->attr.name, "data_0_val") == 0)
+ var = any_umevent_obj->data_0_val;
+ else if (strcmp(attr->attr.name, "data_1_val") == 0)
+ var = any_umevent_obj->data_1_val;
+ else if (strcmp(attr->attr.name, "data_2_val") == 0)
+ var = any_umevent_obj->data_2_val;
+ else if (strcmp(attr->attr.name, "data_3_val") == 0)
+ var = any_umevent_obj->data_3_val;
+ else if (strcmp(attr->attr.name, "data_4_val") == 0)
+ var = any_umevent_obj->data_4_val;
+ else if (strcmp(attr->attr.name, "data_5_val") == 0)
+ var = any_umevent_obj->data_5_val;
+ else if (strcmp(attr->attr.name, "data_6_val") == 0)
+ var = any_umevent_obj->data_6_val;
+ else
+ var = any_umevent_obj->data_7_val;
+
+ return sprintf(buf, "%d\n", var);
+}
+/**
+ * psb_umevent_attr_store_imp - attribute store implementation
+ *
+ * @any_umevent_obj: kobject managed data to write to
+ * @attr: attribute being requested
+ * @buf: input data to write to attribute
+ * @count: character count
+ *
+ */
+ssize_t psb_umevent_attr_store_imp(struct umevent_obj
+ *any_umevent_obj,
+ struct umevent_attribute *attr,
+ const char *buf, size_t count)
+{
+ int var;
+
+ sscanf(buf, "%du", &var);
+ if (strcmp(attr->attr.name, "data_0_val") == 0)
+ any_umevent_obj->data_0_val = var;
+ else if (strcmp(attr->attr.name, "data_1_val") == 0)
+ any_umevent_obj->data_1_val = var;
+ else if (strcmp(attr->attr.name, "data_2_val") == 0)
+ any_umevent_obj->data_2_val = var;
+ else if (strcmp(attr->attr.name, "data_3_val") == 0)
+ any_umevent_obj->data_3_val = var;
+ else if (strcmp(attr->attr.name, "data_4_val") == 0)
+ any_umevent_obj->data_4_val = var;
+ else if (strcmp(attr->attr.name, "data_5_val") == 0)
+ any_umevent_obj->data_5_val = var;
+ else if (strcmp(attr->attr.name, "data_6_val") == 0)
+ any_umevent_obj->data_6_val = var;
+ else
+ any_umevent_obj->data_7_val = var;
+ return count;
+}
+/**
+ * psb_create_umevent_obj - create and track new event objects
+ *
+ * @name: name to give to new sysfs / kobject entry
+ * @list: event object list to track the kobject in
+ */
+struct umevent_obj *psb_create_umevent_obj(const char *name,
+ struct umevent_list
+ *list)
+{
+ struct umevent_obj *new_umevent_obj;
+ int retval;
+ new_umevent_obj = kzalloc(sizeof(*new_umevent_obj),
+ GFP_KERNEL);
+ if (!new_umevent_obj)
+ return NULL;
+
+ new_umevent_obj->kobj.kset = list->umevent_disp_pool;
+ retval = kobject_init_and_add(&new_umevent_obj->kobj,
+ &umevent_obj_ktype, NULL,
+ "%s", name);
+ if (retval) {
+ kobject_put(&new_umevent_obj->kobj);
+ return NULL;
+ }
+ psb_umevent_add_to_list(list, new_umevent_obj);
+ return new_umevent_obj;
+}
+/*EXPORT_SYMBOL(psb_create_umevent_obj); */
+/**
+ * psb_umevent_notify - info user mode of a new device
+ *
+ * @notify_disp_obj: event object to perform notification for
+ *
+ */
+void psb_umevent_notify(struct umevent_obj *notify_disp_obj)
+{
+ kobject_uevent(¬ify_disp_obj->kobj, KOBJ_ADD);
+}
+/*EXPORT_SYMBOL(psb_umevent_notify); */
+
+void psb_umevent_notify_gfxsock(struct umevent_obj *notify_disp_obj,
+ int dst_group_id)
+{
+ psb_kobject_uevent(¬ify_disp_obj->kobj, KOBJ_ADD, dst_group_id);
+}
+/*EXPORT_SYMBOL(psb_umevent_notify_gfxsock);*/
+/**
+ * psb_umevent_notify_change - notify user mode of a change to a device
+ *
+ * @notify_disp_obj: event object to perform notification for
+ *
+ */
+void psb_umevent_notify_change(struct umevent_obj *notify_disp_obj)
+{
+ kobject_uevent(¬ify_disp_obj->kobj, KOBJ_CHANGE);
+}
+/*EXPORT_SYMBOL(psb_umevent_notify_change); */
+/**
+ * psb_umevent_notify_change - notify user mode of a change to a device
+ *
+ * @notify_disp_obj: event object to perform notification for
+ *
+ */
+void psb_umevent_notify_change_gfxsock(struct umevent_obj *notify_disp_obj,
+ int dst_group_id)
+{
+ psb_kobject_uevent(¬ify_disp_obj->kobj, KOBJ_CHANGE, dst_group_id);
+}
+/*EXPORT_SYMBOL(psb_umevent_notify_change_gfxsock); */
+/**
+ * psb_destroy_umvent_obj - decrement ref count on event so kernel can kill it
+ *
+ * @any_umevent_obj: event object to destroy
+ *
+ */
+static void psb_destroy_umevent_obj(struct umevent_obj
+ *any_umevent_obj)
+{
+ kobject_put(&any_umevent_obj->kobj);
+}
+/**
+ *
+ * psb_umevent_init - init the event pool
+ *
+ * @parent_kobj: parent kobject to associate new kset with
+ * @new_umevent_list: event list to associate kset with
+ * @name: name to give to new sysfs entry
+ *
+ */
+int psb_umevent_init(struct kobject *parent_kobj,
+ struct umevent_list *new_umevent_list,
+ const char *name)
+{
+ psb_umevent_init_list(new_umevent_list);
+ new_umevent_list->umevent_disp_pool = kset_create_and_add(name, NULL,
+ parent_kobj);
+ if (!new_umevent_list->umevent_disp_pool)
+ return -ENOMEM;
+
+ return 0;
+}
+/*EXPORT_SYMBOL(psb_umevent_init); */
+/**
+ *
+ * psb_umevent_cleanup - cleanup all event objects
+ *
+ * @kill_list: list of events to destroy
+ *
+ */
+void psb_umevent_cleanup(struct umevent_list *kill_list)
+{
+ psb_umevent_destroy_list(kill_list);
+}
+/*EXPORT_SYMBOL(psb_umevent_cleanup); */
+/**
+ * psb_umevent_add_to_list - add an event to the event list
+ *
+ * @list: list to add the event to
+ * @umevent_obj_to_add: event to add
+ *
+ */
+void psb_umevent_add_to_list(struct umevent_list *list,
+ struct umevent_obj *umevent_obj_to_add)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&list->list_lock, flags);
+ list_add(&umevent_obj_to_add->head, &list->head);
+ spin_unlock_irqrestore(&list->list_lock, flags);
+}
+/**
+ * psb_umevent_init_list - initialize event list
+ *
+ * @list: list to initialize
+ *
+ */
+void psb_umevent_init_list(struct umevent_list *list)
+{
+ spin_lock_init(&list->list_lock);
+ INIT_LIST_HEAD(&list->head);
+}
+/**
+ * psb_umevent_create_list - allocate an event list
+ *
+ */
+struct umevent_list *psb_umevent_create_list(void)
+{
+ struct umevent_list *new_umevent_list;
+ new_umevent_list = NULL;
+ new_umevent_list = kmalloc(sizeof(struct umevent_list),
+ GFP_ATOMIC);
+ return new_umevent_list;
+}
+/*EXPORT_SYMBOL(psb_umevent_create_list); */
+/**
+ * psb_umevent_destroy_list - destroy a list and clean up all mem
+ *
+ * @list: list to destroy and clean up after
+ *
+ */
+void psb_umevent_destroy_list(struct umevent_list *list)
+{
+ struct umevent_obj *umevent_obj_curr;
+ struct list_head *node;
+ struct list_head *node_kill;
+ int i;
+ i = 0;
+ node = NULL;
+ node_kill = NULL;
+ node = list->head.next;
+ while (node != (&list->head)) {
+ umevent_obj_curr = list_entry(node,
+ struct umevent_obj,
+ head);
+ node_kill = node;
+ node = umevent_obj_curr->head.next;
+ list_del(node_kill);
+ psb_destroy_umevent_obj(umevent_obj_curr);
+ umevent_obj_curr = NULL;
+ i++;
+ }
+ kset_unregister(list->umevent_disp_pool);
+ kfree(list);
+}
+/**
+ * psb_umevent_remove_from_list - remove an event from tracking list
+ *
+ * @list: list to remove the event from
+ * @disp_to_remove: name of event to remove.
+ *
+ */
+void psb_umevent_remove_from_list(struct umevent_list *list,
+ const char *disp_to_remove)
+{
+ struct umevent_obj *umevent_obj_curr = NULL;
+ struct list_head *node = NULL;
+ struct list_head *node_kill = NULL;
+ int i = 0;
+ int found_match = 0;
+ i = 0;
+ node = NULL;
+ node_kill = NULL;
+ node = list->head.next;
+ while (node != (&list->head)) {
+ umevent_obj_curr = list_entry(node,
+ struct umevent_obj, head);
+ if (strcmp(umevent_obj_curr->kobj.name,
+ disp_to_remove) == 0) {
+ found_match = 1;
+ break;
+ }
+ node = NULL;
+ node = umevent_obj_curr->head.next;
+ i++;
+ }
+ if (found_match == 1) {
+ node_kill = node;
+ node = umevent_obj_curr->head.next;
+ list_del(node_kill);
+ psb_destroy_umevent_obj(umevent_obj_curr);
+ umevent_obj_curr = NULL;
+ }
+}
+/*EXPORT_SYMBOL(psb_umevent_remove_from_list); */
+/**
+ * psb_umevent_find_obj - find an event in a tracking list
+ *
+ * @name: name of the event to find
+ * @list: list to find the event in
+ *
+ */
+struct umevent_obj *psb_umevent_find_obj(const char *name,
+ struct umevent_list *list)
+{
+ struct umevent_obj *umevent_obj_curr = NULL;
+ struct list_head *node = NULL;
+ struct list_head *node_find = NULL;
+ int i = 0;
+ int found_match = 0;
+ i = 0;
+ node = NULL;
+ node_find = NULL;
+ node = list->head.next;
+ while (node != (&list->head)) {
+ umevent_obj_curr = list_entry(node,
+ struct umevent_obj, head);
+ if (strcmp(umevent_obj_curr->kobj.name,
+ name) == 0) {
+ found_match = 1;
+ break;
+ }
+ node = NULL;
+ node = umevent_obj_curr->head.next;
+ i++;
+ }
+ if (found_match == 1)
+ return umevent_obj_curr;
+
+ return NULL;
+}
+/*EXPORT_SYMBOL(psb_umevent_find_obj); */
+/**
+ * psb_umevent_debug_dump_list - debug list dump
+ *
+ * @list: list to dump
+ *
+ */
+void psb_umevent_debug_dump_list(struct umevent_list *list)
+{
+ struct umevent_obj *umevent_obj_curr;
+ unsigned long flags;
+ struct list_head *node;
+ int i;
+ spin_lock_irqsave(&list->list_lock, flags);
+ i = 0;
+ node = NULL;
+ node = list->head.next;
+ while (node != (&list->head)) {
+ umevent_obj_curr = list_entry(node,
+ struct umevent_obj,
+ head);
+ /*TBD: DUMP ANY REQUIRED VALUES WITH PRINTK*/
+ node = NULL;
+ node = umevent_obj_curr->head.next;
+ i++;
+ }
+ spin_unlock_irqrestore(&list->list_lock, flags);
+}
--- /dev/null
+/*
+ * Copyright (c) 2009, Intel Corporation.
+ *
+ * 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 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.
+ *
+ * Authors:
+ * James C. Gualario <james.c.gualario@intel.com>
+ *
+ */
+#ifndef _PSB_UMEVENT_H_
+#define _PSB_UMEVENT_H_
+/**
+ * required includes
+ *
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <drm/drmP.h>
+#include <drm/drm_core.h>
+#include <drm/drm_pciids.h>
+#include <linux/spinlock.h>
+/**
+ * event groups for routing to different user mode threads
+ *
+ */
+#define DRM_DPST_SOCKET_GROUP_ID 1
+#define DRM_HOTPLUG_SOCKET_GROUP_ID 2
+#define DRM_HDMI_AUDIO_SOCKET_GROUP 4
+#define DRM_HDMI_HDCP_SOCKET_GROUP 8
+#define DRM_GFX_SOCKET_GROUPS 15
+/**
+ * event structure managed by kobjects
+ *
+ */
+struct umevent_obj {
+ struct kobject kobj;
+ struct list_head head;
+ int data_0_val;
+ int data_1_val;
+ int data_2_val;
+ int data_3_val;
+ int data_4_val;
+ int data_5_val;
+ int data_6_val;
+ int data_7_val;
+};
+/**
+ * event tracking list element
+ *
+ */
+struct umevent_list{
+ struct list_head head;
+ struct kset *umevent_disp_pool;
+ spinlock_t list_lock;
+};
+/**
+ * to go back and forth between kobjects and their main container
+ *
+ */
+#define to_umevent_obj(x) \
+ container_of(x, struct umevent_obj, kobj)
+
+/**
+ * event attributes exposed via sysfs
+ *
+ */
+struct umevent_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct umevent_obj *any_umevent_obj,
+ struct umevent_attribute *attr, char *buf);
+ ssize_t (*store)(struct umevent_obj *any_umevent_obj,
+ struct umevent_attribute *attr,
+ const char *buf, size_t count);
+};
+/**
+ * to go back and forth between the attribute passed to us by the OS
+ * and the umevent_attribute
+ *
+ */
+#define to_umevent_attr(x) \
+ container_of(x, struct umevent_attribute, \
+ attr)
+
+/**
+ * umevent function prototypes
+ *
+ */
+extern struct umevent_obj *psb_create_umevent_obj(const char *name,
+ struct umevent_list
+ *list);
+extern ssize_t psb_umevent_attr_show(struct kobject *kobj,
+ struct attribute *attr, char *buf);
+extern ssize_t psb_umevent_attr_store(struct kobject *kobj,
+ struct attribute *attr,
+ const char *buf, size_t len);
+extern ssize_t psb_umevent_attr_show_imp(struct umevent_obj
+ *any_umevent_obj,
+ struct umevent_attribute *attr,
+ char *buf);
+extern ssize_t psb_umevent_attr_store_imp(struct umevent_obj
+ *any_umevent_obj,
+ struct umevent_attribute *attr,
+ const char *buf, size_t count);
+extern void psb_umevent_cleanup(struct umevent_list *kill_list);
+extern int psb_umevent_init(struct kobject *parent_kobj,
+ struct umevent_list *new_umevent_list,
+ const char *name);
+extern void psb_umevent_init_list(struct umevent_list *list);
+extern void psb_umevent_debug_dump_list(struct umevent_list *list);
+extern void psb_umevent_add_to_list(struct umevent_list *list,
+ struct umevent_obj
+ *umevent_obj_to_add);
+extern void psb_umevent_destroy_list(struct umevent_list *list);
+extern struct umevent_list *psb_umevent_create_list(void);
+extern void psb_umevent_notify(struct umevent_obj *notify_disp_obj);
+extern void psb_umevent_notify_gfxsock(struct umevent_obj *notify_disp_obj,
+ int dst_group_id);
+extern void psb_umevent_obj_release(struct kobject *kobj);
+extern void psb_umevent_remove_from_list(struct umevent_list *list,
+ const char *disp_to_remove);
+extern void psb_umevent_workqueue_dispatch(int work_type, const char *name,
+ struct umevent_list *list);
+extern void psb_umevent_notify_change(struct umevent_obj *notify_disp_obj);
+extern void psb_umevent_notify_change_gfxsock(struct umevent_obj
+ *notify_disp_obj,
+ int dst_group_id);
+extern struct umevent_obj *psb_umevent_find_obj(const char *name,
+ struct umevent_list
+ *list);
+/**
+ * socket function prototypes
+ *
+ */
+extern int psb_kobject_uevent(struct kobject *kobj,
+ enum kobject_action action, int dst_group_id);
+extern int psb_kobject_uevent_env(struct kobject *kobj,
+ enum kobject_action action,
+ char *envp[], int dst_group_id);
+int psb_add_uevent_var(struct kobj_uevent_env *env,
+ const char *format, ...)
+ __attribute__((format (printf, 2, 3)));
+int psb_kobject_action_type(const char *buf,
+ size_t count, enum kobject_action *type);
+
+#if defined(CONFIG_NET)
+int psb_kobject_uevent_init(void);
+#endif
+
+#endif
--- /dev/null
+/*
+ * Copyright © 2011 Intel 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 (including the next
+ * paragraph) 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.
+ *
+ */
+
+#include "mdfld_dsi_dpi.h"
+#include "mdfld_output.h"
+#include "mdfld_dsi_pkg_sender.h"
+#include "tc35876x-dsi-lvds.h"
+
+static struct i2c_client *tc35876x_client;
+
+/* GPIO pins. FIXME: Get these from platform data (firmware) */
+#define GPIO_MIPI_BRIDGE_RESET 115
+#define GPIO_MIPI_PANEL_RESET 128
+#define GPIO_MIPI_LCD_STBYB 173
+#define GPIO_MIPI_LCD_BIAS_EN 108
+#define GPIO_MIPI_LCD_VADD 110
+
+#define FLD_MASK(start, end) (((1 << ((start) - (end) + 1)) - 1) << (end))
+#define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end))
+
+/* DSI D-PHY Layer Registers */
+#define D0W_DPHYCONTTX 0x0004
+#define CLW_DPHYCONTRX 0x0020
+#define D0W_DPHYCONTRX 0x0024
+#define D1W_DPHYCONTRX 0x0028
+#define D2W_DPHYCONTRX 0x002C
+#define D3W_DPHYCONTRX 0x0030
+#define COM_DPHYCONTRX 0x0038
+#define CLW_CNTRL 0x0040
+#define D0W_CNTRL 0x0044
+#define D1W_CNTRL 0x0048
+#define D2W_CNTRL 0x004C
+#define D3W_CNTRL 0x0050
+#define DFTMODE_CNTRL 0x0054
+
+/* DSI PPI Layer Registers */
+#define PPI_STARTPPI 0x0104
+#define PPI_BUSYPPI 0x0108
+#define PPI_LINEINITCNT 0x0110
+#define PPI_LPTXTIMECNT 0x0114
+#define PPI_LANEENABLE 0x0134
+#define PPI_TX_RX_TA 0x013C
+#define PPI_CLS_ATMR 0x0140
+#define PPI_D0S_ATMR 0x0144
+#define PPI_D1S_ATMR 0x0148
+#define PPI_D2S_ATMR 0x014C
+#define PPI_D3S_ATMR 0x0150
+#define PPI_D0S_CLRSIPOCOUNT 0x0164
+#define PPI_D1S_CLRSIPOCOUNT 0x0168
+#define PPI_D2S_CLRSIPOCOUNT 0x016C
+#define PPI_D3S_CLRSIPOCOUNT 0x0170
+#define CLS_PRE 0x0180
+#define D0S_PRE 0x0184
+#define D1S_PRE 0x0188
+#define D2S_PRE 0x018C
+#define D3S_PRE 0x0190
+#define CLS_PREP 0x01A0
+#define D0S_PREP 0x01A4
+#define D1S_PREP 0x01A8
+#define D2S_PREP 0x01AC
+#define D3S_PREP 0x01B0
+#define CLS_ZERO 0x01C0
+#define D0S_ZERO 0x01C4
+#define D1S_ZERO 0x01C8
+#define D2S_ZERO 0x01CC
+#define D3S_ZERO 0x01D0
+#define PPI_CLRFLG 0x01E0
+#define PPI_CLRSIPO 0x01E4
+#define HSTIMEOUT 0x01F0
+#define HSTIMEOUTENABLE 0x01F4
+
+/* DSI Protocol Layer Registers */
+#define DSI_STARTDSI 0x0204
+#define DSI_BUSYDSI 0x0208
+#define DSI_LANEENABLE 0x0210
+#define DSI_LANESTATUS0 0x0214
+#define DSI_LANESTATUS1 0x0218
+#define DSI_INTSTATUS 0x0220
+#define DSI_INTMASK 0x0224
+#define DSI_INTCLR 0x0228
+#define DSI_LPTXTO 0x0230
+
+/* DSI General Registers */
+#define DSIERRCNT 0x0300
+
+/* DSI Application Layer Registers */
+#define APLCTRL 0x0400
+#define RDPKTLN 0x0404
+
+/* Video Path Registers */
+#define VPCTRL 0x0450
+#define HTIM1 0x0454
+#define HTIM2 0x0458
+#define VTIM1 0x045C
+#define VTIM2 0x0460
+#define VFUEN 0x0464
+
+/* LVDS Registers */
+#define LVMX0003 0x0480
+#define LVMX0407 0x0484
+#define LVMX0811 0x0488
+#define LVMX1215 0x048C
+#define LVMX1619 0x0490
+#define LVMX2023 0x0494
+#define LVMX2427 0x0498
+#define LVCFG 0x049C
+#define LVPHY0 0x04A0
+#define LVPHY1 0x04A4
+
+/* System Registers */
+#define SYSSTAT 0x0500
+#define SYSRST 0x0504
+
+/* GPIO Registers */
+#define GPIOC 0x0520
+#define GPIOO 0x0524
+#define GPIOI 0x0528
+
+/* I2C Registers */
+#define I2CTIMCTRL 0x0540
+#define I2CMADDR 0x0544
+#define WDATAQ 0x0548
+#define RDATAQ 0x054C
+
+/* Chip/Rev Registers */
+#define IDREG 0x0580
+
+/* Debug Registers */
+#define DEBUG00 0x05A0
+#define DEBUG01 0x05A4
+
+/* Input muxing for registers LVMX0003...LVMX2427 */
+enum {
+ INPUT_R0, /* 0 */
+ INPUT_R1,
+ INPUT_R2,
+ INPUT_R3,
+ INPUT_R4,
+ INPUT_R5,
+ INPUT_R6,
+ INPUT_R7,
+ INPUT_G0, /* 8 */
+ INPUT_G1,
+ INPUT_G2,
+ INPUT_G3,
+ INPUT_G4,
+ INPUT_G5,
+ INPUT_G6,
+ INPUT_G7,
+ INPUT_B0, /* 16 */
+ INPUT_B1,
+ INPUT_B2,
+ INPUT_B3,
+ INPUT_B4,
+ INPUT_B5,
+ INPUT_B6,
+ INPUT_B7,
+ INPUT_HSYNC, /* 24 */
+ INPUT_VSYNC,
+ INPUT_DE,
+ LOGIC_0,
+ /* 28...31 undefined */
+};
+
+#define INPUT_MUX(lvmx03, lvmx02, lvmx01, lvmx00) \
+ (FLD_VAL(lvmx03, 29, 24) | FLD_VAL(lvmx02, 20, 16) | \
+ FLD_VAL(lvmx01, 12, 8) | FLD_VAL(lvmx00, 4, 0))
+
+/**
+ * tc35876x_regw - Write DSI-LVDS bridge register using I2C
+ * @client: struct i2c_client to use
+ * @reg: register address
+ * @value: value to write
+ *
+ * Returns 0 on success, or a negative error value.
+ */
+static int tc35876x_regw(struct i2c_client *client, u16 reg, u32 value)
+{
+ int r;
+ u8 tx_data[] = {
+ /* NOTE: Register address big-endian, data little-endian. */
+ (reg >> 8) & 0xff,
+ reg & 0xff,
+ value & 0xff,
+ (value >> 8) & 0xff,
+ (value >> 16) & 0xff,
+ (value >> 24) & 0xff,
+ };
+ struct i2c_msg msgs[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .buf = tx_data,
+ .len = ARRAY_SIZE(tx_data),
+ },
+ };
+
+ r = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+ if (r < 0) {
+ dev_err(&client->dev, "%s: reg 0x%04x val 0x%08x error %d\n",
+ __func__, reg, value, r);
+ return r;
+ }
+
+ if (r < ARRAY_SIZE(msgs)) {
+ dev_err(&client->dev, "%s: reg 0x%04x val 0x%08x msgs %d\n",
+ __func__, reg, value, r);
+ return -EAGAIN;
+ }
+
+ dev_dbg(&client->dev, "%s: reg 0x%04x val 0x%08x\n", __func__, reg,
+ value);
+
+ return 0;
+}
+
+/**
+ * tc35876x_regr - Read DSI-LVDS bridge register using I2C
+ * @client: struct i2c_client to use
+ * @reg: register address
+ * @value: pointer for storing the value
+ *
+ * Returns 0 on success, or a negative error value.
+ */
+static int tc35876x_regr(struct i2c_client *client, u16 reg, u32 *value)
+{
+ int r;
+ u8 tx_data[] = {
+ (reg >> 8) & 0xff,
+ reg & 0xff,
+ };
+ u8 rx_data[4];
+ struct i2c_msg msgs[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .buf = tx_data,
+ .len = ARRAY_SIZE(tx_data),
+ },
+ {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .buf = rx_data,
+ .len = ARRAY_SIZE(rx_data),
+ },
+ };
+
+ r = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+ if (r < 0) {
+ dev_err(&client->dev, "%s: reg 0x%04x error %d\n", __func__,
+ reg, r);
+ return r;
+ }
+
+ if (r < ARRAY_SIZE(msgs)) {
+ dev_err(&client->dev, "%s: reg 0x%04x msgs %d\n", __func__,
+ reg, r);
+ return -EAGAIN;
+ }
+
+ *value = rx_data[0] << 24 | rx_data[1] << 16 |
+ rx_data[2] << 8 | rx_data[3];
+
+ dev_dbg(&client->dev, "%s: reg 0x%04x value 0x%08x\n", __func__,
+ reg, *value);
+
+ return 0;
+}
+
+void tc35876x_set_bridge_reset_state(int state)
+{
+ WARN_ON(!tc35876x_client);
+ dev_dbg(&tc35876x_client->dev, "%s: state %d\n", __func__, state);
+
+ if (state) {
+ gpio_set_value_cansleep(GPIO_MIPI_BRIDGE_RESET, 0);
+ mdelay(10);
+ } else {
+ /* Pull MIPI Bridge reset pin to Low */
+ gpio_set_value_cansleep(GPIO_MIPI_BRIDGE_RESET, 0);
+ mdelay(20);
+ /* Pull MIPI Bridge reset pin to High */
+ gpio_set_value_cansleep(GPIO_MIPI_BRIDGE_RESET, 1);
+ mdelay(40);
+ }
+}
+
+void tc35876x_configure_lvds_bridge(struct drm_device *dev)
+{
+ struct i2c_client *i2c = tc35876x_client;
+ u32 ppi_lptxtimecnt;
+ u32 txtagocnt;
+ u32 txtasurecnt;
+ u32 id;
+
+ WARN_ON(!tc35876x_client);
+ dev_dbg(&tc35876x_client->dev, "%s\n", __func__);
+
+ tc35876x_regr(i2c, IDREG, &id);
+ dev_info(&tc35876x_client->dev, "tc35876x ID 0x%08x\n", id);
+
+ ppi_lptxtimecnt = 4;
+ txtagocnt = (5 * ppi_lptxtimecnt - 3) / 4;
+ txtasurecnt = 3 * ppi_lptxtimecnt / 2;
+ tc35876x_regw(i2c, PPI_TX_RX_TA, FLD_VAL(txtagocnt, 26, 16) |
+ FLD_VAL(txtasurecnt, 10, 0));
+ tc35876x_regw(i2c, PPI_LPTXTIMECNT, FLD_VAL(ppi_lptxtimecnt, 10, 0));
+
+ tc35876x_regw(i2c, PPI_D0S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0));
+ tc35876x_regw(i2c, PPI_D1S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0));
+ tc35876x_regw(i2c, PPI_D2S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0));
+ tc35876x_regw(i2c, PPI_D3S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0));
+
+ /* Enabling MIPI & PPI lanes, Enable 4 lanes */
+ tc35876x_regw(i2c, PPI_LANEENABLE,
+ BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0));
+ tc35876x_regw(i2c, DSI_LANEENABLE,
+ BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0));
+ tc35876x_regw(i2c, PPI_STARTPPI, BIT(0));
+ tc35876x_regw(i2c, DSI_STARTDSI, BIT(0));
+
+ /* Setting LVDS output frequency */
+ tc35876x_regw(i2c, LVPHY0, FLD_VAL(1, 20, 16) |
+ FLD_VAL(2, 15, 14) | FLD_VAL(6, 4, 0)); /* 0x00048006 */
+
+ /* Setting video panel control register,0x00000120 VTGen=ON ?!?!? */
+ tc35876x_regw(i2c, VPCTRL, BIT(8) | BIT(5));
+
+ /* Horizontal back porch and horizontal pulse width. 0x00280028 */
+ tc35876x_regw(i2c, HTIM1, FLD_VAL(40, 24, 16) | FLD_VAL(40, 8, 0));
+
+ /* Horizontal front porch and horizontal active video size. 0x00500500*/
+ tc35876x_regw(i2c, HTIM2, FLD_VAL(80, 24, 16) | FLD_VAL(1280, 10, 0));
+
+ /* Vertical back porch and vertical sync pulse width. 0x000e000a */
+ tc35876x_regw(i2c, VTIM1, FLD_VAL(14, 23, 16) | FLD_VAL(10, 7, 0));
+
+ /* Vertical front porch and vertical display size. 0x000e0320 */
+ tc35876x_regw(i2c, VTIM2, FLD_VAL(14, 23, 16) | FLD_VAL(800, 10, 0));
+
+ /* Set above HTIM1, HTIM2, VTIM1, and VTIM2 at next VSYNC. */
+ tc35876x_regw(i2c, VFUEN, BIT(0));
+
+ /* LVDS-TX input muxing */
+ tc35876x_regw(i2c, LVMX0003, /* 0x03020100 */
+ INPUT_MUX(INPUT_R3, INPUT_R2, INPUT_R1, INPUT_R0));
+ tc35876x_regw(i2c, LVMX0407, /* 0x08050704 */
+ INPUT_MUX(INPUT_G0, INPUT_R5, INPUT_R7, INPUT_R4));
+ tc35876x_regw(i2c, LVMX0811, /* 0x0F0E0A09 */
+ INPUT_MUX(INPUT_G7, INPUT_G6, INPUT_G2, INPUT_G1));
+ tc35876x_regw(i2c, LVMX1215, /* 0x100D0C0B */
+ INPUT_MUX(INPUT_B0, INPUT_G5, INPUT_G4, INPUT_G3));
+ tc35876x_regw(i2c, LVMX1619, /* 0x12111716 */
+ INPUT_MUX(INPUT_B2, INPUT_B1, INPUT_B7, INPUT_B6));
+ tc35876x_regw(i2c, LVMX2023, /* 0x1B151413 */
+ INPUT_MUX(LOGIC_0, INPUT_B5, INPUT_B4, INPUT_B3));
+ tc35876x_regw(i2c, LVMX2427, /* 0x061A1918 */
+ INPUT_MUX(INPUT_R6, INPUT_DE, INPUT_VSYNC, INPUT_HSYNC));
+
+ /* Enable LVDS transmitter. */
+ tc35876x_regw(i2c, LVCFG, BIT(0));
+
+ /* Clear notifications. Don't write reserved bits. Was write 0xffffffff
+ * to 0x0288, must be in error?! */
+ tc35876x_regw(i2c, DSI_INTCLR, FLD_MASK(31, 30) | FLD_MASK(22, 0));
+}
+
+void tc35876x_toshiba_bridge_panel_off(void)
+{
+ WARN_ON(!tc35876x_client);
+ dev_dbg(&tc35876x_client->dev, "%s\n", __func__);
+
+ gpio_set_value_cansleep(GPIO_MIPI_LCD_STBYB, 0);
+ mdelay(1);
+
+ gpio_set_value_cansleep(GPIO_MIPI_PANEL_RESET, 0);
+ mdelay(1);
+}
+
+void tc35876x_toshiba_bridge_panel_on(void)
+{
+ WARN_ON(!tc35876x_client);
+ dev_dbg(&tc35876x_client->dev, "%s\n", __func__);
+
+ gpio_set_value_cansleep(GPIO_MIPI_LCD_STBYB, 0);
+ gpio_set_value_cansleep(GPIO_MIPI_PANEL_RESET, 0);
+ gpio_set_value_cansleep(GPIO_MIPI_LCD_VADD, 0);
+ gpio_set_value_cansleep(GPIO_MIPI_LCD_BIAS_EN, 0);
+ mdelay(10);
+
+ gpio_set_value_cansleep(GPIO_MIPI_LCD_STBYB, 1);
+ mdelay(10);
+
+ gpio_set_value_cansleep(GPIO_MIPI_LCD_VADD, 1);
+ mdelay(50);
+
+ gpio_set_value_cansleep(GPIO_MIPI_PANEL_RESET, 1);
+ mdelay(100);
+
+ gpio_set_value_cansleep(GPIO_MIPI_LCD_BIAS_EN, 1);
+}
+
+void tc35876x_bridge_get_display_params(struct drm_display_mode *mode)
+{
+ WARN_ON(!tc35876x_client);
+ dev_dbg(&tc35876x_client->dev, "%s\n", __func__);
+
+ /* FIXME: do this properly. */
+ mode->hdisplay = 1280;
+ mode->vdisplay = 800;
+ mode->hsync_start = 1360;
+ mode->hsync_end = 1400;
+ mode->htotal = 1440;
+ mode->vsync_start = 814;
+ mode->vsync_end = 824;
+ mode->vtotal = 838;
+ mode->clock = 33324;
+
+ dev_info(&tc35876x_client->dev, "hdisplay(w) = %d\n", mode->hdisplay);
+ dev_info(&tc35876x_client->dev, "vdisplay(h) = %d\n", mode->vdisplay);
+ dev_info(&tc35876x_client->dev, "HSS = %d\n", mode->hsync_start);
+ dev_info(&tc35876x_client->dev, "HSE = %d\n", mode->hsync_end);
+ dev_info(&tc35876x_client->dev, "htotal = %d\n", mode->htotal);
+ dev_info(&tc35876x_client->dev, "VSS = %d\n", mode->vsync_start);
+ dev_info(&tc35876x_client->dev, "VSE = %d\n", mode->vsync_end);
+ dev_info(&tc35876x_client->dev, "vtotal = %d\n", mode->vtotal);
+ dev_info(&tc35876x_client->dev, "clock = %d\n", mode->clock);
+}
+
+static int tc35876x_bridge_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ dev_info(&client->dev, "%s\n", __func__);
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ dev_err(&client->dev, "%s: i2c_check_functionality() failed\n",
+ __func__);
+ return -ENODEV;
+ }
+
+ /* FIXME: get GPIOs from platform data, check for errors. */
+ gpio_request(GPIO_MIPI_BRIDGE_RESET, "tc35876x bridge reset");
+ gpio_direction_output(GPIO_MIPI_BRIDGE_RESET, 0);
+
+ gpio_request(GPIO_MIPI_PANEL_RESET, "tc35876x panel reset");
+ gpio_direction_output(GPIO_MIPI_PANEL_RESET, 0);
+
+ gpio_request(GPIO_MIPI_LCD_STBYB, "tc35876x lcd stbyb");
+ gpio_direction_output(GPIO_MIPI_LCD_STBYB, 0);
+
+ gpio_request(GPIO_MIPI_LCD_BIAS_EN, "tc35876x lcd bias en");
+ gpio_direction_output(GPIO_MIPI_LCD_BIAS_EN, 0);
+
+ gpio_request(GPIO_MIPI_LCD_VADD, "tc35876x lcd vadd");
+ gpio_direction_output(GPIO_MIPI_LCD_VADD, 0);
+
+ tc35876x_client = client;
+
+ return 0;
+}
+
+static int tc35876x_bridge_remove(struct i2c_client *client)
+{
+ dev_dbg(&client->dev, "%s\n", __func__);
+
+ gpio_free(GPIO_MIPI_BRIDGE_RESET);
+ gpio_free(GPIO_MIPI_PANEL_RESET);
+ gpio_free(GPIO_MIPI_LCD_STBYB);
+ gpio_free(GPIO_MIPI_LCD_BIAS_EN);
+ gpio_free(GPIO_MIPI_LCD_VADD);
+
+ tc35876x_client = NULL;
+
+ return 0;
+}
+
+static const struct i2c_device_id tc35876x_bridge_id[] = {
+ { "tc35876x", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, tc35876x_bridge_id);
+
+static struct i2c_driver tc35876x_bridge_i2c_driver = {
+ .driver = {
+ .name = "tc35876x",
+ },
+ .id_table = tc35876x_bridge_id,
+ .probe = tc35876x_bridge_probe,
+ .remove = __devexit_p(tc35876x_bridge_remove),
+};
+
+#if 1
+#define TC35876X_I2C_ADAPTER 2
+#define TC35876X_I2C_ADDR 0x0f
+
+/* HACK to create I2C device while it's not created by platform code */
+static int __init tc35876x_hack_create_device(void)
+{
+ struct i2c_adapter *adapter;
+ struct i2c_client *client;
+ struct i2c_board_info info = {
+ .type = "tc35876x",
+ .addr = TC35876X_I2C_ADDR,
+ };
+
+ pr_debug("%s\n", __func__);
+
+ adapter = i2c_get_adapter(TC35876X_I2C_ADAPTER);
+ if (!adapter) {
+ pr_err("%s: i2c_get_adapter(%d) failed\n", __func__,
+ TC35876X_I2C_ADAPTER);
+ return -EINVAL;
+ }
+
+ client = i2c_new_device(adapter, &info);
+ if (!client) {
+ pr_err("%s: i2c_new_device() failed\n", __func__);
+ i2c_put_adapter(adapter);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+#else
+static inline int __init tc35876x_hack_create_device(void)
+{
+ return 0;
+}
+#endif
+
+int tc35876x_bridge_init(void)
+{
+ int r;
+
+ pr_debug("%s\n", __func__);
+
+ r = tc35876x_hack_create_device();
+ if (r)
+ return r;
+
+ return i2c_add_driver(&tc35876x_bridge_i2c_driver);
+}
+
+void tc35876x_bridge_exit(void)
+{
+ pr_debug("%s\n", __func__);
+
+ i2c_del_driver(&tc35876x_bridge_i2c_driver);
+}
--- /dev/null
+/*
+ * Copyright © 2011 Intel 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 (including the next
+ * paragraph) 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.
+ *
+ */
+
+#ifndef __MDFLD_DSI_LVDS_BRIDGE_H__
+#define __MDFLD_DSI_LVDS_BRIDGE_H__
+
+void tc35876x_set_bridge_reset_state(int state);
+void tc35876x_configure_lvds_bridge(struct drm_device *dev);
+void tc35876x_toshiba_bridge_panel_off(void);
+void tc35876x_toshiba_bridge_panel_on(void);
+void tc35876x_bridge_get_display_params(struct drm_display_mode *mode);
+int tc35876x_bridge_init(void);
+void tc35876x_bridge_exit(void);
+
+#endif /*__MDFLD_DSI_LVDS_BRIDGE_H__*/
--- /dev/null
+/*
+ * Copyright © 2010 Intel 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 (including the next
+ * paragraph) 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.
+ *
+ * Authors:
+ * Jim Liu <jim.liu@intel.com>
+ * Jackie Li<yaodong.li@intel.com>
+ * Gideon Eaton <eaton.
+ * Scott Rowe <scott.m.rowe@intel.com>
+ */
+
+#include "displays/tmd_vid.h"
+#include "mdfld_dsi_dpi.h"
+#include "mdfld_dsi_pkg_sender.h"
+#include "tc35876x-dsi-lvds.h"
+
+static struct drm_display_mode*
+tmd_vid_get_config_mode(struct drm_device* dev)
+{
+ struct drm_display_mode *mode;
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) dev->dev_private;
+ struct mrst_timing_info *ti = &dev_priv->gct_data.DTD;
+ bool use_gct = false; /*Disable GCT for now*/
+
+ PSB_DEBUG_ENTRY("\n");
+
+ mode = kzalloc(sizeof(*mode), GFP_KERNEL);
+ if (!mode)
+ return NULL;
+
+ if (get_panel_type(dev, 0) == TC35876X) { /* FIXME: pipe */
+ tc35876x_bridge_get_display_params(mode);
+ } else if (use_gct) {
+ PSB_DEBUG_ENTRY("gct find MIPI panel. \n");
+
+ mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo;
+ mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo;
+ mode->hsync_start = mode->hdisplay + \
+ ((ti->hsync_offset_hi << 8) | \
+ ti->hsync_offset_lo);
+ mode->hsync_end = mode->hsync_start + \
+ ((ti->hsync_pulse_width_hi << 8) | \
+ ti->hsync_pulse_width_lo);
+ mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \
+ ti->hblank_lo);
+ mode->vsync_start = \
+ mode->vdisplay + ((ti->vsync_offset_hi << 8) | \
+ ti->vsync_offset_lo);
+ mode->vsync_end = \
+ mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \
+ ti->vsync_pulse_width_lo);
+ mode->vtotal = mode->vdisplay + \
+ ((ti->vblank_hi << 8) | ti->vblank_lo);
+ mode->clock = ti->pixel_clock * 10;
+
+ PSB_DEBUG_ENTRY("hdisplay is %d\n", mode->hdisplay);
+ PSB_DEBUG_ENTRY("vdisplay is %d\n", mode->vdisplay);
+ PSB_DEBUG_ENTRY("HSS is %d\n", mode->hsync_start);
+ PSB_DEBUG_ENTRY("HSE is %d\n", mode->hsync_end);
+ PSB_DEBUG_ENTRY("htotal is %d\n", mode->htotal);
+ PSB_DEBUG_ENTRY("VSS is %d\n", mode->vsync_start);
+ PSB_DEBUG_ENTRY("VSE is %d\n", mode->vsync_end);
+ PSB_DEBUG_ENTRY("vtotal is %d\n", mode->vtotal);
+ PSB_DEBUG_ENTRY("clock is %d\n", mode->clock);
+ } else {
+ mode->hdisplay = 480;
+ mode->vdisplay = 854;
+ mode->hsync_start = 487;
+ mode->hsync_end = 490;
+ mode->htotal = 499;
+ mode->vsync_start = 861;
+ mode->vsync_end = 865;
+ mode->vtotal = 873;
+ mode->clock = 33264;
+ }
+
+ drm_mode_set_name(mode);
+ drm_mode_set_crtcinfo(mode, 0);
+
+ mode->type |= DRM_MODE_TYPE_PREFERRED;
+
+ return mode;
+}
+
+static int tmd_vid_get_panel_info(struct drm_device * dev,
+ int pipe,
+ struct panel_info * pi)
+{
+ if(!dev || !pi)
+ return -EINVAL;
+
+ pi->width_mm = TMD_PANEL_WIDTH;
+ pi->height_mm = TMD_PANEL_HEIGHT;
+
+ return 0;
+}
+
+/* ************************************************************************* *\
+ * FUNCTION: mdfld_init_TMD_MIPI
+ *
+ * DESCRIPTION: This function is called only by mrst_dsi_mode_set and
+ * restore_display_registers. since this function does not
+ * acquire the mutex, it is important that the calling function
+ * does!
+\* ************************************************************************* */
+
+/* FIXME: make the below data u8 instead of u32; note byte order! */
+static u32 tmd_cmd_mcap_off[] = {0x000000b2};
+static u32 tmd_cmd_enable_lane_switch[] = {0x000101ef};
+static u32 tmd_cmd_set_lane_num[] = {0x006360ef};
+static u32 tmd_cmd_pushing_clock0[] = {0x00cc2fef};
+static u32 tmd_cmd_pushing_clock1[] = {0x00dd6eef};
+static u32 tmd_cmd_set_mode[] = {0x000000b3};
+static u32 tmd_cmd_set_sync_pulse_mode[] = {0x000961ef};
+static u32 tmd_cmd_set_column[] = {0x0100002a, 0x000000df};
+static u32 tmd_cmd_set_page[] = {0x0300002b, 0x00000055};
+static u32 tmd_cmd_set_video_mode[] = {0x00000153};
+/*no auto_bl,need add in furture*/
+static u32 tmd_cmd_enable_backlight[] = {0x00005ab4};
+static u32 tmd_cmd_set_backlight_dimming[] = {0x00000ebd};
+
+static void mdfld_dsi_tmd_drv_ic_init(struct mdfld_dsi_config *dsi_config,
+ int pipe)
+{
+ struct mdfld_dsi_pkg_sender *sender
+ = mdfld_dsi_get_pkg_sender(dsi_config);
+
+ DRM_INFO("Enter mdfld init TMD MIPI display.\n");
+
+ if (!sender) {
+ DRM_ERROR("Cannot get sender\n");
+ return;
+ }
+
+ if (dsi_config->dvr_ic_inited)
+ return;
+
+ msleep(3);
+
+ /* FIXME: make the below data u8 instead of u32; note byte order! */
+
+ mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_mcap_off,
+ sizeof(tmd_cmd_mcap_off), false);
+ mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_enable_lane_switch,
+ sizeof(tmd_cmd_enable_lane_switch), false);
+ mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_set_lane_num,
+ sizeof(tmd_cmd_set_lane_num), false);
+ mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_pushing_clock0,
+ sizeof(tmd_cmd_pushing_clock0), false);
+ mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_pushing_clock1,
+ sizeof(tmd_cmd_pushing_clock1), false);
+ mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_set_mode,
+ sizeof(tmd_cmd_set_mode), false);
+ mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_set_sync_pulse_mode,
+ sizeof(tmd_cmd_set_sync_pulse_mode), false);
+ mdfld_dsi_send_mcs_long(sender, (u8 *) tmd_cmd_set_column,
+ sizeof(tmd_cmd_set_column), false);
+ mdfld_dsi_send_mcs_long(sender, (u8 *) tmd_cmd_set_page,
+ sizeof(tmd_cmd_set_page), false);
+ mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_set_video_mode,
+ sizeof(tmd_cmd_set_video_mode), false);
+ mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_enable_backlight,
+ sizeof(tmd_cmd_enable_backlight), false);
+ mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_set_backlight_dimming,
+ sizeof(tmd_cmd_set_backlight_dimming), false);
+
+ dsi_config->dvr_ic_inited = 1;
+}
+
+/*TPO DPI encoder helper funcs*/
+static const struct drm_encoder_helper_funcs mdfld_tpo_dpi_encoder_helper_funcs = {
+ .dpms = mdfld_dsi_dpi_dpms,
+ .mode_fixup = mdfld_dsi_dpi_mode_fixup,
+ .prepare = mdfld_dsi_dpi_prepare,
+ .mode_set = mdfld_dsi_dpi_mode_set,
+ .commit = mdfld_dsi_dpi_commit,
+};
+
+/*TPO DPI encoder funcs*/
+static const struct drm_encoder_funcs mdfld_tpo_dpi_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
+void tmd_vid_init(struct drm_device* dev, struct panel_funcs* p_funcs)
+{
+ if(!dev || !p_funcs) {
+ DRM_ERROR("Invalid parameters\n");
+ return;
+ }
+
+ PSB_DEBUG_ENTRY("\n");
+
+ p_funcs->encoder_funcs = &mdfld_tpo_dpi_encoder_funcs;
+ p_funcs->encoder_helper_funcs = &mdfld_tpo_dpi_encoder_helper_funcs;
+ p_funcs->get_config_mode = &tmd_vid_get_config_mode;
+ p_funcs->update_fb = NULL;
+ p_funcs->get_panel_info = tmd_vid_get_panel_info;
+ if (get_panel_type(dev, 0) != TC35876X) { /* FIXME: pipe */
+ p_funcs->reset = mdfld_dsi_panel_reset;
+ p_funcs->drv_ic_init = mdfld_dsi_tmd_drv_ic_init;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2010 Intel 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, sublicensen
+ * 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 (including the next
+ * paragraph) 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.
+ *
+ * Authors:
+ * Thomas Eaton <thomas.g.eaton@intel.com>
+ * Scott Rowe <scott.m.rowe@intel.com>
+*/
+
+
+
+#include "displays/tpo_cmd.h"
+#include "mdfld_dsi_dbi.h"
+#include "mdfld_dsi_dbi_dpu.h"
+#include "mdfld_dsi_pkg_sender.h"
+#include "psb_powermgmt.h"
+
+static struct drm_display_mode*
+tpo_cmd_get_config_mode(struct drm_device* dev)
+{
+ struct drm_display_mode *mode;
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) dev->dev_private;
+ struct mrst_timing_info *ti = &dev_priv->gct_data.DTD;
+ bool use_gct = false;
+
+ PSB_DEBUG_ENTRY("\n");
+
+ mode = kzalloc(sizeof(*mode), GFP_KERNEL);
+ if (!mode)
+ return NULL;
+
+ if (use_gct) {
+ PSB_DEBUG_ENTRY("gct find MIPI panel. \n");
+
+ mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo;
+ mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo;
+ mode->hsync_start = mode->hdisplay + \
+ ((ti->hsync_offset_hi << 8) | \
+ ti->hsync_offset_lo);
+ mode->hsync_end = mode->hsync_start + \
+ ((ti->hsync_pulse_width_hi << 8) | \
+ ti->hsync_pulse_width_lo);
+ mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \
+ ti->hblank_lo);
+ mode->vsync_start = \
+ mode->vdisplay + ((ti->vsync_offset_hi << 8) | \
+ ti->vsync_offset_lo);
+ mode->vsync_end = \
+ mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \
+ ti->vsync_pulse_width_lo);
+ mode->vtotal = mode->vdisplay + \
+ ((ti->vblank_hi << 8) | ti->vblank_lo);
+ mode->clock = ti->pixel_clock * 10;
+
+ PSB_DEBUG_ENTRY("hdisplay is %d\n", mode->hdisplay);
+ PSB_DEBUG_ENTRY("vdisplay is %d\n", mode->vdisplay);
+ PSB_DEBUG_ENTRY("HSS is %d\n", mode->hsync_start);
+ PSB_DEBUG_ENTRY("HSE is %d\n", mode->hsync_end);
+ PSB_DEBUG_ENTRY("htotal is %d\n", mode->htotal);
+ PSB_DEBUG_ENTRY("VSS is %d\n", mode->vsync_start);
+ PSB_DEBUG_ENTRY("VSE is %d\n", mode->vsync_end);
+ PSB_DEBUG_ENTRY("vtotal is %d\n", mode->vtotal);
+ PSB_DEBUG_ENTRY("clock is %d\n", mode->clock);
+ } else {
+ mode->hdisplay = 864;
+ mode->vdisplay = 480;
+ mode->hsync_start = 872;
+ mode->hsync_end = 876;
+ mode->htotal = 884;
+ mode->vsync_start = 482;
+ mode->vsync_end = 494;
+ mode->vtotal = 486;
+ mode->clock = 25777;
+ }
+
+ drm_mode_set_name(mode);
+ drm_mode_set_crtcinfo(mode, 0);
+
+ mode->type |= DRM_MODE_TYPE_PREFERRED;
+
+ return mode;
+}
+
+static bool mdfld_dsi_dbi_mode_fixup(struct drm_encoder * encoder,
+ struct drm_display_mode * mode,
+ struct drm_display_mode * adjusted_mode)
+{
+ struct drm_device* dev = encoder->dev;
+ struct drm_display_mode * fixed_mode = tpo_cmd_get_config_mode(dev);
+
+ PSB_DEBUG_ENTRY("\n");
+
+ if(fixed_mode) {
+ adjusted_mode->hdisplay = fixed_mode->hdisplay;
+ adjusted_mode->hsync_start = fixed_mode->hsync_start;
+ adjusted_mode->hsync_end = fixed_mode->hsync_end;
+ adjusted_mode->htotal = fixed_mode->htotal;
+ adjusted_mode->vdisplay = fixed_mode->vdisplay;
+ adjusted_mode->vsync_start = fixed_mode->vsync_start;
+ adjusted_mode->vsync_end = fixed_mode->vsync_end;
+ adjusted_mode->vtotal = fixed_mode->vtotal;
+ adjusted_mode->clock = fixed_mode->clock;
+ drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
+ kfree(fixed_mode);
+ }
+
+ return true;
+}
+
+static void mdfld_dsi_dbi_set_power(struct drm_encoder *encoder, bool on)
+{
+ int ret = 0;
+ struct mdfld_dsi_encoder *dsi_encoder =
+ MDFLD_DSI_ENCODER(encoder);
+ struct mdfld_dsi_dbi_output *dbi_output =
+ MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
+ struct mdfld_dsi_config *dsi_config =
+ mdfld_dsi_encoder_get_config(dsi_encoder);
+ struct mdfld_dsi_pkg_sender *sender =
+ mdfld_dsi_encoder_get_pkg_sender(dsi_encoder);
+ /*struct drm_device * dev = dbi_output->dev;*/
+ struct drm_device* dev = encoder->dev;
+ struct drm_psb_private * dev_priv = dev->dev_private;
+ int pipe = (dbi_output->channel_num == 0) ? 0 : 2;
+ u32 data = 0;
+
+ PSB_DEBUG_ENTRY("pipe %d : %s, panel on: %s\n",pipe, on ? "On" : "Off", dbi_output->dbi_panel_on ? "True" : "False");
+
+ if(pipe == 2) {
+ if(on)
+ dev_priv->dual_mipi = true;
+ else
+ dev_priv->dual_mipi = false;
+ } else {
+ if (!on)
+ dev_priv->dual_mipi = false;
+ }
+
+ if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) {
+ DRM_ERROR("hw begin failed\n");
+ return;
+ }
+
+
+ if(on) {
+ if(dbi_output->dbi_panel_on)
+ goto out_err;
+
+ ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_ON);
+ if(ret) {
+ DRM_ERROR("power on error\n");
+ goto out_err;
+ }
+
+ dbi_output->dbi_panel_on = true;
+
+ if(pipe == 2)
+ dev_priv->dbi_panel_on2 = true;
+ else
+ dev_priv->dbi_panel_on = true;
+
+ mdfld_enable_te(dev, pipe);
+ } else {
+ if(!dbi_output->dbi_panel_on && !dbi_output->first_boot)
+ goto out_err;
+
+ dbi_output->dbi_panel_on = false;
+ dbi_output->first_boot = false;
+
+ if (pipe == 2)
+ dev_priv->dbi_panel_on2 = false;
+ else
+ dev_priv->dbi_panel_on = false;
+
+ mdfld_disable_te(dev, pipe);
+
+ ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_OFF);
+ if(ret) {
+ DRM_ERROR("power on error\n");
+ goto out_err;
+ }
+ }
+
+ /**
+ * FIXME: this is a WA for TPO panel crash on DPMS on & off around
+ * 83 times. the root cause of this issue is that Booster in
+ * drvIC crashed. Add this WA so that we can resume the driver IC
+ * once we found that booster has a fault
+ */
+ mdfld_dsi_get_power_mode(dsi_config, &data, true);
+ if (on && data && !(data & BIT(7))) {
+ /*soft reset*/
+ mdfld_dsi_send_mcs_short(sender, DCS_SOFT_RESET, 0, 0, true);
+
+ /*init drvIC*/
+ if (dbi_output->p_funcs->drv_ic_init)
+ dbi_output->p_funcs->drv_ic_init(dsi_config,
+ pipe);
+ }
+
+out_err:
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+
+ if(ret)
+ DRM_ERROR("failed\n");
+ else
+ PSB_DEBUG_ENTRY("successfully\n");
+}
+
+
+static void mdfld_dsi_dbi_mode_set(struct drm_encoder * encoder,
+ struct drm_display_mode * mode,
+ struct drm_display_mode * adjusted_mode)
+{
+ int ret = 0;
+ struct drm_device * dev = encoder->dev;
+ struct drm_psb_private * dev_priv = (struct drm_psb_private*)dev->dev_private;
+ struct mdfld_dsi_encoder * dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+ struct mdfld_dsi_dbi_output * dsi_output = MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
+ struct mdfld_dsi_config * dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder);
+ struct mdfld_dsi_connector * dsi_connector = dsi_config->connector;
+ struct mdfld_dsi_pkg_sender *sender =
+ mdfld_dsi_encoder_get_pkg_sender(&dsi_output->base);
+ int pipe = dsi_connector->pipe;
+
+ /*regs*/
+ u32 dspcntr_reg = DSPACNTR;
+ u32 pipeconf_reg = PIPEACONF;
+
+ /*values*/
+ u32 dspcntr_val = dev_priv->dspcntr;
+ u32 pipeconf_val = dev_priv->pipeconf;
+ u32 h_active_area = mode->hdisplay;
+ u32 v_active_area = mode->vdisplay;
+ u32 mipi_val = (PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX);
+
+ mipi_val = PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX |
+ TE_TRIGGER_GPIO_PIN;
+
+ PSB_DEBUG_ENTRY("mipi_val =0x%x\n", mipi_val);
+
+ PSB_DEBUG_ENTRY("type %s\n", (pipe == 2) ? "MIPI2" : "MIPI");
+ PSB_DEBUG_ENTRY("h %d v %d\n", mode->hdisplay, mode->vdisplay);
+
+ if(pipe == 2) {
+ dspcntr_reg = DSPCCNTR;
+ pipeconf_reg = PIPECCONF;
+ dspcntr_val = dev_priv->dspcntr2;
+ pipeconf_val = dev_priv->pipeconf2;
+ } else {
+ mipi_val |= 0x2; /*two lanes for port A and C respectively*/
+ }
+
+ if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) {
+ DRM_ERROR("hw begin failed\n");
+ return;
+ }
+
+ REG_WRITE(dspcntr_reg, dspcntr_val);
+ REG_READ(dspcntr_reg);
+
+ /*20ms delay before sending exit_sleep_mode*/
+ msleep(20);
+
+ /*send exit_sleep_mode DCS*/
+ ret = mdfld_dsi_send_mcs_short(sender, DCS_EXIT_SLEEP_MODE, 0, 0, true);
+ if(ret) {
+ DRM_ERROR("sent exit_sleep_mode faild\n");
+ goto out_err;
+ }
+
+ /*send set_tear_on DCS*/
+ ret = mdfld_dsi_send_mcs_short(sender, DCS_SET_TEAR_ON, 0, 1, true);
+ if (ret) {
+ DRM_ERROR("%s - sent set_tear_on faild\n", __FUNCTION__);
+ goto out_err;
+ }
+
+ REG_WRITE(pipeconf_reg, pipeconf_val | PIPEACONF_DSR);
+ REG_READ(pipeconf_reg);
+
+ /*TODO: this looks ugly, try to move it to CRTC mode setting*/
+ if(pipe == 2) {
+ dev_priv->pipeconf2 |= PIPEACONF_DSR;
+ } else {
+ dev_priv->pipeconf |= PIPEACONF_DSR;
+ }
+
+ PSB_DEBUG_ENTRY("pipeconf %x\n", REG_READ(pipeconf_reg));
+
+ ret = mdfld_dsi_dbi_update_area(dsi_output, 0, 0, h_active_area - 1, v_active_area - 1);
+ if(ret) {
+ DRM_ERROR("update area failed\n");
+ goto out_err;
+ }
+
+out_err:
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+
+ if(ret) {
+ DRM_ERROR("mode set failed\n");
+ } else {
+ PSB_DEBUG_ENTRY("mode set done successfully\n");
+ }
+}
+
+static void mdfld_dsi_dbi_prepare(struct drm_encoder * encoder)
+{
+ struct mdfld_dsi_encoder * dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+ struct mdfld_dsi_dbi_output * dbi_output = MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
+
+ PSB_DEBUG_ENTRY("\n");
+
+ dbi_output->mode_flags |= MODE_SETTING_IN_ENCODER;
+ dbi_output->mode_flags &= ~MODE_SETTING_ENCODER_DONE;
+
+ mdfld_dsi_dbi_set_power(encoder, false);
+
+}
+
+static void mdfld_dsi_dbi_commit(struct drm_encoder * encoder)
+{
+ struct mdfld_dsi_encoder * dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+ struct mdfld_dsi_dbi_output * dbi_output = MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
+ struct drm_device * dev = dbi_output->dev;
+ struct drm_psb_private * dev_priv = dev->dev_private;
+
+/*DSI DPU was still on debugging, will remove this option later*/
+#ifdef CONFIG_MDFLD_DSI_DPU
+ struct psb_drm_dpu_rect rect;
+#endif
+
+ PSB_DEBUG_ENTRY("\n");
+
+ mdfld_dsi_dbi_set_power(encoder, true);
+
+ dbi_output->mode_flags &= ~MODE_SETTING_IN_ENCODER;
+
+#ifdef CONFIG_MDFLD_DSI_DPU
+ rect.x = rect.y = 0;
+ rect.width = 864;
+ rect.height = 480;
+#endif
+
+ if(dbi_output->channel_num == 1) {
+ dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_2;
+#ifdef CONFIG_MDFLD_DSI_DPU
+ /*if dpu enabled report a fullscreen damage*/
+ mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEC, &rect);
+#endif
+ } else {
+ dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_0;
+
+#ifdef CONFIG_MDFLD_DSI_DPU
+ mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEA, &rect);
+#endif
+ }
+
+ dbi_output->mode_flags |= MODE_SETTING_ENCODER_DONE;
+}
+
+static void mdfld_dsi_dbi_dpms(struct drm_encoder *encoder, int mode)
+{
+ struct mdfld_dsi_encoder * dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+ struct mdfld_dsi_dbi_output * dbi_output = MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
+ struct drm_device * dev = dbi_output->dev;
+ static bool bdispoff = false;
+
+ PSB_DEBUG_ENTRY("%s \n", (mode == DRM_MODE_DPMS_ON ? "on":"off"));
+
+ if (mode == DRM_MODE_DPMS_ON){
+ /**
+ * FIXME: in case I am wrong!
+ * we don't need to exit dsr here to wake up plane/pipe/pll
+ * if everything goes right, hw_begin will resume them all
+ * during set_power.
+ */
+ if(gbgfxsuspended && bdispoff){
+ bdispoff = false;
+ gbdispstatus = true;
+ gbgfxsuspended = false;
+ mdfld_dsi_dbi_exit_dsr (dev, MDFLD_DSR_2D_3D);
+ }
+
+ mdfld_dsi_dbi_set_power(encoder, true);
+ } else {
+ /**
+ * I am not sure whether this is the perfect place to
+ * turn rpm on since we still have a lot of CRTC turnning
+ * on work to do.
+ */
+ bdispoff = true;
+ gbdispstatus = false;
+ mdfld_dsi_dbi_set_power(encoder, false);
+ }
+}
+
+
+/**
+ * Update the DBI MIPI Panel Frame Buffer.
+ */
+static void mdfld_dsi_dbi_update_fb (struct mdfld_dsi_dbi_output * dbi_output, int pipe)
+{
+ struct mdfld_dsi_pkg_sender * sender =
+ mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base);
+ struct drm_device * dev = dbi_output->dev;
+ struct drm_crtc * crtc = dbi_output->base.base.crtc;
+ struct psb_intel_crtc * psb_crtc = (crtc) ? to_psb_intel_crtc(crtc) : NULL;
+
+ u32 dpll_reg = MRST_DPLL_A;
+ u32 dspcntr_reg = DSPACNTR;
+ u32 pipeconf_reg = PIPEACONF;
+ u32 dsplinoff_reg = DSPALINOFF;
+ u32 dspsurf_reg = DSPASURF;
+
+ /*if mode setting on-going, back off*/
+ if((dbi_output->mode_flags & MODE_SETTING_ON_GOING) ||
+ (psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING) ||
+ !(dbi_output->mode_flags & MODE_SETTING_ENCODER_DONE))
+ return;
+
+ if(pipe == 2) {
+ dspcntr_reg = DSPCCNTR;
+ pipeconf_reg = PIPECCONF;
+ dsplinoff_reg = DSPCLINOFF;
+ dspsurf_reg = DSPCSURF;
+ }
+
+ if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) {
+ DRM_ERROR("hw begin failed\n");
+ return;
+ }
+
+ /*check DBI FIFO status*/
+ if (!(REG_READ(dpll_reg) & DPLL_VCO_ENABLE) ||
+ !(REG_READ(dspcntr_reg) & DISPLAY_PLANE_ENABLE) ||
+ !(REG_READ(pipeconf_reg) & DISPLAY_PLANE_ENABLE)) {
+ goto update_fb_out0;
+ }
+
+ /*refresh plane changes*/
+ REG_WRITE(dsplinoff_reg, REG_READ(dsplinoff_reg));
+ REG_WRITE(dspsurf_reg, REG_READ(dspsurf_reg));
+ REG_READ(dspsurf_reg);
+
+ mdfld_dsi_write_mem_start(sender);
+
+ dbi_output->dsr_fb_update_done = true;
+update_fb_out0:
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+}
+
+static int tpo_cmd_get_panel_info(struct drm_device * dev,
+ int pipe,
+ struct panel_info * pi)
+{
+ if(!dev || !pi)
+ return -EINVAL;
+
+ pi->width_mm = TPO_PANEL_WIDTH;
+ pi->height_mm = TPO_PANEL_HEIGHT;
+
+ return 0;
+}
+
+
+/*TPO DBI encoder helper funcs*/
+static const struct drm_encoder_helper_funcs mdfld_dsi_dbi_helper_funcs = {
+ .dpms = mdfld_dsi_dbi_dpms,
+ .mode_fixup = mdfld_dsi_dbi_mode_fixup,
+ .prepare = mdfld_dsi_dbi_prepare,
+ .mode_set = mdfld_dsi_dbi_mode_set,
+ .commit = mdfld_dsi_dbi_commit,
+};
+
+/*TPO DBI encoder funcs*/
+static const struct drm_encoder_funcs mdfld_dsi_dbi_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
+void tpo_cmd_init(struct drm_device* dev, struct panel_funcs* p_funcs)
+{
+ p_funcs->encoder_funcs = &mdfld_dsi_dbi_encoder_funcs;
+ p_funcs->encoder_helper_funcs = &mdfld_dsi_dbi_helper_funcs;
+ p_funcs->get_config_mode = &tpo_cmd_get_config_mode;
+ p_funcs->update_fb = mdfld_dsi_dbi_update_fb;
+ p_funcs->get_panel_info = tpo_cmd_get_panel_info;
+ p_funcs->reset = mdfld_dsi_panel_reset;
+ p_funcs->drv_ic_init = mdfld_dsi_brightness_init;
+}
--- /dev/null
+/*
+ * Copyright © 2010 Intel 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 (including the next
+ * paragraph) 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.
+ *
+ * Authors:
+ * jim liu <jim.liu@intel.com>
+ * Jackie Li<yaodong.li@intel.com>
+ */
+
+#include "displays/tpo_vid.h"
+#include "mdfld_dsi_dpi.h"
+
+static struct drm_display_mode*
+tpo_vid_get_config_mode(struct drm_device* dev)
+{
+ struct drm_display_mode *mode;
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) dev->dev_private;
+ struct mrst_timing_info *ti = &dev_priv->gct_data.DTD;
+ bool use_gct = false;
+
+ PSB_DEBUG_ENTRY("\n");
+
+ mode = kzalloc(sizeof(*mode), GFP_KERNEL);
+ if (!mode)
+ return NULL;
+
+ if (use_gct) {
+ PSB_DEBUG_ENTRY("gct find MIPI panel. \n");
+
+ mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo;
+ mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo;
+ mode->hsync_start = mode->hdisplay + \
+ ((ti->hsync_offset_hi << 8) | \
+ ti->hsync_offset_lo);
+ mode->hsync_end = mode->hsync_start + \
+ ((ti->hsync_pulse_width_hi << 8) | \
+ ti->hsync_pulse_width_lo);
+ mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \
+ ti->hblank_lo);
+ mode->vsync_start = \
+ mode->vdisplay + ((ti->vsync_offset_hi << 8) | \
+ ti->vsync_offset_lo);
+ mode->vsync_end = \
+ mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \
+ ti->vsync_pulse_width_lo);
+ mode->vtotal = mode->vdisplay + \
+ ((ti->vblank_hi << 8) | ti->vblank_lo);
+ mode->clock = ti->pixel_clock * 10;
+
+ PSB_DEBUG_ENTRY("hdisplay is %d\n", mode->hdisplay);
+ PSB_DEBUG_ENTRY("vdisplay is %d\n", mode->vdisplay);
+ PSB_DEBUG_ENTRY("HSS is %d\n", mode->hsync_start);
+ PSB_DEBUG_ENTRY("HSE is %d\n", mode->hsync_end);
+ PSB_DEBUG_ENTRY("htotal is %d\n", mode->htotal);
+ PSB_DEBUG_ENTRY("VSS is %d\n", mode->vsync_start);
+ PSB_DEBUG_ENTRY("VSE is %d\n", mode->vsync_end);
+ PSB_DEBUG_ENTRY("vtotal is %d\n", mode->vtotal);
+ PSB_DEBUG_ENTRY("clock is %d\n", mode->clock);
+ } else {
+ mode->hdisplay = 864;
+ mode->vdisplay = 480;
+ mode->hsync_start = 873;
+ mode->hsync_end = 876;
+ mode->htotal = 887;
+ mode->vsync_start = 487;
+ mode->vsync_end = 490;
+ mode->vtotal = 499;
+ mode->clock = 33264;
+ }
+
+ drm_mode_set_name(mode);
+ drm_mode_set_crtcinfo(mode, 0);
+
+ mode->type |= DRM_MODE_TYPE_PREFERRED;
+
+ return mode;
+}
+
+static int tpo_vid_get_panel_info(struct drm_device * dev,
+ int pipe,
+ struct panel_info * pi)
+{
+ if(!dev || !pi)
+ return -EINVAL;
+
+ pi->width_mm = TPO_PANEL_WIDTH;
+ pi->height_mm = TPO_PANEL_HEIGHT;
+
+ return 0;
+}
+
+/*TPO DPI encoder helper funcs*/
+static const struct drm_encoder_helper_funcs mdfld_tpo_dpi_encoder_helper_funcs = {
+ .dpms = mdfld_dsi_dpi_dpms,
+ .mode_fixup = mdfld_dsi_dpi_mode_fixup,
+ .prepare = mdfld_dsi_dpi_prepare,
+ .mode_set = mdfld_dsi_dpi_mode_set,
+ .commit = mdfld_dsi_dpi_commit,
+};
+
+/*TPO DPI encoder funcs*/
+static const struct drm_encoder_funcs mdfld_tpo_dpi_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
+void tpo_vid_init(struct drm_device* dev, struct panel_funcs* p_funcs)
+{
+ if(!dev || !p_funcs) {
+ DRM_ERROR("Invalid parameters\n");
+ return;
+ }
+
+ PSB_DEBUG_ENTRY("\n");
+
+ p_funcs->encoder_funcs = &mdfld_tpo_dpi_encoder_funcs;
+ p_funcs->encoder_helper_funcs = &mdfld_tpo_dpi_encoder_helper_funcs;
+ p_funcs->get_config_mode = &tpo_vid_get_config_mode;
+ p_funcs->update_fb = NULL;
+ p_funcs->get_panel_info = tpo_vid_get_panel_info;
+}
--- /dev/null
+/*
+ * Copyright (c) 2009, Intel Corporation.
+ *
+ * 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 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.
+ *
+ * Authors: binglin.chen@intel.com>
+ *
+ */
+
+#include "msvdx_power.h"
+#include "psb_msvdx.h"
+#include "psb_drv.h"
+#include "psb_powermgmt.h"
+
+#include "services_headers.h"
+#include "sysconfig.h"
+
+static PVRSRV_ERROR DevInitMSVDXPart1(IMG_VOID *pvDeviceNode)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvDeviceNode;
+ PVRSRV_ERROR eError;
+ PVRSRV_DEV_POWER_STATE eDefaultPowerState;
+
+ /* register power operation function */
+ /* FIXME: this should be in part2 init function, but
+ * currently here only OSPM needs IMG device... */
+ eDefaultPowerState = PVRSRV_DEV_POWER_STATE_OFF;
+ eError = PVRSRVRegisterPowerDevice(psDeviceNode->sDevId.ui32DeviceIndex,
+ MSVDXPrePowerState,
+ MSVDXPostPowerState,
+ MSVDXPreClockSpeedChange,
+ MSVDXPostClockSpeedChange,
+ (IMG_HANDLE)psDeviceNode,
+ PVRSRV_DEV_POWER_STATE_ON,
+ eDefaultPowerState);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR, "DevInitMSVDXPart1: failed to "
+ "register device with power manager"));
+ return eError;
+ }
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR DevDeInitMSVDX(IMG_VOID *pvDeviceNode)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvDeviceNode;
+ PVRSRV_ERROR eError;
+
+ /* should deinit all resource */
+
+ eError = PVRSRVRemovePowerDevice(psDeviceNode->sDevId.ui32DeviceIndex);
+ if (eError != PVRSRV_OK)
+ return eError;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR MSVDXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ /* version check */
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR MSVDXRegisterDevice(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ psDeviceNode->sDevId.eDeviceType = PVRSRV_DEVICE_TYPE_MSVDX;
+ psDeviceNode->sDevId.eDeviceClass = PVRSRV_DEVICE_CLASS_VIDEO;
+
+ psDeviceNode->pfnInitDevice = DevInitMSVDXPart1;
+ psDeviceNode->pfnDeInitDevice = DevDeInitMSVDX;
+
+ psDeviceNode->pfnInitDeviceCompatCheck = MSVDXDevInitCompatCheck;
+
+ psDeviceNode->pfnDeviceISR = psb_msvdx_interrupt;
+ psDeviceNode->pvISRData = (IMG_VOID *)gpDrmDevice;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR MSVDXPrePowerState(IMG_HANDLE hDevHandle,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+#if 1
+ /* ask for a change not power on*/
+ if ((eNewPowerState != eCurrentPowerState) &&
+ (eNewPowerState != PVRSRV_DEV_POWER_STATE_ON)) {
+ struct drm_psb_private *dev_priv = gpDrmDevice->dev_private;
+ struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+ MSVDX_NEW_PMSTATE(gpDrmDevice, msvdx_priv, PSB_PMSTATE_POWERDOWN);
+
+ /* context save */
+ psb_msvdx_save_context(gpDrmDevice);
+
+ /* internally close the device */
+
+ /* ask for power off */
+ if (eNewPowerState == PVRSRV_DEV_POWER_STATE_OFF) {
+ /* here will deinitialize the driver if needed */
+ } else {
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "%s no action for transform from %d to %d",
+ __func__,
+ eCurrentPowerState,
+ eNewPowerState));
+ }
+ }
+#endif
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR MSVDXPostPowerState(IMG_HANDLE hDevHandle,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+#if 1
+ /* if ask for change & current status is not on */
+ if ((eNewPowerState != eCurrentPowerState) &&
+ (eCurrentPowerState != PVRSRV_DEV_POWER_STATE_ON)) {
+ /* internally open device */
+ struct drm_psb_private *dev_priv = gpDrmDevice->dev_private;
+ struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+ MSVDX_NEW_PMSTATE(gpDrmDevice, msvdx_priv, PSB_PMSTATE_POWERUP);
+
+ /* context restore */
+ psb_msvdx_restore_context(gpDrmDevice);
+
+ if (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_OFF) {
+ /* here will initialize the driver if needed */
+ } else {
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "%s no action for transform from %d to %d",
+ __func__,
+ eCurrentPowerState,
+ eNewPowerState));
+ }
+ }
+#endif
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR MSVDXPreClockSpeedChange(IMG_HANDLE hDevHandle,
+ IMG_BOOL bIdleDevice,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR MSVDXPostClockSpeedChange(IMG_HANDLE hDevHandle,
+ IMG_BOOL bIdleDevice,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+ return PVRSRV_OK;
+}
--- /dev/null
+/*
+ * Copyright (c) 2009, Intel Corporation.
+ *
+ * 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 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.
+ *
+ * Authors: binglin.chen@intel.com>
+ *
+ */
+
+#ifndef MSVDX_POWER_H_
+#define MSVDX_POWER_H_
+
+#include "services_headers.h"
+#include "sysconfig.h"
+
+/* function define */
+PVRSRV_ERROR MSVDXRegisterDevice(PVRSRV_DEVICE_NODE *psDeviceNode);
+PVRSRV_ERROR MSVDXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+/* power function define */
+PVRSRV_ERROR MSVDXPrePowerState(IMG_HANDLE hDevHandle,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+PVRSRV_ERROR MSVDXPostPowerState(IMG_HANDLE hDevHandle,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+PVRSRV_ERROR MSVDXPreClockSpeedChange(IMG_HANDLE hDevHandle,
+ IMG_BOOL bIdleDevice,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+PVRSRV_ERROR MSVDXPostClockSpeedChange(IMG_HANDLE hDevHandle,
+ IMG_BOOL bIdleDevice,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+PVRSRV_ERROR MSVDXInitOSPM(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+#endif /* !MSVDX_POWER_H_ */
--- /dev/null
+/**
+ * file pnw_topaz.c
+ * TOPAZ I/O operations and IRQ handling
+ *
+ */
+
+/**************************************************************************
+ *
+ * Copyright (c) 2007 Intel Corporation, Hillsboro, OR, USA
+ * Copyright (c) Imagination Technologies Limited, UK
+ *
+ * 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 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.
+ *
+ **************************************************************************/
+
+/* include headers */
+/* #define DRM_DEBUG_CODE 2 */
+#include <drm/drmP.h>
+#include <drm/drm_os_linux.h>
+
+#include "psb_drv.h"
+#include "psb_drm.h"
+#include "pnw_topaz.h"
+#include "psb_powermgmt.h"
+#include "pnw_topaz_hw_reg.h"
+
+#include <linux/io.h>
+#include <linux/delay.h>
+
+#define TOPAZ_MAX_COMMAND_IN_QUEUE 0x1000
+//#define SYNC_FOR_EACH_COMMAND
+/* static function define */
+static int pnw_topaz_deliver_command(struct drm_device *dev,
+ struct ttm_buffer_object *cmd_buffer,
+ unsigned long cmd_offset,
+ unsigned long cmd_size,
+ void **topaz_cmd, uint32_t sequence,
+ int copy_cmd);
+static int pnw_topaz_send(struct drm_device *dev, void *cmd,
+ unsigned long cmd_size, uint32_t sync_seq);
+static int pnw_topaz_dequeue_send(struct drm_device *dev);
+static int pnw_topaz_save_command(struct drm_device *dev, void *cmd,
+ unsigned long cmd_size, uint32_t sequence);
+
+static void pnw_topaz_mtx_kick(struct drm_psb_private *dev_priv,
+ uint32_t core_id, uint32_t kick_count);
+
+IMG_BOOL pnw_topaz_interrupt(IMG_VOID *pvData)
+{
+ struct drm_device *dev;
+ struct drm_psb_private *dev_priv;
+ uint32_t clr_flag;
+ struct pnw_topaz_private *topaz_priv;
+ uint32_t topaz_stat;
+ uint32_t cur_seq, cmd_id;
+
+ PSB_DEBUG_IRQ("Got an TopazSC interrupt\n");
+
+ if (pvData == IMG_NULL) {
+ DRM_ERROR("ERROR: TOPAZ %s, Invalid params\n", __func__);
+ return IMG_FALSE;
+ }
+
+ dev = (struct drm_device *)pvData;
+
+ if (!ospm_power_is_hw_on(OSPM_VIDEO_ENC_ISLAND)) {
+ DRM_ERROR("ERROR: interrupt arrived but HW is power off\n");
+ return IMG_FALSE;
+ }
+
+ dev_priv = (struct drm_psb_private *) dev->dev_private;
+ topaz_priv = dev_priv->topaz_private;
+
+ /*TODO : check if topaz is busy*/
+ topaz_priv->topaz_hw_busy = REG_READ(0x20D0) & (0x1 << 11);
+
+ TOPAZ_READ32(TOPAZ_CR_IMG_TOPAZ_INTSTAT, &topaz_stat, 0);
+ clr_flag = pnw_topaz_queryirq(dev);
+
+ pnw_topaz_clearirq(dev, clr_flag);
+
+ TOPAZ_MTX_WB_READ32(topaz_priv->topaz_sync_addr,
+ 0, MTX_WRITEBACK_CMDWORD, &cmd_id);
+ cmd_id = (cmd_id & 0x7f); /* CMD ID */
+ if (cmd_id != MTX_CMDID_NULL)
+ return IMG_TRUE;
+
+ TOPAZ_MTX_WB_READ32(topaz_priv->topaz_sync_addr,
+ 0, MTX_WRITEBACK_VALUE, &cur_seq);
+
+ PSB_DEBUG_IRQ("TOPAZ:Got SYNC IRQ,sync seq:0x%08x (MTX)"
+ " vs 0x%08x(fence)\n",
+ cur_seq, dev_priv->sequence[LNC_ENGINE_ENCODE]);
+
+ psb_fence_handler(dev, LNC_ENGINE_ENCODE);
+
+ topaz_priv->topaz_busy = 1;
+ pnw_topaz_dequeue_send(dev);
+
+ if (drm_topaz_pmpolicy != PSB_PMPOLICY_NOPM \
+ && topaz_priv->topaz_busy == 0) {
+ PSB_DEBUG_IRQ("TOPAZ:Schedule a work to power down Topaz\n");
+ schedule_delayed_work(&dev_priv->scheduler.topaz_suspend_wq, 0);
+ }
+
+ return IMG_TRUE;
+}
+
+//#define PSB_DEBUG_GENERAL DRM_ERROR
+static int pnw_submit_encode_cmdbuf(struct drm_device *dev,
+ struct ttm_buffer_object *cmd_buffer,
+ unsigned long cmd_offset, unsigned long cmd_size,
+ struct ttm_fence_object *fence)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ unsigned long irq_flags;
+ int ret = 0;
+ void *cmd;
+ uint32_t tmp;
+ uint32_t sequence = dev_priv->sequence[LNC_ENGINE_ENCODE];
+ struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+
+ PSB_DEBUG_GENERAL("TOPAZ: command submit\n");
+
+ PSB_DEBUG_GENERAL("TOPAZ: topaz busy = %d\n", topaz_priv->topaz_busy);
+
+ if (dev_priv->last_topaz_ctx != dev_priv->topaz_ctx) {
+ /* todo: save current context into dev_priv->last_topaz_ctx
+ * and reload dev_priv->topaz_ctx context
+ */
+ PSB_DEBUG_GENERAL("TOPAZ: context switch\n");
+ dev_priv->last_topaz_ctx = dev_priv->topaz_ctx;
+ }
+
+ if (topaz_priv->topaz_fw_loaded == 0) {
+ /* #.# load fw to driver */
+ PSB_DEBUG_INIT("TOPAZ: load /lib/firmware/topaz_fwsc.bin\n");
+ ret = pnw_topaz_init_fw(dev);
+ if (ret != 0) {
+ /* FIXME: find a proper return value */
+ DRM_ERROR("TOPAX:load /lib/firmware/topaz_fwsc.bin"
+ " fails, ensure udevd is configured"
+ " correctly!\n");
+ return -EFAULT;
+ }
+ topaz_priv->topaz_fw_loaded = 1;
+ }
+
+ tmp = atomic_cmpxchg(&dev_priv->topaz_mmu_invaldc, 1, 0);
+ if (tmp == 1)
+ pnw_topaz_mmu_flushcache(dev_priv);
+
+ /* # schedule watchdog */
+ /* psb_schedule_watchdog(dev_priv); */
+
+ /* # spin lock irq save [msvdx_lock] */
+ spin_lock_irqsave(&topaz_priv->topaz_lock, irq_flags);
+
+ /* # if topaz need to reset, reset it */
+ if (topaz_priv->topaz_needs_reset) {
+ /* #.# reset it */
+ spin_unlock_irqrestore(&topaz_priv->topaz_lock, irq_flags);
+ PSB_DEBUG_GENERAL("TOPAZ: needs reset.\n");
+
+ if (pnw_topaz_reset(dev_priv)) {
+ ret = -EBUSY;
+ DRM_ERROR("TOPAZ: reset failed.\n");
+ return ret;
+ }
+
+ PSB_DEBUG_GENERAL("TOPAZ: reset ok.\n");
+
+ /* #.# upload firmware */
+ if (pnw_topaz_setup_fw(dev, topaz_priv->topaz_cur_codec)) {
+ DRM_ERROR("TOPAZ: upload FW to HW failed\n");
+ return -EBUSY;
+ }
+
+ spin_lock_irqsave(&topaz_priv->topaz_lock, irq_flags);
+ }
+
+ if (!topaz_priv->topaz_busy) {
+ /* # direct map topaz command if topaz is free */
+ PSB_DEBUG_GENERAL("TOPAZ:direct send command,sequence %08x\n",
+ sequence);
+
+ topaz_priv->topaz_busy = 1;
+ spin_unlock_irqrestore(&topaz_priv->topaz_lock, irq_flags);
+
+ ret = pnw_topaz_deliver_command(dev, cmd_buffer, cmd_offset,
+ cmd_size, NULL, sequence, 0);
+
+ if (ret) {
+ DRM_ERROR("TOPAZ: failed to extract cmd...\n");
+ return ret;
+ }
+ } else {
+ PSB_DEBUG_GENERAL("TOPAZ: queue command,sequence %08x \n",
+ sequence);
+ cmd = NULL;
+
+ spin_unlock_irqrestore(&topaz_priv->topaz_lock, irq_flags);
+
+ ret = pnw_topaz_deliver_command(dev, cmd_buffer, cmd_offset,
+ cmd_size, &cmd, sequence, 1);
+ if (cmd == NULL || ret) {
+ DRM_ERROR("TOPAZ: map command for save fialed\n");
+ return ret;
+ }
+
+ ret = pnw_topaz_save_command(dev, cmd, cmd_size, sequence);
+ if (ret)
+ DRM_ERROR("TOPAZ: save command failed\n");
+ }
+
+ return ret;
+}
+
+static int pnw_topaz_save_command(struct drm_device *dev, void *cmd,
+ unsigned long cmd_size, uint32_t sequence)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct pnw_topaz_cmd_queue *topaz_cmd;
+ unsigned long irq_flags;
+ struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+
+ PSB_DEBUG_GENERAL("TOPAZ: queue command,sequence: %08x..\n",
+ sequence);
+
+ topaz_cmd = kzalloc(sizeof(struct pnw_topaz_cmd_queue),
+ GFP_KERNEL);
+ if (topaz_cmd == NULL) {
+ mutex_unlock(&topaz_priv->topaz_mutex);
+ DRM_ERROR("TOPAZ: out of memory....\n");
+ return -ENOMEM;
+ }
+
+ topaz_cmd->cmd = cmd;
+ topaz_cmd->cmd_size = cmd_size;
+ topaz_cmd->sequence = sequence;
+
+ spin_lock_irqsave(&topaz_priv->topaz_lock, irq_flags);
+ list_add_tail(&topaz_cmd->head, &topaz_priv->topaz_queue);
+ if (!topaz_priv->topaz_busy) {
+ /* topaz_priv->topaz_busy = 1; */
+ PSB_DEBUG_GENERAL("TOPAZ: need immediate dequeue...\n");
+ pnw_topaz_dequeue_send(dev);
+ PSB_DEBUG_GENERAL("TOPAZ: after dequeue command\n");
+ }
+
+ spin_unlock_irqrestore(&topaz_priv->topaz_lock, irq_flags);
+
+ return 0;
+}
+
+
+int pnw_cmdbuf_video(struct drm_file *priv,
+ struct list_head *validate_list,
+ uint32_t fence_type,
+ struct drm_psb_cmdbuf_arg *arg,
+ struct ttm_buffer_object *cmd_buffer,
+ struct psb_ttm_fence_rep *fence_arg)
+{
+ struct drm_device *dev = priv->minor->dev;
+ struct ttm_fence_object *fence = NULL;
+ int ret;
+
+ PSB_DEBUG_GENERAL("TOPAZ : enter %s cmdsize: %d\n", __func__,
+ arg->cmdbuf_size);
+
+ ret = pnw_submit_encode_cmdbuf(dev, cmd_buffer, arg->cmdbuf_offset,
+ arg->cmdbuf_size, fence);
+ if (ret)
+ return ret;
+
+ /* workaround for interrupt issue */
+ psb_fence_or_sync(priv, LNC_ENGINE_ENCODE, fence_type, arg->fence_flags,
+ validate_list, fence_arg, &fence);
+
+ if (fence)
+ ttm_fence_object_unref(&fence);
+
+ spin_lock(&cmd_buffer->bdev->fence_lock);
+ if (cmd_buffer->sync_obj != NULL)
+ ttm_fence_sync_obj_unref(&cmd_buffer->sync_obj);
+ spin_unlock(&cmd_buffer->bdev->fence_lock);
+
+ PSB_DEBUG_GENERAL("TOPAZ exit %s\n", __func__);
+ return 0;
+}
+
+int pnw_wait_on_sync(struct drm_psb_private *dev_priv,
+ uint32_t sync_seq,
+ uint32_t *sync_p)
+{
+ int count = 10000;
+ if (sync_p == NULL) {
+ DRM_ERROR("TOPAZ: pnw_wait_on_sync invalid memory address\n ");
+ return -1;
+ }
+
+ while (count && (sync_seq != *sync_p)) {
+ PSB_UDELAY(100);
+ --count;
+ }
+ if ((count == 0) && (sync_seq != *sync_p)) {
+ DRM_ERROR("TOPAZ: wait sycn timeout (0x%08x),actual 0x%08x\n",
+ sync_seq, *sync_p);
+ return -EBUSY;
+ }
+ PSB_DEBUG_GENERAL("TOPAZ: SYNC done, seq=0x%08x\n", *sync_p);
+ return 0;
+}
+
+static int pnw_topaz_deliver_command(struct drm_device *dev,
+ struct ttm_buffer_object *cmd_buffer,
+ unsigned long cmd_offset, unsigned long cmd_size,
+ void **topaz_cmd, uint32_t sequence,
+ int copy_cmd)
+{
+ unsigned long cmd_page_offset = cmd_offset & ~PAGE_MASK;
+ struct ttm_bo_kmap_obj cmd_kmap;
+ bool is_iomem;
+ int ret;
+ unsigned char *cmd_start, *tmp;
+
+ ret = ttm_bo_kmap(cmd_buffer, cmd_offset >> PAGE_SHIFT, 2,
+ &cmd_kmap);
+ if (ret) {
+ DRM_ERROR("TOPAZ: drm_bo_kmap failed: %d\n", ret);
+ return ret;
+ }
+ cmd_start = (unsigned char *) ttm_kmap_obj_virtual(&cmd_kmap,
+ &is_iomem) + cmd_page_offset;
+
+ if (copy_cmd) {
+ PSB_DEBUG_GENERAL("TOPAZ: queue commands\n");
+ tmp = kzalloc(cmd_size, GFP_KERNEL);
+ if (tmp == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ memcpy(tmp, cmd_start, cmd_size);
+ *topaz_cmd = tmp;
+ } else {
+ PSB_DEBUG_GENERAL("TOPAZ: directly send the command\n");
+ ret = pnw_topaz_send(dev, cmd_start, cmd_size, sequence);
+ if (ret) {
+ DRM_ERROR("TOPAZ: commit commands failed.\n");
+ ret = -EINVAL;
+ }
+ }
+
+out:
+ PSB_DEBUG_GENERAL("TOPAZ:cmd_size(%ld), sequence(%d)"
+ " copy_cmd(%d)\n",
+ cmd_size, sequence, copy_cmd);
+
+ ttm_bo_kunmap(&cmd_kmap);
+
+ return ret;
+}
+
+
+int pnw_topaz_kick_null_cmd(struct drm_psb_private *dev_priv,
+ uint32_t core_id,
+ uint32_t wb_offset,
+ uint32_t sync_seq,
+ uint8_t irq_enable)
+{
+ struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+ uint32_t cur_free_space;
+ struct topaz_cmd_header cur_cmd_header;
+ int ret;
+
+ POLL_TOPAZ_FREE_FIFO_SPACE(4, 100, 10000, &cur_free_space);
+ if (ret) {
+ DRM_ERROR("TOPAZ: error -- ret(%d)\n", ret);
+ return ret;
+ }
+
+ cur_cmd_header.core = core_id;
+ cur_cmd_header.seq = sync_seq,
+ cur_cmd_header.enable_interrupt = ((irq_enable == 0) ? 0 : 1);
+ cur_cmd_header.id = MTX_CMDID_NULL;
+
+ topaz_priv->topaz_cmd_count %= MAX_TOPAZ_CMD_COUNT;
+ PSB_DEBUG_GENERAL("TOPAZ: free FIFO space %d\n",
+ cur_free_space);
+ PSB_DEBUG_GENERAL("TOPAZ: write 4 words to FIFO:"
+ "0x%08x,0x%08x,0x%08x,0x%08x\n",
+ cur_cmd_header.val,
+ 0,
+ wb_offset,
+ cur_cmd_header.seq);
+
+ TOPAZ_MULTICORE_WRITE32(TOPAZSC_CR_MULTICORE_CMD_FIFO_0,
+ cur_cmd_header.val);
+ TOPAZ_MULTICORE_WRITE32(TOPAZSC_CR_MULTICORE_CMD_FIFO_0,
+ 0);
+ TOPAZ_MULTICORE_WRITE32(TOPAZSC_CR_MULTICORE_CMD_FIFO_0,
+ wb_offset);
+ TOPAZ_MULTICORE_WRITE32(TOPAZSC_CR_MULTICORE_CMD_FIFO_0,
+ sync_seq);
+
+ PSB_DEBUG_GENERAL("TOPAZ: Write back value for NULL CMD is %d\n",
+ sync_seq);
+
+ pnw_topaz_mtx_kick(dev_priv, 0, 1);
+
+ return 0;
+}
+
+static int
+pnw_topaz_send(struct drm_device *dev, void *cmd,
+ unsigned long cmd_size, uint32_t sync_seq)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ int ret = 0;
+ unsigned char *command = (unsigned char *) cmd;
+ struct topaz_cmd_header *cur_cmd_header;
+ uint32_t cur_cmd_size = 4, cur_cmd_id, cur_free_space = 0;
+ uint32_t codec;
+ struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+ uint32_t reg_off, reg_val, reg_cnt;
+ uint32_t *p_command;
+
+ PSB_DEBUG_GENERAL("TOPAZ: send the command in the buffer one by one\n");
+
+ while (cmd_size > 0) {
+ cur_cmd_header = (struct topaz_cmd_header *) command;
+ cur_cmd_id = cur_cmd_header->id;
+ PSB_DEBUG_GENERAL("TOPAZ: %s: \n", cmd_to_string(cur_cmd_id));
+
+ switch (cur_cmd_id) {
+ case MTX_CMDID_SW_NEW_CODEC:
+ codec = *((uint32_t *) cmd + 1);
+ topaz_priv->frame_h = (uint16_t)
+ ((*((uint32_t *) cmd + 2)) & 0xffff) ;
+ topaz_priv->frame_w = (uint16_t)
+ (((*((uint32_t *) cmd + 2))
+ & 0xffff0000) >> 16) ;
+
+ PSB_DEBUG_GENERAL("TOPAZ: setup new codec %s (%d),"
+ " width %d, height %d\n",
+ codec_to_string(codec), codec,
+ topaz_priv->frame_w,
+ topaz_priv->frame_h);
+ if (pnw_topaz_setup_fw(dev, codec)) {
+ DRM_ERROR("TOPAZ: upload FW to HW failed\n");
+ return -EBUSY;
+ }
+ topaz_priv->topaz_cur_codec = codec;
+ cur_cmd_size = 3;
+ break;
+
+ case MTX_CMDID_SW_ENTER_LOWPOWER:
+ PSB_DEBUG_GENERAL("TOPAZ: enter lowpower.... \n");
+ PSB_DEBUG_GENERAL("XXX: implement it\n");
+ cur_cmd_size = 1;
+ break;
+
+ case MTX_CMDID_SW_LEAVE_LOWPOWER:
+ PSB_DEBUG_GENERAL("TOPAZ: leave lowpower... \n");
+ PSB_DEBUG_GENERAL("XXX: implement it\n");
+ cur_cmd_size = 1;
+ break;
+
+ case MTX_CMDID_SW_WRITEREG:
+ p_command = (uint32_t *)(command);
+ p_command++;
+ cur_cmd_size = *p_command;
+ p_command++;
+ PSB_DEBUG_GENERAL("TOPAZ: Start to write"
+ " %d Registers\n", cur_cmd_size);
+ if (cur_cmd_size > (cmd_size / 4)) {
+ DRM_ERROR("TOPAZ: Wrong number of write "
+ "operations.Exceed command buffer."
+ "(%d)\n", (int)(cmd_size / 4));
+ goto out;
+ }
+
+ for (reg_cnt = 0; reg_cnt < cur_cmd_size; reg_cnt++) {
+ reg_off = *p_command;
+ p_command++;
+ reg_val = *p_command;
+ p_command++;
+ if (reg_off > TOPAZSC_REG_OFF_MAX)
+ DRM_ERROR("TOPAZ: Ignore write (0x%08x)"
+ " to register 0x%08x\n",
+ reg_val, reg_off);
+ else
+ MM_WRITE32(0, reg_off, reg_val);
+ }
+ /* Reg_off and reg_val are stored in a pair of words*/
+ cur_cmd_size *= 2;
+ /* Header size, 2 words */
+ cur_cmd_size += 2;
+ break;
+ case MTX_CMDID_PAD:
+ /*Ignore this command, which is used to skip
+ * some commands in user space*/
+ cur_cmd_size = 4;
+ break;
+ /* ordinary commmand */
+ case MTX_CMDID_START_PIC:
+ case MTX_CMDID_DO_HEADER:
+ case MTX_CMDID_ENCODE_SLICE:
+ case MTX_CMDID_END_PIC:
+ case MTX_CMDID_SETQUANT:
+ case MTX_CMDID_RESET_ENCODE:
+ case MTX_CMDID_ISSUEBUFF:
+ case MTX_CMDID_SETUP:
+ cur_cmd_header->seq = topaz_priv->topaz_cmd_count++;
+ cur_cmd_header->enable_interrupt = 0;
+ cur_cmd_size = 4;
+ if (cur_free_space < cur_cmd_size) {
+ POLL_TOPAZ_FREE_FIFO_SPACE(4, 100, 10000,
+ &cur_free_space);
+ if (ret) {
+ DRM_ERROR("TOPAZ: error -- ret(%d)\n",
+ ret);
+ goto out;
+ }
+ }
+
+ PSB_DEBUG_GENERAL("TOPAZ: free FIFO space %d\n",
+ cur_free_space);
+ PSB_DEBUG_GENERAL("TOPAZ: write 4 words to FIFO:"
+ "0x%08x,0x%08x,0x%08x,0x%08x\n",
+ cur_cmd_header->val,
+ *((uint32_t *)(command) + 1),
+ TOPAZ_MTX_WB_OFFSET(
+ topaz_priv->topaz_wb_offset,
+ cur_cmd_header->core),
+ cur_cmd_header->seq);
+
+ TOPAZ_MULTICORE_WRITE32(TOPAZSC_CR_MULTICORE_CMD_FIFO_0,
+ cur_cmd_header->val);
+ TOPAZ_MULTICORE_WRITE32(TOPAZSC_CR_MULTICORE_CMD_FIFO_0,
+ *((uint32_t *)(command) + 1));
+ TOPAZ_MULTICORE_WRITE32(TOPAZSC_CR_MULTICORE_CMD_FIFO_0,
+ TOPAZ_MTX_WB_OFFSET(
+ topaz_priv->topaz_wb_offset,
+ cur_cmd_header->core));
+ TOPAZ_MULTICORE_WRITE32(TOPAZSC_CR_MULTICORE_CMD_FIFO_0,
+ cur_cmd_header->seq);
+
+ cur_free_space -= 4;
+ topaz_priv->aui32LastSync[0][cur_cmd_header->core]
+ = cur_cmd_header->seq;
+ topaz_priv->topaz_cmd_count %= MAX_TOPAZ_CMD_COUNT;
+ pnw_topaz_mtx_kick(dev_priv, 0, 1);
+#ifdef SYNC_FOR_EACH_COMMAND
+ pnw_wait_on_sync(dev_priv, cur_cmd_header->seq,
+ topaz_priv->topaz_mtx_wb +
+ cur_cmd_header->core *
+ MTX_WRITEBACK_DATASIZE_ROUND + 1);
+#endif
+ break;
+ default:
+ DRM_ERROR("TOPAZ: unsupported command id: %x\n",
+ cur_cmd_id);
+ goto out;
+ }
+
+ /*cur_cmd_size indicate the number of words of current command*/
+ command += cur_cmd_size * 4;
+ cmd_size -= cur_cmd_size * 4;
+ }
+#if PNW_TOPAZ_NO_IRQ
+ PSB_DEBUG_GENERAL("reset NULL writeback to 0xffffffff,"
+ "topaz_priv->topaz_sync_addr=0x%p\n",
+ topaz_priv->topaz_sync_addr);
+
+ *((uint32_t *)topaz_priv->topaz_sync_addr + MTX_WRITEBACK_VALUE) = ~0;
+ pnw_topaz_kick_null_cmd(dev_priv, 0,
+ topaz_priv->topaz_sync_offset, sync_seq, 0);
+
+ if (0 != pnw_wait_on_sync(dev_priv, sync_seq,
+ topaz_priv->topaz_sync_addr + MTX_WRITEBACK_VALUE)) {
+ DRM_ERROR("TOPAZSC: Polling the writeback of last command"
+ " failed!\n");
+ topaz_read_core_reg(dev_priv, 0, 0x5, ®_val);
+ DRM_ERROR("TOPAZSC: PC pointer of core 0 is %x\n", reg_val);
+ topaz_read_core_reg(dev_priv, 1, 0x5, ®_val);
+ DRM_ERROR("TOPAZSC: PC pointer of core 1 is %x\n", reg_val);
+ TOPAZ_MULTICORE_READ32(TOPAZSC_CR_MULTICORE_CMD_FIFO_1,
+ ®_val);
+ reg_val &= MASK_TOPAZSC_CR_CMD_FIFO_SPACE;
+ DRM_ERROR("TOPAZSC: Free words in command FIFO %d\n", reg_val);
+ DRM_ERROR("TOPAZSC: Last writeback of core 0 %d\n",
+ *(topaz_priv->topaz_mtx_wb + 1));
+ DRM_ERROR("TOPAZSC: Last writeback of core 1 %d\n",
+ *(topaz_priv->topaz_mtx_wb +
+ MTX_WRITEBACK_DATASIZE_ROUND + 1));
+ }
+
+ PSB_DEBUG_GENERAL("Kicked command with sequence 0x%08x,"
+ " and polling it, got 0x%08x\n",
+ sync_seq,
+ *(topaz_priv->topaz_sync_addr + MTX_WRITEBACK_VALUE));
+ PSB_DEBUG_GENERAL("Can handle unfence here, but let fence"
+ " polling do it\n");
+ topaz_priv->topaz_busy = 0;
+#else
+ PSB_DEBUG_GENERAL("Kick command with sequence %x\n", sync_seq);
+ pnw_topaz_kick_null_cmd(dev_priv, 0,
+ topaz_priv->topaz_sync_offset,
+ sync_seq, 1);
+#endif
+out:
+ return ret;
+}
+
+static int pnw_topaz_dequeue_send(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct pnw_topaz_cmd_queue *topaz_cmd = NULL;
+ int ret;
+ struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+
+ PSB_DEBUG_GENERAL("TOPAZ: dequeue command and send it to topaz\n");
+
+ if (list_empty(&topaz_priv->topaz_queue)) {
+ topaz_priv->topaz_busy = 0;
+ return 0;
+ }
+
+ topaz_priv->topaz_busy = 1;
+ topaz_cmd = list_first_entry(&topaz_priv->topaz_queue,
+ struct pnw_topaz_cmd_queue, head);
+
+ PSB_DEBUG_GENERAL("TOPAZ: queue has id %08x\n", topaz_cmd->sequence);
+ ret = pnw_topaz_send(dev, topaz_cmd->cmd, topaz_cmd->cmd_size,
+ topaz_cmd->sequence);
+ if (ret) {
+ DRM_ERROR("TOPAZ: pnw_topaz_send failed.\n");
+ ret = -EINVAL;
+ }
+
+ list_del(&topaz_cmd->head);
+ kfree(topaz_cmd->cmd);
+ kfree(topaz_cmd);
+
+ return ret;
+}
+
+static void pnw_topaz_mtx_kick(struct drm_psb_private *dev_priv, uint32_t core_id, uint32_t kick_count)
+{
+ PSB_DEBUG_GENERAL("TOPAZ: kick core(%d) mtx count(%d).\n",
+ core_id, kick_count);
+ topaz_set_mtx_target(dev_priv, core_id, 0);
+ MTX_WRITE32(MTX_CR_MTX_KICK, kick_count, core_id);
+ return;
+}
+
+int pnw_check_topaz_idle(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *)dev->dev_private;
+ struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+
+ if (dev_priv->topaz_ctx == NULL)
+ return 0;
+
+ if (topaz_priv->topaz_busy)
+ return -EBUSY;
+
+ if (topaz_priv->topaz_hw_busy) {
+ PSB_DEBUG_PM("TOPAZ: %s, HW is busy\n", __func__);
+ return -EBUSY;
+ }
+
+ return 0; /* we think it is idle */
+}
+
+
+int pnw_video_get_core_num(struct drm_device *dev, uint64_t user_pointer)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *)dev->dev_private;
+ struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+ int ret;
+
+ ret = copy_to_user((void __user *)((unsigned long)user_pointer),
+ &topaz_priv->topaz_num_cores,
+ sizeof(topaz_priv->topaz_num_cores));
+
+ if (ret)
+ return -EFAULT;
+
+ return 0;
+
+}
+
+int pnw_video_frameskip(struct drm_device *dev, uint64_t user_pointer)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *)dev->dev_private;
+ struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+ int ret;
+
+ ret = copy_to_user((void __user *)((unsigned long)user_pointer),
+ &topaz_priv->frame_skip, sizeof(topaz_priv->frame_skip));
+
+ if (ret)
+ return -EFAULT;
+
+ return 0;
+}
+
+static void pnw_topaz_flush_cmd_queue(struct pnw_topaz_private *topaz_priv)
+{
+ struct pnw_topaz_cmd_queue *entry, *next;
+
+ /* remind to reset topaz */
+ topaz_priv->topaz_needs_reset = 1;
+
+ if (list_empty(&topaz_priv->topaz_queue)) {
+ topaz_priv->topaz_busy = 0;
+ return;
+ }
+
+ /* flush all command in queue */
+ list_for_each_entry_safe(entry, next,
+ &topaz_priv->topaz_queue,
+ head) {
+ list_del(&entry->head);
+ kfree(entry->cmd);
+ kfree(entry);
+ }
+
+ return;
+}
+
+void pnw_topaz_handle_timeout(struct ttm_fence_device *fdev)
+{
+ struct drm_psb_private *dev_priv =
+ container_of(fdev, struct drm_psb_private, fdev);
+ struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+
+ pnw_topaz_flush_cmd_queue(topaz_priv);
+}
+
+
+void pnw_map_topaz_reg(struct drm_device *dev)
+{
+ unsigned long resource_start;
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *)dev->dev_private;
+
+ resource_start = pci_resource_start(dev->pdev, PSB_MMIO_RESOURCE);
+
+ if (!dev_priv->topaz_disabled) {
+ dev_priv->topaz_reg = ioremap(
+ resource_start + PNW_TOPAZ_OFFSET,
+ PNW_TOPAZ_SIZE);
+ if (!dev_priv->topaz_reg)
+ DRM_ERROR("failed to map TOPAZ register address\n");
+ }
+
+ return;
+}
+
+void pnw_unmap_topaz_reg(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *)dev->dev_private;
+
+ if (dev_priv->topaz_reg) {
+ iounmap(dev_priv->topaz_reg);
+ dev_priv->topaz_reg = NULL;
+ }
+
+ return;
+}
+
+void pnw_topaz_enableirq(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ /* uint32_t ier = dev_priv->vdc_irq_mask | _PNW_IRQ_TOPAZ_FLAG; */
+
+ PSB_DEBUG_IRQ("TOPAZ: enable IRQ\n");
+
+ /* Only enable the master core IRQ*/
+ TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_INTENAB,
+ F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_MAS_INTEN) |
+ /* F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_INTEN_MVEA) | */
+ F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_INTEN_MMU_FAULT) |
+ F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_INTEN_MTX) |
+ F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_INTEN_MTX_HALT),
+ 0);
+
+ /* write in sysirq.c */
+ /* PSB_WVDC32(ier, PSB_INT_ENABLE_R); /\* essential *\/ */
+}
+
+void pnw_topaz_disableirq(struct drm_device *dev)
+{
+
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ /*uint32_t ier = dev_priv->vdc_irq_mask & (~_PNW_IRQ_TOPAZ_FLAG); */
+
+ PSB_DEBUG_INIT("TOPAZ: disable IRQ\n");
+
+ TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_INTENAB, 0, 0);
+
+ /* write in sysirq.c */
+ /* PSB_WVDC32(ier, PSB_INT_ENABLE_R); /\* essential *\/ */
+}
+
--- /dev/null
+/**************************************************************************
+ *
+ * Copyright (c) 2007 Intel Corporation, Hillsboro, OR, USA
+ * Copyright (c) Imagination Technologies Limited, UK
+ *
+ * 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 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.
+ *
+ **************************************************************************/
+
+#ifndef _PNW_TOPAZ_H_
+#define _PNW_TOPAZ_H_
+
+#include "psb_drv.h"
+#include "img_types.h"
+
+#define PNW_TOPAZ_NO_IRQ 0
+#define TOPAZ_MTX_REG_SIZE (34 * 4 + 183 * 4)
+#define MAX_TOPAZ_CORES 2
+
+/*Must be equal to IMG_CODEC_NUM*/
+#define PNW_TOPAZ_CODEC_NUM_MAX (11)
+//#define TOPAZ_PDUMP
+
+extern int drm_topaz_pmpolicy;
+
+/* XXX: it's a copy of msvdx cmd queue. should have some change? */
+struct pnw_topaz_cmd_queue {
+ struct list_head head;
+ void *cmd;
+ unsigned long cmd_size;
+ uint32_t sequence;
+};
+
+/* define structure */
+/* firmware file's info head */
+struct topazsc_fwinfo {
+ unsigned int ver: 16;
+ unsigned int codec: 16;
+
+ unsigned int text_size;
+ unsigned int data_size;
+ unsigned int data_location;
+};
+
+/* firmware data array define */
+struct pnw_topaz_codec_fw {
+ uint32_t ver;
+ uint32_t codec;
+
+ uint32_t text_size;
+ uint32_t data_size;
+ uint32_t data_location;
+
+ struct ttm_buffer_object *text;
+ struct ttm_buffer_object *data;
+};
+
+struct pnw_topaz_private {
+ unsigned int pmstate;
+ struct sysfs_dirent *sysfs_pmstate;
+ int frame_skip;
+
+ void *topaz_mtx_reg_state[MAX_TOPAZ_CORES] ;
+ struct ttm_buffer_object *topaz_mtx_data_mem[MAX_TOPAZ_CORES];
+ uint32_t topaz_cur_codec;
+ uint32_t cur_mtx_data_size[MAX_TOPAZ_CORES];
+ int topaz_needs_reset;
+
+ /*
+ *topaz command queue
+ */
+ spinlock_t topaz_lock;
+ struct mutex topaz_mutex;
+ struct list_head topaz_queue;
+ int topaz_busy; /* 0 means topaz is free */
+ int topaz_fw_loaded;
+
+ uint32_t stored_initial_qp;
+ uint32_t topaz_dash_access_ctrl;
+
+ struct ttm_buffer_object *topaz_bo; /* 4K->2K/2K for writeback/sync */
+ struct ttm_bo_kmap_obj topaz_bo_kmap;
+ uint32_t *topaz_mtx_wb;
+ uint32_t topaz_wb_offset;
+ uint32_t *topaz_sync_addr;
+ uint32_t topaz_sync_offset;
+ uint32_t topaz_cmd_count;
+ uint32_t topaz_mtx_saved;
+
+
+ /* firmware */
+ struct pnw_topaz_codec_fw topaz_fw[PNW_TOPAZ_CODEC_NUM_MAX * 2];
+
+ uint32_t topaz_hw_busy;
+
+ uint32_t topaz_num_cores;
+ uint32_t aui32LastSync[2][MAX_TOPAZ_CORES + 1]; //!< Last sync value sent to each core
+
+ /*Before load firmware, need to set up jitter according to resolution*/
+ /*The data of MTX_CMDID_SW_NEW_CODEC command contains width and length.*/
+ uint16_t frame_w;
+ uint16_t frame_h;
+};
+
+/* external function declare */
+/*ISR of TopazSC*/
+extern IMG_BOOL pnw_topaz_interrupt(IMG_VOID *pvData);
+
+/*topaz commad handling function*/
+extern int pnw_cmdbuf_video(struct drm_file *priv,
+ struct list_head *validate_list,
+ uint32_t fence_type,
+ struct drm_psb_cmdbuf_arg *arg,
+ struct ttm_buffer_object *cmd_buffer,
+ struct psb_ttm_fence_rep *fence_arg);
+extern int pnw_wait_topaz_idle(struct drm_device *dev);
+extern int pnw_check_topaz_idle(struct drm_device *dev);
+extern void pnw_unmap_topaz_reg(struct drm_device *dev);
+extern void pnw_map_topaz_reg(struct drm_device *dev);
+extern int pnw_topaz_restore_mtx_state(struct drm_device *dev);
+extern void pnw_topaz_enableirq(struct drm_device *dev);
+extern void pnw_topaz_disableirq(struct drm_device *dev);
+
+extern int pnw_topaz_init(struct drm_device *dev);
+extern int pnw_topaz_uninit(struct drm_device *dev);
+extern void pnw_topaz_handle_timeout(struct ttm_fence_device *fdev);
+
+extern int pnw_topaz_save_mtx_state(struct drm_device *dev);
+extern void pnw_reset_fw_status(struct drm_device *dev);
+
+extern void topaz_write_core_reg(struct drm_psb_private *dev_priv,
+ uint32_t core,
+ uint32_t reg,
+ const uint32_t val);
+extern void topaz_read_core_reg(struct drm_psb_private *dev_priv,
+ uint32_t core,
+ uint32_t reg,
+ uint32_t *ret_val);
+#define PNW_TOPAZ_NEW_PMSTATE(drm_dev, topaz_priv, new_state) \
+do { \
+ topaz_priv->pmstate = new_state; \
+ sysfs_notify_dirent(topaz_priv->sysfs_pmstate); \
+ PSB_DEBUG_PM("TOPAZ: %s\n", \
+ (new_state == PSB_PMSTATE_POWERUP) ? "powerup": "powerdown"); \
+} while (0)
+
+#endif /* _PNW_TOPAZ_H_ */
--- /dev/null
+/**************************************************************************
+ *
+ * Copyright (c) 2007 Intel Corporation, Hillsboro, OR, USA
+ * Copyright (c) Imagination Technologies Limited, UK
+ *
+ * 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 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.
+ *
+ **************************************************************************/
+
+#ifndef _PNW_TOPAZ_HW_REG_H_
+#define _PNW_TOPAZ_HW_REG_H_
+
+#include "psb_drv.h"
+#include "img_types.h"
+#include "pnw_topaz.h"
+
+/*
+ * MACROS to insert values into fields within a word. The basename of the
+ * field must have MASK_BASENAME and SHIFT_BASENAME constants.
+ */
+#define MM_WRITE32(base, offset, value) \
+do { \
+ *((unsigned long *)((unsigned char *)(dev_priv->topaz_reg) \
+ + base + offset)) = value; \
+} while (0)
+
+#define MM_READ32(base, offset, pointer) \
+do { \
+ *(pointer) = *((unsigned long *)((unsigned char *)(dev_priv->topaz_reg)\
+ + base + offset)); \
+} while (0)
+
+#define F_MASK(basename) (MASK_##basename)
+#define F_SHIFT(basename) (SHIFT_##basename)
+
+#define F_ENCODE(val, basename) \
+ (((val) << (F_SHIFT(basename))) & (F_MASK(basename)))
+
+
+#define F_EXTRACT(val,basename) (((val)&(F_MASK(basename)))>>(F_SHIFT(basename)))
+
+/*! The number of TOPAZ cores present in the system */
+#define TOPAZSC_NUM_CORES 2
+
+#define TOPAZSC_REG_OFF_MAX (TOPAZSC_NUM_CORES * 0x10000 + 0x10000)
+#define REG_BASE_MTX 0x04800000
+#define REG_BASE_HOST 0x00000000
+
+#define MTX_CORE_CODE_MEM (0x10)
+#define MTX_CORE_DATA_MEM (0x18)
+
+/* Multicore Regs */
+#define REG_OFFSET_TOPAZ_MULTICORE 0x00000000
+#define REG_OFFSET_TOPAZ_DMAC 0x00001000
+
+#define REG_SIZE_TOPAZ_MULTICORE 0x00001000
+#define REG_SIZE_TOPAZ_DMAC 0x00001000
+
+/* Topaz core registers - Host view */
+#define REG_OFFSET_TOPAZ_CORE_HOST 0x00010000
+#define REG_SIZE_TOPAZ_CORE_HOST 0x00010000
+
+#define REG_OFFSET_TOPAZ_MTX_HOST 0x00000000
+#define REG_OFFSET_TOPAZ_TOPAZ_HOST 0x00002000
+#define REG_OFFSET_TOPAZ_MVEA_HOST 0x00003000
+#define REG_OFFSET_TOPAZ_MVEACMD_HOST 0x00004000
+#define REG_OFFSET_TOPAZ_VLC_HOST 0x00005000
+#define REG_OFFSET_TOPAZ_DEBLOCKER_HOST 0x00006000
+#define REG_OFFSET_TOPAZ_COMMS_HOST 0x00007000
+#define REG_OFFSET_TOPAZ_ESB_HOST 0x00008000
+
+#define REG_SIZE_TOPAZ_MTX_HOST 0x00002000
+#define REG_SIZE_TOPAZ_TOPAZ_HOST 0x00001000
+#define REG_SIZE_TOPAZ_MVEA_HOST 0x00001000
+#define REG_SIZE_TOPAZ_MVEACMD_HOST 0x00001000
+#define REG_SIZE_TOPAZ_VLC_HOST 0x00001000
+#define REG_SIZE_TOPAZ_DEBLOCKER_HOST 0x00001000
+#define REG_SIZE_TOPAZ_COMMS_HOST 0x00001000
+#define REG_SIZE_TOPAZ_ESB_HOST 0x00004000
+
+
+/* Topaz core registers MTX view */
+#define REG_OFFSET_TOPAZ_CORE_MTX 0x00010000 // MUST confirm
+#define REG_SIZE_TOPAZ_CORE_MTX 0x00010000 // MUST confirm
+
+#define REG_OFFSET_TOPAZ_MTX_MTX 0x00000000
+#define REG_OFFSET_TOPAZ_TOPAZ_MTX 0x00000800
+#define REG_OFFSET_TOPAZ_MVEA_MTX 0x00000C00
+#define REG_OFFSET_TOPAZ_MVEACMD_MTX 0x00001000
+#define REG_OFFSET_TOPAZ_VLC_MTX 0x00001400
+#define REG_OFFSET_TOPAZ_DEBLOCKER_MTX 0x00001800
+#define REG_OFFSET_TOPAZ_COMMS_MTX 0x00001C00
+#define REG_OFFSET_TOPAZ_ESB_MTX 0x00002000
+
+#define REG_SIZE_TOPAZ_MTX_MTX 0x00000800
+#define REG_SIZE_TOPAZ_TOPAZ_MTX 0x00000400
+#define REG_SIZE_TOPAZ_MVEA_MTX 0x00000400
+#define REG_SIZE_TOPAZ_MVEACMD_MTX 0x00000400
+#define REG_SIZE_TOPAZ_VLC_MTX 0x00000400
+#define REG_SIZE_TOPAZ_DEBLOCKER_MTX 0x00000400
+#define REG_SIZE_TOPAZ_COMMS_MTX 0x00000400
+#define REG_SIZE_TOPAZ_ESB_MTX 0x00002000
+
+
+/* Register bank addresses - Host View */
+#define REG_START_TOPAZ_MULTICORE_HOST (REG_BASE_HOST + REG_OFFSET_TOPAZ_MULTICORE)
+#define REG_END_TOPAZ_MULTICORE_HOST (REG_START_TOPAZ_MULTICORE_HOST + REG_SIZE_TOPAZ_MULTICORE)
+
+#define REG_START_TOPAZ_DMAC_HOST (REG_BASE_HOST + REG_OFFSET_TOPAZ_DMAC)
+#define REG_END_TOPAZ_DMAC_HOST (REG_START_TOPAZ_DMAC_HOST + REG_SIZE_TOPAZ_DMAC)
+
+#define REG_START_TOPAZ_MTX_HOST(core) (REG_BASE_HOST + (REG_SIZE_TOPAZ_CORE_HOST*core) + REG_OFFSET_TOPAZ_CORE_HOST + REG_OFFSET_TOPAZ_MTX_HOST)
+#define REG_END_TOPAZ_MTX_HOST(core) (REG_START_TOPAZ_MTX_HOST(core) + REG_SIZE_TOPAZ_MTX_HOST)
+
+#define REG_START_TOPAZ_TOPAZ_HOST(core) (REG_BASE_HOST + (REG_SIZE_TOPAZ_CORE_HOST*core) + REG_OFFSET_TOPAZ_CORE_HOST + REG_OFFSET_TOPAZ_TOPAZ_HOST)
+#define REG_END_TOPAZ_TOPAZ_HOST(core) (REG_START_TOPAZ_TOPAZ_HOST(core) + REG_SIZE_TOPAZ_TOPAZ_HOST)
+
+#define REG_START_TOPAZ_MVEA_HOST(core) (REG_BASE_HOST + (REG_SIZE_TOPAZ_CORE_HOST*core) + REG_OFFSET_TOPAZ_CORE_HOST + REG_OFFSET_TOPAZ_MVEA_HOST)
+#define REG_END_TOPAZ_MVEA_HOST(core) (REG_START_TOPAZ_MVEA_HOST(core) + REG_SIZE_TOPAZ_MVEA_HOST)
+
+
+/* Register bank addresses - MTX view */
+#define REG_START_TOPAZ_MULTICORE_MTX (REG_BASE_MTX + REG_OFFSET_TOPAZ_MULTICORE)
+#define REG_END_TOPAZ_MULTICORE_MTX (REG_START_TOPAZ_MULTICORE_MTX + REG_SIZE_TOPAZ_MULTICORE)
+
+#define REG_START_TOPAZ_DMAC_MTX (REG_BASE_MTX + REG_OFFSET_TOPAZ_DMAC)
+#define REG_END_TOPAZ_DMAC_MTX (REG_START_TOPAZ_DMAC_MTX + REG_SIZE_TOPAZ_DMAC)
+
+#define REG_START_TOPAZ_MTX_MTX(core) (REG_BASE_MTX + (REG_SIZE_TOPAZ_CORE_MTX*core) + REG_OFFSET_TOPAZ_CORE_MTX + REG_OFFSET_TOPAZ_MTX_MTX)
+#define REG_END_TOPAZ_MTX_MTX(core) (REG_START_TOPAZ_MTX_MTX(core) + REG_SIZE_TOPAZ_MTX_MTX)
+
+#define REG_START_TOPAZ_TOPAZ_MTX(core) (REG_BASE_MTX + (REG_SIZE_TOPAZ_CORE_MTX*core) + REG_OFFSET_TOPAZ_CORE_MTX + REG_OFFSET_TOPAZ_TOPAZ_MTX)
+#define REG_END_TOPAZ_TOPAZ_MTX(core) (REG_START_TOPAZ_TOPAZ_MTX(core) + REG_SIZE_TOPAZ_TOPAZ_MTX)
+
+#define REG_START_TOPAZ_MVEA_MTX(core) (REG_BASE_MTX + (REG_SIZE_TOPAZ_CORE_MTX*core) + REG_OFFSET_TOPAZ_CORE_MTX + REG_OFFSET_TOPAZ_MVEA_MTX)
+#define REG_END_TOPAZ_MVEA_MTX(core) (REG_START_TOPAZ_MVEA_MTX(core) + REG_SIZE_TOPAZ_MVEA_MTX)
+
+
+/* Every Topaz core has a 64K address space*/
+#define TOPAZ_CORE_REG_BASE(core) (REG_BASE_HOST + (REG_SIZE_TOPAZ_CORE_HOST*core) + REG_OFFSET_TOPAZ_CORE_HOST)
+
+/* MVEA macro */
+#define MVEA_START 0x03000
+
+#ifdef TOPAZ_PDUMP
+#define MVEA_WRITE32(offset, value, core) \
+ do { \
+ MM_WRITE32(MVEA_START + TOPAZ_CORE_REG_BASE(core), offset, value); \
+ DRM_ERROR("TOPAZ_PDUMP: MVEA core %d, REG_WT %x %x\n", core, offset, value); \
+ } while (0)
+#define MVEA_READ32(offset, pointer, core) \
+ do { \
+ MM_READ32(MVEA_START + TOPAZ_CORE_REG_BASE(core), offset, pointer); \
+ DRM_ERROR("TOPAZ_PDUMP: MVEA core %d, REG_RD %x %x\n", core, offset, *(uint32_t *)pointer);\
+ } while (0)
+#else
+#define MVEA_WRITE32(offset, value, core) \
+ MM_WRITE32(MVEA_START + TOPAZ_CORE_REG_BASE(core), offset, value)
+
+#define MVEA_READ32(offset, pointer, core) \
+ MM_READ32(MVEA_START + TOPAZ_CORE_REG_BASE(core), offset, pointer)
+#endif
+
+#define F_MASK_MVEA(basename) (MASK_MVEA_##basename) /* MVEA */
+#define F_SHIFT_MVEA(basename) (SHIFT_MVEA_##basename) /* MVEA */
+#define F_ENCODE_MVEA(val, basename) \
+ (((val)<<(F_SHIFT_MVEA(basename)))&(F_MASK_MVEA(basename)))
+
+/* MVEA ESB macro */
+#define MVEA_ESB_START 0x08000
+
+#ifdef TOPAZ_PDUMP
+#define MVEA_ESB_WRITE32(offset, value, core) \
+ do { \
+ MM_WRITE32(MVEA_ESB_START + TOPAZ_CORE_REG_BASE(core),\
+ offset, value); \
+ DRM_ERROR("TOPAZ_PDUMP: MVEA core %d, REG_WT %x %x\n", \
+ core, offset, value); \
+ } while (0)
+#define MVEA_ESB_READ32(offset, pointer, core) \
+ do { \
+ MM_READ32(MVEA_ESB_START + TOPAZ_CORE_REG_BASE(core),\
+ offset, pointer); \
+ DRM_ERROR("TOPAZ_PDUMP: MVEA core %d, REG_RD %x %x\n", \
+ core, offset, *(uint32_t *)pointer);\
+ } while (0)
+#else
+#define MVEA_ESB_WRITE32(offset, value, core) \
+ MM_WRITE32(MVEA_ESB_START + TOPAZ_CORE_REG_BASE(core), \
+ offset, value)
+
+#define MVEA_ESB_READ32(offset, pointer, core) \
+ MM_READ32(MVEA_ESB_START + TOPAZ_CORE_REG_BASE(core), \
+ offset, pointer)
+#endif
+
+
+/* VLC macro */
+#define TOPAZ_VLC_START 0x05000
+
+/* TOPAZ macro */
+#define TOPAZ_START 0x02000
+
+#ifdef TOPAZ_PDUMP
+#define TOPAZ_WRITE32(offset, value, core) \
+ do {\
+ MM_WRITE32(TOPAZ_START + TOPAZ_CORE_REG_BASE(core), offset, value); \
+ DRM_ERROR("TOPAZ_PDUMP: TOPAZ_CORE %d REG_WT: %x %x\n", core, \
+ offset, value);\
+ } while (0)
+#define TOPAZ_READ32(offset, pointer, core) \
+ do { \
+ MM_READ32(TOPAZ_START + TOPAZ_CORE_REG_BASE(core), offset, pointer); \
+ DRM_ERROR("TOPAZ_PDUMP: TOPAZ_CORE %d REG_RD: %x %x\n", core, \
+ offset, *(uint32_t *)pointer);\
+ } while (0)
+#else
+#define TOPAZ_WRITE32(offset, value, core) \
+ MM_WRITE32(TOPAZ_START + TOPAZ_CORE_REG_BASE(core), offset, value)
+#define TOPAZ_READ32(offset, pointer, core) \
+ MM_READ32(TOPAZ_START + TOPAZ_CORE_REG_BASE(core), offset, pointer)
+#endif
+#define F_MASK_TOPAZ(basename) (MASK_TOPAZ_##basename)
+#define F_SHIFT_TOPAZ(basename) (SHIFT_TOPAZ_##basename)
+#define F_ENCODE_TOPAZ(val, basename) \
+ (((val)<<(F_SHIFT_TOPAZ(basename)))&(F_MASK_TOPAZ(basename)))
+
+/* MTX macro */
+#define MTX_START 0x0
+
+#ifdef TOPAZ_PDUMP
+#define MTX_WRITE32(offset, value, core) \
+ do { \
+ MM_WRITE32(MTX_START + TOPAZ_CORE_REG_BASE(core), offset, value); \
+ DRM_ERROR("TOPAZ_PDUMP: MTX core %d REG_WT: %x %x\n", core,\
+ offset, value);\
+ } while (0)
+
+
+#define MTX_READ32(offset, pointer, core) \
+ do { \
+ MM_READ32(MTX_START + TOPAZ_CORE_REG_BASE(core), offset, pointer); \
+ DRM_ERROR("TOPAZ_PDUMP: MTX core %d REG_RD %x %x\n", core, \
+ offset, *(uint32_t *)pointer); \
+ } while (0);
+#else
+
+#define MTX_WRITE32(offset, value, core) \
+ MM_WRITE32(MTX_START + TOPAZ_CORE_REG_BASE(core), offset, value)
+#define MTX_READ32(offset, pointer, core) \
+ MM_READ32(MTX_START + TOPAZ_CORE_REG_BASE(core), offset, pointer)
+#endif
+
+/* DMAC macro */
+#define DMAC_START 0x01000
+
+#ifdef TOPAZ_DUMP
+#define DMAC_WRITE32(offset, value) \
+ do { \
+ MM_WRITE32(DMAC_START, offset, value);\
+ DRM_ERROR("TOPAZ_PDUMP: DMAC WT %x %x\n", offset, value);\
+ } while (0);
+
+#define DMAC_READ32(offset, pointer) \
+ do {\
+ MM_READ32(DMAC_START, offset, pointer);\
+ DRM_ERROR("TOPAZ_PDUMP: DMAC RD %x %x\n", offset, *(uint32_t *)pointer); \
+ } while (0)
+#else
+
+#define DMAC_WRITE32(offset, value) \
+ MM_WRITE32(DMAC_START, offset, value)
+
+#define DMAC_READ32(offset, pointer) \
+ MM_READ32(DMAC_START, offset, pointer)
+#endif
+#define F_MASK_DMAC(basename) (MASK_DMAC_##basename)
+#define F_SHIFT_DMAC(basename) (SHIFT_DMAC_##basename)
+#define F_ENCODE_DMAC(val, basename) \
+ (((val)<<(F_SHIFT_DMAC(basename)))&(F_MASK_DMAC(basename)))
+
+/* Register CR_IMG_TOPAZ_INTENAB */
+#define TOPAZ_CR_IMG_TOPAZ_INTENAB 0x0008
+#define MASK_TOPAZ_CR_IMG_TOPAZ_INTEN_MVEA 0x00000001
+#define SHIFT_TOPAZ_CR_IMG_TOPAZ_INTEN_MVEA 0
+#define REGNUM_TOPAZ_CR_IMG_TOPAZ_INTEN_MVEA 0x0008
+
+#define MASK_TOPAZ_CR_IMG_TOPAZ_INTEN_MTX 0x00000002
+#define SHIFT_TOPAZ_CR_IMG_TOPAZ_INTEN_MTX 1
+#define REGNUM_TOPAZ_CR_IMG_TOPAZ_INTEN_MTX 0x0008
+
+#define MASK_TOPAZ_CR_IMG_TOPAZ_INTEN_MTX_HALT 0x00000004
+#define SHIFT_TOPAZ_CR_IMG_TOPAZ_INTEN_MTX_HALT 2
+#define REGNUM_TOPAZ_CR_IMG_TOPAZ_INTEN_MTX_HALT 0x0008
+
+/*(Bit 3 enables fault interrupts caused by the topaz_cores. Bit 4 enables
+ * fault interrupts caused by the DMAC)*/
+#define MASK_TOPAZ_CR_IMG_TOPAZ_INTEN_MMU_FAULT 0x00000018
+#define SHIFT_TOPAZ_CR_IMG_TOPAZ_INTEN_MMU_FAULT 3
+#define REGNUM_TOPAZ_CR_IMG_TOPAZ_INTEN_MMU_FAULT 0x0008
+
+#define MASK_TOPAZ_CR_IMG_TOPAZ_MAS_INTEN 0x80000000
+#define SHIFT_TOPAZ_CR_IMG_TOPAZ_MAS_INTEN 31
+#define REGNUM_TOPAZ_CR_IMG_TOPAZ_MAS_INTEN 0x0008
+
+#define TOPAZ_CR_IMG_TOPAZ_INTCLEAR 0x000C
+#define MASK_TOPAZ_CR_IMG_TOPAZ_INTCLR_MVEA 0x00000001
+#define SHIFT_TOPAZ_CR_IMG_TOPAZ_INTCLR_MVEA 0
+#define REGNUM_TOPAZ_CR_IMG_TOPAZ_INTCLR_MVEA 0x000C
+
+#define TOPAZ_CR_IMG_TOPAZ_INTSTAT 0x0004
+#define MASK_TOPAZ_CR_IMG_TOPAZ_INTS_MVEA 0x00000001
+#define SHIFT_TOPAZ_CR_IMG_TOPAZ_INTS_MVEA 0
+#define REGNUM_TOPAZ_CR_IMG_TOPAZ_INTS_MVEA 0x0004
+
+#define MTX_CCBCTRL_ROFF 0
+#define MTX_CCBCTRL_COMPLETE 4
+#define MTX_CCBCTRL_CCBSIZE 8
+#define MTX_CCBCTRL_QP 12
+#define MTX_CCBCTRL_FRAMESKIP 20
+#define MTX_CCBCTRL_INITQP 24
+
+#define TOPAZ_CR_MMU_STATUS 0x001C
+#define MASK_TOPAZ_CR_MMU_PF_N_RW 0x00000001
+#define SHIFT_TOPAZ_CR_MMU_PF_N_RW 0
+#define REGNUM_TOPAZ_CR_MMU_PF_N_RW 0x001C
+
+#define MASK_TOPAZ_CR_IMG_TOPAZ_INTCLR_MMU_FAULT 0x00000008
+#define SHIFT_TOPAZ_CR_IMG_TOPAZ_INTCLR_MMU_FAULT 3
+#define REGNUM_TOPAZ_CR_IMG_TOPAZ_INTCLR_MMU_FAULT 0x000C
+
+#define TOPAZ_CR_MMU_MEM_REQ 0x0020
+#define MASK_TOPAZ_CR_MEM_REQ_STAT_READS 0x000000FF
+#define SHIFT_TOPAZ_CR_MEM_REQ_STAT_READS 0
+#define REGNUM_TOPAZ_CR_MEM_REQ_STAT_READS 0x0020
+
+#define MASK_TOPAZ_CR_IMG_TOPAZ_INTCLR_MTX 0x00000002
+#define SHIFT_TOPAZ_CR_IMG_TOPAZ_INTCLR_MTX 1
+#define REGNUM_TOPAZ_CR_IMG_TOPAZ_INTCLR_MTX 0x000C
+
+#define MASK_TOPAZ_CR_IMG_TOPAZ_INTCLR_MTX_HALT 0x00000004
+#define SHIFT_TOPAZ_CR_IMG_TOPAZ_INTCLR_MTX_HALT 2
+#define REGNUM_TOPAZ_CR_IMG_TOPAZ_INTCLR_MTX_HALT 0x000C
+
+/* Register CR_TOPAZ_CMD_FIFO_2 */
+#define TOPAZ_CR_TOPAZ_CMD_FIFO_2 0x005C
+#define MASK_TOPAZ_CR_CMD_FIFO_FLUSH 0x00000001
+#define SHIFT_TOPAZ_CR_CMD_FIFO_FLUSH 0
+#define REGNUM_TOPAZ_CR_CMD_FIFO_FLUSH 0x005C
+
+#define MTX_CR_MTX_KICK 0x0080
+#define MASK_MTX_MTX_KICK 0x0000FFFF
+#define SHIFT_MTX_MTX_KICK 0
+#define REGNUM_MTX_MTX_KICK 0x0080
+
+#define MTX_DATA_MEM_BASE 0x82880000
+
+#define MTX_CR_MTX_RAM_ACCESS_CONTROL 0x0108
+#define MASK_MTX_MTX_MCMR 0x00000001
+#define SHIFT_MTX_MTX_MCMR 0
+#define REGNUM_MTX_MTX_MCMR 0x0108
+
+#define MASK_MTX_MTX_MCMID 0x0FF00000
+#define SHIFT_MTX_MTX_MCMID 20
+#define REGNUM_MTX_MTX_MCMID 0x0108
+
+#define MASK_MTX_MTX_MCM_ADDR 0x000FFFFC
+#define SHIFT_MTX_MTX_MCM_ADDR 2
+#define REGNUM_MTX_MTX_MCM_ADDR 0x0108
+
+#define MTX_CR_MTX_RAM_ACCESS_STATUS 0x010C
+#define MASK_MTX_MTX_MTX_MCM_STAT 0x00000001
+#define SHIFT_MTX_MTX_MTX_MCM_STAT 0
+#define REGNUM_MTX_MTX_MTX_MCM_STAT 0x010C
+
+#define MASK_MTX_MTX_MCMAI 0x00000002
+#define SHIFT_MTX_MTX_MCMAI 1
+#define REGNUM_MTX_MTX_MCMAI 0x0108
+
+#define MVEA_CR_MVEA_BUSY 0x0018
+#define MVEA_CR_MVEA_DMACMDFIFO_WAIT 0x001C
+#define MVEA_CR_MVEA_DMACMDFIFO_STATUS 0x0020
+
+#define MVEA_CR_IMG_MVEA_SRST 0x0000
+#define MASK_MVEA_CR_IMG_MVEA_SPE_SOFT_RESET 0x00000001
+#define SHIFT_MVEA_CR_IMG_MVEA_SPE_SOFT_RESET 0
+#define REGNUM_MVEA_CR_IMG_MVEA_SPE_SOFT_RESET 0x0000
+
+#define MASK_MVEA_CR_IMG_MVEA_IPE_SOFT_RESET 0x00000002
+#define SHIFT_MVEA_CR_IMG_MVEA_IPE_SOFT_RESET 1
+#define REGNUM_MVEA_CR_IMG_MVEA_IPE_SOFT_RESET 0x0000
+
+#define MASK_MVEA_CR_IMG_MVEA_CMPRS_SOFT_RESET 0x00000004
+#define SHIFT_MVEA_CR_IMG_MVEA_CMPRS_SOFT_RESET 2
+#define REGNUM_MVEA_CR_IMG_MVEA_CMPRS_SOFT_RESET 0x0000
+
+#define MASK_MVEA_CR_IMG_MVEA_JMCOMP_SOFT_RESET 0x00000008
+#define SHIFT_MVEA_CR_IMG_MVEA_JMCOMP_SOFT_RESET 3
+#define REGNUM_MVEA_CR_IMG_MVEA_JMCOMP_SOFT_RESET 0x0000
+
+#define MASK_MVEA_CR_IMG_MVEA_CMC_SOFT_RESET 0x00000010
+#define SHIFT_MVEA_CR_IMG_MVEA_CMC_SOFT_RESET 4
+#define REGNUM_MVEA_CR_IMG_MVEA_CMC_SOFT_RESET 0x0000
+
+#define MASK_MVEA_CR_IMG_MVEA_DCF_SOFT_RESET 0x00000020
+#define SHIFT_MVEA_CR_IMG_MVEA_DCF_SOFT_RESET 5
+#define REGNUM_MVEA_CR_IMG_MVEA_DCF_SOFT_RESET 0x0000
+
+#define TOPAZ_CR_IMG_TOPAZ_CORE_ID 0x03C0
+#define TOPAZ_CR_IMG_TOPAZ_CORE_REV 0x03D0
+
+#define TOPAZ_MTX_PC (0x00000005)
+
+#define TOPAZ_CR_TOPAZ_AUTO_CLK_GATE 0x0014
+#define MASK_TOPAZ_CR_TOPAZ_VLC_AUTO_CLK_GATE 0x00000001
+#define SHIFT_TOPAZ_CR_TOPAZ_VLC_AUTO_CLK_GATE 0
+#define REGNUM_TOPAZ_CR_TOPAZ_VLC_AUTO_CLK_GATE 0x0014
+
+#define MASK_TOPAZ_CR_TOPAZ_DB_AUTO_CLK_GATE 0x00000002
+#define SHIFT_TOPAZ_CR_TOPAZ_DB_AUTO_CLK_GATE 1
+#define REGNUM_TOPAZ_CR_TOPAZ_DB_AUTO_CLK_GATE 0x0014
+
+#define MTX_CORE_CR_MTX_REGISTER_READ_WRITE_DATA_OFFSET 0x000000F8
+#define MTX_CORE_CR_MTX_REGISTER_READ_WRITE_REQUEST_OFFSET 0x000000FC
+#define MTX_CORE_CR_MTX_REGISTER_READ_WRITE_REQUEST_MTX_RNW_MASK 0x00010000
+#define MTX_CORE_CR_MTX_REGISTER_READ_WRITE_REQUEST_MTX_DREADY_MASK 0x80000000
+
+#define TOPAZ_CORE_CR_MTX_DEBUG_OFFSET 0x00000044
+
+#define MASK_TOPAZ_CR_MTX_RAM_BANKS 0x00000F00
+#define SHIFT_TOPAZ_CR_MTX_RAM_BANKS 8
+#define REGNUM_TOPAZ_CR_MTX_RAM_BANKS 0x0044
+
+#define MASK_TOPAZ_CR_MTX_RAM_BANK_SIZE 0x000F0000
+#define SHIFT_TOPAZ_CR_MTX_RAM_BANK_SIZE 16
+#define REGNUM_TOPAZ_CR_MTX_RAM_BANK_SIZE 0x0044
+
+#define MASK_TOPAZ_CR_MTX_LAST_RAM_BANK_SIZE 0x0F000000
+#define SHIFT_TOPAZ_CR_MTX_LAST_RAM_BANK_SIZE 24
+#define REGNUM_TOPAZ_CR_MTX_LAST_RAM_BANK_SIZE 0x0044
+
+#define MASK_TOPAZ_CR_MTX_DBG_IS_SLAVE 0x00000004
+#define SHIFT_TOPAZ_CR_MTX_DBG_IS_SLAVE 2
+#define REGNUM_TOPAZ_CR_MTX_DBG_IS_SLAVE 0x003C
+
+#define MASK_TOPAZ_CR_MTX_DBG_GPIO_OUT 0x00000018
+#define SHIFT_TOPAZ_CR_MTX_DBG_GPIO_OUT 3
+#define REGNUM_TOPAZ_CR_MTX_DBG_GPIO_OUT 0x003C
+
+/* Register CR_MTX_RAM_ACCESS_DATA_EXCHANGE */
+#define MTX_CR_MTX_RAM_ACCESS_DATA_EXCHANGE 0x0100
+/* Register CR_MTX_RAM_ACCESS_DATA_TRANSFER */
+#define MTX_CR_MTX_RAM_ACCESS_DATA_TRANSFER 0x0104
+
+#define MTX_CORE_CR_MTX_RAM_ACCESS_CONTROL_OFFSET 0x00000108
+#define MASK_MTX_MTX_MCMR 0x00000001
+#define SHIFT_MTX_MTX_MCMR 0
+#define REGNUM_MTX_MTX_MCMR 0x0108
+
+#define MASK_MTX_MTX_MCMAI 0x00000002
+#define SHIFT_MTX_MTX_MCMAI 1
+#define REGNUM_MTX_MTX_MCMAI 0x0108
+
+#define MASK_MTX_MTX_MCM_ADDR 0x000FFFFC
+#define SHIFT_MTX_MTX_MCM_ADDR 2
+#define REGNUM_MTX_MTX_MCM_ADDR 0x0108
+
+#define MASK_MTX_MTX_MCMID 0x0FF00000
+#define SHIFT_MTX_MTX_MCMID 20
+#define REGNUM_MTX_MTX_MCMID 0x0108
+
+#define TOPAZ_CR_MMU_CONTROL0 0x0024
+#define MASK_TOPAZ_CR_MMU_BYPASS_DMAC 0x00020000
+#define SHIFT_TOPAZ_CR_MMU_BYPASS_DMAC 17
+#define REGNUM_TOPAZ_CR_MMU_BYPASS_DMAC 0x0024
+
+#define MASK_TOPAZ_CR_MMU_BYPASS 0x00010000
+#define SHIFT_TOPAZ_CR_MMU_BYPASS 16
+#define REGNUM_TOPAZ_CR_MMU_BYPASS 0x0024
+
+#define TOPAZ_CR_MMU_DIR_LIST_BASE(X) (0x0030 + (4 * (X)))
+#define MASK_TOPAZ_CR_MMU_DIR_LIST_BASE_ADDR 0xFFFFF000
+#define SHIFT_TOPAZ_CR_MMU_DIR_LIST_BASE_ADDR 12
+#define REGNUM_TOPAZ_CR_MMU_DIR_LIST_BASE_ADDR 0x0030
+
+#define MASK_TOPAZ_CR_MMU_INVALDC 0x00000008
+#define SHIFT_TOPAZ_CR_MMU_INVALDC 3
+#define REGNUM_TOPAZ_CR_MMU_INVALDC 0x0024
+
+#define MASK_TOPAZ_CR_MMU_FLUSH 0x00000004
+#define SHIFT_TOPAZ_CR_MMU_FLUSH 2
+#define REGNUM_TOPAZ_CR_MMU_FLUSH 0x0024
+
+#define TOPAZ_CR_MMU_CONTROL1 0x0028
+
+/* Register CR_MMU_BANK_INDEX */
+#define TOPAZ_CR_MMU_BANK_INDEX 0x0040
+#define MASK_TOPAZ_CR_MMU_BANK_N_INDEX_M(i) (0x00000003 << (8 + ((i) * 2)))
+#define SHIFT_TOPAZ_CR_MMU_BANK_N_INDEX_M(i) (8 + ((i) * 2))
+#define REGNUM_TOPAZ_CR_MMU_BANK_N_INDEX_M(i) 0x0040
+
+#define MASK_TOPAZ_CR_MMU_BANK_SELECT(i) (0x00000001 << (0 + ((i) * 1)))
+#define SHIFT_TOPAZ_CR_MMU_BANK_SELECT(i) (0 + ((i) * 1))
+#define REGNUM_TOPAZ_CR_MMU_BANK_SELECT(i) 0x0040
+
+#define TOPAZ_CR_TOPAZ_MAN_CLK_GATE 0x0010
+#define MASK_TOPAZ_CR_TOPAZ_MTX_MAN_CLK_GATE 0x00000002
+#define SHIFT_TOPAZ_CR_TOPAZ_MTX_MAN_CLK_GATE 1
+#define REGNUM_TOPAZ_CR_TOPAZ_MTX_MAN_CLK_GATE 0x0010
+
+#define MTX_CORE_CR_MTX_TXRPT_OFFSET 0x0000000c
+#define TXRPT_WAITONKICK_VALUE 0x8ade0000
+
+#define MTX_CORE_CR_MTX_ENABLE_MTX_TOFF_MASK 0x00000002
+
+#define MTX_CORE_CR_MTX_ENABLE_OFFSET 0x00000000
+#define MTX_CORE_CR_MTX_ENABLE_MTX_ENABLE_MASK 0x00000001
+
+#define MASK_TOPAZ_CR_IMG_TOPAZ_INTS_MTX 0x00000002
+#define SHIFT_TOPAZ_CR_IMG_TOPAZ_INTS_MTX 1
+#define REGNUM_TOPAZ_CR_IMG_TOPAZ_INTS_MTX 0x0004
+
+#define MTX_CORE_CR_MTX_SOFT_RESET_OFFSET 0x00000200
+#define MTX_CORE_CR_MTX_SOFT_RESET_MTX_RESET_MASK 0x00000001
+
+#define MTX_CR_MTX_SYSC_CDMAA 0x0344
+#define MASK_MTX_CDMAA_ADDRESS 0x03FFFFFC
+#define SHIFT_MTX_CDMAA_ADDRESS 2
+#define REGNUM_MTX_CDMAA_ADDRESS 0x0344
+
+#define MTX_CR_MTX_SYSC_CDMAC 0x0340
+#define MASK_MTX_LENGTH 0x0000FFFF
+#define SHIFT_MTX_LENGTH 0
+#define REGNUM_MTX_LENGTH 0x0340
+
+#define MASK_MTX_BURSTSIZE 0x07000000
+#define SHIFT_MTX_BURSTSIZE 24
+#define REGNUM_MTX_BURSTSIZE 0x0340
+
+#define MASK_MTX_RNW 0x00020000
+#define SHIFT_MTX_RNW 17
+#define REGNUM_MTX_RNW 0x0340
+
+#define MASK_MTX_ENABLE 0x00010000
+#define SHIFT_MTX_ENABLE 16
+#define REGNUM_MTX_ENABLE 0x0340
+
+#define MASK_MTX_LENGTH 0x0000FFFF
+#define SHIFT_MTX_LENGTH 0
+#define REGNUM_MTX_LENGTH 0x0340
+
+#define TOPAZ_CR_IMG_TOPAZ_SRST 0x0000
+#define MASK_TOPAZ_CR_IMG_TOPAZ_MVEA_SOFT_RESET 0x00000001
+#define SHIFT_TOPAZ_CR_IMG_TOPAZ_MVEA_SOFT_RESET 0
+#define REGNUM_TOPAZ_CR_IMG_TOPAZ_MVEA_SOFT_RESET 0x0000
+
+#define MASK_TOPAZ_CR_IMG_TOPAZ_IO_SOFT_RESET 0x00000004
+#define SHIFT_TOPAZ_CR_IMG_TOPAZ_IO_SOFT_RESET 2
+#define REGNUM_TOPAZ_CR_IMG_TOPAZ_IO_SOFT_RESET 0x0000
+#define SIGNED_TOPAZ_CR_IMG_TOPAZ_IO_SOFT_RESET 0
+
+#define MASK_TOPAZ_CR_IMG_TOPAZ_VLC_SOFT_RESET 0x00000008
+#define SHIFT_TOPAZ_CR_IMG_TOPAZ_VLC_SOFT_RESET 3
+#define REGNUM_TOPAZ_CR_IMG_TOPAZ_VLC_SOFT_RESET 0x0000
+#define SIGNED_TOPAZ_CR_IMG_TOPAZ_VLC_SOFT_RESET 0
+
+#define MASK_TOPAZ_CR_IMG_TOPAZ_DB_SOFT_RESET 0x00000010
+#define SHIFT_TOPAZ_CR_IMG_TOPAZ_DB_SOFT_RESET 4
+#define REGNUM_TOPAZ_CR_IMG_TOPAZ_DB_SOFT_RESET 0x0000
+#define SIGNED_TOPAZ_CR_IMG_TOPAZ_DB_SOFT_RESET 0
+
+#define MASK_TOPAZ_CR_IMG_TOPAZ_MTX_SOFT_RESET 0x00000002
+#define SHIFT_TOPAZ_CR_IMG_TOPAZ_MTX_SOFT_RESET 1
+#define REGNUM_TOPAZ_CR_IMG_TOPAZ_MTX_SOFT_RESET 0x0000
+
+#define MVEA_CR_MVEA_AUTO_CLOCK_GATING 0x0024
+#define MASK_MVEA_CR_MVEA_SPE_AUTO_CLK_GATE 0x00000001
+#define SHIFT_MVEA_CR_MVEA_SPE_AUTO_CLK_GATE 0
+#define REGNUM_MVEA_CR_MVEA_SPE_AUTO_CLK_GATE 0x0024
+
+#define MASK_MVEA_CR_MVEA_IPE_AUTO_CLK_GATE 0x00000002
+#define SHIFT_MVEA_CR_MVEA_IPE_AUTO_CLK_GATE 1
+#define REGNUM_MVEA_CR_MVEA_IPE_AUTO_CLK_GATE 0x0024
+
+#define MASK_MVEA_CR_MVEA_CMPRS_AUTO_CLK_GATE 0x00000004
+#define SHIFT_MVEA_CR_MVEA_CMPRS_AUTO_CLK_GATE 2
+#define REGNUM_MVEA_CR_MVEA_CMPRS_AUTO_CLK_GATE 0x0024
+
+#define MASK_MVEA_CR_MVEA_JMCOMP_AUTO_CLK_GATE 0x00000008
+#define SHIFT_MVEA_CR_MVEA_JMCOMP_AUTO_CLK_GATE 3
+#define REGNUM_MVEA_CR_MVEA_JMCOMP_AUTO_CLK_GATE 0x0024
+
+/*#define TOPAZ_CR_IMG_TOPAZ_DMAC_MODE 0x0040
+#define MASK_TOPAZ_CR_DMAC_MASTER_MODE 0x00000001
+#define SHIFT_TOPAZ_CR_DMAC_MASTER_MODE 0
+#define REGNUM_TOPAZ_CR_DMAC_MASTER_MODE 0x0040*/
+
+/* Register CR_TOPAZ_HW_CFG */
+#define TOPAZ_CR_TOPAZ_HW_CFG 0x0050
+#define MASK_TOPAZ_CR_NUM_CORES_SUPPORTED 0x0000001F
+#define SHIFT_TOPAZ_CR_NUM_CORES_SUPPORTED 0
+#define REGNUM_TOPAZ_CR_NUM_CORES_SUPPORTED 0x0050
+
+/* Register CR_TOPAZ_CMD_FIFO_0 */
+#define TOPAZ_CR_TOPAZ_CMD_FIFO_0 0x0054
+#define MASK_TOPAZ_CR_CMD_FIFO_RDATA 0xFFFFFFFF
+#define SHIFT_TOPAZ_CR_CMD_FIFO_RDATA 0
+#define REGNUM_TOPAZ_CR_CMD_FIFO_RDATA 0x0054
+
+/* Register CR_TOPAZ_CMD_FIFO_1 */
+#define TOPAZ_CR_TOPAZ_CMD_FIFO_1 0x0058
+#define MASK_TOPAZ_CR_CMD_FIFO_QUANTITY 0x000000FF
+#define SHIFT_TOPAZ_CR_CMD_FIFO_QUANTITY 0
+#define REGNUM_TOPAZ_CR_CMD_FIFO_QUANTITY 0x0058
+
+#define MASK_TOPAZ_CR_CMD_FIFO_NOTEMPTY 0x00000100
+#define SHIFT_TOPAZ_CR_CMD_FIFO_NOTEMPTY 8
+#define REGNUM_TOPAZ_CR_CMD_FIFO_NOTEMPTY 0x0058
+
+/* Register CR_TOPAZ_CMD_FIFO_2 */
+#define TOPAZ_CR_TOPAZ_CMD_FIFO_2 0x005C
+#define MASK_TOPAZ_CR_CMD_FIFO_FLUSH 0x00000001
+#define SHIFT_TOPAZ_CR_CMD_FIFO_FLUSH 0
+#define REGNUM_TOPAZ_CR_CMD_FIFO_FLUSH 0x005C
+
+#define MTX_CR_MTX_SYSC_CDMAT 0x0350
+#define MASK_MTX_TRANSFERDATA 0xFFFFFFFF
+#define SHIFT_MTX_TRANSFERDATA 0
+#define REGNUM_MTX_TRANSFERDATA 0x0350
+
+#define IMG_SOC_DMAC_IRQ_STAT(X) (0x000C + (32 * (X)))
+#define MASK_IMG_SOC_TRANSFER_FIN 0x00020000
+#define SHIFT_IMG_SOC_TRANSFER_FIN 17
+#define REGNUM_IMG_SOC_TRANSFER_FIN 0x000C
+
+#define IMG_SOC_DMAC_COUNT(X) (0x0004 + (32 * (X)))
+#define MASK_IMG_SOC_CNT 0x0000FFFF
+#define SHIFT_IMG_SOC_CNT 0
+#define REGNUM_IMG_SOC_CNT 0x0004
+
+#define MASK_IMG_SOC_EN 0x00010000
+#define SHIFT_IMG_SOC_EN 16
+#define REGNUM_IMG_SOC_EN 0x0004
+
+#define MASK_IMG_SOC_LIST_EN 0x00040000
+#define SHIFT_IMG_SOC_LIST_EN 18
+#define REGNUM_IMG_SOC_LIST_EN 0x0004
+
+#define IMG_SOC_DMAC_PER_HOLD(X) (0x0018 + (32 * (X)))
+#define MASK_IMG_SOC_PER_HOLD 0x0000007F
+#define SHIFT_IMG_SOC_PER_HOLD 0
+#define REGNUM_IMG_SOC_PER_HOLD 0x0018
+
+#define IMG_SOC_DMAC_SETUP(X) (0x0000 + (32 * (X)))
+#define MASK_IMG_SOC_START_ADDRESS 0xFFFFFFF
+#define SHIFT_IMG_SOC_START_ADDRESS 0
+#define REGNUM_IMG_SOC_START_ADDRESS 0x0000
+
+#define MASK_IMG_SOC_BSWAP 0x40000000
+#define SHIFT_IMG_SOC_BSWAP 30
+#define REGNUM_IMG_SOC_BSWAP 0x0004
+
+#define MASK_IMG_SOC_PW 0x18000000
+#define SHIFT_IMG_SOC_PW 27
+#define REGNUM_IMG_SOC_PW 0x0004
+
+#define MASK_IMG_SOC_DIR 0x04000000
+#define SHIFT_IMG_SOC_DIR 26
+#define REGNUM_IMG_SOC_DIR 0x0004
+
+#define MASK_IMG_SOC_PI 0x03000000
+#define SHIFT_IMG_SOC_PI 24
+#define REGNUM_IMG_SOC_PI 0x0004
+#define IMG_SOC_PI_1 0x00000002
+#define IMG_SOC_PI_2 0x00000001
+#define IMG_SOC_PI_4 0x00000000
+
+#define MASK_IMG_SOC_TRANSFER_IEN 0x20000000
+#define SHIFT_IMG_SOC_TRANSFER_IEN 29
+#define REGNUM_IMG_SOC_TRANSFER_IEN 0x0004
+
+#define DMAC_VALUE_COUNT(BSWAP, PW, DIR, PERIPH_INCR, COUNT) \
+ ((((BSWAP) << SHIFT_IMG_SOC_BSWAP) & MASK_IMG_SOC_BSWAP)| \
+ (((PW) << SHIFT_IMG_SOC_PW) & MASK_IMG_SOC_PW)| \
+ (((DIR) << SHIFT_IMG_SOC_DIR) & MASK_IMG_SOC_DIR)| \
+ (((PERIPH_INCR) << SHIFT_IMG_SOC_PI) & MASK_IMG_SOC_PI)| \
+ (((COUNT) << SHIFT_IMG_SOC_CNT) & MASK_IMG_SOC_CNT))
+
+#define IMG_SOC_DMAC_PERIPH(X) (0x0008 + (32 * (X)))
+#define MASK_IMG_SOC_EXT_SA 0x0000000F
+#define SHIFT_IMG_SOC_EXT_SA 0
+#define REGNUM_IMG_SOC_EXT_SA 0x0008
+
+#define MASK_IMG_SOC_ACC_DEL 0xE0000000
+#define SHIFT_IMG_SOC_ACC_DEL 29
+#define REGNUM_IMG_SOC_ACC_DEL 0x0008
+
+#define MASK_IMG_SOC_INCR 0x08000000
+#define SHIFT_IMG_SOC_INCR 27
+#define REGNUM_IMG_SOC_INCR 0x0008
+
+#define MASK_IMG_SOC_BURST 0x07000000
+#define SHIFT_IMG_SOC_BURST 24
+#define REGNUM_IMG_SOC_BURST 0x0008
+
+#define DMAC_VALUE_PERIPH_PARAM(ACC_DEL, INCR, BURST) \
+((((ACC_DEL) << SHIFT_IMG_SOC_ACC_DEL) & MASK_IMG_SOC_ACC_DEL)| \
+(((INCR) << SHIFT_IMG_SOC_INCR) & MASK_IMG_SOC_INCR)| \
+(((BURST) << SHIFT_IMG_SOC_BURST) & MASK_IMG_SOC_BURST))
+
+#define IMG_SOC_DMAC_PERIPHERAL_ADDR(X) (0x0014 + (32 * (X)))
+#define MASK_IMG_SOC_ADDR 0x007FFFFF
+#define SHIFT_IMG_SOC_ADDR 0
+#define REGNUM_IMG_SOC_ADDR 0x0014
+
+#define SHIFT_TOPAZ_VEC_BUSY 11
+#define MASK_TOPAZ_VEC_BUSY (0x1<<SHIFT_TOPAZ_VEC_BUSY)
+
+#define TOPAZ_MTX_TXRPT_OFFSET 0xc
+#define TOPAZ_GUNIT_GVD_PSMI_GFX_OFFSET 0x20D0
+
+#define TOPAZ_GUNIT_READ32(offset) ioread32(dev_priv->vdc_reg + offset)
+#define TOPAZ_READ_BITS(val, basename) \
+ (((val)&MASK_TOPAZ_##basename)>>SHIFT_TOPAZ_##basename)
+
+#define TOPAZ_WAIT_UNTIL_IDLE \
+ do { \
+ uint8_t tmp_poll_number = 0;\
+ uint32_t tmp_reg; \
+ if (topaz_priv->topaz_cmd_windex == WB_CCB_CTRL_RINDEX(dev_priv)) { \
+ tmp_reg = TOPAZ_GUNIT_READ32(TOPAZ_GUNIT_GVD_PSMI_GFX_OFFSET);\
+ if (0 != TOPAZ_READ_BITS(tmp_reg, VEC_BUSY)) { \
+ MTX_READ32(TOPAZ_MTX_TXRPT_OFFSET, &tmp_reg);\
+ while ((tmp_reg != 0x8ade0000) && \
+ (tmp_poll_number++ < 10)) \
+ MTX_READ32(0xc, &tmp_reg); \
+ PSB_DEBUG_GENERAL( \
+ "TOPAZ: TXRPT reg remain: %x,poll %d times.\n",\
+ tmp_reg, tmp_poll_number);\
+ } \
+ } \
+ } while (0)
+
+/* Register CR_BUFFER_SIDEBAND */
+#define MVEA_CR_BUFFER_SIDEBAND 0x017C
+#define MASK_MVEA_CR_CURR_MB_SBAND 0x00000003
+#define SHIFT_MVEA_CR_CURR_MB_SBAND 0
+#define REGNUM_MVEA_CR_CURR_MB_SBAND 0x017C
+
+#define MASK_MVEA_CR_ABOVE_PIX_IN_SBAND 0x0000000C
+#define SHIFT_MVEA_CR_ABOVE_PIX_IN_SBAND 2
+#define REGNUM_MVEA_CR_ABOVE_PIX_IN_SBAND 0x017C
+
+#define MASK_MVEA_CR_CURR_PARAM_SBAND 0x00000030
+#define SHIFT_MVEA_CR_CURR_PARAM_SBAND 4
+#define REGNUM_MVEA_CR_CURR_PARAM_SBAND 0x017C
+
+#define MASK_MVEA_CR_BELOW_PARAM_IN_SBAND 0x000000C0
+#define SHIFT_MVEA_CR_BELOW_PARAM_IN_SBAND 6
+#define REGNUM_MVEA_CR_BELOW_PARAM_IN_SBAND 0x017C
+
+#define MASK_MVEA_CR_ABOVE_PARAM_IN_SBAND 0x00000300
+#define SHIFT_MVEA_CR_ABOVE_PARAM_IN_SBAND 8
+#define REGNUM_MVEA_CR_ABOVE_PARAM_IN_SBAND 0x017C
+
+#define MASK_MVEA_CR_REF_SBAND 0x00000C00
+#define SHIFT_MVEA_CR_REF_SBAND 10
+#define REGNUM_MVEA_CR_REF_SBAND 0x017C
+
+#define MASK_MVEA_CR_RECON_SBAND 0x00003000
+#define SHIFT_MVEA_CR_RECON_SBAND 12
+#define REGNUM_MVEA_CR_RECON_SBAND 0x017C
+
+#define MASK_MVEA_CR_ABOVE_PIX_OUT_SBAND 0x0000C000
+#define SHIFT_MVEA_CR_ABOVE_PIX_OUT_SBAND 14
+#define REGNUM_MVEA_CR_ABOVE_PIX_OUT_SBAND 0x017C
+
+#define MASK_MVEA_CR_BELOW_PARAM_OUT_SBAND 0x00030000
+#define SHIFT_MVEA_CR_BELOW_PARAM_OUT_SBAND 16
+#define REGNUM_MVEA_CR_BELOW_PARAM_OUT_SBAND 0x017C
+
+#define MASK_MVEA_CR_ABOVE_PARAM_OUT_SBAND 0x000C0000
+#define SHIFT_MVEA_CR_ABOVE_PARAM_OUT_SBAND 18
+#define REGNUM_MVEA_CR_ABOVE_PARAM_OUT_SBAND 0x017C
+
+/* Register CR_IPE_JITTER_FACTOR */
+#define MVEA_CR_IPE_JITTER_FACTOR 0x0218
+#define MASK_MVEA_CR_IPE_JITTER_FACTOR 0x00000003
+#define SHIFT_MVEA_CR_IPE_JITTER_FACTOR 0
+#define REGNUM_MVEA_CR_IPE_JITTER_FACTOR 0x0218
+
+/* Register CR_MULTICORE_INT_STAT */
+#define TOPAZSC_CR_MULTICORE_INT_STAT 0x0000
+#define MASK_TOPAZSC_CR_INT_STAT_DMAC 0x80000000
+#define SHIFT_TOPAZSC_CR_INT_STAT_DMAC 31
+#define REGNUM_TOPAZSC_CR_INT_STAT_DMAC 0x0000
+
+#define MASK_TOPAZSC_CR_INT_STAT_CORES 0x7FFFFFFF
+#define SHIFT_TOPAZSC_CR_INT_STAT_CORES 0
+#define REGNUM_TOPAZSC_CR_INT_STAT_CORES 0x0000
+
+/* Register CR_MULTICORE_CORE_SEL_0 */
+#define TOPAZSC_CR_MULTICORE_CORE_SEL_0 0x0004
+#define MASK_TOPAZSC_CR_DMAC_CORE_SELECT 0x0000000F
+#define SHIFT_TOPAZSC_CR_DMAC_CORE_SELECT 0
+#define REGNUM_TOPAZSC_CR_DMAC_CORE_SELECT 0x0004
+
+#define MASK_TOPAZSC_CR_WRITES_CORE_ALL 0x80000000
+#define SHIFT_TOPAZSC_CR_WRITES_CORE_ALL 31
+#define REGNUM_TOPAZSC_CR_WRITES_CORE_ALL 0x0004
+
+/* Register CR_MULTICORE_CORE_SEL_1 */
+#define TOPAZSC_CR_MULTICORE_CORE_SEL_1 0x0008
+#define MASK_TOPAZSC_CR_RTM_PORT_CORE_SELECT 0x0000000F
+#define SHIFT_TOPAZSC_CR_RTM_PORT_CORE_SELECT 0
+#define REGNUM_TOPAZSC_CR_RTM_PORT_CORE_SELECT 0x0008
+
+/* Register CR_MULTICORE_RSVD0 */
+#define TOPAZSC_CR_MULTICORE_RSVD0 0x0010
+#define MASK_TOPAZSC_CR_RESERVED0 0xFFFFFFFF
+#define SHIFT_TOPAZSC_CR_RESERVED0 0
+#define REGNUM_TOPAZSC_CR_RESERVED0 0x0010
+
+/* Register CR_MULTICORE_CMD_FIFO_0 */
+#define TOPAZSC_CR_MULTICORE_CMD_FIFO_0 0x0014
+#define MASK_TOPAZSC_CR_CMD_FIFO_WDATA 0xFFFFFFFF
+#define SHIFT_TOPAZSC_CR_CMD_FIFO_WDATA 0
+#define REGNUM_TOPAZSC_CR_CMD_FIFO_WDATA 0x0014
+
+/* Register CR_MULTICORE_CMD_FIFO_1 */
+#define TOPAZSC_CR_MULTICORE_CMD_FIFO_1 0x0018
+#define MASK_TOPAZSC_CR_CMD_FIFO_SPACE 0x000000FF
+#define SHIFT_TOPAZSC_CR_CMD_FIFO_SPACE 0
+#define REGNUM_TOPAZSC_CR_CMD_FIFO_SPACE 0x0018
+
+#define MASK_TOPAZSC_CR_CMD_FIFO_FULL 0x00000100
+#define SHIFT_TOPAZSC_CR_CMD_FIFO_FULL 8
+#define REGNUM_TOPAZSC_CR_CMD_FIFO_FULL 0x0018
+
+/* Register CR_MULTICORE_IDLE_PWR_MAN */
+#define TOPAZSC_CR_MULTICORE_IDLE_PWR_MAN 0x001C
+#define MASK_TOPAZSC_CR_TOPAZ_IDLE_DISABLE 0x00000001
+#define SHIFT_TOPAZSC_CR_TOPAZ_IDLE_DISABLE 0
+#define REGNUM_TOPAZSC_CR_TOPAZ_IDLE_DISABLE 0x001C
+
+/* Register CR_CMC_PROC_ESB_ACCESS */
+#define MVEA_CR_CMC_PROC_ESB_ACCESS 0x011C
+#define MASK_MVEA_CR_CMC_PROC_ESB_REGION_NUMBER 0x0000001F
+#define SHIFT_MVEA_CR_CMC_PROC_ESB_REGION_NUMBER 0
+#define REGNUM_MVEA_CR_CMC_PROC_ESB_REGION_NUMBER 0x011C
+#define SIGNED_MVEA_CR_CMC_PROC_ESB_REGION_NUMBER 0
+
+
+/* Table CR_CMC_ESB_LOGICAL_REGION_SETUP_TABLE */
+
+/* Register CR_CMC_ESB_LOGICAL_REGION_SETUP */
+#define MVEA_CR_CMC_ESB_LOGICAL_REGION_SETUP(X) (0x0080 + (4 * (X)))
+#define MASK_MVEA_CR_CMC_ESB_REGION_VALID 0x80000000
+#define SHIFT_MVEA_CR_CMC_ESB_REGION_VALID 31
+#define REGNUM_MVEA_CR_CMC_ESB_REGION_VALID 0x0080
+#define SIGNED_MVEA_CR_CMC_ESB_REGION_VALID 0
+
+#define MASK_MVEA_CR_CMC_ESB_REGION_TYPE 0x60000000
+#define SHIFT_MVEA_CR_CMC_ESB_REGION_TYPE 29
+#define REGNUM_MVEA_CR_CMC_ESB_REGION_TYPE 0x0080
+#define SIGNED_MVEA_CR_CMC_ESB_REGION_TYPE 0
+
+#define MASK_MVEA_CR_CMC_ESB_REGION_LOGICAL_WIDTH 0x00F00000
+#define SHIFT_MVEA_CR_CMC_ESB_REGION_LOGICAL_WIDTH 20
+#define REGNUM_MVEA_CR_CMC_ESB_REGION_LOGICAL_WIDTH 0x0080
+#define SIGNED_MVEA_CR_CMC_ESB_REGION_LOGICAL_WIDTH 0
+
+#define MASK_MVEA_CR_CMC_ESB_REGION_LOGICAL_OFFSET_X 0x000F0000
+#define SHIFT_MVEA_CR_CMC_ESB_REGION_LOGICAL_OFFSET_X 16
+#define REGNUM_MVEA_CR_CMC_ESB_REGION_LOGICAL_OFFSET_X 0x0080
+#define SIGNED_MVEA_CR_CMC_ESB_REGION_LOGICAL_OFFSET_X 0
+
+#define MASK_MVEA_CR_CMC_ESB_REGION_PHYS_HEIGHT 0x0000F000
+#define SHIFT_MVEA_CR_CMC_ESB_REGION_PHYS_HEIGHT 12
+#define REGNUM_MVEA_CR_CMC_ESB_REGION_PHYS_HEIGHT 0x0080
+#define SIGNED_MVEA_CR_CMC_ESB_REGION_PHYS_HEIGHT 0
+
+#define MASK_MVEA_CR_CMC_ESB_REGION_PHYS_WIDTH 0x00000F00
+#define SHIFT_MVEA_CR_CMC_ESB_REGION_PHYS_WIDTH 8
+#define REGNUM_MVEA_CR_CMC_ESB_REGION_PHYS_WIDTH 0x0080
+#define SIGNED_MVEA_CR_CMC_ESB_REGION_PHYS_WIDTH 0
+
+#define MASK_MVEA_CR_CMC_ESB_REGION_PHYS_ORIGIN_Y 0x000000F0
+#define SHIFT_MVEA_CR_CMC_ESB_REGION_PHYS_ORIGIN_Y 4
+#define REGNUM_MVEA_CR_CMC_ESB_REGION_PHYS_ORIGIN_Y 0x0080
+#define SIGNED_MVEA_CR_CMC_ESB_REGION_PHYS_ORIGIN_Y 0
+
+#define MASK_MVEA_CR_CMC_ESB_REGION_PHYS_ORIGIN_X 0x0000000F
+#define SHIFT_MVEA_CR_CMC_ESB_REGION_PHYS_ORIGIN_X 0
+#define REGNUM_MVEA_CR_CMC_ESB_REGION_PHYS_ORIGIN_X 0x0080
+#define SIGNED_MVEA_CR_CMC_ESB_REGION_PHYS_ORIGIN_X 0
+
+
+/* Bit 31:16 is the count of remaining items to be transferred */
+/* Bit 0 is 1 if transfer State == 'do_nothing'*/
+#define MTX_CR_MTX_SYSC_CDMAS0 0x0348
+
+/* Bit 25:2 is the current core DMA transfer address.*/
+#define MTX_CR_MTX_SYSC_CDMAS1 0x034C
+
+/* Bit 31:0 is the data to be wroten */
+#define MTX_CR_MTX_SYSC_CDMAT 0x0350
+
+/* Number of entries in table CR_CMC_ESB_LOGICAL_REGION_SETUP_TABLE */
+
+#define MVEA_CR_CMC_ESB_LOGICAL_REGION_SETUP_TABLE_SIZE_UINT32 32
+#define MVEA_CR_CMC_ESB_LOGICAL_REGION_SETUP_TABLE_NUM_ENTRIES 32
+
+#define ESB_HWSYNC 10
+#define ESB_POS_MANGLER_ORIGINX(x) ((x) >> 3)
+#define ESB_POS_MANGLER(x) ((x) >> 3)
+
+#define ESB_SIZE_MANGLER(x) (((x) >> 3) - 1)
+#define REGION_TYPE_LINEAR 0
+
+#define TOPAZSC_ESB_REGION_Y_MAX (46)
+#define TOPAZSC_ESB_REGION_X_MAX (64)
+
+#define TOPAZSC_ESB_REGION_HEIGH (48)
+#define TOPAZSC_ESB_REGION_WIDTH (64)
+
+
+#define REG_OFFSET_COMMS_CORE_HOST 0x00070000
+#define REG_SIZE_COMMS_CORE_HOST 0x00070000
+#define REG_OFFSET_TOPAZ_COMMS_HOST 0x00007000
+#define REG_SIZE_TOPAZ_COMMS_HOST 0x00001000
+#define TOPAZ_COMMS_START 0x07000
+/* Register CR_STAT_1 */
+#define TOPAZ_COMMS_CR_STAT_1(X) (0x0018 + (192 * (X)))
+#define MASK_TOPAZ_COMMS_CR_STAT_DATA_1 0xFFFFFFFF
+#define SHIFT_TOPAZ_COMMS_CR_STAT_DATA_1 0
+#define REGNUM_TOPAZ_COMMS_CR_STAT_DATA_1 0x0018
+
+/* Register CR_STAT_0 */
+#define TOPAZ_COMMS_CR_STAT_0(X) (0x0014 + (192 * (X)))
+#define MASK_TOPAZ_COMMS_CR_STAT_DATA_0 0xFFFFFFFF
+#define SHIFT_TOPAZ_COMMS_CR_STAT_DATA_0 0
+#define REGNUM_TOPAZ_COMMS_CR_STAT_DATA_0 0x0014
+
+/* Register CR_MTX_STATUS */
+#define TOPAZ_COMMS_CR_MTX_STATUS(X) (0x0010 + (192 * (X)))
+#define MASK_TOPAZ_COMMS_FLAGS_WORD 0xFFFFFFFF
+#define SHIFT_TOPAZ_COMMS_FLAGS_WORD 0
+#define REGNUM_TOPAZ_COMMS_FLAGS_WORD 0x0010
+
+/* Register CR_CMD_WB_VAL */
+#define TOPAZ_COMMS_CR_CMD_WB_VAL(X) (0x000C + (192 * (X)))
+#define MASK_TOPAZ_COMMS_CR_WB_VAL 0xFFFFFFFF
+#define SHIFT_TOPAZ_COMMS_CR_WB_VAL 0
+#define REGNUM_TOPAZ_COMMS_CR_WB_VAL 0x000C
+
+/* Register CR_CMD_WB_ADDR */
+#define TOPAZ_COMMS_CR_CMD_WB_ADDR(X) (0x0008 + (192 * (X)))
+#define MASK_TOPAZ_COMMS_CR_WB_ADDR 0xFFFFFFFF
+#define SHIFT_TOPAZ_COMMS_CR_WB_ADDR 0
+#define REGNUM_TOPAZ_COMMS_CR_WB_ADDR 0x0008
+
+/* Register CR_CMD_DATA_ADDR */
+#define TOPAZ_COMMS_CR_CMD_DATA_ADDR(X) (0x0004 + (192 * (X)))
+#define MASK_TOPAZ_COMMS_CR_DATA_ADDR 0xFFFFFFFF
+#define SHIFT_TOPAZ_COMMS_CR_DATA_ADDR 0
+#define REGNUM_TOPAZ_COMMS_CR_DATA_ADDR 0x0004
+/* Register CR_TOPAZ_HW_CFG */
+#define TOPAZ_CR_TOPAZ_HW_CFG 0x0050
+#define MASK_TOPAZ_CR_NUM_CORES_SUPPORTED 0x0000001F
+#define SHIFT_TOPAZ_CR_NUM_CORES_SUPPORTED 0
+#define REGNUM_TOPAZ_CR_NUM_CORES_SUPPORTED 0x0050
+/* Register CR_CMD_WORD */
+#define TOPAZ_COMMS_CR_CMD_WORD(X) (0x0000 + (192 * (X)))
+#define MASK_TOPAZ_COMMS_CR_MTX_CMD_ID 0x0000007F
+#define SHIFT_TOPAZ_COMMS_CR_MTX_CMD_ID 0
+#define REGNUM_TOPAZ_COMMS_CR_MTX_CMD_ID 0x0000
+#define MTX_CR_MTX_SYSC_CDMAT 0x0350
+#define MASK_MTX_TRANSFERDATA 0xFFFFFFFF
+#define SHIFT_MTX_TRANSFERDATA 0
+#define REGNUM_MTX_TRANSFERDATA 0x0350
+
+
+#define COMMS_WRITE32(offset, value, core) \
+ MM_WRITE32(TOPAZ_COMMS_START + TOPAZ_CORE_REG_BASE(core), \
+ offset, value)
+#define COMMS_READ32(offset, pointer, core) \
+ MM_READ32(TOPAZ_COMMS_START + TOPAZ_CORE_REG_BASE(core), \
+ offset, pointer)
+
+#define TOPAZ_CORE_NUMBER_SET_OFFSET (0x100 + (2 << 2))
+
+#define REG_SIZE_COMMS_CORE_HOST 0x00070000
+#define MVEASETUPESBREGION(_OriginX_, _OriginY_, _PhysWidth_,\
+ _PhysHeight_, _LogWidth_, _RegType_)\
+((F_ENCODE(ESB_POS_MANGLER_ORIGINX(_OriginX_),\
+ MVEA_CR_CMC_ESB_REGION_PHYS_ORIGIN_X))\
+ | (F_ENCODE(ESB_POS_MANGLER(_OriginY_),\
+ MVEA_CR_CMC_ESB_REGION_PHYS_ORIGIN_Y))\
+ | (F_ENCODE(ESB_SIZE_MANGLER(_PhysWidth_),\
+ MVEA_CR_CMC_ESB_REGION_PHYS_WIDTH))\
+ | (F_ENCODE(ESB_SIZE_MANGLER(_PhysHeight_),\
+ MVEA_CR_CMC_ESB_REGION_PHYS_HEIGHT))\
+ | (F_ENCODE(ESB_SIZE_MANGLER(_LogWidth_),\
+ MVEA_CR_CMC_ESB_REGION_LOGICAL_WIDTH))\
+ | (F_ENCODE(_RegType_, MVEA_CR_CMC_ESB_REGION_TYPE))\
+ | (F_ENCODE(1, MVEA_CR_CMC_ESB_REGION_VALID)))
+
+
+#define TOPAZ_MULTICORE_START 0x00000000
+
+#ifdef TOPAZ_PDUMP
+#define TOPAZ_MULTICORE_WRITE32(offset, value) \
+ do { \
+ MM_WRITE32(TOPAZ_MULTICORE_START, offset, value); \
+ DRM_ERROR("TOPAZ_PDUMP: MULTICORE, REG_WT %x %x\n", offset, value);\
+ } while (0)
+
+#define TOPAZ_MULTICORE_READ32(offset,pointer) \
+ do { \
+ MM_READ32(TOPAZ_MULTICORE_START, offset, pointer); \
+ DRM_ERROR("TOPAZ_PDUMP: MULTICORE, REG_RD %x %x\n", offset, *(uint32_t *)pointer); \
+ } while (0)
+#else
+#define TOPAZ_MULTICORE_WRITE32(offset, value) \
+ MM_WRITE32(TOPAZ_MULTICORE_START, offset, value)
+#define TOPAZ_MULTICORE_READ32(offset,pointer) \
+ MM_READ32(TOPAZ_MULTICORE_START, offset, pointer)
+#endif
+
+#define MTX_DMA_BURSTSIZE_BYTES 32
+#define MTX_DMA_ALIGNMENT_BYTES 16
+
+#define MTX_DMA_MEMORY_BASE (0x82880000)
+#define PC_START_ADDRESS (0x80900000)
+
+#define MAX_TOPAZ_CMD_COUNT (0x1000) /* max syncStatus value used*/
+
+
+#define MTX_WRITEBACK_DATASIZE_ROUND 4
+
+#define TOPAZ_MTX_WB_READ32(base, core, word, pointer) \
+ do { \
+ *(uint32_t *)(pointer) = *((uint32_t *)(base) + \
+ (core)*MTX_WRITEBACK_DATASIZE_ROUND + (word) ); \
+ } while (0)
+
+#define TOPAZ_MTX_WB_WRITE32(base, core, word, value) \
+ do { \
+ *((uint32_t *)(base) + (core)*MTX_WRITEBACK_DATASIZE_ROUND + (word) ) \
+ = value; \
+ } while (0)
+
+
+#define TOPAZ_MTX_WB_OFFSET(base, core) \
+ ((base) + (core)*MTX_WRITEBACK_DATASIZE_ROUND*4)
+
+#define POLL_TOPAZ_FREE_FIFO_SPACE(word_num, delay, retries, pointer) \
+ do { \
+ uint32_t free_space=0, i; \
+ for (i = 0; i < retries; i++) {\
+ TOPAZ_MULTICORE_READ32(TOPAZSC_CR_MULTICORE_CMD_FIFO_1, &free_space);\
+ free_space &= MASK_TOPAZSC_CR_CMD_FIFO_SPACE; \
+ if (free_space >= word_num) \
+ break; \
+ else \
+ PSB_UDELAY(delay);\
+ }\
+ if ( i >= retries){ \
+ ret = -1;\
+ DRM_ERROR("TOPAZ: poll FIFO free space failed (%d words free)!\n", free_space); \
+ }\
+ else \
+ ret = 0; \
+ *pointer = free_space; \
+ } while (0)
+
+
+/* **************** DMAC define **************** */
+enum DMAC_eBSwap {
+ DMAC_BSWAP_NO_SWAP = 0x0,/* !< No byte swapping will be performed. */
+ DMAC_BSWAP_REVERSE = 0x1,/* !< Byte order will be reversed. */
+};
+
+enum DMAC_ePW {
+ DMAC_PWIDTH_32_BIT = 0x0,/* !< Peripheral width 32-bit. */
+ DMAC_PWIDTH_16_BIT = 0x1,/* !< Peripheral width 16-bit. */
+ DMAC_PWIDTH_8_BIT = 0x2,/* !< Peripheral width 8-bit. */
+};
+
+enum DMAC_eAccDel {
+ DMAC_ACC_DEL_0 = 0x0, /* !< Access delay zero clock cycles */
+ DMAC_ACC_DEL_256 = 0x1, /* !< Access delay 256 clock cycles */
+ DMAC_ACC_DEL_512 = 0x2, /* !< Access delay 512 clock cycles */
+ DMAC_ACC_DEL_768 = 0x3, /* !< Access delay 768 clock cycles */
+ DMAC_ACC_DEL_1024 = 0x4,/* !< Access delay 1024 clock cycles */
+ DMAC_ACC_DEL_1280 = 0x5,/* !< Access delay 1280 clock cycles */
+ DMAC_ACC_DEL_1536 = 0x6,/* !< Access delay 1536 clock cycles */
+ DMAC_ACC_DEL_1792 = 0x7,/* !< Access delay 1792 clock cycles */
+};
+
+enum DMAC_eBurst {
+ DMAC_BURST_0 = 0x0, /* !< burst size of 0 */
+ DMAC_BURST_1 = 0x1, /* !< burst size of 1 */
+ DMAC_BURST_2 = 0x2, /* !< burst size of 2 */
+ DMAC_BURST_3 = 0x3, /* !< burst size of 3 */
+ DMAC_BURST_4 = 0x4, /* !< burst size of 4 */
+ DMAC_BURST_5 = 0x5, /* !< burst size of 5 */
+ DMAC_BURST_6 = 0x6, /* !< burst size of 6 */
+ DMAC_BURST_7 = 0x7, /* !< burst size of 7 */
+};
+
+/* commands for topaz,shared with user space driver */
+enum drm_pnw_topaz_cmd {
+ MTX_CMDID_NULL = 0,
+ MTX_CMDID_SHUTDOWN = 1,
+ MTX_CMDID_START_PIC = 2,
+ MTX_CMDID_DO_HEADER = 3,
+ MTX_CMDID_ENCODE_SLICE = 4,
+ MTX_CMDID_END_PIC = 5,
+ MTX_CMDID_FLUSH = 6,
+ /*JPEG commands*/
+ MTX_CMDID_SETQUANT = 7,
+ MTX_CMDID_RESET_ENCODE = 8,
+ MTX_CMDID_ISSUEBUFF = 9,
+ MTX_CMDID_SETUP = 10,
+
+ MTX_CMDID_PAD = 0x7a, /*Will be ignored*/
+ MTX_CMDID_SW_WRITEREG = 0x7b,
+ MTX_CMDID_SW_LEAVE_LOWPOWER = 0x7c,
+ MTX_CMDID_SW_ENTER_LOWPOWER = 0x7e,
+ MTX_CMDID_SW_NEW_CODEC = 0x7f
+};
+
+struct topaz_cmd_header {
+ union {
+ struct {
+ unsigned long id: 7;
+ unsigned long enable_interrupt: 1;
+ unsigned long core: 8;
+ unsigned long seq: 16;
+ };
+ uint32_t val;
+ };
+};
+
+/* codecs topaz supports,shared with user space driver */
+enum drm_pnw_topaz_codec {
+ IMG_CODEC_JPEG = 0,
+ IMG_CODEC_H264_NO_RC,
+ IMG_CODEC_H264_VBR,
+ IMG_CODEC_H264_CBR,
+ IMG_CODEC_H263_NO_RC,
+ IMG_CODEC_H263_VBR,
+ IMG_CODEC_H263_CBR,
+ IMG_CODEC_MPEG4_NO_RC,
+ IMG_CODEC_MPEG4_VBR,
+ IMG_CODEC_MPEG4_CBR,
+ IMG_CODEC_H264_VCM,
+ IMG_CODEC_NUM
+};
+
+
+typedef enum {
+ MTX_WRITEBACK_CMDWORD = 0, //!< Command word of command executed by MTX
+ MTX_WRITEBACK_VALUE = 1, //!< Writeback value returned by command
+ MTX_WRITEBACK_FLAGSWORD_0 = 2, //!< Flags word indicating MTX status (see MTX writeback flags)
+ MTX_WRITEBACK_BITSWRITTEN = 3, //!< number of bits written out by this core
+
+ MTX_WRITEBACK_DATASIZE //!< End marker for enum
+
+} MTX_eWriteBackData;
+
+/* pnw_topazinit.c */
+int pnw_topaz_reset(struct drm_psb_private *dev_priv);
+int pnw_topaz_init_fw(struct drm_device *dev);
+int pnw_topaz_setup_fw(struct drm_device *dev, enum drm_pnw_topaz_codec codec);
+int pnw_topaz_wait_for_register(struct drm_psb_private *dev_priv,
+ uint32_t addr, uint32_t value,
+ uint32_t enable);
+/*void topaz_write_mtx_mem(struct drm_psb_private *dev_priv,
+ uint32_t byte_addr, uint32_t val);
+uint32_t topaz_read_mtx_mem(struct drm_psb_private *dev_priv,
+ uint32_t byte_addr);
+void topaz_write_mtx_mem_multiple_setup(struct drm_psb_private *dev_priv,
+ uint32_t addr);
+void topaz_write_mtx_mem_multiple(struct drm_psb_private *dev_priv,
+ uint32_t val);*/
+void pnw_topaz_mmu_flushcache(struct drm_psb_private *dev_priv);
+
+uint32_t psb_get_default_pd_addr(struct psb_mmu_driver *driver);
+int pnw_video_get_core_num(struct drm_device *dev, uint64_t user_pointer);
+int pnw_topaz_kick_null_cmd(struct drm_psb_private *dev_priv,
+ uint32_t core_id,
+ uint32_t wb_offset,
+ uint32_t sync_req,
+ uint8_t irq_enable);
+int pnw_wait_on_sync(struct drm_psb_private *dev_priv,
+ uint32_t sync_seq,
+ uint32_t *sync_p);
+
+int pnw_video_frameskip(struct drm_device *dev, uint64_t user_pointer);
+
+static inline char *cmd_to_string(int cmd_id)
+{
+ switch (cmd_id) {
+ case MTX_CMDID_START_PIC:
+ return "MTX_CMDID_START_PIC";
+ case MTX_CMDID_END_PIC:
+ return "MTX_CMDID_END_PIC";
+ case MTX_CMDID_DO_HEADER:
+ return "MTX_CMDID_DO_HEADER";
+ case MTX_CMDID_ENCODE_SLICE:
+ return "MTX_CMDID_ENCODE_SLICE";
+ case MTX_CMDID_SW_NEW_CODEC:
+ return "MTX_CMDID_SW_NEW_CODEC";
+ case MTX_CMDID_SETQUANT:
+ return "MTX_CMDID_SETQUANT";
+ case MTX_CMDID_RESET_ENCODE:
+ return "MTX_CMDID_RESET_ENCODE";
+ case MTX_CMDID_ISSUEBUFF:
+ return "MTX_CMDID_ISSUEBUFF";
+ case MTX_CMDID_SETUP:
+ return "MTX_CMDID_SETUP";
+ case MTX_CMDID_SW_WRITEREG:
+ return "MTX_CMDID_SW_WRITEREG";
+ default:
+ return "Undefined command";
+
+ }
+}
+
+static inline char *codec_to_string(int codec)
+{
+ switch (codec) {
+ case IMG_CODEC_JPEG: /* Just guess, is JPEG firmware included in topaz_bin? */
+ return "JPEG";
+ case IMG_CODEC_H264_NO_RC:
+ return "H264_NO_RC";
+ case IMG_CODEC_H264_VBR:
+ return "H264_VBR";
+ case IMG_CODEC_H264_CBR:
+ return "H264_CBR";
+ case IMG_CODEC_H263_NO_RC:
+ return "H263_NO_RC";
+ case IMG_CODEC_H263_VBR:
+ return "H263_VBR";
+ case IMG_CODEC_H263_CBR:
+ return "H263_CBR";
+ case IMG_CODEC_MPEG4_NO_RC:
+ return "MPEG4_NO_RC";
+ case IMG_CODEC_MPEG4_VBR:
+ return "MPEG4_VBR";
+ case IMG_CODEC_MPEG4_CBR:
+ return "MPEG4_CBR";
+ case IMG_CODEC_H264_VCM:
+ return "H264_VCM";
+ default:
+ return "Undefined codec";
+ }
+}
+
+static inline void pnw_topaz_clearirq(struct drm_device *dev,
+ uint32_t clear_topaz)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+
+ PSB_DEBUG_GENERAL("TOPAZ: clear IRQ\n");
+ if (clear_topaz != 0)
+ TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_INTCLEAR, clear_topaz, 0);
+
+ /* PSB_WVDC32(_PNW_IRQ_TOPAZ_FLAG, PSB_INT_IDENTITY_R); */
+}
+
+static inline uint32_t pnw_topaz_queryirq(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ uint32_t val, /* iir, */ clear = 0;
+ struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+
+ TOPAZ_READ32(TOPAZ_CR_IMG_TOPAZ_INTSTAT, &val, 0);
+ /* iir = PSB_RVDC32(PSB_INT_IDENTITY_R); */
+
+ (void) topaz_priv;
+
+ if ((val == 0) /* && (iir == 0) */) {/* no interrupt */
+ PSB_DEBUG_GENERAL("TOPAZ: no interrupt,IIR=TOPAZ_INTSTAT=0\n");
+ return 0;
+ }
+
+ PSB_DEBUG_IRQ("TOPAZ:TOPAZ_INTSTAT=0x%08x\n", val);
+
+ if (val & (1 << 31))
+ PSB_DEBUG_IRQ("TOPAZ:IRQ pin activated,cmd seq=0x%04x,"
+ "sync seq: 0x%08x vs 0x%08x (MTX)\n",
+ topaz_priv->aui32LastSync[0][0] ,
+ dev_priv->sequence[LNC_ENGINE_ENCODE],
+ *((uint32_t *)topaz_priv->topaz_mtx_wb + MTX_WRITEBACK_VALUE));
+ else
+ PSB_DEBUG_IRQ("TOPAZ:IRQ pin not activated,cmd seq=0x%04x,"
+ "sync seq: 0x%08x vs 0x%08x (MTX)\n",
+ topaz_priv->aui32LastSync[0][0],
+ dev_priv->sequence[LNC_ENGINE_ENCODE],
+ *((uint32_t *)topaz_priv->topaz_mtx_wb + MTX_WRITEBACK_VALUE));
+
+ if (val & 0x8) {
+ uint32_t mmu_status, mmu_req;
+
+ TOPAZ_READ32(TOPAZ_CR_MMU_STATUS, &mmu_status, 0);
+ TOPAZ_READ32(TOPAZ_CR_MMU_MEM_REQ, &mmu_req, 0);
+
+ PSB_DEBUG_IRQ("TOPAZ: detect a page fault interrupt, "
+ "address=0x%08x,mem req=0x%08x\n",
+ mmu_status, mmu_req);
+ clear |= F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_INTCLR_MMU_FAULT);
+ }
+
+ if (val & 0x4) {
+ PSB_DEBUG_IRQ("TOPAZ: detect a MTX_HALT interrupt\n");
+ clear |= F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_INTCLR_MTX_HALT);
+ }
+
+ if (val & 0x2) {
+ PSB_DEBUG_IRQ("TOPAZ: detect a MTX interrupt\n");
+ clear |= F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_INTCLR_MTX);
+ }
+
+ if (val & 0x1) {
+ PSB_DEBUG_IRQ("TOPAZ: detect a MVEA interrupt\n");
+ clear |= F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_INTCLR_MVEA);
+ }
+
+ return clear;
+}
+
+/*Set whether the write operation take effect on all cores
+ * or only the specific one*/
+static inline void topaz_set_mtx_target(struct drm_psb_private *dev_priv,
+ uint32_t core, uint8_t bTargetAll)
+{
+ TOPAZ_MULTICORE_WRITE32(
+ TOPAZSC_CR_MULTICORE_CORE_SEL_0,
+ F_ENCODE((bTargetAll), TOPAZSC_CR_WRITES_CORE_ALL) |
+ F_ENCODE(core, TOPAZSC_CR_DMAC_CORE_SELECT));
+
+}
+
+#endif /* _PNW_TOPAZ_H_ */
--- /dev/null
+/**
+ * file pnw_topazinit.c
+ * TOPAZ initialization and mtx-firmware upload
+ *
+ */
+
+/**************************************************************************
+ *
+ * Copyright (c) 2007 Intel Corporation, Hillsboro, OR, USA
+ * Copyright (c) Imagination Technologies Limited, UK
+ *
+ * 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 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.
+ *
+ **************************************************************************/
+
+/* NOTE: (READ BEFORE REFINE CODE)
+ * 1. The FIRMWARE's SIZE is measured by byte, we have to pass the size
+ * measured by word to DMAC.
+ *
+ *
+ *
+ */
+
+/* include headers */
+
+/* #define DRM_DEBUG_CODE 2 */
+
+#include <linux/firmware.h>
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+
+#include "psb_drv.h"
+#include "pnw_topaz.h"
+#include "psb_powermgmt.h"
+#include "pnw_topaz_hw_reg.h"
+
+/* WARNING: this define is very important */
+#define RAM_SIZE (1024 * 24)
+
+#define MEMORY_ONLY 0
+#define MEM_AND_CACHE 1
+#define CACHE_ONLY 2
+
+#define FIRMWARE_NAME "topazsc_fw.bin"
+#define TOPAZ_KICK_RETRY_MAX 5
+
+/* static function define */
+static int topaz_upload_fw(struct drm_device *dev,
+ enum drm_pnw_topaz_codec codec,
+ uint32_t core_id);
+
+#define UPLOAD_FW_BY_DMA 1
+
+#if UPLOAD_FW_BY_DMA
+static int topaz_dma_transfer(struct drm_psb_private *dev_priv,
+ uint32_t channel, uint32_t src_phy_addr,
+ uint32_t offset, uint32_t dst_addr,
+ uint32_t byte_num, uint32_t is_increment,
+ uint32_t is_write);
+#else
+static void topaz_mtx_upload_by_register(struct drm_device *dev,
+ uint32_t mtx_mem, uint32_t addr,
+ uint32_t size,
+ struct ttm_buffer_object *buf,
+ uint32_t core);
+#endif
+
+static void get_mtx_control_from_dash(struct drm_psb_private *dev_priv,
+ uint32_t core);
+static void release_mtx_control_from_dash(struct drm_psb_private *dev_priv,
+ uint32_t core);
+static void pnw_topaz_mmu_hwsetup(struct drm_psb_private *dev_priv,
+ uint32_t core_id);
+static int mtx_dma_read(struct drm_device *dev, uint32_t core,
+ uint32_t source_addr, uint32_t size);
+static int mtx_dma_write(struct drm_device *dev,
+ uint32_t core);
+
+/* Reset the encode system buffer registers.*/
+static int pnw_topazsc_reset_ESB(struct drm_psb_private *dev_priv, int core_id)
+{
+ int x_pos, y_pos, i;
+
+ MVEA_WRITE32(MVEA_CR_CMC_ESB_LOGICAL_REGION_SETUP(ESB_HWSYNC),
+ MVEASETUPESBREGION(0, 0,
+ TOPAZSC_ESB_REGION_HEIGH,
+ TOPAZSC_ESB_REGION_WIDTH,
+ TOPAZSC_ESB_REGION_HEIGH,
+ REGION_TYPE_LINEAR),
+ core_id);
+ MVEA_WRITE32(MVEA_CR_CMC_PROC_ESB_ACCESS, ESB_HWSYNC, core_id);
+
+ i = 0;
+ for (y_pos = 0; y_pos < TOPAZSC_ESB_REGION_Y_MAX; y_pos++) {
+ for (x_pos = 0; x_pos < TOPAZSC_ESB_REGION_X_MAX;
+ x_pos += 4, i += 4) {
+ MVEA_ESB_WRITE32(i, 0, core_id);
+ }
+ }
+
+ MVEA_WRITE32(MVEA_CR_CMC_ESB_LOGICAL_REGION_SETUP(ESB_HWSYNC),
+ MVEASETUPESBREGION(0, TOPAZSC_ESB_REGION_WIDTH,
+ TOPAZSC_ESB_REGION_HEIGH,
+ TOPAZSC_ESB_REGION_WIDTH,
+ TOPAZSC_ESB_REGION_HEIGH,
+ REGION_TYPE_LINEAR),
+ core_id);
+
+ i = 0;
+ for (y_pos = 0; y_pos < TOPAZSC_ESB_REGION_Y_MAX; y_pos++) {
+ for (x_pos = 0; x_pos < TOPAZSC_ESB_REGION_X_MAX;
+ x_pos += 4, i += 4) {
+ MVEA_ESB_WRITE32(i, 0, core_id);
+ }
+ }
+
+ MVEA_WRITE32(MVEA_CR_CMC_PROC_ESB_ACCESS, 0, core_id);
+ return 0;
+}
+
+static int pnw_error_dump_reg(struct drm_psb_private *dev_priv, int core_id)
+{
+ uint32_t reg_val;
+ int i;
+ DRM_ERROR("DMA Register value dump:\n");
+ for (i = 0; i < 8; i++) {
+ DMAC_READ32(i * 4, ®_val);
+ DRM_ERROR("DMAC REG%d: 0x%08x\n", i, reg_val);
+ }
+ TOPAZ_MULTICORE_READ32(
+ TOPAZSC_CR_MULTICORE_CORE_SEL_0, ®_val);
+ DRM_ERROR("TOPAZSC_CR_MULTICORE_CORE_SEL_0 0x%08x\n", reg_val);
+ MTX_READ32(MTX_CR_MTX_SYSC_CDMAA, ®_val, core_id);
+ DRM_ERROR("MTX_CR_MTX_SYSC_CDMAA 0x%08x\n", reg_val);
+ MTX_READ32(MTX_CR_MTX_SYSC_CDMAC, ®_val, core_id);
+ DRM_ERROR("MTX_CR_MTX_SYSC_CDMAC 0x%08x\n", reg_val);
+
+ MTX_READ32(MTX_CR_MTX_SYSC_CDMAS0 , ®_val, core_id);
+ DRM_ERROR("MTX_CR_MTX_SYSC_CDMAS0 0x%08x\n", reg_val);
+ MTX_READ32(MTX_CR_MTX_SYSC_CDMAS1, ®_val, core_id);
+ DRM_ERROR("MTX_CR_MTX_SYSC_CDMAS1 0x%08x\n", reg_val);
+ MTX_READ32(MTX_CR_MTX_SYSC_CDMAT, ®_val, core_id);
+ DRM_ERROR("MTX_CR_MTX_SYSC_CDMAT 0x%08x\n", reg_val);
+ for (i = 0; i < 6; i++) {
+ TOPAZ_READ32(0x1c + i * 4, ®_val, core_id);
+ DRM_ERROR("MMU REG %d value 0x%08x\n", i, reg_val);
+ }
+
+ topaz_read_core_reg(dev_priv, core_id, TOPAZ_MTX_PC, ®_val);
+ DRM_ERROR("PC pointer: 0x%08x\n", reg_val);
+
+ TOPAZ_MULTICORE_READ32(TOPAZSC_CR_MULTICORE_CMD_FIFO_1,
+ ®_val);
+ reg_val &= MASK_TOPAZSC_CR_CMD_FIFO_SPACE;
+ DRM_ERROR("TOPAZSC: Free words in command FIFO %d\n", reg_val);
+
+ return 0;
+}
+
+int pnw_topaz_wait_for_register(struct drm_psb_private *dev_priv,
+ uint32_t addr, uint32_t value, uint32_t mask)
+{
+ uint32_t tmp;
+ uint32_t count = 1000000;
+
+ /* # poll topaz register for certain times */
+ while (count) {
+ /* #.# read */
+ MM_READ32(addr, 0, &tmp);
+
+ if (value == (tmp & mask))
+ return 0;
+
+ /* #.# delay and loop */
+ PSB_UDELAY(1);
+ --count;
+ }
+
+ /* # now waiting is timeout, return 1 indicat failed */
+ /* XXX: testsuit means a timeout 10000 */
+
+ DRM_ERROR("TOPAZ:time out to poll addr(0x%x) expected value(0x%08x), "
+ "actual 0x%08x (0x%08x & 0x%08x)\n",
+ addr, value, tmp & mask, tmp, mask);
+
+ return -EBUSY;
+
+}
+
+static ssize_t psb_topaz_pmstate_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct drm_device *drm_dev = dev_get_drvdata(dev);
+ struct drm_psb_private *dev_priv;
+ struct pnw_topaz_private *topaz_priv;
+ unsigned int pmstate;
+ unsigned long flags;
+ int ret = -EINVAL;
+
+ if (drm_dev == NULL)
+ return 0;
+
+ dev_priv = drm_dev->dev_private;
+ topaz_priv = dev_priv->topaz_private;
+ pmstate = topaz_priv->pmstate;
+
+ pmstate = topaz_priv->pmstate;
+ spin_lock_irqsave(&topaz_priv->topaz_lock, flags);
+ ret = snprintf(buf, 64, "%s\n",
+ (pmstate == PSB_PMSTATE_POWERUP) ?
+ "powerup" : "powerdown");
+ spin_unlock_irqrestore(&topaz_priv->topaz_lock, flags);
+
+ return ret;
+}
+
+static DEVICE_ATTR(topaz_pmstate, 0444, psb_topaz_pmstate_show, NULL);
+
+
+/* this function finish the first part of initialization, the rest
+ * should be done in pnw_topaz_setup_fw
+ */
+int pnw_topaz_init(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct ttm_bo_device *bdev = &dev_priv->bdev;
+ uint32_t core_id, core_rev;
+ int ret = 0, n;
+ bool is_iomem;
+ struct pnw_topaz_private *topaz_priv;
+ void *topaz_bo_virt;
+
+ PSB_DEBUG_GENERAL("TOPAZ: init topazsc data structures\n");
+ topaz_priv = kmalloc(sizeof(struct pnw_topaz_private), GFP_KERNEL);
+ if (topaz_priv == NULL)
+ return -1;
+
+ dev_priv->topaz_private = topaz_priv;
+ memset(topaz_priv, 0, sizeof(struct pnw_topaz_private));
+
+ /* get device --> drm_device --> drm_psb_private --> topaz_priv
+ * for psb_topaz_pmstate_show: topaz_pmpolicy
+ * if not pci_set_drvdata, can't get drm_device from device
+ */
+ pci_set_drvdata(dev->pdev, dev);
+ if (device_create_file(&dev->pdev->dev,
+ &dev_attr_topaz_pmstate))
+ DRM_ERROR("TOPAZ: could not create sysfs file\n");
+ topaz_priv->sysfs_pmstate = sysfs_get_dirent(dev->pdev->dev.kobj.sd,
+ NULL, "topaz_pmstate");
+
+ topaz_priv = dev_priv->topaz_private;
+
+ /* # initialize comand topaz queueing [msvdx_queue] */
+ INIT_LIST_HEAD(&topaz_priv->topaz_queue);
+ /* # init mutex? CHECK: mutex usage [msvdx_mutex] */
+ mutex_init(&topaz_priv->topaz_mutex);
+ /* # spin lock init? CHECK spin lock usage [msvdx_lock] */
+ spin_lock_init(&topaz_priv->topaz_lock);
+
+ /* # topaz status init. [msvdx_busy] */
+ topaz_priv->topaz_busy = 0;
+ /*Initial topaz_cmd_count should be larger than initial
+ *writeback value*/
+ topaz_priv->topaz_cmd_count = 1;
+ topaz_priv->topaz_fw_loaded = 0;
+ /* FIXME: workaround since JPEG firmware is not ready */
+ topaz_priv->topaz_cur_codec = 0;
+ topaz_priv->topaz_hw_busy = 1;
+ /* # gain write back structure,we may only need 32+4=40DW */
+ ret = ttm_buffer_object_create(bdev, 4096,
+ ttm_bo_type_kernel,
+ DRM_PSB_FLAG_MEM_MMU | TTM_PL_FLAG_NO_EVICT,
+ 0, 0, 0, NULL, &(topaz_priv->topaz_bo));
+ if (ret != 0) {
+ DRM_ERROR("TOPAZ: failed to allocate topaz BO.\n");
+ return -1;
+ }
+
+ ret = ttm_bo_kmap(topaz_priv->topaz_bo, 0,
+ topaz_priv->topaz_bo->num_pages,
+ &topaz_priv->topaz_bo_kmap);
+ if (ret) {
+ DRM_ERROR("TOPAZ: map topaz BO bo failed......\n");
+ ttm_bo_unref(&topaz_priv->topaz_bo);
+ return -1;
+ }
+
+ TOPAZ_READ32(TOPAZ_CR_TOPAZ_HW_CFG, &topaz_priv->topaz_num_cores, 0);
+
+ topaz_priv->topaz_num_cores = F_EXTRACT(topaz_priv->topaz_num_cores,
+ TOPAZ_CR_NUM_CORES_SUPPORTED);
+ PSB_DEBUG_GENERAL("TOPAZ: number of cores: %d\n",
+ topaz_priv->topaz_num_cores);
+
+ if (topaz_priv->topaz_num_cores > TOPAZSC_NUM_CORES) {
+ topaz_priv->topaz_num_cores = TOPAZSC_NUM_CORES;
+ DRM_ERROR("TOPAZ: number of cores (%d) exceed "
+ "TOPAZSC_NUM_CORES (%d)!\n",
+ topaz_priv->topaz_num_cores, TOPAZSC_NUM_CORES);
+ }
+
+ for (n = 0; n < MAX_TOPAZ_CORES; n++) {
+ topaz_priv->topaz_mtx_data_mem[n] = NULL;
+ topaz_priv->topaz_mtx_reg_state[n] = NULL;
+ topaz_priv->cur_mtx_data_size[n] = 0;
+ topaz_priv->topaz_fw[n].text = NULL;
+ topaz_priv->topaz_fw[n].data = NULL;
+ }
+
+ for (n = 0; n < topaz_priv->topaz_num_cores; n++) {
+ TOPAZ_READ32(TOPAZ_CR_IMG_TOPAZ_CORE_ID, &core_id, n);
+ TOPAZ_READ32(TOPAZ_CR_IMG_TOPAZ_CORE_REV, &core_rev, n);
+
+ PSB_DEBUG_GENERAL("TOPAZ: core(%d), core_id(%x) core_rev(%x)\n",
+ n, core_id, core_rev);
+
+ topaz_priv->topaz_mtx_reg_state[n] = kmalloc(TOPAZ_MTX_REG_SIZE,
+ GFP_KERNEL);
+ if (topaz_priv->topaz_mtx_reg_state[n] == NULL) {
+ DRM_ERROR("TOPAZ: failed to allocate space "
+ "for mtx register\n");
+ goto out;
+ }
+
+ ret = ttm_buffer_object_create(bdev,
+ 12 * 4096,
+ ttm_bo_type_kernel,
+ DRM_PSB_FLAG_MEM_MMU |
+ TTM_PL_FLAG_NO_EVICT,
+ 0, 0, 0, NULL,
+ &topaz_priv->topaz_mtx_data_mem[n]);
+ if (ret) {
+ DRM_ERROR("TOPAZ: failed to allocate ttm buffer for "
+ "mtx data save of core (%d)\n", n);
+ goto out;
+ }
+
+ }
+
+ topaz_bo_virt = ttm_kmap_obj_virtual(&topaz_priv->topaz_bo_kmap,
+ &is_iomem);
+ topaz_priv->topaz_mtx_wb = (uint32_t *) topaz_bo_virt;
+ topaz_priv->topaz_wb_offset = topaz_priv->topaz_bo->offset;
+ topaz_priv->topaz_sync_addr = (uint32_t *)(topaz_bo_virt
+ + 2048);
+ topaz_priv->topaz_sync_offset = topaz_priv->topaz_wb_offset
+ + 2048;
+
+ PSB_DEBUG_GENERAL("TOPAZ: alloc BO for WriteBack\n");
+ PSB_DEBUG_GENERAL("TOPAZ: WB offset=0x%08x\n",
+ topaz_priv->topaz_wb_offset);
+ PSB_DEBUG_GENERAL("TOPAZ: SYNC offset=0x%08x\n",
+ topaz_priv->topaz_sync_offset);
+
+ /*topaz_cmd_count starts with 1. Reset writback value with 0*/
+ memset((void *)(topaz_priv->topaz_mtx_wb), 0,
+ topaz_priv->topaz_num_cores
+ * MTX_WRITEBACK_DATASIZE_ROUND);
+ memset((void *)topaz_priv->topaz_sync_addr, 0,
+ MTX_WRITEBACK_DATASIZE_ROUND);
+
+ /*fence sequence number starts with 0. Reset sync seq with ~1*/
+ *(topaz_priv->topaz_sync_addr) = ~0;
+
+ pnw_topaz_mmu_flushcache(dev_priv);
+
+ /* # set up MMU */
+ for (n = 0; n < topaz_priv->topaz_num_cores; n++)
+ pnw_topaz_mmu_hwsetup(dev_priv, n);
+
+
+ for (n = 0; n < topaz_priv->topaz_num_cores; n++) {
+ /* # reset topaz */
+ MVEA_WRITE32(MVEA_CR_IMG_MVEA_SRST,
+ F_ENCODE(1, MVEA_CR_IMG_MVEA_SPE_SOFT_RESET) |
+ F_ENCODE(1, MVEA_CR_IMG_MVEA_IPE_SOFT_RESET) |
+ F_ENCODE(1, MVEA_CR_IMG_MVEA_CMPRS_SOFT_RESET) |
+ F_ENCODE(1, MVEA_CR_IMG_MVEA_JMCOMP_SOFT_RESET)
+ |
+ F_ENCODE(1, MVEA_CR_IMG_MVEA_CMC_SOFT_RESET) |
+ F_ENCODE(1, MVEA_CR_IMG_MVEA_DCF_SOFT_RESET),
+ n);
+
+ MVEA_WRITE32(MVEA_CR_IMG_MVEA_SRST,
+ F_ENCODE(0, MVEA_CR_IMG_MVEA_SPE_SOFT_RESET) |
+ F_ENCODE(0, MVEA_CR_IMG_MVEA_IPE_SOFT_RESET) |
+ F_ENCODE(0, MVEA_CR_IMG_MVEA_CMPRS_SOFT_RESET) |
+ F_ENCODE(0, MVEA_CR_IMG_MVEA_JMCOMP_SOFT_RESET)
+ |
+ F_ENCODE(0, MVEA_CR_IMG_MVEA_CMC_SOFT_RESET) |
+ F_ENCODE(0, MVEA_CR_IMG_MVEA_DCF_SOFT_RESET),
+ n);
+ }
+
+ PSB_DEBUG_GENERAL("TOPAZ: Reset MVEA successfully.\n");
+
+ for (n = 0; n < MAX_TOPAZ_CORES + 1; n++) {
+ topaz_priv->aui32LastSync[0][n] = ~0;
+ topaz_priv->aui32LastSync[1][n] = ~0;
+ }
+
+ /* create firmware storage */
+ for (n = 0; n < IMG_CODEC_NUM * 2; ++n) {
+ /* #.# malloc DRM object for fw storage */
+ ret = ttm_buffer_object_create(bdev, 12 * 4096,
+ ttm_bo_type_kernel,
+ DRM_PSB_FLAG_MEM_MMU | TTM_PL_FLAG_NO_EVICT,
+ 0, 0, 0, NULL, &topaz_priv->topaz_fw[n].text);
+ if (ret) {
+ DRM_ERROR("Failed to allocate firmware.\n");
+ goto out;
+ }
+
+ /* #.# malloc DRM object for fw storage */
+ ret = ttm_buffer_object_create(bdev, 12 * 4096,
+ ttm_bo_type_kernel,
+ DRM_PSB_FLAG_MEM_MMU | TTM_PL_FLAG_NO_EVICT,
+ 0, 0, 0, NULL, &topaz_priv->topaz_fw[n].data);
+ if (ret) {
+ DRM_ERROR("Failed to allocate firmware.\n");
+ goto out;
+ }
+ }
+
+ PSB_DEBUG_INIT("TOPAZ:old clock gating disable = 0x%08x\n",
+ PSB_RVDC32(PSB_TOPAZ_CLOCKGATING));
+
+ PSB_DEBUG_INIT("TOPAZ:reset to disable clock gating\n");
+
+ PSB_WVDC32(0x007fffff, PSB_TOPAZ_CLOCKGATING);
+
+ PSB_DEBUG_GENERAL("TOPAZ: Exit initialization\n");
+ return 0;
+
+out:
+ for (n = 0; n < IMG_CODEC_NUM * 2; ++n) {
+ if (topaz_priv->topaz_fw[n].text != NULL)
+ ttm_bo_unref(&topaz_priv->topaz_fw[n].text);
+ if (topaz_priv->topaz_fw[n].data != NULL)
+ ttm_bo_unref(&topaz_priv->topaz_fw[n].data);
+ }
+
+ for (n = 0; n < MAX_TOPAZ_CORES; n++) {
+ if (topaz_priv->topaz_mtx_data_mem[n] != NULL)
+ ttm_bo_unref(&topaz_priv->topaz_mtx_data_mem[n]);
+ if (topaz_priv->topaz_mtx_reg_state[n] != NULL)
+ kfree(topaz_priv->topaz_mtx_reg_state[n]);
+ }
+
+ return ret;
+}
+
+int pnw_topaz_uninit(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+ int n;
+
+ /* flush MMU */
+ PSB_DEBUG_GENERAL("XXX: need to flush mmu cache here??\n");
+ /* pnw_topaz_mmu_flushcache (dev_priv); */
+
+ if (NULL == topaz_priv) {
+ DRM_ERROR("TOPAZ: topaz_priv is NULL!\n");
+ return -1;
+ }
+
+ /* # reset TOPAZ chip */
+ pnw_topaz_reset(dev_priv);
+
+ /* release resources */
+ /* # release write back memory */
+ topaz_priv->topaz_mtx_wb = NULL;
+
+ for (n = 0; n < topaz_priv->topaz_num_cores; n++) {
+ /* release mtx register save space */
+ kfree(topaz_priv->topaz_mtx_reg_state[n]);
+
+ /* release mtx data memory save space */
+ if (topaz_priv->topaz_mtx_data_mem[n])
+ ttm_bo_unref(&topaz_priv->topaz_mtx_data_mem[n]);
+ }
+ /* # release firmware storage */
+ for (n = 0; n < IMG_CODEC_NUM * 2; ++n) {
+ if (topaz_priv->topaz_fw[n].text != NULL)
+ ttm_bo_unref(&topaz_priv->topaz_fw[n].text);
+ if (topaz_priv->topaz_fw[n].data != NULL)
+ ttm_bo_unref(&topaz_priv->topaz_fw[n].data);
+ }
+
+ ttm_bo_kunmap(&topaz_priv->topaz_bo_kmap);
+ ttm_bo_unref(&topaz_priv->topaz_bo);
+
+ if (topaz_priv) {
+ pci_set_drvdata(dev->pdev, NULL);
+ device_remove_file(&dev->pdev->dev, &dev_attr_topaz_pmstate);
+ sysfs_put(topaz_priv->sysfs_pmstate);
+ topaz_priv->sysfs_pmstate = NULL;
+
+ kfree(topaz_priv);
+ dev_priv->topaz_private = NULL;
+ }
+
+ return 0;
+}
+
+int pnw_topaz_reset(struct drm_psb_private *dev_priv)
+{
+ struct pnw_topaz_private *topaz_priv;
+ uint32_t i;
+
+ topaz_priv = dev_priv->topaz_private;
+ topaz_priv->topaz_busy = 0;
+ topaz_priv->topaz_cmd_count = 0;
+ for (i = 0; i < MAX_TOPAZ_CORES; i++)
+ topaz_priv->cur_mtx_data_size[i] = 0;
+ topaz_priv->topaz_needs_reset = 0;
+
+ memset((void *)(topaz_priv->topaz_mtx_wb), 0,
+ MAX_TOPAZ_CORES * MTX_WRITEBACK_DATASIZE_ROUND);
+
+ for (i = 0; i < topaz_priv->topaz_num_cores; i++) {
+ /* # reset topaz */
+ MVEA_WRITE32(MVEA_CR_IMG_MVEA_SRST,
+ F_ENCODE(1, MVEA_CR_IMG_MVEA_SPE_SOFT_RESET) |
+ F_ENCODE(1, MVEA_CR_IMG_MVEA_IPE_SOFT_RESET) |
+ F_ENCODE(1, MVEA_CR_IMG_MVEA_CMPRS_SOFT_RESET) |
+ F_ENCODE(1, MVEA_CR_IMG_MVEA_JMCOMP_SOFT_RESET)
+ |
+ F_ENCODE(1, MVEA_CR_IMG_MVEA_CMC_SOFT_RESET) |
+ F_ENCODE(1, MVEA_CR_IMG_MVEA_DCF_SOFT_RESET),
+ i);
+
+ MVEA_WRITE32(MVEA_CR_IMG_MVEA_SRST,
+ F_ENCODE(0, MVEA_CR_IMG_MVEA_SPE_SOFT_RESET) |
+ F_ENCODE(0, MVEA_CR_IMG_MVEA_IPE_SOFT_RESET) |
+ F_ENCODE(0, MVEA_CR_IMG_MVEA_CMPRS_SOFT_RESET) |
+ F_ENCODE(0, MVEA_CR_IMG_MVEA_JMCOMP_SOFT_RESET)
+ |
+ F_ENCODE(0, MVEA_CR_IMG_MVEA_CMC_SOFT_RESET) |
+ F_ENCODE(0, MVEA_CR_IMG_MVEA_DCF_SOFT_RESET),
+ i);
+ }
+
+ /* # set up MMU */
+ for (i = 0; i < topaz_priv->topaz_num_cores; i++)
+ pnw_topaz_mmu_hwsetup(dev_priv, i);
+
+ return 0;
+}
+
+
+/* read firmware bin file and load all data into driver */
+int pnw_topaz_init_fw(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ const struct firmware *raw = NULL;
+ unsigned char *ptr;
+ int ret = 0;
+ int n;
+ struct topazsc_fwinfo *cur_fw;
+ int cur_size, total_size;
+ struct pnw_topaz_codec_fw *cur_codec;
+ struct ttm_buffer_object **cur_drm_obj;
+ struct ttm_bo_kmap_obj tmp_kmap;
+ bool is_iomem;
+ struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+
+ topaz_priv->stored_initial_qp = 0;
+
+ /* # get firmware */
+ ret = request_firmware(&raw, FIRMWARE_NAME, &dev->pdev->dev);
+ if (ret != 0) {
+ DRM_ERROR("TOPAZ: request_firmware failed: %d\n", ret);
+ return ret;
+ }
+
+ if ((NULL == raw) || (raw->size < sizeof(struct topazsc_fwinfo))) {
+ DRM_ERROR("TOPAZ: firmware file is not correct size.\n");
+ goto out;
+ }
+
+ total_size = raw->size;
+ PSB_DEBUG_GENERAL("TOPAZ: opened firmware, size %d\n", raw->size);
+
+ ptr = (unsigned char *) raw->data;
+
+ if (!ptr) {
+ DRM_ERROR("TOPAZ: failed to load firmware.\n");
+ goto out;
+ }
+
+ /* # load fw from file */
+ PSB_DEBUG_GENERAL("TOPAZ: load firmware.....\n");
+ cur_fw = NULL;
+ for (n = 0; n < IMG_CODEC_NUM * 2; ++n) {
+ if (total_size < sizeof(struct topazsc_fwinfo)) {
+ PSB_DEBUG_GENERAL("TOPAZ: WARNING: Rearch end of "
+ "firmware. Have loaded %d firmwares.",
+ n);
+ break;
+ }
+
+ total_size -= sizeof(struct topazsc_fwinfo);
+ cur_fw = (struct topazsc_fwinfo *) ptr;
+
+ cur_codec = &topaz_priv->topaz_fw[cur_fw->codec];
+ cur_codec->ver = cur_fw->ver;
+ cur_codec->codec = cur_fw->codec;
+ cur_codec->text_size = cur_fw->text_size;
+ cur_codec->data_size = cur_fw->data_size;
+ cur_codec->data_location = cur_fw->data_location;
+
+ total_size -= cur_fw->text_size;
+ total_size -= cur_fw->data_size;
+
+ if (total_size < 0) {
+ PSB_DEBUG_GENERAL("TOPAZ: WARNING: wrong size number "
+ "of data or text. Have loaded"
+ " %d firmwares.", n);
+ break;
+ }
+
+ PSB_DEBUG_GENERAL("TOPAZ: load firemware %s.\n",
+ codec_to_string(cur_fw->codec / 2));
+
+ /* #.# handle text section */
+ ptr += sizeof(struct topazsc_fwinfo);
+ cur_drm_obj = &cur_codec->text;
+ cur_size = cur_fw->text_size;
+
+ /* #.# fill DRM object with firmware data */
+ ret = ttm_bo_kmap(*cur_drm_obj, 0, (*cur_drm_obj)->num_pages,
+ &tmp_kmap);
+ if (ret) {
+ PSB_DEBUG_GENERAL("drm_bo_kmap failed: %d\n", ret);
+ ttm_bo_unref(cur_drm_obj);
+ *cur_drm_obj = NULL;
+ goto out;
+ }
+
+ PSB_DEBUG_GENERAL(" load codec %d, text_size: %d, "
+ "data_size %d, data_location 08%x\n",
+ cur_codec->codec / 2, cur_codec->text_size,
+ cur_codec->data_size, cur_codec->data_location);
+ memcpy(ttm_kmap_obj_virtual(&tmp_kmap, &is_iomem), ptr,
+ cur_size);
+
+ ttm_bo_kunmap(&tmp_kmap);
+
+ /* #.# handle data section */
+ ptr += cur_fw->text_size;
+ cur_drm_obj = &cur_codec->data;
+ cur_size = cur_fw->data_size;
+
+ /* #.# fill DRM object with firmware data */
+ ret = ttm_bo_kmap(*cur_drm_obj, 0, (*cur_drm_obj)->num_pages,
+ &tmp_kmap);
+ if (ret) {
+ PSB_DEBUG_GENERAL("drm_bo_kmap failed: %d\n", ret);
+ ttm_bo_unref(cur_drm_obj);
+ *cur_drm_obj = NULL;
+ goto out;
+ }
+
+ memcpy(ttm_kmap_obj_virtual(&tmp_kmap, &is_iomem), ptr,
+ cur_size);
+
+ ttm_bo_kunmap(&tmp_kmap);
+
+ /* #.# update ptr */
+ ptr += cur_fw->data_size;
+ }
+
+ release_firmware(raw);
+ PSB_DEBUG_GENERAL("TOPAZ: return from firmware init\n");
+
+ return 0;
+
+out:
+ if (raw) {
+ PSB_DEBUG_GENERAL("release firmware....\n");
+ release_firmware(raw);
+ }
+
+ return -1;
+}
+
+/* setup fw when start a new context */
+int pnw_topaz_setup_fw(struct drm_device *dev, enum drm_pnw_topaz_codec codec)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ uint32_t verify_pc;
+ int core_id;
+ struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+ int i, ret = 0;
+
+ /*Reset TopazSC*/
+ PSB_DEBUG_GENERAL("TOPAZ: should reset topaz when context change\n");
+
+ if (topaz_priv->topaz_num_cores > MAX_TOPAZ_CORES) {
+ DRM_ERROR("TOPAZ: Invalid core nubmer %d\n",
+ topaz_priv->topaz_num_cores);
+ return -1;
+ }
+
+ PSB_DEBUG_GENERAL("TOPAZ: Set up mmu for all %d cores\n",
+ topaz_priv->topaz_num_cores);
+
+ for (core_id = 0; core_id < topaz_priv->topaz_num_cores; core_id++)
+ pnw_topaz_mmu_hwsetup(dev_priv, core_id);
+
+ /* # reset MVEA */
+ for (core_id = 0; core_id < topaz_priv->topaz_num_cores; core_id++) {
+ pnw_topazsc_reset_ESB(dev_priv, core_id);
+
+ MVEA_WRITE32(MVEA_CR_IMG_MVEA_SRST,
+ F_ENCODE(1, MVEA_CR_IMG_MVEA_SPE_SOFT_RESET) |
+ F_ENCODE(1, MVEA_CR_IMG_MVEA_IPE_SOFT_RESET) |
+ F_ENCODE(1, MVEA_CR_IMG_MVEA_CMPRS_SOFT_RESET) |
+ F_ENCODE(1, MVEA_CR_IMG_MVEA_JMCOMP_SOFT_RESET)
+ |
+ F_ENCODE(1, MVEA_CR_IMG_MVEA_CMC_SOFT_RESET) |
+ F_ENCODE(1, MVEA_CR_IMG_MVEA_DCF_SOFT_RESET),
+ core_id);
+
+ MVEA_WRITE32(MVEA_CR_IMG_MVEA_SRST,
+ F_ENCODE(0, MVEA_CR_IMG_MVEA_SPE_SOFT_RESET) |
+ F_ENCODE(0, MVEA_CR_IMG_MVEA_IPE_SOFT_RESET) |
+ F_ENCODE(0, MVEA_CR_IMG_MVEA_CMPRS_SOFT_RESET) |
+ F_ENCODE(0, MVEA_CR_IMG_MVEA_JMCOMP_SOFT_RESET)
+ |
+ F_ENCODE(0, MVEA_CR_IMG_MVEA_CMC_SOFT_RESET) |
+ F_ENCODE(0, MVEA_CR_IMG_MVEA_DCF_SOFT_RESET),
+ core_id);
+ }
+
+ psb_irq_uninstall_islands(dev, OSPM_VIDEO_ENC_ISLAND);
+
+ PSB_DEBUG_GENERAL("TOPAZ: will setup firmware ....\n");
+
+ /*start each MTX in turn MUST start with master to
+ * enable comms to other cores*/
+ for (core_id = topaz_priv->topaz_num_cores - 1;
+ core_id >= 0; core_id--) {
+ topaz_set_mtx_target(dev_priv, core_id, 0);
+ /* # reset mtx */
+ TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_SRST,
+ F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_MVEA_SOFT_RESET)
+ |
+ F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_MTX_SOFT_RESET) |
+ F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_VLC_SOFT_RESET),
+ core_id);
+
+ TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_SRST, 0x0, core_id);
+
+ /* # upload fw by drm */
+ PSB_DEBUG_GENERAL("TOPAZ: will upload firmware to %d cores\n",
+ topaz_priv->topaz_num_cores);
+
+ topaz_upload_fw(dev, codec, core_id);
+
+ PSB_DEBUG_GENERAL("TOPAZ: after upload fw ....\n");
+
+ /* D0.5, D0.6 and D0.7 */
+ for (i = 5; i < 8; i++) {
+ topaz_write_core_reg(dev_priv, core_id, 0x1 | (i << 4),
+ 0);
+ }
+ /* Saves 8 Registers of D1 Bank */
+ /* D1.5, D1.6 and D1.7 */
+ for (i = 5; i < 8; i++) {
+ topaz_write_core_reg(dev_priv, core_id, 0x2 | (i << 4),
+ 0);
+ }
+
+ PSB_DEBUG_GENERAL("TOPAZ: setting up pc address: 0x%08x"
+ "for core (%d)\n",
+ PC_START_ADDRESS, core_id);
+ topaz_write_core_reg(dev_priv, core_id,
+ TOPAZ_MTX_PC, PC_START_ADDRESS);
+
+ topaz_read_core_reg(dev_priv, core_id,
+ TOPAZ_MTX_PC, &verify_pc);
+
+ PSB_DEBUG_GENERAL("TOPAZ: verify pc address for core"
+ " (%d):0x%08x\n",
+ core_id, verify_pc);
+
+ /* enable auto clock is essential for this driver */
+ TOPAZ_WRITE32(TOPAZ_CR_TOPAZ_AUTO_CLK_GATE,
+ F_ENCODE(1, TOPAZ_CR_TOPAZ_VLC_AUTO_CLK_GATE) |
+ F_ENCODE(1, TOPAZ_CR_TOPAZ_DB_AUTO_CLK_GATE),
+ core_id);
+ MVEA_WRITE32(MVEA_CR_MVEA_AUTO_CLOCK_GATING,
+ F_ENCODE(1, MVEA_CR_MVEA_IPE_AUTO_CLK_GATE) |
+ F_ENCODE(1, MVEA_CR_MVEA_SPE_AUTO_CLK_GATE) |
+ F_ENCODE(1, MVEA_CR_MVEA_CMPRS_AUTO_CLK_GATE) |
+ F_ENCODE(1, MVEA_CR_MVEA_JMCOMP_AUTO_CLK_GATE),
+ core_id);
+
+ /* flush the command FIFO - only has effect on master MTX */
+ if (core_id == 0)
+ TOPAZ_WRITE32(TOPAZ_CR_TOPAZ_CMD_FIFO_2,
+ F_ENCODE(1, TOPAZ_CR_CMD_FIFO_FLUSH),
+ 0);
+
+ /* clear MTX interrupt */
+ TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_INTCLEAR,
+ F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_INTCLR_MTX),
+ core_id);
+
+ /* put the number of cores in use in the scratch register
+ * so is is ready when the firmware wakes up. */
+ TOPAZ_WRITE32(0x100 + (2 << 2), 2, core_id);
+
+ /* # turn on MTX */
+ topaz_set_mtx_target(dev_priv, core_id, 0);
+ MTX_WRITE32(MTX_CORE_CR_MTX_ENABLE_OFFSET,
+ MTX_CORE_CR_MTX_ENABLE_MTX_ENABLE_MASK,
+ core_id);
+
+ topaz_set_mtx_target(dev_priv, core_id, 0);
+ MTX_WRITE32(MTX_CR_MTX_KICK, 1, core_id);
+ }
+
+ topaz_priv->topaz_cmd_count = 1;
+ /* # poll on the interrupt which the firmware will generate */
+ /*With DDKv186, interrupt would't be generated automatically after
+ * firmware set up*/
+ PSB_DEBUG_GENERAL("TOPAZ: send NULL command to test firmware\n");
+ for (core_id = 0; core_id < topaz_priv->topaz_num_cores; core_id++) {
+ pnw_topaz_kick_null_cmd(dev_priv, core_id,
+ topaz_priv->topaz_sync_offset,
+ topaz_priv->topaz_cmd_count++, 0);
+
+ ret = pnw_wait_on_sync(dev_priv,
+ topaz_priv->topaz_cmd_count - 1,
+ topaz_priv->topaz_sync_addr
+ + MTX_WRITEBACK_VALUE);
+ if (0 != ret) {
+ DRM_ERROR("TOPAZ: Failed to upload firmware for codec"
+ " %d!\n",
+ codec);
+ pnw_error_dump_reg(dev_priv, core_id);
+ return -1;
+ }
+
+ *(topaz_priv->topaz_sync_addr + MTX_WRITEBACK_VALUE)
+ = 0xa5a5a5a5;
+ TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_INTCLEAR,
+ F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_INTCLR_MTX),
+ core_id);
+ }
+
+
+ PSB_DEBUG_GENERAL("TOPAZ: after topaz mtx setup ....\n");
+
+ memset((void *)(topaz_priv->topaz_mtx_wb),
+ 0,
+ topaz_priv->topaz_num_cores
+ * MTX_WRITEBACK_DATASIZE_ROUND);
+
+ PSB_DEBUG_GENERAL("TOPAZ: firmware uploaded.\n");
+
+ topaz_priv->topaz_busy = 0;
+
+ for (core_id = 0; core_id < topaz_priv->topaz_num_cores; core_id++) {
+ MVEA_WRITE32(MVEA_CR_BUFFER_SIDEBAND,
+ F_ENCODE(CACHE_ONLY, MVEA_CR_ABOVE_PARAM_OUT_SBAND) |
+ F_ENCODE(CACHE_ONLY, MVEA_CR_BELOW_PARAM_OUT_SBAND) |
+ F_ENCODE(MEM_AND_CACHE, MVEA_CR_ABOVE_PIX_OUT_SBAND) |
+ F_ENCODE(MEM_AND_CACHE, MVEA_CR_RECON_SBAND) |
+ F_ENCODE(CACHE_ONLY, MVEA_CR_REF_SBAND) |
+ F_ENCODE(CACHE_ONLY, MVEA_CR_ABOVE_PARAM_IN_SBAND) |
+ F_ENCODE(CACHE_ONLY, MVEA_CR_BELOW_PARAM_IN_SBAND) |
+ F_ENCODE(MEMORY_ONLY, MVEA_CR_CURR_PARAM_SBAND) |
+ F_ENCODE(CACHE_ONLY, MVEA_CR_ABOVE_PIX_IN_SBAND) |
+ F_ENCODE(MEMORY_ONLY, MVEA_CR_CURR_MB_SBAND),
+ core_id);
+ MVEA_WRITE32(MVEA_CR_IPE_JITTER_FACTOR, 3 - 1, core_id);
+
+ /*setup the jitter, base it on image size (using the height)*/
+ if (topaz_priv->frame_h >= 720)
+ MVEA_WRITE32(MVEA_CR_IPE_JITTER_FACTOR, 3 - 1, core_id);
+ else if (topaz_priv->frame_w >= 480)
+ MVEA_WRITE32(MVEA_CR_IPE_JITTER_FACTOR, 2 - 1, core_id);
+ else
+ MVEA_WRITE32(MVEA_CR_IPE_JITTER_FACTOR, 3 - 1, core_id);
+ }
+
+ psb_irq_preinstall_islands(dev, OSPM_VIDEO_ENC_ISLAND);
+ psb_irq_postinstall_islands(dev, OSPM_VIDEO_ENC_ISLAND);
+ pnw_topaz_enableirq(dev);
+
+ return 0;
+}
+
+#if UPLOAD_FW_BY_DMA
+static int topaz_upload_fw(struct drm_device *dev, enum drm_pnw_topaz_codec codec, uint32_t core_id)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ const struct pnw_topaz_codec_fw *cur_codec_fw;
+ uint32_t text_size, data_size;
+ uint32_t data_location;
+ uint32_t cur_mtx_data_size;
+ struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+ int ret = 0;
+
+ if (codec >= IMG_CODEC_NUM) {
+ DRM_ERROR("TOPAZ: Invalid codec %d\n", codec);
+ return -1;
+ }
+
+ /* # MTX reset */
+ PSB_DEBUG_GENERAL("TOPAZ: mtx reset.\n");
+ MTX_WRITE32(MTX_CORE_CR_MTX_SOFT_RESET_OFFSET,
+ MTX_CORE_CR_MTX_SOFT_RESET_MTX_RESET_MASK,
+ core_id);
+
+ /* # upload the master and slave firmware by DMA */
+ if (core_id == 0)
+ cur_codec_fw = &topaz_priv->topaz_fw[codec*2];
+ else
+ cur_codec_fw = &topaz_priv->topaz_fw[codec*2 + 1];
+
+ PSB_DEBUG_GENERAL("Topaz:upload codec %s(%d) text sz=%d data sz=%d\n"
+ "data location(0x%08x) to core(%d).\n",
+ codec_to_string(codec), codec,
+ cur_codec_fw->text_size, cur_codec_fw->data_size,
+ cur_codec_fw->data_location, core_id);
+
+ /* # upload text. text_size is byte size*/
+ text_size = cur_codec_fw->text_size / 4;
+ /* adjust transfer sizes of text and data sections to match burst size*/
+ text_size = ((text_size * 4 + (MTX_DMA_BURSTSIZE_BYTES - 1))
+ & ~(MTX_DMA_BURSTSIZE_BYTES - 1)) / 4;
+
+ PSB_DEBUG_GENERAL("TOPAZ: text_size round up to %d\n", text_size);
+ /* setup the MTX to start recieving data:
+ use a register for the transfer which will point to the source
+ (MTX_CR_MTX_SYSC_CDMAT) */
+ /*MTX burst size (4 * 2 * 32bits = 32bytes) should match DMA burst
+ size (2 * 128bits = 32bytes) */
+ /* #.# fill the dst addr */
+
+ MTX_WRITE32(MTX_CR_MTX_SYSC_CDMAA, MTX_DMA_MEMORY_BASE, core_id);
+ MTX_WRITE32(MTX_CR_MTX_SYSC_CDMAC,
+ F_ENCODE(4, MTX_BURSTSIZE) |
+ F_ENCODE(0, MTX_RNW) |
+ F_ENCODE(1, MTX_ENABLE) |
+ F_ENCODE(text_size, MTX_LENGTH), core_id);
+
+ /* #.# set DMAC access to host memory via BIF (deserted)*/
+ /* TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_DMAC_MODE, 1, core_id);*/
+
+ /* #.# transfer the codec */
+ if (0 != topaz_dma_transfer(dev_priv, 0, cur_codec_fw->text->offset, 0,
+ MTX_CR_MTX_SYSC_CDMAT,
+ text_size, core_id, 0)) {
+ pnw_error_dump_reg(dev_priv, core_id);
+ return -1;
+ }
+
+ /* #.# wait dma finish */
+ ret = pnw_topaz_wait_for_register(dev_priv,
+ DMAC_START + IMG_SOC_DMAC_IRQ_STAT(0),
+ F_ENCODE(1, IMG_SOC_TRANSFER_FIN),
+ F_ENCODE(1, IMG_SOC_TRANSFER_FIN));
+ if (ret != 0) {
+ pnw_error_dump_reg(dev_priv, core_id);
+ return -1;
+ }
+
+ /* #.# clear interrupt */
+ DMAC_WRITE32(IMG_SOC_DMAC_IRQ_STAT(0), 0);
+
+ PSB_DEBUG_GENERAL("TOPAZ: firmware text upload complete.\n");
+
+ /* # return access to topaz core (deserted)*/
+ /*TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_DMAC_MODE, 0, core_id);*/
+
+ /* # upload data */
+ data_size = cur_codec_fw->data_size / 4;
+ data_size = ((data_size * 4 + (MTX_DMA_BURSTSIZE_BYTES - 1))
+ & ~(MTX_DMA_BURSTSIZE_BYTES - 1)) / 4;
+
+ data_location = cur_codec_fw->data_location;
+ data_location = data_location & (~(MTX_DMA_BURSTSIZE_BYTES - 1));
+
+ PSB_DEBUG_GENERAL("TOPAZ: data_size round up to %d\n"
+ "data_location round up to 0x%08x\n",
+ data_size, data_location);
+ /* #.# fill the dst addr */
+ MTX_WRITE32(MTX_CR_MTX_SYSC_CDMAA,
+ data_location, core_id);
+ MTX_WRITE32(MTX_CR_MTX_SYSC_CDMAC,
+ F_ENCODE(4, MTX_BURSTSIZE) |
+ F_ENCODE(0, MTX_RNW) |
+ F_ENCODE(1, MTX_ENABLE) |
+ F_ENCODE(data_size, MTX_LENGTH), core_id);
+ /* #.# set DMAC access to host memory via BIF(deserted) */
+ /*TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_DMAC_MODE, 1, core_id);*/
+
+ /* #.# transfer the codec */
+ if (0 != topaz_dma_transfer(dev_priv, 0, cur_codec_fw->data->offset, 0,
+ MTX_CR_MTX_SYSC_CDMAT, data_size, core_id, 0)) {
+ pnw_error_dump_reg(dev_priv, core_id);
+ return -1;
+ }
+
+ /* #.# wait dma finish */
+ ret = pnw_topaz_wait_for_register(dev_priv,
+ DMAC_START + IMG_SOC_DMAC_IRQ_STAT(0),
+ F_ENCODE(1, IMG_SOC_TRANSFER_FIN),
+ F_ENCODE(1, IMG_SOC_TRANSFER_FIN));
+ if (ret != 0) {
+ pnw_error_dump_reg(dev_priv, core_id);
+ return -1;
+ }
+ /* #.# clear interrupt */
+ DMAC_WRITE32(IMG_SOC_DMAC_IRQ_STAT(0), 0);
+
+ pnw_topaz_mmu_flushcache(dev_priv);
+ PSB_DEBUG_GENERAL("TOPAZ: firmware data upload complete.\n");
+ /* # return access to topaz core(deserted) */
+ /*TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_DMAC_MODE, 0, core_id);*/
+
+ /* record this codec's mtx data size for
+ * context save & restore */
+ /* FIXME: since non-root sighting fixed by pre allocated,
+ * only need to correct the buffer size
+ */
+ cur_mtx_data_size = cur_codec_fw->data_size / 4;
+ if (topaz_priv->cur_mtx_data_size[core_id] != cur_mtx_data_size)
+ topaz_priv->cur_mtx_data_size[core_id] = cur_mtx_data_size;
+
+ return 0;
+}
+
+#else
+
+void topaz_mtx_upload_by_register(struct drm_device *dev, uint32_t mtx_mem,
+ uint32_t addr, uint32_t size,
+ struct ttm_buffer_object *buf,
+ uint32_t core)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ uint32_t *buf_p;
+ uint32_t debug_reg, bank_size, bank_ram_size, bank_count;
+ uint32_t cur_ram_id, ram_addr , ram_id;
+ int map_ret, lp;
+ struct ttm_bo_kmap_obj bo_kmap;
+ bool is_iomem;
+ uint32_t cur_addr, ui32Size;
+
+ PSB_DEBUG_GENERAL("TOPAZ: mtx upload: mtx_mem(0x%08x) addr(0x%08x)"
+ "size(%d)\n", mtx_mem, addr, size);
+
+ get_mtx_control_from_dash(dev_priv, core);
+
+ map_ret = ttm_bo_kmap(buf, 0, buf->num_pages, &bo_kmap);
+ if (map_ret) {
+ DRM_ERROR("TOPAZ: drm_bo_kmap failed: %d\n", map_ret);
+ return;
+ }
+ buf_p = (uint32_t *) ttm_kmap_obj_virtual(&bo_kmap, &is_iomem);
+
+
+ TOPAZ_READ32(TOPAZ_CORE_CR_MTX_DEBUG_OFFSET, &debug_reg, core);
+ debug_reg = 0x0a0a0600;
+ /*bank_size = (debug_reg & 0xf0000) >> 16;
+ bank_ram_size = 1 << (bank_size + 2);*/
+
+ /*Bank size 4096, BanK number 6, Totally ram size:24k*/
+ ui32Size = 0x1 << (F_EXTRACT(debug_reg,
+ TOPAZ_CR_MTX_LAST_RAM_BANK_SIZE) + 2);
+ /* all other banks */
+ bank_size = 0x1 << (F_EXTRACT(debug_reg,
+ TOPAZ_CR_MTX_RAM_BANK_SIZE) + 2);
+ /* total RAM size */
+ bank_ram_size = ui32Size + (bank_size *
+ (F_EXTRACT(debug_reg, TOPAZ_CR_MTX_RAM_BANKS) - 1));
+
+ bank_count = (debug_reg & 0xf00) >> 8;
+
+ PSB_DEBUG_GENERAL("TOPAZ: bank size %d, bank count %d, ram size %d\n",
+ bank_size, bank_count, bank_ram_size);
+
+ pnw_topaz_wait_for_register(dev_priv,
+ REG_START_TOPAZ_MTX_HOST(core)
+ + MTX_CR_MTX_RAM_ACCESS_STATUS,
+ MASK_MTX_MTX_MTX_MCM_STAT,
+ MASK_MTX_MTX_MTX_MCM_STAT);
+
+ cur_ram_id = -1;
+ cur_addr = addr;
+ for (lp = 0; lp < size / 4; ++lp) {
+ ram_id = mtx_mem + (cur_addr / bank_size);
+
+ if (cur_ram_id != ram_id) {
+ ram_addr = cur_addr >> 2;
+
+ MTX_WRITE32(MTX_CR_MTX_RAM_ACCESS_CONTROL,
+ F_ENCODE(ram_id, MTX_MTX_MCMID) |
+ F_ENCODE(ram_addr, MTX_MTX_MCM_ADDR) |
+ F_ENCODE(1, MTX_MTX_MCMAI),
+ core);
+
+ cur_ram_id = ram_id;
+ }
+ cur_addr += 4;
+
+ MTX_WRITE32(MTX_CR_MTX_RAM_ACCESS_DATA_TRANSFER,
+ *(buf_p + lp), core);
+
+ pnw_topaz_wait_for_register(dev_priv,
+ MTX_CR_MTX_RAM_ACCESS_STATUS
+ + REG_START_TOPAZ_MTX_HOST(core),
+ MASK_MTX_MTX_MTX_MCM_STAT,
+ MASK_MTX_MTX_MTX_MCM_STAT);
+ }
+
+ release_mtx_control_from_dash(dev_priv, core);
+ ttm_bo_kunmap(&bo_kmap);
+
+ PSB_DEBUG_GENERAL("TOPAZ: register data upload done\n");
+ return;
+}
+
+int topaz_upload_fw(struct drm_device *dev, enum drm_pnw_topaz_codec codec,
+ uint32_t core_id)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ const struct pnw_topaz_codec_fw *cur_codec_fw;
+ uint32_t text_size, data_size;
+ uint32_t data_location;
+ struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+
+ /* # refer HLD document */
+ /* # MTX reset */
+ PSB_DEBUG_GENERAL("TOPAZ: mtx reset.\n");
+ MTX_WRITE32(MTX_CORE_CR_MTX_SOFT_RESET_OFFSET,
+ MTX_CORE_CR_MTX_SOFT_RESET_MTX_RESET_MASK,
+ core_id);
+
+ /* # upload the master and slave firmware by DMA */
+ if (core_id == 0)
+ cur_codec_fw = &topaz_priv->topaz_fw[codec * 2];
+ else
+ cur_codec_fw = &topaz_priv->topaz_fw[codec * 2 + 1];
+
+ PSB_DEBUG_GENERAL("Topaz:upload codec by MTX reg %s(%d)"
+ " text sz=%d data sz=%d"
+ " data location(%d) to core(%d).\n",
+ codec_to_string(codec), codec,
+ cur_codec_fw->text_size, cur_codec_fw->data_size,
+ cur_codec_fw->data_location, core_id);
+
+ /* # upload text */
+ text_size = cur_codec_fw->text_size;
+
+ topaz_mtx_upload_by_register(dev, MTX_CORE_CODE_MEM,
+ 0,
+ /*PC_START_ADDRESS - MTX_MEMORY_BASE,*/
+ text_size, cur_codec_fw->text, core_id);
+
+ /* # upload data */
+ data_size = cur_codec_fw->data_size;
+ data_location = cur_codec_fw->data_location;
+
+ topaz_mtx_upload_by_register(dev, MTX_CORE_DATA_MEM,
+ data_location - MTX_DMA_MEMORY_BASE, data_size,
+ cur_codec_fw->data, core_id);
+
+ return 0;
+}
+
+#endif /* UPLOAD_FW_BY_DMA */
+
+/* is_increment is always 0, so use it as core_id for workaround*/
+static int topaz_dma_transfer(struct drm_psb_private *dev_priv, uint32_t channel,
+ uint32_t src_phy_addr, uint32_t offset,
+ uint32_t soc_addr, uint32_t byte_num,
+ uint32_t is_increment, uint32_t is_write)
+{
+ uint32_t dmac_count;
+ uint32_t irq_stat;
+ uint32_t count;
+
+ PSB_DEBUG_GENERAL("TOPAZ: using dma to transfer firmware\n");
+ /* # check that no transfer is currently in progress and no
+ interrupts are outstanding ?? (why care interrupt) */
+ DMAC_READ32(IMG_SOC_DMAC_COUNT(channel), &dmac_count);
+ if (0 != (dmac_count & (MASK_IMG_SOC_EN | MASK_IMG_SOC_LIST_EN))) {
+ DRM_ERROR("TOPAZ: there is tranfer in progress\n");
+ return -1;
+ }
+
+ /* assert(0==(dmac_count & (MASK_IMG_SOC_EN | MASK_IMG_SOC_LIST_EN)));*/
+
+ /* clear status of any previous interrupts */
+ DMAC_WRITE32(IMG_SOC_DMAC_IRQ_STAT(channel), 0);
+
+ /* check irq status */
+ DMAC_READ32(IMG_SOC_DMAC_IRQ_STAT(channel), &irq_stat);
+ /* assert(0 == irq_stat); */
+ if (0 != irq_stat)
+ DRM_ERROR("TOPAZ: there is hold up\n");
+
+ /*MTX_WRITE32(MTX_CR_MTX_SYSC_CDMAA, MTX_DMA_MEMORY_BASE, is_increment);
+ MTX_WRITE32(MTX_CR_MTX_SYSC_CDMAC,
+ F_ENCODE(4, MTX_BURSTSIZE) |
+ F_ENCODE(0, MTX_RNW) |
+ F_ENCODE(1, MTX_ENABLE) |
+ F_ENCODE(byte_num, MTX_LENGTH), is_increment);*/
+
+ /* per hold - allow HW to sort itself out */
+ DMAC_WRITE32(IMG_SOC_DMAC_PER_HOLD(channel), 16);
+ /* clear previous interrupts */
+ DMAC_WRITE32(IMG_SOC_DMAC_IRQ_STAT(channel), 0);
+
+ DMAC_WRITE32(IMG_SOC_DMAC_SETUP(channel),
+ (src_phy_addr + offset));
+ count = DMAC_VALUE_COUNT(DMAC_BSWAP_NO_SWAP, DMAC_PWIDTH_32_BIT,
+ is_write, DMAC_PWIDTH_32_BIT, byte_num);
+ /* generate an interrupt at the end of transfer */
+ /* count |= MASK_IMG_SOC_TRANSFER_IEN; */
+ /*count |= F_ENCODE(is_write, IMG_SOC_DIR);*/
+ DMAC_WRITE32(IMG_SOC_DMAC_COUNT(channel), count);
+
+ /* Burst : 2 * 128 bits = 32 bytes*/
+ DMAC_WRITE32(IMG_SOC_DMAC_PERIPH(channel),
+ DMAC_VALUE_PERIPH_PARAM(DMAC_ACC_DEL_0,
+ 0, DMAC_BURST_2));
+
+ /* is_increment here is actually core_id*/
+ DMAC_WRITE32(IMG_SOC_DMAC_PERIPHERAL_ADDR(channel),
+ MTX_CR_MTX_SYSC_CDMAT
+ + REG_START_TOPAZ_MTX_HOST(is_increment));
+
+ /* Finally, rewrite the count register with
+ * the enable bit set to kick off the transfer
+ */
+ DMAC_WRITE32(IMG_SOC_DMAC_COUNT(channel), count | MASK_IMG_SOC_EN);
+
+ PSB_DEBUG_GENERAL("TOPAZ: dma transfer started.\n");
+
+ return 0;
+}
+
+void topaz_write_core_reg(struct drm_psb_private *dev_priv,
+ uint32_t core,
+ uint32_t reg,
+ const uint32_t val)
+{
+ uint32_t tmp;
+ get_mtx_control_from_dash(dev_priv, core);
+
+ /* put data into MTX_RW_DATA */
+ MTX_WRITE32(MTX_CORE_CR_MTX_REGISTER_READ_WRITE_DATA_OFFSET, val, core);
+
+ /* request a write */
+ tmp = reg &
+ ~MTX_CORE_CR_MTX_REGISTER_READ_WRITE_REQUEST_MTX_DREADY_MASK;
+
+ MTX_WRITE32(MTX_CORE_CR_MTX_REGISTER_READ_WRITE_REQUEST_OFFSET,
+ tmp, core);
+
+ /* wait for operation finished */
+ pnw_topaz_wait_for_register(dev_priv,
+ REG_START_TOPAZ_MTX_HOST(core) +
+ MTX_CORE_CR_MTX_REGISTER_READ_WRITE_REQUEST_OFFSET,
+ MTX_CORE_CR_MTX_REGISTER_READ_WRITE_REQUEST_MTX_DREADY_MASK,
+ MTX_CORE_CR_MTX_REGISTER_READ_WRITE_REQUEST_MTX_DREADY_MASK);
+
+ release_mtx_control_from_dash(dev_priv, core);
+}
+
+void topaz_read_core_reg(struct drm_psb_private *dev_priv,
+ uint32_t core,
+ uint32_t reg,
+ uint32_t *ret_val)
+{
+ uint32_t tmp;
+
+ get_mtx_control_from_dash(dev_priv, core);
+
+ /* request a write */
+ tmp = (reg &
+ ~MTX_CORE_CR_MTX_REGISTER_READ_WRITE_REQUEST_MTX_DREADY_MASK);
+
+ MTX_WRITE32(MTX_CORE_CR_MTX_REGISTER_READ_WRITE_REQUEST_OFFSET,
+ MTX_CORE_CR_MTX_REGISTER_READ_WRITE_REQUEST_MTX_RNW_MASK
+ | tmp, core);
+
+ /* wait for operation finished */
+ pnw_topaz_wait_for_register(dev_priv,
+ REG_START_TOPAZ_MTX_HOST(core) +
+ MTX_CORE_CR_MTX_REGISTER_READ_WRITE_REQUEST_OFFSET,
+ MTX_CORE_CR_MTX_REGISTER_READ_WRITE_REQUEST_MTX_DREADY_MASK,
+ MTX_CORE_CR_MTX_REGISTER_READ_WRITE_REQUEST_MTX_DREADY_MASK);
+
+ /* read */
+ MTX_READ32(MTX_CORE_CR_MTX_REGISTER_READ_WRITE_DATA_OFFSET,
+ ret_val, core);
+
+ release_mtx_control_from_dash(dev_priv, core);
+}
+
+static void get_mtx_control_from_dash(struct drm_psb_private *dev_priv, uint32_t core)
+{
+ int debug_reg_slave_val;
+ struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+ int count = 0;
+
+ /* GetMTXControlFromDash */
+ TOPAZ_WRITE32(TOPAZ_CORE_CR_MTX_DEBUG_OFFSET,
+ F_ENCODE(1, TOPAZ_CR_MTX_DBG_IS_SLAVE) |
+ F_ENCODE(2, TOPAZ_CR_MTX_DBG_GPIO_OUT), core);
+ do {
+ TOPAZ_READ32(TOPAZ_CORE_CR_MTX_DEBUG_OFFSET,
+ &debug_reg_slave_val, core);
+ count++;
+ } while (((debug_reg_slave_val & 0x18) != 0) && count < 50000);
+
+ if (count >= 50000)
+ PSB_DEBUG_GENERAL("TOPAZ: timeout in "
+ "get_mtx_control_from_dash\n");
+
+ /* save access control */
+ TOPAZ_READ32(MTX_CORE_CR_MTX_RAM_ACCESS_CONTROL_OFFSET,
+ &topaz_priv->topaz_dash_access_ctrl, core);
+}
+
+static void release_mtx_control_from_dash(struct drm_psb_private *dev_priv,
+ uint32_t core)
+{
+ struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+
+ /* restore access control */
+ TOPAZ_WRITE32(MTX_CORE_CR_MTX_RAM_ACCESS_CONTROL_OFFSET,
+ topaz_priv->topaz_dash_access_ctrl, core);
+
+ /* release bus */
+ TOPAZ_WRITE32(TOPAZ_CORE_CR_MTX_DEBUG_OFFSET,
+ F_ENCODE(1, TOPAZ_CR_MTX_DBG_IS_SLAVE), core);
+}
+
+static void pnw_topaz_mmu_hwsetup(struct drm_psb_private *dev_priv, uint32_t core_id)
+{
+ uint32_t pd_addr = psb_get_default_pd_addr(dev_priv->mmu);
+
+ PSB_DEBUG_GENERAL("TOPAZ: core (%d) MMU set up.\n", core_id);
+
+ /* bypass all request while MMU is being configured */
+ TOPAZ_WRITE32(TOPAZ_CR_MMU_CONTROL0,
+ F_ENCODE(1, TOPAZ_CR_MMU_BYPASS)
+ | F_ENCODE(1, TOPAZ_CR_MMU_BYPASS_DMAC), core_id);
+
+ /* set MMU hardware at the page table directory */
+ PSB_DEBUG_GENERAL("TOPAZ: write PD phyaddr=0x%08x "
+ "into MMU_DIR_LIST0/1\n", pd_addr);
+ /*There's two of these (0) and (1).. only 0 is currently used*/
+ TOPAZ_WRITE32(TOPAZ_CR_MMU_DIR_LIST_BASE(0), pd_addr, core_id);
+ /*TOPAZ_WRITE32(TOPAZ_CR_MMU_DIR_LIST_BASE(1), 0, core_id);*/
+
+ /* setup index register, all pointing to directory bank 0 */
+ TOPAZ_WRITE32(TOPAZ_CR_MMU_BANK_INDEX, 0, core_id);
+
+ /* now enable MMU access for all requestors */
+ TOPAZ_WRITE32(TOPAZ_CR_MMU_CONTROL0,
+ F_ENCODE(0, TOPAZ_CR_MMU_BYPASS)
+ | F_ENCODE(0, TOPAZ_CR_MMU_BYPASS_DMAC), core_id);
+}
+
+void pnw_topaz_mmu_flushcache(struct drm_psb_private *dev_priv)
+{
+ uint32_t mmu_control;
+
+ if (dev_priv->topaz_disabled)
+ return;
+
+ PSB_DEBUG_GENERAL("TOPAZ: pnw_topaz_mmu_flushcache\n");
+#if 0
+ PSB_DEBUG_GENERAL("XXX: Only one PTD/PTE cache"
+ " so flush using the master core\n");
+#endif
+ /* XXX: disable interrupt */
+ TOPAZ_READ32(TOPAZ_CR_MMU_CONTROL0, &mmu_control, 0);
+ mmu_control |= F_ENCODE(1, TOPAZ_CR_MMU_INVALDC);
+ /*mmu_control |= F_ENCODE(1, TOPAZ_CR_MMU_FLUSH);*/
+
+#if 0
+ PSB_DEBUG_GENERAL("Set Invalid flag (this causes a flush with MMU\n"
+ "still operating afterwards even if not cleared,\n"
+ "but may want to replace with MMU_FLUSH?\n");
+#endif
+ TOPAZ_WRITE32(TOPAZ_CR_MMU_CONTROL0, mmu_control, 0);
+
+ /* clear it */
+ mmu_control &= (~F_ENCODE(1, TOPAZ_CR_MMU_INVALDC));
+ //mmu_control &= (~F_ENCODE(1, TOPAZ_CR_MMU_FLUSH));
+ TOPAZ_WRITE32(TOPAZ_CR_MMU_CONTROL0, mmu_control, 0);
+ psb_gl3_global_invalidation(dev_priv->dev);
+}
+
+
+static void pnw_topaz_retry_kick(struct drm_device *dev, int core_id)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *)dev->dev_private;
+ struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+ int i, j;
+
+ for (j = 0; j < TOPAZ_KICK_RETRY_MAX; j++) {
+ PSB_DEBUG_GENERAL("TOPAZ: Kick was missing. Try again.\n");
+ topaz_set_mtx_target(dev_priv, 0, 0);
+ MTX_WRITE32(MTX_CR_MTX_KICK, 1, 0);
+ i = 3000;
+ PSB_DEBUG_GENERAL("TOPAZ: Wait for the NULL command...\n");
+ while (i && \
+ ((topaz_priv->topaz_cmd_count - 1) != \
+ *(topaz_priv->topaz_mtx_wb + \
+ core_id * MTX_WRITEBACK_DATASIZE_ROUND\
+ + MTX_WRITEBACK_VALUE))) {
+ cpu_relax();
+ i--;
+ }
+
+ if (0 != i) {
+ PSB_DEBUG_GENERAL("TOPAZ: Finished.\n");
+ break;
+ }
+ }
+
+ if (j == TOPAZ_KICK_RETRY_MAX)
+ DRM_ERROR("TOPAZ:Have toggled MTX kick %d times but all "\
+ "failed!\n",
+ TOPAZ_KICK_RETRY_MAX);
+ return;
+}
+
+int pnw_topaz_restore_mtx_state(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *)dev->dev_private;
+ int32_t core_id;
+ uint32_t *mtx_reg_state;
+ int i, need_restore;
+ struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+ struct psb_video_ctx *pos, *n;
+ uint32_t wb_offset;
+
+ if (!topaz_priv->topaz_mtx_saved)
+ return -1;
+
+ list_for_each_entry_safe(pos, n, &dev_priv->video_ctx, head) {
+ if ((pos->ctx_type & 0xff) == 6)
+ need_restore = 1;
+ }
+
+ if (0 == need_restore) {
+ topaz_priv->topaz_mtx_saved = 0;
+ PSB_DEBUG_GENERAL("topaz: no vec context found. needn't"
+ " to restore mtx registers.\n");
+ return 0;
+ }
+
+ if (topaz_priv->topaz_fw_loaded == 0) {
+ PSB_DEBUG_GENERAL("TOPAZ: needn't to restore context"
+ " without firmware uploaded\n");
+ return 0;
+ }
+
+ if (topaz_priv->topaz_mtx_data_mem[0] == NULL) {
+ PSB_DEBUG_GENERAL("TOPAZ: try to restore context"
+ " without space allocated, return"
+ " directly without restore\n");
+ return -1;
+ }
+
+ pnw_topaz_mmu_flushcache(dev_priv);
+
+ /*TopazSC will be reset, no need to save context.*/
+ for (core_id = 0; core_id < topaz_priv->topaz_num_cores; core_id++)
+ pnw_topaz_mmu_hwsetup(dev_priv, core_id);
+ for (core_id = 0; core_id < topaz_priv->topaz_num_cores; core_id++) {
+ MVEA_WRITE32(MVEA_CR_IMG_MVEA_SRST,
+ F_ENCODE(1, MVEA_CR_IMG_MVEA_SPE_SOFT_RESET) |
+ F_ENCODE(1, MVEA_CR_IMG_MVEA_IPE_SOFT_RESET) |
+ F_ENCODE(1, MVEA_CR_IMG_MVEA_CMPRS_SOFT_RESET) |
+ F_ENCODE(1, MVEA_CR_IMG_MVEA_JMCOMP_SOFT_RESET)
+ |
+ F_ENCODE(1, MVEA_CR_IMG_MVEA_CMC_SOFT_RESET) |
+ F_ENCODE(1, MVEA_CR_IMG_MVEA_DCF_SOFT_RESET),
+ core_id);
+ MVEA_WRITE32(MVEA_CR_IMG_MVEA_SRST,
+ F_ENCODE(0, MVEA_CR_IMG_MVEA_SPE_SOFT_RESET) |
+ F_ENCODE(0, MVEA_CR_IMG_MVEA_IPE_SOFT_RESET) |
+ F_ENCODE(0, MVEA_CR_IMG_MVEA_CMPRS_SOFT_RESET) |
+ F_ENCODE(0, MVEA_CR_IMG_MVEA_JMCOMP_SOFT_RESET)
+ |
+ F_ENCODE(0, MVEA_CR_IMG_MVEA_CMC_SOFT_RESET) |
+ F_ENCODE(0, MVEA_CR_IMG_MVEA_DCF_SOFT_RESET),
+ core_id);
+ }
+
+ for (core_id = 0; core_id < topaz_priv->topaz_num_cores; core_id++)
+ pnw_topaz_mmu_hwsetup(dev_priv, core_id);
+
+ for (core_id = 0; core_id < topaz_priv->topaz_num_cores; core_id++) {
+ pnw_topazsc_reset_ESB(dev_priv, core_id);
+ MVEA_WRITE32(MVEA_CR_IMG_MVEA_SRST,
+ F_ENCODE(1, MVEA_CR_IMG_MVEA_SPE_SOFT_RESET) |
+ F_ENCODE(1, MVEA_CR_IMG_MVEA_IPE_SOFT_RESET) |
+ F_ENCODE(1, MVEA_CR_IMG_MVEA_CMPRS_SOFT_RESET) |
+ F_ENCODE(1, MVEA_CR_IMG_MVEA_JMCOMP_SOFT_RESET)
+ |
+ F_ENCODE(1, MVEA_CR_IMG_MVEA_CMC_SOFT_RESET) |
+ F_ENCODE(1, MVEA_CR_IMG_MVEA_DCF_SOFT_RESET),
+ core_id);
+ MVEA_WRITE32(MVEA_CR_IMG_MVEA_SRST,
+ F_ENCODE(0, MVEA_CR_IMG_MVEA_SPE_SOFT_RESET) |
+ F_ENCODE(0, MVEA_CR_IMG_MVEA_IPE_SOFT_RESET) |
+ F_ENCODE(0, MVEA_CR_IMG_MVEA_CMPRS_SOFT_RESET) |
+ F_ENCODE(0, MVEA_CR_IMG_MVEA_JMCOMP_SOFT_RESET)
+ |
+ F_ENCODE(0, MVEA_CR_IMG_MVEA_CMC_SOFT_RESET) |
+ F_ENCODE(0, MVEA_CR_IMG_MVEA_DCF_SOFT_RESET),
+ core_id);
+ }
+
+ for (core_id = topaz_priv->topaz_num_cores - 1;
+ core_id >= 0; core_id--) {
+ topaz_set_mtx_target(dev_priv, core_id, 0);
+
+ TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_SRST,
+ F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_MVEA_SOFT_RESET)
+ |
+ F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_IO_SOFT_RESET) |
+ F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_DB_SOFT_RESET) |
+ F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_MTX_SOFT_RESET) |
+ F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_VLC_SOFT_RESET),
+ core_id);
+ TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_SRST,
+ 0,
+ core_id);
+
+ topaz_set_mtx_target(dev_priv, core_id, 0);
+ MTX_WRITE32(MTX_CORE_CR_MTX_SOFT_RESET_OFFSET,
+ MTX_CORE_CR_MTX_SOFT_RESET_MTX_RESET_MASK,
+ core_id);
+ MTX_WRITE32(MTX_CORE_CR_MTX_SOFT_RESET_OFFSET,
+ 0, core_id);
+
+ /* # upload fw by drm */
+ PSB_DEBUG_GENERAL("TOPAZ: Restore text and data for core %d\n",
+ core_id);
+ if (0 != mtx_dma_write(dev, core_id))
+ return -1;
+
+ pnw_topaz_mmu_flushcache(dev_priv);
+ }
+
+ for (core_id = topaz_priv->topaz_num_cores - 1;
+ core_id >= 0; core_id--) {
+ topaz_set_mtx_target(dev_priv, core_id, 0);
+
+ /*Reset IO again. WA for BZ1478*/
+ TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_SRST,
+ F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_IO_SOFT_RESET),
+ core_id);
+ TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_SRST,
+ 0,
+ core_id);
+
+ mtx_reg_state = topaz_priv->topaz_mtx_reg_state[core_id];
+ /* restore register */
+ /* Saves 8 Registers of D0 Bank */
+ /* DoRe0, D0Ar6, D0Ar4, D0Ar2, D0FrT, D0.5, D0.6 and D0.7 */
+ for (i = 0; i < 8; i++) {
+ topaz_write_core_reg(dev_priv, core_id, 0x1 | (i << 4),
+ *mtx_reg_state);
+ mtx_reg_state++;
+ }
+ /* Saves 8 Registers of D1 Bank */
+ /* D1Re0, D1Ar5, D1Ar3, D1Ar1, D1RtP, D1.5, D1.6 and D1.7 */
+ for (i = 0; i < 8; i++) {
+ topaz_write_core_reg(dev_priv, core_id, 0x2 | (i << 4),
+ *mtx_reg_state);
+ mtx_reg_state++;
+ }
+ /* Saves 4 Registers of A0 Bank */
+ /* A0StP, A0FrP, A0.2 and A0.3 */
+ for (i = 0; i < 4; i++) {
+ topaz_write_core_reg(dev_priv, core_id, 0x3 | (i << 4),
+ *mtx_reg_state);
+ mtx_reg_state++;
+ }
+ /* Saves 4 Registers of A1 Bank */
+ /* A1GbP, A1LbP, A1.2 and A1.3 */
+ for (i = 0; i < 4; i++) {
+ topaz_write_core_reg(dev_priv, core_id, 0x4 | (i << 4),
+ *mtx_reg_state);
+ mtx_reg_state++;
+ }
+ /* Saves PC and PCX */
+ for (i = 0; i < 2; i++) {
+ topaz_write_core_reg(dev_priv, core_id, 0x5 | (i << 4),
+ *mtx_reg_state);
+ mtx_reg_state++;
+ }
+ /* Saves 8 Control Registers */
+ /* TXSTAT, TXMASK, TXSTATI, TXMASKI, TXPOLL, TXGPIOI, TXPOLLI,
+ * TXGPIOO */
+ for (i = 1; i < 8; i += 2) {
+ /*Force the busy bit of core 0 to be 1. Since idle
+ * signal may cause the clock to the MTX is not running
+ * when the kick is written to it. WA for BZ1478.*/
+ if (i == 7 && core_id == 0)
+ topaz_write_core_reg(dev_priv, core_id,
+ 0x7 | (i << 4),
+ 0x2 | (*mtx_reg_state));
+ else
+ topaz_write_core_reg(dev_priv, core_id,
+ 0x7 | (i << 4),
+ *mtx_reg_state);
+ mtx_reg_state++;
+ }
+ COMMS_WRITE32(TOPAZ_COMMS_CR_STAT_1(0), \
+ *mtx_reg_state++, core_id);
+ COMMS_WRITE32(TOPAZ_COMMS_CR_STAT_0(0), \
+ *mtx_reg_state++, core_id);
+ COMMS_WRITE32(TOPAZ_COMMS_CR_MTX_STATUS(0), \
+ *mtx_reg_state++, core_id);
+ COMMS_WRITE32(TOPAZ_COMMS_CR_CMD_WB_VAL(0), \
+ *mtx_reg_state++, core_id);
+ COMMS_WRITE32(TOPAZ_COMMS_CR_CMD_WB_ADDR(0), \
+ *mtx_reg_state++, core_id);
+ COMMS_WRITE32(TOPAZ_COMMS_CR_CMD_DATA_ADDR(0), \
+ *mtx_reg_state++, core_id);
+ COMMS_WRITE32(TOPAZ_COMMS_CR_CMD_WORD(0), \
+ *mtx_reg_state++, core_id);
+
+ /* enable auto clock is essential for this driver */
+ TOPAZ_WRITE32(TOPAZ_CR_TOPAZ_AUTO_CLK_GATE,
+ F_ENCODE(1, TOPAZ_CR_TOPAZ_VLC_AUTO_CLK_GATE) |
+ F_ENCODE(1, TOPAZ_CR_TOPAZ_DB_AUTO_CLK_GATE),
+ core_id);
+ MVEA_WRITE32(MVEA_CR_MVEA_AUTO_CLOCK_GATING,
+ F_ENCODE(1, MVEA_CR_MVEA_IPE_AUTO_CLK_GATE) |
+ F_ENCODE(1, MVEA_CR_MVEA_SPE_AUTO_CLK_GATE) |
+ F_ENCODE(1, MVEA_CR_MVEA_CMPRS_AUTO_CLK_GATE) |
+ F_ENCODE(1, MVEA_CR_MVEA_JMCOMP_AUTO_CLK_GATE),
+ core_id);
+
+ topaz_read_core_reg(dev_priv, core_id,
+ TOPAZ_MTX_PC, &i);
+
+ PSB_DEBUG_GENERAL("TOPAZ: verify pc address for core"
+ " (%d):0x%08x\n",
+ core_id, i);
+
+ /* flush the command FIFO - only has effect on master MTX */
+ if (core_id == 0)
+ TOPAZ_WRITE32(TOPAZ_CR_TOPAZ_CMD_FIFO_2,
+ F_ENCODE(1, TOPAZ_CR_CMD_FIFO_FLUSH),
+ 0);
+
+ /* clear MTX interrupt */
+ TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_INTCLEAR,
+ F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_INTCLR_MTX),
+ core_id);
+
+ /* put the number of cores in use in the scratch register
+ * so is is ready when the firmware wakes up. */
+ TOPAZ_WRITE32(TOPAZ_CORE_NUMBER_SET_OFFSET, 2, core_id);
+
+ /* # turn on MTX */
+ topaz_set_mtx_target(dev_priv, core_id, 0);
+ MTX_WRITE32(MTX_CORE_CR_MTX_ENABLE_OFFSET,
+ MTX_CORE_CR_MTX_ENABLE_MTX_ENABLE_MASK,
+ core_id);
+
+ }
+ PSB_DEBUG_GENERAL("TOPAZ: send NULL command to test firmware\n");
+
+ /*WA for BZ1478. Enable IRQ here, since it's disabled by IO reset*/
+ pnw_topaz_enableirq(dev);
+ TOPAZ_WRITE32(TOPAZ_CR_TOPAZ_CMD_FIFO_1,
+ F_ENCODE(1, TOPAZ_CR_CMD_FIFO_FLUSH),
+ 0);
+
+ for (core_id = topaz_priv->topaz_num_cores - 1;
+ core_id >= 0; core_id--) {
+ wb_offset = TOPAZ_MTX_WB_OFFSET(
+ topaz_priv->topaz_wb_offset,
+ core_id);
+
+ pnw_topaz_kick_null_cmd(dev_priv, core_id,
+ wb_offset,
+ topaz_priv->topaz_cmd_count++, 0);
+
+ i = 3000;
+ PSB_DEBUG_GENERAL("TOPAZ: Wait for the NULL command...\n");
+ while (i && \
+ ((topaz_priv->topaz_cmd_count - 1) != \
+ *(topaz_priv->topaz_mtx_wb + \
+ core_id * MTX_WRITEBACK_DATASIZE_ROUND\
+ + MTX_WRITEBACK_VALUE))) {
+ cpu_relax();
+ i--;
+ }
+
+ if (i == 0)
+ pnw_topaz_retry_kick(dev, core_id);
+ else
+ PSB_DEBUG_GENERAL("TOPAZ:Finished.\n");
+
+ TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_INTCLEAR,
+ F_ENCODE(1, TOPAZ_CR_IMG_TOPAZ_INTCLR_MTX),
+ core_id);
+ }
+
+ topaz_priv->topaz_mtx_saved = 0;
+ return 0;
+}
+
+int pnw_topaz_save_mtx_state(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *)dev->dev_private;
+ uint32_t *mtx_reg_state;
+ int i, need_save = 0;
+ uint32_t data_location, data_size;
+ int core;
+ struct pnw_topaz_codec_fw *cur_codec_fw;
+ struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+ struct psb_video_ctx *pos, *n;
+ uint32_t reg_val;
+ int j;
+
+ topaz_priv->topaz_mtx_saved = 0;
+
+ list_for_each_entry_safe(pos, n, &dev_priv->video_ctx, head) {
+ if ((pos->ctx_type & 0xff) == 6)
+ need_save = 1;
+ }
+
+ if (0 == need_save) {
+ PSB_DEBUG_GENERAL("TOPAZ: vec context not found. No need"
+ " to save mtx registers.\n");
+ return 0;
+ }
+
+ /*TopazSC will be reset, no need to save context.*/
+ if (topaz_priv->topaz_needs_reset)
+ return 0;
+
+ PSB_DEBUG_GENERAL("TOPAZ: Found one vec context. "
+ "Need to save mtx registers.\n");
+ if (topaz_priv->topaz_num_cores > MAX_TOPAZ_CORES) {
+ DRM_ERROR("TOPAZ: Invalid core numbers: %d\n",
+ topaz_priv->topaz_num_cores);
+ return -1;
+ }
+
+ if (topaz_priv->topaz_fw_loaded == 0) {
+ PSB_DEBUG_GENERAL("TOPAZ: No need to restore context since"
+ " firmware has not been uploaded.\n");
+ return -1;
+ }
+
+ for (core = topaz_priv->topaz_num_cores - 1; core >= 0; core--) {
+ if (topaz_priv->topaz_mtx_data_mem[core] == NULL) {
+ PSB_DEBUG_GENERAL("TOPAZ: try to save context "
+ "without space allocated, return"
+ " directly without save\n");
+ return -1;
+ }
+
+ topaz_set_mtx_target(dev_priv, core, 0);
+ /* stop mtx */
+ MTX_WRITE32(MTX_CORE_CR_MTX_ENABLE_OFFSET,
+ MTX_CORE_CR_MTX_ENABLE_MTX_TOFF_MASK, core);
+
+ if (core == 0) {
+ if (0 != pnw_topaz_wait_for_register(dev_priv,
+ REG_START_TOPAZ_MTX_HOST(core)
+ + MTX_CORE_CR_MTX_TXRPT_OFFSET,
+ TXRPT_WAITONKICK_VALUE,
+ 0xffffffff)) {
+ DRM_ERROR("TOPAZ: Stop MTX failed!\n");
+ topaz_priv->topaz_needs_reset = 1;
+ return -1;
+ }
+ }
+
+ mtx_reg_state = topaz_priv->topaz_mtx_reg_state[core];
+
+ /* Saves 8 Registers of D0 Bank */
+ /* DoRe0, D0Ar6, D0Ar4, D0Ar2, D0FrT, D0.5, D0.6 and D0.7 */
+ for (i = 0; i < 8; i++) {
+ topaz_read_core_reg(dev_priv, core, 0x1 | (i << 4),
+ mtx_reg_state);
+ mtx_reg_state++;
+ }
+ /* Saves 8 Registers of D1 Bank */
+ /* D1Re0, D1Ar5, D1Ar3, D1Ar1, D1RtP, D1.5, D1.6 and D1.7 */
+ for (i = 0; i < 8; i++) {
+ topaz_read_core_reg(dev_priv, core, 0x2 | (i << 4),
+ mtx_reg_state);
+ mtx_reg_state++;
+ }
+ /* Saves 4 Registers of A0 Bank */
+ /* A0StP, A0FrP, A0.2 and A0.3 */
+ for (i = 0; i < 4; i++) {
+ topaz_read_core_reg(dev_priv, core, 0x3 | (i << 4),
+ mtx_reg_state);
+ mtx_reg_state++;
+ }
+ /* Saves 4 Registers of A1 Bank */
+ /* A1GbP, A1LbP, A1.2 and A1.3 */
+ for (i = 0; i < 4; i++) {
+ topaz_read_core_reg(dev_priv, core, 0x4 | (i << 4),
+ mtx_reg_state);
+ mtx_reg_state++;
+ }
+ /* Saves PC and PCX */
+ for (i = 0; i < 2; i++) {
+ topaz_read_core_reg(dev_priv, core, 0x5 | (i << 4),
+ mtx_reg_state);
+ mtx_reg_state++;
+ }
+ /* Saves 8 Control Registers */
+ /* TXSTAT, TXMASK, TXSTATI, TXMASKI, TXPOLL, TXGPIOI, TXPOLLI,
+ * TXGPIOO */
+ for (i = 1; i < 8; i += 2) {
+ topaz_read_core_reg(dev_priv, core, 0x7 | (i << 4),
+ mtx_reg_state);
+ mtx_reg_state++;
+ }
+
+ COMMS_READ32(TOPAZ_COMMS_CR_STAT_1(0), \
+ mtx_reg_state++, core);
+ COMMS_READ32(TOPAZ_COMMS_CR_STAT_0(0), \
+ mtx_reg_state++, core);
+ COMMS_READ32(TOPAZ_COMMS_CR_MTX_STATUS(0), \
+ mtx_reg_state++, core);
+ COMMS_READ32(TOPAZ_COMMS_CR_CMD_WB_VAL(0), \
+ mtx_reg_state++, core);
+ COMMS_READ32(TOPAZ_COMMS_CR_CMD_WB_ADDR(0), \
+ mtx_reg_state++, core);
+ COMMS_READ32(TOPAZ_COMMS_CR_CMD_DATA_ADDR(0), \
+ mtx_reg_state++, core);
+ COMMS_READ32(TOPAZ_COMMS_CR_CMD_WORD(0), \
+ mtx_reg_state++, core);
+
+ /* save mtx data memory */
+ if (0 == core) {
+ /*master core*/
+ cur_codec_fw = &topaz_priv->topaz_fw[
+ topaz_priv->topaz_cur_codec * 2];
+ } else {
+ cur_codec_fw = &topaz_priv->topaz_fw[
+ topaz_priv->topaz_cur_codec * 2 \
+ + 1];
+ }
+
+ data_size = cur_codec_fw->data_size / 4;
+ data_size = ((data_size * 4 + (MTX_DMA_BURSTSIZE_BYTES - 1))
+ & ~(MTX_DMA_BURSTSIZE_BYTES - 1)) / 4;
+
+ data_location = cur_codec_fw->data_location
+ & ~(MTX_DMA_BURSTSIZE_BYTES - 1);
+ if (0 != mtx_dma_read(dev, core,
+ data_location,
+ data_size)) {
+ DRM_ERROR("TOPAZ: mtx_dma_read failed!\n");
+ return -1;
+ }
+ pnw_topaz_mmu_flushcache(dev_priv);
+ }
+
+ TOPAZ_WRITE32(TOPAZ_CR_MMU_CONTROL0,
+ 0x2, 0);
+ /*Make sure there is no pending memory request.*/
+ j = 0;
+ for (i = 0; i < 10000; i++) {
+ TOPAZ_READ32(TOPAZ_CR_MMU_MEM_REQ, ®_val, 0);
+ if (reg_val == 0)
+ j++;
+ if (j >= 100)
+ break;
+ }
+ if (i >= 10000)
+ DRM_ERROR("Polling TOPAZ_CR_MMU_MEM_REQ timeout\n");
+
+ topaz_priv->topaz_mtx_saved = 1;
+
+ return 0;
+}
+
+static int mtx_dma_read(struct drm_device *dev, uint32_t core,
+ uint32_t source_addr, uint32_t size)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *)dev->dev_private;
+ struct ttm_buffer_object *target;
+ struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+
+ /* setup mtx DMAC registers to do transfer */
+ MTX_WRITE32(MTX_CR_MTX_SYSC_CDMAA, source_addr, core);
+ MTX_WRITE32(MTX_CR_MTX_SYSC_CDMAC,
+ F_ENCODE(4, MTX_BURSTSIZE) |
+ F_ENCODE(1, MTX_RNW) |
+ F_ENCODE(1, MTX_ENABLE) |
+ F_ENCODE(size, MTX_LENGTH), core);
+
+ /* give the DMAC access to the host memory via BIF */
+ /*TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_DMAC_MODE, 1, 0);*/
+
+ target = topaz_priv->topaz_mtx_data_mem[core];
+ /* transfert the data */
+ if (0 != topaz_dma_transfer(dev_priv, 0, target->offset, 0,
+ MTX_CR_MTX_SYSC_CDMAT,
+ size, core, 1)) {
+ pnw_error_dump_reg(dev_priv, core);
+ return -1;
+ }
+
+ /* wait for it transfer */
+ if (0 != pnw_topaz_wait_for_register(dev_priv,
+ IMG_SOC_DMAC_IRQ_STAT(0) + DMAC_START,
+ F_ENCODE(1, IMG_SOC_TRANSFER_FIN),
+ F_ENCODE(1, IMG_SOC_TRANSFER_FIN))) {
+ pnw_error_dump_reg(dev_priv, core);
+ return -1;
+ }
+
+ /* clear interrupt */
+ DMAC_WRITE32(IMG_SOC_DMAC_IRQ_STAT(0), 0);
+ /* give access back to topaz core */
+ /*TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_DMAC_MODE, 0, 0);*/
+ return 0;
+}
+
+static int mtx_dma_write(struct drm_device *dev, uint32_t core_id)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *)dev->dev_private;
+ struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+ struct pnw_topaz_codec_fw *cur_codec_fw;
+ uint32_t text_size, data_size;
+ uint32_t data_location;
+ int ret = 0;
+
+ if (core_id == 0)/*for master core*/
+ cur_codec_fw = &topaz_priv->topaz_fw[
+ topaz_priv->topaz_cur_codec * 2];
+ else
+ cur_codec_fw = &topaz_priv->topaz_fw[
+ topaz_priv->topaz_cur_codec * 2 + 1];
+
+ PSB_DEBUG_GENERAL("Topaz: Restore codec %s(%d) text sz=%d data sz=%d\n"
+ "data location(0x%x) to core(%d).\n",
+ codec_to_string(topaz_priv->topaz_cur_codec),
+ topaz_priv->topaz_cur_codec,
+ cur_codec_fw->text_size, cur_codec_fw->data_size,
+ cur_codec_fw->data_location, core_id);
+
+ /* # upload text. text_size is byte size*/
+ text_size = cur_codec_fw->text_size / 4;
+ /* adjust transfer sizes of text and data sections to match burst size*/
+ text_size = ((text_size * 4 + (MTX_DMA_BURSTSIZE_BYTES - 1))
+ & ~(MTX_DMA_BURSTSIZE_BYTES - 1)) / 4;
+
+ PSB_DEBUG_GENERAL("TOPAZ: text_size round up to %d\n", text_size);
+ /* setup the MTX to start recieving data:
+ use a register for the transfer which will point to the source
+ (MTX_CR_MTX_SYSC_CDMAT) */
+ /*MTX burst size (4 * 2 * 32bits = 32bytes) should match DMA burst
+ size (2 * 128bits = 32bytes) */
+ /* #.# fill the dst addr */
+
+ MTX_WRITE32(MTX_CR_MTX_SYSC_CDMAA, MTX_DMA_MEMORY_BASE, core_id);
+ MTX_WRITE32(MTX_CR_MTX_SYSC_CDMAC,
+ F_ENCODE(4, MTX_BURSTSIZE) |
+ F_ENCODE(0, MTX_RNW) |
+ F_ENCODE(1, MTX_ENABLE) |
+ F_ENCODE(text_size, MTX_LENGTH), core_id);
+
+ /* #.# set DMAC access to host memory via BIF (deserted)*/
+ /* TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_DMAC_MODE, 1, core_id);*/
+
+ /* #.# transfer the codec */
+ if (0 != topaz_dma_transfer(dev_priv, 0, cur_codec_fw->text->offset, 0,
+ MTX_CR_MTX_SYSC_CDMAT,
+ text_size, core_id, 0)) {
+ pnw_error_dump_reg(dev_priv, core_id);
+ return -1;
+ }
+
+ /* #.# wait dma finish */
+ ret = pnw_topaz_wait_for_register(dev_priv,
+ DMAC_START + IMG_SOC_DMAC_IRQ_STAT(0),
+ F_ENCODE(1, IMG_SOC_TRANSFER_FIN),
+ F_ENCODE(1, IMG_SOC_TRANSFER_FIN));
+ if (ret != 0) {
+ pnw_error_dump_reg(dev_priv, core_id);
+ return -1;
+ }
+
+ /* #.# clear interrupt */
+ DMAC_WRITE32(IMG_SOC_DMAC_IRQ_STAT(0), 0);
+
+ PSB_DEBUG_GENERAL("TOPAZ: firmware text upload complete.\n");
+
+ /* # return access to topaz core (deserted)*/
+ /*TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_DMAC_MODE, 0, core_id);*/
+
+ /* # upload data */
+ data_size = cur_codec_fw->data_size / 4;
+ data_size = ((data_size * 4 + (MTX_DMA_BURSTSIZE_BYTES - 1))
+ & ~(MTX_DMA_BURSTSIZE_BYTES - 1)) / 4;
+
+ data_location = cur_codec_fw->data_location;
+ data_location = data_location & (~(MTX_DMA_BURSTSIZE_BYTES - 1));
+
+ PSB_DEBUG_GENERAL("TOPAZ: data_size round up to %d\n"
+ "data_location round up to 0x%08x\n",
+ data_size, data_location);
+ /* #.# fill the dst addr */
+ MTX_WRITE32(MTX_CR_MTX_SYSC_CDMAA,
+ data_location, core_id);
+ MTX_WRITE32(MTX_CR_MTX_SYSC_CDMAC,
+ F_ENCODE(4, MTX_BURSTSIZE) |
+ F_ENCODE(0, MTX_RNW) |
+ F_ENCODE(1, MTX_ENABLE) |
+ F_ENCODE(data_size, MTX_LENGTH), core_id);
+ /* #.# set DMAC access to host memory via BIF(deserted) */
+ /*TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_DMAC_MODE, 1, core_id);*/
+
+ /* #.# transfer the codec */
+ if (0 != topaz_dma_transfer(dev_priv, 0,
+ topaz_priv->topaz_mtx_data_mem[core_id]->offset,
+ 0,
+ MTX_CR_MTX_SYSC_CDMAT, data_size, core_id, 0)) {
+ pnw_error_dump_reg(dev_priv, core_id);
+ return -1;
+ }
+
+ /* #.# wait dma finish */
+ ret = pnw_topaz_wait_for_register(dev_priv,
+ DMAC_START + IMG_SOC_DMAC_IRQ_STAT(0),
+ F_ENCODE(1, IMG_SOC_TRANSFER_FIN),
+ F_ENCODE(1, IMG_SOC_TRANSFER_FIN));
+ if (ret != 0) {
+ pnw_error_dump_reg(dev_priv, core_id);
+ return -1;
+ }
+ /* #.# clear interrupt */
+ DMAC_WRITE32(IMG_SOC_DMAC_IRQ_STAT(0), 0);
+
+ PSB_DEBUG_GENERAL("TOPAZ: firmware text upload complete.\n");
+
+ /*TOPAZ_WRITE32(TOPAZ_CR_IMG_TOPAZ_DMAC_MODE, 0, 0);*/
+ return 0;
+}
+
+
+void pnw_reset_fw_status(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *)dev->dev_private;
+ struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+
+ /*Before end the session, mark firmware MTX data as invalid.*/
+ topaz_priv->topaz_mtx_saved = 0;
+
+}
--- /dev/null
+/**************************************************************************
+ * Copyright (c) 2007, Intel Corporation.
+ *
+ * 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 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.
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellstrom <thomas-at-tungstengraphics.com>
+ */
+#include "ttm/ttm_placement.h"
+#include "ttm/ttm_execbuf_util.h"
+#include "psb_ttm_fence_api.h"
+#include <drm/drmP.h>
+#include "psb_drv.h"
+#include "psb_schedule.h"
+
+#define DRM_MEM_TTM 26
+
+struct drm_psb_ttm_backend {
+ struct ttm_backend base;
+ struct page **pages;
+ unsigned int desired_tile_stride;
+ unsigned int hw_tile_stride;
+ int mem_type;
+ unsigned long offset;
+ unsigned long num_pages;
+};
+
+/*
+ * MSVDX/TOPAZ GPU virtual space looks like this
+ * (We currently use only one MMU context).
+ * PSB_MEM_MMU_START: from 0x00000000~0xe000000, for generic buffers
+ * TTM_PL_CI: from 0xe0000000+half GTT space, for camear/video buffer sharing
+ * TTM_PL_RAR: from TTM_PL_CI+CI size, for RAR/video buffer sharing
+ * TTM_PL_TT: from TTM_PL_RAR+RAR size, for buffers need to mapping into GTT
+ */
+static int psb_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
+ struct ttm_mem_type_manager *man)
+{
+
+ struct drm_psb_private *dev_priv =
+ container_of(bdev, struct drm_psb_private, bdev);
+ struct psb_gtt *pg = dev_priv->pg;
+
+ switch (type) {
+ case TTM_PL_SYSTEM:
+ man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
+ man->available_caching = TTM_PL_FLAG_CACHED |
+ TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC;
+ man->default_caching = TTM_PL_FLAG_CACHED;
+ break;
+ case DRM_PSB_MEM_MMU:
+ man->func = &ttm_bo_manager_func;
+ man->flags = TTM_MEMTYPE_FLAG_MAPPABLE |
+ TTM_MEMTYPE_FLAG_CMA;
+ man->gpu_offset = PSB_MEM_MMU_START;
+ man->available_caching = TTM_PL_FLAG_CACHED |
+ TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC;
+ man->default_caching = TTM_PL_FLAG_WC;
+ break;
+ case TTM_PL_CI:
+ man->func = &ttm_bo_manager_func;
+ man->flags = TTM_MEMTYPE_FLAG_MAPPABLE |
+ TTM_MEMTYPE_FLAG_FIXED;
+ man->gpu_offset = pg->mmu_gatt_start + (pg->ci_start);
+ man->available_caching = TTM_PL_FLAG_UNCACHED;
+ man->default_caching = TTM_PL_FLAG_UNCACHED;
+ break;
+ case TTM_PL_RAR: /* Unmappable RAR memory */
+ man->func = &ttm_bo_manager_func;
+ man->flags = TTM_MEMTYPE_FLAG_MAPPABLE |
+ TTM_MEMTYPE_FLAG_FIXED;
+ man->available_caching = TTM_PL_FLAG_UNCACHED;
+ man->default_caching = TTM_PL_FLAG_UNCACHED;
+ man->gpu_offset = pg->mmu_gatt_start + (pg->rar_start);
+ break;
+ case TTM_PL_TT: /* Mappable GATT memory */
+ man->func = &ttm_bo_manager_func;
+#ifdef PSB_WORKING_HOST_MMU_ACCESS
+ man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
+#else
+ man->flags = TTM_MEMTYPE_FLAG_MAPPABLE |
+ TTM_MEMTYPE_FLAG_CMA;
+#endif
+ man->available_caching = TTM_PL_FLAG_CACHED |
+ TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC;
+ man->default_caching = TTM_PL_FLAG_WC;
+ man->gpu_offset = pg->mmu_gatt_start + (pg->rar_start + dev_priv->rar_region_size);
+ break;
+ default:
+ DRM_ERROR("Unsupported memory type %u\n", (unsigned) type);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+
+static void psb_evict_mask(struct ttm_buffer_object *bo, struct ttm_placement* placement)
+{
+ static uint32_t cur_placement;
+
+ cur_placement = bo->mem.placement & ~TTM_PL_MASK_MEM;
+ cur_placement |= TTM_PL_FLAG_SYSTEM;
+
+ placement->fpfn = 0;
+ placement->lpfn = 0;
+ placement->num_placement = 1;
+ placement->placement = &cur_placement;
+ placement->num_busy_placement = 0;
+ placement->busy_placement = NULL;
+
+ /* all buffers evicted to system memory */
+ /* return cur_placement | TTM_PL_FLAG_SYSTEM; */
+}
+
+static int psb_invalidate_caches(struct ttm_bo_device *bdev,
+ uint32_t placement)
+{
+ return 0;
+}
+
+static int psb_move_blit(struct ttm_buffer_object *bo,
+ bool evict, bool no_wait,
+ struct ttm_mem_reg *new_mem)
+{
+ BUG();
+ return 0;
+}
+
+/*
+ * Flip destination ttm into GATT,
+ * then blit and subsequently move out again.
+ */
+
+static int psb_move_flip(struct ttm_buffer_object *bo,
+ bool evict, bool interruptible, bool no_wait,
+ struct ttm_mem_reg *new_mem)
+{
+ /*struct ttm_bo_device *bdev = bo->bdev;*/
+ struct ttm_mem_reg tmp_mem;
+ int ret;
+ struct ttm_placement placement;
+ uint32_t flags = TTM_PL_FLAG_TT;
+
+ tmp_mem = *new_mem;
+ tmp_mem.mm_node = NULL;
+
+ placement.fpfn = 0;
+ placement.lpfn = 0;
+ placement.num_placement = 1;
+ placement.placement = &flags;
+ placement.num_busy_placement = 0; /* FIXME */
+ placement.busy_placement = NULL;
+
+ ret = ttm_bo_mem_space(bo, &placement, &tmp_mem, interruptible, false, no_wait);
+ if (ret)
+ return ret;
+ ret = ttm_tt_bind(bo->ttm, &tmp_mem);
+ if (ret)
+ goto out_cleanup;
+ ret = psb_move_blit(bo, true, no_wait, &tmp_mem);
+ if (ret)
+ goto out_cleanup;
+
+ ret = ttm_bo_move_ttm(bo, evict, false, no_wait, new_mem);
+out_cleanup:
+ if (tmp_mem.mm_node) {
+ /*spin_lock(&bdev->lru_lock);*/ // lru_lock is removed from upstream TTM
+ drm_mm_put_block(tmp_mem.mm_node);
+ tmp_mem.mm_node = NULL;
+ /*spin_unlock(&bdev->lru_lock);*/
+ }
+ return ret;
+}
+
+static int psb_move(struct ttm_buffer_object *bo,
+ bool evict, bool interruptible, bool no_wait_reserve,
+ bool no_wait, struct ttm_mem_reg *new_mem)
+{
+ struct ttm_mem_reg *old_mem = &bo->mem;
+
+ if ((old_mem->mem_type == TTM_PL_RAR) ||
+ (new_mem->mem_type == TTM_PL_RAR)) {
+ if (old_mem->mm_node) {
+ spin_lock(&bo->glob->lru_lock);
+ drm_mm_put_block(old_mem->mm_node);
+ spin_unlock(&bo->glob->lru_lock);
+ }
+ old_mem->mm_node = NULL;
+ *old_mem = *new_mem;
+ } else if (old_mem->mem_type == TTM_PL_SYSTEM) {
+ return ttm_bo_move_memcpy(bo, evict, false, no_wait, new_mem);
+ } else if (new_mem->mem_type == TTM_PL_SYSTEM) {
+ int ret = psb_move_flip(bo, evict, interruptible,
+ no_wait, new_mem);
+ if (unlikely(ret != 0)) {
+ if (ret == -ERESTART)
+ return ret;
+ else
+ return ttm_bo_move_memcpy(bo, evict, false, no_wait,
+ new_mem);
+ }
+ } else {
+ if (psb_move_blit(bo, evict, no_wait, new_mem))
+ return ttm_bo_move_memcpy(bo, evict, false, no_wait,
+ new_mem);
+ }
+ return 0;
+}
+
+/* REVISIT: is there a need to use the dma_addrs or other parameters? */
+static int drm_psb_tbe_populate(struct ttm_backend *backend,
+ unsigned long num_pages,
+ struct page **pages,
+ struct page *dummy_read_page,
+ dma_addr_t *dma_addrs)
+{
+ struct drm_psb_ttm_backend *psb_be =
+ container_of(backend, struct drm_psb_ttm_backend, base);
+
+ psb_be->pages = pages;
+ return 0;
+}
+
+static int drm_psb_tbe_unbind(struct ttm_backend *backend)
+{
+ struct ttm_bo_device *bdev = backend->bdev;
+ struct drm_psb_private *dev_priv =
+ container_of(bdev, struct drm_psb_private, bdev);
+ struct drm_psb_ttm_backend *psb_be =
+ container_of(backend, struct drm_psb_ttm_backend, base);
+ struct psb_mmu_pd *pd = psb_mmu_get_default_pd(dev_priv->mmu);
+ /* struct ttm_mem_type_manager *man = &bdev->man[psb_be->mem_type]; */
+
+ if (psb_be->mem_type == TTM_PL_TT) {
+ uint32_t gatt_p_offset =
+ (psb_be->offset - dev_priv->pg->mmu_gatt_start) >> PAGE_SHIFT;
+
+ (void) psb_gtt_remove_pages(dev_priv->pg, gatt_p_offset,
+ psb_be->num_pages,
+ psb_be->desired_tile_stride,
+ psb_be->hw_tile_stride, 0);
+ }
+
+ psb_mmu_remove_pages(pd, psb_be->offset,
+ psb_be->num_pages,
+ psb_be->desired_tile_stride,
+ psb_be->hw_tile_stride);
+
+ return 0;
+}
+
+static int drm_psb_tbe_bind(struct ttm_backend *backend,
+ struct ttm_mem_reg *bo_mem)
+{
+ struct ttm_bo_device *bdev = backend->bdev;
+ struct drm_psb_private *dev_priv =
+ container_of(bdev, struct drm_psb_private, bdev);
+ struct drm_psb_ttm_backend *psb_be =
+ container_of(backend, struct drm_psb_ttm_backend, base);
+ struct psb_mmu_pd *pd = psb_mmu_get_default_pd(dev_priv->mmu);
+ struct ttm_mem_type_manager *man = &bdev->man[bo_mem->mem_type];
+ int type;
+ int ret = 0;
+
+ psb_be->mem_type = bo_mem->mem_type;
+ psb_be->num_pages = bo_mem->num_pages;
+ psb_be->desired_tile_stride = 0;
+ psb_be->hw_tile_stride = 0;
+ psb_be->offset = (bo_mem->start << PAGE_SHIFT) + man->gpu_offset;
+
+ type =
+ (bo_mem->
+ placement & TTM_PL_FLAG_CACHED) ? PSB_MMU_CACHED_MEMORY : 0;
+
+ if (psb_be->mem_type == TTM_PL_TT) {
+ uint32_t gatt_p_offset =
+ (psb_be->offset - dev_priv->pg->mmu_gatt_start) >> PAGE_SHIFT;
+
+ ret = psb_gtt_insert_pages(dev_priv->pg, psb_be->pages,
+ gatt_p_offset,
+ psb_be->num_pages,
+ psb_be->desired_tile_stride,
+ psb_be->hw_tile_stride, type);
+ }
+
+ ret = psb_mmu_insert_pages(pd, psb_be->pages,
+ psb_be->offset, psb_be->num_pages,
+ psb_be->desired_tile_stride,
+ psb_be->hw_tile_stride, type);
+ if (ret)
+ goto out_err;
+
+ return 0;
+out_err:
+ drm_psb_tbe_unbind(backend);
+ return ret;
+
+}
+
+static void drm_psb_tbe_clear(struct ttm_backend *backend)
+{
+ struct drm_psb_ttm_backend *psb_be =
+ container_of(backend, struct drm_psb_ttm_backend, base);
+
+ psb_be->pages = NULL;
+ return;
+}
+
+static void drm_psb_tbe_destroy(struct ttm_backend *backend)
+{
+ struct drm_psb_ttm_backend *psb_be =
+ container_of(backend, struct drm_psb_ttm_backend, base);
+
+ if (backend)
+ kfree(psb_be);
+}
+
+static struct ttm_backend_func psb_ttm_backend = {
+ .populate = drm_psb_tbe_populate,
+ .clear = drm_psb_tbe_clear,
+ .bind = drm_psb_tbe_bind,
+ .unbind = drm_psb_tbe_unbind,
+ .destroy = drm_psb_tbe_destroy,
+};
+
+static struct ttm_backend *drm_psb_tbe_init(struct ttm_bo_device *bdev) {
+ struct drm_psb_ttm_backend *psb_be;
+
+ psb_be = kzalloc(sizeof(*psb_be), GFP_KERNEL);
+ if (!psb_be)
+ return NULL;
+ psb_be->pages = NULL;
+ psb_be->base.func = &psb_ttm_backend;
+ psb_be->base.bdev = bdev;
+ return &psb_be->base;
+}
+
+static int psb_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
+{
+ struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
+ struct drm_psb_private *dev_priv =
+ container_of(bdev, struct drm_psb_private, bdev);
+ struct psb_gtt *pg = dev_priv->pg;
+
+ mem->bus.addr = NULL;
+ mem->bus.offset = 0;
+ mem->bus.size = mem->num_pages << PAGE_SHIFT;
+ mem->bus.base = 0;
+ mem->bus.is_iomem = false;
+ if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE))
+ return -EINVAL;
+ switch (mem->mem_type) {
+ case TTM_PL_SYSTEM:
+ /* system memory */
+ return 0;
+ case TTM_PL_TT:
+ mem->bus.offset = mem->start << PAGE_SHIFT;
+ mem->bus.base = pg->gatt_start;
+ mem->bus.is_iomem = false; /* Don't know whether it is IO_MEM, this flag used in vm_fault handle */
+ break;
+ case DRM_PSB_MEM_MMU:
+ mem->bus.offset = mem->start << PAGE_SHIFT;
+ mem->bus.base = 0x00000000;
+ break;
+ case TTM_PL_CI:
+ mem->bus.offset = mem->start << PAGE_SHIFT;
+ mem->bus.base = dev_priv->ci_region_start;;
+ mem->bus.is_iomem = true;
+ break;
+ case TTM_PL_RAR:
+ mem->bus.offset = mem->start << PAGE_SHIFT;
+ mem->bus.base = dev_priv->rar_region_start;;
+ mem->bus.is_iomem = true;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static void psb_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
+{
+}
+
+/*
+ * Use this memory type priority if no eviction is needed.
+ */
+/*
+static uint32_t psb_mem_prios[] = {
+ TTM_PL_CI,
+ TTM_PL_RAR,
+ TTM_PL_TT,
+ DRM_PSB_MEM_MMU,
+ TTM_PL_SYSTEM
+};
+*/
+/*
+ * Use this memory type priority if need to evict.
+ */
+/*
+static uint32_t psb_busy_prios[] = {
+ TTM_PL_TT,
+ TTM_PL_CI,
+ TTM_PL_RAR,
+ DRM_PSB_MEM_MMU,
+ TTM_PL_SYSTEM
+};
+*/
+struct ttm_bo_driver psb_ttm_bo_driver = {
+ /*
+ .mem_type_prio = psb_mem_prios,
+ .mem_busy_prio = psb_busy_prios,
+ .num_mem_type_prio = ARRAY_SIZE(psb_mem_prios),
+ .num_mem_busy_prio = ARRAY_SIZE(psb_busy_prios),
+ */
+ .create_ttm_backend_entry = &drm_psb_tbe_init,
+ .invalidate_caches = &psb_invalidate_caches,
+ .init_mem_type = &psb_init_mem_type,
+ .evict_flags = &psb_evict_mask,
+ .move = &psb_move,
+ .verify_access = &psb_verify_access,
+ .sync_obj_signaled = &ttm_fence_sync_obj_signaled,
+ .sync_obj_wait = &ttm_fence_sync_obj_wait,
+ .sync_obj_flush = &ttm_fence_sync_obj_flush,
+ .sync_obj_unref = &ttm_fence_sync_obj_unref,
+ .sync_obj_ref = &ttm_fence_sync_obj_ref,
+ .io_mem_reserve = &psb_ttm_io_mem_reserve,
+ .io_mem_free = &psb_ttm_io_mem_free
+};
--- /dev/null
+/*
+ * Copyright (c) 2007, Intel Corporation.
+ * 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 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.
+ *
+ *
+ * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
+ */
+
+#include <drm/drmP.h>
+#include "psb_drv.h"
+#include "psb_msvdx.h"
+#include "pnw_topaz.h"
+
+static void psb_fence_poll(struct ttm_fence_device *fdev,
+ uint32_t fence_class, uint32_t waiting_types)
+{
+ struct drm_psb_private *dev_priv =
+ container_of(fdev, struct drm_psb_private, fdev);
+ uint32_t sequence = 0;
+ struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+
+
+ if (unlikely(!dev_priv))
+ return;
+
+ if (waiting_types == 0)
+ return;
+
+ switch (fence_class) {
+ case PSB_ENGINE_VIDEO:
+ sequence = msvdx_priv->msvdx_current_sequence;
+ break;
+ case LNC_ENGINE_ENCODE:
+ sequence = *((uint32_t *)
+ ((struct pnw_topaz_private *)dev_priv->topaz_private)->topaz_sync_addr + 1);
+ break;
+ default:
+ break;
+ }
+
+ /* DRM_ERROR("Polling fence sequence, got 0x%08x\n", sequence); */
+ ttm_fence_handler(fdev, fence_class, sequence,
+ _PSB_FENCE_TYPE_EXE, 0);
+}
+
+void psb_fence_error(struct drm_device *dev,
+ uint32_t fence_class,
+ uint32_t sequence, uint32_t type, int error)
+{
+ struct drm_psb_private *dev_priv = psb_priv(dev);
+ struct ttm_fence_device *fdev = &dev_priv->fdev;
+ unsigned long irq_flags;
+ struct ttm_fence_class_manager *fc =
+ &fdev->fence_class[fence_class];
+
+ BUG_ON(fence_class >= PSB_NUM_ENGINES);
+ write_lock_irqsave(&fc->lock, irq_flags);
+ ttm_fence_handler(fdev, fence_class, sequence, type, error);
+ write_unlock_irqrestore(&fc->lock, irq_flags);
+}
+
+int psb_fence_emit_sequence(struct ttm_fence_device *fdev,
+ uint32_t fence_class,
+ uint32_t flags, uint32_t *sequence,
+ unsigned long *timeout_jiffies)
+{
+ struct drm_psb_private *dev_priv =
+ container_of(fdev, struct drm_psb_private, fdev);
+ uint32_t seq = 0;
+
+ if (!dev_priv)
+ return -EINVAL;
+
+ if (fence_class >= PSB_NUM_ENGINES)
+ return -EINVAL;
+
+ switch (fence_class) {
+ case PSB_ENGINE_VIDEO:
+ spin_lock(&dev_priv->sequence_lock);
+ seq = dev_priv->sequence[fence_class]++;
+ spin_unlock(&dev_priv->sequence_lock);
+ break;
+ case LNC_ENGINE_ENCODE:
+ spin_lock(&dev_priv->sequence_lock);
+ seq = dev_priv->sequence[fence_class]++;
+ spin_unlock(&dev_priv->sequence_lock);
+ break;
+ default:
+ DRM_ERROR("Unexpected fence class\n");
+ return -EINVAL;
+ }
+
+ *sequence = seq;
+ *timeout_jiffies = jiffies + DRM_HZ * 3;
+
+ return 0;
+}
+
+static void psb_fence_lockup(struct ttm_fence_object *fence,
+ uint32_t fence_types)
+{
+ struct ttm_fence_device *fdev = fence->fdev;
+ struct ttm_fence_class_manager *fc = ttm_fence_fc(fence);
+ struct drm_psb_private *dev_priv =
+ container_of(fdev, struct drm_psb_private, fdev);
+ struct drm_device *dev = (struct drm_device *)dev_priv->dev;
+
+ if (fence->fence_class == LNC_ENGINE_ENCODE) {
+ DRM_ERROR("TOPAZ timeout (probable lockup) detected, flush queued cmdbuf");
+
+ write_lock(&fc->lock);
+ pnw_topaz_handle_timeout(fence->fdev);
+ ttm_fence_handler(fence->fdev, fence->fence_class,
+ fence->sequence, fence_types, -EBUSY);
+ write_unlock(&fc->lock);
+ } else if (fence->fence_class == PSB_ENGINE_VIDEO) {
+ struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+
+ DRM_ERROR("MSVDX timeout (probable lockup) detected, flush queued cmdbuf");
+
+ psb_msvdx_flush_cmd_queue(dev);
+
+ write_lock(&fc->lock);
+ ttm_fence_handler(fence->fdev, fence->fence_class,
+ fence->sequence, fence_types, -EBUSY);
+ write_unlock(&fc->lock);
+
+ msvdx_priv->msvdx_needs_reset = 1;
+ } else
+ DRM_ERROR("Unsupported fence class\n");
+}
+
+void psb_fence_handler(struct drm_device *dev, uint32_t fence_class)
+{
+ struct drm_psb_private *dev_priv = psb_priv(dev);
+ struct ttm_fence_device *fdev = &dev_priv->fdev;
+ struct ttm_fence_class_manager *fc =
+ &fdev->fence_class[fence_class];
+ unsigned long irq_flags;
+
+ write_lock_irqsave(&fc->lock, irq_flags);
+ psb_fence_poll(fdev, fence_class, fc->waiting_types);
+ write_unlock_irqrestore(&fc->lock, irq_flags);
+}
+
+
+static struct ttm_fence_driver psb_ttm_fence_driver = {
+ .has_irq = NULL,
+ .emit = psb_fence_emit_sequence,
+ .flush = NULL,
+ .poll = psb_fence_poll,
+ .needed_flush = NULL,
+ .wait = NULL,
+ .signaled = NULL,
+ .lockup = psb_fence_lockup,
+};
+
+int psb_ttm_fence_device_init(struct ttm_fence_device *fdev)
+{
+ struct drm_psb_private *dev_priv =
+ container_of(fdev, struct drm_psb_private, fdev);
+ struct ttm_fence_class_init fci = {.wrap_diff = (1 << 30),
+ .flush_diff = (1 << 29),
+ .sequence_mask = 0xFFFFFFFF
+ };
+
+ return ttm_fence_device_init(PSB_NUM_ENGINES,
+ dev_priv->mem_global_ref.object,
+ fdev, &fci, 1,
+ &psb_ttm_fence_driver);
+}
--- /dev/null
+/**************************************************************************
+ * Copyright (c) 2007, Intel Corporation.
+ *
+ * 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 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.
+ *
+ **************************************************************************/
+#include <drm/drmP.h>
+#include "psb_drv.h"
+#include "psb_reg.h"
+#include "psb_msvdx.h"
+
+/*
+ * Code for the SGX MMU:
+ */
+
+/*
+ * clflush on one processor only:
+ * clflush should apparently flush the cache line on all processors in an
+ * SMP system.
+ */
+
+/*
+ * kmap atomic:
+ * The usage of the slots must be completely encapsulated within a spinlock, and
+ * no other functions that may be using the locks for other purposed may be
+ * called from within the locked region.
+ * Since the slots are per processor, this will guarantee that we are the only
+ * user.
+ */
+
+/*
+ * TODO: Inserting ptes from an interrupt handler:
+ * This may be desirable for some SGX functionality where the GPU can fault in
+ * needed pages. For that, we need to make an atomic insert_pages function, that
+ * may fail.
+ * If it fails, the caller need to insert the page using a workqueue function,
+ * but on average it should be fast.
+ */
+
+struct psb_mmu_driver {
+ /* protects driver- and pd structures. Always take in read mode
+ * before taking the page table spinlock.
+ */
+ struct rw_semaphore sem;
+
+ /* protects page tables, directory tables and pt tables.
+ * and pt structures.
+ */
+ spinlock_t lock;
+
+ atomic_t needs_tlbflush;
+
+ uint8_t __iomem *register_map;
+ struct psb_mmu_pd *default_pd;
+ /*uint32_t bif_ctrl;*/
+ int has_clflush;
+ int clflush_add;
+ unsigned long clflush_mask;
+
+ struct drm_psb_private *dev_priv;
+};
+
+struct psb_mmu_pd;
+
+struct psb_mmu_pt {
+ struct psb_mmu_pd *pd;
+ uint32_t index;
+ uint32_t count;
+ struct page *p;
+ uint32_t *v;
+};
+
+struct psb_mmu_pd {
+ struct psb_mmu_driver *driver;
+ int hw_context;
+ struct psb_mmu_pt **tables;
+ struct page *p;
+ struct page *dummy_pt;
+ struct page *dummy_page;
+ uint32_t pd_mask;
+ uint32_t invalid_pde;
+ uint32_t invalid_pte;
+};
+
+static inline uint32_t psb_mmu_pt_index(uint32_t offset)
+{
+ return (offset >> PSB_PTE_SHIFT) & 0x3FF;
+}
+
+static inline uint32_t psb_mmu_pd_index(uint32_t offset)
+{
+ return offset >> PSB_PDE_SHIFT;
+}
+
+#if defined(CONFIG_X86)
+static inline void psb_clflush(void *addr)
+{
+ __asm__ __volatile__("clflush (%0)\n" : : "r"(addr) : "memory");
+}
+
+static inline void psb_mmu_clflush(struct psb_mmu_driver *driver,
+ void *addr)
+{
+ if (!driver->has_clflush)
+ return;
+
+ mb();
+ psb_clflush(addr);
+ mb();
+}
+
+static void psb_page_clflush(struct psb_mmu_driver *driver, struct page* page)
+{
+ uint32_t clflush_add = driver->clflush_add >> PAGE_SHIFT;
+ uint32_t clflush_count = PAGE_SIZE / clflush_add;
+ int i;
+ uint8_t *clf;
+
+ clf = kmap_atomic(page, KM_USER0);
+ mb();
+ for (i = 0; i < clflush_count; ++i) {
+ psb_clflush(clf);
+ clf += clflush_add;
+ }
+ mb();
+ kunmap_atomic(clf, KM_USER0);
+}
+
+static void psb_pages_clflush(struct psb_mmu_driver *driver, struct page *page[], unsigned long num_pages)
+{
+ int i;
+
+ if (!driver->has_clflush)
+ return ;
+
+ for (i = 0; i < num_pages; i++)
+ psb_page_clflush(driver, *page++);
+}
+#else
+
+static inline void psb_mmu_clflush(struct psb_mmu_driver *driver,
+ void *addr)
+{
+ ;
+}
+
+static void psb_pages_clflush(struct psb_mmu_driver *driver, struct page *page[], unsigned long num_pages)
+{
+ printk("Dumy psb_pages_clflush\n");
+}
+
+#endif
+
+static void psb_mmu_flush_pd_locked(struct psb_mmu_driver *driver,
+ int force)
+{
+ if (atomic_read(&driver->needs_tlbflush) || force) {
+ if (driver->dev_priv) {
+ atomic_set(&driver->dev_priv->msvdx_mmu_invaldc, 1);
+ atomic_set(&driver->dev_priv->topaz_mmu_invaldc, 1);
+ }
+ }
+ atomic_set(&driver->needs_tlbflush, 0);
+}
+
+static void psb_mmu_flush_pd(struct psb_mmu_driver *driver, int force)
+{
+ down_write(&driver->sem);
+ psb_mmu_flush_pd_locked(driver, force);
+ up_write(&driver->sem);
+}
+
+void psb_mmu_flush(struct psb_mmu_driver *driver, int rc_prot)
+{
+ if (rc_prot)
+ down_write(&driver->sem);
+ if (driver->dev_priv) {
+ atomic_set(&driver->dev_priv->msvdx_mmu_invaldc, 1);
+ atomic_set(&driver->dev_priv->topaz_mmu_invaldc, 1);
+ }
+ if (rc_prot)
+ up_write(&driver->sem);
+}
+
+void psb_mmu_set_pd_context(struct psb_mmu_pd *pd, int hw_context)
+{
+ /*ttm_tt_cache_flush(&pd->p, 1);*/
+ psb_pages_clflush(pd->driver, &pd->p, 1);
+ down_write(&pd->driver->sem);
+ wmb();
+ psb_mmu_flush_pd_locked(pd->driver, 1);
+ pd->hw_context = hw_context;
+ up_write(&pd->driver->sem);
+
+}
+
+static inline unsigned long psb_pd_addr_end(unsigned long addr,
+ unsigned long end)
+{
+
+ addr = (addr + PSB_PDE_MASK + 1) & ~PSB_PDE_MASK;
+ return (addr < end) ? addr : end;
+}
+
+static inline uint32_t psb_mmu_mask_pte(uint32_t pfn, int type)
+{
+ uint32_t mask = PSB_PTE_VALID;
+
+ if (type & PSB_MMU_CACHED_MEMORY)
+ mask |= PSB_PTE_CACHED;
+ if (type & PSB_MMU_RO_MEMORY)
+ mask |= PSB_PTE_RO;
+ if (type & PSB_MMU_WO_MEMORY)
+ mask |= PSB_PTE_WO;
+
+ return (pfn << PAGE_SHIFT) | mask;
+}
+
+struct psb_mmu_pd *psb_mmu_alloc_pd(struct psb_mmu_driver *driver,
+ int trap_pagefaults, int invalid_type) {
+ struct psb_mmu_pd *pd = kmalloc(sizeof(*pd), GFP_KERNEL);
+ uint32_t *v;
+ int i;
+
+ if (!pd)
+ return NULL;
+
+ pd->p = alloc_page(GFP_DMA32);
+ if (!pd->p)
+ goto out_err1;
+ pd->dummy_pt = alloc_page(GFP_DMA32);
+ if (!pd->dummy_pt)
+ goto out_err2;
+ pd->dummy_page = alloc_page(GFP_DMA32);
+ if (!pd->dummy_page)
+ goto out_err3;
+
+ if (!trap_pagefaults) {
+ pd->invalid_pde =
+ psb_mmu_mask_pte(page_to_pfn(pd->dummy_pt),
+ invalid_type);
+ pd->invalid_pte =
+ psb_mmu_mask_pte(page_to_pfn(pd->dummy_page),
+ invalid_type);
+ } else {
+ pd->invalid_pde = 0;
+ pd->invalid_pte = 0;
+ }
+
+ v = kmap(pd->dummy_pt);
+ for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i)
+ v[i] = pd->invalid_pte;
+
+ kunmap(pd->dummy_pt);
+
+ v = kmap(pd->p);
+ for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i)
+ v[i] = pd->invalid_pde;
+
+ kunmap(pd->p);
+
+ clear_page(kmap(pd->dummy_page));
+ kunmap(pd->dummy_page);
+
+ pd->tables = vmalloc_user(sizeof(struct psb_mmu_pt *) * 1024);
+ if (!pd->tables)
+ goto out_err4;
+
+ pd->hw_context = -1;
+ pd->pd_mask = PSB_PTE_VALID;
+ pd->driver = driver;
+
+ return pd;
+
+out_err4:
+ __free_page(pd->dummy_page);
+out_err3:
+ __free_page(pd->dummy_pt);
+out_err2:
+ __free_page(pd->p);
+out_err1:
+ kfree(pd);
+ return NULL;
+}
+
+static void psb_mmu_free_pt(struct psb_mmu_pt *pt)
+{
+ __free_page(pt->p);
+ kfree(pt);
+}
+
+void psb_mmu_free_pagedir(struct psb_mmu_pd *pd)
+{
+ struct psb_mmu_driver *driver = pd->driver;
+ struct psb_mmu_pt *pt;
+ int i;
+
+ down_write(&driver->sem);
+ if (pd->hw_context != -1)
+ psb_mmu_flush_pd_locked(driver, 1);
+
+ /* Should take the spinlock here, but we don't need to do that
+ since we have the semaphore in write mode. */
+
+ for (i = 0; i < 1024; ++i) {
+ pt = pd->tables[i];
+ if (pt)
+ psb_mmu_free_pt(pt);
+ }
+
+ vfree(pd->tables);
+ __free_page(pd->dummy_page);
+ __free_page(pd->dummy_pt);
+ __free_page(pd->p);
+ kfree(pd);
+ up_write(&driver->sem);
+}
+
+static struct psb_mmu_pt *psb_mmu_alloc_pt(struct psb_mmu_pd *pd) {
+ struct psb_mmu_pt *pt = kmalloc(sizeof(*pt), GFP_KERNEL);
+ void *v;
+ uint32_t clflush_add = pd->driver->clflush_add >> PAGE_SHIFT;
+ uint32_t clflush_count = PAGE_SIZE / clflush_add;
+ spinlock_t *lock = &pd->driver->lock;
+ uint8_t *clf;
+ uint32_t *ptes;
+ int i;
+
+ if (!pt)
+ return NULL;
+
+ pt->p = alloc_page(GFP_DMA32);
+ if (!pt->p) {
+ kfree(pt);
+ return NULL;
+ }
+
+ spin_lock(lock);
+
+ v = kmap_atomic(pt->p, KM_USER0);
+ clf = (uint8_t *) v;
+ ptes = (uint32_t *) v;
+ for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i)
+ *ptes++ = pd->invalid_pte;
+
+
+#if defined(CONFIG_X86)
+ if (pd->driver->has_clflush && pd->hw_context != -1) {
+ mb();
+ for (i = 0; i < clflush_count; ++i) {
+ psb_clflush(clf);
+ clf += clflush_add;
+ }
+ mb();
+ }
+#endif
+ kunmap_atomic(v, KM_USER0);
+ spin_unlock(lock);
+
+ pt->count = 0;
+ pt->pd = pd;
+ pt->index = 0;
+
+ return pt;
+}
+
+static struct psb_mmu_pt *psb_mmu_pt_alloc_map_lock(struct psb_mmu_pd *pd,
+ unsigned long addr) {
+ uint32_t index = psb_mmu_pd_index(addr);
+ struct psb_mmu_pt *pt;
+ uint32_t *v;
+ spinlock_t *lock = &pd->driver->lock;
+
+ spin_lock(lock);
+ pt = pd->tables[index];
+ while (!pt) {
+ spin_unlock(lock);
+ pt = psb_mmu_alloc_pt(pd);
+ if (!pt)
+ return NULL;
+ spin_lock(lock);
+
+ if (pd->tables[index]) {
+ spin_unlock(lock);
+ psb_mmu_free_pt(pt);
+ spin_lock(lock);
+ pt = pd->tables[index];
+ continue;
+ }
+
+ v = kmap_atomic(pd->p, KM_USER0);
+ pd->tables[index] = pt;
+ v[index] = (page_to_pfn(pt->p) << 12) | pd->pd_mask;
+ pt->index = index;
+ kunmap_atomic((void *) v, KM_USER0);
+
+ if (pd->hw_context != -1) {
+ psb_mmu_clflush(pd->driver, (void *) &v[index]);
+ atomic_set(&pd->driver->needs_tlbflush, 1);
+ }
+ }
+ pt->v = kmap_atomic(pt->p, KM_USER0);
+ return pt;
+}
+
+static struct psb_mmu_pt *psb_mmu_pt_map_lock(struct psb_mmu_pd *pd,
+ unsigned long addr) {
+ uint32_t index = psb_mmu_pd_index(addr);
+ struct psb_mmu_pt *pt;
+ spinlock_t *lock = &pd->driver->lock;
+
+ spin_lock(lock);
+ pt = pd->tables[index];
+ if (!pt) {
+ spin_unlock(lock);
+ return NULL;
+ }
+ pt->v = kmap_atomic(pt->p, KM_USER0);
+ return pt;
+}
+
+static void psb_mmu_pt_unmap_unlock(struct psb_mmu_pt *pt)
+{
+ struct psb_mmu_pd *pd = pt->pd;
+ uint32_t *v;
+
+ kunmap_atomic(pt->v, KM_USER0);
+ if (pt->count == 0) {
+ v = kmap_atomic(pd->p, KM_USER0);
+ v[pt->index] = pd->invalid_pde;
+ pd->tables[pt->index] = NULL;
+
+ if (pd->hw_context != -1) {
+ psb_mmu_clflush(pd->driver,
+ (void *) &v[pt->index]);
+ atomic_set(&pd->driver->needs_tlbflush, 1);
+ }
+ kunmap_atomic(pt->v, KM_USER0);
+ spin_unlock(&pd->driver->lock);
+ psb_mmu_free_pt(pt);
+ return;
+ }
+ spin_unlock(&pd->driver->lock);
+}
+
+static inline void psb_mmu_set_pte(struct psb_mmu_pt *pt,
+ unsigned long addr, uint32_t pte)
+{
+ pt->v[psb_mmu_pt_index(addr)] = pte;
+}
+
+static inline void psb_mmu_invalidate_pte(struct psb_mmu_pt *pt,
+ unsigned long addr)
+{
+ pt->v[psb_mmu_pt_index(addr)] = pt->pd->invalid_pte;
+}
+
+#if 0
+static uint32_t psb_mmu_check_pte_locked(struct psb_mmu_pd *pd,
+ uint32_t mmu_offset)
+{
+ uint32_t *v;
+ uint32_t pfn;
+
+ v = kmap_atomic(pd->p, KM_USER0);
+ if (!v) {
+ printk(KERN_INFO "Could not kmap pde page.\n");
+ return 0;
+ }
+ pfn = v[psb_mmu_pd_index(mmu_offset)];
+ /* printk(KERN_INFO "pde is 0x%08x\n",pfn); */
+ kunmap_atomic(v, KM_USER0);
+ if (((pfn & 0x0F) != PSB_PTE_VALID)) {
+ printk(KERN_INFO "Strange pde at 0x%08x: 0x%08x.\n",
+ mmu_offset, pfn);
+ }
+ v = ioremap(pfn & 0xFFFFF000, 4096);
+ if (!v) {
+ printk(KERN_INFO "Could not kmap pte page.\n");
+ return 0;
+ }
+ pfn = v[psb_mmu_pt_index(mmu_offset)];
+ /* printk(KERN_INFO "pte is 0x%08x\n",pfn); */
+ iounmap(v);
+ if (((pfn & 0x0F) != PSB_PTE_VALID)) {
+ printk(KERN_INFO "Strange pte at 0x%08x: 0x%08x.\n",
+ mmu_offset, pfn);
+ }
+ return pfn >> PAGE_SHIFT;
+}
+
+static void psb_mmu_check_mirrored_gtt(struct psb_mmu_pd *pd,
+ uint32_t mmu_offset,
+ uint32_t gtt_pages)
+{
+ uint32_t start;
+ uint32_t next;
+
+ printk(KERN_INFO "Checking mirrored gtt 0x%08x %d\n",
+ mmu_offset, gtt_pages);
+ down_read(&pd->driver->sem);
+ start = psb_mmu_check_pte_locked(pd, mmu_offset);
+ mmu_offset += PAGE_SIZE;
+ gtt_pages -= 1;
+ while (gtt_pages--) {
+ next = psb_mmu_check_pte_locked(pd, mmu_offset);
+ if (next != start + 1) {
+ printk(KERN_INFO
+ "Ptes out of order: 0x%08x, 0x%08x.\n",
+ start, next);
+ }
+ start = next;
+ mmu_offset += PAGE_SIZE;
+ }
+ up_read(&pd->driver->sem);
+}
+
+#endif
+
+void psb_mmu_mirror_gtt(struct psb_mmu_pd *pd,
+ uint32_t mmu_offset, uint32_t gtt_start,
+ uint32_t gtt_pages)
+{
+ uint32_t *v;
+ uint32_t start = psb_mmu_pd_index(mmu_offset);
+ struct psb_mmu_driver *driver = pd->driver;
+ int num_pages = gtt_pages;
+
+ down_read(&driver->sem);
+ spin_lock(&driver->lock);
+
+ v = kmap_atomic(pd->p, KM_USER0);
+ v += start;
+
+ while (gtt_pages--) {
+ *v++ = gtt_start | pd->pd_mask;
+ gtt_start += PAGE_SIZE;
+ }
+
+ /*ttm_tt_cache_flush(&pd->p, num_pages);*/
+ psb_pages_clflush(pd->driver, &pd->p, num_pages);
+ kunmap_atomic(v, KM_USER0);
+ spin_unlock(&driver->lock);
+
+ if (pd->hw_context != -1)
+ atomic_set(&pd->driver->needs_tlbflush, 1);
+
+ up_read(&pd->driver->sem);
+ psb_mmu_flush_pd(pd->driver, 0);
+}
+
+struct psb_mmu_pd *psb_mmu_get_default_pd(struct psb_mmu_driver *driver) {
+ struct psb_mmu_pd *pd;
+
+ /* down_read(&driver->sem); */
+ pd = driver->default_pd;
+ /* up_read(&driver->sem); */
+
+ return pd;
+}
+
+/* Returns the physical address of the PD shared by sgx/msvdx */
+uint32_t psb_get_default_pd_addr(struct psb_mmu_driver *driver)
+{
+ struct psb_mmu_pd *pd;
+
+ pd = psb_mmu_get_default_pd(driver);
+ return page_to_pfn(pd->p) << PAGE_SHIFT;
+}
+
+void psb_mmu_driver_takedown(struct psb_mmu_driver *driver)
+{
+ psb_mmu_free_pagedir(driver->default_pd);
+ kfree(driver);
+}
+
+struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers,
+ int trap_pagefaults,
+ int invalid_type,
+ struct drm_psb_private *dev_priv) {
+ struct psb_mmu_driver *driver;
+
+ driver = kmalloc(sizeof(*driver), GFP_KERNEL);
+
+ if (!driver)
+ return NULL;
+ driver->dev_priv = dev_priv;
+
+ driver->default_pd = psb_mmu_alloc_pd(driver, trap_pagefaults,
+ invalid_type);
+ if (!driver->default_pd)
+ goto out_err1;
+
+ spin_lock_init(&driver->lock);
+ init_rwsem(&driver->sem);
+ down_write(&driver->sem);
+ driver->register_map = registers;
+ atomic_set(&driver->needs_tlbflush, 1);
+
+ driver->has_clflush = 0;
+
+#if defined(CONFIG_X86)
+ if (boot_cpu_has(X86_FEATURE_CLFLSH)) {
+ uint32_t tfms, misc, cap0, cap4, clflush_size;
+
+ /*
+ * clflush size is determined at kernel setup for x86_64
+ * but not for i386. We have to do it here.
+ */
+
+ cpuid(0x00000001, &tfms, &misc, &cap0, &cap4);
+ clflush_size = ((misc >> 8) & 0xff) * 8;
+ driver->has_clflush = 1;
+ driver->clflush_add =
+ PAGE_SIZE * clflush_size / sizeof(uint32_t);
+ driver->clflush_mask = driver->clflush_add - 1;
+ driver->clflush_mask = ~driver->clflush_mask;
+ }
+#endif
+
+ up_write(&driver->sem);
+ return driver;
+
+out_err1:
+ kfree(driver);
+ return NULL;
+}
+
+#if defined(CONFIG_X86)
+static void psb_mmu_flush_ptes(struct psb_mmu_pd *pd,
+ unsigned long address, uint32_t num_pages,
+ uint32_t desired_tile_stride,
+ uint32_t hw_tile_stride)
+{
+ struct psb_mmu_pt *pt;
+ uint32_t rows = 1;
+ uint32_t i;
+ unsigned long addr;
+ unsigned long end;
+ unsigned long next;
+ unsigned long add;
+ unsigned long row_add;
+ unsigned long clflush_add = pd->driver->clflush_add;
+ unsigned long clflush_mask = pd->driver->clflush_mask;
+
+ if (!pd->driver->has_clflush) {
+ /*ttm_tt_cache_flush(&pd->p, num_pages);*/
+ psb_pages_clflush(pd->driver, &pd->p, num_pages);
+ return;
+ }
+
+ if (hw_tile_stride)
+ rows = num_pages / desired_tile_stride;
+ else
+ desired_tile_stride = num_pages;
+
+ add = desired_tile_stride << PAGE_SHIFT;
+ row_add = hw_tile_stride << PAGE_SHIFT;
+ mb();
+ for (i = 0; i < rows; ++i) {
+
+ addr = address;
+ end = addr + add;
+
+ do {
+ next = psb_pd_addr_end(addr, end);
+ pt = psb_mmu_pt_map_lock(pd, addr);
+ if (!pt)
+ continue;
+ do {
+ psb_clflush(&pt->v
+ [psb_mmu_pt_index(addr)]);
+ } while (addr +=
+ clflush_add,
+ (addr & clflush_mask) < next);
+
+ psb_mmu_pt_unmap_unlock(pt);
+ } while (addr = next, next != end);
+ address += row_add;
+ }
+ mb();
+}
+#else
+static void psb_mmu_flush_ptes(struct psb_mmu_pd *pd,
+ unsigned long address, uint32_t num_pages,
+ uint32_t desired_tile_stride,
+ uint32_t hw_tile_stride)
+{
+ drm_ttm_cache_flush(&pd->p, num_pages);
+}
+#endif
+
+void psb_mmu_remove_pfn_sequence(struct psb_mmu_pd *pd,
+ unsigned long address, uint32_t num_pages)
+{
+ struct psb_mmu_pt *pt;
+ unsigned long addr;
+ unsigned long end;
+ unsigned long next;
+ unsigned long f_address = address;
+
+ down_read(&pd->driver->sem);
+
+ addr = address;
+ end = addr + (num_pages << PAGE_SHIFT);
+
+ do {
+ next = psb_pd_addr_end(addr, end);
+ pt = psb_mmu_pt_alloc_map_lock(pd, addr);
+ if (!pt)
+ goto out;
+ do {
+ psb_mmu_invalidate_pte(pt, addr);
+ --pt->count;
+ } while (addr += PAGE_SIZE, addr < next);
+ psb_mmu_pt_unmap_unlock(pt);
+
+ } while (addr = next, next != end);
+
+out:
+ if (pd->hw_context != -1)
+ psb_mmu_flush_ptes(pd, f_address, num_pages, 1, 1);
+
+ up_read(&pd->driver->sem);
+
+ if (pd->hw_context != -1)
+ psb_mmu_flush(pd->driver, 0);
+
+ return;
+}
+
+void psb_mmu_remove_pages(struct psb_mmu_pd *pd, unsigned long address,
+ uint32_t num_pages, uint32_t desired_tile_stride,
+ uint32_t hw_tile_stride)
+{
+ struct psb_mmu_pt *pt;
+ uint32_t rows = 1;
+ uint32_t i;
+ unsigned long addr;
+ unsigned long end;
+ unsigned long next;
+ unsigned long add;
+ unsigned long row_add;
+ unsigned long f_address = address;
+
+ if (hw_tile_stride)
+ rows = num_pages / desired_tile_stride;
+ else
+ desired_tile_stride = num_pages;
+
+ add = desired_tile_stride << PAGE_SHIFT;
+ row_add = hw_tile_stride << PAGE_SHIFT;
+
+ /* down_read(&pd->driver->sem); */
+
+ /* Make sure we only need to flush this processor's cache */
+
+ for (i = 0; i < rows; ++i) {
+
+ addr = address;
+ end = addr + add;
+
+ do {
+ next = psb_pd_addr_end(addr, end);
+ pt = psb_mmu_pt_map_lock(pd, addr);
+ if (!pt)
+ continue;
+ do {
+ psb_mmu_invalidate_pte(pt, addr);
+ --pt->count;
+
+ } while (addr += PAGE_SIZE, addr < next);
+ psb_mmu_pt_unmap_unlock(pt);
+
+ } while (addr = next, next != end);
+ address += row_add;
+ }
+ if (pd->hw_context != -1)
+ psb_mmu_flush_ptes(pd, f_address, num_pages,
+ desired_tile_stride, hw_tile_stride);
+
+ /* up_read(&pd->driver->sem); */
+
+ if (pd->hw_context != -1)
+ psb_mmu_flush(pd->driver, 0);
+}
+
+int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd, uint32_t start_pfn,
+ unsigned long address, uint32_t num_pages,
+ int type)
+{
+ struct psb_mmu_pt *pt;
+ uint32_t pte;
+ unsigned long addr;
+ unsigned long end;
+ unsigned long next;
+ unsigned long f_address = address;
+ int ret = 0;
+
+ down_read(&pd->driver->sem);
+
+ addr = address;
+ end = addr + (num_pages << PAGE_SHIFT);
+
+ do {
+ next = psb_pd_addr_end(addr, end);
+ pt = psb_mmu_pt_alloc_map_lock(pd, addr);
+ if (!pt) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ do {
+ pte = psb_mmu_mask_pte(start_pfn++, type);
+ psb_mmu_set_pte(pt, addr, pte);
+ pt->count++;
+ } while (addr += PAGE_SIZE, addr < next);
+ psb_mmu_pt_unmap_unlock(pt);
+
+ } while (addr = next, next != end);
+
+out:
+ if (pd->hw_context != -1)
+ psb_mmu_flush_ptes(pd, f_address, num_pages, 1, 1);
+
+ up_read(&pd->driver->sem);
+
+ if (pd->hw_context != -1)
+ psb_mmu_flush(pd->driver, 1);
+
+ return ret;
+}
+
+int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages,
+ unsigned long address, uint32_t num_pages,
+ uint32_t desired_tile_stride,
+ uint32_t hw_tile_stride, int type)
+{
+ struct psb_mmu_pt *pt;
+ uint32_t rows = 1;
+ uint32_t i;
+ uint32_t pte;
+ unsigned long addr;
+ unsigned long end;
+ unsigned long next;
+ unsigned long add;
+ unsigned long row_add;
+ unsigned long f_address = address;
+ int ret = 0;
+
+ if (hw_tile_stride) {
+ if (num_pages % desired_tile_stride != 0)
+ return -EINVAL;
+ rows = num_pages / desired_tile_stride;
+ } else {
+ desired_tile_stride = num_pages;
+ }
+
+ add = desired_tile_stride << PAGE_SHIFT;
+ row_add = hw_tile_stride << PAGE_SHIFT;
+
+ down_read(&pd->driver->sem);
+
+ for (i = 0; i < rows; ++i) {
+
+ addr = address;
+ end = addr + add;
+
+ do {
+ next = psb_pd_addr_end(addr, end);
+ pt = psb_mmu_pt_alloc_map_lock(pd, addr);
+ if (!pt) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ do {
+ pte =
+ psb_mmu_mask_pte(page_to_pfn(*pages++),
+ type);
+ psb_mmu_set_pte(pt, addr, pte);
+ pt->count++;
+ } while (addr += PAGE_SIZE, addr < next);
+ psb_mmu_pt_unmap_unlock(pt);
+
+ } while (addr = next, next != end);
+
+ address += row_add;
+ }
+out:
+ if (pd->hw_context != -1)
+ psb_mmu_flush_ptes(pd, f_address, num_pages,
+ desired_tile_stride, hw_tile_stride);
+
+ up_read(&pd->driver->sem);
+
+ if (pd->hw_context != -1)
+ psb_mmu_flush(pd->driver, 1);
+
+ return ret;
+}
+#if 0 /*comented out, only used in mmu test now*/
+void psb_mmu_enable_requestor(struct psb_mmu_driver *driver, uint32_t mask)
+{
+ mask &= _PSB_MMU_ER_MASK;
+ psb_iowrite32(driver,
+ psb_ioread32(driver, PSB_CR_BIF_CTRL) & ~mask,
+ PSB_CR_BIF_CTRL);
+ (void) psb_ioread32(driver, PSB_CR_BIF_CTRL);
+}
+
+void psb_mmu_disable_requestor(struct psb_mmu_driver *driver,
+ uint32_t mask)
+{
+ mask &= _PSB_MMU_ER_MASK;
+ psb_iowrite32(driver, psb_ioread32(driver, PSB_CR_BIF_CTRL) | mask,
+ PSB_CR_BIF_CTRL);
+ (void) psb_ioread32(driver, PSB_CR_BIF_CTRL);
+}
+#endif
+int psb_mmu_virtual_to_pfn(struct psb_mmu_pd *pd, uint32_t virtual,
+ unsigned long *pfn)
+{
+ int ret;
+ struct psb_mmu_pt *pt;
+ uint32_t tmp;
+ spinlock_t *lock = &pd->driver->lock;
+
+ down_read(&pd->driver->sem);
+ pt = psb_mmu_pt_map_lock(pd, virtual);
+ if (!pt) {
+ uint32_t *v;
+
+ spin_lock(lock);
+ v = kmap_atomic(pd->p, KM_USER0);
+ tmp = v[psb_mmu_pd_index(virtual)];
+ kunmap_atomic(v, KM_USER0);
+ spin_unlock(lock);
+
+ if (tmp != pd->invalid_pde || !(tmp & PSB_PTE_VALID) ||
+ !(pd->invalid_pte & PSB_PTE_VALID)) {
+ ret = -EINVAL;
+ goto out;
+ }
+ ret = 0;
+ *pfn = pd->invalid_pte >> PAGE_SHIFT;
+ goto out;
+ }
+ tmp = pt->v[psb_mmu_pt_index(virtual)];
+ if (!(tmp & PSB_PTE_VALID)) {
+ ret = -EINVAL;
+ } else {
+ ret = 0;
+ *pfn = tmp >> PAGE_SHIFT;
+ }
+ psb_mmu_pt_unmap_unlock(pt);
+out:
+ up_read(&pd->driver->sem);
+ return ret;
+}
+#if 0
+void psb_mmu_test(struct psb_mmu_driver *driver, uint32_t offset)
+{
+ struct page *p;
+ unsigned long pfn;
+ int ret = 0;
+ struct psb_mmu_pd *pd;
+ uint32_t *v;
+ uint32_t *vmmu;
+
+ pd = driver->default_pd;
+ if (!pd)
+ printk(KERN_WARNING "Could not get default pd\n");
+
+
+ p = alloc_page(GFP_DMA32);
+
+ if (!p) {
+ printk(KERN_WARNING "Failed allocating page\n");
+ return;
+ }
+
+ v = kmap(p);
+ memset(v, 0x67, PAGE_SIZE);
+
+ pfn = (offset >> PAGE_SHIFT);
+
+ ret = psb_mmu_insert_pages(pd, &p, pfn << PAGE_SHIFT, 1, 0, 0, 0);
+ if (ret) {
+ printk(KERN_WARNING "Failed inserting mmu page\n");
+ goto out_err1;
+ }
+
+ /* Ioremap the page through the GART aperture */
+
+ vmmu = ioremap(pfn << PAGE_SHIFT, PAGE_SIZE);
+ if (!vmmu) {
+ printk(KERN_WARNING "Failed ioremapping page\n");
+ goto out_err2;
+ }
+
+ /* Read from the page with mmu disabled. */
+ printk(KERN_INFO "Page first dword is 0x%08x\n", ioread32(vmmu));
+
+ /* Enable the mmu for host accesses and read again. */
+ psb_mmu_enable_requestor(driver, _PSB_MMU_ER_HOST);
+
+ printk(KERN_INFO "MMU Page first dword is (0x67676767) 0x%08x\n",
+ ioread32(vmmu));
+ *v = 0x15243705;
+ printk(KERN_INFO "MMU Page new dword is (0x15243705) 0x%08x\n",
+ ioread32(vmmu));
+ iowrite32(0x16243355, vmmu);
+ (void) ioread32(vmmu);
+ printk(KERN_INFO "Page new dword is (0x16243355) 0x%08x\n", *v);
+
+ printk(KERN_INFO "Int stat is 0x%08x\n",
+ psb_ioread32(driver, PSB_CR_BIF_INT_STAT));
+ printk(KERN_INFO "Fault is 0x%08x\n",
+ psb_ioread32(driver, PSB_CR_BIF_FAULT));
+
+ /* Disable MMU for host accesses and clear page fault register */
+ psb_mmu_disable_requestor(driver, _PSB_MMU_ER_HOST);
+ iounmap(vmmu);
+out_err2:
+ psb_mmu_remove_pages(pd, pfn << PAGE_SHIFT, 1, 0, 0);
+out_err1:
+ kunmap(p);
+ __free_page(p);
+}
+#endif
--- /dev/null
+/**************************************************************************
+ * MSVDX I/O operations and IRQ handling
+ *
+ * Copyright (c) 2007 Intel Corporation, Hillsboro, OR, USA
+ * Copyright (c) Imagination Technologies Limited, UK
+ *
+ * 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 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.
+ *
+ **************************************************************************/
+
+#include <drm/drmP.h>
+#include <drm/drm_os_linux.h>
+#include "psb_drm.h"
+#include "psb_drv.h"
+#include "psb_msvdx.h"
+#include "pnw_topaz.h"
+#include "psb_powermgmt.h"
+#include <linux/io.h>
+#include <linux/delay.h>
+
+#ifndef list_first_entry
+#define list_first_entry(ptr, type, member) \
+ list_entry((ptr)->next, type, member)
+#endif
+
+
+static int psb_msvdx_send(struct drm_device *dev, void *cmd,
+ unsigned long cmd_size);
+
+static int psb_msvdx_dequeue_send(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct psb_msvdx_cmd_queue *msvdx_cmd = NULL;
+ int ret = 0;
+ struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+
+ if (list_empty(&msvdx_priv->msvdx_queue)) {
+ PSB_DEBUG_GENERAL("MSVDXQUE: msvdx list empty.\n");
+ msvdx_priv->msvdx_busy = 0;
+ return -EINVAL;
+ }
+ msvdx_cmd = list_first_entry(&msvdx_priv->msvdx_queue,
+ struct psb_msvdx_cmd_queue, head);
+ PSB_DEBUG_GENERAL("MSVDXQUE: Queue has id %08x\n", msvdx_cmd->sequence);
+ ret = psb_msvdx_send(dev, msvdx_cmd->cmd, msvdx_cmd->cmd_size);
+ if (ret) {
+ DRM_ERROR("MSVDXQUE: psb_msvdx_send failed\n");
+ ret = -EINVAL;
+ }
+ list_del(&msvdx_cmd->head);
+ kfree(msvdx_cmd->cmd);
+ kfree(msvdx_cmd);
+
+ return ret;
+}
+
+static int psb_msvdx_map_command(struct drm_device *dev,
+ struct ttm_buffer_object *cmd_buffer,
+ unsigned long cmd_offset, unsigned long cmd_size,
+ void **msvdx_cmd, uint32_t sequence, int copy_cmd)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+ int ret = 0;
+ unsigned long cmd_page_offset = cmd_offset & ~PAGE_MASK;
+ unsigned long cmd_size_remaining;
+ struct ttm_bo_kmap_obj cmd_kmap, regio_kmap;
+ void *cmd, *cmd_copy, *cmd_start;
+ bool is_iomem;
+ int i;
+ struct HOST_BE_OPP_PARAMS * oppParam;
+ drm_psb_msvdx_frame_info_t * current_frame = NULL;
+ int first_empty = -1;
+
+
+ /* command buffers may not exceed page boundary */
+ if (cmd_size + cmd_page_offset > PAGE_SIZE)
+ return -EINVAL;
+
+ ret = ttm_bo_kmap(cmd_buffer, cmd_offset >> PAGE_SHIFT, 1, &cmd_kmap);
+ if (ret) {
+ DRM_ERROR("MSVDXQUE:ret:%d\n", ret);
+ return ret;
+ }
+
+ cmd_start = (void *)ttm_kmap_obj_virtual(&cmd_kmap, &is_iomem)
+ + cmd_page_offset;
+ cmd = cmd_start;
+ cmd_size_remaining = cmd_size;
+
+ while (cmd_size_remaining > 0) {
+ uint32_t cur_cmd_size = MEMIO_READ_FIELD(cmd, FWRK_GENMSG_SIZE);
+ uint32_t cur_cmd_id = MEMIO_READ_FIELD(cmd, FWRK_GENMSG_ID);
+ uint32_t mmu_ptd = 0, msvdx_mmu_invalid = 0;
+ struct psb_msvdx_deblock_queue *msvdx_deblock;
+ unsigned long irq_flags;
+
+ PSB_DEBUG_GENERAL("cmd start at %08x cur_cmd_size = %d"
+ " cur_cmd_id = %02x fence = %08x\n",
+ (uint32_t) cmd, cur_cmd_size, cur_cmd_id, sequence);
+ if ((cur_cmd_size % sizeof(uint32_t))
+ || (cur_cmd_size > cmd_size_remaining)) {
+ ret = -EINVAL;
+ DRM_ERROR("MSVDX: ret:%d\n", ret);
+ goto out;
+ }
+
+ switch (cur_cmd_id) {
+ case VA_MSGID_RENDER:
+ PSB_DEBUG_MSVDX("MSVDX_DEBUG: send render message. \n");
+
+ /* Fence ID */
+ MEMIO_WRITE_FIELD(cmd, FW_VA_DECODE_MSG_ID, sequence);
+
+ mmu_ptd = psb_get_default_pd_addr(dev_priv->mmu);
+ msvdx_mmu_invalid = atomic_cmpxchg(&dev_priv->msvdx_mmu_invaldc,
+ 1, 0);
+ if (msvdx_mmu_invalid == 1) {
+ uint32_t flags;
+ flags = MEMIO_READ_FIELD(cmd, FW_DEVA_DECODE_FLAGS);
+ flags |= FW_DEVA_INVALIDATE_MMU;
+ MEMIO_WRITE_FIELD(cmd, FW_DEVA_DECODE_FLAGS, flags);
+ psb_gl3_global_invalidation(dev);
+
+ PSB_DEBUG_GENERAL("MSVDX:Set MMU invalidate\n");
+ }
+
+ /* PTD */
+ mmu_ptd |= MEMIO_READ_FIELD(cmd,
+ FW_VA_DECODE_MMUPTD) & 0xff;
+ MEMIO_WRITE_FIELD(cmd, FW_VA_DECODE_MMUPTD, mmu_ptd);
+ break;
+
+ case VA_MSGID_OOLD:
+ MEMIO_WRITE_FIELD(cmd, FW_DXVA_OOLD_FENCE_VALUE,
+ sequence);
+ mmu_ptd = psb_get_default_pd_addr(dev_priv->mmu);
+ msvdx_mmu_invalid = atomic_cmpxchg(&dev_priv->msvdx_mmu_invaldc,
+ 1, 0);
+ if (msvdx_mmu_invalid == 1) {
+ mmu_ptd |= 1;
+ PSB_DEBUG_GENERAL("MSVDX:Set MMU invalidate\n");
+ }
+
+ /* PTD */
+ MEMIO_WRITE_FIELD(cmd, FW_DXVA_OOLD_MMUPTD, mmu_ptd);
+
+ PSB_DEBUG_GENERAL("MSVDX:Get oold cmd\n");
+
+ break;
+
+ case VA_MSGID_OOLD_MFLD:
+ case VA_MSGID_DEBLOCK_MFLD: {
+ FW_VA_DEBLOCK_MSG * deblock_msg;
+
+ PSB_DEBUG_GENERAL("MSVDX:Get deblock cmd for medfield\n");
+
+ deblock_msg = (FW_VA_DEBLOCK_MSG *)cmd;
+
+ mmu_ptd = psb_get_default_pd_addr(dev_priv->mmu);
+ msvdx_mmu_invalid = atomic_cmpxchg(&dev_priv->msvdx_mmu_invaldc,
+ 1, 0);
+ if (msvdx_mmu_invalid == 1) {
+ uint32_t flags;
+ flags = deblock_msg->flags;
+ flags |= FW_DEVA_INVALIDATE_MMU;
+ deblock_msg->flags = flags;
+
+ PSB_DEBUG_GENERAL("MSVDX:Set MMU invalidate\n");
+ }
+
+
+ deblock_msg->header.bits.msg_type = cur_cmd_id - VA_MSGID_DEBLOCK_MFLD + VA_MSGID_DEBLOCK; /* patch to right cmd type */
+ deblock_msg->header.bits.msg_fence = (uint16_t)(sequence & 0xffff);
+ deblock_msg->mmu_context.bits.mmu_ptd = (mmu_ptd >> 8);
+
+ }
+ break;
+
+ case VA_MSGID_DEBLOCK:
+ msvdx_priv->deblock_enabled = 1;
+ /* Fence ID */
+ MEMIO_WRITE_FIELD(cmd, FW_DXVA_DEBLOCK_FENCE_VALUE,
+ sequence);
+ mmu_ptd = psb_get_default_pd_addr(dev_priv->mmu);
+ msvdx_mmu_invalid = atomic_cmpxchg(&dev_priv->msvdx_mmu_invaldc,
+ 1, 0);
+ if (msvdx_mmu_invalid == 1) {
+ mmu_ptd |= 1;
+ PSB_DEBUG_GENERAL("MSVDX:Set MMU invalidate\n");
+ }
+
+ /* PTD */
+ MEMIO_WRITE_FIELD(cmd,
+ FW_DXVA_DEBLOCK_MMUPTD,
+ mmu_ptd);
+
+ /* printk("Got deblock msg\n"); */
+ /* Deblock message is followed by 32 */
+ /* bytes of deblock params */
+ msvdx_deblock = kmalloc(
+ sizeof(struct psb_msvdx_deblock_queue),
+ GFP_KERNEL);
+
+ if (msvdx_deblock == NULL) {
+ DRM_ERROR("DEBLOCK QUE: Out of memory...\n");
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ memcpy(&msvdx_deblock->dbParams, cmd + 16, sizeof(struct DEBLOCKPARAMS));
+
+ ret = ttm_bo_kmap(
+ (struct ttm_buffer_object *)
+ msvdx_deblock->dbParams.handle,
+ 0,
+ (msvdx_deblock->dbParams.buffer_size +
+ PAGE_SIZE - 1) >> PAGE_SHIFT,
+ ®io_kmap);
+
+ /* printk("deblock regio buffer size is 0x%x\n",
+ msvdx_deblock->dbParams.buffer_size); */
+
+ if (likely(!ret)) {
+ msvdx_deblock->dbParams.pPicparams = kmalloc(
+ msvdx_deblock->dbParams.buffer_size,
+ GFP_KERNEL);
+
+ if (msvdx_deblock->dbParams.pPicparams != NULL)
+ memcpy(
+ msvdx_deblock->dbParams.pPicparams,
+ regio_kmap.virtual,
+ msvdx_deblock->dbParams.buffer_size);
+ ttm_bo_kunmap(®io_kmap);
+ }
+ spin_lock_irqsave(&msvdx_priv->msvdx_lock, irq_flags);
+ list_add_tail(&msvdx_deblock->head,
+ &msvdx_priv->deblock_queue);
+ spin_unlock_irqrestore(&msvdx_priv->msvdx_lock,
+ irq_flags);
+
+ cmd += sizeof(struct DEBLOCKPARAMS);
+ cmd_size_remaining -= sizeof(struct DEBLOCKPARAMS);
+ break;
+
+ case VA_MSGID_HOST_BE_OPP:
+
+ PSB_DEBUG_MSVDX("MSVDX_DEBUG: send host_be_opp message. \n");
+
+ msvdx_priv->host_be_opp_enabled = 1;
+ /* Fence ID */
+ MEMIO_WRITE_FIELD(cmd, FW_VA_HOST_BE_OPP_FENCE_VALUE,
+ sequence);
+ mmu_ptd = psb_get_default_pd_addr(dev_priv->mmu);
+ msvdx_mmu_invalid = atomic_cmpxchg(&dev_priv->msvdx_mmu_invaldc,
+ 1, 0);
+ if (msvdx_mmu_invalid == 1) {
+ mmu_ptd |= 1;
+ PSB_DEBUG_GENERAL("MSVDX:Set MMU invalidate\n");
+ }
+
+ /* PTD */
+ MEMIO_WRITE_FIELD(cmd,
+ FW_VA_HOST_BE_OPP_MMUPTD,
+ mmu_ptd);
+
+ /* HostBeOpp message is followed by 32 bytes of host_be_opp params */
+ oppParam = kmalloc(
+ sizeof(struct HOST_BE_OPP_PARAMS),
+ GFP_KERNEL);
+
+ if (oppParam == NULL) {
+ DRM_ERROR("DEBLOCK QUE: Out of memory...\n");
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ memcpy(oppParam, cmd + 16, sizeof(struct HOST_BE_OPP_PARAMS));
+ /*get the right frame_info struct for current surface*/
+ for (i = 0; i < MAX_DECODE_BUFFERS; i++) {
+ if (msvdx_priv->frame_info[i].handle == oppParam->handle) {
+ current_frame = &(msvdx_priv->frame_info[i]);
+ break;
+ }
+ if ((first_empty == -1) && (msvdx_priv->frame_info[i].handle == 0))
+ first_empty = i;
+ }
+
+ /*if didn't find the struct for current surface, use the earliest empty one*/
+ if (!current_frame) {
+ if (first_empty == -1) {
+ DRM_ERROR("failed find the struct for current surface and also there is no empty one.\n");
+ ret = -EFAULT;
+ goto out;
+ }
+ current_frame = &(msvdx_priv->frame_info[first_empty]);
+ }
+
+ memset(current_frame, 0, sizeof(drm_psb_msvdx_frame_info_t));
+ current_frame->handle = oppParam->handle;
+ current_frame->buffer_stride = oppParam->buffer_stride;
+ current_frame->buffer_size = oppParam->buffer_size;
+ current_frame->picture_width_mb = oppParam->picture_width_mb;
+ current_frame->size_mb = oppParam->size_mb;
+ current_frame->fence = sequence;
+
+
+ cmd += sizeof(struct HOST_BE_OPP_PARAMS);
+ cmd_size_remaining -= sizeof(struct HOST_BE_OPP_PARAMS);
+
+ break;
+
+ default:
+ /* Msg not supported */
+ ret = -EINVAL;
+ PSB_DEBUG_GENERAL("MSVDX: ret:%d\n", ret);
+ goto out;
+ }
+
+ cmd += cur_cmd_size;
+ cmd_size_remaining -= cur_cmd_size;
+ }
+
+ if (copy_cmd) {
+ PSB_DEBUG_GENERAL("MSVDXQUE:copying command\n");
+
+ cmd_copy = kzalloc(cmd_size, GFP_KERNEL);
+ if (cmd_copy == NULL) {
+ ret = -ENOMEM;
+ DRM_ERROR("MSVDX: fail to callc,ret=:%d\n", ret);
+ goto out;
+ }
+ memcpy(cmd_copy, cmd_start, cmd_size);
+ *msvdx_cmd = cmd_copy;
+ } else {
+ PSB_DEBUG_GENERAL("MSVDXQUE:did NOT copy command\n");
+ ret = psb_msvdx_send(dev, cmd_start, cmd_size);
+ if (ret) {
+ DRM_ERROR("MSVDXQUE: psb_msvdx_send failed\n");
+ ret = -EINVAL;
+ }
+ }
+
+out:
+ ttm_bo_kunmap(&cmd_kmap);
+
+ return ret;
+}
+
+static int psb_submit_video_cmdbuf(struct drm_device *dev,
+ struct ttm_buffer_object *cmd_buffer,
+ unsigned long cmd_offset, unsigned long cmd_size,
+ struct ttm_fence_object *fence)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ uint32_t sequence = dev_priv->sequence[PSB_ENGINE_VIDEO];
+ unsigned long irq_flags;
+ int ret = 0;
+ struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+ int offset = 0;
+ /* psb_schedule_watchdog(dev_priv); */
+
+ spin_lock_irqsave(&msvdx_priv->msvdx_lock, irq_flags);
+
+ /* expected msvdx_needs_reset is set after previous session exited
+ * but msvdx_hw_busy is always 1, and caused powerdown not excuted
+ * so reload the firmware for every new context
+ */
+ dev_priv->last_msvdx_ctx = dev_priv->msvdx_ctx;
+
+ if (msvdx_priv->msvdx_needs_reset) {
+ spin_unlock_irqrestore(&msvdx_priv->msvdx_lock, irq_flags);
+ PSB_DEBUG_GENERAL("MSVDX: will reset msvdx\n");
+ if (psb_msvdx_reset(dev_priv)) {
+ ret = -EBUSY;
+ DRM_ERROR("MSVDX: Reset failed\n");
+ return ret;
+ }
+ msvdx_priv->msvdx_needs_reset = 0;
+ msvdx_priv->msvdx_busy = 0;
+
+ psb_msvdx_init(dev);
+
+ /* restore vec local mem if needed */
+ if (msvdx_priv->vec_local_mem_saved) {
+ for (offset = 0; offset < VEC_LOCAL_MEM_BYTE_SIZE / 4; ++offset)
+ PSB_WMSVDX32(msvdx_priv->vec_local_mem_data[offset],
+ VEC_LOCAL_MEM_OFFSET + offset * 4);
+
+ msvdx_priv->vec_local_mem_saved = 0;
+ }
+
+ spin_lock_irqsave(&msvdx_priv->msvdx_lock, irq_flags);
+ }
+
+ if (!msvdx_priv->msvdx_fw_loaded) {
+ spin_unlock_irqrestore(&msvdx_priv->msvdx_lock, irq_flags);
+ PSB_DEBUG_GENERAL("MSVDX:reload FW to MTX\n");
+
+ ret = psb_setup_fw(dev);
+ if (ret) {
+ DRM_ERROR("MSVDX:fail to load FW\n");
+ /* FIXME: find a proper return value */
+ return -EFAULT;
+ }
+ msvdx_priv->msvdx_fw_loaded = 1;
+
+ PSB_DEBUG_GENERAL("MSVDX: load firmware successfully\n");
+ spin_lock_irqsave(&msvdx_priv->msvdx_lock, irq_flags);
+ }
+
+ if (!msvdx_priv->msvdx_busy) {
+ msvdx_priv->msvdx_busy = 1;
+ spin_unlock_irqrestore(&msvdx_priv->msvdx_lock, irq_flags);
+ PSB_DEBUG_GENERAL("MSVDX: commit command to HW,seq=0x%08x\n",
+ sequence);
+ ret = psb_msvdx_map_command(dev, cmd_buffer, cmd_offset,
+ cmd_size, NULL, sequence, 0);
+ if (ret) {
+ DRM_ERROR("MSVDXQUE: Failed to extract cmd\n");
+ return ret;
+ }
+ } else {
+ struct psb_msvdx_cmd_queue *msvdx_cmd;
+ void *cmd = NULL;
+
+ spin_unlock_irqrestore(&msvdx_priv->msvdx_lock, irq_flags);
+ /* queue the command to be sent when the h/w is ready */
+ PSB_DEBUG_GENERAL("MSVDXQUE: queueing sequence:%08x..\n",
+ sequence);
+ msvdx_cmd = kzalloc(sizeof(struct psb_msvdx_cmd_queue),
+ GFP_KERNEL);
+ if (msvdx_cmd == NULL) {
+ DRM_ERROR("MSVDXQUE: Out of memory...\n");
+ return -ENOMEM;
+ }
+
+ ret = psb_msvdx_map_command(dev, cmd_buffer, cmd_offset,
+ cmd_size, &cmd, sequence, 1);
+ if (ret) {
+ DRM_ERROR("MSVDXQUE: Failed to extract cmd\n");
+ kfree(msvdx_cmd
+ );
+ return ret;
+ }
+ msvdx_cmd->cmd = cmd;
+ msvdx_cmd->cmd_size = cmd_size;
+ msvdx_cmd->sequence = sequence;
+ spin_lock_irqsave(&msvdx_priv->msvdx_lock, irq_flags);
+ list_add_tail(&msvdx_cmd->head, &msvdx_priv->msvdx_queue);
+ if (!msvdx_priv->msvdx_busy) {
+ msvdx_priv->msvdx_busy = 1;
+ PSB_DEBUG_GENERAL("MSVDXQUE: Need immediate dequeue\n");
+ psb_msvdx_dequeue_send(dev);
+ }
+ spin_unlock_irqrestore(&msvdx_priv->msvdx_lock, irq_flags);
+ }
+
+ return ret;
+}
+
+int psb_cmdbuf_video(struct drm_file *priv,
+ struct list_head *validate_list,
+ uint32_t fence_type,
+ struct drm_psb_cmdbuf_arg *arg,
+ struct ttm_buffer_object *cmd_buffer,
+ struct psb_ttm_fence_rep *fence_arg)
+{
+ struct drm_device *dev = priv->minor->dev;
+ struct ttm_fence_object *fence;
+ int ret;
+
+ /*
+ * Check this. Doesn't seem right. Have fencing done AFTER command
+ * submission and make sure drm_psb_idle idles the MSVDX completely.
+ */
+ ret =
+ psb_submit_video_cmdbuf(dev, cmd_buffer, arg->cmdbuf_offset,
+ arg->cmdbuf_size, NULL);
+ if (ret)
+ return ret;
+
+
+ /* DRM_ERROR("Intel: Fix video fencing!!\n"); */
+ psb_fence_or_sync(priv, PSB_ENGINE_VIDEO, fence_type,
+ arg->fence_flags, validate_list, fence_arg,
+ &fence);
+
+ ttm_fence_object_unref(&fence);
+ spin_lock(&cmd_buffer->bdev->fence_lock);
+ if (cmd_buffer->sync_obj != NULL)
+ ttm_fence_sync_obj_unref(&cmd_buffer->sync_obj);
+ spin_unlock(&cmd_buffer->bdev->fence_lock);
+
+ return 0;
+}
+
+
+static int psb_msvdx_send(struct drm_device *dev, void *cmd,
+ unsigned long cmd_size)
+{
+ int ret = 0;
+ struct drm_psb_private *dev_priv = dev->dev_private;
+
+ while (cmd_size > 0) {
+ uint32_t cur_cmd_size = MEMIO_READ_FIELD(cmd, FWRK_GENMSG_SIZE);
+ uint32_t cur_cmd_id = MEMIO_READ_FIELD(cmd, FWRK_GENMSG_ID);
+ if (cur_cmd_size > cmd_size) {
+ ret = -EINVAL;
+ DRM_ERROR("MSVDX:cmd_size %lu cur_cmd_size %lu\n",
+ cmd_size, (unsigned long)cur_cmd_size);
+ goto out;
+ }
+
+ /* Send the message to h/w */
+ ret = psb_mtx_send(dev_priv, cmd);
+ if (ret) {
+ PSB_DEBUG_GENERAL("MSVDX: ret:%d\n", ret);
+ goto out;
+ }
+ cmd += cur_cmd_size;
+ cmd_size -= cur_cmd_size;
+ if (cur_cmd_id == VA_MSGID_HOST_BE_OPP) {
+ cmd += sizeof(struct HOST_BE_OPP_PARAMS);
+ cmd_size -= sizeof(struct HOST_BE_OPP_PARAMS);
+ }
+ if (cmd_size)
+ PSB_UDELAY(200);
+ }
+
+out:
+ PSB_DEBUG_GENERAL("MSVDX: ret:%d\n", ret);
+ return ret;
+}
+
+int psb_mtx_send(struct drm_psb_private *dev_priv, const void *msg)
+{
+ static uint32_t pad_msg[FWRK_PADMSG_SIZE];
+ const uint32_t *p_msg = (uint32_t *) msg;
+ uint32_t msg_num, words_free, ridx, widx, buf_size, buf_offset;
+ int ret = 0;
+
+ PSB_DEBUG_GENERAL("MSVDX: psb_mtx_send\n");
+
+ /* we need clocks enabled before we touch VEC local ram */
+ PSB_WMSVDX32(clk_enable_all, MSVDX_MAN_CLK_ENABLE);
+
+ msg_num = (MEMIO_READ_FIELD(msg, FWRK_GENMSG_SIZE) + 3) / 4;
+
+ /*
+ {
+ int i;
+ printk("MSVDX: psb_mtx_send is %dDW\n", msg_num);
+
+ for(i = 0; i < msg_num; i++)
+ printk("0x%08x ", p_msg[i]);
+ printk("\n");
+ }
+ */
+ buf_size = PSB_RMSVDX32(MSVDX_COMMS_TO_MTX_BUF_SIZE) & ((1 << 16) - 1);
+
+ if (msg_num > buf_size) {
+ ret = -EINVAL;
+ DRM_ERROR("MSVDX: message exceed maximum,ret:%d\n", ret);
+ goto out;
+ }
+
+ ridx = PSB_RMSVDX32(MSVDX_COMMS_TO_MTX_RD_INDEX);
+ widx = PSB_RMSVDX32(MSVDX_COMMS_TO_MTX_WRT_INDEX);
+
+
+ buf_size = PSB_RMSVDX32(MSVDX_COMMS_TO_MTX_BUF_SIZE) & ((1 << 16) - 1);
+ /*0x2000 is VEC Local Ram offset*/
+ buf_offset =
+ (PSB_RMSVDX32(MSVDX_COMMS_TO_MTX_BUF_SIZE) >> 16) + 0x2000;
+
+ /* message would wrap, need to send a pad message */
+ if (widx + msg_num > buf_size) {
+ /* Shouldn't happen for a PAD message itself */
+ BUG_ON(MEMIO_READ_FIELD(msg, FWRK_GENMSG_ID)
+ == FWRK_MSGID_PADDING);
+
+ /* if the read pointer is at zero then we must wait for it to
+ * change otherwise the write pointer will equal the read
+ * pointer,which should only happen when the buffer is empty
+ *
+ * This will only happens if we try to overfill the queue,
+ * queue management should make
+ * sure this never happens in the first place.
+ */
+ BUG_ON(0 == ridx);
+ if (0 == ridx) {
+ ret = -EINVAL;
+ DRM_ERROR("MSVDX: RIndex=0, ret:%d\n", ret);
+ goto out;
+ }
+
+ /* Send a pad message */
+ MEMIO_WRITE_FIELD(pad_msg, FWRK_GENMSG_SIZE,
+ (buf_size - widx) << 2);
+ MEMIO_WRITE_FIELD(pad_msg, FWRK_GENMSG_ID,
+ FWRK_MSGID_PADDING);
+ psb_mtx_send(dev_priv, pad_msg);
+ widx = PSB_RMSVDX32(MSVDX_COMMS_TO_MTX_WRT_INDEX);
+ }
+
+ if (widx >= ridx)
+ words_free = buf_size - (widx - ridx) - 1;
+ else
+ words_free = ridx - widx - 1;
+
+ BUG_ON(msg_num > words_free);
+ if (msg_num > words_free) {
+ ret = -EINVAL;
+ DRM_ERROR("MSVDX: msg_num > words_free, ret:%d\n", ret);
+ goto out;
+ }
+ while (msg_num > 0) {
+ PSB_WMSVDX32(*p_msg++, buf_offset + (widx << 2));
+ msg_num--;
+ widx++;
+ if (buf_size == widx)
+ widx = 0;
+ }
+
+ PSB_WMSVDX32(widx, MSVDX_COMMS_TO_MTX_WRT_INDEX);
+
+ /* Make sure clocks are enabled before we kick */
+ PSB_WMSVDX32(clk_enable_all, MSVDX_MAN_CLK_ENABLE);
+
+ PSB_WMSVDX32(clk_enable_all, MSVDX_MAN_CLK_ENABLE);
+
+ /* signal an interrupt to let the mtx know there is a new message */
+ /* PSB_WMSVDX32(1, MSVDX_MTX_KICKI); */
+ PSB_WMSVDX32(1, MSVDX_MTX_KICK);
+
+ /* Read MSVDX Register several times in case Idle signal assert */
+ PSB_RMSVDX32(MSVDX_INTERRUPT_STATUS);
+ PSB_RMSVDX32(MSVDX_INTERRUPT_STATUS);
+ PSB_RMSVDX32(MSVDX_INTERRUPT_STATUS);
+ PSB_RMSVDX32(MSVDX_INTERRUPT_STATUS);
+
+
+out:
+ return ret;
+}
+
+static int psb_msvdx_towpass_deblock(struct drm_device *dev,
+ uint32_t *pPicparams)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *)dev->dev_private;
+ uint32_t cmd_size, cmd_count = 0;
+ uint32_t cmd_id, reg, value, wait, reg_value, read = 0, ret = 0;
+
+ cmd_size = *pPicparams++;
+ PSB_DEBUG_GENERAL("MSVDX DEBLOCK: deblock get cmd size %d\n", cmd_size);
+ /* printk("MSVDX DEBLOCK: deblock get cmd size %d\n", cmd_size); */
+
+ do {
+ cmd_id = (*pPicparams) & 0xf0000000;
+ reg = (*pPicparams++) & 0x0fffffff;
+ switch (cmd_id) {
+ case MSVDX_DEBLOCK_REG_SET: {
+ value = *pPicparams++;
+ PSB_WMSVDX32(value, reg);
+ cmd_count += 2;
+ break;
+ }
+ case MSVDX_DEBLOCK_REG_GET: {
+ read = PSB_RMSVDX32(reg);
+ cmd_count += 1;
+ break;
+ }
+ case MSVDX_DEBLOCK_REG_POLLn: {
+ value = *pPicparams++;
+ wait = 0;
+
+ do {
+ reg_value = PSB_RMSVDX32(reg);
+ } while ((wait++ < 20000) && (value > reg_value));
+
+ if (wait >= 20000) {
+ ret = 1;
+ PSB_DEBUG_GENERAL(
+ "MSVDX DEBLOCK: polln cmd space time out!\n");
+ goto finish_deblock;
+ }
+ cmd_count += 2;
+ break;
+ }
+ case MSVDX_DEBLOCK_REG_POLLx: {
+ wait = 0;
+
+ do {
+ reg_value = PSB_RMSVDX32(reg);
+ } while ((wait++ < 20000) && (read > reg_value));
+
+ if (wait >= 20000) {
+ ret = 1;
+ PSB_DEBUG_GENERAL(
+ "MSVDX DEBLOCK: pollx cmd space time out!\n");
+ goto finish_deblock;
+ }
+
+ cmd_count += 1;
+ break;
+ }
+ default:
+ ret = 1;
+ PSB_DEBUG_GENERAL(
+ "MSVDX DEBLOCK: get error cmd_id: 0x%x!\n",
+ cmd_id);
+ PSB_DEBUG_GENERAL(
+ "MSVDX DEBLOCK: execute cmd num is %d\n",
+ cmd_count);
+ /* printk("MSVDX DEBLOCK: get error cmd_id: 0x%x!\n",
+ cmd_id); */
+ /* printk("MSVDX DEBLOCK: execute cmd num is %d\n",
+ cmd_count); */
+ goto finish_deblock;
+ }
+ } while (cmd_count < cmd_size);
+
+
+finish_deblock:
+ PSB_DEBUG_GENERAL("MSVDX DEBLOCK: execute cmd num is %d\n", cmd_count);
+ return ret;
+}
+
+/*
+ * MSVDX MTX interrupt
+ */
+static void psb_msvdx_mtx_interrupt(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *)dev->dev_private;
+ static uint32_t buf[128]; /* message buffer */
+ uint32_t ridx, widx, buf_size, buf_offset;
+ uint32_t num, ofs; /* message num and offset */
+ struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+ int i;
+
+ PSB_DEBUG_GENERAL("MSVDX:Got a MSVDX MTX interrupt\n");
+
+ /* Are clocks enabled - If not enable before
+ * attempting to read from VLR
+ */
+ if (PSB_RMSVDX32(MSVDX_MAN_CLK_ENABLE) != (clk_enable_all)) {
+ PSB_DEBUG_GENERAL("MSVDX:Clocks disabled when Interupt set\n");
+ PSB_WMSVDX32(clk_enable_all, MSVDX_MAN_CLK_ENABLE);
+ }
+
+loop: /* just for coding style check */
+ ridx = PSB_RMSVDX32(MSVDX_COMMS_TO_HOST_RD_INDEX);
+ widx = PSB_RMSVDX32(MSVDX_COMMS_TO_HOST_WRT_INDEX);
+
+ /* Get out of here if nothing */
+ if (ridx == widx)
+ goto done;
+
+ buf_size = PSB_RMSVDX32(MSVDX_COMMS_TO_HOST_BUF_SIZE) & ((1 << 16) - 1);
+ /*0x2000 is VEC Local Ram offset*/
+ buf_offset =
+ (PSB_RMSVDX32(MSVDX_COMMS_TO_HOST_BUF_SIZE) >> 16) + 0x2000;
+
+ ofs = 0;
+ buf[ofs] = PSB_RMSVDX32(buf_offset + (ridx << 2));
+
+ /* round to nearest word */
+ num = (MEMIO_READ_FIELD(buf, FWRK_GENMSG_SIZE) + 3) / 4;
+
+ /* ASSERT(num <= sizeof(buf) / sizeof(uint32_t)); */
+
+ if (++ridx >= buf_size)
+ ridx = 0;
+
+ for (ofs++; ofs < num; ofs++) {
+ buf[ofs] = PSB_RMSVDX32(buf_offset + (ridx << 2));
+
+ if (++ridx >= buf_size)
+ ridx = 0;
+ }
+
+ /* Update the Read index */
+ PSB_WMSVDX32(ridx, MSVDX_COMMS_TO_HOST_RD_INDEX);
+
+ if (msvdx_priv->msvdx_needs_reset)
+ goto loop;
+
+ switch (MEMIO_READ_FIELD(buf, FWRK_GENMSG_ID)) {
+ case VA_MSGID_CMD_HW_PANIC:
+ case VA_MSGID_CMD_FAILED: {
+ /* For VXD385 firmware, fence value is not validate here */
+ uint32_t msg_id = MEMIO_READ_FIELD(buf, FWRK_GENMSG_ID);
+ uint32_t diff = 0;
+ uint32_t fence, fault;
+ uint32_t last_mb, first_mb;
+ drm_psb_msvdx_frame_info_t *failed_frame = NULL;
+
+ if (msg_id == VA_MSGID_CMD_HW_PANIC)
+ PSB_DEBUG_MSVDX("MSVDX_DEBUG: get panic message.\n");
+ else
+ PSB_DEBUG_MSVDX("MSVDX_DEBUG: get failed message.\n");
+
+ if (msg_id == VA_MSGID_CMD_HW_PANIC) {
+ fence = MEMIO_READ_FIELD(buf,
+ FW_VA_HW_PANIC_FENCE_VALUE);
+ first_mb = MEMIO_READ_FIELD(buf,
+ FW_VA_HW_PANIC_FIRST_MB_NUM);
+ last_mb = MEMIO_READ_FIELD(buf,
+ FW_VA_HW_PANIC_FAULT_MB_NUM);
+ printk("jiangfei debug: fence in panic message is %d.\n", fence);
+ PSB_DEBUG_MSVDX("MSVDX_DEBUG: PANIC MESSAGE fence is %d.\n", MEMIO_READ_FIELD(buf, FW_VA_HW_PANIC_FENCE_VALUE));
+ PSB_DEBUG_MSVDX("MSVDX_DEBUG: PANIC MESSAGE first mb num is %d.\n", MEMIO_READ_FIELD(buf, FW_VA_HW_PANIC_FIRST_MB_NUM));
+ PSB_DEBUG_MSVDX("MSVDX_DEBUG: PANIC MESSAGE fault mb num is %d.\n", MEMIO_READ_FIELD(buf, FW_VA_HW_PANIC_FAULT_MB_NUM));
+ PSB_DEBUG_MSVDX("MSVDX_DEBUG: PANIC MESSAGE fe status is 0x%x.\n", MEMIO_READ_FIELD(buf, FW_VA_HW_PANIC_FESTATUS));
+ PSB_DEBUG_MSVDX("MSVDX_DEBUG: PANIC MESSAGE be status is 0x%x.\n", MEMIO_READ_FIELD(buf, FW_VA_HW_PANIC_BESTATUS));
+ } else {
+ fence = MEMIO_READ_FIELD(buf,
+ FW_VA_CMD_FAILED_FENCE_VALUE);
+ PSB_DEBUG_MSVDX("MSVDX_DEBUG: FAILED MESSAGE fence is %d.\n", MEMIO_READ_FIELD(buf, FW_VA_HW_PANIC_FIRST_MB_NUM));
+ PSB_DEBUG_MSVDX("MSVDX_DEBUG: FAILED MESSAGE flag is %d.\n", MEMIO_READ_FIELD(buf, FW_VA_CMD_FAILED_FLAGS));
+ }
+
+ fence = MEMIO_READ_FIELD(buf, FW_DEVA_CMD_FAILED_MSG_ID);
+ fault = MEMIO_READ_FIELD(buf, FW_DEVA_CMD_FAILED_FLAGS);
+
+ if (msg_id == VA_MSGID_CMD_HW_PANIC)
+ PSB_DEBUG_GENERAL("MSVDX: VA_MSGID_CMD_HW_PANIC:"
+ "Fault detected"
+ " - Fence: %08x"
+ " - resetting and ignoring error\n",
+ fence);
+ else
+ PSB_DEBUG_GENERAL("MSVDX: VA_MSGID_CMD_FAILED:"
+ "Fault detected"
+ " - Fence: %08x"
+ " - resetting and ignoring error\n",
+ fence);
+
+ msvdx_priv->msvdx_needs_reset = 1;
+
+ if (msg_id == VA_MSGID_CMD_HW_PANIC) {
+ diff = msvdx_priv->msvdx_current_sequence
+ - dev_priv->sequence[PSB_ENGINE_VIDEO];
+
+ if (diff > 0x0FFFFFFF)
+ msvdx_priv->msvdx_current_sequence++;
+
+ PSB_DEBUG_GENERAL("MSVDX: Fence ID missing, "
+ "assuming %08x\n",
+ msvdx_priv->msvdx_current_sequence);
+ } else {
+ msvdx_priv->msvdx_current_sequence = fence;
+ }
+
+ psb_fence_error(dev, PSB_ENGINE_VIDEO,
+ msvdx_priv->msvdx_current_sequence,
+ _PSB_FENCE_TYPE_EXE, DRM_CMD_FAILED);
+
+ /* Flush the command queue */
+ psb_msvdx_flush_cmd_queue(dev);
+
+ if (msvdx_priv->host_be_opp_enabled) {
+ /*get the frame_info struct for error concealment frame*/
+ for (i = 0; i < MAX_DECODE_BUFFERS; i++) {
+ /*by default the fence is 0, so there is problem here???*/
+ if (msvdx_priv->frame_info[i].fence == fence) {
+ failed_frame = &msvdx_priv->frame_info[i];
+ break;
+ }
+ }
+ if (!failed_frame) {
+ DRM_ERROR("MSVDX: didn't find frame_info which matched the fence %d in failed/panic message\n", fence);
+ goto done;
+ }
+
+ failed_frame->fw_status = 1; /* set ERROR flag */
+ } else
+ msvdx_priv->fw_status = 1; /* set ERROR flag */
+
+ goto done;
+ }
+ case VA_MSGID_CMD_COMPLETED: {
+ uint32_t fence;
+ uint32_t flags = MEMIO_READ_FIELD(buf, FW_VA_CMD_COMPLETED_FLAGS);
+ /* uint32_t last_mb = MEMIO_READ_FIELD(buf,
+ FW_VA_CMD_COMPLETED_LASTMB);
+ */
+
+ fence = MEMIO_READ_FIELD(buf, FW_VA_CMD_COMPLETED_MSG_ID);
+
+ PSB_DEBUG_GENERAL("MSVDX:VA_MSGID_CMD_COMPLETED: "
+ "FenceID: %08x, flags: 0x%x\n",
+ fence, flags);
+
+ msvdx_priv->msvdx_current_sequence = fence;
+ msvdx_priv->ref_pic_fence = fence;
+
+ psb_fence_handler(dev, PSB_ENGINE_VIDEO);
+
+ if (flags & FW_VA_RENDER_HOST_INT) {
+ /*Now send the next command from the msvdx cmd queue */
+ psb_msvdx_dequeue_send(dev);
+ goto done;
+ }
+
+ break;
+ }
+ case VA_MSGID_CMD_COMPLETED_BATCH: {
+ uint32_t fence = MEMIO_READ_FIELD(buf,
+ FW_VA_CMD_COMPLETED_FENCE_VALUE);
+ uint32_t tickcnt = MEMIO_READ_FIELD(buf,
+ FW_VA_CMD_COMPLETED_NO_TICKS);
+ (void)tickcnt;
+ /* we have the fence value in the message */
+ PSB_DEBUG_GENERAL("MSVDX:VA_MSGID_CMD_COMPLETED_BATCH:"
+ " FenceID: %08x, TickCount: %08x\n",
+ fence, tickcnt);
+ msvdx_priv->msvdx_current_sequence = fence;
+
+ break;
+ }
+ case VA_MSGID_ACK:
+ PSB_DEBUG_GENERAL("MSVDX: VA_MSGID_ACK\n");
+ break;
+
+ case VA_MSGID_TEST1:
+ PSB_DEBUG_GENERAL("MSVDX: VA_MSGID_TEST1\n");
+ break;
+
+ /* Penwell deblock is not implemented here */
+ case VA_MSGID_DEBLOCK_REQUIRED: {
+ uint32_t ctxid = MEMIO_READ_FIELD(buf,
+ FW_VA_DEBLOCK_REQUIRED_CONTEXT);
+ struct psb_msvdx_deblock_queue *msvdx_deblock;
+ uint32_t fence = MEMIO_READ_FIELD(buf,
+ FW_VA_DEBLOCK_REQUIRED_FENCE_VALUE);
+
+ PSB_DEBUG_GENERAL("MSVDX: VA_MSGID_DEBLOCK_REQUIRED"
+ " Context=%08x\n", ctxid);
+
+
+ /*deblock and on-be-opp use the same message, there is difficulty to distinguish them*/
+ /*now I just let user space use cpu copy error mb*/
+ if ((msvdx_priv->deblock_enabled == 1) && (msvdx_priv->host_be_opp_enabled == 1)) {
+ DRM_ERROR("MSVDX: should not support both deblock and host_be_opp message. \n");
+ goto done;
+ } else if (msvdx_priv->deblock_enabled == 1) {
+ PSB_DEBUG_MSVDX("MSVDX_DEBUG: get deblock required message for deblock operation.\n");
+ if (list_empty(&msvdx_priv->deblock_queue)) {
+ PSB_DEBUG_GENERAL(
+ "DEBLOCKQUE: deblock param list is empty\n");
+ PSB_WMSVDX32(0, MSVDX_CMDS_END_SLICE_PICTURE);
+ PSB_WMSVDX32(1, MSVDX_CMDS_END_SLICE_PICTURE);
+ goto done;
+ }
+ msvdx_deblock = list_first_entry(&msvdx_priv->deblock_queue,
+ struct psb_msvdx_deblock_queue, head);
+
+ if (0) {
+ PSB_DEBUG_GENERAL("MSVDX DEBLOCK: by pass \n");
+ /* try to unblock rendec */
+ PSB_WMSVDX32(0, MSVDX_CMDS_END_SLICE_PICTURE);
+ PSB_WMSVDX32(1, MSVDX_CMDS_END_SLICE_PICTURE);
+ kfree(msvdx_deblock->dbParams.pPicparams);
+ list_del(&msvdx_deblock->head);
+ goto done;
+ }
+
+
+ if (ctxid != msvdx_deblock->dbParams.ctxid) {
+ PSB_DEBUG_GENERAL("MSVDX DEBLOCK: wrong ctxid, may "
+ "caused by multiple context since "
+ "it's not supported yet\n");
+ /* try to unblock rendec */
+ PSB_WMSVDX32(0, MSVDX_CMDS_END_SLICE_PICTURE);
+ PSB_WMSVDX32(1, MSVDX_CMDS_END_SLICE_PICTURE);
+ kfree(msvdx_deblock->dbParams.pPicparams);
+ list_del(&msvdx_deblock->head);
+ goto done;
+ }
+
+ if (msvdx_deblock->dbParams.pPicparams) {
+ PSB_DEBUG_GENERAL("MSVDX DEBLOCK: start deblocking\n");
+ /* printk("MSVDX DEBLOCK: start deblocking\n"); */
+
+ if (psb_msvdx_towpass_deblock(dev,
+ msvdx_deblock->dbParams.pPicparams)) {
+
+ PSB_DEBUG_GENERAL(
+ "MSVDX DEBLOCK: deblock fail!\n");
+ PSB_WMSVDX32(0, MSVDX_CMDS_END_SLICE_PICTURE);
+ PSB_WMSVDX32(1, MSVDX_CMDS_END_SLICE_PICTURE);
+ }
+ kfree(msvdx_deblock->dbParams.pPicparams);
+ } else {
+ PSB_DEBUG_GENERAL("MSVDX DEBLOCK: deblock abort!\n");
+ /* printk("MSVDX DEBLOCK: deblock abort!\n"); */
+ PSB_WMSVDX32(0, MSVDX_CMDS_END_SLICE_PICTURE);
+ PSB_WMSVDX32(1, MSVDX_CMDS_END_SLICE_PICTURE);
+ }
+
+ list_del(&msvdx_deblock->head);
+ kfree(msvdx_deblock);
+ } else if (msvdx_priv->host_be_opp_enabled == 1) {
+ PSB_DEBUG_MSVDX("MSVDX_DEBUG: get deblock required message for error concealment.\n");
+
+ /* try to unblock rendec */
+ PSB_WMSVDX32(0, MSVDX_CMDS_END_SLICE_PICTURE);
+ PSB_WMSVDX32(1, MSVDX_CMDS_END_SLICE_PICTURE);
+
+ /*do error concealment with hw*/
+ msvdx_priv->ec_fence = fence;
+ schedule_work(&msvdx_priv->ec_work);
+ }
+
+ break;
+ }
+
+ case VA_MSGID_CMD_CONTIGUITY_WARNING: {
+ drm_psb_msvdx_frame_info_t *ec_frame = NULL;
+ drm_psb_msvdx_decode_status_t *fault_region = NULL;
+
+ /*get erro info*/
+ uint32_t fence = MEMIO_READ_FIELD(buf,
+ FW_VA_CONTIGUITY_WARNING_FENCE_VALUE);
+ uint32_t ui32Start = MEMIO_READ_FIELD(buf,
+ FW_VA_CONTIGUITY_WARNING_BEGIN_MB_NUM);
+ uint32_t ui32End = MEMIO_READ_FIELD(buf,
+ FW_VA_CONTIGUITY_WARNING_END_MB_NUM);
+ PSB_DEBUG_GENERAL("MSVDX: VA_MSGID_CMD_CONTIGUITY_WARNING\n");
+ PSB_DEBUG_MSVDX("MSVDX_DEBUG: get contiguity warning message.\n");
+ PSB_DEBUG_MSVDX("MSVDX_DEBUG: CONTIGUITY_WARNING MESSAGE fence is %d.\n", MEMIO_READ_FIELD(buf, FW_VA_CONTIGUITY_WARNING_FENCE_VALUE));
+ PSB_DEBUG_MSVDX("MSVDX_DEBUG: CONTIGUITY_WARNING MESSAGE end mb num is %d.\n", MEMIO_READ_FIELD(buf, FW_VA_CONTIGUITY_WARNING_END_MB_NUM));
+ PSB_DEBUG_MSVDX("MSVDX_DEBUG: CONTIGUITY_WARNING MESSAGE begin mb num is %d.\n", MEMIO_READ_FIELD(buf, FW_VA_CONTIGUITY_WARNING_BEGIN_MB_NUM));
+
+ /*get the frame_info struct for error concealment frame*/
+ for (i = 0; i < MAX_DECODE_BUFFERS; i++) {
+ if (msvdx_priv->frame_info[i].fence == fence) {
+ ec_frame = &msvdx_priv->frame_info[i];
+ break;
+ }
+ }
+ if (!ec_frame) {
+ DRM_ERROR("MSVDX: didn't find frame_info which matched the fence %d when get contiguity warning.\n", fence);
+ goto done;
+ } else if (msvdx_priv->host_be_opp_enabled) {
+ ec_frame->fw_status = 1;
+ fault_region = &ec_frame->decode_status;
+ if (ui32Start == 0xffff) {
+ if (fault_region->num_error_slice == 0) {
+ fault_region->start_error_mb_list[fault_region->num_error_slice] = 0;
+ fault_region->end_error_mb_list[fault_region->num_error_slice] = ui32End;
+ fault_region->num_error_slice++;
+ } else if (fault_region->end_error_mb_list[fault_region->num_error_slice - 1] == 0xffff) {
+ fault_region->end_error_mb_list[fault_region->num_error_slice - 1] = ui32End;
+ }
+ } else if (ui32Start < ui32End) {
+ fault_region->start_error_mb_list[fault_region->num_error_slice] = ui32Start;
+ fault_region->end_error_mb_list[fault_region->num_error_slice] = ui32End;
+ fault_region->num_error_slice++;
+ } else {
+ DRM_ERROR("msvdx error: start mb counter should not be larger than end mb counter.\n");
+ goto done;
+ }
+ }
+
+ break;
+
+ }
+ default:
+ DRM_ERROR("ERROR: msvdx Unknown message from MTX, ID:0x%08x\n", MEMIO_READ_FIELD(buf, FWRK_GENMSG_ID));
+ goto done;
+ }
+
+done:
+ if (ridx != widx) {
+ PSB_DEBUG_GENERAL("MSVDX Interrupt: there are more message to be read\n");
+ goto loop;
+ }
+ /* we get a frame/slice done, try to save some power*/
+ if (drm_msvdx_pmpolicy != PSB_PMPOLICY_NOPM)
+ schedule_delayed_work(&dev_priv->scheduler.msvdx_suspend_wq, 0);
+
+ DRM_MEMORYBARRIER(); /* TBD check this... */
+}
+
+
+/*
+ * MSVDX interrupt.
+ */
+IMG_BOOL psb_msvdx_interrupt(IMG_VOID *pvData)
+{
+ struct drm_device *dev;
+ struct drm_psb_private *dev_priv;
+ struct msvdx_private *msvdx_priv;
+ uint32_t msvdx_stat;
+
+ if (pvData == IMG_NULL) {
+ DRM_ERROR("ERROR: msvdx %s, Invalid params\n", __func__);
+ return IMG_FALSE;
+ }
+
+ dev = (struct drm_device *)pvData;
+
+ dev_priv = (struct drm_psb_private *) dev->dev_private;
+ msvdx_priv = dev_priv->msvdx_private;
+
+ msvdx_priv->msvdx_hw_busy = REG_READ(0x20D0) & (0x1 << 9);
+
+ msvdx_stat = PSB_RMSVDX32(MSVDX_INTERRUPT_STATUS);
+
+ if (msvdx_stat & MSVDX_INTERRUPT_STATUS_CR_MMU_FAULT_IRQ_MASK) {
+ /*Ideally we should we should never get to this */
+ PSB_DEBUG_IRQ("MSVDX:MMU Fault:0x%x\n", msvdx_stat);
+
+ /* Pause MMU */
+ PSB_WMSVDX32(MSVDX_MMU_CONTROL0_CR_MMU_PAUSE_MASK,
+ MSVDX_MMU_CONTROL0);
+ DRM_WRITEMEMORYBARRIER();
+
+ /* Clear this interupt bit only */
+ PSB_WMSVDX32(MSVDX_INTERRUPT_STATUS_CR_MMU_FAULT_IRQ_MASK,
+ MSVDX_INTERRUPT_CLEAR);
+ PSB_RMSVDX32(MSVDX_INTERRUPT_CLEAR);
+ DRM_READMEMORYBARRIER();
+
+ msvdx_priv->msvdx_needs_reset = 1;
+ } else if (msvdx_stat & MSVDX_INTERRUPT_STATUS_CR_MTX_IRQ_MASK) {
+ PSB_DEBUG_IRQ
+ ("MSVDX: msvdx_stat: 0x%x(MTX)\n", msvdx_stat);
+
+ /* Clear all interupt bits */
+ PSB_WMSVDX32(0xffff, MSVDX_INTERRUPT_CLEAR);
+ PSB_RMSVDX32(MSVDX_INTERRUPT_CLEAR);
+ DRM_READMEMORYBARRIER();
+
+ psb_msvdx_mtx_interrupt(dev);
+ }
+
+ return IMG_TRUE;
+}
+
+
+void psb_msvdx_lockup(struct drm_psb_private *dev_priv,
+ int *msvdx_lockup, int *msvdx_idle)
+{
+ int diff;
+ struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+
+ *msvdx_lockup = 0;
+ *msvdx_idle = 1;
+
+#if 0
+ PSB_DEBUG_GENERAL("MSVDXTimer: current_sequence:%d "
+ "last_sequence:%d and last_submitted_sequence :%d\n",
+ msvdx_priv->msvdx_current_sequence,
+ msvdx_priv->msvdx_last_sequence,
+ dev_priv->sequence[PSB_ENGINE_VIDEO]);
+#endif
+
+ diff = msvdx_priv->msvdx_current_sequence -
+ dev_priv->sequence[PSB_ENGINE_VIDEO];
+
+ if (diff > 0x0FFFFFFF) {
+ if (msvdx_priv->msvdx_current_sequence ==
+ msvdx_priv->msvdx_last_sequence) {
+ DRM_ERROR("MSVDXTimer:locked-up for sequence:%d\n",
+ msvdx_priv->msvdx_current_sequence);
+ *msvdx_lockup = 1;
+ } else {
+ PSB_DEBUG_GENERAL("MSVDXTimer: "
+ "msvdx responded fine so far\n");
+ msvdx_priv->msvdx_last_sequence =
+ msvdx_priv->msvdx_current_sequence;
+ *msvdx_idle = 0;
+ }
+ }
+}
+
+int psb_check_msvdx_idle(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *)dev->dev_private;
+ struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+ /* drm_psb_msvdx_frame_info_t *current_frame = NULL; */
+
+ if (msvdx_priv->msvdx_fw_loaded == 0)
+ return 0;
+
+ if (msvdx_priv->msvdx_busy) {
+ PSB_DEBUG_PM("MSVDX: psb_check_msvdx_idle returns busy\n");
+ return -EBUSY;
+ }
+ /*
+ if (msvdx_priv->msvdx_hw_busy) {
+ PSB_DEBUG_PM("MSVDX: %s, HW is busy\n", __func__);
+ return -EBUSY;
+ }
+ */
+ return 0;
+}
+
+
+int psb_remove_videoctx(struct drm_psb_private *dev_priv, struct file *filp)
+{
+ struct psb_video_ctx *pos, *n;
+
+ list_for_each_entry_safe(pos, n, &dev_priv->video_ctx, head) {
+ if (pos->filp == filp) {
+ PSB_DEBUG_GENERAL("Video:remove context profile %d,"
+ " entrypoint %d",
+ (pos->ctx_type >> 8),
+ (pos->ctx_type & 0xff));
+ /*Reset fw load status here.*/
+ if ((VAEntrypointEncSlice == (pos->ctx_type & 0xff)
+ || VAEntrypointEncPicture ==
+ (pos->ctx_type & 0xff)))
+ pnw_reset_fw_status(dev_priv->dev);
+
+ /* if current ctx points to it, set to NULL */
+ if (dev_priv->topaz_ctx == pos)
+ dev_priv->topaz_ctx = NULL;
+ if (dev_priv->last_topaz_ctx == pos)
+ dev_priv->last_topaz_ctx = NULL;
+
+ if (dev_priv->msvdx_ctx == pos)
+ dev_priv->msvdx_ctx = NULL;
+ if (dev_priv->last_msvdx_ctx == pos)
+ dev_priv->last_msvdx_ctx = NULL;
+
+ list_del(&pos->head);
+ kfree(pos);
+ }
+ }
+ return 0;
+}
+
+
+int lnc_video_getparam(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_lnc_video_getparam_arg *arg = data;
+ int ret = 0;
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *)file_priv->minor->dev->dev_private;
+ drm_psb_msvdx_frame_info_t *current_frame = NULL;
+ uint32_t handle, i;
+
+#if defined(CONFIG_MRST_RAR_HANDLER)
+ struct RAR_buffer rar_buf;
+ size_t rar_status;
+#endif
+ void *rar_handler;
+ uint32_t offset = 0;
+ uint32_t device_info = 0;
+ uint32_t ctx_type = 0;
+ struct psb_video_ctx *video_ctx = NULL;
+ uint32_t rar_ci_info[2];
+ struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+
+ switch (arg->key) {
+ case LNC_VIDEO_GETPARAM_RAR_INFO:
+ rar_ci_info[0] = dev_priv->rar_region_start;
+ rar_ci_info[1] = dev_priv->rar_region_size;
+ ret = copy_to_user((void __user *)((unsigned long)arg->value),
+ &rar_ci_info[0],
+ sizeof(rar_ci_info));
+ break;
+ case LNC_VIDEO_GETPARAM_CI_INFO:
+ rar_ci_info[0] = dev_priv->ci_region_start;
+ rar_ci_info[1] = dev_priv->ci_region_size;
+ ret = copy_to_user((void __user *)((unsigned long)arg->value),
+ &rar_ci_info[0],
+ sizeof(rar_ci_info));
+ break;
+ case LNC_VIDEO_GETPARAM_RAR_HANDLER_OFFSET:
+ ret = copy_from_user(&rar_handler,
+ (void __user *)((unsigned long)arg->arg),
+ sizeof(rar_handler));
+ if (ret)
+ break;
+
+#if defined(CONFIG_MRST_RAR_HANDLER)
+ rar_buf.info.handle = (__u32)rar_handler;
+ rar_buf.bus_address = (dma_addr_t)dev_priv->rar_region_start;
+ rar_status = 1;
+
+ rar_status = rar_handle_to_bus(&rar_buf, 1);
+ if (rar_status != 1) {
+ DRM_ERROR("MSVDX:rar_handle_to_bus failed\n");
+ ret = -1;
+ break;
+ }
+ rar_status = rar_release(&rar_buf, 1);
+ if (rar_status != 1)
+ DRM_ERROR("MSVDX:rar_release failed\n");
+
+ offset = (uint32_t) rar_buf.bus_address - dev_priv->rar_region_start;
+ PSB_DEBUG_GENERAL("MSVDX:RAR handler %p, bus address=0x%08x,"
+ "RAR region=0x%08x\n",
+ rar_handler,
+ (uint32_t)rar_buf.bus_address,
+ dev_priv->rar_region_start);
+#endif
+ ret = copy_to_user((void __user *)((unsigned long)arg->value),
+ &offset,
+ sizeof(offset));
+ break;
+ case LNC_VIDEO_FRAME_SKIP:
+ ret = -EFAULT;
+ break;
+ case LNC_VIDEO_DEVICE_INFO:
+ device_info = 0xffff & dev_priv->video_device_fuse;
+ device_info |= (0xffff & dev->pci_device) << 16;
+
+ ret = copy_to_user((void __user *)((unsigned long)arg->value),
+ &device_info, sizeof(device_info));
+ break;
+ case IMG_VIDEO_NEW_CONTEXT:
+ /* add video decode/encode context */
+ ret = copy_from_user(&ctx_type, (void __user *)((unsigned long)arg->value),
+ sizeof(ctx_type));
+ video_ctx = kmalloc(sizeof(struct psb_video_ctx), GFP_KERNEL);
+ if (video_ctx == NULL) {
+ ret = -ENOMEM;
+ break;
+ }
+ INIT_LIST_HEAD(&video_ctx->head);
+ video_ctx->ctx_type = ctx_type;
+ video_ctx->filp = file_priv->filp;
+ list_add(&video_ctx->head, &dev_priv->video_ctx);
+ PSB_DEBUG_GENERAL("Video:add context profile %d, entrypoint %d",
+ (ctx_type >> 8), (ctx_type & 0xff));
+ break;
+
+ case IMG_VIDEO_RM_CONTEXT:
+ psb_remove_videoctx(dev_priv, file_priv->filp);
+ break;
+ case IMG_VIDEO_DECODE_STATUS:
+ if (msvdx_priv->host_be_opp_enabled) {
+ /*get the right frame_info struct for current surface*/
+ ret = copy_from_user(&handle,
+ (void __user *)((unsigned long)arg->arg), 4);
+ if (ret) {
+ DRM_ERROR("MSVDX in lnc_video_getparam, copy_from_user failed.\n");
+ break;
+ }
+
+ for (i = 0; i < MAX_DECODE_BUFFERS; i++) {
+ if (msvdx_priv->frame_info[i].handle == handle) {
+ current_frame = &msvdx_priv->frame_info[i];
+ break;
+ }
+ }
+ if (!current_frame) {
+ DRM_ERROR("MSVDX: didn't find frame_info which matched the surface_id. \n");
+ return -EFAULT;
+ }
+ ret = copy_to_user((void __user *)((unsigned long)arg->value),
+ ¤t_frame->fw_status, sizeof(current_frame->fw_status));
+ } else
+ ret = copy_to_user((void __user *)((unsigned long)arg->value),
+ &msvdx_priv->fw_status, sizeof(msvdx_priv->fw_status));
+ break;
+
+ case IMG_VIDEO_MB_ERROR:
+ /*get the right frame_info struct for current surface*/
+ ret = copy_from_user(&handle,
+ (void __user *)((unsigned long)arg->arg), 4);
+ if (ret)
+ break;
+
+ for (i = 0; i < MAX_DECODE_BUFFERS; i++) {
+ if (msvdx_priv->frame_info[i].handle == handle) {
+ current_frame = &msvdx_priv->frame_info[i];
+ break;
+ }
+ }
+ if (!current_frame) {
+ DRM_ERROR("MSVDX: didn't find frame_info which matched the surface_id. \n");
+ return -EFAULT;
+ }
+ ret = copy_to_user((void __user *)((unsigned long)arg->value),
+ &(current_frame->decode_status), sizeof(drm_psb_msvdx_decode_status_t));
+ if (ret) {
+ DRM_ERROR("lnc_video_getparam copy_to_user error.\n");
+ return -EFAULT;
+ }
+ break;
+
+
+ default:
+ ret = -EFAULT;
+ break;
+ }
+
+ if (ret)
+ return -EFAULT;
+
+ return 0;
+}
+
+inline int psb_try_power_down_msvdx(struct drm_device *dev)
+{
+ ospm_apm_power_down_msvdx(dev);
+ return 0;
+}
+
+int psb_msvdx_save_context(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *)dev->dev_private;
+ struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+ int offset = 0;
+
+ msvdx_priv->msvdx_needs_reset = 1;
+
+ for (offset = 0; offset < VEC_LOCAL_MEM_BYTE_SIZE / 4; ++offset)
+ msvdx_priv->vec_local_mem_data[offset] =
+ PSB_RMSVDX32(VEC_LOCAL_MEM_OFFSET + offset * 4);
+
+ msvdx_priv->vec_local_mem_saved = 1;
+
+ return 0;
+}
+
+int psb_msvdx_restore_context(struct drm_device *dev)
+{
+ return 0;
+}
--- /dev/null
+/**************************************************************************
+ *
+ * Copyright (c) 2007 Intel Corporation, Hillsboro, OR, USA
+ * Copyright (c) Imagination Technologies Limited, UK
+ *
+ * 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 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.
+ *
+ **************************************************************************/
+
+#ifndef _PSB_MSVDX_H_
+#define _PSB_MSVDX_H_
+
+#include "psb_drv.h"
+#include "img_types.h"
+
+#if defined(CONFIG_MRST_RAR_HANDLER)
+#include "../../memrar/memrar.h"
+#endif
+
+extern int drm_msvdx_pmpolicy;
+extern int drm_msvdx_delay;
+
+typedef enum {
+ PSB_DMAC_BSWAP_NO_SWAP = 0x0, //!< No byte swapping will be performed.
+ PSB_DMAC_BSWAP_REVERSE = 0x1, //!< Byte order will be reversed.
+
+} DMAC_eBSwap;
+
+typedef enum {
+ PSB_DMAC_DIR_MEM_TO_PERIPH = 0x0, //!< Data from memory to peripheral.
+ PSB_DMAC_DIR_PERIPH_TO_MEM = 0x1, //!< Data from peripheral to memory.
+
+} DMAC_eDir;
+
+typedef enum {
+ PSB_DMAC_ACC_DEL_0 = 0x0, //!< Access delay zero clock cycles
+ PSB_DMAC_ACC_DEL_256 = 0x1, //!< Access delay 256 clock cycles
+ PSB_DMAC_ACC_DEL_512 = 0x2, //!< Access delay 512 clock cycles
+ PSB_DMAC_ACC_DEL_768 = 0x3, //!< Access delay 768 clock cycles
+ PSB_DMAC_ACC_DEL_1024 = 0x4, //!< Access delay 1024 clock cycles
+ PSB_DMAC_ACC_DEL_1280 = 0x5, //!< Access delay 1280 clock cycles
+ PSB_DMAC_ACC_DEL_1536 = 0x6, //!< Access delay 1536 clock cycles
+ PSB_DMAC_ACC_DEL_1792 = 0x7, //!< Access delay 1792 clock cycles
+
+} DMAC_eAccDel;
+
+typedef enum {
+ PSB_DMAC_INCR_OFF = 0, //!< Static peripheral address.
+ PSB_DMAC_INCR_ON = 1 //!< Incrementing peripheral address.
+
+} DMAC_eIncr;
+
+typedef enum {
+ PSB_DMAC_BURST_0 = 0x0, //!< burst size of 0
+ PSB_DMAC_BURST_1 = 0x1, //!< burst size of 1
+ PSB_DMAC_BURST_2 = 0x2, //!< burst size of 2
+ PSB_DMAC_BURST_3 = 0x3, //!< burst size of 3
+ PSB_DMAC_BURST_4 = 0x4, //!< burst size of 4
+ PSB_DMAC_BURST_5 = 0x5, //!< burst size of 5
+ PSB_DMAC_BURST_6 = 0x6, //!< burst size of 6
+ PSB_DMAC_BURST_7 = 0x7, //!< burst size of 7
+
+} DMAC_eBurst;
+
+int psb_wait_for_register(struct drm_psb_private *dev_priv,
+ uint32_t offset,
+ uint32_t value,
+ uint32_t enable);
+
+IMG_BOOL psb_msvdx_interrupt(IMG_VOID *pvData);
+
+int psb_msvdx_init(struct drm_device *dev);
+int psb_msvdx_uninit(struct drm_device *dev);
+int psb_msvdx_reset(struct drm_psb_private *dev_priv);
+uint32_t psb_get_default_pd_addr(struct psb_mmu_driver *driver);
+int psb_mtx_send(struct drm_psb_private *dev_priv, const void *pvMsg);
+void psb_msvdx_flush_cmd_queue(struct drm_device *dev);
+void psb_msvdx_lockup(struct drm_psb_private *dev_priv,
+ int *msvdx_lockup, int *msvdx_idle);
+int psb_setup_fw(struct drm_device *dev);
+int psb_check_msvdx_idle(struct drm_device *dev);
+int psb_wait_msvdx_idle(struct drm_device *dev);
+int psb_cmdbuf_video(struct drm_file *priv,
+ struct list_head *validate_list,
+ uint32_t fence_type,
+ struct drm_psb_cmdbuf_arg *arg,
+ struct ttm_buffer_object *cmd_buffer,
+ struct psb_ttm_fence_rep *fence_arg);
+int psb_msvdx_save_context(struct drm_device *dev);
+int psb_msvdx_restore_context(struct drm_device *dev);
+
+bool
+psb_host_second_pass(struct drm_device *dev,
+ uint32_t ui32OperatingModeCmd,
+ void *pvParamBase,
+ uint32_t PicWidthInMbs,
+ uint32_t FrameHeightInMbs,
+ uint32_t ui32DeblockSourceY,
+ uint32_t ui32DeblockSourceUV);
+
+/* Non-Optimal Invalidation is not default */
+#define MSVDX_DEVICE_NODE_FLAGS_MMU_NONOPT_INV 2
+#define MSVDX_CORE_CR_MSVDX_CONTROL_CR_MSVDX_SOFT_RESET_MASK (0x00000100)
+
+#define FW_VA_RENDER_HOST_INT 0x00004000
+#define MSVDX_DEVICE_NODE_FLAGS_MMU_HW_INVALIDATION 0x00000020
+
+/* There is no work currently underway on the hardware */
+#define MSVDX_FW_STATUS_HW_IDLE 0x00000001
+#define MSVDX_DEVICE_NODE_FLAG_BRN23154_BLOCK_ON_FE 0x00000200
+#define MSVDX_DEVICE_NODE_FLAGS_DEFAULT_D0 \
+ (MSVDX_DEVICE_NODE_FLAGS_MMU_NONOPT_INV | \
+ MSVDX_DEVICE_NODE_FLAGS_MMU_HW_INVALIDATION | \
+ MSVDX_DEVICE_NODE_FLAG_BRN23154_BLOCK_ON_FE)
+
+#define MSVDX_DEVICE_NODE_FLAGS_DEFAULT_D1 \
+ (MSVDX_DEVICE_NODE_FLAGS_MMU_HW_INVALIDATION | \
+ MSVDX_DEVICE_NODE_FLAG_BRN23154_BLOCK_ON_FE)
+
+#define POULSBO_D0 0x5
+#define POULSBO_D1 0x6
+#define PSB_REVID_OFFSET 0x8
+
+#define MTX_CODE_BASE (0x80900000)
+#define MTX_DATA_BASE (0x82880000)
+#define PC_START_ADDRESS (0x80900000)
+
+#define MTX_CORE_CODE_MEM (0x10)
+#define MTX_CORE_DATA_MEM (0x18)
+
+#define MSVDX_CONTROL_CR_MSVDX_SOFT_RESET_MASK (0x00000100)
+#define MSVDX_CONTROL_CR_MSVDX_SOFT_RESET_SHIFT (8)
+#define MSVDX_CORE_CR_MSVDX_CONTROL_CR_MSVDX_FE_SOFT_RESET_MASK \
+ (0x00010000)
+#define MSVDX_CORE_CR_MSVDX_CONTROL_CR_MSVDX_BE_SOFT_RESET_MASK \
+ (0x00100000)
+#define MSVDX_CORE_CR_MSVDX_CONTROL_CR_MSVDX_VEC_MEMIF_SOFT_RESET_MASK \
+ (0x01000000)
+#define MSVDX_CORE_CR_MSVDX_CONTROL_CR_MSVDX_VEC_RENDEC_DEC_SOFT_RESET_MASK \
+ (0x10000000)
+
+#define clk_enable_all \
+(MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_CORE_MAN_CLK_ENABLE_MASK | \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VDEB_PROCESS_MAN_CLK_ENABLE_MASK | \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VDEB_ACCESS_MAN_CLK_ENABLE_MASK | \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VDMC_MAN_CLK_ENABLE_MASK | \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VEC_ENTDEC_MAN_CLK_ENABLE_MASK | \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VEC_ITRANS_MAN_CLK_ENABLE_MASK | \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_MTX_MAN_CLK_ENABLE_MASK)
+
+#define clk_enable_minimal \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_CORE_MAN_CLK_ENABLE_MASK | \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_MTX_MAN_CLK_ENABLE_MASK
+
+#define clk_enable_auto \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VDEB_PROCESS_AUTO_CLK_ENABLE_MASK | \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VDEB_ACCESS_AUTO_CLK_ENABLE_MASK | \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VDMC_AUTO_CLK_ENABLE_MASK | \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VEC_ENTDEC_AUTO_CLK_ENABLE_MASK | \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VEC_ITRANS_AUTO_CLK_ENABLE_MASK | \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_CORE_MAN_CLK_ENABLE_MASK | \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_MTX_MAN_CLK_ENABLE_MASK
+
+#define msvdx_sw_reset_all \
+(MSVDX_CORE_CR_MSVDX_CONTROL_CR_MSVDX_SOFT_RESET_MASK | \
+MSVDX_CORE_CR_MSVDX_CONTROL_CR_MSVDX_FE_SOFT_RESET_MASK | \
+MSVDX_CORE_CR_MSVDX_CONTROL_CR_MSVDX_BE_SOFT_RESET_MASK | \
+MSVDX_CORE_CR_MSVDX_CONTROL_CR_MSVDX_VEC_MEMIF_SOFT_RESET_MASK | \
+MSVDX_CORE_CR_MSVDX_CONTROL_CR_MSVDX_VEC_RENDEC_DEC_SOFT_RESET_MASK)
+
+#define MTX_INTERNAL_REG(R_SPECIFIER , U_SPECIFIER) \
+ (((R_SPECIFIER)<<4) | (U_SPECIFIER))
+#define MTX_PC MTX_INTERNAL_REG(0, 5)
+
+#define RENDEC_A_SIZE (4 * 1024 * 1024)
+#define RENDEC_B_SIZE (1024 * 1024)
+
+#define MEMIO_READ_FIELD(vpMem, field) \
+ ((uint32_t)(((*((field##_TYPE*)(((uint32_t)vpMem) + field##_OFFSET))) \
+ & field##_MASK) >> field##_SHIFT))
+
+#define MEMIO_WRITE_FIELD(vpMem, field, value) \
+ (*((field##_TYPE*)(((uint32_t)vpMem) + field##_OFFSET))) = \
+ ((*((field##_TYPE*)(((uint32_t)vpMem) + field##_OFFSET))) \
+ & (field##_TYPE)~field##_MASK) | \
+ (field##_TYPE)(((uint32_t)(value) << field##_SHIFT) & field##_MASK)
+
+#define MEMIO_WRITE_FIELD_LITE(vpMem, field, value) \
+ (*((field##_TYPE*)(((uint32_t)vpMem) + field##_OFFSET))) = \
+ ((*((field##_TYPE*)(((uint32_t)vpMem) + field##_OFFSET))) | \
+ (field##_TYPE)(((uint32_t)(value) << field##_SHIFT)));
+
+#define REGIO_READ_FIELD(reg_val, reg, field) \
+ ((reg_val & reg##_##field##_MASK) >> reg##_##field##_SHIFT)
+
+#define REGIO_WRITE_FIELD(reg_val, reg, field, value) \
+ (reg_val) = \
+ ((reg_val) & ~(reg##_##field##_MASK)) | \
+ (((value) << (reg##_##field##_SHIFT)) & (reg##_##field##_MASK));
+
+#define REGIO_WRITE_FIELD_LITE(reg_val, reg, field, value) \
+ (reg_val) = \
+ ((reg_val) | ((value) << (reg##_##field##_SHIFT)));
+
+#define MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_CORE_MAN_CLK_ENABLE_MASK \
+ (0x00000001)
+#define MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VDEB_PROCESS_MAN_CLK_ENABLE_MASK \
+ (0x00000002)
+#define MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VDEB_ACCESS_MAN_CLK_ENABLE_MASK \
+ (0x00000004)
+#define MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VDMC_MAN_CLK_ENABLE_MASK \
+ (0x00000008)
+#define MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VEC_ENTDEC_MAN_CLK_ENABLE_MASK \
+ (0x00000010)
+#define MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VEC_ITRANS_MAN_CLK_ENABLE_MASK \
+ (0x00000020)
+#define MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_MTX_MAN_CLK_ENABLE_MASK \
+ (0x00000040)
+
+#define clk_enable_all \
+ (MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_CORE_MAN_CLK_ENABLE_MASK | \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VDEB_PROCESS_MAN_CLK_ENABLE_MASK | \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VDEB_ACCESS_MAN_CLK_ENABLE_MASK | \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VDMC_MAN_CLK_ENABLE_MASK | \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VEC_ENTDEC_MAN_CLK_ENABLE_MASK | \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_VEC_ITRANS_MAN_CLK_ENABLE_MASK | \
+MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_MTX_MAN_CLK_ENABLE_MASK)
+
+#define clk_enable_minimal \
+ MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_CORE_MAN_CLK_ENABLE_MASK | \
+ MSVDX_CORE_CR_MSVDX_MAN_CLK_ENABLE_CR_MTX_MAN_CLK_ENABLE_MASK
+
+/* MTX registers */
+#define MSVDX_MTX_ENABLE (0x0000)
+#define MSVDX_MTX_KICKI (0x0088)
+#define MSVDX_MTX_KICK (0x0080)
+#define MSVDX_MTX_REGISTER_READ_WRITE_REQUEST (0x00FC)
+#define MSVDX_MTX_REGISTER_READ_WRITE_DATA (0x00F8)
+#define MSVDX_MTX_RAM_ACCESS_DATA_TRANSFER (0x0104)
+#define MSVDX_MTX_RAM_ACCESS_CONTROL (0x0108)
+#define MSVDX_MTX_RAM_ACCESS_STATUS (0x010C)
+#define MSVDX_MTX_SOFT_RESET (0x0200)
+#define MSVDX_MTX_SYSC_TIMERDIV (0x0208)
+#define MTX_CORE_CR_MTX_SYSC_CDMAS0_OFFSET (0x0348)
+#define MTX_CORE_CR_MTX_SYSC_CDMAA_OFFSET (0x0344)
+#define MTX_CORE_CR_MTX_SYSC_CDMAT_OFFSET (0x0350)
+#define MTX_CORE_CR_MTX_SYSC_CDMAC_OFFSET (0x0340)
+
+/* MSVDX registers */
+#define MSVDX_CONTROL (0x0600)
+#define MSVDX_INTERRUPT_CLEAR (0x060C)
+#define MSVDX_INTERRUPT_STATUS (0x0608)
+#define MSVDX_HOST_INTERRUPT_ENABLE (0x0610)
+#define MSVDX_CORE_REV (0x0640)
+#define MSVDX_MMU_CONTROL0 (0x0680)
+#define MSVDX_MMU_MEM_REQ (0x06D0)
+#define MSVDX_MTX_RAM_BANK (0x06F0)
+#define MSVDX_MTX_DEBUG MSVDX_MTX_RAM_BANK
+#define MSVDX_MAN_CLK_ENABLE (0x0620)
+#define MSVDX_CORE_CR_MSVDX_CONTROL_OFFSET (0x0600)
+#define MSVDX_CORE_CR_MMU_BANK_INDEX_OFFSET (0x0688)
+#define MSVDX_CORE_CR_MMU_DIR_LIST_BASE_OFFSET (0x0694)
+#define MSVDX_CORE_CR_MMU_CONTROL0_OFFSET MSVDX_MMU_CONTROL0
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_COMPAREMATCH (0x66c)
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_COMPAREMATCH (0x678)
+
+/* RENDEC registers */
+#define MSVDX_RENDEC_CONTROL0 (0x0868)
+#define MSVDX_RENDEC_CONTROL1 (0x086C)
+#define MSVDX_RENDEC_BUFFER_SIZE (0x0870)
+#define MSVDX_RENDEC_BASE_ADDR0 (0x0874)
+#define MSVDX_RENDEC_BASE_ADDR1 (0x0878)
+#define MSVDX_RENDEC_READ_DATA (0x0898)
+#define MSVDX_RENDEC_CONTEXT0 (0x0950)
+#define MSVDX_RENDEC_CONTEXT1 (0x0954)
+#define MSVDX_RENDEC_CONTEXT2 (0x0958)
+#define MSVDX_RENDEC_CONTEXT3 (0x095C)
+#define MSVDX_RENDEC_CONTEXT4 (0x0960)
+#define MSVDX_RENDEC_CONTEXT5 (0x0964)
+
+/* VEC registers */
+#define MSVDX_VEC_SHIFTREG_CONTROL (0x0818)
+
+/* DMAC registers */
+#define DMAC_DMAC_SETUP_OFFSET (0x0500)
+#define DMAC_DMAC_COUNT_OFFSET (0x0504)
+#define DMAC_DMAC_PERIPH_OFFSET (0x0508)
+#define DMAC_DMAC_IRQ_STAT_OFFSET (0x050C)
+#define DMAC_DMAC_PERIPHERAL_ADDR_OFFSET (0x0514)
+
+/* DMAC control */
+#define PSB_DMAC_VALUE_COUNT(BSWAP,PW,DIR,PERIPH_INCR,COUNT) \
+ \
+ (((BSWAP) & DMAC_DMAC_COUNT_BSWAP_LSBMASK) << DMAC_DMAC_COUNT_BSWAP_SHIFT) | \
+ (((PW) & DMAC_DMAC_COUNT_PW_LSBMASK) << DMAC_DMAC_COUNT_PW_SHIFT) | \
+ (((DIR) & DMAC_DMAC_COUNT_DIR_LSBMASK) << DMAC_DMAC_COUNT_DIR_SHIFT) | \
+ (((PERIPH_INCR) & DMAC_DMAC_COUNT_PI_LSBMASK) << DMAC_DMAC_COUNT_PI_SHIFT) | \
+ (((COUNT) & DMAC_DMAC_COUNT_CNT_LSBMASK) << DMAC_DMAC_COUNT_CNT_SHIFT)
+
+#define PSB_DMAC_VALUE_PERIPH_PARAM(ACC_DEL,INCR,BURST) \
+ \
+ (((ACC_DEL) & DMAC_DMAC_PERIPH_ACC_DEL_LSBMASK) << DMAC_DMAC_PERIPH_ACC_DEL_SHIFT) | \
+ (((INCR) & DMAC_DMAC_PERIPH_INCR_LSBMASK) << DMAC_DMAC_PERIPH_INCR_SHIFT) | \
+ (((BURST) & DMAC_DMAC_PERIPH_BURST_LSBMASK) << DMAC_DMAC_PERIPH_BURST_SHIFT)
+
+
+/* CMD */
+#define MSVDX_CMDS_END_SLICE_PICTURE (0x1404)
+
+/*
+ * This defines the MSVDX communication buffer
+ */
+#define MSVDX_COMMS_SIGNATURE_VALUE (0xA5A5A5A5) /*!< Signature value */
+/*!< Host buffer size (in 32-bit words) */
+#define NUM_WORDS_HOST_BUF (100)
+/*!< MTX buffer size (in 32-bit words) */
+#define NUM_WORDS_MTX_BUF (100)
+
+/* There is no work currently underway on the hardware */
+#define MSVDX_FW_STATUS_HW_IDLE 0x00000001
+
+#define MSVDX_EXT_FW_ERROR_STATE (0x2884)
+#define MSVDX_COMMS_AREA_ADDR (0x02fe0)
+
+#define MSVDX_COMMS_CORE_WTD (MSVDX_COMMS_AREA_ADDR - 0x08)
+#define MSVDX_COMMS_ERROR_TRIG (MSVDX_COMMS_AREA_ADDR - 0x08)
+#define MSVDX_COMMS_FIRMWARE_ID (MSVDX_COMMS_AREA_ADDR - 0x0C)
+#define MSVDX_COMMS_OFFSET_FLAGS (MSVDX_COMMS_AREA_ADDR + 0x18)
+#define MSVDX_COMMS_MSG_COUNTER (MSVDX_COMMS_AREA_ADDR - 0x04)
+#define MSVDX_COMMS_FW_STATUS (MSVDX_COMMS_AREA_ADDR - 0x10)
+#define MSVDX_COMMS_SIGNATURE (MSVDX_COMMS_AREA_ADDR + 0x00)
+#define MSVDX_COMMS_TO_HOST_BUF_SIZE (MSVDX_COMMS_AREA_ADDR + 0x04)
+#define MSVDX_COMMS_TO_HOST_RD_INDEX (MSVDX_COMMS_AREA_ADDR + 0x08)
+#define MSVDX_COMMS_TO_HOST_WRT_INDEX (MSVDX_COMMS_AREA_ADDR + 0x0C)
+#define MSVDX_COMMS_TO_MTX_BUF_SIZE (MSVDX_COMMS_AREA_ADDR + 0x10)
+#define MSVDX_COMMS_TO_MTX_RD_INDEX (MSVDX_COMMS_AREA_ADDR + 0x14)
+#define MSVDX_COMMS_TO_MTX_CB_RD_INDEX (MSVDX_COMMS_AREA_ADDR + 0x18)
+#define MSVDX_COMMS_TO_MTX_WRT_INDEX (MSVDX_COMMS_AREA_ADDR + 0x1C)
+#define MSVDX_COMMS_TO_HOST_BUF (MSVDX_COMMS_AREA_ADDR + 0x20)
+#define MSVDX_COMMS_TO_MTX_BUF \
+ (MSVDX_COMMS_TO_HOST_BUF + (NUM_WORDS_HOST_BUF << 2))
+
+#define DSIABLE_FW_WDT 0x0008
+#define ABORT_ON_ERRORS_IMMEDIATE 0x0010
+#define ABORT_FAULTED_SLICE_IMMEDIATE 0x0020
+#define RETURN_VDEB_DATA_IN_COMPLETION 0x0800
+#define DSIABLE_Auto_CLOCK_GATING 0x1000
+#define DSIABLE_IDLE_GPIO_SIG 0x2000
+/*
+#define MSVDX_COMMS_AREA_END \
+ (MSVDX_COMMS_TO_MTX_BUF + (NUM_WORDS_HOST_BUF << 2))
+*/
+#define MSVDX_COMMS_AREA_END 0x03000
+
+#if (MSVDX_COMMS_AREA_END != 0x03000)
+#error
+#endif
+
+#define MSVDX_MTX_REGISTER_READ_WRITE_REQUEST_MTX_DREADY_MASK (0x80000000)
+#define MSVDX_MTX_REGISTER_READ_WRITE_REQUEST_MTX_DREADY_SHIFT (31)
+
+#define MSVDX_MTX_REGISTER_READ_WRITE_REQUEST_MTX_RNW_MASK (0x00010000)
+#define MSVDX_MTX_REGISTER_READ_WRITE_REQUEST_MTX_RNW_SHIFT (16)
+
+#define MSVDX_MTX_RAM_ACCESS_CONTROL_MTX_MCMID_MASK (0x0FF00000)
+#define MSVDX_MTX_RAM_ACCESS_CONTROL_MTX_MCMID_SHIFT (20)
+
+#define MSVDX_MTX_RAM_ACCESS_CONTROL_MTX_MCM_ADDR_MASK (0x000FFFFC)
+#define MSVDX_MTX_RAM_ACCESS_CONTROL_MTX_MCM_ADDR_SHIFT (2)
+
+#define MSVDX_MTX_RAM_ACCESS_CONTROL_MTX_MCMAI_MASK (0x00000002)
+#define MSVDX_MTX_RAM_ACCESS_CONTROL_MTX_MCMAI_SHIFT (1)
+
+#define MSVDX_MTX_RAM_ACCESS_CONTROL_MTX_MCMR_MASK (0x00000001)
+#define MSVDX_MTX_RAM_ACCESS_CONTROL_MTX_MCMR_SHIFT (0)
+
+#define MSVDX_MTX_SOFT_RESET_MTX_RESET_MASK (0x00000001)
+#define MSVDX_MTX_SOFT_RESET_MTX_RESET_SHIFT (0)
+
+#define MSVDX_MTX_ENABLE_MTX_ENABLE_MASK (0x00000001)
+#define MSVDX_MTX_ENABLE_MTX_ENABLE_SHIFT (0)
+
+#define MSVDX_CONTROL_CR_MSVDX_SOFT_RESET_MASK (0x00000100)
+#define MSVDX_CONTROL_CR_MSVDX_SOFT_RESET_SHIFT (8)
+
+#define MSVDX_INTERRUPT_STATUS_CR_MMU_FAULT_IRQ_MASK (0x00000F00)
+#define MSVDX_INTERRUPT_STATUS_CR_MMU_FAULT_IRQ_SHIFT (8)
+
+#define MSVDX_INTERRUPT_STATUS_CR_MTX_IRQ_MASK (0x00004000)
+#define MSVDX_INTERRUPT_STATUS_CR_MTX_IRQ_SHIFT (14)
+
+#define MSVDX_MMU_CONTROL0_CR_MMU_PAUSE_MASK (0x00000002)
+#define MSVDX_MMU_CONTROL0_CR_MMU_PAUSE_SHIFT (1)
+
+#define MSVDX_MTX_RAM_BANK_CR_MTX_RAM_BANK_SIZE_MASK (0x000F0000)
+#define MSVDX_MTX_RAM_BANK_CR_MTX_RAM_BANK_SIZE_SHIFT (16)
+
+#define MSVDX_MTX_DEBUG_MTX_DBG_IS_SLAVE_MASK (0x00000004)
+#define MSVDX_MTX_DEBUG_MTX_DBG_IS_SLAVE_LSBMASK (0x00000001)
+#define MSVDX_MTX_DEBUG_MTX_DBG_IS_SLAVE_SHIFT (2)
+
+#define MSVDX_MTX_DEBUG_MTX_DBG_GPIO_IN_MASK (0x00000003)
+#define MSVDX_MTX_DEBUG_MTX_DBG_GPIO_IN_LSBMASK (0x00000003)
+#define MSVDX_MTX_DEBUG_MTX_DBG_GPIO_IN_SHIFT (0)
+
+#define MSVDX_RENDEC_BUFFER_SIZE_RENDEC_BUFFER_SIZE0_MASK (0x0000FFFF)
+#define MSVDX_RENDEC_BUFFER_SIZE_RENDEC_BUFFER_SIZE0_SHIFT (0)
+
+#define MSVDX_RENDEC_BUFFER_SIZE_RENDEC_BUFFER_SIZE1_MASK (0xFFFF0000)
+#define MSVDX_RENDEC_BUFFER_SIZE_RENDEC_BUFFER_SIZE1_SHIFT (16)
+
+#define MSVDX_RENDEC_CONTROL1_RENDEC_DECODE_START_SIZE_MASK (0x000000FF)
+#define MSVDX_RENDEC_CONTROL1_RENDEC_DECODE_START_SIZE_SHIFT (0)
+
+#define MSVDX_RENDEC_CONTROL1_RENDEC_BURST_SIZE_W_MASK (0x000C0000)
+#define MSVDX_RENDEC_CONTROL1_RENDEC_BURST_SIZE_W_SHIFT (18)
+
+#define MSVDX_RENDEC_CONTROL1_RENDEC_BURST_SIZE_R_MASK (0x00030000)
+#define MSVDX_RENDEC_CONTROL1_RENDEC_BURST_SIZE_R_SHIFT (16)
+
+#define MSVDX_RENDEC_CONTROL1_RENDEC_EXTERNAL_MEMORY_MASK (0x01000000)
+#define MSVDX_RENDEC_CONTROL1_RENDEC_EXTERNAL_MEMORY_SHIFT (24)
+
+#define MSVDX_RENDEC_CONTROL0_RENDEC_INITIALISE_MASK (0x00000001)
+#define MSVDX_RENDEC_CONTROL0_RENDEC_INITIALISE_SHIFT (0)
+
+#define VEC_SHIFTREG_CONTROL_SR_MASTER_SELECT_MASK (0x00000300)
+#define VEC_SHIFTREG_CONTROL_SR_MASTER_SELECT_SHIFT (8)
+
+#define MTX_CORE_CR_MTX_SYSC_CDMAC_BURSTSIZE_MASK (0x07000000)
+#define MTX_CORE_CR_MTX_SYSC_CDMAC_BURSTSIZE_SHIFT (24)
+
+#define MTX_CORE_CR_MTX_SYSC_CDMAC_RNW_MASK (0x00020000)
+#define MTX_CORE_CR_MTX_SYSC_CDMAC_RNW_SHIFT (17)
+
+#define MTX_CORE_CR_MTX_SYSC_CDMAC_ENABLE_MASK (0x00010000)
+#define MTX_CORE_CR_MTX_SYSC_CDMAC_ENABLE_SHIFT (16)
+
+#define MTX_CORE_CR_MTX_SYSC_CDMAC_LENGTH_MASK (0x0000FFFF)
+#define MTX_CORE_CR_MTX_SYSC_CDMAC_LENGTH_SHIFT (0)
+
+#define MSVDX_CORE_CR_MSVDX_CONTROL_DMAC_CH0_SELECT_MASK (0x00001000)
+#define MSVDX_CORE_CR_MSVDX_CONTROL_DMAC_CH0_SELECT_SHIFT (12)
+
+#define MSVDX_CORE_CR_MMU_CONTROL0_CR_MMU_INVALDC_MASK (0x00000008)
+#define MSVDX_CORE_CR_MMU_CONTROL0_CR_MMU_INVALDC_SHIFT (3)
+
+#define DMAC_DMAC_COUNT_BSWAP_LSBMASK (0x00000001)
+#define DMAC_DMAC_COUNT_BSWAP_SHIFT (30)
+
+#define DMAC_DMAC_COUNT_PW_LSBMASK (0x00000003)
+#define DMAC_DMAC_COUNT_PW_SHIFT (27)
+
+#define DMAC_DMAC_COUNT_DIR_LSBMASK (0x00000001)
+#define DMAC_DMAC_COUNT_DIR_SHIFT (26)
+
+#define DMAC_DMAC_COUNT_PI_LSBMASK (0x00000003)
+#define DMAC_DMAC_COUNT_PI_SHIFT (24)
+
+#define DMAC_DMAC_COUNT_CNT_LSBMASK (0x0000FFFF)
+#define DMAC_DMAC_COUNT_CNT_SHIFT (0)
+
+#define DMAC_DMAC_PERIPH_ACC_DEL_LSBMASK (0x00000007)
+#define DMAC_DMAC_PERIPH_ACC_DEL_SHIFT (29)
+
+#define DMAC_DMAC_PERIPH_INCR_LSBMASK (0x00000001)
+#define DMAC_DMAC_PERIPH_INCR_SHIFT (27)
+
+#define DMAC_DMAC_PERIPH_BURST_LSBMASK (0x00000007)
+#define DMAC_DMAC_PERIPH_BURST_SHIFT (24)
+
+#define DMAC_DMAC_PERIPHERAL_ADDR_ADDR_MASK (0x007FFFFF)
+#define DMAC_DMAC_PERIPHERAL_ADDR_ADDR_LSBMASK (0x007FFFFF)
+#define DMAC_DMAC_PERIPHERAL_ADDR_ADDR_SHIFT (0)
+
+#define DMAC_DMAC_COUNT_EN_MASK (0x00010000)
+#define DMAC_DMAC_COUNT_EN_SHIFT (16)
+
+#define DMAC_DMAC_IRQ_STAT_TRANSFER_FIN_MASK (0x00020000)
+
+/*watch dog for FE and BE*/
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_OFFSET (0x0064)
+
+// MSVDX_CORE, CR_FE_MSVDX_WDT_CONTROL, FE_WDT_CNT_CTRL
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_CNT_CTRL_MASK (0x00060000)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_CNT_CTRL_LSBMASK (0x00000003)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_CNT_CTRL_SHIFT (17)
+
+// MSVDX_CORE, CR_FE_MSVDX_WDT_CONTROL, FE_WDT_ENABLE
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_ENABLE_MASK (0x00010000)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_ENABLE_LSBMASK (0x00000001)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_ENABLE_SHIFT (16)
+
+// MSVDX_CORE, CR_FE_MSVDX_WDT_CONTROL, FE_WDT_ACTION1
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_ACTION1_MASK (0x00003000)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_ACTION1_LSBMASK (0x00000003)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_ACTION1_SHIFT (12)
+
+// MSVDX_CORE, CR_FE_MSVDX_WDT_CONTROL, FE_WDT_ACTION0
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_ACTION0_MASK (0x00000100)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_ACTION0_LSBMASK (0x00000001)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_ACTION0_SHIFT (8)
+
+// MSVDX_CORE, CR_FE_MSVDX_WDT_CONTROL, FE_WDT_CLEAR_SELECT
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_CLEAR_SELECT_MASK (0x00000030)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_CLEAR_SELECT_LSBMASK (0x00000003)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_CLEAR_SELECT_SHIFT (4)
+
+// MSVDX_CORE, CR_FE_MSVDX_WDT_CONTROL, FE_WDT_CLKDIV_SELECT
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_CLKDIV_SELECT_MASK (0x00000007)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_CLKDIV_SELECT_LSBMASK (0x00000007)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL_FE_WDT_CLKDIV_SELECT_SHIFT (0)
+
+#define MSVDX_CORE_CR_FE_MSVDX_WDTIMER_OFFSET (0x0068)
+
+// MSVDX_CORE, CR_FE_MSVDX_WDTIMER, FE_WDT_COUNTER
+#define MSVDX_CORE_CR_FE_MSVDX_WDTIMER_FE_WDT_COUNTER_MASK (0x0000FFFF)
+#define MSVDX_CORE_CR_FE_MSVDX_WDTIMER_FE_WDT_COUNTER_LSBMASK (0x0000FFFF)
+#define MSVDX_CORE_CR_FE_MSVDX_WDTIMER_FE_WDT_COUNTER_SHIFT (0)
+
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_COMPAREMATCH_OFFSET (0x006C)
+
+// MSVDX_CORE, CR_FE_MSVDX_WDT_COMPAREMATCH, FE_WDT_CM1
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_COMPAREMATCH_FE_WDT_CM1_MASK (0xFFFF0000)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_COMPAREMATCH_FE_WDT_CM1_LSBMASK (0x0000FFFF)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_COMPAREMATCH_FE_WDT_CM1_SHIFT (16)
+
+// MSVDX_CORE, CR_FE_MSVDX_WDT_COMPAREMATCH, FE_WDT_CM0
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_COMPAREMATCH_FE_WDT_CM0_MASK (0x0000FFFF)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_COMPAREMATCH_FE_WDT_CM0_LSBMASK (0x0000FFFF)
+#define MSVDX_CORE_CR_FE_MSVDX_WDT_COMPAREMATCH_FE_WDT_CM0_SHIFT (0)
+
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_OFFSET (0x0070)
+
+// MSVDX_CORE, CR_BE_MSVDX_WDT_CONTROL, BE_WDT_CNT_CTRL
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_CNT_CTRL_MASK (0x001E0000)
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_CNT_CTRL_LSBMASK (0x0000000F)
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_CNT_CTRL_SHIFT (17)
+
+// MSVDX_CORE, CR_BE_MSVDX_WDT_CONTROL, BE_WDT_ENABLE
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_ENABLE_MASK (0x00010000)
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_ENABLE_LSBMASK (0x00000001)
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_ENABLE_SHIFT (16)
+
+// MSVDX_CORE, CR_BE_MSVDX_WDT_CONTROL, BE_WDT_ACTION0
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_ACTION0_MASK (0x00000100)
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_ACTION0_LSBMASK (0x00000001)
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_ACTION0_SHIFT (8)
+
+// MSVDX_CORE, CR_BE_MSVDX_WDT_CONTROL, BE_WDT_CLEAR_SELECT
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_CLEAR_SELECT_MASK (0x000000F0)
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_CLEAR_SELECT_LSBMASK (0x0000000F)
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_CLEAR_SELECT_SHIFT (4)
+
+// MSVDX_CORE, CR_BE_MSVDX_WDT_CONTROL, BE_WDT_CLKDIV_SELECT
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_CLKDIV_SELECT_MASK (0x00000007)
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_CLKDIV_SELECT_LSBMASK (0x00000007)
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL_BE_WDT_CLKDIV_SELECT_SHIFT (0)
+
+#define MSVDX_CORE_CR_BE_MSVDX_WDTIMER_OFFSET (0x0074)
+
+// MSVDX_CORE, CR_BE_MSVDX_WDTIMER, BE_WDT_COUNTER
+#define MSVDX_CORE_CR_BE_MSVDX_WDTIMER_BE_WDT_COUNTER_MASK (0x0000FFFF)
+#define MSVDX_CORE_CR_BE_MSVDX_WDTIMER_BE_WDT_COUNTER_LSBMASK (0x0000FFFF)
+#define MSVDX_CORE_CR_BE_MSVDX_WDTIMER_BE_WDT_COUNTER_SHIFT (0)
+
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_COMPAREMATCH_OFFSET (0x0078)
+
+// MSVDX_CORE, CR_BE_MSVDX_WDT_COMPAREMATCH, BE_WDT_CM0
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_COMPAREMATCH_BE_WDT_CM0_MASK (0x0000FFFF)
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_COMPAREMATCH_BE_WDT_CM0_LSBMASK (0x0000FFFF)
+#define MSVDX_CORE_CR_BE_MSVDX_WDT_COMPAREMATCH_BE_WDT_CM0_SHIFT (0)
+/*watch dog end*/
+
+/* Start of parser specific Host->MTX messages. */
+#define FWRK_MSGID_START_PSR_HOSTMTX_MSG (0x80)
+
+/* Start of parser specific MTX->Host messages. */
+#define FWRK_MSGID_START_PSR_MTXHOST_MSG (0xC0)
+
+/* Host defined msg, just for host use, MTX not recgnize */
+#define FWRK_MSGID_HOST_EMULATED (0x40)
+
+#define FWRK_MSGID_PADDING (0)
+
+#define FWRK_GENMSG_SIZE_TYPE uint8_t
+#define FWRK_GENMSG_SIZE_MASK (0xFF)
+#define FWRK_GENMSG_SIZE_SHIFT (0)
+#define FWRK_GENMSG_SIZE_OFFSET (0x0000)
+#define FWRK_GENMSG_ID_TYPE uint8_t
+#define FWRK_GENMSG_ID_MASK (0xFF)
+#define FWRK_GENMSG_ID_SHIFT (0)
+#define FWRK_GENMSG_ID_OFFSET (0x0001)
+#define FWRK_PADMSG_SIZE (2)
+
+/* Deblock CMD_ID */
+#define MSVDX_DEBLOCK_REG_SET 0x10000000
+#define MSVDX_DEBLOCK_REG_GET 0x20000000
+#define MSVDX_DEBLOCK_REG_POLLn 0x30000000
+#define MSVDX_DEBLOCK_REG_POLLx 0x40000000
+
+/* vec local MEM save/restore */
+#define VEC_LOCAL_MEM_BYTE_SIZE (4 * 1024)
+#define VEC_LOCAL_MEM_OFFSET 0x2000
+
+/* This type defines the framework specified message ids */
+enum {
+ /* ! Sent by the DXVA driver on the host to the mtx firmware.
+ */
+ VA_MSGID_INIT = FWRK_MSGID_START_PSR_HOSTMTX_MSG,
+ VA_MSGID_RENDER,
+ VA_MSGID_DEBLOCK,
+ VA_MSGID_OOLD,
+
+ /* Test Messages */
+ VA_MSGID_TEST1,
+ VA_MSGID_HOST_BE_OPP,
+
+ /*! Sent by the mtx firmware to itself.
+ */
+ VA_MSGID_RENDER_MC_INTERRUPT,
+
+ VA_MSGID_DEBLOCK_MFLD = FWRK_MSGID_HOST_EMULATED,
+ VA_MSGID_OOLD_MFLD,
+ /*! Sent by the DXVA firmware on the MTX to the host.
+ */
+ VA_MSGID_CMD_COMPLETED = FWRK_MSGID_START_PSR_MTXHOST_MSG,
+ VA_MSGID_CMD_COMPLETED_BATCH,
+ VA_MSGID_DEBLOCK_REQUIRED,
+ VA_MSGID_TEST_RESPONCE,
+ VA_MSGID_ACK,
+
+ VA_MSGID_CMD_FAILED,
+ VA_MSGID_CMD_CONTIGUITY_WARNING,
+ VA_MSGID_CMD_HW_PANIC,
+};
+
+/* Deblock parameters */
+struct DEBLOCKPARAMS {
+ uint32_t handle; /* struct ttm_buffer_object * of REGIO */
+ uint32_t buffer_size;
+ uint32_t ctxid;
+
+ uint32_t *pPicparams;
+ struct ttm_bo_kmap_obj *regio_kmap; /* virtual of regio */
+ uint32_t pad[3];
+};
+
+/* HOST_BE_OPP parameters */
+struct HOST_BE_OPP_PARAMS {
+ uint32_t handle; /* struct ttm_buffer_object * of REGIO */
+ uint32_t buffer_stride;
+ uint32_t buffer_size;
+ uint32_t picture_width_mb;
+ uint32_t size_mb;
+};
+struct psb_msvdx_deblock_queue {
+
+ struct list_head head;
+ struct DEBLOCKPARAMS dbParams;
+};
+
+typedef struct {
+ union {
+ struct {
+ uint32_t msg_size : 8;
+ uint32_t msg_type : 8;
+ uint32_t msg_fence : 16;
+ } bits;
+ uint32_t value;
+ } header;
+ uint32_t flags;
+ uint32_t operating_mode;
+ union {
+ struct {
+ uint32_t context : 8;
+ uint32_t mmu_ptd : 24;
+ } bits;
+ uint32_t value;
+ } mmu_context;
+ union {
+ struct {
+ uint32_t frame_height_mb : 16;
+ uint32_t pic_width_mb : 16;
+ } bits;
+ uint32_t value;
+ } pic_size;
+ uint32_t address_a0;
+ uint32_t address_a1;
+ uint32_t mb_param_address;
+ uint32_t address_b0;
+ uint32_t address_b1;
+ uint32_t rotation_flags;
+} FW_VA_DEBLOCK_MSG;
+
+typedef struct drm_psb_msvdx_frame_info {
+ uint32_t handle;
+ uint32_t surface_id;
+ uint32_t fence;
+ uint32_t buffer_stride;
+ uint32_t buffer_size;
+ uint32_t picture_width_mb;
+ uint32_t fw_status;
+ uint32_t size_mb;
+ drm_psb_msvdx_decode_status_t decode_status;
+} drm_psb_msvdx_frame_info_t;
+
+#define MAX_DECODE_BUFFERS 24
+/* MSVDX private structure */
+struct msvdx_private {
+ int msvdx_needs_reset;
+
+ unsigned int pmstate;
+
+ struct sysfs_dirent *sysfs_pmstate;
+
+ uint32_t msvdx_current_sequence;
+ uint32_t msvdx_last_sequence;
+
+ /*
+ *MSVDX Rendec Memory
+ */
+ struct ttm_buffer_object *ccb0;
+ uint32_t base_addr0;
+ struct ttm_buffer_object *ccb1;
+ uint32_t base_addr1;
+
+ struct ttm_buffer_object *fw;
+ uint32_t is_load;
+ uint32_t mtx_mem_size;
+
+ /*
+ *msvdx command queue
+ */
+ spinlock_t msvdx_lock;
+ struct mutex msvdx_mutex;
+ struct list_head msvdx_queue;
+ int msvdx_busy;
+ int msvdx_fw_loaded;
+ void *msvdx_fw;
+ int msvdx_fw_size;
+
+ struct list_head deblock_queue; /* deblock parameter list */
+
+ uint32_t msvdx_hw_busy;
+
+ uint32_t *vec_local_mem_data;
+ uint32_t vec_local_mem_size;
+ uint32_t vec_local_mem_saved;
+ uint32_t psb_dash_access_ctrl;
+ uint32_t fw_status;
+
+ drm_psb_msvdx_frame_info_t frame_info[MAX_DECODE_BUFFERS];
+ drm_psb_msvdx_decode_status_t decode_status;
+ uint32_t deblock_enabled;
+ uint32_t host_be_opp_enabled;
+
+ uint32_t ec_fence;
+ uint32_t ref_pic_fence;
+ /*work for error concealment*/
+ struct work_struct ec_work;
+ struct ttm_object_file *tfile;
+};
+
+#define REGISTER(__group__, __reg__ ) (__group__##_##__reg__##_OFFSET)
+/* MSVDX Firmware interface */
+#define FW_VA_INIT_SIZE (8)
+#define FW_VA_DEBUG_TEST2_SIZE (4)
+
+/*MESSAGE SENT FROM HOST TO FW*/
+/*FW_VA_RENDER MESSAGE*/
+/* FW_VA_RENDER BUFFER_SIZE */
+#define FW_VA_RENDER_BUFFER_SIZE_TYPE uint16_t
+#define FW_VA_RENDER_BUFFER_SIZE_MASK (0x0FFF)
+#define FW_VA_RENDER_BUFFER_SIZE_OFFSET (0x0002)
+#define FW_VA_RENDER_BUFFER_SIZE_SHIFT (0)
+
+/* FW_VA_RENDER MMUPTD */
+#define FW_VA_RENDER_MMUPTD_TYPE uint32_t
+#define FW_VA_RENDER_MMUPTD_MASK (0xFFFFFFFF)
+#define FW_VA_RENDER_MMUPTD_OFFSET (0x0004)
+#define FW_VA_RENDER_MMUPTD_SHIFT (0)
+
+/* FW_VA_RENDER LLDMA_ADDRESS */
+#define FW_VA_RENDER_LLDMA_ADDRESS_START_BIT 0
+#define FW_VA_RENDER_LLDMA_ADDRESS_END_BIT 31
+#define FW_VA_RENDER_LLDMA_ADDRESS_ALIGNMENT (4)
+#define FW_VA_RENDER_LLDMA_ADDRESS_TYPE uint32_t
+#define FW_VA_RENDER_LLDMA_ADDRESS_MASK (0xFFFFFFFF)
+#define FW_VA_RENDER_LLDMA_ADDRESS_LSBMASK (0xFFFFFFFF)
+#define FW_VA_RENDER_LLDMA_ADDRESS_OFFSET (0x0008)
+#define FW_VA_RENDER_LLDMA_ADDRESS_SHIFT (0)
+#define FW_VA_RENDER_LLDMA_ADDRESS_SIGNED_FIELD (0)
+
+/* FW_VA_RENDER CONTEXT */
+#define FW_VA_RENDER_CONTEXT_START_BIT 0
+#define FW_VA_RENDER_CONTEXT_END_BIT 31
+#define FW_VA_RENDER_CONTEXT_ALIGNMENT (4)
+#define FW_VA_RENDER_CONTEXT_TYPE uint32_t
+#define FW_VA_RENDER_CONTEXT_MASK (0xFFFFFFFF)
+#define FW_VA_RENDER_CONTEXT_LSBMASK (0xFFFFFFFF)
+#define FW_VA_RENDER_CONTEXT_OFFSET (0x000C)
+#define FW_VA_RENDER_CONTEXT_SHIFT (0)
+#define FW_VA_RENDER_CONTEXT_SIGNED_FIELD (0)
+
+
+/* FW_VA_RENDER FENCE_VALUE_NO_EC */
+#define FW_VA_RENDER_FENCE_VALUE_TYPE uint32_t
+#define FW_VA_RENDER_FENCE_VALUE_MASK (0xFFFFFFFF)
+#define FW_VA_RENDER_FENCE_VALUE_OFFSET (0x0010)
+#define FW_VA_RENDER_FENCE_VALUE_SHIFT (0)
+
+/* FW_VA_RENDER OPERATING_MODE */
+#define FW_VA_RENDER_OPERATING_MODE_ALIGNMENT (4)
+#define FW_VA_RENDER_OPERATING_MODE_TYPE uint32_t
+#define FW_VA_RENDER_OPERATING_MODE_MASK (0xFFFFFFFF)
+#define FW_VA_RENDER_OPERATING_MODE_LSBMASK (0xFFFFFFFF)
+#define FW_VA_RENDER_OPERATING_MODE_OFFSET (0x0014)
+#define FW_VA_RENDER_OPERATING_MODE_SHIFT (0)
+#define FW_VA_RENDER_OPERATING_MODE_SIGNED_FIELD (0)
+
+/* FW_VA_RENDER FIRST_MB_IN_SLICE */
+#define FW_VA_RENDER_FIRST_MB_IN_SLICE_START_BIT 0
+#define FW_VA_RENDER_FIRST_MB_IN_SLICE_END_BIT 15
+#define FW_VA_RENDER_FIRST_MB_IN_SLICE_ALIGNMENT (2)
+#define FW_VA_RENDER_FIRST_MB_IN_SLICE_TYPE uint16_t
+#define FW_VA_RENDER_FIRST_MB_IN_SLICE_MASK (0xFFFF)
+#define FW_VA_RENDER_FIRST_MB_IN_SLICE_LSBMASK (0xFFFF)
+#define FW_VA_RENDER_FIRST_MB_IN_SLICE_OFFSET (0x0018)
+#define FW_VA_RENDER_FIRST_MB_IN_SLICE_SHIFT (0)
+#define FW_VA_RENDER_FIRST_MB_IN_SLICE_SIGNED_FIELD (0)
+
+/* FW_VA_RENDER LAST_MB_IN_FRAME */
+#define FW_VA_RENDER_LAST_MB_IN_FRAME_START_BIT 16
+#define FW_VA_RENDER_LAST_MB_IN_FRAME_END_BIT 31
+#define FW_VA_RENDER_LAST_MB_IN_FRAME_ALIGNMENT (2)
+#define FW_VA_RENDER_LAST_MB_IN_FRAME_TYPE uint16_t
+#define FW_VA_RENDER_LAST_MB_IN_FRAME_MASK (0xFFFF)
+#define FW_VA_RENDER_LAST_MB_IN_FRAME_LSBMASK (0xFFFF)
+#define FW_VA_RENDER_LAST_MB_IN_FRAME_OFFSET (0x001A)
+#define FW_VA_RENDER_LAST_MB_IN_FRAME_SHIFT (0)
+#define FW_VA_RENDER_LAST_MB_IN_FRAME_SIGNED_FIELD (0)
+
+/* FW_VA_RENDER FLAGS */
+#define FW_VA_RENDER_FLAGS_START_BIT 0
+#define FW_VA_RENDER_FLAGS_END_BIT 31
+#define FW_VA_RENDER_FLAGS_ALIGNMENT (4)
+#define FW_VA_RENDER_FLAGS_TYPE uint32_t
+#define FW_VA_RENDER_FLAGS_MASK (0xFFFFFFFF)
+#define FW_VA_RENDER_FLAGS_LSBMASK (0xFFFFFFFF)
+#define FW_VA_RENDER_FLAGS_OFFSET (0x001C)
+#define FW_VA_RENDER_FLAGS_SHIFT (0)
+#define FW_VA_RENDER_FLAGS_SIGNED_FIELD (0)
+/* FW_VA_DEBUG_TEST2 MSG_SIZE */
+#define FW_VA_DEBUG_TEST2_MSG_SIZE_TYPE uint8_t
+#define FW_VA_DEBUG_TEST2_MSG_SIZE_MASK (0xFF)
+#define FW_VA_DEBUG_TEST2_MSG_SIZE_OFFSET (0x0000)
+#define FW_VA_DEBUG_TEST2_MSG_SIZE_SHIFT (0)
+
+/* FW_VA_DEBUG_TEST2 ID */
+#define FW_VA_DEBUG_TEST2_ID_TYPE uint8_t
+#define FW_VA_DEBUG_TEST2_ID_MASK (0xFF)
+#define FW_VA_DEBUG_TEST2_ID_OFFSET (0x0001)
+#define FW_VA_DEBUG_TEST2_ID_SHIFT (0)
+
+/* FW_VA_CMD_FAILED FENCE_VALUE */
+#define FW_VA_CMD_FAILED_FENCE_VALUE_TYPE uint32_t
+#define FW_VA_CMD_FAILED_FENCE_VALUE_MASK (0xFFFFFFFF)
+#define FW_VA_CMD_FAILED_FENCE_VALUE_OFFSET (0x0004)
+#define FW_VA_CMD_FAILED_FENCE_VALUE_SHIFT (0)
+
+/* FW_VA_CMD_FAILED IRQSTATUS */
+#define FW_VA_CMD_FAILED_IRQSTATUS_TYPE uint32_t
+#define FW_VA_CMD_FAILED_IRQSTATUS_MASK (0xFFFFFFFF)
+#define FW_VA_CMD_FAILED_IRQSTATUS_OFFSET (0x0008)
+#define FW_VA_CMD_FAILED_IRQSTATUS_SHIFT (0)
+/*FW_DXVA_DEBLOCK MESSAGE*/
+/* FW_DXVA_DEBLOCK MSG_SIZE */
+#define FW_DXVA_DEBLOCK_MSG_SIZE_ALIGNMENT (1)
+#define FW_DXVA_DEBLOCK_MSG_SIZE_TYPE uint8_t
+#define FW_DXVA_DEBLOCK_MSG_SIZE_MASK (0xFF)
+#define FW_DXVA_DEBLOCK_MSG_SIZE_LSBMASK (0xFF)
+#define FW_DXVA_DEBLOCK_MSG_SIZE_OFFSET (0x0000)
+#define FW_DXVA_DEBLOCK_MSG_SIZE_SHIFT (0)
+
+/* FW_DXVA_DEBLOCK ID */
+#define FW_DXVA_DEBLOCK_ID_ALIGNMENT (1)
+#define FW_DXVA_DEBLOCK_ID_TYPE uint8_t
+#define FW_DXVA_DEBLOCK_ID_MASK (0xFF)
+#define FW_DXVA_DEBLOCK_ID_LSBMASK (0xFF)
+#define FW_DXVA_DEBLOCK_ID_OFFSET (0x0001)
+#define FW_DXVA_DEBLOCK_ID_SHIFT (0)
+
+// FW_DXVA_DEBLOCK FLAGS
+#define FW_DXVA_DEBLOCK_FLAGS_START_BIT 16
+#define FW_DXVA_DEBLOCK_FLAGS_END_BIT 31
+#define FW_DXVA_DEBLOCK_FLAGS_ALIGNMENT (2)
+#define FW_DXVA_DEBLOCK_FLAGS_TYPE uint16_t
+#define FW_DXVA_DEBLOCK_FLAGS_MASK (0xFFFF)
+#define FW_DXVA_DEBLOCK_FLAGS_LSBMASK (0xFFFF)
+#define FW_DXVA_DEBLOCK_FLAGS_OFFSET (0x0002)
+#define FW_DXVA_DEBLOCK_FLAGS_SHIFT (0)
+#define FW_DXVA_DEBLOCK_FLAGS_SIGNED_FIELD (0)
+
+/* FW_DXVA_DEBLOCK CONTEXT */
+#define FW_DXVA_DEBLOCK_CONTEXT_START_BIT 0
+#define FW_DXVA_DEBLOCK_CONTEXT_END_BIT 11
+#define FW_DXVA_DEBLOCK_CONTEXT_ALIGNMENT (4)
+#define FW_DXVA_DEBLOCK_CONTEXT_TYPE uint16_t
+#define FW_DXVA_DEBLOCK_CONTEXT_MASK (0xFFF)
+#define FW_DXVA_DEBLOCK_CONTEXT_LSBMASK (0xFFF)
+#define FW_DXVA_DEBLOCK_CONTEXT_OFFSET (0x0004)
+#define FW_DXVA_DEBLOCK_CONTEXT_SHIFT (0)
+#define FW_DXVA_DEBLOCK_CONTEXT_SIGNED_FIELD (0)
+
+
+/* FW_DXVA_DEBLOCK CONTEXT_NO_EC */
+#define FW_DXVA_DEBLOCK_CONTEXT_NO_EC_START_BIT 0
+#define FW_DXVA_DEBLOCK_CONTEXT_NO_EC_END_BIT 31
+#define FW_DXVA_DEBLOCK_CONTEXT_NO_EC_ALIGNMENT (4)
+#define FW_DXVA_DEBLOCK_CONTEXT_NO_EC_TYPE uint32_t
+#define FW_DXVA_DEBLOCK_CONTEXT_NO_EC_MASK (0xFFFFFFFF)
+#define FW_DXVA_DEBLOCK_CONTEXT_NO_EC_LSBMASK (0xFFFFFFFF)
+#define FW_DXVA_DEBLOCK_CONTEXT_NO_EC_OFFSET (0x0004)
+#define FW_DXVA_DEBLOCK_CONTEXT_SHIFT (0)
+#define FW_DXVA_DEBLOCK_CONTEXT_SIGNED_FIELD (0)
+
+/* FW_DXVA_DEBLOCK FENCE_VALUE_NO_EC */
+#define FW_DXVA_DEBLOCK_FENCE_VALUE_NO_EC_START_BIT 0
+#define FW_DXVA_DEBLOCK_FENCE_VALUE_NO_EC_END_BIT 31
+#define FW_DXVA_DEBLOCK_FENCE_VALUE_NO_EC_ALIGNMENT (4)
+#define FW_DXVA_DEBLOCK_FENCE_VALUE_NO_EC_TYPE uint32_t
+#define FW_DXVA_DEBLOCK_FENCE_VALUE_NO_EC_MASK (0xFFFFFFFF)
+#define FW_DXVA_DEBLOCK_FENCE_VALUE_NO_EC_LSBMASK (0xFFFFFFFF)
+#define FW_DXVA_DEBLOCK_FENCE_VALUE_NO_EC_OFFSET (0x0008)
+#define FW_DXVA_DEBLOCK_FENCE_VALUE_NO_EC_SHIFT (0)
+#define FW_DXVA_DEBLOCK_FENCE_VALUE_NO_EC_SIGNED_FIELD (0)
+
+
+/* FW_DXVA_DEBLOCK MMUPTD */
+#define FW_DXVA_DEBLOCK_MMUPTD_START_BIT 0
+#define FW_DXVA_DEBLOCK_MMUPTD_END_BIT 31
+#define FW_DXVA_DEBLOCK_MMUPTD_ALIGNMENT (4)
+#define FW_DXVA_DEBLOCK_MMUPTD_TYPE uint32_t
+#define FW_DXVA_DEBLOCK_MMUPTD_MASK (0xFFFFFFFF)
+#define FW_DXVA_DEBLOCK_MMUPTD_LSBMASK (0xFFFFFFFF)
+#define FW_DXVA_DEBLOCK_MMUPTD_OFFSET (0x000C)
+#define FW_DXVA_DEBLOCK_MMUPTD_SHIFT (0)
+#define FW_DXVA_DEBLOCK_MMUPTD_SIGNED_FIELD (0)
+
+
+/* FW_VA_HOST_BE_OPP MMUPTD */
+#define FW_VA_HOST_BE_OPP_MMUPTD_ALIGNMENT (4)
+#define FW_VA_HOST_BE_OPP_MMUPTD_TYPE uint32_t
+#define FW_VA_HOST_BE_OPP_MMUPTD_MASK (0xFFFFFFFF)
+#define FW_VA_HOST_BE_OPP_MMUPTD_LSBMASK (0xFFFFFFFF)
+#define FW_VA_HOST_BE_OPP_MMUPTD_OFFSET (0x000C)
+#define FW_VA_HOST_BE_OPP_MMUPTD_SHIFT (0)
+
+
+/*MESSAGE SENT FROM FW TO HOST*/
+
+/* FW_VA_CMD_COMPLETED MESSAGE*/
+/* FW_VA_CMD_COMPLETED LASTMB */
+#define FW_VA_CMD_COMPLETED_LASTMB_ALIGNMENT (2)
+#define FW_VA_CMD_COMPLETED_LASTMB_TYPE uint16_t
+#define FW_VA_CMD_COMPLETED_LASTMB_MASK (0xFFFF)
+#define FW_VA_CMD_COMPLETED_LASTMB_LSBMASK (0xFFFF)
+#define FW_VA_CMD_COMPLETED_LASTMB_OFFSET (0x0002)
+#define FW_VA_CMD_COMPLETED_LASTMB_SHIFT (0)
+#define FW_VA_CMD_COMPLETED_LASTMB_SIGNED_FIELD (0)
+
+/* FW_VA_CMD_COMPLETED NO_TICKSNO_EC */
+#define FW_VA_CMD_COMPLETED_NO_TICKS_NO_EC_TYPE uint16_t
+#define FW_VA_CMD_COMPLETED_NO_TICKS_NO_EC_MASK (0xFFFF)
+#define FW_VA_CMD_COMPLETED_NO_TICKS_NO_EC_OFFSET (0x0002)
+#define FW_VA_CMD_COMPLETED_NO_TICKS_NO_EC_SHIFT (0)
+/* FW_VA_CMD_COMPLETED FENCE_VALUE */
+#define FW_VA_CMD_COMPLETED_FENCE_VALUE_TYPE uint32_t
+#define FW_VA_CMD_COMPLETED_FENCE_VALUE_MASK (0xFFFFFFFF)
+#define FW_VA_CMD_COMPLETED_FENCE_VALUE_OFFSET (0x0004)
+#define FW_VA_CMD_COMPLETED_FENCE_VALUE_SHIFT (0)
+
+/* FW_VA_CMD_COMPLETED FENCE_VALUE_NO_EC */
+#define FW_VA_CMD_COMPLETED_FENCE_VALUE_NO_EC_TYPE uint32_t
+#define FW_VA_CMD_COMPLETED_FENCE_VALUE_NO_EC_MASK (0xFFFFFFFF)
+#define FW_VA_CMD_COMPLETED_FENCE_VALUE_NO_EC_OFFSET (0x0004)
+#define FW_VA_CMD_COMPLETED_FENCE_VALUE_NO_EC_SHIFT (0)
+
+/* FW_VA_CMD_COMPLETED FLAGS */
+#define FW_VA_CMD_COMPLETED_FLAGS_ALIGNMENT (4)
+#define FW_VA_CMD_COMPLETED_FLAGS_TYPE uint32_t
+#define FW_VA_CMD_COMPLETED_FLAGS_MASK (0xFFFFFFFF)
+#define FW_VA_CMD_COMPLETED_FLAGS_LSBMASK (0xFFFFFFFF)
+#define FW_VA_CMD_COMPLETED_FLAGS_OFFSET (0x0008)
+#define FW_VA_CMD_COMPLETED_FLAGS_SHIFT (0)
+
+/* FW_VA_CMD_COMPLETED NO_TICKS */
+#define FW_VA_CMD_COMPLETED_NO_TICKS_TYPE uint16_t
+#define FW_VA_CMD_COMPLETED_NO_TICKS_MASK (0xFFFF)
+#define FW_VA_CMD_COMPLETED_NO_TICKS_OFFSET (0x0002)
+#define FW_VA_CMD_COMPLETED_NO_TICKS_SHIFT (0)
+
+
+/* FW_VA_DEBLOCK_REQUIRED CONTEXT */
+#define FW_VA_DEBLOCK_REQUIRED_CONTEXT_TYPE uint16_t
+#define FW_VA_DEBLOCK_REQUIRED_CONTEXT_MASK (0xFFF)
+#define FW_VA_DEBLOCK_REQUIRED_CONTEXT_OFFSET (0x0004)
+#define FW_VA_DEBLOCK_REQUIRED_CONTEXT_SHIFT (0)
+
+/* FW_VA_INIT GLOBAL_PTD */
+#define FW_VA_INIT_GLOBAL_PTD_TYPE uint32_t
+#define FW_VA_INIT_GLOBAL_PTD_MASK (0xFFFFFFFF)
+#define FW_VA_INIT_GLOBAL_PTD_OFFSET (0x0004)
+#define FW_VA_INIT_GLOBAL_PTD_SHIFT (0)
+
+/* FW_VA_RENDER FENCE_VALUE */
+#define FW_VA_RENDER_FENCE_VALUE_TYPE uint32_t
+#define FW_VA_RENDER_FENCE_VALUE_MASK (0xFFFFFFFF)
+#define FW_VA_RENDER_FENCE_VALUE_OFFSET (0x0010)
+#define FW_VA_RENDER_FENCE_VALUE_SHIFT (0)
+
+/* FW_DXVA_OOLD FENCE_VALUE */
+#define FW_DXVA_OOLD_FENCE_VALUE_ALIGNMENT (4)
+#define FW_DXVA_OOLD_FENCE_VALUE_TYPE uint32_t
+#define FW_DXVA_OOLD_FENCE_VALUE_MASK (0xFFFFFFFF)
+#define FW_DXVA_OOLD_FENCE_VALUE_LSBMASK (0xFFFFFFFF)
+#define FW_DXVA_OOLD_FENCE_VALUE_OFFSET (0x0008)
+#define FW_DXVA_OOLD_FENCE_VALUE_SHIFT (0)
+
+
+/* FW_VA_RENDER MMUPTD */
+#define FW_VA_RENDER_MMUPTD_TYPE uint32_t
+#define FW_VA_RENDER_MMUPTD_MASK (0xFFFFFFFF)
+#define FW_VA_RENDER_MMUPTD_OFFSET (0x0004)
+#define FW_VA_RENDER_MMUPTD_SHIFT (0)
+
+/* FW_VA_RENDER BUFFER_ADDRESS */
+#define FW_VA_RENDER_BUFFER_ADDRESS_TYPE uint32_t
+#define FW_VA_RENDER_BUFFER_ADDRESS_MASK (0xFFFFFFFF)
+#define FW_VA_RENDER_BUFFER_ADDRESS_OFFSET (0x0008)
+#define FW_VA_RENDER_BUFFER_ADDRESS_SHIFT (0)
+
+/* FW_VA_RENDER BUFFER_SIZE */
+#define FW_VA_RENDER_BUFFER_SIZE_TYPE uint16_t
+#define FW_VA_RENDER_BUFFER_SIZE_MASK (0x0FFF)
+#define FW_VA_RENDER_BUFFER_SIZE_OFFSET (0x0002)
+#define FW_VA_RENDER_BUFFER_SIZE_SHIFT (0)
+
+/* FW_VA_RENDER FLAGS */
+#define FW_VA_RENDER_FLAGS_TYPE uint32_t
+#define FW_VA_RENDER_FLAGS_MASK (0xFFFFFFFF)
+#define FW_VA_RENDER_FLAGS_OFFSET (0x001C)
+#define FW_VA_RENDER_FLAGS_SHIFT (0)
+
+/* FW_DEVA_DECODE MMUPTD */
+#define FW_VA_DECODE_MMUPTD_TYPE uint32_t
+#define FW_VA_DECODE_MMUPTD_MASK (0xFFFFFF00)
+#define FW_VA_DECODE_MMUPTD_OFFSET (0x000C)
+#define FW_VA_DECODE_MMUPTD_SHIFT (0)
+
+/* FW_DEVA_DECODE MSG_ID */
+#define FW_VA_DECODE_MSG_ID_TYPE uint16_t
+#define FW_VA_DECODE_MSG_ID_MASK (0xFFFF)
+#define FW_VA_DECODE_MSG_ID_OFFSET (0x0002)
+#define FW_VA_DECODE_MSG_ID_SHIFT (0)
+
+/* FW_DEVA_DECODE FLAGS */
+#define FW_DEVA_DECODE_FLAGS_TYPE uint16_t
+#define FW_DEVA_DECODE_FLAGS_MASK (0xFFFF)
+#define FW_DEVA_DECODE_FLAGS_OFFSET (0x0004)
+#define FW_DEVA_DECODE_FLAGS_SHIFT (0)
+
+#define FW_DEVA_INVALIDATE_MMU (0x00000010)
+
+/* FW_DEVA_CMD_COMPLETED MSG_ID */
+#define FW_VA_CMD_COMPLETED_MSG_ID_TYPE uint16_t
+#define FW_VA_CMD_COMPLETED_MSG_ID_MASK (0xFFFF)
+#define FW_VA_CMD_COMPLETED_MSG_ID_OFFSET (0x0002)
+#define FW_VA_CMD_COMPLETED_MSG_ID_SHIFT (0)
+
+/* FW_DEVA_CMD_FAILED MSG_ID */
+#define FW_DEVA_CMD_FAILED_MSG_ID_TYPE uint16_t
+#define FW_DEVA_CMD_FAILED_MSG_ID_MASK (0xFFFF)
+#define FW_DEVA_CMD_FAILED_MSG_ID_OFFSET (0x0002)
+#define FW_DEVA_CMD_FAILED_MSG_ID_SHIFT (0)
+
+/* FW_DEVA_CMD_FAILED FLAGS */
+#define FW_DEVA_CMD_FAILED_FLAGS_TYPE uint32_t
+#define FW_DEVA_CMD_FAILED_FLAGS_MASK (0xFFFFFFFF)
+#define FW_DEVA_CMD_FAILED_FLAGS_OFFSET (0x0004)
+#define FW_DEVA_CMD_FAILED_FLAGS_SHIFT (0)
+
+/* FW_DXVA_DEBLOCK MSG_SIZE */
+#define FW_DXVA_DEBLOCK_MSG_SIZE_ALIGNMENT (1)
+#define FW_DXVA_DEBLOCK_MSG_SIZE_TYPE uint8_t
+#define FW_DXVA_DEBLOCK_MSG_SIZE_MASK (0xFF)
+#define FW_DXVA_DEBLOCK_MSG_SIZE_LSBMASK (0xFF)
+#define FW_DXVA_DEBLOCK_MSG_SIZE_OFFSET (0x0000)
+#define FW_DXVA_DEBLOCK_MSG_SIZE_SHIFT (0)
+
+/* FW_DXVA_DEBLOCK ID */
+#define FW_DXVA_DEBLOCK_ID_ALIGNMENT (1)
+#define FW_DXVA_DEBLOCK_ID_TYPE uint8_t
+#define FW_DXVA_DEBLOCK_ID_MASK (0xFF)
+#define FW_DXVA_DEBLOCK_ID_LSBMASK (0xFF)
+#define FW_DXVA_DEBLOCK_ID_OFFSET (0x0001)
+#define FW_DXVA_DEBLOCK_ID_SHIFT (0)
+
+/* FW_DXVA_DEBLOCK FENCE_VALUE */
+#define FW_DXVA_DEBLOCK_FENCE_VALUE_START_BIT 0
+#define FW_DXVA_DEBLOCK_FENCE_VALUE_END_BIT 15
+#define FW_DXVA_DEBLOCK_FENCE_VALUE_ALIGNMENT (4)
+#define FW_DXVA_DEBLOCK_FENCE_VALUE_TYPE uint16_t
+#define FW_DXVA_DEBLOCK_FENCE_VALUE_MASK (0xFFFF)
+#define FW_DXVA_DEBLOCK_FENCE_VALUE_LSBMASK (0xFFFF)
+#define FW_DXVA_DEBLOCK_FENCE_VALUE_OFFSET (0x0008)
+#define FW_DXVA_DEBLOCK_FENCE_VALUE_SHIFT (0)
+#define FW_DXVA_DEBLOCK_FENCE_VALUE_SIGNED_FIELD (0)
+
+/* FW_VA_HOST_BE_OPP MESSAGE */
+/* FW_VA_HOST_BE_OPP FENCE_VALUE */
+#define FW_VA_HOST_BE_OPP_FENCE_VALUE_ALIGNMENT (4)
+#define FW_VA_HOST_BE_OPP_FENCE_VALUE_TYPE uint16_t
+#define FW_VA_HOST_BE_OPP_FENCE_VALUE_MASK (0xFFFF)
+#define FW_VA_HOST_BE_OPP_FENCE_VALUE_LSBMASK (0xFFFF)
+#define FW_VA_HOST_BE_OPP_FENCE_VALUE_OFFSET (0x0008)
+#define FW_VA_HOST_BE_OPP_FENCE_VALUE_SHIFT (0)
+
+
+/* FW_VA_HOST_BE_OPP MMUPTD */
+#define FW_VA_HOST_BE_OPP_MMUPTD_ALIGNMENT (4)
+#define FW_VA_HOST_BE_OPP_MMUPTD_TYPE uint32_t
+#define FW_VA_HOST_BE_OPP_MMUPTD_MASK (0xFFFFFFFF)
+#define FW_VA_HOST_BE_OPP_MMUPTD_LSBMASK (0xFFFFFFFF)
+#define FW_VA_HOST_BE_OPP_MMUPTD_OFFSET (0x000C)
+#define FW_VA_HOST_BE_OPP_MMUPTD_SHIFT (0)
+
+
+/* FW_DXVA_DEBLOCK MMUPTD */
+#define FW_DXVA_DEBLOCK_MMUPTD_ALIGNMENT (4)
+#define FW_DXVA_DEBLOCK_MMUPTD_TYPE uint32_t
+#define FW_DXVA_DEBLOCK_MMUPTD_MASK (0xFFFFFFFF)
+#define FW_DXVA_DEBLOCK_MMUPTD_LSBMASK (0xFFFFFFFF)
+#define FW_DXVA_DEBLOCK_MMUPTD_OFFSET (0x000C)
+#define FW_DXVA_DEBLOCK_MMUPTD_SHIFT (0)
+
+#define FW_DXVA_OOLD_SIZE (40)
+
+
+// FW_VA_CMD_COMPLETED VDEBCR
+#define FW_VA_CMD_COMPLETED_VDEBCR_START_BIT 0
+#define FW_VA_CMD_COMPLETED_VDEBCR_END_BIT 31
+#define FW_VA_CMD_COMPLETED_VDEBCR_ALIGNMENT (4)
+#define FW_VA_CMD_COMPLETED_VDEBCR_TYPE uint32_t
+#define FW_VA_CMD_COMPLETED_VDEBCR_MASK (0xFFFFFFFF)
+#define FW_VA_CMD_COMPLETED_VDEBCR_LSBMASK (0xFFFFFFFF)
+#define FW_VA_CMD_COMPLETED_VDEBCR_OFFSET (0x000C)
+#define FW_VA_CMD_COMPLETED_VDEBCR_SHIFT (0)
+#define FW_VA_CMD_COMPLETED_VDEBCR_SIGNED_FIELD (0)
+
+/* FW_VA_CMD_FAILED FLAGS */
+#define FW_VA_CMD_FAILED_FLAGS_ALIGNMENT (4)
+#define FW_VA_CMD_FAILED_FLAGS_TYPE uint32_t
+#define FW_VA_CMD_FAILED_FLAGS_MASK (0xFFFFFFFF)
+#define FW_VA_CMD_FAILED_FLAGS_LSBMASK (0xFFFFFFFF)
+#define FW_VA_CMD_FAILED_FLAGS_OFFSET (0x0004)
+#define FW_VA_CMD_FAILED_FLAGS_SHIFT (0)
+#define FW_VA_CMD_FAILED_FLAGS_SIGNED_FIELD (0)
+
+/* FW_VA_CMD_FAILED_NO_EC FENCE_VALUE */
+#define FW_VA_CMD_FAILED_FENCE_VALUE_NO_EC_TYPE uint32_t
+#define FW_VA_CMD_FAILED_FENCE_VALUE_NO_EC_MASK (0xFFFFFFFF)
+#define FW_VA_CMD_FAILED_FENCE_VALUE_NO_EC_OFFSET (0x0004)
+#define FW_VA_CMD_FAILED_FENCE_VALUE_NO_EC_SHIFT (0)
+
+/* FW_VA_CMD_FAILED_NO_EC IRQSTATUS */
+#define FW_VA_CMD_FAILED_IRQSTATUS_NO_EC_TYPE uint32_t
+#define FW_VA_CMD_FAILED_IRQSTATUS_NO_EC_MASK (0xFFFFFFFF)
+#define FW_VA_CMD_FAILED_IRQSTATUS_NO_EC_OFFSET (0x0008)
+#define FW_VA_CMD_FAILED_IRQSTATUS_NO_EC_SHIFT (0)
+
+/* PANIC MESSAGE */
+// FW_VA_HW_PANIC FENCE_VALUE
+#define FW_VA_HW_PANIC_FENCE_VALUE_START_BIT 16
+#define FW_VA_HW_PANIC_FENCE_VALUE_END_BIT 31
+#define FW_VA_HW_PANIC_FENCE_VALUE_ALIGNMENT (2)
+#define FW_VA_HW_PANIC_FENCE_VALUE_TYPE uint16_t
+#define FW_VA_HW_PANIC_FENCE_VALUE_MASK (0xFFFF)
+#define FW_VA_HW_PANIC_FENCE_VALUE_LSBMASK (0xFFFF)
+#define FW_VA_HW_PANIC_FENCE_VALUE_OFFSET (0x0002)
+#define FW_VA_HW_PANIC_FENCE_VALUE_SHIFT (0)
+#define FW_VA_HW_PANIC_FENCE_VALUE_SIGNED_FIELD (0)
+
+/* FW_VA_HW_PANIC FIRST_MB_NUM */
+#define FW_VA_HW_PANIC_FIRST_MB_NUM_START_BIT 0
+#define FW_VA_HW_PANIC_FIRST_MB_NUM_END_BIT 15
+#define FW_VA_HW_PANIC_FIRST_MB_NUM_ALIGNMENT (2)
+#define FW_VA_HW_PANIC_FIRST_MB_NUM_TYPE uint16_t
+#define FW_VA_HW_PANIC_FIRST_MB_NUM_MASK (0xFFFF)
+#define FW_VA_HW_PANIC_FIRST_MB_NUM_LSBMASK (0xFFFF)
+#define FW_VA_HW_PANIC_FIRST_MB_NUM_OFFSET (0x0004)
+#define FW_VA_HW_PANIC_FIRST_MB_NUM_SHIFT (0)
+#define FW_VA_HW_PANIC_FIRST_MB_NUM_SIGNED_FIELD (0)
+
+/* FW_VA_HW_PANIC FAULT_MB_NUM */
+#define FW_VA_HW_PANIC_FAULT_MB_NUM_START_BIT 16
+#define FW_VA_HW_PANIC_FAULT_MB_NUM_END_BIT 31
+#define FW_VA_HW_PANIC_FAULT_MB_NUM_ALIGNMENT (2)
+#define FW_VA_HW_PANIC_FAULT_MB_NUM_TYPE uint16_t
+#define FW_VA_HW_PANIC_FAULT_MB_NUM_MASK (0xFFFF)
+#define FW_VA_HW_PANIC_FAULT_MB_NUM_LSBMASK (0xFFFF)
+#define FW_VA_HW_PANIC_FAULT_MB_NUM_OFFSET (0x0006)
+#define FW_VA_HW_PANIC_FAULT_MB_NUM_SHIFT (0)
+#define FW_VA_HW_PANIC_FAULT_MB_NUM_SIGNED_FIELD (0)
+
+/* FW_VA_HW_PANIC FESTATUS */
+#define FW_VA_HW_PANIC_FESTATUS_START_BIT 0
+#define FW_VA_HW_PANIC_FESTATUS_END_BIT 31
+#define FW_VA_HW_PANIC_FESTATUS_ALIGNMENT (4)
+#define FW_VA_HW_PANIC_FESTATUS_TYPE uint32_t
+#define FW_VA_HW_PANIC_FESTATUS_MASK (0xFFFFFFFF)
+#define FW_VA_HW_PANIC_FESTATUS_LSBMASK (0xFFFFFFFF)
+#define FW_VA_HW_PANIC_FESTATUS_OFFSET (0x0008)
+#define FW_VA_HW_PANIC_FESTATUS_SHIFT (0)
+#define FW_VA_HW_PANIC_FESTATUS_SIGNED_FIELD (0)
+
+/* FW_VA_HW_PANIC BESTATUS */
+#define FW_VA_HW_PANIC_BESTATUS_START_BIT 0
+#define FW_VA_HW_PANIC_BESTATUS_END_BIT 31
+#define FW_VA_HW_PANIC_BESTATUS_ALIGNMENT (4)
+#define FW_VA_HW_PANIC_BESTATUS_TYPE uint32_t
+#define FW_VA_HW_PANIC_BESTATUS_MASK (0xFFFFFFFF)
+#define FW_VA_HW_PANIC_BESTATUS_LSBMASK (0xFFFFFFFF)
+#define FW_VA_HW_PANIC_BESTATUS_OFFSET (0x000C)
+#define FW_VA_HW_PANIC_BESTATUS_SHIFT (0)
+#define FW_VA_HW_PANIC_BESTATUS_SIGNED_FIELD (0)
+
+/* FW_VA_DEBLOCK_REQUIRED MESSAGE*/
+/* FW_VA_DEBLOCK_REQUIRED FENCE_VALUE */
+#define FW_VA_DEBLOCK_REQUIRED_FENCE_VALUE_ALIGNMENT (2)
+#define FW_VA_DEBLOCK_REQUIRED_FENCE_VALUE_TYPE uint16_t
+#define FW_VA_DEBLOCK_REQUIRED_FENCE_VALUE_MASK (0xFFFF)
+#define FW_VA_DEBLOCK_REQUIRED_FENCE_VALUE_LSBMASK (0xFFFF)
+#define FW_VA_DEBLOCK_REQUIRED_FENCE_VALUE_OFFSET (0x0002)
+#define FW_VA_DEBLOCK_REQUIRED_FENCE_VALUE_SHIFT (0)
+#define FW_VA_DEBLOCK_REQUIRED_FENCE_VALUE_SIGNED_FIELD (0)
+
+
+/* FW_VA_DEBLOCK_REQUIRED CONTEXTNO_EC */
+#define FW_VA_DEBLOCK_REQUIRED_CONTEXT_NO_EC_TYPE uint32_t
+#define FW_VA_DEBLOCK_REQUIRED_CONTEXT_NO_EC_MASK (0xFFFFFFFF)
+#define FW_VA_DEBLOCK_REQUIRED_CONTEXT_NO_EC_OFFSET (0x0004)
+#define FW_VA_DEBLOCK_REQUIRED_CONTEXT_NO_EC_SHIFT (0)
+
+/* FW_VA_CONTIGUITY_WARNING MESSAGE */
+#define FW_VA_CONTIGUITY_WARNING_SIZE (8)
+
+/* FW_VA_CONTIGUITY_WARNING FENCE_VALUE */
+#define FW_VA_CONTIGUITY_WARNING_FENCE_VALUE_START_BIT 16
+#define FW_VA_CONTIGUITY_WARNING_FENCE_VALUE_END_BIT 31
+#define FW_VA_CONTIGUITY_WARNING_FENCE_VALUE_ALIGNMENT (2)
+#define FW_VA_CONTIGUITY_WARNING_FENCE_VALUE_TYPE uint16_t
+#define FW_VA_CONTIGUITY_WARNING_FENCE_VALUE_MASK (0xFFFF)
+#define FW_VA_CONTIGUITY_WARNING_FENCE_VALUE_LSBMASK (0xFFFF)
+#define FW_VA_CONTIGUITY_WARNING_FENCE_VALUE_OFFSET (0x0002)
+#define FW_VA_CONTIGUITY_WARNING_FENCE_VALUE_SHIFT (0)
+#define FW_VA_CONTIGUITY_WARNING_FENCE_VALUE_SIGNED_FIELD (0)
+
+/* FW_VA_CONTIGUITY_WARNING ID */
+#define FW_VA_CONTIGUITY_WARNING_ID_START_BIT 8
+#define FW_VA_CONTIGUITY_WARNING_ID_END_BIT 15
+#define FW_VA_CONTIGUITY_WARNING_ID_ALIGNMENT (1)
+#define FW_VA_CONTIGUITY_WARNING_ID_TYPE uint8_t
+#define FW_VA_CONTIGUITY_WARNING_ID_MASK (0xFF)
+#define FW_VA_CONTIGUITY_WARNING_ID_LSBMASK (0xFF)
+#define FW_VA_CONTIGUITY_WARNING_ID_OFFSET (0x0001)
+#define FW_VA_CONTIGUITY_WARNING_ID_SHIFT (0)
+#define FW_VA_CONTIGUITY_WARNING_ID_SIGNED_FIELD (0)
+
+/* FW_VA_CONTIGUITY_WARNING MSG_SIZE */
+#define FW_VA_CONTIGUITY_WARNING_MSG_SIZE_START_BIT 0
+#define FW_VA_CONTIGUITY_WARNING_MSG_SIZE_END_BIT 7
+#define FW_VA_CONTIGUITY_WARNING_MSG_SIZE_ALIGNMENT (1)
+#define FW_VA_CONTIGUITY_WARNING_MSG_SIZE_TYPE uint8_t
+#define FW_VA_CONTIGUITY_WARNING_MSG_SIZE_MASK (0xFF)
+#define FW_VA_CONTIGUITY_WARNING_MSG_SIZE_LSBMASK (0xFF)
+#define FW_VA_CONTIGUITY_WARNING_MSG_SIZE_OFFSET (0x0000)
+#define FW_VA_CONTIGUITY_WARNING_MSG_SIZE_SHIFT (0)
+#define FW_VA_CONTIGUITY_WARNING_MSG_SIZE_SIGNED_FIELD (0)
+
+/* FW_VA_CONTIGUITY_WARNING END_MB_NUM */
+#define FW_VA_CONTIGUITY_WARNING_END_MB_NUM_START_BIT 0
+#define FW_VA_CONTIGUITY_WARNING_END_MB_NUM_END_BIT 15
+#define FW_VA_CONTIGUITY_WARNING_END_MB_NUM_ALIGNMENT (2)
+#define FW_VA_CONTIGUITY_WARNING_END_MB_NUM_TYPE uint16_t
+#define FW_VA_CONTIGUITY_WARNING_END_MB_NUM_MASK (0xFFFF)
+#define FW_VA_CONTIGUITY_WARNING_END_MB_NUM_LSBMASK (0xFFFF)
+#define FW_VA_CONTIGUITY_WARNING_END_MB_NUM_OFFSET (0x0004)
+#define FW_VA_CONTIGUITY_WARNING_END_MB_NUM_SHIFT (0)
+#define FW_VA_CONTIGUITY_WARNING_END_MB_NUM_SIGNED_FIELD (0)
+
+/* FW_VA_CONTIGUITY_WARNING BEGIN_MB_NUM */
+#define FW_VA_CONTIGUITY_WARNING_BEGIN_MB_NUM_START_BIT 16
+#define FW_VA_CONTIGUITY_WARNING_BEGIN_MB_NUM_END_BIT 31
+#define FW_VA_CONTIGUITY_WARNING_BEGIN_MB_NUM_ALIGNMENT (2)
+#define FW_VA_CONTIGUITY_WARNING_BEGIN_MB_NUM_TYPE uint16_t
+#define FW_VA_CONTIGUITY_WARNING_BEGIN_MB_NUM_MASK (0xFFFF)
+#define FW_VA_CONTIGUITY_WARNING_BEGIN_MB_NUM_LSBMASK (0xFFFF)
+#define FW_VA_CONTIGUITY_WARNING_BEGIN_MB_NUM_OFFSET (0x0006)
+#define FW_VA_CONTIGUITY_WARNING_BEGIN_MB_NUM_SHIFT (0)
+#define FW_VA_CONTIGUITY_WARNING_BEGIN_MB_NUM_SIGNED_FIELD (0)
+
+/* FW_DXVA_OOLD FENCE_VALUE */
+#define FW_DXVA_OOLD_FENCE_VALUE_ALIGNMENT (4)
+#define FW_DXVA_OOLD_FENCE_VALUE_TYPE uint32_t
+#define FW_DXVA_OOLD_FENCE_VALUE_MASK (0xFFFFFFFF)
+#define FW_DXVA_OOLD_FENCE_VALUE_LSBMASK (0xFFFFFFFF)
+#define FW_DXVA_OOLD_FENCE_VALUE_OFFSET (0x0008)
+#define FW_DXVA_OOLD_FENCE_VALUE_SHIFT (0)
+
+/* FW_DXVA_OOLD MMUPTD */
+#define FW_DXVA_OOLD_MMUPTD_ALIGNMENT (4)
+#define FW_DXVA_OOLD_MMUPTD_TYPE IMG_UINT32
+#define FW_DXVA_OOLD_MMUPTD_MASK (0xFFFFFFFF)
+#define FW_DXVA_OOLD_MMUPTD_LSBMASK (0xFFFFFFFF)
+#define FW_DXVA_OOLD_MMUPTD_OFFSET (0x0004)
+#define FW_DXVA_OOLD_MMUPTD_SHIFT (0)
+
+#define FW_VA_LAST_SLICE_OF_EXT_DMA 0x00001000
+
+static inline void psb_msvdx_clearirq(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ unsigned long mtx_int = 0;
+
+ PSB_DEBUG_IRQ("MSVDX: clear IRQ\n");
+
+ /* Clear MTX interrupt */
+ REGIO_WRITE_FIELD_LITE(mtx_int, MSVDX_INTERRUPT_STATUS, CR_MTX_IRQ,
+ 1);
+ PSB_WMSVDX32(mtx_int, MSVDX_INTERRUPT_CLEAR);
+}
+
+
+static inline void psb_msvdx_disableirq(struct drm_device *dev)
+{
+ /* nothing */
+}
+
+
+static inline void psb_msvdx_enableirq(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ unsigned long enables = 0;
+
+ PSB_DEBUG_IRQ("MSVDX: enable MSVDX MTX IRQ\n");
+ REGIO_WRITE_FIELD_LITE(enables, MSVDX_INTERRUPT_STATUS, CR_MTX_IRQ,
+ 1);
+ PSB_WMSVDX32(enables, MSVDX_HOST_INTERRUPT_ENABLE);
+}
+
+#define MSVDX_NEW_PMSTATE(drm_dev, msvdx_priv, new_state) \
+do { \
+ msvdx_priv->pmstate = new_state; \
+ sysfs_notify_dirent(msvdx_priv->sysfs_pmstate); \
+ PSB_DEBUG_PM("MSVDX: %s\n", \
+ (new_state == PSB_PMSTATE_POWERUP) ? "powerup" \
+ : ((new_state == PSB_PMSTATE_POWERDOWN) ? "powerdown" \
+ : "clockgated")); \
+} while (0)
+
+#endif
--- /dev/null
+/**************************************************************************
+ * psb_msvdxinit.c
+ * MSVDX initialization and mtx-firmware upload
+ *
+ * Copyright (c) 2007 Intel Corporation, Hillsboro, OR, USA
+ * Copyright (c) Imagination Technologies Limited, UK
+ *
+ * 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 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.
+ *
+ **************************************************************************/
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include "psb_drv.h"
+#include "psb_msvdx.h"
+#include <linux/firmware.h>
+
+#define MSVDX_REG (dev_priv->msvdx_reg)
+#define UPLOAD_FW_BY_DMA 1
+#define STACKGUARDWORD ( 0x10101010 )
+#define MSVDX_MTX_DATA_LOCATION ( 0x82880000 )
+#define UNINITILISE_MEM ( 0xcdcdcdcd )
+#define FIRMWAREID ( 0x014d42ab )
+
+static uint8_t psb_rev_id;
+/*MSVDX FW header*/
+struct msvdx_fw {
+ uint32_t ver;
+ uint32_t text_size;
+ uint32_t data_size;
+ uint32_t data_location;
+};
+
+int psb_wait_for_register(struct drm_psb_private *dev_priv,
+ uint32_t offset, uint32_t value, uint32_t enable)
+{
+ uint32_t reg_value;
+ uint32_t poll_cnt = 1000000;
+ while (poll_cnt) {
+ reg_value = PSB_RMSVDX32(offset);
+ if (value == (reg_value & enable)) /* All the bits are reset */
+ return 0; /* So exit */
+
+ /* Wait a bit */
+ PSB_UDELAY(1);
+ poll_cnt--;
+ }
+ DRM_ERROR("MSVDX: Timeout while waiting for register %08x:"
+ " expecting %08x (mask %08x), got %08x\n",
+ offset, value, enable, reg_value);
+
+ return 1;
+}
+
+static int psb_poll_mtx_irq(struct drm_psb_private *dev_priv)
+{
+ int ret = 0;
+ uint32_t mtx_int = 0;
+
+ REGIO_WRITE_FIELD_LITE(mtx_int, MSVDX_INTERRUPT_STATUS, CR_MTX_IRQ,
+ 1);
+
+ ret = psb_wait_for_register(dev_priv, MSVDX_INTERRUPT_STATUS,
+ /* Required value */
+ mtx_int,
+ /* Enabled bits */
+ mtx_int);
+
+ if (ret) {
+ DRM_ERROR("MSVDX: Error Mtx did not return"
+ " int within a resonable time\n");
+ return ret;
+ }
+
+ PSB_DEBUG_IRQ("MSVDX: Got MTX Int\n");
+
+ /* Got it so clear the bit */
+ PSB_WMSVDX32(mtx_int, MSVDX_INTERRUPT_CLEAR);
+
+ return ret;
+}
+
+static void psb_write_mtx_core_reg(struct drm_psb_private *dev_priv,
+ const uint32_t core_reg, const uint32_t val)
+{
+ uint32_t reg = 0;
+
+ /* Put data in MTX_RW_DATA */
+ PSB_WMSVDX32(val, MSVDX_MTX_REGISTER_READ_WRITE_DATA);
+
+ /* DREADY is set to 0 and request a write */
+ reg = core_reg;
+ REGIO_WRITE_FIELD_LITE(reg, MSVDX_MTX_REGISTER_READ_WRITE_REQUEST,
+ MTX_RNW, 0);
+ REGIO_WRITE_FIELD_LITE(reg, MSVDX_MTX_REGISTER_READ_WRITE_REQUEST,
+ MTX_DREADY, 0);
+ PSB_WMSVDX32(reg, MSVDX_MTX_REGISTER_READ_WRITE_REQUEST);
+
+ psb_wait_for_register(dev_priv,
+ MSVDX_MTX_REGISTER_READ_WRITE_REQUEST,
+ MSVDX_MTX_REGISTER_READ_WRITE_REQUEST_MTX_DREADY_MASK,
+ MSVDX_MTX_REGISTER_READ_WRITE_REQUEST_MTX_DREADY_MASK);
+}
+
+#if UPLOAD_FW_BY_DMA
+
+static void psb_get_mtx_control_from_dash(struct drm_psb_private *dev_priv)
+{
+ struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+ int count = 0;
+ uint32_t reg_val = 0;
+
+ REGIO_WRITE_FIELD(reg_val, MSVDX_MTX_DEBUG, MTX_DBG_IS_SLAVE, 1);
+ REGIO_WRITE_FIELD(reg_val, MSVDX_MTX_DEBUG, MTX_DBG_GPIO_IN, 0x02);
+ PSB_WMSVDX32(reg_val, MSVDX_MTX_DEBUG);
+
+ do {
+ reg_val = PSB_RMSVDX32(MSVDX_MTX_DEBUG);
+ count++;
+ } while (((reg_val & 0x18) != 0) && count < 50000);
+
+ if (count >= 50000)
+ PSB_DEBUG_GENERAL("TOPAZ: timeout in get_mtx_control_from_dash\n");
+
+ /* Save the access control register...*/
+ msvdx_priv->psb_dash_access_ctrl = PSB_RMSVDX32(MSVDX_MTX_RAM_ACCESS_CONTROL);
+
+}
+
+static void psb_release_mtx_control_from_dash(struct drm_psb_private *dev_priv)
+{
+ struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+
+ /* restore access control */
+ PSB_WMSVDX32(msvdx_priv->psb_dash_access_ctrl, MSVDX_MTX_RAM_ACCESS_CONTROL);
+ /* release bus */
+ PSB_WMSVDX32(0x4, MSVDX_MTX_DEBUG);
+}
+
+
+
+static void psb_upload_fw(struct drm_psb_private *dev_priv,
+ uint32_t address, const unsigned int words, int fw_sel)
+{
+ uint32_t reg_val = 0;
+ uint32_t cmd;
+ uint32_t uCountReg, offset, mmu_ptd;
+ uint32_t size = (words * 4); /* byte count */
+ uint32_t dma_channel = 0; /* Setup a Simple DMA for Ch0 */
+ struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+
+ PSB_DEBUG_GENERAL("MSVDX: Upload firmware by DMA\n");
+ psb_get_mtx_control_from_dash(dev_priv);
+
+ // dma transfers to/from the mtx have to be 32-bit aligned and in multiples of 32 bits
+ PSB_WMSVDX32(address, REGISTER(MTX_CORE, CR_MTX_SYSC_CDMAA));
+
+ REGIO_WRITE_FIELD_LITE(reg_val, MTX_CORE_CR_MTX_SYSC_CDMAC, BURSTSIZE, 4); // burst size in multiples of 64 bits (allowed values are 2 or 4)
+ REGIO_WRITE_FIELD_LITE(reg_val, MTX_CORE_CR_MTX_SYSC_CDMAC, RNW, 0); // false means write to mtx mem, true means read from mtx mem
+ REGIO_WRITE_FIELD_LITE(reg_val, MTX_CORE_CR_MTX_SYSC_CDMAC, ENABLE, 1); // begin transfer
+ REGIO_WRITE_FIELD_LITE(reg_val, MTX_CORE_CR_MTX_SYSC_CDMAC, LENGTH, words); // This specifies the transfer size of the DMA operation in terms of 32-bit words
+ PSB_WMSVDX32(reg_val, REGISTER(MTX_CORE, CR_MTX_SYSC_CDMAC));
+
+ // toggle channel 0 usage between mtx and other msvdx peripherals
+ {
+ reg_val = PSB_RMSVDX32(REGISTER(MSVDX_CORE, CR_MSVDX_CONTROL));
+ REGIO_WRITE_FIELD(reg_val, MSVDX_CORE_CR_MSVDX_CONTROL, DMAC_CH0_SELECT, 0);
+ PSB_WMSVDX32(reg_val, REGISTER(MSVDX_CORE, CR_MSVDX_CONTROL));
+ }
+
+
+ /* Clear the DMAC Stats */
+ PSB_WMSVDX32(0 , REGISTER(DMAC, DMAC_IRQ_STAT) + dma_channel);
+
+ offset = msvdx_priv->fw->offset;
+
+ if (fw_sel)
+ offset += ((msvdx_priv->mtx_mem_size + 8192) & ~0xfff);
+
+ /* use bank 0 */
+ cmd = 0;
+ PSB_WMSVDX32(cmd, REGISTER(MSVDX_CORE, CR_MMU_BANK_INDEX));
+
+ /* Write PTD to mmu base 0*/
+ mmu_ptd = psb_get_default_pd_addr(dev_priv->mmu);
+ PSB_WMSVDX32(mmu_ptd, REGISTER(MSVDX_CORE, CR_MMU_DIR_LIST_BASE) + 0);
+
+ /* Invalidate */
+ reg_val = PSB_RMSVDX32(REGISTER(MSVDX_CORE, CR_MMU_CONTROL0));
+ reg_val &= ~0xf;
+ REGIO_WRITE_FIELD(reg_val, MSVDX_CORE_CR_MMU_CONTROL0, CR_MMU_INVALDC, 1);
+ PSB_WMSVDX32(reg_val, REGISTER(MSVDX_CORE, CR_MMU_CONTROL0));
+
+ PSB_WMSVDX32(offset, REGISTER(DMAC, DMAC_SETUP) + dma_channel);
+
+ /* Only use a single dma - assert that this is valid */
+ if ((size / 4) >= (1 << 15)) {
+ DRM_ERROR("psb: DMA size beyond limited, aboart firmware uploading\n");
+ return;
+ }
+
+
+ uCountReg = PSB_DMAC_VALUE_COUNT(PSB_DMAC_BSWAP_NO_SWAP,
+ 0, /* 32 bits */
+ PSB_DMAC_DIR_MEM_TO_PERIPH,
+ 0,
+ (size / 4));
+ /* Set the number of bytes to dma*/
+ PSB_WMSVDX32(uCountReg, REGISTER(DMAC, DMAC_COUNT) + dma_channel);
+
+ cmd = PSB_DMAC_VALUE_PERIPH_PARAM(PSB_DMAC_ACC_DEL_0, PSB_DMAC_INCR_OFF, PSB_DMAC_BURST_2);
+ PSB_WMSVDX32(cmd, REGISTER(DMAC, DMAC_PERIPH) + dma_channel);
+
+ /* Set destination port for dma */
+ cmd = 0;
+ REGIO_WRITE_FIELD(cmd, DMAC_DMAC_PERIPHERAL_ADDR, ADDR, MTX_CORE_CR_MTX_SYSC_CDMAT_OFFSET);
+ PSB_WMSVDX32(cmd, REGISTER(DMAC, DMAC_PERIPHERAL_ADDR) + dma_channel);
+
+
+ /* Finally, rewrite the count register with the enable bit set*/
+ PSB_WMSVDX32(uCountReg | DMAC_DMAC_COUNT_EN_MASK, REGISTER(DMAC, DMAC_COUNT) + dma_channel);
+
+ /* Wait for all to be done */
+ if (psb_wait_for_register(dev_priv,
+ REGISTER(DMAC, DMAC_IRQ_STAT) + dma_channel,
+ DMAC_DMAC_IRQ_STAT_TRANSFER_FIN_MASK,
+ DMAC_DMAC_IRQ_STAT_TRANSFER_FIN_MASK)) {
+ psb_release_mtx_control_from_dash(dev_priv);
+ return;
+ }
+
+ /* Assert that the MTX DMA port is all done aswell */
+ if (psb_wait_for_register(dev_priv, REGISTER(MTX_CORE, CR_MTX_SYSC_CDMAS0), 1, 1)) {
+ psb_release_mtx_control_from_dash(dev_priv);
+ return;
+ }
+
+ psb_release_mtx_control_from_dash(dev_priv);
+ PSB_DEBUG_GENERAL("MSVDX: Upload done\n");
+}
+
+#else
+
+static void psb_upload_fw(struct drm_psb_private *dev_priv,
+ const uint32_t data_mem, uint32_t ram_bank_size,
+ uint32_t address, const unsigned int words,
+ const uint32_t * const data)
+{
+ uint32_t loop, ctrl, ram_id, addr, cur_bank = (uint32_t) ~0;
+ uint32_t access_ctrl;
+
+ PSB_DEBUG_GENERAL("MSVDX: Upload firmware by register interface\n");
+ /* Save the access control register... */
+ access_ctrl = PSB_RMSVDX32(MSVDX_MTX_RAM_ACCESS_CONTROL);
+
+ /* Wait for MCMSTAT to become be idle 1 */
+ psb_wait_for_register(dev_priv, MSVDX_MTX_RAM_ACCESS_STATUS,
+ 1, /* Required Value */
+ 0xffffffff /* Enables */);
+
+ for (loop = 0; loop < words; loop++) {
+ ram_id = data_mem + (address / ram_bank_size);
+ if (ram_id != cur_bank) {
+ addr = address >> 2;
+ ctrl = 0;
+ REGIO_WRITE_FIELD_LITE(ctrl,
+ MSVDX_MTX_RAM_ACCESS_CONTROL,
+ MTX_MCMID, ram_id);
+ REGIO_WRITE_FIELD_LITE(ctrl,
+ MSVDX_MTX_RAM_ACCESS_CONTROL,
+ MTX_MCM_ADDR, addr);
+ REGIO_WRITE_FIELD_LITE(ctrl,
+ MSVDX_MTX_RAM_ACCESS_CONTROL,
+ MTX_MCMAI, 1);
+ PSB_WMSVDX32(ctrl, MSVDX_MTX_RAM_ACCESS_CONTROL);
+ cur_bank = ram_id;
+ }
+ address += 4;
+
+ PSB_WMSVDX32(data[loop],
+ MSVDX_MTX_RAM_ACCESS_DATA_TRANSFER);
+
+ /* Wait for MCMSTAT to become be idle 1 */
+ psb_wait_for_register(dev_priv, MSVDX_MTX_RAM_ACCESS_STATUS,
+ 1, /* Required Value */
+ 0xffffffff /* Enables */);
+ }
+ PSB_DEBUG_GENERAL("MSVDX: Upload done\n");
+
+ /* Restore the access control register... */
+ PSB_WMSVDX32(access_ctrl, MSVDX_MTX_RAM_ACCESS_CONTROL);
+}
+
+#endif
+
+static int psb_verify_fw(struct drm_psb_private *dev_priv,
+ const uint32_t ram_bank_size,
+ const uint32_t data_mem, uint32_t address,
+ const uint32_t words, const uint32_t * const data)
+{
+ uint32_t loop, ctrl, ram_id, addr, cur_bank = (uint32_t) ~0;
+ uint32_t access_ctrl;
+ int ret = 0;
+
+ /* Save the access control register... */
+ access_ctrl = PSB_RMSVDX32(MSVDX_MTX_RAM_ACCESS_CONTROL);
+
+ /* Wait for MCMSTAT to become be idle 1 */
+ psb_wait_for_register(dev_priv, MSVDX_MTX_RAM_ACCESS_STATUS,
+ 1, /* Required Value */
+ 0xffffffff /* Enables */);
+
+ for (loop = 0; loop < words; loop++) {
+ uint32_t reg_value;
+ ram_id = data_mem + (address / ram_bank_size);
+
+ if (ram_id != cur_bank) {
+ addr = address >> 2;
+ ctrl = 0;
+ REGIO_WRITE_FIELD_LITE(ctrl,
+ MSVDX_MTX_RAM_ACCESS_CONTROL,
+ MTX_MCMID, ram_id);
+ REGIO_WRITE_FIELD_LITE(ctrl,
+ MSVDX_MTX_RAM_ACCESS_CONTROL,
+ MTX_MCM_ADDR, addr);
+ REGIO_WRITE_FIELD_LITE(ctrl,
+ MSVDX_MTX_RAM_ACCESS_CONTROL,
+ MTX_MCMAI, 1);
+ REGIO_WRITE_FIELD_LITE(ctrl,
+ MSVDX_MTX_RAM_ACCESS_CONTROL,
+ MTX_MCMR, 1);
+
+ PSB_WMSVDX32(ctrl, MSVDX_MTX_RAM_ACCESS_CONTROL);
+
+ cur_bank = ram_id;
+ }
+ address += 4;
+
+ /* Wait for MCMSTAT to become be idle 1 */
+ psb_wait_for_register(dev_priv, MSVDX_MTX_RAM_ACCESS_STATUS,
+ 1, /* Required Value */
+ 0xffffffff /* Enables */);
+
+ reg_value = PSB_RMSVDX32(MSVDX_MTX_RAM_ACCESS_DATA_TRANSFER);
+ if (data[loop] != reg_value) {
+ DRM_ERROR("psb: Firmware validation fails"
+ " at index=%08x\n", loop);
+ ret = 1;
+ break;
+ }
+ }
+
+ /* Restore the access control register... */
+ PSB_WMSVDX32(access_ctrl, MSVDX_MTX_RAM_ACCESS_CONTROL);
+
+ return ret;
+}
+
+static int msvdx_get_fw_bo(struct drm_device *dev,
+ const struct firmware **raw, uint8_t *name)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ int rc, fw_size;
+ void *ptr = NULL;
+ struct ttm_bo_kmap_obj tmp_kmap;
+ bool is_iomem;
+ struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+ void *gpu_addr;
+
+ rc = request_firmware(raw, name, &dev->pdev->dev);
+ if (rc < 0) {
+ DRM_ERROR("MSVDX: %s request_firmware failed: Reason %d\n",
+ name, rc);
+ return 1;
+ }
+
+ if ((*raw)->size < sizeof(struct msvdx_fw)) {
+ DRM_ERROR("MSVDX: %s is is not correct size(%zd)\n",
+ name, (*raw)->size);
+ return 1;
+ }
+
+ ptr = (void *)((*raw))->data;
+
+ if (!ptr) {
+ DRM_ERROR("MSVDX: Failed to load %s\n", name);
+ return 1;
+ }
+
+ /* another sanity check... */
+ fw_size = sizeof(struct msvdx_fw) +
+ sizeof(uint32_t) * ((struct msvdx_fw *) ptr)->text_size +
+ sizeof(uint32_t) * ((struct msvdx_fw *) ptr)->data_size;
+ if ((*raw)->size < fw_size) {
+ DRM_ERROR("MSVDX: %s is is not correct size(%zd)\n",
+ name, (*raw)->size);
+ return 1;
+ }
+
+ rc = ttm_bo_kmap(msvdx_priv->fw, 0, (msvdx_priv->fw)->num_pages, &tmp_kmap);
+ if (rc) {
+ PSB_DEBUG_GENERAL("drm_bo_kmap failed: %d\n", rc);
+ ttm_bo_unref(&msvdx_priv->fw);
+ ttm_bo_kunmap(&tmp_kmap);
+ return 1;
+ } else {
+ uint32_t *last_word;
+ gpu_addr = ttm_kmap_obj_virtual(&tmp_kmap, &is_iomem);
+
+ memset(gpu_addr, UNINITILISE_MEM, msvdx_priv->mtx_mem_size);
+
+ memcpy(gpu_addr, ptr + sizeof(struct msvdx_fw),
+ sizeof(uint32_t) *((struct msvdx_fw *) ptr)->text_size);
+
+ memcpy(gpu_addr + (((struct msvdx_fw *) ptr)->data_location - MSVDX_MTX_DATA_LOCATION),
+ (void *)ptr + sizeof(struct msvdx_fw) + sizeof(uint32_t) *((struct msvdx_fw *) ptr)->text_size,
+ sizeof(uint32_t) *((struct msvdx_fw *) ptr)->data_size);
+
+ last_word = (uint32_t *)(gpu_addr + msvdx_priv->mtx_mem_size - 4);
+ /* Write a know value to last word in mtx memory*/
+ /* Usefull for detection of stack overrun */
+ *last_word = STACKGUARDWORD;
+ }
+
+ ttm_bo_kunmap(&tmp_kmap);
+ PSB_DEBUG_GENERAL("MSVDX: releasing firmware resouces\n");
+ PSB_DEBUG_GENERAL("MSVDX: Load firmware into BO successfully\n");
+ release_firmware(*raw);
+ return rc;
+}
+
+
+static uint32_t *msvdx_get_fw(struct drm_device *dev,
+ const struct firmware **raw, uint8_t *name)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ int rc, fw_size;
+ void *ptr = NULL;
+ struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+
+ rc = request_firmware(raw, name, &dev->pdev->dev);
+ if (rc < 0) {
+ DRM_ERROR("MSVDX: %s request_firmware failed: Reason %d\n",
+ name, rc);
+ return NULL;
+ }
+
+ if ((*raw)->size < sizeof(struct msvdx_fw)) {
+ DRM_ERROR("MSVDX: %s is is not correct size(%zd)\n",
+ name, (*raw)->size);
+ return NULL;
+ }
+
+ ptr = (int *)((*raw))->data;
+
+ if (!ptr) {
+ DRM_ERROR("MSVDX: Failed to load %s\n", name);
+ return NULL;
+ }
+
+ /* another sanity check... */
+ fw_size = sizeof(struct msvdx_fw) +
+ sizeof(uint32_t) * ((struct msvdx_fw *) ptr)->text_size +
+ sizeof(uint32_t) * ((struct msvdx_fw *) ptr)->data_size;
+ if ((*raw)->size < fw_size) {
+ DRM_ERROR("MSVDX: %s is is not correct size(%zd)\n",
+ name, (*raw)->size);
+ return NULL;
+ } else if ((*raw)->size > fw_size) { /* there is ec firmware */
+ ptr += ((fw_size + 0xfff) & ~0xfff);
+ fw_size += (sizeof(struct msvdx_fw) +
+ sizeof(uint32_t) * ((struct msvdx_fw *) ptr)->text_size +
+ sizeof(uint32_t) * ((struct msvdx_fw *) ptr)->data_size);
+
+ ptr = (int *)((*raw))->data; /* Resotre ptr to start of the firmware file */
+ }
+
+ msvdx_priv->msvdx_fw = kzalloc(fw_size, GFP_KERNEL);
+ if (msvdx_priv->msvdx_fw == NULL)
+ DRM_ERROR("MSVDX: allocate FW buffer failed\n");
+ else {
+ memcpy(msvdx_priv->msvdx_fw, ptr, fw_size);
+ msvdx_priv->msvdx_fw_size = fw_size;
+ }
+
+ PSB_DEBUG_GENERAL("MSVDX: releasing firmware resouces\n");
+ release_firmware(*raw);
+
+ return msvdx_priv->msvdx_fw;
+}
+
+int psb_setup_fw(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ uint32_t ram_bank_size;
+ struct msvdx_fw *fw;
+ uint32_t *fw_ptr = NULL;
+ uint32_t *text_ptr = NULL;
+ uint32_t *data_ptr = NULL;
+ const struct firmware *raw = NULL;
+ struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+ int ec_firmware = 0, ret = 0;
+
+ /* todo : Assert the clock is on - if not turn it on to upload code */
+ PSB_DEBUG_GENERAL("MSVDX: psb_setup_fw\n");
+ PSB_WMSVDX32(clk_enable_all, MSVDX_MAN_CLK_ENABLE);
+
+ /* Reset MTX */
+ PSB_WMSVDX32(MSVDX_MTX_SOFT_RESET_MTX_RESET_MASK,
+ MSVDX_MTX_SOFT_RESET);
+
+ /* Initialses Communication controll area to 0 */
+ /*
+ if (psb_rev_id >= POULSBO_D1) {
+ PSB_DEBUG_GENERAL("MSVDX: Detected Poulsbo D1"
+ " or later revision.\n");
+ PSB_WMSVDX32(MSVDX_DEVICE_NODE_FLAGS_DEFAULT_D1,
+ MSVDX_COMMS_OFFSET_FLAGS);
+ } else {
+ PSB_DEBUG_GENERAL("MSVDX: Detected Poulsbo D0"
+ " or earlier revision.\n");
+ PSB_WMSVDX32(MSVDX_DEVICE_NODE_FLAGS_DEFAULT_D0,
+ MSVDX_COMMS_OFFSET_FLAGS);
+ }
+ */
+
+ PSB_WMSVDX32(FIRMWAREID, MSVDX_COMMS_FIRMWARE_ID);
+
+ PSB_WMSVDX32(0, MSVDX_COMMS_ERROR_TRIG);
+ PSB_WMSVDX32(199, MSVDX_MTX_SYSC_TIMERDIV); /* MTX_SYSC_TIMERDIV */
+ PSB_WMSVDX32(0, MSVDX_EXT_FW_ERROR_STATE); /* EXT_FW_ERROR_STATE */
+
+ PSB_WMSVDX32(0, MSVDX_COMMS_MSG_COUNTER);
+ PSB_WMSVDX32(0, MSVDX_COMMS_SIGNATURE);
+ PSB_WMSVDX32(0, MSVDX_COMMS_TO_HOST_RD_INDEX);
+ PSB_WMSVDX32(0, MSVDX_COMMS_TO_HOST_WRT_INDEX);
+ PSB_WMSVDX32(0, MSVDX_COMMS_TO_MTX_RD_INDEX);
+ PSB_WMSVDX32(0, MSVDX_COMMS_TO_MTX_WRT_INDEX);
+ PSB_WMSVDX32(0, MSVDX_COMMS_FW_STATUS);
+ PSB_WMSVDX32(DSIABLE_IDLE_GPIO_SIG | DSIABLE_Auto_CLOCK_GATING | RETURN_VDEB_DATA_IN_COMPLETION | DSIABLE_FW_WDT,
+ MSVDX_COMMS_OFFSET_FLAGS);
+ PSB_WMSVDX32(0, MSVDX_COMMS_SIGNATURE);
+ /* read register bank size */
+ {
+ uint32_t bank_size, reg;
+ reg = PSB_RMSVDX32(MSVDX_MTX_RAM_BANK);
+ bank_size =
+ REGIO_READ_FIELD(reg, MSVDX_MTX_RAM_BANK,
+ CR_MTX_RAM_BANK_SIZE);
+ ram_bank_size = (uint32_t)(1 << (bank_size + 2));
+ }
+
+ PSB_DEBUG_GENERAL("MSVDX: RAM bank size = %d bytes\n",
+ ram_bank_size);
+
+ /* if FW already loaded from storage */
+ if (msvdx_priv->msvdx_fw)
+ fw_ptr = msvdx_priv->msvdx_fw;
+ else {
+ fw_ptr = msvdx_get_fw(dev, &raw, "msvdx_fw_mfld_DE2.0.bin");
+
+ PSB_DEBUG_GENERAL("MSVDX:load msvdx_fw_mfld_DE2.0.bin by udevd\n");
+ }
+
+ if (!fw_ptr) {
+ DRM_ERROR("MSVDX:load msvdx_fw.bin failed,is udevd running?\n");
+ ret = 1;
+ goto out;
+ }
+
+ if (!msvdx_priv->is_load) {/* Load firmware into BO */
+ PSB_DEBUG_GENERAL("MSVDX:load msvdx_fw.bin by udevd into BO\n");
+ ret = msvdx_get_fw_bo(dev, &raw, "msvdx_fw_mfld_DE2.0.bin");
+ msvdx_priv->is_load = 1;
+ }
+
+
+ fw = (struct msvdx_fw *) fw_ptr;
+
+ if (ec_firmware) {
+ fw_ptr += (((sizeof(struct msvdx_fw) + (fw->text_size + fw->data_size) * 4 + 0xfff) & ~0xfff) / sizeof(uint32_t));
+ fw = (struct msvdx_fw *) fw_ptr;
+ }
+
+ /*
+ if (fw->ver != 0x02) {
+ DRM_ERROR("psb: msvdx_fw.bin firmware version mismatch,"
+ "got version=%02x expected version=%02x\n",
+ fw->ver, 0x02);
+ ret = 1;
+ goto out;
+ }
+ */
+ text_ptr =
+ (uint32_t *)((uint8_t *) fw_ptr + sizeof(struct msvdx_fw));
+ data_ptr = text_ptr + fw->text_size;
+
+ if (fw->text_size == 2858)
+ PSB_DEBUG_GENERAL(
+ "MSVDX: FW ver 1.00.10.0187 of SliceSwitch variant\n");
+ else if (fw->text_size == 3021)
+ PSB_DEBUG_GENERAL(
+ "MSVDX: FW ver 1.00.10.0187 of FrameSwitch variant\n");
+ else if (fw->text_size == 2841)
+ PSB_DEBUG_GENERAL("MSVDX: FW ver 1.00.10.0788\n");
+ else if (fw->text_size == 3147)
+ PSB_DEBUG_GENERAL("MSVDX: FW ver BUILD_DXVA_FW1.00.10.1042 of SliceSwitch variant\n");
+ else if (fw->text_size == 3097)
+ PSB_DEBUG_GENERAL("MSVDX: FW ver BUILD_DXVA_FW1.00.10.0963.02.0011 of FrameSwitch variant\n");
+ else
+ PSB_DEBUG_GENERAL("MSVDX: FW ver unknown\n");
+
+
+ PSB_DEBUG_GENERAL("MSVDX: Retrieved pointers for firmware\n");
+ PSB_DEBUG_GENERAL("MSVDX: text_size: %d\n", fw->text_size);
+ PSB_DEBUG_GENERAL("MSVDX: data_size: %d\n", fw->data_size);
+ PSB_DEBUG_GENERAL("MSVDX: data_location: 0x%x\n",
+ fw->data_location);
+ PSB_DEBUG_GENERAL("MSVDX: First 4 bytes of text: 0x%x\n",
+ *text_ptr);
+ PSB_DEBUG_GENERAL("MSVDX: First 4 bytes of data: 0x%x\n",
+ *data_ptr);
+
+ PSB_DEBUG_GENERAL("MSVDX: Uploading firmware\n");
+#if UPLOAD_FW_BY_DMA
+ psb_upload_fw(dev_priv, 0, msvdx_priv->mtx_mem_size / 4, ec_firmware);
+#else
+ psb_upload_fw(dev_priv, MTX_CORE_CODE_MEM, ram_bank_size,
+ PC_START_ADDRESS - MTX_CODE_BASE, fw->text_size,
+ text_ptr);
+ psb_upload_fw(dev_priv, MTX_CORE_DATA_MEM, ram_bank_size,
+ fw->data_location - MTX_DATA_BASE, fw->data_size,
+ data_ptr);
+#endif
+#if 0
+ /* todo : Verify code upload possibly only in debug */
+ ret = psb_verify_fw(dev_priv, ram_bank_size,
+ MTX_CORE_CODE_MEM,
+ PC_START_ADDRESS - MTX_CODE_BASE,
+ fw->text_size, text_ptr);
+ if (ret) {
+ /* Firmware code upload failed */
+ ret = 1;
+ goto out;
+ }
+
+ ret = psb_verify_fw(dev_priv, ram_bank_size, MTX_CORE_DATA_MEM,
+ fw->data_location - MTX_DATA_BASE,
+ fw->data_size, data_ptr);
+ if (ret) {
+ /* Firmware data upload failed */
+ ret = 1;
+ goto out;
+ }
+#else
+ (void)psb_verify_fw;
+#endif
+ /* -- Set starting PC address */
+ psb_write_mtx_core_reg(dev_priv, MTX_PC, PC_START_ADDRESS);
+
+ /* -- Turn on the thread */
+ PSB_WMSVDX32(MSVDX_MTX_ENABLE_MTX_ENABLE_MASK, MSVDX_MTX_ENABLE);
+
+ /* Wait for the signature value to be written back */
+ ret = psb_wait_for_register(dev_priv, MSVDX_COMMS_SIGNATURE,
+ MSVDX_COMMS_SIGNATURE_VALUE, /*Required value*/
+ 0xffffffff /* Enabled bits */);
+ if (ret) {
+ DRM_ERROR("MSVDX: firmware fails to initialize.\n");
+ goto out;
+ }
+
+ PSB_DEBUG_GENERAL("MSVDX: MTX Initial indications OK\n");
+ PSB_DEBUG_GENERAL("MSVDX: MSVDX_COMMS_AREA_ADDR = %08x\n",
+ MSVDX_COMMS_AREA_ADDR);
+#if 0
+
+ /* Send test message */
+ {
+ uint32_t msg_buf[FW_VA_DEBUG_TEST2_SIZE >> 2];
+
+ MEMIO_WRITE_FIELD(msg_buf, FW_VA_DEBUG_TEST2_MSG_SIZE,
+ FW_VA_DEBUG_TEST2_SIZE);
+ MEMIO_WRITE_FIELD(msg_buf, FW_VA_DEBUG_TEST2_ID,
+ VA_MSGID_TEST2);
+
+ ret = psb_mtx_send(dev_priv, msg_buf);
+ if (ret) {
+ DRM_ERROR("psb: MSVDX sending fails.\n");
+ goto out;
+ }
+
+ /* Wait for Mtx to ack this message */
+ psb_poll_mtx_irq(dev_priv);
+
+ }
+#endif
+out:
+
+ return ret;
+}
+
+
+static void psb_free_ccb(struct ttm_buffer_object **ccb)
+{
+ ttm_bo_unref(ccb);
+ *ccb = NULL;
+}
+
+/**
+ * Reset chip and disable interrupts.
+ * Return 0 success, 1 failure
+ */
+int psb_msvdx_reset(struct drm_psb_private *dev_priv)
+{
+ int ret = 0;
+
+ if (IS_PENWELL(dev_priv->dev)) {
+ int loop;
+ /* Enable Clocks */
+ PSB_DEBUG_GENERAL("Enabling clocks\n");
+ PSB_WMSVDX32(clk_enable_all, MSVDX_MAN_CLK_ENABLE);
+
+ /* Always pause the MMU as the core may be still active when resetting. It is very bad to have memory
+ activity at the same time as a reset - Very Very bad */
+ PSB_WMSVDX32(2, MSVDX_MMU_CONTROL0);
+
+ for (loop = 0; loop < 50; loop++)
+ ret = psb_wait_for_register(dev_priv, MSVDX_MMU_MEM_REQ, 0,
+ 0xff);
+ if (ret)
+ return ret;
+ }
+ /* Issue software reset */
+ /* PSB_WMSVDX32(msvdx_sw_reset_all, MSVDX_CONTROL); */
+ PSB_WMSVDX32(MSVDX_CONTROL_CR_MSVDX_SOFT_RESET_MASK, MSVDX_CONTROL);
+
+ ret = psb_wait_for_register(dev_priv, MSVDX_CONTROL, 0,
+ MSVDX_CONTROL_CR_MSVDX_SOFT_RESET_MASK);
+
+ if (!ret) {
+ /* Clear interrupt enabled flag */
+ PSB_WMSVDX32(0, MSVDX_HOST_INTERRUPT_ENABLE);
+
+ /* Clear any pending interrupt flags */
+ PSB_WMSVDX32(0xFFFFFFFF, MSVDX_INTERRUPT_CLEAR);
+ }
+
+ /* mutex_destroy(&msvdx_priv->msvdx_mutex); */
+
+ return ret;
+}
+
+static int psb_allocate_ccb(struct drm_device *dev,
+ struct ttm_buffer_object **ccb,
+ uint32_t *base_addr, unsigned long size)
+{
+ struct drm_psb_private *dev_priv = psb_priv(dev);
+ struct ttm_bo_device *bdev = &dev_priv->bdev;
+ int ret;
+ struct ttm_bo_kmap_obj tmp_kmap;
+ bool is_iomem;
+
+ PSB_DEBUG_INIT("MSVDX: allocate CCB\n");
+
+ ret = ttm_buffer_object_create(bdev, size,
+ ttm_bo_type_kernel,
+ DRM_PSB_FLAG_MEM_MMU |
+ TTM_PL_FLAG_NO_EVICT, 0, 0, 0,
+ NULL, ccb);
+ if (ret) {
+ DRM_ERROR("MSVDX:failed to allocate CCB.\n");
+ *ccb = NULL;
+ return 1;
+ }
+
+ ret = ttm_bo_kmap(*ccb, 0, (*ccb)->num_pages, &tmp_kmap);
+ if (ret) {
+ PSB_DEBUG_GENERAL("ttm_bo_kmap failed ret: %d\n", ret);
+ ttm_bo_unref(ccb);
+ *ccb = NULL;
+ return 1;
+ }
+ /*
+ memset(ttm_kmap_obj_virtual(&tmp_kmap, &is_iomem), 0,
+ RENDEC_A_SIZE);
+ */
+ memset(ttm_kmap_obj_virtual(&tmp_kmap, &is_iomem), 0,
+ size);
+ ttm_bo_kunmap(&tmp_kmap);
+
+ *base_addr = (*ccb)->offset;
+ return 0;
+}
+
+static ssize_t psb_msvdx_pmstate_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct drm_device *drm_dev = dev_get_drvdata(dev);
+ struct drm_psb_private *dev_priv;
+ struct msvdx_private *msvdx_priv;
+ unsigned int pmstate;
+ unsigned long flags;
+ int ret = -EINVAL;
+
+ if (drm_dev == NULL)
+ return 0;
+
+ dev_priv = drm_dev->dev_private;
+ msvdx_priv = dev_priv->msvdx_private;
+ pmstate = msvdx_priv->pmstate;
+
+ spin_lock_irqsave(&msvdx_priv->msvdx_lock, flags);
+ ret = snprintf(buf, 64, "%s\n",
+ (pmstate == PSB_PMSTATE_POWERUP) ? "powerup"
+ : ((pmstate == PSB_PMSTATE_POWERDOWN) ? "powerdown"
+ : "clockgated"));
+ spin_unlock_irqrestore(&msvdx_priv->msvdx_lock, flags);
+
+ return ret;
+}
+
+static DEVICE_ATTR(msvdx_pmstate, 0444, psb_msvdx_pmstate_show, NULL);
+
+static void psb_msvdx_conceal_mb(char * ec_start, char * ref_start,
+ uint32_t start_err_mb, uint32_t end_err_mb,
+ uint32_t pic_width_mb, uint32_t stride,
+ uint32_t mb_width, uint32_t mb_height)
+{
+ int i, offset_start, offset_end, size, full_line_start, full_line_end, extra_line_start, extra_line_end;
+ char *src, *dst;
+
+ (void)offset_end;
+ (void)offset_start;
+
+ full_line_start = (start_err_mb / pic_width_mb) * stride * mb_height;
+ full_line_end = ((end_err_mb + 1) / pic_width_mb) * stride * mb_height;
+ extra_line_start = (start_err_mb % pic_width_mb) * mb_width;
+ extra_line_end = (end_err_mb + 1) % pic_width_mb * mb_width;
+ if (extra_line_start != 0) {
+ size = stride - extra_line_start;
+ src = ref_start + full_line_start + extra_line_start;
+ dst = ec_start + full_line_start + extra_line_start;
+ for (i = 0; i < mb_height; i++) {
+ memcpy(dst, src, size);
+ //memset(dst, 255, size);
+ src += stride;
+ dst += stride;
+ }
+ full_line_start += stride * mb_height;
+ }
+ src = ref_start + full_line_start;
+ dst = ec_start + full_line_start;
+ size = full_line_end - full_line_start;
+ memcpy(dst, src, size);
+ //memset(dst, 255, size);
+ if (extra_line_end != 0) {
+ size = extra_line_end;
+ src = ref_start + full_line_end;
+ dst = ec_start + full_line_end;
+ for (i = 0; i < mb_height; i++) {
+ memcpy(dst, src, size);
+ //memset(dst, 255, size);
+ src += stride;
+ dst += stride;
+ }
+ }
+}
+
+
+static void psb_msvdx_error_concealment(struct work_struct *data)
+{
+ uint32_t i;
+ int ret;
+ struct msvdx_private *msvdx_priv = container_of(data, struct msvdx_private, ec_work);
+ drm_psb_msvdx_frame_info_t *ec_frame = NULL;
+ drm_psb_msvdx_frame_info_t *ref_frame = NULL;
+ static struct ttm_bo_kmap_obj ec_kmap, ref_kmap;
+ struct ttm_buffer_object *ec_bo = NULL;
+ struct ttm_buffer_object *ref_bo = NULL;
+ struct ttm_object_file *tfile = msvdx_priv->tfile;
+ drm_psb_msvdx_decode_status_t *decode_status = NULL;
+ bool is_iomem;
+ char *ec_start, *ref_start;
+
+ if (msvdx_priv->ec_fence > 0)
+ msvdx_priv->ref_pic_fence = msvdx_priv->ec_fence - 1;
+ else {
+ DRM_ERROR("Can't do error concealment for the first frame.\n");
+ return;
+ }
+
+ /*get the frame_info struct for error concealment frame*/
+ for (i = 0; i < MAX_DECODE_BUFFERS; i++) {
+ if (msvdx_priv->frame_info[i].fence == msvdx_priv->ec_fence) {
+ ec_frame = &msvdx_priv->frame_info[i];
+ break;
+ }
+ }
+ if (!ec_frame) {
+ DRM_ERROR("MSVDX: didn't find frame_info which matched the ec fence\n");
+ return;
+ }
+ decode_status = &ec_frame->decode_status;
+ ec_bo = ttm_buffer_object_lookup(tfile, ec_frame->handle);
+ if (unlikely(ec_bo == NULL)) {
+ printk(KERN_ERR " : Could not find buffer object for setstatus.\n");
+ return;
+ }
+ ret = ttm_bo_reserve(ec_bo, true, true, false, 0);
+ if (ret) {
+ DRM_ERROR("MSVDX ERROR CONCEALMENT: reserver failed.\n");
+ return;
+ }
+ ret = ttm_bo_kmap(ec_bo,
+ 0,
+ (ec_frame->buffer_size +
+ PAGE_SIZE - 1) >> PAGE_SHIFT,
+ &ec_kmap);
+ if (ret) {
+ printk("MSVDX ERROR CONCEALMENT: ec kmap failed, %d.\n", ret);
+ return;
+ }
+ ec_start = (unsigned char *) ttm_kmap_obj_virtual(&ec_kmap,
+ &is_iomem);
+
+ /*get the frame_info struct for reference frame*/
+ for (i = 0; i < MAX_DECODE_BUFFERS; i++) {
+ if (msvdx_priv->frame_info[i].fence == msvdx_priv->ref_pic_fence) {
+ ref_frame = &msvdx_priv->frame_info[i];
+ break;
+ }
+ }
+ if (!ref_frame) {
+ DRM_ERROR("MSVDX: didn't find frame_info which matched the ref fence\n");
+ return;
+ }
+ ref_bo = ttm_buffer_object_lookup(tfile, ref_frame->handle);
+ if (unlikely(ref_bo == NULL)) {
+ printk(KERN_ERR " : Could not find buffer object for setstatus.\n");
+ }
+ ret = ttm_bo_reserve(ref_bo, true, true, false, 0);
+ if (ret) {
+ DRM_ERROR("MSVDX ERROR CONCEALMENT: reserver failed.\n");
+ return;
+ }
+ ret = ttm_bo_kmap(ref_bo,
+ 0,
+ (ref_frame->buffer_size +
+ PAGE_SIZE - 1) >> PAGE_SHIFT,
+ &ref_kmap);
+ if (ret) {
+ printk("MSVDX ERROR CONCEALMENT: ref kmap failed, %d.\n", ret);
+ return;
+ }
+ ref_start = (unsigned char *) ttm_kmap_obj_virtual(&ref_kmap,
+ &is_iomem);
+
+ /*copy missing mb from ref picture to ec picture*/
+ for (i = 0; i < decode_status->num_error_slice; i++) {
+ if ((decode_status->start_error_mb_list[i] >= ec_frame->size_mb) ||
+ (decode_status->end_error_mb_list[i] >= ec_frame->size_mb) ||
+ (decode_status->start_error_mb_list[i] > decode_status->end_error_mb_list[i]))
+ continue;
+ psb_msvdx_conceal_mb(ec_start, ref_start,
+ decode_status->start_error_mb_list[i],
+ decode_status->end_error_mb_list[i],
+ ec_frame->picture_width_mb, ec_frame->buffer_stride,
+ 16, 16);
+ psb_msvdx_conceal_mb(ec_start + ec_frame->buffer_size * 2 / 3,
+ ref_start + ec_frame->buffer_size * 2 / 3,
+ decode_status->start_error_mb_list[i],
+ decode_status->end_error_mb_list[i],
+ ec_frame->picture_width_mb, ec_frame->buffer_stride,
+ 16, 8);
+ }
+
+ ttm_bo_kunmap(&ec_kmap);
+ ttm_bo_kunmap(&ref_kmap);
+ ttm_bo_unreserve(ec_bo);
+ ttm_bo_unreserve(ref_bo);
+
+ if (ec_bo)
+ ttm_bo_unref(&ec_bo);
+ if (ref_bo)
+ ttm_bo_unref(&ref_bo);
+
+}
+
+int psb_msvdx_init(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ /* uint32_t clk_gate_ctrl = clk_enable_all; */
+ uint32_t cmd;
+ int ret;
+ struct msvdx_private *msvdx_priv;
+ /*
+ uint32_t reg_value;
+ uint32_t reg_val;
+ */
+ if (!dev_priv->msvdx_private) {
+ msvdx_priv = kmalloc(sizeof(struct msvdx_private), GFP_KERNEL);
+ if (msvdx_priv == NULL)
+ goto err_exit;
+
+ dev_priv->msvdx_private = msvdx_priv;
+ memset(msvdx_priv, 0, sizeof(struct msvdx_private));
+
+ /* get device --> drm_device --> drm_psb_private --> msvdx_priv
+ * for psb_msvdx_pmstate_show: msvdx_pmpolicy
+ * if not pci_set_drvdata, can't get drm_device from device
+ */
+ /* pci_set_drvdata(dev->pdev, dev); */
+ if (device_create_file(&dev->pdev->dev,
+ &dev_attr_msvdx_pmstate))
+ DRM_ERROR("MSVDX: could not create sysfs file\n");
+ msvdx_priv->sysfs_pmstate =
+ sysfs_get_dirent(dev->pdev->dev.kobj.sd,
+ NULL, "msvdx_pmstate");
+ }
+
+ msvdx_priv = dev_priv->msvdx_private;
+ if (!msvdx_priv->ccb0) { /* one for the first time */
+ /* Initialize comand msvdx queueing */
+ INIT_LIST_HEAD(&msvdx_priv->msvdx_queue);
+ INIT_LIST_HEAD(&msvdx_priv->deblock_queue);
+ mutex_init(&msvdx_priv->msvdx_mutex);
+ spin_lock_init(&msvdx_priv->msvdx_lock);
+ /*figure out the stepping */
+ pci_read_config_byte(dev->pdev, PSB_REVID_OFFSET, &psb_rev_id);
+ }
+
+ msvdx_priv->vec_local_mem_size = VEC_LOCAL_MEM_BYTE_SIZE;
+ if (!msvdx_priv->vec_local_mem_data) {
+ msvdx_priv->vec_local_mem_data =
+ kmalloc(msvdx_priv->vec_local_mem_size, GFP_KERNEL);
+ memset(msvdx_priv->vec_local_mem_data, 0, msvdx_priv->vec_local_mem_size);
+ }
+
+ msvdx_priv->msvdx_busy = 0;
+ msvdx_priv->msvdx_hw_busy = 1;
+
+ /* Enable Clocks */
+ PSB_DEBUG_GENERAL("Enabling clocks\n");
+ PSB_WMSVDX32(clk_enable_all, MSVDX_MAN_CLK_ENABLE);
+
+ /* Issue software reset for all but core*/
+ /*
+ PSB_WMSVDX32((uint32_t) ~MSVDX_CORE_CR_MSVDX_CONTROL_CR_MSVDX_SOFT_RESET_MASK, REGISTER(MSVDX_CORE, CR_MSVDX_CONTROL));
+ reg_value = PSB_RMSVDX32(REGISTER(MSVDX_CORE, CR_MSVDX_CONTROL));
+ PSB_WMSVDX32(0, REGISTER(MSVDX_CORE, CR_MSVDX_CONTROL));
+ PSB_WMSVDX32(MSVDX_CORE_CR_MSVDX_CONTROL_CR_MSVDX_SOFT_RESET_MASK, REGISTER(MSVDX_CORE, CR_MSVDX_CONTROL));
+
+ reg_val = 0;
+ REGIO_WRITE_FIELD(reg_val, MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL, FE_WDT_CNT_CTRL, 0x3);
+ REGIO_WRITE_FIELD(reg_val, MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL, FE_WDT_ENABLE, 0);
+ REGIO_WRITE_FIELD(reg_val, MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL, FE_WDT_ACTION0, 1);
+ REGIO_WRITE_FIELD(reg_val, MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL, FE_WDT_CLEAR_SELECT, 1);
+ REGIO_WRITE_FIELD(reg_val, MSVDX_CORE_CR_FE_MSVDX_WDT_CONTROL, FE_WDT_CLKDIV_SELECT, 7);
+ PSB_WMSVDX32(820, REGISTER( MSVDX_CORE, CR_FE_MSVDX_WDT_COMPAREMATCH ));
+ PSB_WMSVDX32(reg_val, REGISTER( MSVDX_CORE, CR_FE_MSVDX_WDT_CONTROL ));
+
+ reg_val = 0;
+ REGIO_WRITE_FIELD(reg_val, MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL, BE_WDT_CNT_CTRL, 0x7);
+ REGIO_WRITE_FIELD(reg_val, MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL, BE_WDT_ENABLE, 0);
+ REGIO_WRITE_FIELD(reg_val, MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL, BE_WDT_ACTION0, 1);
+ REGIO_WRITE_FIELD(reg_val, MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL, BE_WDT_CLEAR_SELECT, 0xd);
+ REGIO_WRITE_FIELD(reg_val, MSVDX_CORE_CR_BE_MSVDX_WDT_CONTROL, BE_WDT_CLKDIV_SELECT, 7);
+ PSB_WMSVDX32(8200, REGISTER(MSVDX_CORE, CR_BE_MSVDX_WDT_COMPAREMATCH));
+ PSB_WMSVDX32(reg_val, REGISTER(MSVDX_CORE, CR_BE_MSVDX_WDT_CONTROL));
+ */
+ /* Enable MMU by removing all bypass bits */
+ PSB_WMSVDX32(0, MSVDX_MMU_CONTROL0);
+
+ /* move firmware loading to the place receiving first command buffer */
+
+ PSB_DEBUG_GENERAL("MSVDX: Setting up RENDEC,allocate CCB 0/1\n");
+ /* Allocate device virtual memory as required by rendec.... */
+ if (!msvdx_priv->ccb0) {
+ ret = psb_allocate_ccb(dev, &msvdx_priv->ccb0,
+ &msvdx_priv->base_addr0,
+ RENDEC_A_SIZE);
+ if (ret) {
+ PSB_DEBUG_GENERAL("Allocate Rendec A fail\n");
+ goto err_exit;
+ }
+ }
+
+ if (!msvdx_priv->ccb1) {
+ ret = psb_allocate_ccb(dev, &msvdx_priv->ccb1,
+ &msvdx_priv->base_addr1,
+ RENDEC_B_SIZE);
+ if (ret)
+ goto err_exit;
+ }
+
+ if (!msvdx_priv->fw) {
+ uint32_t core_rev;
+ uint32_t fw_bo_size;
+
+ core_rev = PSB_RMSVDX32(MSVDX_CORE_REV);
+
+ if ((core_rev & 0xffffff) < 0x020000)
+ msvdx_priv->mtx_mem_size = 16 * 1024;
+ else
+ msvdx_priv->mtx_mem_size = 40 * 1024;
+
+ fw_bo_size = msvdx_priv->mtx_mem_size + 4096;
+
+ PSB_DEBUG_INIT("MSVDX: MTX mem size is 0x%08xbytes allocate firmware BO size 0x%08x\n", msvdx_priv->mtx_mem_size,
+ fw_bo_size);
+
+ ret = ttm_buffer_object_create(&dev_priv->bdev, fw_bo_size, /* DMA may run over a page */
+ ttm_bo_type_kernel,
+ DRM_PSB_FLAG_MEM_MMU | TTM_PL_FLAG_NO_EVICT,
+ 0, 0, 0, NULL, &msvdx_priv->fw);
+
+ if (ret) {
+ PSB_DEBUG_GENERAL("Allocate firmware BO fail\n");
+ goto err_exit;
+ }
+ }
+
+ PSB_DEBUG_GENERAL("MSVDX: RENDEC A: %08x RENDEC B: %08x\n",
+ msvdx_priv->base_addr0, msvdx_priv->base_addr1);
+
+ PSB_WMSVDX32(msvdx_priv->base_addr0, MSVDX_RENDEC_BASE_ADDR0);
+ PSB_WMSVDX32(msvdx_priv->base_addr1, MSVDX_RENDEC_BASE_ADDR1);
+
+ cmd = 0;
+ REGIO_WRITE_FIELD(cmd, MSVDX_RENDEC_BUFFER_SIZE,
+ RENDEC_BUFFER_SIZE0, RENDEC_A_SIZE / 4096);
+ REGIO_WRITE_FIELD(cmd, MSVDX_RENDEC_BUFFER_SIZE,
+ RENDEC_BUFFER_SIZE1, RENDEC_B_SIZE / 4096);
+ PSB_WMSVDX32(cmd, MSVDX_RENDEC_BUFFER_SIZE);
+
+ if (!msvdx_priv->fw) {
+ uint32_t core_rev;
+
+ core_rev = PSB_RMSVDX32(MSVDX_CORE_REV);
+
+ if ((core_rev & 0xffffff) < 0x020000)
+ msvdx_priv->mtx_mem_size = 16 * 1024;
+ else
+ msvdx_priv->mtx_mem_size = 40 * 1024;
+
+ PSB_DEBUG_INIT("MSVDX: MTX mem size is 0x%08xbytes allocate firmware BO size 0x%08x\n", msvdx_priv->mtx_mem_size,
+ msvdx_priv->mtx_mem_size + 4096);
+
+ ret = ttm_buffer_object_create(&dev_priv->bdev, msvdx_priv->mtx_mem_size + 4096, /* DMA may run over a page */
+ ttm_bo_type_kernel,
+ DRM_PSB_FLAG_MEM_MMU | TTM_PL_FLAG_NO_EVICT,
+ 0, 0, 0, NULL, &msvdx_priv->fw);
+
+ if (ret) {
+ PSB_DEBUG_GENERAL("Allocate firmware BO fail\n");
+ goto err_exit;
+ }
+ }
+
+ cmd = 0;
+ REGIO_WRITE_FIELD(cmd, MSVDX_RENDEC_CONTROL1,
+ RENDEC_DECODE_START_SIZE, 0);
+ REGIO_WRITE_FIELD(cmd, MSVDX_RENDEC_CONTROL1,
+ RENDEC_BURST_SIZE_W, 1);
+ REGIO_WRITE_FIELD(cmd, MSVDX_RENDEC_CONTROL1,
+ RENDEC_BURST_SIZE_R, 1);
+ REGIO_WRITE_FIELD(cmd, MSVDX_RENDEC_CONTROL1,
+ RENDEC_EXTERNAL_MEMORY, 1);
+ PSB_WMSVDX32(cmd, MSVDX_RENDEC_CONTROL1);
+
+ cmd = 0x00101010;
+ PSB_WMSVDX32(cmd, MSVDX_RENDEC_CONTEXT0);
+ PSB_WMSVDX32(cmd, MSVDX_RENDEC_CONTEXT1);
+ PSB_WMSVDX32(cmd, MSVDX_RENDEC_CONTEXT2);
+ PSB_WMSVDX32(cmd, MSVDX_RENDEC_CONTEXT3);
+ PSB_WMSVDX32(cmd, MSVDX_RENDEC_CONTEXT4);
+ PSB_WMSVDX32(cmd, MSVDX_RENDEC_CONTEXT5);
+
+ cmd = 0;
+ REGIO_WRITE_FIELD(cmd, MSVDX_RENDEC_CONTROL0, RENDEC_INITIALISE,
+ 1);
+ PSB_WMSVDX32(cmd, MSVDX_RENDEC_CONTROL0);
+
+ /* PSB_WMSVDX32(clk_enable_minimal, MSVDX_MAN_CLK_ENABLE); */
+ PSB_DEBUG_INIT("MSVDX:defer firmware loading to the"
+ " place when receiving user space commands\n");
+
+ msvdx_priv->msvdx_fw_loaded = 0; /* need to load firware */
+
+ PSB_WMSVDX32(820, MSVDX_CORE_CR_FE_MSVDX_WDT_COMPAREMATCH);
+ PSB_WMSVDX32(8200, MSVDX_CORE_CR_BE_MSVDX_WDT_COMPAREMATCH);
+
+ PSB_WMSVDX32(820, MSVDX_CORE_CR_FE_MSVDX_WDT_COMPAREMATCH);
+ PSB_WMSVDX32(8200, MSVDX_CORE_CR_BE_MSVDX_WDT_COMPAREMATCH);
+
+ psb_msvdx_clearirq(dev);
+ psb_msvdx_enableirq(dev);
+
+ PSB_DEBUG_INIT("MSDVX:old clock gating disable = 0x%08x\n",
+ PSB_RVDC32(PSB_MSVDX_CLOCKGATING));
+
+ {
+ cmd = 0;
+ cmd = PSB_RMSVDX32(MSVDX_VEC_SHIFTREG_CONTROL); /* VEC_SHIFTREG_CONTROL */
+ REGIO_WRITE_FIELD(cmd,
+ VEC_SHIFTREG_CONTROL,
+ SR_MASTER_SELECT,
+ 1); /* Host */
+ PSB_WMSVDX32(cmd, MSVDX_VEC_SHIFTREG_CONTROL);
+ }
+
+#if 0
+ ret = psb_setup_fw(dev);
+ if (ret)
+ goto err_exit;
+ /* Send Initialisation message to firmware */
+ if (0) {
+ uint32_t msg_init[FW_VA_INIT_SIZE >> 2];
+ MEMIO_WRITE_FIELD(msg_init, FWRK_GENMSG_SIZE,
+ FW_VA_INIT_SIZE);
+ MEMIO_WRITE_FIELD(msg_init, FWRK_GENMSG_ID, VA_MSGID_INIT);
+
+ /* Need to set this for all but A0 */
+ MEMIO_WRITE_FIELD(msg_init, FW_VA_INIT_GLOBAL_PTD,
+ psb_get_default_pd_addr(dev_priv->mmu));
+
+ ret = psb_mtx_send(dev_priv, msg_init);
+ if (ret)
+ goto err_exit;
+
+ psb_poll_mtx_irq(dev_priv);
+ }
+#endif
+
+ return 0;
+
+err_exit:
+ DRM_ERROR("MSVDX: initialization failed\n");
+ if (msvdx_priv && msvdx_priv->ccb0)
+ psb_free_ccb(&msvdx_priv->ccb0);
+ if (msvdx_priv && msvdx_priv->ccb1)
+ psb_free_ccb(&msvdx_priv->ccb1);
+ kfree(dev_priv->msvdx_private);
+
+ return 1;
+}
+
+int psb_msvdx_uninit(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct msvdx_private *msvdx_priv = dev_priv->msvdx_private;
+
+ /* Reset MSVDX chip */
+ psb_msvdx_reset(dev_priv);
+
+ /* PSB_WMSVDX32 (clk_enable_minimal, MSVDX_MAN_CLK_ENABLE); */
+ PSB_DEBUG_INIT("MSVDX:set the msvdx clock to 0\n");
+ PSB_WMSVDX32(0, MSVDX_MAN_CLK_ENABLE);
+
+ if (NULL == msvdx_priv) {
+ DRM_ERROR("MSVDX: psb_msvdx_uninit: msvdx_priv is NULL!\n");
+ return -1;
+ }
+
+ if (msvdx_priv->ccb0)
+ psb_free_ccb(&msvdx_priv->ccb0);
+ if (msvdx_priv->ccb1)
+ psb_free_ccb(&msvdx_priv->ccb1);
+ if (msvdx_priv->msvdx_fw)
+ kfree(msvdx_priv->msvdx_fw
+ );
+ if (msvdx_priv->vec_local_mem_data)
+ kfree(msvdx_priv->vec_local_mem_data);
+
+ if (msvdx_priv) {
+ /* pci_set_drvdata(dev->pdev, NULL); */
+ device_remove_file(&dev->pdev->dev, &dev_attr_msvdx_pmstate);
+ sysfs_put(msvdx_priv->sysfs_pmstate);
+ msvdx_priv->sysfs_pmstate = NULL;
+
+ kfree(msvdx_priv);
+ dev_priv->msvdx_private = NULL;
+ }
+
+ return 0;
+}
--- /dev/null
+/**************************************************************************
+ *
+ * Copyright (c) 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA
+ * All Rights Reserved.
+ * Copyright (c) 2009 VMware, Inc., Palo Alto, CA., USA
+ * 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 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.
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
+ */
+
+#include "psb_ttm_fence_api.h"
+#include "psb_ttm_fence_driver.h"
+#include <linux/wait.h>
+#include <linux/sched.h>
+
+#include <drm/drmP.h>
+
+/*
+ * Simple implementation for now.
+ */
+
+static void ttm_fence_lockup(struct ttm_fence_object *fence, uint32_t mask)
+{
+ struct ttm_fence_class_manager *fc = ttm_fence_fc(fence);
+
+ printk(KERN_ERR "GPU lockup dectected on engine %u "
+ "fence type 0x%08x\n",
+ (unsigned int)fence->fence_class, (unsigned int)mask);
+ /*
+ * Give engines some time to idle?
+ */
+
+ write_lock(&fc->lock);
+ ttm_fence_handler(fence->fdev, fence->fence_class,
+ fence->sequence, mask, -EBUSY);
+ write_unlock(&fc->lock);
+}
+
+/*
+ * Convenience function to be called by fence::wait methods that
+ * need polling.
+ */
+
+static int ttm_fence_wait_polling(struct ttm_fence_object *fence, bool lazy,
+ bool interruptible, uint32_t mask)
+{
+ struct ttm_fence_class_manager *fc = ttm_fence_fc(fence);
+ const struct ttm_fence_driver *driver = ttm_fence_driver(fence);
+ uint32_t count = 0;
+ int ret;
+ unsigned long end_jiffies = fence->timeout_jiffies;
+
+ DECLARE_WAITQUEUE(entry, current);
+ add_wait_queue(&fc->fence_queue, &entry);
+
+ ret = 0;
+
+ for (;;) {
+ __set_current_state((interruptible) ?
+ TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
+ if (ttm_fence_object_signaled(fence, mask))
+ break;
+ if (time_after_eq(jiffies, end_jiffies)) {
+ if (driver->lockup)
+ driver->lockup(fence, mask);
+ else
+ ttm_fence_lockup(fence, mask);
+ continue;
+ }
+ if (lazy)
+ schedule_timeout(1);
+ else if ((++count & 0x0F) == 0) {
+ __set_current_state(TASK_RUNNING);
+ schedule();
+ __set_current_state((interruptible) ?
+ TASK_INTERRUPTIBLE :
+ TASK_UNINTERRUPTIBLE);
+ }
+ if (interruptible && signal_pending(current)) {
+ ret = -ERESTART;
+ break;
+ }
+ }
+ __set_current_state(TASK_RUNNING);
+ remove_wait_queue(&fc->fence_queue, &entry);
+ return ret;
+}
+
+/*
+ * Typically called by the IRQ handler.
+ */
+
+void ttm_fence_handler(struct ttm_fence_device *fdev, uint32_t fence_class,
+ uint32_t sequence, uint32_t type, uint32_t error)
+{
+ int wake = 0;
+ uint32_t diff;
+ uint32_t relevant_type;
+ uint32_t new_type;
+ struct ttm_fence_class_manager *fc = &fdev->fence_class[fence_class];
+ const struct ttm_fence_driver *driver = ttm_fence_driver_from_dev(fdev);
+ struct list_head *head;
+ struct ttm_fence_object *fence, *next;
+ bool found = false;
+
+ if (list_empty(&fc->ring))
+ return;
+
+ list_for_each_entry(fence, &fc->ring, ring) {
+ diff = (sequence - fence->sequence) & fc->sequence_mask;
+ if (diff > fc->wrap_diff) {
+ found = true;
+ break;
+ }
+ }
+
+ fc->waiting_types &= ~type;
+ head = (found) ? &fence->ring : &fc->ring;
+
+ list_for_each_entry_safe_reverse(fence, next, head, ring) {
+ if (&fence->ring == &fc->ring)
+ break;
+
+ DRM_DEBUG("Fence 0x%08lx, sequence 0x%08x, type 0x%08x\n",
+ (unsigned long)fence, fence->sequence,
+ fence->fence_type);
+
+ if (error) {
+ fence->info.error = error;
+ fence->info.signaled_types = fence->fence_type;
+ list_del_init(&fence->ring);
+ wake = 1;
+ break;
+ }
+
+ relevant_type = type & fence->fence_type;
+ new_type = (fence->info.signaled_types | relevant_type) ^
+ fence->info.signaled_types;
+
+ if (new_type) {
+ fence->info.signaled_types |= new_type;
+ DRM_DEBUG("Fence 0x%08lx signaled 0x%08x\n",
+ (unsigned long)fence,
+ fence->info.signaled_types);
+
+ if (unlikely(driver->signaled))
+ driver->signaled(fence);
+
+ if (driver->needed_flush)
+ fc->pending_flush |=
+ driver->needed_flush(fence);
+
+ if (new_type & fence->waiting_types)
+ wake = 1;
+ }
+
+ fc->waiting_types |=
+ fence->waiting_types & ~fence->info.signaled_types;
+
+ if (!(fence->fence_type & ~fence->info.signaled_types)) {
+ DRM_DEBUG("Fence completely signaled 0x%08lx\n",
+ (unsigned long)fence);
+ list_del_init(&fence->ring);
+ }
+ }
+
+ /*
+ * Reinstate lost waiting types.
+ */
+
+ if ((fc->waiting_types & type) != type) {
+ head = head->prev;
+ list_for_each_entry(fence, head, ring) {
+ if (&fence->ring == &fc->ring)
+ break;
+ diff =
+ (fc->highest_waiting_sequence -
+ fence->sequence) & fc->sequence_mask;
+ if (diff > fc->wrap_diff)
+ break;
+
+ fc->waiting_types |=
+ fence->waiting_types & ~fence->info.signaled_types;
+ }
+ }
+
+ if (wake)
+ wake_up_all(&fc->fence_queue);
+}
+
+static void ttm_fence_unring(struct ttm_fence_object *fence)
+{
+ struct ttm_fence_class_manager *fc = ttm_fence_fc(fence);
+ unsigned long irq_flags;
+
+ write_lock_irqsave(&fc->lock, irq_flags);
+ list_del_init(&fence->ring);
+ write_unlock_irqrestore(&fc->lock, irq_flags);
+}
+
+bool ttm_fence_object_signaled(struct ttm_fence_object *fence, uint32_t mask)
+{
+ unsigned long flags;
+ bool signaled;
+ const struct ttm_fence_driver *driver = ttm_fence_driver(fence);
+ struct ttm_fence_class_manager *fc = ttm_fence_fc(fence);
+
+ mask &= fence->fence_type;
+ read_lock_irqsave(&fc->lock, flags);
+ signaled = (mask & fence->info.signaled_types) == mask;
+ read_unlock_irqrestore(&fc->lock, flags);
+ if (!signaled && driver->poll) {
+ write_lock_irqsave(&fc->lock, flags);
+ driver->poll(fence->fdev, fence->fence_class, mask);
+ signaled = (mask & fence->info.signaled_types) == mask;
+ write_unlock_irqrestore(&fc->lock, flags);
+ }
+ return signaled;
+}
+
+int ttm_fence_object_flush(struct ttm_fence_object *fence, uint32_t type)
+{
+ const struct ttm_fence_driver *driver = ttm_fence_driver(fence);
+ struct ttm_fence_class_manager *fc = ttm_fence_fc(fence);
+ unsigned long irq_flags;
+ uint32_t saved_pending_flush;
+ uint32_t diff;
+ bool call_flush;
+
+ if (type & ~fence->fence_type) {
+ DRM_ERROR("Flush trying to extend fence type, "
+ "0x%x, 0x%x\n", type, fence->fence_type);
+ return -EINVAL;
+ }
+
+ write_lock_irqsave(&fc->lock, irq_flags);
+ fence->waiting_types |= type;
+ fc->waiting_types |= fence->waiting_types;
+ diff = (fence->sequence - fc->highest_waiting_sequence) &
+ fc->sequence_mask;
+
+ if (diff < fc->wrap_diff)
+ fc->highest_waiting_sequence = fence->sequence;
+
+ /*
+ * fence->waiting_types has changed. Determine whether
+ * we need to initiate some kind of flush as a result of this.
+ */
+
+ saved_pending_flush = fc->pending_flush;
+ if (driver->needed_flush)
+ fc->pending_flush |= driver->needed_flush(fence);
+
+ if (driver->poll)
+ driver->poll(fence->fdev, fence->fence_class,
+ fence->waiting_types);
+
+ call_flush = (fc->pending_flush != 0);
+ write_unlock_irqrestore(&fc->lock, irq_flags);
+
+ if (call_flush && driver->flush)
+ driver->flush(fence->fdev, fence->fence_class);
+
+ return 0;
+}
+
+/*
+ * Make sure old fence objects are signaled before their fence sequences are
+ * wrapped around and reused.
+ */
+
+static void ttm_fence_flush_old(struct ttm_fence_device *fdev,
+ uint32_t fence_class, uint32_t sequence)
+{
+ struct ttm_fence_class_manager *fc = &fdev->fence_class[fence_class];
+ struct ttm_fence_object *fence;
+ unsigned long irq_flags;
+ const struct ttm_fence_driver *driver = fdev->driver;
+ bool call_flush;
+
+ uint32_t diff;
+
+ write_lock_irqsave(&fc->lock, irq_flags);
+
+ list_for_each_entry_reverse(fence, &fc->ring, ring) {
+ diff = (sequence - fence->sequence) & fc->sequence_mask;
+ if (diff <= fc->flush_diff)
+ break;
+
+ fence->waiting_types = fence->fence_type;
+ fc->waiting_types |= fence->fence_type;
+
+ if (driver->needed_flush)
+ fc->pending_flush |= driver->needed_flush(fence);
+ }
+
+ if (driver->poll)
+ driver->poll(fdev, fence_class, fc->waiting_types);
+
+ call_flush = (fc->pending_flush != 0);
+ write_unlock_irqrestore(&fc->lock, irq_flags);
+
+ if (call_flush && driver->flush)
+ driver->flush(fdev, fence->fence_class);
+
+ /*
+ * FIXME: Shold we implement a wait here for really old fences?
+ */
+
+}
+
+int ttm_fence_object_wait(struct ttm_fence_object *fence,
+ bool lazy, bool interruptible, uint32_t mask)
+{
+ const struct ttm_fence_driver *driver = ttm_fence_driver(fence);
+ struct ttm_fence_class_manager *fc = ttm_fence_fc(fence);
+ int ret = 0;
+ unsigned long timeout;
+ unsigned long cur_jiffies;
+ unsigned long to_jiffies;
+
+ if (mask & ~fence->fence_type) {
+ DRM_ERROR("Wait trying to extend fence type"
+ " 0x%08x 0x%08x\n", mask, fence->fence_type);
+ BUG();
+ return -EINVAL;
+ }
+
+ if (driver->wait)
+ return driver->wait(fence, lazy, interruptible, mask);
+
+ ttm_fence_object_flush(fence, mask);
+retry:
+ if (!driver->has_irq ||
+ driver->has_irq(fence->fdev, fence->fence_class, mask)) {
+
+ cur_jiffies = jiffies;
+ to_jiffies = fence->timeout_jiffies;
+
+ timeout = (time_after(to_jiffies, cur_jiffies)) ?
+ to_jiffies - cur_jiffies : 1;
+
+ if (interruptible)
+ ret = wait_event_interruptible_timeout
+ (fc->fence_queue,
+ ttm_fence_object_signaled(fence, mask), timeout);
+ else
+ ret = wait_event_timeout
+ (fc->fence_queue,
+ ttm_fence_object_signaled(fence, mask), timeout);
+
+ if (unlikely(ret == -ERESTARTSYS))
+ return -ERESTART;
+
+ if (unlikely(ret == 0)) {
+ if (driver->lockup)
+ driver->lockup(fence, mask);
+ else
+ ttm_fence_lockup(fence, mask);
+ goto retry;
+ }
+
+ return 0;
+ }
+
+ return ttm_fence_wait_polling(fence, lazy, interruptible, mask);
+}
+
+static int ttm_fence_object_emit(struct ttm_fence_object *fence, uint32_t fence_flags,
+ uint32_t fence_class, uint32_t type)
+{
+ const struct ttm_fence_driver *driver = ttm_fence_driver(fence);
+ struct ttm_fence_class_manager *fc = ttm_fence_fc(fence);
+ unsigned long flags;
+ uint32_t sequence;
+ unsigned long timeout;
+ int ret;
+
+ ttm_fence_unring(fence);
+ ret = driver->emit(fence->fdev,
+ fence_class, fence_flags, &sequence, &timeout);
+ if (ret)
+ return ret;
+
+ write_lock_irqsave(&fc->lock, flags);
+ fence->fence_class = fence_class;
+ fence->fence_type = type;
+ fence->waiting_types = 0;
+ fence->info.signaled_types = 0;
+ fence->info.error = 0;
+ fence->sequence = sequence;
+ fence->timeout_jiffies = timeout;
+ if (list_empty(&fc->ring))
+ fc->highest_waiting_sequence = sequence - 1;
+ list_add_tail(&fence->ring, &fc->ring);
+ fc->latest_queued_sequence = sequence;
+ write_unlock_irqrestore(&fc->lock, flags);
+ return 0;
+}
+
+int ttm_fence_object_init(struct ttm_fence_device *fdev,
+ uint32_t fence_class,
+ uint32_t type,
+ uint32_t create_flags,
+ void (*destroy)(struct ttm_fence_object *),
+ struct ttm_fence_object *fence)
+{
+ int ret = 0;
+
+ kref_init(&fence->kref);
+ fence->fence_class = fence_class;
+ fence->fence_type = type;
+ fence->info.signaled_types = 0;
+ fence->waiting_types = 0;
+ fence->sequence = 0;
+ fence->info.error = 0;
+ fence->fdev = fdev;
+ fence->destroy = destroy;
+ INIT_LIST_HEAD(&fence->ring);
+ atomic_inc(&fdev->count);
+
+ if (create_flags & TTM_FENCE_FLAG_EMIT) {
+ ret = ttm_fence_object_emit(fence, create_flags,
+ fence->fence_class, type);
+ }
+
+ return ret;
+}
+
+int ttm_fence_object_create(struct ttm_fence_device *fdev,
+ uint32_t fence_class,
+ uint32_t type,
+ uint32_t create_flags,
+ struct ttm_fence_object **c_fence)
+{
+ struct ttm_fence_object *fence;
+ int ret;
+
+ ret = ttm_mem_global_alloc(fdev->mem_glob,
+ sizeof(*fence),
+ false,
+ false);
+ if (unlikely(ret != 0)) {
+ printk(KERN_ERR "Out of memory creating fence object\n");
+ return ret;
+ }
+
+ fence = kmalloc(sizeof(*fence), GFP_KERNEL);
+ if (!fence) {
+ printk(KERN_ERR "Out of memory creating fence object\n");
+ ttm_mem_global_free(fdev->mem_glob, sizeof(*fence));
+ return -ENOMEM;
+ }
+
+ ret = ttm_fence_object_init(fdev, fence_class, type,
+ create_flags, NULL, fence);
+ if (ret) {
+ ttm_fence_object_unref(&fence);
+ return ret;
+ }
+ *c_fence = fence;
+
+ return 0;
+}
+
+static void ttm_fence_object_destroy(struct kref *kref)
+{
+ struct ttm_fence_object *fence =
+ container_of(kref, struct ttm_fence_object, kref);
+ struct ttm_fence_class_manager *fc = ttm_fence_fc(fence);
+ unsigned long irq_flags;
+
+ write_lock_irqsave(&fc->lock, irq_flags);
+ list_del_init(&fence->ring);
+ write_unlock_irqrestore(&fc->lock, irq_flags);
+
+ atomic_dec(&fence->fdev->count);
+ if (fence->destroy)
+ fence->destroy(fence);
+ else {
+ ttm_mem_global_free(fence->fdev->mem_glob,
+ sizeof(*fence));
+ kfree(fence);
+ }
+}
+
+void ttm_fence_device_release(struct ttm_fence_device *fdev)
+{
+ kfree(fdev->fence_class);
+}
+
+int
+ttm_fence_device_init(int num_classes,
+ struct ttm_mem_global *mem_glob,
+ struct ttm_fence_device *fdev,
+ const struct ttm_fence_class_init *init,
+ bool replicate_init,
+ const struct ttm_fence_driver *driver)
+{
+ struct ttm_fence_class_manager *fc;
+ const struct ttm_fence_class_init *fci;
+ int i;
+
+ fdev->mem_glob = mem_glob;
+ fdev->fence_class = kzalloc(num_classes *
+ sizeof(*fdev->fence_class), GFP_KERNEL);
+
+ if (unlikely(!fdev->fence_class))
+ return -ENOMEM;
+
+ fdev->num_classes = num_classes;
+ atomic_set(&fdev->count, 0);
+ fdev->driver = driver;
+
+ for (i = 0; i < fdev->num_classes; ++i) {
+ fc = &fdev->fence_class[i];
+ fci = &init[(replicate_init) ? 0 : i];
+
+ fc->wrap_diff = fci->wrap_diff;
+ fc->flush_diff = fci->flush_diff;
+ fc->sequence_mask = fci->sequence_mask;
+
+ rwlock_init(&fc->lock);
+ INIT_LIST_HEAD(&fc->ring);
+ init_waitqueue_head(&fc->fence_queue);
+ }
+
+ return 0;
+}
+
+struct ttm_fence_info ttm_fence_get_info(struct ttm_fence_object *fence) {
+ struct ttm_fence_class_manager *fc = ttm_fence_fc(fence);
+ struct ttm_fence_info tmp;
+ unsigned long irq_flags;
+
+ read_lock_irqsave(&fc->lock, irq_flags);
+ tmp = fence->info;
+ read_unlock_irqrestore(&fc->lock, irq_flags);
+
+ return tmp;
+}
+
+void ttm_fence_object_unref(struct ttm_fence_object **p_fence)
+{
+ struct ttm_fence_object *fence = *p_fence;
+
+ *p_fence = NULL;
+ (void)kref_put(&fence->kref, &ttm_fence_object_destroy);
+}
+
+/*
+ * Placement / BO sync object glue.
+ */
+
+bool ttm_fence_sync_obj_signaled(void *sync_obj, void *sync_arg)
+{
+ struct ttm_fence_object *fence = (struct ttm_fence_object *)sync_obj;
+ uint32_t fence_types = (uint32_t)(unsigned long)sync_arg;
+
+ return ttm_fence_object_signaled(fence, fence_types);
+}
+
+int ttm_fence_sync_obj_wait(void *sync_obj, void *sync_arg,
+ bool lazy, bool interruptible)
+{
+ struct ttm_fence_object *fence = (struct ttm_fence_object *)sync_obj;
+ uint32_t fence_types = (uint32_t)(unsigned long)sync_arg;
+
+ return ttm_fence_object_wait(fence, lazy, interruptible, fence_types);
+}
+
+int ttm_fence_sync_obj_flush(void *sync_obj, void *sync_arg)
+{
+ struct ttm_fence_object *fence = (struct ttm_fence_object *)sync_obj;
+ uint32_t fence_types = (uint32_t)(unsigned long)sync_arg;
+
+ return ttm_fence_object_flush(fence, fence_types);
+}
+
+void ttm_fence_sync_obj_unref(void **sync_obj)
+{
+ ttm_fence_object_unref((struct ttm_fence_object **)sync_obj);
+}
+
+void *ttm_fence_sync_obj_ref(void *sync_obj)
+{
+ return (void *)
+ ttm_fence_object_ref((struct ttm_fence_object *)sync_obj);
+}
--- /dev/null
+/**************************************************************************
+ *
+ * Copyright (c) 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA
+ * All Rights Reserved.
+ * Copyright (c) 2009 VMware, Inc., Palo Alto, CA., USA
+ * 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 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.
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
+ */
+#ifndef _TTM_FENCE_API_H_
+#define _TTM_FENCE_API_H_
+
+#include <linux/list.h>
+#include <linux/kref.h>
+
+#define TTM_FENCE_FLAG_EMIT (1 << 0)
+#define TTM_FENCE_TYPE_EXE (1 << 0)
+
+struct ttm_fence_device;
+
+/**
+ * struct ttm_fence_info
+ *
+ * @fence_class: The fence class.
+ * @fence_type: Bitfield indicating types for this fence.
+ * @signaled_types: Bitfield indicating which types are signaled.
+ * @error: Last error reported from the device.
+ *
+ * Used as output from the ttm_fence_get_info
+ */
+
+struct ttm_fence_info {
+ uint32_t signaled_types;
+ uint32_t error;
+};
+
+/**
+ * struct ttm_fence_object
+ *
+ * @fdev: Pointer to the fence device struct.
+ * @kref: Holds the reference count of this fence object.
+ * @ring: List head used for the circular list of not-completely
+ * signaled fences.
+ * @info: Data for fast retrieval using the ttm_fence_get_info()
+ * function.
+ * @timeout_jiffies: Absolute jiffies value indicating when this fence
+ * object times out and, if waited on, calls ttm_fence_lockup
+ * to check for and resolve a GPU lockup.
+ * @sequence: Fence sequence number.
+ * @waiting_types: Types currently waited on.
+ * @destroy: Called to free the fence object, when its refcount has
+ * reached zero. If NULL, kfree is used.
+ *
+ * This struct is provided in the driver interface so that drivers can
+ * derive from it and create their own fence implementation. All members
+ * are private to the fence implementation and the fence driver callbacks.
+ * Otherwise a driver may access the derived object using container_of().
+ */
+
+struct ttm_fence_object {
+ struct ttm_fence_device *fdev;
+ struct kref kref;
+ uint32_t fence_class;
+ uint32_t fence_type;
+
+ /*
+ * The below fields are protected by the fence class
+ * manager spinlock.
+ */
+
+ struct list_head ring;
+ struct ttm_fence_info info;
+ unsigned long timeout_jiffies;
+ uint32_t sequence;
+ uint32_t waiting_types;
+ void (*destroy)(struct ttm_fence_object *);
+};
+
+/**
+ * ttm_fence_object_init
+ *
+ * @fdev: Pointer to a struct ttm_fence_device.
+ * @fence_class: Fence class for this fence.
+ * @type: Fence type for this fence.
+ * @create_flags: Flags indicating varios actions at init time. At this point
+ * there's only TTM_FENCE_FLAG_EMIT, which triggers a sequence emission to
+ * the command stream.
+ * @destroy: Destroy function. If NULL, kfree() is used.
+ * @fence: The struct ttm_fence_object to initialize.
+ *
+ * Initialize a pre-allocated fence object. This function, together with the
+ * destroy function makes it possible to derive driver-specific fence objects.
+ */
+
+extern int
+ttm_fence_object_init(struct ttm_fence_device *fdev,
+ uint32_t fence_class,
+ uint32_t type,
+ uint32_t create_flags,
+ void (*destroy)(struct ttm_fence_object *fence),
+ struct ttm_fence_object *fence);
+
+/**
+ * ttm_fence_object_create
+ *
+ * @fdev: Pointer to a struct ttm_fence_device.
+ * @fence_class: Fence class for this fence.
+ * @type: Fence type for this fence.
+ * @create_flags: Flags indicating varios actions at init time. At this point
+ * there's only TTM_FENCE_FLAG_EMIT, which triggers a sequence emission to
+ * the command stream.
+ * @c_fence: On successful termination, *(@c_fence) will point to the created
+ * fence object.
+ *
+ * Create and initialize a struct ttm_fence_object. The destroy function will
+ * be set to kfree().
+ */
+
+extern int
+ttm_fence_object_create(struct ttm_fence_device *fdev,
+ uint32_t fence_class,
+ uint32_t type,
+ uint32_t create_flags,
+ struct ttm_fence_object **c_fence);
+
+/**
+ * ttm_fence_object_wait
+ *
+ * @fence: The fence object to wait on.
+ * @lazy: Allow sleeps to reduce the cpu-usage if polling.
+ * @interruptible: Sleep interruptible when waiting.
+ * @type_mask: Wait for the given type_mask to signal.
+ *
+ * Wait for a fence to signal the given type_mask. The function will
+ * perform a fence_flush using type_mask. (See ttm_fence_object_flush).
+ *
+ * Returns
+ * -ERESTART if interrupted by a signal.
+ * May return driver-specific error codes if timed-out.
+ */
+
+extern int
+ttm_fence_object_wait(struct ttm_fence_object *fence,
+ bool lazy, bool interruptible, uint32_t type_mask);
+
+/**
+ * ttm_fence_object_flush
+ *
+ * @fence: The fence object to flush.
+ * @flush_mask: Fence types to flush.
+ *
+ * Make sure that the given fence eventually signals the
+ * types indicated by @flush_mask. Note that this may or may not
+ * map to a CPU or GPU flush.
+ */
+
+extern int
+ttm_fence_object_flush(struct ttm_fence_object *fence, uint32_t flush_mask);
+
+/**
+ * ttm_fence_get_info
+ *
+ * @fence: The fence object.
+ *
+ * Copy the info block from the fence while holding relevant locks.
+ */
+
+struct ttm_fence_info ttm_fence_get_info(struct ttm_fence_object *fence);
+
+/**
+ * ttm_fence_object_ref
+ *
+ * @fence: The fence object.
+ *
+ * Return a ref-counted pointer to the fence object indicated by @fence.
+ */
+
+static inline struct ttm_fence_object *ttm_fence_object_ref(struct
+ ttm_fence_object
+ *fence) {
+ kref_get(&fence->kref);
+ return fence;
+}
+
+/**
+ * ttm_fence_object_unref
+ *
+ * @p_fence: Pointer to a ref-counted pinter to a struct ttm_fence_object.
+ *
+ * Unreference the fence object pointed to by *(@p_fence), clearing
+ * *(p_fence).
+ */
+
+extern void ttm_fence_object_unref(struct ttm_fence_object **p_fence);
+
+/**
+ * ttm_fence_object_signaled
+ *
+ * @fence: Pointer to the struct ttm_fence_object.
+ * @mask: Type mask to check whether signaled.
+ *
+ * This function checks (without waiting) whether the fence object
+ * pointed to by @fence has signaled the types indicated by @mask,
+ * and returns 1 if true, 0 if false. This function does NOT perform
+ * an implicit fence flush.
+ */
+
+extern bool
+ttm_fence_object_signaled(struct ttm_fence_object *fence, uint32_t mask);
+
+/**
+ * ttm_fence_class
+ *
+ * @fence: Pointer to the struct ttm_fence_object.
+ *
+ * Convenience function that returns the fence class of a
+ * struct ttm_fence_object.
+ */
+
+static inline uint32_t ttm_fence_class(const struct ttm_fence_object *fence)
+{
+ return fence->fence_class;
+}
+
+/**
+ * ttm_fence_types
+ *
+ * @fence: Pointer to the struct ttm_fence_object.
+ *
+ * Convenience function that returns the fence types of a
+ * struct ttm_fence_object.
+ */
+
+static inline uint32_t ttm_fence_types(const struct ttm_fence_object *fence)
+{
+ return fence->fence_type;
+}
+
+/*
+ * The functions below are wrappers to the above functions, with
+ * similar names but with sync_obj omitted. These wrappers are intended
+ * to be plugged directly into the buffer object driver's sync object
+ * API, if the driver chooses to use ttm_fence_objects as buffer object
+ * sync objects. In the prototypes below, a sync_obj is cast to a
+ * struct ttm_fence_object, whereas a sync_arg is cast to an
+ * uint32_t representing a fence_type argument.
+ */
+
+extern bool ttm_fence_sync_obj_signaled(void *sync_obj, void *sync_arg);
+extern int ttm_fence_sync_obj_wait(void *sync_obj, void *sync_arg,
+ bool lazy, bool interruptible);
+extern int ttm_fence_sync_obj_flush(void *sync_obj, void *sync_arg);
+extern void ttm_fence_sync_obj_unref(void **sync_obj);
+extern void *ttm_fence_sync_obj_ref(void *sync_obj);
+
+#endif
--- /dev/null
+/**************************************************************************
+ *
+ * Copyright (c) 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA
+ * All Rights Reserved.
+ * Copyright (c) 2009 VMware, Inc., Palo Alto, CA., USA
+ * 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 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.
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
+ */
+#ifndef _TTM_FENCE_DRIVER_H_
+#define _TTM_FENCE_DRIVER_H_
+
+#include <linux/kref.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
+#include "psb_ttm_fence_api.h"
+#include "ttm/ttm_memory.h"
+
+/** @file ttm_fence_driver.h
+ *
+ * Definitions needed for a driver implementing the
+ * ttm_fence subsystem.
+ */
+
+/**
+ * struct ttm_fence_class_manager:
+ *
+ * @wrap_diff: Sequence difference to catch 32-bit wrapping.
+ * if (seqa - seqb) > @wrap_diff, then seqa < seqb.
+ * @flush_diff: Sequence difference to trigger fence flush.
+ * if (cur_seq - seqa) > @flush_diff, then consider fence object with
+ * seqa as old an needing a flush.
+ * @sequence_mask: Mask of valid bits in a fence sequence.
+ * @lock: Lock protecting this struct as well as fence objects
+ * associated with this struct.
+ * @ring: Circular sequence-ordered list of fence objects.
+ * @pending_flush: Fence types currently needing a flush.
+ * @waiting_types: Fence types that are currently waited for.
+ * @fence_queue: Queue of waiters on fences belonging to this fence class.
+ * @highest_waiting_sequence: Sequence number of the fence with highest
+ * sequence number and that is waited for.
+ * @latest_queued_sequence: Sequence number of the fence latest queued
+ * on the ring.
+ */
+
+struct ttm_fence_class_manager {
+
+ /*
+ * Unprotected constant members.
+ */
+
+ uint32_t wrap_diff;
+ uint32_t flush_diff;
+ uint32_t sequence_mask;
+
+ /*
+ * The rwlock protects this structure as well as
+ * the data in all fence objects belonging to this
+ * class. This should be OK as most fence objects are
+ * only read from once they're created.
+ */
+
+ rwlock_t lock;
+ struct list_head ring;
+ uint32_t pending_flush;
+ uint32_t waiting_types;
+ wait_queue_head_t fence_queue;
+ uint32_t highest_waiting_sequence;
+ uint32_t latest_queued_sequence;
+};
+
+/**
+ * struct ttm_fence_device
+ *
+ * @fence_class: Array of fence class managers.
+ * @num_classes: Array dimension of @fence_class.
+ * @count: Current number of fence objects for statistics.
+ * @driver: Driver struct.
+ *
+ * Provided in the driver interface so that the driver can derive
+ * from this struct for its driver_private, and accordingly
+ * access the driver_private from the fence driver callbacks.
+ *
+ * All members except "count" are initialized at creation and
+ * never touched after that. No protection needed.
+ *
+ * This struct is private to the fence implementation and to the fence
+ * driver callbacks, and may otherwise be used by drivers only to
+ * obtain the derived device_private object using container_of().
+ */
+
+struct ttm_fence_device {
+ struct ttm_mem_global *mem_glob;
+ struct ttm_fence_class_manager *fence_class;
+ uint32_t num_classes;
+ atomic_t count;
+ const struct ttm_fence_driver *driver;
+};
+
+/**
+ * struct ttm_fence_class_init
+ *
+ * @wrap_diff: Fence sequence number wrap indicator. If
+ * (sequence1 - sequence2) > @wrap_diff, then sequence1 is
+ * considered to be older than sequence2.
+ * @flush_diff: Fence sequence number flush indicator.
+ * If a non-completely-signaled fence has a fence sequence number
+ * sequence1 and (sequence1 - current_emit_sequence) > @flush_diff,
+ * the fence is considered too old and it will be flushed upon the
+ * next call of ttm_fence_flush_old(), to make sure no fences with
+ * stale sequence numbers remains unsignaled. @flush_diff should
+ * be sufficiently less than @wrap_diff.
+ * @sequence_mask: Mask with valid bits of the fence sequence
+ * number set to 1.
+ *
+ * This struct is used as input to ttm_fence_device_init.
+ */
+
+struct ttm_fence_class_init {
+ uint32_t wrap_diff;
+ uint32_t flush_diff;
+ uint32_t sequence_mask;
+};
+
+/**
+ * struct ttm_fence_driver
+ *
+ * @has_irq: Called by a potential waiter. Should return 1 if a
+ * fence object with indicated parameters is expected to signal
+ * automatically, and 0 if the fence implementation needs to
+ * repeatedly call @poll to make it signal.
+ * @emit: Make sure a fence with the given parameters is
+ * present in the indicated command stream. Return its sequence number
+ * in "breadcrumb".
+ * @poll: Check and report sequences of the given "fence_class"
+ * that have signaled "types"
+ * @flush: Make sure that the types indicated by the bitfield
+ * ttm_fence_class_manager::pending_flush will eventually
+ * signal. These bits have been put together using the
+ * result from the needed_flush function described below.
+ * @needed_flush: Given the fence_class and fence_types indicated by
+ * "fence", and the last received fence sequence of this
+ * fence class, indicate what types need a fence flush to
+ * signal. Return as a bitfield.
+ * @wait: Set to non-NULL if the driver wants to override the fence
+ * wait implementation. Return 0 on success, -EBUSY on failure,
+ * and -ERESTART if interruptible and a signal is pending.
+ * @signaled: Driver callback that is called whenever a
+ * ttm_fence_object::signaled_types has changed status.
+ * This function is called from atomic context,
+ * with the ttm_fence_class_manager::lock held in write mode.
+ * @lockup: Driver callback that is called whenever a wait has exceeded
+ * the lifetime of a fence object.
+ * If there is a GPU lockup,
+ * this function should, if possible, reset the GPU,
+ * call the ttm_fence_handler with an error status, and
+ * return. If no lockup was detected, simply extend the
+ * fence timeout_jiffies and return. The driver might
+ * want to protect the lockup check with a mutex and cache a
+ * non-locked-up status for a while to avoid an excessive
+ * amount of lockup checks from every waiting thread.
+ */
+
+struct ttm_fence_driver {
+ bool (*has_irq)(struct ttm_fence_device *fdev,
+ uint32_t fence_class, uint32_t flags);
+ int (*emit)(struct ttm_fence_device *fdev,
+ uint32_t fence_class,
+ uint32_t flags,
+ uint32_t *breadcrumb, unsigned long *timeout_jiffies);
+ void (*flush)(struct ttm_fence_device *fdev, uint32_t fence_class);
+ void (*poll)(struct ttm_fence_device *fdev,
+ uint32_t fence_class, uint32_t types);
+ uint32_t(*needed_flush)
+ (struct ttm_fence_object *fence);
+ int (*wait)(struct ttm_fence_object *fence, bool lazy,
+ bool interruptible, uint32_t mask);
+ void (*signaled)(struct ttm_fence_object *fence);
+ void (*lockup)(struct ttm_fence_object *fence, uint32_t fence_types);
+};
+
+/**
+ * function ttm_fence_device_init
+ *
+ * @num_classes: Number of fence classes for this fence implementation.
+ * @mem_global: Pointer to the global memory accounting info.
+ * @fdev: Pointer to an uninitialised struct ttm_fence_device.
+ * @init: Array of initialization info for each fence class.
+ * @replicate_init: Use the first @init initialization info for all classes.
+ * @driver: Driver callbacks.
+ *
+ * Initialize a struct ttm_fence_driver structure. Returns -ENOMEM if
+ * out-of-memory. Otherwise returns 0.
+ */
+extern int
+ttm_fence_device_init(int num_classes,
+ struct ttm_mem_global *mem_glob,
+ struct ttm_fence_device *fdev,
+ const struct ttm_fence_class_init *init,
+ bool replicate_init,
+ const struct ttm_fence_driver *driver);
+
+/**
+ * function ttm_fence_device_release
+ *
+ * @fdev: Pointer to the fence device.
+ *
+ * Release all resources held by a fence device. Note that before
+ * this function is called, the caller must have made sure all fence
+ * objects belonging to this fence device are completely signaled.
+ */
+
+extern void ttm_fence_device_release(struct ttm_fence_device *fdev);
+
+/**
+ * ttm_fence_handler - the fence handler.
+ *
+ * @fdev: Pointer to the fence device.
+ * @fence_class: Fence class that signals.
+ * @sequence: Signaled sequence.
+ * @type: Types that signal.
+ * @error: Error from the engine.
+ *
+ * This function signals all fences with a sequence previous to the
+ * @sequence argument, and belonging to @fence_class. The signaled fence
+ * types are provided in @type. If error is non-zero, the error member
+ * of the fence with sequence = @sequence is set to @error. This value
+ * may be reported back to user-space, indicating, for example an illegal
+ * 3D command or illegal mpeg data.
+ *
+ * This function is typically called from the driver::poll method when the
+ * command sequence preceding the fence marker has executed. It should be
+ * called with the ttm_fence_class_manager::lock held in write mode and
+ * may be called from interrupt context.
+ */
+
+extern void
+ttm_fence_handler(struct ttm_fence_device *fdev,
+ uint32_t fence_class,
+ uint32_t sequence, uint32_t type, uint32_t error);
+
+/**
+ * ttm_fence_driver_from_dev
+ *
+ * @fdev: The ttm fence device.
+ *
+ * Returns a pointer to the fence driver struct.
+ */
+
+static inline const struct ttm_fence_driver *ttm_fence_driver_from_dev(
+ struct ttm_fence_device *fdev) {
+ return fdev->driver;
+}
+
+/**
+ * ttm_fence_driver
+ *
+ * @fence: Pointer to a ttm fence object.
+ *
+ * Returns a pointer to the fence driver struct.
+ */
+
+static inline const struct ttm_fence_driver *ttm_fence_driver(struct
+ ttm_fence_object
+ *fence) {
+ return ttm_fence_driver_from_dev(fence->fdev);
+}
+
+/**
+ * ttm_fence_fc
+ *
+ * @fence: Pointer to a ttm fence object.
+ *
+ * Returns a pointer to the struct ttm_fence_class_manager for the
+ * fence class of @fence.
+ */
+
+static inline struct ttm_fence_class_manager *ttm_fence_fc(struct
+ ttm_fence_object
+ *fence) {
+ return &fence->fdev->fence_class[fence->fence_class];
+}
+
+#endif
--- /dev/null
+/**************************************************************************
+ *
+ * Copyright (c) 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA
+ * All Rights Reserved.
+ * Copyright (c) 2009 VMware, Inc., Palo Alto, CA., USA
+ * 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 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.
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
+ */
+
+#include <drm/drmP.h>
+#include "psb_ttm_fence_user.h"
+#include "ttm/ttm_object.h"
+#include "psb_ttm_fence_driver.h"
+#include "psb_ttm_userobj_api.h"
+
+/**
+ * struct ttm_fence_user_object
+ *
+ * @base: The base object used for user-space visibility and refcounting.
+ *
+ * @fence: The fence object itself.
+ *
+ */
+
+struct ttm_fence_user_object {
+ struct ttm_base_object base;
+ struct ttm_fence_object fence;
+};
+
+static struct ttm_fence_user_object *ttm_fence_user_object_lookup(
+ struct ttm_object_file *tfile,
+ uint32_t handle) {
+ struct ttm_base_object *base;
+
+ base = ttm_base_object_lookup(tfile, handle);
+ if (unlikely(base == NULL)) {
+ printk(KERN_ERR "Invalid fence handle 0x%08lx\n",
+ (unsigned long)handle);
+ return NULL;
+ }
+
+ if (unlikely(base->object_type != ttm_fence_type)) {
+ ttm_base_object_unref(&base);
+ printk(KERN_ERR "Invalid fence handle 0x%08lx\n",
+ (unsigned long)handle);
+ return NULL;
+ }
+
+ return container_of(base, struct ttm_fence_user_object, base);
+}
+
+/*
+ * The fence object destructor.
+ */
+
+static void ttm_fence_user_destroy(struct ttm_fence_object *fence)
+{
+ struct ttm_fence_user_object *ufence =
+ container_of(fence, struct ttm_fence_user_object, fence);
+
+ ttm_mem_global_free(fence->fdev->mem_glob, sizeof(*ufence));
+ kfree(ufence);
+}
+
+/*
+ * The base object destructor. We basically unly unreference the
+ * attached fence object.
+ */
+
+static void ttm_fence_user_release(struct ttm_base_object **p_base)
+{
+ struct ttm_fence_user_object *ufence;
+ struct ttm_base_object *base = *p_base;
+ struct ttm_fence_object *fence;
+
+ *p_base = NULL;
+
+ if (unlikely(base == NULL))
+ return;
+
+ ufence = container_of(base, struct ttm_fence_user_object, base);
+ fence = &ufence->fence;
+ ttm_fence_object_unref(&fence);
+}
+
+int
+ttm_fence_user_create(struct ttm_fence_device *fdev,
+ struct ttm_object_file *tfile,
+ uint32_t fence_class,
+ uint32_t fence_types,
+ uint32_t create_flags,
+ struct ttm_fence_object **fence,
+ uint32_t *user_handle)
+{
+ int ret;
+ struct ttm_fence_object *tmp;
+ struct ttm_fence_user_object *ufence;
+
+ ret = ttm_mem_global_alloc(fdev->mem_glob,
+ sizeof(*ufence),
+ false,
+ false);
+ if (unlikely(ret != 0))
+ return -ENOMEM;
+
+ ufence = kmalloc(sizeof(*ufence), GFP_KERNEL);
+ if (unlikely(ufence == NULL)) {
+ ttm_mem_global_free(fdev->mem_glob, sizeof(*ufence));
+ return -ENOMEM;
+ }
+
+ ret = ttm_fence_object_init(fdev,
+ fence_class,
+ fence_types, create_flags,
+ &ttm_fence_user_destroy, &ufence->fence);
+
+ if (unlikely(ret != 0))
+ goto out_err0;
+
+ /*
+ * One fence ref is held by the fence ptr we return.
+ * The other one by the base object. Need to up the
+ * fence refcount before we publish this object to
+ * user-space.
+ */
+
+ tmp = ttm_fence_object_ref(&ufence->fence);
+ ret = ttm_base_object_init(tfile, &ufence->base,
+ false, ttm_fence_type,
+ &ttm_fence_user_release, NULL);
+
+ if (unlikely(ret != 0))
+ goto out_err1;
+
+ *fence = &ufence->fence;
+ *user_handle = ufence->base.hash.key;
+
+ return 0;
+out_err1:
+ ttm_fence_object_unref(&tmp);
+ tmp = &ufence->fence;
+ ttm_fence_object_unref(&tmp);
+ return ret;
+out_err0:
+ ttm_mem_global_free(fdev->mem_glob, sizeof(*ufence));
+ kfree(ufence);
+ return ret;
+}
+
+int ttm_fence_signaled_ioctl(struct ttm_object_file *tfile, void *data)
+{
+ int ret;
+ union ttm_fence_signaled_arg *arg = data;
+ struct ttm_fence_object *fence;
+ struct ttm_fence_info info;
+ struct ttm_fence_user_object *ufence;
+ struct ttm_base_object *base;
+ ret = 0;
+
+ ufence = ttm_fence_user_object_lookup(tfile, arg->req.handle);
+ if (unlikely(ufence == NULL))
+ return -EINVAL;
+
+ fence = &ufence->fence;
+
+ if (arg->req.flush) {
+ ret = ttm_fence_object_flush(fence, arg->req.fence_type);
+ if (unlikely(ret != 0))
+ goto out;
+ }
+
+ info = ttm_fence_get_info(fence);
+ arg->rep.signaled_types = info.signaled_types;
+ arg->rep.fence_error = info.error;
+
+out:
+ base = &ufence->base;
+ ttm_base_object_unref(&base);
+ return ret;
+}
+
+int ttm_fence_finish_ioctl(struct ttm_object_file *tfile, void *data)
+{
+ int ret;
+ union ttm_fence_finish_arg *arg = data;
+ struct ttm_fence_user_object *ufence;
+ struct ttm_base_object *base;
+ struct ttm_fence_object *fence;
+ ret = 0;
+
+ ufence = ttm_fence_user_object_lookup(tfile, arg->req.handle);
+ if (unlikely(ufence == NULL))
+ return -EINVAL;
+
+ fence = &ufence->fence;
+
+ ret = ttm_fence_object_wait(fence,
+ arg->req.mode & TTM_FENCE_FINISH_MODE_LAZY,
+ true, arg->req.fence_type);
+ if (likely(ret == 0)) {
+ struct ttm_fence_info info = ttm_fence_get_info(fence);
+
+ arg->rep.signaled_types = info.signaled_types;
+ arg->rep.fence_error = info.error;
+ }
+
+ base = &ufence->base;
+ ttm_base_object_unref(&base);
+
+ return ret;
+}
+
+int ttm_fence_unref_ioctl(struct ttm_object_file *tfile, void *data)
+{
+ struct ttm_fence_unref_arg *arg = data;
+ int ret = 0;
+
+ ret = ttm_ref_object_base_unref(tfile, arg->handle, ttm_fence_type);
+ return ret;
+}
--- /dev/null
+/**************************************************************************
+ *
+ * Copyright 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA
+ * All Rights Reserved.
+ * Copyright (c) 2009 VMware, Inc., Palo Alto, CA., USA
+ * 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 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.
+ *
+ **************************************************************************/
+/*
+ * Authors
+ * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ */
+
+#ifndef TTM_FENCE_USER_H
+#define TTM_FENCE_USER_H
+
+#if !defined(__KERNEL__) && !defined(_KERNEL)
+#include <stdint.h>
+#endif
+
+#define TTM_FENCE_MAJOR 0
+#define TTM_FENCE_MINOR 1
+#define TTM_FENCE_PL 0
+#define TTM_FENCE_DATE "080819"
+
+/**
+ * struct ttm_fence_signaled_req
+ *
+ * @handle: Handle to the fence object. Input.
+ *
+ * @fence_type: Fence types we want to flush. Input.
+ *
+ * @flush: Boolean. Flush the indicated fence_types. Input.
+ *
+ * Argument to the TTM_FENCE_SIGNALED ioctl.
+ */
+
+struct ttm_fence_signaled_req {
+ uint32_t handle;
+ uint32_t fence_type;
+ int32_t flush;
+ uint32_t pad64;
+};
+
+/**
+ * struct ttm_fence_rep
+ *
+ * @signaled_types: Fence type that has signaled.
+ *
+ * @fence_error: Command execution error.
+ * Hardware errors that are consequences of the execution
+ * of the command stream preceding the fence are reported
+ * here.
+ *
+ * Output argument to the TTM_FENCE_SIGNALED and
+ * TTM_FENCE_FINISH ioctls.
+ */
+
+struct ttm_fence_rep {
+ uint32_t signaled_types;
+ uint32_t fence_error;
+};
+
+union ttm_fence_signaled_arg {
+ struct ttm_fence_signaled_req req;
+ struct ttm_fence_rep rep;
+};
+
+/*
+ * Waiting mode flags for the TTM_FENCE_FINISH ioctl.
+ *
+ * TTM_FENCE_FINISH_MODE_LAZY: Allow for sleeps during polling
+ * wait.
+ *
+ * TTM_FENCE_FINISH_MODE_NO_BLOCK: Don't block waiting for GPU,
+ * but return -EBUSY if the buffer is busy.
+ */
+
+#define TTM_FENCE_FINISH_MODE_LAZY (1 << 0)
+#define TTM_FENCE_FINISH_MODE_NO_BLOCK (1 << 1)
+
+/**
+ * struct ttm_fence_finish_req
+ *
+ * @handle: Handle to the fence object. Input.
+ *
+ * @fence_type: Fence types we want to finish.
+ *
+ * @mode: Wait mode.
+ *
+ * Input to the TTM_FENCE_FINISH ioctl.
+ */
+
+struct ttm_fence_finish_req {
+ uint32_t handle;
+ uint32_t fence_type;
+ uint32_t mode;
+ uint32_t pad64;
+};
+
+union ttm_fence_finish_arg {
+ struct ttm_fence_finish_req req;
+ struct ttm_fence_rep rep;
+};
+
+/**
+ * struct ttm_fence_unref_arg
+ *
+ * @handle: Handle to the fence object.
+ *
+ * Argument to the TTM_FENCE_UNREF ioctl.
+ */
+
+struct ttm_fence_unref_arg {
+ uint32_t handle;
+ uint32_t pad64;
+};
+
+/*
+ * Ioctl offsets frome extenstion start.
+ */
+
+#define TTM_FENCE_SIGNALED 0x01
+#define TTM_FENCE_FINISH 0x02
+#define TTM_FENCE_UNREF 0x03
+
+#endif
--- /dev/null
+/**************************************************************************
+ * Copyright (c) 2008, Intel Corporation.
+ * All Rights Reserved.
+ * Copyright (c) 2008, Tungsten Graphics Inc. Cedar Park, TX., USA.
+ * 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 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.
+ *
+ **************************************************************************/
+
+
+#include <drm/drmP.h>
+#include "psb_drv.h"
+#include "psb_ttm_userobj_api.h"
+#include <linux/io.h>
+#include "psb_msvdx.h"
+#include "bufferclass_video.h"
+#include "bufferclass_video_linux.h"
+
+/*IMG Headers*/
+#include "private_data.h"
+
+extern int PVRMMap(struct file *pFile, struct vm_area_struct *ps_vma);
+int BC_DestroyBuffers(int id);
+
+static struct vm_operations_struct psb_ttm_vm_ops;
+
+/**
+ * NOTE: driver_private of drm_file is now a PVRSRV_FILE_PRIVATE_DATA struct
+ * pPriv in PVRSRV_FILE_PRIVATE_DATA contains the original psb_fpriv;
+ */
+int psb_open(struct inode *inode, struct file *filp)
+{
+ struct drm_file *file_priv;
+ struct drm_psb_private *dev_priv;
+ struct psb_fpriv *psb_fp;
+ PVRSRV_FILE_PRIVATE_DATA *pvr_file_priv;
+ int ret;
+
+ DRM_DEBUG("\n");
+
+ ret = drm_open(inode, filp);
+ if (unlikely(ret))
+ return ret;
+
+ psb_fp = kzalloc(sizeof(*psb_fp), GFP_KERNEL);
+
+ if (unlikely(psb_fp == NULL))
+ goto out_err0;
+
+ file_priv = (struct drm_file *) filp->private_data;
+ dev_priv = psb_priv(file_priv->minor->dev);
+
+ DRM_DEBUG("is_master %d\n", file_priv->is_master ? 1 : 0);
+
+ psb_fp->tfile = ttm_object_file_init(dev_priv->tdev,
+ PSB_FILE_OBJECT_HASH_ORDER);
+ if (unlikely(psb_fp->tfile == NULL))
+ goto out_err1;
+
+ pvr_file_priv = (PVRSRV_FILE_PRIVATE_DATA *)file_priv->driver_priv;
+ if (!pvr_file_priv) {
+ DRM_ERROR("drm file private is NULL\n");
+ goto out_err1;
+ }
+
+ pvr_file_priv->pPriv = psb_fp;
+ if (unlikely(dev_priv->bdev.dev_mapping == NULL))
+ dev_priv->bdev.dev_mapping = dev_priv->dev->dev_mapping;
+
+ return 0;
+
+out_err1:
+ kfree(psb_fp);
+out_err0:
+ (void) drm_release(inode, filp);
+ return ret;
+}
+
+int psb_release(struct inode *inode, struct file *filp)
+{
+ struct drm_file *file_priv;
+ struct psb_fpriv *psb_fp;
+ struct drm_psb_private *dev_priv;
+ struct msvdx_private *msvdx_priv;
+ int ret;
+ file_priv = (struct drm_file *) filp->private_data;
+ psb_fp = psb_fpriv(file_priv);
+ dev_priv = psb_priv(file_priv->minor->dev);
+ msvdx_priv = (struct msvdx_private *)dev_priv->msvdx_private;
+
+ /*cleanup for msvdx*/
+ if (msvdx_priv->tfile == psb_fpriv(file_priv)->tfile) {
+ msvdx_priv->fw_status = 0;
+ msvdx_priv->host_be_opp_enabled = 0;
+ msvdx_priv->deblock_enabled = 0;
+ memset(&msvdx_priv->frame_info, 0, sizeof(struct drm_psb_msvdx_frame_info) * MAX_DECODE_BUFFERS);
+ }
+
+ if (psb_fp->bcd_index >= 0 &&
+ psb_fp->bcd_index < BC_VIDEO_DEVICE_MAX_ID &&
+ bc_video_id_usage[psb_fp->bcd_index] == 1) {
+ bc_video_id_usage[psb_fp->bcd_index] = 0;
+ BC_DestroyBuffers(psb_fp->bcd_index);
+ }
+
+ ttm_object_file_release(&psb_fp->tfile);
+ kfree(psb_fp);
+
+ /* remove video context */
+ psb_remove_videoctx(dev_priv, filp);
+
+ ret = drm_release(inode, filp);
+
+ return ret;
+}
+
+int psb_fence_signaled_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+
+ return ttm_fence_signaled_ioctl(psb_fpriv(file_priv)->tfile, data);
+}
+
+int psb_fence_finish_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ return ttm_fence_finish_ioctl(psb_fpriv(file_priv)->tfile, data);
+}
+
+int psb_fence_unref_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ return ttm_fence_unref_ioctl(psb_fpriv(file_priv)->tfile, data);
+}
+
+int psb_pl_waitidle_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ return ttm_pl_waitidle_ioctl(psb_fpriv(file_priv)->tfile, data);
+}
+
+int psb_pl_setstatus_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ return ttm_pl_setstatus_ioctl(psb_fpriv(file_priv)->tfile,
+ &psb_priv(dev)->ttm_lock, data);
+
+}
+
+int psb_pl_synccpu_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ return ttm_pl_synccpu_ioctl(psb_fpriv(file_priv)->tfile, data);
+}
+
+int psb_pl_unref_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ return ttm_pl_unref_ioctl(psb_fpriv(file_priv)->tfile, data);
+
+}
+
+int psb_pl_reference_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ return ttm_pl_reference_ioctl(psb_fpriv(file_priv)->tfile, data);
+
+}
+
+int psb_pl_create_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_psb_private *dev_priv = psb_priv(dev);
+
+ return ttm_pl_create_ioctl(psb_fpriv(file_priv)->tfile,
+ &dev_priv->bdev, &dev_priv->ttm_lock, data);
+
+}
+
+int psb_pl_ub_create_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_psb_private *dev_priv = psb_priv(dev);
+
+ return ttm_pl_ub_create_ioctl(psb_fpriv(file_priv)->tfile,
+ &dev_priv->bdev, &dev_priv->ttm_lock, data);
+
+}
+/**
+ * psb_ttm_fault - Wrapper around the ttm fault method.
+ *
+ * @vma: The struct vm_area_struct as in the vm fault() method.
+ * @vmf: The struct vm_fault as in the vm fault() method.
+ *
+ * Since ttm_fault() will reserve buffers while faulting,
+ * we need to take the ttm read lock around it, as this driver
+ * relies on the ttm_lock in write mode to exclude all threads from
+ * reserving and thus validating buffers in aperture- and memory shortage
+ * situations.
+ */
+
+static int psb_ttm_fault(struct vm_area_struct *vma,
+ struct vm_fault *vmf)
+{
+ struct ttm_buffer_object *bo = (struct ttm_buffer_object *)
+ vma->vm_private_data;
+ struct drm_psb_private *dev_priv =
+ container_of(bo->bdev, struct drm_psb_private, bdev);
+ int ret;
+
+ ret = ttm_read_lock(&dev_priv->ttm_lock, true);
+ if (unlikely(ret != 0))
+ return VM_FAULT_NOPAGE;
+
+ ret = dev_priv->ttm_vm_ops->fault(vma, vmf);
+
+ ttm_read_unlock(&dev_priv->ttm_lock);
+ return ret;
+}
+
+/**
+ * if vm_pgoff < DRM_PSB_FILE_PAGE_OFFSET call directly to
+ * PVRMMap
+ */
+int psb_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+ struct drm_file *file_priv;
+ struct drm_psb_private *dev_priv;
+ int ret;
+
+ if (vma->vm_pgoff < DRM_PSB_FILE_PAGE_OFFSET ||
+ vma->vm_pgoff > 2 * DRM_PSB_FILE_PAGE_OFFSET)
+ return PVRMMap(filp, vma);
+
+ file_priv = (struct drm_file *) filp->private_data;
+ dev_priv = psb_priv(file_priv->minor->dev);
+
+ ret = ttm_bo_mmap(filp, vma, &dev_priv->bdev);
+ if (unlikely(ret != 0))
+ return ret;
+
+ if (unlikely(dev_priv->ttm_vm_ops == NULL)) {
+ dev_priv->ttm_vm_ops = (struct vm_operations_struct *)vma->vm_ops;
+ psb_ttm_vm_ops = *vma->vm_ops;
+ psb_ttm_vm_ops.fault = &psb_ttm_fault;
+ }
+
+ vma->vm_ops = &psb_ttm_vm_ops;
+
+ return 0;
+}
+/*
+ssize_t psb_ttm_write(struct file *filp, const char __user *buf,
+ size_t count, loff_t *f_pos)
+{
+ struct drm_file *file_priv = (struct drm_file *)filp->private_data;
+ struct drm_psb_private *dev_priv = psb_priv(file_priv->minor->dev);
+
+ return ttm_bo_io(&dev_priv->bdev, filp, buf, NULL, count, f_pos, 1);
+}
+
+ssize_t psb_ttm_read(struct file *filp, char __user *buf,
+ size_t count, loff_t *f_pos)
+{
+ struct drm_file *file_priv = (struct drm_file *)filp->private_data;
+ struct drm_psb_private *dev_priv = psb_priv(file_priv->minor->dev);
+
+ return ttm_bo_io(&dev_priv->bdev, filp, NULL, buf, count, f_pos, 1);
+}
+*/
+int psb_verify_access(struct ttm_buffer_object *bo,
+ struct file *filp)
+{
+ struct drm_file *file_priv = (struct drm_file *)filp->private_data;
+
+ if (capable(CAP_SYS_ADMIN))
+ return 0;
+
+ if (unlikely(!file_priv->authenticated))
+ return -EPERM;
+
+ return ttm_pl_verify_access(bo, psb_fpriv(file_priv)->tfile);
+}
+
+static int psb_ttm_mem_global_init(struct drm_global_reference *ref)
+{
+ return ttm_mem_global_init(ref->object);
+}
+
+static void psb_ttm_mem_global_release(struct drm_global_reference *ref)
+{
+ ttm_mem_global_release(ref->object);
+}
+
+int psb_ttm_global_init(struct drm_psb_private *dev_priv)
+{
+ struct drm_global_reference *global_ref;
+ struct drm_global_reference *global;
+ int ret;
+
+ global_ref = &dev_priv->mem_global_ref;
+ global_ref->global_type = DRM_GLOBAL_TTM_MEM;
+ global_ref->size = sizeof(struct ttm_mem_global);
+ global_ref->init = &psb_ttm_mem_global_init;
+ global_ref->release = &psb_ttm_mem_global_release;
+
+ ret = drm_global_item_ref(global_ref);
+ if (unlikely(ret != 0)) {
+ DRM_ERROR("Failed referencing a global TTM memory object.\n");
+ return ret;
+ }
+
+ dev_priv->bo_global_ref.mem_glob = dev_priv->mem_global_ref.object;
+ global = &dev_priv->bo_global_ref.ref;
+ global->global_type = DRM_GLOBAL_TTM_BO;
+ global->size = sizeof(struct ttm_bo_global);
+ global->init = &ttm_bo_global_init;
+ global->release = &ttm_bo_global_release;
+ ret = drm_global_item_ref(global);
+ if (ret != 0) {
+ DRM_ERROR("Failed setting up TTM BO subsystem.\n");
+ drm_global_item_unref(global_ref);
+ return ret;
+ }
+
+ return 0;
+}
+
+void psb_ttm_global_release(struct drm_psb_private *dev_priv)
+{
+ drm_global_item_unref(&dev_priv->mem_global_ref);
+}
+
+int psb_getpageaddrs_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_psb_getpageaddrs_arg *arg = data;
+ struct ttm_buffer_object *bo;
+ struct ttm_tt *ttm;
+ struct page **tt_pages;
+ unsigned long i, num_pages;
+ unsigned long *p = arg->page_addrs;
+ int ret = 0;
+
+ bo = ttm_buffer_object_lookup(psb_fpriv(file_priv)->tfile,
+ arg->handle);
+ if (unlikely(bo == NULL)) {
+ printk(KERN_ERR
+ "Could not find buffer object for getpageaddrs.\n");
+ return -EINVAL;
+ }
+
+ arg->gtt_offset = bo->offset;
+ ttm = bo->ttm;
+ num_pages = ttm->num_pages;
+ tt_pages = ttm->pages;
+
+ for (i = 0; i < num_pages; i++)
+ p[i] = (unsigned long)page_to_phys(tt_pages[i]);
+
+ if (bo)
+ ttm_bo_unref(&bo);
+
+ return ret;
+}
--- /dev/null
+/**************************************************************************
+ *
+ * Copyright (c) 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA
+ * 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 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.
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
+ */
+
+#include "psb_ttm_placement_user.h"
+#include "ttm/ttm_bo_driver.h"
+#include "ttm/ttm_object.h"
+#include "psb_ttm_userobj_api.h"
+#include "ttm/ttm_lock.h"
+#include <linux/slab.h>
+#include <linux/sched.h>
+
+struct ttm_bo_user_object {
+ struct ttm_base_object base;
+ struct ttm_buffer_object bo;
+};
+
+static size_t pl_bo_size;
+
+static uint32_t psb_busy_prios[] = {
+ TTM_PL_TT,
+ TTM_PL_PRIV0, /* CI */
+ TTM_PL_PRIV2, /* RAR */
+ TTM_PL_PRIV1, /* DRM_PSB_MEM_MMU */
+ TTM_PL_SYSTEM
+};
+
+static const struct ttm_placement default_placement = {0, 0, 0, NULL, 5, psb_busy_prios};
+
+static size_t ttm_pl_size(struct ttm_bo_device *bdev, unsigned long num_pages)
+{
+ size_t page_array_size =
+ (num_pages * sizeof(void *) + PAGE_SIZE - 1) & PAGE_MASK;
+
+ if (unlikely(pl_bo_size == 0)) {
+ pl_bo_size = bdev->glob->ttm_bo_extra_size +
+ ttm_round_pot(sizeof(struct ttm_bo_user_object));
+ }
+
+ return bdev->glob->ttm_bo_size + 2 * page_array_size;
+}
+
+static struct ttm_bo_user_object *ttm_bo_user_lookup(struct ttm_object_file
+ *tfile, uint32_t handle) {
+ struct ttm_base_object *base;
+
+ base = ttm_base_object_lookup(tfile, handle);
+ if (unlikely(base == NULL)) {
+ printk(KERN_ERR "Invalid buffer object handle 0x%08lx.\n",
+ (unsigned long)handle);
+ return NULL;
+ }
+
+ if (unlikely(base->object_type != ttm_buffer_type)) {
+ ttm_base_object_unref(&base);
+ printk(KERN_ERR "Invalid buffer object handle 0x%08lx.\n",
+ (unsigned long)handle);
+ return NULL;
+ }
+
+ return container_of(base, struct ttm_bo_user_object, base);
+}
+
+struct ttm_buffer_object *ttm_buffer_object_lookup(struct ttm_object_file
+ *tfile, uint32_t handle) {
+ struct ttm_bo_user_object *user_bo;
+ struct ttm_base_object *base;
+
+ user_bo = ttm_bo_user_lookup(tfile, handle);
+ if (unlikely(user_bo == NULL))
+ return NULL;
+
+ (void)ttm_bo_reference(&user_bo->bo);
+ base = &user_bo->base;
+ ttm_base_object_unref(&base);
+ return &user_bo->bo;
+}
+
+static void ttm_bo_user_destroy(struct ttm_buffer_object *bo)
+{
+ struct ttm_bo_user_object *user_bo =
+ container_of(bo, struct ttm_bo_user_object, bo);
+
+ ttm_mem_global_free(bo->glob->mem_glob, bo->acc_size);
+ kfree(user_bo);
+}
+
+static void ttm_bo_user_release(struct ttm_base_object **p_base)
+{
+ struct ttm_bo_user_object *user_bo;
+ struct ttm_base_object *base = *p_base;
+ struct ttm_buffer_object *bo;
+
+ *p_base = NULL;
+
+ if (unlikely(base == NULL))
+ return;
+
+ user_bo = container_of(base, struct ttm_bo_user_object, base);
+ bo = &user_bo->bo;
+ ttm_bo_unref(&bo);
+}
+
+static void ttm_bo_user_ref_release(struct ttm_base_object *base,
+ enum ttm_ref_type ref_type)
+{
+ struct ttm_bo_user_object *user_bo =
+ container_of(base, struct ttm_bo_user_object, base);
+ struct ttm_buffer_object *bo = &user_bo->bo;
+
+ switch (ref_type) {
+ case TTM_REF_SYNCCPU_WRITE:
+ ttm_bo_synccpu_write_release(bo);
+ break;
+ default:
+ BUG();
+ }
+}
+
+static void ttm_pl_fill_rep(struct ttm_buffer_object *bo,
+ struct ttm_pl_rep *rep)
+{
+ struct ttm_bo_user_object *user_bo =
+ container_of(bo, struct ttm_bo_user_object, bo);
+
+ rep->gpu_offset = bo->offset;
+ rep->bo_size = bo->num_pages << PAGE_SHIFT;
+ rep->map_handle = bo->addr_space_offset;
+ rep->placement = bo->mem.placement;
+ rep->handle = user_bo->base.hash.key;
+ rep->sync_object_arg = (uint32_t)(unsigned long)bo->sync_obj_arg;
+}
+
+/* FIXME Copy from upstream TTM */
+static inline size_t ttm_bo_size(struct ttm_bo_global *glob,
+ unsigned long num_pages)
+{
+ size_t page_array_size = (num_pages * sizeof(void *) + PAGE_SIZE - 1) &
+ PAGE_MASK;
+
+ return glob->ttm_bo_size + 2 * page_array_size;
+}
+
+/* FIXME Copy from upstream TTM "ttm_bo_create", upstream TTM does not export this, so copy it here */
+static int ttm_bo_create_private(struct ttm_bo_device *bdev,
+ unsigned long size,
+ enum ttm_bo_type type,
+ struct ttm_placement *placement,
+ uint32_t page_alignment,
+ unsigned long buffer_start,
+ bool interruptible,
+ struct file *persistant_swap_storage,
+ struct ttm_buffer_object **p_bo)
+{
+ struct ttm_buffer_object *bo;
+ struct ttm_mem_global *mem_glob = bdev->glob->mem_glob;
+ int ret;
+
+ size_t acc_size =
+ ttm_bo_size(bdev->glob, (size + PAGE_SIZE - 1) >> PAGE_SHIFT);
+ ret = ttm_mem_global_alloc(mem_glob, acc_size, false, false);
+ if (unlikely(ret != 0))
+ return ret;
+
+ bo = kzalloc(sizeof(*bo), GFP_KERNEL);
+
+ if (unlikely(bo == NULL)) {
+ ttm_mem_global_free(mem_glob, acc_size);
+ return -ENOMEM;
+ }
+
+ ret = ttm_bo_init(bdev, bo, size, type, placement, page_alignment,
+ buffer_start, interruptible,
+ persistant_swap_storage, acc_size, NULL);
+ if (likely(ret == 0))
+ *p_bo = bo;
+
+ return ret;
+}
+
+int psb_ttm_bo_check_placement(struct ttm_buffer_object *bo,
+ struct ttm_placement *placement)
+{
+ int i;
+
+ for (i = 0; i < placement->num_placement; i++) {
+ if (!capable(CAP_SYS_ADMIN)) {
+ if (placement->placement[i] & TTM_PL_FLAG_NO_EVICT) {
+ printk(KERN_ERR TTM_PFX "Need to be root to "
+ "modify NO_EVICT status.\n");
+ return -EINVAL;
+ }
+ }
+ }
+ for (i = 0; i < placement->num_busy_placement; i++) {
+ if (!capable(CAP_SYS_ADMIN)) {
+ if (placement->busy_placement[i] & TTM_PL_FLAG_NO_EVICT) {
+ printk(KERN_ERR TTM_PFX "Need to be root to "
+ "modify NO_EVICT status.\n");
+ return -EINVAL;
+ }
+ }
+ }
+ return 0;
+}
+
+int ttm_buffer_object_create(struct ttm_bo_device *bdev,
+ unsigned long size,
+ enum ttm_bo_type type,
+ uint32_t flags,
+ uint32_t page_alignment,
+ unsigned long buffer_start,
+ bool interruptible,
+ struct file *persistant_swap_storage,
+ struct ttm_buffer_object **p_bo)
+{
+ struct ttm_placement placement = default_placement;
+ int ret;
+
+ if ((flags & TTM_PL_MASK_CACHING) == 0)
+ flags |= TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED;
+
+ placement.num_placement = 1;
+ placement.placement = &flags;
+
+ ret = ttm_bo_create_private(bdev,
+ size,
+ type,
+ &placement,
+ page_alignment,
+ buffer_start,
+ interruptible,
+ persistant_swap_storage,
+ p_bo);
+
+ return ret;
+}
+
+
+int ttm_pl_create_ioctl(struct ttm_object_file *tfile,
+ struct ttm_bo_device *bdev,
+ struct ttm_lock *lock, void *data)
+{
+ union ttm_pl_create_arg *arg = data;
+ struct ttm_pl_create_req *req = &arg->req;
+ struct ttm_pl_rep *rep = &arg->rep;
+ struct ttm_buffer_object *bo;
+ struct ttm_buffer_object *tmp;
+ struct ttm_bo_user_object *user_bo;
+ uint32_t flags;
+ int ret = 0;
+ struct ttm_mem_global *mem_glob = bdev->glob->mem_glob;
+ struct ttm_placement placement = default_placement;
+ size_t acc_size =
+ ttm_pl_size(bdev, (req->size + PAGE_SIZE - 1) >> PAGE_SHIFT);
+ ret = ttm_mem_global_alloc(mem_glob, acc_size, false, false);
+ if (unlikely(ret != 0))
+ return ret;
+
+ flags = req->placement;
+ user_bo = kzalloc(sizeof(*user_bo), GFP_KERNEL);
+ if (unlikely(user_bo == NULL)) {
+ ttm_mem_global_free(mem_glob, acc_size);
+ return -ENOMEM;
+ }
+
+ bo = &user_bo->bo;
+ ret = ttm_read_lock(lock, true);
+ if (unlikely(ret != 0)) {
+ ttm_mem_global_free(mem_glob, acc_size);
+ kfree(user_bo);
+ return ret;
+ }
+
+ placement.num_placement = 1;
+ placement.placement = &flags;
+
+ if ((flags & TTM_PL_MASK_CACHING) == 0)
+ flags |= TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED;
+
+ ret = ttm_bo_init(bdev, bo, req->size,
+ ttm_bo_type_device, &placement,
+ req->page_alignment, 0, true,
+ NULL, acc_size, &ttm_bo_user_destroy);
+ ttm_read_unlock(lock);
+
+ /*
+ * Note that the ttm_buffer_object_init function
+ * would've called the destroy function on failure!!
+ */
+
+ if (unlikely(ret != 0))
+ goto out;
+
+ tmp = ttm_bo_reference(bo);
+ ret = ttm_base_object_init(tfile, &user_bo->base,
+ flags & TTM_PL_FLAG_SHARED,
+ ttm_buffer_type,
+ &ttm_bo_user_release,
+ &ttm_bo_user_ref_release);
+ if (unlikely(ret != 0))
+ goto out_err;
+
+ spin_lock(&bo->bdev->fence_lock);
+ ttm_pl_fill_rep(bo, rep);
+ spin_unlock(&bo->bdev->fence_lock);
+ ttm_bo_unref(&bo);
+out:
+ return 0;
+out_err:
+ ttm_bo_unref(&tmp);
+ ttm_bo_unref(&bo);
+ return ret;
+}
+
+int ttm_pl_ub_create_ioctl(struct ttm_object_file *tfile,
+ struct ttm_bo_device *bdev,
+ struct ttm_lock *lock, void *data)
+{
+ union ttm_pl_create_ub_arg *arg = data;
+ struct ttm_pl_create_ub_req *req = &arg->req;
+ struct ttm_pl_rep *rep = &arg->rep;
+ struct ttm_buffer_object *bo;
+ struct ttm_buffer_object *tmp;
+ struct ttm_bo_user_object *user_bo;
+ uint32_t flags;
+ int ret = 0;
+ struct ttm_mem_global *mem_glob = bdev->glob->mem_glob;
+ struct ttm_placement placement = default_placement;
+ size_t acc_size =
+ ttm_pl_size(bdev, (req->size + PAGE_SIZE - 1) >> PAGE_SHIFT);
+ ret = ttm_mem_global_alloc(mem_glob, acc_size, false, false);
+ if (unlikely(ret != 0))
+ return ret;
+
+ flags = req->placement;
+ user_bo = kzalloc(sizeof(*user_bo), GFP_KERNEL);
+ if (unlikely(user_bo == NULL)) {
+ ttm_mem_global_free(mem_glob, acc_size);
+ return -ENOMEM;
+ }
+ ret = ttm_read_lock(lock, true);
+ if (unlikely(ret != 0)) {
+ ttm_mem_global_free(mem_glob, acc_size);
+ kfree(user_bo);
+ return ret;
+ }
+ bo = &user_bo->bo;
+
+ placement.num_placement = 1;
+ placement.placement = &flags;
+
+ ret = ttm_bo_init(bdev,
+ bo,
+ req->size,
+ ttm_bo_type_user,
+ &placement,
+ req->page_alignment,
+ req->user_address,
+ true,
+ NULL,
+ acc_size,
+ &ttm_bo_user_destroy);
+
+ /*
+ * Note that the ttm_buffer_object_init function
+ * would've called the destroy function on failure!!
+ */
+ ttm_read_unlock(lock);
+ if (unlikely(ret != 0))
+ goto out;
+
+ tmp = ttm_bo_reference(bo);
+ ret = ttm_base_object_init(tfile, &user_bo->base,
+ flags & TTM_PL_FLAG_SHARED,
+ ttm_buffer_type,
+ &ttm_bo_user_release,
+ &ttm_bo_user_ref_release);
+ if (unlikely(ret != 0))
+ goto out_err;
+
+ spin_lock(&bo->bdev->fence_lock);
+ ttm_pl_fill_rep(bo, rep);
+ spin_unlock(&bo->bdev->fence_lock);
+ ttm_bo_unref(&bo);
+out:
+ return 0;
+out_err:
+ ttm_bo_unref(&tmp);
+ ttm_bo_unref(&bo);
+ return ret;
+}
+
+int ttm_pl_reference_ioctl(struct ttm_object_file *tfile, void *data)
+{
+ union ttm_pl_reference_arg *arg = data;
+ struct ttm_pl_rep *rep = &arg->rep;
+ struct ttm_bo_user_object *user_bo;
+ struct ttm_buffer_object *bo;
+ struct ttm_base_object *base;
+ int ret;
+
+ user_bo = ttm_bo_user_lookup(tfile, arg->req.handle);
+ if (unlikely(user_bo == NULL)) {
+ printk(KERN_ERR "Could not reference buffer object.\n");
+ return -EINVAL;
+ }
+
+ bo = &user_bo->bo;
+ ret = ttm_ref_object_add(tfile, &user_bo->base, TTM_REF_USAGE, NULL);
+ if (unlikely(ret != 0)) {
+ printk(KERN_ERR
+ "Could not add a reference to buffer object.\n");
+ goto out;
+ }
+
+ spin_lock(&bo->bdev->fence_lock);
+ ttm_pl_fill_rep(bo, rep);
+ spin_unlock(&bo->bdev->fence_lock);
+
+out:
+ base = &user_bo->base;
+ ttm_base_object_unref(&base);
+ return ret;
+}
+
+int ttm_pl_unref_ioctl(struct ttm_object_file *tfile, void *data)
+{
+ struct ttm_pl_reference_req *arg = data;
+
+ return ttm_ref_object_base_unref(tfile, arg->handle, TTM_REF_USAGE);
+}
+
+int ttm_pl_synccpu_ioctl(struct ttm_object_file *tfile, void *data)
+{
+ struct ttm_pl_synccpu_arg *arg = data;
+ struct ttm_bo_user_object *user_bo;
+ struct ttm_buffer_object *bo;
+ struct ttm_base_object *base;
+ bool existed;
+ int ret;
+
+ switch (arg->op) {
+ case TTM_PL_SYNCCPU_OP_GRAB:
+ user_bo = ttm_bo_user_lookup(tfile, arg->handle);
+ if (unlikely(user_bo == NULL)) {
+ printk(KERN_ERR
+ "Could not find buffer object for synccpu.\n");
+ return -EINVAL;
+ }
+ bo = &user_bo->bo;
+ base = &user_bo->base;
+ ret = ttm_bo_synccpu_write_grab(bo,
+ arg->access_mode &
+ TTM_PL_SYNCCPU_MODE_NO_BLOCK);
+ if (unlikely(ret != 0)) {
+ ttm_base_object_unref(&base);
+ goto out;
+ }
+ ret = ttm_ref_object_add(tfile, &user_bo->base,
+ TTM_REF_SYNCCPU_WRITE, &existed);
+ if (existed || ret != 0)
+ ttm_bo_synccpu_write_release(bo);
+ ttm_base_object_unref(&base);
+ break;
+ case TTM_PL_SYNCCPU_OP_RELEASE:
+ ret = ttm_ref_object_base_unref(tfile, arg->handle,
+ TTM_REF_SYNCCPU_WRITE);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+out:
+ return ret;
+}
+
+int ttm_pl_setstatus_ioctl(struct ttm_object_file *tfile,
+ struct ttm_lock *lock, void *data)
+{
+ union ttm_pl_setstatus_arg *arg = data;
+ struct ttm_pl_setstatus_req *req = &arg->req;
+ struct ttm_pl_rep *rep = &arg->rep;
+ struct ttm_buffer_object *bo;
+ struct ttm_bo_device *bdev;
+ struct ttm_placement placement = default_placement;
+ uint32_t flags[2];
+ int ret;
+
+ bo = ttm_buffer_object_lookup(tfile, req->handle);
+ if (unlikely(bo == NULL)) {
+ printk(KERN_ERR
+ "Could not find buffer object for setstatus.\n");
+ return -EINVAL;
+ }
+
+ bdev = bo->bdev;
+
+ ret = ttm_read_lock(lock, true);
+ if (unlikely(ret != 0))
+ goto out_err0;
+
+ ret = ttm_bo_reserve(bo, true, false, false, 0);
+ if (unlikely(ret != 0))
+ goto out_err1;
+
+ ret = ttm_bo_wait_cpu(bo, false);
+ if (unlikely(ret != 0))
+ goto out_err2;
+
+ flags[0] = req->set_placement;
+ flags[1] = req->clr_placement;
+
+ placement.num_placement = 2;
+ placement.placement = flags;
+
+ spin_lock(&bo->bdev->fence_lock);
+
+ ret = psb_ttm_bo_check_placement(bo, &placement);
+ if (unlikely(ret != 0))
+ goto out_err2;
+
+ placement.num_placement = 1;
+ flags[0] = (req->set_placement | bo->mem.placement) & ~req->clr_placement;
+
+ ret = ttm_bo_validate(bo, &placement, true, false, false);
+ if (unlikely(ret != 0))
+ goto out_err2;
+
+ ttm_pl_fill_rep(bo, rep);
+out_err2:
+ spin_unlock(&bo->bdev->fence_lock);
+ ttm_bo_unreserve(bo);
+out_err1:
+ ttm_read_unlock(lock);
+out_err0:
+ ttm_bo_unref(&bo);
+ return ret;
+}
+
+static int psb_ttm_bo_block_reservation(struct ttm_buffer_object *bo, bool interruptible,
+ bool no_wait)
+{
+ int ret;
+
+ while (unlikely(atomic_cmpxchg(&bo->reserved, 0, 1) != 0)) {
+ if (no_wait)
+ return -EBUSY;
+ else if (interruptible) {
+ ret = wait_event_interruptible
+ (bo->event_queue, atomic_read(&bo->reserved) == 0);
+ if (unlikely(ret != 0))
+ return -ERESTART;
+ } else {
+ wait_event(bo->event_queue,
+ atomic_read(&bo->reserved) == 0);
+ }
+ }
+ return 0;
+}
+
+static void psb_ttm_bo_unblock_reservation(struct ttm_buffer_object *bo)
+{
+ atomic_set(&bo->reserved, 0);
+ wake_up_all(&bo->event_queue);
+}
+
+int ttm_pl_waitidle_ioctl(struct ttm_object_file *tfile, void *data)
+{
+ struct ttm_pl_waitidle_arg *arg = data;
+ struct ttm_buffer_object *bo;
+ int ret;
+
+ bo = ttm_buffer_object_lookup(tfile, arg->handle);
+ if (unlikely(bo == NULL)) {
+ printk(KERN_ERR "Could not find buffer object for waitidle.\n");
+ return -EINVAL;
+ }
+
+ ret =
+ psb_ttm_bo_block_reservation(bo, true,
+ arg->mode & TTM_PL_WAITIDLE_MODE_NO_BLOCK);
+ if (unlikely(ret != 0))
+ goto out;
+ spin_lock(&bo->bdev->fence_lock);
+ ret = ttm_bo_wait(bo,
+ arg->mode & TTM_PL_WAITIDLE_MODE_LAZY,
+ true, arg->mode & TTM_PL_WAITIDLE_MODE_NO_BLOCK);
+ spin_unlock(&bo->bdev->fence_lock);
+ psb_ttm_bo_unblock_reservation(bo);
+out:
+ ttm_bo_unref(&bo);
+ return ret;
+}
+
+int ttm_pl_verify_access(struct ttm_buffer_object *bo,
+ struct ttm_object_file *tfile)
+{
+ struct ttm_bo_user_object *ubo;
+
+ /*
+ * Check bo subclass.
+ */
+
+ if (unlikely(bo->destroy != &ttm_bo_user_destroy))
+ return -EPERM;
+
+ ubo = container_of(bo, struct ttm_bo_user_object, bo);
+ if (likely(ubo->base.shareable || ubo->base.tfile == tfile))
+ return 0;
+
+ return -EPERM;
+}
--- /dev/null
+/**************************************************************************
+ *
+ * Copyright 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA
+ * All Rights Reserved.
+ * Copyright (c) 2009 VMware, Inc., Palo Alto, CA., USA
+ * 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 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.
+ *
+ **************************************************************************/
+/*
+ * Authors
+ * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+ */
+
+#ifndef _TTM_PLACEMENT_USER_H_
+#define _TTM_PLACEMENT_USER_H_
+
+#if !defined(__KERNEL__) && !defined(_KERNEL)
+#include <stdint.h>
+#else
+#include <linux/kernel.h>
+#endif
+
+#include "ttm/ttm_placement.h"
+
+#define TTM_PLACEMENT_MAJOR 0
+#define TTM_PLACEMENT_MINOR 1
+#define TTM_PLACEMENT_PL 0
+#define TTM_PLACEMENT_DATE "080819"
+
+/**
+ * struct ttm_pl_create_req
+ *
+ * @size: The buffer object size.
+ * @placement: Flags that indicate initial acceptable
+ * placement.
+ * @page_alignment: Required alignment in pages.
+ *
+ * Input to the TTM_BO_CREATE ioctl.
+ */
+
+struct ttm_pl_create_req {
+ uint64_t size;
+ uint32_t placement;
+ uint32_t page_alignment;
+};
+
+/**
+ * struct ttm_pl_create_ub_req
+ *
+ * @size: The buffer object size.
+ * @user_address: User-space address of the memory area that
+ * should be used to back the buffer object cast to 64-bit.
+ * @placement: Flags that indicate initial acceptable
+ * placement.
+ * @page_alignment: Required alignment in pages.
+ *
+ * Input to the TTM_BO_CREATE_UB ioctl.
+ */
+
+struct ttm_pl_create_ub_req {
+ uint64_t size;
+ uint64_t user_address;
+ uint32_t placement;
+ uint32_t page_alignment;
+};
+
+/**
+ * struct ttm_pl_rep
+ *
+ * @gpu_offset: The current offset into the memory region used.
+ * This can be used directly by the GPU if there are no
+ * additional GPU mapping procedures used by the driver.
+ *
+ * @bo_size: Actual buffer object size.
+ *
+ * @map_handle: Offset into the device address space.
+ * Used for map, seek, read, write. This will never change
+ * during the lifetime of an object.
+ *
+ * @placement: Flag indicating the placement status of
+ * the buffer object using the TTM_PL flags above.
+ *
+ * @sync_object_arg: Used for user-space synchronization and
+ * depends on the synchronization model used. If fences are
+ * used, this is the buffer_object::fence_type_mask
+ *
+ * Output from the TTM_PL_CREATE and TTM_PL_REFERENCE, and
+ * TTM_PL_SETSTATUS ioctls.
+ */
+
+struct ttm_pl_rep {
+ uint64_t gpu_offset;
+ uint64_t bo_size;
+ uint64_t map_handle;
+ uint32_t placement;
+ uint32_t handle;
+ uint32_t sync_object_arg;
+ uint32_t pad64;
+};
+
+/**
+ * struct ttm_pl_setstatus_req
+ *
+ * @set_placement: Placement flags to set.
+ *
+ * @clr_placement: Placement flags to clear.
+ *
+ * @handle: The object handle
+ *
+ * Input to the TTM_PL_SETSTATUS ioctl.
+ */
+
+struct ttm_pl_setstatus_req {
+ uint32_t set_placement;
+ uint32_t clr_placement;
+ uint32_t handle;
+ uint32_t pad64;
+};
+
+/**
+ * struct ttm_pl_reference_req
+ *
+ * @handle: The object to put a reference on.
+ *
+ * Input to the TTM_PL_REFERENCE and the TTM_PL_UNREFERENCE ioctls.
+ */
+
+struct ttm_pl_reference_req {
+ uint32_t handle;
+ uint32_t pad64;
+};
+
+/*
+ * ACCESS mode flags for SYNCCPU.
+ *
+ * TTM_SYNCCPU_MODE_READ will guarantee that the GPU is not
+ * writing to the buffer.
+ *
+ * TTM_SYNCCPU_MODE_WRITE will guarantee that the GPU is not
+ * accessing the buffer.
+ *
+ * TTM_SYNCCPU_MODE_NO_BLOCK makes sure the call does not wait
+ * for GPU accesses to finish but return -EBUSY.
+ *
+ * TTM_SYNCCPU_MODE_TRYCACHED Try to place the buffer in cacheable
+ * memory while synchronized for CPU.
+ */
+
+#define TTM_PL_SYNCCPU_MODE_READ TTM_ACCESS_READ
+#define TTM_PL_SYNCCPU_MODE_WRITE TTM_ACCESS_WRITE
+#define TTM_PL_SYNCCPU_MODE_NO_BLOCK (1 << 2)
+#define TTM_PL_SYNCCPU_MODE_TRYCACHED (1 << 3)
+
+/**
+ * struct ttm_pl_synccpu_arg
+ *
+ * @handle: The object to synchronize.
+ *
+ * @access_mode: access mode indicated by the
+ * TTM_SYNCCPU_MODE flags.
+ *
+ * @op: indicates whether to grab or release the
+ * buffer for cpu usage.
+ *
+ * Input to the TTM_PL_SYNCCPU ioctl.
+ */
+
+struct ttm_pl_synccpu_arg {
+ uint32_t handle;
+ uint32_t access_mode;
+ enum {
+ TTM_PL_SYNCCPU_OP_GRAB,
+ TTM_PL_SYNCCPU_OP_RELEASE
+ } op;
+ uint32_t pad64;
+};
+
+/*
+ * Waiting mode flags for the TTM_BO_WAITIDLE ioctl.
+ *
+ * TTM_WAITIDLE_MODE_LAZY: Allow for sleeps during polling
+ * wait.
+ *
+ * TTM_WAITIDLE_MODE_NO_BLOCK: Don't block waiting for GPU,
+ * but return -EBUSY if the buffer is busy.
+ */
+
+#define TTM_PL_WAITIDLE_MODE_LAZY (1 << 0)
+#define TTM_PL_WAITIDLE_MODE_NO_BLOCK (1 << 1)
+
+/**
+ * struct ttm_waitidle_arg
+ *
+ * @handle: The object to synchronize.
+ *
+ * @mode: wait mode indicated by the
+ * TTM_SYNCCPU_MODE flags.
+ *
+ * Argument to the TTM_BO_WAITIDLE ioctl.
+ */
+
+struct ttm_pl_waitidle_arg {
+ uint32_t handle;
+ uint32_t mode;
+};
+
+union ttm_pl_create_arg {
+ struct ttm_pl_create_req req;
+ struct ttm_pl_rep rep;
+};
+
+union ttm_pl_reference_arg {
+ struct ttm_pl_reference_req req;
+ struct ttm_pl_rep rep;
+};
+
+union ttm_pl_setstatus_arg {
+ struct ttm_pl_setstatus_req req;
+ struct ttm_pl_rep rep;
+};
+
+union ttm_pl_create_ub_arg {
+ struct ttm_pl_create_ub_req req;
+ struct ttm_pl_rep rep;
+};
+
+/*
+ * Ioctl offsets.
+ */
+
+#define TTM_PL_CREATE 0x00
+#define TTM_PL_REFERENCE 0x01
+#define TTM_PL_UNREF 0x02
+#define TTM_PL_SYNCCPU 0x03
+#define TTM_PL_WAITIDLE 0x04
+#define TTM_PL_SETSTATUS 0x05
+#define TTM_PL_CREATE_UB 0x06
+
+#endif
--- /dev/null
+/**************************************************************************
+ *
+ * Copyright (c) 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA
+ * All Rights Reserved.
+ * Copyright (c) 2009 VMware, Inc., Palo Alto, CA., USA
+ * 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 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.
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
+ */
+
+#ifndef _TTM_USEROBJ_API_H_
+#define _TTM_USEROBJ_API_H_
+
+#include "psb_ttm_placement_user.h"
+#include "psb_ttm_fence_user.h"
+#include "ttm/ttm_object.h"
+#include "psb_ttm_fence_api.h"
+#include "ttm/ttm_bo_api.h"
+
+struct ttm_lock;
+
+/*
+ * User ioctls.
+ */
+
+extern int ttm_pl_create_ioctl(struct ttm_object_file *tfile,
+ struct ttm_bo_device *bdev,
+ struct ttm_lock *lock, void *data);
+extern int ttm_pl_ub_create_ioctl(struct ttm_object_file *tfile,
+ struct ttm_bo_device *bdev,
+ struct ttm_lock *lock, void *data);
+extern int ttm_pl_reference_ioctl(struct ttm_object_file *tfile, void *data);
+extern int ttm_pl_unref_ioctl(struct ttm_object_file *tfile, void *data);
+extern int ttm_pl_synccpu_ioctl(struct ttm_object_file *tfile, void *data);
+extern int ttm_pl_setstatus_ioctl(struct ttm_object_file *tfile,
+ struct ttm_lock *lock, void *data);
+extern int ttm_pl_waitidle_ioctl(struct ttm_object_file *tfile, void *data);
+extern int ttm_fence_signaled_ioctl(struct ttm_object_file *tfile, void *data);
+extern int ttm_fence_finish_ioctl(struct ttm_object_file *tfile, void *data);
+extern int ttm_fence_unref_ioctl(struct ttm_object_file *tfile, void *data);
+
+extern int
+ttm_fence_user_create(struct ttm_fence_device *fdev,
+ struct ttm_object_file *tfile,
+ uint32_t fence_class,
+ uint32_t fence_types,
+ uint32_t create_flags,
+ struct ttm_fence_object **fence, uint32_t * user_handle);
+
+extern struct ttm_buffer_object *ttm_buffer_object_lookup(struct ttm_object_file
+ *tfile,
+ uint32_t handle);
+
+extern int
+ttm_pl_verify_access(struct ttm_buffer_object *bo,
+ struct ttm_object_file *tfile);
+
+extern int ttm_buffer_object_create(struct ttm_bo_device *bdev,
+ unsigned long size,
+ enum ttm_bo_type type,
+ uint32_t flags,
+ uint32_t page_alignment,
+ unsigned long buffer_start,
+ bool interruptible,
+ struct file *persistant_swap_storage,
+ struct ttm_buffer_object **p_bo);
+
+extern int psb_ttm_bo_check_placement(struct ttm_buffer_object *bo,
+ struct ttm_placement *placement);
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2009, Intel Corporation.
+ *
+ * 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 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.
+ *
+ * Author:binglin.chen@intel.com
+ */
+
+#include "topaz_power.h"
+#include "pnw_topaz.h"
+#include "psb_drv.h"
+#include "services_headers.h"
+#include "sysconfig.h"
+#include "psb_powermgmt.h"
+
+static PVRSRV_ERROR DevInitTOPAZPart1(IMG_VOID *pvDeviceNode)
+{
+#if 1
+ PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvDeviceNode;
+ PVRSRV_ERROR eError;
+ PVRSRV_DEV_POWER_STATE eDefaultPowerState;
+
+ /* register power operation function */
+ /* FIXME: this should be in part2 init function, but
+ * currently here only OSPM needs IMG device... */
+ eDefaultPowerState = PVRSRV_DEV_POWER_STATE_OFF;
+ eError = PVRSRVRegisterPowerDevice(psDeviceNode->sDevId.ui32DeviceIndex,
+ TOPAZPrePowerState,
+ TOPAZPostPowerState,
+ TOPAZPreClockSpeedChange,
+ TOPAZPostClockSpeedChange,
+ (IMG_HANDLE)psDeviceNode,
+ PVRSRV_DEV_POWER_STATE_ON,
+ eDefaultPowerState);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR, "DevInitTOPAZPart1: failed to "
+ "register device with power manager"));
+ return eError;
+ }
+#endif
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR DevDeInitTOPAZ(IMG_VOID *pvDeviceNode)
+{
+#if 1
+ PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvDeviceNode;
+ PVRSRV_ERROR eError;
+
+ /* should deinit all resource */
+
+ eError = PVRSRVRemovePowerDevice(psDeviceNode->sDevId.ui32DeviceIndex);
+ if (eError != PVRSRV_OK)
+ return eError;
+#endif
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR TOPAZDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ /* version check */
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR TOPAZRegisterDevice(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ psDeviceNode->sDevId.eDeviceType = PVRSRV_DEVICE_TYPE_TOPAZ;
+ psDeviceNode->sDevId.eDeviceClass = PVRSRV_DEVICE_CLASS_VIDEO;
+
+ psDeviceNode->pfnInitDevice = DevInitTOPAZPart1;
+ psDeviceNode->pfnDeInitDevice = DevDeInitTOPAZ;
+
+ psDeviceNode->pfnInitDeviceCompatCheck = TOPAZDevInitCompatCheck;
+
+ psDeviceNode->pfnDeviceISR = pnw_topaz_interrupt;
+ psDeviceNode->pvISRData = (IMG_VOID *)gpDrmDevice;
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR TOPAZPrePowerState(IMG_HANDLE hDevHandle,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+#if 1
+ /* ask for a change not power on*/
+ if ((eNewPowerState != eCurrentPowerState) &&
+ (eNewPowerState != PVRSRV_DEV_POWER_STATE_ON)) {
+ struct drm_psb_private *dev_priv = gpDrmDevice->dev_private;
+ struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+ PNW_TOPAZ_NEW_PMSTATE(gpDrmDevice, topaz_priv, PSB_PMSTATE_POWERDOWN);
+
+ /* context save */
+ /* context save require irq disable first */
+ psb_irq_uninstall_islands(gpDrmDevice, OSPM_VIDEO_ENC_ISLAND);
+ pnw_topaz_save_mtx_state(gpDrmDevice);
+
+ /* internally close the device */
+
+ /* ask for power off */
+ if (eNewPowerState == PVRSRV_DEV_POWER_STATE_OFF) {
+ /* here will deinitialize the driver if needed */
+ /* FIXME: according to latest topaz runtime_pm suspend/resume
+ * 6f78a5b61be55d222fa3880008d2198efa7713bf by Austin, Yuan
+ * 1) Remove map_topaz_reg/unmap_topaz_reg for suspend/resume
+ * no map/umap topaz register is needed */
+ //pnw_unmap_topaz_reg(gpDrmDevice);
+ } else {
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "%s no action for transform from %d to %d",
+ __func__,
+ eCurrentPowerState,
+ eNewPowerState));
+ }
+ }
+#endif
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR TOPAZPostPowerState(IMG_HANDLE hDevHandle,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+#if 1
+ /* if ask for change & current status is not on */
+ if ((eNewPowerState != eCurrentPowerState) &&
+ (eCurrentPowerState != PVRSRV_DEV_POWER_STATE_ON)) {
+ /* internally open device */
+ struct drm_psb_private *dev_priv = gpDrmDevice->dev_private;
+ struct pnw_topaz_private *topaz_priv = dev_priv->topaz_private;
+ PNW_TOPAZ_NEW_PMSTATE(gpDrmDevice, topaz_priv, PSB_PMSTATE_POWERUP);
+
+ if (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_OFF) {
+ /* here will initialize the driver if needed */
+ /* FIXME: according to latest topaz runtime_pm suspend/resume
+ * 6f78a5b61be55d222fa3880008d2198efa7713bf by Austin, Yuan
+ * 1) Remove map_topaz_reg/unmap_topaz_reg for suspend/resume
+ * no map/umap topaz register is needed */
+ //pnw_map_topaz_reg(gpDrmDevice);
+ } else {
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "%s no action for transform from %d to %d",
+ __func__,
+ eCurrentPowerState,
+ eNewPowerState));
+ }
+
+ /* context restore */
+ psb_irq_uninstall_islands(gpDrmDevice, OSPM_VIDEO_ENC_ISLAND);
+ pnw_topaz_restore_mtx_state(gpDrmDevice);
+ psb_irq_preinstall_islands(gpDrmDevice, OSPM_VIDEO_ENC_ISLAND);
+ psb_irq_postinstall_islands(gpDrmDevice, OSPM_VIDEO_ENC_ISLAND);
+ }
+#endif
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR TOPAZPreClockSpeedChange(IMG_HANDLE hDevHandle,
+ IMG_BOOL bIdleDevice,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR TOPAZPostClockSpeedChange(IMG_HANDLE hDevHandle,
+ IMG_BOOL bIdleDevice,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+ return PVRSRV_OK;
+}
--- /dev/null
+/*
+** topaz_power.h
+** Login : <binglin.chen@intel.com>
+** Started on Mon Nov 16 13:31:42 2009 brady
+**
+** Copyright (C) 2009 brady
+** 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef TOPAZ_POWER_H_
+#define TOPAZ_POWER_H_
+
+#include "services_headers.h"
+#include "sysconfig.h"
+
+/* function define */
+PVRSRV_ERROR TOPAZRegisterDevice(PVRSRV_DEVICE_NODE *psDeviceNode);
+PVRSRV_ERROR TOPAZDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+/* power function define */
+PVRSRV_ERROR TOPAZPrePowerState(
+ IMG_HANDLE hDevHandle,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+PVRSRV_ERROR TOPAZPostPowerState(
+ IMG_HANDLE hDevHandle,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+PVRSRV_ERROR TOPAZPreClockSpeedChange(
+ IMG_HANDLE hDevHandle,
+ IMG_BOOL bIdleDevice,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+PVRSRV_ERROR TOPAZPostClockSpeedChange(
+ IMG_HANDLE hDevHandle,
+ IMG_BOOL bIdleDevice,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+PVRSRV_ERROR TOPAZInitOSPM(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+#endif /* !TOPAZ_POWER_H_ */
--- /dev/null
+# Makefile for the drm device driver. This driver provides support for the
+# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
+
+INCDIR=drivers/staging/mrst
+
+include_dirs := \
+ -I$(INCDIR)/pvr \
+ -I$(INCDIR)/pvr/include4 \
+ -I$(INCDIR)/pvr/services4/include \
+ -I$(INCDIR)/pvr/services4/include/env/linux \
+ -I$(INCDIR)/pvr/services4/3rdparty/linux_framebuffer_mrst \
+ -I$(INCDIR)/pvr/services4/srvkm/env/linux \
+ -I$(INCDIR)/pvr/services4/srvkm/include \
+ -I$(INCDIR)/pvr/services4/srvkm/bridged \
+ -I$(INCDIR)/pvr/services4/srvkm/common \
+ -I$(INCDIR)/pvr/services4/system/include \
+ -I$(INCDIR)/pvr/services4/srvkm/hwdefs \
+ -I$(INCDIR)/pvr/services4/srvkm/bridged/sgx \
+ -I$(INCDIR)/pvr/services4/srvkm/devices/sgx \
+ -I$(INCDIR)/ \
+ -I$(INCDIR)/drv \
+ -I$(INCDIR)/bc_video \
+ -I$(INCDIR)/imgv \
+ -Iinclude/linux \
+ -Iinclude/drm
+
+ccflags-y += $(include_dirs)
+ccflags-y += -I$(INCDIR)/pvr/services4/system/unified -DSGX540 -DSUPPORT_SGX540 -DSGX_CORE_REV=121
+
+ccflags-y += \
+ -DLINUX \
+ -DPVR_BUILD_DIR="\"pc_i686_moorestown_linux\"" \
+ -DSERVICES4 \
+ -D_XOPEN_SOURCE=600 \
+ -DPVR2D_VALIDATE_INPUT_PARAMS \
+ -DDISPLAY_CONTROLLER=mrstlfb \
+ -UDEBUG_LOG_PATH_TRUNCATE \
+ -DSUPPORT_SRVINIT \
+ -DSUPPORT_SGX \
+ -DSUPPORT_LINUX_X86_WRITECOMBINE \
+ -DTRANSFER_QUEUE \
+ -DSUPPORT_DRI_DRM \
+ -DSUPPORT_DRI_DRM_EXT \
+ -DSYS_USING_INTERRUPTS \
+ -DSUPPORT_HW_RECOVERY \
+ -DSUPPORT_ACTIVE_POWER_MANAGEMENT \
+ -DPVR_SECURE_HANDLES \
+ -DUSE_PTHREADS \
+ -DSUPPORT_SGX_EVENT_OBJECT \
+ -DSUPPORT_SGX_HWPERF \
+ -DSUPPORT_SGX_LOW_LATENCY_SCHEDULING \
+ -DSUPPORT_LINUX_X86_PAT \
+ -DPVR_PROC_USE_SEQ_FILE \
+ -DSUPPORT_CACHE_LINE_FLUSH \
+ -DSUPPORT_CPU_CACHED_BUFFERS \
+ -DDEBUG_MESA_OGL_TRACE \
+ -DDISABLE_PM \
+ -DSUPPORT_SGX_NEW_STATUS_VALS \
+ -DSUPPORT_PERCONTEXT_PB \
+ -DDRM_PVR_USE_INTEL_FB \
+ -DSUPPORT_MEMINFO_IDS
+
+GL3_EXTERNAL_SYSTEM_CACHE ?=0
+ifeq ($(GL3_EXTERNAL_SYSTEM_CACHE),1)
+ SUPPORT_EXTERNAL_SYSTEM_CACHE = y
+ CONFIG_MDFD_GL3 = y
+else
+ SUPPORT_EXTERNAL_SYSTEM_CACHE =
+ CONFIG_MDFD_GL3 =
+endif
+ccflags-$(SUPPORT_EXTERNAL_SYSTEM_CACHE) += -DSUPPORT_EXTERNAL_SYSTEM_CACHE -DCONFIG_MDFD_GL3
+
+PVRSRV_RESOURCE_PROFILING =
+PERPROC_LIST =
+RES_MAN_EXTEND =
+PVRSRV_OS_MEM_INFO =
+
+ccflags-$(PVRSRV_RESOURCE_PROFILING) += -DPVRSRV_RESOURCE_PROFILING
+ccflags-$(PERPROC_LIST) += -DPERPROC_LIST
+ccflags-$(RES_MAN_EXTEND) += -DRES_MAN_EXTEND
+ccflags-$(PVRSRV_OS_MEM_INFO) += -DPVRSRV_OS_MEM_INFO
+
+ccflags-$(CONFIG_DRM_MID_RELEASE) += -DBUILD="\"release\"" -DPVR_BUILD_TYPE="\"release\"" -DRELEASE
+ccflags-$(CONFIG_DRM_MID_DEBUG) += -DBUILD="\"debug\"" -DPVR_BUILD_TYPE="\"debug\"" -DDEBUG -DDEBUG_LINUX_MEM_AREAS -DDEBUG_LINUX_MEMORY_ALLOCATIONS -DDEBUG_LINUX_MMAP_AREAS -DDEBUG_BRIDGE_KM
+ccflags-$(CONFIG_PCI_MSI) += -DCONFIG_PCI_MSI
+
+PVRDIR = ../pvr
+ENVDIR = ../pvr/services4/srvkm/env/linux
+COMMONDIR = ../pvr/services4/srvkm/common
+BRIDGEDDIR = ../pvr/services4/srvkm/bridged
+SGXDIR = ../pvr/services4/srvkm/devices/sgx
+FBDEVDIR = ../pvr/services4/3rdparty/linux_framebuffer_mrst
+DRMDRVDIR = ../drv
+SYSCONFIGDIR = ../pvr/services4/system/unified
+IMGVDIR = ../imgv
+BUFFER_CLASS_DIR = ../bc_video
+
+medfield_gfx-y += $(ENVDIR)/osfunc.o \
+ $(ENVDIR)/ossync.o \
+ $(ENVDIR)/mutils.o \
+ $(ENVDIR)/mmap.o \
+ $(ENVDIR)/module.o \
+ $(ENVDIR)/pdump.o \
+ $(ENVDIR)/proc.o \
+ $(ENVDIR)/pvr_bridge_k.o \
+ $(ENVDIR)/pvr_debug.o \
+ $(ENVDIR)/mm.o \
+ $(ENVDIR)/mutex.o \
+ $(ENVDIR)/event.o \
+ $(ENVDIR)/osperproc.o \
+ $(ENVDIR)/pvr_drm.o
+
+medfield_gfx-y += $(COMMONDIR)/buffer_manager.o \
+ $(COMMONDIR)/devicemem.o \
+ $(COMMONDIR)/deviceclass.o \
+ $(COMMONDIR)/handle.o \
+ $(COMMONDIR)/hash.o \
+ $(COMMONDIR)/metrics.o \
+ $(COMMONDIR)/pvrsrv.o \
+ $(COMMONDIR)/queue.o \
+ $(COMMONDIR)/ra.o \
+ $(COMMONDIR)/resman.o \
+ $(COMMONDIR)/power.o \
+ $(COMMONDIR)/mem.o \
+ $(COMMONDIR)/pdump_common.o \
+ $(COMMONDIR)/perproc.o \
+ $(COMMONDIR)/lists.o \
+ $(COMMONDIR)/mem_debug.o \
+ $(COMMONDIR)/osfunc_common.o
+
+medfield_gfx-y += $(BRIDGEDDIR)/bridged_support.o \
+ $(BRIDGEDDIR)/bridged_pvr_bridge.o \
+ $(BRIDGEDDIR)/sgx/bridged_sgx_bridge.o
+
+medfield_gfx-y += $(SYSCONFIGDIR)/sysconfig.o \
+ $(SYSCONFIGDIR)/sysutils.o \
+ $(SYSCONFIGDIR)/sys_pvr_drm_export.o
+
+medfield_gfx-y += $(SGXDIR)/sgxinit.o \
+ $(SGXDIR)/sgxpower.o \
+ $(SGXDIR)/sgxreset.o \
+ $(SGXDIR)/sgxutils.o \
+ $(SGXDIR)/sgxkick.o \
+ $(SGXDIR)/sgxtransfer.o \
+ $(SGXDIR)/mmu.o \
+ $(SGXDIR)/pb.o
+
+medfield_gfx-y += $(FBDEVDIR)/mrstlfb_displayclass.o \
+ $(FBDEVDIR)/mrstlfb_linux.o
+
+medfield_gfx-y += $(DRMDRVDIR)/psb_bl.o \
+ $(DRMDRVDIR)/psb_dpst.o \
+ $(DRMDRVDIR)/psb_drv.o \
+ $(DRMDRVDIR)/psb_fb.o \
+ $(DRMDRVDIR)/psb_gtt.o \
+ $(DRMDRVDIR)/psb_hotplug.o \
+ $(DRMDRVDIR)/psb_intel_display.o \
+ $(DRMDRVDIR)/psb_page_flip.o \
+ $(DRMDRVDIR)/mdfld_hdmi_audio.o \
+ $(DRMDRVDIR)/mdfld_msic.o \
+ $(DRMDRVDIR)/mdfld_intel_hdcp.o \
+ $(DRMDRVDIR)/psb_intel_hdmi.o \
+ $(DRMDRVDIR)/psb_intel_hdmi_i2c.o \
+ $(DRMDRVDIR)/psb_reset.o \
+ $(DRMDRVDIR)/psb_schedule.o \
+ $(DRMDRVDIR)/psb_sgx.o \
+ $(DRMDRVDIR)/psb_socket.o \
+ $(DRMDRVDIR)/psb_pvr_glue.o \
+ $(DRMDRVDIR)/psb_umevents.o \
+ $(DRMDRVDIR)/mdfld_dsi_dbi.o \
+ $(DRMDRVDIR)/mdfld_dsi_dpi.o \
+ $(DRMDRVDIR)/mdfld_dsi_output.o \
+ $(DRMDRVDIR)/mdfld_output.o \
+ $(DRMDRVDIR)/tpo_cmd.o \
+ $(DRMDRVDIR)/tpo_vid.o \
+ $(DRMDRVDIR)/tmd_vid.o \
+ $(DRMDRVDIR)/tc35876x-dsi-lvds.o \
+ $(DRMDRVDIR)/mdfld_dsi_pkg_sender.o
+
+medfield_gfx-y += \
+ $(IMGVDIR)/topaz_power.o \
+ $(IMGVDIR)/pnw_topaz.o \
+ $(IMGVDIR)/pnw_topazinit.o \
+ $(IMGVDIR)/psb_buffer.o \
+ $(IMGVDIR)/psb_fence.o \
+ $(IMGVDIR)/psb_mmu.o \
+ $(IMGVDIR)/psb_msvdx.o \
+ $(IMGVDIR)/msvdx_power.o \
+ $(IMGVDIR)/psb_msvdxinit.o \
+ $(IMGVDIR)/psb_ttm_glue.o \
+ $(IMGVDIR)/psb_ttm_fence.o \
+ $(IMGVDIR)/psb_ttm_fence_user.o \
+ $(IMGVDIR)/psb_ttm_placement_user.o
+
+medfield_gfx-$(CONFIG_MDFLD_DSI_DPU) += $(DRMDRVDIR)/mdfld_dsi_dbi_dpu.o
+
+medfield_gfx-$(CONFIG_MDFD_GL3) += $(DRMDRVDIR)/mdfld_gl3.o
+
+medfield_gfx-$(CONFIG_DEBUG_FS) += $(PVRDIR)/pvr_debugfs.o
+medfield_gfx-$(CONFIG_PVR_TRACE_CMD) += $(PVRDIR)/pvr_trace_cmd.o
+
+medfield_gfx-y += $(DRMDRVDIR)/psb_powermgmt.o $(DRMDRVDIR)/psb_irq.o
+
+medfield_gfx-y += $(BUFFER_CLASS_DIR)/bufferclass_video.o \
+ $(BUFFER_CLASS_DIR)/bufferclass_video_linux.o
+
+obj-$(CONFIG_DRM_MDFLD) += medfield_gfx.o
--- /dev/null
+
+This software is Copyright (C) 2008 Imagination Technologies Ltd.
+ All rights reserved.
+
+You may use, distribute and copy this software under the terms of
+GNU General Public License version 2, which is displayed below.
+
+-------------------------------------------------------------------------
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
+
+-------------------------------------------------------------------------
+
--- /dev/null
+
+SGX Embedded Systems DDK for the Linux kernel.
+Copyright (C) 2008 Imagination Technologies Ltd. All rights reserved.
+======================================================================
+
+This file covers how to build and install the Imagination Technologies
+SGX DDK for the Linux kernel.
+
+
+Build System Environment Variables
+-------------------------------------------
+
+The SGX DDK Build scripts depend on a number of environment variables
+being setup before compilation or installation of DDK software can
+commence:
+
+$DISCIMAGE
+The DDK Build scripts install files to the location specified by the
+DISCIMAGE environment variable, when the make install target is used.
+This should point to the target filesystem.
+$ export DISCIMAGE=/path/to/filesystem
+
+$KERNELDIR
+When building the SGX DDK kernel module, the build needs access
+to the headers of the Linux kernel
+$ export KERNELDIR=/path/to/kernel
+
+$PATH
+If a cross compiler is being used make sure the PATH environment variable
+includes the path to the toolchain
+$ export PATH=$PATH:/path/to/toolchain
+
+$CROSS_COMPILE
+Since the SGX DDK Build scripts are geared toward a cross-compilation
+workflow, the CROSS_COMPILE environment variable needs to be set
+$ export CROSS_COMPILE=toolchain-prefix-
+
+
+Build and Install Instructions
+-------------------------------------------
+
+The SGX DDK configures different target builds within directories under
+eurasiacon/build/linux/.
+
+The supported build targets are:
+
+ all Makes everything
+ clean Removes all intermediate files created by a build.
+ clobber Removes all binaries for all builds as well.
+ install Runs the install script generated by the build.
+
+The following variables may be set on the command line to influence a build.
+
+ BUILD The type of build being performed.
+ Alternatives are release, timing or debug.
+ CFLAGS Build dependent optimisations and debug information flags.
+ SILENT Determines whether text of commands is produced during build.
+
+To build for, change to the appropriate target directory, e.g.:
+$ cd eurasiacon/build/linux/platform/kbuild
+
+Issue the make command:
+$ make BUILD=debug all
+
+The DDK software must be installed by the root user. Become the root user:
+$ su
+
+Install the DDK software:
+$ make install
+
+Become an ordinary user again:
+$ exit
+
+
+
+
--- /dev/null
+
+SGX Embedded Systems DDK for Linux kernel.
+Copyright (C) 2008 Imagination Technologies Ltd. All rights reserved.
+======================================================================
+
+
+About
+-------------------------------------------
+
+This is the Imagination Technologies SGX DDK for the Linux kernel.
+
+
+License
+-------------------------------------------
+
+You may use, distribute and copy this software under the terms of
+GNU General Public License version 2.
+
+The full GNU General Public License version 2 is included in this
+distribution in the file called "COPYING".
+
+
+Build and Install Instructions
+-------------------------------------------
+
+For details see the "INSTALL" file.
+
+To build for, change to the appropriate target directory, e.g.:
+$ cd eurasiacon/build/linux/platform/kbuild
+
+Issue the make command:
+$ make BUILD=debug all
+
+The DDK software must be installed by the root user. Become the root user:
+$ su
+
+Install the DDK software:
+$ make install
+
+Become an ordinary user again:
+$ exit
+
+
+Contact information:
+-------------------------------------------
+
+Imagination Technologies Ltd. <gpl-support@imgtec.com>
+Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
--- /dev/null
+bin_pc_i686*
+tmp_pc_i686*
+host_pc_i686*
+binary_pc_i686*
+*.o
+*.o.cmd
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef _DBGDRVIF_
+#define _DBGDRVIF_
+
+
+#include "ioctldef.h"
+
+#define DEBUG_CAPMODE_FRAMED 0x00000001UL
+#define DEBUG_CAPMODE_CONTINUOUS 0x00000002UL
+#define DEBUG_CAPMODE_HOTKEY 0x00000004UL
+
+#define DEBUG_OUTMODE_STANDARDDBG 0x00000001UL
+#define DEBUG_OUTMODE_MONO 0x00000002UL
+#define DEBUG_OUTMODE_STREAMENABLE 0x00000004UL
+#define DEBUG_OUTMODE_ASYNC 0x00000008UL
+#define DEBUG_OUTMODE_SGXVGA 0x00000010UL
+
+#define DEBUG_FLAGS_USE_NONPAGED_MEM 0x00000001UL
+#define DEBUG_FLAGS_NO_BUF_EXPANDSION 0x00000002UL
+#define DEBUG_FLAGS_ENABLESAMPLE 0x00000004UL
+#define DEBUG_FLAGS_READONLY 0x00000008UL
+#define DEBUG_FLAGS_WRITEONLY 0x00000010UL
+
+#define DEBUG_FLAGS_TEXTSTREAM 0x80000000UL
+
+#define DEBUG_LEVEL_0 0x00000001UL
+#define DEBUG_LEVEL_1 0x00000003UL
+#define DEBUG_LEVEL_2 0x00000007UL
+#define DEBUG_LEVEL_3 0x0000000FUL
+#define DEBUG_LEVEL_4 0x0000001FUL
+#define DEBUG_LEVEL_5 0x0000003FUL
+#define DEBUG_LEVEL_6 0x0000007FUL
+#define DEBUG_LEVEL_7 0x000000FFUL
+#define DEBUG_LEVEL_8 0x000001FFUL
+#define DEBUG_LEVEL_9 0x000003FFUL
+#define DEBUG_LEVEL_10 0x000007FFUL
+#define DEBUG_LEVEL_11 0x00000FFFUL
+
+#define DEBUG_LEVEL_SEL0 0x00000001UL
+#define DEBUG_LEVEL_SEL1 0x00000002UL
+#define DEBUG_LEVEL_SEL2 0x00000004UL
+#define DEBUG_LEVEL_SEL3 0x00000008UL
+#define DEBUG_LEVEL_SEL4 0x00000010UL
+#define DEBUG_LEVEL_SEL5 0x00000020UL
+#define DEBUG_LEVEL_SEL6 0x00000040UL
+#define DEBUG_LEVEL_SEL7 0x00000080UL
+#define DEBUG_LEVEL_SEL8 0x00000100UL
+#define DEBUG_LEVEL_SEL9 0x00000200UL
+#define DEBUG_LEVEL_SEL10 0x00000400UL
+#define DEBUG_LEVEL_SEL11 0x00000800UL
+
+#define DEBUG_SERVICE_IOCTL_BASE 0x800UL
+#define DEBUG_SERVICE_CREATESTREAM CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x01, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_DESTROYSTREAM CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x02, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_GETSTREAM CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x03, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITESTRING CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x04, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_READSTRING CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x05, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITE CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x06, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_READ CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x07, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_SETDEBUGMODE CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x08, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_SETDEBUGOUTMODE CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x09, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_SETDEBUGLEVEL CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0A, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_SETFRAME CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0B, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_GETFRAME CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0C, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_OVERRIDEMODE CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0D, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_DEFAULTMODE CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0E, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_GETSERVICETABLE CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0F, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITE2 CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x10, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITESTRINGCM CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x11, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITECM CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x12, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_SETMARKER CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x13, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_GETMARKER CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x14, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_ISCAPTUREFRAME CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x15, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITELF CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x16, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_READLF CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x17, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WAITFOREVENT CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x18, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_SETCONNNOTIFY CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x19, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+
+typedef enum _DBG_EVENT_
+{
+ DBG_EVENT_STREAM_DATA = 1
+} DBG_EVENT;
+
+
+typedef struct _DBG_IN_CREATESTREAM_
+{
+ union
+ {
+ IMG_CHAR *pszName;
+ IMG_UINT64 ui64Name;
+ } u;
+ IMG_UINT32 ui32Pages;
+ IMG_UINT32 ui32CapMode;
+ IMG_UINT32 ui32OutMode;
+}DBG_IN_CREATESTREAM, *PDBG_IN_CREATESTREAM;
+
+typedef struct _DBG_IN_FINDSTREAM_
+{
+ union
+ {
+ IMG_CHAR *pszName;
+ IMG_UINT64 ui64Name;
+ }u;
+ IMG_BOOL bResetStream;
+}DBG_IN_FINDSTREAM, *PDBG_IN_FINDSTREAM;
+
+typedef struct _DBG_IN_WRITESTRING_
+{
+ union
+ {
+ IMG_CHAR *pszString;
+ IMG_UINT64 ui64String;
+ } u;
+ IMG_SID hStream;
+ IMG_UINT32 ui32Level;
+}DBG_IN_WRITESTRING, *PDBG_IN_WRITESTRING;
+
+typedef struct _DBG_IN_READSTRING_
+{
+ union
+ {
+ IMG_CHAR *pszString;
+ IMG_UINT64 ui64String;
+ } u;
+ IMG_SID hStream;
+ IMG_UINT32 ui32StringLen;
+} DBG_IN_READSTRING, *PDBG_IN_READSTRING;
+
+typedef struct _DBG_IN_SETDEBUGMODE_
+{
+ IMG_SID hStream;
+ IMG_UINT32 ui32Mode;
+ IMG_UINT32 ui32Start;
+ IMG_UINT32 ui32End;
+ IMG_UINT32 ui32SampleRate;
+} DBG_IN_SETDEBUGMODE, *PDBG_IN_SETDEBUGMODE;
+
+typedef struct _DBG_IN_SETDEBUGOUTMODE_
+{
+ IMG_SID hStream;
+ IMG_UINT32 ui32Mode;
+} DBG_IN_SETDEBUGOUTMODE, *PDBG_IN_SETDEBUGOUTMODE;
+
+typedef struct _DBG_IN_SETDEBUGLEVEL_
+{
+ IMG_SID hStream;
+ IMG_UINT32 ui32Level;
+} DBG_IN_SETDEBUGLEVEL, *PDBG_IN_SETDEBUGLEVEL;
+
+typedef struct _DBG_IN_SETFRAME_
+{
+ IMG_SID hStream;
+ IMG_UINT32 ui32Frame;
+} DBG_IN_SETFRAME, *PDBG_IN_SETFRAME;
+
+typedef struct _DBG_IN_WRITE_
+{
+ union
+ {
+ IMG_UINT8 *pui8InBuffer;
+ IMG_UINT64 ui64InBuffer;
+ } u;
+ IMG_SID hStream;
+ IMG_UINT32 ui32Level;
+ IMG_UINT32 ui32TransferSize;
+} DBG_IN_WRITE, *PDBG_IN_WRITE;
+
+typedef struct _DBG_IN_READ_
+{
+ union
+ {
+ IMG_UINT8 *pui8OutBuffer;
+ IMG_UINT64 ui64OutBuffer;
+ } u;
+ IMG_SID hStream;
+ IMG_BOOL bReadInitBuffer;
+ IMG_UINT32 ui32OutBufferSize;
+} DBG_IN_READ, *PDBG_IN_READ;
+
+typedef struct _DBG_IN_OVERRIDEMODE_
+{
+ IMG_SID hStream;
+ IMG_UINT32 ui32Mode;
+} DBG_IN_OVERRIDEMODE, *PDBG_IN_OVERRIDEMODE;
+
+typedef struct _DBG_IN_ISCAPTUREFRAME_
+{
+ IMG_SID hStream;
+ IMG_BOOL bCheckPreviousFrame;
+} DBG_IN_ISCAPTUREFRAME, *PDBG_IN_ISCAPTUREFRAME;
+
+typedef struct _DBG_IN_SETMARKER_
+{
+ IMG_SID hStream;
+ IMG_UINT32 ui32Marker;
+} DBG_IN_SETMARKER, *PDBG_IN_SETMARKER;
+
+typedef struct _DBG_IN_WRITE_LF_
+{
+ union
+ {
+ IMG_UINT8 *pui8InBuffer;
+ IMG_UINT64 ui64InBuffer;
+ } u;
+ IMG_UINT32 ui32Flags;
+ IMG_SID hStream;
+ IMG_UINT32 ui32Level;
+ IMG_UINT32 ui32BufferSize;
+} DBG_IN_WRITE_LF, *PDBG_IN_WRITE_LF;
+
+#define WRITELF_FLAGS_RESETBUF 0x00000001UL
+
+typedef struct _DBG_STREAM_CONTROL_
+{
+ IMG_BOOL bInitPhaseComplete;
+ IMG_UINT32 ui32Flags;
+
+ IMG_UINT32 ui32CapMode;
+ IMG_UINT32 ui32OutMode;
+ IMG_UINT32 ui32DebugLevel;
+ IMG_UINT32 ui32DefaultMode;
+ IMG_UINT32 ui32Start;
+ IMG_UINT32 ui32End;
+ IMG_UINT32 ui32Current;
+ IMG_UINT32 ui32SampleRate;
+ IMG_UINT32 ui32Reserved;
+} DBG_STREAM_CONTROL, *PDBG_STREAM_CONTROL;
+typedef struct _DBG_STREAM_
+{
+ struct _DBG_STREAM_ *psNext;
+ struct _DBG_STREAM_ *psInitStream;
+ DBG_STREAM_CONTROL *psCtrl;
+ IMG_BOOL bCircularAllowed;
+ IMG_PVOID pvBase;
+ IMG_UINT32 ui32Size;
+ IMG_UINT32 ui32RPtr;
+ IMG_UINT32 ui32WPtr;
+ IMG_UINT32 ui32DataWritten;
+ IMG_UINT32 ui32Marker;
+ IMG_UINT32 ui32InitPhaseWOff;
+
+ IMG_CHAR szName[30];
+} DBG_STREAM,*PDBG_STREAM;
+
+typedef struct _DBGKM_CONNECT_NOTIFIER_
+{
+ IMG_VOID (IMG_CALLCONV *pfnConnectNotifier) (IMG_VOID);
+} DBGKM_CONNECT_NOTIFIER, *PDBGKM_CONNECT_NOTIFIER;
+
+typedef struct _DBGKM_SERVICE_TABLE_
+{
+ IMG_UINT32 ui32Size;
+ IMG_VOID * (IMG_CALLCONV *pfnCreateStream) (IMG_CHAR * pszName,IMG_UINT32 ui32CapMode,IMG_UINT32 ui32OutMode,IMG_UINT32 ui32Flags,IMG_UINT32 ui32Pages);
+ IMG_VOID (IMG_CALLCONV *pfnDestroyStream) (PDBG_STREAM psStream);
+ IMG_VOID * (IMG_CALLCONV *pfnFindStream) (IMG_CHAR * pszName, IMG_BOOL bResetInitBuffer);
+ IMG_UINT32 (IMG_CALLCONV *pfnWriteString) (PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level);
+ IMG_UINT32 (IMG_CALLCONV *pfnReadString) (PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Limit);
+ IMG_UINT32 (IMG_CALLCONV *pfnWriteBIN) (PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+ IMG_UINT32 (IMG_CALLCONV *pfnReadBIN) (PDBG_STREAM psStream,IMG_BOOL bReadInitBuffer, IMG_UINT32 ui32OutBufferSize,IMG_UINT8 *pui8OutBuf);
+ IMG_VOID (IMG_CALLCONV *pfnSetCaptureMode) (PDBG_STREAM psStream,IMG_UINT32 ui32CapMode,IMG_UINT32 ui32Start,IMG_UINT32 ui32Stop,IMG_UINT32 ui32SampleRate);
+ IMG_VOID (IMG_CALLCONV *pfnSetOutputMode) (PDBG_STREAM psStream,IMG_UINT32 ui32OutMode);
+ IMG_VOID (IMG_CALLCONV *pfnSetDebugLevel) (PDBG_STREAM psStream,IMG_UINT32 ui32DebugLevel);
+ IMG_VOID (IMG_CALLCONV *pfnSetFrame) (PDBG_STREAM psStream,IMG_UINT32 ui32Frame);
+ IMG_UINT32 (IMG_CALLCONV *pfnGetFrame) (PDBG_STREAM psStream);
+ IMG_VOID (IMG_CALLCONV *pfnOverrideMode) (PDBG_STREAM psStream,IMG_UINT32 ui32Mode);
+ IMG_VOID (IMG_CALLCONV *pfnDefaultMode) (PDBG_STREAM psStream);
+ IMG_UINT32 (IMG_CALLCONV *pfnDBGDrivWrite2) (PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+ IMG_UINT32 (IMG_CALLCONV *pfnWriteStringCM) (PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level);
+ IMG_UINT32 (IMG_CALLCONV *pfnWriteBINCM) (PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+ IMG_VOID (IMG_CALLCONV *pfnSetMarker) (PDBG_STREAM psStream,IMG_UINT32 ui32Marker);
+ IMG_UINT32 (IMG_CALLCONV *pfnGetMarker) (PDBG_STREAM psStream);
+ IMG_VOID (IMG_CALLCONV *pfnStartInitPhase) (PDBG_STREAM psStream);
+ IMG_VOID (IMG_CALLCONV *pfnStopInitPhase) (PDBG_STREAM psStream);
+ IMG_BOOL (IMG_CALLCONV *pfnIsCaptureFrame) (PDBG_STREAM psStream, IMG_BOOL bCheckPreviousFrame);
+ IMG_UINT32 (IMG_CALLCONV *pfnWriteLF) (PDBG_STREAM psStream, IMG_UINT8 *pui8InBuf, IMG_UINT32 ui32InBuffSize, IMG_UINT32 ui32Level, IMG_UINT32 ui32Flags);
+ IMG_UINT32 (IMG_CALLCONV *pfnReadLF) (PDBG_STREAM psStream, IMG_UINT32 ui32OutBuffSize, IMG_UINT8 *pui8OutBuf);
+ IMG_UINT32 (IMG_CALLCONV *pfnGetStreamOffset) (PDBG_STREAM psStream);
+ IMG_VOID (IMG_CALLCONV *pfnSetStreamOffset) (PDBG_STREAM psStream, IMG_UINT32 ui32StreamOffset);
+ IMG_BOOL (IMG_CALLCONV *pfnIsLastCaptureFrame) (PDBG_STREAM psStream);
+ IMG_VOID (IMG_CALLCONV *pfnWaitForEvent) (DBG_EVENT eEvent);
+ IMG_VOID (IMG_CALLCONV *pfnSetConnectNotifier) (DBGKM_CONNECT_NOTIFIER fn_notifier);
+ IMG_UINT32 (IMG_CALLCONV *pfnWritePersist) (PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+} DBGKM_SERVICE_TABLE, *PDBGKM_SERVICE_TABLE;
+
+
+#endif
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#if !defined (__IMG_DEFS_H__)
+#define __IMG_DEFS_H__
+
+#include "img_types.h"
+
+typedef enum img_tag_TriStateSwitch
+{
+ IMG_ON = 0x00,
+ IMG_OFF,
+ IMG_IGNORE
+
+} img_TriStateSwitch, * img_pTriStateSwitch;
+
+#define IMG_SUCCESS 0
+
+#define IMG_NO_REG 1
+
+#if defined (NO_INLINE_FUNCS)
+ #define INLINE
+ #define FORCE_INLINE
+#else
+#if defined (__cplusplus)
+ #define INLINE inline
+ #define FORCE_INLINE inline
+#else
+#if !defined(INLINE)
+ #define INLINE __inline
+#endif
+ #define FORCE_INLINE static __inline
+#endif
+#endif
+
+
+#ifndef PVR_UNREFERENCED_PARAMETER
+#define PVR_UNREFERENCED_PARAMETER(param) (param) = (param)
+#endif
+
+#ifdef __GNUC__
+#define unref__ __attribute__ ((unused))
+#else
+#define unref__
+#endif
+
+#ifndef _TCHAR_DEFINED
+#if defined(UNICODE)
+typedef unsigned short TCHAR, *PTCHAR, *PTSTR;
+#else
+typedef char TCHAR, *PTCHAR, *PTSTR;
+#endif
+#define _TCHAR_DEFINED
+#endif
+
+
+ #if defined(__linux__) || defined(__METAG)
+
+ #define IMG_CALLCONV
+ #define IMG_INTERNAL __attribute__ ((visibility ("hidden")))
+ #define IMG_EXPORT __attribute__((visibility("default")))
+ #define IMG_IMPORT
+ #define IMG_RESTRICT __restrict__
+
+ #else
+ #error("define an OS")
+ #endif
+
+#ifndef IMG_ABORT
+ #define IMG_ABORT() abort()
+#endif
+
+#ifndef IMG_MALLOC
+ #define IMG_MALLOC(A) malloc (A)
+#endif
+
+#ifndef IMG_FREE
+ #define IMG_FREE(A) free (A)
+#endif
+
+#define IMG_CONST const
+
+#if defined(__GNUC__)
+#define IMG_FORMAT_PRINTF(x,y) __attribute__((format(printf,x,y)))
+#else
+#define IMG_FORMAT_PRINTF(x,y)
+#endif
+
+#if defined (_WIN64)
+#define IMG_UNDEF (~0ULL)
+#else
+#define IMG_UNDEF (~0UL)
+#endif
+
+#endif
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef __IMG_TYPES_H__
+#define __IMG_TYPES_H__
+
+#include <drm/drm.h>
+
+#if !defined(IMG_ADDRSPACE_CPUVADDR_BITS)
+#define IMG_ADDRSPACE_CPUVADDR_BITS 32
+#endif
+
+#if !defined(IMG_ADDRSPACE_PHYSADDR_BITS)
+#define IMG_ADDRSPACE_PHYSADDR_BITS 32
+#endif
+
+typedef uint32_t IMG_UINT, *IMG_PUINT;
+typedef int32_t IMG_INT, *IMG_PINT;
+
+typedef uint8_t IMG_UINT8, *IMG_PUINT8;
+typedef uint8_t IMG_BYTE, *IMG_PBYTE;
+typedef int8_t IMG_INT8, *IMG_PINT8;
+typedef char IMG_CHAR, *IMG_PCHAR;
+
+typedef uint16_t IMG_UINT16, *IMG_PUINT16;
+typedef int16_t IMG_INT16, *IMG_PINT16;
+
+
+#if !defined(IMG_UINT32_IS_ULONG)
+typedef uint32_t IMG_UINT32, *IMG_PUINT32;
+typedef int32_t IMG_INT32, *IMG_PINT32;
+#else
+typedef uint32_t IMG_UINT32, *IMG_PUINT32;
+typedef int32_t IMG_INT32, *IMG_PINT32;
+#endif
+
+
+#if !defined(IMG_UINT32_MAX)
+ #define IMG_UINT32_MAX 0xFFFFFFFFUL
+#endif
+
+ #if (defined(LINUX) || defined(__METAG))
+#if !defined(USE_CODE)
+ typedef unsigned long long IMG_UINT64, *IMG_PUINT64;
+ typedef long long IMG_INT64, *IMG_PINT64;
+#endif
+ #else
+
+ #error("define an OS")
+
+ #endif
+
+#if !(defined(LINUX) && defined (__KERNEL__))
+typedef float IMG_FLOAT, *IMG_PFLOAT;
+typedef double IMG_DOUBLE, *IMG_PDOUBLE;
+#endif
+
+typedef enum tag_img_bool
+{
+ IMG_FALSE = 0,
+ IMG_TRUE = 1,
+ IMG_FORCE_ALIGN = 0x7FFFFFFF
+} IMG_BOOL, *IMG_PBOOL;
+
+typedef void IMG_VOID, *IMG_PVOID;
+
+typedef IMG_INT32 IMG_RESULT;
+
+#if defined(_WIN64)
+typedef unsigned __int64 IMG_UINTPTR_T;
+#else
+typedef unsigned int IMG_UINTPTR_T;
+#endif
+
+typedef IMG_PVOID IMG_HANDLE;
+
+typedef void** IMG_HVOID, * IMG_PHVOID;
+
+typedef IMG_UINT32 IMG_SIZE_T;
+
+#define IMG_NULL 0
+
+typedef IMG_UINT32 IMG_SID;
+
+typedef IMG_PVOID IMG_CPU_VIRTADDR;
+
+typedef struct _IMG_DEV_VIRTADDR
+{
+
+ IMG_UINT32 uiAddr;
+#define IMG_CAST_TO_DEVVADDR_UINT(var) (IMG_UINT32)(var)
+
+} IMG_DEV_VIRTADDR;
+
+typedef struct _IMG_CPU_PHYADDR
+{
+
+ IMG_UINTPTR_T uiAddr;
+} IMG_CPU_PHYADDR;
+
+typedef struct _IMG_DEV_PHYADDR
+{
+#if IMG_ADDRSPACE_PHYSADDR_BITS == 32
+
+ IMG_UINTPTR_T uiAddr;
+#else
+ IMG_UINT32 uiAddr;
+ IMG_UINT32 uiHighAddr;
+#endif
+} IMG_DEV_PHYADDR;
+
+typedef struct _IMG_SYS_PHYADDR
+{
+
+ IMG_UINTPTR_T uiAddr;
+} IMG_SYS_PHYADDR;
+
+#include "img_defs.h"
+
+#endif
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef __IOCTLDEF_H__
+#define __IOCTLDEF_H__
+
+#define MAKEIOCTLINDEX(i) (((i) >> 2) & 0xFFF)
+
+#ifndef CTL_CODE
+
+#define DEVICE_TYPE ULONG
+
+#define FILE_DEVICE_BEEP 0x00000001
+#define FILE_DEVICE_CD_ROM 0x00000002
+#define FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003
+#define FILE_DEVICE_CONTROLLER 0x00000004
+#define FILE_DEVICE_DATALINK 0x00000005
+#define FILE_DEVICE_DFS 0x00000006
+#define FILE_DEVICE_DISK 0x00000007
+#define FILE_DEVICE_DISK_FILE_SYSTEM 0x00000008
+#define FILE_DEVICE_FILE_SYSTEM 0x00000009
+#define FILE_DEVICE_INPORT_PORT 0x0000000a
+#define FILE_DEVICE_KEYBOARD 0x0000000b
+#define FILE_DEVICE_MAILSLOT 0x0000000c
+#define FILE_DEVICE_MIDI_IN 0x0000000d
+#define FILE_DEVICE_MIDI_OUT 0x0000000e
+#define FILE_DEVICE_MOUSE 0x0000000f
+#define FILE_DEVICE_MULTI_UNC_PROVIDER 0x00000010
+#define FILE_DEVICE_NAMED_PIPE 0x00000011
+#define FILE_DEVICE_NETWORK 0x00000012
+#define FILE_DEVICE_NETWORK_BROWSER 0x00000013
+#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014
+#define FILE_DEVICE_NULL 0x00000015
+#define FILE_DEVICE_PARALLEL_PORT 0x00000016
+#define FILE_DEVICE_PHYSICAL_NETCARD 0x00000017
+#define FILE_DEVICE_PRINTER 0x00000018
+#define FILE_DEVICE_SCANNER 0x00000019
+#define FILE_DEVICE_SERIAL_MOUSE_PORT 0x0000001a
+#define FILE_DEVICE_SERIAL_PORT 0x0000001b
+#define FILE_DEVICE_SCREEN 0x0000001c
+#define FILE_DEVICE_SOUND 0x0000001d
+#define FILE_DEVICE_STREAMS 0x0000001e
+#define FILE_DEVICE_TAPE 0x0000001f
+#define FILE_DEVICE_TAPE_FILE_SYSTEM 0x00000020
+#define FILE_DEVICE_TRANSPORT 0x00000021
+#define FILE_DEVICE_UNKNOWN 0x00000022
+#define FILE_DEVICE_VIDEO 0x00000023
+#define FILE_DEVICE_VIRTUAL_DISK 0x00000024
+#define FILE_DEVICE_WAVE_IN 0x00000025
+#define FILE_DEVICE_WAVE_OUT 0x00000026
+#define FILE_DEVICE_8042_PORT 0x00000027
+#define FILE_DEVICE_NETWORK_REDIRECTOR 0x00000028
+#define FILE_DEVICE_BATTERY 0x00000029
+#define FILE_DEVICE_BUS_EXTENDER 0x0000002a
+#define FILE_DEVICE_MODEM 0x0000002b
+#define FILE_DEVICE_VDM 0x0000002c
+#define FILE_DEVICE_MASS_STORAGE 0x0000002d
+
+#define CTL_CODE( DeviceType, Function, Method, Access ) ( \
+ ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
+)
+
+#define METHOD_BUFFERED 0
+#define METHOD_IN_DIRECT 1
+#define METHOD_OUT_DIRECT 2
+#define METHOD_NEITHER 3
+
+#define FILE_ANY_ACCESS 0
+#define FILE_READ_ACCESS ( 0x0001 )
+#define FILE_WRITE_ACCESS ( 0x0002 )
+
+#endif
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#if !defined (__PDUMPDEFS_H__)
+#define __PDUMPDEFS_H__
+
+typedef enum _PDUMP_PIXEL_FORMAT_
+{
+ PVRSRV_PDUMP_PIXEL_FORMAT_UNSUPPORTED = 0,
+ PVRSRV_PDUMP_PIXEL_FORMAT_RGB8 = 1,
+ PVRSRV_PDUMP_PIXEL_FORMAT_RGB332 = 2,
+ PVRSRV_PDUMP_PIXEL_FORMAT_KRGB555 = 3,
+ PVRSRV_PDUMP_PIXEL_FORMAT_RGB565 = 4,
+ PVRSRV_PDUMP_PIXEL_FORMAT_ARGB4444 = 5,
+ PVRSRV_PDUMP_PIXEL_FORMAT_ARGB1555 = 6,
+ PVRSRV_PDUMP_PIXEL_FORMAT_RGB888 = 7,
+ PVRSRV_PDUMP_PIXEL_FORMAT_ARGB8888 = 8,
+ PVRSRV_PDUMP_PIXEL_FORMAT_YUV8 = 9,
+ PVRSRV_PDUMP_PIXEL_FORMAT_AYUV4444 = 10,
+ PVRSRV_PDUMP_PIXEL_FORMAT_VY0UY1_8888 = 11,
+ PVRSRV_PDUMP_PIXEL_FORMAT_UY0VY1_8888 = 12,
+ PVRSRV_PDUMP_PIXEL_FORMAT_Y0UY1V_8888 = 13,
+ PVRSRV_PDUMP_PIXEL_FORMAT_Y0VY1U_8888 = 14,
+ PVRSRV_PDUMP_PIXEL_FORMAT_YUV888 = 15,
+ PVRSRV_PDUMP_PIXEL_FORMAT_UYVY10101010 = 16,
+ PVRSRV_PDUMP_PIXEL_FORMAT_VYAUYA8888 = 17,
+ PVRSRV_PDUMP_PIXEL_FORMAT_AYUV8888 = 18,
+ PVRSRV_PDUMP_PIXEL_FORMAT_AYUV2101010 = 19,
+ PVRSRV_PDUMP_PIXEL_FORMAT_YUV101010 = 20,
+ PVRSRV_PDUMP_PIXEL_FORMAT_PL12Y8 = 21,
+ PVRSRV_PDUMP_PIXEL_FORMAT_YUV_IMC2 = 22,
+ PVRSRV_PDUMP_PIXEL_FORMAT_YUV_YV12 = 23,
+ PVRSRV_PDUMP_PIXEL_FORMAT_YUV_PL8 = 24,
+ PVRSRV_PDUMP_PIXEL_FORMAT_YUV_PL12 = 25,
+ PVRSRV_PDUMP_PIXEL_FORMAT_422PL12YUV8 = 26,
+ PVRSRV_PDUMP_PIXEL_FORMAT_420PL12YUV8 = 27,
+ PVRSRV_PDUMP_PIXEL_FORMAT_PL12Y10 = 28,
+ PVRSRV_PDUMP_PIXEL_FORMAT_422PL12YUV10 = 29,
+ PVRSRV_PDUMP_PIXEL_FORMAT_420PL12YUV10 = 30,
+ PVRSRV_PDUMP_PIXEL_FORMAT_ABGR8888 = 31,
+ PVRSRV_PDUMP_PIXEL_FORMAT_BGRA8888 = 32,
+ PVRSRV_PDUMP_PIXEL_FORMAT_ARGB8332 = 33,
+ PVRSRV_PDUMP_PIXEL_FORMAT_RGB555 = 34,
+ PVRSRV_PDUMP_PIXEL_FORMAT_F16 = 35,
+ PVRSRV_PDUMP_PIXEL_FORMAT_F32 = 36,
+ PVRSRV_PDUMP_PIXEL_FORMAT_L16 = 37,
+ PVRSRV_PDUMP_PIXEL_FORMAT_L32 = 38,
+
+ PVRSRV_PDUMP_PIXEL_FORMAT_FORCE_I32 = 0x7fffffff
+
+} PDUMP_PIXEL_FORMAT;
+
+typedef enum _PDUMP_MEM_FORMAT_
+{
+ PVRSRV_PDUMP_MEM_FORMAT_STRIDE = 0,
+ PVRSRV_PDUMP_MEM_FORMAT_RESERVED = 1,
+ PVRSRV_PDUMP_MEM_FORMAT_TILED = 8,
+ PVRSRV_PDUMP_MEM_FORMAT_TWIDDLED = 9,
+ PVRSRV_PDUMP_MEM_FORMAT_HYBRID = 10,
+
+ PVRSRV_PDUMP_MEM_FORMAT_FORCE_I32 = 0x7fffffff
+} PDUMP_MEM_FORMAT;
+
+typedef enum _PDUMP_POLL_OPERATOR
+{
+ PDUMP_POLL_OPERATOR_EQUAL = 0,
+ PDUMP_POLL_OPERATOR_LESS = 1,
+ PDUMP_POLL_OPERATOR_LESSEQUAL = 2,
+ PDUMP_POLL_OPERATOR_GREATER = 3,
+ PDUMP_POLL_OPERATOR_GREATEREQUAL = 4,
+ PDUMP_POLL_OPERATOR_NOTEQUAL = 5,
+} PDUMP_POLL_OPERATOR;
+
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef __PVR_DEBUG_H__
+#define __PVR_DEBUG_H__
+
+
+#include "img_types.h"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define PVR_MAX_DEBUG_MESSAGE_LEN (512)
+
+#define DBGPRIV_FATAL 0x01UL
+#define DBGPRIV_ERROR 0x02UL
+#define DBGPRIV_WARNING 0x04UL
+#define DBGPRIV_MESSAGE 0x08UL
+#define DBGPRIV_VERBOSE 0x10UL
+#define DBGPRIV_CALLTRACE 0x20UL
+#define DBGPRIV_ALLOC 0x40UL
+
+#define DBGPRIV_DBGDRV_MESSAGE 0x1000UL
+
+#define DBGPRIV_ALLLEVELS (DBGPRIV_FATAL | DBGPRIV_ERROR | DBGPRIV_WARNING | DBGPRIV_MESSAGE | DBGPRIV_VERBOSE)
+
+
+
+#define PVR_DBG_FATAL DBGPRIV_FATAL,__FILE__, __LINE__
+#define PVR_DBG_ERROR DBGPRIV_ERROR,__FILE__, __LINE__
+#define PVR_DBG_WARNING DBGPRIV_WARNING,__FILE__, __LINE__
+#define PVR_DBG_MESSAGE DBGPRIV_MESSAGE,__FILE__, __LINE__
+#define PVR_DBG_VERBOSE DBGPRIV_VERBOSE,__FILE__, __LINE__
+#define PVR_DBG_CALLTRACE DBGPRIV_CALLTRACE,__FILE__, __LINE__
+#define PVR_DBG_ALLOC DBGPRIV_ALLOC,__FILE__, __LINE__
+
+#define PVR_DBGDRIV_MESSAGE DBGPRIV_DBGDRV_MESSAGE, "", 0
+
+#if !defined(PVRSRV_NEED_PVR_ASSERT) && defined(DEBUG)
+#define PVRSRV_NEED_PVR_ASSERT
+#endif
+
+#if defined(PVRSRV_NEED_PVR_ASSERT) && !defined(PVRSRV_NEED_PVR_DPF)
+#define PVRSRV_NEED_PVR_DPF
+#endif
+
+#if !defined(PVRSRV_NEED_PVR_TRACE) && (defined(DEBUG) || defined(TIMING))
+#define PVRSRV_NEED_PVR_TRACE
+#endif
+
+
+#if defined(PVRSRV_NEED_PVR_ASSERT)
+
+ #define PVR_ASSERT(EXPR) if (!(EXPR)) PVRSRVDebugAssertFail(__FILE__, __LINE__);
+
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVDebugAssertFail(const IMG_CHAR *pszFile,
+ IMG_UINT32 ui32Line);
+
+ #if defined(PVR_DBG_BREAK_ASSERT_FAIL)
+ #define PVR_DBG_BREAK PVRSRVDebugAssertFail("PVR_DBG_BREAK", 0)
+ #else
+ #define PVR_DBG_BREAK
+ #endif
+
+#else
+
+ #define PVR_ASSERT(EXPR)
+ #define PVR_DBG_BREAK
+
+#endif
+
+
+#if defined(PVRSRV_NEED_PVR_DPF)
+
+ #define PVR_DPF(X) PVRSRVDebugPrintf X
+
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVDebugPrintf(IMG_UINT32 ui32DebugLevel,
+ const IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32Line,
+ const IMG_CHAR *pszFormat,
+ ...) IMG_FORMAT_PRINTF(4, 5);
+
+#else
+
+ #define PVR_DPF(X)
+
+#endif
+
+
+#if defined(PVRSRV_NEED_PVR_TRACE)
+
+ #define PVR_TRACE(X) PVRSRVTrace X
+
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVTrace(const IMG_CHAR* pszFormat, ... )
+ IMG_FORMAT_PRINTF(1, 2);
+
+#else
+
+ #define PVR_TRACE(X)
+
+#endif
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef _PVRMODULE_H_
+#define _PVRMODULE_H_
+MODULE_AUTHOR("Imagination Technologies Ltd. <gpl-support@imgtec.com>");
+MODULE_LICENSE("GPL");
+#endif
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef _PVRVERSION_H_
+#define _PVRVERSION_H_
+
+#define PVRVERSION_MAJ 1
+#define PVRVERSION_MIN 6
+#define PVRVERSION_BRANCH 16
+#define PVRVERSION_BUILD 4043
+#define PVRVERSION_STRING "1.6.16.4043"
+#define PVRVERSION_FILE "eurasiacon.pj"
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef __REGPATHS_H__
+#define __REGPATHS_H__
+
+#define POWERVR_REG_ROOT "Drivers\\Display\\PowerVR"
+#define POWERVR_CHIP_KEY "\\SGX1\\"
+
+#define POWERVR_EURASIA_KEY "PowerVREurasia\\"
+
+#define POWERVR_SERVICES_KEY "\\Registry\\Machine\\System\\CurrentControlSet\\Services\\PowerVR\\"
+
+#define PVRSRV_REGISTRY_ROOT POWERVR_EURASIA_KEY "HWSettings\\PVRSRVKM"
+
+
+#define MAX_REG_STRING_SIZE 128
+
+
+#endif
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef __SERVICES_H__
+#define __SERVICES_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "img_defs.h"
+#include "servicesext.h"
+#include "pdumpdefs.h"
+
+
+#define PVRSRV_4K_PAGE_SIZE 4096UL
+
+#define PVRSRV_MAX_CMD_SIZE 1024
+
+#define PVRSRV_MAX_DEVICES 16
+
+#define EVENTOBJNAME_MAXLENGTH (50)
+
+#define PVRSRV_MEM_READ (1U<<0)
+#define PVRSRV_MEM_WRITE (1U<<1)
+#define PVRSRV_MEM_CACHE_CONSISTENT (1U<<2)
+#define PVRSRV_MEM_NO_SYNCOBJ (1U<<3)
+#define PVRSRV_MEM_INTERLEAVED (1U<<4)
+#define PVRSRV_MEM_DUMMY (1U<<5)
+#define PVRSRV_MEM_EDM_PROTECT (1U<<6)
+#define PVRSRV_MEM_ZERO (1U<<7)
+#define PVRSRV_MEM_USER_SUPPLIED_DEVVADDR (1U<<8)
+#define PVRSRV_MEM_RAM_BACKED_ALLOCATION (1U<<9)
+#define PVRSRV_MEM_NO_RESMAN (1U<<10)
+#define PVRSRV_MEM_EXPORTED (1U<<11)
+
+
+#define PVRSRV_HAP_CACHED (1U<<12)
+#define PVRSRV_HAP_UNCACHED (1U<<13)
+#define PVRSRV_HAP_WRITECOMBINE (1U<<14)
+#define PVRSRV_HAP_CACHETYPE_MASK (PVRSRV_HAP_CACHED|PVRSRV_HAP_UNCACHED|PVRSRV_HAP_WRITECOMBINE)
+#define PVRSRV_HAP_KERNEL_ONLY (1U<<15)
+#define PVRSRV_HAP_SINGLE_PROCESS (1U<<16)
+#define PVRSRV_HAP_MULTI_PROCESS (1U<<17)
+#define PVRSRV_HAP_FROM_EXISTING_PROCESS (1U<<18)
+#define PVRSRV_HAP_NO_CPU_VIRTUAL (1U<<19)
+#define PVRSRV_HAP_MAPTYPE_MASK (PVRSRV_HAP_KERNEL_ONLY \
+ |PVRSRV_HAP_SINGLE_PROCESS \
+ |PVRSRV_HAP_MULTI_PROCESS \
+ |PVRSRV_HAP_FROM_EXISTING_PROCESS \
+ |PVRSRV_HAP_NO_CPU_VIRTUAL)
+
+#define PVRSRV_MEM_CACHED PVRSRV_HAP_CACHED
+#define PVRSRV_MEM_UNCACHED PVRSRV_HAP_UNCACHED
+#define PVRSRV_MEM_WRITECOMBINE PVRSRV_HAP_WRITECOMBINE
+
+#define PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT (24)
+
+#define PVRSRV_MAP_NOUSERVIRTUAL (1UL<<27)
+
+#define PVRSRV_NO_CONTEXT_LOSS 0
+#define PVRSRV_SEVERE_LOSS_OF_CONTEXT 1
+#define PVRSRV_PRE_STATE_CHANGE_MASK 0x80
+
+
+#define PVRSRV_DEFAULT_DEV_COOKIE (1)
+
+
+#define PVRSRV_MISC_INFO_TIMER_PRESENT (1U<<0)
+#define PVRSRV_MISC_INFO_CLOCKGATE_PRESENT (1U<<1)
+#define PVRSRV_MISC_INFO_MEMSTATS_PRESENT (1U<<2)
+#define PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT (1U<<3)
+#define PVRSRV_MISC_INFO_DDKVERSION_PRESENT (1U<<4)
+#define PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT (1U<<5)
+#define PVRSRV_MISC_INFO_FREEMEM_PRESENT (1U<<6)
+
+#define PVRSRV_MISC_INFO_RESET_PRESENT (1U<<31)
+
+#define PVRSRV_PDUMP_MAX_FILENAME_SIZE 20
+#define PVRSRV_PDUMP_MAX_COMMENT_SIZE 200
+
+
+#define PVRSRV_CHANGEDEVMEM_ATTRIBS_CACHECOHERENT 0x00000001
+
+#define PVRSRV_MAPEXTMEMORY_FLAGS_ALTERNATEVA 0x00000001
+#define PVRSRV_MAPEXTMEMORY_FLAGS_PHYSCONTIG 0x00000002
+
+#define PVRSRV_MODIFYSYNCOPS_FLAGS_WO_INC 0x00000001
+#define PVRSRV_MODIFYSYNCOPS_FLAGS_RO_INC 0x00000002
+
+#define SRV_FLAGS_PERSIST 0x1
+#define SRV_FLAGS_PDUMP_ACTIVE 0x2
+
+#define PVRSRV_PDUMP_FLAGS_CONTINUOUS 0x1
+
+
+typedef enum _PVRSRV_DEVICE_TYPE_
+{
+ PVRSRV_DEVICE_TYPE_UNKNOWN = 0 ,
+ PVRSRV_DEVICE_TYPE_MBX1 = 1 ,
+ PVRSRV_DEVICE_TYPE_MBX1_LITE = 2 ,
+
+ PVRSRV_DEVICE_TYPE_M24VA = 3,
+ PVRSRV_DEVICE_TYPE_MVDA2 = 4,
+ PVRSRV_DEVICE_TYPE_MVED1 = 5,
+ PVRSRV_DEVICE_TYPE_MSVDX = 6,
+
+ PVRSRV_DEVICE_TYPE_SGX = 7,
+
+ PVRSRV_DEVICE_TYPE_VGX = 8,
+
+ PVRSRV_DEVICE_TYPE_TOPAZ = 9,
+
+ PVRSRV_DEVICE_TYPE_EXT = 10,
+
+ PVRSRV_DEVICE_TYPE_LAST = 10,
+
+ PVRSRV_DEVICE_TYPE_FORCE_I32 = 0x7fffffff
+
+} PVRSRV_DEVICE_TYPE;
+
+#define HEAP_ID( _dev_ , _dev_heap_idx_ ) ( ((_dev_)<<24) | ((_dev_heap_idx_)&((1<<24)-1)) )
+#define HEAP_IDX( _heap_id_ ) ( (_heap_id_)&((1<<24) - 1 ) )
+#define HEAP_DEV( _heap_id_ ) ( (_heap_id_)>>24 )
+
+#define PVRSRV_UNDEFINED_HEAP_ID (~0LU)
+
+typedef enum
+{
+ IMG_EGL = 0x00000001,
+ IMG_OPENGLES1 = 0x00000002,
+ IMG_OPENGLES2 = 0x00000003,
+ IMG_D3DM = 0x00000004,
+ IMG_SRV_UM = 0x00000005,
+ IMG_OPENVG = 0x00000006,
+ IMG_SRVCLIENT = 0x00000007,
+ IMG_VISTAKMD = 0x00000008,
+ IMG_VISTA3DNODE = 0x00000009,
+ IMG_VISTAMVIDEONODE = 0x0000000A,
+ IMG_VISTAVPBNODE = 0x0000000B,
+ IMG_OPENGL = 0x0000000C,
+ IMG_D3D = 0x0000000D,
+#if defined(SUPPORT_GRAPHICS_HAL)
+ IMG_GRAPHICS_HAL = 0x0000000E
+#endif
+
+} IMG_MODULE_ID;
+
+
+#define APPHINT_MAX_STRING_SIZE 256
+
+typedef enum
+{
+ IMG_STRING_TYPE = 1,
+ IMG_FLOAT_TYPE ,
+ IMG_UINT_TYPE ,
+ IMG_INT_TYPE ,
+ IMG_FLAG_TYPE
+}IMG_DATA_TYPE;
+
+
+typedef struct _PVRSRV_DEV_DATA_ *PPVRSRV_DEV_DATA;
+
+typedef struct _PVRSRV_DEVICE_IDENTIFIER_
+{
+ PVRSRV_DEVICE_TYPE eDeviceType;
+ PVRSRV_DEVICE_CLASS eDeviceClass;
+ IMG_UINT32 ui32DeviceIndex;
+ IMG_CHAR *pszPDumpDevName;
+ IMG_CHAR *pszPDumpRegName;
+
+} PVRSRV_DEVICE_IDENTIFIER;
+
+
+typedef struct _PVRSRV_CLIENT_DEV_DATA_
+{
+ IMG_UINT32 ui32NumDevices;
+ PVRSRV_DEVICE_IDENTIFIER asDevID[PVRSRV_MAX_DEVICES];
+ PVRSRV_ERROR (*apfnDevConnect[PVRSRV_MAX_DEVICES])(PPVRSRV_DEV_DATA);
+ PVRSRV_ERROR (*apfnDumpTrace[PVRSRV_MAX_DEVICES])(PPVRSRV_DEV_DATA);
+
+} PVRSRV_CLIENT_DEV_DATA;
+
+
+typedef struct _PVRSRV_CONNECTION_
+{
+ IMG_HANDLE hServices;
+ IMG_UINTPTR_T ui32ProcessID;
+ PVRSRV_CLIENT_DEV_DATA sClientDevData;
+ IMG_UINT32 ui32SrvFlags;
+}PVRSRV_CONNECTION;
+
+
+typedef struct _PVRSRV_DEV_DATA_
+{
+ IMG_CONST PVRSRV_CONNECTION *psConnection;
+ IMG_HANDLE hDevCookie;
+
+} PVRSRV_DEV_DATA;
+
+typedef struct _PVRSRV_MEMUPDATE_
+{
+ IMG_UINTPTR_T ui32UpdateAddr;
+ IMG_UINT32 ui32UpdateVal;
+} PVRSRV_MEMUPDATE;
+
+typedef struct _PVRSRV_HWREG_
+{
+ IMG_UINT32 ui32RegAddr;
+ IMG_UINT32 ui32RegVal;
+} PVRSRV_HWREG;
+
+typedef struct _PVRSRV_MEMBLK_
+{
+ IMG_DEV_VIRTADDR sDevVirtAddr;
+ IMG_HANDLE hOSMemHandle;
+ IMG_HANDLE hOSWrapMem;
+ IMG_HANDLE hBuffer;
+ IMG_HANDLE hResItem;
+ IMG_SYS_PHYADDR *psIntSysPAddr;
+
+} PVRSRV_MEMBLK;
+
+typedef struct _PVRSRV_KERNEL_MEM_INFO_ *PPVRSRV_KERNEL_MEM_INFO;
+
+typedef struct _PVRSRV_CLIENT_MEM_INFO_
+{
+
+ IMG_PVOID pvLinAddr;
+
+
+ IMG_PVOID pvLinAddrKM;
+
+
+ IMG_DEV_VIRTADDR sDevVAddr;
+
+
+
+
+
+
+ IMG_CPU_PHYADDR sCpuPAddr;
+
+
+ IMG_UINT32 ui32Flags;
+
+
+
+
+ IMG_UINT32 ui32ClientFlags;
+
+
+ IMG_SIZE_T ui32AllocSize;
+
+
+
+ struct _PVRSRV_CLIENT_SYNC_INFO_ *psClientSyncInfo;
+
+
+ IMG_HANDLE hMappingInfo;
+
+
+ IMG_HANDLE hKernelMemInfo;
+
+
+ IMG_HANDLE hResItem;
+
+#if defined(SUPPORT_MEMINFO_IDS)
+ #if !defined(USE_CODE)
+
+ IMG_UINT64 ui64Stamp;
+ #else
+ IMG_UINT32 dummy1;
+ IMG_UINT32 dummy2;
+ #endif
+#endif
+
+
+
+
+ struct _PVRSRV_CLIENT_MEM_INFO_ *psNext;
+
+} PVRSRV_CLIENT_MEM_INFO, *PPVRSRV_CLIENT_MEM_INFO;
+
+
+#define PVRSRV_MAX_CLIENT_HEAPS (32)
+typedef struct _PVRSRV_HEAP_INFO_
+{
+ IMG_UINT32 ui32HeapID;
+ IMG_HANDLE hDevMemHeap;
+ IMG_DEV_VIRTADDR sDevVAddrBase;
+ IMG_UINT32 ui32HeapByteSize;
+ IMG_UINT32 ui32Attribs;
+ IMG_UINT32 ui32XTileStride;
+}PVRSRV_HEAP_INFO;
+
+
+
+
+typedef struct _PVRSRV_EVENTOBJECT_
+{
+
+ IMG_CHAR szName[EVENTOBJNAME_MAXLENGTH];
+
+ IMG_HANDLE hOSEventKM;
+
+} PVRSRV_EVENTOBJECT;
+
+typedef enum
+{
+ PVRSRV_MISC_INFO_CPUCACHEOP_NONE = 0,
+ PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN,
+ PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH
+} PVRSRV_MISC_INFO_CPUCACHEOP_TYPE;
+
+typedef struct _PVRSRV_MISC_INFO_
+{
+ IMG_UINT32 ui32StateRequest;
+ IMG_UINT32 ui32StatePresent;
+
+
+ IMG_VOID *pvSOCTimerRegisterKM;
+ IMG_VOID *pvSOCTimerRegisterUM;
+ IMG_HANDLE hSOCTimerRegisterOSMemHandle;
+ IMG_HANDLE hSOCTimerRegisterMappingInfo;
+
+
+ IMG_VOID *pvSOCClockGateRegs;
+ IMG_UINT32 ui32SOCClockGateRegsSize;
+
+
+ IMG_CHAR *pszMemoryStr;
+ IMG_UINT32 ui32MemoryStrLen;
+
+
+ PVRSRV_EVENTOBJECT sGlobalEventObject;
+ IMG_HANDLE hOSGlobalEvent;
+
+
+ IMG_UINT32 aui32DDKVersion[4];
+
+
+ struct
+ {
+
+ IMG_BOOL bDeferOp;
+
+
+ PVRSRV_MISC_INFO_CPUCACHEOP_TYPE eCacheOpType;
+
+
+ union
+ {
+
+ PVRSRV_CLIENT_MEM_INFO *psClientMemInfo;
+
+
+ struct _PVRSRV_KERNEL_MEM_INFO_ *psKernelMemInfo;
+ } u;
+
+
+ IMG_VOID *pvBaseVAddr;
+
+
+ IMG_UINT32 ui32Length;
+ } sCacheOpCtl;
+} PVRSRV_MISC_INFO;
+
+
+typedef enum _PVRSRV_CLIENT_EVENT_
+{
+ PVRSRV_CLIENT_EVENT_HWTIMEOUT = 0,
+} PVRSRV_CLIENT_EVENT;
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVClientEvent(IMG_CONST PVRSRV_CLIENT_EVENT eEvent,
+ PVRSRV_DEV_DATA *psDevData,
+ IMG_PVOID pvData);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVConnect(PVRSRV_CONNECTION **ppsConnection, IMG_UINT32 ui32SrvFlags);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDisconnect(IMG_CONST PVRSRV_CONNECTION *psConnection);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumerateDevices(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_UINT32 *puiNumDevices,
+ PVRSRV_DEVICE_IDENTIFIER *puiDevIDs);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAcquireDeviceData(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_UINT32 uiDevIndex,
+ PVRSRV_DEV_DATA *psDevData,
+ PVRSRV_DEVICE_TYPE eDeviceType);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfo (IMG_CONST PVRSRV_CONNECTION *psConnection, PVRSRV_MISC_INFO *psMiscInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVReleaseMiscInfo (IMG_CONST PVRSRV_CONNECTION *psConnection, PVRSRV_MISC_INFO *psMiscInfo);
+
+#if 1
+IMG_IMPORT
+IMG_UINT32 ReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset);
+
+IMG_IMPORT
+IMG_VOID WriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value);
+
+IMG_IMPORT IMG_VOID WriteHWRegs(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Count, PVRSRV_HWREG *psHWRegs);
+#endif
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVPollForValue ( const PVRSRV_CONNECTION *psConnection,
+ IMG_HANDLE hOSEvent,
+ volatile IMG_UINT32 *pui32LinMemAddr,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask,
+ IMG_UINT32 ui32Waitus,
+ IMG_UINT32 ui32Tries);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateDeviceMemContext(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ IMG_HANDLE *phDevMemContext,
+ IMG_UINT32 *pui32SharedHeapCount,
+ PVRSRV_HEAP_INFO *psHeapInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyDeviceMemContext(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ IMG_HANDLE hDevMemContext);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapInfo(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ IMG_HANDLE hDevMemContext,
+ IMG_UINT32 *pui32SharedHeapCount,
+ PVRSRV_HEAP_INFO *psHeapInfo);
+
+#if defined(PVRSRV_LOG_MEMORY_ALLOCS)
+ #define PVRSRVAllocDeviceMem_log(psDevData, hDevMemHeap, ui32Attribs, ui32Size, ui32Alignment, ppsMemInfo, logStr) \
+ (PVR_TRACE(("PVRSRVAllocDeviceMem(" #psDevData "," #hDevMemHeap "," #ui32Attribs "," #ui32Size "," #ui32Alignment "," #ppsMemInfo ")" \
+ ": " logStr " (size = 0x%lx)", ui32Size)), \
+ PVRSRVAllocDeviceMem(psDevData, hDevMemHeap, ui32Attribs, ui32Size, ui32Alignment, ppsMemInfo))
+#else
+ #define PVRSRVAllocDeviceMem_log(psDevData, hDevMemHeap, ui32Attribs, ui32Size, ui32Alignment, ppsMemInfo, logStr) \
+ PVRSRVAllocDeviceMem(psDevData, hDevMemHeap, ui32Attribs, ui32Size, ui32Alignment, ppsMemInfo)
+#endif
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAllocDeviceMem(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ IMG_HANDLE hDevMemHeap,
+ IMG_UINT32 ui32Attribs,
+ IMG_SIZE_T ui32Size,
+ IMG_SIZE_T ui32Alignment,
+ PVRSRV_CLIENT_MEM_INFO **ppsMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeDeviceMem(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ PVRSRV_CLIENT_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVExportDeviceMem(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ PVRSRV_CLIENT_MEM_INFO *psMemInfo,
+ IMG_HANDLE *phMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVReserveDeviceVirtualMem(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ IMG_HANDLE hDevMemHeap,
+ IMG_DEV_VIRTADDR *psDevVAddr,
+ IMG_SIZE_T ui32Size,
+ IMG_SIZE_T ui32Alignment,
+ PVRSRV_CLIENT_MEM_INFO **ppsMemInfo);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeDeviceVirtualMem(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ PVRSRV_CLIENT_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceMemory (IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ IMG_HANDLE hKernelMemInfo,
+ IMG_HANDLE hDstDevMemHeap,
+ PVRSRV_CLIENT_MEM_INFO **ppsDstMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceMemory (IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ PVRSRV_CLIENT_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapExtMemory (IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ PVRSRV_CLIENT_MEM_INFO *psMemInfo,
+ IMG_SYS_PHYADDR *psSysPAddr,
+ IMG_UINT32 ui32Flags);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapExtMemory (IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ PVRSRV_CLIENT_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Flags);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVWrapExtMemory(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ IMG_HANDLE hDevMemContext,
+ IMG_SIZE_T ui32ByteSize,
+ IMG_SIZE_T ui32PageOffset,
+ IMG_BOOL bPhysContig,
+ IMG_SYS_PHYADDR *psSysPAddr,
+ IMG_VOID *pvLinAddr,
+ IMG_UINT32 ui32Flags,
+ PVRSRV_CLIENT_MEM_INFO **ppsMemInfo);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnwrapExtMemory (IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ PVRSRV_CLIENT_MEM_INFO *psMemInfo);
+
+PVRSRV_ERROR PVRSRVChangeDeviceMemoryAttributes(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ PVRSRV_CLIENT_MEM_INFO *psClientMemInfo,
+ IMG_UINT32 ui32Attribs);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceClassMemory (IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ IMG_HANDLE hDevMemContext,
+ IMG_HANDLE hDeviceClassBuffer,
+ PVRSRV_CLIENT_MEM_INFO **ppsMemInfo);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceClassMemory (IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ PVRSRV_CLIENT_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapPhysToUserSpace(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ IMG_SYS_PHYADDR sSysPhysAddr,
+ IMG_UINT32 uiSizeInBytes,
+ IMG_PVOID *ppvUserAddr,
+ IMG_UINT32 *puiActualSize,
+ IMG_PVOID *ppvProcess);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapPhysToUserSpace(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ IMG_PVOID pvUserAddr,
+ IMG_PVOID pvProcess);
+
+typedef enum _PVRSRV_SYNCVAL_MODE_
+{
+ PVRSRV_SYNCVAL_READ = IMG_TRUE,
+ PVRSRV_SYNCVAL_WRITE = IMG_FALSE,
+
+} PVRSRV_SYNCVAL_MODE, *PPVRSRV_SYNCVAL_MODE;
+
+typedef IMG_UINT32 PVRSRV_SYNCVAL;
+
+IMG_IMPORT PVRSRV_ERROR PVRSRVWaitForOpsComplete(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+ PVRSRV_SYNCVAL_MODE eMode, PVRSRV_SYNCVAL OpRequired);
+
+IMG_IMPORT PVRSRV_ERROR PVRSRVWaitForAllOpsComplete(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+ PVRSRV_SYNCVAL_MODE eMode);
+
+IMG_IMPORT IMG_BOOL PVRSRVTestOpsComplete(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+ PVRSRV_SYNCVAL_MODE eMode, PVRSRV_SYNCVAL OpRequired);
+
+IMG_IMPORT IMG_BOOL PVRSRVTestAllOpsComplete(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+ PVRSRV_SYNCVAL_MODE eMode);
+
+IMG_IMPORT IMG_BOOL PVRSRVTestOpsNotComplete(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+ PVRSRV_SYNCVAL_MODE eMode, PVRSRV_SYNCVAL OpRequired);
+
+IMG_IMPORT IMG_BOOL PVRSRVTestAllOpsNotComplete(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+ PVRSRV_SYNCVAL_MODE eMode);
+
+IMG_IMPORT PVRSRV_SYNCVAL PVRSRVGetPendingOpSyncVal(PPVRSRV_CLIENT_MEM_INFO psMemInfo,
+ PVRSRV_SYNCVAL_MODE eMode);
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumerateDeviceClass(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ PVRSRV_DEVICE_CLASS DeviceClass,
+ IMG_UINT32 *pui32DevCount,
+ IMG_UINT32 *pui32DevID);
+
+IMG_IMPORT
+IMG_HANDLE IMG_CALLCONV PVRSRVOpenDCDevice(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ IMG_UINT32 ui32DeviceID);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCloseDCDevice(IMG_CONST PVRSRV_CONNECTION *psConnection, IMG_HANDLE hDevice);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumDCFormats (IMG_HANDLE hDevice,
+ IMG_UINT32 *pui32Count,
+ DISPLAY_FORMAT *psFormat);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumDCDims (IMG_HANDLE hDevice,
+ IMG_UINT32 *pui32Count,
+ DISPLAY_FORMAT *psFormat,
+ DISPLAY_DIMS *psDims);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDCSystemBuffer(IMG_HANDLE hDevice,
+ IMG_HANDLE *phBuffer);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDCInfo(IMG_HANDLE hDevice,
+ DISPLAY_INFO* psDisplayInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateDCSwapChain (IMG_HANDLE hDevice,
+ IMG_UINT32 ui32Flags,
+ DISPLAY_SURF_ATTRIBUTES *psDstSurfAttrib,
+ DISPLAY_SURF_ATTRIBUTES *psSrcSurfAttrib,
+ IMG_UINT32 ui32BufferCount,
+ IMG_UINT32 ui32OEMFlags,
+ IMG_UINT32 *pui32SwapChainID,
+ IMG_HANDLE *phSwapChain);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyDCSwapChain (IMG_HANDLE hDevice,
+ IMG_HANDLE hSwapChain);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSetDCDstRect (IMG_HANDLE hDevice,
+ IMG_HANDLE hSwapChain,
+ IMG_RECT *psDstRect);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSetDCSrcRect (IMG_HANDLE hDevice,
+ IMG_HANDLE hSwapChain,
+ IMG_RECT *psSrcRect);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSetDCDstColourKey (IMG_HANDLE hDevice,
+ IMG_HANDLE hSwapChain,
+ IMG_UINT32 ui32CKColour);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSetDCSrcColourKey (IMG_HANDLE hDevice,
+ IMG_HANDLE hSwapChain,
+ IMG_UINT32 ui32CKColour);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDCBuffers(IMG_HANDLE hDevice,
+ IMG_HANDLE hSwapChain,
+ IMG_HANDLE *phBuffer);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSwapToDCBuffer (IMG_HANDLE hDevice,
+ IMG_HANDLE hBuffer,
+ IMG_UINT32 ui32ClipRectCount,
+ IMG_RECT *psClipRect,
+ IMG_UINT32 ui32SwapInterval,
+ IMG_HANDLE hPrivateTag);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSwapToDCSystem (IMG_HANDLE hDevice,
+ IMG_HANDLE hSwapChain);
+
+
+IMG_IMPORT
+IMG_HANDLE IMG_CALLCONV PVRSRVOpenBCDevice(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ IMG_UINT32 ui32DeviceID);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCloseBCDevice(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_HANDLE hDevice);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetBCBufferInfo(IMG_HANDLE hDevice,
+ BUFFER_INFO *psBuffer);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetBCBuffer(IMG_HANDLE hDevice,
+ IMG_UINT32 ui32BufferIndex,
+ IMG_HANDLE *phBuffer);
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpInit(IMG_CONST PVRSRV_CONNECTION *psConnection);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpStartInitPhase(IMG_CONST PVRSRV_CONNECTION *psConnection);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpStopInitPhase(IMG_CONST PVRSRV_CONNECTION *psConnection);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpMemPol(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ PVRSRV_CLIENT_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask,
+ PDUMP_POLL_OPERATOR eOperator,
+ IMG_UINT32 ui32Flags);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpSyncPol(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ PVRSRV_CLIENT_SYNC_INFO *psClientSyncInfo,
+ IMG_BOOL bIsRead,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpMem(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_PVOID pvAltLinAddr,
+ PVRSRV_CLIENT_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32Flags);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpSync(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_PVOID pvAltLinAddr,
+ PVRSRV_CLIENT_SYNC_INFO *psClientSyncInfo,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Bytes);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpReg(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ IMG_CHAR *pszRegRegion,
+ IMG_UINT32 ui32RegAddr,
+ IMG_UINT32 ui32RegValue,
+ IMG_UINT32 ui32Flags);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpRegPolWithFlags(const PVRSRV_DEV_DATA *psDevData,
+ IMG_CHAR *pszRegRegion,
+ IMG_UINT32 ui32RegAddr,
+ IMG_UINT32 ui32RegValue,
+ IMG_UINT32 ui32Mask,
+ IMG_UINT32 ui32Flags);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpRegPol(const PVRSRV_DEV_DATA *psDevData,
+ IMG_CHAR *pszRegRegion,
+ IMG_UINT32 ui32RegAddr,
+ IMG_UINT32 ui32RegValue,
+ IMG_UINT32 ui32Mask);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpPDReg(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_UINT32 ui32RegAddr,
+ IMG_UINT32 ui32RegValue);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpPDDevPAddr(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ PVRSRV_CLIENT_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Offset,
+ IMG_DEV_PHYADDR sPDDevPAddr);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpMemPages(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_HANDLE hKernelMemInfo,
+ IMG_DEV_PHYADDR *pPages,
+ IMG_UINT32 ui32NumPages,
+ IMG_DEV_VIRTADDR sDevAddr,
+ IMG_UINT32 ui32Start,
+ IMG_UINT32 ui32Length,
+ IMG_BOOL bContinuous);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpSetFrame(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_UINT32 ui32Frame);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpComment(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_CONST IMG_CHAR *pszComment,
+ IMG_BOOL bContinuous);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpCommentf(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_BOOL bContinuous,
+ IMG_CONST IMG_CHAR *pszFormat, ...)
+#if !defined(USE_CODE)
+ IMG_FORMAT_PRINTF(3, 4)
+#endif
+;
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpCommentWithFlagsf(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_UINT32 ui32Flags,
+ IMG_CONST IMG_CHAR *pszFormat, ...)
+#if !defined(USE_CODE)
+ IMG_FORMAT_PRINTF(3, 4)
+#endif
+;
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpDriverInfo(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_CHAR *pszString,
+ IMG_BOOL bContinuous);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpIsCapturing(IMG_CONST PVRSRV_CONNECTION *psConnection,
+ IMG_BOOL *pbIsCapturing);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpBitmap(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32FileOffset,
+ IMG_UINT32 ui32Width,
+ IMG_UINT32 ui32Height,
+ IMG_UINT32 ui32StrideInBytes,
+ IMG_DEV_VIRTADDR sDevBaseAddr,
+ IMG_HANDLE hDevMemContext,
+ IMG_UINT32 ui32Size,
+ PDUMP_PIXEL_FORMAT ePixelFormat,
+ PDUMP_MEM_FORMAT eMemFormat,
+ IMG_UINT32 ui32PDumpFlags);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpRegRead(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ IMG_CONST IMG_CHAR *pszRegRegion,
+ IMG_CONST IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32FileOffset,
+ IMG_UINT32 ui32Address,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32PDumpFlags);
+
+
+IMG_IMPORT
+IMG_BOOL IMG_CALLCONV PVRSRVPDumpIsCapturingTest(IMG_CONST PVRSRV_CONNECTION *psConnection);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVPDumpCycleCountRegRead(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ IMG_UINT32 ui32RegOffset,
+ IMG_BOOL bLastFrame);
+
+IMG_IMPORT IMG_HANDLE PVRSRVLoadLibrary(const IMG_CHAR *pszLibraryName);
+IMG_IMPORT PVRSRV_ERROR PVRSRVUnloadLibrary(IMG_HANDLE hExtDrv);
+IMG_IMPORT PVRSRV_ERROR PVRSRVGetLibFuncAddr(IMG_HANDLE hExtDrv, const IMG_CHAR *pszFunctionName, IMG_VOID **ppvFuncAddr);
+
+IMG_IMPORT IMG_UINT32 PVRSRVClockus (void);
+IMG_IMPORT IMG_VOID PVRSRVWaitus (IMG_UINT32 ui32Timeus);
+IMG_IMPORT IMG_VOID PVRSRVReleaseThreadQuanta (void);
+IMG_IMPORT IMG_UINTPTR_T IMG_CALLCONV PVRSRVGetCurrentProcessID(void);
+IMG_IMPORT IMG_CHAR * IMG_CALLCONV PVRSRVSetLocale(const IMG_CHAR *pszLocale);
+
+
+
+
+
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVCreateAppHintState(IMG_MODULE_ID eModuleID,
+ const IMG_CHAR *pszAppName,
+ IMG_VOID **ppvState);
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVFreeAppHintState(IMG_MODULE_ID eModuleID,
+ IMG_VOID *pvHintState);
+
+IMG_IMPORT IMG_BOOL IMG_CALLCONV PVRSRVGetAppHint(IMG_VOID *pvHintState,
+ const IMG_CHAR *pszHintName,
+ IMG_DATA_TYPE eDataType,
+ const IMG_VOID *pvDefault,
+ IMG_VOID *pvReturn);
+
+IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVAllocUserModeMem (IMG_SIZE_T ui32Size);
+IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVCallocUserModeMem (IMG_SIZE_T ui32Size);
+IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVReallocUserModeMem (IMG_PVOID pvBase, IMG_SIZE_T uNewSize);
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVFreeUserModeMem (IMG_PVOID pvMem);
+IMG_IMPORT IMG_VOID PVRSRVMemCopy(IMG_VOID *pvDst, const IMG_VOID *pvSrc, IMG_SIZE_T ui32Size);
+IMG_IMPORT IMG_VOID PVRSRVMemSet(IMG_VOID *pvDest, IMG_UINT8 ui8Value, IMG_SIZE_T ui32Size);
+
+struct _PVRSRV_MUTEX_OPAQUE_STRUCT_;
+typedef struct _PVRSRV_MUTEX_OPAQUE_STRUCT_ *PVRSRV_MUTEX_HANDLE;
+
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateMutex(PVRSRV_MUTEX_HANDLE *phMutex);
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyMutex(PVRSRV_MUTEX_HANDLE hMutex);
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVLockMutex(PVRSRV_MUTEX_HANDLE hMutex);
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVUnlockMutex(PVRSRV_MUTEX_HANDLE hMutex);
+
+struct _PVRSRV_SEMAPHORE_OPAQUE_STRUCT_;
+typedef struct _PVRSRV_SEMAPHORE_OPAQUE_STRUCT_ *PVRSRV_SEMAPHORE_HANDLE;
+
+
+ #define IMG_SEMAPHORE_WAIT_INFINITE ((IMG_UINT64)0xFFFFFFFFFFFFFFFFull)
+
+
+#if !defined(USE_CODE)
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVCreateSemaphore)
+#endif
+static INLINE PVRSRV_ERROR PVRSRVCreateSemaphore(PVRSRV_SEMAPHORE_HANDLE *phSemaphore, IMG_INT iInitialCount)
+{
+ PVR_UNREFERENCED_PARAMETER(iInitialCount);
+ *phSemaphore = 0;
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVDestroySemaphore)
+#endif
+static INLINE PVRSRV_ERROR PVRSRVDestroySemaphore(PVRSRV_SEMAPHORE_HANDLE hSemaphore)
+{
+ PVR_UNREFERENCED_PARAMETER(hSemaphore);
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVWaitSemaphore)
+#endif
+static INLINE PVRSRV_ERROR PVRSRVWaitSemaphore(PVRSRV_SEMAPHORE_HANDLE hSemaphore, IMG_UINT64 ui64TimeoutMicroSeconds)
+{
+ PVR_UNREFERENCED_PARAMETER(hSemaphore);
+ PVR_UNREFERENCED_PARAMETER(ui64TimeoutMicroSeconds);
+ return PVRSRV_ERROR_INVALID_PARAMS;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVPostSemaphore)
+#endif
+static INLINE IMG_VOID PVRSRVPostSemaphore(PVRSRV_SEMAPHORE_HANDLE hSemaphore, IMG_INT iPostCount)
+{
+ PVR_UNREFERENCED_PARAMETER(hSemaphore);
+ PVR_UNREFERENCED_PARAMETER(iPostCount);
+}
+
+#endif
+
+
+#if (defined(DEBUG) && defined(__linux__))
+IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVAllocUserModeMemTracking(IMG_SIZE_T ui32Size, IMG_CHAR *pszFileName, IMG_UINT32 ui32LineNumber);
+
+IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVCallocUserModeMemTracking(IMG_SIZE_T ui32Size, IMG_CHAR *pszFileName, IMG_UINT32 ui32LineNumber);
+
+IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVFreeUserModeMemTracking(IMG_VOID *pvMem);
+
+IMG_IMPORT IMG_PVOID IMG_CALLCONV PVRSRVReallocUserModeMemTracking(IMG_VOID *pvMem, IMG_SIZE_T ui32NewSize,
+ IMG_CHAR *pszFileName, IMG_UINT32 ui32LineNumber);
+#endif
+
+IMG_IMPORT PVRSRV_ERROR PVRSRVEventObjectWait(const PVRSRV_CONNECTION *psConnection,
+ IMG_HANDLE hOSEvent);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateSyncInfoModObj(const PVRSRV_CONNECTION *psConnection,
+ IMG_HANDLE *phKernelSyncInfoModObj);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroySyncInfoModObj(const PVRSRV_CONNECTION *psConnection,
+ IMG_HANDLE hKernelSyncInfoModObj);
+
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVModifyPendingSyncOps(const PVRSRV_CONNECTION *psConnection,
+ IMG_HANDLE hKernelSyncInfoModObj,
+ PVRSRV_CLIENT_SYNC_INFO *psSyncInfo,
+ IMG_UINT32 ui32ModifyFlags,
+ IMG_UINT32 *pui32ReadOpsPending,
+ IMG_UINT32 *pui32WriteOpsPending);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVModifyCompleteSyncOps(const PVRSRV_CONNECTION *psConnection,
+ IMG_HANDLE hKernelSyncInfoModObj);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSyncOpsFlushToModObj(const PVRSRV_CONNECTION *psConnection,
+ IMG_HANDLE hKernelSyncInfoModObj,
+ IMG_BOOL bWait);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSyncOpsFlushToDelta(const PVRSRV_CONNECTION *psConnection,
+ PVRSRV_CLIENT_SYNC_INFO *psClientSyncInfo,
+ IMG_UINT32 ui32Delta,
+ IMG_BOOL bWait);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAllocSyncInfo(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ PVRSRV_CLIENT_SYNC_INFO **ppsSyncInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeSyncInfo(IMG_CONST PVRSRV_DEV_DATA *psDevData,
+ PVRSRV_CLIENT_SYNC_INFO *psSyncInfo);
+
+IMG_IMPORT
+const IMG_CHAR *PVRSRVGetErrorString(PVRSRV_ERROR eError);
+
+
+#define TIME_NOT_PASSED_UINT32(a,b,c) (((a) - (b)) < (c))
+
+#if defined (__cplusplus)
+}
+#endif
+#endif
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#if !defined (__SERVICESEXT_H__)
+#define __SERVICESEXT_H__
+
+#define PVRSRV_LOCKFLG_READONLY (1)
+
+typedef enum _PVRSRV_ERROR_
+{
+ PVRSRV_OK = 0,
+ PVRSRV_ERROR_GENERIC,
+ PVRSRV_ERROR_OUT_OF_MEMORY,
+ PVRSRV_ERROR_TOO_FEW_BUFFERS,
+ PVRSRV_ERROR_INVALID_PARAMS,
+ PVRSRV_ERROR_INIT_FAILURE,
+ PVRSRV_ERROR_CANT_REGISTER_CALLBACK,
+ PVRSRV_ERROR_INVALID_DEVICE,
+ PVRSRV_ERROR_NOT_OWNER,
+ PVRSRV_ERROR_BAD_MAPPING,
+ PVRSRV_ERROR_TIMEOUT,
+ PVRSRV_ERROR_FLIP_CHAIN_EXISTS,
+ PVRSRV_ERROR_INVALID_SWAPINTERVAL,
+ PVRSRV_ERROR_SCENE_INVALID,
+ PVRSRV_ERROR_STREAM_ERROR,
+ PVRSRV_ERROR_FAILED_DEPENDENCIES,
+ PVRSRV_ERROR_CMD_NOT_PROCESSED,
+ PVRSRV_ERROR_CMD_TOO_BIG,
+ PVRSRV_ERROR_DEVICE_REGISTER_FAILED,
+ PVRSRV_ERROR_TOOMANYBUFFERS,
+ PVRSRV_ERROR_NOT_SUPPORTED,
+ PVRSRV_ERROR_PROCESSING_BLOCKED,
+
+ PVRSRV_ERROR_CANNOT_FLUSH_QUEUE,
+ PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE,
+ PVRSRV_ERROR_CANNOT_GET_RENDERDETAILS,
+ PVRSRV_ERROR_RETRY,
+
+ PVRSRV_ERROR_DDK_VERSION_MISMATCH,
+ PVRSRV_ERROR_BUILD_MISMATCH,
+ PVRSRV_ERROR_CORE_REVISION_MISMATCH,
+
+ PVRSRV_ERROR_UPLOAD_TOO_BIG,
+
+ PVRSRV_ERROR_INVALID_FLAGS,
+ PVRSRV_ERROR_FAILED_TO_REGISTER_PROCESS,
+
+ PVRSRV_ERROR_UNABLE_TO_LOAD_LIBRARY,
+ PVRSRV_ERROR_UNABLE_GET_FUNC_ADDR,
+ PVRSRV_ERROR_UNLOAD_LIBRARY_FAILED,
+
+ PVRSRV_ERROR_BRIDGE_CALL_FAILED,
+ PVRSRV_ERROR_IOCTL_CALL_FAILED,
+
+ PVRSRV_ERROR_MMU_CONTEXT_NOT_FOUND,
+ PVRSRV_ERROR_BUFFER_DEVICE_NOT_FOUND,
+ PVRSRV_ERROR_BUFFER_DEVICE_ALREADY_PRESENT,
+
+ PVRSRV_ERROR_PCI_DEVICE_NOT_FOUND,
+ PVRSRV_ERROR_PCI_CALL_FAILED,
+ PVRSRV_ERROR_PCI_REGION_TOO_SMALL,
+ PVRSRV_ERROR_PCI_REGION_UNAVAILABLE,
+ PVRSRV_ERROR_BAD_REGION_SIZE_MISMATCH,
+
+ PVRSRV_ERROR_REGISTER_BASE_NOT_SET,
+
+ PVRSRV_ERROR_FAILED_TO_ALLOC_USER_MEM,
+ PVRSRV_ERROR_FAILED_TO_ALLOC_VP_MEMORY,
+ PVRSRV_ERROR_FAILED_TO_MAP_SHARED_PBDESC,
+ PVRSRV_ERROR_FAILED_TO_GET_PHYS_ADDR,
+
+ PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY,
+ PVRSRV_ERROR_FAILED_TO_COPY_VIRT_MEMORY,
+
+ PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES,
+ PVRSRV_ERROR_FAILED_TO_FREE_PAGES,
+ PVRSRV_ERROR_FAILED_TO_COPY_PAGES,
+ PVRSRV_ERROR_UNABLE_TO_LOCK_PAGES,
+ PVRSRV_ERROR_UNABLE_TO_UNLOCK_PAGES,
+ PVRSRV_ERROR_STILL_MAPPED,
+ PVRSRV_ERROR_MAPPING_NOT_FOUND,
+ PVRSRV_ERROR_PHYS_ADDRESS_EXCEEDS_32BIT,
+ PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE,
+
+ PVRSRV_ERROR_INVALID_SEGMENT_BLOCK,
+ PVRSRV_ERROR_INVALID_SGXDEVDATA,
+ PVRSRV_ERROR_INVALID_DEVINFO,
+ PVRSRV_ERROR_INVALID_MEMINFO,
+ PVRSRV_ERROR_INVALID_MISCINFO,
+ PVRSRV_ERROR_UNKNOWN_IOCTL,
+ PVRSRV_ERROR_INVALID_CONTEXT,
+ PVRSRV_ERROR_UNABLE_TO_DESTROY_CONTEXT,
+ PVRSRV_ERROR_INVALID_HEAP,
+ PVRSRV_ERROR_INVALID_KERNELINFO,
+ PVRSRV_ERROR_UNKNOWN_POWER_STATE,
+ PVRSRV_ERROR_INVALID_HANDLE_TYPE,
+ PVRSRV_ERROR_INVALID_WRAP_TYPE,
+ PVRSRV_ERROR_INVALID_PHYS_ADDR,
+ PVRSRV_ERROR_INVALID_CPU_ADDR,
+ PVRSRV_ERROR_INVALID_HEAPINFO,
+ PVRSRV_ERROR_INVALID_PERPROC,
+ PVRSRV_ERROR_FAILED_TO_RETRIEVE_HEAPINFO,
+ PVRSRV_ERROR_INVALID_MAP_REQUEST,
+ PVRSRV_ERROR_INVALID_UNMAP_REQUEST,
+ PVRSRV_ERROR_UNABLE_TO_FIND_MAPPING_HEAP,
+ PVRSRV_ERROR_MAPPING_STILL_IN_USE,
+
+ PVRSRV_ERROR_EXCEEDED_HW_LIMITS,
+ PVRSRV_ERROR_NO_STAGING_BUFFER_ALLOCATED,
+
+ PVRSRV_ERROR_UNABLE_TO_CREATE_PERPROC_AREA,
+ PVRSRV_ERROR_UNABLE_TO_CREATE_EVENT,
+ PVRSRV_ERROR_UNABLE_TO_ENABLE_EVENT,
+ PVRSRV_ERROR_UNABLE_TO_REGISTER_EVENT,
+ PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT,
+ PVRSRV_ERROR_UNABLE_TO_CREATE_THREAD,
+ PVRSRV_ERROR_UNABLE_TO_CLOSE_THREAD,
+ PVRSRV_ERROR_THREAD_READ_ERROR,
+ PVRSRV_ERROR_UNABLE_TO_REGISTER_ISR_HANDLER,
+ PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR,
+ PVRSRV_ERROR_UNABLE_TO_UNINSTALL_ISR,
+ PVRSRV_ERROR_ISR_ALREADY_INSTALLED,
+ PVRSRV_ERROR_ISR_NOT_INSTALLED,
+ PVRSRV_ERROR_UNABLE_TO_INITIALISE_INTERRUPT,
+ PVRSRV_ERROR_UNABLE_TO_RETRIEVE_INFO,
+ PVRSRV_ERROR_UNABLE_TO_DO_BACKWARDS_BLIT,
+ PVRSRV_ERROR_UNABLE_TO_CLOSE_SERVICES,
+ PVRSRV_ERROR_UNABLE_TO_REGISTER_CONTEXT,
+ PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE,
+
+ PVRSRV_ERROR_INVALID_CCB_COMMAND,
+
+ PVRSRV_ERROR_UNABLE_TO_LOCK_RESOURCE,
+ PVRSRV_ERROR_INVALID_LOCK_ID,
+ PVRSRV_ERROR_RESOURCE_NOT_LOCKED,
+
+ PVRSRV_ERROR_FLIP_FAILED,
+ PVRSRV_ERROR_UNBLANK_DISPLAY_FAILED,
+
+ PVRSRV_ERROR_TIMEOUT_POLLING_FOR_VALUE,
+
+ PVRSRV_ERROR_CREATE_RENDER_CONTEXT_FAILED,
+ PVRSRV_ERROR_UNKNOWN_PRIMARY_FRAG,
+ PVRSRV_ERROR_UNEXPECTED_SECONDARY_FRAG,
+ PVRSRV_ERROR_UNEXPECTED_PRIMARY_FRAG,
+
+ PVRSRV_ERROR_UNABLE_TO_INSERT_FENCE_ID,
+
+ PVRSRV_ERROR_BLIT_SETUP_FAILED,
+
+ PVRSRV_ERROR_PDUMP_NOT_AVAILABLE,
+ PVRSRV_ERROR_PDUMP_BUFFER_FULL,
+ PVRSRV_ERROR_PDUMP_BUF_OVERFLOW,
+ PVRSRV_ERROR_PDUMP_NOT_ACTIVE,
+ PVRSRV_ERROR_INCOMPLETE_LINE_OVERLAPS_PAGES,
+
+ PVRSRV_ERROR_MUTEX_DESTROY_FAILED,
+ PVRSRV_ERROR_MUTEX_INTERRUPTIBLE_ERROR,
+
+ PVRSRV_ERROR_INSUFFICIENT_SCRIPT_SPACE,
+ PVRSRV_ERROR_INSUFFICIENT_SPACE_FOR_COMMAND,
+
+ PVRSRV_ERROR_PROCESS_NOT_INITIALISED,
+ PVRSRV_ERROR_PROCESS_NOT_FOUND,
+ PVRSRV_ERROR_SRV_CONNECT_FAILED,
+ PVRSRV_ERROR_SRV_DISCONNECT_FAILED,
+ PVRSRV_ERROR_DEINT_PHASE_FAILED,
+ PVRSRV_ERROR_INIT2_PHASE_FAILED,
+
+ PVRSRV_ERROR_UNABLE_TO_FIND_RESOURCE,
+
+ PVRSRV_ERROR_NO_DC_DEVICES_FOUND,
+ PVRSRV_ERROR_UNABLE_TO_OPEN_DC_DEVICE,
+ PVRSRV_ERROR_UNABLE_TO_REMOVE_DEVICE,
+ PVRSRV_ERROR_NO_DEVICEDATA_FOUND,
+ PVRSRV_ERROR_NO_DEVICENODE_FOUND,
+ PVRSRV_ERROR_NO_CLIENTNODE_FOUND,
+ PVRSRV_ERROR_FAILED_TO_PROCESS_QUEUE,
+
+ PVRSRV_ERROR_UNABLE_TO_INIT_TASK,
+ PVRSRV_ERROR_UNABLE_TO_SCHEDULE_TASK,
+ PVRSRV_ERROR_UNABLE_TO_KILL_TASK,
+
+ PVRSRV_ERROR_UNABLE_TO_ENABLE_TIMER,
+ PVRSRV_ERROR_UNABLE_TO_DISABLE_TIMER,
+ PVRSRV_ERROR_UNABLE_TO_REMOVE_TIMER,
+
+ PVRSRV_ERROR_UNKNOWN_PIXEL_FORMAT,
+ PVRSRV_ERROR_UNKNOWN_SCRIPT_OPERATION,
+
+ PVRSRV_ERROR_HANDLE_INDEX_OUT_OF_RANGE,
+ PVRSRV_ERROR_HANDLE_NOT_ALLOCATED,
+ PVRSRV_ERROR_HANDLE_TYPE_MISMATCH,
+ PVRSRV_ERROR_UNABLE_TO_ADD_HANDLE,
+ PVRSRV_ERROR_HANDLE_NOT_SHAREABLE,
+ PVRSRV_ERROR_HANDLE_NOT_FOUND,
+ PVRSRV_ERROR_INVALID_SUBHANDLE,
+ PVRSRV_ERROR_HANDLE_BATCH_IN_USE,
+ PVRSRV_ERROR_HANDLE_BATCH_COMMIT_FAILURE,
+
+ PVRSRV_ERROR_UNABLE_TO_CREATE_HASH_TABLE,
+ PVRSRV_ERROR_INSERT_HASH_TABLE_DATA_FAILED,
+
+ PVRSRV_ERROR_UNSUPPORTED_BACKING_STORE,
+ PVRSRV_ERROR_UNABLE_TO_DESTROY_BM_HEAP,
+
+ PVRSRV_ERROR_UNKNOWN_INIT_SERVER_STATE,
+
+ PVRSRV_ERROR_NO_FREE_DEVICEIDS_AVALIABLE,
+ PVRSRV_ERROR_INVALID_DEVICEID,
+ PVRSRV_ERROR_DEVICEID_NOT_FOUND,
+
+ PVRSRV_ERROR_MEMORY_TEST_FAILED,
+ PVRSRV_ERROR_CPUPADDR_TEST_FAILED,
+ PVRSRV_ERROR_COPY_TEST_FAILED,
+
+ PVRSRV_ERROR_SEMAPHORE_NOT_INITIALISED,
+
+ PVRSRV_ERROR_UNABLE_TO_RELEASE_CLOCK,
+ PVRSRV_ERROR_CLOCK_REQUEST_FAILED,
+ PVRSRV_ERROR_DISABLE_CLOCK_FAILURE,
+ PVRSRV_ERROR_UNABLE_TO_SET_CLOCK_RATE,
+ PVRSRV_ERROR_UNABLE_TO_ROUND_CLOCK_RATE,
+ PVRSRV_ERROR_UNABLE_TO_ENABLE_CLOCK,
+ PVRSRV_ERROR_UNABLE_TO_GET_CLOCK,
+ PVRSRV_ERROR_UNABLE_TO_GET_PARENT_CLOCK,
+ PVRSRV_ERROR_UNABLE_TO_GET_SYSTEM_CLOCK,
+
+ PVRSRV_ERROR_UNKNOWN_SGL_ERROR,
+
+ PVRSRV_ERROR_SYSTEM_POWER_CHANGE_FAILURE,
+ PVRSRV_ERROR_DEVICE_POWER_CHANGE_FAILURE,
+
+ PVRSRV_ERROR_BAD_SYNC_STATE,
+
+ PVRSRV_ERROR_CACHEOP_FAILED,
+
+ PVRSRV_ERROR_FORCE_I32 = 0x7fffffff
+
+} PVRSRV_ERROR;
+
+
+typedef enum _PVRSRV_DEVICE_CLASS_
+{
+ PVRSRV_DEVICE_CLASS_3D = 0 ,
+ PVRSRV_DEVICE_CLASS_DISPLAY = 1 ,
+ PVRSRV_DEVICE_CLASS_BUFFER = 2 ,
+ PVRSRV_DEVICE_CLASS_VIDEO = 3 ,
+
+ PVRSRV_DEVICE_CLASS_FORCE_I32 = 0x7fffffff
+
+} PVRSRV_DEVICE_CLASS;
+
+
+typedef enum _PVRSRV_SYS_POWER_STATE_
+{
+ PVRSRV_SYS_POWER_STATE_Unspecified = -1,
+ PVRSRV_SYS_POWER_STATE_D0 = 0,
+ PVRSRV_SYS_POWER_STATE_D1 = 1,
+ PVRSRV_SYS_POWER_STATE_D2 = 2,
+ PVRSRV_SYS_POWER_STATE_D3 = 3,
+ PVRSRV_SYS_POWER_STATE_D4 = 4,
+
+ PVRSRV_SYS_POWER_STATE_FORCE_I32 = 0x7fffffff
+
+} PVRSRV_SYS_POWER_STATE, *PPVRSRV_SYS_POWER_STATE;
+
+
+typedef enum _PVRSRV_DEV_POWER_STATE_
+{
+ PVRSRV_DEV_POWER_STATE_DEFAULT = -1,
+ PVRSRV_DEV_POWER_STATE_ON = 0,
+ PVRSRV_DEV_POWER_STATE_IDLE = 1,
+ PVRSRV_DEV_POWER_STATE_OFF = 2,
+
+ PVRSRV_DEV_POWER_STATE_FORCE_I32 = 0x7fffffff
+
+} PVRSRV_DEV_POWER_STATE, *PPVRSRV_DEV_POWER_STATE;
+
+
+typedef PVRSRV_ERROR (*PFN_PRE_POWER) (IMG_HANDLE hDevHandle,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+typedef PVRSRV_ERROR (*PFN_POST_POWER) (IMG_HANDLE hDevHandle,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+
+typedef PVRSRV_ERROR (*PFN_PRE_CLOCKSPEED_CHANGE) (IMG_HANDLE hDevHandle,
+ IMG_BOOL bIdleDevice,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+typedef PVRSRV_ERROR (*PFN_POST_CLOCKSPEED_CHANGE) (IMG_HANDLE hDevHandle,
+ IMG_BOOL bIdleDevice,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+
+
+typedef enum _PVRSRV_PIXEL_FORMAT_ {
+
+ PVRSRV_PIXEL_FORMAT_UNKNOWN = 0,
+ PVRSRV_PIXEL_FORMAT_RGB565 = 1,
+ PVRSRV_PIXEL_FORMAT_RGB555 = 2,
+ PVRSRV_PIXEL_FORMAT_RGB888 = 3,
+ PVRSRV_PIXEL_FORMAT_BGR888 = 4,
+ PVRSRV_PIXEL_FORMAT_GREY_SCALE = 8,
+ PVRSRV_PIXEL_FORMAT_PAL12 = 13,
+ PVRSRV_PIXEL_FORMAT_PAL8 = 14,
+ PVRSRV_PIXEL_FORMAT_PAL4 = 15,
+ PVRSRV_PIXEL_FORMAT_PAL2 = 16,
+ PVRSRV_PIXEL_FORMAT_PAL1 = 17,
+ PVRSRV_PIXEL_FORMAT_ARGB1555 = 18,
+ PVRSRV_PIXEL_FORMAT_ARGB4444 = 19,
+ PVRSRV_PIXEL_FORMAT_ARGB8888 = 20,
+ PVRSRV_PIXEL_FORMAT_ABGR8888 = 21,
+ PVRSRV_PIXEL_FORMAT_YV12 = 22,
+ PVRSRV_PIXEL_FORMAT_I420 = 23,
+ PVRSRV_PIXEL_FORMAT_IMC2 = 25,
+ PVRSRV_PIXEL_FORMAT_XRGB8888 = 26,
+ PVRSRV_PIXEL_FORMAT_XBGR8888 = 27,
+ PVRSRV_PIXEL_FORMAT_BGRA8888 = 28,
+ PVRSRV_PIXEL_FORMAT_XRGB4444 = 29,
+ PVRSRV_PIXEL_FORMAT_ARGB8332 = 30,
+ PVRSRV_PIXEL_FORMAT_A2RGB10 = 31,
+ PVRSRV_PIXEL_FORMAT_A2BGR10 = 32,
+ PVRSRV_PIXEL_FORMAT_P8 = 33,
+ PVRSRV_PIXEL_FORMAT_L8 = 34,
+ PVRSRV_PIXEL_FORMAT_A8L8 = 35,
+ PVRSRV_PIXEL_FORMAT_A4L4 = 36,
+ PVRSRV_PIXEL_FORMAT_L16 = 37,
+ PVRSRV_PIXEL_FORMAT_L6V5U5 = 38,
+ PVRSRV_PIXEL_FORMAT_V8U8 = 39,
+ PVRSRV_PIXEL_FORMAT_V16U16 = 40,
+ PVRSRV_PIXEL_FORMAT_QWVU8888 = 41,
+ PVRSRV_PIXEL_FORMAT_XLVU8888 = 42,
+ PVRSRV_PIXEL_FORMAT_QWVU16 = 43,
+ PVRSRV_PIXEL_FORMAT_D16 = 44,
+ PVRSRV_PIXEL_FORMAT_D24S8 = 45,
+ PVRSRV_PIXEL_FORMAT_D24X8 = 46,
+
+
+ PVRSRV_PIXEL_FORMAT_ABGR16 = 47,
+ PVRSRV_PIXEL_FORMAT_ABGR16F = 48,
+ PVRSRV_PIXEL_FORMAT_ABGR32 = 49,
+ PVRSRV_PIXEL_FORMAT_ABGR32F = 50,
+ PVRSRV_PIXEL_FORMAT_B10GR11 = 51,
+ PVRSRV_PIXEL_FORMAT_GR88 = 52,
+ PVRSRV_PIXEL_FORMAT_BGR32 = 53,
+ PVRSRV_PIXEL_FORMAT_GR32 = 54,
+ PVRSRV_PIXEL_FORMAT_E5BGR9 = 55,
+
+
+ PVRSRV_PIXEL_FORMAT_RESERVED1 = 56,
+ PVRSRV_PIXEL_FORMAT_RESERVED2 = 57,
+ PVRSRV_PIXEL_FORMAT_RESERVED3 = 58,
+ PVRSRV_PIXEL_FORMAT_RESERVED4 = 59,
+ PVRSRV_PIXEL_FORMAT_RESERVED5 = 60,
+
+
+ PVRSRV_PIXEL_FORMAT_R8G8_B8G8 = 61,
+ PVRSRV_PIXEL_FORMAT_G8R8_G8B8 = 62,
+
+
+ PVRSRV_PIXEL_FORMAT_NV11 = 63,
+ PVRSRV_PIXEL_FORMAT_NV12 = 64,
+
+
+ PVRSRV_PIXEL_FORMAT_YUY2 = 65,
+ PVRSRV_PIXEL_FORMAT_YUV420 = 66,
+ PVRSRV_PIXEL_FORMAT_YUV444 = 67,
+ PVRSRV_PIXEL_FORMAT_VUY444 = 68,
+ PVRSRV_PIXEL_FORMAT_YUYV = 69,
+ PVRSRV_PIXEL_FORMAT_YVYU = 70,
+ PVRSRV_PIXEL_FORMAT_UYVY = 71,
+ PVRSRV_PIXEL_FORMAT_VYUY = 72,
+
+ PVRSRV_PIXEL_FORMAT_FOURCC_ORG_UYVY = 73,
+ PVRSRV_PIXEL_FORMAT_FOURCC_ORG_YUYV = 74,
+ PVRSRV_PIXEL_FORMAT_FOURCC_ORG_YVYU = 75,
+ PVRSRV_PIXEL_FORMAT_FOURCC_ORG_VYUY = 76,
+ PVRSRV_PIXEL_FORMAT_FOURCC_ORG_AYUV = 77,
+
+
+ PVRSRV_PIXEL_FORMAT_A32B32G32R32 = 78,
+ PVRSRV_PIXEL_FORMAT_A32B32G32R32F = 79,
+ PVRSRV_PIXEL_FORMAT_A32B32G32R32_UINT = 80,
+ PVRSRV_PIXEL_FORMAT_A32B32G32R32_SINT = 81,
+
+
+ PVRSRV_PIXEL_FORMAT_B32G32R32 = 82,
+ PVRSRV_PIXEL_FORMAT_B32G32R32F = 83,
+ PVRSRV_PIXEL_FORMAT_B32G32R32_UINT = 84,
+ PVRSRV_PIXEL_FORMAT_B32G32R32_SINT = 85,
+
+
+ PVRSRV_PIXEL_FORMAT_G32R32 = 86,
+ PVRSRV_PIXEL_FORMAT_G32R32F = 87,
+ PVRSRV_PIXEL_FORMAT_G32R32_UINT = 88,
+ PVRSRV_PIXEL_FORMAT_G32R32_SINT = 89,
+
+
+ PVRSRV_PIXEL_FORMAT_D32F = 90,
+ PVRSRV_PIXEL_FORMAT_R32 = 91,
+ PVRSRV_PIXEL_FORMAT_R32F = 92,
+ PVRSRV_PIXEL_FORMAT_R32_UINT = 93,
+ PVRSRV_PIXEL_FORMAT_R32_SINT = 94,
+
+
+ PVRSRV_PIXEL_FORMAT_A16B16G16R16 = 95,
+ PVRSRV_PIXEL_FORMAT_A16B16G16R16F = 96,
+ PVRSRV_PIXEL_FORMAT_A16B16G16R16_SINT = 97,
+ PVRSRV_PIXEL_FORMAT_A16B16G16R16_SNORM = 98,
+ PVRSRV_PIXEL_FORMAT_A16B16G16R16_UINT = 99,
+ PVRSRV_PIXEL_FORMAT_A16B16G16R16_UNORM = 100,
+
+
+ PVRSRV_PIXEL_FORMAT_G16R16 = 101,
+ PVRSRV_PIXEL_FORMAT_G16R16F = 102,
+ PVRSRV_PIXEL_FORMAT_G16R16_UINT = 103,
+ PVRSRV_PIXEL_FORMAT_G16R16_UNORM = 104,
+ PVRSRV_PIXEL_FORMAT_G16R16_SINT = 105,
+ PVRSRV_PIXEL_FORMAT_G16R16_SNORM = 106,
+
+
+ PVRSRV_PIXEL_FORMAT_R16 = 107,
+ PVRSRV_PIXEL_FORMAT_R16F = 108,
+ PVRSRV_PIXEL_FORMAT_R16_UINT = 109,
+ PVRSRV_PIXEL_FORMAT_R16_UNORM = 110,
+ PVRSRV_PIXEL_FORMAT_R16_SINT = 111,
+ PVRSRV_PIXEL_FORMAT_R16_SNORM = 112,
+
+
+ PVRSRV_PIXEL_FORMAT_X8R8G8B8 = 113,
+ PVRSRV_PIXEL_FORMAT_X8R8G8B8_UNORM = 114,
+ PVRSRV_PIXEL_FORMAT_X8R8G8B8_UNORM_SRGB = 115,
+
+ PVRSRV_PIXEL_FORMAT_A8R8G8B8 = 116,
+ PVRSRV_PIXEL_FORMAT_A8R8G8B8_UNORM = 117,
+ PVRSRV_PIXEL_FORMAT_A8R8G8B8_UNORM_SRGB = 118,
+
+ PVRSRV_PIXEL_FORMAT_A8B8G8R8 = 119,
+ PVRSRV_PIXEL_FORMAT_A8B8G8R8_UINT = 120,
+ PVRSRV_PIXEL_FORMAT_A8B8G8R8_UNORM = 121,
+ PVRSRV_PIXEL_FORMAT_A8B8G8R8_UNORM_SRGB = 122,
+ PVRSRV_PIXEL_FORMAT_A8B8G8R8_SINT = 123,
+ PVRSRV_PIXEL_FORMAT_A8B8G8R8_SNORM = 124,
+
+
+ PVRSRV_PIXEL_FORMAT_G8R8 = 125,
+ PVRSRV_PIXEL_FORMAT_G8R8_UINT = 126,
+ PVRSRV_PIXEL_FORMAT_G8R8_UNORM = 127,
+ PVRSRV_PIXEL_FORMAT_G8R8_SINT = 128,
+ PVRSRV_PIXEL_FORMAT_G8R8_SNORM = 129,
+
+
+ PVRSRV_PIXEL_FORMAT_A8 = 130,
+ PVRSRV_PIXEL_FORMAT_R8 = 131,
+ PVRSRV_PIXEL_FORMAT_R8_UINT = 132,
+ PVRSRV_PIXEL_FORMAT_R8_UNORM = 133,
+ PVRSRV_PIXEL_FORMAT_R8_SINT = 134,
+ PVRSRV_PIXEL_FORMAT_R8_SNORM = 135,
+
+
+ PVRSRV_PIXEL_FORMAT_A2B10G10R10 = 136,
+ PVRSRV_PIXEL_FORMAT_A2B10G10R10_UNORM = 137,
+ PVRSRV_PIXEL_FORMAT_A2B10G10R10_UINT = 138,
+
+
+ PVRSRV_PIXEL_FORMAT_B10G11R11 = 139,
+ PVRSRV_PIXEL_FORMAT_B10G11R11F = 140,
+
+
+ PVRSRV_PIXEL_FORMAT_X24G8R32 = 141,
+ PVRSRV_PIXEL_FORMAT_G8R24 = 142,
+ PVRSRV_PIXEL_FORMAT_X8R24 = 143,
+ PVRSRV_PIXEL_FORMAT_E5B9G9R9 = 144,
+ PVRSRV_PIXEL_FORMAT_R1 = 145,
+
+ PVRSRV_PIXEL_FORMAT_RESERVED6 = 146,
+ PVRSRV_PIXEL_FORMAT_RESERVED7 = 147,
+ PVRSRV_PIXEL_FORMAT_RESERVED8 = 148,
+ PVRSRV_PIXEL_FORMAT_RESERVED9 = 149,
+ PVRSRV_PIXEL_FORMAT_RESERVED10 = 150,
+ PVRSRV_PIXEL_FORMAT_RESERVED11 = 151,
+ PVRSRV_PIXEL_FORMAT_RESERVED12 = 152,
+ PVRSRV_PIXEL_FORMAT_RESERVED13 = 153,
+ PVRSRV_PIXEL_FORMAT_RESERVED14 = 154,
+ PVRSRV_PIXEL_FORMAT_RESERVED15 = 155,
+ PVRSRV_PIXEL_FORMAT_RESERVED16 = 156,
+ PVRSRV_PIXEL_FORMAT_RESERVED17 = 157,
+ PVRSRV_PIXEL_FORMAT_RESERVED18 = 158,
+ PVRSRV_PIXEL_FORMAT_RESERVED19 = 159,
+ PVRSRV_PIXEL_FORMAT_RESERVED20 = 160,
+
+
+ PVRSRV_PIXEL_FORMAT_UBYTE4 = 161,
+ PVRSRV_PIXEL_FORMAT_SHORT4 = 162,
+ PVRSRV_PIXEL_FORMAT_SHORT4N = 163,
+ PVRSRV_PIXEL_FORMAT_USHORT4N = 164,
+ PVRSRV_PIXEL_FORMAT_SHORT2N = 165,
+ PVRSRV_PIXEL_FORMAT_SHORT2 = 166,
+ PVRSRV_PIXEL_FORMAT_USHORT2N = 167,
+ PVRSRV_PIXEL_FORMAT_UDEC3 = 168,
+ PVRSRV_PIXEL_FORMAT_DEC3N = 169,
+ PVRSRV_PIXEL_FORMAT_F16_2 = 170,
+ PVRSRV_PIXEL_FORMAT_F16_4 = 171,
+
+
+ PVRSRV_PIXEL_FORMAT_L_F16 = 172,
+ PVRSRV_PIXEL_FORMAT_L_F16_REP = 173,
+ PVRSRV_PIXEL_FORMAT_L_F16_A_F16 = 174,
+ PVRSRV_PIXEL_FORMAT_A_F16 = 175,
+ PVRSRV_PIXEL_FORMAT_B16G16R16F = 176,
+
+ PVRSRV_PIXEL_FORMAT_L_F32 = 177,
+ PVRSRV_PIXEL_FORMAT_A_F32 = 178,
+ PVRSRV_PIXEL_FORMAT_L_F32_A_F32 = 179,
+
+
+ PVRSRV_PIXEL_FORMAT_PVRTC2 = 180,
+ PVRSRV_PIXEL_FORMAT_PVRTC4 = 181,
+ PVRSRV_PIXEL_FORMAT_PVRTCII2 = 182,
+ PVRSRV_PIXEL_FORMAT_PVRTCII4 = 183,
+ PVRSRV_PIXEL_FORMAT_PVRTCIII = 184,
+ PVRSRV_PIXEL_FORMAT_PVRO8 = 185,
+ PVRSRV_PIXEL_FORMAT_PVRO88 = 186,
+ PVRSRV_PIXEL_FORMAT_PT1 = 187,
+ PVRSRV_PIXEL_FORMAT_PT2 = 188,
+ PVRSRV_PIXEL_FORMAT_PT4 = 189,
+ PVRSRV_PIXEL_FORMAT_PT8 = 190,
+ PVRSRV_PIXEL_FORMAT_PTW = 191,
+ PVRSRV_PIXEL_FORMAT_PTB = 192,
+ PVRSRV_PIXEL_FORMAT_MONO8 = 193,
+ PVRSRV_PIXEL_FORMAT_MONO16 = 194,
+
+
+ PVRSRV_PIXEL_FORMAT_C0_YUYV = 195,
+ PVRSRV_PIXEL_FORMAT_C0_UYVY = 196,
+ PVRSRV_PIXEL_FORMAT_C0_YVYU = 197,
+ PVRSRV_PIXEL_FORMAT_C0_VYUY = 198,
+ PVRSRV_PIXEL_FORMAT_C1_YUYV = 199,
+ PVRSRV_PIXEL_FORMAT_C1_UYVY = 200,
+ PVRSRV_PIXEL_FORMAT_C1_YVYU = 201,
+ PVRSRV_PIXEL_FORMAT_C1_VYUY = 202,
+
+
+ PVRSRV_PIXEL_FORMAT_C0_YUV420_2P_UV = 203,
+ PVRSRV_PIXEL_FORMAT_C0_YUV420_2P_VU = 204,
+ PVRSRV_PIXEL_FORMAT_C0_YUV420_3P = 205,
+ PVRSRV_PIXEL_FORMAT_C1_YUV420_2P_UV = 206,
+ PVRSRV_PIXEL_FORMAT_C1_YUV420_2P_VU = 207,
+ PVRSRV_PIXEL_FORMAT_C1_YUV420_3P = 208,
+
+ PVRSRV_PIXEL_FORMAT_A2B10G10R10F = 209,
+ PVRSRV_PIXEL_FORMAT_B8G8R8_SINT = 210,
+ PVRSRV_PIXEL_FORMAT_PVRF32SIGNMASK = 211,
+
+ PVRSRV_PIXEL_FORMAT_ABGR4444 = 212,
+ PVRSRV_PIXEL_FORMAT_ABGR1555 = 213,
+ PVRSRV_PIXEL_FORMAT_BGR565 = 214,
+
+ PVRSRV_PIXEL_FORMAT_FORCE_I32 = 0x7fffffff
+
+} PVRSRV_PIXEL_FORMAT;
+
+typedef enum _PVRSRV_ALPHA_FORMAT_ {
+ PVRSRV_ALPHA_FORMAT_UNKNOWN = 0x00000000,
+ PVRSRV_ALPHA_FORMAT_PRE = 0x00000001,
+ PVRSRV_ALPHA_FORMAT_NONPRE = 0x00000002,
+ PVRSRV_ALPHA_FORMAT_MASK = 0x0000000F,
+} PVRSRV_ALPHA_FORMAT;
+
+typedef enum _PVRSRV_COLOURSPACE_FORMAT_ {
+ PVRSRV_COLOURSPACE_FORMAT_UNKNOWN = 0x00000000,
+ PVRSRV_COLOURSPACE_FORMAT_LINEAR = 0x00010000,
+ PVRSRV_COLOURSPACE_FORMAT_NONLINEAR = 0x00020000,
+ PVRSRV_COLOURSPACE_FORMAT_MASK = 0x000F0000,
+} PVRSRV_COLOURSPACE_FORMAT;
+
+
+typedef enum _PVRSRV_ROTATION_ {
+ PVRSRV_ROTATE_0 = 0,
+ PVRSRV_ROTATE_90 = 1,
+ PVRSRV_ROTATE_180 = 2,
+ PVRSRV_ROTATE_270 = 3,
+ PVRSRV_FLIP_Y
+
+} PVRSRV_ROTATION;
+
+#define PVRSRV_CREATE_SWAPCHAIN_SHARED (1<<0)
+#define PVRSRV_CREATE_SWAPCHAIN_QUERY (1<<1)
+#define PVRSRV_CREATE_SWAPCHAIN_OEMOVERLAY (1<<2)
+
+typedef struct _PVRSRV_SYNC_DATA_
+{
+
+ IMG_UINT32 ui32WriteOpsPending;
+ volatile IMG_UINT32 ui32WriteOpsComplete;
+
+
+ IMG_UINT32 ui32ReadOpsPending;
+ volatile IMG_UINT32 ui32ReadOpsComplete;
+
+
+ IMG_UINT32 ui32LastOpDumpVal;
+ IMG_UINT32 ui32LastReadOpDumpVal;
+
+} PVRSRV_SYNC_DATA;
+
+typedef struct _PVRSRV_CLIENT_SYNC_INFO_
+{
+
+ PVRSRV_SYNC_DATA *psSyncData;
+
+
+
+
+
+ IMG_DEV_VIRTADDR sWriteOpsCompleteDevVAddr;
+
+
+ IMG_DEV_VIRTADDR sReadOpsCompleteDevVAddr;
+
+
+ IMG_HANDLE hMappingInfo;
+
+
+ IMG_HANDLE hKernelSyncInfo;
+
+} PVRSRV_CLIENT_SYNC_INFO, *PPVRSRV_CLIENT_SYNC_INFO;
+
+typedef struct PVRSRV_RESOURCE_TAG
+{
+ volatile IMG_UINT32 ui32Lock;
+ IMG_UINT32 ui32ID;
+}PVRSRV_RESOURCE;
+typedef PVRSRV_RESOURCE PVRSRV_RES_HANDLE;
+
+
+typedef IMG_VOID (*PFN_CMD_COMPLETE) (IMG_HANDLE);
+typedef IMG_VOID (**PPFN_CMD_COMPLETE) (IMG_HANDLE);
+
+typedef IMG_BOOL (*PFN_CMD_PROC) (IMG_HANDLE, IMG_UINT32, IMG_VOID*);
+typedef IMG_BOOL (**PPFN_CMD_PROC) (IMG_HANDLE, IMG_UINT32, IMG_VOID*);
+
+
+typedef struct _IMG_RECT_
+{
+ IMG_INT32 x0;
+ IMG_INT32 y0;
+ IMG_INT32 x1;
+ IMG_INT32 y1;
+}IMG_RECT;
+
+typedef struct _IMG_RECT_16_
+{
+ IMG_INT16 x0;
+ IMG_INT16 y0;
+ IMG_INT16 x1;
+ IMG_INT16 y1;
+}IMG_RECT_16;
+
+
+typedef PVRSRV_ERROR (*PFN_GET_BUFFER_ADDR)(IMG_HANDLE,
+ IMG_HANDLE,
+ IMG_SYS_PHYADDR**,
+ IMG_SIZE_T*,
+ IMG_VOID**,
+ IMG_HANDLE*,
+ IMG_BOOL*,
+ IMG_UINT32*);
+
+
+typedef struct DISPLAY_DIMS_TAG
+{
+ IMG_UINT32 ui32ByteStride;
+ IMG_UINT32 ui32Width;
+ IMG_UINT32 ui32Height;
+} DISPLAY_DIMS;
+
+
+typedef struct DISPLAY_FORMAT_TAG
+{
+
+ PVRSRV_PIXEL_FORMAT pixelformat;
+} DISPLAY_FORMAT;
+
+typedef struct DISPLAY_SURF_ATTRIBUTES_TAG
+{
+
+ PVRSRV_PIXEL_FORMAT pixelformat;
+
+ DISPLAY_DIMS sDims;
+} DISPLAY_SURF_ATTRIBUTES;
+
+
+typedef struct DISPLAY_MODE_INFO_TAG
+{
+
+ PVRSRV_PIXEL_FORMAT pixelformat;
+
+ DISPLAY_DIMS sDims;
+
+ IMG_UINT32 ui32RefreshHZ;
+
+ IMG_UINT32 ui32OEMFlags;
+} DISPLAY_MODE_INFO;
+
+
+
+#define MAX_DISPLAY_NAME_SIZE (50)
+
+typedef struct DISPLAY_INFO_TAG
+{
+
+ IMG_UINT32 ui32MaxSwapChains;
+
+ IMG_UINT32 ui32MaxSwapChainBuffers;
+
+ IMG_UINT32 ui32MinSwapInterval;
+
+ IMG_UINT32 ui32MaxSwapInterval;
+
+ IMG_UINT32 ui32PhysicalWidthmm;
+ IMG_UINT32 ui32PhysicalHeightmm;
+
+ IMG_CHAR szDisplayName[MAX_DISPLAY_NAME_SIZE];
+#if defined(SUPPORT_HW_CURSOR)
+
+ IMG_UINT16 ui32CursorWidth;
+ IMG_UINT16 ui32CursorHeight;
+#endif
+} DISPLAY_INFO;
+
+typedef struct ACCESS_INFO_TAG
+{
+ IMG_UINT32 ui32Size;
+ IMG_UINT32 ui32FBPhysBaseAddress;
+ IMG_UINT32 ui32FBMemAvailable;
+ IMG_UINT32 ui32SysPhysBaseAddress;
+ IMG_UINT32 ui32SysSize;
+ IMG_UINT32 ui32DevIRQ;
+}ACCESS_INFO;
+
+
+typedef struct PVRSRV_CURSOR_SHAPE_TAG
+{
+ IMG_UINT16 ui16Width;
+ IMG_UINT16 ui16Height;
+ IMG_INT16 i16XHot;
+ IMG_INT16 i16YHot;
+
+
+ IMG_VOID* pvMask;
+ IMG_INT16 i16MaskByteStride;
+
+
+ IMG_VOID* pvColour;
+ IMG_INT16 i16ColourByteStride;
+ PVRSRV_PIXEL_FORMAT eColourPixelFormat;
+} PVRSRV_CURSOR_SHAPE;
+
+#define PVRSRV_SET_CURSOR_VISIBILITY (1<<0)
+#define PVRSRV_SET_CURSOR_POSITION (1<<1)
+#define PVRSRV_SET_CURSOR_SHAPE (1<<2)
+#define PVRSRV_SET_CURSOR_ROTATION (1<<3)
+
+typedef struct PVRSRV_CURSOR_INFO_TAG
+{
+
+ IMG_UINT32 ui32Flags;
+
+
+ IMG_BOOL bVisible;
+
+
+ IMG_INT16 i16XPos;
+ IMG_INT16 i16YPos;
+
+
+ PVRSRV_CURSOR_SHAPE sCursorShape;
+
+
+ IMG_UINT32 ui32Rotation;
+
+} PVRSRV_CURSOR_INFO;
+
+#if defined(PDUMP_SUSPEND_IS_PER_THREAD)
+typedef struct {
+ IMG_UINT32 threadId;
+ int suspendCount;
+} PVRSRV_THREAD_SUSPEND_COUNT;
+
+#define PVRSRV_PDUMP_SUSPEND_Q_NAME "PVRSRVPDumpSuspendMsgQ"
+#define PVRSRV_PDUMP_SUSPEND_Q_LENGTH 8
+
+#endif
+
+typedef struct _PVRSRV_REGISTRY_INFO_
+{
+ IMG_UINT32 ui32DevCookie;
+ IMG_PCHAR pszKey;
+ IMG_PCHAR pszValue;
+ IMG_PCHAR pszBuf;
+ IMG_UINT32 ui32BufSize;
+} PVRSRV_REGISTRY_INFO, *PPVRSRV_REGISTRY_INFO;
+
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVReadRegistryString (PPVRSRV_REGISTRY_INFO psRegInfo);
+PVRSRV_ERROR IMG_CALLCONV PVRSRVWriteRegistryString (PPVRSRV_REGISTRY_INFO psRegInfo);
+
+
+#define PVRSRV_BC_FLAGS_YUVCSC_CONFORMANT_RANGE (0 << 0)
+#define PVRSRV_BC_FLAGS_YUVCSC_FULL_RANGE (1 << 0)
+
+#define PVRSRV_BC_FLAGS_YUVCSC_BT601 (0 << 1)
+#define PVRSRV_BC_FLAGS_YUVCSC_BT709 (1 << 1)
+
+#define MAX_BUFFER_DEVICE_NAME_SIZE (50)
+
+typedef struct BUFFER_INFO_TAG
+{
+ IMG_UINT32 ui32BufferCount;
+ IMG_UINT32 ui32BufferDeviceID;
+ PVRSRV_PIXEL_FORMAT pixelformat;
+ IMG_UINT32 ui32ByteStride;
+ IMG_UINT32 ui32Width;
+ IMG_UINT32 ui32Height;
+ IMG_UINT32 ui32Flags;
+ IMG_CHAR szDeviceName[MAX_BUFFER_DEVICE_NAME_SIZE];
+} BUFFER_INFO;
+
+typedef enum _OVERLAY_DEINTERLACE_MODE_
+{
+ WEAVE=0x0,
+ BOB_ODD,
+ BOB_EVEN,
+ BOB_EVEN_NONINTERLEAVED
+} OVERLAY_DEINTERLACE_MODE;
+
+#endif
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#if defined(DEBUG) || defined (INTERNAL_TEST)
+#define DEBUG_SET_OFFSET OPTIONS_BIT0
+#define OPTIONS_BIT0 0x1
+#else
+#define OPTIONS_BIT0 0x0
+#endif
+
+#if defined(PDUMP) || defined (INTERNAL_TEST)
+#define PDUMP_SET_OFFSET OPTIONS_BIT1
+#define OPTIONS_BIT1 (0x1 << 1)
+#else
+#define OPTIONS_BIT1 0x0
+#endif
+
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG) || defined (INTERNAL_TEST)
+#define PVRSRV_USSE_EDM_STATUS_DEBUG_SET_OFFSET OPTIONS_BIT2
+#define OPTIONS_BIT2 (0x1 << 2)
+#else
+#define OPTIONS_BIT2 0x0
+#endif
+
+#if defined(SUPPORT_HW_RECOVERY) || defined (INTERNAL_TEST)
+#define SUPPORT_HW_RECOVERY_SET_OFFSET OPTIONS_BIT3
+#define OPTIONS_BIT3 (0x1 << 3)
+#else
+#define OPTIONS_BIT3 0x0
+#endif
+
+
+
+#if defined(PVR_SECURE_HANDLES) || defined (INTERNAL_TEST)
+#define PVR_SECURE_HANDLES_SET_OFFSET OPTIONS_BIT4
+#define OPTIONS_BIT4 (0x1 << 4)
+#else
+#define OPTIONS_BIT4 0x0
+#endif
+
+#if defined(SGX_BYPASS_SYSTEM_CACHE) || defined (INTERNAL_TEST)
+#define SGX_BYPASS_SYSTEM_CACHE_SET_OFFSET OPTIONS_BIT5
+#define OPTIONS_BIT5 (0x1 << 5)
+#else
+#define OPTIONS_BIT5 0x0
+#endif
+
+#if defined(SGX_DMS_AGE_ENABLE) || defined (INTERNAL_TEST)
+#define SGX_DMS_AGE_ENABLE_SET_OFFSET OPTIONS_BIT6
+#define OPTIONS_BIT6 (0x1 << 6)
+#else
+#define OPTIONS_BIT6 0x0
+#endif
+
+#if defined(SGX_FAST_DPM_INIT) || defined (INTERNAL_TEST)
+#define SGX_FAST_DPM_INIT_SET_OFFSET OPTIONS_BIT8
+#define OPTIONS_BIT8 (0x1 << 8)
+#else
+#define OPTIONS_BIT8 0x0
+#endif
+
+#if defined(SGX_FEATURE_WRITEBACK_DCU) || defined (INTERNAL_TEST)
+#define SGX_FEATURE_DCU_SET_OFFSET OPTIONS_BIT9
+#define OPTIONS_BIT9 (0x1 << 9)
+#else
+#define OPTIONS_BIT9 0x0
+#endif
+
+#if defined(SGX_FEATURE_MP) || defined (INTERNAL_TEST)
+#define SGX_FEATURE_MP_SET_OFFSET OPTIONS_BIT10
+#define OPTIONS_BIT10 (0x1 << 10)
+#else
+#define OPTIONS_BIT10 0x0
+#endif
+
+#if defined(SGX_FEATURE_MULTITHREADED_UKERNEL) || defined (INTERNAL_TEST)
+#define SGX_FEATURE_MULTITHREADED_UKERNEL_SET_OFFSET OPTIONS_BIT11
+#define OPTIONS_BIT11 (0x1 << 11)
+#else
+#define OPTIONS_BIT11 0x0
+#endif
+
+
+
+#if defined(SGX_FEATURE_OVERLAPPED_SPM) || defined (INTERNAL_TEST)
+#define SGX_FEATURE_OVERLAPPED_SPM_SET_OFFSET OPTIONS_BIT12
+#define OPTIONS_BIT12 (0x1 << 12)
+#else
+#define OPTIONS_BIT12 0x0
+#endif
+
+
+#if defined(SGX_FEATURE_SYSTEM_CACHE) || defined (INTERNAL_TEST)
+#define SGX_FEATURE_SYSTEM_CACHE_SET_OFFSET OPTIONS_BIT13
+#define OPTIONS_BIT13 (0x1 << 13)
+#else
+#define OPTIONS_BIT13 0x0
+#endif
+
+#if defined(SGX_SUPPORT_HWPROFILING) || defined (INTERNAL_TEST)
+#define SGX_SUPPORT_HWPROFILING_SET_OFFSET OPTIONS_BIT14
+#define OPTIONS_BIT14 (0x1 << 14)
+#else
+#define OPTIONS_BIT14 0x0
+#endif
+
+
+
+#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT) || defined (INTERNAL_TEST)
+#define SUPPORT_ACTIVE_POWER_MANAGEMENT_SET_OFFSET OPTIONS_BIT15
+#define OPTIONS_BIT15 (0x1 << 15)
+#else
+#define OPTIONS_BIT15 0x0
+#endif
+
+#if defined(SUPPORT_DISPLAYCONTROLLER_TILING) || defined (INTERNAL_TEST)
+#define SUPPORT_DISPLAYCONTROLLER_TILING_SET_OFFSET OPTIONS_BIT16
+#define OPTIONS_BIT16 (0x1 << 16)
+#else
+#define OPTIONS_BIT16 0x0
+#endif
+
+#if defined(SUPPORT_PERCONTEXT_PB) || defined (INTERNAL_TEST)
+#define SUPPORT_PERCONTEXT_PB_SET_OFFSET OPTIONS_BIT17
+#define OPTIONS_BIT17 (0x1 << 17)
+#else
+#define OPTIONS_BIT17 0x0
+#endif
+
+#if defined(SUPPORT_SGX_HWPERF) || defined (INTERNAL_TEST)
+#define SUPPORT_SGX_HWPERF_SET_OFFSET OPTIONS_BIT18
+#define OPTIONS_BIT18 (0x1 << 18)
+#else
+#define OPTIONS_BIT18 0x0
+#endif
+
+
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE) || defined (INTERNAL_TEST)
+#define SUPPORT_SGX_MMU_DUMMY_PAGE_SET_OFFSET OPTIONS_BIT19
+#define OPTIONS_BIT19 (0x1 << 19)
+#else
+#define OPTIONS_BIT19 0x0
+#endif
+
+#if defined(SUPPORT_SGX_PRIORITY_SCHEDULING) || defined (INTERNAL_TEST)
+#define SUPPORT_SGX_PRIORITY_SCHEDULING_SET_OFFSET OPTIONS_BIT20
+#define OPTIONS_BIT20 (0x1 << 20)
+#else
+#define OPTIONS_BIT20 0x0
+#endif
+
+#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) || defined (INTERNAL_TEST)
+#define SUPPORT_SGX_LOW_LATENCY_SCHEDULING_SET_OFFSET OPTIONS_BIT21
+#define OPTIONS_BIT21 (0x1 << 21)
+#else
+#define OPTIONS_BIT21 0x0
+#endif
+
+#if defined(USE_SUPPORT_NO_TA3D_OVERLAP) || defined (INTERNAL_TEST)
+#define USE_SUPPORT_NO_TA3D_OVERLAP_SET_OFFSET OPTIONS_BIT22
+#define OPTIONS_BIT22 (0x1 << 22)
+#else
+#define OPTIONS_BIT22 0x0
+#endif
+
+#define PVR_DISABLE_SECURE_FD_EXPORT_OFFSET 27
+
+#if defined(SGX_FEATURE_MP) || defined (INTERNAL_TEST)
+#define OPTIONS_HIGHBYTE ((SGX_FEATURE_MP_CORE_COUNT-1) << SGX_FEATURE_MP_CORE_COUNT_SET_OFFSET)
+#define SGX_FEATURE_MP_CORE_COUNT_SET_OFFSET 28UL
+#define SGX_FEATURE_MP_CORE_COUNT_SET_MASK 0xFF
+#else
+#define OPTIONS_HIGHBYTE 0x0
+#endif
+
+#define __BIT_MASK(len) ((1ULL << (len)) - 1)
+#define OPTION_BIT_MASK(start, len) \
+ (__BIT_MASK((start) + (len)) & ~__BIT_MASK(start))
+
+/*
+ * The option bits covered by the following mask must match between kernel and
+ * user space. The rest of the bits in the options word are dynamic, that is
+ * libraries built with or without those will be supported by the kernel. In the
+ * future we would like to minimize the set of these options.
+ */
+#define SGX_BUILD_OPTION_MASK (OPTION_BIT_MASK(0, 22) | \
+ OPTION_BIT_MASK(28, 4))
+
+#define SGX_BUILD_OPTIONS (\
+ OPTIONS_BIT0 |\
+ OPTIONS_BIT1 |\
+ OPTIONS_BIT2 |\
+ OPTIONS_BIT3 |\
+ OPTIONS_BIT4 |\
+ OPTIONS_BIT5 |\
+ OPTIONS_BIT6 |\
+ OPTIONS_BIT8 |\
+ OPTIONS_BIT9 |\
+ OPTIONS_BIT10 |\
+ OPTIONS_BIT11 |\
+ OPTIONS_BIT12 |\
+ OPTIONS_BIT13 |\
+ OPTIONS_BIT14 |\
+ OPTIONS_BIT15 |\
+ OPTIONS_BIT16 |\
+ OPTIONS_BIT17 |\
+ OPTIONS_BIT18 |\
+ OPTIONS_BIT19 |\
+ OPTIONS_BIT20 |\
+ OPTIONS_BIT21 |\
+ OPTIONS_BIT22 |\
+ OPTIONS_HIGHBYTE )
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef __SGXAPI_KM_H__
+#define __SGXAPI_KM_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "sgxdefs.h"
+
+#if defined(__linux__) && !defined(USE_CODE)
+ #if defined(__KERNEL__)
+ #include <asm/unistd.h>
+ #else
+ #include <unistd.h>
+ #endif
+#endif
+
+#define SGX_UNDEFINED_HEAP_ID (~0LU)
+#define SGX_GENERAL_HEAP_ID 0
+#define SGX_TADATA_HEAP_ID 1
+#define SGX_KERNEL_CODE_HEAP_ID 2
+#define SGX_KERNEL_DATA_HEAP_ID 3
+#define SGX_PIXELSHADER_HEAP_ID 4
+#define SGX_VERTEXSHADER_HEAP_ID 5
+#define SGX_PDSPIXEL_CODEDATA_HEAP_ID 6
+#define SGX_PDSVERTEX_CODEDATA_HEAP_ID 7
+#define SGX_SYNCINFO_HEAP_ID 8
+#define SGX_3DPARAMETERS_HEAP_ID 9
+#if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+#define SGX_GENERAL_MAPPING_HEAP_ID 10
+#endif
+#if defined(SGX_FEATURE_2D_HARDWARE)
+#define SGX_2D_HEAP_ID 11
+#else
+#if defined(FIX_HW_BRN_26915)
+#define SGX_CGBUFFER_HEAP_ID 12
+#endif
+#endif
+#define SGX_MAX_HEAP_ID 13
+
+#if defined(SGX543) || defined(SGX544) || defined(SGX554)
+#define SGX_USE_CODE_SEGMENT_RANGE_BITS 23
+#else
+#define SGX_USE_CODE_SEGMENT_RANGE_BITS 19
+#endif
+
+#define SGX_MAX_TA_STATUS_VALS 32
+#define SGX_MAX_3D_STATUS_VALS 4
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+#define SGX_MAX_TA_DST_SYNCS 1
+#define SGX_MAX_TA_SRC_SYNCS 1
+#define SGX_MAX_3D_SRC_SYNCS 4
+#else
+#define SGX_MAX_SRC_SYNCS 8
+#define SGX_MAX_DST_SYNCS 1
+#endif
+
+
+#if defined(SGX_FEATURE_EXTENDED_PERF_COUNTERS)
+#define PVRSRV_SGX_HWPERF_NUM_COUNTERS 8
+#else
+#define PVRSRV_SGX_HWPERF_NUM_COUNTERS 9
+#endif
+
+#define PVRSRV_SGX_HWPERF_INVALID 0x1
+
+#define PVRSRV_SGX_HWPERF_TRANSFER 0x2
+#define PVRSRV_SGX_HWPERF_TA 0x3
+#define PVRSRV_SGX_HWPERF_3D 0x4
+#define PVRSRV_SGX_HWPERF_2D 0x5
+#define PVRSRV_SGX_HWPERF_POWER 0x6
+#define PVRSRV_SGX_HWPERF_PERIODIC 0x7
+
+#define PVRSRV_SGX_HWPERF_MK_EVENT 0x101
+#define PVRSRV_SGX_HWPERF_MK_TA 0x102
+#define PVRSRV_SGX_HWPERF_MK_3D 0x103
+#define PVRSRV_SGX_HWPERF_MK_2D 0x104
+
+#define PVRSRV_SGX_HWPERF_TYPE_STARTEND_BIT 28
+#define PVRSRV_SGX_HWPERF_TYPE_OP_MASK ((1UL << PVRSRV_SGX_HWPERF_TYPE_STARTEND_BIT) - 1)
+#define PVRSRV_SGX_HWPERF_TYPE_OP_START (0UL << PVRSRV_SGX_HWPERF_TYPE_STARTEND_BIT)
+#define PVRSRV_SGX_HWPERF_TYPE_OP_END (1Ul << PVRSRV_SGX_HWPERF_TYPE_STARTEND_BIT)
+
+#define PVRSRV_SGX_HWPERF_TYPE_TRANSFER_START (PVRSRV_SGX_HWPERF_TRANSFER | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_TRANSFER_END (PVRSRV_SGX_HWPERF_TRANSFER | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_TA_START (PVRSRV_SGX_HWPERF_TA | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_TA_END (PVRSRV_SGX_HWPERF_TA | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_3D_START (PVRSRV_SGX_HWPERF_3D | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_3D_END (PVRSRV_SGX_HWPERF_3D | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_2D_START (PVRSRV_SGX_HWPERF_2D | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_2D_END (PVRSRV_SGX_HWPERF_2D | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_POWER_START (PVRSRV_SGX_HWPERF_POWER | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_POWER_END (PVRSRV_SGX_HWPERF_POWER | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_PERIODIC (PVRSRV_SGX_HWPERF_PERIODIC)
+
+#define PVRSRV_SGX_HWPERF_TYPE_MK_EVENT_START (PVRSRV_SGX_HWPERF_MK_EVENT | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_EVENT_END (PVRSRV_SGX_HWPERF_MK_EVENT | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_TA_START (PVRSRV_SGX_HWPERF_MK_TA | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_TA_END (PVRSRV_SGX_HWPERF_MK_TA | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_3D_START (PVRSRV_SGX_HWPERF_MK_3D | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_3D_END (PVRSRV_SGX_HWPERF_MK_3D | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_2D_START (PVRSRV_SGX_HWPERF_MK_2D | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_2D_END (PVRSRV_SGX_HWPERF_MK_2D | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+
+#define PVRSRV_SGX_HWPERF_STATUS_OFF (0x0)
+#define PVRSRV_SGX_HWPERF_STATUS_RESET_COUNTERS (1UL << 0)
+#define PVRSRV_SGX_HWPERF_STATUS_GRAPHICS_ON (1UL << 1)
+#define PVRSRV_SGX_HWPERF_STATUS_PERIODIC_ON (1UL << 2)
+#define PVRSRV_SGX_HWPERF_STATUS_MK_EXECUTION_ON (1UL << 3)
+
+#define PVR_FW_VER_MAJOR(x) (((x) >> 16) & 0xff)
+#define PVR_FW_VER_MINOR(x) (((x) >> 8) & 0xff)
+#define PVR_FW_VER_BRANCH(x) ((x) & 0xff)
+
+typedef struct _PVRSRV_SGX_HWPERF_CB_ENTRY_
+{
+ IMG_UINT32 ui32FrameNo;
+ IMG_UINT32 ui32Type;
+ IMG_UINT32 ui32Ordinal;
+ IMG_UINT32 ui32Info;
+ IMG_UINT32 ui32Clocksx16;
+ IMG_UINT32 ui32Counters[SGX_FEATURE_MP_CORE_COUNT][PVRSRV_SGX_HWPERF_NUM_COUNTERS];
+} PVRSRV_SGX_HWPERF_CB_ENTRY;
+
+
+typedef struct _CTL_STATUS_
+{
+ IMG_DEV_VIRTADDR sStatusDevAddr;
+ IMG_UINT32 ui32StatusValue;
+} CTL_STATUS;
+
+
+typedef enum _SGX_MISC_INFO_REQUEST_
+{
+ SGX_MISC_INFO_REQUEST_CLOCKSPEED = 0,
+ SGX_MISC_INFO_REQUEST_SGXREV,
+ SGX_MISC_INFO_REQUEST_DRIVER_SGXREV,
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+ SGX_MISC_INFO_REQUEST_MEMREAD,
+ SGX_MISC_INFO_REQUEST_MEMCOPY,
+#endif
+ SGX_MISC_INFO_REQUEST_SET_HWPERF_STATUS,
+#if defined(SGX_FEATURE_DATA_BREAKPOINTS)
+ SGX_MISC_INFO_REQUEST_SET_BREAKPOINT,
+ SGX_MISC_INFO_REQUEST_WAIT_FOR_BREAKPOINT,
+ SGX_MISC_INFO_REQUEST_POLL_BREAKPOINT,
+ SGX_MISC_INFO_REQUEST_RESUME_BREAKPOINT,
+#endif
+ SGX_MISC_INFO_DUMP_DEBUG_INFO,
+ SGX_MISC_INFO_PANIC,
+ SGX_MISC_INFO_REQUEST_SPM,
+ SGX_MISC_INFO_REQUEST_ACTIVEPOWER,
+ SGX_MISC_INFO_REQUEST_LOCKUPS,
+#if defined(PVRSRV_RESOURCE_PROFILING)
+ SGX_MISC_INFO_RESOURCEPROF_SIMPLE,
+ SGX_MISC_INFO_RESOURCEPROF_GLOBAL,
+ SGX_MISC_INFO_RESOURCEPROF_MEM_INFO,
+#endif
+ SGX_MISC_INFO_REQUEST_FORCE_I16 = 0x7fff
+} SGX_MISC_INFO_REQUEST;
+
+
+typedef struct _PVRSRV_SGX_MISCINFO_FEATURES
+{
+ IMG_UINT32 ui32CoreRev;
+ IMG_UINT32 ui32CoreID;
+ IMG_UINT32 ui32DDKVersion;
+ IMG_UINT32 ui32DDKBuild;
+ IMG_UINT32 ui32CoreIdSW;
+ IMG_UINT32 ui32CoreRevSW;
+ IMG_UINT32 ui32BuildOptions;
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+ IMG_UINT32 ui32DeviceMemValue;
+#endif
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+ IMG_DEV_VIRTADDR sDevVAEDMStatusBuffer;
+ IMG_PVOID pvEDMStatusBuffer;
+#endif
+} PVRSRV_SGX_MISCINFO_FEATURES;
+
+
+typedef struct _PVRSRV_SGX_MISCINFO_LOCKUPS
+{
+ IMG_UINT32 ui32HostDetectedLockups;
+ IMG_UINT32 ui32uKernelDetectedLockups;
+} PVRSRV_SGX_MISCINFO_LOCKUPS;
+
+
+typedef struct _PVRSRV_SGX_MISCINFO_ACTIVEPOWER
+{
+ IMG_UINT32 ui32NumActivePowerEvents;
+} PVRSRV_SGX_MISCINFO_ACTIVEPOWER;
+
+
+typedef struct _PVRSRV_SGX_MISCINFO_SPM
+{
+ IMG_HANDLE hRTDataSet;
+ IMG_UINT32 ui32NumOutOfMemSignals;
+ IMG_UINT32 ui32NumSPMRenders;
+} PVRSRV_SGX_MISCINFO_SPM;
+
+
+#if defined(SGX_FEATURE_DATA_BREAKPOINTS)
+typedef struct _SGX_BREAKPOINT_INFO
+{
+
+ IMG_BOOL bBPEnable;
+
+ IMG_UINT32 ui32BPIndex;
+
+ IMG_UINT32 ui32DataMasterMask;
+
+ IMG_DEV_VIRTADDR sBPDevVAddr, sBPDevVAddrEnd;
+
+ IMG_BOOL bTrapped;
+
+ IMG_BOOL bRead;
+
+ IMG_BOOL bWrite;
+
+ IMG_BOOL bTrappedBP;
+
+ IMG_UINT32 ui32CoreNum;
+ IMG_DEV_VIRTADDR sTrappedBPDevVAddr;
+ IMG_UINT32 ui32TrappedBPBurstLength;
+ IMG_BOOL bTrappedBPRead;
+ IMG_UINT32 ui32TrappedBPDataMaster;
+ IMG_UINT32 ui32TrappedBPTag;
+} SGX_BREAKPOINT_INFO;
+#endif
+
+
+typedef struct _PVRSRV_SGX_MISCINFO_SET_HWPERF_STATUS
+{
+
+ IMG_UINT32 ui32NewHWPerfStatus;
+
+ #if defined(SGX_FEATURE_EXTENDED_PERF_COUNTERS)
+
+ IMG_UINT32 aui32PerfGroup[PVRSRV_SGX_HWPERF_NUM_COUNTERS];
+
+ IMG_UINT32 aui32PerfBit[PVRSRV_SGX_HWPERF_NUM_COUNTERS];
+ #else
+
+ IMG_UINT32 ui32PerfGroup;
+ #endif
+} PVRSRV_SGX_MISCINFO_SET_HWPERF_STATUS;
+
+#if defined(PVRSRV_RESOURCE_PROFILING)
+#define MAX_PROC 80
+typedef struct _PVRSRV_SGX_RESOURCE_INFO
+{
+ IMG_UINT32 ui32TotalMem;
+ IMG_UINT32 ui32UsedMem;
+ IMG_UINT32 aui32ProcMem[MAX_PROC][3];
+ IMG_UINT32 ui32ProcCnt;
+} PVRSRV_SGX_RESOURCE_INFO;
+#endif
+
+
+typedef struct _SGX_MISC_INFO_
+{
+ SGX_MISC_INFO_REQUEST eRequest;
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+ IMG_DEV_VIRTADDR sDevVAddrSrc;
+ IMG_DEV_VIRTADDR sDevVAddrDest;
+ IMG_HANDLE hDevMemContext;
+#endif
+ union
+ {
+ IMG_UINT32 reserved;
+ PVRSRV_SGX_MISCINFO_FEATURES sSGXFeatures;
+ IMG_UINT32 ui32SGXClockSpeed;
+ PVRSRV_SGX_MISCINFO_ACTIVEPOWER sActivePower;
+ PVRSRV_SGX_MISCINFO_LOCKUPS sLockups;
+ PVRSRV_SGX_MISCINFO_SPM sSPM;
+#if defined(SGX_FEATURE_DATA_BREAKPOINTS)
+ SGX_BREAKPOINT_INFO sSGXBreakpointInfo;
+#endif
+ PVRSRV_SGX_MISCINFO_SET_HWPERF_STATUS sSetHWPerfStatus;
+#if defined(PVRSRV_RESOURCE_PROFILING)
+ PVRSRV_SGX_RESOURCE_INFO sSGXResourceInfo;
+ PVRSRV_CLIENT_MEM_INFO sSGXResProfMemInfo;
+#endif
+ } uData;
+} SGX_MISC_INFO;
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+#define PVRSRV_MAX_BLT_SRC_SYNCS 3
+#endif
+
+
+#define SGX_KICKTA_DUMPBITMAP_MAX_NAME_LENGTH 256
+
+typedef struct _SGX_KICKTA_DUMPBITMAP_
+{
+ IMG_DEV_VIRTADDR sDevBaseAddr;
+ IMG_UINT32 ui32Flags;
+ IMG_UINT32 ui32Width;
+ IMG_UINT32 ui32Height;
+ IMG_UINT32 ui32Stride;
+ IMG_UINT32 ui32PDUMPFormat;
+ IMG_UINT32 ui32BytesPP;
+ IMG_CHAR pszName[SGX_KICKTA_DUMPBITMAP_MAX_NAME_LENGTH];
+} SGX_KICKTA_DUMPBITMAP, *PSGX_KICKTA_DUMPBITMAP;
+
+#define PVRSRV_SGX_PDUMP_CONTEXT_MAX_BITMAP_ARRAY_SIZE (16)
+
+typedef struct _PVRSRV_SGX_PDUMP_CONTEXT_
+{
+
+ IMG_UINT32 ui32CacheControl;
+
+} PVRSRV_SGX_PDUMP_CONTEXT;
+
+
+typedef struct _SGX_KICKTA_DUMP_ROFF_
+{
+ IMG_HANDLE hKernelMemInfo;
+ IMG_UINT32 uiAllocIndex;
+ IMG_UINT32 ui32Offset;
+ IMG_UINT32 ui32Value;
+ IMG_PCHAR pszName;
+} SGX_KICKTA_DUMP_ROFF, *PSGX_KICKTA_DUMP_ROFF;
+
+typedef struct _SGX_KICKTA_DUMP_BUFFER_
+{
+ IMG_UINT32 ui32SpaceUsed;
+ IMG_UINT32 ui32Start;
+ IMG_UINT32 ui32End;
+ IMG_UINT32 ui32BufferSize;
+ IMG_UINT32 ui32BackEndLength;
+ IMG_UINT32 uiAllocIndex;
+ IMG_HANDLE hKernelMemInfo;
+ IMG_PVOID pvLinAddr;
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+ IMG_HANDLE hCtrlKernelMemInfo;
+ IMG_DEV_VIRTADDR sCtrlDevVAddr;
+#endif
+ IMG_PCHAR pszName;
+} SGX_KICKTA_DUMP_BUFFER, *PSGX_KICKTA_DUMP_BUFFER;
+
+#ifdef PDUMP
+typedef struct _SGX_KICKTA_PDUMP_
+{
+
+ PSGX_KICKTA_DUMPBITMAP psPDumpBitmapArray;
+ IMG_UINT32 ui32PDumpBitmapSize;
+
+
+ PSGX_KICKTA_DUMP_BUFFER psBufferArray;
+ IMG_UINT32 ui32BufferArraySize;
+
+
+ PSGX_KICKTA_DUMP_ROFF psROffArray;
+ IMG_UINT32 ui32ROffArraySize;
+} SGX_KICKTA_PDUMP, *PSGX_KICKTA_PDUMP;
+#endif
+
+#if defined(TRANSFER_QUEUE)
+#if defined(SGX_FEATURE_2D_HARDWARE)
+#define SGX_MAX_2D_BLIT_CMD_SIZE 26
+#define SGX_MAX_2D_SRC_SYNC_OPS 3
+#endif
+#define SGX_MAX_TRANSFER_STATUS_VALS 2
+#define SGX_MAX_TRANSFER_SYNC_OPS 5
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef __SGXSCRIPT_H__
+#define __SGXSCRIPT_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define SGX_MAX_INIT_COMMANDS 64
+#define SGX_MAX_DEINIT_COMMANDS 16
+
+typedef enum _SGX_INIT_OPERATION
+{
+ SGX_INIT_OP_ILLEGAL = 0,
+ SGX_INIT_OP_WRITE_HW_REG,
+#if defined(PDUMP)
+ SGX_INIT_OP_PDUMP_HW_REG,
+#endif
+ SGX_INIT_OP_HALT
+} SGX_INIT_OPERATION;
+
+typedef union _SGX_INIT_COMMAND
+{
+ SGX_INIT_OPERATION eOp;
+ struct {
+ SGX_INIT_OPERATION eOp;
+ IMG_UINT32 ui32Offset;
+ IMG_UINT32 ui32Value;
+ } sWriteHWReg;
+#if defined(PDUMP)
+ struct {
+ SGX_INIT_OPERATION eOp;
+ IMG_UINT32 ui32Offset;
+ IMG_UINT32 ui32Value;
+ } sPDumpHWReg;
+#endif
+#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
+ struct {
+ SGX_INIT_OPERATION eOp;
+ } sWorkaroundBRN22997;
+#endif
+} SGX_INIT_COMMAND;
+
+typedef struct _SGX_INIT_SCRIPTS_
+{
+ SGX_INIT_COMMAND asInitCommandsPart1[SGX_MAX_INIT_COMMANDS];
+ SGX_INIT_COMMAND asInitCommandsPart2[SGX_MAX_INIT_COMMANDS];
+ SGX_INIT_COMMAND asDeinitCommands[SGX_MAX_DEINIT_COMMANDS];
+} SGX_INIT_SCRIPTS;
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
+
--- /dev/null
+/*
+ * Copyright (C) 2011 Nokia Corporation
+ * Copyright (C) 2011 Intel Corporation
+ * Author: Luc Verhaegen <libv@codethink.co.uk>
+ * Author: Imre Deak <imre.deak@intel.com>
+ *
+ * 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/debugfs.h>
+#include <linux/vmalloc.h>
+#include <linux/mutex.h>
+
+#include "img_types.h"
+#include "servicesext.h"
+#include "services.h"
+#include "sgxinfokm.h"
+#include "syscommon.h"
+#include "pvr_bridge_km.h"
+#include "sgxutils.h"
+#include "pvr_debugfs.h"
+#include "mmu.h"
+#include "bridged_support.h"
+#include "mm.h"
+#include "pvr_trace_cmd.h"
+
+static struct dentry *pvr_debugfs_dir;
+
+#ifdef CONFIG_PVR_TRACE_CMD
+
+static void *trcmd_str_buf;
+static u8 *trcmd_snapshot;
+static size_t trcmd_snapshot_size;
+static unsigned long trcmd_busy;
+
+static int pvr_dbg_trcmd_open(struct inode *inode, struct file *file)
+{
+ int r;
+
+ if (test_and_set_bit(0, &trcmd_busy))
+ return -EBUSY;
+
+ trcmd_str_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!trcmd_str_buf) {
+ clear_bit(0, &trcmd_busy);
+
+ return -ENOMEM;
+ }
+
+ r = pvr_trcmd_create_snapshot(&trcmd_snapshot, &trcmd_snapshot_size);
+ if (r < 0) {
+ kfree(trcmd_str_buf);
+ clear_bit(0, &trcmd_busy);
+
+ return r;
+ }
+
+ return 0;
+}
+
+static int pvr_dbg_trcmd_release(struct inode *inode, struct file *file)
+{
+ pvr_trcmd_destroy_snapshot(trcmd_snapshot);
+ kfree(trcmd_str_buf);
+ clear_bit(0, &trcmd_busy);
+
+ return 0;
+}
+
+static ssize_t pvr_dbg_trcmd_read(struct file *file, char __user *buffer,
+ size_t count, loff_t *ppos)
+{
+ ssize_t ret;
+
+ ret = pvr_trcmd_print(trcmd_str_buf, max_t(size_t, PAGE_SIZE, count),
+ trcmd_snapshot, trcmd_snapshot_size, ppos);
+ if (copy_to_user(buffer, trcmd_str_buf, ret))
+ return -EFAULT;
+
+ return ret;
+}
+
+static const struct file_operations pvr_dbg_trcmd_fops = {
+ .owner = THIS_MODULE,
+ .open = pvr_dbg_trcmd_open,
+ .release = pvr_dbg_trcmd_release,
+ .read = pvr_dbg_trcmd_read,
+};
+#endif
+
+int pvr_debugfs_init(void)
+{
+ pvr_debugfs_dir = debugfs_create_dir("pvr", NULL);
+ if (!pvr_debugfs_dir)
+ goto err;
+
+#ifdef CONFIG_PVR_TRACE_CMD
+ if (!debugfs_create_file("command_trace", S_IRUGO, pvr_debugfs_dir,
+ NULL, &pvr_dbg_trcmd_fops))
+ goto err;
+#endif
+ return 0;
+err:
+ debugfs_remove_recursive(pvr_debugfs_dir);
+ pr_err("pvr: debugfs init failed\n");
+
+ return -ENODEV;
+}
+
+void pvr_debugfs_cleanup(void)
+{
+ debugfs_remove_recursive(pvr_debugfs_dir);
+}
+
--- /dev/null
+#ifndef _PVR_DEBUGFS_H_
+#define _PVR_DEBUGFS_H_ 1
+
+#ifdef CONFIG_DEBUG_FS
+int pvr_debugfs_init(void);
+void pvr_debugfs_cleanup(void);
+#else
+static inline int pvr_debugfs_init(void)
+{
+ return 0;
+}
+static inline void pvr_debugfs_cleanup(void)
+{
+}
+#endif
+
+#endif /* _PVR_DEBUGFS_H_ */
--- /dev/null
+/*
+ * Copyright (C) 2011 Nokia Corporation
+ * Copyright (C) 2011 Intel Corporation
+ * Author: Imre Deak <imre.deak@intel.com>
+ *
+ * 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/vmalloc.h>
+
+#include "img_types.h"
+#include "resman.h"
+#include "handle.h"
+#include "pvr_trace_cmd.h"
+#include "perproc.h"
+#include "pvr_bridge_km.h"
+
+/* Need to be log2 size. */
+#define PVR_TBUF_SIZE (1 << (CONFIG_PVR_TRACE_CMD_BUF_SHIFT + PAGE_SHIFT))
+
+#define PVR_TRCMD_INDENT 3
+
+static struct pvr_trcmd_buf {
+ int read_idx;
+ int write_idx;
+ int pending_idx; /*
+ * the pending_idx ... write_idx area
+ * is already allocated but still being
+ * written to
+ */
+ int write_pending; /*
+ * number of writers in the above
+ * pending area
+ */
+ char data[PVR_TBUF_SIZE];
+} tbuf;
+
+static LIST_HEAD(syn_track_list);
+
+static char tbuf_overflow[1024];
+
+static DEFINE_SPINLOCK(tbuf_lock); /* protects tbuf and syn_track_list */
+
+struct tbuf_frame {
+ unsigned short size;
+ unsigned short type;
+ unsigned long pid;
+ unsigned long long time;
+ char pname[16];
+};
+
+struct trcmd_desc {
+ const char *name;
+ size_t (*print)(char *dst, size_t dst_size, const void *tbuf);
+};
+
+static size_t prn_syn(const char *name, char *dst, size_t dst_size,
+ const struct pvr_trcmd_syn *ts)
+{
+ size_t len;
+
+ if (!ts->addr)
+ return 0;
+
+ len = scnprintf(dst, dst_size, "%*s%s", PVR_TRCMD_INDENT, "", name);
+ len += scnprintf(&dst[len], dst_size - len, " addr:%08lx", ts->addr);
+ len += scnprintf(&dst[len], dst_size - len,
+ " rop/c:%8lu/%8lu wop/c:%8lu/%8lu\n",
+ ts->rd_pend, ts->rd_comp, ts->wr_pend, ts->wr_comp);
+
+ return len;
+}
+
+static size_t trcmd_prn_syn(char *dst, size_t dst_size, const void *tbuf)
+{
+ const struct pvr_trcmd_syn *ts = tbuf;
+
+ return prn_syn("syn ", dst, dst_size, ts);
+}
+
+static size_t trcmd_prn_sgxkick(char *dst, size_t dst_size, const void *tbuf)
+{
+ const struct pvr_trcmd_sgxkick *d = tbuf;
+ size_t len;
+ int i;
+
+ len = prn_syn("tatq_syn", dst, dst_size, &d->tatq_syn);
+ len += prn_syn("3dtq_syn", &dst[len], dst_size - len, &d->_3dtq_syn);
+ for (i = 0; i < SGX_MAX_SRC_SYNCS; i++) {
+ char sname[10];
+
+ snprintf(sname, sizeof(sname), "src_syn%d", i);
+ len += prn_syn(sname, &dst[len], dst_size - len,
+ &d->src_syn[i]);
+ }
+ len += prn_syn("dst_syn ", &dst[len], dst_size - len, &d->dst_syn);
+ len += prn_syn("ta3d_syn", &dst[len], dst_size - len, &d->ta3d_syn);
+ len += scnprintf(&dst[len], dst_size - len, "%*sctx %08lx\n",
+ PVR_TRCMD_INDENT, "", d->ctx);
+
+ return len;
+}
+
+static size_t trcmd_prn_sgxtfer(char *dst, size_t dst_size, const void *tbuf)
+{
+ const struct pvr_trcmd_sgxtransfer *d = tbuf;
+ size_t len;
+ int i;
+
+ len = prn_syn("ta_syn ", dst, dst_size, &d->ta_syn);
+ len += prn_syn("3d_syn ", &dst[len], dst_size - len, &d->_3d_syn);
+ for (i = 0; i < ARRAY_SIZE(d->src_syn); i++) {
+ char sname[10];
+
+ snprintf(sname, sizeof(sname), "src_syn%d", i);
+ len += prn_syn(sname, &dst[len], dst_size - len,
+ &d->src_syn[i]);
+ }
+ for (i = 0; i < ARRAY_SIZE(d->dst_syn); i++) {
+ char sname[10];
+
+ snprintf(sname, sizeof(sname), "dst_syn%d", i);
+ len += prn_syn(sname, &dst[len], dst_size - len,
+ &d->dst_syn[i]);
+ }
+ len += scnprintf(&dst[len], dst_size - len, "%*sctx %08lx\n",
+ PVR_TRCMD_INDENT, "", d->ctx);
+
+ return len;
+}
+
+static size_t trcmd_prn_flpreq(char *dst, size_t dst_size, const void *tbuf)
+{
+ const struct pvr_trcmd_flpreq *d = tbuf;
+ size_t len = 0;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(d->src_syn); i++) {
+ char sname[10];
+
+ snprintf(sname, sizeof(sname), "src_syn%d", i);
+ len += prn_syn(sname, &dst[len], dst_size - len,
+ &d->src_syn[i]);
+ }
+
+ return len;
+}
+
+static struct trcmd_desc trcmd_desc_table[] = {
+ [PVR_TRCMD_SGX_FIRSTKICK] = { "sgx_first_kick", trcmd_prn_sgxkick },
+ [PVR_TRCMD_SGX_KICK] = { "sgx_kick", trcmd_prn_sgxkick },
+ [PVR_TRCMD_SGX_TFER_KICK] = { "sgx_tfer_kick", trcmd_prn_sgxtfer },
+ [PVR_TRCMD_SGX_QBLT_SYNCHK] = { "sgx_qblt_synchk", trcmd_prn_syn },
+ [PVR_TRCMD_SGX_COMP] = { "sgx_comp", trcmd_prn_syn },
+ [PVR_TRCMD_FLPREQ] = { "sgx_flip_req", trcmd_prn_flpreq },
+ [PVR_TRCMD_FLPCOMP] = { "sgx_flip_comp", trcmd_prn_syn },
+ [PVR_TRCMD_SYN_REMOVE] = { "sgx_syn_remove", trcmd_prn_syn },
+};
+
+/* Modular add */
+static inline int tbuf_idx_add(int val, int delta)
+{
+ val += delta;
+ val &= PVR_TBUF_SIZE - 1;
+
+ return val;
+}
+
+static size_t prn_frame(const struct tbuf_frame *f, char *dst, size_t dst_size)
+{
+ const struct trcmd_desc *desc;
+ unsigned long long sec;
+ unsigned long usec_frac;
+ size_t len;
+
+ desc = &trcmd_desc_table[f->type];
+
+ sec = f->time;
+ usec_frac = do_div(sec, 1000000000) / 1000;
+
+ len = scnprintf(dst, dst_size, "[%5llu.%06lu] %s[%ld]: %s\n",
+ sec, usec_frac, f->pname, f->pid, desc->name);
+ if (desc->print)
+ len += desc->print(&dst[len], dst_size - len, (void *)(f + 1));
+
+ return len;
+}
+
+int pvr_trcmd_create_snapshot(uint8_t **snapshot_ret, size_t *snapshot_size)
+{
+ uint8_t *snapshot = NULL;
+ int read_idx;
+ size_t size = -1;
+ size_t tail_size;
+ unsigned long flags;
+
+ spin_lock_irqsave(&tbuf_lock, flags);
+
+ while (1) {
+ int check_size;
+
+ read_idx = tbuf.read_idx;
+ check_size = tbuf_idx_add(tbuf.pending_idx, -read_idx);
+ if (snapshot || !size) {
+ if (size == check_size)
+ break;
+ /* alloc size changed, try again */
+ }
+ size = check_size;
+
+ spin_unlock_irqrestore(&tbuf_lock, flags);
+
+ /*
+ * vmalloc might reschedule, so release the lock and recheck
+ * later if the required allocation size changed. If so, try
+ * again.
+ */
+ if (snapshot)
+ vfree(snapshot);
+ if (size) {
+ snapshot = vmalloc(size);
+
+ if (!snapshot)
+ return -ENOMEM;
+ }
+
+ spin_lock_irqsave(&tbuf_lock, flags);
+ }
+
+ tail_size = min_t(size_t, size, PVR_TBUF_SIZE - read_idx);
+ memcpy(snapshot, &tbuf.data[read_idx], tail_size);
+ memcpy(&snapshot[tail_size], tbuf.data, size - tail_size);
+
+ spin_unlock_irqrestore(&tbuf_lock, flags);
+
+ *snapshot_ret = snapshot;
+ *snapshot_size = size;
+
+ return 0;
+}
+
+void pvr_trcmd_destroy_snapshot(void *snapshot)
+{
+ vfree(snapshot);
+}
+
+size_t pvr_trcmd_print(char *dst, size_t dst_size, const u8 *snapshot,
+ size_t snapshot_size, loff_t *snapshot_ofs)
+{
+ size_t dst_len;
+
+ if (*snapshot_ofs >= snapshot_size)
+ return 0;
+ dst_len = 0;
+
+ snapshot_size -= *snapshot_ofs;
+
+ while (snapshot_size) {
+ const struct tbuf_frame *f;
+ size_t this_len;
+
+ if (WARN_ON_ONCE(snapshot_size < 4))
+ break;
+
+ f = (struct tbuf_frame *)&snapshot[*snapshot_ofs];
+ if (WARN_ON_ONCE(!f->size || f->size > snapshot_size ||
+ f->type >= ARRAY_SIZE(trcmd_desc_table)))
+ break;
+
+ if (f->type != PVR_TRCMD_PAD)
+ this_len = prn_frame(f, &dst[dst_len],
+ dst_size - dst_len);
+ else
+ this_len = 0;
+
+ if (dst_len + this_len + 1 == dst_size) {
+ /* drop the last printed frame */
+ dst[dst_len] = '\0';
+
+ break;
+ }
+
+ *snapshot_ofs += f->size;
+ dst_len += this_len;
+ snapshot_size -= f->size;
+ }
+
+ return dst_len;
+}
+
+static void *tbuf_get_space(size_t size)
+{
+ void *ret;
+ int buf_idx;
+
+ while (1) {
+ if (tbuf_idx_add(tbuf.pending_idx - 1, -tbuf.write_idx) <
+ size) {
+ /*
+ * Can't allocate into the incomplete area, since it
+ * might be still being written to. New data will be
+ * lost.
+ */
+ WARN_ONCE(1, "pvr: command trace buffer overflow\n");
+
+ return NULL;
+ }
+
+ if (tbuf_idx_add(tbuf.read_idx - 1, -tbuf.write_idx) < size) {
+ /*
+ * Trace buffer overflow, discard the frame that will
+ * be overwritten by the next write. Old data will be
+ * lost.
+ */
+ struct tbuf_frame *f;
+
+ f = (struct tbuf_frame *)&tbuf.data[tbuf.read_idx];
+ buf_idx = tbuf.read_idx;
+ tbuf.read_idx = tbuf_idx_add(tbuf.read_idx, f->size);
+ } else if (PVR_TBUF_SIZE - tbuf.write_idx < size) {
+ struct tbuf_frame *f =
+ (void *)&tbuf.data[tbuf.write_idx];
+ /*
+ * Not enough space until the end of trace buffer,
+ * rewind to the beginning. Frames are sizeof(long)
+ * aligned, thus we are guaranteed to have space for
+ * the following two fields.
+ */
+ f->size = PVR_TBUF_SIZE - tbuf.write_idx;
+ f->type = PVR_TRCMD_PAD;
+ if (tbuf.pending_idx == tbuf.write_idx)
+ tbuf.pending_idx = 0;
+ tbuf.write_idx = 0;
+ } else {
+ break;
+ }
+ }
+ ret = &tbuf.data[tbuf.write_idx];
+ tbuf.write_idx = tbuf_idx_add(tbuf.write_idx, size);
+
+ return ret;
+}
+
+static void *frame_reserve(unsigned type, int pid, const char *pname,
+ size_t size)
+{
+ struct tbuf_frame *f;
+ size_t total_size;
+
+ size = ALIGN(size, __alignof__(*f));
+ total_size = sizeof(*f) + size;
+ f = tbuf_get_space(total_size);
+ if (!f) {
+ /*
+ * Return something the caller can write into, so the caller
+ * doesn't need to check for NULL.
+ */
+ WARN_ON_ONCE(total_size > sizeof(tbuf_overflow));
+
+ return tbuf_overflow;
+ }
+ tbuf.write_pending++;
+
+ f->size = total_size;
+ f->type = type;
+ f->pid = pid;
+ f->time = cpu_clock(smp_processor_id());
+ strlcpy(f->pname, pname, sizeof(f->pname));
+
+ return f + 1;
+}
+
+static void frame_commit(void *alloc_ptr)
+{
+ struct tbuf_frame *f;
+
+ if (alloc_ptr == tbuf_overflow)
+ return;
+
+ if (WARN_ON_ONCE(tbuf.write_pending <= 0))
+ return;
+
+ f = (struct tbuf_frame *)alloc_ptr - 1;
+
+ tbuf.write_pending--;
+ WARN_ON_ONCE(f->size > tbuf_idx_add(tbuf.write_idx, -tbuf.pending_idx));
+ if (!tbuf.write_pending) {
+ tbuf.pending_idx = tbuf.write_idx;
+ } else {
+ int f_idx = (char *)f - tbuf.data;
+
+ if (f_idx == tbuf.pending_idx)
+ tbuf.pending_idx = tbuf_idx_add(tbuf.pending_idx,
+ f->size);
+ }
+}
+
+void *pvr_trcmd_reserve(unsigned type, int pid, const char *pname, size_t size)
+{
+ struct tbuf_frame *f;
+ unsigned long flags;
+
+ spin_lock_irqsave(&tbuf_lock, flags);
+ f = frame_reserve(type, pid, pname, size);
+ spin_unlock_irqrestore(&tbuf_lock, flags);
+
+ return f;
+}
+
+void pvr_trcmd_commit(void *alloc_ptr)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&tbuf_lock, flags);
+ frame_commit(alloc_ptr);
+ spin_unlock_irqrestore(&tbuf_lock, flags);
+}
+
+static void add_syn_to_track_list(PVRSRV_KERNEL_SYNC_INFO *si)
+{
+ /* only add if not already on the list */
+ if (list_empty(&si->link))
+ list_add(&si->link, &syn_track_list);
+}
+
+static void remove_syn_from_track_list(PVRSRV_KERNEL_SYNC_INFO *si)
+{
+ list_del_init(&si->link);
+}
+
+static void __set_syn(struct pvr_trcmd_syn *ts,
+ PVRSRV_KERNEL_SYNC_INFO *si)
+{
+ PVRSRV_SYNC_DATA *sd = si->psSyncData;
+
+ ts->rd_pend = sd->ui32ReadOpsPending;
+ ts->rd_comp = sd->ui32ReadOpsComplete;
+ ts->wr_pend = sd->ui32WriteOpsPending;
+ ts->wr_comp = sd->ui32WriteOpsComplete;
+ ts->addr = si->sWriteOpsCompleteDevVAddr.uiAddr - 4;
+}
+
+void pvr_trcmd_remove_syn(int pid, const char *pname,
+ PVRSRV_KERNEL_SYNC_INFO *si)
+{
+ struct pvr_trcmd_syn *ts;
+ unsigned long flags;
+
+ spin_lock_irqsave(&tbuf_lock, flags);
+
+ ts = frame_reserve(PVR_TRCMD_SYN_REMOVE, pid, pname,
+ sizeof(*ts));
+ __set_syn(ts, si);
+ frame_commit(ts);
+ remove_syn_from_track_list(si);
+
+ spin_unlock_irqrestore(&tbuf_lock, flags);
+}
+
+void pvr_trcmd_set_syn(struct pvr_trcmd_syn *ts,
+ PVRSRV_KERNEL_SYNC_INFO *si)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&tbuf_lock, flags);
+ add_syn_to_track_list(si);
+ spin_unlock_irqrestore(&tbuf_lock, flags);
+
+ __set_syn(ts, si);
+}
+
+static unsigned long calc_syn_digest(PVRSRV_SYNC_DATA *sd)
+{
+ return sd->ui32ReadOpsPending +
+ sd->ui32ReadOpsComplete +
+ sd->ui32WriteOpsPending +
+ sd->ui32WriteOpsComplete;
+}
+
+static int syn_has_changed(PVRSRV_KERNEL_SYNC_INFO *si)
+{
+ unsigned long digest;
+ int changed;
+
+ digest = calc_syn_digest(si->psSyncData);
+ changed = digest != si->counter_digest;
+ si->counter_digest = digest;
+
+ return changed;
+}
+
+static int syn_is_complete(PVRSRV_KERNEL_SYNC_INFO *si)
+{
+ PVRSRV_SYNC_DATA *sd = si->psSyncData;
+
+ return sd->ui32ReadOpsPending == sd->ui32ReadOpsComplete &&
+ sd->ui32WriteOpsPending == sd->ui32WriteOpsComplete;
+}
+
+void pvr_trcmd_check_syn_completions(int type)
+{
+ PVRSRV_KERNEL_SYNC_INFO *si;
+ PVRSRV_KERNEL_SYNC_INFO *tmp;
+ unsigned long flags;
+
+ spin_lock_irqsave(&tbuf_lock, flags);
+
+ list_for_each_entry_safe(si, tmp, &syn_track_list, link) {
+ if (syn_has_changed(si)) {
+ struct pvr_trcmd_syn *ts;
+
+ ts = frame_reserve(type, 0, "irq", sizeof(*ts));
+ __set_syn(ts, si);
+ frame_commit(ts);
+ }
+ if (syn_is_complete(si))
+ remove_syn_from_track_list(si);
+ }
+
+ spin_unlock_irqrestore(&tbuf_lock, flags);
+}
--- /dev/null
+/*
+ * Copyright (C) 2011 Nokia Corporation
+ * Copyright (C) 2011 Intel Corporation
+ * Author: Imre Deak <imre.deak@intel.com>
+ *
+ * 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __PVR_TRACE_CMD_H__
+#define __PVR_TRACE_CMD_H__
+
+#include <linux/mutex.h>
+
+#include "servicesint.h"
+#include "sgxapi_km.h"
+
+enum pvr_trcmd_type {
+ PVR_TRCMD_PAD,
+ PVR_TRCMD_SGX_FIRSTKICK,
+ PVR_TRCMD_SGX_KICK,
+ PVR_TRCMD_SGX_TFER_KICK,
+ PVR_TRCMD_SGX_COMP,
+ PVR_TRCMD_SYN_REMOVE,
+ PVR_TRCMD_SGX_QBLT_SYNCHK,
+ PVR_TRCMD_FLPREQ,
+ PVR_TRCMD_FLPCOMP,
+};
+
+struct pvr_trcmd_buf;
+
+struct pvr_trcmd_syn {
+ unsigned long rd_pend;
+ unsigned long rd_comp;
+ unsigned long wr_pend;
+ unsigned long wr_comp;
+ unsigned long addr;
+};
+
+struct pvr_trcmd_sgxkick {
+ struct pvr_trcmd_syn tatq_syn;
+ struct pvr_trcmd_syn _3dtq_syn;
+ struct pvr_trcmd_syn src_syn[SGX_MAX_SRC_SYNCS];
+ struct pvr_trcmd_syn dst_syn;
+ struct pvr_trcmd_syn ta3d_syn;
+ unsigned long ctx;
+};
+
+struct pvr_trcmd_sgxtransfer {
+ struct pvr_trcmd_syn ta_syn;
+ struct pvr_trcmd_syn _3d_syn;
+ struct pvr_trcmd_syn src_syn[SGX_MAX_TRANSFER_SYNC_OPS];
+ struct pvr_trcmd_syn dst_syn[SGX_MAX_TRANSFER_SYNC_OPS];
+ unsigned long ctx;
+};
+
+struct pvr_trcmd_flpreq {
+ struct pvr_trcmd_syn src_syn[2];
+};
+
+#ifdef CONFIG_PVR_TRACE_CMD
+
+void *pvr_trcmd_reserve(unsigned type, int pid, const char *pname,
+ size_t size);
+
+void pvr_trcmd_commit(void *alloc_ptr);
+
+int pvr_trcmd_create_snapshot(u8 **snapshot_ret, size_t *snapshot_size);
+void pvr_trcmd_destroy_snapshot(void *snapshot);
+
+size_t pvr_trcmd_print(char *dst, size_t dst_size, const u8 *snapshot,
+ size_t snapshot_size, loff_t *snapshot_ofs);
+
+void pvr_trcmd_set_syn(struct pvr_trcmd_syn *ts,
+ PVRSRV_KERNEL_SYNC_INFO *si);
+
+void pvr_trcmd_remove_syn(int pid, const char *pname,
+ PVRSRV_KERNEL_SYNC_INFO *si);
+
+static inline void pvr_trcmd_set_data(unsigned long *a, unsigned long val)
+{
+ *a = val;
+}
+
+static inline void pvr_trcmd_clear_syn(struct pvr_trcmd_syn *ts)
+{
+ memset(ts, 0, sizeof(*ts));
+}
+
+void pvr_trcmd_check_syn_completions(int type);
+
+#else
+
+static inline void *
+pvr_trcmd_reserve(unsigned type, int pid, const char *pname,
+ size_t size)
+{
+ return NULL;
+}
+
+static inline void pvr_trcmd_commit(void *alloc_ptr)
+{
+}
+
+static inline int
+pvr_trcmd_create_snapshot(u8 **snapshot_ret, size_t *snapshot_size)
+{
+ return 0;
+}
+
+static inline void pvr_trcmd_destroy_snapshot(void *snapshot)
+{
+}
+
+static inline size_t
+pvr_trcmd_print(char *dst, size_t dst_size, const u8 *snapshot,
+ size_t snapshot_size, loff_t *snapshot_ofs)
+{
+ return 0;
+}
+
+static inline void
+pvr_trcmd_set_syn(struct pvr_trcmd_syn *ts,
+ PVRSRV_KERNEL_SYNC_INFO *si)
+{
+}
+
+static inline void pvr_trcmd_remove_syn(int pid, const char *pname,
+ PVRSRV_KERNEL_SYNC_INFO *si)
+{
+}
+
+static inline void pvr_trcmd_set_data(unsigned long *a, unsigned long val)
+{
+}
+
+static inline void pvr_trcmd_clear_syn(struct pvr_trcmd_syn *ts)
+{
+}
+
+static inline void pvr_trcmd_check_syn_completions(int type)
+{
+}
+
+#endif /* CONFIG_PVR_SYNC_CNT */
+
+#endif
--- /dev/null
+bin_pc_i686*
+tmp_pc_i686*
+host_pc_i686*
+binary_pc_i686*
+*.o
+*.o.cmd
--- /dev/null
+#
+# 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
+#
+#
+#
+
+ifeq ($(SUPPORT_DRI_DRM),1)
+DISPLAY_CONTROLLER_SOURCES_ROOT = $(KBUILDROOT)/$(DISPLAY_CONTROLLER_DIR)
+else
+DISPLAY_CONTROLLER_SOURCES_ROOT = ..
+endif
+
+INCLUDES += -I$(EURASIAROOT)/include4 \
+ -I$(EURASIAROOT)/services4/include \
+ -I$(EURASIAROOT)/services4/system/$(PVR_SYSTEM) \
+ -I$(EURASIAROOT)/services4/system/include \
+ -I$(EURASIAROOT)/services4/srvkm/env/linux/mrst
+
+SOURCES += $(DISPLAY_CONTROLLER_SOURCES_ROOT)/mrstlfb_displayclass.c \
+ $(DISPLAY_CONTROLLER_SOURCES_ROOT)/mrstlfb_linux.c
+MODULE_CFLAGS += -DPVR_MRST_FB_SET_PAR_ON_INIT
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef __MRSTLFB_H__
+#define __MRSTLFB_H__
+
+#include <drm/drmP.h>
+#include "psb_intel_reg.h"
+
+#define MRST_USING_INTERRUPTS
+
+#define PSB_HWSTAM 0x2098
+#define PSB_INSTPM 0x20C0
+#define PSB_INT_IDENTITY_R 0x20A4
+#define _PSB_VSYNC_PIPEB_FLAG (1<<5)
+#define _PSB_VSYNC_PIPEA_FLAG (1<<7)
+#define _PSB_IRQ_SGX_FLAG (1<<18)
+#define _PSB_IRQ_MSVDX_FLAG (1<<19)
+#define _LNC_IRQ_TOPAZ_FLAG (1<<20)
+#define PSB_INT_MASK_R 0x20A8
+#define PSB_INT_ENABLE_R 0x20A0
+
+#define MAX_SWAPCHAINS 10
+
+/* IPC message and command defines used to enable/disable mipi panel voltages */
+#define IPC_MSG_PANEL_ON_OFF 0xE9
+#define IPC_CMD_PANEL_ON 1
+#define IPC_CMD_PANEL_OFF 0
+
+typedef void * MRST_HANDLE;
+
+typedef enum tag_mrst_bool
+{
+ MRST_FALSE = 0,
+ MRST_TRUE = 1,
+} MRST_BOOL, *MRST_PBOOL;
+
+typedef int(* MRSTLFB_VSYNC_ISR_PFN)(struct drm_device* psDrmDevice, int iPipe);
+
+
+typedef struct MRSTLFB_BUFFER_TAG
+{
+
+ IMG_UINT32 ui32BufferSize;
+ union {
+
+ IMG_SYS_PHYADDR *psNonCont;
+
+ IMG_SYS_PHYADDR sCont;
+ } uSysAddr;
+
+ IMG_DEV_VIRTADDR sDevVAddr;
+
+ IMG_CPU_VIRTADDR sCPUVAddr;
+
+ PVRSRV_SYNC_DATA *psSyncData;
+
+ MRST_BOOL bIsContiguous;
+
+ MRST_BOOL bIsAllocated;
+
+ IMG_UINT32 ui32OwnerTaskID;
+} MRSTLFB_BUFFER;
+
+typedef struct MRSTLFB_VSYNC_FLIP_ITEM_TAG
+{
+
+
+
+ MRST_HANDLE hCmdComplete;
+
+ unsigned long ulSwapInterval;
+
+ MRST_BOOL bValid;
+
+ MRST_BOOL bFlipped;
+
+ MRST_BOOL bCmdCompleted;
+
+
+
+
+
+ MRSTLFB_BUFFER* psBuffer;
+} MRSTLFB_VSYNC_FLIP_ITEM;
+
+typedef struct MRSTLFB_SWAPCHAIN_TAG
+{
+
+ unsigned long ulBufferCount;
+
+ IMG_UINT32 ui32SwapChainID;
+
+
+ MRSTLFB_BUFFER **ppsBuffer;
+
+
+ unsigned long ulSwapChainLength;
+
+
+ MRSTLFB_VSYNC_FLIP_ITEM *psVSyncFlips;
+
+
+ unsigned long ulInsertIndex;
+
+
+ unsigned long ulRemoveIndex;
+
+
+ PVRSRV_DC_DISP2SRV_KMJTABLE *psPVRJTable;
+
+
+ struct drm_driver *psDrmDriver;
+
+
+ struct drm_device *psDrmDev;
+
+ struct MRSTLFB_SWAPCHAIN_TAG *psNext;
+
+ struct MRSTLFB_DEVINFO_TAG *psDevInfo;
+
+} MRSTLFB_SWAPCHAIN;
+
+typedef struct MRSTLFB_FBINFO_TAG
+{
+ unsigned long ulFBSize;
+ unsigned long ulBufferSize;
+ unsigned long ulRoundedBufferSize;
+ unsigned long ulWidth;
+ unsigned long ulHeight;
+ unsigned long ulByteStride;
+
+
+
+ IMG_SYS_PHYADDR sSysAddr;
+ IMG_CPU_VIRTADDR sCPUVAddr;
+ IMG_DEV_VIRTADDR sDevVAddr;
+
+
+ PVRSRV_PIXEL_FORMAT ePixelFormat;
+}MRSTLFB_FBINFO;
+
+/**
+ * If DRI is enable then extemding drm_device
+ */
+typedef struct MRSTLFB_DEVINFO_TAG
+{
+ unsigned int uiDeviceID;
+
+ struct drm_device *psDrmDevice;
+
+
+
+ MRSTLFB_BUFFER sSystemBuffer;
+
+
+ PVRSRV_DC_DISP2SRV_KMJTABLE sPVRJTable;
+
+
+ PVRSRV_DC_SRV2DISP_KMJTABLE sDCJTable;
+
+
+ unsigned long ulRefCount;
+
+ MRSTLFB_SWAPCHAIN *psCurrentSwapChain;
+
+ MRSTLFB_SWAPCHAIN *apsSwapChains[MAX_SWAPCHAINS];
+
+ IMG_UINT32 ui32SwapChainNum;
+
+
+ void *pvRegs;
+
+
+ unsigned long ulSetFlushStateRefCount;
+
+
+ MRST_BOOL bFlushCommands;
+
+
+ MRST_BOOL bBlanked;
+
+
+ struct fb_info *psLINFBInfo;
+
+
+ struct notifier_block sLINNotifBlock;
+
+
+ spinlock_t sSwapChainLock;
+
+
+
+
+ IMG_DEV_VIRTADDR sDisplayDevVAddr;
+
+ DISPLAY_INFO sDisplayInfo;
+
+
+ DISPLAY_FORMAT sDisplayFormat;
+
+
+ DISPLAY_DIMS sDisplayDim;
+
+ IMG_UINT32 ui32MainPipe;
+
+
+ MRST_BOOL bSuspended;
+
+
+ MRST_BOOL bLeaveVT;
+
+
+ unsigned long ulLastFlipAddr;
+
+
+ MRST_BOOL bLastFlipAddrValid;
+} MRSTLFB_DEVINFO;
+
+#if 0
+#define MRSTLFB_PAGE_SIZE 4096
+#define MRSTLFB_PAGE_MASK (MRSTLFB_PAGE_SIZE - 1)
+#define MRSTLFB_PAGE_TRUNC (~MRSTLFB_PAGE_MASK)
+
+#define MRSTLFB_PAGE_ROUNDUP(x) (((x) + MRSTLFB_PAGE_MASK) & MRSTLFB_PAGE_TRUNC)
+#endif
+
+#ifdef DEBUG
+#define DEBUG_PRINTK(x) printk x
+#else
+#define DEBUG_PRINTK(x)
+#endif
+
+#define DISPLAY_DEVICE_NAME "PowerVR Moorestown Linux Display Driver"
+#define DRVNAME "mrstlfb"
+#define DEVNAME DRVNAME
+#define DRIVER_PREFIX DRVNAME
+
+typedef enum _MRST_ERROR_
+{
+ MRST_OK = 0,
+ MRST_ERROR_GENERIC = 1,
+ MRST_ERROR_OUT_OF_MEMORY = 2,
+ MRST_ERROR_TOO_FEW_BUFFERS = 3,
+ MRST_ERROR_INVALID_PARAMS = 4,
+ MRST_ERROR_INIT_FAILURE = 5,
+ MRST_ERROR_CANT_REGISTER_CALLBACK = 6,
+ MRST_ERROR_INVALID_DEVICE = 7,
+ MRST_ERROR_DEVICE_REGISTER_FAILED = 8
+} MRST_ERROR;
+
+
+#ifndef UNREFERENCED_PARAMETER
+#define UNREFERENCED_PARAMETER(param) (param) = (param)
+#endif
+
+MRST_ERROR MRSTLFBInit(struct drm_device * dev);
+MRST_ERROR MRSTLFBDeinit(void);
+
+MRST_ERROR MRSTLFBAllocBuffer(struct MRSTLFB_DEVINFO_TAG *psDevInfo, IMG_UINT32 ui32Size, MRSTLFB_BUFFER **ppBuffer);
+MRST_ERROR MRSTLFBFreeBuffer(struct MRSTLFB_DEVINFO_TAG *psDevInfo, MRSTLFB_BUFFER **ppBuffer);
+
+void *MRSTLFBAllocKernelMem(unsigned long ulSize);
+void MRSTLFBFreeKernelMem(void *pvMem);
+MRST_ERROR MRSTLFBGetLibFuncAddr(char *szFunctionName, PFN_DC_GET_PVRJTABLE *ppfnFuncTable);
+MRST_ERROR MRSTLFBInstallVSyncISR (MRSTLFB_DEVINFO *psDevInfo, MRSTLFB_VSYNC_ISR_PFN pVsyncHandler);
+MRST_ERROR MRSTLFBUninstallVSyncISR(MRSTLFB_DEVINFO *psDevInfo);
+void MRSTLFBEnableVSyncInterrupt(MRSTLFB_DEVINFO *psDevInfo);
+void MRSTLFBDisableVSyncInterrupt(MRSTLFB_DEVINFO *psDevInfo);
+
+void MRSTLFBFlipToSurface(MRSTLFB_DEVINFO *psDevInfo, unsigned long uiAddr);
+
+void MRSTLFBSuspend(void);
+void MRSTLFBResume(void);
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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/version.h>
+#include <linux/kernel.h>
+#include <linux/console.h>
+#include <linux/fb.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/notifier.h>
+#include <linux/spinlock.h>
+#include <asm/intel_scu_ipc.h>
+
+#include "img_defs.h"
+#include "servicesext.h"
+#include "kerneldisplay.h"
+#include "mrstlfb.h"
+
+#include "psb_fb.h"
+#include "psb_drv.h"
+#include "psb_powermgmt.h"
+
+#if !defined(SUPPORT_DRI_DRM)
+#error "SUPPORT_DRI_DRM must be set"
+#endif
+
+IMG_UINT32 gui32MRSTDisplayDeviceID;
+
+PVRSRV_ERROR MRSTLFBPrePowerState(IMG_HANDLE hDevHandle,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+
+PVRSRV_ERROR MRSTLFBPostPowerState(IMG_HANDLE hDevHandle,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+
+struct psbfb_par {
+ struct drm_device *dev;
+ void *psbfb;
+
+ int dpms_state;
+
+ int crtc_count;
+
+ uint32_t crtc_ids[2];
+};
+
+static void *gpvAnchor;
+
+
+#define MRSTLFB_COMMAND_COUNT 1
+
+static PFN_DC_GET_PVRJTABLE pfnGetPVRJTable = 0;
+
+static MRSTLFB_DEVINFO * GetAnchorPtr(void)
+{
+ return (MRSTLFB_DEVINFO *)gpvAnchor;
+}
+
+static void SetAnchorPtr(MRSTLFB_DEVINFO *psDevInfo)
+{
+ gpvAnchor = (void*)psDevInfo;
+}
+
+static void MRSTLFBFlip(MRSTLFB_DEVINFO *psDevInfo, MRSTLFB_BUFFER *psBuffer)
+{
+ unsigned long ulAddr = (unsigned long)psBuffer->sDevVAddr.uiAddr;
+
+ if (!psDevInfo->bSuspended && !psDevInfo->bLeaveVT)
+ {
+ MRSTLFBFlipToSurface(psDevInfo, ulAddr);
+ }
+
+ psDevInfo->ulLastFlipAddr = ulAddr;
+ psDevInfo->bLastFlipAddrValid = MRST_TRUE;
+}
+
+static void MRSTLFBRestoreLastFlip(MRSTLFB_DEVINFO *psDevInfo)
+{
+ if (!psDevInfo->bSuspended && !psDevInfo->bLeaveVT)
+ {
+ if (psDevInfo->bLastFlipAddrValid)
+ {
+ MRSTLFBFlipToSurface(psDevInfo, psDevInfo->ulLastFlipAddr);
+ }
+ }
+}
+
+static void MRSTLFBClearSavedFlip(MRSTLFB_DEVINFO *psDevInfo)
+{
+ psDevInfo->bLastFlipAddrValid = MRST_FALSE;
+}
+
+static void FlushInternalVSyncQueue(MRSTLFB_SWAPCHAIN *psSwapChain, MRST_BOOL bFlip)
+{
+ MRSTLFB_VSYNC_FLIP_ITEM *psFlipItem;
+ unsigned long ulMaxIndex;
+ unsigned long i;
+
+
+ psFlipItem = &psSwapChain->psVSyncFlips[psSwapChain->ulRemoveIndex];
+ ulMaxIndex = psSwapChain->ulSwapChainLength - 1;
+
+ for(i = 0; i < psSwapChain->ulSwapChainLength; i++)
+ {
+ if (psFlipItem->bValid == MRST_FALSE)
+ {
+ continue;
+ }
+
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": FlushInternalVSyncQueue: Flushing swap buffer (index %lu)\n", psSwapChain->ulRemoveIndex));
+
+ if(psFlipItem->bFlipped == MRST_FALSE)
+ {
+ if (bFlip)
+ {
+
+ MRSTLFBFlip(psSwapChain->psDevInfo, psFlipItem->psBuffer);
+ }
+ }
+
+ if(psFlipItem->bCmdCompleted == MRST_FALSE)
+ {
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": FlushInternalVSyncQueue: Calling command complete for swap buffer (index %lu)\n", psSwapChain->ulRemoveIndex));
+
+ psSwapChain->psPVRJTable->pfnPVRSRVCmdComplete((IMG_HANDLE)psFlipItem->hCmdComplete, MRST_TRUE);
+ }
+
+
+ psSwapChain->ulRemoveIndex++;
+
+ if(psSwapChain->ulRemoveIndex > ulMaxIndex)
+ {
+ psSwapChain->ulRemoveIndex = 0;
+ }
+
+
+ psFlipItem->bFlipped = MRST_FALSE;
+ psFlipItem->bCmdCompleted = MRST_FALSE;
+ psFlipItem->bValid = MRST_FALSE;
+
+
+ psFlipItem = &psSwapChain->psVSyncFlips[psSwapChain->ulRemoveIndex];
+ }
+
+ psSwapChain->ulInsertIndex = 0;
+ psSwapChain->ulRemoveIndex = 0;
+}
+
+static void DRMLFBFlipBuffer(MRSTLFB_DEVINFO *psDevInfo, MRSTLFB_SWAPCHAIN *psSwapChain, MRSTLFB_BUFFER *psBuffer)
+{
+ if(psSwapChain != NULL)
+ {
+ if(psDevInfo->psCurrentSwapChain != NULL)
+ {
+
+ if(psDevInfo->psCurrentSwapChain != psSwapChain)
+ FlushInternalVSyncQueue(psDevInfo->psCurrentSwapChain, MRST_FALSE);
+ }
+ psDevInfo->psCurrentSwapChain = psSwapChain;
+ }
+
+
+ MRSTLFBFlip(psDevInfo, psBuffer);
+}
+
+static void SetFlushStateNoLock(MRSTLFB_DEVINFO* psDevInfo,
+ MRST_BOOL bFlushState)
+{
+ if (bFlushState)
+ {
+ if (psDevInfo->ulSetFlushStateRefCount == 0)
+ {
+ psDevInfo->bFlushCommands = MRST_TRUE;
+ if (psDevInfo->psCurrentSwapChain != NULL)
+ {
+ FlushInternalVSyncQueue(psDevInfo->psCurrentSwapChain, MRST_TRUE);
+ }
+ }
+ psDevInfo->ulSetFlushStateRefCount++;
+ }
+ else
+ {
+ if (psDevInfo->ulSetFlushStateRefCount != 0)
+ {
+ psDevInfo->ulSetFlushStateRefCount--;
+ if (psDevInfo->ulSetFlushStateRefCount == 0)
+ {
+ psDevInfo->bFlushCommands = MRST_FALSE;
+ }
+ }
+ }
+}
+
+static IMG_VOID SetFlushState(MRSTLFB_DEVINFO* psDevInfo,
+ MRST_BOOL bFlushState)
+{
+ unsigned long ulLockFlags;
+
+ spin_lock_irqsave(&psDevInfo->sSwapChainLock, ulLockFlags);
+
+ SetFlushStateNoLock(psDevInfo, bFlushState);
+
+ spin_unlock_irqrestore(&psDevInfo->sSwapChainLock, ulLockFlags);
+}
+
+static IMG_VOID SetDCState(IMG_HANDLE hDevice, IMG_UINT32 ui32State)
+{
+ MRSTLFB_DEVINFO *psDevInfo = (MRSTLFB_DEVINFO *)hDevice;
+
+ switch (ui32State)
+ {
+ case DC_STATE_FLUSH_COMMANDS:
+ SetFlushState(psDevInfo, MRST_TRUE);
+ break;
+ case DC_STATE_NO_FLUSH_COMMANDS:
+ SetFlushState(psDevInfo, MRST_FALSE);
+ break;
+ default:
+ break;
+ }
+
+ return;
+}
+
+static int FrameBufferEvents(struct notifier_block *psNotif,
+ unsigned long event, void *data)
+{
+ MRSTLFB_DEVINFO *psDevInfo;
+ struct fb_event *psFBEvent = (struct fb_event *)data;
+ MRST_BOOL bBlanked;
+
+
+ if (event != FB_EVENT_BLANK)
+ {
+ return 0;
+ }
+
+ psDevInfo = GetAnchorPtr();
+
+ bBlanked = (*(IMG_INT *)psFBEvent->data != 0) ? MRST_TRUE: MRST_FALSE;
+
+ if (bBlanked != psDevInfo->bBlanked)
+ {
+ psDevInfo->bBlanked = bBlanked;
+
+ SetFlushState(psDevInfo, bBlanked);
+ }
+
+ return 0;
+}
+
+
+static MRST_ERROR UnblankDisplay(MRSTLFB_DEVINFO *psDevInfo)
+{
+ int res;
+
+ console_lock();
+ res = fb_blank(psDevInfo->psLINFBInfo, 0);
+ console_unlock();
+ if (res != 0)
+ {
+ printk(KERN_WARNING DRIVER_PREFIX
+ ": fb_blank failed (%d)", res);
+ return (MRST_ERROR_GENERIC);
+ }
+
+ return (MRST_OK);
+}
+
+static MRST_ERROR EnableLFBEventNotification(MRSTLFB_DEVINFO *psDevInfo)
+{
+ int res;
+ MRST_ERROR eError;
+
+
+ memset(&psDevInfo->sLINNotifBlock, 0, sizeof(psDevInfo->sLINNotifBlock));
+
+ psDevInfo->sLINNotifBlock.notifier_call = FrameBufferEvents;
+ psDevInfo->bBlanked = MRST_FALSE;
+
+ res = fb_register_client(&psDevInfo->sLINNotifBlock);
+ if (res != 0)
+ {
+ printk(KERN_WARNING DRIVER_PREFIX
+ ": fb_register_client failed (%d)", res);
+
+ return (MRST_ERROR_GENERIC);
+ }
+
+ eError = UnblankDisplay(psDevInfo);
+ if (eError != MRST_OK)
+ {
+ DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX
+ ": UnblankDisplay failed (%d)", eError));
+ return eError;
+ }
+
+ return (MRST_OK);
+}
+
+static MRST_ERROR DisableLFBEventNotification(MRSTLFB_DEVINFO *psDevInfo)
+{
+ int res;
+
+
+ res = fb_unregister_client(&psDevInfo->sLINNotifBlock);
+ if (res != 0)
+ {
+ printk(KERN_WARNING DRIVER_PREFIX
+ ": fb_unregister_client failed (%d)", res);
+ return (MRST_ERROR_GENERIC);
+ }
+
+ return (MRST_OK);
+}
+
+static PVRSRV_ERROR OpenDCDevice(IMG_UINT32 ui32DeviceID,
+ IMG_HANDLE *phDevice,
+ PVRSRV_SYNC_DATA* psSystemBufferSyncData)
+{
+ MRSTLFB_DEVINFO *psDevInfo;
+ MRST_ERROR eError;
+
+ UNREFERENCED_PARAMETER(ui32DeviceID);
+
+ psDevInfo = GetAnchorPtr();
+
+
+ psDevInfo->sSystemBuffer.psSyncData = psSystemBufferSyncData;
+
+ psDevInfo->ulSetFlushStateRefCount = 0;
+ psDevInfo->bFlushCommands = MRST_FALSE;
+
+ eError = EnableLFBEventNotification(psDevInfo);
+ if (eError != MRST_OK)
+ {
+ printk(KERN_WARNING DRIVER_PREFIX ": Couldn't enable framebuffer event notification\n");
+ return PVRSRV_ERROR_UNABLE_TO_OPEN_DC_DEVICE;
+ }
+
+
+ *phDevice = (IMG_HANDLE)psDevInfo;
+
+ return (PVRSRV_OK);
+}
+
+static PVRSRV_ERROR CloseDCDevice(IMG_HANDLE hDevice)
+{
+ MRSTLFB_DEVINFO *psDevInfo = (MRSTLFB_DEVINFO *)hDevice;
+ MRST_ERROR eError;
+
+ eError = DisableLFBEventNotification(psDevInfo);
+ if (eError != MRST_OK)
+ {
+ printk(KERN_WARNING DRIVER_PREFIX ": Couldn't disable framebuffer event notification\n");
+ return PVRSRV_ERROR_UNABLE_TO_REMOVE_DEVICE;
+ }
+
+ return (PVRSRV_OK);
+}
+
+static PVRSRV_ERROR EnumDCFormats(IMG_HANDLE hDevice,
+ IMG_UINT32 *pui32NumFormats,
+ DISPLAY_FORMAT *psFormat)
+{
+ MRSTLFB_DEVINFO *psDevInfo;
+
+ if(!hDevice || !pui32NumFormats)
+ {
+ return (PVRSRV_ERROR_INVALID_PARAMS);
+ }
+
+ psDevInfo = (MRSTLFB_DEVINFO*)hDevice;
+
+ *pui32NumFormats = 1;
+
+ if(psFormat)
+ {
+ psFormat[0] = psDevInfo->sDisplayFormat;
+ }
+
+ return (PVRSRV_OK);
+}
+
+static PVRSRV_ERROR EnumDCDims(IMG_HANDLE hDevice,
+ DISPLAY_FORMAT *psFormat,
+ IMG_UINT32 *pui32NumDims,
+ DISPLAY_DIMS *psDim)
+{
+ MRSTLFB_DEVINFO *psDevInfo;
+
+ if(!hDevice || !psFormat || !pui32NumDims)
+ {
+ return (PVRSRV_ERROR_INVALID_PARAMS);
+ }
+
+ psDevInfo = (MRSTLFB_DEVINFO*)hDevice;
+
+ *pui32NumDims = 1;
+
+
+ if(psDim)
+ {
+ psDim[0] = psDevInfo->sDisplayDim;
+ }
+
+ return (PVRSRV_OK);
+}
+
+
+static PVRSRV_ERROR GetDCSystemBuffer(IMG_HANDLE hDevice, IMG_HANDLE *phBuffer)
+{
+ MRSTLFB_DEVINFO *psDevInfo;
+
+ if(!hDevice || !phBuffer)
+ {
+ return (PVRSRV_ERROR_INVALID_PARAMS);
+ }
+
+ psDevInfo = (MRSTLFB_DEVINFO*)hDevice;
+
+
+
+ *phBuffer = (IMG_HANDLE)&psDevInfo->sSystemBuffer;
+
+ return (PVRSRV_OK);
+}
+
+
+static PVRSRV_ERROR GetDCInfo(IMG_HANDLE hDevice, DISPLAY_INFO *psDCInfo)
+{
+ MRSTLFB_DEVINFO *psDevInfo;
+
+ if(!hDevice || !psDCInfo)
+ {
+ return (PVRSRV_ERROR_INVALID_PARAMS);
+ }
+
+ psDevInfo = (MRSTLFB_DEVINFO*)hDevice;
+
+ *psDCInfo = psDevInfo->sDisplayInfo;
+
+ return (PVRSRV_OK);
+}
+
+static PVRSRV_ERROR GetDCBufferAddr(IMG_HANDLE hDevice,
+ IMG_HANDLE hBuffer,
+ IMG_SYS_PHYADDR **ppsSysAddr,
+ IMG_SIZE_T *pui32ByteSize,
+ IMG_VOID **ppvCpuVAddr,
+ IMG_HANDLE *phOSMapInfo,
+ IMG_BOOL *pbIsContiguous,
+ IMG_UINT32 *pui32TilingStride)
+{
+ MRSTLFB_DEVINFO *psDevInfo;
+ MRSTLFB_BUFFER *psSystemBuffer;
+
+ UNREFERENCED_PARAMETER(pui32TilingStride);
+
+ if(!hDevice)
+ {
+ return (PVRSRV_ERROR_INVALID_PARAMS);
+ }
+ psDevInfo = (MRSTLFB_DEVINFO*)hDevice;
+
+ if(!hBuffer)
+ {
+ return (PVRSRV_ERROR_INVALID_PARAMS);
+ }
+ psSystemBuffer = (MRSTLFB_BUFFER *)hBuffer;
+
+ if (!ppsSysAddr)
+ {
+ return (PVRSRV_ERROR_INVALID_PARAMS);
+ }
+
+ if( psSystemBuffer->bIsContiguous )
+ *ppsSysAddr = &psSystemBuffer->uSysAddr.sCont;
+ else
+ *ppsSysAddr = psSystemBuffer->uSysAddr.psNonCont;
+
+ if (!pui32ByteSize)
+ {
+ return (PVRSRV_ERROR_INVALID_PARAMS);
+ }
+ *pui32ByteSize = psSystemBuffer->ui32BufferSize;
+
+ if (ppvCpuVAddr)
+ {
+ *ppvCpuVAddr = psSystemBuffer->sCPUVAddr;
+ }
+
+ if (phOSMapInfo)
+ {
+ *phOSMapInfo = (IMG_HANDLE)0;
+ }
+
+ if (pbIsContiguous)
+ {
+ *pbIsContiguous = psSystemBuffer->bIsContiguous;
+ }
+
+ return (PVRSRV_OK);
+}
+
+
+#if 0
+static MRST_ERROR MRSTLFBEnableSwapChains(MRSTLFB_DEVINFO *psDevInfo)
+{
+ unsigned long ulLockFlags;
+
+ spin_lock_irqsave(&psDevInfo->sSwapChainLock, ulLockFlags);
+
+ if(!psDevInfo->bFlushCommands)
+ MRSTLFBEnableVSyncInterrupt(psDevInfo);
+
+ spin_unlock_irqrestore(&psDevInfo->sSwapChainLock, ulLockFlags);
+
+ if (EnableLFBEventNotification(psDevInfo)!= MRST_OK)
+ {
+ printk(KERN_WARNING DRIVER_PREFIX ": Couldn't enable framebuffer event notification\n");
+ }
+
+ return MRST_OK;
+}
+
+static MRST_ERROR MRSTLFBDisableSwapChains(MRSTLFB_DEVINFO *psDevInfo)
+{
+ MRST_ERROR eError;
+ unsigned long ulLockFlags;
+
+ eError = DisableLFBEventNotification(psDevInfo);
+ if (eError != MRST_OK)
+ {
+ printk(KERN_WARNING DRIVER_PREFIX ": Couldn't disable framebuffer event notification\n");
+ }
+
+ spin_lock_irqsave(&psDevInfo->sSwapChainLock, ulLockFlags);
+
+ MRSTLFBDisableVSyncInterrupt(psDevInfo);
+
+
+ MRSTLFBFlip(psDevInfo, &psDevInfo->sSystemBuffer);
+
+ psDevInfo->psCurrentSwapChain = NULL;
+
+ spin_unlock_irqrestore(&psDevInfo->sSwapChainLock, ulLockFlags);
+ return MRST_OK;
+}
+#endif
+
+
+static PVRSRV_ERROR CreateDCSwapChain(IMG_HANDLE hDevice,
+ IMG_UINT32 ui32Flags,
+ DISPLAY_SURF_ATTRIBUTES *psDstSurfAttrib,
+ DISPLAY_SURF_ATTRIBUTES *psSrcSurfAttrib,
+ IMG_UINT32 ui32BufferCount,
+ PVRSRV_SYNC_DATA **ppsSyncData,
+ IMG_UINT32 ui32OEMFlags,
+ IMG_HANDLE *phSwapChain,
+ IMG_UINT32 *pui32SwapChainID)
+{
+ MRSTLFB_DEVINFO *psDevInfo;
+ MRSTLFB_SWAPCHAIN *psSwapChain;
+ MRSTLFB_BUFFER **ppsBuffer;
+ MRSTLFB_VSYNC_FLIP_ITEM *psVSyncFlips;
+ IMG_UINT32 i;
+ IMG_UINT32 iSCId = MAX_SWAPCHAINS;
+ PVRSRV_ERROR eError = PVRSRV_ERROR_NOT_SUPPORTED;
+ unsigned long ulLockFlags;
+ struct drm_device* psDrmDev;
+ unsigned long ulSwapChainLength;
+
+ UNREFERENCED_PARAMETER(ui32OEMFlags);
+
+
+ if(!hDevice
+ || !psDstSurfAttrib
+ || !psSrcSurfAttrib
+ || !ppsSyncData
+ || !phSwapChain)
+ {
+ return (PVRSRV_ERROR_INVALID_PARAMS);
+ }
+
+ psDevInfo = (MRSTLFB_DEVINFO*)hDevice;
+
+
+ if(ui32BufferCount > psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers)
+ {
+ return (PVRSRV_ERROR_TOOMANYBUFFERS);
+ }
+
+
+ ulSwapChainLength = ui32BufferCount + 1;
+
+
+
+ if(psDstSurfAttrib->pixelformat != psDevInfo->sDisplayFormat.pixelformat
+ || psDstSurfAttrib->sDims.ui32ByteStride != psDevInfo->sDisplayDim.ui32ByteStride
+ || psDstSurfAttrib->sDims.ui32Width != psDevInfo->sDisplayDim.ui32Width
+ || psDstSurfAttrib->sDims.ui32Height != psDevInfo->sDisplayDim.ui32Height)
+ {
+
+ return (PVRSRV_ERROR_INVALID_PARAMS);
+ }
+
+ if(psDstSurfAttrib->pixelformat != psSrcSurfAttrib->pixelformat
+ || psDstSurfAttrib->sDims.ui32ByteStride != psSrcSurfAttrib->sDims.ui32ByteStride
+ || psDstSurfAttrib->sDims.ui32Width != psSrcSurfAttrib->sDims.ui32Width
+ || psDstSurfAttrib->sDims.ui32Height != psSrcSurfAttrib->sDims.ui32Height)
+ {
+
+ return (PVRSRV_ERROR_INVALID_PARAMS);
+ }
+
+
+ UNREFERENCED_PARAMETER(ui32Flags);
+
+
+ psSwapChain = (MRSTLFB_SWAPCHAIN*)MRSTLFBAllocKernelMem(sizeof(MRSTLFB_SWAPCHAIN));
+ if(!psSwapChain)
+ {
+ return (PVRSRV_ERROR_OUT_OF_MEMORY);
+ }
+
+ for(iSCId = 0;iSCId < MAX_SWAPCHAINS;++iSCId)
+ {
+ if( psDevInfo->apsSwapChains[iSCId] == NULL )
+ {
+ psDevInfo->apsSwapChains[iSCId] = psSwapChain;
+ break;
+ }
+ }
+
+ if(iSCId == MAX_SWAPCHAINS)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto ErrorFreeSwapChain;
+ }
+
+ ppsBuffer = (MRSTLFB_BUFFER**)MRSTLFBAllocKernelMem(sizeof(MRSTLFB_BUFFER*) * ui32BufferCount);
+ if(!ppsBuffer)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto ErrorFreeSwapChain;
+ }
+
+ psVSyncFlips = (MRSTLFB_VSYNC_FLIP_ITEM *)MRSTLFBAllocKernelMem(sizeof(MRSTLFB_VSYNC_FLIP_ITEM) * ulSwapChainLength);
+ if (!psVSyncFlips)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto ErrorFreeBuffers;
+ }
+
+ psSwapChain->ulSwapChainLength = ulSwapChainLength;
+ psSwapChain->ulBufferCount = (unsigned long)ui32BufferCount;
+ psSwapChain->ppsBuffer = ppsBuffer;
+ psSwapChain->psVSyncFlips = psVSyncFlips;
+ psSwapChain->ulInsertIndex = 0;
+ psSwapChain->ulRemoveIndex = 0;
+ psSwapChain->psPVRJTable = &psDevInfo->sPVRJTable;
+
+
+
+ for (i = 0; i < ui32BufferCount; i++)
+ {
+ unsigned long bufSize = psDevInfo->sDisplayDim.ui32ByteStride * psDevInfo->sDisplayDim.ui32Height;
+ MRSTLFBAllocBuffer(psDevInfo, bufSize, &ppsBuffer[i] );
+ ppsBuffer[i]->psSyncData = ppsSyncData[i];
+ }
+
+
+ for (i = 0; i < ulSwapChainLength; i++)
+ {
+ psVSyncFlips[i].bValid = MRST_FALSE;
+ psVSyncFlips[i].bFlipped = MRST_FALSE;
+ psVSyncFlips[i].bCmdCompleted = MRST_FALSE;
+ }
+
+
+ psDrmDev = psDevInfo->psDrmDevice;
+
+ psSwapChain->psDevInfo = psDevInfo;
+ psSwapChain->psDrmDev = psDrmDev;
+ psSwapChain->psDrmDriver = psDrmDev->driver;
+
+ spin_lock_irqsave(&psDevInfo->sSwapChainLock, ulLockFlags);
+
+ psSwapChain->ui32SwapChainID = *pui32SwapChainID = iSCId+1;
+
+ if(psDevInfo->psCurrentSwapChain == NULL)
+ psDevInfo->psCurrentSwapChain = psSwapChain;
+
+ psDevInfo->ui32SwapChainNum++;
+ if(psDevInfo->ui32SwapChainNum == 1)
+ {
+ MRSTLFBEnableVSyncInterrupt(psDevInfo);
+ }
+
+ spin_unlock_irqrestore(&psDevInfo->sSwapChainLock, ulLockFlags);
+
+
+ *phSwapChain = (IMG_HANDLE)psSwapChain;
+
+ return (PVRSRV_OK);
+
+ MRSTLFBFreeKernelMem(psVSyncFlips);
+ErrorFreeBuffers:
+ MRSTLFBFreeKernelMem(ppsBuffer);
+ErrorFreeSwapChain:
+ if(iSCId != MAX_SWAPCHAINS && psDevInfo->apsSwapChains[iSCId] == psSwapChain )
+ psDevInfo->apsSwapChains[iSCId] = NULL;
+ MRSTLFBFreeKernelMem(psSwapChain);
+
+ return eError;
+}
+
+static PVRSRV_ERROR DestroyDCSwapChain(IMG_HANDLE hDevice,
+ IMG_HANDLE hSwapChain)
+{
+ MRSTLFB_DEVINFO *psDevInfo;
+ MRSTLFB_SWAPCHAIN *psSwapChain;
+ unsigned long ulLockFlags;
+ int i;
+
+
+ if(!hDevice || !hSwapChain)
+ {
+ return (PVRSRV_ERROR_INVALID_PARAMS);
+ }
+
+ psDevInfo = (MRSTLFB_DEVINFO*)hDevice;
+ psSwapChain = (MRSTLFB_SWAPCHAIN*)hSwapChain;
+
+ spin_lock_irqsave(&psDevInfo->sSwapChainLock, ulLockFlags);
+
+ psDevInfo->ui32SwapChainNum--;
+
+ if(psDevInfo->ui32SwapChainNum == 0)
+ {
+ MRSTLFBDisableVSyncInterrupt(psDevInfo);
+ psDevInfo->psCurrentSwapChain = NULL;
+ }
+
+ psDevInfo->apsSwapChains[ psSwapChain->ui32SwapChainID -1] = NULL;
+
+
+ FlushInternalVSyncQueue(psSwapChain, psDevInfo->ui32SwapChainNum == 0);
+
+ if (psDevInfo->ui32SwapChainNum == 0)
+ {
+
+ DRMLFBFlipBuffer(psDevInfo, NULL, &psDevInfo->sSystemBuffer);
+ MRSTLFBClearSavedFlip(psDevInfo);
+ }
+
+ if(psDevInfo->psCurrentSwapChain == psSwapChain)
+ psDevInfo->psCurrentSwapChain = NULL;
+
+ spin_unlock_irqrestore(&psDevInfo->sSwapChainLock, ulLockFlags);
+
+
+ for (i = 0; i < psSwapChain->ulBufferCount; i++)
+ {
+ MRSTLFBFreeBuffer(psDevInfo, &psSwapChain->ppsBuffer[i] );
+ }
+ MRSTLFBFreeKernelMem(psSwapChain->psVSyncFlips);
+ MRSTLFBFreeKernelMem(psSwapChain->ppsBuffer);
+ MRSTLFBFreeKernelMem(psSwapChain);
+
+ return (PVRSRV_OK);
+}
+
+static PVRSRV_ERROR SetDCDstRect(IMG_HANDLE hDevice,
+ IMG_HANDLE hSwapChain,
+ IMG_RECT *psRect)
+{
+ UNREFERENCED_PARAMETER(hDevice);
+ UNREFERENCED_PARAMETER(hSwapChain);
+ UNREFERENCED_PARAMETER(psRect);
+
+
+
+ return (PVRSRV_ERROR_NOT_SUPPORTED);
+}
+
+static PVRSRV_ERROR SetDCSrcRect(IMG_HANDLE hDevice,
+ IMG_HANDLE hSwapChain,
+ IMG_RECT *psRect)
+{
+ UNREFERENCED_PARAMETER(hDevice);
+ UNREFERENCED_PARAMETER(hSwapChain);
+ UNREFERENCED_PARAMETER(psRect);
+
+
+
+ return (PVRSRV_ERROR_NOT_SUPPORTED);
+}
+
+static PVRSRV_ERROR SetDCDstColourKey(IMG_HANDLE hDevice,
+ IMG_HANDLE hSwapChain,
+ IMG_UINT32 ui32CKColour)
+{
+ UNREFERENCED_PARAMETER(hDevice);
+ UNREFERENCED_PARAMETER(hSwapChain);
+ UNREFERENCED_PARAMETER(ui32CKColour);
+
+
+
+ return (PVRSRV_ERROR_NOT_SUPPORTED);
+}
+
+static PVRSRV_ERROR SetDCSrcColourKey(IMG_HANDLE hDevice,
+ IMG_HANDLE hSwapChain,
+ IMG_UINT32 ui32CKColour)
+{
+ UNREFERENCED_PARAMETER(hDevice);
+ UNREFERENCED_PARAMETER(hSwapChain);
+ UNREFERENCED_PARAMETER(ui32CKColour);
+
+
+
+ return (PVRSRV_ERROR_NOT_SUPPORTED);
+}
+
+static PVRSRV_ERROR GetDCBuffers(IMG_HANDLE hDevice,
+ IMG_HANDLE hSwapChain,
+ IMG_UINT32 *pui32BufferCount,
+ IMG_HANDLE *phBuffer)
+{
+ MRSTLFB_DEVINFO *psDevInfo;
+ MRSTLFB_SWAPCHAIN *psSwapChain;
+ unsigned long i;
+
+
+ if(!hDevice
+ || !hSwapChain
+ || !pui32BufferCount
+ || !phBuffer)
+ {
+ return (PVRSRV_ERROR_INVALID_PARAMS);
+ }
+
+ psDevInfo = (MRSTLFB_DEVINFO*)hDevice;
+ psSwapChain = (MRSTLFB_SWAPCHAIN*)hSwapChain;
+
+
+ *pui32BufferCount = (IMG_UINT32)psSwapChain->ulBufferCount;
+
+
+ for(i=0; i<psSwapChain->ulBufferCount; i++)
+ {
+ phBuffer[i] = (IMG_HANDLE)psSwapChain->ppsBuffer[i];
+ }
+
+ return (PVRSRV_OK);
+}
+
+static PVRSRV_ERROR SwapToDCBuffer(IMG_HANDLE hDevice,
+ IMG_HANDLE hBuffer,
+ IMG_UINT32 ui32SwapInterval,
+ IMG_HANDLE hPrivateTag,
+ IMG_UINT32 ui32ClipRectCount,
+ IMG_RECT *psClipRect)
+{
+ MRSTLFB_DEVINFO *psDevInfo;
+
+ UNREFERENCED_PARAMETER(ui32SwapInterval);
+ UNREFERENCED_PARAMETER(hPrivateTag);
+ UNREFERENCED_PARAMETER(psClipRect);
+
+ if(!hDevice
+ || !hBuffer
+ || (ui32ClipRectCount != 0))
+ {
+ return (PVRSRV_ERROR_INVALID_PARAMS);
+ }
+
+ psDevInfo = (MRSTLFB_DEVINFO*)hDevice;
+
+
+ return (PVRSRV_OK);
+}
+
+static PVRSRV_ERROR SwapToDCSystem(IMG_HANDLE hDevice,
+ IMG_HANDLE hSwapChain)
+{
+ if(!hDevice || !hSwapChain)
+ {
+ return (PVRSRV_ERROR_INVALID_PARAMS);
+ }
+
+
+ return (PVRSRV_OK);
+}
+
+static MRST_BOOL MRSTLFBVSyncIHandler(MRSTLFB_DEVINFO *psDevInfo)
+{
+ MRST_BOOL bStatus = MRST_TRUE;
+ MRSTLFB_VSYNC_FLIP_ITEM *psFlipItem;
+ unsigned long ulMaxIndex;
+ unsigned long ulLockFlags;
+ MRSTLFB_SWAPCHAIN *psSwapChain;
+
+ spin_lock_irqsave(&psDevInfo->sSwapChainLock, ulLockFlags);
+
+
+ psSwapChain = psDevInfo->psCurrentSwapChain;
+ if (psSwapChain == NULL)
+ {
+ goto ExitUnlock;
+ }
+
+
+ if (psDevInfo->bFlushCommands || psDevInfo->bSuspended || psDevInfo->bLeaveVT)
+ {
+ goto ExitUnlock;
+ }
+
+ psFlipItem = &psSwapChain->psVSyncFlips[psSwapChain->ulRemoveIndex];
+ ulMaxIndex = psSwapChain->ulSwapChainLength - 1;
+
+ while(psFlipItem->bValid)
+ {
+
+ if(psFlipItem->bFlipped)
+ {
+
+ if(!psFlipItem->bCmdCompleted)
+ {
+
+ MRST_BOOL bScheduleMISR;
+
+ bScheduleMISR = MRST_TRUE;
+
+
+ psSwapChain->psPVRJTable->pfnPVRSRVCmdComplete((IMG_HANDLE)psFlipItem->hCmdComplete, bScheduleMISR);
+
+
+ psFlipItem->bCmdCompleted = MRST_TRUE;
+ }
+
+
+ /* DGA: fix wrap bug with unsigned int */
+ if (psFlipItem->ulSwapInterval-- <= 1)
+ {
+
+ psSwapChain->ulRemoveIndex++;
+
+ if(psSwapChain->ulRemoveIndex > ulMaxIndex)
+ {
+ psSwapChain->ulRemoveIndex = 0;
+ }
+
+
+ psFlipItem->bCmdCompleted = MRST_FALSE;
+ psFlipItem->bFlipped = MRST_FALSE;
+
+
+ psFlipItem->bValid = MRST_FALSE;
+ }
+ else
+ {
+
+ break;
+ }
+ }
+ else
+ {
+
+ DRMLFBFlipBuffer(psDevInfo, psSwapChain, psFlipItem->psBuffer);
+
+
+ psFlipItem->bFlipped = MRST_TRUE;
+
+
+ break;
+ }
+
+
+ psFlipItem = &psSwapChain->psVSyncFlips[psSwapChain->ulRemoveIndex];
+ }
+
+ExitUnlock:
+ spin_unlock_irqrestore(&psDevInfo->sSwapChainLock, ulLockFlags);
+
+ return bStatus;
+}
+
+#if defined(MRST_USING_INTERRUPTS)
+static int
+MRSTLFBVSyncISR(struct drm_device *psDrmDevice, int iPipe)
+{
+ MRSTLFB_DEVINFO *psDevInfo = GetAnchorPtr();
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *)psDrmDevice->dev_private;
+
+ /* DGA: lets update the DRM device structure's swapchain flag */
+ dev_priv->swap_chain_flag = (int)psDevInfo->psCurrentSwapChain;
+ MRSTLFBVSyncIHandler(psDevInfo);
+
+
+ return 0;
+}
+#endif
+
+#if 0 /* defined(MRST_USING_INTERRUPTS) */
+static IMG_BOOL
+MRSTLFBISRHandler(IMG_VOID* pvDevInfo)
+{
+ MRSTLFB_DEVINFO *psDevInfo = (MRSTLFB_DEVINFO *)pvDevInfo;
+#if 0
+#ifdef MRST_USING_INTERRUPTS
+ MRSTLFB_SWAPCHAIN *psSwapChain;
+#endif
+#endif
+ unsigned long vdc_stat;
+ struct drm_psb_private *dev_priv;
+#if defined(SUPPORT_DRI_DRM)
+ uint32_t pipea_stat = 0;
+#endif
+
+ if (!ospm_power_is_hw_on(OSPM_DISPLAY_ISLAND)) {
+ DRM_ERROR("ERROR: interrupt arrived but Display HW is power off\n");
+ return IMG_FALSE;
+ }
+
+#if defined(SUPPORT_DRI_DRM)
+ dev_priv = (struct drm_psb_private *) psDevInfo->psDrmDevice->dev_private;
+
+ pipea_stat = PSB_RVDC32(PIPEASTAT);
+ //write back to clear all interrupt status bits and reset interrupts.
+ PSB_WVDC32(pipea_stat, PIPEASTAT);
+
+ vdc_stat = PSB_RVDC32(PSB_INT_IDENTITY_R);
+ vdc_stat &= dev_priv->vdc_irq_mask;
+ if (vdc_stat & _PSB_VSYNC_PIPEA_FLAG)
+ {
+ drm_handle_vblank(psDevInfo->psDrmDevice, 0);
+ }
+#endif
+
+/* Use drm_handle_vblank() as the VSync handler, otherwise kernel would panic if handle
+ * the VSync event again. */
+#if 0
+#ifdef MRST_USING_INTERRUPTS
+
+ psSwapChain = psDevInfo->psSwapChain;
+ vdc_stat = MRSTLFBVSyncReadReg(psDevInfo, PSB_INT_IDENTITY_R);
+
+ if (vdc_stat & _PSB_VSYNC_PIPEA_FLAG)
+ {
+ if(!psDevInfo->psSwapChain)
+ {
+ psSwapChain = psDevInfo->psSwapChain;
+ (void) MRSTLFBVSyncIHandler(psSwapChain);
+ }
+ }
+#endif
+#endif
+
+#if defined(SUPPORT_DRI_DRM)
+ vdc_stat = PSB_RVDC32(PSB_INT_IDENTITY_R);
+ vdc_stat &= dev_priv->vdc_irq_mask;
+ if (vdc_stat & _PSB_DPST_PIPEA_FLAG) {
+
+ /* Check for DPST related interrupts */
+ if((pipea_stat & PIPE_DPST_EVENT_STATUS) &&
+ (dev_priv->psb_dpst_state != NULL)) {
+ uint32_t pwm_reg = 0;
+ uint32_t hist_reg = 0;
+ u32 irqCtrl = 0;
+ struct dpst_guardband guardband_reg;
+ struct dpst_ie_histogram_control ie_hist_cont_reg;
+
+ hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
+
+ /* Determine if this is histogram or pwm interrupt */
+ if(hist_reg & HISTOGRAM_INT_CTRL_CLEAR) {
+ /* Notify UM of histogram interrupt */
+ psb_dpst_notify_change_um(DPST_EVENT_HIST_INTERRUPT,
+ dev_priv->psb_dpst_state);
+
+ /* disable dpst interrupts */
+ guardband_reg.data = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
+ guardband_reg.interrupt_enable = 0;
+ guardband_reg.interrupt_status = 1;
+ PSB_WVDC32(guardband_reg.data, HISTOGRAM_INT_CONTROL);
+
+ ie_hist_cont_reg.data = PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL);
+ ie_hist_cont_reg.ie_histogram_enable = 0;
+ PSB_WVDC32(ie_hist_cont_reg.data, HISTOGRAM_LOGIC_CONTROL);
+
+ irqCtrl = PSB_RVDC32(PIPEASTAT);
+ irqCtrl &= ~PIPE_DPST_EVENT_ENABLE;
+ PSB_WVDC32(irqCtrl, PIPEASTAT);
+ }
+ pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
+ if((pwm_reg & PWM_PHASEIN_INT_ENABLE) &&
+ !(pwm_reg & PWM_PHASEIN_ENABLE)) {
+ /* Notify UM of the phase complete */
+ psb_dpst_notify_change_um(DPST_EVENT_PHASE_COMPLETE,
+ dev_priv->psb_dpst_state);
+
+ /* Temporarily get phase mngr ready to generate
+ * another interrupt until this can be moved to
+ * user mode */
+ /* PSB_WVDC32(pwm_reg | 0x80010100 | PWM_PHASEIN_ENABLE,
+ PWM_CONTROL_LOGIC); */
+ }
+ }
+ }
+#endif
+ return IMG_TRUE;
+}
+#endif
+
+static IMG_BOOL ProcessFlip(IMG_HANDLE hCmdCookie,
+ IMG_UINT32 ui32DataSize,
+ IMG_VOID *pvData)
+{
+ DISPLAYCLASS_FLIP_COMMAND *psFlipCmd;
+ MRSTLFB_DEVINFO *psDevInfo;
+ MRSTLFB_BUFFER *psBuffer;
+ MRSTLFB_SWAPCHAIN *psSwapChain;
+#if defined(MRST_USING_INTERRUPTS)
+ MRSTLFB_VSYNC_FLIP_ITEM* psFlipItem;
+#endif
+ unsigned long ulLockFlags;
+
+
+ if(!hCmdCookie || !pvData)
+ {
+ return IMG_FALSE;
+ }
+
+
+ psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND*)pvData;
+
+ if (psFlipCmd == IMG_NULL || sizeof(DISPLAYCLASS_FLIP_COMMAND) != ui32DataSize)
+ {
+ return IMG_FALSE;
+ }
+
+
+ psDevInfo = (MRSTLFB_DEVINFO*)psFlipCmd->hExtDevice;
+
+ psBuffer = (MRSTLFB_BUFFER*)psFlipCmd->hExtBuffer;
+ psSwapChain = (MRSTLFB_SWAPCHAIN*) psFlipCmd->hExtSwapChain;
+
+ spin_lock_irqsave(&psDevInfo->sSwapChainLock, ulLockFlags);
+
+#if defined(MRST_USING_INTERRUPTS)
+
+ if(psFlipCmd->ui32SwapInterval == 0 || psDevInfo->bFlushCommands)
+ {
+#endif
+ DRMLFBFlipBuffer(psDevInfo, psSwapChain, psBuffer);
+
+
+
+ psSwapChain->psPVRJTable->pfnPVRSRVCmdComplete(hCmdCookie, IMG_TRUE);
+
+#if defined(MRST_USING_INTERRUPTS)
+ goto ExitTrueUnlock;
+ }
+
+ psFlipItem = &psSwapChain->psVSyncFlips[psSwapChain->ulInsertIndex];
+
+
+ if(psFlipItem->bValid == MRST_FALSE)
+ {
+ unsigned long ulMaxIndex = psSwapChain->ulSwapChainLength - 1;
+
+ if(psSwapChain->ulInsertIndex == psSwapChain->ulRemoveIndex)
+ {
+
+ DRMLFBFlipBuffer(psDevInfo, psSwapChain, psBuffer);
+
+ psFlipItem->bFlipped = MRST_TRUE;
+ }
+ else
+ {
+ psFlipItem->bFlipped = MRST_FALSE;
+ }
+
+ psFlipItem->hCmdComplete = (MRST_HANDLE)hCmdCookie;
+ psFlipItem->ulSwapInterval = (unsigned long)psFlipCmd->ui32SwapInterval;
+ psFlipItem->psBuffer = psBuffer;
+ psFlipItem->bValid = MRST_TRUE;
+
+ psSwapChain->ulInsertIndex++;
+ if(psSwapChain->ulInsertIndex > ulMaxIndex)
+ {
+ psSwapChain->ulInsertIndex = 0;
+ }
+
+ goto ExitTrueUnlock;
+ }
+
+ spin_unlock_irqrestore(&psDevInfo->sSwapChainLock, ulLockFlags);
+ return IMG_FALSE;
+
+ExitTrueUnlock:
+#endif
+ spin_unlock_irqrestore(&psDevInfo->sSwapChainLock, ulLockFlags);
+ return IMG_TRUE;
+}
+
+
+#if defined(PVR_MRST_FB_SET_PAR_ON_INIT)
+static void MRSTFBSetPar(struct fb_info *psLINFBInfo)
+{
+ console_lock();
+
+ if (psLINFBInfo->fbops->fb_set_par != NULL)
+ {
+ int res;
+
+ res = psLINFBInfo->fbops->fb_set_par(psLINFBInfo);
+ if (res != 0)
+ {
+ printk(KERN_WARNING DRIVER_PREFIX
+ ": fb_set_par failed: %d\n", res);
+
+ }
+ }
+ else
+ {
+ printk(KERN_WARNING DRIVER_PREFIX
+ ": fb_set_par not set - HW cursor may not work\n");
+ }
+
+ console_unlock();
+}
+#endif
+
+void MRSTLFBSuspend(void)
+{
+ MRSTLFB_DEVINFO *psDevInfo = GetAnchorPtr();
+ unsigned long ulLockFlags;
+
+ spin_lock_irqsave(&psDevInfo->sSwapChainLock, ulLockFlags);
+
+ if (!psDevInfo->bSuspended)
+ {
+#if !defined(PVR_MRST_STYLE_PM)
+ if(psDevInfo->ui32SwapChainNum != 0)
+ {
+ MRSTLFBDisableVSyncInterrupt(psDevInfo);
+ }
+#endif
+ psDevInfo->bSuspended = MRST_TRUE;
+ }
+
+ spin_unlock_irqrestore(&psDevInfo->sSwapChainLock, ulLockFlags);
+}
+
+void MRSTLFBResume(void)
+{
+ MRSTLFB_DEVINFO *psDevInfo = GetAnchorPtr();
+ unsigned long ulLockFlags;
+
+ spin_lock_irqsave(&psDevInfo->sSwapChainLock, ulLockFlags);
+
+ if (psDevInfo->bSuspended)
+ {
+#if !defined(PVR_MRST_STYLE_PM)
+ if(psDevInfo->ui32SwapChainNum != 0)
+ {
+ MRSTLFBEnableVSyncInterrupt(psDevInfo);
+ }
+#endif
+ psDevInfo->bSuspended = MRST_FALSE;
+
+ MRSTLFBRestoreLastFlip(psDevInfo);
+ }
+
+ spin_unlock_irqrestore(&psDevInfo->sSwapChainLock, ulLockFlags);
+
+#if !defined(PVR_MRST_STYLE_PM)
+ (void) UnblankDisplay(psDevInfo);
+#endif
+}
+
+#ifdef DRM_PVR_USE_INTEL_FB
+#include "mm.h"
+int MRSTLFBHandleChangeFB(struct drm_device* dev, struct psb_framebuffer *psbfb)
+{
+ MRSTLFB_DEVINFO *psDevInfo = GetAnchorPtr();
+ int i;
+ struct drm_psb_private * dev_priv = (struct drm_psb_private *)dev->dev_private;
+ struct psb_gtt * pg = dev_priv->pg;
+ LinuxMemArea *psLinuxMemArea;
+
+ if( !psDevInfo->sSystemBuffer.bIsContiguous )
+ MRSTLFBFreeKernelMem( psDevInfo->sSystemBuffer.uSysAddr.psNonCont );
+
+ psDevInfo->sDisplayFormat.pixelformat = (psbfb->base.depth == 16) ? PVRSRV_PIXEL_FORMAT_RGB565 : PVRSRV_PIXEL_FORMAT_ARGB8888;
+
+ psDevInfo->sDisplayDim.ui32ByteStride = psbfb->base.pitch;
+ psDevInfo->sDisplayDim.ui32Width = psbfb->base.width;
+ psDevInfo->sDisplayDim.ui32Height = psbfb->base.height;
+
+ psDevInfo->sSystemBuffer.ui32BufferSize = psbfb->size;
+
+ if (psbfb->pvrBO != NULL)
+ {
+ psDevInfo->sSystemBuffer.sCPUVAddr = psbfb->fbdev->screen_base;
+ psDevInfo->sSystemBuffer.sDevVAddr.uiAddr = psbfb->offset;
+ }
+ else
+ {
+ psDevInfo->sSystemBuffer.sCPUVAddr = pg->vram_addr;
+ psDevInfo->sSystemBuffer.sDevVAddr.uiAddr = 0;
+ }
+
+ psDevInfo->sSystemBuffer.bIsAllocated = MRST_FALSE;
+
+ if (psbfb->pvrBO != NULL)
+ {
+ psLinuxMemArea = (LinuxMemArea *)psbfb->pvrBO->sMemBlk.hOSMemHandle;
+ }
+
+ if ((psbfb->pvrBO == NULL) || (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_ALLOC_PAGES))
+ {
+ psDevInfo->sSystemBuffer.bIsContiguous = MRST_TRUE;
+ psDevInfo->sSystemBuffer.uSysAddr.sCont.uiAddr = pg->stolen_base;
+ } else {
+ struct page **page_list = psLinuxMemArea->uData.sPageList.pvPageList;
+
+ psDevInfo->sSystemBuffer.bIsContiguous = MRST_FALSE;
+ psDevInfo->sSystemBuffer.uSysAddr.psNonCont = MRSTLFBAllocKernelMem( sizeof( IMG_SYS_PHYADDR ) * (psbfb->size >> PAGE_SHIFT));
+
+ for (i = 0; i < psbfb->size >> PAGE_SHIFT; i++)
+ {
+ psDevInfo->sSystemBuffer.uSysAddr.psNonCont[i].uiAddr = page_to_pfn( page_list[i] ) << PAGE_SHIFT;
+ }
+ }
+
+ return 0;
+}
+
+#else
+
+int MRSTLFBHandleChangeFB(struct drm_device* dev, struct psb_framebuffer *psbfb)
+{
+ MRSTLFB_DEVINFO *psDevInfo = GetAnchorPtr();
+ int i;
+ struct drm_psb_private * dev_priv;
+ struct psb_gtt * pg;
+
+ if( !psDevInfo->sSystemBuffer.bIsContiguous )
+ MRSTLFBFreeKernelMem( psDevInfo->sSystemBuffer.uSysAddr.psNonCont );
+
+ dev_priv = (struct drm_psb_private *)dev->dev_private;
+ pg = dev_priv->pg;
+
+ psDevInfo->sDisplayFormat.pixelformat = (psbfb->base.depth == 16) ? PVRSRV_PIXEL_FORMAT_RGB565 : PVRSRV_PIXEL_FORMAT_ARGB8888;
+
+ psDevInfo->sDisplayDim.ui32ByteStride = psbfb->base.pitch;
+ psDevInfo->sDisplayDim.ui32Width = psbfb->base.width;
+ psDevInfo->sDisplayDim.ui32Height = psbfb->base.height;
+
+ psDevInfo->sSystemBuffer.ui32BufferSize = psbfb->size;
+ //psDevInfo->sSystemBuffer.sCPUVAddr = psbfb->pvKMAddr;
+ psDevInfo->sSystemBuffer.sCPUVAddr = pg->vram_addr;
+ //psDevInfo->sSystemBuffer.sDevVAddr.uiAddr = psbfb->offsetGTT;
+ psDevInfo->sSystemBuffer.sDevVAddr.uiAddr = 0;
+ psDevInfo->sSystemBuffer.bIsAllocated = IMG_FALSE;
+
+ if(psbfb->bo )
+ {
+
+ psDevInfo->sSystemBuffer.bIsContiguous = IMG_FALSE;
+ psDevInfo->sSystemBuffer.uSysAddr.psNonCont = MRSTLFBAllocKernelMem( sizeof( IMG_SYS_PHYADDR ) * psbfb->bo->ttm->num_pages);
+ for(i = 0;i < psbfb->bo->ttm->num_pages;++i)
+ {
+ /* struct page *p = ttm_tt_get_page( psbfb->bo->ttm, i);
+
+ psDevInfo->sSystemBuffer.uSysAddr.psNonCont[i].uiAddr = page_to_pfn(p) << PAGE_SHIFT;
+ */
+ }
+ }
+ else
+ {
+
+ //struct drm_device * psDrmDevice = psDevInfo->psDrmDevice;
+ //struct drm_psb_private * dev_priv = (struct drm_psb_private *)psDrmDevice->dev_private;
+ //struct psb_gtt * pg = dev_priv->pg;
+
+ psDevInfo->sSystemBuffer.bIsContiguous = IMG_TRUE;
+ psDevInfo->sSystemBuffer.uSysAddr.sCont.uiAddr = pg->stolen_base;
+ }
+
+ return 0;
+}
+#endif
+
+static int MRSTLFBFindMainPipe(struct drm_device *dev)
+{
+ struct drm_crtc *crtc;
+
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
+ {
+ if ( drm_helper_crtc_in_use(crtc) )
+ {
+ struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+ return psb_intel_crtc->pipe;
+ }
+ }
+
+ return 0;
+}
+
+#if 0
+static int DRMLFBLeaveVTHandler(struct drm_device *dev)
+{
+ MRSTLFB_DEVINFO *psDevInfo = GetAnchorPtr();
+ unsigned long ulLockFlags;
+
+ spin_lock_irqsave(&psDevInfo->sSwapChainLock, ulLockFlags);
+
+ if (!psDevInfo->bLeaveVT)
+ {
+ if(psDevInfo->psCurrentSwapChain != NULL)
+ {
+ FlushInternalVSyncQueue(psDevInfo->psCurrentSwapChain, MRST_TRUE);
+ SetFlushStateNoLock(psDevInfo, MRST_TRUE);
+ }
+
+ DRMLFBFlipBuffer(psDevInfo, NULL, &psDevInfo->sSystemBuffer);
+
+ psDevInfo->bLeaveVT = MRST_TRUE;
+ }
+
+ spin_unlock_irqrestore(&psDevInfo->sSwapChainLock, ulLockFlags);
+
+ return 0;
+}
+
+static int DRMLFBEnterVTHandler(struct drm_device *dev)
+{
+ MRSTLFB_DEVINFO *psDevInfo = GetAnchorPtr();
+ unsigned long ulLockFlags;
+
+ spin_lock_irqsave(&psDevInfo->sSwapChainLock, ulLockFlags);
+
+ if (psDevInfo->bLeaveVT)
+ {
+ if(psDevInfo->psCurrentSwapChain != NULL)
+ {
+ SetFlushStateNoLock(psDevInfo, MRST_FALSE);
+ }
+
+ psDevInfo->bLeaveVT = MRST_FALSE;
+
+ MRSTLFBRestoreLastFlip(psDevInfo);
+ }
+
+ spin_unlock_irqrestore(&psDevInfo->sSwapChainLock, ulLockFlags);
+
+ return 0;
+}
+#endif
+
+static MRST_ERROR InitDev(MRSTLFB_DEVINFO *psDevInfo)
+{
+ MRST_ERROR eError = MRST_ERROR_GENERIC;
+ struct fb_info *psLINFBInfo;
+ struct drm_device * psDrmDevice = psDevInfo->psDrmDevice;
+ struct drm_psb_private * psDrmPrivate = (struct drm_psb_private *)psDrmDevice->dev_private;
+ struct psb_fbdev * psPsbFBDev = (struct psb_fbdev *)psDrmPrivate->fbdev;
+ struct drm_framebuffer * psDrmFB;
+ struct psb_framebuffer *psbfb;
+
+
+ int hdisplay;
+ int vdisplay;
+ int i;
+ unsigned long FBSize;
+
+ psDrmFB = psPsbFBDev->psb_fb_helper.fb;
+ if(!psDrmFB) {
+ printk(KERN_INFO"%s:Cannot find drm FB", __FUNCTION__);
+ return eError;
+ }
+ psbfb = to_psb_fb(psDrmFB);
+
+ hdisplay = psDrmFB->width;
+ vdisplay = psDrmFB->height;
+ FBSize = psDrmFB->pitch * psDrmFB->height;
+
+ psLINFBInfo = (struct fb_info*)psPsbFBDev->psb_fb_helper.fbdev;
+
+#if defined(PVR_MRST_FB_SET_PAR_ON_INIT)
+ MRSTFBSetPar(psLINFBInfo);
+#endif
+
+
+ psDevInfo->sSystemBuffer.bIsContiguous = MRST_TRUE;
+ psDevInfo->sSystemBuffer.bIsAllocated = MRST_FALSE;
+
+ MRSTLFBHandleChangeFB(psDrmDevice, psbfb);
+
+
+ psDevInfo->sDisplayFormat.pixelformat = PVRSRV_PIXEL_FORMAT_ARGB8888;
+ psDevInfo->psLINFBInfo = psLINFBInfo;
+
+
+ psDevInfo->ui32MainPipe = MRSTLFBFindMainPipe(psDevInfo->psDrmDevice);
+
+ for(i = 0;i < MAX_SWAPCHAINS;++i)
+ {
+ psDevInfo->apsSwapChains[i] = NULL;
+ }
+
+
+
+
+ psDevInfo->pvRegs = psbfb_vdc_reg(psDevInfo->psDrmDevice);
+
+ if (psDevInfo->pvRegs == NULL)
+ {
+ eError = PVRSRV_ERROR_BAD_MAPPING;
+ printk(KERN_WARNING DRIVER_PREFIX ": Couldn't map registers needed for flipping\n");
+ return eError;
+ }
+
+ return MRST_OK;
+}
+
+static void DeInitDev(MRSTLFB_DEVINFO *psDevInfo)
+{
+
+}
+
+MRST_ERROR MRSTLFBInit(struct drm_device * dev)
+{
+ MRSTLFB_DEVINFO *psDevInfo;
+ //struct drm_psb_private *psDrmPriv = (struct drm_psb_private *)dev->dev_private;
+
+ psDevInfo = GetAnchorPtr();
+
+ if (psDevInfo == NULL)
+ {
+ PFN_CMD_PROC pfnCmdProcList[MRSTLFB_COMMAND_COUNT];
+ IMG_UINT32 aui32SyncCountList[MRSTLFB_COMMAND_COUNT][2];
+
+ psDevInfo = (MRSTLFB_DEVINFO *)MRSTLFBAllocKernelMem(sizeof(MRSTLFB_DEVINFO));
+
+ if(!psDevInfo)
+ {
+ return (MRST_ERROR_OUT_OF_MEMORY);
+ }
+
+
+ memset(psDevInfo, 0, sizeof(MRSTLFB_DEVINFO));
+
+
+ SetAnchorPtr((void*)psDevInfo);
+
+ psDevInfo->psDrmDevice = dev;
+ psDevInfo->ulRefCount = 0;
+
+
+ if(InitDev(psDevInfo) != MRST_OK)
+ {
+ return (MRST_ERROR_INIT_FAILURE);
+ }
+
+ if(MRSTLFBGetLibFuncAddr ("PVRGetDisplayClassJTable", &pfnGetPVRJTable) != MRST_OK)
+ {
+ return (MRST_ERROR_INIT_FAILURE);
+ }
+
+
+ if(!(*pfnGetPVRJTable)(&psDevInfo->sPVRJTable))
+ {
+ return (MRST_ERROR_INIT_FAILURE);
+ }
+
+
+ spin_lock_init(&psDevInfo->sSwapChainLock);
+
+ psDevInfo->psCurrentSwapChain = NULL;
+ psDevInfo->bFlushCommands = MRST_FALSE;
+
+ psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers = 3;
+ psDevInfo->sDisplayInfo.ui32MaxSwapChains = MAX_SWAPCHAINS;
+ psDevInfo->sDisplayInfo.ui32MaxSwapInterval = 3;
+ psDevInfo->sDisplayInfo.ui32MinSwapInterval = 0;
+
+ strncpy(psDevInfo->sDisplayInfo.szDisplayName, DISPLAY_DEVICE_NAME, MAX_DISPLAY_NAME_SIZE);
+
+
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
+ ": Maximum number of swap chain buffers: %u\n",
+ psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers));
+
+
+
+
+ psDevInfo->sDCJTable.ui32TableSize = sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE);
+ psDevInfo->sDCJTable.pfnOpenDCDevice = OpenDCDevice;
+ psDevInfo->sDCJTable.pfnCloseDCDevice = CloseDCDevice;
+ psDevInfo->sDCJTable.pfnEnumDCFormats = EnumDCFormats;
+ psDevInfo->sDCJTable.pfnEnumDCDims = EnumDCDims;
+ psDevInfo->sDCJTable.pfnGetDCSystemBuffer = GetDCSystemBuffer;
+ psDevInfo->sDCJTable.pfnGetDCInfo = GetDCInfo;
+ psDevInfo->sDCJTable.pfnGetBufferAddr = GetDCBufferAddr;
+ psDevInfo->sDCJTable.pfnCreateDCSwapChain = CreateDCSwapChain;
+ psDevInfo->sDCJTable.pfnDestroyDCSwapChain = DestroyDCSwapChain;
+ psDevInfo->sDCJTable.pfnSetDCDstRect = SetDCDstRect;
+ psDevInfo->sDCJTable.pfnSetDCSrcRect = SetDCSrcRect;
+ psDevInfo->sDCJTable.pfnSetDCDstColourKey = SetDCDstColourKey;
+ psDevInfo->sDCJTable.pfnSetDCSrcColourKey = SetDCSrcColourKey;
+ psDevInfo->sDCJTable.pfnGetDCBuffers = GetDCBuffers;
+ psDevInfo->sDCJTable.pfnSwapToDCBuffer = SwapToDCBuffer;
+ psDevInfo->sDCJTable.pfnSwapToDCSystem = SwapToDCSystem;
+ psDevInfo->sDCJTable.pfnSetDCState = SetDCState;
+
+
+ if(psDevInfo->sPVRJTable.pfnPVRSRVRegisterDCDevice (
+ &psDevInfo->sDCJTable,
+ &psDevInfo->uiDeviceID ) != PVRSRV_OK)
+ {
+ return (MRST_ERROR_DEVICE_REGISTER_FAILED);
+ }
+
+ printk("Device ID: %d\n", (int)psDevInfo->uiDeviceID);
+
+#if 0
+#if defined (SYS_USING_INTERRUPTS)
+ if (psDevInfo->sPVRJTable.pfnPVRSRVRegisterSystemISRHandler(MRSTLFBISRHandler,
+ psDevInfo,
+ 0,
+ (IMG_UINT32)psDevInfo->uiDeviceID) != PVRSRV_OK)
+ {
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX "ISR Installation failed\n"));
+ return (MRST_ERROR_INIT_FAILURE);
+ }
+#endif
+
+ if (psDevInfo->sPVRJTable.pfnPVRSRVRegisterPowerDevice((IMG_UINT32)psDevInfo->uiDeviceID,
+ MRSTLFBPrePowerState, MRSTLFBPostPowerState,
+ IMG_NULL, IMG_NULL,
+ psDevInfo,
+ PVRSRV_DEV_POWER_STATE_ON,
+ PVRSRV_DEV_POWER_STATE_ON) != PVRSRV_OK)
+ {
+ return (MRST_ERROR_INIT_FAILURE);
+ }
+#endif
+
+#if defined (MRST_USING_INTERRUPTS)
+
+ if(MRSTLFBInstallVSyncISR(psDevInfo,MRSTLFBVSyncISR) != MRST_OK)
+ {
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX "ISR Installation failed\n"));
+ return (MRST_ERROR_INIT_FAILURE);
+ }
+#endif
+
+
+ pfnCmdProcList[DC_FLIP_COMMAND] = ProcessFlip;
+
+
+ aui32SyncCountList[DC_FLIP_COMMAND][0] = 0;
+ aui32SyncCountList[DC_FLIP_COMMAND][1] = 2;
+
+
+ if (psDevInfo->sPVRJTable.pfnPVRSRVRegisterCmdProcList (psDevInfo->uiDeviceID,
+ &pfnCmdProcList[0],
+ aui32SyncCountList,
+ MRSTLFB_COMMAND_COUNT) != PVRSRV_OK)
+ {
+ printk(KERN_WARNING DRIVER_PREFIX ": Can't register callback\n");
+ return (MRST_ERROR_CANT_REGISTER_CALLBACK);
+ }
+
+
+ }
+
+
+ //psDrmPriv->psb_change_fb_handler = MRSTLFBHandleChangeFB;
+
+ //psDrmPriv->psb_leave_vt_handler = DRMLFBLeaveVTHandler;
+ //psDrmPriv->psb_enter_vt_handler = DRMLFBEnterVTHandler;
+
+ psDevInfo->ulRefCount++;
+
+
+ return (MRST_OK);
+}
+
+MRST_ERROR MRSTLFBDeinit(void)
+{
+ MRSTLFB_DEVINFO *psDevInfo, *psDevFirst;
+
+ psDevFirst = GetAnchorPtr();
+ psDevInfo = psDevFirst;
+
+
+ if (psDevInfo == NULL)
+ {
+ return (MRST_ERROR_GENERIC);
+ }
+
+
+ psDevInfo->ulRefCount--;
+
+ psDevInfo->psDrmDevice = NULL;
+ if (psDevInfo->ulRefCount == 0)
+ {
+
+ PVRSRV_DC_DISP2SRV_KMJTABLE *psJTable = &psDevInfo->sPVRJTable;
+
+ if (psDevInfo->sPVRJTable.pfnPVRSRVRemoveCmdProcList (psDevInfo->uiDeviceID, MRSTLFB_COMMAND_COUNT) != PVRSRV_OK)
+ {
+ return (MRST_ERROR_GENERIC);
+ }
+
+ if (psDevInfo->sPVRJTable.pfnPVRSRVRegisterPowerDevice((IMG_UINT32)psDevInfo->uiDeviceID,
+ IMG_NULL, IMG_NULL,
+ IMG_NULL, IMG_NULL, IMG_NULL,
+ PVRSRV_DEV_POWER_STATE_ON,
+ PVRSRV_DEV_POWER_STATE_ON) != PVRSRV_OK)
+ {
+ return (MRST_ERROR_GENERIC);
+ }
+
+#if 0 /* defined (SYS_USING_INTERRUPTS) */
+ if (psDevInfo->sPVRJTable.pfnPVRSRVRegisterSystemISRHandler(IMG_NULL, IMG_NULL, 0,
+ (IMG_UINT32)psDevInfo->uiDeviceID) != PVRSRV_OK)
+ {
+ return (MRST_ERROR_GENERIC);
+ }
+#endif
+
+#if defined (MRST_USING_INTERRUPTS)
+
+ if(MRSTLFBUninstallVSyncISR(psDevInfo) != MRST_OK)
+ {
+ return (MRST_ERROR_GENERIC);
+ }
+#endif
+
+ if (psJTable->pfnPVRSRVRemoveDCDevice(psDevInfo->uiDeviceID) != PVRSRV_OK)
+ {
+ return (MRST_ERROR_GENERIC);
+ }
+
+ DeInitDev(psDevInfo);
+
+
+ MRSTLFBFreeKernelMem(psDevInfo);
+ }
+
+
+ SetAnchorPtr(NULL);
+
+
+ return (MRST_OK);
+}
+
+MRST_ERROR MRSTLFBAllocBuffer(struct MRSTLFB_DEVINFO_TAG *psDevInfo, IMG_UINT32 ui32Size, MRSTLFB_BUFFER **ppBuffer)
+{
+ IMG_VOID *pvBuf;
+ IMG_UINT32 ulPagesNumber;
+ IMG_UINT32 ulCounter;
+ int i;
+
+ pvBuf = __vmalloc( ui32Size, GFP_KERNEL | __GFP_HIGHMEM, __pgprot((pgprot_val(PAGE_KERNEL ) & ~_PAGE_CACHE_MASK) | _PAGE_CACHE_WC) );
+ if( pvBuf == NULL )
+ {
+ return MRST_ERROR_OUT_OF_MEMORY;
+ }
+
+ ulPagesNumber = (ui32Size + PAGE_SIZE -1) / PAGE_SIZE;
+
+ *ppBuffer = MRSTLFBAllocKernelMem( sizeof( MRSTLFB_BUFFER ) );
+ (*ppBuffer)->sCPUVAddr = pvBuf;
+ (*ppBuffer)->ui32BufferSize = ui32Size;
+ (*ppBuffer)->uSysAddr.psNonCont = MRSTLFBAllocKernelMem( sizeof( IMG_SYS_PHYADDR ) * ulPagesNumber);
+ (*ppBuffer)->bIsAllocated = MRST_TRUE;
+ (*ppBuffer)->bIsContiguous = MRST_FALSE;
+ (*ppBuffer)->ui32OwnerTaskID = task_tgid_nr(current);
+
+ i = 0;
+ for(ulCounter = 0; ulCounter < ui32Size; ulCounter += PAGE_SIZE)
+ {
+ (*ppBuffer)->uSysAddr.psNonCont[i++].uiAddr = vmalloc_to_pfn( pvBuf + ulCounter ) << PAGE_SHIFT;
+ }
+
+ psb_gtt_map_pvr_memory( psDevInfo->psDrmDevice,
+ (unsigned int)*ppBuffer,
+ (*ppBuffer)->ui32OwnerTaskID,
+ (IMG_CPU_PHYADDR*) (*ppBuffer)->uSysAddr.psNonCont,
+ ulPagesNumber,
+ &(*ppBuffer)->sDevVAddr.uiAddr );
+
+ (*ppBuffer)->sDevVAddr.uiAddr <<= PAGE_SHIFT;
+
+ return MRST_OK;
+}
+
+MRST_ERROR MRSTLFBFreeBuffer(struct MRSTLFB_DEVINFO_TAG *psDevInfo, MRSTLFB_BUFFER **ppBuffer)
+{
+ if( !(*ppBuffer)->bIsAllocated )
+ return MRST_ERROR_INVALID_PARAMS;
+
+ psb_gtt_unmap_pvr_memory( psDevInfo->psDrmDevice,
+ (unsigned int)*ppBuffer,
+ (*ppBuffer)->ui32OwnerTaskID);
+
+ vfree( (*ppBuffer)->sCPUVAddr );
+
+ MRSTLFBFreeKernelMem( (*ppBuffer)->uSysAddr.psNonCont );
+
+ MRSTLFBFreeKernelMem( *ppBuffer);
+
+ *ppBuffer = NULL;
+
+ return MRST_OK;
+}
+
+#if 0
+/*
+ * save_display_registers
+ *
+ * Description: We are going to suspend so save current display
+ * register state.
+ */
+static void save_display_registers(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ int i;
+
+ /* Display arbitration control + watermarks */
+ dev_priv->saveDSPARB = PSB_RVDC32(DSPARB);
+ dev_priv->saveDSPFW1 = PSB_RVDC32(DSPFW1);
+ dev_priv->saveDSPFW2 = PSB_RVDC32(DSPFW2);
+ dev_priv->saveDSPFW3 = PSB_RVDC32(DSPFW3);
+ dev_priv->saveDSPFW4 = PSB_RVDC32(DSPFW4);
+ dev_priv->saveDSPFW5 = PSB_RVDC32(DSPFW5);
+ dev_priv->saveDSPFW6 = PSB_RVDC32(DSPFW6);
+ dev_priv->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT);
+
+ /* Pipe & plane A info */
+ dev_priv->savePIPEACONF = PSB_RVDC32(PIPEACONF);
+ dev_priv->savePIPEASRC = PSB_RVDC32(PIPEASRC);
+ dev_priv->saveFPA0 = PSB_RVDC32(MRST_FPA0);
+ dev_priv->saveFPA1 = PSB_RVDC32(MRST_FPA1);
+ dev_priv->saveDPLL_A = PSB_RVDC32(MRST_DPLL_A);
+ dev_priv->saveHTOTAL_A = PSB_RVDC32(HTOTAL_A);
+ dev_priv->saveHBLANK_A = PSB_RVDC32(HBLANK_A);
+ dev_priv->saveHSYNC_A = PSB_RVDC32(HSYNC_A);
+ dev_priv->saveVTOTAL_A = PSB_RVDC32(VTOTAL_A);
+ dev_priv->saveVBLANK_A = PSB_RVDC32(VBLANK_A);
+ dev_priv->saveVSYNC_A = PSB_RVDC32(VSYNC_A);
+ dev_priv->saveBCLRPAT_A = PSB_RVDC32(BCLRPAT_A);
+ dev_priv->saveDSPACNTR = PSB_RVDC32(DSPACNTR);
+ dev_priv->saveDSPASTRIDE = PSB_RVDC32(DSPASTRIDE);
+ dev_priv->saveDSPAADDR = PSB_RVDC32(DSPABASE);
+ dev_priv->saveDSPASURF = PSB_RVDC32(DSPASURF);
+ dev_priv->saveDSPALINOFF = PSB_RVDC32(DSPALINOFF);
+ dev_priv->saveDSPATILEOFF = PSB_RVDC32(DSPATILEOFF);
+
+ /*save cursor regs*/
+ dev_priv->saveDSPACURSOR_CTRL = PSB_RVDC32(CURACNTR);
+ dev_priv->saveDSPACURSOR_BASE = PSB_RVDC32(CURABASE);
+ dev_priv->saveDSPACURSOR_POS = PSB_RVDC32(CURAPOS);
+
+ /*save palette (gamma) */
+ for (i = 0; i < 256; i++)
+ dev_priv->save_palette_a[i] = PSB_RVDC32(PALETTE_A + (i<<2));
+
+ /*save performance state*/
+ dev_priv->savePERF_MODE = PSB_RVDC32(MRST_PERF_MODE);
+
+ /* LVDS state */
+ dev_priv->savePP_CONTROL = PSB_RVDC32(PP_CONTROL);
+ dev_priv->savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS);
+ dev_priv->savePFIT_AUTO_RATIOS = PSB_RVDC32(PFIT_AUTO_RATIOS);
+ dev_priv->saveBLC_PWM_CTL = PSB_RVDC32(BLC_PWM_CTL);
+ dev_priv->saveBLC_PWM_CTL2 = PSB_RVDC32(BLC_PWM_CTL2);
+ dev_priv->saveLVDS = PSB_RVDC32(LVDS);
+ dev_priv->savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL);
+ dev_priv->savePP_ON_DELAYS = PSB_RVDC32(LVDSPP_ON);
+ dev_priv->savePP_OFF_DELAYS = PSB_RVDC32(LVDSPP_OFF);
+ dev_priv->savePP_DIVISOR = PSB_RVDC32(PP_CYCLE);
+
+ /* HW overlay */
+ dev_priv->saveOV_OVADD = PSB_RVDC32(OV_OVADD);
+ dev_priv->saveOV_OGAMC0 = PSB_RVDC32(OV_OGAMC0);
+ dev_priv->saveOV_OGAMC1 = PSB_RVDC32(OV_OGAMC1);
+ dev_priv->saveOV_OGAMC2 = PSB_RVDC32(OV_OGAMC2);
+ dev_priv->saveOV_OGAMC3 = PSB_RVDC32(OV_OGAMC3);
+ dev_priv->saveOV_OGAMC4 = PSB_RVDC32(OV_OGAMC4);
+ dev_priv->saveOV_OGAMC5 = PSB_RVDC32(OV_OGAMC5);
+
+ /* MIPI DSI */
+ dev_priv->saveMIPI = PSB_RVDC32(MIPI);
+ dev_priv->saveDEVICE_READY_REG = PSB_RVDC32(DEVICE_READY_REG);
+ dev_priv->saveINTR_EN_REG = PSB_RVDC32(INTR_EN_REG);
+ dev_priv->saveDSI_FUNC_PRG_REG = PSB_RVDC32(DSI_FUNC_PRG_REG);
+ dev_priv->saveHS_TX_TIMEOUT_REG = PSB_RVDC32(HS_TX_TIMEOUT_REG);
+ dev_priv->saveLP_RX_TIMEOUT_REG = PSB_RVDC32(LP_RX_TIMEOUT_REG);
+ dev_priv->saveTURN_AROUND_TIMEOUT_REG =
+ PSB_RVDC32(TURN_AROUND_TIMEOUT_REG);
+ dev_priv->saveDEVICE_RESET_REG = PSB_RVDC32(DEVICE_RESET_REG);
+ dev_priv->saveDPI_RESOLUTION_REG =
+ PSB_RVDC32(DPI_RESOLUTION_REG);
+ dev_priv->saveHORIZ_SYNC_PAD_COUNT_REG =
+ PSB_RVDC32(HORIZ_SYNC_PAD_COUNT_REG);
+ dev_priv->saveHORIZ_BACK_PORCH_COUNT_REG =
+ PSB_RVDC32(HORIZ_BACK_PORCH_COUNT_REG);
+ dev_priv->saveHORIZ_FRONT_PORCH_COUNT_REG =
+ PSB_RVDC32(HORIZ_FRONT_PORCH_COUNT_REG);
+ dev_priv->saveHORIZ_ACTIVE_AREA_COUNT_REG =
+ PSB_RVDC32(HORIZ_ACTIVE_AREA_COUNT_REG);
+ dev_priv->saveVERT_SYNC_PAD_COUNT_REG =
+ PSB_RVDC32(VERT_SYNC_PAD_COUNT_REG);
+ dev_priv->saveVERT_BACK_PORCH_COUNT_REG =
+ PSB_RVDC32(VERT_BACK_PORCH_COUNT_REG);
+ dev_priv->saveVERT_FRONT_PORCH_COUNT_REG =
+ PSB_RVDC32(VERT_FRONT_PORCH_COUNT_REG);
+ dev_priv->saveHIGH_LOW_SWITCH_COUNT_REG =
+ PSB_RVDC32(HIGH_LOW_SWITCH_COUNT_REG);
+ dev_priv->saveINIT_COUNT_REG = PSB_RVDC32(INIT_COUNT_REG);
+ dev_priv->saveMAX_RET_PAK_REG = PSB_RVDC32(MAX_RET_PAK_REG);
+ dev_priv->saveVIDEO_FMT_REG = PSB_RVDC32(VIDEO_FMT_REG);
+ dev_priv->saveEOT_DISABLE_REG = PSB_RVDC32(EOT_DISABLE_REG);
+ dev_priv->saveLP_BYTECLK_REG = PSB_RVDC32(LP_BYTECLK_REG);
+ dev_priv->saveHS_LS_DBI_ENABLE_REG =
+ PSB_RVDC32(HS_LS_DBI_ENABLE_REG);
+ dev_priv->saveTXCLKESC_REG = PSB_RVDC32(TXCLKESC_REG);
+ dev_priv->saveDPHY_PARAM_REG = PSB_RVDC32(DPHY_PARAM_REG);
+ dev_priv->saveMIPI_CONTROL_REG = PSB_RVDC32(MIPI_CONTROL_REG);
+
+ /* DPST registers */
+ dev_priv->saveHISTOGRAM_INT_CONTROL_REG = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
+ dev_priv->saveHISTOGRAM_LOGIC_CONTROL_REG = PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL);
+}
+
+
+/*
+ * restore_display_registers
+ *
+ * Description: We are going to resume so restore display register state.
+ */
+static void restore_display_registers(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ unsigned long i, pp_stat;
+
+ /* Display arbitration + watermarks */
+ PSB_WVDC32(dev_priv->saveDSPARB, DSPARB);
+ PSB_WVDC32(dev_priv->saveDSPFW1, DSPFW1);
+ PSB_WVDC32(dev_priv->saveDSPFW2, DSPFW2);
+ PSB_WVDC32(dev_priv->saveDSPFW3, DSPFW3);
+ PSB_WVDC32(dev_priv->saveDSPFW4, DSPFW4);
+ PSB_WVDC32(dev_priv->saveDSPFW5, DSPFW5);
+ PSB_WVDC32(dev_priv->saveDSPFW6, DSPFW6);
+ PSB_WVDC32(dev_priv->saveCHICKENBIT, DSPCHICKENBIT);
+
+ /*make sure VGA plane is off. it initializes to on after reset!*/
+ PSB_WVDC32(0x80000000, VGACNTRL);
+
+ /* set the plls */
+ PSB_WVDC32(dev_priv->saveFPA0, MRST_FPA0);
+ PSB_WVDC32(dev_priv->saveFPA1, MRST_FPA1);
+ /* Actually enable it */
+ PSB_WVDC32(dev_priv->saveDPLL_A, MRST_DPLL_A);
+ DRM_UDELAY(150);
+
+ /* Restore mode */
+ PSB_WVDC32(dev_priv->saveHTOTAL_A, HTOTAL_A);
+ PSB_WVDC32(dev_priv->saveHBLANK_A, HBLANK_A);
+ PSB_WVDC32(dev_priv->saveHSYNC_A, HSYNC_A);
+ PSB_WVDC32(dev_priv->saveVTOTAL_A, VTOTAL_A);
+ PSB_WVDC32(dev_priv->saveVBLANK_A, VBLANK_A);
+ PSB_WVDC32(dev_priv->saveVSYNC_A, VSYNC_A);
+ PSB_WVDC32(dev_priv->savePIPEASRC, PIPEASRC);
+ PSB_WVDC32(dev_priv->saveBCLRPAT_A, BCLRPAT_A);
+
+ /*restore performance mode*/
+ PSB_WVDC32(dev_priv->savePERF_MODE, MRST_PERF_MODE);
+
+ /*enable the pipe*/
+ if (dev_priv->iLVDS_enable)
+ PSB_WVDC32(dev_priv->savePIPEACONF, PIPEACONF);
+
+ /* set up MIPI */
+ PSB_WVDC32(dev_priv->saveINTR_EN_REG, INTR_EN_REG);
+ PSB_WVDC32(dev_priv->saveDSI_FUNC_PRG_REG, DSI_FUNC_PRG_REG);
+ PSB_WVDC32(dev_priv->saveHS_TX_TIMEOUT_REG, HS_TX_TIMEOUT_REG);
+ PSB_WVDC32(dev_priv->saveLP_RX_TIMEOUT_REG, LP_RX_TIMEOUT_REG);
+ PSB_WVDC32(dev_priv->saveTURN_AROUND_TIMEOUT_REG,
+ TURN_AROUND_TIMEOUT_REG);
+ PSB_WVDC32(dev_priv->saveDEVICE_RESET_REG, DEVICE_RESET_REG);
+ PSB_WVDC32(dev_priv->saveDPI_RESOLUTION_REG,
+ DPI_RESOLUTION_REG);
+ PSB_WVDC32(dev_priv->saveHORIZ_SYNC_PAD_COUNT_REG,
+ HORIZ_SYNC_PAD_COUNT_REG);
+ PSB_WVDC32(dev_priv->saveHORIZ_BACK_PORCH_COUNT_REG,
+ HORIZ_BACK_PORCH_COUNT_REG);
+ PSB_WVDC32(dev_priv->saveHORIZ_FRONT_PORCH_COUNT_REG,
+ HORIZ_FRONT_PORCH_COUNT_REG);
+ PSB_WVDC32(dev_priv->saveHORIZ_ACTIVE_AREA_COUNT_REG,
+ HORIZ_ACTIVE_AREA_COUNT_REG);
+ PSB_WVDC32(dev_priv->saveVERT_SYNC_PAD_COUNT_REG,
+ VERT_SYNC_PAD_COUNT_REG);
+ PSB_WVDC32(dev_priv->saveVERT_BACK_PORCH_COUNT_REG,
+ VERT_BACK_PORCH_COUNT_REG);
+ PSB_WVDC32(dev_priv->saveVERT_FRONT_PORCH_COUNT_REG,
+ VERT_FRONT_PORCH_COUNT_REG);
+ PSB_WVDC32(dev_priv->saveHIGH_LOW_SWITCH_COUNT_REG,
+ HIGH_LOW_SWITCH_COUNT_REG);
+ PSB_WVDC32(dev_priv->saveINIT_COUNT_REG, INIT_COUNT_REG);
+ PSB_WVDC32(dev_priv->saveMAX_RET_PAK_REG, MAX_RET_PAK_REG);
+ PSB_WVDC32(dev_priv->saveVIDEO_FMT_REG, VIDEO_FMT_REG);
+ PSB_WVDC32(dev_priv->saveEOT_DISABLE_REG, EOT_DISABLE_REG);
+ PSB_WVDC32(dev_priv->saveLP_BYTECLK_REG, LP_BYTECLK_REG);
+ PSB_WVDC32(dev_priv->saveHS_LS_DBI_ENABLE_REG,
+ HS_LS_DBI_ENABLE_REG);
+ PSB_WVDC32(dev_priv->saveTXCLKESC_REG, TXCLKESC_REG);
+ PSB_WVDC32(dev_priv->saveDPHY_PARAM_REG, DPHY_PARAM_REG);
+ PSB_WVDC32(dev_priv->saveMIPI_CONTROL_REG, MIPI_CONTROL_REG);
+
+ /*set up the plane*/
+ PSB_WVDC32(dev_priv->saveDSPALINOFF, DSPALINOFF);
+ PSB_WVDC32(dev_priv->saveDSPASTRIDE, DSPASTRIDE);
+ PSB_WVDC32(dev_priv->saveDSPATILEOFF, DSPATILEOFF);
+
+ /* Enable the plane */
+ PSB_WVDC32(dev_priv->saveDSPACNTR, DSPACNTR);
+ PSB_WVDC32(dev_priv->saveDSPASURF, DSPASURF);
+
+ /*Enable Cursor A*/
+ PSB_WVDC32(dev_priv->saveDSPACURSOR_CTRL, CURACNTR);
+ PSB_WVDC32(dev_priv->saveDSPACURSOR_POS, CURAPOS);
+ PSB_WVDC32(dev_priv->saveDSPACURSOR_BASE, CURABASE);
+
+ /* restore palette (gamma) */
+ /*DRM_UDELAY(50000); */
+ for (i = 0; i < 256; i++)
+ PSB_WVDC32(dev_priv->save_palette_a[i], PALETTE_A + (i<<2));
+
+ if (dev_priv->iLVDS_enable) {
+ PSB_WVDC32(dev_priv->saveBLC_PWM_CTL2, BLC_PWM_CTL2);
+ PSB_WVDC32(dev_priv->saveLVDS, LVDS); /*port 61180h*/
+ PSB_WVDC32(dev_priv->savePFIT_CONTROL, PFIT_CONTROL);
+ PSB_WVDC32(dev_priv->savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS);
+ PSB_WVDC32(dev_priv->savePFIT_AUTO_RATIOS, PFIT_AUTO_RATIOS);
+ PSB_WVDC32(dev_priv->saveBLC_PWM_CTL, BLC_PWM_CTL);
+ PSB_WVDC32(dev_priv->savePP_ON_DELAYS, LVDSPP_ON);
+ PSB_WVDC32(dev_priv->savePP_OFF_DELAYS, LVDSPP_OFF);
+ PSB_WVDC32(dev_priv->savePP_DIVISOR, PP_CYCLE);
+ PSB_WVDC32(dev_priv->savePP_CONTROL, PP_CONTROL);
+ } else { /* enable MIPI */
+ PSB_WVDC32(MIPI_PORT_EN | MIPI_BORDER_EN, MIPI); /*force on port*/
+ PSB_WVDC32(1, DEVICE_READY_REG);/* force on to re-program */
+ dev_priv->init_drvIC(dev);
+ PSB_WVDC32(dev_priv->saveMIPI, MIPI); /*port 61190h*/
+ PSB_WVDC32(dev_priv->saveDEVICE_READY_REG, DEVICE_READY_REG);
+ if (dev_priv->saveDEVICE_READY_REG)
+ PSB_WVDC32(DPI_TURN_ON, DPI_CONTROL_REG);
+ PSB_WVDC32(dev_priv->savePIPEACONF, PIPEACONF);
+ PSB_WVDC32(dev_priv->saveBLC_PWM_CTL2, BLC_PWM_CTL2);
+ PSB_WVDC32(dev_priv->saveBLC_PWM_CTL, BLC_PWM_CTL);
+ }
+
+ /*wait for cycle delay*/
+ do {
+ pp_stat = PSB_RVDC32(PP_STATUS);
+ } while (pp_stat & 0x08000000);
+
+ DRM_UDELAY(999);
+ /*wait for panel power up*/
+ do {
+ pp_stat = PSB_RVDC32(PP_STATUS);
+ } while (pp_stat & 0x10000000);
+
+ /* restore HW overlay */
+ PSB_WVDC32(dev_priv->saveOV_OVADD, OV_OVADD);
+ PSB_WVDC32(dev_priv->saveOV_OGAMC0, OV_OGAMC0);
+ PSB_WVDC32(dev_priv->saveOV_OGAMC1, OV_OGAMC1);
+ PSB_WVDC32(dev_priv->saveOV_OGAMC2, OV_OGAMC2);
+ PSB_WVDC32(dev_priv->saveOV_OGAMC3, OV_OGAMC3);
+ PSB_WVDC32(dev_priv->saveOV_OGAMC4, OV_OGAMC4);
+ PSB_WVDC32(dev_priv->saveOV_OGAMC5, OV_OGAMC5);
+
+ /* DPST registers */
+ PSB_WVDC32(dev_priv->saveHISTOGRAM_INT_CONTROL_REG, HISTOGRAM_INT_CONTROL);
+ PSB_WVDC32(dev_priv->saveHISTOGRAM_LOGIC_CONTROL_REG, HISTOGRAM_LOGIC_CONTROL);
+}
+
+
+PVRSRV_ERROR MRSTLFBPrePowerState(IMG_HANDLE hDevHandle,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+ MRSTLFB_DEVINFO* psDevInfo = (MRSTLFB_DEVINFO *)hDevHandle;
+ struct drm_device* dev = psDevInfo->psDrmDevice;
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ int pp_stat;
+
+ if ((eNewPowerState == eCurrentPowerState) ||
+ (eNewPowerState == PVRSRV_DEV_POWER_STATE_ON))
+ return PVRSRV_OK;
+
+ if (!dev_priv->iLVDS_enable && dev_priv->dsi_prePowerState != NULL)
+ dev_priv->dsi_prePowerState(dev);
+
+ save_display_registers(dev);
+
+ if (dev_priv->iLVDS_enable) {
+ /*shutdown the panel*/
+ PSB_WVDC32(0, PP_CONTROL);
+
+ do {
+ pp_stat = PSB_RVDC32(PP_STATUS);
+ } while (pp_stat & 0x80000000);
+
+ /*turn off the plane*/
+ PSB_WVDC32(0x58000000, DSPACNTR);
+ PSB_WVDC32(0, DSPASURF);/*trigger the plane disable*/
+ msleep(4);
+
+ /*turn off pipe*/
+ PSB_WVDC32(0x0, PIPEACONF);
+ msleep(8);
+
+ /*turn off PLLs*/
+ PSB_WVDC32(0, MRST_DPLL_A);
+ }
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR MRSTLFBPostPowerState(IMG_HANDLE hDevHandle,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+ MRSTLFB_DEVINFO* psDevInfo = (MRSTLFB_DEVINFO *)hDevHandle;
+ struct drm_device* dev = psDevInfo->psDrmDevice;
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct psb_gtt *pg = dev_priv->pg;
+
+ if ((eNewPowerState == eCurrentPowerState) ||
+ (eNewPowerState == PVRSRV_DEV_POWER_STATE_OFF))
+ return PVRSRV_OK;
+
+ PSB_WVDC32(pg->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL);
+ pci_write_config_word(dev->pdev, PSB_GMCH_CTRL,
+ pg->gmch_ctrl | _PSB_GMCH_ENABLED);
+
+ /* Don't reinitialize the GTT as it is unnecessary. The gtt is
+ * stored in memory so it will automatically be restored. All
+ * we need to do is restore the PGETBL_CTL which we already do
+ * above.
+ */
+ /*psb_gtt_init(dev_priv->pg, 1);*/
+
+ restore_display_registers(dev);
+
+ if (!dev_priv->iLVDS_enable && dev_priv->dsi_postPowerState != NULL)
+ dev_priv->dsi_postPowerState(dev);
+
+ return PVRSRV_OK;
+}
+#endif
--- /dev/null
+/**********************************************************************
+ *
+ * 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/version.h>
+
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+
+#include <drm/drmP.h>
+
+#include <asm/io.h>
+
+#include "img_defs.h"
+#include "servicesext.h"
+#include "kerneldisplay.h"
+#include "pvrmodule.h"
+#include "pvr_drm.h"
+#include "mrstlfb.h"
+#include "kerneldisplay.h"
+#include "psb_irq.h"
+
+#include "psb_drv.h"
+
+#include "mdfld_dsi_dbi.h"
+#include "mdfld_dsi_dbi_dpu.h"
+
+#if !defined(SUPPORT_DRI_DRM)
+#error "SUPPORT_DRI_DRM must be set"
+#endif
+
+#define MAKESTRING(x) # x
+
+#if !defined(DISPLAY_CONTROLLER)
+#define DISPLAY_CONTROLLER pvrlfb
+#endif
+
+//#define MAKENAME_HELPER(x, y) x ## y
+//#define MAKENAME2(x, y) MAKENAME_HELPER(x, y)
+//#define MAKENAME(x) MAKENAME2(DISPLAY_CONTROLLER, x)
+
+#define unref__ __attribute__ ((unused))
+
+void *MRSTLFBAllocKernelMem(unsigned long ulSize)
+{
+ return kmalloc(ulSize, GFP_KERNEL);
+}
+
+void MRSTLFBFreeKernelMem(void *pvMem)
+{
+ kfree(pvMem);
+}
+
+
+MRST_ERROR MRSTLFBGetLibFuncAddr (char *szFunctionName, PFN_DC_GET_PVRJTABLE *ppfnFuncTable)
+{
+ if(strcmp("PVRGetDisplayClassJTable", szFunctionName) != 0)
+ {
+ return (MRST_ERROR_INVALID_PARAMS);
+ }
+
+
+ *ppfnFuncTable = PVRGetDisplayClassJTable;
+
+ return (MRST_OK);
+}
+
+static void MRSTLFBVSyncWriteReg(MRSTLFB_DEVINFO *psDevInfo, unsigned long ulOffset, unsigned long ulValue)
+{
+
+ void *pvRegAddr = (void *)(psDevInfo->pvRegs + ulOffset);
+ mb();
+ iowrite32(ulValue, pvRegAddr);
+}
+
+unsigned long MRSTLFBVSyncReadReg(MRSTLFB_DEVINFO * psDevinfo, unsigned long ulOffset)
+{
+ mb();
+ return ioread32((char *)psDevinfo->pvRegs + ulOffset);
+}
+
+void MRSTLFBEnableVSyncInterrupt(MRSTLFB_DEVINFO * psDevinfo)
+{
+#if defined(MRST_USING_INTERRUPTS)
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) psDevinfo->psDrmDevice->dev_private;
+ dev_priv->vblanksEnabledForFlips = true;
+ psb_enable_vblank(psDevinfo->psDrmDevice, 0);
+
+#endif
+}
+
+void MRSTLFBDisableVSyncInterrupt(MRSTLFB_DEVINFO * psDevinfo)
+{
+#if defined(MRST_USING_INTERRUPTS)
+ struct drm_device * dev = psDevinfo->psDrmDevice;
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) psDevinfo->psDrmDevice->dev_private;
+ dev_priv->vblanksEnabledForFlips = false;
+ //Only turn off if DRM isn't currently using vblanks, otherwise, leave on.
+ if (!dev->vblank_enabled[0])
+ psb_disable_vblank(psDevinfo->psDrmDevice, 0);
+#endif
+}
+
+#if defined(MRST_USING_INTERRUPTS)
+MRST_ERROR MRSTLFBInstallVSyncISR(MRSTLFB_DEVINFO *psDevInfo, MRSTLFB_VSYNC_ISR_PFN pVsyncHandler)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) psDevInfo->psDrmDevice->dev_private;
+ dev_priv->psb_vsync_handler = pVsyncHandler;
+ return (MRST_OK);
+}
+
+
+MRST_ERROR MRSTLFBUninstallVSyncISR(MRSTLFB_DEVINFO *psDevInfo)
+{
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) psDevInfo->psDrmDevice->dev_private;
+ dev_priv->psb_vsync_handler = NULL;
+ return (MRST_OK);
+}
+#endif
+
+
+void MRSTLFBFlipToSurface(MRSTLFB_DEVINFO *psDevInfo, unsigned long uiAddr)
+{
+ int dspbase = (psDevInfo->ui32MainPipe == 0 ? DSPABASE : DSPBBASE);
+ int dspsurf = (psDevInfo->ui32MainPipe == 0 ? DSPASURF : DSPBSURF);
+ int panel_type;
+
+ panel_type = is_panel_vid_or_cmd(psDevInfo->psDrmDevice);
+
+ if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, true))
+ {
+ dspsurf = DSPASURF;
+ MRSTLFBVSyncWriteReg(psDevInfo, dspsurf, uiAddr);
+#if defined(CONFIG_MDFD_DUAL_MIPI)
+ dspsurf = DSPCSURF;
+ MRSTLFBVSyncWriteReg(psDevInfo, dspsurf, uiAddr);
+#endif
+
+ if (panel_type == MDFLD_DSI_ENCODER_DBI) {
+#if defined(CONFIG_MDFLD_DSI_DPU)
+ mdfld_dbi_dpu_report_fullscreen_damage(psDevInfo->psDrmDevice);
+#elif defined(CONFIG_MDFLD_DSI_DSR)
+ /*if in DSR mode, exit it!*/
+ mdfld_dsi_dbi_exit_dsr (psDevInfo->psDrmDevice, MDFLD_DSR_2D_3D);
+#endif
+ }
+
+ dspsurf = DSPBSURF;
+ MRSTLFBVSyncWriteReg(psDevInfo, dspsurf, uiAddr);
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+ }
+}
+
+
+int PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Init)(struct drm_device unref__ *dev)
+{
+ if(MRSTLFBInit(dev) != MRST_OK)
+ {
+ printk(KERN_WARNING DRIVER_PREFIX ": MRSTLFB_Init: MRSTLFBInit failed\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+void PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Cleanup)(struct drm_device unref__ *dev)
+{
+ if(MRSTLFBDeinit() != MRST_OK)
+ {
+ printk(KERN_WARNING DRIVER_PREFIX "%s: can't deinit device\n", __FUNCTION__);
+ }
+}
+
+int PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Suspend)(struct drm_device unref__ *dev)
+{
+ MRSTLFBSuspend();
+
+ return 0;
+}
+
+int PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Resume)(struct drm_device unref__ *dev)
+{
+ MRSTLFBResume();
+
+ return 0;
+}
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#if !defined(__PVR_DRM_SHARED_H__)
+#define __PVR_DRM_SHARED_H__
+
+#if defined(SUPPORT_DRI_DRM)
+
+#define PVR_DRM_SRVKM_CMD 0x12
+#define PVR_DRM_DISP_CMD 0x13
+#define PVR_DRM_BC_CMD 0x14
+#define PVR_DRM_IS_MASTER_CMD 0x15
+#define PVR_DRM_UNPRIV_CMD 0x16
+#define PVR_DRM_DBGDRV_CMD 0x1E
+
+#define PVR_DRM_UNPRIV_INIT_SUCCESFUL 0
+#define PVR_DRM_UNPRIV_BUSID_TYPE 1
+#define PVR_DRM_UNPRIV_BUSID_FIELD 2
+
+#define PVR_DRM_BUS_TYPE_PCI 0
+
+#define PVR_DRM_PCI_DOMAIN 0
+#define PVR_DRM_PCI_BUS 1
+#define PVR_DRM_PCI_DEV 2
+#define PVR_DRM_PCI_FUNC 3
+
+#endif
+
+#endif
+
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#if !defined(__PVR_DRM_SHARED_H__)
+#define __PVR_DRM_SHARED_H__
+
+#if defined(SUPPORT_DRI_DRM)
+
+#define PVR_DRM_SRVKM_CMD 0x12
+#define PVR_DRM_DISP_CMD 0x13
+#define PVR_DRM_BC_CMD 0x14
+#define PVR_DRM_IS_MASTER_CMD 0x15
+#define PVR_DRM_UNPRIV_CMD 0x16
+#define PVR_DRM_DBGDRV_CMD 0x1E
+
+#define PVR_DRM_UNPRIV_INIT_SUCCESFUL 0
+#define PVR_DRM_UNPRIV_BUSID_TYPE 1
+#define PVR_DRM_UNPRIV_BUSID_FIELD 2
+
+#define PVR_DRM_BUS_TYPE_PCI 0
+
+#define PVR_DRM_PCI_DOMAIN 0
+#define PVR_DRM_PCI_BUS 1
+#define PVR_DRM_PCI_DEV 2
+#define PVR_DRM_PCI_FUNC 3
+
+#endif
+
+#endif
+
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#if !defined (__KERNELBUFFER_H__)
+#define __KERNELBUFFER_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+typedef PVRSRV_ERROR (*PFN_OPEN_BC_DEVICE)(IMG_UINT32, IMG_HANDLE*);
+typedef PVRSRV_ERROR (*PFN_CLOSE_BC_DEVICE)(IMG_UINT32, IMG_HANDLE);
+typedef PVRSRV_ERROR (*PFN_GET_BC_INFO)(IMG_HANDLE, BUFFER_INFO*);
+typedef PVRSRV_ERROR (*PFN_GET_BC_BUFFER)(IMG_HANDLE, IMG_UINT32, PVRSRV_SYNC_DATA*, IMG_HANDLE*);
+
+typedef struct PVRSRV_BC_SRV2BUFFER_KMJTABLE_TAG
+{
+ IMG_UINT32 ui32TableSize;
+ PFN_OPEN_BC_DEVICE pfnOpenBCDevice;
+ PFN_CLOSE_BC_DEVICE pfnCloseBCDevice;
+ PFN_GET_BC_INFO pfnGetBCInfo;
+ PFN_GET_BC_BUFFER pfnGetBCBuffer;
+ PFN_GET_BUFFER_ADDR pfnGetBufferAddr;
+
+} PVRSRV_BC_SRV2BUFFER_KMJTABLE;
+
+
+typedef PVRSRV_ERROR (*PFN_BC_REGISTER_BUFFER_DEV)(PVRSRV_BC_SRV2BUFFER_KMJTABLE*, IMG_UINT32*);
+typedef IMG_VOID (*PFN_BC_SCHEDULE_DEVICES)(IMG_VOID);
+typedef PVRSRV_ERROR (*PFN_BC_REMOVE_BUFFER_DEV)(IMG_UINT32);
+
+typedef struct PVRSRV_BC_BUFFER2SRV_KMJTABLE_TAG
+{
+ IMG_UINT32 ui32TableSize;
+ PFN_BC_REGISTER_BUFFER_DEV pfnPVRSRVRegisterBCDevice;
+ PFN_BC_SCHEDULE_DEVICES pfnPVRSRVScheduleDevices;
+ PFN_BC_REMOVE_BUFFER_DEV pfnPVRSRVRemoveBCDevice;
+
+} PVRSRV_BC_BUFFER2SRV_KMJTABLE, *PPVRSRV_BC_BUFFER2SRV_KMJTABLE;
+
+typedef IMG_BOOL (*PFN_BC_GET_PVRJTABLE) (PPVRSRV_BC_BUFFER2SRV_KMJTABLE);
+
+IMG_IMPORT IMG_BOOL PVRGetBufferClassJTable(PVRSRV_BC_BUFFER2SRV_KMJTABLE *psJTable);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#if !defined (__KERNELDISPLAY_H__)
+#define __KERNELDISPLAY_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+typedef PVRSRV_ERROR (*PFN_OPEN_DC_DEVICE)(IMG_UINT32, IMG_HANDLE*, PVRSRV_SYNC_DATA*);
+typedef PVRSRV_ERROR (*PFN_CLOSE_DC_DEVICE)(IMG_HANDLE);
+typedef PVRSRV_ERROR (*PFN_ENUM_DC_FORMATS)(IMG_HANDLE, IMG_UINT32*, DISPLAY_FORMAT*);
+typedef PVRSRV_ERROR (*PFN_ENUM_DC_DIMS)(IMG_HANDLE,
+ DISPLAY_FORMAT*,
+ IMG_UINT32*,
+ DISPLAY_DIMS*);
+typedef PVRSRV_ERROR (*PFN_GET_DC_SYSTEMBUFFER)(IMG_HANDLE, IMG_HANDLE*);
+typedef PVRSRV_ERROR (*PFN_GET_DC_INFO)(IMG_HANDLE, DISPLAY_INFO*);
+typedef PVRSRV_ERROR (*PFN_CREATE_DC_SWAPCHAIN)(IMG_HANDLE,
+ IMG_UINT32,
+ DISPLAY_SURF_ATTRIBUTES*,
+ DISPLAY_SURF_ATTRIBUTES*,
+ IMG_UINT32,
+ PVRSRV_SYNC_DATA**,
+ IMG_UINT32,
+ IMG_HANDLE*,
+ IMG_UINT32*);
+typedef PVRSRV_ERROR (*PFN_DESTROY_DC_SWAPCHAIN)(IMG_HANDLE,
+ IMG_HANDLE);
+typedef PVRSRV_ERROR (*PFN_SET_DC_DSTRECT)(IMG_HANDLE, IMG_HANDLE, IMG_RECT*);
+typedef PVRSRV_ERROR (*PFN_SET_DC_SRCRECT)(IMG_HANDLE, IMG_HANDLE, IMG_RECT*);
+typedef PVRSRV_ERROR (*PFN_SET_DC_DSTCK)(IMG_HANDLE, IMG_HANDLE, IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_SET_DC_SRCCK)(IMG_HANDLE, IMG_HANDLE, IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_GET_DC_BUFFERS)(IMG_HANDLE,
+ IMG_HANDLE,
+ IMG_UINT32*,
+ IMG_HANDLE*);
+typedef PVRSRV_ERROR (*PFN_SWAP_TO_DC_BUFFER)(IMG_HANDLE,
+ IMG_HANDLE,
+ IMG_UINT32,
+ IMG_HANDLE,
+ IMG_UINT32,
+ IMG_RECT*);
+typedef PVRSRV_ERROR (*PFN_SWAP_TO_DC_SYSTEM)(IMG_HANDLE, IMG_HANDLE);
+typedef IMG_VOID (*PFN_QUERY_SWAP_COMMAND_ID)(IMG_HANDLE, IMG_HANDLE, IMG_HANDLE, IMG_HANDLE, IMG_UINT16*, IMG_BOOL*);
+typedef IMG_VOID (*PFN_SET_DC_STATE)(IMG_HANDLE, IMG_UINT32);
+
+typedef struct PVRSRV_DC_SRV2DISP_KMJTABLE_TAG
+{
+ IMG_UINT32 ui32TableSize;
+ PFN_OPEN_DC_DEVICE pfnOpenDCDevice;
+ PFN_CLOSE_DC_DEVICE pfnCloseDCDevice;
+ PFN_ENUM_DC_FORMATS pfnEnumDCFormats;
+ PFN_ENUM_DC_DIMS pfnEnumDCDims;
+ PFN_GET_DC_SYSTEMBUFFER pfnGetDCSystemBuffer;
+ PFN_GET_DC_INFO pfnGetDCInfo;
+ PFN_GET_BUFFER_ADDR pfnGetBufferAddr;
+ PFN_CREATE_DC_SWAPCHAIN pfnCreateDCSwapChain;
+ PFN_DESTROY_DC_SWAPCHAIN pfnDestroyDCSwapChain;
+ PFN_SET_DC_DSTRECT pfnSetDCDstRect;
+ PFN_SET_DC_SRCRECT pfnSetDCSrcRect;
+ PFN_SET_DC_DSTCK pfnSetDCDstColourKey;
+ PFN_SET_DC_SRCCK pfnSetDCSrcColourKey;
+ PFN_GET_DC_BUFFERS pfnGetDCBuffers;
+ PFN_SWAP_TO_DC_BUFFER pfnSwapToDCBuffer;
+ PFN_SWAP_TO_DC_SYSTEM pfnSwapToDCSystem;
+ PFN_SET_DC_STATE pfnSetDCState;
+ PFN_QUERY_SWAP_COMMAND_ID pfnQuerySwapCommandID;
+
+} PVRSRV_DC_SRV2DISP_KMJTABLE;
+
+typedef IMG_BOOL (*PFN_ISR_HANDLER)(IMG_VOID*);
+
+typedef PVRSRV_ERROR (*PFN_DC_REGISTER_DISPLAY_DEV)(PVRSRV_DC_SRV2DISP_KMJTABLE*, IMG_UINT32*);
+typedef PVRSRV_ERROR (*PFN_DC_REMOVE_DISPLAY_DEV)(IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_DC_OEM_FUNCTION)(IMG_UINT32, IMG_VOID*, IMG_UINT32, IMG_VOID*, IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_DC_REGISTER_COMMANDPROCLIST)(IMG_UINT32, PPFN_CMD_PROC,IMG_UINT32[][2], IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_DC_REMOVE_COMMANDPROCLIST)(IMG_UINT32, IMG_UINT32);
+typedef IMG_VOID (*PFN_DC_CMD_COMPLETE)(IMG_HANDLE, IMG_BOOL);
+typedef PVRSRV_ERROR (*PFN_DC_REGISTER_SYS_ISR)(PFN_ISR_HANDLER, IMG_VOID*, IMG_UINT32, IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_DC_REGISTER_POWER)(IMG_UINT32, PFN_PRE_POWER, PFN_POST_POWER,
+ PFN_PRE_CLOCKSPEED_CHANGE, PFN_POST_CLOCKSPEED_CHANGE,
+ IMG_HANDLE, PVRSRV_DEV_POWER_STATE, PVRSRV_DEV_POWER_STATE);
+
+typedef struct PVRSRV_DC_DISP2SRV_KMJTABLE_TAG
+{
+ IMG_UINT32 ui32TableSize;
+ PFN_DC_REGISTER_DISPLAY_DEV pfnPVRSRVRegisterDCDevice;
+ PFN_DC_REMOVE_DISPLAY_DEV pfnPVRSRVRemoveDCDevice;
+ PFN_DC_OEM_FUNCTION pfnPVRSRVOEMFunction;
+ PFN_DC_REGISTER_COMMANDPROCLIST pfnPVRSRVRegisterCmdProcList;
+ PFN_DC_REMOVE_COMMANDPROCLIST pfnPVRSRVRemoveCmdProcList;
+ PFN_DC_CMD_COMPLETE pfnPVRSRVCmdComplete;
+ PFN_DC_REGISTER_SYS_ISR pfnPVRSRVRegisterSystemISRHandler;
+ PFN_DC_REGISTER_POWER pfnPVRSRVRegisterPowerDevice;
+ PFN_DC_CMD_COMPLETE pfnPVRSRVFreeCmdCompletePacket;
+} PVRSRV_DC_DISP2SRV_KMJTABLE, *PPVRSRV_DC_DISP2SRV_KMJTABLE;
+
+
+typedef struct DISPLAYCLASS_FLIP_COMMAND_TAG
+{
+
+ IMG_HANDLE hExtDevice;
+
+
+ IMG_HANDLE hExtSwapChain;
+
+
+ IMG_HANDLE hExtBuffer;
+
+
+ IMG_HANDLE hPrivateTag;
+
+
+ IMG_UINT32 ui32ClipRectCount;
+
+
+ IMG_RECT *psClipRect;
+
+
+ IMG_UINT32 ui32SwapInterval;
+
+} DISPLAYCLASS_FLIP_COMMAND;
+
+#define DC_FLIP_COMMAND 0
+
+#define DC_STATE_NO_FLUSH_COMMANDS 0
+#define DC_STATE_FLUSH_COMMANDS 1
+
+
+typedef IMG_BOOL (*PFN_DC_GET_PVRJTABLE)(PPVRSRV_DC_DISP2SRV_KMJTABLE);
+
+IMG_IMPORT IMG_BOOL PVRGetDisplayClassJTable(PVRSRV_DC_DISP2SRV_KMJTABLE *psJTable);
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef _SERVICES_PDUMP_H_
+#define _SERVICES_PDUMP_H_
+
+#define PDUMP_FLAGS_NEVER 0x08000000U
+#define PDUMP_FLAGS_LASTFRAME 0x10000000U
+#define PDUMP_FLAGS_RESETLFBUFFER 0x20000000U
+#define PDUMP_FLAGS_CONTINUOUS 0x40000000U
+#define PDUMP_FLAGS_PERSISTENT 0x80000000U
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef __PVR_BRIDGE_H__
+#define __PVR_BRIDGE_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "servicesint.h"
+
+#ifdef __linux__
+
+ #include <linux/ioctl.h>
+
+ #define PVRSRV_IOC_GID 'g'
+ #define PVRSRV_IO(INDEX) _IO(PVRSRV_IOC_GID, INDEX, PVRSRV_BRIDGE_PACKAGE)
+ #define PVRSRV_IOW(INDEX) _IOW(PVRSRV_IOC_GID, INDEX, PVRSRV_BRIDGE_PACKAGE)
+ #define PVRSRV_IOR(INDEX) _IOR(PVRSRV_IOC_GID, INDEX, PVRSRV_BRIDGE_PACKAGE)
+ #define PVRSRV_IOWR(INDEX) _IOWR(PVRSRV_IOC_GID, INDEX, PVRSRV_BRIDGE_PACKAGE)
+
+#else
+
+ #error Unknown platform: Cannot define ioctls
+
+ #define PVRSRV_IO(INDEX) (PVRSRV_IOC_GID + (INDEX))
+ #define PVRSRV_IOW(INDEX) (PVRSRV_IOC_GID + (INDEX))
+ #define PVRSRV_IOR(INDEX) (PVRSRV_IOC_GID + (INDEX))
+ #define PVRSRV_IOWR(INDEX) (PVRSRV_IOC_GID + (INDEX))
+
+ #define PVRSRV_BRIDGE_BASE PVRSRV_IOC_GID
+#endif
+
+
+#define PVRSRV_BRIDGE_CORE_CMD_FIRST 0UL
+#define PVRSRV_BRIDGE_ENUM_DEVICES PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_ACQUIRE_DEVICEINFO PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_RELEASE_DEVICEINFO PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_CREATE_DEVMEMCONTEXT PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_DESTROY_DEVMEMCONTEXT PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+4)
+#define PVRSRV_BRIDGE_GET_DEVMEM_HEAPINFO PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+5)
+#define PVRSRV_BRIDGE_ALLOC_DEVICEMEM PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+6)
+#define PVRSRV_BRIDGE_FREE_DEVICEMEM PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+7)
+#define PVRSRV_BRIDGE_GETFREE_DEVICEMEM PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+8)
+#define PVRSRV_BRIDGE_CREATE_COMMANDQUEUE PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+9)
+#define PVRSRV_BRIDGE_DESTROY_COMMANDQUEUE PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+10)
+#define PVRSRV_BRIDGE_MHANDLE_TO_MMAP_DATA PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+11)
+#define PVRSRV_BRIDGE_CONNECT_SERVICES PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+12)
+#define PVRSRV_BRIDGE_DISCONNECT_SERVICES PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+13)
+#define PVRSRV_BRIDGE_WRAP_DEVICE_MEM PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+14)
+#define PVRSRV_BRIDGE_GET_DEVICEMEMINFO PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+15)
+#define PVRSRV_BRIDGE_RESERVE_DEV_VIRTMEM PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+16)
+#define PVRSRV_BRIDGE_FREE_DEV_VIRTMEM PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+17)
+#define PVRSRV_BRIDGE_MAP_EXT_MEMORY PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+18)
+#define PVRSRV_BRIDGE_UNMAP_EXT_MEMORY PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+19)
+#define PVRSRV_BRIDGE_MAP_DEV_MEMORY PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+20)
+#define PVRSRV_BRIDGE_UNMAP_DEV_MEMORY PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+21)
+#define PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+22)
+#define PVRSRV_BRIDGE_UNMAP_DEVICECLASS_MEMORY PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+23)
+#define PVRSRV_BRIDGE_MAP_MEM_INFO_TO_USER PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+24)
+#define PVRSRV_BRIDGE_UNMAP_MEM_INFO_FROM_USER PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+25)
+#define PVRSRV_BRIDGE_EXPORT_DEVICEMEM PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+26)
+#define PVRSRV_BRIDGE_RELEASE_MMAP_DATA PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+27)
+#define PVRSRV_BRIDGE_CORE_CMD_LAST (PVRSRV_BRIDGE_CORE_CMD_FIRST+27)
+
+#define PVRSRV_BRIDGE_SIM_CMD_FIRST (PVRSRV_BRIDGE_CORE_CMD_LAST+1)
+#define PVRSRV_BRIDGE_PROCESS_SIMISR_EVENT PVRSRV_IOWR(PVRSRV_BRIDGE_SIM_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_REGISTER_SIM_PROCESS PVRSRV_IOWR(PVRSRV_BRIDGE_SIM_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_UNREGISTER_SIM_PROCESS PVRSRV_IOWR(PVRSRV_BRIDGE_SIM_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_SIM_CMD_LAST (PVRSRV_BRIDGE_SIM_CMD_FIRST+2)
+
+#define PVRSRV_BRIDGE_MAPPING_CMD_FIRST (PVRSRV_BRIDGE_SIM_CMD_LAST+1)
+#define PVRSRV_BRIDGE_MAPPHYSTOUSERSPACE PVRSRV_IOWR(PVRSRV_BRIDGE_MAPPING_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_UNMAPPHYSTOUSERSPACE PVRSRV_IOWR(PVRSRV_BRIDGE_MAPPING_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_GETPHYSTOUSERSPACEMAP PVRSRV_IOWR(PVRSRV_BRIDGE_MAPPING_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_MAPPING_CMD_LAST (PVRSRV_BRIDGE_MAPPING_CMD_FIRST+2)
+
+#define PVRSRV_BRIDGE_STATS_CMD_FIRST (PVRSRV_BRIDGE_MAPPING_CMD_LAST+1)
+#define PVRSRV_BRIDGE_GET_FB_STATS PVRSRV_IOWR(PVRSRV_BRIDGE_STATS_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_STATS_CMD_LAST (PVRSRV_BRIDGE_STATS_CMD_FIRST+0)
+
+#define PVRSRV_BRIDGE_MISC_CMD_FIRST (PVRSRV_BRIDGE_STATS_CMD_LAST+1)
+#define PVRSRV_BRIDGE_GET_MISC_INFO PVRSRV_IOWR(PVRSRV_BRIDGE_MISC_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_RELEASE_MISC_INFO PVRSRV_IOWR(PVRSRV_BRIDGE_MISC_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_MISC_CMD_LAST (PVRSRV_BRIDGE_MISC_CMD_FIRST+1)
+
+#if defined (SUPPORT_OVERLAY_ROTATE_BLIT)
+#define PVRSRV_BRIDGE_OVERLAY_CMD_FIRST (PVRSRV_BRIDGE_MISC_CMD_LAST+1)
+#define PVRSRV_BRIDGE_INIT_3D_OVL_BLT_RES PVRSRV_IOWR(PVRSRV_BRIDGE_OVERLAY_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_DEINIT_3D_OVL_BLT_RES PVRSRV_IOWR(PVRSRV_BRIDGE_OVERLAY_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_OVERLAY_CMD_LAST (PVRSRV_BRIDGE_OVERLAY_CMD_FIRST+1)
+#else
+#define PVRSRV_BRIDGE_OVERLAY_CMD_LAST PVRSRV_BRIDGE_MISC_CMD_LAST
+#endif
+
+#if defined(PDUMP)
+#define PVRSRV_BRIDGE_PDUMP_CMD_FIRST (PVRSRV_BRIDGE_OVERLAY_CMD_LAST+1)
+#define PVRSRV_BRIDGE_PDUMP_INIT PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_PDUMP_MEMPOL PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_PDUMP_DUMPMEM PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_PDUMP_REG PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_PDUMP_REGPOL PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+4)
+#define PVRSRV_BRIDGE_PDUMP_COMMENT PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+5)
+#define PVRSRV_BRIDGE_PDUMP_SETFRAME PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+6)
+#define PVRSRV_BRIDGE_PDUMP_ISCAPTURING PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+7)
+#define PVRSRV_BRIDGE_PDUMP_DUMPBITMAP PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+8)
+#define PVRSRV_BRIDGE_PDUMP_DUMPREADREG PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+9)
+#define PVRSRV_BRIDGE_PDUMP_SYNCPOL PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+10)
+#define PVRSRV_BRIDGE_PDUMP_DUMPSYNC PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+11)
+#define PVRSRV_BRIDGE_PDUMP_MEMPAGES PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+12)
+#define PVRSRV_BRIDGE_PDUMP_DRIVERINFO PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+13)
+#define PVRSRV_BRIDGE_PDUMP_DUMPPDDEVPADDR PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+15)
+#define PVRSRV_BRIDGE_PDUMP_CYCLE_COUNT_REG_READ PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+16)
+#define PVRSRV_BRIDGE_PDUMP_STARTINITPHASE PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+17)
+#define PVRSRV_BRIDGE_PDUMP_STOPINITPHASE PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+18)
+#define PVRSRV_BRIDGE_PDUMP_CMD_LAST (PVRSRV_BRIDGE_PDUMP_CMD_FIRST+18)
+#else
+#define PVRSRV_BRIDGE_PDUMP_CMD_LAST PVRSRV_BRIDGE_OVERLAY_CMD_LAST
+#endif
+
+#define PVRSRV_BRIDGE_OEM_CMD_FIRST (PVRSRV_BRIDGE_PDUMP_CMD_LAST+1)
+#define PVRSRV_BRIDGE_GET_OEMJTABLE PVRSRV_IOWR(PVRSRV_BRIDGE_OEM_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_OEM_CMD_LAST (PVRSRV_BRIDGE_OEM_CMD_FIRST+0)
+
+#define PVRSRV_BRIDGE_DEVCLASS_CMD_FIRST (PVRSRV_BRIDGE_OEM_CMD_LAST+1)
+#define PVRSRV_BRIDGE_ENUM_CLASS PVRSRV_IOWR(PVRSRV_BRIDGE_DEVCLASS_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_DEVCLASS_CMD_LAST (PVRSRV_BRIDGE_DEVCLASS_CMD_FIRST+0)
+
+#define PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST (PVRSRV_BRIDGE_DEVCLASS_CMD_LAST+1)
+#define PVRSRV_BRIDGE_OPEN_DISPCLASS_DEVICE PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_CLOSE_DISPCLASS_DEVICE PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_ENUM_DISPCLASS_FORMATS PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_ENUM_DISPCLASS_DIMS PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_GET_DISPCLASS_SYSBUFFER PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+4)
+#define PVRSRV_BRIDGE_GET_DISPCLASS_INFO PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+5)
+#define PVRSRV_BRIDGE_CREATE_DISPCLASS_SWAPCHAIN PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+6)
+#define PVRSRV_BRIDGE_DESTROY_DISPCLASS_SWAPCHAIN PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+7)
+#define PVRSRV_BRIDGE_SET_DISPCLASS_DSTRECT PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+8)
+#define PVRSRV_BRIDGE_SET_DISPCLASS_SRCRECT PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+9)
+#define PVRSRV_BRIDGE_SET_DISPCLASS_DSTCOLOURKEY PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+10)
+#define PVRSRV_BRIDGE_SET_DISPCLASS_SRCCOLOURKEY PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+11)
+#define PVRSRV_BRIDGE_GET_DISPCLASS_BUFFERS PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+12)
+#define PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_BUFFER PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+13)
+#define PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_SYSTEM PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+14)
+#define PVRSRV_BRIDGE_GET_DISPCLASS_FRONT_BUFFER PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+15)
+#define PVRSRV_BRIDGE_DISPCLASS_CMD_LAST (PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+15)
+
+
+#define PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST (PVRSRV_BRIDGE_DISPCLASS_CMD_LAST+1)
+#define PVRSRV_BRIDGE_OPEN_BUFFERCLASS_DEVICE PVRSRV_IOWR(PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_CLOSE_BUFFERCLASS_DEVICE PVRSRV_IOWR(PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_GET_BUFFERCLASS_INFO PVRSRV_IOWR(PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_GET_BUFFERCLASS_BUFFER PVRSRV_IOWR(PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_BUFCLASS_CMD_LAST (PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST+3)
+
+#define PVRSRV_BRIDGE_WRAP_CMD_FIRST (PVRSRV_BRIDGE_BUFCLASS_CMD_LAST+1)
+#define PVRSRV_BRIDGE_WRAP_EXT_MEMORY PVRSRV_IOWR(PVRSRV_BRIDGE_WRAP_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_UNWRAP_EXT_MEMORY PVRSRV_IOWR(PVRSRV_BRIDGE_WRAP_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_WRAP_CMD_LAST (PVRSRV_BRIDGE_WRAP_CMD_FIRST+1)
+
+#define PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST (PVRSRV_BRIDGE_WRAP_CMD_LAST+1)
+#define PVRSRV_BRIDGE_ALLOC_SHARED_SYS_MEM PVRSRV_IOWR(PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_FREE_SHARED_SYS_MEM PVRSRV_IOWR(PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_MAP_MEMINFO_MEM PVRSRV_IOWR(PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_UNMAP_MEMINFO_MEM PVRSRV_IOWR(PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_SHAREDMEM_CMD_LAST (PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST+3)
+
+#define PVRSRV_BRIDGE_SERVICES4_TMP_CMD_FIRST (PVRSRV_BRIDGE_SHAREDMEM_CMD_LAST+1)
+#define PVRSRV_BRIDGE_GETMMU_PD_DEVPADDR PVRSRV_IOWR(PVRSRV_BRIDGE_SERVICES4_TMP_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_SERVICES4_TMP_CMD_LAST (PVRSRV_BRIDGE_SERVICES4_TMP_CMD_FIRST+0)
+
+#define PVRSRV_BRIDGE_INITSRV_CMD_FIRST (PVRSRV_BRIDGE_SERVICES4_TMP_CMD_LAST+1)
+#define PVRSRV_BRIDGE_INITSRV_CONNECT PVRSRV_IOWR(PVRSRV_BRIDGE_INITSRV_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_INITSRV_DISCONNECT PVRSRV_IOWR(PVRSRV_BRIDGE_INITSRV_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_INITSRV_CMD_LAST (PVRSRV_BRIDGE_INITSRV_CMD_FIRST+1)
+
+#define PVRSRV_BRIDGE_EVENT_OBJECT_CMD_FIRST (PVRSRV_BRIDGE_INITSRV_CMD_LAST+1)
+#define PVRSRV_BRIDGE_EVENT_OBJECT_WAIT PVRSRV_IOWR(PVRSRV_BRIDGE_EVENT_OBJECT_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_EVENT_OBJECT_OPEN PVRSRV_IOWR(PVRSRV_BRIDGE_EVENT_OBJECT_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_EVENT_OBJECT_CLOSE PVRSRV_IOWR(PVRSRV_BRIDGE_EVENT_OBJECT_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_EVENT_OBJECT_CMD_LAST (PVRSRV_BRIDGE_EVENT_OBJECT_CMD_FIRST+2)
+
+#define PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST (PVRSRV_BRIDGE_EVENT_OBJECT_CMD_LAST+1)
+#define PVRSRV_BRIDGE_CREATE_SYNC_INFO_MOD_OBJ PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_DESTROY_SYNC_INFO_MOD_OBJ PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_MODIFY_PENDING_SYNC_OPS PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_MODIFY_COMPLETE_SYNC_OPS PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_SYNC_OPS_FLUSH_TO_MOD_OBJ PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+4)
+#define PVRSRV_BRIDGE_SYNC_OPS_FLUSH_TO_DELTA PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+5)
+#define PVRSRV_BRIDGE_ALLOC_SYNC_INFO PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+6)
+#define PVRSRV_BRIDGE_FREE_SYNC_INFO PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+7)
+#define PVRSRV_BRIDGE_SYNC_OPS_CMD_LAST (PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+7)
+
+#define PVRSRV_BRIDGE_LAST_NON_DEVICE_CMD (PVRSRV_BRIDGE_SYNC_OPS_CMD_LAST+1)
+
+
+#define PVRSRV_KERNEL_MODE_CLIENT 1
+
+typedef struct PVRSRV_BRIDGE_RETURN_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_VOID *pvData;
+
+}PVRSRV_BRIDGE_RETURN;
+
+
+typedef struct PVRSRV_BRIDGE_PACKAGE_TAG
+{
+ IMG_UINT32 ui32BridgeID;
+ IMG_UINT32 ui32Size;
+ IMG_VOID *pvParamIn;
+ IMG_UINT32 ui32InBufferSize;
+ IMG_VOID *pvParamOut;
+ IMG_UINT32 ui32OutBufferSize;
+
+ IMG_HANDLE hKernelServices;
+}PVRSRV_BRIDGE_PACKAGE;
+
+
+
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_CONNECT_SERVICES_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32Flags;
+} PVRSRV_BRIDGE_IN_CONNECT_SERVICES;
+
+typedef struct PVRSRV_BRIDGE_IN_ACQUIRE_DEVICEINFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 uiDevIndex;
+ PVRSRV_DEVICE_TYPE eDeviceType;
+
+} PVRSRV_BRIDGE_IN_ACQUIRE_DEVICEINFO;
+
+
+typedef struct PVRSRV_BRIDGE_IN_ENUMCLASS_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_DEVICE_CLASS sDeviceClass;
+} PVRSRV_BRIDGE_IN_ENUMCLASS;
+
+
+typedef struct PVRSRV_BRIDGE_IN_CLOSE_DISPCLASS_DEVICE_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDeviceKM;
+} PVRSRV_BRIDGE_IN_CLOSE_DISPCLASS_DEVICE;
+
+
+typedef struct PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_FORMATS_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDeviceKM;
+} PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_FORMATS;
+
+
+typedef struct PVRSRV_BRIDGE_IN_GET_DISPCLASS_SYSBUFFER_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDeviceKM;
+} PVRSRV_BRIDGE_IN_GET_DISPCLASS_SYSBUFFER;
+
+
+typedef struct PVRSRV_BRIDGE_IN_GET_DISPCLASS_INFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDeviceKM;
+} PVRSRV_BRIDGE_IN_GET_DISPCLASS_INFO;
+
+
+typedef struct PVRSRV_BRIDGE_IN_CLOSE_BUFFERCLASS_DEVICE_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDeviceKM;
+} PVRSRV_BRIDGE_IN_CLOSE_BUFFERCLASS_DEVICE;
+
+
+typedef struct PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_INFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDeviceKM;
+} PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_INFO;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_RELEASE_DEVICEINFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+
+} PVRSRV_BRIDGE_IN_RELEASE_DEVICEINFO;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_FREE_CLASSDEVICEINFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_DEVICE_CLASS DeviceClass;
+ IMG_VOID* pvDevInfo;
+
+}PVRSRV_BRIDGE_IN_FREE_CLASSDEVICEINFO;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_GET_DEVMEM_HEAPINFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_HANDLE hDevMemContext;
+
+}PVRSRV_BRIDGE_IN_GET_DEVMEM_HEAPINFO;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_CREATE_DEVMEMCONTEXT_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+
+}PVRSRV_BRIDGE_IN_CREATE_DEVMEMCONTEXT;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_DESTROY_DEVMEMCONTEXT_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_HANDLE hDevMemContext;
+
+}PVRSRV_BRIDGE_IN_DESTROY_DEVMEMCONTEXT;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_ALLOCDEVICEMEM_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_HANDLE hDevMemHeap;
+ IMG_UINT32 ui32Attribs;
+ IMG_SIZE_T ui32Size;
+ IMG_SIZE_T ui32Alignment;
+
+}PVRSRV_BRIDGE_IN_ALLOCDEVICEMEM;
+
+
+typedef struct PVRSRV_BRIDGE_IN_MAPMEMINFOTOUSER_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+}PVRSRV_BRIDGE_IN_MAPMEMINFOTOUSER;
+
+
+typedef struct PVRSRV_BRIDGE_IN_UNMAPMEMINFOFROMUSER_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ IMG_PVOID pvLinAddr;
+ IMG_HANDLE hMappingInfo;
+
+}PVRSRV_BRIDGE_IN_UNMAPMEMINFOFROMUSER;
+
+
+typedef struct PVRSRV_BRIDGE_IN_FREEDEVICEMEM_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+
+}PVRSRV_BRIDGE_IN_FREEDEVICEMEM;
+
+
+typedef struct PVRSRV_BRIDGE_IN_EXPORTDEVICEMEM_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+}PVRSRV_BRIDGE_IN_EXPORTDEVICEMEM;
+
+
+typedef struct PVRSRV_BRIDGE_IN_GETFREEDEVICEMEM_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32Flags;
+
+} PVRSRV_BRIDGE_IN_GETFREEDEVICEMEM;
+
+
+typedef struct PVRSRV_BRIDGE_IN_CREATECOMMANDQUEUE_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_SIZE_T ui32QueueSize;
+
+}PVRSRV_BRIDGE_IN_CREATECOMMANDQUEUE;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_DESTROYCOMMANDQUEUE_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ PVRSRV_QUEUE_INFO *psQueueInfo;
+
+}PVRSRV_BRIDGE_IN_DESTROYCOMMANDQUEUE;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_MHANDLE_TO_MMAP_DATA_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hMHandle;
+} PVRSRV_BRIDGE_IN_MHANDLE_TO_MMAP_DATA;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_RELEASE_MMAP_DATA_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hMHandle;
+} PVRSRV_BRIDGE_IN_RELEASE_MMAP_DATA;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_RESERVE_DEV_VIRTMEM_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevMemHeap;
+ IMG_DEV_VIRTADDR *psDevVAddr;
+ IMG_SIZE_T ui32Size;
+ IMG_SIZE_T ui32Alignment;
+
+}PVRSRV_BRIDGE_IN_RESERVE_DEV_VIRTMEM;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_CONNECT_SERVICES_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hKernelServices;
+}PVRSRV_BRIDGE_OUT_CONNECT_SERVICES;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_RESERVE_DEV_VIRTMEM_TAG
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+ PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+
+}PVRSRV_BRIDGE_OUT_RESERVE_DEV_VIRTMEM;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_FREE_DEV_VIRTMEM_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+ PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+
+}PVRSRV_BRIDGE_IN_FREE_DEV_VIRTMEM;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hKernelMemInfo;
+ IMG_HANDLE hDstDevMemHeap;
+
+}PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY_TAG
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_KERNEL_MEM_INFO *psDstKernelMemInfo;
+ PVRSRV_CLIENT_MEM_INFO sDstClientMemInfo;
+ PVRSRV_CLIENT_SYNC_INFO sDstClientSyncInfo;
+
+}PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_UNMAP_DEV_MEMORY_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+ PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+
+}PVRSRV_BRIDGE_IN_UNMAP_DEV_MEMORY;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_MAP_EXT_MEMORY_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ IMG_SYS_PHYADDR *psSysPAddr;
+ IMG_UINT32 ui32Flags;
+
+}PVRSRV_BRIDGE_IN_MAP_EXT_MEMORY;
+
+
+typedef struct PVRSRV_BRIDGE_IN_UNMAP_EXT_MEMORY_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+ PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+ IMG_UINT32 ui32Flags;
+
+}PVRSRV_BRIDGE_IN_UNMAP_EXT_MEMORY;
+
+
+typedef struct PVRSRV_BRIDGE_IN_MAP_DEVICECLASS_MEMORY_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDeviceClassBuffer;
+ IMG_HANDLE hDevMemContext;
+
+}PVRSRV_BRIDGE_IN_MAP_DEVICECLASS_MEMORY;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY_TAG
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+ PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ IMG_HANDLE hMappingInfo;
+
+}PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_UNMAP_DEVICECLASS_MEMORY_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+ PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+
+}PVRSRV_BRIDGE_IN_UNMAP_DEVICECLASS_MEMORY;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_MEMPOL_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ IMG_UINT32 ui32Offset;
+ IMG_UINT32 ui32Value;
+ IMG_UINT32 ui32Mask;
+ PDUMP_POLL_OPERATOR eOperator;
+ IMG_UINT32 ui32Flags;
+
+}PVRSRV_BRIDGE_IN_PDUMP_MEMPOL;
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_SYNCPOL_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+ IMG_BOOL bIsRead;
+ IMG_UINT32 ui32Value;
+ IMG_UINT32 ui32Mask;
+
+}PVRSRV_BRIDGE_IN_PDUMP_SYNCPOL;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_DUMPMEM_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_PVOID pvLinAddr;
+ IMG_PVOID pvAltLinAddr;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ IMG_UINT32 ui32Offset;
+ IMG_UINT32 ui32Bytes;
+ IMG_UINT32 ui32Flags;
+
+}PVRSRV_BRIDGE_IN_PDUMP_DUMPMEM;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_DUMPSYNC_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_PVOID pvAltLinAddr;
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+ IMG_UINT32 ui32Offset;
+ IMG_UINT32 ui32Bytes;
+
+}PVRSRV_BRIDGE_IN_PDUMP_DUMPSYNC;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_DUMPREG_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ PVRSRV_HWREG sHWReg;
+ IMG_UINT32 ui32Flags;
+ IMG_CHAR szRegRegion[32];
+
+}PVRSRV_BRIDGE_IN_PDUMP_DUMPREG;
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_REGPOL_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ PVRSRV_HWREG sHWReg;
+ IMG_UINT32 ui32Mask;
+ IMG_UINT32 ui32Flags;
+ IMG_CHAR szRegRegion[32];
+}PVRSRV_BRIDGE_IN_PDUMP_REGPOL;
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_DUMPPDREG_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_HWREG sHWReg;
+ IMG_UINT32 ui32Flags;
+
+}PVRSRV_BRIDGE_IN_PDUMP_DUMPPDREG;
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_MEMPAGES_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hKernelMemInfo;
+ IMG_DEV_PHYADDR *pPages;
+ IMG_UINT32 ui32NumPages;
+ IMG_DEV_VIRTADDR sDevAddr;
+ IMG_UINT32 ui32Start;
+ IMG_UINT32 ui32Length;
+ IMG_BOOL bContinuous;
+
+}PVRSRV_BRIDGE_IN_PDUMP_MEMPAGES;
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_COMMENT_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_CHAR szComment[PVRSRV_PDUMP_MAX_COMMENT_SIZE];
+ IMG_UINT32 ui32Flags;
+
+}PVRSRV_BRIDGE_IN_PDUMP_COMMENT;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_SETFRAME_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32Frame;
+
+}PVRSRV_BRIDGE_IN_PDUMP_SETFRAME;
+
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_BITMAP_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_CHAR szFileName[PVRSRV_PDUMP_MAX_FILENAME_SIZE];
+ IMG_UINT32 ui32FileOffset;
+ IMG_UINT32 ui32Width;
+ IMG_UINT32 ui32Height;
+ IMG_UINT32 ui32StrideInBytes;
+ IMG_DEV_VIRTADDR sDevBaseAddr;
+ IMG_HANDLE hDevMemContext;
+ IMG_UINT32 ui32Size;
+ PDUMP_PIXEL_FORMAT ePixelFormat;
+ PDUMP_MEM_FORMAT eMemFormat;
+ IMG_UINT32 ui32Flags;
+
+}PVRSRV_BRIDGE_IN_PDUMP_BITMAP;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_READREG_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_CHAR szFileName[PVRSRV_PDUMP_MAX_FILENAME_SIZE];
+ IMG_UINT32 ui32FileOffset;
+ IMG_UINT32 ui32Address;
+ IMG_UINT32 ui32Size;
+ IMG_UINT32 ui32Flags;
+ IMG_CHAR szRegRegion[32];
+
+}PVRSRV_BRIDGE_IN_PDUMP_READREG;
+
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_DRIVERINFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_CHAR szString[PVRSRV_PDUMP_MAX_COMMENT_SIZE];
+ IMG_BOOL bContinuous;
+
+}PVRSRV_BRIDGE_IN_PDUMP_DRIVERINFO;
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_DUMPPDDEVPADDR_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hKernelMemInfo;
+ IMG_UINT32 ui32Offset;
+ IMG_DEV_PHYADDR sPDDevPAddr;
+}PVRSRV_BRIDGE_IN_PDUMP_DUMPPDDEVPADDR;
+
+
+typedef struct PVRSRV_BRIDGE_PDUM_IN_CYCLE_COUNT_REG_READ_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_UINT32 ui32RegOffset;
+ IMG_BOOL bLastFrame;
+}PVRSRV_BRIDGE_IN_PDUMP_CYCLE_COUNT_REG_READ;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_ENUMDEVICE_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32NumDevices;
+ PVRSRV_DEVICE_IDENTIFIER asDeviceIdentifier[PVRSRV_MAX_DEVICES];
+
+}PVRSRV_BRIDGE_OUT_ENUMDEVICE;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_ACQUIRE_DEVICEINFO_TAG
+{
+
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hDevCookie;
+
+} PVRSRV_BRIDGE_OUT_ACQUIRE_DEVICEINFO;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_ENUMCLASS_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32NumDevices;
+ IMG_UINT32 ui32DevID[PVRSRV_MAX_DEVICES];
+
+}PVRSRV_BRIDGE_OUT_ENUMCLASS;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_OPEN_DISPCLASS_DEVICE_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32DeviceID;
+ IMG_HANDLE hDevCookie;
+
+}PVRSRV_BRIDGE_IN_OPEN_DISPCLASS_DEVICE;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_OPEN_DISPCLASS_DEVICE_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hDeviceKM;
+
+}PVRSRV_BRIDGE_OUT_OPEN_DISPCLASS_DEVICE;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_WRAP_EXT_MEMORY_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_HANDLE hDevMemContext;
+ IMG_VOID *pvLinAddr;
+ IMG_SIZE_T ui32ByteSize;
+ IMG_SIZE_T ui32PageOffset;
+ IMG_BOOL bPhysContig;
+ IMG_UINT32 ui32NumPageTableEntries;
+ IMG_SYS_PHYADDR *psSysPAddr;
+ IMG_UINT32 ui32Flags;
+
+}PVRSRV_BRIDGE_IN_WRAP_EXT_MEMORY;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_WRAP_EXT_MEMORY_TAG
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+ PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+
+}PVRSRV_BRIDGE_OUT_WRAP_EXT_MEMORY;
+
+
+typedef struct PVRSRV_BRIDGE_IN_UNWRAP_EXT_MEMORY_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hKernelMemInfo;
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+ PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+
+}PVRSRV_BRIDGE_IN_UNWRAP_EXT_MEMORY;
+
+
+#define PVRSRV_MAX_DC_DISPLAY_FORMATS 10
+#define PVRSRV_MAX_DC_DISPLAY_DIMENSIONS 10
+#define PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS 4
+#define PVRSRV_MAX_DC_CLIP_RECTS 32
+
+
+typedef struct PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_FORMATS_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32Count;
+ DISPLAY_FORMAT asFormat[PVRSRV_MAX_DC_DISPLAY_FORMATS];
+
+}PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_FORMATS;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_DIMS_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDeviceKM;
+ DISPLAY_FORMAT sFormat;
+
+}PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_DIMS;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_DIMS_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32Count;
+ DISPLAY_DIMS asDim[PVRSRV_MAX_DC_DISPLAY_DIMENSIONS];
+
+}PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_DIMS;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GET_DISPCLASS_INFO_TAG
+{
+ PVRSRV_ERROR eError;
+ DISPLAY_INFO sDisplayInfo;
+
+}PVRSRV_BRIDGE_OUT_GET_DISPCLASS_INFO;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GET_DISPCLASS_SYSBUFFER_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hBuffer;
+
+}PVRSRV_BRIDGE_OUT_GET_DISPCLASS_SYSBUFFER;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_CREATE_DISPCLASS_SWAPCHAIN_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDeviceKM;
+ IMG_UINT32 ui32Flags;
+ DISPLAY_SURF_ATTRIBUTES sDstSurfAttrib;
+ DISPLAY_SURF_ATTRIBUTES sSrcSurfAttrib;
+ IMG_UINT32 ui32BufferCount;
+ IMG_UINT32 ui32OEMFlags;
+ IMG_UINT32 ui32SwapChainID;
+
+} PVRSRV_BRIDGE_IN_CREATE_DISPCLASS_SWAPCHAIN;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_CREATE_DISPCLASS_SWAPCHAIN_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hSwapChain;
+ IMG_UINT32 ui32SwapChainID;
+
+} PVRSRV_BRIDGE_OUT_CREATE_DISPCLASS_SWAPCHAIN;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_DESTROY_DISPCLASS_SWAPCHAIN_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDeviceKM;
+ IMG_HANDLE hSwapChain;
+
+} PVRSRV_BRIDGE_IN_DESTROY_DISPCLASS_SWAPCHAIN;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_SET_DISPCLASS_RECT_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDeviceKM;
+ IMG_HANDLE hSwapChain;
+ IMG_RECT sRect;
+
+} PVRSRV_BRIDGE_IN_SET_DISPCLASS_RECT;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_SET_DISPCLASS_COLOURKEY_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDeviceKM;
+ IMG_HANDLE hSwapChain;
+ IMG_UINT32 ui32CKColour;
+
+} PVRSRV_BRIDGE_IN_SET_DISPCLASS_COLOURKEY;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_GET_DISPCLASS_BUFFERS_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDeviceKM;
+ IMG_HANDLE hSwapChain;
+
+} PVRSRV_BRIDGE_IN_GET_DISPCLASS_BUFFERS;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GET_DISPCLASS_BUFFERS_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32BufferCount;
+ IMG_HANDLE ahBuffer[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
+
+} PVRSRV_BRIDGE_OUT_GET_DISPCLASS_BUFFERS;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_BUFFER_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDeviceKM;
+ IMG_HANDLE hBuffer;
+ IMG_UINT32 ui32SwapInterval;
+ IMG_HANDLE hPrivateTag;
+ IMG_UINT32 ui32ClipRectCount;
+ IMG_RECT sClipRect[PVRSRV_MAX_DC_CLIP_RECTS];
+
+} PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_BUFFER;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_SYSTEM_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDeviceKM;
+ IMG_HANDLE hSwapChain;
+
+} PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_SYSTEM;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_GET_DISPCLASS_FRONT_BUFFER_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDeviceKM;
+
+} PVRSRV_BRIDGE_IN_GET_DISPCLASS_FRONT_BUFFER;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GET_DISPCLASS_FRONT_BUFFER_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32BufferIndex;
+ IMG_UINT32 ui32FlipChainID;
+
+} PVRSRV_BRIDGE_OUT_GET_DISPCLASS_FRONT_BUFFER;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_OPEN_BUFFERCLASS_DEVICE_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32DeviceID;
+ IMG_HANDLE hDevCookie;
+
+} PVRSRV_BRIDGE_IN_OPEN_BUFFERCLASS_DEVICE;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_OPEN_BUFFERCLASS_DEVICE_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hDeviceKM;
+
+} PVRSRV_BRIDGE_OUT_OPEN_BUFFERCLASS_DEVICE;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_INFO_TAG
+{
+ PVRSRV_ERROR eError;
+ BUFFER_INFO sBufferInfo;
+
+} PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_INFO;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_BUFFER_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDeviceKM;
+ IMG_UINT32 ui32BufferIndex;
+
+} PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_BUFFER;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_BUFFER_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hBuffer;
+
+} PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_BUFFER;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GET_DEVMEM_HEAPINFO_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32ClientHeapCount;
+ PVRSRV_HEAP_INFO sHeapInfo[PVRSRV_MAX_CLIENT_HEAPS];
+
+} PVRSRV_BRIDGE_OUT_GET_DEVMEM_HEAPINFO;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_CREATE_DEVMEMCONTEXT_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hDevMemContext;
+ IMG_UINT32 ui32ClientHeapCount;
+ PVRSRV_HEAP_INFO sHeapInfo[PVRSRV_MAX_CLIENT_HEAPS];
+
+} PVRSRV_BRIDGE_OUT_CREATE_DEVMEMCONTEXT;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_CREATE_DEVMEMHEAP_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hDevMemHeap;
+
+} PVRSRV_BRIDGE_OUT_CREATE_DEVMEMHEAP;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM_TAG
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+ PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+
+} PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hMemInfo;
+#if defined(SUPPORT_MEMINFO_IDS)
+ IMG_UINT64 ui64Stamp;
+#endif
+
+} PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_MAPMEMINFOTOUSER_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_PVOID pvLinAddr;
+ IMG_HANDLE hMappingInfo;
+
+}PVRSRV_BRIDGE_OUT_MAPMEMINFOTOUSER;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GETFREEDEVICEMEM_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_SIZE_T ui32Total;
+ IMG_SIZE_T ui32Free;
+ IMG_SIZE_T ui32LargestBlock;
+
+} PVRSRV_BRIDGE_OUT_GETFREEDEVICEMEM;
+
+
+#include "pvrmmap.h"
+typedef struct PVRSRV_BRIDGE_OUT_MHANDLE_TO_MMAP_DATA_TAG
+{
+ PVRSRV_ERROR eError;
+
+
+ IMG_UINT32 ui32MMapOffset;
+
+
+ IMG_UINT32 ui32ByteOffset;
+
+
+ IMG_UINT32 ui32RealByteSize;
+
+
+ IMG_UINT32 ui32UserVAddr;
+
+} PVRSRV_BRIDGE_OUT_MHANDLE_TO_MMAP_DATA;
+
+typedef struct PVRSRV_BRIDGE_OUT_RELEASE_MMAP_DATA_TAG
+{
+ PVRSRV_ERROR eError;
+
+
+ IMG_BOOL bMUnmap;
+
+
+ IMG_UINT32 ui32UserVAddr;
+
+
+ IMG_UINT32 ui32RealByteSize;
+} PVRSRV_BRIDGE_OUT_RELEASE_MMAP_DATA;
+
+typedef struct PVRSRV_BRIDGE_IN_GET_MISC_INFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_MISC_INFO sMiscInfo;
+
+}PVRSRV_BRIDGE_IN_GET_MISC_INFO;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GET_MISC_INFO_TAG
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_MISC_INFO sMiscInfo;
+
+}PVRSRV_BRIDGE_OUT_GET_MISC_INFO;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_RELEASE_MISC_INFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_MISC_INFO sMiscInfo;
+
+}PVRSRV_BRIDGE_IN_RELEASE_MISC_INFO;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_RELEASE_MISC_INFO_TAG
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_MISC_INFO sMiscInfo;
+
+}PVRSRV_BRIDGE_OUT_RELEASE_MISC_INFO;
+
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_PDUMP_ISCAPTURING_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_BOOL bIsCapturing;
+
+} PVRSRV_BRIDGE_OUT_PDUMP_ISCAPTURING;
+
+
+typedef struct PVRSRV_BRIDGE_IN_GET_FB_STATS_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_SIZE_T ui32Total;
+ IMG_SIZE_T ui32Available;
+
+} PVRSRV_BRIDGE_IN_GET_FB_STATS;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_MAPPHYSTOUSERSPACE_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_SYS_PHYADDR sSysPhysAddr;
+ IMG_UINT32 uiSizeInBytes;
+
+} PVRSRV_BRIDGE_IN_MAPPHYSTOUSERSPACE;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_MAPPHYSTOUSERSPACE_TAG
+{
+ IMG_PVOID pvUserAddr;
+ IMG_UINT32 uiActualSize;
+ IMG_PVOID pvProcess;
+
+} PVRSRV_BRIDGE_OUT_MAPPHYSTOUSERSPACE;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_UNMAPPHYSTOUSERSPACE_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_PVOID pvUserAddr;
+ IMG_PVOID pvProcess;
+
+} PVRSRV_BRIDGE_IN_UNMAPPHYSTOUSERSPACE;
+
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GETPHYSTOUSERSPACEMAP_TAG
+{
+ IMG_PVOID *ppvTbl;
+ IMG_UINT32 uiTblSize;
+
+} PVRSRV_BRIDGE_OUT_GETPHYSTOUSERSPACEMAP;
+
+
+
+typedef struct PVRSRV_BRIDGE_IN_REGISTER_SIM_PROCESS_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_PVOID pvProcess;
+
+} PVRSRV_BRIDGE_IN_REGISTER_SIM_PROCESS;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_REGISTER_SIM_PROCESS_TAG
+{
+ IMG_SYS_PHYADDR sRegsPhysBase;
+ IMG_VOID *pvRegsBase;
+ IMG_PVOID pvProcess;
+ IMG_UINT32 ulNoOfEntries;
+ IMG_PVOID pvTblLinAddr;
+
+} PVRSRV_BRIDGE_OUT_REGISTER_SIM_PROCESS;
+
+
+typedef struct PVRSRV_BRIDGE_IN_UNREGISTER_SIM_PROCESS_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_PVOID pvProcess;
+ IMG_VOID *pvRegsBase;
+
+} PVRSRV_BRIDGE_IN_UNREGISTER_SIM_PROCESS;
+
+typedef struct PVRSRV_BRIDGE_IN_PROCESS_SIMISR_EVENT_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_UINT32 ui32StatusAndMask;
+ PVRSRV_ERROR eError;
+
+} PVRSRV_BRIDGE_IN_PROCESS_SIMISR_EVENT;
+
+typedef struct PVRSRV_BRIDGE_IN_INITSRV_DISCONNECT_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_BOOL bInitSuccesful;
+} PVRSRV_BRIDGE_IN_INITSRV_DISCONNECT;
+
+
+typedef struct PVRSRV_BRIDGE_IN_ALLOC_SHARED_SYS_MEM_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32Flags;
+ IMG_SIZE_T ui32Size;
+}PVRSRV_BRIDGE_IN_ALLOC_SHARED_SYS_MEM;
+
+typedef struct PVRSRV_BRIDGE_OUT_ALLOC_SHARED_SYS_MEM_TAG
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+}PVRSRV_BRIDGE_OUT_ALLOC_SHARED_SYS_MEM;
+
+typedef struct PVRSRV_BRIDGE_IN_FREE_SHARED_SYS_MEM_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+}PVRSRV_BRIDGE_IN_FREE_SHARED_SYS_MEM;
+
+typedef struct PVRSRV_BRIDGE_OUT_FREE_SHARED_SYS_MEM_TAG
+{
+ PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_FREE_SHARED_SYS_MEM;
+
+typedef struct PVRSRV_BRIDGE_IN_MAP_MEMINFO_MEM_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hKernelMemInfo;
+}PVRSRV_BRIDGE_IN_MAP_MEMINFO_MEM;
+
+typedef struct PVRSRV_BRIDGE_OUT_MAP_MEMINFO_MEM_TAG
+{
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+ PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_MAP_MEMINFO_MEM;
+
+typedef struct PVRSRV_BRIDGE_IN_UNMAP_MEMINFO_MEM_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+}PVRSRV_BRIDGE_IN_UNMAP_MEMINFO_MEM;
+
+typedef struct PVRSRV_BRIDGE_OUT_UNMAP_MEMINFO_MEM_TAG
+{
+ PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_UNMAP_MEMINFO_MEM;
+
+typedef struct PVRSRV_BRIDGE_IN_GETMMU_PD_DEVPADDR_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevMemContext;
+}PVRSRV_BRIDGE_IN_GETMMU_PD_DEVPADDR;
+
+typedef struct PVRSRV_BRIDGE_OUT_GETMMU_PD_DEVPADDR_TAG
+{
+ IMG_DEV_PHYADDR sPDDevPAddr;
+ PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_GETMMU_PD_DEVPADDR;
+
+typedef struct PVRSRV_BRIDGE_IN_EVENT_OBJECT_WAI_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hOSEventKM;
+} PVRSRV_BRIDGE_IN_EVENT_OBJECT_WAIT;
+
+typedef struct PVRSRV_BRIDGE_IN_EVENT_OBJECT_OPEN_TAG
+{
+ PVRSRV_EVENTOBJECT sEventObject;
+} PVRSRV_BRIDGE_IN_EVENT_OBJECT_OPEN;
+
+typedef struct PVRSRV_BRIDGE_OUT_EVENT_OBJECT_OPEN_TAG
+{
+ IMG_HANDLE hOSEvent;
+ PVRSRV_ERROR eError;
+} PVRSRV_BRIDGE_OUT_EVENT_OBJECT_OPEN;
+
+typedef struct PVRSRV_BRIDGE_IN_EVENT_OBJECT_CLOSE_TAG
+{
+ PVRSRV_EVENTOBJECT sEventObject;
+ IMG_HANDLE hOSEventKM;
+} PVRSRV_BRIDGE_IN_EVENT_OBJECT_CLOSE;
+
+typedef struct PVRSRV_BRIDGE_OUT_CREATE_SYNC_INFO_MOD_OBJ_TAG
+{
+ PVRSRV_ERROR eError;
+
+ IMG_HANDLE hKernelSyncInfoModObj;
+
+} PVRSRV_BRIDGE_OUT_CREATE_SYNC_INFO_MOD_OBJ;
+
+typedef struct PVRSRV_BRIDGE_IN_DESTROY_SYNC_INFO_MOD_OBJ
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hKernelSyncInfoModObj;
+} PVRSRV_BRIDGE_IN_DESTROY_SYNC_INFO_MOD_OBJ;
+
+typedef struct PVRSRV_BRIDGE_IN_MODIFY_PENDING_SYNC_OPS_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hKernelSyncInfoModObj;
+ IMG_HANDLE hKernelSyncInfo;
+ IMG_UINT32 ui32ModifyFlags;
+
+} PVRSRV_BRIDGE_IN_MODIFY_PENDING_SYNC_OPS;
+
+typedef struct PVRSRV_BRIDGE_IN_MODIFY_COMPLETE_SYNC_OPS_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hKernelSyncInfoModObj;
+} PVRSRV_BRIDGE_IN_MODIFY_COMPLETE_SYNC_OPS;
+
+typedef struct PVRSRV_BRIDGE_OUT_MODIFY_PENDING_SYNC_OPS_TAG
+{
+ PVRSRV_ERROR eError;
+
+
+ IMG_UINT32 ui32ReadOpsPending;
+ IMG_UINT32 ui32WriteOpsPending;
+
+} PVRSRV_BRIDGE_OUT_MODIFY_PENDING_SYNC_OPS;
+
+typedef struct PVRSRV_BRIDGE_IN_SYNC_OPS_FLUSH_TO_MOD_OBJ_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hKernelSyncInfoModObj;
+} PVRSRV_BRIDGE_IN_SYNC_OPS_FLUSH_TO_MOD_OBJ;
+
+typedef struct PVRSRV_BRIDGE_IN_SYNC_OPS_FLUSH_TO_DELTA_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hKernelSyncInfo;
+ IMG_UINT32 ui32Delta;
+} PVRSRV_BRIDGE_IN_SYNC_OPS_FLUSH_TO_DELTA;
+
+typedef struct PVRSRV_BRIDGE_IN_ALLOC_SYNC_INFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+
+ IMG_HANDLE hDevCookie;
+} PVRSRV_BRIDGE_IN_ALLOC_SYNC_INFO;
+
+typedef struct PVRSRV_BRIDGE_OUT_ALLOC_SYNC_INFO_TAG
+{
+ PVRSRV_ERROR eError;
+
+ IMG_HANDLE hKernelSyncInfo;
+} PVRSRV_BRIDGE_OUT_ALLOC_SYNC_INFO;
+
+typedef struct PVRSRV_BRIDGE_IN_FREE_SYNC_INFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+
+ IMG_HANDLE hKernelSyncInfo;
+} PVRSRV_BRIDGE_IN_FREE_SYNC_INFO;
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef __PVR_BRIDGE_KM_H_
+#define __PVR_BRIDGE_KM_H_
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "pvr_bridge.h"
+#include "perproc.h"
+
+#if defined(__linux__)
+PVRSRV_ERROR LinuxBridgeInit(IMG_VOID);
+IMG_VOID LinuxBridgeDeInit(IMG_VOID);
+#endif
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumerateDevicesKM(IMG_UINT32 *pui32NumDevices,
+ PVRSRV_DEVICE_IDENTIFIER *psDevIdList);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAcquireDeviceDataKM(IMG_UINT32 uiDevIndex,
+ PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_HANDLE *phDevCookie);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateCommandQueueKM(IMG_SIZE_T ui32QueueSize,
+ PVRSRV_QUEUE_INFO **ppsQueueInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyCommandQueueKM(PVRSRV_QUEUE_INFO *psQueueInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapsKM(IMG_HANDLE hDevCookie,
+ PVRSRV_HEAP_INFO *psHeapInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateDeviceMemContextKM(IMG_HANDLE hDevCookie,
+ PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE *phDevMemContext,
+ IMG_UINT32 *pui32ClientHeapCount,
+ PVRSRV_HEAP_INFO *psHeapInfo,
+ IMG_BOOL *pbCreated,
+ IMG_BOOL *pbShared);
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyDeviceMemContextKM(IMG_HANDLE hDevCookie,
+ IMG_HANDLE hDevMemContext,
+ IMG_BOOL *pbDestroyed);
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapInfoKM(IMG_HANDLE hDevCookie,
+ IMG_HANDLE hDevMemContext,
+ IMG_UINT32 *pui32ClientHeapCount,
+ PVRSRV_HEAP_INFO *psHeapInfo,
+ IMG_BOOL *pbShared
+ );
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV _PVRSRVAllocDeviceMemKM(IMG_HANDLE hDevCookie,
+ PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDevMemHeap,
+ IMG_UINT32 ui32Flags,
+ IMG_SIZE_T ui32Size,
+ IMG_SIZE_T ui32Alignment,
+ PVRSRV_KERNEL_MEM_INFO **ppsMemInfo);
+
+
+#if defined(PVRSRV_LOG_MEMORY_ALLOCS)
+ #define PVRSRVAllocDeviceMemKM(devCookie, perProc, devMemHeap, flags, size, alignment, memInfo, logStr) \
+ (PVR_TRACE(("PVRSRVAllocDeviceMemKM(" #devCookie ", " #perProc ", " #devMemHeap ", " #flags ", " #size \
+ ", " #alignment "," #memInfo "): " logStr " (size = 0x%;x)", size)),\
+ _PVRSRVAllocDeviceMemKM(devCookie, perProc, devMemHeap, flags, size, alignment, memInfo))
+#else
+ #define PVRSRVAllocDeviceMemKM(devCookie, perProc, devMemHeap, flags, size, alignment, memInfo, logStr) \
+ _PVRSRVAllocDeviceMemKM(devCookie, perProc, devMemHeap, flags, size, alignment, memInfo)
+#endif
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeDeviceMemKM(IMG_HANDLE hDevCookie,
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDissociateDeviceMemKM(IMG_HANDLE hDevCookie,
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVReserveDeviceVirtualMemKM(IMG_HANDLE hDevMemHeap,
+ IMG_DEV_VIRTADDR *psDevVAddr,
+ IMG_SIZE_T ui32Size,
+ IMG_SIZE_T ui32Alignment,
+ PVRSRV_KERNEL_MEM_INFO **ppsMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeDeviceVirtualMemKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceMemoryKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ PVRSRV_KERNEL_MEM_INFO *psSrcMemInfo,
+ IMG_HANDLE hDstDevMemHeap,
+ PVRSRV_KERNEL_MEM_INFO **ppsDstMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceMemoryKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVWrapExtMemoryKM(IMG_HANDLE hDevCookie,
+ PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDevMemContext,
+ IMG_SIZE_T ui32ByteSize,
+ IMG_SIZE_T ui32PageOffset,
+ IMG_BOOL bPhysContig,
+ IMG_SYS_PHYADDR *psSysAddr,
+ IMG_VOID *pvLinAddr,
+ IMG_UINT32 ui32Flags,
+ PVRSRV_KERNEL_MEM_INFO **ppsMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnwrapExtMemoryKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVEnumerateDCKM(PVRSRV_DEVICE_CLASS DeviceClass,
+ IMG_UINT32 *pui32DevCount,
+ IMG_UINT32 *pui32DevID );
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVOpenDCDeviceKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_UINT32 ui32DeviceID,
+ IMG_HANDLE hDevCookie,
+ IMG_HANDLE *phDeviceKM);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVCloseDCDeviceKM(IMG_HANDLE hDeviceKM, IMG_BOOL bResManCallback);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVEnumDCFormatsKM(IMG_HANDLE hDeviceKM,
+ IMG_UINT32 *pui32Count,
+ DISPLAY_FORMAT *psFormat);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVEnumDCDimsKM(IMG_HANDLE hDeviceKM,
+ DISPLAY_FORMAT *psFormat,
+ IMG_UINT32 *pui32Count,
+ DISPLAY_DIMS *psDim);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVGetDCSystemBufferKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE *phBuffer);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVGetDCInfoKM(IMG_HANDLE hDeviceKM,
+ DISPLAY_INFO *psDisplayInfo);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVCreateDCSwapChainKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDeviceKM,
+ IMG_UINT32 ui32Flags,
+ DISPLAY_SURF_ATTRIBUTES *psDstSurfAttrib,
+ DISPLAY_SURF_ATTRIBUTES *psSrcSurfAttrib,
+ IMG_UINT32 ui32BufferCount,
+ IMG_UINT32 ui32OEMFlags,
+ IMG_HANDLE *phSwapChain,
+ IMG_UINT32 *pui32SwapChainID);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVDestroyDCSwapChainKM(IMG_HANDLE hSwapChain);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetDCDstRectKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hSwapChain,
+ IMG_RECT *psRect);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetDCSrcRectKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hSwapChain,
+ IMG_RECT *psRect);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetDCDstColourKeyKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hSwapChain,
+ IMG_UINT32 ui32CKColour);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetDCSrcColourKeyKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hSwapChain,
+ IMG_UINT32 ui32CKColour);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVGetDCBuffersKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hSwapChain,
+ IMG_UINT32 *pui32BufferCount,
+ IMG_HANDLE *phBuffer);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSwapToDCBufferKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hBuffer,
+ IMG_UINT32 ui32SwapInterval,
+ IMG_HANDLE hPrivateTag,
+ IMG_UINT32 ui32ClipRectCount,
+ IMG_RECT *psClipRect,
+ PVRSRV_PER_PROCESS_DATA *psPerProc);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSwapToDCSystemKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hSwapChain);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVOpenBCDeviceKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_UINT32 ui32DeviceID,
+ IMG_HANDLE hDevCookie,
+ IMG_HANDLE *phDeviceKM);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVCloseBCDeviceKM(IMG_HANDLE hDeviceKM, IMG_BOOL bResManCallback);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVGetBCInfoKM(IMG_HANDLE hDeviceKM,
+ BUFFER_INFO *psBufferInfo);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVGetBCBufferKM(IMG_HANDLE hDeviceKM,
+ IMG_UINT32 ui32BufferIndex,
+ IMG_HANDLE *phBuffer);
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceClassMemoryKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDevMemContext,
+ IMG_HANDLE hDeviceClassBuffer,
+ PVRSRV_KERNEL_MEM_INFO **ppsMemInfo,
+ IMG_HANDLE *phOSMapInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceClassMemoryKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetFreeDeviceMemKM(IMG_UINT32 ui32Flags,
+ IMG_SIZE_T *pui32Total,
+ IMG_SIZE_T *pui32Free,
+ IMG_SIZE_T *pui32LargestBlock);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAllocSyncInfoKM(IMG_HANDLE hDevCookie,
+ IMG_HANDLE hDevMemContext,
+ PVRSRV_KERNEL_SYNC_INFO **ppsKernelSyncInfo);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeSyncInfoKM(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo);
+
+IMG_IMPORT PVRSRV_ERROR
+PVRSRVAllocSharedSysMemoryKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_UINT32 ui32Flags,
+ IMG_SIZE_T ui32Size,
+ PVRSRV_KERNEL_MEM_INFO **ppsKernelMemInfo);
+
+IMG_IMPORT PVRSRV_ERROR
+PVRSRVFreeSharedSysMemoryKM(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo);
+
+IMG_IMPORT PVRSRV_ERROR
+PVRSRVDissociateMemFromResmanKM(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef __PVRMMAP_H__
+#define __PVRMMAP_H__
+
+PVRSRV_ERROR PVRPMapKMem(IMG_HANDLE hModule, IMG_VOID **ppvLinAddr, IMG_VOID *pvLinAddrKM, IMG_HANDLE *phMappingInfo, IMG_HANDLE hMHandle);
+
+
+IMG_BOOL PVRUnMapKMem(IMG_HANDLE hModule, IMG_HANDLE hMappingInfo, IMG_HANDLE hMHandle);
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#if !defined (__PVRSRV_ERRORS_H__)
+#define __PVRSRV_ERRORS_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+ switch (eError)
+ {
+ case PVRSRV_OK: return "No Errors";
+ case PVRSRV_ERROR_OUT_OF_MEMORY: return "PVRSRV_ERROR_OUT_OF_MEMORY - Unable to allocate required memory";
+ case PVRSRV_ERROR_TOO_FEW_BUFFERS: return "PVRSRV_ERROR_TOO_FEW_BUFFERS";
+ case PVRSRV_ERROR_INVALID_PARAMS: return "PVRSRV_ERROR_INVALID_PARAMS";
+ case PVRSRV_ERROR_INIT_FAILURE: return "PVRSRV_ERROR_INIT_FAILURE";
+ case PVRSRV_ERROR_CANT_REGISTER_CALLBACK: return "PVRSRV_ERROR_CANT_REGISTER_CALLBACK";
+ case PVRSRV_ERROR_INVALID_DEVICE: return "PVRSRV_ERROR_INVALID_DEVICE";
+ case PVRSRV_ERROR_NOT_OWNER: return "PVRSRV_ERROR_NOT_OWNER";
+ case PVRSRV_ERROR_BAD_MAPPING: return "PVRSRV_ERROR_BAD_MAPPING";
+ case PVRSRV_ERROR_TIMEOUT: return "PVRSRV_ERROR_TIMEOUT";
+ case PVRSRV_ERROR_FLIP_CHAIN_EXISTS: return "PVRSRV_ERROR_FLIP_CHAIN_EXISTS";
+ case PVRSRV_ERROR_INVALID_SWAPINTERVAL: return "PVRSRV_ERROR_INVALID_SWAPINTERVAL";
+ case PVRSRV_ERROR_SCENE_INVALID: return "PVRSRV_ERROR_SCENE_INVALID";
+ case PVRSRV_ERROR_STREAM_ERROR: return "PVRSRV_ERROR_STREAM_ERROR";
+ case PVRSRV_ERROR_FAILED_DEPENDENCIES: return "PVRSRV_ERROR_FAILED_DEPENDENCIES";
+ case PVRSRV_ERROR_CMD_NOT_PROCESSED: return "PVRSRV_ERROR_CMD_NOT_PROCESSED";
+ case PVRSRV_ERROR_CMD_TOO_BIG: return "PVRSRV_ERROR_CMD_TOO_BIG";
+ case PVRSRV_ERROR_DEVICE_REGISTER_FAILED: return "PVRSRV_ERROR_DEVICE_REGISTER_FAILED";
+ case PVRSRV_ERROR_TOOMANYBUFFERS: return "PVRSRV_ERROR_TOOMANYBUFFERS";
+ case PVRSRV_ERROR_NOT_SUPPORTED: return "PVRSRV_ERROR_NOT_SUPPORTED - fix";
+ case PVRSRV_ERROR_PROCESSING_BLOCKED: return "PVRSRV_ERROR_PROCESSING_BLOCKED";
+
+ case PVRSRV_ERROR_CANNOT_FLUSH_QUEUE: return "PVRSRV_ERROR_CANNOT_FLUSH_QUEUE";
+ case PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE: return "PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE";
+ case PVRSRV_ERROR_CANNOT_GET_RENDERDETAILS: return "PVRSRV_ERROR_CANNOT_GET_RENDERDETAILS";
+ case PVRSRV_ERROR_RETRY: return "PVRSRV_ERROR_RETRY";
+
+ case PVRSRV_ERROR_DDK_VERSION_MISMATCH: return "PVRSRV_ERROR_DDK_VERSION_MISMATCH";
+ case PVRSRV_ERROR_BUILD_MISMATCH: return "PVRSRV_ERROR_BUILD_MISMATCH";
+ case PVRSRV_ERROR_CORE_REVISION_MISMATCH: return "PVRSRV_ERROR_CORE_REVISION_MISMATCH";
+
+ case PVRSRV_ERROR_UPLOAD_TOO_BIG: return "PVRSRV_ERROR_UPLOAD_TOO_BIG";
+
+ case PVRSRV_ERROR_INVALID_FLAGS: return "PVRSRV_ERROR_INVALID_FLAGS";
+ case PVRSRV_ERROR_FAILED_TO_REGISTER_PROCESS: return "PVRSRV_ERROR_FAILED_TO_REGISTER_PROCESS";
+
+ case PVRSRV_ERROR_UNABLE_TO_LOAD_LIBRARY: return "PVRSRV_ERROR_UNABLE_TO_LOAD_LIBRARY";
+ case PVRSRV_ERROR_UNABLE_GET_FUNC_ADDR: return "PVRSRV_ERROR_UNABLE_GET_FUNC_ADDR";
+ case PVRSRV_ERROR_UNLOAD_LIBRARY_FAILED: return "PVRSRV_ERROR_UNLOAD_LIBRARY_FAILED";
+
+ case PVRSRV_ERROR_BRIDGE_CALL_FAILED: return "PVRSRV_ERROR_BRIDGE_CALL_FAILED";
+ case PVRSRV_ERROR_IOCTL_CALL_FAILED: return "PVRSRV_ERROR_IOCTL_CALL_FAILED";
+
+ case PVRSRV_ERROR_MMU_CONTEXT_NOT_FOUND: return "PVRSRV_ERROR_MMU_CONTEXT_NOT_FOUND";
+ case PVRSRV_ERROR_BUFFER_DEVICE_NOT_FOUND: return "PVRSRV_ERROR_BUFFER_DEVICE_NOT_FOUND";
+ case PVRSRV_ERROR_BUFFER_DEVICE_ALREADY_PRESENT:return "PVRSRV_ERROR_BUFFER_DEVICE_ALREADY_PRESENT";
+
+ case PVRSRV_ERROR_PCI_DEVICE_NOT_FOUND: return "PVRSRV_ERROR_PCI_DEVICE_NOT_FOUND";
+ case PVRSRV_ERROR_PCI_CALL_FAILED: return "PVRSRV_ERROR_PCI_CALL_FAILED";
+ case PVRSRV_ERROR_PCI_REGION_TOO_SMALL: return "PVRSRV_ERROR_PCI_REGION_TOO_SMALL";
+ case PVRSRV_ERROR_PCI_REGION_UNAVAILABLE: return "PVRSRV_ERROR_PCI_REGION_UNAVAILABLE";
+ case PVRSRV_ERROR_BAD_REGION_SIZE_MISMATCH: return "PVRSRV_ERROR_BAD_REGION_SIZE_MISMATCH";
+
+ case PVRSRV_ERROR_REGISTER_BASE_NOT_SET: return "PVRSRV_ERROR_REGISTER_BASE_NOT_SET";
+
+ case PVRSRV_ERROR_FAILED_TO_ALLOC_USER_MEM: return "PVRSRV_ERROR_FAILED_TO_ALLOC_USER_MEM";
+ case PVRSRV_ERROR_FAILED_TO_ALLOC_VP_MEMORY: return "PVRSRV_ERROR_FAILED_TO_ALLOC_VP_MEMORY";
+ case PVRSRV_ERROR_FAILED_TO_MAP_SHARED_PBDESC: return "PVRSRV_ERROR_FAILED_TO_MAP_SHARED_PBDESC";
+ case PVRSRV_ERROR_FAILED_TO_GET_PHYS_ADDR: return "PVRSRV_ERROR_FAILED_TO_GET_PHYS_ADDR";
+
+ case PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY: return "PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY";
+ case PVRSRV_ERROR_FAILED_TO_COPY_VIRT_MEMORY: return "PVRSRV_ERROR_FAILED_TO_COPY_VIRT_MEMORY";
+
+ case PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES: return "PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES";
+ case PVRSRV_ERROR_FAILED_TO_FREE_PAGES: return "PVRSRV_ERROR_FAILED_TO_FREE_PAGES";
+ case PVRSRV_ERROR_FAILED_TO_COPY_PAGES: return "PVRSRV_ERROR_FAILED_TO_COPY_PAGES";
+ case PVRSRV_ERROR_UNABLE_TO_LOCK_PAGES: return "PVRSRV_ERROR_UNABLE_TO_LOCK_PAGES";
+ case PVRSRV_ERROR_UNABLE_TO_UNLOCK_PAGES: return "PVRSRV_ERROR_UNABLE_TO_UNLOCK_PAGES";
+ case PVRSRV_ERROR_STILL_MAPPED: return "PVRSRV_ERROR_STILL_MAPPED";
+ case PVRSRV_ERROR_MAPPING_NOT_FOUND: return "PVRSRV_ERROR_MAPPING_NOT_FOUND";
+ case PVRSRV_ERROR_PHYS_ADDRESS_EXCEEDS_32BIT: return "PVRSRV_ERROR_PHYS_ADDRESS_EXCEEDS_32BIT";
+ case PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE: return "PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE";
+
+ case PVRSRV_ERROR_INVALID_SEGMENT_BLOCK: return "PVRSRV_ERROR_INVALID_SEGMENT_BLOCK";
+ case PVRSRV_ERROR_INVALID_SGXDEVDATA: return "PVRSRV_ERROR_INVALID_SGXDEVDATA";
+ case PVRSRV_ERROR_INVALID_DEVINFO: return "PVRSRV_ERROR_INVALID_DEVINFO";
+ case PVRSRV_ERROR_INVALID_MEMINFO: return "PVRSRV_ERROR_INVALID_MEMINFO";
+ case PVRSRV_ERROR_INVALID_MISCINFO: return "PVRSRV_ERROR_INVALID_MISCINFO";
+ case PVRSRV_ERROR_UNKNOWN_IOCTL: return "PVRSRV_ERROR_UNKNOWN_IOCTL";
+ case PVRSRV_ERROR_INVALID_CONTEXT: return "PVRSRV_ERROR_INVALID_CONTEXT";
+ case PVRSRV_ERROR_UNABLE_TO_DESTROY_CONTEXT: return "PVRSRV_ERROR_UNABLE_TO_DESTROY_CONTEXT";
+ case PVRSRV_ERROR_INVALID_HEAP: return "PVRSRV_ERROR_INVALID_HEAP";
+ case PVRSRV_ERROR_INVALID_KERNELINFO: return "PVRSRV_ERROR_INVALID_KERNELINFO";
+ case PVRSRV_ERROR_UNKNOWN_POWER_STATE: return "PVRSRV_ERROR_UNKNOWN_POWER_STATE";
+ case PVRSRV_ERROR_INVALID_HANDLE_TYPE: return "PVRSRV_ERROR_INVALID_HANDLE_TYPE";
+ case PVRSRV_ERROR_INVALID_WRAP_TYPE: return "PVRSRV_ERROR_INVALID_WRAP_TYPE";
+ case PVRSRV_ERROR_INVALID_PHYS_ADDR: return "PVRSRV_ERROR_INVALID_PHYS_ADDR";
+ case PVRSRV_ERROR_INVALID_CPU_ADDR: return "PVRSRV_ERROR_INVALID_CPU_ADDR";
+ case PVRSRV_ERROR_INVALID_HEAPINFO: return "PVRSRV_ERROR_INVALID_HEAPINFO";
+ case PVRSRV_ERROR_INVALID_PERPROC: return "PVRSRV_ERROR_INVALID_PERPROC";
+ case PVRSRV_ERROR_FAILED_TO_RETRIEVE_HEAPINFO: return "PVRSRV_ERROR_FAILED_TO_RETRIEVE_HEAPINFO";
+ case PVRSRV_ERROR_INVALID_MAP_REQUEST: return "PVRSRV_ERROR_INVALID_MAP_REQUEST";
+ case PVRSRV_ERROR_INVALID_UNMAP_REQUEST: return "PVRSRV_ERROR_INVALID_UNMAP_REQUEST";
+ case PVRSRV_ERROR_UNABLE_TO_FIND_MAPPING_HEAP: return "PVRSRV_ERROR_UNABLE_TO_FIND_MAPPING_HEAP";
+ case PVRSRV_ERROR_MAPPING_STILL_IN_USE: return "PVRSRV_ERROR_MAPPING_STILL_IN_USE";
+
+ case PVRSRV_ERROR_EXCEEDED_HW_LIMITS: return "PVRSRV_ERROR_EXCEEDED_HW_LIMITS";
+ case PVRSRV_ERROR_NO_STAGING_BUFFER_ALLOCATED: return "PVRSRV_ERROR_NO_STAGING_BUFFER_ALLOCATED";
+
+ case PVRSRV_ERROR_UNABLE_TO_CREATE_PERPROC_AREA:return "PVRSRV_ERROR_UNABLE_TO_CREATE_PERPROC_AREA";
+ case PVRSRV_ERROR_UNABLE_TO_CREATE_EVENT: return "PVRSRV_ERROR_UNABLE_TO_CREATE_EVENT";
+ case PVRSRV_ERROR_UNABLE_TO_ENABLE_EVENT: return "PVRSRV_ERROR_UNABLE_TO_ENABLE_EVENT";
+ case PVRSRV_ERROR_UNABLE_TO_REGISTER_EVENT: return "PVRSRV_ERROR_UNABLE_TO_REGISTER_EVENT";
+ case PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT: return "PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT";
+ case PVRSRV_ERROR_UNABLE_TO_CREATE_THREAD: return "PVRSRV_ERROR_UNABLE_TO_CREATE_THREAD";
+ case PVRSRV_ERROR_UNABLE_TO_CLOSE_THREAD: return "PVRSRV_ERROR_UNABLE_TO_CLOSE_THREAD";
+ case PVRSRV_ERROR_THREAD_READ_ERROR: return "PVRSRV_ERROR_THREAD_READ_ERROR";
+ case PVRSRV_ERROR_UNABLE_TO_REGISTER_ISR_HANDLER:return "PVRSRV_ERROR_UNABLE_TO_REGISTER_ISR_HANDLER";
+ case PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR: return "PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR";
+ case PVRSRV_ERROR_UNABLE_TO_UNINSTALL_ISR: return "PVRSRV_ERROR_UNABLE_TO_UNINSTALL_ISR";
+ case PVRSRV_ERROR_ISR_ALREADY_INSTALLED: return "PVRSRV_ERROR_ISR_ALREADY_INSTALLED";
+ case PVRSRV_ERROR_ISR_NOT_INSTALLED: return "PVRSRV_ERROR_ISR_NOT_INSTALLED";
+ case PVRSRV_ERROR_UNABLE_TO_INITIALISE_INTERRUPT:return "PVRSRV_ERROR_UNABLE_TO_INITIALISE_INTERRUPT";
+ case PVRSRV_ERROR_UNABLE_TO_RETRIEVE_INFO: return "PVRSRV_ERROR_UNABLE_TO_RETRIEVE_INFO";
+ case PVRSRV_ERROR_UNABLE_TO_DO_BACKWARDS_BLIT: return "PVRSRV_ERROR_UNABLE_TO_DO_BACKWARDS_BLIT";
+ case PVRSRV_ERROR_UNABLE_TO_CLOSE_SERVICES: return "PVRSRV_ERROR_UNABLE_TO_CLOSE_SERVICES";
+ case PVRSRV_ERROR_UNABLE_TO_REGISTER_CONTEXT: return "PVRSRV_ERROR_UNABLE_TO_REGISTER_CONTEXT";
+ case PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE: return "PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE";
+
+ case PVRSRV_ERROR_INVALID_CCB_COMMAND: return "PVRSRV_ERROR_INVALID_CCB_COMMAND";
+
+ case PVRSRV_ERROR_UNABLE_TO_LOCK_RESOURCE: return "PVRSRV_ERROR_UNABLE_TO_LOCK_RESOURCE";
+ case PVRSRV_ERROR_INVALID_LOCK_ID: return "PVRSRV_ERROR_INVALID_LOCK_ID";
+ case PVRSRV_ERROR_RESOURCE_NOT_LOCKED: return "PVRSRV_ERROR_RESOURCE_NOT_LOCKED";
+
+ case PVRSRV_ERROR_FLIP_FAILED: return "PVRSRV_ERROR_FLIP_FAILED";
+ case PVRSRV_ERROR_UNBLANK_DISPLAY_FAILED: return "PVRSRV_ERROR_UNBLANK_DISPLAY_FAILED";
+
+ case PVRSRV_ERROR_TIMEOUT_POLLING_FOR_VALUE: return "PVRSRV_ERROR_TIMEOUT_POLLING_FOR_VALUE";
+
+ case PVRSRV_ERROR_CREATE_RENDER_CONTEXT_FAILED: return "PVRSRV_ERROR_CREATE_RENDER_CONTEXT_FAILED";
+ case PVRSRV_ERROR_UNKNOWN_PRIMARY_FRAG: return "PVRSRV_ERROR_UNKNOWN_PRIMARY_FRAG";
+ case PVRSRV_ERROR_UNEXPECTED_SECONDARY_FRAG: return "PVRSRV_ERROR_UNEXPECTED_SECONDARY_FRAG";
+ case PVRSRV_ERROR_UNEXPECTED_PRIMARY_FRAG: return "PVRSRV_ERROR_UNEXPECTED_PRIMARY_FRAG";
+
+ case PVRSRV_ERROR_UNABLE_TO_INSERT_FENCE_ID: return "PVRSRV_ERROR_UNABLE_TO_INSERT_FENCE_ID";
+
+ case PVRSRV_ERROR_BLIT_SETUP_FAILED: return "PVRSRV_ERROR_BLIT_SETUP_FAILED";
+
+ case PVRSRV_ERROR_PDUMP_NOT_AVAILABLE: return "PVRSRV_ERROR_PDUMP_NOT_AVAILABLE";
+ case PVRSRV_ERROR_PDUMP_BUFFER_FULL: return "PVRSRV_ERROR_PDUMP_BUFFER_FULL";
+ case PVRSRV_ERROR_PDUMP_BUF_OVERFLOW: return "PVRSRV_ERROR_PDUMP_BUF_OVERFLOW";
+ case PVRSRV_ERROR_PDUMP_NOT_ACTIVE: return "PVRSRV_ERROR_PDUMP_NOT_ACTIVE";
+ case PVRSRV_ERROR_INCOMPLETE_LINE_OVERLAPS_PAGES:return "PVRSRV_ERROR_INCOMPLETE_LINE_OVERLAPS_PAGES";
+
+ case PVRSRV_ERROR_MUTEX_DESTROY_FAILED: return "PVRSRV_ERROR_MUTEX_DESTROY_FAILED";
+ case PVRSRV_ERROR_MUTEX_INTERRUPTIBLE_ERROR: return "PVRSRV_ERROR_MUTEX_INTERRUPTIBLE_ERROR";
+
+ case PVRSRV_ERROR_INSUFFICIENT_SCRIPT_SPACE: return "PVRSRV_ERROR_INSUFFICIENT_SCRIPT_SPACE";
+ case PVRSRV_ERROR_INSUFFICIENT_SPACE_FOR_COMMAND:return "PVRSRV_ERROR_INSUFFICIENT_SPACE_FOR_COMMAND";
+
+ case PVRSRV_ERROR_PROCESS_NOT_INITIALISED: return "PVRSRV_ERROR_PROCESS_NOT_INITIALISED";
+ case PVRSRV_ERROR_PROCESS_NOT_FOUND: return "PVRSRV_ERROR_PROCESS_NOT_FOUND";
+ case PVRSRV_ERROR_SRV_CONNECT_FAILED: return "PVRSRV_ERROR_SRV_CONNECT_FAILED";
+ case PVRSRV_ERROR_SRV_DISCONNECT_FAILED: return "PVRSRV_ERROR_SRV_DISCONNECT_FAILED";
+ case PVRSRV_ERROR_DEINT_PHASE_FAILED: return "PVRSRV_ERROR_DEINT_PHASE_FAILED";
+ case PVRSRV_ERROR_INIT2_PHASE_FAILED: return "PVRSRV_ERROR_INIT2_PHASE_FAILED";
+
+ case PVRSRV_ERROR_NO_DC_DEVICES_FOUND: return "PVRSRV_ERROR_NO_DC_DEVICES_FOUND";
+ case PVRSRV_ERROR_UNABLE_TO_OPEN_DC_DEVICE: return "PVRSRV_ERROR_UNABLE_TO_OPEN_DC_DEVICE";
+ case PVRSRV_ERROR_UNABLE_TO_REMOVE_DEVICE: return "PVRSRV_ERROR_UNABLE_TO_REMOVE_DEVICE";
+ case PVRSRV_ERROR_NO_DEVICEDATA_FOUND: return "PVRSRV_ERROR_NO_DEVICEDATA_FOUND";
+ case PVRSRV_ERROR_NO_DEVICENODE_FOUND: return "PVRSRV_ERROR_NO_DEVICENODE_FOUND";
+ case PVRSRV_ERROR_NO_CLIENTNODE_FOUND: return "PVRSRV_ERROR_NO_CLIENTNODE_FOUND";
+ case PVRSRV_ERROR_FAILED_TO_PROCESS_QUEUE: return "PVRSRV_ERROR_FAILED_TO_PROCESS_QUEUE";
+
+ case PVRSRV_ERROR_UNABLE_TO_INIT_TASK: return "PVRSRV_ERROR_UNABLE_TO_INIT_TASK";
+ case PVRSRV_ERROR_UNABLE_TO_SCHEDULE_TASK: return "PVRSRV_ERROR_UNABLE_TO_SCHEDULE_TASK";
+ case PVRSRV_ERROR_UNABLE_TO_KILL_TASK: return "PVRSRV_ERROR_UNABLE_TO_KILL_TASK";
+
+ case PVRSRV_ERROR_UNABLE_TO_ENABLE_TIMER: return "PVRSRV_ERROR_UNABLE_TO_ENABLE_TIMER";
+ case PVRSRV_ERROR_UNABLE_TO_DISABLE_TIMER: return "PVRSRV_ERROR_UNABLE_TO_DISABLE_TIMER";
+ case PVRSRV_ERROR_UNABLE_TO_REMOVE_TIMER: return "PVRSRV_ERROR_UNABLE_TO_REMOVE_TIMER";
+
+ case PVRSRV_ERROR_UNKNOWN_PIXEL_FORMAT: return "PVRSRV_ERROR_UNKNOWN_PIXEL_FORMAT";
+ case PVRSRV_ERROR_UNKNOWN_SCRIPT_OPERATION: return "PVRSRV_ERROR_UNKNOWN_SCRIPT_OPERATION";
+
+ case PVRSRV_ERROR_HANDLE_INDEX_OUT_OF_RANGE: return "PVRSRV_ERROR_HANDLE_INDEX_OUT_OF_RANGE";
+ case PVRSRV_ERROR_HANDLE_NOT_ALLOCATED: return "PVRSRV_ERROR_HANDLE_NOT_ALLOCATED";
+ case PVRSRV_ERROR_HANDLE_TYPE_MISMATCH: return "PVRSRV_ERROR_HANDLE_TYPE_MISMATCH";
+ case PVRSRV_ERROR_UNABLE_TO_ADD_HANDLE: return "PVRSRV_ERROR_UNABLE_TO_ADD_HANDLE";
+ case PVRSRV_ERROR_HANDLE_NOT_SHAREABLE: return "PVRSRV_ERROR_HANDLE_NOT_SHAREABLE";
+ case PVRSRV_ERROR_HANDLE_NOT_FOUND: return "PVRSRV_ERROR_HANDLE_NOT_FOUND";
+ case PVRSRV_ERROR_INVALID_SUBHANDLE: return "PVRSRV_ERROR_INVALID_SUBHANDLE";
+ case PVRSRV_ERROR_HANDLE_BATCH_IN_USE: return "PVRSRV_ERROR_HANDLE_BATCH_IN_USE";
+ case PVRSRV_ERROR_HANDLE_BATCH_COMMIT_FAILURE: return "PVRSRV_ERROR_HANDLE_BATCH_COMMIT_FAILURE";
+
+ case PVRSRV_ERROR_UNABLE_TO_CREATE_HASH_TABLE: return "PVRSRV_ERROR_UNABLE_TO_CREATE_HASH_TABLE";
+ case PVRSRV_ERROR_INSERT_HASH_TABLE_DATA_FAILED:return "PVRSRV_ERROR_INSERT_HASH_TABLE_DATA_FAILED";
+
+ case PVRSRV_ERROR_UNSUPPORTED_BACKING_STORE: return "PVRSRV_ERROR_UNSUPPORTED_BACKING_STORE";
+ case PVRSRV_ERROR_UNABLE_TO_DESTROY_BM_HEAP: return "PVRSRV_ERROR_UNABLE_TO_DESTROY_BM_HEAP";
+
+ case PVRSRV_ERROR_UNKNOWN_INIT_SERVER_STATE: return "PVRSRV_ERROR_UNKNOWN_INIT_SERVER_STATE";
+
+ case PVRSRV_ERROR_NO_FREE_DEVICEIDS_AVALIABLE: return "PVRSRV_ERROR_NO_FREE_DEVICEIDS_AVALIABLE";
+ case PVRSRV_ERROR_INVALID_DEVICEID: return "PVRSRV_ERROR_INVALID_DEVICEID";
+ case PVRSRV_ERROR_DEVICEID_NOT_FOUND: return "PVRSRV_ERROR_DEVICEID_NOT_FOUND";
+
+ case PVRSRV_ERROR_MEMORY_TEST_FAILED: return "PVRSRV_ERROR_MEMORY_TEST_FAILED";
+ case PVRSRV_ERROR_CPUPADDR_TEST_FAILED: return "PVRSRV_ERROR_CPUPADDR_TEST_FAILED";
+ case PVRSRV_ERROR_COPY_TEST_FAILED: return "PVRSRV_ERROR_COPY_TEST_FAILED";
+
+ case PVRSRV_ERROR_SEMAPHORE_NOT_INITIALISED: return "PVRSRV_ERROR_SEMAPHORE_NOT_INITIALISED";
+
+ case PVRSRV_ERROR_UNABLE_TO_RELEASE_CLOCK: return "PVRSRV_ERROR_UNABLE_TO_RELEASE_CLOCK";
+ case PVRSRV_ERROR_CLOCK_REQUEST_FAILED: return "PVRSRV_ERROR_CLOCK_REQUEST_FAILED";
+ case PVRSRV_ERROR_DISABLE_CLOCK_FAILURE: return "PVRSRV_ERROR_DISABLE_CLOCK_FAILURE";
+ case PVRSRV_ERROR_UNABLE_TO_SET_CLOCK_RATE: return "PVRSRV_ERROR_UNABLE_TO_SET_CLOCK_RATE";
+ case PVRSRV_ERROR_UNABLE_TO_ROUND_CLOCK_RATE: return "PVRSRV_ERROR_UNABLE_TO_ROUND_CLOCK_RATE";
+ case PVRSRV_ERROR_UNABLE_TO_ENABLE_CLOCK: return "PVRSRV_ERROR_UNABLE_TO_ENABLE_CLOCK";
+ case PVRSRV_ERROR_UNABLE_TO_GET_CLOCK: return "PVRSRV_ERROR_UNABLE_TO_GET_CLOCK";
+ case PVRSRV_ERROR_UNABLE_TO_GET_PARENT_CLOCK: return "PVRSRV_ERROR_UNABLE_TO_GET_PARENT_CLOCK";
+ case PVRSRV_ERROR_UNABLE_TO_GET_SYSTEM_CLOCK: return "PVRSRV_ERROR_UNABLE_TO_GET_SYSTEM_CLOCK";
+
+ case PVRSRV_ERROR_UNKNOWN_SGL_ERROR: return "PVRSRV_ERROR_UNKNOWN_SGL_ERROR";
+ case PVRSRV_ERROR_BAD_SYNC_STATE: return "PVRSRV_ERROR_BAD_SYNC_STATE";
+
+ case PVRSRV_ERROR_FORCE_I32: return "PVRSRV_ERROR_FORCE_I32";
+
+ default:
+ return "Unknown PVRSRV error number";
+ }
+
+#if defined (__cplusplus)
+}
+#endif
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#if !defined (__SERVICESINT_H__)
+#define __SERVICESINT_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include <linux/types.h>
+
+#include "services.h"
+#include "sysinfo.h"
+
+#define HWREC_DEFAULT_TIMEOUT (500)
+
+#define DRIVERNAME_MAXLENGTH (100)
+
+#define ALIGNSIZE(size, alignshift) (((size) + ((1UL << (alignshift))-1)) & ~((1UL << (alignshift))-1))
+
+#ifndef MAX
+#define MAX(a,b) max(a,b)
+#endif
+#ifndef MIN
+#define MIN(a,b) min(a,b)
+#endif
+
+
+typedef enum _PVRSRV_MEMTYPE_
+{
+ PVRSRV_MEMTYPE_UNKNOWN = 0,
+ PVRSRV_MEMTYPE_DEVICE = 1,
+ PVRSRV_MEMTYPE_DEVICECLASS = 2,
+ PVRSRV_MEMTYPE_WRAPPED = 3,
+ PVRSRV_MEMTYPE_MAPPED = 4,
+} PVRSRV_MEMTYPE;
+
+typedef struct _PVRSRV_KERNEL_MEM_INFO_
+{
+
+ IMG_PVOID pvLinAddrKM;
+
+
+ IMG_DEV_VIRTADDR sDevVAddr;
+
+
+ IMG_UINT32 ui32Flags;
+
+
+ IMG_SIZE_T ui32AllocSize;
+
+
+ PVRSRV_MEMBLK sMemBlk;
+
+
+ IMG_PVOID pvSysBackupBuffer;
+
+
+ IMG_UINT32 ui32RefCount;
+
+
+ IMG_BOOL bPendingFree;
+
+
+#if defined(SUPPORT_MEMINFO_IDS)
+ #if !defined(USE_CODE)
+
+ IMG_UINT64 ui64Stamp;
+ #else
+ IMG_UINT32 dummy1;
+ IMG_UINT32 dummy2;
+ #endif
+#endif
+
+
+ struct _PVRSRV_KERNEL_SYNC_INFO_ *psKernelSyncInfo;
+
+ PVRSRV_MEMTYPE memType;
+} PVRSRV_KERNEL_MEM_INFO;
+
+
+typedef struct _PVRSRV_KERNEL_SYNC_INFO_
+{
+
+ PVRSRV_SYNC_DATA *psSyncData;
+
+
+ IMG_DEV_VIRTADDR sWriteOpsCompleteDevVAddr;
+
+
+ IMG_DEV_VIRTADDR sReadOpsCompleteDevVAddr;
+
+
+ PVRSRV_KERNEL_MEM_INFO *psSyncDataMemInfoKM;
+
+
+
+ IMG_UINT32 ui32RefCount;
+
+
+ IMG_HANDLE hResItem;
+
+#ifdef CONFIG_PVR_TRACE_CMD
+ struct list_head link;
+ unsigned long counter_digest;
+#endif
+} PVRSRV_KERNEL_SYNC_INFO;
+
+typedef struct _PVRSRV_DEVICE_SYNC_OBJECT_
+{
+
+ IMG_UINT32 ui32ReadOpsPendingVal;
+ IMG_DEV_VIRTADDR sReadOpsCompleteDevVAddr;
+ IMG_UINT32 ui32WriteOpsPendingVal;
+ IMG_DEV_VIRTADDR sWriteOpsCompleteDevVAddr;
+} PVRSRV_DEVICE_SYNC_OBJECT;
+
+typedef struct _PVRSRV_SYNC_OBJECT
+{
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfoKM;
+ IMG_UINT32 ui32WriteOpsPending;
+ IMG_UINT32 ui32ReadOpsPending;
+
+}PVRSRV_SYNC_OBJECT, *PPVRSRV_SYNC_OBJECT;
+
+typedef struct _PVRSRV_COMMAND
+{
+ IMG_SIZE_T ui32CmdSize;
+ IMG_UINT32 ui32DevIndex;
+ IMG_UINT32 CommandType;
+ IMG_UINT32 ui32DstSyncCount;
+ IMG_UINT32 ui32SrcSyncCount;
+ PVRSRV_SYNC_OBJECT *psDstSync;
+ PVRSRV_SYNC_OBJECT *psSrcSync;
+ IMG_SIZE_T ui32DataSize;
+ IMG_UINT32 ui32ProcessID;
+ IMG_VOID *pvData;
+}PVRSRV_COMMAND, *PPVRSRV_COMMAND;
+
+
+typedef struct _PVRSRV_QUEUE_INFO_
+{
+ IMG_VOID *pvLinQueueKM;
+ IMG_VOID *pvLinQueueUM;
+ volatile IMG_SIZE_T ui32ReadOffset;
+ volatile IMG_SIZE_T ui32WriteOffset;
+ IMG_UINT32 *pui32KickerAddrKM;
+ IMG_UINT32 *pui32KickerAddrUM;
+ IMG_SIZE_T ui32QueueSize;
+
+ IMG_UINT32 ui32ProcessID;
+
+ IMG_HANDLE hMemBlock[2];
+
+ struct _PVRSRV_QUEUE_INFO_ *psNextKM;
+}PVRSRV_QUEUE_INFO;
+
+typedef PVRSRV_ERROR (*PFN_INSERT_CMD) (PVRSRV_QUEUE_INFO*,
+ PVRSRV_COMMAND**,
+ IMG_UINT32,
+ IMG_UINT16,
+ IMG_UINT32,
+ PVRSRV_KERNEL_SYNC_INFO*[],
+ IMG_UINT32,
+ PVRSRV_KERNEL_SYNC_INFO*[],
+ IMG_UINT32);
+typedef PVRSRV_ERROR (*PFN_SUBMIT_CMD) (PVRSRV_QUEUE_INFO*, PVRSRV_COMMAND*, IMG_BOOL);
+
+
+typedef struct PVRSRV_DEVICECLASS_BUFFER_TAG
+{
+ PFN_GET_BUFFER_ADDR pfnGetBufferAddr;
+ IMG_HANDLE hDevMemContext;
+ IMG_HANDLE hExtDevice;
+ IMG_HANDLE hExtBuffer;
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+
+} PVRSRV_DEVICECLASS_BUFFER;
+
+
+typedef struct PVRSRV_CLIENT_DEVICECLASS_INFO_TAG
+{
+ IMG_HANDLE hDeviceKM;
+ IMG_HANDLE hServices;
+} PVRSRV_CLIENT_DEVICECLASS_INFO;
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVGetWriteOpsPending)
+#endif
+static INLINE
+IMG_UINT32 PVRSRVGetWriteOpsPending(PVRSRV_KERNEL_SYNC_INFO *psSyncInfo, IMG_BOOL bIsReadOp)
+{
+ IMG_UINT32 ui32WriteOpsPending;
+
+ if(bIsReadOp)
+ {
+ ui32WriteOpsPending = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+ else
+ {
+
+
+
+ ui32WriteOpsPending = psSyncInfo->psSyncData->ui32WriteOpsPending++;
+ }
+
+ return ui32WriteOpsPending;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVGetReadOpsPending)
+#endif
+static INLINE
+IMG_UINT32 PVRSRVGetReadOpsPending(PVRSRV_KERNEL_SYNC_INFO *psSyncInfo, IMG_BOOL bIsReadOp)
+{
+ IMG_UINT32 ui32ReadOpsPending;
+
+ if(bIsReadOp)
+ {
+ ui32ReadOpsPending = psSyncInfo->psSyncData->ui32ReadOpsPending++;
+ }
+ else
+ {
+ ui32ReadOpsPending = psSyncInfo->psSyncData->ui32ReadOpsPending;
+ }
+
+ return ui32ReadOpsPending;
+}
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVQueueCommand(IMG_HANDLE hQueueInfo,
+ PVRSRV_COMMAND *psCommand);
+
+
+
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV
+PVRSRVGetMMUContextPDDevPAddr(const PVRSRV_CONNECTION *psConnection,
+ IMG_HANDLE hDevMemContext,
+ IMG_DEV_PHYADDR *sPDDevPAddr);
+
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV
+PVRSRVAllocSharedSysMem(const PVRSRV_CONNECTION *psConnection,
+ IMG_UINT32 ui32Flags,
+ IMG_SIZE_T ui32Size,
+ PVRSRV_CLIENT_MEM_INFO **ppsClientMemInfo);
+
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV
+PVRSRVFreeSharedSysMem(const PVRSRV_CONNECTION *psConnection,
+ PVRSRV_CLIENT_MEM_INFO *psClientMemInfo);
+
+IMG_IMPORT PVRSRV_ERROR
+PVRSRVUnrefSharedSysMem(const PVRSRV_CONNECTION *psConnection,
+ PVRSRV_CLIENT_MEM_INFO *psClientMemInfo);
+
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV
+PVRSRVMapMemInfoMem(const PVRSRV_CONNECTION *psConnection,
+ IMG_HANDLE hKernelMemInfo,
+ PVRSRV_CLIENT_MEM_INFO **ppsClientMemInfo);
+
+#if defined(PVRSRV_RESOURCE_PROFILING)
+PVRSRV_KERNEL_MEM_INFO* PVRSRVGetMapMemInfo(IMG_VOID *psMap);
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#if !defined(__SGX_BRIDGE_H__)
+#define __SGX_BRIDGE_H__
+
+#include "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "pvr_bridge.h"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+
+#define PVRSRV_BRIDGE_SGX_CMD_BASE (PVRSRV_BRIDGE_LAST_NON_DEVICE_CMD+1)
+#define PVRSRV_BRIDGE_SGX_GETCLIENTINFO PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+0)
+#define PVRSRV_BRIDGE_SGX_RELEASECLIENTINFO PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+1)
+#define PVRSRV_BRIDGE_SGX_GETINTERNALDEVINFO PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+2)
+#define PVRSRV_BRIDGE_SGX_DOKICK PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+3)
+#define PVRSRV_BRIDGE_SGX_GETPHYSPAGEADDR PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+4)
+#define PVRSRV_BRIDGE_SGX_READREGISTRYDWORD PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+5)
+
+#define PVRSRV_BRIDGE_SGX_2DQUERYBLTSCOMPLETE PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+9)
+
+#define PVRSRV_BRIDGE_SGX_GETMMUPDADDR PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+10)
+
+#if defined(TRANSFER_QUEUE)
+#define PVRSRV_BRIDGE_SGX_SUBMITTRANSFER PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+13)
+#endif
+#define PVRSRV_BRIDGE_SGX_GETMISCINFO PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+14)
+#define PVRSRV_BRIDGE_SGXINFO_FOR_SRVINIT PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+15)
+#define PVRSRV_BRIDGE_SGX_DEVINITPART2 PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+16)
+
+#define PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+17)
+#define PVRSRV_BRIDGE_SGX_UNREFSHAREDPBDESC PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+18)
+#define PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+19)
+#define PVRSRV_BRIDGE_SGX_REGISTER_HW_RENDER_CONTEXT PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+20)
+#define PVRSRV_BRIDGE_SGX_FLUSH_HW_RENDER_TARGET PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+21)
+#define PVRSRV_BRIDGE_SGX_UNREGISTER_HW_RENDER_CONTEXT PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+22)
+#if defined(SGX_FEATURE_2D_HARDWARE)
+#define PVRSRV_BRIDGE_SGX_SUBMIT2D PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+23)
+#define PVRSRV_BRIDGE_SGX_REGISTER_HW_2D_CONTEXT PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+24)
+#define PVRSRV_BRIDGE_SGX_UNREGISTER_HW_2D_CONTEXT PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+25)
+#endif
+#define PVRSRV_BRIDGE_SGX_REGISTER_HW_TRANSFER_CONTEXT PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+26)
+#define PVRSRV_BRIDGE_SGX_UNREGISTER_HW_TRANSFER_CONTEXT PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+27)
+
+#define PVRSRV_BRIDGE_SGX_SCHEDULE_PROCESS_QUEUES PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+28)
+
+#define PVRSRV_BRIDGE_SGX_READ_HWPERF_CB PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+30)
+
+#if defined(PDUMP)
+#define PVRSRV_BRIDGE_SGX_PDUMP_BUFFER_ARRAY PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+31)
+#define PVRSRV_BRIDGE_SGX_PDUMP_3D_SIGNATURE_REGISTERS PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+32)
+#define PVRSRV_BRIDGE_SGX_PDUMP_COUNTER_REGISTERS PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+33)
+#define PVRSRV_BRIDGE_SGX_PDUMP_TA_SIGNATURE_REGISTERS PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+34)
+#define PVRSRV_BRIDGE_SGX_PDUMP_HWPERFCB PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+35)
+#define PVRSRV_BRIDGE_SGX_PDUMP_SAVEMEM PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+36)
+#endif
+
+
+
+#define PVRSRV_BRIDGE_LAST_SGX_CMD (PVRSRV_BRIDGE_SGX_CMD_BASE+36)
+
+
+typedef struct PVRSRV_BRIDGE_IN_GETPHYSPAGEADDR
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevMemHeap;
+ IMG_DEV_VIRTADDR sDevVAddr;
+}PVRSRV_BRIDGE_IN_GETPHYSPAGEADDR;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GETPHYSPAGEADDR
+{
+ PVRSRV_ERROR eError;
+ IMG_DEV_PHYADDR DevPAddr;
+ IMG_CPU_PHYADDR CpuPAddr;
+}PVRSRV_BRIDGE_OUT_GETPHYSPAGEADDR;
+
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_GETMMU_PDADDR_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_HANDLE hDevMemContext;
+}PVRSRV_BRIDGE_IN_SGX_GETMMU_PDADDR;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_SGX_GETMMU_PDADDR_TAG
+{
+ IMG_DEV_PHYADDR sPDDevPAddr;
+ PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_SGX_GETMMU_PDADDR;
+
+
+typedef struct PVRSRV_BRIDGE_IN_GETCLIENTINFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+}PVRSRV_BRIDGE_IN_GETCLIENTINFO;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GETINTERNALDEVINFO_TAG
+{
+ SGX_INTERNAL_DEVINFO sSGXInternalDevInfo;
+ PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_GETINTERNALDEVINFO;
+
+
+typedef struct PVRSRV_BRIDGE_IN_GETINTERNALDEVINFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+}PVRSRV_BRIDGE_IN_GETINTERNALDEVINFO;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_GETCLIENTINFO_TAG
+{
+ SGX_CLIENT_INFO sClientInfo;
+ PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_GETCLIENTINFO;
+
+
+typedef struct PVRSRV_BRIDGE_IN_RELEASECLIENTINFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ SGX_CLIENT_INFO sClientInfo;
+}PVRSRV_BRIDGE_IN_RELEASECLIENTINFO;
+
+
+typedef struct PVRSRV_BRIDGE_IN_ISPBREAKPOLL_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+}PVRSRV_BRIDGE_IN_ISPBREAKPOLL;
+
+
+typedef struct PVRSRV_BRIDGE_IN_DOKICK_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ SGX_CCB_KICK sCCBKick;
+}PVRSRV_BRIDGE_IN_DOKICK;
+
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_SCHEDULE_PROCESS_QUEUES_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+}PVRSRV_BRIDGE_IN_SGX_SCHEDULE_PROCESS_QUEUES;
+
+
+#if defined(TRANSFER_QUEUE)
+
+typedef struct PVRSRV_BRIDGE_IN_SUBMITTRANSFER_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ PVRSRV_TRANSFER_SGX_KICK sKick;
+}PVRSRV_BRIDGE_IN_SUBMITTRANSFER;
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+
+typedef struct PVRSRV_BRIDGE_IN_SUBMIT2D_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ PVRSRV_2D_SGX_KICK sKick;
+} PVRSRV_BRIDGE_IN_SUBMIT2D;
+#endif
+#endif
+
+
+typedef struct PVRSRV_BRIDGE_IN_READREGDWORD_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_PCHAR pszKey;
+ IMG_PCHAR pszValue;
+}PVRSRV_BRIDGE_IN_READREGDWORD;
+
+
+typedef struct PVRSRV_BRIDGE_OUT_READREGDWORD_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32Data;
+}PVRSRV_BRIDGE_OUT_READREGDWORD;
+
+
+typedef struct PVRSRV_BRIDGE_IN_SGXGETMISCINFO_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ SGX_MISC_INFO *psMiscInfo;
+}PVRSRV_BRIDGE_IN_SGXGETMISCINFO;
+
+typedef struct PVRSRV_BRIDGE_IN_SGXINFO_FOR_SRVINIT_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+}PVRSRV_BRIDGE_IN_SGXINFO_FOR_SRVINIT;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGXINFO_FOR_SRVINIT_TAG
+{
+ PVRSRV_ERROR eError;
+ SGX_BRIDGE_INFO_FOR_SRVINIT sInitInfo;
+}PVRSRV_BRIDGE_OUT_SGXINFO_FOR_SRVINIT;
+
+typedef struct PVRSRV_BRIDGE_IN_SGXDEVINITPART2_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ SGX_BRIDGE_INIT_INFO sInitInfo;
+}PVRSRV_BRIDGE_IN_SGXDEVINITPART2;
+
+
+typedef struct PVRSRV_BRIDGE_IN_2DQUERYBLTSCOMPLETE_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_HANDLE hKernSyncInfo;
+ IMG_BOOL bWaitForComplete;
+}PVRSRV_BRIDGE_IN_2DQUERYBLTSCOMPLETE;
+
+
+#define PVRSRV_BRIDGE_SGX_SHAREDPBDESC_MAX_SUBMEMINFOS 10
+
+typedef struct PVRSRV_BRIDGE_IN_SGXFINDSHAREDPBDESC_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_BOOL bLockOnFailure;
+ IMG_UINT32 ui32TotalPBSize;
+}PVRSRV_BRIDGE_IN_SGXFINDSHAREDPBDESC;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGXFINDSHAREDPBDESC_TAG
+{
+ IMG_HANDLE hKernelMemInfo;
+ IMG_HANDLE hSharedPBDesc;
+ IMG_HANDLE hSharedPBDescKernelMemInfoHandle;
+ IMG_HANDLE hHWPBDescKernelMemInfoHandle;
+ IMG_HANDLE hBlockKernelMemInfoHandle;
+ IMG_HANDLE hHWBlockKernelMemInfoHandle;
+ IMG_HANDLE ahSharedPBDescSubKernelMemInfoHandles[PVRSRV_BRIDGE_SGX_SHAREDPBDESC_MAX_SUBMEMINFOS];
+ IMG_UINT32 ui32SharedPBDescSubKernelMemInfoHandlesCount;
+ PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_SGXFINDSHAREDPBDESC;
+
+typedef struct PVRSRV_BRIDGE_IN_SGXUNREFSHAREDPBDESC_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hSharedPBDesc;
+}PVRSRV_BRIDGE_IN_SGXUNREFSHAREDPBDESC;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGXUNREFSHAREDPBDESC_TAG
+{
+ PVRSRV_ERROR eError;
+}PVRSRV_BRIDGE_OUT_SGXUNREFSHAREDPBDESC;
+
+
+typedef struct PVRSRV_BRIDGE_IN_SGXADDSHAREDPBDESC_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_HANDLE hSharedPBDescKernelMemInfo;
+ IMG_HANDLE hHWPBDescKernelMemInfo;
+ IMG_HANDLE hBlockKernelMemInfo;
+ IMG_HANDLE hHWBlockKernelMemInfo;
+ IMG_UINT32 ui32TotalPBSize;
+ IMG_HANDLE *phKernelMemInfoHandles;
+ IMG_UINT32 ui32KernelMemInfoHandlesCount;
+}PVRSRV_BRIDGE_IN_SGXADDSHAREDPBDESC;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGXADDSHAREDPBDESC_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hSharedPBDesc;
+}PVRSRV_BRIDGE_OUT_SGXADDSHAREDPBDESC;
+
+
+#ifdef PDUMP
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_BUFFER_ARRAY_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ SGX_KICKTA_DUMP_BUFFER *psBufferArray;
+ IMG_UINT32 ui32BufferArrayLength;
+ IMG_BOOL bDumpPolls;
+} PVRSRV_BRIDGE_IN_PDUMP_BUFFER_ARRAY;
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_3D_SIGNATURE_REGISTERS_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_UINT32 ui32DumpFrameNum;
+ IMG_BOOL bLastFrame;
+ IMG_UINT32 *pui32Registers;
+ IMG_UINT32 ui32NumRegisters;
+}PVRSRV_BRIDGE_IN_PDUMP_3D_SIGNATURE_REGISTERS;
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMPCOUNTER_REGISTERS_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_UINT32 ui32DumpFrameNum;
+ IMG_BOOL bLastFrame;
+ IMG_UINT32 *pui32Registers;
+ IMG_UINT32 ui32NumRegisters;
+}PVRSRV_BRIDGE_IN_PDUMP_COUNTER_REGISTERS;
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_TA_SIGNATURE_REGISTERS_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_UINT32 ui32DumpFrameNum;
+ IMG_UINT32 ui32TAKickCount;
+ IMG_BOOL bLastFrame;
+ IMG_UINT32 *pui32Registers;
+ IMG_UINT32 ui32NumRegisters;
+}PVRSRV_BRIDGE_IN_PDUMP_TA_SIGNATURE_REGISTERS;
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_HWPERFCB_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_CHAR szFileName[PVRSRV_PDUMP_MAX_FILENAME_SIZE];
+ IMG_UINT32 ui32FileOffset;
+ IMG_UINT32 ui32PDumpFlags;
+
+}PVRSRV_BRIDGE_IN_PDUMP_HWPERFCB;
+
+typedef struct PVRSRV_BRIDGE_IN_PDUMP_SAVEMEM
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_CHAR szFileName[PVRSRV_PDUMP_MAX_FILENAME_SIZE];
+ IMG_UINT32 ui32FileOffset;
+ IMG_DEV_VIRTADDR sDevVAddr;
+ IMG_UINT32 ui32Size;
+ IMG_UINT32 ui32DataMaster;
+ IMG_UINT32 ui32PDumpFlags;
+
+}PVRSRV_BRIDGE_IN_PDUMP_SAVEMEM;
+
+#endif
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_RENDER_CONTEXT_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_DEV_VIRTADDR sHWRenderContextDevVAddr;
+}PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_RENDER_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_RENDER_CONTEXT_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hHWRenderContext;
+}PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_RENDER_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_RENDER_CONTEXT_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_HANDLE hHWRenderContext;
+}PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_RENDER_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_TRANSFER_CONTEXT_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_DEV_VIRTADDR sHWTransferContextDevVAddr;
+}PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_TRANSFER_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_TRANSFER_CONTEXT_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hHWTransferContext;
+}PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_TRANSFER_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_TRANSFER_CONTEXT_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_HANDLE hHWTransferContext;
+}PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_TRANSFER_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_FLUSH_HW_RENDER_TARGET_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_DEV_VIRTADDR sHWRTDataSetDevVAddr;
+}PVRSRV_BRIDGE_IN_SGX_FLUSH_HW_RENDER_TARGET;
+
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+typedef struct PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_2D_CONTEXT_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_DEV_VIRTADDR sHW2DContextDevVAddr;
+}PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_2D_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_2D_CONTEXT_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hHW2DContext;
+}PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_2D_CONTEXT;
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_2D_CONTEXT_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_HANDLE hHW2DContext;
+}PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_2D_CONTEXT;
+
+#define SGX2D_MAX_BLT_CMD_SIZ 256
+#endif
+
+
+typedef struct PVRSRV_BRIDGE_IN_SGX_READ_HWPERF_CB_TAG
+{
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_HANDLE hDevCookie;
+ IMG_UINT32 ui32ArraySize;
+ PVRSRV_SGX_HWPERF_CB_ENTRY *psHWPerfCBData;
+} PVRSRV_BRIDGE_IN_SGX_READ_HWPERF_CB;
+
+typedef struct PVRSRV_BRIDGE_OUT_SGX_READ_HWPERF_CB_TAG
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32DataCount;
+ IMG_UINT32 ui32ClockSpeed;
+ IMG_UINT32 ui32HostTimeStamp;
+} PVRSRV_BRIDGE_OUT_SGX_READ_HWPERF_CB;
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#if !defined (__SGX_MKIF_KM_H__)
+#define __SGX_MKIF_KM_H__
+
+#include "img_types.h"
+#include "servicesint.h"
+#include "sgxapi_km.h"
+
+
+#if defined(SGX_FEATURE_MP)
+ #define SGX_REG_BANK_SHIFT (12)
+ #define SGX_REG_BANK_SIZE (0x4000)
+ #if defined(SGX541)
+ #define SGX_REG_BANK_BASE_INDEX (1)
+ #define SGX_REG_BANK_MASTER_INDEX (SGX_REG_BANK_BASE_INDEX + SGX_FEATURE_MP_CORE_COUNT)
+ #else
+ #define SGX_REG_BANK_BASE_INDEX (2)
+ #define SGX_REG_BANK_MASTER_INDEX (1)
+ #endif
+ #define SGX_MP_CORE_SELECT(x,i) (x + ((i + SGX_REG_BANK_BASE_INDEX) * SGX_REG_BANK_SIZE))
+ #define SGX_MP_MASTER_SELECT(x) (x + (SGX_REG_BANK_MASTER_INDEX * SGX_REG_BANK_SIZE))
+#else
+ #define SGX_MP_CORE_SELECT(x,i) (x)
+#endif
+
+
+typedef struct _SGXMKIF_COMMAND_
+{
+ IMG_UINT32 ui32ServiceAddress;
+ IMG_UINT32 ui32CacheControl;
+ IMG_UINT32 ui32Data[4];
+ IMG_UINT32 ui32Padding[2];
+} SGXMKIF_COMMAND;
+
+
+typedef struct _PVRSRV_SGX_KERNEL_CCB_
+{
+ SGXMKIF_COMMAND asCommands[256];
+} PVRSRV_SGX_KERNEL_CCB;
+
+
+typedef struct _PVRSRV_SGX_CCB_CTL_
+{
+ IMG_UINT32 ui32WriteOffset;
+ IMG_UINT32 ui32ReadOffset;
+} PVRSRV_SGX_CCB_CTL;
+
+
+typedef struct _SGXMKIF_HOST_CTL_
+{
+#if defined(PVRSRV_USSE_EDM_BREAKPOINTS)
+ IMG_UINT32 ui32BreakpointDisable;
+ IMG_UINT32 ui32Continue;
+#endif
+
+ volatile IMG_UINT32 ui32InitStatus;
+ volatile IMG_UINT32 ui32PowerStatus;
+ volatile IMG_UINT32 ui32CleanupStatus;
+#if defined(FIX_HW_BRN_28889)
+ volatile IMG_UINT32 ui32InvalStatus;
+#endif
+#if defined(SUPPORT_HW_RECOVERY)
+ IMG_UINT32 ui32uKernelDetectedLockups;
+ IMG_UINT32 ui32HostDetectedLockups;
+ IMG_UINT32 ui32HWRecoverySampleRate;
+#endif
+ IMG_UINT32 ui32uKernelTimerClock;
+ IMG_UINT32 ui32ActivePowManSampleRate;
+ IMG_UINT32 ui32InterruptFlags;
+ IMG_UINT32 ui32InterruptClearFlags;
+ IMG_UINT32 ui32BPSetClearSignal;
+
+ IMG_UINT32 ui32NumActivePowerEvents;
+
+ IMG_UINT32 ui32TimeWraps;
+ IMG_UINT32 ui32HostClock;
+
+#if defined(SGX_FEATURE_EXTENDED_PERF_COUNTERS)
+ IMG_UINT32 aui32PerfGroup[PVRSRV_SGX_HWPERF_NUM_COUNTERS];
+ IMG_UINT32 aui32PerfBit[PVRSRV_SGX_HWPERF_NUM_COUNTERS];
+#else
+ IMG_UINT32 ui32PerfGroup;
+#endif
+} SGXMKIF_HOST_CTL;
+
+#define SGXMKIF_CMDTA_CTRLFLAGS_READY 0x00000001
+typedef struct _SGXMKIF_CMDTA_SHARED_
+{
+ IMG_UINT32 ui32CtrlFlags;
+
+ IMG_UINT32 ui32NumTAStatusVals;
+ IMG_UINT32 ui32Num3DStatusVals;
+
+
+ IMG_UINT32 ui32TATQSyncWriteOpsPendingVal;
+ IMG_DEV_VIRTADDR sTATQSyncWriteOpsCompleteDevVAddr;
+ IMG_UINT32 ui32TATQSyncReadOpsPendingVal;
+ IMG_DEV_VIRTADDR sTATQSyncReadOpsCompleteDevVAddr;
+
+
+ IMG_UINT32 ui323DTQSyncWriteOpsPendingVal;
+ IMG_DEV_VIRTADDR s3DTQSyncWriteOpsCompleteDevVAddr;
+ IMG_UINT32 ui323DTQSyncReadOpsPendingVal;
+ IMG_DEV_VIRTADDR s3DTQSyncReadOpsCompleteDevVAddr;
+
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+
+ IMG_UINT32 ui32NumTASrcSyncs;
+ PVRSRV_DEVICE_SYNC_OBJECT asTASrcSyncs[SGX_MAX_TA_SRC_SYNCS];
+ IMG_UINT32 ui32NumTADstSyncs;
+ PVRSRV_DEVICE_SYNC_OBJECT asTADstSyncs[SGX_MAX_TA_DST_SYNCS];
+ IMG_UINT32 ui32Num3DSrcSyncs;
+ PVRSRV_DEVICE_SYNC_OBJECT as3DSrcSyncs[SGX_MAX_3D_SRC_SYNCS];
+#else
+
+ IMG_UINT32 ui32NumSrcSyncs;
+ PVRSRV_DEVICE_SYNC_OBJECT asSrcSyncs[SGX_MAX_SRC_SYNCS];
+#endif
+
+
+ PVRSRV_DEVICE_SYNC_OBJECT sTA3DDependency;
+
+ CTL_STATUS sCtlTAStatusInfo[SGX_MAX_TA_STATUS_VALS];
+ CTL_STATUS sCtl3DStatusInfo[SGX_MAX_3D_STATUS_VALS];
+
+} SGXMKIF_CMDTA_SHARED;
+
+#define SGXTQ_MAX_STATUS SGX_MAX_TRANSFER_STATUS_VALS + 2
+
+#define SGXMKIF_TQFLAGS_NOSYNCUPDATE 0x00000001
+#define SGXMKIF_TQFLAGS_KEEPPENDING 0x00000002
+#define SGXMKIF_TQFLAGS_TATQ_SYNC 0x00000004
+#define SGXMKIF_TQFLAGS_3DTQ_SYNC 0x00000008
+#if defined(SGX_FEATURE_FAST_RENDER_CONTEXT_SWITCH)
+#define SGXMKIF_TQFLAGS_CTXSWITCH 0x00000010
+#endif
+#define SGXMKIF_TQFLAGS_DUMMYTRANSFER 0x00000020
+
+typedef struct _SGXMKIF_TRANSFERCMD_SHARED_
+{
+
+
+ IMG_UINT32 ui32NumSrcSyncs;
+ PVRSRV_DEVICE_SYNC_OBJECT asSrcSyncs[SGX_MAX_SRC_SYNCS];
+
+
+ IMG_UINT32 ui32NumDstSyncs;
+ PVRSRV_DEVICE_SYNC_OBJECT asDstSyncs[SGX_MAX_DST_SYNCS];
+
+ IMG_UINT32 ui32DstReadOpPendingVal;
+ IMG_DEV_VIRTADDR sDstReadOpsCompleteDevAddr;
+
+ IMG_UINT32 ui32DstWriteOpPendingVal;
+ IMG_DEV_VIRTADDR sDstWriteOpsCompleteDevAddr;
+
+
+ IMG_UINT32 ui32TASyncWriteOpsPendingVal;
+ IMG_DEV_VIRTADDR sTASyncWriteOpsCompleteDevVAddr;
+ IMG_UINT32 ui32TASyncReadOpsPendingVal;
+ IMG_DEV_VIRTADDR sTASyncReadOpsCompleteDevVAddr;
+
+
+ IMG_UINT32 ui323DSyncWriteOpsPendingVal;
+ IMG_DEV_VIRTADDR s3DSyncWriteOpsCompleteDevVAddr;
+ IMG_UINT32 ui323DSyncReadOpsPendingVal;
+ IMG_DEV_VIRTADDR s3DSyncReadOpsCompleteDevVAddr;
+
+ IMG_UINT32 ui32NumStatusVals;
+ CTL_STATUS sCtlStatusInfo[SGXTQ_MAX_STATUS];
+} SGXMKIF_TRANSFERCMD_SHARED, *PSGXMKIF_TRANSFERCMD_SHARED;
+
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+typedef struct _SGXMKIF_2DCMD_SHARED_ {
+
+ IMG_UINT32 ui32NumSrcSync;
+ PVRSRV_DEVICE_SYNC_OBJECT sSrcSyncData[SGX_MAX_2D_SRC_SYNC_OPS];
+
+
+ PVRSRV_DEVICE_SYNC_OBJECT sDstSyncData;
+
+
+ PVRSRV_DEVICE_SYNC_OBJECT sTASyncData;
+
+
+ PVRSRV_DEVICE_SYNC_OBJECT s3DSyncData;
+} SGXMKIF_2DCMD_SHARED, *PSGXMKIF_2DCMD_SHARED;
+#endif
+
+
+typedef struct _SGXMKIF_HWDEVICE_SYNC_LIST_
+{
+ IMG_DEV_VIRTADDR sAccessDevAddr;
+ IMG_UINT32 ui32NumSyncObjects;
+
+ PVRSRV_DEVICE_SYNC_OBJECT asSyncData[1];
+} SGXMKIF_HWDEVICE_SYNC_LIST, *PSGXMKIF_HWDEVICE_SYNC_LIST;
+
+
+#define PVRSRV_USSE_EDM_INIT_COMPLETE (1UL << 0)
+
+#define PVRSRV_USSE_EDM_POWMAN_IDLE_COMPLETE (1UL << 2)
+#define PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE (1UL << 3)
+#define PVRSRV_USSE_EDM_POWMAN_POWEROFF_RESTART_IMMEDIATE (1UL << 4)
+#define PVRSRV_USSE_EDM_POWMAN_NO_WORK (1UL << 5)
+
+#define PVRSRV_USSE_EDM_INTERRUPT_HWR (1UL << 0)
+#define PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER (1UL << 1)
+
+#define PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE (1UL << 0)
+
+#if defined(FIX_HW_BRN_28889)
+#define PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE (1UL << 0)
+#endif
+
+#define PVRSRV_USSE_MISCINFO_READY 0x1UL
+#define PVRSRV_USSE_MISCINFO_GET_STRUCT_SIZES 0x2UL
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+#define PVRSRV_USSE_MISCINFO_MEMREAD 0x4UL
+#define PVRSRV_USSE_MISCINFO_MEMWRITE 0x8UL
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+#define PVRSRV_USSE_MISCINFO_MEMREAD_FAIL 0x1UL << 31
+#endif
+#endif
+
+
+#define PVRSRV_CLEANUPCMD_RT 0x1
+#define PVRSRV_CLEANUPCMD_RC 0x2
+#define PVRSRV_CLEANUPCMD_TC 0x3
+#define PVRSRV_CLEANUPCMD_2DC 0x4
+#define PVRSRV_CLEANUPCMD_PB 0x5
+
+#define PVRSRV_POWERCMD_POWEROFF 0x1
+#define PVRSRV_POWERCMD_IDLE 0x2
+#define PVRSRV_POWERCMD_RESUME 0x3
+
+
+#if defined(SGX_FEATURE_BIF_NUM_DIRLISTS)
+#define SGX_BIF_DIR_LIST_INDEX_EDM (SGX_FEATURE_BIF_NUM_DIRLISTS - 1)
+#else
+#define SGX_BIF_DIR_LIST_INDEX_EDM (0)
+#endif
+
+#define SGXMKIF_CC_INVAL_BIF_PT 0x1
+#define SGXMKIF_CC_INVAL_BIF_PD 0x2
+#define SGXMKIF_CC_INVAL_BIF_SL 0x4
+#define SGXMKIF_CC_INVAL_DATA 0x8
+
+
+typedef struct _SGX_MISCINFO_STRUCT_SIZES_
+{
+#if defined (SGX_FEATURE_2D_HARDWARE)
+ IMG_UINT32 ui32Sizeof_2DCMD;
+ IMG_UINT32 ui32Sizeof_2DCMD_SHARED;
+#endif
+ IMG_UINT32 ui32Sizeof_CMDTA;
+ IMG_UINT32 ui32Sizeof_CMDTA_SHARED;
+ IMG_UINT32 ui32Sizeof_TRANSFERCMD;
+ IMG_UINT32 ui32Sizeof_TRANSFERCMD_SHARED;
+ IMG_UINT32 ui32Sizeof_3DREGISTERS;
+ IMG_UINT32 ui32Sizeof_HWPBDESC;
+ IMG_UINT32 ui32Sizeof_HWRENDERCONTEXT;
+ IMG_UINT32 ui32Sizeof_HWRENDERDETAILS;
+ IMG_UINT32 ui32Sizeof_HWRTDATA;
+ IMG_UINT32 ui32Sizeof_HWRTDATASET;
+ IMG_UINT32 ui32Sizeof_HWTRANSFERCONTEXT;
+ IMG_UINT32 ui32Sizeof_HOST_CTL;
+ IMG_UINT32 ui32Sizeof_COMMAND;
+} SGX_MISCINFO_STRUCT_SIZES;
+
+
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+typedef struct _PVRSRV_SGX_MISCINFO_MEMACCESS
+{
+ IMG_DEV_VIRTADDR sDevVAddr;
+ IMG_DEV_PHYADDR sPDDevPAddr;
+} PVRSRV_SGX_MISCINFO_MEMACCESS;
+#endif
+
+typedef struct _PVRSRV_SGX_MISCINFO_INFO
+{
+ IMG_UINT32 ui32MiscInfoFlags;
+ PVRSRV_SGX_MISCINFO_FEATURES sSGXFeatures;
+ SGX_MISCINFO_STRUCT_SIZES sSGXStructSizes;
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+ PVRSRV_SGX_MISCINFO_MEMACCESS sSGXMemAccessSrc;
+ PVRSRV_SGX_MISCINFO_MEMACCESS sSGXMemAccessDest;
+#endif
+} PVRSRV_SGX_MISCINFO_INFO;
+
+#ifdef PVRSRV_USSE_EDM_STATUS_DEBUG
+#define SGXMK_TRACE_BUFFER_SIZE 512
+#endif
+
+#define SGXMKIF_HWPERF_CB_SIZE 0x100
+
+typedef struct _SGXMKIF_HWPERF_CB_ENTRY_
+{
+ IMG_UINT32 ui32FrameNo;
+ IMG_UINT32 ui32Type;
+ IMG_UINT32 ui32Ordinal;
+ IMG_UINT32 ui32Info;
+ IMG_UINT32 ui32TimeWraps;
+ IMG_UINT32 ui32Time;
+ IMG_UINT32 ui32Counters[SGX_FEATURE_MP_CORE_COUNT][PVRSRV_SGX_HWPERF_NUM_COUNTERS];
+} SGXMKIF_HWPERF_CB_ENTRY;
+
+typedef struct _SGXMKIF_HWPERF_CB_
+{
+ IMG_UINT32 ui32Woff;
+ IMG_UINT32 ui32Roff;
+ IMG_UINT32 ui32Ordinal;
+ SGXMKIF_HWPERF_CB_ENTRY psHWPerfCBData[SGXMKIF_HWPERF_CB_SIZE];
+} SGXMKIF_HWPERF_CB;
+
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#if !defined (__SGXINFO_H__)
+#define __SGXINFO_H__
+
+#include "sgxscript.h"
+#include "servicesint.h"
+#include "services.h"
+#include "sgxapi_km.h"
+#include "sgx_mkif_km.h"
+
+
+#define SGX_MAX_DEV_DATA 24
+#define SGX_MAX_INIT_MEM_HANDLES 16
+
+
+typedef struct _SGX_BRIDGE_INFO_FOR_SRVINIT
+{
+ IMG_DEV_PHYADDR sPDDevPAddr;
+ PVRSRV_HEAP_INFO asHeapInfo[PVRSRV_MAX_CLIENT_HEAPS];
+} SGX_BRIDGE_INFO_FOR_SRVINIT;
+
+
+typedef enum _SGXMKIF_CMD_TYPE_
+{
+ SGXMKIF_CMD_TA = 0,
+ SGXMKIF_CMD_TRANSFER = 1,
+ SGXMKIF_CMD_2D = 2,
+ SGXMKIF_CMD_POWER = 3,
+ SGXMKIF_CMD_CLEANUP = 4,
+ SGXMKIF_CMD_GETMISCINFO = 5,
+ SGXMKIF_CMD_PROCESS_QUEUES = 6,
+ SGXMKIF_CMD_DATABREAKPOINT = 7,
+ SGXMKIF_CMD_SETHWPERFSTATUS = 8,
+ SGXMKIF_CMD_MAX = 9,
+
+ SGXMKIF_CMD_FORCE_I32 = -1,
+
+} SGXMKIF_CMD_TYPE;
+
+
+typedef struct _SGX_BRIDGE_INIT_INFO_
+{
+ IMG_HANDLE hKernelCCBMemInfo;
+ IMG_HANDLE hKernelCCBCtlMemInfo;
+ IMG_HANDLE hKernelCCBEventKickerMemInfo;
+ IMG_HANDLE hKernelSGXHostCtlMemInfo;
+ IMG_HANDLE hKernelSGXTA3DCtlMemInfo;
+ IMG_HANDLE hKernelSGXMiscMemInfo;
+
+ IMG_UINT32 aui32HostKickAddr[SGXMKIF_CMD_MAX];
+
+ SGX_INIT_SCRIPTS sScripts;
+
+ IMG_UINT32 ui32ClientBuildOptions;
+ SGX_MISCINFO_STRUCT_SIZES sSGXStructSizes;
+
+#if defined(SGX_SUPPORT_HWPROFILING)
+ IMG_HANDLE hKernelHWProfilingMemInfo;
+#endif
+#if defined(SUPPORT_SGX_HWPERF)
+ IMG_HANDLE hKernelHWPerfCBMemInfo;
+#endif
+ IMG_HANDLE hKernelTASigBufferMemInfo;
+ IMG_HANDLE hKernel3DSigBufferMemInfo;
+
+#if defined(FIX_HW_BRN_29702)
+ IMG_HANDLE hKernelCFIMemInfo;
+#endif
+#if defined(FIX_HW_BRN_29823)
+ IMG_HANDLE hKernelDummyTermStreamMemInfo;
+#endif
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+ IMG_HANDLE hKernelEDMStatusBufferMemInfo;
+#endif
+#if defined(SGX_FEATURE_OVERLAPPED_SPM)
+ IMG_HANDLE hKernelTmpRgnHeaderMemInfo;
+#endif
+#if defined(SGX_FEATURE_SPM_MODE_0)
+ IMG_HANDLE hKernelTmpDPMStateMemInfo;
+#endif
+
+ IMG_UINT32 ui32EDMTaskReg0;
+ IMG_UINT32 ui32EDMTaskReg1;
+
+ IMG_UINT32 ui32ClkGateStatusReg;
+ IMG_UINT32 ui32ClkGateStatusMask;
+#if defined(SGX_FEATURE_MP)
+ IMG_UINT32 ui32MasterClkGateStatusReg;
+ IMG_UINT32 ui32MasterClkGateStatusMask;
+ IMG_UINT32 ui32MasterClkGateStatus2Reg;
+ IMG_UINT32 ui32MasterClkGateStatus2Mask;
+#endif
+
+ IMG_UINT32 ui32CacheControl;
+
+ IMG_UINT32 asInitDevData[SGX_MAX_DEV_DATA];
+ IMG_HANDLE asInitMemHandles[SGX_MAX_INIT_MEM_HANDLES];
+
+} SGX_BRIDGE_INIT_INFO;
+
+
+typedef struct _SGX_DEVICE_SYNC_LIST_
+{
+ PSGXMKIF_HWDEVICE_SYNC_LIST psHWDeviceSyncList;
+
+ IMG_HANDLE hKernelHWSyncListMemInfo;
+ PVRSRV_CLIENT_MEM_INFO *psHWDeviceSyncListClientMemInfo;
+ PVRSRV_CLIENT_MEM_INFO *psAccessResourceClientMemInfo;
+
+ volatile IMG_UINT32 *pui32Lock;
+
+ struct _SGX_DEVICE_SYNC_LIST_ *psNext;
+
+
+ IMG_UINT32 ui32NumSyncObjects;
+ IMG_HANDLE ahSyncHandles[1];
+} SGX_DEVICE_SYNC_LIST, *PSGX_DEVICE_SYNC_LIST;
+
+
+typedef struct _SGX_INTERNEL_STATUS_UPDATE_
+{
+ CTL_STATUS sCtlStatus;
+ IMG_HANDLE hKernelMemInfo;
+} SGX_INTERNEL_STATUS_UPDATE;
+
+
+typedef struct _SGX_CCB_KICK_
+{
+ SGXMKIF_COMMAND sCommand;
+ IMG_HANDLE hCCBKernelMemInfo;
+
+ IMG_UINT32 ui32NumDstSyncObjects;
+ IMG_HANDLE hKernelHWSyncListMemInfo;
+
+
+ IMG_HANDLE *pahDstSyncHandles;
+
+ IMG_UINT32 ui32NumTAStatusVals;
+ IMG_UINT32 ui32Num3DStatusVals;
+
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+ SGX_INTERNEL_STATUS_UPDATE asTAStatusUpdate[SGX_MAX_TA_STATUS_VALS];
+ SGX_INTERNEL_STATUS_UPDATE as3DStatusUpdate[SGX_MAX_3D_STATUS_VALS];
+#else
+ IMG_HANDLE ahTAStatusSyncInfo[SGX_MAX_TA_STATUS_VALS];
+ IMG_HANDLE ah3DStatusSyncInfo[SGX_MAX_3D_STATUS_VALS];
+#endif
+
+ IMG_BOOL bFirstKickOrResume;
+#if (defined(NO_HARDWARE) || defined(PDUMP))
+ IMG_BOOL bTerminateOrAbort;
+#endif
+ IMG_BOOL bLastInScene;
+
+
+ IMG_UINT32 ui32CCBOffset;
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+
+ IMG_UINT32 ui32NumTASrcSyncs;
+ IMG_HANDLE ahTASrcKernelSyncInfo[SGX_MAX_TA_SRC_SYNCS];
+ IMG_UINT32 ui32NumTADstSyncs;
+ IMG_HANDLE ahTADstKernelSyncInfo[SGX_MAX_TA_DST_SYNCS];
+ IMG_UINT32 ui32Num3DSrcSyncs;
+ IMG_HANDLE ah3DSrcKernelSyncInfo[SGX_MAX_3D_SRC_SYNCS];
+#else
+
+ IMG_UINT32 ui32NumSrcSyncs;
+ IMG_HANDLE ahSrcKernelSyncInfo[SGX_MAX_SRC_SYNCS];
+#endif
+
+
+ IMG_BOOL bTADependency;
+ IMG_HANDLE hTA3DSyncInfo;
+
+ IMG_HANDLE hTASyncInfo;
+ IMG_HANDLE h3DSyncInfo;
+#if defined(PDUMP)
+ IMG_UINT32 ui32CCBDumpWOff;
+#endif
+#if defined(NO_HARDWARE)
+ IMG_UINT32 ui32WriteOpsPendingVal;
+#endif
+} SGX_CCB_KICK;
+
+
+#define SGX_KERNEL_USE_CODE_BASE_INDEX 15
+
+
+typedef struct _SGX_CLIENT_INFO_
+{
+ IMG_UINT32 ui32ProcessID;
+ IMG_VOID *pvProcess;
+ PVRSRV_MISC_INFO sMiscInfo;
+
+ IMG_UINT32 asDevData[SGX_MAX_DEV_DATA];
+
+} SGX_CLIENT_INFO;
+
+typedef struct _SGX_INTERNAL_DEVINFO_
+{
+ IMG_UINT32 ui32Flags;
+ IMG_HANDLE hHostCtlKernelMemInfoHandle;
+ IMG_BOOL bForcePTOff;
+} SGX_INTERNAL_DEVINFO;
+
+
+#if defined(TRANSFER_QUEUE)
+typedef struct _PVRSRV_TRANSFER_SGX_KICK_
+{
+ IMG_HANDLE hCCBMemInfo;
+ IMG_UINT32 ui32SharedCmdCCBOffset;
+
+ IMG_DEV_VIRTADDR sHWTransferContextDevVAddr;
+
+ IMG_HANDLE hTASyncInfo;
+ IMG_HANDLE h3DSyncInfo;
+
+ IMG_UINT32 ui32NumSrcSync;
+ IMG_HANDLE ahSrcSyncInfo[SGX_MAX_TRANSFER_SYNC_OPS];
+
+ IMG_UINT32 ui32NumDstSync;
+ IMG_HANDLE ahDstSyncInfo[SGX_MAX_TRANSFER_SYNC_OPS];
+
+ IMG_UINT32 ui32Flags;
+
+ IMG_UINT32 ui32PDumpFlags;
+#if defined(PDUMP)
+ IMG_UINT32 ui32CCBDumpWOff;
+#endif
+} PVRSRV_TRANSFER_SGX_KICK, *PPVRSRV_TRANSFER_SGX_KICK;
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+typedef struct _PVRSRV_2D_SGX_KICK_
+{
+ IMG_HANDLE hCCBMemInfo;
+ IMG_UINT32 ui32SharedCmdCCBOffset;
+
+ IMG_DEV_VIRTADDR sHW2DContextDevVAddr;
+
+ IMG_UINT32 ui32NumSrcSync;
+ IMG_HANDLE ahSrcSyncInfo[SGX_MAX_2D_SRC_SYNC_OPS];
+
+
+ IMG_HANDLE hDstSyncInfo;
+
+
+ IMG_HANDLE hTASyncInfo;
+
+
+ IMG_HANDLE h3DSyncInfo;
+
+ IMG_UINT32 ui32PDumpFlags;
+#if defined(PDUMP)
+ IMG_UINT32 ui32CCBDumpWOff;
+#endif
+} PVRSRV_2D_SGX_KICK, *PPVRSRV_2D_SGX_KICK;
+#endif
+#endif
+
+
+#endif
--- /dev/null
+bin_pc_i686*
+tmp_pc_i686*
+host_pc_i686*
+*.o
+*.o.cmd
--- /dev/null
+/**********************************************************************
+ *
+ * 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 <stddef.h>
+
+#include "img_defs.h"
+#include "services.h"
+#include "pvr_bridge_km.h"
+#include "pvr_debug.h"
+#include "ra.h"
+#include "pvr_bridge.h"
+#if defined(SUPPORT_SGX)
+#include "sgx_bridge.h"
+#endif
+#if defined(SUPPORT_VGX)
+#include "vgx_bridge.h"
+#endif
+#if defined(SUPPORT_MSVDX)
+#include "msvdx_bridge.h"
+#endif
+#include "perproc.h"
+#include "device.h"
+#include "buffer_manager.h"
+
+#include "pdump_km.h"
+#include "syscommon.h"
+
+#include "bridged_pvr_bridge.h"
+#if defined(SUPPORT_SGX)
+#include "bridged_sgx_bridge.h"
+#endif
+#if defined(SUPPORT_VGX)
+#include "bridged_vgx_bridge.h"
+#endif
+#if defined(SUPPORT_MSVDX)
+#include "bridged_msvdx_bridge.h"
+#endif
+
+#include "env_data.h"
+
+#if defined (__linux__)
+#include "mmap.h"
+#endif
+
+#include "psb_intel_display.h" /* mdfld__intel_plane_set_alpha() */
+
+#include "srvkm.h"
+
+PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY g_BridgeDispatchTable[BRIDGE_DISPATCH_TABLE_ENTRY_COUNT];
+
+#if defined(DEBUG_BRIDGE_KM)
+PVRSRV_BRIDGE_GLOBAL_STATS g_BridgeGlobalStats;
+#endif
+
+#if defined(PVR_SECURE_HANDLES)
+static IMG_BOOL abSharedDeviceMemHeap[PVRSRV_MAX_CLIENT_HEAPS];
+static IMG_BOOL *pbSharedDeviceMemHeap = abSharedDeviceMemHeap;
+#else
+static IMG_BOOL *pbSharedDeviceMemHeap = (IMG_BOOL*)IMG_NULL;
+#endif
+
+
+#if defined(DEBUG_BRIDGE_KM)
+PVRSRV_ERROR
+CopyFromUserWrapper(PVRSRV_PER_PROCESS_DATA *pProcData,
+ IMG_UINT32 ui32BridgeID,
+ IMG_VOID *pvDest,
+ IMG_VOID *pvSrc,
+ IMG_UINT32 ui32Size)
+{
+ g_BridgeDispatchTable[ui32BridgeID].ui32CopyFromUserTotalBytes+=ui32Size;
+ g_BridgeGlobalStats.ui32TotalCopyFromUserBytes+=ui32Size;
+ return OSCopyFromUser(pProcData, pvDest, pvSrc, ui32Size);
+}
+PVRSRV_ERROR
+CopyToUserWrapper(PVRSRV_PER_PROCESS_DATA *pProcData,
+ IMG_UINT32 ui32BridgeID,
+ IMG_VOID *pvDest,
+ IMG_VOID *pvSrc,
+ IMG_UINT32 ui32Size)
+{
+ g_BridgeDispatchTable[ui32BridgeID].ui32CopyToUserTotalBytes+=ui32Size;
+ g_BridgeGlobalStats.ui32TotalCopyToUserBytes+=ui32Size;
+ return OSCopyToUser(pProcData, pvDest, pvSrc, ui32Size);
+}
+#endif
+
+
+static IMG_INT
+PVRSRVEnumerateDevicesBW(IMG_UINT32 ui32BridgeID,
+ IMG_VOID *psBridgeIn,
+ PVRSRV_BRIDGE_OUT_ENUMDEVICE *psEnumDeviceOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ENUM_DEVICES);
+
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+ PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+
+ psEnumDeviceOUT->eError =
+ PVRSRVEnumerateDevicesKM(&psEnumDeviceOUT->ui32NumDevices,
+ psEnumDeviceOUT->asDeviceIdentifier);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVAcquireDeviceDataBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_ACQUIRE_DEVICEINFO *psAcquireDevInfoIN,
+ PVRSRV_BRIDGE_OUT_ACQUIRE_DEVICEINFO *psAcquireDevInfoOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ACQUIRE_DEVICEINFO);
+
+ psAcquireDevInfoOUT->eError =
+ PVRSRVAcquireDeviceDataKM(psAcquireDevInfoIN->uiDevIndex,
+ psAcquireDevInfoIN->eDeviceType,
+ &hDevCookieInt);
+ if(psAcquireDevInfoOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ psAcquireDevInfoOUT->eError =
+ PVRSRVAllocHandle(psPerProc->psHandleBase,
+ &psAcquireDevInfoOUT->hDevCookie,
+ hDevCookieInt,
+ PVRSRV_HANDLE_TYPE_DEV_NODE,
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVCreateDeviceMemContextBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_CREATE_DEVMEMCONTEXT *psCreateDevMemContextIN,
+ PVRSRV_BRIDGE_OUT_CREATE_DEVMEMCONTEXT *psCreateDevMemContextOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_HANDLE hDevMemContextInt;
+ IMG_UINT32 i;
+ IMG_BOOL bCreated;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CREATE_DEVMEMCONTEXT);
+
+
+ NEW_HANDLE_BATCH_OR_ERROR(psCreateDevMemContextOUT->eError, psPerProc, PVRSRV_MAX_CLIENT_HEAPS + 1);
+
+ psCreateDevMemContextOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psCreateDevMemContextIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psCreateDevMemContextOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psCreateDevMemContextOUT->eError =
+ PVRSRVCreateDeviceMemContextKM(hDevCookieInt,
+ psPerProc,
+ &hDevMemContextInt,
+ &psCreateDevMemContextOUT->ui32ClientHeapCount,
+ &psCreateDevMemContextOUT->sHeapInfo[0],
+ &bCreated,
+ pbSharedDeviceMemHeap);
+
+ if(psCreateDevMemContextOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ if(bCreated)
+ {
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psCreateDevMemContextOUT->hDevMemContext,
+ hDevMemContextInt,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+ }
+ else
+ {
+ psCreateDevMemContextOUT->eError =
+ PVRSRVFindHandle(psPerProc->psHandleBase,
+ &psCreateDevMemContextOUT->hDevMemContext,
+ hDevMemContextInt,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+ if(psCreateDevMemContextOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ for(i = 0; i < psCreateDevMemContextOUT->ui32ClientHeapCount; i++)
+ {
+ IMG_HANDLE hDevMemHeapExt;
+
+#if defined(PVR_SECURE_HANDLES)
+ if(abSharedDeviceMemHeap[i])
+#endif
+ {
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase, &hDevMemHeapExt,
+ psCreateDevMemContextOUT->sHeapInfo[i].hDevMemHeap,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+ }
+#if defined(PVR_SECURE_HANDLES)
+ else
+ {
+
+ if(bCreated)
+ {
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase, &hDevMemHeapExt,
+ psCreateDevMemContextOUT->sHeapInfo[i].hDevMemHeap,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+ psCreateDevMemContextOUT->hDevMemContext);
+ }
+ else
+ {
+ psCreateDevMemContextOUT->eError =
+ PVRSRVFindHandle(psPerProc->psHandleBase, &hDevMemHeapExt,
+ psCreateDevMemContextOUT->sHeapInfo[i].hDevMemHeap,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP);
+ if(psCreateDevMemContextOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+ }
+#endif
+ psCreateDevMemContextOUT->sHeapInfo[i].hDevMemHeap = hDevMemHeapExt;
+ }
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psCreateDevMemContextOUT->eError, psPerProc);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVDestroyDeviceMemContextBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DESTROY_DEVMEMCONTEXT *psDestroyDevMemContextIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_HANDLE hDevMemContextInt;
+ IMG_BOOL bDestroyed;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DESTROY_DEVMEMCONTEXT);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psDestroyDevMemContextIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevMemContextInt,
+ psDestroyDevMemContextIN->hDevMemContext,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVDestroyDeviceMemContextKM(hDevCookieInt, hDevMemContextInt, &bDestroyed);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ if(bDestroyed)
+ {
+ psRetOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psDestroyDevMemContextIN->hDevMemContext,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+ }
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVGetDeviceMemHeapInfoBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GET_DEVMEM_HEAPINFO *psGetDevMemHeapInfoIN,
+ PVRSRV_BRIDGE_OUT_GET_DEVMEM_HEAPINFO *psGetDevMemHeapInfoOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_HANDLE hDevMemContextInt;
+ IMG_UINT32 i;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_DEVMEM_HEAPINFO);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psGetDevMemHeapInfoOUT->eError, psPerProc, PVRSRV_MAX_CLIENT_HEAPS);
+
+ psGetDevMemHeapInfoOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psGetDevMemHeapInfoIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psGetDevMemHeapInfoOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psGetDevMemHeapInfoOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevMemContextInt,
+ psGetDevMemHeapInfoIN->hDevMemContext,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+ if(psGetDevMemHeapInfoOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psGetDevMemHeapInfoOUT->eError =
+ PVRSRVGetDeviceMemHeapInfoKM(hDevCookieInt,
+ hDevMemContextInt,
+ &psGetDevMemHeapInfoOUT->ui32ClientHeapCount,
+ &psGetDevMemHeapInfoOUT->sHeapInfo[0],
+ pbSharedDeviceMemHeap);
+
+ if(psGetDevMemHeapInfoOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ for(i = 0; i < psGetDevMemHeapInfoOUT->ui32ClientHeapCount; i++)
+ {
+ IMG_HANDLE hDevMemHeapExt;
+
+#if defined(PVR_SECURE_HANDLES)
+ if(abSharedDeviceMemHeap[i])
+#endif
+ {
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase, &hDevMemHeapExt,
+ psGetDevMemHeapInfoOUT->sHeapInfo[i].hDevMemHeap,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+ }
+#if defined(PVR_SECURE_HANDLES)
+ else
+ {
+
+ psGetDevMemHeapInfoOUT->eError =
+ PVRSRVFindHandle(psPerProc->psHandleBase, &hDevMemHeapExt,
+ psGetDevMemHeapInfoOUT->sHeapInfo[i].hDevMemHeap,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP);
+ if(psGetDevMemHeapInfoOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+#endif
+ psGetDevMemHeapInfoOUT->sHeapInfo[i].hDevMemHeap = hDevMemHeapExt;
+ }
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psGetDevMemHeapInfoOUT->eError, psPerProc);
+
+ return 0;
+}
+
+
+#if defined(OS_PVRSRV_ALLOC_DEVICE_MEM_BW)
+IMG_INT
+PVRSRVAllocDeviceMemBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_ALLOCDEVICEMEM *psAllocDeviceMemIN,
+ PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM *psAllocDeviceMemOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc);
+#else
+static IMG_INT
+PVRSRVAllocDeviceMemBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_ALLOCDEVICEMEM *psAllocDeviceMemIN,
+ PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM *psAllocDeviceMemOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+ IMG_HANDLE hDevCookieInt;
+ IMG_HANDLE hDevMemHeapInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ALLOC_DEVICEMEM);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psAllocDeviceMemOUT->eError, psPerProc, 2);
+
+ psAllocDeviceMemOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psAllocDeviceMemIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psAllocDeviceMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psAllocDeviceMemOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevMemHeapInt,
+ psAllocDeviceMemIN->hDevMemHeap,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP);
+
+ if(psAllocDeviceMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psAllocDeviceMemOUT->eError =
+ PVRSRVAllocDeviceMemKM(hDevCookieInt,
+ psPerProc,
+ hDevMemHeapInt,
+ psAllocDeviceMemIN->ui32Attribs,
+ psAllocDeviceMemIN->ui32Size,
+ psAllocDeviceMemIN->ui32Alignment,
+ &psMemInfo,
+ "" );
+
+ if(psAllocDeviceMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ OSMemSet(&psAllocDeviceMemOUT->sClientMemInfo,
+ 0,
+ sizeof(psAllocDeviceMemOUT->sClientMemInfo));
+
+ psAllocDeviceMemOUT->sClientMemInfo.pvLinAddrKM =
+ psMemInfo->pvLinAddrKM;
+
+#if defined (__linux__)
+ psAllocDeviceMemOUT->sClientMemInfo.pvLinAddr = 0;
+#else
+ psAllocDeviceMemOUT->sClientMemInfo.pvLinAddr = psMemInfo->pvLinAddrKM;
+#endif
+ psAllocDeviceMemOUT->sClientMemInfo.sDevVAddr = psMemInfo->sDevVAddr;
+ psAllocDeviceMemOUT->sClientMemInfo.ui32Flags = psMemInfo->ui32Flags;
+ psAllocDeviceMemOUT->sClientMemInfo.ui32AllocSize = psMemInfo->ui32AllocSize;
+ psAllocDeviceMemOUT->sClientMemInfo.hMappingInfo = psMemInfo->sMemBlk.hOSMemHandle;
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psAllocDeviceMemOUT->sClientMemInfo.hKernelMemInfo,
+ psMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+ if(psAllocDeviceMemIN->ui32Attribs & PVRSRV_MEM_NO_SYNCOBJ)
+ {
+
+ OSMemSet(&psAllocDeviceMemOUT->sClientSyncInfo,
+ 0,
+ sizeof (PVRSRV_CLIENT_SYNC_INFO));
+ psAllocDeviceMemOUT->sClientMemInfo.psClientSyncInfo = IMG_NULL;
+ }
+ else
+ {
+
+
+ psAllocDeviceMemOUT->sClientSyncInfo.psSyncData =
+ psMemInfo->psKernelSyncInfo->psSyncData;
+ psAllocDeviceMemOUT->sClientSyncInfo.sWriteOpsCompleteDevVAddr =
+ psMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
+ psAllocDeviceMemOUT->sClientSyncInfo.sReadOpsCompleteDevVAddr =
+ psMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+
+ psAllocDeviceMemOUT->sClientSyncInfo.hMappingInfo =
+ psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle;
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psAllocDeviceMemOUT->sClientSyncInfo.hKernelSyncInfo,
+ psMemInfo->psKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+ psAllocDeviceMemOUT->sClientMemInfo.hKernelMemInfo);
+
+ psAllocDeviceMemOUT->sClientMemInfo.psClientSyncInfo =
+ &psAllocDeviceMemOUT->sClientSyncInfo;
+
+ }
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psAllocDeviceMemOUT->eError, psPerProc);
+
+ return 0;
+}
+
+#endif
+
+static IMG_INT
+PVRSRVFreeDeviceMemBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_FREEDEVICEMEM *psFreeDeviceMemIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_VOID *pvKernelMemInfo;
+
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_FREE_DEVICEMEM);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psFreeDeviceMemIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &pvKernelMemInfo,
+ psFreeDeviceMemIN->psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = PVRSRVFreeDeviceMemKM(hDevCookieInt, pvKernelMemInfo);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psFreeDeviceMemIN->psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVExportDeviceMemBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_EXPORTDEVICEMEM *psExportDeviceMemIN,
+ PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM *psExportDeviceMemOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_EXPORT_DEVICEMEM);
+
+
+ psExportDeviceMemOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psExportDeviceMemIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psExportDeviceMemOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVExportDeviceMemBW: can't find devcookie"));
+ return 0;
+ }
+
+
+ psExportDeviceMemOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, (IMG_PVOID *)&psKernelMemInfo,
+ psExportDeviceMemIN->psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ if(psExportDeviceMemOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVExportDeviceMemBW: can't find kernel meminfo"));
+ return 0;
+ }
+
+
+ psExportDeviceMemOUT->eError =
+ PVRSRVFindHandle(KERNEL_HANDLE_BASE,
+ &psExportDeviceMemOUT->hMemInfo,
+ psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(psExportDeviceMemOUT->eError == PVRSRV_OK)
+ {
+
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVExportDeviceMemBW: allocation is already exported"));
+ return 0;
+ }
+
+
+ psExportDeviceMemOUT->eError = PVRSRVAllocHandle(KERNEL_HANDLE_BASE,
+ &psExportDeviceMemOUT->hMemInfo,
+ psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+ if (psExportDeviceMemOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVExportDeviceMemBW: failed to allocate handle from global handle list"));
+ return 0;
+ }
+
+
+ psKernelMemInfo->ui32Flags |= PVRSRV_MEM_EXPORTED;
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVMapDeviceMemoryBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY *psMapDevMemIN,
+ PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY *psMapDevMemOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_KERNEL_MEM_INFO *psSrcKernelMemInfo = IMG_NULL;
+ PVRSRV_KERNEL_MEM_INFO *psDstKernelMemInfo = IMG_NULL;
+ IMG_HANDLE hDstDevMemHeap = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MAP_DEV_MEMORY);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psMapDevMemOUT->eError, psPerProc, 2);
+
+
+ psMapDevMemOUT->eError = PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
+ (IMG_VOID**)&psSrcKernelMemInfo,
+ psMapDevMemIN->hKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(psMapDevMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ psMapDevMemOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDstDevMemHeap,
+ psMapDevMemIN->hDstDevMemHeap,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP);
+ if(psMapDevMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ psMapDevMemOUT->eError = PVRSRVMapDeviceMemoryKM(psPerProc,
+ psSrcKernelMemInfo,
+ hDstDevMemHeap,
+ &psDstKernelMemInfo);
+ if(psMapDevMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ OSMemSet(&psMapDevMemOUT->sDstClientMemInfo,
+ 0,
+ sizeof(psMapDevMemOUT->sDstClientMemInfo));
+ OSMemSet(&psMapDevMemOUT->sDstClientSyncInfo,
+ 0,
+ sizeof(psMapDevMemOUT->sDstClientSyncInfo));
+
+ psMapDevMemOUT->sDstClientMemInfo.pvLinAddrKM =
+ psDstKernelMemInfo->pvLinAddrKM;
+
+ psMapDevMemOUT->sDstClientMemInfo.pvLinAddr = 0;
+ psMapDevMemOUT->sDstClientMemInfo.sDevVAddr = psDstKernelMemInfo->sDevVAddr;
+ psMapDevMemOUT->sDstClientMemInfo.ui32Flags = psDstKernelMemInfo->ui32Flags;
+ psMapDevMemOUT->sDstClientMemInfo.ui32AllocSize = psDstKernelMemInfo->ui32AllocSize;
+ psMapDevMemOUT->sDstClientMemInfo.hMappingInfo = psDstKernelMemInfo->sMemBlk.hOSMemHandle;
+
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psMapDevMemOUT->sDstClientMemInfo.hKernelMemInfo,
+ psDstKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+ psMapDevMemOUT->sDstClientSyncInfo.hKernelSyncInfo = IMG_NULL;
+
+
+ if(psDstKernelMemInfo->psKernelSyncInfo)
+ {
+ psMapDevMemOUT->sDstClientSyncInfo.psSyncData =
+ psDstKernelMemInfo->psKernelSyncInfo->psSyncData;
+ psMapDevMemOUT->sDstClientSyncInfo.sWriteOpsCompleteDevVAddr =
+ psDstKernelMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
+ psMapDevMemOUT->sDstClientSyncInfo.sReadOpsCompleteDevVAddr =
+ psDstKernelMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+
+ psMapDevMemOUT->sDstClientSyncInfo.hMappingInfo =
+ psDstKernelMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle;
+
+ psMapDevMemOUT->sDstClientMemInfo.psClientSyncInfo = &psMapDevMemOUT->sDstClientSyncInfo;
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psMapDevMemOUT->sDstClientSyncInfo.hKernelSyncInfo,
+ psDstKernelMemInfo->psKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+ psMapDevMemOUT->sDstClientMemInfo.hKernelMemInfo);
+ }
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psMapDevMemOUT->eError, psPerProc);
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVUnmapDeviceMemoryBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_UNMAP_DEV_MEMORY *psUnmapDevMemIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_UNMAP_DEV_MEMORY);
+
+ psRetOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID**)&psKernelMemInfo,
+ psUnmapDevMemIN->psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = PVRSRVUnmapDeviceMemoryKM(psKernelMemInfo);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psUnmapDevMemIN->psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ return 0;
+}
+
+
+
+static IMG_INT
+PVRSRVMapDeviceClassMemoryBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_MAP_DEVICECLASS_MEMORY *psMapDevClassMemIN,
+ PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY *psMapDevClassMemOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+ IMG_HANDLE hOSMapInfo;
+ IMG_HANDLE hDeviceClassBufferInt;
+ IMG_HANDLE hDevMemContextInt;
+ PVRSRV_HANDLE_TYPE eHandleType;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psMapDevClassMemOUT->eError, psPerProc, 2);
+
+
+ psMapDevClassMemOUT->eError =
+ PVRSRVLookupHandleAnyType(psPerProc->psHandleBase, &hDeviceClassBufferInt,
+ &eHandleType,
+ psMapDevClassMemIN->hDeviceClassBuffer);
+
+ if(psMapDevClassMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ psMapDevClassMemOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevMemContextInt,
+ psMapDevClassMemIN->hDevMemContext,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+ if(psMapDevClassMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ switch(eHandleType)
+ {
+#if defined(PVR_SECURE_HANDLES)
+ case PVRSRV_HANDLE_TYPE_DISP_BUFFER:
+ case PVRSRV_HANDLE_TYPE_BUF_BUFFER:
+#else
+ case PVRSRV_HANDLE_TYPE_NONE:
+#endif
+ break;
+ default:
+ psMapDevClassMemOUT->eError = PVRSRV_ERROR_INVALID_HANDLE_TYPE;
+ return 0;
+ }
+
+ psMapDevClassMemOUT->eError =
+ PVRSRVMapDeviceClassMemoryKM(psPerProc,
+ hDevMemContextInt,
+ hDeviceClassBufferInt,
+ &psMemInfo,
+ &hOSMapInfo);
+ if(psMapDevClassMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ OSMemSet(&psMapDevClassMemOUT->sClientMemInfo,
+ 0,
+ sizeof(psMapDevClassMemOUT->sClientMemInfo));
+ OSMemSet(&psMapDevClassMemOUT->sClientSyncInfo,
+ 0,
+ sizeof(psMapDevClassMemOUT->sClientSyncInfo));
+
+ psMapDevClassMemOUT->sClientMemInfo.pvLinAddrKM =
+ psMemInfo->pvLinAddrKM;
+
+ psMapDevClassMemOUT->sClientMemInfo.pvLinAddr = 0;
+ psMapDevClassMemOUT->sClientMemInfo.sDevVAddr = psMemInfo->sDevVAddr;
+ psMapDevClassMemOUT->sClientMemInfo.ui32Flags = psMemInfo->ui32Flags;
+ psMapDevClassMemOUT->sClientMemInfo.ui32AllocSize = psMemInfo->ui32AllocSize;
+ psMapDevClassMemOUT->sClientMemInfo.hMappingInfo = psMemInfo->sMemBlk.hOSMemHandle;
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psMapDevClassMemOUT->sClientMemInfo.hKernelMemInfo,
+ psMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+ psMapDevClassMemIN->hDeviceClassBuffer);
+
+ psMapDevClassMemOUT->sClientSyncInfo.hKernelSyncInfo = IMG_NULL;
+
+
+ if(psMemInfo->psKernelSyncInfo)
+ {
+ psMapDevClassMemOUT->sClientSyncInfo.psSyncData =
+ psMemInfo->psKernelSyncInfo->psSyncData;
+ psMapDevClassMemOUT->sClientSyncInfo.sWriteOpsCompleteDevVAddr =
+ psMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
+ psMapDevClassMemOUT->sClientSyncInfo.sReadOpsCompleteDevVAddr =
+ psMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+
+ psMapDevClassMemOUT->sClientSyncInfo.hMappingInfo =
+ psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle;
+
+ psMapDevClassMemOUT->sClientMemInfo.psClientSyncInfo = &psMapDevClassMemOUT->sClientSyncInfo;
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psMapDevClassMemOUT->sClientSyncInfo.hKernelSyncInfo,
+ psMemInfo->psKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+ psMapDevClassMemOUT->sClientMemInfo.hKernelMemInfo);
+ }
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psMapDevClassMemOUT->eError, psPerProc);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVUnmapDeviceClassMemoryBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_UNMAP_DEVICECLASS_MEMORY *psUnmapDevClassMemIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvKernelMemInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_UNMAP_DEVICECLASS_MEMORY);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &pvKernelMemInfo,
+ psUnmapDevClassMemIN->psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = PVRSRVUnmapDeviceClassMemoryKM(pvKernelMemInfo);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psUnmapDevClassMemIN->psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ return 0;
+}
+
+
+#if defined(OS_PVRSRV_WRAP_EXT_MEM_BW)
+IMG_INT
+PVRSRVWrapExtMemoryBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_WRAP_EXT_MEMORY *psWrapExtMemIN,
+ PVRSRV_BRIDGE_OUT_WRAP_EXT_MEMORY *psWrapExtMemOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc);
+#else
+static IMG_INT
+PVRSRVWrapExtMemoryBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_WRAP_EXT_MEMORY *psWrapExtMemIN,
+ PVRSRV_BRIDGE_OUT_WRAP_EXT_MEMORY *psWrapExtMemOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_HANDLE hDevMemContextInt;
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+ IMG_SYS_PHYADDR *psSysPAddr = IMG_NULL;
+ IMG_UINT32 ui32PageTableSize = 0;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_WRAP_EXT_MEMORY);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psWrapExtMemOUT->eError, psPerProc, 2);
+
+
+ psWrapExtMemOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psWrapExtMemIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psWrapExtMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ psWrapExtMemOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevMemContextInt,
+ psWrapExtMemIN->hDevMemContext,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+ if(psWrapExtMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ if(psWrapExtMemIN->ui32NumPageTableEntries)
+ {
+ ui32PageTableSize = psWrapExtMemIN->ui32NumPageTableEntries
+ * sizeof(IMG_SYS_PHYADDR);
+
+ ASSIGN_AND_EXIT_ON_ERROR(psWrapExtMemOUT->eError,
+ OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32PageTableSize,
+ (IMG_VOID **)&psSysPAddr, 0,
+ "Page Table"));
+
+ if(CopyFromUserWrapper(psPerProc,
+ ui32BridgeID,
+ psSysPAddr,
+ psWrapExtMemIN->psSysPAddr,
+ ui32PageTableSize) != PVRSRV_OK)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32PageTableSize, (IMG_VOID *)psSysPAddr, 0);
+
+ return -EFAULT;
+ }
+ }
+
+ psWrapExtMemOUT->eError =
+ PVRSRVWrapExtMemoryKM(hDevCookieInt,
+ psPerProc,
+ hDevMemContextInt,
+ psWrapExtMemIN->ui32ByteSize,
+ psWrapExtMemIN->ui32PageOffset,
+ psWrapExtMemIN->bPhysContig,
+ psSysPAddr,
+ psWrapExtMemIN->pvLinAddr,
+ psWrapExtMemIN->ui32Flags,
+ &psMemInfo);
+
+ if(psWrapExtMemIN->ui32NumPageTableEntries)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32PageTableSize,
+ (IMG_VOID *)psSysPAddr, 0);
+
+ }
+
+ if(psWrapExtMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psWrapExtMemOUT->sClientMemInfo.pvLinAddrKM =
+ psMemInfo->pvLinAddrKM;
+
+
+ psWrapExtMemOUT->sClientMemInfo.pvLinAddr = 0;
+ psWrapExtMemOUT->sClientMemInfo.sDevVAddr = psMemInfo->sDevVAddr;
+ psWrapExtMemOUT->sClientMemInfo.ui32Flags = psMemInfo->ui32Flags;
+ psWrapExtMemOUT->sClientMemInfo.ui32AllocSize = psMemInfo->ui32AllocSize;
+ psWrapExtMemOUT->sClientMemInfo.hMappingInfo = psMemInfo->sMemBlk.hOSMemHandle;
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psWrapExtMemOUT->sClientMemInfo.hKernelMemInfo,
+ psMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+
+ psWrapExtMemOUT->sClientSyncInfo.psSyncData =
+ psMemInfo->psKernelSyncInfo->psSyncData;
+ psWrapExtMemOUT->sClientSyncInfo.sWriteOpsCompleteDevVAddr =
+ psMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
+ psWrapExtMemOUT->sClientSyncInfo.sReadOpsCompleteDevVAddr =
+ psMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+
+ psWrapExtMemOUT->sClientSyncInfo.hMappingInfo =
+ psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle;
+
+ psWrapExtMemOUT->sClientMemInfo.psClientSyncInfo = &psWrapExtMemOUT->sClientSyncInfo;
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psWrapExtMemOUT->sClientSyncInfo.hKernelSyncInfo,
+ (IMG_HANDLE)psMemInfo->psKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+ psWrapExtMemOUT->sClientMemInfo.hKernelMemInfo);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psWrapExtMemOUT->eError, psPerProc);
+
+ return 0;
+}
+#endif
+
+static IMG_INT
+PVRSRVUnwrapExtMemoryBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_UNWRAP_EXT_MEMORY *psUnwrapExtMemIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvMemInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_UNWRAP_EXT_MEMORY);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvMemInfo,
+ psUnwrapExtMemIN->hKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVUnwrapExtMemoryKM((PVRSRV_KERNEL_MEM_INFO *)pvMemInfo);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psUnwrapExtMemIN->hKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVGetFreeDeviceMemBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GETFREEDEVICEMEM *psGetFreeDeviceMemIN,
+ PVRSRV_BRIDGE_OUT_GETFREEDEVICEMEM *psGetFreeDeviceMemOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GETFREE_DEVICEMEM);
+
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ psGetFreeDeviceMemOUT->eError =
+ PVRSRVGetFreeDeviceMemKM(psGetFreeDeviceMemIN->ui32Flags,
+ &psGetFreeDeviceMemOUT->ui32Total,
+ &psGetFreeDeviceMemOUT->ui32Free,
+ &psGetFreeDeviceMemOUT->ui32LargestBlock);
+
+ return 0;
+}
+
+static IMG_INT
+PVRMMapOSMemHandleToMMapDataBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_MHANDLE_TO_MMAP_DATA *psMMapDataIN,
+ PVRSRV_BRIDGE_OUT_MHANDLE_TO_MMAP_DATA *psMMapDataOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MHANDLE_TO_MMAP_DATA);
+
+#if defined (__linux__)
+ psMMapDataOUT->eError =
+ PVRMMapOSMemHandleToMMapData(psPerProc,
+ psMMapDataIN->hMHandle,
+ &psMMapDataOUT->ui32MMapOffset,
+ &psMMapDataOUT->ui32ByteOffset,
+ &psMMapDataOUT->ui32RealByteSize,
+ &psMMapDataOUT->ui32UserVAddr);
+#else
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+ PVR_UNREFERENCED_PARAMETER(psMMapDataIN);
+
+ psMMapDataOUT->eError = PVRSRV_ERROR_NOT_SUPPORTED;
+#endif
+ return 0;
+}
+
+
+static IMG_INT
+PVRMMapReleaseMMapDataBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RELEASE_MMAP_DATA *psMMapDataIN,
+ PVRSRV_BRIDGE_OUT_RELEASE_MMAP_DATA *psMMapDataOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RELEASE_MMAP_DATA);
+
+#if defined (__linux__)
+ psMMapDataOUT->eError =
+ PVRMMapReleaseMMapData(psPerProc,
+ psMMapDataIN->hMHandle,
+ &psMMapDataOUT->bMUnmap,
+ &psMMapDataOUT->ui32RealByteSize,
+ &psMMapDataOUT->ui32UserVAddr);
+#else
+
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+ PVR_UNREFERENCED_PARAMETER(psMMapDataIN);
+
+ psMMapDataOUT->eError = PVRSRV_ERROR_NOT_SUPPORTED;
+#endif
+ return 0;
+}
+
+
+#ifdef PDUMP
+static IMG_INT
+PDumpIsCaptureFrameBW(IMG_UINT32 ui32BridgeID,
+ IMG_VOID *psBridgeIn,
+ PVRSRV_BRIDGE_OUT_PDUMP_ISCAPTURING *psPDumpIsCapturingOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_ISCAPTURING);
+ PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ psPDumpIsCapturingOUT->bIsCapturing = PDumpIsCaptureFrameKM();
+ psPDumpIsCapturingOUT->eError = PVRSRV_OK;
+
+ return 0;
+}
+
+static IMG_INT
+PDumpCommentBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_COMMENT *psPDumpCommentIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_COMMENT);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ psRetOUT->eError = PDumpCommentKM(&psPDumpCommentIN->szComment[0],
+ psPDumpCommentIN->ui32Flags);
+ return 0;
+}
+
+static IMG_INT
+PDumpSetFrameBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_SETFRAME *psPDumpSetFrameIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_SETFRAME);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ psRetOUT->eError = PDumpSetFrameKM(psPDumpSetFrameIN->ui32Frame);
+
+ return 0;
+}
+
+static IMG_INT
+PDumpRegWithFlagsBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_DUMPREG *psPDumpRegDumpIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_REG);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID **)&psDeviceNode,
+ psPDumpRegDumpIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = PDumpRegWithFlagsKM (psPDumpRegDumpIN->szRegRegion,
+ psPDumpRegDumpIN->sHWReg.ui32RegAddr,
+ psPDumpRegDumpIN->sHWReg.ui32RegVal,
+ psPDumpRegDumpIN->ui32Flags);
+
+ return 0;
+}
+
+static IMG_INT
+PDumpRegPolBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_REGPOL *psPDumpRegPolIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_REGPOL);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID **)&psDeviceNode,
+ psPDumpRegPolIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ psRetOUT->eError =
+ PDumpRegPolWithFlagsKM(psPDumpRegPolIN->szRegRegion,
+ psPDumpRegPolIN->sHWReg.ui32RegAddr,
+ psPDumpRegPolIN->sHWReg.ui32RegVal,
+ psPDumpRegPolIN->ui32Mask,
+ psPDumpRegPolIN->ui32Flags);
+
+ return 0;
+}
+
+static IMG_INT
+PDumpMemPolBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_MEMPOL *psPDumpMemPolIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvMemInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_MEMPOL);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvMemInfo,
+ psPDumpMemPolIN->psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PDumpMemPolKM(((PVRSRV_KERNEL_MEM_INFO *)pvMemInfo),
+ psPDumpMemPolIN->ui32Offset,
+ psPDumpMemPolIN->ui32Value,
+ psPDumpMemPolIN->ui32Mask,
+ psPDumpMemPolIN->eOperator,
+ psPDumpMemPolIN->ui32Flags,
+ MAKEUNIQUETAG(pvMemInfo));
+
+ return 0;
+}
+
+static IMG_INT
+PDumpMemBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_DUMPMEM *psPDumpMemDumpIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvMemInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_DUMPMEM);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvMemInfo,
+ psPDumpMemDumpIN->psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PDumpMemUM(psPerProc,
+ psPDumpMemDumpIN->pvAltLinAddr,
+ psPDumpMemDumpIN->pvLinAddr,
+ pvMemInfo,
+ psPDumpMemDumpIN->ui32Offset,
+ psPDumpMemDumpIN->ui32Bytes,
+ psPDumpMemDumpIN->ui32Flags,
+ MAKEUNIQUETAG(pvMemInfo));
+
+ return 0;
+}
+
+static IMG_INT
+PDumpBitmapBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_BITMAP *psPDumpBitmapIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ IMG_HANDLE hDevMemContextInt;
+
+ PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, (IMG_VOID **)&psDeviceNode,
+ psPDumpBitmapIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle( psPerProc->psHandleBase,
+ &hDevMemContextInt,
+ psPDumpBitmapIN->hDevMemContext,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PDumpBitmapKM(psDeviceNode,
+ &psPDumpBitmapIN->szFileName[0],
+ psPDumpBitmapIN->ui32FileOffset,
+ psPDumpBitmapIN->ui32Width,
+ psPDumpBitmapIN->ui32Height,
+ psPDumpBitmapIN->ui32StrideInBytes,
+ psPDumpBitmapIN->sDevBaseAddr,
+ hDevMemContextInt,
+ psPDumpBitmapIN->ui32Size,
+ psPDumpBitmapIN->ePixelFormat,
+ psPDumpBitmapIN->eMemFormat,
+ psPDumpBitmapIN->ui32Flags);
+
+ return 0;
+}
+
+static IMG_INT
+PDumpReadRegBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_READREG *psPDumpReadRegIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_DUMPREADREG);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, (IMG_VOID **)&psDeviceNode,
+ psPDumpReadRegIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ psRetOUT->eError =
+ PDumpReadRegKM(&psPDumpReadRegIN->szRegRegion[0],
+ &psPDumpReadRegIN->szFileName[0],
+ psPDumpReadRegIN->ui32FileOffset,
+ psPDumpReadRegIN->ui32Address,
+ psPDumpReadRegIN->ui32Size,
+ psPDumpReadRegIN->ui32Flags);
+
+ return 0;
+}
+
+static IMG_INT
+PDumpDriverInfoBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_DRIVERINFO *psPDumpDriverInfoIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_UINT32 ui32PDumpFlags;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_DRIVERINFO);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ ui32PDumpFlags = 0;
+ if(psPDumpDriverInfoIN->bContinuous)
+ {
+ ui32PDumpFlags |= PDUMP_FLAGS_CONTINUOUS;
+ }
+ psRetOUT->eError =
+ PDumpDriverInfoKM(&psPDumpDriverInfoIN->szString[0],
+ ui32PDumpFlags);
+
+ return 0;
+}
+
+static IMG_INT
+PDumpSyncDumpBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_DUMPSYNC *psPDumpSyncDumpIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_UINT32 ui32Bytes = psPDumpSyncDumpIN->ui32Bytes;
+ IMG_VOID *pvSyncInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_DUMPSYNC);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &pvSyncInfo,
+ psPDumpSyncDumpIN->psKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PDumpMemUM(psPerProc,
+ psPDumpSyncDumpIN->pvAltLinAddr,
+ IMG_NULL,
+ ((PVRSRV_KERNEL_SYNC_INFO *)pvSyncInfo)->psSyncDataMemInfoKM,
+ psPDumpSyncDumpIN->ui32Offset,
+ ui32Bytes,
+ 0,
+ MAKEUNIQUETAG(((PVRSRV_KERNEL_SYNC_INFO *)pvSyncInfo)->psSyncDataMemInfoKM));
+
+ return 0;
+}
+
+static IMG_INT
+PDumpSyncPolBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_SYNCPOL *psPDumpSyncPolIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_UINT32 ui32Offset;
+ IMG_VOID *pvSyncInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_SYNCPOL);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &pvSyncInfo,
+ psPDumpSyncPolIN->psKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ if(psPDumpSyncPolIN->bIsRead)
+ {
+ ui32Offset = offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete);
+ }
+ else
+ {
+ ui32Offset = offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete);
+ }
+
+ psRetOUT->eError =
+ PDumpMemPolKM(((PVRSRV_KERNEL_SYNC_INFO *)pvSyncInfo)->psSyncDataMemInfoKM,
+ ui32Offset,
+ psPDumpSyncPolIN->ui32Value,
+ psPDumpSyncPolIN->ui32Mask,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ 0,
+ MAKEUNIQUETAG(((PVRSRV_KERNEL_SYNC_INFO *)pvSyncInfo)->psSyncDataMemInfoKM));
+
+ return 0;
+}
+
+
+static IMG_INT
+PDumpCycleCountRegReadBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_CYCLE_COUNT_REG_READ *psPDumpCycleCountRegReadIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_CYCLE_COUNT_REG_READ);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID **)&psDeviceNode,
+ psPDumpCycleCountRegReadIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ PDumpCycleCountRegRead(&psDeviceNode->sDevId,
+ psPDumpCycleCountRegReadIN->ui32RegOffset,
+ psPDumpCycleCountRegReadIN->bLastFrame);
+
+ psRetOUT->eError = PVRSRV_OK;
+
+ return 0;
+}
+
+static IMG_INT
+PDumpPDDevPAddrBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_DUMPPDDEVPADDR *psPDumpPDDevPAddrIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvMemInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_DUMPPDDEVPADDR);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &pvMemInfo,
+ psPDumpPDDevPAddrIN->hKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PDumpPDDevPAddrKM((PVRSRV_KERNEL_MEM_INFO *)pvMemInfo,
+ psPDumpPDDevPAddrIN->ui32Offset,
+ psPDumpPDDevPAddrIN->sPDDevPAddr,
+ MAKEUNIQUETAG(pvMemInfo),
+ PDUMP_PD_UNIQUETAG);
+ return 0;
+}
+
+static IMG_INT
+PDumpStartInitPhaseBW(IMG_UINT32 ui32BridgeID,
+ IMG_VOID *psBridgeIn,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_STARTINITPHASE);
+ PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ psRetOUT->eError = PDumpStartInitPhaseKM();
+
+ return 0;
+}
+
+static IMG_INT
+PDumpStopInitPhaseBW(IMG_UINT32 ui32BridgeID,
+ IMG_VOID *psBridgeIn,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_STOPINITPHASE);
+ PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ psRetOUT->eError = PDumpStopInitPhaseKM();
+
+ return 0;
+}
+
+#endif
+
+
+static IMG_INT
+PVRSRVGetMiscInfoBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GET_MISC_INFO *psGetMiscInfoIN,
+ PVRSRV_BRIDGE_OUT_GET_MISC_INFO *psGetMiscInfoOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_ERROR eError;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_MISC_INFO);
+
+ OSMemCopy(&psGetMiscInfoOUT->sMiscInfo,
+ &psGetMiscInfoIN->sMiscInfo,
+ sizeof(PVRSRV_MISC_INFO));
+
+ if (((psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) != 0) &&
+ ((psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0) &&
+ ((psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_FREEMEM_PRESENT) != 0))
+ {
+
+ psGetMiscInfoOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+
+ if (((psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) != 0) ||
+ ((psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0) ||
+ ((psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_FREEMEM_PRESENT) != 0))
+ {
+
+ ASSIGN_AND_EXIT_ON_ERROR(psGetMiscInfoOUT->eError,
+ OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ psGetMiscInfoOUT->sMiscInfo.ui32MemoryStrLen,
+ (IMG_VOID **)&psGetMiscInfoOUT->sMiscInfo.pszMemoryStr, 0,
+ "Output string buffer"));
+
+ psGetMiscInfoOUT->eError = PVRSRVGetMiscInfoKM(&psGetMiscInfoOUT->sMiscInfo);
+
+
+ eError = CopyToUserWrapper(psPerProc, ui32BridgeID,
+ psGetMiscInfoIN->sMiscInfo.pszMemoryStr,
+ psGetMiscInfoOUT->sMiscInfo.pszMemoryStr,
+ psGetMiscInfoOUT->sMiscInfo.ui32MemoryStrLen);
+
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ psGetMiscInfoOUT->sMiscInfo.ui32MemoryStrLen,
+ (IMG_VOID *)psGetMiscInfoOUT->sMiscInfo.pszMemoryStr, 0);
+ psGetMiscInfoOUT->sMiscInfo.pszMemoryStr = IMG_NULL;
+
+
+ psGetMiscInfoOUT->sMiscInfo.pszMemoryStr = psGetMiscInfoIN->sMiscInfo.pszMemoryStr;
+
+ if(eError != PVRSRV_OK)
+ {
+
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetMiscInfoBW Error copy to user"));
+ return -EFAULT;
+ }
+ }
+ else
+ {
+ psGetMiscInfoOUT->eError = PVRSRVGetMiscInfoKM(&psGetMiscInfoOUT->sMiscInfo);
+ }
+
+
+ if (psGetMiscInfoOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ if (psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT)
+ {
+ psGetMiscInfoOUT->eError = PVRSRVAllocHandle(psPerProc->psHandleBase,
+ &psGetMiscInfoOUT->sMiscInfo.sGlobalEventObject.hOSEventKM,
+ psGetMiscInfoOUT->sMiscInfo.sGlobalEventObject.hOSEventKM,
+ PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT,
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+
+ if (psGetMiscInfoOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ if (psGetMiscInfoOUT->sMiscInfo.hSOCTimerRegisterOSMemHandle)
+ {
+
+ psGetMiscInfoOUT->eError = PVRSRVAllocHandle(psPerProc->psHandleBase,
+ &psGetMiscInfoOUT->sMiscInfo.hSOCTimerRegisterOSMemHandle,
+ psGetMiscInfoOUT->sMiscInfo.hSOCTimerRegisterOSMemHandle,
+ PVRSRV_HANDLE_TYPE_SOC_TIMER,
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+
+ if (psGetMiscInfoOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVConnectBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_CONNECT_SERVICES *psConnectServicesIN,
+ PVRSRV_BRIDGE_OUT_CONNECT_SERVICES *psConnectServicesOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CONNECT_SERVICES);
+
+#if defined(PDUMP)
+
+ psPerProc->bPDumpPersistent |= ( (psConnectServicesIN->ui32Flags & SRV_FLAGS_PERSIST) != 0) ? IMG_TRUE : IMG_FALSE;
+
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+
+ psPerProc->bPDumpActive |= ( (psConnectServicesIN->ui32Flags & SRV_FLAGS_PDUMP_ACTIVE) != 0) ? IMG_TRUE : IMG_FALSE;
+#endif
+#else
+ PVR_UNREFERENCED_PARAMETER(psConnectServicesIN);
+#endif
+ psConnectServicesOUT->hKernelServices = psPerProc->hPerProcData;
+ psConnectServicesOUT->eError = PVRSRV_OK;
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVDisconnectBW(IMG_UINT32 ui32BridgeID,
+ IMG_VOID *psBridgeIn,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+ PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DISCONNECT_SERVICES);
+
+
+ psRetOUT->eError = PVRSRV_OK;
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVEnumerateDCBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_ENUMCLASS *psEnumDispClassIN,
+ PVRSRV_BRIDGE_OUT_ENUMCLASS *psEnumDispClassOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ENUM_CLASS);
+
+ psEnumDispClassOUT->eError =
+ PVRSRVEnumerateDCKM(psEnumDispClassIN->sDeviceClass,
+ &psEnumDispClassOUT->ui32NumDevices,
+ &psEnumDispClassOUT->ui32DevID[0]);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVOpenDCDeviceBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_OPEN_DISPCLASS_DEVICE *psOpenDispClassDeviceIN,
+ PVRSRV_BRIDGE_OUT_OPEN_DISPCLASS_DEVICE *psOpenDispClassDeviceOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_HANDLE hDispClassInfoInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_OPEN_DISPCLASS_DEVICE);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psOpenDispClassDeviceOUT->eError, psPerProc, 1);
+
+ psOpenDispClassDeviceOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psOpenDispClassDeviceIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psOpenDispClassDeviceOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psOpenDispClassDeviceOUT->eError =
+ PVRSRVOpenDCDeviceKM(psPerProc,
+ psOpenDispClassDeviceIN->ui32DeviceID,
+ hDevCookieInt,
+ &hDispClassInfoInt);
+
+ if(psOpenDispClassDeviceOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psOpenDispClassDeviceOUT->hDeviceKM,
+ hDispClassInfoInt,
+ PVRSRV_HANDLE_TYPE_DISP_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+ COMMIT_HANDLE_BATCH_OR_ERROR(psOpenDispClassDeviceOUT->eError, psPerProc);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVCloseDCDeviceBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_CLOSE_DISPCLASS_DEVICE *psCloseDispClassDeviceIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvDispClassInfoInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CLOSE_DISPCLASS_DEVICE);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfoInt,
+ psCloseDispClassDeviceIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = PVRSRVCloseDCDeviceKM(pvDispClassInfoInt, IMG_FALSE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psCloseDispClassDeviceIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ return 0;
+}
+
+static IMG_INT
+PVRSRVEnumDCFormatsBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_FORMATS *psEnumDispClassFormatsIN,
+ PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_FORMATS *psEnumDispClassFormatsOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvDispClassInfoInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ENUM_DISPCLASS_FORMATS);
+
+ psEnumDispClassFormatsOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfoInt,
+ psEnumDispClassFormatsIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if(psEnumDispClassFormatsOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psEnumDispClassFormatsOUT->eError =
+ PVRSRVEnumDCFormatsKM(pvDispClassInfoInt,
+ &psEnumDispClassFormatsOUT->ui32Count,
+ psEnumDispClassFormatsOUT->asFormat);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVEnumDCDimsBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_DIMS *psEnumDispClassDimsIN,
+ PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_DIMS *psEnumDispClassDimsOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvDispClassInfoInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ENUM_DISPCLASS_DIMS);
+
+ psEnumDispClassDimsOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfoInt,
+ psEnumDispClassDimsIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+
+ if(psEnumDispClassDimsOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psEnumDispClassDimsOUT->eError =
+ PVRSRVEnumDCDimsKM(pvDispClassInfoInt,
+ &psEnumDispClassDimsIN->sFormat,
+ &psEnumDispClassDimsOUT->ui32Count,
+ psEnumDispClassDimsOUT->asDim);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVGetDCSystemBufferBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GET_DISPCLASS_SYSBUFFER *psGetDispClassSysBufferIN,
+ PVRSRV_BRIDGE_OUT_GET_DISPCLASS_SYSBUFFER *psGetDispClassSysBufferOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hBufferInt;
+ IMG_VOID *pvDispClassInfoInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_DISPCLASS_SYSBUFFER);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psGetDispClassSysBufferOUT->eError, psPerProc, 1);
+
+ psGetDispClassSysBufferOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfoInt,
+ psGetDispClassSysBufferIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if(psGetDispClassSysBufferOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psGetDispClassSysBufferOUT->eError =
+ PVRSRVGetDCSystemBufferKM(pvDispClassInfoInt,
+ &hBufferInt);
+
+ if(psGetDispClassSysBufferOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psGetDispClassSysBufferOUT->hBuffer,
+ hBufferInt,
+ PVRSRV_HANDLE_TYPE_DISP_BUFFER,
+ (PVRSRV_HANDLE_ALLOC_FLAG)(PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE | PVRSRV_HANDLE_ALLOC_FLAG_SHARED),
+ psGetDispClassSysBufferIN->hDeviceKM);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psGetDispClassSysBufferOUT->eError, psPerProc);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVGetDCInfoBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GET_DISPCLASS_INFO *psGetDispClassInfoIN,
+ PVRSRV_BRIDGE_OUT_GET_DISPCLASS_INFO *psGetDispClassInfoOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvDispClassInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_DISPCLASS_INFO);
+
+ psGetDispClassInfoOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfo,
+ psGetDispClassInfoIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if(psGetDispClassInfoOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psGetDispClassInfoOUT->eError =
+ PVRSRVGetDCInfoKM(pvDispClassInfo,
+ &psGetDispClassInfoOUT->sDisplayInfo);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVCreateDCSwapChainBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_CREATE_DISPCLASS_SWAPCHAIN *psCreateDispClassSwapChainIN,
+ PVRSRV_BRIDGE_OUT_CREATE_DISPCLASS_SWAPCHAIN *psCreateDispClassSwapChainOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvDispClassInfo;
+ IMG_HANDLE hSwapChainInt;
+ IMG_UINT32 ui32SwapChainID;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CREATE_DISPCLASS_SWAPCHAIN);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psCreateDispClassSwapChainOUT->eError, psPerProc, 1);
+
+ psCreateDispClassSwapChainOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfo,
+ psCreateDispClassSwapChainIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+
+ if(psCreateDispClassSwapChainOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ ui32SwapChainID = psCreateDispClassSwapChainIN->ui32SwapChainID;
+
+ psCreateDispClassSwapChainOUT->eError =
+ PVRSRVCreateDCSwapChainKM(psPerProc, pvDispClassInfo,
+ psCreateDispClassSwapChainIN->ui32Flags,
+ &psCreateDispClassSwapChainIN->sDstSurfAttrib,
+ &psCreateDispClassSwapChainIN->sSrcSurfAttrib,
+ psCreateDispClassSwapChainIN->ui32BufferCount,
+ psCreateDispClassSwapChainIN->ui32OEMFlags,
+ &hSwapChainInt,
+ &ui32SwapChainID);
+
+ if(psCreateDispClassSwapChainOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ psCreateDispClassSwapChainOUT->ui32SwapChainID = ui32SwapChainID;
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psCreateDispClassSwapChainOUT->hSwapChain,
+ hSwapChainInt,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+ psCreateDispClassSwapChainIN->hDeviceKM);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psCreateDispClassSwapChainOUT->eError, psPerProc);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVDestroyDCSwapChainBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DESTROY_DISPCLASS_SWAPCHAIN *psDestroyDispClassSwapChainIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvSwapChain;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DESTROY_DISPCLASS_SWAPCHAIN);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &pvSwapChain,
+ psDestroyDispClassSwapChainIN->hSwapChain,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVDestroyDCSwapChainKM(pvSwapChain);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psDestroyDispClassSwapChainIN->hSwapChain,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVSetDCDstRectBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SET_DISPCLASS_RECT *psSetDispClassDstRectIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvDispClassInfo;
+ IMG_VOID *pvSwapChain;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SET_DISPCLASS_DSTRECT);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfo,
+ psSetDispClassDstRectIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvSwapChain,
+ psSetDispClassDstRectIN->hSwapChain,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVSetDCDstRectKM(pvDispClassInfo,
+ pvSwapChain,
+ &psSetDispClassDstRectIN->sRect);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVSetDCSrcRectBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SET_DISPCLASS_RECT *psSetDispClassSrcRectIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvDispClassInfo;
+ IMG_VOID *pvSwapChain;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SET_DISPCLASS_SRCRECT);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfo,
+ psSetDispClassSrcRectIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvSwapChain,
+ psSetDispClassSrcRectIN->hSwapChain,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVSetDCSrcRectKM(pvDispClassInfo,
+ pvSwapChain,
+ &psSetDispClassSrcRectIN->sRect);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVSetDCDstColourKeyBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SET_DISPCLASS_COLOURKEY *psSetDispClassColKeyIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvDispClassInfo;
+ IMG_VOID *pvSwapChain;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SET_DISPCLASS_DSTCOLOURKEY);
+
+ /* XXX this is a workaround, will have a formal implementation later on */
+ if ((IMG_UINT32)psSetDispClassColKeyIN->hSwapChain == 0xC0C0C0C0) {
+ if ( (IMG_UINT32)psSetDispClassColKeyIN->ui32CKColour == 0xD0D0D0D0) {
+ mdfld__intel_plane_set_alpha(IMG_TRUE);
+ } else if ((IMG_UINT32)psSetDispClassColKeyIN->ui32CKColour == 0xE0E0E0E0) {
+ mdfld__intel_plane_set_alpha(IMG_FALSE);
+ }
+ psRetOUT->eError = PVRSRV_OK;
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfo,
+ psSetDispClassColKeyIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvSwapChain,
+ psSetDispClassColKeyIN->hSwapChain,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVSetDCDstColourKeyKM(pvDispClassInfo,
+ pvSwapChain,
+ psSetDispClassColKeyIN->ui32CKColour);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVSetDCSrcColourKeyBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SET_DISPCLASS_COLOURKEY *psSetDispClassColKeyIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvDispClassInfo;
+ IMG_VOID *pvSwapChain;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SET_DISPCLASS_SRCCOLOURKEY);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfo,
+ psSetDispClassColKeyIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvSwapChain,
+ psSetDispClassColKeyIN->hSwapChain,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVSetDCSrcColourKeyKM(pvDispClassInfo,
+ pvSwapChain,
+ psSetDispClassColKeyIN->ui32CKColour);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVGetDCBuffersBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GET_DISPCLASS_BUFFERS *psGetDispClassBuffersIN,
+ PVRSRV_BRIDGE_OUT_GET_DISPCLASS_BUFFERS *psGetDispClassBuffersOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvDispClassInfo;
+ IMG_VOID *pvSwapChain;
+ IMG_UINT32 i;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_DISPCLASS_BUFFERS);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psGetDispClassBuffersOUT->eError, psPerProc, PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS);
+
+ psGetDispClassBuffersOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfo,
+ psGetDispClassBuffersIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if(psGetDispClassBuffersOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psGetDispClassBuffersOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvSwapChain,
+ psGetDispClassBuffersIN->hSwapChain,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+ if(psGetDispClassBuffersOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psGetDispClassBuffersOUT->eError =
+ PVRSRVGetDCBuffersKM(pvDispClassInfo,
+ pvSwapChain,
+ &psGetDispClassBuffersOUT->ui32BufferCount,
+ psGetDispClassBuffersOUT->ahBuffer);
+ if (psGetDispClassBuffersOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ PVR_ASSERT(psGetDispClassBuffersOUT->ui32BufferCount <= PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS);
+
+ for(i = 0; i < psGetDispClassBuffersOUT->ui32BufferCount; i++)
+ {
+ IMG_HANDLE hBufferExt;
+
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &hBufferExt,
+ psGetDispClassBuffersOUT->ahBuffer[i],
+ PVRSRV_HANDLE_TYPE_DISP_BUFFER,
+ (PVRSRV_HANDLE_ALLOC_FLAG)(PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE | PVRSRV_HANDLE_ALLOC_FLAG_SHARED),
+ psGetDispClassBuffersIN->hSwapChain);
+
+ psGetDispClassBuffersOUT->ahBuffer[i] = hBufferExt;
+ }
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psGetDispClassBuffersOUT->eError, psPerProc);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVSwapToDCBufferBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_BUFFER *psSwapDispClassBufferIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvDispClassInfo;
+ IMG_VOID *pvSwapChainBuf;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_BUFFER);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfo,
+ psSwapDispClassBufferIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupSubHandle(psPerProc->psHandleBase,
+ &pvSwapChainBuf,
+ psSwapDispClassBufferIN->hBuffer,
+ PVRSRV_HANDLE_TYPE_DISP_BUFFER,
+ psSwapDispClassBufferIN->hDeviceKM);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVSwapToDCBufferKM(pvDispClassInfo,
+ pvSwapChainBuf,
+ psSwapDispClassBufferIN->ui32SwapInterval,
+ psSwapDispClassBufferIN->hPrivateTag,
+ psSwapDispClassBufferIN->ui32ClipRectCount,
+ psSwapDispClassBufferIN->sClipRect,
+ psPerProc);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVSwapToDCSystemBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_SYSTEM *psSwapDispClassSystemIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvDispClassInfo;
+ IMG_VOID *pvSwapChain;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_SYSTEM);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfo,
+ psSwapDispClassSystemIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupSubHandle(psPerProc->psHandleBase,
+ &pvSwapChain,
+ psSwapDispClassSystemIN->hSwapChain,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN,
+ psSwapDispClassSystemIN->hDeviceKM);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ psRetOUT->eError =
+ PVRSRVSwapToDCSystemKM(pvDispClassInfo,
+ pvSwapChain);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVGetDCFrontBufferBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GET_DISPCLASS_FRONT_BUFFER *psSwapDispClassSystemIN,
+ PVRSRV_BRIDGE_OUT_GET_DISPCLASS_FRONT_BUFFER *psSwapDispClassSystemOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_DISPCLASS_FRONT_BUFFER);
+ psSwapDispClassSystemOUT->eError = PVRSRV_ERROR_GENERIC;
+ return 0;
+}
+
+static IMG_INT
+PVRSRVOpenBCDeviceBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_OPEN_BUFFERCLASS_DEVICE *psOpenBufferClassDeviceIN,
+ PVRSRV_BRIDGE_OUT_OPEN_BUFFERCLASS_DEVICE *psOpenBufferClassDeviceOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_HANDLE hBufClassInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_OPEN_BUFFERCLASS_DEVICE);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psOpenBufferClassDeviceOUT->eError, psPerProc, 1);
+
+ psOpenBufferClassDeviceOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psOpenBufferClassDeviceIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psOpenBufferClassDeviceOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psOpenBufferClassDeviceOUT->eError =
+ PVRSRVOpenBCDeviceKM(psPerProc,
+ psOpenBufferClassDeviceIN->ui32DeviceID,
+ hDevCookieInt,
+ &hBufClassInfo);
+ if(psOpenBufferClassDeviceOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psOpenBufferClassDeviceOUT->hDeviceKM,
+ hBufClassInfo,
+ PVRSRV_HANDLE_TYPE_BUF_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psOpenBufferClassDeviceOUT->eError, psPerProc);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVCloseBCDeviceBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_CLOSE_BUFFERCLASS_DEVICE *psCloseBufferClassDeviceIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvBufClassInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CLOSE_BUFFERCLASS_DEVICE);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvBufClassInfo,
+ psCloseBufferClassDeviceIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_BUF_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVCloseBCDeviceKM(pvBufClassInfo, IMG_FALSE);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psCloseBufferClassDeviceIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_BUF_INFO);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVGetBCInfoBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_INFO *psGetBufferClassInfoIN,
+ PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_INFO *psGetBufferClassInfoOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvBufClassInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_BUFFERCLASS_INFO);
+
+ psGetBufferClassInfoOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvBufClassInfo,
+ psGetBufferClassInfoIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_BUF_INFO);
+ if(psGetBufferClassInfoOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psGetBufferClassInfoOUT->eError =
+ PVRSRVGetBCInfoKM(pvBufClassInfo,
+ &psGetBufferClassInfoOUT->sBufferInfo);
+ return 0;
+}
+
+static IMG_INT
+PVRSRVGetBCBufferBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_BUFFER *psGetBufferClassBufferIN,
+ PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_BUFFER *psGetBufferClassBufferOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvBufClassInfo;
+ IMG_HANDLE hBufferInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_BUFFERCLASS_BUFFER);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psGetBufferClassBufferOUT->eError, psPerProc, 1);
+
+ psGetBufferClassBufferOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvBufClassInfo,
+ psGetBufferClassBufferIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_BUF_INFO);
+ if(psGetBufferClassBufferOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psGetBufferClassBufferOUT->eError =
+ PVRSRVGetBCBufferKM(pvBufClassInfo,
+ psGetBufferClassBufferIN->ui32BufferIndex,
+ &hBufferInt);
+
+ if(psGetBufferClassBufferOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psGetBufferClassBufferOUT->hBuffer,
+ hBufferInt,
+ PVRSRV_HANDLE_TYPE_BUF_BUFFER,
+ (PVRSRV_HANDLE_ALLOC_FLAG)(PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE | PVRSRV_HANDLE_ALLOC_FLAG_SHARED),
+ psGetBufferClassBufferIN->hDeviceKM);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psGetBufferClassBufferOUT->eError, psPerProc);
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVAllocSharedSysMemoryBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_ALLOC_SHARED_SYS_MEM *psAllocSharedSysMemIN,
+ PVRSRV_BRIDGE_OUT_ALLOC_SHARED_SYS_MEM *psAllocSharedSysMemOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ALLOC_SHARED_SYS_MEM);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psAllocSharedSysMemOUT->eError, psPerProc, 1);
+
+ psAllocSharedSysMemOUT->eError =
+ PVRSRVAllocSharedSysMemoryKM(psPerProc,
+ psAllocSharedSysMemIN->ui32Flags,
+ psAllocSharedSysMemIN->ui32Size,
+ &psKernelMemInfo);
+ if(psAllocSharedSysMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ OSMemSet(&psAllocSharedSysMemOUT->sClientMemInfo,
+ 0,
+ sizeof(psAllocSharedSysMemOUT->sClientMemInfo));
+
+ psAllocSharedSysMemOUT->sClientMemInfo.pvLinAddrKM =
+ psKernelMemInfo->pvLinAddrKM;
+
+ psAllocSharedSysMemOUT->sClientMemInfo.pvLinAddr = 0;
+ psAllocSharedSysMemOUT->sClientMemInfo.ui32Flags =
+ psKernelMemInfo->ui32Flags;
+ psAllocSharedSysMemOUT->sClientMemInfo.ui32AllocSize =
+ psKernelMemInfo->ui32AllocSize;
+ psAllocSharedSysMemOUT->sClientMemInfo.hMappingInfo = psKernelMemInfo->sMemBlk.hOSMemHandle;
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psAllocSharedSysMemOUT->sClientMemInfo.hKernelMemInfo,
+ psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psAllocSharedSysMemOUT->eError, psPerProc);
+
+ return 0;
+}
+
+static IMG_INT
+PVRSRVFreeSharedSysMemoryBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_FREE_SHARED_SYS_MEM *psFreeSharedSysMemIN,
+ PVRSRV_BRIDGE_OUT_FREE_SHARED_SYS_MEM *psFreeSharedSysMemOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_FREE_SHARED_SYS_MEM);
+
+ psFreeSharedSysMemOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID **)&psKernelMemInfo,
+ psFreeSharedSysMemIN->psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+
+ if(psFreeSharedSysMemOUT->eError != PVRSRV_OK)
+ return 0;
+
+ psFreeSharedSysMemOUT->eError =
+ PVRSRVFreeSharedSysMemoryKM(psKernelMemInfo);
+ if(psFreeSharedSysMemOUT->eError != PVRSRV_OK)
+ return 0;
+
+ psFreeSharedSysMemOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psFreeSharedSysMemIN->psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+ return 0;
+}
+
+static IMG_INT
+PVRSRVMapMemInfoMemBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_MAP_MEMINFO_MEM *psMapMemInfoMemIN,
+ PVRSRV_BRIDGE_OUT_MAP_MEMINFO_MEM *psMapMemInfoMemOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ PVRSRV_HANDLE_TYPE eHandleType;
+ IMG_HANDLE hParent;
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MAP_MEMINFO_MEM);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psMapMemInfoMemOUT->eError, psPerProc, 2);
+
+ psMapMemInfoMemOUT->eError =
+ PVRSRVLookupHandleAnyType(psPerProc->psHandleBase,
+ (IMG_VOID **)&psKernelMemInfo,
+ &eHandleType,
+ psMapMemInfoMemIN->hKernelMemInfo);
+ if(psMapMemInfoMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ switch (eHandleType)
+ {
+#if defined(PVR_SECURE_HANDLES)
+ case PVRSRV_HANDLE_TYPE_MEM_INFO:
+ case PVRSRV_HANDLE_TYPE_MEM_INFO_REF:
+ case PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO:
+#else
+ case PVRSRV_HANDLE_TYPE_NONE:
+#endif
+ break;
+ default:
+ psMapMemInfoMemOUT->eError = PVRSRV_ERROR_INVALID_HANDLE_TYPE;
+ return 0;
+ }
+
+
+ psMapMemInfoMemOUT->eError =
+ PVRSRVGetParentHandle(psPerProc->psHandleBase,
+ &hParent,
+ psMapMemInfoMemIN->hKernelMemInfo,
+ eHandleType);
+ if (psMapMemInfoMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ if (hParent == IMG_NULL)
+ {
+ hParent = psMapMemInfoMemIN->hKernelMemInfo;
+ }
+
+ OSMemSet(&psMapMemInfoMemOUT->sClientMemInfo,
+ 0,
+ sizeof(psMapMemInfoMemOUT->sClientMemInfo));
+
+ psMapMemInfoMemOUT->sClientMemInfo.pvLinAddrKM =
+ psKernelMemInfo->pvLinAddrKM;
+
+ psMapMemInfoMemOUT->sClientMemInfo.pvLinAddr = 0;
+ psMapMemInfoMemOUT->sClientMemInfo.sDevVAddr =
+ psKernelMemInfo->sDevVAddr;
+ psMapMemInfoMemOUT->sClientMemInfo.ui32Flags =
+ psKernelMemInfo->ui32Flags;
+ psMapMemInfoMemOUT->sClientMemInfo.ui32AllocSize =
+ psKernelMemInfo->ui32AllocSize;
+ psMapMemInfoMemOUT->sClientMemInfo.hMappingInfo = psKernelMemInfo->sMemBlk.hOSMemHandle;
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psMapMemInfoMemOUT->sClientMemInfo.hKernelMemInfo,
+ psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+ hParent);
+
+ if(psKernelMemInfo->ui32Flags & PVRSRV_MEM_NO_SYNCOBJ)
+ {
+
+ OSMemSet(&psMapMemInfoMemOUT->sClientSyncInfo,
+ 0,
+ sizeof (PVRSRV_CLIENT_SYNC_INFO));
+ }
+ else
+ {
+
+ psMapMemInfoMemOUT->sClientSyncInfo.psSyncData =
+ psKernelMemInfo->psKernelSyncInfo->psSyncData;
+ psMapMemInfoMemOUT->sClientSyncInfo.sWriteOpsCompleteDevVAddr =
+ psKernelMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
+ psMapMemInfoMemOUT->sClientSyncInfo.sReadOpsCompleteDevVAddr =
+ psKernelMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+
+ psMapMemInfoMemOUT->sClientSyncInfo.hMappingInfo =
+ psKernelMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle;
+
+ psMapMemInfoMemOUT->sClientMemInfo.psClientSyncInfo = &psMapMemInfoMemOUT->sClientSyncInfo;
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psMapMemInfoMemOUT->sClientSyncInfo.hKernelSyncInfo,
+ psKernelMemInfo->psKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+ psMapMemInfoMemOUT->sClientMemInfo.hKernelMemInfo);
+ }
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psMapMemInfoMemOUT->eError, psPerProc);
+
+ return 0;
+}
+
+
+
+static IMG_INT
+MMU_GetPDDevPAddrBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GETMMU_PD_DEVPADDR *psGetMmuPDDevPAddrIN,
+ PVRSRV_BRIDGE_OUT_GETMMU_PD_DEVPADDR *psGetMmuPDDevPAddrOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevMemContextInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GETMMU_PD_DEVPADDR);
+
+ psGetMmuPDDevPAddrOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevMemContextInt,
+ psGetMmuPDDevPAddrIN->hDevMemContext,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+ if(psGetMmuPDDevPAddrOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psGetMmuPDDevPAddrOUT->sPDDevPAddr =
+ BM_GetDeviceNode(hDevMemContextInt)->pfnMMUGetPDDevPAddr(BM_GetMMUContextFromMemContext(hDevMemContextInt));
+ if(psGetMmuPDDevPAddrOUT->sPDDevPAddr.uiAddr)
+ {
+ psGetMmuPDDevPAddrOUT->eError = PVRSRV_OK;
+ }
+ else
+ {
+ psGetMmuPDDevPAddrOUT->eError = PVRSRV_ERROR_INVALID_PHYS_ADDR;
+ }
+ return 0;
+}
+
+
+
+IMG_INT
+DummyBW(IMG_UINT32 ui32BridgeID,
+ IMG_VOID *psBridgeIn,
+ IMG_VOID *psBridgeOut,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+#if !defined(DEBUG)
+ PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+#endif
+ PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+ PVR_UNREFERENCED_PARAMETER(psBridgeOut);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+#if defined(DEBUG_BRIDGE_KM)
+ PVR_DPF((PVR_DBG_ERROR, "%s: BRIDGE ERROR: BridgeID %u (%s) mapped to "
+ "Dummy Wrapper (probably not what you want!)",
+ __FUNCTION__, ui32BridgeID, g_BridgeDispatchTable[ui32BridgeID].pszIOCName));
+#else
+ PVR_DPF((PVR_DBG_ERROR, "%s: BRIDGE ERROR: BridgeID %u mapped to "
+ "Dummy Wrapper (probably not what you want!)",
+ __FUNCTION__, ui32BridgeID));
+#endif
+ return -ENOTTY;
+}
+
+
+IMG_VOID
+_SetDispatchTableEntry(IMG_UINT32 ui32Index,
+ const IMG_CHAR *pszIOCName,
+ BridgeWrapperFunction pfFunction,
+ const IMG_CHAR *pszFunctionName,
+ size_t in_size, size_t out_size,
+ off_t err_offset)
+{
+ static IMG_UINT32 ui32PrevIndex = ~0UL;
+#if !defined(DEBUG)
+ PVR_UNREFERENCED_PARAMETER(pszIOCName);
+#endif
+#if !defined(DEBUG_BRIDGE_KM_DISPATCH_TABLE) && !defined(DEBUG_BRIDGE_KM)
+ PVR_UNREFERENCED_PARAMETER(pszFunctionName);
+#endif
+
+#if defined(DEBUG_BRIDGE_KM_DISPATCH_TABLE)
+
+ PVR_DPF((PVR_DBG_WARNING, "%s: %d %s %s", __FUNCTION__, ui32Index, pszIOCName, pszFunctionName));
+#endif
+
+
+ if(g_BridgeDispatchTable[ui32Index].pfFunction)
+ {
+#if defined(DEBUG_BRIDGE_KM)
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: BUG!: Adding dispatch table entry for %s clobbers an existing entry for %s",
+ __FUNCTION__, pszIOCName, g_BridgeDispatchTable[ui32Index].pszIOCName));
+#else
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: BUG!: Adding dispatch table entry for %s clobbers an existing entry (index=%u)",
+ __FUNCTION__, pszIOCName, ui32Index));
+#endif
+ PVR_DPF((PVR_DBG_ERROR, "NOTE: Enabling DEBUG_BRIDGE_KM_DISPATCH_TABLE may help debug this issue."));
+ }
+
+
+ if((ui32PrevIndex != ~0UL) &&
+ ((ui32Index >= ui32PrevIndex + DISPATCH_TABLE_GAP_THRESHOLD) ||
+ (ui32Index <= ui32PrevIndex)))
+ {
+#if defined(DEBUG_BRIDGE_KM)
+ PVR_DPF((PVR_DBG_WARNING,
+ "%s: There is a gap in the dispatch table between indices %u (%s) and %u (%s)",
+ __FUNCTION__, ui32PrevIndex, g_BridgeDispatchTable[ui32PrevIndex].pszIOCName,
+ ui32Index, pszIOCName));
+#else
+ PVR_DPF((PVR_DBG_WARNING,
+ "%s: There is a gap in the dispatch table between indices %u and %u (%s)",
+ __FUNCTION__, (IMG_UINT)ui32PrevIndex, (IMG_UINT)ui32Index, pszIOCName));
+#endif
+ PVR_DPF((PVR_DBG_ERROR, "NOTE: Enabling DEBUG_BRIDGE_KM_DISPATCH_TABLE may help debug this issue."));
+ }
+
+ g_BridgeDispatchTable[ui32Index].pfFunction = pfFunction;
+ g_BridgeDispatchTable[ui32Index].in_size = in_size;
+ g_BridgeDispatchTable[ui32Index].out_size = out_size;
+ g_BridgeDispatchTable[ui32Index].err_offset = err_offset;
+#if defined(DEBUG_BRIDGE_KM)
+ g_BridgeDispatchTable[ui32Index].pszIOCName = pszIOCName;
+ g_BridgeDispatchTable[ui32Index].pszFunctionName = pszFunctionName;
+ g_BridgeDispatchTable[ui32Index].ui32CallCount = 0;
+ g_BridgeDispatchTable[ui32Index].ui32CopyFromUserTotalBytes = 0;
+#endif
+
+ ui32PrevIndex = ui32Index;
+}
+
+static IMG_INT
+PVRSRVInitSrvConnectBW(IMG_UINT32 ui32BridgeID,
+ IMG_VOID *psBridgeIn,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_INITSRV_CONNECT);
+ PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+
+
+ if((OSProcHasPrivSrvInit() == IMG_FALSE) || PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RUNNING) || PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RAN))
+ {
+ psRetOUT->eError = PVRSRV_ERROR_SRV_CONNECT_FAILED;
+ return 0;
+ }
+
+#if defined (__linux__)
+ PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_RUNNING, IMG_TRUE);
+#endif
+ psPerProc->bInitProcess = IMG_TRUE;
+
+ psRetOUT->eError = PVRSRV_OK;
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVInitSrvDisconnectBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_INITSRV_DISCONNECT *psInitSrvDisconnectIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_INITSRV_DISCONNECT);
+
+ if(!psPerProc->bInitProcess)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_SRV_DISCONNECT_FAILED;
+ return 0;
+ }
+
+ psPerProc->bInitProcess = IMG_FALSE;
+
+ PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_RUNNING, IMG_FALSE);
+ PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_RAN, IMG_TRUE);
+
+ psRetOUT->eError = PVRSRVFinaliseSystem(psInitSrvDisconnectIN->bInitSuccesful);
+
+ PVRSRVSetInitServerState( PVRSRV_INIT_SERVER_SUCCESSFUL ,
+ ((psRetOUT->eError == PVRSRV_OK) && (psInitSrvDisconnectIN->bInitSuccesful))
+ ? IMG_TRUE : IMG_FALSE);
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVEventObjectWaitBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_EVENT_OBJECT_WAIT *psEventObjectWaitIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hOSEventKM;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_EVENT_OBJECT_WAIT);
+
+ psRetOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hOSEventKM,
+ psEventObjectWaitIN->hOSEventKM,
+ PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = OSEventObjectWait(hOSEventKM);
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVEventObjectOpenBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_EVENT_OBJECT_OPEN *psEventObjectOpenIN,
+ PVRSRV_BRIDGE_OUT_EVENT_OBJECT_OPEN *psEventObjectOpenOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_EVENT_OBJECT_OPEN);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psEventObjectOpenOUT->eError, psPerProc, 1);
+
+ psEventObjectOpenOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psEventObjectOpenIN->sEventObject.hOSEventKM,
+ psEventObjectOpenIN->sEventObject.hOSEventKM,
+ PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT);
+
+ if(psEventObjectOpenOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psEventObjectOpenOUT->eError = OSEventObjectOpen(&psEventObjectOpenIN->sEventObject, &psEventObjectOpenOUT->hOSEvent);
+
+ if(psEventObjectOpenOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psEventObjectOpenOUT->hOSEvent,
+ psEventObjectOpenOUT->hOSEvent,
+ PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psEventObjectOpenOUT->eError, psPerProc);
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVEventObjectCloseBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_EVENT_OBJECT_CLOSE *psEventObjectCloseIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hOSEventKM;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_EVENT_OBJECT_CLOSE);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psEventObjectCloseIN->sEventObject.hOSEventKM,
+ psEventObjectCloseIN->sEventObject.hOSEventKM,
+ PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &hOSEventKM,
+ psEventObjectCloseIN->hOSEventKM,
+ PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = OSEventObjectClose(&psEventObjectCloseIN->sEventObject, hOSEventKM);
+
+ return 0;
+}
+
+
+typedef struct _MODIFY_SYNC_OP_INFO
+{
+ IMG_HANDLE hResItem;
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+ IMG_UINT32 ui32ModifyFlags;
+ IMG_UINT32 ui32ReadOpsPendingSnapShot;
+ IMG_UINT32 ui32WriteOpsPendingSnapShot;
+} MODIFY_SYNC_OP_INFO;
+
+
+static PVRSRV_ERROR DoQuerySyncOpsSatisfied(MODIFY_SYNC_OP_INFO *psModSyncOpInfo)
+{
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+
+ psKernelSyncInfo = psModSyncOpInfo->psKernelSyncInfo;
+
+ if (!psKernelSyncInfo)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if((psModSyncOpInfo->ui32WriteOpsPendingSnapShot == psKernelSyncInfo->psSyncData->ui32WriteOpsComplete)
+ && (psModSyncOpInfo->ui32ReadOpsPendingSnapShot == psKernelSyncInfo->psSyncData->ui32ReadOpsComplete))
+ {
+#if defined(PDUMP)
+
+ PDumpComment("Poll for read ops complete to reach value (%u)", psModSyncOpInfo->ui32ReadOpsPendingSnapShot);
+ PDumpMemPolKM(psKernelSyncInfo->psSyncDataMemInfoKM,
+ offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete),
+ psModSyncOpInfo->ui32ReadOpsPendingSnapShot,
+ 0xFFFFFFFF,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ 0,
+ MAKEUNIQUETAG(psKernelSyncInfo->psSyncDataMemInfoKM));
+
+
+ PDumpComment("Poll for write ops complete to reach value (%u)", psModSyncOpInfo->ui32WriteOpsPendingSnapShot);
+ PDumpMemPolKM(psKernelSyncInfo->psSyncDataMemInfoKM,
+ offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete),
+ psModSyncOpInfo->ui32WriteOpsPendingSnapShot,
+ 0xFFFFFFFF,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ 0,
+ MAKEUNIQUETAG(psKernelSyncInfo->psSyncDataMemInfoKM));
+#endif
+ return PVRSRV_OK;
+ }
+ else
+ {
+ return PVRSRV_ERROR_RETRY;
+ }
+}
+
+static PVRSRV_ERROR DoModifyCompleteSyncOps(MODIFY_SYNC_OP_INFO *psModSyncOpInfo)
+{
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+
+ psKernelSyncInfo = psModSyncOpInfo->psKernelSyncInfo;
+
+ if (!psKernelSyncInfo)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ if((psModSyncOpInfo->ui32WriteOpsPendingSnapShot != psKernelSyncInfo->psSyncData->ui32WriteOpsComplete)
+ || (psModSyncOpInfo->ui32ReadOpsPendingSnapShot != psKernelSyncInfo->psSyncData->ui32ReadOpsComplete))
+ {
+ return PVRSRV_ERROR_BAD_SYNC_STATE;
+ }
+
+
+ if(psModSyncOpInfo->ui32ModifyFlags & PVRSRV_MODIFYSYNCOPS_FLAGS_WO_INC)
+ {
+ psKernelSyncInfo->psSyncData->ui32WriteOpsComplete++;
+ }
+
+
+ if(psModSyncOpInfo->ui32ModifyFlags & PVRSRV_MODIFYSYNCOPS_FLAGS_RO_INC)
+ {
+ psKernelSyncInfo->psSyncData->ui32ReadOpsComplete++;
+ }
+
+ return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR ModifyCompleteSyncOpsCallBack(IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param)
+{
+ MODIFY_SYNC_OP_INFO *psModSyncOpInfo;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ if (!pvParam)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ModifyCompleteSyncOpsCallBack: invalid parameter"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psModSyncOpInfo = (MODIFY_SYNC_OP_INFO*)pvParam;
+
+ if (psModSyncOpInfo->psKernelSyncInfo)
+ {
+
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+ {
+ if (DoQuerySyncOpsSatisfied(psModSyncOpInfo) == PVRSRV_OK)
+ {
+ goto OpFlushedComplete;
+ }
+ PVR_DPF((PVR_DBG_WARNING, "ModifyCompleteSyncOpsCallBack: waiting for current Ops to flush"));
+ OSSleepms(1);
+ } END_LOOP_UNTIL_TIMEOUT();
+
+ PVR_DPF((PVR_DBG_ERROR, "ModifyCompleteSyncOpsCallBack: timeout whilst waiting for current Ops to flush."));
+ PVR_DPF((PVR_DBG_ERROR, " Write ops pending snapshot = %d, write ops complete = %d",
+ psModSyncOpInfo->ui32WriteOpsPendingSnapShot,
+ psModSyncOpInfo->psKernelSyncInfo->psSyncData->ui32WriteOpsComplete));
+ PVR_DPF((PVR_DBG_ERROR, " Read ops pending snapshot = %d, write ops complete = %d",
+ psModSyncOpInfo->ui32ReadOpsPendingSnapShot,
+ psModSyncOpInfo->psKernelSyncInfo->psSyncData->ui32ReadOpsComplete));
+
+ return PVRSRV_ERROR_TIMEOUT;
+
+ OpFlushedComplete:
+
+ DoModifyCompleteSyncOps(psModSyncOpInfo);
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(MODIFY_SYNC_OP_INFO), (IMG_VOID *)psModSyncOpInfo, 0);
+
+
+
+ PVRSRVScheduleDeviceCallbacks();
+
+ return PVRSRV_OK;
+}
+
+
+static IMG_INT
+PVRSRVCreateSyncInfoModObjBW(IMG_UINT32 ui32BridgeID,
+ IMG_VOID *psBridgeIn,
+ PVRSRV_BRIDGE_OUT_CREATE_SYNC_INFO_MOD_OBJ *psCreateSyncInfoModObjOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ MODIFY_SYNC_OP_INFO *psModSyncOpInfo;
+
+ PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CREATE_SYNC_INFO_MOD_OBJ);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psCreateSyncInfoModObjOUT->eError, psPerProc, 1);
+
+ ASSIGN_AND_EXIT_ON_ERROR(psCreateSyncInfoModObjOUT->eError,
+ OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(MODIFY_SYNC_OP_INFO),
+ (IMG_VOID **)&psModSyncOpInfo, 0,
+ "ModSyncOpInfo (MODIFY_SYNC_OP_INFO)"));
+
+ psModSyncOpInfo->psKernelSyncInfo = IMG_NULL;
+
+ psCreateSyncInfoModObjOUT->eError = PVRSRVAllocHandle(psPerProc->psHandleBase,
+ &psCreateSyncInfoModObjOUT->hKernelSyncInfoModObj,
+ psModSyncOpInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO_MOD_OBJ,
+ PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE);
+
+ if (psCreateSyncInfoModObjOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psModSyncOpInfo->hResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_MODIFY_SYNC_OPS,
+ psModSyncOpInfo,
+ 0,
+ &ModifyCompleteSyncOpsCallBack);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psCreateSyncInfoModObjOUT->eError, psPerProc);
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVDestroySyncInfoModObjBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DESTROY_SYNC_INFO_MOD_OBJ *psDestroySyncInfoModObjIN,
+ PVRSRV_BRIDGE_RETURN *psDestroySyncInfoModObjOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ MODIFY_SYNC_OP_INFO *psModSyncOpInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DESTROY_SYNC_INFO_MOD_OBJ);
+
+ psDestroySyncInfoModObjOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID**)&psModSyncOpInfo,
+ psDestroySyncInfoModObjIN->hKernelSyncInfoModObj,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO_MOD_OBJ);
+ if (psDestroySyncInfoModObjOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVDestroySyncInfoModObjBW: PVRSRVLookupHandle failed"));
+ return 0;
+ }
+
+ if(psModSyncOpInfo->psKernelSyncInfo != IMG_NULL)
+ {
+
+ psDestroySyncInfoModObjOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+
+ psDestroySyncInfoModObjOUT->eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psDestroySyncInfoModObjIN->hKernelSyncInfoModObj,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO_MOD_OBJ);
+
+ if (psDestroySyncInfoModObjOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVDestroySyncInfoModObjBW: PVRSRVReleaseHandle failed"));
+ return 0;
+ }
+
+ psDestroySyncInfoModObjOUT->eError = ResManFreeResByPtr(psModSyncOpInfo->hResItem);
+ if (psDestroySyncInfoModObjOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVDestroySyncInfoModObjBW: ResManFreeResByPtr failed"));
+ return 0;
+ }
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVModifyPendingSyncOpsBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_MODIFY_PENDING_SYNC_OPS *psModifySyncOpsIN,
+ PVRSRV_BRIDGE_OUT_MODIFY_PENDING_SYNC_OPS *psModifySyncOpsOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+ MODIFY_SYNC_OP_INFO *psModSyncOpInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MODIFY_PENDING_SYNC_OPS);
+
+ psModifySyncOpsOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID**)&psModSyncOpInfo,
+ psModifySyncOpsIN->hKernelSyncInfoModObj,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO_MOD_OBJ);
+ if (psModifySyncOpsOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVModifyPendingSyncOpsBW: PVRSRVLookupHandle failed"));
+ return 0;
+ }
+
+ psModifySyncOpsOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID**)&psKernelSyncInfo,
+ psModifySyncOpsIN->hKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if (psModifySyncOpsOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVModifyPendingSyncOpsBW: PVRSRVLookupHandle failed"));
+ return 0;
+ }
+
+ if(psModSyncOpInfo->psKernelSyncInfo)
+ {
+
+ psModifySyncOpsOUT->eError = PVRSRV_ERROR_RETRY;
+ PVR_DPF((PVR_DBG_VERBOSE, "PVRSRVModifyPendingSyncOpsBW: SyncInfo Modification object is not empty"));
+ return 0;
+ }
+
+
+ psModSyncOpInfo->psKernelSyncInfo = psKernelSyncInfo;
+ psModSyncOpInfo->ui32ModifyFlags = psModifySyncOpsIN->ui32ModifyFlags;
+ psModSyncOpInfo->ui32ReadOpsPendingSnapShot = psKernelSyncInfo->psSyncData->ui32ReadOpsPending;
+ psModSyncOpInfo->ui32WriteOpsPendingSnapShot = psKernelSyncInfo->psSyncData->ui32WriteOpsPending;
+
+
+
+ psModifySyncOpsOUT->ui32ReadOpsPending = psKernelSyncInfo->psSyncData->ui32ReadOpsPending;
+ psModifySyncOpsOUT->ui32WriteOpsPending = psKernelSyncInfo->psSyncData->ui32WriteOpsPending;
+
+ if(psModifySyncOpsIN->ui32ModifyFlags & PVRSRV_MODIFYSYNCOPS_FLAGS_WO_INC)
+ {
+ psKernelSyncInfo->psSyncData->ui32WriteOpsPending++;
+ }
+
+ if(psModifySyncOpsIN->ui32ModifyFlags & PVRSRV_MODIFYSYNCOPS_FLAGS_RO_INC)
+ {
+ psKernelSyncInfo->psSyncData->ui32ReadOpsPending++;
+ }
+
+
+ psModifySyncOpsOUT->eError = ResManDissociateRes(psModSyncOpInfo->hResItem,
+ psPerProc->hResManContext);
+
+ if (psModifySyncOpsOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVModifyPendingSyncOpsBW: PVRSRVLookupHandle failed"));
+ return 0;
+ }
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVModifyCompleteSyncOpsBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_MODIFY_COMPLETE_SYNC_OPS *psModifySyncOpsIN,
+ PVRSRV_BRIDGE_RETURN *psModifySyncOpsOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ MODIFY_SYNC_OP_INFO *psModSyncOpInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MODIFY_COMPLETE_SYNC_OPS);
+
+ psModifySyncOpsOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID**)&psModSyncOpInfo,
+ psModifySyncOpsIN->hKernelSyncInfoModObj,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO_MOD_OBJ);
+ if (psModifySyncOpsOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVModifyCompleteSyncOpsBW: PVRSRVLookupHandle failed"));
+ return 0;
+ }
+
+ if(psModSyncOpInfo->psKernelSyncInfo == IMG_NULL)
+ {
+
+ psModifySyncOpsOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+
+ psModifySyncOpsOUT->eError = DoModifyCompleteSyncOps(psModSyncOpInfo);
+
+ if (psModifySyncOpsOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVModifyCompleteSyncOpsBW: DoModifyCompleteSyncOps failed"));
+ return 0;
+ }
+
+ psModSyncOpInfo->psKernelSyncInfo = IMG_NULL;
+
+
+ PVRSRVScheduleDeviceCallbacks();
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVSyncOpsFlushToModObjBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SYNC_OPS_FLUSH_TO_MOD_OBJ *psSyncOpsFlushToModObjIN,
+ PVRSRV_BRIDGE_RETURN *psSyncOpsFlushToModObjOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ MODIFY_SYNC_OP_INFO *psModSyncOpInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNC_OPS_FLUSH_TO_MOD_OBJ);
+
+ psSyncOpsFlushToModObjOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID**)&psModSyncOpInfo,
+ psSyncOpsFlushToModObjIN->hKernelSyncInfoModObj,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO_MOD_OBJ);
+ if (psSyncOpsFlushToModObjOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSyncOpsFlushToModObjBW: PVRSRVLookupHandle failed"));
+ return 0;
+ }
+
+ if(psModSyncOpInfo->psKernelSyncInfo == IMG_NULL)
+ {
+
+ psSyncOpsFlushToModObjOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+
+ psSyncOpsFlushToModObjOUT->eError = DoQuerySyncOpsSatisfied(psModSyncOpInfo);
+
+ if (psSyncOpsFlushToModObjOUT->eError != PVRSRV_OK && psSyncOpsFlushToModObjOUT->eError != PVRSRV_ERROR_RETRY)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSyncOpsFlushToModObjBW: DoQuerySyncOpsSatisfied failed"));
+ return 0;
+ }
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVSyncOpsFlushToDeltaBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SYNC_OPS_FLUSH_TO_DELTA *psSyncOpsFlushToDeltaIN,
+ PVRSRV_BRIDGE_RETURN *psSyncOpsFlushToDeltaOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+ IMG_UINT32 ui32DeltaRead;
+ IMG_UINT32 ui32DeltaWrite;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNC_OPS_FLUSH_TO_DELTA);
+
+ psSyncOpsFlushToDeltaOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID**)&psSyncInfo,
+ psSyncOpsFlushToDeltaIN->hKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if (psSyncOpsFlushToDeltaOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSyncOpsFlushToDeltaBW: PVRSRVLookupHandle failed"));
+ return 0;
+ }
+
+ ui32DeltaRead = psSyncInfo->psSyncData->ui32ReadOpsPending - psSyncInfo->psSyncData->ui32ReadOpsComplete;
+ ui32DeltaWrite = psSyncInfo->psSyncData->ui32WriteOpsPending - psSyncInfo->psSyncData->ui32WriteOpsComplete;
+
+ if (ui32DeltaRead <= psSyncOpsFlushToDeltaIN->ui32Delta && ui32DeltaWrite <= psSyncOpsFlushToDeltaIN->ui32Delta)
+ {
+#if defined(PDUMP)
+ IMG_UINT32 ui32MinimumReadOpsComplete;
+
+ ui32MinimumReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending;
+ if (ui32MinimumReadOpsComplete < psSyncOpsFlushToDeltaIN->ui32Delta)
+ {
+ ui32MinimumReadOpsComplete = 0;
+ }
+ else
+ {
+ ui32MinimumReadOpsComplete = ui32MinimumReadOpsComplete - psSyncOpsFlushToDeltaIN->ui32Delta;
+ }
+
+
+ PDumpComment("Poll for read ops complete to delta (%u)",
+ psSyncOpsFlushToDeltaIN->ui32Delta);
+ psSyncOpsFlushToDeltaOUT->eError =
+ PDumpMemPolKM(psSyncInfo->psSyncDataMemInfoKM,
+ offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete),
+ psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ 0xFFFFFFFF,
+ PDUMP_POLL_OPERATOR_GREATEREQUAL,
+ 0,
+ MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+
+
+ PDumpComment("Poll for write ops complete to delta (%u)",
+ psSyncOpsFlushToDeltaIN->ui32Delta);
+ psSyncOpsFlushToDeltaOUT->eError =
+ PDumpMemPolKM(psSyncInfo->psSyncDataMemInfoKM,
+ offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete),
+ psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ 0xFFFFFFFF,
+ PDUMP_POLL_OPERATOR_GREATEREQUAL,
+ 0,
+ MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+#endif
+
+ psSyncOpsFlushToDeltaOUT->eError = PVRSRV_OK;
+ }
+ else
+ {
+ psSyncOpsFlushToDeltaOUT->eError = PVRSRV_ERROR_RETRY;
+ }
+
+ return 0;
+}
+
+
+static PVRSRV_ERROR
+FreeSyncInfoCallback(IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param)
+{
+ PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+ PVRSRV_ERROR eError;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)pvParam;
+
+ eError = PVRSRVFreeSyncInfoKM(psSyncInfo);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ return PVRSRV_OK;
+}
+
+
+static IMG_INT
+PVRSRVAllocSyncInfoBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_ALLOC_SYNC_INFO *psAllocSyncInfoIN,
+ PVRSRV_BRIDGE_OUT_ALLOC_SYNC_INFO *psAllocSyncInfoOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+ PVRSRV_ERROR eError;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ IMG_HANDLE hDevMemContext;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ALLOC_SYNC_INFO);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psAllocSyncInfoOUT->eError, psPerProc, 1);
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_HANDLE *)&psDeviceNode,
+ psAllocSyncInfoIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(eError != PVRSRV_OK)
+ {
+ goto allocsyncinfo_errorexit;
+ }
+
+ hDevMemContext = psDeviceNode->sDevMemoryInfo.pBMKernelContext;
+
+ eError = PVRSRVAllocSyncInfoKM(psDeviceNode,
+ hDevMemContext,
+ &psSyncInfo);
+
+ if (eError != PVRSRV_OK)
+ {
+ goto allocsyncinfo_errorexit;
+ }
+
+ eError = PVRSRVAllocHandle(psPerProc->psHandleBase,
+ &psAllocSyncInfoOUT->hKernelSyncInfo,
+ psSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE);
+
+ if(eError != PVRSRV_OK)
+ {
+ goto allocsyncinfo_errorexit_freesyncinfo;
+ }
+
+ psSyncInfo->hResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_SYNC_INFO,
+ psSyncInfo,
+ 0,
+ FreeSyncInfoCallback);
+
+
+ goto allocsyncinfo_commit;
+
+
+ allocsyncinfo_errorexit_freesyncinfo:
+ PVRSRVFreeSyncInfoKM(psSyncInfo);
+
+ allocsyncinfo_errorexit:
+
+
+ allocsyncinfo_commit:
+ psAllocSyncInfoOUT->eError = eError;
+ COMMIT_HANDLE_BATCH_OR_ERROR(eError, psPerProc);
+
+ return 0;
+}
+
+
+static IMG_INT
+PVRSRVFreeSyncInfoBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_FREE_SYNC_INFO *psFreeSyncInfoIN,
+ PVRSRV_BRIDGE_RETURN *psFreeSyncInfoOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+ PVRSRV_ERROR eError;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_FREE_SYNC_INFO);
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID**)&psSyncInfo,
+ psFreeSyncInfoIN->hKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVFreeSyncInfoBW: PVRSRVLookupHandle failed"));
+ psFreeSyncInfoOUT->eError = eError;
+ return 0;
+ }
+
+ eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psFreeSyncInfoIN->hKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVFreeSyncInfoBW: PVRSRVReleaseHandle failed"));
+ psFreeSyncInfoOUT->eError = eError;
+ return 0;
+ }
+
+ eError = ResManFreeResByPtr(psSyncInfo->hResItem);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVFreeSyncInfoBW: ResManFreeResByPtr failed"));
+ psFreeSyncInfoOUT->eError = eError;
+ return 0;
+ }
+
+ return 0;
+}
+
+
+PVRSRV_ERROR
+CommonBridgeInit(IMG_VOID)
+{
+ IMG_UINT32 i;
+
+ PVR_IO_NSTD(ENUM_DEVICES, PVRSRVEnumerateDevicesBW,
+ 0, sizeof(PVRSRV_BRIDGE_OUT_ENUMDEVICE),
+ offsetof(PVRSRV_BRIDGE_OUT_ENUMDEVICE, eError));
+ PVR_IO_RW(ACQUIRE_DEVICEINFO, PVRSRVAcquireDeviceDataBW);
+ PVR_IO_INV(RELEASE_DEVICEINFO);
+ PVR_IO_RW(CREATE_DEVMEMCONTEXT, PVRSRVCreateDeviceMemContextBW);
+ PVR_IO_W(DESTROY_DEVMEMCONTEXT, PVRSRVDestroyDeviceMemContextBW);
+ PVR_IO_RW(GET_DEVMEM_HEAPINFO, PVRSRVGetDeviceMemHeapInfoBW);
+ PVR_IO_NSTD(ALLOC_DEVICEMEM, PVRSRVAllocDeviceMemBW,
+ sizeof(PVRSRV_BRIDGE_IN_ALLOCDEVICEMEM),
+ sizeof(PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM),
+ offsetof(PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM, eError));
+ PVR_IO_NSTD(FREE_DEVICEMEM, PVRSRVFreeDeviceMemBW,
+ sizeof(PVRSRV_BRIDGE_IN_FREEDEVICEMEM),
+ sizeof(PVRSRV_BRIDGE_RETURN),
+ offsetof(PVRSRV_BRIDGE_RETURN, eError));
+ PVR_IO_NSTD(GETFREE_DEVICEMEM, PVRSRVGetFreeDeviceMemBW,
+ sizeof(PVRSRV_BRIDGE_IN_GETFREEDEVICEMEM),
+ sizeof(PVRSRV_BRIDGE_OUT_GETFREEDEVICEMEM),
+ offsetof(PVRSRV_BRIDGE_OUT_GETFREEDEVICEMEM, eError));
+ PVR_IO_INV(CREATE_COMMANDQUEUE);
+ PVR_IO_INV(DESTROY_COMMANDQUEUE);
+ PVR_IO_RW(MHANDLE_TO_MMAP_DATA, PVRMMapOSMemHandleToMMapDataBW);
+ PVR_IO_RW(CONNECT_SERVICES, PVRSRVConnectBW);
+ PVR_IO_NSTD(DISCONNECT_SERVICES, PVRSRVDisconnectBW,
+ 0, sizeof(PVRSRV_BRIDGE_RETURN),
+ offsetof(PVRSRV_BRIDGE_RETURN, eError));
+ PVR_IO_INV(WRAP_DEVICE_MEM);
+ PVR_IO_INV(GET_DEVICEMEMINFO);
+ PVR_IO_INV(RESERVE_DEV_VIRTMEM);
+ PVR_IO_INV(FREE_DEV_VIRTMEM);
+ PVR_IO_INV(MAP_EXT_MEMORY);
+ PVR_IO_INV(UNMAP_EXT_MEMORY);
+ PVR_IO_RW(MAP_DEV_MEMORY, PVRSRVMapDeviceMemoryBW);
+ PVR_IO_W(UNMAP_DEV_MEMORY, PVRSRVUnmapDeviceMemoryBW);
+ PVR_IO_RW(MAP_DEVICECLASS_MEMORY, PVRSRVMapDeviceClassMemoryBW);
+ PVR_IO_W(UNMAP_DEVICECLASS_MEMORY, PVRSRVUnmapDeviceClassMemoryBW);
+ PVR_IO_INV(MAP_MEM_INFO_TO_USER);
+ PVR_IO_INV(UNMAP_MEM_INFO_FROM_USER);
+ PVR_IO_NSTD(EXPORT_DEVICEMEM, PVRSRVExportDeviceMemBW,
+ sizeof(PVRSRV_BRIDGE_IN_EXPORTDEVICEMEM),
+ sizeof(PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM),
+ offsetof(PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM, eError));
+ PVR_IO_RW(RELEASE_MMAP_DATA, PVRMMapReleaseMMapDataBW);
+ PVR_IO_INV(PROCESS_SIMISR_EVENT);
+ PVR_IO_INV(REGISTER_SIM_PROCESS);
+ PVR_IO_INV(UNREGISTER_SIM_PROCESS);
+ PVR_IO_INV(MAPPHYSTOUSERSPACE);
+ PVR_IO_INV(UNMAPPHYSTOUSERSPACE);
+ PVR_IO_INV(GETPHYSTOUSERSPACEMAP);
+ PVR_IO_INV(GET_FB_STATS);
+ PVR_IO_RW(GET_MISC_INFO, PVRSRVGetMiscInfoBW);
+ PVR_IO_INV(RELEASE_MISC_INFO);
+
+#if defined (SUPPORT_OVERLAY_ROTATE_BLIT)
+ PVR_IO_INV(INIT_3D_OVL_BLT_RES);
+ PVR_IO_INV(DEINIT_3D_OVL_BLT_RES);
+#endif
+
+#if defined(PDUMP)
+ PVR_IO_INV(PDUMP_INIT);
+ PVR_IO_W(PDUMP_MEMPOL, PDumpMemPolBW);
+ PVR_IO_W(PDUMP_DUMPMEM, PDumpMemBW);
+ PVR_IO_NSTD(PDUMP_REG, PDumpRegWithFlagsBW,
+ sizeof(PVRSRV_BRIDGE_IN_PDUMP_DUMPREG),
+ sizeof(PVRSRV_BRIDGE_RETURN),
+ offsetof(PVRSRV_BRIDGE_RETURN, eError));
+ PVR_IO_W(PDUMP_REGPOL, PDumpRegPolBW);
+ PVR_IO_W(PDUMP_COMMENT, PDumpCommentBW);
+ PVR_IO_W(PDUMP_SETFRAME, PDumpSetFrameBW);
+ PVR_IO_R(PDUMP_ISCAPTURING, PDumpIsCaptureFrameBW);
+ PVR_IO_NSTD(PDUMP_DUMPBITMAP, PDumpBitmapBW,
+ sizeof(PVRSRV_BRIDGE_IN_PDUMP_BITMAP),
+ sizeof(PVRSRV_BRIDGE_RETURN),
+ offsetof(PVRSRV_BRIDGE_RETURN, eError));
+ PVR_IO_NSTD(PDUMP_DUMPREADREG, PDumpReadRegBW,
+ sizeof(PVRSRV_BRIDGE_IN_PDUMP_READREG),
+ sizeof(PVRSRV_BRIDGE_RETURN),
+ offsetof(PVRSRV_BRIDGE_RETURN, eError));
+ PVR_IO_W(PDUMP_SYNCPOL, PDumpSyncPolBW);
+ PVR_IO_W(PDUMP_DUMPSYNC, PDumpSyncDumpBW);
+ PVR_IO_W(PDUMP_DRIVERINFO, PDumpDriverInfoBW);
+ PVR_IO_W(PDUMP_DUMPPDDEVPADDR, PDumpPDDevPAddrBW);
+ PVR_IO_W(PDUMP_CYCLE_COUNT_REG_READ, PDumpCycleCountRegReadBW);
+ PVR_IO_NSTD(PDUMP_STARTINITPHASE, PDumpStartInitPhaseBW,
+ 0, sizeof(PVRSRV_BRIDGE_RETURN),
+ offsetof(PVRSRV_BRIDGE_RETURN, eError));
+ PVR_IO_NSTD(PDUMP_STOPINITPHASE, PDumpStopInitPhaseBW,
+ 0, sizeof(PVRSRV_BRIDGE_RETURN),
+ offsetof(PVRSRV_BRIDGE_RETURN, eError));
+#endif
+ PVR_IO_INV(GET_OEMJTABLE);
+ PVR_IO_NSTD(ENUM_CLASS, PVRSRVEnumerateDCBW,
+ sizeof(PVRSRV_BRIDGE_IN_ENUMCLASS),
+ sizeof(PVRSRV_BRIDGE_OUT_ENUMCLASS),
+ offsetof(PVRSRV_BRIDGE_OUT_ENUMCLASS, eError));
+ PVR_IO_RW(OPEN_DISPCLASS_DEVICE, PVRSRVOpenDCDeviceBW);
+ PVR_IO_W(CLOSE_DISPCLASS_DEVICE, PVRSRVCloseDCDeviceBW);
+ PVR_IO_RW(ENUM_DISPCLASS_FORMATS, PVRSRVEnumDCFormatsBW);
+ PVR_IO_RW(ENUM_DISPCLASS_DIMS, PVRSRVEnumDCDimsBW);
+ PVR_IO_RW(GET_DISPCLASS_SYSBUFFER, PVRSRVGetDCSystemBufferBW);
+ PVR_IO_RW(GET_DISPCLASS_INFO, PVRSRVGetDCInfoBW);
+ PVR_IO_RW(CREATE_DISPCLASS_SWAPCHAIN, PVRSRVCreateDCSwapChainBW);
+ PVR_IO_W(DESTROY_DISPCLASS_SWAPCHAIN, PVRSRVDestroyDCSwapChainBW);
+ PVR_IO_NSTD(SET_DISPCLASS_DSTRECT, PVRSRVSetDCDstRectBW,
+ sizeof(PVRSRV_BRIDGE_IN_SET_DISPCLASS_RECT),
+ sizeof(PVRSRV_BRIDGE_RETURN),
+ offsetof(PVRSRV_BRIDGE_RETURN, eError));
+ PVR_IO_NSTD(SET_DISPCLASS_SRCRECT, PVRSRVSetDCSrcRectBW,
+ sizeof(PVRSRV_BRIDGE_IN_SET_DISPCLASS_RECT),
+ sizeof(PVRSRV_BRIDGE_RETURN),
+ offsetof(PVRSRV_BRIDGE_RETURN, eError));
+ PVR_IO_NSTD(SET_DISPCLASS_DSTCOLOURKEY, PVRSRVSetDCDstColourKeyBW,
+ sizeof(PVRSRV_BRIDGE_IN_SET_DISPCLASS_COLOURKEY),
+ sizeof(PVRSRV_BRIDGE_RETURN),
+ offsetof(PVRSRV_BRIDGE_RETURN, eError));
+ PVR_IO_NSTD(SET_DISPCLASS_SRCCOLOURKEY, PVRSRVSetDCSrcColourKeyBW,
+ sizeof(PVRSRV_BRIDGE_IN_SET_DISPCLASS_COLOURKEY),
+ sizeof(PVRSRV_BRIDGE_RETURN),
+ offsetof(PVRSRV_BRIDGE_RETURN, eError));
+ PVR_IO_RW(GET_DISPCLASS_BUFFERS, PVRSRVGetDCBuffersBW);
+ PVR_IO_W(SWAP_DISPCLASS_TO_BUFFER, PVRSRVSwapToDCBufferBW);
+ PVR_IO_W(SWAP_DISPCLASS_TO_SYSTEM, PVRSRVSwapToDCSystemBW);
+ PVR_IO_RW(GET_DISPCLASS_FRONT_BUFFER, PVRSRVGetDCFrontBufferBW);
+ PVR_IO_RW(OPEN_BUFFERCLASS_DEVICE, PVRSRVOpenBCDeviceBW);
+ PVR_IO_W(CLOSE_BUFFERCLASS_DEVICE, PVRSRVCloseBCDeviceBW);
+ PVR_IO_RW(GET_BUFFERCLASS_INFO, PVRSRVGetBCInfoBW);
+ PVR_IO_RW(GET_BUFFERCLASS_BUFFER, PVRSRVGetBCBufferBW);
+ PVR_IO_RW(WRAP_EXT_MEMORY, PVRSRVWrapExtMemoryBW);
+ PVR_IO_W(UNWRAP_EXT_MEMORY, PVRSRVUnwrapExtMemoryBW);
+ PVR_IO_RW(ALLOC_SHARED_SYS_MEM, PVRSRVAllocSharedSysMemoryBW);
+ PVR_IO_RW(FREE_SHARED_SYS_MEM, PVRSRVFreeSharedSysMemoryBW);
+ PVR_IO_RW(MAP_MEMINFO_MEM, PVRSRVMapMemInfoMemBW);
+ PVR_IO_RW(GETMMU_PD_DEVPADDR, MMU_GetPDDevPAddrBW);
+ PVR_IO_NSTD(INITSRV_CONNECT, PVRSRVInitSrvConnectBW,
+ 0, sizeof(PVRSRV_BRIDGE_RETURN),
+ offsetof(PVRSRV_BRIDGE_RETURN, eError));
+ PVR_IO_W(INITSRV_DISCONNECT, PVRSRVInitSrvDisconnectBW);
+ PVR_IO_W(EVENT_OBJECT_WAIT, PVRSRVEventObjectWaitBW);
+ PVR_IO_RW(EVENT_OBJECT_OPEN, PVRSRVEventObjectOpenBW);
+ PVR_IO_W(EVENT_OBJECT_CLOSE, PVRSRVEventObjectCloseBW);
+ PVR_IO_NSTD(CREATE_SYNC_INFO_MOD_OBJ, PVRSRVCreateSyncInfoModObjBW,
+ 0, sizeof(PVRSRV_BRIDGE_OUT_CREATE_SYNC_INFO_MOD_OBJ),
+ offsetof(PVRSRV_BRIDGE_OUT_CREATE_SYNC_INFO_MOD_OBJ, eError));
+ PVR_IO_W(DESTROY_SYNC_INFO_MOD_OBJ, PVRSRVDestroySyncInfoModObjBW);
+ PVR_IO_RW(MODIFY_PENDING_SYNC_OPS, PVRSRVModifyPendingSyncOpsBW);
+ PVR_IO_W(MODIFY_COMPLETE_SYNC_OPS, PVRSRVModifyCompleteSyncOpsBW);
+ PVR_IO_W(SYNC_OPS_FLUSH_TO_MOD_OBJ, PVRSRVSyncOpsFlushToModObjBW);
+ PVR_IO_W(SYNC_OPS_FLUSH_TO_DELTA, PVRSRVSyncOpsFlushToDeltaBW);
+ PVR_IO_RW(ALLOC_SYNC_INFO, PVRSRVAllocSyncInfoBW);
+ PVR_IO_W(FREE_SYNC_INFO, PVRSRVFreeSyncInfoBW);
+#if defined (SUPPORT_SGX)
+ SetSGXDispatchTableEntry();
+#endif
+#if defined (SUPPORT_VGX)
+ SetVGXDispatchTableEntry();
+#endif
+#if defined (SUPPORT_MSVDX)
+ SetMSVDXDispatchTableEntry();
+#endif
+
+
+
+
+ for(i=0;i<BRIDGE_DISPATCH_TABLE_ENTRY_COUNT;i++)
+ {
+ if(!g_BridgeDispatchTable[i].pfFunction)
+ {
+ g_BridgeDispatchTable[i].pfFunction = &DummyBW;
+#if defined(DEBUG_BRIDGE_KM)
+ g_BridgeDispatchTable[i].pszIOCName = "_PVRSRV_BRIDGE_DUMMY";
+ g_BridgeDispatchTable[i].pszFunctionName = "DummyBW";
+ g_BridgeDispatchTable[i].ui32CallCount = 0;
+ g_BridgeDispatchTable[i].ui32CopyFromUserTotalBytes = 0;
+ g_BridgeDispatchTable[i].ui32CopyToUserTotalBytes = 0;
+#endif
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+IMG_INT BridgedDispatchKM(PVRSRV_PER_PROCESS_DATA * psPerProc,
+ PVRSRV_BRIDGE_PACKAGE * psBridgePackageKM)
+{
+
+ IMG_VOID * psBridgeIn;
+ IMG_VOID * psBridgeOut;
+ BridgeWrapperFunction pfBridgeHandler;
+ PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY *dte;
+ IMG_UINT32 ui32BridgeID = psBridgePackageKM->ui32BridgeID;
+ IMG_INT err = -EFAULT;
+ PVRSRV_ERROR pvr_err = PVRSRV_OK;
+
+ dte = &g_BridgeDispatchTable[ui32BridgeID];
+
+#if defined(DEBUG_TRACE_BRIDGE_KM)
+ pr_debug("pvr %s: %s", __func__, dte->pszIOCName);
+#endif
+
+#if defined(DEBUG_BRIDGE_KM)
+ dte->ui32CallCount++;
+ g_BridgeGlobalStats.ui32IOCTLCount++;
+#endif
+
+ if (psBridgePackageKM->ui32InBufferSize != dte->in_size ||
+ psBridgePackageKM->ui32OutBufferSize != dte->out_size) {
+ pr_debug("pvr: invalid param size for IOCTL#%d:\n"
+ " kern/user in,out: %d/%d,%d/%d\n",
+ ui32BridgeID,
+ dte->in_size, psBridgePackageKM->ui32InBufferSize,
+ dte->out_size, psBridgePackageKM->ui32OutBufferSize);
+ goto return_fault;
+ }
+
+ if(!psPerProc->bInitProcess)
+ {
+ if(PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RAN))
+ {
+ if(!PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Initialisation failed. Driver unusable.",
+ __FUNCTION__));
+ goto return_fault;
+ }
+ }
+ else
+ {
+ if(PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RUNNING))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Initialisation is in progress",
+ __FUNCTION__));
+ goto return_fault;
+ }
+ else
+ {
+
+ switch(ui32BridgeID)
+ {
+ case PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_CONNECT_SERVICES):
+ case PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_DISCONNECT_SERVICES):
+ case PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_INITSRV_CONNECT):
+ case PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_INITSRV_DISCONNECT):
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "%s: Driver initialisation not completed yet.",
+ __FUNCTION__));
+ goto return_fault;
+ }
+ }
+ }
+ }
+
+
+
+#if defined(__linux__)
+ {
+
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+
+
+ psBridgeIn = ((ENV_DATA *)psSysData->pvEnvSpecificData)->pvBridgeData;
+ psBridgeOut = (IMG_PVOID)((IMG_PBYTE)psBridgeIn + PVRSRV_MAX_BRIDGE_IN_SIZE);
+
+
+#if defined(DEBUG)
+ PVR_ASSERT(psBridgePackageKM->ui32InBufferSize < PVRSRV_MAX_BRIDGE_IN_SIZE);
+ PVR_ASSERT(psBridgePackageKM->ui32OutBufferSize < PVRSRV_MAX_BRIDGE_OUT_SIZE);
+#endif
+
+ if(psBridgePackageKM->ui32InBufferSize > 0)
+ {
+ if(!OSAccessOK(PVR_VERIFY_READ,
+ psBridgePackageKM->pvParamIn,
+ psBridgePackageKM->ui32InBufferSize))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Invalid pvParamIn pointer", __FUNCTION__));
+ }
+
+ if(CopyFromUserWrapper(psPerProc,
+ ui32BridgeID,
+ psBridgeIn,
+ psBridgePackageKM->pvParamIn,
+ psBridgePackageKM->ui32InBufferSize)
+ != PVRSRV_OK)
+ {
+ goto return_fault;
+ }
+ }
+ }
+#else
+ psBridgeIn = psBridgePackageKM->pvParamIn;
+ psBridgeOut = psBridgePackageKM->pvParamOut;
+#endif
+
+ if(ui32BridgeID >= (BRIDGE_DISPATCH_TABLE_ENTRY_COUNT))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: ui32BridgeID = %d is out if range!",
+ __FUNCTION__, ui32BridgeID));
+ goto return_fault;
+ }
+ pfBridgeHandler = (BridgeWrapperFunction)dte->pfFunction;
+ err = pfBridgeHandler(ui32BridgeID,
+ psBridgeIn,
+ psBridgeOut,
+ psPerProc);
+ if(err < 0)
+ {
+ goto return_fault;
+ }
+
+
+#if defined(__linux__)
+
+ if(CopyToUserWrapper(psPerProc,
+ ui32BridgeID,
+ psBridgePackageKM->pvParamOut,
+ psBridgeOut,
+ psBridgePackageKM->ui32OutBufferSize)
+ != PVRSRV_OK)
+ {
+ goto return_fault;
+ }
+#endif
+
+ err = 0;
+ if (dte->out_size && dte->err_offset)
+ pvr_err = *(PVRSRV_ERROR *)(((u8 *)psBridgeOut) +
+ dte->err_offset);
+ else
+ pvr_err = 0;
+return_fault:
+ ReleaseHandleBatch(psPerProc);
+
+ if (err < 0 || pvr_err)
+ pr_err("pvr: %.*s: ioctl#%d failed (err %d, pvr_err %d)\n",
+ sizeof(psPerProc->name), psPerProc->name,
+ ui32BridgeID, err, pvr_err);
+
+ return err;
+}
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef __BRIDGED_PVR_BRIDGE_H__
+#define __BRIDGED_PVR_BRIDGE_H__
+
+#include "pvr_bridge.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#if defined(__linux__)
+#define PVRSRV_GET_BRIDGE_ID(X) _IOC_NR(X)
+#else
+#define PVRSRV_GET_BRIDGE_ID(X) ((X) - PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST))
+#endif
+
+#ifndef ENOMEM
+#define ENOMEM 12
+#endif
+#ifndef EFAULT
+#define EFAULT 14
+#endif
+#ifndef ENOTTY
+#define ENOTTY 25
+#endif
+
+#if defined(DEBUG_BRIDGE_KM)
+PVRSRV_ERROR
+CopyFromUserWrapper(PVRSRV_PER_PROCESS_DATA *pProcData,
+ IMG_UINT32 ui32BridgeID,
+ IMG_VOID *pvDest,
+ IMG_VOID *pvSrc,
+ IMG_UINT32 ui32Size);
+PVRSRV_ERROR
+CopyToUserWrapper(PVRSRV_PER_PROCESS_DATA *pProcData,
+ IMG_UINT32 ui32BridgeID,
+ IMG_VOID *pvDest,
+ IMG_VOID *pvSrc,
+ IMG_UINT32 ui32Size);
+#else
+#define CopyFromUserWrapper(pProcData, ui32BridgeID, pvDest, pvSrc, ui32Size) \
+ OSCopyFromUser(pProcData, pvDest, pvSrc, ui32Size)
+#define CopyToUserWrapper(pProcData, ui32BridgeID, pvDest, pvSrc, ui32Size) \
+ OSCopyToUser(pProcData, pvDest, pvSrc, ui32Size)
+#endif
+
+
+#define ASSIGN_AND_RETURN_ON_ERROR(error, src, res) \
+ do \
+ { \
+ (error) = (src); \
+ if ((error) != PVRSRV_OK) \
+ { \
+ return (res); \
+ } \
+ } while ((error) != PVRSRV_OK)
+
+#define ASSIGN_AND_EXIT_ON_ERROR(error, src) \
+ ASSIGN_AND_RETURN_ON_ERROR(error, src, 0)
+
+#if defined (PVR_SECURE_HANDLES)
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(NewHandleBatch)
+#endif
+static INLINE PVRSRV_ERROR
+NewHandleBatch(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_UINT32 ui32BatchSize)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(!psPerProc->bHandlesBatched);
+
+ eError = PVRSRVNewHandleBatch(psPerProc->psHandleBase, ui32BatchSize);
+
+ if (eError == PVRSRV_OK)
+ {
+ psPerProc->bHandlesBatched = IMG_TRUE;
+ }
+
+ return eError;
+}
+
+#define NEW_HANDLE_BATCH_OR_ERROR(error, psPerProc, ui32BatchSize) \
+ ASSIGN_AND_EXIT_ON_ERROR(error, NewHandleBatch(psPerProc, ui32BatchSize))
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(CommitHandleBatch)
+#endif
+static INLINE PVRSRV_ERROR
+CommitHandleBatch(PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVR_ASSERT(psPerProc->bHandlesBatched);
+
+ psPerProc->bHandlesBatched = IMG_FALSE;
+
+ return PVRSRVCommitHandleBatch(psPerProc->psHandleBase);
+}
+
+
+#define COMMIT_HANDLE_BATCH_OR_ERROR(error, psPerProc) \
+ ASSIGN_AND_EXIT_ON_ERROR(error, CommitHandleBatch(psPerProc))
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(ReleaseHandleBatch)
+#endif
+static INLINE IMG_VOID
+ReleaseHandleBatch(PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ if (psPerProc->bHandlesBatched)
+ {
+ psPerProc->bHandlesBatched = IMG_FALSE;
+
+ PVRSRVReleaseHandleBatch(psPerProc->psHandleBase);
+ }
+}
+#else
+#define NEW_HANDLE_BATCH_OR_ERROR(error, psPerProc, ui32BatchSize)
+#define COMMIT_HANDLE_BATCH_OR_ERROR(error, psPerProc)
+#define ReleaseHandleBatch(psPerProc)
+#endif
+
+IMG_INT
+DummyBW(IMG_UINT32 ui32BridgeID,
+ IMG_VOID *psBridgeIn,
+ IMG_VOID *psBridgeOut,
+ PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+typedef IMG_INT (*BridgeWrapperFunction)(IMG_UINT32 ui32BridgeID,
+ IMG_VOID *psBridgeIn,
+ IMG_VOID *psBridgeOut,
+ PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+typedef struct _PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY
+{
+ BridgeWrapperFunction pfFunction;
+ size_t in_size;
+ size_t out_size;
+ off_t err_offset;
+#if defined(DEBUG_BRIDGE_KM)
+ const IMG_CHAR *pszIOCName;
+ const IMG_CHAR *pszFunctionName;
+ IMG_UINT32 ui32CallCount;
+ IMG_UINT32 ui32CopyFromUserTotalBytes;
+ IMG_UINT32 ui32CopyToUserTotalBytes;
+#endif
+}PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY;
+
+#if defined(SUPPORT_VGX) || defined(SUPPORT_MSVDX)
+ #if defined(SUPPORT_VGX)
+ #define BRIDGE_DISPATCH_TABLE_ENTRY_COUNT (PVRSRV_BRIDGE_LAST_VGX_CMD+1)
+ #define PVRSRV_BRIDGE_LAST_DEVICE_CMD PVRSRV_BRIDGE_LAST_VGX_CMD
+ #else
+ #define BRIDGE_DISPATCH_TABLE_ENTRY_COUNT (PVRSRV_BRIDGE_LAST_MSVDX_CMD+1)
+ #define PVRSRV_BRIDGE_LAST_DEVICE_CMD PVRSRV_BRIDGE_LAST_MSVDX_CMD
+ #endif
+#else
+ #if defined(SUPPORT_SGX)
+ #define BRIDGE_DISPATCH_TABLE_ENTRY_COUNT (PVRSRV_BRIDGE_LAST_SGX_CMD+1)
+ #define PVRSRV_BRIDGE_LAST_DEVICE_CMD PVRSRV_BRIDGE_LAST_SGX_CMD
+ #else
+ #define BRIDGE_DISPATCH_TABLE_ENTRY_COUNT (PVRSRV_BRIDGE_LAST_NON_DEVICE_CMD+1)
+ #define PVRSRV_BRIDGE_LAST_DEVICE_CMD PVRSRV_BRIDGE_LAST_NON_DEVICE_CMD
+ #endif
+#endif
+
+extern PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY g_BridgeDispatchTable[BRIDGE_DISPATCH_TABLE_ENTRY_COUNT];
+
+IMG_VOID
+_SetDispatchTableEntry(IMG_UINT32 ui32Index,
+ const IMG_CHAR *pszIOCName,
+ BridgeWrapperFunction pfFunction,
+ const IMG_CHAR *pszFunctionName,
+ size_t in_size, size_t out_size,
+ off_t err_offset);
+
+
+#define __set_table(id, fn, in_size, out_size, err_offset) \
+ _SetDispatchTableEntry(PVRSRV_GET_BRIDGE_ID(id), #id, \
+ (BridgeWrapperFunction)fn, #fn, \
+ in_size, out_size, err_offset)
+
+#define PVR_IO_RW(id, fn) \
+ __set_table(PVRSRV_BRIDGE_##id, fn, \
+ sizeof(PVRSRV_BRIDGE_IN_##id), \
+ sizeof(PVRSRV_BRIDGE_OUT_##id), \
+ offsetof(PVRSRV_BRIDGE_OUT_##id, eError))
+
+#define PVR_IO_R(id, fn) \
+ __set_table(PVRSRV_BRIDGE_##id, fn, 0, \
+ sizeof(PVRSRV_BRIDGE_OUT_##id), \
+ offsetof(PVRSRV_BRIDGE_OUT_##id, eError))
+
+#define PVR_IO_W(id, fn) \
+ __set_table(PVRSRV_BRIDGE_##id, fn, \
+ sizeof(PVRSRV_BRIDGE_IN_##id), \
+ sizeof(PVRSRV_BRIDGE_RETURN), \
+ offsetof(PVRSRV_BRIDGE_RETURN, eError))
+
+#define PVR_IO_NSTD(id, fn, in_size, out_size, err_offset) \
+ __set_table(PVRSRV_BRIDGE_##id, fn, in_size, out_size, err_offset)
+
+#define PVR_IO_INV(id) \
+ __set_table(PVRSRV_BRIDGE_##id, DummyBW, 0, 0, 0)
+
+#define DISPATCH_TABLE_GAP_THRESHOLD 5
+
+#if defined(DEBUG)
+#define PVRSRV_BRIDGE_ASSERT_CMD(X, Y) PVR_ASSERT(X == PVRSRV_GET_BRIDGE_ID(Y))
+#else
+#define PVRSRV_BRIDGE_ASSERT_CMD(X, Y) PVR_UNREFERENCED_PARAMETER(X)
+#endif
+
+
+#if defined(DEBUG_BRIDGE_KM)
+typedef struct _PVRSRV_BRIDGE_GLOBAL_STATS
+{
+ IMG_UINT32 ui32IOCTLCount;
+ IMG_UINT32 ui32TotalCopyFromUserBytes;
+ IMG_UINT32 ui32TotalCopyToUserBytes;
+}PVRSRV_BRIDGE_GLOBAL_STATS;
+
+extern PVRSRV_BRIDGE_GLOBAL_STATS g_BridgeGlobalStats;
+#endif
+
+
+PVRSRV_ERROR CommonBridgeInit(IMG_VOID);
+
+IMG_INT BridgedDispatchKM(PVRSRV_PER_PROCESS_DATA * psPerProc,
+ PVRSRV_BRIDGE_PACKAGE * psBridgePackageKM);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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 "img_defs.h"
+#include "servicesint.h"
+#include "bridged_support.h"
+
+
+PVRSRV_ERROR
+PVRSRVLookupOSMemHandle(PVRSRV_HANDLE_BASE *psHandleBase, IMG_HANDLE *phOSMemHandle, IMG_HANDLE hMHandle)
+{
+ IMG_HANDLE hMHandleInt;
+ PVRSRV_HANDLE_TYPE eHandleType;
+ PVRSRV_ERROR eError;
+
+
+ eError = PVRSRVLookupHandleAnyType(psHandleBase, &hMHandleInt,
+ &eHandleType,
+ hMHandle);
+ if(eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ switch(eHandleType)
+ {
+#if defined(PVR_SECURE_HANDLES)
+ case PVRSRV_HANDLE_TYPE_MEM_INFO:
+ case PVRSRV_HANDLE_TYPE_MEM_INFO_REF:
+ case PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO:
+ {
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo = (PVRSRV_KERNEL_MEM_INFO *)hMHandleInt;
+
+ *phOSMemHandle = psMemInfo->sMemBlk.hOSMemHandle;
+
+ break;
+ }
+ case PVRSRV_HANDLE_TYPE_SYNC_INFO:
+ {
+ PVRSRV_KERNEL_SYNC_INFO *psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)hMHandleInt;
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo = psSyncInfo->psSyncDataMemInfoKM;
+
+ *phOSMemHandle = psMemInfo->sMemBlk.hOSMemHandle;
+
+ break;
+ }
+ case PVRSRV_HANDLE_TYPE_SOC_TIMER:
+ {
+ *phOSMemHandle = (IMG_VOID *)hMHandleInt;
+ break;
+ }
+#else
+ case PVRSRV_HANDLE_TYPE_NONE:
+ *phOSMemHandle = (IMG_VOID *)hMHandleInt;
+ break;
+#endif
+ default:
+ return PVRSRV_ERROR_BAD_MAPPING;
+ }
+
+ return PVRSRV_OK;
+}
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef __BRIDGED_SUPPORT_H__
+#define __BRIDGED_SUPPORT_H__
+
+#include "handle.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+PVRSRV_ERROR PVRSRVLookupOSMemHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phOSMemHandle, IMG_HANDLE hMHandle);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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 <stddef.h>
+
+#include "img_defs.h"
+
+#if defined(SUPPORT_SGX)
+
+#include "services.h"
+#include "pvr_debug.h"
+#include "pvr_bridge.h"
+#include "sgx_bridge.h"
+#include "perproc.h"
+#include "power.h"
+#include "pvr_bridge_km.h"
+#include "sgx_bridge_km.h"
+
+#if defined(SUPPORT_MSVDX)
+ #include "msvdx_bridge.h"
+#endif
+
+#include "bridged_pvr_bridge.h"
+#include "bridged_sgx_bridge.h"
+#include "sgxutils.h"
+#include "pdump_km.h"
+#include "pvr_trace_cmd.h"
+
+static IMG_INT
+SGXGetClientInfoBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GETCLIENTINFO *psGetClientInfoIN,
+ PVRSRV_BRIDGE_OUT_GETCLIENTINFO *psGetClientInfoOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_GETCLIENTINFO);
+
+ psGetClientInfoOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psGetClientInfoIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psGetClientInfoOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psGetClientInfoOUT->eError =
+ SGXGetClientInfoKM(hDevCookieInt,
+ &psGetClientInfoOUT->sClientInfo);
+ return 0;
+}
+
+static IMG_INT
+SGXReleaseClientInfoBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RELEASECLIENTINFO *psReleaseClientInfoIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+ IMG_HANDLE hDevCookieInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_RELEASECLIENTINFO);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psReleaseClientInfoIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookieInt)->pvDevice;
+
+ PVR_ASSERT(psDevInfo->ui32ClientRefCount > 0);
+
+ psDevInfo->ui32ClientRefCount--;
+
+ psRetOUT->eError = PVRSRV_OK;
+
+ return 0;
+}
+
+
+static IMG_INT
+SGXGetInternalDevInfoBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GETINTERNALDEVINFO *psSGXGetInternalDevInfoIN,
+ PVRSRV_BRIDGE_OUT_GETINTERNALDEVINFO *psSGXGetInternalDevInfoOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_GETINTERNALDEVINFO);
+
+ psSGXGetInternalDevInfoOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psSGXGetInternalDevInfoIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psSGXGetInternalDevInfoOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psSGXGetInternalDevInfoOUT->eError =
+ SGXGetInternalDevInfoKM(hDevCookieInt,
+ &psSGXGetInternalDevInfoOUT->sSGXInternalDevInfo);
+
+
+ psSGXGetInternalDevInfoOUT->eError =
+ PVRSRVAllocHandle(psPerProc->psHandleBase,
+ &psSGXGetInternalDevInfoOUT->sSGXInternalDevInfo.hHostCtlKernelMemInfoHandle,
+ psSGXGetInternalDevInfoOUT->sSGXInternalDevInfo.hHostCtlKernelMemInfoHandle,
+ PVRSRV_HANDLE_TYPE_MEM_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+
+ return 0;
+}
+
+
+static IMG_INT
+SGXDoKickBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DOKICK *psDoKickIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_UINT32 i;
+ IMG_INT ret = 0;
+ IMG_UINT32 ui32NumDstSyncs;
+ IMG_HANDLE *phKernelSyncInfoHandles = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_DOKICK);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psDoKickIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.hCCBKernelMemInfo,
+ psDoKickIN->sCCBKick.hCCBKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ if(psDoKickIN->sCCBKick.hTA3DSyncInfo != IMG_NULL)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.hTA3DSyncInfo,
+ psDoKickIN->sCCBKick.hTA3DSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ if(psDoKickIN->sCCBKick.hTASyncInfo != IMG_NULL)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.hTASyncInfo,
+ psDoKickIN->sCCBKick.hTASyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ if(psDoKickIN->sCCBKick.h3DSyncInfo != IMG_NULL)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.h3DSyncInfo,
+ psDoKickIN->sCCBKick.h3DSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+
+ if (psDoKickIN->sCCBKick.ui32NumTASrcSyncs > SGX_MAX_TA_SRC_SYNCS)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+
+ for(i=0; i<psDoKickIN->sCCBKick.ui32NumTASrcSyncs; i++)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.ahTASrcKernelSyncInfo[i],
+ psDoKickIN->sCCBKick.ahTASrcKernelSyncInfo[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ if (psDoKickIN->sCCBKick.ui32NumTADstSyncs > SGX_MAX_TA_DST_SYNCS)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+
+ for(i=0; i<psDoKickIN->sCCBKick.ui32NumTADstSyncs; i++)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.ahTADstKernelSyncInfo[i],
+ psDoKickIN->sCCBKick.ahTADstKernelSyncInfo[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ if (psDoKickIN->sCCBKick.ui32Num3DSrcSyncs > SGX_MAX_3D_SRC_SYNCS)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+
+ for(i=0; i<psDoKickIN->sCCBKick.ui32Num3DSrcSyncs; i++)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.ah3DSrcKernelSyncInfo[i],
+ psDoKickIN->sCCBKick.ah3DSrcKernelSyncInfo[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+#else
+
+ if (psDoKickIN->sCCBKick.ui32NumSrcSyncs > SGX_MAX_SRC_SYNCS)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+ for(i=0; i<psDoKickIN->sCCBKick.ui32NumSrcSyncs; i++)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.ahSrcKernelSyncInfo[i],
+ psDoKickIN->sCCBKick.ahSrcKernelSyncInfo[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+#endif
+
+ if (psDoKickIN->sCCBKick.ui32NumTAStatusVals > SGX_MAX_TA_STATUS_VALS)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+ for (i = 0; i < psDoKickIN->sCCBKick.ui32NumTAStatusVals; i++)
+ {
+ psRetOUT->eError =
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.asTAStatusUpdate[i].hKernelMemInfo,
+ psDoKickIN->sCCBKick.asTAStatusUpdate[i].hKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+#else
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.ahTAStatusSyncInfo[i],
+ psDoKickIN->sCCBKick.ahTAStatusSyncInfo[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+#endif
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ if (psDoKickIN->sCCBKick.ui32Num3DStatusVals > SGX_MAX_3D_STATUS_VALS)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+ for(i = 0; i < psDoKickIN->sCCBKick.ui32Num3DStatusVals; i++)
+ {
+ psRetOUT->eError =
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.as3DStatusUpdate[i].hKernelMemInfo,
+ psDoKickIN->sCCBKick.as3DStatusUpdate[i].hKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+#else
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.ah3DStatusSyncInfo[i],
+ psDoKickIN->sCCBKick.ah3DStatusSyncInfo[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+#endif
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ ui32NumDstSyncs = psDoKickIN->sCCBKick.ui32NumDstSyncObjects;
+
+ if(ui32NumDstSyncs > 0)
+ {
+ if(!OSAccessOK(PVR_VERIFY_READ,
+ psDoKickIN->sCCBKick.pahDstSyncHandles,
+ ui32NumDstSyncs * sizeof(IMG_HANDLE)))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: SGXDoKickBW:"
+ " Invalid pasDstSyncHandles pointer", __FUNCTION__));
+ return -EFAULT;
+ }
+
+ psRetOUT->eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32NumDstSyncs * sizeof(IMG_HANDLE),
+ (IMG_VOID **)&phKernelSyncInfoHandles,
+ 0,
+ "Array of Synchronization Info Handles");
+ if (psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ if(CopyFromUserWrapper(psPerProc,
+ ui32BridgeID,
+ phKernelSyncInfoHandles,
+ psDoKickIN->sCCBKick.pahDstSyncHandles,
+ ui32NumDstSyncs * sizeof(IMG_HANDLE)) != PVRSRV_OK)
+ {
+ ret = -EFAULT;
+ goto PVRSRV_BRIDGE_SGX_DOKICK_RETURN_RESULT;
+ }
+
+
+ psDoKickIN->sCCBKick.pahDstSyncHandles = phKernelSyncInfoHandles;
+
+ for( i = 0; i < ui32NumDstSyncs; i++)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.pahDstSyncHandles[i],
+ psDoKickIN->sCCBKick.pahDstSyncHandles[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_DOKICK_RETURN_RESULT;
+ }
+
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.hKernelHWSyncListMemInfo,
+ psDoKickIN->sCCBKick.hKernelHWSyncListMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_DOKICK_RETURN_RESULT;
+ }
+ }
+
+ psRetOUT->eError =
+ SGXDoKickKM(hDevCookieInt, &psDoKickIN->sCCBKick,
+ psPerProc);
+
+PVRSRV_BRIDGE_SGX_DOKICK_RETURN_RESULT:
+
+ if(phKernelSyncInfoHandles)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32NumDstSyncs * sizeof(IMG_HANDLE),
+ (IMG_VOID *)phKernelSyncInfoHandles,
+ 0);
+
+ }
+ return ret;
+}
+
+
+static IMG_INT
+SGXScheduleProcessQueuesBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGX_SCHEDULE_PROCESS_QUEUES *psScheduleProcQIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_SCHEDULE_PROCESS_QUEUES);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psScheduleProcQIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = SGXScheduleProcessQueuesKM(hDevCookieInt);
+
+ return 0;
+}
+
+
+#if defined(TRANSFER_QUEUE)
+static IMG_INT
+SGXSubmitTransferBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SUBMITTRANSFER *psSubmitTransferIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ PVRSRV_TRANSFER_SGX_KICK *psKick;
+ IMG_UINT32 i;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_SUBMITTRANSFER);
+ PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+
+ psKick = &psSubmitTransferIN->sKick;
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSubmitTransferIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psKick->hCCBMemInfo,
+ psKick->hCCBMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ if (psKick->hTASyncInfo != IMG_NULL)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psKick->hTASyncInfo,
+ psKick->hTASyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ if (psKick->h3DSyncInfo != IMG_NULL)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psKick->h3DSyncInfo,
+ psKick->h3DSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ if (psKick->ui32NumSrcSync > SGX_MAX_TRANSFER_SYNC_OPS)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+ for (i = 0; i < psKick->ui32NumSrcSync; i++)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psKick->ahSrcSyncInfo[i],
+ psKick->ahSrcSyncInfo[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ if (psKick->ui32NumDstSync > SGX_MAX_TRANSFER_SYNC_OPS)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+ for (i = 0; i < psKick->ui32NumDstSync; i++)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psKick->ahDstSyncInfo[i],
+ psKick->ahDstSyncInfo[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ psRetOUT->eError = SGXSubmitTransferKM(hDevCookieInt, psKick, psPerProc);
+
+ return 0;
+}
+
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+static IMG_INT
+SGXSubmit2DBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SUBMIT2D *psSubmit2DIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ PVRSRV_2D_SGX_KICK *psKick;
+ IMG_UINT32 i;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_SUBMIT2D);
+ PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSubmit2DIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psKick = &psSubmit2DIN->sKick;
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psKick->hCCBMemInfo,
+ psKick->hCCBMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ if (psKick->hTASyncInfo != IMG_NULL)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psKick->hTASyncInfo,
+ psKick->hTASyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ if (psKick->h3DSyncInfo != IMG_NULL)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psKick->h3DSyncInfo,
+ psKick->h3DSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ if (psKick->ui32NumSrcSync > SGX_MAX_2D_SRC_SYNC_OPS)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+ for (i = 0; i < psKick->ui32NumSrcSync; i++)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psKick->ahSrcSyncInfo[i],
+ psKick->ahSrcSyncInfo[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ if (psKick->hDstSyncInfo != IMG_NULL)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psKick->hDstSyncInfo,
+ psKick->hDstSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ psRetOUT->eError =
+ SGXSubmit2DKM(hDevCookieInt, psKick);
+
+ return 0;
+}
+#endif
+#endif
+
+
+static IMG_INT
+SGXGetMiscInfoBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGXGETMISCINFO *psSGXGetMiscInfoIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_HANDLE hDevMemContextInt = 0;
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+ SGX_MISC_INFO sMiscInfo;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_SGX_GETMISCINFO);
+
+ psRetOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSGXGetMiscInfoIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+
+ if (psSGXGetMiscInfoIN->psMiscInfo->eRequest == SGX_MISC_INFO_REQUEST_MEMREAD)
+ {
+ psRetOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevMemContextInt,
+ psSGXGetMiscInfoIN->psMiscInfo->hDevMemContext,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+#endif
+
+ psDeviceNode = hDevCookieInt;
+ PVR_ASSERT(psDeviceNode != IMG_NULL);
+ if (psDeviceNode == IMG_NULL)
+ {
+ return -EFAULT;
+ }
+
+ psDevInfo = psDeviceNode->pvDevice;
+
+
+ psRetOUT->eError = CopyFromUserWrapper(psPerProc,
+ ui32BridgeID,
+ &sMiscInfo,
+ psSGXGetMiscInfoIN->psMiscInfo,
+ sizeof(SGX_MISC_INFO));
+ if (psRetOUT->eError != PVRSRV_OK)
+ {
+ return -EFAULT;
+ }
+
+ {
+ psRetOUT->eError = SGXGetMiscInfoKM(psDevInfo, &sMiscInfo, psDeviceNode, hDevMemContextInt);
+
+ if (psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+#if defined(PVRSRV_RESOURCE_PROFILING)
+ if (psSGXGetMiscInfoIN->psMiscInfo->eRequest == SGX_MISC_INFO_RESOURCEPROF_MEM_INFO)
+ {
+ NEW_HANDLE_BATCH_OR_ERROR(psRetOUT->eError, psPerProc, 1);
+ if (psRetOUT->eError != PVRSRV_OK)
+ { /*PVR_LOG(("RESOURCE_PROFILING: batch handle fail\n"));*/
+ return -EFAULT;
+ }
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &sMiscInfo.uData.sSGXResProfMemInfo.hKernelMemInfo,
+ psDevInfo->psResProfMemInfo,
+ PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psRetOUT->eError, psPerProc);
+ if (psRetOUT->eError != PVRSRV_OK)
+ {
+ /*PVR_LOG(("RESOURCE_PROFILING: batch commit fail\n"));*/
+ return -EFAULT;
+ }
+ }
+#endif
+
+ psRetOUT->eError = CopyToUserWrapper(psPerProc,
+ ui32BridgeID,
+ psSGXGetMiscInfoIN->psMiscInfo,
+ &sMiscInfo,
+ sizeof(SGX_MISC_INFO));
+ if (psRetOUT->eError != PVRSRV_OK)
+ {
+ return -EFAULT;
+ }
+ return 0;
+}
+
+
+static IMG_INT
+SGXReadHWPerfCBBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGX_READ_HWPERF_CB *psSGXReadHWPerfCBIN,
+ PVRSRV_BRIDGE_OUT_SGX_READ_HWPERF_CB *psSGXReadHWPerfCBOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ PVRSRV_SGX_HWPERF_CB_ENTRY *psAllocated;
+ IMG_HANDLE hAllocatedHandle;
+ IMG_UINT32 ui32AllocatedSize;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_READ_HWPERF_CB);
+
+ psSGXReadHWPerfCBOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSGXReadHWPerfCBIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psSGXReadHWPerfCBOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ ui32AllocatedSize = psSGXReadHWPerfCBIN->ui32ArraySize *
+ sizeof(psSGXReadHWPerfCBIN->psHWPerfCBData[0]);
+ ASSIGN_AND_EXIT_ON_ERROR(psSGXReadHWPerfCBOUT->eError,
+ OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32AllocatedSize,
+ (IMG_VOID **)&psAllocated,
+ &hAllocatedHandle,
+ "Array of Hardware Performance Circular Buffer Data"));
+
+ psSGXReadHWPerfCBOUT->eError = SGXReadHWPerfCBKM(hDevCookieInt,
+ psSGXReadHWPerfCBIN->ui32ArraySize,
+ psAllocated,
+ &psSGXReadHWPerfCBOUT->ui32DataCount,
+ &psSGXReadHWPerfCBOUT->ui32ClockSpeed,
+ &psSGXReadHWPerfCBOUT->ui32HostTimeStamp);
+ if (psSGXReadHWPerfCBOUT->eError == PVRSRV_OK)
+ {
+ psSGXReadHWPerfCBOUT->eError = CopyToUserWrapper(psPerProc,
+ ui32BridgeID,
+ psSGXReadHWPerfCBIN->psHWPerfCBData,
+ psAllocated,
+ ui32AllocatedSize);
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32AllocatedSize,
+ psAllocated,
+ hAllocatedHandle);
+
+
+ return 0;
+}
+
+
+static IMG_INT
+SGXDevInitPart2BW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGXDEVINITPART2 *psSGXDevInitPart2IN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ PVRSRV_ERROR eError;
+ IMG_BOOL bDissociateFailed = IMG_FALSE;
+ IMG_BOOL bLookupFailed = IMG_FALSE;
+ IMG_BOOL bReleaseFailed = IMG_FALSE;
+ IMG_HANDLE hDummy;
+ IMG_UINT32 i;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_DEVINITPART2);
+
+ if(!psPerProc->bInitProcess)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_PROCESS_NOT_INITIALISED;
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSGXDevInitPart2IN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelCCBCtlMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelCCBEventKickerMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelSGXHostCtlMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelSGXTA3DCtlMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelSGXMiscMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+
+#if defined(SGX_SUPPORT_HWPROFILING)
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelHWProfilingMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+#endif
+
+#if defined(SUPPORT_SGX_HWPERF)
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelHWPerfCBMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+#endif
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelTASigBufferMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernel3DSigBufferMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+
+#if defined(FIX_HW_BRN_29702)
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelCFIMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+#endif
+
+#if defined(FIX_HW_BRN_29823)
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelDummyTermStreamMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+#endif
+
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelEDMStatusBufferMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+#endif
+
+#if defined(SGX_FEATURE_SPM_MODE_0)
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelTmpDPMStateMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+#endif
+
+ for (i = 0; i < SGX_MAX_INIT_MEM_HANDLES; i++)
+ {
+ IMG_HANDLE hHandle = psSGXDevInitPart2IN->sInitInfo.asInitMemHandles[i];
+
+ if (hHandle == IMG_NULL)
+ {
+ continue;
+ }
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ hHandle,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+ }
+
+ if (bLookupFailed)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "DevInitSGXPart2BW: A handle lookup failed"));
+ psRetOUT->eError = PVRSRV_ERROR_INIT2_PHASE_FAILED;
+ return 0;
+ }
+
+
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bReleaseFailed = IMG_TRUE;
+ }
+
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.hKernelCCBCtlMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.hKernelCCBCtlMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bReleaseFailed = IMG_TRUE;
+ }
+
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.hKernelCCBEventKickerMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.hKernelCCBEventKickerMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bReleaseFailed = IMG_TRUE;
+ }
+
+
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.hKernelSGXHostCtlMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.hKernelSGXHostCtlMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bReleaseFailed = IMG_TRUE;
+ }
+
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.hKernelSGXTA3DCtlMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.hKernelSGXTA3DCtlMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bReleaseFailed = IMG_TRUE;
+ }
+
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.hKernelSGXMiscMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.hKernelSGXMiscMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bReleaseFailed = IMG_TRUE;
+ }
+
+
+ #if defined(SGX_SUPPORT_HWPROFILING)
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.hKernelHWProfilingMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.hKernelHWProfilingMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bReleaseFailed = IMG_TRUE;
+ }
+#endif
+
+#if defined(SUPPORT_SGX_HWPERF)
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.hKernelHWPerfCBMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.hKernelHWPerfCBMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bReleaseFailed = IMG_TRUE;
+ }
+#endif
+
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.hKernelTASigBufferMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.hKernelTASigBufferMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bReleaseFailed = IMG_TRUE;
+ }
+
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.hKernel3DSigBufferMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.hKernel3DSigBufferMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bReleaseFailed = IMG_TRUE;
+ }
+
+#if defined(FIX_HW_BRN_29702)
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.hKernelCFIMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.hKernelCFIMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bLookupFailed = IMG_TRUE;
+ }
+#endif
+
+#if defined(FIX_HW_BRN_29823)
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.hKernelDummyTermStreamMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.hKernelDummyTermStreamMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bReleaseFailed = IMG_TRUE;
+ }
+#endif
+
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.hKernelEDMStatusBufferMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.hKernelEDMStatusBufferMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bReleaseFailed = IMG_TRUE;
+ }
+#endif
+
+#if defined(SGX_FEATURE_SPM_MODE_0)
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.hKernelTmpDPMStateMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.hKernelTmpDPMStateMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bReleaseFailed = IMG_TRUE;
+ }
+#endif
+
+
+ for (i = 0; i < SGX_MAX_INIT_MEM_HANDLES; i++)
+ {
+ IMG_HANDLE *phHandle = &psSGXDevInitPart2IN->sInitInfo.asInitMemHandles[i];
+
+ if (*phHandle == IMG_NULL)
+ continue;
+
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ phHandle,
+ *phHandle,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK)
+ {
+ bReleaseFailed = IMG_TRUE;
+ }
+ }
+
+ if (bReleaseFailed)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "DevInitSGXPart2BW: A handle release failed"));
+ psRetOUT->eError = PVRSRV_ERROR_INIT2_PHASE_FAILED;
+
+ PVR_DBG_BREAK;
+ return 0;
+ }
+
+
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo);
+ if (eError != PVRSRV_OK)
+ {
+ bDissociateFailed = IMG_TRUE;
+ }
+
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCCBCtlMemInfo);
+ if (eError != PVRSRV_OK)
+ {
+ bDissociateFailed = IMG_TRUE;
+ }
+
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCCBEventKickerMemInfo);
+ if (eError != PVRSRV_OK)
+ {
+ bDissociateFailed = IMG_TRUE;
+ }
+
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXHostCtlMemInfo);
+ if (eError != PVRSRV_OK)
+ {
+ bDissociateFailed = IMG_TRUE;
+ }
+
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXTA3DCtlMemInfo);
+ if (eError != PVRSRV_OK)
+ {
+ bDissociateFailed = IMG_TRUE;
+ }
+
+
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXMiscMemInfo);
+ if (eError != PVRSRV_OK)
+ {
+ bDissociateFailed = IMG_TRUE;
+ }
+
+
+#if defined(SGX_SUPPORT_HWPROFILING)
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelHWProfilingMemInfo);
+ bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+
+#if defined(SUPPORT_SGX_HWPERF)
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelHWPerfCBMemInfo);
+ if (eError != PVRSRV_OK)
+ {
+ bDissociateFailed = IMG_TRUE;
+ }
+#endif
+
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelTASigBufferMemInfo);
+ if (eError != PVRSRV_OK)
+ {
+ bDissociateFailed = IMG_TRUE;
+ }
+
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernel3DSigBufferMemInfo);
+ if (eError != PVRSRV_OK)
+ {
+ bDissociateFailed = IMG_TRUE;
+ }
+
+#if defined(FIX_HW_BRN_29702)
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCFIMemInfo);
+ bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+
+#if defined(FIX_HW_BRN_29823)
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelDummyTermStreamMemInfo);
+ bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelEDMStatusBufferMemInfo);
+ bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+#endif
+
+#if defined(SGX_FEATURE_SPM_MODE_0)
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelTmpDPMStateMemInfo);
+ if (eError != PVRSRV_OK)
+ {
+ bDissociateFailed = IMG_TRUE;
+ }
+#endif
+
+ for (i = 0; i < SGX_MAX_INIT_MEM_HANDLES; i++)
+ {
+ IMG_HANDLE hHandle = psSGXDevInitPart2IN->sInitInfo.asInitMemHandles[i];
+
+ if (hHandle == IMG_NULL)
+ continue;
+
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, hHandle);
+ if (eError != PVRSRV_OK)
+ {
+ bDissociateFailed = IMG_TRUE;
+ }
+ }
+
+
+ if(bDissociateFailed)
+ {
+ PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo);
+ PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCCBCtlMemInfo);
+ PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXHostCtlMemInfo);
+ PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXTA3DCtlMemInfo);
+ PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXMiscMemInfo);
+
+ for (i = 0; i < SGX_MAX_INIT_MEM_HANDLES; i++)
+ {
+ IMG_HANDLE hHandle = psSGXDevInitPart2IN->sInitInfo.asInitMemHandles[i];
+
+ if (hHandle == IMG_NULL)
+ continue;
+
+ PVRSRVFreeDeviceMemKM(hDevCookieInt, (PVRSRV_KERNEL_MEM_INFO *)hHandle);
+
+ }
+
+ PVR_DPF((PVR_DBG_ERROR, "DevInitSGXPart2BW: A dissociate failed"));
+
+ psRetOUT->eError = PVRSRV_ERROR_INIT2_PHASE_FAILED;
+
+
+ PVR_DBG_BREAK;
+ return 0;
+ }
+
+ psRetOUT->eError =
+ DevInitSGXPart2KM(psPerProc,
+ hDevCookieInt,
+ &psSGXDevInitPart2IN->sInitInfo);
+
+ return 0;
+}
+
+
+static IMG_INT
+SGXRegisterHWRenderContextBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_RENDER_CONTEXT *psSGXRegHWRenderContextIN,
+ PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_RENDER_CONTEXT *psSGXRegHWRenderContextOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_HANDLE hHWRenderContextInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_REGISTER_HW_RENDER_CONTEXT);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psSGXRegHWRenderContextOUT->eError, psPerProc, 1);
+
+ psSGXRegHWRenderContextOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSGXRegHWRenderContextIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psSGXRegHWRenderContextOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ hHWRenderContextInt =
+ SGXRegisterHWRenderContextKM(hDevCookieInt,
+ &psSGXRegHWRenderContextIN->sHWRenderContextDevVAddr,
+ psPerProc);
+
+ if (hHWRenderContextInt == IMG_NULL)
+ {
+ psSGXRegHWRenderContextOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_CONTEXT;
+ return 0;
+ }
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psSGXRegHWRenderContextOUT->hHWRenderContext,
+ hHWRenderContextInt,
+ PVRSRV_HANDLE_TYPE_SGX_HW_RENDER_CONTEXT,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psSGXRegHWRenderContextOUT->eError, psPerProc);
+
+ return 0;
+}
+
+
+static IMG_INT
+SGXUnregisterHWRenderContextBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_RENDER_CONTEXT *psSGXUnregHWRenderContextIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hHWRenderContextInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_UNREGISTER_HW_RENDER_CONTEXT);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hHWRenderContextInt,
+ psSGXUnregHWRenderContextIN->hHWRenderContext,
+ PVRSRV_HANDLE_TYPE_SGX_HW_RENDER_CONTEXT);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = SGXUnregisterHWRenderContextKM(hHWRenderContextInt);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psSGXUnregHWRenderContextIN->hHWRenderContext,
+ PVRSRV_HANDLE_TYPE_SGX_HW_RENDER_CONTEXT);
+
+ return 0;
+}
+
+
+static IMG_INT
+SGXRegisterHWTransferContextBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_TRANSFER_CONTEXT *psSGXRegHWTransferContextIN,
+ PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_TRANSFER_CONTEXT *psSGXRegHWTransferContextOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_HANDLE hHWTransferContextInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_REGISTER_HW_TRANSFER_CONTEXT);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psSGXRegHWTransferContextOUT->eError, psPerProc, 1);
+
+ psSGXRegHWTransferContextOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSGXRegHWTransferContextIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psSGXRegHWTransferContextOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ hHWTransferContextInt =
+ SGXRegisterHWTransferContextKM(hDevCookieInt,
+ &psSGXRegHWTransferContextIN->sHWTransferContextDevVAddr,
+ psPerProc);
+
+ if (hHWTransferContextInt == IMG_NULL)
+ {
+ psSGXRegHWTransferContextOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_CONTEXT;
+ return 0;
+ }
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psSGXRegHWTransferContextOUT->hHWTransferContext,
+ hHWTransferContextInt,
+ PVRSRV_HANDLE_TYPE_SGX_HW_TRANSFER_CONTEXT,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psSGXRegHWTransferContextOUT->eError, psPerProc);
+
+ return 0;
+}
+
+
+static IMG_INT
+SGXUnregisterHWTransferContextBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_TRANSFER_CONTEXT *psSGXUnregHWTransferContextIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hHWTransferContextInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_UNREGISTER_HW_TRANSFER_CONTEXT);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hHWTransferContextInt,
+ psSGXUnregHWTransferContextIN->hHWTransferContext,
+ PVRSRV_HANDLE_TYPE_SGX_HW_TRANSFER_CONTEXT);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = SGXUnregisterHWTransferContextKM(hHWTransferContextInt);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psSGXUnregHWTransferContextIN->hHWTransferContext,
+ PVRSRV_HANDLE_TYPE_SGX_HW_TRANSFER_CONTEXT);
+
+ return 0;
+}
+
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+static IMG_INT
+SGXRegisterHW2DContextBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_2D_CONTEXT *psSGXRegHW2DContextIN,
+ PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_2D_CONTEXT *psSGXRegHW2DContextOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_HANDLE hHW2DContextInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_REGISTER_HW_2D_CONTEXT);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psSGXRegHW2DContextOUT->eError, psPerProc, 1);
+
+ psSGXRegHW2DContextOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSGXRegHW2DContextIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psSGXRegHW2DContextOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ hHW2DContextInt =
+ SGXRegisterHW2DContextKM(hDevCookieInt,
+ &psSGXRegHW2DContextIN->sHW2DContextDevVAddr,
+ psPerProc);
+
+ if (hHW2DContextInt == IMG_NULL)
+ {
+ psSGXRegHW2DContextOUT->eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_CONTEXT;
+ return 0;
+ }
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psSGXRegHW2DContextOUT->hHW2DContext,
+ hHW2DContextInt,
+ PVRSRV_HANDLE_TYPE_SGX_HW_2D_CONTEXT,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psSGXRegHW2DContextOUT->eError, psPerProc);
+
+ return 0;
+}
+
+
+static IMG_INT
+SGXUnregisterHW2DContextBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_2D_CONTEXT *psSGXUnregHW2DContextIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hHW2DContextInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_UNREGISTER_HW_2D_CONTEXT);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hHW2DContextInt,
+ psSGXUnregHW2DContextIN->hHW2DContext,
+ PVRSRV_HANDLE_TYPE_SGX_HW_2D_CONTEXT);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = SGXUnregisterHW2DContextKM(hHW2DContextInt);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psSGXUnregHW2DContextIN->hHW2DContext,
+ PVRSRV_HANDLE_TYPE_SGX_HW_2D_CONTEXT);
+
+ return 0;
+}
+#endif
+
+static IMG_INT
+SGXFlushHWRenderTargetBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGX_FLUSH_HW_RENDER_TARGET *psSGXFlushHWRenderTargetIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_FLUSH_HW_RENDER_TARGET);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSGXFlushHWRenderTargetIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ SGXFlushHWRenderTargetKM(hDevCookieInt, psSGXFlushHWRenderTargetIN->sHWRTDataSetDevVAddr);
+
+ return 0;
+}
+
+static void trace_query_cmd(PVRSRV_PER_PROCESS_DATA *proc, int type,
+ PVRSRV_KERNEL_SYNC_INFO *si)
+{
+ struct pvr_trcmd_syn *ts;
+ size_t size;
+
+ size = si ? sizeof(*ts) : 0;
+
+ ts = pvr_trcmd_reserve(type, proc->ui32PID, proc->name, size);
+ if (si)
+ pvr_trcmd_set_syn(ts, si);
+
+ pvr_trcmd_commit(ts);
+}
+
+static IMG_INT
+SGX2DQueryBlitsCompleteBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_2DQUERYBLTSCOMPLETE *ps2DQueryBltsCompleteIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_VOID *pvSyncInfo;
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_2DQUERYBLTSCOMPLETE);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ ps2DQueryBltsCompleteIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &pvSyncInfo,
+ ps2DQueryBltsCompleteIN->hKernSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookieInt)->pvDevice;
+
+ psRetOUT->eError =
+ SGX2DQueryBlitsCompleteKM(psDevInfo,
+ (PVRSRV_KERNEL_SYNC_INFO *)pvSyncInfo,
+ ps2DQueryBltsCompleteIN->bWaitForComplete);
+
+ trace_query_cmd(psPerProc, PVR_TRCMD_SGX_QBLT_SYNCHK, pvSyncInfo);
+
+ return 0;
+}
+
+
+static IMG_INT
+SGXFindSharedPBDescBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGXFINDSHAREDPBDESC *psSGXFindSharedPBDescIN,
+ PVRSRV_BRIDGE_OUT_SGXFINDSHAREDPBDESC *psSGXFindSharedPBDescOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ PVRSRV_KERNEL_MEM_INFO *psSharedPBDescKernelMemInfo;
+ PVRSRV_KERNEL_MEM_INFO *psHWPBDescKernelMemInfo;
+ PVRSRV_KERNEL_MEM_INFO *psBlockKernelMemInfo;
+ PVRSRV_KERNEL_MEM_INFO *psHWBlockKernelMemInfo;
+ PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescSubKernelMemInfos = IMG_NULL;
+ IMG_UINT32 ui32SharedPBDescSubKernelMemInfosCount = 0;
+ IMG_UINT32 i;
+ IMG_HANDLE hSharedPBDesc = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psSGXFindSharedPBDescOUT->eError, psPerProc, PVRSRV_BRIDGE_SGX_SHAREDPBDESC_MAX_SUBMEMINFOS + 4);
+
+ psSGXFindSharedPBDescOUT->hSharedPBDesc = IMG_NULL;
+
+ psSGXFindSharedPBDescOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSGXFindSharedPBDescIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psSGXFindSharedPBDescOUT->eError != PVRSRV_OK)
+ goto PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC_EXIT;
+
+ psSGXFindSharedPBDescOUT->eError =
+ SGXFindSharedPBDescKM(psPerProc, hDevCookieInt,
+ psSGXFindSharedPBDescIN->bLockOnFailure,
+ psSGXFindSharedPBDescIN->ui32TotalPBSize,
+ &hSharedPBDesc,
+ &psSharedPBDescKernelMemInfo,
+ &psHWPBDescKernelMemInfo,
+ &psBlockKernelMemInfo,
+ &psHWBlockKernelMemInfo,
+ &ppsSharedPBDescSubKernelMemInfos,
+ &ui32SharedPBDescSubKernelMemInfosCount);
+ if(psSGXFindSharedPBDescOUT->eError != PVRSRV_OK)
+ goto PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC_EXIT;
+
+ PVR_ASSERT(ui32SharedPBDescSubKernelMemInfosCount
+ <= PVRSRV_BRIDGE_SGX_SHAREDPBDESC_MAX_SUBMEMINFOS);
+
+ psSGXFindSharedPBDescOUT->ui32SharedPBDescSubKernelMemInfoHandlesCount =
+ ui32SharedPBDescSubKernelMemInfosCount;
+
+ if(hSharedPBDesc == IMG_NULL)
+ {
+ psSGXFindSharedPBDescOUT->hSharedPBDescKernelMemInfoHandle = 0;
+
+ goto PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC_EXIT;
+ }
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psSGXFindSharedPBDescOUT->hSharedPBDesc,
+ hSharedPBDesc,
+ PVRSRV_HANDLE_TYPE_SHARED_PB_DESC,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psSGXFindSharedPBDescOUT->hSharedPBDescKernelMemInfoHandle,
+ psSharedPBDescKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+ psSGXFindSharedPBDescOUT->hSharedPBDesc);
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psSGXFindSharedPBDescOUT->hHWPBDescKernelMemInfoHandle,
+ psHWPBDescKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+ psSGXFindSharedPBDescOUT->hSharedPBDesc);
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psSGXFindSharedPBDescOUT->hBlockKernelMemInfoHandle,
+ psBlockKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+ psSGXFindSharedPBDescOUT->hSharedPBDesc);
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psSGXFindSharedPBDescOUT->hHWBlockKernelMemInfoHandle,
+ psHWBlockKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+ psSGXFindSharedPBDescOUT->hSharedPBDesc);
+
+
+ for(i=0; i<ui32SharedPBDescSubKernelMemInfosCount; i++)
+ {
+ PVRSRV_BRIDGE_OUT_SGXFINDSHAREDPBDESC *psSGXFindSharedPBDescOut =
+ psSGXFindSharedPBDescOUT;
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psSGXFindSharedPBDescOut->ahSharedPBDescSubKernelMemInfoHandles[i],
+ ppsSharedPBDescSubKernelMemInfos[i],
+ PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+ psSGXFindSharedPBDescOUT->hSharedPBDescKernelMemInfoHandle);
+ }
+
+PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC_EXIT:
+ if (ppsSharedPBDescSubKernelMemInfos != IMG_NULL)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO *) * ui32SharedPBDescSubKernelMemInfosCount,
+ ppsSharedPBDescSubKernelMemInfos,
+ IMG_NULL);
+ }
+
+ if(psSGXFindSharedPBDescOUT->eError != PVRSRV_OK)
+ {
+ if(hSharedPBDesc != IMG_NULL)
+ {
+ SGXUnrefSharedPBDescKM(hSharedPBDesc);
+ }
+ }
+ else
+ {
+ COMMIT_HANDLE_BATCH_OR_ERROR(psSGXFindSharedPBDescOUT->eError, psPerProc);
+ }
+
+ return 0;
+}
+
+
+static IMG_INT
+SGXUnrefSharedPBDescBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGXUNREFSHAREDPBDESC *psSGXUnrefSharedPBDescIN,
+ PVRSRV_BRIDGE_OUT_SGXUNREFSHAREDPBDESC *psSGXUnrefSharedPBDescOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hSharedPBDesc;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_UNREFSHAREDPBDESC);
+
+ psSGXUnrefSharedPBDescOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hSharedPBDesc,
+ psSGXUnrefSharedPBDescIN->hSharedPBDesc,
+ PVRSRV_HANDLE_TYPE_SHARED_PB_DESC);
+ if(psSGXUnrefSharedPBDescOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psSGXUnrefSharedPBDescOUT->eError =
+ SGXUnrefSharedPBDescKM(hSharedPBDesc);
+
+ if(psSGXUnrefSharedPBDescOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psSGXUnrefSharedPBDescOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psSGXUnrefSharedPBDescIN->hSharedPBDesc,
+ PVRSRV_HANDLE_TYPE_SHARED_PB_DESC);
+
+ return 0;
+}
+
+
+static IMG_INT
+SGXAddSharedPBDescBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGXADDSHAREDPBDESC *psSGXAddSharedPBDescIN,
+ PVRSRV_BRIDGE_OUT_SGXADDSHAREDPBDESC *psSGXAddSharedPBDescOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ PVRSRV_KERNEL_MEM_INFO *psSharedPBDescKernelMemInfo;
+ PVRSRV_KERNEL_MEM_INFO *psHWPBDescKernelMemInfo;
+ PVRSRV_KERNEL_MEM_INFO *psBlockKernelMemInfo;
+ PVRSRV_KERNEL_MEM_INFO *psHWBlockKernelMemInfo;
+ IMG_UINT32 ui32KernelMemInfoHandlesCount =
+ psSGXAddSharedPBDescIN->ui32KernelMemInfoHandlesCount;
+ IMG_INT ret = 0;
+ IMG_HANDLE *phKernelMemInfoHandles = IMG_NULL;
+ PVRSRV_KERNEL_MEM_INFO **ppsKernelMemInfos = IMG_NULL;
+ IMG_UINT32 i;
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hSharedPBDesc = IMG_NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psSGXAddSharedPBDescOUT->eError, psPerProc, 1);
+
+ psSGXAddSharedPBDescOUT->hSharedPBDesc = IMG_NULL;
+
+ PVR_ASSERT(ui32KernelMemInfoHandlesCount
+ <= PVRSRV_BRIDGE_SGX_SHAREDPBDESC_MAX_SUBMEMINFOS);
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSGXAddSharedPBDescIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID **)&psSharedPBDescKernelMemInfo,
+ psSGXAddSharedPBDescIN->hSharedPBDescKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+ if(eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID **)&psHWPBDescKernelMemInfo,
+ psSGXAddSharedPBDescIN->hHWPBDescKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID **)&psBlockKernelMemInfo,
+ psSGXAddSharedPBDescIN->hBlockKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+ if(eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID **)&psHWBlockKernelMemInfo,
+ psSGXAddSharedPBDescIN->hHWBlockKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+
+
+ if(!OSAccessOK(PVR_VERIFY_READ,
+ psSGXAddSharedPBDescIN->phKernelMemInfoHandles,
+ ui32KernelMemInfoHandlesCount * sizeof(IMG_HANDLE)))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC:"
+ " Invalid phKernelMemInfos pointer", __FUNCTION__));
+ ret = -EFAULT;
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32KernelMemInfoHandlesCount * sizeof(IMG_HANDLE),
+ (IMG_VOID **)&phKernelMemInfoHandles,
+ 0,
+ "Array of Handles");
+ if (eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+
+ if(CopyFromUserWrapper(psPerProc,
+ ui32BridgeID,
+ phKernelMemInfoHandles,
+ psSGXAddSharedPBDescIN->phKernelMemInfoHandles,
+ ui32KernelMemInfoHandlesCount * sizeof(IMG_HANDLE))
+ != PVRSRV_OK)
+ {
+ ret = -EFAULT;
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32KernelMemInfoHandlesCount * sizeof(PVRSRV_KERNEL_MEM_INFO *),
+ (IMG_VOID **)&ppsKernelMemInfos,
+ 0,
+ "Array of pointers to Kernel Memory Info");
+ if (eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+
+ for(i=0; i<ui32KernelMemInfoHandlesCount; i++)
+ {
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_VOID **)&ppsKernelMemInfos[i],
+ phKernelMemInfoHandles[i],
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+ }
+
+
+
+ eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psSGXAddSharedPBDescIN->hSharedPBDescKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+
+ eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psSGXAddSharedPBDescIN->hHWPBDescKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+
+ eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psSGXAddSharedPBDescIN->hBlockKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+
+ eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psSGXAddSharedPBDescIN->hHWBlockKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ for(i=0; i<ui32KernelMemInfoHandlesCount; i++)
+ {
+
+ eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ phKernelMemInfoHandles[i],
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ PVR_ASSERT(eError == PVRSRV_OK);
+ }
+
+ eError = SGXAddSharedPBDescKM(psPerProc, hDevCookieInt,
+ psSharedPBDescKernelMemInfo,
+ psHWPBDescKernelMemInfo,
+ psBlockKernelMemInfo,
+ psHWBlockKernelMemInfo,
+ psSGXAddSharedPBDescIN->ui32TotalPBSize,
+ &hSharedPBDesc,
+ ppsKernelMemInfos,
+ ui32KernelMemInfoHandlesCount);
+
+
+ if (eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psSGXAddSharedPBDescOUT->hSharedPBDesc,
+ hSharedPBDesc,
+ PVRSRV_HANDLE_TYPE_SHARED_PB_DESC,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT:
+
+ if(phKernelMemInfoHandles)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ psSGXAddSharedPBDescIN->ui32KernelMemInfoHandlesCount * sizeof(IMG_HANDLE),
+ (IMG_VOID *)phKernelMemInfoHandles,
+ 0);
+ }
+ if(ppsKernelMemInfos)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ psSGXAddSharedPBDescIN->ui32KernelMemInfoHandlesCount * sizeof(PVRSRV_KERNEL_MEM_INFO *),
+ (IMG_VOID *)ppsKernelMemInfos,
+ 0);
+ }
+
+ if(ret == 0 && eError == PVRSRV_OK)
+ {
+ COMMIT_HANDLE_BATCH_OR_ERROR(psSGXAddSharedPBDescOUT->eError, psPerProc);
+ }
+
+ psSGXAddSharedPBDescOUT->eError = eError;
+
+ return ret;
+}
+
+static IMG_INT
+SGXGetInfoForSrvinitBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGXINFO_FOR_SRVINIT *psSGXInfoForSrvinitIN,
+ PVRSRV_BRIDGE_OUT_SGXINFO_FOR_SRVINIT *psSGXInfoForSrvinitOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_HANDLE hDevCookieInt;
+ IMG_UINT32 i;
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGXINFO_FOR_SRVINIT);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psSGXInfoForSrvinitOUT->eError, psPerProc, PVRSRV_MAX_CLIENT_HEAPS);
+
+ if(!psPerProc->bInitProcess)
+ {
+ psSGXInfoForSrvinitOUT->eError = PVRSRV_ERROR_PROCESS_NOT_INITIALISED;
+ return 0;
+ }
+
+ psSGXInfoForSrvinitOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psSGXInfoForSrvinitIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psSGXInfoForSrvinitOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psSGXInfoForSrvinitOUT->eError =
+ SGXGetInfoForSrvinitKM(hDevCookieInt,
+ &psSGXInfoForSrvinitOUT->sInitInfo);
+
+ if(psSGXInfoForSrvinitOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ for(i = 0; i < PVRSRV_MAX_CLIENT_HEAPS; i++)
+ {
+ PVRSRV_HEAP_INFO *psHeapInfo;
+
+ psHeapInfo = &psSGXInfoForSrvinitOUT->sInitInfo.asHeapInfo[i];
+
+ if (psHeapInfo->ui32HeapID != (IMG_UINT32)SGX_UNDEFINED_HEAP_ID)
+ {
+ IMG_HANDLE hDevMemHeapExt;
+
+ if (psHeapInfo->hDevMemHeap != IMG_NULL)
+ {
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &hDevMemHeapExt,
+ psHeapInfo->hDevMemHeap,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+ psHeapInfo->hDevMemHeap = hDevMemHeapExt;
+ }
+ }
+ }
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psSGXInfoForSrvinitOUT->eError, psPerProc);
+
+ return 0;
+}
+
+#if defined(PDUMP)
+static IMG_VOID
+DumpBufferArray(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ PSGX_KICKTA_DUMP_BUFFER psBufferArray,
+ IMG_UINT32 ui32BufferArrayLength,
+ IMG_BOOL bDumpPolls)
+{
+ IMG_UINT32 i;
+
+ for (i=0; i<ui32BufferArrayLength; i++)
+ {
+ PSGX_KICKTA_DUMP_BUFFER psBuffer;
+ PVRSRV_KERNEL_MEM_INFO *psCtrlMemInfoKM;
+ IMG_CHAR * pszName;
+ IMG_HANDLE hUniqueTag;
+ IMG_UINT32 ui32Offset;
+
+ psBuffer = &psBufferArray[i];
+ pszName = psBuffer->pszName;
+ if (!pszName)
+ {
+ pszName = "Nameless buffer";
+ }
+
+ hUniqueTag = MAKEUNIQUETAG((PVRSRV_KERNEL_MEM_INFO *)psBuffer->hKernelMemInfo);
+
+ #if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+ psCtrlMemInfoKM = ((PVRSRV_KERNEL_MEM_INFO *)psBuffer->hCtrlKernelMemInfo);
+ ui32Offset = psBuffer->sCtrlDevVAddr.uiAddr - psCtrlMemInfoKM->sDevVAddr.uiAddr;
+ #else
+ psCtrlMemInfoKM = ((PVRSRV_KERNEL_MEM_INFO *)psBuffer->hKernelMemInfo)->psKernelSyncInfo->psSyncDataMemInfoKM;
+ ui32Offset = offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete);
+ #endif
+
+ if (psBuffer->ui32Start <= psBuffer->ui32End)
+ {
+ if (bDumpPolls)
+ {
+ PDUMPCOMMENTWITHFLAGS(0, "Wait for %s space\r\n", pszName);
+ PDUMPCBP(psCtrlMemInfoKM,
+ ui32Offset,
+ psBuffer->ui32Start,
+ psBuffer->ui32SpaceUsed,
+ psBuffer->ui32BufferSize,
+ 0,
+ MAKEUNIQUETAG(psCtrlMemInfoKM));
+ }
+
+ PDUMPCOMMENTWITHFLAGS(0, "%s\r\n", pszName);
+ PDUMPMEMUM(psPerProc,
+ IMG_NULL,
+ psBuffer->pvLinAddr,
+ (PVRSRV_KERNEL_MEM_INFO*)psBuffer->hKernelMemInfo,
+ psBuffer->ui32Start,
+ psBuffer->ui32End - psBuffer->ui32Start,
+ 0,
+ hUniqueTag);
+ }
+ else
+ {
+
+
+ if (bDumpPolls)
+ {
+ PDUMPCOMMENTWITHFLAGS(0, "Wait for %s space\r\n", pszName);
+ PDUMPCBP(psCtrlMemInfoKM,
+ ui32Offset,
+ psBuffer->ui32Start,
+ psBuffer->ui32BackEndLength,
+ psBuffer->ui32BufferSize,
+ 0,
+ MAKEUNIQUETAG(psCtrlMemInfoKM));
+ }
+ PDUMPCOMMENTWITHFLAGS(0, "%s (part 1)\r\n", pszName);
+ PDUMPMEMUM(psPerProc,
+ IMG_NULL,
+ psBuffer->pvLinAddr,
+ (PVRSRV_KERNEL_MEM_INFO*)psBuffer->hKernelMemInfo,
+ psBuffer->ui32Start,
+ psBuffer->ui32BackEndLength,
+ 0,
+ hUniqueTag);
+
+ if (bDumpPolls)
+ {
+ PDUMPMEMPOL(psCtrlMemInfoKM,
+ ui32Offset,
+ 0,
+ 0xFFFFFFFF,
+ PDUMP_POLL_OPERATOR_NOTEQUAL,
+ 0,
+ MAKEUNIQUETAG(psCtrlMemInfoKM));
+
+ PDUMPCOMMENTWITHFLAGS(0, "Wait for %s space\r\n", pszName);
+ PDUMPCBP(psCtrlMemInfoKM,
+ ui32Offset,
+ 0,
+ psBuffer->ui32End,
+ psBuffer->ui32BufferSize,
+ 0,
+ MAKEUNIQUETAG(psCtrlMemInfoKM));
+ }
+ PDUMPCOMMENTWITHFLAGS(0, "%s (part 2)\r\n", pszName);
+ PDUMPMEMUM(psPerProc,
+ IMG_NULL,
+ psBuffer->pvLinAddr,
+ (PVRSRV_KERNEL_MEM_INFO*)psBuffer->hKernelMemInfo,
+ 0,
+ psBuffer->ui32End,
+ 0,
+ hUniqueTag);
+ }
+ }
+}
+static IMG_INT
+SGXPDumpBufferArrayBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_BUFFER_ARRAY *psPDumpBufferArrayIN,
+ IMG_VOID *psBridgeOut,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_UINT32 i;
+ SGX_KICKTA_DUMP_BUFFER *psKickTADumpBuffer;
+ IMG_UINT32 ui32BufferArrayLength =
+ psPDumpBufferArrayIN->ui32BufferArrayLength;
+ IMG_UINT32 ui32BufferArraySize =
+ ui32BufferArrayLength * sizeof(SGX_KICKTA_DUMP_BUFFER);
+ PVRSRV_ERROR eError = PVRSRV_ERROR_TOO_FEW_BUFFERS;
+
+ PVR_UNREFERENCED_PARAMETER(psBridgeOut);
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_BUFFER_ARRAY);
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32BufferArraySize,
+ (IMG_PVOID *)&psKickTADumpBuffer, 0,
+ "Array of Kick Tile Accelerator Dump Buffer") != PVRSRV_OK)
+ {
+ return -ENOMEM;
+ }
+
+ if(CopyFromUserWrapper(psPerProc,
+ ui32BridgeID,
+ psKickTADumpBuffer,
+ psPDumpBufferArrayIN->psBufferArray,
+ ui32BufferArraySize) != PVRSRV_OK)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32BufferArraySize, psKickTADumpBuffer, 0);
+
+ return -EFAULT;
+ }
+
+ for(i = 0; i < ui32BufferArrayLength; i++)
+ {
+ IMG_VOID *pvMemInfo;
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvMemInfo,
+ psKickTADumpBuffer[i].hKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRV_BRIDGE_SGX_PDUMP_BUFFER_ARRAY: "
+ "PVRSRVLookupHandle failed (%d)", eError));
+ break;
+ }
+ psKickTADumpBuffer[i].hKernelMemInfo = pvMemInfo;
+
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvMemInfo,
+ psKickTADumpBuffer[i].hCtrlKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRV_BRIDGE_SGX_PDUMP_BUFFER_ARRAY: "
+ "PVRSRVLookupHandle failed (%d)", eError));
+ break;
+ }
+ psKickTADumpBuffer[i].hCtrlKernelMemInfo = pvMemInfo;
+#endif
+ }
+
+ if(eError == PVRSRV_OK)
+ {
+ DumpBufferArray(psPerProc,
+ psKickTADumpBuffer,
+ ui32BufferArrayLength,
+ psPDumpBufferArrayIN->bDumpPolls);
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32BufferArraySize, psKickTADumpBuffer, 0);
+
+
+ return 0;
+}
+
+static IMG_INT
+SGXPDump3DSignatureRegistersBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_3D_SIGNATURE_REGISTERS *psPDump3DSignatureRegistersIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_UINT32 ui32RegisterArraySize = psPDump3DSignatureRegistersIN->ui32NumRegisters * sizeof(IMG_UINT32);
+ IMG_UINT32 *pui32Registers = IMG_NULL;
+ PVRSRV_SGXDEV_INFO *psDevInfo = IMG_NULL;
+#if defined(SGX_FEATURE_MP) && defined(FIX_HW_BRN_27270)
+ IMG_UINT32 ui32RegVal = 0;
+#endif
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ IMG_INT ret = -EFAULT;
+
+ PVR_UNREFERENCED_PARAMETER(psRetOUT);
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_3D_SIGNATURE_REGISTERS);
+
+ if (ui32RegisterArraySize == 0)
+ {
+ goto ExitNoError;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, (IMG_VOID**)&psDeviceNode,
+ psPDump3DSignatureRegistersIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpTASignatureRegistersBW: hDevCookie lookup failed"));
+ goto Exit;
+ }
+
+ psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+
+#if defined(SGX_FEATURE_MP) && defined(FIX_HW_BRN_27270)
+
+ ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE, (SGX_FEATURE_MP_CORE_COUNT - 1) << EUR_CR_MASTER_CORE_ENABLE_SHIFT);
+#if defined(PDUMP)
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_MASTER_CORE, (SGX_FEATURE_MP_CORE_COUNT - 1) << EUR_CR_MASTER_CORE_ENABLE_SHIFT,
+ psPDump3DSignatureRegistersIN->bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0);
+#endif
+#endif
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32RegisterArraySize,
+ (IMG_PVOID *)&pui32Registers, 0,
+ "Array of Registers") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDump3DSignatureRegistersBW: OSAllocMem failed"));
+ goto Exit;
+ }
+
+ if(CopyFromUserWrapper(psPerProc,
+ ui32BridgeID,
+ pui32Registers,
+ psPDump3DSignatureRegistersIN->pui32Registers,
+ ui32RegisterArraySize) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDump3DSignatureRegistersBW: CopyFromUserWrapper failed"));
+ goto Exit;
+ }
+
+ PDump3DSignatureRegisters(&psDeviceNode->sDevId,
+ psPDump3DSignatureRegistersIN->ui32DumpFrameNum,
+ psPDump3DSignatureRegistersIN->bLastFrame,
+ pui32Registers,
+ psPDump3DSignatureRegistersIN->ui32NumRegisters);
+
+ PDumpSignatureBuffer(&psDeviceNode->sDevId,
+ "out.tasig", "TA", 0,
+ psDevInfo->psKernelTASigBufferMemInfo->sDevVAddr,
+ psDevInfo->psKernelTASigBufferMemInfo->ui32AllocSize,
+ 0 );
+ PDumpSignatureBuffer(&psDeviceNode->sDevId,
+ "out.3dsig", "3D", 0,
+ psDevInfo->psKernel3DSigBufferMemInfo->sDevVAddr,
+ psDevInfo->psKernel3DSigBufferMemInfo->ui32AllocSize,
+ 0 );
+
+ExitNoError:
+ psRetOUT->eError = PVRSRV_OK;
+ ret = 0;
+Exit:
+ if (pui32Registers != IMG_NULL)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32RegisterArraySize, pui32Registers, 0);
+ }
+
+#if defined(SGX_FEATURE_MP) && defined(FIX_HW_BRN_27270)
+ if (psDevInfo != IMG_NULL)
+ {
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE, ui32RegVal);
+#if defined(PDUMP)
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_MASTER_CORE, ui32RegVal,
+ psPDump3DSignatureRegistersIN->bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0);
+#endif
+ }
+#endif
+
+ return ret;
+}
+
+static IMG_INT
+SGXPDumpCounterRegistersBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_COUNTER_REGISTERS *psPDumpCounterRegistersIN,
+ IMG_VOID *psBridgeOut,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_UINT32 ui32RegisterArraySize = psPDumpCounterRegistersIN->ui32NumRegisters * sizeof(IMG_UINT32);
+ IMG_UINT32 *pui32Registers = IMG_NULL;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ IMG_INT ret = -EFAULT;
+
+ PVR_UNREFERENCED_PARAMETER(psBridgeOut);
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_COUNTER_REGISTERS);
+
+ if (ui32RegisterArraySize == 0)
+ {
+ goto ExitNoError;
+ }
+
+ if(PVRSRVLookupHandle(psPerProc->psHandleBase, (IMG_VOID**)&psDeviceNode,
+ psPDumpCounterRegistersIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXPDumpCounterRegistersBW: hDevCookie lookup failed"));
+ ret = -ENOMEM;
+ goto Exit;
+ }
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32RegisterArraySize,
+ (IMG_PVOID *)&pui32Registers, 0,
+ "Array of Registers") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpCounterRegistersBW: OSAllocMem failed"));
+ ret = -ENOMEM;
+ goto Exit;
+ }
+
+ if(CopyFromUserWrapper(psPerProc,
+ ui32BridgeID,
+ pui32Registers,
+ psPDumpCounterRegistersIN->pui32Registers,
+ ui32RegisterArraySize) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpCounterRegistersBW: CopyFromUserWrapper failed"));
+ goto Exit;
+ }
+
+ PDumpCounterRegisters(&psDeviceNode->sDevId,
+ psPDumpCounterRegistersIN->ui32DumpFrameNum,
+ psPDumpCounterRegistersIN->bLastFrame,
+ pui32Registers,
+ psPDumpCounterRegistersIN->ui32NumRegisters);
+
+ExitNoError:
+ ret = 0;
+Exit:
+ if (pui32Registers != IMG_NULL)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32RegisterArraySize, pui32Registers, 0);
+ }
+
+ return ret;
+}
+
+static IMG_INT
+SGXPDumpTASignatureRegistersBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_TA_SIGNATURE_REGISTERS *psPDumpTASignatureRegistersIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_UINT32 ui32RegisterArraySize = psPDumpTASignatureRegistersIN->ui32NumRegisters * sizeof(IMG_UINT32);
+ IMG_UINT32 *pui32Registers = IMG_NULL;
+#if defined(SGX_FEATURE_MP) && defined(FIX_HW_BRN_27270)
+ PVRSRV_SGXDEV_INFO *psDevInfo = IMG_NULL;
+ IMG_UINT32 ui32RegVal = 0;
+#endif
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ IMG_INT ret = -EFAULT;
+
+ PVR_UNREFERENCED_PARAMETER(psRetOUT);
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_TA_SIGNATURE_REGISTERS);
+
+ if (ui32RegisterArraySize == 0)
+ {
+ goto ExitNoError;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, (IMG_VOID**)&psDeviceNode,
+ psPDumpTASignatureRegistersIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpTASignatureRegistersBW: hDevCookie lookup failed"));
+ goto Exit;
+ }
+
+#if defined(SGX_FEATURE_MP) && defined(FIX_HW_BRN_27270)
+
+ psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+
+
+ ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE, (SGX_FEATURE_MP_CORE_COUNT - 1) << EUR_CR_MASTER_CORE_ENABLE_SHIFT);
+#if defined(PDUMP)
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_MASTER_CORE, (SGX_FEATURE_MP_CORE_COUNT - 1) << EUR_CR_MASTER_CORE_ENABLE_SHIFT,
+ psPDumpTASignatureRegistersIN->bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0);
+#endif
+#endif
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32RegisterArraySize,
+ (IMG_PVOID *)&pui32Registers, 0,
+ "Array of Registers") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpTASignatureRegistersBW: OSAllocMem failed"));
+ ret = -ENOMEM;
+ goto Exit;
+ }
+
+ if(CopyFromUserWrapper(psPerProc,
+ ui32BridgeID,
+ pui32Registers,
+ psPDumpTASignatureRegistersIN->pui32Registers,
+ ui32RegisterArraySize) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpTASignatureRegistersBW: CopyFromUserWrapper failed"));
+ goto Exit;
+ }
+
+ PDumpTASignatureRegisters(&psDeviceNode->sDevId,
+ psPDumpTASignatureRegistersIN->ui32DumpFrameNum,
+ psPDumpTASignatureRegistersIN->ui32TAKickCount,
+ psPDumpTASignatureRegistersIN->bLastFrame,
+ pui32Registers,
+ psPDumpTASignatureRegistersIN->ui32NumRegisters);
+
+ExitNoError:
+ psRetOUT->eError = PVRSRV_OK;
+ ret = 0;
+Exit:
+ if (pui32Registers != IMG_NULL)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32RegisterArraySize, pui32Registers, 0);
+ }
+
+#if defined(SGX_FEATURE_MP) && defined(FIX_HW_BRN_27270)
+ if (psDevInfo != IMG_NULL)
+ {
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE, ui32RegVal);
+#if defined(PDUMP)
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_MASTER_CORE, ui32RegVal,
+ psPDumpTASignatureRegistersIN->bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0);
+#endif
+ }
+#endif
+
+ return ret;
+}
+static IMG_INT
+SGXPDumpHWPerfCBBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_HWPERFCB *psPDumpHWPerfCBIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+#if defined(SUPPORT_SGX_HWPERF)
+#if defined(__linux__)
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_HWPERFCB);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, (IMG_VOID**)&psDeviceNode,
+ psPDumpHWPerfCBIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psDevInfo = psDeviceNode->pvDevice;
+
+ PDumpHWPerfCBKM(&psDeviceNode->sDevId,
+ &psPDumpHWPerfCBIN->szFileName[0],
+ psPDumpHWPerfCBIN->ui32FileOffset,
+ psDevInfo->psKernelHWPerfCBMemInfo->sDevVAddr,
+ psDevInfo->psKernelHWPerfCBMemInfo->ui32AllocSize,
+ psPDumpHWPerfCBIN->ui32PDumpFlags);
+
+ return 0;
+#else
+ PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+ PVR_UNREFERENCED_PARAMETER(psPDumpHWPerfCBIN);
+ PVR_UNREFERENCED_PARAMETER(psRetOUT);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+ return 0;
+#endif
+#else
+ PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+ PVR_UNREFERENCED_PARAMETER(psPDumpHWPerfCBIN);
+ PVR_UNREFERENCED_PARAMETER(psRetOUT);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+ return -EFAULT;
+#endif
+}
+
+
+static IMG_INT
+SGXPDumpSaveMemBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_SAVEMEM *psPDumpSaveMem,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_SAVEMEM);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, (IMG_VOID**)&psDeviceNode,
+ psPDumpSaveMem->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ PDumpSaveMemKM(&psDeviceNode->sDevId,
+ &psPDumpSaveMem->szFileName[0],
+ psPDumpSaveMem->ui32FileOffset,
+ psPDumpSaveMem->sDevVAddr,
+ psPDumpSaveMem->ui32Size,
+ psPDumpSaveMem->ui32DataMaster,
+ psPDumpSaveMem->ui32PDumpFlags);
+ return 0;
+}
+
+#endif
+
+
+
+IMG_VOID SetSGXDispatchTableEntry(IMG_VOID)
+{
+ PVR_IO_NSTD(SGX_GETCLIENTINFO, SGXGetClientInfoBW,
+ sizeof(PVRSRV_BRIDGE_IN_GETCLIENTINFO),
+ sizeof(PVRSRV_BRIDGE_OUT_GETCLIENTINFO),
+ offsetof(PVRSRV_BRIDGE_OUT_GETCLIENTINFO, eError));
+ PVR_IO_NSTD(SGX_RELEASECLIENTINFO, SGXReleaseClientInfoBW,
+ sizeof(PVRSRV_BRIDGE_IN_RELEASECLIENTINFO),
+ sizeof(PVRSRV_BRIDGE_RETURN),
+ offsetof(PVRSRV_BRIDGE_RETURN, eError));
+ PVR_IO_NSTD(SGX_GETINTERNALDEVINFO, SGXGetInternalDevInfoBW,
+ sizeof(PVRSRV_BRIDGE_IN_GETINTERNALDEVINFO),
+ sizeof(PVRSRV_BRIDGE_OUT_GETINTERNALDEVINFO),
+ offsetof(PVRSRV_BRIDGE_OUT_GETINTERNALDEVINFO, eError));
+ PVR_IO_NSTD(SGX_DOKICK, SGXDoKickBW,
+ sizeof(PVRSRV_BRIDGE_IN_DOKICK),
+ sizeof(PVRSRV_BRIDGE_RETURN),
+ offsetof(PVRSRV_BRIDGE_RETURN, eError));
+ PVR_IO_NSTD(SGX_GETPHYSPAGEADDR, DummyBW,
+ sizeof(PVRSRV_BRIDGE_IN_GETPHYSPAGEADDR),
+ sizeof(PVRSRV_BRIDGE_OUT_GETPHYSPAGEADDR),
+ offsetof(PVRSRV_BRIDGE_OUT_GETPHYSPAGEADDR, eError));
+ PVR_IO_INV(SGX_READREGISTRYDWORD);
+ PVR_IO_NSTD(SGX_2DQUERYBLTSCOMPLETE, SGX2DQueryBlitsCompleteBW,
+ sizeof(PVRSRV_BRIDGE_IN_2DQUERYBLTSCOMPLETE),
+ sizeof(PVRSRV_BRIDGE_RETURN),
+ offsetof(PVRSRV_BRIDGE_RETURN, eError));
+ PVR_IO_INV(SGX_GETMMUPDADDR);
+
+#if defined(TRANSFER_QUEUE)
+ PVR_IO_NSTD(SGX_SUBMITTRANSFER, SGXSubmitTransferBW,
+ sizeof(PVRSRV_BRIDGE_IN_SUBMITTRANSFER),
+ sizeof(PVRSRV_BRIDGE_RETURN),
+ offsetof(PVRSRV_BRIDGE_RETURN, eError));
+#endif
+ PVR_IO_NSTD(SGX_GETMISCINFO, SGXGetMiscInfoBW,
+ sizeof(PVRSRV_BRIDGE_IN_SGXGETMISCINFO),
+ sizeof(PVRSRV_BRIDGE_RETURN),
+ offsetof(PVRSRV_BRIDGE_RETURN, eError));
+ PVR_IO_NSTD(SGXINFO_FOR_SRVINIT, SGXGetInfoForSrvinitBW,
+ sizeof(PVRSRV_BRIDGE_IN_SGXINFO_FOR_SRVINIT),
+ sizeof(PVRSRV_BRIDGE_OUT_SGXINFO_FOR_SRVINIT),
+ offsetof(PVRSRV_BRIDGE_OUT_SGXINFO_FOR_SRVINIT, eError));
+ PVR_IO_NSTD(SGX_DEVINITPART2, SGXDevInitPart2BW,
+ sizeof(PVRSRV_BRIDGE_IN_SGXDEVINITPART2),
+ sizeof(PVRSRV_BRIDGE_RETURN),
+ offsetof(PVRSRV_BRIDGE_RETURN, eError));
+ PVR_IO_NSTD(SGX_FINDSHAREDPBDESC, SGXFindSharedPBDescBW,
+ sizeof(PVRSRV_BRIDGE_IN_SGXFINDSHAREDPBDESC),
+ sizeof(PVRSRV_BRIDGE_OUT_SGXFINDSHAREDPBDESC),
+ offsetof(PVRSRV_BRIDGE_OUT_SGXFINDSHAREDPBDESC, eError));
+ PVR_IO_NSTD(SGX_UNREFSHAREDPBDESC, SGXUnrefSharedPBDescBW,
+ sizeof(PVRSRV_BRIDGE_IN_SGXUNREFSHAREDPBDESC),
+ sizeof(PVRSRV_BRIDGE_OUT_SGXUNREFSHAREDPBDESC),
+ offsetof(PVRSRV_BRIDGE_OUT_SGXUNREFSHAREDPBDESC, eError));
+ PVR_IO_NSTD(SGX_ADDSHAREDPBDESC, SGXAddSharedPBDescBW,
+ sizeof(PVRSRV_BRIDGE_IN_SGXADDSHAREDPBDESC),
+ sizeof(PVRSRV_BRIDGE_OUT_SGXADDSHAREDPBDESC),
+ offsetof(PVRSRV_BRIDGE_OUT_SGXADDSHAREDPBDESC, eError));
+ PVR_IO_RW(SGX_REGISTER_HW_RENDER_CONTEXT, SGXRegisterHWRenderContextBW);
+ PVR_IO_W(SGX_FLUSH_HW_RENDER_TARGET, SGXFlushHWRenderTargetBW);
+ PVR_IO_W(SGX_UNREGISTER_HW_RENDER_CONTEXT, SGXUnregisterHWRenderContextBW);
+#if defined(SGX_FEATURE_2D_HARDWARE)
+ PVR_IO_NSTD(SGX_SUBMIT2D, SGXSubmit2DBW,
+ sizeof(PVRSRV_BRIDGE_IN_SUBMIT2D),
+ sizeof(PVRSRV_BRIDGE_OUT_SUBMIT2D),
+ offsetof(PVRSRV_BRIDGE_OUT_SUBMIT2D, eError));
+ PVR_IO_NSTD(SGX_REGISTER_HW_2D_CONTEXT, SGXRegisterHW2DContextBW,
+ sizeof(PVRSRV_BRIDGE_IN_REGISTER_HW_2D_CONTEXT),
+ sizeof(PVRSRV_BRIDGE_OUT_REGISTER_HW_2D_CONTEXT),
+ offsetof(PVRSRV_BRIDGE_OUT_REGISTER_HW_2D_CONTEXT, eError));
+ PVR_IO_NSTD(SGX_UNREGISTER_HW_2D_CONTEXT, SGXUnregisterHW2DContextBW,
+ sizeof(PVRSRV_BRIDGE_IN_UNREGISTER_HW_2D_CONTEXT),
+ sizeof(PVRSRV_BRIDGE_OUT_UNREGISTER_HW_2D_CONTEXT),
+ offsetof(PVRSRV_BRIDGE_OUT_UNREGISTER_HW_2D_CONTEXT, eError));
+#endif
+ PVR_IO_RW(SGX_REGISTER_HW_TRANSFER_CONTEXT, SGXRegisterHWTransferContextBW);
+ PVR_IO_W(SGX_UNREGISTER_HW_TRANSFER_CONTEXT, SGXUnregisterHWTransferContextBW);
+ PVR_IO_W(SGX_SCHEDULE_PROCESS_QUEUES, SGXScheduleProcessQueuesBW);
+ PVR_IO_RW(SGX_READ_HWPERF_CB, SGXReadHWPerfCBBW);
+
+#if defined(PDUMP)
+ PVR_IO_NSTD(SGX_PDUMP_BUFFER_ARRAY, SGXPDumpBufferArrayBW,
+ sizeof(PVRSRV_BRIDGE_IN_PDUMP_BUFFER_ARRAY), 0, 0);
+ PVR_IO_NSTD(SGX_PDUMP_3D_SIGNATURE_REGISTERS, SGXPDump3DSignatureRegistersBW,
+ sizeof(PVRSRV_BRIDGE_IN_PDUMP_3D_SIGNATURE_REGISTERS),
+ sizeof(PVRSRV_BRIDGE_RETURN),
+ offsetof(PVRSRV_BRIDGE_RETURN, eError));
+ PVR_IO_NSTD(SGX_PDUMP_COUNTER_REGISTERS, SGXPDumpCounterRegistersBW,
+ sizeof(PVRSRV_BRIDGE_IN_PDUMP_COUNTER_REGISTERS), 0, 0);
+ PVR_IO_NSTD(SGX_PDUMP_TA_SIGNATURE_REGISTERS, SGXPDumpTASignatureRegistersBW,
+ sizeof(PVRSRV_BRIDGE_IN_PDUMP_TA_SIGNATURE_REGISTERS),
+ sizeof(PVRSRV_BRIDGE_RETURN),
+ offsetof(PVRSRV_BRIDGE_RETURN, eError));
+ PVR_IO_NSTD(SGX_PDUMP_HWPERFCB, SGXPDumpHWPerfCBBW,
+ sizeof(PVRSRV_BRIDGE_IN_PDUMP_HWPERFCB),
+ sizeof(PVRSRV_BRIDGE_RETURN),
+ offsetof(PVRSRV_BRIDGE_RETURN, eError));
+ PVR_IO_NSTD(SGX_PDUMP_SAVEMEM, SGXPDumpSaveMemBW,
+ sizeof(PVRSRV_BRIDGE_IN_PDUMP_SAVEMEM),
+ sizeof(PVRSRV_BRIDGE_RETURN),
+ offsetof(PVRSRV_BRIDGE_RETURN, eError));
+#endif
+}
+
+
+#endif
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef __BRIDGED_SGX_BRIDGE_H__
+#define __BRIDGED_SGX_BRIDGE_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+
+IMG_VOID SetSGXDispatchTableEntry(IMG_VOID);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
--- /dev/null
+bin_pc_i686*
+tmp_pc_i686*
+host_pc_i686*
+*.o
+*.o.cmd
--- /dev/null
+/**********************************************************************
+ *
+ * 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 "services_headers.h"
+
+#include "sysconfig.h"
+#include "hash.h"
+#include "ra.h"
+#include "pdump_km.h"
+#include "lists.h"
+
+static IMG_BOOL
+ZeroBuf(BM_BUF *pBuf, BM_MAPPING *pMapping, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags);
+static IMG_VOID
+BM_FreeMemory (IMG_VOID *pH, IMG_UINTPTR_T base, BM_MAPPING *psMapping);
+static IMG_BOOL
+BM_ImportMemory(IMG_VOID *pH, IMG_SIZE_T uSize,
+ IMG_SIZE_T *pActualSize, BM_MAPPING **ppsMapping,
+ IMG_UINT32 uFlags, IMG_UINTPTR_T *pBase);
+
+static IMG_BOOL
+DevMemoryAlloc (BM_CONTEXT *pBMContext,
+ BM_MAPPING *pMapping,
+ IMG_SIZE_T *pActualSize,
+ IMG_UINT32 uFlags,
+ IMG_UINT32 dev_vaddr_alignment,
+ IMG_DEV_VIRTADDR *pDevVAddr);
+static IMG_VOID
+DevMemoryFree (BM_MAPPING *pMapping);
+
+static IMG_BOOL
+AllocMemory (BM_CONTEXT *pBMContext,
+ BM_HEAP *psBMHeap,
+ IMG_DEV_VIRTADDR *psDevVAddr,
+ IMG_SIZE_T uSize,
+ IMG_UINT32 uFlags,
+ IMG_UINT32 uDevVAddrAlignment,
+ BM_BUF *pBuf)
+{
+ BM_MAPPING *pMapping;
+ IMG_UINTPTR_T uOffset;
+ RA_ARENA *pArena = IMG_NULL;
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "AllocMemory (uSize=0x%x, uFlags=0x%x, align=0x%x)",
+ uSize, uFlags, uDevVAddrAlignment));
+
+
+
+
+ if(uFlags & PVRSRV_MEM_RAM_BACKED_ALLOCATION)
+ {
+ if(uFlags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR)
+ {
+
+ PVR_DPF ((PVR_DBG_ERROR, "AllocMemory: combination of DevVAddr management and RAM backing mode unsupported"));
+ return IMG_FALSE;
+ }
+
+
+
+
+ if(psBMHeap->ui32Attribs
+ & (PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG
+ |PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG))
+ {
+
+ pArena = psBMHeap->pImportArena;
+ PVR_ASSERT(psBMHeap->sDevArena.psDeviceMemoryHeapInfo->ui32Attribs & PVRSRV_MEM_RAM_BACKED_ALLOCATION);
+ }
+ else
+ {
+ PVR_DPF ((PVR_DBG_ERROR, "AllocMemory: backing store type doesn't match heap"));
+ return IMG_FALSE;
+ }
+
+
+ if (!RA_Alloc(pArena,
+ uSize,
+ IMG_NULL,
+ (IMG_VOID*) &pMapping,
+ uFlags,
+ uDevVAddrAlignment,
+ 0,
+ (IMG_UINTPTR_T *)&(pBuf->DevVAddr.uiAddr)))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "AllocMemory: RA_Alloc(0x%x) FAILED", uSize));
+ return IMG_FALSE;
+ }
+
+ uOffset = pBuf->DevVAddr.uiAddr - pMapping->DevVAddr.uiAddr;
+ if(pMapping->CpuVAddr)
+ {
+ pBuf->CpuVAddr = (IMG_VOID*) ((IMG_UINTPTR_T)pMapping->CpuVAddr + uOffset);
+ }
+ else
+ {
+ pBuf->CpuVAddr = IMG_NULL;
+ }
+
+ if(uSize == pMapping->uSize)
+ {
+ pBuf->hOSMemHandle = pMapping->hOSMemHandle;
+ }
+ else
+ {
+ if(OSGetSubMemHandle(pMapping->hOSMemHandle,
+ uOffset,
+ uSize,
+ psBMHeap->ui32Attribs,
+ &pBuf->hOSMemHandle)!=PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "AllocMemory: OSGetSubMemHandle FAILED"));
+ return IMG_FALSE;
+ }
+ }
+
+
+ pBuf->CpuPAddr.uiAddr = pMapping->CpuPAddr.uiAddr + uOffset;
+
+ if(uFlags & PVRSRV_MEM_ZERO)
+ {
+ if(!ZeroBuf(pBuf, pMapping, uSize, psBMHeap->ui32Attribs | uFlags))
+ {
+ return IMG_FALSE;
+ }
+ }
+ }
+ else
+ {
+ if(uFlags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR)
+ {
+
+ PVR_ASSERT(psDevVAddr != IMG_NULL);
+
+ if (psDevVAddr == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "AllocMemory: invalid parameter - psDevVAddr"));
+ return IMG_FALSE;
+ }
+
+
+ pBMContext->psDeviceNode->pfnMMUAlloc (psBMHeap->pMMUHeap,
+ uSize,
+ IMG_NULL,
+ PVRSRV_MEM_USER_SUPPLIED_DEVVADDR,
+ uDevVAddrAlignment,
+ psDevVAddr);
+
+
+ pBuf->DevVAddr = *psDevVAddr;
+ }
+ else
+ {
+
+
+
+ pBMContext->psDeviceNode->pfnMMUAlloc (psBMHeap->pMMUHeap,
+ uSize,
+ IMG_NULL,
+ 0,
+ uDevVAddrAlignment,
+ &pBuf->DevVAddr);
+ }
+
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof (struct _BM_MAPPING_),
+ (IMG_PVOID *)&pMapping, IMG_NULL,
+ "Buffer Manager Mapping") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "AllocMemory: OSAllocMem(0x%x) FAILED", sizeof(*pMapping)));
+ return IMG_FALSE;
+ }
+
+
+ pBuf->CpuVAddr = IMG_NULL;
+ pBuf->hOSMemHandle = 0;
+ pBuf->CpuPAddr.uiAddr = 0;
+
+
+ pMapping->CpuVAddr = IMG_NULL;
+ pMapping->CpuPAddr.uiAddr = 0;
+ pMapping->DevVAddr = pBuf->DevVAddr;
+ pMapping->psSysAddr = IMG_NULL;
+ pMapping->uSize = uSize;
+ pMapping->hOSMemHandle = 0;
+ }
+
+
+ pMapping->pArena = pArena;
+
+ pMapping->psDeviceNode = psBMHeap->pBMContext->psDeviceNode;
+ pMapping->pBMContext = psBMHeap->pBMContext;
+ pMapping->pBMHeap = psBMHeap;
+ pBuf->pMapping = pMapping;
+
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "AllocMemory: pMapping=%08x: DevV=%08X CpuV=%08x CpuP=%08X uSize=0x%x",
+ (IMG_UINTPTR_T)pMapping,
+ pMapping->DevVAddr.uiAddr,
+ (IMG_UINTPTR_T)pMapping->CpuVAddr,
+ pMapping->CpuPAddr.uiAddr,
+ pMapping->uSize));
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "AllocMemory: pBuf=%08x: DevV=%08X CpuV=%08x CpuP=%08X uSize=0x%x",
+ (IMG_UINTPTR_T)pBuf,
+ pBuf->DevVAddr.uiAddr,
+ (IMG_UINTPTR_T)pBuf->CpuVAddr,
+ pBuf->CpuPAddr.uiAddr,
+ uSize));
+
+
+ PVR_ASSERT(((pBuf->DevVAddr.uiAddr) & (uDevVAddrAlignment - 1)) == 0);
+
+ return IMG_TRUE;
+}
+
+
+static IMG_BOOL
+WrapMemory (BM_HEAP *psBMHeap,
+ IMG_SIZE_T uSize,
+ IMG_SIZE_T ui32BaseOffset,
+ IMG_BOOL bPhysContig,
+ IMG_SYS_PHYADDR *psAddr,
+ IMG_VOID *pvCPUVAddr,
+ IMG_UINT32 uFlags,
+ BM_BUF *pBuf)
+{
+ IMG_DEV_VIRTADDR DevVAddr = {0};
+ BM_MAPPING *pMapping;
+ IMG_BOOL bResult;
+ IMG_SIZE_T const ui32PageSize = HOST_PAGESIZE();
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "WrapMemory(psBMHeap=%08X, size=0x%x, offset=0x%x, bPhysContig=0x%x, pvCPUVAddr = 0x%08x, flags=0x%x)",
+ (IMG_UINTPTR_T)psBMHeap, uSize, ui32BaseOffset, bPhysContig, (IMG_UINTPTR_T)pvCPUVAddr, uFlags));
+
+ PVR_ASSERT((psAddr->uiAddr & (ui32PageSize - 1)) == 0);
+
+ PVR_ASSERT(((IMG_UINTPTR_T)pvCPUVAddr & (ui32PageSize - 1)) == 0);
+
+ uSize += ui32BaseOffset;
+ uSize = HOST_PAGEALIGN (uSize);
+
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(*pMapping),
+ (IMG_PVOID *)&pMapping, IMG_NULL,
+ "Mocked-up mapping") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "WrapMemory: OSAllocMem(0x%x) FAILED",sizeof(*pMapping)));
+ return IMG_FALSE;
+ }
+
+ OSMemSet(pMapping, 0, sizeof (*pMapping));
+
+ pMapping->uSize = uSize;
+ pMapping->pBMHeap = psBMHeap;
+ pMapping->psDeviceNode = psBMHeap->pBMContext->psDeviceNode;
+ pMapping->pBMContext = psBMHeap->pBMContext;
+
+ if(pvCPUVAddr)
+ {
+ pMapping->CpuVAddr = pvCPUVAddr;
+
+ if (bPhysContig)
+ {
+ pMapping->eCpuMemoryOrigin = hm_wrapped_virtaddr;
+ pMapping->CpuPAddr = SysSysPAddrToCpuPAddr(psAddr[0]);
+
+ if(OSRegisterMem(pMapping->CpuPAddr,
+ pMapping->CpuVAddr,
+ pMapping->uSize,
+ uFlags,
+ &pMapping->hOSMemHandle) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "WrapMemory: OSRegisterMem Phys=0x%08X, Size=%d) failed",
+ pMapping->CpuPAddr.uiAddr, pMapping->uSize));
+ goto fail_cleanup;
+ }
+ }
+ else
+ {
+ pMapping->eCpuMemoryOrigin = hm_wrapped_scatter_virtaddr;
+ pMapping->psSysAddr = psAddr;
+
+ if(OSRegisterDiscontigMem(pMapping->psSysAddr,
+ pMapping->CpuVAddr,
+ pMapping->uSize,
+ uFlags,
+ &pMapping->hOSMemHandle) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "WrapMemory: OSRegisterDiscontigMem Size=%d) failed",
+ pMapping->uSize));
+ goto fail_cleanup;
+ }
+ }
+ }
+ else
+ {
+ if (bPhysContig)
+ {
+ pMapping->eCpuMemoryOrigin = hm_wrapped;
+ pMapping->CpuPAddr = SysSysPAddrToCpuPAddr(psAddr[0]);
+
+ if(OSReservePhys(pMapping->CpuPAddr,
+ pMapping->uSize,
+ uFlags,
+ &pMapping->CpuVAddr,
+ &pMapping->hOSMemHandle) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "WrapMemory: OSReservePhys Phys=0x%08X, Size=%d) failed",
+ pMapping->CpuPAddr.uiAddr, pMapping->uSize));
+ goto fail_cleanup;
+ }
+ }
+ else
+ {
+ pMapping->eCpuMemoryOrigin = hm_wrapped_scatter;
+ pMapping->psSysAddr = psAddr;
+
+ if(OSReserveDiscontigPhys(pMapping->psSysAddr,
+ pMapping->uSize,
+ uFlags,
+ &pMapping->CpuVAddr,
+ &pMapping->hOSMemHandle) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "WrapMemory: OSReserveDiscontigPhys Size=%d) failed",
+ pMapping->uSize));
+ goto fail_cleanup;
+ }
+ }
+ }
+
+
+ bResult = DevMemoryAlloc(psBMHeap->pBMContext,
+ pMapping,
+ IMG_NULL,
+ uFlags | PVRSRV_MEM_READ | PVRSRV_MEM_WRITE,
+ IMG_CAST_TO_DEVVADDR_UINT(ui32PageSize),
+ &DevVAddr);
+ if (!bResult)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "WrapMemory: DevMemoryAlloc(0x%x) failed",
+ pMapping->uSize));
+ goto fail_cleanup;
+ }
+
+
+ pBuf->CpuPAddr.uiAddr = pMapping->CpuPAddr.uiAddr + ui32BaseOffset;
+ if(!ui32BaseOffset)
+ {
+ pBuf->hOSMemHandle = pMapping->hOSMemHandle;
+ }
+ else
+ {
+ if(OSGetSubMemHandle(pMapping->hOSMemHandle,
+ ui32BaseOffset,
+ (pMapping->uSize-ui32BaseOffset),
+ uFlags,
+ &pBuf->hOSMemHandle)!=PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "WrapMemory: OSGetSubMemHandle failed"));
+ goto fail_cleanup;
+ }
+ }
+ if(pMapping->CpuVAddr)
+ {
+ pBuf->CpuVAddr = (IMG_VOID*) ((IMG_UINTPTR_T)pMapping->CpuVAddr + ui32BaseOffset);
+ }
+ pBuf->DevVAddr.uiAddr = pMapping->DevVAddr.uiAddr + IMG_CAST_TO_DEVVADDR_UINT(ui32BaseOffset);
+
+ if(uFlags & PVRSRV_MEM_ZERO)
+ {
+ if(!ZeroBuf(pBuf, pMapping, uSize, uFlags))
+ {
+ return IMG_FALSE;
+ }
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE, "DevVaddr.uiAddr=%08X", DevVAddr.uiAddr));
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "WrapMemory: DevV=%08X CpuP=%08X uSize=0x%x",
+ pMapping->DevVAddr.uiAddr, pMapping->CpuPAddr.uiAddr, pMapping->uSize));
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "WrapMemory: DevV=%08X CpuP=%08X uSize=0x%x",
+ pBuf->DevVAddr.uiAddr, pBuf->CpuPAddr.uiAddr, uSize));
+
+ pBuf->pMapping = pMapping;
+ return IMG_TRUE;
+
+fail_cleanup:
+ if(ui32BaseOffset && pBuf->hOSMemHandle)
+ {
+ OSReleaseSubMemHandle(pBuf->hOSMemHandle, uFlags);
+ }
+
+ if(pMapping && (pMapping->CpuVAddr || pMapping->hOSMemHandle))
+ {
+ switch(pMapping->eCpuMemoryOrigin)
+ {
+ case hm_wrapped:
+ OSUnReservePhys(pMapping->CpuVAddr, pMapping->uSize, uFlags, pMapping->hOSMemHandle);
+ break;
+ case hm_wrapped_virtaddr:
+ OSUnRegisterMem(pMapping->CpuVAddr, pMapping->uSize, uFlags, pMapping->hOSMemHandle);
+ break;
+ case hm_wrapped_scatter:
+ OSUnReserveDiscontigPhys(pMapping->CpuVAddr, pMapping->uSize, uFlags, pMapping->hOSMemHandle);
+ break;
+ case hm_wrapped_scatter_virtaddr:
+ OSUnRegisterDiscontigMem(pMapping->CpuVAddr, pMapping->uSize, uFlags, pMapping->hOSMemHandle);
+ break;
+ default:
+ break;
+ }
+
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), pMapping, IMG_NULL);
+
+
+ return IMG_FALSE;
+}
+
+
+static IMG_BOOL
+ZeroBuf(BM_BUF *pBuf, BM_MAPPING *pMapping, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags)
+{
+ IMG_VOID *pvCpuVAddr;
+
+ if(pBuf->CpuVAddr)
+ {
+ OSMemSet(pBuf->CpuVAddr, 0, ui32Bytes);
+ }
+ else if(pMapping->eCpuMemoryOrigin == hm_contiguous
+ || pMapping->eCpuMemoryOrigin == hm_wrapped)
+ {
+ pvCpuVAddr = OSMapPhysToLin(pBuf->CpuPAddr,
+ ui32Bytes,
+ PVRSRV_HAP_KERNEL_ONLY
+ | (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK),
+ IMG_NULL);
+ if(!pvCpuVAddr)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ZeroBuf: OSMapPhysToLin for contiguous buffer failed"));
+ return IMG_FALSE;
+ }
+ OSMemSet(pvCpuVAddr, 0, ui32Bytes);
+ OSUnMapPhysToLin(pvCpuVAddr,
+ ui32Bytes,
+ PVRSRV_HAP_KERNEL_ONLY
+ | (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK),
+ IMG_NULL);
+ }
+ else
+ {
+ IMG_SIZE_T ui32BytesRemaining = ui32Bytes;
+ IMG_SIZE_T ui32CurrentOffset = 0;
+ IMG_CPU_PHYADDR CpuPAddr;
+
+
+ PVR_ASSERT(pBuf->hOSMemHandle);
+
+ while(ui32BytesRemaining > 0)
+ {
+ IMG_SIZE_T ui32BlockBytes = MIN(ui32BytesRemaining, HOST_PAGESIZE());
+ CpuPAddr = OSMemHandleToCpuPAddr(pBuf->hOSMemHandle, ui32CurrentOffset);
+
+ if(CpuPAddr.uiAddr & (HOST_PAGESIZE() -1))
+ {
+ ui32BlockBytes =
+ MIN(ui32BytesRemaining, (IMG_UINT32)(HOST_PAGEALIGN(CpuPAddr.uiAddr) - CpuPAddr.uiAddr));
+ }
+
+ pvCpuVAddr = OSMapPhysToLin(CpuPAddr,
+ ui32BlockBytes,
+ PVRSRV_HAP_KERNEL_ONLY
+ | (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK),
+ IMG_NULL);
+ if(!pvCpuVAddr)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ZeroBuf: OSMapPhysToLin while zeroing non-contiguous memory FAILED"));
+ return IMG_FALSE;
+ }
+ OSMemSet(pvCpuVAddr, 0, ui32BlockBytes);
+ OSUnMapPhysToLin(pvCpuVAddr,
+ ui32BlockBytes,
+ PVRSRV_HAP_KERNEL_ONLY
+ | (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK),
+ IMG_NULL);
+
+ ui32BytesRemaining -= ui32BlockBytes;
+ ui32CurrentOffset += ui32BlockBytes;
+ }
+ }
+
+ return IMG_TRUE;
+}
+
+static IMG_VOID
+FreeBuf (BM_BUF *pBuf, IMG_UINT32 ui32Flags, IMG_BOOL bFromAllocator)
+{
+ BM_MAPPING *pMapping;
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "FreeBuf: pBuf=0x%x: DevVAddr=%08X CpuVAddr=0x%x CpuPAddr=%08X",
+ (IMG_UINTPTR_T)pBuf, pBuf->DevVAddr.uiAddr,
+ (IMG_UINTPTR_T)pBuf->CpuVAddr, pBuf->CpuPAddr.uiAddr));
+
+
+ pMapping = pBuf->pMapping;
+
+ if(ui32Flags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR)
+ {
+
+ if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
+ {
+
+ if(ui32Flags & PVRSRV_MEM_RAM_BACKED_ALLOCATION)
+ {
+
+ PVR_DPF ((PVR_DBG_ERROR, "FreeBuf: combination of DevVAddr management and RAM backing mode unsupported"));
+ }
+ else
+ {
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), pMapping, IMG_NULL);
+ pBuf->pMapping = IMG_NULL;
+ }
+ }
+ }
+ else
+ {
+ SYS_DATA *psSysData;
+ IMG_BOOL bBufferValid = IMG_TRUE;
+
+ SysAcquireData(&psSysData);
+ if (!List_PVRSRV_DEVICE_NODE_Find(psSysData->psDeviceNodeList, pMapping->psDeviceNode))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Invalid PVRSRV_DEVICE_NODE %p", pMapping->psDeviceNode));
+ bBufferValid = IMG_FALSE;
+ }
+ else if ((!List_BM_CONTEXT_Find(pMapping->psDeviceNode->sDevMemoryInfo.pBMContext, pMapping->pBMContext)) &&
+ (pMapping->pBMContext != pMapping->psDeviceNode->sDevMemoryInfo.pBMKernelContext))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Invalid BM_Context %p", pMapping->pBMContext));
+ bBufferValid = IMG_FALSE;
+ }
+ else if (!List_BM_HEAP_Find(pMapping->pBMContext->psBMHeap, pMapping->pBMHeap))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Invalid BM_Heap %p", pMapping->pBMHeap));
+ bBufferValid = IMG_FALSE;
+ }
+
+#if defined(PVRSRV_RESOURCE_PROFILING)
+ if ((bBufferValid == IMG_TRUE) && pMapping->psDeviceNode->pfnResProfCB)
+ {
+ pMapping->psDeviceNode->pfnResProfCB((IMG_PVOID)pMapping->psDeviceNode, pMapping->uSize, IMG_FALSE);
+ }
+#endif
+
+ if(pBuf->hOSMemHandle != pMapping->hOSMemHandle)
+ {
+
+ if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
+ {
+ if (bBufferValid == IMG_TRUE)
+ {
+ OSReleaseSubMemHandle(pBuf->hOSMemHandle, ui32Flags);
+ }
+ }
+ }
+ if(ui32Flags & PVRSRV_MEM_RAM_BACKED_ALLOCATION)
+ {
+
+
+ if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
+ {
+
+
+
+ PVR_ASSERT(pBuf->ui32ExportCount == 0);
+ if (bBufferValid == IMG_TRUE)
+ {
+ RA_Free (pBuf->pMapping->pArena, pBuf->DevVAddr.uiAddr, IMG_FALSE);
+ }
+ }
+ }
+ else
+ {
+ if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
+ {
+ switch (pMapping->eCpuMemoryOrigin)
+ {
+ case hm_wrapped:
+ OSUnReservePhys(pMapping->CpuVAddr, pMapping->uSize, ui32Flags, pMapping->hOSMemHandle);
+ break;
+ case hm_wrapped_virtaddr:
+ OSUnRegisterMem(pMapping->CpuVAddr, pMapping->uSize, ui32Flags, pMapping->hOSMemHandle);
+ break;
+ case hm_wrapped_scatter:
+ OSUnReserveDiscontigPhys(pMapping->CpuVAddr, pMapping->uSize, ui32Flags, pMapping->hOSMemHandle);
+ break;
+ case hm_wrapped_scatter_virtaddr:
+ OSUnRegisterDiscontigMem(pMapping->CpuVAddr, pMapping->uSize, ui32Flags, pMapping->hOSMemHandle);
+ break;
+ default:
+ break;
+ }
+ }
+ if (bBufferValid == IMG_TRUE && bFromAllocator)
+ {
+ DevMemoryFree (pMapping);
+ }
+
+ if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
+ {
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), pMapping, IMG_NULL);
+ pBuf->pMapping = IMG_NULL;
+ }
+ }
+ }
+
+
+ if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_BUF), pBuf, IMG_NULL);
+
+ }
+}
+
+static PVRSRV_ERROR BM_DestroyContext_AnyCb(BM_HEAP *psBMHeap)
+{
+ if(psBMHeap->ui32Attribs
+ & (PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG
+ |PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG))
+ {
+ if (psBMHeap->pImportArena)
+ {
+ IMG_BOOL bTestDelete = RA_TestDelete(psBMHeap->pImportArena);
+ if (!bTestDelete)
+ {
+ PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext_AnyCb: RA_TestDelete failed"));
+ return PVRSRV_ERROR_UNABLE_TO_DESTROY_BM_HEAP;
+ }
+ }
+ }
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR
+BM_DestroyContext(IMG_HANDLE hBMContext,
+ IMG_BOOL *pbDestroyed)
+{
+ PVRSRV_ERROR eError;
+ BM_CONTEXT *pBMContext = (BM_CONTEXT*)hBMContext;
+
+ PVR_DPF ((PVR_DBG_MESSAGE, "BM_DestroyContext"));
+
+ if (pbDestroyed != IMG_NULL)
+ {
+ *pbDestroyed = IMG_FALSE;
+ }
+
+
+
+ if (pBMContext == IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: Invalid handle"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ pBMContext->ui32RefCount--;
+
+ if (pBMContext->ui32RefCount > 0)
+ {
+
+ return PVRSRV_OK;
+ }
+
+
+
+
+ eError = List_BM_HEAP_PVRSRV_ERROR_Any(pBMContext->psBMHeap, &BM_DestroyContext_AnyCb);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: List_BM_HEAP_PVRSRV_ERROR_Any failed"));
+#if 0
+
+
+
+
+ PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: Cleaning up with ResManFreeSpecial"));
+ if(ResManFreeSpecial() != PVRSRV_OK)
+ {
+ PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: ResManFreeSpecial failed %d",eError));
+ }
+
+#endif
+ return eError;
+ }
+ else
+ {
+
+ eError = ResManFreeResByPtr(pBMContext->hResItem);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: ResManFreeResByPtr failed %d",eError));
+ return eError;
+ }
+
+
+ if (pbDestroyed != IMG_NULL)
+ {
+ *pbDestroyed = IMG_TRUE;
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR BM_DestroyContextCallBack_AnyVaCb(BM_HEAP *psBMHeap, va_list va)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ psDeviceNode = va_arg(va, PVRSRV_DEVICE_NODE*);
+
+
+ if(psBMHeap->ui32Attribs
+ & (PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG
+ |PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG))
+ {
+ if (psBMHeap->pImportArena)
+ {
+ RA_Delete (psBMHeap->pImportArena);
+ }
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_DestroyContext: backing store type unsupported"));
+ return PVRSRV_ERROR_UNSUPPORTED_BACKING_STORE;
+ }
+
+
+ psDeviceNode->pfnMMUDelete(psBMHeap->pMMUHeap);
+
+ List_BM_HEAP_Remove(psBMHeap);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_HEAP), psBMHeap, IMG_NULL);
+
+
+ return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR BM_DestroyContextCallBack(IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param)
+{
+ BM_CONTEXT *pBMContext = pvParam;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ PVRSRV_ERROR eError;
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+
+
+ psDeviceNode = pBMContext->psDeviceNode;
+
+
+
+ eError = List_BM_HEAP_PVRSRV_ERROR_Any_va(pBMContext->psBMHeap,
+ &BM_DestroyContextCallBack_AnyVaCb,
+ psDeviceNode);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+
+ if (pBMContext->psMMUContext)
+ {
+ psDeviceNode->pfnMMUFinalise(pBMContext->psMMUContext);
+ }
+
+
+
+ if (pBMContext->pBufferHash)
+ {
+ HASH_Delete(pBMContext->pBufferHash);
+ }
+
+ if (pBMContext == psDeviceNode->sDevMemoryInfo.pBMKernelContext)
+ {
+
+ psDeviceNode->sDevMemoryInfo.pBMKernelContext = IMG_NULL;
+ }
+ else
+ {
+
+ List_BM_CONTEXT_Remove(pBMContext);
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_CONTEXT), pBMContext, IMG_NULL);
+
+
+ return PVRSRV_OK;
+}
+
+
+static IMG_HANDLE BM_CreateContext_IncRefCount_AnyVaCb(BM_CONTEXT *pBMContext, va_list va)
+{
+ PRESMAN_CONTEXT hResManContext;
+ hResManContext = va_arg(va, PRESMAN_CONTEXT);
+ if(ResManFindResourceByPtr(hResManContext, pBMContext->hResItem) == PVRSRV_OK)
+ {
+
+ pBMContext->ui32RefCount++;
+ return pBMContext;
+ }
+ return IMG_NULL;
+}
+
+static IMG_VOID BM_CreateContext_InsertHeap_ForEachVaCb(BM_HEAP *psBMHeap, va_list va)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ BM_CONTEXT *pBMContext;
+ psDeviceNode = va_arg(va, PVRSRV_DEVICE_NODE*);
+ pBMContext = va_arg(va, BM_CONTEXT*);
+ switch(psBMHeap->sDevArena.DevMemHeapType)
+ {
+ case DEVICE_MEMORY_HEAP_SHARED:
+ case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
+ {
+
+ psDeviceNode->pfnMMUInsertHeap(pBMContext->psMMUContext, psBMHeap->pMMUHeap);
+ break;
+ }
+ }
+}
+
+IMG_HANDLE
+BM_CreateContext(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_DEV_PHYADDR *psPDDevPAddr,
+ PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_BOOL *pbCreated)
+{
+ BM_CONTEXT *pBMContext;
+ DEVICE_MEMORY_INFO *psDevMemoryInfo;
+ IMG_BOOL bKernelContext;
+ PRESMAN_CONTEXT hResManContext;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "BM_CreateContext"));
+
+ if (psPerProc == IMG_NULL)
+ {
+ bKernelContext = IMG_TRUE;
+ hResManContext = psDeviceNode->hResManContext;
+ }
+ else
+ {
+ bKernelContext = IMG_FALSE;
+ hResManContext = psPerProc->hResManContext;
+ }
+
+ if (pbCreated != IMG_NULL)
+ {
+ *pbCreated = IMG_FALSE;
+ }
+
+
+ psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+
+ if (bKernelContext == IMG_FALSE)
+ {
+ IMG_HANDLE res = (IMG_HANDLE) List_BM_CONTEXT_Any_va(psDevMemoryInfo->pBMContext,
+ &BM_CreateContext_IncRefCount_AnyVaCb,
+ hResManContext);
+ if (res)
+ {
+ return res;
+ }
+ }
+
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof (struct _BM_CONTEXT_),
+ (IMG_PVOID *)&pBMContext, IMG_NULL,
+ "Buffer Manager Context") != PVRSRV_OK)
+ {
+ PVR_DPF ((PVR_DBG_ERROR, "BM_CreateContext: Alloc failed"));
+ return IMG_NULL;
+ }
+ OSMemSet(pBMContext, 0, sizeof (BM_CONTEXT));
+
+
+ pBMContext->psDeviceNode = psDeviceNode;
+
+
+
+ pBMContext->pBufferHash = HASH_Create(32);
+ if (pBMContext->pBufferHash==IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR, "BM_CreateContext: HASH_Create failed"));
+ goto cleanup;
+ }
+
+ if(psDeviceNode->pfnMMUInitialise(psDeviceNode,
+ &pBMContext->psMMUContext,
+ psPDDevPAddr) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_CreateContext: MMUInitialise failed"));
+ goto cleanup;
+ }
+
+ if(bKernelContext)
+ {
+
+ PVR_ASSERT(psDevMemoryInfo->pBMKernelContext == IMG_NULL);
+ psDevMemoryInfo->pBMKernelContext = pBMContext;
+ }
+ else
+ {
+
+
+
+
+
+ PVR_ASSERT(psDevMemoryInfo->pBMKernelContext);
+
+ if (psDevMemoryInfo->pBMKernelContext == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_CreateContext: psDevMemoryInfo->pBMKernelContext invalid"));
+ goto cleanup;
+ }
+
+ PVR_ASSERT(psDevMemoryInfo->pBMKernelContext->psBMHeap);
+
+
+
+
+
+ pBMContext->psBMSharedHeap = psDevMemoryInfo->pBMKernelContext->psBMHeap;
+
+
+
+
+ List_BM_HEAP_ForEach_va(pBMContext->psBMSharedHeap,
+ &BM_CreateContext_InsertHeap_ForEachVaCb,
+ psDeviceNode,
+ pBMContext);
+
+
+ List_BM_CONTEXT_Insert(&psDevMemoryInfo->pBMContext, pBMContext);
+ }
+
+
+ pBMContext->ui32RefCount++;
+
+
+ pBMContext->hResItem = ResManRegisterRes(hResManContext,
+ RESMAN_TYPE_DEVICEMEM_CONTEXT,
+ pBMContext,
+ 0,
+ &BM_DestroyContextCallBack);
+ if (pBMContext->hResItem == IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR, "BM_CreateContext: ResManRegisterRes failed"));
+ goto cleanup;
+ }
+
+ if (pbCreated != IMG_NULL)
+ {
+ *pbCreated = IMG_TRUE;
+ }
+ return (IMG_HANDLE)pBMContext;
+
+cleanup:
+ (IMG_VOID)BM_DestroyContextCallBack(pBMContext, 0);
+
+ return IMG_NULL;
+}
+
+
+static IMG_VOID *BM_CreateHeap_AnyVaCb(BM_HEAP *psBMHeap, va_list va)
+{
+ DEVICE_MEMORY_HEAP_INFO *psDevMemHeapInfo;
+ psDevMemHeapInfo = va_arg(va, DEVICE_MEMORY_HEAP_INFO*);
+ if (psBMHeap->sDevArena.ui32HeapID == psDevMemHeapInfo->ui32HeapID)
+ {
+
+ return psBMHeap;
+ }
+ else
+ {
+ return IMG_NULL;
+ }
+}
+
+IMG_HANDLE
+BM_CreateHeap (IMG_HANDLE hBMContext,
+ DEVICE_MEMORY_HEAP_INFO *psDevMemHeapInfo)
+{
+ BM_CONTEXT *pBMContext = (BM_CONTEXT*)hBMContext;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ BM_HEAP *psBMHeap;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "BM_CreateHeap"));
+
+ if(!pBMContext)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_CreateHeap: BM_CONTEXT null"));
+ return IMG_NULL;
+ }
+
+ psDeviceNode = pBMContext->psDeviceNode;
+
+
+
+
+
+
+ if(pBMContext->ui32RefCount > 0)
+ {
+ psBMHeap = (BM_HEAP*)List_BM_HEAP_Any_va(pBMContext->psBMHeap,
+ &BM_CreateHeap_AnyVaCb,
+ psDevMemHeapInfo);
+
+ if (psBMHeap)
+ {
+ return psBMHeap;
+ }
+ }
+
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof (BM_HEAP),
+ (IMG_PVOID *)&psBMHeap, IMG_NULL,
+ "Buffer Manager Heap") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_CreateHeap: Alloc failed"));
+ return IMG_NULL;
+ }
+
+ OSMemSet (psBMHeap, 0, sizeof (BM_HEAP));
+
+ psBMHeap->sDevArena.ui32HeapID = psDevMemHeapInfo->ui32HeapID;
+ psBMHeap->sDevArena.pszName = psDevMemHeapInfo->pszName;
+ psBMHeap->sDevArena.BaseDevVAddr = psDevMemHeapInfo->sDevVAddrBase;
+ psBMHeap->sDevArena.ui32Size = psDevMemHeapInfo->ui32HeapSize;
+ psBMHeap->sDevArena.DevMemHeapType = psDevMemHeapInfo->DevMemHeapType;
+ psBMHeap->sDevArena.ui32DataPageSize = psDevMemHeapInfo->ui32DataPageSize;
+ psBMHeap->sDevArena.psDeviceMemoryHeapInfo = psDevMemHeapInfo;
+ psBMHeap->ui32Attribs = psDevMemHeapInfo->ui32Attribs;
+
+
+ psBMHeap->pBMContext = pBMContext;
+
+ psBMHeap->pMMUHeap = psDeviceNode->pfnMMUCreate (pBMContext->psMMUContext,
+ &psBMHeap->sDevArena,
+ &psBMHeap->pVMArena,
+ &psBMHeap->psMMUAttrib);
+ if (!psBMHeap->pMMUHeap)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_CreateHeap: MMUCreate failed"));
+ goto ErrorExit;
+ }
+
+
+ psBMHeap->pImportArena = RA_Create (psDevMemHeapInfo->pszBSName,
+ 0, 0, IMG_NULL,
+ MAX(HOST_PAGESIZE(), psBMHeap->sDevArena.ui32DataPageSize),
+ &BM_ImportMemory,
+ &BM_FreeMemory,
+ IMG_NULL,
+ psBMHeap);
+ if(psBMHeap->pImportArena == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_CreateHeap: RA_Create failed"));
+ goto ErrorExit;
+ }
+
+ if(psBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG)
+ {
+
+
+
+
+ psBMHeap->pLocalDevMemArena = psDevMemHeapInfo->psLocalDevMemArena;
+ if(psBMHeap->pLocalDevMemArena == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_CreateHeap: LocalDevMemArena null"));
+ goto ErrorExit;
+ }
+ }
+
+
+ List_BM_HEAP_Insert(&pBMContext->psBMHeap, psBMHeap);
+
+ return (IMG_HANDLE)psBMHeap;
+
+
+ErrorExit:
+
+
+ if (psBMHeap->pMMUHeap != IMG_NULL)
+ {
+ psDeviceNode->pfnMMUDelete (psBMHeap->pMMUHeap);
+ psDeviceNode->pfnMMUFinalise (pBMContext->psMMUContext);
+ }
+
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_HEAP), psBMHeap, IMG_NULL);
+
+
+ return IMG_NULL;
+}
+
+IMG_VOID
+BM_DestroyHeap (IMG_HANDLE hDevMemHeap)
+{
+ BM_HEAP* psBMHeap = (BM_HEAP*)hDevMemHeap;
+ PVRSRV_DEVICE_NODE *psDeviceNode = psBMHeap->pBMContext->psDeviceNode;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "BM_DestroyHeap"));
+
+ if(psBMHeap)
+ {
+
+ if(psBMHeap->ui32Attribs
+ & (PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG
+ |PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG))
+ {
+ if (psBMHeap->pImportArena)
+ {
+ RA_Delete (psBMHeap->pImportArena);
+ }
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_DestroyHeap: backing store type unsupported"));
+ return;
+ }
+
+
+ psDeviceNode->pfnMMUDelete (psBMHeap->pMMUHeap);
+
+
+ List_BM_HEAP_Remove(psBMHeap);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_HEAP), psBMHeap, IMG_NULL);
+
+ }
+ else
+ {
+ PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyHeap: invalid heap handle"));
+ }
+}
+
+
+IMG_BOOL
+BM_Reinitialise (PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+
+ PVR_DPF((PVR_DBG_MESSAGE, "BM_Reinitialise"));
+ PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+
+
+ return IMG_TRUE;
+}
+
+IMG_BOOL
+BM_Alloc ( IMG_HANDLE hDevMemHeap,
+ IMG_DEV_VIRTADDR *psDevVAddr,
+ IMG_SIZE_T uSize,
+ IMG_UINT32 *pui32Flags,
+ IMG_UINT32 uDevVAddrAlignment,
+ BM_HANDLE *phBuf)
+{
+ BM_BUF *pBuf;
+ BM_CONTEXT *pBMContext;
+ BM_HEAP *psBMHeap;
+ SYS_DATA *psSysData;
+ IMG_UINT32 uFlags;
+
+ if (pui32Flags == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_Alloc: invalid parameter"));
+ PVR_DBG_BREAK;
+ return IMG_FALSE;
+ }
+
+ uFlags = *pui32Flags;
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "BM_Alloc (uSize=0x%x, uFlags=0x%x, uDevVAddrAlignment=0x%x)",
+ uSize, uFlags, uDevVAddrAlignment));
+
+ SysAcquireData(&psSysData);
+
+ psBMHeap = (BM_HEAP*)hDevMemHeap;
+ pBMContext = psBMHeap->pBMContext;
+
+ if(uDevVAddrAlignment == 0)
+ {
+ uDevVAddrAlignment = 1;
+ }
+
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof (BM_BUF),
+ (IMG_PVOID *)&pBuf, IMG_NULL,
+ "Buffer Manager buffer") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_Alloc: BM_Buf alloc FAILED"));
+ return IMG_FALSE;
+ }
+ OSMemSet(pBuf, 0, sizeof (BM_BUF));
+
+
+ if (AllocMemory(pBMContext,
+ psBMHeap,
+ psDevVAddr,
+ uSize,
+ uFlags,
+ uDevVAddrAlignment,
+ pBuf) != IMG_TRUE)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof (BM_BUF), pBuf, IMG_NULL);
+
+ PVR_DPF((PVR_DBG_ERROR, "BM_Alloc: AllocMemory FAILED"));
+ return IMG_FALSE;
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "BM_Alloc (uSize=0x%x, uFlags=0x%x)",
+ uSize, uFlags));
+
+
+ pBuf->ui32RefCount = 1;
+ *phBuf = (BM_HANDLE)pBuf;
+ *pui32Flags = uFlags | psBMHeap->ui32Attribs;
+
+
+ if(uFlags & PVRSRV_HAP_CACHETYPE_MASK)
+ {
+ *pui32Flags &= ~PVRSRV_HAP_CACHETYPE_MASK;
+ *pui32Flags |= (uFlags & PVRSRV_HAP_CACHETYPE_MASK);
+ }
+
+ return IMG_TRUE;
+}
+
+
+
+#if defined(PVR_LMA)
+static IMG_BOOL
+ValidSysPAddrArrayForDev(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_SYS_PHYADDR *psSysPAddr, IMG_UINT32 ui32PageCount, IMG_SIZE_T ui32PageSize)
+{
+ IMG_UINT32 i;
+
+ for (i = 0; i < ui32PageCount; i++)
+ {
+ IMG_SYS_PHYADDR sStartSysPAddr = psSysPAddr[i];
+ IMG_SYS_PHYADDR sEndSysPAddr;
+
+ if (!SysVerifySysPAddrToDevPAddr(psDeviceNode->sDevId.eDeviceType, sStartSysPAddr))
+ {
+ return IMG_FALSE;
+ }
+
+ sEndSysPAddr.uiAddr = sStartSysPAddr.uiAddr + ui32PageSize;
+
+ if (!SysVerifySysPAddrToDevPAddr(psDeviceNode->sDevId.eDeviceType, sEndSysPAddr))
+ {
+ return IMG_FALSE;
+ }
+ }
+
+ return IMG_TRUE;
+}
+
+static IMG_BOOL
+ValidSysPAddrRangeForDev(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_SYS_PHYADDR sStartSysPAddr, IMG_SIZE_T ui32Range)
+{
+ IMG_SYS_PHYADDR sEndSysPAddr;
+
+ if (!SysVerifySysPAddrToDevPAddr(psDeviceNode->sDevId.eDeviceType, sStartSysPAddr))
+ {
+ return IMG_FALSE;
+ }
+
+ sEndSysPAddr.uiAddr = sStartSysPAddr.uiAddr + ui32Range;
+
+ if (!SysVerifySysPAddrToDevPAddr(psDeviceNode->sDevId.eDeviceType, sEndSysPAddr))
+ {
+ return IMG_FALSE;
+ }
+
+ return IMG_TRUE;
+}
+
+#define WRAP_MAPPING_SIZE(ui32ByteSize, ui32PageOffset) HOST_PAGEALIGN((ui32ByteSize) + (ui32PageOffset))
+
+#define WRAP_PAGE_COUNT(ui32ByteSize, ui32PageOffset, ui32HostPageSize) (WRAP_MAPPING_SIZE(ui32ByteSize, ui32PageOffset) / (ui32HostPageSize))
+
+#endif
+
+
+IMG_BOOL
+BM_Wrap ( IMG_HANDLE hDevMemHeap,
+ IMG_SIZE_T ui32Size,
+ IMG_SIZE_T ui32Offset,
+ IMG_BOOL bPhysContig,
+ IMG_SYS_PHYADDR *psSysAddr,
+ IMG_VOID *pvCPUVAddr,
+ IMG_UINT32 *pui32Flags,
+ BM_HANDLE *phBuf)
+{
+ BM_BUF *pBuf;
+ BM_CONTEXT *psBMContext;
+ BM_HEAP *psBMHeap;
+ SYS_DATA *psSysData;
+ IMG_SYS_PHYADDR sHashAddress;
+ IMG_UINT32 uFlags;
+
+ psBMHeap = (BM_HEAP*)hDevMemHeap;
+ psBMContext = psBMHeap->pBMContext;
+
+ uFlags = psBMHeap->ui32Attribs & (PVRSRV_HAP_CACHETYPE_MASK | PVRSRV_HAP_MAPTYPE_MASK);
+
+ if ((pui32Flags != IMG_NULL) && ((*pui32Flags & PVRSRV_HAP_CACHETYPE_MASK) != 0))
+ {
+ uFlags &= ~PVRSRV_HAP_CACHETYPE_MASK;
+ uFlags |= *pui32Flags & PVRSRV_HAP_CACHETYPE_MASK;
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "BM_Wrap (uSize=0x%x, uOffset=0x%x, bPhysContig=0x%x, pvCPUVAddr=0x%x, uFlags=0x%x)",
+ ui32Size, ui32Offset, bPhysContig, (IMG_UINTPTR_T)pvCPUVAddr, uFlags));
+
+ SysAcquireData(&psSysData);
+
+#if defined(PVR_LMA)
+ if (bPhysContig)
+ {
+ if (!ValidSysPAddrRangeForDev(psBMContext->psDeviceNode, *psSysAddr, WRAP_MAPPING_SIZE(ui32Size, ui32Offset)))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: System address range invalid for device"));
+ return IMG_FALSE;
+ }
+ }
+ else
+ {
+ IMG_SIZE_T ui32HostPageSize = HOST_PAGESIZE();
+
+ if (!ValidSysPAddrArrayForDev(psBMContext->psDeviceNode, psSysAddr, WRAP_PAGE_COUNT(ui32Size, ui32Offset, ui32HostPageSize), ui32HostPageSize))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: Array of system addresses invalid for device"));
+ return IMG_FALSE;
+ }
+ }
+#endif
+
+ sHashAddress = psSysAddr[0];
+
+
+ sHashAddress.uiAddr += ui32Offset;
+
+
+ pBuf = (BM_BUF *)HASH_Retrieve(psBMContext->pBufferHash, sHashAddress.uiAddr);
+
+ if(pBuf)
+ {
+ IMG_SIZE_T ui32MappingSize = HOST_PAGEALIGN (ui32Size + ui32Offset);
+
+
+ if(pBuf->pMapping->uSize == ui32MappingSize && (pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped ||
+ pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr))
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "BM_Wrap (Matched previous Wrap! uSize=0x%x, uOffset=0x%x, SysAddr=%08X)",
+ ui32Size, ui32Offset, sHashAddress.uiAddr));
+
+ pBuf->ui32RefCount++;
+ *phBuf = (BM_HANDLE)pBuf;
+ if(pui32Flags)
+ *pui32Flags = uFlags;
+
+ return IMG_TRUE;
+ }
+ }
+
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof (BM_BUF),
+ (IMG_PVOID *)&pBuf, IMG_NULL,
+ "Buffer Manager buffer") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: BM_Buf alloc FAILED"));
+ return IMG_FALSE;
+ }
+ OSMemSet(pBuf, 0, sizeof (BM_BUF));
+
+
+ if (WrapMemory (psBMHeap, ui32Size, ui32Offset, bPhysContig, psSysAddr, pvCPUVAddr, uFlags, pBuf) != IMG_TRUE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: WrapMemory FAILED"));
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof (BM_BUF), pBuf, IMG_NULL);
+
+ return IMG_FALSE;
+ }
+
+
+ if(pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped || pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr)
+ {
+
+ PVR_ASSERT(SysSysPAddrToCpuPAddr(sHashAddress).uiAddr == pBuf->CpuPAddr.uiAddr);
+
+ if (!HASH_Insert (psBMContext->pBufferHash, sHashAddress.uiAddr, (IMG_UINTPTR_T)pBuf))
+ {
+ FreeBuf (pBuf, uFlags, IMG_TRUE);
+ PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: HASH_Insert FAILED"));
+ return IMG_FALSE;
+ }
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "BM_Wrap (uSize=0x%x, uFlags=0x%x, devVAddr=%08X)",
+ ui32Size, uFlags, pBuf->DevVAddr.uiAddr));
+
+
+ pBuf->ui32RefCount = 1;
+ *phBuf = (BM_HANDLE)pBuf;
+ if(pui32Flags)
+ {
+
+ *pui32Flags = (uFlags & ~PVRSRV_HAP_MAPTYPE_MASK) | PVRSRV_HAP_MULTI_PROCESS;
+ }
+
+ return IMG_TRUE;
+}
+
+IMG_VOID
+BM_Export (BM_HANDLE hBuf)
+{
+ BM_BUF *pBuf = (BM_BUF *)hBuf;
+
+ pBuf->ui32ExportCount++;
+}
+
+IMG_VOID
+BM_FreeExport(BM_HANDLE hBuf,
+ IMG_UINT32 ui32Flags)
+{
+ BM_BUF *pBuf = (BM_BUF *)hBuf;
+
+ pBuf->ui32ExportCount--;
+ FreeBuf (pBuf, ui32Flags, IMG_FALSE);
+}
+
+IMG_VOID
+BM_Free (BM_HANDLE hBuf,
+ IMG_UINT32 ui32Flags)
+{
+ BM_BUF *pBuf = (BM_BUF *)hBuf;
+ SYS_DATA *psSysData;
+ IMG_SYS_PHYADDR sHashAddr;
+
+ PVR_DPF ((PVR_DBG_MESSAGE, "BM_Free (h=0x%x)", (IMG_UINTPTR_T)hBuf));
+ PVR_ASSERT (pBuf!=IMG_NULL);
+
+ if (pBuf == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_Free: invalid parameter"));
+ return;
+ }
+
+ SysAcquireData(&psSysData);
+
+ pBuf->ui32RefCount--;
+
+ if(pBuf->ui32RefCount == 0)
+ {
+ if(pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped || pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr)
+ {
+ sHashAddr = SysCpuPAddrToSysPAddr(pBuf->CpuPAddr);
+
+ HASH_Remove (pBuf->pMapping->pBMHeap->pBMContext->pBufferHash, (IMG_UINTPTR_T)sHashAddr.uiAddr);
+ }
+ FreeBuf (pBuf, ui32Flags, IMG_TRUE);
+ }
+}
+
+
+IMG_CPU_VIRTADDR
+BM_HandleToCpuVaddr (BM_HANDLE hBuf)
+{
+ BM_BUF *pBuf = (BM_BUF *)hBuf;
+
+ PVR_ASSERT (pBuf != IMG_NULL);
+ if (pBuf == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_HandleToCpuVaddr: invalid parameter"));
+ return IMG_NULL;
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "BM_HandleToCpuVaddr(h=0x%x)=0x%x",
+ (IMG_UINTPTR_T)hBuf, (IMG_UINTPTR_T)pBuf->CpuVAddr));
+ return pBuf->CpuVAddr;
+}
+
+
+IMG_DEV_VIRTADDR
+BM_HandleToDevVaddr (BM_HANDLE hBuf)
+{
+ BM_BUF *pBuf = (BM_BUF *)hBuf;
+
+ PVR_ASSERT (pBuf != IMG_NULL);
+ if (pBuf == IMG_NULL)
+ {
+ IMG_DEV_VIRTADDR DevVAddr = {0};
+ PVR_DPF((PVR_DBG_ERROR, "BM_HandleToDevVaddr: invalid parameter"));
+ return DevVAddr;
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE, "BM_HandleToDevVaddr(h=0x%x)=%08X", (IMG_UINTPTR_T)hBuf, pBuf->DevVAddr.uiAddr));
+ return pBuf->DevVAddr;
+}
+
+
+IMG_SYS_PHYADDR
+BM_HandleToSysPaddr (BM_HANDLE hBuf)
+{
+ BM_BUF *pBuf = (BM_BUF *)hBuf;
+
+ PVR_ASSERT (pBuf != IMG_NULL);
+
+ if (pBuf == IMG_NULL)
+ {
+ IMG_SYS_PHYADDR PhysAddr = {0};
+ PVR_DPF((PVR_DBG_ERROR, "BM_HandleToSysPaddr: invalid parameter"));
+ return PhysAddr;
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE, "BM_HandleToSysPaddr(h=0x%x)=%08X", (IMG_UINTPTR_T)hBuf, pBuf->CpuPAddr.uiAddr));
+ return SysCpuPAddrToSysPAddr (pBuf->CpuPAddr);
+}
+
+IMG_HANDLE
+BM_HandleToOSMemHandle(BM_HANDLE hBuf)
+{
+ BM_BUF *pBuf = (BM_BUF *)hBuf;
+
+ PVR_ASSERT (pBuf != IMG_NULL);
+
+ if (pBuf == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_HandleToOSMemHandle: invalid parameter"));
+ return IMG_NULL;
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "BM_HandleToOSMemHandle(h=0x%x)=0x%x",
+ (IMG_UINTPTR_T)hBuf, (IMG_UINTPTR_T)pBuf->hOSMemHandle));
+ return pBuf->hOSMemHandle;
+}
+
+static IMG_BOOL
+DevMemoryAlloc (BM_CONTEXT *pBMContext,
+ BM_MAPPING *pMapping,
+ IMG_SIZE_T *pActualSize,
+ IMG_UINT32 uFlags,
+ IMG_UINT32 dev_vaddr_alignment,
+ IMG_DEV_VIRTADDR *pDevVAddr)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+#ifdef PDUMP
+ IMG_UINT32 ui32PDumpSize = pMapping->uSize;
+#endif
+
+ psDeviceNode = pBMContext->psDeviceNode;
+
+ if(uFlags & PVRSRV_MEM_INTERLEAVED)
+ {
+
+ pMapping->uSize *= 2;
+ }
+
+#ifdef PDUMP
+ if(uFlags & PVRSRV_MEM_DUMMY)
+ {
+
+ ui32PDumpSize = pMapping->pBMHeap->sDevArena.ui32DataPageSize;
+ }
+#endif
+
+
+ if (!psDeviceNode->pfnMMUAlloc (pMapping->pBMHeap->pMMUHeap,
+ pMapping->uSize,
+ pActualSize,
+ 0,
+ dev_vaddr_alignment,
+ &(pMapping->DevVAddr)))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "DevMemoryAlloc ERROR MMU_Alloc"));
+ return IMG_FALSE;
+ }
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+ EnableHostAccess(pBMContext->psMMUContext);
+#endif
+
+#if defined(PDUMP)
+
+ PDUMPMALLOCPAGES(&psDeviceNode->sDevId,
+ pMapping->DevVAddr.uiAddr,
+ pMapping->CpuVAddr,
+ pMapping->hOSMemHandle,
+ ui32PDumpSize,
+ pMapping->pBMHeap->sDevArena.ui32DataPageSize,
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+ psDeviceNode->pfnMMUIsHeapShared(pMapping->pBMHeap->pMMUHeap),
+#else
+ IMG_FALSE,
+#endif
+ (IMG_HANDLE)pMapping);
+#endif
+
+ switch (pMapping->eCpuMemoryOrigin)
+ {
+ case hm_wrapped:
+ case hm_wrapped_virtaddr:
+ case hm_contiguous:
+ {
+ psDeviceNode->pfnMMUMapPages ( pMapping->pBMHeap->pMMUHeap,
+ pMapping->DevVAddr,
+ SysCpuPAddrToSysPAddr (pMapping->CpuPAddr),
+ pMapping->uSize,
+ uFlags,
+ (IMG_HANDLE)pMapping);
+
+ *pDevVAddr = pMapping->DevVAddr;
+ break;
+ }
+ case hm_env:
+ {
+ psDeviceNode->pfnMMUMapShadow ( pMapping->pBMHeap->pMMUHeap,
+ pMapping->DevVAddr,
+ pMapping->uSize,
+ pMapping->CpuVAddr,
+ pMapping->hOSMemHandle,
+ pDevVAddr,
+ uFlags,
+ (IMG_HANDLE)pMapping);
+ break;
+ }
+ case hm_wrapped_scatter:
+ case hm_wrapped_scatter_virtaddr:
+ {
+ psDeviceNode->pfnMMUMapScatter (pMapping->pBMHeap->pMMUHeap,
+ pMapping->DevVAddr,
+ pMapping->psSysAddr,
+ pMapping->uSize,
+ uFlags,
+ (IMG_HANDLE)pMapping);
+
+ *pDevVAddr = pMapping->DevVAddr;
+ break;
+ }
+ default:
+ PVR_DPF((PVR_DBG_ERROR,
+ "Illegal value %d for pMapping->eCpuMemoryOrigin",
+ pMapping->eCpuMemoryOrigin));
+ return IMG_FALSE;
+ }
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+ DisableHostAccess(pBMContext->psMMUContext);
+#endif
+
+ return IMG_TRUE;
+}
+
+static IMG_VOID
+DevMemoryFree (BM_MAPPING *pMapping)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+#ifdef PDUMP
+ IMG_UINT32 ui32PSize;
+#endif
+
+#ifdef PDUMP
+
+ if(pMapping->ui32Flags & PVRSRV_MEM_DUMMY)
+ {
+
+ ui32PSize = pMapping->pBMHeap->sDevArena.ui32DataPageSize;
+ }
+ else
+ {
+ ui32PSize = pMapping->uSize;
+ }
+
+ PDUMPFREEPAGES(pMapping->pBMHeap,
+ pMapping->DevVAddr,
+ ui32PSize,
+ pMapping->pBMHeap->sDevArena.ui32DataPageSize,
+ (IMG_HANDLE)pMapping,
+ (pMapping->ui32Flags & PVRSRV_MEM_INTERLEAVED) ? IMG_TRUE : IMG_FALSE);
+#endif
+
+ psDeviceNode = pMapping->pBMHeap->pBMContext->psDeviceNode;
+
+ psDeviceNode->pfnMMUFree (pMapping->pBMHeap->pMMUHeap, pMapping->DevVAddr, IMG_CAST_TO_DEVVADDR_UINT(pMapping->uSize));
+}
+
+static IMG_BOOL
+BM_ImportMemory (IMG_VOID *pH,
+ IMG_SIZE_T uRequestSize,
+ IMG_SIZE_T *pActualSize,
+ BM_MAPPING **ppsMapping,
+ IMG_UINT32 uFlags,
+ IMG_UINTPTR_T *pBase)
+{
+ BM_MAPPING *pMapping;
+ BM_HEAP *pBMHeap = pH;
+ BM_CONTEXT *pBMContext = pBMHeap->pBMContext;
+ IMG_BOOL bResult;
+ IMG_SIZE_T uSize;
+ IMG_SIZE_T uPSize;
+ IMG_UINT32 uDevVAddrAlignment = 0;
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "BM_ImportMemory (pBMContext=0x%x, uRequestSize=0x%x, uFlags=0x%x, uAlign=0x%x)",
+ (IMG_UINTPTR_T)pBMContext, uRequestSize, uFlags, uDevVAddrAlignment));
+
+ PVR_ASSERT (ppsMapping != IMG_NULL);
+ PVR_ASSERT (pBMContext != IMG_NULL);
+
+ if (ppsMapping == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_ImportMemory: invalid parameter"));
+ goto fail_exit;
+ }
+
+ uSize = HOST_PAGEALIGN (uRequestSize);
+ PVR_ASSERT (uSize >= uRequestSize);
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof (BM_MAPPING),
+ (IMG_PVOID *)&pMapping, IMG_NULL,
+ "Buffer Manager Mapping") != PVRSRV_OK)
+ {
+ PVR_DPF ((PVR_DBG_ERROR, "BM_ImportMemory: failed BM_MAPPING alloc"));
+ goto fail_exit;
+ }
+
+ pMapping->hOSMemHandle = 0;
+ pMapping->CpuVAddr = 0;
+ pMapping->DevVAddr.uiAddr = 0;
+ pMapping->CpuPAddr.uiAddr = 0;
+ pMapping->uSize = uSize;
+ pMapping->pBMHeap = pBMHeap;
+ pMapping->ui32Flags = uFlags;
+ pMapping->psDeviceNode = pBMContext->psDeviceNode;
+ pMapping->pBMContext = pBMContext;
+
+ if (pActualSize)
+ {
+ *pActualSize = uSize;
+ }
+
+
+ if(pMapping->ui32Flags & PVRSRV_MEM_DUMMY)
+ {
+ uPSize = pBMHeap->sDevArena.ui32DataPageSize;
+ }
+ else
+ {
+ uPSize = pMapping->uSize;
+ }
+
+
+
+ if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG)
+ {
+ IMG_UINT32 ui32Attribs = pBMHeap->ui32Attribs;
+
+
+ if (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)
+ {
+ ui32Attribs &= ~PVRSRV_HAP_CACHETYPE_MASK;
+ ui32Attribs |= (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK);
+ }
+
+
+ if (OSAllocPages(ui32Attribs,
+ uPSize,
+ pBMHeap->sDevArena.ui32DataPageSize,
+ (IMG_VOID **)&pMapping->CpuVAddr,
+ &pMapping->hOSMemHandle) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "BM_ImportMemory: OSAllocPages(0x%x) failed",
+ uPSize));
+ goto fail_mapping_alloc;
+ }
+
+
+ pMapping->eCpuMemoryOrigin = hm_env;
+ }
+ else if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG)
+ {
+ IMG_SYS_PHYADDR sSysPAddr;
+ IMG_UINT32 ui32Attribs = pBMHeap->ui32Attribs;
+
+
+ PVR_ASSERT(pBMHeap->pLocalDevMemArena != IMG_NULL);
+
+
+ if (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)
+ {
+ ui32Attribs &= ~PVRSRV_HAP_CACHETYPE_MASK;
+ ui32Attribs |= (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK);
+ }
+
+ if (!RA_Alloc (pBMHeap->pLocalDevMemArena,
+ uPSize,
+ IMG_NULL,
+ IMG_NULL,
+ 0,
+ pBMHeap->sDevArena.ui32DataPageSize,
+ 0,
+ (IMG_UINTPTR_T *)&sSysPAddr.uiAddr))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_ImportMemory: RA_Alloc(0x%x) FAILED", uPSize));
+ goto fail_mapping_alloc;
+ }
+
+
+ pMapping->CpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+ if(OSReservePhys(pMapping->CpuPAddr,
+ uPSize,
+ ui32Attribs,
+ &pMapping->CpuVAddr,
+ &pMapping->hOSMemHandle) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_ImportMemory: OSReservePhys failed"));
+ goto fail_dev_mem_alloc;
+ }
+
+
+ pMapping->eCpuMemoryOrigin = hm_contiguous;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_ImportMemory: Invalid backing store type"));
+ goto fail_mapping_alloc;
+ }
+
+
+ bResult = DevMemoryAlloc (pBMContext,
+ pMapping,
+ IMG_NULL,
+ uFlags,
+ uDevVAddrAlignment,
+ &pMapping->DevVAddr);
+ if (!bResult)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "BM_ImportMemory: DevMemoryAlloc(0x%x) failed",
+ pMapping->uSize));
+ goto fail_dev_mem_alloc;
+ }
+
+
+
+ PVR_ASSERT (uDevVAddrAlignment>1?(pMapping->DevVAddr.uiAddr%uDevVAddrAlignment)==0:1);
+
+ *pBase = pMapping->DevVAddr.uiAddr;
+ *ppsMapping = pMapping;
+
+ PVR_DPF ((PVR_DBG_MESSAGE, "BM_ImportMemory: IMG_TRUE"));
+ return IMG_TRUE;
+
+fail_dev_mem_alloc:
+ if (pMapping && (pMapping->CpuVAddr || pMapping->hOSMemHandle))
+ {
+
+ if(pMapping->ui32Flags & PVRSRV_MEM_INTERLEAVED)
+ {
+ pMapping->uSize /= 2;
+ }
+
+ if(pMapping->ui32Flags & PVRSRV_MEM_DUMMY)
+ {
+ uPSize = pBMHeap->sDevArena.ui32DataPageSize;
+ }
+ else
+ {
+ uPSize = pMapping->uSize;
+ }
+
+ if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG)
+ {
+ OSFreePages(pBMHeap->ui32Attribs,
+ uPSize,
+ (IMG_VOID *)pMapping->CpuVAddr,
+ pMapping->hOSMemHandle);
+ }
+ else
+ {
+ IMG_SYS_PHYADDR sSysPAddr;
+
+ if(pMapping->CpuVAddr)
+ {
+ OSUnReservePhys(pMapping->CpuVAddr,
+ uPSize,
+ pBMHeap->ui32Attribs,
+ pMapping->hOSMemHandle);
+ }
+ sSysPAddr = SysCpuPAddrToSysPAddr(pMapping->CpuPAddr);
+ RA_Free (pBMHeap->pLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
+ }
+ }
+fail_mapping_alloc:
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), pMapping, IMG_NULL);
+
+fail_exit:
+ return IMG_FALSE;
+}
+
+
+static IMG_VOID
+BM_FreeMemory (IMG_VOID *h, IMG_UINTPTR_T _base, BM_MAPPING *psMapping)
+{
+ BM_HEAP *pBMHeap = h;
+ IMG_SIZE_T uPSize;
+
+ PVR_UNREFERENCED_PARAMETER (_base);
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "BM_FreeMemory (h=0x%x, base=0x%x, psMapping=0x%x)",
+ (IMG_UINTPTR_T)h, _base, (IMG_UINTPTR_T)psMapping));
+
+ PVR_ASSERT (psMapping != IMG_NULL);
+
+ if (psMapping == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_FreeMemory: invalid parameter"));
+ return;
+ }
+
+ DevMemoryFree (psMapping);
+
+
+ if((psMapping->ui32Flags & PVRSRV_MEM_INTERLEAVED) != 0)
+ {
+ psMapping->uSize /= 2;
+ }
+
+ if(psMapping->ui32Flags & PVRSRV_MEM_DUMMY)
+ {
+ uPSize = psMapping->pBMHeap->sDevArena.ui32DataPageSize;
+ }
+ else
+ {
+ uPSize = psMapping->uSize;
+ }
+
+ if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG)
+ {
+ OSFreePages(pBMHeap->ui32Attribs,
+ uPSize,
+ (IMG_VOID *) psMapping->CpuVAddr,
+ psMapping->hOSMemHandle);
+ }
+ else if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG)
+ {
+ IMG_SYS_PHYADDR sSysPAddr;
+
+ OSUnReservePhys(psMapping->CpuVAddr, uPSize, pBMHeap->ui32Attribs, psMapping->hOSMemHandle);
+
+ sSysPAddr = SysCpuPAddrToSysPAddr(psMapping->CpuPAddr);
+
+ RA_Free (pBMHeap->pLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "BM_FreeMemory: Invalid backing store type"));
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), psMapping, IMG_NULL);
+
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "..BM_FreeMemory (h=0x%x, base=0x%x)",
+ (IMG_UINTPTR_T)h, _base));
+}
+
+IMG_VOID BM_GetPhysPageAddr(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_DEV_VIRTADDR sDevVPageAddr,
+ IMG_DEV_PHYADDR *psDevPAddr)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "BM_GetPhysPageAddr"));
+
+ PVR_ASSERT (psMemInfo && psDevPAddr)
+
+
+ PVR_ASSERT((sDevVPageAddr.uiAddr & 0xFFF) == 0);
+
+ psDeviceNode = ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->pBMContext->psDeviceNode;
+
+ *psDevPAddr = psDeviceNode->pfnMMUGetPhysPageAddr(((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->pMMUHeap,
+ sDevVPageAddr);
+}
+
+
+MMU_CONTEXT* BM_GetMMUContext(IMG_HANDLE hDevMemHeap)
+{
+ BM_HEAP *pBMHeap = (BM_HEAP*)hDevMemHeap;
+
+ PVR_DPF((PVR_DBG_VERBOSE, "BM_GetMMUContext"));
+
+ return pBMHeap->pBMContext->psMMUContext;
+}
+
+MMU_CONTEXT* BM_GetMMUContextFromMemContext(IMG_HANDLE hDevMemContext)
+{
+ BM_CONTEXT *pBMContext = (BM_CONTEXT*)hDevMemContext;
+
+ PVR_DPF ((PVR_DBG_VERBOSE, "BM_GetMMUContextFromMemContext"));
+
+ return pBMContext->psMMUContext;
+}
+
+IMG_HANDLE BM_GetMMUHeap(IMG_HANDLE hDevMemHeap)
+{
+ PVR_DPF((PVR_DBG_VERBOSE, "BM_GetMMUHeap"));
+
+ return (IMG_HANDLE)((BM_HEAP*)hDevMemHeap)->pMMUHeap;
+}
+
+
+PVRSRV_DEVICE_NODE* BM_GetDeviceNode(IMG_HANDLE hDevMemContext)
+{
+ PVR_DPF((PVR_DBG_VERBOSE, "BM_GetDeviceNode"));
+
+ return ((BM_CONTEXT*)hDevMemContext)->psDeviceNode;
+}
+
+
+IMG_HANDLE BM_GetMappingHandle(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+ PVR_DPF((PVR_DBG_VERBOSE, "BM_GetMappingHandle"));
+
+ return ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->hOSMemHandle;
+}
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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 "services_headers.h"
+#include "buffer_manager.h"
+#include "kernelbuffer.h"
+#include "kerneldisplay.h"
+#include "pvr_bridge_km.h"
+#include "pdump_km.h"
+#include "deviceid.h"
+
+#include "lists.h"
+#include "pvr_trace_cmd.h"
+
+PVRSRV_ERROR AllocateDeviceID(SYS_DATA *psSysData, IMG_UINT32 *pui32DevID);
+PVRSRV_ERROR FreeDeviceID(SYS_DATA *psSysData, IMG_UINT32 ui32DevID);
+
+#if defined(SUPPORT_MISR_IN_THREAD)
+void OSVSyncMISR(IMG_HANDLE, IMG_BOOL);
+#endif
+
+#if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS)
+IMG_VOID PVRSRVFreeCommandCompletePacketKM(IMG_HANDLE hCmdCookie,
+ IMG_BOOL bScheduleMISR);
+#endif
+typedef struct PVRSRV_DC_SRV2DISP_KMJTABLE_TAG *PPVRSRV_DC_SRV2DISP_KMJTABLE;
+
+typedef struct PVRSRV_DC_BUFFER_TAG
+{
+
+ PVRSRV_DEVICECLASS_BUFFER sDeviceClassBuffer;
+
+ struct PVRSRV_DISPLAYCLASS_INFO_TAG *psDCInfo;
+ struct PVRSRV_DC_SWAPCHAIN_TAG *psSwapChain;
+} PVRSRV_DC_BUFFER;
+
+typedef struct PVRSRV_DC_SWAPCHAIN_TAG
+{
+ IMG_HANDLE hExtSwapChain;
+ IMG_UINT32 ui32SwapChainID;
+ IMG_UINT32 ui32RefCount;
+ IMG_UINT32 ui32Flags;
+ PVRSRV_QUEUE_INFO *psQueue;
+ PVRSRV_DC_BUFFER asBuffer[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
+ IMG_UINT32 ui32BufferCount;
+ PVRSRV_DC_BUFFER *psLastFlipBuffer;
+ IMG_UINT32 ui32MinSwapInterval;
+ IMG_UINT32 ui32MaxSwapInterval;
+ struct PVRSRV_DISPLAYCLASS_INFO_TAG *psDCInfo;
+ struct PVRSRV_DC_SWAPCHAIN_TAG *psNext;
+} PVRSRV_DC_SWAPCHAIN;
+
+
+typedef struct PVRSRV_DC_SWAPCHAIN_REF_TAG
+{
+ struct PVRSRV_DC_SWAPCHAIN_TAG *psSwapChain;
+ IMG_HANDLE hResItem;
+} PVRSRV_DC_SWAPCHAIN_REF;
+
+
+typedef struct PVRSRV_DISPLAYCLASS_INFO_TAG
+{
+ IMG_UINT32 ui32RefCount;
+ IMG_UINT32 ui32DeviceID;
+ IMG_HANDLE hExtDevice;
+ PPVRSRV_DC_SRV2DISP_KMJTABLE psFuncTable;
+ IMG_HANDLE hDevMemContext;
+ PVRSRV_DC_BUFFER sSystemBuffer;
+ struct PVRSRV_DC_SWAPCHAIN_TAG *psDCSwapChainShared;
+} PVRSRV_DISPLAYCLASS_INFO;
+
+
+typedef struct PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO_TAG
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PRESMAN_ITEM hResItem;
+} PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO;
+
+
+typedef struct PVRSRV_BC_SRV2BUFFER_KMJTABLE_TAG *PPVRSRV_BC_SRV2BUFFER_KMJTABLE;
+
+typedef struct PVRSRV_BC_BUFFER_TAG
+{
+
+ PVRSRV_DEVICECLASS_BUFFER sDeviceClassBuffer;
+
+ struct PVRSRV_BUFFERCLASS_INFO_TAG *psBCInfo;
+} PVRSRV_BC_BUFFER;
+
+
+typedef struct PVRSRV_BUFFERCLASS_INFO_TAG
+{
+ IMG_UINT32 ui32RefCount;
+ IMG_UINT32 ui32DeviceID;
+ IMG_HANDLE hExtDevice;
+ PPVRSRV_BC_SRV2BUFFER_KMJTABLE psFuncTable;
+ IMG_HANDLE hDevMemContext;
+
+ IMG_UINT32 ui32BufferCount;
+ PVRSRV_BC_BUFFER *psBuffer;
+
+} PVRSRV_BUFFERCLASS_INFO;
+
+
+typedef struct PVRSRV_BUFFERCLASS_PERCONTEXT_INFO_TAG
+{
+ PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+ IMG_HANDLE hResItem;
+} PVRSRV_BUFFERCLASS_PERCONTEXT_INFO;
+
+
+static PVRSRV_DISPLAYCLASS_INFO* DCDeviceHandleToDCInfo (IMG_HANDLE hDeviceKM)
+{
+ PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
+
+ psDCPerContextInfo = (PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *)hDeviceKM;
+
+ return psDCPerContextInfo->psDCInfo;
+}
+
+
+static PVRSRV_BUFFERCLASS_INFO* BCDeviceHandleToBCInfo (IMG_HANDLE hDeviceKM)
+{
+ PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo;
+
+ psBCPerContextInfo = (PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *)hDeviceKM;
+
+ return psBCPerContextInfo->psBCInfo;
+}
+
+static IMG_VOID PVRSRVEnumerateDCKM_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
+{
+ IMG_UINT *pui32DevCount;
+ IMG_UINT32 **ppui32DevID;
+ PVRSRV_DEVICE_CLASS peDeviceClass;
+
+ pui32DevCount = va_arg(va, IMG_UINT*);
+ ppui32DevID = va_arg(va, IMG_UINT32**);
+ peDeviceClass = va_arg(va, PVRSRV_DEVICE_CLASS);
+
+ if ((psDeviceNode->sDevId.eDeviceClass == peDeviceClass)
+ && (psDeviceNode->sDevId.eDeviceType == PVRSRV_DEVICE_TYPE_EXT))
+ {
+ (*pui32DevCount)++;
+ if(*ppui32DevID)
+ {
+ *(*ppui32DevID)++ = psDeviceNode->sDevId.ui32DeviceIndex;
+ }
+ }
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVEnumerateDCKM (PVRSRV_DEVICE_CLASS DeviceClass,
+ IMG_UINT32 *pui32DevCount,
+ IMG_UINT32 *pui32DevID )
+{
+
+ IMG_UINT ui32DevCount = 0;
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+
+
+ List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList,
+ &PVRSRVEnumerateDCKM_ForEachVaCb,
+ &ui32DevCount,
+ &pui32DevID,
+ DeviceClass);
+
+ if(pui32DevCount)
+ {
+ *pui32DevCount = ui32DevCount;
+ }
+ else if(pui32DevID == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumerateDCKM: Invalid parameters"));
+ return (PVRSRV_ERROR_INVALID_PARAMS);
+ }
+
+ return PVRSRV_OK;
+}
+
+
+static
+PVRSRV_ERROR PVRSRVRegisterDCDeviceKM (PVRSRV_DC_SRV2DISP_KMJTABLE *psFuncTable,
+ IMG_UINT32 *pui32DeviceID)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo = IMG_NULL;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ SYS_DATA *psSysData;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SysAcquireData(&psSysData);
+
+
+
+
+
+ if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(*psDCInfo),
+ (IMG_VOID **)&psDCInfo, IMG_NULL,
+ "Display Class Info") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDCDeviceKM: Failed psDCInfo alloc"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ OSMemSet (psDCInfo, 0, sizeof(*psDCInfo));
+
+
+ if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE),
+ (IMG_VOID **)&psDCInfo->psFuncTable, IMG_NULL,
+ "Function table for SRVKM->DISPLAY") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDCDeviceKM: Failed psFuncTable alloc"));
+ goto ErrorExit;
+ }
+ OSMemSet (psDCInfo->psFuncTable, 0, sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE));
+
+
+ *psDCInfo->psFuncTable = *psFuncTable;
+
+
+ if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DEVICE_NODE),
+ (IMG_VOID **)&psDeviceNode, IMG_NULL,
+ "Device Node") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDCDeviceKM: Failed psDeviceNode alloc"));
+ goto ErrorExit;
+ }
+ OSMemSet (psDeviceNode, 0, sizeof(PVRSRV_DEVICE_NODE));
+
+ psDeviceNode->pvDevice = (IMG_VOID*)psDCInfo;
+ psDeviceNode->ui32pvDeviceSize = sizeof(*psDCInfo);
+ psDeviceNode->ui32RefCount = 1;
+ psDeviceNode->sDevId.eDeviceType = PVRSRV_DEVICE_TYPE_EXT;
+ psDeviceNode->sDevId.eDeviceClass = PVRSRV_DEVICE_CLASS_DISPLAY;
+ psDeviceNode->psSysData = psSysData;
+
+
+ if (AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed to allocate Device ID"));
+ goto ErrorExit;
+ }
+ psDCInfo->ui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
+ if (pui32DeviceID)
+ {
+ *pui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
+ }
+
+
+ SysRegisterExternalDevice(psDeviceNode);
+
+
+ List_PVRSRV_DEVICE_NODE_Insert(&psSysData->psDeviceNodeList, psDeviceNode);
+
+ return PVRSRV_OK;
+
+ErrorExit:
+
+ if(psDCInfo->psFuncTable)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE), psDCInfo->psFuncTable, IMG_NULL);
+ psDCInfo->psFuncTable = IMG_NULL;
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DISPLAYCLASS_INFO), psDCInfo, IMG_NULL);
+
+
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+}
+
+static PVRSRV_ERROR PVRSRVRemoveDCDeviceKM(IMG_UINT32 ui32DevIndex)
+{
+ SYS_DATA *psSysData;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+
+ SysAcquireData(&psSysData);
+
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE*)
+ List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+ &MatchDeviceKM_AnyVaCb,
+ ui32DevIndex,
+ IMG_FALSE,
+ PVRSRV_DEVICE_CLASS_DISPLAY);
+ if (!psDeviceNode)
+ {
+
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveDCDeviceKM: requested device %d not present", ui32DevIndex));
+ return PVRSRV_ERROR_NO_DEVICENODE_FOUND;
+ }
+
+
+ psDCInfo = (PVRSRV_DISPLAYCLASS_INFO*)psDeviceNode->pvDevice;
+
+
+
+
+ if(psDCInfo->ui32RefCount == 0)
+ {
+
+
+ List_PVRSRV_DEVICE_NODE_Remove(psDeviceNode);
+
+
+ SysRemoveExternalDevice(psDeviceNode);
+
+
+
+
+ PVR_ASSERT(psDCInfo->ui32RefCount == 0);
+ (IMG_VOID)FreeDeviceID(psSysData, ui32DevIndex);
+ (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE), psDCInfo->psFuncTable, IMG_NULL);
+ psDCInfo->psFuncTable = IMG_NULL;
+ (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DISPLAYCLASS_INFO), psDCInfo, IMG_NULL);
+
+ (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL);
+
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveDCDeviceKM: failed as %d Services DC API connections are still open", psDCInfo->ui32RefCount));
+ return PVRSRV_ERROR_UNABLE_TO_REMOVE_DEVICE;
+ }
+
+ return PVRSRV_OK;
+}
+
+
+static
+PVRSRV_ERROR PVRSRVRegisterBCDeviceKM (PVRSRV_BC_SRV2BUFFER_KMJTABLE *psFuncTable,
+ IMG_UINT32 *pui32DeviceID)
+{
+ PVRSRV_BUFFERCLASS_INFO *psBCInfo = IMG_NULL;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ SYS_DATA *psSysData;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SysAcquireData(&psSysData);
+
+
+
+
+
+ if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(*psBCInfo),
+ (IMG_VOID **)&psBCInfo, IMG_NULL,
+ "Buffer Class Info") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed psBCInfo alloc"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ OSMemSet (psBCInfo, 0, sizeof(*psBCInfo));
+
+
+ if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE),
+ (IMG_VOID **)&psBCInfo->psFuncTable, IMG_NULL,
+ "Function table for SRVKM->BUFFER") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed psFuncTable alloc"));
+ goto ErrorExit;
+ }
+ OSMemSet (psBCInfo->psFuncTable, 0, sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE));
+
+
+ *psBCInfo->psFuncTable = *psFuncTable;
+
+
+ if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DEVICE_NODE),
+ (IMG_VOID **)&psDeviceNode, IMG_NULL,
+ "Device Node") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed psDeviceNode alloc"));
+ goto ErrorExit;
+ }
+ OSMemSet (psDeviceNode, 0, sizeof(PVRSRV_DEVICE_NODE));
+
+ psDeviceNode->pvDevice = (IMG_VOID*)psBCInfo;
+ psDeviceNode->ui32pvDeviceSize = sizeof(*psBCInfo);
+ psDeviceNode->ui32RefCount = 1;
+ psDeviceNode->sDevId.eDeviceType = PVRSRV_DEVICE_TYPE_EXT;
+ psDeviceNode->sDevId.eDeviceClass = PVRSRV_DEVICE_CLASS_BUFFER;
+ psDeviceNode->psSysData = psSysData;
+
+
+ if (AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed to allocate Device ID"));
+ goto ErrorExit;
+ }
+ psBCInfo->ui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
+ if (pui32DeviceID)
+ {
+ *pui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
+ }
+
+
+ List_PVRSRV_DEVICE_NODE_Insert(&psSysData->psDeviceNodeList, psDeviceNode);
+
+ return PVRSRV_OK;
+
+ErrorExit:
+
+ if(psBCInfo->psFuncTable)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PPVRSRV_BC_SRV2BUFFER_KMJTABLE), psBCInfo->psFuncTable, IMG_NULL);
+ psBCInfo->psFuncTable = IMG_NULL;
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BUFFERCLASS_INFO), psBCInfo, IMG_NULL);
+
+
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+}
+
+
+static PVRSRV_ERROR PVRSRVRemoveBCDeviceKM(IMG_UINT32 ui32DevIndex)
+{
+ SYS_DATA *psSysData;
+ PVRSRV_DEVICE_NODE *psDevNode;
+ PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+
+ SysAcquireData(&psSysData);
+
+
+ psDevNode = (PVRSRV_DEVICE_NODE*)
+ List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+ &MatchDeviceKM_AnyVaCb,
+ ui32DevIndex,
+ IMG_FALSE,
+ PVRSRV_DEVICE_CLASS_BUFFER);
+
+ if (!psDevNode)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveBCDeviceKM: requested device %d not present", ui32DevIndex));
+ return PVRSRV_ERROR_NO_DEVICENODE_FOUND;
+ }
+
+
+
+ psBCInfo = (PVRSRV_BUFFERCLASS_INFO*)psDevNode->pvDevice;
+
+
+
+
+ if(psBCInfo->ui32RefCount == 0)
+ {
+
+
+ List_PVRSRV_DEVICE_NODE_Remove(psDevNode);
+
+
+
+
+ (IMG_VOID)FreeDeviceID(psSysData, ui32DevIndex);
+
+
+ (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE), psBCInfo->psFuncTable, IMG_NULL);
+ psBCInfo->psFuncTable = IMG_NULL;
+ (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BUFFERCLASS_INFO), psBCInfo, IMG_NULL);
+
+ (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DEVICE_NODE), psDevNode, IMG_NULL);
+
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveBCDeviceKM: failed as %d Services BC API connections are still open", psBCInfo->ui32RefCount));
+ return PVRSRV_ERROR_UNABLE_TO_REMOVE_DEVICE;
+ }
+
+ return PVRSRV_OK;
+}
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVCloseDCDeviceKM (IMG_HANDLE hDeviceKM,
+ IMG_BOOL bResManCallback)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
+
+ PVR_UNREFERENCED_PARAMETER(bResManCallback);
+
+ psDCPerContextInfo = (PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *)hDeviceKM;
+
+
+ eError = ResManFreeResByPtr(psDCPerContextInfo->hResItem);
+
+ return eError;
+}
+
+
+static PVRSRV_ERROR CloseDCDeviceCallBack(IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param)
+{
+ PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ psDCPerContextInfo = (PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *)pvParam;
+ psDCInfo = psDCPerContextInfo->psDCInfo;
+
+ psDCInfo->ui32RefCount--;
+ if(psDCInfo->ui32RefCount == 0)
+ {
+
+ psDCInfo->psFuncTable->pfnCloseDCDevice(psDCInfo->hExtDevice);
+
+ if (--psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0)
+ {
+ PVRSRVFreeSyncInfoKM(psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo);
+ }
+
+ psDCInfo->hDevMemContext = IMG_NULL;
+ psDCInfo->hExtDevice = IMG_NULL;
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO), psDCPerContextInfo, IMG_NULL);
+
+
+ return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVOpenDCDeviceKM (PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_UINT32 ui32DeviceID,
+ IMG_HANDLE hDevCookie,
+ IMG_HANDLE *phDeviceKM)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ SYS_DATA *psSysData;
+ PVRSRV_ERROR eError;
+
+ if(!phDeviceKM || !hDevCookie)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Invalid params"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ SysAcquireData(&psSysData);
+
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE*)
+ List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+ &MatchDeviceKM_AnyVaCb,
+ ui32DeviceID,
+ IMG_FALSE,
+ PVRSRV_DEVICE_CLASS_DISPLAY);
+ if (!psDeviceNode)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: no devnode matching index %d", ui32DeviceID));
+ return PVRSRV_ERROR_NO_DEVICENODE_FOUND;
+ }
+ psDCInfo = (PVRSRV_DISPLAYCLASS_INFO*)psDeviceNode->pvDevice;
+
+
+
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(*psDCPerContextInfo),
+ (IMG_VOID **)&psDCPerContextInfo, IMG_NULL,
+ "Display Class per Context Info") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed psDCPerContextInfo alloc"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ OSMemSet(psDCPerContextInfo, 0, sizeof(*psDCPerContextInfo));
+
+ if(psDCInfo->ui32RefCount++ == 0)
+ {
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
+
+
+ psDCInfo->hDevMemContext = (IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext;
+
+
+ eError = PVRSRVAllocSyncInfoKM(IMG_NULL,
+ (IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext,
+ &psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed sync info alloc"));
+ psDCInfo->ui32RefCount--;
+ return eError;
+ }
+
+
+ eError = psDCInfo->psFuncTable->pfnOpenDCDevice(ui32DeviceID,
+ &psDCInfo->hExtDevice,
+ (PVRSRV_SYNC_DATA*)psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed to open external DC device"));
+ psDCInfo->ui32RefCount--;
+ PVRSRVFreeSyncInfoKM(psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo);
+ return eError;
+ }
+
+ psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount++;
+ }
+
+ psDCPerContextInfo->psDCInfo = psDCInfo;
+ psDCPerContextInfo->hResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_DISPLAYCLASS_DEVICE,
+ psDCPerContextInfo,
+ 0,
+ &CloseDCDeviceCallBack);
+
+
+ *phDeviceKM = (IMG_HANDLE)psDCPerContextInfo;
+
+ return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVEnumDCFormatsKM (IMG_HANDLE hDeviceKM,
+ IMG_UINT32 *pui32Count,
+ DISPLAY_FORMAT *psFormat)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+
+ if(!hDeviceKM || !pui32Count || !psFormat)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumDCFormatsKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+
+ return psDCInfo->psFuncTable->pfnEnumDCFormats(psDCInfo->hExtDevice, pui32Count, psFormat);
+}
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVEnumDCDimsKM (IMG_HANDLE hDeviceKM,
+ DISPLAY_FORMAT *psFormat,
+ IMG_UINT32 *pui32Count,
+ DISPLAY_DIMS *psDim)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+
+ if(!hDeviceKM || !pui32Count || !psFormat)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumDCDimsKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+
+ return psDCInfo->psFuncTable->pfnEnumDCDims(psDCInfo->hExtDevice, psFormat, pui32Count, psDim);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVGetDCSystemBufferKM (IMG_HANDLE hDeviceKM,
+ IMG_HANDLE *phBuffer)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ IMG_HANDLE hExtBuffer;
+
+ if(!hDeviceKM || !phBuffer)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetDCSystemBufferKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+
+ eError = psDCInfo->psFuncTable->pfnGetDCSystemBuffer(psDCInfo->hExtDevice, &hExtBuffer);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetDCSystemBufferKM: Failed to get valid buffer handle from external driver"));
+ return eError;
+ }
+
+
+ psDCInfo->sSystemBuffer.sDeviceClassBuffer.pfnGetBufferAddr = psDCInfo->psFuncTable->pfnGetBufferAddr;
+ psDCInfo->sSystemBuffer.sDeviceClassBuffer.hDevMemContext = psDCInfo->hDevMemContext;
+ psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtDevice = psDCInfo->hExtDevice;
+ psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtBuffer = hExtBuffer;
+
+ psDCInfo->sSystemBuffer.psDCInfo = psDCInfo;
+
+
+ *phBuffer = (IMG_HANDLE)&(psDCInfo->sSystemBuffer);
+
+ return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVGetDCInfoKM (IMG_HANDLE hDeviceKM,
+ DISPLAY_INFO *psDisplayInfo)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_ERROR eError;
+
+ if(!hDeviceKM || !psDisplayInfo)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetDCInfoKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+
+ eError = psDCInfo->psFuncTable->pfnGetDCInfo(psDCInfo->hExtDevice, psDisplayInfo);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ if (psDisplayInfo->ui32MaxSwapChainBuffers > PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS)
+ {
+ psDisplayInfo->ui32MaxSwapChainBuffers = PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS;
+ }
+
+ return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVDestroyDCSwapChainKM(IMG_HANDLE hSwapChainRef)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef;
+
+ if(!hSwapChainRef)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVDestroyDCSwapChainKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psSwapChainRef = hSwapChainRef;
+
+ eError = ResManFreeResByPtr(psSwapChainRef->hResItem);
+
+ return eError;
+}
+
+
+static PVRSRV_ERROR DestroyDCSwapChain(PVRSRV_DC_SWAPCHAIN *psSwapChain)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo = psSwapChain->psDCInfo;
+ IMG_UINT32 i;
+
+
+
+ if( psDCInfo->psDCSwapChainShared )
+ {
+ if( psDCInfo->psDCSwapChainShared == psSwapChain )
+ {
+ psDCInfo->psDCSwapChainShared = psSwapChain->psNext;
+ }
+ else
+ {
+ PVRSRV_DC_SWAPCHAIN *psCurrentSwapChain;
+ psCurrentSwapChain = psDCInfo->psDCSwapChainShared;
+ while( psCurrentSwapChain->psNext )
+ {
+ if( psCurrentSwapChain->psNext != psSwapChain )
+ {
+ psCurrentSwapChain = psCurrentSwapChain->psNext;
+ continue;
+ }
+ psCurrentSwapChain->psNext = psSwapChain->psNext;
+ break;
+ }
+ }
+ }
+
+
+ PVRSRVDestroyCommandQueueKM(psSwapChain->psQueue);
+
+
+ eError = psDCInfo->psFuncTable->pfnDestroyDCSwapChain(psDCInfo->hExtDevice,
+ psSwapChain->hExtSwapChain);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DestroyDCSwapChainCallBack: Failed to destroy DC swap chain"));
+ return eError;
+ }
+
+
+ for(i=0; i<psSwapChain->ui32BufferCount; i++)
+ {
+ if(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo)
+ {
+ if (--psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0)
+ {
+ PVRSRVFreeSyncInfoKM(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo);
+ }
+ }
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN), psSwapChain, IMG_NULL);
+
+
+ return eError;
+}
+
+
+static PVRSRV_ERROR DestroyDCSwapChainRefCallBack(IMG_PVOID pvParam, IMG_UINT32 ui32Param)
+{
+ PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef = (PVRSRV_DC_SWAPCHAIN_REF *) pvParam;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ if(--psSwapChainRef->psSwapChain->ui32RefCount == 0)
+ {
+ eError = DestroyDCSwapChain(psSwapChainRef->psSwapChain);
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN_REF), psSwapChainRef, IMG_NULL);
+ return eError;
+}
+
+static PVRSRV_DC_SWAPCHAIN* PVRSRVFindSharedDCSwapChainKM(PVRSRV_DISPLAYCLASS_INFO *psDCInfo,
+ IMG_UINT32 ui32SwapChainID)
+{
+ PVRSRV_DC_SWAPCHAIN *psCurrentSwapChain;
+
+ for(psCurrentSwapChain = psDCInfo->psDCSwapChainShared;
+ psCurrentSwapChain;
+ psCurrentSwapChain = psCurrentSwapChain->psNext)
+ {
+ if(psCurrentSwapChain->ui32SwapChainID == ui32SwapChainID)
+ return psCurrentSwapChain;
+ }
+ return IMG_NULL;
+}
+
+static PVRSRV_ERROR PVRSRVCreateDCSwapChainRefKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ PVRSRV_DC_SWAPCHAIN *psSwapChain,
+ PVRSRV_DC_SWAPCHAIN_REF **ppsSwapChainRef)
+{
+ PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef = IMG_NULL;
+
+
+ if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DC_SWAPCHAIN_REF),
+ (IMG_VOID **)&psSwapChainRef, IMG_NULL,
+ "Display Class Swapchain Reference") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainRefKM: Failed psSwapChainRef alloc"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ OSMemSet (psSwapChainRef, 0, sizeof(PVRSRV_DC_SWAPCHAIN_REF));
+
+
+ psSwapChain->ui32RefCount++;
+
+
+ psSwapChainRef->psSwapChain = psSwapChain;
+ psSwapChainRef->hResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_DISPLAYCLASS_SWAPCHAIN_REF,
+ psSwapChainRef,
+ 0,
+ &DestroyDCSwapChainRefCallBack);
+ *ppsSwapChainRef = psSwapChainRef;
+
+ return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVCreateDCSwapChainKM (PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDeviceKM,
+ IMG_UINT32 ui32Flags,
+ DISPLAY_SURF_ATTRIBUTES *psDstSurfAttrib,
+ DISPLAY_SURF_ATTRIBUTES *psSrcSurfAttrib,
+ IMG_UINT32 ui32BufferCount,
+ IMG_UINT32 ui32OEMFlags,
+ IMG_HANDLE *phSwapChainRef,
+ IMG_UINT32 *pui32SwapChainID)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_DC_SWAPCHAIN *psSwapChain = IMG_NULL;
+ PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef = IMG_NULL;
+ PVRSRV_SYNC_DATA *apsSyncData[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
+ PVRSRV_QUEUE_INFO *psQueue = IMG_NULL;
+ PVRSRV_ERROR eError;
+ IMG_UINT32 i;
+ DISPLAY_INFO sDisplayInfo;
+
+
+ if(!hDeviceKM
+ || !psDstSurfAttrib
+ || !psSrcSurfAttrib
+ || !phSwapChainRef
+ || !pui32SwapChainID)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if (ui32BufferCount > PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Too many buffers"));
+ return PVRSRV_ERROR_TOOMANYBUFFERS;
+ }
+
+ if (ui32BufferCount < 2)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Too few buffers"));
+ return PVRSRV_ERROR_TOO_FEW_BUFFERS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+ if( ui32Flags & PVRSRV_CREATE_SWAPCHAIN_QUERY )
+ {
+
+ psSwapChain = PVRSRVFindSharedDCSwapChainKM(psDCInfo, *pui32SwapChainID );
+ if( psSwapChain )
+ {
+
+ eError = PVRSRVCreateDCSwapChainRefKM(psPerProc,
+ psSwapChain,
+ &psSwapChainRef);
+ if( eError != PVRSRV_OK )
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Couldn't create swap chain reference"));
+ return eError;
+ }
+
+ *phSwapChainRef = (IMG_HANDLE)psSwapChainRef;
+ return PVRSRV_OK;
+ }
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: No shared SwapChain found for query"));
+ return PVRSRV_ERROR_FLIP_CHAIN_EXISTS;
+ }
+
+
+ if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DC_SWAPCHAIN),
+ (IMG_VOID **)&psSwapChain, IMG_NULL,
+ "Display Class Swapchain") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed psSwapChain alloc"));
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto ErrorExit;
+ }
+ OSMemSet (psSwapChain, 0, sizeof(PVRSRV_DC_SWAPCHAIN));
+
+
+ eError = PVRSRVCreateCommandQueueKM(1024, &psQueue);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed to create CmdQueue"));
+ goto ErrorExit;
+ }
+
+
+ psSwapChain->psQueue = psQueue;
+
+
+ for(i=0; i<ui32BufferCount; i++)
+ {
+ eError = PVRSRVAllocSyncInfoKM(IMG_NULL,
+ psDCInfo->hDevMemContext,
+ &psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed to alloc syninfo for psSwapChain"));
+ goto ErrorExit;
+ }
+
+ psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount++;
+
+
+ psSwapChain->asBuffer[i].sDeviceClassBuffer.pfnGetBufferAddr = psDCInfo->psFuncTable->pfnGetBufferAddr;
+ psSwapChain->asBuffer[i].sDeviceClassBuffer.hDevMemContext = psDCInfo->hDevMemContext;
+ psSwapChain->asBuffer[i].sDeviceClassBuffer.hExtDevice = psDCInfo->hExtDevice;
+
+
+ psSwapChain->asBuffer[i].psDCInfo = psDCInfo;
+ psSwapChain->asBuffer[i].psSwapChain = psSwapChain;
+
+
+ apsSyncData[i] = (PVRSRV_SYNC_DATA*)psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM;
+ }
+
+ psSwapChain->ui32BufferCount = ui32BufferCount;
+ psSwapChain->psDCInfo = psDCInfo;
+
+#if defined(PDUMP)
+ PDUMPCOMMENT("Allocate DC swap chain (SwapChainID == %u, BufferCount == %u)",
+ *pui32SwapChainID,
+ ui32BufferCount);
+ PDUMPCOMMENT(" Src surface dimensions == %u x %u",
+ psSrcSurfAttrib->sDims.ui32Width,
+ psSrcSurfAttrib->sDims.ui32Height);
+ PDUMPCOMMENT(" Dst surface dimensions == %u x %u",
+ psDstSurfAttrib->sDims.ui32Width,
+ psDstSurfAttrib->sDims.ui32Height);
+#endif
+
+ eError = psDCInfo->psFuncTable->pfnGetDCInfo(psDCInfo->hExtDevice, &sDisplayInfo);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed to get DC info"));
+ return eError;
+ }
+
+ psSwapChain->ui32MinSwapInterval = sDisplayInfo.ui32MinSwapInterval;
+ psSwapChain->ui32MaxSwapInterval = sDisplayInfo.ui32MaxSwapInterval;
+
+
+ eError = psDCInfo->psFuncTable->pfnCreateDCSwapChain(psDCInfo->hExtDevice,
+ ui32Flags,
+ psDstSurfAttrib,
+ psSrcSurfAttrib,
+ ui32BufferCount,
+ apsSyncData,
+ ui32OEMFlags,
+ &psSwapChain->hExtSwapChain,
+ &psSwapChain->ui32SwapChainID);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed to create 3rd party SwapChain"));
+ PDUMPCOMMENT("Swapchain allocation failed.");
+ goto ErrorExit;
+ }
+
+
+ eError = PVRSRVCreateDCSwapChainRefKM(psPerProc,
+ psSwapChain,
+ &psSwapChainRef);
+ if( eError != PVRSRV_OK )
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Couldn't create swap chain reference"));
+ PDUMPCOMMENT("Swapchain allocation failed.");
+ goto ErrorExit;
+ }
+
+ psSwapChain->ui32RefCount = 1;
+ psSwapChain->ui32Flags = ui32Flags;
+
+
+ if( ui32Flags & PVRSRV_CREATE_SWAPCHAIN_SHARED )
+ {
+ if(! psDCInfo->psDCSwapChainShared )
+ {
+ psDCInfo->psDCSwapChainShared = psSwapChain;
+ }
+ else
+ {
+ PVRSRV_DC_SWAPCHAIN *psOldHead = psDCInfo->psDCSwapChainShared;
+ psDCInfo->psDCSwapChainShared = psSwapChain;
+ psSwapChain->psNext = psOldHead;
+ }
+ }
+
+
+ *pui32SwapChainID = psSwapChain->ui32SwapChainID;
+
+
+ *phSwapChainRef= (IMG_HANDLE)psSwapChainRef;
+
+ return eError;
+
+ErrorExit:
+
+ for(i=0; i<ui32BufferCount; i++)
+ {
+ if(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo)
+ {
+ if (--psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0)
+ {
+ PVRSRVFreeSyncInfoKM(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo);
+ }
+ }
+ }
+
+ if(psQueue)
+ {
+ PVRSRVDestroyCommandQueueKM(psQueue);
+ }
+
+ if(psSwapChain)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN), psSwapChain, IMG_NULL);
+
+ }
+
+ return eError;
+}
+
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetDCDstRectKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hSwapChainRef,
+ IMG_RECT *psRect)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_DC_SWAPCHAIN *psSwapChain;
+
+ if(!hDeviceKM || !hSwapChainRef)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSetDCDstRectKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+ psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain;
+
+ return psDCInfo->psFuncTable->pfnSetDCDstRect(psDCInfo->hExtDevice,
+ psSwapChain->hExtSwapChain,
+ psRect);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetDCSrcRectKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hSwapChainRef,
+ IMG_RECT *psRect)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_DC_SWAPCHAIN *psSwapChain;
+
+ if(!hDeviceKM || !hSwapChainRef)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSetDCSrcRectKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+ psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain;
+
+ return psDCInfo->psFuncTable->pfnSetDCSrcRect(psDCInfo->hExtDevice,
+ psSwapChain->hExtSwapChain,
+ psRect);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetDCDstColourKeyKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hSwapChainRef,
+ IMG_UINT32 ui32CKColour)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_DC_SWAPCHAIN *psSwapChain;
+
+ if(!hDeviceKM || !hSwapChainRef)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSetDCDstColourKeyKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+ psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain;
+
+ return psDCInfo->psFuncTable->pfnSetDCDstColourKey(psDCInfo->hExtDevice,
+ psSwapChain->hExtSwapChain,
+ ui32CKColour);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetDCSrcColourKeyKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hSwapChainRef,
+ IMG_UINT32 ui32CKColour)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_DC_SWAPCHAIN *psSwapChain;
+
+ if(!hDeviceKM || !hSwapChainRef)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSetDCSrcColourKeyKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+ psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain;
+
+ return psDCInfo->psFuncTable->pfnSetDCSrcColourKey(psDCInfo->hExtDevice,
+ psSwapChain->hExtSwapChain,
+ ui32CKColour);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVGetDCBuffersKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hSwapChainRef,
+ IMG_UINT32 *pui32BufferCount,
+ IMG_HANDLE *phBuffer)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_DC_SWAPCHAIN *psSwapChain;
+ IMG_HANDLE ahExtBuffer[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
+ PVRSRV_ERROR eError;
+ IMG_UINT32 i;
+
+ if(!hDeviceKM || !hSwapChainRef || !phBuffer)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetDCBuffersKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+ psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain;
+
+
+ eError = psDCInfo->psFuncTable->pfnGetDCBuffers(psDCInfo->hExtDevice,
+ psSwapChain->hExtSwapChain,
+ pui32BufferCount,
+ ahExtBuffer);
+
+ PVR_ASSERT(*pui32BufferCount <= PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS);
+
+
+
+
+ for(i=0; i<*pui32BufferCount; i++)
+ {
+ psSwapChain->asBuffer[i].sDeviceClassBuffer.hExtBuffer = ahExtBuffer[i];
+ phBuffer[i] = (IMG_HANDLE)&psSwapChain->asBuffer[i];
+ }
+
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSwapToDCBufferKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hBuffer,
+ IMG_UINT32 ui32SwapInterval,
+ IMG_HANDLE hPrivateTag,
+ IMG_UINT32 ui32ClipRectCount,
+ IMG_RECT *psClipRect,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_DC_BUFFER *psBuffer;
+ PVRSRV_QUEUE_INFO *psQueue;
+ DISPLAYCLASS_FLIP_COMMAND *psFlipCmd;
+ IMG_UINT32 i;
+ IMG_BOOL bAddReferenceToLast = IMG_TRUE;
+ IMG_UINT16 ui16SwapCommandID = DC_FLIP_COMMAND;
+ IMG_UINT32 ui32NumSrcSyncs = 1;
+ PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[2];
+ PVRSRV_COMMAND *psCommand;
+ struct pvr_trcmd_flpreq *fltrace;
+
+ if(!hDeviceKM || !hBuffer || !psClipRect)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+#if defined(SUPPORT_LMA)
+ eError = PVRSRVPowerLock(KERNEL_ID, IMG_FALSE);
+ if(eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+#endif
+
+ psBuffer = (PVRSRV_DC_BUFFER*)hBuffer;
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+
+ if(ui32SwapInterval < psBuffer->psSwapChain->ui32MinSwapInterval ||
+ ui32SwapInterval > psBuffer->psSwapChain->ui32MaxSwapInterval)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Invalid swap interval. Requested %u, Allowed range %u-%u",
+ ui32SwapInterval, psBuffer->psSwapChain->ui32MinSwapInterval, psBuffer->psSwapChain->ui32MaxSwapInterval));
+ return PVRSRV_ERROR_INVALID_SWAPINTERVAL;
+ }
+
+#if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS)
+
+ if(psDCInfo->psFuncTable->pfnQuerySwapCommandID != IMG_NULL)
+ {
+ psDCInfo->psFuncTable->pfnQuerySwapCommandID(psDCInfo->hExtDevice,
+ psBuffer->psSwapChain->hExtSwapChain,
+ psBuffer->sDeviceClassBuffer.hExtBuffer,
+ hPrivateTag,
+ &ui16SwapCommandID,
+ &bAddReferenceToLast);
+
+ }
+
+#endif
+
+
+ psQueue = psBuffer->psSwapChain->psQueue;
+
+
+ apsSrcSync[0] = psBuffer->sDeviceClassBuffer.psKernelSyncInfo;
+
+
+
+ if(bAddReferenceToLast && psBuffer->psSwapChain->psLastFlipBuffer &&
+ psBuffer != psBuffer->psSwapChain->psLastFlipBuffer)
+ {
+ apsSrcSync[1] = psBuffer->psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.psKernelSyncInfo;
+
+
+
+ ui32NumSrcSyncs++;
+ }
+
+
+ eError = PVRSRVInsertCommandKM (psQueue,
+ &psCommand,
+ psDCInfo->ui32DeviceID,
+ ui16SwapCommandID,
+ 0,
+ IMG_NULL,
+ ui32NumSrcSyncs,
+ apsSrcSync,
+ sizeof(DISPLAYCLASS_FLIP_COMMAND) + (sizeof(IMG_RECT) * ui32ClipRectCount));
+ fltrace = pvr_trcmd_reserve(PVR_TRCMD_FLPREQ, psPerProc->ui32PID,
+ psPerProc->name, sizeof(*fltrace));
+ pvr_trcmd_set_syn(&fltrace->src_syn[0], apsSrcSync[0]);
+ if (ui32NumSrcSyncs > 1)
+ pvr_trcmd_set_syn(&fltrace->src_syn[1], apsSrcSync[1]);
+ else
+ pvr_trcmd_clear_syn(&fltrace->src_syn[1]);
+
+ pvr_trcmd_commit(fltrace);
+
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Failed to get space in queue"));
+ goto Exit;
+ }
+
+
+ psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND*)psCommand->pvData;
+
+
+ psFlipCmd->hExtDevice = psDCInfo->hExtDevice;
+
+
+ psFlipCmd->hExtSwapChain = psBuffer->psSwapChain->hExtSwapChain;
+
+
+ psFlipCmd->hExtBuffer = psBuffer->sDeviceClassBuffer.hExtBuffer;
+
+
+ psFlipCmd->hPrivateTag = hPrivateTag;
+
+
+ psFlipCmd->ui32ClipRectCount = ui32ClipRectCount;
+
+ psFlipCmd->psClipRect = (IMG_RECT*)((IMG_UINT8*)psFlipCmd + sizeof(DISPLAYCLASS_FLIP_COMMAND));
+
+ for(i=0; i<ui32ClipRectCount; i++)
+ {
+ psFlipCmd->psClipRect[i] = psClipRect[i];
+ }
+
+
+ psFlipCmd->ui32SwapInterval = ui32SwapInterval;
+
+
+ eError = PVRSRVSubmitCommandKM (psQueue, psCommand);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Failed to submit command"));
+ goto Exit;
+ }
+
+
+
+
+
+
+
+
+
+
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+ {
+ if(PVRSRVProcessQueues(KERNEL_ID, IMG_FALSE) != PVRSRV_ERROR_PROCESSING_BLOCKED)
+ {
+ goto ProcessedQueues;
+ }
+ OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+ } END_LOOP_UNTIL_TIMEOUT();
+
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Failed to process queues"));
+
+ eError = PVRSRV_ERROR_FAILED_TO_PROCESS_QUEUE;
+ goto Exit;
+
+ProcessedQueues:
+
+ psBuffer->psSwapChain->psLastFlipBuffer = psBuffer;
+
+Exit:
+
+ if(eError == PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE)
+ {
+ eError = PVRSRV_ERROR_RETRY;
+ }
+
+#if defined(SUPPORT_LMA)
+ PVRSRVPowerUnlock(KERNEL_ID);
+#endif
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSwapToDCSystemKM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hSwapChainRef)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_QUEUE_INFO *psQueue;
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_DC_SWAPCHAIN *psSwapChain;
+ PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef;
+ DISPLAYCLASS_FLIP_COMMAND *psFlipCmd;
+ IMG_UINT32 ui32NumSrcSyncs = 1;
+ PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[2];
+ PVRSRV_COMMAND *psCommand;
+ IMG_BOOL bAddReferenceToLast = IMG_TRUE;
+ IMG_UINT16 ui16SwapCommandID = DC_FLIP_COMMAND;
+
+ if(!hDeviceKM || !hSwapChainRef)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+#if defined(SUPPORT_LMA)
+ eError = PVRSRVPowerLock(KERNEL_ID, IMG_FALSE);
+ if(eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+#endif
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+ psSwapChainRef = (PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef;
+ psSwapChain = psSwapChainRef->psSwapChain;
+
+
+ psQueue = psSwapChain->psQueue;
+
+#if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS)
+
+ if(psDCInfo->psFuncTable->pfnQuerySwapCommandID != IMG_NULL)
+ {
+ psDCInfo->psFuncTable->pfnQuerySwapCommandID(psDCInfo->hExtDevice,
+ psSwapChain->hExtSwapChain,
+ psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtBuffer,
+ 0,
+ &ui16SwapCommandID,
+ &bAddReferenceToLast);
+
+ }
+
+#endif
+
+
+ apsSrcSync[0] = psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo;
+
+
+
+ if(bAddReferenceToLast && psSwapChain->psLastFlipBuffer)
+ {
+
+ if (apsSrcSync[0] != psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.psKernelSyncInfo)
+ {
+ apsSrcSync[1] = psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.psKernelSyncInfo;
+
+
+
+ ui32NumSrcSyncs++;
+ }
+ }
+
+
+ eError = PVRSRVInsertCommandKM (psQueue,
+ &psCommand,
+ psDCInfo->ui32DeviceID,
+ ui16SwapCommandID,
+ 0,
+ IMG_NULL,
+ ui32NumSrcSyncs,
+ apsSrcSync,
+ sizeof(DISPLAYCLASS_FLIP_COMMAND));
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Failed to get space in queue"));
+ goto Exit;
+ }
+
+
+ psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND*)psCommand->pvData;
+
+
+ psFlipCmd->hExtDevice = psDCInfo->hExtDevice;
+
+
+ psFlipCmd->hExtSwapChain = psSwapChain->hExtSwapChain;
+
+
+ psFlipCmd->hExtBuffer = psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtBuffer;
+
+
+ psFlipCmd->hPrivateTag = IMG_NULL;
+
+
+ psFlipCmd->ui32ClipRectCount = 0;
+
+ psFlipCmd->ui32SwapInterval = 1;
+
+
+ eError = PVRSRVSubmitCommandKM (psQueue, psCommand);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Failed to submit command"));
+ goto Exit;
+ }
+
+
+
+
+
+
+
+
+
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+ {
+ if(PVRSRVProcessQueues(KERNEL_ID, IMG_FALSE) != PVRSRV_ERROR_PROCESSING_BLOCKED)
+ {
+ goto ProcessedQueues;
+ }
+
+ OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+ } END_LOOP_UNTIL_TIMEOUT();
+
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Failed to process queues"));
+ eError = PVRSRV_ERROR_FAILED_TO_PROCESS_QUEUE;
+ goto Exit;
+
+ProcessedQueues:
+
+ psSwapChain->psLastFlipBuffer = &psDCInfo->sSystemBuffer;
+
+ eError = PVRSRV_OK;
+
+Exit:
+
+ if(eError == PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE)
+ {
+ eError = PVRSRV_ERROR_RETRY;
+ }
+
+#if defined(SUPPORT_LMA)
+ PVRSRVPowerUnlock(KERNEL_ID);
+#endif
+ return eError;
+}
+
+
+static
+PVRSRV_ERROR PVRSRVRegisterSystemISRHandler (PFN_ISR_HANDLER pfnISRHandler,
+ IMG_VOID *pvISRHandlerData,
+ IMG_UINT32 ui32ISRSourceMask,
+ IMG_UINT32 ui32DeviceID)
+{
+ SYS_DATA *psSysData;
+ PVRSRV_DEVICE_NODE *psDevNode;
+
+ PVR_UNREFERENCED_PARAMETER(ui32ISRSourceMask);
+
+ SysAcquireData(&psSysData);
+
+
+ psDevNode = (PVRSRV_DEVICE_NODE*)
+ List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+ &MatchDeviceKM_AnyVaCb,
+ ui32DeviceID,
+ IMG_TRUE);
+
+ if (psDevNode == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterSystemISRHandler: Failed to get psDevNode"));
+ PVR_DBG_BREAK;
+ return PVRSRV_ERROR_NO_DEVICENODE_FOUND;
+ }
+
+
+ psDevNode->pvISRData = (IMG_VOID*) pvISRHandlerData;
+
+
+ psDevNode->pfnDeviceISR = pfnISRHandler;
+
+ return PVRSRV_OK;
+}
+
+static
+IMG_VOID PVRSRVSetDCState_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ IMG_UINT32 ui32State;
+ ui32State = va_arg(va, IMG_UINT32);
+
+ if (psDeviceNode->sDevId.eDeviceClass == PVRSRV_DEVICE_CLASS_DISPLAY)
+ {
+ psDCInfo = (PVRSRV_DISPLAYCLASS_INFO *)psDeviceNode->pvDevice;
+ if (psDCInfo->psFuncTable->pfnSetDCState && psDCInfo->hExtDevice)
+ {
+ psDCInfo->psFuncTable->pfnSetDCState(psDCInfo->hExtDevice, ui32State);
+ }
+ }
+}
+
+
+IMG_VOID IMG_CALLCONV PVRSRVSetDCState(IMG_UINT32 ui32State)
+{
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+
+ List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList,
+ &PVRSRVSetDCState_ForEachVaCb,
+ ui32State);
+}
+
+
+IMG_EXPORT
+IMG_BOOL PVRGetDisplayClassJTable(PVRSRV_DC_DISP2SRV_KMJTABLE *psJTable)
+{
+ psJTable->ui32TableSize = sizeof(PVRSRV_DC_DISP2SRV_KMJTABLE);
+ psJTable->pfnPVRSRVRegisterDCDevice = &PVRSRVRegisterDCDeviceKM;
+ psJTable->pfnPVRSRVRemoveDCDevice = &PVRSRVRemoveDCDeviceKM;
+ psJTable->pfnPVRSRVOEMFunction = &SysOEMFunction;
+ psJTable->pfnPVRSRVRegisterCmdProcList = &PVRSRVRegisterCmdProcListKM;
+ psJTable->pfnPVRSRVRemoveCmdProcList = &PVRSRVRemoveCmdProcListKM;
+#if defined(SUPPORT_MISR_IN_THREAD)
+ psJTable->pfnPVRSRVCmdComplete = &OSVSyncMISR;
+#else
+ psJTable->pfnPVRSRVCmdComplete = &PVRSRVCommandCompleteKM;
+#endif
+ psJTable->pfnPVRSRVRegisterSystemISRHandler = &PVRSRVRegisterSystemISRHandler;
+ psJTable->pfnPVRSRVRegisterPowerDevice = &PVRSRVRegisterPowerDevice;
+#if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS)
+ psJTable->pfnPVRSRVFreeCmdCompletePacket = &PVRSRVFreeCommandCompletePacketKM;
+#endif
+
+ return IMG_TRUE;
+}
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVCloseBCDeviceKM (IMG_HANDLE hDeviceKM,
+ IMG_BOOL bResManCallback)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo;
+
+ PVR_UNREFERENCED_PARAMETER(bResManCallback);
+
+ psBCPerContextInfo = (PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *)hDeviceKM;
+
+
+ eError = ResManFreeResByPtr(psBCPerContextInfo->hResItem);
+
+ return eError;
+}
+
+
+static PVRSRV_ERROR CloseBCDeviceCallBack(IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param)
+{
+ PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo;
+ PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ psBCPerContextInfo = (PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *)pvParam;
+ psBCInfo = psBCPerContextInfo->psBCInfo;
+
+ psBCInfo->ui32RefCount--;
+ if(psBCInfo->ui32RefCount == 0)
+ {
+ IMG_UINT32 i;
+
+
+ psBCInfo->psFuncTable->pfnCloseBCDevice(psBCInfo->ui32DeviceID, psBCInfo->hExtDevice);
+
+
+ for(i=0; i<psBCInfo->ui32BufferCount; i++)
+ {
+ if(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo)
+ {
+ if (--psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0)
+ {
+ PVRSRVFreeSyncInfoKM(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo);
+ }
+ }
+ }
+
+
+ if(psBCInfo->psBuffer)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BC_BUFFER) * psBCInfo->ui32BufferCount, psBCInfo->psBuffer, IMG_NULL);
+ psBCInfo->psBuffer = IMG_NULL;
+ }
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BUFFERCLASS_PERCONTEXT_INFO), psBCPerContextInfo, IMG_NULL);
+
+
+ return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVOpenBCDeviceKM (PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_UINT32 ui32DeviceID,
+ IMG_HANDLE hDevCookie,
+ IMG_HANDLE *phDeviceKM)
+{
+ PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+ PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ SYS_DATA *psSysData;
+ IMG_UINT32 i;
+ PVRSRV_ERROR eError;
+
+ if(!phDeviceKM || !hDevCookie)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Invalid params"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ SysAcquireData(&psSysData);
+
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE*)
+ List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+ &MatchDeviceKM_AnyVaCb,
+ ui32DeviceID,
+ IMG_FALSE,
+ PVRSRV_DEVICE_CLASS_BUFFER);
+ if (!psDeviceNode)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: No devnode matching index %d", ui32DeviceID));
+ return PVRSRV_ERROR_NO_DEVICENODE_FOUND;
+ }
+ psBCInfo = (PVRSRV_BUFFERCLASS_INFO*)psDeviceNode->pvDevice;
+
+
+
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(*psBCPerContextInfo),
+ (IMG_VOID **)&psBCPerContextInfo, IMG_NULL,
+ "Buffer Class per Context Info") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed psBCPerContextInfo alloc"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ OSMemSet(psBCPerContextInfo, 0, sizeof(*psBCPerContextInfo));
+
+ if(psBCInfo->ui32RefCount++ == 0)
+ {
+ BUFFER_INFO sBufferInfo;
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
+
+
+ psBCInfo->hDevMemContext = (IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext;
+
+
+ eError = psBCInfo->psFuncTable->pfnOpenBCDevice(ui32DeviceID, &psBCInfo->hExtDevice);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed to open external BC device"));
+ return eError;
+ }
+
+
+ eError = psBCInfo->psFuncTable->pfnGetBCInfo(psBCInfo->hExtDevice, &sBufferInfo);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM : Failed to get BC Info"));
+ return eError;
+ }
+
+
+ psBCInfo->ui32BufferCount = sBufferInfo.ui32BufferCount;
+
+
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_BC_BUFFER) * sBufferInfo.ui32BufferCount,
+ (IMG_VOID **)&psBCInfo->psBuffer,
+ IMG_NULL,
+ "Array of Buffer Class Buffer");
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed to allocate BC buffers"));
+ return eError;
+ }
+ OSMemSet (psBCInfo->psBuffer,
+ 0,
+ sizeof(PVRSRV_BC_BUFFER) * sBufferInfo.ui32BufferCount);
+
+ for(i=0; i<psBCInfo->ui32BufferCount; i++)
+ {
+
+ eError = PVRSRVAllocSyncInfoKM(IMG_NULL,
+ psBCInfo->hDevMemContext,
+ &psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed sync info alloc"));
+ goto ErrorExit;
+ }
+
+ psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount++;
+
+
+
+
+ eError = psBCInfo->psFuncTable->pfnGetBCBuffer(psBCInfo->hExtDevice,
+ i,
+ psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->psSyncData,
+ &psBCInfo->psBuffer[i].sDeviceClassBuffer.hExtBuffer);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed to get BC buffers"));
+ goto ErrorExit;
+ }
+
+
+ psBCInfo->psBuffer[i].sDeviceClassBuffer.pfnGetBufferAddr = psBCInfo->psFuncTable->pfnGetBufferAddr;
+ psBCInfo->psBuffer[i].sDeviceClassBuffer.hDevMemContext = psBCInfo->hDevMemContext;
+ psBCInfo->psBuffer[i].sDeviceClassBuffer.hExtDevice = psBCInfo->hExtDevice;
+ }
+ }
+
+ psBCPerContextInfo->psBCInfo = psBCInfo;
+ psBCPerContextInfo->hResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_BUFFERCLASS_DEVICE,
+ psBCPerContextInfo,
+ 0,
+ &CloseBCDeviceCallBack);
+
+
+ *phDeviceKM = (IMG_HANDLE)psBCPerContextInfo;
+
+ return PVRSRV_OK;
+
+ErrorExit:
+
+
+ for(i=0; i<psBCInfo->ui32BufferCount; i++)
+ {
+ if(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo)
+ {
+ if (--psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0)
+ {
+ PVRSRVFreeSyncInfoKM(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo);
+ }
+ }
+ }
+
+
+ if(psBCInfo->psBuffer)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BC_BUFFER), psBCInfo->psBuffer, IMG_NULL);
+ psBCInfo->psBuffer = IMG_NULL;
+ }
+
+ return eError;
+}
+
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVGetBCInfoKM (IMG_HANDLE hDeviceKM,
+ BUFFER_INFO *psBufferInfo)
+{
+ PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+ PVRSRV_ERROR eError;
+
+ if(!hDeviceKM || !psBufferInfo)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetBCInfoKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psBCInfo = BCDeviceHandleToBCInfo(hDeviceKM);
+
+ eError = psBCInfo->psFuncTable->pfnGetBCInfo(psBCInfo->hExtDevice, psBufferInfo);
+
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetBCInfoKM : Failed to get BC Info"));
+ return eError;
+ }
+
+ return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVGetBCBufferKM (IMG_HANDLE hDeviceKM,
+ IMG_UINT32 ui32BufferIndex,
+ IMG_HANDLE *phBuffer)
+{
+ PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+
+ if(!hDeviceKM || !phBuffer)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetBCBufferKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psBCInfo = BCDeviceHandleToBCInfo(hDeviceKM);
+
+ if(ui32BufferIndex < psBCInfo->ui32BufferCount)
+ {
+ *phBuffer = (IMG_HANDLE)&psBCInfo->psBuffer[ui32BufferIndex];
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetBCBufferKM: Buffer index %d out of range (%d)", ui32BufferIndex,psBCInfo->ui32BufferCount));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+IMG_BOOL PVRGetBufferClassJTable(PVRSRV_BC_BUFFER2SRV_KMJTABLE *psJTable)
+{
+ psJTable->ui32TableSize = sizeof(PVRSRV_BC_BUFFER2SRV_KMJTABLE);
+
+ psJTable->pfnPVRSRVRegisterBCDevice = &PVRSRVRegisterBCDeviceKM;
+ psJTable->pfnPVRSRVScheduleDevices = &PVRSRVScheduleDevicesKM;
+ psJTable->pfnPVRSRVRemoveBCDevice = &PVRSRVRemoveBCDeviceKM;
+
+ return IMG_TRUE;
+}
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef __DEVICEID_H__
+#define __DEVICEID_H__
+
+#include "services.h"
+#include "syscommon.h"
+
+PVRSRV_ERROR AllocateDeviceID(SYS_DATA *psSysData, IMG_UINT32 *pui32DevID);
+PVRSRV_ERROR FreeDeviceID(SYS_DATA *psSysData, IMG_UINT32 ui32DevID);
+
+#endif
--- /dev/null
+/**********************************************************************
+ *
+ * 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 <stddef.h>
+
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "pdump_km.h"
+#include "pvr_bridge_km.h"
+
+#include "pvr_trace_cmd.h"
+
+static PVRSRV_ERROR AllocDeviceMem(IMG_HANDLE hDevCookie,
+ IMG_HANDLE hDevMemHeap,
+ IMG_UINT32 ui32Flags,
+ IMG_SIZE_T ui32Size,
+ IMG_SIZE_T ui32Alignment,
+ PVRSRV_KERNEL_MEM_INFO **ppsMemInfo);
+
+typedef struct _RESMAN_MAP_DEVICE_MEM_DATA_
+{
+
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+
+ PVRSRV_KERNEL_MEM_INFO *psSrcMemInfo;
+} RESMAN_MAP_DEVICE_MEM_DATA;
+
+typedef struct _PVRSRV_DC_MAPINFO_
+{
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ IMG_UINT32 ui32RangeIndex;
+ IMG_UINT32 ui32TilingStride;
+} PVRSRV_DC_MAPINFO;
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapsKM(IMG_HANDLE hDevCookie,
+ PVRSRV_HEAP_INFO *psHeapInfo)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ IMG_UINT32 ui32HeapCount;
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+ IMG_UINT32 i;
+
+ if (hDevCookie == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetDeviceMemHeapsKM: hDevCookie invalid"));
+ PVR_DBG_BREAK;
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
+
+
+ ui32HeapCount = psDeviceNode->sDevMemoryInfo.ui32HeapCount;
+ psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
+
+
+ PVR_ASSERT(ui32HeapCount <= PVRSRV_MAX_CLIENT_HEAPS);
+
+
+ for(i=0; i<ui32HeapCount; i++)
+ {
+
+ psHeapInfo[i].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID;
+ psHeapInfo[i].hDevMemHeap = psDeviceMemoryHeap[i].hDevMemHeap;
+ psHeapInfo[i].sDevVAddrBase = psDeviceMemoryHeap[i].sDevVAddrBase;
+ psHeapInfo[i].ui32HeapByteSize = psDeviceMemoryHeap[i].ui32HeapSize;
+ psHeapInfo[i].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs;
+ }
+
+ for(; i < PVRSRV_MAX_CLIENT_HEAPS; i++)
+ {
+ OSMemSet(psHeapInfo + i, 0, sizeof(*psHeapInfo));
+ psHeapInfo[i].ui32HeapID = (IMG_UINT32)PVRSRV_UNDEFINED_HEAP_ID;
+ }
+
+ return PVRSRV_OK;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateDeviceMemContextKM(IMG_HANDLE hDevCookie,
+ PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE *phDevMemContext,
+ IMG_UINT32 *pui32ClientHeapCount,
+ PVRSRV_HEAP_INFO *psHeapInfo,
+ IMG_BOOL *pbCreated,
+ IMG_BOOL *pbShared)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ IMG_UINT32 ui32HeapCount, ui32ClientHeapCount=0;
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+ IMG_HANDLE hDevMemContext;
+ IMG_HANDLE hDevMemHeap;
+ IMG_DEV_PHYADDR sPDDevPAddr;
+ IMG_UINT32 i;
+
+#if !defined(PVR_SECURE_HANDLES)
+ PVR_UNREFERENCED_PARAMETER(pbShared);
+#endif
+
+ if (hDevCookie == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVCreateDeviceMemContextKM: hDevCookie invalid"));
+ PVR_DBG_BREAK;
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
+
+
+
+ ui32HeapCount = psDeviceNode->sDevMemoryInfo.ui32HeapCount;
+ psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
+
+
+
+ PVR_ASSERT(ui32HeapCount <= PVRSRV_MAX_CLIENT_HEAPS);
+
+
+
+ hDevMemContext = BM_CreateContext(psDeviceNode,
+ &sPDDevPAddr,
+ psPerProc,
+ pbCreated);
+ if (hDevMemContext == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDeviceMemContextKM: Failed BM_CreateContext"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+
+ for(i=0; i<ui32HeapCount; i++)
+ {
+ switch(psDeviceMemoryHeap[i].DevMemHeapType)
+ {
+ case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
+ {
+
+ psHeapInfo[ui32ClientHeapCount].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID;
+ psHeapInfo[ui32ClientHeapCount].hDevMemHeap = psDeviceMemoryHeap[i].hDevMemHeap;
+ psHeapInfo[ui32ClientHeapCount].sDevVAddrBase = psDeviceMemoryHeap[i].sDevVAddrBase;
+ psHeapInfo[ui32ClientHeapCount].ui32HeapByteSize = psDeviceMemoryHeap[i].ui32HeapSize;
+ psHeapInfo[ui32ClientHeapCount].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs;
+#if defined(PVR_SECURE_HANDLES)
+ pbShared[ui32ClientHeapCount] = IMG_TRUE;
+#endif
+ ui32ClientHeapCount++;
+ break;
+ }
+ case DEVICE_MEMORY_HEAP_PERCONTEXT:
+ {
+ hDevMemHeap = BM_CreateHeap(hDevMemContext,
+ &psDeviceMemoryHeap[i]);
+
+
+ psHeapInfo[ui32ClientHeapCount].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID;
+ psHeapInfo[ui32ClientHeapCount].hDevMemHeap = hDevMemHeap;
+ psHeapInfo[ui32ClientHeapCount].sDevVAddrBase = psDeviceMemoryHeap[i].sDevVAddrBase;
+ psHeapInfo[ui32ClientHeapCount].ui32HeapByteSize = psDeviceMemoryHeap[i].ui32HeapSize;
+ psHeapInfo[ui32ClientHeapCount].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs;
+#if defined(PVR_SECURE_HANDLES)
+ pbShared[ui32ClientHeapCount] = IMG_FALSE;
+#endif
+
+ ui32ClientHeapCount++;
+ break;
+ }
+ }
+ }
+
+
+ *pui32ClientHeapCount = ui32ClientHeapCount;
+ *phDevMemContext = hDevMemContext;
+
+ return PVRSRV_OK;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyDeviceMemContextKM(IMG_HANDLE hDevCookie,
+ IMG_HANDLE hDevMemContext,
+ IMG_BOOL *pbDestroyed)
+{
+ PVR_UNREFERENCED_PARAMETER(hDevCookie);
+
+ return BM_DestroyContext(hDevMemContext, pbDestroyed);
+}
+
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapInfoKM(IMG_HANDLE hDevCookie,
+ IMG_HANDLE hDevMemContext,
+ IMG_UINT32 *pui32ClientHeapCount,
+ PVRSRV_HEAP_INFO *psHeapInfo,
+ IMG_BOOL *pbShared)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ IMG_UINT32 ui32HeapCount, ui32ClientHeapCount=0;
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+ IMG_HANDLE hDevMemHeap;
+ IMG_UINT32 i;
+
+#if !defined(PVR_SECURE_HANDLES)
+ PVR_UNREFERENCED_PARAMETER(pbShared);
+#endif
+
+ if (hDevCookie == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetDeviceMemHeapInfoKM: hDevCookie invalid"));
+ PVR_DBG_BREAK;
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
+
+
+
+ ui32HeapCount = psDeviceNode->sDevMemoryInfo.ui32HeapCount;
+ psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
+
+
+
+ PVR_ASSERT(ui32HeapCount <= PVRSRV_MAX_CLIENT_HEAPS);
+
+
+ for(i=0; i<ui32HeapCount; i++)
+ {
+ switch(psDeviceMemoryHeap[i].DevMemHeapType)
+ {
+ case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
+ {
+
+ psHeapInfo[ui32ClientHeapCount].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID;
+ psHeapInfo[ui32ClientHeapCount].hDevMemHeap = psDeviceMemoryHeap[i].hDevMemHeap;
+ psHeapInfo[ui32ClientHeapCount].sDevVAddrBase = psDeviceMemoryHeap[i].sDevVAddrBase;
+ psHeapInfo[ui32ClientHeapCount].ui32HeapByteSize = psDeviceMemoryHeap[i].ui32HeapSize;
+ psHeapInfo[ui32ClientHeapCount].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs;
+#if defined(PVR_SECURE_HANDLES)
+ pbShared[ui32ClientHeapCount] = IMG_TRUE;
+#endif
+ ui32ClientHeapCount++;
+ break;
+ }
+ case DEVICE_MEMORY_HEAP_PERCONTEXT:
+ {
+ hDevMemHeap = BM_CreateHeap(hDevMemContext,
+ &psDeviceMemoryHeap[i]);
+
+
+ psHeapInfo[ui32ClientHeapCount].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID;
+ psHeapInfo[ui32ClientHeapCount].hDevMemHeap = hDevMemHeap;
+ psHeapInfo[ui32ClientHeapCount].sDevVAddrBase = psDeviceMemoryHeap[i].sDevVAddrBase;
+ psHeapInfo[ui32ClientHeapCount].ui32HeapByteSize = psDeviceMemoryHeap[i].ui32HeapSize;
+ psHeapInfo[ui32ClientHeapCount].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs;
+#if defined(PVR_SECURE_HANDLES)
+ pbShared[ui32ClientHeapCount] = IMG_FALSE;
+#endif
+
+ ui32ClientHeapCount++;
+ break;
+ }
+ }
+ }
+
+
+ *pui32ClientHeapCount = ui32ClientHeapCount;
+
+ return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR AllocDeviceMem(IMG_HANDLE hDevCookie,
+ IMG_HANDLE hDevMemHeap,
+ IMG_UINT32 ui32Flags,
+ IMG_SIZE_T ui32Size,
+ IMG_SIZE_T ui32Alignment,
+ PVRSRV_KERNEL_MEM_INFO **ppsMemInfo)
+{
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+ BM_HANDLE hBuffer;
+
+ PVRSRV_MEMBLK *psMemBlock;
+ IMG_BOOL bBMError;
+
+ PVR_UNREFERENCED_PARAMETER(hDevCookie);
+
+ *ppsMemInfo = IMG_NULL;
+
+ if(OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(PVRSRV_KERNEL_MEM_INFO),
+ (IMG_VOID **)&psMemInfo, IMG_NULL,
+ "Kernel Memory Info") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"AllocDeviceMem: Failed to alloc memory for block"));
+ return (PVRSRV_ERROR_OUT_OF_MEMORY);
+ }
+
+ OSMemSet(psMemInfo, 0, sizeof(*psMemInfo));
+
+ psMemBlock = &(psMemInfo->sMemBlk);
+
+
+ psMemInfo->ui32Flags = ui32Flags | PVRSRV_MEM_RAM_BACKED_ALLOCATION;
+
+ bBMError = BM_Alloc (hDevMemHeap,
+ IMG_NULL,
+ ui32Size,
+ &psMemInfo->ui32Flags,
+ IMG_CAST_TO_DEVVADDR_UINT(ui32Alignment),
+ &hBuffer);
+
+ if (!bBMError)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"AllocDeviceMem: BM_Alloc Failed"));
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
+
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+
+ psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
+ psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
+
+
+ psMemBlock->hBuffer = (IMG_HANDLE)hBuffer;
+
+
+
+ psMemInfo->pvLinAddrKM = BM_HandleToCpuVaddr(hBuffer);
+
+ psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
+
+ psMemInfo->ui32AllocSize = ui32Size;
+
+
+ psMemInfo->pvSysBackupBuffer = IMG_NULL;
+
+
+ *ppsMemInfo = psMemInfo;
+
+
+ return (PVRSRV_OK);
+}
+
+static PVRSRV_ERROR FreeDeviceMem2(PVRSRV_KERNEL_MEM_INFO *psMemInfo, IMG_BOOL bFromAllocator)
+{
+ BM_HANDLE hBuffer;
+
+ if (!psMemInfo)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ hBuffer = psMemInfo->sMemBlk.hBuffer;
+
+ if (bFromAllocator)
+ BM_Free(hBuffer, psMemInfo->ui32Flags);
+ else
+ BM_FreeExport(hBuffer, psMemInfo->ui32Flags);
+
+
+ if ((psMemInfo->pvSysBackupBuffer) && bFromAllocator)
+ {
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, psMemInfo->ui32AllocSize, psMemInfo->pvSysBackupBuffer, IMG_NULL);
+ psMemInfo->pvSysBackupBuffer = IMG_NULL;
+ }
+
+ if (psMemInfo->ui32RefCount == 0)
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
+
+ return(PVRSRV_OK);
+}
+
+static PVRSRV_ERROR FreeDeviceMem(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+ BM_HANDLE hBuffer;
+
+ if (!psMemInfo)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ hBuffer = psMemInfo->sMemBlk.hBuffer;
+
+ BM_Free(hBuffer, psMemInfo->ui32Flags);
+
+ if(psMemInfo->pvSysBackupBuffer)
+ {
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, psMemInfo->ui32AllocSize, psMemInfo->pvSysBackupBuffer, IMG_NULL);
+ psMemInfo->pvSysBackupBuffer = IMG_NULL;
+ }
+
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
+
+
+ return(PVRSRV_OK);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAllocSyncInfoKM(IMG_HANDLE hDevCookie,
+ IMG_HANDLE hDevMemContext,
+ PVRSRV_KERNEL_SYNC_INFO **ppsKernelSyncInfo)
+{
+ IMG_HANDLE hSyncDevMemHeap;
+ DEVICE_MEMORY_INFO *psDevMemoryInfo;
+ BM_CONTEXT *pBMContext;
+ PVRSRV_ERROR eError;
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+ PVRSRV_SYNC_DATA *psSyncData;
+
+ eError = OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(PVRSRV_KERNEL_SYNC_INFO),
+ (IMG_VOID **)&psKernelSyncInfo, IMG_NULL,
+ "Kernel Synchronization Info");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVAllocSyncInfoKM: Failed to alloc memory"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ psKernelSyncInfo->ui32RefCount = 0;
+
+#ifdef CONFIG_PVR_TRACE_CMD
+ INIT_LIST_HEAD(&psKernelSyncInfo->link);
+ psKernelSyncInfo->counter_digest = 0;
+#endif
+
+ pBMContext = (BM_CONTEXT*)hDevMemContext;
+ psDevMemoryInfo = &pBMContext->psDeviceNode->sDevMemoryInfo;
+
+
+ hSyncDevMemHeap = psDevMemoryInfo->psDeviceMemoryHeap[psDevMemoryInfo->ui32SyncHeapID].hDevMemHeap;
+
+
+
+
+ eError = AllocDeviceMem(hDevCookie,
+ hSyncDevMemHeap,
+ PVRSRV_MEM_CACHE_CONSISTENT,
+ sizeof(PVRSRV_SYNC_DATA),
+ sizeof(IMG_UINT32),
+ &psKernelSyncInfo->psSyncDataMemInfoKM);
+
+ if (eError != PVRSRV_OK)
+ {
+
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVAllocSyncInfoKM: Failed to alloc memory"));
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_SYNC_INFO), psKernelSyncInfo, IMG_NULL);
+
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+
+ psKernelSyncInfo->psSyncData = psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM;
+ psSyncData = psKernelSyncInfo->psSyncData;
+
+ psSyncData->ui32WriteOpsPending = 0;
+ psSyncData->ui32WriteOpsComplete = 0;
+ psSyncData->ui32ReadOpsPending = 0;
+ psSyncData->ui32ReadOpsComplete = 0;
+ psSyncData->ui32LastOpDumpVal = 0;
+ psSyncData->ui32LastReadOpDumpVal = 0;
+
+#if defined(PDUMP)
+ PDUMPCOMMENT("Allocating kernel sync object");
+ PDUMPMEM(psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM,
+ psKernelSyncInfo->psSyncDataMemInfoKM,
+ 0,
+ psKernelSyncInfo->psSyncDataMemInfoKM->ui32AllocSize,
+ PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psKernelSyncInfo->psSyncDataMemInfoKM));
+#endif
+
+ psKernelSyncInfo->sWriteOpsCompleteDevVAddr.uiAddr = psKernelSyncInfo->psSyncDataMemInfoKM->sDevVAddr.uiAddr + offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete);
+ psKernelSyncInfo->sReadOpsCompleteDevVAddr.uiAddr = psKernelSyncInfo->psSyncDataMemInfoKM->sDevVAddr.uiAddr + offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete);
+
+
+ psKernelSyncInfo->psSyncDataMemInfoKM->psKernelSyncInfo = IMG_NULL;
+
+
+ *ppsKernelSyncInfo = psKernelSyncInfo;
+
+ return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeSyncInfoKM(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo)
+{
+ PVRSRV_ERROR eError;
+
+ if (psKernelSyncInfo->ui32RefCount != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "oops: sync info ref count not zero at destruction"));
+
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ /*
+ * TODO: arrange for the per proc info to be passed to this func, so
+ * we can trace the pid and proc name.
+ */
+ pvr_trcmd_remove_syn(0, "n/a", psKernelSyncInfo);
+
+ eError = FreeDeviceMem(psKernelSyncInfo->psSyncDataMemInfoKM);
+ (IMG_VOID)OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_SYNC_INFO), psKernelSyncInfo, IMG_NULL);
+
+
+ return eError;
+}
+
+static IMG_VOID freeWrapped(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+ IMG_HANDLE hOSWrapMem = psMemInfo->sMemBlk.hOSWrapMem;
+
+
+ if(psMemInfo->sMemBlk.psIntSysPAddr)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(IMG_SYS_PHYADDR), psMemInfo->sMemBlk.psIntSysPAddr, IMG_NULL);
+ psMemInfo->sMemBlk.psIntSysPAddr = IMG_NULL;
+ }
+
+ if(hOSWrapMem)
+ {
+ OSReleasePhysPageAddr(hOSWrapMem);
+ }
+}
+
+static PVRSRV_ERROR FreeMemCallBackCommon(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Param,
+ IMG_BOOL bFromAllocator)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+
+ psMemInfo->ui32RefCount--;
+
+ if (psMemInfo->ui32RefCount == 0)
+ {
+ if(psMemInfo->ui32Flags & PVRSRV_MEM_EXPORTED)
+ {
+ IMG_HANDLE hMemInfo = IMG_NULL;
+
+
+ eError = PVRSRVFindHandle(KERNEL_HANDLE_BASE,
+ &hMemInfo,
+ psMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeMemCallBackCommon: can't find exported meminfo in the global handle list"));
+ return eError;
+ }
+
+
+ eError = PVRSRVReleaseHandle(KERNEL_HANDLE_BASE,
+ hMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeMemCallBackCommon: PVRSRVReleaseHandle failed for exported meminfo"));
+ return eError;
+ }
+ }
+
+ switch(psMemInfo->memType)
+ {
+
+ case PVRSRV_MEMTYPE_WRAPPED:
+ freeWrapped(psMemInfo);
+ case PVRSRV_MEMTYPE_DEVICE:
+ if (psMemInfo->psKernelSyncInfo)
+ {
+ psMemInfo->psKernelSyncInfo->ui32RefCount--;
+
+ if (psMemInfo->psKernelSyncInfo->ui32RefCount == 0)
+ {
+ eError = PVRSRVFreeSyncInfoKM(psMemInfo->psKernelSyncInfo);
+ }
+ }
+
+ case PVRSRV_MEMTYPE_DEVICECLASS:
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "FreeMemCallBackCommon: Unknown memType"));
+ eError = PVRSRV_ERROR_INVALID_MEMINFO;
+ }
+ }
+
+
+
+ eError = FreeDeviceMem2(psMemInfo, bFromAllocator);
+
+ return eError;
+}
+
+static PVRSRV_ERROR FreeDeviceMemCallBack(IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param)
+{
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo = (PVRSRV_KERNEL_MEM_INFO *)pvParam;
+ return FreeMemCallBackCommon(psMemInfo, ui32Param, IMG_TRUE);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeDeviceMemKM(IMG_HANDLE hDevCookie,
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_UNREFERENCED_PARAMETER(hDevCookie);
+
+ if (!psMemInfo)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if (psMemInfo->sMemBlk.hResItem != IMG_NULL)
+ {
+ eError = ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem);
+ }
+ else
+ {
+
+ eError = FreeDeviceMemCallBack(psMemInfo, 0);
+ }
+
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV _PVRSRVAllocDeviceMemKM(IMG_HANDLE hDevCookie,
+ PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDevMemHeap,
+ IMG_UINT32 ui32Flags,
+ IMG_SIZE_T ui32Size,
+ IMG_SIZE_T ui32Alignment,
+ PVRSRV_KERNEL_MEM_INFO **ppsMemInfo)
+{
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+ PVRSRV_ERROR eError;
+ BM_HEAP *psBMHeap;
+ IMG_HANDLE hDevMemContext;
+
+ if (!hDevMemHeap ||
+ (ui32Size == 0))
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ if (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)
+ {
+
+ if (((ui32Size % HOST_PAGESIZE()) != 0) ||
+ ((ui32Alignment % HOST_PAGESIZE()) != 0))
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ }
+
+ eError = AllocDeviceMem(hDevCookie,
+ hDevMemHeap,
+ ui32Flags,
+ ui32Size,
+ ui32Alignment,
+ &psMemInfo);
+
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+#if defined(PVRSRV_RESOURCE_PROFILING)
+ psBMHeap = (BM_HEAP*)hDevMemHeap;
+ if (psBMHeap->pBMContext->psDeviceNode->pfnResProfCB)
+ psBMHeap->pBMContext->psDeviceNode->pfnResProfCB(hDevCookie, psMemInfo->ui32AllocSize, IMG_TRUE);
+#endif
+
+ if (ui32Flags & PVRSRV_MEM_NO_SYNCOBJ)
+ {
+ psMemInfo->psKernelSyncInfo = IMG_NULL;
+ }
+ else
+ {
+
+
+
+ psBMHeap = (BM_HEAP*)hDevMemHeap;
+ hDevMemContext = (IMG_HANDLE)psBMHeap->pBMContext;
+ eError = PVRSRVAllocSyncInfoKM(hDevCookie,
+ hDevMemContext,
+ &psMemInfo->psKernelSyncInfo);
+ if(eError != PVRSRV_OK)
+ {
+ goto free_mainalloc;
+ }
+ psMemInfo->psKernelSyncInfo->ui32RefCount++;
+#if defined(PVRSRV_RESOURCE_PROFILING)
+ if (psBMHeap->pBMContext->psDeviceNode->pfnResProfCB)
+ psBMHeap->pBMContext->psDeviceNode->pfnResProfCB(hDevCookie,
+ psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->ui32AllocSize, IMG_TRUE);
+#endif
+ }
+
+
+ *ppsMemInfo = psMemInfo;
+
+ if (ui32Flags & PVRSRV_MEM_NO_RESMAN)
+ {
+ psMemInfo->sMemBlk.hResItem = IMG_NULL;
+ }
+ else
+ {
+
+ psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_DEVICEMEM_ALLOCATION,
+ psMemInfo,
+ 0,
+ &FreeDeviceMemCallBack);
+ if (psMemInfo->sMemBlk.hResItem == IMG_NULL)
+ {
+
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto free_mainalloc;
+ }
+ }
+
+
+ psMemInfo->ui32RefCount++;
+
+ psMemInfo->memType = PVRSRV_MEMTYPE_DEVICE;
+
+
+ return (PVRSRV_OK);
+
+free_mainalloc:
+#if defined(PVRSRV_RESOURCE_PROFILING)
+ if (psBMHeap->pBMContext->psDeviceNode->pfnResProfCB)
+ psBMHeap->pBMContext->psDeviceNode->pfnResProfCB(hDevCookie,
+ psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->ui32AllocSize, IMG_FALSE);
+#endif
+ FreeDeviceMem(psMemInfo);
+
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDissociateDeviceMemKM(IMG_HANDLE hDevCookie,
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DEVICE_NODE *psDeviceNode = hDevCookie;
+
+ PVR_UNREFERENCED_PARAMETER(hDevCookie);
+
+ if (!psMemInfo)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ eError = ResManDissociateRes(psMemInfo->sMemBlk.hResItem, psDeviceNode->hResManContext);
+
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetFreeDeviceMemKM(IMG_UINT32 ui32Flags,
+ IMG_SIZE_T *pui32Total,
+ IMG_SIZE_T *pui32Free,
+ IMG_SIZE_T *pui32LargestBlock)
+{
+
+
+ PVR_UNREFERENCED_PARAMETER(ui32Flags);
+ PVR_UNREFERENCED_PARAMETER(pui32Total);
+ PVR_UNREFERENCED_PARAMETER(pui32Free);
+ PVR_UNREFERENCED_PARAMETER(pui32LargestBlock);
+
+ return PVRSRV_OK;
+}
+
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnwrapExtMemoryKM (PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+ if (!psMemInfo)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem);
+}
+
+
+static PVRSRV_ERROR UnwrapExtMemoryCallBack(IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param)
+{
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo = (PVRSRV_KERNEL_MEM_INFO *)pvParam;
+
+ return FreeMemCallBackCommon(psMemInfo, ui32Param, IMG_TRUE);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVWrapExtMemoryKM(IMG_HANDLE hDevCookie,
+ PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDevMemContext,
+ IMG_SIZE_T ui32ByteSize,
+ IMG_SIZE_T ui32PageOffset,
+ IMG_BOOL bPhysContig,
+ IMG_SYS_PHYADDR *psExtSysPAddr,
+ IMG_VOID *pvLinAddr,
+ IMG_UINT32 ui32Flags,
+ PVRSRV_KERNEL_MEM_INFO **ppsMemInfo)
+{
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo = IMG_NULL;
+ DEVICE_MEMORY_INFO *psDevMemoryInfo;
+ IMG_SIZE_T ui32HostPageSize = HOST_PAGESIZE();
+ IMG_HANDLE hDevMemHeap = IMG_NULL;
+ PVRSRV_DEVICE_NODE* psDeviceNode;
+ BM_HANDLE hBuffer;
+ PVRSRV_MEMBLK *psMemBlock;
+ IMG_BOOL bBMError;
+ BM_HEAP *psBMHeap;
+ PVRSRV_ERROR eError;
+ IMG_VOID *pvPageAlignedCPUVAddr;
+ IMG_SYS_PHYADDR *psIntSysPAddr = IMG_NULL;
+ IMG_HANDLE hOSWrapMem = IMG_NULL;
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+ IMG_UINT32 i;
+ IMG_SIZE_T ui32PageCount = 0;
+
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE*)hDevCookie;
+ PVR_ASSERT(psDeviceNode != IMG_NULL);
+
+ if (psDeviceNode == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVWrapExtMemoryKM: invalid parameter"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if(pvLinAddr)
+ {
+
+ ui32PageOffset = (IMG_UINTPTR_T)pvLinAddr & (ui32HostPageSize - 1);
+
+
+ ui32PageCount = HOST_PAGEALIGN(ui32ByteSize + ui32PageOffset) / ui32HostPageSize;
+ pvPageAlignedCPUVAddr = (IMG_VOID *)((IMG_UINTPTR_T)pvLinAddr - ui32PageOffset);
+
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32PageCount * sizeof(IMG_SYS_PHYADDR),
+ (IMG_VOID **)&psIntSysPAddr, IMG_NULL,
+ "Array of Page Addresses") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: Failed to alloc memory for block"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ eError = OSAcquirePhysPageAddr(pvPageAlignedCPUVAddr,
+ ui32PageCount * ui32HostPageSize,
+ psIntSysPAddr,
+ &hOSWrapMem);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: Failed to alloc memory for block"));
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto ErrorExitPhase1;
+ }
+
+
+ psExtSysPAddr = psIntSysPAddr;
+
+
+
+ bPhysContig = IMG_FALSE;
+ }
+ else
+ {
+
+ }
+
+
+ psDevMemoryInfo = &((BM_CONTEXT*)hDevMemContext)->psDeviceNode->sDevMemoryInfo;
+ psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
+ for(i=0; i<PVRSRV_MAX_CLIENT_HEAPS; i++)
+ {
+ if(HEAP_IDX(psDeviceMemoryHeap[i].ui32HeapID) == psDevMemoryInfo->ui32MappingHeapID)
+ {
+ if(psDeviceMemoryHeap[i].DevMemHeapType == DEVICE_MEMORY_HEAP_PERCONTEXT)
+ {
+
+ hDevMemHeap = BM_CreateHeap(hDevMemContext, &psDeviceMemoryHeap[i]);
+ }
+ else
+ {
+ hDevMemHeap = psDevMemoryInfo->psDeviceMemoryHeap[i].hDevMemHeap;
+ }
+ break;
+ }
+ }
+
+ if(hDevMemHeap == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: unable to find mapping heap"));
+ eError = PVRSRV_ERROR_UNABLE_TO_FIND_MAPPING_HEAP;
+ goto ErrorExitPhase2;
+ }
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO),
+ (IMG_VOID **)&psMemInfo, IMG_NULL,
+ "Kernel Memory Info") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: Failed to alloc memory for block"));
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto ErrorExitPhase2;
+ }
+
+ OSMemSet(psMemInfo, 0, sizeof(*psMemInfo));
+ psMemInfo->ui32Flags = ui32Flags;
+
+ psMemBlock = &(psMemInfo->sMemBlk);
+
+ bBMError = BM_Wrap(hDevMemHeap,
+ ui32ByteSize,
+ ui32PageOffset,
+ bPhysContig,
+ psExtSysPAddr,
+ IMG_NULL,
+ &psMemInfo->ui32Flags,
+ &hBuffer);
+ if (!bBMError)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: BM_Wrap Failed"));
+ eError = PVRSRV_ERROR_BAD_MAPPING;
+ goto ErrorExitPhase3;
+ }
+
+
+ psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
+ psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
+ psMemBlock->hOSWrapMem = hOSWrapMem;
+ psMemBlock->psIntSysPAddr = psIntSysPAddr;
+
+
+ psMemBlock->hBuffer = (IMG_HANDLE)hBuffer;
+
+
+ psMemInfo->pvLinAddrKM = BM_HandleToCpuVaddr(hBuffer);
+ psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
+ psMemInfo->ui32AllocSize = ui32ByteSize;
+
+
+
+ psMemInfo->pvSysBackupBuffer = IMG_NULL;
+
+
+
+
+ psBMHeap = (BM_HEAP*)hDevMemHeap;
+ hDevMemContext = (IMG_HANDLE)psBMHeap->pBMContext;
+ eError = PVRSRVAllocSyncInfoKM(hDevCookie,
+ hDevMemContext,
+ &psMemInfo->psKernelSyncInfo);
+ if(eError != PVRSRV_OK)
+ {
+ goto ErrorExitPhase4;
+ }
+
+ psMemInfo->psKernelSyncInfo->ui32RefCount++;
+
+
+ psMemInfo->ui32RefCount++;
+
+ psMemInfo->memType = PVRSRV_MEMTYPE_WRAPPED;
+
+
+ psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_DEVICEMEM_WRAP,
+ psMemInfo,
+ 0,
+ &UnwrapExtMemoryCallBack);
+
+
+ *ppsMemInfo = psMemInfo;
+
+ return PVRSRV_OK;
+
+
+
+ErrorExitPhase4:
+ if(psMemInfo)
+ {
+ FreeDeviceMem(psMemInfo);
+
+
+
+ psMemInfo = IMG_NULL;
+ }
+
+ErrorExitPhase3:
+ if(psMemInfo)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
+
+ }
+
+ErrorExitPhase2:
+ if(psIntSysPAddr)
+ {
+ OSReleasePhysPageAddr(hOSWrapMem);
+ }
+
+ErrorExitPhase1:
+ if(psIntSysPAddr)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32PageCount * sizeof(IMG_SYS_PHYADDR), psIntSysPAddr, IMG_NULL);
+
+ }
+
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceMemoryKM (PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+ if (!psMemInfo)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem);
+}
+
+
+static PVRSRV_ERROR UnmapDeviceMemoryCallBack(IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param)
+{
+ PVRSRV_ERROR eError;
+ RESMAN_MAP_DEVICE_MEM_DATA *psMapData = pvParam;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ if(psMapData->psMemInfo->sMemBlk.psIntSysPAddr)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(IMG_SYS_PHYADDR), psMapData->psMemInfo->sMemBlk.psIntSysPAddr, IMG_NULL);
+ psMapData->psMemInfo->sMemBlk.psIntSysPAddr = IMG_NULL;
+ }
+
+ if( psMapData->psMemInfo->psKernelSyncInfo )
+ {
+ psMapData->psMemInfo->psKernelSyncInfo->ui32RefCount--;
+ if (psMapData->psMemInfo->psKernelSyncInfo->ui32RefCount == 0)
+ {
+ eError = PVRSRVFreeSyncInfoKM(psMapData->psMemInfo->psKernelSyncInfo);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"UnmapDeviceMemoryCallBack: Failed to free sync info"));
+ return eError;
+ }
+ }
+ }
+
+ eError = FreeDeviceMem(psMapData->psMemInfo);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"UnmapDeviceMemoryCallBack: Failed to free DST meminfo"));
+ return eError;
+ }
+
+
+ eError = FreeMemCallBackCommon(psMapData->psSrcMemInfo, 0, IMG_FALSE);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RESMAN_MAP_DEVICE_MEM_DATA), psMapData, IMG_NULL);
+
+
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceMemoryKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ PVRSRV_KERNEL_MEM_INFO *psSrcMemInfo,
+ IMG_HANDLE hDstDevMemHeap,
+ PVRSRV_KERNEL_MEM_INFO **ppsDstMemInfo)
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 i;
+ IMG_SIZE_T ui32PageCount, ui32PageOffset;
+ IMG_SIZE_T ui32HostPageSize = HOST_PAGESIZE();
+ IMG_SYS_PHYADDR *psSysPAddr = IMG_NULL;
+ IMG_DEV_PHYADDR sDevPAddr;
+ BM_BUF *psBuf;
+ IMG_DEV_VIRTADDR sDevVAddr;
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo = IMG_NULL;
+ BM_HANDLE hBuffer;
+ PVRSRV_MEMBLK *psMemBlock;
+ IMG_BOOL bBMError;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ IMG_VOID *pvPageAlignedCPUVAddr;
+ RESMAN_MAP_DEVICE_MEM_DATA *psMapData = IMG_NULL;
+
+
+ if(!psSrcMemInfo || !hDstDevMemHeap || !ppsDstMemInfo)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ *ppsDstMemInfo = IMG_NULL;
+
+ ui32PageOffset = psSrcMemInfo->sDevVAddr.uiAddr & (ui32HostPageSize - 1);
+ ui32PageCount = HOST_PAGEALIGN(psSrcMemInfo->ui32AllocSize + ui32PageOffset) / ui32HostPageSize;
+ pvPageAlignedCPUVAddr = (IMG_VOID *)((IMG_UINTPTR_T)psSrcMemInfo->pvLinAddrKM - ui32PageOffset);
+
+
+
+
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32PageCount*sizeof(IMG_SYS_PHYADDR),
+ (IMG_VOID **)&psSysPAddr, IMG_NULL,
+ "Array of Page Addresses") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: Failed to alloc memory for block"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ psBuf = psSrcMemInfo->sMemBlk.hBuffer;
+
+
+ psDeviceNode = psBuf->pMapping->pBMHeap->pBMContext->psDeviceNode;
+
+
+ sDevVAddr.uiAddr = psSrcMemInfo->sDevVAddr.uiAddr - IMG_CAST_TO_DEVVADDR_UINT(ui32PageOffset);
+ for(i=0; i<ui32PageCount; i++)
+ {
+ BM_GetPhysPageAddr(psSrcMemInfo, sDevVAddr, &sDevPAddr);
+
+
+ psSysPAddr[i] = SysDevPAddrToSysPAddr (psDeviceNode->sDevId.eDeviceType, sDevPAddr);
+
+
+ sDevVAddr.uiAddr += IMG_CAST_TO_DEVVADDR_UINT(ui32HostPageSize);
+ }
+
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(RESMAN_MAP_DEVICE_MEM_DATA),
+ (IMG_VOID **)&psMapData, IMG_NULL,
+ "Resource Manager Map Data") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: Failed to alloc resman map data"));
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto ErrorExit;
+ }
+
+
+ if(OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(PVRSRV_KERNEL_MEM_INFO),
+ (IMG_VOID **)&psMemInfo, IMG_NULL,
+ "Kernel Memory Info") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: Failed to alloc memory for block"));
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto ErrorExit;
+ }
+
+ OSMemSet(psMemInfo, 0, sizeof(*psMemInfo));
+ psMemInfo->ui32Flags = psSrcMemInfo->ui32Flags;
+
+ psMemBlock = &(psMemInfo->sMemBlk);
+
+ bBMError = BM_Wrap(hDstDevMemHeap,
+ psSrcMemInfo->ui32AllocSize,
+ ui32PageOffset,
+ IMG_FALSE,
+ psSysPAddr,
+ pvPageAlignedCPUVAddr,
+ &psMemInfo->ui32Flags,
+ &hBuffer);
+
+ if (!bBMError)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: BM_Wrap Failed"));
+ eError = PVRSRV_ERROR_BAD_MAPPING;
+ goto ErrorExit;
+ }
+
+
+ psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
+ psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
+
+
+ psMemBlock->hBuffer = (IMG_HANDLE)hBuffer;
+
+
+ psMemBlock->psIntSysPAddr = psSysPAddr;
+
+
+ psMemInfo->pvLinAddrKM = psSrcMemInfo->pvLinAddrKM;
+
+
+ psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
+ psMemInfo->ui32AllocSize = psSrcMemInfo->ui32AllocSize;
+ psMemInfo->psKernelSyncInfo = psSrcMemInfo->psKernelSyncInfo;
+
+
+ if( psMemInfo->psKernelSyncInfo )
+ psMemInfo->psKernelSyncInfo->ui32RefCount++;
+
+
+
+ psMemInfo->pvSysBackupBuffer = IMG_NULL;
+
+
+ psMemInfo->ui32RefCount++;
+
+
+ psSrcMemInfo->ui32RefCount++;
+
+
+ BM_Export(psSrcMemInfo->sMemBlk.hBuffer);
+
+ psMemInfo->memType = PVRSRV_MEMTYPE_MAPPED;
+
+
+ psMapData->psMemInfo = psMemInfo;
+ psMapData->psSrcMemInfo = psSrcMemInfo;
+
+
+ psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_DEVICEMEM_MAPPING,
+ psMapData,
+ 0,
+ &UnmapDeviceMemoryCallBack);
+
+ *ppsDstMemInfo = psMemInfo;
+
+ return PVRSRV_OK;
+
+
+
+ErrorExit:
+
+ if(psSysPAddr)
+ {
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(IMG_SYS_PHYADDR), psSysPAddr, IMG_NULL);
+
+ }
+
+ if(psMemInfo)
+ {
+
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
+
+ }
+
+ if(psMapData)
+ {
+
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(RESMAN_MAP_DEVICE_MEM_DATA), psMapData, IMG_NULL);
+
+ }
+
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceClassMemoryKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+ if (!psMemInfo)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem);
+}
+
+
+static PVRSRV_ERROR UnmapDeviceClassMemoryCallBack(IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param)
+{
+ PVRSRV_DC_MAPINFO *psDCMapInfo = pvParam;
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ psMemInfo = psDCMapInfo->psMemInfo;
+
+#if defined(SUPPORT_MEMORY_TILING)
+ if(psDCMapInfo->ui32TilingStride > 0)
+ {
+ PVRSRV_DEVICE_NODE *psDeviceNode = psDCMapInfo->psDeviceNode;
+
+ if (psDeviceNode->pfnFreeMemTilingRange(psDeviceNode,
+ psDCMapInfo->ui32RangeIndex) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"UnmapDeviceClassMemoryCallBack: FreeMemTilingRange failed"));
+ }
+ }
+#endif
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_MAPINFO), psDCMapInfo, IMG_NULL);
+
+ return FreeMemCallBackCommon(psMemInfo, ui32Param, IMG_TRUE);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceClassMemoryKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDevMemContext,
+ IMG_HANDLE hDeviceClassBuffer,
+ PVRSRV_KERNEL_MEM_INFO **ppsMemInfo,
+ IMG_HANDLE *phOSMapInfo)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DEVICE_NODE* psDeviceNode;
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo = IMG_NULL;
+ PVRSRV_DEVICECLASS_BUFFER *psDeviceClassBuffer;
+ IMG_SYS_PHYADDR *psSysPAddr;
+ IMG_VOID *pvCPUVAddr, *pvPageAlignedCPUVAddr;
+ IMG_BOOL bPhysContig;
+ BM_CONTEXT *psBMContext;
+ DEVICE_MEMORY_INFO *psDevMemoryInfo;
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+ IMG_HANDLE hDevMemHeap = IMG_NULL;
+ IMG_SIZE_T ui32ByteSize;
+ IMG_SIZE_T ui32Offset;
+ IMG_SIZE_T ui32PageSize = HOST_PAGESIZE();
+ BM_HANDLE hBuffer;
+ PVRSRV_MEMBLK *psMemBlock;
+ IMG_BOOL bBMError;
+ IMG_UINT32 i;
+ PVRSRV_DC_MAPINFO *psDCMapInfo = IMG_NULL;
+
+ if(!hDeviceClassBuffer || !ppsMemInfo || !phOSMapInfo || !hDevMemContext)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DC_MAPINFO),
+ (IMG_VOID **)&psDCMapInfo, IMG_NULL,
+ "PVRSRV_DC_MAPINFO") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: Failed to alloc memory for psDCMapInfo"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ OSMemSet(psDCMapInfo, 0, sizeof(PVRSRV_DC_MAPINFO));
+
+ psDeviceClassBuffer = (PVRSRV_DEVICECLASS_BUFFER*)hDeviceClassBuffer;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ eError = psDeviceClassBuffer->pfnGetBufferAddr(psDeviceClassBuffer->hExtDevice,
+ psDeviceClassBuffer->hExtBuffer,
+ &psSysPAddr,
+ &ui32ByteSize,
+ &pvCPUVAddr,
+ phOSMapInfo,
+ &bPhysContig,
+ &psDCMapInfo->ui32TilingStride);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: unable to get buffer address"));
+ goto ErrorExitPhase1;
+ }
+
+
+ psBMContext = (BM_CONTEXT*)psDeviceClassBuffer->hDevMemContext;
+ psDeviceNode = psBMContext->psDeviceNode;
+ psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+ psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
+ for(i=0; i<PVRSRV_MAX_CLIENT_HEAPS; i++)
+ {
+ if(HEAP_IDX(psDeviceMemoryHeap[i].ui32HeapID) == psDevMemoryInfo->ui32MappingHeapID)
+ {
+ if(psDeviceMemoryHeap[i].DevMemHeapType == DEVICE_MEMORY_HEAP_PERCONTEXT)
+ {
+
+ hDevMemHeap = BM_CreateHeap(hDevMemContext, &psDeviceMemoryHeap[i]);
+ }
+ else
+ {
+ hDevMemHeap = psDevMemoryInfo->psDeviceMemoryHeap[i].hDevMemHeap;
+ }
+ break;
+ }
+ }
+
+ if(hDevMemHeap == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: unable to find mapping heap"));
+ eError = PVRSRV_ERROR_UNABLE_TO_FIND_RESOURCE;
+ goto ErrorExitPhase1;
+ }
+
+
+ ui32Offset = ((IMG_UINTPTR_T)pvCPUVAddr) & (ui32PageSize - 1);
+ pvPageAlignedCPUVAddr = (IMG_VOID *)((IMG_UINTPTR_T)pvCPUVAddr - ui32Offset);
+
+ eError = OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(PVRSRV_KERNEL_MEM_INFO),
+ (IMG_VOID **)&psMemInfo, IMG_NULL,
+ "Kernel Memory Info");
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: Failed to alloc memory for block"));
+ goto ErrorExitPhase1;
+ }
+
+ OSMemSet(psMemInfo, 0, sizeof(*psMemInfo));
+
+ psMemBlock = &(psMemInfo->sMemBlk);
+
+ bBMError = BM_Wrap(hDevMemHeap,
+ ui32ByteSize,
+ ui32Offset,
+ bPhysContig,
+ psSysPAddr,
+ pvPageAlignedCPUVAddr,
+ &psMemInfo->ui32Flags,
+ &hBuffer);
+
+ if (!bBMError)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: BM_Wrap Failed"));
+
+ eError = PVRSRV_ERROR_BAD_MAPPING;
+ goto ErrorExitPhase2;
+ }
+
+
+ psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
+ psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
+
+
+ psMemBlock->hBuffer = (IMG_HANDLE)hBuffer;
+
+
+
+ psMemInfo->pvLinAddrKM = BM_HandleToCpuVaddr(hBuffer);
+
+
+ psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
+ psMemInfo->ui32AllocSize = ui32ByteSize;
+ psMemInfo->psKernelSyncInfo = psDeviceClassBuffer->psKernelSyncInfo;
+
+
+
+ psMemInfo->pvSysBackupBuffer = IMG_NULL;
+
+
+ psDCMapInfo->psMemInfo = psMemInfo;
+
+#if defined(SUPPORT_MEMORY_TILING)
+ psDCMapInfo->psDeviceNode = psDeviceNode;
+
+ if(psDCMapInfo->ui32TilingStride > 0)
+ {
+
+ eError = psDeviceNode->pfnAllocMemTilingRange(psDeviceNode,
+ psMemInfo,
+ psDCMapInfo->ui32TilingStride,
+ &psDCMapInfo->ui32RangeIndex);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: AllocMemTilingRange failed"));
+ goto ErrorExitPhase3;
+ }
+ }
+#endif
+
+
+ psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_DEVICECLASSMEM_MAPPING,
+ psDCMapInfo,
+ 0,
+ &UnmapDeviceClassMemoryCallBack);
+
+ psMemInfo->ui32RefCount++;
+
+ psMemInfo->memType = PVRSRV_MEMTYPE_DEVICECLASS;
+
+
+ *ppsMemInfo = psMemInfo;
+
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+
+ PDUMPCOMMENT("Dump display surface");
+ PDUMPMEM(IMG_NULL, psMemInfo, ui32Offset, psMemInfo->ui32AllocSize, PDUMP_FLAGS_CONTINUOUS, ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping);
+#endif
+ return PVRSRV_OK;
+
+#if defined(SUPPORT_MEMORY_TILING)
+ErrorExitPhase3:
+ if(psMemInfo)
+ {
+ FreeDeviceMem(psMemInfo);
+
+
+
+ psMemInfo = IMG_NULL;
+ }
+#endif
+
+ErrorExitPhase2:
+ if(psMemInfo)
+ {
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
+ }
+
+ErrorExitPhase1:
+ if(psDCMapInfo)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_MEM_INFO), psDCMapInfo, IMG_NULL);
+ }
+
+ return eError;
+}
+
+#if defined(PVRSRV_RESOURCE_PROFILING)
+PVRSRV_KERNEL_MEM_INFO* PVRSRVGetMapMemInfo(IMG_VOID *psMap)
+{
+ RESMAN_MAP_DEVICE_MEM_DATA *psMapData = psMap;
+ if (psMapData)
+ return psMapData->psMemInfo;
+ else
+ return IMG_NULL;
+}
+#endif
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifdef PVR_SECURE_HANDLES
+#include <stddef.h>
+
+#include "services_headers.h"
+#include "handle.h"
+
+#ifdef DEBUG
+#define HANDLE_BLOCK_SHIFT 2
+#else
+#define HANDLE_BLOCK_SHIFT 8
+#endif
+
+#define DIVIDE_BY_BLOCK_SIZE(i) (((IMG_UINT32)(i)) >> HANDLE_BLOCK_SHIFT)
+#define MULTIPLY_BY_BLOCK_SIZE(i) (((IMG_UINT32)(i)) << HANDLE_BLOCK_SHIFT)
+
+#define HANDLE_BLOCK_SIZE MULTIPLY_BY_BLOCK_SIZE(1)
+#define HANDLE_SUB_BLOCK_MASK (HANDLE_BLOCK_SIZE - 1)
+#define HANDLE_BLOCK_MASK (~(HANDLE_SUB_BLOCK_MASK))
+
+#define HANDLE_HASH_TAB_INIT_SIZE 32
+
+#define INDEX_IS_VALID(psBase, i) ((i) < (psBase)->ui32TotalHandCount)
+
+#define INDEX_TO_HANDLE(i) ((IMG_HANDLE)((i) + 1))
+#define HANDLE_TO_INDEX(h) ((IMG_UINT32)(h) - 1)
+
+#define INDEX_TO_BLOCK_INDEX(i) DIVIDE_BY_BLOCK_SIZE(i)
+#define BLOCK_INDEX_TO_INDEX(i) MULTIPLY_BY_BLOCK_SIZE(i)
+#define INDEX_TO_SUB_BLOCK_INDEX(i) ((i) & HANDLE_SUB_BLOCK_MASK)
+
+#define INDEX_TO_INDEX_STRUCT_PTR(psArray, i) (&((psArray)[INDEX_TO_BLOCK_INDEX(i)]))
+#define BASE_AND_INDEX_TO_INDEX_STRUCT_PTR(psBase, i) INDEX_TO_INDEX_STRUCT_PTR((psBase)->psHandleArray, i)
+
+#define INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, i) (BASE_AND_INDEX_TO_INDEX_STRUCT_PTR(psBase, i)->ui32FreeHandBlockCount)
+
+#define INDEX_TO_HANDLE_STRUCT_PTR(psBase, i) (BASE_AND_INDEX_TO_INDEX_STRUCT_PTR(psBase, i)->psHandle + INDEX_TO_SUB_BLOCK_INDEX(i))
+
+#define HANDLE_TO_HANDLE_STRUCT_PTR(psBase, h) (INDEX_TO_HANDLE_STRUCT_PTR(psBase, HANDLE_TO_INDEX(h)))
+
+#define HANDLE_PTR_TO_INDEX(psHandle) ((psHandle)->ui32Index)
+#define HANDLE_PTR_TO_HANDLE(psHandle) INDEX_TO_HANDLE(HANDLE_PTR_TO_INDEX(psHandle))
+
+#define ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE(a) (HANDLE_BLOCK_MASK & (a))
+#define ROUND_UP_TO_MULTIPLE_OF_BLOCK_SIZE(a) ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE((a) + HANDLE_BLOCK_SIZE - 1)
+
+#define DEFAULT_MAX_HANDLE 0x7fffffffu
+#define DEFAULT_MAX_INDEX_PLUS_ONE ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE(DEFAULT_MAX_HANDLE)
+
+#define HANDLES_BATCHED(psBase) ((psBase)->ui32HandBatchSize != 0)
+
+#define HANDLE_ARRAY_SIZE(handleCount) DIVIDE_BY_BLOCK_SIZE(ROUND_UP_TO_MULTIPLE_OF_BLOCK_SIZE(handleCount))
+
+#define SET_FLAG(v, f) ((IMG_VOID)((v) |= (f)))
+#define CLEAR_FLAG(v, f) ((IMG_VOID)((v) &= ~(f)))
+#define TEST_FLAG(v, f) ((IMG_BOOL)(((v) & (f)) != 0))
+
+#define TEST_ALLOC_FLAG(psHandle, f) TEST_FLAG((psHandle)->eFlag, f)
+
+#define SET_INTERNAL_FLAG(psHandle, f) SET_FLAG((psHandle)->eInternalFlag, f)
+#define CLEAR_INTERNAL_FLAG(psHandle, f) CLEAR_FLAG((psHandle)->eInternalFlag, f)
+#define TEST_INTERNAL_FLAG(psHandle, f) TEST_FLAG((psHandle)->eInternalFlag, f)
+
+#define BATCHED_HANDLE(psHandle) TEST_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED)
+
+#define SET_BATCHED_HANDLE(psHandle) SET_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED)
+
+#define SET_UNBATCHED_HANDLE(psHandle) CLEAR_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED)
+
+#define BATCHED_HANDLE_PARTIALLY_FREE(psHandle) TEST_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED_PARTIALLY_FREE)
+
+#define SET_BATCHED_HANDLE_PARTIALLY_FREE(psHandle) SET_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED_PARTIALLY_FREE)
+
+#define HANDLE_STRUCT_IS_FREE(psHandle) ((psHandle)->eType == PVRSRV_HANDLE_TYPE_NONE && (psHandle)->eInternalFlag == INTERNAL_HANDLE_FLAG_NONE)
+
+#ifdef MIN
+#undef MIN
+#endif
+
+#define MIN(x, y) (((x) < (y)) ? (x) : (y))
+
+struct sHandleList
+{
+ IMG_UINT32 ui32Prev;
+ IMG_UINT32 ui32Next;
+ IMG_HANDLE hParent;
+};
+
+enum ePVRSRVInternalHandleFlag
+{
+ INTERNAL_HANDLE_FLAG_NONE = 0x00,
+ INTERNAL_HANDLE_FLAG_BATCHED = 0x01,
+ INTERNAL_HANDLE_FLAG_BATCHED_PARTIALLY_FREE = 0x02,
+};
+
+struct sHandle
+{
+
+ PVRSRV_HANDLE_TYPE eType;
+
+
+ IMG_VOID *pvData;
+
+
+ IMG_UINT32 ui32NextIndexPlusOne;
+
+
+ enum ePVRSRVInternalHandleFlag eInternalFlag;
+
+
+ PVRSRV_HANDLE_ALLOC_FLAG eFlag;
+
+
+ IMG_UINT32 ui32Index;
+
+
+ struct sHandleList sChildren;
+
+
+ struct sHandleList sSiblings;
+};
+
+struct sHandleIndex
+{
+
+ struct sHandle *psHandle;
+
+
+ IMG_HANDLE hBlockAlloc;
+
+
+ IMG_UINT32 ui32FreeHandBlockCount;
+};
+
+struct _PVRSRV_HANDLE_BASE_
+{
+
+ IMG_HANDLE hBaseBlockAlloc;
+
+
+ IMG_HANDLE hArrayBlockAlloc;
+
+
+ struct sHandleIndex *psHandleArray;
+
+
+ HASH_TABLE *psHashTab;
+
+
+ IMG_UINT32 ui32FreeHandCount;
+
+
+ IMG_UINT32 ui32FirstFreeIndex;
+
+
+ IMG_UINT32 ui32MaxIndexPlusOne;
+
+
+ IMG_UINT32 ui32TotalHandCount;
+
+
+ IMG_UINT32 ui32LastFreeIndexPlusOne;
+
+
+ IMG_UINT32 ui32HandBatchSize;
+
+
+ IMG_UINT32 ui32TotalHandCountPreBatch;
+
+
+ IMG_UINT32 ui32FirstBatchIndexPlusOne;
+
+
+ IMG_UINT32 ui32BatchHandAllocFailures;
+
+
+ IMG_BOOL bPurgingEnabled;
+};
+
+enum eHandKey {
+ HAND_KEY_DATA = 0,
+ HAND_KEY_TYPE,
+ HAND_KEY_PARENT,
+ HAND_KEY_LEN
+};
+
+PVRSRV_HANDLE_BASE *gpsKernelHandleBase = IMG_NULL;
+
+typedef IMG_UINTPTR_T HAND_KEY[HAND_KEY_LEN];
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(HandleListInit)
+#endif
+static INLINE
+IMG_VOID HandleListInit(IMG_UINT32 ui32Index, struct sHandleList *psList, IMG_HANDLE hParent)
+{
+ psList->ui32Next = ui32Index;
+ psList->ui32Prev = ui32Index;
+ psList->hParent = hParent;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(InitParentList)
+#endif
+static INLINE
+IMG_VOID InitParentList(struct sHandle *psHandle)
+{
+ IMG_UINT32 ui32Parent = HANDLE_PTR_TO_INDEX(psHandle);
+
+ HandleListInit(ui32Parent, &psHandle->sChildren, INDEX_TO_HANDLE(ui32Parent));
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(InitChildEntry)
+#endif
+static INLINE
+IMG_VOID InitChildEntry(struct sHandle *psHandle)
+{
+ HandleListInit(HANDLE_PTR_TO_INDEX(psHandle), &psHandle->sSiblings, IMG_NULL);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(HandleListIsEmpty)
+#endif
+static INLINE
+IMG_BOOL HandleListIsEmpty(IMG_UINT32 ui32Index, struct sHandleList *psList)
+{
+ IMG_BOOL bIsEmpty;
+
+ bIsEmpty = (IMG_BOOL)(psList->ui32Next == ui32Index);
+
+#ifdef DEBUG
+ {
+ IMG_BOOL bIsEmpty2;
+
+ bIsEmpty2 = (IMG_BOOL)(psList->ui32Prev == ui32Index);
+ PVR_ASSERT(bIsEmpty == bIsEmpty2);
+ }
+#endif
+
+ return bIsEmpty;
+}
+
+#ifdef DEBUG
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(NoChildren)
+#endif
+static INLINE
+IMG_BOOL NoChildren(struct sHandle *psHandle)
+{
+ PVR_ASSERT(psHandle->sChildren.hParent == HANDLE_PTR_TO_HANDLE(psHandle));
+
+ return HandleListIsEmpty(HANDLE_PTR_TO_INDEX(psHandle), &psHandle->sChildren);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(NoParent)
+#endif
+static INLINE
+IMG_BOOL NoParent(struct sHandle *psHandle)
+{
+ if (HandleListIsEmpty(HANDLE_PTR_TO_INDEX(psHandle), &psHandle->sSiblings))
+ {
+ PVR_ASSERT(psHandle->sSiblings.hParent == IMG_NULL);
+
+ return IMG_TRUE;
+ }
+ else
+ {
+ PVR_ASSERT(psHandle->sSiblings.hParent != IMG_NULL);
+ }
+ return IMG_FALSE;
+}
+#endif
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(ParentHandle)
+#endif
+static INLINE
+IMG_HANDLE ParentHandle(struct sHandle *psHandle)
+{
+ return psHandle->sSiblings.hParent;
+}
+
+#define LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, i, p, po, eo) \
+ ((struct sHandleList *)((IMG_CHAR *)(INDEX_TO_HANDLE_STRUCT_PTR(psBase, i)) + (((i) == (p)) ? (po) : (eo))))
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(HandleListInsertBefore)
+#endif
+static INLINE
+IMG_VOID HandleListInsertBefore(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32InsIndex, struct sHandleList *psIns, IMG_SIZE_T uiParentOffset, IMG_UINT32 ui32EntryIndex, struct sHandleList *psEntry, IMG_SIZE_T uiEntryOffset, IMG_UINT32 ui32ParentIndex)
+{
+
+ struct sHandleList *psPrevIns = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psIns->ui32Prev, ui32ParentIndex, uiParentOffset, uiEntryOffset);
+
+ PVR_ASSERT(psEntry->hParent == IMG_NULL);
+ PVR_ASSERT(ui32InsIndex == psPrevIns->ui32Next);
+ PVR_ASSERT(LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, ui32ParentIndex, ui32ParentIndex, uiParentOffset, uiParentOffset)->hParent == INDEX_TO_HANDLE(ui32ParentIndex));
+
+ psEntry->ui32Prev = psIns->ui32Prev;
+ psIns->ui32Prev = ui32EntryIndex;
+ psEntry->ui32Next = ui32InsIndex;
+ psPrevIns->ui32Next = ui32EntryIndex;
+
+ psEntry->hParent = INDEX_TO_HANDLE(ui32ParentIndex);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(AdoptChild)
+#endif
+static INLINE
+IMG_VOID AdoptChild(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psParent, struct sHandle *psChild)
+{
+ IMG_UINT32 ui32Parent = HANDLE_TO_INDEX(psParent->sChildren.hParent);
+
+ PVR_ASSERT(ui32Parent == HANDLE_PTR_TO_INDEX(psParent));
+
+ HandleListInsertBefore(psBase, ui32Parent, &psParent->sChildren, offsetof(struct sHandle, sChildren), HANDLE_PTR_TO_INDEX(psChild), &psChild->sSiblings, offsetof(struct sHandle, sSiblings), ui32Parent);
+
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(HandleListRemove)
+#endif
+static INLINE
+IMG_VOID HandleListRemove(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32EntryIndex, struct sHandleList *psEntry, IMG_SIZE_T uiEntryOffset, IMG_SIZE_T uiParentOffset)
+{
+ if (!HandleListIsEmpty(ui32EntryIndex, psEntry))
+ {
+
+ struct sHandleList *psPrev = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psEntry->ui32Prev, HANDLE_TO_INDEX(psEntry->hParent), uiParentOffset, uiEntryOffset);
+ struct sHandleList *psNext = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psEntry->ui32Next, HANDLE_TO_INDEX(psEntry->hParent), uiParentOffset, uiEntryOffset);
+
+
+ PVR_ASSERT(psEntry->hParent != IMG_NULL);
+
+ psPrev->ui32Next = psEntry->ui32Next;
+ psNext->ui32Prev = psEntry->ui32Prev;
+
+ HandleListInit(ui32EntryIndex, psEntry, IMG_NULL);
+ }
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(UnlinkFromParent)
+#endif
+static INLINE
+IMG_VOID UnlinkFromParent(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHandle)
+{
+ HandleListRemove(psBase, HANDLE_PTR_TO_INDEX(psHandle), &psHandle->sSiblings, offsetof(struct sHandle, sSiblings), offsetof(struct sHandle, sChildren));
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(HandleListIterate)
+#endif
+static INLINE
+PVRSRV_ERROR HandleListIterate(PVRSRV_HANDLE_BASE *psBase, struct sHandleList *psHead, IMG_SIZE_T uiParentOffset, IMG_SIZE_T uiEntryOffset, PVRSRV_ERROR (*pfnIterFunc)(PVRSRV_HANDLE_BASE *, struct sHandle *))
+{
+ IMG_UINT32 ui32Index;
+ IMG_UINT32 ui32Parent = HANDLE_TO_INDEX(psHead->hParent);
+
+ PVR_ASSERT(psHead->hParent != IMG_NULL);
+
+
+ for(ui32Index = psHead->ui32Next; ui32Index != ui32Parent; )
+ {
+ struct sHandle *psHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, ui32Index);
+
+ struct sHandleList *psEntry = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, ui32Index, ui32Parent, uiParentOffset, uiEntryOffset);
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(psEntry->hParent == psHead->hParent);
+
+ ui32Index = psEntry->ui32Next;
+
+ eError = (*pfnIterFunc)(psBase, psHandle);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(IterateOverChildren)
+#endif
+static INLINE
+PVRSRV_ERROR IterateOverChildren(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psParent, PVRSRV_ERROR (*pfnIterFunc)(PVRSRV_HANDLE_BASE *, struct sHandle *))
+{
+ return HandleListIterate(psBase, &psParent->sChildren, offsetof(struct sHandle, sChildren), offsetof(struct sHandle, sSiblings), pfnIterFunc);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(GetHandleStructure)
+#endif
+static INLINE
+PVRSRV_ERROR GetHandleStructure(PVRSRV_HANDLE_BASE *psBase, struct sHandle **ppsHandle, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+ IMG_UINT32 ui32Index = HANDLE_TO_INDEX(hHandle);
+ struct sHandle *psHandle;
+
+
+ if (!INDEX_IS_VALID(psBase, ui32Index))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "GetHandleStructure: Handle index out of range (%u >= %u)", ui32Index, psBase->ui32TotalHandCount));
+ return PVRSRV_ERROR_HANDLE_INDEX_OUT_OF_RANGE;
+ }
+
+ psHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, ui32Index);
+ if (psHandle->eType == PVRSRV_HANDLE_TYPE_NONE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "GetHandleStructure: Handle not allocated (index: %u)", ui32Index));
+ return PVRSRV_ERROR_HANDLE_NOT_ALLOCATED;
+ }
+
+
+ if (eType != PVRSRV_HANDLE_TYPE_NONE && eType != psHandle->eType)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "GetHandleStructure: Handle type mismatch (%d != %d)", eType, psHandle->eType));
+ return PVRSRV_ERROR_HANDLE_TYPE_MISMATCH;
+ }
+
+
+ *ppsHandle = psHandle;
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(ParentIfPrivate)
+#endif
+static INLINE
+IMG_HANDLE ParentIfPrivate(struct sHandle *psHandle)
+{
+ return TEST_ALLOC_FLAG(psHandle, PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE) ?
+ ParentHandle(psHandle) : IMG_NULL;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(InitKey)
+#endif
+static INLINE
+IMG_VOID InitKey(HAND_KEY aKey, PVRSRV_HANDLE_BASE *psBase, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hParent)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ aKey[HAND_KEY_DATA] = (IMG_UINTPTR_T)pvData;
+ aKey[HAND_KEY_TYPE] = (IMG_UINTPTR_T)eType;
+ aKey[HAND_KEY_PARENT] = (IMG_UINTPTR_T)hParent;
+}
+
+static
+PVRSRV_ERROR ReallocHandleArray(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32NewCount)
+{
+ struct sHandleIndex *psOldArray = psBase->psHandleArray;
+ IMG_HANDLE hOldArrayBlockAlloc = psBase->hArrayBlockAlloc;
+ IMG_UINT32 ui32OldCount = psBase->ui32TotalHandCount;
+ struct sHandleIndex *psNewArray = IMG_NULL;
+ IMG_HANDLE hNewArrayBlockAlloc = IMG_NULL;
+ PVRSRV_ERROR eError;
+ PVRSRV_ERROR eReturn = PVRSRV_OK;
+ IMG_UINT32 ui32Index;
+
+ if (ui32NewCount == ui32OldCount)
+ {
+ return PVRSRV_OK;
+ }
+
+ if (ui32NewCount != 0 && !psBase->bPurgingEnabled &&
+ ui32NewCount < ui32OldCount)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if (((ui32OldCount % HANDLE_BLOCK_SIZE) != 0) ||
+ ((ui32NewCount % HANDLE_BLOCK_SIZE) != 0))
+ {
+ PVR_ASSERT((ui32OldCount % HANDLE_BLOCK_SIZE) == 0);
+ PVR_ASSERT((ui32NewCount % HANDLE_BLOCK_SIZE) == 0);
+
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if (ui32NewCount != 0)
+ {
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ HANDLE_ARRAY_SIZE(ui32NewCount) * sizeof(struct sHandleIndex),
+ (IMG_VOID **)&psNewArray,
+ &hNewArrayBlockAlloc,
+ "Memory Area");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Couldn't allocate new handle array (%d)", eError));
+ eReturn = eError;
+ goto error;
+ }
+
+ if (ui32OldCount != 0)
+ {
+ OSMemCopy(psNewArray, psOldArray, HANDLE_ARRAY_SIZE(MIN(ui32NewCount, ui32OldCount)) * sizeof(struct sHandleIndex));
+ }
+ }
+
+
+ for(ui32Index = ui32NewCount; ui32Index < ui32OldCount; ui32Index += HANDLE_BLOCK_SIZE)
+ {
+ struct sHandleIndex *psIndex = INDEX_TO_INDEX_STRUCT_PTR(psOldArray, ui32Index);
+
+ eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct sHandle) * HANDLE_BLOCK_SIZE,
+ psIndex->psHandle,
+ psIndex->hBlockAlloc);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Couldn't free handle structures (%d)", eError));
+ }
+ }
+
+
+ for(ui32Index = ui32OldCount; ui32Index < ui32NewCount; ui32Index += HANDLE_BLOCK_SIZE)
+ {
+
+ struct sHandleIndex *psIndex = INDEX_TO_INDEX_STRUCT_PTR(psNewArray, ui32Index);
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct sHandle) * HANDLE_BLOCK_SIZE,
+ (IMG_VOID **)&psIndex->psHandle,
+ &psIndex->hBlockAlloc,
+ "Memory Area");
+ if (eError != PVRSRV_OK)
+ {
+ psIndex->psHandle = IMG_NULL;
+ PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Couldn't allocate handle structures (%d)", eError));
+ eReturn = eError;
+ }
+ else
+ {
+ IMG_UINT32 ui32SubIndex;
+
+ psIndex->ui32FreeHandBlockCount = HANDLE_BLOCK_SIZE;
+
+ for(ui32SubIndex = 0; ui32SubIndex < HANDLE_BLOCK_SIZE; ui32SubIndex++)
+ {
+ struct sHandle *psHandle = psIndex->psHandle + ui32SubIndex;
+
+
+ psHandle->ui32Index = ui32SubIndex + ui32Index;
+ psHandle->eType = PVRSRV_HANDLE_TYPE_NONE;
+ psHandle->eInternalFlag = INTERNAL_HANDLE_FLAG_NONE;
+ psHandle->ui32NextIndexPlusOne = 0;
+ }
+ }
+ }
+ if (eReturn != PVRSRV_OK)
+ {
+ goto error;
+ }
+
+#ifdef DEBUG_MAX_HANDLE_COUNT
+
+ if (ui32NewCount > DEBUG_MAX_HANDLE_COUNT)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Max handle count (%u) reached", DEBUG_MAX_HANDLE_COUNT));
+ eReturn = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto error;
+ }
+#endif
+
+ if (psOldArray != IMG_NULL)
+ {
+
+ eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ HANDLE_ARRAY_SIZE(ui32OldCount) * sizeof(struct sHandleIndex),
+ psOldArray,
+ hOldArrayBlockAlloc);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Couldn't free old handle array (%d)", eError));
+ }
+ }
+
+ psBase->psHandleArray = psNewArray;
+ psBase->hArrayBlockAlloc = hNewArrayBlockAlloc;
+ psBase->ui32TotalHandCount = ui32NewCount;
+
+ if (ui32NewCount > ui32OldCount)
+ {
+
+ PVR_ASSERT(psBase->ui32FreeHandCount + (ui32NewCount - ui32OldCount) > psBase->ui32FreeHandCount)
+
+
+ psBase->ui32FreeHandCount += (ui32NewCount - ui32OldCount);
+
+
+ if (psBase->ui32FirstFreeIndex == 0)
+ {
+ PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == 0)
+
+ psBase->ui32FirstFreeIndex = ui32OldCount;
+ }
+ else
+ {
+ if (!psBase->bPurgingEnabled)
+ {
+ PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne != 0)
+ PVR_ASSERT(INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne == 0)
+
+ INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne = ui32OldCount + 1;
+ }
+ }
+
+ if (!psBase->bPurgingEnabled)
+ {
+ psBase->ui32LastFreeIndexPlusOne = ui32NewCount;
+ }
+ }
+ else
+ {
+ PVR_ASSERT(ui32NewCount == 0 || psBase->bPurgingEnabled)
+ PVR_ASSERT(ui32NewCount == 0 || psBase->ui32FirstFreeIndex <= ui32NewCount)
+ PVR_ASSERT(psBase->ui32FreeHandCount - (ui32OldCount - ui32NewCount) < psBase->ui32FreeHandCount)
+
+
+ psBase->ui32FreeHandCount -= (ui32OldCount - ui32NewCount);
+
+ if (ui32NewCount == 0)
+ {
+ psBase->ui32FirstFreeIndex = 0;
+ psBase->ui32LastFreeIndexPlusOne = 0;
+ }
+ }
+
+ PVR_ASSERT(psBase->ui32FirstFreeIndex <= psBase->ui32TotalHandCount);
+
+ return PVRSRV_OK;
+
+error:
+ PVR_ASSERT(eReturn != PVRSRV_OK);
+
+ if (psNewArray != IMG_NULL)
+ {
+
+ for(ui32Index = ui32OldCount; ui32Index < ui32NewCount; ui32Index += HANDLE_BLOCK_SIZE)
+ {
+ struct sHandleIndex *psIndex = INDEX_TO_INDEX_STRUCT_PTR(psNewArray, ui32Index);
+ if (psIndex->psHandle != IMG_NULL)
+ {
+ eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct sHandle) * HANDLE_BLOCK_SIZE,
+ psIndex->psHandle,
+ psIndex->hBlockAlloc);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Couldn't free handle structures (%d)", eError));
+ }
+ }
+ }
+
+
+ eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ HANDLE_ARRAY_SIZE(ui32NewCount) * sizeof(struct sHandleIndex),
+ psNewArray,
+ hNewArrayBlockAlloc);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Couldn't free new handle array (%d)", eError));
+ }
+ }
+
+ return eReturn;
+}
+
+static PVRSRV_ERROR FreeHandleArray(PVRSRV_HANDLE_BASE *psBase)
+{
+ return ReallocHandleArray(psBase, 0);
+}
+
+static PVRSRV_ERROR FreeHandle(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHandle)
+{
+ HAND_KEY aKey;
+ IMG_UINT32 ui32Index = HANDLE_PTR_TO_INDEX(psHandle);
+ PVRSRV_ERROR eError;
+
+
+ InitKey(aKey, psBase, psHandle->pvData, psHandle->eType, ParentIfPrivate(psHandle));
+
+ if (!TEST_ALLOC_FLAG(psHandle, PVRSRV_HANDLE_ALLOC_FLAG_MULTI) && !BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
+ {
+ IMG_HANDLE hHandle;
+ hHandle = (IMG_HANDLE) HASH_Remove_Extended(psBase->psHashTab, aKey);
+
+ PVR_ASSERT(hHandle != IMG_NULL);
+ PVR_ASSERT(hHandle == INDEX_TO_HANDLE(ui32Index));
+ PVR_UNREFERENCED_PARAMETER(hHandle);
+ }
+
+
+ UnlinkFromParent(psBase, psHandle);
+
+
+ eError = IterateOverChildren(psBase, psHandle, FreeHandle);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeHandle: Error whilst freeing subhandles (%d)", eError));
+ return eError;
+ }
+
+
+ psHandle->eType = PVRSRV_HANDLE_TYPE_NONE;
+
+ if (BATCHED_HANDLE(psHandle) && !BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
+ {
+
+ SET_BATCHED_HANDLE_PARTIALLY_FREE(psHandle);
+
+ return PVRSRV_OK;
+ }
+
+
+ if (!psBase->bPurgingEnabled)
+ {
+ if (psBase->ui32FreeHandCount == 0)
+ {
+ PVR_ASSERT(psBase->ui32FirstFreeIndex == 0);
+ PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == 0);
+
+ psBase->ui32FirstFreeIndex = ui32Index;
+ }
+ else
+ {
+
+ PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne != 0);
+ PVR_ASSERT(INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne == 0);
+ INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne = ui32Index + 1;
+ }
+
+ PVR_ASSERT(psHandle->ui32NextIndexPlusOne == 0);
+
+
+ psBase->ui32LastFreeIndexPlusOne = ui32Index + 1;
+ }
+
+ psBase->ui32FreeHandCount++;
+ INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32Index)++;
+
+ PVR_ASSERT(INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32Index)<= HANDLE_BLOCK_SIZE);
+
+#ifdef DEBUG
+ {
+ IMG_UINT32 ui32BlockedIndex;
+ IMG_UINT32 ui32FreeHandCount = 0;
+
+ for (ui32BlockedIndex = 0; ui32BlockedIndex < psBase->ui32TotalHandCount; ui32BlockedIndex += HANDLE_BLOCK_SIZE)
+ {
+ ui32FreeHandCount += INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32BlockedIndex);
+ }
+
+ PVR_ASSERT(ui32FreeHandCount == psBase->ui32FreeHandCount);
+ }
+#endif
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR FreeAllHandles(PVRSRV_HANDLE_BASE *psBase)
+{
+ IMG_UINT32 i;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if (psBase->ui32FreeHandCount == psBase->ui32TotalHandCount)
+ {
+ return eError;
+ }
+
+ for (i = 0; i < psBase->ui32TotalHandCount; i++)
+ {
+ struct sHandle *psHandle;
+
+ psHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, i);
+
+ if (psHandle->eType != PVRSRV_HANDLE_TYPE_NONE)
+ {
+ eError = FreeHandle(psBase, psHandle);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeAllHandles: FreeHandle failed (%d)", eError));
+ break;
+ }
+
+
+ if (psBase->ui32FreeHandCount == psBase->ui32TotalHandCount)
+ {
+ break;
+ }
+ }
+ }
+
+ return eError;
+}
+
+static PVRSRV_ERROR FreeHandleBase(PVRSRV_HANDLE_BASE *psBase)
+{
+ PVRSRV_ERROR eError;
+
+ if (HANDLES_BATCHED(psBase))
+ {
+ PVR_DPF((PVR_DBG_WARNING, "FreeHandleBase: Uncommitted/Unreleased handle batch"));
+ PVRSRVReleaseHandleBatch(psBase);
+ }
+
+
+ eError = FreeAllHandles(psBase);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeHandleBase: Couldn't free handles (%d)", eError));
+ return eError;
+ }
+
+
+ eError = FreeHandleArray(psBase);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeHandleBase: Couldn't free handle array (%d)", eError));
+ return eError;
+ }
+
+ if (psBase->psHashTab != IMG_NULL)
+ {
+
+ HASH_Delete(psBase->psHashTab);
+ }
+
+ eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(*psBase),
+ psBase,
+ psBase->hBaseBlockAlloc);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeHandleBase: Couldn't free handle base (%d)", eError));
+ return eError;
+ }
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(FindHandle)
+#endif
+static INLINE
+IMG_HANDLE FindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hParent)
+{
+ HAND_KEY aKey;
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+ InitKey(aKey, psBase, pvData, eType, hParent);
+
+ return (IMG_HANDLE) HASH_Retrieve_Extended(psBase->psHashTab, aKey);
+}
+
+static PVRSRV_ERROR IncreaseHandleArraySize(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32Delta)
+{
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32DeltaAdjusted = ROUND_UP_TO_MULTIPLE_OF_BLOCK_SIZE(ui32Delta);
+ IMG_UINT32 ui32NewTotalHandCount = psBase->ui32TotalHandCount + ui32DeltaAdjusted;
+;
+
+ PVR_ASSERT(ui32Delta != 0);
+
+
+ if (ui32NewTotalHandCount > psBase->ui32MaxIndexPlusOne || ui32NewTotalHandCount <= psBase->ui32TotalHandCount)
+ {
+ ui32NewTotalHandCount = psBase->ui32MaxIndexPlusOne;
+
+ ui32DeltaAdjusted = ui32NewTotalHandCount - psBase->ui32TotalHandCount;
+
+ if (ui32DeltaAdjusted < ui32Delta)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "IncreaseHandleArraySize: Maximum handle limit reached (%d)", psBase->ui32MaxIndexPlusOne));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ }
+
+ PVR_ASSERT(ui32DeltaAdjusted >= ui32Delta);
+
+
+ eError = ReallocHandleArray(psBase, ui32NewTotalHandCount);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "IncreaseHandleArraySize: ReallocHandleArray failed (%d)", eError));
+ return eError;
+ }
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR EnsureFreeHandles(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32Free)
+{
+ PVRSRV_ERROR eError;
+
+ if (ui32Free > psBase->ui32FreeHandCount)
+ {
+ IMG_UINT32 ui32FreeHandDelta = ui32Free - psBase->ui32FreeHandCount;
+ eError = IncreaseHandleArraySize(psBase, ui32FreeHandDelta);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "EnsureFreeHandles: Couldn't allocate %u handles to ensure %u free handles (IncreaseHandleArraySize failed with error %d)", ui32FreeHandDelta, ui32Free, eError));
+
+ return eError;
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR AllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_HANDLE hParent)
+{
+ IMG_UINT32 ui32NewIndex = DEFAULT_MAX_INDEX_PLUS_ONE;
+ struct sHandle *psNewHandle = IMG_NULL;
+ IMG_HANDLE hHandle;
+ HAND_KEY aKey;
+ PVRSRV_ERROR eError;
+
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+ PVR_ASSERT(psBase != IMG_NULL);
+ PVR_ASSERT(psBase->psHashTab != IMG_NULL);
+
+ if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
+ {
+
+ PVR_ASSERT(FindHandle(psBase, pvData, eType, hParent) == IMG_NULL);
+ }
+
+ if (psBase->ui32FreeHandCount == 0 && HANDLES_BATCHED(psBase))
+ {
+ PVR_DPF((PVR_DBG_WARNING, "AllocHandle: Handle batch size (%u) was too small, allocating additional space", psBase->ui32HandBatchSize));
+ }
+
+
+ eError = EnsureFreeHandles(psBase, 1);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "AllocHandle: EnsureFreeHandles failed (%d)", eError));
+ return eError;
+ }
+ PVR_ASSERT(psBase->ui32FreeHandCount != 0)
+
+ if (!psBase->bPurgingEnabled)
+ {
+
+ ui32NewIndex = psBase->ui32FirstFreeIndex;
+
+
+ psNewHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, ui32NewIndex);
+ }
+ else
+ {
+ IMG_UINT32 ui32BlockedIndex;
+
+
+
+ PVR_ASSERT((psBase->ui32FirstFreeIndex % HANDLE_BLOCK_SIZE) == 0);
+
+ for (ui32BlockedIndex = ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE(psBase->ui32FirstFreeIndex); ui32BlockedIndex < psBase->ui32TotalHandCount; ui32BlockedIndex += HANDLE_BLOCK_SIZE)
+ {
+ struct sHandleIndex *psIndex = BASE_AND_INDEX_TO_INDEX_STRUCT_PTR(psBase, ui32BlockedIndex);
+
+ if (psIndex->ui32FreeHandBlockCount == 0)
+ {
+ continue;
+ }
+
+ for (ui32NewIndex = ui32BlockedIndex; ui32NewIndex < ui32BlockedIndex + HANDLE_BLOCK_SIZE; ui32NewIndex++)
+ {
+ psNewHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, ui32NewIndex);
+ if (HANDLE_STRUCT_IS_FREE(psNewHandle))
+ {
+ break;
+ }
+ }
+ }
+ psBase->ui32FirstFreeIndex = 0;
+ PVR_ASSERT(ui32NewIndex < psBase->ui32TotalHandCount);
+ }
+ PVR_ASSERT(psNewHandle != IMG_NULL);
+
+
+ hHandle = INDEX_TO_HANDLE(ui32NewIndex);
+
+
+ if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
+ {
+
+ InitKey(aKey, psBase, pvData, eType, hParent);
+
+
+ if (!HASH_Insert_Extended(psBase->psHashTab, aKey, (IMG_UINTPTR_T)hHandle))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "AllocHandle: Couldn't add handle to hash table"));
+
+ return PVRSRV_ERROR_UNABLE_TO_ADD_HANDLE;
+ }
+ }
+
+ psBase->ui32FreeHandCount--;
+
+ PVR_ASSERT(INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32NewIndex) <= HANDLE_BLOCK_SIZE);
+ PVR_ASSERT(INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32NewIndex) > 0);
+
+ INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32NewIndex)--;
+
+
+ if (!psBase->bPurgingEnabled)
+ {
+
+ if (psBase->ui32FreeHandCount == 0)
+ {
+ PVR_ASSERT(psBase->ui32FirstFreeIndex == ui32NewIndex);
+ PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == (ui32NewIndex + 1));
+
+ psBase->ui32LastFreeIndexPlusOne = 0;
+ psBase->ui32FirstFreeIndex = 0;
+ }
+ else
+ {
+
+ psBase->ui32FirstFreeIndex = (psNewHandle->ui32NextIndexPlusOne == 0) ?
+ ui32NewIndex + 1 :
+ psNewHandle->ui32NextIndexPlusOne - 1;
+ }
+ }
+
+
+ PVR_ASSERT(psNewHandle->ui32Index == ui32NewIndex);
+
+
+ psNewHandle->eType = eType;
+ psNewHandle->pvData = pvData;
+ psNewHandle->eInternalFlag = INTERNAL_HANDLE_FLAG_NONE;
+ psNewHandle->eFlag = eFlag;
+
+ InitParentList(psNewHandle);
+#if defined(DEBUG)
+ PVR_ASSERT(NoChildren(psNewHandle));
+#endif
+
+ InitChildEntry(psNewHandle);
+#if defined(DEBUG)
+ PVR_ASSERT(NoParent(psNewHandle));
+#endif
+
+ if (HANDLES_BATCHED(psBase))
+ {
+
+ psNewHandle->ui32NextIndexPlusOne = psBase->ui32FirstBatchIndexPlusOne;
+
+ psBase->ui32FirstBatchIndexPlusOne = ui32NewIndex + 1;
+
+
+ SET_BATCHED_HANDLE(psNewHandle);
+ }
+ else
+ {
+ psNewHandle->ui32NextIndexPlusOne = 0;
+ }
+
+
+ *phHandle = hHandle;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag)
+{
+ IMG_HANDLE hHandle;
+ PVRSRV_ERROR eError;
+
+ *phHandle = IMG_NULL;
+
+ if (HANDLES_BATCHED(psBase))
+ {
+
+ psBase->ui32BatchHandAllocFailures++;
+ }
+
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+ if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
+ {
+
+ hHandle = FindHandle(psBase, pvData, eType, IMG_NULL);
+ if (hHandle != IMG_NULL)
+ {
+ struct sHandle *psHandle;
+
+ eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandle: Lookup of existing handle failed"));
+ return eError;
+ }
+
+
+ if (TEST_FLAG(psHandle->eFlag & eFlag, PVRSRV_HANDLE_ALLOC_FLAG_SHARED))
+ {
+ *phHandle = hHandle;
+ eError = PVRSRV_OK;
+ goto exit_ok;
+ }
+ return PVRSRV_ERROR_HANDLE_NOT_SHAREABLE;
+ }
+ }
+
+ eError = AllocHandle(psBase, phHandle, pvData, eType, eFlag, IMG_NULL);
+
+exit_ok:
+ if (HANDLES_BATCHED(psBase) && (eError == PVRSRV_OK))
+ {
+ psBase->ui32BatchHandAllocFailures--;
+ }
+
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_HANDLE hParent)
+{
+ struct sHandle *psPHand;
+ struct sHandle *psCHand;
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hParentKey;
+ IMG_HANDLE hHandle;
+
+ *phHandle = IMG_NULL;
+
+ if (HANDLES_BATCHED(psBase))
+ {
+
+ psBase->ui32BatchHandAllocFailures++;
+ }
+
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+ hParentKey = TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE) ?
+ hParent : IMG_NULL;
+
+
+ eError = GetHandleStructure(psBase, &psPHand, hParent, PVRSRV_HANDLE_TYPE_NONE);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
+ {
+
+ hHandle = FindHandle(psBase, pvData, eType, hParentKey);
+ if (hHandle != IMG_NULL)
+ {
+ struct sHandle *psCHandle;
+ PVRSRV_ERROR eErr;
+
+ eErr = GetHandleStructure(psBase, &psCHandle, hHandle, eType);
+ if (eErr != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocSubHandle: Lookup of existing handle failed"));
+ return eErr;
+ }
+
+ PVR_ASSERT(hParentKey != IMG_NULL && ParentHandle(HANDLE_TO_HANDLE_STRUCT_PTR(psBase, hHandle)) == hParent);
+
+
+ if (TEST_FLAG(psCHandle->eFlag & eFlag, PVRSRV_HANDLE_ALLOC_FLAG_SHARED) && ParentHandle(HANDLE_TO_HANDLE_STRUCT_PTR(psBase, hHandle)) == hParent)
+ {
+ *phHandle = hHandle;
+ goto exit_ok;
+ }
+ return PVRSRV_ERROR_HANDLE_NOT_SHAREABLE;
+ }
+ }
+
+ eError = AllocHandle(psBase, &hHandle, pvData, eType, eFlag, hParentKey);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+
+ psPHand = HANDLE_TO_HANDLE_STRUCT_PTR(psBase, hParent);
+
+ psCHand = HANDLE_TO_HANDLE_STRUCT_PTR(psBase, hHandle);
+
+ AdoptChild(psBase, psPHand, psCHand);
+
+ *phHandle = hHandle;
+
+exit_ok:
+ if (HANDLES_BATCHED(psBase))
+ {
+ psBase->ui32BatchHandAllocFailures--;
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVFindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType)
+{
+ IMG_HANDLE hHandle;
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+
+ hHandle = (IMG_HANDLE) FindHandle(psBase, pvData, eType, IMG_NULL);
+ if (hHandle == IMG_NULL)
+ {
+ return PVRSRV_ERROR_HANDLE_NOT_FOUND;
+ }
+
+ *phHandle = hHandle;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVLookupHandleAnyType(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, PVRSRV_HANDLE_TYPE *peType, IMG_HANDLE hHandle)
+{
+ struct sHandle *psHandle;
+ PVRSRV_ERROR eError;
+
+ eError = GetHandleStructure(psBase, &psHandle, hHandle, PVRSRV_HANDLE_TYPE_NONE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupHandleAnyType: Error looking up handle (%d)", eError));
+ return eError;
+ }
+
+ *ppvData = psHandle->pvData;
+ *peType = psHandle->eType;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+ struct sHandle *psHandle;
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+ eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupHandle: Error looking up handle (%d)", eError));
+ return eError;
+ }
+
+ *ppvData = psHandle->pvData;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hAncestor)
+{
+ struct sHandle *psPHand;
+ struct sHandle *psCHand;
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+ eError = GetHandleStructure(psBase, &psCHand, hHandle, eType);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupSubHandle: Error looking up subhandle (%d)", eError));
+ return eError;
+ }
+
+
+ for (psPHand = psCHand; ParentHandle(psPHand) != hAncestor; )
+ {
+ eError = GetHandleStructure(psBase, &psPHand, ParentHandle(psPHand), PVRSRV_HANDLE_TYPE_NONE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupSubHandle: Subhandle doesn't belong to given ancestor"));
+ return PVRSRV_ERROR_INVALID_SUBHANDLE;
+ }
+ }
+
+ *ppvData = psCHand->pvData;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *phParent, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+ struct sHandle *psHandle;
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+ eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetParentHandle: Error looking up subhandle (%d)", eError));
+ return eError;
+ }
+
+ *phParent = ParentHandle(psHandle);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+ struct sHandle *psHandle;
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+ eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVLookupAndReleaseHandle: Error looking up handle (%d)", eError));
+ return eError;
+ }
+
+ *ppvData = psHandle->pvData;
+
+ eError = FreeHandle(psBase, psHandle);
+
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+ struct sHandle *psHandle;
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+ eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVReleaseHandle: Error looking up handle (%d)", eError));
+ return eError;
+ }
+
+ eError = FreeHandle(psBase, psHandle);
+
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVNewHandleBatch(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32BatchSize)
+{
+ PVRSRV_ERROR eError;
+
+ if (HANDLES_BATCHED(psBase))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVNewHandleBatch: There is a handle batch already in use (size %u)", psBase->ui32HandBatchSize));
+ return PVRSRV_ERROR_HANDLE_BATCH_IN_USE;
+ }
+
+ if (ui32BatchSize == 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVNewHandleBatch: Invalid batch size (%u)", ui32BatchSize));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ eError = EnsureFreeHandles(psBase, ui32BatchSize);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVNewHandleBatch: EnsureFreeHandles failed (error %d)", eError));
+ return eError;
+ }
+
+ psBase->ui32HandBatchSize = ui32BatchSize;
+
+
+ psBase->ui32TotalHandCountPreBatch = psBase->ui32TotalHandCount;
+
+ PVR_ASSERT(psBase->ui32BatchHandAllocFailures == 0);
+
+ PVR_ASSERT(psBase->ui32FirstBatchIndexPlusOne == 0);
+
+ PVR_ASSERT(HANDLES_BATCHED(psBase));
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR PVRSRVHandleBatchCommitOrRelease(PVRSRV_HANDLE_BASE *psBase, IMG_BOOL bCommit)
+{
+
+ IMG_UINT32 ui32IndexPlusOne;
+ IMG_BOOL bCommitBatch = bCommit;
+
+ if (!HANDLES_BATCHED(psBase))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleBatchCommitOrRelease: There is no handle batch"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+
+ }
+
+ if (psBase->ui32BatchHandAllocFailures != 0)
+ {
+ if (bCommit)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleBatchCommitOrRelease: Attempting to commit batch with handle allocation failures."));
+ }
+ bCommitBatch = IMG_FALSE;
+ }
+
+ PVR_ASSERT(psBase->ui32BatchHandAllocFailures == 0 || !bCommit);
+
+ ui32IndexPlusOne = psBase->ui32FirstBatchIndexPlusOne;
+ while(ui32IndexPlusOne != 0)
+ {
+ struct sHandle *psHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, ui32IndexPlusOne - 1);
+ IMG_UINT32 ui32NextIndexPlusOne = psHandle->ui32NextIndexPlusOne;
+ PVR_ASSERT(BATCHED_HANDLE(psHandle));
+
+ psHandle->ui32NextIndexPlusOne = 0;
+
+ if (!bCommitBatch || BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
+ {
+ PVRSRV_ERROR eError;
+
+
+ if (!BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
+ {
+
+ SET_UNBATCHED_HANDLE(psHandle);
+ }
+
+ eError = FreeHandle(psBase, psHandle);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleBatchCommitOrRelease: Error freeing handle (%d)", eError));
+ }
+ PVR_ASSERT(eError == PVRSRV_OK);
+ }
+ else
+ {
+
+ SET_UNBATCHED_HANDLE(psHandle);
+ }
+
+ ui32IndexPlusOne = ui32NextIndexPlusOne;
+ }
+
+#ifdef DEBUG
+ if (psBase->ui32TotalHandCountPreBatch != psBase->ui32TotalHandCount)
+ {
+ IMG_UINT32 ui32Delta = psBase->ui32TotalHandCount - psBase->ui32TotalHandCountPreBatch;
+
+ PVR_ASSERT(psBase->ui32TotalHandCount > psBase->ui32TotalHandCountPreBatch);
+
+ PVR_DPF((PVR_DBG_WARNING, "PVRSRVHandleBatchCommitOrRelease: The batch size was too small. Batch size was %u, but needs to be %u", psBase->ui32HandBatchSize, psBase->ui32HandBatchSize + ui32Delta));
+
+ }
+#endif
+
+ psBase->ui32HandBatchSize = 0;
+ psBase->ui32FirstBatchIndexPlusOne = 0;
+ psBase->ui32TotalHandCountPreBatch = 0;
+ psBase->ui32BatchHandAllocFailures = 0;
+
+ if (psBase->ui32BatchHandAllocFailures != 0 && bCommit)
+ {
+ PVR_ASSERT(!bCommitBatch);
+
+ return PVRSRV_ERROR_HANDLE_BATCH_COMMIT_FAILURE;
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVCommitHandleBatch(PVRSRV_HANDLE_BASE *psBase)
+{
+ return PVRSRVHandleBatchCommitOrRelease(psBase, IMG_TRUE);
+}
+
+IMG_VOID PVRSRVReleaseHandleBatch(PVRSRV_HANDLE_BASE *psBase)
+{
+ (IMG_VOID) PVRSRVHandleBatchCommitOrRelease(psBase, IMG_FALSE);
+}
+
+PVRSRV_ERROR PVRSRVSetMaxHandle(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32MaxHandle)
+{
+ IMG_UINT32 ui32MaxHandleRounded;
+
+ if (HANDLES_BATCHED(psBase))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSetMaxHandle: Limit cannot be set whilst in batch mode"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ if (ui32MaxHandle == 0 || ui32MaxHandle > DEFAULT_MAX_HANDLE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSetMaxHandle: Limit must be between %u and %u, inclusive", 0, DEFAULT_MAX_HANDLE));
+
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ if (psBase->ui32TotalHandCount != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSetMaxHandle: Limit cannot be set because handles have already been allocated"));
+
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ ui32MaxHandleRounded = ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE(ui32MaxHandle);
+
+
+ if (ui32MaxHandleRounded != 0 && ui32MaxHandleRounded < psBase->ui32MaxIndexPlusOne)
+ {
+ psBase->ui32MaxIndexPlusOne = ui32MaxHandleRounded;
+ }
+
+ PVR_ASSERT(psBase->ui32MaxIndexPlusOne != 0);
+ PVR_ASSERT(psBase->ui32MaxIndexPlusOne <= DEFAULT_MAX_INDEX_PLUS_ONE);
+ PVR_ASSERT((psBase->ui32MaxIndexPlusOne % HANDLE_BLOCK_SIZE) == 0);
+
+ return PVRSRV_OK;
+}
+
+IMG_UINT32 PVRSRVGetMaxHandle(PVRSRV_HANDLE_BASE *psBase)
+{
+ return psBase->ui32MaxIndexPlusOne;
+}
+
+PVRSRV_ERROR PVRSRVEnableHandlePurging(PVRSRV_HANDLE_BASE *psBase)
+{
+ if (psBase->bPurgingEnabled)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "PVRSRVEnableHandlePurging: Purging already enabled"));
+ return PVRSRV_OK;
+ }
+
+
+ if (psBase->ui32TotalHandCount != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVEnableHandlePurging: Handles have already been allocated"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psBase->bPurgingEnabled = IMG_TRUE;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVPurgeHandles(PVRSRV_HANDLE_BASE *psBase)
+{
+ IMG_UINT32 ui32BlockIndex;
+ IMG_UINT32 ui32NewHandCount;
+
+ if (!psBase->bPurgingEnabled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVPurgeHandles: Purging not enabled for this handle base"));
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+ }
+
+ if (HANDLES_BATCHED(psBase))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVPurgeHandles: Purging not allowed whilst in batch mode"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ PVR_ASSERT((psBase->ui32TotalHandCount % HANDLE_BLOCK_SIZE) == 0);
+
+ for (ui32BlockIndex = INDEX_TO_BLOCK_INDEX(psBase->ui32TotalHandCount); ui32BlockIndex != 0; ui32BlockIndex--)
+ {
+ if (psBase->psHandleArray[ui32BlockIndex - 1].ui32FreeHandBlockCount != HANDLE_BLOCK_SIZE)
+ {
+ break;
+ }
+ }
+ ui32NewHandCount = BLOCK_INDEX_TO_INDEX(ui32BlockIndex);
+
+
+ if (ui32NewHandCount <= (psBase->ui32TotalHandCount/2))
+ {
+ PVRSRV_ERROR eError;
+
+
+
+ eError = ReallocHandleArray(psBase, ui32NewHandCount);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE **ppsBase)
+{
+ PVRSRV_HANDLE_BASE *psBase;
+ IMG_HANDLE hBlockAlloc;
+ PVRSRV_ERROR eError;
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(*psBase),
+ (IMG_PVOID *)&psBase,
+ &hBlockAlloc,
+ "Handle Base");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandleBase: Couldn't allocate handle base (%d)", eError));
+ return eError;
+ }
+ OSMemSet(psBase, 0, sizeof(*psBase));
+
+
+ psBase->psHashTab = HASH_Create_Extended(HANDLE_HASH_TAB_INIT_SIZE, sizeof(HAND_KEY), HASH_Func_Default, HASH_Key_Comp_Default);
+ if (psBase->psHashTab == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocHandleBase: Couldn't create data pointer hash table\n"));
+ (IMG_VOID)PVRSRVFreeHandleBase(psBase);
+ return PVRSRV_ERROR_UNABLE_TO_CREATE_HASH_TABLE;
+ }
+
+ psBase->hBaseBlockAlloc = hBlockAlloc;
+
+ psBase->ui32MaxIndexPlusOne = DEFAULT_MAX_INDEX_PLUS_ONE;
+
+ *ppsBase = psBase;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVFreeHandleBase(PVRSRV_HANDLE_BASE *psBase)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(psBase != gpsKernelHandleBase);
+
+ eError = FreeHandleBase(psBase);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVFreeHandleBase: FreeHandleBase failed (%d)", eError));
+ }
+
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVHandleInit(IMG_VOID)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(gpsKernelHandleBase == IMG_NULL);
+
+ eError = PVRSRVAllocHandleBase(&gpsKernelHandleBase);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleInit: PVRSRVAllocHandleBase failed (%d)", eError));
+ goto error;
+ }
+
+ eError = PVRSRVEnableHandlePurging(gpsKernelHandleBase);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleInit: PVRSRVEnableHandlePurging failed (%d)", eError));
+ goto error;
+ }
+
+ return PVRSRV_OK;
+error:
+ (IMG_VOID) PVRSRVHandleDeInit();
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVHandleDeInit(IMG_VOID)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if (gpsKernelHandleBase != IMG_NULL)
+ {
+ eError = FreeHandleBase(gpsKernelHandleBase);
+ if (eError == PVRSRV_OK)
+ {
+ gpsKernelHandleBase = IMG_NULL;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleDeInit: FreeHandleBase failed (%d)", eError));
+ }
+ }
+
+ return eError;
+}
+#else
+#endif
--- /dev/null
+/**********************************************************************
+ *
+ * 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 "pvr_debug.h"
+#include "img_defs.h"
+#include "services.h"
+#include "servicesint.h"
+#include "hash.h"
+#include "osfunc.h"
+
+#define PRIVATE_MAX(a,b) ((a)>(b)?(a):(b))
+
+#define KEY_TO_INDEX(pHash, key, uSize) \
+ ((pHash)->pfnHashFunc((pHash)->uKeySize, (key), (uSize)) % (uSize))
+
+#define KEY_COMPARE(pHash, pKey1, pKey2) \
+ ((pHash)->pfnKeyComp((pHash)->uKeySize, (pKey1), (pKey2)))
+
+struct _BUCKET_
+{
+
+ struct _BUCKET_ *pNext;
+
+
+ IMG_UINTPTR_T v;
+
+
+ IMG_UINTPTR_T k[];
+};
+typedef struct _BUCKET_ BUCKET;
+
+struct _HASH_TABLE_
+{
+
+ BUCKET **ppBucketTable;
+
+
+ IMG_UINT32 uSize;
+
+
+ IMG_UINT32 uCount;
+
+
+ IMG_UINT32 uMinimumSize;
+
+
+ IMG_UINT32 uKeySize;
+
+
+ HASH_FUNC *pfnHashFunc;
+
+
+ HASH_KEY_COMP *pfnKeyComp;
+};
+
+IMG_UINT32
+HASH_Func_Default (IMG_SIZE_T uKeySize, IMG_VOID *pKey, IMG_UINT32 uHashTabLen)
+{
+ IMG_UINTPTR_T *p = (IMG_UINTPTR_T *)pKey;
+ IMG_UINT32 uKeyLen = uKeySize / sizeof(IMG_UINTPTR_T);
+ IMG_UINT32 ui;
+ IMG_UINT32 uHashKey = 0;
+
+ PVR_UNREFERENCED_PARAMETER(uHashTabLen);
+
+ PVR_ASSERT((uKeySize % sizeof(IMG_UINTPTR_T)) == 0);
+
+ for (ui = 0; ui < uKeyLen; ui++)
+ {
+ IMG_UINT32 uHashPart = (IMG_UINT32)*p++;
+
+ uHashPart += (uHashPart << 12);
+ uHashPart ^= (uHashPart >> 22);
+ uHashPart += (uHashPart << 4);
+ uHashPart ^= (uHashPart >> 9);
+ uHashPart += (uHashPart << 10);
+ uHashPart ^= (uHashPart >> 2);
+ uHashPart += (uHashPart << 7);
+ uHashPart ^= (uHashPart >> 12);
+
+ uHashKey += uHashPart;
+ }
+
+ return uHashKey;
+}
+
+IMG_BOOL
+HASH_Key_Comp_Default (IMG_SIZE_T uKeySize, IMG_VOID *pKey1, IMG_VOID *pKey2)
+{
+ IMG_UINTPTR_T *p1 = (IMG_UINTPTR_T *)pKey1;
+ IMG_UINTPTR_T *p2 = (IMG_UINTPTR_T *)pKey2;
+ IMG_UINT32 uKeyLen = uKeySize / sizeof(IMG_UINTPTR_T);
+ IMG_UINT32 ui;
+
+ PVR_ASSERT((uKeySize % sizeof(IMG_UINTPTR_T)) == 0);
+
+ for (ui = 0; ui < uKeyLen; ui++)
+ {
+ if (*p1++ != *p2++)
+ return IMG_FALSE;
+ }
+
+ return IMG_TRUE;
+}
+
+static PVRSRV_ERROR
+_ChainInsert (HASH_TABLE *pHash, BUCKET *pBucket, BUCKET **ppBucketTable, IMG_UINT32 uSize)
+{
+ IMG_UINT32 uIndex;
+
+ PVR_ASSERT (pBucket != IMG_NULL);
+ PVR_ASSERT (ppBucketTable != IMG_NULL);
+ PVR_ASSERT (uSize != 0);
+
+ if ((pBucket == IMG_NULL) || (ppBucketTable == IMG_NULL) || (uSize == 0))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "_ChainInsert: invalid parameter"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ uIndex = KEY_TO_INDEX(pHash, pBucket->k, uSize);
+ pBucket->pNext = ppBucketTable[uIndex];
+ ppBucketTable[uIndex] = pBucket;
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR
+_Rehash (HASH_TABLE *pHash,
+ BUCKET **ppOldTable, IMG_UINT32 uOldSize,
+ BUCKET **ppNewTable, IMG_UINT32 uNewSize)
+{
+ IMG_UINT32 uIndex;
+ for (uIndex=0; uIndex< uOldSize; uIndex++)
+ {
+ BUCKET *pBucket;
+ pBucket = ppOldTable[uIndex];
+ while (pBucket != IMG_NULL)
+ {
+ PVRSRV_ERROR eError;
+ BUCKET *pNextBucket = pBucket->pNext;
+ eError = _ChainInsert (pHash, pBucket, ppNewTable, uNewSize);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "_Rehash: call to _ChainInsert failed"));
+ return eError;
+ }
+ pBucket = pNextBucket;
+ }
+ }
+ return PVRSRV_OK;
+}
+
+static IMG_BOOL
+_Resize (HASH_TABLE *pHash, IMG_UINT32 uNewSize)
+{
+ if (uNewSize != pHash->uSize)
+ {
+ BUCKET **ppNewTable;
+ IMG_UINT32 uIndex;
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "HASH_Resize: oldsize=0x%x newsize=0x%x count=0x%x",
+ pHash->uSize, uNewSize, pHash->uCount));
+
+ OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof (BUCKET *) * uNewSize,
+ (IMG_PVOID*)&ppNewTable, IMG_NULL,
+ "Hash Table Buckets");
+ if (ppNewTable == IMG_NULL)
+ return IMG_FALSE;
+
+ for (uIndex=0; uIndex<uNewSize; uIndex++)
+ ppNewTable[uIndex] = IMG_NULL;
+
+ if (_Rehash (pHash, pHash->ppBucketTable, pHash->uSize, ppNewTable, uNewSize) != PVRSRV_OK)
+ {
+ return IMG_FALSE;
+ }
+
+ OSFreeMem (PVRSRV_PAGEABLE_SELECT, sizeof(BUCKET *)*pHash->uSize, pHash->ppBucketTable, IMG_NULL);
+
+ pHash->ppBucketTable = ppNewTable;
+ pHash->uSize = uNewSize;
+ }
+ return IMG_TRUE;
+}
+
+
+HASH_TABLE * HASH_Create_Extended (IMG_UINT32 uInitialLen, IMG_SIZE_T uKeySize, HASH_FUNC *pfnHashFunc, HASH_KEY_COMP *pfnKeyComp)
+{
+ HASH_TABLE *pHash;
+ IMG_UINT32 uIndex;
+
+ PVR_DPF ((PVR_DBG_MESSAGE, "HASH_Create_Extended: InitialSize=0x%x", uInitialLen));
+
+ if(OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(HASH_TABLE),
+ (IMG_VOID **)&pHash, IMG_NULL,
+ "Hash Table") != PVRSRV_OK)
+ {
+ return IMG_NULL;
+ }
+
+ pHash->uCount = 0;
+ pHash->uSize = uInitialLen;
+ pHash->uMinimumSize = uInitialLen;
+ pHash->uKeySize = uKeySize;
+ pHash->pfnHashFunc = pfnHashFunc;
+ pHash->pfnKeyComp = pfnKeyComp;
+
+ OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof (BUCKET *) * pHash->uSize,
+ (IMG_PVOID*)&pHash->ppBucketTable, IMG_NULL,
+ "Hash Table Buckets");
+
+ if (pHash->ppBucketTable == IMG_NULL)
+ {
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(HASH_TABLE), pHash, IMG_NULL);
+
+ return IMG_NULL;
+ }
+
+ for (uIndex=0; uIndex<pHash->uSize; uIndex++)
+ pHash->ppBucketTable[uIndex] = IMG_NULL;
+ return pHash;
+}
+
+HASH_TABLE * HASH_Create (IMG_UINT32 uInitialLen)
+{
+ return HASH_Create_Extended(uInitialLen, sizeof(IMG_UINTPTR_T),
+ &HASH_Func_Default, &HASH_Key_Comp_Default);
+}
+
+IMG_VOID
+HASH_Delete (HASH_TABLE *pHash)
+{
+ if (pHash != IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_MESSAGE, "HASH_Delete"));
+
+ PVR_ASSERT (pHash->uCount==0);
+ if(pHash->uCount != 0)
+ {
+ PVR_DPF ((PVR_DBG_ERROR, "HASH_Delete: leak detected in hash table!"));
+ PVR_DPF ((PVR_DBG_ERROR, "Likely Cause: client drivers not freeing alocations before destroying devmemcontext"));
+ }
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(BUCKET *)*pHash->uSize, pHash->ppBucketTable, IMG_NULL);
+ pHash->ppBucketTable = IMG_NULL;
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(HASH_TABLE), pHash, IMG_NULL);
+
+ }
+}
+
+IMG_BOOL
+HASH_Insert_Extended (HASH_TABLE *pHash, IMG_VOID *pKey, IMG_UINTPTR_T v)
+{
+ BUCKET *pBucket;
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "HASH_Insert_Extended: Hash=0x%08x, pKey=0x%08x, v=0x%x",
+ (IMG_UINTPTR_T)pHash, (IMG_UINTPTR_T)pKey, v));
+
+ PVR_ASSERT (pHash != IMG_NULL);
+
+ if (pHash == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "HASH_Insert_Extended: invalid parameter"));
+ return IMG_FALSE;
+ }
+
+ if(OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(BUCKET) + pHash->uKeySize,
+ (IMG_VOID **)&pBucket, IMG_NULL,
+ "Hash Table entry") != PVRSRV_OK)
+ {
+ return IMG_FALSE;
+ }
+
+ pBucket->v = v;
+
+ OSMemCopy(pBucket->k, pKey, pHash->uKeySize);
+ if (_ChainInsert (pHash, pBucket, pHash->ppBucketTable, pHash->uSize) != PVRSRV_OK)
+ {
+ return IMG_FALSE;
+ }
+
+ pHash->uCount++;
+
+
+ if (pHash->uCount << 1 > pHash->uSize)
+ {
+
+
+ _Resize (pHash, pHash->uSize << 1);
+ }
+
+
+ return IMG_TRUE;
+}
+
+IMG_BOOL
+HASH_Insert (HASH_TABLE *pHash, IMG_UINTPTR_T k, IMG_UINTPTR_T v)
+{
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "HASH_Insert: Hash=0x%x, k=0x%x, v=0x%x",
+ (IMG_UINTPTR_T)pHash, k, v));
+
+ return HASH_Insert_Extended(pHash, &k, v);
+}
+
+IMG_UINTPTR_T
+HASH_Remove_Extended(HASH_TABLE *pHash, IMG_VOID *pKey)
+{
+ BUCKET **ppBucket;
+ IMG_UINT32 uIndex;
+
+ PVR_DPF ((PVR_DBG_MESSAGE, "HASH_Remove_Extended: Hash=0x%x, pKey=0x%x",
+ (IMG_UINTPTR_T)pHash, (IMG_UINTPTR_T)pKey));
+
+ PVR_ASSERT (pHash != IMG_NULL);
+
+ if (pHash == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "HASH_Remove_Extended: Null hash table"));
+ return 0;
+ }
+
+ uIndex = KEY_TO_INDEX(pHash, pKey, pHash->uSize);
+
+ for (ppBucket = &(pHash->ppBucketTable[uIndex]); *ppBucket != IMG_NULL; ppBucket = &((*ppBucket)->pNext))
+ {
+
+ if (KEY_COMPARE(pHash, (*ppBucket)->k, pKey))
+ {
+ BUCKET *pBucket = *ppBucket;
+ IMG_UINTPTR_T v = pBucket->v;
+ (*ppBucket) = pBucket->pNext;
+
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(BUCKET) + pHash->uKeySize, pBucket, IMG_NULL);
+
+
+ pHash->uCount--;
+
+
+ if (pHash->uSize > (pHash->uCount << 2) &&
+ pHash->uSize > pHash->uMinimumSize)
+ {
+
+
+ _Resize (pHash,
+ PRIVATE_MAX (pHash->uSize >> 1,
+ pHash->uMinimumSize));
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "HASH_Remove_Extended: Hash=0x%x, pKey=0x%x = 0x%x",
+ (IMG_UINTPTR_T)pHash, (IMG_UINTPTR_T)pKey, v));
+ return v;
+ }
+ }
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "HASH_Remove_Extended: Hash=0x%x, pKey=0x%x = 0x0 !!!!",
+ (IMG_UINTPTR_T)pHash, (IMG_UINTPTR_T)pKey));
+ return 0;
+}
+
+IMG_UINTPTR_T
+HASH_Remove (HASH_TABLE *pHash, IMG_UINTPTR_T k)
+{
+ PVR_DPF ((PVR_DBG_MESSAGE, "HASH_Remove: Hash=0x%x, k=0x%x",
+ (IMG_UINTPTR_T)pHash, k));
+
+ return HASH_Remove_Extended(pHash, &k);
+}
+
+IMG_UINTPTR_T
+HASH_Retrieve_Extended (HASH_TABLE *pHash, IMG_VOID *pKey)
+{
+ BUCKET **ppBucket;
+ IMG_UINT32 uIndex;
+
+ PVR_DPF ((PVR_DBG_MESSAGE, "HASH_Retrieve_Extended: Hash=0x%x, pKey=0x%x",
+ (IMG_UINTPTR_T)pHash, (IMG_UINTPTR_T)pKey));
+
+ PVR_ASSERT (pHash != IMG_NULL);
+
+ if (pHash == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "HASH_Retrieve_Extended: Null hash table"));
+ return 0;
+ }
+
+ uIndex = KEY_TO_INDEX(pHash, pKey, pHash->uSize);
+
+ for (ppBucket = &(pHash->ppBucketTable[uIndex]); *ppBucket != IMG_NULL; ppBucket = &((*ppBucket)->pNext))
+ {
+
+ if (KEY_COMPARE(pHash, (*ppBucket)->k, pKey))
+ {
+ BUCKET *pBucket = *ppBucket;
+ IMG_UINTPTR_T v = pBucket->v;
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "HASH_Retrieve: Hash=0x%x, pKey=0x%x = 0x%x",
+ (IMG_UINTPTR_T)pHash, (IMG_UINTPTR_T)pKey, v));
+ return v;
+ }
+ }
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "HASH_Retrieve: Hash=0x%x, pKey=0x%x = 0x0 !!!!",
+ (IMG_UINTPTR_T)pHash, (IMG_UINTPTR_T)pKey));
+ return 0;
+}
+
+IMG_UINTPTR_T
+HASH_Retrieve (HASH_TABLE *pHash, IMG_UINTPTR_T k)
+{
+ PVR_DPF ((PVR_DBG_MESSAGE, "HASH_Retrieve: Hash=0x%x, k=0x%x",
+ (IMG_UINTPTR_T)pHash, k));
+ return HASH_Retrieve_Extended(pHash, &k);
+}
+
+#ifdef HASH_TRACE
+IMG_VOID
+HASH_Dump (HASH_TABLE *pHash)
+{
+ IMG_UINT32 uIndex;
+ IMG_UINT32 uMaxLength=0;
+ IMG_UINT32 uEmptyCount=0;
+
+ PVR_ASSERT (pHash != IMG_NULL);
+ for (uIndex=0; uIndex<pHash->uSize; uIndex++)
+ {
+ BUCKET *pBucket;
+ IMG_UINT32 uLength = 0;
+ if (pHash->ppBucketTable[uIndex] == IMG_NULL)
+ {
+ uEmptyCount++;
+ }
+ for (pBucket=pHash->ppBucketTable[uIndex];
+ pBucket != IMG_NULL;
+ pBucket = pBucket->pNext)
+ {
+ uLength++;
+ }
+ uMaxLength = PRIVATE_MAX (uMaxLength, uLength);
+ }
+
+ PVR_TRACE(("hash table: uMinimumSize=%d size=%d count=%d",
+ pHash->uMinimumSize, pHash->uSize, pHash->uCount));
+ PVR_TRACE((" empty=%d max=%d", uEmptyCount, uMaxLength));
+}
+#endif
--- /dev/null
+/**********************************************************************
+ *
+ * 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 "lists.h"
+#include "services_headers.h"
+
+IMPLEMENT_LIST_ANY_VA(BM_HEAP)
+IMPLEMENT_LIST_ANY_2(BM_HEAP, PVRSRV_ERROR, PVRSRV_OK)
+IMPLEMENT_LIST_ANY_VA_2(BM_HEAP, PVRSRV_ERROR, PVRSRV_OK)
+IMPLEMENT_LIST_FOR_EACH_VA(BM_HEAP)
+IMPLEMENT_LIST_REMOVE(BM_HEAP)
+IMPLEMENT_LIST_INSERT(BM_HEAP)
+IMPLEMENT_LIST_FIND(BM_HEAP)
+
+IMPLEMENT_LIST_ANY_VA(BM_CONTEXT)
+IMPLEMENT_LIST_ANY_VA_2(BM_CONTEXT, IMG_HANDLE, IMG_NULL)
+IMPLEMENT_LIST_ANY_VA_2(BM_CONTEXT, PVRSRV_ERROR, PVRSRV_OK)
+IMPLEMENT_LIST_FOR_EACH(BM_CONTEXT)
+IMPLEMENT_LIST_REMOVE(BM_CONTEXT)
+IMPLEMENT_LIST_INSERT(BM_CONTEXT)
+IMPLEMENT_LIST_FIND(BM_CONTEXT)
+
+IMPLEMENT_LIST_ANY_2(PVRSRV_DEVICE_NODE, PVRSRV_ERROR, PVRSRV_OK)
+IMPLEMENT_LIST_ANY_VA(PVRSRV_DEVICE_NODE)
+IMPLEMENT_LIST_ANY_VA_2(PVRSRV_DEVICE_NODE, PVRSRV_ERROR, PVRSRV_OK)
+IMPLEMENT_LIST_FOR_EACH(PVRSRV_DEVICE_NODE)
+IMPLEMENT_LIST_FOR_EACH_VA(PVRSRV_DEVICE_NODE)
+IMPLEMENT_LIST_INSERT(PVRSRV_DEVICE_NODE)
+IMPLEMENT_LIST_REMOVE(PVRSRV_DEVICE_NODE)
+IMPLEMENT_LIST_FIND(PVRSRV_DEVICE_NODE)
+
+IMPLEMENT_LIST_ANY_VA(PVRSRV_POWER_DEV)
+IMPLEMENT_LIST_ANY_VA_2(PVRSRV_POWER_DEV, PVRSRV_ERROR, PVRSRV_OK)
+IMPLEMENT_LIST_INSERT(PVRSRV_POWER_DEV)
+IMPLEMENT_LIST_REMOVE(PVRSRV_POWER_DEV)
+
+#if defined(PERPROC_LIST)
+IMPLEMENT_LIST_FOR_EACH_VA(PVRSRV_PER_PROCESS_DATA);
+IMPLEMENT_LIST_INSERT(PVRSRV_PER_PROCESS_DATA);
+IMPLEMENT_LIST_REMOVE(PVRSRV_PER_PROCESS_DATA);
+#endif
+
+
+IMG_VOID* MatchDeviceKM_AnyVaCb(PVRSRV_DEVICE_NODE* psDeviceNode, va_list va)
+{
+ IMG_UINT32 ui32DevIndex;
+ IMG_BOOL bIgnoreClass;
+ PVRSRV_DEVICE_CLASS eDevClass;
+
+ ui32DevIndex = va_arg(va, IMG_UINT32);
+ bIgnoreClass = va_arg(va, IMG_BOOL);
+ if (!bIgnoreClass)
+ {
+ eDevClass = va_arg(va, PVRSRV_DEVICE_CLASS);
+ }
+ else
+ {
+
+
+ eDevClass = PVRSRV_DEVICE_CLASS_FORCE_I32;
+ }
+
+ if ((bIgnoreClass || psDeviceNode->sDevId.eDeviceClass == eDevClass) &&
+ psDeviceNode->sDevId.ui32DeviceIndex == ui32DevIndex)
+ {
+ return psDeviceNode;
+ }
+ return IMG_NULL;
+}
+
+IMG_VOID* MatchPowerDeviceIndex_AnyVaCb(PVRSRV_POWER_DEV *psPowerDev, va_list va)
+{
+ IMG_UINT32 ui32DeviceIndex;
+
+ ui32DeviceIndex = va_arg(va, IMG_UINT32);
+
+ if (psPowerDev->ui32DeviceIndex == ui32DeviceIndex)
+ {
+ return psPowerDev;
+ }
+ else
+ {
+ return IMG_NULL;
+ }
+}
--- /dev/null
+/**********************************************************************
+ *
+ * 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 "services_headers.h"
+#include "pvr_bridge_km.h"
+
+
+static PVRSRV_ERROR
+FreeSharedSysMemCallBack(IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param)
+{
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = pvParam;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ OSFreePages(psKernelMemInfo->ui32Flags,
+ psKernelMemInfo->ui32AllocSize,
+ psKernelMemInfo->pvLinAddrKM,
+ psKernelMemInfo->sMemBlk.hOSMemHandle);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO),
+ psKernelMemInfo,
+ IMG_NULL);
+
+
+ return PVRSRV_OK;
+}
+
+
+IMG_EXPORT PVRSRV_ERROR
+PVRSRVAllocSharedSysMemoryKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_UINT32 ui32Flags,
+ IMG_SIZE_T ui32Size,
+ PVRSRV_KERNEL_MEM_INFO **ppsKernelMemInfo)
+{
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO),
+ (IMG_VOID **)&psKernelMemInfo, IMG_NULL,
+ "Kernel Memory Info") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVAllocSharedSysMemoryKM: Failed to alloc memory for meminfo"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ OSMemSet(psKernelMemInfo, 0, sizeof(*psKernelMemInfo));
+
+ ui32Flags &= ~PVRSRV_HAP_MAPTYPE_MASK;
+ ui32Flags |= PVRSRV_HAP_MULTI_PROCESS;
+ psKernelMemInfo->ui32Flags = ui32Flags;
+ psKernelMemInfo->ui32AllocSize = ui32Size;
+
+ if(OSAllocPages(psKernelMemInfo->ui32Flags,
+ psKernelMemInfo->ui32AllocSize,
+ HOST_PAGESIZE(),
+ &psKernelMemInfo->pvLinAddrKM,
+ &psKernelMemInfo->sMemBlk.hOSMemHandle)
+ != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocSharedSysMemoryKM: Failed to alloc memory for block"));
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO),
+ psKernelMemInfo,
+ 0);
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+
+ psKernelMemInfo->sMemBlk.hResItem =
+ ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_SHARED_MEM_INFO,
+ psKernelMemInfo,
+ 0,
+ &FreeSharedSysMemCallBack);
+
+ *ppsKernelMemInfo = psKernelMemInfo;
+
+ return PVRSRV_OK;
+}
+
+
+IMG_EXPORT PVRSRV_ERROR
+PVRSRVFreeSharedSysMemoryKM(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+ PVRSRV_ERROR eError;
+
+ if(psKernelMemInfo->sMemBlk.hResItem)
+ {
+ eError = ResManFreeResByPtr(psKernelMemInfo->sMemBlk.hResItem);
+ }
+ else
+ {
+ eError = FreeSharedSysMemCallBack(psKernelMemInfo, 0);
+ }
+
+ return eError;
+}
+
+
+IMG_EXPORT PVRSRV_ERROR
+PVRSRVDissociateMemFromResmanKM(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if(!psKernelMemInfo)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if(psKernelMemInfo->sMemBlk.hResItem)
+ {
+ eError = ResManDissociateRes(psKernelMemInfo->sMemBlk.hResItem, IMG_NULL);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVDissociateMemFromResmanKM: ResManDissociateRes failed"));
+ PVR_DBG_BREAK;
+ return eError;
+ }
+
+ psKernelMemInfo->sMemBlk.hResItem = IMG_NULL;
+ }
+
+ return eError;
+}
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef MEM_DEBUG_C
+#define MEM_DEBUG_C
+
+#if defined(PVRSRV_DEBUG_OS_MEMORY)
+
+#include "img_types.h"
+#include "services_headers.h"
+
+#if defined (__cplusplus)
+extern "C"
+{
+#endif
+
+#define STOP_ON_ERROR 0
+
+
+
+
+
+
+
+
+
+ IMG_BOOL MemCheck(const IMG_PVOID pvAddr, const IMG_UINT8 ui8Pattern, IMG_SIZE_T uSize)
+ {
+ IMG_UINT8 *pui8Addr;
+ for (pui8Addr = (IMG_UINT8*)pvAddr; uSize > 0; uSize--, pui8Addr++)
+ {
+ if (*pui8Addr != ui8Pattern)
+ {
+ return IMG_FALSE;
+ }
+ }
+ return IMG_TRUE;
+ }
+
+
+
+ IMG_VOID OSCheckMemDebug(IMG_PVOID pvCpuVAddr, IMG_SIZE_T uSize, const IMG_CHAR *pszFileName, const IMG_UINT32 uLine)
+ {
+ OSMEM_DEBUG_INFO const *psInfo = (OSMEM_DEBUG_INFO *)((IMG_UINT32)pvCpuVAddr - TEST_BUFFER_PADDING_STATUS);
+
+
+ if (pvCpuVAddr == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : null pointer"
+ " - referenced %s:%d - allocated %s:%d",
+ pvCpuVAddr,
+ pszFileName, uLine,
+ psInfo->sFileName, psInfo->uLineNo));
+ while (STOP_ON_ERROR);
+ }
+
+
+ if (((IMG_UINT32)pvCpuVAddr&3) != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : invalid alignment"
+ " - referenced %s:%d - allocated %s:%d",
+ pvCpuVAddr,
+ pszFileName, uLine,
+ psInfo->sFileName, psInfo->uLineNo));
+ while (STOP_ON_ERROR);
+ }
+
+
+ if (!MemCheck((IMG_PVOID)psInfo->sGuardRegionBefore, 0xB1, sizeof(psInfo->sGuardRegionBefore)))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : guard region before overwritten"
+ " - referenced %s:%d - allocated %s:%d",
+ pvCpuVAddr,
+ pszFileName, uLine,
+ psInfo->sFileName, psInfo->uLineNo));
+ while (STOP_ON_ERROR);
+ }
+
+
+ if (uSize != psInfo->uSize)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "Pointer 0x%X : supplied size was different to stored size (0x%X != 0x%X)"
+ " - referenced %s:%d - allocated %s:%d",
+ pvCpuVAddr, uSize, psInfo->uSize,
+ pszFileName, uLine,
+ psInfo->sFileName, psInfo->uLineNo));
+ while (STOP_ON_ERROR);
+ }
+
+
+ if ((0x01234567 ^ psInfo->uSizeParityCheck) != psInfo->uSize)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "Pointer 0x%X : stored size parity error (0x%X != 0x%X)"
+ " - referenced %s:%d - allocated %s:%d",
+ pvCpuVAddr, psInfo->uSize, 0x01234567 ^ psInfo->uSizeParityCheck,
+ pszFileName, uLine,
+ psInfo->sFileName, psInfo->uLineNo));
+ while (STOP_ON_ERROR);
+ }
+ else
+ {
+
+ uSize = psInfo->uSize;
+ }
+
+
+ if (uSize)
+ {
+ if (!MemCheck((IMG_VOID*)((IMG_UINT32)pvCpuVAddr + uSize), 0xB2, TEST_BUFFER_PADDING_AFTER))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : guard region after overwritten"
+ " - referenced from %s:%d - allocated from %s:%d",
+ pvCpuVAddr,
+ pszFileName, uLine,
+ psInfo->sFileName, psInfo->uLineNo));
+ }
+ }
+
+
+ if (psInfo->eValid != isAllocated)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : not allocated (freed? %d)"
+ " - referenced %s:%d - freed %s:%d",
+ pvCpuVAddr, psInfo->eValid == isFree,
+ pszFileName, uLine,
+ psInfo->sFileName, psInfo->uLineNo));
+ while (STOP_ON_ERROR);
+ }
+ }
+
+ IMG_VOID debug_strcpy(IMG_CHAR *pDest, const IMG_CHAR *pSrc)
+ {
+ IMG_SIZE_T i = 0;
+
+ for (; i < 128; i++)
+ {
+ *pDest = *pSrc;
+ if (*pSrc == '\0') break;
+ pDest++;
+ pSrc++;
+ }
+ }
+
+ PVRSRV_ERROR OSAllocMem_Debug_Wrapper(IMG_UINT32 ui32Flags,
+ IMG_UINT32 ui32Size,
+ IMG_PVOID *ppvCpuVAddr,
+ IMG_HANDLE *phBlockAlloc,
+ IMG_CHAR *pszFilename,
+ IMG_UINT32 ui32Line)
+ {
+ OSMEM_DEBUG_INFO *psInfo;
+
+ PVRSRV_ERROR eError;
+
+ eError = OSAllocMem_Debug_Linux_Memory_Allocations(ui32Flags,
+ ui32Size + TEST_BUFFER_PADDING,
+ ppvCpuVAddr,
+ phBlockAlloc,
+ pszFilename,
+ ui32Line);
+
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+
+ OSMemSet((IMG_CHAR *)(*ppvCpuVAddr) + TEST_BUFFER_PADDING_STATUS, 0xBB, ui32Size);
+ OSMemSet((IMG_CHAR *)(*ppvCpuVAddr) + ui32Size + TEST_BUFFER_PADDING_STATUS, 0xB2, TEST_BUFFER_PADDING_AFTER);
+
+
+ psInfo = (OSMEM_DEBUG_INFO *)(*ppvCpuVAddr);
+
+ OSMemSet(psInfo->sGuardRegionBefore, 0xB1, sizeof(psInfo->sGuardRegionBefore));
+ debug_strcpy(psInfo->sFileName, pszFilename);
+ psInfo->uLineNo = ui32Line;
+ psInfo->eValid = isAllocated;
+ psInfo->uSize = ui32Size;
+ psInfo->uSizeParityCheck = 0x01234567 ^ ui32Size;
+
+
+ *ppvCpuVAddr = (IMG_PVOID) ((IMG_UINT32)*ppvCpuVAddr)+TEST_BUFFER_PADDING_STATUS;
+
+#ifdef PVRSRV_LOG_MEMORY_ALLOCS
+
+ PVR_TRACE(("Allocated pointer (after debug info): 0x%X from %s:%d", *ppvCpuVAddr, pszFilename, ui32Line));
+#endif
+
+ return PVRSRV_OK;
+ }
+
+ PVRSRV_ERROR OSFreeMem_Debug_Wrapper(IMG_UINT32 ui32Flags,
+ IMG_UINT32 ui32Size,
+ IMG_PVOID pvCpuVAddr,
+ IMG_HANDLE hBlockAlloc,
+ IMG_CHAR *pszFilename,
+ IMG_UINT32 ui32Line)
+ {
+ OSMEM_DEBUG_INFO *psInfo;
+
+
+ OSCheckMemDebug(pvCpuVAddr, ui32Size, pszFilename, ui32Line);
+
+
+ OSMemSet(pvCpuVAddr, 0xBF, ui32Size + TEST_BUFFER_PADDING_AFTER);
+
+
+ psInfo = (OSMEM_DEBUG_INFO *)((IMG_UINT32) pvCpuVAddr - TEST_BUFFER_PADDING_STATUS);
+
+
+ psInfo->uSize = 0;
+ psInfo->uSizeParityCheck = 0;
+ psInfo->eValid = isFree;
+ psInfo->uLineNo = ui32Line;
+ debug_strcpy(psInfo->sFileName, pszFilename);
+
+ return OSFreeMem_Debug_Linux_Memory_Allocations(ui32Flags, ui32Size + TEST_BUFFER_PADDING, psInfo, hBlockAlloc, pszFilename, ui32Line);
+ }
+
+#if defined (__cplusplus)
+
+}
+#endif
+
+#endif
+
+#endif
--- /dev/null
+/**********************************************************************
+ *
+ * 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 "services_headers.h"
+#include "metrics.h"
+
+#if defined(SUPPORT_VGX)
+#include "vgxapi_km.h"
+#endif
+
+#if defined(SUPPORT_SGX)
+#include "sgxapi_km.h"
+#endif
+
+#if defined(DEBUG) || defined(TIMING)
+
+static volatile IMG_UINT32 *pui32TimerRegister = 0;
+
+#define PVRSRV_TIMER_TOTAL_IN_TICKS(X) asTimers[X].ui32Total
+#define PVRSRV_TIMER_TOTAL_IN_MS(X) ((1000*asTimers[X].ui32Total)/ui32TicksPerMS)
+#define PVRSRV_TIMER_COUNT(X) asTimers[X].ui32Count
+
+
+Temporal_Data asTimers[PVRSRV_NUM_TIMERS];
+
+
+IMG_UINT32 PVRSRVTimeNow(IMG_VOID)
+{
+ if (!pui32TimerRegister)
+ {
+ static IMG_BOOL bFirstTime = IMG_TRUE;
+
+ if (bFirstTime)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVTimeNow: No timer register set up"));
+
+ bFirstTime = IMG_FALSE;
+ }
+
+ return 0;
+ }
+
+#if defined(__sh__)
+
+ return (0xffffffff-*pui32TimerRegister);
+
+#else
+
+ return 0;
+
+#endif
+}
+
+
+static IMG_UINT32 PVRSRVGetCPUFreq(IMG_VOID)
+{
+ IMG_UINT32 ui32Time1, ui32Time2;
+
+ ui32Time1 = PVRSRVTimeNow();
+
+ OSWaitus(1000000);
+
+ ui32Time2 = PVRSRVTimeNow();
+
+ PVR_DPF((PVR_DBG_WARNING, "PVRSRVGetCPUFreq: timer frequency = %d Hz", ui32Time2 - ui32Time1));
+
+ return (ui32Time2 - ui32Time1);
+}
+
+
+IMG_VOID PVRSRVSetupMetricTimers(IMG_VOID *pvDevInfo)
+{
+ IMG_UINT32 ui32Loop;
+
+ PVR_UNREFERENCED_PARAMETER(pvDevInfo);
+
+ for(ui32Loop=0; ui32Loop < (PVRSRV_NUM_TIMERS); ui32Loop++)
+ {
+ asTimers[ui32Loop].ui32Total = 0;
+ asTimers[ui32Loop].ui32Count = 0;
+ }
+
+
+ #if defined(__sh__)
+
+
+
+
+
+ *TCR_2 = TIMER_DIVISOR;
+
+
+ *TCOR_2 = *TCNT_2 = (IMG_UINT)0xffffffff;
+
+
+ *TST_REG |= (IMG_UINT8)0x04;
+
+ pui32TimerRegister = (IMG_UINT32 *)TCNT_2;
+
+ #else
+
+ pui32TimerRegister = 0;
+
+ #endif
+
+}
+
+
+IMG_VOID PVRSRVOutputMetricTotals(IMG_VOID)
+{
+ IMG_UINT32 ui32TicksPerMS, ui32Loop;
+
+ ui32TicksPerMS = PVRSRVGetCPUFreq();
+
+ if (!ui32TicksPerMS)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOutputMetricTotals: Failed to get CPU Freq"));
+ return;
+ }
+
+ for(ui32Loop=0; ui32Loop < (PVRSRV_NUM_TIMERS); ui32Loop++)
+ {
+ if (asTimers[ui32Loop].ui32Count & 0x80000000L)
+ {
+ PVR_DPF((PVR_DBG_WARNING,"PVRSRVOutputMetricTotals: Timer %u is still ON", ui32Loop));
+ }
+ }
+#if 0
+
+ PVR_DPF((PVR_DBG_ERROR," Timer(%u): Total = %u",PVRSRV_TIMER_EXAMPLE_1, PVRSRV_TIMER_TOTAL_IN_TICKS(PVRSRV_TIMER_EXAMPLE_1)));
+ PVR_DPF((PVR_DBG_ERROR," Timer(%u): Time = %ums",PVRSRV_TIMER_EXAMPLE_1, PVRSRV_TIMER_TOTAL_IN_MS(PVRSRV_TIMER_EXAMPLE_1)));
+ PVR_DPF((PVR_DBG_ERROR," Timer(%u): Count = %u",PVRSRV_TIMER_EXAMPLE_1, PVRSRV_TIMER_COUNT(PVRSRV_TIMER_EXAMPLE_1)));
+#endif
+}
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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 "img_types.h"
+#include "services_headers.h"
+#include "osfunc.h"
+
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#if defined(PDUMP)
+#include <stdarg.h>
+
+#include "services_headers.h"
+#if defined(SUPPORT_SGX)
+#include "sgxdefs.h"
+#endif
+#include "perproc.h"
+
+#include "pdump_km.h"
+#include "pdump_int.h"
+
+#if !defined(PDUMP_TEMP_BUFFER_SIZE)
+#define PDUMP_TEMP_BUFFER_SIZE (64 * 1024U)
+#endif
+
+#if 1
+#define PDUMP_DBG(a) PDumpOSDebugPrintf (a)
+#else
+#define PDUMP_DBG(a)
+#endif
+
+#define PDUMP_DATAMASTER_PIXEL (1)
+#define PDUMP_DATAMASTER_EDM (3)
+
+#define PTR_PLUS(t, p, x) ((t)(((IMG_CHAR *)(p)) + (x)))
+#define VPTR_PLUS(p, x) PTR_PLUS(IMG_VOID *, p, x)
+#define VPTR_INC(p, x) ((p) = VPTR_PLUS(p, x))
+#define MAX_PDUMP_MMU_CONTEXTS (32)
+static IMG_VOID *gpvTempBuffer = IMG_NULL;
+static IMG_HANDLE ghTempBufferBlockAlloc;
+static IMG_UINT16 gui16MMUContextUsage = 0;
+
+#if defined(PDUMP_DEBUG_OUTFILES)
+IMG_UINT32 g_ui32EveryLineCounter = 1U;
+#endif
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(_PDumpIsPersistent)
+#endif
+static INLINE
+IMG_BOOL _PDumpIsPersistent(IMG_VOID)
+{
+ PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData();
+ if(psPerProc == IMG_NULL)
+ {
+
+ return IMG_FALSE;
+ }
+ return psPerProc->bPDumpPersistent;
+}
+
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+static INLINE
+IMG_BOOL _PDumpIsProcessActive(IMG_VOID)
+{
+ PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData();
+ if(psPerProc == IMG_NULL)
+ {
+
+ return IMG_TRUE;
+ }
+ return psPerProc->bPDumpActive;
+}
+#endif
+
+#if defined(PDUMP_DEBUG_OUTFILES)
+static INLINE
+IMG_UINT32 _PDumpGetPID(IMG_VOID)
+{
+ PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData();
+ if(psPerProc == IMG_NULL)
+ {
+
+ return 0;
+ }
+ return psPerProc->ui32PID;
+}
+#endif
+
+static IMG_VOID *GetTempBuffer(IMG_VOID)
+{
+
+ if (gpvTempBuffer == IMG_NULL)
+ {
+ PVRSRV_ERROR eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ PDUMP_TEMP_BUFFER_SIZE,
+ &gpvTempBuffer,
+ &ghTempBufferBlockAlloc,
+ "PDUMP Temporary Buffer");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "GetTempBuffer: OSAllocMem failed: %d", eError));
+ }
+ }
+
+ return gpvTempBuffer;
+}
+
+static IMG_VOID FreeTempBuffer(IMG_VOID)
+{
+
+ if (gpvTempBuffer != IMG_NULL)
+ {
+ PVRSRV_ERROR eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ PDUMP_TEMP_BUFFER_SIZE,
+ gpvTempBuffer,
+ ghTempBufferBlockAlloc);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeTempBuffer: OSFreeMem failed: %d", eError));
+ }
+ else
+ {
+ gpvTempBuffer = IMG_NULL;
+ }
+ }
+}
+
+IMG_VOID PDumpInitCommon(IMG_VOID)
+{
+
+ (IMG_VOID) GetTempBuffer();
+
+
+ PDumpInit();
+}
+
+IMG_VOID PDumpDeInitCommon(IMG_VOID)
+{
+
+ FreeTempBuffer();
+
+
+ PDumpDeInit();
+}
+
+IMG_BOOL PDumpIsSuspended(IMG_VOID)
+{
+ return PDumpOSIsSuspended();
+}
+
+IMG_BOOL PDumpIsCaptureFrameKM(IMG_VOID)
+{
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+ if( _PDumpIsProcessActive() )
+ {
+ return PDumpOSIsCaptureFrameKM();
+ }
+ return IMG_FALSE;
+#else
+ return PDumpOSIsCaptureFrameKM();
+#endif
+}
+
+PVRSRV_ERROR PDumpSetFrameKM(IMG_UINT32 ui32Frame)
+{
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+ if( _PDumpIsProcessActive() )
+ {
+ return PDumpOSSetFrameKM(ui32Frame);
+ }
+ return PVRSRV_OK;
+#else
+ return PDumpOSSetFrameKM(ui32Frame);
+#endif
+}
+
+
+PVRSRV_ERROR PDumpRegWithFlagsKM(IMG_CHAR *pszPDumpRegName,
+ IMG_UINT32 ui32Reg,
+ IMG_UINT32 ui32Data,
+ IMG_UINT32 ui32Flags)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING()
+ PDUMP_DBG(("PDumpRegWithFlagsKM"));
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "WRW :%s:0x%08X 0x%08X\r\n",
+ pszPDumpRegName, ui32Reg, ui32Data);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpRegKM(IMG_CHAR *pszPDumpRegName,
+ IMG_UINT32 ui32Reg,
+ IMG_UINT32 ui32Data)
+{
+ return PDumpRegWithFlagsKM(pszPDumpRegName, ui32Reg, ui32Data, PDUMP_FLAGS_CONTINUOUS);
+}
+
+PVRSRV_ERROR PDumpRegPolWithFlagsKM(IMG_CHAR *pszPDumpRegName,
+ IMG_UINT32 ui32RegAddr,
+ IMG_UINT32 ui32RegValue,
+ IMG_UINT32 ui32Mask,
+ IMG_UINT32 ui32Flags)
+{
+
+ #define POLL_DELAY 1000U
+ #define POLL_COUNT_LONG (2000000000U / POLL_DELAY)
+ #define POLL_COUNT_SHORT (1000000U / POLL_DELAY)
+
+ PVRSRV_ERROR eErr;
+ IMG_UINT32 ui32PollCount;
+
+ PDUMP_GET_SCRIPT_STRING();
+ PDUMP_DBG(("PDumpRegPolWithFlagsKM"));
+ if ( _PDumpIsPersistent() )
+ {
+
+ return PVRSRV_OK;
+ }
+
+#if 0
+ if (((ui32RegAddr == EUR_CR_EVENT_STATUS) &&
+ (ui32RegValue & ui32Mask & EUR_CR_EVENT_STATUS_TA_FINISHED_MASK) != 0) ||
+ ((ui32RegAddr == EUR_CR_EVENT_STATUS) &&
+ (ui32RegValue & ui32Mask & EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_MASK) != 0) ||
+ ((ui32RegAddr == EUR_CR_EVENT_STATUS) &&
+ (ui32RegValue & ui32Mask & EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK) != 0))
+ {
+ ui32PollCount = POLL_COUNT_LONG;
+ }
+ else
+#endif
+ {
+ ui32PollCount = POLL_COUNT_LONG;
+ }
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "POL :%s:0x%08X 0x%08X 0x%08X %d %u %d\r\n",
+ pszPDumpRegName, ui32RegAddr, ui32RegValue,
+ ui32Mask, 0, ui32PollCount, POLL_DELAY);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PDumpRegPolKM(IMG_CHAR *pszPDumpRegName, IMG_UINT32 ui32RegAddr, IMG_UINT32 ui32RegValue, IMG_UINT32 ui32Mask)
+{
+ return PDumpRegPolWithFlagsKM(pszPDumpRegName, ui32RegAddr, ui32RegValue, ui32Mask, PDUMP_FLAGS_CONTINUOUS);
+}
+
+PVRSRV_ERROR PDumpMallocPages (PVRSRV_DEVICE_IDENTIFIER *psDevID,
+ IMG_UINT32 ui32DevVAddr,
+ IMG_CPU_VIRTADDR pvLinAddr,
+ IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32NumBytes,
+ IMG_UINT32 ui32PageSize,
+ IMG_BOOL bShared,
+ IMG_HANDLE hUniqueTag)
+{
+ PVRSRV_ERROR eErr;
+ IMG_PUINT8 pui8LinAddr;
+ IMG_UINT32 ui32Offset;
+ IMG_UINT32 ui32NumPages;
+ IMG_DEV_PHYADDR sDevPAddr;
+ IMG_UINT32 ui32Page;
+ IMG_UINT32 ui32Flags = PDUMP_FLAGS_CONTINUOUS;
+
+ PDUMP_GET_SCRIPT_STRING();
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+
+ ui32Flags |= ( _PDumpIsPersistent() || bShared ) ? PDUMP_FLAGS_PERSISTENT : 0;
+#else
+ PVR_UNREFERENCED_PARAMETER(bShared);
+ ui32Flags |= ( _PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
+#endif
+
+
+#if !defined(LINUX)
+ PVR_ASSERT(((IMG_UINTPTR_T)pvLinAddr & HOST_PAGEMASK) == 0);
+#endif
+
+ PVR_ASSERT(((IMG_UINT32) ui32DevVAddr & HOST_PAGEMASK) == 0);
+ PVR_ASSERT(((IMG_UINT32) ui32NumBytes & HOST_PAGEMASK) == 0);
+
+
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "-- MALLOC :%s:VA_%08X 0x%08X %u\r\n",
+ psDevID->pszPDumpDevName, ui32DevVAddr, ui32NumBytes, ui32PageSize);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+
+
+ pui8LinAddr = (IMG_PUINT8) pvLinAddr;
+ ui32Offset = 0;
+ ui32NumPages = ui32NumBytes / ui32PageSize;
+ while (ui32NumPages)
+ {
+ ui32NumPages--;
+
+
+
+
+
+
+
+
+
+
+
+ PDumpOSCPUVAddrToDevPAddr(psDevID->eDeviceType,
+ hOSMemHandle,
+ ui32Offset,
+ pui8LinAddr,
+ ui32PageSize,
+ &sDevPAddr);
+ ui32Page = (IMG_UINT32)(sDevPAddr.uiAddr / ui32PageSize);
+
+ pui8LinAddr += ui32PageSize;
+ ui32Offset += ui32PageSize;
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "MALLOC :%s:PA_%08X%08X %u %u 0x%08X\r\n",
+ psDevID->pszPDumpDevName,
+ (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag,
+ ui32Page * ui32PageSize,
+ ui32PageSize,
+ ui32PageSize,
+ ui32Page * ui32PageSize);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+ }
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpMallocPageTable (PVRSRV_DEVICE_IDENTIFIER *psDevId,
+ IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32Offset,
+ IMG_CPU_VIRTADDR pvLinAddr,
+ IMG_UINT32 ui32PTSize,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag)
+{
+ PVRSRV_ERROR eErr;
+ IMG_DEV_PHYADDR sDevPAddr;
+
+ PDUMP_GET_SCRIPT_STRING();
+
+ PVR_ASSERT(((IMG_UINTPTR_T)pvLinAddr & (ui32PTSize - 1)) == 0);
+ ui32Flags |= PDUMP_FLAGS_CONTINUOUS;
+ ui32Flags |= ( _PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
+
+
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "-- MALLOC :%s:PAGE_TABLE 0x%08X %u\r\n",
+ psDevId->pszPDumpDevName,
+ ui32PTSize,
+ ui32PTSize);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+
+
+
+
+
+
+
+ PDumpOSCPUVAddrToDevPAddr(psDevId->eDeviceType,
+ hOSMemHandle,
+ ui32Offset,
+ (IMG_PUINT8) pvLinAddr,
+ ui32PTSize,
+ &sDevPAddr);
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "MALLOC :%s:PA_%08X%08X 0x%X %u 0x%08X\r\n",
+ psDevId->pszPDumpDevName,
+ (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag,
+ sDevPAddr.uiAddr,
+ ui32PTSize,
+ ui32PTSize,
+ sDevPAddr.uiAddr);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpFreePages (BM_HEAP *psBMHeap,
+ IMG_DEV_VIRTADDR sDevVAddr,
+ IMG_UINT32 ui32NumBytes,
+ IMG_UINT32 ui32PageSize,
+ IMG_HANDLE hUniqueTag,
+ IMG_BOOL bInterleaved)
+{
+ PVRSRV_ERROR eErr;
+ IMG_UINT32 ui32NumPages, ui32PageCounter;
+ IMG_DEV_PHYADDR sDevPAddr;
+ IMG_UINT32 ui32Flags = PDUMP_FLAGS_CONTINUOUS;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+
+ PDUMP_GET_SCRIPT_STRING();
+
+ PVR_ASSERT(((IMG_UINT32) sDevVAddr.uiAddr & (ui32PageSize - 1)) == 0);
+ PVR_ASSERT(((IMG_UINT32) ui32NumBytes & (ui32PageSize - 1)) == 0);
+
+ psDeviceNode = psBMHeap->pBMContext->psDeviceNode;
+ ui32Flags |= ( _PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
+
+
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "-- FREE :%s:VA_%08X\r\n",
+ psDeviceNode->sDevId.pszPDumpDevName, sDevVAddr.uiAddr);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+
+ {
+ PVRSRV_DEVICE_NODE *psDeviceNode = psBMHeap->pBMContext->psDeviceNode;
+
+ if( psDeviceNode->pfnMMUIsHeapShared(psBMHeap->pMMUHeap) )
+ {
+ ui32Flags |= PDUMP_FLAGS_PERSISTENT;
+ }
+ }
+#endif
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+
+
+ ui32NumPages = ui32NumBytes / ui32PageSize;
+ for (ui32PageCounter = 0; ui32PageCounter < ui32NumPages; ui32PageCounter++)
+ {
+ if (!bInterleaved || (ui32PageCounter % 2) == 0)
+ {
+ sDevPAddr = psDeviceNode->pfnMMUGetPhysPageAddr(psBMHeap->pMMUHeap, sDevVAddr);
+ {
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "FREE :%s:PA_%08X%08X\r\n",
+ psDeviceNode->sDevId.pszPDumpDevName, (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag, sDevPAddr.uiAddr);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+ }
+ }
+ else
+ {
+
+ }
+
+ sDevVAddr.uiAddr += ui32PageSize;
+ }
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpFreePageTable (PVRSRV_DEVICE_IDENTIFIER *psDevID,
+ IMG_HANDLE hOSMemHandle,
+ IMG_CPU_VIRTADDR pvLinAddr,
+ IMG_UINT32 ui32PTSize,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag)
+{
+ PVRSRV_ERROR eErr;
+ IMG_DEV_PHYADDR sDevPAddr;
+
+ PDUMP_GET_SCRIPT_STRING();
+
+ PVR_UNREFERENCED_PARAMETER(ui32PTSize);
+ ui32Flags |= PDUMP_FLAGS_CONTINUOUS;
+ ui32Flags |= ( _PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
+
+
+ PVR_ASSERT(((IMG_UINTPTR_T)pvLinAddr & (ui32PTSize-1UL)) == 0);
+
+
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "-- FREE :%s:PAGE_TABLE\r\n", psDevID->pszPDumpDevName);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+
+
+
+
+
+
+
+ PDumpOSCPUVAddrToDevPAddr(psDevID->eDeviceType,
+ hOSMemHandle,
+ 0,
+ (IMG_PUINT8) pvLinAddr,
+ ui32PTSize,
+ &sDevPAddr);
+
+ {
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "FREE :%s:PA_%08X%08X\r\n",
+ psDevID->pszPDumpDevName,
+ (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag,
+ sDevPAddr.uiAddr);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpPDRegWithFlags(PDUMP_MMU_ATTRIB *psMMUAttrib,
+ IMG_UINT32 ui32Reg,
+ IMG_UINT32 ui32Data,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag)
+{
+ PVRSRV_ERROR eErr;
+ IMG_CHAR *pszRegString;
+ PDUMP_GET_SCRIPT_STRING()
+
+ if(psMMUAttrib->pszPDRegRegion != IMG_NULL)
+ {
+ pszRegString = psMMUAttrib->pszPDRegRegion;
+ }
+ else
+ {
+ pszRegString = psMMUAttrib->sDevId.pszPDumpRegName;
+ }
+
+
+
+#if defined(SGX_FEATURE_36BIT_MMU)
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen,
+ "WRW :%s:$1 :%s:PA_%08X%08X:0x0\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ (IMG_UINT32)hUniqueTag,
+ (ui32Data & psMMUAttrib->ui32PDEMask) << psMMUAttrib->ui32PDEAlignShift);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "SHR :%s:$1 :%s:$1 0x4\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ psMMUAttrib->sDevId.pszPDumpDevName);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen,
+ "WRW :%s:0x%08X: %s:$1\r\n",
+ pszRegString,
+ ui32Reg,
+ psMMUAttrib->sDevId.pszPDumpDevName);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+#else
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "WRW :%s:0x%08X :%s:PA_%08X%08X:0x%08X\r\n",
+ pszRegString,
+ ui32Reg,
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag,
+ (ui32Data & psMMUAttrib->ui32PDEMask) << psMMUAttrib->ui32PDEAlignShift,
+ ui32Data & ~psMMUAttrib->ui32PDEMask);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+#endif
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpPDReg (PDUMP_MMU_ATTRIB *psMMUAttrib,
+ IMG_UINT32 ui32Reg,
+ IMG_UINT32 ui32Data,
+ IMG_HANDLE hUniqueTag)
+{
+ return PDumpPDRegWithFlags(psMMUAttrib, ui32Reg, ui32Data, PDUMP_FLAGS_CONTINUOUS, hUniqueTag);
+}
+
+PVRSRV_ERROR PDumpMemPolKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask,
+ PDUMP_POLL_OPERATOR eOperator,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag)
+{
+ #define MEMPOLL_DELAY (1000)
+ #define MEMPOLL_COUNT (2000000000 / MEMPOLL_DELAY)
+
+ PVRSRV_ERROR eErr;
+ IMG_UINT32 ui32PageOffset;
+ IMG_UINT8 *pui8LinAddr;
+ IMG_DEV_PHYADDR sDevPAddr;
+ IMG_DEV_VIRTADDR sDevVPageAddr;
+ PDUMP_MMU_ATTRIB *psMMUAttrib;
+
+ PDUMP_GET_SCRIPT_STRING();
+ if ( _PDumpIsPersistent() )
+ {
+
+ return PVRSRV_OK;
+ }
+
+
+ PVR_ASSERT((ui32Offset + sizeof(IMG_UINT32)) <= psMemInfo->ui32AllocSize);
+
+ psMMUAttrib = ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->psMMUAttrib;
+
+
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "-- POL :%s:VA_%08X 0x%08X 0x%08X %d %d %d\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ psMemInfo->sDevVAddr.uiAddr + ui32Offset,
+ ui32Value,
+ ui32Mask,
+ eOperator,
+ MEMPOLL_COUNT,
+ MEMPOLL_DELAY);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+
+ pui8LinAddr = psMemInfo->pvLinAddrKM;
+
+
+ pui8LinAddr += ui32Offset;
+
+
+
+
+ PDumpOSCPUVAddrToPhysPages(psMemInfo->sMemBlk.hOSMemHandle,
+ ui32Offset,
+ pui8LinAddr,
+ psMMUAttrib->ui32DataPageMask,
+ &ui32PageOffset);
+
+
+ sDevVPageAddr.uiAddr = psMemInfo->sDevVAddr.uiAddr + ui32Offset - ui32PageOffset;
+
+ PVR_ASSERT((sDevVPageAddr.uiAddr & psMMUAttrib->ui32DataPageMask) == 0);
+
+
+ BM_GetPhysPageAddr(psMemInfo, sDevVPageAddr, &sDevPAddr);
+
+
+ sDevPAddr.uiAddr += ui32PageOffset;
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "POL :%s:PA_%08X%08X:0x%08X 0x%08X 0x%08X %d %d %d\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag,
+ sDevPAddr.uiAddr & ~(psMMUAttrib->ui32DataPageMask),
+ sDevPAddr.uiAddr & (psMMUAttrib->ui32DataPageMask),
+ ui32Value,
+ ui32Mask,
+ eOperator,
+ MEMPOLL_COUNT,
+ MEMPOLL_DELAY);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpMemKM(IMG_PVOID pvAltLinAddr,
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag)
+{
+ PVRSRV_ERROR eErr;
+ IMG_UINT32 ui32NumPages;
+ IMG_UINT32 ui32PageByteOffset;
+ IMG_UINT32 ui32BlockBytes;
+ IMG_UINT8* pui8LinAddr;
+ IMG_UINT8* pui8DataLinAddr = IMG_NULL;
+ IMG_DEV_VIRTADDR sDevVPageAddr;
+ IMG_DEV_VIRTADDR sDevVAddr;
+ IMG_DEV_PHYADDR sDevPAddr;
+ IMG_UINT32 ui32ParamOutPos;
+ PDUMP_MMU_ATTRIB *psMMUAttrib;
+ IMG_UINT32 ui32DataPageSize;
+
+ PDUMP_GET_SCRIPT_AND_FILE_STRING();
+
+ psMMUAttrib = ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->psMMUAttrib;
+
+
+
+ PVR_ASSERT((ui32Offset + ui32Bytes) <= psMemInfo->ui32AllocSize);
+
+ if (!PDumpOSJTInitialised())
+ {
+ return PVRSRV_ERROR_PDUMP_NOT_AVAILABLE;
+ }
+
+
+ if (ui32Bytes == 0 || PDumpOSIsSuspended())
+ {
+ return PVRSRV_OK;
+ }
+
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+
+ {
+ BM_HEAP *pHeap = ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap;
+ PVRSRV_DEVICE_NODE *psDeviceNode = pHeap->pBMContext->psDeviceNode;
+
+ if( psDeviceNode->pfnMMUIsHeapShared(pHeap->pMMUHeap) )
+ {
+ ui32Flags |= PDUMP_FLAGS_PERSISTENT;
+ }
+ }
+#endif
+
+
+ if(pvAltLinAddr)
+ {
+ pui8DataLinAddr = pvAltLinAddr;
+ }
+ else if(psMemInfo->pvLinAddrKM)
+ {
+ pui8DataLinAddr = (IMG_UINT8 *)psMemInfo->pvLinAddrKM + ui32Offset;
+ }
+ pui8LinAddr = (IMG_UINT8 *)psMemInfo->pvLinAddrKM;
+ sDevVAddr = psMemInfo->sDevVAddr;
+
+
+ sDevVAddr.uiAddr += ui32Offset;
+ pui8LinAddr += ui32Offset;
+
+ PVR_ASSERT(pui8DataLinAddr);
+
+ PDumpOSCheckForSplitting(PDumpOSGetStream(PDUMP_STREAM_PARAM2), ui32Bytes, ui32Flags);
+
+ ui32ParamOutPos = PDumpOSGetStreamOffset(PDUMP_STREAM_PARAM2);
+
+
+
+ if(!PDumpOSWriteString(PDumpOSGetStream(PDUMP_STREAM_PARAM2),
+ pui8DataLinAddr,
+ ui32Bytes,
+ ui32Flags))
+ {
+ return PVRSRV_ERROR_PDUMP_BUFFER_FULL;
+ }
+
+ if (PDumpOSGetParamFileNum() == 0)
+ {
+ eErr = PDumpOSSprintf(pszFileName, ui32MaxLenFileName, "%%0%%.prm");
+ }
+ else
+ {
+ eErr = PDumpOSSprintf(pszFileName, ui32MaxLenFileName, "%%0%%_%u.prm", PDumpOSGetParamFileNum());
+ }
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "-- LDB :%s:VA_%08X%08X:0x%08X 0x%08X 0x%08X %s\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag,
+ psMemInfo->sDevVAddr.uiAddr,
+ ui32Offset,
+ ui32Bytes,
+ ui32ParamOutPos,
+ pszFileName);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+
+
+
+ PDumpOSCPUVAddrToPhysPages(psMemInfo->sMemBlk.hOSMemHandle,
+ ui32Offset,
+ pui8LinAddr,
+ psMMUAttrib->ui32DataPageMask,
+ &ui32PageByteOffset);
+ ui32DataPageSize = psMMUAttrib->ui32DataPageMask + 1;
+ ui32NumPages = (ui32PageByteOffset + ui32Bytes + psMMUAttrib->ui32DataPageMask) / ui32DataPageSize;
+
+ while(ui32NumPages)
+ {
+ ui32NumPages--;
+
+
+ sDevVPageAddr.uiAddr = sDevVAddr.uiAddr - ui32PageByteOffset;
+
+ if (ui32DataPageSize <= PDUMP_TEMP_BUFFER_SIZE)
+ {
+
+ PVR_ASSERT((sDevVPageAddr.uiAddr & psMMUAttrib->ui32DataPageMask) == 0);
+ }
+
+
+ BM_GetPhysPageAddr(psMemInfo, sDevVPageAddr, &sDevPAddr);
+
+
+ sDevPAddr.uiAddr += ui32PageByteOffset;
+
+
+ if (ui32PageByteOffset + ui32Bytes > ui32DataPageSize)
+ {
+
+ ui32BlockBytes = ui32DataPageSize - ui32PageByteOffset;
+ }
+ else
+ {
+
+ ui32BlockBytes = ui32Bytes;
+ }
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "LDB :%s:PA_%08X%08X:0x%08X 0x%08X 0x%08X %s\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag,
+ sDevPAddr.uiAddr & ~(psMMUAttrib->ui32DataPageMask),
+ sDevPAddr.uiAddr & (psMMUAttrib->ui32DataPageMask),
+ ui32BlockBytes,
+ ui32ParamOutPos,
+ pszFileName);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+
+
+#if defined(SGX_FEATURE_VARIABLE_MMU_PAGE_SIZE)
+
+ ui32PageByteOffset = (ui32PageByteOffset + ui32BlockBytes) % ui32DataPageSize;
+#else
+
+ ui32PageByteOffset = 0;
+#endif
+
+ ui32Bytes -= ui32BlockBytes;
+
+ sDevVAddr.uiAddr += ui32BlockBytes;
+
+ pui8LinAddr += ui32BlockBytes;
+
+ ui32ParamOutPos += ui32BlockBytes;
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpMemPDEntriesKM(PDUMP_MMU_ATTRIB *psMMUAttrib,
+ IMG_HANDLE hOSMemHandle,
+ IMG_CPU_VIRTADDR pvLinAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_BOOL bInitialisePages,
+ IMG_HANDLE hUniqueTag1,
+ IMG_HANDLE hUniqueTag2)
+{
+ PDUMP_MMU_ATTRIB sMMUAttrib;
+
+
+ sMMUAttrib = *psMMUAttrib;
+ sMMUAttrib.ui32PTSize = HOST_PAGESIZE();
+ return PDumpMemPTEntriesKM( &sMMUAttrib,
+ hOSMemHandle,
+ pvLinAddr,
+ ui32Bytes,
+ ui32Flags,
+ bInitialisePages,
+ hUniqueTag1,
+ hUniqueTag2);
+}
+
+PVRSRV_ERROR PDumpMemPTEntriesKM(PDUMP_MMU_ATTRIB *psMMUAttrib,
+ IMG_HANDLE hOSMemHandle,
+ IMG_CPU_VIRTADDR pvLinAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_BOOL bInitialisePages,
+ IMG_HANDLE hUniqueTag1,
+ IMG_HANDLE hUniqueTag2)
+{
+ PVRSRV_ERROR eErr;
+ IMG_UINT32 ui32NumPages;
+ IMG_UINT32 ui32PageOffset;
+ IMG_UINT32 ui32BlockBytes;
+ IMG_UINT8* pui8LinAddr;
+ IMG_DEV_PHYADDR sDevPAddr;
+ IMG_CPU_PHYADDR sCpuPAddr;
+ IMG_UINT32 ui32Offset;
+ IMG_UINT32 ui32ParamOutPos;
+ IMG_UINT32 ui32PageMask;
+
+ PDUMP_GET_SCRIPT_AND_FILE_STRING();
+ ui32Flags |= ( _PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
+
+ if (!PDumpOSJTInitialised())
+ {
+ return PVRSRV_ERROR_PDUMP_NOT_AVAILABLE;
+ }
+
+ if (!pvLinAddr)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if (PDumpOSIsSuspended())
+ {
+ return PVRSRV_OK;
+ }
+
+ PDumpOSCheckForSplitting(PDumpOSGetStream(PDUMP_STREAM_PARAM2), ui32Bytes, ui32Flags);
+
+ ui32ParamOutPos = PDumpOSGetStreamOffset(PDUMP_STREAM_PARAM2);
+
+ if (bInitialisePages)
+ {
+
+
+
+ if (!PDumpOSWriteString(PDumpOSGetStream(PDUMP_STREAM_PARAM2),
+ pvLinAddr,
+ ui32Bytes,
+ ui32Flags | PDUMP_FLAGS_CONTINUOUS))
+ {
+ return PVRSRV_ERROR_PDUMP_BUFFER_FULL;
+ }
+
+ if (PDumpOSGetParamFileNum() == 0)
+ {
+ eErr = PDumpOSSprintf(pszFileName, ui32MaxLenFileName, "%%0%%.prm");
+ }
+ else
+ {
+ eErr = PDumpOSSprintf(pszFileName, ui32MaxLenFileName, "%%0%%_%u.prm", PDumpOSGetParamFileNum());
+ }
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ }
+
+
+
+
+
+
+ ui32PageMask = psMMUAttrib->ui32PTSize - 1;
+
+
+
+
+ ui32PageOffset = (IMG_UINT32)((IMG_UINTPTR_T)pvLinAddr & (psMMUAttrib->ui32PTSize - 1));
+ ui32NumPages = (ui32PageOffset + ui32Bytes + psMMUAttrib->ui32PTSize - 1) / psMMUAttrib->ui32PTSize;
+ pui8LinAddr = (IMG_UINT8*) pvLinAddr;
+
+ while (ui32NumPages)
+ {
+ ui32NumPages--;
+
+
+
+
+
+
+ sCpuPAddr = OSMapLinToCPUPhys(hOSMemHandle, pui8LinAddr);
+ sDevPAddr = SysCpuPAddrToDevPAddr(psMMUAttrib->sDevId.eDeviceType, sCpuPAddr);
+
+
+ if (ui32PageOffset + ui32Bytes > psMMUAttrib->ui32PTSize)
+ {
+
+ ui32BlockBytes = psMMUAttrib->ui32PTSize - ui32PageOffset;
+ }
+ else
+ {
+
+ ui32BlockBytes = ui32Bytes;
+ }
+
+
+
+
+ if (bInitialisePages)
+ {
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "LDB :%s:PA_%08X%08X:0x%08X 0x%08X 0x%08X %s\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag1,
+ sDevPAddr.uiAddr & ~ui32PageMask,
+ sDevPAddr.uiAddr & ui32PageMask,
+ ui32BlockBytes,
+ ui32ParamOutPos,
+ pszFileName);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags | PDUMP_FLAGS_CONTINUOUS);
+ }
+ else
+ {
+ for (ui32Offset = 0; ui32Offset < ui32BlockBytes; ui32Offset += sizeof(IMG_UINT32))
+ {
+ IMG_UINT32 ui32PTE = *((IMG_UINT32 *) (pui8LinAddr + ui32Offset));
+
+ if ((ui32PTE & psMMUAttrib->ui32PDEMask) != 0)
+ {
+
+#if defined(SGX_FEATURE_36BIT_MMU)
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "WRW :%s:$1 :%s:PA_%08X%08X:0x0\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ (IMG_UINT32)hUniqueTag2,
+ (ui32PTE & psMMUAttrib->ui32PDEMask) << psMMUAttrib->ui32PTEAlignShift);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags | PDUMP_FLAGS_CONTINUOUS);
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLenScript, "SHR :%s:$1 :%s:$1 0x4\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ psMMUAttrib->sDevId.pszPDumpDevName);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags | PDUMP_FLAGS_CONTINUOUS);
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLenScript, "OR :%s:$1 :%s:$1 0x%08X\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ ui32PTE & ~psMMUAttrib->ui32PDEMask);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags | PDUMP_FLAGS_CONTINUOUS);
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "WRW :%s:PA_%08X%08X:0x%08X :%s:$1\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ (IMG_UINT32)hUniqueTag1,
+ (sDevPAddr.uiAddr + ui32Offset) & ~ui32PageMask,
+ (sDevPAddr.uiAddr + ui32Offset) & ui32PageMask,
+ psMMUAttrib->sDevId.pszPDumpDevName);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags | PDUMP_FLAGS_CONTINUOUS);
+#else
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "WRW :%s:PA_%08X%08X:0x%08X :%s:PA_%08X%08X:0x%08X\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag1,
+ (sDevPAddr.uiAddr + ui32Offset) & ~ui32PageMask,
+ (sDevPAddr.uiAddr + ui32Offset) & ui32PageMask,
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag2,
+ (ui32PTE & psMMUAttrib->ui32PDEMask) << psMMUAttrib->ui32PTEAlignShift,
+ ui32PTE & ~psMMUAttrib->ui32PDEMask);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags | PDUMP_FLAGS_CONTINUOUS);
+#endif
+ }
+ else
+ {
+ PVR_ASSERT((ui32PTE & psMMUAttrib->ui32PTEValid) == 0UL);
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "WRW :%s:PA_%08X%08X:0x%08X 0x%08X%08X\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag1,
+ (sDevPAddr.uiAddr + ui32Offset) & ~ui32PageMask,
+ (sDevPAddr.uiAddr + ui32Offset) & ui32PageMask,
+ (ui32PTE << psMMUAttrib->ui32PTEAlignShift),
+ (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag2);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags | PDUMP_FLAGS_CONTINUOUS);
+ }
+ }
+ }
+
+
+
+
+ ui32PageOffset = 0;
+
+ ui32Bytes -= ui32BlockBytes;
+
+ pui8LinAddr += ui32BlockBytes;
+
+ ui32ParamOutPos += ui32BlockBytes;
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpPDDevPAddrKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Offset,
+ IMG_DEV_PHYADDR sPDDevPAddr,
+ IMG_HANDLE hUniqueTag1,
+ IMG_HANDLE hUniqueTag2)
+{
+ PVRSRV_ERROR eErr;
+ IMG_UINT32 ui32PageByteOffset;
+ IMG_DEV_VIRTADDR sDevVAddr;
+ IMG_DEV_VIRTADDR sDevVPageAddr;
+ IMG_DEV_PHYADDR sDevPAddr;
+ IMG_UINT32 ui32Flags = PDUMP_FLAGS_CONTINUOUS;
+ IMG_UINT32 ui32ParamOutPos;
+ PDUMP_MMU_ATTRIB *psMMUAttrib;
+ IMG_UINT32 ui32PageMask;
+
+ PDUMP_GET_SCRIPT_AND_FILE_STRING();
+
+ if (!PDumpOSJTInitialised())
+ {
+ return PVRSRV_ERROR_PDUMP_NOT_AVAILABLE;
+ }
+
+ psMMUAttrib = ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->psMMUAttrib;
+ ui32PageMask = psMMUAttrib->ui32PTSize - 1;
+
+ ui32ParamOutPos = PDumpOSGetStreamOffset(PDUMP_STREAM_PARAM2);
+
+
+ if(!PDumpOSWriteString(PDumpOSGetStream(PDUMP_STREAM_PARAM2),
+ (IMG_UINT8 *)&sPDDevPAddr,
+ sizeof(IMG_DEV_PHYADDR),
+ ui32Flags))
+ {
+ return PVRSRV_ERROR_PDUMP_BUFFER_FULL;
+ }
+
+ if (PDumpOSGetParamFileNum() == 0)
+ {
+ eErr = PDumpOSSprintf(pszFileName, ui32MaxLenFileName, "%%0%%.prm");
+ }
+ else
+ {
+ eErr = PDumpOSSprintf(pszFileName, ui32MaxLenFileName, "%%0%%_%u.prm", PDumpOSGetParamFileNum());
+ }
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "-- LDB :%s:PA_0x%08X%08X:0x%08X 0x%08X 0x%08X %s\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag1,
+ sPDDevPAddr.uiAddr & ~ui32PageMask,
+ sPDDevPAddr.uiAddr & ui32PageMask,
+ sizeof(IMG_DEV_PHYADDR),
+ ui32ParamOutPos,
+ pszFileName);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+
+ sDevVAddr = psMemInfo->sDevVAddr;
+ ui32PageByteOffset = sDevVAddr.uiAddr & ui32PageMask;
+
+ sDevVPageAddr.uiAddr = sDevVAddr.uiAddr - ui32PageByteOffset;
+ PVR_ASSERT((sDevVPageAddr.uiAddr & 0xFFF) == 0);
+
+ BM_GetPhysPageAddr(psMemInfo, sDevVPageAddr, &sDevPAddr);
+ sDevPAddr.uiAddr += ui32PageByteOffset + ui32Offset;
+
+ if ((sPDDevPAddr.uiAddr & psMMUAttrib->ui32PDEMask) != 0UL)
+ {
+#if defined(SGX_FEATURE_36BIT_MMU)
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "WRW :%s:$1 :%s:PA_%08X%08X:0x0\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ (IMG_UINT32)hUniqueTag2,
+ sPDDevPAddr.uiAddr);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLenScript, "AND :%s:$2 :%s:$1 0xFFFFFFFF\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ psMMUAttrib->sDevId.pszPDumpDevName);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "WRW :%s:PA_%08X%08X:0x%08X :%s:$2\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ (IMG_UINT32)hUniqueTag1,
+ (sDevPAddr.uiAddr) & ~(psMMUAttrib->ui32DataPageMask),
+ (sDevPAddr.uiAddr) & (psMMUAttrib->ui32DataPageMask),
+ psMMUAttrib->sDevId.pszPDumpDevName);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLenScript, "SHR :%s:$2 :%s:$1 0x20\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ psMMUAttrib->sDevId.pszPDumpDevName);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "WRW :%s:PA_%08X%08X:0x%08X :%s:$2\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ (IMG_UINT32)hUniqueTag1,
+ (sDevPAddr.uiAddr + 4) & ~(psMMUAttrib->ui32DataPageMask),
+ (sDevPAddr.uiAddr + 4) & (psMMUAttrib->ui32DataPageMask),
+ psMMUAttrib->sDevId.pszPDumpDevName);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+#else
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "WRW :%s:PA_%08X%08X:0x%08X :%s:PA_%08X%08X:0x%08X\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag1,
+ sDevPAddr.uiAddr & ~ui32PageMask,
+ sDevPAddr.uiAddr & ui32PageMask,
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag2,
+ sPDDevPAddr.uiAddr & psMMUAttrib->ui32PDEMask,
+ sPDDevPAddr.uiAddr & ~psMMUAttrib->ui32PDEMask);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+#endif
+ }
+ else
+ {
+ PVR_ASSERT(!(sDevPAddr.uiAddr & psMMUAttrib->ui32PTEValid));
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "WRW :%s:PA_%08X%08X:0x%08X 0x%08X\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag1,
+ sDevPAddr.uiAddr & ~ui32PageMask,
+ sDevPAddr.uiAddr & ui32PageMask,
+ sPDDevPAddr.uiAddr);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpCommentKM(IMG_CHAR *pszComment, IMG_UINT32 ui32Flags)
+{
+ PVRSRV_ERROR eErr;
+ IMG_CHAR pszCommentPrefix[] = "-- ";
+#if defined(PDUMP_DEBUG_OUTFILES)
+ IMG_CHAR pszTemp[256];
+#endif
+ IMG_UINT32 ui32LenCommentPrefix;
+ PDUMP_GET_SCRIPT_STRING();
+ PDUMP_DBG(("PDumpCommentKM"));
+#if defined(PDUMP_DEBUG_OUTFILES)
+
+ ui32Flags |= ( _PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
+#endif
+
+ PDumpOSVerifyLineEnding(pszComment, ui32MaxLen);
+
+
+ ui32LenCommentPrefix = PDumpOSBuflen(pszCommentPrefix, sizeof(pszCommentPrefix));
+
+
+ if (!PDumpOSWriteString(PDumpOSGetStream(PDUMP_STREAM_SCRIPT2),
+ (IMG_UINT8*)pszCommentPrefix,
+ ui32LenCommentPrefix,
+ ui32Flags))
+ {
+ if(ui32Flags & PDUMP_FLAGS_CONTINUOUS)
+ {
+ return PVRSRV_ERROR_PDUMP_BUFFER_FULL;
+ }
+ else
+ {
+ return PVRSRV_ERROR_CMD_NOT_PROCESSED;
+ }
+ }
+#if defined(PDUMP_DEBUG_OUTFILES)
+
+ eErr = PDumpOSSprintf(pszTemp, 256, "%d-%d %s",
+ _PDumpGetPID(),
+ g_ui32EveryLineCounter,
+ pszComment);
+
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "%s",
+ pszTemp);
+#else
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "%s",
+ pszComment);
+#endif
+ if( (eErr != PVRSRV_OK) &&
+ (eErr != PVRSRV_ERROR_PDUMP_BUF_OVERFLOW))
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpCommentWithFlags(IMG_UINT32 ui32Flags, IMG_CHAR * pszFormat, ...)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_va_list ap;
+ PDUMP_GET_MSG_STRING();
+
+
+ PDUMP_va_start(ap, pszFormat);
+ eErr = PDumpOSVSprintf(pszMsg, ui32MaxLen, pszFormat, ap);
+ PDUMP_va_end(ap);
+
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ return PDumpCommentKM(pszMsg, ui32Flags);
+}
+
+PVRSRV_ERROR PDumpComment(IMG_CHAR *pszFormat, ...)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_va_list ap;
+ PDUMP_GET_MSG_STRING();
+
+
+ PDUMP_va_start(ap, pszFormat);
+ eErr = PDumpOSVSprintf(pszMsg, ui32MaxLen, pszFormat, ap);
+ PDUMP_va_end(ap);
+
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ return PDumpCommentKM(pszMsg, PDUMP_FLAGS_CONTINUOUS);
+}
+
+PVRSRV_ERROR PDumpDriverInfoKM(IMG_CHAR *pszString, IMG_UINT32 ui32Flags)
+{
+ PVRSRV_ERROR eErr;
+ IMG_UINT32 ui32MsgLen;
+ PDUMP_GET_MSG_STRING();
+
+
+ eErr = PDumpOSSprintf(pszMsg, ui32MaxLen, "%s", pszString);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+
+ PDumpOSVerifyLineEnding(pszMsg, ui32MaxLen);
+ ui32MsgLen = PDumpOSBuflen(pszMsg, ui32MaxLen);
+
+ if (!PDumpOSWriteString(PDumpOSGetStream(PDUMP_STREAM_DRIVERINFO),
+ (IMG_UINT8*)pszMsg,
+ ui32MsgLen,
+ ui32Flags))
+ {
+ if (ui32Flags & PDUMP_FLAGS_CONTINUOUS)
+ {
+ return PVRSRV_ERROR_PDUMP_BUFFER_FULL;
+ }
+ else
+ {
+ return PVRSRV_ERROR_CMD_NOT_PROCESSED;
+ }
+ }
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpBitmapKM( PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32FileOffset,
+ IMG_UINT32 ui32Width,
+ IMG_UINT32 ui32Height,
+ IMG_UINT32 ui32StrideInBytes,
+ IMG_DEV_VIRTADDR sDevBaseAddr,
+ IMG_HANDLE hDevMemContext,
+ IMG_UINT32 ui32Size,
+ PDUMP_PIXEL_FORMAT ePixelFormat,
+ PDUMP_MEM_FORMAT eMemFormat,
+ IMG_UINT32 ui32PDumpFlags)
+{
+ PVRSRV_DEVICE_IDENTIFIER *psDevId = &psDeviceNode->sDevId;
+
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING();
+
+ if ( _PDumpIsPersistent() )
+ {
+ return PVRSRV_OK;
+ }
+
+ PDumpCommentWithFlags(ui32PDumpFlags, "\r\n-- Dump bitmap of render\r\n");
+
+
+
+
+ PVR_UNREFERENCED_PARAMETER(hDevMemContext);
+
+#if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "SII %s %s.bin :%s:v%x:0x%08X 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X\r\n",
+ pszFileName,
+ pszFileName,
+ psDevId->pszPDumpDevName,
+ PDUMP_DATAMASTER_PIXEL,
+ sDevBaseAddr.uiAddr,
+ ui32Size,
+ ui32FileOffset,
+ ePixelFormat,
+ ui32Width,
+ ui32Height,
+ ui32StrideInBytes,
+ eMemFormat);
+#else
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "SII %s %s.bin :%s:v:0x%08X 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X\r\n",
+ pszFileName,
+ pszFileName,
+ psDevId->pszPDumpDevName,
+ sDevBaseAddr.uiAddr,
+ ui32Size,
+ ui32FileOffset,
+ ePixelFormat,
+ ui32Width,
+ ui32Height,
+ ui32StrideInBytes,
+ eMemFormat);
+#endif
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+ PDumpOSWriteString2( hScript, ui32PDumpFlags);
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpReadRegKM ( IMG_CHAR *pszPDumpRegName,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32FileOffset,
+ IMG_UINT32 ui32Address,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32PDumpFlags)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING();
+
+ PVR_UNREFERENCED_PARAMETER(ui32Size);
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "SAB :%s:0x%08X 0x%08X %s\r\n",
+ pszPDumpRegName,
+ ui32Address,
+ ui32FileOffset,
+ pszFileName);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+ PDumpOSWriteString2( hScript, ui32PDumpFlags);
+
+ return PVRSRV_OK;
+}
+
+IMG_BOOL PDumpTestNextFrame(IMG_UINT32 ui32CurrentFrame)
+{
+ IMG_BOOL bFrameDumped;
+
+
+
+ (IMG_VOID) PDumpSetFrameKM(ui32CurrentFrame + 1);
+ bFrameDumped = PDumpIsCaptureFrameKM();
+ (IMG_VOID) PDumpSetFrameKM(ui32CurrentFrame);
+
+ return bFrameDumped;
+}
+
+static PVRSRV_ERROR PDumpSignatureRegister (PVRSRV_DEVICE_IDENTIFIER *psDevId,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32Address,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 *pui32FileOffset,
+ IMG_UINT32 ui32Flags)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING();
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "SAB :%s:0x%08X 0x%08X %s\r\n",
+ psDevId->pszPDumpRegName,
+ ui32Address,
+ *pui32FileOffset,
+ pszFileName);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+ PDumpOSWriteString2(hScript, ui32Flags);
+ *pui32FileOffset += ui32Size;
+ return PVRSRV_OK;
+}
+
+static IMG_VOID PDumpRegisterRange(PVRSRV_DEVICE_IDENTIFIER *psDevId,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 *pui32Registers,
+ IMG_UINT32 ui32NumRegisters,
+ IMG_UINT32 *pui32FileOffset,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32Flags)
+{
+ IMG_UINT32 i;
+ for (i = 0; i < ui32NumRegisters; i++)
+ {
+ PDumpSignatureRegister(psDevId, pszFileName, pui32Registers[i], ui32Size, pui32FileOffset, ui32Flags);
+ }
+}
+
+PVRSRV_ERROR PDump3DSignatureRegisters(PVRSRV_DEVICE_IDENTIFIER *psDevId,
+ IMG_UINT32 ui32DumpFrameNum,
+ IMG_BOOL bLastFrame,
+ IMG_UINT32 *pui32Registers,
+ IMG_UINT32 ui32NumRegisters)
+{
+ PVRSRV_ERROR eErr;
+ IMG_UINT32 ui32FileOffset, ui32Flags;
+
+ PDUMP_GET_FILE_STRING();
+
+ ui32Flags = bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0;
+ ui32FileOffset = 0;
+
+ PDumpCommentWithFlags(ui32Flags, "\r\n-- Dump 3D signature registers\r\n");
+ eErr = PDumpOSSprintf(pszFileName, ui32MaxLen, "out%u_3d.sig", ui32DumpFrameNum);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+ PDumpRegisterRange(psDevId,
+ pszFileName,
+ pui32Registers,
+ ui32NumRegisters,
+ &ui32FileOffset,
+ sizeof(IMG_UINT32),
+ ui32Flags);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpTASignatureRegisters (PVRSRV_DEVICE_IDENTIFIER *psDevId,
+ IMG_UINT32 ui32DumpFrameNum,
+ IMG_UINT32 ui32TAKickCount,
+ IMG_BOOL bLastFrame,
+ IMG_UINT32 *pui32Registers,
+ IMG_UINT32 ui32NumRegisters)
+{
+ PVRSRV_ERROR eErr;
+ IMG_UINT32 ui32FileOffset, ui32Flags;
+
+ PDUMP_GET_FILE_STRING();
+
+ ui32Flags = bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0;
+ ui32FileOffset = ui32TAKickCount * ui32NumRegisters * sizeof(IMG_UINT32);
+
+ PDumpCommentWithFlags(ui32Flags, "\r\n-- Dump TA signature registers\r\n");
+ eErr = PDumpOSSprintf(pszFileName, ui32MaxLen, "out%u_ta.sig", ui32DumpFrameNum);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+ PDumpRegisterRange(psDevId,
+ pszFileName,
+ pui32Registers,
+ ui32NumRegisters,
+ &ui32FileOffset,
+ sizeof(IMG_UINT32),
+ ui32Flags);
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpCounterRegisters (PVRSRV_DEVICE_IDENTIFIER *psDevId,
+ IMG_UINT32 ui32DumpFrameNum,
+ IMG_BOOL bLastFrame,
+ IMG_UINT32 *pui32Registers,
+ IMG_UINT32 ui32NumRegisters)
+{
+ PVRSRV_ERROR eErr;
+ IMG_UINT32 ui32FileOffset, ui32Flags;
+
+ PDUMP_GET_FILE_STRING();
+
+ ui32Flags = bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0UL;
+ ui32FileOffset = 0UL;
+
+ PDumpCommentWithFlags(ui32Flags, "\r\n-- Dump counter registers\r\n");
+ eErr = PDumpOSSprintf(pszFileName, ui32MaxLen, "out%u.perf", ui32DumpFrameNum);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+ PDumpRegisterRange(psDevId,
+ pszFileName,
+ pui32Registers,
+ ui32NumRegisters,
+ &ui32FileOffset,
+ sizeof(IMG_UINT32),
+ ui32Flags);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpRegRead(IMG_CHAR *pszPDumpRegName,
+ const IMG_UINT32 ui32RegOffset,
+ IMG_UINT32 ui32Flags)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING();
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "RDW :%s:0x%X\r\n",
+ pszPDumpRegName,
+ ui32RegOffset);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpSaveMemKM (PVRSRV_DEVICE_IDENTIFIER *psDevId,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32FileOffset,
+ IMG_DEV_VIRTADDR sDevBaseAddr,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32DataMaster,
+ IMG_UINT32 ui32PDumpFlags)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING();
+
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+ PVR_UNREFERENCED_PARAMETER(ui32DataMaster);
+#endif
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+#if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+ "SAB :%s:v%x:0x%08X 0x%08X 0x%08X %s.bin\r\n",
+ psDevId->pszPDumpDevName,
+ ui32DataMaster,
+#else
+ "SAB :%s:v:0x%08X 0x%08X 0x%08X %s.bin\r\n",
+ psDevId->pszPDumpDevName,
+#endif
+ sDevBaseAddr.uiAddr,
+ ui32Size,
+ ui32FileOffset,
+ pszFileName);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+
+ PDumpOSWriteString2(hScript, ui32PDumpFlags);
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpCycleCountRegRead(PVRSRV_DEVICE_IDENTIFIER *psDevId,
+ const IMG_UINT32 ui32RegOffset,
+ IMG_BOOL bLastFrame)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING();
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "RDW :%s:0x%X\r\n",
+ psDevId->pszPDumpRegName,
+ ui32RegOffset);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0);
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PDumpSignatureBuffer (PVRSRV_DEVICE_IDENTIFIER *psDevId,
+ IMG_CHAR *pszFileName,
+ IMG_CHAR *pszBufferType,
+ IMG_UINT32 ui32FileOffset,
+ IMG_DEV_VIRTADDR sDevBaseAddr,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32PDumpFlags)
+{
+ PDumpCommentWithFlags(ui32PDumpFlags, "\r\n-- Dump microkernel %s signature Buffer\r\n",
+ pszBufferType);
+ PDumpCommentWithFlags(ui32PDumpFlags, "Buffer format (sizes in 32-bit words):\r\n");
+ PDumpCommentWithFlags(ui32PDumpFlags, "\tNumber of signatures per sample (1)\r\n");
+ PDumpCommentWithFlags(ui32PDumpFlags, "\tNumber of samples (1)\r\n");
+ PDumpCommentWithFlags(ui32PDumpFlags, "\tSignature register offsets (1 * number of signatures)\r\n");
+ PDumpCommentWithFlags(ui32PDumpFlags, "\tSignature sample values (number of samples * number of signatures)\r\n");
+ PDumpCommentWithFlags(ui32PDumpFlags, "Note: If buffer is full, last sample is final state after test completed\r\n");
+ return PDumpSaveMemKM(psDevId, pszFileName, ui32FileOffset, sDevBaseAddr, ui32Size,
+ PDUMP_DATAMASTER_EDM, ui32PDumpFlags);
+}
+
+
+PVRSRV_ERROR PDumpHWPerfCBKM (PVRSRV_DEVICE_IDENTIFIER *psDevId,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32FileOffset,
+ IMG_DEV_VIRTADDR sDevBaseAddr,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32PDumpFlags)
+{
+ PDumpCommentWithFlags(ui32PDumpFlags, "\r\n-- Dump Hardware Performance Circular Buffer\r\n");
+ return PDumpSaveMemKM(psDevId, pszFileName, ui32FileOffset, sDevBaseAddr, ui32Size,
+ PDUMP_DATAMASTER_EDM, ui32PDumpFlags);
+}
+
+
+PVRSRV_ERROR PDumpCBP(PPVRSRV_KERNEL_MEM_INFO psROffMemInfo,
+ IMG_UINT32 ui32ROffOffset,
+ IMG_UINT32 ui32WPosVal,
+ IMG_UINT32 ui32PacketSize,
+ IMG_UINT32 ui32BufferSize,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag)
+{
+ PVRSRV_ERROR eErr;
+ IMG_UINT32 ui32PageOffset;
+ IMG_UINT8 *pui8LinAddr;
+ IMG_DEV_VIRTADDR sDevVAddr;
+ IMG_DEV_PHYADDR sDevPAddr;
+ IMG_DEV_VIRTADDR sDevVPageAddr;
+
+ PDUMP_MMU_ATTRIB *psMMUAttrib;
+
+ PDUMP_GET_SCRIPT_STRING();
+
+ psMMUAttrib = ((BM_BUF*)psROffMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->psMMUAttrib;
+
+
+ PVR_ASSERT((ui32ROffOffset + sizeof(IMG_UINT32)) <= psROffMemInfo->ui32AllocSize);
+
+ pui8LinAddr = psROffMemInfo->pvLinAddrKM;
+ sDevVAddr = psROffMemInfo->sDevVAddr;
+
+
+ pui8LinAddr += ui32ROffOffset;
+ sDevVAddr.uiAddr += ui32ROffOffset;
+
+
+
+
+ PDumpOSCPUVAddrToPhysPages(psROffMemInfo->sMemBlk.hOSMemHandle,
+ ui32ROffOffset,
+ pui8LinAddr,
+ psMMUAttrib->ui32DataPageMask,
+ &ui32PageOffset);
+
+
+ sDevVPageAddr.uiAddr = sDevVAddr.uiAddr - ui32PageOffset;
+
+ PVR_ASSERT((sDevVPageAddr.uiAddr & 0xFFF) == 0);
+
+
+ BM_GetPhysPageAddr(psROffMemInfo, sDevVPageAddr, &sDevPAddr);
+
+
+ sDevPAddr.uiAddr += ui32PageOffset;
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "CBP :%s:PA_%08X%08X:0x%08X 0x%08X 0x%08X 0x%08X\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag,
+ sDevPAddr.uiAddr & ~(psMMUAttrib->ui32DataPageMask),
+ sDevPAddr.uiAddr & (psMMUAttrib->ui32DataPageMask),
+ ui32WPosVal,
+ ui32PacketSize,
+ ui32BufferSize);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PDumpIDLWithFlags(IMG_UINT32 ui32Clocks, IMG_UINT32 ui32Flags)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING();
+ PDUMP_DBG(("PDumpIDLWithFlags"));
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "IDL %u\r\n", ui32Clocks);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PDumpIDL(IMG_UINT32 ui32Clocks)
+{
+ return PDumpIDLWithFlags(ui32Clocks, PDUMP_FLAGS_CONTINUOUS);
+}
+
+PVRSRV_ERROR PDumpMemUM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_PVOID pvAltLinAddrUM,
+ IMG_PVOID pvLinAddrUM,
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag)
+{
+ IMG_VOID *pvAddrUM;
+ IMG_VOID *pvAddrKM;
+ IMG_UINT32 ui32BytesDumped;
+ IMG_UINT32 ui32CurrentOffset;
+
+ if (psMemInfo->pvLinAddrKM != IMG_NULL && pvAltLinAddrUM == IMG_NULL)
+ {
+
+ return PDumpMemKM(IMG_NULL,
+ psMemInfo,
+ ui32Offset,
+ ui32Bytes,
+ ui32Flags,
+ hUniqueTag);
+ }
+
+ pvAddrUM = (pvAltLinAddrUM != IMG_NULL) ? pvAltLinAddrUM : ((pvLinAddrUM != IMG_NULL) ? VPTR_PLUS(pvLinAddrUM, ui32Offset) : IMG_NULL);
+
+ pvAddrKM = GetTempBuffer();
+
+
+ PVR_ASSERT(pvAddrUM != IMG_NULL && pvAddrKM != IMG_NULL);
+ if (pvAddrUM == IMG_NULL || pvAddrKM == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpMemUM: Nothing to dump"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if (ui32Bytes > PDUMP_TEMP_BUFFER_SIZE)
+ {
+ PDumpCommentWithFlags(ui32Flags, "Dumping 0x%08x bytes of memory, in blocks of 0x%08x bytes", ui32Bytes, (IMG_UINT32)PDUMP_TEMP_BUFFER_SIZE);
+ }
+
+ ui32CurrentOffset = ui32Offset;
+ for (ui32BytesDumped = 0; ui32BytesDumped < ui32Bytes;)
+ {
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32BytesToDump = MIN(PDUMP_TEMP_BUFFER_SIZE, ui32Bytes - ui32BytesDumped);
+
+ eError = OSCopyFromUser(psPerProc,
+ pvAddrKM,
+ pvAddrUM,
+ ui32BytesToDump);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpMemUM: OSCopyFromUser failed (%d)", eError));
+ return eError;
+ }
+
+ eError = PDumpMemKM(pvAddrKM,
+ psMemInfo,
+ ui32CurrentOffset,
+ ui32BytesToDump,
+ ui32Flags,
+ hUniqueTag);
+
+ if (eError != PVRSRV_OK)
+ {
+
+ if (ui32BytesDumped != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpMemUM: PDumpMemKM failed (%d)", eError));
+ }
+ PVR_ASSERT(ui32BytesDumped == 0);
+ return eError;
+ }
+
+ VPTR_INC(pvAddrUM, ui32BytesToDump);
+ ui32CurrentOffset += ui32BytesToDump;
+ ui32BytesDumped += ui32BytesToDump;
+ }
+
+ return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR _PdumpAllocMMUContext(IMG_UINT32 *pui32MMUContextID)
+{
+ IMG_UINT32 i;
+
+
+ for(i=0; i<MAX_PDUMP_MMU_CONTEXTS; i++)
+ {
+ if((gui16MMUContextUsage & (1U << i)) == 0)
+ {
+
+ gui16MMUContextUsage |= 1U << i;
+ *pui32MMUContextID = i;
+ return PVRSRV_OK;
+ }
+ }
+
+ PVR_DPF((PVR_DBG_ERROR, "_PdumpAllocMMUContext: no free MMU context ids"));
+
+ return PVRSRV_ERROR_MMU_CONTEXT_NOT_FOUND;
+}
+
+
+static PVRSRV_ERROR _PdumpFreeMMUContext(IMG_UINT32 ui32MMUContextID)
+{
+ if(ui32MMUContextID < MAX_PDUMP_MMU_CONTEXTS)
+ {
+
+ gui16MMUContextUsage &= ~(1U << ui32MMUContextID);
+ return PVRSRV_OK;
+ }
+
+ PVR_DPF((PVR_DBG_ERROR, "_PdumpFreeMMUContext: MMU context ids invalid"));
+
+ return PVRSRV_ERROR_MMU_CONTEXT_NOT_FOUND;
+}
+
+
+PVRSRV_ERROR PDumpSetMMUContext(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_CHAR *pszMemSpace,
+ IMG_UINT32 *pui32MMUContextID,
+ IMG_UINT32 ui32MMUType,
+ IMG_HANDLE hUniqueTag1,
+ IMG_HANDLE hOSMemHandle,
+ IMG_VOID *pvPDCPUAddr)
+{
+ IMG_UINT8 *pui8LinAddr = (IMG_UINT8 *)pvPDCPUAddr;
+ IMG_CPU_PHYADDR sCpuPAddr;
+ IMG_DEV_PHYADDR sDevPAddr;
+ IMG_UINT32 ui32MMUContextID;
+ PVRSRV_ERROR eError;
+
+ eError = _PdumpAllocMMUContext(&ui32MMUContextID);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpSetMMUContext: _PdumpAllocMMUContext failed: %d", eError));
+ return eError;
+ }
+
+
+
+ sCpuPAddr = OSMapLinToCPUPhys(hOSMemHandle, pui8LinAddr);
+ sDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
+
+ sDevPAddr.uiAddr &= ~((PVRSRV_4K_PAGE_SIZE) -1);
+
+ PDumpComment("Set MMU Context\r\n");
+
+ PDumpComment("MMU :%s:v%d %d :%s:PA_%08X%08X\r\n",
+ pszMemSpace,
+ ui32MMUContextID,
+ ui32MMUType,
+ pszMemSpace,
+ (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag1,
+ sDevPAddr.uiAddr);
+
+
+ *pui32MMUContextID = ui32MMUContextID;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PDumpClearMMUContext(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_CHAR *pszMemSpace,
+ IMG_UINT32 ui32MMUContextID,
+ IMG_UINT32 ui32MMUType)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_UNREFERENCED_PARAMETER(eDeviceType);
+
+
+ PDumpComment("Clear MMU Context for memory space %s\r\n", pszMemSpace);
+
+ PDumpComment("MMU :%s:v%d %d\r\n",
+ pszMemSpace,
+ ui32MMUContextID,
+ ui32MMUType);
+
+ eError = _PdumpFreeMMUContext(ui32MMUContextID);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpClearMMUContext: _PdumpFreeMMUContext failed: %d", eError));
+ return eError;
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpStoreMemToFile(PDUMP_MMU_ATTRIB *psMMUAttrib,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32FileOffset,
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 uiAddr,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32PDumpFlags,
+ IMG_HANDLE hUniqueTag)
+{
+ IMG_DEV_PHYADDR sDevPAddr;
+ IMG_DEV_VIRTADDR sDevVPageAddr;
+ IMG_UINT32 ui32PageOffset;
+
+ PDUMP_GET_SCRIPT_STRING();
+
+
+
+
+ ui32PageOffset = (IMG_UINT32)psMemInfo->pvLinAddrKM & psMMUAttrib->ui32DataPageMask;
+
+
+ sDevVPageAddr.uiAddr = uiAddr - ui32PageOffset;
+
+
+ BM_GetPhysPageAddr(psMemInfo, sDevVPageAddr, &sDevPAddr);
+
+
+ sDevPAddr.uiAddr += ui32PageOffset;
+
+ PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "SAB :%s:PA_%08X%08X:0x%08X 0x%08X 0x%08X %s\r\n",
+ psMMUAttrib->sDevId.pszPDumpDevName,
+ (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag,
+ sDevPAddr.uiAddr & ~psMMUAttrib->ui32DataPageMask,
+ sDevPAddr.uiAddr & psMMUAttrib->ui32DataPageMask,
+ ui32Size,
+ ui32FileOffset,
+ pszFileName);
+
+ PDumpOSWriteString2(hScript, ui32PDumpFlags);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpRegBasedCBP(IMG_CHAR *pszPDumpRegName,
+ IMG_UINT32 ui32RegOffset,
+ IMG_UINT32 ui32WPosVal,
+ IMG_UINT32 ui32PacketSize,
+ IMG_UINT32 ui32BufferSize,
+ IMG_UINT32 ui32Flags)
+{
+ PDUMP_GET_SCRIPT_STRING();
+
+ PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "CBP :%s:0x%08X 0x%08X 0x%08X 0x%08X\r\n",
+ pszPDumpRegName,
+ ui32RegOffset,
+ ui32WPosVal,
+ ui32PacketSize,
+ ui32BufferSize);
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+ return PVRSRV_OK;
+}
+
+
+#include "syscommon.h"
+
+IMG_EXPORT IMG_VOID PDumpConnectionNotify(IMG_VOID)
+{
+ SYS_DATA *psSysData;
+ PVRSRV_DEVICE_NODE *psThis;
+ PVR_DPF((PVR_DBG_WARNING, "PDump has connected."));
+
+
+ SysAcquireData(&psSysData);
+
+ psThis = psSysData->psDeviceNodeList;
+ while (psThis)
+ {
+ if (psThis->pfnPDumpInitDevice)
+ {
+
+ psThis->pfnPDumpInitDevice(psThis);
+ }
+ psThis = psThis->psNext;
+ }
+}
+
+IMG_UINT32 DbgWrite(PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32BCount, IMG_UINT32 ui32Flags)
+{
+ IMG_UINT32 ui32BytesWritten = 0;
+ IMG_UINT32 ui32Off = 0;
+ PDBG_STREAM_CONTROL psCtrl = psStream->psCtrl;
+
+
+ if ((ui32Flags & PDUMP_FLAGS_NEVER) != 0)
+ {
+ return ui32BCount;
+ }
+
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+
+ if ( (_PDumpIsProcessActive() == IMG_FALSE ) &&
+ ((ui32Flags & PDUMP_FLAGS_PERSISTENT) == 0) )
+ {
+ return ui32BCount;
+ }
+#endif
+
+
+ if ( ((ui32Flags & PDUMP_FLAGS_PERSISTENT) != 0) && (psCtrl->bInitPhaseComplete) )
+ {
+ while (((IMG_UINT32) ui32BCount > 0) && (ui32BytesWritten != 0xFFFFFFFFU))
+ {
+
+
+
+ ui32BytesWritten = PDumpOSDebugDriverWrite( psStream,
+ PDUMP_WRITE_MODE_PERSISTENT,
+ &pui8Data[ui32Off], ui32BCount, 1, 0);
+
+ if (ui32BytesWritten == 0)
+ {
+ PDumpOSReleaseExecution();
+ }
+
+ if (ui32BytesWritten != 0xFFFFFFFFU)
+ {
+ ui32Off += ui32BytesWritten;
+ ui32BCount -= ui32BytesWritten;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "DbgWrite: Failed to send persistent data"));
+ if( (psCtrl->ui32Flags & DEBUG_FLAGS_READONLY) != 0)
+ {
+
+ PDumpSuspendKM();
+ }
+ return 0xFFFFFFFFU;
+ }
+ }
+
+
+ ui32BCount = ui32Off; ui32Off = 0; ui32BytesWritten = 0;
+ }
+
+ while (((IMG_UINT32) ui32BCount > 0) && (ui32BytesWritten != 0xFFFFFFFFU))
+ {
+ if ((ui32Flags & PDUMP_FLAGS_CONTINUOUS) != 0)
+ {
+
+
+ if (((psCtrl->ui32CapMode & DEBUG_CAPMODE_FRAMED) != 0) &&
+ (psCtrl->ui32Start == 0xFFFFFFFFU) &&
+ (psCtrl->ui32End == 0xFFFFFFFFU) &&
+ psCtrl->bInitPhaseComplete)
+ {
+ ui32BytesWritten = ui32BCount;
+ }
+ else
+ {
+ ui32BytesWritten = PDumpOSDebugDriverWrite( psStream,
+ PDUMP_WRITE_MODE_CONTINUOUS,
+ &pui8Data[ui32Off], ui32BCount, 1, 0);
+ }
+ }
+ else
+ {
+ if (ui32Flags & PDUMP_FLAGS_LASTFRAME)
+ {
+ IMG_UINT32 ui32DbgFlags;
+
+ ui32DbgFlags = 0;
+ if (ui32Flags & PDUMP_FLAGS_RESETLFBUFFER)
+ {
+ ui32DbgFlags |= WRITELF_FLAGS_RESETBUF;
+ }
+
+ ui32BytesWritten = PDumpOSDebugDriverWrite( psStream,
+ PDUMP_WRITE_MODE_LASTFRAME,
+ &pui8Data[ui32Off], ui32BCount, 1, ui32DbgFlags);
+ }
+ else
+ {
+ ui32BytesWritten = PDumpOSDebugDriverWrite( psStream,
+ PDUMP_WRITE_MODE_BINCM,
+ &pui8Data[ui32Off], ui32BCount, 1, 0);
+ }
+ }
+
+
+
+
+ if (ui32BytesWritten == 0)
+ {
+ PDumpOSReleaseExecution();
+ }
+
+ if (ui32BytesWritten != 0xFFFFFFFFU)
+ {
+ ui32Off += ui32BytesWritten;
+ ui32BCount -= ui32BytesWritten;
+ }
+
+
+ }
+
+
+
+ return ui32BytesWritten;
+}
+
+
+
+#else
+#endif
--- /dev/null
+/**********************************************************************
+ *
+ * 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/sched.h>
+
+#include "services_headers.h"
+#include "resman.h"
+#include "handle.h"
+#include "perproc.h"
+#include "osperproc.h"
+#if defined(PERPROC_LIST)
+#include "lists.h"
+#endif
+#define HASH_TAB_INIT_SIZE 32
+
+static HASH_TABLE *psHashTab = IMG_NULL;
+#if defined(PERPROC_LIST)
+static PVRSRV_PER_PROCESS_DATA *psPerProcList = IMG_NULL;
+#endif
+static PVRSRV_ERROR FreePerProcessData(PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_ERROR eError;
+ IMG_UINTPTR_T uiPerProc;
+
+ PVR_ASSERT(psPerProc != IMG_NULL);
+
+ if (psPerProc == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: invalid parameter"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ uiPerProc = HASH_Remove(psHashTab, (IMG_UINTPTR_T)psPerProc->ui32PID);
+ if (uiPerProc == 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: Couldn't find process in per-process data hash table"));
+
+ PVR_ASSERT(psPerProc->ui32PID == 0);
+ }
+ else
+ {
+ PVR_ASSERT((PVRSRV_PER_PROCESS_DATA *)uiPerProc == psPerProc);
+ PVR_ASSERT(((PVRSRV_PER_PROCESS_DATA *)uiPerProc)->ui32PID == psPerProc->ui32PID);
+ }
+#if defined(PERPROC_LIST)
+ List_PVRSRV_PER_PROCESS_DATA_Remove(psPerProc);
+ /*PVR_LOG(("MarkTu free perproce %d\n", psPerProc->ui32PID));*/
+#endif
+
+ if (psPerProc->psHandleBase != IMG_NULL)
+ {
+ eError = PVRSRVFreeHandleBase(psPerProc->psHandleBase);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: Couldn't free handle base for process (%d)", eError));
+ return eError;
+ }
+ }
+
+
+ if (psPerProc->hPerProcData != IMG_NULL)
+ {
+ eError = PVRSRVReleaseHandle(KERNEL_HANDLE_BASE, psPerProc->hPerProcData, PVRSRV_HANDLE_TYPE_PERPROC_DATA);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: Couldn't release per-process data handle (%d)", eError));
+ return eError;
+ }
+ }
+
+
+ eError = OSPerProcessPrivateDataDeInit(psPerProc->hOsPrivateData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: OSPerProcessPrivateDataDeInit failed (%d)", eError));
+ return eError;
+ }
+
+ eError = OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(*psPerProc),
+ psPerProc,
+ psPerProc->hBlockAlloc);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: Couldn't free per-process data (%d)", eError));
+ return eError;
+ }
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_PER_PROCESS_DATA *PVRSRVPerProcessData(IMG_UINT32 ui32PID)
+{
+ PVRSRV_PER_PROCESS_DATA *psPerProc;
+
+ PVR_ASSERT(psHashTab != IMG_NULL);
+
+
+ psPerProc = (PVRSRV_PER_PROCESS_DATA *)HASH_Retrieve(psHashTab, (IMG_UINTPTR_T)ui32PID);
+ return psPerProc;
+}
+
+
+PVRSRV_ERROR PVRSRVPerProcessDataConnect(IMG_UINT32 ui32PID, IMG_UINT32 ui32Flags)
+{
+ PVRSRV_PER_PROCESS_DATA *psPerProc;
+ IMG_HANDLE hBlockAlloc;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ PVR_ASSERT(psHashTab != IMG_NULL);
+
+
+ psPerProc = (PVRSRV_PER_PROCESS_DATA *)HASH_Retrieve(psHashTab, (IMG_UINTPTR_T)ui32PID);
+
+ if (psPerProc == IMG_NULL)
+ {
+
+ eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(*psPerProc),
+ (IMG_PVOID *)&psPerProc,
+ &hBlockAlloc,
+ "Per Process Data");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't allocate per-process data (%d)", eError));
+ return eError;
+ }
+ OSMemSet(psPerProc, 0, sizeof(*psPerProc));
+ psPerProc->hBlockAlloc = hBlockAlloc;
+
+ /*
+ * FIXME: using a hash to retrieve psPerProc makes not much
+ * sense. We always want to have this struct on the IOCTL path
+ * for the current task, so it'd be just a matter of storing
+ * it in the file private object. Until this is resolved and
+ * we get rid of this pid specific lookup make sure the above
+ * assumption holds.
+ */
+ WARN_ON(OSGetCurrentProcessIDKM() != ui32PID);
+ get_task_comm(psPerProc->name, current);
+
+ if (!HASH_Insert(psHashTab, (IMG_UINTPTR_T)ui32PID, (IMG_UINTPTR_T)psPerProc))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't insert per-process data into hash table"));
+ eError = PVRSRV_ERROR_INSERT_HASH_TABLE_DATA_FAILED;
+ goto failure;
+ }
+ psPerProc->ui32PID = ui32PID;
+ psPerProc->ui32RefCount = 0;
+
+#if defined(PERPROC_LIST)
+ List_PVRSRV_PER_PROCESS_DATA_Insert(&psPerProcList, psPerProc);
+ /*PVR_LOG(("MarkTupsperproc %d\n", ui32PID));*/
+#endif
+
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+ if (ui32Flags == SRV_FLAGS_PDUMP_ACTIVE)
+ {
+ psPerProc->bPDumpActive = IMG_TRUE;
+ }
+#else
+ PVR_UNREFERENCED_PARAMETER(ui32Flags);
+#endif
+
+
+ eError = OSPerProcessPrivateDataInit(&psPerProc->hOsPrivateData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: OSPerProcessPrivateDataInit failed (%d)", eError));
+ goto failure;
+ }
+
+
+ eError = PVRSRVAllocHandle(KERNEL_HANDLE_BASE,
+ &psPerProc->hPerProcData,
+ psPerProc,
+ PVRSRV_HANDLE_TYPE_PERPROC_DATA,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't allocate handle for per-process data (%d)", eError));
+ goto failure;
+ }
+
+
+ eError = PVRSRVAllocHandleBase(&psPerProc->psHandleBase);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't allocate handle base for process (%d)", eError));
+ goto failure;
+ }
+
+
+ eError = OSPerProcessSetHandleOptions(psPerProc->psHandleBase);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't set handle options (%d)", eError));
+ goto failure;
+ }
+
+
+ eError = PVRSRVResManConnect(psPerProc, &psPerProc->hResManContext);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: Couldn't register with the resource manager"));
+ goto failure;
+ }
+ }
+
+ psPerProc->ui32RefCount++;
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "PVRSRVPerProcessDataConnect: Process 0x%x has ref-count %d",
+ ui32PID, psPerProc->ui32RefCount));
+
+ return eError;
+
+failure:
+ (IMG_VOID)FreePerProcessData(psPerProc);
+ return eError;
+}
+
+
+IMG_VOID PVRSRVPerProcessDataDisconnect(IMG_UINT32 ui32PID)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_PER_PROCESS_DATA *psPerProc;
+
+ PVR_ASSERT(psHashTab != IMG_NULL);
+
+ psPerProc = (PVRSRV_PER_PROCESS_DATA *)HASH_Retrieve(psHashTab, (IMG_UINTPTR_T)ui32PID);
+ if (psPerProc == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataDealloc: Couldn't locate per-process data for PID %u", ui32PID));
+ }
+ else
+ {
+ psPerProc->ui32RefCount--;
+ if (psPerProc->ui32RefCount == 0)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVPerProcessDataDisconnect: "
+ "Last close from process 0x%x received", ui32PID));
+
+
+ PVRSRVResManDisconnect(psPerProc->hResManContext, IMG_FALSE);
+
+
+ eError = FreePerProcessData(psPerProc);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataDisconnect: Error freeing per-process data"));
+ }
+ }
+ }
+
+ eError = PVRSRVPurgeHandles(KERNEL_HANDLE_BASE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataDisconnect: Purge of global handle pool failed (%d)", eError));
+ }
+}
+
+
+PVRSRV_ERROR PVRSRVPerProcessDataInit(IMG_VOID)
+{
+ PVR_ASSERT(psHashTab == IMG_NULL);
+
+
+ psHashTab = HASH_Create(HASH_TAB_INIT_SIZE);
+ if (psHashTab == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVPerProcessDataInit: Couldn't create per-process data hash table"));
+ return PVRSRV_ERROR_UNABLE_TO_CREATE_HASH_TABLE;
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVPerProcessDataDeInit(IMG_VOID)
+{
+
+ if (psHashTab != IMG_NULL)
+ {
+
+ HASH_Delete(psHashTab);
+ psHashTab = IMG_NULL;
+ }
+
+ return PVRSRV_OK;
+}
+
+#if defined(PERPROC_LIST)
+/*only used by PVRSRV_RESOURCE_PROFILING now*/
+PVRSRV_PER_PROCESS_DATA* PVRSRVPerProcessList(IMG_VOID)
+{
+ return psPerProcList;
+}
+#endif
--- /dev/null
+/**********************************************************************
+ *
+ * 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 "services_headers.h"
+#include "pdump_km.h"
+
+#include "lists.h"
+
+static IMG_BOOL gbInitServerRunning = IMG_FALSE;
+static IMG_BOOL gbInitServerRan = IMG_FALSE;
+static IMG_BOOL gbInitSuccessful = IMG_FALSE;
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_STATE eInitServerState, IMG_BOOL bState)
+{
+
+ switch(eInitServerState)
+ {
+ case PVRSRV_INIT_SERVER_RUNNING:
+ gbInitServerRunning = bState;
+ break;
+ case PVRSRV_INIT_SERVER_RAN:
+ gbInitServerRan = bState;
+ break;
+ case PVRSRV_INIT_SERVER_SUCCESSFUL:
+ gbInitSuccessful = bState;
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVSetInitServerState : Unknown state %x", eInitServerState));
+ return PVRSRV_ERROR_UNKNOWN_INIT_SERVER_STATE;
+ }
+
+ return PVRSRV_OK;
+}
+
+IMG_EXPORT
+IMG_BOOL PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_STATE eInitServerState)
+{
+ IMG_BOOL bReturnVal;
+
+ switch(eInitServerState)
+ {
+ case PVRSRV_INIT_SERVER_RUNNING:
+ bReturnVal = gbInitServerRunning;
+ break;
+ case PVRSRV_INIT_SERVER_RAN:
+ bReturnVal = gbInitServerRan;
+ break;
+ case PVRSRV_INIT_SERVER_SUCCESSFUL:
+ bReturnVal = gbInitSuccessful;
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVGetInitServerState : Unknown state %x", eInitServerState));
+ bReturnVal = IMG_FALSE;
+ }
+
+ return bReturnVal;
+}
+
+static IMG_BOOL _IsSystemStatePowered(PVRSRV_SYS_POWER_STATE eSystemPowerState)
+{
+ return (IMG_BOOL)(eSystemPowerState < PVRSRV_SYS_POWER_STATE_D2);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVPowerLock(IMG_UINT32 ui32CallerID,
+ IMG_BOOL bSystemPowerEvent)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+ IMG_UINT32 ui32Timeout = 1000000;
+
+#if defined(SUPPORT_LMA)
+
+ ui32Timeout *= 60;
+#endif
+
+ SysAcquireData(&psSysData);
+
+#if defined(SYS_CUSTOM_POWERLOCK_WRAP)
+ eError = SysPowerLockWrap(psSysData);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+#endif
+ do
+ {
+ eError = OSLockResource(&psSysData->sPowerStateChangeResource,
+ ui32CallerID);
+ if (eError == PVRSRV_OK)
+ {
+ break;
+ }
+ else if (ui32CallerID == ISR_ID)
+ {
+
+
+ eError = PVRSRV_ERROR_RETRY;
+ break;
+ }
+
+ OSWaitus(1);
+ ui32Timeout--;
+ } while (ui32Timeout > 0);
+
+#if defined(SYS_CUSTOM_POWERLOCK_WRAP)
+ if (eError != PVRSRV_OK)
+ {
+ SysPowerLockUnwrap(psSysData);
+ }
+#endif
+
+ if ((eError == PVRSRV_OK) &&
+ !bSystemPowerEvent &&
+ !_IsSystemStatePowered(psSysData->eCurrentPowerState))
+ {
+
+ PVRSRVPowerUnlock(ui32CallerID);
+ eError = PVRSRV_ERROR_RETRY;
+ }
+
+ return eError;
+}
+
+
+IMG_EXPORT
+IMG_VOID PVRSRVPowerUnlock(IMG_UINT32 ui32CallerID)
+{
+ OSUnlockResource(&gpsSysData->sPowerStateChangeResource, ui32CallerID);
+#if defined(SYS_CUSTOM_POWERLOCK_WRAP)
+ SysPowerLockUnwrap(gpsSysData);
+#endif
+}
+
+
+static PVRSRV_ERROR PVRSRVDevicePrePowerStateKM_AnyVaCb(PVRSRV_POWER_DEV *psPowerDevice, va_list va)
+{
+ PVRSRV_DEV_POWER_STATE eNewDevicePowerState;
+ PVRSRV_ERROR eError;
+
+
+ IMG_BOOL bAllDevices;
+ IMG_UINT32 ui32DeviceIndex;
+ PVRSRV_DEV_POWER_STATE eNewPowerState;
+
+
+ bAllDevices = va_arg(va, IMG_BOOL);
+ ui32DeviceIndex = va_arg(va, IMG_UINT32);
+ eNewPowerState = va_arg(va, PVRSRV_DEV_POWER_STATE);
+
+ if (bAllDevices || (ui32DeviceIndex == psPowerDevice->ui32DeviceIndex))
+ {
+ eNewDevicePowerState = (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT) ?
+ psPowerDevice->eDefaultPowerState : eNewPowerState;
+
+ if (psPowerDevice->eCurrentPowerState != eNewDevicePowerState)
+ {
+ if (psPowerDevice->pfnPrePower != IMG_NULL)
+ {
+
+ eError = psPowerDevice->pfnPrePower(psPowerDevice->hDevCookie,
+ eNewDevicePowerState,
+ psPowerDevice->eCurrentPowerState);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+
+
+ eError = SysDevicePrePowerState(psPowerDevice->ui32DeviceIndex,
+ eNewDevicePowerState,
+ psPowerDevice->eCurrentPowerState);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+static
+PVRSRV_ERROR PVRSRVDevicePrePowerStateKM(IMG_BOOL bAllDevices,
+ IMG_UINT32 ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE eNewPowerState)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+
+
+ eError = List_PVRSRV_POWER_DEV_PVRSRV_ERROR_Any_va(psSysData->psPowerDeviceList,
+ &PVRSRVDevicePrePowerStateKM_AnyVaCb,
+ bAllDevices,
+ ui32DeviceIndex,
+ eNewPowerState);
+
+ return eError;
+}
+
+static PVRSRV_ERROR PVRSRVDevicePostPowerStateKM_AnyVaCb(PVRSRV_POWER_DEV *psPowerDevice, va_list va)
+{
+ PVRSRV_DEV_POWER_STATE eNewDevicePowerState;
+ PVRSRV_ERROR eError;
+
+
+ IMG_BOOL bAllDevices;
+ IMG_UINT32 ui32DeviceIndex;
+ PVRSRV_DEV_POWER_STATE eNewPowerState;
+
+
+ bAllDevices = va_arg(va, IMG_BOOL);
+ ui32DeviceIndex = va_arg(va, IMG_UINT32);
+ eNewPowerState = va_arg(va, PVRSRV_DEV_POWER_STATE);
+
+ if (bAllDevices || (ui32DeviceIndex == psPowerDevice->ui32DeviceIndex))
+ {
+ eNewDevicePowerState = (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT) ?
+ psPowerDevice->eDefaultPowerState : eNewPowerState;
+
+ if (psPowerDevice->eCurrentPowerState != eNewDevicePowerState)
+ {
+
+ eError = SysDevicePostPowerState(psPowerDevice->ui32DeviceIndex,
+ eNewDevicePowerState,
+ psPowerDevice->eCurrentPowerState);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ if (psPowerDevice->pfnPostPower != IMG_NULL)
+ {
+
+ eError = psPowerDevice->pfnPostPower(psPowerDevice->hDevCookie,
+ eNewDevicePowerState,
+ psPowerDevice->eCurrentPowerState);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+
+ psPowerDevice->eCurrentPowerState = eNewDevicePowerState;
+ }
+ }
+ return PVRSRV_OK;
+}
+
+static
+PVRSRV_ERROR PVRSRVDevicePostPowerStateKM(IMG_BOOL bAllDevices,
+ IMG_UINT32 ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE eNewPowerState)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+
+
+ eError = List_PVRSRV_POWER_DEV_PVRSRV_ERROR_Any_va(psSysData->psPowerDeviceList,
+ &PVRSRVDevicePostPowerStateKM_AnyVaCb,
+ bAllDevices,
+ ui32DeviceIndex,
+ eNewPowerState);
+
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetDevicePowerStateKM(IMG_UINT32 ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ IMG_UINT32 ui32CallerID,
+ IMG_BOOL bRetainMutex)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+
+ eError = PVRSRVPowerLock(ui32CallerID, IMG_FALSE);
+ if(eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ #if defined(PDUMP)
+ if (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT)
+ {
+
+
+
+
+ eError = PVRSRVDevicePrePowerStateKM(IMG_FALSE, ui32DeviceIndex, PVRSRV_DEV_POWER_STATE_ON);
+ if(eError != PVRSRV_OK)
+ {
+ goto Exit;
+ }
+
+ eError = PVRSRVDevicePostPowerStateKM(IMG_FALSE, ui32DeviceIndex, PVRSRV_DEV_POWER_STATE_ON);
+
+ if (eError != PVRSRV_OK)
+ {
+ goto Exit;
+ }
+
+ PDUMPSUSPEND();
+ }
+ #endif
+
+ eError = PVRSRVDevicePrePowerStateKM(IMG_FALSE, ui32DeviceIndex, eNewPowerState);
+ if(eError != PVRSRV_OK)
+ {
+ if (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT)
+ {
+ PDUMPRESUME();
+ }
+ goto Exit;
+ }
+
+ eError = PVRSRVDevicePostPowerStateKM(IMG_FALSE, ui32DeviceIndex, eNewPowerState);
+
+ if (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT)
+ {
+ PDUMPRESUME();
+ }
+
+Exit:
+
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVSetDevicePowerStateKM : Transition to %d FAILED 0x%x", eNewPowerState, eError));
+ }
+
+ if (!bRetainMutex || (eError != PVRSRV_OK))
+ {
+ PVRSRVPowerUnlock(ui32CallerID);
+ }
+
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSystemPrePowerStateKM(PVRSRV_SYS_POWER_STATE eNewSysPowerState)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+ PVRSRV_DEV_POWER_STATE eNewDevicePowerState;
+
+ SysAcquireData(&psSysData);
+
+
+ eError = PVRSRVPowerLock(KERNEL_ID, IMG_TRUE);
+ if(eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ if (_IsSystemStatePowered(eNewSysPowerState) !=
+ _IsSystemStatePowered(psSysData->eCurrentPowerState))
+ {
+ if (_IsSystemStatePowered(eNewSysPowerState))
+ {
+
+ eNewDevicePowerState = PVRSRV_DEV_POWER_STATE_DEFAULT;
+ }
+ else
+ {
+ eNewDevicePowerState = PVRSRV_DEV_POWER_STATE_OFF;
+ }
+
+
+ eError = PVRSRVDevicePrePowerStateKM(IMG_TRUE, 0, eNewDevicePowerState);
+ if (eError != PVRSRV_OK)
+ {
+ goto ErrorExit;
+ }
+ }
+
+ if (eNewSysPowerState != psSysData->eCurrentPowerState)
+ {
+
+ eError = SysSystemPrePowerState(eNewSysPowerState);
+ if (eError != PVRSRV_OK)
+ {
+ goto ErrorExit;
+ }
+ }
+
+ return eError;
+
+ErrorExit:
+
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVSystemPrePowerStateKM: Transition from %d to %d FAILED 0x%x",
+ psSysData->eCurrentPowerState, eNewSysPowerState, eError));
+
+
+ psSysData->eFailedPowerState = eNewSysPowerState;
+
+ PVRSRVPowerUnlock(KERNEL_ID);
+
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSystemPostPowerStateKM(PVRSRV_SYS_POWER_STATE eNewSysPowerState)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ SYS_DATA *psSysData;
+ PVRSRV_DEV_POWER_STATE eNewDevicePowerState;
+
+ SysAcquireData(&psSysData);
+
+ if (eNewSysPowerState != psSysData->eCurrentPowerState)
+ {
+
+ eError = SysSystemPostPowerState(eNewSysPowerState);
+ if (eError != PVRSRV_OK)
+ {
+ goto Exit;
+ }
+ }
+
+ if (_IsSystemStatePowered(eNewSysPowerState) !=
+ _IsSystemStatePowered(psSysData->eCurrentPowerState))
+ {
+ if (_IsSystemStatePowered(eNewSysPowerState))
+ {
+
+ eNewDevicePowerState = PVRSRV_DEV_POWER_STATE_DEFAULT;
+ }
+ else
+ {
+ eNewDevicePowerState = PVRSRV_DEV_POWER_STATE_OFF;
+ }
+
+
+ eError = PVRSRVDevicePostPowerStateKM(IMG_TRUE, 0, eNewDevicePowerState);
+ if (eError != PVRSRV_OK)
+ {
+ goto Exit;
+ }
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "PVRSRVSystemPostPowerStateKM: System Power Transition from %d to %d OK",
+ psSysData->eCurrentPowerState, eNewSysPowerState));
+
+ psSysData->eCurrentPowerState = eNewSysPowerState;
+
+Exit:
+
+ PVRSRVPowerUnlock(KERNEL_ID);
+
+
+ if (_IsSystemStatePowered(eNewSysPowerState) &&
+ PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL))
+ {
+
+
+
+ PVRSRVScheduleDeviceCallbacks();
+ }
+
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE eNewSysPowerState)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+
+ eError = PVRSRVSystemPrePowerStateKM(eNewSysPowerState);
+ if(eError != PVRSRV_OK)
+ {
+ goto ErrorExit;
+ }
+
+ eError = PVRSRVSystemPostPowerStateKM(eNewSysPowerState);
+ if(eError != PVRSRV_OK)
+ {
+ goto ErrorExit;
+ }
+
+
+ psSysData->eFailedPowerState = PVRSRV_SYS_POWER_STATE_Unspecified;
+
+ return PVRSRV_OK;
+
+ErrorExit:
+
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVSetPowerStateKM: Transition from %d to %d FAILED 0x%x",
+ psSysData->eCurrentPowerState, eNewSysPowerState, eError));
+
+
+ psSysData->eFailedPowerState = eNewSysPowerState;
+
+ return eError;
+}
+
+
+PVRSRV_ERROR PVRSRVRegisterPowerDevice(IMG_UINT32 ui32DeviceIndex,
+ PFN_PRE_POWER pfnPrePower,
+ PFN_POST_POWER pfnPostPower,
+ PFN_PRE_CLOCKSPEED_CHANGE pfnPreClockSpeedChange,
+ PFN_POST_CLOCKSPEED_CHANGE pfnPostClockSpeedChange,
+ IMG_HANDLE hDevCookie,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState,
+ PVRSRV_DEV_POWER_STATE eDefaultPowerState)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+ PVRSRV_POWER_DEV *psPowerDevice;
+
+ if (pfnPrePower == IMG_NULL &&
+ pfnPostPower == IMG_NULL)
+ {
+ return PVRSRVRemovePowerDevice(ui32DeviceIndex);
+ }
+
+ SysAcquireData(&psSysData);
+
+ eError = OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_POWER_DEV),
+ (IMG_VOID **)&psPowerDevice, IMG_NULL,
+ "Power Device");
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterPowerDevice: Failed to alloc PVRSRV_POWER_DEV"));
+ return eError;
+ }
+
+
+ psPowerDevice->pfnPrePower = pfnPrePower;
+ psPowerDevice->pfnPostPower = pfnPostPower;
+ psPowerDevice->pfnPreClockSpeedChange = pfnPreClockSpeedChange;
+ psPowerDevice->pfnPostClockSpeedChange = pfnPostClockSpeedChange;
+ psPowerDevice->hDevCookie = hDevCookie;
+ psPowerDevice->ui32DeviceIndex = ui32DeviceIndex;
+ psPowerDevice->eCurrentPowerState = eCurrentPowerState;
+ psPowerDevice->eDefaultPowerState = eDefaultPowerState;
+
+
+ List_PVRSRV_POWER_DEV_Insert(&(psSysData->psPowerDeviceList), psPowerDevice);
+
+ return (PVRSRV_OK);
+}
+
+
+PVRSRV_ERROR PVRSRVRemovePowerDevice (IMG_UINT32 ui32DeviceIndex)
+{
+ SYS_DATA *psSysData;
+ PVRSRV_POWER_DEV *psPowerDev;
+
+ SysAcquireData(&psSysData);
+
+
+ psPowerDev = (PVRSRV_POWER_DEV*)
+ List_PVRSRV_POWER_DEV_Any_va(psSysData->psPowerDeviceList,
+ &MatchPowerDeviceIndex_AnyVaCb,
+ ui32DeviceIndex);
+
+ if (psPowerDev)
+ {
+ List_PVRSRV_POWER_DEV_Remove(psPowerDev);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_POWER_DEV), psPowerDev, IMG_NULL);
+
+ }
+
+ return (PVRSRV_OK);
+}
+
+
+IMG_EXPORT
+IMG_BOOL PVRSRVIsDevicePowered(IMG_UINT32 ui32DeviceIndex)
+{
+ SYS_DATA *psSysData;
+ PVRSRV_POWER_DEV *psPowerDevice;
+
+ SysAcquireData(&psSysData);
+
+
+ if (OSIsResourceLocked(&psSysData->sPowerStateChangeResource, KERNEL_ID) ||
+ OSIsResourceLocked(&psSysData->sPowerStateChangeResource, ISR_ID))
+ {
+ return IMG_FALSE;
+ }
+
+ psPowerDevice = (PVRSRV_POWER_DEV*)
+ List_PVRSRV_POWER_DEV_Any_va(psSysData->psPowerDeviceList,
+ &MatchPowerDeviceIndex_AnyVaCb,
+ ui32DeviceIndex);
+ return (psPowerDevice && (psPowerDevice->eCurrentPowerState == PVRSRV_DEV_POWER_STATE_ON))
+ ? IMG_TRUE : IMG_FALSE;
+}
+
+
+PVRSRV_ERROR PVRSRVDevicePreClockSpeedChange(IMG_UINT32 ui32DeviceIndex,
+ IMG_BOOL bIdleDevice,
+ IMG_VOID *pvInfo)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ SYS_DATA *psSysData;
+ PVRSRV_POWER_DEV *psPowerDevice;
+
+ PVR_UNREFERENCED_PARAMETER(pvInfo);
+
+ SysAcquireData(&psSysData);
+
+ if (bIdleDevice)
+ {
+
+ eError = PVRSRVPowerLock(KERNEL_ID, IMG_FALSE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVDevicePreClockSpeedChange : failed to acquire lock, error:0x%x", eError));
+ return eError;
+ }
+ }
+
+
+ psPowerDevice = (PVRSRV_POWER_DEV*)
+ List_PVRSRV_POWER_DEV_Any_va(psSysData->psPowerDeviceList,
+ &MatchPowerDeviceIndex_AnyVaCb,
+ ui32DeviceIndex);
+
+ if (psPowerDevice && psPowerDevice->pfnPostClockSpeedChange)
+ {
+ eError = psPowerDevice->pfnPreClockSpeedChange(psPowerDevice->hDevCookie,
+ bIdleDevice,
+ psPowerDevice->eCurrentPowerState);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVDevicePreClockSpeedChange : Device %u failed, error:0x%x",
+ ui32DeviceIndex, eError));
+ }
+ }
+
+ if (bIdleDevice && eError != PVRSRV_OK)
+ {
+ PVRSRVPowerUnlock(KERNEL_ID);
+ }
+
+ return eError;
+}
+
+
+IMG_VOID PVRSRVDevicePostClockSpeedChange(IMG_UINT32 ui32DeviceIndex,
+ IMG_BOOL bIdleDevice,
+ IMG_VOID *pvInfo)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+ PVRSRV_POWER_DEV *psPowerDevice;
+
+ PVR_UNREFERENCED_PARAMETER(pvInfo);
+
+ SysAcquireData(&psSysData);
+
+
+ psPowerDevice = (PVRSRV_POWER_DEV*)
+ List_PVRSRV_POWER_DEV_Any_va(psSysData->psPowerDeviceList,
+ &MatchPowerDeviceIndex_AnyVaCb,
+ ui32DeviceIndex);
+
+ if (psPowerDevice && psPowerDevice->pfnPostClockSpeedChange)
+ {
+ eError = psPowerDevice->pfnPostClockSpeedChange(psPowerDevice->hDevCookie,
+ bIdleDevice,
+ psPowerDevice->eCurrentPowerState);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVDevicePostClockSpeedChange : Device %u failed, error:0x%x",
+ ui32DeviceIndex, eError));
+ }
+ }
+
+
+ if (bIdleDevice)
+ {
+
+ PVRSRVPowerUnlock(KERNEL_ID);
+ }
+}
+
+#if 0
+/*
+ * PVRSRVPowerOnSystemWithDevice
+ *
+ * Description: Power on the System if it is off, but instead of powering all
+ * of the devices to their "default" state, only turn on the specified
+ * device index.
+ */
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVPowerOnSystemWithDevice(IMG_UINT32 ui32DeviceIndex,
+ IMG_UINT32 ui32CallerID,
+ IMG_BOOL bRetainMutex)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+
+ eError = PVRSRVPowerLock(ui32CallerID, IMG_TRUE);
+ if(eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ eError = PVRSRVDevicePrePowerStateKM(IMG_FALSE, ui32DeviceIndex, PVRSRV_DEV_POWER_STATE_ON);
+ if (eError != PVRSRV_OK)
+ {
+ goto ErrorExit;
+ }
+
+ if (!_IsSystemStatePowered(psSysData->eCurrentPowerState))
+ {
+ eError = SysSystemPrePowerState(PVRSRV_SYS_POWER_STATE_D0);
+ if (eError != PVRSRV_OK)
+ {
+ goto ErrorExit;
+ }
+
+ eError = SysSystemPostPowerState(PVRSRV_SYS_POWER_STATE_D0);
+ if (eError != PVRSRV_OK)
+ {
+ goto ErrorExit;
+ }
+ psSysData->eCurrentPowerState = PVRSRV_SYS_POWER_STATE_D0;
+ }
+
+ eError = PVRSRVDevicePostPowerStateKM(IMG_FALSE, ui32DeviceIndex, PVRSRV_DEV_POWER_STATE_ON);
+ if (eError != PVRSRV_OK)
+ {
+ goto ErrorExit;
+ }
+
+ErrorExit:
+
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVPowerOnSystemWithDevice : FAILED 0x%x", eError));
+ }
+
+ if (!bRetainMutex || (eError != PVRSRV_OK))
+ {
+ PVRSRVPowerUnlock(ui32CallerID);
+ }
+
+ return eError;
+}
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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 "services_headers.h"
+#include "buffer_manager.h"
+#include "pvr_bridge_km.h"
+#include "sgx_bridge_km.h"
+#include "sgx_mkif_km.h"
+#include "sgxapi_km.h"
+#include "sgxinfokm.h"
+#include "handle.h"
+#include "perproc.h"
+#include "pdump_km.h"
+#include "deviceid.h"
+#include "ra.h"
+
+#include "pvrversion.h"
+
+#include "lists.h"
+
+IMG_UINT32 g_ui32InitFlags;
+
+#define INIT_DATA_ENABLE_PDUMPINIT 0x1U
+
+PVRSRV_ERROR AllocateDeviceID(SYS_DATA *psSysData, IMG_UINT32 *pui32DevID)
+{
+ SYS_DEVICE_ID* psDeviceWalker;
+ SYS_DEVICE_ID* psDeviceEnd;
+
+ psDeviceWalker = &psSysData->sDeviceID[0];
+ psDeviceEnd = psDeviceWalker + psSysData->ui32NumDevices;
+
+
+ while (psDeviceWalker < psDeviceEnd)
+ {
+ if (!psDeviceWalker->bInUse)
+ {
+ psDeviceWalker->bInUse = IMG_TRUE;
+ *pui32DevID = psDeviceWalker->uiID;
+ return PVRSRV_OK;
+ }
+ psDeviceWalker++;
+ }
+
+ PVR_DPF((PVR_DBG_ERROR,"AllocateDeviceID: No free and valid device IDs available!"));
+
+
+ PVR_ASSERT(psDeviceWalker < psDeviceEnd);
+
+ return PVRSRV_ERROR_NO_FREE_DEVICEIDS_AVALIABLE;
+}
+
+
+PVRSRV_ERROR FreeDeviceID(SYS_DATA *psSysData, IMG_UINT32 ui32DevID)
+{
+ SYS_DEVICE_ID* psDeviceWalker;
+ SYS_DEVICE_ID* psDeviceEnd;
+
+ psDeviceWalker = &psSysData->sDeviceID[0];
+ psDeviceEnd = psDeviceWalker + psSysData->ui32NumDevices;
+
+
+ while (psDeviceWalker < psDeviceEnd)
+ {
+
+ if (
+ (psDeviceWalker->uiID == ui32DevID) &&
+ (psDeviceWalker->bInUse)
+ )
+ {
+ psDeviceWalker->bInUse = IMG_FALSE;
+ return PVRSRV_OK;
+ }
+ psDeviceWalker++;
+ }
+
+ PVR_DPF((PVR_DBG_ERROR,"FreeDeviceID: no matching dev ID that is in use!"));
+
+
+ PVR_ASSERT(psDeviceWalker < psDeviceEnd);
+
+ return PVRSRV_ERROR_INVALID_DEVICEID;
+}
+
+
+#ifndef ReadHWReg
+IMG_EXPORT
+IMG_UINT32 ReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset)
+{
+ return *(volatile IMG_UINT32*)((IMG_UINTPTR_T)pvLinRegBaseAddr+ui32Offset);
+}
+#endif
+
+
+#ifndef WriteHWReg
+IMG_EXPORT
+IMG_VOID WriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value)
+{
+ PVR_DPF((PVR_DBG_MESSAGE,"WriteHWReg Base:%x, Offset: %x, Value %x",
+ (IMG_UINTPTR_T)pvLinRegBaseAddr,ui32Offset,ui32Value));
+
+ *(IMG_UINT32*)((IMG_UINTPTR_T)pvLinRegBaseAddr+ui32Offset) = ui32Value;
+}
+#endif
+
+
+#ifndef WriteHWRegs
+IMG_EXPORT
+IMG_VOID WriteHWRegs(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Count, PVRSRV_HWREG *psHWRegs)
+{
+ while (ui32Count)
+ {
+ WriteHWReg (pvLinRegBaseAddr, psHWRegs->ui32RegAddr, psHWRegs->ui32RegVal);
+ psHWRegs++;
+ ui32Count--;
+ }
+}
+#endif
+
+static IMG_VOID PVRSRVEnumerateDevicesKM_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
+{
+ IMG_UINT *pui32DevCount;
+ PVRSRV_DEVICE_IDENTIFIER **ppsDevIdList;
+
+ pui32DevCount = va_arg(va, IMG_UINT*);
+ ppsDevIdList = va_arg(va, PVRSRV_DEVICE_IDENTIFIER**);
+
+ if (psDeviceNode->sDevId.eDeviceType != PVRSRV_DEVICE_TYPE_EXT)
+ {
+ *(*ppsDevIdList) = psDeviceNode->sDevId;
+ (*ppsDevIdList)++;
+ (*pui32DevCount)++;
+ }
+}
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumerateDevicesKM(IMG_UINT32 *pui32NumDevices,
+ PVRSRV_DEVICE_IDENTIFIER *psDevIdList)
+{
+ SYS_DATA *psSysData;
+ IMG_UINT32 i;
+
+ if (!pui32NumDevices || !psDevIdList)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumerateDevicesKM: Invalid params"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ SysAcquireData(&psSysData);
+
+
+
+ for (i=0; i<PVRSRV_MAX_DEVICES; i++)
+ {
+ psDevIdList[i].eDeviceType = PVRSRV_DEVICE_TYPE_UNKNOWN;
+ }
+
+
+ *pui32NumDevices = 0;
+
+
+
+
+
+ List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList,
+ &PVRSRVEnumerateDevicesKM_ForEachVaCb,
+ pui32NumDevices,
+ &psDevIdList);
+
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVInit(PSYS_DATA psSysData)
+{
+ PVRSRV_ERROR eError;
+
+
+ eError = ResManInit();
+ if (eError != PVRSRV_OK)
+ {
+ goto Error;
+ }
+
+ eError = PVRSRVPerProcessDataInit();
+ if(eError != PVRSRV_OK)
+ {
+ goto Error;
+ }
+
+
+ eError = PVRSRVHandleInit();
+ if(eError != PVRSRV_OK)
+ {
+ goto Error;
+ }
+
+
+ eError = OSCreateResource(&psSysData->sPowerStateChangeResource);
+ if (eError != PVRSRV_OK)
+ {
+ goto Error;
+ }
+
+
+ psSysData->eCurrentPowerState = PVRSRV_SYS_POWER_STATE_D0;
+ psSysData->eFailedPowerState = PVRSRV_SYS_POWER_STATE_Unspecified;
+
+
+ if(OSAllocMem( PVRSRV_PAGEABLE_SELECT,
+ sizeof(PVRSRV_EVENTOBJECT) ,
+ (IMG_VOID **)&psSysData->psGlobalEventObject, 0,
+ "Event Object") != PVRSRV_OK)
+ {
+
+ goto Error;
+ }
+
+ if(OSEventObjectCreate("PVRSRV_GLOBAL_EVENTOBJECT", psSysData->psGlobalEventObject) != PVRSRV_OK)
+ {
+ goto Error;
+ }
+
+
+ PDUMPINIT();
+ g_ui32InitFlags |= INIT_DATA_ENABLE_PDUMPINIT;
+
+ return eError;
+
+Error:
+ PVRSRVDeInit(psSysData);
+ return eError;
+}
+
+
+
+IMG_VOID IMG_CALLCONV PVRSRVDeInit(PSYS_DATA psSysData)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_UNREFERENCED_PARAMETER(psSysData);
+
+ if (psSysData == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PVRSRVHandleDeInit failed - invalid param"));
+ return;
+ }
+
+
+ if( (g_ui32InitFlags & INIT_DATA_ENABLE_PDUMPINIT) > 0)
+ {
+ PDUMPDEINIT();
+ }
+
+
+ if(psSysData->psGlobalEventObject)
+ {
+ OSEventObjectDestroy(psSysData->psGlobalEventObject);
+ OSFreeMem( PVRSRV_PAGEABLE_SELECT,
+ sizeof(PVRSRV_EVENTOBJECT),
+ psSysData->psGlobalEventObject,
+ 0);
+ psSysData->psGlobalEventObject = IMG_NULL;
+ }
+
+ eError = PVRSRVHandleDeInit();
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PVRSRVHandleDeInit failed"));
+ }
+
+ eError = PVRSRVPerProcessDataDeInit();
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PVRSRVPerProcessDataDeInit failed"));
+ }
+
+ ResManDeInit();
+}
+
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVRegisterDevice(PSYS_DATA psSysData,
+ PVRSRV_ERROR (*pfnRegisterDevice)(PVRSRV_DEVICE_NODE*),
+ IMG_UINT32 ui32SOCInterruptBit,
+ IMG_UINT32 *pui32DeviceIndex)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+
+
+ if(OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DEVICE_NODE),
+ (IMG_VOID **)&psDeviceNode, IMG_NULL,
+ "Device Node") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDevice : Failed to alloc memory for psDeviceNode"));
+ return (PVRSRV_ERROR_OUT_OF_MEMORY);
+ }
+ OSMemSet (psDeviceNode, 0, sizeof(PVRSRV_DEVICE_NODE));
+
+ eError = pfnRegisterDevice(psDeviceNode);
+ if (eError != PVRSRV_OK)
+ {
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL);
+
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDevice : Failed to register device"));
+ return (PVRSRV_ERROR_DEVICE_REGISTER_FAILED);
+ }
+
+
+
+
+
+
+ psDeviceNode->ui32RefCount = 1;
+ psDeviceNode->psSysData = psSysData;
+ psDeviceNode->ui32SOCInterruptBit = ui32SOCInterruptBit;
+
+
+ AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex);
+
+
+ List_PVRSRV_DEVICE_NODE_Insert(&psSysData->psDeviceNodeList, psDeviceNode);
+
+
+ *pui32DeviceIndex = psDeviceNode->sDevId.ui32DeviceIndex;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVInitialiseDevice (IMG_UINT32 ui32DevIndex)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ SYS_DATA *psSysData;
+ PVRSRV_ERROR eError;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVInitialiseDevice"));
+
+ SysAcquireData(&psSysData);
+
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE*)
+ List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+ &MatchDeviceKM_AnyVaCb,
+ ui32DevIndex,
+ IMG_TRUE);
+ if(!psDeviceNode)
+ {
+
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVInitialiseDevice: requested device is not present"));
+ return PVRSRV_ERROR_INIT_FAILURE;
+ }
+ PVR_ASSERT (psDeviceNode->ui32RefCount > 0);
+
+
+
+ eError = PVRSRVResManConnect(IMG_NULL, &psDeviceNode->hResManContext);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVInitialiseDevice: Failed PVRSRVResManConnect call"));
+ return eError;
+ }
+
+
+ if(psDeviceNode->pfnInitDevice != IMG_NULL)
+ {
+ eError = psDeviceNode->pfnInitDevice(psDeviceNode);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVInitialiseDevice: Failed InitDevice call"));
+ return eError;
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR PVRSRVFinaliseSystem_SetPowerState_AnyCb(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVRSRV_ERROR eError;
+ eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE_DEFAULT,
+ KERNEL_ID, IMG_FALSE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed PVRSRVSetDevicePowerStateKM call (device index: %d)", psDeviceNode->sDevId.ui32DeviceIndex));
+ }
+ return eError;
+}
+
+static PVRSRV_ERROR PVRSRVFinaliseSystem_CompatCheck_AnyCb(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVRSRV_ERROR eError;
+ eError = PVRSRVDevInitCompatCheck(psDeviceNode);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed PVRSRVDevInitCompatCheck call (device index: %d)", psDeviceNode->sDevId.ui32DeviceIndex));
+ }
+ return eError;
+}
+
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFinaliseSystem(IMG_BOOL bInitSuccessful)
+{
+ SYS_DATA *psSysData;
+ PVRSRV_ERROR eError;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVFinaliseSystem"));
+
+ SysAcquireData(&psSysData);
+
+ if (bInitSuccessful)
+ {
+ eError = SysFinalise();
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: SysFinalise failed (%d)", eError));
+ return eError;
+ }
+
+
+ eError = List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any(psSysData->psDeviceNodeList,
+ &PVRSRVFinaliseSystem_SetPowerState_AnyCb);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+
+ eError = List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any(psSysData->psDeviceNodeList,
+ &PVRSRVFinaliseSystem_CompatCheck_AnyCb);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+
+
+
+
+
+ PDUMPENDINITPHASE();
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PVRSRVDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+
+ if (psDeviceNode->pfnInitDeviceCompatCheck)
+ return psDeviceNode->pfnInitDeviceCompatCheck(psDeviceNode);
+ else
+ return PVRSRV_OK;
+}
+
+static IMG_VOID * PVRSRVAcquireDeviceDataKM_Match_AnyVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
+{
+ PVRSRV_DEVICE_TYPE eDeviceType;
+ IMG_UINT32 ui32DevIndex;
+
+ eDeviceType = va_arg(va, PVRSRV_DEVICE_TYPE);
+ ui32DevIndex = va_arg(va, IMG_UINT32);
+
+ if ((eDeviceType != PVRSRV_DEVICE_TYPE_UNKNOWN &&
+ psDeviceNode->sDevId.eDeviceType == eDeviceType) ||
+ (eDeviceType == PVRSRV_DEVICE_TYPE_UNKNOWN &&
+ psDeviceNode->sDevId.ui32DeviceIndex == ui32DevIndex))
+ {
+ return psDeviceNode;
+ }
+ else
+ {
+ return IMG_NULL;
+ }
+}
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVAcquireDeviceDataKM (IMG_UINT32 ui32DevIndex,
+ PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_HANDLE *phDevCookie)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ SYS_DATA *psSysData;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVAcquireDeviceDataKM"));
+
+ SysAcquireData(&psSysData);
+
+
+ psDeviceNode = List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+ &PVRSRVAcquireDeviceDataKM_Match_AnyVaCb,
+ eDeviceType,
+ ui32DevIndex);
+
+
+ if (!psDeviceNode)
+ {
+
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVAcquireDeviceDataKM: requested device is not present"));
+ return PVRSRV_ERROR_INIT_FAILURE;
+ }
+
+ PVR_ASSERT (psDeviceNode->ui32RefCount > 0);
+
+
+ if (phDevCookie)
+ {
+ *phDevCookie = (IMG_HANDLE)psDeviceNode;
+ }
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDeinitialiseDevice(IMG_UINT32 ui32DevIndex)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ SYS_DATA *psSysData;
+ PVRSRV_ERROR eError;
+
+ SysAcquireData(&psSysData);
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE*)
+ List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+ &MatchDeviceKM_AnyVaCb,
+ ui32DevIndex,
+ IMG_TRUE);
+
+ if (!psDeviceNode)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: requested device %d is not present", ui32DevIndex));
+ return PVRSRV_ERROR_DEVICEID_NOT_FOUND;
+ }
+
+
+
+ eError = PVRSRVSetDevicePowerStateKM(ui32DevIndex,
+ PVRSRV_DEV_POWER_STATE_OFF,
+ KERNEL_ID,
+ IMG_FALSE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed PVRSRVSetDevicePowerStateKM call"));
+ return eError;
+ }
+
+
+
+ eError = ResManFreeResByCriteria(psDeviceNode->hResManContext,
+ RESMAN_CRITERIA_RESTYPE,
+ RESMAN_TYPE_DEVICEMEM_ALLOCATION,
+ IMG_NULL, 0);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed ResManFreeResByCriteria call"));
+ return eError;
+ }
+
+
+
+ if(psDeviceNode->pfnDeInitDevice != IMG_NULL)
+ {
+ eError = psDeviceNode->pfnDeInitDevice(psDeviceNode);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed DeInitDevice call"));
+ return eError;
+ }
+ }
+
+
+
+ PVRSRVResManDisconnect(psDeviceNode->hResManContext, IMG_TRUE);
+ psDeviceNode->hResManContext = IMG_NULL;
+
+
+ List_PVRSRV_DEVICE_NODE_Remove(psDeviceNode);
+
+
+ (IMG_VOID)FreeDeviceID(psSysData, ui32DevIndex);
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL);
+
+
+ return (PVRSRV_OK);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PollForValueKM (volatile IMG_UINT32* pui32LinMemAddr,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask,
+ IMG_UINT32 ui32Timeoutus,
+ IMG_UINT32 ui32PollPeriodus,
+ IMG_BOOL bAllowPreemption)
+{
+ {
+ IMG_UINT32 ui32ActualValue = 0xFFFFFFFFU;
+
+ if (bAllowPreemption)
+ {
+ PVR_ASSERT(ui32PollPeriodus >= 1000);
+ }
+
+
+ LOOP_UNTIL_TIMEOUT(ui32Timeoutus)
+ {
+ ui32ActualValue = (*pui32LinMemAddr & ui32Mask);
+ if(ui32ActualValue == ui32Value)
+ {
+ return PVRSRV_OK;
+ }
+
+ if (bAllowPreemption)
+ {
+ OSSleepms(ui32PollPeriodus / 1000);
+ }
+ else
+ {
+ OSWaitus(ui32PollPeriodus);
+ }
+ } END_LOOP_UNTIL_TIMEOUT();
+
+ PVR_DPF((PVR_DBG_ERROR,"PollForValueKM: Timeout. Expected 0x%x but found 0x%x (mask 0x%x).",
+ ui32Value, ui32ActualValue, ui32Mask));
+ }
+
+ return PVRSRV_ERROR_TIMEOUT;
+}
+
+
+static IMG_VOID PVRSRVGetMiscInfoKM_RA_GetStats_ForEachVaCb(BM_HEAP *psBMHeap, va_list va)
+{
+ IMG_CHAR **ppszStr;
+ IMG_UINT32 *pui32StrLen;
+ IMG_UINT32 ui32Mode;
+ PVRSRV_ERROR (*pfnGetStats)(RA_ARENA *, IMG_CHAR **, IMG_UINT32 *);
+
+ ppszStr = va_arg(va, IMG_CHAR**);
+ pui32StrLen = va_arg(va, IMG_UINT32*);
+ ui32Mode = va_arg(va, IMG_UINT32);
+
+
+ switch(ui32Mode)
+ {
+ case PVRSRV_MISC_INFO_MEMSTATS_PRESENT:
+ pfnGetStats = &RA_GetStats;
+ break;
+ case PVRSRV_MISC_INFO_FREEMEM_PRESENT:
+ pfnGetStats = &RA_GetStatsFreeMem;
+ break;
+ default:
+ return;
+ }
+
+ if(psBMHeap->pImportArena)
+ {
+ pfnGetStats(psBMHeap->pImportArena,
+ ppszStr,
+ pui32StrLen);
+ }
+
+ if(psBMHeap->pVMArena)
+ {
+ pfnGetStats(psBMHeap->pVMArena,
+ ppszStr,
+ pui32StrLen);
+ }
+}
+
+static PVRSRV_ERROR PVRSRVGetMiscInfoKM_BMContext_AnyVaCb(BM_CONTEXT *psBMContext, va_list va)
+{
+
+ IMG_UINT32 *pui32StrLen;
+ IMG_INT32 *pi32Count;
+ IMG_CHAR **ppszStr;
+ IMG_UINT32 ui32Mode;
+
+ pui32StrLen = va_arg(va, IMG_UINT32*);
+ pi32Count = va_arg(va, IMG_INT32*);
+ ppszStr = va_arg(va, IMG_CHAR**);
+ ui32Mode = va_arg(va, IMG_UINT32);
+
+ CHECK_SPACE(*pui32StrLen);
+ *pi32Count = OSSNPrintf(*ppszStr, 100, "\nApplication Context (hDevMemContext) %p:\n",
+ (IMG_HANDLE)psBMContext);
+ UPDATE_SPACE(*ppszStr, *pi32Count, *pui32StrLen);
+
+ List_BM_HEAP_ForEach_va(psBMContext->psBMHeap,
+ &PVRSRVGetMiscInfoKM_RA_GetStats_ForEachVaCb,
+ ppszStr,
+ pui32StrLen,
+ ui32Mode);
+ return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR PVRSRVGetMiscInfoKM_Device_AnyVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
+{
+ IMG_UINT32 *pui32StrLen;
+ IMG_INT32 *pi32Count;
+ IMG_CHAR **ppszStr;
+ IMG_UINT32 ui32Mode;
+
+ pui32StrLen = va_arg(va, IMG_UINT32*);
+ pi32Count = va_arg(va, IMG_INT32*);
+ ppszStr = va_arg(va, IMG_CHAR**);
+ ui32Mode = va_arg(va, IMG_UINT32);
+
+ CHECK_SPACE(*pui32StrLen);
+ *pi32Count = OSSNPrintf(*ppszStr, 100, "\n\nDevice Type %d:\n", psDeviceNode->sDevId.eDeviceType);
+ UPDATE_SPACE(*ppszStr, *pi32Count, *pui32StrLen);
+
+
+ if(psDeviceNode->sDevMemoryInfo.pBMKernelContext)
+ {
+ CHECK_SPACE(*pui32StrLen);
+ *pi32Count = OSSNPrintf(*ppszStr, 100, "\nKernel Context:\n");
+ UPDATE_SPACE(*ppszStr, *pi32Count, *pui32StrLen);
+
+ List_BM_HEAP_ForEach_va(psDeviceNode->sDevMemoryInfo.pBMKernelContext->psBMHeap,
+ &PVRSRVGetMiscInfoKM_RA_GetStats_ForEachVaCb,
+ ppszStr,
+ pui32StrLen,
+ ui32Mode);
+ }
+
+
+ return List_BM_CONTEXT_PVRSRV_ERROR_Any_va(psDeviceNode->sDevMemoryInfo.pBMContext,
+ &PVRSRVGetMiscInfoKM_BMContext_AnyVaCb,
+ pui32StrLen,
+ pi32Count,
+ ppszStr,
+ ui32Mode);
+}
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo)
+{
+ SYS_DATA *psSysData;
+
+ if(!psMiscInfo)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetMiscInfoKM: invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psMiscInfo->ui32StatePresent = 0;
+
+
+ if(psMiscInfo->ui32StateRequest & ~(PVRSRV_MISC_INFO_TIMER_PRESENT
+ |PVRSRV_MISC_INFO_CLOCKGATE_PRESENT
+ |PVRSRV_MISC_INFO_MEMSTATS_PRESENT
+ |PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT
+ |PVRSRV_MISC_INFO_DDKVERSION_PRESENT
+ |PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT
+ |PVRSRV_MISC_INFO_RESET_PRESENT
+ |PVRSRV_MISC_INFO_FREEMEM_PRESENT))
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetMiscInfoKM: invalid state request flags"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ SysAcquireData(&psSysData);
+
+
+ if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_TIMER_PRESENT) != 0UL) &&
+ (psSysData->pvSOCTimerRegisterKM != IMG_NULL))
+ {
+ psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_TIMER_PRESENT;
+ psMiscInfo->pvSOCTimerRegisterKM = psSysData->pvSOCTimerRegisterKM;
+ psMiscInfo->hSOCTimerRegisterOSMemHandle = psSysData->hSOCTimerRegisterOSMemHandle;
+ }
+ else
+ {
+ psMiscInfo->pvSOCTimerRegisterKM = IMG_NULL;
+ psMiscInfo->hSOCTimerRegisterOSMemHandle = IMG_NULL;
+ }
+
+
+ if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_CLOCKGATE_PRESENT) != 0UL) &&
+ (psSysData->pvSOCClockGateRegsBase != IMG_NULL))
+ {
+ psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_CLOCKGATE_PRESENT;
+ psMiscInfo->pvSOCClockGateRegs = psSysData->pvSOCClockGateRegsBase;
+ psMiscInfo->ui32SOCClockGateRegsSize = psSysData->ui32SOCClockGateRegsSize;
+ }
+
+
+ if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) != 0UL) &&
+ (psMiscInfo->pszMemoryStr != IMG_NULL))
+ {
+ RA_ARENA **ppArena;
+ IMG_CHAR *pszStr;
+ IMG_UINT32 ui32StrLen;
+ IMG_INT32 i32Count;
+
+ pszStr = psMiscInfo->pszMemoryStr;
+ ui32StrLen = psMiscInfo->ui32MemoryStrLen;
+
+ psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_MEMSTATS_PRESENT;
+
+
+ ppArena = &psSysData->apsLocalDevMemArena[0];
+ while(*ppArena)
+ {
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "\nLocal Backing Store:\n");
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ RA_GetStats(*ppArena,
+ &pszStr,
+ &ui32StrLen);
+
+ ppArena++;
+ }
+
+
+
+ List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psSysData->psDeviceNodeList,
+ &PVRSRVGetMiscInfoKM_Device_AnyVaCb,
+ &ui32StrLen,
+ &i32Count,
+ &pszStr,
+ PVRSRV_MISC_INFO_MEMSTATS_PRESENT);
+
+
+ i32Count = OSSNPrintf(pszStr, 100, "\n");
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+ }
+
+
+ if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_FREEMEM_PRESENT)
+ && psMiscInfo->pszMemoryStr)
+ {
+ IMG_CHAR *pszStr;
+ IMG_UINT32 ui32StrLen;
+ IMG_INT32 i32Count;
+
+ pszStr = psMiscInfo->pszMemoryStr;
+ ui32StrLen = psMiscInfo->ui32MemoryStrLen;
+
+ psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_FREEMEM_PRESENT;
+
+
+ List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psSysData->psDeviceNodeList,
+ &PVRSRVGetMiscInfoKM_Device_AnyVaCb,
+ &ui32StrLen,
+ &i32Count,
+ &pszStr,
+ PVRSRV_MISC_INFO_FREEMEM_PRESENT);
+
+ i32Count = OSSNPrintf(pszStr, 100, "\n");
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+ }
+
+ if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT) != 0UL) &&
+ (psSysData->psGlobalEventObject != IMG_NULL))
+ {
+ psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT;
+ psMiscInfo->sGlobalEventObject = *psSysData->psGlobalEventObject;
+ }
+
+
+
+ if (((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0UL)
+ && ((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) == 0UL)
+ && (psMiscInfo->pszMemoryStr != IMG_NULL))
+ {
+ IMG_CHAR *pszStr;
+ IMG_UINT32 ui32StrLen;
+ IMG_UINT32 ui32LenStrPerNum = 12;
+ IMG_INT32 i32Count;
+ PVRSRV_SGXDEV_INFO *sgx_dev_info;
+ PVRSRV_SGX_MISCINFO_INFO *sgx_misc_info;
+ PVRSRV_SGX_MISCINFO_FEATURES *sgx_features;
+ unsigned long fw_ver;
+ IMG_INT i;
+ psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_DDKVERSION_PRESENT;
+
+ /*
+ * Since the kernel driver has already made sure that the
+ * firmware version is supported by the kernel driver in
+ * SGXDevInitCompatCheck, it's redundant for the user space
+ * part to perform the same check. In order to support older
+ * user space libraries where this check hasn't yet been removed,
+ * simply report the version of the downloaded firmware which
+ * will result in an exact match in user space.
+ */
+ sgx_dev_info = pvr_get_sgx_dev_info();
+ if (!sgx_dev_info || !sgx_dev_info->psKernelSGXMiscMemInfo ||
+ !sgx_dev_info->psKernelSGXMiscMemInfo->pvLinAddrKM)
+ return PVRSRV_ERROR_INVALID_DEVICE;
+
+ sgx_misc_info = sgx_dev_info->psKernelSGXMiscMemInfo->pvLinAddrKM;
+ sgx_features = &sgx_misc_info->sSGXFeatures;
+ fw_ver = sgx_features->ui32DDKVersion;
+
+ psMiscInfo->aui32DDKVersion[0] = PVR_FW_VER_MAJOR(fw_ver);
+ psMiscInfo->aui32DDKVersion[1] = PVR_FW_VER_MINOR(fw_ver);
+ psMiscInfo->aui32DDKVersion[2] = PVR_FW_VER_BRANCH(fw_ver);
+ psMiscInfo->aui32DDKVersion[3] = sgx_features->ui32DDKBuild;
+
+ pszStr = psMiscInfo->pszMemoryStr;
+ ui32StrLen = psMiscInfo->ui32MemoryStrLen;
+
+ for (i=0; i<4; i++)
+ {
+ if (ui32StrLen < ui32LenStrPerNum)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ i32Count = OSSNPrintf(pszStr, ui32LenStrPerNum, "%u", psMiscInfo->aui32DDKVersion[i]);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+ if (i != 3)
+ {
+ i32Count = OSSNPrintf(pszStr, 2, ".");
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+ }
+ }
+ }
+
+ if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT) != 0UL)
+ {
+ if(psMiscInfo->sCacheOpCtl.bDeferOp)
+ {
+
+ psSysData->ePendingCacheOpType = psMiscInfo->sCacheOpCtl.eCacheOpType;
+ }
+ else
+ {
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ PVRSRV_PER_PROCESS_DATA *psPerProc;
+
+ if(!psMiscInfo->sCacheOpCtl.u.psKernelMemInfo)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "PVRSRVGetMiscInfoKM: "
+ "Ignoring non-deferred cache op with no meminfo"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if(psSysData->ePendingCacheOpType != PVRSRV_MISC_INFO_CPUCACHEOP_NONE)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "PVRSRVGetMiscInfoKM: "
+ "Deferred cache op is pending. It is unlikely you want "
+ "to combine deferred cache ops with immediate ones"));
+ }
+
+
+ psPerProc = PVRSRVFindPerProcessData();
+
+ if(PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_PVOID *)&psKernelMemInfo,
+ psMiscInfo->sCacheOpCtl.u.psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetMiscInfoKM: "
+ "Can't find kernel meminfo"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if(psMiscInfo->sCacheOpCtl.eCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH)
+ {
+ if(!OSFlushCPUCacheRangeKM(psKernelMemInfo->sMemBlk.hOSMemHandle,
+ psMiscInfo->sCacheOpCtl.pvBaseVAddr,
+ psMiscInfo->sCacheOpCtl.ui32Length))
+ {
+ return PVRSRV_ERROR_CACHEOP_FAILED;
+ }
+ }
+ else if(psMiscInfo->sCacheOpCtl.eCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN)
+ {
+ if(!OSCleanCPUCacheRangeKM(psKernelMemInfo->sMemBlk.hOSMemHandle,
+ psMiscInfo->sCacheOpCtl.pvBaseVAddr,
+ psMiscInfo->sCacheOpCtl.ui32Length))
+ {
+ return PVRSRV_ERROR_CACHEOP_FAILED;
+ }
+ }
+ }
+ }
+
+#if defined(PVRSRV_RESET_ON_HWTIMEOUT)
+ if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_RESET_PRESENT) != 0UL)
+ {
+ PVR_LOG(("User requested OS reset"));
+ OSPanic();
+ }
+#endif
+
+ return PVRSRV_OK;
+}
+
+
+IMG_BOOL IMG_CALLCONV PVRSRVDeviceLISR(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ SYS_DATA *psSysData;
+ IMG_BOOL bStatus = IMG_FALSE;
+ IMG_UINT32 ui32InterruptSource;
+
+ if(!psDeviceNode)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVDeviceLISR: Invalid params\n"));
+ goto out;
+ }
+ psSysData = psDeviceNode->psSysData;
+
+
+ ui32InterruptSource = SysGetInterruptSource(psSysData, psDeviceNode);
+ if(ui32InterruptSource & psDeviceNode->ui32SOCInterruptBit)
+ {
+ if(psDeviceNode->pfnDeviceISR != IMG_NULL)
+ {
+ bStatus = (*psDeviceNode->pfnDeviceISR)(psDeviceNode->pvISRData);
+ }
+
+ SysClearInterrupts(psSysData, psDeviceNode->ui32SOCInterruptBit);
+ }
+
+out:
+ return bStatus;
+}
+
+static IMG_VOID PVRSRVSystemLISR_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
+{
+
+ IMG_BOOL *pbStatus;
+ IMG_UINT32 *pui32InterruptSource;
+ IMG_UINT32 *pui32ClearInterrupts;
+
+ pbStatus = va_arg(va, IMG_BOOL*);
+ pui32InterruptSource = va_arg(va, IMG_UINT32*);
+ pui32ClearInterrupts = va_arg(va, IMG_UINT32*);
+
+
+ if(psDeviceNode->pfnDeviceISR != IMG_NULL)
+ {
+ if(*pui32InterruptSource & psDeviceNode->ui32SOCInterruptBit)
+ {
+ if((*psDeviceNode->pfnDeviceISR)(psDeviceNode->pvISRData))
+ {
+
+ *pbStatus = IMG_TRUE;
+ }
+
+ *pui32ClearInterrupts |= psDeviceNode->ui32SOCInterruptBit;
+ }
+ }
+}
+
+IMG_BOOL IMG_CALLCONV PVRSRVSystemLISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = pvSysData;
+ IMG_BOOL bStatus = IMG_FALSE;
+ IMG_UINT32 ui32InterruptSource;
+ IMG_UINT32 ui32ClearInterrupts = 0;
+ if(!psSysData)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSystemLISR: Invalid params\n"));
+ }
+ else
+ {
+
+ ui32InterruptSource = SysGetInterruptSource(psSysData, IMG_NULL);
+
+
+ if(ui32InterruptSource)
+ {
+
+ List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList,
+ &PVRSRVSystemLISR_ForEachVaCb,
+ &bStatus,
+ &ui32InterruptSource,
+ &ui32ClearInterrupts);
+
+ SysClearInterrupts(psSysData, ui32ClearInterrupts);
+ }
+ }
+ return bStatus;
+}
+
+
+static IMG_VOID PVRSRVMISR_ForEachCb(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ if(psDeviceNode->pfnDeviceMISR != IMG_NULL)
+ {
+ (*psDeviceNode->pfnDeviceMISR)(psDeviceNode->pvISRData);
+ }
+}
+
+IMG_VOID IMG_CALLCONV PVRSRVMISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = pvSysData;
+ if(!psSysData)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVMISR: Invalid params\n"));
+ return;
+ }
+
+
+ List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList,
+ &PVRSRVMISR_ForEachCb);
+
+
+ if (PVRSRVProcessQueues(ISR_ID, IMG_FALSE) == PVRSRV_ERROR_PROCESSING_BLOCKED)
+ {
+ PVRSRVProcessQueues(ISR_ID, IMG_FALSE);
+ }
+
+
+ if (psSysData->psGlobalEventObject)
+ {
+ IMG_HANDLE hOSEventKM = psSysData->psGlobalEventObject->hOSEventKM;
+ if(hOSEventKM)
+ {
+ OSEventObjectSignal(hOSEventKM);
+ }
+ }
+
+ PVRSRVCheckPendingSyncs();
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVProcessConnect(IMG_UINT32 ui32PID, IMG_UINT32 ui32Flags)
+{
+ return PVRSRVPerProcessDataConnect(ui32PID, ui32Flags);
+}
+
+
+IMG_EXPORT
+IMG_VOID IMG_CALLCONV PVRSRVProcessDisconnect(IMG_UINT32 ui32PID)
+{
+ PVRSRVPerProcessDataDisconnect(ui32PID);
+}
+
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSaveRestoreLiveSegments(IMG_HANDLE hArena, IMG_PBYTE pbyBuffer,
+ IMG_SIZE_T *puiBufSize, IMG_BOOL bSave)
+{
+ IMG_SIZE_T uiBytesSaved = 0;
+ IMG_PVOID pvLocalMemCPUVAddr;
+ RA_SEGMENT_DETAILS sSegDetails;
+
+ if (hArena == IMG_NULL)
+ {
+ return (PVRSRV_ERROR_INVALID_PARAMS);
+ }
+
+ sSegDetails.uiSize = 0;
+ sSegDetails.sCpuPhyAddr.uiAddr = 0;
+ sSegDetails.hSegment = 0;
+
+
+ while (RA_GetNextLiveSegment(hArena, &sSegDetails))
+ {
+ if (pbyBuffer == IMG_NULL)
+ {
+
+ uiBytesSaved += sizeof(sSegDetails.uiSize) + sSegDetails.uiSize;
+ }
+ else
+ {
+ if ((uiBytesSaved + sizeof(sSegDetails.uiSize) + sSegDetails.uiSize) > *puiBufSize)
+ {
+ return (PVRSRV_ERROR_OUT_OF_MEMORY);
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVSaveRestoreLiveSegments: Base %08x size %08x", sSegDetails.sCpuPhyAddr.uiAddr, sSegDetails.uiSize));
+
+
+ pvLocalMemCPUVAddr = OSMapPhysToLin(sSegDetails.sCpuPhyAddr,
+ sSegDetails.uiSize,
+ PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+ IMG_NULL);
+ if (pvLocalMemCPUVAddr == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSaveRestoreLiveSegments: Failed to map local memory to host"));
+ return (PVRSRV_ERROR_OUT_OF_MEMORY);
+ }
+
+ if (bSave)
+ {
+
+ OSMemCopy(pbyBuffer, &sSegDetails.uiSize, sizeof(sSegDetails.uiSize));
+ pbyBuffer += sizeof(sSegDetails.uiSize);
+
+ OSMemCopy(pbyBuffer, pvLocalMemCPUVAddr, sSegDetails.uiSize);
+ pbyBuffer += sSegDetails.uiSize;
+ }
+ else
+ {
+ IMG_UINT32 uiSize;
+
+ OSMemCopy(&uiSize, pbyBuffer, sizeof(sSegDetails.uiSize));
+
+ if (uiSize != sSegDetails.uiSize)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSaveRestoreLiveSegments: Segment size error"));
+ }
+ else
+ {
+ pbyBuffer += sizeof(sSegDetails.uiSize);
+
+ OSMemCopy(pvLocalMemCPUVAddr, pbyBuffer, sSegDetails.uiSize);
+ pbyBuffer += sSegDetails.uiSize;
+ }
+ }
+
+
+ uiBytesSaved += sizeof(sSegDetails.uiSize) + sSegDetails.uiSize;
+
+ OSUnMapPhysToLin(pvLocalMemCPUVAddr,
+ sSegDetails.uiSize,
+ PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+ IMG_NULL);
+ }
+ }
+
+ if (pbyBuffer == IMG_NULL)
+ {
+ *puiBufSize = uiBytesSaved;
+ }
+
+ return (PVRSRV_OK);
+}
+
+
+IMG_EXPORT
+const IMG_CHAR *PVRSRVGetErrorStringKM(PVRSRV_ERROR eError)
+{
+
+#include "pvrsrv_errors.h"
+}
+
+static IMG_VOID PVRSRVCommandCompleteCallbacks_ForEachCb(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ if(psDeviceNode->pfnDeviceCommandComplete != IMG_NULL)
+ {
+
+ (*psDeviceNode->pfnDeviceCommandComplete)(psDeviceNode);
+ }
+}
+
+IMG_VOID PVRSRVScheduleDeviceCallbacks(IMG_VOID)
+{
+ SYS_DATA *psSysData;
+ SysAcquireData(&psSysData);
+
+
+ List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList,
+ &PVRSRVCommandCompleteCallbacks_ForEachCb);
+}
+
+IMG_EXPORT
+IMG_VOID PVRSRVScheduleDevicesKM(IMG_VOID)
+{
+ PVRSRVScheduleDeviceCallbacks();
+}
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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 "services_headers.h"
+
+#include "lists.h"
+#include "pvr_trace_cmd.h"
+
+
+#define DC_NUM_COMMANDS_PER_TYPE 1
+
+typedef struct _DEVICE_COMMAND_DATA_
+{
+ PFN_CMD_PROC pfnCmdProc;
+ PCOMMAND_COMPLETE_DATA apsCmdCompleteData[DC_NUM_COMMANDS_PER_TYPE];
+ IMG_UINT32 ui32CCBOffset;
+} DEVICE_COMMAND_DATA;
+
+
+#if defined(__linux__) && defined(__KERNEL__)
+
+#include "proc.h"
+
+void ProcSeqShowQueue(struct seq_file *sfile,void* el)
+{
+ PVRSRV_QUEUE_INFO *psQueue = (PVRSRV_QUEUE_INFO*)el;
+ IMG_INT cmds = 0;
+ IMG_SIZE_T ui32ReadOffset;
+ IMG_SIZE_T ui32WriteOffset;
+ PVRSRV_COMMAND *psCmd;
+
+ if(el == PVR_PROC_SEQ_START_TOKEN)
+ {
+ seq_printf( sfile,
+ "Command Queues\n"
+ "Queue CmdPtr Pid Command Size DevInd DSC SSC #Data ...\n");
+ return;
+ }
+
+ ui32ReadOffset = psQueue->ui32ReadOffset;
+ ui32WriteOffset = psQueue->ui32WriteOffset;
+
+ while (ui32ReadOffset != ui32WriteOffset)
+ {
+ psCmd= (PVRSRV_COMMAND *)((IMG_UINTPTR_T)psQueue->pvLinQueueKM + ui32ReadOffset);
+
+ seq_printf(sfile, "%x %x %5u %6u %3u %5u %2u %2u %3u \n",
+ (IMG_UINTPTR_T)psQueue,
+ (IMG_UINTPTR_T)psCmd,
+ psCmd->ui32ProcessID,
+ psCmd->CommandType,
+ psCmd->ui32CmdSize,
+ psCmd->ui32DevIndex,
+ psCmd->ui32DstSyncCount,
+ psCmd->ui32SrcSyncCount,
+ psCmd->ui32DataSize);
+
+ ui32ReadOffset += psCmd->ui32CmdSize;
+ ui32ReadOffset &= psQueue->ui32QueueSize - 1;
+ cmds++;
+ }
+
+ if (cmds == 0)
+ {
+ seq_printf(sfile, "%x <empty>\n", (IMG_UINTPTR_T)psQueue);
+ }
+}
+
+void* ProcSeqOff2ElementQueue(struct seq_file * sfile, loff_t off)
+{
+ PVRSRV_QUEUE_INFO *psQueue = IMG_NULL;
+ SYS_DATA *psSysData;
+
+ PVR_UNREFERENCED_PARAMETER(sfile);
+
+ if(!off)
+ {
+ return PVR_PROC_SEQ_START_TOKEN;
+ }
+
+
+ psSysData = SysAcquireDataNoCheck();
+ if (psSysData != IMG_NULL)
+ {
+ for (psQueue = psSysData->psQueueList; (((--off) > 0) && (psQueue != IMG_NULL)); psQueue = psQueue->psNextKM);
+ }
+
+ return psQueue;
+}
+#endif
+
+#define GET_SPACE_IN_CMDQ(psQueue) \
+ ((((psQueue)->ui32ReadOffset - (psQueue)->ui32WriteOffset) \
+ + ((psQueue)->ui32QueueSize - 1)) & ((psQueue)->ui32QueueSize - 1))
+
+#define UPDATE_QUEUE_WOFF(psQueue, ui32Size) \
+ (psQueue)->ui32WriteOffset = ((psQueue)->ui32WriteOffset + (ui32Size)) \
+ & ((psQueue)->ui32QueueSize - 1);
+
+#define SYNCOPS_STALE(ui32OpsComplete, ui32OpsPending) \
+ ((ui32OpsComplete) >= (ui32OpsPending))
+
+
+static IMG_VOID QueueDumpCmdComplete(COMMAND_COMPLETE_DATA *psCmdCompleteData,
+ IMG_UINT32 i,
+ IMG_BOOL bIsSrc)
+{
+ PVRSRV_SYNC_OBJECT *psSyncObject;
+
+ psSyncObject = bIsSrc ? psCmdCompleteData->psSrcSync : psCmdCompleteData->psDstSync;
+
+ if (psCmdCompleteData->bInUse)
+ {
+ PVR_LOG(("\t%s %u: ROC DevVAddr:0x%X ROP:0x%x ROC:0x%x, WOC DevVAddr:0x%X WOP:0x%x WOC:0x%x",
+ bIsSrc ? "SRC" : "DEST", i,
+ psSyncObject[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+ psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32ReadOpsPending,
+ psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32ReadOpsComplete,
+ psSyncObject[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+ psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32WriteOpsPending,
+ psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32WriteOpsComplete))
+ }
+ else
+ {
+ PVR_LOG(("\t%s %u: (Not in use)", bIsSrc ? "SRC" : "DEST", i))
+ }
+}
+
+
+static IMG_VOID QueueDumpDebugInfo_ForEachCb(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ if (psDeviceNode->sDevId.eDeviceClass == PVRSRV_DEVICE_CLASS_DISPLAY)
+ {
+ IMG_UINT32 ui32CmdCounter, ui32SyncCounter;
+ SYS_DATA *psSysData;
+ DEVICE_COMMAND_DATA *psDeviceCommandData;
+ PCOMMAND_COMPLETE_DATA psCmdCompleteData;
+
+ SysAcquireData(&psSysData);
+
+ psDeviceCommandData = psSysData->apsDeviceCommandData[psDeviceNode->sDevId.ui32DeviceIndex];
+
+ if (psDeviceCommandData != IMG_NULL)
+ {
+ for (ui32CmdCounter = 0; ui32CmdCounter < DC_NUM_COMMANDS_PER_TYPE; ui32CmdCounter++)
+ {
+ psCmdCompleteData = psDeviceCommandData[DC_FLIP_COMMAND].apsCmdCompleteData[ui32CmdCounter];
+
+ PVR_LOG(("Flip Command Complete Data %u for display device %u:",
+ ui32CmdCounter, psDeviceNode->sDevId.ui32DeviceIndex))
+
+ for (ui32SyncCounter = 0;
+ ui32SyncCounter < psCmdCompleteData->ui32SrcSyncCount;
+ ui32SyncCounter++)
+ {
+ QueueDumpCmdComplete(psCmdCompleteData, ui32SyncCounter, IMG_TRUE);
+ }
+
+ for (ui32SyncCounter = 0;
+ ui32SyncCounter < psCmdCompleteData->ui32DstSyncCount;
+ ui32SyncCounter++)
+ {
+ QueueDumpCmdComplete(psCmdCompleteData, ui32SyncCounter, IMG_FALSE);
+ }
+ }
+ }
+ else
+ {
+ PVR_LOG(("There is no Command Complete Data for display device %u", psDeviceNode->sDevId.ui32DeviceIndex))
+ }
+ }
+}
+
+
+IMG_VOID QueueDumpDebugInfo(IMG_VOID)
+{
+ SYS_DATA *psSysData;
+ SysAcquireData(&psSysData);
+ List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList, &QueueDumpDebugInfo_ForEachCb);
+}
+
+
+static IMG_SIZE_T NearestPower2(IMG_SIZE_T ui32Value)
+{
+ IMG_SIZE_T ui32Temp, ui32Result = 1;
+
+ if(!ui32Value)
+ return 0;
+
+ ui32Temp = ui32Value - 1;
+ while(ui32Temp)
+ {
+ ui32Result <<= 1;
+ ui32Temp >>= 1;
+ }
+
+ return ui32Result;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateCommandQueueKM(IMG_SIZE_T ui32QueueSize,
+ PVRSRV_QUEUE_INFO **ppsQueueInfo)
+{
+ PVRSRV_QUEUE_INFO *psQueueInfo;
+ IMG_SIZE_T ui32Power2QueueSize = NearestPower2(ui32QueueSize);
+ SYS_DATA *psSysData;
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hMemBlock;
+
+ SysAcquireData(&psSysData);
+
+
+ eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_QUEUE_INFO),
+ (IMG_VOID **)&psQueueInfo, &hMemBlock,
+ "Queue Info");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateCommandQueueKM: Failed to alloc queue struct"));
+ goto ErrorExit;
+ }
+ OSMemSet(psQueueInfo, 0, sizeof(PVRSRV_QUEUE_INFO));
+
+ psQueueInfo->hMemBlock[0] = hMemBlock;
+ psQueueInfo->ui32ProcessID = OSGetCurrentProcessIDKM();
+
+
+ eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ ui32Power2QueueSize + PVRSRV_MAX_CMD_SIZE,
+ &psQueueInfo->pvLinQueueKM, &hMemBlock,
+ "Command Queue");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateCommandQueueKM: Failed to alloc queue buffer"));
+ goto ErrorExit;
+ }
+
+ psQueueInfo->hMemBlock[1] = hMemBlock;
+ psQueueInfo->pvLinQueueUM = psQueueInfo->pvLinQueueKM;
+
+
+ PVR_ASSERT(psQueueInfo->ui32ReadOffset == 0);
+ PVR_ASSERT(psQueueInfo->ui32WriteOffset == 0);
+
+ psQueueInfo->ui32QueueSize = ui32Power2QueueSize;
+
+
+ if (psSysData->psQueueList == IMG_NULL)
+ {
+ eError = OSCreateResource(&psSysData->sQProcessResource);
+ if (eError != PVRSRV_OK)
+ {
+ goto ErrorExit;
+ }
+ }
+
+
+ eError = OSLockResource(&psSysData->sQProcessResource,
+ KERNEL_ID);
+ if (eError != PVRSRV_OK)
+ {
+ goto ErrorExit;
+ }
+
+ psQueueInfo->psNextKM = psSysData->psQueueList;
+ psSysData->psQueueList = psQueueInfo;
+
+ eError = OSUnlockResource(&psSysData->sQProcessResource, KERNEL_ID);
+ if (eError != PVRSRV_OK)
+ {
+ goto ErrorExit;
+ }
+
+ *ppsQueueInfo = psQueueInfo;
+
+ return PVRSRV_OK;
+
+ErrorExit:
+
+ if(psQueueInfo)
+ {
+ if(psQueueInfo->pvLinQueueKM)
+ {
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ psQueueInfo->ui32QueueSize,
+ psQueueInfo->pvLinQueueKM,
+ psQueueInfo->hMemBlock[1]);
+ psQueueInfo->pvLinQueueKM = IMG_NULL;
+ }
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_QUEUE_INFO),
+ psQueueInfo,
+ psQueueInfo->hMemBlock[0]);
+
+ }
+
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyCommandQueueKM(PVRSRV_QUEUE_INFO *psQueueInfo)
+{
+ PVRSRV_QUEUE_INFO *psQueue;
+ SYS_DATA *psSysData;
+ PVRSRV_ERROR eError;
+ IMG_BOOL bTimeout = IMG_TRUE;
+
+ SysAcquireData(&psSysData);
+
+ psQueue = psSysData->psQueueList;
+
+
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+ {
+ if(psQueueInfo->ui32ReadOffset == psQueueInfo->ui32WriteOffset)
+ {
+ bTimeout = IMG_FALSE;
+ break;
+ }
+ OSSleepms(1);
+ } END_LOOP_UNTIL_TIMEOUT();
+
+ if (bTimeout)
+ {
+
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVDestroyCommandQueueKM : Failed to empty queue"));
+ eError = PVRSRV_ERROR_CANNOT_FLUSH_QUEUE;
+ goto ErrorExit;
+ }
+
+
+ eError = OSLockResource(&psSysData->sQProcessResource,
+ KERNEL_ID);
+ if (eError != PVRSRV_OK)
+ {
+ goto ErrorExit;
+ }
+
+ if(psQueue == psQueueInfo)
+ {
+ psSysData->psQueueList = psQueueInfo->psNextKM;
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ NearestPower2(psQueueInfo->ui32QueueSize) + PVRSRV_MAX_CMD_SIZE,
+ psQueueInfo->pvLinQueueKM,
+ psQueueInfo->hMemBlock[1]);
+ psQueueInfo->pvLinQueueKM = IMG_NULL;
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_QUEUE_INFO),
+ psQueueInfo,
+ psQueueInfo->hMemBlock[0]);
+
+ psQueueInfo = IMG_NULL;
+ }
+ else
+ {
+ while(psQueue)
+ {
+ if(psQueue->psNextKM == psQueueInfo)
+ {
+ psQueue->psNextKM = psQueueInfo->psNextKM;
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ psQueueInfo->ui32QueueSize,
+ psQueueInfo->pvLinQueueKM,
+ psQueueInfo->hMemBlock[1]);
+ psQueueInfo->pvLinQueueKM = IMG_NULL;
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_QUEUE_INFO),
+ psQueueInfo,
+ psQueueInfo->hMemBlock[0]);
+
+ psQueueInfo = IMG_NULL;
+ break;
+ }
+ psQueue = psQueue->psNextKM;
+ }
+
+ if(!psQueue)
+ {
+ eError = OSUnlockResource(&psSysData->sQProcessResource, KERNEL_ID);
+ if (eError != PVRSRV_OK)
+ {
+ goto ErrorExit;
+ }
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto ErrorExit;
+ }
+ }
+
+
+ eError = OSUnlockResource(&psSysData->sQProcessResource, KERNEL_ID);
+ if (eError != PVRSRV_OK)
+ {
+ goto ErrorExit;
+ }
+
+
+ if (psSysData->psQueueList == IMG_NULL)
+ {
+ eError = OSDestroyResource(&psSysData->sQProcessResource);
+ if (eError != PVRSRV_OK)
+ {
+ goto ErrorExit;
+ }
+ }
+
+ErrorExit:
+
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetQueueSpaceKM(PVRSRV_QUEUE_INFO *psQueue,
+ IMG_SIZE_T ui32ParamSize,
+ IMG_VOID **ppvSpace)
+{
+ IMG_BOOL bTimeout = IMG_TRUE;
+
+
+ ui32ParamSize = (ui32ParamSize+3) & 0xFFFFFFFC;
+
+ if (ui32ParamSize > PVRSRV_MAX_CMD_SIZE)
+ {
+ PVR_DPF((PVR_DBG_WARNING,"PVRSRVGetQueueSpace: max command size is %d bytes", PVRSRV_MAX_CMD_SIZE));
+ return PVRSRV_ERROR_CMD_TOO_BIG;
+ }
+
+
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+ {
+ if (GET_SPACE_IN_CMDQ(psQueue) > ui32ParamSize)
+ {
+ bTimeout = IMG_FALSE;
+ break;
+ }
+ OSSleepms(1);
+ } END_LOOP_UNTIL_TIMEOUT();
+
+ if (bTimeout == IMG_TRUE)
+ {
+ *ppvSpace = IMG_NULL;
+
+ return PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE;
+ }
+ else
+ {
+ *ppvSpace = (IMG_VOID *)((IMG_UINTPTR_T)psQueue->pvLinQueueUM + psQueue->ui32WriteOffset);
+ }
+
+ return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVInsertCommandKM(PVRSRV_QUEUE_INFO *psQueue,
+ PVRSRV_COMMAND **ppsCommand,
+ IMG_UINT32 ui32DevIndex,
+ IMG_UINT16 CommandType,
+ IMG_UINT32 ui32DstSyncCount,
+ PVRSRV_KERNEL_SYNC_INFO *apsDstSync[],
+ IMG_UINT32 ui32SrcSyncCount,
+ PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[],
+ IMG_SIZE_T ui32DataByteSize )
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_COMMAND *psCommand;
+ IMG_SIZE_T ui32CommandSize;
+ IMG_UINT32 i;
+
+
+ ui32DataByteSize = (ui32DataByteSize + 3UL) & ~3UL;
+
+
+ ui32CommandSize = sizeof(PVRSRV_COMMAND)
+ + ((ui32DstSyncCount + ui32SrcSyncCount) * sizeof(PVRSRV_SYNC_OBJECT))
+ + ui32DataByteSize;
+
+
+ eError = PVRSRVGetQueueSpaceKM (psQueue, ui32CommandSize, (IMG_VOID**)&psCommand);
+ if(eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ psCommand->ui32ProcessID = OSGetCurrentProcessIDKM();
+
+
+ psCommand->ui32CmdSize = ui32CommandSize;
+ psCommand->ui32DevIndex = ui32DevIndex;
+ psCommand->CommandType = CommandType;
+ psCommand->ui32DstSyncCount = ui32DstSyncCount;
+ psCommand->ui32SrcSyncCount = ui32SrcSyncCount;
+
+
+ psCommand->psDstSync = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psCommand) + sizeof(PVRSRV_COMMAND));
+
+
+ psCommand->psSrcSync = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psCommand->psDstSync)
+ + (ui32DstSyncCount * sizeof(PVRSRV_SYNC_OBJECT)));
+
+ psCommand->pvData = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psCommand->psSrcSync)
+ + (ui32SrcSyncCount * sizeof(PVRSRV_SYNC_OBJECT)));
+ psCommand->ui32DataSize = ui32DataByteSize;
+
+
+ for (i=0; i<ui32DstSyncCount; i++)
+ {
+ psCommand->psDstSync[i].psKernelSyncInfoKM = apsDstSync[i];
+ psCommand->psDstSync[i].ui32WriteOpsPending = PVRSRVGetWriteOpsPending(apsDstSync[i], IMG_FALSE);
+ psCommand->psDstSync[i].ui32ReadOpsPending = PVRSRVGetReadOpsPending(apsDstSync[i], IMG_FALSE);
+
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVInsertCommandKM: Dst %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x",
+ i, psCommand->psDstSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+ psCommand->psDstSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+ psCommand->psDstSync[i].ui32ReadOpsPending,
+ psCommand->psDstSync[i].ui32WriteOpsPending));
+ }
+
+
+ for (i=0; i<ui32SrcSyncCount; i++)
+ {
+ psCommand->psSrcSync[i].psKernelSyncInfoKM = apsSrcSync[i];
+ psCommand->psSrcSync[i].ui32WriteOpsPending = PVRSRVGetWriteOpsPending(apsSrcSync[i], IMG_TRUE);
+ psCommand->psSrcSync[i].ui32ReadOpsPending = PVRSRVGetReadOpsPending(apsSrcSync[i], IMG_TRUE);
+
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVInsertCommandKM: Src %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x",
+ i, psCommand->psSrcSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+ psCommand->psSrcSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+ psCommand->psSrcSync[i].ui32ReadOpsPending,
+ psCommand->psSrcSync[i].ui32WriteOpsPending));
+ }
+
+
+ *ppsCommand = psCommand;
+
+ return PVRSRV_OK;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSubmitCommandKM(PVRSRV_QUEUE_INFO *psQueue,
+ PVRSRV_COMMAND *psCommand)
+{
+
+
+
+ if (psCommand->ui32DstSyncCount > 0)
+ {
+ psCommand->psDstSync = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psQueue->pvLinQueueKM)
+ + psQueue->ui32WriteOffset + sizeof(PVRSRV_COMMAND));
+ }
+
+ if (psCommand->ui32SrcSyncCount > 0)
+ {
+ psCommand->psSrcSync = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psQueue->pvLinQueueKM)
+ + psQueue->ui32WriteOffset + sizeof(PVRSRV_COMMAND)
+ + (psCommand->ui32DstSyncCount * sizeof(PVRSRV_SYNC_OBJECT)));
+ }
+
+ psCommand->pvData = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psQueue->pvLinQueueKM)
+ + psQueue->ui32WriteOffset + sizeof(PVRSRV_COMMAND)
+ + (psCommand->ui32DstSyncCount * sizeof(PVRSRV_SYNC_OBJECT))
+ + (psCommand->ui32SrcSyncCount * sizeof(PVRSRV_SYNC_OBJECT)));
+
+
+ UPDATE_QUEUE_WOFF(psQueue, psCommand->ui32CmdSize);
+
+ return PVRSRV_OK;
+}
+
+
+
+static
+PVRSRV_ERROR PVRSRVProcessCommand(SYS_DATA *psSysData,
+ PVRSRV_COMMAND *psCommand,
+ IMG_BOOL bFlush)
+{
+ PVRSRV_SYNC_OBJECT *psWalkerObj;
+ PVRSRV_SYNC_OBJECT *psEndObj;
+ IMG_UINT32 i;
+ COMMAND_COMPLETE_DATA *psCmdCompleteData;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ IMG_UINT32 ui32WriteOpsComplete;
+ IMG_UINT32 ui32ReadOpsComplete;
+ DEVICE_COMMAND_DATA *psDeviceCommandData;
+ IMG_UINT32 ui32CCBOffset;
+
+
+ psWalkerObj = psCommand->psDstSync;
+ psEndObj = psWalkerObj + psCommand->ui32DstSyncCount;
+ while (psWalkerObj < psEndObj)
+ {
+ PVRSRV_SYNC_DATA *psSyncData = psWalkerObj->psKernelSyncInfoKM->psSyncData;
+
+ ui32WriteOpsComplete = psSyncData->ui32WriteOpsComplete;
+ ui32ReadOpsComplete = psSyncData->ui32ReadOpsComplete;
+
+ if ((ui32WriteOpsComplete != psWalkerObj->ui32WriteOpsPending)
+ || (ui32ReadOpsComplete != psWalkerObj->ui32ReadOpsPending))
+ {
+ if (!bFlush ||
+ !SYNCOPS_STALE(ui32WriteOpsComplete, psWalkerObj->ui32WriteOpsPending) ||
+ !SYNCOPS_STALE(ui32ReadOpsComplete, psWalkerObj->ui32ReadOpsPending))
+ {
+ return PVRSRV_ERROR_FAILED_DEPENDENCIES;
+ }
+ }
+
+ psWalkerObj++;
+ }
+
+
+ psWalkerObj = psCommand->psSrcSync;
+ psEndObj = psWalkerObj + psCommand->ui32SrcSyncCount;
+ while (psWalkerObj < psEndObj)
+ {
+ PVRSRV_SYNC_DATA *psSyncData = psWalkerObj->psKernelSyncInfoKM->psSyncData;
+
+ ui32ReadOpsComplete = psSyncData->ui32ReadOpsComplete;
+ ui32WriteOpsComplete = psSyncData->ui32WriteOpsComplete;
+
+ if ((ui32WriteOpsComplete != psWalkerObj->ui32WriteOpsPending)
+ || (ui32ReadOpsComplete != psWalkerObj->ui32ReadOpsPending))
+ {
+ if (!bFlush &&
+ SYNCOPS_STALE(ui32WriteOpsComplete, psWalkerObj->ui32WriteOpsPending) &&
+ SYNCOPS_STALE(ui32ReadOpsComplete, psWalkerObj->ui32ReadOpsPending))
+ {
+ PVR_DPF((PVR_DBG_WARNING,
+ "PVRSRVProcessCommand: Stale syncops psSyncData:0x%x ui32WriteOpsComplete:0x%x ui32WriteOpsPending:0x%x",
+ (IMG_UINTPTR_T)psSyncData, ui32WriteOpsComplete, psWalkerObj->ui32WriteOpsPending));
+ }
+
+ if (!bFlush ||
+ !SYNCOPS_STALE(ui32WriteOpsComplete, psWalkerObj->ui32WriteOpsPending) ||
+ !SYNCOPS_STALE(ui32ReadOpsComplete, psWalkerObj->ui32ReadOpsPending))
+ {
+ return PVRSRV_ERROR_FAILED_DEPENDENCIES;
+ }
+ }
+ psWalkerObj++;
+ }
+
+
+ if (psCommand->ui32DevIndex >= SYS_DEVICE_COUNT)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVProcessCommand: invalid DeviceType 0x%x",
+ psCommand->ui32DevIndex));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ psDeviceCommandData = psSysData->apsDeviceCommandData[psCommand->ui32DevIndex];
+ ui32CCBOffset = psDeviceCommandData[psCommand->CommandType].ui32CCBOffset;
+ psCmdCompleteData = psDeviceCommandData[psCommand->CommandType].apsCmdCompleteData[ui32CCBOffset];
+ if (psCmdCompleteData->bInUse)
+ {
+
+ return PVRSRV_ERROR_FAILED_DEPENDENCIES;
+ }
+
+
+ psCmdCompleteData->bInUse = IMG_TRUE;
+
+
+ psCmdCompleteData->ui32DstSyncCount = psCommand->ui32DstSyncCount;
+ for (i=0; i<psCommand->ui32DstSyncCount; i++)
+ {
+ psCmdCompleteData->psDstSync[i] = psCommand->psDstSync[i];
+
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVProcessCommand: Dst %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x (CCB:%u)",
+ i, psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+ psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+ psCmdCompleteData->psDstSync[i].ui32ReadOpsPending,
+ psCmdCompleteData->psDstSync[i].ui32WriteOpsPending,
+ ui32CCBOffset));
+ }
+
+
+
+ psCmdCompleteData->ui32SrcSyncCount = psCommand->ui32SrcSyncCount;
+ for (i=0; i<psCommand->ui32SrcSyncCount; i++)
+ {
+ psCmdCompleteData->psSrcSync[i] = psCommand->psSrcSync[i];
+
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVProcessCommand: Src %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x (CCB:%u)",
+ i, psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+ psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+ psCmdCompleteData->psSrcSync[i].ui32ReadOpsPending,
+ psCmdCompleteData->psSrcSync[i].ui32WriteOpsPending,
+ ui32CCBOffset));
+ }
+
+
+
+
+
+
+
+
+
+
+
+ if (psDeviceCommandData[psCommand->CommandType].pfnCmdProc((IMG_HANDLE)psCmdCompleteData,
+ psCommand->ui32DataSize,
+ psCommand->pvData) == IMG_FALSE)
+ {
+
+
+
+ psCmdCompleteData->bInUse = IMG_FALSE;
+ eError = PVRSRV_ERROR_CMD_NOT_PROCESSED;
+ }
+
+
+ psDeviceCommandData[psCommand->CommandType].ui32CCBOffset = (ui32CCBOffset + 1) % DC_NUM_COMMANDS_PER_TYPE;
+
+ return eError;
+}
+
+
+static IMG_VOID PVRSRVProcessQueues_ForEachCb(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ if (psDeviceNode->bReProcessDeviceCommandComplete &&
+ psDeviceNode->pfnDeviceCommandComplete != IMG_NULL)
+ {
+ (*psDeviceNode->pfnDeviceCommandComplete)(psDeviceNode);
+ }
+}
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVProcessQueues(IMG_UINT32 ui32CallerID,
+ IMG_BOOL bFlush)
+{
+ PVRSRV_QUEUE_INFO *psQueue;
+ SYS_DATA *psSysData;
+ PVRSRV_COMMAND *psCommand;
+ PVRSRV_ERROR eError;
+
+ SysAcquireData(&psSysData);
+
+
+ psSysData->bReProcessQueues = IMG_FALSE;
+
+
+ eError = OSLockResource(&psSysData->sQProcessResource,
+ ui32CallerID);
+ if(eError != PVRSRV_OK)
+ {
+
+ psSysData->bReProcessQueues = IMG_TRUE;
+
+
+ if(ui32CallerID == ISR_ID)
+ {
+ if (bFlush)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVProcessQueues: Couldn't acquire queue processing lock for FLUSH"));
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"PVRSRVProcessQueues: Couldn't acquire queue processing lock"));
+ }
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"PVRSRVProcessQueues: Queue processing lock-acquire failed when called from the Services driver."));
+ PVR_DPF((PVR_DBG_MESSAGE," This is due to MISR queue processing being interrupted by the Services driver."));
+ }
+
+ return PVRSRV_OK;
+ }
+
+ psQueue = psSysData->psQueueList;
+
+ if(!psQueue)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"No Queues installed - cannot process commands"));
+ }
+
+ if (bFlush)
+ {
+ PVRSRVSetDCState(DC_STATE_FLUSH_COMMANDS);
+ }
+
+ while (psQueue)
+ {
+ while (psQueue->ui32ReadOffset != psQueue->ui32WriteOffset)
+ {
+ psCommand = (PVRSRV_COMMAND*)((IMG_UINTPTR_T)psQueue->pvLinQueueKM + psQueue->ui32ReadOffset);
+
+ if (PVRSRVProcessCommand(psSysData, psCommand, bFlush) == PVRSRV_OK)
+ {
+
+ UPDATE_QUEUE_ROFF(psQueue, psCommand->ui32CmdSize)
+
+ continue;
+ }
+
+ break;
+ }
+ psQueue = psQueue->psNextKM;
+ }
+
+ if (bFlush)
+ {
+ PVRSRVSetDCState(DC_STATE_NO_FLUSH_COMMANDS);
+ }
+
+
+ List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList,
+ &PVRSRVProcessQueues_ForEachCb);
+
+
+
+ OSUnlockResource(&psSysData->sQProcessResource, ui32CallerID);
+
+
+ if(psSysData->bReProcessQueues)
+ {
+ return PVRSRV_ERROR_PROCESSING_BLOCKED;
+ }
+
+ return PVRSRV_OK;
+}
+
+#if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS)
+IMG_INTERNAL
+IMG_VOID PVRSRVFreeCommandCompletePacketKM(IMG_HANDLE hCmdCookie,
+ IMG_BOOL bScheduleMISR)
+{
+ COMMAND_COMPLETE_DATA *psCmdCompleteData = (COMMAND_COMPLETE_DATA *)hCmdCookie;
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+
+
+ psCmdCompleteData->bInUse = IMG_FALSE;
+
+
+ PVRSRVScheduleDeviceCallbacks();
+
+ if(bScheduleMISR)
+ {
+ OSScheduleMISR(psSysData);
+ }
+}
+
+#endif
+
+
+IMG_EXPORT
+IMG_VOID PVRSRVCommandCompleteKM(IMG_HANDLE hCmdCookie,
+ IMG_BOOL bScheduleMISR)
+{
+ IMG_UINT32 i;
+ COMMAND_COMPLETE_DATA *psCmdCompleteData = (COMMAND_COMPLETE_DATA *)hCmdCookie;
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+
+
+ for (i=0; i<psCmdCompleteData->ui32DstSyncCount; i++)
+ {
+ psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->psSyncData->ui32WriteOpsComplete++;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVCommandCompleteKM: Dst %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x",
+ i, psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+ psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+ psCmdCompleteData->psDstSync[i].ui32ReadOpsPending,
+ psCmdCompleteData->psDstSync[i].ui32WriteOpsPending));
+ }
+
+
+ for (i=0; i<psCmdCompleteData->ui32SrcSyncCount; i++)
+ {
+ psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->psSyncData->ui32ReadOpsComplete++;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVCommandCompleteKM: Src %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x",
+ i, psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+ psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
+ psCmdCompleteData->psSrcSync[i].ui32ReadOpsPending,
+ psCmdCompleteData->psSrcSync[i].ui32WriteOpsPending));
+ }
+
+ pvr_trcmd_check_syn_completions(PVR_TRCMD_FLPCOMP);
+
+ psCmdCompleteData->bInUse = IMG_FALSE;
+
+
+ PVRSRVScheduleDeviceCallbacks();
+
+ if(bScheduleMISR)
+ {
+ OSScheduleMISR(psSysData);
+ }
+}
+
+
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRegisterCmdProcListKM(IMG_UINT32 ui32DevIndex,
+ PFN_CMD_PROC *ppfnCmdProcList,
+ IMG_UINT32 ui32MaxSyncsPerCmd[][2],
+ IMG_UINT32 ui32CmdCount)
+{
+ SYS_DATA *psSysData;
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32CmdCounter, ui32CmdTypeCounter;
+ IMG_SIZE_T ui32AllocSize;
+ DEVICE_COMMAND_DATA *psDeviceCommandData;
+ COMMAND_COMPLETE_DATA *psCmdCompleteData;
+
+
+ if(ui32DevIndex >= SYS_DEVICE_COUNT)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVRegisterCmdProcListKM: invalid DeviceType 0x%x",
+ ui32DevIndex));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ SysAcquireData(&psSysData);
+
+
+ ui32AllocSize = ui32CmdCount * sizeof(*psDeviceCommandData);
+ eError = OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP,
+ ui32AllocSize,
+ (IMG_VOID **)&psDeviceCommandData, IMG_NULL,
+ "Array of Pointers for Command Store");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterCmdProcListKM: Failed to alloc CC data"));
+ goto ErrorExit;
+ }
+
+ psSysData->apsDeviceCommandData[ui32DevIndex] = psDeviceCommandData;
+
+ for (ui32CmdTypeCounter = 0; ui32CmdTypeCounter < ui32CmdCount; ui32CmdTypeCounter++)
+ {
+ psDeviceCommandData[ui32CmdTypeCounter].pfnCmdProc = ppfnCmdProcList[ui32CmdTypeCounter];
+ psDeviceCommandData[ui32CmdTypeCounter].ui32CCBOffset = 0;
+
+ for (ui32CmdCounter = 0; ui32CmdCounter < DC_NUM_COMMANDS_PER_TYPE; ui32CmdCounter++)
+ {
+
+
+ ui32AllocSize = sizeof(COMMAND_COMPLETE_DATA)
+ + ((ui32MaxSyncsPerCmd[ui32CmdTypeCounter][0]
+ + ui32MaxSyncsPerCmd[ui32CmdTypeCounter][1])
+ * sizeof(PVRSRV_SYNC_OBJECT));
+
+ eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ ui32AllocSize,
+ (IMG_VOID **)&psCmdCompleteData,
+ IMG_NULL,
+ "Command Complete Data");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterCmdProcListKM: Failed to alloc cmd %d", ui32CmdTypeCounter));
+ goto ErrorExit;
+ }
+
+ psDeviceCommandData[ui32CmdTypeCounter].apsCmdCompleteData[ui32CmdCounter] = psCmdCompleteData;
+
+
+ OSMemSet(psCmdCompleteData, 0x00, ui32AllocSize);
+
+
+ psCmdCompleteData->psDstSync = (PVRSRV_SYNC_OBJECT*)
+ (((IMG_UINTPTR_T)psCmdCompleteData)
+ + sizeof(COMMAND_COMPLETE_DATA));
+ psCmdCompleteData->psSrcSync = (PVRSRV_SYNC_OBJECT*)
+ (((IMG_UINTPTR_T)psCmdCompleteData->psDstSync)
+ + (sizeof(PVRSRV_SYNC_OBJECT) * ui32MaxSyncsPerCmd[ui32CmdTypeCounter][0]));
+
+ psCmdCompleteData->ui32AllocSize = ui32AllocSize;
+ }
+ }
+
+ return PVRSRV_OK;
+
+ErrorExit:
+
+
+
+ if (PVRSRVRemoveCmdProcListKM(ui32DevIndex, ui32CmdCount) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVRegisterCmdProcListKM: Failed to clean up after error, device 0x%x",
+ ui32DevIndex));
+ }
+
+ return eError;
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVRemoveCmdProcListKM(IMG_UINT32 ui32DevIndex,
+ IMG_UINT32 ui32CmdCount)
+{
+ SYS_DATA *psSysData;
+ IMG_UINT32 ui32CmdTypeCounter, ui32CmdCounter;
+ DEVICE_COMMAND_DATA *psDeviceCommandData;
+ COMMAND_COMPLETE_DATA *psCmdCompleteData;
+ IMG_SIZE_T ui32AllocSize;
+
+
+ if(ui32DevIndex >= SYS_DEVICE_COUNT)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVRemoveCmdProcListKM: invalid DeviceType 0x%x",
+ ui32DevIndex));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ SysAcquireData(&psSysData);
+
+ psDeviceCommandData = psSysData->apsDeviceCommandData[ui32DevIndex];
+ if(psDeviceCommandData != IMG_NULL)
+ {
+ for (ui32CmdTypeCounter = 0; ui32CmdTypeCounter < ui32CmdCount; ui32CmdTypeCounter++)
+ {
+ for (ui32CmdCounter = 0; ui32CmdCounter < DC_NUM_COMMANDS_PER_TYPE; ui32CmdCounter++)
+ {
+ psCmdCompleteData = psDeviceCommandData[ui32CmdTypeCounter].apsCmdCompleteData[ui32CmdCounter];
+
+
+ if (psCmdCompleteData != IMG_NULL)
+ {
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, psCmdCompleteData->ui32AllocSize,
+ psCmdCompleteData, IMG_NULL);
+ psDeviceCommandData[ui32CmdTypeCounter].apsCmdCompleteData[ui32CmdCounter] = IMG_NULL;
+ }
+ }
+ }
+
+
+ ui32AllocSize = ui32CmdCount * sizeof(*psDeviceCommandData);
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, ui32AllocSize, psDeviceCommandData, IMG_NULL);
+ psSysData->apsDeviceCommandData[ui32DevIndex] = IMG_NULL;
+ }
+
+ return PVRSRV_OK;
+}
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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 "services_headers.h"
+#include "hash.h"
+#include "ra.h"
+#include "buffer_manager.h"
+#include "osfunc.h"
+
+#ifdef __linux__
+#include <linux/kernel.h>
+#include "proc.h"
+#endif
+
+#ifdef USE_BM_FREESPACE_CHECK
+#include <stdio.h>
+#endif
+
+#define MINIMUM_HASH_SIZE (64)
+
+#if defined(VALIDATE_ARENA_TEST)
+
+typedef enum RESOURCE_DESCRIPTOR_TAG {
+
+ RESOURCE_SPAN_LIVE = 10,
+ RESOURCE_SPAN_FREE,
+ IMPORTED_RESOURCE_SPAN_START,
+ IMPORTED_RESOURCE_SPAN_LIVE,
+ IMPORTED_RESOURCE_SPAN_FREE,
+ IMPORTED_RESOURCE_SPAN_END,
+
+} RESOURCE_DESCRIPTOR;
+
+typedef enum RESOURCE_TYPE_TAG {
+
+ IMPORTED_RESOURCE_TYPE = 20,
+ NON_IMPORTED_RESOURCE_TYPE
+
+} RESOURCE_TYPE;
+
+
+static IMG_UINT32 ui32BoundaryTagID = 0;
+
+IMG_UINT32 ValidateArena(RA_ARENA *pArena);
+#endif
+
+struct _BT_
+{
+ enum bt_type
+ {
+ btt_span,
+ btt_free,
+ btt_live
+ } type;
+
+
+ IMG_UINTPTR_T base;
+ IMG_SIZE_T uSize;
+
+
+ struct _BT_ *pNextSegment;
+ struct _BT_ *pPrevSegment;
+
+ struct _BT_ *pNextFree;
+ struct _BT_ *pPrevFree;
+
+ BM_MAPPING *psMapping;
+
+#if defined(VALIDATE_ARENA_TEST)
+ RESOURCE_DESCRIPTOR eResourceSpan;
+ RESOURCE_TYPE eResourceType;
+
+
+ IMG_UINT32 ui32BoundaryTagID;
+#endif
+
+};
+typedef struct _BT_ BT;
+
+
+struct _RA_ARENA_
+{
+
+ IMG_CHAR *name;
+
+
+ IMG_SIZE_T uQuantum;
+
+
+ IMG_BOOL (*pImportAlloc)(IMG_VOID *,
+ IMG_SIZE_T uSize,
+ IMG_SIZE_T *pActualSize,
+ BM_MAPPING **ppsMapping,
+ IMG_UINT32 uFlags,
+ IMG_UINTPTR_T *pBase);
+ IMG_VOID (*pImportFree) (IMG_VOID *,
+ IMG_UINTPTR_T,
+ BM_MAPPING *psMapping);
+ IMG_VOID (*pBackingStoreFree) (IMG_VOID *, IMG_SIZE_T, IMG_SIZE_T, IMG_HANDLE);
+
+
+ IMG_VOID *pImportHandle;
+
+
+#define FREE_TABLE_LIMIT 32
+
+
+ BT *aHeadFree [FREE_TABLE_LIMIT];
+
+
+ BT *pHeadSegment;
+ BT *pTailSegment;
+
+
+ HASH_TABLE *pSegmentHash;
+
+#ifdef RA_STATS
+ RA_STATISTICS sStatistics;
+#endif
+
+#if defined(CONFIG_PROC_FS) && defined(DEBUG)
+#define PROC_NAME_SIZE 32
+
+ struct proc_dir_entry* pProcInfo;
+ struct proc_dir_entry* pProcSegs;
+
+ IMG_BOOL bInitProcEntry;
+#endif
+};
+#if defined(ENABLE_RA_DUMP)
+IMG_VOID RA_Dump (RA_ARENA *pArena);
+#endif
+
+#if defined(CONFIG_PROC_FS) && defined(DEBUG)
+
+static void RA_ProcSeqShowInfo(struct seq_file *sfile, void* el);
+static void* RA_ProcSeqOff2ElementInfo(struct seq_file * sfile, loff_t off);
+
+static void RA_ProcSeqShowRegs(struct seq_file *sfile, void* el);
+static void* RA_ProcSeqOff2ElementRegs(struct seq_file * sfile, loff_t off);
+
+#endif
+
+#ifdef USE_BM_FREESPACE_CHECK
+IMG_VOID CheckBMFreespace(IMG_VOID);
+#endif
+
+#if defined(CONFIG_PROC_FS) && defined(DEBUG)
+static IMG_CHAR *ReplaceSpaces(IMG_CHAR * const pS)
+{
+ IMG_CHAR *pT;
+
+ for(pT = pS; *pT != 0; pT++)
+ {
+ if (*pT == ' ' || *pT == '\t')
+ {
+ *pT = '_';
+ }
+ }
+
+ return pS;
+}
+#endif
+
+static IMG_BOOL
+_RequestAllocFail (IMG_VOID *_h,
+ IMG_SIZE_T _uSize,
+ IMG_SIZE_T *_pActualSize,
+ BM_MAPPING **_ppsMapping,
+ IMG_UINT32 _uFlags,
+ IMG_UINTPTR_T *_pBase)
+{
+ PVR_UNREFERENCED_PARAMETER (_h);
+ PVR_UNREFERENCED_PARAMETER (_uSize);
+ PVR_UNREFERENCED_PARAMETER (_pActualSize);
+ PVR_UNREFERENCED_PARAMETER (_ppsMapping);
+ PVR_UNREFERENCED_PARAMETER (_uFlags);
+ PVR_UNREFERENCED_PARAMETER (_pBase);
+
+ return IMG_FALSE;
+}
+
+static IMG_UINT32
+pvr_log2 (IMG_SIZE_T n)
+{
+ IMG_UINT32 l = 0;
+ n>>=1;
+ while (n>0)
+ {
+ n>>=1;
+ l++;
+ }
+ return l;
+}
+
+static PVRSRV_ERROR
+_SegmentListInsertAfter (RA_ARENA *pArena,
+ BT *pInsertionPoint,
+ BT *pBT)
+{
+ PVR_ASSERT (pArena != IMG_NULL);
+ PVR_ASSERT (pInsertionPoint != IMG_NULL);
+
+ if ((pInsertionPoint == IMG_NULL) || (pArena == IMG_NULL))
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"_SegmentListInsertAfter: invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ pBT->pNextSegment = pInsertionPoint->pNextSegment;
+ pBT->pPrevSegment = pInsertionPoint;
+ if (pInsertionPoint->pNextSegment == IMG_NULL)
+ pArena->pTailSegment = pBT;
+ else
+ pInsertionPoint->pNextSegment->pPrevSegment = pBT;
+ pInsertionPoint->pNextSegment = pBT;
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR
+_SegmentListInsert (RA_ARENA *pArena, BT *pBT)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+
+ if (pArena->pHeadSegment == IMG_NULL)
+ {
+ pArena->pHeadSegment = pArena->pTailSegment = pBT;
+ pBT->pNextSegment = pBT->pPrevSegment = IMG_NULL;
+ }
+ else
+ {
+ BT *pBTScan;
+
+ if (pBT->base < pArena->pHeadSegment->base)
+ {
+
+ pBT->pNextSegment = pArena->pHeadSegment;
+ pArena->pHeadSegment->pPrevSegment = pBT;
+ pArena->pHeadSegment = pBT;
+ pBT->pPrevSegment = IMG_NULL;
+ }
+ else
+ {
+
+
+
+
+ pBTScan = pArena->pHeadSegment;
+
+ while ((pBTScan->pNextSegment != IMG_NULL) && (pBT->base >= pBTScan->pNextSegment->base))
+ {
+ pBTScan = pBTScan->pNextSegment;
+ }
+
+ eError = _SegmentListInsertAfter (pArena, pBTScan, pBT);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+ }
+ return eError;
+}
+
+static IMG_VOID
+_SegmentListRemove (RA_ARENA *pArena, BT *pBT)
+{
+ if (pBT->pPrevSegment == IMG_NULL)
+ pArena->pHeadSegment = pBT->pNextSegment;
+ else
+ pBT->pPrevSegment->pNextSegment = pBT->pNextSegment;
+
+ if (pBT->pNextSegment == IMG_NULL)
+ pArena->pTailSegment = pBT->pPrevSegment;
+ else
+ pBT->pNextSegment->pPrevSegment = pBT->pPrevSegment;
+}
+
+static BT *
+_SegmentSplit (RA_ARENA *pArena, BT *pBT, IMG_SIZE_T uSize)
+{
+ BT *pNeighbour;
+
+ PVR_ASSERT (pArena != IMG_NULL);
+
+ if (pArena == IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"_SegmentSplit: invalid parameter - pArena"));
+ return IMG_NULL;
+ }
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(BT),
+ (IMG_VOID **)&pNeighbour, IMG_NULL,
+ "Boundary Tag") != PVRSRV_OK)
+ {
+ return IMG_NULL;
+ }
+
+ OSMemSet(pNeighbour, 0, sizeof(BT));
+
+#if defined(VALIDATE_ARENA_TEST)
+ pNeighbour->ui32BoundaryTagID = ++ui32BoundaryTagID;
+#endif
+
+ pNeighbour->pPrevSegment = pBT;
+ pNeighbour->pNextSegment = pBT->pNextSegment;
+ if (pBT->pNextSegment == IMG_NULL)
+ pArena->pTailSegment = pNeighbour;
+ else
+ pBT->pNextSegment->pPrevSegment = pNeighbour;
+ pBT->pNextSegment = pNeighbour;
+
+ pNeighbour->type = btt_free;
+ pNeighbour->uSize = pBT->uSize - uSize;
+ pNeighbour->base = pBT->base + uSize;
+ pNeighbour->psMapping = pBT->psMapping;
+ pBT->uSize = uSize;
+
+#if defined(VALIDATE_ARENA_TEST)
+ if (pNeighbour->pPrevSegment->eResourceType == IMPORTED_RESOURCE_TYPE)
+ {
+ pNeighbour->eResourceType = IMPORTED_RESOURCE_TYPE;
+ pNeighbour->eResourceSpan = IMPORTED_RESOURCE_SPAN_FREE;
+ }
+ else if (pNeighbour->pPrevSegment->eResourceType == NON_IMPORTED_RESOURCE_TYPE)
+ {
+ pNeighbour->eResourceType = NON_IMPORTED_RESOURCE_TYPE;
+ pNeighbour->eResourceSpan = RESOURCE_SPAN_FREE;
+ }
+ else
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"_SegmentSplit: pNeighbour->pPrevSegment->eResourceType unrecognized"));
+ PVR_DBG_BREAK;
+ }
+#endif
+
+ return pNeighbour;
+}
+
+static IMG_VOID
+_FreeListInsert (RA_ARENA *pArena, BT *pBT)
+{
+ IMG_UINT32 uIndex;
+ uIndex = pvr_log2 (pBT->uSize);
+ pBT->type = btt_free;
+ pBT->pNextFree = pArena->aHeadFree [uIndex];
+ pBT->pPrevFree = IMG_NULL;
+ if (pArena->aHeadFree[uIndex] != IMG_NULL)
+ pArena->aHeadFree[uIndex]->pPrevFree = pBT;
+ pArena->aHeadFree [uIndex] = pBT;
+}
+
+static IMG_VOID
+_FreeListRemove (RA_ARENA *pArena, BT *pBT)
+{
+ IMG_UINT32 uIndex;
+ uIndex = pvr_log2 (pBT->uSize);
+ if (pBT->pNextFree != IMG_NULL)
+ pBT->pNextFree->pPrevFree = pBT->pPrevFree;
+ if (pBT->pPrevFree == IMG_NULL)
+ pArena->aHeadFree[uIndex] = pBT->pNextFree;
+ else
+ pBT->pPrevFree->pNextFree = pBT->pNextFree;
+}
+
+static BT *
+_BuildSpanMarker (IMG_UINTPTR_T base, IMG_SIZE_T uSize)
+{
+ BT *pBT;
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(BT),
+ (IMG_VOID **)&pBT, IMG_NULL,
+ "Boundary Tag") != PVRSRV_OK)
+ {
+ return IMG_NULL;
+ }
+
+ OSMemSet(pBT, 0, sizeof(BT));
+
+#if defined(VALIDATE_ARENA_TEST)
+ pBT->ui32BoundaryTagID = ++ui32BoundaryTagID;
+#endif
+
+ pBT->type = btt_span;
+ pBT->base = base;
+ pBT->uSize = uSize;
+ pBT->psMapping = IMG_NULL;
+
+ return pBT;
+}
+
+static BT *
+_BuildBT (IMG_UINTPTR_T base, IMG_SIZE_T uSize)
+{
+ BT *pBT;
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(BT),
+ (IMG_VOID **)&pBT, IMG_NULL,
+ "Boundary Tag") != PVRSRV_OK)
+ {
+ return IMG_NULL;
+ }
+
+ OSMemSet(pBT, 0, sizeof(BT));
+
+#if defined(VALIDATE_ARENA_TEST)
+ pBT->ui32BoundaryTagID = ++ui32BoundaryTagID;
+#endif
+
+ pBT->type = btt_free;
+ pBT->base = base;
+ pBT->uSize = uSize;
+
+ return pBT;
+}
+
+static BT *
+_InsertResource (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize)
+{
+ BT *pBT;
+ PVR_ASSERT (pArena!=IMG_NULL);
+ if (pArena == IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"_InsertResource: invalid parameter - pArena"));
+ return IMG_NULL;
+ }
+
+ pBT = _BuildBT (base, uSize);
+ if (pBT != IMG_NULL)
+ {
+
+#if defined(VALIDATE_ARENA_TEST)
+ pBT->eResourceSpan = RESOURCE_SPAN_FREE;
+ pBT->eResourceType = NON_IMPORTED_RESOURCE_TYPE;
+#endif
+
+ if (_SegmentListInsert (pArena, pBT) != PVRSRV_OK)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"_InsertResource: call to _SegmentListInsert failed"));
+ return IMG_NULL;
+ }
+ _FreeListInsert (pArena, pBT);
+#ifdef RA_STATS
+ pArena->sStatistics.uTotalResourceCount+=uSize;
+ pArena->sStatistics.uFreeResourceCount+=uSize;
+ pArena->sStatistics.uSpanCount++;
+#endif
+ }
+ return pBT;
+}
+
+static BT *
+_InsertResourceSpan (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize)
+{
+ PVRSRV_ERROR eError;
+ BT *pSpanStart;
+ BT *pSpanEnd;
+ BT *pBT;
+
+ PVR_ASSERT (pArena != IMG_NULL);
+ if (pArena == IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"_InsertResourceSpan: invalid parameter - pArena"));
+ return IMG_NULL;
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "RA_InsertResourceSpan: arena='%s', base=0x%x, size=0x%x",
+ pArena->name, base, uSize));
+
+ pSpanStart = _BuildSpanMarker (base, uSize);
+ if (pSpanStart == IMG_NULL)
+ {
+ goto fail_start;
+ }
+
+#if defined(VALIDATE_ARENA_TEST)
+ pSpanStart->eResourceSpan = IMPORTED_RESOURCE_SPAN_START;
+ pSpanStart->eResourceType = IMPORTED_RESOURCE_TYPE;
+#endif
+
+ pSpanEnd = _BuildSpanMarker (base + uSize, 0);
+ if (pSpanEnd == IMG_NULL)
+ {
+ goto fail_end;
+ }
+
+#if defined(VALIDATE_ARENA_TEST)
+ pSpanEnd->eResourceSpan = IMPORTED_RESOURCE_SPAN_END;
+ pSpanEnd->eResourceType = IMPORTED_RESOURCE_TYPE;
+#endif
+
+ pBT = _BuildBT (base, uSize);
+ if (pBT == IMG_NULL)
+ {
+ goto fail_bt;
+ }
+
+#if defined(VALIDATE_ARENA_TEST)
+ pBT->eResourceSpan = IMPORTED_RESOURCE_SPAN_FREE;
+ pBT->eResourceType = IMPORTED_RESOURCE_TYPE;
+#endif
+
+ eError = _SegmentListInsert (pArena, pSpanStart);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_SegListInsert;
+ }
+
+ eError = _SegmentListInsertAfter (pArena, pSpanStart, pBT);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_SegListInsert;
+ }
+
+ _FreeListInsert (pArena, pBT);
+
+ eError = _SegmentListInsertAfter (pArena, pBT, pSpanEnd);
+ if (eError != PVRSRV_OK)
+ {
+ goto fail_SegListInsert;
+ }
+
+#ifdef RA_STATS
+ pArena->sStatistics.uTotalResourceCount+=uSize;
+#endif
+ return pBT;
+
+ fail_SegListInsert:
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pBT, IMG_NULL);
+
+ fail_bt:
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pSpanEnd, IMG_NULL);
+
+ fail_end:
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pSpanStart, IMG_NULL);
+
+ fail_start:
+ return IMG_NULL;
+}
+
+static IMG_VOID
+_FreeBT (RA_ARENA *pArena, BT *pBT, IMG_BOOL bFreeBackingStore)
+{
+ BT *pNeighbour;
+ IMG_UINTPTR_T uOrigBase;
+ IMG_SIZE_T uOrigSize;
+
+ PVR_ASSERT (pArena!=IMG_NULL);
+ PVR_ASSERT (pBT!=IMG_NULL);
+
+ if ((pArena == IMG_NULL) || (pBT == IMG_NULL))
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"_FreeBT: invalid parameter"));
+ return;
+ }
+
+#ifdef RA_STATS
+ pArena->sStatistics.uLiveSegmentCount--;
+ pArena->sStatistics.uFreeSegmentCount++;
+ pArena->sStatistics.uFreeResourceCount+=pBT->uSize;
+#endif
+
+ uOrigBase = pBT->base;
+ uOrigSize = pBT->uSize;
+
+
+ pNeighbour = pBT->pPrevSegment;
+ if (pNeighbour!=IMG_NULL
+ && pNeighbour->type == btt_free
+ && pNeighbour->base + pNeighbour->uSize == pBT->base)
+ {
+ _FreeListRemove (pArena, pNeighbour);
+ _SegmentListRemove (pArena, pNeighbour);
+ pBT->base = pNeighbour->base;
+ pBT->uSize += pNeighbour->uSize;
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pNeighbour, IMG_NULL);
+
+#ifdef RA_STATS
+ pArena->sStatistics.uFreeSegmentCount--;
+#endif
+ }
+
+
+ pNeighbour = pBT->pNextSegment;
+ if (pNeighbour!=IMG_NULL
+ && pNeighbour->type == btt_free
+ && pBT->base + pBT->uSize == pNeighbour->base)
+ {
+ _FreeListRemove (pArena, pNeighbour);
+ _SegmentListRemove (pArena, pNeighbour);
+ pBT->uSize += pNeighbour->uSize;
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pNeighbour, IMG_NULL);
+
+#ifdef RA_STATS
+ pArena->sStatistics.uFreeSegmentCount--;
+#endif
+ }
+
+
+ if (pArena->pBackingStoreFree != IMG_NULL && bFreeBackingStore)
+ {
+ IMG_UINTPTR_T uRoundedStart, uRoundedEnd;
+
+
+ uRoundedStart = (uOrigBase / pArena->uQuantum) * pArena->uQuantum;
+
+ if (uRoundedStart < pBT->base)
+ {
+ uRoundedStart += pArena->uQuantum;
+ }
+
+
+ uRoundedEnd = ((uOrigBase + uOrigSize + pArena->uQuantum - 1) / pArena->uQuantum) * pArena->uQuantum;
+
+ if (uRoundedEnd > (pBT->base + pBT->uSize))
+ {
+ uRoundedEnd -= pArena->uQuantum;
+ }
+
+ if (uRoundedStart < uRoundedEnd)
+ {
+ pArena->pBackingStoreFree(pArena->pImportHandle, (IMG_SIZE_T)uRoundedStart, (IMG_SIZE_T)uRoundedEnd, (IMG_HANDLE)0);
+ }
+ }
+
+ if (pBT->pNextSegment!=IMG_NULL && pBT->pNextSegment->type == btt_span
+ && pBT->pPrevSegment!=IMG_NULL && pBT->pPrevSegment->type == btt_span)
+ {
+ BT *next = pBT->pNextSegment;
+ BT *prev = pBT->pPrevSegment;
+ _SegmentListRemove (pArena, next);
+ _SegmentListRemove (pArena, prev);
+ _SegmentListRemove (pArena, pBT);
+ pArena->pImportFree (pArena->pImportHandle, pBT->base, pBT->psMapping);
+#ifdef RA_STATS
+ pArena->sStatistics.uSpanCount--;
+ pArena->sStatistics.uExportCount++;
+ pArena->sStatistics.uFreeSegmentCount--;
+ pArena->sStatistics.uFreeResourceCount-=pBT->uSize;
+ pArena->sStatistics.uTotalResourceCount-=pBT->uSize;
+#endif
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), next, IMG_NULL);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), prev, IMG_NULL);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pBT, IMG_NULL);
+
+ }
+ else
+ _FreeListInsert (pArena, pBT);
+}
+
+
+static IMG_BOOL
+_AttemptAllocAligned (RA_ARENA *pArena,
+ IMG_SIZE_T uSize,
+ BM_MAPPING **ppsMapping,
+ IMG_UINT32 uFlags,
+ IMG_UINT32 uAlignment,
+ IMG_UINT32 uAlignmentOffset,
+ IMG_UINTPTR_T *base)
+{
+ IMG_UINT32 uIndex;
+ PVR_ASSERT (pArena!=IMG_NULL);
+ if (pArena == IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned: invalid parameter - pArena"));
+ return IMG_FALSE;
+ }
+
+ if (uAlignment>1)
+ uAlignmentOffset %= uAlignment;
+
+
+
+ uIndex = pvr_log2 (uSize);
+
+#if 0
+
+ if (1u<<uIndex < uSize)
+ uIndex++;
+#endif
+
+ while (uIndex < FREE_TABLE_LIMIT && pArena->aHeadFree[uIndex]==IMG_NULL)
+ uIndex++;
+
+ while (uIndex < FREE_TABLE_LIMIT)
+ {
+ if (pArena->aHeadFree[uIndex]!=IMG_NULL)
+ {
+
+ BT *pBT;
+
+ pBT = pArena->aHeadFree [uIndex];
+ while (pBT!=IMG_NULL)
+ {
+ IMG_UINTPTR_T aligned_base;
+
+ if (uAlignment>1)
+ aligned_base = (pBT->base + uAlignmentOffset + uAlignment - 1) / uAlignment * uAlignment - uAlignmentOffset;
+ else
+ aligned_base = pBT->base;
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "RA_AttemptAllocAligned: pBT-base=0x%x "
+ "pBT-size=0x%x alignedbase=0x%x size=0x%x",
+ pBT->base, pBT->uSize, aligned_base, uSize));
+
+ if (pBT->base + pBT->uSize >= aligned_base + uSize)
+ {
+ if(!pBT->psMapping || pBT->psMapping->ui32Flags == uFlags)
+ {
+ _FreeListRemove (pArena, pBT);
+
+ PVR_ASSERT (pBT->type == btt_free);
+
+#ifdef RA_STATS
+ pArena->sStatistics.uLiveSegmentCount++;
+ pArena->sStatistics.uFreeSegmentCount--;
+ pArena->sStatistics.uFreeResourceCount-=pBT->uSize;
+#endif
+
+
+ if (aligned_base > pBT->base)
+ {
+ BT *pNeighbour;
+ pNeighbour = _SegmentSplit (pArena, pBT, (IMG_SIZE_T)(aligned_base - pBT->base));
+
+ if (pNeighbour==IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned: Front split failed"));
+
+ _FreeListInsert (pArena, pBT);
+ return IMG_FALSE;
+ }
+
+ _FreeListInsert (pArena, pBT);
+ #ifdef RA_STATS
+ pArena->sStatistics.uFreeSegmentCount++;
+ pArena->sStatistics.uFreeResourceCount+=pBT->uSize;
+ #endif
+ pBT = pNeighbour;
+ }
+
+
+ if (pBT->uSize > uSize)
+ {
+ BT *pNeighbour;
+ pNeighbour = _SegmentSplit (pArena, pBT, uSize);
+
+ if (pNeighbour==IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned: Back split failed"));
+
+ _FreeListInsert (pArena, pBT);
+ return IMG_FALSE;
+ }
+
+ _FreeListInsert (pArena, pNeighbour);
+ #ifdef RA_STATS
+ pArena->sStatistics.uFreeSegmentCount++;
+ pArena->sStatistics.uFreeResourceCount+=pNeighbour->uSize;
+ #endif
+ }
+
+ pBT->type = btt_live;
+
+#if defined(VALIDATE_ARENA_TEST)
+ if (pBT->eResourceType == IMPORTED_RESOURCE_TYPE)
+ {
+ pBT->eResourceSpan = IMPORTED_RESOURCE_SPAN_LIVE;
+ }
+ else if (pBT->eResourceType == NON_IMPORTED_RESOURCE_TYPE)
+ {
+ pBT->eResourceSpan = RESOURCE_SPAN_LIVE;
+ }
+ else
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned ERROR: pBT->eResourceType unrecognized"));
+ PVR_DBG_BREAK;
+ }
+#endif
+ if (!HASH_Insert (pArena->pSegmentHash, pBT->base, (IMG_UINTPTR_T) pBT))
+ {
+ _FreeBT (pArena, pBT, IMG_FALSE);
+ return IMG_FALSE;
+ }
+
+ if (ppsMapping!=IMG_NULL)
+ *ppsMapping = pBT->psMapping;
+
+ *base = pBT->base;
+
+ return IMG_TRUE;
+ }
+ else
+ {
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "AttemptAllocAligned: mismatch in flags. Import has %x, request was %x", pBT->psMapping->ui32Flags, uFlags));
+
+ }
+ }
+ pBT = pBT->pNextFree;
+ }
+
+ }
+ uIndex++;
+ }
+
+ return IMG_FALSE;
+}
+
+
+
+RA_ARENA *
+RA_Create (IMG_CHAR *name,
+ IMG_UINTPTR_T base,
+ IMG_SIZE_T uSize,
+ BM_MAPPING *psMapping,
+ IMG_SIZE_T uQuantum,
+ IMG_BOOL (*imp_alloc)(IMG_VOID *, IMG_SIZE_T uSize, IMG_SIZE_T *pActualSize,
+ BM_MAPPING **ppsMapping, IMG_UINT32 _flags, IMG_UINTPTR_T *pBase),
+ IMG_VOID (*imp_free) (IMG_VOID *, IMG_UINTPTR_T, BM_MAPPING *),
+ IMG_VOID (*backingstore_free) (IMG_VOID*, IMG_SIZE_T, IMG_SIZE_T, IMG_HANDLE),
+ IMG_VOID *pImportHandle)
+{
+ RA_ARENA *pArena;
+ BT *pBT;
+ IMG_INT i;
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "RA_Create: name='%s', base=0x%x, uSize=0x%x, alloc=0x%x, free=0x%x",
+ name, base, uSize, (IMG_UINTPTR_T)imp_alloc, (IMG_UINTPTR_T)imp_free));
+
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof (*pArena),
+ (IMG_VOID **)&pArena, IMG_NULL,
+ "Resource Arena") != PVRSRV_OK)
+ {
+ goto arena_fail;
+ }
+
+ pArena->name = name;
+ pArena->pImportAlloc = (imp_alloc!=IMG_NULL) ? imp_alloc : &_RequestAllocFail;
+ pArena->pImportFree = imp_free;
+ pArena->pBackingStoreFree = backingstore_free;
+ pArena->pImportHandle = pImportHandle;
+ for (i=0; i<FREE_TABLE_LIMIT; i++)
+ pArena->aHeadFree[i] = IMG_NULL;
+ pArena->pHeadSegment = IMG_NULL;
+ pArena->pTailSegment = IMG_NULL;
+ pArena->uQuantum = uQuantum;
+
+#ifdef RA_STATS
+ pArena->sStatistics.uSpanCount = 0;
+ pArena->sStatistics.uLiveSegmentCount = 0;
+ pArena->sStatistics.uFreeSegmentCount = 0;
+ pArena->sStatistics.uFreeResourceCount = 0;
+ pArena->sStatistics.uTotalResourceCount = 0;
+ pArena->sStatistics.uCumulativeAllocs = 0;
+ pArena->sStatistics.uCumulativeFrees = 0;
+ pArena->sStatistics.uImportCount = 0;
+ pArena->sStatistics.uExportCount = 0;
+#endif
+
+#if defined(CONFIG_PROC_FS) && defined(DEBUG)
+ if(strcmp(pArena->name,"") != 0)
+ {
+ IMG_INT ret;
+ IMG_CHAR szProcInfoName[PROC_NAME_SIZE];
+ IMG_CHAR szProcSegsName[PROC_NAME_SIZE];
+ struct proc_dir_entry* (*pfnCreateProcEntrySeq)(const IMG_CHAR *,
+ IMG_VOID*,
+ pvr_next_proc_seq_t,
+ pvr_show_proc_seq_t,
+ pvr_off2element_proc_seq_t,
+ pvr_startstop_proc_seq_t,
+ write_proc_t);
+
+ pArena->bInitProcEntry = !PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL);
+
+
+ pfnCreateProcEntrySeq = pArena->bInitProcEntry ? CreateProcEntrySeq : CreatePerProcessProcEntrySeq;
+
+ ret = snprintf(szProcInfoName, sizeof(szProcInfoName), "ra_info_%s", pArena->name);
+ if (ret > 0 && ret < sizeof(szProcInfoName))
+ {
+ pArena->pProcInfo = pfnCreateProcEntrySeq(ReplaceSpaces(szProcInfoName), pArena, NULL,
+ RA_ProcSeqShowInfo, RA_ProcSeqOff2ElementInfo, NULL, NULL);
+ }
+ else
+ {
+ pArena->pProcInfo = 0;
+ PVR_DPF((PVR_DBG_ERROR, "RA_Create: couldn't create ra_info proc entry for arena %s", pArena->name));
+ }
+
+ ret = snprintf(szProcSegsName, sizeof(szProcSegsName), "ra_segs_%s", pArena->name);
+ if (ret > 0 && ret < sizeof(szProcInfoName))
+ {
+ pArena->pProcSegs = pfnCreateProcEntrySeq(ReplaceSpaces(szProcSegsName), pArena, NULL,
+ RA_ProcSeqShowRegs, RA_ProcSeqOff2ElementRegs, NULL, NULL);
+ }
+ else
+ {
+ pArena->pProcSegs = 0;
+ PVR_DPF((PVR_DBG_ERROR, "RA_Create: couldn't create ra_segs proc entry for arena %s", pArena->name));
+ }
+ }
+#endif
+
+ pArena->pSegmentHash = HASH_Create (MINIMUM_HASH_SIZE);
+ if (pArena->pSegmentHash==IMG_NULL)
+ {
+ goto hash_fail;
+ }
+ if (uSize>0)
+ {
+ uSize = (uSize + uQuantum - 1) / uQuantum * uQuantum;
+ pBT = _InsertResource (pArena, base, uSize);
+ if (pBT == IMG_NULL)
+ {
+ goto insert_fail;
+ }
+ pBT->psMapping = psMapping;
+
+ }
+ return pArena;
+
+insert_fail:
+ HASH_Delete (pArena->pSegmentHash);
+hash_fail:
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RA_ARENA), pArena, IMG_NULL);
+
+arena_fail:
+ return IMG_NULL;
+}
+
+IMG_VOID
+RA_Delete (RA_ARENA *pArena)
+{
+ IMG_UINT32 uIndex;
+
+ PVR_ASSERT(pArena != IMG_NULL);
+
+ if (pArena == IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"RA_Delete: invalid parameter - pArena"));
+ return;
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "RA_Delete: name='%s'", pArena->name));
+
+ for (uIndex=0; uIndex<FREE_TABLE_LIMIT; uIndex++)
+ pArena->aHeadFree[uIndex] = IMG_NULL;
+
+ while (pArena->pHeadSegment != IMG_NULL)
+ {
+ BT *pBT = pArena->pHeadSegment;
+
+ if (pBT->type != btt_free)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"Leaking base = 0x%x type=%d size=0x%x", pBT->base, pBT->type, pBT->uSize));
+ RA_Free(pArena, pBT->base, IMG_FALSE);
+ }
+ else
+ {
+ _SegmentListRemove (pArena, pBT);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pBT, IMG_NULL);
+
+#ifdef RA_STATS
+ pArena->sStatistics.uSpanCount--;
+#endif
+ }
+ }
+
+#if defined(CONFIG_PROC_FS) && defined(DEBUG)
+ {
+ IMG_VOID (*pfnRemoveProcEntrySeq)(struct proc_dir_entry*);
+
+ pfnRemoveProcEntrySeq = pArena->bInitProcEntry ? RemoveProcEntrySeq : RemovePerProcessProcEntrySeq;
+
+ if (pArena->pProcInfo != 0)
+ {
+ pfnRemoveProcEntrySeq( pArena->pProcInfo );
+ }
+
+ if (pArena->pProcSegs != 0)
+ {
+ pfnRemoveProcEntrySeq( pArena->pProcSegs );
+ }
+ }
+#endif
+ HASH_Delete (pArena->pSegmentHash);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RA_ARENA), pArena, IMG_NULL);
+
+}
+
+IMG_BOOL
+RA_TestDelete (RA_ARENA *pArena)
+{
+ PVR_ASSERT(pArena != IMG_NULL);
+
+ if (pArena != IMG_NULL)
+ {
+ while (pArena->pHeadSegment != IMG_NULL)
+ {
+ BT *pBT = pArena->pHeadSegment;
+ if (pBT->type != btt_free)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"RA_TestDelete: detected resource leak!"));
+ PVR_DPF ((PVR_DBG_ERROR,"RA_TestDelete: base = 0x%x size=0x%x", pBT->base, pBT->uSize));
+ return IMG_FALSE;
+ }
+ }
+ }
+
+ return IMG_TRUE;
+}
+
+IMG_BOOL
+RA_Add (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize)
+{
+ PVR_ASSERT (pArena != IMG_NULL);
+
+ if (pArena == IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"RA_Add: invalid parameter - pArena"));
+ return IMG_FALSE;
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "RA_Add: name='%s', base=0x%x, size=0x%x", pArena->name, base, uSize));
+
+ uSize = (uSize + pArena->uQuantum - 1) / pArena->uQuantum * pArena->uQuantum;
+ return ((IMG_BOOL)(_InsertResource (pArena, base, uSize) != IMG_NULL));
+}
+
+IMG_BOOL
+RA_Alloc (RA_ARENA *pArena,
+ IMG_SIZE_T uRequestSize,
+ IMG_SIZE_T *pActualSize,
+ BM_MAPPING **ppsMapping,
+ IMG_UINT32 uFlags,
+ IMG_UINT32 uAlignment,
+ IMG_UINT32 uAlignmentOffset,
+ IMG_UINTPTR_T *base)
+{
+ IMG_BOOL bResult;
+ IMG_SIZE_T uSize = uRequestSize;
+
+ PVR_ASSERT (pArena!=IMG_NULL);
+
+ if (pArena == IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"RA_Alloc: invalid parameter - pArena"));
+ return IMG_FALSE;
+ }
+
+#if defined(VALIDATE_ARENA_TEST)
+ ValidateArena(pArena);
+#endif
+
+#ifdef USE_BM_FREESPACE_CHECK
+ CheckBMFreespace();
+#endif
+
+ if (pActualSize != IMG_NULL)
+ {
+ *pActualSize = uSize;
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "RA_Alloc: arena='%s', size=0x%x(0x%x), alignment=0x%x, offset=0x%x",
+ pArena->name, uSize, uRequestSize, uAlignment, uAlignmentOffset));
+
+
+
+ bResult = _AttemptAllocAligned (pArena, uSize, ppsMapping, uFlags,
+ uAlignment, uAlignmentOffset, base);
+ if (!bResult)
+ {
+ BM_MAPPING *psImportMapping;
+ IMG_UINTPTR_T import_base;
+ IMG_SIZE_T uImportSize = uSize;
+
+
+
+
+ if (uAlignment > pArena->uQuantum)
+ {
+ uImportSize += (uAlignment - 1);
+ }
+
+
+ uImportSize = ((uImportSize + pArena->uQuantum - 1)/pArena->uQuantum)*pArena->uQuantum;
+
+ bResult =
+ pArena->pImportAlloc (pArena->pImportHandle, uImportSize, &uImportSize,
+ &psImportMapping, uFlags, &import_base);
+ if (bResult)
+ {
+ BT *pBT;
+ pBT = _InsertResourceSpan (pArena, import_base, uImportSize);
+
+ if (pBT == IMG_NULL)
+ {
+
+ pArena->pImportFree(pArena->pImportHandle, import_base,
+ psImportMapping);
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "RA_Alloc: name='%s', size=0x%x failed!",
+ pArena->name, uSize));
+
+ return IMG_FALSE;
+ }
+ pBT->psMapping = psImportMapping;
+#ifdef RA_STATS
+ pArena->sStatistics.uFreeSegmentCount++;
+ pArena->sStatistics.uFreeResourceCount += uImportSize;
+ pArena->sStatistics.uImportCount++;
+ pArena->sStatistics.uSpanCount++;
+#endif
+ bResult = _AttemptAllocAligned(pArena, uSize, ppsMapping, uFlags,
+ uAlignment, uAlignmentOffset,
+ base);
+ if (!bResult)
+ {
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "RA_Alloc: name='%s' uAlignment failed!",
+ pArena->name));
+ }
+ }
+ }
+#ifdef RA_STATS
+ if (bResult)
+ pArena->sStatistics.uCumulativeAllocs++;
+#endif
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "RA_Alloc: name='%s', size=0x%x, *base=0x%x = %d",
+ pArena->name, uSize, *base, bResult));
+
+
+
+#if defined(VALIDATE_ARENA_TEST)
+ ValidateArena(pArena);
+#endif
+
+ return bResult;
+}
+
+
+#if defined(VALIDATE_ARENA_TEST)
+
+IMG_UINT32 ValidateArena(RA_ARENA *pArena)
+{
+ BT* pSegment;
+ RESOURCE_DESCRIPTOR eNextSpan;
+
+ pSegment = pArena->pHeadSegment;
+
+ if (pSegment == IMG_NULL)
+ {
+ return 0;
+ }
+
+ if (pSegment->eResourceType == IMPORTED_RESOURCE_TYPE)
+ {
+ PVR_ASSERT(pSegment->eResourceSpan == IMPORTED_RESOURCE_SPAN_START);
+
+ while (pSegment->pNextSegment)
+ {
+ eNextSpan = pSegment->pNextSegment->eResourceSpan;
+
+ switch (pSegment->eResourceSpan)
+ {
+ case IMPORTED_RESOURCE_SPAN_LIVE:
+
+ if (!((eNextSpan == IMPORTED_RESOURCE_SPAN_LIVE) ||
+ (eNextSpan == IMPORTED_RESOURCE_SPAN_FREE) ||
+ (eNextSpan == IMPORTED_RESOURCE_SPAN_END)))
+ {
+
+ PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
+ pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
+
+ PVR_DBG_BREAK;
+ }
+ break;
+
+ case IMPORTED_RESOURCE_SPAN_FREE:
+
+ if (!((eNextSpan == IMPORTED_RESOURCE_SPAN_LIVE) ||
+ (eNextSpan == IMPORTED_RESOURCE_SPAN_END)))
+ {
+
+ PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
+ pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
+
+ PVR_DBG_BREAK;
+ }
+ break;
+
+ case IMPORTED_RESOURCE_SPAN_END:
+
+ if ((eNextSpan == IMPORTED_RESOURCE_SPAN_LIVE) ||
+ (eNextSpan == IMPORTED_RESOURCE_SPAN_FREE) ||
+ (eNextSpan == IMPORTED_RESOURCE_SPAN_END))
+ {
+
+ PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
+ pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
+
+ PVR_DBG_BREAK;
+ }
+ break;
+
+
+ case IMPORTED_RESOURCE_SPAN_START:
+
+ if (!((eNextSpan == IMPORTED_RESOURCE_SPAN_LIVE) ||
+ (eNextSpan == IMPORTED_RESOURCE_SPAN_FREE)))
+ {
+
+ PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
+ pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
+
+ PVR_DBG_BREAK;
+ }
+ break;
+
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
+ pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
+
+ PVR_DBG_BREAK;
+ break;
+ }
+ pSegment = pSegment->pNextSegment;
+ }
+ }
+ else if (pSegment->eResourceType == NON_IMPORTED_RESOURCE_TYPE)
+ {
+ PVR_ASSERT((pSegment->eResourceSpan == RESOURCE_SPAN_FREE) || (pSegment->eResourceSpan == RESOURCE_SPAN_LIVE));
+
+ while (pSegment->pNextSegment)
+ {
+ eNextSpan = pSegment->pNextSegment->eResourceSpan;
+
+ switch (pSegment->eResourceSpan)
+ {
+ case RESOURCE_SPAN_LIVE:
+
+ if (!((eNextSpan == RESOURCE_SPAN_FREE) ||
+ (eNextSpan == RESOURCE_SPAN_LIVE)))
+ {
+
+ PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
+ pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
+
+ PVR_DBG_BREAK;
+ }
+ break;
+
+ case RESOURCE_SPAN_FREE:
+
+ if (!((eNextSpan == RESOURCE_SPAN_FREE) ||
+ (eNextSpan == RESOURCE_SPAN_LIVE)))
+ {
+
+ PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
+ pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
+
+ PVR_DBG_BREAK;
+ }
+ break;
+
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
+ pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
+
+ PVR_DBG_BREAK;
+ break;
+ }
+ pSegment = pSegment->pNextSegment;
+ }
+
+ }
+ else
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"ValidateArena ERROR: pSegment->eResourceType unrecognized"));
+
+ PVR_DBG_BREAK;
+ }
+
+ return 0;
+}
+
+#endif
+
+
+IMG_VOID
+RA_Free (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_BOOL bFreeBackingStore)
+{
+ BT *pBT;
+
+ PVR_ASSERT (pArena != IMG_NULL);
+
+ if (pArena == IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_ERROR,"RA_Free: invalid parameter - pArena"));
+ return;
+ }
+
+#ifdef USE_BM_FREESPACE_CHECK
+ CheckBMFreespace();
+#endif
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "RA_Free: name='%s', base=0x%x", pArena->name, base));
+
+ pBT = (BT *) HASH_Remove (pArena->pSegmentHash, base);
+ PVR_ASSERT (pBT != IMG_NULL);
+
+ if (pBT)
+ {
+ PVR_ASSERT (pBT->base == base);
+
+#ifdef RA_STATS
+ pArena->sStatistics.uCumulativeFrees++;
+#endif
+
+#ifdef USE_BM_FREESPACE_CHECK
+{
+ IMG_BYTE* p;
+ IMG_BYTE* endp;
+
+ p = (IMG_BYTE*)pBT->base + SysGetDevicePhysOffset();
+ endp = (IMG_BYTE*)((IMG_UINT32)(p + pBT->uSize));
+ while ((IMG_UINT32)p & 3)
+ {
+ *p++ = 0xAA;
+ }
+ while (p < (IMG_BYTE*)((IMG_UINT32)endp & 0xfffffffc))
+ {
+ *(IMG_UINT32*)p = 0xAAAAAAAA;
+ p += sizeof(IMG_UINT32);
+ }
+ while (p < endp)
+ {
+ *p++ = 0xAA;
+ }
+ PVR_DPF((PVR_DBG_MESSAGE,"BM_FREESPACE_CHECK: RA_Free Cleared %08X to %08X (size=0x%x)",(IMG_BYTE*)pBT->base + SysGetDevicePhysOffset(),endp-1,pBT->uSize));
+}
+#endif
+ _FreeBT (pArena, pBT, bFreeBackingStore);
+ }
+}
+
+
+IMG_BOOL RA_GetNextLiveSegment(IMG_HANDLE hArena, RA_SEGMENT_DETAILS *psSegDetails)
+{
+ BT *pBT;
+
+ if (psSegDetails->hSegment)
+ {
+ pBT = (BT *)psSegDetails->hSegment;
+ }
+ else
+ {
+ RA_ARENA *pArena = (RA_ARENA *)hArena;
+
+ pBT = pArena->pHeadSegment;
+ }
+
+ while (pBT != IMG_NULL)
+ {
+ if (pBT->type == btt_live)
+ {
+ psSegDetails->uiSize = pBT->uSize;
+ psSegDetails->sCpuPhyAddr.uiAddr = pBT->base;
+ psSegDetails->hSegment = (IMG_HANDLE)pBT->pNextSegment;
+
+ return IMG_TRUE;
+ }
+
+ pBT = pBT->pNextSegment;
+ }
+
+ psSegDetails->uiSize = 0;
+ psSegDetails->sCpuPhyAddr.uiAddr = 0;
+ psSegDetails->hSegment = (IMG_HANDLE)IMG_UNDEF;
+
+ return IMG_FALSE;
+}
+
+
+#ifdef USE_BM_FREESPACE_CHECK
+RA_ARENA* pJFSavedArena = IMG_NULL;
+
+IMG_VOID CheckBMFreespace(IMG_VOID)
+{
+ BT *pBT;
+ IMG_BYTE* p;
+ IMG_BYTE* endp;
+
+ if (pJFSavedArena != IMG_NULL)
+ {
+ for (pBT=pJFSavedArena->pHeadSegment; pBT!=IMG_NULL; pBT=pBT->pNextSegment)
+ {
+ if (pBT->type == btt_free)
+ {
+ p = (IMG_BYTE*)pBT->base + SysGetDevicePhysOffset();
+ endp = (IMG_BYTE*)((IMG_UINT32)(p + pBT->uSize) & 0xfffffffc);
+
+ while ((IMG_UINT32)p & 3)
+ {
+ if (*p++ != 0xAA)
+ {
+ fprintf(stderr,"BM_FREESPACE_CHECK: Blank space at %08X has changed to 0x%x\n",p,*(IMG_UINT32*)p);
+ for (;;);
+ break;
+ }
+ }
+ while (p < endp)
+ {
+ if (*(IMG_UINT32*)p != 0xAAAAAAAA)
+ {
+ fprintf(stderr,"BM_FREESPACE_CHECK: Blank space at %08X has changed to 0x%x\n",p,*(IMG_UINT32*)p);
+ for (;;);
+ break;
+ }
+ p += 4;
+ }
+ }
+ }
+ }
+}
+#endif
+
+
+#if (defined(CONFIG_PROC_FS) && defined(DEBUG)) || defined (RA_STATS)
+static IMG_CHAR *
+_BTType (IMG_INT eType)
+{
+ switch (eType)
+ {
+ case btt_span: return "span";
+ case btt_free: return "free";
+ case btt_live: return "live";
+ }
+ return "junk";
+}
+#endif
+
+#if defined(ENABLE_RA_DUMP)
+IMG_VOID
+RA_Dump (RA_ARENA *pArena)
+{
+ BT *pBT;
+ PVR_ASSERT (pArena != IMG_NULL);
+ PVR_DPF ((PVR_DBG_MESSAGE,"Arena '%s':", pArena->name));
+ PVR_DPF ((PVR_DBG_MESSAGE," alloc=%08X free=%08X handle=%08X quantum=%d",
+ pArena->pImportAlloc, pArena->pImportFree, pArena->pImportHandle,
+ pArena->uQuantum));
+ PVR_DPF ((PVR_DBG_MESSAGE," segment Chain:"));
+ if (pArena->pHeadSegment != IMG_NULL &&
+ pArena->pHeadSegment->pPrevSegment != IMG_NULL)
+ PVR_DPF ((PVR_DBG_MESSAGE," error: head boundary tag has invalid pPrevSegment"));
+ if (pArena->pTailSegment != IMG_NULL &&
+ pArena->pTailSegment->pNextSegment != IMG_NULL)
+ PVR_DPF ((PVR_DBG_MESSAGE," error: tail boundary tag has invalid pNextSegment"));
+
+ for (pBT=pArena->pHeadSegment; pBT!=IMG_NULL; pBT=pBT->pNextSegment)
+ {
+ PVR_DPF ((PVR_DBG_MESSAGE,"\tbase=0x%x size=0x%x type=%s ref=%08X",
+ (IMG_UINT32) pBT->base, pBT->uSize, _BTType (pBT->type),
+ pBT->pRef));
+ }
+
+#ifdef HASH_TRACE
+ HASH_Dump (pArena->pSegmentHash);
+#endif
+}
+#endif
+
+
+#if defined(CONFIG_PROC_FS) && defined(DEBUG)
+
+
+static void RA_ProcSeqShowInfo(struct seq_file *sfile, void* el)
+{
+ PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)sfile->private;
+ RA_ARENA *pArena = (RA_ARENA *)handlers->data;
+ IMG_INT off = (IMG_INT)el;
+
+ switch (off)
+ {
+ case 1:
+ seq_printf(sfile, "quantum\t\t\t%u\n", pArena->uQuantum);
+ break;
+ case 2:
+ seq_printf(sfile, "import_handle\t\t%08X\n", (IMG_UINT)pArena->pImportHandle);
+ break;
+#ifdef RA_STATS
+ case 3:
+ seq_printf(sfile,"span count\t\t%u\n", pArena->sStatistics.uSpanCount);
+ break;
+ case 4:
+ seq_printf(sfile, "live segment count\t%u\n", pArena->sStatistics.uLiveSegmentCount);
+ break;
+ case 5:
+ seq_printf(sfile, "free segment count\t%u\n", pArena->sStatistics.uFreeSegmentCount);
+ break;
+ case 6:
+ seq_printf(sfile, "free resource count\t%u (0x%x)\n",
+ pArena->sStatistics.uFreeResourceCount,
+ (IMG_UINT)pArena->sStatistics.uFreeResourceCount);
+ break;
+ case 7:
+ seq_printf(sfile, "total allocs\t\t%u\n", pArena->sStatistics.uCumulativeAllocs);
+ break;
+ case 8:
+ seq_printf(sfile, "total frees\t\t%u\n", pArena->sStatistics.uCumulativeFrees);
+ break;
+ case 9:
+ seq_printf(sfile, "import count\t\t%u\n", pArena->sStatistics.uImportCount);
+ break;
+ case 10:
+ seq_printf(sfile, "export count\t\t%u\n", pArena->sStatistics.uExportCount);
+ break;
+#endif
+ }
+
+}
+
+static void* RA_ProcSeqOff2ElementInfo(struct seq_file * sfile, loff_t off)
+{
+#ifdef RA_STATS
+ if(off <= 9)
+#else
+ if(off <= 1)
+#endif
+ return (void*)(IMG_INT)(off+1);
+ return 0;
+}
+
+static void RA_ProcSeqShowRegs(struct seq_file *sfile, void* el)
+{
+ PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)sfile->private;
+ RA_ARENA *pArena = (RA_ARENA *)handlers->data;
+ BT *pBT = (BT*)el;
+
+ if (el == PVR_PROC_SEQ_START_TOKEN)
+ {
+ seq_printf(sfile, "Arena \"%s\"\nBase Size Type Ref\n", pArena->name);
+ return;
+ }
+
+ if (pBT)
+ {
+ seq_printf(sfile, "%08x %8x %4s %08x\n",
+ (IMG_UINT)pBT->base, (IMG_UINT)pBT->uSize, _BTType (pBT->type),
+ (IMG_UINT)pBT->psMapping);
+ }
+}
+
+static void* RA_ProcSeqOff2ElementRegs(struct seq_file * sfile, loff_t off)
+{
+ PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)sfile->private;
+ RA_ARENA *pArena = (RA_ARENA *)handlers->data;
+ BT *pBT = 0;
+
+ if(off == 0)
+ return PVR_PROC_SEQ_START_TOKEN;
+
+ for (pBT=pArena->pHeadSegment; --off && pBT; pBT=pBT->pNextSegment);
+
+ return (void*)pBT;
+}
+
+#endif
+
+
+#ifdef RA_STATS
+PVRSRV_ERROR RA_GetStats(RA_ARENA *pArena,
+ IMG_CHAR **ppszStr,
+ IMG_UINT32 *pui32StrLen)
+{
+ IMG_CHAR *pszStr = *ppszStr;
+ IMG_UINT32 ui32StrLen = *pui32StrLen;
+ IMG_INT32 i32Count;
+ BT *pBT;
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "\nArena '%s':\n", pArena->name);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, " allocCB=%p freeCB=%p handle=%p quantum=%d\n",
+ pArena->pImportAlloc,
+ pArena->pImportFree,
+ pArena->pImportHandle,
+ pArena->uQuantum);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "span count\t\t%u\n", pArena->sStatistics.uSpanCount);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "live segment count\t%u\n", pArena->sStatistics.uLiveSegmentCount);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "free segment count\t%u\n", pArena->sStatistics.uFreeSegmentCount);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "free resource count\t%u (0x%x)\n",
+ pArena->sStatistics.uFreeResourceCount,
+ (IMG_UINT)pArena->sStatistics.uFreeResourceCount);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "total allocs\t\t%u\n", pArena->sStatistics.uCumulativeAllocs);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "total frees\t\t%u\n", pArena->sStatistics.uCumulativeFrees);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "import count\t\t%u\n", pArena->sStatistics.uImportCount);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "export count\t\t%u\n", pArena->sStatistics.uExportCount);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, " segment Chain:\n");
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ if (pArena->pHeadSegment != IMG_NULL &&
+ pArena->pHeadSegment->pPrevSegment != IMG_NULL)
+ {
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, " error: head boundary tag has invalid pPrevSegment\n");
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+ }
+
+ if (pArena->pTailSegment != IMG_NULL &&
+ pArena->pTailSegment->pNextSegment != IMG_NULL)
+ {
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, " error: tail boundary tag has invalid pNextSegment\n");
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+ }
+
+ for (pBT=pArena->pHeadSegment; pBT!=IMG_NULL; pBT=pBT->pNextSegment)
+ {
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "\tbase=0x%x size=0x%x type=%s ref=%p\n",
+ (IMG_UINT32) pBT->base,
+ pBT->uSize,
+ _BTType(pBT->type),
+ pBT->psMapping);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+ }
+
+ *ppszStr = pszStr;
+ *pui32StrLen = ui32StrLen;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR RA_GetStatsFreeMem(RA_ARENA *pArena,
+ IMG_CHAR **ppszStr,
+ IMG_UINT32 *pui32StrLen)
+{
+ IMG_CHAR *pszStr = *ppszStr;
+ IMG_UINT32 ui32StrLen = *pui32StrLen;
+ IMG_INT32 i32Count;
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "Bytes free: Arena %-30s: %u (0x%x)\n", pArena->name,
+ pArena->sStatistics.uFreeResourceCount,
+ pArena->sStatistics.uFreeResourceCount);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+ *ppszStr = pszStr;
+ *pui32StrLen = ui32StrLen;
+
+ return PVRSRV_OK;
+}
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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 "services_headers.h"
+#include "resman.h"
+
+#ifdef __linux__
+#include <linux/version.h>
+#include <linux/sched.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9)
+#include <linux/hardirq.h>
+#else
+#include <asm/hardirq.h>
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
+#include <linux/semaphore.h>
+#else
+#include <asm/semaphore.h>
+#endif
+
+static DEFINE_SEMAPHORE(lock);
+
+#define ACQUIRE_SYNC_OBJ do { \
+ if (in_interrupt()) { \
+ printk ("ISR cannot take RESMAN mutex\n"); \
+ BUG(); \
+ } \
+ else down (&lock); \
+} while (0)
+#define RELEASE_SYNC_OBJ up (&lock)
+
+#else
+
+#define ACQUIRE_SYNC_OBJ
+#define RELEASE_SYNC_OBJ
+
+#endif
+
+#define RESMAN_SIGNATURE 0x12345678
+
+typedef struct _RESMAN_ITEM_
+{
+#ifdef DEBUG
+ IMG_UINT32 ui32Signature;
+#endif
+ struct _RESMAN_ITEM_ **ppsThis;
+ struct _RESMAN_ITEM_ *psNext;
+
+ IMG_UINT32 ui32Flags;
+ IMG_UINT32 ui32ResType;
+
+ IMG_PVOID pvParam;
+ IMG_UINT32 ui32Param;
+
+ RESMAN_FREE_FN pfnFreeResource;
+} RESMAN_ITEM;
+
+
+typedef struct _RESMAN_CONTEXT_
+{
+#ifdef DEBUG
+ IMG_UINT32 ui32Signature;
+#endif
+ struct _RESMAN_CONTEXT_ **ppsThis;
+ struct _RESMAN_CONTEXT_ *psNext;
+
+ PVRSRV_PER_PROCESS_DATA *psPerProc;
+
+ RESMAN_ITEM *psResItemList;
+
+} RESMAN_CONTEXT;
+
+
+typedef struct
+{
+ RESMAN_CONTEXT *psContextList;
+
+} RESMAN_LIST, *PRESMAN_LIST;
+
+
+PRESMAN_LIST gpsResList = IMG_NULL;
+
+#include "lists.h"
+
+static IMPLEMENT_LIST_ANY_VA(RESMAN_ITEM)
+static IMPLEMENT_LIST_ANY_VA_2(RESMAN_ITEM, IMG_BOOL, IMG_FALSE)
+static IMPLEMENT_LIST_INSERT(RESMAN_ITEM)
+static IMPLEMENT_LIST_REMOVE(RESMAN_ITEM)
+static IMPLEMENT_LIST_REVERSE(RESMAN_ITEM)
+
+static IMPLEMENT_LIST_REMOVE(RESMAN_CONTEXT)
+static IMPLEMENT_LIST_INSERT(RESMAN_CONTEXT)
+
+
+#define PRINT_RESLIST(x, y, z)
+
+static PVRSRV_ERROR FreeResourceByPtr(RESMAN_ITEM *psItem, IMG_BOOL bExecuteCallback);
+
+static PVRSRV_ERROR FreeResourceByCriteria(PRESMAN_CONTEXT psContext,
+ IMG_UINT32 ui32SearchCriteria,
+ IMG_UINT32 ui32ResType,
+ IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param,
+ IMG_BOOL bExecuteCallback);
+
+
+#ifdef DEBUG
+ static IMG_VOID ValidateResList(PRESMAN_LIST psResList);
+ #define VALIDATERESLIST() ValidateResList(gpsResList)
+#else
+ #define VALIDATERESLIST()
+#endif
+
+
+
+
+
+
+PVRSRV_ERROR ResManInit(IMG_VOID)
+{
+ if (gpsResList == IMG_NULL)
+ {
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(*gpsResList),
+ (IMG_VOID **)&gpsResList, IMG_NULL,
+ "Resource Manager List") != PVRSRV_OK)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+
+ gpsResList->psContextList = IMG_NULL;
+
+
+ VALIDATERESLIST();
+ }
+
+ return PVRSRV_OK;
+}
+
+
+IMG_VOID ResManDeInit(IMG_VOID)
+{
+ if (gpsResList != IMG_NULL)
+ {
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*gpsResList), gpsResList, IMG_NULL);
+ gpsResList = IMG_NULL;
+ }
+}
+
+
+PVRSRV_ERROR PVRSRVResManConnect(IMG_HANDLE hPerProc,
+ PRESMAN_CONTEXT *phResManContext)
+{
+ PVRSRV_ERROR eError;
+ PRESMAN_CONTEXT psResManContext;
+
+
+ ACQUIRE_SYNC_OBJ;
+
+
+ VALIDATERESLIST();
+
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psResManContext),
+ (IMG_VOID **)&psResManContext, IMG_NULL,
+ "Resource Manager Context");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVResManConnect: ERROR allocating new RESMAN context struct"));
+
+
+ VALIDATERESLIST();
+
+
+ RELEASE_SYNC_OBJ;
+
+ return eError;
+ }
+
+#ifdef DEBUG
+ psResManContext->ui32Signature = RESMAN_SIGNATURE;
+#endif
+ psResManContext->psResItemList = IMG_NULL;
+ psResManContext->psPerProc = hPerProc;
+
+
+ List_RESMAN_CONTEXT_Insert(&gpsResList->psContextList, psResManContext);
+
+
+ VALIDATERESLIST();
+
+
+ RELEASE_SYNC_OBJ;
+
+ *phResManContext = psResManContext;
+
+ return PVRSRV_OK;
+}
+
+
+IMG_VOID PVRSRVResManDisconnect(PRESMAN_CONTEXT psResManContext,
+ IMG_BOOL bKernelContext)
+{
+
+ ACQUIRE_SYNC_OBJ;
+
+
+ VALIDATERESLIST();
+
+
+ PRINT_RESLIST(gpsResList, psResManContext, IMG_TRUE);
+
+
+
+ if (!bKernelContext)
+ {
+
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_OS_USERMODE_MAPPING, 0, 0, IMG_TRUE);
+
+
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_EVENT_OBJECT, 0, 0, IMG_TRUE);
+
+
+
+ List_RESMAN_ITEM_Reverse(&psResManContext->psResItemList);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_MODIFY_SYNC_OPS, 0, 0, IMG_TRUE);
+ List_RESMAN_ITEM_Reverse(&psResManContext->psResItemList);
+
+
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_HW_RENDER_CONTEXT, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_HW_TRANSFER_CONTEXT, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_HW_2D_CONTEXT, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_TRANSFER_CONTEXT, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_SHARED_PB_DESC_CREATE_LOCK, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_SHARED_PB_DESC, 0, 0, IMG_TRUE);
+
+
+
+
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DISPLAYCLASS_SWAPCHAIN_REF, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DISPLAYCLASS_DEVICE, 0, 0, IMG_TRUE);
+
+
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_BUFFERCLASS_DEVICE, 0, 0, IMG_TRUE);
+
+
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_SYNC_INFO, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICECLASSMEM_MAPPING, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_WRAP, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_MAPPING, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_KERNEL_DEVICEMEM_ALLOCATION, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_ALLOCATION, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_CONTEXT, 0, 0, IMG_TRUE);
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_SHARED_MEM_INFO, 0, 0, IMG_TRUE);
+ }
+
+
+ PVR_ASSERT(psResManContext->psResItemList == IMG_NULL);
+
+
+ List_RESMAN_CONTEXT_Remove(psResManContext);
+
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RESMAN_CONTEXT), psResManContext, IMG_NULL);
+
+
+
+
+ VALIDATERESLIST();
+
+
+ PRINT_RESLIST(gpsResList, psResManContext, IMG_FALSE);
+
+
+ RELEASE_SYNC_OBJ;
+}
+
+
+PRESMAN_ITEM ResManRegisterRes(PRESMAN_CONTEXT psResManContext,
+ IMG_UINT32 ui32ResType,
+ IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param,
+ RESMAN_FREE_FN pfnFreeResource)
+{
+ PRESMAN_ITEM psNewResItem;
+
+ PVR_ASSERT(psResManContext != IMG_NULL);
+ PVR_ASSERT(ui32ResType != 0);
+
+ if (psResManContext == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ResManRegisterRes: invalid parameter - psResManContext"));
+ return (PRESMAN_ITEM) IMG_NULL;
+ }
+
+
+ ACQUIRE_SYNC_OBJ;
+
+
+ VALIDATERESLIST();
+
+ PVR_DPF((PVR_DBG_MESSAGE, "ResManRegisterRes: register resource "
+ "Context 0x%x, ResType 0x%x, pvParam 0x%x, ui32Param 0x%x, "
+ "FreeFunc %08X",
+ (IMG_UINTPTR_T)psResManContext,
+ ui32ResType,
+ (IMG_UINTPTR_T)pvParam,
+ ui32Param,
+ (IMG_UINTPTR_T)pfnFreeResource));
+
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(RESMAN_ITEM), (IMG_VOID **)&psNewResItem,
+ IMG_NULL,
+ "Resource Manager Item") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ResManRegisterRes: "
+ "ERROR allocating new resource item"));
+
+
+ RELEASE_SYNC_OBJ;
+
+ return((PRESMAN_ITEM)IMG_NULL);
+ }
+
+
+#ifdef DEBUG
+ psNewResItem->ui32Signature = RESMAN_SIGNATURE;
+#endif
+ psNewResItem->ui32ResType = ui32ResType;
+ psNewResItem->pvParam = pvParam;
+ psNewResItem->ui32Param = ui32Param;
+ psNewResItem->pfnFreeResource = pfnFreeResource;
+ psNewResItem->ui32Flags = 0;
+
+
+ List_RESMAN_ITEM_Insert(&psResManContext->psResItemList, psNewResItem);
+
+
+ VALIDATERESLIST();
+
+
+ RELEASE_SYNC_OBJ;
+
+ return(psNewResItem);
+}
+
+PVRSRV_ERROR ResManFreeResByPtr(RESMAN_ITEM *psResItem)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(psResItem != IMG_NULL);
+
+ if (psResItem == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "ResManFreeResByPtr: NULL ptr - nothing to do"));
+ return PVRSRV_OK;
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE, "ResManFreeResByPtr: freeing resource at %08X",
+ (IMG_UINTPTR_T)psResItem));
+
+
+ ACQUIRE_SYNC_OBJ;
+
+
+ VALIDATERESLIST();
+
+
+ eError = FreeResourceByPtr(psResItem, IMG_TRUE);
+
+
+ VALIDATERESLIST();
+
+
+ RELEASE_SYNC_OBJ;
+
+ return(eError);
+}
+
+
+PVRSRV_ERROR ResManFreeResByCriteria(PRESMAN_CONTEXT psResManContext,
+ IMG_UINT32 ui32SearchCriteria,
+ IMG_UINT32 ui32ResType,
+ IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(psResManContext != IMG_NULL);
+
+
+ ACQUIRE_SYNC_OBJ;
+
+
+ VALIDATERESLIST();
+
+ PVR_DPF((PVR_DBG_MESSAGE, "ResManFreeResByCriteria: "
+ "Context 0x%x, Criteria 0x%x, Type 0x%x, Addr 0x%x, Param 0x%x",
+ (IMG_UINTPTR_T)psResManContext, ui32SearchCriteria, ui32ResType,
+ (IMG_UINTPTR_T)pvParam, ui32Param));
+
+
+ eError = FreeResourceByCriteria(psResManContext, ui32SearchCriteria,
+ ui32ResType, pvParam, ui32Param,
+ IMG_TRUE);
+
+
+ VALIDATERESLIST();
+
+
+ RELEASE_SYNC_OBJ;
+
+ return eError;
+}
+
+
+PVRSRV_ERROR ResManDissociateRes(RESMAN_ITEM *psResItem,
+ PRESMAN_CONTEXT psNewResManContext)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ PVR_ASSERT(psResItem != IMG_NULL);
+
+ if (psResItem == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ResManDissociateRes: invalid parameter - psResItem"));
+ PVR_DBG_BREAK;
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+#ifdef DEBUG
+ PVR_ASSERT(psResItem->ui32Signature == RESMAN_SIGNATURE);
+#endif
+
+ if (psNewResManContext != IMG_NULL)
+ {
+
+ List_RESMAN_ITEM_Remove(psResItem);
+
+
+ List_RESMAN_ITEM_Insert(&psNewResManContext->psResItemList, psResItem);
+
+ }
+ else
+ {
+ eError = FreeResourceByPtr(psResItem, IMG_FALSE);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ResManDissociateRes: failed to free resource by pointer"));
+ return eError;
+ }
+ }
+
+ return eError;
+}
+
+static IMG_BOOL ResManFindResourceByPtr_AnyVaCb(RESMAN_ITEM *psCurItem, va_list va)
+{
+ RESMAN_ITEM *psItem;
+
+ psItem = va_arg(va, RESMAN_ITEM*);
+
+ return (IMG_BOOL)(psCurItem == psItem);
+}
+
+
+IMG_INTERNAL PVRSRV_ERROR ResManFindResourceByPtr(PRESMAN_CONTEXT psResManContext,
+ RESMAN_ITEM *psItem)
+{
+ PVRSRV_ERROR eResult;
+
+ PVR_ASSERT(psResManContext != IMG_NULL);
+ PVR_ASSERT(psItem != IMG_NULL);
+
+ if ((psItem == IMG_NULL) || (psResManContext == IMG_NULL))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "ResManFindResourceByPtr: invalid parameter"));
+ PVR_DBG_BREAK;
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+#ifdef DEBUG
+ PVR_ASSERT(psItem->ui32Signature == RESMAN_SIGNATURE);
+#endif
+
+
+ ACQUIRE_SYNC_OBJ;
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "FindResourceByPtr: psItem=%08X, psItem->psNext=%08X",
+ (IMG_UINTPTR_T)psItem, (IMG_UINTPTR_T)psItem->psNext));
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "FindResourceByPtr: Resource Ctx 0x%x, Type 0x%x, Addr 0x%x, "
+ "Param 0x%x, FnCall %08X, Flags 0x%x",
+ (IMG_UINTPTR_T)psResManContext,
+ psItem->ui32ResType,
+ (IMG_UINTPTR_T)psItem->pvParam,
+ psItem->ui32Param,
+ (IMG_UINTPTR_T)psItem->pfnFreeResource,
+ psItem->ui32Flags));
+
+
+ if(List_RESMAN_ITEM_IMG_BOOL_Any_va(psResManContext->psResItemList,
+ &ResManFindResourceByPtr_AnyVaCb,
+ psItem))
+ {
+ eResult = PVRSRV_OK;
+ }
+ else
+ {
+ eResult = PVRSRV_ERROR_NOT_OWNER;
+ }
+
+
+ RELEASE_SYNC_OBJ;
+
+ return eResult;
+}
+
+static PVRSRV_ERROR FreeResourceByPtr(RESMAN_ITEM *psItem,
+ IMG_BOOL bExecuteCallback)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(psItem != IMG_NULL);
+
+ if (psItem == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeResourceByPtr: invalid parameter"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+#ifdef DEBUG
+ PVR_ASSERT(psItem->ui32Signature == RESMAN_SIGNATURE);
+#endif
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "FreeResourceByPtr: psItem=%08X, psItem->psNext=%08X",
+ (IMG_UINTPTR_T)psItem, (IMG_UINTPTR_T)psItem->psNext));
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "FreeResourceByPtr: Type 0x%x, Addr 0x%x, "
+ "Param 0x%x, FnCall %08X, Flags 0x%x",
+ psItem->ui32ResType,
+ (IMG_UINTPTR_T)psItem->pvParam, psItem->ui32Param,
+ (IMG_UINTPTR_T)psItem->pfnFreeResource, psItem->ui32Flags));
+
+
+ List_RESMAN_ITEM_Remove(psItem);
+
+
+
+ RELEASE_SYNC_OBJ;
+
+
+ if (bExecuteCallback)
+ {
+ eError = psItem->pfnFreeResource(psItem->pvParam, psItem->ui32Param);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeResourceByPtr: ERROR calling FreeResource function"));
+ }
+ }
+
+
+ ACQUIRE_SYNC_OBJ;
+
+
+ eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RESMAN_ITEM), psItem, IMG_NULL);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeResourceByPtr: ERROR freeing resource list item memory"));
+ }
+
+ return(eError);
+}
+
+static IMG_VOID* FreeResourceByCriteria_AnyVaCb(RESMAN_ITEM *psCurItem, va_list va)
+{
+ IMG_UINT32 ui32SearchCriteria;
+ IMG_UINT32 ui32ResType;
+ IMG_PVOID pvParam;
+ IMG_UINT32 ui32Param;
+
+ ui32SearchCriteria = va_arg(va, IMG_UINT32);
+ ui32ResType = va_arg(va, IMG_UINT32);
+ pvParam = va_arg(va, IMG_PVOID);
+ ui32Param = va_arg(va, IMG_UINT32);
+
+
+ if(
+
+ (((ui32SearchCriteria & RESMAN_CRITERIA_RESTYPE) == 0UL) ||
+ (psCurItem->ui32ResType == ui32ResType))
+ &&
+
+ (((ui32SearchCriteria & RESMAN_CRITERIA_PVOID_PARAM) == 0UL) ||
+ (psCurItem->pvParam == pvParam))
+ &&
+
+ (((ui32SearchCriteria & RESMAN_CRITERIA_UI32_PARAM) == 0UL) ||
+ (psCurItem->ui32Param == ui32Param))
+ )
+ {
+ return psCurItem;
+ }
+ else
+ {
+ return IMG_NULL;
+ }
+}
+
+static PVRSRV_ERROR FreeResourceByCriteria(PRESMAN_CONTEXT psResManContext,
+ IMG_UINT32 ui32SearchCriteria,
+ IMG_UINT32 ui32ResType,
+ IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param,
+ IMG_BOOL bExecuteCallback)
+{
+ PRESMAN_ITEM psCurItem;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+
+
+ while((psCurItem = (PRESMAN_ITEM)
+ List_RESMAN_ITEM_Any_va(psResManContext->psResItemList,
+ &FreeResourceByCriteria_AnyVaCb,
+ ui32SearchCriteria,
+ ui32ResType,
+ pvParam,
+ ui32Param)) != IMG_NULL
+ && eError == PVRSRV_OK)
+ {
+ eError = FreeResourceByPtr(psCurItem, bExecuteCallback);
+ }
+
+ return eError;
+}
+
+
+#ifdef DEBUG
+static IMG_VOID ValidateResList(PRESMAN_LIST psResList)
+{
+ PRESMAN_ITEM psCurItem, *ppsThisItem;
+ PRESMAN_CONTEXT psCurContext, *ppsThisContext;
+
+
+ if (psResList == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "ValidateResList: resman not initialised yet"));
+ return;
+ }
+
+ psCurContext = psResList->psContextList;
+ ppsThisContext = &psResList->psContextList;
+
+
+ while(psCurContext != IMG_NULL)
+ {
+
+ PVR_ASSERT(psCurContext->ui32Signature == RESMAN_SIGNATURE);
+ if (psCurContext->ppsThis != ppsThisContext)
+ {
+ PVR_DPF((PVR_DBG_WARNING,
+ "psCC=%08X psCC->ppsThis=%08X psCC->psNext=%08X ppsTC=%08X",
+ (IMG_UINTPTR_T)psCurContext,
+ (IMG_UINTPTR_T)psCurContext->ppsThis,
+ (IMG_UINTPTR_T)psCurContext->psNext,
+ (IMG_UINTPTR_T)ppsThisContext));
+ PVR_ASSERT(psCurContext->ppsThis == ppsThisContext);
+ }
+
+
+ psCurItem = psCurContext->psResItemList;
+ ppsThisItem = &psCurContext->psResItemList;
+ while(psCurItem != IMG_NULL)
+ {
+
+ PVR_ASSERT(psCurItem->ui32Signature == RESMAN_SIGNATURE);
+ if (psCurItem->ppsThis != ppsThisItem)
+ {
+ PVR_DPF((PVR_DBG_WARNING,
+ "psCurItem=%08X psCurItem->ppsThis=%08X psCurItem->psNext=%08X ppsThisItem=%08X",
+ (IMG_UINTPTR_T)psCurItem,
+ (IMG_UINTPTR_T)psCurItem->ppsThis,
+ (IMG_UINTPTR_T)psCurItem->psNext,
+ (IMG_UINTPTR_T)ppsThisItem));
+ PVR_ASSERT(psCurItem->ppsThis == ppsThisItem);
+ }
+
+
+ ppsThisItem = &psCurItem->psNext;
+ psCurItem = psCurItem->psNext;
+ }
+
+
+ ppsThisContext = &psCurContext->psNext;
+ psCurContext = psCurContext->psNext;
+ }
+}
+#endif
+
+#ifdef RES_MAN_EXTEND
+
+IMG_PVOID PVRSRVGetResData(PRESMAN_ITEM psResItem)
+{
+ if (psResItem)
+ return psResItem->pvParam;
+ else
+ return IMG_NULL;
+}
+
+static IMG_VOID* PickResourceByCriteria_AnyVaCb(RESMAN_ITEM *psCurItem, va_list va)
+{
+ IMG_UINT32 ui32SearchCriteria;
+ IMG_UINT32 ui32ResType;
+ IMG_PVOID pvParam;
+ IMG_UINT32 ui32Param;
+
+ ui32SearchCriteria = va_arg(va, IMG_UINT32);
+ ui32ResType = va_arg(va, IMG_UINT32);
+ pvParam = va_arg(va, IMG_PVOID);
+ ui32Param = va_arg(va, IMG_UINT32);
+
+
+ if(
+
+ (((ui32SearchCriteria & RESMAN_CRITERIA_RESTYPE) == 0UL) ||
+ (psCurItem->ui32ResType == ui32ResType))
+ &&
+
+ (((ui32SearchCriteria & RESMAN_CRITERIA_PVOID_PARAM) == 0UL) ||
+ (psCurItem->pvParam == pvParam))
+ &&
+
+ (((ui32SearchCriteria & RESMAN_CRITERIA_UI32_PARAM) == 0UL) ||
+ (psCurItem->ui32Param == ui32Param))
+ )
+ {
+ return psCurItem;
+ }
+ else
+ {
+ return IMG_NULL;
+ }
+}
+
+PVRSRV_ERROR PVRSRVResManAnyByCriteria(PRESMAN_CONTEXT psResManContext,
+ IMG_UINT32 ui32SearchCriteria,
+ IMG_UINT32 ui32ResType,
+ IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param,
+ PVRSRV_ERROR(*pfnCallBack)(PRESMAN_ITEM psRes, va_list va), ...)
+{
+ PRESMAN_ITEM psCurItem;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ va_list ap;
+
+ psCurItem = psResManContext->psResItemList;
+ while((psCurItem = (PRESMAN_ITEM)
+ List_RESMAN_ITEM_Any_va(psCurItem,
+ &PickResourceByCriteria_AnyVaCb,
+ ui32SearchCriteria,
+ ui32ResType,
+ pvParam,
+ ui32Param)) != IMG_NULL
+ && eError == PVRSRV_OK)
+ {
+ va_start(ap, pfnCallBack);
+ eError = pfnCallBack(psCurItem, ap);
+ va_end(ap);
+ psCurItem = psCurItem->psNext;
+ }
+
+ return eError;
+}
+#endif
--- /dev/null
+bin_pc_i686*
+tmp_pc_i686*
+host_pc_i686*
+*.o
+*.o.cmd
--- /dev/null
+/**********************************************************************
+ *
+ * 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 "sgxdefs.h"
+#include "sgxmmu.h"
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "hash.h"
+#include "ra.h"
+#include "pdump_km.h"
+#include "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "sgxinfokm.h"
+#include "mmu.h"
+#include "sgxconfig.h"
+#include "sgx_bridge_km.h"
+#include "pdump_osfunc.h"
+
+#define UINT32_MAX_VALUE 0xFFFFFFFFUL
+
+#define SGX_MAX_PD_ENTRIES (1<<(SGX_FEATURE_ADDRESS_SPACE_SIZE - SGX_MMU_PT_SHIFT - SGX_MMU_PAGE_SHIFT))
+
+typedef struct _MMU_PT_INFO_
+{
+
+ IMG_VOID *hPTPageOSMemHandle;
+ IMG_CPU_VIRTADDR PTPageCpuVAddr;
+ IMG_UINT32 ui32ValidPTECount;
+} MMU_PT_INFO;
+
+struct _MMU_CONTEXT_
+{
+
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+
+
+ IMG_CPU_VIRTADDR pvPDCpuVAddr;
+ IMG_DEV_PHYADDR sPDDevPAddr;
+
+ IMG_VOID *hPDOSMemHandle;
+
+
+ MMU_PT_INFO *apsPTInfoList[SGX_MAX_PD_ENTRIES];
+
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+
+#if defined(PDUMP)
+ IMG_UINT32 ui32PDumpMMUContextID;
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+ IMG_BOOL bPDumpActive;
+#endif
+#endif
+
+ struct _MMU_CONTEXT_ *psNext;
+};
+
+struct _MMU_HEAP_
+{
+
+ MMU_CONTEXT *psMMUContext;
+
+
+
+
+ IMG_UINT32 ui32PDBaseIndex;
+
+ IMG_UINT32 ui32PageTableCount;
+
+ IMG_UINT32 ui32PTETotal;
+
+ IMG_UINT32 ui32PDEPageSizeCtrl;
+
+
+
+
+ IMG_UINT32 ui32DataPageSize;
+
+ IMG_UINT32 ui32DataPageBitWidth;
+
+ IMG_UINT32 ui32DataPageMask;
+
+
+
+
+ IMG_UINT32 ui32PTShift;
+
+ IMG_UINT32 ui32PTBitWidth;
+
+ IMG_UINT32 ui32PTMask;
+
+ IMG_UINT32 ui32PTSize;
+
+ IMG_UINT32 ui32PTECount;
+
+
+
+
+ IMG_UINT32 ui32PDShift;
+
+ IMG_UINT32 ui32PDBitWidth;
+
+ IMG_UINT32 ui32PDMask;
+
+
+
+ RA_ARENA *psVMArena;
+ DEV_ARENA_DESCRIPTOR *psDevArena;
+#if defined(PDUMP)
+ PDUMP_MMU_ATTRIB sMMUAttrib;
+#endif
+};
+
+
+
+#if defined (SUPPORT_SGX_MMU_DUMMY_PAGE)
+#define DUMMY_DATA_PAGE_SIGNATURE 0xDEADBEEF
+#endif
+
+#if defined(PDUMP)
+static IMG_VOID
+MMU_PDumpPageTables (MMU_HEAP *pMMUHeap,
+ IMG_DEV_VIRTADDR DevVAddr,
+ IMG_SIZE_T uSize,
+ IMG_BOOL bForUnmap,
+ IMG_HANDLE hUniqueTag);
+#endif
+
+#define PAGE_TEST 0
+#if PAGE_TEST
+static IMG_VOID PageTest(IMG_VOID* pMem, IMG_DEV_PHYADDR sDevPAddr);
+#endif
+
+#define PT_DEBUG 0
+#if PT_DEBUG
+static IMG_VOID DumpPT(MMU_PT_INFO *psPTInfoList)
+{
+ IMG_UINT32 *p = (IMG_UINT32*)psPTInfoList->PTPageCpuVAddr;
+ IMG_UINT32 i;
+
+
+ for(i = 0; i < 1024; i += 8)
+ {
+ PVR_DPF((PVR_DBG_WARNING,
+ "%08X %08X %08X %08X %08X %08X %08X %08X\n",
+ p[i + 0], p[i + 1], p[i + 2], p[i + 3],
+ p[i + 4], p[i + 5], p[i + 6], p[i + 7]));
+ }
+}
+
+static IMG_VOID CheckPT(MMU_PT_INFO *psPTInfoList)
+{
+ IMG_UINT32 *p = (IMG_UINT32*) psPTInfoList->PTPageCpuVAddr;
+ IMG_UINT32 i, ui32Count = 0;
+
+
+ for(i = 0; i < 1024; i++)
+ if(p[i] & SGX_MMU_PTE_VALID)
+ ui32Count++;
+
+ if(psPTInfoList->ui32ValidPTECount != ui32Count)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "ui32ValidPTECount: %u ui32Count: %u\n",
+ psPTInfoList->ui32ValidPTECount, ui32Count));
+ DumpPT(psPTInfoList);
+ BUG();
+ }
+}
+#else
+static INLINE IMG_VOID DumpPT(MMU_PT_INFO *psPTInfoList)
+{
+ PVR_UNREFERENCED_PARAMETER(psPTInfoList);
+}
+
+static INLINE IMG_VOID CheckPT(MMU_PT_INFO *psPTInfoList)
+{
+ PVR_UNREFERENCED_PARAMETER(psPTInfoList);
+}
+#endif
+
+
+IMG_BOOL MMU_IsHeapShared(MMU_HEAP* pMMUHeap)
+{
+ switch(pMMUHeap->psDevArena->DevMemHeapType)
+ {
+ case DEVICE_MEMORY_HEAP_SHARED :
+ case DEVICE_MEMORY_HEAP_SHARED_EXPORTED :
+ return IMG_TRUE;
+ case DEVICE_MEMORY_HEAP_PERCONTEXT :
+ case DEVICE_MEMORY_HEAP_KERNEL :
+ return IMG_FALSE;
+ default:
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_IsHeapShared: ERROR invalid heap type"));
+ return IMG_FALSE;
+ }
+ }
+}
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+IMG_VOID
+EnableHostAccess (MMU_CONTEXT *psMMUContext)
+{
+ IMG_UINT32 ui32RegVal;
+ IMG_VOID *pvRegsBaseKM = psMMUContext->psDevInfo->pvRegsBaseKM;
+
+
+
+
+ ui32RegVal = OSReadHWReg(pvRegsBaseKM, EUR_CR_BIF_CTRL);
+
+ OSWriteHWReg(pvRegsBaseKM,
+ EUR_CR_BIF_CTRL,
+ ui32RegVal | EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_MASK);
+
+ PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_MASK);
+}
+
+IMG_VOID
+DisableHostAccess (MMU_CONTEXT *psMMUContext)
+{
+ IMG_UINT32 ui32RegVal;
+ IMG_VOID *pvRegsBaseKM = psMMUContext->psDevInfo->pvRegsBaseKM;
+
+
+
+
+
+ OSWriteHWReg(pvRegsBaseKM,
+ EUR_CR_BIF_CTRL,
+ ui32RegVal & ~EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_MASK);
+
+ PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, 0);
+}
+#endif
+
+
+#if defined(SGX_FEATURE_SYSTEM_CACHE)
+static IMG_VOID MMU_InvalidateSystemLevelCache(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+ #if defined(SGX_FEATURE_MP)
+ psDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_BIF_SL;
+ #else
+
+ PVR_UNREFERENCED_PARAMETER(psDevInfo);
+ #endif
+}
+#endif
+
+IMG_VOID MMU_InvalidateDirectoryCache(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+ psDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_BIF_PD;
+ #if defined(SGX_FEATURE_SYSTEM_CACHE)
+ MMU_InvalidateSystemLevelCache(psDevInfo);
+ #endif
+}
+
+
+static IMG_VOID MMU_InvalidatePageTableCache(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+ psDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_BIF_PT;
+ #if defined(SGX_FEATURE_SYSTEM_CACHE)
+ MMU_InvalidateSystemLevelCache(psDevInfo);
+ #endif
+}
+
+
+static IMG_BOOL
+_AllocPageTableMemory (MMU_HEAP *pMMUHeap,
+ MMU_PT_INFO *psPTInfoList,
+ IMG_DEV_PHYADDR *psDevPAddr)
+{
+ IMG_DEV_PHYADDR sDevPAddr;
+ IMG_CPU_PHYADDR sCpuPAddr;
+
+
+
+
+ if(pMMUHeap->psDevArena->psDeviceMemoryHeapInfo->psLocalDevMemArena == IMG_NULL)
+ {
+
+ if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ pMMUHeap->ui32PTSize,
+ SGX_MMU_PAGE_SIZE,
+ (IMG_VOID **)&psPTInfoList->PTPageCpuVAddr,
+ &psPTInfoList->hPTPageOSMemHandle) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "_AllocPageTableMemory: ERROR call to OSAllocPages failed"));
+ return IMG_FALSE;
+ }
+
+
+ if(psPTInfoList->PTPageCpuVAddr)
+ {
+ sCpuPAddr = OSMapLinToCPUPhys(psPTInfoList->hPTPageOSMemHandle,
+ psPTInfoList->PTPageCpuVAddr);
+ }
+ else
+ {
+
+ sCpuPAddr = OSMemHandleToCpuPAddr(psPTInfoList->hPTPageOSMemHandle, 0);
+ }
+
+ sDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+ }
+ else
+ {
+ IMG_SYS_PHYADDR sSysPAddr;
+
+
+
+
+
+ if(RA_Alloc(pMMUHeap->psDevArena->psDeviceMemoryHeapInfo->psLocalDevMemArena,
+ SGX_MMU_PAGE_SIZE,
+ IMG_NULL,
+ IMG_NULL,
+ 0,
+ SGX_MMU_PAGE_SIZE,
+ 0,
+ &(sSysPAddr.uiAddr))!= IMG_TRUE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "_AllocPageTableMemory: ERROR call to RA_Alloc failed"));
+ return IMG_FALSE;
+ }
+
+
+ sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+
+ psPTInfoList->PTPageCpuVAddr = OSMapPhysToLin(sCpuPAddr,
+ SGX_MMU_PAGE_SIZE,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ &psPTInfoList->hPTPageOSMemHandle);
+ if(!psPTInfoList->PTPageCpuVAddr)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "_AllocPageTableMemory: ERROR failed to map page tables"));
+ return IMG_FALSE;
+ }
+
+
+ sDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+
+ #if PAGE_TEST
+ PageTest(psPTInfoList->PTPageCpuVAddr, sDevPAddr);
+ #endif
+ }
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+ {
+ IMG_UINT32 *pui32Tmp;
+ IMG_UINT32 i;
+
+ pui32Tmp = (IMG_UINT32*)psPTInfoList->PTPageCpuVAddr;
+
+ for(i=0; i<pMMUHeap->ui32PTECount; i++)
+ {
+ pui32Tmp[i] = (pMMUHeap->psMMUContext->psDevInfo->sDummyDataDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PTE_VALID;
+ }
+ }
+#else
+
+ OSMemSet(psPTInfoList->PTPageCpuVAddr, 0, pMMUHeap->ui32PTSize);
+#endif
+
+#if defined(PDUMP)
+ {
+ IMG_UINT32 ui32Flags = 0;
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+
+ ui32Flags |= ( MMU_IsHeapShared(pMMUHeap) ) ? PDUMP_FLAGS_PERSISTENT : 0;
+#endif
+
+ PDUMPMALLOCPAGETABLE(&pMMUHeap->psMMUContext->psDeviceNode->sDevId, psPTInfoList->hPTPageOSMemHandle, 0, psPTInfoList->PTPageCpuVAddr, pMMUHeap->ui32PTSize, ui32Flags, PDUMP_PT_UNIQUETAG);
+
+ PDUMPMEMPTENTRIES(&pMMUHeap->sMMUAttrib, psPTInfoList->hPTPageOSMemHandle, psPTInfoList->PTPageCpuVAddr, pMMUHeap->ui32PTSize, ui32Flags, IMG_TRUE, PDUMP_PT_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+ }
+#endif
+
+
+ *psDevPAddr = sDevPAddr;
+
+ return IMG_TRUE;
+}
+
+
+static IMG_VOID
+_FreePageTableMemory (MMU_HEAP *pMMUHeap, MMU_PT_INFO *psPTInfoList)
+{
+
+
+
+
+ if(pMMUHeap->psDevArena->psDeviceMemoryHeapInfo->psLocalDevMemArena == IMG_NULL)
+ {
+
+ OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ pMMUHeap->ui32PTSize,
+ psPTInfoList->PTPageCpuVAddr,
+ psPTInfoList->hPTPageOSMemHandle);
+ }
+ else
+ {
+ IMG_SYS_PHYADDR sSysPAddr;
+ IMG_CPU_PHYADDR sCpuPAddr;
+
+
+ sCpuPAddr = OSMapLinToCPUPhys(psPTInfoList->hPTPageOSMemHandle,
+ psPTInfoList->PTPageCpuVAddr);
+ sSysPAddr = SysCpuPAddrToSysPAddr (sCpuPAddr);
+
+
+
+ OSUnMapPhysToLin(psPTInfoList->PTPageCpuVAddr,
+ SGX_MMU_PAGE_SIZE,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ psPTInfoList->hPTPageOSMemHandle);
+
+
+
+
+ RA_Free (pMMUHeap->psDevArena->psDeviceMemoryHeapInfo->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
+ }
+}
+
+
+
+static IMG_VOID
+_DeferredFreePageTable (MMU_HEAP *pMMUHeap, IMG_UINT32 ui32PTIndex, IMG_BOOL bOSFreePT)
+{
+ IMG_UINT32 *pui32PDEntry;
+ IMG_UINT32 i;
+ IMG_UINT32 ui32PDIndex;
+ SYS_DATA *psSysData;
+ MMU_PT_INFO **ppsPTInfoList;
+
+ SysAcquireData(&psSysData);
+
+
+ ui32PDIndex = pMMUHeap->psDevArena->BaseDevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
+
+
+ ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
+
+ {
+#if PT_DEBUG
+ if(ppsPTInfoList[ui32PTIndex] && ppsPTInfoList[ui32PTIndex]->ui32ValidPTECount > 0)
+ {
+ DumpPT(ppsPTInfoList[ui32PTIndex]);
+
+ }
+#endif
+
+
+ PVR_ASSERT(ppsPTInfoList[ui32PTIndex] == IMG_NULL || ppsPTInfoList[ui32PTIndex]->ui32ValidPTECount == 0);
+ }
+
+#if defined(PDUMP)
+ {
+ IMG_UINT32 ui32Flags = 0;
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+ ui32Flags |= ( MMU_IsHeapShared(pMMUHeap) ) ? PDUMP_FLAGS_PERSISTENT : 0;
+#endif
+
+ PDUMPCOMMENT("Free page table (page count == %08X)", pMMUHeap->ui32PageTableCount);
+ if(ppsPTInfoList[ui32PTIndex] && ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr)
+ {
+ PDUMPFREEPAGETABLE(&pMMUHeap->psMMUContext->psDeviceNode->sDevId, ppsPTInfoList[ui32PTIndex]->hPTPageOSMemHandle, ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr, pMMUHeap->ui32PTSize, ui32Flags, PDUMP_PT_UNIQUETAG);
+ }
+ }
+#endif
+
+ switch(pMMUHeap->psDevArena->DevMemHeapType)
+ {
+ case DEVICE_MEMORY_HEAP_SHARED :
+ case DEVICE_MEMORY_HEAP_SHARED_EXPORTED :
+ {
+
+ MMU_CONTEXT *psMMUContext = (MMU_CONTEXT*)pMMUHeap->psMMUContext->psDevInfo->pvMMUContextList;
+
+ while(psMMUContext)
+ {
+
+ pui32PDEntry = (IMG_UINT32*)psMMUContext->pvPDCpuVAddr;
+ pui32PDEntry += ui32PDIndex;
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+ pui32PDEntry[ui32PTIndex] = (psMMUContext->psDevInfo->sDummyPTDevPAddr.uiAddr
+ >>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PDE_PAGE_SIZE_4K
+ | SGX_MMU_PDE_VALID;
+#else
+
+ if(bOSFreePT)
+ {
+ pui32PDEntry[ui32PTIndex] = 0;
+ }
+#endif
+ #if defined(PDUMP)
+
+ #if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+ if(psMMUContext->bPDumpActive)
+ #endif
+ {
+ PDUMPPDENTRIES(&pMMUHeap->sMMUAttrib, psMMUContext->hPDOSMemHandle, (IMG_VOID*)&pui32PDEntry[ui32PTIndex], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PT_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+ }
+ #endif
+
+ psMMUContext = psMMUContext->psNext;
+ }
+ break;
+ }
+ case DEVICE_MEMORY_HEAP_PERCONTEXT :
+ case DEVICE_MEMORY_HEAP_KERNEL :
+ {
+
+ pui32PDEntry = (IMG_UINT32*)pMMUHeap->psMMUContext->pvPDCpuVAddr;
+ pui32PDEntry += ui32PDIndex;
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+ pui32PDEntry[ui32PTIndex] = (pMMUHeap->psMMUContext->psDevInfo->sDummyPTDevPAddr.uiAddr
+ >>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PDE_PAGE_SIZE_4K
+ | SGX_MMU_PDE_VALID;
+#else
+
+ if(bOSFreePT)
+ {
+ pui32PDEntry[ui32PTIndex] = 0;
+ }
+#endif
+
+
+ PDUMPPDENTRIES(&pMMUHeap->sMMUAttrib, pMMUHeap->psMMUContext->hPDOSMemHandle, (IMG_VOID*)&pui32PDEntry[ui32PTIndex], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+ break;
+ }
+ default:
+ {
+ PVR_DPF((PVR_DBG_ERROR, "_DeferredFreePagetable: ERROR invalid heap type"));
+ return;
+ }
+ }
+
+
+ if(ppsPTInfoList[ui32PTIndex] != IMG_NULL)
+ {
+ if(ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr != IMG_NULL)
+ {
+ IMG_PUINT32 pui32Tmp;
+
+ pui32Tmp = (IMG_UINT32*)ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr;
+
+
+ for(i=0;
+ (i<pMMUHeap->ui32PTETotal) && (i<pMMUHeap->ui32PTECount);
+ i++)
+ {
+ pui32Tmp[i] = 0;
+ }
+
+
+
+ if(bOSFreePT)
+ {
+ _FreePageTableMemory(pMMUHeap, ppsPTInfoList[ui32PTIndex]);
+ }
+
+
+
+
+ pMMUHeap->ui32PTETotal -= i;
+ }
+ else
+ {
+
+ pMMUHeap->ui32PTETotal -= pMMUHeap->ui32PTECount;
+ }
+
+ if(bOSFreePT)
+ {
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(MMU_PT_INFO),
+ ppsPTInfoList[ui32PTIndex],
+ IMG_NULL);
+ ppsPTInfoList[ui32PTIndex] = IMG_NULL;
+ }
+ }
+ else
+ {
+
+ pMMUHeap->ui32PTETotal -= pMMUHeap->ui32PTECount;
+ }
+
+ PDUMPCOMMENT("Finished free page table (page count == %08X)", pMMUHeap->ui32PageTableCount);
+}
+
+static IMG_VOID
+_DeferredFreePageTables (MMU_HEAP *pMMUHeap)
+{
+ IMG_UINT32 i;
+#if defined(PDUMP)
+ PDUMPCOMMENT("Free PTs (MMU Context ID == %u, PDBaseIndex == %u, PT count == 0x%x)",
+ pMMUHeap->psMMUContext->ui32PDumpMMUContextID,
+ pMMUHeap->ui32PDBaseIndex,
+ pMMUHeap->ui32PageTableCount);
+#endif
+ for(i=0; i<pMMUHeap->ui32PageTableCount; i++)
+ {
+ _DeferredFreePageTable(pMMUHeap, i, IMG_TRUE);
+ }
+ MMU_InvalidateDirectoryCache(pMMUHeap->psMMUContext->psDevInfo);
+}
+
+
+static IMG_BOOL
+_DeferredAllocPagetables(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR DevVAddr, IMG_UINT32 ui32Size)
+{
+ IMG_UINT32 ui32PageTableCount;
+ IMG_UINT32 ui32PDIndex;
+ IMG_UINT32 i;
+ IMG_UINT32 *pui32PDEntry;
+ MMU_PT_INFO **ppsPTInfoList;
+ SYS_DATA *psSysData;
+ IMG_DEV_VIRTADDR sHighDevVAddr;
+
+
+#if SGX_FEATURE_ADDRESS_SPACE_SIZE < 32
+ PVR_ASSERT(DevVAddr.uiAddr < (1<<SGX_FEATURE_ADDRESS_SPACE_SIZE));
+#endif
+
+
+ SysAcquireData(&psSysData);
+
+
+ ui32PDIndex = DevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
+
+
+
+ if((UINT32_MAX_VALUE - DevVAddr.uiAddr)
+ < (ui32Size + pMMUHeap->ui32DataPageMask + pMMUHeap->ui32PTMask))
+ {
+
+ sHighDevVAddr.uiAddr = UINT32_MAX_VALUE;
+ }
+ else
+ {
+ sHighDevVAddr.uiAddr = DevVAddr.uiAddr
+ + ui32Size
+ + pMMUHeap->ui32DataPageMask
+ + pMMUHeap->ui32PTMask;
+ }
+
+ ui32PageTableCount = sHighDevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
+
+ ui32PageTableCount -= ui32PDIndex;
+
+
+ pui32PDEntry = (IMG_UINT32*)pMMUHeap->psMMUContext->pvPDCpuVAddr;
+ pui32PDEntry += ui32PDIndex;
+
+
+ ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
+
+#if defined(PDUMP)
+ PDUMPCOMMENT("Alloc PTs (MMU Context ID == %u, PDBaseIndex == %u, Size == 0x%x)",
+ pMMUHeap->psMMUContext->ui32PDumpMMUContextID,
+ pMMUHeap->ui32PDBaseIndex,
+ ui32Size);
+ PDUMPCOMMENT("Alloc page table (page count == %08X)", ui32PageTableCount);
+ PDUMPCOMMENT("Page directory mods (page count == %08X)", ui32PageTableCount);
+#endif
+
+ for(i=0; i<ui32PageTableCount; i++)
+ {
+ if(ppsPTInfoList[i] == IMG_NULL)
+ {
+ OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof (MMU_PT_INFO),
+ (IMG_VOID **)&ppsPTInfoList[i], IMG_NULL,
+ "MMU Page Table Info");
+ if (ppsPTInfoList[i] == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "_DeferredAllocPagetables: ERROR call to OSAllocMem failed"));
+ return IMG_FALSE;
+ }
+ OSMemSet (ppsPTInfoList[i], 0, sizeof(MMU_PT_INFO));
+ }
+
+ if(ppsPTInfoList[i]->hPTPageOSMemHandle == IMG_NULL
+ && ppsPTInfoList[i]->PTPageCpuVAddr == IMG_NULL)
+ {
+ IMG_DEV_PHYADDR sDevPAddr;
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+ IMG_UINT32 *pui32Tmp;
+ IMG_UINT32 j;
+#else
+
+ PVR_ASSERT(pui32PDEntry[i] == 0);
+#endif
+
+ if(_AllocPageTableMemory (pMMUHeap, ppsPTInfoList[i], &sDevPAddr) != IMG_TRUE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "_DeferredAllocPagetables: ERROR call to _AllocPageTableMemory failed"));
+ return IMG_FALSE;
+ }
+
+ switch(pMMUHeap->psDevArena->DevMemHeapType)
+ {
+ case DEVICE_MEMORY_HEAP_SHARED :
+ case DEVICE_MEMORY_HEAP_SHARED_EXPORTED :
+ {
+
+ MMU_CONTEXT *psMMUContext = (MMU_CONTEXT*)pMMUHeap->psMMUContext->psDevInfo->pvMMUContextList;
+
+ while(psMMUContext)
+ {
+
+ pui32PDEntry = (IMG_UINT32*)psMMUContext->pvPDCpuVAddr;
+ pui32PDEntry += ui32PDIndex;
+
+
+ pui32PDEntry[i] = (sDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+ | pMMUHeap->ui32PDEPageSizeCtrl
+ | SGX_MMU_PDE_VALID;
+
+ #if defined(PDUMP)
+
+ #if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+ if(psMMUContext->bPDumpActive)
+ #endif
+ {
+
+ PDUMPPDENTRIES(&pMMUHeap->sMMUAttrib, psMMUContext->hPDOSMemHandle, (IMG_VOID*)&pui32PDEntry[i], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+ }
+ #endif
+
+
+ psMMUContext = psMMUContext->psNext;
+ }
+ break;
+ }
+ case DEVICE_MEMORY_HEAP_PERCONTEXT :
+ case DEVICE_MEMORY_HEAP_KERNEL :
+ {
+
+ pui32PDEntry[i] = (sDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+ | pMMUHeap->ui32PDEPageSizeCtrl
+ | SGX_MMU_PDE_VALID;
+
+
+ PDUMPPDENTRIES(&pMMUHeap->sMMUAttrib, pMMUHeap->psMMUContext->hPDOSMemHandle, (IMG_VOID*)&pui32PDEntry[i], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+ break;
+ }
+ default:
+ {
+ PVR_DPF((PVR_DBG_ERROR, "_DeferredAllocPagetables: ERROR invalid heap type"));
+ return IMG_FALSE;
+ }
+ }
+
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+
+
+
+
+ MMU_InvalidateDirectoryCache(pMMUHeap->psMMUContext->psDevInfo);
+#endif
+ }
+ else
+ {
+
+ PVR_ASSERT(pui32PDEntry[i] != 0);
+ }
+ }
+
+ #if defined(SGX_FEATURE_SYSTEM_CACHE)
+ MMU_InvalidateSystemLevelCache(pMMUHeap->psMMUContext->psDevInfo);
+ #endif
+
+ return IMG_TRUE;
+}
+
+
+#if defined(PDUMP)
+IMG_UINT32 MMU_GetPDumpContextID(IMG_HANDLE hDevMemContext)
+{
+ BM_CONTEXT *pBMContext = hDevMemContext;
+ PVR_ASSERT(pBMContext);
+ return pBMContext->psMMUContext->ui32PDumpMMUContextID;
+}
+
+static IMG_VOID MMU_SetPDumpAttribs(PDUMP_MMU_ATTRIB *psMMUAttrib,
+ PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 ui32DataPageMask,
+ IMG_UINT32 ui32PTSize)
+{
+
+ psMMUAttrib->sDevId = psDeviceNode->sDevId;
+
+ psMMUAttrib->pszPDRegRegion = IMG_NULL;
+ psMMUAttrib->ui32DataPageMask = ui32DataPageMask;
+
+ psMMUAttrib->ui32PTEValid = SGX_MMU_PTE_VALID;
+ psMMUAttrib->ui32PTSize = ui32PTSize;
+ psMMUAttrib->ui32PTEAlignShift = SGX_MMU_PTE_ADDR_ALIGNSHIFT;
+
+ psMMUAttrib->ui32PDEMask = SGX_MMU_PDE_ADDR_MASK;
+ psMMUAttrib->ui32PDEAlignShift = SGX_MMU_PDE_ADDR_ALIGNSHIFT;
+}
+#endif
+
+PVRSRV_ERROR
+MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, IMG_DEV_PHYADDR *psPDDevPAddr)
+{
+ IMG_UINT32 *pui32Tmp;
+ IMG_UINT32 i;
+ IMG_CPU_VIRTADDR pvPDCpuVAddr;
+ IMG_DEV_PHYADDR sPDDevPAddr;
+ IMG_CPU_PHYADDR sCpuPAddr;
+ MMU_CONTEXT *psMMUContext;
+ IMG_HANDLE hPDOSMemHandle;
+ SYS_DATA *psSysData;
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+#if defined(PDUMP)
+ PDUMP_MMU_ATTRIB sMMUAttrib;
+#endif
+ PVR_DPF ((PVR_DBG_MESSAGE, "MMU_Initialise"));
+
+ SysAcquireData(&psSysData);
+#if defined(PDUMP)
+
+
+ MMU_SetPDumpAttribs(&sMMUAttrib, psDeviceNode,
+ SGX_MMU_PAGE_MASK,
+ SGX_MMU_PT_SIZE * sizeof(IMG_UINT32));
+#endif
+
+ OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof (MMU_CONTEXT),
+ (IMG_VOID **)&psMMUContext, IMG_NULL,
+ "MMU Context");
+ if (psMMUContext == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocMem failed"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ OSMemSet (psMMUContext, 0, sizeof(MMU_CONTEXT));
+
+
+ psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+ psMMUContext->psDevInfo = psDevInfo;
+
+
+ psMMUContext->psDeviceNode = psDeviceNode;
+
+
+ if(psDeviceNode->psLocalDevMemArena == IMG_NULL)
+ {
+ if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ SGX_MMU_PAGE_SIZE,
+ SGX_MMU_PAGE_SIZE,
+ &pvPDCpuVAddr,
+ &hPDOSMemHandle) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocPages failed"));
+ return PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES;
+ }
+
+ if(pvPDCpuVAddr)
+ {
+ sCpuPAddr = OSMapLinToCPUPhys(hPDOSMemHandle,
+ pvPDCpuVAddr);
+ }
+ else
+ {
+
+ sCpuPAddr = OSMemHandleToCpuPAddr(hPDOSMemHandle, 0);
+ }
+ sPDDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+
+ #if PAGE_TEST
+ PageTest(pvPDCpuVAddr, sPDDevPAddr);
+ #endif
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+ if(!psDevInfo->pvMMUContextList)
+ {
+
+ if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ SGX_MMU_PAGE_SIZE,
+ SGX_MMU_PAGE_SIZE,
+ &psDevInfo->pvDummyPTPageCpuVAddr,
+ &psDevInfo->hDummyPTPageOSMemHandle) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocPages failed"));
+ return PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES;
+ }
+
+ if(psDevInfo->pvDummyPTPageCpuVAddr)
+ {
+ sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->hDummyPTPageOSMemHandle,
+ psDevInfo->pvDummyPTPageCpuVAddr);
+ }
+ else
+ {
+
+ sCpuPAddr = OSMemHandleToCpuPAddr(psDevInfo->hDummyPTPageOSMemHandle, 0);
+ }
+ psDevInfo->sDummyPTDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+
+
+ if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ SGX_MMU_PAGE_SIZE,
+ SGX_MMU_PAGE_SIZE,
+ &psDevInfo->pvDummyDataPageCpuVAddr,
+ &psDevInfo->hDummyDataPageOSMemHandle) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocPages failed"));
+ return PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES;
+ }
+
+ if(psDevInfo->pvDummyDataPageCpuVAddr)
+ {
+ sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->hDummyPTPageOSMemHandle,
+ psDevInfo->pvDummyDataPageCpuVAddr);
+ }
+ else
+ {
+ sCpuPAddr = OSMemHandleToCpuPAddr(psDevInfo->hDummyDataPageOSMemHandle, 0);
+ }
+ psDevInfo->sDummyDataDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+ }
+#endif
+ }
+ else
+ {
+ IMG_SYS_PHYADDR sSysPAddr;
+
+
+ if(RA_Alloc(psDeviceNode->psLocalDevMemArena,
+ SGX_MMU_PAGE_SIZE,
+ IMG_NULL,
+ IMG_NULL,
+ 0,
+ SGX_MMU_PAGE_SIZE,
+ 0,
+ &(sSysPAddr.uiAddr))!= IMG_TRUE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to RA_Alloc failed"));
+ return PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY;
+ }
+
+
+ sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+ sPDDevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysPAddr);
+ pvPDCpuVAddr = OSMapPhysToLin(sCpuPAddr,
+ SGX_MMU_PAGE_SIZE,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ &hPDOSMemHandle);
+ if(!pvPDCpuVAddr)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR failed to map page tables"));
+ return PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE;
+ }
+
+ #if PAGE_TEST
+ PageTest(pvPDCpuVAddr, sPDDevPAddr);
+ #endif
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+ if(!psDevInfo->pvMMUContextList)
+ {
+
+ if(RA_Alloc(psDeviceNode->psLocalDevMemArena,
+ SGX_MMU_PAGE_SIZE,
+ IMG_NULL,
+ IMG_NULL,
+ 0,
+ SGX_MMU_PAGE_SIZE,
+ 0,
+ &(sSysPAddr.uiAddr))!= IMG_TRUE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to RA_Alloc failed"));
+ return PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY;
+ }
+
+
+ sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+ psDevInfo->sDummyPTDevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysPAddr);
+ psDevInfo->pvDummyPTPageCpuVAddr = OSMapPhysToLin(sCpuPAddr,
+ SGX_MMU_PAGE_SIZE,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ &psDevInfo->hDummyPTPageOSMemHandle);
+ if(!psDevInfo->pvDummyPTPageCpuVAddr)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR failed to map page tables"));
+ return PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE;
+ }
+
+
+ if(RA_Alloc(psDeviceNode->psLocalDevMemArena,
+ SGX_MMU_PAGE_SIZE,
+ IMG_NULL,
+ IMG_NULL,
+ 0,
+ SGX_MMU_PAGE_SIZE,
+ 0,
+ &(sSysPAddr.uiAddr))!= IMG_TRUE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to RA_Alloc failed"));
+ return PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY;
+ }
+
+
+ sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+ psDevInfo->sDummyDataDevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysPAddr);
+ psDevInfo->pvDummyDataPageCpuVAddr = OSMapPhysToLin(sCpuPAddr,
+ SGX_MMU_PAGE_SIZE,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ &psDevInfo->hDummyDataPageOSMemHandle);
+ if(!psDevInfo->pvDummyDataPageCpuVAddr)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR failed to map page tables"));
+ return PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE;
+ }
+ }
+#endif
+ }
+
+#if defined(PDUMP)
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+
+ {
+ PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData();
+ if(psPerProc == IMG_NULL)
+ {
+
+ psMMUContext->bPDumpActive = IMG_TRUE;
+ }
+ else
+ {
+ psMMUContext->bPDumpActive = psPerProc->bPDumpActive;
+ }
+ }
+#endif
+
+#if IMG_ADDRSPACE_PHYSADDR_BITS == 32
+ PDUMPCOMMENT("Alloc page directory for new MMU context (PDDevPAddr == 0x%08x)",
+ sPDDevPAddr.uiAddr);
+#else
+ PDUMPCOMMENT("Alloc page directory for new MMU context, 64-bit arch detected (PDDevPAddr == 0x%08x%08x)",
+ sPDDevPAddr.uiHighAddr, sPDDevPAddr.uiAddr);
+#endif
+ PDUMPMALLOCPAGETABLE(&psDeviceNode->sDevId, hPDOSMemHandle, 0, pvPDCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PD_UNIQUETAG);
+#endif
+#ifdef SUPPORT_SGX_MMU_BYPASS
+ EnableHostAccess(psMMUContext);
+#endif
+
+ if (pvPDCpuVAddr)
+ {
+ pui32Tmp = (IMG_UINT32 *)pvPDCpuVAddr;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: pvPDCpuVAddr invalid"));
+ return PVRSRV_ERROR_INVALID_CPU_ADDR;
+ }
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+ for(i=0; i<SGX_MMU_PD_SIZE; i++)
+ {
+ pui32Tmp[i] = (psDevInfo->sDummyPTDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PDE_PAGE_SIZE_4K
+ | SGX_MMU_PDE_VALID;
+ }
+
+ if(!psDevInfo->pvMMUContextList)
+ {
+
+
+
+ pui32Tmp = (IMG_UINT32 *)psDevInfo->pvDummyPTPageCpuVAddr;
+ for(i=0; i<SGX_MMU_PT_SIZE; i++)
+ {
+ pui32Tmp[i] = (psDevInfo->sDummyDataDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PTE_VALID;
+ }
+
+ PDUMPCOMMENT("Dummy Page table contents");
+ PDUMPMEMPTENTRIES(&sMMUAttrib, psDevInfo->hDummyPTOSMemHandle, psDevInfo->pvDummyPTPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+
+
+
+ pui32Tmp = (IMG_UINT32 *)psDevInfo->pvDummyDataPageCpuVAddr;
+ for(i=0; i<(SGX_MMU_PAGE_SIZE/4); i++)
+ {
+ pui32Tmp[i] = DUMMY_DATA_PAGE_SIGNATURE;
+ }
+
+ PDUMPCOMMENT("Dummy Data Page contents");
+ PDUMPMEMPTENTRIES(PVRSRV_DEVICE_TYPE_SGX, psDevInfo->hDummyDataPageOSMemHandle, psDevInfo->pvDummyDataPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+ }
+#else
+
+ for(i=0; i<SGX_MMU_PD_SIZE; i++)
+ {
+
+ pui32Tmp[i] = 0;
+ }
+#endif
+
+#if defined(PDUMP)
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+ if(psMMUContext->bPDumpActive)
+#endif
+ {
+
+ PDUMPCOMMENT("Page directory contents");
+ PDUMPPDENTRIES(&sMMUAttrib, hPDOSMemHandle, pvPDCpuVAddr, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+ }
+
+
+ {
+ PVRSRV_ERROR eError;
+
+ IMG_UINT32 ui32MMUType = 1;
+
+ #if defined(SGX_FEATURE_36BIT_MMU)
+ ui32MMUType = 3;
+ #else
+ #if defined(SGX_FEATURE_VARIABLE_MMU_PAGE_SIZE)
+ ui32MMUType = 2;
+ #endif
+ #endif
+
+ eError = PDumpSetMMUContext(PVRSRV_DEVICE_TYPE_SGX,
+ psDeviceNode->sDevId.pszPDumpDevName,
+ &psMMUContext->ui32PDumpMMUContextID,
+ ui32MMUType,
+ PDUMP_PT_UNIQUETAG,
+ hPDOSMemHandle,
+ pvPDCpuVAddr);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to PDumpSetMMUContext failed"));
+ return eError;
+ }
+ }
+
+
+ PDUMPCOMMENT("Set MMU context complete (MMU Context ID == %u)", psMMUContext->ui32PDumpMMUContextID);
+#endif
+
+
+ psMMUContext->pvPDCpuVAddr = pvPDCpuVAddr;
+ psMMUContext->sPDDevPAddr = sPDDevPAddr;
+ psMMUContext->hPDOSMemHandle = hPDOSMemHandle;
+
+
+ *ppsMMUContext = psMMUContext;
+
+
+ *psPDDevPAddr = sPDDevPAddr;
+
+
+ psMMUContext->psNext = (MMU_CONTEXT*)psDevInfo->pvMMUContextList;
+ psDevInfo->pvMMUContextList = (IMG_VOID*)psMMUContext;
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+ DisableHostAccess(psMMUContext);
+#endif
+
+ return PVRSRV_OK;
+}
+
+IMG_VOID
+MMU_Finalise (MMU_CONTEXT *psMMUContext)
+{
+ IMG_UINT32 *pui32Tmp, i;
+ SYS_DATA *psSysData;
+ MMU_CONTEXT **ppsMMUContext;
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+ PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO*)psMMUContext->psDevInfo;
+ MMU_CONTEXT *psMMUContextList = (MMU_CONTEXT*)psDevInfo->pvMMUContextList;
+#endif
+
+ SysAcquireData(&psSysData);
+
+#if defined(PDUMP)
+
+ PDUMPCOMMENT("Clear MMU context (MMU Context ID == %u)", psMMUContext->ui32PDumpMMUContextID);
+ PDUMPCLEARMMUCONTEXT(PVRSRV_DEVICE_TYPE_SGX, psMMUContext->psDeviceNode->sDevId.pszPDumpDevName, psMMUContext->ui32PDumpMMUContextID, 2);
+
+
+#if IMG_ADDRSPACE_PHYSADDR_BITS == 32
+ PDUMPCOMMENT("Free page directory (PDDevPAddr == 0x%08x)",
+ psMMUContext->sPDDevPAddr.uiAddr);
+#else
+ PDUMPCOMMENT("Free page directory, 64-bit arch detected (PDDevPAddr == 0x%08x%08x)",
+ psMMUContext->sPDDevPAddr.uiHighAddr, psMMUContext->sPDDevPAddr.uiAddr);
+#endif
+#endif
+
+ PDUMPFREEPAGETABLE(&psMMUContext->psDeviceNode->sDevId, psMMUContext->hPDOSMemHandle, psMMUContext->pvPDCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+ PDUMPFREEPAGETABLE(&psMMUContext->psDeviceNode->sDevId, psDevInfo->hDummyPTPageOSMemHandle, psDevInfo->pvDummyPTPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
+ PDUMPFREEPAGETABLE(&psMMUContext->psDeviceNode->sDevId, psDevInfo->hDummyDataPageOSMemHandle, psDevInfo->pvDummyDataPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
+#endif
+
+ pui32Tmp = (IMG_UINT32 *)psMMUContext->pvPDCpuVAddr;
+
+
+ for(i=0; i<SGX_MMU_PD_SIZE; i++)
+ {
+
+ pui32Tmp[i] = 0;
+ }
+
+
+
+
+
+ if(psMMUContext->psDeviceNode->psLocalDevMemArena == IMG_NULL)
+ {
+ OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ SGX_MMU_PAGE_SIZE,
+ psMMUContext->pvPDCpuVAddr,
+ psMMUContext->hPDOSMemHandle);
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+ if(!psMMUContextList->psNext)
+ {
+ OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ SGX_MMU_PAGE_SIZE,
+ psDevInfo->pvDummyPTPageCpuVAddr,
+ psDevInfo->hDummyPTPageOSMemHandle);
+ OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ SGX_MMU_PAGE_SIZE,
+ psDevInfo->pvDummyDataPageCpuVAddr,
+ psDevInfo->hDummyDataPageOSMemHandle);
+ }
+#endif
+ }
+ else
+ {
+ IMG_SYS_PHYADDR sSysPAddr;
+ IMG_CPU_PHYADDR sCpuPAddr;
+
+
+ sCpuPAddr = OSMapLinToCPUPhys(psMMUContext->hPDOSMemHandle,
+ psMMUContext->pvPDCpuVAddr);
+ sSysPAddr = SysCpuPAddrToSysPAddr(sCpuPAddr);
+
+
+ OSUnMapPhysToLin(psMMUContext->pvPDCpuVAddr,
+ SGX_MMU_PAGE_SIZE,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ psMMUContext->hPDOSMemHandle);
+
+ RA_Free (psMMUContext->psDeviceNode->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+ if(!psMMUContextList->psNext)
+ {
+
+ sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->hDummyPTPageOSMemHandle,
+ psDevInfo->pvDummyPTPageCpuVAddr);
+ sSysPAddr = SysCpuPAddrToSysPAddr(sCpuPAddr);
+
+
+ OSUnMapPhysToLin(psDevInfo->pvDummyPTPageCpuVAddr,
+ SGX_MMU_PAGE_SIZE,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ psDevInfo->hDummyPTPageOSMemHandle);
+
+ RA_Free (psMMUContext->psDeviceNode->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
+
+
+ sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->hDummyDataPageOSMemHandle,
+ psDevInfo->pvDummyDataPageCpuVAddr);
+ sSysPAddr = SysCpuPAddrToSysPAddr(sCpuPAddr);
+
+
+ OSUnMapPhysToLin(psDevInfo->pvDummyDataPageCpuVAddr,
+ SGX_MMU_PAGE_SIZE,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ psDevInfo->hDummyDataPageOSMemHandle);
+
+ RA_Free (psMMUContext->psDeviceNode->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
+ }
+#endif
+ }
+
+ PVR_DPF ((PVR_DBG_MESSAGE, "MMU_Finalise"));
+
+
+ ppsMMUContext = (MMU_CONTEXT**)&psMMUContext->psDevInfo->pvMMUContextList;
+ while(*ppsMMUContext)
+ {
+ if(*ppsMMUContext == psMMUContext)
+ {
+
+ *ppsMMUContext = psMMUContext->psNext;
+ break;
+ }
+
+
+ ppsMMUContext = &((*ppsMMUContext)->psNext);
+ }
+
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(MMU_CONTEXT), psMMUContext, IMG_NULL);
+
+}
+
+
+IMG_VOID
+MMU_InsertHeap(MMU_CONTEXT *psMMUContext, MMU_HEAP *psMMUHeap)
+{
+ IMG_UINT32 *pui32PDCpuVAddr = (IMG_UINT32 *) psMMUContext->pvPDCpuVAddr;
+ IMG_UINT32 *pui32KernelPDCpuVAddr = (IMG_UINT32 *) psMMUHeap->psMMUContext->pvPDCpuVAddr;
+ IMG_UINT32 ui32PDEntry;
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+ IMG_BOOL bInvalidateDirectoryCache = IMG_FALSE;
+#endif
+
+
+ pui32PDCpuVAddr += psMMUHeap->psDevArena->BaseDevVAddr.uiAddr >> psMMUHeap->ui32PDShift;
+ pui32KernelPDCpuVAddr += psMMUHeap->psDevArena->BaseDevVAddr.uiAddr >> psMMUHeap->ui32PDShift;
+
+
+
+
+#if defined(PDUMP)
+ PDUMPCOMMENT("Page directory shared heap range copy");
+ PDUMPCOMMENT(" (Source heap MMU Context ID == %u, PT count == 0x%x)",
+ psMMUHeap->psMMUContext->ui32PDumpMMUContextID,
+ psMMUHeap->ui32PageTableCount);
+ PDUMPCOMMENT(" (Destination MMU Context ID == %u)", psMMUContext->ui32PDumpMMUContextID);
+#endif
+#ifdef SUPPORT_SGX_MMU_BYPASS
+ EnableHostAccess(psMMUContext);
+#endif
+
+ for (ui32PDEntry = 0; ui32PDEntry < psMMUHeap->ui32PageTableCount; ui32PDEntry++)
+ {
+#if !defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+ PVR_ASSERT(pui32PDCpuVAddr[ui32PDEntry] == 0);
+#endif
+
+
+ pui32PDCpuVAddr[ui32PDEntry] = pui32KernelPDCpuVAddr[ui32PDEntry];
+ if (pui32PDCpuVAddr[ui32PDEntry])
+ {
+
+ #if defined(PDUMP)
+
+ #if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+ if(psMMUContext->bPDumpActive)
+ #endif
+ {
+ PDUMPPDENTRIES(&psMMUHeap->sMMUAttrib, psMMUContext->hPDOSMemHandle, (IMG_VOID *) &pui32PDCpuVAddr[ui32PDEntry], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+ }
+ #endif
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+ bInvalidateDirectoryCache = IMG_TRUE;
+#endif
+ }
+ }
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+ DisableHostAccess(psMMUContext);
+#endif
+
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+ if (bInvalidateDirectoryCache)
+ {
+
+
+
+
+ MMU_InvalidateDirectoryCache(psMMUContext->psDevInfo);
+ }
+#endif
+}
+
+
+static IMG_VOID
+MMU_UnmapPagesAndFreePTs (MMU_HEAP *psMMUHeap,
+ IMG_DEV_VIRTADDR sDevVAddr,
+ IMG_UINT32 ui32PageCount,
+ IMG_HANDLE hUniqueTag)
+{
+ IMG_DEV_VIRTADDR sTmpDevVAddr;
+ IMG_UINT32 i;
+ IMG_UINT32 ui32PDIndex;
+ IMG_UINT32 ui32PTIndex;
+ IMG_UINT32 *pui32Tmp;
+ IMG_BOOL bInvalidateDirectoryCache = IMG_FALSE;
+
+#if !defined (PDUMP)
+ PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif
+
+ sTmpDevVAddr = sDevVAddr;
+
+ for(i=0; i<ui32PageCount; i++)
+ {
+ MMU_PT_INFO **ppsPTInfoList;
+
+
+ ui32PDIndex = sTmpDevVAddr.uiAddr >> psMMUHeap->ui32PDShift;
+
+
+ ppsPTInfoList = &psMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
+
+ {
+
+ ui32PTIndex = (sTmpDevVAddr.uiAddr & psMMUHeap->ui32PTMask) >> psMMUHeap->ui32PTShift;
+
+
+ if (!ppsPTInfoList[0])
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "MMU_UnmapPagesAndFreePTs: Invalid PT for alloc at VAddr:0x%08X (VaddrIni:0x%08X AllocPage:%u) PDIdx:%u PTIdx:%u",sTmpDevVAddr.uiAddr, sDevVAddr.uiAddr,i, ui32PDIndex, ui32PTIndex ));
+
+
+ sTmpDevVAddr.uiAddr += psMMUHeap->ui32DataPageSize;
+
+
+ continue;
+ }
+
+
+ pui32Tmp = (IMG_UINT32*)ppsPTInfoList[0]->PTPageCpuVAddr;
+
+
+ if (!pui32Tmp)
+ {
+ continue;
+ }
+
+ CheckPT(ppsPTInfoList[0]);
+
+
+ if (pui32Tmp[ui32PTIndex] & SGX_MMU_PTE_VALID)
+ {
+ ppsPTInfoList[0]->ui32ValidPTECount--;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "MMU_UnmapPagesAndFreePTs: Page is already invalid for alloc at VAddr:0x%08X (VAddrIni:0x%08X AllocPage:%u) PDIdx:%u PTIdx:%u",sTmpDevVAddr.uiAddr, sDevVAddr.uiAddr,i, ui32PDIndex, ui32PTIndex ));
+ }
+
+
+ PVR_ASSERT((IMG_INT32)ppsPTInfoList[0]->ui32ValidPTECount >= 0);
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+ pui32Tmp[ui32PTIndex] = (psMMUHeap->psMMUContext->psDevInfo->sDummyDataDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PTE_VALID;
+#else
+
+ pui32Tmp[ui32PTIndex] = 0;
+#endif
+
+ CheckPT(ppsPTInfoList[0]);
+ }
+
+
+
+ if (ppsPTInfoList[0] && ppsPTInfoList[0]->ui32ValidPTECount == 0)
+ {
+ _DeferredFreePageTable(psMMUHeap, ui32PDIndex - psMMUHeap->ui32PDBaseIndex, IMG_TRUE);
+ bInvalidateDirectoryCache = IMG_TRUE;
+ }
+
+
+ sTmpDevVAddr.uiAddr += psMMUHeap->ui32DataPageSize;
+ }
+
+ if(bInvalidateDirectoryCache)
+ {
+ MMU_InvalidateDirectoryCache(psMMUHeap->psMMUContext->psDevInfo);
+ }
+ else
+ {
+ MMU_InvalidatePageTableCache(psMMUHeap->psMMUContext->psDevInfo);
+ }
+
+#if defined(PDUMP)
+ MMU_PDumpPageTables(psMMUHeap,
+ sDevVAddr,
+ psMMUHeap->ui32DataPageSize * ui32PageCount,
+ IMG_TRUE,
+ hUniqueTag);
+#endif
+}
+
+
+static IMG_VOID MMU_FreePageTables(IMG_PVOID pvMMUHeap,
+ IMG_SIZE_T ui32Start,
+ IMG_SIZE_T ui32End,
+ IMG_HANDLE hUniqueTag)
+{
+ MMU_HEAP *pMMUHeap = (MMU_HEAP*)pvMMUHeap;
+ IMG_DEV_VIRTADDR Start;
+
+ Start.uiAddr = ui32Start;
+
+ MMU_UnmapPagesAndFreePTs(pMMUHeap, Start, (ui32End - ui32Start) >> pMMUHeap->ui32PTShift, hUniqueTag);
+}
+
+MMU_HEAP *
+MMU_Create (MMU_CONTEXT *psMMUContext,
+ DEV_ARENA_DESCRIPTOR *psDevArena,
+ RA_ARENA **ppsVMArena,
+ PDUMP_MMU_ATTRIB **ppsMMUAttrib)
+{
+ MMU_HEAP *pMMUHeap;
+ IMG_UINT32 ui32ScaleSize;
+
+ PVR_UNREFERENCED_PARAMETER(ppsMMUAttrib);
+
+ PVR_ASSERT (psDevArena != IMG_NULL);
+
+ if (psDevArena == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Create: invalid parameter"));
+ return IMG_NULL;
+ }
+
+ OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof (MMU_HEAP),
+ (IMG_VOID **)&pMMUHeap, IMG_NULL,
+ "MMU Heap");
+ if (pMMUHeap == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Create: ERROR call to OSAllocMem failed"));
+ return IMG_NULL;
+ }
+
+ pMMUHeap->psMMUContext = psMMUContext;
+ pMMUHeap->psDevArena = psDevArena;
+
+
+
+
+ switch(pMMUHeap->psDevArena->ui32DataPageSize)
+ {
+ case 0x1000:
+ ui32ScaleSize = 0;
+ pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_4K;
+ break;
+#if defined(SGX_FEATURE_VARIABLE_MMU_PAGE_SIZE)
+ case 0x4000:
+ ui32ScaleSize = 2;
+ pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_16K;
+ break;
+ case 0x10000:
+ ui32ScaleSize = 4;
+ pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_64K;
+ break;
+ case 0x40000:
+ ui32ScaleSize = 6;
+ pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_256K;
+ break;
+ case 0x100000:
+ ui32ScaleSize = 8;
+ pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_1M;
+ break;
+ case 0x400000:
+ ui32ScaleSize = 10;
+ pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_4M;
+ break;
+#endif
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Create: invalid data page size"));
+ goto ErrorFreeHeap;
+ }
+
+
+ pMMUHeap->ui32DataPageSize = psDevArena->ui32DataPageSize;
+ pMMUHeap->ui32DataPageBitWidth = SGX_MMU_PAGE_SHIFT + ui32ScaleSize;
+ pMMUHeap->ui32DataPageMask = pMMUHeap->ui32DataPageSize - 1;
+
+ pMMUHeap->ui32PTShift = pMMUHeap->ui32DataPageBitWidth;
+ pMMUHeap->ui32PTBitWidth = SGX_MMU_PT_SHIFT - ui32ScaleSize;
+ pMMUHeap->ui32PTMask = SGX_MMU_PT_MASK & (SGX_MMU_PT_MASK<<ui32ScaleSize);
+ pMMUHeap->ui32PTSize = (IMG_UINT32)(1UL<<pMMUHeap->ui32PTBitWidth) * sizeof(IMG_UINT32);
+
+ if(pMMUHeap->ui32PTSize < 4 * sizeof(IMG_UINT32))
+ {
+ pMMUHeap->ui32PTSize = 4 * sizeof(IMG_UINT32);
+ }
+ pMMUHeap->ui32PTECount = pMMUHeap->ui32PTSize >> 2;
+
+
+ pMMUHeap->ui32PDShift = pMMUHeap->ui32PTBitWidth + pMMUHeap->ui32PTShift;
+ pMMUHeap->ui32PDBitWidth = SGX_FEATURE_ADDRESS_SPACE_SIZE - pMMUHeap->ui32PTBitWidth - pMMUHeap->ui32DataPageBitWidth;
+ pMMUHeap->ui32PDMask = SGX_MMU_PD_MASK & (SGX_MMU_PD_MASK>>(32-SGX_FEATURE_ADDRESS_SPACE_SIZE));
+
+
+
+
+/* External system cache violates this rule */
+#if !defined (SUPPORT_EXTERNAL_SYSTEM_CACHE)
+
+ if(psDevArena->BaseDevVAddr.uiAddr > (pMMUHeap->ui32DataPageMask | pMMUHeap->ui32PTMask))
+ {
+
+
+
+ PVR_ASSERT ((psDevArena->BaseDevVAddr.uiAddr
+ & (pMMUHeap->ui32DataPageMask
+ | pMMUHeap->ui32PTMask)) == 0);
+ }
+
+#endif
+
+ pMMUHeap->ui32PTETotal = pMMUHeap->psDevArena->ui32Size >> pMMUHeap->ui32PTShift;
+
+
+ pMMUHeap->ui32PDBaseIndex = (pMMUHeap->psDevArena->BaseDevVAddr.uiAddr & pMMUHeap->ui32PDMask) >> pMMUHeap->ui32PDShift;
+
+
+
+
+ pMMUHeap->ui32PageTableCount = (pMMUHeap->ui32PTETotal + pMMUHeap->ui32PTECount - 1)
+ >> pMMUHeap->ui32PTBitWidth;
+
+
+ pMMUHeap->psVMArena = RA_Create(psDevArena->pszName,
+ psDevArena->BaseDevVAddr.uiAddr,
+ psDevArena->ui32Size,
+ IMG_NULL,
+ MAX(HOST_PAGESIZE(), pMMUHeap->ui32DataPageSize),
+ IMG_NULL,
+ IMG_NULL,
+ &MMU_FreePageTables,
+ pMMUHeap);
+
+ if (pMMUHeap->psVMArena == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Create: ERROR call to RA_Create failed"));
+ goto ErrorFreePagetables;
+ }
+
+#if defined(PDUMP)
+
+ MMU_SetPDumpAttribs(&pMMUHeap->sMMUAttrib,
+ psMMUContext->psDeviceNode,
+ pMMUHeap->ui32DataPageMask,
+ pMMUHeap->ui32PTSize);
+ *ppsMMUAttrib = &pMMUHeap->sMMUAttrib;
+
+ PDUMPCOMMENT("Create MMU device from arena %s (Size == 0x%x, DataPageSize == 0x%x, BaseDevVAddr == 0x%x)",
+ psDevArena->pszName,
+ psDevArena->ui32Size,
+ pMMUHeap->ui32DataPageSize,
+ psDevArena->BaseDevVAddr.uiAddr);
+#endif
+
+#if 0
+
+ if(psDevArena->ui32HeapID == SGX_TILED_HEAP_ID)
+ {
+ IMG_UINT32 ui32RegVal;
+ IMG_UINT32 ui32XTileStride;
+
+
+
+
+
+
+ ui32XTileStride = 2;
+
+ ui32RegVal = (EUR_CR_BIF_TILE0_MIN_ADDRESS_MASK
+ & ((psDevArena->BaseDevVAddr.uiAddr>>20)
+ << EUR_CR_BIF_TILE0_MIN_ADDRESS_SHIFT))
+ |(EUR_CR_BIF_TILE0_MAX_ADDRESS_MASK
+ & (((psDevArena->BaseDevVAddr.uiAddr+psDevArena->ui32Size)>>20)
+ << EUR_CR_BIF_TILE0_MAX_ADDRESS_SHIFT))
+ |(EUR_CR_BIF_TILE0_CFG_MASK
+ & (((ui32XTileStride<<1)|8) << EUR_CR_BIF_TILE0_CFG_SHIFT));
+ PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_TILE0, ui32RegVal);
+ }
+#endif
+
+
+
+ *ppsVMArena = pMMUHeap->psVMArena;
+
+ return pMMUHeap;
+
+
+ErrorFreePagetables:
+ _DeferredFreePageTables (pMMUHeap);
+
+ErrorFreeHeap:
+ OSFreeMem (PVRSRV_OS_PAGEABLE_HEAP, sizeof(MMU_HEAP), pMMUHeap, IMG_NULL);
+
+
+ return IMG_NULL;
+}
+
+IMG_VOID
+MMU_Delete (MMU_HEAP *pMMUHeap)
+{
+ if (pMMUHeap != IMG_NULL)
+ {
+ PVR_DPF ((PVR_DBG_MESSAGE, "MMU_Delete"));
+
+ if(pMMUHeap->psVMArena)
+ {
+ RA_Delete (pMMUHeap->psVMArena);
+ }
+
+#if defined(PDUMP)
+ PDUMPCOMMENT("Delete MMU device from arena %s (BaseDevVAddr == 0x%x, PT count for deferred free == 0x%x)",
+ pMMUHeap->psDevArena->pszName,
+ pMMUHeap->psDevArena->BaseDevVAddr.uiAddr,
+ pMMUHeap->ui32PageTableCount);
+#endif
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+ EnableHostAccess(pMMUHeap->psMMUContext);
+#endif
+ _DeferredFreePageTables (pMMUHeap);
+#ifdef SUPPORT_SGX_MMU_BYPASS
+ DisableHostAccess(pMMUHeap->psMMUContext);
+#endif
+
+ OSFreeMem (PVRSRV_OS_PAGEABLE_HEAP, sizeof(MMU_HEAP), pMMUHeap, IMG_NULL);
+
+ }
+}
+
+IMG_BOOL
+MMU_Alloc (MMU_HEAP *pMMUHeap,
+ IMG_SIZE_T uSize,
+ IMG_SIZE_T *pActualSize,
+ IMG_UINT32 uFlags,
+ IMG_UINT32 uDevVAddrAlignment,
+ IMG_DEV_VIRTADDR *psDevVAddr)
+{
+ IMG_BOOL bStatus;
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "MMU_Alloc: uSize=0x%x, flags=0x%x, align=0x%x",
+ uSize, uFlags, uDevVAddrAlignment));
+
+
+
+ if((uFlags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR) == 0)
+ {
+ IMG_UINTPTR_T uiAddr;
+
+ bStatus = RA_Alloc (pMMUHeap->psVMArena,
+ uSize,
+ pActualSize,
+ IMG_NULL,
+ 0,
+ uDevVAddrAlignment,
+ 0,
+ &uiAddr);
+ if(!bStatus)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"MMU_Alloc: RA_Alloc of VMArena failed"));
+ PVR_DPF((PVR_DBG_ERROR,"MMU_Alloc: Alloc of DevVAddr failed from heap %s ID%d",
+ pMMUHeap->psDevArena->pszName,
+ pMMUHeap->psDevArena->ui32HeapID));
+ return bStatus;
+ }
+
+ psDevVAddr->uiAddr = IMG_CAST_TO_DEVVADDR_UINT(uiAddr);
+ }
+
+ #ifdef SUPPORT_SGX_MMU_BYPASS
+ EnableHostAccess(pMMUHeap->psMMUContext);
+ #endif
+
+
+ bStatus = _DeferredAllocPagetables(pMMUHeap, *psDevVAddr, uSize);
+
+ #ifdef SUPPORT_SGX_MMU_BYPASS
+ DisableHostAccess(pMMUHeap->psMMUContext);
+ #endif
+
+ if (!bStatus)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"MMU_Alloc: _DeferredAllocPagetables failed"));
+ PVR_DPF((PVR_DBG_ERROR,"MMU_Alloc: Failed to alloc pagetable(s) for DevVAddr 0x%8.8x from heap %s ID%d",
+ psDevVAddr->uiAddr,
+ pMMUHeap->psDevArena->pszName,
+ pMMUHeap->psDevArena->ui32HeapID));
+ if((uFlags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR) == 0)
+ {
+
+ RA_Free (pMMUHeap->psVMArena, psDevVAddr->uiAddr, IMG_FALSE);
+ }
+ }
+
+ return bStatus;
+}
+
+IMG_VOID
+MMU_Free (MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR DevVAddr, IMG_UINT32 ui32Size)
+{
+ PVR_ASSERT (pMMUHeap != IMG_NULL);
+
+ if (pMMUHeap == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_Free: invalid parameter"));
+ return;
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE, "MMU_Free: Freeing DevVAddr 0x%08X from heap %s ID%d",
+ DevVAddr.uiAddr,
+ pMMUHeap->psDevArena->pszName,
+ pMMUHeap->psDevArena->ui32HeapID));
+
+ if((DevVAddr.uiAddr >= pMMUHeap->psDevArena->BaseDevVAddr.uiAddr) &&
+ (DevVAddr.uiAddr + ui32Size <= pMMUHeap->psDevArena->BaseDevVAddr.uiAddr + pMMUHeap->psDevArena->ui32Size))
+ {
+ RA_Free (pMMUHeap->psVMArena, DevVAddr.uiAddr, IMG_TRUE);
+ return;
+ }
+
+ PVR_DPF((PVR_DBG_ERROR,"MMU_Free: Couldn't free DevVAddr %08X from heap %s ID%d (not in range of heap))",
+ DevVAddr.uiAddr,
+ pMMUHeap->psDevArena->pszName,
+ pMMUHeap->psDevArena->ui32HeapID));
+}
+
+IMG_VOID
+MMU_Enable (MMU_HEAP *pMMUHeap)
+{
+ PVR_UNREFERENCED_PARAMETER(pMMUHeap);
+
+}
+
+IMG_VOID
+MMU_Disable (MMU_HEAP *pMMUHeap)
+{
+ PVR_UNREFERENCED_PARAMETER(pMMUHeap);
+
+}
+
+#if defined(PDUMP)
+static IMG_VOID
+MMU_PDumpPageTables (MMU_HEAP *pMMUHeap,
+ IMG_DEV_VIRTADDR DevVAddr,
+ IMG_SIZE_T uSize,
+ IMG_BOOL bForUnmap,
+ IMG_HANDLE hUniqueTag)
+{
+ IMG_UINT32 ui32NumPTEntries;
+ IMG_UINT32 ui32PTIndex;
+ IMG_UINT32 *pui32PTEntry;
+
+ MMU_PT_INFO **ppsPTInfoList;
+ IMG_UINT32 ui32PDIndex;
+ IMG_UINT32 ui32PTDumpCount;
+
+
+ ui32NumPTEntries = (uSize + pMMUHeap->ui32DataPageMask) >> pMMUHeap->ui32PTShift;
+
+
+ ui32PDIndex = DevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
+
+
+ ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
+
+
+ ui32PTIndex = (DevVAddr.uiAddr & pMMUHeap->ui32PTMask) >> pMMUHeap->ui32PTShift;
+
+
+ PDUMPCOMMENT("Page table mods (num entries == %08X) %s", ui32NumPTEntries, bForUnmap ? "(for unmap)" : "");
+
+
+ while(ui32NumPTEntries > 0)
+ {
+ MMU_PT_INFO* psPTInfo = *ppsPTInfoList++;
+
+ if(ui32NumPTEntries <= pMMUHeap->ui32PTECount - ui32PTIndex)
+ {
+ ui32PTDumpCount = ui32NumPTEntries;
+ }
+ else
+ {
+ ui32PTDumpCount = pMMUHeap->ui32PTECount - ui32PTIndex;
+ }
+
+ if (psPTInfo)
+ {
+ IMG_UINT32 ui32Flags = 0;
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+ ui32Flags |= ( MMU_IsHeapShared(pMMUHeap) ) ? PDUMP_FLAGS_PERSISTENT : 0;
+#endif
+ pui32PTEntry = (IMG_UINT32*)psPTInfo->PTPageCpuVAddr;
+ PDUMPMEMPTENTRIES(&pMMUHeap->sMMUAttrib, psPTInfo->hPTPageOSMemHandle, (IMG_VOID *) &pui32PTEntry[ui32PTIndex], ui32PTDumpCount * sizeof(IMG_UINT32), ui32Flags, IMG_FALSE, PDUMP_PT_UNIQUETAG, hUniqueTag);
+ }
+
+
+ ui32NumPTEntries -= ui32PTDumpCount;
+
+
+ ui32PTIndex = 0;
+ }
+
+ PDUMPCOMMENT("Finished page table mods %s", bForUnmap ? "(for unmap)" : "");
+}
+#endif
+
+
+static IMG_VOID
+MMU_MapPage (MMU_HEAP *pMMUHeap,
+ IMG_DEV_VIRTADDR DevVAddr,
+ IMG_DEV_PHYADDR DevPAddr,
+ IMG_UINT32 ui32MemFlags)
+{
+ IMG_UINT32 ui32Index;
+ IMG_UINT32 *pui32Tmp;
+ IMG_UINT32 ui32MMUFlags = 0;
+ MMU_PT_INFO **ppsPTInfoList;
+
+
+ PVR_ASSERT((DevPAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0);
+
+
+
+ if(((PVRSRV_MEM_READ|PVRSRV_MEM_WRITE) & ui32MemFlags) == (PVRSRV_MEM_READ|PVRSRV_MEM_WRITE))
+ {
+
+ ui32MMUFlags = 0;
+ }
+ else if(PVRSRV_MEM_READ & ui32MemFlags)
+ {
+
+ ui32MMUFlags |= SGX_MMU_PTE_READONLY;
+ }
+ else if(PVRSRV_MEM_WRITE & ui32MemFlags)
+ {
+
+ ui32MMUFlags |= SGX_MMU_PTE_WRITEONLY;
+ }
+
+
+ if(PVRSRV_MEM_CACHE_CONSISTENT & ui32MemFlags)
+ {
+ ui32MMUFlags |= SGX_MMU_PTE_CACHECONSISTENT;
+ }
+
+#if !defined(FIX_HW_BRN_25503)
+
+ if(PVRSRV_MEM_EDM_PROTECT & ui32MemFlags)
+ {
+ ui32MMUFlags |= SGX_MMU_PTE_EDMPROTECT;
+ }
+#endif
+
+
+
+
+
+ ui32Index = DevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
+
+
+ ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32Index];
+
+ CheckPT(ppsPTInfoList[0]);
+
+
+ ui32Index = (DevVAddr.uiAddr & pMMUHeap->ui32PTMask) >> pMMUHeap->ui32PTShift;
+
+
+ pui32Tmp = (IMG_UINT32*)ppsPTInfoList[0]->PTPageCpuVAddr;
+
+#if !defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+ {
+ IMG_UINT32 uTmp = pui32Tmp[ui32Index];
+
+
+ if (uTmp & SGX_MMU_PTE_VALID)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_MapPage: Page is already valid for alloc at VAddr:0x%08X PDIdx:%u PTIdx:%u",
+ DevVAddr.uiAddr,
+ DevVAddr.uiAddr >> pMMUHeap->ui32PDShift,
+ ui32Index ));
+ PVR_DPF((PVR_DBG_ERROR, "MMU_MapPage: Page table entry value: 0x%08X", uTmp));
+ PVR_DPF((PVR_DBG_ERROR, "MMU_MapPage: Physical page to map: 0x%08X", DevPAddr.uiAddr));
+ }
+
+ PVR_ASSERT((uTmp & SGX_MMU_PTE_VALID) == 0);
+ }
+#endif
+
+
+ ppsPTInfoList[0]->ui32ValidPTECount++;
+
+
+ pui32Tmp[ui32Index] = ((DevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+ & ((~pMMUHeap->ui32DataPageMask)>>SGX_MMU_PTE_ADDR_ALIGNSHIFT))
+ | SGX_MMU_PTE_VALID
+ | ui32MMUFlags;
+
+ CheckPT(ppsPTInfoList[0]);
+}
+
+
+IMG_VOID
+MMU_MapScatter (MMU_HEAP *pMMUHeap,
+ IMG_DEV_VIRTADDR DevVAddr,
+ IMG_SYS_PHYADDR *psSysAddr,
+ IMG_SIZE_T uSize,
+ IMG_UINT32 ui32MemFlags,
+ IMG_HANDLE hUniqueTag)
+{
+#if defined(PDUMP)
+ IMG_DEV_VIRTADDR MapBaseDevVAddr;
+#endif
+ IMG_UINT32 uCount, i;
+ IMG_DEV_PHYADDR DevPAddr;
+
+ PVR_ASSERT (pMMUHeap != IMG_NULL);
+
+#if defined(PDUMP)
+ MapBaseDevVAddr = DevVAddr;
+#else
+ PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif
+
+ for (i=0, uCount=0; uCount<uSize; i++, uCount+=pMMUHeap->ui32DataPageSize)
+ {
+ IMG_SYS_PHYADDR sSysAddr;
+
+ sSysAddr = psSysAddr[i];
+
+
+
+ PVR_ASSERT((sSysAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0);
+
+ DevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysAddr);
+
+ MMU_MapPage (pMMUHeap, DevVAddr, DevPAddr, ui32MemFlags);
+ DevVAddr.uiAddr += pMMUHeap->ui32DataPageSize;
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "MMU_MapScatter: devVAddr=%08X, SysAddr=%08X, size=0x%x/0x%x",
+ DevVAddr.uiAddr, sSysAddr.uiAddr, uCount, uSize));
+ }
+
+#if defined(PDUMP)
+ MMU_PDumpPageTables (pMMUHeap, MapBaseDevVAddr, uSize, IMG_FALSE, hUniqueTag);
+#endif
+}
+
+IMG_VOID
+MMU_MapPages (MMU_HEAP *pMMUHeap,
+ IMG_DEV_VIRTADDR DevVAddr,
+ IMG_SYS_PHYADDR SysPAddr,
+ IMG_SIZE_T uSize,
+ IMG_UINT32 ui32MemFlags,
+ IMG_HANDLE hUniqueTag)
+{
+ IMG_DEV_PHYADDR DevPAddr;
+#if defined(PDUMP)
+ IMG_DEV_VIRTADDR MapBaseDevVAddr;
+#endif
+ IMG_UINT32 uCount;
+ IMG_UINT32 ui32VAdvance;
+ IMG_UINT32 ui32PAdvance;
+
+ PVR_ASSERT (pMMUHeap != IMG_NULL);
+
+ PVR_DPF ((PVR_DBG_MESSAGE, "MMU_MapPages: heap:%s, heap_id:%d devVAddr=%08X, SysPAddr=%08X, size=0x%x",
+ pMMUHeap->psDevArena->pszName,
+ pMMUHeap->psDevArena->ui32HeapID,
+ DevVAddr.uiAddr,
+ SysPAddr.uiAddr,
+ uSize));
+
+
+ ui32VAdvance = pMMUHeap->ui32DataPageSize;
+ ui32PAdvance = pMMUHeap->ui32DataPageSize;
+
+#if defined(PDUMP)
+ MapBaseDevVAddr = DevVAddr;
+#else
+ PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif
+
+ DevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, SysPAddr);
+
+
+ PVR_ASSERT((DevPAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0);
+
+#if defined(FIX_HW_BRN_23281)
+ if(ui32MemFlags & PVRSRV_MEM_INTERLEAVED)
+ {
+ ui32VAdvance *= 2;
+ }
+#endif
+
+
+
+
+ if(ui32MemFlags & PVRSRV_MEM_DUMMY)
+ {
+ ui32PAdvance = 0;
+ }
+
+ for (uCount=0; uCount<uSize; uCount+=ui32VAdvance)
+ {
+ MMU_MapPage (pMMUHeap, DevVAddr, DevPAddr, ui32MemFlags);
+ DevVAddr.uiAddr += ui32VAdvance;
+ DevPAddr.uiAddr += ui32PAdvance;
+ }
+
+#if defined(PDUMP)
+ MMU_PDumpPageTables (pMMUHeap, MapBaseDevVAddr, uSize, IMG_FALSE, hUniqueTag);
+#endif
+}
+
+IMG_VOID
+MMU_MapShadow (MMU_HEAP *pMMUHeap,
+ IMG_DEV_VIRTADDR MapBaseDevVAddr,
+ IMG_SIZE_T uByteSize,
+ IMG_CPU_VIRTADDR CpuVAddr,
+ IMG_HANDLE hOSMemHandle,
+ IMG_DEV_VIRTADDR *pDevVAddr,
+ IMG_UINT32 ui32MemFlags,
+ IMG_HANDLE hUniqueTag)
+{
+ IMG_UINT32 i;
+ IMG_UINT32 uOffset = 0;
+ IMG_DEV_VIRTADDR MapDevVAddr;
+ IMG_UINT32 ui32VAdvance;
+ IMG_UINT32 ui32PAdvance;
+
+#if !defined (PDUMP)
+ PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "MMU_MapShadow: DevVAddr:%08X, Bytes:0x%x, CPUVAddr:%08X",
+ MapBaseDevVAddr.uiAddr,
+ uByteSize,
+ (IMG_UINTPTR_T)CpuVAddr));
+
+
+ ui32VAdvance = pMMUHeap->ui32DataPageSize;
+ ui32PAdvance = pMMUHeap->ui32DataPageSize;
+
+
+ PVR_ASSERT(((IMG_UINTPTR_T)CpuVAddr & (SGX_MMU_PAGE_SIZE - 1)) == 0);
+ PVR_ASSERT(((IMG_UINT32)uByteSize & pMMUHeap->ui32DataPageMask) == 0);
+ pDevVAddr->uiAddr = MapBaseDevVAddr.uiAddr;
+
+#if defined(FIX_HW_BRN_23281)
+ if(ui32MemFlags & PVRSRV_MEM_INTERLEAVED)
+ {
+ ui32VAdvance *= 2;
+ }
+#endif
+
+
+
+
+ if(ui32MemFlags & PVRSRV_MEM_DUMMY)
+ {
+ ui32PAdvance = 0;
+ }
+
+
+ MapDevVAddr = MapBaseDevVAddr;
+ for (i=0; i<uByteSize; i+=ui32VAdvance)
+ {
+ IMG_CPU_PHYADDR CpuPAddr;
+ IMG_DEV_PHYADDR DevPAddr;
+
+ if(CpuVAddr)
+ {
+ CpuPAddr = OSMapLinToCPUPhys (hOSMemHandle,
+ (IMG_VOID *)((IMG_UINTPTR_T)CpuVAddr + uOffset));
+ }
+ else
+ {
+ CpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, uOffset);
+ }
+ DevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, CpuPAddr);
+
+
+ PVR_ASSERT((DevPAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0);
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "Offset=0x%x: CpuVAddr=%08X, CpuPAddr=%08X, DevVAddr=%08X, DevPAddr=%08X",
+ uOffset,
+ (IMG_UINTPTR_T)CpuVAddr + uOffset,
+ CpuPAddr.uiAddr,
+ MapDevVAddr.uiAddr,
+ DevPAddr.uiAddr));
+
+ MMU_MapPage (pMMUHeap, MapDevVAddr, DevPAddr, ui32MemFlags);
+
+
+ MapDevVAddr.uiAddr += ui32VAdvance;
+ uOffset += ui32PAdvance;
+ }
+
+#if defined(PDUMP)
+ MMU_PDumpPageTables (pMMUHeap, MapBaseDevVAddr, uByteSize, IMG_FALSE, hUniqueTag);
+#endif
+}
+
+
+IMG_VOID
+MMU_UnmapPages (MMU_HEAP *psMMUHeap,
+ IMG_DEV_VIRTADDR sDevVAddr,
+ IMG_UINT32 ui32PageCount,
+ IMG_HANDLE hUniqueTag)
+{
+ IMG_UINT32 uPageSize = psMMUHeap->ui32DataPageSize;
+ IMG_DEV_VIRTADDR sTmpDevVAddr;
+ IMG_UINT32 i;
+ IMG_UINT32 ui32PDIndex;
+ IMG_UINT32 ui32PTIndex;
+ IMG_UINT32 *pui32Tmp;
+
+#if !defined (PDUMP)
+ PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif
+
+
+ sTmpDevVAddr = sDevVAddr;
+
+ for(i=0; i<ui32PageCount; i++)
+ {
+ MMU_PT_INFO **ppsPTInfoList;
+
+
+ ui32PDIndex = sTmpDevVAddr.uiAddr >> psMMUHeap->ui32PDShift;
+
+
+ ppsPTInfoList = &psMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
+
+
+ ui32PTIndex = (sTmpDevVAddr.uiAddr & psMMUHeap->ui32PTMask) >> psMMUHeap->ui32PTShift;
+
+
+ if (!ppsPTInfoList[0])
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_UnmapPages: ERROR Invalid PT for alloc at VAddr:0x%08X (VaddrIni:0x%08X AllocPage:%u) PDIdx:%u PTIdx:%u",
+ sTmpDevVAddr.uiAddr,
+ sDevVAddr.uiAddr,
+ i,
+ ui32PDIndex,
+ ui32PTIndex));
+
+
+ sTmpDevVAddr.uiAddr += uPageSize;
+
+
+ continue;
+ }
+
+ CheckPT(ppsPTInfoList[0]);
+
+
+ pui32Tmp = (IMG_UINT32*)ppsPTInfoList[0]->PTPageCpuVAddr;
+
+
+ if (pui32Tmp[ui32PTIndex] & SGX_MMU_PTE_VALID)
+ {
+ ppsPTInfoList[0]->ui32ValidPTECount--;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_UnmapPages: Page is already invalid for alloc at VAddr:0x%08X (VAddrIni:0x%08X AllocPage:%u) PDIdx:%u PTIdx:%u",
+ sTmpDevVAddr.uiAddr,
+ sDevVAddr.uiAddr,
+ i,
+ ui32PDIndex,
+ ui32PTIndex));
+ PVR_DPF((PVR_DBG_ERROR, "MMU_UnmapPages: Page table entry value: 0x%08X", pui32Tmp[ui32PTIndex]));
+ }
+
+
+ PVR_ASSERT((IMG_INT32)ppsPTInfoList[0]->ui32ValidPTECount >= 0);
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+ pui32Tmp[ui32PTIndex] = (psMMUHeap->psMMUContext->psDevInfo->sDummyDataDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PTE_VALID;
+#else
+
+ pui32Tmp[ui32PTIndex] = 0;
+#endif
+
+ CheckPT(ppsPTInfoList[0]);
+
+
+ sTmpDevVAddr.uiAddr += uPageSize;
+ }
+
+ MMU_InvalidatePageTableCache(psMMUHeap->psMMUContext->psDevInfo);
+
+#if defined(PDUMP)
+ MMU_PDumpPageTables (psMMUHeap, sDevVAddr, uPageSize*ui32PageCount, IMG_TRUE, hUniqueTag);
+#endif
+}
+
+
+IMG_DEV_PHYADDR
+MMU_GetPhysPageAddr(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR sDevVPageAddr)
+{
+ IMG_UINT32 *pui32PageTable;
+ IMG_UINT32 ui32Index;
+ IMG_DEV_PHYADDR sDevPAddr;
+ MMU_PT_INFO **ppsPTInfoList;
+
+
+ ui32Index = sDevVPageAddr.uiAddr >> pMMUHeap->ui32PDShift;
+
+
+ ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32Index];
+ if (!ppsPTInfoList[0])
+ {
+ PVR_DPF((PVR_DBG_ERROR,"MMU_GetPhysPageAddr: Not mapped in at 0x%08x", sDevVPageAddr.uiAddr));
+ sDevPAddr.uiAddr = 0;
+ return sDevPAddr;
+ }
+
+
+ ui32Index = (sDevVPageAddr.uiAddr & pMMUHeap->ui32PTMask) >> pMMUHeap->ui32PTShift;
+
+
+ pui32PageTable = (IMG_UINT32*)ppsPTInfoList[0]->PTPageCpuVAddr;
+
+
+ sDevPAddr.uiAddr = pui32PageTable[ui32Index];
+
+
+ sDevPAddr.uiAddr &= ~(pMMUHeap->ui32DataPageMask>>SGX_MMU_PTE_ADDR_ALIGNSHIFT);
+
+
+ sDevPAddr.uiAddr <<= SGX_MMU_PTE_ADDR_ALIGNSHIFT;
+
+ return sDevPAddr;
+}
+
+
+IMG_DEV_PHYADDR MMU_GetPDDevPAddr(MMU_CONTEXT *pMMUContext)
+{
+ return (pMMUContext->sPDDevPAddr);
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR SGXGetPhysPageAddrKM (IMG_HANDLE hDevMemHeap,
+ IMG_DEV_VIRTADDR sDevVAddr,
+ IMG_DEV_PHYADDR *pDevPAddr,
+ IMG_CPU_PHYADDR *pCpuPAddr)
+{
+ MMU_HEAP *pMMUHeap;
+ IMG_DEV_PHYADDR DevPAddr;
+
+
+
+ pMMUHeap = (MMU_HEAP*)BM_GetMMUHeap(hDevMemHeap);
+
+ DevPAddr = MMU_GetPhysPageAddr(pMMUHeap, sDevVAddr);
+ pCpuPAddr->uiAddr = DevPAddr.uiAddr;
+ pDevPAddr->uiAddr = DevPAddr.uiAddr;
+
+ return (pDevPAddr->uiAddr != 0) ? PVRSRV_OK : PVRSRV_ERROR_INVALID_PARAMS;
+}
+
+
+PVRSRV_ERROR SGXGetMMUPDAddrKM(IMG_HANDLE hDevCookie,
+ IMG_HANDLE hDevMemContext,
+ IMG_DEV_PHYADDR *psPDDevPAddr)
+{
+ if (!hDevCookie || !hDevMemContext || !psPDDevPAddr)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ *psPDDevPAddr = ((BM_CONTEXT*)hDevMemContext)->psMMUContext->sPDDevPAddr;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR MMU_BIFResetPDAlloc(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+ RA_ARENA *psLocalDevMemArena;
+ IMG_HANDLE hOSMemHandle = IMG_NULL;
+ IMG_BYTE *pui8MemBlock = IMG_NULL;
+ IMG_SYS_PHYADDR sMemBlockSysPAddr;
+ IMG_CPU_PHYADDR sMemBlockCpuPAddr;
+
+ SysAcquireData(&psSysData);
+
+ psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
+
+
+ if(psLocalDevMemArena == IMG_NULL)
+ {
+
+ eError = OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ 3 * SGX_MMU_PAGE_SIZE,
+ SGX_MMU_PAGE_SIZE,
+ (IMG_VOID **)&pui8MemBlock,
+ &hOSMemHandle);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_BIFResetPDAlloc: ERROR call to OSAllocPages failed"));
+ return eError;
+ }
+
+
+ if(pui8MemBlock)
+ {
+ sMemBlockCpuPAddr = OSMapLinToCPUPhys(hOSMemHandle,
+ pui8MemBlock);
+ }
+ else
+ {
+
+ sMemBlockCpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, 0);
+ }
+ }
+ else
+ {
+
+
+ if(RA_Alloc(psLocalDevMemArena,
+ 3 * SGX_MMU_PAGE_SIZE,
+ IMG_NULL,
+ IMG_NULL,
+ 0,
+ SGX_MMU_PAGE_SIZE,
+ 0,
+ &(sMemBlockSysPAddr.uiAddr)) != IMG_TRUE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_BIFResetPDAlloc: ERROR call to RA_Alloc failed"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+
+ sMemBlockCpuPAddr = SysSysPAddrToCpuPAddr(sMemBlockSysPAddr);
+ pui8MemBlock = OSMapPhysToLin(sMemBlockCpuPAddr,
+ SGX_MMU_PAGE_SIZE * 3,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ &hOSMemHandle);
+ if(!pui8MemBlock)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "MMU_BIFResetPDAlloc: ERROR failed to map page tables"));
+ return PVRSRV_ERROR_BAD_MAPPING;
+ }
+ }
+
+ psDevInfo->hBIFResetPDOSMemHandle = hOSMemHandle;
+ psDevInfo->sBIFResetPDDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sMemBlockCpuPAddr);
+ psDevInfo->sBIFResetPTDevPAddr.uiAddr = psDevInfo->sBIFResetPDDevPAddr.uiAddr + SGX_MMU_PAGE_SIZE;
+ psDevInfo->sBIFResetPageDevPAddr.uiAddr = psDevInfo->sBIFResetPTDevPAddr.uiAddr + SGX_MMU_PAGE_SIZE;
+
+
+ psDevInfo->pui32BIFResetPD = (IMG_UINT32 *)pui8MemBlock;
+ psDevInfo->pui32BIFResetPT = (IMG_UINT32 *)(pui8MemBlock + SGX_MMU_PAGE_SIZE);
+
+
+ OSMemSet(psDevInfo->pui32BIFResetPD, 0, SGX_MMU_PAGE_SIZE);
+ OSMemSet(psDevInfo->pui32BIFResetPT, 0, SGX_MMU_PAGE_SIZE);
+
+ OSMemSet(pui8MemBlock + (2 * SGX_MMU_PAGE_SIZE), 0xDB, SGX_MMU_PAGE_SIZE);
+
+ return PVRSRV_OK;
+}
+
+IMG_VOID MMU_BIFResetPDFree(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+ SYS_DATA *psSysData;
+ RA_ARENA *psLocalDevMemArena;
+ IMG_SYS_PHYADDR sPDSysPAddr;
+
+ SysAcquireData(&psSysData);
+
+ psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
+
+
+ if(psLocalDevMemArena == IMG_NULL)
+ {
+ OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ 3 * SGX_MMU_PAGE_SIZE,
+ psDevInfo->pui32BIFResetPD,
+ psDevInfo->hBIFResetPDOSMemHandle);
+ }
+ else
+ {
+ OSUnMapPhysToLin(psDevInfo->pui32BIFResetPD,
+ 3 * SGX_MMU_PAGE_SIZE,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ psDevInfo->hBIFResetPDOSMemHandle);
+
+ sPDSysPAddr = SysDevPAddrToSysPAddr(PVRSRV_DEVICE_TYPE_SGX, psDevInfo->sBIFResetPDDevPAddr);
+ RA_Free(psLocalDevMemArena, sPDSysPAddr.uiAddr, IMG_FALSE);
+ }
+}
+
+
+#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
+PVRSRV_ERROR WorkaroundBRN22997Alloc(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+ RA_ARENA *psLocalDevMemArena;
+ IMG_HANDLE hPTPageOSMemHandle = IMG_NULL;
+ IMG_HANDLE hPDPageOSMemHandle = IMG_NULL;
+ IMG_UINT32 *pui32PD = IMG_NULL;
+ IMG_UINT32 *pui32PT = IMG_NULL;
+ IMG_CPU_PHYADDR sCpuPAddr;
+ IMG_DEV_PHYADDR sPTDevPAddr;
+ IMG_DEV_PHYADDR sPDDevPAddr;
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+ IMG_UINT32 ui32PDOffset;
+ IMG_UINT32 ui32PTOffset;
+
+ psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+
+ SysAcquireData(&psSysData);
+
+ psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
+
+
+ if(psLocalDevMemArena == IMG_NULL)
+ {
+
+ eError = OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ SGX_MMU_PAGE_SIZE,
+ SGX_MMU_PAGE_SIZE,
+ (IMG_VOID **)&pui32PT,
+ &hPTPageOSMemHandle);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "WorkaroundBRN22997: ERROR call to OSAllocPages failed"));
+ return eError;
+ }
+ ui32PTOffset = 0;
+
+ eError = OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ SGX_MMU_PAGE_SIZE,
+ SGX_MMU_PAGE_SIZE,
+ (IMG_VOID **)&pui32PD,
+ &hPDPageOSMemHandle);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "WorkaroundBRN22997: ERROR call to OSAllocPages failed"));
+ return eError;
+ }
+ ui32PDOffset = 0;
+
+
+ if(pui32PT)
+ {
+ sCpuPAddr = OSMapLinToCPUPhys(hPTPageOSMemHandle,
+ pui32PT);
+ }
+ else
+ {
+
+ sCpuPAddr = OSMemHandleToCpuPAddr(hPTPageOSMemHandle, 0);
+ }
+ sPTDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+
+ if(pui32PD)
+ {
+ sCpuPAddr = OSMapLinToCPUPhys(hPDPageOSMemHandle,
+ pui32PD);
+ }
+ else
+ {
+
+ sCpuPAddr = OSMemHandleToCpuPAddr(hPDPageOSMemHandle, 0);
+ }
+ sPDDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+
+ }
+ else
+ {
+
+
+ if(RA_Alloc(psLocalDevMemArena,
+ SGX_MMU_PAGE_SIZE * 2,
+ IMG_NULL,
+ IMG_NULL,
+ 0,
+ SGX_MMU_PAGE_SIZE,
+ 0,
+ &(psDevInfo->sBRN22997SysPAddr.uiAddr))!= IMG_TRUE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "WorkaroundBRN22997: ERROR call to RA_Alloc failed"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+
+ sCpuPAddr = SysSysPAddrToCpuPAddr(psDevInfo->sBRN22997SysPAddr);
+ pui32PT = OSMapPhysToLin(sCpuPAddr,
+ SGX_MMU_PAGE_SIZE * 2,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ &hPTPageOSMemHandle);
+ if(!pui32PT)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "WorkaroundBRN22997: ERROR failed to map page tables"));
+ return PVRSRV_ERROR_BAD_MAPPING;
+ }
+ ui32PTOffset = 0;
+
+
+ sPTDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+
+ pui32PD = pui32PT + SGX_MMU_PAGE_SIZE/sizeof(IMG_UINT32);
+ ui32PDOffset = SGX_MMU_PAGE_SIZE;
+ hPDPageOSMemHandle = hPTPageOSMemHandle;
+ sPDDevPAddr.uiAddr = sPTDevPAddr.uiAddr + SGX_MMU_PAGE_SIZE;
+ }
+
+ OSMemSet(pui32PD, 0, SGX_MMU_PAGE_SIZE);
+ OSMemSet(pui32PT, 0, SGX_MMU_PAGE_SIZE);
+
+
+ PDUMPMALLOCPAGETABLE(&psDeviceNode->sDevId, hPDPageOSMemHandle, ui32PDOffset, pui32PD, SGX_MMU_PAGE_SIZE, 0, PDUMP_PD_UNIQUETAG);
+ PDUMPMALLOCPAGETABLE(&psDeviceNode->sDevId, hPTPageOSMemHandle, ui32PTOffset, pui32PT, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
+ PDUMPMEMPTENTRIES(&psDevInfo->sMMUAttrib, hPDPageOSMemHandle, pui32PD, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+ PDUMPMEMPTENTRIES(&psDevInfo->sMMUAttrib, hPTPageOSMemHandle, pui32PT, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PT_UNIQUETAG, PDUMP_PD_UNIQUETAG);
+
+ psDevInfo->hBRN22997PTPageOSMemHandle = hPTPageOSMemHandle;
+ psDevInfo->hBRN22997PDPageOSMemHandle = hPDPageOSMemHandle;
+ psDevInfo->sBRN22997PTDevPAddr = sPTDevPAddr;
+ psDevInfo->sBRN22997PDDevPAddr = sPDDevPAddr;
+ psDevInfo->pui32BRN22997PD = pui32PD;
+ psDevInfo->pui32BRN22997PT = pui32PT;
+
+ return PVRSRV_OK;
+}
+
+
+IMG_VOID WorkaroundBRN22997ReadHostPort(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+ IMG_UINT32 *pui32PD = psDevInfo->pui32BRN22997PD;
+ IMG_UINT32 *pui32PT = psDevInfo->pui32BRN22997PT;
+ IMG_UINT32 ui32PDIndex;
+ IMG_UINT32 ui32PTIndex;
+ IMG_DEV_VIRTADDR sDevVAddr;
+ volatile IMG_UINT32 *pui32HostPort;
+ IMG_UINT32 ui32BIFCtrl;
+
+
+
+
+ pui32HostPort = (volatile IMG_UINT32*)(((IMG_UINT8*)psDevInfo->pvHostPortBaseKM) + SYS_SGX_HOSTPORT_BRN23030_OFFSET);
+
+
+ sDevVAddr.uiAddr = SYS_SGX_HOSTPORT_BASE_DEVVADDR + SYS_SGX_HOSTPORT_BRN23030_OFFSET;
+
+ ui32PDIndex = (sDevVAddr.uiAddr & SGX_MMU_PD_MASK) >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT);
+ ui32PTIndex = (sDevVAddr.uiAddr & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT;
+
+
+ pui32PD[ui32PDIndex] = (psDevInfo->sBRN22997PTDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PDE_VALID;
+
+ pui32PT[ui32PTIndex] = (psDevInfo->sBRN22997PTDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PTE_VALID;
+
+ PDUMPMEMPTENTRIES(&psDevInfo->sMMUAttrib, psDevInfo->hBRN22997PDPageOSMemHandle, pui32PD, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+ PDUMPMEMPTENTRIES(&psDevInfo->sMMUAttrib, psDevInfo->hBRN22997PTPageOSMemHandle, pui32PT, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PT_UNIQUETAG, PDUMP_PD_UNIQUETAG);
+
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_DIR_LIST_BASE0,
+ psDevInfo->sBRN22997PDDevPAddr.uiAddr);
+ PDUMPPDREG(&psDevInfo->sMMUAttrib, EUR_CR_BIF_DIR_LIST_BASE0, psDevInfo->sBRN22997PDDevPAddr.uiAddr, PDUMP_PD_UNIQUETAG);
+
+
+ ui32BIFCtrl = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl | EUR_CR_BIF_CTRL_INVALDC_MASK);
+ PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32BIFCtrl | EUR_CR_BIF_CTRL_INVALDC_MASK);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl);
+ PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32BIFCtrl);
+
+
+ if (pui32HostPort)
+ {
+
+ IMG_UINT32 ui32Tmp;
+ ui32Tmp = *pui32HostPort;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,"Host Port not present for BRN22997 workaround"));
+ }
+
+
+
+
+
+
+
+ PDUMPCOMMENT("RDW :SGXMEM:v4:%08X\r\n", sDevVAddr.uiAddr);
+
+ PDUMPCOMMENT("SAB :SGXMEM:v4:%08X 4 0 hostport.bin", sDevVAddr.uiAddr);
+
+
+ pui32PD[ui32PDIndex] = 0;
+ pui32PT[ui32PTIndex] = 0;
+
+
+ PDUMPMEMPTENTRIES(&psDevInfo->sMMUAttrib, psDevInfo->hBRN22997PDPageOSMemHandle, pui32PD, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+ PDUMPMEMPTENTRIES(&psDevInfo->sMMUAttrib, psDevInfo->hBRN22997PTPageOSMemHandle, pui32PT, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PT_UNIQUETAG, PDUMP_PD_UNIQUETAG);
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl | EUR_CR_BIF_CTRL_INVALDC_MASK);
+ PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32BIFCtrl | EUR_CR_BIF_CTRL_INVALDC_MASK);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl);
+ PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32BIFCtrl);
+}
+
+
+IMG_VOID WorkaroundBRN22997Free(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ SYS_DATA *psSysData;
+ RA_ARENA *psLocalDevMemArena;
+ PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+
+
+ SysAcquireData(&psSysData);
+
+ psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
+
+ PDUMPFREEPAGETABLE(&psDeviceNode->sDevId, psDevInfo->hBRN22997PDPageOSMemHandle, psDevInfo->pui32BRN22997PD, SGX_MMU_PAGE_SIZE, 0, PDUMP_PD_UNIQUETAG);
+ PDUMPFREEPAGETABLE(&psDeviceNode->sDevId, psDevInfo->hBRN22997PTPageOSMemHandle, psDevInfo->pui32BRN22997PT, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
+
+
+ if(psLocalDevMemArena == IMG_NULL)
+ {
+ if (psDevInfo->pui32BRN22997PD != IMG_NULL)
+ {
+ OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ SGX_MMU_PAGE_SIZE,
+ psDevInfo->pui32BRN22997PD,
+ psDevInfo->hBRN22997PDPageOSMemHandle);
+ }
+
+ if (psDevInfo->pui32BRN22997PT != IMG_NULL)
+ {
+ OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ SGX_MMU_PAGE_SIZE,
+ psDevInfo->pui32BRN22997PT,
+ psDevInfo->hBRN22997PTPageOSMemHandle);
+ }
+ }
+ else
+ {
+ if (psDevInfo->pui32BRN22997PT != IMG_NULL)
+ {
+ OSUnMapPhysToLin(psDevInfo->pui32BRN22997PT,
+ SGX_MMU_PAGE_SIZE * 2,
+ PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
+ psDevInfo->hBRN22997PTPageOSMemHandle);
+
+
+ RA_Free(psLocalDevMemArena, psDevInfo->sBRN22997SysPAddr.uiAddr, IMG_FALSE);
+ }
+ }
+}
+#endif
+
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+PVRSRV_ERROR MMU_MapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ IMG_UINT32 *pui32PT;
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+ IMG_UINT32 ui32PDIndex;
+ IMG_UINT32 ui32PTIndex;
+#if defined(PDUMP)
+ PDUMP_MMU_ATTRIB sMMUAttrib;
+#endif
+
+ psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+
+#if defined(PDUMP)
+ sMMUAttrib = psDevInfo->sMMUAttrib;
+ MMU_SetPDumpAttribs(&sMMUAttrib, psDeviceNode,
+ SGX_MMU_PAGE_MASK,
+ SGX_MMU_PT_SIZE * sizeof(IMG_UINT32));
+#endif
+
+#if defined(PDUMP)
+ {
+ IMG_CHAR szScript[128];
+ sprintf(szScript, "MALLOC :EXTSYSCACHE:PA_%08X%08X %u %u 0x%08X\r\n", 0, psDevInfo->sExtSysCacheRegsDevPBase.uiAddr, SGX_MMU_PAGE_SIZE, SGX_MMU_PAGE_SIZE, psDevInfo->sExtSysCacheRegsDevPBase.uiAddr);
+ PDumpOSWriteString2(szScript, PDUMP_FLAGS_CONTINUOUS);
+ }
+#endif
+
+
+ ui32PDIndex = (SGX_EXT_SYSTEM_CACHE_REGS_DEVVADDR_BASE & SGX_MMU_PD_MASK) >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT);
+ ui32PTIndex = (SGX_EXT_SYSTEM_CACHE_REGS_DEVVADDR_BASE & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT;
+
+
+ pui32PT = (IMG_UINT32 *) psDeviceNode->sDevMemoryInfo.pBMKernelContext->psMMUContext->apsPTInfoList[ui32PDIndex]->PTPageCpuVAddr;
+
+ pui32PT[ui32PTIndex] = (psDevInfo->sExtSysCacheRegsDevPBase.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PTE_VALID;
+
+
+#if defined(PDUMP)
+ /* Add the entery to the PT */
+ {
+ IMG_DEV_PHYADDR sDevPAddr;
+ IMG_CPU_PHYADDR sCpuPAddr;
+ IMG_UINT32 ui32PageMask;
+ IMG_UINT32 ui32PTE;
+ PVRSRV_ERROR eErr;
+
+ PDUMP_GET_SCRIPT_AND_FILE_STRING();
+
+ ui32PageMask = sMMUAttrib.ui32PTSize - 1;
+ sCpuPAddr = OSMapLinToCPUPhys(psDeviceNode->sDevMemoryInfo.pBMKernelContext->psMMUContext->apsPTInfoList[ui32PDIndex]->hPTPageOSMemHandle, &pui32PT[ui32PTIndex]);
+ sDevPAddr = SysCpuPAddrToDevPAddr(sMMUAttrib.sDevId.eDeviceType, sCpuPAddr);
+ ui32PTE = *((IMG_UINT32 *) (&pui32PT[ui32PTIndex]));
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "WRW :%s:PA_%08X%08X:0x%08X :%s:PA_%08X%08X:0x%08X\r\n",
+ sMMUAttrib.sDevId.pszPDumpDevName,
+ (IMG_UINT32)(IMG_UINTPTR_T)PDUMP_PT_UNIQUETAG,
+ (sDevPAddr.uiAddr) & ~ui32PageMask,
+ (sDevPAddr.uiAddr) & ui32PageMask,
+ "EXTSYSCACHE",
+ (IMG_UINT32)(IMG_UINTPTR_T)PDUMP_PD_UNIQUETAG,
+ (ui32PTE & sMMUAttrib.ui32PDEMask) << sMMUAttrib.ui32PTEAlignShift,
+ ui32PTE & ~sMMUAttrib.ui32PDEMask);
+ if(eErr != PVRSRV_OK)
+ {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+ }
+#endif
+
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR MMU_UnmapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ SYS_DATA *psSysData;
+ RA_ARENA *psLocalDevMemArena;
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+ IMG_UINT32 ui32PDIndex;
+ IMG_UINT32 ui32PTIndex;
+ IMG_UINT32 *pui32PT;
+#if defined(PDUMP)
+ PDUMP_MMU_ATTRIB sMMUAttrib;
+#endif
+
+ psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+
+#if defined(PDUMP)
+ sMMUAttrib = psDevInfo->sMMUAttrib;
+ MMU_SetPDumpAttribs(&sMMUAttrib, psDeviceNode,
+ SGX_MMU_PAGE_MASK,
+ SGX_MMU_PT_SIZE * sizeof(IMG_UINT32));
+#endif
+
+ SysAcquireData(&psSysData);
+
+ psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
+
+
+ ui32PDIndex = (SGX_EXT_SYSTEM_CACHE_REGS_DEVVADDR_BASE & SGX_MMU_PD_MASK) >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT);
+
+ ui32PTIndex = (SGX_EXT_SYSTEM_CACHE_REGS_DEVVADDR_BASE & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT;
+
+ /* Only unmap it if the PT hasn't already been freed */
+ if (psDeviceNode->sDevMemoryInfo.pBMKernelContext->psMMUContext->apsPTInfoList[ui32PDIndex])
+ {
+ if (psDeviceNode->sDevMemoryInfo.pBMKernelContext->psMMUContext->apsPTInfoList[ui32PDIndex]->PTPageCpuVAddr)
+ {
+
+ pui32PT = (IMG_UINT32 *) psDeviceNode->sDevMemoryInfo.pBMKernelContext->psMMUContext->apsPTInfoList[ui32PDIndex]->PTPageCpuVAddr;
+ pui32PT[ui32PTIndex] = 0;
+ PDUMPMEMPTENTRIES(&sMMUAttrib, psDeviceNode->sDevMemoryInfo.pBMKernelContext->psMMUContext->hPDOSMemHandle, &pui32PT[ui32PTIndex], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+ }
+ }
+
+ return PVRSRV_OK;
+}
+#endif
+
+
+#if PAGE_TEST
+static IMG_VOID PageTest(IMG_VOID* pMem, IMG_DEV_PHYADDR sDevPAddr)
+{
+ volatile IMG_UINT32 ui32WriteData;
+ volatile IMG_UINT32 ui32ReadData;
+ volatile IMG_UINT32 *pMem32 = (volatile IMG_UINT32 *)pMem;
+ IMG_INT n;
+ IMG_BOOL bOK=IMG_TRUE;
+
+ ui32WriteData = 0xffffffff;
+
+ for (n=0; n<1024; n++)
+ {
+ pMem32[n] = ui32WriteData;
+ ui32ReadData = pMem32[n];
+
+ if (ui32WriteData != ui32ReadData)
+ {
+
+ PVR_DPF ((PVR_DBG_ERROR, "Error - memory page test failed at device phys address 0x%08X", sDevPAddr.uiAddr + (n<<2) ));
+ PVR_DBG_BREAK;
+ bOK = IMG_FALSE;
+ }
+ }
+
+ ui32WriteData = 0;
+
+ for (n=0; n<1024; n++)
+ {
+ pMem32[n] = ui32WriteData;
+ ui32ReadData = pMem32[n];
+
+ if (ui32WriteData != ui32ReadData)
+ {
+
+ PVR_DPF ((PVR_DBG_ERROR, "Error - memory page test failed at device phys address 0x%08X", sDevPAddr.uiAddr + (n<<2) ));
+ PVR_DBG_BREAK;
+ bOK = IMG_FALSE;
+ }
+ }
+
+ if (bOK)
+ {
+ PVR_DPF ((PVR_DBG_VERBOSE, "MMU Page 0x%08X is OK", sDevPAddr.uiAddr));
+ }
+ else
+ {
+ PVR_DPF ((PVR_DBG_VERBOSE, "MMU Page 0x%08X *** FAILED ***", sDevPAddr.uiAddr));
+ }
+}
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef _MMU_H_
+#define _MMU_H_
+
+#include "sgxinfokm.h"
+
+PVRSRV_ERROR
+MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, IMG_DEV_PHYADDR *psPDDevPAddr);
+
+IMG_VOID
+MMU_Finalise (MMU_CONTEXT *psMMUContext);
+
+
+IMG_VOID
+MMU_InsertHeap(MMU_CONTEXT *psMMUContext, MMU_HEAP *psMMUHeap);
+
+MMU_HEAP *
+MMU_Create (MMU_CONTEXT *psMMUContext,
+ DEV_ARENA_DESCRIPTOR *psDevArena,
+ RA_ARENA **ppsVMArena,
+ PDUMP_MMU_ATTRIB **ppsMMUAttrib);
+
+IMG_VOID
+MMU_Delete (MMU_HEAP *pMMUHeap);
+
+IMG_BOOL
+MMU_Alloc (MMU_HEAP *pMMUHeap,
+ IMG_SIZE_T uSize,
+ IMG_SIZE_T *pActualSize,
+ IMG_UINT32 uFlags,
+ IMG_UINT32 uDevVAddrAlignment,
+ IMG_DEV_VIRTADDR *pDevVAddr);
+
+IMG_VOID
+MMU_Free (MMU_HEAP *pMMUHeap,
+ IMG_DEV_VIRTADDR DevVAddr,
+ IMG_UINT32 ui32Size);
+
+IMG_VOID
+MMU_Enable (MMU_HEAP *pMMUHeap);
+
+IMG_VOID
+MMU_Disable (MMU_HEAP *pMMUHeap);
+
+IMG_VOID
+MMU_MapPages (MMU_HEAP *pMMUHeap,
+ IMG_DEV_VIRTADDR DevVAddr,
+ IMG_SYS_PHYADDR SysPAddr,
+ IMG_SIZE_T uSize,
+ IMG_UINT32 ui32MemFlags,
+ IMG_HANDLE hUniqueTag);
+
+IMG_VOID
+MMU_MapShadow (MMU_HEAP * pMMUHeap,
+ IMG_DEV_VIRTADDR MapBaseDevVAddr,
+ IMG_SIZE_T uByteSize,
+ IMG_CPU_VIRTADDR CpuVAddr,
+ IMG_HANDLE hOSMemHandle,
+ IMG_DEV_VIRTADDR * pDevVAddr,
+ IMG_UINT32 ui32MemFlags,
+ IMG_HANDLE hUniqueTag);
+
+IMG_VOID
+MMU_UnmapPages (MMU_HEAP *psMMUHeap,
+ IMG_DEV_VIRTADDR sDevVAddr,
+ IMG_UINT32 ui32PageCount,
+ IMG_HANDLE hUniqueTag);
+
+IMG_VOID
+MMU_MapScatter (MMU_HEAP *pMMUHeap,
+ IMG_DEV_VIRTADDR DevVAddr,
+ IMG_SYS_PHYADDR *psSysAddr,
+ IMG_SIZE_T uSize,
+ IMG_UINT32 ui32MemFlags,
+ IMG_HANDLE hUniqueTag);
+
+
+IMG_DEV_PHYADDR
+MMU_GetPhysPageAddr(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR sDevVPageAddr);
+
+
+IMG_DEV_PHYADDR
+MMU_GetPDDevPAddr(MMU_CONTEXT *pMMUContext);
+
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+IMG_VOID
+EnableHostAccess (MMU_CONTEXT *psMMUContext);
+
+
+IMG_VOID
+DisableHostAccess (MMU_CONTEXT *psMMUContext);
+#endif
+
+IMG_VOID MMU_InvalidateDirectoryCache(PVRSRV_SGXDEV_INFO *psDevInfo);
+
+PVRSRV_ERROR MMU_BIFResetPDAlloc(PVRSRV_SGXDEV_INFO *psDevInfo);
+
+IMG_VOID MMU_BIFResetPDFree(PVRSRV_SGXDEV_INFO *psDevInfo);
+
+#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
+PVRSRV_ERROR WorkaroundBRN22997Alloc(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+IMG_VOID WorkaroundBRN22997ReadHostPort(PVRSRV_SGXDEV_INFO *psDevInfo);
+
+IMG_VOID WorkaroundBRN22997Free(PVRSRV_DEVICE_NODE *psDeviceNode);
+#endif
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+PVRSRV_ERROR MMU_MapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+PVRSRV_ERROR MMU_UnmapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode);
+#endif
+
+IMG_BOOL MMU_IsHeapShared(MMU_HEAP* pMMU_Heap);
+
+#if defined(PDUMP)
+IMG_UINT32 MMU_GetPDumpContextID(IMG_HANDLE hDevMemContext);
+#endif
+
+#endif
--- /dev/null
+/**********************************************************************
+ *
+ * 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 <stddef.h>
+
+#include "services_headers.h"
+#include "sgx_bridge_km.h"
+#include "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "sgxinfokm.h"
+#include "pvr_bridge_km.h"
+#include "pdump_km.h"
+#include "sgxutils.h"
+
+#ifndef __linux__
+#pragma message("TODO: Review use of OS_PAGEABLE vs OS_NON_PAGEABLE")
+#endif
+
+#include "lists.h"
+
+static IMPLEMENT_LIST_INSERT(PVRSRV_STUB_PBDESC)
+static IMPLEMENT_LIST_REMOVE(PVRSRV_STUB_PBDESC)
+
+static PRESMAN_ITEM psResItemCreateSharedPB = IMG_NULL;
+static PVRSRV_PER_PROCESS_DATA *psPerProcCreateSharedPB = IMG_NULL;
+
+static PVRSRV_ERROR SGXCleanupSharedPBDescCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param);
+static PVRSRV_ERROR SGXCleanupSharedPBDescCreateLockCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param);
+
+IMG_EXPORT PVRSRV_ERROR
+SGXFindSharedPBDescKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDevCookie,
+ IMG_BOOL bLockOnFailure,
+ IMG_UINT32 ui32TotalPBSize,
+ IMG_HANDLE *phSharedPBDesc,
+ PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO **ppsHWPBDescKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO **ppsBlockKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO **ppsHWBlockKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO ***pppsSharedPBDescSubKernelMemInfos,
+ IMG_UINT32 *ui32SharedPBDescSubKernelMemInfosCount)
+{
+ PVRSRV_STUB_PBDESC *psStubPBDesc;
+ PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescSubKernelMemInfos=IMG_NULL;
+ PVRSRV_SGXDEV_INFO *psSGXDevInfo;
+ PVRSRV_ERROR eError;
+
+ psSGXDevInfo = ((PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
+
+ psStubPBDesc = psSGXDevInfo->psStubPBDescListKM;
+ if (psStubPBDesc != IMG_NULL)
+ {
+ IMG_UINT32 i;
+ PRESMAN_ITEM psResItem;
+
+ if(psStubPBDesc->ui32TotalPBSize != ui32TotalPBSize)
+ {
+ PVR_DPF((PVR_DBG_WARNING,
+ "SGXFindSharedPBDescKM: Shared PB requested with different size (0x%x) from existing shared PB (0x%x) - requested size ignored",
+ ui32TotalPBSize, psStubPBDesc->ui32TotalPBSize));
+ }
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO *)
+ * psStubPBDesc->ui32SubKernelMemInfosCount,
+ (IMG_VOID **)&ppsSharedPBDescSubKernelMemInfos,
+ IMG_NULL,
+ "Array of Kernel Memory Info") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXFindSharedPBDescKM: OSAllocMem failed"));
+
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto ExitNotFound;
+ }
+
+ psResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_SHARED_PB_DESC,
+ psStubPBDesc,
+ 0,
+ &SGXCleanupSharedPBDescCallback);
+
+ if (psResItem == IMG_NULL)
+ {
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO *) * psStubPBDesc->ui32SubKernelMemInfosCount,
+ ppsSharedPBDescSubKernelMemInfos,
+ 0);
+
+
+ PVR_DPF((PVR_DBG_ERROR, "SGXFindSharedPBDescKM: ResManRegisterRes failed"));
+
+ eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto ExitNotFound;
+ }
+
+ *ppsSharedPBDescKernelMemInfo = psStubPBDesc->psSharedPBDescKernelMemInfo;
+ *ppsHWPBDescKernelMemInfo = psStubPBDesc->psHWPBDescKernelMemInfo;
+ *ppsBlockKernelMemInfo = psStubPBDesc->psBlockKernelMemInfo;
+ *ppsHWBlockKernelMemInfo = psStubPBDesc->psHWBlockKernelMemInfo;
+
+ *ui32SharedPBDescSubKernelMemInfosCount =
+ psStubPBDesc->ui32SubKernelMemInfosCount;
+
+ *pppsSharedPBDescSubKernelMemInfos = ppsSharedPBDescSubKernelMemInfos;
+
+ for(i=0; i<psStubPBDesc->ui32SubKernelMemInfosCount; i++)
+ {
+ ppsSharedPBDescSubKernelMemInfos[i] =
+ psStubPBDesc->ppsSubKernelMemInfos[i];
+ }
+
+ psStubPBDesc->ui32RefCount++;
+ *phSharedPBDesc = (IMG_HANDLE)psResItem;
+ return PVRSRV_OK;
+ }
+
+ eError = PVRSRV_OK;
+ if (bLockOnFailure)
+ {
+ if (psResItemCreateSharedPB == IMG_NULL)
+ {
+ psResItemCreateSharedPB = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_SHARED_PB_DESC_CREATE_LOCK,
+ psPerProc,
+ 0,
+ &SGXCleanupSharedPBDescCreateLockCallback);
+
+ if (psResItemCreateSharedPB == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXFindSharedPBDescKM: ResManRegisterRes failed"));
+
+ eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
+ goto ExitNotFound;
+ }
+ PVR_ASSERT(psPerProcCreateSharedPB == IMG_NULL);
+ psPerProcCreateSharedPB = psPerProc;
+ }
+ else
+ {
+ eError = PVRSRV_ERROR_PROCESSING_BLOCKED;
+ }
+ }
+ExitNotFound:
+ *phSharedPBDesc = IMG_NULL;
+
+ return eError;
+}
+
+
+static PVRSRV_ERROR
+SGXCleanupSharedPBDescKM(PVRSRV_STUB_PBDESC *psStubPBDescIn)
+{
+
+ IMG_UINT32 i;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE*)psStubPBDescIn->hDevCookie;
+
+
+
+
+ psStubPBDescIn->ui32RefCount--;
+ if (psStubPBDescIn->ui32RefCount == 0)
+ {
+ List_PVRSRV_STUB_PBDESC_Remove(psStubPBDescIn);
+ for(i=0 ; i<psStubPBDescIn->ui32SubKernelMemInfosCount; i++)
+ {
+
+ PVRSRVFreeDeviceMemKM(psStubPBDescIn->hDevCookie,
+ psStubPBDescIn->ppsSubKernelMemInfos[i]);
+ }
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO *) * psStubPBDescIn->ui32SubKernelMemInfosCount,
+ psStubPBDescIn->ppsSubKernelMemInfos,
+ 0);
+ psStubPBDescIn->ppsSubKernelMemInfos = IMG_NULL;
+
+ PVRSRVFreeSharedSysMemoryKM(psStubPBDescIn->psBlockKernelMemInfo);
+
+ PVRSRVFreeDeviceMemKM(psStubPBDescIn->hDevCookie, psStubPBDescIn->psHWBlockKernelMemInfo);
+
+ PVRSRVFreeDeviceMemKM(psStubPBDescIn->hDevCookie, psStubPBDescIn->psHWPBDescKernelMemInfo);
+
+ PVRSRVFreeSharedSysMemoryKM(psStubPBDescIn->psSharedPBDescKernelMemInfo);
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_STUB_PBDESC),
+ psStubPBDescIn,
+ 0);
+
+
+
+ SGXCleanupRequest(psDeviceNode,
+ IMG_NULL,
+ PVRSRV_CLEANUPCMD_PB);
+ }
+ return PVRSRV_OK;
+
+}
+
+static PVRSRV_ERROR SGXCleanupSharedPBDescCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param)
+{
+ PVRSRV_STUB_PBDESC *psStubPBDesc = (PVRSRV_STUB_PBDESC *)pvParam;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ return SGXCleanupSharedPBDescKM(psStubPBDesc);
+}
+
+static PVRSRV_ERROR SGXCleanupSharedPBDescCreateLockCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param)
+{
+#ifdef DEBUG
+ PVRSRV_PER_PROCESS_DATA *psPerProc = (PVRSRV_PER_PROCESS_DATA *)pvParam;
+ PVR_ASSERT(psPerProc == psPerProcCreateSharedPB);
+#else
+ PVR_UNREFERENCED_PARAMETER(pvParam);
+#endif
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ psPerProcCreateSharedPB = IMG_NULL;
+ psResItemCreateSharedPB = IMG_NULL;
+
+ return PVRSRV_OK;
+}
+
+
+IMG_EXPORT PVRSRV_ERROR
+SGXUnrefSharedPBDescKM(IMG_HANDLE hSharedPBDesc)
+{
+ PVR_ASSERT(hSharedPBDesc != IMG_NULL);
+
+ return ResManFreeResByPtr(hSharedPBDesc);
+}
+
+
+IMG_EXPORT PVRSRV_ERROR
+SGXAddSharedPBDescKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDevCookie,
+ PVRSRV_KERNEL_MEM_INFO *psSharedPBDescKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO *psHWPBDescKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO *psBlockKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO *psHWBlockKernelMemInfo,
+ IMG_UINT32 ui32TotalPBSize,
+ IMG_HANDLE *phSharedPBDesc,
+ PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescSubKernelMemInfos,
+ IMG_UINT32 ui32SharedPBDescSubKernelMemInfosCount)
+{
+ PVRSRV_STUB_PBDESC *psStubPBDesc=IMG_NULL;
+ PVRSRV_ERROR eRet = PVRSRV_ERROR_INVALID_PERPROC;
+ IMG_UINT32 i;
+ PVRSRV_SGXDEV_INFO *psSGXDevInfo;
+ PRESMAN_ITEM psResItem;
+
+
+ if (psPerProcCreateSharedPB != psPerProc)
+ {
+ goto NoAdd;
+ }
+ else
+ {
+ PVR_ASSERT(psResItemCreateSharedPB != IMG_NULL);
+
+ ResManFreeResByPtr(psResItemCreateSharedPB);
+
+ PVR_ASSERT(psResItemCreateSharedPB == IMG_NULL);
+ PVR_ASSERT(psPerProcCreateSharedPB == IMG_NULL);
+ }
+
+ psSGXDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
+
+ psStubPBDesc = psSGXDevInfo->psStubPBDescListKM;
+ if (psStubPBDesc != IMG_NULL)
+ {
+ if(psStubPBDesc->ui32TotalPBSize != ui32TotalPBSize)
+ {
+ PVR_DPF((PVR_DBG_WARNING,
+ "SGXAddSharedPBDescKM: Shared PB requested with different size (0x%x) from existing shared PB (0x%x) - requested size ignored",
+ ui32TotalPBSize, psStubPBDesc->ui32TotalPBSize));
+
+ }
+
+
+ psResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_SHARED_PB_DESC,
+ psStubPBDesc,
+ 0,
+ &SGXCleanupSharedPBDescCallback);
+ if (psResItem == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "SGXAddSharedPBDescKM: "
+ "Failed to register existing shared "
+ "PBDesc with the resource manager"));
+ goto NoAddKeepPB;
+ }
+
+
+ psStubPBDesc->ui32RefCount++;
+
+ *phSharedPBDesc = (IMG_HANDLE)psResItem;
+ eRet = PVRSRV_OK;
+ goto NoAddKeepPB;
+ }
+
+ if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_STUB_PBDESC),
+ (IMG_VOID **)&psStubPBDesc,
+ 0,
+ "Stub Parameter Buffer Description") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXAddSharedPBDescKM: Failed to alloc "
+ "StubPBDesc"));
+ eRet = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto NoAdd;
+ }
+
+
+ psStubPBDesc->ppsSubKernelMemInfos = IMG_NULL;
+
+ if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO *)
+ * ui32SharedPBDescSubKernelMemInfosCount,
+ (IMG_VOID **)&psStubPBDesc->ppsSubKernelMemInfos,
+ 0,
+ "Array of Kernel Memory Info") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXAddSharedPBDescKM: "
+ "Failed to alloc "
+ "StubPBDesc->ppsSubKernelMemInfos"));
+ eRet = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto NoAdd;
+ }
+
+ if(PVRSRVDissociateMemFromResmanKM(psSharedPBDescKernelMemInfo)
+ != PVRSRV_OK)
+ {
+ goto NoAdd;
+ }
+
+ if(PVRSRVDissociateMemFromResmanKM(psHWPBDescKernelMemInfo)
+ != PVRSRV_OK)
+ {
+ goto NoAdd;
+ }
+
+ if(PVRSRVDissociateMemFromResmanKM(psBlockKernelMemInfo)
+ != PVRSRV_OK)
+ {
+ goto NoAdd;
+ }
+
+ if(PVRSRVDissociateMemFromResmanKM(psHWBlockKernelMemInfo)
+ != PVRSRV_OK)
+ {
+ goto NoAdd;
+ }
+
+ psStubPBDesc->ui32RefCount = 1;
+ psStubPBDesc->ui32TotalPBSize = ui32TotalPBSize;
+ psStubPBDesc->psSharedPBDescKernelMemInfo = psSharedPBDescKernelMemInfo;
+ psStubPBDesc->psHWPBDescKernelMemInfo = psHWPBDescKernelMemInfo;
+ psStubPBDesc->psBlockKernelMemInfo = psBlockKernelMemInfo;
+ psStubPBDesc->psHWBlockKernelMemInfo = psHWBlockKernelMemInfo;
+
+ psStubPBDesc->ui32SubKernelMemInfosCount =
+ ui32SharedPBDescSubKernelMemInfosCount;
+ for(i=0; i<ui32SharedPBDescSubKernelMemInfosCount; i++)
+ {
+ psStubPBDesc->ppsSubKernelMemInfos[i] = ppsSharedPBDescSubKernelMemInfos[i];
+ if(PVRSRVDissociateMemFromResmanKM(ppsSharedPBDescSubKernelMemInfos[i])
+ != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXAddSharedPBDescKM: "
+ "Failed to dissociate shared PBDesc "
+ "from process"));
+ goto NoAdd;
+ }
+ }
+
+ psResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_SHARED_PB_DESC,
+ psStubPBDesc,
+ 0,
+ &SGXCleanupSharedPBDescCallback);
+ if (psResItem == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXAddSharedPBDescKM: "
+ "Failed to register shared PBDesc "
+ " with the resource manager"));
+ goto NoAdd;
+ }
+ psStubPBDesc->hDevCookie = hDevCookie;
+
+
+ List_PVRSRV_STUB_PBDESC_Insert(&(psSGXDevInfo->psStubPBDescListKM),
+ psStubPBDesc);
+
+ *phSharedPBDesc = (IMG_HANDLE)psResItem;
+
+ return PVRSRV_OK;
+
+NoAdd:
+ if(psStubPBDesc)
+ {
+ if(psStubPBDesc->ppsSubKernelMemInfos)
+ {
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO *) * ui32SharedPBDescSubKernelMemInfosCount,
+ psStubPBDesc->ppsSubKernelMemInfos,
+ 0);
+ psStubPBDesc->ppsSubKernelMemInfos = IMG_NULL;
+ }
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_STUB_PBDESC),
+ psStubPBDesc,
+ 0);
+
+ }
+
+NoAddKeepPB:
+ for (i = 0; i < ui32SharedPBDescSubKernelMemInfosCount; i++)
+ {
+ PVRSRVFreeDeviceMemKM(hDevCookie, ppsSharedPBDescSubKernelMemInfos[i]);
+ }
+
+ PVRSRVFreeSharedSysMemoryKM(psSharedPBDescKernelMemInfo);
+ PVRSRVFreeDeviceMemKM(hDevCookie, psHWPBDescKernelMemInfo);
+
+ PVRSRVFreeSharedSysMemoryKM(psBlockKernelMemInfo);
+ PVRSRVFreeDeviceMemKM(hDevCookie, psHWBlockKernelMemInfo);
+
+ return eRet;
+}
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#if !defined(__SGX_BRIDGE_KM_H__)
+#define __SGX_BRIDGE_KM_H__
+
+#include "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "sgxinfokm.h"
+#include "sgx_bridge.h"
+#include "pvr_bridge.h"
+#include "perproc.h"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+IMG_IMPORT
+PVRSRV_ERROR SGXSubmitTransferKM(IMG_HANDLE hDevHandle, PVRSRV_TRANSFER_SGX_KICK *psKick,
+ PVRSRV_PER_PROCESS_DATA *proc);
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+IMG_IMPORT
+PVRSRV_ERROR SGXSubmit2DKM(IMG_HANDLE hDevHandle, PVRSRV_2D_SGX_KICK *psKick);
+#endif
+
+IMG_IMPORT
+PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick,
+ PVRSRV_PER_PROCESS_DATA *proc);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXGetPhysPageAddrKM(IMG_HANDLE hDevMemHeap,
+ IMG_DEV_VIRTADDR sDevVAddr,
+ IMG_DEV_PHYADDR *pDevPAddr,
+ IMG_CPU_PHYADDR *pCpuPAddr);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV SGXGetMMUPDAddrKM(IMG_HANDLE hDevCookie,
+ IMG_HANDLE hDevMemContext,
+ IMG_DEV_PHYADDR *psPDDevPAddr);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXGetClientInfoKM(IMG_HANDLE hDevCookie,
+ SGX_CLIENT_INFO* psClientInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo,
+ SGX_MISC_INFO *psMiscInfo,
+ PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_HANDLE hDevMemContext);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXReadHWPerfCBKM(IMG_HANDLE hDevHandle,
+ IMG_UINT32 ui32ArraySize,
+ PVRSRV_SGX_HWPERF_CB_ENTRY *psHWPerfCBData,
+ IMG_UINT32 *pui32DataCount,
+ IMG_UINT32 *pui32ClockSpeed,
+ IMG_UINT32 *pui32HostTimeStamp);
+
+IMG_IMPORT
+PVRSRV_ERROR SGX2DQueryBlitsCompleteKM(PVRSRV_SGXDEV_INFO *psDevInfo,
+ PVRSRV_KERNEL_SYNC_INFO *psSyncInfo,
+ IMG_BOOL bWaitForComplete);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXGetInfoForSrvinitKM(IMG_HANDLE hDevHandle,
+ SGX_BRIDGE_INFO_FOR_SRVINIT *psInitInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR DevInitSGXPart2KM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDevHandle,
+ SGX_BRIDGE_INIT_INFO *psInitInfo);
+
+IMG_IMPORT PVRSRV_ERROR
+SGXFindSharedPBDescKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDevCookie,
+ IMG_BOOL bLockOnFailure,
+ IMG_UINT32 ui32TotalPBSize,
+ IMG_HANDLE *phSharedPBDesc,
+ PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO **ppsHWPBDescKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO **ppsBlockKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO **ppsHWBlockKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO ***pppsSharedPBDescSubKernelMemInfos,
+ IMG_UINT32 *ui32SharedPBDescSubKernelMemInfosCount);
+
+IMG_IMPORT PVRSRV_ERROR
+SGXUnrefSharedPBDescKM(IMG_HANDLE hSharedPBDesc);
+
+IMG_IMPORT PVRSRV_ERROR
+SGXAddSharedPBDescKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDevCookie,
+ PVRSRV_KERNEL_MEM_INFO *psSharedPBDescKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO *psHWPBDescKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO *psBlockKernelMemInfo,
+ PVRSRV_KERNEL_MEM_INFO *psHWBlockKernelMemInfo,
+ IMG_UINT32 ui32TotalPBSize,
+ IMG_HANDLE *phSharedPBDesc,
+ PVRSRV_KERNEL_MEM_INFO **psSharedPBDescSubKernelMemInfos,
+ IMG_UINT32 ui32SharedPBDescSubKernelMemInfosCount);
+
+
+IMG_IMPORT PVRSRV_ERROR
+SGXGetInternalDevInfoKM(IMG_HANDLE hDevCookie,
+ SGX_INTERNAL_DEVINFO *psSGXInternalDevInfo);
+
+extern PVRSRV_SGXDEV_INFO *pvr_sgx_dev_info;
+
+PVRSRV_SGXDEV_INFO *__pvr_get_sgx_dev_info(void);
+static inline PVRSRV_SGXDEV_INFO *pvr_get_sgx_dev_info(void)
+{
+ if (pvr_sgx_dev_info)
+ return pvr_sgx_dev_info;
+
+ return __pvr_get_sgx_dev_info();
+}
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef __SGXCONFIG_H__
+#define __SGXCONFIG_H__
+
+#include "sgxdefs.h"
+
+#define DEV_DEVICE_TYPE PVRSRV_DEVICE_TYPE_SGX
+#define DEV_DEVICE_CLASS PVRSRV_DEVICE_CLASS_3D
+
+#define DEV_MAJOR_VERSION 1
+#define DEV_MINOR_VERSION 0
+
+#if SGX_FEATURE_ADDRESS_SPACE_SIZE == 32
+ #if defined(SGX_FEATURE_2D_HARDWARE)
+ #define SGX_2D_HEAP_BASE 0x00100000
+ #define SGX_2D_HEAP_SIZE (0x08000000-0x00100000-0x00001000)
+ #else
+ #if defined(FIX_HW_BRN_26915)
+ #define SGX_CGBUFFER_HEAP_BASE 0x00100000
+ #define SGX_CGBUFFER_HEAP_SIZE (0x08000000-0x00100000-0x00001000)
+ #endif
+ #endif
+
+ #if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+ #define SGX_GENERAL_MAPPING_HEAP_BASE 0x08000000
+ #define SGX_GENERAL_MAPPING_HEAP_SIZE (0x20000000-0x00001000)
+ #endif
+
+ #define SGX_GENERAL_HEAP_BASE 0x28000000
+ #define SGX_GENERAL_HEAP_SIZE (0xAA000000-0x00001000)
+
+ #define SGX_3DPARAMETERS_HEAP_BASE 0xD2000000
+ #define SGX_3DPARAMETERS_HEAP_SIZE (0x10000000-0x00001000)
+
+ #define SGX_TADATA_HEAP_BASE 0xE2000000
+ #define SGX_TADATA_HEAP_SIZE (0x0D000000-0x00001000)
+
+ #define SGX_SYNCINFO_HEAP_BASE 0xEF000000
+ #define SGX_SYNCINFO_HEAP_SIZE (0x01000000-0x00001000)
+
+ #define SGX_PDSPIXEL_CODEDATA_HEAP_BASE 0xF0000000
+ #define SGX_PDSPIXEL_CODEDATA_HEAP_SIZE (0x02000000-0x00001000)
+
+ #define SGX_KERNEL_CODE_HEAP_BASE 0xF2000000
+ #define SGX_KERNEL_CODE_HEAP_SIZE (0x00080000-0x00001000)
+
+ #define SGX_PDSVERTEX_CODEDATA_HEAP_BASE 0xF2400000
+ #define SGX_PDSVERTEX_CODEDATA_HEAP_SIZE (0x01C00000-0x00001000)
+
+ #define SGX_KERNEL_DATA_HEAP_BASE (0xF4000000)
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+ #define SGX_KERNEL_DATA_HEAP_SIZE (0x05000000-0x00002000)
+#else
+ #define SGX_KERNEL_DATA_HEAP_SIZE (0x05000000-0x00001000)
+#endif
+
+ #define SGX_PIXELSHADER_HEAP_BASE 0xF9000000
+ #define SGX_PIXELSHADER_HEAP_SIZE (0x05000000-0x00001000)
+
+ #define SGX_VERTEXSHADER_HEAP_BASE 0xFE000000
+ #define SGX_VERTEXSHADER_HEAP_SIZE (0x02000000-0x00001000)
+
+
+ #define SGX_CORE_IDENTIFIED
+#endif
+
+#if SGX_FEATURE_ADDRESS_SPACE_SIZE == 28
+
+#if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+ #define SGX_GENERAL_MAPPING_HEAP_BASE 0x00001000
+ #define SGX_GENERAL_MAPPING_HEAP_SIZE (0x01800000-0x00001000-0x00001000)
+
+ #define SGX_GENERAL_HEAP_BASE 0x01800000
+ #define SGX_GENERAL_HEAP_SIZE (0x07000000-0x00001000)
+
+#else
+ #define SGX_GENERAL_HEAP_BASE 0x00001000
+ #define SGX_GENERAL_HEAP_SIZE (0x0C000000-0x00001000-0x00001000)
+#endif
+
+ #define SGX_3DPARAMETERS_HEAP_BASE 0x0C000000
+ #define SGX_3DPARAMETERS_HEAP_SIZE (0x00800000-0x00001000)
+
+ #define SGX_TADATA_HEAP_BASE 0x0C800000
+ #define SGX_TADATA_HEAP_SIZE (0x01000000-0x00001000)
+
+ #define SGX_SYNCINFO_HEAP_BASE 0x0D800000
+ #define SGX_SYNCINFO_HEAP_SIZE (0x00400000-0x00001000)
+
+ #define SGX_PDSPIXEL_CODEDATA_HEAP_BASE 0x0DC00000
+ #define SGX_PDSPIXEL_CODEDATA_HEAP_SIZE (0x00800000-0x00001000)
+
+ #define SGX_KERNEL_CODE_HEAP_BASE 0x0E400000
+ #define SGX_KERNEL_CODE_HEAP_SIZE (0x00080000-0x00001000)
+
+ #define SGX_PDSVERTEX_CODEDATA_HEAP_BASE 0x0E800000
+ #define SGX_PDSVERTEX_CODEDATA_HEAP_SIZE (0x00800000-0x00001000)
+
+ #define SGX_KERNEL_DATA_HEAP_BASE (0x0F000000)
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+ #define SGX_KERNEL_DATA_HEAP_SIZE (0x00400000-0x00002000)
+#else
+ #define SGX_KERNEL_DATA_HEAP_SIZE (0x00400000-0x00001000)
+#endif
+
+ #define SGX_PIXELSHADER_HEAP_BASE 0x0F400000
+ #define SGX_PIXELSHADER_HEAP_SIZE (0x00500000-0x00001000)
+
+ #define SGX_VERTEXSHADER_HEAP_BASE 0x0FC00000
+ #define SGX_VERTEXSHADER_HEAP_SIZE (0x00200000-0x00001000)
+
+
+ #define SGX_CORE_IDENTIFIED
+
+#endif
+
+#if !defined(SGX_CORE_IDENTIFIED)
+ #error "sgxconfig.h: ERROR: unspecified SGX Core version"
+#endif
+
+#if !defined (SGX_FEATURE_EDM_VERTEX_PDSADDR_FULL_RANGE)
+ #if ((SGX_KERNEL_CODE_HEAP_BASE + SGX_KERNEL_CODE_HEAP_SIZE - SGX_PDSPIXEL_CODEDATA_HEAP_BASE) > 0x4000000)
+ #error "sgxconfig.h: ERROR: SGX_KERNEL_CODE_HEAP_BASE out of range of SGX_PDSPIXEL_CODEDATA_HEAP_BASE"
+ #endif
+
+ #if ((SGX_PDSVERTEX_CODEDATA_HEAP_BASE + SGX_PDSVERTEX_CODEDATA_HEAP_SIZE - SGX_PDSPIXEL_CODEDATA_HEAP_BASE) > 0x4000000)
+ #error "sgxconfig.h: ERROR: SGX_PDSVERTEX_CODEDATA_HEAP_BASE out of range of SGX_PDSPIXEL_CODEDATA_HEAP_BASE"
+ #endif
+#endif
+
+#if defined(SGX_FEATURE_2D_HARDWARE) && defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+ #if ((SGX_GENERAL_MAPPING_HEAP_BASE + SGX_GENERAL_MAPPING_HEAP_SIZE - SGX_2D_HEAP_BASE) >= EUR_CR_BIF_TWOD_REQ_BASE_ADDR_MASK)
+ #error "sgxconfig.h: ERROR: SGX_GENERAL_MAPPING_HEAP inaccessable by 2D requestor"
+ #endif
+#endif
+
+#if defined (EURASIA_USE_CODE_PAGE_SIZE)
+ #if ((SGX_KERNEL_CODE_HEAP_BASE & (EURASIA_USE_CODE_PAGE_SIZE - 1)) != 0)
+ #error "sgxconfig.h: ERROR: Kernel code heap base misalignment"
+ #endif
+#endif
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+ #if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+ #if ((SGX_2D_HEAP_BASE + SGX_2D_HEAP_SIZE) >= SGX_GENERAL_MAPPING_HEAP_BASE)
+ #error "sgxconfig.h: ERROR: SGX_2D_HEAP overlaps SGX_GENERAL_MAPPING_HEAP"
+ #endif
+ #else
+ #if ((SGX_2D_HEAP_BASE + SGX_2D_HEAP_SIZE) >= SGX_GENERAL_HEAP_BASE)
+ #error "sgxconfig.h: ERROR: SGX_2D_HEAP overlaps SGX_GENERAL_HEAP_BASE"
+ #endif
+ #endif
+#else
+ #if defined(FIX_HW_BRN_26915)
+ #if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+ #if ((SGX_CGBUFFER_HEAP_BASE + SGX_CGBUFFER_HEAP_SIZE) >= SGX_GENERAL_MAPPING_HEAP_BASE)
+ #error "sgxconfig.h: ERROR: SGX_CGBUFFER_HEAP overlaps SGX_GENERAL_MAPPING_HEAP"
+ #endif
+ #else
+ #if ((SGX_CGBUFFER_HEAP_BASE + SGX_CGBUFFER_HEAP_SIZE) >= SGX_GENERAL_HEAP_BASE)
+ #error "sgxconfig.h: ERROR: SGX_CGBUFFER_HEAP overlaps SGX_GENERAL_HEAP_BASE"
+ #endif
+ #endif
+ #endif
+#endif
+
+#if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+ #if ((SGX_GENERAL_MAPPING_HEAP_BASE + SGX_GENERAL_MAPPING_HEAP_SIZE) >= SGX_GENERAL_HEAP_BASE)
+ #error "sgxconfig.h: ERROR: SGX_GENERAL_MAPPING_HEAP overlaps SGX_GENERAL_HEAP"
+ #endif
+#endif
+
+#if ((SGX_GENERAL_HEAP_BASE + SGX_GENERAL_HEAP_SIZE) >= SGX_3DPARAMETERS_HEAP_BASE)
+ #error "sgxconfig.h: ERROR: SGX_GENERAL_HEAP overlaps SGX_3DPARAMETERS_HEAP"
+#endif
+
+#if ((SGX_3DPARAMETERS_HEAP_BASE + SGX_3DPARAMETERS_HEAP_SIZE) >= SGX_TADATA_HEAP_BASE)
+ #error "sgxconfig.h: ERROR: SGX_3DPARAMETERS_HEAP overlaps SGX_TADATA_HEAP"
+#endif
+
+#if ((SGX_TADATA_HEAP_BASE + SGX_TADATA_HEAP_SIZE) >= SGX_SYNCINFO_HEAP_BASE)
+ #error "sgxconfig.h: ERROR: SGX_TADATA_HEAP overlaps SGX_SYNCINFO_HEAP"
+#endif
+
+#if ((SGX_SYNCINFO_HEAP_BASE + SGX_SYNCINFO_HEAP_SIZE) >= SGX_PDSPIXEL_CODEDATA_HEAP_BASE)
+ #error "sgxconfig.h: ERROR: SGX_SYNCINFO_HEAP overlaps SGX_PDSPIXEL_CODEDATA_HEAP"
+#endif
+
+#if ((SGX_PDSPIXEL_CODEDATA_HEAP_BASE + SGX_PDSPIXEL_CODEDATA_HEAP_SIZE) >= SGX_KERNEL_CODE_HEAP_BASE)
+ #error "sgxconfig.h: ERROR: SGX_PDSPIXEL_CODEDATA_HEAP overlaps SGX_KERNEL_CODE_HEAP"
+#endif
+
+#if ((SGX_KERNEL_CODE_HEAP_BASE + SGX_KERNEL_CODE_HEAP_SIZE) >= SGX_PDSVERTEX_CODEDATA_HEAP_BASE)
+ #error "sgxconfig.h: ERROR: SGX_KERNEL_CODE_HEAP overlaps SGX_PDSVERTEX_CODEDATA_HEAP"
+#endif
+
+#if ((SGX_PDSVERTEX_CODEDATA_HEAP_BASE + SGX_PDSVERTEX_CODEDATA_HEAP_SIZE) >= SGX_KERNEL_DATA_HEAP_BASE)
+ #error "sgxconfig.h: ERROR: SGX_PDSVERTEX_CODEDATA_HEAP overlaps SGX_KERNEL_DATA_HEAP"
+#endif
+
+#if ((SGX_KERNEL_DATA_HEAP_BASE + SGX_KERNEL_DATA_HEAP_SIZE) >= SGX_PIXELSHADER_HEAP_BASE)
+ #error "sgxconfig.h: ERROR: SGX_KERNEL_DATA_HEAP overlaps SGX_PIXELSHADER_HEAP"
+#endif
+
+#if ((SGX_PIXELSHADER_HEAP_BASE + SGX_PIXELSHADER_HEAP_SIZE) >= SGX_VERTEXSHADER_HEAP_BASE)
+ #error "sgxconfig.h: ERROR: SGX_PIXELSHADER_HEAP overlaps SGX_VERTEXSHADER_HEAP"
+#endif
+
+#if ((SGX_VERTEXSHADER_HEAP_BASE + SGX_VERTEXSHADER_HEAP_SIZE) < SGX_VERTEXSHADER_HEAP_BASE)
+ #error "sgxconfig.h: ERROR: SGX_VERTEXSHADER_HEAP_BASE size cause wraparound"
+#endif
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef __SGXINFOKM_H__
+#define __SGXINFOKM_H__
+
+#include "sgxdefs.h"
+#include "device.h"
+#include "power.h"
+#include "sysconfig.h"
+#include "sgxscript.h"
+#include "sgxinfo.h"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define SGX_HOSTPORT_PRESENT 0x00000001UL
+
+
+#define SGX_PDUMPREG_NAME "SGXREG"
+
+typedef struct _PVRSRV_STUB_PBDESC_ PVRSRV_STUB_PBDESC;
+
+
+typedef struct _PVRSRV_SGX_CCB_INFO_ *PPVRSRV_SGX_CCB_INFO;
+
+typedef struct _PVRSRV_SGXDEV_INFO_
+{
+ PVRSRV_DEVICE_TYPE eDeviceType;
+ PVRSRV_DEVICE_CLASS eDeviceClass;
+
+ IMG_UINT8 ui8VersionMajor;
+ IMG_UINT8 ui8VersionMinor;
+ IMG_UINT32 ui32CoreConfig;
+ IMG_UINT32 ui32CoreFlags;
+
+
+ IMG_PVOID pvRegsBaseKM;
+
+#if defined(SGX_FEATURE_HOST_PORT)
+
+ IMG_PVOID pvHostPortBaseKM;
+
+ IMG_UINT32 ui32HPSize;
+
+ IMG_SYS_PHYADDR sHPSysPAddr;
+#endif
+
+
+ IMG_HANDLE hRegMapping;
+
+
+ IMG_SYS_PHYADDR sRegsPhysBase;
+
+ IMG_UINT32 ui32RegSize;
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+
+ IMG_UINT32 ui32ExtSysCacheRegsSize;
+
+ IMG_DEV_PHYADDR sExtSysCacheRegsDevPBase;
+
+ IMG_UINT32 *pui32ExtSystemCacheRegsPT;
+
+ IMG_HANDLE hExtSystemCacheRegsPTPageOSMemHandle;
+
+ IMG_SYS_PHYADDR sExtSystemCacheRegsPTSysPAddr;
+#endif
+
+
+ IMG_UINT32 ui32CoreClockSpeed;
+ IMG_UINT32 ui32uKernelTimerClock;
+
+ PVRSRV_STUB_PBDESC *psStubPBDescListKM;
+
+
+
+ IMG_DEV_PHYADDR sKernelPDDevPAddr;
+
+ IMG_VOID *pvDeviceMemoryHeap;
+ PPVRSRV_KERNEL_MEM_INFO psKernelCCBMemInfo;
+ PVRSRV_SGX_KERNEL_CCB *psKernelCCB;
+ PPVRSRV_SGX_CCB_INFO psKernelCCBInfo;
+ PPVRSRV_KERNEL_MEM_INFO psKernelCCBCtlMemInfo;
+ PVRSRV_SGX_CCB_CTL *psKernelCCBCtl;
+ PPVRSRV_KERNEL_MEM_INFO psKernelCCBEventKickerMemInfo;
+ IMG_UINT32 *pui32KernelCCBEventKicker;
+#if defined(PDUMP)
+ IMG_UINT32 ui32KernelCCBEventKickerDumpVal;
+#endif
+ PVRSRV_KERNEL_MEM_INFO *psKernelSGXMiscMemInfo;
+ IMG_UINT32 aui32HostKickAddr[SGXMKIF_CMD_MAX];
+#if defined(SGX_SUPPORT_HWPROFILING)
+ PPVRSRV_KERNEL_MEM_INFO psKernelHWProfilingMemInfo;
+#endif
+ PPVRSRV_KERNEL_MEM_INFO psKernelHWPerfCBMemInfo;
+ PPVRSRV_KERNEL_MEM_INFO psKernelTASigBufferMemInfo;
+ PPVRSRV_KERNEL_MEM_INFO psKernel3DSigBufferMemInfo;
+#if defined(FIX_HW_BRN_29702)
+ PPVRSRV_KERNEL_MEM_INFO psKernelCFIMemInfo;
+#endif
+#if defined(FIX_HW_BRN_29823)
+ PPVRSRV_KERNEL_MEM_INFO psKernelDummyTermStreamMemInfo;
+#endif
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+ PPVRSRV_KERNEL_MEM_INFO psKernelEDMStatusBufferMemInfo;
+#endif
+#if defined(SGX_FEATURE_OVERLAPPED_SPM)
+ PPVRSRV_KERNEL_MEM_INFO psKernelTmpRgnHeaderMemInfo;
+#endif
+#if defined(SGX_FEATURE_SPM_MODE_0)
+ PPVRSRV_KERNEL_MEM_INFO psKernelTmpDPMStateMemInfo;
+#endif
+
+
+ IMG_UINT32 ui32ClientRefCount;
+
+
+ IMG_UINT32 ui32CacheControl;
+
+
+ IMG_UINT32 ui32ClientBuildOptions;
+
+
+ SGX_MISCINFO_STRUCT_SIZES sSGXStructSizes;
+
+
+
+
+ IMG_VOID *pvMMUContextList;
+
+
+ IMG_BOOL bForcePTOff;
+
+ IMG_UINT32 ui32EDMTaskReg0;
+ IMG_UINT32 ui32EDMTaskReg1;
+
+ IMG_UINT32 ui32ClkGateStatusReg;
+ IMG_UINT32 ui32ClkGateStatusMask;
+#if defined(SGX_FEATURE_MP)
+ IMG_UINT32 ui32MasterClkGateStatusReg;
+ IMG_UINT32 ui32MasterClkGateStatusMask;
+ IMG_UINT32 ui32MasterClkGateStatus2Reg;
+ IMG_UINT32 ui32MasterClkGateStatus2Mask;
+#endif
+ SGX_INIT_SCRIPTS sScripts;
+
+
+ IMG_HANDLE hBIFResetPDOSMemHandle;
+ IMG_DEV_PHYADDR sBIFResetPDDevPAddr;
+ IMG_DEV_PHYADDR sBIFResetPTDevPAddr;
+ IMG_DEV_PHYADDR sBIFResetPageDevPAddr;
+ IMG_UINT32 *pui32BIFResetPD;
+ IMG_UINT32 *pui32BIFResetPT;
+
+#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
+
+ IMG_HANDLE hBRN22997PTPageOSMemHandle;
+ IMG_HANDLE hBRN22997PDPageOSMemHandle;
+ IMG_DEV_PHYADDR sBRN22997PTDevPAddr;
+ IMG_DEV_PHYADDR sBRN22997PDDevPAddr;
+ IMG_UINT32 *pui32BRN22997PT;
+ IMG_UINT32 *pui32BRN22997PD;
+ IMG_SYS_PHYADDR sBRN22997SysPAddr;
+#endif
+
+#if defined(SUPPORT_HW_RECOVERY)
+
+ IMG_HANDLE hTimer;
+
+ IMG_UINT32 ui32TimeStamp;
+#endif
+
+
+ IMG_UINT32 ui32NumResets;
+
+
+ PVRSRV_KERNEL_MEM_INFO *psKernelSGXHostCtlMemInfo;
+ SGXMKIF_HOST_CTL *psSGXHostCtl;
+
+
+ PVRSRV_KERNEL_MEM_INFO *psKernelSGXTA3DCtlMemInfo;
+
+ IMG_UINT32 ui32Flags;
+
+
+ IMG_UINT32 ui32MemTilingUsage;
+
+ #if defined(PDUMP)
+ PVRSRV_SGX_PDUMP_CONTEXT sPDContext;
+ #endif
+
+#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
+
+ IMG_VOID *pvDummyPTPageCpuVAddr;
+ IMG_DEV_PHYADDR sDummyPTDevPAddr;
+ IMG_HANDLE hDummyPTPageOSMemHandle;
+ IMG_VOID *pvDummyDataPageCpuVAddr;
+ IMG_DEV_PHYADDR sDummyDataDevPAddr;
+ IMG_HANDLE hDummyDataPageOSMemHandle;
+#endif
+#if defined(PDUMP)
+ PDUMP_MMU_ATTRIB sMMUAttrib;
+#endif
+ IMG_UINT32 asSGXDevData[SGX_MAX_DEV_DATA];
+
+#if defined(PVRSRV_RESOURCE_PROFILING)
+ PVRSRV_KERNEL_MEM_INFO* psResProfMemInfo;
+ IMG_UINT32* pui32UsedMem;
+
+#endif
+} PVRSRV_SGXDEV_INFO;
+
+
+typedef struct _SGX_TIMING_INFORMATION_
+{
+ IMG_UINT32 ui32CoreClockSpeed;
+ IMG_UINT32 ui32HWRecoveryFreq;
+ IMG_BOOL bEnableActivePM;
+ IMG_UINT32 ui32ActivePowManLatencyms;
+ IMG_UINT32 ui32uKernelFreq;
+} SGX_TIMING_INFORMATION;
+
+typedef struct _SGX_DEVICE_MAP_
+{
+ IMG_UINT32 ui32Flags;
+
+
+ IMG_SYS_PHYADDR sRegsSysPBase;
+ IMG_CPU_PHYADDR sRegsCpuPBase;
+ IMG_CPU_VIRTADDR pvRegsCpuVBase;
+ IMG_UINT32 ui32RegsSize;
+
+#if defined(SGX_FEATURE_HOST_PORT)
+ IMG_SYS_PHYADDR sHPSysPBase;
+ IMG_CPU_PHYADDR sHPCpuPBase;
+ IMG_UINT32 ui32HPSize;
+#endif
+
+
+ IMG_SYS_PHYADDR sLocalMemSysPBase;
+ IMG_DEV_PHYADDR sLocalMemDevPBase;
+ IMG_CPU_PHYADDR sLocalMemCpuPBase;
+ IMG_UINT32 ui32LocalMemSize;
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+ IMG_UINT32 ui32ExtSysCacheRegsSize;
+ IMG_DEV_PHYADDR sExtSysCacheRegsDevPBase;
+#endif
+
+
+ IMG_UINT32 ui32IRQ;
+
+#if !defined(SGX_DYNAMIC_TIMING_INFO)
+
+ SGX_TIMING_INFORMATION sTimingInfo;
+#endif
+#if defined(PVRSRV_RESOURCE_PROFILING)
+ IMG_UINT32 ui32MemThreshold;
+#endif
+#if defined(PDUMP)
+
+ IMG_CHAR *pszPDumpDevName;
+#endif
+} SGX_DEVICE_MAP;
+
+
+struct _PVRSRV_STUB_PBDESC_
+{
+ IMG_UINT32 ui32RefCount;
+ IMG_UINT32 ui32TotalPBSize;
+ PVRSRV_KERNEL_MEM_INFO *psSharedPBDescKernelMemInfo;
+ PVRSRV_KERNEL_MEM_INFO *psHWPBDescKernelMemInfo;
+ PVRSRV_KERNEL_MEM_INFO **ppsSubKernelMemInfos;
+ IMG_UINT32 ui32SubKernelMemInfosCount;
+ IMG_HANDLE hDevCookie;
+ PVRSRV_KERNEL_MEM_INFO *psBlockKernelMemInfo;
+ PVRSRV_KERNEL_MEM_INFO *psHWBlockKernelMemInfo;
+ PVRSRV_STUB_PBDESC *psNext;
+ PVRSRV_STUB_PBDESC **ppsThis;
+};
+
+typedef struct _PVRSRV_SGX_CCB_INFO_
+{
+ PVRSRV_KERNEL_MEM_INFO *psCCBMemInfo;
+ PVRSRV_KERNEL_MEM_INFO *psCCBCtlMemInfo;
+ SGXMKIF_COMMAND *psCommands;
+ IMG_UINT32 *pui32WriteOffset;
+ volatile IMG_UINT32 *pui32ReadOffset;
+#if defined(PDUMP)
+ IMG_UINT32 ui32CCBDumpWOff;
+#endif
+} PVRSRV_SGX_CCB_INFO;
+
+PVRSRV_ERROR SGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode);
+
+IMG_VOID SGXOSTimer(IMG_VOID *pvData);
+
+IMG_VOID SGXReset(PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_BOOL bHardwareRecovery,
+ IMG_UINT32 ui32PDUMPFlags);
+
+PVRSRV_ERROR SGXInitialise(PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_BOOL bHardwareRecovery);
+PVRSRV_ERROR SGXDeinitialise(IMG_HANDLE hDevCookie);
+
+PVRSRV_ERROR SGXPrePowerState(IMG_HANDLE hDevHandle,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+
+PVRSRV_ERROR SGXPostPowerState(IMG_HANDLE hDevHandle,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+
+PVRSRV_ERROR SGXPreClockSpeedChange(IMG_HANDLE hDevHandle,
+ IMG_BOOL bIdleDevice,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+
+PVRSRV_ERROR SGXPostClockSpeedChange(IMG_HANDLE hDevHandle,
+ IMG_BOOL bIdleDevice,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+
+IMG_VOID SGXPanic(PVRSRV_SGXDEV_INFO *psDevInfo);
+
+PVRSRV_ERROR SGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+#if defined(SGX_DYNAMIC_TIMING_INFO)
+IMG_VOID SysGetSGXTimingInformation(SGX_TIMING_INFORMATION *psSGXTimingInfo);
+#endif
+
+#if defined(NO_HARDWARE)
+static INLINE IMG_VOID NoHardwareGenerateEvent(PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32StatusRegister,
+ IMG_UINT32 ui32StatusValue,
+ IMG_UINT32 ui32StatusMask)
+{
+ IMG_UINT32 ui32RegVal;
+
+ ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, ui32StatusRegister);
+
+ ui32RegVal &= ~ui32StatusMask;
+ ui32RegVal |= (ui32StatusValue & ui32StatusMask);
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32StatusRegister, ui32RegVal);
+}
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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 <stddef.h>
+
+#include "sgxdefs.h"
+#include "sgxmmu.h"
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "sgx_mkif_km.h"
+#include "sgxconfig.h"
+#include "sysconfig.h"
+#include "pvr_bridge_km.h"
+
+#include "sgx_bridge_km.h"
+
+#include "pdump_km.h"
+#include "ra.h"
+#include "mmu.h"
+#include "handle.h"
+#include "perproc.h"
+
+#include "sgxutils.h"
+#include "pvrversion.h"
+#include "sgx_options.h"
+
+#include "lists.h"
+#include "srvkm.h"
+#include "pvr_trace_cmd.h"
+
+#define VAR(x) #x
+
+
+#define CHECK_SIZE(NAME) \
+{ \
+ if (psSGXStructSizes->ui32Sizeof_##NAME != psDevInfo->sSGXStructSizes.ui32Sizeof_##NAME) \
+ { \
+ PVR_DPF((PVR_DBG_ERROR, "SGXDevInitCompatCheck: Size check failed for SGXMKIF_%s (client) = %d bytes, (ukernel) = %d bytes\n", \
+ VAR(NAME), \
+ psDevInfo->sSGXStructSizes.ui32Sizeof_##NAME, \
+ psSGXStructSizes->ui32Sizeof_##NAME )); \
+ bStructSizesFailed = IMG_TRUE; \
+ } \
+}
+
+#if defined (SYS_USING_INTERRUPTS)
+IMG_BOOL SGX_ISRHandler(IMG_VOID *pvData);
+#endif
+
+
+static
+PVRSRV_ERROR SGXGetMiscInfoUkernel(PVRSRV_SGXDEV_INFO *psDevInfo,
+ PVRSRV_DEVICE_NODE *psDeviceNode);
+#if defined(PDUMP)
+static
+PVRSRV_ERROR SGXResetPDump(PVRSRV_DEVICE_NODE *psDeviceNode);
+#endif
+
+static IMG_VOID SGXCommandComplete(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+#if defined(OS_SUPPORTS_IN_LISR)
+ if (OSInLISR(psDeviceNode->psSysData))
+ {
+
+ psDeviceNode->bReProcessDeviceCommandComplete = IMG_TRUE;
+ }
+ else
+ {
+ SGXScheduleProcessQueuesKM(psDeviceNode);
+ }
+#else
+ SGXScheduleProcessQueuesKM(psDeviceNode);
+#endif
+}
+
+static IMG_UINT32 DeinitDevInfo(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+ if (psDevInfo->psKernelCCBInfo != IMG_NULL)
+ {
+
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_SGX_CCB_INFO), psDevInfo->psKernelCCBInfo, IMG_NULL);
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_SGXDEV_INFO *pvr_sgx_dev_info;
+
+PVRSRV_SGXDEV_INFO *__pvr_get_sgx_dev_info(void)
+{
+ PVRSRV_DEVICE_NODE *dev_node;
+ PVRSRV_ERROR err;
+
+ err = PVRSRVAcquireDeviceDataKM(0, PVRSRV_DEVICE_TYPE_SGX,
+ (IMG_HANDLE)&dev_node);
+ if (err != PVRSRV_OK || !dev_node || !dev_node->pvDevice) {
+ WARN_ONCE(1, "pvr: can't get SGX device info\n");
+
+ return NULL;
+ }
+
+ pvr_sgx_dev_info = dev_node->pvDevice;
+
+ return pvr_sgx_dev_info;
+}
+
+static PVRSRV_ERROR InitDevInfo(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ PVRSRV_DEVICE_NODE *psDeviceNode,
+ SGX_BRIDGE_INIT_INFO *psInitInfo)
+{
+ PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+ PVRSRV_ERROR eError;
+
+ PVRSRV_SGX_CCB_INFO *psKernelCCBInfo = IMG_NULL;
+
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+ psDevInfo->sScripts = psInitInfo->sScripts;
+
+ psDevInfo->psKernelCCBMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelCCBMemInfo;
+ psDevInfo->psKernelCCB = (PVRSRV_SGX_KERNEL_CCB *) psDevInfo->psKernelCCBMemInfo->pvLinAddrKM;
+
+ psDevInfo->psKernelCCBCtlMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelCCBCtlMemInfo;
+ psDevInfo->psKernelCCBCtl = (PVRSRV_SGX_CCB_CTL *) psDevInfo->psKernelCCBCtlMemInfo->pvLinAddrKM;
+
+ psDevInfo->psKernelCCBEventKickerMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelCCBEventKickerMemInfo;
+ psDevInfo->pui32KernelCCBEventKicker = (IMG_UINT32 *)psDevInfo->psKernelCCBEventKickerMemInfo->pvLinAddrKM;
+
+ psDevInfo->psKernelSGXHostCtlMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelSGXHostCtlMemInfo;
+ psDevInfo->psSGXHostCtl = (SGXMKIF_HOST_CTL *)psDevInfo->psKernelSGXHostCtlMemInfo->pvLinAddrKM;
+
+ psDevInfo->psKernelSGXTA3DCtlMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelSGXTA3DCtlMemInfo;
+
+ psDevInfo->psKernelSGXMiscMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelSGXMiscMemInfo;
+
+#if defined(SGX_SUPPORT_HWPROFILING)
+ psDevInfo->psKernelHWProfilingMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelHWProfilingMemInfo;
+#endif
+#if defined(SUPPORT_SGX_HWPERF)
+ psDevInfo->psKernelHWPerfCBMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelHWPerfCBMemInfo;
+#endif
+ psDevInfo->psKernelTASigBufferMemInfo = psInitInfo->hKernelTASigBufferMemInfo;
+ psDevInfo->psKernel3DSigBufferMemInfo = psInitInfo->hKernel3DSigBufferMemInfo;
+#if defined(FIX_HW_BRN_29702)
+ psDevInfo->psKernelCFIMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelCFIMemInfo;
+#endif
+#if defined(FIX_HW_BRN_29823)
+ psDevInfo->psKernelDummyTermStreamMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelDummyTermStreamMemInfo;
+#endif
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+ psDevInfo->psKernelEDMStatusBufferMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelEDMStatusBufferMemInfo;
+#endif
+#if defined(SGX_FEATURE_OVERLAPPED_SPM)
+ psDevInfo->psKernelTmpRgnHeaderMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelTmpRgnHeaderMemInfo;
+#endif
+#if defined(SGX_FEATURE_SPM_MODE_0)
+ psDevInfo->psKernelTmpDPMStateMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelTmpDPMStateMemInfo;
+#endif
+
+ psDevInfo->ui32ClientBuildOptions = psInitInfo->ui32ClientBuildOptions;
+
+
+ psDevInfo->sSGXStructSizes = psInitInfo->sSGXStructSizes;
+
+
+
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_SGX_CCB_INFO),
+ (IMG_VOID **)&psKernelCCBInfo, 0,
+ "SGX Circular Command Buffer Info");
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"InitDevInfo: Failed to alloc memory"));
+ goto failed_allockernelccb;
+ }
+
+
+ OSMemSet(psKernelCCBInfo, 0, sizeof(PVRSRV_SGX_CCB_INFO));
+ psKernelCCBInfo->psCCBMemInfo = psDevInfo->psKernelCCBMemInfo;
+ psKernelCCBInfo->psCCBCtlMemInfo = psDevInfo->psKernelCCBCtlMemInfo;
+ psKernelCCBInfo->psCommands = psDevInfo->psKernelCCB->asCommands;
+ psKernelCCBInfo->pui32WriteOffset = &psDevInfo->psKernelCCBCtl->ui32WriteOffset;
+ psKernelCCBInfo->pui32ReadOffset = &psDevInfo->psKernelCCBCtl->ui32ReadOffset;
+ psDevInfo->psKernelCCBInfo = psKernelCCBInfo;
+
+
+
+ OSMemCopy(psDevInfo->aui32HostKickAddr, psInitInfo->aui32HostKickAddr,
+ SGXMKIF_CMD_MAX * sizeof(psDevInfo->aui32HostKickAddr[0]));
+
+ psDevInfo->bForcePTOff = IMG_FALSE;
+
+ psDevInfo->ui32CacheControl = psInitInfo->ui32CacheControl;
+
+ psDevInfo->ui32EDMTaskReg0 = psInitInfo->ui32EDMTaskReg0;
+ psDevInfo->ui32EDMTaskReg1 = psInitInfo->ui32EDMTaskReg1;
+ psDevInfo->ui32ClkGateStatusReg = psInitInfo->ui32ClkGateStatusReg;
+ psDevInfo->ui32ClkGateStatusMask = psInitInfo->ui32ClkGateStatusMask;
+#if defined(SGX_FEATURE_MP)
+ psDevInfo->ui32MasterClkGateStatusReg = psInitInfo->ui32MasterClkGateStatusReg;
+ psDevInfo->ui32MasterClkGateStatusMask = psInitInfo->ui32MasterClkGateStatusMask;
+ psDevInfo->ui32MasterClkGateStatus2Reg = psInitInfo->ui32MasterClkGateStatus2Reg;
+ psDevInfo->ui32MasterClkGateStatus2Mask = psInitInfo->ui32MasterClkGateStatus2Mask;
+#endif
+
+
+
+ OSMemCopy(&psDevInfo->asSGXDevData, &psInitInfo->asInitDevData, sizeof(psDevInfo->asSGXDevData));
+
+ return PVRSRV_OK;
+
+failed_allockernelccb:
+ DeinitDevInfo(psDevInfo);
+
+ return eError;
+}
+
+
+
+
+static PVRSRV_ERROR SGXRunScript(PVRSRV_SGXDEV_INFO *psDevInfo, SGX_INIT_COMMAND *psScript, IMG_UINT32 ui32NumInitCommands)
+{
+ IMG_UINT32 ui32PC;
+ SGX_INIT_COMMAND *psComm;
+
+ for (ui32PC = 0, psComm = psScript;
+ ui32PC < ui32NumInitCommands;
+ ui32PC++, psComm++)
+ {
+ switch (psComm->eOp)
+ {
+ case SGX_INIT_OP_WRITE_HW_REG:
+ {
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, psComm->sWriteHWReg.ui32Offset, psComm->sWriteHWReg.ui32Value);
+ PDUMPCOMMENT("SGXRunScript: Write HW reg operation");
+ PDUMPREG(SGX_PDUMPREG_NAME, psComm->sWriteHWReg.ui32Offset, psComm->sWriteHWReg.ui32Value);
+ break;
+ }
+#if defined(PDUMP)
+ case SGX_INIT_OP_PDUMP_HW_REG:
+ {
+ PDUMPCOMMENT("SGXRunScript: Dump HW reg operation");
+ PDUMPREG(SGX_PDUMPREG_NAME, psComm->sPDumpHWReg.ui32Offset, psComm->sPDumpHWReg.ui32Value);
+ break;
+ }
+#endif
+ case SGX_INIT_OP_HALT:
+ {
+ return PVRSRV_OK;
+ }
+ case SGX_INIT_OP_ILLEGAL:
+
+ default:
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXRunScript: PC %d: Illegal command: %d", ui32PC, psComm->eOp));
+ return PVRSRV_ERROR_UNKNOWN_SCRIPT_OPERATION;
+ }
+ }
+
+ }
+
+ return PVRSRV_ERROR_UNKNOWN_SCRIPT_OPERATION;
+}
+
+PVRSRV_ERROR SGXInitialise(PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_BOOL bHardwareRecovery)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_KERNEL_MEM_INFO *psSGXHostCtlMemInfo = psDevInfo->psKernelSGXHostCtlMemInfo;
+ SGXMKIF_HOST_CTL *psSGXHostCtl = psSGXHostCtlMemInfo->pvLinAddrKM;
+ static IMG_BOOL bFirstTime = IMG_TRUE;
+#if defined(PDUMP)
+ IMG_BOOL bPDumpIsSuspended = PDumpIsSuspended();
+#endif
+
+
+
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "SGX initialisation script part 1\n");
+ eError = SGXRunScript(psDevInfo, psDevInfo->sScripts.asInitCommandsPart1, SGX_MAX_INIT_COMMANDS);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXInitialise: SGXRunScript (part 1) failed (%d)", eError));
+ return eError;
+ }
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "End of SGX initialisation script part 1\n");
+
+
+ SGXReset(psDevInfo, bFirstTime || bHardwareRecovery, PDUMP_FLAGS_CONTINUOUS);
+
+#if defined(EUR_CR_POWER)
+#if defined(SGX531)
+
+
+
+
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_POWER, 1);
+ PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_POWER, 1);
+#else
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_POWER, 0);
+ PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_POWER, 0);
+#endif
+#endif
+
+
+ *psDevInfo->pui32KernelCCBEventKicker = 0;
+#if defined(PDUMP)
+ if (!bPDumpIsSuspended)
+ {
+ psDevInfo->ui32KernelCCBEventKickerDumpVal = 0;
+ PDUMPMEM(&psDevInfo->ui32KernelCCBEventKickerDumpVal,
+ psDevInfo->psKernelCCBEventKickerMemInfo, 0,
+ sizeof(*psDevInfo->pui32KernelCCBEventKicker), PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
+ }
+#endif
+
+
+
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "SGX initialisation script part 2\n");
+ eError = SGXRunScript(psDevInfo, psDevInfo->sScripts.asInitCommandsPart2, SGX_MAX_INIT_COMMANDS);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXInitialise: SGXRunScript (part 2) failed (%d)", eError));
+ return eError;
+ }
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "End of SGX initialisation script part 2\n");
+
+
+ psSGXHostCtl->ui32HostClock = OSClockus();
+
+ psSGXHostCtl->ui32InitStatus = 0;
+#if defined(PDUMP)
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+ "Reset the SGX microkernel initialisation status\n");
+ PDUMPMEM(IMG_NULL, psSGXHostCtlMemInfo,
+ offsetof(SGXMKIF_HOST_CTL, ui32InitStatus),
+ sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psSGXHostCtlMemInfo));
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+ "Initialise the microkernel\n");
+#endif
+
+#if defined(SGX_FEATURE_MULTI_EVENT_KICK)
+ OSWriteMemoryBarrier();
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM,
+ SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK2, 0),
+ EUR_CR_EVENT_KICK2_NOW_MASK);
+#else
+ *psDevInfo->pui32KernelCCBEventKicker = (*psDevInfo->pui32KernelCCBEventKicker + 1) & 0xFF;
+ OSWriteMemoryBarrier();
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM,
+ SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK, 0),
+ EUR_CR_EVENT_KICK_NOW_MASK);
+#endif
+
+ OSMemoryBarrier();
+
+#if defined(PDUMP)
+
+
+ if (!bPDumpIsSuspended)
+ {
+#if defined(SGX_FEATURE_MULTI_EVENT_KICK)
+ PDUMPREG(SGX_PDUMPREG_NAME, SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK2, 0), EUR_CR_EVENT_KICK2_NOW_MASK);
+#else
+ psDevInfo->ui32KernelCCBEventKickerDumpVal = 1;
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+ "First increment of the SGX event kicker value\n");
+ PDUMPMEM(&psDevInfo->ui32KernelCCBEventKickerDumpVal,
+ psDevInfo->psKernelCCBEventKickerMemInfo,
+ 0,
+ sizeof(IMG_UINT32),
+ PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
+ PDUMPREG(SGX_PDUMPREG_NAME, SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK, 0), EUR_CR_EVENT_KICK_NOW_MASK);
+#endif
+ }
+#endif
+
+#if !defined(NO_HARDWARE)
+
+
+ if (PollForValueKM(&psSGXHostCtl->ui32InitStatus,
+ PVRSRV_USSE_EDM_INIT_COMPLETE,
+ PVRSRV_USSE_EDM_INIT_COMPLETE,
+ MAX_HW_TIME_US,
+ MAX_HW_TIME_US/WAIT_TRY_COUNT,
+ IMG_FALSE) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXInitialise: Wait for uKernel initialisation failed"));
+ #if !defined(FIX_HW_BRN_23281)
+ PVR_DBG_BREAK;
+ #endif
+ return PVRSRV_ERROR_RETRY;
+ }
+#endif
+
+#if defined(PDUMP)
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+ "Wait for the SGX microkernel initialisation to complete");
+ PDUMPMEMPOL(psSGXHostCtlMemInfo,
+ offsetof(SGXMKIF_HOST_CTL, ui32InitStatus),
+ PVRSRV_USSE_EDM_INIT_COMPLETE,
+ PVRSRV_USSE_EDM_INIT_COMPLETE,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psSGXHostCtlMemInfo));
+#endif
+
+#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
+
+
+
+ WorkaroundBRN22997ReadHostPort(psDevInfo);
+#endif
+
+ PVR_ASSERT(psDevInfo->psKernelCCBCtl->ui32ReadOffset == psDevInfo->psKernelCCBCtl->ui32WriteOffset);
+
+ bFirstTime = IMG_FALSE;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR SGXDeinitialise(IMG_HANDLE hDevCookie)
+
+{
+ PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *) hDevCookie;
+ PVRSRV_ERROR eError;
+
+
+ if (psDevInfo->pvRegsBaseKM == IMG_NULL)
+ {
+ return PVRSRV_OK;
+ }
+
+ eError = SGXRunScript(psDevInfo, psDevInfo->sScripts.asDeinitCommands, SGX_MAX_DEINIT_COMMANDS);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXDeinitialise: SGXRunScript failed (%d)", eError));
+ return eError;
+ }
+
+ return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR DevInitSGXPart1 (IMG_VOID *pvDeviceNode)
+{
+ IMG_HANDLE hDevMemHeap = IMG_NULL;
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+ IMG_HANDLE hKernelDevMemContext;
+ IMG_DEV_PHYADDR sPDDevPAddr;
+ IMG_UINT32 i;
+ PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvDeviceNode;
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
+ PVRSRV_ERROR eError;
+
+
+ PDUMPCOMMENT("SGX Core Version Information: %s", SGX_CORE_FRIENDLY_NAME);
+
+ #if defined(SGX_FEATURE_MP)
+ PDUMPCOMMENT("SGX Multi-processor: %d cores", SGX_FEATURE_MP_CORE_COUNT);
+ #endif
+
+#if (SGX_CORE_REV == 0)
+ PDUMPCOMMENT("SGX Core Revision Information: head RTL");
+#else
+ PDUMPCOMMENT("SGX Core Revision Information: %d", SGX_CORE_REV);
+#endif
+
+ #if defined(SGX_FEATURE_SYSTEM_CACHE)
+ PDUMPCOMMENT("SGX System Level Cache is present\r\n");
+ #if defined(SGX_BYPASS_SYSTEM_CACHE)
+ PDUMPCOMMENT("SGX System Level Cache is bypassed\r\n");
+ #endif
+ #endif
+
+ PDUMPCOMMENT("SGX Initialisation Part 1");
+
+
+ if(OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_SGXDEV_INFO),
+ (IMG_VOID **)&psDevInfo, IMG_NULL,
+ "SGX Device Info") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart1 : Failed to alloc memory for DevInfo"));
+ return (PVRSRV_ERROR_OUT_OF_MEMORY);
+ }
+ OSMemSet (psDevInfo, 0, sizeof(PVRSRV_SGXDEV_INFO));
+
+
+ psDevInfo->eDeviceType = DEV_DEVICE_TYPE;
+ psDevInfo->eDeviceClass = DEV_DEVICE_CLASS;
+
+
+ psDeviceNode->pvDevice = (IMG_PVOID)psDevInfo;
+
+
+ psDevInfo->pvDeviceMemoryHeap = (IMG_VOID*)psDeviceMemoryHeap;
+
+
+ hKernelDevMemContext = BM_CreateContext(psDeviceNode,
+ &sPDDevPAddr,
+ IMG_NULL,
+ IMG_NULL);
+ if (hKernelDevMemContext == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart1: Failed BM_CreateContext"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ psDevInfo->sKernelPDDevPAddr = sPDDevPAddr;
+
+
+ for(i=0; i<psDeviceNode->sDevMemoryInfo.ui32HeapCount; i++)
+ {
+ switch(psDeviceMemoryHeap[i].DevMemHeapType)
+ {
+ case DEVICE_MEMORY_HEAP_KERNEL:
+ case DEVICE_MEMORY_HEAP_SHARED:
+ case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
+ {
+ hDevMemHeap = BM_CreateHeap (hKernelDevMemContext,
+ &psDeviceMemoryHeap[i]);
+
+
+
+ psDeviceMemoryHeap[i].hDevMemHeap = hDevMemHeap;
+ break;
+ }
+ }
+ }
+#if defined(PDUMP)
+ if(hDevMemHeap)
+ {
+
+ psDevInfo->sMMUAttrib = *((BM_HEAP*)hDevMemHeap)->psMMUAttrib;
+ }
+#endif
+ eError = MMU_BIFResetPDAlloc(psDevInfo);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DevInitSGX : Failed to alloc memory for BIF reset"));
+ return eError;
+ }
+#if defined(PVRSRV_RESOURCE_PROFILING)
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO),
+ (IMG_VOID **)&psDevInfo->psResProfMemInfo, IMG_NULL,
+ "Res Memory Info") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"InitDevInfo: Failed to alloc memory for meminfo"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ OSMemSet(psDevInfo->psResProfMemInfo, 0, sizeof(*psDevInfo->psResProfMemInfo));
+ psDevInfo->psResProfMemInfo->ui32Flags |= PVRSRV_HAP_MULTI_PROCESS | PVRSRV_HAP_UNCACHED;
+ psDevInfo->psResProfMemInfo->ui32AllocSize = sizeof(IMG_UINT32);
+ if(OSAllocPages(psDevInfo->psResProfMemInfo->ui32Flags,
+ psDevInfo->psResProfMemInfo->ui32AllocSize,
+ HOST_PAGESIZE(),
+ &psDevInfo->psResProfMemInfo->pvLinAddrKM,
+ &psDevInfo->psResProfMemInfo->sMemBlk.hOSMemHandle)
+ != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "InitDevInfo: Failed to alloc memory for block"));
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO),
+ psDevInfo->psResProfMemInfo,
+ 0);
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ psDevInfo->pui32UsedMem = psDevInfo->psResProfMemInfo->pvLinAddrKM;
+ if(psDevInfo->pui32UsedMem == IMG_NULL)
+ PVR_LOG(("InitDevInfo:res kernel mem info has no kernel address"));
+ *psDevInfo->pui32UsedMem = 0;
+#endif
+ return PVRSRV_OK;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR SGXGetInfoForSrvinitKM(IMG_HANDLE hDevHandle, SGX_BRIDGE_INFO_FOR_SRVINIT *psInitInfo)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+ PVRSRV_ERROR eError;
+
+ PDUMPCOMMENT("SGXGetInfoForSrvinit");
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevHandle;
+ psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+
+ psInitInfo->sPDDevPAddr = psDevInfo->sKernelPDDevPAddr;
+
+ eError = PVRSRVGetDeviceMemHeapsKM(hDevHandle, &psInitInfo->asHeapInfo[0]);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXGetInfoForSrvinit: PVRSRVGetDeviceMemHeapsKM failed (%d)", eError));
+ return eError;
+ }
+
+ return eError;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR DevInitSGXPart2KM (PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDevHandle,
+ SGX_BRIDGE_INIT_INFO *psInitInfo)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+ PVRSRV_ERROR eError;
+ SGX_DEVICE_MAP *psSGXDeviceMap;
+ PVRSRV_DEV_POWER_STATE eDefaultPowerState;
+
+ PDUMPCOMMENT("SGX Initialisation Part 2");
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevHandle;
+ psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+
+ eError = InitDevInfo(psPerProc, psDeviceNode, psInitInfo);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart2KM: Failed to load EDM program"));
+ goto failed_init_dev_info;
+ }
+
+
+ eError = SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX,
+ (IMG_VOID**)&psSGXDeviceMap);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart2KM: Failed to get device memory map!"));
+ return PVRSRV_ERROR_INIT_FAILURE;
+ }
+
+
+ if (psSGXDeviceMap->pvRegsCpuVBase)
+ {
+ psDevInfo->pvRegsBaseKM = psSGXDeviceMap->pvRegsCpuVBase;
+ }
+ else
+ {
+
+ psDevInfo->pvRegsBaseKM = OSMapPhysToLin(psSGXDeviceMap->sRegsCpuPBase,
+ psSGXDeviceMap->ui32RegsSize,
+ PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+ IMG_NULL);
+ if (!psDevInfo->pvRegsBaseKM)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart2KM: Failed to map in regs\n"));
+ return PVRSRV_ERROR_BAD_MAPPING;
+ }
+ }
+ psDevInfo->ui32RegSize = psSGXDeviceMap->ui32RegsSize;
+ psDevInfo->sRegsPhysBase = psSGXDeviceMap->sRegsSysPBase;
+
+
+#if defined(SGX_FEATURE_HOST_PORT)
+ if (psSGXDeviceMap->ui32Flags & SGX_HOSTPORT_PRESENT)
+ {
+
+ psDevInfo->pvHostPortBaseKM = OSMapPhysToLin(psSGXDeviceMap->sHPCpuPBase,
+ psSGXDeviceMap->ui32HPSize,
+ PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+ IMG_NULL);
+ if (!psDevInfo->pvHostPortBaseKM)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart2KM: Failed to map in host port\n"));
+ return PVRSRV_ERROR_BAD_MAPPING;
+ }
+ psDevInfo->ui32HPSize = psSGXDeviceMap->ui32HPSize;
+ psDevInfo->sHPSysPAddr = psSGXDeviceMap->sHPSysPBase;
+ }
+#endif
+
+#if defined (SYS_USING_INTERRUPTS)
+
+
+ psDeviceNode->pvISRData = psDeviceNode;
+
+ PVR_ASSERT(psDeviceNode->pfnDeviceISR == SGX_ISRHandler);
+
+#endif
+
+
+ psDevInfo->psSGXHostCtl->ui32PowerStatus |= PVRSRV_USSE_EDM_POWMAN_NO_WORK;
+ eDefaultPowerState = PVRSRV_DEV_POWER_STATE_OFF;
+
+ eError = PVRSRVRegisterPowerDevice (psDeviceNode->sDevId.ui32DeviceIndex,
+ &SGXPrePowerState, &SGXPostPowerState,
+ &SGXPreClockSpeedChange, &SGXPostClockSpeedChange,
+ (IMG_HANDLE)psDeviceNode,
+ PVRSRV_DEV_POWER_STATE_OFF,
+ eDefaultPowerState);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DevInitSGXPart2KM: failed to register device with power manager"));
+ return eError;
+ }
+
+#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
+ eError = WorkaroundBRN22997Alloc(psDeviceNode);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXInitialise : Failed to alloc memory for BRN22997 workaround"));
+ return eError;
+ }
+#endif
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+
+ psDevInfo->ui32ExtSysCacheRegsSize = psSGXDeviceMap->ui32ExtSysCacheRegsSize;
+ psDevInfo->sExtSysCacheRegsDevPBase = psSGXDeviceMap->sExtSysCacheRegsDevPBase;
+ eError = MMU_MapExtSystemCacheRegs(psDeviceNode);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXInitialise : Failed to map external system cache registers"));
+ return eError;
+ }
+#endif
+
+
+
+ OSMemSet(psDevInfo->psKernelCCB, 0, sizeof(PVRSRV_SGX_KERNEL_CCB));
+ OSMemSet(psDevInfo->psKernelCCBCtl, 0, sizeof(PVRSRV_SGX_CCB_CTL));
+ OSMemSet(psDevInfo->pui32KernelCCBEventKicker, 0, sizeof(*psDevInfo->pui32KernelCCBEventKicker));
+ PDUMPCOMMENT("Initialise Kernel CCB");
+ PDUMPMEM(IMG_NULL, psDevInfo->psKernelCCBMemInfo, 0, sizeof(PVRSRV_SGX_KERNEL_CCB), PDUMP_FLAGS_CONTINUOUS, MAKEUNIQUETAG(psDevInfo->psKernelCCBMemInfo));
+ PDUMPCOMMENT("Initialise Kernel CCB Control");
+ PDUMPMEM(IMG_NULL, psDevInfo->psKernelCCBCtlMemInfo, 0, sizeof(PVRSRV_SGX_CCB_CTL), PDUMP_FLAGS_CONTINUOUS, MAKEUNIQUETAG(psDevInfo->psKernelCCBCtlMemInfo));
+ PDUMPCOMMENT("Initialise Kernel CCB Event Kicker");
+ PDUMPMEM(IMG_NULL, psDevInfo->psKernelCCBEventKickerMemInfo, 0, sizeof(*psDevInfo->pui32KernelCCBEventKicker), PDUMP_FLAGS_CONTINUOUS, MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
+
+ return PVRSRV_OK;
+
+failed_init_dev_info:
+ return eError;
+}
+
+static PVRSRV_ERROR DevDeInitSGX (IMG_VOID *pvDeviceNode)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvDeviceNode;
+ PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32Heap;
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+ SGX_DEVICE_MAP *psSGXDeviceMap;
+
+ if (!psDevInfo)
+ {
+
+ PVR_DPF((PVR_DBG_ERROR,"DevDeInitSGX: Null DevInfo"));
+ return PVRSRV_OK;
+ }
+
+#if defined(SUPPORT_HW_RECOVERY)
+ if (psDevInfo->hTimer)
+ {
+ eError = OSRemoveTimer(psDevInfo->hTimer);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DevDeInitSGX: Failed to remove timer"));
+ return eError;
+ }
+ psDevInfo->hTimer = IMG_NULL;
+ }
+#endif
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+
+ eError = MMU_UnmapExtSystemCacheRegs(psDeviceNode);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DevDeInitSGX: Failed to unmap ext system cache registers"));
+ return eError;
+ }
+#endif
+
+#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
+ WorkaroundBRN22997Free(psDeviceNode);
+#endif
+
+ MMU_BIFResetPDFree(psDevInfo);
+
+
+
+ DeinitDevInfo(psDevInfo);
+
+#if defined(PVRSRV_RESOURCE_PROFILING)
+ if (psDevInfo->psResProfMemInfo != IMG_NULL)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO),
+ psDevInfo->psResProfMemInfo,
+ 0);
+ }
+ psDevInfo->pui32UsedMem = IMG_NULL;
+#endif
+
+ psDeviceMemoryHeap = (DEVICE_MEMORY_HEAP_INFO *)psDevInfo->pvDeviceMemoryHeap;
+ for(ui32Heap=0; ui32Heap<psDeviceNode->sDevMemoryInfo.ui32HeapCount; ui32Heap++)
+ {
+ switch(psDeviceMemoryHeap[ui32Heap].DevMemHeapType)
+ {
+ case DEVICE_MEMORY_HEAP_KERNEL:
+ case DEVICE_MEMORY_HEAP_SHARED:
+ case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
+ {
+ if (psDeviceMemoryHeap[ui32Heap].hDevMemHeap != IMG_NULL)
+ {
+ BM_DestroyHeap(psDeviceMemoryHeap[ui32Heap].hDevMemHeap);
+ }
+ break;
+ }
+ }
+ }
+
+
+ eError = BM_DestroyContext(psDeviceNode->sDevMemoryInfo.pBMKernelContext, IMG_NULL);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DevDeInitSGX : Failed to destroy kernel context"));
+ return eError;
+ }
+
+
+ eError = PVRSRVRemovePowerDevice (((PVRSRV_DEVICE_NODE*)pvDeviceNode)->sDevId.ui32DeviceIndex);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ eError = SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX,
+ (IMG_VOID**)&psSGXDeviceMap);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DevDeInitSGX: Failed to get device memory map!"));
+ return eError;
+ }
+
+
+ if (!psSGXDeviceMap->pvRegsCpuVBase)
+ {
+
+ if (psDevInfo->pvRegsBaseKM != IMG_NULL)
+ {
+ OSUnMapPhysToLin(psDevInfo->pvRegsBaseKM,
+ psDevInfo->ui32RegSize,
+ PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+ IMG_NULL);
+ }
+ }
+
+#if defined(SGX_FEATURE_HOST_PORT)
+ if (psSGXDeviceMap->ui32Flags & SGX_HOSTPORT_PRESENT)
+ {
+
+ if (psDevInfo->pvHostPortBaseKM != IMG_NULL)
+ {
+ OSUnMapPhysToLin(psDevInfo->pvHostPortBaseKM,
+ psDevInfo->ui32HPSize,
+ PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
+ IMG_NULL);
+ }
+ }
+#endif
+
+
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_SGXDEV_INFO),
+ psDevInfo,
+ 0);
+
+ psDeviceNode->pvDevice = IMG_NULL;
+
+ if (psDeviceMemoryHeap != IMG_NULL)
+ {
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(DEVICE_MEMORY_HEAP_INFO) * SGX_MAX_HEAP_ID,
+ psDeviceMemoryHeap,
+ 0);
+ }
+
+ return PVRSRV_OK;
+}
+
+
+static IMG_VOID SGXDumpDebugReg (PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32CoreNum,
+ IMG_CHAR *pszName,
+ IMG_UINT32 ui32RegAddr)
+{
+ IMG_UINT32 ui32RegVal;
+ ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(ui32RegAddr, ui32CoreNum));
+ PVR_LOG(("(P%u) %s%08X", ui32CoreNum, pszName, ui32RegVal));
+}
+
+static IMG_VOID SGXDumpDebugInfo (PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_BOOL bDumpSGXRegs)
+{
+ IMG_UINT32 ui32CoreNum;
+
+ PVR_LOG(("SGX debug (%s)", PVRVERSION_STRING));
+
+ if (bDumpSGXRegs)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGX Register Base Address (Linear): 0x%08X", (IMG_UINTPTR_T)psDevInfo->pvRegsBaseKM));
+ PVR_DPF((PVR_DBG_ERROR,"SGX Register Base Address (Physical): 0x%08X", psDevInfo->sRegsPhysBase.uiAddr));
+
+ for (ui32CoreNum = 0; ui32CoreNum < SGX_FEATURE_MP_CORE_COUNT; ui32CoreNum++)
+ {
+
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_EVENT_STATUS: ", EUR_CR_EVENT_STATUS);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_EVENT_STATUS2: ", EUR_CR_EVENT_STATUS2);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_BIF_CTRL: ", EUR_CR_BIF_CTRL);
+ #if defined(EUR_CR_BIF_BANK0)
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_BIF_BANK0: ", EUR_CR_BIF_BANK0);
+ #endif
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_BIF_INT_STAT: ", EUR_CR_BIF_INT_STAT);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_BIF_FAULT: ", EUR_CR_BIF_FAULT);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_BIF_MEM_REQ_STAT: ", EUR_CR_BIF_MEM_REQ_STAT);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_CLKGATECTL: ", EUR_CR_CLKGATECTL);
+ #if defined(EUR_CR_PDS_PC_BASE)
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_PDS_PC_BASE: ", EUR_CR_PDS_PC_BASE);
+ #endif
+ }
+ }
+
+
+
+ QueueDumpDebugInfo();
+
+ {
+
+
+ IMG_UINT32 *pui32HostCtlBuffer = (IMG_UINT32 *)psDevInfo->psSGXHostCtl;
+ IMG_UINT32 ui32LoopCounter;
+
+ PVR_LOG(("SGX Host control:"));
+
+ for (ui32LoopCounter = 0;
+ ui32LoopCounter < sizeof(*psDevInfo->psSGXHostCtl) / sizeof(*pui32HostCtlBuffer);
+ ui32LoopCounter += 4)
+ {
+ PVR_LOG(("\t(HC-%X) 0x%08X 0x%08X 0x%08X 0x%08X", ui32LoopCounter * sizeof(*pui32HostCtlBuffer),
+ pui32HostCtlBuffer[ui32LoopCounter + 0], pui32HostCtlBuffer[ui32LoopCounter + 1],
+ pui32HostCtlBuffer[ui32LoopCounter + 2], pui32HostCtlBuffer[ui32LoopCounter + 3]));
+ }
+ }
+
+ {
+
+
+ IMG_UINT32 *pui32TA3DCtlBuffer = psDevInfo->psKernelSGXTA3DCtlMemInfo->pvLinAddrKM;
+ IMG_UINT32 ui32LoopCounter;
+
+ PVR_LOG(("SGX TA/3D control:"));
+
+ for (ui32LoopCounter = 0;
+ ui32LoopCounter < psDevInfo->psKernelSGXTA3DCtlMemInfo->ui32AllocSize / sizeof(*pui32TA3DCtlBuffer);
+ ui32LoopCounter += 4)
+ {
+ PVR_LOG(("\t(T3C-%X) 0x%08X 0x%08X 0x%08X 0x%08X", ui32LoopCounter * sizeof(*pui32TA3DCtlBuffer),
+ pui32TA3DCtlBuffer[ui32LoopCounter + 0], pui32TA3DCtlBuffer[ui32LoopCounter + 1],
+ pui32TA3DCtlBuffer[ui32LoopCounter + 2], pui32TA3DCtlBuffer[ui32LoopCounter + 3]));
+ }
+ }
+
+ #if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+ {
+ IMG_UINT32 *pui32MKTraceBuffer = psDevInfo->psKernelEDMStatusBufferMemInfo->pvLinAddrKM;
+ IMG_UINT32 ui32LastStatusCode, ui32WriteOffset;
+
+ ui32LastStatusCode = *pui32MKTraceBuffer;
+ pui32MKTraceBuffer++;
+ ui32WriteOffset = *pui32MKTraceBuffer;
+ pui32MKTraceBuffer++;
+
+ PVR_LOG(("Last SGX microkernel status code: %08X", ui32LastStatusCode));
+
+ #if defined(PVRSRV_DUMP_MK_TRACE)
+
+
+ {
+ IMG_UINT32 ui32LoopCounter;
+
+ for (ui32LoopCounter = 0;
+ ui32LoopCounter < SGXMK_TRACE_BUFFER_SIZE;
+ ui32LoopCounter++)
+ {
+ IMG_UINT32 *pui32BufPtr;
+ pui32BufPtr = pui32MKTraceBuffer +
+ (((ui32WriteOffset + ui32LoopCounter) % SGXMK_TRACE_BUFFER_SIZE) * 4);
+ PVR_LOG(("\t(MKT-%X) %08X %08X %08X %08X", ui32LoopCounter,
+ pui32BufPtr[2], pui32BufPtr[3], pui32BufPtr[1], pui32BufPtr[0]));
+ }
+ }
+ #endif
+ }
+ #endif
+
+ {
+
+
+ PVR_LOG(("SGX Kernel CCB WO:0x%X RO:0x%X",
+ psDevInfo->psKernelCCBCtl->ui32WriteOffset,
+ psDevInfo->psKernelCCBCtl->ui32ReadOffset));
+
+ #if defined(PVRSRV_DUMP_KERNEL_CCB)
+ {
+ IMG_UINT32 ui32LoopCounter;
+
+ for (ui32LoopCounter = 0;
+ ui32LoopCounter < sizeof(psDevInfo->psKernelCCB->asCommands) /
+ sizeof(psDevInfo->psKernelCCB->asCommands[0]);
+ ui32LoopCounter++)
+ {
+ SGXMKIF_COMMAND *psCommand = &psDevInfo->psKernelCCB->asCommands[ui32LoopCounter];
+
+ PVR_LOG(("\t(KCCB-%X) %08X %08X - %08X %08X %08X %08X", ui32LoopCounter,
+ psCommand->ui32ServiceAddress, psCommand->ui32CacheControl,
+ psCommand->ui32Data[0], psCommand->ui32Data[1],
+ psCommand->ui32Data[2], psCommand->ui32Data[3]));
+ }
+ }
+ #endif
+ }
+}
+
+
+#if defined(SYS_USING_INTERRUPTS) || defined(SUPPORT_HW_RECOVERY)
+static
+IMG_VOID HWRecoveryResetSGX (PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 ui32Component,
+ IMG_UINT32 ui32CallerID)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+ SGXMKIF_HOST_CTL *psSGXHostCtl = (SGXMKIF_HOST_CTL *)psDevInfo->psSGXHostCtl;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Component);
+
+
+
+ eError = PVRSRVPowerLock(ui32CallerID, IMG_FALSE);
+ if(eError != PVRSRV_OK)
+ {
+
+
+
+ PVR_DPF((PVR_DBG_WARNING,"HWRecoveryResetSGX: Power transition in progress"));
+ return;
+ }
+
+ psSGXHostCtl->ui32InterruptClearFlags |= PVRSRV_USSE_EDM_INTERRUPT_HWR;
+
+ PVR_LOG(("HWRecoveryResetSGX: SGX Hardware Recovery triggered"));
+
+ SGXDumpDebugInfo(psDeviceNode->pvDevice, IMG_TRUE);
+
+
+ PDUMPSUSPEND();
+
+
+#if defined(FIX_HW_BRN_23281)
+
+ for (eError = PVRSRV_ERROR_RETRY; eError == PVRSRV_ERROR_RETRY;)
+#endif
+ {
+ eError = SGXInitialise(psDevInfo, IMG_TRUE);
+ }
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"HWRecoveryResetSGX: SGXInitialise failed (%d)", eError));
+ }
+
+
+ PDUMPRESUME();
+
+ PVRSRVPowerUnlock(ui32CallerID);
+
+
+ SGXScheduleProcessQueuesKM(psDeviceNode);
+
+
+
+ PVRSRVProcessQueues(ui32CallerID, IMG_TRUE);
+}
+#endif
+
+
+#if defined(SUPPORT_HW_RECOVERY)
+IMG_VOID SGXOSTimer(IMG_VOID *pvData)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode = pvData;
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ static IMG_UINT32 ui32EDMTasks = 0;
+ static IMG_UINT32 ui32LockupCounter = 0;
+ static IMG_UINT32 ui32NumResets = 0;
+#if defined(FIX_HW_BRN_31093)
+ static IMG_BOOL bBRN31093Inval = IMG_FALSE;
+#endif
+ IMG_UINT32 ui32CurrentEDMTasks;
+ IMG_BOOL bLockup = IMG_FALSE;
+ IMG_BOOL bPoweredDown;
+
+
+ psDevInfo->ui32TimeStamp++;
+
+#if defined(NO_HARDWARE)
+ bPoweredDown = IMG_TRUE;
+#else
+ bPoweredDown = (SGXIsDevicePowered(psDeviceNode)) ? IMG_FALSE : IMG_TRUE;
+#endif
+
+
+
+ if (bPoweredDown)
+ {
+ ui32LockupCounter = 0;
+ #if defined(FIX_HW_BRN_31093)
+ bBRN31093Inval = IMG_FALSE;
+ #endif
+ }
+ else
+ {
+
+ ui32CurrentEDMTasks = OSReadHWReg(psDevInfo->pvRegsBaseKM, psDevInfo->ui32EDMTaskReg0);
+ if (psDevInfo->ui32EDMTaskReg1 != 0)
+ {
+ ui32CurrentEDMTasks ^= OSReadHWReg(psDevInfo->pvRegsBaseKM, psDevInfo->ui32EDMTaskReg1);
+ }
+ if ((ui32CurrentEDMTasks == ui32EDMTasks) &&
+ (psDevInfo->ui32NumResets == ui32NumResets))
+ {
+ ui32LockupCounter++;
+ if (ui32LockupCounter == 3)
+ {
+ ui32LockupCounter = 0;
+
+ #if defined(FIX_HW_BRN_31093)
+ if (bBRN31093Inval == IMG_FALSE)
+ {
+
+ #if defined(FIX_HW_BRN_29997)
+ IMG_UINT32 ui32BIFCtrl;
+
+ ui32BIFCtrl = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl | EUR_CR_BIF_CTRL_PAUSE_MASK);
+
+ OSWaitus(200 * 1000000 / psDevInfo->ui32CoreClockSpeed);
+ #endif
+
+ bBRN31093Inval = IMG_TRUE;
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL_INVAL, EUR_CR_BIF_CTRL_INVAL_PTE_MASK);
+
+ OSWaitus(200 * 1000000 / psDevInfo->ui32CoreClockSpeed);
+
+ #if defined(FIX_HW_BRN_29997)
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl);
+ #endif
+ }
+ else
+ #endif
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXOSTimer() detected SGX lockup (0x%x tasks)", ui32EDMTasks));
+
+ bLockup = IMG_TRUE;
+ }
+ }
+ }
+ else
+ {
+ #if defined(FIX_HW_BRN_31093)
+ bBRN31093Inval = IMG_FALSE;
+ #endif
+ ui32LockupCounter = 0;
+ ui32EDMTasks = ui32CurrentEDMTasks;
+ ui32NumResets = psDevInfo->ui32NumResets;
+ }
+ }
+
+ if (bLockup)
+ {
+ SGXMKIF_HOST_CTL *psSGXHostCtl = (SGXMKIF_HOST_CTL *)psDevInfo->psSGXHostCtl;
+
+
+ psSGXHostCtl->ui32HostDetectedLockups ++;
+
+
+ HWRecoveryResetSGX(psDeviceNode, 0, KERNEL_ID);
+ }
+}
+#endif
+
+
+#if defined(SYS_USING_INTERRUPTS)
+
+IMG_BOOL SGX_ISRHandler (IMG_VOID *pvData)
+{
+ IMG_BOOL bInterruptProcessed = IMG_FALSE;
+
+
+
+ {
+ IMG_UINT32 ui32EventStatus, ui32EventEnable;
+ IMG_UINT32 ui32EventClear = 0;
+#if defined(SGX_FEATURE_DATA_BREAKPOINTS)
+ IMG_UINT32 ui32EventStatus2, ui32EventEnable2;
+#endif
+ IMG_UINT32 ui32EventClear2 = 0;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+
+
+ if(pvData == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGX_ISRHandler: Invalid params\n"));
+ return bInterruptProcessed;
+ }
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE *)pvData;
+ psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+
+ ui32EventStatus = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS);
+ ui32EventEnable = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_ENABLE);
+
+
+ ui32EventStatus &= ui32EventEnable;
+
+#if defined(SGX_FEATURE_DATA_BREAKPOINTS)
+ ui32EventStatus2 = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS2);
+ ui32EventEnable2 = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_ENABLE2);
+
+
+ ui32EventStatus2 &= ui32EventEnable2;
+#endif
+
+
+
+ if (ui32EventStatus & EUR_CR_EVENT_STATUS_SW_EVENT_MASK)
+ {
+ ui32EventClear |= EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_MASK;
+ }
+
+#if defined(SGX_FEATURE_DATA_BREAKPOINTS)
+ if (ui32EventStatus2 & EUR_CR_EVENT_STATUS2_DATA_BREAKPOINT_UNTRAPPED_MASK)
+ {
+ ui32EventClear2 |= EUR_CR_EVENT_HOST_CLEAR2_DATA_BREAKPOINT_UNTRAPPED_MASK;
+ }
+
+ if (ui32EventStatus2 & EUR_CR_EVENT_STATUS2_DATA_BREAKPOINT_TRAPPED_MASK)
+ {
+ ui32EventClear2 |= EUR_CR_EVENT_HOST_CLEAR2_DATA_BREAKPOINT_TRAPPED_MASK;
+ }
+#endif
+
+ if (ui32EventClear || ui32EventClear2)
+ {
+ bInterruptProcessed = IMG_TRUE;
+
+
+ ui32EventClear |= EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK;
+
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR, ui32EventClear);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR2, ui32EventClear2);
+ }
+ }
+
+ return bInterruptProcessed;
+}
+
+
+static IMG_VOID SGX_MISRHandler (IMG_VOID *pvData)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvData;
+ PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
+ SGXMKIF_HOST_CTL *psSGXHostCtl = (SGXMKIF_HOST_CTL *)psDevInfo->psSGXHostCtl;
+
+ if (((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_HWR) != 0UL) &&
+ ((psSGXHostCtl->ui32InterruptClearFlags & PVRSRV_USSE_EDM_INTERRUPT_HWR) == 0UL))
+ {
+ HWRecoveryResetSGX(psDeviceNode, 0, ISR_ID);
+ }
+
+#if defined(OS_SUPPORTS_IN_LISR)
+ if (psDeviceNode->bReProcessDeviceCommandComplete)
+ {
+ SGXScheduleProcessQueuesKM(psDeviceNode);
+ }
+#endif
+
+ SGXTestActivePowerEvent(psDeviceNode, ISR_ID);
+
+ pvr_trcmd_check_syn_completions(PVR_TRCMD_SGX_COMP);
+}
+#endif
+
+
+
+#if defined(SUPPORT_MEMORY_TILING)
+PVRSRV_ERROR SGX_AllocMemTilingRange(PVRSRV_DEVICE_NODE *psDeviceNode,
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32TilingStride,
+ IMG_UINT32 *pui32RangeIndex)
+{
+#if defined(SGX_FEATURE_BIF_WIDE_TILING_AND_4K_ADDRESS)
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ IMG_UINT32 i;
+ IMG_UINT32 ui32Start;
+ IMG_UINT32 ui32End;
+ IMG_UINT32 ui32Offset;
+ IMG_UINT32 ui32Val;
+
+
+ for(i=0; i<10; i++)
+ {
+ if((psDevInfo->ui32MemTilingUsage & (1U << i)) == 0)
+ {
+
+ psDevInfo->ui32MemTilingUsage |= 1U << i;
+
+ *pui32RangeIndex = i;
+ goto RangeAllocated;
+ }
+ }
+
+ PVR_DPF((PVR_DBG_ERROR,"SGX_AllocMemTilingRange: all tiling ranges in use"));
+ return PVRSRV_ERROR_EXCEEDED_HW_LIMITS;
+
+RangeAllocated:
+ ui32Offset = EUR_CR_BIF_TILE0 + (i<<2);
+
+ ui32Start = psMemInfo->sDevVAddr.uiAddr;
+ ui32End = ui32Start + psMemInfo->ui32AllocSize + SGX_MMU_PAGE_SIZE - 1;
+
+ ui32Val = ((ui32TilingStride << EUR_CR_BIF_TILE0_CFG_SHIFT) & EUR_CR_BIF_TILE0_CFG_MASK)
+ | (((ui32End>>20) << EUR_CR_BIF_TILE0_MAX_ADDRESS_SHIFT) & EUR_CR_BIF_TILE0_MAX_ADDRESS_MASK)
+ | (((ui32Start>>20) << EUR_CR_BIF_TILE0_MIN_ADDRESS_SHIFT) & EUR_CR_BIF_TILE0_MIN_ADDRESS_MASK)
+ | (0x8 << EUR_CR_BIF_TILE0_CFG_SHIFT);
+
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32Offset, ui32Val);
+ PDUMPREG(SGX_PDUMPREG_NAME, ui32Offset, ui32Val);
+
+ ui32Offset = EUR_CR_BIF_TILE0_ADDR_EXT + (i<<2);
+
+ ui32Val = (((ui32End>>12) << EUR_CR_BIF_TILE0_ADDR_EXT_MAX_SHIFT) & EUR_CR_BIF_TILE0_ADDR_EXT_MAX_MASK)
+ | (((ui32Start>>12) << EUR_CR_BIF_TILE0_ADDR_EXT_MIN_SHIFT) & EUR_CR_BIF_TILE0_ADDR_EXT_MIN_MASK);
+
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32Offset, ui32Val);
+ PDUMPREG(SGX_PDUMPREG_NAME, ui32Offset, ui32Val);
+
+ return PVRSRV_OK;
+#else
+ PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+ PVR_UNREFERENCED_PARAMETER(psMemInfo);
+ PVR_UNREFERENCED_PARAMETER(ui32TilingStride);
+ PVR_UNREFERENCED_PARAMETER(pui32RangeIndex);
+
+ PVR_DPF((PVR_DBG_ERROR,"SGX_AllocMemTilingRange: device does not support memory tiling"));
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+#endif
+}
+
+PVRSRV_ERROR SGX_FreeMemTilingRange(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 ui32RangeIndex)
+{
+#if defined(SGX_FEATURE_BIF_WIDE_TILING_AND_4K_ADDRESS)
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ IMG_UINT32 ui32Offset;
+ IMG_UINT32 ui32Val;
+
+ if(ui32RangeIndex >= 10)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGX_FreeMemTilingRange: invalid Range index "));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ psDevInfo->ui32MemTilingUsage &= ~(1<<ui32RangeIndex);
+
+
+ ui32Offset = EUR_CR_BIF_TILE0 + (ui32RangeIndex<<2);
+ ui32Val = 0;
+
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32Offset, ui32Val);
+ PDUMPREG(SGX_PDUMPREG_NAME, ui32Offset, ui32Val);
+
+ return PVRSRV_OK;
+#else
+ PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+ PVR_UNREFERENCED_PARAMETER(ui32RangeIndex);
+
+ PVR_DPF((PVR_DBG_ERROR,"SGX_FreeMemTilingRange: device does not support memory tiling"));
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+#endif
+}
+#endif
+
+#if defined(PVRSRV_RESOURCE_PROFILING)
+static
+PVRSRV_ERROR SGXAccumlateMapRes(PRESMAN_ITEM psRes, va_list va)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode = IMG_NULL;
+ IMG_UINT32 *pui32UsedPrivateMem = IMG_NULL, *pui32UsedSharedMem = IMG_NULL;
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+ BM_BUF *psBuf;
+ psDeviceNode = va_arg(va, PVRSRV_DEVICE_NODE*);
+ pui32UsedPrivateMem = va_arg(va, IMG_UINT32*);
+ pui32UsedSharedMem = va_arg(va, IMG_UINT32*);
+ if (!psDeviceNode || !pui32UsedPrivateMem || !pui32UsedSharedMem) {
+ PVR_LOG(("DBGRESPROF:wrong prarmeter\n"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ /*if (psRes->ui32ResType != RESMAN_TYPE_DEVICEMEM_MAPPING)
+ PVR_LOG(("DBGRESPROF:wrong resource type\n"));*/
+
+ psMemInfo = PVRSRVGetMapMemInfo(PVRSRVGetResData(psRes));
+ psBuf = psMemInfo->sMemBlk.hBuffer;
+ if (psDeviceNode == psBuf->pMapping->pBMHeap->pBMContext->psDeviceNode)
+ {
+ *pui32UsedSharedMem += psMemInfo->ui32AllocSize;
+ if (psMemInfo->psKernelSyncInfo)
+ *pui32UsedSharedMem += psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->ui32AllocSize;
+ }
+ return PVRSRV_OK;
+}
+static
+PVRSRV_ERROR SGXAccumlateAllocRes(PRESMAN_ITEM psRes, va_list va)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode = IMG_NULL;
+ IMG_UINT32 *pui32UsedPrivateMem = IMG_NULL, *pui32UsedExportedMem = IMG_NULL;
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+ BM_BUF *psBuf;
+ psDeviceNode = va_arg(va, PVRSRV_DEVICE_NODE*);
+ pui32UsedPrivateMem = va_arg(va, IMG_UINT32*);
+ pui32UsedExportedMem = va_arg(va, IMG_UINT32*);
+ if (!psDeviceNode || !pui32UsedPrivateMem || !pui32UsedExportedMem) {
+ PVR_LOG(("DBGRESPROF:wrong prarmeter\n"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ /*if (psRes->ui32ResType != RESMAN_TYPE_DEVICEMEM_ALLOCATION)
+ PVR_LOG(("DBGRESPROF:wrong resource type\n"));*/
+
+ psMemInfo = PVRSRVGetResData(psRes);
+ psBuf = psMemInfo->sMemBlk.hBuffer;
+ if (psDeviceNode == psBuf->pMapping->pBMHeap->pBMContext->psDeviceNode)
+ {
+ if (psBuf->ui32ExportCount)
+ {
+ *pui32UsedExportedMem += psMemInfo->ui32AllocSize;
+ if (psMemInfo->psKernelSyncInfo)
+ *pui32UsedExportedMem += psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->ui32AllocSize;
+ }
+ else
+ {
+ *pui32UsedPrivateMem += psMemInfo->ui32AllocSize;
+ if (psMemInfo->psKernelSyncInfo)
+ *pui32UsedPrivateMem += psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->ui32AllocSize;
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+
+static
+IMG_VOID SGXAccumlateUsedMem(PVRSRV_PER_PROCESS_DATA* psProc, va_list va)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ SGX_MISC_INFO *psMiscInfo;
+ IMG_UINT32 ui32UsedPrivateMem = 0, ui32UsedSharedMem = 0, ui32UsedExportedMem = 0;
+ PVRSRV_SGX_RESOURCE_INFO *psSGXResInfo;
+ psDeviceNode = va_arg(va, PVRSRV_DEVICE_NODE*);
+ psMiscInfo = va_arg(va, SGX_MISC_INFO*);
+ psSGXResInfo = &psMiscInfo->uData.sSGXResourceInfo;
+
+ PVRSRVResManAnyByCriteria(psProc->hResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_ALLOCATION, 0,
+ 0, &SGXAccumlateAllocRes, psDeviceNode, &ui32UsedPrivateMem, &ui32UsedExportedMem);
+ PVRSRVResManAnyByCriteria(psProc->hResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_MAPPING, 0,
+ 0, &SGXAccumlateMapRes, psDeviceNode, &ui32UsedPrivateMem, &ui32UsedSharedMem);
+ psSGXResInfo->ui32UsedMem += ui32UsedPrivateMem;
+ psSGXResInfo->ui32UsedMem += ui32UsedExportedMem;
+ /*PVR_LOG(("MarkTu ID:%d, used:%d, shared:%d\n", psProc->ui32PID, ui32UsedPrivateMem, ui32UsedSharedMem));*/
+ if ((psMiscInfo->eRequest == SGX_MISC_INFO_RESOURCEPROF_GLOBAL) &&
+ (ui32UsedPrivateMem || ui32UsedSharedMem) &&
+ (psSGXResInfo->ui32ProcCnt < MAX_PROC))
+ {
+ psSGXResInfo->aui32ProcMem[psSGXResInfo->ui32ProcCnt][0] = psProc->ui32PID;
+ psSGXResInfo->aui32ProcMem[psSGXResInfo->ui32ProcCnt][1] = ui32UsedPrivateMem;
+ psSGXResInfo->aui32ProcMem[psSGXResInfo->ui32ProcCnt][2] = ui32UsedExportedMem + ui32UsedSharedMem;
+ psSGXResInfo->ui32ProcCnt++;
+ }
+ if(psSGXResInfo->ui32ProcCnt >= MAX_PROC)
+ PVR_LOG(("DBGRESPROF:Maxiam process number exceed\n"));
+
+}
+static
+PVRSRV_ERROR SGXGetResourceProfile(SGX_MISC_INFO *psMiscInfo, PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVRSRV_MEM_INFO sMemInfo;
+ IMG_UINT32 ui32FreeMem;
+ PVRSRV_PER_PROCESS_DATA* psPerProcList;
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ if (!psMiscInfo || !psDeviceNode)
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ OSGetMemoryInfo(&sMemInfo);
+ ui32FreeMem = sMemInfo.ui32FreeMem / 2;
+ OSMemSet(&psMiscInfo->uData.sSGXResourceInfo, 0,sizeof(psMiscInfo->uData.sSGXResourceInfo));
+ psPerProcList = PVRSRVPerProcessList();
+ List_PVRSRV_PER_PROCESS_DATA_ForEach_va(psPerProcList,
+ &SGXAccumlateUsedMem,
+ psDeviceNode,
+ psMiscInfo);
+ if(psMiscInfo->uData.sSGXResourceInfo.ui32UsedMem != *psDevInfo->pui32UsedMem)
+ {
+ PVR_LOG(("Usedmem:cal:%d;stat:%d\n", psMiscInfo->uData.sSGXResourceInfo.ui32UsedMem,
+ *psDevInfo->pui32UsedMem));
+ }
+ psMiscInfo->uData.sSGXResourceInfo.ui32TotalMem = ui32FreeMem + psMiscInfo->uData.sSGXResourceInfo.ui32UsedMem;
+
+ return PVRSRV_OK;
+}
+
+static
+PVRSRV_ERROR SGXGetResProfMemInfo(SGX_MISC_INFO *psMiscInfo, PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVRSRV_CLIENT_MEM_INFO *psSGXResProfMemInfo;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = ((PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice)->psResProfMemInfo;
+ psSGXResProfMemInfo = &psMiscInfo->uData.sSGXResProfMemInfo;
+ OSMemSet(psSGXResProfMemInfo,
+ 0,
+ sizeof(*psSGXResProfMemInfo));
+
+ psSGXResProfMemInfo->pvLinAddrKM =
+ psKernelMemInfo->pvLinAddrKM;
+
+ psSGXResProfMemInfo->pvLinAddr = 0;
+ psSGXResProfMemInfo->ui32Flags =
+ psKernelMemInfo->ui32Flags;
+ psSGXResProfMemInfo->ui32AllocSize =
+ psKernelMemInfo->ui32AllocSize;
+ psSGXResProfMemInfo->hMappingInfo = psKernelMemInfo->sMemBlk.hOSMemHandle;
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR SGXResProfiling(IMG_VOID *pvDeviceNode, IMG_UINT32 ui32AllocedMem, IMG_BOOL bAlloc)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE*)pvDeviceNode;
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ SYS_DATA* psSysData = IMG_NULL;
+ IMG_HANDLE hOSEventKM;
+
+ if (!psDevInfo || psDeviceNode->sDevId.eDeviceType != PVRSRV_DEVICE_TYPE_SGX)
+ {
+ PVR_LOG(("SGXResProfiling:invalid psDevInfo or invaid device type"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ if(bAlloc)
+ {
+ *psDevInfo->pui32UsedMem += ui32AllocedMem;
+ }
+ else
+ {
+ *psDevInfo->pui32UsedMem -= ui32AllocedMem;
+ }
+ SysAcquireData(&psSysData);
+ if (psSysData->psGlobalEventObject)
+ {
+ hOSEventKM = psSysData->psGlobalEventObject->hOSEventKM;
+ if(hOSEventKM)
+ {
+ OSEventObjectSignal(hOSEventKM);
+ }
+ }
+ return PVRSRV_OK;
+}
+
+#endif
+PVRSRV_ERROR SGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ DEVICE_MEMORY_INFO *psDevMemoryInfo;
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+
+
+ psDeviceNode->sDevId.eDeviceType = DEV_DEVICE_TYPE;
+ psDeviceNode->sDevId.eDeviceClass = DEV_DEVICE_CLASS;
+#if defined(PDUMP)
+ {
+
+ SGX_DEVICE_MAP *psSGXDeviceMemMap;
+ SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX,
+ (IMG_VOID**)&psSGXDeviceMemMap);
+
+ psDeviceNode->sDevId.pszPDumpDevName = psSGXDeviceMemMap->pszPDumpDevName;
+ PVR_ASSERT(psDeviceNode->sDevId.pszPDumpDevName != IMG_NULL);
+ }
+
+ psDeviceNode->sDevId.pszPDumpRegName = SGX_PDUMPREG_NAME;
+#endif
+
+ psDeviceNode->pfnInitDevice = &DevInitSGXPart1;
+ psDeviceNode->pfnDeInitDevice = &DevDeInitSGX;
+
+ psDeviceNode->pfnInitDeviceCompatCheck = &SGXDevInitCompatCheck;
+#if defined(PDUMP)
+ psDeviceNode->pfnPDumpInitDevice = &SGXResetPDump;
+ psDeviceNode->pfnMMUGetContextID = &MMU_GetPDumpContextID;
+#endif
+
+
+ psDeviceNode->pfnMMUInitialise = &MMU_Initialise;
+ psDeviceNode->pfnMMUFinalise = &MMU_Finalise;
+ psDeviceNode->pfnMMUInsertHeap = &MMU_InsertHeap;
+ psDeviceNode->pfnMMUCreate = &MMU_Create;
+ psDeviceNode->pfnMMUDelete = &MMU_Delete;
+ psDeviceNode->pfnMMUAlloc = &MMU_Alloc;
+ psDeviceNode->pfnMMUFree = &MMU_Free;
+ psDeviceNode->pfnMMUMapPages = &MMU_MapPages;
+ psDeviceNode->pfnMMUMapShadow = &MMU_MapShadow;
+ psDeviceNode->pfnMMUUnmapPages = &MMU_UnmapPages;
+ psDeviceNode->pfnMMUMapScatter = &MMU_MapScatter;
+ psDeviceNode->pfnMMUGetPhysPageAddr = &MMU_GetPhysPageAddr;
+ psDeviceNode->pfnMMUGetPDDevPAddr = &MMU_GetPDDevPAddr;
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+ psDeviceNode->pfnMMUIsHeapShared = &MMU_IsHeapShared;
+#endif
+
+#if defined (SYS_USING_INTERRUPTS)
+
+
+ psDeviceNode->pfnDeviceISR = SGX_ISRHandler;
+ psDeviceNode->pfnDeviceMISR = SGX_MISRHandler;
+#endif
+
+#if defined(SUPPORT_MEMORY_TILING)
+ psDeviceNode->pfnAllocMemTilingRange = SGX_AllocMemTilingRange;
+ psDeviceNode->pfnFreeMemTilingRange = SGX_FreeMemTilingRange;
+#endif
+
+#if defined(PVRSRV_RESOURCE_PROFILING)
+ psDeviceNode->pfnResProfCB = &SGXResProfiling;
+#endif
+
+ psDeviceNode->pfnDeviceCommandComplete = &SGXCommandComplete;
+
+
+
+ psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+
+ psDevMemoryInfo->ui32AddressSpaceSizeLog2 = SGX_FEATURE_ADDRESS_SPACE_SIZE;
+
+
+ psDevMemoryInfo->ui32Flags = 0;
+
+
+ if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(DEVICE_MEMORY_HEAP_INFO) * SGX_MAX_HEAP_ID,
+ (IMG_VOID **)&psDevMemoryInfo->psDeviceMemoryHeap, 0,
+ "Array of Device Memory Heap Info") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXRegisterDevice : Failed to alloc memory for DEVICE_MEMORY_HEAP_INFO"));
+ return (PVRSRV_ERROR_OUT_OF_MEMORY);
+ }
+ OSMemSet(psDevMemoryInfo->psDeviceMemoryHeap, 0, sizeof(DEVICE_MEMORY_HEAP_INFO) * SGX_MAX_HEAP_ID);
+
+ psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
+
+
+
+
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_GENERAL_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_GENERAL_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_GENERAL_HEAP_SIZE;
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_SINGLE_PROCESS;
+ psDeviceMemoryHeap->pszName = "General";
+ psDeviceMemoryHeap->pszBSName = "General BS";
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+#if !defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+
+ psDevMemoryInfo->ui32MappingHeapID = (IMG_UINT32)(psDeviceMemoryHeap - psDevMemoryInfo->psDeviceMemoryHeap);
+#endif
+ psDeviceMemoryHeap++;
+
+
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_TADATA_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_TADATA_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_TADATA_HEAP_SIZE;
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_MULTI_PROCESS;
+ psDeviceMemoryHeap->pszName = "TA Data";
+ psDeviceMemoryHeap->pszBSName = "TA Data BS";
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+ psDeviceMemoryHeap++;
+
+
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_KERNEL_CODE_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_KERNEL_CODE_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_KERNEL_CODE_HEAP_SIZE;
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_MULTI_PROCESS;
+ psDeviceMemoryHeap->pszName = "Kernel Code";
+ psDeviceMemoryHeap->pszBSName = "Kernel Code BS";
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+ psDeviceMemoryHeap++;
+
+
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_KERNEL_DATA_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_KERNEL_DATA_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_KERNEL_DATA_HEAP_SIZE;
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_MULTI_PROCESS;
+ psDeviceMemoryHeap->pszName = "KernelData";
+ psDeviceMemoryHeap->pszBSName = "KernelData BS";
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+ psDeviceMemoryHeap++;
+
+
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_PIXELSHADER_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_PIXELSHADER_HEAP_BASE;
+
+
+
+
+
+
+ psDeviceMemoryHeap->ui32HeapSize = ((10 << SGX_USE_CODE_SEGMENT_RANGE_BITS) - 0x00001000);
+ PVR_ASSERT(psDeviceMemoryHeap->ui32HeapSize <= SGX_PIXELSHADER_HEAP_SIZE);
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_SINGLE_PROCESS;
+ psDeviceMemoryHeap->pszName = "PixelShaderUSSE";
+ psDeviceMemoryHeap->pszBSName = "PixelShaderUSSE BS";
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+ psDeviceMemoryHeap++;
+
+
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_VERTEXSHADER_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_VERTEXSHADER_HEAP_BASE;
+
+ psDeviceMemoryHeap->ui32HeapSize = ((4 << SGX_USE_CODE_SEGMENT_RANGE_BITS) - 0x00001000);
+ PVR_ASSERT(psDeviceMemoryHeap->ui32HeapSize <= SGX_VERTEXSHADER_HEAP_SIZE);
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_SINGLE_PROCESS;
+ psDeviceMemoryHeap->pszName = "VertexShaderUSSE";
+ psDeviceMemoryHeap->pszBSName = "VertexShaderUSSE BS";
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+ psDeviceMemoryHeap++;
+
+
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_PDSPIXEL_CODEDATA_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_PDSPIXEL_CODEDATA_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_PDSPIXEL_CODEDATA_HEAP_SIZE;
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_SINGLE_PROCESS;
+ psDeviceMemoryHeap->pszName = "PDSPixelCodeData";
+ psDeviceMemoryHeap->pszBSName = "PDSPixelCodeData BS";
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+ psDeviceMemoryHeap++;
+
+
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_PDSVERTEX_CODEDATA_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_PDSVERTEX_CODEDATA_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_PDSVERTEX_CODEDATA_HEAP_SIZE;
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_SINGLE_PROCESS;
+ psDeviceMemoryHeap->pszName = "PDSVertexCodeData";
+ psDeviceMemoryHeap->pszBSName = "PDSVertexCodeData BS";
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+ psDeviceMemoryHeap++;
+
+
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_SYNCINFO_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_SYNCINFO_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_SYNCINFO_HEAP_SIZE;
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_MULTI_PROCESS;
+ psDeviceMemoryHeap->pszName = "CacheCoherent";
+ psDeviceMemoryHeap->pszBSName = "CacheCoherent BS";
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+
+ psDevMemoryInfo->ui32SyncHeapID = (IMG_UINT32)(psDeviceMemoryHeap - psDevMemoryInfo->psDeviceMemoryHeap);
+ psDeviceMemoryHeap++;
+
+
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_3DPARAMETERS_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_3DPARAMETERS_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_3DPARAMETERS_HEAP_SIZE;
+ psDeviceMemoryHeap->pszName = "3DParameters";
+ psDeviceMemoryHeap->pszBSName = "3DParameters BS";
+#if defined(SUPPORT_PERCONTEXT_PB)
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_SINGLE_PROCESS;
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+#else
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_MULTI_PROCESS;
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+#endif
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+ psDeviceMemoryHeap++;
+
+
+#if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_GENERAL_MAPPING_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_GENERAL_MAPPING_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_GENERAL_MAPPING_HEAP_SIZE;
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_MULTI_PROCESS;
+ psDeviceMemoryHeap->pszName = "GeneralMapping";
+ psDeviceMemoryHeap->pszBSName = "GeneralMapping BS";
+ #if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS) && defined(FIX_HW_BRN_23410)
+
+
+
+
+
+
+
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+ #else
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+ #endif
+
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+
+ psDevMemoryInfo->ui32MappingHeapID = (IMG_UINT32)(psDeviceMemoryHeap - psDevMemoryInfo->psDeviceMemoryHeap);
+ psDeviceMemoryHeap++;
+#endif
+
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_2D_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_2D_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_2D_HEAP_SIZE;
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_SINGLE_PROCESS;
+ psDeviceMemoryHeap->pszName = "2D";
+ psDeviceMemoryHeap->pszBSName = "2D BS";
+
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+ psDeviceMemoryHeap++;
+#endif
+
+
+#if defined(FIX_HW_BRN_26915)
+
+
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_CGBUFFER_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_CGBUFFER_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_CGBUFFER_HEAP_SIZE;
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_SINGLE_PROCESS;
+ psDeviceMemoryHeap->pszName = "CGBuffer";
+ psDeviceMemoryHeap->pszBSName = "CGBuffer BS";
+
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+ psDeviceMemoryHeap++;
+#endif
+
+
+ psDevMemoryInfo->ui32HeapCount = (IMG_UINT32)(psDeviceMemoryHeap - psDevMemoryInfo->psDeviceMemoryHeap);
+
+ return PVRSRV_OK;
+}
+
+#if defined(PDUMP)
+static
+PVRSRV_ERROR SGXResetPDump(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *)(psDeviceNode->pvDevice);
+ psDevInfo->psKernelCCBInfo->ui32CCBDumpWOff = 0;
+ PVR_DPF((PVR_DBG_MESSAGE, "Reset pdump CCB write offset."));
+
+ return PVRSRV_OK;
+}
+#endif
+
+
+IMG_EXPORT
+PVRSRV_ERROR SGXGetClientInfoKM(IMG_HANDLE hDevCookie,
+ SGX_CLIENT_INFO* psClientInfo)
+{
+ PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
+
+
+
+ psDevInfo->ui32ClientRefCount++;
+
+
+
+ psClientInfo->ui32ProcessID = OSGetCurrentProcessIDKM();
+
+
+
+ OSMemCopy(&psClientInfo->asDevData, &psDevInfo->asSGXDevData, sizeof(psClientInfo->asDevData));
+
+
+ return PVRSRV_OK;
+}
+
+
+IMG_VOID SGXPanic(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+ PVR_LOG(("SGX panic"));
+ SGXDumpDebugInfo(psDevInfo, IMG_FALSE);
+ OSPanic();
+}
+
+static int fw_version_supported(const int fw_ver[4])
+{
+ static const int sup_versions[][4] = {
+ { 1, 6, 16, 4120 },
+ { 1, 6, 16, 4043 },
+ };
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(sup_versions); i++)
+ if (!memcmp(fw_ver, sup_versions[i], sizeof(fw_ver)))
+ return 1;
+
+ return 0;
+}
+
+PVRSRV_ERROR SGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+ unsigned long build_options;
+ unsigned long fw_ver_packed;
+ int fw_ver[4];
+#if !defined(NO_HARDWARE)
+ PPVRSRV_KERNEL_MEM_INFO psMemInfo;
+ PVRSRV_SGX_MISCINFO_INFO *psSGXMiscInfoInt;
+ PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
+ SGX_MISCINFO_STRUCT_SIZES *psSGXStructSizes;
+ IMG_BOOL bStructSizesFailed;
+
+
+ IMG_BOOL bCheckCoreRev;
+ const IMG_UINT32 aui32CoreRevExceptions[] =
+ {
+ 0x10100, 0x10101
+ };
+ const IMG_UINT32 ui32NumCoreExceptions = sizeof(aui32CoreRevExceptions) / (2*sizeof(IMG_UINT32));
+ IMG_UINT i;
+#endif
+
+
+ if(psDeviceNode->sDevId.eDeviceType != PVRSRV_DEVICE_TYPE_SGX)
+ {
+ PVR_LOG(("(FAIL) SGXInit: Device not of type SGX"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto chk_exit;
+ }
+
+
+ psDevInfo = psDeviceNode->pvDevice;
+ build_options = psDevInfo->ui32ClientBuildOptions &
+ SGX_BUILD_OPTION_MASK;
+
+ if (build_options != SGX_BUILD_OPTIONS) {
+ pr_err("pvr: user compile option mismatch (kernel:%#08lx, user:%#08lx)\n",
+ (unsigned long)SGX_BUILD_OPTIONS, build_options);
+ eError = PVRSRV_ERROR_BUILD_MISMATCH;
+
+ goto chk_exit;
+ } else {
+ pr_debug("pvr: user compile options ok\n");
+ }
+
+#if !defined (NO_HARDWARE)
+ psMemInfo = psDevInfo->psKernelSGXMiscMemInfo;
+
+
+ psSGXMiscInfoInt = psMemInfo->pvLinAddrKM;
+ psSGXMiscInfoInt->ui32MiscInfoFlags = 0;
+ psSGXMiscInfoInt->ui32MiscInfoFlags |= PVRSRV_USSE_MISCINFO_GET_STRUCT_SIZES;
+ eError = SGXGetMiscInfoUkernel(psDevInfo, psDeviceNode);
+
+ if (eError != PVRSRV_OK) {
+ pr_err("pvr: can't retrieve the firmware version\n");
+ goto chk_exit;
+ }
+
+ psSGXFeatures = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXFeatures;
+ fw_ver_packed = psSGXFeatures->ui32DDKVersion;
+
+ fw_ver[0] = PVR_FW_VER_MAJOR(fw_ver_packed);
+ fw_ver[1] = PVR_FW_VER_MINOR(fw_ver_packed);
+ fw_ver[2] = PVR_FW_VER_BRANCH(fw_ver_packed);
+ fw_ver[3] = psSGXFeatures->ui32DDKBuild;
+
+ if (!fw_version_supported(fw_ver)) {
+ pr_err("pvr: unsupported firmware version (%d.%d.%d.%d)\n",
+ fw_ver[0], fw_ver[1], fw_ver[2], fw_ver[3]);
+ eError = PVRSRV_ERROR_DDK_VERSION_MISMATCH;
+ PVR_DBG_BREAK;
+
+ goto chk_exit;
+ } else {
+ pr_debug("pvr: firmware version ok (%d.%d.%d.%d)\n",
+ fw_ver[0], fw_ver[1], fw_ver[2], fw_ver[3]);
+ }
+
+
+ if (psSGXFeatures->ui32CoreRevSW == 0)
+ {
+
+
+ PVR_LOG(("SGXInit: HW core rev (%x) check skipped.",
+ psSGXFeatures->ui32CoreRev));
+ }
+ else
+ {
+
+ bCheckCoreRev = IMG_TRUE;
+ for(i=0; i<ui32NumCoreExceptions; i+=2)
+ {
+ if( (psSGXFeatures->ui32CoreRev==aui32CoreRevExceptions[i]) &&
+ (psSGXFeatures->ui32CoreRevSW==aui32CoreRevExceptions[i+1]) )
+ {
+ PVR_LOG(("SGXInit: HW core rev (%x), SW core rev (%x) check skipped.",
+ psSGXFeatures->ui32CoreRev,
+ psSGXFeatures->ui32CoreRevSW));
+ bCheckCoreRev = IMG_FALSE;
+ }
+ }
+
+ if (bCheckCoreRev)
+ {
+ if (psSGXFeatures->ui32CoreRev != psSGXFeatures->ui32CoreRevSW)
+ {
+ PVR_LOG(("(FAIL) SGXInit: Incompatible HW core rev (%x) and SW core rev (%x).",
+ psSGXFeatures->ui32CoreRev, psSGXFeatures->ui32CoreRevSW));
+ eError = PVRSRV_ERROR_BUILD_MISMATCH;
+ goto chk_exit;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "SGXInit: HW core rev (%x) and SW core rev (%x) match. [ OK ]",
+ psSGXFeatures->ui32CoreRev, psSGXFeatures->ui32CoreRevSW));
+ }
+ }
+ }
+
+
+ psSGXStructSizes = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXStructSizes;
+
+ bStructSizesFailed = IMG_FALSE;
+
+ CHECK_SIZE(HOST_CTL);
+ CHECK_SIZE(COMMAND);
+#if defined(SGX_FEATURE_2D_HARDWARE)
+ CHECK_SIZE(2DCMD);
+ CHECK_SIZE(2DCMD_SHARED);
+#endif
+ CHECK_SIZE(CMDTA);
+ CHECK_SIZE(CMDTA_SHARED);
+ CHECK_SIZE(TRANSFERCMD);
+ CHECK_SIZE(TRANSFERCMD_SHARED);
+
+ CHECK_SIZE(3DREGISTERS);
+ CHECK_SIZE(HWPBDESC);
+ CHECK_SIZE(HWRENDERCONTEXT);
+ CHECK_SIZE(HWRENDERDETAILS);
+ CHECK_SIZE(HWRTDATA);
+ CHECK_SIZE(HWRTDATASET);
+ CHECK_SIZE(HWTRANSFERCONTEXT);
+
+ if (bStructSizesFailed == IMG_TRUE)
+ {
+ PVR_LOG(("(FAIL) SGXInit: Mismatch in SGXMKIF structure sizes."));
+ eError = PVRSRV_ERROR_BUILD_MISMATCH;
+ goto chk_exit;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "SGXInit: SGXMKIF structure sizes match. [ OK ]"));
+ }
+
+
+ build_options = psSGXFeatures->ui32BuildOptions & SGX_BUILD_OPTION_MASK;
+ if (build_options != SGX_BUILD_OPTIONS) {
+ pr_err("pvr: firwmare compile option mismatch (kernel:%#08lx, firmware:%#08lx)\n",
+ (unsigned long)SGX_BUILD_OPTIONS, build_options);
+ eError = PVRSRV_ERROR_BUILD_MISMATCH;
+
+ goto chk_exit;
+ } else {
+ pr_debug("pvr: firwmare build options match\n");
+ }
+#endif
+
+ eError = PVRSRV_OK;
+chk_exit:
+#if defined(IGNORE_SGX_INIT_COMPATIBILITY_CHECK)
+ return PVRSRV_OK;
+#else
+ return eError;
+#endif
+}
+
+static
+PVRSRV_ERROR SGXGetMiscInfoUkernel(PVRSRV_SGXDEV_INFO *psDevInfo,
+ PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVRSRV_ERROR eError;
+ SGXMKIF_COMMAND sCommandData;
+ PVRSRV_SGX_MISCINFO_INFO *psSGXMiscInfoInt;
+ PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
+ SGX_MISCINFO_STRUCT_SIZES *psSGXStructSizes;
+
+ PPVRSRV_KERNEL_MEM_INFO psMemInfo = psDevInfo->psKernelSGXMiscMemInfo;
+
+ if (! psMemInfo->pvLinAddrKM)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXGetMiscInfoUkernel: Invalid address."));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ psSGXMiscInfoInt = psMemInfo->pvLinAddrKM;
+ psSGXFeatures = &psSGXMiscInfoInt->sSGXFeatures;
+ psSGXStructSizes = &psSGXMiscInfoInt->sSGXStructSizes;
+
+ psSGXMiscInfoInt->ui32MiscInfoFlags &= ~PVRSRV_USSE_MISCINFO_READY;
+
+
+ OSMemSet(psSGXFeatures, 0, sizeof(*psSGXFeatures));
+ OSMemSet(psSGXStructSizes, 0, sizeof(*psSGXStructSizes));
+
+
+ sCommandData.ui32Data[1] = psMemInfo->sDevVAddr.uiAddr;
+
+ PDUMPCOMMENT("Microkernel kick for SGXGetMiscInfo");
+ eError = SGXScheduleCCBCommandKM(psDeviceNode,
+ SGXMKIF_CMD_GETMISCINFO,
+ &sCommandData,
+ KERNEL_ID,
+ 0);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXGetMiscInfoUkernel: SGXScheduleCCBCommandKM failed."));
+ return eError;
+ }
+
+
+#if !defined(NO_HARDWARE)
+ {
+ IMG_BOOL bExit;
+
+ bExit = IMG_FALSE;
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+ {
+ if ((psSGXMiscInfoInt->ui32MiscInfoFlags & PVRSRV_USSE_MISCINFO_READY) != 0)
+ {
+ bExit = IMG_TRUE;
+ break;
+ }
+ } END_LOOP_UNTIL_TIMEOUT();
+
+
+ if (!bExit)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXGetMiscInfoUkernel: Timeout occurred waiting for misc info."));
+ return PVRSRV_ERROR_TIMEOUT;
+ }
+ }
+#endif
+
+ return PVRSRV_OK;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo,
+ SGX_MISC_INFO *psMiscInfo,
+ PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_HANDLE hDevMemContext)
+{
+ PVRSRV_ERROR eError;
+ PPVRSRV_KERNEL_MEM_INFO psMemInfo = psDevInfo->psKernelSGXMiscMemInfo;
+ IMG_UINT32 *pui32MiscInfoFlags = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->ui32MiscInfoFlags;
+
+
+ *pui32MiscInfoFlags = 0;
+
+#if !defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+ PVR_UNREFERENCED_PARAMETER(hDevMemContext);
+#endif
+
+ switch(psMiscInfo->eRequest)
+ {
+#if defined(SGX_FEATURE_DATA_BREAKPOINTS)
+ case SGX_MISC_INFO_REQUEST_SET_BREAKPOINT:
+ {
+ IMG_UINT32 ui32MaskDM;
+ IMG_UINT32 ui32CtrlWEnable;
+ IMG_UINT32 ui32CtrlREnable;
+ IMG_UINT32 ui32CtrlTrapEnable;
+ IMG_UINT32 ui32RegVal;
+ IMG_UINT32 ui32StartRegVal;
+ IMG_UINT32 ui32EndRegVal;
+ SGXMKIF_COMMAND sCommandData;
+
+
+ if(psMiscInfo->uData.sSGXBreakpointInfo.bBPEnable)
+ {
+
+ IMG_DEV_VIRTADDR sBPDevVAddr = psMiscInfo->uData.sSGXBreakpointInfo.sBPDevVAddr;
+ IMG_DEV_VIRTADDR sBPDevVAddrEnd = psMiscInfo->uData.sSGXBreakpointInfo.sBPDevVAddrEnd;
+
+
+ ui32StartRegVal = sBPDevVAddr.uiAddr & EUR_CR_BREAKPOINT0_START_ADDRESS_MASK;
+ ui32EndRegVal = sBPDevVAddrEnd.uiAddr & EUR_CR_BREAKPOINT0_END_ADDRESS_MASK;
+
+ ui32MaskDM = psMiscInfo->uData.sSGXBreakpointInfo.ui32DataMasterMask;
+ ui32CtrlWEnable = psMiscInfo->uData.sSGXBreakpointInfo.bWrite;
+ ui32CtrlREnable = psMiscInfo->uData.sSGXBreakpointInfo.bRead;
+ ui32CtrlTrapEnable = psMiscInfo->uData.sSGXBreakpointInfo.bTrapped;
+
+
+ ui32RegVal = ((ui32MaskDM<<EUR_CR_BREAKPOINT0_MASK_DM_SHIFT) & EUR_CR_BREAKPOINT0_MASK_DM_MASK) |
+ ((ui32CtrlWEnable<<EUR_CR_BREAKPOINT0_CTRL_WENABLE_SHIFT) & EUR_CR_BREAKPOINT0_CTRL_WENABLE_MASK) |
+ ((ui32CtrlREnable<<EUR_CR_BREAKPOINT0_CTRL_RENABLE_SHIFT) & EUR_CR_BREAKPOINT0_CTRL_RENABLE_MASK) |
+ ((ui32CtrlTrapEnable<<EUR_CR_BREAKPOINT0_CTRL_TRAPENABLE_SHIFT) & EUR_CR_BREAKPOINT0_CTRL_TRAPENABLE_MASK);
+ }
+ else
+ {
+
+ ui32RegVal = ui32StartRegVal = ui32EndRegVal = 0;
+ }
+
+
+ sCommandData.ui32Data[0] = psMiscInfo->uData.sSGXBreakpointInfo.ui32BPIndex;
+ sCommandData.ui32Data[1] = ui32StartRegVal;
+ sCommandData.ui32Data[2] = ui32EndRegVal;
+ sCommandData.ui32Data[3] = ui32RegVal;
+
+
+ psDevInfo->psSGXHostCtl->ui32BPSetClearSignal = 0;
+
+ PDUMPCOMMENT("Microkernel kick for setting a data breakpoint");
+ eError = SGXScheduleCCBCommandKM(psDeviceNode,
+ SGXMKIF_CMD_DATABREAKPOINT,
+ &sCommandData,
+ KERNEL_ID,
+ 0);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXGetMiscInfoKM: SGXScheduleCCBCommandKM failed."));
+ return eError;
+ }
+
+#if defined(NO_HARDWARE)
+
+ psDevInfo->psSGXHostCtl->ui32BPSetClearSignal = 0;
+#else
+ {
+ IMG_BOOL bExit;
+
+ bExit = IMG_FALSE;
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+ {
+ if (psDevInfo->psSGXHostCtl->ui32BPSetClearSignal != 0)
+ {
+ bExit = IMG_TRUE;
+
+ psDevInfo->psSGXHostCtl->ui32BPSetClearSignal = 0;
+ break;
+ }
+ } END_LOOP_UNTIL_TIMEOUT();
+
+
+ if (!bExit)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXGetMiscInfoKM: Timeout occurred waiting BP set/clear"));
+ return PVRSRV_ERROR_TIMEOUT;
+ }
+ }
+#endif
+
+ return PVRSRV_OK;
+ }
+
+ case SGX_MISC_INFO_REQUEST_WAIT_FOR_BREAKPOINT:
+ {
+
+
+ PDUMPCOMMENT("Wait for data breakpoint hit");
+
+#if defined(NO_HARDWARE) && defined(PDUMP)
+ {
+ PDUMPREGPOL(SGX_PDUMPREG_NAME,
+ EUR_CR_EVENT_STATUS2,
+ EUR_CR_EVENT_STATUS2_DATA_BREAKPOINT_TRAPPED_MASK,
+ EUR_CR_EVENT_STATUS2_DATA_BREAKPOINT_TRAPPED_MASK);
+
+ PDUMPREG(SGX_PDUMPREG_NAME,
+ EUR_CR_EVENT_HOST_CLEAR2,
+ EUR_CR_EVENT_HOST_CLEAR2_DATA_BREAKPOINT_TRAPPED_MASK);
+
+ PDUMPCOMMENT("Breakpoint detected. Wait a bit to show that pipeline stops in simulation");
+ PDUMPIDL(2000);
+
+ PDUMPCOMMENT("Now we can resume");
+ PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BREAKPOINT_TRAP, EUR_CR_BREAKPOINT_TRAP_WRNOTIFY_MASK | EUR_CR_BREAKPOINT_TRAP_CONTINUE_MASK);
+ }
+#else
+ {
+
+ }
+#endif
+ return PVRSRV_OK;
+ }
+
+ case SGX_MISC_INFO_REQUEST_POLL_BREAKPOINT:
+ {
+
+
+
+
+
+
+
+#if !defined(NO_HARDWARE)
+ IMG_BOOL bTrappedBPMaster;
+ IMG_BOOL abTrappedBPPerCore[SGX_FEATURE_MP_CORE_COUNT];
+ IMG_UINT32 ui32CoreNum, ui32TrappedBPCoreNum;
+ IMG_BOOL bTrappedBPAny;
+
+ ui32TrappedBPCoreNum = 0;
+ bTrappedBPMaster = !!(EUR_CR_MASTER_BREAKPOINT_TRAPPED_MASK & OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_BREAKPOINT));
+ bTrappedBPAny = bTrappedBPMaster;
+ for (ui32CoreNum = 0; ui32CoreNum < SGX_FEATURE_MP_CORE_COUNT; ui32CoreNum++)
+ {
+ abTrappedBPPerCore[ui32CoreNum] = !!(EUR_CR_BREAKPOINT_TRAPPED_MASK & OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT, ui32CoreNum)));
+ if (abTrappedBPPerCore[ui32CoreNum])
+ {
+ bTrappedBPAny = IMG_TRUE;
+ ui32TrappedBPCoreNum = ui32CoreNum;
+ }
+ }
+
+ psMiscInfo->uData.sSGXBreakpointInfo.bTrappedBP = bTrappedBPAny;
+
+ if (psMiscInfo->uData.sSGXBreakpointInfo.bTrappedBP)
+ {
+ IMG_UINT32 ui32Info0, ui32Info1;
+
+ ui32Info0 = OSReadHWReg(psDevInfo->pvRegsBaseKM, bTrappedBPMaster?EUR_CR_MASTER_BREAKPOINT_TRAP_INFO0:SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT_TRAP_INFO0, ui32TrappedBPCoreNum));
+ ui32Info1 = OSReadHWReg(psDevInfo->pvRegsBaseKM, bTrappedBPMaster?EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1:SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT_TRAP_INFO1, ui32TrappedBPCoreNum));
+
+ psMiscInfo->uData.sSGXBreakpointInfo.ui32BPIndex = (ui32Info1 & EUR_CR_BREAKPOINT_TRAP_INFO1_NUMBER_MASK) >> EUR_CR_BREAKPOINT_TRAP_INFO1_NUMBER_SHIFT;
+ psMiscInfo->uData.sSGXBreakpointInfo.sTrappedBPDevVAddr.uiAddr = ui32Info0 & EUR_CR_BREAKPOINT_TRAP_INFO0_ADDRESS_MASK;
+ psMiscInfo->uData.sSGXBreakpointInfo.ui32TrappedBPBurstLength = (ui32Info1 & EUR_CR_BREAKPOINT_TRAP_INFO1_SIZE_MASK) >> EUR_CR_BREAKPOINT_TRAP_INFO1_SIZE_SHIFT;
+ psMiscInfo->uData.sSGXBreakpointInfo.bTrappedBPRead = !!(ui32Info1 & EUR_CR_BREAKPOINT_TRAP_INFO1_RNW_MASK);
+ psMiscInfo->uData.sSGXBreakpointInfo.ui32TrappedBPDataMaster = (ui32Info1 & EUR_CR_BREAKPOINT_TRAP_INFO1_DATA_MASTER_MASK) >> EUR_CR_BREAKPOINT_TRAP_INFO1_DATA_MASTER_SHIFT;
+ psMiscInfo->uData.sSGXBreakpointInfo.ui32TrappedBPTag = (ui32Info1 & EUR_CR_BREAKPOINT_TRAP_INFO1_TAG_MASK) >> EUR_CR_BREAKPOINT_TRAP_INFO1_TAG_SHIFT;
+ psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum = bTrappedBPMaster?65535:ui32TrappedBPCoreNum;
+ }
+#endif
+ return PVRSRV_OK;
+ }
+
+ case SGX_MISC_INFO_REQUEST_RESUME_BREAKPOINT:
+ {
+
+
+
+#if !defined(NO_HARDWARE)
+ IMG_UINT32 ui32CoreNum;
+ IMG_BOOL bMaster;
+ IMG_UINT32 ui32OldSeqNum, ui32NewSeqNum;
+
+ ui32CoreNum = psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum;
+ bMaster = ui32CoreNum > SGX_FEATURE_MP_CORE_COUNT;
+ if (bMaster)
+ {
+
+
+ ui32OldSeqNum = 0x1c & OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_BREAKPOINT);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_BREAKPOINT_TRAP, EUR_CR_MASTER_BREAKPOINT_TRAP_WRNOTIFY_MASK | EUR_CR_MASTER_BREAKPOINT_TRAP_CONTINUE_MASK);
+ do
+ {
+ ui32NewSeqNum = 0x1c & OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_BREAKPOINT);
+ }
+ while (ui32OldSeqNum == ui32NewSeqNum);
+ }
+ else
+ {
+
+ ui32OldSeqNum = 0x1c & OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT, ui32CoreNum));
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT_TRAP, ui32CoreNum), EUR_CR_BREAKPOINT_TRAP_WRNOTIFY_MASK | EUR_CR_BREAKPOINT_TRAP_CONTINUE_MASK);
+ do
+ {
+ ui32NewSeqNum = 0x1c & OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT, ui32CoreNum));
+ }
+ while (ui32OldSeqNum == ui32NewSeqNum);
+ }
+#endif
+ return PVRSRV_OK;
+ }
+#endif
+
+ case SGX_MISC_INFO_REQUEST_CLOCKSPEED:
+ {
+ psMiscInfo->uData.ui32SGXClockSpeed = psDevInfo->ui32CoreClockSpeed;
+ return PVRSRV_OK;
+ }
+
+ case SGX_MISC_INFO_REQUEST_ACTIVEPOWER:
+ {
+ psMiscInfo->uData.sActivePower.ui32NumActivePowerEvents = psDevInfo->psSGXHostCtl->ui32NumActivePowerEvents;
+ return PVRSRV_OK;
+ }
+
+ case SGX_MISC_INFO_REQUEST_LOCKUPS:
+ {
+#if defined(SUPPORT_HW_RECOVERY)
+ psMiscInfo->uData.sLockups.ui32uKernelDetectedLockups = psDevInfo->psSGXHostCtl->ui32uKernelDetectedLockups;
+ psMiscInfo->uData.sLockups.ui32HostDetectedLockups = psDevInfo->psSGXHostCtl->ui32HostDetectedLockups;
+#else
+ psMiscInfo->uData.sLockups.ui32uKernelDetectedLockups = 0;
+ psMiscInfo->uData.sLockups.ui32HostDetectedLockups = 0;
+#endif
+ return PVRSRV_OK;
+ }
+
+ case SGX_MISC_INFO_REQUEST_SPM:
+ {
+
+ return PVRSRV_OK;
+ }
+
+ case SGX_MISC_INFO_REQUEST_SGXREV:
+ {
+ PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
+ eError = SGXGetMiscInfoUkernel(psDevInfo, psDeviceNode);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "An error occurred in SGXGetMiscInfoUkernel: %d\n",
+ eError));
+ return eError;
+ }
+ psSGXFeatures = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXFeatures;
+
+
+ psMiscInfo->uData.sSGXFeatures = *psSGXFeatures;
+
+
+ PVR_DPF((PVR_DBG_MESSAGE, "SGXGetMiscInfoKM: Core 0x%x, sw ID 0x%x, sw Rev 0x%x\n",
+ psSGXFeatures->ui32CoreRev,
+ psSGXFeatures->ui32CoreIdSW,
+ psSGXFeatures->ui32CoreRevSW));
+ PVR_DPF((PVR_DBG_MESSAGE, "SGXGetMiscInfoKM: DDK version 0x%x, DDK build 0x%x\n",
+ psSGXFeatures->ui32DDKVersion,
+ psSGXFeatures->ui32DDKBuild));
+
+
+ return PVRSRV_OK;
+ }
+
+ case SGX_MISC_INFO_REQUEST_DRIVER_SGXREV:
+ {
+ PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
+
+ psSGXFeatures = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXFeatures;
+
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+
+ psSGXFeatures->sDevVAEDMStatusBuffer = psDevInfo->psKernelEDMStatusBufferMemInfo->sDevVAddr;
+ psSGXFeatures->pvEDMStatusBuffer = psDevInfo->psKernelEDMStatusBufferMemInfo->pvLinAddrKM;
+#endif
+
+ psMiscInfo->uData.sSGXFeatures = *psSGXFeatures;
+ return PVRSRV_OK;
+ }
+
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+ case SGX_MISC_INFO_REQUEST_MEMREAD:
+ case SGX_MISC_INFO_REQUEST_MEMCOPY:
+ {
+ PVRSRV_ERROR eError;
+ PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
+ PVRSRV_SGX_MISCINFO_MEMACCESS *psSGXMemSrc;
+ PVRSRV_SGX_MISCINFO_MEMACCESS *psSGXMemDest;
+
+ {
+
+ *pui32MiscInfoFlags |= PVRSRV_USSE_MISCINFO_MEMREAD;
+ psSGXMemSrc = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXMemAccessSrc;
+
+ if(psMiscInfo->sDevVAddrSrc.uiAddr != 0)
+ {
+ psSGXMemSrc->sDevVAddr = psMiscInfo->sDevVAddrSrc;
+ }
+ else
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ }
+
+ if( psMiscInfo->eRequest == SGX_MISC_INFO_REQUEST_MEMCOPY)
+ {
+
+ *pui32MiscInfoFlags |= PVRSRV_USSE_MISCINFO_MEMWRITE;
+ psSGXMemDest = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXMemAccessDest;
+
+ if(psMiscInfo->sDevVAddrDest.uiAddr != 0)
+ {
+ psSGXMemDest->sDevVAddr = psMiscInfo->sDevVAddrDest;
+ }
+ else
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ }
+
+
+ if(psMiscInfo->hDevMemContext != IMG_NULL)
+ {
+ SGXGetMMUPDAddrKM( (IMG_HANDLE)psDeviceNode, hDevMemContext, &psSGXMemSrc->sPDDevPAddr);
+
+
+ psSGXMemDest->sPDDevPAddr = psSGXMemSrc->sPDDevPAddr;
+ }
+ else
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ eError = SGXGetMiscInfoUkernel(psDevInfo, psDeviceNode);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "An error occurred in SGXGetMiscInfoUkernel: %d\n",
+ eError));
+ return eError;
+ }
+ psSGXFeatures = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXFeatures;
+
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+ if(*pui32MiscInfoFlags & PVRSRV_USSE_MISCINFO_MEMREAD_FAIL)
+ {
+ return PVRSRV_ERROR_INVALID_MISCINFO;
+ }
+#endif
+
+ psMiscInfo->uData.sSGXFeatures = *psSGXFeatures;
+ return PVRSRV_OK;
+ }
+#endif
+
+#if defined(SUPPORT_SGX_HWPERF)
+ case SGX_MISC_INFO_REQUEST_SET_HWPERF_STATUS:
+ {
+ PVRSRV_SGX_MISCINFO_SET_HWPERF_STATUS *psSetHWPerfStatus = &psMiscInfo->uData.sSetHWPerfStatus;
+ const IMG_UINT32 ui32ValidFlags = PVRSRV_SGX_HWPERF_STATUS_RESET_COUNTERS |
+ PVRSRV_SGX_HWPERF_STATUS_GRAPHICS_ON |
+ PVRSRV_SGX_HWPERF_STATUS_PERIODIC_ON |
+ PVRSRV_SGX_HWPERF_STATUS_MK_EXECUTION_ON;
+ SGXMKIF_COMMAND sCommandData = {0};
+
+
+ if ((psSetHWPerfStatus->ui32NewHWPerfStatus & ~ui32ValidFlags) != 0)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ #if defined(PDUMP)
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+ "SGX ukernel HWPerf status %u\n",
+ psSetHWPerfStatus->ui32NewHWPerfStatus);
+ #endif
+
+
+ #if defined(SGX_FEATURE_EXTENDED_PERF_COUNTERS)
+ OSMemCopy(&psDevInfo->psSGXHostCtl->aui32PerfGroup[0],
+ &psSetHWPerfStatus->aui32PerfGroup[0],
+ sizeof(psDevInfo->psSGXHostCtl->aui32PerfGroup));
+ OSMemCopy(&psDevInfo->psSGXHostCtl->aui32PerfBit[0],
+ &psSetHWPerfStatus->aui32PerfBit[0],
+ sizeof(psDevInfo->psSGXHostCtl->aui32PerfBit));
+ #if defined(PDUMP)
+ PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+ offsetof(SGXMKIF_HOST_CTL, aui32PerfGroup),
+ sizeof(psDevInfo->psSGXHostCtl->aui32PerfGroup),
+ PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+ PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+ offsetof(SGXMKIF_HOST_CTL, aui32PerfBit),
+ sizeof(psDevInfo->psSGXHostCtl->aui32PerfBit),
+ PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+ #endif
+ #else
+ psDevInfo->psSGXHostCtl->ui32PerfGroup = psSetHWPerfStatus->ui32PerfGroup;
+ #if defined(PDUMP)
+ PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+ offsetof(SGXMKIF_HOST_CTL, ui32PerfGroup),
+ sizeof(psDevInfo->psSGXHostCtl->ui32PerfGroup),
+ PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+ #endif
+ #endif
+
+
+ sCommandData.ui32Data[0] = psSetHWPerfStatus->ui32NewHWPerfStatus;
+ eError = SGXScheduleCCBCommandKM(psDeviceNode,
+ SGXMKIF_CMD_SETHWPERFSTATUS,
+ &sCommandData,
+ KERNEL_ID,
+ 0);
+ return eError;
+ }
+#endif
+
+ case SGX_MISC_INFO_DUMP_DEBUG_INFO:
+ {
+ PVR_LOG(("User requested SGX debug info"));
+
+
+ SGXDumpDebugInfo(psDeviceNode->pvDevice, IMG_FALSE);
+
+ return PVRSRV_OK;
+ }
+
+ case SGX_MISC_INFO_PANIC:
+ {
+ PVR_LOG(("User requested SGX panic"));
+
+ SGXPanic(psDeviceNode->pvDevice);
+
+ return PVRSRV_OK;
+ }
+#if defined(PVRSRV_RESOURCE_PROFILING)
+ case SGX_MISC_INFO_RESOURCEPROF_SIMPLE:
+ case SGX_MISC_INFO_RESOURCEPROF_GLOBAL:
+ {
+ PVR_LOG(("User requested resource profiling"));
+ SGXGetResourceProfile(psMiscInfo, psDeviceNode);
+ return PVRSRV_OK;
+ }
+ case SGX_MISC_INFO_RESOURCEPROF_MEM_INFO:
+ {
+ PVR_LOG(("User requested resource mem info"));
+ SGXGetResProfMemInfo(psMiscInfo, psDeviceNode);
+ return PVRSRV_OK;
+ }
+#endif
+ default:
+ {
+
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ }
+}
+
+
+IMG_EXPORT
+PVRSRV_ERROR SGXReadHWPerfCBKM(IMG_HANDLE hDevHandle,
+ IMG_UINT32 ui32ArraySize,
+ PVRSRV_SGX_HWPERF_CB_ENTRY *psClientHWPerfEntry,
+ IMG_UINT32 *pui32DataCount,
+ IMG_UINT32 *pui32ClockSpeed,
+ IMG_UINT32 *pui32HostTimeStamp)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ SGXMKIF_HWPERF_CB *psHWPerfCB = psDevInfo->psKernelHWPerfCBMemInfo->pvLinAddrKM;
+ IMG_UINT i;
+
+ for (i = 0;
+ psHWPerfCB->ui32Woff != psHWPerfCB->ui32Roff && i < ui32ArraySize;
+ i++)
+ {
+ SGXMKIF_HWPERF_CB_ENTRY *psMKPerfEntry = &psHWPerfCB->psHWPerfCBData[psHWPerfCB->ui32Roff];
+
+ psClientHWPerfEntry[i].ui32FrameNo = psMKPerfEntry->ui32FrameNo;
+ psClientHWPerfEntry[i].ui32Type = psMKPerfEntry->ui32Type;
+ psClientHWPerfEntry[i].ui32Ordinal = psMKPerfEntry->ui32Ordinal;
+ psClientHWPerfEntry[i].ui32Info = psMKPerfEntry->ui32Info;
+ psClientHWPerfEntry[i].ui32Clocksx16 = SGXConvertTimeStamp(psDevInfo,
+ psMKPerfEntry->ui32TimeWraps,
+ psMKPerfEntry->ui32Time);
+ OSMemCopy(&psClientHWPerfEntry[i].ui32Counters[0][0],
+ &psMKPerfEntry->ui32Counters[0][0],
+ sizeof(psMKPerfEntry->ui32Counters));
+
+ psHWPerfCB->ui32Roff = (psHWPerfCB->ui32Roff + 1) & (SGXMKIF_HWPERF_CB_SIZE - 1);
+ }
+
+ *pui32DataCount = i;
+ *pui32ClockSpeed = psDevInfo->ui32CoreClockSpeed;
+ *pui32HostTimeStamp = OSClockus();
+
+ return eError;
+}
+
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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 <stddef.h>
+#include "services_headers.h"
+#include "sgxinfo.h"
+#include "sgxinfokm.h"
+#if defined (PDUMP)
+#include "sgxapi_km.h"
+#include "pdump_km.h"
+#endif
+#include "sgx_bridge_km.h"
+#include "osfunc.h"
+#include "pvr_debug.h"
+#include "sgxutils.h"
+#include "perproc.h"
+#include "pvr_trace_cmd.h"
+
+IMG_EXPORT
+PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick,
+ PVRSRV_PER_PROCESS_DATA *proc)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+ PVRSRV_KERNEL_MEM_INFO *psCCBMemInfo = (PVRSRV_KERNEL_MEM_INFO *) psCCBKick->hCCBKernelMemInfo;
+ SGXMKIF_CMDTA_SHARED *psTACmd;
+ IMG_UINT32 i;
+ struct pvr_trcmd_sgxkick *ktrace;
+ int trcmd_type;
+
+ if (!CCB_OFFSET_IS_VALID(SGXMKIF_CMDTA_SHARED, psCCBMemInfo, psCCBKick, ui32CCBOffset))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXDoKickKM: Invalid CCB offset"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ psTACmd = CCB_DATA_FROM_OFFSET(SGXMKIF_CMDTA_SHARED, psCCBMemInfo, psCCBKick, ui32CCBOffset);
+
+ trcmd_type = psCCBKick->bFirstKickOrResume ?
+ PVR_TRCMD_SGX_FIRSTKICK : PVR_TRCMD_SGX_KICK;
+ ktrace = pvr_trcmd_reserve(trcmd_type, proc->ui32PID, proc->name,
+ sizeof(*ktrace));
+
+
+ if (psCCBKick->hTA3DSyncInfo)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTA3DSyncInfo;
+ psTACmd->sTA3DDependency.sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+
+ psTACmd->sTA3DDependency.ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+
+ if (psCCBKick->bTADependency)
+ {
+ psSyncInfo->psSyncData->ui32WriteOpsPending++;
+ }
+
+ pvr_trcmd_set_syn(&ktrace->ta3d_syn, psSyncInfo);
+ } else {
+ pvr_trcmd_clear_syn(&ktrace->ta3d_syn);
+ }
+
+ if (psCCBKick->hTASyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTASyncInfo;
+
+ psTACmd->sTATQSyncReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+ psTACmd->sTATQSyncWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+
+ psTACmd->ui32TATQSyncReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending++;
+ psTACmd->ui32TATQSyncWriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+
+ pvr_trcmd_set_syn(&ktrace->tatq_syn, psSyncInfo);
+ } else {
+ pvr_trcmd_clear_syn(&ktrace->tatq_syn);
+ }
+
+ if (psCCBKick->h3DSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->h3DSyncInfo;
+
+ psTACmd->s3DTQSyncReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+ psTACmd->s3DTQSyncWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+
+ psTACmd->ui323DTQSyncReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending++;
+ psTACmd->ui323DTQSyncWriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+
+ pvr_trcmd_set_syn(&ktrace->_3dtq_syn, psSyncInfo);
+ } else {
+ pvr_trcmd_clear_syn(&ktrace->_3dtq_syn);
+ }
+
+ psTACmd->ui32NumTAStatusVals = psCCBKick->ui32NumTAStatusVals;
+ if (psCCBKick->ui32NumTAStatusVals != 0)
+ {
+
+ for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++)
+ {
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+ psTACmd->sCtlTAStatusInfo[i] = psCCBKick->asTAStatusUpdate[i].sCtlStatus;
+#else
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ahTAStatusSyncInfo[i];
+ psTACmd->sCtlTAStatusInfo[i].sStatusDevAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+ psTACmd->sCtlTAStatusInfo[i].ui32StatusValue = psSyncInfo->psSyncData->ui32ReadOpsPending;
+#endif
+ }
+ }
+
+ psTACmd->ui32Num3DStatusVals = psCCBKick->ui32Num3DStatusVals;
+ if (psCCBKick->ui32Num3DStatusVals != 0)
+ {
+
+ for (i = 0; i < psCCBKick->ui32Num3DStatusVals; i++)
+ {
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+ psTACmd->sCtl3DStatusInfo[i] = psCCBKick->as3DStatusUpdate[i].sCtlStatus;
+#else
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ah3DStatusSyncInfo[i];
+ psTACmd->sCtl3DStatusInfo[i].sStatusDevAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+ psTACmd->sCtl3DStatusInfo[i].ui32StatusValue = psSyncInfo->psSyncData->ui32ReadOpsPending;
+#endif
+ }
+ }
+
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+
+ psTACmd->ui32NumTASrcSyncs = psCCBKick->ui32NumTASrcSyncs;
+ for (i=0; i<psCCBKick->ui32NumTASrcSyncs; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTASrcKernelSyncInfo[i];
+
+ psTACmd->asTASrcSyncs[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+ psTACmd->asTASrcSyncs[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+
+
+ psTACmd->asTASrcSyncs[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending++;
+
+ psTACmd->asTASrcSyncs[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+
+ psTACmd->ui32NumTADstSyncs = psCCBKick->ui32NumTADstSyncs;
+ for (i=0; i<psCCBKick->ui32NumTADstSyncs; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTADstKernelSyncInfo[i];
+
+ psTACmd->asTADstSyncs[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+ psTACmd->asTADstSyncs[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+
+
+ psTACmd->asTADstSyncs[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+ psTACmd->asTADstSyncs[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++;
+ }
+
+ psTACmd->ui32Num3DSrcSyncs = psCCBKick->ui32Num3DSrcSyncs;
+ for (i=0; i<psCCBKick->ui32Num3DSrcSyncs; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ah3DSrcKernelSyncInfo[i];
+
+ psTACmd->as3DSrcSyncs[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+ psTACmd->as3DSrcSyncs[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+
+
+ psTACmd->as3DSrcSyncs[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending++;
+
+ psTACmd->as3DSrcSyncs[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+#else
+
+ psTACmd->ui32NumSrcSyncs = psCCBKick->ui32NumSrcSyncs;
+
+ for (i = 0; i < SGX_MAX_SRC_SYNCS; i++) {
+ if (i >= psCCBKick->ui32NumSrcSyncs) {
+ pvr_trcmd_clear_syn(&ktrace->src_syn[i]);
+ continue;
+ }
+
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahSrcKernelSyncInfo[i];
+
+ psTACmd->asSrcSyncs[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+ psTACmd->asSrcSyncs[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+
+
+ psTACmd->asSrcSyncs[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending++;
+
+ psTACmd->asSrcSyncs[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+
+ pvr_trcmd_set_syn(&ktrace->src_syn[i], psSyncInfo);
+ }
+#endif
+
+ if (psCCBKick->bFirstKickOrResume && psCCBKick->ui32NumDstSyncObjects > 0)
+ {
+ PVRSRV_KERNEL_MEM_INFO *psHWDstSyncListMemInfo =
+ (PVRSRV_KERNEL_MEM_INFO *)psCCBKick->hKernelHWSyncListMemInfo;
+ SGXMKIF_HWDEVICE_SYNC_LIST *psHWDeviceSyncList = psHWDstSyncListMemInfo->pvLinAddrKM;
+ IMG_UINT32 ui32NumDstSyncs = psCCBKick->ui32NumDstSyncObjects;
+
+ PVR_ASSERT(((PVRSRV_KERNEL_MEM_INFO *)psCCBKick->hKernelHWSyncListMemInfo)->ui32AllocSize >= (sizeof(SGXMKIF_HWDEVICE_SYNC_LIST) +
+ (sizeof(PVRSRV_DEVICE_SYNC_OBJECT) * ui32NumDstSyncs)));
+
+ psHWDeviceSyncList->ui32NumSyncObjects = ui32NumDstSyncs;
+#if defined(PDUMP)
+ if (PDumpIsCaptureFrameKM())
+ {
+ PDUMPCOMMENT("HWDeviceSyncList for TACmd\r\n");
+ PDUMPMEM(IMG_NULL,
+ psHWDstSyncListMemInfo,
+ 0,
+ sizeof(SGXMKIF_HWDEVICE_SYNC_LIST),
+ 0,
+ MAKEUNIQUETAG(psHWDstSyncListMemInfo));
+ }
+#endif
+
+ for (i=0; i<ui32NumDstSyncs; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->pahDstSyncHandles[i];
+
+ if (psSyncInfo)
+ {
+ psHWDeviceSyncList->asSyncData[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+ psHWDeviceSyncList->asSyncData[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+
+ psHWDeviceSyncList->asSyncData[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+ psHWDeviceSyncList->asSyncData[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++;
+
+ pvr_trcmd_set_syn(&ktrace->dst_syn, psSyncInfo);
+
+ #if defined(PDUMP)
+ if (PDumpIsCaptureFrameKM())
+ {
+ IMG_UINT32 ui32ModifiedValue;
+ IMG_UINT32 ui32SyncOffset = offsetof(SGXMKIF_HWDEVICE_SYNC_LIST, asSyncData)
+ + (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT));
+ IMG_UINT32 ui32WOpsOffset = ui32SyncOffset
+ + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal);
+ IMG_UINT32 ui32ROpsOffset = ui32SyncOffset
+ + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal);
+
+ PDUMPCOMMENT("HWDeviceSyncObject for RT: %i\r\n", i);
+
+ PDUMPMEM(IMG_NULL,
+ psHWDstSyncListMemInfo,
+ ui32SyncOffset,
+ sizeof(PVRSRV_DEVICE_SYNC_OBJECT),
+ 0,
+ MAKEUNIQUETAG(psHWDstSyncListMemInfo));
+
+ if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) &&
+ (psSyncInfo->psSyncData->ui32LastReadOpDumpVal == 0))
+ {
+
+ PDUMPCOMMENT("Init RT ROpsComplete\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psSyncInfo->psSyncDataMemInfoKM,
+ offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete),
+ sizeof(psSyncInfo->psSyncData->ui32ReadOpsComplete),
+ 0,
+ MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+
+ PDUMPCOMMENT("Init RT WOpsComplete\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psSyncInfo->psSyncDataMemInfoKM,
+ offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete),
+ sizeof(psSyncInfo->psSyncData->ui32WriteOpsComplete),
+ 0,
+ MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+ }
+
+ psSyncInfo->psSyncData->ui32LastOpDumpVal++;
+
+ ui32ModifiedValue = psSyncInfo->psSyncData->ui32LastOpDumpVal - 1;
+
+ PDUMPCOMMENT("Modify RT %d WOpPendingVal in HWDevSyncList\r\n", i);
+
+ PDUMPMEM(&ui32ModifiedValue,
+ psHWDstSyncListMemInfo,
+ ui32WOpsOffset,
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psHWDstSyncListMemInfo));
+
+ ui32ModifiedValue = 0;
+ PDUMPCOMMENT("Modify RT %d ROpsPendingVal in HWDevSyncList\r\n", i);
+
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psHWDstSyncListMemInfo,
+ ui32ROpsOffset,
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psHWDstSyncListMemInfo));
+ }
+ #endif
+ }
+ else
+ {
+ psHWDeviceSyncList->asSyncData[i].sWriteOpsCompleteDevVAddr.uiAddr = 0;
+ psHWDeviceSyncList->asSyncData[i].sReadOpsCompleteDevVAddr.uiAddr = 0;
+
+ psHWDeviceSyncList->asSyncData[i].ui32ReadOpsPendingVal = 0;
+ psHWDeviceSyncList->asSyncData[i].ui32WriteOpsPendingVal = 0;
+
+ pvr_trcmd_clear_syn(&ktrace->dst_syn);
+ }
+ }
+ } else {
+ pvr_trcmd_clear_syn(&ktrace->dst_syn);
+ }
+
+ psTACmd->ui32CtrlFlags |= SGXMKIF_CMDTA_CTRLFLAGS_READY;
+
+#if defined(PDUMP)
+ if (PDumpIsCaptureFrameKM())
+ {
+ PDUMPCOMMENT("Shared part of TA command\r\n");
+
+ PDUMPMEM(psTACmd,
+ psCCBMemInfo,
+ psCCBKick->ui32CCBDumpWOff,
+ sizeof(SGXMKIF_CMDTA_SHARED),
+ 0,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+ for (i=0; i<psCCBKick->ui32NumTASrcSyncs; i++)
+ {
+ IMG_UINT32 ui32ModifiedValue;
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTASrcKernelSyncInfo[i];
+
+ if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) &&
+ (psSyncInfo->psSyncData->ui32LastReadOpDumpVal == 0))
+ {
+
+ PDUMPCOMMENT("Init RT TA-SRC ROpsComplete\r\n", i);
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psSyncInfo->psSyncDataMemInfoKM,
+ offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete),
+ sizeof(psSyncInfo->psSyncData->ui32ReadOpsComplete),
+ 0,
+ MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+
+ PDUMPCOMMENT("Init RT TA-SRC WOpsComplete\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psSyncInfo->psSyncDataMemInfoKM,
+ offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete),
+ sizeof(psSyncInfo->psSyncData->ui32WriteOpsComplete),
+ 0,
+ MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+ }
+
+ psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
+
+ ui32ModifiedValue = psSyncInfo->psSyncData->ui32LastReadOpDumpVal - 1;
+
+ PDUMPCOMMENT("Modify TA SrcSync %d ROpsPendingVal\r\n", i);
+
+ PDUMPMEM(&ui32ModifiedValue,
+ psCCBMemInfo,
+ psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, asTASrcSyncs) +
+ (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal),
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ PDUMPCOMMENT("Modify TA SrcSync %d WOpPendingVal\r\n", i);
+
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psCCBMemInfo,
+ psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, asTASrcSyncs) +
+ (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal),
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psCCBMemInfo));
+ }
+
+ for (i=0; i<psCCBKick->ui32NumTADstSyncs; i++)
+ {
+ IMG_UINT32 ui32ModifiedValue;
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTADstKernelSyncInfo[i];
+
+ if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) &&
+ (psSyncInfo->psSyncData->ui32LastReadOpDumpVal == 0))
+ {
+
+ PDUMPCOMMENT("Init RT TA-DST ROpsComplete\r\n", i);
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psSyncInfo->psSyncDataMemInfoKM,
+ offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete),
+ sizeof(psSyncInfo->psSyncData->ui32ReadOpsComplete),
+ 0,
+ MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+
+ PDUMPCOMMENT("Init RT TA-DST WOpsComplete\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psSyncInfo->psSyncDataMemInfoKM,
+ offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete),
+ sizeof(psSyncInfo->psSyncData->ui32WriteOpsComplete),
+ 0,
+ MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+ }
+
+ psSyncInfo->psSyncData->ui32LastOpDumpVal++;
+
+ ui32ModifiedValue = psSyncInfo->psSyncData->ui32LastOpDumpVal - 1;
+
+ PDUMPCOMMENT("Modify TA DstSync %d WOpPendingVal\r\n", i);
+
+ PDUMPMEM(&ui32ModifiedValue,
+ psCCBMemInfo,
+ psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, asTADstSyncs) +
+ (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal),
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ PDUMPCOMMENT("Modify TA DstSync %d ROpsPendingVal\r\n", i);
+
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psCCBMemInfo,
+ psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, asTADstSyncs) +
+ (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal),
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psCCBMemInfo));
+ }
+
+ for (i=0; i<psCCBKick->ui32Num3DSrcSyncs; i++)
+ {
+ IMG_UINT32 ui32ModifiedValue;
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ah3DSrcKernelSyncInfo[i];
+
+ if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) &&
+ (psSyncInfo->psSyncData->ui32LastReadOpDumpVal == 0))
+ {
+
+ PDUMPCOMMENT("Init RT 3D-SRC ROpsComplete\r\n", i);
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psSyncInfo->psSyncDataMemInfoKM,
+ offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete),
+ sizeof(psSyncInfo->psSyncData->ui32ReadOpsComplete),
+ 0,
+ MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+
+ PDUMPCOMMENT("Init RT 3D-SRC WOpsComplete\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psSyncInfo->psSyncDataMemInfoKM,
+ offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete),
+ sizeof(psSyncInfo->psSyncData->ui32WriteOpsComplete),
+ 0,
+ MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+ }
+
+ psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
+
+ ui32ModifiedValue = psSyncInfo->psSyncData->ui32LastReadOpDumpVal - 1;
+
+ PDUMPCOMMENT("Modify 3D SrcSync %d ROpsPendingVal\r\n", i);
+
+ PDUMPMEM(&ui32ModifiedValue,
+ psCCBMemInfo,
+ psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, as3DSrcSyncs) +
+ (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal),
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ PDUMPCOMMENT("Modify 3D SrcSync %d WOpPendingVal\r\n", i);
+
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psCCBMemInfo,
+ psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, as3DSrcSyncs) +
+ (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal),
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psCCBMemInfo));
+ }
+#else
+ for (i=0; i<psCCBKick->ui32NumSrcSyncs; i++)
+ {
+ IMG_UINT32 ui32ModifiedValue;
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahSrcKernelSyncInfo[i];
+
+ if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) &&
+ (psSyncInfo->psSyncData->ui32LastReadOpDumpVal == 0))
+ {
+
+ PDUMPCOMMENT("Init RT ROpsComplete\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psSyncInfo->psSyncDataMemInfoKM,
+ offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete),
+ sizeof(psSyncInfo->psSyncData->ui32ReadOpsComplete),
+ 0,
+ MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+
+ PDUMPCOMMENT("Init RT WOpsComplete\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psSyncInfo->psSyncDataMemInfoKM,
+ offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete),
+ sizeof(psSyncInfo->psSyncData->ui32WriteOpsComplete),
+ 0,
+ MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+ }
+
+ psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
+
+ ui32ModifiedValue = psSyncInfo->psSyncData->ui32LastReadOpDumpVal - 1;
+
+ PDUMPCOMMENT("Modify SrcSync %d ROpsPendingVal\r\n", i);
+
+ PDUMPMEM(&ui32ModifiedValue,
+ psCCBMemInfo,
+ psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, asSrcSyncs) +
+ (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal),
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ PDUMPCOMMENT("Modify SrcSync %d WOpPendingVal\r\n", i);
+
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psCCBMemInfo,
+ psCCBKick->ui32CCBDumpWOff + offsetof(SGXMKIF_CMDTA_SHARED, asSrcSyncs) +
+ (i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT)) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal),
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psCCBMemInfo));
+ }
+#endif
+
+ for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++)
+ {
+#if !defined(SUPPORT_SGX_NEW_STATUS_VALS)
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ahTAStatusSyncInfo[i];
+ PDUMPCOMMENT("Modify TA status value in TA cmd\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psCCBMemInfo,
+ psCCBKick->ui32CCBDumpWOff + (IMG_UINT32)offsetof(SGXMKIF_CMDTA_SHARED, sCtlTAStatusInfo[i].ui32StatusValue),
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psCCBMemInfo));
+#endif
+ }
+
+ for (i = 0; i < psCCBKick->ui32Num3DStatusVals; i++)
+ {
+#if !defined(SUPPORT_SGX_NEW_STATUS_VALS)
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ah3DStatusSyncInfo[i];
+ PDUMPCOMMENT("Modify 3D status value in TA cmd\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psCCBMemInfo,
+ psCCBKick->ui32CCBDumpWOff + (IMG_UINT32)offsetof(SGXMKIF_CMDTA_SHARED, sCtl3DStatusInfo[i].ui32StatusValue),
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psCCBMemInfo));
+#endif
+ }
+ }
+#endif
+
+ pvr_trcmd_set_data(&ktrace->ctx, psCCBKick->sCommand.ui32Data[1]);
+ pvr_trcmd_commit(ktrace);
+
+ eError = SGXScheduleCCBCommandKM(hDevHandle, SGXMKIF_CMD_TA, &psCCBKick->sCommand, KERNEL_ID, 0);
+ if (eError == PVRSRV_ERROR_RETRY)
+ {
+ if (psCCBKick->bFirstKickOrResume && psCCBKick->ui32NumDstSyncObjects > 0)
+ {
+ for (i=0; i < psCCBKick->ui32NumDstSyncObjects; i++)
+ {
+
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->pahDstSyncHandles[i];
+
+ if (psSyncInfo)
+ {
+ psSyncInfo->psSyncData->ui32WriteOpsPending--;
+#if defined(PDUMP)
+ if (PDumpIsCaptureFrameKM())
+ {
+ psSyncInfo->psSyncData->ui32LastOpDumpVal--;
+ }
+#endif
+ }
+ }
+ }
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+ for (i=0; i<psCCBKick->ui32NumTASrcSyncs; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTASrcKernelSyncInfo[i];
+ psSyncInfo->psSyncData->ui32ReadOpsPending--;
+ }
+ for (i=0; i<psCCBKick->ui32NumTADstSyncs; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTADstKernelSyncInfo[i];
+ psSyncInfo->psSyncData->ui32WriteOpsPending--;
+ }
+ for (i=0; i<psCCBKick->ui32Num3DSrcSyncs; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ah3DSrcKernelSyncInfo[i];
+ psSyncInfo->psSyncData->ui32ReadOpsPending--;
+ }
+#else
+ for (i=0; i<psCCBKick->ui32NumSrcSyncs; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahSrcKernelSyncInfo[i];
+ psSyncInfo->psSyncData->ui32ReadOpsPending--;
+ }
+#endif
+
+ return eError;
+ }
+ else if (PVRSRV_OK != eError)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXDoKickKM: SGXScheduleCCBCommandKM failed."));
+ return eError;
+ }
+
+
+#if defined(NO_HARDWARE)
+
+
+
+ if (psCCBKick->hTA3DSyncInfo)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTA3DSyncInfo;
+
+ if (psCCBKick->bTADependency)
+ {
+ psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+ }
+
+ if (psCCBKick->hTASyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTASyncInfo;
+
+ psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending;
+ }
+
+ if (psCCBKick->h3DSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->h3DSyncInfo;
+
+ psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending;
+ }
+
+
+ for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++)
+ {
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = (PVRSRV_KERNEL_MEM_INFO*)psCCBKick->asTAStatusUpdate[i].hKernelMemInfo;
+
+ *(IMG_UINT32*)((IMG_UINTPTR_T)psKernelMemInfo->pvLinAddrKM
+ + (psTACmd->sCtlTAStatusInfo[i].sStatusDevAddr.uiAddr
+ - psKernelMemInfo->sDevVAddr.uiAddr)) = psTACmd->sCtlTAStatusInfo[i].ui32StatusValue;
+#else
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ahTAStatusSyncInfo[i];
+ psSyncInfo->psSyncData->ui32ReadOpsComplete = psTACmd->sCtlTAStatusInfo[i].ui32StatusValue;
+#endif
+ }
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+
+ for (i=0; i<psCCBKick->ui32NumTASrcSyncs; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTASrcKernelSyncInfo[i];
+ psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending;
+ }
+ for (i=0; i<psCCBKick->ui32NumTADstSyncs; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTADstKernelSyncInfo[i];
+ psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+ for (i=0; i<psCCBKick->ui32Num3DSrcSyncs; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ah3DSrcKernelSyncInfo[i];
+ psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending;
+ }
+#else
+
+ for (i=0; i<psCCBKick->ui32NumSrcSyncs; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahSrcKernelSyncInfo[i];
+ psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending;
+ }
+#endif
+
+ if (psCCBKick->bTerminateOrAbort)
+ {
+ if (psCCBKick->ui32NumDstSyncObjects > 0)
+ {
+ PVRSRV_KERNEL_MEM_INFO *psHWDstSyncListMemInfo =
+ (PVRSRV_KERNEL_MEM_INFO *)psCCBKick->hKernelHWSyncListMemInfo;
+ SGXMKIF_HWDEVICE_SYNC_LIST *psHWDeviceSyncList = psHWDstSyncListMemInfo->pvLinAddrKM;
+
+ for (i=0; i<psCCBKick->ui32NumDstSyncObjects; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->pahDstSyncHandles[i];
+ if (psSyncInfo)
+ psSyncInfo->psSyncData->ui32WriteOpsComplete = psHWDeviceSyncList->asSyncData[i].ui32WriteOpsPendingVal+1;
+ }
+ }
+
+
+ for (i = 0; i < psCCBKick->ui32Num3DStatusVals; i++)
+ {
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = (PVRSRV_KERNEL_MEM_INFO*)psCCBKick->as3DStatusUpdate[i].hKernelMemInfo;
+
+ *(IMG_UINT32*)((IMG_UINTPTR_T)psKernelMemInfo->pvLinAddrKM
+ + (psTACmd->sCtl3DStatusInfo[i].sStatusDevAddr.uiAddr
+ - psKernelMemInfo->sDevVAddr.uiAddr)) = psTACmd->sCtl3DStatusInfo[i].ui32StatusValue;
+#else
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->ah3DStatusSyncInfo[i];
+ psSyncInfo->psSyncData->ui32ReadOpsComplete = psTACmd->sCtl3DStatusInfo[i].ui32StatusValue;
+#endif
+ }
+ }
+#endif
+
+ return eError;
+}
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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 <stddef.h>
+
+#include "sgxdefs.h"
+#include "services_headers.h"
+#include "sgxapi_km.h"
+#include "sgx_mkif_km.h"
+#include "sgxutils.h"
+#include "pdump_km.h"
+
+
+#if defined(SUPPORT_HW_RECOVERY)
+static PVRSRV_ERROR SGXAddTimer(PVRSRV_DEVICE_NODE *psDeviceNode,
+ SGX_TIMING_INFORMATION *psSGXTimingInfo,
+ IMG_HANDLE *phTimer)
+{
+
+
+
+ *phTimer = OSAddTimer(SGXOSTimer, psDeviceNode,
+ 1000 * 50 / psSGXTimingInfo->ui32uKernelFreq);
+ if(*phTimer == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXAddTimer : Failed to register timer callback function"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ return PVRSRV_OK;
+}
+#endif
+
+
+static PVRSRV_ERROR SGXUpdateTimingInfo(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+#if defined(SGX_DYNAMIC_TIMING_INFO)
+ SGX_TIMING_INFORMATION sSGXTimingInfo = {0};
+#else
+ SGX_DEVICE_MAP *psSGXDeviceMap;
+#endif
+ IMG_UINT32 ui32ActivePowManSampleRate;
+ SGX_TIMING_INFORMATION *psSGXTimingInfo;
+
+
+#if defined(SGX_DYNAMIC_TIMING_INFO)
+ psSGXTimingInfo = &sSGXTimingInfo;
+ SysGetSGXTimingInformation(psSGXTimingInfo);
+#else
+ SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX,
+ (IMG_VOID**)&psSGXDeviceMap);
+ psSGXTimingInfo = &psSGXDeviceMap->sTimingInfo;
+#endif
+
+#if defined(SUPPORT_HW_RECOVERY)
+ {
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32OlduKernelFreq;
+
+ if (psDevInfo->hTimer != IMG_NULL)
+ {
+ ui32OlduKernelFreq = psDevInfo->ui32CoreClockSpeed / psDevInfo->ui32uKernelTimerClock;
+ if (ui32OlduKernelFreq != psSGXTimingInfo->ui32uKernelFreq)
+ {
+
+
+ IMG_HANDLE hNewTimer;
+
+ eError = SGXAddTimer(psDeviceNode, psSGXTimingInfo, &hNewTimer);
+ if (eError == PVRSRV_OK)
+ {
+ eError = OSRemoveTimer(psDevInfo->hTimer);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXUpdateTimingInfo: Failed to remove timer"));
+ }
+ psDevInfo->hTimer = hNewTimer;
+ }
+ else
+ {
+
+ }
+ }
+ }
+ else
+ {
+ eError = SGXAddTimer(psDeviceNode, psSGXTimingInfo, &psDevInfo->hTimer);
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+
+ psDevInfo->psSGXHostCtl->ui32HWRecoverySampleRate =
+ psSGXTimingInfo->ui32uKernelFreq / psSGXTimingInfo->ui32HWRecoveryFreq;
+ }
+#endif
+
+
+ psDevInfo->ui32CoreClockSpeed = psSGXTimingInfo->ui32CoreClockSpeed;
+ psDevInfo->ui32uKernelTimerClock = psSGXTimingInfo->ui32CoreClockSpeed / psSGXTimingInfo->ui32uKernelFreq;
+
+
+ psDevInfo->psSGXHostCtl->ui32uKernelTimerClock = psDevInfo->ui32uKernelTimerClock;
+#if defined(PDUMP)
+ PDUMPCOMMENT("Host Control - Microkernel clock");
+ PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+ offsetof(SGXMKIF_HOST_CTL, ui32uKernelTimerClock),
+ sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+#endif
+
+ if (psSGXTimingInfo->bEnableActivePM)
+ {
+ ui32ActivePowManSampleRate =
+ psSGXTimingInfo->ui32uKernelFreq * psSGXTimingInfo->ui32ActivePowManLatencyms / 1000;
+
+
+
+
+
+
+
+ ui32ActivePowManSampleRate += 1;
+ }
+ else
+ {
+ ui32ActivePowManSampleRate = 0;
+ }
+
+ psDevInfo->psSGXHostCtl->ui32ActivePowManSampleRate = ui32ActivePowManSampleRate;
+#if defined(PDUMP)
+ PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+ offsetof(SGXMKIF_HOST_CTL, ui32ActivePowManSampleRate),
+ sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+#endif
+
+ return PVRSRV_OK;
+}
+
+
+static IMG_VOID SGXStartTimer(PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+ #if defined(SUPPORT_HW_RECOVERY)
+ PVRSRV_ERROR eError;
+
+ eError = OSEnableTimer(psDevInfo->hTimer);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXStartTimer : Failed to enable host timer"));
+ }
+ #else
+ PVR_UNREFERENCED_PARAMETER(psDevInfo);
+ #endif
+}
+
+
+static IMG_VOID SGXPollForClockGating (PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32Register,
+ IMG_UINT32 ui32RegisterValue,
+ IMG_CHAR *pszComment)
+{
+ PVR_UNREFERENCED_PARAMETER(psDevInfo);
+ PVR_UNREFERENCED_PARAMETER(ui32Register);
+ PVR_UNREFERENCED_PARAMETER(ui32RegisterValue);
+ PVR_UNREFERENCED_PARAMETER(pszComment);
+
+ #if !defined(NO_HARDWARE)
+ PVR_ASSERT(psDevInfo != IMG_NULL);
+
+
+ if (PollForValueKM((IMG_UINT32 *)psDevInfo->pvRegsBaseKM + (ui32Register >> 2),
+ 0,
+ ui32RegisterValue,
+ MAX_HW_TIME_US,
+ MAX_HW_TIME_US/WAIT_TRY_COUNT,
+ IMG_FALSE) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXPollForClockGating: %s failed.", pszComment));
+ PVR_DBG_BREAK;
+ }
+ #endif
+
+ PDUMPCOMMENT("%s", pszComment);
+ PDUMPREGPOL(SGX_PDUMPREG_NAME, ui32Register, 0, ui32RegisterValue);
+}
+
+
+PVRSRV_ERROR SGXPrePowerState (IMG_HANDLE hDevHandle,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+ if ((eNewPowerState != eCurrentPowerState) &&
+ (eNewPowerState != PVRSRV_DEV_POWER_STATE_ON))
+ {
+ PVRSRV_ERROR eError;
+ PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ IMG_UINT32 ui32PowerCmd, ui32CompleteStatus;
+ SGXMKIF_COMMAND sCommand = {0};
+ IMG_UINT32 ui32Core;
+
+ #if defined(SUPPORT_HW_RECOVERY)
+
+ eError = OSDisableTimer(psDevInfo->hTimer);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: Failed to disable timer"));
+ return eError;
+ }
+ #endif
+
+ if (eNewPowerState == PVRSRV_DEV_POWER_STATE_OFF)
+ {
+
+ ui32PowerCmd = PVRSRV_POWERCMD_POWEROFF;
+ ui32CompleteStatus = PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE;
+ PDUMPCOMMENT("SGX power off request");
+ }
+ else
+ {
+
+ ui32PowerCmd = PVRSRV_POWERCMD_IDLE;
+ ui32CompleteStatus = PVRSRV_USSE_EDM_POWMAN_IDLE_COMPLETE;
+ PDUMPCOMMENT("SGX idle request");
+ }
+
+ sCommand.ui32Data[1] = ui32PowerCmd;
+
+ eError = SGXScheduleCCBCommand(psDevInfo, SGXMKIF_CMD_POWER, &sCommand, KERNEL_ID, 0);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: Failed to submit power down command"));
+ return eError;
+ }
+
+
+ #if !defined(NO_HARDWARE)
+ if (PollForValueKM(&psDevInfo->psSGXHostCtl->ui32PowerStatus,
+ ui32CompleteStatus,
+ ui32CompleteStatus,
+ MAX_HW_TIME_US,
+ MAX_HW_TIME_US/WAIT_TRY_COUNT,
+ IMG_FALSE) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: Wait for SGX ukernel power transition failed."));
+ PVR_DBG_BREAK;
+ }
+ #endif
+
+ #if defined(PDUMP)
+ PDUMPCOMMENT("TA/3D CCB Control - Wait for power event on uKernel.");
+ PDUMPMEMPOL(psDevInfo->psKernelSGXHostCtlMemInfo,
+ offsetof(SGXMKIF_HOST_CTL, ui32PowerStatus),
+ ui32CompleteStatus,
+ ui32CompleteStatus,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ 0,
+ MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+ #endif
+
+ for (ui32Core = 0; ui32Core < SGX_FEATURE_MP_CORE_COUNT; ui32Core++)
+ {
+
+ SGXPollForClockGating(psDevInfo,
+ SGX_MP_CORE_SELECT(psDevInfo->ui32ClkGateStatusReg, ui32Core),
+ psDevInfo->ui32ClkGateStatusMask,
+ "Wait for SGX clock gating");
+ }
+
+ #if defined(SGX_FEATURE_MP)
+
+ SGXPollForClockGating(psDevInfo,
+ psDevInfo->ui32MasterClkGateStatusReg,
+ psDevInfo->ui32MasterClkGateStatusMask,
+ "Wait for SGX master clock gating");
+
+ SGXPollForClockGating(psDevInfo,
+ psDevInfo->ui32MasterClkGateStatus2Reg,
+ psDevInfo->ui32MasterClkGateStatus2Mask,
+ "Wait for SGX master clock gating (2)");
+ #endif
+
+ if (eNewPowerState == PVRSRV_DEV_POWER_STATE_OFF)
+ {
+
+ eError = SGXDeinitialise(psDevInfo);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: SGXDeinitialise failed: %u", eError));
+ return eError;
+ }
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR SGXPostPowerState (IMG_HANDLE hDevHandle,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+ if ((eNewPowerState != eCurrentPowerState) &&
+ (eCurrentPowerState != PVRSRV_DEV_POWER_STATE_ON))
+ {
+ PVRSRV_ERROR eError;
+ PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ SGXMKIF_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl;
+
+
+ psSGXHostCtl->ui32PowerStatus = 0;
+ #if defined(PDUMP)
+ PDUMPCOMMENT("Host Control - Reset power status");
+ PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+ offsetof(SGXMKIF_HOST_CTL, ui32PowerStatus),
+ sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+ #endif
+
+ if (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_OFF)
+ {
+
+
+
+
+ eError = SGXUpdateTimingInfo(psDeviceNode);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXPostPowerState: SGXUpdateTimingInfo failed"));
+ return eError;
+ }
+
+
+
+ eError = SGXInitialise(psDevInfo, IMG_FALSE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXPostPowerState: SGXInitialise failed"));
+ return eError;
+ }
+ }
+ else
+ {
+
+
+ SGXMKIF_COMMAND sCommand = {0};
+
+ sCommand.ui32Data[1] = PVRSRV_POWERCMD_RESUME;
+ eError = SGXScheduleCCBCommand(psDevInfo, SGXMKIF_CMD_POWER, &sCommand, ISR_ID, 0);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXPostPowerState failed to schedule CCB command: %u", eError));
+ return eError;
+ }
+ }
+
+ SGXStartTimer(psDevInfo);
+ }
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR SGXPreClockSpeedChange (IMG_HANDLE hDevHandle,
+ IMG_BOOL bIdleDevice,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+
+ PVR_UNREFERENCED_PARAMETER(psDevInfo);
+
+ if (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_ON)
+ {
+ if (bIdleDevice)
+ {
+
+ PDUMPSUSPEND();
+
+ eError = SGXPrePowerState(hDevHandle, PVRSRV_DEV_POWER_STATE_IDLE,
+ PVRSRV_DEV_POWER_STATE_ON);
+
+ if (eError != PVRSRV_OK)
+ {
+ PDUMPRESUME();
+ return eError;
+ }
+ }
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE,"SGXPreClockSpeedChange: SGX clock speed was %uHz",
+ psDevInfo->ui32CoreClockSpeed));
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR SGXPostClockSpeedChange (IMG_HANDLE hDevHandle,
+ IMG_BOOL bIdleDevice,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ IMG_UINT32 ui32OldClockSpeed = psDevInfo->ui32CoreClockSpeed;
+
+ PVR_UNREFERENCED_PARAMETER(ui32OldClockSpeed);
+
+ if (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_ON)
+ {
+ PVRSRV_ERROR eError;
+
+
+
+ eError = SGXUpdateTimingInfo(psDeviceNode);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXPostPowerState: SGXUpdateTimingInfo failed"));
+ return eError;
+ }
+
+ if (bIdleDevice)
+ {
+
+ eError = SGXPostPowerState(hDevHandle, PVRSRV_DEV_POWER_STATE_ON,
+ PVRSRV_DEV_POWER_STATE_IDLE);
+
+ PDUMPRESUME();
+
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+ else
+ {
+ SGXStartTimer(psDevInfo);
+ }
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE,"SGXPostClockSpeedChange: SGX clock speed changed from %uHz to %uHz",
+ ui32OldClockSpeed, psDevInfo->ui32CoreClockSpeed));
+
+ return PVRSRV_OK;
+}
+
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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 "sgxdefs.h"
+#include "sgxmmu.h"
+#include "services_headers.h"
+#include "sgxinfokm.h"
+#include "sgxconfig.h"
+
+#include "pdump_km.h"
+
+
+static IMG_VOID SGXResetSoftReset(PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_BOOL bResetBIF,
+ IMG_UINT32 ui32PDUMPFlags,
+ IMG_BOOL bPDump)
+{
+ IMG_UINT32 ui32SoftResetRegVal;
+
+#if defined(SGX_FEATURE_MP)
+ ui32SoftResetRegVal =
+ EUR_CR_MASTER_SOFT_RESET_IPF_RESET_MASK |
+ EUR_CR_MASTER_SOFT_RESET_DPM_RESET_MASK |
+ EUR_CR_MASTER_SOFT_RESET_VDM_RESET_MASK;
+
+#if defined(SGX_FEATURE_PTLA)
+ ui32SoftResetRegVal |= EUR_CR_MASTER_SOFT_RESET_PTLA_RESET_MASK;
+#endif
+#if defined(SGX_FEATURE_SYSTEM_CACHE)
+ ui32SoftResetRegVal |= EUR_CR_MASTER_SOFT_RESET_SLC_RESET_MASK;
+#endif
+
+ if (bResetBIF)
+ {
+ ui32SoftResetRegVal |= EUR_CR_MASTER_SOFT_RESET_BIF_RESET_MASK;
+ }
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_SOFT_RESET, ui32SoftResetRegVal);
+ if (bPDump)
+ {
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_MASTER_SOFT_RESET, ui32SoftResetRegVal, ui32PDUMPFlags);
+ }
+#endif
+
+ ui32SoftResetRegVal =
+
+ EUR_CR_SOFT_RESET_DPM_RESET_MASK |
+ EUR_CR_SOFT_RESET_TA_RESET_MASK |
+ EUR_CR_SOFT_RESET_USE_RESET_MASK |
+ EUR_CR_SOFT_RESET_ISP_RESET_MASK |
+ EUR_CR_SOFT_RESET_TSP_RESET_MASK;
+
+#ifdef EUR_CR_SOFT_RESET_TWOD_RESET_MASK
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_TWOD_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_TE_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_TE_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_MTE_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_MTE_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_ISP2_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_ISP2_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_PDS_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_PDS_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_PBE_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_PBE_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_CACHEL2_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_CACHEL2_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_TCU_L2_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_TCU_L2_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_UCACHEL2_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_UCACHEL2_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_MADD_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_MADD_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_ITR_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_ITR_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_TEX_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_TEX_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_IDXFIFO_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_IDXFIFO_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_VDM_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_VDM_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_DCU_L2_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_DCU_L2_RESET_MASK;
+#endif
+#if defined(EUR_CR_SOFT_RESET_DCU_L0L1_RESET_MASK)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_DCU_L0L1_RESET_MASK;
+#endif
+
+#if !defined(PDUMP)
+ PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
+#endif
+
+ if (bResetBIF)
+ {
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_BIF_RESET_MASK;
+ }
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_SOFT_RESET, ui32SoftResetRegVal);
+ if (bPDump)
+ {
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_SOFT_RESET, ui32SoftResetRegVal, ui32PDUMPFlags);
+ }
+}
+
+
+static IMG_VOID SGXResetSleep(PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32PDUMPFlags,
+ IMG_BOOL bPDump)
+{
+#if !defined(PDUMP)
+ PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
+#endif
+
+
+ OSWaitus(100 * 1000000 / psDevInfo->ui32CoreClockSpeed);
+ if (bPDump)
+ {
+ PDUMPIDLWITHFLAGS(30, ui32PDUMPFlags);
+#if defined(PDUMP)
+ PDumpRegRead(SGX_PDUMPREG_NAME, EUR_CR_SOFT_RESET, ui32PDUMPFlags);
+#endif
+ }
+
+}
+
+
+static IMG_VOID SGXResetInvalDC(PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32PDUMPFlags,
+ IMG_BOOL bPDump)
+{
+ IMG_UINT32 ui32RegVal;
+
+
+#if defined(EUR_CR_BIF_CTRL_INVAL)
+ ui32RegVal = EUR_CR_BIF_CTRL_INVAL_ALL_MASK;
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL_INVAL, ui32RegVal);
+ if (bPDump)
+ {
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL_INVAL, ui32RegVal, ui32PDUMPFlags);
+ }
+#else
+ ui32RegVal = EUR_CR_BIF_CTRL_INVALDC_MASK;
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
+ if (bPDump)
+ {
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+ }
+
+ ui32RegVal = 0;
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
+ if (bPDump)
+ {
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+ }
+#endif
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, bPDump);
+
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+ {
+
+
+
+ if (PollForValueKM((IMG_UINT32 *)((IMG_UINT8*)psDevInfo->pvRegsBaseKM + EUR_CR_BIF_MEM_REQ_STAT),
+ 0,
+ EUR_CR_BIF_MEM_REQ_STAT_READS_MASK,
+ MAX_HW_TIME_US,
+ MAX_HW_TIME_US/WAIT_TRY_COUNT,
+ IMG_FALSE) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"Wait for DC invalidate failed."));
+ PVR_DBG_BREAK;
+ }
+
+ if (bPDump)
+ {
+ PDUMPREGPOLWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_MEM_REQ_STAT, 0, EUR_CR_BIF_MEM_REQ_STAT_READS_MASK, ui32PDUMPFlags);
+ }
+ }
+#endif
+}
+
+
+IMG_VOID SGXReset(PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_BOOL bHardwareRecovery,
+ IMG_UINT32 ui32PDUMPFlags)
+{
+ IMG_UINT32 ui32RegVal;
+#if defined(EUR_CR_BIF_INT_STAT_FAULT_REQ_MASK)
+ const IMG_UINT32 ui32BifFaultMask = EUR_CR_BIF_INT_STAT_FAULT_REQ_MASK;
+#else
+ const IMG_UINT32 ui32BifFaultMask = EUR_CR_BIF_INT_STAT_FAULT_MASK;
+#endif
+
+#ifndef PDUMP
+ PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
+#endif
+
+ psDevInfo->ui32NumResets++;
+
+ PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Start of SGX reset sequence\r\n");
+
+#if defined(FIX_HW_BRN_23944)
+
+ ui32RegVal = EUR_CR_BIF_CTRL_PAUSE_MASK;
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+ ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_INT_STAT);
+ if (ui32RegVal & ui32BifFaultMask)
+ {
+
+ ui32RegVal = EUR_CR_BIF_CTRL_PAUSE_MASK | EUR_CR_BIF_CTRL_CLEAR_FAULT_MASK;
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+ ui32RegVal = EUR_CR_BIF_CTRL_PAUSE_MASK;
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+ }
+#endif
+
+
+ SGXResetSoftReset(psDevInfo, IMG_TRUE, ui32PDUMPFlags, IMG_TRUE);
+
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+
+
+#if defined(SGX_FEATURE_36BIT_MMU)
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_36BIT_ADDRESSING, EUR_CR_BIF_36BIT_ADDRESSING_ENABLE_MASK);
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_36BIT_ADDRESSING, EUR_CR_BIF_36BIT_ADDRESSING_ENABLE_MASK, ui32PDUMPFlags);
+#endif
+
+ ui32RegVal = 0;
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+#if defined(SGX_FEATURE_MP)
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_BIF_CTRL, ui32RegVal);
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_MASTER_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+#endif
+#if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_BANK_SET, ui32RegVal);
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_BANK_SET, ui32RegVal, ui32PDUMPFlags);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_BANK0, ui32RegVal);
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_BANK0, ui32RegVal, ui32PDUMPFlags);
+#endif
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_DIR_LIST_BASE0, ui32RegVal);
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_DIR_LIST_BASE0, ui32RegVal, ui32PDUMPFlags);
+
+#if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+ {
+ IMG_UINT32 ui32DirList, ui32DirListReg;
+
+ for (ui32DirList = 1;
+ ui32DirList < SGX_FEATURE_BIF_NUM_DIRLISTS;
+ ui32DirList++)
+ {
+ ui32DirListReg = EUR_CR_BIF_DIR_LIST_BASE1 + 4 * (ui32DirList - 1);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32DirListReg, ui32RegVal);
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, ui32DirListReg, ui32RegVal, ui32PDUMPFlags);
+ }
+ }
+#endif
+
+#if defined(EUR_CR_BIF_MEM_ARB_CONFIG)
+
+
+ ui32RegVal = (12UL << EUR_CR_BIF_MEM_ARB_CONFIG_PAGE_SIZE_SHIFT) |
+ (7UL << EUR_CR_BIF_MEM_ARB_CONFIG_BEST_CNT_SHIFT) |
+ (12UL << EUR_CR_BIF_MEM_ARB_CONFIG_TTE_THRESH_SHIFT);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_MEM_ARB_CONFIG, ui32RegVal);
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_MEM_ARB_CONFIG, ui32RegVal, ui32PDUMPFlags);
+#endif
+
+#if defined(SGX_FEATURE_SYSTEM_CACHE)
+#if defined(SGX_FEATURE_MP)
+ #if defined(SGX_BYPASS_SYSTEM_CACHE)
+ #error SGX_BYPASS_SYSTEM_CACHE not supported
+ #else
+ ui32RegVal = EUR_CR_MASTER_SLC_CTRL_USSE_INVAL_REQ0_MASK |
+ #if defined(FIX_HW_BRN_30954)
+ EUR_CR_MASTER_SLC_CTRL_DISABLE_REORDERING_MASK |
+ #endif
+ (0xC << EUR_CR_MASTER_SLC_CTRL_ARB_PAGE_SIZE_SHIFT);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_SLC_CTRL, ui32RegVal);
+ PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_MASTER_SLC_CTRL, ui32RegVal);
+
+ ui32RegVal = EUR_CR_MASTER_SLC_CTRL_BYPASS_BYP_CC_MASK;
+ #if defined(FIX_HW_BRN_31195)
+ ui32RegVal |= EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_USE0_MASK |
+ EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_USE1_MASK |
+ EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_USE2_MASK |
+ EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_USE3_MASK |
+ EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_TA_MASK;
+ #endif
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_SLC_CTRL_BYPASS, ui32RegVal);
+ PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_MASTER_SLC_CTRL_BYPASS, ui32RegVal);
+ #endif
+#else
+ #if defined(SGX_BYPASS_SYSTEM_CACHE)
+
+ ui32RegVal = MNE_CR_CTRL_BYPASS_ALL_MASK;
+ #else
+ #if defined(FIX_HW_BRN_26620)
+ ui32RegVal = 0;
+ #else
+
+ ui32RegVal = MNE_CR_CTRL_BYP_CC_MASK;
+ #endif
+ #endif
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, MNE_CR_CTRL, ui32RegVal);
+ PDUMPREG(SGX_PDUMPREG_NAME, MNE_CR_CTRL, ui32RegVal);
+#endif
+#endif
+
+ if (bHardwareRecovery)
+ {
+
+
+
+
+
+
+
+ ui32RegVal = (IMG_UINT32)psDevInfo->sBIFResetPDDevPAddr.uiAddr;
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_DIR_LIST_BASE0, ui32RegVal);
+
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+
+ SGXResetSoftReset(psDevInfo, IMG_FALSE, ui32PDUMPFlags, IMG_TRUE);
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+ SGXResetInvalDC(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+
+
+ for (;;)
+ {
+ IMG_UINT32 ui32BifIntStat = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_INT_STAT);
+ IMG_DEV_VIRTADDR sBifFault;
+ IMG_UINT32 ui32PDIndex, ui32PTIndex;
+
+ if ((ui32BifIntStat & ui32BifFaultMask) == 0)
+ {
+ break;
+ }
+
+
+
+
+ sBifFault.uiAddr = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_FAULT);
+ PVR_DPF((PVR_DBG_WARNING, "SGXReset: Page fault 0x%x/0x%x", ui32BifIntStat, sBifFault.uiAddr));
+ ui32PDIndex = sBifFault.uiAddr >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT);
+ ui32PTIndex = (sBifFault.uiAddr & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT;
+
+
+ SGXResetSoftReset(psDevInfo, IMG_TRUE, ui32PDUMPFlags, IMG_FALSE);
+
+
+ psDevInfo->pui32BIFResetPD[ui32PDIndex] = (psDevInfo->sBIFResetPTDevPAddr.uiAddr
+ >>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PDE_PAGE_SIZE_4K
+ | SGX_MMU_PDE_VALID;
+ psDevInfo->pui32BIFResetPT[ui32PTIndex] = (psDevInfo->sBIFResetPageDevPAddr.uiAddr
+ >>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PTE_VALID;
+
+
+ ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR, ui32RegVal);
+ ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS2);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR2, ui32RegVal);
+
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+
+ SGXResetSoftReset(psDevInfo, IMG_FALSE, ui32PDUMPFlags, IMG_FALSE);
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+
+ SGXResetInvalDC(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+
+ psDevInfo->pui32BIFResetPD[ui32PDIndex] = 0;
+ psDevInfo->pui32BIFResetPT[ui32PTIndex] = 0;
+ }
+ }
+ else
+ {
+
+ SGXResetSoftReset(psDevInfo, IMG_FALSE, ui32PDUMPFlags, IMG_TRUE);
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+ }
+
+
+
+ #if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+
+ ui32RegVal = (SGX_BIF_DIR_LIST_INDEX_EDM << EUR_CR_BIF_BANK0_INDEX_EDM_SHIFT);
+
+ #if defined(SGX_FEATURE_2D_HARDWARE) && !defined(SGX_FEATURE_PTLA)
+
+ ui32RegVal |= (SGX_BIF_DIR_LIST_INDEX_EDM << EUR_CR_BIF_BANK0_INDEX_2D_SHIFT);
+ #endif
+
+ #if defined(FIX_HW_BRN_23410)
+
+ ui32RegVal |= (SGX_BIF_DIR_LIST_INDEX_EDM << EUR_CR_BIF_BANK0_INDEX_TA_SHIFT);
+ #endif
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_BANK0, ui32RegVal);
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_BANK0, ui32RegVal, ui32PDUMPFlags);
+ #endif
+
+ {
+ IMG_UINT32 ui32EDMDirListReg;
+
+
+ #if (SGX_BIF_DIR_LIST_INDEX_EDM == 0)
+ ui32EDMDirListReg = EUR_CR_BIF_DIR_LIST_BASE0;
+ #else
+
+ ui32EDMDirListReg = EUR_CR_BIF_DIR_LIST_BASE1 + 4 * (SGX_BIF_DIR_LIST_INDEX_EDM - 1);
+ #endif
+
+#if defined(FIX_HW_BRN_28011)
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_DIR_LIST_BASE0, psDevInfo->sKernelPDDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT);
+ PDUMPPDREGWITHFLAGS(&psDevInfo->sMMUAttrib, EUR_CR_BIF_DIR_LIST_BASE0, psDevInfo->sKernelPDDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT, ui32PDUMPFlags, PDUMP_PD_UNIQUETAG);
+#endif
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32EDMDirListReg, psDevInfo->sKernelPDDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT);
+ PDUMPPDREGWITHFLAGS(&psDevInfo->sMMUAttrib, ui32EDMDirListReg, psDevInfo->sKernelPDDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT, ui32PDUMPFlags, PDUMP_PD_UNIQUETAG);
+ }
+
+#if defined(SGX_FEATURE_2D_HARDWARE) && !defined(SGX_FEATURE_PTLA)
+
+ #if ((SGX_2D_HEAP_BASE & ~EUR_CR_BIF_TWOD_REQ_BASE_ADDR_MASK) != 0)
+ #error "SGXReset: SGX_2D_HEAP_BASE doesn't match EUR_CR_BIF_TWOD_REQ_BASE_ADDR_MASK alignment"
+ #endif
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_TWOD_REQ_BASE, SGX_2D_HEAP_BASE);
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_TWOD_REQ_BASE, SGX_2D_HEAP_BASE, ui32PDUMPFlags);
+#endif
+
+
+ SGXResetInvalDC(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+ PVR_DPF((PVR_DBG_MESSAGE,"Soft Reset of SGX"));
+
+
+ ui32RegVal = 0;
+#if defined(SGX_FEATURE_MP)
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_SOFT_RESET, ui32RegVal);
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_MASTER_SOFT_RESET, ui32RegVal, ui32PDUMPFlags);
+#endif
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_SOFT_RESET, ui32RegVal);
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_SOFT_RESET, ui32RegVal, ui32PDUMPFlags);
+
+
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+ PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "End of SGX reset sequence\r\n");
+}
+
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#if defined(TRANSFER_QUEUE)
+
+#include <stddef.h>
+
+#include "sgxdefs.h"
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "sgxinfo.h"
+#include "sysconfig.h"
+#include "regpaths.h"
+#include "pdump_km.h"
+#include "mmu.h"
+#include "pvr_bridge.h"
+#include "sgx_bridge_km.h"
+#include "sgxinfokm.h"
+#include "osfunc.h"
+#include "pvr_debug.h"
+#include "sgxutils.h"
+#include "perproc.h"
+#include "pvr_trace_cmd.h"
+
+IMG_EXPORT PVRSRV_ERROR SGXSubmitTransferKM(IMG_HANDLE hDevHandle, PVRSRV_TRANSFER_SGX_KICK *psKick,
+ PVRSRV_PER_PROCESS_DATA *proc)
+{
+ PVRSRV_KERNEL_MEM_INFO *psCCBMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psKick->hCCBMemInfo;
+ SGXMKIF_COMMAND sCommand = {0};
+ SGXMKIF_TRANSFERCMD_SHARED *psSharedTransferCmd;
+ PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+ PVRSRV_ERROR eError;
+ IMG_UINT32 loop;
+ struct pvr_trcmd_sgxtransfer *ttrace;
+
+#if defined(PDUMP)
+ IMG_BOOL bPersistentProcess = IMG_FALSE;
+
+ {
+ PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData();
+ if(psPerProc != IMG_NULL)
+ {
+ bPersistentProcess = psPerProc->bPDumpPersistent;
+ }
+ }
+#endif
+
+ if (!CCB_OFFSET_IS_VALID(SGXMKIF_TRANSFERCMD_SHARED, psCCBMemInfo, psKick, ui32SharedCmdCCBOffset))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXSubmitTransferKM: Invalid CCB offset"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ psSharedTransferCmd = CCB_DATA_FROM_OFFSET(SGXMKIF_TRANSFERCMD_SHARED, psCCBMemInfo, psKick, ui32SharedCmdCCBOffset);
+
+ ttrace = pvr_trcmd_reserve(PVR_TRCMD_SGX_TFER_KICK, proc->ui32PID,
+ proc->name, sizeof(*ttrace));
+
+ if (psKick->hTASyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
+
+ psSharedTransferCmd->ui32TASyncWriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++;
+ psSharedTransferCmd->ui32TASyncReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+ psSharedTransferCmd->sTASyncWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+ psSharedTransferCmd->sTASyncReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+
+ pvr_trcmd_set_syn(&ttrace->ta_syn, psSyncInfo);
+ }
+ else
+ {
+ psSharedTransferCmd->sTASyncWriteOpsCompleteDevVAddr.uiAddr = 0;
+ psSharedTransferCmd->sTASyncReadOpsCompleteDevVAddr.uiAddr = 0;
+
+ pvr_trcmd_clear_syn(&ttrace->ta_syn);
+ }
+
+ if (psKick->h3DSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
+
+ psSharedTransferCmd->ui323DSyncWriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++;
+ psSharedTransferCmd->ui323DSyncReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+ psSharedTransferCmd->s3DSyncWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+ psSharedTransferCmd->s3DSyncReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+
+ pvr_trcmd_set_syn(&ttrace->_3d_syn, psSyncInfo);
+ }
+ else
+ {
+ psSharedTransferCmd->s3DSyncWriteOpsCompleteDevVAddr.uiAddr = 0;
+ psSharedTransferCmd->s3DSyncReadOpsCompleteDevVAddr.uiAddr = 0;
+
+ pvr_trcmd_clear_syn(&ttrace->_3d_syn);
+ }
+
+ psSharedTransferCmd->ui32NumSrcSyncs = psKick->ui32NumSrcSync;
+ psSharedTransferCmd->ui32NumDstSyncs = psKick->ui32NumDstSync;
+ if ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) == 0UL)
+ {
+ for (loop=0; loop<psKick->ui32NumSrcSync; loop++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[loop];
+
+ psSharedTransferCmd->asSrcSyncs[loop].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ psSharedTransferCmd->asSrcSyncs[loop].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+ psSharedTransferCmd->asSrcSyncs[loop].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+ psSharedTransferCmd->asSrcSyncs[loop].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+
+ }
+ for (loop=0; loop<psKick->ui32NumDstSync; loop++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[loop];
+
+ psSharedTransferCmd->asDstSyncs[loop].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ psSharedTransferCmd->asDstSyncs[loop].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+ psSharedTransferCmd->asDstSyncs[loop].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+ psSharedTransferCmd->asDstSyncs[loop].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+
+ }
+
+
+ for (loop = 0; loop < SGX_MAX_TRANSFER_SYNC_OPS; loop++)
+ {
+ if (loop >= psKick->ui32NumSrcSync) {
+ pvr_trcmd_clear_syn(&ttrace->src_syn[loop]);
+ continue;
+ }
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[loop];
+ psSyncInfo->psSyncData->ui32ReadOpsPending++;
+
+ pvr_trcmd_set_syn(&ttrace->src_syn[loop], psSyncInfo);
+ }
+ for (loop = 0; loop < SGX_MAX_TRANSFER_SYNC_OPS; loop++)
+ {
+ if (loop >= psKick->ui32NumDstSync) {
+ pvr_trcmd_clear_syn(&ttrace->dst_syn[loop]);
+ continue;
+ }
+
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[loop];
+ psSyncInfo->psSyncData->ui32WriteOpsPending++;
+
+ pvr_trcmd_set_syn(&ttrace->dst_syn[loop], psSyncInfo);
+ }
+ }
+
+#if defined(PDUMP)
+ if ((PDumpIsCaptureFrameKM()
+ || ((psKick->ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0))
+ && (bPersistentProcess == IMG_FALSE) )
+ {
+ PDUMPCOMMENT("Shared part of transfer command\r\n");
+ PDUMPMEM(psSharedTransferCmd,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff,
+ sizeof(SGXMKIF_TRANSFERCMD_SHARED),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ if ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) == 0UL)
+ {
+ for (loop=0; loop<psKick->ui32NumSrcSync ; loop++)
+ {
+ psSyncInfo = psKick->ahSrcSyncInfo[loop];
+
+ PDUMPCOMMENT("Hack src surface write op in transfer cmd\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff + offsetof(SGXMKIF_TRANSFERCMD_SHARED, asSrcSyncs) + loop * sizeof(PVRSRV_DEVICE_SYNC_OBJECT) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal),
+ sizeof(psSyncInfo->psSyncData->ui32LastOpDumpVal),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ PDUMPCOMMENT("Hack src surface read op in transfer cmd\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff + offsetof(SGXMKIF_TRANSFERCMD_SHARED, asSrcSyncs) + loop * sizeof(PVRSRV_DEVICE_SYNC_OBJECT) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal),
+ sizeof(psSyncInfo->psSyncData->ui32LastReadOpDumpVal),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ }
+ }
+ if ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) == 0UL)
+ {
+ for (loop=0; loop< psKick->ui32NumDstSync; loop++)
+ {
+ psSyncInfo = psKick->ahDstSyncInfo[loop];
+
+ PDUMPCOMMENT("Hack dest surface write op in transfer cmd\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff + offsetof(SGXMKIF_TRANSFERCMD_SHARED, asDstSyncs) + loop * sizeof(PVRSRV_DEVICE_SYNC_OBJECT) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal) ,
+ sizeof(psSyncInfo->psSyncData->ui32LastOpDumpVal),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ PDUMPCOMMENT("Hack dest surface read op in transfer cmd\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff + offsetof(SGXMKIF_TRANSFERCMD_SHARED, asDstSyncs) + loop * sizeof(PVRSRV_DEVICE_SYNC_OBJECT) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal),
+ sizeof(psSyncInfo->psSyncData->ui32LastReadOpDumpVal),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ }
+ }
+
+
+ if((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING)== 0UL)
+ {
+ for (loop=0; loop<(psKick->ui32NumSrcSync); loop++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[loop];
+ psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
+ }
+ }
+
+ if((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) == 0UL)
+ {
+ for (loop=0; loop<(psKick->ui32NumDstSync); loop++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[0];
+ psSyncInfo->psSyncData->ui32LastOpDumpVal++;
+ }
+ }
+ }
+#endif
+
+ sCommand.ui32Data[1] = psKick->sHWTransferContextDevVAddr.uiAddr;
+
+ pvr_trcmd_set_data(&ttrace->ctx,
+ psKick->sHWTransferContextDevVAddr.uiAddr);
+ pvr_trcmd_commit(ttrace);
+
+
+ eError = SGXScheduleCCBCommandKM(hDevHandle, SGXMKIF_CMD_TRANSFER, &sCommand, KERNEL_ID, psKick->ui32PDumpFlags);
+
+ if (eError == PVRSRV_ERROR_RETRY)
+ {
+
+ if ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) == 0UL)
+ {
+ if (psKick->ui32NumSrcSync > 0)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[0];
+ psSyncInfo->psSyncData->ui32ReadOpsPending--;
+ }
+ if (psKick->ui32NumDstSync > 0)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[0];
+ psSyncInfo->psSyncData->ui32WriteOpsPending--;
+ }
+#if defined(PDUMP)
+ if (PDumpIsCaptureFrameKM()
+ || ((psKick->ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0))
+ {
+ if (psKick->ui32NumSrcSync > 0)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[0];
+ psSyncInfo->psSyncData->ui32LastReadOpDumpVal--;
+ }
+ if (psKick->ui32NumDstSync > 0)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[0];
+ psSyncInfo->psSyncData->ui32LastOpDumpVal--;
+ }
+ }
+#endif
+ }
+
+
+ if (psKick->hTASyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
+ psSyncInfo->psSyncData->ui32WriteOpsPending--;
+ }
+
+
+ if (psKick->h3DSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
+ psSyncInfo->psSyncData->ui32WriteOpsPending--;
+ }
+ }
+
+ else if (PVRSRV_OK != eError)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXSubmitTransferKM: SGXScheduleCCBCommandKM failed."));
+ return eError;
+ }
+
+
+#if defined(NO_HARDWARE)
+ if ((psKick->ui32Flags & SGXMKIF_TQFLAGS_NOSYNCUPDATE) == 0)
+ {
+ IMG_UINT32 i;
+
+
+ for(i = 0; i < psKick->ui32NumSrcSync; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[i];
+ psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending;
+ }
+
+ for(i = 0; i < psKick->ui32NumDstSync; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[i];
+ psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+
+ }
+
+ if (psKick->hTASyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
+
+ psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+
+ if (psKick->h3DSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
+
+ psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+ }
+#endif
+
+ return eError;
+}
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+IMG_EXPORT PVRSRV_ERROR SGXSubmit2DKM(IMG_HANDLE hDevHandle, PVRSRV_2D_SGX_KICK *psKick)
+
+{
+ PVRSRV_KERNEL_MEM_INFO *psCCBMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psKick->hCCBMemInfo;
+ SGXMKIF_COMMAND sCommand = {0};
+ SGXMKIF_2DCMD_SHARED *ps2DCmd;
+ PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+ PVRSRV_ERROR eError;
+ IMG_UINT32 i;
+#if defined(PDUMP)
+ IMG_BOOL bPersistentProcess = IMG_FALSE;
+
+ {
+ PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData();
+ if(psPerProc != IMG_NULL)
+ {
+ bPersistentProcess = psPerProc->bPDumpPersistent;
+ }
+ }
+#endif
+
+ if (!CCB_OFFSET_IS_VALID(SGXMKIF_2DCMD_SHARED, psCCBMemInfo, psKick, ui32SharedCmdCCBOffset))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXSubmit2DKM: Invalid CCB offset"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+
+ ps2DCmd = CCB_DATA_FROM_OFFSET(SGXMKIF_2DCMD_SHARED, psCCBMemInfo, psKick, ui32SharedCmdCCBOffset);
+
+ OSMemSet(ps2DCmd, 0, sizeof(*ps2DCmd));
+
+
+ if (psKick->hTASyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
+
+ ps2DCmd->sTASyncData.ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++;
+ ps2DCmd->sTASyncData.ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+ ps2DCmd->sTASyncData.sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+ ps2DCmd->sTASyncData.sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+ }
+
+
+ if (psKick->h3DSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
+
+ ps2DCmd->s3DSyncData.ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++;
+ ps2DCmd->s3DSyncData.ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+ ps2DCmd->s3DSyncData.sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+ ps2DCmd->s3DSyncData.sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+ }
+
+
+ ps2DCmd->ui32NumSrcSync = psKick->ui32NumSrcSync;
+ for (i = 0; i < psKick->ui32NumSrcSync; i++)
+ {
+ psSyncInfo = psKick->ahSrcSyncInfo[i];
+
+ ps2DCmd->sSrcSyncData[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ ps2DCmd->sSrcSyncData[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+ ps2DCmd->sSrcSyncData[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+ ps2DCmd->sSrcSyncData[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+ }
+
+ if (psKick->hDstSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = psKick->hDstSyncInfo;
+
+ ps2DCmd->sDstSyncData.ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ ps2DCmd->sDstSyncData.ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+ ps2DCmd->sDstSyncData.sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
+ ps2DCmd->sDstSyncData.sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+ }
+
+
+ for (i = 0; i < psKick->ui32NumSrcSync; i++)
+ {
+ psSyncInfo = psKick->ahSrcSyncInfo[i];
+ psSyncInfo->psSyncData->ui32ReadOpsPending++;
+ }
+
+ if (psKick->hDstSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = psKick->hDstSyncInfo;
+ psSyncInfo->psSyncData->ui32WriteOpsPending++;
+ }
+
+#if defined(PDUMP)
+ if ((PDumpIsCaptureFrameKM()
+ || ((psKick->ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0))
+ && (bPersistentProcess == IMG_FALSE) )
+ {
+
+ PDUMPCOMMENT("Shared part of 2D command\r\n");
+ PDUMPMEM(ps2DCmd,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff,
+ sizeof(SGXMKIF_2DCMD_SHARED),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ for (i = 0; i < psKick->ui32NumSrcSync; i++)
+ {
+ psSyncInfo = psKick->ahSrcSyncInfo[i];
+
+ PDUMPCOMMENT("Hack src surface write op in 2D cmd\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff + offsetof(SGXMKIF_2DCMD_SHARED, sSrcSyncData[i].ui32WriteOpsPendingVal),
+ sizeof(psSyncInfo->psSyncData->ui32LastOpDumpVal),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ PDUMPCOMMENT("Hack src surface read op in 2D cmd\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff + offsetof(SGXMKIF_2DCMD_SHARED, sSrcSyncData[i].ui32ReadOpsPendingVal),
+ sizeof(psSyncInfo->psSyncData->ui32LastReadOpDumpVal),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+ }
+
+ if (psKick->hDstSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = psKick->hDstSyncInfo;
+
+ PDUMPCOMMENT("Hack dest surface write op in 2D cmd\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff + offsetof(SGXMKIF_2DCMD_SHARED, sDstSyncData.ui32WriteOpsPendingVal),
+ sizeof(psSyncInfo->psSyncData->ui32LastOpDumpVal),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ PDUMPCOMMENT("Hack dest surface read op in 2D cmd\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff + offsetof(SGXMKIF_2DCMD_SHARED, sDstSyncData.ui32ReadOpsPendingVal),
+ sizeof(psSyncInfo->psSyncData->ui32LastReadOpDumpVal),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+ }
+
+
+ for (i = 0; i < psKick->ui32NumSrcSync; i++)
+ {
+ psSyncInfo = psKick->ahSrcSyncInfo[i];
+ psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
+ }
+
+ if (psKick->hDstSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = psKick->hDstSyncInfo;
+ psSyncInfo->psSyncData->ui32LastOpDumpVal++;
+ }
+ }
+#endif
+
+ sCommand.ui32Data[1] = psKick->sHW2DContextDevVAddr.uiAddr;
+
+ eError = SGXScheduleCCBCommandKM(hDevHandle, SGXMKIF_CMD_2D, &sCommand, KERNEL_ID, psKick->ui32PDumpFlags);
+
+ if (eError == PVRSRV_ERROR_RETRY)
+ {
+
+
+#if defined(PDUMP)
+ if (PDumpIsCaptureFrameKM())
+ {
+ for (i = 0; i < psKick->ui32NumSrcSync; i++)
+ {
+ psSyncInfo = psKick->ahSrcSyncInfo[i];
+ psSyncInfo->psSyncData->ui32LastReadOpDumpVal--;
+ }
+
+ if (psKick->hDstSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = psKick->hDstSyncInfo;
+ psSyncInfo->psSyncData->ui32LastOpDumpVal--;
+ }
+ }
+#endif
+
+ for (i = 0; i < psKick->ui32NumSrcSync; i++)
+ {
+ psSyncInfo = psKick->ahSrcSyncInfo[i];
+ psSyncInfo->psSyncData->ui32ReadOpsPending--;
+ }
+
+ if (psKick->hDstSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = psKick->hDstSyncInfo;
+ psSyncInfo->psSyncData->ui32WriteOpsPending--;
+ }
+
+
+ if (psKick->hTASyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
+
+ psSyncInfo->psSyncData->ui32WriteOpsPending--;
+ }
+
+
+ if (psKick->h3DSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
+
+ psSyncInfo->psSyncData->ui32WriteOpsPending--;
+ }
+ }
+
+
+
+
+#if defined(NO_HARDWARE)
+
+ for(i = 0; i < psKick->ui32NumSrcSync; i++)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[i];
+ psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending;
+ }
+
+ if (psKick->hDstSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hDstSyncInfo;
+ psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+
+ if (psKick->hTASyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
+
+ psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+
+ if (psKick->h3DSyncInfo != IMG_NULL)
+ {
+ psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
+
+ psSyncInfo->psSyncData->ui32WriteOpsComplete = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+#endif
+
+ return eError;
+}
+#endif
+#endif
--- /dev/null
+/**********************************************************************
+ *
+ * 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 <stddef.h>
+
+#include "sgxdefs.h"
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "sgx_bridge_km.h"
+#include "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "sgx_mkif_km.h"
+#include "sysconfig.h"
+#include "pdump_km.h"
+#include "mmu.h"
+#include "pvr_bridge_km.h"
+#include "osfunc.h"
+#include "pvr_debug.h"
+#include "sgxutils.h"
+
+#ifdef __linux__
+#include <linux/kernel.h>
+#include <linux/string.h>
+#else
+#include <stdio.h>
+#endif
+#include "psb_powermgmt.h"
+
+
+#if defined(SYS_CUSTOM_POWERDOWN)
+PVRSRV_ERROR SysPowerDownMISR(PVRSRV_DEVICE_NODE * psDeviceNode, IMG_UINT32 ui32CallerID);
+#endif
+
+
+
+static IMG_VOID SGXPostActivePowerEvent(PVRSRV_DEVICE_NODE * psDeviceNode,
+ IMG_UINT32 ui32CallerID)
+{
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ SGXMKIF_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl;
+
+
+ psSGXHostCtl->ui32NumActivePowerEvents++;
+
+ if ((psSGXHostCtl->ui32PowerStatus & PVRSRV_USSE_EDM_POWMAN_POWEROFF_RESTART_IMMEDIATE) != 0)
+ {
+
+
+
+ if (ui32CallerID == ISR_ID)
+ {
+ psDeviceNode->bReProcessDeviceCommandComplete = IMG_TRUE;
+ }
+ else
+ {
+ SGXScheduleProcessQueuesKM(psDeviceNode);
+ }
+ }
+}
+
+
+IMG_VOID SGXTestActivePowerEvent (PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 ui32CallerID)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ SGXMKIF_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl;
+
+ if (((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER) != 0) &&
+ ((psSGXHostCtl->ui32InterruptClearFlags & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER) == 0))
+ {
+
+ psSGXHostCtl->ui32InterruptClearFlags |= PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER;
+
+
+ PDUMPSUSPEND();
+
+#if defined(SYS_CUSTOM_POWERDOWN)
+
+
+
+ eError = SysPowerDownMISR(psDeviceNode, ui32CallerID);
+#else
+ eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE_OFF,
+ ui32CallerID, IMG_FALSE);
+ if (eError == PVRSRV_OK)
+ {
+ SGXPostActivePowerEvent(psDeviceNode, ui32CallerID);
+ }
+#endif
+ if (eError == PVRSRV_ERROR_RETRY)
+ {
+
+
+ psSGXHostCtl->ui32InterruptClearFlags &= ~PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER;
+ eError = PVRSRV_OK;
+ }
+
+
+ PDUMPRESUME();
+ }
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXTestActivePowerEvent error:%u", eError));
+ }
+}
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SGXAcquireKernelCCBSlot)
+#endif
+static INLINE SGXMKIF_COMMAND * SGXAcquireKernelCCBSlot(PVRSRV_SGX_CCB_INFO *psCCB)
+{
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+ {
+ if(((*psCCB->pui32WriteOffset + 1) & 255) != *psCCB->pui32ReadOffset)
+ {
+ return &psCCB->psCommands[*psCCB->pui32WriteOffset];
+ }
+
+ OSSleepms(1);
+ } END_LOOP_UNTIL_TIMEOUT();
+
+
+ return IMG_NULL;
+}
+
+PVRSRV_ERROR SGXScheduleCCBCommand(PVRSRV_SGXDEV_INFO *psDevInfo,
+ SGXMKIF_CMD_TYPE eCmdType,
+ SGXMKIF_COMMAND *psCommandData,
+ IMG_UINT32 ui32CallerID,
+ IMG_UINT32 ui32PDumpFlags)
+{
+ PVRSRV_SGX_CCB_INFO *psKernelCCB;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ SGXMKIF_COMMAND *psSGXCommand;
+ SYS_DATA *psSysData;
+#if defined(PDUMP)
+ IMG_VOID *pvDumpCommand;
+ IMG_BOOL bPDumpIsSuspended = PDumpIsSuspended();
+ IMG_BOOL bPersistentProcess = IMG_FALSE;
+#else
+ PVR_UNREFERENCED_PARAMETER(ui32CallerID);
+ PVR_UNREFERENCED_PARAMETER(ui32PDumpFlags);
+#endif
+
+#if defined(FIX_HW_BRN_28889)
+
+
+
+
+ if ( (eCmdType != SGXMKIF_CMD_PROCESS_QUEUES) &&
+ ((psDevInfo->ui32CacheControl & SGXMKIF_CC_INVAL_DATA) != 0) &&
+ ((psDevInfo->ui32CacheControl & (SGXMKIF_CC_INVAL_BIF_PT | SGXMKIF_CC_INVAL_BIF_PD)) != 0))
+ {
+ #if defined(PDUMP)
+ PVRSRV_KERNEL_MEM_INFO *psSGXHostCtlMemInfo = psDevInfo->psKernelSGXHostCtlMemInfo;
+ #endif
+ SGXMKIF_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl;
+ SGXMKIF_COMMAND sCacheCommand = {0};
+
+ eError = SGXScheduleCCBCommand(psDevInfo,
+ SGXMKIF_CMD_PROCESS_QUEUES,
+ &sCacheCommand,
+ ui32CallerID,
+ ui32PDumpFlags);
+ if (eError != PVRSRV_OK)
+ {
+ goto Exit;
+ }
+
+
+ #if !defined(NO_HARDWARE)
+ if(PollForValueKM(&psSGXHostCtl->ui32InvalStatus,
+ PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE,
+ PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE,
+ 2 * MAX_HW_TIME_US,
+ MAX_HW_TIME_US/WAIT_TRY_COUNT,
+ IMG_FALSE) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXScheduleCCBCommand: Wait for uKernel to Invalidate BIF cache failed"));
+ PVR_DBG_BREAK;
+ }
+ #endif
+
+ #if defined(PDUMP)
+
+ PDUMPCOMMENTWITHFLAGS(0, "Host Control - Poll for BIF cache invalidate request to complete");
+ PDUMPMEMPOL(psSGXHostCtlMemInfo,
+ offsetof(SGXMKIF_HOST_CTL, ui32InvalStatus),
+ PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE,
+ PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ 0,
+ MAKEUNIQUETAG(psSGXHostCtlMemInfo));
+ #endif
+
+ psSGXHostCtl->ui32InvalStatus &= ~(PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE);
+ PDUMPMEM(IMG_NULL, psSGXHostCtlMemInfo, offsetof(SGXMKIF_HOST_CTL, ui32CleanupStatus), sizeof(IMG_UINT32), 0, MAKEUNIQUETAG(psSGXHostCtlMemInfo));
+ }
+#endif
+
+#if defined(PDUMP)
+
+ {
+ PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData();
+ if(psPerProc != IMG_NULL)
+ {
+ bPersistentProcess = psPerProc->bPDumpPersistent;
+ }
+ }
+#endif
+ psKernelCCB = psDevInfo->psKernelCCBInfo;
+
+ psSGXCommand = SGXAcquireKernelCCBSlot(psKernelCCB);
+
+
+ if(!psSGXCommand)
+ {
+ eError = PVRSRV_ERROR_TIMEOUT;
+ goto Exit;
+ }
+
+
+ psCommandData->ui32CacheControl = psDevInfo->ui32CacheControl;
+
+#if defined(PDUMP)
+
+ psDevInfo->sPDContext.ui32CacheControl |= psDevInfo->ui32CacheControl;
+#endif
+
+
+ psDevInfo->ui32CacheControl = 0;
+
+
+ *psSGXCommand = *psCommandData;
+
+ if (eCmdType >= SGXMKIF_CMD_MAX)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXScheduleCCBCommandKM: Unknown command type: %d", eCmdType)) ;
+ eError = PVRSRV_ERROR_INVALID_CCB_COMMAND;
+ goto Exit;
+ }
+
+
+ SysAcquireData(&psSysData);
+
+ if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH)
+ {
+ OSFlushCPUCacheKM();
+ }
+ else if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN)
+ {
+ OSCleanCPUCacheKM();
+ }
+
+
+ psSysData->ePendingCacheOpType = PVRSRV_MISC_INFO_CPUCACHEOP_NONE;
+
+ PVR_ASSERT(eCmdType < SGXMKIF_CMD_MAX);
+ psSGXCommand->ui32ServiceAddress = psDevInfo->aui32HostKickAddr[eCmdType];
+
+#if defined(PDUMP)
+ if ((ui32CallerID != ISR_ID) && (bPDumpIsSuspended == IMG_FALSE) &&
+ (bPersistentProcess == IMG_FALSE) )
+ {
+
+ PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Poll for space in the Kernel CCB\r\n");
+ PDUMPMEMPOL(psKernelCCB->psCCBCtlMemInfo,
+ offsetof(PVRSRV_SGX_CCB_CTL, ui32ReadOffset),
+ (psKernelCCB->ui32CCBDumpWOff + 1) & 0xff,
+ 0xff,
+ PDUMP_POLL_OPERATOR_NOTEQUAL,
+ ui32PDumpFlags,
+ MAKEUNIQUETAG(psKernelCCB->psCCBCtlMemInfo));
+
+ PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Kernel CCB command (type == %d)\r\n", eCmdType);
+ pvDumpCommand = (IMG_VOID *)((IMG_UINT8 *)psKernelCCB->psCCBMemInfo->pvLinAddrKM + (*psKernelCCB->pui32WriteOffset * sizeof(SGXMKIF_COMMAND)));
+
+ PDUMPMEM(pvDumpCommand,
+ psKernelCCB->psCCBMemInfo,
+ psKernelCCB->ui32CCBDumpWOff * sizeof(SGXMKIF_COMMAND),
+ sizeof(SGXMKIF_COMMAND),
+ ui32PDumpFlags,
+ MAKEUNIQUETAG(psKernelCCB->psCCBMemInfo));
+
+
+ PDUMPMEM(&psDevInfo->sPDContext.ui32CacheControl,
+ psKernelCCB->psCCBMemInfo,
+ psKernelCCB->ui32CCBDumpWOff * sizeof(SGXMKIF_COMMAND) +
+ offsetof(SGXMKIF_COMMAND, ui32CacheControl),
+ sizeof(IMG_UINT32),
+ ui32PDumpFlags,
+ MAKEUNIQUETAG(psKernelCCB->psCCBMemInfo));
+
+ if (PDumpIsCaptureFrameKM()
+ || ((ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0))
+ {
+
+ psDevInfo->sPDContext.ui32CacheControl = 0;
+ }
+ }
+#endif
+
+#if defined(FIX_HW_BRN_26620) && defined(SGX_FEATURE_SYSTEM_CACHE) && !defined(SGX_BYPASS_SYSTEM_CACHE)
+
+ eError = PollForValueKM (psKernelCCB->pui32ReadOffset,
+ *psKernelCCB->pui32WriteOffset,
+ 0xFF,
+ MAX_HW_TIME_US,
+ MAX_HW_TIME_US/WAIT_TRY_COUNT,
+ IMG_FALSE);
+ if (eError != PVRSRV_OK)
+ {
+ eError = PVRSRV_ERROR_TIMEOUT;
+ goto Exit;
+ }
+#endif
+
+
+
+ *psKernelCCB->pui32WriteOffset = (*psKernelCCB->pui32WriteOffset + 1) & 255;
+
+#if defined(PDUMP)
+ if ((ui32CallerID != ISR_ID) && (bPDumpIsSuspended == IMG_FALSE) &&
+ (bPersistentProcess == IMG_FALSE) )
+ {
+ #if defined(FIX_HW_BRN_26620) && defined(SGX_FEATURE_SYSTEM_CACHE) && !defined(SGX_BYPASS_SYSTEM_CACHE)
+ PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Poll for previous Kernel CCB CMD to be read\r\n");
+ PDUMPMEMPOL(psKernelCCB->psCCBCtlMemInfo,
+ offsetof(PVRSRV_SGX_CCB_CTL, ui32ReadOffset),
+ (psKernelCCB->ui32CCBDumpWOff),
+ 0xFF,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ ui32PDumpFlags,
+ MAKEUNIQUETAG(psKernelCCB->psCCBCtlMemInfo));
+ #endif
+
+ if (PDumpIsCaptureFrameKM()
+ || ((ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0))
+ {
+ psKernelCCB->ui32CCBDumpWOff = (psKernelCCB->ui32CCBDumpWOff + 1) & 0xFF;
+ psDevInfo->ui32KernelCCBEventKickerDumpVal = (psDevInfo->ui32KernelCCBEventKickerDumpVal + 1) & 0xFF;
+ }
+
+ PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Kernel CCB write offset\r\n");
+ PDUMPMEM(&psKernelCCB->ui32CCBDumpWOff,
+ psKernelCCB->psCCBCtlMemInfo,
+ offsetof(PVRSRV_SGX_CCB_CTL, ui32WriteOffset),
+ sizeof(IMG_UINT32),
+ ui32PDumpFlags,
+ MAKEUNIQUETAG(psKernelCCB->psCCBCtlMemInfo));
+ PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Kernel CCB event kicker\r\n");
+ PDUMPMEM(&psDevInfo->ui32KernelCCBEventKickerDumpVal,
+ psDevInfo->psKernelCCBEventKickerMemInfo,
+ 0,
+ sizeof(IMG_UINT32),
+ ui32PDumpFlags,
+ MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
+ PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Kick the SGX microkernel\r\n");
+ #if defined(FIX_HW_BRN_26620) && defined(SGX_FEATURE_SYSTEM_CACHE) && !defined(SGX_BYPASS_SYSTEM_CACHE)
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK2, 0), EUR_CR_EVENT_KICK2_NOW_MASK, ui32PDumpFlags);
+ #else
+ PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK, 0), EUR_CR_EVENT_KICK_NOW_MASK, ui32PDumpFlags);
+ #endif
+ }
+#endif
+
+ *psDevInfo->pui32KernelCCBEventKicker = (*psDevInfo->pui32KernelCCBEventKicker + 1) & 0xFF;
+
+ OSWriteMemoryBarrier();
+
+#if defined(FIX_HW_BRN_26620) && defined(SGX_FEATURE_SYSTEM_CACHE) && !defined(SGX_BYPASS_SYSTEM_CACHE)
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM,
+ SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK2, 0),
+ EUR_CR_EVENT_KICK2_NOW_MASK);
+#else
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM,
+ SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK, 0),
+ EUR_CR_EVENT_KICK_NOW_MASK);
+#endif
+
+ OSMemoryBarrier();
+
+#if defined(NO_HARDWARE)
+
+ *psKernelCCB->pui32ReadOffset = (*psKernelCCB->pui32ReadOffset + 1) & 255;
+#endif
+
+Exit:
+ return eError;
+}
+
+
+PVRSRV_ERROR SGXScheduleCCBCommandKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+ SGXMKIF_CMD_TYPE eCmdType,
+ SGXMKIF_COMMAND *psCommandData,
+ IMG_UINT32 ui32CallerID,
+ IMG_UINT32 ui32PDumpFlags)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+
+
+ PDUMPSUSPEND();
+
+ eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE_ON,
+ ui32CallerID,
+ IMG_TRUE);
+
+ PDUMPRESUME();
+
+ if (eError == PVRSRV_OK)
+ {
+ psDeviceNode->bReProcessDeviceCommandComplete = IMG_FALSE;
+ }
+ else
+ {
+ if (eError == PVRSRV_ERROR_RETRY)
+ {
+ if (ui32CallerID == ISR_ID)
+ {
+
+
+
+ psDeviceNode->bReProcessDeviceCommandComplete = IMG_TRUE;
+ eError = PVRSRV_OK;
+ }
+ else
+ {
+
+
+ }
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXScheduleCCBCommandKM failed to acquire lock - "
+ "ui32CallerID:%d eError:%u", ui32CallerID, eError));
+ }
+
+ return eError;
+ }
+
+ eError = SGXScheduleCCBCommand(psDevInfo, eCmdType, psCommandData, ui32CallerID, ui32PDumpFlags);
+
+ PVRSRVPowerUnlock(ui32CallerID);
+
+ if (ui32CallerID != ISR_ID)
+ {
+
+
+
+ SGXTestActivePowerEvent(psDeviceNode, ui32CallerID);
+ }
+
+ return eError;
+}
+
+
+PVRSRV_ERROR SGXScheduleProcessQueuesKM(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ SGXMKIF_HOST_CTL *psHostCtl = psDevInfo->psKernelSGXHostCtlMemInfo->pvLinAddrKM;
+ IMG_UINT32 ui32PowerStatus;
+ SGXMKIF_COMMAND sCommand = {0};
+
+ ui32PowerStatus = psHostCtl->ui32PowerStatus;
+ if ((ui32PowerStatus & PVRSRV_USSE_EDM_POWMAN_NO_WORK) != 0)
+ {
+
+ return PVRSRV_OK;
+ }
+
+ eError = SGXScheduleCCBCommandKM(psDeviceNode, SGXMKIF_CMD_PROCESS_QUEUES, &sCommand, ISR_ID, 0);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXScheduleProcessQueuesKM failed to schedule CCB command: %u", eError));
+ return eError;
+ }
+
+ return PVRSRV_OK;
+}
+
+
+IMG_BOOL SGXIsDevicePowered(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ return PVRSRVIsDevicePowered(psDeviceNode->sDevId.ui32DeviceIndex);
+}
+
+IMG_EXPORT
+PVRSRV_ERROR SGXGetInternalDevInfoKM(IMG_HANDLE hDevCookie,
+ SGX_INTERNAL_DEVINFO *psSGXInternalDevInfo)
+{
+ PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
+
+ psSGXInternalDevInfo->ui32Flags = psDevInfo->ui32Flags;
+ psSGXInternalDevInfo->bForcePTOff = (IMG_BOOL)psDevInfo->bForcePTOff;
+
+
+ psSGXInternalDevInfo->hHostCtlKernelMemInfoHandle =
+ (IMG_HANDLE)psDevInfo->psKernelSGXHostCtlMemInfo;
+
+ return PVRSRV_OK;
+}
+
+
+IMG_VOID SGXCleanupRequest(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_DEV_VIRTADDR *psHWDataDevVAddr,
+ IMG_UINT32 ui32CleanupType)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_SGXDEV_INFO *psSGXDevInfo = psDeviceNode->pvDevice;
+ PVRSRV_KERNEL_MEM_INFO *psSGXHostCtlMemInfo = psSGXDevInfo->psKernelSGXHostCtlMemInfo;
+ SGXMKIF_HOST_CTL *psSGXHostCtl = psSGXHostCtlMemInfo->pvLinAddrKM;
+
+ if ((psSGXHostCtl->ui32PowerStatus & PVRSRV_USSE_EDM_POWMAN_NO_WORK) != 0)
+ {
+
+ }
+ else
+ {
+ SGXMKIF_COMMAND sCommand = {0};
+
+ PDUMPCOMMENTWITHFLAGS(0, "Request ukernel resouce clean-up");
+ sCommand.ui32Data[0] = ui32CleanupType;
+ sCommand.ui32Data[1] = (psHWDataDevVAddr == IMG_NULL) ? 0 : psHWDataDevVAddr->uiAddr;
+
+ eError = SGXScheduleCCBCommandKM(psDeviceNode, SGXMKIF_CMD_CLEANUP, &sCommand, KERNEL_ID, 0);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXCleanupRequest: Failed to submit clean-up command"));
+ PVR_DBG_BREAK;
+ }
+
+
+ #if !defined(NO_HARDWARE)
+ if(PollForValueKM(&psSGXHostCtl->ui32CleanupStatus,
+ PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE,
+ PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE,
+ 10 * MAX_HW_TIME_US,
+ 1000,
+ IMG_TRUE) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXCleanupRequest: Wait for uKernel to clean up (%u) failed", ui32CleanupType));
+ PVR_DBG_BREAK;
+ }
+ #endif
+
+ #if defined(PDUMP)
+
+ PDUMPCOMMENTWITHFLAGS(0, "Host Control - Poll for clean-up request to complete");
+ PDUMPMEMPOL(psSGXHostCtlMemInfo,
+ offsetof(SGXMKIF_HOST_CTL, ui32CleanupStatus),
+ PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE,
+ PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ 0,
+ MAKEUNIQUETAG(psSGXHostCtlMemInfo));
+ #endif
+
+ psSGXHostCtl->ui32CleanupStatus &= ~(PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE);
+ PDUMPMEM(IMG_NULL, psSGXHostCtlMemInfo, offsetof(SGXMKIF_HOST_CTL, ui32CleanupStatus), sizeof(IMG_UINT32), 0, MAKEUNIQUETAG(psSGXHostCtlMemInfo));
+
+
+ #if defined(SGX_FEATURE_SYSTEM_CACHE)
+ psSGXDevInfo->ui32CacheControl |= (SGXMKIF_CC_INVAL_BIF_SL | SGXMKIF_CC_INVAL_DATA);
+ #else
+ psSGXDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_DATA;
+ #endif
+ }
+}
+
+
+typedef struct _SGX_HW_RENDER_CONTEXT_CLEANUP_
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ IMG_DEV_VIRTADDR sHWRenderContextDevVAddr;
+ IMG_HANDLE hBlockAlloc;
+ PRESMAN_ITEM psResItem;
+} SGX_HW_RENDER_CONTEXT_CLEANUP;
+
+
+static PVRSRV_ERROR SGXCleanupHWRenderContextCallback(IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param)
+{
+ SGX_HW_RENDER_CONTEXT_CLEANUP *psCleanup = pvParam;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ SGXCleanupRequest(psCleanup->psDeviceNode,
+ &psCleanup->sHWRenderContextDevVAddr,
+ PVRSRV_CLEANUPCMD_RC);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(SGX_HW_RENDER_CONTEXT_CLEANUP),
+ psCleanup,
+ psCleanup->hBlockAlloc);
+
+
+ return PVRSRV_OK;
+}
+
+typedef struct _SGX_HW_TRANSFER_CONTEXT_CLEANUP_
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ IMG_DEV_VIRTADDR sHWTransferContextDevVAddr;
+ IMG_HANDLE hBlockAlloc;
+ PRESMAN_ITEM psResItem;
+} SGX_HW_TRANSFER_CONTEXT_CLEANUP;
+
+
+static PVRSRV_ERROR SGXCleanupHWTransferContextCallback(IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param)
+{
+ SGX_HW_TRANSFER_CONTEXT_CLEANUP *psCleanup = (SGX_HW_TRANSFER_CONTEXT_CLEANUP *)pvParam;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ SGXCleanupRequest(psCleanup->psDeviceNode,
+ &psCleanup->sHWTransferContextDevVAddr,
+ PVRSRV_CLEANUPCMD_TC);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(SGX_HW_TRANSFER_CONTEXT_CLEANUP),
+ psCleanup,
+ psCleanup->hBlockAlloc);
+
+
+ return PVRSRV_OK;
+}
+
+IMG_EXPORT
+IMG_HANDLE SGXRegisterHWRenderContextKM(IMG_HANDLE psDeviceNode,
+ IMG_DEV_VIRTADDR *psHWRenderContextDevVAddr,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hBlockAlloc;
+ SGX_HW_RENDER_CONTEXT_CLEANUP *psCleanup;
+ PRESMAN_ITEM psResItem;
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(SGX_HW_RENDER_CONTEXT_CLEANUP),
+ (IMG_VOID **)&psCleanup,
+ &hBlockAlloc,
+ "SGX Hardware Render Context Cleanup");
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWRenderContextKM: Couldn't allocate memory for SGX_HW_RENDER_CONTEXT_CLEANUP structure"));
+ return IMG_NULL;
+ }
+
+ psCleanup->hBlockAlloc = hBlockAlloc;
+ psCleanup->psDeviceNode = psDeviceNode;
+ psCleanup->sHWRenderContextDevVAddr = *psHWRenderContextDevVAddr;
+
+ psResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_HW_RENDER_CONTEXT,
+ (IMG_VOID *)psCleanup,
+ 0,
+ &SGXCleanupHWRenderContextCallback);
+
+ if (psResItem == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWRenderContextKM: ResManRegisterRes failed"));
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(SGX_HW_RENDER_CONTEXT_CLEANUP),
+ psCleanup,
+ psCleanup->hBlockAlloc);
+
+
+ return IMG_NULL;
+ }
+
+ psCleanup->psResItem = psResItem;
+
+ return (IMG_HANDLE)psCleanup;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR SGXUnregisterHWRenderContextKM(IMG_HANDLE hHWRenderContext)
+{
+ PVRSRV_ERROR eError;
+ SGX_HW_RENDER_CONTEXT_CLEANUP *psCleanup;
+
+ PVR_ASSERT(hHWRenderContext != IMG_NULL);
+
+ psCleanup = (SGX_HW_RENDER_CONTEXT_CLEANUP *)hHWRenderContext;
+
+ if (psCleanup == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXUnregisterHWRenderContextKM: invalid parameter"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ eError = ResManFreeResByPtr(psCleanup->psResItem);
+
+ return eError;
+}
+
+
+IMG_EXPORT
+IMG_HANDLE SGXRegisterHWTransferContextKM(IMG_HANDLE psDeviceNode,
+ IMG_DEV_VIRTADDR *psHWTransferContextDevVAddr,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hBlockAlloc;
+ SGX_HW_TRANSFER_CONTEXT_CLEANUP *psCleanup;
+ PRESMAN_ITEM psResItem;
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(SGX_HW_TRANSFER_CONTEXT_CLEANUP),
+ (IMG_VOID **)&psCleanup,
+ &hBlockAlloc,
+ "SGX Hardware Transfer Context Cleanup");
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWTransferContextKM: Couldn't allocate memory for SGX_HW_TRANSFER_CONTEXT_CLEANUP structure"));
+ return IMG_NULL;
+ }
+
+ psCleanup->hBlockAlloc = hBlockAlloc;
+ psCleanup->psDeviceNode = psDeviceNode;
+ psCleanup->sHWTransferContextDevVAddr = *psHWTransferContextDevVAddr;
+
+ psResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_HW_TRANSFER_CONTEXT,
+ psCleanup,
+ 0,
+ &SGXCleanupHWTransferContextCallback);
+
+ if (psResItem == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHWTransferContextKM: ResManRegisterRes failed"));
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(SGX_HW_TRANSFER_CONTEXT_CLEANUP),
+ psCleanup,
+ psCleanup->hBlockAlloc);
+
+
+ return IMG_NULL;
+ }
+
+ psCleanup->psResItem = psResItem;
+
+ return (IMG_HANDLE)psCleanup;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR SGXUnregisterHWTransferContextKM(IMG_HANDLE hHWTransferContext)
+{
+ PVRSRV_ERROR eError;
+ SGX_HW_TRANSFER_CONTEXT_CLEANUP *psCleanup;
+
+ PVR_ASSERT(hHWTransferContext != IMG_NULL);
+
+ psCleanup = (SGX_HW_TRANSFER_CONTEXT_CLEANUP *)hHWTransferContext;
+
+ if (psCleanup == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXUnregisterHWTransferContextKM: invalid parameter"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ eError = ResManFreeResByPtr(psCleanup->psResItem);
+
+ return eError;
+}
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+typedef struct _SGX_HW_2D_CONTEXT_CLEANUP_
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ IMG_DEV_VIRTADDR sHW2DContextDevVAddr;
+ IMG_HANDLE hBlockAlloc;
+ PRESMAN_ITEM psResItem;
+} SGX_HW_2D_CONTEXT_CLEANUP;
+
+static PVRSRV_ERROR SGXCleanupHW2DContextCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param)
+{
+ SGX_HW_2D_CONTEXT_CLEANUP *psCleanup = (SGX_HW_2D_CONTEXT_CLEANUP *)pvParam;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ SGXCleanupRequest(psCleanup->psDeviceNode,
+ &psCleanup->sHW2DContextDevVAddr,
+ PVRSRV_CLEANUPCMD_2DC);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(SGX_HW_2D_CONTEXT_CLEANUP),
+ psCleanup,
+ psCleanup->hBlockAlloc);
+
+
+ return PVRSRV_OK;
+}
+
+IMG_EXPORT
+IMG_HANDLE SGXRegisterHW2DContextKM(IMG_HANDLE psDeviceNode,
+ IMG_DEV_VIRTADDR *psHW2DContextDevVAddr,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hBlockAlloc;
+ SGX_HW_2D_CONTEXT_CLEANUP *psCleanup;
+ PRESMAN_ITEM psResItem;
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(SGX_HW_2D_CONTEXT_CLEANUP),
+ (IMG_VOID **)&psCleanup,
+ &hBlockAlloc,
+ "SGX Hardware 2D Context Cleanup");
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHW2DContextKM: Couldn't allocate memory for SGX_HW_2D_CONTEXT_CLEANUP structure"));
+ return IMG_NULL;
+ }
+
+ psCleanup->hBlockAlloc = hBlockAlloc;
+ psCleanup->psDeviceNode = psDeviceNode;
+ psCleanup->sHW2DContextDevVAddr = *psHW2DContextDevVAddr;
+
+ psResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_HW_2D_CONTEXT,
+ psCleanup,
+ 0,
+ &SGXCleanupHW2DContextCallback);
+
+ if (psResItem == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SGXRegisterHW2DContextKM: ResManRegisterRes failed"));
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(SGX_HW_2D_CONTEXT_CLEANUP),
+ psCleanup,
+ psCleanup->hBlockAlloc);
+
+
+ return IMG_NULL;
+ }
+
+ psCleanup->psResItem = psResItem;
+
+ return (IMG_HANDLE)psCleanup;
+}
+
+IMG_EXPORT
+PVRSRV_ERROR SGXUnregisterHW2DContextKM(IMG_HANDLE hHW2DContext)
+{
+ PVRSRV_ERROR eError;
+ SGX_HW_2D_CONTEXT_CLEANUP *psCleanup;
+
+ PVR_ASSERT(hHW2DContext != IMG_NULL);
+
+ if (hHW2DContext == IMG_NULL)
+ {
+ return (PVRSRV_ERROR_INVALID_PARAMS);
+ }
+
+ psCleanup = (SGX_HW_2D_CONTEXT_CLEANUP *)hHW2DContext;
+
+ eError = ResManFreeResByPtr(psCleanup->psResItem);
+
+ return eError;
+}
+#endif
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SGX2DQuerySyncOpsComplete)
+#endif
+static INLINE
+IMG_BOOL SGX2DQuerySyncOpsComplete(PVRSRV_KERNEL_SYNC_INFO *psSyncInfo,
+ IMG_UINT32 ui32ReadOpsPending,
+ IMG_UINT32 ui32WriteOpsPending)
+{
+ PVRSRV_SYNC_DATA *psSyncData = psSyncInfo->psSyncData;
+
+ return (IMG_BOOL)(
+ (psSyncData->ui32ReadOpsComplete >= ui32ReadOpsPending) &&
+ (psSyncData->ui32WriteOpsComplete >= ui32WriteOpsPending)
+ );
+}
+
+IMG_EXPORT
+PVRSRV_ERROR SGX2DQueryBlitsCompleteKM(PVRSRV_SGXDEV_INFO *psDevInfo,
+ PVRSRV_KERNEL_SYNC_INFO *psSyncInfo,
+ IMG_BOOL bWaitForComplete)
+{
+ IMG_UINT32 ui32ReadOpsPending, ui32WriteOpsPending;
+
+ PVR_UNREFERENCED_PARAMETER(psDevInfo);
+
+ PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DQueryBlitsCompleteKM: Start"));
+
+ ui32ReadOpsPending = psSyncInfo->psSyncData->ui32ReadOpsPending;
+ ui32WriteOpsPending = psSyncInfo->psSyncData->ui32WriteOpsPending;
+
+ if(SGX2DQuerySyncOpsComplete(psSyncInfo, ui32ReadOpsPending, ui32WriteOpsPending))
+ {
+
+ PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DQueryBlitsCompleteKM: No wait. Blits complete."));
+ return PVRSRV_OK;
+ }
+
+
+ if (!bWaitForComplete)
+ {
+
+ PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DQueryBlitsCompleteKM: No wait. Ops pending."));
+ return PVRSRV_ERROR_CMD_NOT_PROCESSED;
+ }
+
+
+ PVR_DPF((PVR_DBG_MESSAGE, "SGX2DQueryBlitsCompleteKM: Ops pending. Start polling."));
+
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+ {
+ OSSleepms(1);
+
+ if(SGX2DQuerySyncOpsComplete(psSyncInfo, ui32ReadOpsPending, ui32WriteOpsPending))
+ {
+
+ PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DQueryBlitsCompleteKM: Wait over. Blits complete."));
+ return PVRSRV_OK;
+ }
+
+ OSSleepms(1);
+ } END_LOOP_UNTIL_TIMEOUT();
+
+
+ PVR_DPF((PVR_DBG_ERROR,"SGX2DQueryBlitsCompleteKM: Timed out. Ops pending."));
+
+#if defined(DEBUG)
+ {
+ PVRSRV_SYNC_DATA *psSyncData = psSyncInfo->psSyncData;
+
+ PVR_TRACE(("SGX2DQueryBlitsCompleteKM: Syncinfo: 0x%x, Syncdata: 0x%x",
+ (IMG_UINTPTR_T)psSyncInfo, (IMG_UINTPTR_T)psSyncData));
+
+ PVR_TRACE(("SGX2DQueryBlitsCompleteKM: Read ops complete: %d, Read ops pending: %d", psSyncData->ui32ReadOpsComplete, psSyncData->ui32ReadOpsPending));
+ PVR_TRACE(("SGX2DQueryBlitsCompleteKM: Write ops complete: %d, Write ops pending: %d", psSyncData->ui32WriteOpsComplete, psSyncData->ui32WriteOpsPending));
+
+ }
+#endif
+
+ return PVRSRV_ERROR_TIMEOUT;
+}
+
+
+IMG_EXPORT
+IMG_VOID SGXFlushHWRenderTargetKM(IMG_HANDLE psDeviceNode, IMG_DEV_VIRTADDR sHWRTDataSetDevVAddr)
+{
+ PVR_ASSERT(sHWRTDataSetDevVAddr.uiAddr != IMG_NULL);
+
+ SGXCleanupRequest(psDeviceNode,
+ &sHWRTDataSetDevVAddr,
+ PVRSRV_CLEANUPCMD_RT);
+}
+
+
+IMG_UINT32 SGXConvertTimeStamp(PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32TimeWraps,
+ IMG_UINT32 ui32Time)
+{
+#if defined(EUR_CR_TIMER)
+ PVR_UNREFERENCED_PARAMETER(psDevInfo);
+ PVR_UNREFERENCED_PARAMETER(ui32TimeWraps);
+ return ui32Time;
+#else
+ IMG_UINT64 ui64Clocks;
+ IMG_UINT32 ui32Clocksx16;
+
+ ui64Clocks = ((IMG_UINT64)ui32TimeWraps * psDevInfo->ui32uKernelTimerClock) +
+ (psDevInfo->ui32uKernelTimerClock - (ui32Time & EUR_CR_EVENT_TIMER_VALUE_MASK));
+ ui32Clocksx16 = (IMG_UINT32)(ui64Clocks / 16);
+
+ return ui32Clocksx16;
+#endif
+}
+
+
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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 "perproc.h"
+#include "sgxinfokm.h"
+
+#define CCB_OFFSET_IS_VALID(type, psCCBMemInfo, psCCBKick, offset) \
+ ((sizeof(type) <= (psCCBMemInfo)->ui32AllocSize) && \
+ ((psCCBKick)->offset <= (psCCBMemInfo)->ui32AllocSize - sizeof(type)))
+
+#define CCB_DATA_FROM_OFFSET(type, psCCBMemInfo, psCCBKick, offset) \
+ ((type *)(((IMG_CHAR *)(psCCBMemInfo)->pvLinAddrKM) + \
+ (psCCBKick)->offset))
+
+
+IMG_IMPORT
+IMG_VOID SGXTestActivePowerEvent(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_UINT32 ui32CallerID);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXScheduleCCBCommand(PVRSRV_SGXDEV_INFO *psDevInfo,
+ SGXMKIF_CMD_TYPE eCommandType,
+ SGXMKIF_COMMAND *psCommandData,
+ IMG_UINT32 ui32CallerID,
+ IMG_UINT32 ui32PDumpFlags);
+IMG_IMPORT
+PVRSRV_ERROR SGXScheduleCCBCommandKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+ SGXMKIF_CMD_TYPE eCommandType,
+ SGXMKIF_COMMAND *psCommandData,
+ IMG_UINT32 ui32CallerID,
+ IMG_UINT32 ui32PDumpFlags);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXScheduleProcessQueuesKM(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+IMG_IMPORT
+IMG_BOOL SGXIsDevicePowered(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+IMG_IMPORT
+IMG_HANDLE SGXRegisterHWRenderContextKM(IMG_HANDLE psDeviceNode,
+ IMG_DEV_VIRTADDR *psHWRenderContextDevVAddr,
+ PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+IMG_IMPORT
+IMG_HANDLE SGXRegisterHWTransferContextKM(IMG_HANDLE psDeviceNode,
+ IMG_DEV_VIRTADDR *psHWTransferContextDevVAddr,
+ PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+IMG_IMPORT
+IMG_VOID SGXFlushHWRenderTargetKM(IMG_HANDLE psSGXDevInfo, IMG_DEV_VIRTADDR psHWRTDataSetDevVAddr);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXUnregisterHWRenderContextKM(IMG_HANDLE hHWRenderContext);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXUnregisterHWTransferContextKM(IMG_HANDLE hHWTransferContext);
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+IMG_IMPORT
+IMG_HANDLE SGXRegisterHW2DContextKM(IMG_HANDLE psDeviceNode,
+ IMG_DEV_VIRTADDR *psHW2DContextDevVAddr,
+ PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+IMG_IMPORT
+PVRSRV_ERROR SGXUnregisterHW2DContextKM(IMG_HANDLE hHW2DContext);
+#endif
+
+IMG_UINT32 SGXConvertTimeStamp(PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32TimeWraps,
+ IMG_UINT32 ui32Time);
+
+IMG_VOID SGXCleanupRequest(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_DEV_VIRTADDR *psHWDataDevVAddr,
+ IMG_UINT32 ui32CleanupType);
+
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef _ENV_DATA_
+#define _ENV_DATA_
+
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+
+#if defined(PVR_LINUX_MISR_USING_WORKQUEUE) || defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE)
+#include <linux/workqueue.h>
+#endif
+
+#define PVRSRV_MAX_BRIDGE_IN_SIZE 0x1000
+#define PVRSRV_MAX_BRIDGE_OUT_SIZE 0x1000
+
+typedef struct _PVR_PCI_DEV_TAG
+{
+ struct pci_dev *psPCIDev;
+ HOST_PCI_INIT_FLAGS ePCIFlags;
+ IMG_BOOL abPCIResourceInUse[DEVICE_COUNT_RESOURCE];
+} PVR_PCI_DEV;
+
+typedef struct _ENV_DATA_TAG
+{
+ IMG_VOID *pvBridgeData;
+ struct pm_dev *psPowerDevice;
+ IMG_BOOL bLISRInstalled;
+ IMG_BOOL bMISRInstalled;
+ IMG_UINT32 ui32IRQ;
+ IMG_VOID *pvISRCookie;
+#if defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE)
+ struct workqueue_struct *psWorkQueue;
+#endif
+#if defined(PVR_LINUX_MISR_USING_WORKQUEUE) || defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE)
+ struct work_struct sMISRWork;
+ IMG_VOID *pvMISRData;
+#else
+ struct tasklet_struct sMISRTasklet;
+#endif
+} ENV_DATA;
+
+#endif
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef __ENV_PERPROC_H__
+#define __ENV_PERPROC_H__
+
+#include <linux/list.h>
+#include <linux/proc_fs.h>
+
+#include "services.h"
+#include "handle.h"
+
+typedef struct _PVRSRV_ENV_PER_PROCESS_DATA_
+{
+ IMG_HANDLE hBlockAlloc;
+ struct proc_dir_entry *psProcDir;
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+ struct list_head sDRMAuthListHead;
+#endif
+} PVRSRV_ENV_PER_PROCESS_DATA;
+
+IMG_VOID RemovePerProcessProcDir(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc);
+
+PVRSRV_ERROR LinuxMMapPerProcessConnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc);
+
+IMG_VOID LinuxMMapPerProcessDisconnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc);
+
+PVRSRV_ERROR LinuxMMapPerProcessHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase);
+
+IMG_HANDLE LinuxTerminatingProcessPrivateData(IMG_VOID);
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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/version.h>
+#include <asm/io.h>
+#include <asm/page.h>
+#include <asm/system.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <asm/hardirq.h>
+#include <linux/timer.h>
+#include <linux/capability.h>
+#include <linux/sched.h>
+#include <asm/uaccess.h>
+
+#include "img_types.h"
+#include "services_headers.h"
+#include "mm.h"
+#include "pvrmmap.h"
+#include "mmap.h"
+#include "env_data.h"
+#include "proc.h"
+#include "lock.h"
+
+typedef struct PVRSRV_LINUX_EVENT_OBJECT_LIST_TAG
+{
+ rwlock_t sLock;
+ struct list_head sList;
+
+} PVRSRV_LINUX_EVENT_OBJECT_LIST;
+
+
+typedef struct PVRSRV_LINUX_EVENT_OBJECT_TAG
+{
+ atomic_t sTimeStamp;
+ IMG_UINT32 ui32TimeStampPrevious;
+#if defined(DEBUG)
+ IMG_UINT ui32Stats;
+#endif
+ wait_queue_head_t sWait;
+ struct list_head sList;
+ IMG_HANDLE hResItem;
+ PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList;
+} PVRSRV_LINUX_EVENT_OBJECT;
+
+PVRSRV_ERROR LinuxEventObjectListCreate(IMG_HANDLE *phEventObjectList)
+{
+ PVRSRV_LINUX_EVENT_OBJECT_LIST *psEvenObjectList;
+
+ if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT_LIST),
+ (IMG_VOID **)&psEvenObjectList, IMG_NULL,
+ "Linux Event Object List") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectCreate: failed to allocate memory for event list"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ INIT_LIST_HEAD(&psEvenObjectList->sList);
+
+ rwlock_init(&psEvenObjectList->sLock);
+
+ *phEventObjectList = (IMG_HANDLE *) psEvenObjectList;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR LinuxEventObjectListDestroy(IMG_HANDLE hEventObjectList)
+{
+
+ PVRSRV_LINUX_EVENT_OBJECT_LIST *psEvenObjectList = (PVRSRV_LINUX_EVENT_OBJECT_LIST *) hEventObjectList ;
+
+ if(psEvenObjectList)
+ {
+ if (!list_empty(&psEvenObjectList->sList))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectListDestroy: Event List is not empty"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT_LIST), psEvenObjectList, IMG_NULL);
+
+ }
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR LinuxEventObjectDelete(IMG_HANDLE hOSEventObjectList, IMG_HANDLE hOSEventObject)
+{
+ if(hOSEventObjectList)
+ {
+ if(hOSEventObject)
+ {
+ PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject = (PVRSRV_LINUX_EVENT_OBJECT *)hOSEventObject;
+#if defined(DEBUG)
+ PVR_DPF((PVR_DBG_MESSAGE, "LinuxEventObjectListDelete: Event object waits: %lu", psLinuxEventObject->ui32Stats));
+#endif
+ if(ResManFreeResByPtr(psLinuxEventObject->hResItem) != PVRSRV_OK)
+ {
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ return PVRSRV_OK;
+ }
+ }
+ return PVRSRV_ERROR_GENERIC;
+
+}
+
+static PVRSRV_ERROR LinuxEventObjectDeleteCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param)
+{
+ PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject = pvParam;
+ PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList = psLinuxEventObject->psLinuxEventObjectList;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ write_lock_bh(&psLinuxEventObjectList->sLock);
+ list_del(&psLinuxEventObject->sList);
+ write_unlock_bh(&psLinuxEventObjectList->sLock);
+
+#if defined(DEBUG)
+ PVR_DPF((PVR_DBG_MESSAGE, "LinuxEventObjectDeleteCallback: Event object waits: %lu", psLinuxEventObject->ui32Stats));
+#endif
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT), psLinuxEventObject, IMG_NULL);
+
+
+ return PVRSRV_OK;
+}
+PVRSRV_ERROR LinuxEventObjectAdd(IMG_HANDLE hOSEventObjectList, IMG_HANDLE *phOSEventObject)
+ {
+ PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject;
+ PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList = (PVRSRV_LINUX_EVENT_OBJECT_LIST*)hOSEventObjectList;
+ IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+ PVRSRV_PER_PROCESS_DATA *psPerProc;
+
+ psPerProc = PVRSRVPerProcessData(ui32PID);
+ if (psPerProc == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectAdd: Couldn't find per-process data"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+
+ if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT),
+ (IMG_VOID **)&psLinuxEventObject, IMG_NULL,
+ "Linux Event Object") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectAdd: failed to allocate memory "));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ INIT_LIST_HEAD(&psLinuxEventObject->sList);
+
+ atomic_set(&psLinuxEventObject->sTimeStamp, 0);
+ psLinuxEventObject->ui32TimeStampPrevious = 0;
+
+#if defined(DEBUG)
+ psLinuxEventObject->ui32Stats = 0;
+#endif
+ init_waitqueue_head(&psLinuxEventObject->sWait);
+
+ psLinuxEventObject->psLinuxEventObjectList = psLinuxEventObjectList;
+
+ psLinuxEventObject->hResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_EVENT_OBJECT,
+ psLinuxEventObject,
+ 0,
+ &LinuxEventObjectDeleteCallback);
+
+ write_lock_bh(&psLinuxEventObjectList->sLock);
+ list_add(&psLinuxEventObject->sList, &psLinuxEventObjectList->sList);
+ write_unlock_bh(&psLinuxEventObjectList->sLock);
+
+ *phOSEventObject = psLinuxEventObject;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR LinuxEventObjectSignal(IMG_HANDLE hOSEventObjectList)
+{
+ PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject;
+ PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList = (PVRSRV_LINUX_EVENT_OBJECT_LIST*)hOSEventObjectList;
+ struct list_head *psListEntry, *psListEntryTemp, *psList;
+ psList = &psLinuxEventObjectList->sList;
+
+ list_for_each_safe(psListEntry, psListEntryTemp, psList)
+ {
+
+ psLinuxEventObject = (PVRSRV_LINUX_EVENT_OBJECT *)list_entry(psListEntry, PVRSRV_LINUX_EVENT_OBJECT, sList);
+
+ atomic_inc(&psLinuxEventObject->sTimeStamp);
+ wake_up_interruptible(&psLinuxEventObject->sWait);
+ }
+
+ return PVRSRV_OK;
+
+}
+
+PVRSRV_ERROR LinuxEventObjectWait(IMG_HANDLE hOSEventObject, IMG_UINT32 ui32MSTimeout)
+{
+ IMG_UINT32 ui32TimeStamp;
+ DEFINE_WAIT(sWait);
+
+ PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject = (PVRSRV_LINUX_EVENT_OBJECT *) hOSEventObject;
+
+ IMG_UINT32 ui32TimeOutJiffies = msecs_to_jiffies(ui32MSTimeout);
+
+ do
+ {
+ prepare_to_wait(&psLinuxEventObject->sWait, &sWait, TASK_INTERRUPTIBLE);
+ ui32TimeStamp = atomic_read(&psLinuxEventObject->sTimeStamp);
+
+ if(psLinuxEventObject->ui32TimeStampPrevious != ui32TimeStamp)
+ {
+ break;
+ }
+
+ mutex_unlock(&gPVRSRVLock);
+
+ ui32TimeOutJiffies = (IMG_UINT32)schedule_timeout((IMG_INT32)ui32TimeOutJiffies);
+
+ mutex_lock(&gPVRSRVLock);
+#if defined(DEBUG)
+ psLinuxEventObject->ui32Stats++;
+#endif
+
+
+ } while (ui32TimeOutJiffies);
+
+ finish_wait(&psLinuxEventObject->sWait, &sWait);
+
+ psLinuxEventObject->ui32TimeStampPrevious = ui32TimeStamp;
+
+ return ui32TimeOutJiffies ? PVRSRV_OK : PVRSRV_ERROR_TIMEOUT;
+
+}
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+PVRSRV_ERROR LinuxEventObjectListCreate(IMG_HANDLE *phEventObjectList);
+PVRSRV_ERROR LinuxEventObjectListDestroy(IMG_HANDLE hEventObjectList);
+PVRSRV_ERROR LinuxEventObjectAdd(IMG_HANDLE hOSEventObjectList, IMG_HANDLE *phOSEventObject);
+PVRSRV_ERROR LinuxEventObjectDelete(IMG_HANDLE hOSEventObjectList, IMG_HANDLE hOSEventObject);
+PVRSRV_ERROR LinuxEventObjectSignal(IMG_HANDLE hOSEventObjectList);
+PVRSRV_ERROR LinuxEventObjectWait(IMG_HANDLE hOSEventObject, IMG_UINT32 ui32MSTimeout);
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef __LINKAGE_H__
+#define __LINKAGE_H__
+
+#if !defined(SUPPORT_DRI_DRM)
+IMG_INT32 PVRSRV_BridgeDispatchKM(struct file *file, IMG_UINT cmd, IMG_UINT32 arg);
+#endif
+
+IMG_VOID PVRDPFInit(IMG_VOID);
+PVRSRV_ERROR PVROSFuncInit(IMG_VOID);
+IMG_VOID PVROSFuncDeInit(IMG_VOID);
+
+#ifdef DEBUG
+IMG_INT PVRDebugProcSetLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT32 count, IMG_VOID *data);
+IMG_VOID PVRDebugSetLevel(IMG_UINT32 uDebugLevel);
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+void ProcSeqShowDebugLevel(struct seq_file *sfile,void* el);
+#else
+IMG_INT PVRDebugProcGetLevel(IMG_CHAR *page, IMG_CHAR **start, off_t off, IMG_INT count, IMG_INT *eof, IMG_VOID *data);
+#endif
+
+#ifdef PVR_MANUAL_POWER_CONTROL
+IMG_INT PVRProcSetPowerLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT32 count, IMG_VOID *data);
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+void ProcSeqShowPowerLevel(struct seq_file *sfile,void* el);
+#else
+IMG_INT PVRProcGetPowerLevel(IMG_CHAR *page, IMG_CHAR **start, off_t off, IMG_INT count, IMG_INT *eof, IMG_VOID *data);
+#endif
+
+
+#endif
+#endif
+
+#endif
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef __LOCK_H__
+#define __LOCK_H__
+
+#include <linux/mutex.h>
+
+extern struct mutex gPVRSRVLock;
+
+#endif
--- /dev/null
+/**********************************************************************
+ *
+ * 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/mm.h>
+#include <linux/vmalloc.h>
+#include <asm/io.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/sched.h>
+#include <linux/mutex.h>
+
+#include "img_defs.h"
+#include "services.h"
+#include "servicesint.h"
+#include "syscommon.h"
+#include "mutils.h"
+#include "mm.h"
+#include "pvrmmap.h"
+#include "mmap.h"
+#include "osfunc.h"
+#include "pvr_debug.h"
+#include "proc.h"
+#include "lock.h"
+
+
+static struct kmem_cache *linux_mem_area_cache;
+
+int linux_mm_init(void)
+{
+ linux_mem_area_cache = kmem_cache_create("img-mm", sizeof(LinuxMemArea), 0, 0, NULL);
+
+ if (!linux_mem_area_cache)
+ {
+ pr_err("%s: failed to allocate kmem_cache", __FUNCTION__);
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+void linux_mm_cleanup(void)
+{
+ if (linux_mem_area_cache)
+ {
+ kmem_cache_destroy(linux_mem_area_cache);
+ linux_mem_area_cache = NULL;
+ }
+}
+
+void *vmalloc_wrapper(u32 bytes, u32 alloc_flags)
+{
+ /*
+ * FIXME: This function creates a memory alias
+ * of a page, with a mismatching PAT type.
+ * This wants to be fixed most likely.
+ */
+ pgprot_t pgprot_flags;
+
+ switch(alloc_flags & PVRSRV_HAP_CACHETYPE_MASK)
+ {
+ case PVRSRV_HAP_CACHED:
+ pgprot_flags = PAGE_KERNEL;
+ break;
+ case PVRSRV_HAP_WRITECOMBINE:
+ pgprot_flags = PGPROT_WC(PAGE_KERNEL);
+ break;
+ case PVRSRV_HAP_UNCACHED:
+ pgprot_flags = PGPROT_UC(PAGE_KERNEL);
+ break;
+ default:
+ WARN(1, "unknown mapping flags=0x%08x", alloc_flags);
+ return NULL;
+ }
+
+
+ return __vmalloc(bytes, GFP_KERNEL | __GFP_HIGHMEM, pgprot_flags);
+}
+
+LinuxMemArea *vmalloc_linux_mem_area(u32 bytes, u32 area_flags)
+{
+ LinuxMemArea *mem_area;
+ void *vptr;
+
+ mem_area = kmem_cache_alloc(linux_mem_area_cache, GFP_KERNEL);
+
+ if (!mem_area)
+ goto failed;
+
+ vptr = vmalloc_wrapper(bytes, area_flags);
+ if (!vptr)
+ goto failed;
+
+ mem_area->eAreaType = LINUX_MEM_AREA_VMALLOC;
+ mem_area->uData.sVmalloc.pvVmallocAddress = vptr;
+ mem_area->ui32ByteSize = bytes;
+ mem_area->ui32AreaFlags = area_flags;
+ mem_area->bMMapRegistered = IMG_FALSE;
+ INIT_LIST_HEAD(&mem_area->sMMapOffsetStructList);
+
+ return mem_area;
+
+failed:
+ pr_err("%s: failed!", __FUNCTION__);
+ if (mem_area)
+ kmem_cache_free(linux_mem_area_cache, mem_area);
+ return NULL;
+}
+
+
+void __iomem *ioremap_wrapper(resource_size_t address,
+ u32 bytes, u32 mapping_flags)
+{
+ void __iomem *cookie;
+
+ switch(mapping_flags & PVRSRV_HAP_CACHETYPE_MASK)
+ {
+ case PVRSRV_HAP_CACHED:
+ cookie = ioremap_cache(address, bytes);
+ break;
+ case PVRSRV_HAP_WRITECOMBINE:
+ cookie = ioremap_wc(address, bytes);
+ break;
+ case PVRSRV_HAP_UNCACHED:
+ cookie = ioremap_nocache(address, bytes);
+ break;
+ default:
+ pr_err("ioremap_wrapper: unknown mapping flags");
+ return NULL;
+ }
+
+ return cookie;
+}
+
+LinuxMemArea *
+ioremap_linux_mem_area(resource_size_t address, u32 bytes, u32 area_flags)
+{
+ LinuxMemArea *mem_area;
+ void __iomem *cookie;
+
+ mem_area = kmem_cache_alloc(linux_mem_area_cache, GFP_KERNEL);
+ if (!mem_area)
+ return NULL;
+
+ cookie = ioremap_wrapper(address, bytes, area_flags);
+ if (!cookie)
+ {
+ kmem_cache_free(linux_mem_area_cache, mem_area);
+ return NULL;
+ }
+
+ mem_area->eAreaType = LINUX_MEM_AREA_IOREMAP;
+ mem_area->uData.sIORemap.pvIORemapCookie = cookie;
+ mem_area->uData.sIORemap.CPUPhysAddr = address;
+ mem_area->ui32ByteSize = bytes;
+ mem_area->ui32AreaFlags = area_flags;
+ mem_area->bMMapRegistered = IMG_FALSE;
+ INIT_LIST_HEAD(&mem_area->sMMapOffsetStructList);
+
+ return mem_area;
+}
+
+
+static IMG_BOOL
+TreatExternalPagesAsContiguous(IMG_SYS_PHYADDR *psSysPhysAddr, u32 ui32Bytes, IMG_BOOL bPhysContig)
+{
+ u32 ui32;
+ u32 ui32AddrChk;
+ u32 ui32NumPages = RANGE_TO_PAGES(ui32Bytes);
+
+ for (ui32 = 0, ui32AddrChk = psSysPhysAddr[0].uiAddr;
+ ui32 < ui32NumPages;
+ ui32++, ui32AddrChk = (bPhysContig) ? (ui32AddrChk + PAGE_SIZE) : psSysPhysAddr[ui32].uiAddr)
+ {
+ if (!pfn_valid(PHYS_TO_PFN(ui32AddrChk)))
+ {
+ break;
+ }
+ }
+ if (ui32 == ui32NumPages)
+ {
+ return IMG_FALSE;
+ }
+
+ if (!bPhysContig)
+ {
+ for (ui32 = 0, ui32AddrChk = psSysPhysAddr[0].uiAddr;
+ ui32 < ui32NumPages;
+ ui32++, ui32AddrChk += PAGE_SIZE)
+ {
+ if (psSysPhysAddr[ui32].uiAddr != ui32AddrChk)
+ {
+ return IMG_FALSE;
+ }
+ }
+ }
+
+ return IMG_TRUE;
+}
+
+
+LinuxMemArea *NewExternalKVLinuxMemArea(IMG_SYS_PHYADDR *pBasePAddr, void *pvCPUVAddr, u32 bytes, IMG_BOOL bPhysContig, u32 area_flags)
+{
+ LinuxMemArea *mem_area;
+
+ mem_area = kmem_cache_alloc(linux_mem_area_cache, GFP_KERNEL);
+
+ if (!mem_area)
+ return NULL;
+
+ mem_area->eAreaType = LINUX_MEM_AREA_EXTERNAL_KV;
+ mem_area->uData.sExternalKV.pvExternalKV = pvCPUVAddr;
+ mem_area->uData.sExternalKV.bPhysContig = (IMG_BOOL)(bPhysContig || TreatExternalPagesAsContiguous(pBasePAddr, bytes, bPhysContig));
+
+ if (mem_area->uData.sExternalKV.bPhysContig)
+ mem_area->uData.sExternalKV.uPhysAddr.SysPhysAddr = *pBasePAddr;
+ else
+ mem_area->uData.sExternalKV.uPhysAddr.pSysPhysAddr = pBasePAddr;
+
+ mem_area->ui32ByteSize = bytes;
+ mem_area->ui32AreaFlags = area_flags;
+ mem_area->bMMapRegistered = IMG_FALSE;
+ INIT_LIST_HEAD(&mem_area->sMMapOffsetStructList);
+
+ return mem_area;
+}
+
+LinuxMemArea *
+NewIOLinuxMemArea(resource_size_t address, u32 bytes, u32 area_flags)
+{
+ LinuxMemArea *mem_area;
+
+ mem_area = kmem_cache_alloc(linux_mem_area_cache, GFP_KERNEL);
+
+ if (!mem_area)
+ return NULL;
+
+ mem_area->eAreaType = LINUX_MEM_AREA_IO;
+ mem_area->uData.sIO.CPUPhysAddr = address;
+ mem_area->ui32ByteSize = bytes;
+ mem_area->ui32AreaFlags = area_flags;
+ mem_area->bMMapRegistered = IMG_FALSE;
+ INIT_LIST_HEAD(&mem_area->sMMapOffsetStructList);
+
+ return mem_area;
+}
+
+
+LinuxMemArea * alloc_pages_linux_mem_area(u32 bytes, u32 area_flags)
+{
+ LinuxMemArea *mem_area;
+ int page_count;
+ struct page **page_list;
+ IMG_HANDLE hBlockPageList;
+ int i;
+ PVRSRV_ERROR eError;
+
+ mem_area = kmem_cache_alloc(linux_mem_area_cache, GFP_KERNEL);
+ if (!mem_area)
+ goto failed_area_alloc;
+
+
+ page_count = RANGE_TO_PAGES(bytes);
+
+ eError = OSAllocMem(0, sizeof(*page_list) * page_count, (void **)&page_list, &hBlockPageList,
+ "Array of pages");
+
+ if(eError != PVRSRV_OK)
+ goto failed_page_list_alloc;
+
+ for(i=0; i<page_count; i++)
+ {
+ page_list[i] = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, 0);
+ if(!page_list[i])
+ goto failed_alloc_pages;
+ }
+
+ mem_area->eAreaType = LINUX_MEM_AREA_ALLOC_PAGES;
+ mem_area->uData.sPageList.pvPageList = page_list;
+ mem_area->uData.sPageList.hBlockPageList = hBlockPageList;
+ mem_area->ui32ByteSize = bytes;
+ mem_area->ui32AreaFlags = area_flags;
+ mem_area->bMMapRegistered = IMG_FALSE;
+ INIT_LIST_HEAD(&mem_area->sMMapOffsetStructList);
+
+ return mem_area;
+
+failed_alloc_pages:
+ for(i--; i >= 0; i--)
+ __free_pages(page_list[i], 0);
+
+ OSFreeMem(0, sizeof(*page_list) * page_count, page_list, hBlockPageList);
+ mem_area->uData.sPageList.pvPageList = NULL;
+failed_page_list_alloc:
+ kmem_cache_free(linux_mem_area_cache, mem_area);
+failed_area_alloc:
+ pr_debug("%s: failed", __FUNCTION__);
+
+ return NULL;
+}
+
+
+void free_pages_linux_mem_area(LinuxMemArea *mem_area)
+{
+ u32 page_count;
+ struct page **page_list;
+ IMG_HANDLE hBlockPageList;
+ int i;
+
+ BUG_ON(!mem_area);
+
+
+ page_count = RANGE_TO_PAGES(mem_area->ui32ByteSize);
+ page_list = mem_area->uData.sPageList.pvPageList;
+ hBlockPageList = mem_area->uData.sPageList.hBlockPageList;
+
+ for(i = 0; i < page_count; i++)
+ __free_pages(page_list[i], 0);
+
+
+ OSFreeMem(0, sizeof(*page_list) * page_count, page_list, hBlockPageList);
+ mem_area->uData.sPageList.pvPageList = NULL;
+}
+
+
+struct page* LinuxMemAreaOffsetToPage(LinuxMemArea *mem_area, u32 offset)
+{
+ u32 page_index;
+ u8 *addr;
+
+ switch(mem_area->eAreaType)
+ {
+ case LINUX_MEM_AREA_ALLOC_PAGES:
+ page_index = PHYS_TO_PFN(offset);
+ return mem_area->uData.sPageList.pvPageList[page_index];
+
+ case LINUX_MEM_AREA_VMALLOC:
+ addr = mem_area->uData.sVmalloc.pvVmallocAddress;
+ addr += offset;
+ return vmalloc_to_page(addr);
+
+ case LINUX_MEM_AREA_SUB_ALLOC:
+ return LinuxMemAreaOffsetToPage(mem_area->uData.sSubAlloc.psParentLinuxMemArea,
+ mem_area->uData.sSubAlloc.ui32ByteOffset
+ + offset);
+ default:
+ pr_err("%s: Unsupported request for struct page from LinuxMemArea with type=%s",
+ __FUNCTION__, LinuxMemAreaTypeToString(mem_area->eAreaType));
+ return NULL;
+ }
+}
+
+
+LinuxMemArea *NewSubLinuxMemArea(LinuxMemArea *parent, u32 offset, u32 bytes)
+{
+ LinuxMemArea *mem_area;
+
+ BUG_ON(offset+bytes > parent->ui32ByteSize);
+
+ mem_area = kmem_cache_alloc(linux_mem_area_cache, GFP_KERNEL);
+ if (!mem_area)
+ return NULL;
+
+ mem_area->eAreaType = LINUX_MEM_AREA_SUB_ALLOC;
+ mem_area->uData.sSubAlloc.psParentLinuxMemArea = parent;
+ mem_area->uData.sSubAlloc.ui32ByteOffset = offset;
+ mem_area->ui32ByteSize = bytes;
+ mem_area->ui32AreaFlags = parent->ui32AreaFlags;
+ mem_area->bMMapRegistered = IMG_FALSE;
+ INIT_LIST_HEAD(&mem_area->sMMapOffsetStructList);
+
+ return mem_area;
+}
+
+
+void LinuxMemAreaDeepFree(LinuxMemArea *mem_area)
+{
+ /* FIXME: call vfree and co direct, and free the mem area centrally at the end */
+ switch(mem_area->eAreaType)
+ {
+ case LINUX_MEM_AREA_VMALLOC:
+ vfree(mem_area->uData.sVmalloc.pvVmallocAddress);
+ break;
+ case LINUX_MEM_AREA_ALLOC_PAGES:
+ free_pages_linux_mem_area(mem_area);
+ break;
+ case LINUX_MEM_AREA_IOREMAP:
+ iounmap(mem_area->uData.sIORemap.pvIORemapCookie);
+ break;
+ case LINUX_MEM_AREA_EXTERNAL_KV:
+ case LINUX_MEM_AREA_IO:
+ case LINUX_MEM_AREA_SUB_ALLOC:
+ break;
+ default:
+ pr_debug("%s: Unknown are type (%d)\n",
+ __FUNCTION__, mem_area->eAreaType);
+ break;
+ }
+ kmem_cache_free(linux_mem_area_cache, mem_area);
+}
+
+
+void * LinuxMemAreaToCpuVAddr(LinuxMemArea *mem_area)
+{
+ switch(mem_area->eAreaType)
+ {
+ case LINUX_MEM_AREA_VMALLOC:
+ return mem_area->uData.sVmalloc.pvVmallocAddress;
+ case LINUX_MEM_AREA_IOREMAP:
+ return mem_area->uData.sIORemap.pvIORemapCookie;
+ case LINUX_MEM_AREA_EXTERNAL_KV:
+ return mem_area->uData.sExternalKV.pvExternalKV;
+ case LINUX_MEM_AREA_SUB_ALLOC:
+ {
+ char *addr = LinuxMemAreaToCpuVAddr(mem_area->uData.sSubAlloc.psParentLinuxMemArea);
+ if (!addr)
+ return NULL;
+ return addr + mem_area->uData.sSubAlloc.ui32ByteOffset;
+ }
+ default:
+ return NULL;
+ }
+}
+
+
+resource_size_t LinuxMemAreaToCpuPAddr(LinuxMemArea *mem_area, u32 offset)
+{
+ resource_size_t address;
+
+ address = 0;
+
+ switch(mem_area->eAreaType)
+ {
+ case LINUX_MEM_AREA_IOREMAP:
+ {
+ address = mem_area->uData.sIORemap.CPUPhysAddr;
+ address += offset;
+ break;
+ }
+ case LINUX_MEM_AREA_EXTERNAL_KV:
+ {
+ if (mem_area->uData.sExternalKV.bPhysContig)
+ {
+ IMG_CPU_PHYADDR CpuPAddr = SysSysPAddrToCpuPAddr(mem_area->uData.sExternalKV.uPhysAddr.SysPhysAddr);
+ address = CpuPAddr.uiAddr + offset;
+ } else {
+ u32 page_index = PHYS_TO_PFN(offset);
+ IMG_SYS_PHYADDR SysPAddr = mem_area->uData.sExternalKV.uPhysAddr.pSysPhysAddr[page_index];
+ IMG_CPU_PHYADDR CpuPAddr = SysSysPAddrToCpuPAddr(SysPAddr);
+ address = CpuPAddr.uiAddr + ADDR_TO_PAGE_OFFSET(offset);
+ }
+ break;
+ }
+ case LINUX_MEM_AREA_IO:
+ {
+ address = mem_area->uData.sIO.CPUPhysAddr;
+ address += offset;
+ break;
+ }
+ case LINUX_MEM_AREA_VMALLOC:
+ {
+ char *vaddr;
+ vaddr = mem_area->uData.sVmalloc.pvVmallocAddress;
+ vaddr += offset;
+ address = VMallocToPhys(vaddr);
+ break;
+ }
+ case LINUX_MEM_AREA_ALLOC_PAGES:
+ {
+ struct page *page;
+ u32 page_index = PHYS_TO_PFN(offset);
+ page = mem_area->uData.sPageList.pvPageList[page_index];
+ address = page_to_phys(page);
+ address += ADDR_TO_PAGE_OFFSET(offset);
+ break;
+ }
+ case LINUX_MEM_AREA_SUB_ALLOC:
+ {
+ IMG_CPU_PHYADDR CpuPAddr =
+ OSMemHandleToCpuPAddr(mem_area->uData.sSubAlloc.psParentLinuxMemArea,
+ mem_area->uData.sSubAlloc.ui32ByteOffset
+ + offset);
+
+ address = CpuPAddr.uiAddr;
+ break;
+ }
+ default:
+ pr_debug("%s: Unknown LinuxMemArea type (%d)\n",
+ __FUNCTION__, mem_area->eAreaType);
+ break;
+ }
+
+ BUG_ON(!address);
+ return address;
+}
+
+
+IMG_BOOL LinuxMemAreaPhysIsContig(LinuxMemArea *mem_area)
+{
+ switch(mem_area->eAreaType)
+ {
+ case LINUX_MEM_AREA_IOREMAP:
+ case LINUX_MEM_AREA_IO:
+ return IMG_TRUE;
+
+ case LINUX_MEM_AREA_EXTERNAL_KV:
+ return mem_area->uData.sExternalKV.bPhysContig;
+
+ case LINUX_MEM_AREA_VMALLOC:
+ case LINUX_MEM_AREA_ALLOC_PAGES:
+ return IMG_FALSE;
+
+ case LINUX_MEM_AREA_SUB_ALLOC:
+
+ return LinuxMemAreaPhysIsContig(mem_area->uData.sSubAlloc.psParentLinuxMemArea);
+
+ default:
+ pr_debug("%s: Unknown LinuxMemArea type (%d)\n",
+ __FUNCTION__, mem_area->eAreaType);
+ break;
+ }
+ return IMG_FALSE;
+}
+
+
+const char *
+LinuxMemAreaTypeToString(LINUX_MEM_AREA_TYPE eMemAreaType)
+{
+
+ switch(eMemAreaType)
+ {
+ case LINUX_MEM_AREA_IOREMAP:
+ return "LINUX_MEM_AREA_IOREMAP";
+ case LINUX_MEM_AREA_EXTERNAL_KV:
+ return "LINUX_MEM_AREA_EXTERNAL_KV";
+ case LINUX_MEM_AREA_IO:
+ return "LINUX_MEM_AREA_IO";
+ case LINUX_MEM_AREA_VMALLOC:
+ return "LINUX_MEM_AREA_VMALLOC";
+ case LINUX_MEM_AREA_SUB_ALLOC:
+ return "LINUX_MEM_AREA_SUB_ALLOC";
+ case LINUX_MEM_AREA_ALLOC_PAGES:
+ return "LINUX_MEM_AREA_ALLOC_PAGES";
+ default:
+ BUG();
+ }
+
+ return "";
+}
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef __IMG_LINUX_MM_H__
+#define __IMG_LINUX_MM_H__
+
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/list.h>
+#include <linux/types.h>
+
+#include <asm/io.h>
+
+#define PHYS_TO_PFN(phys) ((phys) >> PAGE_SHIFT)
+#define PFN_TO_PHYS(pfn) ((pfn) << PAGE_SHIFT)
+
+#define RANGE_TO_PAGES(range) (((range) + (PAGE_SIZE - 1)) >> PAGE_SHIFT)
+
+#define ADDR_TO_PAGE_OFFSET(addr) (((unsigned long)(addr)) & (PAGE_SIZE - 1))
+
+static inline u32 VMallocToPhys(void *pCpuVAddr)
+{
+ return (page_to_phys(vmalloc_to_page(pCpuVAddr)) + ADDR_TO_PAGE_OFFSET(pCpuVAddr));
+
+}
+
+typedef enum {
+ LINUX_MEM_AREA_IOREMAP,
+ LINUX_MEM_AREA_EXTERNAL_KV,
+ LINUX_MEM_AREA_IO,
+ LINUX_MEM_AREA_VMALLOC,
+ LINUX_MEM_AREA_ALLOC_PAGES,
+ LINUX_MEM_AREA_SUB_ALLOC,
+ LINUX_MEM_AREA_TYPE_COUNT
+}LINUX_MEM_AREA_TYPE;
+
+typedef struct _LinuxMemArea LinuxMemArea;
+
+
+struct _LinuxMemArea {
+ LINUX_MEM_AREA_TYPE eAreaType;
+ union _uData
+ {
+ struct _sIORemap
+ {
+
+ resource_size_t CPUPhysAddr;
+ void *pvIORemapCookie;
+ }sIORemap;
+ struct _sExternalKV
+ {
+
+ IMG_BOOL bPhysContig;
+ union {
+
+ IMG_SYS_PHYADDR SysPhysAddr;
+ IMG_SYS_PHYADDR *pSysPhysAddr;
+ } uPhysAddr;
+ void *pvExternalKV;
+ }sExternalKV;
+ struct _sIO
+ {
+ resource_size_t CPUPhysAddr;
+ }sIO;
+ struct _sVmalloc
+ {
+
+ void *pvVmallocAddress;
+ }sVmalloc;
+ struct _sPageList
+ {
+
+ struct page **pvPageList;
+ IMG_HANDLE hBlockPageList;
+ }sPageList;
+ struct _sSubAlloc
+ {
+
+ LinuxMemArea *psParentLinuxMemArea;
+ u32 ui32ByteOffset;
+ }sSubAlloc;
+ }uData;
+
+ u32 ui32ByteSize;
+
+ u32 ui32AreaFlags;
+
+ IMG_BOOL bMMapRegistered;
+
+
+ struct list_head sMMapItem;
+
+
+ struct list_head sMMapOffsetStructList;
+};
+
+int linux_mm_init(void);
+
+
+void linux_mm_cleanup(void);
+
+void *vmalloc_wrapper(u32 bytes, u32 alloc_flags);
+
+LinuxMemArea *vmalloc_linux_mem_area(u32 bytes, u32 area_flags);
+
+
+void *ioremap_wrapper(resource_size_t address, u32 bytes, u32 mapping_flags);
+
+
+LinuxMemArea *ioremap_linux_mem_area(resource_size_t address, u32 bytes, u32 area_flags);
+
+
+LinuxMemArea *NewExternalKVLinuxMemArea(IMG_SYS_PHYADDR *pBasePAddr, void *pvCPUVAddr, u32 ui32Bytes, IMG_BOOL bPhysContig, u32 ui32AreaFlags);
+
+
+struct page *LinuxMemAreaOffsetToPage(LinuxMemArea *psLinuxMemArea, u32 ui32ByteOffset);
+
+
+LinuxMemArea *NewIOLinuxMemArea(resource_size_t address, u32 ui32Bytes, u32 ui32AreaFlags);
+
+
+LinuxMemArea *alloc_pages_linux_mem_area(u32 ui32Bytes, u32 ui32AreaFlags);
+
+
+void free_pages_linux_mem_area(LinuxMemArea *psLinuxMemArea);
+
+
+LinuxMemArea *NewSubLinuxMemArea(LinuxMemArea *psParentLinuxMemArea,
+ u32 ui32ByteOffset,
+ u32 ui32Bytes);
+
+
+void LinuxMemAreaDeepFree(LinuxMemArea *psLinuxMemArea);
+
+
+void *LinuxMemAreaToCpuVAddr(LinuxMemArea *psLinuxMemArea);
+
+
+resource_size_t LinuxMemAreaToCpuPAddr(LinuxMemArea *mem_area, u32 offset);
+
+
+#define LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32ByteOffset) PHYS_TO_PFN(LinuxMemAreaToCpuPAddr(psLinuxMemArea, ui32ByteOffset))
+
+IMG_BOOL LinuxMemAreaPhysIsContig(LinuxMemArea *psLinuxMemArea);
+
+static inline LinuxMemArea *
+LinuxMemAreaRoot(LinuxMemArea *psLinuxMemArea)
+{
+ if(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC)
+ {
+ return psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea;
+ }
+ else
+ {
+ return psLinuxMemArea;
+ }
+}
+
+
+static inline LINUX_MEM_AREA_TYPE
+LinuxMemAreaRootType(LinuxMemArea *psLinuxMemArea)
+{
+ return LinuxMemAreaRoot(psLinuxMemArea)->eAreaType;
+}
+
+
+const IMG_CHAR *LinuxMemAreaTypeToString(LINUX_MEM_AREA_TYPE eMemAreaType);
+
+
+#if defined(DEBUG)
+const IMG_CHAR *HAPFlagsToString(u32 ui32Flags);
+#endif
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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/version.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <asm/io.h>
+#include <asm/page.h>
+#include <asm/shmparam.h>
+#include <asm/pgtable.h>
+#include <linux/sched.h>
+#include <asm/current.h>
+#if defined(SUPPORT_DRI_DRM)
+#include <drm/drmP.h>
+#endif
+
+#include "img_defs.h"
+#include "services.h"
+#include "servicesint.h"
+#include "pvrmmap.h"
+#include "mutils.h"
+#include "mmap.h"
+#include "mm.h"
+#include "pvr_debug.h"
+#include "osfunc.h"
+#include "proc.h"
+#include "handle.h"
+#include "perproc.h"
+#include "env_perproc.h"
+#include "bridged_support.h"
+#if defined(SUPPORT_DRI_DRM)
+#include "pvr_drm.h"
+#endif
+
+#if !defined(PVR_SECURE_HANDLES)
+#error "The mmap code requires PVR_SECURE_HANDLES"
+#endif
+
+static struct mutex g_sMMapMutex;
+
+static struct kmem_cache *g_psMemmapCache = NULL;
+static LIST_HEAD(g_sMMapAreaList);
+static LIST_HEAD(g_sMMapOffsetStructList);
+
+
+#define FIRST_PHYSICAL_PFN 0
+#define LAST_PHYSICAL_PFN 0x7fffffffUL
+#define FIRST_SPECIAL_PFN (LAST_PHYSICAL_PFN + 1)
+#define LAST_SPECIAL_PFN 0xffffffffUL
+
+#define MAX_MMAP_HANDLE 0x7fffffffUL
+
+static inline IMG_BOOL
+PFNIsPhysical(IMG_UINT32 pfn)
+{
+
+ return ((pfn >= FIRST_PHYSICAL_PFN) && (pfn <= LAST_PHYSICAL_PFN)) ? IMG_TRUE : IMG_FALSE;
+}
+
+static inline IMG_BOOL
+PFNIsSpecial(IMG_UINT32 pfn)
+{
+
+ return ((pfn >= FIRST_SPECIAL_PFN) && (pfn <= LAST_SPECIAL_PFN)) ? IMG_TRUE : IMG_FALSE;
+}
+
+static inline IMG_HANDLE
+MMapOffsetToHandle(IMG_UINT32 pfn)
+{
+ if (PFNIsPhysical(pfn))
+ {
+ PVR_ASSERT(PFNIsPhysical(pfn));
+ return IMG_NULL;
+ }
+
+ return (IMG_HANDLE)(pfn - FIRST_SPECIAL_PFN);
+}
+
+static inline IMG_UINT32
+HandleToMMapOffset(IMG_HANDLE hHandle)
+{
+ IMG_UINT32 ulHandle = (IMG_UINT32)hHandle;
+
+ if (PFNIsSpecial(ulHandle))
+ {
+ PVR_ASSERT(PFNIsSpecial(ulHandle));
+ return 0;
+ }
+
+ return ulHandle + FIRST_SPECIAL_PFN;
+}
+
+static inline IMG_BOOL
+LinuxMemAreaUsesPhysicalMap(LinuxMemArea *psLinuxMemArea)
+{
+ return LinuxMemAreaPhysIsContig(psLinuxMemArea);
+}
+
+static inline IMG_UINT32
+GetCurrentThreadID(IMG_VOID)
+{
+ return (IMG_UINT32)current->pid;
+}
+
+static PKV_OFFSET_STRUCT
+CreateOffsetStruct(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32Offset, IMG_UINT32 ui32RealByteSize)
+{
+ PKV_OFFSET_STRUCT psOffsetStruct;
+#if defined(DEBUG)
+ const IMG_CHAR *pszName = LinuxMemAreaTypeToString(LinuxMemAreaRootType(psLinuxMemArea));
+#endif
+
+#if defined(DEBUG)
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "%s(%s, psLinuxMemArea: 0x%p, ui32AllocFlags: 0x%8lx)",
+ __FUNCTION__, pszName, psLinuxMemArea, psLinuxMemArea->ui32AreaFlags));
+#endif
+
+ PVR_ASSERT(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC || LinuxMemAreaRoot(psLinuxMemArea)->eAreaType != LINUX_MEM_AREA_SUB_ALLOC);
+
+ PVR_ASSERT(psLinuxMemArea->bMMapRegistered);
+
+ psOffsetStruct = kmem_cache_alloc(g_psMemmapCache, GFP_KERNEL);
+ if(psOffsetStruct == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRMMapRegisterArea: Couldn't alloc another mapping record from cache"));
+ return IMG_NULL;
+ }
+
+ psOffsetStruct->ui32MMapOffset = ui32Offset;
+
+ psOffsetStruct->psLinuxMemArea = psLinuxMemArea;
+
+ psOffsetStruct->ui32Mapped = 0;
+
+ psOffsetStruct->ui32RealByteSize = ui32RealByteSize;
+
+
+ psOffsetStruct->ui32TID = GetCurrentThreadID();
+
+ psOffsetStruct->ui32PID = OSGetCurrentProcessIDKM();
+
+ psOffsetStruct->bOnMMapList = IMG_FALSE;
+
+ psOffsetStruct->ui32RefCount = 0;
+
+ psOffsetStruct->ui32UserVAddr = 0;
+
+ list_add_tail(&psOffsetStruct->sAreaItem, &psLinuxMemArea->sMMapOffsetStructList);
+
+ return psOffsetStruct;
+}
+
+
+static IMG_VOID
+DestroyOffsetStruct(PKV_OFFSET_STRUCT psOffsetStruct)
+{
+ list_del(&psOffsetStruct->sAreaItem);
+
+ if (psOffsetStruct->bOnMMapList)
+ {
+ list_del(&psOffsetStruct->sMMapItem);
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE, "%s: Table entry: "
+ "psLinuxMemArea=0x%08lX, CpuPAddr=0x%08lX", __FUNCTION__,
+ psOffsetStruct->psLinuxMemArea,
+ LinuxMemAreaToCpuPAddr(psOffsetStruct->psLinuxMemArea, 0)));
+
+ kmem_cache_free(g_psMemmapCache, psOffsetStruct);
+}
+
+
+static inline IMG_VOID
+DetermineUsersSizeAndByteOffset(LinuxMemArea *psLinuxMemArea,
+ IMG_UINT32 *pui32RealByteSize,
+ IMG_UINT32 *pui32ByteOffset)
+{
+ IMG_UINT32 ui32PageAlignmentOffset;
+ IMG_CPU_PHYADDR CpuPAddr;
+
+ CpuPAddr.uiAddr = LinuxMemAreaToCpuPAddr(psLinuxMemArea, 0);
+ ui32PageAlignmentOffset = ADDR_TO_PAGE_OFFSET(CpuPAddr.uiAddr);
+
+ *pui32ByteOffset = ui32PageAlignmentOffset;
+
+ *pui32RealByteSize = PAGE_ALIGN(psLinuxMemArea->ui32ByteSize + ui32PageAlignmentOffset);
+}
+
+
+PVRSRV_ERROR
+PVRMMapOSMemHandleToMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hMHandle,
+ IMG_UINT32 *pui32MMapOffset,
+ IMG_UINT32 *pui32ByteOffset,
+ IMG_UINT32 *pui32RealByteSize,
+ IMG_UINT32 *pui32UserVAddr)
+{
+ LinuxMemArea *psLinuxMemArea;
+ PKV_OFFSET_STRUCT psOffsetStruct;
+ IMG_HANDLE hOSMemHandle;
+ PVRSRV_ERROR eError;
+
+ mutex_lock(&g_sMMapMutex);
+
+ PVR_ASSERT(PVRSRVGetMaxHandle(psPerProc->psHandleBase) <= MAX_MMAP_HANDLE);
+
+ eError = PVRSRVLookupOSMemHandle(psPerProc->psHandleBase, &hOSMemHandle, hMHandle);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Lookup of handle 0x%lx failed", __FUNCTION__, hMHandle));
+
+ goto exit_unlock;
+ }
+
+ psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+ DetermineUsersSizeAndByteOffset(psLinuxMemArea,
+ pui32RealByteSize,
+ pui32ByteOffset);
+
+
+ list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
+ {
+ if (psPerProc->ui32PID == psOffsetStruct->ui32PID)
+ {
+
+ PVR_ASSERT(*pui32RealByteSize == psOffsetStruct->ui32RealByteSize);
+
+ *pui32MMapOffset = psOffsetStruct->ui32MMapOffset;
+ *pui32UserVAddr = psOffsetStruct->ui32UserVAddr;
+ psOffsetStruct->ui32RefCount++;
+
+ eError = PVRSRV_OK;
+ goto exit_unlock;
+ }
+ }
+
+
+ *pui32UserVAddr = 0;
+
+ if (LinuxMemAreaUsesPhysicalMap(psLinuxMemArea))
+ {
+ *pui32MMapOffset = LinuxMemAreaToCpuPFN(psLinuxMemArea, 0);
+ PVR_ASSERT(PFNIsPhysical(*pui32MMapOffset));
+ }
+ else
+ {
+ *pui32MMapOffset = HandleToMMapOffset(hMHandle);
+ PVR_ASSERT(PFNIsSpecial(*pui32MMapOffset));
+ }
+
+ psOffsetStruct = CreateOffsetStruct(psLinuxMemArea, *pui32MMapOffset, *pui32RealByteSize);
+ if (psOffsetStruct == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto exit_unlock;
+ }
+
+
+ list_add_tail(&psOffsetStruct->sMMapItem, &g_sMMapOffsetStructList);
+
+ psOffsetStruct->bOnMMapList = IMG_TRUE;
+
+ psOffsetStruct->ui32RefCount++;
+
+ eError = PVRSRV_OK;
+
+exit_unlock:
+ mutex_unlock(&g_sMMapMutex);
+
+ return eError;
+}
+
+
+PVRSRV_ERROR
+PVRMMapReleaseMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hMHandle,
+ IMG_BOOL *pbMUnmap,
+ IMG_UINT32 *pui32RealByteSize,
+ IMG_UINT32 *pui32UserVAddr)
+{
+ LinuxMemArea *psLinuxMemArea;
+ PKV_OFFSET_STRUCT psOffsetStruct;
+ IMG_HANDLE hOSMemHandle;
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+
+ mutex_lock(&g_sMMapMutex);
+
+ PVR_ASSERT(PVRSRVGetMaxHandle(psPerProc->psHandleBase) <= MAX_MMAP_HANDLE);
+
+ eError = PVRSRVLookupOSMemHandle(psPerProc->psHandleBase, &hOSMemHandle, hMHandle);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Lookup of handle 0x%lx failed", __FUNCTION__, hMHandle));
+
+ goto exit_unlock;
+ }
+
+ psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+
+ list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
+ {
+ if (psOffsetStruct->ui32PID == ui32PID)
+ {
+ if (psOffsetStruct->ui32RefCount == 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Attempt to release mmap data with zero reference count for offset struct 0x%p, memory area 0x%p", __FUNCTION__, psOffsetStruct, psLinuxMemArea));
+ eError = PVRSRV_ERROR_GENERIC;
+ goto exit_unlock;
+ }
+
+ psOffsetStruct->ui32RefCount--;
+
+ *pbMUnmap = (IMG_BOOL)((psOffsetStruct->ui32RefCount == 0) && (psOffsetStruct->ui32UserVAddr != 0));
+
+ *pui32UserVAddr = (*pbMUnmap) ? psOffsetStruct->ui32UserVAddr : 0;
+ *pui32RealByteSize = (*pbMUnmap) ? psOffsetStruct->ui32RealByteSize : 0;
+
+ eError = PVRSRV_OK;
+ goto exit_unlock;
+ }
+ }
+
+
+ PVR_DPF((PVR_DBG_ERROR, "%s: Mapping data not found for handle 0x%lx (memory area 0x%p)", __FUNCTION__, hMHandle, psLinuxMemArea));
+
+ eError = PVRSRV_ERROR_GENERIC;
+
+exit_unlock:
+ mutex_unlock(&g_sMMapMutex);
+
+ return eError;
+}
+
+static inline PKV_OFFSET_STRUCT
+FindOffsetStructByOffset(IMG_UINT32 ui32Offset, IMG_UINT32 ui32RealByteSize)
+{
+ PKV_OFFSET_STRUCT psOffsetStruct;
+ IMG_UINT32 ui32TID = GetCurrentThreadID();
+ IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+
+ list_for_each_entry(psOffsetStruct, &g_sMMapOffsetStructList, sMMapItem)
+ {
+ if (ui32Offset == psOffsetStruct->ui32MMapOffset && ui32RealByteSize == psOffsetStruct->ui32RealByteSize && psOffsetStruct->ui32PID == ui32PID)
+ {
+
+ if (!PFNIsPhysical(ui32Offset) || psOffsetStruct->ui32TID == ui32TID)
+ {
+ return psOffsetStruct;
+ }
+ }
+ }
+
+ return IMG_NULL;
+}
+
+
+static IMG_BOOL
+DoMapToUser(LinuxMemArea *psLinuxMemArea,
+ struct vm_area_struct* ps_vma,
+ IMG_UINT32 ui32ByteOffset)
+{
+ IMG_UINT32 ui32ByteSize;
+
+ if (psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC)
+ {
+ return DoMapToUser(LinuxMemAreaRoot(psLinuxMemArea),
+ ps_vma,
+ psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset + ui32ByteOffset);
+ }
+
+
+ ui32ByteSize = ps_vma->vm_end - ps_vma->vm_start;
+ PVR_ASSERT(ADDR_TO_PAGE_OFFSET(ui32ByteSize) == 0);
+
+#if defined (__sparc__)
+
+#error "SPARC not supported"
+#endif
+
+ if (PFNIsPhysical(ps_vma->vm_pgoff))
+ {
+ IMG_INT result;
+
+ PVR_ASSERT(LinuxMemAreaPhysIsContig(psLinuxMemArea));
+ PVR_ASSERT(LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32ByteOffset) == ps_vma->vm_pgoff);
+
+
+ result = io_remap_pfn_range(ps_vma, ps_vma->vm_start, ps_vma->vm_pgoff, ui32ByteSize, ps_vma->vm_page_prot);
+
+ if(result == 0)
+ {
+ return IMG_TRUE;
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE, "%s: Failed to map contiguous physical address range (%d), trying non-contiguous path", __FUNCTION__, result));
+ }
+
+ {
+
+ IMG_UINT32 ulVMAPos;
+ IMG_UINT32 ui32ByteEnd = ui32ByteOffset + ui32ByteSize;
+ IMG_UINT32 ui32PA;
+
+
+ for(ui32PA = ui32ByteOffset; ui32PA < ui32ByteEnd; ui32PA += PAGE_SIZE)
+ {
+ IMG_UINT32 pfn = LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32PA);
+
+ if (!pfn_valid(pfn))
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: Error - PFN invalid: 0x%lx", __FUNCTION__, pfn));
+ return IMG_FALSE;
+ }
+ }
+
+
+ ulVMAPos = ps_vma->vm_start;
+ for(ui32PA = ui32ByteOffset; ui32PA < ui32ByteEnd; ui32PA += PAGE_SIZE)
+ {
+ IMG_UINT32 pfn;
+ struct page *psPage;
+ IMG_INT result;
+
+ pfn = LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32PA);
+ PVR_ASSERT(pfn_valid(pfn));
+
+ psPage = pfn_to_page(pfn);
+
+ result = vm_insert_page(ps_vma, ulVMAPos, psPage);
+ if(result != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: Error - vm_insert_page failed (%d)", __FUNCTION__, result));
+ return IMG_FALSE;
+ }
+ ulVMAPos += PAGE_SIZE;
+ }
+ }
+
+ return IMG_TRUE;
+}
+
+
+static IMG_VOID
+MMapVOpenNoLock(struct vm_area_struct* ps_vma)
+{
+ PKV_OFFSET_STRUCT psOffsetStruct = (PKV_OFFSET_STRUCT)ps_vma->vm_private_data;
+ PVR_ASSERT(psOffsetStruct != IMG_NULL)
+ psOffsetStruct->ui32Mapped++;
+ PVR_ASSERT(!psOffsetStruct->bOnMMapList);
+
+ if (psOffsetStruct->ui32Mapped > 1)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "%s: Offset structure 0x%p is being shared across processes (psOffsetStruct->ui32Mapped: %lu)", __FUNCTION__, psOffsetStruct, psOffsetStruct->ui32Mapped));
+ PVR_ASSERT((ps_vma->vm_flags & VM_DONTCOPY) == 0);
+ }
+
+}
+
+
+static void
+MMapVOpen(struct vm_area_struct* ps_vma)
+{
+ mutex_lock(&g_sMMapMutex);
+
+ MMapVOpenNoLock(ps_vma);
+
+ mutex_unlock(&g_sMMapMutex);
+}
+
+
+static IMG_VOID
+MMapVCloseNoLock(struct vm_area_struct* ps_vma)
+{
+ PKV_OFFSET_STRUCT psOffsetStruct = (PKV_OFFSET_STRUCT)ps_vma->vm_private_data;
+ PVR_ASSERT(psOffsetStruct != IMG_NULL)
+
+ PVR_ASSERT(!psOffsetStruct->bOnMMapList);
+ psOffsetStruct->ui32Mapped--;
+ if (psOffsetStruct->ui32Mapped == 0)
+ {
+ if (psOffsetStruct->ui32RefCount != 0)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "%s: psOffsetStruct 0x%p has non-zero reference count (ui32RefCount = %lu). User mode address of start of mapping: 0x%lx", __FUNCTION__, psOffsetStruct, psOffsetStruct->ui32RefCount, psOffsetStruct->ui32UserVAddr));
+ }
+
+ DestroyOffsetStruct(psOffsetStruct);
+ }
+
+ ps_vma->vm_private_data = NULL;
+
+}
+
+static void
+MMapVClose(struct vm_area_struct* ps_vma)
+{
+ mutex_lock(&g_sMMapMutex);
+
+ MMapVCloseNoLock(ps_vma);
+
+ mutex_unlock(&g_sMMapMutex);
+}
+
+
+static struct vm_operations_struct MMapIOOps =
+{
+ .open=MMapVOpen,
+ .close=MMapVClose
+};
+
+
+int
+PVRMMap(struct file* pFile, struct vm_area_struct* ps_vma)
+{
+ IMG_UINT32 ui32ByteSize;
+ PKV_OFFSET_STRUCT psOffsetStruct;
+ int iRetVal = 0;
+
+ PVR_UNREFERENCED_PARAMETER(pFile);
+
+ mutex_lock(&g_sMMapMutex);
+
+ ui32ByteSize = ps_vma->vm_end - ps_vma->vm_start;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "%s: Received mmap(2) request with ui32MMapOffset 0x%08lx,"
+ " and ui32ByteSize %ld(0x%08lx)",
+ __FUNCTION__,
+ ps_vma->vm_pgoff,
+ ui32ByteSize, ui32ByteSize));
+
+ psOffsetStruct = FindOffsetStructByOffset(ps_vma->vm_pgoff, ui32ByteSize);
+ if (psOffsetStruct == IMG_NULL)
+ {
+#if defined(SUPPORT_DRI_DRM)
+ mutex_unlock(&g_sMMapMutex);
+
+
+ return drm_mmap(pFile, ps_vma);
+#else
+ PVR_UNREFERENCED_PARAMETER(pFile);
+
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: Attempted to mmap unregistered area at vm_pgoff %ld",
+ __FUNCTION__, ps_vma->vm_pgoff));
+ iRetVal = -EINVAL;
+#endif
+ goto unlock_and_return;
+ }
+ list_del(&psOffsetStruct->sMMapItem);
+ psOffsetStruct->bOnMMapList = IMG_FALSE;
+
+
+ if (((ps_vma->vm_flags & VM_WRITE) != 0) &&
+ ((ps_vma->vm_flags & VM_SHARED) == 0))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Cannot mmap non-shareable writable areas", __FUNCTION__));
+ iRetVal = -EINVAL;
+ goto unlock_and_return;
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE, "%s: Mapped psLinuxMemArea 0x%p\n",
+ __FUNCTION__, psOffsetStruct->psLinuxMemArea));
+
+ ps_vma->vm_flags |= VM_RESERVED;
+ ps_vma->vm_flags |= VM_IO;
+
+
+ ps_vma->vm_flags |= VM_DONTEXPAND;
+
+
+ ps_vma->vm_flags |= VM_DONTCOPY;
+
+ ps_vma->vm_private_data = (void *)psOffsetStruct;
+
+ switch(psOffsetStruct->psLinuxMemArea->ui32AreaFlags & PVRSRV_HAP_CACHETYPE_MASK)
+ {
+ case PVRSRV_HAP_CACHED:
+
+ break;
+ case PVRSRV_HAP_WRITECOMBINE:
+ ps_vma->vm_page_prot = PGPROT_WC(ps_vma->vm_page_prot);
+ break;
+ case PVRSRV_HAP_UNCACHED:
+ ps_vma->vm_page_prot = PGPROT_UC(ps_vma->vm_page_prot);
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "%s: unknown cache type", __FUNCTION__));
+ iRetVal = -EINVAL;
+ goto unlock_and_return;
+ }
+
+
+ ps_vma->vm_ops = &MMapIOOps;
+
+ if(!DoMapToUser(psOffsetStruct->psLinuxMemArea, ps_vma, 0))
+ {
+ iRetVal = -EAGAIN;
+ goto unlock_and_return;
+ }
+
+ PVR_ASSERT(psOffsetStruct->ui32UserVAddr == 0)
+
+ psOffsetStruct->ui32UserVAddr = ps_vma->vm_start;
+
+
+ MMapVOpenNoLock(ps_vma);
+
+ PVR_DPF((PVR_DBG_MESSAGE, "%s: Mapped area at offset 0x%08lx\n",
+ __FUNCTION__, ps_vma->vm_pgoff));
+
+unlock_and_return:
+ if (iRetVal != 0 && psOffsetStruct != IMG_NULL)
+ {
+ DestroyOffsetStruct(psOffsetStruct);
+ }
+
+ mutex_unlock(&g_sMMapMutex);
+
+ return iRetVal;
+}
+
+
+
+
+PVRSRV_ERROR
+PVRMMapRegisterArea(LinuxMemArea *psLinuxMemArea)
+{
+ PVRSRV_ERROR eError;
+#if defined(DEBUG)
+ const IMG_CHAR *pszName = LinuxMemAreaTypeToString(LinuxMemAreaRootType(psLinuxMemArea));
+#endif
+
+ mutex_lock(&g_sMMapMutex);
+
+#if defined(DEBUG)
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "%s(%s, psLinuxMemArea 0x%p, ui32AllocFlags 0x%8lx)",
+ __FUNCTION__, pszName, psLinuxMemArea, psLinuxMemArea->ui32AreaFlags));
+#endif
+
+ PVR_ASSERT(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC || LinuxMemAreaRoot(psLinuxMemArea)->eAreaType != LINUX_MEM_AREA_SUB_ALLOC);
+
+
+ if(psLinuxMemArea->bMMapRegistered)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: psLinuxMemArea 0x%p is already registered",
+ __FUNCTION__, psLinuxMemArea));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto exit_unlock;
+ }
+
+ list_add_tail(&psLinuxMemArea->sMMapItem, &g_sMMapAreaList);
+
+ psLinuxMemArea->bMMapRegistered = IMG_TRUE;
+
+ eError = PVRSRV_OK;
+
+exit_unlock:
+ mutex_unlock(&g_sMMapMutex);
+
+ return eError;
+}
+
+
+PVRSRV_ERROR
+PVRMMapRemoveRegisteredArea(LinuxMemArea *psLinuxMemArea)
+{
+ PVRSRV_ERROR eError;
+ PKV_OFFSET_STRUCT psOffsetStruct, psTmpOffsetStruct;
+
+ mutex_lock(&g_sMMapMutex);
+
+ PVR_ASSERT(psLinuxMemArea->bMMapRegistered);
+
+ list_for_each_entry_safe(psOffsetStruct, psTmpOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
+ {
+ if (psOffsetStruct->ui32Mapped != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: psOffsetStruct 0x%p for memory area 0x0x%p is still mapped; psOffsetStruct->ui32Mapped %lu", __FUNCTION__, psOffsetStruct, psLinuxMemArea, psOffsetStruct->ui32Mapped));
+ eError = PVRSRV_ERROR_GENERIC;
+ goto exit_unlock;
+ }
+ else
+ {
+
+ PVR_DPF((PVR_DBG_WARNING, "%s: psOffsetStruct 0x%p was never mapped", __FUNCTION__, psOffsetStruct));
+ }
+
+ PVR_ASSERT((psOffsetStruct->ui32Mapped == 0) && psOffsetStruct->bOnMMapList);
+
+ DestroyOffsetStruct(psOffsetStruct);
+ }
+
+ list_del(&psLinuxMemArea->sMMapItem);
+
+ psLinuxMemArea->bMMapRegistered = IMG_FALSE;
+
+ eError = PVRSRV_OK;
+
+exit_unlock:
+ mutex_unlock(&g_sMMapMutex);
+ return eError;
+}
+
+
+PVRSRV_ERROR
+LinuxMMapPerProcessConnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc)
+{
+ PVR_UNREFERENCED_PARAMETER(psEnvPerProc);
+
+ return PVRSRV_OK;
+}
+
+IMG_VOID
+LinuxMMapPerProcessDisconnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc)
+{
+ PKV_OFFSET_STRUCT psOffsetStruct, psTmpOffsetStruct;
+ IMG_BOOL bWarn = IMG_FALSE;
+ IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+
+ PVR_UNREFERENCED_PARAMETER(psEnvPerProc);
+
+ mutex_lock(&g_sMMapMutex);
+
+ list_for_each_entry_safe(psOffsetStruct, psTmpOffsetStruct, &g_sMMapOffsetStructList, sMMapItem)
+ {
+ if (psOffsetStruct->ui32PID == ui32PID)
+ {
+ if (!bWarn)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "%s: process has unmapped offset structures. Removing them", __FUNCTION__));
+ bWarn = IMG_TRUE;
+ }
+ PVR_ASSERT(psOffsetStruct->ui32Mapped == 0);
+ PVR_ASSERT(psOffsetStruct->bOnMMapList);
+
+ DestroyOffsetStruct(psOffsetStruct);
+ }
+ }
+
+ mutex_unlock(&g_sMMapMutex);
+}
+
+
+PVRSRV_ERROR LinuxMMapPerProcessHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase)
+{
+ PVRSRV_ERROR eError;
+
+ eError = PVRSRVSetMaxHandle(psHandleBase, MAX_MMAP_HANDLE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: failed to set handle limit (%d)", __FUNCTION__, eError));
+ return eError;
+ }
+
+ return eError;
+}
+
+
+IMG_VOID
+PVRMMapInit(IMG_VOID)
+{
+ mutex_init(&g_sMMapMutex);
+
+ g_psMemmapCache = kmem_cache_create("img-mmap", sizeof(KV_OFFSET_STRUCT), 0, 0, NULL);
+ if (!g_psMemmapCache)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: failed to allocate kmem_cache", __FUNCTION__));
+ goto error;
+ }
+
+ return;
+
+error:
+ PVRMMapCleanup();
+ return;
+}
+
+
+IMG_VOID
+PVRMMapCleanup(IMG_VOID)
+{
+ PVRSRV_ERROR eError;
+
+ if (!list_empty(&g_sMMapAreaList))
+ {
+ LinuxMemArea *psLinuxMemArea, *psTmpMemArea;
+
+ PVR_DPF((PVR_DBG_ERROR, "%s: Memory areas are still registered with MMap", __FUNCTION__));
+
+ PVR_TRACE(("%s: Unregistering memory areas", __FUNCTION__));
+ list_for_each_entry_safe(psLinuxMemArea, psTmpMemArea, &g_sMMapAreaList, sMMapItem)
+ {
+ eError = PVRMMapRemoveRegisteredArea(psLinuxMemArea);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: PVRMMapRemoveRegisteredArea failed (%d)", __FUNCTION__, eError));
+ }
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ LinuxMemAreaDeepFree(psLinuxMemArea);
+ }
+ }
+ PVR_ASSERT(list_empty((&g_sMMapAreaList)));
+
+ if(g_psMemmapCache)
+ {
+ kmem_cache_destroy(g_psMemmapCache);
+ g_psMemmapCache = NULL;
+ }
+}
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#if !defined(__MMAP_H__)
+#define __MMAP_H__
+
+#include <linux/mm.h>
+#include <linux/list.h>
+
+#include "perproc.h"
+#include "mm.h"
+
+typedef struct KV_OFFSET_STRUCT_TAG
+{
+
+ IMG_UINT32 ui32Mapped;
+
+
+ IMG_UINT32 ui32MMapOffset;
+
+ IMG_UINT32 ui32RealByteSize;
+
+
+ LinuxMemArea *psLinuxMemArea;
+
+
+ IMG_UINT32 ui32TID;
+
+
+ IMG_UINT32 ui32PID;
+
+
+ IMG_BOOL bOnMMapList;
+
+
+ IMG_UINT32 ui32RefCount;
+
+
+ IMG_UINT32 ui32UserVAddr;
+
+
+ struct list_head sMMapItem;
+
+
+ struct list_head sAreaItem;
+}KV_OFFSET_STRUCT, *PKV_OFFSET_STRUCT;
+
+
+
+IMG_VOID PVRMMapInit(IMG_VOID);
+
+
+IMG_VOID PVRMMapCleanup(IMG_VOID);
+
+
+PVRSRV_ERROR PVRMMapRegisterArea(LinuxMemArea *psLinuxMemArea);
+
+
+PVRSRV_ERROR PVRMMapRemoveRegisteredArea(LinuxMemArea *psLinuxMemArea);
+
+
+PVRSRV_ERROR PVRMMapOSMemHandleToMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hMHandle,
+ IMG_UINT32 *pui32MMapOffset,
+ IMG_UINT32 *pui32ByteOffset,
+ IMG_UINT32 *pui32RealByteSize, IMG_UINT32 *pui32UserVAddr);
+
+PVRSRV_ERROR
+PVRMMapReleaseMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hMHandle,
+ IMG_BOOL *pbMUnmap,
+ IMG_UINT32 *pui32RealByteSize,
+ IMG_UINT32 *pui32UserVAddr);
+
+int PVRMMap(struct file* pFile, struct vm_area_struct* ps_vma);
+
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#if !defined(SUPPORT_DRI_DRM)
+
+ #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
+#endif
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <linux/mutex.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 "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
+#define DRVNAME "pvrsrvkm"
+#define DEVNAME "pvrsrvkm"
+
+#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);
+#ifdef DEBUG
+static IMG_INT debug = DBGPRIV_WARNING;
+#include <linux/moduleparam.h>
+module_param(debug, int, 0);
+#endif
+
+
+extern IMG_BOOL PVRGetDisplayClassJTable(PVRSRV_DC_DISP2SRV_KMJTABLE *psJTable);
+extern IMG_BOOL PVRGetBufferClassJTable(PVRSRV_BC_BUFFER2SRV_KMJTABLE *psJTable);
+
+/*EXPORT_SYMBOL(PVRGetDisplayClassJTable); */
+/*EXPORT_SYMBOL(PVRGetBufferClassJTable); */
+
+
+#if defined(PVR_LDM_MODULE)
+static struct class *psPvrClass;
+#endif
+
+#if !defined(SUPPORT_DRI_DRM)
+static IMG_INT AssignedMajorNumber;
+
+static IMG_INT PVRSRVOpen(struct inode* pInode, struct file* pFile);
+static IMG_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
+
+struct 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 IMG_INT PVRSRVDriverRemove(LDM_DEV *device);
+static IMG_INT PVRSRVDriverProbe(LDM_DEV *device);
+#endif
+#if defined(PVR_LDM_PCI_MODULE)
+static IMG_VOID PVRSRVDriverRemove(LDM_DEV *device);
+static IMG_INT PVRSRVDriverProbe(LDM_DEV *device, const struct pci_device_id *id);
+#endif
+static IMG_INT PVRSRVDriverSuspend(LDM_DEV *device, pm_message_t state);
+static IMG_VOID PVRSRVDriverShutdown(LDM_DEV *device);
+static IMG_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) },
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, powervr_id_table);
+#endif
+
+static LDM_DRV powervr_driver = {
+#if defined(PVR_LDM_PLATFORM_MODULE)
+ .driver = {
+ .name = DRVNAME,
+ },
+#endif
+#if defined(PVR_LDM_PCI_MODULE)
+ .name = DRVNAME,
+ .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)
+
+static IMG_VOID PVRSRVDeviceRelease(struct device *pDevice)
+{
+ PVR_UNREFERENCED_PARAMETER(pDevice);
+}
+
+static struct platform_device powervr_device = {
+ .name = DEVNAME,
+ .id = -1,
+ .dev = {
+ .release = PVRSRVDeviceRelease
+ }
+};
+
+#endif
+
+#if defined(PVR_LDM_PLATFORM_MODULE)
+static IMG_INT PVRSRVDriverProbe(LDM_DEV *pDevice)
+#endif
+#if defined(PVR_LDM_PCI_MODULE)
+static IMG_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
+
+ if (SysAcquireData(&psSysData) != PVRSRV_OK)
+ {
+ gpsPVRLDMDev = pDevice;
+
+ if (SysInitialise() != PVRSRV_OK)
+ {
+ return -ENODEV;
+ }
+ }
+
+ return 0;
+}
+
+
+#if defined (PVR_LDM_PLATFORM_MODULE)
+static IMG_INT PVRSRVDriverRemove(LDM_DEV *pDevice)
+#endif
+#if defined(PVR_LDM_PCI_MODULE)
+static IMG_VOID __devexit PVRSRVDriverRemove(LDM_DEV *pDevice)
+#endif
+{
+ SYS_DATA *psSysData;
+
+ PVR_TRACE(("PVRSRVDriverRemove(pDevice=%p)", pDevice));
+
+ if (SysAcquireData(&psSysData) == PVRSRV_OK)
+ {
+#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL)
+ if (gPVRPowerLevel != 0)
+ {
+ if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D0) == PVRSRV_OK)
+ {
+ gPVRPowerLevel = 0;
+ }
+ }
+#endif
+ 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
+}
+
+
+static IMG_VOID PVRSRVDriverShutdown(LDM_DEV *pDevice)
+{
+ PVR_TRACE(("PVRSRVDriverShutdown(pDevice=%p)", pDevice));
+
+ (IMG_VOID) PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D3);
+}
+
+#endif
+
+
+#if defined(PVR_LDM_MODULE) || defined(SUPPORT_DRI_DRM)
+#if defined(SUPPORT_DRI_DRM)
+IMG_INT PVRSRVDriverSuspend(struct drm_device *pDevice, pm_message_t state)
+#else
+static IMG_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));
+ printk(KERN_ALERT "PVRSRVDriverSuspend(pDevice=%p)", pDevice);
+
+ if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D3) != PVRSRV_OK)
+ {
+ return -EINVAL;
+ }
+#endif
+ return 0;
+}
+
+
+#if defined(SUPPORT_DRI_DRM)
+IMG_INT PVRSRVDriverResume(struct drm_device *pDevice)
+#else
+static IMG_INT PVRSRVDriverResume(LDM_DEV *pDevice)
+#endif
+{
+#if !(defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL) && !defined(SUPPORT_DRI_DRM))
+ PVR_TRACE(("PVRSRVDriverResume(pDevice=%p)", pDevice));
+ printk(KERN_ALERT "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);
+}
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+void ProcSeqShowPowerLevel(struct seq_file *sfile,void* el)
+{
+ seq_printf(sfile, "%lu\n", gPVRPowerLevel);
+}
+
+#else
+IMG_INT PVRProcGetPowerLevel(IMG_CHAR *page, IMG_CHAR **start, off_t off, IMG_INT count, IMG_INT *eof, IMG_VOID *data)
+{
+ if (off == 0) {
+ *start = (IMG_CHAR *)1;
+ return printAppend(page, count, 0, "%lu\n", gPVRPowerLevel);
+ }
+ *eof = 1;
+ return 0;
+}
+#endif
+
+#endif
+
+#if defined(SUPPORT_DRI_DRM)
+IMG_INT PVRSRVOpen(struct drm_device unref__ *dev, struct drm_file *pFile)
+#else
+static IMG_INT PVRSRVOpen(struct inode unref__ * pInode, struct file *pFile)
+#endif
+{
+ PVRSRV_FILE_PRIVATE_DATA *psPrivateData;
+ IMG_HANDLE hBlockAlloc;
+ IMG_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
+
+#if defined(SUPPORT_DRI_DRM)
+ PVR_UNREFERENCED_PARAMETER(dev);
+#else
+ PVR_UNREFERENCED_PARAMETER(pInode);
+#endif
+
+ mutex_lock(&gPVRSRVLock);
+
+ ui32PID = OSGetCurrentProcessIDKM();
+
+ if (PVRSRVProcessConnect(ui32PID) != 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(PVR_SECURE_FD_EXPORT)
+ 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:
+ mutex_unlock(&gPVRSRVLock);
+ return iRet;
+}
+
+
+#if defined(SUPPORT_DRI_DRM)
+IMG_INT PVRSRVRelease(struct drm_device unref__ *dev, struct drm_file *pFile)
+#else
+static IMG_INT PVRSRVRelease(struct inode unref__ * pInode, struct file *pFile)
+#endif
+{
+ PVRSRV_FILE_PRIVATE_DATA *psPrivateData;
+
+#if defined(SUPPORT_DRI_DRM)
+ PVR_UNREFERENCED_PARAMETER(dev);
+#else
+ PVR_UNREFERENCED_PARAMETER(pInode);
+#endif
+
+ mutex_lock(&gPVRSRVLock);
+
+ psPrivateData = PRIVATE_DATA(pFile);
+
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+ list_del(&psPrivateData->sDRMAuthListItem);
+#endif
+
+
+ gui32ReleasePID = psPrivateData->ui32OpenPID;
+ PVRSRVProcessDisconnect(psPrivateData->ui32OpenPID);
+ gui32ReleasePID = 0;
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_FILE_PRIVATE_DATA),
+ psPrivateData, psPrivateData->hBlockAlloc);
+ PRIVATE_DATA(pFile) = NULL;
+
+ mutex_unlock(&gPVRSRVLock);
+ return 0;
+}
+
+
+#if defined(SUPPORT_DRI_DRM)
+IMG_INT PVRCore_Init(IMG_VOID)
+#else
+static IMG_INT __init PVRCore_Init(IMG_VOID)
+#endif
+{
+ IMG_INT error;
+#if !defined(PVR_LDM_MODULE)
+ PVRSRV_ERROR eError;
+#else
+ struct device *psDev;
+#endif
+
+#if !defined(SUPPORT_DRI_DRM)
+
+ PVRDPFInit();
+#endif
+ PVR_TRACE(("PVRCore_Init"));
+
+ mutex_init(&gPVRSRVLock);
+
+#ifdef DEBUG
+ PVRDebugSetLevel(debug);
+#endif
+
+ if (CreateProcEntries ())
+ {
+ error = -ENOMEM;
+ return error;
+ }
+
+ if (PVROSFuncInit() != PVRSRV_OK)
+ {
+ error = -ENOMEM;
+ goto init_failed;
+ }
+
+ PVRLinuxMUtilsInit();
+
+ if (linux_mm_init())
+ {
+ error = -ENOMEM;
+ goto init_failed;
+ }
+
+ LinuxBridgeInit();
+
+ PVRMMapInit();
+
+#if defined(PVR_LDM_MODULE)
+
+#if defined(PVR_LDM_PLATFORM_MODULE)
+ 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)
+ 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
+
+#else
+
+ 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));
+#endif
+
+#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), NULL, 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
+
+ return 0;
+
+#if defined(PVR_LDM_MODULE)
+destroy_class:
+ class_destroy(psPvrClass);
+unregister_device:
+ unregister_chrdev((IMG_UINT)AssignedMajorNumber, DRVNAME);
+#endif
+#if !defined(SUPPORT_DRI_DRM)
+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)
+ platform_device_unregister(&powervr_device);
+#endif
+ platform_driver_unregister(&powervr_driver);
+#endif
+
+#else
+
+ {
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+ if (psSysData != IMG_NULL)
+ {
+ SysDeinitialise(psSysData);
+ }
+ }
+#endif
+init_failed:
+ PVRMMapCleanup();
+ linux_mm_cleanup();
+ LinuxBridgeDeInit();
+ PVROSFuncDeInit();
+ RemoveProcEntries();
+
+ return error;
+
+}
+
+
+#if defined(SUPPORT_DRI_DRM)
+IMG_VOID PVRCore_Cleanup(IMG_VOID)
+#else
+static IMG_VOID __exit PVRCore_Cleanup(IMG_VOID)
+#endif
+{
+ SYS_DATA *psSysData;
+
+ PVR_TRACE(("PVRCore_Cleanup"));
+
+ SysAcquireData(&psSysData);
+
+#if defined(PVR_LDM_MODULE)
+ device_destroy(psPvrClass, MKDEV(AssignedMajorNumber, 0));
+ class_destroy(psPvrClass);
+#endif
+
+#if !defined(SUPPORT_DRI_DRM)
+ unregister_chrdev((IMG_UINT)AssignedMajorNumber, DRVNAME);
+#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)
+ 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
+
+ SysDeinitialise(psSysData);
+#endif
+
+ PVRMMapCleanup();
+
+ linux_mm_cleanup();
+
+ LinuxBridgeDeInit();
+
+ PVROSFuncDeInit();
+
+ RemoveProcEntries();
+
+ PVR_TRACE(("PVRCore_Cleanup: unloading"));
+}
+
+#if !defined(SUPPORT_DRI_DRM)
+module_init(PVRCore_Init);
+module_exit(PVRCore_Cleanup);
+#endif
--- /dev/null
+/**********************************************************************
+ *
+ * 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/version.h>
+
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+#include "img_defs.h"
+#include "pvr_debug.h"
+#include "mutils.h"
+
+#if defined(SUPPORT_LINUX_X86_PAT)
+#define PAT_LINUX_X86_WC 1
+
+#define PAT_X86_ENTRY_BITS 8
+
+#define PAT_X86_BIT_PWT 1U
+#define PAT_X86_BIT_PCD 2U
+#define PAT_X86_BIT_PAT 4U
+#define PAT_X86_BIT_MASK (PAT_X86_BIT_PAT | PAT_X86_BIT_PCD | PAT_X86_BIT_PWT)
+
+static IMG_BOOL g_write_combining_available = IMG_FALSE;
+
+#define PROT_TO_PAT_INDEX(v, B) ((v & _PAGE_ ## B) ? PAT_X86_BIT_ ## B : 0)
+
+static inline IMG_UINT
+pvr_pat_index(pgprotval_t prot_val)
+{
+ IMG_UINT ret = 0;
+ pgprotval_t val = prot_val & _PAGE_CACHE_MASK;
+
+ ret |= PROT_TO_PAT_INDEX(val, PAT);
+ ret |= PROT_TO_PAT_INDEX(val, PCD);
+ ret |= PROT_TO_PAT_INDEX(val, PWT);
+
+ return ret;
+}
+
+static inline IMG_UINT
+pvr_pat_entry(u64 pat, IMG_UINT index)
+{
+ return (IMG_UINT)(pat >> (index * PAT_X86_ENTRY_BITS)) & PAT_X86_BIT_MASK;
+}
+
+static IMG_VOID
+PVRLinuxX86PATProbe(IMG_VOID)
+{
+
+ if (cpu_has_pat)
+ {
+ u64 pat;
+ IMG_UINT pat_index;
+ IMG_UINT pat_entry;
+
+ PVR_TRACE(("%s: PAT available", __FUNCTION__));
+
+ rdmsrl(MSR_IA32_CR_PAT, pat);
+ PVR_TRACE(("%s: Top 32 bits of PAT: 0x%.8x", __FUNCTION__, (IMG_UINT)(pat >> 32)));
+ PVR_TRACE(("%s: Bottom 32 bits of PAT: 0x%.8x", __FUNCTION__, (IMG_UINT)(pat)));
+
+ pat_index = pvr_pat_index(_PAGE_CACHE_WC);
+ PVR_TRACE(("%s: PAT index for write combining: %u", __FUNCTION__, pat_index));
+
+ pat_entry = pvr_pat_entry(pat, pat_index);
+ PVR_TRACE(("%s: PAT entry for write combining: 0x%.2x (should be 0x%.2x)", __FUNCTION__, pat_entry, PAT_LINUX_X86_WC));
+
+#if defined(SUPPORT_LINUX_X86_WRITECOMBINE)
+ g_write_combining_available = (IMG_BOOL)(pat_entry == PAT_LINUX_X86_WC);
+#endif
+ }
+#if defined(DEBUG)
+#if defined(SUPPORT_LINUX_X86_WRITECOMBINE)
+ if (g_write_combining_available)
+ {
+ PVR_TRACE(("%s: Write combining available via PAT", __FUNCTION__));
+ }
+ else
+ {
+ PVR_TRACE(("%s: Write combining not available", __FUNCTION__));
+ }
+#else
+ PVR_TRACE(("%s: Write combining disabled in driver build", __FUNCTION__));
+#endif
+#endif
+}
+
+pgprot_t
+pvr_pgprot_writecombine(pgprot_t prot)
+{
+
+
+ return (g_write_combining_available) ?
+ __pgprot((pgprot_val(prot) & ~_PAGE_CACHE_MASK) | _PAGE_CACHE_WC) : pgprot_noncached(prot);
+}
+#endif
+
+IMG_VOID
+PVRLinuxMUtilsInit(IMG_VOID)
+{
+#if defined(SUPPORT_LINUX_X86_PAT)
+ PVRLinuxX86PATProbe();
+#endif
+}
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef __IMG_LINUX_MUTILS_H__
+#define __IMG_LINUX_MUTILS_H__
+
+#include <linux/version.h>
+
+#if !(defined(__i386__))
+#if defined(SUPPORT_LINUX_X86_PAT)
+#undef SUPPORT_LINUX_X86_PAT
+#endif
+#endif
+
+#if defined(SUPPORT_LINUX_X86_PAT)
+ pgprot_t pvr_pgprot_writecombine(pgprot_t prot);
+ #define PGPROT_WC(pv) pvr_pgprot_writecombine(pv)
+#else
+ #if defined(__arm__) || defined(__sh__)
+ #define PGPROT_WC(pv) pgprot_writecombine(pv)
+ #else
+ #if defined(__i386__)
+ #define PGPROT_WC(pv) pgprot_noncached(pv)
+ #else
+ #define PGPROT_WC(pv) pgprot_noncached(pv)
+ #error Unsupported architecture!
+ #endif
+ #endif
+#endif
+
+#define PGPROT_UC(pv) pgprot_noncached(pv)
+
+#if defined(__i386__)
+ #define IOREMAP(pa, bytes) ioremap_cache(pa, bytes)
+#else
+ #if defined(__arm__)
+ #define IOREMAP(pa, bytes) ioremap_cached(pa, bytes)
+ #else
+ #define IOREMAP(pa, bytes) ioremap(pa, bytes)
+ #endif
+#endif
+
+#if defined(SUPPORT_LINUX_X86_PAT)
+ #if defined(SUPPORT_LINUX_X86_WRITECOMBINE)
+ #define IOREMAP_WC(pa, bytes) ioremap_wc(pa, bytes)
+ #else
+ #define IOREMAP_WC(pa, bytes) ioremap_nocache(pa, bytes)
+ #endif
+#else
+ #if defined(__arm__)
+ #define IOREMAP_WC(pa, bytes) ioremap_wc(pa, bytes)
+ #else
+ #define IOREMAP_WC(pa, bytes) ioremap_nocache(pa, bytes)
+ #endif
+#endif
+
+#define IOREMAP_UC(pa, bytes) ioremap_nocache(pa, bytes)
+
+IMG_VOID PVRLinuxMUtilsInit(IMG_VOID);
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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/version.h>
+#include <asm/io.h>
+#include <asm/page.h>
+#include <asm/system.h>
+#if defined(SUPPORT_CPU_CACHED_BUFFERS)
+#include <asm/cacheflush.h>
+#endif
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/hugetlb.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <asm/hardirq.h>
+#include <linux/timer.h>
+#include <linux/capability.h>
+#include <asm/uaccess.h>
+#include <linux/spinlock.h>
+#if defined(PVR_LINUX_MISR_USING_WORKQUEUE) || \
+ defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE) || \
+ defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || \
+ defined(PVR_LINUX_USING_WORKQUEUES)
+#include <linux/workqueue.h>
+#endif
+
+#include "img_types.h"
+#include "services_headers.h"
+#include "mm.h"
+#include "pvrmmap.h"
+#include "mmap.h"
+#include "env_data.h"
+#include "proc.h"
+#include "event.h"
+#include "linkage.h"
+
+#define EVENT_OBJECT_TIMEOUT_MS (100)
+
+#if defined(SUPPORT_CPU_CACHED_BUFFERS) || \
+ defined(SUPPORT_CACHEFLUSH_ON_ALLOC)
+
+#if defined(__i386__)
+static void per_cpu_cache_flush(void *arg)
+{
+ PVR_UNREFERENCED_PARAMETER(arg);
+ wbinvd();
+}
+#endif
+
+#if !defined(SUPPORT_CPU_CACHED_BUFFERS)
+static
+#endif
+IMG_VOID OSFlushCPUCacheKM(IMG_VOID)
+{
+#if defined(__arm__)
+ flush_cache_all();
+#elif defined(__i386__)
+
+ on_each_cpu(per_cpu_cache_flush, NULL, 1);
+#else
+#error "Implement full CPU cache flush for this CPU!"
+#endif
+}
+
+#endif
+#if defined(SUPPORT_CPU_CACHED_BUFFERS)
+
+IMG_VOID OSFlushCPUCacheRangeKM(IMG_VOID *pvRangeAddrStart,
+ IMG_VOID *pvRangeAddrEnd)
+{
+ PVR_UNREFERENCED_PARAMETER(pvRangeAddrStart);
+ PVR_UNREFERENCED_PARAMETER(pvRangeAddrEnd);
+
+
+ OSFlushCPUCacheKM();
+}
+
+#endif
+
+#define HOST_ALLOC_MEM_USING_KMALLOC ((IMG_HANDLE)0)
+#define HOST_ALLOC_MEM_USING_VMALLOC ((IMG_HANDLE)1)
+
+PVRSRV_ERROR OSAllocMem_Impl(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_PVOID *ppvCpuVAddr, IMG_HANDLE *phBlockAlloc)
+{
+ PVR_UNREFERENCED_PARAMETER(ui32Flags);
+
+ *ppvCpuVAddr = kmalloc(ui32Size, GFP_KERNEL);
+
+ if(*ppvCpuVAddr)
+ {
+ if (phBlockAlloc)
+ {
+
+ *phBlockAlloc = HOST_ALLOC_MEM_USING_KMALLOC;
+ }
+ }
+ else
+ {
+ if (!phBlockAlloc)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+
+ *ppvCpuVAddr = vmalloc_wrapper(ui32Size, PVRSRV_HAP_CACHED);
+ if (!*ppvCpuVAddr)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+
+ *phBlockAlloc = HOST_ALLOC_MEM_USING_VMALLOC;
+ }
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSFreeMem_Impl(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_PVOID pvCpuVAddr, IMG_HANDLE hBlockAlloc)
+{
+ PVR_UNREFERENCED_PARAMETER(ui32Flags);
+ PVR_UNREFERENCED_PARAMETER(ui32Size);
+
+ if (hBlockAlloc == HOST_ALLOC_MEM_USING_VMALLOC)
+ {
+ vfree(pvCpuVAddr);
+ }
+ else
+ {
+ kfree(pvCpuVAddr);
+ }
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR
+OSAllocPages_Impl(IMG_UINT32 ui32AllocFlags,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32PageSize,
+ IMG_VOID **ppvCpuVAddr,
+ IMG_HANDLE *phOSMemHandle)
+{
+ LinuxMemArea *psLinuxMemArea;
+
+ PVR_UNREFERENCED_PARAMETER(ui32PageSize);
+
+#if 0
+
+ if(ui32AllocFlags & PVRSRV_HAP_SINGLE_PROCESS)
+ {
+ ui32AllocFlags &= ~PVRSRV_HAP_SINGLE_PROCESS;
+ ui32AllocFlags |= PVRSRV_HAP_MULTI_PROCESS;
+ }
+#endif
+
+ switch(ui32AllocFlags & PVRSRV_HAP_MAPTYPE_MASK)
+ {
+ case PVRSRV_HAP_KERNEL_ONLY:
+ {
+ psLinuxMemArea = vmalloc_linux_mem_area(ui32Size, ui32AllocFlags);
+ if(!psLinuxMemArea)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ break;
+ }
+ case PVRSRV_HAP_SINGLE_PROCESS:
+ {
+
+
+ psLinuxMemArea = alloc_pages_linux_mem_area(ui32Size, ui32AllocFlags);
+ if(!psLinuxMemArea)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ PVRMMapRegisterArea(psLinuxMemArea);
+ break;
+ }
+
+ case PVRSRV_HAP_MULTI_PROCESS:
+ {
+
+#if defined(VIVT_CACHE) || defined(__sh__)
+
+ ui32AllocFlags &= ~PVRSRV_HAP_CACHED;
+#endif
+ psLinuxMemArea = vmalloc_linux_mem_area(ui32Size, ui32AllocFlags);
+ if(!psLinuxMemArea)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ PVRMMapRegisterArea(psLinuxMemArea);
+ break;
+ }
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "OSAllocPages: invalid flags 0x%x\n", ui32AllocFlags));
+ *ppvCpuVAddr = NULL;
+ *phOSMemHandle = (IMG_HANDLE)0;
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+#if defined(SUPPORT_CACHEFLUSH_ON_ALLOC)
+
+ if(ui32AllocFlags & (PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_UNCACHED))
+ {
+ OSFlushCPUCacheKM();
+ }
+#endif
+
+ *ppvCpuVAddr = LinuxMemAreaToCpuVAddr(psLinuxMemArea);
+ *phOSMemHandle = psLinuxMemArea;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR
+OSFreePages(IMG_UINT32 ui32AllocFlags, IMG_UINT32 ui32Bytes, IMG_VOID *pvCpuVAddr, IMG_HANDLE hOSMemHandle)
+{
+ LinuxMemArea *psLinuxMemArea;
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+ PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+
+ psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+ switch(ui32AllocFlags & PVRSRV_HAP_MAPTYPE_MASK)
+ {
+ case PVRSRV_HAP_KERNEL_ONLY:
+ break;
+ case PVRSRV_HAP_SINGLE_PROCESS:
+ case PVRSRV_HAP_MULTI_PROCESS:
+ if(PVRMMapRemoveRegisteredArea(psLinuxMemArea) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSFreePages(ui32AllocFlags=0x%08X, ui32Bytes=%ld, "
+ "pvCpuVAddr=%p, hOSMemHandle=%p) FAILED!",
+ ui32AllocFlags, ui32Bytes, pvCpuVAddr, hOSMemHandle));
+ return PVRSRV_ERROR_GENERIC;
+ }
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR,"%s: invalid flags 0x%x\n",
+ __FUNCTION__, ui32AllocFlags));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ LinuxMemAreaDeepFree(psLinuxMemArea);
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR
+OSGetSubMemHandle(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32ByteOffset,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE *phOSMemHandleRet)
+{
+ LinuxMemArea *psParentLinuxMemArea, *psLinuxMemArea;
+ PVRSRV_ERROR eError;
+
+ psParentLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+ psLinuxMemArea = NewSubLinuxMemArea(psParentLinuxMemArea, ui32ByteOffset, ui32Bytes);
+ if(!psLinuxMemArea)
+ {
+ *phOSMemHandleRet = NULL;
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ *phOSMemHandleRet = psLinuxMemArea;
+
+
+ if(ui32Flags & PVRSRV_HAP_KERNEL_ONLY)
+ {
+ return PVRSRV_OK;
+ }
+
+ eError = PVRMMapRegisterArea(psLinuxMemArea);
+ if(eError != PVRSRV_OK)
+ {
+ goto failed_register_area;
+ }
+
+ return PVRSRV_OK;
+
+failed_register_area:
+ *phOSMemHandleRet = NULL;
+ LinuxMemAreaDeepFree(psLinuxMemArea);
+ return eError;
+}
+
+PVRSRV_ERROR
+OSReleaseSubMemHandle(IMG_VOID *hOSMemHandle, IMG_UINT32 ui32Flags)
+{
+ LinuxMemArea *psLinuxMemArea;
+ PVRSRV_ERROR eError;
+
+ psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+ PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC);
+
+ if((ui32Flags & PVRSRV_HAP_KERNEL_ONLY) == 0)
+ {
+ eError = PVRMMapRemoveRegisteredArea(psLinuxMemArea);
+ if(eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+ LinuxMemAreaDeepFree(psLinuxMemArea);
+
+ return PVRSRV_OK;
+}
+
+
+IMG_CPU_PHYADDR
+OSMemHandleToCpuPAddr(IMG_VOID *hOSMemHandle, IMG_UINT32 ui32ByteOffset)
+{
+ IMG_CPU_PHYADDR cpu_addr;
+ BUG_ON(!hOSMemHandle);
+
+ memset(&cpu_addr, 0, sizeof(cpu_addr));
+
+ cpu_addr.uiAddr = LinuxMemAreaToCpuPAddr(hOSMemHandle, ui32ByteOffset);
+
+ return cpu_addr;
+}
+
+
+
+IMG_VOID OSMemCopy(IMG_VOID *pvDst, IMG_VOID *pvSrc, IMG_UINT32 ui32Size)
+{
+#if defined(USE_UNOPTIMISED_MEMCPY)
+ IMG_UINT8 *Src,*Dst;
+ IMG_INT i;
+
+ Src=(IMG_UINT8 *)pvSrc;
+ Dst=(IMG_UINT8 *)pvDst;
+ for(i=0;i<ui32Size;i++)
+ {
+ Dst[i]=Src[i];
+ }
+#else
+ memcpy(pvDst, pvSrc, ui32Size);
+#endif
+}
+
+
+IMG_VOID OSMemSet(IMG_VOID *pvDest, IMG_UINT8 ui8Value, IMG_UINT32 ui32Size)
+{
+#if defined(USE_UNOPTIMISED_MEMSET)
+ IMG_UINT8 *Buff;
+ IMG_INT i;
+
+ Buff=(IMG_UINT8 *)pvDest;
+ for(i=0;i<ui32Size;i++)
+ {
+ Buff[i]=ui8Value;
+ }
+#else
+ memset(pvDest, (IMG_INT) ui8Value, (size_t) ui32Size);
+#endif
+}
+
+
+IMG_CHAR *OSStringCopy(IMG_CHAR *pszDest, const IMG_CHAR *pszSrc)
+{
+ return (strcpy(pszDest, pszSrc));
+}
+
+IMG_INT32 OSSNPrintf(IMG_CHAR *pStr, IMG_UINT32 ui32Size, const IMG_CHAR *pszFormat, ...)
+{
+ va_list argList;
+ IMG_INT32 iCount;
+
+ va_start(argList, pszFormat);
+ iCount = vsnprintf(pStr, (size_t)ui32Size, pszFormat, argList);
+ va_end(argList);
+
+ return iCount;
+}
+
+IMG_VOID OSBreakResourceLock (PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID)
+{
+ volatile IMG_UINT32 *pui32Access = (volatile IMG_UINT32 *)&psResource->ui32Lock;
+
+ if(*pui32Access)
+ {
+ if(psResource->ui32ID == ui32ID)
+ {
+ psResource->ui32ID = 0;
+ *pui32Access = 0;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"OSBreakResourceLock: Resource is not locked for this process."));
+ }
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"OSBreakResourceLock: Resource is not locked"));
+ }
+}
+
+
+PVRSRV_ERROR OSCreateResource(PVRSRV_RESOURCE *psResource)
+{
+ psResource->ui32ID = 0;
+ psResource->ui32Lock = 0;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSDestroyResource (PVRSRV_RESOURCE *psResource)
+{
+ OSBreakResourceLock (psResource, psResource->ui32ID);
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSInitEnvData(IMG_PVOID *ppvEnvSpecificData)
+{
+ ENV_DATA *psEnvData;
+
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(ENV_DATA), (IMG_VOID **)&psEnvData, IMG_NULL,
+ "Environment Data") != PVRSRV_OK)
+ {
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, PVRSRV_MAX_BRIDGE_IN_SIZE + PVRSRV_MAX_BRIDGE_OUT_SIZE,
+ &psEnvData->pvBridgeData, IMG_NULL,
+ "Bridge Data") != PVRSRV_OK)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(ENV_DATA), psEnvData, IMG_NULL);
+
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+
+
+ psEnvData->bMISRInstalled = IMG_FALSE;
+ psEnvData->bLISRInstalled = IMG_FALSE;
+
+
+ *ppvEnvSpecificData = psEnvData;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSDeInitEnvData(IMG_PVOID pvEnvSpecificData)
+{
+ ENV_DATA *psEnvData = (ENV_DATA*)pvEnvSpecificData;
+
+ PVR_ASSERT(!psEnvData->bMISRInstalled);
+ PVR_ASSERT(!psEnvData->bLISRInstalled);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, PVRSRV_MAX_BRIDGE_IN_SIZE + PVRSRV_MAX_BRIDGE_OUT_SIZE, psEnvData->pvBridgeData, IMG_NULL);
+ psEnvData->pvBridgeData = IMG_NULL;
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(ENV_DATA), pvEnvSpecificData, IMG_NULL);
+
+
+ return PVRSRV_OK;
+}
+
+
+
+IMG_VOID OSReleaseThreadQuanta(IMG_VOID)
+{
+ schedule();
+}
+
+
+
+IMG_UINT32 OSClockus(IMG_VOID)
+{
+ IMG_UINT32 time, j = jiffies;
+
+ time = j * (1000000 / HZ);
+
+ return time;
+}
+
+
+
+IMG_VOID OSWaitus(IMG_UINT32 ui32Timeus)
+{
+ udelay(ui32Timeus);
+}
+
+
+IMG_UINT32 OSGetCurrentProcessIDKM(IMG_VOID)
+{
+ if (in_interrupt())
+ {
+ return KERNEL_ID;
+ }
+
+ return (IMG_UINT32)task_tgid_nr(current);
+}
+
+
+IMG_UINT32 OSGetPageSize(IMG_VOID)
+{
+#if defined(__sh__)
+ IMG_UINT32 ui32ReturnValue = PAGE_SIZE;
+
+ return (ui32ReturnValue);
+#else
+ return PAGE_SIZE;
+#endif
+}
+
+static irqreturn_t DeviceISRWrapper(int irq, void *dev_id
+ )
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ IMG_BOOL bStatus = IMG_FALSE;
+
+ PVR_UNREFERENCED_PARAMETER(irq);
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE*)dev_id;
+ if(!psDeviceNode)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "DeviceISRWrapper: invalid params\n"));
+ goto out;
+ }
+
+ bStatus = PVRSRVDeviceLISR(psDeviceNode);
+
+ if (bStatus)
+ {
+ OSScheduleMISR((IMG_VOID *)psDeviceNode->psSysData);
+ }
+
+out:
+ return bStatus ? IRQ_HANDLED : IRQ_NONE;
+}
+
+
+
+static irqreturn_t SystemISRWrapper(int irq, void *dev_id)
+{
+ SYS_DATA *psSysData;
+ IMG_BOOL bStatus = IMG_FALSE;
+
+ PVR_UNREFERENCED_PARAMETER(irq);
+
+ psSysData = (SYS_DATA *)dev_id;
+ if(!psSysData)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SystemISRWrapper: invalid params\n"));
+ goto out;
+ }
+
+ bStatus = PVRSRVSystemLISR(psSysData);
+
+ if (bStatus)
+ {
+ OSScheduleMISR((IMG_VOID *)psSysData);
+ }
+
+out:
+ return bStatus ? IRQ_HANDLED : IRQ_NONE;
+}
+PVRSRV_ERROR OSInstallDeviceLISR(IMG_VOID *pvSysData,
+ IMG_UINT32 ui32Irq,
+ IMG_CHAR *pszISRName,
+ IMG_VOID *pvDeviceNode)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (psEnvData->bLISRInstalled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSInstallDeviceLISR: An ISR has already been installed: IRQ %d cookie %x", psEnvData->ui32IRQ, psEnvData->pvISRCookie));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ PVR_TRACE(("Installing device LISR %s on IRQ %d with cookie %x", pszISRName, ui32Irq, pvDeviceNode));
+
+ if(request_irq(ui32Irq, DeviceISRWrapper, IRQF_SHARED, pszISRName, pvDeviceNode))
+ {
+ PVR_DPF((PVR_DBG_ERROR,"OSInstallDeviceLISR: Couldn't install device LISR on IRQ %d", ui32Irq));
+
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ psEnvData->ui32IRQ = ui32Irq;
+ psEnvData->pvISRCookie = pvDeviceNode;
+ psEnvData->bLISRInstalled = IMG_TRUE;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSUninstallDeviceLISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (!psEnvData->bLISRInstalled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSUninstallDeviceLISR: No LISR has been installed"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ PVR_TRACE(("Uninstalling device LISR on IRQ %d with cookie %x", psEnvData->ui32IRQ, psEnvData->pvISRCookie));
+
+ free_irq(psEnvData->ui32IRQ, psEnvData->pvISRCookie);
+
+ psEnvData->bLISRInstalled = IMG_FALSE;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSInstallSystemLISR(IMG_VOID *pvSysData, IMG_UINT32 ui32Irq)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (psEnvData->bLISRInstalled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSInstallSystemLISR: An LISR has already been installed: IRQ %d cookie %x", psEnvData->ui32IRQ, psEnvData->pvISRCookie));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ PVR_TRACE(("Installing system LISR on IRQ %d with cookie %x", ui32Irq, pvSysData));
+
+ if(request_irq(ui32Irq, SystemISRWrapper, IRQF_SHARED, "PowerVR", pvSysData))
+ {
+ PVR_DPF((PVR_DBG_ERROR,"OSInstallSystemLISR: Couldn't install system LISR on IRQ %d", ui32Irq));
+
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ psEnvData->ui32IRQ = ui32Irq;
+ psEnvData->pvISRCookie = pvSysData;
+ psEnvData->bLISRInstalled = IMG_TRUE;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSUninstallSystemLISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (!psEnvData->bLISRInstalled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSUninstallSystemLISR: No LISR has been installed"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ PVR_TRACE(("Uninstalling system LISR on IRQ %d with cookie %x", psEnvData->ui32IRQ, psEnvData->pvISRCookie));
+
+ free_irq(psEnvData->ui32IRQ, psEnvData->pvISRCookie);
+
+ psEnvData->bLISRInstalled = IMG_FALSE;
+
+ return PVRSRV_OK;
+}
+
+#if defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE)
+static void MISRWrapper(struct work_struct *data)
+{
+ ENV_DATA *psEnvData = container_of(data, ENV_DATA, sMISRWork);
+ SYS_DATA *psSysData = (SYS_DATA *)psEnvData->pvMISRData;
+
+ PVRSRVMISR(psSysData);
+}
+
+
+PVRSRV_ERROR OSInstallMISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (psEnvData->bMISRInstalled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSInstallMISR: An MISR has already been installed"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ PVR_TRACE(("Installing MISR with cookie %p", pvSysData));
+
+ psEnvData->psWorkQueue = create_singlethread_workqueue("pvr_workqueue");
+
+ if (psEnvData->psWorkQueue == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSInstallMISR: create_singlethreaded_workqueue failed"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ INIT_WORK(&psEnvData->sMISRWork, MISRWrapper);
+
+ psEnvData->pvMISRData = pvSysData;
+ psEnvData->bMISRInstalled = IMG_TRUE;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSUninstallMISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (!psEnvData->bMISRInstalled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSUninstallMISR: No MISR has been installed"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ PVR_TRACE(("Uninstalling MISR"));
+
+ destroy_workqueue(psEnvData->psWorkQueue);
+
+ psEnvData->bMISRInstalled = IMG_FALSE;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSScheduleMISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA*)psSysData->pvEnvSpecificData;
+
+ if (psEnvData->bMISRInstalled)
+ {
+ queue_work(psEnvData->psWorkQueue, &psEnvData->sMISRWork);
+ }
+
+ return PVRSRV_OK;
+}
+#else
+#if defined(PVR_LINUX_MISR_USING_WORKQUEUE)
+static void MISRWrapper(struct work_struct *data)
+{
+ ENV_DATA *psEnvData = container_of(data, ENV_DATA, sMISRWork);
+ SYS_DATA *psSysData = (SYS_DATA *)psEnvData->pvMISRData;
+
+ PVRSRVMISR(psSysData);
+}
+
+
+PVRSRV_ERROR OSInstallMISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (psEnvData->bMISRInstalled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSInstallMISR: An MISR has already been installed"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ PVR_TRACE(("Installing MISR with cookie %x", pvSysData));
+
+ INIT_WORK(&psEnvData->sMISRWork, MISRWrapper);
+
+ psEnvData->pvMISRData = pvSysData;
+ psEnvData->bMISRInstalled = IMG_TRUE;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSUninstallMISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (!psEnvData->bMISRInstalled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSUninstallMISR: No MISR has been installed"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ PVR_TRACE(("Uninstalling MISR"));
+
+ flush_scheduled_work();
+
+ psEnvData->bMISRInstalled = IMG_FALSE;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSScheduleMISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA*)psSysData->pvEnvSpecificData;
+
+ if (psEnvData->bMISRInstalled)
+ {
+ schedule_work(&psEnvData->sMISRWork);
+ }
+
+ return PVRSRV_OK;
+}
+
+#else
+
+
+static void MISRWrapper(unsigned long data)
+{
+ SYS_DATA *psSysData;
+
+ psSysData = (SYS_DATA *)data;
+
+ PVRSRVMISR(psSysData);
+}
+
+
+PVRSRV_ERROR OSInstallMISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (psEnvData->bMISRInstalled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSInstallMISR: An MISR has already been installed"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ PVR_TRACE(("Installing MISR with cookie %x", pvSysData));
+
+ tasklet_init(&psEnvData->sMISRTasklet, MISRWrapper, (unsigned long)pvSysData);
+
+ psEnvData->bMISRInstalled = IMG_TRUE;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSUninstallMISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (!psEnvData->bMISRInstalled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSUninstallMISR: No MISR has been installed"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ PVR_TRACE(("Uninstalling MISR"));
+
+ tasklet_kill(&psEnvData->sMISRTasklet);
+
+ psEnvData->bMISRInstalled = IMG_FALSE;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSScheduleMISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA*)psSysData->pvEnvSpecificData;
+
+ if (psEnvData->bMISRInstalled)
+ {
+ tasklet_schedule(&psEnvData->sMISRTasklet);
+ }
+
+ return PVRSRV_OK;
+}
+
+#endif
+#endif
+
+
+IMG_VOID OSPanic(IMG_VOID)
+{
+ BUG();
+}
+
+#define OS_TAS(p) xchg((p), 1)
+PVRSRV_ERROR OSLockResource ( PVRSRV_RESOURCE *psResource,
+ IMG_UINT32 ui32ID)
+
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if(!OS_TAS(&psResource->ui32Lock))
+ psResource->ui32ID = ui32ID;
+ else
+ eError = PVRSRV_ERROR_GENERIC;
+
+ return eError;
+}
+
+
+PVRSRV_ERROR OSUnlockResource (PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID)
+{
+ volatile IMG_UINT32 *pui32Access = (volatile IMG_UINT32 *)&psResource->ui32Lock;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if(*pui32Access)
+ {
+ if(psResource->ui32ID == ui32ID)
+ {
+ psResource->ui32ID = 0;
+ *pui32Access = 0;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,"OSUnlockResource: Resource %p is not locked with expected value.", psResource));
+ PVR_DPF((PVR_DBG_MESSAGE,"Should be %x is actually %x", ui32ID, psResource->ui32ID));
+ eError = PVRSRV_ERROR_GENERIC;
+ }
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,"OSUnlockResource: Resource %p is not locked", psResource));
+ eError = PVRSRV_ERROR_GENERIC;
+ }
+
+ return eError;
+}
+
+
+IMG_BOOL OSIsResourceLocked (PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID)
+{
+ volatile IMG_UINT32 *pui32Access = (volatile IMG_UINT32 *)&psResource->ui32Lock;
+
+ return (*(volatile IMG_UINT32 *)pui32Access == 1) && (psResource->ui32ID == ui32ID)
+ ? IMG_TRUE
+ : IMG_FALSE;
+}
+
+
+IMG_CPU_PHYADDR OSMapLinToCPUPhys(IMG_VOID *pvLinAddr)
+{
+ IMG_CPU_PHYADDR CpuPAddr;
+
+ CpuPAddr.uiAddr = (IMG_UINTPTR_T)VMallocToPhys(pvLinAddr);
+
+ return CpuPAddr;
+}
+
+
+IMG_VOID *
+OSMapPhysToLin(IMG_CPU_PHYADDR BasePAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32MappingFlags,
+ IMG_HANDLE *phOSMemHandle)
+{
+ if(phOSMemHandle)
+ {
+ *phOSMemHandle = (IMG_HANDLE)0;
+ }
+
+ if(ui32MappingFlags & PVRSRV_HAP_KERNEL_ONLY)
+ {
+ IMG_VOID *pvIORemapCookie;
+ pvIORemapCookie = ioremap_wrapper(BasePAddr.uiAddr, ui32Bytes, ui32MappingFlags);
+ if(pvIORemapCookie == IMG_NULL)
+ {
+ return NULL;
+ }
+ return pvIORemapCookie;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSMapPhysToLin should only be used with PVRSRV_HAP_KERNEL_ONLY "
+ " (Use OSReservePhys otherwise)"));
+ return NULL;
+ }
+}
+
+IMG_BOOL
+OSUnMapPhysToLin(IMG_VOID *pvLinAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32MappingFlags, IMG_HANDLE hPageAlloc)
+{
+ PVR_TRACE(("%s: unmapping %d bytes from 0x%08x", __FUNCTION__, ui32Bytes, pvLinAddr));
+
+ PVR_UNREFERENCED_PARAMETER(hPageAlloc);
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+
+ if(ui32MappingFlags & PVRSRV_HAP_KERNEL_ONLY)
+ {
+ iounmap(pvLinAddr);
+ return IMG_TRUE;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSUnMapPhysToLin should only be used with PVRSRV_HAP_KERNEL_ONLY "
+ " (Use OSUnReservePhys otherwise)"));
+ return IMG_FALSE;
+ }
+}
+
+static PVRSRV_ERROR
+RegisterExternalMem(IMG_SYS_PHYADDR *pBasePAddr,
+ IMG_VOID *pvCPUVAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_BOOL bPhysContig,
+ IMG_UINT32 ui32MappingFlags,
+ IMG_HANDLE *phOSMemHandle)
+{
+ LinuxMemArea *psLinuxMemArea;
+
+ switch(ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK)
+ {
+ case PVRSRV_HAP_KERNEL_ONLY:
+ {
+ psLinuxMemArea = NewExternalKVLinuxMemArea(pBasePAddr, pvCPUVAddr, ui32Bytes, bPhysContig, ui32MappingFlags);
+
+ if(!psLinuxMemArea)
+ {
+ return PVRSRV_ERROR_GENERIC;
+ }
+ break;
+ }
+ case PVRSRV_HAP_SINGLE_PROCESS:
+ {
+ psLinuxMemArea = NewExternalKVLinuxMemArea(pBasePAddr, pvCPUVAddr, ui32Bytes, bPhysContig, ui32MappingFlags);
+
+ if(!psLinuxMemArea)
+ {
+ return PVRSRV_ERROR_GENERIC;
+ }
+ PVRMMapRegisterArea(psLinuxMemArea);
+ break;
+ }
+ case PVRSRV_HAP_MULTI_PROCESS:
+ {
+
+#if defined(VIVT_CACHE) || defined(__sh__)
+
+ ui32MappingFlags &= ~PVRSRV_HAP_CACHED;
+#endif
+ psLinuxMemArea = NewExternalKVLinuxMemArea(pBasePAddr, pvCPUVAddr, ui32Bytes, bPhysContig, ui32MappingFlags);
+
+ if(!psLinuxMemArea)
+ {
+ return PVRSRV_ERROR_GENERIC;
+ }
+ PVRMMapRegisterArea(psLinuxMemArea);
+ break;
+ }
+ default:
+ PVR_DPF((PVR_DBG_ERROR,"OSRegisterMem : invalid flags 0x%x\n", ui32MappingFlags));
+ *phOSMemHandle = (IMG_HANDLE)0;
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ *phOSMemHandle = (IMG_HANDLE)psLinuxMemArea;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR
+OSRegisterMem(IMG_CPU_PHYADDR BasePAddr,
+ IMG_VOID *pvCPUVAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32MappingFlags,
+ IMG_HANDLE *phOSMemHandle)
+{
+ IMG_SYS_PHYADDR SysPAddr = SysCpuPAddrToSysPAddr(BasePAddr);
+
+ return RegisterExternalMem(&SysPAddr, pvCPUVAddr, ui32Bytes, IMG_TRUE, ui32MappingFlags, phOSMemHandle);
+}
+
+
+PVRSRV_ERROR OSRegisterDiscontigMem(IMG_SYS_PHYADDR *pBasePAddr, IMG_VOID *pvCPUVAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32MappingFlags, IMG_HANDLE *phOSMemHandle)
+{
+ return RegisterExternalMem(pBasePAddr, pvCPUVAddr, ui32Bytes, IMG_FALSE, ui32MappingFlags, phOSMemHandle);
+}
+
+
+PVRSRV_ERROR
+OSUnRegisterMem (IMG_VOID *pvCpuVAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32MappingFlags,
+ IMG_HANDLE hOSMemHandle)
+{
+ LinuxMemArea *psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+ PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+
+ switch(ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK)
+ {
+ case PVRSRV_HAP_KERNEL_ONLY:
+ break;
+ case PVRSRV_HAP_SINGLE_PROCESS:
+ case PVRSRV_HAP_MULTI_PROCESS:
+ {
+ if(PVRMMapRemoveRegisteredArea(psLinuxMemArea) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s(%p, %d, 0x%08X, %p) FAILED!",
+ __FUNCTION__, pvCpuVAddr, ui32Bytes,
+ ui32MappingFlags, hOSMemHandle));
+ return PVRSRV_ERROR_GENERIC;
+ }
+ break;
+ }
+ default:
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSUnRegisterMem : invalid flags 0x%x", ui32MappingFlags));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ }
+
+ LinuxMemAreaDeepFree(psLinuxMemArea);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSUnRegisterDiscontigMem(IMG_VOID *pvCpuVAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32Flags, IMG_HANDLE hOSMemHandle)
+{
+ return OSUnRegisterMem(pvCpuVAddr, ui32Bytes, ui32Flags, hOSMemHandle);
+}
+
+PVRSRV_ERROR
+OSReservePhys(IMG_CPU_PHYADDR BasePAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32MappingFlags,
+ IMG_VOID **ppvCpuVAddr,
+ IMG_HANDLE *phOSMemHandle)
+{
+ LinuxMemArea *psLinuxMemArea;
+
+#if 0
+
+ if(ui32MappingFlags & PVRSRV_HAP_SINGLE_PROCESS)
+ {
+ ui32MappingFlags &= ~PVRSRV_HAP_SINGLE_PROCESS;
+ ui32MappingFlags |= PVRSRV_HAP_MULTI_PROCESS;
+ }
+#endif
+
+ switch(ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK)
+ {
+ case PVRSRV_HAP_KERNEL_ONLY:
+ {
+
+ psLinuxMemArea = ioremap_linux_mem_area(BasePAddr.uiAddr, ui32Bytes, ui32MappingFlags);
+ if(!psLinuxMemArea)
+ {
+ return PVRSRV_ERROR_GENERIC;
+ }
+ break;
+ }
+ case PVRSRV_HAP_SINGLE_PROCESS:
+ {
+
+ psLinuxMemArea = NewIOLinuxMemArea(BasePAddr.uiAddr, ui32Bytes, ui32MappingFlags);
+ if(!psLinuxMemArea)
+ {
+ return PVRSRV_ERROR_GENERIC;
+ }
+ PVRMMapRegisterArea(psLinuxMemArea);
+ break;
+ }
+ case PVRSRV_HAP_MULTI_PROCESS:
+ {
+
+#if defined(VIVT_CACHE) || defined(__sh__)
+
+ ui32MappingFlags &= ~PVRSRV_HAP_CACHED;
+#endif
+ psLinuxMemArea = ioremap_linux_mem_area(BasePAddr.uiAddr, ui32Bytes, ui32MappingFlags);
+ if(!psLinuxMemArea)
+ {
+ return PVRSRV_ERROR_GENERIC;
+ }
+ PVRMMapRegisterArea(psLinuxMemArea);
+ break;
+ }
+ default:
+ PVR_DPF((PVR_DBG_ERROR,"OSMapPhysToLin : invalid flags 0x%x\n", ui32MappingFlags));
+ *ppvCpuVAddr = NULL;
+ *phOSMemHandle = (IMG_HANDLE)0;
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ *phOSMemHandle = (IMG_HANDLE)psLinuxMemArea;
+ *ppvCpuVAddr = LinuxMemAreaToCpuVAddr(psLinuxMemArea);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+OSUnReservePhys(IMG_VOID *pvCpuVAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32MappingFlags,
+ IMG_HANDLE hOSMemHandle)
+{
+ LinuxMemArea *psLinuxMemArea;
+
+ PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+
+ psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+ switch(ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK)
+ {
+ case PVRSRV_HAP_KERNEL_ONLY:
+ break;
+ case PVRSRV_HAP_SINGLE_PROCESS:
+ case PVRSRV_HAP_MULTI_PROCESS:
+ {
+ if(PVRMMapRemoveRegisteredArea(psLinuxMemArea) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s(%p, %d, 0x%08X, %p) FAILED!",
+ __FUNCTION__, pvCpuVAddr, ui32Bytes,
+ ui32MappingFlags, hOSMemHandle));
+ return PVRSRV_ERROR_GENERIC;
+ }
+ break;
+ }
+ default:
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSUnMapPhysToLin : invalid flags 0x%x", ui32MappingFlags));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ }
+
+ LinuxMemAreaDeepFree(psLinuxMemArea);
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSBaseAllocContigMemory(IMG_UINT32 ui32Size, IMG_CPU_VIRTADDR *pvLinAddr, IMG_CPU_PHYADDR *psPhysAddr)
+{
+#if !defined(NO_HARDWARE)
+ PVR_UNREFERENCED_PARAMETER(ui32Size);
+ PVR_UNREFERENCED_PARAMETER(pvLinAddr);
+ PVR_UNREFERENCED_PARAMETER(psPhysAddr);
+ PVR_DPF((PVR_DBG_ERROR, "%s: Not available", __FUNCTION__));
+
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+#else
+ IMG_VOID *pvKernLinAddr;
+
+ pvKernLinAddr = kmalloc(ui32Size, GFP_KERNEL);
+
+ if (!pvKernLinAddr)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ *pvLinAddr = pvKernLinAddr;
+
+ psPhysAddr->uiAddr = virt_to_phys(pvKernLinAddr);
+
+ return PVRSRV_OK;
+#endif
+}
+
+
+PVRSRV_ERROR OSBaseFreeContigMemory(IMG_UINT32 ui32Size, IMG_CPU_VIRTADDR pvLinAddr, IMG_CPU_PHYADDR psPhysAddr)
+{
+#if !defined(NO_HARDWARE)
+ PVR_UNREFERENCED_PARAMETER(ui32Size);
+ PVR_UNREFERENCED_PARAMETER(pvLinAddr);
+ PVR_UNREFERENCED_PARAMETER(psPhysAddr.uiAddr);
+
+ PVR_DPF((PVR_DBG_WARNING, "%s: Not available", __FUNCTION__));
+#else
+ PVR_UNREFERENCED_PARAMETER(ui32Size);
+ PVR_UNREFERENCED_PARAMETER(psPhysAddr.uiAddr);
+
+ kfree(pvLinAddr);
+#endif
+ return PVRSRV_OK;
+}
+
+IMG_UINT32 OSReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset)
+{
+#if !defined(NO_HARDWARE)
+ return (IMG_UINT32) readl((IMG_PBYTE)pvLinRegBaseAddr+ui32Offset);
+#else
+ return *(IMG_UINT32 *)((IMG_PBYTE)pvLinRegBaseAddr+ui32Offset);
+#endif
+}
+
+IMG_VOID OSWriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value)
+{
+#if !defined(NO_HARDWARE)
+ writel(ui32Value, (IMG_PBYTE)pvLinRegBaseAddr+ui32Offset);
+#else
+ *(IMG_UINT32 *)((IMG_PBYTE)pvLinRegBaseAddr+ui32Offset) = ui32Value;
+#endif
+}
+
+PVRSRV_PCI_DEV_HANDLE OSPCISetDev(IMG_VOID *pvPCICookie, HOST_PCI_INIT_FLAGS eFlags)
+{
+ int err;
+ IMG_UINT32 i;
+ PVR_PCI_DEV *psPVRPCI;
+
+ PVR_TRACE(("OSPCISetDev"));
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psPVRPCI), (IMG_VOID **)&psPVRPCI, IMG_NULL,
+ "PCI Device") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSPCISetDev: Couldn't allocate PVR PCI structure"));
+ return IMG_NULL;
+ }
+
+ psPVRPCI->psPCIDev = (struct pci_dev *)pvPCICookie;
+ psPVRPCI->ePCIFlags = eFlags;
+
+ err = pci_enable_device(psPVRPCI->psPCIDev);
+ if (err != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSPCISetDev: Couldn't enable device (%d)", err));
+ return IMG_NULL;
+ }
+
+ if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_BUS_MASTER)
+ {
+ pci_set_master(psPVRPCI->psPCIDev);
+ }
+
+ if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_MSI)
+ {
+#if defined(CONFIG_PCI_MSI)
+ if (psPVRPCI->psPCIDev->device == PSB_SYS_SGX_DEV_DEVICE_ID_1 ||
+ psPVRPCI->psPCIDev->device == PSB_SYS_SGX_DEV_DEVICE_ID_2) // Disable MSI for Menlow
+ psPVRPCI->ePCIFlags &= ~HOST_PCI_INIT_FLAG_MSI;
+ else if(!psPVRPCI->psPCIDev->msi_enabled)
+ /* MSIs enabled at probe() time */
+ psPVRPCI->ePCIFlags &= ~HOST_PCI_INIT_FLAG_MSI;
+#else
+ PVR_DPF((PVR_DBG_WARNING, "OSPCISetDev: MSI support not enabled in the kernel"));
+#endif
+ }
+
+
+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+ {
+ psPVRPCI->abPCIResourceInUse[i] = IMG_FALSE;
+ }
+
+ return (PVRSRV_PCI_DEV_HANDLE)psPVRPCI;
+}
+
+PVRSRV_PCI_DEV_HANDLE OSPCIAcquireDev(IMG_UINT16 ui16VendorID, IMG_UINT16 ui16DeviceID, HOST_PCI_INIT_FLAGS eFlags)
+{
+ struct pci_dev *psPCIDev;
+
+ psPCIDev = pci_get_device(ui16VendorID, ui16DeviceID, NULL);
+ if (psPCIDev == NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSPCIAcquireDev: Couldn't acquire device"));
+ return IMG_NULL;
+ }
+
+ return OSPCISetDev((IMG_VOID *)psPCIDev, eFlags);
+}
+
+PVRSRV_ERROR OSPCIIRQ(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 *pui32IRQ)
+{
+ PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+
+ *pui32IRQ = psPVRPCI->psPCIDev->irq;
+
+ return PVRSRV_OK;
+}
+
+enum HOST_PCI_ADDR_RANGE_FUNC
+{
+ HOST_PCI_ADDR_RANGE_FUNC_LEN,
+ HOST_PCI_ADDR_RANGE_FUNC_START,
+ HOST_PCI_ADDR_RANGE_FUNC_END,
+ HOST_PCI_ADDR_RANGE_FUNC_REQUEST,
+ HOST_PCI_ADDR_RANGE_FUNC_RELEASE
+};
+
+static IMG_UINT32 OSPCIAddrRangeFunc(enum HOST_PCI_ADDR_RANGE_FUNC eFunc,
+ PVRSRV_PCI_DEV_HANDLE hPVRPCI,
+ IMG_UINT32 ui32Index)
+{
+ PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+
+ if (ui32Index >= DEVICE_COUNT_RESOURCE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSPCIAddrRangeFunc: Index out of range"));
+ return 0;
+
+ }
+
+ switch (eFunc)
+ {
+ case HOST_PCI_ADDR_RANGE_FUNC_LEN:
+ return pci_resource_len(psPVRPCI->psPCIDev, ui32Index);
+ case HOST_PCI_ADDR_RANGE_FUNC_START:
+ return pci_resource_start(psPVRPCI->psPCIDev, ui32Index);
+ case HOST_PCI_ADDR_RANGE_FUNC_END:
+ return pci_resource_end(psPVRPCI->psPCIDev, ui32Index);
+ case HOST_PCI_ADDR_RANGE_FUNC_REQUEST:
+ {
+ int err;
+
+ err = pci_request_region(psPVRPCI->psPCIDev, (IMG_INT)ui32Index, "PowerVR");
+ if (err != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSPCIAddrRangeFunc: pci_request_region_failed (%d)", err));
+ return 0;
+ }
+ psPVRPCI->abPCIResourceInUse[ui32Index] = IMG_TRUE;
+ return 1;
+ }
+ case HOST_PCI_ADDR_RANGE_FUNC_RELEASE:
+ if (psPVRPCI->abPCIResourceInUse[ui32Index])
+ {
+ pci_release_region(psPVRPCI->psPCIDev, (IMG_INT)ui32Index);
+ psPVRPCI->abPCIResourceInUse[ui32Index] = IMG_FALSE;
+ }
+ return 1;
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "OSPCIAddrRangeFunc: Unknown function"));
+ break;
+ }
+
+ return 0;
+}
+
+IMG_UINT32 OSPCIAddrRangeLen(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index)
+{
+ return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_LEN, hPVRPCI, ui32Index);
+}
+
+IMG_UINT32 OSPCIAddrRangeStart(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index)
+{
+ return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_START, hPVRPCI, ui32Index);
+}
+
+IMG_UINT32 OSPCIAddrRangeEnd(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index)
+{
+ return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_END, hPVRPCI, ui32Index);
+}
+
+PVRSRV_ERROR OSPCIRequestAddrRange(PVRSRV_PCI_DEV_HANDLE hPVRPCI,
+ IMG_UINT32 ui32Index)
+{
+ return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_REQUEST, hPVRPCI, ui32Index) == 0 ? PVRSRV_ERROR_GENERIC : PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSPCIReleaseAddrRange(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index)
+{
+ return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_RELEASE, hPVRPCI, ui32Index) == 0 ? PVRSRV_ERROR_GENERIC : PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSPCIReleaseDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI)
+{
+ PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+ int i;
+
+ PVR_TRACE(("OSPCIReleaseDev"));
+
+
+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+ {
+ if (psPVRPCI->abPCIResourceInUse[i])
+ {
+ PVR_TRACE(("OSPCIReleaseDev: Releasing Address range %d", i));
+ pci_release_region(psPVRPCI->psPCIDev, i);
+ psPVRPCI->abPCIResourceInUse[i] = IMG_FALSE;
+ }
+ }
+
+#if defined(CONFIG_PCI_MSI)
+ if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_MSI)
+ {
+ pci_disable_msi(psPVRPCI->psPCIDev);
+ }
+#endif
+
+ if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_BUS_MASTER)
+ {
+ pci_clear_master(psPVRPCI->psPCIDev);
+ }
+ pci_disable_device(psPVRPCI->psPCIDev);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psPVRPCI), (IMG_VOID *)psPVRPCI, IMG_NULL);
+
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSPCISuspendDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI)
+{
+ PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+ int i;
+ int err;
+
+ PVR_TRACE(("OSPCISuspendDev"));
+
+
+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+ {
+ if (psPVRPCI->abPCIResourceInUse[i])
+ {
+ pci_release_region(psPVRPCI->psPCIDev, i);
+ }
+ }
+
+ err = pci_save_state(psPVRPCI->psPCIDev);
+ if (err != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSPCISuspendDev: pci_save_state_failed (%d)", err));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ pci_disable_device(psPVRPCI->psPCIDev);
+
+ err = pci_set_power_state(psPVRPCI->psPCIDev, PCI_D3hot);//pci_choose_state(psPVRPCI->psPCIDev, PMSG_SUSPEND));
+ switch(err)
+ {
+ case 0:
+ break;
+ case -EIO:
+ PVR_DPF((PVR_DBG_WARNING, "OSPCISuspendDev: device doesn't support PCI PM"));
+ break;
+ case -EINVAL:
+ PVR_DPF((PVR_DBG_ERROR, "OSPCISuspendDev: can't enter requested power state"));
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "OSPCISuspendDev: pci_set_power_state failed (%d)", err));
+ break;
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSPCIResumeDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI)
+{
+ PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+ int err;
+ int i;
+
+ PVR_TRACE(("OSPCIResumeDev"));
+
+ err = pci_set_power_state(psPVRPCI->psPCIDev, PCI_D0);//pci_choose_state(psPVRPCI->psPCIDev, PMSG_ON));
+ switch(err)
+ {
+ case 0:
+ break;
+ case -EIO:
+ PVR_DPF((PVR_DBG_WARNING, "OSPCIResumeDev: device doesn't support PCI PM"));
+ break;
+ case -EINVAL:
+ PVR_DPF((PVR_DBG_ERROR, "OSPCIResumeDev: can't enter requested power state"));
+ return PVRSRV_ERROR_GENERIC;
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "OSPCIResumeDev: pci_set_power_state failed (%d)", err));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ pci_restore_state(psPVRPCI->psPCIDev);
+
+ err = pci_enable_device(psPVRPCI->psPCIDev);
+ if (err != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSPCIResumeDev: Couldn't enable device (%d)", err));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_BUS_MASTER)
+ pci_set_master(psPVRPCI->psPCIDev);
+
+
+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+ {
+ if (psPVRPCI->abPCIResourceInUse[i])
+ {
+ err = pci_request_region(psPVRPCI->psPCIDev, i, "PowerVR");
+ if (err != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSPCIResumeDev: pci_request_region_failed (region %d, error %d)", i, err));
+ }
+ }
+
+ }
+
+ return PVRSRV_OK;
+}
+
+#define OS_MAX_TIMERS 8
+
+typedef struct TIMER_CALLBACK_DATA_TAG
+{
+ IMG_BOOL bInUse;
+ PFN_TIMER_FUNC pfnTimerFunc;
+ IMG_VOID *pvData;
+ struct timer_list sTimer;
+ IMG_UINT32 ui32Delay;
+ IMG_BOOL bActive;
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+ struct work_struct sWork;
+#endif
+}TIMER_CALLBACK_DATA;
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+static struct workqueue_struct *psTimerWorkQueue;
+#endif
+
+static TIMER_CALLBACK_DATA sTimers[OS_MAX_TIMERS];
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+DEFINE_MUTEX(sTimerStructLock);
+#else
+static DEFINE_SPINLOCK(sTimerStructLock);
+#endif
+
+static void OSTimerCallbackBody(TIMER_CALLBACK_DATA *psTimerCBData)
+{
+ if (!psTimerCBData->bActive)
+ return;
+
+
+ psTimerCBData->pfnTimerFunc(psTimerCBData->pvData);
+
+
+ mod_timer(&psTimerCBData->sTimer, psTimerCBData->ui32Delay + jiffies);
+}
+
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+static void OSTimerWorkQueueCallBack(struct work_struct *psWork)
+{
+ TIMER_CALLBACK_DATA *psTimerCBData = container_of(psWork, TIMER_CALLBACK_DATA, sWork);
+
+ OSTimerCallbackBody(psTimerCBData);
+}
+#endif
+
+static IMG_VOID OSTimerCallbackWrapper(IMG_UINT32 ui32Data)
+{
+ TIMER_CALLBACK_DATA *psTimerCBData = (TIMER_CALLBACK_DATA*)ui32Data;
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+ int res;
+
+ res = queue_work(psTimerWorkQueue, &psTimerCBData->sWork);
+ if (res == 0)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "OSTimerCallbackWrapper: work already queued"));
+ }
+#else
+ OSTimerCallbackBody(psTimerCBData);
+#endif
+}
+
+
+IMG_HANDLE OSAddTimer(PFN_TIMER_FUNC pfnTimerFunc, IMG_VOID *pvData, IMG_UINT32 ui32MsTimeout)
+{
+ TIMER_CALLBACK_DATA *psTimerCBData;
+ IMG_UINT32 ui32i;
+#if !defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+ unsigned long ulLockFlags;
+#endif
+
+
+ if(!pfnTimerFunc)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSAddTimer: passed invalid callback"));
+ return IMG_NULL;
+ }
+
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+ mutex_lock(&sTimerStructLock);
+#else
+ spin_lock_irqsave(&sTimerStructLock, ulLockFlags);
+#endif
+ for (ui32i = 0; ui32i < OS_MAX_TIMERS; ui32i++)
+ {
+ psTimerCBData = &sTimers[ui32i];
+ if (!psTimerCBData->bInUse)
+ {
+ psTimerCBData->bInUse = IMG_TRUE;
+ break;
+ }
+ }
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+ mutex_unlock(&sTimerStructLock);
+#else
+ spin_unlock_irqrestore(&sTimerStructLock, ulLockFlags);
+#endif
+ if (ui32i >= OS_MAX_TIMERS)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSAddTimer: all timers are in use"));
+ return IMG_NULL;
+ }
+
+ psTimerCBData->pfnTimerFunc = pfnTimerFunc;
+ psTimerCBData->pvData = pvData;
+ psTimerCBData->bActive = IMG_FALSE;
+
+
+
+
+ psTimerCBData->ui32Delay = ((HZ * ui32MsTimeout) < 1000)
+ ? 1
+ : ((HZ * ui32MsTimeout) / 1000);
+
+ init_timer(&psTimerCBData->sTimer);
+
+
+ psTimerCBData->sTimer.function = (IMG_VOID *)OSTimerCallbackWrapper;
+ psTimerCBData->sTimer.data = (IMG_UINT32)psTimerCBData;
+ psTimerCBData->sTimer.expires = psTimerCBData->ui32Delay + jiffies;
+
+ return (IMG_HANDLE)(ui32i + 1);
+}
+
+
+static inline TIMER_CALLBACK_DATA *GetTimerStructure(IMG_HANDLE hTimer)
+{
+ IMG_UINT32 ui32i = ((IMG_UINT32)hTimer) - 1;
+
+ PVR_ASSERT(ui32i < OS_MAX_TIMERS);
+
+ return &sTimers[ui32i];
+}
+
+PVRSRV_ERROR OSRemoveTimer (IMG_HANDLE hTimer)
+{
+ TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer);
+
+ PVR_ASSERT(psTimerCBData->bInUse);
+ PVR_ASSERT(!psTimerCBData->bActive);
+
+
+ psTimerCBData->bInUse = IMG_FALSE;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSEnableTimer (IMG_HANDLE hTimer)
+{
+ TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer);
+
+ PVR_ASSERT(psTimerCBData->bInUse);
+ PVR_ASSERT(!psTimerCBData->bActive);
+
+
+ psTimerCBData->bActive = IMG_TRUE;
+
+
+ psTimerCBData->sTimer.expires = psTimerCBData->ui32Delay + jiffies;
+
+
+ add_timer(&psTimerCBData->sTimer);
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSDisableTimer (IMG_HANDLE hTimer)
+{
+ TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer);
+
+ PVR_ASSERT(psTimerCBData->bInUse);
+ PVR_ASSERT(psTimerCBData->bActive);
+
+
+ psTimerCBData->bActive = IMG_FALSE;
+ smp_mb();
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+ flush_workqueue(psTimerWorkQueue);
+#endif
+
+
+ del_timer_sync(&psTimerCBData->sTimer);
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+
+ flush_workqueue(psTimerWorkQueue);
+#endif
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSEventObjectCreate(const IMG_CHAR *pszName, PVRSRV_EVENTOBJECT *psEventObject)
+{
+
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if(psEventObject)
+ {
+ if(pszName)
+ {
+
+ strncpy(psEventObject->szName, pszName, EVENTOBJNAME_MAXLENGTH);
+ }
+ else
+ {
+
+ static IMG_UINT16 ui16NameIndex = 0;
+ snprintf(psEventObject->szName, EVENTOBJNAME_MAXLENGTH, "PVRSRV_EVENTOBJECT_%d", ui16NameIndex++);
+ }
+
+ if(LinuxEventObjectListCreate(&psEventObject->hOSEventKM) != PVRSRV_OK)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSEventObjectCreate: psEventObject is not a valid pointer"));
+ eError = PVRSRV_ERROR_GENERIC;
+ }
+
+ return eError;
+
+}
+
+
+PVRSRV_ERROR OSEventObjectDestroy(PVRSRV_EVENTOBJECT *psEventObject)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if(psEventObject)
+ {
+ if(psEventObject->hOSEventKM)
+ {
+ LinuxEventObjectListDestroy(psEventObject->hOSEventKM);
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSEventObjectDestroy: hOSEventKM is not a valid pointer"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSEventObjectDestroy: psEventObject is not a valid pointer"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return eError;
+}
+
+PVRSRV_ERROR OSEventObjectWait(IMG_HANDLE hOSEventKM)
+{
+ PVRSRV_ERROR eError;
+
+ if(hOSEventKM)
+ {
+ eError = LinuxEventObjectWait(hOSEventKM, EVENT_OBJECT_TIMEOUT_MS);
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSEventObjectWait: hOSEventKM is not a valid handle"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return eError;
+}
+
+PVRSRV_ERROR OSEventObjectOpen(PVRSRV_EVENTOBJECT *psEventObject,
+ IMG_HANDLE *phOSEvent)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if(psEventObject)
+ {
+ if(LinuxEventObjectAdd(psEventObject->hOSEventKM, phOSEvent) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectAdd: failed"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSEventObjectCreate: psEventObject is not a valid pointer"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return eError;
+}
+
+PVRSRV_ERROR OSEventObjectClose(PVRSRV_EVENTOBJECT *psEventObject,
+ IMG_HANDLE hOSEventKM)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if(psEventObject)
+ {
+ if(LinuxEventObjectDelete(psEventObject->hOSEventKM, hOSEventKM) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectDelete: failed"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSEventObjectDestroy: psEventObject is not a valid pointer"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return eError;
+
+}
+
+PVRSRV_ERROR OSEventObjectSignal(IMG_HANDLE hOSEventKM)
+{
+ PVRSRV_ERROR eError;
+
+ if(hOSEventKM)
+ {
+ eError = LinuxEventObjectSignal(hOSEventKM);
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSEventObjectSignal: hOSEventKM is not a valid handle"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return eError;
+}
+
+IMG_BOOL OSProcHasPrivSrvInit(IMG_VOID)
+{
+ return (capable(CAP_SYS_MODULE) != 0) ? IMG_TRUE : IMG_FALSE;
+}
+
+PVRSRV_ERROR OSCopyToUser(IMG_PVOID pvProcess,
+ IMG_VOID *pvDest,
+ IMG_VOID *pvSrc,
+ IMG_UINT32 ui32Bytes)
+{
+ PVR_UNREFERENCED_PARAMETER(pvProcess);
+
+ if(copy_to_user(pvDest, pvSrc, ui32Bytes)==0)
+ return PVRSRV_OK;
+ else
+ return PVRSRV_ERROR_GENERIC;
+}
+
+PVRSRV_ERROR OSCopyFromUser( IMG_PVOID pvProcess,
+ IMG_VOID *pvDest,
+ IMG_VOID *pvSrc,
+ IMG_UINT32 ui32Bytes)
+{
+ PVR_UNREFERENCED_PARAMETER(pvProcess);
+
+ if(copy_from_user(pvDest, pvSrc, ui32Bytes)==0)
+ return PVRSRV_OK;
+ else
+ return PVRSRV_ERROR_GENERIC;
+}
+
+IMG_BOOL OSAccessOK(IMG_VERIFY_TEST eVerification, IMG_VOID *pvUserPtr, IMG_UINT32 ui32Bytes)
+{
+ IMG_INT linuxType;
+
+ if (eVerification == PVR_VERIFY_READ)
+ {
+ linuxType = VERIFY_READ;
+ }
+ else
+ {
+ PVR_ASSERT(eVerification == PVR_VERIFY_WRITE);
+ linuxType = VERIFY_WRITE;
+ }
+
+ return access_ok(linuxType, pvUserPtr, ui32Bytes);
+}
+
+typedef enum _eWrapMemType_
+{
+ WRAP_TYPE_CLEANUP,
+ WRAP_TYPE_GET_USER_PAGES,
+ WRAP_TYPE_FIND_VMA_PAGES,
+ WRAP_TYPE_FIND_VMA_PFN
+} eWrapMemType;
+
+typedef struct _sWrapMemInfo_
+{
+ eWrapMemType eType;
+ IMG_INT iNumPages;
+ struct page **ppsPages;
+ IMG_SYS_PHYADDR *psPhysAddr;
+ IMG_INT iPageOffset;
+ IMG_INT iContiguous;
+#if defined(DEBUG)
+ IMG_UINT32 ulStartAddr;
+ IMG_UINT32 ulBeyondEndAddr;
+ struct vm_area_struct *psVMArea;
+#endif
+ IMG_BOOL bWrapWorkaround;
+} sWrapMemInfo;
+
+static IMG_VOID CheckPagesContiguous(sWrapMemInfo *psInfo)
+{
+ IMG_INT i;
+ IMG_UINT32 ui32AddrChk;
+
+ BUG_ON(psInfo == IMG_NULL);
+
+ psInfo->iContiguous = 1;
+
+ for (i = 0, ui32AddrChk = psInfo->psPhysAddr[0].uiAddr;
+ i < psInfo->iNumPages;
+ i++, ui32AddrChk += PAGE_SIZE)
+ {
+ if (psInfo->psPhysAddr[i].uiAddr != ui32AddrChk)
+ {
+ psInfo->iContiguous = 0;
+ break;
+ }
+ }
+}
+
+static struct page *CPUVAddrToPage(struct vm_area_struct *psVMArea, IMG_UINT32 ulCPUVAddr)
+{
+ pgd_t *psPGD;
+ pud_t *psPUD;
+ pmd_t *psPMD;
+ pte_t *psPTE;
+ struct mm_struct *psMM = psVMArea->vm_mm;
+ IMG_UINT32 ulPFN;
+ spinlock_t *psPTLock;
+ struct page *psPage;
+
+ psPGD = pgd_offset(psMM, ulCPUVAddr);
+ if (pgd_none(*psPGD) || pgd_bad(*psPGD))
+ return NULL;
+
+ psPUD = pud_offset(psPGD, ulCPUVAddr);
+ if (pud_none(*psPUD) || pud_bad(*psPUD))
+ return NULL;
+
+ psPMD = pmd_offset(psPUD, ulCPUVAddr);
+ if (pmd_none(*psPMD) || pmd_bad(*psPMD))
+ return NULL;
+
+ psPage = NULL;
+
+ psPTE = (pte_t *)pte_offset_map_lock(psMM, psPMD, ulCPUVAddr, &psPTLock);
+ if ((pte_none(*psPTE) != 0) || (pte_present(*psPTE) == 0) || (pte_write(*psPTE) == 0))
+ goto exit_unlock;
+
+ ulPFN = pte_pfn(*psPTE);
+ if (!pfn_valid(ulPFN))
+ goto exit_unlock;
+
+ psPage = pfn_to_page(ulPFN);
+
+ get_page(psPage);
+
+exit_unlock:
+ pte_unmap_unlock(psPTE, psPTLock);
+
+ return psPage;
+}
+PVRSRV_ERROR OSReleasePhysPageAddr(IMG_HANDLE hOSWrapMem)
+{
+ sWrapMemInfo *psInfo = (sWrapMemInfo *)hOSWrapMem;
+ IMG_INT i;
+
+ BUG_ON(psInfo == IMG_NULL);
+
+ switch (psInfo->eType)
+ {
+ case WRAP_TYPE_CLEANUP:
+ break;
+ case WRAP_TYPE_FIND_VMA_PFN:
+ break;
+ case WRAP_TYPE_GET_USER_PAGES:
+ {
+ for (i = 0; i < psInfo->iNumPages; i++)
+ {
+ struct page *psPage = psInfo->ppsPages[i];
+
+
+ if (!PageReserved(psPage));
+ {
+ SetPageDirty(psPage);
+ }
+ page_cache_release(psPage);
+ }
+ break;
+ }
+ case WRAP_TYPE_FIND_VMA_PAGES:
+ {
+ for (i = 0; i < psInfo->iNumPages; i++)
+ {
+ if(psInfo->bWrapWorkaround)
+ put_page(psInfo->ppsPages[i]);
+ else
+ put_page_testzero(psInfo->ppsPages[i]);
+ }
+ break;
+ }
+ default:
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSReleasePhysPageAddr: Unknown wrap type (%d)", psInfo->eType));
+ return PVRSRV_ERROR_GENERIC;
+ }
+ }
+
+ if (psInfo->ppsPages != IMG_NULL)
+ {
+ kfree(psInfo->ppsPages);
+ }
+
+ if (psInfo->psPhysAddr != IMG_NULL)
+ {
+ kfree(psInfo->psPhysAddr);
+ }
+
+ kfree(psInfo);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID* pvCPUVAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_SYS_PHYADDR *psSysPAddr,
+ IMG_HANDLE *phOSWrapMem,
+ IMG_BOOL bWrapWorkaround)
+{
+ IMG_UINT32 ulStartAddrOrig = (IMG_UINT32) pvCPUVAddr;
+ IMG_UINT32 ulAddrRangeOrig = (IMG_UINT32) ui32Bytes;
+ IMG_UINT32 ulBeyondEndAddrOrig = ulStartAddrOrig + ulAddrRangeOrig;
+ IMG_UINT32 ulStartAddr;
+ IMG_UINT32 ulAddrRange;
+ IMG_UINT32 ulBeyondEndAddr;
+ IMG_UINT32 ulAddr;
+ IMG_INT iNumPagesMapped;
+ IMG_INT i;
+ struct vm_area_struct *psVMArea;
+ sWrapMemInfo *psInfo;
+
+
+ ulStartAddr = ulStartAddrOrig & PAGE_MASK;
+ ulBeyondEndAddr = PAGE_ALIGN(ulBeyondEndAddrOrig);
+ ulAddrRange = ulBeyondEndAddr - ulStartAddr;
+
+
+ psInfo = kmalloc(sizeof(*psInfo), GFP_KERNEL);
+ if (psInfo == NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: Couldn't allocate information structure"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ memset(psInfo, 0, sizeof(*psInfo));
+ psInfo->bWrapWorkaround = bWrapWorkaround;
+
+#if defined(DEBUG)
+ psInfo->ulStartAddr = ulStartAddrOrig;
+ psInfo->ulBeyondEndAddr = ulBeyondEndAddrOrig;
+#endif
+
+ psInfo->iNumPages = (IMG_INT)(ulAddrRange >> PAGE_SHIFT);
+ psInfo->iPageOffset = (IMG_INT)(ulStartAddrOrig & ~PAGE_MASK);
+
+
+ psInfo->psPhysAddr = kmalloc((size_t)psInfo->iNumPages * sizeof(*psInfo->psPhysAddr), GFP_KERNEL);
+ if (psInfo->psPhysAddr == NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: Couldn't allocate page array"));
+ goto error_free;
+ }
+
+
+ psInfo->ppsPages = kmalloc((size_t)psInfo->iNumPages * sizeof(*psInfo->ppsPages), GFP_KERNEL);
+ if (psInfo->ppsPages == NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: Couldn't allocate page array"));
+ goto error_free;
+ }
+
+
+ down_read(¤t->mm->mmap_sem);
+ iNumPagesMapped = get_user_pages(current, current->mm, ulStartAddr, psInfo->iNumPages, 1, 0, psInfo->ppsPages, NULL);
+ up_read(¤t->mm->mmap_sem);
+
+ if (iNumPagesMapped >= 0)
+ {
+
+ if (iNumPagesMapped != psInfo->iNumPages)
+ {
+ PVR_TRACE(("OSAcquirePhysPageAddr: Couldn't map all the pages needed (wanted: %d, got %d)", psInfo->iNumPages, iNumPagesMapped));
+
+
+ for (i = 0; i < iNumPagesMapped; i++)
+ {
+ page_cache_release(psInfo->ppsPages[i]);
+
+ }
+ goto error_free;
+ }
+
+
+ for (i = 0; i < psInfo->iNumPages; i++)
+ {
+ IMG_CPU_PHYADDR CPUPhysAddr;
+
+ CPUPhysAddr.uiAddr = page_to_pfn(psInfo->ppsPages[i]) << PAGE_SHIFT;
+ psInfo->psPhysAddr[i] = SysCpuPAddrToSysPAddr(CPUPhysAddr);
+ psSysPAddr[i] = psInfo->psPhysAddr[i];
+
+ }
+
+ psInfo->eType = WRAP_TYPE_GET_USER_PAGES;
+
+ goto exit_check;
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE, "OSAcquirePhysPageAddr: get_user_pages failed (%d), trying something else", iNumPagesMapped));
+
+
+ down_read(¤t->mm->mmap_sem);
+
+ psVMArea = find_vma(current->mm, ulStartAddrOrig);
+ if (psVMArea == NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: Couldn't find memory region containing start address %lx", ulStartAddrOrig));
+
+ goto error_release_mmap_sem;
+ }
+#if defined(DEBUG)
+ psInfo->psVMArea = psVMArea;
+#endif
+
+
+ if (ulStartAddrOrig < psVMArea->vm_start)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: Start address %lx is outside of the region returned by find_vma", ulStartAddrOrig));
+ goto error_release_mmap_sem;
+ }
+
+
+ if (ulBeyondEndAddrOrig > psVMArea->vm_end)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: End address %lx is outside of the region returned by find_vma", ulBeyondEndAddrOrig));
+ goto error_release_mmap_sem;
+ }
+
+
+ if ((psVMArea->vm_flags & (VM_IO | VM_RESERVED)) != (VM_IO | VM_RESERVED))
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: Memory region does not represent memory mapped I/O (VMA flags: 0x%lx)", psVMArea->vm_flags));
+ goto error_release_mmap_sem;
+ }
+
+
+ if ((psVMArea->vm_flags & (VM_READ | VM_WRITE)) != (VM_READ | VM_WRITE))
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: No read/write access to memory region (VMA flags: 0x%lx)", psVMArea->vm_flags));
+ goto error_release_mmap_sem;
+ }
+
+
+ for (ulAddr = ulStartAddrOrig, i = 0; ulAddr < ulBeyondEndAddrOrig; ulAddr += PAGE_SIZE, i++)
+ {
+ struct page *psPage;
+
+ BUG_ON(i >= psInfo->iNumPages);
+
+ psPage = CPUVAddrToPage(psVMArea, ulAddr);
+ if (psPage == NULL)
+ {
+ IMG_INT j;
+
+ PVR_TRACE(("OSAcquirePhysPageAddr: Couldn't lookup page structure for address 0x%lx, trying something else", ulAddr));
+
+
+ for (j = 0; j < i; j++)
+ {
+ if(psInfo->bWrapWorkaround)
+ put_page(psInfo->ppsPages[j]);
+ else
+ put_page_testzero(psInfo->ppsPages[j]);
+ }
+ break;
+ }
+
+ psInfo->ppsPages[i] = psPage;
+ }
+
+ BUG_ON(i > psInfo->iNumPages);
+ if (i == psInfo->iNumPages)
+ {
+
+ for (i = 0; i < psInfo->iNumPages; i++)
+ {
+ struct page *psPage = psInfo->ppsPages[i];
+ IMG_CPU_PHYADDR CPUPhysAddr;
+
+
+ CPUPhysAddr.uiAddr = page_to_pfn(psPage) << PAGE_SHIFT;
+
+ psInfo->psPhysAddr[i] = SysCpuPAddrToSysPAddr(CPUPhysAddr);
+ psSysPAddr[i] = psInfo->psPhysAddr[i];
+ }
+
+ psInfo->eType = WRAP_TYPE_FIND_VMA_PAGES;
+ }
+ else
+ {
+#if defined(PVR_SECURE_HANDLES)
+
+
+
+ if ((psVMArea->vm_flags & VM_PFNMAP) == 0)
+ {
+ PVR_DPF((PVR_DBG_WARNING,
+ "OSAcquirePhysPageAddr: Region isn't a raw PFN mapping. Giving up."));
+ goto error_release_mmap_sem;
+ }
+
+ for (ulAddr = ulStartAddrOrig, i = 0; ulAddr < ulBeyondEndAddrOrig; ulAddr += PAGE_SIZE, i++)
+ {
+ IMG_CPU_PHYADDR CPUPhysAddr;
+
+ CPUPhysAddr.uiAddr = ((ulAddr - psVMArea->vm_start) + (psVMArea->vm_pgoff << PAGE_SHIFT)) & PAGE_MASK;
+
+ psInfo->psPhysAddr[i] = SysCpuPAddrToSysPAddr(CPUPhysAddr);
+ psSysPAddr[i] = psInfo->psPhysAddr[i];
+ }
+ BUG_ON(i != psInfo->iNumPages);
+
+ psInfo->eType = WRAP_TYPE_FIND_VMA_PFN;
+
+
+ PVR_DPF((PVR_DBG_WARNING,
+ "OSAcquirePhysPageAddr: Region can't be locked down"));
+#else
+ PVR_DPF((PVR_DBG_WARNING,
+ "OSAcquirePhysPageAddr: Raw PFN mappings not supported. Giving up."));
+ goto error_release_mmap_sem;
+#endif
+ }
+
+ up_read(¤t->mm->mmap_sem);
+
+exit_check:
+ CheckPagesContiguous(psInfo);
+
+
+
+ *phOSWrapMem = (IMG_HANDLE)psInfo;
+
+ return PVRSRV_OK;
+
+error_release_mmap_sem:
+ up_read(¤t->mm->mmap_sem);
+error_free:
+ psInfo->eType = WRAP_TYPE_CLEANUP;
+ OSReleasePhysPageAddr((IMG_HANDLE)psInfo);
+ return PVRSRV_ERROR_GENERIC;
+}
+
+PVRSRV_ERROR PVROSFuncInit(IMG_VOID)
+{
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+ {
+ IMG_UINT32 ui32i;
+
+ psTimerWorkQueue = create_workqueue("pvr_timer");
+ if (psTimerWorkQueue == NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: couldn't create timer workqueue", __FUNCTION__));
+ return PVRSRV_ERROR_GENERIC;
+
+ }
+
+ for (ui32i = 0; ui32i < OS_MAX_TIMERS; ui32i++)
+ {
+ TIMER_CALLBACK_DATA *psTimerCBData = &sTimers[ui32i];
+
+ INIT_WORK(&psTimerCBData->sWork, OSTimerWorkQueueCallBack);
+ }
+ }
+#endif
+ return PVRSRV_OK;
+}
+
+IMG_VOID PVROSFuncDeInit(IMG_VOID)
+{
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+ if (psTimerWorkQueue != NULL)
+ {
+ destroy_workqueue(psTimerWorkQueue);
+ }
+#endif
+}
--- /dev/null
+/**********************************************************************
+ *
+ * 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 "services_headers.h"
+#include "osperproc.h"
+
+#include "env_perproc.h"
+#include "proc.h"
+
+extern IMG_UINT32 gui32ReleasePID;
+
+PVRSRV_ERROR OSPerProcessPrivateDataInit(IMG_HANDLE *phOsPrivateData)
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hBlockAlloc;
+ PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc;
+
+ eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_ENV_PER_PROCESS_DATA),
+ phOsPrivateData,
+ &hBlockAlloc,
+ "Environment per Process Data");
+
+ if (eError != PVRSRV_OK)
+ {
+ *phOsPrivateData = IMG_NULL;
+
+ PVR_DPF((PVR_DBG_ERROR, "%s: OSAllocMem failed (%d)", __FUNCTION__, eError));
+ return eError;
+ }
+
+ psEnvPerProc = (PVRSRV_ENV_PER_PROCESS_DATA *)*phOsPrivateData;
+ OSMemSet(psEnvPerProc, 0, sizeof(*psEnvPerProc));
+
+ psEnvPerProc->hBlockAlloc = hBlockAlloc;
+
+
+ LinuxMMapPerProcessConnect(psEnvPerProc);
+
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+
+ INIT_LIST_HEAD(&psEnvPerProc->sDRMAuthListHead);
+#endif
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSPerProcessPrivateDataDeInit(IMG_HANDLE hOsPrivateData)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc;
+
+ if (hOsPrivateData == IMG_NULL)
+ {
+ return PVRSRV_OK;
+ }
+
+ psEnvPerProc = (PVRSRV_ENV_PER_PROCESS_DATA *)hOsPrivateData;
+
+
+ LinuxMMapPerProcessDisconnect(psEnvPerProc);
+
+
+ RemovePerProcessProcDir(psEnvPerProc);
+
+ eError = OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_ENV_PER_PROCESS_DATA),
+ hOsPrivateData,
+ psEnvPerProc->hBlockAlloc);
+
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: OSFreeMem failed (%d)", __FUNCTION__, eError));
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSPerProcessSetHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase)
+{
+ return LinuxMMapPerProcessHandleOptions(psHandleBase);
+}
+
+IMG_HANDLE LinuxTerminatingProcessPrivateData(IMG_VOID)
+{
+ if(!gui32ReleasePID)
+ return NULL;
+ return PVRSRVPerProcessPrivateData(gui32ReleasePID);
+}
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#if defined (SUPPORT_SGX)
+#if defined (PDUMP)
+
+#include <asm/atomic.h>
+#include <stdarg.h>
+#include "sgxdefs.h"
+#include "services_headers.h"
+
+#include "pvrversion.h"
+#include "pvr_debug.h"
+
+#include "dbgdrvif.h"
+#include "sgxmmu.h"
+#include "mm.h"
+#include "pdump_km.h"
+
+#include <linux/tty.h>
+
+static IMG_BOOL PDumpWriteString2 (IMG_CHAR * pszString, IMG_UINT32 ui32Flags);
+static IMG_BOOL PDumpWriteILock (PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32Count, IMG_UINT32 ui32Flags);
+static IMG_VOID DbgSetFrame (PDBG_STREAM psStream, IMG_UINT32 ui32Frame);
+static IMG_UINT32 DbgGetFrame (PDBG_STREAM psStream);
+static IMG_VOID DbgSetMarker (PDBG_STREAM psStream, IMG_UINT32 ui32Marker);
+static IMG_UINT32 DbgWrite (PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32BCount, IMG_UINT32 ui32Flags);
+
+#define PDUMP_DATAMASTER_PIXEL (1)
+#define PDUMP_DATAMASTER_EDM (3)
+
+#define MIN(a,b) (a > b ? b : a)
+
+#define MAX_FILE_SIZE 0x40000000
+
+static atomic_t gsPDumpSuspended = ATOMIC_INIT(0);
+
+static PDBGKM_SERVICE_TABLE gpfnDbgDrv = IMG_NULL;
+
+
+
+IMG_CHAR *pszStreamName[PDUMP_NUM_STREAMS] = { "ParamStream2",
+ "ScriptStream2",
+ "DriverInfoStream"};
+typedef struct PDBG_PDUMP_STATE_TAG
+{
+ PDBG_STREAM psStream[PDUMP_NUM_STREAMS];
+ IMG_UINT32 ui32ParamFileNum;
+
+ IMG_CHAR *pszMsg;
+ IMG_CHAR *pszScript;
+ IMG_CHAR *pszFile;
+
+} PDBG_PDUMP_STATE;
+
+static PDBG_PDUMP_STATE gsDBGPdumpState = {{IMG_NULL}, 0, IMG_NULL, IMG_NULL, IMG_NULL};
+
+#define SZ_MSG_SIZE_MAX PVRSRV_PDUMP_MAX_COMMENT_SIZE-1
+#define SZ_SCRIPT_SIZE_MAX PVRSRV_PDUMP_MAX_COMMENT_SIZE-1
+#define SZ_FILENAME_SIZE_MAX PVRSRV_PDUMP_MAX_COMMENT_SIZE-1
+
+
+
+
+IMG_VOID DBGDrvGetServiceTable(IMG_VOID **fn_table);
+
+static inline IMG_BOOL PDumpSuspended(IMG_VOID)
+{
+ return atomic_read(&gsPDumpSuspended) != 0;
+}
+
+PVRSRV_ERROR PDumpOSGetScriptString(IMG_HANDLE *phScript,
+ IMG_UINT32 *pui32MaxLen)
+{
+ *phScript = (IMG_HANDLE)gsDBGPdumpState.pszScript;
+ *pui32MaxLen = SZ_SCRIPT_SIZE_MAX;
+ if ((!*phScript) || PDumpSuspended())
+ {
+ return PVRSRV_ERROR_GENERIC;
+ }
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpOSGetMessageString(IMG_HANDLE *phMsg,
+ IMG_UINT32 *pui32MaxLen)
+{
+ *phMsg = (IMG_HANDLE)gsDBGPdumpState.pszMsg;
+ *pui32MaxLen = SZ_MSG_SIZE_MAX;
+ if ((!*phMsg) || PDumpSuspended())
+ {
+ return PVRSRV_ERROR_GENERIC;
+ }
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpOSGetFilenameString(IMG_CHAR **ppszFile,
+ IMG_UINT32 *pui32MaxLen)
+{
+ *ppszFile = gsDBGPdumpState.pszFile;
+ *pui32MaxLen = SZ_FILENAME_SIZE_MAX;
+ if ((!*ppszFile) || PDumpSuspended())
+ {
+ return PVRSRV_ERROR_GENERIC;
+ }
+ return PVRSRV_OK;
+}
+
+IMG_BOOL PDumpOSWriteString2(IMG_HANDLE hScript, IMG_UINT32 ui32Flags)
+{
+ return PDumpWriteString2(hScript, ui32Flags);
+}
+
+PVRSRV_ERROR PDumpOSBufprintf(IMG_HANDLE hBuf, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, ...)
+{
+ IMG_CHAR* pszBuf = hBuf;
+ IMG_UINT32 n;
+ va_list vaArgs;
+
+ va_start(vaArgs, pszFormat);
+
+ n = vsnprintf(pszBuf, ui32ScriptSizeMax, pszFormat, vaArgs);
+
+ va_end(vaArgs);
+
+ if (n>=ui32ScriptSizeMax || n==-1)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete."));
+
+ return PVRSRV_ERROR_PDUMP_BUF_OVERFLOW;
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpOSVSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, PDUMP_va_list vaArgs)
+{
+ IMG_UINT32 n;
+
+ n = vsnprintf(pszComment, ui32ScriptSizeMax, pszFormat, vaArgs);
+
+ if (n>=ui32ScriptSizeMax || n==-1)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete."));
+
+ return PVRSRV_ERROR_PDUMP_BUF_OVERFLOW;
+ }
+
+ return PVRSRV_OK;
+}
+
+IMG_VOID PDumpOSDebugPrintf(IMG_CHAR* pszFormat, ...)
+{
+
+}
+
+PVRSRV_ERROR PDumpOSSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR *pszFormat, ...)
+{
+ IMG_UINT32 n;
+ va_list vaArgs;
+
+ va_start(vaArgs, pszFormat);
+
+ n = vsnprintf(pszComment, ui32ScriptSizeMax, pszFormat, vaArgs);
+
+ va_end(vaArgs);
+
+ if (n>=ui32ScriptSizeMax || n==-1)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete."));
+
+ return PVRSRV_ERROR_PDUMP_BUF_OVERFLOW;
+ }
+
+ return PVRSRV_OK;
+}
+
+IMG_UINT32 PDumpOSBuflen(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax)
+{
+ IMG_CHAR* pszBuf = hBuffer;
+ IMG_UINT32 ui32Count = 0;
+
+ while ((pszBuf[ui32Count]!=0) && (ui32Count<ui32BufferSizeMax) )
+ {
+ ui32Count++;
+ }
+ return(ui32Count);
+}
+
+IMG_VOID PDumpOSVerifyLineEnding(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax)
+{
+ IMG_UINT32 ui32Count = 0;
+ IMG_CHAR* pszBuf = hBuffer;
+
+
+ ui32Count = PDumpOSBuflen(hBuffer, ui32BufferSizeMax);
+
+
+ if ((ui32Count >= 1) && (pszBuf[ui32Count-1] != '\n') && (ui32Count<ui32BufferSizeMax))
+ {
+ pszBuf[ui32Count] = '\n';
+ ui32Count++;
+ pszBuf[ui32Count] = '\0';
+ }
+ if ((ui32Count >= 2) && (pszBuf[ui32Count-2] != '\r') && (ui32Count<ui32BufferSizeMax))
+ {
+ pszBuf[ui32Count-1] = '\r';
+ pszBuf[ui32Count] = '\n';
+ ui32Count++;
+ pszBuf[ui32Count] = '\0';
+ }
+}
+
+IMG_HANDLE PDumpOSGetStream(IMG_UINT32 ePDumpStream)
+{
+ return (IMG_HANDLE)gsDBGPdumpState.psStream[ePDumpStream];
+}
+
+IMG_UINT32 PDumpOSGetStreamOffset(IMG_UINT32 ePDumpStream)
+{
+ PDBG_STREAM psStream = gsDBGPdumpState.psStream[ePDumpStream];
+ return gpfnDbgDrv->pfnGetStreamOffset(psStream);
+}
+
+IMG_UINT32 PDumpOSGetParamFileNum(IMG_VOID)
+{
+ return gsDBGPdumpState.ui32ParamFileNum;
+}
+
+IMG_BOOL PDumpOSWriteString(IMG_HANDLE hStream,
+ IMG_UINT8 *psui8Data,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32Flags)
+{
+ PDBG_STREAM psStream = (PDBG_STREAM)hStream;
+ return PDumpWriteILock(psStream,
+ psui8Data,
+ ui32Size,
+ ui32Flags);
+}
+
+IMG_VOID PDumpOSCheckForSplitting(IMG_HANDLE hStream, IMG_UINT32 ui32Size, IMG_UINT32 ui32Flags)
+{
+
+ PVR_UNREFERENCED_PARAMETER(hStream);
+ PVR_UNREFERENCED_PARAMETER(ui32Size);
+ PVR_UNREFERENCED_PARAMETER(ui32Size);
+}
+
+IMG_BOOL PDumpOSJTInitialised(IMG_VOID)
+{
+ if(gpfnDbgDrv)
+ {
+ return IMG_TRUE;
+ }
+ return IMG_FALSE;
+}
+
+inline IMG_BOOL PDumpOSIsSuspended(IMG_VOID)
+{
+ return atomic_read(&gsPDumpSuspended) != 0;
+}
+
+IMG_VOID PDumpOSCPUVAddrToDevPAddr(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT8 *pui8LinAddr,
+ IMG_UINT32 ui32PageSize,
+ IMG_DEV_PHYADDR *psDevPAddr)
+{
+ if(hOSMemHandle)
+ {
+
+ IMG_CPU_PHYADDR sCpuPAddr;
+
+ PVR_UNREFERENCED_PARAMETER(pui8LinAddr);
+
+ sCpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, ui32Offset);
+ PVR_ASSERT((sCpuPAddr.uiAddr & (ui32PageSize - 1)) == 0);
+
+
+ *psDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
+ }
+ else
+ {
+ IMG_CPU_PHYADDR sCpuPAddr;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Offset);
+
+ sCpuPAddr = OSMapLinToCPUPhys(pui8LinAddr);
+ *psDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
+ }
+}
+
+IMG_VOID PDumpOSCPUVAddrToPhysPages(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32Offset,
+ IMG_PUINT8 pui8LinAddr,
+ IMG_UINT32 *pui32PageOffset)
+{
+ if(hOSMemHandle)
+ {
+
+ IMG_CPU_PHYADDR sCpuPAddr;
+
+ PVR_UNREFERENCED_PARAMETER(pui8LinAddr);
+
+ sCpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, ui32Offset);
+ *pui32PageOffset = sCpuPAddr.uiAddr & (HOST_PAGESIZE() -1);
+ }
+ else
+ {
+ PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+ PVR_UNREFERENCED_PARAMETER(ui32Offset);
+
+ *pui32PageOffset = (IMG_UINT32)pui8LinAddr & (HOST_PAGESIZE() - 1);
+ }
+}
+
+
+
+IMG_VOID PDumpInit(IMG_VOID)
+{
+ IMG_UINT32 i;
+
+
+ if (!gpfnDbgDrv)
+ {
+ DBGDrvGetServiceTable((IMG_VOID **)&gpfnDbgDrv);
+
+
+
+
+ if (gpfnDbgDrv == IMG_NULL)
+ {
+ return;
+ }
+
+ if(!gsDBGPdumpState.pszFile)
+ {
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_FILENAME_SIZE_MAX, (IMG_PVOID *)&gsDBGPdumpState.pszFile, 0,
+ "Filename string") != PVRSRV_OK)
+ {
+ goto init_failed;
+ }
+ }
+
+ if(!gsDBGPdumpState.pszMsg)
+ {
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_MSG_SIZE_MAX, (IMG_PVOID *)&gsDBGPdumpState.pszMsg, 0,
+ "Message string") != PVRSRV_OK)
+ {
+ goto init_failed;
+ }
+ }
+
+ if(!gsDBGPdumpState.pszScript)
+ {
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_SCRIPT_SIZE_MAX, (IMG_PVOID *)&gsDBGPdumpState.pszScript, 0,
+ "Script string") != PVRSRV_OK)
+ {
+ goto init_failed;
+ }
+ }
+
+ for(i=0; i < PDUMP_NUM_STREAMS; i++)
+ {
+ gsDBGPdumpState.psStream[i] = gpfnDbgDrv->pfnCreateStream(pszStreamName[i],
+ DEBUG_CAPMODE_FRAMED,
+ DEBUG_OUTMODE_STREAMENABLE,
+ 0,
+ 10);
+
+ gpfnDbgDrv->pfnSetCaptureMode(gsDBGPdumpState.psStream[i],DEBUG_CAPMODE_FRAMED,0xFFFFFFFF, 0xFFFFFFFF, 1);
+ gpfnDbgDrv->pfnSetFrame(gsDBGPdumpState.psStream[i],0);
+ }
+
+ PDUMPCOMMENT("Driver Product Name: %s", VS_PRODUCT_NAME);
+ PDUMPCOMMENT("Driver Product Version: %s (%s)", PVRVERSION_STRING, PVRVERSION_FILE);
+ PDUMPCOMMENT("Start of Init Phase");
+ }
+
+ return;
+
+init_failed:
+
+ if(gsDBGPdumpState.pszFile)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_FILENAME_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszFile, 0);
+ gsDBGPdumpState.pszFile = IMG_NULL;
+ }
+
+ if(gsDBGPdumpState.pszScript)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_SCRIPT_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszScript, 0);
+ gsDBGPdumpState.pszScript = IMG_NULL;
+ }
+
+ if(gsDBGPdumpState.pszMsg)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_MSG_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszMsg, 0);
+ gsDBGPdumpState.pszMsg = IMG_NULL;
+ }
+
+ gpfnDbgDrv = IMG_NULL;
+}
+
+
+IMG_VOID PDumpDeInit(IMG_VOID)
+{
+ IMG_UINT32 i;
+
+ for(i=0; i < PDUMP_NUM_STREAMS; i++)
+ {
+ gpfnDbgDrv->pfnDestroyStream(gsDBGPdumpState.psStream[i]);
+ }
+
+ if(gsDBGPdumpState.pszFile)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_FILENAME_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszFile, 0);
+ gsDBGPdumpState.pszFile = IMG_NULL;
+ }
+
+ if(gsDBGPdumpState.pszScript)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_SCRIPT_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszScript, 0);
+ gsDBGPdumpState.pszScript = IMG_NULL;
+ }
+
+ if(gsDBGPdumpState.pszMsg)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_MSG_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszMsg, 0);
+ gsDBGPdumpState.pszMsg = IMG_NULL;
+ }
+
+ gpfnDbgDrv = IMG_NULL;
+}
+
+PVRSRV_ERROR PDumpStartInitPhaseKM(IMG_VOID)
+{
+ IMG_UINT32 i;
+
+ if (gpfnDbgDrv)
+ {
+ PDUMPCOMMENT("Start Init Phase");
+ for(i=0; i < PDUMP_NUM_STREAMS; i++)
+ {
+ gpfnDbgDrv->pfnStartInitPhase(gsDBGPdumpState.psStream[i]);
+ }
+ }
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpStopInitPhaseKM(IMG_VOID)
+{
+ IMG_UINT32 i;
+
+ if (gpfnDbgDrv)
+ {
+ PDUMPCOMMENT("Stop Init Phase");
+
+ for(i=0; i < PDUMP_NUM_STREAMS; i++)
+ {
+ gpfnDbgDrv->pfnStopInitPhase(gsDBGPdumpState.psStream[i]);
+ }
+ }
+ return PVRSRV_OK;
+}
+
+IMG_BOOL PDumpIsLastCaptureFrameKM(IMG_VOID)
+{
+ return gpfnDbgDrv->pfnIsLastCaptureFrame(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2]);
+}
+
+
+IMG_BOOL PDumpIsCaptureFrameKM(IMG_VOID)
+{
+ if (PDumpSuspended())
+ {
+ return IMG_FALSE;
+ }
+ return gpfnDbgDrv->pfnIsCaptureFrame(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2], IMG_FALSE);
+}
+
+PVRSRV_ERROR PDumpSetFrameKM(IMG_UINT32 ui32Frame)
+{
+ IMG_UINT32 ui32Stream;
+
+ for (ui32Stream = 0; ui32Stream < PDUMP_NUM_STREAMS; ui32Stream++)
+ {
+ if (gsDBGPdumpState.psStream[ui32Stream])
+ {
+ DbgSetFrame(gsDBGPdumpState.psStream[ui32Stream], ui32Frame);
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpGetFrameKM(IMG_PUINT32 pui32Frame)
+{
+ *pui32Frame = DbgGetFrame(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2]);
+
+ return PVRSRV_OK;
+}
+
+
+
+static IMG_BOOL PDumpWriteString2(IMG_CHAR * pszString, IMG_UINT32 ui32Flags)
+{
+ return PDumpWriteILock(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2], (IMG_UINT8 *) pszString, strlen(pszString), ui32Flags);
+}
+
+
+static IMG_BOOL PDumpWriteILock(PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32Count, IMG_UINT32 ui32Flags)
+{
+ IMG_UINT32 ui32Written = 0;
+ IMG_UINT32 ui32Off = 0;
+
+ if ((psStream == IMG_NULL) || PDumpSuspended() || ((ui32Flags & PDUMP_FLAGS_NEVER) != 0))
+ {
+ return IMG_TRUE;
+ }
+
+
+
+
+ if (psStream == gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2])
+ {
+ IMG_UINT32 ui32ParamOutPos = gpfnDbgDrv->pfnGetStreamOffset(gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2]);
+
+ if (ui32ParamOutPos + ui32Count > MAX_FILE_SIZE)
+ {
+ if ((gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2] && PDumpWriteString2("\r\n-- Splitting pdump output file\r\n\r\n", ui32Flags)))
+ {
+ DbgSetMarker(gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2], ui32ParamOutPos);
+ gsDBGPdumpState.ui32ParamFileNum++;
+ }
+ }
+ }
+
+
+ while (((IMG_UINT32) ui32Count > 0) && (ui32Written != 0xFFFFFFFF))
+ {
+ ui32Written = DbgWrite(psStream, &pui8Data[ui32Off], ui32Count, ui32Flags);
+
+
+
+
+ if (ui32Written == 0)
+ {
+ OSReleaseThreadQuanta();
+ }
+
+ if (ui32Written != 0xFFFFFFFF)
+ {
+ ui32Off += ui32Written;
+ ui32Count -= ui32Written;
+ }
+ }
+
+ if (ui32Written == 0xFFFFFFFF)
+ {
+ return IMG_FALSE;
+ }
+
+ return IMG_TRUE;
+}
+
+static IMG_VOID DbgSetFrame(PDBG_STREAM psStream, IMG_UINT32 ui32Frame)
+{
+ gpfnDbgDrv->pfnSetFrame(psStream, ui32Frame);
+}
+
+
+static IMG_UINT32 DbgGetFrame(PDBG_STREAM psStream)
+{
+ return gpfnDbgDrv->pfnGetFrame(psStream);
+}
+
+static IMG_VOID DbgSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker)
+{
+ gpfnDbgDrv->pfnSetMarker(psStream, ui32Marker);
+}
+
+static IMG_UINT32 DbgWrite(PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32BCount, IMG_UINT32 ui32Flags)
+{
+ IMG_UINT32 ui32BytesWritten;
+
+ if ((ui32Flags & PDUMP_FLAGS_CONTINUOUS) != 0)
+ {
+
+
+ if (((psStream->ui32CapMode & DEBUG_CAPMODE_FRAMED) != 0) &&
+ (psStream->ui32Start == 0xFFFFFFFFUL) &&
+ (psStream->ui32End == 0xFFFFFFFFUL) &&
+ psStream->bInitPhaseComplete)
+ {
+ ui32BytesWritten = ui32BCount;
+ }
+ else
+ {
+ ui32BytesWritten = gpfnDbgDrv->pfnDBGDrivWrite2(psStream, pui8Data, ui32BCount, 1);
+ }
+ }
+ else
+ {
+ if (ui32Flags & PDUMP_FLAGS_LASTFRAME)
+ {
+ IMG_UINT32 ui32DbgFlags;
+
+ ui32DbgFlags = 0;
+ if (ui32Flags & PDUMP_FLAGS_RESETLFBUFFER)
+ {
+ ui32DbgFlags |= WRITELF_FLAGS_RESETBUF;
+ }
+
+ ui32BytesWritten = gpfnDbgDrv->pfnWriteLF(psStream, pui8Data, ui32BCount, 1, ui32DbgFlags);
+ }
+ else
+ {
+ ui32BytesWritten = gpfnDbgDrv->pfnWriteBINCM(psStream, pui8Data, ui32BCount, 1);
+ }
+ }
+
+ return ui32BytesWritten;
+}
+
+
+IMG_VOID PDumpSuspendKM(IMG_VOID)
+{
+ atomic_inc(&gsPDumpSuspended);
+}
+
+IMG_VOID PDumpResumeKM(IMG_VOID)
+{
+ atomic_dec(&gsPDumpSuspended);
+}
+
+#endif
+#endif
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef __INCLUDED_PRIVATE_DATA_H_
+#define __INCLUDED_PRIVATE_DATA_H_
+
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+#include <linux/list.h>
+#include <drm/drmP.h>
+#endif
+
+typedef struct
+{
+
+ IMG_UINT32 ui32OpenPID;
+
+#if defined(PVR_SECURE_FD_EXPORT)
+
+ IMG_HANDLE hKernelMemInfo;
+#endif
+
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+
+ struct list_head sDRMAuthListItem;
+
+ struct drm_file *psDRMFile;
+#endif
+
+#if defined(SUPPORT_MEMINFO_IDS)
+
+ IMG_UINT64 ui64Stamp;
+#endif
+
+
+ IMG_HANDLE hBlockAlloc;
+
+#if defined(SUPPORT_DRI_DRM_EXT)
+ IMG_PVOID pPriv;
+#endif
+}
+PVRSRV_FILE_PRIVATE_DATA;
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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/init.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+#include "services_headers.h"
+
+#include "queue.h"
+#include "resman.h"
+#include "pvrmmap.h"
+#include "pvr_debug.h"
+#include "pvrversion.h"
+#include "proc.h"
+#include "perproc.h"
+#include "env_perproc.h"
+#include "linkage.h"
+
+#include "lists.h"
+DECLARE_LIST_ANY_VA(PVRSRV_DEVICE_NODE);
+
+
+static struct proc_dir_entry * dir;
+
+#ifndef PVR_PROC_USE_SEQ_FILE
+static off_t procDumpSysNodes(IMG_CHAR *buf, size_t size, off_t off);
+static off_t procDumpVersion(IMG_CHAR *buf, size_t size, off_t off);
+#endif
+
+
+static const IMG_CHAR PVRProcDirRoot[] = "pvr";
+
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+
+#define PVR_PROC_SEQ_START_TOKEN (void*)1
+static IMG_INT pvr_proc_open(struct inode *inode,struct file *file);
+static void *pvr_proc_seq_start (struct seq_file *m, loff_t *pos);
+static void pvr_proc_seq_stop (struct seq_file *m, void *v);
+static void *pvr_proc_seq_next (struct seq_file *m, void *v, loff_t *pos);
+static int pvr_proc_seq_show (struct seq_file *m, void *v);
+static ssize_t pvr_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos);
+
+static struct file_operations pvr_proc_operations =
+{
+ .open = pvr_proc_open,
+ .read = seq_read,
+ .write = pvr_proc_write,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+static struct seq_operations pvr_proc_seq_operations =
+{
+ .start = pvr_proc_seq_start,
+ .next = pvr_proc_seq_next,
+ .stop = pvr_proc_seq_stop,
+ .show = pvr_proc_seq_show,
+};
+
+static struct proc_dir_entry* g_pProcQueue;
+static struct proc_dir_entry* g_pProcVersion;
+static struct proc_dir_entry* g_pProcSysNodes;
+
+#ifdef DEBUG
+static struct proc_dir_entry* g_pProcDebugLevel;
+#endif
+
+#ifdef PVR_MANUAL_POWER_CONTROL
+static struct proc_dir_entry* g_pProcPowerLevel;
+#endif
+
+
+static void ProcSeqShowVersion(struct seq_file *sfile,void* el);
+
+static void ProcSeqShowSysNodes(struct seq_file *sfile,void* el);
+static void* ProcSeqOff2ElementSysNodes(struct seq_file * sfile, loff_t off);
+
+#endif
+
+off_t printAppend(IMG_CHAR * buffer, size_t size, off_t off, const IMG_CHAR * format, ...)
+{
+ IMG_INT n;
+ size_t space = size - (size_t)off;
+ va_list ap;
+
+ PVR_ASSERT(space >= 0);
+
+ va_start (ap, format);
+
+ n = vsnprintf (buffer+off, space, format, ap);
+
+ va_end (ap);
+
+ if (n >= (IMG_INT)space || n < 0)
+ {
+
+ buffer[size - 1] = 0;
+ return (off_t)(size - 1);
+ }
+ else
+ {
+ return (off + (off_t)n);
+ }
+}
+
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+
+void* ProcSeq1ElementOff2Element(struct seq_file *sfile, loff_t off)
+{
+
+ if(!off)
+ return (void*)2;
+ return NULL;
+}
+
+
+void* ProcSeq1ElementHeaderOff2Element(struct seq_file *sfile, loff_t off)
+{
+ if(!off)
+ {
+ return PVR_PROC_SEQ_START_TOKEN;
+ }
+
+
+ if(off == 1)
+ return (void*)2;
+
+ return NULL;
+}
+
+
+static IMG_INT pvr_proc_open(struct inode *inode,struct file *file)
+{
+ IMG_INT ret = seq_open(file, &pvr_proc_seq_operations);
+
+ struct seq_file *seq = (struct seq_file*)file->private_data;
+ struct proc_dir_entry* pvr_proc_entry = PDE(inode);
+
+
+ seq->private = pvr_proc_entry->data;
+ return ret;
+}
+
+static ssize_t pvr_proc_write(struct file *file, const char __user *buffer,
+ size_t count, loff_t *ppos)
+{
+ struct inode *inode = file->f_path.dentry->d_inode;
+ struct proc_dir_entry * dp;
+
+ dp = PDE(inode);
+
+ if (!dp->write_proc)
+ return -EIO;
+
+ return dp->write_proc(file, buffer, count, dp->data);
+}
+
+
+static void *pvr_proc_seq_start (struct seq_file *proc_seq_file, loff_t *pos)
+{
+ PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)proc_seq_file->private;
+ if(handlers->startstop != NULL)
+ handlers->startstop(proc_seq_file, IMG_TRUE);
+ return handlers->off2element(proc_seq_file, *pos);
+}
+
+static void pvr_proc_seq_stop (struct seq_file *proc_seq_file, void *v)
+{
+ PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)proc_seq_file->private;
+ if(handlers->startstop != NULL)
+ handlers->startstop(proc_seq_file, IMG_FALSE);
+}
+
+static void *pvr_proc_seq_next (struct seq_file *proc_seq_file, void *v, loff_t *pos)
+{
+ PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)proc_seq_file->private;
+ (*pos)++;
+ if( handlers->next != NULL)
+ return handlers->next( proc_seq_file, v, *pos );
+ return handlers->off2element(proc_seq_file, *pos);
+}
+
+static int pvr_proc_seq_show (struct seq_file *proc_seq_file, void *v)
+{
+ PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)proc_seq_file->private;
+ handlers->show( proc_seq_file,v );
+ return 0;
+}
+
+
+
+static struct proc_dir_entry* CreateProcEntryInDirSeq(
+ struct proc_dir_entry *pdir,
+ const IMG_CHAR * name,
+ IMG_VOID* data,
+ pvr_next_proc_seq_t next_handler,
+ pvr_show_proc_seq_t show_handler,
+ pvr_off2element_proc_seq_t off2element_handler,
+ pvr_startstop_proc_seq_t startstop_handler,
+ write_proc_t whandler
+ )
+{
+
+ struct proc_dir_entry * file;
+ mode_t mode;
+
+ if (!dir)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcEntryInDirSeq: cannot make proc entry /proc/%s/%s: no parent", PVRProcDirRoot, name));
+ return NULL;
+ }
+
+ mode = S_IFREG;
+
+ if (show_handler)
+ {
+ mode |= S_IRUGO;
+ }
+
+ if (whandler)
+ {
+ mode |= S_IWUSR;
+ }
+
+ file=create_proc_entry(name, mode, pdir);
+
+ if (file)
+ {
+ PVR_PROC_SEQ_HANDLERS *seq_handlers;
+
+ file->proc_fops = &pvr_proc_operations;
+ file->write_proc = whandler;
+
+
+ file->data = kmalloc(sizeof(PVR_PROC_SEQ_HANDLERS), GFP_KERNEL);
+ if(file->data)
+ {
+ seq_handlers = (PVR_PROC_SEQ_HANDLERS*)file->data;
+ seq_handlers->next = next_handler;
+ seq_handlers->show = show_handler;
+ seq_handlers->off2element = off2element_handler;
+ seq_handlers->startstop = startstop_handler;
+ seq_handlers->data = data;
+
+ return file;
+ }
+ }
+
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcEntryInDirSeq: cannot make proc entry /proc/%s/%s: no memory", PVRProcDirRoot, name));
+ return 0;
+}
+
+
+struct proc_dir_entry* CreateProcReadEntrySeq (
+ const IMG_CHAR * name,
+ IMG_VOID* data,
+ pvr_next_proc_seq_t next_handler,
+ pvr_show_proc_seq_t show_handler,
+ pvr_off2element_proc_seq_t off2element_handler,
+ pvr_startstop_proc_seq_t startstop_handler
+ )
+{
+ return CreateProcEntrySeq(name,
+ data,
+ next_handler,
+ show_handler,
+ off2element_handler,
+ startstop_handler,
+ NULL);
+}
+
+struct proc_dir_entry* CreateProcEntrySeq (
+ const IMG_CHAR * name,
+ IMG_VOID* data,
+ pvr_next_proc_seq_t next_handler,
+ pvr_show_proc_seq_t show_handler,
+ pvr_off2element_proc_seq_t off2element_handler,
+ pvr_startstop_proc_seq_t startstop_handler,
+ write_proc_t whandler
+ )
+{
+ return CreateProcEntryInDirSeq(
+ dir,
+ name,
+ data,
+ next_handler,
+ show_handler,
+ off2element_handler,
+ startstop_handler,
+ NULL
+ );
+}
+
+
+
+struct proc_dir_entry* CreatePerProcessProcEntrySeq (
+ const IMG_CHAR * name,
+ IMG_VOID* data,
+ pvr_next_proc_seq_t next_handler,
+ pvr_show_proc_seq_t show_handler,
+ pvr_off2element_proc_seq_t off2element_handler,
+ pvr_startstop_proc_seq_t startstop_handler,
+ write_proc_t whandler
+ )
+{
+ PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
+ IMG_UINT32 ui32PID;
+
+ if (!dir)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntrySeq: /proc/%s doesn't exist", PVRProcDirRoot));
+ return NULL;
+ }
+
+ ui32PID = OSGetCurrentProcessIDKM();
+
+ psPerProc = PVRSRVPerProcessPrivateData(ui32PID);
+ if (!psPerProc)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntrySeq: no per process data"));
+
+ return NULL;
+ }
+
+ if (!psPerProc->psProcDir)
+ {
+ IMG_CHAR dirname[16];
+ IMG_INT ret;
+
+ ret = snprintf(dirname, sizeof(dirname), "%lu", ui32PID);
+
+ if (ret <=0 || ret >= (IMG_INT)sizeof(dirname))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: couldn't generate per process proc directory name \"%u\"", ui32PID));
+ return NULL;
+ }
+ else
+ {
+ psPerProc->psProcDir = proc_mkdir(dirname, dir);
+ if (!psPerProc->psProcDir)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: couldn't create per process proc directory /proc/%s/%u",
+ PVRProcDirRoot, ui32PID));
+ return NULL;
+ }
+ }
+ }
+
+ return CreateProcEntryInDirSeq(psPerProc->psProcDir, name, data, next_handler,
+ show_handler,off2element_handler,startstop_handler,whandler);
+}
+
+
+IMG_VOID RemoveProcEntrySeq( struct proc_dir_entry* proc_entry )
+{
+ if (dir)
+ {
+ void* data = proc_entry->data ;
+ PVR_DPF((PVR_DBG_MESSAGE, "Removing /proc/%s/%s", PVRProcDirRoot, proc_entry->name));
+
+ remove_proc_entry(proc_entry->name, dir);
+ if( data)
+ kfree( data );
+
+ }
+}
+
+IMG_VOID RemovePerProcessProcEntrySeq(struct proc_dir_entry* proc_entry)
+{
+ PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
+
+ psPerProc = LinuxTerminatingProcessPrivateData();
+ if (!psPerProc)
+ {
+ psPerProc = PVRSRVFindPerProcessPrivateData();
+ if (!psPerProc)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: can't "
+ "remove %s, no per process data", proc_entry->name));
+ return;
+ }
+ }
+
+ if (psPerProc->psProcDir)
+ {
+ void* data = proc_entry->data ;
+ PVR_DPF((PVR_DBG_MESSAGE, "Removing proc entry %s from %s", proc_entry->name, psPerProc->psProcDir->name));
+
+ remove_proc_entry(proc_entry->name, psPerProc->psProcDir);
+ if(data)
+ kfree( data );
+ }
+}
+
+#endif
+
+static IMG_INT pvr_read_proc(IMG_CHAR *page, IMG_CHAR **start, off_t off,
+ IMG_INT count, IMG_INT *eof, IMG_VOID *data)
+{
+ pvr_read_proc_t *pprn = (pvr_read_proc_t *)data;
+
+ off_t len = pprn (page, (size_t)count, off);
+
+ if (len == END_OF_FILE)
+ {
+ len = 0;
+ *eof = 1;
+ }
+ else if (!len)
+ {
+ *start = (IMG_CHAR *) 0;
+ }
+ else
+ {
+ *start = (IMG_CHAR *) 1;
+ }
+
+ return len;
+}
+
+
+static IMG_INT CreateProcEntryInDir(struct proc_dir_entry *pdir, const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data)
+{
+ struct proc_dir_entry * file;
+ mode_t mode;
+
+ if (!pdir)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcEntryInDir: parent directory doesn't exist"));
+
+ return -ENOMEM;
+ }
+
+ mode = S_IFREG;
+
+ if (rhandler)
+ {
+ mode |= S_IRUGO;
+ }
+
+ if (whandler)
+ {
+ mode |= S_IWUSR;
+ }
+
+ file = create_proc_entry(name, mode, pdir);
+
+ if (file)
+ {
+ file->read_proc = rhandler;
+ file->write_proc = whandler;
+ file->data = data;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "Created proc entry %s in %s", name, pdir->name));
+
+ return 0;
+ }
+
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcEntry: cannot create proc entry %s in %s", name, pdir->name));
+
+ return -ENOMEM;
+}
+
+
+IMG_INT CreateProcEntry(const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data)
+{
+ return CreateProcEntryInDir(dir, name, rhandler, whandler, data);
+}
+
+
+IMG_INT CreatePerProcessProcEntry(const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data)
+{
+ PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
+ IMG_UINT32 ui32PID;
+
+ if (!dir)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: /proc/%s doesn't exist", PVRProcDirRoot));
+
+ return -ENOMEM;
+ }
+
+ ui32PID = OSGetCurrentProcessIDKM();
+
+ psPerProc = PVRSRVPerProcessPrivateData(ui32PID);
+ if (!psPerProc)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: no per process data"));
+
+ return -ENOMEM;
+ }
+
+ if (!psPerProc->psProcDir)
+ {
+ IMG_CHAR dirname[16];
+ IMG_INT ret;
+
+ ret = snprintf(dirname, sizeof(dirname), "%lu", ui32PID);
+
+ if (ret <=0 || ret >= (IMG_INT)sizeof(dirname))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: couldn't generate per process proc directory name \"%u\"", ui32PID));
+
+ return -ENOMEM;
+ }
+ else
+ {
+ psPerProc->psProcDir = proc_mkdir(dirname, dir);
+ if (!psPerProc->psProcDir)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: couldn't create per process proc directory /proc/%s/%u", PVRProcDirRoot, ui32PID));
+
+ return -ENOMEM;
+ }
+ }
+ }
+
+ return CreateProcEntryInDir(psPerProc->psProcDir, name, rhandler, whandler, data);
+}
+
+
+IMG_INT CreateProcReadEntry(const IMG_CHAR * name, pvr_read_proc_t handler)
+{
+ struct proc_dir_entry * file;
+
+ if (!dir)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcReadEntry: cannot make proc entry /proc/%s/%s: no parent", PVRProcDirRoot, name));
+
+ return -ENOMEM;
+ }
+
+ file = create_proc_read_entry (name, S_IFREG | S_IRUGO, dir, pvr_read_proc, (IMG_VOID *)handler);
+
+ if (file)
+ return 0;
+
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcReadEntry: cannot make proc entry /proc/%s/%s: no memory", PVRProcDirRoot, name));
+
+ return -ENOMEM;
+}
+
+
+IMG_INT CreateProcEntries(IMG_VOID)
+{
+ dir = proc_mkdir (PVRProcDirRoot, NULL);
+
+ if (!dir)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcEntries: cannot make /proc/%s directory", PVRProcDirRoot));
+
+ return -ENOMEM;
+ }
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+ g_pProcQueue = CreateProcReadEntrySeq("queue", NULL, NULL, ProcSeqShowQueue, ProcSeqOff2ElementQueue, NULL);
+ g_pProcVersion = CreateProcReadEntrySeq("version", NULL, NULL, ProcSeqShowVersion, ProcSeq1ElementHeaderOff2Element, NULL);
+ g_pProcSysNodes = CreateProcReadEntrySeq("nodes", NULL, NULL, ProcSeqShowSysNodes, ProcSeqOff2ElementSysNodes, NULL);
+
+ if(!g_pProcQueue || !g_pProcVersion || !g_pProcSysNodes)
+#else
+ if (CreateProcReadEntry("queue", QueuePrintQueues) ||
+ CreateProcReadEntry("version", procDumpVersion) ||
+ CreateProcReadEntry("nodes", procDumpSysNodes))
+#endif
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcEntries: couldn't make /proc/%s files", PVRProcDirRoot));
+
+ return -ENOMEM;
+ }
+
+
+#ifdef DEBUG
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+ g_pProcDebugLevel = CreateProcEntrySeq("debug_level", NULL, NULL,
+ ProcSeqShowDebugLevel,
+ ProcSeq1ElementOff2Element, NULL,
+ PVRDebugProcSetLevel);
+ if(!g_pProcDebugLevel)
+#else
+ if (CreateProcEntry ("debug_level", PVRDebugProcGetLevel, PVRDebugProcSetLevel, 0))
+#endif
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcEntries: couldn't make /proc/%s/debug_level", PVRProcDirRoot));
+
+ return -ENOMEM;
+ }
+
+#ifdef PVR_MANUAL_POWER_CONTROL
+#ifdef PVR_PROC_USE_SEQ_FILE
+ g_pProcPowerLevel = CreateProcEntrySeq("power_control", NULL, NULL,
+ ProcSeqShowPowerLevel,
+ ProcSeq1ElementOff2Element, NULL,
+ PVRProcSetPowerLevel);
+ if(!g_pProcPowerLevel)
+#else
+ if (CreateProcEntry("power_control", PVRProcGetPowerLevel, PVRProcSetPowerLevel, 0))
+#endif
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcEntries: couldn't make /proc/%s/power_control", PVRProcDirRoot));
+
+ return -ENOMEM;
+ }
+#endif
+#endif
+
+ return 0;
+}
+
+
+IMG_VOID RemoveProcEntry(const IMG_CHAR * name)
+{
+ if (dir)
+ {
+ remove_proc_entry(name, dir);
+ PVR_DPF((PVR_DBG_MESSAGE, "Removing /proc/%s/%s", PVRProcDirRoot, name));
+ }
+}
+
+
+IMG_VOID RemovePerProcessProcEntry(const IMG_CHAR *name)
+{
+ PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
+
+ psPerProc = LinuxTerminatingProcessPrivateData();
+ if (!psPerProc)
+ {
+ psPerProc = PVRSRVFindPerProcessPrivateData();
+ if (!psPerProc)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: can't "
+ "remove %s, no per process data", name));
+ return;
+ }
+ }
+
+ if (psPerProc->psProcDir)
+ {
+ remove_proc_entry(name, psPerProc->psProcDir);
+
+ PVR_DPF((PVR_DBG_MESSAGE, "Removing proc entry %s from %s", name, psPerProc->psProcDir->name));
+ }
+}
+
+
+IMG_VOID RemovePerProcessProcDir(PVRSRV_ENV_PER_PROCESS_DATA *psPerProc)
+{
+ if (psPerProc->psProcDir)
+ {
+ while (psPerProc->psProcDir->subdir)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "Belatedly removing /proc/%s/%s/%s", PVRProcDirRoot, psPerProc->psProcDir->name, psPerProc->psProcDir->subdir->name));
+
+ RemoveProcEntry(psPerProc->psProcDir->subdir->name);
+ }
+ RemoveProcEntry(psPerProc->psProcDir->name);
+ }
+}
+
+IMG_VOID RemoveProcEntries(IMG_VOID)
+{
+#ifdef DEBUG
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+ RemoveProcEntrySeq( g_pProcDebugLevel );
+#else
+ RemoveProcEntry("debug_level");
+#endif
+
+#ifdef PVR_MANUAL_POWER_CONTROL
+#ifdef PVR_PROC_USE_SEQ_FILE
+ RemoveProcEntrySeq( g_pProcPowerLevel );
+#else
+ RemoveProcEntry("power_control");
+#endif
+#endif
+
+#endif
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+ RemoveProcEntrySeq(g_pProcQueue);
+ RemoveProcEntrySeq(g_pProcVersion);
+ RemoveProcEntrySeq(g_pProcSysNodes);
+#else
+ RemoveProcEntry("queue");
+ RemoveProcEntry("version");
+ RemoveProcEntry("nodes");
+#endif
+
+ while (dir->subdir)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "Belatedly removing /proc/%s/%s", PVRProcDirRoot, dir->subdir->name));
+
+ RemoveProcEntry(dir->subdir->name);
+ }
+
+ remove_proc_entry(PVRProcDirRoot, NULL);
+}
+
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+
+static void ProcSeqShowVersion(struct seq_file *sfile,void* el)
+{
+ SYS_DATA * psSysData;
+ IMG_CHAR *pszSystemVersionString = "None";
+
+ if(el == PVR_PROC_SEQ_START_TOKEN)
+ {
+ seq_printf( sfile,
+ "Version %s (%s) %s\n",
+ PVRVERSION_STRING,
+ PVR_BUILD_TYPE, PVR_BUILD_DIR);
+ return;
+ }
+
+ SysAcquireData(&psSysData);
+
+ if(psSysData->pszVersionString)
+ {
+ pszSystemVersionString = psSysData->pszVersionString;
+ }
+
+ seq_printf( sfile, "System Version String: %s\n", pszSystemVersionString);
+}
+
+#else
+
+static off_t procDumpVersion(IMG_CHAR *buf, size_t size, off_t off)
+{
+ SYS_DATA *psSysData;
+
+ if (off == 0)
+ {
+ return printAppend(buf, size, 0,
+ "Version %s (%s) %s\n",
+ PVRVERSION_STRING,
+ PVR_BUILD_TYPE, PVR_BUILD_DIR);
+ }
+
+ SysAcquireData(&psSysData)
+
+ if (off == 1)
+ {
+ IMG_CHAR *pszSystemVersionString = "None";
+
+ if(psSysData->pszVersionString)
+ {
+ pszSystemVersionString = psSysData->pszVersionString;
+ }
+
+ if(strlen(pszSystemVersionString)
+ + strlen("System Version String: \n")
+ + 1 > size)
+ {
+ return 0;
+ }
+ return printAppend(buf, size, 0,
+ "System Version String: %s\n",
+ pszSystemVersionString);
+ }
+
+ return END_OF_FILE;
+}
+
+#endif
+
+
+static const IMG_CHAR *deviceTypeToString(PVRSRV_DEVICE_TYPE deviceType)
+{
+ switch (deviceType)
+ {
+ default:
+ {
+ static IMG_CHAR text[10];
+
+ sprintf(text, "?%x", (IMG_UINT)deviceType);
+
+ return text;
+ }
+ }
+}
+
+
+static const IMG_CHAR *deviceClassToString(PVRSRV_DEVICE_CLASS deviceClass)
+{
+ switch (deviceClass)
+ {
+ case PVRSRV_DEVICE_CLASS_3D:
+ {
+ return "3D";
+ }
+ case PVRSRV_DEVICE_CLASS_DISPLAY:
+ {
+ return "display";
+ }
+ case PVRSRV_DEVICE_CLASS_BUFFER:
+ {
+ return "buffer";
+ }
+ default:
+ {
+ static IMG_CHAR text[10];
+
+ sprintf(text, "?%x", (IMG_UINT)deviceClass);
+ return text;
+ }
+ }
+}
+
+IMG_VOID* DecOffPsDev_AnyVaCb(PVRSRV_DEVICE_NODE *psNode, va_list va)
+{
+ off_t *pOff = va_arg(va, off_t*);
+ if (--(*pOff))
+ {
+ return IMG_NULL;
+ }
+ else
+ {
+ return psNode;
+ }
+}
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+
+static void ProcSeqShowSysNodes(struct seq_file *sfile,void* el)
+{
+ SYS_DATA * psSysData;
+ PVRSRV_DEVICE_NODE *psDevNode = (PVRSRV_DEVICE_NODE*)el;
+
+ if(el == PVR_PROC_SEQ_START_TOKEN)
+ {
+ seq_printf( sfile,
+ "Registered nodes\n"
+ "Addr Type Class Index Ref pvDev Size Res\n");
+ return;
+ }
+
+ SysAcquireData(&psSysData);
+
+ seq_printf( sfile,
+ "%p %-8s %-8s %4d %2lu %p %3lu %p\n",
+ psDevNode,
+ deviceTypeToString(psDevNode->sDevId.eDeviceType),
+ deviceClassToString(psDevNode->sDevId.eDeviceClass),
+ psDevNode->sDevId.eDeviceClass,
+ psDevNode->ui32RefCount,
+ psDevNode->pvDevice,
+ psDevNode->ui32pvDeviceSize,
+ psDevNode->hResManContext);
+
+}
+
+static void* ProcSeqOff2ElementSysNodes(struct seq_file * sfile, loff_t off)
+{
+ SYS_DATA *psSysData;
+ PVRSRV_DEVICE_NODE *psDevNode;
+ if(!off)
+ {
+ return PVR_PROC_SEQ_START_TOKEN;
+ }
+
+ SysAcquireData(&psSysData);
+
+
+ psDevNode = (PVRSRV_DEVICE_NODE*)
+ List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+ DecOffPsDev_AnyVaCb,
+ &off);
+
+
+ return (void*)psDevNode;
+}
+
+#else
+
+static
+off_t procDumpSysNodes(IMG_CHAR *buf, size_t size, off_t off)
+{
+ SYS_DATA *psSysData;
+ PVRSRV_DEVICE_NODE *psDevNode;
+ off_t len;
+
+
+ if (size < 80)
+ {
+ return 0;
+ }
+
+ if (off == 0)
+ {
+ return printAppend(buf, size, 0,
+ "Registered nodes\n"
+ "Addr Type Class Index Ref pvDev Size Res\n");
+ }
+
+ SysAcquireData(&psSysData);
+
+
+ psDevNode = (PVRSRV_DEVICE_NODE*)
+ List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+ DecOffPsDev_AnyVaCb,
+ &off);
+
+ if (!psDevNode)
+ {
+ return END_OF_FILE;
+ }
+
+ len = printAppend(buf, size, 0,
+ "%p %-8s %-8s %4d %2lu %p %3lu %p\n",
+ psDevNode,
+ deviceTypeToString(psDevNode->sDevId.eDeviceType),
+ deviceClassToString(psDevNode->sDevId.eDeviceClass),
+ psDevNode->sDevId.eDeviceClass,
+ psDevNode->ui32RefCount,
+ psDevNode->pvDevice,
+ psDevNode->ui32pvDeviceSize,
+ psDevNode->hResManContext);
+ return (len);
+}
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef __SERVICES_PROC_H__
+#define __SERVICES_PROC_H__
+
+#include <asm/system.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+#define END_OF_FILE (off_t) -1
+
+typedef off_t (pvr_read_proc_t)(IMG_CHAR *, size_t, off_t);
+
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+#define PVR_PROC_SEQ_START_TOKEN (void*)1
+typedef void* (pvr_next_proc_seq_t)(struct seq_file *,void*,loff_t);
+typedef void* (pvr_off2element_proc_seq_t)(struct seq_file *, loff_t);
+typedef void (pvr_show_proc_seq_t)(struct seq_file *,void*);
+typedef void (pvr_startstop_proc_seq_t)(struct seq_file *, IMG_BOOL start);
+
+typedef struct _PVR_PROC_SEQ_HANDLERS_ {
+ pvr_next_proc_seq_t *next;
+ pvr_show_proc_seq_t *show;
+ pvr_off2element_proc_seq_t *off2element;
+ pvr_startstop_proc_seq_t *startstop;
+ IMG_VOID *data;
+} PVR_PROC_SEQ_HANDLERS;
+
+
+void* ProcSeq1ElementOff2Element(struct seq_file *sfile, loff_t off);
+
+void* ProcSeq1ElementHeaderOff2Element(struct seq_file *sfile, loff_t off);
+
+
+#endif
+
+off_t printAppend(IMG_CHAR * buffer, size_t size, off_t off, const IMG_CHAR * format, ...)
+ __attribute__((format(printf, 4, 5)));
+
+IMG_INT CreateProcEntries(IMG_VOID);
+
+IMG_INT CreateProcReadEntry (const IMG_CHAR * name, pvr_read_proc_t handler);
+
+IMG_INT CreateProcEntry(const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data);
+
+IMG_INT CreatePerProcessProcEntry(const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data);
+
+IMG_VOID RemoveProcEntry(const IMG_CHAR * name);
+
+IMG_VOID RemovePerProcessProcEntry(const IMG_CHAR * name);
+
+IMG_VOID RemoveProcEntries(IMG_VOID);
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+struct proc_dir_entry* CreateProcReadEntrySeq (
+ const IMG_CHAR* name,
+ IMG_VOID* data,
+ pvr_next_proc_seq_t next_handler,
+ pvr_show_proc_seq_t show_handler,
+ pvr_off2element_proc_seq_t off2element_handler,
+ pvr_startstop_proc_seq_t startstop_handler
+ );
+
+struct proc_dir_entry* CreateProcEntrySeq (
+ const IMG_CHAR* name,
+ IMG_VOID* data,
+ pvr_next_proc_seq_t next_handler,
+ pvr_show_proc_seq_t show_handler,
+ pvr_off2element_proc_seq_t off2element_handler,
+ pvr_startstop_proc_seq_t startstop_handler,
+ write_proc_t whandler
+ );
+
+struct proc_dir_entry* CreatePerProcessProcEntrySeq (
+ const IMG_CHAR* name,
+ IMG_VOID* data,
+ pvr_next_proc_seq_t next_handler,
+ pvr_show_proc_seq_t show_handler,
+ pvr_off2element_proc_seq_t off2element_handler,
+ pvr_startstop_proc_seq_t startstop_handler,
+ write_proc_t whandler
+ );
+
+
+IMG_VOID RemoveProcEntrySeq(struct proc_dir_entry* proc_entry);
+IMG_VOID RemovePerProcessProcEntrySeq(struct proc_dir_entry* proc_entry);
+
+#endif
+
+#endif
--- /dev/null
+/**********************************************************************
+ *
+ * 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 "img_defs.h"
+#include "services.h"
+#include "pvr_bridge.h"
+#include "perproc.h"
+#include "syscommon.h"
+#include "pvr_debug.h"
+#include "proc.h"
+#include "private_data.h"
+#include "linkage.h"
+#include "pvr_bridge_km.h"
+
+#include <linux/mutex.h>
+
+#if defined(SUPPORT_DRI_DRM)
+#include <drm/drmP.h>
+#include "pvr_drm.h"
+#if defined(PVR_SECURE_DRM_AUTH_EXPORT)
+#include "env_perproc.h"
+#endif
+#endif
+
+#if defined(SUPPORT_VGX)
+#include "vgx_bridge.h"
+#endif
+
+#if defined(SUPPORT_SGX)
+#include "sgx_bridge.h"
+#endif
+
+#include "bridged_pvr_bridge.h"
+
+#ifdef MODULE_TEST
+#include "pvr_test_bridge.h"
+#include "kern_test.h"
+#endif
+
+
+#if defined(SUPPORT_DRI_DRM)
+#define PRIVATE_DATA(pFile) ((pFile)->driver_priv)
+#else
+#define PRIVATE_DATA(pFile) ((pFile)->private_data)
+#endif
+
+#if defined(DEBUG_BRIDGE_KM)
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+static struct proc_dir_entry *g_ProcBridgeStats =0;
+static void* ProcSeqNextBridgeStats(struct seq_file *sfile,void* el,loff_t off);
+static void ProcSeqShowBridgeStats(struct seq_file *sfile,void* el);
+static void* ProcSeqOff2ElementBridgeStats(struct seq_file * sfile, loff_t off);
+static void ProcSeqStartstopBridgeStats(struct seq_file *sfile,IMG_BOOL start);
+
+#else
+static off_t printLinuxBridgeStats(IMG_CHAR * buffer, size_t size, off_t off);
+#endif
+
+#endif
+
+extern struct mutex gPVRSRVLock;
+
+#if defined(SUPPORT_MEMINFO_IDS)
+static IMG_UINT64 ui64Stamp;
+#endif
+
+PVRSRV_ERROR
+LinuxBridgeInit(IMG_VOID)
+{
+#if defined(DEBUG_BRIDGE_KM)
+ {
+ IMG_INT iStatus;
+#ifdef PVR_PROC_USE_SEQ_FILE
+ g_ProcBridgeStats = CreateProcReadEntrySeq(
+ "bridge_stats",
+ NULL,
+ ProcSeqNextBridgeStats,
+ ProcSeqShowBridgeStats,
+ ProcSeqOff2ElementBridgeStats,
+ ProcSeqStartstopBridgeStats
+ );
+ iStatus = !g_ProcBridgeStats ? -1 : 0;
+#else
+ iStatus = CreateProcReadEntry("bridge_stats", printLinuxBridgeStats);
+#endif
+
+ if(iStatus!=0)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ }
+#endif
+ return CommonBridgeInit();
+}
+
+IMG_VOID
+LinuxBridgeDeInit(IMG_VOID)
+{
+#if defined(DEBUG_BRIDGE_KM)
+#ifdef PVR_PROC_USE_SEQ_FILE
+ RemoveProcEntrySeq(g_ProcBridgeStats);
+#else
+ RemoveProcEntry("bridge_stats");
+#endif
+#endif
+}
+
+#if defined(DEBUG_BRIDGE_KM)
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+
+static void ProcSeqStartstopBridgeStats(struct seq_file *sfile,IMG_BOOL start)
+{
+ if(start)
+ {
+ mutex_lock(&gPVRSRVLock);
+ }
+ else
+ {
+ mutex_unlock(&gPVRSRVLock);
+ }
+}
+
+
+static void* ProcSeqOff2ElementBridgeStats(struct seq_file *sfile, loff_t off)
+{
+ if(!off)
+ {
+ return PVR_PROC_SEQ_START_TOKEN;
+ }
+
+ if(off > BRIDGE_DISPATCH_TABLE_ENTRY_COUNT)
+ {
+ return (void*)0;
+ }
+
+
+ return (void*)&g_BridgeDispatchTable[off-1];
+}
+
+static void* ProcSeqNextBridgeStats(struct seq_file *sfile,void* el,loff_t off)
+{
+ return ProcSeqOff2ElementBridgeStats(sfile,off);
+}
+
+
+static void ProcSeqShowBridgeStats(struct seq_file *sfile,void* el)
+{
+ PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY *psEntry = ( PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY*)el;
+
+ if(el == PVR_PROC_SEQ_START_TOKEN)
+ {
+ seq_printf(sfile,
+ "Total ioctl call count = %lu\n"
+ "Total number of bytes copied via copy_from_user = %lu\n"
+ "Total number of bytes copied via copy_to_user = %lu\n"
+ "Total number of bytes copied via copy_*_user = %lu\n\n"
+ "%-45s | %-40s | %10s | %20s | %10s\n",
+ g_BridgeGlobalStats.ui32IOCTLCount,
+ g_BridgeGlobalStats.ui32TotalCopyFromUserBytes,
+ g_BridgeGlobalStats.ui32TotalCopyToUserBytes,
+ g_BridgeGlobalStats.ui32TotalCopyFromUserBytes+g_BridgeGlobalStats.ui32TotalCopyToUserBytes,
+ "Bridge Name",
+ "Wrapper Function",
+ "Call Count",
+ "copy_from_user Bytes",
+ "copy_to_user Bytes"
+ );
+ return;
+ }
+
+ seq_printf(sfile,
+ "%-45s %-40s %-10lu %-20lu %-10lu\n",
+ psEntry->pszIOCName,
+ psEntry->pszFunctionName,
+ psEntry->ui32CallCount,
+ psEntry->ui32CopyFromUserTotalBytes,
+ psEntry->ui32CopyToUserTotalBytes);
+}
+
+#else
+
+static off_t
+printLinuxBridgeStats(IMG_CHAR * buffer, size_t count, off_t off)
+{
+ PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY *psEntry;
+ off_t Ret;
+
+ mutex_lock(&gPVRSRVLock);
+
+ if(!off)
+ {
+ if(count < 500)
+ {
+ Ret = 0;
+ goto unlock_and_return;
+ }
+ Ret = printAppend(buffer, count, 0,
+ "Total ioctl call count = %lu\n"
+ "Total number of bytes copied via copy_from_user = %lu\n"
+ "Total number of bytes copied via copy_to_user = %lu\n"
+ "Total number of bytes copied via copy_*_user = %lu\n\n"
+ "%-45s | %-40s | %10s | %20s | %10s\n",
+ g_BridgeGlobalStats.ui32IOCTLCount,
+ g_BridgeGlobalStats.ui32TotalCopyFromUserBytes,
+ g_BridgeGlobalStats.ui32TotalCopyToUserBytes,
+ g_BridgeGlobalStats.ui32TotalCopyFromUserBytes+g_BridgeGlobalStats.ui32TotalCopyToUserBytes,
+ "Bridge Name",
+ "Wrapper Function",
+ "Call Count",
+ "copy_from_user Bytes",
+ "copy_to_user Bytes"
+ );
+ goto unlock_and_return;
+ }
+
+ if(off > BRIDGE_DISPATCH_TABLE_ENTRY_COUNT)
+ {
+ Ret = END_OF_FILE;
+ goto unlock_and_return;
+ }
+
+ if(count < 300)
+ {
+ Ret = 0;
+ goto unlock_and_return;
+ }
+
+ psEntry = &g_BridgeDispatchTable[off-1];
+ Ret = printAppend(buffer, count, 0,
+ "%-45s %-40s %-10lu %-20lu %-10lu\n",
+ psEntry->pszIOCName,
+ psEntry->pszFunctionName,
+ psEntry->ui32CallCount,
+ psEntry->ui32CopyFromUserTotalBytes,
+ psEntry->ui32CopyToUserTotalBytes);
+
+unlock_and_return:
+ mutex_unlock(&gPVRSRVLock);
+ return Ret;
+}
+#endif
+#endif
+
+
+
+#if defined(SUPPORT_DRI_DRM)
+IMG_INT
+PVRSRV_BridgeDispatchKM(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile)
+#else
+IMG_INT32
+PVRSRV_BridgeDispatchKM(struct file *pFile, IMG_UINT unref__ ioctlCmd, IMG_UINT32 arg)
+#endif
+{
+ IMG_UINT32 cmd;
+#if !defined(SUPPORT_DRI_DRM)
+ PVRSRV_BRIDGE_PACKAGE *psBridgePackageUM = (PVRSRV_BRIDGE_PACKAGE *)arg;
+ PVRSRV_BRIDGE_PACKAGE sBridgePackageKM;
+#endif
+ PVRSRV_BRIDGE_PACKAGE *psBridgePackageKM;
+ IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+ PVRSRV_PER_PROCESS_DATA *psPerProc;
+ IMG_INT err = -EFAULT;
+
+ mutex_lock(&gPVRSRVLock);
+
+#if defined(SUPPORT_DRI_DRM)
+ PVR_UNREFERENCED_PARAMETER(dev);
+
+ psBridgePackageKM = (PVRSRV_BRIDGE_PACKAGE *)arg;
+ PVR_ASSERT(psBridgePackageKM != IMG_NULL);
+#else
+ PVR_UNREFERENCED_PARAMETER(ioctlCmd);
+
+ psBridgePackageKM = &sBridgePackageKM;
+
+ if(!OSAccessOK(PVR_VERIFY_WRITE,
+ psBridgePackageUM,
+ sizeof(PVRSRV_BRIDGE_PACKAGE)))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Received invalid pointer to function arguments",
+ __FUNCTION__));
+
+ goto unlock_and_return;
+ }
+
+
+ if(OSCopyFromUser(IMG_NULL,
+ psBridgePackageKM,
+ psBridgePackageUM,
+ sizeof(PVRSRV_BRIDGE_PACKAGE))
+ != PVRSRV_OK)
+ {
+ goto unlock_and_return;
+ }
+#endif
+
+ cmd = psBridgePackageKM->ui32BridgeID;
+
+#if defined(MODULE_TEST)
+ switch (cmd)
+ {
+ case PVRSRV_BRIDGE_SERVICES_TEST_MEM1:
+ {
+ PVRSRV_ERROR eError = MemTest1();
+ if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+ {
+ PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+ pReturn->eError = eError;
+ }
+ }
+ err = 0;
+ goto unlock_and_return;
+ case PVRSRV_BRIDGE_SERVICES_TEST_MEM2:
+ {
+ PVRSRV_ERROR eError = MemTest2();
+ if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+ {
+ PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+ pReturn->eError = eError;
+ }
+ }
+ err = 0;
+ goto unlock_and_return;
+
+ case PVRSRV_BRIDGE_SERVICES_TEST_RESOURCE:
+ {
+ PVRSRV_ERROR eError = ResourceTest();
+ if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+ {
+ PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+ pReturn->eError = eError;
+ }
+ }
+ err = 0;
+ goto unlock_and_return;
+
+ case PVRSRV_BRIDGE_SERVICES_TEST_EVENTOBJECT:
+ {
+ PVRSRV_ERROR eError = EventObjectTest();
+ if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+ {
+ PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+ pReturn->eError = eError;
+ }
+ }
+ err = 0;
+ goto unlock_and_return;
+
+ case PVRSRV_BRIDGE_SERVICES_TEST_MEMMAPPING:
+ {
+ PVRSRV_ERROR eError = MemMappingTest();
+ if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+ {
+ PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+ pReturn->eError = eError;
+ }
+ }
+ err = 0;
+ goto unlock_and_return;
+
+ case PVRSRV_BRIDGE_SERVICES_TEST_PROCESSID:
+ {
+ PVRSRV_ERROR eError = ProcessIDTest();
+ if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+ {
+ PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+ pReturn->eError = eError;
+ }
+ }
+ err = 0;
+ goto unlock_and_return;
+
+ case PVRSRV_BRIDGE_SERVICES_TEST_CLOCKUSWAITUS:
+ {
+ PVRSRV_ERROR eError = ClockusWaitusTest();
+ if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+ {
+ PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+ pReturn->eError = eError;
+ }
+ }
+ err = 0;
+ goto unlock_and_return;
+
+ case PVRSRV_BRIDGE_SERVICES_TEST_TIMER:
+ {
+ PVRSRV_ERROR eError = TimerTest();
+ if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+ {
+ PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+ pReturn->eError = eError;
+ }
+ }
+ err = 0;
+ goto unlock_and_return;
+
+ case PVRSRV_BRIDGE_SERVICES_TEST_PRIVSRV:
+ {
+ PVRSRV_ERROR eError = PrivSrvTest();
+ if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+ {
+ PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+ pReturn->eError = eError;
+ }
+ }
+ err = 0;
+ goto unlock_and_return;
+ case PVRSRV_BRIDGE_SERVICES_TEST_COPYDATA:
+ {
+ IMG_UINT32 ui32PID;
+ PVRSRV_PER_PROCESS_DATA *psPerProc;
+ PVRSRV_ERROR eError;
+
+ ui32PID = OSGetCurrentProcessIDKM();
+
+ PVRSRVTrace("PVRSRV_BRIDGE_SERVICES_TEST_COPYDATA %d", ui32PID);
+
+ psPerProc = PVRSRVPerProcessData(ui32PID);
+
+ eError = CopyDataTest(psBridgePackageKM->pvParamIn, psBridgePackageKM->pvParamOut, psPerProc);
+
+ *(PVRSRV_ERROR*)psBridgePackageKM->pvParamOut = eError;
+ err = 0;
+ goto unlock_and_return;
+ }
+
+
+ case PVRSRV_BRIDGE_SERVICES_TEST_POWERMGMT:
+ {
+ PVRSRV_ERROR eError = PowerMgmtTest();
+ if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+ {
+ PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+ pReturn->eError = eError;
+ }
+ }
+ err = 0;
+ goto unlock_and_return;
+
+ }
+#endif
+
+ if(cmd != PVRSRV_BRIDGE_CONNECT_SERVICES)
+ {
+ PVRSRV_ERROR eError;
+
+ eError = PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
+ (IMG_PVOID *)&psPerProc,
+ psBridgePackageKM->hKernelServices,
+ PVRSRV_HANDLE_TYPE_PERPROC_DATA);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Invalid kernel services handle (%d)",
+ __FUNCTION__, eError));
+ goto unlock_and_return;
+ }
+
+ if(psPerProc->ui32PID != ui32PID)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Process %d tried to access data "
+ "belonging to process %d", __FUNCTION__, ui32PID,
+ psPerProc->ui32PID));
+ goto unlock_and_return;
+ }
+ }
+ else
+ {
+
+ psPerProc = PVRSRVPerProcessData(ui32PID);
+ if(psPerProc == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRV_BridgeDispatchKM: "
+ "Couldn't create per-process data area"));
+ goto unlock_and_return;
+ }
+ }
+
+ psBridgePackageKM->ui32BridgeID = PVRSRV_GET_BRIDGE_ID(psBridgePackageKM->ui32BridgeID);
+
+#if defined(PVR_SECURE_FD_EXPORT)
+ switch(cmd)
+ {
+ case PVRSRV_BRIDGE_EXPORT_DEVICEMEM:
+ {
+ PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
+
+ if(psPrivateData->hKernelMemInfo)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Can only export one MemInfo "
+ "per file descriptor", __FUNCTION__));
+ err = -EINVAL;
+ goto unlock_and_return;
+ }
+ break;
+ }
+
+ case PVRSRV_BRIDGE_MAP_DEV_MEMORY:
+ {
+ PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY *psMapDevMemIN =
+ (PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY *)psBridgePackageKM->pvParamIn;
+ PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
+
+ if(!psPrivateData->hKernelMemInfo)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: File descriptor has no "
+ "associated MemInfo handle", __FUNCTION__));
+ err = -EINVAL;
+ goto unlock_and_return;
+ }
+
+ psMapDevMemIN->hKernelMemInfo = psPrivateData->hKernelMemInfo;
+ break;
+ }
+
+ default:
+ {
+ PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
+
+ if(psPrivateData->hKernelMemInfo)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Import/Export handle tried "
+ "to use privileged service", __FUNCTION__));
+ goto unlock_and_return;
+ }
+ break;
+ }
+ }
+#endif
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+ switch(cmd)
+ {
+ case PVRSRV_BRIDGE_MAP_DEV_MEMORY:
+ case PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY:
+ {
+ PVRSRV_FILE_PRIVATE_DATA *psPrivateData;
+ IMG_INT authenticated = pFile->authenticated;
+ PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc;
+
+ if (authenticated)
+ {
+ break;
+ }
+
+
+ psEnvPerProc = (PVRSRV_ENV_PER_PROCESS_DATA *)PVRSRVProcessPrivateData(psPerProc);
+ if (psEnvPerProc == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Process private data not allocated", __FUNCTION__));
+ err = -EFAULT;
+ goto unlock_and_return;
+ }
+
+ list_for_each_entry(psPrivateData, &psEnvPerProc->sDRMAuthListHead, sDRMAuthListItem)
+ {
+ struct drm_file *psDRMFile = psPrivateData->psDRMFile;
+
+ if (pFile->master == psDRMFile->master)
+ {
+ authenticated |= psDRMFile->authenticated;
+ if (authenticated)
+ {
+ break;
+ }
+ }
+ }
+
+ if (!authenticated)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Not authenticated for mapping device or device class memory", __FUNCTION__));
+ err = -EPERM;
+ goto unlock_and_return;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+#endif
+
+ err = BridgedDispatchKM(psPerProc, psBridgePackageKM);
+ if(err != PVRSRV_OK)
+ goto unlock_and_return;
+
+ switch(cmd)
+ {
+#if defined(PVR_SECURE_FD_EXPORT)
+ case PVRSRV_BRIDGE_EXPORT_DEVICEMEM:
+ {
+ PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM *psExportDeviceMemOUT =
+ (PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM *)psBridgePackageKM->pvParamOut;
+ PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
+
+ psPrivateData->hKernelMemInfo = psExportDeviceMemOUT->hMemInfo;
+#if defined(SUPPORT_MEMINFO_IDS)
+ psExportDeviceMemOUT->ui64Stamp = psPrivateData->ui64Stamp = ++ui64Stamp;
+#endif
+ break;
+ }
+#endif
+
+#if defined(SUPPORT_MEMINFO_IDS)
+ case PVRSRV_BRIDGE_MAP_DEV_MEMORY:
+ {
+ PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY *psMapDeviceMemoryOUT =
+ (PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY *)psBridgePackageKM->pvParamOut;
+ PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
+ psMapDeviceMemoryOUT->sDstClientMemInfo.ui64Stamp = psPrivateData->ui64Stamp;
+ break;
+ }
+
+ case PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY:
+ {
+ PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY *psDeviceClassMemoryOUT =
+ (PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY *)psBridgePackageKM->pvParamOut;
+ psDeviceClassMemoryOUT->sClientMemInfo.ui64Stamp = ++ui64Stamp;
+ break;
+ }
+#endif
+
+ default:
+ break;
+ }
+
+unlock_and_return:
+ mutex_unlock(&gPVRSRVLock);
+ return err;
+}
--- /dev/null
+/**********************************************************************
+ *
+ * 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 <asm/io.h>
+#include <asm/uaccess.h>
+#include <linux/kernel.h>
+#include <linux/hardirq.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/tty.h>
+#include <linux/mutex.h>
+#include <stdarg.h>
+#include "img_types.h"
+#include "servicesext.h"
+#include "pvr_debug.h"
+#include "proc.h"
+#include "linkage.h"
+
+#if defined(PVRSRV_NEED_PVR_DPF)
+
+#define PVR_MAX_FILEPATH_LEN 256
+
+static IMG_UINT32 gPVRDebugLevel = DBGPRIV_WARNING;
+
+#endif
+
+#define PVR_MAX_MSG_LEN PVR_MAX_DEBUG_MESSAGE_LEN
+
+static IMG_CHAR gszBufferNonIRQ[PVR_MAX_MSG_LEN + 1];
+
+static IMG_CHAR gszBufferIRQ[PVR_MAX_MSG_LEN + 1];
+
+static struct mutex gsDebugMutexNonIRQ;
+
+static DEFINE_SPINLOCK(gsDebugLockIRQ);
+
+#define USE_SPIN_LOCK (in_interrupt() || !preemptible())
+
+static inline void GetBufferLock(unsigned long *pulLockFlags)
+{
+ /* This is broken! */
+ if (USE_SPIN_LOCK)
+ {
+ spin_lock_irqsave(&gsDebugLockIRQ, *pulLockFlags);
+ }
+ else
+ {
+ mutex_lock(&gsDebugMutexNonIRQ);
+ }
+}
+
+static inline void ReleaseBufferLock(unsigned long ulLockFlags)
+{
+ /* and this is even more broken */
+ if (USE_SPIN_LOCK)
+ {
+ spin_unlock_irqrestore(&gsDebugLockIRQ, ulLockFlags);
+ }
+ else
+ {
+ mutex_unlock(&gsDebugMutexNonIRQ);
+ }
+}
+
+static inline void SelectBuffer(IMG_CHAR **ppszBuf, IMG_UINT32 *pui32BufSiz)
+{
+ if (USE_SPIN_LOCK)
+ {
+ *ppszBuf = gszBufferIRQ;
+ *pui32BufSiz = sizeof(gszBufferIRQ);
+ }
+ else
+ {
+ *ppszBuf = gszBufferNonIRQ;
+ *pui32BufSiz = sizeof(gszBufferNonIRQ);
+ }
+}
+
+static IMG_BOOL VBAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz, const IMG_CHAR* pszFormat, va_list VArgs)
+{
+ IMG_UINT32 ui32Used;
+ IMG_UINT32 ui32Space;
+ IMG_INT32 i32Len;
+
+ ui32Used = strlen(pszBuf);
+ BUG_ON(ui32Used >= ui32BufSiz);
+ ui32Space = ui32BufSiz - ui32Used;
+
+ i32Len = vsnprintf(&pszBuf[ui32Used], ui32Space, pszFormat, VArgs);
+ pszBuf[ui32BufSiz - 1] = 0;
+
+
+ return (i32Len < 0 || i32Len >= ui32Space);
+}
+
+IMG_VOID PVRDPFInit(IMG_VOID)
+{
+ mutex_init(&gsDebugMutexNonIRQ);
+}
+
+IMG_VOID PVRSRVReleasePrintf(const IMG_CHAR *pszFormat, ...)
+{
+ va_list vaArgs;
+ unsigned long ulLockFlags = 0;
+ IMG_CHAR *pszBuf;
+ IMG_UINT32 ui32BufSiz;
+
+ SelectBuffer(&pszBuf, &ui32BufSiz);
+
+ va_start(vaArgs, pszFormat);
+
+ GetBufferLock(&ulLockFlags);
+ strncpy (pszBuf, "PVR_K: ", (ui32BufSiz -1));
+
+ if (VBAppend(pszBuf, ui32BufSiz, pszFormat, vaArgs))
+ {
+ printk(KERN_INFO "PVR_K:(Message Truncated): %s\n", pszBuf);
+ }
+ else
+ {
+ printk(KERN_INFO "%s\n", pszBuf);
+ }
+
+ ReleaseBufferLock(ulLockFlags);
+ va_end(vaArgs);
+
+}
+
+#if defined(PVRSRV_NEED_PVR_ASSERT)
+
+IMG_VOID PVRSRVDebugAssertFail(const IMG_CHAR* pszFile, IMG_UINT32 uLine)
+{
+ PVRSRVDebugPrintf(DBGPRIV_FATAL, pszFile, uLine, "Debug assertion failed!");
+ BUG();
+}
+
+#endif
+
+#if defined(PVRSRV_NEED_PVR_TRACE)
+
+IMG_VOID PVRSRVTrace(const IMG_CHAR* pszFormat, ...)
+{
+ va_list VArgs;
+ unsigned long ulLockFlags = 0;
+ IMG_CHAR *pszBuf;
+ IMG_UINT32 ui32BufSiz;
+
+ SelectBuffer(&pszBuf, &ui32BufSiz);
+
+ va_start(VArgs, pszFormat);
+
+ GetBufferLock(&ulLockFlags);
+
+ strncpy(pszBuf, "PVR: ", (ui32BufSiz -1));
+
+ if (VBAppend(pszBuf, ui32BufSiz, pszFormat, VArgs))
+ {
+ printk(KERN_INFO "PVR_K:(Message Truncated): %s\n", pszBuf);
+ }
+ else
+ {
+ printk(KERN_INFO "%s\n", pszBuf);
+ }
+
+ ReleaseBufferLock(ulLockFlags);
+
+ va_end(VArgs);
+}
+
+#endif
+
+#if defined(PVRSRV_NEED_PVR_DPF)
+
+static IMG_BOOL BAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz, const IMG_CHAR *pszFormat, ...)
+{
+ va_list VArgs;
+ IMG_BOOL bTrunc;
+
+ va_start (VArgs, pszFormat);
+
+ bTrunc = VBAppend(pszBuf, ui32BufSiz, pszFormat, VArgs);
+
+ va_end (VArgs);
+
+ return bTrunc;
+}
+
+IMG_VOID PVRSRVDebugPrintf (
+ IMG_UINT32 ui32DebugLevel,
+ const IMG_CHAR* pszFullFileName,
+ IMG_UINT32 ui32Line,
+ const IMG_CHAR* pszFormat,
+ ...
+ )
+{
+ IMG_BOOL bTrace, bDebug;
+ const IMG_CHAR *pszFileName = pszFullFileName;
+ IMG_CHAR *pszLeafName;
+
+ bTrace = gPVRDebugLevel & ui32DebugLevel & DBGPRIV_CALLTRACE;
+ bDebug = ((gPVRDebugLevel & DBGPRIV_ALLLEVELS) >= ui32DebugLevel);
+
+ if (bTrace || bDebug)
+ {
+ va_list vaArgs;
+ unsigned long ulLockFlags = 0;
+ IMG_CHAR *pszBuf;
+ IMG_UINT32 ui32BufSiz;
+
+ SelectBuffer(&pszBuf, &ui32BufSiz);
+
+ va_start(vaArgs, pszFormat);
+
+ GetBufferLock(&ulLockFlags);
+
+
+ if (bDebug)
+ {
+ switch(ui32DebugLevel)
+ {
+ case DBGPRIV_FATAL:
+ {
+ strncpy (pszBuf, "PVR_K:(Fatal): ", (ui32BufSiz -1));
+ break;
+ }
+ case DBGPRIV_ERROR:
+ {
+ strncpy (pszBuf, "PVR_K:(Error): ", (ui32BufSiz -1));
+ break;
+ }
+ case DBGPRIV_WARNING:
+ {
+ strncpy (pszBuf, "PVR_K:(Warning): ", (ui32BufSiz -1));
+ break;
+ }
+ case DBGPRIV_MESSAGE:
+ {
+ strncpy (pszBuf, "PVR_K:(Message): ", (ui32BufSiz -1));
+ break;
+ }
+ case DBGPRIV_VERBOSE:
+ {
+ strncpy (pszBuf, "PVR_K:(Verbose): ", (ui32BufSiz -1));
+ break;
+ }
+ default:
+ {
+ strncpy (pszBuf, "PVR_K:(Unknown message level)", (ui32BufSiz -1));
+ break;
+ }
+ }
+ }
+ else
+ {
+ strncpy (pszBuf, "PVR_K: ", (ui32BufSiz -1));
+ }
+
+ if (VBAppend(pszBuf, ui32BufSiz, pszFormat, vaArgs))
+ {
+ printk(KERN_INFO "PVR_K:(Message Truncated): %s\n", pszBuf);
+ }
+ else
+ {
+
+ if (!bTrace)
+ {
+#ifdef DEBUG_LOG_PATH_TRUNCATE
+
+ static IMG_CHAR szFileNameRewrite[PVR_MAX_FILEPATH_LEN];
+
+ IMG_CHAR* pszTruncIter;
+ IMG_CHAR* pszTruncBackInter;
+
+
+ pszFileName = pszFullFileName + strlen(DEBUG_LOG_PATH_TRUNCATE)+1;
+
+
+ strncpy(szFileNameRewrite, pszFileName,PVR_MAX_FILEPATH_LEN);
+
+ if(strlen(szFileNameRewrite) == PVR_MAX_FILEPATH_LEN-1) {
+ IMG_CHAR szTruncateMassage[] = "FILENAME TRUNCATED";
+ strcpy(szFileNameRewrite + (PVR_MAX_FILEPATH_LEN - 1 - strlen(szTruncateMassage)), szTruncateMassage);
+ }
+
+ pszTruncIter = szFileNameRewrite;
+ while(*pszTruncIter++ != 0)
+ {
+ IMG_CHAR* pszNextStartPoint;
+
+ if(
+ !( ( *pszTruncIter == '/' && (pszTruncIter-4 >= szFileNameRewrite) ) &&
+ ( *(pszTruncIter-1) == '.') &&
+ ( *(pszTruncIter-2) == '.') &&
+ ( *(pszTruncIter-3) == '/') )
+ ) continue;
+
+
+ pszTruncBackInter = pszTruncIter - 3;
+ while(*(--pszTruncBackInter) != '/')
+ {
+ if(pszTruncBackInter <= szFileNameRewrite) break;
+ }
+ pszNextStartPoint = pszTruncBackInter;
+
+
+ while(*pszTruncIter != 0)
+ {
+ *pszTruncBackInter++ = *pszTruncIter++;
+ }
+ *pszTruncBackInter = 0;
+
+
+ pszTruncIter = pszNextStartPoint;
+ }
+
+ pszFileName = szFileNameRewrite;
+
+ if(*pszFileName == '/') pszFileName++;
+#endif
+
+#if !defined(__sh__)
+ pszLeafName = (IMG_CHAR *)strrchr (pszFileName, '\\');
+
+ if (pszLeafName)
+ {
+ pszFileName = pszLeafName;
+ }
+#endif
+
+ if (BAppend(pszBuf, ui32BufSiz, " [%lu, %s]", ui32Line, pszFileName))
+ {
+ printk(KERN_INFO "PVR_K:(Message Truncated): %s\n", pszBuf);
+ }
+ else
+ {
+ printk(KERN_INFO "%s\n", pszBuf);
+ }
+ }
+ else
+ {
+ printk(KERN_INFO "%s\n", pszBuf);
+ }
+ }
+
+ ReleaseBufferLock(ulLockFlags);
+
+ va_end (vaArgs);
+ }
+}
+
+#endif
+
+#if defined(DEBUG)
+
+IMG_VOID PVRDebugSetLevel(IMG_UINT32 uDebugLevel)
+{
+ printk(KERN_INFO "PVR: Setting Debug Level = 0x%x\n",(IMG_UINT)uDebugLevel);
+
+ gPVRDebugLevel = uDebugLevel;
+}
+
+IMG_INT PVRDebugProcSetLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT32 count, IMG_VOID *data)
+{
+#define _PROC_SET_BUFFER_SZ 2
+ IMG_CHAR data_buffer[_PROC_SET_BUFFER_SZ];
+
+ if (count != _PROC_SET_BUFFER_SZ)
+ {
+ return -EINVAL;
+ }
+ else
+ {
+ if (copy_from_user(data_buffer, buffer, count))
+ return -EINVAL;
+ if (data_buffer[count - 1] != '\n')
+ return -EINVAL;
+ PVRDebugSetLevel(data_buffer[0] - '0');
+ }
+ return (count);
+}
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+void ProcSeqShowDebugLevel(struct seq_file *sfile,void* el)
+{
+ seq_printf(sfile, "%lu\n", gPVRDebugLevel);
+}
+
+#else
+IMG_INT PVRDebugProcGetLevel(IMG_CHAR *page, IMG_CHAR **start, off_t off, IMG_INT count, IMG_INT *eof, IMG_VOID *data)
+{
+ if (off == 0) {
+ *start = (IMG_CHAR *)1;
+ return printAppend(page, count, 0, "%lu\n", gPVRDebugLevel);
+ }
+ *eof = 1;
+ return 0;
+}
+#endif
+
+#endif
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#if defined(SUPPORT_DRI_DRM)
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <linux/mutex.h>
+#include <asm/ioctl.h>
+#include <drm/drmP.h>
+#include <drm/drm.h>
+
+#include "img_defs.h"
+#include "services.h"
+#include "kerneldisplay.h"
+#include "kernelbuffer.h"
+#include "syscommon.h"
+#include "pvrmmap.h"
+#include "mm.h"
+#include "mmap.h"
+#include "pvr_debug.h"
+#include "srvkm.h"
+#include "perproc.h"
+#include "handle.h"
+#include "pvr_bridge_km.h"
+#include "pvr_bridge.h"
+#include "proc.h"
+#include "pvrmodule.h"
+#include "pvrversion.h"
+#include "lock.h"
+#include "linkage.h"
+#include "pvr_drm_shared.h"
+#include "pvr_drm.h"
+
+#define MAKENAME_HELPER(x, y) x ## y
+#define MAKENAME(x, y) MAKENAME_HELPER(x, y)
+
+#define PVR_DRM_NAME "pvrsrvkm"
+#define PVR_DRM_DESC "Imagination Technologies PVR DRM"
+
+#define PVR_PCI_IDS \
+ {SYS_SGX_DEV_VENDOR_ID, SYS_SGX_DEV_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+ {0, 0, 0}
+
+struct pci_dev *gpsPVRLDMDev;
+struct drm_device *gpsPVRDRMDev;
+
+#define PVR_DRM_FILE struct drm_file *
+
+#if !defined(SUPPORT_DRI_DRM_EXT)
+static struct pci_device_id asPciIdList[] = {
+ PVR_PCI_IDS
+};
+#endif
+
+IMG_INT PVRSRVDrmLoad(struct drm_device *dev, unsigned long flags)
+{
+ IMG_INT iRes;
+
+ PVR_TRACE(("PVRSRVDrmLoad"));
+
+ gpsPVRDRMDev = dev;
+ gpsPVRLDMDev = dev->pdev;
+
+#if defined(PDUMP)
+ iRes = dbgdrv_init();
+ if (iRes != 0)
+ {
+ return iRes;
+ }
+#endif
+
+ iRes = PVRCore_Init();
+ if (iRes != 0)
+ {
+ goto exit_dbgdrv_cleanup;
+ }
+
+#if defined(DISPLAY_CONTROLLER)
+ iRes = PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Init)(dev);
+ if (iRes != 0)
+ {
+ goto exit_pvrcore_cleanup;
+ }
+#endif
+ return 0;
+
+#if defined(DISPLAY_CONTROLLER)
+exit_pvrcore_cleanup:
+ PVRCore_Cleanup();
+#endif
+exit_dbgdrv_cleanup:
+#if defined(PDUMP)
+ dbgdrv_cleanup();
+#endif
+ return iRes;
+}
+
+IMG_INT PVRSRVDrmUnload(struct drm_device *dev)
+{
+ PVR_TRACE(("PVRSRVDrmUnload"));
+
+#if defined(DISPLAY_CONTROLLER)
+ PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Cleanup)(dev);
+#endif
+
+ PVRCore_Cleanup();
+
+#if defined(PDUMP)
+ dbgdrv_cleanup();
+#endif
+
+ return 0;
+}
+
+IMG_INT PVRSRVDrmOpen(struct drm_device *dev, struct drm_file *file)
+{
+ return PVRSRVOpen(dev, file);
+}
+
+IMG_VOID PVRSRVDrmPostClose(struct drm_device *dev, struct drm_file *file)
+{
+ PVRSRVRelease(dev, file);
+}
+
+DRI_DRM_STATIC IMG_INT
+PVRDRMIsMaster(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile)
+{
+ return 0;
+}
+
+#if defined(SUPPORT_DRI_DRM_EXT)
+IMG_INT
+PVRDRM_Dummy_ioctl(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile)
+{
+ return 0;
+}
+#endif
+
+static IMG_INT
+PVRDRMPCIBusIDField(struct drm_device *dev, IMG_UINT32 *pui32Field, IMG_UINT32 ui32FieldType)
+{
+ struct pci_dev *psPCIDev = (struct pci_dev *)dev->pdev;
+
+ switch (ui32FieldType)
+ {
+ case PVR_DRM_PCI_DOMAIN:
+ *pui32Field = pci_domain_nr(psPCIDev->bus);
+ break;
+
+ case PVR_DRM_PCI_BUS:
+ *pui32Field = psPCIDev->bus->number;
+ break;
+
+ case PVR_DRM_PCI_DEV:
+ *pui32Field = PCI_SLOT(psPCIDev->devfn);
+ break;
+
+ case PVR_DRM_PCI_FUNC:
+ *pui32Field = PCI_FUNC(psPCIDev->devfn);
+ break;
+
+ default:
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+DRI_DRM_STATIC IMG_INT
+PVRDRMUnprivCmd(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile)
+{
+ IMG_UINT32 *pui32Args = (IMG_UINT32 *)arg;
+ IMG_UINT32 ui32Cmd = pui32Args[0];
+ IMG_UINT32 ui32Arg1 = pui32Args[1];
+ IMG_UINT32 *pui32OutArg = (IMG_UINT32 *)arg;
+ IMG_INT ret = 0;
+
+ mutex_lock(&gPVRSRVLock);
+
+ switch (ui32Cmd)
+ {
+ case PVR_DRM_UNPRIV_INIT_SUCCESFUL:
+ *pui32OutArg = PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL) ? 1 : 0;
+ break;
+
+ case PVR_DRM_UNPRIV_BUSID_TYPE:
+ *pui32OutArg = PVR_DRM_BUS_TYPE_PCI;
+ break;
+
+ case PVR_DRM_UNPRIV_BUSID_FIELD:
+ ret = PVRDRMPCIBusIDField(dev, pui32OutArg, ui32Arg1);
+
+ default:
+ ret = -EFAULT;
+ }
+
+ mutex_unlock(&gPVRSRVLock);
+
+ return ret;
+}
+
+#if 0
+struct drm_ioctl_desc sPVRDrmIoctls[] = {
+ DRM_IOCTL_DEF(PVR_DRM_SRVKM_IOCTL, PVRSRV_BridgeDispatchKM, 0),
+ DRM_IOCTL_DEF(PVR_DRM_IS_MASTER_IOCTL, PVRDRMIsMaster, DRM_MASTER),
+ DRM_IOCTL_DEF(PVR_DRM_UNPRIV_IOCTL, PVRDRMUnprivCmd, 0),
+#if defined(PDUMP)
+ DRM_IOCTL_DEF(PVR_DRM_DBGDRV_IOCTL, dbgdrv_ioctl, 0),
+#endif
+};
+
+static IMG_INT pvr_max_ioctl = DRM_ARRAY_SIZE(sPVRDrmIoctls);
+
+static struct drm_driver sPVRDrmDriver =
+{
+ .driver_features = 0,
+ .dev_priv_size = sizeof(sPVRDrmBuffer),
+ .load = PVRSRVDrmLoad,
+ .unload = PVRSRVDrmUnload,
+ .open = PVRSRVDrmOpen,
+ .postclose = PVRSRVDrmPostClose,
+ .suspend = PVRSRVDriverSuspend,
+ .resume = PVRSRVDriverResume,
+ .get_map_ofs = drm_core_get_map_ofs,
+ .get_reg_ofs = drm_core_get_reg_ofs,
+ .ioctls = sPVRDrmIoctls,
+ .fops =
+ {
+ .owner = THIS_MODULE,
+ .open = drm_open,
+ .release = drm_release,
+ .ioctl = drm_ioctl,
+ .mmap = PVRMMap,
+ .poll = drm_poll,
+ .fasync = drm_fasync,
+ },
+ .pci_driver =
+ {
+ .name = PVR_DRM_NAME,
+ .id_table = asPciIdList,
+ },
+
+ .name = PVR_DRM_NAME,
+ .desc = PVR_DRM_DESC,
+ .date = PVR_BUILD_DATE,
+ .major = PVRVERSION_MAJ,
+ .minor = PVRVERSION_MIN,
+ .patchlevel = PVRVERSION_BUILD,
+};
+
+static IMG_INT __init PVRSRVDrmInit(IMG_VOID)
+{
+ IMG_INT iRes;
+ sPVRDrmDriver.num_ioctls = pvr_max_ioctl;
+
+
+ PVRDPFInit();
+
+ iRes = drm_init(&sPVRDrmDriver);
+
+ return iRes;
+}
+
+static IMG_VOID __exit PVRSRVDrmExit(IMG_VOID)
+{
+ drm_exit(&sPVRDrmDriver);
+}
+
+module_init(PVRSRVDrmInit);
+module_exit(PVRSRVDrmExit);
+#endif
+#endif
+
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#if !defined(__PVR_DRM_H__)
+#define __PVR_DRM_H__
+
+#include "pvr_drm_shared.h"
+
+#if defined(SUPPORT_DRI_DRM)
+#define PVR_DRM_MAKENAME_HELPER(x, y) x ## y
+#define PVR_DRM_MAKENAME(x, y) PVR_DRM_MAKENAME_HELPER(x, y)
+
+IMG_INT PVRCore_Init(IMG_VOID);
+IMG_VOID PVRCore_Cleanup(IMG_VOID);
+IMG_INT PVRSRVOpen(struct drm_device *dev, struct drm_file *pFile);
+IMG_INT PVRSRVRelease(struct drm_device *dev, struct drm_file *pFile);
+IMG_INT PVRSRVDriverSuspend(struct drm_device *pDevice, pm_message_t state);
+IMG_INT PVRSRVDriverResume(struct drm_device *pDevice);
+
+IMG_INT PVRSRV_BridgeDispatchKM(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+
+#if defined(SUPPORT_DRI_DRM_EXT)
+#define DRI_DRM_STATIC
+IMG_INT PVRSRVDrmLoad(struct drm_device *dev, unsigned long flags);
+IMG_INT PVRSRVDrmUnload(struct drm_device *dev);
+IMG_INT PVRSRVDrmOpen(struct drm_device *dev, struct drm_file *file);
+IMG_VOID PVRSRVDrmPostClose(struct drm_device *dev, struct drm_file *file);
+IMG_INT PVRDRMIsMaster(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+IMG_INT PVRDRMUnprivCmd(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+IMG_INT PVRDRM_Dummy_ioctl(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+#else
+#define DRI_DRM_STATIC static
+#endif
+
+#if defined(DISPLAY_CONTROLLER)
+extern int PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Init)(struct drm_device *);
+extern void PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Cleanup)(struct drm_device *);
+#endif
+
+#if defined(PDUMP)
+int dbgdrv_init(void);
+void dbgdrv_cleanup(void);
+IMG_INT dbgdrv_ioctl(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+#endif
+
+#if !defined(SUPPORT_DRI_DRM_EXT)
+#define PVR_DRM_SRVKM_IOCTL _IO(0, PVR_DRM_SRVKM_CMD)
+#define PVR_DRM_IS_MASTER_IOCTL _IO(0, PVR_DRM_IS_MASTER_CMD)
+#define PVR_DRM_UNPRIV_IOCTL _IO(0, PVR_DRM_UNPRIV_CMD)
+#define PVR_DRM_DBGDRV_IOCTL _IO(0, PVR_DRM_DBGDRV_CMD)
+#endif
+
+#endif
+
+#endif
+
+
--- /dev/null
+bin_pc_i686*
+tmp_pc_i686*
+host_pc_i686*
+*.o
+*.o.cmd
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef _ENV_DATA_
+#define _ENV_DATA_
+
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+
+#if defined(PVR_LINUX_MISR_USING_WORKQUEUE) || defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE)
+#include <linux/workqueue.h>
+#endif
+
+#define PVRSRV_MAX_BRIDGE_IN_SIZE 0x1000
+#define PVRSRV_MAX_BRIDGE_OUT_SIZE 0x1000
+
+typedef struct _PVR_PCI_DEV_TAG
+{
+ struct pci_dev *psPCIDev;
+ HOST_PCI_INIT_FLAGS ePCIFlags;
+ IMG_BOOL abPCIResourceInUse[DEVICE_COUNT_RESOURCE];
+} PVR_PCI_DEV;
+
+typedef struct _ENV_DATA_TAG
+{
+ IMG_VOID *pvBridgeData;
+ struct pm_dev *psPowerDevice;
+ IMG_BOOL bLISRInstalled;
+ IMG_BOOL bMISRInstalled;
+ IMG_UINT32 ui32IRQ;
+ IMG_VOID *pvISRCookie;
+#if defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE)
+ struct workqueue_struct *psWorkQueue;
+#endif
+#if defined(PVR_LINUX_MISR_USING_WORKQUEUE) || defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE)
+ struct work_struct sMISRWork;
+ IMG_VOID *pvMISRData;
+#else
+ struct tasklet_struct sMISRTasklet;
+#endif
+} ENV_DATA;
+
+#endif
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef __ENV_PERPROC_H__
+#define __ENV_PERPROC_H__
+
+#include <linux/list.h>
+#include <linux/proc_fs.h>
+
+#include "services.h"
+#include "handle.h"
+
+typedef struct _PVRSRV_ENV_PER_PROCESS_DATA_
+{
+ IMG_HANDLE hBlockAlloc;
+ struct proc_dir_entry *psProcDir;
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+ struct list_head sDRMAuthListHead;
+#endif
+} PVRSRV_ENV_PER_PROCESS_DATA;
+
+IMG_VOID RemovePerProcessProcDir(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc);
+
+PVRSRV_ERROR LinuxMMapPerProcessConnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc);
+
+IMG_VOID LinuxMMapPerProcessDisconnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc);
+
+PVRSRV_ERROR LinuxMMapPerProcessHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase);
+
+IMG_HANDLE LinuxTerminatingProcessPrivateData(IMG_VOID);
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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/version.h>
+#include <asm/io.h>
+#include <asm/page.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22))
+#include <asm/system.h>
+#endif
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <asm/hardirq.h>
+#include <linux/spinlock.h>
+#include <linux/timer.h>
+#include <linux/capability.h>
+#include <linux/sched.h>
+#include <asm/uaccess.h>
+
+#include "img_types.h"
+#include "services_headers.h"
+#include "mm.h"
+#include "pvrmmap.h"
+#include "mmap.h"
+#include "env_data.h"
+#include "proc.h"
+#include "mutex.h"
+#include "lock.h"
+#include "event.h"
+
+typedef struct PVRSRV_LINUX_EVENT_OBJECT_LIST_TAG
+{
+ rwlock_t sLock;
+ struct list_head sList;
+
+} PVRSRV_LINUX_EVENT_OBJECT_LIST;
+
+
+typedef struct PVRSRV_LINUX_EVENT_OBJECT_TAG
+{
+ atomic_t sTimeStamp;
+ IMG_UINT32 ui32TimeStampPrevious;
+#if defined(DEBUG)
+ IMG_UINT ui32Stats;
+#endif
+ wait_queue_head_t sWait;
+ struct list_head sList;
+ IMG_HANDLE hResItem;
+ PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList;
+} PVRSRV_LINUX_EVENT_OBJECT;
+
+PVRSRV_ERROR LinuxEventObjectListCreate(IMG_HANDLE *phEventObjectList)
+{
+ PVRSRV_LINUX_EVENT_OBJECT_LIST *psEventObjectList;
+
+ if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT_LIST),
+ (IMG_VOID **)&psEventObjectList, IMG_NULL,
+ "Linux Event Object List") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectCreate: failed to allocate memory for event list"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ INIT_LIST_HEAD(&psEventObjectList->sList);
+
+ rwlock_init(&psEventObjectList->sLock);
+
+ *phEventObjectList = (IMG_HANDLE *) psEventObjectList;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR LinuxEventObjectListDestroy(IMG_HANDLE hEventObjectList)
+{
+
+ PVRSRV_LINUX_EVENT_OBJECT_LIST *psEventObjectList = (PVRSRV_LINUX_EVENT_OBJECT_LIST *) hEventObjectList ;
+
+ if(psEventObjectList)
+ {
+ IMG_BOOL bListEmpty;
+
+ read_lock(&psEventObjectList->sLock);
+ bListEmpty = list_empty(&psEventObjectList->sList);
+ read_unlock(&psEventObjectList->sLock);
+
+ if (!bListEmpty)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectListDestroy: Event List is not empty"));
+ return PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT;
+ }
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT_LIST), psEventObjectList, IMG_NULL);
+
+ }
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR LinuxEventObjectDelete(IMG_HANDLE hOSEventObjectList, IMG_HANDLE hOSEventObject)
+{
+ if(hOSEventObjectList)
+ {
+ if(hOSEventObject)
+ {
+ PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject = (PVRSRV_LINUX_EVENT_OBJECT *)hOSEventObject;
+#if defined(DEBUG)
+ PVR_DPF((PVR_DBG_MESSAGE, "LinuxEventObjectListDelete: Event object waits: %u", psLinuxEventObject->ui32Stats));
+#endif
+ if(ResManFreeResByPtr(psLinuxEventObject->hResItem) != PVRSRV_OK)
+ {
+ return PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT;
+ }
+
+ return PVRSRV_OK;
+ }
+ }
+ return PVRSRV_ERROR_UNABLE_TO_DESTROY_EVENT;
+
+}
+
+static PVRSRV_ERROR LinuxEventObjectDeleteCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param)
+{
+ PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject = pvParam;
+ PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList = psLinuxEventObject->psLinuxEventObjectList;
+ unsigned long ulLockFlags;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ write_lock_irqsave(&psLinuxEventObjectList->sLock, ulLockFlags);
+ list_del(&psLinuxEventObject->sList);
+ write_unlock_irqrestore(&psLinuxEventObjectList->sLock, ulLockFlags);
+
+#if defined(DEBUG)
+ PVR_DPF((PVR_DBG_MESSAGE, "LinuxEventObjectDeleteCallback: Event object waits: %u", psLinuxEventObject->ui32Stats));
+#endif
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT), psLinuxEventObject, IMG_NULL);
+
+
+ return PVRSRV_OK;
+}
+PVRSRV_ERROR LinuxEventObjectAdd(IMG_HANDLE hOSEventObjectList, IMG_HANDLE *phOSEventObject)
+ {
+ PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject;
+ PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList = (PVRSRV_LINUX_EVENT_OBJECT_LIST*)hOSEventObjectList;
+ IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+ PVRSRV_PER_PROCESS_DATA *psPerProc;
+ unsigned long ulLockFlags;
+
+ psPerProc = PVRSRVPerProcessData(ui32PID);
+ if (psPerProc == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectAdd: Couldn't find per-process data"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+
+ if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT),
+ (IMG_VOID **)&psLinuxEventObject, IMG_NULL,
+ "Linux Event Object") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectAdd: failed to allocate memory "));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ INIT_LIST_HEAD(&psLinuxEventObject->sList);
+
+ atomic_set(&psLinuxEventObject->sTimeStamp, 0);
+ psLinuxEventObject->ui32TimeStampPrevious = 0;
+
+#if defined(DEBUG)
+ psLinuxEventObject->ui32Stats = 0;
+#endif
+ init_waitqueue_head(&psLinuxEventObject->sWait);
+
+ psLinuxEventObject->psLinuxEventObjectList = psLinuxEventObjectList;
+
+ psLinuxEventObject->hResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_EVENT_OBJECT,
+ psLinuxEventObject,
+ 0,
+ &LinuxEventObjectDeleteCallback);
+
+ write_lock_irqsave(&psLinuxEventObjectList->sLock, ulLockFlags);
+ list_add(&psLinuxEventObject->sList, &psLinuxEventObjectList->sList);
+ write_unlock_irqrestore(&psLinuxEventObjectList->sLock, ulLockFlags);
+
+ *phOSEventObject = psLinuxEventObject;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR LinuxEventObjectSignal(IMG_HANDLE hOSEventObjectList)
+{
+ PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject;
+ PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList = (PVRSRV_LINUX_EVENT_OBJECT_LIST*)hOSEventObjectList;
+ struct list_head *psListEntry, *psList;
+
+ psList = &psLinuxEventObjectList->sList;
+
+
+ read_lock(&psLinuxEventObjectList->sLock);
+ list_for_each(psListEntry, psList)
+ {
+
+ psLinuxEventObject = (PVRSRV_LINUX_EVENT_OBJECT *)list_entry(psListEntry, PVRSRV_LINUX_EVENT_OBJECT, sList);
+
+ atomic_inc(&psLinuxEventObject->sTimeStamp);
+ wake_up_interruptible(&psLinuxEventObject->sWait);
+ }
+ read_unlock(&psLinuxEventObjectList->sLock);
+
+ return PVRSRV_OK;
+
+}
+
+PVRSRV_ERROR LinuxEventObjectWait(IMG_HANDLE hOSEventObject, IMG_UINT32 ui32MSTimeout)
+{
+ IMG_UINT32 ui32TimeStamp;
+ DEFINE_WAIT(sWait);
+
+ PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject = (PVRSRV_LINUX_EVENT_OBJECT *) hOSEventObject;
+
+ IMG_UINT32 ui32TimeOutJiffies = msecs_to_jiffies(ui32MSTimeout);
+
+ do
+ {
+ prepare_to_wait(&psLinuxEventObject->sWait, &sWait, TASK_INTERRUPTIBLE);
+ ui32TimeStamp = (IMG_UINT32)atomic_read(&psLinuxEventObject->sTimeStamp);
+
+ if(psLinuxEventObject->ui32TimeStampPrevious != ui32TimeStamp)
+ {
+ break;
+ }
+
+ LinuxUnLockMutex(&gPVRSRVLock);
+
+ ui32TimeOutJiffies = (IMG_UINT32)schedule_timeout((IMG_INT32)ui32TimeOutJiffies);
+
+ LinuxLockMutex(&gPVRSRVLock);
+#if defined(DEBUG)
+ psLinuxEventObject->ui32Stats++;
+#endif
+
+
+ } while (ui32TimeOutJiffies);
+
+ finish_wait(&psLinuxEventObject->sWait, &sWait);
+
+ psLinuxEventObject->ui32TimeStampPrevious = ui32TimeStamp;
+
+ return ui32TimeOutJiffies ? PVRSRV_OK : PVRSRV_ERROR_TIMEOUT;
+
+}
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+PVRSRV_ERROR LinuxEventObjectListCreate(IMG_HANDLE *phEventObjectList);
+PVRSRV_ERROR LinuxEventObjectListDestroy(IMG_HANDLE hEventObjectList);
+PVRSRV_ERROR LinuxEventObjectAdd(IMG_HANDLE hOSEventObjectList, IMG_HANDLE *phOSEventObject);
+PVRSRV_ERROR LinuxEventObjectDelete(IMG_HANDLE hOSEventObjectList, IMG_HANDLE hOSEventObject);
+PVRSRV_ERROR LinuxEventObjectSignal(IMG_HANDLE hOSEventObjectList);
+PVRSRV_ERROR LinuxEventObjectWait(IMG_HANDLE hOSEventObject, IMG_UINT32 ui32MSTimeout);
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef __LINKAGE_H__
+#define __LINKAGE_H__
+
+#if !defined(SUPPORT_DRI_DRM)
+long PVRSRV_BridgeDispatchKM(struct file *file, unsigned int cmd, unsigned long arg);
+#endif
+
+IMG_VOID PVRDPFInit(IMG_VOID);
+PVRSRV_ERROR PVROSFuncInit(IMG_VOID);
+IMG_VOID PVROSFuncDeInit(IMG_VOID);
+
+#ifdef DEBUG
+
+IMG_INT PVRDebugProcSetLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT32 count, IMG_VOID *data);
+void ProcSeqShowDebugLevel(struct seq_file *sfile,void* el);
+
+#ifdef PVR_MANUAL_POWER_CONTROL
+IMG_INT PVRProcSetPowerLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT32 count, IMG_VOID *data);
+
+void ProcSeqShowPowerLevel(struct seq_file *sfile,void* el);
+
+#endif
+
+#endif
+
+#endif
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef __LOCK_H__
+#define __LOCK_H__
+
+extern PVRSRV_LINUX_MUTEX gPVRSRVLock;
+
+#endif
--- /dev/null
+/**********************************************************************
+ *
+ * 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/version.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <asm/io.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+#include <linux/wrapper.h>
+#endif
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/sched.h>
+
+#include "img_defs.h"
+#include "services.h"
+#include "servicesint.h"
+#include "syscommon.h"
+#include "mutils.h"
+#include "mm.h"
+#include "pvrmmap.h"
+#include "mmap.h"
+#include "osfunc.h"
+#include "pvr_debug.h"
+#include "proc.h"
+#include "mutex.h"
+#include "lock.h"
+
+#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ #include "lists.h"
+#endif
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+typedef enum {
+ DEBUG_MEM_ALLOC_TYPE_KMALLOC,
+ DEBUG_MEM_ALLOC_TYPE_VMALLOC,
+ DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES,
+ DEBUG_MEM_ALLOC_TYPE_IOREMAP,
+ DEBUG_MEM_ALLOC_TYPE_IO,
+ DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE,
+ DEBUG_MEM_ALLOC_TYPE_COUNT
+}DEBUG_MEM_ALLOC_TYPE;
+
+typedef struct _DEBUG_MEM_ALLOC_REC
+{
+ DEBUG_MEM_ALLOC_TYPE eAllocType;
+ IMG_VOID *pvKey;
+ IMG_VOID *pvCpuVAddr;
+ IMG_UINT32 ulCpuPAddr;
+ IMG_VOID *pvPrivateData;
+ IMG_UINT32 ui32Bytes;
+ pid_t pid;
+ IMG_CHAR *pszFileName;
+ IMG_UINT32 ui32Line;
+
+ struct _DEBUG_MEM_ALLOC_REC *psNext;
+ struct _DEBUG_MEM_ALLOC_REC **ppsThis;
+}DEBUG_MEM_ALLOC_REC;
+
+static IMPLEMENT_LIST_ANY_VA_2(DEBUG_MEM_ALLOC_REC, IMG_BOOL, IMG_FALSE)
+static IMPLEMENT_LIST_ANY_VA(DEBUG_MEM_ALLOC_REC)
+static IMPLEMENT_LIST_FOR_EACH(DEBUG_MEM_ALLOC_REC)
+static IMPLEMENT_LIST_INSERT(DEBUG_MEM_ALLOC_REC)
+static IMPLEMENT_LIST_REMOVE(DEBUG_MEM_ALLOC_REC)
+
+
+static DEBUG_MEM_ALLOC_REC *g_MemoryRecords;
+
+static IMG_UINT32 g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_COUNT];
+static IMG_UINT32 g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_COUNT];
+
+static IMG_UINT32 g_SysRAMWaterMark;
+static IMG_UINT32 g_SysRAMHighWaterMark;
+
+static IMG_UINT32 g_IOMemWaterMark;
+static IMG_UINT32 g_IOMemHighWaterMark;
+
+static IMG_VOID DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE eAllocType,
+ IMG_VOID *pvKey,
+ IMG_VOID *pvCpuVAddr,
+ IMG_UINT32 ulCpuPAddr,
+ IMG_VOID *pvPrivateData,
+ IMG_UINT32 ui32Bytes,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32Line);
+
+static IMG_VOID DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE eAllocType, IMG_VOID *pvKey, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+
+static IMG_CHAR *DebugMemAllocRecordTypeToString(DEBUG_MEM_ALLOC_TYPE eAllocType);
+
+
+static struct proc_dir_entry *g_SeqFileMemoryRecords =0;
+static void* ProcSeqNextMemoryRecords(struct seq_file *sfile,void* el,loff_t off);
+static void ProcSeqShowMemoryRecords(struct seq_file *sfile,void* el);
+static void* ProcSeqOff2ElementMemoryRecords(struct seq_file * sfile, loff_t off);
+
+#endif
+
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+typedef struct _DEBUG_LINUX_MEM_AREA_REC
+{
+ LinuxMemArea *psLinuxMemArea;
+ IMG_UINT32 ui32Flags;
+ pid_t pid;
+
+ struct _DEBUG_LINUX_MEM_AREA_REC *psNext;
+ struct _DEBUG_LINUX_MEM_AREA_REC **ppsThis;
+}DEBUG_LINUX_MEM_AREA_REC;
+
+
+static IMPLEMENT_LIST_ANY_VA(DEBUG_LINUX_MEM_AREA_REC)
+static IMPLEMENT_LIST_FOR_EACH(DEBUG_LINUX_MEM_AREA_REC)
+static IMPLEMENT_LIST_INSERT(DEBUG_LINUX_MEM_AREA_REC)
+static IMPLEMENT_LIST_REMOVE(DEBUG_LINUX_MEM_AREA_REC)
+
+
+
+
+static DEBUG_LINUX_MEM_AREA_REC *g_LinuxMemAreaRecords;
+static IMG_UINT32 g_LinuxMemAreaCount;
+static IMG_UINT32 g_LinuxMemAreaWaterMark;
+static IMG_UINT32 g_LinuxMemAreaHighWaterMark;
+
+
+static struct proc_dir_entry *g_SeqFileMemArea=0;
+
+static void* ProcSeqNextMemArea(struct seq_file *sfile,void* el,loff_t off);
+static void ProcSeqShowMemArea(struct seq_file *sfile,void* el);
+static void* ProcSeqOff2ElementMemArea(struct seq_file *sfile, loff_t off);
+
+#endif
+
+#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+static PVRSRV_LINUX_MUTEX g_sDebugMutex;
+#endif
+
+#if (defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS))
+static void ProcSeqStartstopDebugMutex(struct seq_file *sfile,IMG_BOOL start);
+#endif
+
+static LinuxKMemCache *psLinuxMemAreaCache;
+
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
+static IMG_VOID ReservePages(IMG_VOID *pvAddress, IMG_UINT32 ui32Length);
+static IMG_VOID UnreservePages(IMG_VOID *pvAddress, IMG_UINT32 ui32Length);
+#endif
+
+static LinuxMemArea *LinuxMemAreaStructAlloc(IMG_VOID);
+static IMG_VOID LinuxMemAreaStructFree(LinuxMemArea *psLinuxMemArea);
+#if defined(DEBUG_LINUX_MEM_AREAS)
+static IMG_VOID DebugLinuxMemAreaRecordAdd(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32Flags);
+static DEBUG_LINUX_MEM_AREA_REC *DebugLinuxMemAreaRecordFind(LinuxMemArea *psLinuxMemArea);
+static IMG_VOID DebugLinuxMemAreaRecordRemove(LinuxMemArea *psLinuxMemArea);
+#endif
+
+PVRSRV_ERROR
+LinuxMMInit(IMG_VOID)
+{
+#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ LinuxInitMutex(&g_sDebugMutex);
+#endif
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ {
+ g_SeqFileMemArea = CreateProcReadEntrySeq(
+ "mem_areas",
+ NULL,
+ ProcSeqNextMemArea,
+ ProcSeqShowMemArea,
+ ProcSeqOff2ElementMemArea,
+ ProcSeqStartstopDebugMutex
+ );
+ if(!g_SeqFileMemArea)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ }
+#endif
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ {
+ g_SeqFileMemoryRecords =CreateProcReadEntrySeq(
+ "meminfo",
+ NULL,
+ ProcSeqNextMemoryRecords,
+ ProcSeqShowMemoryRecords,
+ ProcSeqOff2ElementMemoryRecords,
+ ProcSeqStartstopDebugMutex
+ );
+ if(!g_SeqFileMemoryRecords)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ }
+#endif
+
+ psLinuxMemAreaCache = KMemCacheCreateWrapper("img-mm", sizeof(LinuxMemArea), 0, 0);
+ if(!psLinuxMemAreaCache)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: failed to allocate kmem_cache", __FUNCTION__));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ return PVRSRV_OK;
+}
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+static IMG_VOID LinuxMMCleanup_MemAreas_ForEachCb(DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord)
+{
+ LinuxMemArea *psLinuxMemArea;
+
+ psLinuxMemArea = psCurrentRecord->psLinuxMemArea;
+ PVR_DPF((PVR_DBG_ERROR, "%s: BUG!: Cleaning up Linux memory area (%p), type=%s, size=%d bytes",
+ __FUNCTION__,
+ psCurrentRecord->psLinuxMemArea,
+ LinuxMemAreaTypeToString(psCurrentRecord->psLinuxMemArea->eAreaType),
+ psCurrentRecord->psLinuxMemArea->ui32ByteSize));
+
+ LinuxMemAreaDeepFree(psLinuxMemArea);
+}
+#endif
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+static IMG_VOID LinuxMMCleanup_MemRecords_ForEachVa(DEBUG_MEM_ALLOC_REC *psCurrentRecord)
+
+{
+
+ PVR_DPF((PVR_DBG_ERROR, "%s: BUG!: Cleaning up memory: "
+ "type=%s "
+ "CpuVAddr=%p "
+ "CpuPAddr=0x%08x, "
+ "allocated @ file=%s,line=%d",
+ __FUNCTION__,
+ DebugMemAllocRecordTypeToString(psCurrentRecord->eAllocType),
+ psCurrentRecord->pvCpuVAddr,
+ psCurrentRecord->ulCpuPAddr,
+ psCurrentRecord->pszFileName,
+ psCurrentRecord->ui32Line));
+ switch(psCurrentRecord->eAllocType)
+ {
+ case DEBUG_MEM_ALLOC_TYPE_KMALLOC:
+ KFreeWrapper(psCurrentRecord->pvCpuVAddr);
+ break;
+ case DEBUG_MEM_ALLOC_TYPE_IOREMAP:
+ IOUnmapWrapper(psCurrentRecord->pvCpuVAddr);
+ break;
+ case DEBUG_MEM_ALLOC_TYPE_IO:
+
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_IO, psCurrentRecord->pvKey, __FILE__, __LINE__);
+ break;
+ case DEBUG_MEM_ALLOC_TYPE_VMALLOC:
+ VFreeWrapper(psCurrentRecord->pvCpuVAddr);
+ break;
+ case DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES:
+
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES, psCurrentRecord->pvKey, __FILE__, __LINE__);
+ break;
+ case DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE:
+ KMemCacheFreeWrapper(psCurrentRecord->pvPrivateData, psCurrentRecord->pvCpuVAddr);
+ break;
+ default:
+ PVR_ASSERT(0);
+ }
+}
+#endif
+
+
+IMG_VOID
+LinuxMMCleanup(IMG_VOID)
+{
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ {
+ if(g_LinuxMemAreaCount)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: BUG!: There are %d LinuxMemArea allocation unfreed (%d bytes)",
+ __FUNCTION__, g_LinuxMemAreaCount, g_LinuxMemAreaWaterMark));
+ }
+
+ List_DEBUG_LINUX_MEM_AREA_REC_ForEach(g_LinuxMemAreaRecords,
+ LinuxMMCleanup_MemAreas_ForEachCb);
+
+ RemoveProcEntrySeq( g_SeqFileMemArea );
+ }
+#endif
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ {
+
+
+ List_DEBUG_MEM_ALLOC_REC_ForEach(g_MemoryRecords,
+ LinuxMMCleanup_MemRecords_ForEachVa);
+
+ RemoveProcEntrySeq( g_SeqFileMemoryRecords );
+ }
+#endif
+
+ if(psLinuxMemAreaCache)
+ {
+ KMemCacheDestroyWrapper(psLinuxMemAreaCache);
+ psLinuxMemAreaCache=NULL;
+ }
+}
+
+
+IMG_VOID *
+_KMallocWrapper(IMG_UINT32 ui32ByteSize, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+ IMG_VOID *pvRet;
+ pvRet = kmalloc(ui32ByteSize, GFP_KERNEL);
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ if(pvRet)
+ {
+ DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_KMALLOC,
+ pvRet,
+ pvRet,
+ 0,
+ NULL,
+ ui32ByteSize,
+ pszFileName,
+ ui32Line
+ );
+ }
+#else
+ PVR_UNREFERENCED_PARAMETER(pszFileName);
+ PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+ return pvRet;
+}
+
+
+IMG_VOID
+_KFreeWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_KMALLOC, pvCpuVAddr, pszFileName, ui32Line);
+#else
+ PVR_UNREFERENCED_PARAMETER(pszFileName);
+ PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+ kfree(pvCpuVAddr);
+}
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+static IMG_VOID
+DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE eAllocType,
+ IMG_VOID *pvKey,
+ IMG_VOID *pvCpuVAddr,
+ IMG_UINT32 ulCpuPAddr,
+ IMG_VOID *pvPrivateData,
+ IMG_UINT32 ui32Bytes,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32Line)
+{
+ DEBUG_MEM_ALLOC_REC *psRecord;
+
+ LinuxLockMutex(&g_sDebugMutex);
+
+ psRecord = kmalloc(sizeof(DEBUG_MEM_ALLOC_REC), GFP_KERNEL);
+
+ psRecord->eAllocType = eAllocType;
+ psRecord->pvKey = pvKey;
+ psRecord->pvCpuVAddr = pvCpuVAddr;
+ psRecord->ulCpuPAddr = ulCpuPAddr;
+ psRecord->pvPrivateData = pvPrivateData;
+ psRecord->pid = current->pid;
+ psRecord->ui32Bytes = ui32Bytes;
+ psRecord->pszFileName = pszFileName;
+ psRecord->ui32Line = ui32Line;
+
+ List_DEBUG_MEM_ALLOC_REC_Insert(&g_MemoryRecords, psRecord);
+
+ g_WaterMarkData[eAllocType] += ui32Bytes;
+ if(g_WaterMarkData[eAllocType] > g_HighWaterMarkData[eAllocType])
+ {
+ g_HighWaterMarkData[eAllocType] = g_WaterMarkData[eAllocType];
+ }
+
+ if(eAllocType == DEBUG_MEM_ALLOC_TYPE_KMALLOC
+ || eAllocType == DEBUG_MEM_ALLOC_TYPE_VMALLOC
+ || eAllocType == DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES
+ || eAllocType == DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE)
+ {
+ g_SysRAMWaterMark += ui32Bytes;
+ if(g_SysRAMWaterMark > g_SysRAMHighWaterMark)
+ {
+ g_SysRAMHighWaterMark = g_SysRAMWaterMark;
+ }
+ }
+ else if(eAllocType == DEBUG_MEM_ALLOC_TYPE_IOREMAP
+ || eAllocType == DEBUG_MEM_ALLOC_TYPE_IO)
+ {
+ g_IOMemWaterMark += ui32Bytes;
+ if(g_IOMemWaterMark > g_IOMemHighWaterMark)
+ {
+ g_IOMemHighWaterMark = g_IOMemWaterMark;
+ }
+ }
+
+ LinuxUnLockMutex(&g_sDebugMutex);
+}
+
+
+static IMG_BOOL DebugMemAllocRecordRemove_AnyVaCb(DEBUG_MEM_ALLOC_REC *psCurrentRecord, va_list va)
+{
+ DEBUG_MEM_ALLOC_TYPE eAllocType;
+ IMG_VOID *pvKey;
+
+ eAllocType = va_arg(va, DEBUG_MEM_ALLOC_TYPE);
+ pvKey = va_arg(va, IMG_VOID*);
+
+ if(psCurrentRecord->eAllocType == eAllocType
+ && psCurrentRecord->pvKey == pvKey)
+ {
+ eAllocType = psCurrentRecord->eAllocType;
+ g_WaterMarkData[eAllocType] -= psCurrentRecord->ui32Bytes;
+
+ if(eAllocType == DEBUG_MEM_ALLOC_TYPE_KMALLOC
+ || eAllocType == DEBUG_MEM_ALLOC_TYPE_VMALLOC
+ || eAllocType == DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES
+ || eAllocType == DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE)
+ {
+ g_SysRAMWaterMark -= psCurrentRecord->ui32Bytes;
+ }
+ else if(eAllocType == DEBUG_MEM_ALLOC_TYPE_IOREMAP
+ || eAllocType == DEBUG_MEM_ALLOC_TYPE_IO)
+ {
+ g_IOMemWaterMark -= psCurrentRecord->ui32Bytes;
+ }
+
+ List_DEBUG_MEM_ALLOC_REC_Remove(psCurrentRecord);
+ kfree(psCurrentRecord);
+
+ return IMG_TRUE;
+ }
+ else
+ {
+ return IMG_FALSE;
+ }
+}
+
+
+static IMG_VOID
+DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE eAllocType, IMG_VOID *pvKey, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+ LinuxLockMutex(&g_sDebugMutex);
+
+
+ if(!List_DEBUG_MEM_ALLOC_REC_IMG_BOOL_Any_va(g_MemoryRecords,
+ DebugMemAllocRecordRemove_AnyVaCb,
+ eAllocType,
+ pvKey))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: couldn't find an entry for type=%s with pvKey=%p (called from %s, line %d\n",
+ __FUNCTION__, DebugMemAllocRecordTypeToString(eAllocType), pvKey,
+ pszFileName, ui32Line));
+ }
+
+ LinuxUnLockMutex(&g_sDebugMutex);
+}
+
+
+static IMG_CHAR *
+DebugMemAllocRecordTypeToString(DEBUG_MEM_ALLOC_TYPE eAllocType)
+{
+ IMG_CHAR *apszDebugMemoryRecordTypes[] = {
+ "KMALLOC",
+ "VMALLOC",
+ "ALLOC_PAGES",
+ "IOREMAP",
+ "IO",
+ "KMEM_CACHE_ALLOC"
+ };
+ return apszDebugMemoryRecordTypes[eAllocType];
+}
+#endif
+
+
+
+IMG_VOID *
+_VMallocWrapper(IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32AllocFlags,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32Line)
+{
+ pgprot_t PGProtFlags;
+ IMG_VOID *pvRet;
+
+ switch(ui32AllocFlags & PVRSRV_HAP_CACHETYPE_MASK)
+ {
+ case PVRSRV_HAP_CACHED:
+ PGProtFlags = PAGE_KERNEL;
+ break;
+ case PVRSRV_HAP_WRITECOMBINE:
+ PGProtFlags = PGPROT_WC(PAGE_KERNEL);
+ break;
+ case PVRSRV_HAP_UNCACHED:
+ PGProtFlags = PGPROT_UC(PAGE_KERNEL);
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR,
+ "VMAllocWrapper: unknown mapping flags=0x%08x",
+ ui32AllocFlags));
+ dump_stack();
+ return NULL;
+ }
+
+
+ pvRet = __vmalloc(ui32Bytes, GFP_KERNEL | __GFP_HIGHMEM, PGProtFlags);
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ if(pvRet)
+ {
+ DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_VMALLOC,
+ pvRet,
+ pvRet,
+ 0,
+ NULL,
+ PAGE_ALIGN(ui32Bytes),
+ pszFileName,
+ ui32Line
+ );
+ }
+#else
+ PVR_UNREFERENCED_PARAMETER(pszFileName);
+ PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+
+ return pvRet;
+}
+
+
+IMG_VOID
+_VFreeWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_VMALLOC, pvCpuVAddr, pszFileName, ui32Line);
+#else
+ PVR_UNREFERENCED_PARAMETER(pszFileName);
+ PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+ vfree(pvCpuVAddr);
+}
+
+
+LinuxMemArea *
+NewVMallocLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags)
+{
+ LinuxMemArea *psLinuxMemArea;
+ IMG_VOID *pvCpuVAddr;
+
+ psLinuxMemArea = LinuxMemAreaStructAlloc();
+ if(!psLinuxMemArea)
+ {
+ goto failed;
+ }
+
+ pvCpuVAddr = VMallocWrapper(ui32Bytes, ui32AreaFlags);
+ if(!pvCpuVAddr)
+ {
+ goto failed;
+ }
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
+
+ ReservePages(pvCpuVAddr, ui32Bytes);
+#endif
+
+ psLinuxMemArea->eAreaType = LINUX_MEM_AREA_VMALLOC;
+ psLinuxMemArea->uData.sVmalloc.pvVmallocAddress = pvCpuVAddr;
+ psLinuxMemArea->ui32ByteSize = ui32Bytes;
+ psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
+ INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
+#endif
+
+
+ if(ui32AreaFlags & (PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_UNCACHED))
+ OSInvalidateCPUCacheRangeKM(psLinuxMemArea, pvCpuVAddr, ui32Bytes);
+
+ return psLinuxMemArea;
+
+failed:
+ PVR_DPF((PVR_DBG_ERROR, "%s: failed!", __FUNCTION__));
+ if(psLinuxMemArea)
+ LinuxMemAreaStructFree(psLinuxMemArea);
+ return NULL;
+}
+
+
+IMG_VOID
+FreeVMallocLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+ PVR_ASSERT(psLinuxMemArea);
+ PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_VMALLOC);
+ PVR_ASSERT(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
+ UnreservePages(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress,
+ psLinuxMemArea->ui32ByteSize);
+#endif
+
+ PVR_DPF((PVR_DBG_MESSAGE,"%s: pvCpuVAddr: %p",
+ __FUNCTION__, psLinuxMemArea->uData.sVmalloc.pvVmallocAddress));
+ VFreeWrapper(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress);
+
+ LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+IMG_VOID *
+_IORemapWrapper(IMG_CPU_PHYADDR BasePAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32MappingFlags,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32Line)
+{
+ IMG_VOID *pvIORemapCookie;
+
+ switch(ui32MappingFlags & PVRSRV_HAP_CACHETYPE_MASK)
+ {
+ case PVRSRV_HAP_CACHED:
+ pvIORemapCookie = (IMG_VOID *)IOREMAP(BasePAddr.uiAddr, ui32Bytes);
+ break;
+ case PVRSRV_HAP_WRITECOMBINE:
+ pvIORemapCookie = (IMG_VOID *)IOREMAP_WC(BasePAddr.uiAddr, ui32Bytes);
+ break;
+ case PVRSRV_HAP_UNCACHED:
+ pvIORemapCookie = (IMG_VOID *)IOREMAP_UC(BasePAddr.uiAddr, ui32Bytes);
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "IORemapWrapper: unknown mapping flags"));
+ return NULL;
+ }
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ if(pvIORemapCookie)
+ {
+ DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_IOREMAP,
+ pvIORemapCookie,
+ pvIORemapCookie,
+ BasePAddr.uiAddr,
+ NULL,
+ ui32Bytes,
+ pszFileName,
+ ui32Line
+ );
+ }
+#else
+ PVR_UNREFERENCED_PARAMETER(pszFileName);
+ PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+
+ return pvIORemapCookie;
+}
+
+
+IMG_VOID
+_IOUnmapWrapper(IMG_VOID *pvIORemapCookie, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_IOREMAP, pvIORemapCookie, pszFileName, ui32Line);
+#else
+ PVR_UNREFERENCED_PARAMETER(pszFileName);
+ PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+ iounmap(pvIORemapCookie);
+}
+
+
+LinuxMemArea *
+NewIORemapLinuxMemArea(IMG_CPU_PHYADDR BasePAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32AreaFlags)
+{
+ LinuxMemArea *psLinuxMemArea;
+ IMG_VOID *pvIORemapCookie;
+
+ psLinuxMemArea = LinuxMemAreaStructAlloc();
+ if(!psLinuxMemArea)
+ {
+ return NULL;
+ }
+
+ pvIORemapCookie = IORemapWrapper(BasePAddr, ui32Bytes, ui32AreaFlags);
+ if(!pvIORemapCookie)
+ {
+ LinuxMemAreaStructFree(psLinuxMemArea);
+ return NULL;
+ }
+
+ psLinuxMemArea->eAreaType = LINUX_MEM_AREA_IOREMAP;
+ psLinuxMemArea->uData.sIORemap.pvIORemapCookie = pvIORemapCookie;
+ psLinuxMemArea->uData.sIORemap.CPUPhysAddr = BasePAddr;
+ psLinuxMemArea->ui32ByteSize = ui32Bytes;
+ psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
+ INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
+#endif
+
+ return psLinuxMemArea;
+}
+
+
+IMG_VOID
+FreeIORemapLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+ PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_IOREMAP);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+
+ IOUnmapWrapper(psLinuxMemArea->uData.sIORemap.pvIORemapCookie);
+
+ LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+static IMG_BOOL
+TreatExternalPagesAsContiguous(IMG_SYS_PHYADDR *psSysPhysAddr, IMG_UINT32 ui32Bytes, IMG_BOOL bPhysContig)
+{
+ IMG_UINT32 ui32;
+ IMG_UINT32 ui32AddrChk;
+ IMG_UINT32 ui32NumPages = RANGE_TO_PAGES(ui32Bytes);
+
+
+ for (ui32 = 0, ui32AddrChk = psSysPhysAddr[0].uiAddr;
+ ui32 < ui32NumPages;
+ ui32++, ui32AddrChk = (bPhysContig) ? (ui32AddrChk + PAGE_SIZE) : psSysPhysAddr[ui32].uiAddr)
+ {
+ if (!pfn_valid(PHYS_TO_PFN(ui32AddrChk)))
+ {
+ break;
+ }
+ }
+ if (ui32 == ui32NumPages)
+ {
+ return IMG_FALSE;
+ }
+
+ if (!bPhysContig)
+ {
+ for (ui32 = 0, ui32AddrChk = psSysPhysAddr[0].uiAddr;
+ ui32 < ui32NumPages;
+ ui32++, ui32AddrChk += PAGE_SIZE)
+ {
+ if (psSysPhysAddr[ui32].uiAddr != ui32AddrChk)
+ {
+ return IMG_FALSE;
+ }
+ }
+ }
+
+ return IMG_TRUE;
+}
+#endif
+
+LinuxMemArea *NewExternalKVLinuxMemArea(IMG_SYS_PHYADDR *pBasePAddr, IMG_VOID *pvCPUVAddr, IMG_UINT32 ui32Bytes, IMG_BOOL bPhysContig, IMG_UINT32 ui32AreaFlags)
+{
+ LinuxMemArea *psLinuxMemArea;
+
+ psLinuxMemArea = LinuxMemAreaStructAlloc();
+ if(!psLinuxMemArea)
+ {
+ return NULL;
+ }
+
+ psLinuxMemArea->eAreaType = LINUX_MEM_AREA_EXTERNAL_KV;
+ psLinuxMemArea->uData.sExternalKV.pvExternalKV = pvCPUVAddr;
+ psLinuxMemArea->uData.sExternalKV.bPhysContig =
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+ (bPhysContig || TreatExternalPagesAsContiguous(pBasePAddr, ui32Bytes, bPhysContig))
+ ? IMG_TRUE : IMG_FALSE;
+#else
+ bPhysContig;
+#endif
+ if (psLinuxMemArea->uData.sExternalKV.bPhysContig)
+ {
+ psLinuxMemArea->uData.sExternalKV.uPhysAddr.SysPhysAddr = *pBasePAddr;
+ }
+ else
+ {
+ psLinuxMemArea->uData.sExternalKV.uPhysAddr.pSysPhysAddr = pBasePAddr;
+ }
+ psLinuxMemArea->ui32ByteSize = ui32Bytes;
+ psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
+ INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
+#endif
+
+ return psLinuxMemArea;
+}
+
+
+IMG_VOID
+FreeExternalKVLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+ PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_EXTERNAL_KV);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+
+ LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+
+LinuxMemArea *
+NewIOLinuxMemArea(IMG_CPU_PHYADDR BasePAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32AreaFlags)
+{
+ LinuxMemArea *psLinuxMemArea = LinuxMemAreaStructAlloc();
+ if(!psLinuxMemArea)
+ {
+ return NULL;
+ }
+
+
+ psLinuxMemArea->eAreaType = LINUX_MEM_AREA_IO;
+ psLinuxMemArea->uData.sIO.CPUPhysAddr.uiAddr = BasePAddr.uiAddr;
+ psLinuxMemArea->ui32ByteSize = ui32Bytes;
+ psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
+ INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_IO,
+ (IMG_VOID *)BasePAddr.uiAddr,
+ 0,
+ BasePAddr.uiAddr,
+ NULL,
+ ui32Bytes,
+ "unknown",
+ 0
+ );
+#endif
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
+#endif
+
+ return psLinuxMemArea;
+}
+
+
+IMG_VOID
+FreeIOLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+ PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_IO);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_IO,
+ (IMG_VOID *)psLinuxMemArea->uData.sIO.CPUPhysAddr.uiAddr, __FILE__, __LINE__);
+#endif
+
+
+
+ LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+
+LinuxMemArea *
+NewAllocPagesLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags)
+{
+ LinuxMemArea *psLinuxMemArea;
+ IMG_UINT32 ui32PageCount;
+ struct page **pvPageList;
+ IMG_HANDLE hBlockPageList;
+ IMG_INT32 i;
+ PVRSRV_ERROR eError;
+
+ psLinuxMemArea = LinuxMemAreaStructAlloc();
+ if(!psLinuxMemArea)
+ {
+ goto failed_area_alloc;
+ }
+
+ ui32PageCount = RANGE_TO_PAGES(ui32Bytes);
+ eError = OSAllocMem(0, sizeof(*pvPageList) * ui32PageCount, (IMG_VOID **)&pvPageList, &hBlockPageList,
+ "Array of pages");
+ if(eError != PVRSRV_OK)
+ {
+ goto failed_page_list_alloc;
+ }
+
+ for(i=0; i<(IMG_INT32)ui32PageCount; i++)
+ {
+ pvPageList[i] = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, 0);
+ if(!pvPageList[i])
+ {
+ goto failed_alloc_pages;
+ }
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
+ SetPageReserved(pvPageList[i]);
+#else
+ mem_map_reserve(pvPageList[i]);
+#endif
+#endif
+
+ }
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES,
+ pvPageList,
+ 0,
+ 0,
+ NULL,
+ PAGE_ALIGN(ui32Bytes),
+ "unknown",
+ 0
+ );
+#endif
+
+ psLinuxMemArea->eAreaType = LINUX_MEM_AREA_ALLOC_PAGES;
+ psLinuxMemArea->uData.sPageList.pvPageList = pvPageList;
+ psLinuxMemArea->uData.sPageList.hBlockPageList = hBlockPageList;
+ psLinuxMemArea->ui32ByteSize = ui32Bytes;
+ psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
+ INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+
+ if(ui32AreaFlags & (PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_UNCACHED))
+ {
+ psLinuxMemArea->bNeedsCacheInvalidate = IMG_TRUE;
+ }
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
+#endif
+
+ return psLinuxMemArea;
+
+failed_alloc_pages:
+ for(i--; i >= 0; i--)
+ {
+ __free_pages(pvPageList[i], 0);
+ }
+ (IMG_VOID) OSFreeMem(0, sizeof(*pvPageList) * ui32PageCount, pvPageList, hBlockPageList);
+ psLinuxMemArea->uData.sPageList.pvPageList = IMG_NULL;
+failed_page_list_alloc:
+ LinuxMemAreaStructFree(psLinuxMemArea);
+failed_area_alloc:
+ PVR_DPF((PVR_DBG_ERROR, "%s: failed", __FUNCTION__));
+
+ return NULL;
+}
+
+
+IMG_VOID
+FreeAllocPagesLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+ IMG_UINT32 ui32PageCount;
+ struct page **pvPageList;
+ IMG_HANDLE hBlockPageList;
+ IMG_INT32 i;
+
+ PVR_ASSERT(psLinuxMemArea);
+ PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_ALLOC_PAGES);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+
+ ui32PageCount = RANGE_TO_PAGES(psLinuxMemArea->ui32ByteSize);
+ pvPageList = psLinuxMemArea->uData.sPageList.pvPageList;
+ hBlockPageList = psLinuxMemArea->uData.sPageList.hBlockPageList;
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES, pvPageList, __FILE__, __LINE__);
+#endif
+
+ for(i=0;i<(IMG_INT32)ui32PageCount;i++)
+ {
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
+ ClearPageReserved(pvPageList[i]);
+#else
+ mem_map_reserve(pvPageList[i]);
+#endif
+#endif
+ __free_pages(pvPageList[i], 0);
+ }
+
+ (IMG_VOID) OSFreeMem(0, sizeof(*pvPageList) * ui32PageCount, pvPageList, hBlockPageList);
+ psLinuxMemArea->uData.sPageList.pvPageList = IMG_NULL;
+
+ LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+
+struct page*
+LinuxMemAreaOffsetToPage(LinuxMemArea *psLinuxMemArea,
+ IMG_UINT32 ui32ByteOffset)
+{
+ IMG_UINT32 ui32PageIndex;
+ IMG_CHAR *pui8Addr;
+
+ switch(psLinuxMemArea->eAreaType)
+ {
+ case LINUX_MEM_AREA_ALLOC_PAGES:
+ ui32PageIndex = PHYS_TO_PFN(ui32ByteOffset);
+ return psLinuxMemArea->uData.sPageList.pvPageList[ui32PageIndex];
+
+ case LINUX_MEM_AREA_VMALLOC:
+ pui8Addr = psLinuxMemArea->uData.sVmalloc.pvVmallocAddress;
+ pui8Addr += ui32ByteOffset;
+ return vmalloc_to_page(pui8Addr);
+
+ case LINUX_MEM_AREA_SUB_ALLOC:
+
+ return LinuxMemAreaOffsetToPage(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea,
+ psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset
+ + ui32ByteOffset);
+ default:
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: Unsupported request for struct page from LinuxMemArea with type=%s",
+ __FUNCTION__, LinuxMemAreaTypeToString(psLinuxMemArea->eAreaType)));
+ return NULL;
+ }
+}
+
+
+LinuxKMemCache *
+KMemCacheCreateWrapper(IMG_CHAR *pszName,
+ size_t Size,
+ size_t Align,
+ IMG_UINT32 ui32Flags)
+{
+#if defined(DEBUG_LINUX_SLAB_ALLOCATIONS)
+ ui32Flags |= SLAB_POISON|SLAB_RED_ZONE;
+#endif
+ return kmem_cache_create(pszName, Size, Align, ui32Flags, NULL
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22))
+ , NULL
+#endif
+ );
+}
+
+
+IMG_VOID
+KMemCacheDestroyWrapper(LinuxKMemCache *psCache)
+{
+ kmem_cache_destroy(psCache);
+}
+
+
+IMG_VOID *
+_KMemCacheAllocWrapper(LinuxKMemCache *psCache,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14))
+ gfp_t Flags,
+#else
+ IMG_INT Flags,
+#endif
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32Line)
+{
+ IMG_VOID *pvRet;
+
+ pvRet = kmem_cache_zalloc(psCache, Flags);
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE,
+ pvRet,
+ pvRet,
+ 0,
+ psCache,
+ kmem_cache_size(psCache),
+ pszFileName,
+ ui32Line
+ );
+#else
+ PVR_UNREFERENCED_PARAMETER(pszFileName);
+ PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+
+ return pvRet;
+}
+
+
+IMG_VOID
+_KMemCacheFreeWrapper(LinuxKMemCache *psCache, IMG_VOID *pvObject, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE, pvObject, pszFileName, ui32Line);
+#else
+ PVR_UNREFERENCED_PARAMETER(pszFileName);
+ PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+
+ kmem_cache_free(psCache, pvObject);
+}
+
+
+const IMG_CHAR *
+KMemCacheNameWrapper(LinuxKMemCache *psCache)
+{
+ PVR_UNREFERENCED_PARAMETER(psCache);
+
+
+ return "";
+}
+
+
+LinuxMemArea *
+NewSubLinuxMemArea(LinuxMemArea *psParentLinuxMemArea,
+ IMG_UINT32 ui32ByteOffset,
+ IMG_UINT32 ui32Bytes)
+{
+ LinuxMemArea *psLinuxMemArea;
+
+ PVR_ASSERT((ui32ByteOffset+ui32Bytes) <= psParentLinuxMemArea->ui32ByteSize);
+
+ psLinuxMemArea = LinuxMemAreaStructAlloc();
+ if(!psLinuxMemArea)
+ {
+ return NULL;
+ }
+
+ psLinuxMemArea->eAreaType = LINUX_MEM_AREA_SUB_ALLOC;
+ psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea = psParentLinuxMemArea;
+ psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset = ui32ByteOffset;
+ psLinuxMemArea->ui32ByteSize = ui32Bytes;
+ psLinuxMemArea->ui32AreaFlags = psParentLinuxMemArea->ui32AreaFlags;
+ psLinuxMemArea->bNeedsCacheInvalidate = psParentLinuxMemArea->bNeedsCacheInvalidate;
+ INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ {
+ DEBUG_LINUX_MEM_AREA_REC *psParentRecord;
+ psParentRecord = DebugLinuxMemAreaRecordFind(psParentLinuxMemArea);
+ DebugLinuxMemAreaRecordAdd(psLinuxMemArea, psParentRecord->ui32Flags);
+ }
+#endif
+
+ return psLinuxMemArea;
+}
+
+
+static IMG_VOID
+FreeSubLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+ PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+
+
+
+ LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+
+static LinuxMemArea *
+LinuxMemAreaStructAlloc(IMG_VOID)
+{
+#if 0
+ LinuxMemArea *psLinuxMemArea;
+ psLinuxMemArea = kmem_cache_alloc(psLinuxMemAreaCache, GFP_KERNEL);
+ printk(KERN_ERR "%s: psLinuxMemArea=%p\n", __FUNCTION__, psLinuxMemArea);
+ dump_stack();
+ return psLinuxMemArea;
+#else
+ return KMemCacheAllocWrapper(psLinuxMemAreaCache, GFP_KERNEL);
+#endif
+}
+
+
+static IMG_VOID
+LinuxMemAreaStructFree(LinuxMemArea *psLinuxMemArea)
+{
+ KMemCacheFreeWrapper(psLinuxMemAreaCache, psLinuxMemArea);
+
+
+}
+
+
+IMG_VOID
+LinuxMemAreaDeepFree(LinuxMemArea *psLinuxMemArea)
+{
+ switch(psLinuxMemArea->eAreaType)
+ {
+ case LINUX_MEM_AREA_VMALLOC:
+ FreeVMallocLinuxMemArea(psLinuxMemArea);
+ break;
+ case LINUX_MEM_AREA_ALLOC_PAGES:
+ FreeAllocPagesLinuxMemArea(psLinuxMemArea);
+ break;
+ case LINUX_MEM_AREA_IOREMAP:
+ FreeIORemapLinuxMemArea(psLinuxMemArea);
+ break;
+ case LINUX_MEM_AREA_EXTERNAL_KV:
+ FreeExternalKVLinuxMemArea(psLinuxMemArea);
+ break;
+ case LINUX_MEM_AREA_IO:
+ FreeIOLinuxMemArea(psLinuxMemArea);
+ break;
+ case LINUX_MEM_AREA_SUB_ALLOC:
+ FreeSubLinuxMemArea(psLinuxMemArea);
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "%s: Unknown are type (%d)\n",
+ __FUNCTION__, psLinuxMemArea->eAreaType));
+ break;
+ }
+}
+
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+static IMG_VOID
+DebugLinuxMemAreaRecordAdd(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32Flags)
+{
+ DEBUG_LINUX_MEM_AREA_REC *psNewRecord;
+ const IMG_CHAR *pi8FlagsString;
+
+ LinuxLockMutex(&g_sDebugMutex);
+
+ if(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
+ {
+ g_LinuxMemAreaWaterMark += psLinuxMemArea->ui32ByteSize;
+ if(g_LinuxMemAreaWaterMark > g_LinuxMemAreaHighWaterMark)
+ {
+ g_LinuxMemAreaHighWaterMark = g_LinuxMemAreaWaterMark;
+ }
+ }
+ g_LinuxMemAreaCount++;
+
+
+ psNewRecord = kmalloc(sizeof(DEBUG_LINUX_MEM_AREA_REC), GFP_KERNEL);
+ if(psNewRecord)
+ {
+
+ psNewRecord->psLinuxMemArea = psLinuxMemArea;
+ psNewRecord->ui32Flags = ui32Flags;
+ psNewRecord->pid = current->pid;
+
+ List_DEBUG_LINUX_MEM_AREA_REC_Insert(&g_LinuxMemAreaRecords, psNewRecord);
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: failed to allocate linux memory area record.",
+ __FUNCTION__));
+ }
+
+
+ pi8FlagsString = HAPFlagsToString(ui32Flags);
+ if(strstr(pi8FlagsString, "UNKNOWN"))
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: Unexpected flags (0x%08x) associated with psLinuxMemArea @ %p",
+ __FUNCTION__,
+ ui32Flags,
+ psLinuxMemArea));
+
+ }
+
+ LinuxUnLockMutex(&g_sDebugMutex);
+}
+
+
+
+static IMG_VOID* MatchLinuxMemArea_AnyVaCb(DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord,
+ va_list va)
+{
+ LinuxMemArea *psLinuxMemArea;
+
+ psLinuxMemArea = va_arg(va, LinuxMemArea*);
+ if(psCurrentRecord->psLinuxMemArea == psLinuxMemArea)
+ {
+ return psCurrentRecord;
+ }
+ else
+ {
+ return IMG_NULL;
+ }
+}
+
+
+static DEBUG_LINUX_MEM_AREA_REC *
+DebugLinuxMemAreaRecordFind(LinuxMemArea *psLinuxMemArea)
+{
+ DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord;
+
+ LinuxLockMutex(&g_sDebugMutex);
+ psCurrentRecord = List_DEBUG_LINUX_MEM_AREA_REC_Any_va(g_LinuxMemAreaRecords,
+ MatchLinuxMemArea_AnyVaCb,
+ psLinuxMemArea);
+
+ LinuxUnLockMutex(&g_sDebugMutex);
+
+ return psCurrentRecord;
+}
+
+
+static IMG_VOID
+DebugLinuxMemAreaRecordRemove(LinuxMemArea *psLinuxMemArea)
+{
+ DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord;
+
+ LinuxLockMutex(&g_sDebugMutex);
+
+ if(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
+ {
+ g_LinuxMemAreaWaterMark -= psLinuxMemArea->ui32ByteSize;
+ }
+ g_LinuxMemAreaCount--;
+
+
+ psCurrentRecord = List_DEBUG_LINUX_MEM_AREA_REC_Any_va(g_LinuxMemAreaRecords,
+ MatchLinuxMemArea_AnyVaCb,
+ psLinuxMemArea);
+ if(psCurrentRecord)
+ {
+
+ List_DEBUG_LINUX_MEM_AREA_REC_Remove(psCurrentRecord);
+ kfree(psCurrentRecord);
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: couldn't find an entry for psLinuxMemArea=%p\n",
+ __FUNCTION__, psLinuxMemArea));
+ }
+
+ LinuxUnLockMutex(&g_sDebugMutex);
+}
+#endif
+
+
+IMG_VOID *
+LinuxMemAreaToCpuVAddr(LinuxMemArea *psLinuxMemArea)
+{
+ switch(psLinuxMemArea->eAreaType)
+ {
+ case LINUX_MEM_AREA_VMALLOC:
+ return psLinuxMemArea->uData.sVmalloc.pvVmallocAddress;
+ case LINUX_MEM_AREA_IOREMAP:
+ return psLinuxMemArea->uData.sIORemap.pvIORemapCookie;
+ case LINUX_MEM_AREA_EXTERNAL_KV:
+ return psLinuxMemArea->uData.sExternalKV.pvExternalKV;
+ case LINUX_MEM_AREA_SUB_ALLOC:
+ {
+ IMG_CHAR *pAddr =
+ LinuxMemAreaToCpuVAddr(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea);
+ if(!pAddr)
+ {
+ return NULL;
+ }
+ return pAddr + psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset;
+ }
+ default:
+ return NULL;
+ }
+}
+
+
+IMG_CPU_PHYADDR
+LinuxMemAreaToCpuPAddr(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32ByteOffset)
+{
+ IMG_CPU_PHYADDR CpuPAddr;
+
+ CpuPAddr.uiAddr = 0;
+
+ switch(psLinuxMemArea->eAreaType)
+ {
+ case LINUX_MEM_AREA_IOREMAP:
+ {
+ CpuPAddr = psLinuxMemArea->uData.sIORemap.CPUPhysAddr;
+ CpuPAddr.uiAddr += ui32ByteOffset;
+ break;
+ }
+ case LINUX_MEM_AREA_EXTERNAL_KV:
+ {
+ if (psLinuxMemArea->uData.sExternalKV.bPhysContig)
+ {
+ CpuPAddr = SysSysPAddrToCpuPAddr(psLinuxMemArea->uData.sExternalKV.uPhysAddr.SysPhysAddr);
+ CpuPAddr.uiAddr += ui32ByteOffset;
+ }
+ else
+ {
+ IMG_UINT32 ui32PageIndex = PHYS_TO_PFN(ui32ByteOffset);
+ IMG_SYS_PHYADDR SysPAddr = psLinuxMemArea->uData.sExternalKV.uPhysAddr.pSysPhysAddr[ui32PageIndex];
+
+ CpuPAddr = SysSysPAddrToCpuPAddr(SysPAddr);
+ CpuPAddr.uiAddr += ADDR_TO_PAGE_OFFSET(ui32ByteOffset);
+ }
+ break;
+ }
+ case LINUX_MEM_AREA_IO:
+ {
+ CpuPAddr = psLinuxMemArea->uData.sIO.CPUPhysAddr;
+ CpuPAddr.uiAddr += ui32ByteOffset;
+ break;
+ }
+ case LINUX_MEM_AREA_VMALLOC:
+ {
+ IMG_CHAR *pCpuVAddr;
+ pCpuVAddr =
+ (IMG_CHAR *)psLinuxMemArea->uData.sVmalloc.pvVmallocAddress;
+ pCpuVAddr += ui32ByteOffset;
+ CpuPAddr.uiAddr = VMallocToPhys(pCpuVAddr);
+ break;
+ }
+ case LINUX_MEM_AREA_ALLOC_PAGES:
+ {
+ struct page *page;
+ IMG_UINT32 ui32PageIndex = PHYS_TO_PFN(ui32ByteOffset);
+ page = psLinuxMemArea->uData.sPageList.pvPageList[ui32PageIndex];
+ CpuPAddr.uiAddr = page_to_phys(page);
+ CpuPAddr.uiAddr += ADDR_TO_PAGE_OFFSET(ui32ByteOffset);
+ break;
+ }
+ case LINUX_MEM_AREA_SUB_ALLOC:
+ {
+ CpuPAddr =
+ OSMemHandleToCpuPAddr(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea,
+ psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset
+ + ui32ByteOffset);
+ break;
+ }
+ default:
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Unknown LinuxMemArea type (%d)\n",
+ __FUNCTION__, psLinuxMemArea->eAreaType));
+ PVR_ASSERT(CpuPAddr.uiAddr);
+ break;
+ }
+ }
+
+ return CpuPAddr;
+}
+
+
+IMG_BOOL
+LinuxMemAreaPhysIsContig(LinuxMemArea *psLinuxMemArea)
+{
+ switch(psLinuxMemArea->eAreaType)
+ {
+ case LINUX_MEM_AREA_IOREMAP:
+ case LINUX_MEM_AREA_IO:
+ return IMG_TRUE;
+
+ case LINUX_MEM_AREA_EXTERNAL_KV:
+ return psLinuxMemArea->uData.sExternalKV.bPhysContig;
+
+ case LINUX_MEM_AREA_VMALLOC:
+ case LINUX_MEM_AREA_ALLOC_PAGES:
+ return IMG_FALSE;
+
+ case LINUX_MEM_AREA_SUB_ALLOC:
+
+ return LinuxMemAreaPhysIsContig(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea);
+
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "%s: Unknown LinuxMemArea type (%d)\n",
+ __FUNCTION__, psLinuxMemArea->eAreaType));
+ break;
+ }
+ return IMG_FALSE;
+}
+
+
+const IMG_CHAR *
+LinuxMemAreaTypeToString(LINUX_MEM_AREA_TYPE eMemAreaType)
+{
+
+ switch(eMemAreaType)
+ {
+ case LINUX_MEM_AREA_IOREMAP:
+ return "LINUX_MEM_AREA_IOREMAP";
+ case LINUX_MEM_AREA_EXTERNAL_KV:
+ return "LINUX_MEM_AREA_EXTERNAL_KV";
+ case LINUX_MEM_AREA_IO:
+ return "LINUX_MEM_AREA_IO";
+ case LINUX_MEM_AREA_VMALLOC:
+ return "LINUX_MEM_AREA_VMALLOC";
+ case LINUX_MEM_AREA_SUB_ALLOC:
+ return "LINUX_MEM_AREA_SUB_ALLOC";
+ case LINUX_MEM_AREA_ALLOC_PAGES:
+ return "LINUX_MEM_AREA_ALLOC_PAGES";
+ default:
+ PVR_ASSERT(0);
+ }
+
+ return "";
+}
+
+
+#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+static void ProcSeqStartstopDebugMutex(struct seq_file *sfile, IMG_BOOL start)
+{
+ if(start)
+ {
+ LinuxLockMutex(&g_sDebugMutex);
+ }
+ else
+ {
+ LinuxUnLockMutex(&g_sDebugMutex);
+ }
+}
+#endif
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+
+static IMG_VOID* DecOffMemAreaRec_AnyVaCb(DEBUG_LINUX_MEM_AREA_REC *psNode, va_list va)
+{
+ off_t *pOff = va_arg(va, off_t*);
+ if (--(*pOff))
+ {
+ return IMG_NULL;
+ }
+ else
+ {
+ return psNode;
+ }
+}
+
+
+static void* ProcSeqNextMemArea(struct seq_file *sfile,void* el,loff_t off)
+{
+ DEBUG_LINUX_MEM_AREA_REC *psRecord;
+ psRecord = (DEBUG_LINUX_MEM_AREA_REC*)
+ List_DEBUG_LINUX_MEM_AREA_REC_Any_va(g_LinuxMemAreaRecords,
+ DecOffMemAreaRec_AnyVaCb,
+ &off);
+ return (void*)psRecord;
+}
+
+static void* ProcSeqOff2ElementMemArea(struct seq_file * sfile, loff_t off)
+{
+ DEBUG_LINUX_MEM_AREA_REC *psRecord;
+ if(!off)
+ {
+ return PVR_PROC_SEQ_START_TOKEN;
+ }
+
+ psRecord = (DEBUG_LINUX_MEM_AREA_REC*)
+ List_DEBUG_LINUX_MEM_AREA_REC_Any_va(g_LinuxMemAreaRecords,
+ DecOffMemAreaRec_AnyVaCb,
+ &off);
+ return (void*)psRecord;
+}
+
+
+static void ProcSeqShowMemArea(struct seq_file *sfile,void* el)
+{
+ DEBUG_LINUX_MEM_AREA_REC *psRecord = (DEBUG_LINUX_MEM_AREA_REC*)el;
+ if(el == PVR_PROC_SEQ_START_TOKEN)
+ {
+
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+ seq_printf( sfile,
+ "Number of Linux Memory Areas: %u\n"
+ "At the current water mark these areas correspond to %u bytes (excluding SUB areas)\n"
+ "At the highest water mark these areas corresponded to %u bytes (excluding SUB areas)\n"
+ "\nDetails for all Linux Memory Areas:\n"
+ "%s %-24s %s %s %-8s %-5s %s\n",
+ g_LinuxMemAreaCount,
+ g_LinuxMemAreaWaterMark,
+ g_LinuxMemAreaHighWaterMark,
+ "psLinuxMemArea",
+ "LinuxMemType",
+ "CpuVAddr",
+ "CpuPAddr",
+ "Bytes",
+ "Pid",
+ "Flags"
+ );
+#else
+ seq_printf( sfile,
+ "<mem_areas_header>\n"
+ "\t<count>%u</count>\n"
+ "\t<watermark key=\"mar0\" description=\"current\" bytes=\"%u\"/>\n"
+ "\t<watermark key=\"mar1\" description=\"high\" bytes=\"%u\"/>\n"
+ "</mem_areas_header>\n",
+ g_LinuxMemAreaCount,
+ g_LinuxMemAreaWaterMark,
+ g_LinuxMemAreaHighWaterMark
+ );
+#endif
+ return;
+ }
+
+ seq_printf( sfile,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+ "%8p %-24s %8p %08x %-8d %-5u %08x=(%s)\n",
+#else
+ "<linux_mem_area>\n"
+ "\t<pointer>%8p</pointer>\n"
+ "\t<type>%s</type>\n"
+ "\t<cpu_virtual>%8p</cpu_virtual>\n"
+ "\t<cpu_physical>%08x</cpu_physical>\n"
+ "\t<bytes>%ld</bytes>\n"
+ "\t<pid>%u</pid>\n"
+ "\t<flags>%08lx</flags>\n"
+ "\t<flags_string>%s</flags_string>\n"
+ "</linux_mem_area>\n",
+#endif
+ psRecord->psLinuxMemArea,
+ LinuxMemAreaTypeToString(psRecord->psLinuxMemArea->eAreaType),
+ LinuxMemAreaToCpuVAddr(psRecord->psLinuxMemArea),
+ LinuxMemAreaToCpuPAddr(psRecord->psLinuxMemArea,0).uiAddr,
+ psRecord->psLinuxMemArea->ui32ByteSize,
+ psRecord->pid,
+ psRecord->ui32Flags,
+ HAPFlagsToString(psRecord->ui32Flags)
+ );
+
+}
+
+#endif
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+
+static IMG_VOID* DecOffMemAllocRec_AnyVaCb(DEBUG_MEM_ALLOC_REC *psNode, va_list va)
+{
+ off_t *pOff = va_arg(va, off_t*);
+ if (--(*pOff))
+ {
+ return IMG_NULL;
+ }
+ else
+ {
+ return psNode;
+ }
+}
+
+
+
+static void* ProcSeqNextMemoryRecords(struct seq_file *sfile,void* el,loff_t off)
+{
+ DEBUG_MEM_ALLOC_REC *psRecord;
+ psRecord = (DEBUG_MEM_ALLOC_REC*)
+ List_DEBUG_MEM_ALLOC_REC_Any_va(g_MemoryRecords,
+ DecOffMemAllocRec_AnyVaCb,
+ &off);
+#if defined(DEBUG_LINUX_XML_PROC_FILES)
+ if(!psRecord)
+ {
+ seq_printf( sfile, "</meminfo>\n");
+ }
+#endif
+
+ return (void*)psRecord;
+}
+
+static void* ProcSeqOff2ElementMemoryRecords(struct seq_file *sfile, loff_t off)
+{
+ DEBUG_MEM_ALLOC_REC *psRecord;
+ if(!off)
+ {
+ return PVR_PROC_SEQ_START_TOKEN;
+ }
+
+ psRecord = (DEBUG_MEM_ALLOC_REC*)
+ List_DEBUG_MEM_ALLOC_REC_Any_va(g_MemoryRecords,
+ DecOffMemAllocRec_AnyVaCb,
+ &off);
+
+#if defined(DEBUG_LINUX_XML_PROC_FILES)
+ if(!psRecord)
+ {
+ seq_printf( sfile, "</meminfo>\n");
+ }
+#endif
+
+ return (void*)psRecord;
+}
+
+static void ProcSeqShowMemoryRecords(struct seq_file *sfile,void* el)
+{
+ DEBUG_MEM_ALLOC_REC *psRecord = (DEBUG_MEM_ALLOC_REC*)el;
+ if(el == PVR_PROC_SEQ_START_TOKEN)
+ {
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+
+ seq_printf( sfile, "%-60s: %d bytes\n",
+ "Current Water Mark of bytes allocated via kmalloc",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
+ seq_printf( sfile, "%-60s: %d bytes\n",
+ "Highest Water Mark of bytes allocated via kmalloc",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
+ seq_printf( sfile, "%-60s: %d bytes\n",
+ "Current Water Mark of bytes allocated via vmalloc",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
+ seq_printf( sfile, "%-60s: %d bytes\n",
+ "Highest Water Mark of bytes allocated via vmalloc",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
+ seq_printf( sfile, "%-60s: %d bytes\n",
+ "Current Water Mark of bytes allocated via alloc_pages",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
+ seq_printf( sfile, "%-60s: %d bytes\n",
+ "Highest Water Mark of bytes allocated via alloc_pages",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
+ seq_printf( sfile, "%-60s: %d bytes\n",
+ "Current Water Mark of bytes allocated via ioremap",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
+ seq_printf( sfile, "%-60s: %d bytes\n",
+ "Highest Water Mark of bytes allocated via ioremap",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
+ seq_printf( sfile, "%-60s: %d bytes\n",
+ "Current Water Mark of bytes reserved for \"IO\" memory areas",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
+ seq_printf( sfile, "%-60s: %d bytes\n",
+ "Highest Water Mark of bytes allocated for \"IO\" memory areas",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
+ seq_printf( sfile, "%-60s: %d bytes\n",
+ "Current Water Mark of bytes allocated via kmem_cache_alloc",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
+ seq_printf( sfile, "%-60s: %d bytes\n",
+ "Highest Water Mark of bytes allocated via kmem_cache_alloc",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
+ seq_printf( sfile, "\n");
+
+ seq_printf( sfile, "%-60s: %d bytes\n",
+ "The Current Water Mark for memory allocated from system RAM",
+ g_SysRAMWaterMark);
+ seq_printf( sfile, "%-60s: %d bytes\n",
+ "The Highest Water Mark for memory allocated from system RAM",
+ g_SysRAMHighWaterMark);
+ seq_printf( sfile, "%-60s: %d bytes\n",
+ "The Current Water Mark for memory allocated from IO memory",
+ g_IOMemWaterMark);
+ seq_printf( sfile, "%-60s: %d bytes\n",
+ "The Highest Water Mark for memory allocated from IO memory",
+ g_IOMemHighWaterMark);
+
+ seq_printf( sfile, "\n");
+
+ seq_printf( sfile, "Details for all known allocations:\n"
+ "%-16s %-8s %-8s %-10s %-5s %-10s %s\n",
+ "Type",
+ "CpuVAddr",
+ "CpuPAddr",
+ "Bytes",
+ "PID",
+ "PrivateData",
+ "Filename:Line");
+
+#else
+
+
+ seq_printf( sfile, "<meminfo>\n<meminfo_header>\n");
+ seq_printf( sfile,
+ "<watermark key=\"mr0\" description=\"kmalloc_current\" bytes=\"%d\"/>\n",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
+ seq_printf( sfile,
+ "<watermark key=\"mr1\" description=\"kmalloc_high\" bytes=\"%d\"/>\n",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
+ seq_printf( sfile,
+ "<watermark key=\"mr2\" description=\"vmalloc_current\" bytes=\"%d\"/>\n",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
+ seq_printf( sfile,
+ "<watermark key=\"mr3\" description=\"vmalloc_high\" bytes=\"%d\"/>\n",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
+ seq_printf( sfile,
+ "<watermark key=\"mr4\" description=\"alloc_pages_current\" bytes=\"%d\"/>\n",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
+ seq_printf( sfile,
+ "<watermark key=\"mr5\" description=\"alloc_pages_high\" bytes=\"%d\"/>\n",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
+ seq_printf( sfile,
+ "<watermark key=\"mr6\" description=\"ioremap_current\" bytes=\"%d\"/>\n",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
+ seq_printf( sfile,
+ "<watermark key=\"mr7\" description=\"ioremap_high\" bytes=\"%d\"/>\n",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
+ seq_printf( sfile,
+ "<watermark key=\"mr8\" description=\"io_current\" bytes=\"%d\"/>\n",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
+ seq_printf( sfile,
+ "<watermark key=\"mr9\" description=\"io_high\" bytes=\"%d\"/>\n",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
+ seq_printf( sfile,
+ "<watermark key=\"mr10\" description=\"kmem_cache_current\" bytes=\"%d\"/>\n",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
+ seq_printf( sfile,
+ "<watermark key=\"mr11\" description=\"kmem_cache_high\" bytes=\"%d\"/>\n",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
+ seq_printf( sfile,"\n" );
+
+ seq_printf( sfile,
+ "<watermark key=\"mr14\" description=\"system_ram_current\" bytes=\"%d\"/>\n",
+ g_SysRAMWaterMark);
+ seq_printf( sfile,
+ "<watermark key=\"mr15\" description=\"system_ram_high\" bytes=\"%d\"/>\n",
+ g_SysRAMHighWaterMark);
+ seq_printf( sfile,
+ "<watermark key=\"mr16\" description=\"system_io_current\" bytes=\"%d\"/>\n",
+ g_IOMemWaterMark);
+ seq_printf( sfile,
+ "<watermark key=\"mr17\" description=\"system_io_high\" bytes=\"%d\"/>\n",
+ g_IOMemHighWaterMark);
+
+ seq_printf( sfile, "</meminfo_header>\n");
+
+#endif
+ return;
+ }
+
+ if(psRecord->eAllocType != DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE)
+ {
+ seq_printf( sfile,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+ "%-16s %-8p %08x %-10d %-5d %-10s %s:%d\n",
+#else
+ "<allocation>\n"
+ "\t<type>%s</type>\n"
+ "\t<cpu_virtual>%-8p</cpu_virtual>\n"
+ "\t<cpu_physical>%08x</cpu_physical>\n"
+ "\t<bytes>%d</bytes>\n"
+ "\t<pid>%d</pid>\n"
+ "\t<private>%s</private>\n"
+ "\t<filename>%s</filename>\n"
+ "\t<line>%d</line>\n"
+ "</allocation>\n",
+#endif
+ DebugMemAllocRecordTypeToString(psRecord->eAllocType),
+ psRecord->pvCpuVAddr,
+ psRecord->ulCpuPAddr,
+ psRecord->ui32Bytes,
+ psRecord->pid,
+ "NULL",
+ psRecord->pszFileName,
+ psRecord->ui32Line);
+ }
+ else
+ {
+ seq_printf( sfile,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+ "%-16s %-8p %08x %-10d %-5d %-10s %s:%d\n",
+#else
+ "<allocation>\n"
+ "\t<type>%s</type>\n"
+ "\t<cpu_virtual>%-8p</cpu_virtual>\n"
+ "\t<cpu_physical>%08x</cpu_physical>\n"
+ "\t<bytes>%d</bytes>\n"
+ "\t<pid>%d</pid>\n"
+ "\t<private>%s</private>\n"
+ "\t<filename>%s</filename>\n"
+ "\t<line>%d</line>\n"
+ "</allocation>\n",
+#endif
+ DebugMemAllocRecordTypeToString(psRecord->eAllocType),
+ psRecord->pvCpuVAddr,
+ psRecord->ulCpuPAddr,
+ psRecord->ui32Bytes,
+ psRecord->pid,
+ KMemCacheNameWrapper(psRecord->pvPrivateData),
+ psRecord->pszFileName,
+ psRecord->ui32Line);
+ }
+}
+
+#endif
+
+
+#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MMAP_AREAS)
+const IMG_CHAR *
+HAPFlagsToString(IMG_UINT32 ui32Flags)
+{
+ static IMG_CHAR szFlags[50];
+ IMG_INT32 i32Pos = 0;
+ IMG_UINT32 ui32CacheTypeIndex, ui32MapTypeIndex;
+ IMG_CHAR *apszCacheTypes[] = {
+ "UNCACHED",
+ "CACHED",
+ "WRITECOMBINE",
+ "UNKNOWN"
+ };
+ IMG_CHAR *apszMapType[] = {
+ "KERNEL_ONLY",
+ "SINGLE_PROCESS",
+ "MULTI_PROCESS",
+ "FROM_EXISTING_PROCESS",
+ "NO_CPU_VIRTUAL",
+ "UNKNOWN"
+ };
+
+
+ if(ui32Flags & PVRSRV_HAP_UNCACHED){
+ ui32CacheTypeIndex=0;
+ }else if(ui32Flags & PVRSRV_HAP_CACHED){
+ ui32CacheTypeIndex=1;
+ }else if(ui32Flags & PVRSRV_HAP_WRITECOMBINE){
+ ui32CacheTypeIndex=2;
+ }else{
+ ui32CacheTypeIndex=3;
+ PVR_DPF((PVR_DBG_ERROR, "%s: unknown cache type (%u)",
+ __FUNCTION__, (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)));
+ }
+
+
+ if(ui32Flags & PVRSRV_HAP_KERNEL_ONLY){
+ ui32MapTypeIndex = 0;
+ }else if(ui32Flags & PVRSRV_HAP_SINGLE_PROCESS){
+ ui32MapTypeIndex = 1;
+ }else if(ui32Flags & PVRSRV_HAP_MULTI_PROCESS){
+ ui32MapTypeIndex = 2;
+ }else if(ui32Flags & PVRSRV_HAP_FROM_EXISTING_PROCESS){
+ ui32MapTypeIndex = 3;
+ }else if(ui32Flags & PVRSRV_HAP_NO_CPU_VIRTUAL){
+ ui32MapTypeIndex = 4;
+ }else{
+ ui32MapTypeIndex = 5;
+ PVR_DPF((PVR_DBG_ERROR, "%s: unknown map type (%u)",
+ __FUNCTION__, (ui32Flags & PVRSRV_HAP_MAPTYPE_MASK)));
+ }
+
+ i32Pos = sprintf(szFlags, "%s|", apszCacheTypes[ui32CacheTypeIndex]);
+ if (i32Pos <= 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: sprintf for cache type %u failed (%d)",
+ __FUNCTION__, ui32CacheTypeIndex, i32Pos));
+ szFlags[0] = 0;
+ }
+ else
+ {
+ sprintf(szFlags + i32Pos, "%s", apszMapType[ui32MapTypeIndex]);
+ }
+
+ return szFlags;
+}
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef __IMG_LINUX_MM_H__
+#define __IMG_LINUX_MM_H__
+
+#include <linux/version.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/list.h>
+
+#include <asm/io.h>
+
+#define PHYS_TO_PFN(phys) ((phys) >> PAGE_SHIFT)
+#define PFN_TO_PHYS(pfn) ((pfn) << PAGE_SHIFT)
+
+#define RANGE_TO_PAGES(range) (((range) + (PAGE_SIZE - 1)) >> PAGE_SHIFT)
+
+#define ADDR_TO_PAGE_OFFSET(addr) (((unsigned long)(addr)) & (PAGE_SIZE - 1))
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10))
+#define REMAP_PFN_RANGE(vma, addr, pfn, size, prot) remap_pfn_range(vma, addr, pfn, size, prot)
+#else
+#define REMAP_PFN_RANGE(vma, addr, pfn, size, prot) remap_page_range(vma, addr, PFN_TO_PHYS(pfn), size, prot)
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12))
+#define IO_REMAP_PFN_RANGE(vma, addr, pfn, size, prot) io_remap_pfn_range(vma, addr, pfn, size, prot)
+#else
+#define IO_REMAP_PFN_RANGE(vma, addr, pfn, size, prot) io_remap_page_range(vma, addr, PFN_TO_PHYS(pfn), size, prot)
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+#define VM_INSERT_PAGE(vma, addr, page) vm_insert_page(vma, addr, page)
+#else
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10))
+#define VM_INSERT_PAGE(vma, addr, page) remap_pfn_range(vma, addr, page_to_pfn(page), PAGE_SIZE, vma->vm_page_prot);
+#else
+#define VM_INSERT_PAGE(vma, addr, page) remap_page_range(vma, addr, page_to_phys(page), PAGE_SIZE, vma->vm_page_prot);
+#endif
+#endif
+
+static inline IMG_UINT32 VMallocToPhys(IMG_VOID *pCpuVAddr)
+{
+ return (page_to_phys(vmalloc_to_page(pCpuVAddr)) + ADDR_TO_PAGE_OFFSET(pCpuVAddr));
+
+}
+
+typedef enum {
+ LINUX_MEM_AREA_IOREMAP,
+ LINUX_MEM_AREA_EXTERNAL_KV,
+ LINUX_MEM_AREA_IO,
+ LINUX_MEM_AREA_VMALLOC,
+ LINUX_MEM_AREA_ALLOC_PAGES,
+ LINUX_MEM_AREA_SUB_ALLOC,
+ LINUX_MEM_AREA_TYPE_COUNT
+}LINUX_MEM_AREA_TYPE;
+
+typedef struct _LinuxMemArea LinuxMemArea;
+
+
+struct _LinuxMemArea {
+ LINUX_MEM_AREA_TYPE eAreaType;
+ union _uData
+ {
+ struct _sIORemap
+ {
+
+ IMG_CPU_PHYADDR CPUPhysAddr;
+ IMG_VOID *pvIORemapCookie;
+ }sIORemap;
+ struct _sExternalKV
+ {
+
+ IMG_BOOL bPhysContig;
+ union {
+
+ IMG_SYS_PHYADDR SysPhysAddr;
+ IMG_SYS_PHYADDR *pSysPhysAddr;
+ } uPhysAddr;
+ IMG_VOID *pvExternalKV;
+ }sExternalKV;
+ struct _sIO
+ {
+
+ IMG_CPU_PHYADDR CPUPhysAddr;
+ }sIO;
+ struct _sVmalloc
+ {
+
+ IMG_VOID *pvVmallocAddress;
+ }sVmalloc;
+ struct _sPageList
+ {
+
+ struct page **pvPageList;
+ IMG_HANDLE hBlockPageList;
+ }sPageList;
+ struct _sSubAlloc
+ {
+
+ LinuxMemArea *psParentLinuxMemArea;
+ IMG_UINT32 ui32ByteOffset;
+ }sSubAlloc;
+ }uData;
+
+ IMG_UINT32 ui32ByteSize;
+
+ IMG_UINT32 ui32AreaFlags;
+
+ IMG_BOOL bMMapRegistered;
+
+ IMG_BOOL bNeedsCacheInvalidate;
+
+ struct list_head sMMapItem;
+
+
+ struct list_head sMMapOffsetStructList;
+};
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17))
+typedef kmem_cache_t LinuxKMemCache;
+#else
+typedef struct kmem_cache LinuxKMemCache;
+#endif
+
+
+PVRSRV_ERROR LinuxMMInit(IMG_VOID);
+
+
+IMG_VOID LinuxMMCleanup(IMG_VOID);
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define KMallocWrapper(ui32ByteSize) _KMallocWrapper(ui32ByteSize, __FILE__, __LINE__)
+#else
+#define KMallocWrapper(ui32ByteSize) _KMallocWrapper(ui32ByteSize, NULL, 0)
+#endif
+IMG_VOID *_KMallocWrapper(IMG_UINT32 ui32ByteSize, IMG_CHAR *szFileName, IMG_UINT32 ui32Line);
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define KFreeWrapper(pvCpuVAddr) _KFreeWrapper(pvCpuVAddr, __FILE__, __LINE__)
+#else
+#define KFreeWrapper(pvCpuVAddr) _KFreeWrapper(pvCpuVAddr, NULL, 0)
+#endif
+IMG_VOID _KFreeWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define VMallocWrapper(ui32Bytes, ui32AllocFlags) _VMallocWrapper(ui32Bytes, ui32AllocFlags, __FILE__, __LINE__)
+#else
+#define VMallocWrapper(ui32Bytes, ui32AllocFlags) _VMallocWrapper(ui32Bytes, ui32AllocFlags, NULL, 0)
+#endif
+IMG_VOID *_VMallocWrapper(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AllocFlags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define VFreeWrapper(pvCpuVAddr) _VFreeWrapper(pvCpuVAddr, __FILE__, __LINE__)
+#else
+#define VFreeWrapper(pvCpuVAddr) _VFreeWrapper(pvCpuVAddr, NULL, 0)
+#endif
+IMG_VOID _VFreeWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+
+
+LinuxMemArea *NewVMallocLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags);
+
+
+IMG_VOID FreeVMallocLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags) \
+ _IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags, __FILE__, __LINE__)
+#else
+#define IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags) \
+ _IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags, NULL, 0)
+#endif
+IMG_VOID *_IORemapWrapper(IMG_CPU_PHYADDR BasePAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32MappingFlags,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32Line);
+
+
+LinuxMemArea *NewIORemapLinuxMemArea(IMG_CPU_PHYADDR BasePAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags);
+
+
+IMG_VOID FreeIORemapLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+
+LinuxMemArea *NewExternalKVLinuxMemArea(IMG_SYS_PHYADDR *pBasePAddr, IMG_VOID *pvCPUVAddr, IMG_UINT32 ui32Bytes, IMG_BOOL bPhysContig, IMG_UINT32 ui32AreaFlags);
+
+
+IMG_VOID FreeExternalKVLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define IOUnmapWrapper(pvIORemapCookie) \
+ _IOUnmapWrapper(pvIORemapCookie, __FILE__, __LINE__)
+#else
+#define IOUnmapWrapper(pvIORemapCookie) \
+ _IOUnmapWrapper(pvIORemapCookie, NULL, 0)
+#endif
+IMG_VOID _IOUnmapWrapper(IMG_VOID *pvIORemapCookie, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+
+
+struct page *LinuxMemAreaOffsetToPage(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32ByteOffset);
+
+
+LinuxKMemCache *KMemCacheCreateWrapper(IMG_CHAR *pszName, size_t Size, size_t Align, IMG_UINT32 ui32Flags);
+
+
+IMG_VOID KMemCacheDestroyWrapper(LinuxKMemCache *psCache);
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define KMemCacheAllocWrapper(psCache, Flags) _KMemCacheAllocWrapper(psCache, Flags, __FILE__, __LINE__)
+#else
+#define KMemCacheAllocWrapper(psCache, Flags) _KMemCacheAllocWrapper(psCache, Flags, NULL, 0)
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14))
+IMG_VOID *_KMemCacheAllocWrapper(LinuxKMemCache *psCache, gfp_t Flags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+#else
+IMG_VOID *_KMemCacheAllocWrapper(LinuxKMemCache *psCache, int Flags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+#endif
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define KMemCacheFreeWrapper(psCache, pvObject) _KMemCacheFreeWrapper(psCache, pvObject, __FILE__, __LINE__)
+#else
+#define KMemCacheFreeWrapper(psCache, pvObject) _KMemCacheFreeWrapper(psCache, pvObject, NULL, 0)
+#endif
+IMG_VOID _KMemCacheFreeWrapper(LinuxKMemCache *psCache, IMG_VOID *pvObject, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+
+
+const IMG_CHAR *KMemCacheNameWrapper(LinuxKMemCache *psCache);
+
+
+LinuxMemArea *NewIOLinuxMemArea(IMG_CPU_PHYADDR BasePAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags);
+
+
+IMG_VOID FreeIOLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+
+
+LinuxMemArea *NewAllocPagesLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags);
+
+
+IMG_VOID FreeAllocPagesLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+
+
+LinuxMemArea *NewSubLinuxMemArea(LinuxMemArea *psParentLinuxMemArea,
+ IMG_UINT32 ui32ByteOffset,
+ IMG_UINT32 ui32Bytes);
+
+
+IMG_VOID LinuxMemAreaDeepFree(LinuxMemArea *psLinuxMemArea);
+
+
+#if defined(LINUX_MEM_AREAS_DEBUG)
+IMG_VOID LinuxMemAreaRegister(LinuxMemArea *psLinuxMemArea);
+#else
+#define LinuxMemAreaRegister(X)
+#endif
+
+
+IMG_VOID *LinuxMemAreaToCpuVAddr(LinuxMemArea *psLinuxMemArea);
+
+
+IMG_CPU_PHYADDR LinuxMemAreaToCpuPAddr(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32ByteOffset);
+
+
+#define LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32ByteOffset) PHYS_TO_PFN(LinuxMemAreaToCpuPAddr(psLinuxMemArea, ui32ByteOffset).uiAddr)
+
+IMG_BOOL LinuxMemAreaPhysIsContig(LinuxMemArea *psLinuxMemArea);
+
+static inline LinuxMemArea *
+LinuxMemAreaRoot(LinuxMemArea *psLinuxMemArea)
+{
+ if(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC)
+ {
+ return psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea;
+ }
+ else
+ {
+ return psLinuxMemArea;
+ }
+}
+
+
+static inline LINUX_MEM_AREA_TYPE
+LinuxMemAreaRootType(LinuxMemArea *psLinuxMemArea)
+{
+ return LinuxMemAreaRoot(psLinuxMemArea)->eAreaType;
+}
+
+
+const IMG_CHAR *LinuxMemAreaTypeToString(LINUX_MEM_AREA_TYPE eMemAreaType);
+
+
+#if defined(DEBUG) || defined(DEBUG_LINUX_MEM_AREAS)
+const IMG_CHAR *HAPFlagsToString(IMG_UINT32 ui32Flags);
+#endif
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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/version.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+#include <linux/wrapper.h>
+#endif
+#include <linux/slab.h>
+#include <asm/io.h>
+#include <asm/page.h>
+#include <asm/shmparam.h>
+#include <asm/pgtable.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22))
+#include <linux/sched.h>
+#include <asm/current.h>
+#endif
+#if defined(SUPPORT_DRI_DRM)
+#include <drm/drmP.h>
+#endif
+
+#include "img_defs.h"
+#include "services.h"
+#include "servicesint.h"
+#include "pvrmmap.h"
+#include "mutils.h"
+#include "mmap.h"
+#include "mm.h"
+#include "pvr_debug.h"
+#include "osfunc.h"
+#include "proc.h"
+#include "mutex.h"
+#include "handle.h"
+#include "perproc.h"
+#include "env_perproc.h"
+#include "bridged_support.h"
+#if defined(SUPPORT_DRI_DRM)
+#include "pvr_drm.h"
+#endif
+
+#if !defined(PVR_SECURE_HANDLES)
+#error "The mmap code requires PVR_SECURE_HANDLES"
+#endif
+
+static PVRSRV_LINUX_MUTEX g_sMMapMutex;
+
+static LinuxKMemCache *g_psMemmapCache = NULL;
+static LIST_HEAD(g_sMMapAreaList);
+static LIST_HEAD(g_sMMapOffsetStructList);
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+static IMG_UINT32 g_ui32RegisteredAreas = 0;
+static IMG_UINT32 g_ui32TotalByteSize = 0;
+#endif
+
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+static struct proc_dir_entry *g_ProcMMap;
+#endif
+
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+#define MMAP2_PGOFF_RESOLUTION (32-PAGE_SHIFT+12)
+#define RESERVED_PGOFF_BITS 1
+#define MAX_MMAP_HANDLE ((1UL<<(MMAP2_PGOFF_RESOLUTION-RESERVED_PGOFF_BITS))-1)
+
+#define FIRST_PHYSICAL_PFN 0
+#define LAST_PHYSICAL_PFN (FIRST_PHYSICAL_PFN + MAX_MMAP_HANDLE)
+#define FIRST_SPECIAL_PFN (LAST_PHYSICAL_PFN + 1)
+#define LAST_SPECIAL_PFN (FIRST_SPECIAL_PFN + MAX_MMAP_HANDLE)
+
+#else
+
+#if PAGE_SHIFT != 12
+#error This build variant has not yet been made non-4KB page-size aware
+#endif
+
+#if defined(PVR_MMAP_OFFSET_BASE)
+#define FIRST_SPECIAL_PFN PVR_MMAP_OFFSET_BASE
+#else
+#define FIRST_SPECIAL_PFN 0x80000000UL
+#endif
+
+#if defined(PVR_NUM_MMAP_HANDLES)
+#define MAX_MMAP_HANDLE PVR_NUM_MMAP_HANDLES
+#else
+#define MAX_MMAP_HANDLE 0x7fffffffUL
+#endif
+
+#endif
+
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+static inline IMG_BOOL
+PFNIsPhysical(IMG_UINT32 pfn)
+{
+
+ return ( (pfn <= LAST_PHYSICAL_PFN)) ? IMG_TRUE : IMG_FALSE;
+}
+
+static inline IMG_BOOL
+PFNIsSpecial(IMG_UINT32 pfn)
+{
+
+ return ((pfn >= FIRST_SPECIAL_PFN) ) ? IMG_TRUE : IMG_FALSE;
+}
+#endif
+
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+static inline IMG_HANDLE
+MMapOffsetToHandle(IMG_UINT32 pfn)
+{
+ if (PFNIsPhysical(pfn))
+ {
+ PVR_ASSERT(PFNIsPhysical(pfn));
+ return IMG_NULL;
+ }
+ return (IMG_HANDLE)(pfn - FIRST_SPECIAL_PFN);
+}
+#endif
+
+static inline IMG_UINT32
+HandleToMMapOffset(IMG_HANDLE hHandle)
+{
+ IMG_UINT32 ulHandle = (IMG_UINT32)hHandle;
+
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+ if (PFNIsSpecial(ulHandle))
+ {
+ PVR_ASSERT(PFNIsSpecial(ulHandle));
+ return 0;
+ }
+#endif
+ return ulHandle + FIRST_SPECIAL_PFN;
+}
+
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+static inline IMG_BOOL
+LinuxMemAreaUsesPhysicalMap(LinuxMemArea *psLinuxMemArea)
+{
+ return LinuxMemAreaPhysIsContig(psLinuxMemArea);
+}
+#endif
+
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+static inline IMG_UINT32
+GetCurrentThreadID(IMG_VOID)
+{
+
+ return (IMG_UINT32)current->pid;
+}
+#endif
+
+static PKV_OFFSET_STRUCT
+CreateOffsetStruct(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32Offset, IMG_UINT32 ui32RealByteSize)
+{
+ PKV_OFFSET_STRUCT psOffsetStruct;
+#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS)
+ const IMG_CHAR *pszName = LinuxMemAreaTypeToString(LinuxMemAreaRootType(psLinuxMemArea));
+#endif
+
+#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS)
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "%s(%s, psLinuxMemArea: 0x%p, ui32AllocFlags: 0x%8x)",
+ __FUNCTION__, pszName, psLinuxMemArea, psLinuxMemArea->ui32AreaFlags));
+#endif
+
+ PVR_ASSERT(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC || LinuxMemAreaRoot(psLinuxMemArea)->eAreaType != LINUX_MEM_AREA_SUB_ALLOC);
+
+ PVR_ASSERT(psLinuxMemArea->bMMapRegistered);
+
+ psOffsetStruct = KMemCacheAllocWrapper(g_psMemmapCache, GFP_KERNEL);
+ if(psOffsetStruct == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRMMapRegisterArea: Couldn't alloc another mapping record from cache"));
+ return IMG_NULL;
+ }
+
+ psOffsetStruct->ui32MMapOffset = ui32Offset;
+
+ psOffsetStruct->psLinuxMemArea = psLinuxMemArea;
+
+ psOffsetStruct->ui32RealByteSize = ui32RealByteSize;
+
+
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+ psOffsetStruct->ui32TID = GetCurrentThreadID();
+#endif
+ psOffsetStruct->ui32PID = OSGetCurrentProcessIDKM();
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+
+ psOffsetStruct->pszName = pszName;
+#endif
+
+ list_add_tail(&psOffsetStruct->sAreaItem, &psLinuxMemArea->sMMapOffsetStructList);
+
+ return psOffsetStruct;
+}
+
+
+static IMG_VOID
+DestroyOffsetStruct(PKV_OFFSET_STRUCT psOffsetStruct)
+{
+#ifdef DEBUG
+ IMG_CPU_PHYADDR CpuPAddr;
+ CpuPAddr = LinuxMemAreaToCpuPAddr(psOffsetStruct->psLinuxMemArea, 0);
+#endif
+
+ list_del(&psOffsetStruct->sAreaItem);
+
+ if (psOffsetStruct->bOnMMapList)
+ {
+ list_del(&psOffsetStruct->sMMapItem);
+ }
+
+#ifdef DEBUG
+ PVR_DPF((PVR_DBG_MESSAGE, "%s: Table entry: "
+ "psLinuxMemArea=%p, CpuPAddr=0x%08X", __FUNCTION__,
+ psOffsetStruct->psLinuxMemArea,
+ CpuPAddr.uiAddr));
+#endif
+
+ KMemCacheFreeWrapper(g_psMemmapCache, psOffsetStruct);
+}
+
+
+static inline IMG_VOID
+DetermineUsersSizeAndByteOffset(LinuxMemArea *psLinuxMemArea,
+ IMG_UINT32 *pui32RealByteSize,
+ IMG_UINT32 *pui32ByteOffset)
+{
+ IMG_UINT32 ui32PageAlignmentOffset;
+ IMG_CPU_PHYADDR CpuPAddr;
+
+ CpuPAddr = LinuxMemAreaToCpuPAddr(psLinuxMemArea, 0);
+ ui32PageAlignmentOffset = ADDR_TO_PAGE_OFFSET(CpuPAddr.uiAddr);
+
+ *pui32ByteOffset = ui32PageAlignmentOffset;
+
+ *pui32RealByteSize = PAGE_ALIGN(psLinuxMemArea->ui32ByteSize + ui32PageAlignmentOffset);
+}
+
+
+PVRSRV_ERROR
+PVRMMapOSMemHandleToMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hMHandle,
+ IMG_UINT32 *pui32MMapOffset,
+ IMG_UINT32 *pui32ByteOffset,
+ IMG_UINT32 *pui32RealByteSize,
+ IMG_UINT32 *pui32UserVAddr)
+{
+ LinuxMemArea *psLinuxMemArea;
+ PKV_OFFSET_STRUCT psOffsetStruct;
+ IMG_HANDLE hOSMemHandle;
+ PVRSRV_ERROR eError;
+
+ LinuxLockMutex(&g_sMMapMutex);
+
+ PVR_ASSERT(PVRSRVGetMaxHandle(psPerProc->psHandleBase) <= MAX_MMAP_HANDLE);
+
+ eError = PVRSRVLookupOSMemHandle(psPerProc->psHandleBase, &hOSMemHandle, hMHandle);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Lookup of handle %p failed", __FUNCTION__, hMHandle));
+
+ goto exit_unlock;
+ }
+
+ psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+ DetermineUsersSizeAndByteOffset(psLinuxMemArea,
+ pui32RealByteSize,
+ pui32ByteOffset);
+
+
+ list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
+ {
+ if (psPerProc->ui32PID == psOffsetStruct->ui32PID)
+ {
+
+ PVR_ASSERT(*pui32RealByteSize == psOffsetStruct->ui32RealByteSize);
+
+ *pui32MMapOffset = psOffsetStruct->ui32MMapOffset;
+ *pui32UserVAddr = psOffsetStruct->ui32UserVAddr;
+ psOffsetStruct->ui32RefCount++;
+
+ eError = PVRSRV_OK;
+ goto exit_unlock;
+ }
+ }
+
+
+ *pui32UserVAddr = 0;
+
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+ if (LinuxMemAreaUsesPhysicalMap(psLinuxMemArea))
+ {
+ *pui32MMapOffset = LinuxMemAreaToCpuPFN(psLinuxMemArea, 0);
+ PVR_ASSERT(PFNIsPhysical(*pui32MMapOffset));
+ }
+ else
+#endif
+ {
+ *pui32MMapOffset = HandleToMMapOffset(hMHandle);
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+ PVR_ASSERT(PFNIsSpecial(*pui32MMapOffset));
+#endif
+ }
+
+ psOffsetStruct = CreateOffsetStruct(psLinuxMemArea, *pui32MMapOffset, *pui32RealByteSize);
+ if (psOffsetStruct == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto exit_unlock;
+ }
+
+
+ list_add_tail(&psOffsetStruct->sMMapItem, &g_sMMapOffsetStructList);
+
+ psOffsetStruct->bOnMMapList = IMG_TRUE;
+
+ psOffsetStruct->ui32RefCount++;
+
+ eError = PVRSRV_OK;
+
+
+
+
+ *pui32MMapOffset = *pui32MMapOffset << (PAGE_SHIFT - 12);
+
+exit_unlock:
+ LinuxUnLockMutex(&g_sMMapMutex);
+
+ return eError;
+}
+
+
+PVRSRV_ERROR
+PVRMMapReleaseMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hMHandle,
+ IMG_BOOL *pbMUnmap,
+ IMG_UINT32 *pui32RealByteSize,
+ IMG_UINT32 *pui32UserVAddr)
+{
+ LinuxMemArea *psLinuxMemArea;
+ PKV_OFFSET_STRUCT psOffsetStruct;
+ IMG_HANDLE hOSMemHandle;
+ PVRSRV_ERROR eError;
+ IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+
+ LinuxLockMutex(&g_sMMapMutex);
+
+ PVR_ASSERT(PVRSRVGetMaxHandle(psPerProc->psHandleBase) <= MAX_MMAP_HANDLE);
+
+ eError = PVRSRVLookupOSMemHandle(psPerProc->psHandleBase, &hOSMemHandle, hMHandle);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Lookup of handle %p failed", __FUNCTION__, hMHandle));
+
+ goto exit_unlock;
+ }
+
+ psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+
+ list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
+ {
+ if (psOffsetStruct->ui32PID == ui32PID)
+ {
+ if (psOffsetStruct->ui32RefCount == 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Attempt to release mmap data with zero reference count for offset struct 0x%p, memory area %p", __FUNCTION__, psOffsetStruct, psLinuxMemArea));
+ eError = PVRSRV_ERROR_STILL_MAPPED;
+ goto exit_unlock;
+ }
+
+ psOffsetStruct->ui32RefCount--;
+
+ *pbMUnmap = (IMG_BOOL)((psOffsetStruct->ui32RefCount == 0) && (psOffsetStruct->ui32UserVAddr != 0));
+
+ *pui32UserVAddr = (*pbMUnmap) ? psOffsetStruct->ui32UserVAddr : 0;
+ *pui32RealByteSize = (*pbMUnmap) ? psOffsetStruct->ui32RealByteSize : 0;
+
+ eError = PVRSRV_OK;
+ goto exit_unlock;
+ }
+ }
+
+
+ PVR_DPF((PVR_DBG_ERROR, "%s: Mapping data not found for handle %p (memory area %p)", __FUNCTION__, hMHandle, psLinuxMemArea));
+
+ eError = PVRSRV_ERROR_MAPPING_NOT_FOUND;
+
+exit_unlock:
+ LinuxUnLockMutex(&g_sMMapMutex);
+
+ return eError;
+}
+
+static inline PKV_OFFSET_STRUCT
+FindOffsetStructByOffset(IMG_UINT32 ui32Offset, IMG_UINT32 ui32RealByteSize)
+{
+ PKV_OFFSET_STRUCT psOffsetStruct;
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+ IMG_UINT32 ui32TID = GetCurrentThreadID();
+#endif
+ IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+
+ list_for_each_entry(psOffsetStruct, &g_sMMapOffsetStructList, sMMapItem)
+ {
+ if (ui32Offset == psOffsetStruct->ui32MMapOffset && ui32RealByteSize == psOffsetStruct->ui32RealByteSize && psOffsetStruct->ui32PID == ui32PID)
+ {
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+
+ if (!PFNIsPhysical(ui32Offset) || psOffsetStruct->ui32TID == ui32TID)
+#endif
+ {
+ return psOffsetStruct;
+ }
+ }
+ }
+
+ return IMG_NULL;
+}
+
+
+static IMG_BOOL
+DoMapToUser(LinuxMemArea *psLinuxMemArea,
+ struct vm_area_struct* ps_vma,
+ IMG_UINT32 ui32ByteOffset)
+{
+ IMG_UINT32 ui32ByteSize;
+
+ if (psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC)
+ {
+ return DoMapToUser(LinuxMemAreaRoot(psLinuxMemArea),
+ ps_vma,
+ psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset + ui32ByteOffset);
+ }
+
+
+ ui32ByteSize = ps_vma->vm_end - ps_vma->vm_start;
+ PVR_ASSERT(ADDR_TO_PAGE_OFFSET(ui32ByteSize) == 0);
+
+#if defined (__sparc__)
+
+#error "SPARC not supported"
+#endif
+
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+ if (PFNIsPhysical(ps_vma->vm_pgoff))
+ {
+ IMG_INT result;
+
+ PVR_ASSERT(LinuxMemAreaPhysIsContig(psLinuxMemArea));
+ PVR_ASSERT(LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32ByteOffset) == ps_vma->vm_pgoff);
+
+ result = IO_REMAP_PFN_RANGE(ps_vma, ps_vma->vm_start, ps_vma->vm_pgoff, ui32ByteSize, ps_vma->vm_page_prot);
+
+ if(result == 0)
+ {
+ return IMG_TRUE;
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE, "%s: Failed to map contiguous physical address range (%d), trying non-contiguous path", __FUNCTION__, result));
+ }
+#endif
+
+ {
+
+ IMG_UINT32 ulVMAPos;
+ IMG_UINT32 ui32ByteEnd = ui32ByteOffset + ui32ByteSize;
+ IMG_UINT32 ui32PA;
+#if defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+ IMG_BOOL bMixedMap = IMG_FALSE;
+#endif
+
+ for(ui32PA = ui32ByteOffset; ui32PA < ui32ByteEnd; ui32PA += PAGE_SIZE)
+ {
+ IMG_UINT32 pfn = LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32PA);
+
+ if (!pfn_valid(pfn))
+ {
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+ PVR_DPF((PVR_DBG_ERROR,"%s: Error - PFN invalid: 0x%x", __FUNCTION__, pfn));
+ return IMG_FALSE;
+#else
+ bMixedMap = IMG_TRUE;
+#endif
+ }
+ }
+
+#if defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+ if (bMixedMap)
+ {
+ ps_vma->vm_flags |= VM_MIXEDMAP;
+ }
+#endif
+
+ ulVMAPos = ps_vma->vm_start;
+ for(ui32PA = ui32ByteOffset; ui32PA < ui32ByteEnd; ui32PA += PAGE_SIZE)
+ {
+ IMG_UINT32 pfn;
+ IMG_INT result;
+
+ pfn = LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32PA);
+
+#if defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+ if (bMixedMap)
+ {
+ result = vm_insert_mixed(ps_vma, ulVMAPos, pfn);
+ if(result != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: Error - vm_insert_mixed failed (%d)", __FUNCTION__, result));
+ return IMG_FALSE;
+ }
+ }
+ else
+#endif
+ {
+ struct page *psPage;
+
+ PVR_ASSERT(pfn_valid(pfn));
+
+ psPage = pfn_to_page(pfn);
+
+ result = VM_INSERT_PAGE(ps_vma, ulVMAPos, psPage);
+ if(result != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: Error - VM_INSERT_PAGE failed (%d)", __FUNCTION__, result));
+ return IMG_FALSE;
+ }
+ }
+ ulVMAPos += PAGE_SIZE;
+ }
+ }
+
+ return IMG_TRUE;
+}
+
+
+static IMG_VOID
+MMapVOpenNoLock(struct vm_area_struct* ps_vma)
+{
+ PKV_OFFSET_STRUCT psOffsetStruct = (PKV_OFFSET_STRUCT)ps_vma->vm_private_data;
+ PVR_ASSERT(psOffsetStruct != IMG_NULL)
+ psOffsetStruct->ui32Mapped++;
+ PVR_ASSERT(!psOffsetStruct->bOnMMapList);
+
+ if (psOffsetStruct->ui32Mapped > 1)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "%s: Offset structure 0x%p is being shared across processes (psOffsetStruct->ui32Mapped: %u)", __FUNCTION__, psOffsetStruct, psOffsetStruct->ui32Mapped));
+ PVR_ASSERT((ps_vma->vm_flags & VM_DONTCOPY) == 0);
+ }
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "%s: psLinuxMemArea 0x%p, KVAddress 0x%p MMapOffset %d, ui32Mapped %d",
+ __FUNCTION__,
+ psOffsetStruct->psLinuxMemArea,
+ LinuxMemAreaToCpuVAddr(psOffsetStruct->psLinuxMemArea),
+ psOffsetStruct->ui32MMapOffset,
+ psOffsetStruct->ui32Mapped));
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+ MOD_INC_USE_COUNT;
+#endif
+}
+
+
+static void
+MMapVOpen(struct vm_area_struct* ps_vma)
+{
+ LinuxLockMutex(&g_sMMapMutex);
+
+ MMapVOpenNoLock(ps_vma);
+
+ LinuxUnLockMutex(&g_sMMapMutex);
+}
+
+
+static IMG_VOID
+MMapVCloseNoLock(struct vm_area_struct* ps_vma)
+{
+ PKV_OFFSET_STRUCT psOffsetStruct = (PKV_OFFSET_STRUCT)ps_vma->vm_private_data;
+ PVR_ASSERT(psOffsetStruct != IMG_NULL)
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "%s: psLinuxMemArea %p, CpuVAddr %p ui32MMapOffset %d, ui32Mapped %d",
+ __FUNCTION__,
+ psOffsetStruct->psLinuxMemArea,
+ LinuxMemAreaToCpuVAddr(psOffsetStruct->psLinuxMemArea),
+ psOffsetStruct->ui32MMapOffset,
+ psOffsetStruct->ui32Mapped));
+#endif
+
+ PVR_ASSERT(!psOffsetStruct->bOnMMapList);
+ psOffsetStruct->ui32Mapped--;
+ if (psOffsetStruct->ui32Mapped == 0)
+ {
+ if (psOffsetStruct->ui32RefCount != 0)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "%s: psOffsetStruct %p has non-zero reference count (ui32RefCount = %u). User mode address of start of mapping: 0x%x", __FUNCTION__, psOffsetStruct, psOffsetStruct->ui32RefCount, psOffsetStruct->ui32UserVAddr));
+ }
+
+ DestroyOffsetStruct(psOffsetStruct);
+ }
+
+ ps_vma->vm_private_data = NULL;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+ MOD_DEC_USE_COUNT;
+#endif
+}
+
+static void
+MMapVClose(struct vm_area_struct* ps_vma)
+{
+ LinuxLockMutex(&g_sMMapMutex);
+
+ MMapVCloseNoLock(ps_vma);
+
+ LinuxUnLockMutex(&g_sMMapMutex);
+}
+
+
+static struct vm_operations_struct MMapIOOps =
+{
+ .open=MMapVOpen,
+ .close=MMapVClose
+};
+
+
+int
+PVRMMap(struct file* pFile, struct vm_area_struct* ps_vma)
+{
+ IMG_UINT32 ui32ByteSize;
+ PKV_OFFSET_STRUCT psOffsetStruct;
+ int iRetVal = 0;
+
+ PVR_UNREFERENCED_PARAMETER(pFile);
+
+ LinuxLockMutex(&g_sMMapMutex);
+
+ ui32ByteSize = ps_vma->vm_end - ps_vma->vm_start;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "%s: Received mmap(2) request with ui32MMapOffset 0x%08lx,"
+ " and ui32ByteSize %d(0x%08x)",
+ __FUNCTION__,
+ ps_vma->vm_pgoff,
+ ui32ByteSize, ui32ByteSize));
+
+ psOffsetStruct = FindOffsetStructByOffset(ps_vma->vm_pgoff, ui32ByteSize);
+ if (psOffsetStruct == IMG_NULL)
+ {
+#if defined(SUPPORT_DRI_DRM)
+ LinuxUnLockMutex(&g_sMMapMutex);
+
+#if !defined(SUPPORT_DRI_DRM_EXT)
+
+ return drm_mmap(pFile, ps_vma);
+#else
+
+ return -ENOENT;
+#endif
+#else
+ PVR_UNREFERENCED_PARAMETER(pFile);
+
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: Attempted to mmap unregistered area at vm_pgoff 0x%lx",
+ __FUNCTION__, ps_vma->vm_pgoff));
+ iRetVal = -EINVAL;
+#endif
+ goto unlock_and_return;
+ }
+ list_del(&psOffsetStruct->sMMapItem);
+ psOffsetStruct->bOnMMapList = IMG_FALSE;
+
+
+ if (((ps_vma->vm_flags & VM_WRITE) != 0) &&
+ ((ps_vma->vm_flags & VM_SHARED) == 0))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Cannot mmap non-shareable writable areas", __FUNCTION__));
+ iRetVal = -EINVAL;
+ goto unlock_and_return;
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE, "%s: Mapped psLinuxMemArea 0x%p\n",
+ __FUNCTION__, psOffsetStruct->psLinuxMemArea));
+
+ ps_vma->vm_flags |= VM_RESERVED;
+ ps_vma->vm_flags |= VM_IO;
+
+
+ ps_vma->vm_flags |= VM_DONTEXPAND;
+
+
+ ps_vma->vm_flags |= VM_DONTCOPY;
+
+ ps_vma->vm_private_data = (void *)psOffsetStruct;
+
+ switch(psOffsetStruct->psLinuxMemArea->ui32AreaFlags & PVRSRV_HAP_CACHETYPE_MASK)
+ {
+ case PVRSRV_HAP_CACHED:
+
+ break;
+ case PVRSRV_HAP_WRITECOMBINE:
+ ps_vma->vm_page_prot = PGPROT_WC(ps_vma->vm_page_prot);
+ break;
+ case PVRSRV_HAP_UNCACHED:
+ ps_vma->vm_page_prot = PGPROT_UC(ps_vma->vm_page_prot);
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "%s: unknown cache type", __FUNCTION__));
+ iRetVal = -EINVAL;
+ goto unlock_and_return;
+ }
+
+
+ ps_vma->vm_ops = &MMapIOOps;
+
+ if(!DoMapToUser(psOffsetStruct->psLinuxMemArea, ps_vma, 0))
+ {
+ iRetVal = -EAGAIN;
+ goto unlock_and_return;
+ }
+
+ PVR_ASSERT(psOffsetStruct->ui32UserVAddr == 0)
+
+ psOffsetStruct->ui32UserVAddr = ps_vma->vm_start;
+
+
+ if(psOffsetStruct->psLinuxMemArea->bNeedsCacheInvalidate)
+ {
+ IMG_UINT32 ui32RealByteSize, ui32ByteOffset;
+ IMG_VOID *pvBase;
+
+ DetermineUsersSizeAndByteOffset(psOffsetStruct->psLinuxMemArea,
+ &ui32RealByteSize,
+ &ui32ByteOffset);
+
+ ui32RealByteSize = psOffsetStruct->psLinuxMemArea->ui32ByteSize;
+ pvBase = (IMG_VOID *)ps_vma->vm_start + ui32ByteOffset;
+
+ OSInvalidateCPUCacheRangeKM(psOffsetStruct->psLinuxMemArea,
+ pvBase, ui32RealByteSize);
+ psOffsetStruct->psLinuxMemArea->bNeedsCacheInvalidate = IMG_FALSE;
+ }
+
+
+ MMapVOpenNoLock(ps_vma);
+
+ PVR_DPF((PVR_DBG_MESSAGE, "%s: Mapped area at offset 0x%08lx\n",
+ __FUNCTION__, ps_vma->vm_pgoff));
+
+unlock_and_return:
+ if (iRetVal != 0 && psOffsetStruct != IMG_NULL)
+ {
+ DestroyOffsetStruct(psOffsetStruct);
+ }
+
+ LinuxUnLockMutex(&g_sMMapMutex);
+
+ return iRetVal;
+}
+
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+
+static void ProcSeqStartstopMMapRegistations(struct seq_file *sfile,IMG_BOOL start)
+{
+ if(start)
+ {
+ LinuxLockMutex(&g_sMMapMutex);
+ }
+ else
+ {
+ LinuxUnLockMutex(&g_sMMapMutex);
+ }
+}
+
+
+static void* ProcSeqOff2ElementMMapRegistrations(struct seq_file *sfile, loff_t off)
+{
+ LinuxMemArea *psLinuxMemArea;
+ if(!off)
+ {
+ return PVR_PROC_SEQ_START_TOKEN;
+ }
+
+ list_for_each_entry(psLinuxMemArea, &g_sMMapAreaList, sMMapItem)
+ {
+ PKV_OFFSET_STRUCT psOffsetStruct;
+
+ list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
+ {
+ off--;
+ if (off == 0)
+ {
+ PVR_ASSERT(psOffsetStruct->psLinuxMemArea == psLinuxMemArea);
+ return (void*)psOffsetStruct;
+ }
+ }
+ }
+ return (void*)0;
+}
+
+static void* ProcSeqNextMMapRegistrations(struct seq_file *sfile,void* el,loff_t off)
+{
+ return ProcSeqOff2ElementMMapRegistrations(sfile,off);
+}
+
+
+static void ProcSeqShowMMapRegistrations(struct seq_file *sfile, void *el)
+{
+ KV_OFFSET_STRUCT *psOffsetStruct = (KV_OFFSET_STRUCT*)el;
+ LinuxMemArea *psLinuxMemArea;
+ IMG_UINT32 ui32RealByteSize;
+ IMG_UINT32 ui32ByteOffset;
+
+ if(el == PVR_PROC_SEQ_START_TOKEN)
+ {
+ seq_printf( sfile,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+ "Allocations registered for mmap: %u\n"
+ "In total these areas correspond to %u bytes\n"
+ "psLinuxMemArea "
+ "UserVAddr "
+ "KernelVAddr "
+ "CpuPAddr "
+ "MMapOffset "
+ "ByteLength "
+ "LinuxMemType "
+ "Pid Name Flags\n",
+#else
+ "<mmap_header>\n"
+ "\t<count>%u</count>\n"
+ "\t<bytes>%u</bytes>\n"
+ "</mmap_header>\n",
+#endif
+ g_ui32RegisteredAreas,
+ g_ui32TotalByteSize
+ );
+ return;
+ }
+
+ psLinuxMemArea = psOffsetStruct->psLinuxMemArea;
+
+ DetermineUsersSizeAndByteOffset(psLinuxMemArea,
+ &ui32RealByteSize,
+ &ui32ByteOffset);
+
+ seq_printf( sfile,
+#if !defined(DEBUG_LINUX_XML_PROC_FILES)
+ "%-8p %08x %-8p %08x %08x %-8d %-24s %-5u %-8s %08x(%s)\n",
+#else
+ "<mmap_record>\n"
+ "\t<pointer>%-8p</pointer>\n"
+ "\t<user_virtual>%-8x</user_virtual>\n"
+ "\t<kernel_virtual>%-8p</kernel_virtual>\n"
+ "\t<cpu_physical>%08x</cpu_physical>\n"
+ "\t<mmap_offset>%08x</mmap_offset>\n"
+ "\t<bytes>%-8d</bytes>\n"
+ "\t<linux_mem_area_type>%-24s</linux_mem_area_type>\n"
+ "\t<pid>%-5u</pid>\n"
+ "\t<name>%-8s</name>\n"
+ "\t<flags>%08x</flags>\n"
+ "\t<flags_string>%s</flags_string>\n"
+ "</mmap_record>\n",
+#endif
+ psLinuxMemArea,
+ psOffsetStruct->ui32UserVAddr + ui32ByteOffset,
+ LinuxMemAreaToCpuVAddr(psLinuxMemArea),
+ LinuxMemAreaToCpuPAddr(psLinuxMemArea,0).uiAddr,
+ psOffsetStruct->ui32MMapOffset,
+ psLinuxMemArea->ui32ByteSize,
+ LinuxMemAreaTypeToString(psLinuxMemArea->eAreaType),
+ psOffsetStruct->ui32PID,
+ psOffsetStruct->pszName,
+ psLinuxMemArea->ui32AreaFlags,
+ HAPFlagsToString(psLinuxMemArea->ui32AreaFlags));
+}
+
+#endif
+
+
+PVRSRV_ERROR
+PVRMMapRegisterArea(LinuxMemArea *psLinuxMemArea)
+{
+ PVRSRV_ERROR eError;
+#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS)
+ const IMG_CHAR *pszName = LinuxMemAreaTypeToString(LinuxMemAreaRootType(psLinuxMemArea));
+#endif
+
+ LinuxLockMutex(&g_sMMapMutex);
+
+#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS)
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "%s(%s, psLinuxMemArea 0x%p, ui32AllocFlags 0x%8x)",
+ __FUNCTION__, pszName, psLinuxMemArea, psLinuxMemArea->ui32AreaFlags));
+#endif
+
+ PVR_ASSERT(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC || LinuxMemAreaRoot(psLinuxMemArea)->eAreaType != LINUX_MEM_AREA_SUB_ALLOC);
+
+
+ if(psLinuxMemArea->bMMapRegistered)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: psLinuxMemArea 0x%p is already registered",
+ __FUNCTION__, psLinuxMemArea));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto exit_unlock;
+ }
+
+ list_add_tail(&psLinuxMemArea->sMMapItem, &g_sMMapAreaList);
+
+ psLinuxMemArea->bMMapRegistered = IMG_TRUE;
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+ g_ui32RegisteredAreas++;
+
+ if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
+ {
+ g_ui32TotalByteSize += psLinuxMemArea->ui32ByteSize;
+ }
+#endif
+
+ eError = PVRSRV_OK;
+
+exit_unlock:
+ LinuxUnLockMutex(&g_sMMapMutex);
+
+ return eError;
+}
+
+
+PVRSRV_ERROR
+PVRMMapRemoveRegisteredArea(LinuxMemArea *psLinuxMemArea)
+{
+ PVRSRV_ERROR eError;
+ PKV_OFFSET_STRUCT psOffsetStruct, psTmpOffsetStruct;
+
+ LinuxLockMutex(&g_sMMapMutex);
+
+ PVR_ASSERT(psLinuxMemArea->bMMapRegistered);
+
+ list_for_each_entry_safe(psOffsetStruct, psTmpOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
+ {
+ if (psOffsetStruct->ui32Mapped != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: psOffsetStruct 0x%p for memory area 0x0x%p is still mapped; psOffsetStruct->ui32Mapped %u", __FUNCTION__, psOffsetStruct, psLinuxMemArea, psOffsetStruct->ui32Mapped));
+ eError = PVRSRV_ERROR_STILL_MAPPED;
+ goto exit_unlock;
+ }
+ else
+ {
+
+ PVR_DPF((PVR_DBG_WARNING, "%s: psOffsetStruct 0x%p was never mapped", __FUNCTION__, psOffsetStruct));
+ }
+
+ PVR_ASSERT((psOffsetStruct->ui32Mapped == 0) && psOffsetStruct->bOnMMapList);
+
+ DestroyOffsetStruct(psOffsetStruct);
+ }
+
+ list_del(&psLinuxMemArea->sMMapItem);
+
+ psLinuxMemArea->bMMapRegistered = IMG_FALSE;
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+ g_ui32RegisteredAreas--;
+ if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
+ {
+ g_ui32TotalByteSize -= psLinuxMemArea->ui32ByteSize;
+ }
+#endif
+
+ eError = PVRSRV_OK;
+
+exit_unlock:
+ LinuxUnLockMutex(&g_sMMapMutex);
+ return eError;
+}
+
+
+PVRSRV_ERROR
+LinuxMMapPerProcessConnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc)
+{
+ PVR_UNREFERENCED_PARAMETER(psEnvPerProc);
+
+ return PVRSRV_OK;
+}
+
+IMG_VOID
+LinuxMMapPerProcessDisconnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc)
+{
+ PKV_OFFSET_STRUCT psOffsetStruct, psTmpOffsetStruct;
+ IMG_BOOL bWarn = IMG_FALSE;
+ IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+
+ PVR_UNREFERENCED_PARAMETER(psEnvPerProc);
+
+ LinuxLockMutex(&g_sMMapMutex);
+
+ list_for_each_entry_safe(psOffsetStruct, psTmpOffsetStruct, &g_sMMapOffsetStructList, sMMapItem)
+ {
+ if (psOffsetStruct->ui32PID == ui32PID)
+ {
+ if (!bWarn)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "%s: process has unmapped offset structures. Removing them", __FUNCTION__));
+ bWarn = IMG_TRUE;
+ }
+ PVR_ASSERT(psOffsetStruct->ui32Mapped == 0);
+ PVR_ASSERT(psOffsetStruct->bOnMMapList);
+
+ DestroyOffsetStruct(psOffsetStruct);
+ }
+ }
+
+ LinuxUnLockMutex(&g_sMMapMutex);
+}
+
+
+PVRSRV_ERROR LinuxMMapPerProcessHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase)
+{
+ PVRSRV_ERROR eError;
+
+ eError = PVRSRVSetMaxHandle(psHandleBase, MAX_MMAP_HANDLE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: failed to set handle limit (%d)", __FUNCTION__, eError));
+ return eError;
+ }
+
+ return eError;
+}
+
+
+IMG_VOID
+PVRMMapInit(IMG_VOID)
+{
+ LinuxInitMutex(&g_sMMapMutex);
+
+ g_psMemmapCache = KMemCacheCreateWrapper("img-mmap", sizeof(KV_OFFSET_STRUCT), 0, 0);
+ if (!g_psMemmapCache)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: failed to allocate kmem_cache", __FUNCTION__));
+ goto error;
+ }
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+ g_ProcMMap = CreateProcReadEntrySeq("mmap", NULL,
+ ProcSeqNextMMapRegistrations,
+ ProcSeqShowMMapRegistrations,
+ ProcSeqOff2ElementMMapRegistrations,
+ ProcSeqStartstopMMapRegistations
+ );
+#endif
+ return;
+
+error:
+ PVRMMapCleanup();
+ return;
+}
+
+
+IMG_VOID
+PVRMMapCleanup(IMG_VOID)
+{
+ PVRSRV_ERROR eError;
+
+ if (!list_empty(&g_sMMapAreaList))
+ {
+ LinuxMemArea *psLinuxMemArea, *psTmpMemArea;
+
+ PVR_DPF((PVR_DBG_ERROR, "%s: Memory areas are still registered with MMap", __FUNCTION__));
+
+ PVR_TRACE(("%s: Unregistering memory areas", __FUNCTION__));
+ list_for_each_entry_safe(psLinuxMemArea, psTmpMemArea, &g_sMMapAreaList, sMMapItem)
+ {
+ eError = PVRMMapRemoveRegisteredArea(psLinuxMemArea);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: PVRMMapRemoveRegisteredArea failed (%d)", __FUNCTION__, eError));
+ }
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ LinuxMemAreaDeepFree(psLinuxMemArea);
+ }
+ }
+ PVR_ASSERT(list_empty((&g_sMMapAreaList)));
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+ RemoveProcEntrySeq(g_ProcMMap);
+#endif
+
+ if(g_psMemmapCache)
+ {
+ KMemCacheDestroyWrapper(g_psMemmapCache);
+ g_psMemmapCache = NULL;
+ }
+}
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#if !defined(__MMAP_H__)
+#define __MMAP_H__
+
+#include <linux/mm.h>
+#include <linux/list.h>
+
+#if defined(VM_MIXEDMAP)
+#define PVR_MAKE_ALL_PFNS_SPECIAL
+#endif
+
+#include "perproc.h"
+#include "mm.h"
+
+typedef struct KV_OFFSET_STRUCT_TAG
+{
+
+ IMG_UINT32 ui32Mapped;
+
+
+ IMG_UINT32 ui32MMapOffset;
+
+ IMG_UINT32 ui32RealByteSize;
+
+
+ LinuxMemArea *psLinuxMemArea;
+
+#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+
+ IMG_UINT32 ui32TID;
+#endif
+
+
+ IMG_UINT32 ui32PID;
+
+
+ IMG_BOOL bOnMMapList;
+
+
+ IMG_UINT32 ui32RefCount;
+
+
+ IMG_UINT32 ui32UserVAddr;
+
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+ const IMG_CHAR *pszName;
+#endif
+
+
+ struct list_head sMMapItem;
+
+
+ struct list_head sAreaItem;
+}KV_OFFSET_STRUCT, *PKV_OFFSET_STRUCT;
+
+
+
+IMG_VOID PVRMMapInit(IMG_VOID);
+
+
+IMG_VOID PVRMMapCleanup(IMG_VOID);
+
+
+PVRSRV_ERROR PVRMMapRegisterArea(LinuxMemArea *psLinuxMemArea);
+
+
+PVRSRV_ERROR PVRMMapRemoveRegisteredArea(LinuxMemArea *psLinuxMemArea);
+
+
+PVRSRV_ERROR PVRMMapOSMemHandleToMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hMHandle,
+ IMG_UINT32 *pui32MMapOffset,
+ IMG_UINT32 *pui32ByteOffset,
+ IMG_UINT32 *pui32RealByteSize, IMG_UINT32 *pui32UserVAddr);
+
+PVRSRV_ERROR
+PVRMMapReleaseMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hMHandle,
+ IMG_BOOL *pbMUnmap,
+ IMG_UINT32 *pui32RealByteSize,
+ IMG_UINT32 *pui32UserVAddr);
+
+int PVRMMap(struct file* pFile, struct vm_area_struct* ps_vma);
+
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#if !defined(SUPPORT_DRI_DRM)
+
+ #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
+#endif
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.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"
+#include "pvr_debugfs.h"
+
+#if defined(SUPPORT_DRI_DRM)
+#include "pvr_drm.h"
+#endif
+#define DRVNAME PVRSRV_MODNAME
+#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(PVR_LDM_MODULE)
+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
+
+static LDM_DRV powervr_driver = {
+#if defined(PVR_LDM_PLATFORM_MODULE)
+ .driver = {
+ .name = DRVNAME,
+ },
+#endif
+#if defined(PVR_LDM_PCI_MODULE)
+ .name = DRVNAME,
+ .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)
+
+static IMG_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;
+ }
+ }
+
+ 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));
+
+ 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
+ (IMG_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
+}
+
+
+static IMG_VOID PVRSRVDriverShutdown(LDM_DEV *pDevice)
+{
+ PVR_TRACE(("PVRSRVDriverShutdown(pDevice=%p)", pDevice));
+
+ (IMG_VOID) PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D3);
+}
+
+#endif
+
+
+#if defined(PVR_LDM_MODULE) || defined(SUPPORT_DRI_DRM)
+#if defined(SUPPORT_DRI_DRM)
+int PVRSRVDriverSuspend(struct drm_device *pDevice, pm_message_t state)
+#else
+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));
+ printk(KERN_ALERT "PVRSRVDriverSuspend(pDevice=%p)", pDevice);
+
+ if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D3) != PVRSRV_OK)
+ {
+ return -EINVAL;
+ }
+#endif
+ return 0;
+}
+
+
+#if defined(SUPPORT_DRI_DRM)
+int PVRSRVDriverResume(struct drm_device *pDevice)
+#else
+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));
+ printk(KERN_ALERT "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;
+
+ psPrivateData->sec_fd_exp_meminfo = NULL;
+#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;
+
+ 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
+
+
+ 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
+ }
+
+ LinuxUnLockMutex(&gPVRSRVLock);
+
+#if !defined(SUPPORT_DRI_DRM)
+ return 0;
+#endif
+}
+
+
+#if defined(SUPPORT_DRI_DRM)
+int PVRCore_Init(IMG_VOID)
+#else
+static int __init PVRCore_Init(IMG_VOID)
+#endif
+{
+ int error;
+#if !defined(PVR_LDM_MODULE)
+ PVRSRV_ERROR eError;
+#else
+ struct device *psDev;
+#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)
+ 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)
+ 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
+
+#else
+
+ 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));
+#endif
+
+#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
+
+ pvr_debugfs_init();
+
+ return 0;
+
+#if defined(PVR_LDM_MODULE)
+destroy_class:
+ class_destroy(psPvrClass);
+unregister_device:
+ unregister_chrdev((IMG_UINT)AssignedMajorNumber, DRVNAME);
+#endif
+#if !defined(SUPPORT_DRI_DRM)
+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)
+ platform_device_unregister(&powervr_device);
+#endif
+ platform_driver_unregister(&powervr_driver);
+#endif
+
+#else
+
+ {
+ SYS_DATA *psSysData;
+
+ psSysData = SysAcquireDataNoCheck();
+ if (psSysData != IMG_NULL)
+ {
+ (IMG_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
+{
+ SYS_DATA *psSysData;
+
+ PVR_TRACE(("PVRCore_Cleanup"));
+
+ pvr_debugfs_cleanup();
+
+ SysAcquireData(&psSysData);
+
+#if defined(PVR_LDM_MODULE)
+ device_destroy(psPvrClass, MKDEV(AssignedMajorNumber, 0));
+ class_destroy(psPvrClass);
+#endif
+
+#if !defined(SUPPORT_DRI_DRM)
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22))
+ if (
+#endif
+ unregister_chrdev((IMG_UINT)AssignedMajorNumber, DRVNAME)
+#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)
+ 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
--- /dev/null
+/**********************************************************************
+ *
+ * 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/version.h>
+#include <linux/errno.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+#include <linux/mutex.h>
+#else
+#include <asm/semaphore.h>
+#endif
+#include <linux/module.h>
+
+#include <img_defs.h>
+#include <services.h>
+
+#include "mutex.h"
+
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+
+IMG_VOID LinuxLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+ mutex_lock(psPVRSRVMutex);
+}
+
+PVRSRV_ERROR LinuxLockMutexInterruptible(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+ if(mutex_lock_interruptible(psPVRSRVMutex) == -EINTR)
+ {
+ return PVRSRV_ERROR_MUTEX_INTERRUPTIBLE_ERROR;
+ }
+ else
+ {
+ return PVRSRV_OK;
+ }
+}
+
+IMG_INT32 LinuxTryLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+ return mutex_trylock(psPVRSRVMutex);
+}
+
+IMG_VOID LinuxUnLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+ mutex_unlock(psPVRSRVMutex);
+}
+
+IMG_BOOL LinuxIsLockedMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+ return (mutex_is_locked(psPVRSRVMutex)) ? IMG_TRUE : IMG_FALSE;
+}
+
+
+#else
+
+
+IMG_VOID LinuxInitMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+ init_MUTEX(&psPVRSRVMutex->sSemaphore);
+ atomic_set(&psPVRSRVMutex->Count, 0);
+}
+
+IMG_VOID LinuxLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+ down(&psPVRSRVMutex->sSemaphore);
+ atomic_dec(&psPVRSRVMutex->Count);
+}
+
+PVRSRV_ERROR LinuxLockMutexInterruptible(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+ if(down_interruptible(&psPVRSRVMutex->sSemaphore) == -EINTR)
+ {
+
+ return PVRSRV_ERROR_MUTEX_INTERRUPTIBLE_ERROR;
+ }else{
+ atomic_dec(&psPVRSRVMutex->Count);
+ return PVRSRV_OK;
+ }
+}
+
+IMG_INT32 LinuxTryLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+ IMG_INT32 Status = down_trylock(&psPVRSRVMutex->sSemaphore);
+ if(Status == 0)
+ {
+ atomic_dec(&psPVRSRVMutex->Count);
+ }
+
+ return Status;
+}
+
+IMG_VOID LinuxUnLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+ atomic_inc(&psPVRSRVMutex->Count);
+ up(&psPVRSRVMutex->sSemaphore);
+}
+
+IMG_BOOL LinuxIsLockedMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
+{
+ IMG_INT32 iCount;
+
+ iCount = atomic_read(&psPVRSRVMutex->Count);
+
+ return (IMG_BOOL)iCount;
+}
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef __INCLUDED_LINUX_MUTEX_H_
+#define __INCLUDED_LINUX_MUTEX_H_
+
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+#include <linux/mutex.h>
+#else
+#include <asm/semaphore.h>
+#endif
+
+
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+
+typedef struct mutex PVRSRV_LINUX_MUTEX;
+
+#else
+
+
+typedef struct {
+ struct semaphore sSemaphore;
+
+ atomic_t Count;
+}PVRSRV_LINUX_MUTEX;
+
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+
+#define LinuxInitMutex(psPVRSRVMutex) \
+ do { \
+ mutex_init(psPVRSRVMutex); \
+ } while(0)
+#else
+extern IMG_VOID LinuxInitMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex);
+#endif
+
+extern IMG_VOID LinuxLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex);
+
+extern PVRSRV_ERROR LinuxLockMutexInterruptible(PVRSRV_LINUX_MUTEX *psPVRSRVMutex);
+
+extern IMG_INT32 LinuxTryLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex);
+
+extern IMG_VOID LinuxUnLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex);
+
+extern IMG_BOOL LinuxIsLockedMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex);
+
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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/version.h>
+
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+#include "img_defs.h"
+#include "pvr_debug.h"
+#include "mutils.h"
+
+#if defined(SUPPORT_LINUX_X86_PAT)
+#define PAT_LINUX_X86_WC 1
+
+#define PAT_X86_ENTRY_BITS 8
+
+#define PAT_X86_BIT_PWT 1U
+#define PAT_X86_BIT_PCD 2U
+#define PAT_X86_BIT_PAT 4U
+#define PAT_X86_BIT_MASK (PAT_X86_BIT_PAT | PAT_X86_BIT_PCD | PAT_X86_BIT_PWT)
+
+static IMG_BOOL g_write_combining_available = IMG_FALSE;
+
+#define PROT_TO_PAT_INDEX(v, B) ((v & _PAGE_ ## B) ? PAT_X86_BIT_ ## B : 0)
+
+static inline IMG_UINT
+pvr_pat_index(pgprotval_t prot_val)
+{
+ IMG_UINT ret = 0;
+ pgprotval_t val = prot_val & _PAGE_CACHE_MASK;
+
+ ret |= PROT_TO_PAT_INDEX(val, PAT);
+ ret |= PROT_TO_PAT_INDEX(val, PCD);
+ ret |= PROT_TO_PAT_INDEX(val, PWT);
+
+ return ret;
+}
+
+static inline IMG_UINT
+pvr_pat_entry(u64 pat, IMG_UINT index)
+{
+ return (IMG_UINT)(pat >> (index * PAT_X86_ENTRY_BITS)) & PAT_X86_BIT_MASK;
+}
+
+static IMG_VOID
+PVRLinuxX86PATProbe(IMG_VOID)
+{
+
+ if (cpu_has_pat)
+ {
+ u64 pat;
+ IMG_UINT pat_index;
+ IMG_UINT pat_entry;
+
+ PVR_TRACE(("%s: PAT available", __FUNCTION__));
+
+ rdmsrl(MSR_IA32_CR_PAT, pat);
+ PVR_TRACE(("%s: Top 32 bits of PAT: 0x%.8x", __FUNCTION__, (IMG_UINT)(pat >> 32)));
+ PVR_TRACE(("%s: Bottom 32 bits of PAT: 0x%.8x", __FUNCTION__, (IMG_UINT)(pat)));
+
+ pat_index = pvr_pat_index(_PAGE_CACHE_WC);
+ PVR_TRACE(("%s: PAT index for write combining: %u", __FUNCTION__, pat_index));
+
+ pat_entry = pvr_pat_entry(pat, pat_index);
+ PVR_TRACE(("%s: PAT entry for write combining: 0x%.2x (should be 0x%.2x)", __FUNCTION__, pat_entry, PAT_LINUX_X86_WC));
+
+#if defined(SUPPORT_LINUX_X86_WRITECOMBINE)
+ g_write_combining_available = (IMG_BOOL)(pat_entry == PAT_LINUX_X86_WC);
+#endif
+ }
+#if defined(DEBUG)
+#if defined(SUPPORT_LINUX_X86_WRITECOMBINE)
+ if (g_write_combining_available)
+ {
+ PVR_TRACE(("%s: Write combining available via PAT", __FUNCTION__));
+ }
+ else
+ {
+ PVR_TRACE(("%s: Write combining not available", __FUNCTION__));
+ }
+#else
+ PVR_TRACE(("%s: Write combining disabled in driver build", __FUNCTION__));
+#endif
+#endif
+}
+
+pgprot_t
+pvr_pgprot_writecombine(pgprot_t prot)
+{
+
+
+ return (g_write_combining_available) ?
+ __pgprot((pgprot_val(prot) & ~_PAGE_CACHE_MASK) | _PAGE_CACHE_WC) : pgprot_noncached(prot);
+}
+#endif
+
+IMG_VOID
+PVRLinuxMUtilsInit(IMG_VOID)
+{
+#if defined(SUPPORT_LINUX_X86_PAT)
+ PVRLinuxX86PATProbe();
+#endif
+}
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef __IMG_LINUX_MUTILS_H__
+#define __IMG_LINUX_MUTILS_H__
+
+#include <linux/version.h>
+
+#if !(defined(__i386__) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)))
+#if defined(SUPPORT_LINUX_X86_PAT)
+#undef SUPPORT_LINUX_X86_PAT
+#endif
+#endif
+
+#if defined(SUPPORT_LINUX_X86_PAT)
+ pgprot_t pvr_pgprot_writecombine(pgprot_t prot);
+ #define PGPROT_WC(pv) pvr_pgprot_writecombine(pv)
+#else
+ #if defined(__arm__) || defined(__sh__)
+ #define PGPROT_WC(pv) pgprot_writecombine(pv)
+ #else
+ #if defined(__i386__) || defined(__mips__)
+ #define PGPROT_WC(pv) pgprot_noncached(pv)
+ #else
+ #define PGPROT_WC(pv) pgprot_noncached(pv)
+ #error Unsupported architecture!
+ #endif
+ #endif
+#endif
+
+#define PGPROT_UC(pv) pgprot_noncached(pv)
+
+#if defined(__i386__) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26))
+ #define IOREMAP(pa, bytes) ioremap_cache(pa, bytes)
+#else
+ #if defined(__arm__) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+ #define IOREMAP(pa, bytes) ioremap_cached(pa, bytes)
+ #else
+ #define IOREMAP(pa, bytes) ioremap(pa, bytes)
+ #endif
+#endif
+
+#if defined(SUPPORT_LINUX_X86_PAT)
+ #if defined(SUPPORT_LINUX_X86_WRITECOMBINE)
+ #define IOREMAP_WC(pa, bytes) ioremap_wc(pa, bytes)
+ #else
+ #define IOREMAP_WC(pa, bytes) ioremap_nocache(pa, bytes)
+ #endif
+#else
+ #if defined(__arm__)
+ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
+ #define IOREMAP_WC(pa, bytes) ioremap_wc(pa, bytes)
+ #else
+ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22))
+ #define IOREMAP_WC(pa, bytes) ioremap_nocache(pa, bytes)
+ #else
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17))
+ #define IOREMAP_WC(pa, bytes) __ioremap(pa, bytes, L_PTE_BUFFERABLE)
+ #else
+ #define IOREMAP_WC(pa, bytes) __ioremap(pa, bytes, , L_PTE_BUFFERABLE, 1)
+ #endif
+ #endif
+ #endif
+ #else
+ #define IOREMAP_WC(pa, bytes) ioremap_nocache(pa, bytes)
+ #endif
+#endif
+
+#define IOREMAP_UC(pa, bytes) ioremap_nocache(pa, bytes)
+
+IMG_VOID PVRLinuxMUtilsInit(IMG_VOID);
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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/version.h>
+#include <asm/io.h>
+#include <asm/page.h>
+#include <asm/system.h>
+#if defined(SUPPORT_CPU_CACHED_BUFFERS)
+#include <asm/cacheflush.h>
+#endif
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/hugetlb.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <asm/hardirq.h>
+#include <linux/timer.h>
+#include <linux/capability.h>
+#include <asm/uaccess.h>
+#include <linux/spinlock.h>
+#if defined(PVR_LINUX_MISR_USING_WORKQUEUE) || \
+ defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE) || \
+ defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || \
+ defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE) || \
+ defined(PVR_LINUX_USING_WORKQUEUES)
+#include <linux/workqueue.h>
+#endif
+
+#include "img_types.h"
+#include "services_headers.h"
+#include "mm.h"
+#include "pvrmmap.h"
+#include "mmap.h"
+#include "env_data.h"
+#include "proc.h"
+#include "mutex.h"
+#include "event.h"
+#include "linkage.h"
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
+#define ON_EACH_CPU(func, info, wait) on_each_cpu(func, info, wait)
+#else
+#define ON_EACH_CPU(func, info, wait) on_each_cpu(func, info, 0, wait)
+#endif
+
+#if defined(PVR_LINUX_USING_WORKQUEUES) && !defined(CONFIG_PREEMPT)
+#error "A preemptible Linux kernel is required when using workqueues"
+#endif
+
+#define EVENT_OBJECT_TIMEOUT_MS (100)
+
+#define HOST_ALLOC_MEM_USING_KMALLOC ((IMG_HANDLE)0)
+#define HOST_ALLOC_MEM_USING_VMALLOC ((IMG_HANDLE)1)
+
+#if !defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+PVRSRV_ERROR OSAllocMem_Impl(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_PVOID *ppvCpuVAddr, IMG_HANDLE *phBlockAlloc)
+#else
+PVRSRV_ERROR OSAllocMem_Impl(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_PVOID *ppvCpuVAddr, IMG_HANDLE *phBlockAlloc, IMG_CHAR *pszFilename, IMG_UINT32 ui32Line)
+#endif
+{
+ PVR_UNREFERENCED_PARAMETER(ui32Flags);
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ *ppvCpuVAddr = _KMallocWrapper(ui32Size, pszFilename, ui32Line);
+#else
+ *ppvCpuVAddr = KMallocWrapper(ui32Size);
+#endif
+ if(*ppvCpuVAddr)
+ {
+ if (phBlockAlloc)
+ {
+
+ *phBlockAlloc = HOST_ALLOC_MEM_USING_KMALLOC;
+ }
+ }
+ else
+ {
+ if (!phBlockAlloc)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ *ppvCpuVAddr = _VMallocWrapper(ui32Size, PVRSRV_HAP_CACHED, pszFilename, ui32Line);
+#else
+ *ppvCpuVAddr = VMallocWrapper(ui32Size, PVRSRV_HAP_CACHED);
+#endif
+ if (!*ppvCpuVAddr)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+
+ *phBlockAlloc = HOST_ALLOC_MEM_USING_VMALLOC;
+ }
+
+ return PVRSRV_OK;
+}
+
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,24))
+
+static inline int is_vmalloc_addr(const void *pvCpuVAddr)
+{
+ unsigned long lAddr = (unsigned long)pvCpuVAddr;
+ return lAddr >= VMALLOC_START && lAddr < VMALLOC_END;
+}
+
+#endif
+
+#if !defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+PVRSRV_ERROR OSFreeMem_Impl(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_PVOID pvCpuVAddr, IMG_HANDLE hBlockAlloc)
+#else
+PVRSRV_ERROR OSFreeMem_Impl(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_PVOID pvCpuVAddr, IMG_HANDLE hBlockAlloc, IMG_CHAR *pszFilename, IMG_UINT32 ui32Line)
+#endif
+{
+ PVR_UNREFERENCED_PARAMETER(ui32Flags);
+ PVR_UNREFERENCED_PARAMETER(ui32Size);
+
+ if (hBlockAlloc == HOST_ALLOC_MEM_USING_VMALLOC)
+ {
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ _VFreeWrapper(pvCpuVAddr, pszFilename, ui32Line);
+#else
+ VFreeWrapper(pvCpuVAddr);
+#endif
+ }
+ else
+ {
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ _KFreeWrapper(pvCpuVAddr, pszFilename, ui32Line);
+#else
+ KFreeWrapper(pvCpuVAddr);
+#endif
+ }
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR
+OSAllocPages_Impl(IMG_UINT32 ui32AllocFlags,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32PageSize,
+ IMG_VOID **ppvCpuVAddr,
+ IMG_HANDLE *phOSMemHandle)
+{
+ LinuxMemArea *psLinuxMemArea;
+
+ PVR_UNREFERENCED_PARAMETER(ui32PageSize);
+
+#if 0
+
+ if(ui32AllocFlags & PVRSRV_HAP_SINGLE_PROCESS)
+ {
+ ui32AllocFlags &= ~PVRSRV_HAP_SINGLE_PROCESS;
+ ui32AllocFlags |= PVRSRV_HAP_MULTI_PROCESS;
+ }
+#endif
+
+ switch(ui32AllocFlags & PVRSRV_HAP_MAPTYPE_MASK)
+ {
+ case PVRSRV_HAP_KERNEL_ONLY:
+ {
+ psLinuxMemArea = NewVMallocLinuxMemArea(ui32Size, ui32AllocFlags);
+ if(!psLinuxMemArea)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ break;
+ }
+ case PVRSRV_HAP_SINGLE_PROCESS:
+ {
+
+
+ psLinuxMemArea = NewAllocPagesLinuxMemArea(ui32Size, ui32AllocFlags);
+ if(!psLinuxMemArea)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ PVRMMapRegisterArea(psLinuxMemArea);
+ break;
+ }
+
+ case PVRSRV_HAP_MULTI_PROCESS:
+ {
+
+#if defined(VIVT_CACHE) || defined(__sh__)
+
+ ui32AllocFlags &= ~PVRSRV_HAP_CACHED;
+#endif
+ psLinuxMemArea = NewVMallocLinuxMemArea(ui32Size, ui32AllocFlags);
+ if(!psLinuxMemArea)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ PVRMMapRegisterArea(psLinuxMemArea);
+ break;
+ }
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "OSAllocPages: invalid flags 0x%x\n", ui32AllocFlags));
+ *ppvCpuVAddr = NULL;
+ *phOSMemHandle = (IMG_HANDLE)0;
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ *ppvCpuVAddr = LinuxMemAreaToCpuVAddr(psLinuxMemArea);
+ *phOSMemHandle = psLinuxMemArea;
+
+ LinuxMemAreaRegister(psLinuxMemArea);
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR
+OSFreePages(IMG_UINT32 ui32AllocFlags, IMG_UINT32 ui32Bytes, IMG_VOID *pvCpuVAddr, IMG_HANDLE hOSMemHandle)
+{
+ LinuxMemArea *psLinuxMemArea;
+ PVRSRV_ERROR eError;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+ PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+
+ psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+ switch(ui32AllocFlags & PVRSRV_HAP_MAPTYPE_MASK)
+ {
+ case PVRSRV_HAP_KERNEL_ONLY:
+ break;
+ case PVRSRV_HAP_SINGLE_PROCESS:
+ case PVRSRV_HAP_MULTI_PROCESS:
+ eError = PVRMMapRemoveRegisteredArea(psLinuxMemArea);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSFreePages(ui32AllocFlags=0x%08X, ui32Bytes=%d, "
+ "pvCpuVAddr=%p, hOSMemHandle=%p) FAILED!",
+ ui32AllocFlags, ui32Bytes, pvCpuVAddr, hOSMemHandle));
+ return eError;
+ }
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR,"%s: invalid flags 0x%x\n",
+ __FUNCTION__, ui32AllocFlags));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ LinuxMemAreaDeepFree(psLinuxMemArea);
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR
+OSGetSubMemHandle(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32ByteOffset,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE *phOSMemHandleRet)
+{
+ LinuxMemArea *psParentLinuxMemArea, *psLinuxMemArea;
+ PVRSRV_ERROR eError;
+
+ psParentLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+ psLinuxMemArea = NewSubLinuxMemArea(psParentLinuxMemArea, ui32ByteOffset, ui32Bytes);
+ if(!psLinuxMemArea)
+ {
+ *phOSMemHandleRet = NULL;
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ *phOSMemHandleRet = psLinuxMemArea;
+
+
+ if(ui32Flags & PVRSRV_HAP_KERNEL_ONLY)
+ {
+ return PVRSRV_OK;
+ }
+
+ eError = PVRMMapRegisterArea(psLinuxMemArea);
+ if(eError != PVRSRV_OK)
+ {
+ goto failed_register_area;
+ }
+
+ return PVRSRV_OK;
+
+failed_register_area:
+ *phOSMemHandleRet = NULL;
+ LinuxMemAreaDeepFree(psLinuxMemArea);
+ return eError;
+}
+
+PVRSRV_ERROR
+OSReleaseSubMemHandle(IMG_VOID *hOSMemHandle, IMG_UINT32 ui32Flags)
+{
+ LinuxMemArea *psLinuxMemArea;
+ PVRSRV_ERROR eError;
+
+ psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+ PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC);
+
+ if((ui32Flags & PVRSRV_HAP_KERNEL_ONLY) == 0)
+ {
+ eError = PVRMMapRemoveRegisteredArea(psLinuxMemArea);
+ if(eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+ }
+ LinuxMemAreaDeepFree(psLinuxMemArea);
+
+ return PVRSRV_OK;
+}
+
+
+IMG_CPU_PHYADDR
+OSMemHandleToCpuPAddr(IMG_VOID *hOSMemHandle, IMG_UINT32 ui32ByteOffset)
+{
+ PVR_ASSERT(hOSMemHandle);
+
+ return LinuxMemAreaToCpuPAddr(hOSMemHandle, ui32ByteOffset);
+}
+
+
+
+IMG_VOID OSMemCopy(IMG_VOID *pvDst, IMG_VOID *pvSrc, IMG_UINT32 ui32Size)
+{
+#if defined(USE_UNOPTIMISED_MEMCPY)
+ IMG_UINT8 *Src,*Dst;
+ IMG_INT i;
+
+ Src=(IMG_UINT8 *)pvSrc;
+ Dst=(IMG_UINT8 *)pvDst;
+ for(i=0;i<ui32Size;i++)
+ {
+ Dst[i]=Src[i];
+ }
+#else
+ memcpy(pvDst, pvSrc, ui32Size);
+#endif
+}
+
+
+IMG_VOID OSMemSet(IMG_VOID *pvDest, IMG_UINT8 ui8Value, IMG_UINT32 ui32Size)
+{
+#if defined(USE_UNOPTIMISED_MEMSET)
+ IMG_UINT8 *Buff;
+ IMG_INT i;
+
+ Buff=(IMG_UINT8 *)pvDest;
+ for(i=0;i<ui32Size;i++)
+ {
+ Buff[i]=ui8Value;
+ }
+#else
+ memset(pvDest, (IMG_INT) ui8Value, (size_t) ui32Size);
+#endif
+}
+
+
+IMG_CHAR *OSStringCopy(IMG_CHAR *pszDest, const IMG_CHAR *pszSrc)
+{
+ return (strcpy(pszDest, pszSrc));
+}
+
+IMG_INT32 OSSNPrintf(IMG_CHAR *pStr, IMG_UINT32 ui32Size, const IMG_CHAR *pszFormat, ...)
+{
+ va_list argList;
+ IMG_INT32 iCount;
+
+ va_start(argList, pszFormat);
+ iCount = vsnprintf(pStr, (size_t)ui32Size, pszFormat, argList);
+ va_end(argList);
+
+ return iCount;
+}
+
+IMG_VOID OSBreakResourceLock (PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID)
+{
+ volatile IMG_UINT32 *pui32Access = (volatile IMG_UINT32 *)&psResource->ui32Lock;
+
+ if(*pui32Access)
+ {
+ if(psResource->ui32ID == ui32ID)
+ {
+ psResource->ui32ID = 0;
+ *pui32Access = 0;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"OSBreakResourceLock: Resource is not locked for this process."));
+ }
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"OSBreakResourceLock: Resource is not locked"));
+ }
+}
+
+
+PVRSRV_ERROR OSCreateResource(PVRSRV_RESOURCE *psResource)
+{
+ psResource->ui32ID = 0;
+ psResource->ui32Lock = 0;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSDestroyResource (PVRSRV_RESOURCE *psResource)
+{
+ OSBreakResourceLock (psResource, psResource->ui32ID);
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSInitEnvData(IMG_PVOID *ppvEnvSpecificData)
+{
+ ENV_DATA *psEnvData;
+ PVRSRV_ERROR eError;
+
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(ENV_DATA), (IMG_VOID **)&psEnvData, IMG_NULL,
+ "Environment Data");
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, PVRSRV_MAX_BRIDGE_IN_SIZE + PVRSRV_MAX_BRIDGE_OUT_SIZE,
+ &psEnvData->pvBridgeData, IMG_NULL,
+ "Bridge Data");
+ if (eError != PVRSRV_OK)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(ENV_DATA), psEnvData, IMG_NULL);
+
+ return eError;
+ }
+
+
+
+ psEnvData->bMISRInstalled = IMG_FALSE;
+ psEnvData->bLISRInstalled = IMG_FALSE;
+
+
+ *ppvEnvSpecificData = psEnvData;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSDeInitEnvData(IMG_PVOID pvEnvSpecificData)
+{
+ ENV_DATA *psEnvData = (ENV_DATA*)pvEnvSpecificData;
+
+ PVR_ASSERT(!psEnvData->bMISRInstalled);
+ PVR_ASSERT(!psEnvData->bLISRInstalled);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, PVRSRV_MAX_BRIDGE_IN_SIZE + PVRSRV_MAX_BRIDGE_OUT_SIZE, psEnvData->pvBridgeData, IMG_NULL);
+ psEnvData->pvBridgeData = IMG_NULL;
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(ENV_DATA), pvEnvSpecificData, IMG_NULL);
+
+
+ return PVRSRV_OK;
+}
+
+
+
+IMG_VOID OSReleaseThreadQuanta(IMG_VOID)
+{
+ schedule();
+}
+
+
+
+IMG_UINT32 OSClockus(IMG_VOID)
+{
+ IMG_UINT32 time, j = jiffies;
+
+ time = j * (1000000 / HZ);
+
+ return time;
+}
+
+
+IMG_VOID OSWaitus(IMG_UINT32 ui32Timeus)
+{
+ udelay(ui32Timeus);
+}
+
+
+IMG_VOID OSSleepms(IMG_UINT32 ui32Timems)
+{
+ msleep(ui32Timems);
+}
+
+
+IMG_UINT32 OSGetCurrentProcessIDKM(IMG_VOID)
+{
+ if (in_interrupt())
+ {
+ return KERNEL_ID;
+ }
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+ return (IMG_UINT32)current->pgrp;
+#else
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24))
+ return (IMG_UINT32)task_tgid_nr(current);
+#else
+ return (IMG_UINT32)current->tgid;
+#endif
+#endif
+}
+
+
+IMG_UINT32 OSGetPageSize(IMG_VOID)
+{
+#if defined(__sh__)
+ IMG_UINT32 ui32ReturnValue = PAGE_SIZE;
+
+ return (ui32ReturnValue);
+#else
+ return PAGE_SIZE;
+#endif
+}
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
+static irqreturn_t DeviceISRWrapper(int irq, void *dev_id
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
+ , struct pt_regs *regs
+#endif
+ )
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ IMG_BOOL bStatus = IMG_FALSE;
+
+ PVR_UNREFERENCED_PARAMETER(irq);
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
+ PVR_UNREFERENCED_PARAMETER(regs);
+#endif
+ psDeviceNode = (PVRSRV_DEVICE_NODE*)dev_id;
+ if(!psDeviceNode)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "DeviceISRWrapper: invalid params\n"));
+ goto out;
+ }
+
+ bStatus = PVRSRVDeviceLISR(psDeviceNode);
+
+ if (bStatus)
+ {
+ OSScheduleMISR((IMG_VOID *)psDeviceNode->psSysData);
+ }
+
+out:
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+ return bStatus ? IRQ_HANDLED : IRQ_NONE;
+#endif
+}
+
+
+
+static irqreturn_t SystemISRWrapper(int irq, void *dev_id
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
+ , struct pt_regs *regs
+#endif
+ )
+{
+ SYS_DATA *psSysData;
+ IMG_BOOL bStatus = IMG_FALSE;
+
+ PVR_UNREFERENCED_PARAMETER(irq);
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
+ PVR_UNREFERENCED_PARAMETER(regs);
+#endif
+ psSysData = (SYS_DATA *)dev_id;
+ if(!psSysData)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "SystemISRWrapper: invalid params\n"));
+ goto out;
+ }
+
+ bStatus = PVRSRVSystemLISR(psSysData);
+
+ if (bStatus)
+ {
+ OSScheduleMISR((IMG_VOID *)psSysData);
+ }
+
+out:
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+ return bStatus ? IRQ_HANDLED : IRQ_NONE;
+#endif
+}
+PVRSRV_ERROR OSInstallDeviceLISR(IMG_VOID *pvSysData,
+ IMG_UINT32 ui32Irq,
+ IMG_CHAR *pszISRName,
+ IMG_VOID *pvDeviceNode)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (psEnvData->bLISRInstalled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSInstallDeviceLISR: An ISR has already been installed: IRQ %d cookie %p", psEnvData->ui32IRQ, psEnvData->pvISRCookie));
+ return PVRSRV_ERROR_ISR_ALREADY_INSTALLED;
+ }
+
+ PVR_TRACE(("Installing device LISR %s on IRQ %d with cookie %p", pszISRName, ui32Irq, pvDeviceNode));
+
+ if(request_irq(ui32Irq, DeviceISRWrapper,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22))
+ SA_SHIRQ
+#else
+ IRQF_SHARED
+#endif
+ , pszISRName, pvDeviceNode))
+ {
+ PVR_DPF((PVR_DBG_ERROR,"OSInstallDeviceLISR: Couldn't install device LISR on IRQ %d", ui32Irq));
+
+ return PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR;
+ }
+
+ psEnvData->ui32IRQ = ui32Irq;
+ psEnvData->pvISRCookie = pvDeviceNode;
+ psEnvData->bLISRInstalled = IMG_TRUE;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSUninstallDeviceLISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (!psEnvData->bLISRInstalled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSUninstallDeviceLISR: No LISR has been installed"));
+ return PVRSRV_ERROR_ISR_NOT_INSTALLED;
+ }
+
+ PVR_TRACE(("Uninstalling device LISR on IRQ %d with cookie %p", psEnvData->ui32IRQ, psEnvData->pvISRCookie));
+
+ free_irq(psEnvData->ui32IRQ, psEnvData->pvISRCookie);
+
+ psEnvData->bLISRInstalled = IMG_FALSE;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSInstallSystemLISR(IMG_VOID *pvSysData, IMG_UINT32 ui32Irq)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (psEnvData->bLISRInstalled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSInstallSystemLISR: An LISR has already been installed: IRQ %d cookie %p", psEnvData->ui32IRQ, psEnvData->pvISRCookie));
+ return PVRSRV_ERROR_ISR_ALREADY_INSTALLED;
+ }
+
+ PVR_TRACE(("Installing system LISR on IRQ %d with cookie %p", ui32Irq, pvSysData));
+
+ if(request_irq(ui32Irq, SystemISRWrapper,
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22))
+ SA_SHIRQ
+#else
+ IRQF_SHARED
+#endif
+ , "PowerVR", pvSysData))
+ {
+ PVR_DPF((PVR_DBG_ERROR,"OSInstallSystemLISR: Couldn't install system LISR on IRQ %d", ui32Irq));
+
+ return PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR;
+ }
+
+ psEnvData->ui32IRQ = ui32Irq;
+ psEnvData->pvISRCookie = pvSysData;
+ psEnvData->bLISRInstalled = IMG_TRUE;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSUninstallSystemLISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (!psEnvData->bLISRInstalled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSUninstallSystemLISR: No LISR has been installed"));
+ return PVRSRV_ERROR_ISR_NOT_INSTALLED;
+ }
+
+ PVR_TRACE(("Uninstalling system LISR on IRQ %d with cookie %p", psEnvData->ui32IRQ, psEnvData->pvISRCookie));
+
+ free_irq(psEnvData->ui32IRQ, psEnvData->pvISRCookie);
+
+ psEnvData->bLISRInstalled = IMG_FALSE;
+
+ return PVRSRV_OK;
+}
+
+#if defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE)
+static void MISRWrapper(
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
+ void *data
+#else
+ struct work_struct *data
+#endif
+)
+{
+ ENV_DATA *psEnvData = container_of(data, ENV_DATA, sMISRWork);
+ SYS_DATA *psSysData = (SYS_DATA *)psEnvData->pvMISRData;
+
+ PVRSRVMISR(psSysData);
+}
+
+
+PVRSRV_ERROR OSInstallMISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (psEnvData->bMISRInstalled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSInstallMISR: An MISR has already been installed"));
+ return PVRSRV_ERROR_ISR_ALREADY_INSTALLED;
+ }
+
+ PVR_TRACE(("Installing MISR with cookie %p", pvSysData));
+
+ psEnvData->psWorkQueue = create_singlethread_workqueue("pvr_workqueue");
+
+ if (psEnvData->psWorkQueue == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSInstallMISR: create_singlethreaded_workqueue failed"));
+ return PVRSRV_ERROR_UNABLE_TO_CREATE_THREAD;
+ }
+
+ INIT_WORK(&psEnvData->sMISRWork, MISRWrapper
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
+ , (void *)&psEnvData->sMISRWork
+#endif
+ );
+
+ psEnvData->pvMISRData = pvSysData;
+ psEnvData->bMISRInstalled = IMG_TRUE;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSUninstallMISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (!psEnvData->bMISRInstalled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSUninstallMISR: No MISR has been installed"));
+ return PVRSRV_ERROR_ISR_NOT_INSTALLED;
+ }
+
+ PVR_TRACE(("Uninstalling MISR"));
+
+ destroy_workqueue(psEnvData->psWorkQueue);
+
+ psEnvData->bMISRInstalled = IMG_FALSE;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSScheduleMISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA*)psSysData->pvEnvSpecificData;
+
+ if (psEnvData->bMISRInstalled)
+ {
+ queue_work(psEnvData->psWorkQueue, &psEnvData->sMISRWork);
+ }
+
+ return PVRSRV_OK;
+}
+#else
+#if defined(PVR_LINUX_MISR_USING_WORKQUEUE)
+static void MISRWrapper(
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
+ void *data
+#else
+ struct work_struct *data
+#endif
+)
+{
+ ENV_DATA *psEnvData = container_of(data, ENV_DATA, sMISRWork);
+ SYS_DATA *psSysData = (SYS_DATA *)psEnvData->pvMISRData;
+
+ PVRSRVMISR(psSysData);
+}
+
+
+PVRSRV_ERROR OSInstallMISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (psEnvData->bMISRInstalled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSInstallMISR: An MISR has already been installed"));
+ return PVRSRV_ERROR_ISR_ALREADY_INSTALLED;
+ }
+
+ PVR_TRACE(("Installing MISR with cookie %p", pvSysData));
+
+ INIT_WORK(&psEnvData->sMISRWork, MISRWrapper
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
+ , (void *)&psEnvData->sMISRWork
+#endif
+ );
+
+ psEnvData->pvMISRData = pvSysData;
+ psEnvData->bMISRInstalled = IMG_TRUE;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSUninstallMISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (!psEnvData->bMISRInstalled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSUninstallMISR: No MISR has been installed"));
+ return PVRSRV_ERROR_ISR_NOT_INSTALLED;
+ }
+
+ PVR_TRACE(("Uninstalling MISR"));
+
+ flush_scheduled_work();
+
+ psEnvData->bMISRInstalled = IMG_FALSE;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSScheduleMISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA*)psSysData->pvEnvSpecificData;
+
+ if (psEnvData->bMISRInstalled)
+ {
+ schedule_work(&psEnvData->sMISRWork);
+ }
+
+ return PVRSRV_OK;
+}
+
+#else
+
+
+static void MISRWrapper(unsigned long data)
+{
+ SYS_DATA *psSysData;
+
+ psSysData = (SYS_DATA *)data;
+
+ PVRSRVMISR(psSysData);
+}
+
+
+PVRSRV_ERROR OSInstallMISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (psEnvData->bMISRInstalled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSInstallMISR: An MISR has already been installed"));
+ return PVRSRV_ERROR_ISR_ALREADY_INSTALLED;
+ }
+
+ PVR_TRACE(("Installing MISR with cookie %p", pvSysData));
+
+ tasklet_init(&psEnvData->sMISRTasklet, MISRWrapper, (unsigned long)pvSysData);
+
+ psEnvData->bMISRInstalled = IMG_TRUE;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSUninstallMISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (!psEnvData->bMISRInstalled)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSUninstallMISR: No MISR has been installed"));
+ return PVRSRV_ERROR_ISR_NOT_INSTALLED;
+ }
+
+ PVR_TRACE(("Uninstalling MISR"));
+
+ tasklet_kill(&psEnvData->sMISRTasklet);
+
+ psEnvData->bMISRInstalled = IMG_FALSE;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSScheduleMISR(IMG_VOID *pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA*)psSysData->pvEnvSpecificData;
+
+ if (psEnvData->bMISRInstalled)
+ {
+ tasklet_schedule(&psEnvData->sMISRTasklet);
+ }
+
+ return PVRSRV_OK;
+}
+
+#endif
+#endif
+
+#endif
+
+IMG_VOID OSPanic(IMG_VOID)
+{
+ BUG();
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22))
+#define OS_TAS(p) xchg((p), 1)
+#else
+#define OS_TAS(p) tas(p)
+#endif
+PVRSRV_ERROR OSLockResource ( PVRSRV_RESOURCE *psResource,
+ IMG_UINT32 ui32ID)
+
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if(!OS_TAS(&psResource->ui32Lock))
+ psResource->ui32ID = ui32ID;
+ else
+ eError = PVRSRV_ERROR_UNABLE_TO_LOCK_RESOURCE;
+
+ return eError;
+}
+
+
+PVRSRV_ERROR OSUnlockResource (PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID)
+{
+ volatile IMG_UINT32 *pui32Access = (volatile IMG_UINT32 *)&psResource->ui32Lock;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if(*pui32Access)
+ {
+ if(psResource->ui32ID == ui32ID)
+ {
+ psResource->ui32ID = 0;
+ smp_mb();
+ *pui32Access = 0;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,"OSUnlockResource: Resource %p is not locked with expected value.", psResource));
+ PVR_DPF((PVR_DBG_MESSAGE,"Should be %x is actually %x", ui32ID, psResource->ui32ID));
+ eError = PVRSRV_ERROR_INVALID_LOCK_ID;
+ }
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,"OSUnlockResource: Resource %p is not locked", psResource));
+ eError = PVRSRV_ERROR_RESOURCE_NOT_LOCKED;
+ }
+
+ return eError;
+}
+
+
+ IMG_BOOL OSIsResourceLocked (PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID)
+{
+ volatile IMG_UINT32 *pui32Access = (volatile IMG_UINT32 *)&psResource->ui32Lock;
+
+ return (*(volatile IMG_UINT32 *)pui32Access == 1) && (psResource->ui32ID == ui32ID)
+ ? IMG_TRUE
+ : IMG_FALSE;
+}
+
+
+IMG_CPU_PHYADDR OSMapLinToCPUPhys(IMG_HANDLE hOSMemHandle,
+ IMG_VOID *pvLinAddr)
+{
+ IMG_CPU_PHYADDR CpuPAddr;
+ LinuxMemArea *psLinuxMemArea;
+ IMG_UINTPTR_T uiByteOffset;
+ IMG_UINT32 ui32ByteOffset;
+
+ PVR_ASSERT(hOSMemHandle != IMG_NULL);
+
+
+
+ psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+ uiByteOffset = (IMG_UINTPTR_T)pvLinAddr - (IMG_UINTPTR_T)LinuxMemAreaToCpuVAddr(psLinuxMemArea);
+ ui32ByteOffset = (IMG_UINT32)uiByteOffset;
+
+ CpuPAddr = LinuxMemAreaToCpuPAddr(hOSMemHandle, ui32ByteOffset);
+
+ return CpuPAddr;
+}
+
+
+IMG_VOID *
+OSMapPhysToLin(IMG_CPU_PHYADDR BasePAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32MappingFlags,
+ IMG_HANDLE *phOSMemHandle)
+{
+ if(ui32MappingFlags & PVRSRV_HAP_KERNEL_ONLY)
+ {
+
+ if(phOSMemHandle == IMG_NULL)
+ {
+ IMG_VOID *pvIORemapCookie;
+ pvIORemapCookie = IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags);
+ if(pvIORemapCookie == IMG_NULL)
+ {
+ return IMG_NULL;
+ }
+ return pvIORemapCookie;
+ }
+ else
+ {
+ LinuxMemArea *psLinuxMemArea = NewIORemapLinuxMemArea(BasePAddr, ui32Bytes, ui32MappingFlags);
+
+ if(psLinuxMemArea == IMG_NULL)
+ {
+ return IMG_NULL;
+ }
+
+ *phOSMemHandle = (IMG_HANDLE)psLinuxMemArea;
+ return LinuxMemAreaToCpuVAddr(psLinuxMemArea);
+ }
+ }
+
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSMapPhysToLin should only be used with PVRSRV_HAP_KERNEL_ONLY "
+ " (Use OSReservePhys otherwise)"));
+
+ return IMG_NULL;
+}
+
+IMG_BOOL
+OSUnMapPhysToLin(IMG_VOID *pvLinAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32MappingFlags, IMG_HANDLE hOSMemHandle)
+{
+ PVR_TRACE(("%s: unmapping %d bytes from %p", __FUNCTION__, ui32Bytes, pvLinAddr));
+
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+
+ if(ui32MappingFlags & PVRSRV_HAP_KERNEL_ONLY)
+ {
+ if (hOSMemHandle == IMG_NULL)
+ {
+ IOUnmapWrapper(pvLinAddr);
+ }
+ else
+ {
+ LinuxMemArea *psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+ PVR_ASSERT(LinuxMemAreaToCpuVAddr(psLinuxMemArea) == pvLinAddr);
+
+ FreeIORemapLinuxMemArea(psLinuxMemArea);
+ }
+
+ return IMG_TRUE;
+ }
+
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSUnMapPhysToLin should only be used with PVRSRV_HAP_KERNEL_ONLY "
+ " (Use OSUnReservePhys otherwise)"));
+ return IMG_FALSE;
+}
+
+static PVRSRV_ERROR
+RegisterExternalMem(IMG_SYS_PHYADDR *pBasePAddr,
+ IMG_VOID *pvCPUVAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_BOOL bPhysContig,
+ IMG_UINT32 ui32MappingFlags,
+ IMG_HANDLE *phOSMemHandle)
+{
+ LinuxMemArea *psLinuxMemArea;
+
+ switch(ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK)
+ {
+ case PVRSRV_HAP_KERNEL_ONLY:
+ {
+ psLinuxMemArea = NewExternalKVLinuxMemArea(pBasePAddr, pvCPUVAddr, ui32Bytes, bPhysContig, ui32MappingFlags);
+
+ if(!psLinuxMemArea)
+ {
+ return PVRSRV_ERROR_BAD_MAPPING;
+ }
+ break;
+ }
+ case PVRSRV_HAP_SINGLE_PROCESS:
+ {
+ psLinuxMemArea = NewExternalKVLinuxMemArea(pBasePAddr, pvCPUVAddr, ui32Bytes, bPhysContig, ui32MappingFlags);
+
+ if(!psLinuxMemArea)
+ {
+ return PVRSRV_ERROR_BAD_MAPPING;
+ }
+ PVRMMapRegisterArea(psLinuxMemArea);
+ break;
+ }
+ case PVRSRV_HAP_MULTI_PROCESS:
+ {
+
+#if defined(VIVT_CACHE) || defined(__sh__)
+
+ ui32MappingFlags &= ~PVRSRV_HAP_CACHED;
+#endif
+ psLinuxMemArea = NewExternalKVLinuxMemArea(pBasePAddr, pvCPUVAddr, ui32Bytes, bPhysContig, ui32MappingFlags);
+
+ if(!psLinuxMemArea)
+ {
+ return PVRSRV_ERROR_BAD_MAPPING;
+ }
+ PVRMMapRegisterArea(psLinuxMemArea);
+ break;
+ }
+ default:
+ PVR_DPF((PVR_DBG_ERROR,"OSRegisterMem : invalid flags 0x%x\n", ui32MappingFlags));
+ *phOSMemHandle = (IMG_HANDLE)0;
+ return PVRSRV_ERROR_INVALID_FLAGS;
+ }
+
+ *phOSMemHandle = (IMG_HANDLE)psLinuxMemArea;
+
+ LinuxMemAreaRegister(psLinuxMemArea);
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR
+OSRegisterMem(IMG_CPU_PHYADDR BasePAddr,
+ IMG_VOID *pvCPUVAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32MappingFlags,
+ IMG_HANDLE *phOSMemHandle)
+{
+ IMG_SYS_PHYADDR SysPAddr = SysCpuPAddrToSysPAddr(BasePAddr);
+
+ return RegisterExternalMem(&SysPAddr, pvCPUVAddr, ui32Bytes, IMG_TRUE, ui32MappingFlags, phOSMemHandle);
+}
+
+
+PVRSRV_ERROR OSRegisterDiscontigMem(IMG_SYS_PHYADDR *pBasePAddr, IMG_VOID *pvCPUVAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32MappingFlags, IMG_HANDLE *phOSMemHandle)
+{
+ return RegisterExternalMem(pBasePAddr, pvCPUVAddr, ui32Bytes, IMG_FALSE, ui32MappingFlags, phOSMemHandle);
+}
+
+
+PVRSRV_ERROR
+OSUnRegisterMem (IMG_VOID *pvCpuVAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32MappingFlags,
+ IMG_HANDLE hOSMemHandle)
+{
+ LinuxMemArea *psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+ PVRSRV_ERROR eError;
+
+ PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+
+ switch(ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK)
+ {
+ case PVRSRV_HAP_KERNEL_ONLY:
+ break;
+ case PVRSRV_HAP_SINGLE_PROCESS:
+ case PVRSRV_HAP_MULTI_PROCESS:
+ {
+ eError = PVRMMapRemoveRegisteredArea(psLinuxMemArea);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s(%p, %d, 0x%08X, %p) FAILED!",
+ __FUNCTION__, pvCpuVAddr, ui32Bytes,
+ ui32MappingFlags, hOSMemHandle));
+ return eError;
+ }
+ break;
+ }
+ default:
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSUnRegisterMem : invalid flags 0x%x", ui32MappingFlags));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ }
+
+ LinuxMemAreaDeepFree(psLinuxMemArea);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSUnRegisterDiscontigMem(IMG_VOID *pvCpuVAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32Flags, IMG_HANDLE hOSMemHandle)
+{
+ return OSUnRegisterMem(pvCpuVAddr, ui32Bytes, ui32Flags, hOSMemHandle);
+}
+
+PVRSRV_ERROR
+OSReservePhys(IMG_CPU_PHYADDR BasePAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32MappingFlags,
+ IMG_VOID **ppvCpuVAddr,
+ IMG_HANDLE *phOSMemHandle)
+{
+ LinuxMemArea *psLinuxMemArea;
+
+#if 0
+
+ if(ui32MappingFlags & PVRSRV_HAP_SINGLE_PROCESS)
+ {
+ ui32MappingFlags &= ~PVRSRV_HAP_SINGLE_PROCESS;
+ ui32MappingFlags |= PVRSRV_HAP_MULTI_PROCESS;
+ }
+#endif
+
+ switch(ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK)
+ {
+ case PVRSRV_HAP_KERNEL_ONLY:
+ {
+
+ psLinuxMemArea = NewIORemapLinuxMemArea(BasePAddr, ui32Bytes, ui32MappingFlags);
+ if(!psLinuxMemArea)
+ {
+ return PVRSRV_ERROR_BAD_MAPPING;
+ }
+ break;
+ }
+ case PVRSRV_HAP_SINGLE_PROCESS:
+ {
+
+ psLinuxMemArea = NewIOLinuxMemArea(BasePAddr, ui32Bytes, ui32MappingFlags);
+ if(!psLinuxMemArea)
+ {
+ return PVRSRV_ERROR_BAD_MAPPING;
+ }
+ PVRMMapRegisterArea(psLinuxMemArea);
+ break;
+ }
+ case PVRSRV_HAP_MULTI_PROCESS:
+ {
+
+#if defined(VIVT_CACHE) || defined(__sh__)
+
+ ui32MappingFlags &= ~PVRSRV_HAP_CACHED;
+#endif
+ psLinuxMemArea = NewIORemapLinuxMemArea(BasePAddr, ui32Bytes, ui32MappingFlags);
+ if(!psLinuxMemArea)
+ {
+ return PVRSRV_ERROR_BAD_MAPPING;
+ }
+ PVRMMapRegisterArea(psLinuxMemArea);
+ break;
+ }
+ default:
+ PVR_DPF((PVR_DBG_ERROR,"OSMapPhysToLin : invalid flags 0x%x\n", ui32MappingFlags));
+ *ppvCpuVAddr = NULL;
+ *phOSMemHandle = (IMG_HANDLE)0;
+ return PVRSRV_ERROR_INVALID_FLAGS;
+ }
+
+ *phOSMemHandle = (IMG_HANDLE)psLinuxMemArea;
+ *ppvCpuVAddr = LinuxMemAreaToCpuVAddr(psLinuxMemArea);
+
+ LinuxMemAreaRegister(psLinuxMemArea);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+OSUnReservePhys(IMG_VOID *pvCpuVAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32MappingFlags,
+ IMG_HANDLE hOSMemHandle)
+{
+ LinuxMemArea *psLinuxMemArea;
+ PVRSRV_ERROR eError;
+
+ PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+
+ psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+ switch(ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK)
+ {
+ case PVRSRV_HAP_KERNEL_ONLY:
+ break;
+ case PVRSRV_HAP_SINGLE_PROCESS:
+ case PVRSRV_HAP_MULTI_PROCESS:
+ {
+ eError = PVRMMapRemoveRegisteredArea(psLinuxMemArea);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s(%p, %d, 0x%08X, %p) FAILED!",
+ __FUNCTION__, pvCpuVAddr, ui32Bytes,
+ ui32MappingFlags, hOSMemHandle));
+ return eError;
+ }
+ break;
+ }
+ default:
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSUnMapPhysToLin : invalid flags 0x%x", ui32MappingFlags));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ }
+
+ LinuxMemAreaDeepFree(psLinuxMemArea);
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSBaseAllocContigMemory(IMG_UINT32 ui32Size, IMG_CPU_VIRTADDR *pvLinAddr, IMG_CPU_PHYADDR *psPhysAddr)
+{
+#if !defined(NO_HARDWARE)
+ PVR_UNREFERENCED_PARAMETER(ui32Size);
+ PVR_UNREFERENCED_PARAMETER(pvLinAddr);
+ PVR_UNREFERENCED_PARAMETER(psPhysAddr);
+ PVR_DPF((PVR_DBG_ERROR, "%s: Not available", __FUNCTION__));
+
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+#else
+ IMG_VOID *pvKernLinAddr;
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ pvKernLinAddr = _KMallocWrapper(ui32Size, __FILE__, __LINE__);
+#else
+ pvKernLinAddr = KMallocWrapper(ui32Size);
+#endif
+ if (!pvKernLinAddr)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ *pvLinAddr = pvKernLinAddr;
+
+ psPhysAddr->uiAddr = virt_to_phys(pvKernLinAddr);
+
+ return PVRSRV_OK;
+#endif
+}
+
+
+PVRSRV_ERROR OSBaseFreeContigMemory(IMG_UINT32 ui32Size, IMG_CPU_VIRTADDR pvLinAddr, IMG_CPU_PHYADDR psPhysAddr)
+{
+#if !defined(NO_HARDWARE)
+ PVR_UNREFERENCED_PARAMETER(ui32Size);
+ PVR_UNREFERENCED_PARAMETER(pvLinAddr);
+ PVR_UNREFERENCED_PARAMETER(psPhysAddr.uiAddr);
+
+ PVR_DPF((PVR_DBG_WARNING, "%s: Not available", __FUNCTION__));
+#else
+ PVR_UNREFERENCED_PARAMETER(ui32Size);
+ PVR_UNREFERENCED_PARAMETER(psPhysAddr.uiAddr);
+
+ KFreeWrapper(pvLinAddr);
+#endif
+ return PVRSRV_OK;
+}
+
+IMG_UINT32 OSReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset)
+{
+#if !defined(NO_HARDWARE)
+ return (IMG_UINT32) readl((IMG_PBYTE)pvLinRegBaseAddr+ui32Offset);
+#else
+ return *(IMG_UINT32 *)((IMG_PBYTE)pvLinRegBaseAddr+ui32Offset);
+#endif
+}
+
+IMG_VOID OSWriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value)
+{
+#if !defined(NO_HARDWARE)
+ writel(ui32Value, (IMG_PBYTE)pvLinRegBaseAddr+ui32Offset);
+#else
+ *(IMG_UINT32 *)((IMG_PBYTE)pvLinRegBaseAddr+ui32Offset) = ui32Value;
+#endif
+}
+
+#if defined(CONFIG_PCI) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14))
+
+PVRSRV_PCI_DEV_HANDLE OSPCISetDev(IMG_VOID *pvPCICookie, HOST_PCI_INIT_FLAGS eFlags)
+{
+ int err;
+ IMG_UINT32 i;
+ PVR_PCI_DEV *psPVRPCI;
+
+ PVR_TRACE(("OSPCISetDev"));
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psPVRPCI), (IMG_VOID **)&psPVRPCI, IMG_NULL,
+ "PCI Device") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSPCISetDev: Couldn't allocate PVR PCI structure"));
+ return IMG_NULL;
+ }
+
+ psPVRPCI->psPCIDev = (struct pci_dev *)pvPCICookie;
+ psPVRPCI->ePCIFlags = eFlags;
+
+ err = pci_enable_device(psPVRPCI->psPCIDev);
+ if (err != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSPCISetDev: Couldn't enable device (%d)", err));
+ return IMG_NULL;
+ }
+
+ if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_BUS_MASTER)
+ {
+ pci_set_master(psPVRPCI->psPCIDev);
+ }
+
+ if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_MSI)
+ {
+#if defined(CONFIG_PCI_MSI)
+ if (psPVRPCI->psPCIDev->device == PSB_SYS_SGX_DEV_DEVICE_ID_1 ||
+ psPVRPCI->psPCIDev->device == PSB_SYS_SGX_DEV_DEVICE_ID_2) // Disable MSI for Menlow
+ psPVRPCI->ePCIFlags &= ~HOST_PCI_INIT_FLAG_MSI;
+ else if(!psPVRPCI->psPCIDev->msi_enabled)
+ {
+ err = pci_enable_msi(psPVRPCI->psPCIDev);
+ if (err != 0)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "OSPCISetDev: Couldn't enable MSI (%d)", err));
+ psPVRPCI->ePCIFlags &= ~HOST_PCI_INIT_FLAG_MSI;
+ }
+ }
+#else
+ PVR_DPF((PVR_DBG_WARNING, "OSPCISetDev: MSI support not enabled in the kernel"));
+#endif
+ }
+
+
+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+ {
+ psPVRPCI->abPCIResourceInUse[i] = IMG_FALSE;
+ }
+
+ return (PVRSRV_PCI_DEV_HANDLE)psPVRPCI;
+}
+
+PVRSRV_PCI_DEV_HANDLE OSPCIAcquireDev(IMG_UINT16 ui16VendorID, IMG_UINT16 ui16DeviceID, HOST_PCI_INIT_FLAGS eFlags)
+{
+ struct pci_dev *psPCIDev;
+
+ psPCIDev = pci_get_device(ui16VendorID, ui16DeviceID, NULL);
+ if (psPCIDev == NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSPCIAcquireDev: Couldn't acquire device"));
+ return IMG_NULL;
+ }
+
+ return OSPCISetDev((IMG_VOID *)psPCIDev, eFlags);
+}
+
+PVRSRV_ERROR OSPCIIRQ(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 *pui32IRQ)
+{
+ PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+
+ *pui32IRQ = psPVRPCI->psPCIDev->irq;
+
+ return PVRSRV_OK;
+}
+
+enum HOST_PCI_ADDR_RANGE_FUNC
+{
+ HOST_PCI_ADDR_RANGE_FUNC_LEN,
+ HOST_PCI_ADDR_RANGE_FUNC_START,
+ HOST_PCI_ADDR_RANGE_FUNC_END,
+ HOST_PCI_ADDR_RANGE_FUNC_REQUEST,
+ HOST_PCI_ADDR_RANGE_FUNC_RELEASE
+};
+
+static IMG_UINT32 OSPCIAddrRangeFunc(enum HOST_PCI_ADDR_RANGE_FUNC eFunc,
+ PVRSRV_PCI_DEV_HANDLE hPVRPCI,
+ IMG_UINT32 ui32Index)
+{
+ PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+
+ if (ui32Index >= DEVICE_COUNT_RESOURCE)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSPCIAddrRangeFunc: Index out of range"));
+ return 0;
+
+ }
+
+ switch (eFunc)
+ {
+ case HOST_PCI_ADDR_RANGE_FUNC_LEN:
+ return pci_resource_len(psPVRPCI->psPCIDev, ui32Index);
+ case HOST_PCI_ADDR_RANGE_FUNC_START:
+ return pci_resource_start(psPVRPCI->psPCIDev, ui32Index);
+ case HOST_PCI_ADDR_RANGE_FUNC_END:
+ return pci_resource_end(psPVRPCI->psPCIDev, ui32Index);
+ case HOST_PCI_ADDR_RANGE_FUNC_REQUEST:
+ {
+ int err;
+
+ err = pci_request_region(psPVRPCI->psPCIDev, (IMG_INT)ui32Index, "PowerVR");
+ if (err != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSPCIAddrRangeFunc: pci_request_region_failed (%d)", err));
+ return 0;
+ }
+ psPVRPCI->abPCIResourceInUse[ui32Index] = IMG_TRUE;
+ return 1;
+ }
+ case HOST_PCI_ADDR_RANGE_FUNC_RELEASE:
+ if (psPVRPCI->abPCIResourceInUse[ui32Index])
+ {
+ pci_release_region(psPVRPCI->psPCIDev, (IMG_INT)ui32Index);
+ psPVRPCI->abPCIResourceInUse[ui32Index] = IMG_FALSE;
+ }
+ return 1;
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "OSPCIAddrRangeFunc: Unknown function"));
+ break;
+ }
+
+ return 0;
+}
+
+IMG_UINT32 OSPCIAddrRangeLen(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index)
+{
+ return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_LEN, hPVRPCI, ui32Index);
+}
+
+IMG_UINT32 OSPCIAddrRangeStart(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index)
+{
+ return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_START, hPVRPCI, ui32Index);
+}
+
+IMG_UINT32 OSPCIAddrRangeEnd(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index)
+{
+ return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_END, hPVRPCI, ui32Index);
+}
+
+PVRSRV_ERROR OSPCIRequestAddrRange(PVRSRV_PCI_DEV_HANDLE hPVRPCI,
+ IMG_UINT32 ui32Index)
+{
+ return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_REQUEST, hPVRPCI, ui32Index) == 0 ? PVRSRV_ERROR_PCI_CALL_FAILED : PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSPCIReleaseAddrRange(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index)
+{
+ return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_RELEASE, hPVRPCI, ui32Index) == 0 ? PVRSRV_ERROR_PCI_CALL_FAILED : PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSPCIReleaseDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI)
+{
+ PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+ int i;
+
+ PVR_TRACE(("OSPCIReleaseDev"));
+
+
+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+ {
+ if (psPVRPCI->abPCIResourceInUse[i])
+ {
+ PVR_TRACE(("OSPCIReleaseDev: Releasing Address range %d", i));
+ pci_release_region(psPVRPCI->psPCIDev, i);
+ psPVRPCI->abPCIResourceInUse[i] = IMG_FALSE;
+ }
+ }
+
+#if defined(CONFIG_PCI_MSI)
+ if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_MSI)
+ {
+ pci_disable_msi(psPVRPCI->psPCIDev);
+ }
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29))
+ if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_BUS_MASTER)
+ {
+ pci_clear_master(psPVRPCI->psPCIDev);
+ }
+#endif
+ pci_disable_device(psPVRPCI->psPCIDev);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psPVRPCI), (IMG_VOID *)psPVRPCI, IMG_NULL);
+
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSPCISuspendDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI)
+{
+ PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+ int i;
+ int err;
+
+ PVR_TRACE(("OSPCISuspendDev"));
+
+
+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+ {
+ if (psPVRPCI->abPCIResourceInUse[i])
+ {
+ pci_release_region(psPVRPCI->psPCIDev, i);
+ }
+ }
+
+ err = pci_save_state(psPVRPCI->psPCIDev);
+ if (err != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSPCISuspendDev: pci_save_state_failed (%d)", err));
+ return PVRSRV_ERROR_PCI_CALL_FAILED;
+ }
+
+ pci_disable_device(psPVRPCI->psPCIDev);
+
+ err = pci_set_power_state(psPVRPCI->psPCIDev, pci_choose_state(psPVRPCI->psPCIDev, PMSG_SUSPEND));
+ switch(err)
+ {
+ case 0:
+ break;
+ case -EIO:
+ PVR_DPF((PVR_DBG_WARNING, "OSPCISuspendDev: device doesn't support PCI PM"));
+ break;
+ case -EINVAL:
+ PVR_DPF((PVR_DBG_ERROR, "OSPCISuspendDev: can't enter requested power state"));
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "OSPCISuspendDev: pci_set_power_state failed (%d)", err));
+ break;
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSPCIResumeDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI)
+{
+ PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
+ int err;
+ int i;
+
+ PVR_TRACE(("OSPCIResumeDev"));
+
+ err = pci_set_power_state(psPVRPCI->psPCIDev, pci_choose_state(psPVRPCI->psPCIDev, PMSG_ON));
+ switch(err)
+ {
+ case 0:
+ break;
+ case -EIO:
+ PVR_DPF((PVR_DBG_WARNING, "OSPCIResumeDev: device doesn't support PCI PM"));
+ break;
+ case -EINVAL:
+ PVR_DPF((PVR_DBG_ERROR, "OSPCIResumeDev: can't enter requested power state"));
+ return PVRSRV_ERROR_UNKNOWN_POWER_STATE;
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "OSPCIResumeDev: pci_set_power_state failed (%d)", err));
+ return PVRSRV_ERROR_UNKNOWN_POWER_STATE;
+ }
+
+ pci_restore_state(psPVRPCI->psPCIDev);
+
+ err = pci_enable_device(psPVRPCI->psPCIDev);
+ if (err != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSPCIResumeDev: Couldn't enable device (%d)", err));
+ return PVRSRV_ERROR_PCI_CALL_FAILED;
+ }
+
+ if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_BUS_MASTER)
+ pci_set_master(psPVRPCI->psPCIDev);
+
+
+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+ {
+ if (psPVRPCI->abPCIResourceInUse[i])
+ {
+ err = pci_request_region(psPVRPCI->psPCIDev, i, "PowerVR");
+ if (err != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSPCIResumeDev: pci_request_region_failed (region %d, error %d)", i, err));
+ }
+ }
+
+ }
+
+ return PVRSRV_OK;
+}
+
+#endif
+
+#define OS_MAX_TIMERS 8
+
+typedef struct TIMER_CALLBACK_DATA_TAG
+{
+ IMG_BOOL bInUse;
+ PFN_TIMER_FUNC pfnTimerFunc;
+ IMG_VOID *pvData;
+ struct timer_list sTimer;
+ IMG_UINT32 ui32Delay;
+ IMG_BOOL bActive;
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+ struct work_struct sWork;
+#endif
+}TIMER_CALLBACK_DATA;
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+static struct workqueue_struct *psTimerWorkQueue;
+#endif
+
+static TIMER_CALLBACK_DATA sTimers[OS_MAX_TIMERS];
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+DEFINE_MUTEX(sTimerStructLock);
+#else
+
+static DEFINE_SPINLOCK(sTimerStructLock);
+#endif
+
+static void OSTimerCallbackBody(TIMER_CALLBACK_DATA *psTimerCBData)
+{
+ if (!psTimerCBData->bActive)
+ return;
+
+
+ psTimerCBData->pfnTimerFunc(psTimerCBData->pvData);
+
+
+ mod_timer(&psTimerCBData->sTimer, psTimerCBData->ui32Delay + jiffies);
+}
+
+
+static IMG_VOID OSTimerCallbackWrapper(IMG_UINT32 ui32Data)
+{
+ TIMER_CALLBACK_DATA *psTimerCBData = (TIMER_CALLBACK_DATA*)ui32Data;
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+ int res;
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+ res = queue_work(psTimerWorkQueue, &psTimerCBData->sWork);
+#else
+ res = schedule_work(&psTimerCBData->sWork);
+#endif
+ if (res == 0)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "OSTimerCallbackWrapper: work already queued"));
+ }
+#else
+ OSTimerCallbackBody(psTimerCBData);
+#endif
+}
+
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+static void OSTimerWorkQueueCallBack(struct work_struct *psWork)
+{
+ TIMER_CALLBACK_DATA *psTimerCBData = container_of(psWork, TIMER_CALLBACK_DATA, sWork);
+
+ OSTimerCallbackBody(psTimerCBData);
+}
+#endif
+
+IMG_HANDLE OSAddTimer(PFN_TIMER_FUNC pfnTimerFunc, IMG_VOID *pvData, IMG_UINT32 ui32MsTimeout)
+{
+ TIMER_CALLBACK_DATA *psTimerCBData;
+ IMG_UINT32 ui32i;
+#if !(defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE))
+ unsigned long ulLockFlags;
+#endif
+
+
+ if(!pfnTimerFunc)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSAddTimer: passed invalid callback"));
+ return IMG_NULL;
+ }
+
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+ mutex_lock(&sTimerStructLock);
+#else
+ spin_lock_irqsave(&sTimerStructLock, ulLockFlags);
+#endif
+ for (ui32i = 0; ui32i < OS_MAX_TIMERS; ui32i++)
+ {
+ psTimerCBData = &sTimers[ui32i];
+ if (!psTimerCBData->bInUse)
+ {
+ psTimerCBData->bInUse = IMG_TRUE;
+ break;
+ }
+ }
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+ mutex_unlock(&sTimerStructLock);
+#else
+ spin_unlock_irqrestore(&sTimerStructLock, ulLockFlags);
+#endif
+ if (ui32i >= OS_MAX_TIMERS)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSAddTimer: all timers are in use"));
+ return IMG_NULL;
+ }
+
+ psTimerCBData->pfnTimerFunc = pfnTimerFunc;
+ psTimerCBData->pvData = pvData;
+ psTimerCBData->bActive = IMG_FALSE;
+
+
+
+
+ psTimerCBData->ui32Delay = ((HZ * ui32MsTimeout) < 1000)
+ ? 1
+ : ((HZ * ui32MsTimeout) / 1000);
+
+ init_timer(&psTimerCBData->sTimer);
+
+
+
+ psTimerCBData->sTimer.function = (IMG_VOID *)OSTimerCallbackWrapper;
+ psTimerCBData->sTimer.data = (IMG_UINT32)psTimerCBData;
+
+ return (IMG_HANDLE)(ui32i + 1);
+}
+
+
+static inline TIMER_CALLBACK_DATA *GetTimerStructure(IMG_HANDLE hTimer)
+{
+ IMG_UINT32 ui32i = ((IMG_UINT32)hTimer) - 1;
+
+ PVR_ASSERT(ui32i < OS_MAX_TIMERS);
+
+ return &sTimers[ui32i];
+}
+
+PVRSRV_ERROR OSRemoveTimer (IMG_HANDLE hTimer)
+{
+ TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer);
+
+ PVR_ASSERT(psTimerCBData->bInUse);
+ PVR_ASSERT(!psTimerCBData->bActive);
+
+
+ psTimerCBData->bInUse = IMG_FALSE;
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSEnableTimer (IMG_HANDLE hTimer)
+{
+ TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer);
+
+ PVR_ASSERT(psTimerCBData->bInUse);
+ PVR_ASSERT(!psTimerCBData->bActive);
+
+
+ psTimerCBData->bActive = IMG_TRUE;
+
+
+ psTimerCBData->sTimer.expires = psTimerCBData->ui32Delay + jiffies;
+
+
+ add_timer(&psTimerCBData->sTimer);
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSDisableTimer (IMG_HANDLE hTimer)
+{
+ TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer);
+
+ PVR_ASSERT(psTimerCBData->bInUse);
+ PVR_ASSERT(psTimerCBData->bActive);
+
+
+ psTimerCBData->bActive = IMG_FALSE;
+ smp_mb();
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+ flush_workqueue(psTimerWorkQueue);
+#endif
+#if defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+ flush_scheduled_work();
+#endif
+
+
+ del_timer_sync(&psTimerCBData->sTimer);
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+
+ flush_workqueue(psTimerWorkQueue);
+#endif
+#if defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+ flush_scheduled_work();
+#endif
+
+ return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR OSEventObjectCreate(const IMG_CHAR *pszName, PVRSRV_EVENTOBJECT *psEventObject)
+{
+
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if(psEventObject)
+ {
+ if(pszName)
+ {
+
+ strncpy(psEventObject->szName, pszName, EVENTOBJNAME_MAXLENGTH);
+ }
+ else
+ {
+
+ static IMG_UINT16 ui16NameIndex = 0;
+ snprintf(psEventObject->szName, EVENTOBJNAME_MAXLENGTH, "PVRSRV_EVENTOBJECT_%d", ui16NameIndex++);
+ }
+
+ if(LinuxEventObjectListCreate(&psEventObject->hOSEventKM) != PVRSRV_OK)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSEventObjectCreate: psEventObject is not a valid pointer"));
+ eError = PVRSRV_ERROR_UNABLE_TO_CREATE_EVENT;
+ }
+
+ return eError;
+
+}
+
+
+PVRSRV_ERROR OSEventObjectDestroy(PVRSRV_EVENTOBJECT *psEventObject)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if(psEventObject)
+ {
+ if(psEventObject->hOSEventKM)
+ {
+ LinuxEventObjectListDestroy(psEventObject->hOSEventKM);
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSEventObjectDestroy: hOSEventKM is not a valid pointer"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSEventObjectDestroy: psEventObject is not a valid pointer"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return eError;
+}
+
+PVRSRV_ERROR OSEventObjectWait(IMG_HANDLE hOSEventKM)
+{
+ PVRSRV_ERROR eError;
+
+ if(hOSEventKM)
+ {
+ eError = LinuxEventObjectWait(hOSEventKM, EVENT_OBJECT_TIMEOUT_MS);
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSEventObjectWait: hOSEventKM is not a valid handle"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return eError;
+}
+
+PVRSRV_ERROR OSEventObjectOpen(PVRSRV_EVENTOBJECT *psEventObject,
+ IMG_HANDLE *phOSEvent)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if(psEventObject)
+ {
+ if(LinuxEventObjectAdd(psEventObject->hOSEventKM, phOSEvent) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectAdd: failed"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSEventObjectCreate: psEventObject is not a valid pointer"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return eError;
+}
+
+PVRSRV_ERROR OSEventObjectClose(PVRSRV_EVENTOBJECT *psEventObject,
+ IMG_HANDLE hOSEventKM)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if(psEventObject)
+ {
+ if(LinuxEventObjectDelete(psEventObject->hOSEventKM, hOSEventKM) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "LinuxEventObjectDelete: failed"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSEventObjectDestroy: psEventObject is not a valid pointer"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return eError;
+
+}
+
+PVRSRV_ERROR OSEventObjectSignal(IMG_HANDLE hOSEventKM)
+{
+ PVRSRV_ERROR eError;
+
+ if(hOSEventKM)
+ {
+ eError = LinuxEventObjectSignal(hOSEventKM);
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSEventObjectSignal: hOSEventKM is not a valid handle"));
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return eError;
+}
+
+IMG_BOOL OSProcHasPrivSrvInit(IMG_VOID)
+{
+ /*
+ * Return true here so that we can run X as a non-root user.
+ */
+ return IMG_TRUE;
+}
+
+PVRSRV_ERROR OSCopyToUser(IMG_PVOID pvProcess,
+ IMG_VOID *pvDest,
+ IMG_VOID *pvSrc,
+ IMG_UINT32 ui32Bytes)
+{
+ PVR_UNREFERENCED_PARAMETER(pvProcess);
+
+ if(copy_to_user(pvDest, pvSrc, ui32Bytes)==0)
+ return PVRSRV_OK;
+ else
+ return PVRSRV_ERROR_FAILED_TO_COPY_VIRT_MEMORY;
+}
+
+PVRSRV_ERROR OSCopyFromUser( IMG_PVOID pvProcess,
+ IMG_VOID *pvDest,
+ IMG_VOID *pvSrc,
+ IMG_UINT32 ui32Bytes)
+{
+ PVR_UNREFERENCED_PARAMETER(pvProcess);
+
+ if(copy_from_user(pvDest, pvSrc, ui32Bytes)==0)
+ return PVRSRV_OK;
+ else
+ return PVRSRV_ERROR_FAILED_TO_COPY_VIRT_MEMORY;
+}
+
+IMG_BOOL OSAccessOK(IMG_VERIFY_TEST eVerification, IMG_VOID *pvUserPtr, IMG_UINT32 ui32Bytes)
+{
+ IMG_INT linuxType;
+
+ if (eVerification == PVR_VERIFY_READ)
+ {
+ linuxType = VERIFY_READ;
+ }
+ else
+ {
+ PVR_ASSERT(eVerification == PVR_VERIFY_WRITE);
+ linuxType = VERIFY_WRITE;
+ }
+
+ return access_ok(linuxType, pvUserPtr, ui32Bytes);
+}
+
+typedef enum _eWrapMemType_
+{
+ WRAP_TYPE_NULL = 0,
+ WRAP_TYPE_GET_USER_PAGES,
+ WRAP_TYPE_FIND_VMA
+} eWrapMemType;
+
+typedef struct _sWrapMemInfo_
+{
+ eWrapMemType eType;
+ IMG_INT iNumPages;
+ IMG_INT iNumPagesMapped;
+ struct page **ppsPages;
+ IMG_SYS_PHYADDR *psPhysAddr;
+ IMG_INT iPageOffset;
+#if defined(DEBUG)
+ IMG_UINT32 ulStartAddr;
+ IMG_UINT32 ulBeyondEndAddr;
+ struct vm_area_struct *psVMArea;
+#endif
+} sWrapMemInfo;
+
+
+static IMG_BOOL CPUVAddrToPFN(struct vm_area_struct *psVMArea, IMG_UINT32 ulCPUVAddr, IMG_UINT32 *pulPFN, struct page **ppsPage)
+{
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10))
+ pgd_t *psPGD;
+ pud_t *psPUD;
+ pmd_t *psPMD;
+ pte_t *psPTE;
+ struct mm_struct *psMM = psVMArea->vm_mm;
+ spinlock_t *psPTLock;
+ IMG_BOOL bRet = IMG_FALSE;
+
+ *pulPFN = 0;
+ *ppsPage = NULL;
+
+ psPGD = pgd_offset(psMM, ulCPUVAddr);
+ if (pgd_none(*psPGD) || pgd_bad(*psPGD))
+ return bRet;
+
+ psPUD = pud_offset(psPGD, ulCPUVAddr);
+ if (pud_none(*psPUD) || pud_bad(*psPUD))
+ return bRet;
+
+ psPMD = pmd_offset(psPUD, ulCPUVAddr);
+ if (pmd_none(*psPMD) || pmd_bad(*psPMD))
+ return bRet;
+
+ psPTE = (pte_t *)pte_offset_map_lock(psMM, psPMD, ulCPUVAddr, &psPTLock);
+
+ if ((pte_none(*psPTE) == 0) && (pte_present(*psPTE) != 0) && (pte_write(*psPTE) != 0))
+ {
+ *pulPFN = pte_pfn(*psPTE);
+ bRet = IMG_TRUE;
+
+ if (pfn_valid(*pulPFN))
+ {
+ *ppsPage = pfn_to_page(*pulPFN);
+
+ get_page(*ppsPage);
+ }
+ }
+
+ pte_unmap_unlock(psPTE, psPTLock);
+
+ return bRet;
+#else
+ return IMG_FALSE;
+#endif
+}
+
+PVRSRV_ERROR OSReleasePhysPageAddr(IMG_HANDLE hOSWrapMem)
+{
+ sWrapMemInfo *psInfo = (sWrapMemInfo *)hOSWrapMem;
+ IMG_INT i;
+
+ if (psInfo == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_WARNING,
+ "OSReleasePhysPageAddr: called with null wrap handle"));
+ return PVRSRV_OK;
+ }
+
+ switch (psInfo->eType)
+ {
+ case WRAP_TYPE_NULL:
+ {
+ PVR_DPF((PVR_DBG_WARNING,
+ "OSReleasePhysPageAddr: called with wrap type WRAP_TYPE_NULL"));
+ break;
+ }
+ case WRAP_TYPE_GET_USER_PAGES:
+ {
+ for (i = 0; i < psInfo->iNumPagesMapped; i++)
+ {
+ struct page *psPage = psInfo->ppsPages[i];
+
+ PVR_ASSERT(psPage != NULL);
+
+
+ if (psInfo->iNumPagesMapped == psInfo->iNumPages)
+ {
+ if (!PageReserved(psPage))
+ {
+ SetPageDirty(psPage);
+ }
+ }
+ page_cache_release(psPage);
+ }
+ break;
+ }
+ case WRAP_TYPE_FIND_VMA:
+ {
+ for (i = 0; i < psInfo->iNumPages; i++)
+ {
+ if (psInfo->ppsPages[i] != IMG_NULL)
+ {
+ put_page(psInfo->ppsPages[i]);
+ }
+ }
+ break;
+ }
+ default:
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSReleasePhysPageAddr: Unknown wrap type (%d)", psInfo->eType));
+ return PVRSRV_ERROR_INVALID_WRAP_TYPE;
+ }
+ }
+
+ if (psInfo->ppsPages != IMG_NULL)
+ {
+ kfree(psInfo->ppsPages);
+ }
+
+ if (psInfo->psPhysAddr != IMG_NULL)
+ {
+ kfree(psInfo->psPhysAddr);
+ }
+
+ kfree(psInfo);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID *pvCPUVAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_SYS_PHYADDR *psSysPAddr,
+ IMG_HANDLE *phOSWrapMem)
+{
+ IMG_UINT32 ulStartAddrOrig = (IMG_UINT32) pvCPUVAddr;
+ IMG_UINT32 ulAddrRangeOrig = (IMG_UINT32) ui32Bytes;
+ IMG_UINT32 ulBeyondEndAddrOrig = ulStartAddrOrig + ulAddrRangeOrig;
+ IMG_UINT32 ulStartAddr;
+ IMG_UINT32 ulAddrRange;
+ IMG_UINT32 ulBeyondEndAddr;
+ IMG_UINT32 ulAddr;
+ IMG_INT i;
+ struct vm_area_struct *psVMArea;
+ sWrapMemInfo *psInfo = NULL;
+ IMG_BOOL bHavePageStructs = IMG_FALSE;
+ IMG_BOOL bHaveNoPageStructs = IMG_FALSE;
+ IMG_BOOL bPFNMismatch = IMG_FALSE;
+ IMG_BOOL bMMapSemHeld = IMG_FALSE;
+ PVRSRV_ERROR eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+
+ ulStartAddr = ulStartAddrOrig & PAGE_MASK;
+ ulBeyondEndAddr = PAGE_ALIGN(ulBeyondEndAddrOrig);
+ ulAddrRange = ulBeyondEndAddr - ulStartAddr;
+
+
+ if (ulBeyondEndAddr <= ulStartAddr)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: Invalid address range (start %x, length %x)",
+ ulStartAddrOrig, ulAddrRangeOrig));
+ goto error;
+ }
+
+
+ psInfo = kmalloc(sizeof(*psInfo), GFP_KERNEL);
+ if (psInfo == NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: Couldn't allocate information structure"));
+ goto error;
+ }
+ memset(psInfo, 0, sizeof(*psInfo));
+
+#if defined(DEBUG)
+ psInfo->ulStartAddr = ulStartAddrOrig;
+ psInfo->ulBeyondEndAddr = ulBeyondEndAddrOrig;
+#endif
+
+ psInfo->iNumPages = (IMG_INT)(ulAddrRange >> PAGE_SHIFT);
+ psInfo->iPageOffset = (IMG_INT)(ulStartAddrOrig & ~PAGE_MASK);
+
+
+ psInfo->psPhysAddr = kmalloc((size_t)psInfo->iNumPages * sizeof(*psInfo->psPhysAddr), GFP_KERNEL);
+ if (psInfo->psPhysAddr == NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: Couldn't allocate page array"));
+ goto error;
+ }
+ memset(psInfo->psPhysAddr, 0, (size_t)psInfo->iNumPages * sizeof(*psInfo->psPhysAddr));
+
+
+ psInfo->ppsPages = kmalloc((size_t)psInfo->iNumPages * sizeof(*psInfo->ppsPages), GFP_KERNEL);
+ if (psInfo->ppsPages == NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: Couldn't allocate page array"));
+ goto error;
+ }
+ memset(psInfo->ppsPages, 0, (size_t)psInfo->iNumPages * sizeof(*psInfo->ppsPages));
+
+
+ eError = PVRSRV_ERROR_BAD_MAPPING;
+
+
+ psInfo->eType = WRAP_TYPE_GET_USER_PAGES;
+
+
+ down_read(¤t->mm->mmap_sem);
+ bMMapSemHeld = IMG_TRUE;
+
+
+ psInfo->iNumPagesMapped = get_user_pages(current, current->mm, ulStartAddr, psInfo->iNumPages, 1, 0, psInfo->ppsPages, NULL);
+
+ if (psInfo->iNumPagesMapped >= 0)
+ {
+
+ if (psInfo->iNumPagesMapped != psInfo->iNumPages)
+ {
+ PVR_TRACE(("OSAcquirePhysPageAddr: Couldn't map all the pages needed (wanted: %d, got %d)", psInfo->iNumPages, psInfo->iNumPagesMapped));
+
+ goto error;
+ }
+
+
+ for (i = 0; i < psInfo->iNumPages; i++)
+ {
+ IMG_CPU_PHYADDR CPUPhysAddr;
+ IMG_UINT32 ulPFN;
+
+ ulPFN = page_to_pfn(psInfo->ppsPages[i]);
+ CPUPhysAddr.uiAddr = ulPFN << PAGE_SHIFT;
+ if ((CPUPhysAddr.uiAddr >> PAGE_SHIFT) != ulPFN)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: Page frame number out of range (%x)", ulPFN));
+
+ goto error;
+ }
+ psInfo->psPhysAddr[i] = SysCpuPAddrToSysPAddr(CPUPhysAddr);
+ psSysPAddr[i] = psInfo->psPhysAddr[i];
+
+ }
+
+ goto exit;
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE, "OSAcquirePhysPageAddr: get_user_pages failed (%d), using CPU page table", psInfo->iNumPagesMapped));
+
+
+ psInfo->eType = WRAP_TYPE_NULL;
+ psInfo->iNumPagesMapped = 0;
+ memset(psInfo->ppsPages, 0, (size_t)psInfo->iNumPages * sizeof(*psInfo->ppsPages));
+
+
+
+ psInfo->eType = WRAP_TYPE_FIND_VMA;
+
+ psVMArea = find_vma(current->mm, ulStartAddrOrig);
+ if (psVMArea == NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: Couldn't find memory region containing start address %x", ulStartAddrOrig));
+
+ goto error;
+ }
+#if defined(DEBUG)
+ psInfo->psVMArea = psVMArea;
+#endif
+
+
+ if (ulStartAddrOrig < psVMArea->vm_start)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: Start address %x is outside of the region returned by find_vma", ulStartAddrOrig));
+ goto error;
+ }
+
+
+ if (ulBeyondEndAddrOrig > psVMArea->vm_end)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: End address %x is outside of the region returned by find_vma", ulBeyondEndAddrOrig));
+ goto error;
+ }
+
+
+ if ((psVMArea->vm_flags & (VM_IO | VM_RESERVED)) != (VM_IO | VM_RESERVED))
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: Memory region does not represent memory mapped I/O (VMA flags: 0x%lx)", psVMArea->vm_flags));
+ goto error;
+ }
+
+
+ if ((psVMArea->vm_flags & (VM_READ | VM_WRITE)) != (VM_READ | VM_WRITE))
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: No read/write access to memory region (VMA flags: 0x%lx)", psVMArea->vm_flags));
+ goto error;
+ }
+
+ for (ulAddr = ulStartAddrOrig, i = 0; ulAddr < ulBeyondEndAddrOrig; ulAddr += PAGE_SIZE, i++)
+ {
+ IMG_CPU_PHYADDR CPUPhysAddr;
+ IMG_UINT32 ulPFN = 0;
+
+ PVR_ASSERT(i < psInfo->iNumPages);
+
+ if (!CPUVAddrToPFN(psVMArea, ulAddr, &ulPFN, &psInfo->ppsPages[i]))
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: Invalid CPU virtual address"));
+
+ goto error;
+ }
+ if (psInfo->ppsPages[i] == NULL)
+ {
+
+ bHaveNoPageStructs = IMG_TRUE;
+
+#if defined(VM_PFNMAP)
+ if ((psVMArea->vm_flags & VM_PFNMAP) != 0)
+ {
+ IMG_UINT32 ulPFNRaw = ((ulAddr - psVMArea->vm_start) >> PAGE_SHIFT) + psVMArea->vm_pgoff;
+
+ if (ulPFNRaw != ulPFN)
+ {
+ bPFNMismatch = IMG_TRUE;
+ }
+ }
+#endif
+ }
+ else
+ {
+ bHavePageStructs = IMG_TRUE;
+
+ psInfo->iNumPagesMapped++;
+
+ PVR_ASSERT(ulPFN == page_to_pfn(psInfo->ppsPages[i]));
+ }
+
+ CPUPhysAddr.uiAddr = ulPFN << PAGE_SHIFT;
+ if ((CPUPhysAddr.uiAddr >> PAGE_SHIFT) != ulPFN)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: Page frame number out of range (%x)", ulPFN));
+
+ goto error;
+ }
+
+ psInfo->psPhysAddr[i] = SysCpuPAddrToSysPAddr(CPUPhysAddr);
+ psSysPAddr[i] = psInfo->psPhysAddr[i];
+ }
+ PVR_ASSERT(i == psInfo->iNumPages);
+
+#if defined(VM_MIXEDMAP)
+ if ((psVMArea->vm_flags & VM_MIXEDMAP) != 0)
+ {
+ goto exit;
+ }
+#endif
+
+ if (bHavePageStructs && bHaveNoPageStructs)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: Region is VM_MIXEDMAP, but isn't marked as such"));
+ goto error;
+ }
+
+ if (!bHaveNoPageStructs)
+ {
+
+ goto exit;
+ }
+
+#if defined(VM_PFNMAP)
+ if ((psVMArea->vm_flags & VM_PFNMAP) == 0)
+#endif
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: Region is VM_PFNMAP, but isn't marked as such"));
+ goto error;
+ }
+
+ if (bPFNMismatch)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "OSAcquirePhysPageAddr: PFN calculation mismatch for VM_PFNMAP region"));
+ goto error;
+ }
+
+exit:
+ PVR_ASSERT(bMMapSemHeld);
+ up_read(¤t->mm->mmap_sem);
+
+
+ *phOSWrapMem = (IMG_HANDLE)psInfo;
+
+ if (bHaveNoPageStructs)
+ {
+ PVR_DPF((PVR_DBG_WARNING,
+ "OSAcquirePhysPageAddr: Region contains pages which can't be locked down (no page structures)"));
+ }
+
+ PVR_ASSERT(psInfo->eType != 0);
+
+#if 0
+
+
+ OSCleanCPUCacheRangeKM(pvCPUVAddr, (IMG_VOID *)((IMG_CHAR *)pvCPUVAddr + ui32Bytes));
+#endif
+
+ return PVRSRV_OK;
+
+error:
+ if (bMMapSemHeld)
+ {
+ up_read(¤t->mm->mmap_sem);
+ }
+ OSReleasePhysPageAddr((IMG_HANDLE)psInfo);
+
+ PVR_ASSERT(eError != PVRSRV_OK);
+
+ return eError;
+}
+
+typedef void (*InnerCacheOp_t)(const void *pvStart, const void *pvEnd);
+typedef void (*OuterCacheOp_t)(unsigned long ulStart, unsigned long ulEnd);
+
+#if defined(CONFIG_OUTER_CACHE)
+
+typedef unsigned long (*MemAreaToPhys_t)(LinuxMemArea *psLinuxMemArea,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32PageNumOffset,
+ IMG_UINT32 ui32PageNum);
+
+static unsigned long VMallocAreaToPhys(LinuxMemArea *psLinuxMemArea,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32PageNumOffset,
+ IMG_UINT32 ui32PageNum)
+{
+ return vmalloc_to_pfn(pvRangeAddrStart + ui32PageNum * PAGE_SIZE) << PAGE_SHIFT;
+}
+
+static unsigned long ExternalKVAreaToPhys(LinuxMemArea *psLinuxMemArea,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32PageNumOffset,
+ IMG_UINT32 ui32PageNum)
+{
+ IMG_SYS_PHYADDR SysPAddr;
+ IMG_CPU_PHYADDR CpuPAddr;
+ SysPAddr = psLinuxMemArea->uData.sExternalKV.uPhysAddr.pSysPhysAddr[ui32PageNumOffset + ui32PageNum];
+ CpuPAddr = SysSysPAddrToCpuPAddr(SysPAddr);
+ return CpuPAddr.uiAddr;
+}
+
+static unsigned long AllocPagesAreaToPhys(LinuxMemArea *psLinuxMemArea,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32PageNumOffset,
+ IMG_UINT32 ui32PageNum)
+{
+ struct page *pPage;
+ pPage = psLinuxMemArea->uData.sPageList.pvPageList[ui32PageNumOffset + ui32PageNum];
+ return page_to_pfn(pPage) << PAGE_SHIFT;
+}
+
+#endif
+
+#ifndef __mips__
+static
+IMG_VOID *FindMMapBaseVAddr(struct list_head *psMMapOffsetStructList,
+ IMG_VOID *pvRangeAddrStart, IMG_UINT32 ui32Length)
+{
+ PKV_OFFSET_STRUCT psOffsetStruct;
+ IMG_VOID *pvMinVAddr;
+
+
+ list_for_each_entry(psOffsetStruct, psMMapOffsetStructList, sAreaItem)
+ {
+ if(OSGetCurrentProcessIDKM() != psOffsetStruct->ui32PID)
+ continue;
+
+ pvMinVAddr = (IMG_VOID *)psOffsetStruct->ui32UserVAddr;
+
+
+ if(pvRangeAddrStart >= pvMinVAddr &&
+ ui32Length <= psOffsetStruct->ui32RealByteSize)
+ return pvMinVAddr;
+ }
+
+ return IMG_NULL;
+}
+
+static
+IMG_BOOL CheckExecuteCacheOp(IMG_HANDLE hOSMemHandle,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32Length,
+ InnerCacheOp_t pfnInnerCacheOp,
+ OuterCacheOp_t pfnOuterCacheOp)
+{
+ LinuxMemArea *psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+ IMG_UINT32 ui32AreaLength, ui32AreaOffset = 0;
+ struct list_head *psMMapOffsetStructList;
+ IMG_VOID *pvMinVAddr;
+
+#if defined(CONFIG_OUTER_CACHE)
+ MemAreaToPhys_t pfnMemAreaToPhys = IMG_NULL;
+ IMG_UINT32 ui32PageNumOffset = 0;
+#endif
+
+ PVR_ASSERT(psLinuxMemArea != IMG_NULL);
+
+ ui32AreaLength = psLinuxMemArea->ui32ByteSize;
+ psMMapOffsetStructList = &psLinuxMemArea->sMMapOffsetStructList;
+
+ PVR_ASSERT(ui32Length <= ui32AreaLength);
+
+ if(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC)
+ {
+ ui32AreaOffset = psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset;
+ psLinuxMemArea = psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea;
+ }
+
+
+ PVR_ASSERT(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC);
+
+ switch(psLinuxMemArea->eAreaType)
+ {
+ case LINUX_MEM_AREA_VMALLOC:
+ {
+ if(is_vmalloc_addr(pvRangeAddrStart))
+ {
+ pvMinVAddr = psLinuxMemArea->uData.sVmalloc.pvVmallocAddress + ui32AreaOffset;
+
+
+ if(pvRangeAddrStart < pvMinVAddr)
+ goto err_blocked;
+
+ pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
+ }
+ else
+ {
+
+
+
+ pvMinVAddr = FindMMapBaseVAddr(psMMapOffsetStructList,
+ pvRangeAddrStart, ui32Length);
+ if(!pvMinVAddr)
+ goto err_blocked;
+
+ pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
+
+#if defined(CONFIG_OUTER_CACHE)
+
+ pvRangeAddrStart = psLinuxMemArea->uData.sVmalloc.pvVmallocAddress +
+ (ui32AreaOffset & PAGE_MASK) + (pvRangeAddrStart - pvMinVAddr);
+ }
+
+ pfnMemAreaToPhys = VMallocAreaToPhys;
+#else
+ }
+#endif
+ break;
+ }
+
+ case LINUX_MEM_AREA_EXTERNAL_KV:
+ {
+
+ if (psLinuxMemArea->uData.sExternalKV.bPhysContig == IMG_TRUE)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "%s: Attempt to flush contiguous external memory", __func__));
+
+ goto err_blocked;
+ }
+
+
+ if (psLinuxMemArea->uData.sExternalKV.pvExternalKV != IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "%s: Attempt to flush external memory with a kernel virtual address", __func__));
+
+ goto err_blocked;
+ }
+
+
+
+ pvMinVAddr = FindMMapBaseVAddr(psMMapOffsetStructList,
+ pvRangeAddrStart, ui32Length);
+ if(!pvMinVAddr)
+ goto err_blocked;
+
+ pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
+
+#if defined(CONFIG_OUTER_CACHE)
+ ui32PageNumOffset = ((ui32AreaOffset & PAGE_MASK) + (pvRangeAddrStart - pvMinVAddr)) >> PAGE_SHIFT;
+ pfnMemAreaToPhys = ExternalKVAreaToPhys;
+#endif
+ break;
+ }
+
+ case LINUX_MEM_AREA_ALLOC_PAGES:
+ {
+ pvMinVAddr = FindMMapBaseVAddr(psMMapOffsetStructList,
+ pvRangeAddrStart, ui32Length);
+ if(!pvMinVAddr)
+ goto err_blocked;
+
+ pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
+
+#if defined(CONFIG_OUTER_CACHE)
+ ui32PageNumOffset = ((ui32AreaOffset & PAGE_MASK) + (pvRangeAddrStart - pvMinVAddr)) >> PAGE_SHIFT;
+ pfnMemAreaToPhys = AllocPagesAreaToPhys;
+#endif
+ break;
+ }
+
+ default:
+ PVR_DBG_BREAK;
+ }
+
+#if defined(CONFIG_OUTER_CACHE)
+ PVR_ASSERT(pfnMemAreaToPhys != IMG_NULL);
+
+
+ {
+ unsigned long ulStart, ulEnd, ulLength, ulStartOffset, ulEndOffset;
+ IMG_UINT32 i, ui32NumPages;
+
+
+ ulLength = (unsigned long)ui32Length;
+ ulStartOffset = ((unsigned long)pvRangeAddrStart) & (PAGE_SIZE - 1);
+ ulEndOffset = ((unsigned long)pvRangeAddrStart + ulLength) & (PAGE_SIZE - 1);
+
+
+ ui32NumPages = (ulStartOffset + ulLength + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+ for(i = 0; i < ui32NumPages; i++)
+ {
+ ulStart = pfnMemAreaToPhys(psLinuxMemArea, pvRangeAddrStart,
+ ui32PageNumOffset, i);
+ ulEnd = ulStart + PAGE_SIZE;
+
+ if(i == ui32NumPages - 1 && ulEndOffset != 0)
+ ulEnd = ulStart + ulEndOffset;
+
+ if(i == 0)
+ ulStart += ulStartOffset;
+
+ pfnOuterCacheOp(ulStart, ulEnd);
+ }
+ }
+#endif
+
+ return IMG_TRUE;
+
+err_blocked:
+ PVR_DPF((PVR_DBG_WARNING, "%s: Blocked cache op on virtual range "
+ "%p-%p (type %d)", __func__,
+ pvRangeAddrStart, pvRangeAddrStart + ui32Length,
+ psLinuxMemArea->eAreaType));
+ return IMG_FALSE;
+}
+
+#endif
+
+#if defined(__i386__)
+
+#define ROUND_UP(x,a) (((x) + (a) - 1) & ~((a) - 1))
+
+static void per_cpu_cache_flush(void *arg)
+{
+ PVR_UNREFERENCED_PARAMETER(arg);
+ wbinvd();
+}
+
+static void x86_flush_cache_range(const void *pvStart, const void *pvEnd)
+{
+ IMG_BYTE *pbStart = (IMG_BYTE *)pvStart;
+ IMG_BYTE *pbEnd = (IMG_BYTE *)pvEnd;
+ IMG_BYTE *pbBase;
+
+ pbEnd = (IMG_BYTE *)ROUND_UP((IMG_UINTPTR_T)pbEnd,
+ boot_cpu_data.x86_clflush_size);
+
+ mb();
+ for(pbBase = pbStart; pbBase < pbEnd; pbBase += boot_cpu_data.x86_clflush_size)
+ clflush(pbBase);
+ mb();
+}
+
+IMG_VOID OSCleanCPUCacheKM(IMG_VOID)
+{
+
+ ON_EACH_CPU(per_cpu_cache_flush, NULL, 1);
+}
+
+IMG_VOID OSFlushCPUCacheKM(IMG_VOID)
+{
+ ON_EACH_CPU(per_cpu_cache_flush, NULL, 1);
+}
+
+IMG_BOOL OSFlushCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32Length)
+{
+
+ return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
+ x86_flush_cache_range, IMG_NULL);
+}
+
+IMG_BOOL OSCleanCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32Length)
+{
+
+ return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
+ x86_flush_cache_range, IMG_NULL);
+}
+
+IMG_BOOL OSInvalidateCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32Length)
+{
+
+ return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
+ x86_flush_cache_range, IMG_NULL);
+}
+
+#else
+
+#if defined(__arm__)
+
+static void per_cpu_cache_flush(void *arg)
+{
+ PVR_UNREFERENCED_PARAMETER(arg);
+ flush_cache_all();
+}
+
+IMG_VOID OSCleanCPUCacheKM(IMG_VOID)
+{
+
+ ON_EACH_CPU(per_cpu_cache_flush, NULL, 1);
+#if defined(CONFIG_OUTER_CACHE) && !defined(PVR_NO_FULL_CACHE_OPS)
+ outer_clean_all();
+#endif
+}
+
+IMG_VOID OSFlushCPUCacheKM(IMG_VOID)
+{
+ ON_EACH_CPU(per_cpu_cache_flush, NULL, 1);
+#if defined(CONFIG_OUTER_CACHE) && !defined(PVR_NO_FULL_CACHE_OPS)
+ outer_flush_all();
+#endif
+}
+
+IMG_BOOL OSFlushCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32Length)
+{
+ return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
+ dmac_flush_range, outer_flush_range);
+}
+
+IMG_BOOL OSCleanCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32Length)
+{
+ return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
+ dmac_clean_range, outer_clean_range);
+}
+
+IMG_BOOL OSInvalidateCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32Length)
+{
+ return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
+ dmac_inv_range, outer_inv_range);
+}
+
+#else
+
+#error "Implement CPU cache flush/clean/invalidate primitives for this CPU!"
+
+#endif
+
+#endif
+
+PVRSRV_ERROR PVROSFuncInit(IMG_VOID)
+{
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+ {
+ psTimerWorkQueue = create_workqueue("pvr_timer");
+ if (psTimerWorkQueue == NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: couldn't create timer workqueue", __FUNCTION__));
+ return PVRSRV_ERROR_UNABLE_TO_CREATE_THREAD;
+
+ }
+ }
+#endif
+
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
+ {
+ IMG_UINT32 ui32i;
+
+ for (ui32i = 0; ui32i < OS_MAX_TIMERS; ui32i++)
+ {
+ TIMER_CALLBACK_DATA *psTimerCBData = &sTimers[ui32i];
+
+ INIT_WORK(&psTimerCBData->sWork, OSTimerWorkQueueCallBack);
+ }
+ }
+#endif
+ return PVRSRV_OK;
+}
+
+IMG_VOID PVROSFuncDeInit(IMG_VOID)
+{
+#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
+ if (psTimerWorkQueue != NULL)
+ {
+ destroy_workqueue(psTimerWorkQueue);
+ }
+#endif
+}
+#ifdef PVRSRV_OS_MEM_INFO
+IMG_VOID OSGetMemoryInfo(PVRSRV_MEM_INFO * psMemInfo)
+{
+ struct sysinfo si;
+ long cached;
+ si_meminfo(&si);
+ cached = global_page_state(NR_FILE_PAGES);
+ psMemInfo->ui32FreeMem = (cached + si.freeram) << PAGE_SHIFT;
+ psMemInfo->ui32TotalMem = si.totalram;
+}
+#endif
--- /dev/null
+/**********************************************************************
+ *
+ * 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 "services_headers.h"
+#include "osperproc.h"
+
+#include "env_perproc.h"
+#include "proc.h"
+
+extern IMG_UINT32 gui32ReleasePID;
+
+PVRSRV_ERROR OSPerProcessPrivateDataInit(IMG_HANDLE *phOsPrivateData)
+{
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hBlockAlloc;
+ PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc;
+
+ eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_ENV_PER_PROCESS_DATA),
+ phOsPrivateData,
+ &hBlockAlloc,
+ "Environment per Process Data");
+
+ if (eError != PVRSRV_OK)
+ {
+ *phOsPrivateData = IMG_NULL;
+
+ PVR_DPF((PVR_DBG_ERROR, "%s: OSAllocMem failed (%d)", __FUNCTION__, eError));
+ return eError;
+ }
+
+ psEnvPerProc = (PVRSRV_ENV_PER_PROCESS_DATA *)*phOsPrivateData;
+ OSMemSet(psEnvPerProc, 0, sizeof(*psEnvPerProc));
+
+ psEnvPerProc->hBlockAlloc = hBlockAlloc;
+
+
+ LinuxMMapPerProcessConnect(psEnvPerProc);
+
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+
+ INIT_LIST_HEAD(&psEnvPerProc->sDRMAuthListHead);
+#endif
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSPerProcessPrivateDataDeInit(IMG_HANDLE hOsPrivateData)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc;
+
+ if (hOsPrivateData == IMG_NULL)
+ {
+ return PVRSRV_OK;
+ }
+
+ psEnvPerProc = (PVRSRV_ENV_PER_PROCESS_DATA *)hOsPrivateData;
+
+
+ LinuxMMapPerProcessDisconnect(psEnvPerProc);
+
+
+ RemovePerProcessProcDir(psEnvPerProc);
+
+ eError = OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_ENV_PER_PROCESS_DATA),
+ hOsPrivateData,
+ psEnvPerProc->hBlockAlloc);
+
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: OSFreeMem failed (%d)", __FUNCTION__, eError));
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSPerProcessSetHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase)
+{
+ return LinuxMMapPerProcessHandleOptions(psHandleBase);
+}
+
+IMG_HANDLE LinuxTerminatingProcessPrivateData(IMG_VOID)
+{
+ if(!gui32ReleasePID)
+ return NULL;
+ return PVRSRVPerProcessPrivateData(gui32ReleasePID);
+}
--- /dev/null
+/*
+ * Copyright (c) 2011, Intel Corporation.
+ *
+ * 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 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.
+ *
+ * Authors:
+ * Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
+ * Pauli Nieminen <pauli.nieminen@intel.com>
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+
+#include "ossync.h"
+#include "servicesint.h"
+
+DEFINE_SPINLOCK(sync_lock);
+LIST_HEAD(sync_list);
+
+typedef void (*callback_t)(void *);
+
+struct pending_sync {
+ PVRSRV_KERNEL_SYNC_INFO *sync_info;
+ int pending_read_ops;
+ int pending_write_ops;
+ int flags;
+ callback_t callback;
+ void *user_data;
+
+ struct list_head list;
+};
+
+/* Returns 0 if the callback was successfully registered.
+ * Returns a negative value on error.
+ */
+int
+PVRSRVCallbackOnSync(PVRSRV_KERNEL_SYNC_INFO *sync_info, int flags,
+ callback_t callback, void *user_data)
+{
+ struct pending_sync *pending_sync;
+ unsigned long lock_flags;
+
+ /* If the object is already in sync, don't add it to the list */
+ if ((!(flags & PVRSRV_SYNC_READ)
+ || (sync_info->psSyncData->ui32ReadOpsPending
+ <= sync_info->psSyncData->ui32ReadOpsComplete))
+ && (!(flags & PVRSRV_SYNC_WRITE)
+ || (sync_info->psSyncData->ui32WriteOpsPending
+ <= sync_info->psSyncData->ui32WriteOpsComplete))) {
+ callback(user_data);
+ return 0;
+ }
+
+ pending_sync = kmalloc(sizeof *pending_sync, GFP_KERNEL);
+ if (!pending_sync)
+ return -ENOMEM;
+
+ pending_sync->sync_info = sync_info;
+ pending_sync->pending_read_ops = sync_info->psSyncData->ui32ReadOpsPending;
+ pending_sync->pending_write_ops = sync_info->psSyncData->ui32WriteOpsPending;
+ pending_sync->flags = flags;
+ pending_sync->callback = callback;
+ pending_sync->user_data = user_data;
+
+ spin_lock_irqsave(&sync_lock, lock_flags);
+ list_add_tail(&pending_sync->list, &sync_list);
+ spin_unlock_irqrestore(&sync_lock, lock_flags);
+
+ return 0;
+}
+
+void
+PVRSRVCheckPendingSyncs()
+{
+ struct pending_sync *ps, *tmp;
+ int read_ops_done, write_ops_done;
+ int sync_read, sync_write;
+ unsigned long flags;
+
+ spin_lock_irqsave(&sync_lock, flags);
+
+ list_for_each_entry_safe(ps, tmp, &sync_list, list) {
+ sync_read = (ps->flags & PVRSRV_SYNC_READ) != 0;
+ read_ops_done = ps->sync_info->psSyncData->ui32ReadOpsComplete;
+
+ sync_write = (ps->flags & PVRSRV_SYNC_WRITE) != 0;
+ write_ops_done = ps->sync_info->psSyncData->ui32WriteOpsComplete;
+
+ if ((!sync_read || ps->pending_read_ops <= read_ops_done)
+ && (!sync_write || ps->pending_write_ops <= write_ops_done)) {
+ ps->callback(ps->user_data);
+ list_del(&ps->list);
+ kfree(ps);
+ }
+ }
+
+ spin_unlock_irqrestore(&sync_lock, flags);
+}
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#if defined (SUPPORT_SGX) || defined (SUPPORT_VGX)
+#if defined (PDUMP)
+
+#include <asm/atomic.h>
+#include <stdarg.h>
+#if defined (SUPPORT_SGX)
+#include "sgxdefs.h"
+#endif
+#include "services_headers.h"
+
+#include "pvrversion.h"
+#include "pvr_debug.h"
+
+#include "dbgdrvif.h"
+#if defined (SUPPORT_SGX)
+#include "sgxmmu.h"
+#endif
+#include "mm.h"
+#include "pdump_km.h"
+#include "pdump_int.h"
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+
+static IMG_BOOL PDumpWriteString2 (IMG_CHAR * pszString, IMG_UINT32 ui32Flags);
+static IMG_BOOL PDumpWriteILock (PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32Count, IMG_UINT32 ui32Flags);
+static IMG_VOID DbgSetFrame (PDBG_STREAM psStream, IMG_UINT32 ui32Frame);
+static IMG_VOID DbgSetMarker (PDBG_STREAM psStream, IMG_UINT32 ui32Marker);
+
+#define PDUMP_DATAMASTER_PIXEL (1)
+#define PDUMP_DATAMASTER_EDM (3)
+
+#define MAX_FILE_SIZE 0x40000000
+
+static atomic_t gsPDumpSuspended = ATOMIC_INIT(0);
+
+static PDBGKM_SERVICE_TABLE gpfnDbgDrv = IMG_NULL;
+
+
+
+IMG_CHAR *pszStreamName[PDUMP_NUM_STREAMS] = { "ParamStream2",
+ "ScriptStream2",
+ "DriverInfoStream"};
+typedef struct PDBG_PDUMP_STATE_TAG
+{
+ PDBG_STREAM psStream[PDUMP_NUM_STREAMS];
+ IMG_UINT32 ui32ParamFileNum;
+
+ IMG_CHAR *pszMsg;
+ IMG_CHAR *pszScript;
+ IMG_CHAR *pszFile;
+
+} PDBG_PDUMP_STATE;
+
+static PDBG_PDUMP_STATE gsDBGPdumpState = {{IMG_NULL}, 0, IMG_NULL, IMG_NULL, IMG_NULL};
+
+#define SZ_MSG_SIZE_MAX PVRSRV_PDUMP_MAX_COMMENT_SIZE-1
+#define SZ_SCRIPT_SIZE_MAX PVRSRV_PDUMP_MAX_COMMENT_SIZE-1
+#define SZ_FILENAME_SIZE_MAX PVRSRV_PDUMP_MAX_COMMENT_SIZE-1
+
+
+
+
+IMG_VOID DBGDrvGetServiceTable(IMG_VOID **fn_table);
+
+static inline IMG_BOOL PDumpSuspended(IMG_VOID)
+{
+ return (atomic_read(&gsPDumpSuspended) != 0) ? IMG_TRUE : IMG_FALSE;
+}
+
+PVRSRV_ERROR PDumpOSGetScriptString(IMG_HANDLE *phScript,
+ IMG_UINT32 *pui32MaxLen)
+{
+ *phScript = (IMG_HANDLE)gsDBGPdumpState.pszScript;
+ *pui32MaxLen = SZ_SCRIPT_SIZE_MAX;
+ if ((!*phScript) || PDumpSuspended())
+ {
+ return PVRSRV_ERROR_PDUMP_NOT_ACTIVE;
+ }
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpOSGetMessageString(IMG_CHAR **ppszMsg,
+ IMG_UINT32 *pui32MaxLen)
+{
+ *ppszMsg = gsDBGPdumpState.pszMsg;
+ *pui32MaxLen = SZ_MSG_SIZE_MAX;
+ if ((!*ppszMsg) || PDumpSuspended())
+ {
+ return PVRSRV_ERROR_PDUMP_NOT_ACTIVE;
+ }
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpOSGetFilenameString(IMG_CHAR **ppszFile,
+ IMG_UINT32 *pui32MaxLen)
+{
+ *ppszFile = gsDBGPdumpState.pszFile;
+ *pui32MaxLen = SZ_FILENAME_SIZE_MAX;
+ if ((!*ppszFile) || PDumpSuspended())
+ {
+ return PVRSRV_ERROR_PDUMP_NOT_ACTIVE;
+ }
+ return PVRSRV_OK;
+}
+
+IMG_BOOL PDumpOSWriteString2(IMG_HANDLE hScript, IMG_UINT32 ui32Flags)
+{
+ return PDumpWriteString2(hScript, ui32Flags);
+}
+
+PVRSRV_ERROR PDumpOSBufprintf(IMG_HANDLE hBuf, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, ...)
+{
+ IMG_CHAR* pszBuf = hBuf;
+ IMG_INT32 n;
+ va_list vaArgs;
+
+ va_start(vaArgs, pszFormat);
+
+ n = vsnprintf(pszBuf, ui32ScriptSizeMax, pszFormat, vaArgs);
+
+ va_end(vaArgs);
+
+ if (n>=(IMG_INT32)ui32ScriptSizeMax || n==-1)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete."));
+
+ return PVRSRV_ERROR_PDUMP_BUF_OVERFLOW;
+ }
+
+#if defined(PDUMP_DEBUG_OUTFILES)
+ g_ui32EveryLineCounter++;
+#endif
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpOSVSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, PDUMP_va_list vaArgs)
+{
+ IMG_INT32 n;
+
+ n = vsnprintf(pszComment, ui32ScriptSizeMax, pszFormat, vaArgs);
+
+ if (n>=(IMG_INT32)ui32ScriptSizeMax || n==-1)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete."));
+
+ return PVRSRV_ERROR_PDUMP_BUF_OVERFLOW;
+ }
+
+ return PVRSRV_OK;
+}
+
+IMG_VOID PDumpOSDebugPrintf(IMG_CHAR* pszFormat, ...)
+{
+ PVR_UNREFERENCED_PARAMETER(pszFormat);
+
+
+}
+
+PVRSRV_ERROR PDumpOSSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR *pszFormat, ...)
+{
+ IMG_INT32 n;
+ va_list vaArgs;
+
+ va_start(vaArgs, pszFormat);
+
+ n = vsnprintf(pszComment, ui32ScriptSizeMax, pszFormat, vaArgs);
+
+ va_end(vaArgs);
+
+ if (n>=(IMG_INT32)ui32ScriptSizeMax || n==-1)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete."));
+
+ return PVRSRV_ERROR_PDUMP_BUF_OVERFLOW;
+ }
+
+ return PVRSRV_OK;
+}
+
+IMG_UINT32 PDumpOSBuflen(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax)
+{
+ IMG_CHAR* pszBuf = hBuffer;
+ IMG_UINT32 ui32Count = 0;
+
+ while ((pszBuf[ui32Count]!=0) && (ui32Count<ui32BufferSizeMax) )
+ {
+ ui32Count++;
+ }
+ return(ui32Count);
+}
+
+IMG_VOID PDumpOSVerifyLineEnding(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax)
+{
+ IMG_UINT32 ui32Count;
+ IMG_CHAR* pszBuf = hBuffer;
+
+
+ ui32Count = PDumpOSBuflen(hBuffer, ui32BufferSizeMax);
+
+
+ if ((ui32Count >= 1) && (pszBuf[ui32Count-1] != '\n') && (ui32Count<ui32BufferSizeMax))
+ {
+ pszBuf[ui32Count] = '\n';
+ ui32Count++;
+ pszBuf[ui32Count] = '\0';
+ }
+ if ((ui32Count >= 2) && (pszBuf[ui32Count-2] != '\r') && (ui32Count<ui32BufferSizeMax))
+ {
+ pszBuf[ui32Count-1] = '\r';
+ pszBuf[ui32Count] = '\n';
+ ui32Count++;
+ pszBuf[ui32Count] = '\0';
+ }
+}
+
+IMG_HANDLE PDumpOSGetStream(IMG_UINT32 ePDumpStream)
+{
+ return (IMG_HANDLE)gsDBGPdumpState.psStream[ePDumpStream];
+}
+
+IMG_UINT32 PDumpOSGetStreamOffset(IMG_UINT32 ePDumpStream)
+{
+ PDBG_STREAM psStream = gsDBGPdumpState.psStream[ePDumpStream];
+ return gpfnDbgDrv->pfnGetStreamOffset(psStream);
+}
+
+IMG_UINT32 PDumpOSGetParamFileNum(IMG_VOID)
+{
+ return gsDBGPdumpState.ui32ParamFileNum;
+}
+
+IMG_BOOL PDumpOSWriteString(IMG_HANDLE hStream,
+ IMG_UINT8 *psui8Data,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32Flags)
+{
+ PDBG_STREAM psStream = (PDBG_STREAM)hStream;
+ return PDumpWriteILock(psStream,
+ psui8Data,
+ ui32Size,
+ ui32Flags);
+}
+
+IMG_VOID PDumpOSCheckForSplitting(IMG_HANDLE hStream, IMG_UINT32 ui32Size, IMG_UINT32 ui32Flags)
+{
+
+ PVR_UNREFERENCED_PARAMETER(hStream);
+ PVR_UNREFERENCED_PARAMETER(ui32Size);
+ PVR_UNREFERENCED_PARAMETER(ui32Flags);
+}
+
+IMG_BOOL PDumpOSJTInitialised(IMG_VOID)
+{
+ if(gpfnDbgDrv)
+ {
+ return IMG_TRUE;
+ }
+ return IMG_FALSE;
+}
+
+inline IMG_BOOL PDumpOSIsSuspended(IMG_VOID)
+{
+ return (atomic_read(&gsPDumpSuspended) != 0) ? IMG_TRUE : IMG_FALSE;
+}
+
+IMG_VOID PDumpOSCPUVAddrToDevPAddr(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT8 *pui8LinAddr,
+ IMG_UINT32 ui32PageSize,
+ IMG_DEV_PHYADDR *psDevPAddr)
+{
+ IMG_CPU_PHYADDR sCpuPAddr;
+
+ PVR_UNREFERENCED_PARAMETER(pui8LinAddr);
+ PVR_UNREFERENCED_PARAMETER(ui32PageSize);
+
+
+
+ PVR_ASSERT (hOSMemHandle != IMG_NULL);
+
+ sCpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, ui32Offset);
+ PVR_ASSERT((sCpuPAddr.uiAddr & (ui32PageSize - 1)) == 0);
+
+
+ *psDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
+}
+
+IMG_VOID PDumpOSCPUVAddrToPhysPages(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32Offset,
+ IMG_PUINT8 pui8LinAddr,
+ IMG_UINT32 ui32DataPageMask,
+ IMG_UINT32 *pui32PageOffset)
+{
+ if(hOSMemHandle)
+ {
+
+ IMG_CPU_PHYADDR sCpuPAddr;
+
+ PVR_UNREFERENCED_PARAMETER(pui8LinAddr);
+
+ sCpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, ui32Offset);
+ *pui32PageOffset = sCpuPAddr.uiAddr & ui32DataPageMask;
+ }
+ else
+ {
+ PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+ PVR_UNREFERENCED_PARAMETER(ui32Offset);
+
+ *pui32PageOffset = ((IMG_UINT32)pui8LinAddr & ui32DataPageMask);
+ }
+}
+
+IMG_UINT32 PDumpOSDebugDriverWrite( PDBG_STREAM psStream,
+ PDUMP_DDWMODE eDbgDrvWriteMode,
+ IMG_UINT8 *pui8Data,
+ IMG_UINT32 ui32BCount,
+ IMG_UINT32 ui32Level,
+ IMG_UINT32 ui32DbgDrvFlags)
+{
+ switch(eDbgDrvWriteMode)
+ {
+ case PDUMP_WRITE_MODE_CONTINUOUS:
+ PVR_UNREFERENCED_PARAMETER(ui32DbgDrvFlags);
+ return gpfnDbgDrv->pfnDBGDrivWrite2(psStream, pui8Data, ui32BCount, ui32Level);
+ case PDUMP_WRITE_MODE_LASTFRAME:
+ return gpfnDbgDrv->pfnWriteLF(psStream, pui8Data, ui32BCount, ui32Level, ui32DbgDrvFlags);
+ case PDUMP_WRITE_MODE_BINCM:
+ PVR_UNREFERENCED_PARAMETER(ui32DbgDrvFlags);
+ return gpfnDbgDrv->pfnWriteBINCM(psStream, pui8Data, ui32BCount, ui32Level);
+ case PDUMP_WRITE_MODE_PERSISTENT:
+ PVR_UNREFERENCED_PARAMETER(ui32DbgDrvFlags);
+ return gpfnDbgDrv->pfnWritePersist(psStream, pui8Data, ui32BCount, ui32Level);
+ default:
+ PVR_UNREFERENCED_PARAMETER(ui32DbgDrvFlags);
+ break;
+ }
+ return 0xFFFFFFFFU;
+}
+
+IMG_VOID PDumpOSReleaseExecution(IMG_VOID)
+{
+ OSReleaseThreadQuanta();
+}
+
+IMG_VOID PDumpInit(IMG_VOID)
+{
+ IMG_UINT32 i;
+ DBGKM_CONNECT_NOTIFIER sConnectNotifier;
+
+
+ if (!gpfnDbgDrv)
+ {
+ DBGDrvGetServiceTable((IMG_VOID **)&gpfnDbgDrv);
+
+
+
+ if (gpfnDbgDrv == IMG_NULL)
+ {
+ return;
+ }
+
+
+ sConnectNotifier.pfnConnectNotifier = &PDumpConnectionNotify;
+ gpfnDbgDrv->pfnSetConnectNotifier(sConnectNotifier);
+
+ if(!gsDBGPdumpState.pszFile)
+ {
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_FILENAME_SIZE_MAX, (IMG_PVOID *)&gsDBGPdumpState.pszFile, 0,
+ "Filename string") != PVRSRV_OK)
+ {
+ goto init_failed;
+ }
+ }
+
+ if(!gsDBGPdumpState.pszMsg)
+ {
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_MSG_SIZE_MAX, (IMG_PVOID *)&gsDBGPdumpState.pszMsg, 0,
+ "Message string") != PVRSRV_OK)
+ {
+ goto init_failed;
+ }
+ }
+
+ if(!gsDBGPdumpState.pszScript)
+ {
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_SCRIPT_SIZE_MAX, (IMG_PVOID *)&gsDBGPdumpState.pszScript, 0,
+ "Script string") != PVRSRV_OK)
+ {
+ goto init_failed;
+ }
+ }
+
+ for(i=0; i < PDUMP_NUM_STREAMS; i++)
+ {
+ gsDBGPdumpState.psStream[i] = gpfnDbgDrv->pfnCreateStream(pszStreamName[i],
+ DEBUG_CAPMODE_FRAMED,
+ DEBUG_OUTMODE_STREAMENABLE,
+ 0,
+ 10);
+
+ gpfnDbgDrv->pfnSetCaptureMode(gsDBGPdumpState.psStream[i],DEBUG_CAPMODE_FRAMED,0xFFFFFFFF, 0xFFFFFFFF, 1);
+ gpfnDbgDrv->pfnSetFrame(gsDBGPdumpState.psStream[i],0);
+ }
+
+ PDUMPCOMMENT("Driver Product Name: %s", VS_PRODUCT_NAME);
+ PDUMPCOMMENT("Driver Product Version: %s (%s)", PVRVERSION_STRING, PVRVERSION_FILE);
+ PDUMPCOMMENT("Start of Init Phase");
+ }
+
+ return;
+
+init_failed:
+
+ if(gsDBGPdumpState.pszFile)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_FILENAME_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszFile, 0);
+ gsDBGPdumpState.pszFile = IMG_NULL;
+ }
+
+ if(gsDBGPdumpState.pszScript)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_SCRIPT_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszScript, 0);
+ gsDBGPdumpState.pszScript = IMG_NULL;
+ }
+
+ if(gsDBGPdumpState.pszMsg)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_MSG_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszMsg, 0);
+ gsDBGPdumpState.pszMsg = IMG_NULL;
+ }
+
+
+ sConnectNotifier.pfnConnectNotifier = 0;
+ gpfnDbgDrv->pfnSetConnectNotifier(sConnectNotifier);
+
+ gpfnDbgDrv = IMG_NULL;
+}
+
+
+IMG_VOID PDumpDeInit(IMG_VOID)
+{
+ IMG_UINT32 i;
+ DBGKM_CONNECT_NOTIFIER sConnectNotifier;
+
+ for(i=0; i < PDUMP_NUM_STREAMS; i++)
+ {
+ gpfnDbgDrv->pfnDestroyStream(gsDBGPdumpState.psStream[i]);
+ }
+
+ if(gsDBGPdumpState.pszFile)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_FILENAME_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszFile, 0);
+ gsDBGPdumpState.pszFile = IMG_NULL;
+ }
+
+ if(gsDBGPdumpState.pszScript)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_SCRIPT_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszScript, 0);
+ gsDBGPdumpState.pszScript = IMG_NULL;
+ }
+
+ if(gsDBGPdumpState.pszMsg)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_MSG_SIZE_MAX, (IMG_PVOID) gsDBGPdumpState.pszMsg, 0);
+ gsDBGPdumpState.pszMsg = IMG_NULL;
+ }
+
+
+ sConnectNotifier.pfnConnectNotifier = 0;
+ gpfnDbgDrv->pfnSetConnectNotifier(sConnectNotifier);
+
+ gpfnDbgDrv = IMG_NULL;
+}
+
+PVRSRV_ERROR PDumpStartInitPhaseKM(IMG_VOID)
+{
+ IMG_UINT32 i;
+
+ if (gpfnDbgDrv)
+ {
+ PDUMPCOMMENT("Start Init Phase");
+ for(i=0; i < PDUMP_NUM_STREAMS; i++)
+ {
+ gpfnDbgDrv->pfnStartInitPhase(gsDBGPdumpState.psStream[i]);
+ }
+ }
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpStopInitPhaseKM(IMG_VOID)
+{
+ IMG_UINT32 i;
+
+ if (gpfnDbgDrv)
+ {
+ PDUMPCOMMENT("Stop Init Phase");
+
+ for(i=0; i < PDUMP_NUM_STREAMS; i++)
+ {
+ gpfnDbgDrv->pfnStopInitPhase(gsDBGPdumpState.psStream[i]);
+ }
+ }
+ return PVRSRV_OK;
+}
+
+IMG_BOOL PDumpIsLastCaptureFrameKM(IMG_VOID)
+{
+ return gpfnDbgDrv->pfnIsLastCaptureFrame(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2]);
+}
+
+
+IMG_BOOL PDumpOSIsCaptureFrameKM(IMG_VOID)
+{
+ if (PDumpSuspended())
+ {
+ return IMG_FALSE;
+ }
+ return gpfnDbgDrv->pfnIsCaptureFrame(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2], IMG_FALSE);
+}
+
+PVRSRV_ERROR PDumpOSSetFrameKM(IMG_UINT32 ui32Frame)
+{
+ IMG_UINT32 ui32Stream;
+
+ for (ui32Stream = 0; ui32Stream < PDUMP_NUM_STREAMS; ui32Stream++)
+ {
+ if (gsDBGPdumpState.psStream[ui32Stream])
+ {
+ DbgSetFrame(gsDBGPdumpState.psStream[ui32Stream], ui32Frame);
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+
+static IMG_BOOL PDumpWriteString2(IMG_CHAR * pszString, IMG_UINT32 ui32Flags)
+{
+ return PDumpWriteILock(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2], (IMG_UINT8 *) pszString, strlen(pszString), ui32Flags);
+}
+
+
+static IMG_BOOL PDumpWriteILock(PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32Count, IMG_UINT32 ui32Flags)
+{
+ IMG_UINT32 ui32Written = 0;
+ if ((psStream == IMG_NULL) || PDumpSuspended() || ((ui32Flags & PDUMP_FLAGS_NEVER) != 0))
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "PDumpWriteILock: Failed to write 0x%x bytes to stream 0x%x", ui32Count, (IMG_UINT32)psStream));
+ return IMG_TRUE;
+ }
+
+
+
+
+ if (psStream == gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2])
+ {
+ IMG_UINT32 ui32ParamOutPos = gpfnDbgDrv->pfnGetStreamOffset(gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2]);
+
+ if (ui32ParamOutPos + ui32Count > MAX_FILE_SIZE)
+ {
+ if ((gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2] && PDumpWriteString2("\r\n-- Splitting pdump output file\r\n\r\n", ui32Flags)))
+ {
+ DbgSetMarker(gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2], ui32ParamOutPos);
+ gsDBGPdumpState.ui32ParamFileNum++;
+ }
+ }
+ }
+
+ ui32Written = DbgWrite(psStream, pui8Data, ui32Count, ui32Flags);
+
+ if (ui32Written == 0xFFFFFFFF)
+ {
+ return IMG_FALSE;
+ }
+
+ return IMG_TRUE;
+}
+
+static IMG_VOID DbgSetFrame(PDBG_STREAM psStream, IMG_UINT32 ui32Frame)
+{
+ gpfnDbgDrv->pfnSetFrame(psStream, ui32Frame);
+}
+
+static IMG_VOID DbgSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker)
+{
+ gpfnDbgDrv->pfnSetMarker(psStream, ui32Marker);
+}
+
+IMG_VOID PDumpSuspendKM(IMG_VOID)
+{
+ atomic_inc(&gsPDumpSuspended);
+}
+
+IMG_VOID PDumpResumeKM(IMG_VOID)
+{
+ atomic_dec(&gsPDumpSuspended);
+}
+
+#endif
+#endif
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef __INCLUDED_PRIVATE_DATA_H_
+#define __INCLUDED_PRIVATE_DATA_H_
+
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+#include <linux/list.h>
+#include <drm/drmP.h>
+#endif
+
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_LINUX_USING_WORKQUEUES)
+#include <linux/workqueue.h>
+#endif
+
+typedef struct
+{
+
+ IMG_UINT32 ui32OpenPID;
+
+ IMG_HANDLE sec_fd_exp_meminfo;
+
+#if defined(SUPPORT_DRI_DRM)
+#if defined(PVR_SECURE_DRM_AUTH_EXPORT)
+ struct drm_file *psDRMFile;
+
+
+ struct list_head sDRMAuthListItem;
+#endif
+
+#if defined(PVR_LINUX_USING_WORKQUEUES)
+ struct work_struct sReleaseWork;
+#endif
+
+#if defined(SUPPORT_DRI_DRM_EXT)
+ IMG_PVOID pPriv;
+#endif
+#endif
+
+#if defined(SUPPORT_MEMINFO_IDS)
+
+ IMG_UINT64 ui64Stamp;
+#endif
+
+
+ IMG_HANDLE hBlockAlloc;
+}
+PVRSRV_FILE_PRIVATE_DATA;
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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/init.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+#include "services_headers.h"
+
+#include "queue.h"
+#include "resman.h"
+#include "pvrmmap.h"
+#include "pvr_debug.h"
+#include "pvrversion.h"
+#include "proc.h"
+#include "perproc.h"
+#include "env_perproc.h"
+#include "linkage.h"
+
+#include "lists.h"
+
+static struct proc_dir_entry * dir;
+
+static const IMG_CHAR PVRProcDirRoot[] = "pvr";
+
+static IMG_INT pvr_proc_open(struct inode *inode,struct file *file);
+static void *pvr_proc_seq_start (struct seq_file *m, loff_t *pos);
+static void pvr_proc_seq_stop (struct seq_file *m, void *v);
+static void *pvr_proc_seq_next (struct seq_file *m, void *v, loff_t *pos);
+static int pvr_proc_seq_show (struct seq_file *m, void *v);
+static ssize_t pvr_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos);
+
+static struct file_operations pvr_proc_operations =
+{
+ .open = pvr_proc_open,
+ .read = seq_read,
+ .write = pvr_proc_write,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+static struct seq_operations pvr_proc_seq_operations =
+{
+ .start = pvr_proc_seq_start,
+ .next = pvr_proc_seq_next,
+ .stop = pvr_proc_seq_stop,
+ .show = pvr_proc_seq_show,
+};
+
+static struct proc_dir_entry* g_pProcQueue;
+static struct proc_dir_entry* g_pProcVersion;
+static struct proc_dir_entry* g_pProcSysNodes;
+
+#ifdef DEBUG
+static struct proc_dir_entry* g_pProcDebugLevel;
+#endif
+
+#ifdef PVR_MANUAL_POWER_CONTROL
+static struct proc_dir_entry* g_pProcPowerLevel;
+#endif
+
+
+static void ProcSeqShowVersion(struct seq_file *sfile,void* el);
+
+static void ProcSeqShowSysNodes(struct seq_file *sfile,void* el);
+static void* ProcSeqOff2ElementSysNodes(struct seq_file * sfile, loff_t off);
+
+off_t printAppend(IMG_CHAR * buffer, size_t size, off_t off, const IMG_CHAR * format, ...)
+{
+ IMG_INT n;
+ size_t space = size - (size_t)off;
+ va_list ap;
+
+ va_start (ap, format);
+
+ n = vsnprintf (buffer+off, space, format, ap);
+
+ va_end (ap);
+
+ if (n >= (IMG_INT)space || n < 0)
+ {
+
+ buffer[size - 1] = 0;
+ return (off_t)(size - 1);
+ }
+ else
+ {
+ return (off + (off_t)n);
+ }
+}
+
+
+void* ProcSeq1ElementOff2Element(struct seq_file *sfile, loff_t off)
+{
+ PVR_UNREFERENCED_PARAMETER(sfile);
+
+ if(!off)
+ return (void*)2;
+ return NULL;
+}
+
+
+void* ProcSeq1ElementHeaderOff2Element(struct seq_file *sfile, loff_t off)
+{
+ PVR_UNREFERENCED_PARAMETER(sfile);
+
+ if(!off)
+ {
+ return PVR_PROC_SEQ_START_TOKEN;
+ }
+
+
+ if(off == 1)
+ return (void*)2;
+
+ return NULL;
+}
+
+
+static IMG_INT pvr_proc_open(struct inode *inode,struct file *file)
+{
+ IMG_INT ret = seq_open(file, &pvr_proc_seq_operations);
+
+ struct seq_file *seq = (struct seq_file*)file->private_data;
+ struct proc_dir_entry* pvr_proc_entry = PDE(inode);
+
+
+ seq->private = pvr_proc_entry->data;
+ return ret;
+}
+
+static ssize_t pvr_proc_write(struct file *file, const char __user *buffer,
+ size_t count, loff_t *ppos)
+{
+ struct inode *inode = file->f_path.dentry->d_inode;
+ struct proc_dir_entry * dp;
+
+ PVR_UNREFERENCED_PARAMETER(ppos);
+ dp = PDE(inode);
+
+ if (!dp->write_proc)
+ return -EIO;
+
+ return dp->write_proc(file, buffer, count, dp->data);
+}
+
+
+static void *pvr_proc_seq_start (struct seq_file *proc_seq_file, loff_t *pos)
+{
+ PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)proc_seq_file->private;
+ if(handlers->startstop != NULL)
+ handlers->startstop(proc_seq_file, IMG_TRUE);
+ return handlers->off2element(proc_seq_file, *pos);
+}
+
+static void pvr_proc_seq_stop (struct seq_file *proc_seq_file, void *v)
+{
+ PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)proc_seq_file->private;
+ PVR_UNREFERENCED_PARAMETER(v);
+
+ if(handlers->startstop != NULL)
+ handlers->startstop(proc_seq_file, IMG_FALSE);
+}
+
+static void *pvr_proc_seq_next (struct seq_file *proc_seq_file, void *v, loff_t *pos)
+{
+ PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)proc_seq_file->private;
+ (*pos)++;
+ if( handlers->next != NULL)
+ return handlers->next( proc_seq_file, v, *pos );
+ return handlers->off2element(proc_seq_file, *pos);
+}
+
+static int pvr_proc_seq_show (struct seq_file *proc_seq_file, void *v)
+{
+ PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)proc_seq_file->private;
+ handlers->show( proc_seq_file,v );
+ return 0;
+}
+
+
+
+static struct proc_dir_entry* CreateProcEntryInDirSeq(
+ struct proc_dir_entry *pdir,
+ const IMG_CHAR * name,
+ IMG_VOID* data,
+ pvr_next_proc_seq_t next_handler,
+ pvr_show_proc_seq_t show_handler,
+ pvr_off2element_proc_seq_t off2element_handler,
+ pvr_startstop_proc_seq_t startstop_handler,
+ write_proc_t whandler
+ )
+{
+
+ struct proc_dir_entry * file;
+ mode_t mode;
+
+ if (!dir)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcEntryInDirSeq: cannot make proc entry /proc/%s/%s: no parent", PVRProcDirRoot, name));
+ return NULL;
+ }
+
+ mode = S_IFREG;
+
+ if (show_handler)
+ {
+ mode |= S_IRUGO;
+ }
+
+ if (whandler)
+ {
+ mode |= S_IWUSR;
+ }
+
+ file=create_proc_entry(name, mode, pdir);
+
+ if (file)
+ {
+ PVR_PROC_SEQ_HANDLERS *seq_handlers;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
+ file->owner = THIS_MODULE;
+#endif
+
+ file->proc_fops = &pvr_proc_operations;
+ file->write_proc = whandler;
+
+
+ file->data = kmalloc(sizeof(PVR_PROC_SEQ_HANDLERS), GFP_KERNEL);
+ if(file->data)
+ {
+ seq_handlers = (PVR_PROC_SEQ_HANDLERS*)file->data;
+ seq_handlers->next = next_handler;
+ seq_handlers->show = show_handler;
+ seq_handlers->off2element = off2element_handler;
+ seq_handlers->startstop = startstop_handler;
+ seq_handlers->data = data;
+
+ return file;
+ }
+ }
+
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcEntryInDirSeq: cannot make proc entry /proc/%s/%s: no memory", PVRProcDirRoot, name));
+ return NULL;
+}
+
+
+struct proc_dir_entry* CreateProcReadEntrySeq (
+ const IMG_CHAR * name,
+ IMG_VOID* data,
+ pvr_next_proc_seq_t next_handler,
+ pvr_show_proc_seq_t show_handler,
+ pvr_off2element_proc_seq_t off2element_handler,
+ pvr_startstop_proc_seq_t startstop_handler
+ )
+{
+ return CreateProcEntrySeq(name,
+ data,
+ next_handler,
+ show_handler,
+ off2element_handler,
+ startstop_handler,
+ NULL);
+}
+
+struct proc_dir_entry* CreateProcEntrySeq (
+ const IMG_CHAR * name,
+ IMG_VOID* data,
+ pvr_next_proc_seq_t next_handler,
+ pvr_show_proc_seq_t show_handler,
+ pvr_off2element_proc_seq_t off2element_handler,
+ pvr_startstop_proc_seq_t startstop_handler,
+ write_proc_t whandler
+ )
+{
+ return CreateProcEntryInDirSeq(
+ dir,
+ name,
+ data,
+ next_handler,
+ show_handler,
+ off2element_handler,
+ startstop_handler,
+ whandler
+ );
+}
+
+
+
+struct proc_dir_entry* CreatePerProcessProcEntrySeq (
+ const IMG_CHAR * name,
+ IMG_VOID* data,
+ pvr_next_proc_seq_t next_handler,
+ pvr_show_proc_seq_t show_handler,
+ pvr_off2element_proc_seq_t off2element_handler,
+ pvr_startstop_proc_seq_t startstop_handler,
+ write_proc_t whandler
+ )
+{
+ PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
+ IMG_UINT32 ui32PID;
+
+ if (!dir)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntrySeq: /proc/%s doesn't exist", PVRProcDirRoot));
+ return NULL;
+ }
+
+ ui32PID = OSGetCurrentProcessIDKM();
+
+ psPerProc = PVRSRVPerProcessPrivateData(ui32PID);
+ if (!psPerProc)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntrySeq: no per process data"));
+
+ return NULL;
+ }
+
+ if (!psPerProc->psProcDir)
+ {
+ IMG_CHAR dirname[16];
+ IMG_INT ret;
+
+ ret = snprintf(dirname, sizeof(dirname), "%u", ui32PID);
+
+ if (ret <=0 || ret >= (IMG_INT)sizeof(dirname))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: couldn't generate per process proc directory name \"%u\"", ui32PID));
+ return NULL;
+ }
+ else
+ {
+ psPerProc->psProcDir = proc_mkdir(dirname, dir);
+ if (!psPerProc->psProcDir)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: couldn't create per process proc directory /proc/%s/%u",
+ PVRProcDirRoot, ui32PID));
+ return NULL;
+ }
+ }
+ }
+
+ return CreateProcEntryInDirSeq(psPerProc->psProcDir, name, data, next_handler,
+ show_handler,off2element_handler,startstop_handler,whandler);
+}
+
+
+IMG_VOID RemoveProcEntrySeq( struct proc_dir_entry* proc_entry )
+{
+ if (dir)
+ {
+ void* data = proc_entry->data ;
+ PVR_DPF((PVR_DBG_MESSAGE, "Removing /proc/%s/%s", PVRProcDirRoot, proc_entry->name));
+
+ remove_proc_entry(proc_entry->name, dir);
+ if( data)
+ kfree( data );
+
+ }
+}
+
+IMG_VOID RemovePerProcessProcEntrySeq(struct proc_dir_entry* proc_entry)
+{
+ PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
+
+ psPerProc = LinuxTerminatingProcessPrivateData();
+ if (!psPerProc)
+ {
+ psPerProc = PVRSRVFindPerProcessPrivateData();
+ if (!psPerProc)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: can't "
+ "remove %s, no per process data", proc_entry->name));
+ return;
+ }
+ }
+
+ if (psPerProc->psProcDir)
+ {
+ void* data = proc_entry->data ;
+ PVR_DPF((PVR_DBG_MESSAGE, "Removing proc entry %s from %s", proc_entry->name, psPerProc->psProcDir->name));
+
+ remove_proc_entry(proc_entry->name, psPerProc->psProcDir);
+ if(data)
+ kfree( data );
+ }
+}
+
+static IMG_INT pvr_read_proc(IMG_CHAR *page, IMG_CHAR **start, off_t off,
+ IMG_INT count, IMG_INT *eof, IMG_VOID *data)
+{
+
+ pvr_read_proc_t *pprn = (pvr_read_proc_t *)data;
+
+ off_t len = pprn (page, (size_t)count, off);
+
+ if (len == END_OF_FILE)
+ {
+ len = 0;
+ *eof = 1;
+ }
+ else if (!len)
+ {
+ *start = (IMG_CHAR *) 0;
+ }
+ else
+ {
+ *start = (IMG_CHAR *) 1;
+ }
+
+ return len;
+}
+
+
+static IMG_INT CreateProcEntryInDir(struct proc_dir_entry *pdir, const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data)
+{
+ struct proc_dir_entry * file;
+ mode_t mode;
+
+ if (!pdir)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcEntryInDir: parent directory doesn't exist"));
+
+ return -ENOMEM;
+ }
+
+ mode = S_IFREG;
+
+ if (rhandler)
+ {
+ mode |= S_IRUGO;
+ }
+
+ if (whandler)
+ {
+ mode |= S_IWUSR;
+ }
+
+ file = create_proc_entry(name, mode, pdir);
+
+ if (file)
+ {
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
+ file->owner = THIS_MODULE;
+#endif
+ file->read_proc = rhandler;
+ file->write_proc = whandler;
+ file->data = data;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "Created proc entry %s in %s", name, pdir->name));
+
+ return 0;
+ }
+
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcEntry: cannot create proc entry %s in %s", name, pdir->name));
+
+ return -ENOMEM;
+}
+
+
+IMG_INT CreateProcEntry(const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data)
+{
+ return CreateProcEntryInDir(dir, name, rhandler, whandler, data);
+}
+
+
+IMG_INT CreatePerProcessProcEntry(const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data)
+{
+ PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
+ IMG_UINT32 ui32PID;
+
+ if (!dir)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: /proc/%s doesn't exist", PVRProcDirRoot));
+
+ return -ENOMEM;
+ }
+
+ ui32PID = OSGetCurrentProcessIDKM();
+
+ psPerProc = PVRSRVPerProcessPrivateData(ui32PID);
+ if (!psPerProc)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: no per process data"));
+
+ return -ENOMEM;
+ }
+
+ if (!psPerProc->psProcDir)
+ {
+ IMG_CHAR dirname[16];
+ IMG_INT ret;
+
+ ret = snprintf(dirname, sizeof(dirname), "%u", ui32PID);
+
+ if (ret <=0 || ret >= (IMG_INT)sizeof(dirname))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: couldn't generate per process proc directory name \"%u\"", ui32PID));
+
+ return -ENOMEM;
+ }
+ else
+ {
+ psPerProc->psProcDir = proc_mkdir(dirname, dir);
+ if (!psPerProc->psProcDir)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: couldn't create per process proc directory /proc/%s/%u", PVRProcDirRoot, ui32PID));
+
+ return -ENOMEM;
+ }
+ }
+ }
+
+ return CreateProcEntryInDir(psPerProc->psProcDir, name, rhandler, whandler, data);
+}
+
+
+IMG_INT CreateProcReadEntry(const IMG_CHAR * name, pvr_read_proc_t handler)
+{
+ struct proc_dir_entry * file;
+
+ if (!dir)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcReadEntry: cannot make proc entry /proc/%s/%s: no parent", PVRProcDirRoot, name));
+
+ return -ENOMEM;
+ }
+
+
+ file = create_proc_read_entry (name, S_IFREG | S_IRUGO, dir, pvr_read_proc, (IMG_VOID *)handler);
+
+ if (file)
+ {
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
+ file->owner = THIS_MODULE;
+#endif
+ return 0;
+ }
+
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcReadEntry: cannot make proc entry /proc/%s/%s: no memory", PVRProcDirRoot, name));
+
+ return -ENOMEM;
+}
+
+
+IMG_INT CreateProcEntries(IMG_VOID)
+{
+ dir = proc_mkdir (PVRProcDirRoot, NULL);
+
+ if (!dir)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcEntries: cannot make /proc/%s directory", PVRProcDirRoot));
+
+ return -ENOMEM;
+ }
+
+ g_pProcQueue = CreateProcReadEntrySeq("queue", NULL, NULL, ProcSeqShowQueue, ProcSeqOff2ElementQueue, NULL);
+ g_pProcVersion = CreateProcReadEntrySeq("version", NULL, NULL, ProcSeqShowVersion, ProcSeq1ElementHeaderOff2Element, NULL);
+ g_pProcSysNodes = CreateProcReadEntrySeq("nodes", NULL, NULL, ProcSeqShowSysNodes, ProcSeqOff2ElementSysNodes, NULL);
+
+ if(!g_pProcQueue || !g_pProcVersion || !g_pProcSysNodes)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcEntries: couldn't make /proc/%s files", PVRProcDirRoot));
+
+ return -ENOMEM;
+ }
+
+
+#ifdef DEBUG
+
+ g_pProcDebugLevel = CreateProcEntrySeq("debug_level", NULL, NULL,
+ ProcSeqShowDebugLevel,
+ ProcSeq1ElementOff2Element, NULL,
+ (IMG_VOID*)PVRDebugProcSetLevel);
+ if(!g_pProcDebugLevel)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcEntries: couldn't make /proc/%s/debug_level", PVRProcDirRoot));
+
+ return -ENOMEM;
+ }
+
+#ifdef PVR_MANUAL_POWER_CONTROL
+ g_pProcPowerLevel = CreateProcEntrySeq("power_control", NULL, NULL,
+ ProcSeqShowPowerLevel,
+ ProcSeq1ElementOff2Element, NULL,
+ PVRProcSetPowerLevel);
+ if(!g_pProcPowerLevel)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreateProcEntries: couldn't make /proc/%s/power_control", PVRProcDirRoot));
+
+ return -ENOMEM;
+ }
+#endif
+#endif
+
+ return 0;
+}
+
+
+IMG_VOID RemoveProcEntry(const IMG_CHAR * name)
+{
+ if (dir)
+ {
+ remove_proc_entry(name, dir);
+ PVR_DPF((PVR_DBG_MESSAGE, "Removing /proc/%s/%s", PVRProcDirRoot, name));
+ }
+}
+
+
+IMG_VOID RemovePerProcessProcEntry(const IMG_CHAR *name)
+{
+ PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
+
+ psPerProc = LinuxTerminatingProcessPrivateData();
+ if (!psPerProc)
+ {
+ psPerProc = PVRSRVFindPerProcessPrivateData();
+ if (!psPerProc)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CreatePerProcessProcEntries: can't "
+ "remove %s, no per process data", name));
+ return;
+ }
+ }
+
+ if (psPerProc->psProcDir)
+ {
+ remove_proc_entry(name, psPerProc->psProcDir);
+
+ PVR_DPF((PVR_DBG_MESSAGE, "Removing proc entry %s from %s", name, psPerProc->psProcDir->name));
+ }
+}
+
+
+IMG_VOID RemovePerProcessProcDir(PVRSRV_ENV_PER_PROCESS_DATA *psPerProc)
+{
+ if (psPerProc->psProcDir)
+ {
+ while (psPerProc->psProcDir->subdir)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "Belatedly removing /proc/%s/%s/%s", PVRProcDirRoot, psPerProc->psProcDir->name, psPerProc->psProcDir->subdir->name));
+
+ RemoveProcEntry(psPerProc->psProcDir->subdir->name);
+ }
+ RemoveProcEntry(psPerProc->psProcDir->name);
+ }
+}
+
+IMG_VOID RemoveProcEntries(IMG_VOID)
+{
+#ifdef DEBUG
+ RemoveProcEntrySeq( g_pProcDebugLevel );
+#ifdef PVR_MANUAL_POWER_CONTROL
+ RemoveProcEntrySeq( g_pProcPowerLevel );
+#endif
+#endif
+
+ RemoveProcEntrySeq(g_pProcQueue);
+ RemoveProcEntrySeq(g_pProcVersion);
+ RemoveProcEntrySeq(g_pProcSysNodes);
+
+ while (dir->subdir)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "Belatedly removing /proc/%s/%s", PVRProcDirRoot, dir->subdir->name));
+
+ RemoveProcEntry(dir->subdir->name);
+ }
+
+ remove_proc_entry(PVRProcDirRoot, NULL);
+}
+
+static void ProcSeqShowVersion(struct seq_file *sfile,void* el)
+{
+ SYS_DATA *psSysData;
+ IMG_CHAR *pszSystemVersionString = "None";
+
+ if(el == PVR_PROC_SEQ_START_TOKEN)
+ {
+ seq_printf(sfile,
+ "Version %s (%s) %s\n",
+ PVRVERSION_STRING,
+ PVR_BUILD_TYPE, PVR_BUILD_DIR);
+ return;
+ }
+
+ psSysData = SysAcquireDataNoCheck();
+ if(psSysData != IMG_NULL && psSysData->pszVersionString != IMG_NULL)
+ {
+ pszSystemVersionString = psSysData->pszVersionString;
+ }
+
+ seq_printf( sfile, "System Version String: %s\n", pszSystemVersionString);
+}
+
+static const IMG_CHAR *deviceTypeToString(PVRSRV_DEVICE_TYPE deviceType)
+{
+ switch (deviceType)
+ {
+ default:
+ {
+ static IMG_CHAR text[10];
+
+ sprintf(text, "?%x", (IMG_UINT)deviceType);
+
+ return text;
+ }
+ }
+}
+
+
+static const IMG_CHAR *deviceClassToString(PVRSRV_DEVICE_CLASS deviceClass)
+{
+ switch (deviceClass)
+ {
+ case PVRSRV_DEVICE_CLASS_3D:
+ {
+ return "3D";
+ }
+ case PVRSRV_DEVICE_CLASS_DISPLAY:
+ {
+ return "display";
+ }
+ case PVRSRV_DEVICE_CLASS_BUFFER:
+ {
+ return "buffer";
+ }
+ default:
+ {
+ static IMG_CHAR text[10];
+
+ sprintf(text, "?%x", (IMG_UINT)deviceClass);
+ return text;
+ }
+ }
+}
+
+static IMG_VOID* DecOffPsDev_AnyVaCb(PVRSRV_DEVICE_NODE *psNode, va_list va)
+{
+ off_t *pOff = va_arg(va, off_t*);
+ if (--(*pOff))
+ {
+ return IMG_NULL;
+ }
+ else
+ {
+ return psNode;
+ }
+}
+
+static void ProcSeqShowSysNodes(struct seq_file *sfile,void* el)
+{
+ PVRSRV_DEVICE_NODE *psDevNode;
+
+ if(el == PVR_PROC_SEQ_START_TOKEN)
+ {
+ seq_printf( sfile,
+ "Registered nodes\n"
+ "Addr Type Class Index Ref pvDev Size Res\n");
+ return;
+ }
+
+ psDevNode = (PVRSRV_DEVICE_NODE*)el;
+
+ seq_printf( sfile,
+ "%p %-8s %-8s %4d %2u %p %3u %p\n",
+ psDevNode,
+ deviceTypeToString(psDevNode->sDevId.eDeviceType),
+ deviceClassToString(psDevNode->sDevId.eDeviceClass),
+ psDevNode->sDevId.eDeviceClass,
+ psDevNode->ui32RefCount,
+ psDevNode->pvDevice,
+ psDevNode->ui32pvDeviceSize,
+ psDevNode->hResManContext);
+}
+
+static void* ProcSeqOff2ElementSysNodes(struct seq_file * sfile, loff_t off)
+{
+ SYS_DATA *psSysData;
+ PVRSRV_DEVICE_NODE*psDevNode = IMG_NULL;
+
+ PVR_UNREFERENCED_PARAMETER(sfile);
+
+ if(!off)
+ {
+ return PVR_PROC_SEQ_START_TOKEN;
+ }
+
+ psSysData = SysAcquireDataNoCheck();
+ if (psSysData != IMG_NULL)
+ {
+
+ psDevNode = (PVRSRV_DEVICE_NODE*)
+ List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+ DecOffPsDev_AnyVaCb,
+ &off);
+ }
+
+
+ return (void*)psDevNode;
+}
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef __SERVICES_PROC_H__
+#define __SERVICES_PROC_H__
+
+#include <asm/system.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+#define END_OF_FILE (off_t) -1
+
+typedef off_t (pvr_read_proc_t)(IMG_CHAR *, size_t, off_t);
+
+
+#define PVR_PROC_SEQ_START_TOKEN (void*)1
+typedef void* (pvr_next_proc_seq_t)(struct seq_file *,void*,loff_t);
+typedef void* (pvr_off2element_proc_seq_t)(struct seq_file *, loff_t);
+typedef void (pvr_show_proc_seq_t)(struct seq_file *,void*);
+typedef void (pvr_startstop_proc_seq_t)(struct seq_file *, IMG_BOOL start);
+
+typedef struct _PVR_PROC_SEQ_HANDLERS_ {
+ pvr_next_proc_seq_t *next;
+ pvr_show_proc_seq_t *show;
+ pvr_off2element_proc_seq_t *off2element;
+ pvr_startstop_proc_seq_t *startstop;
+ IMG_VOID *data;
+} PVR_PROC_SEQ_HANDLERS;
+
+
+void* ProcSeq1ElementOff2Element(struct seq_file *sfile, loff_t off);
+
+void* ProcSeq1ElementHeaderOff2Element(struct seq_file *sfile, loff_t off);
+
+off_t printAppend(IMG_CHAR * buffer, size_t size, off_t off, const IMG_CHAR * format, ...)
+ __attribute__((format(printf, 4, 5)));
+
+IMG_INT CreateProcEntries(IMG_VOID);
+
+IMG_INT CreateProcReadEntry (const IMG_CHAR * name, pvr_read_proc_t handler);
+
+IMG_INT CreateProcEntry(const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data);
+
+IMG_INT CreatePerProcessProcEntry(const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data);
+
+IMG_VOID RemoveProcEntry(const IMG_CHAR * name);
+
+IMG_VOID RemovePerProcessProcEntry(const IMG_CHAR * name);
+
+IMG_VOID RemoveProcEntries(IMG_VOID);
+
+struct proc_dir_entry* CreateProcReadEntrySeq (
+ const IMG_CHAR* name,
+ IMG_VOID* data,
+ pvr_next_proc_seq_t next_handler,
+ pvr_show_proc_seq_t show_handler,
+ pvr_off2element_proc_seq_t off2element_handler,
+ pvr_startstop_proc_seq_t startstop_handler
+ );
+
+struct proc_dir_entry* CreateProcEntrySeq (
+ const IMG_CHAR* name,
+ IMG_VOID* data,
+ pvr_next_proc_seq_t next_handler,
+ pvr_show_proc_seq_t show_handler,
+ pvr_off2element_proc_seq_t off2element_handler,
+ pvr_startstop_proc_seq_t startstop_handler,
+ write_proc_t whandler
+ );
+
+struct proc_dir_entry* CreatePerProcessProcEntrySeq (
+ const IMG_CHAR* name,
+ IMG_VOID* data,
+ pvr_next_proc_seq_t next_handler,
+ pvr_show_proc_seq_t show_handler,
+ pvr_off2element_proc_seq_t off2element_handler,
+ pvr_startstop_proc_seq_t startstop_handler,
+ write_proc_t whandler
+ );
+
+
+IMG_VOID RemoveProcEntrySeq(struct proc_dir_entry* proc_entry);
+IMG_VOID RemovePerProcessProcEntrySeq(struct proc_dir_entry* proc_entry);
+
+#endif
--- /dev/null
+/**********************************************************************
+ *
+ * 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 "img_defs.h"
+#include "services.h"
+#include "pvr_bridge.h"
+#include "perproc.h"
+#include "mutex.h"
+#include "syscommon.h"
+#include "pvr_debug.h"
+#include "proc.h"
+#include "private_data.h"
+#include "linkage.h"
+#include "pvr_bridge_km.h"
+#include "sgx_bridge_km.h"
+#include "sgx_options.h"
+
+#if defined(SUPPORT_DRI_DRM)
+#include <drm/drmP.h>
+#include "pvr_drm.h"
+#if defined(PVR_SECURE_DRM_AUTH_EXPORT)
+#include "env_perproc.h"
+#endif
+#endif
+
+#if defined(SUPPORT_VGX)
+#include "vgx_bridge.h"
+#endif
+
+#if defined(SUPPORT_SGX)
+#include "sgx_bridge.h"
+#endif
+
+#include "bridged_pvr_bridge.h"
+
+#ifdef MODULE_TEST
+#include "pvr_test_bridge.h"
+#include "kern_test.h"
+#endif
+
+
+#if defined(SUPPORT_DRI_DRM)
+#define PRIVATE_DATA(pFile) ((pFile)->driver_priv)
+#else
+#define PRIVATE_DATA(pFile) ((pFile)->private_data)
+#endif
+
+#if defined(DEBUG_BRIDGE_KM)
+
+static struct proc_dir_entry *g_ProcBridgeStats =0;
+static void* ProcSeqNextBridgeStats(struct seq_file *sfile,void* el,loff_t off);
+static void ProcSeqShowBridgeStats(struct seq_file *sfile,void* el);
+static void* ProcSeqOff2ElementBridgeStats(struct seq_file * sfile, loff_t off);
+static void ProcSeqStartstopBridgeStats(struct seq_file *sfile,IMG_BOOL start);
+
+#endif
+
+extern PVRSRV_LINUX_MUTEX gPVRSRVLock;
+
+#if defined(SUPPORT_MEMINFO_IDS)
+static IMG_UINT64 ui64Stamp;
+#endif
+
+PVRSRV_ERROR
+LinuxBridgeInit(IMG_VOID)
+{
+#if defined(DEBUG_BRIDGE_KM)
+ {
+ g_ProcBridgeStats = CreateProcReadEntrySeq(
+ "bridge_stats",
+ NULL,
+ ProcSeqNextBridgeStats,
+ ProcSeqShowBridgeStats,
+ ProcSeqOff2ElementBridgeStats,
+ ProcSeqStartstopBridgeStats
+ );
+ if(!g_ProcBridgeStats)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ }
+#endif
+ return CommonBridgeInit();
+}
+
+IMG_VOID
+LinuxBridgeDeInit(IMG_VOID)
+{
+#if defined(DEBUG_BRIDGE_KM)
+ RemoveProcEntrySeq(g_ProcBridgeStats);
+#endif
+}
+
+#if defined(DEBUG_BRIDGE_KM)
+
+static void ProcSeqStartstopBridgeStats(struct seq_file *sfile,IMG_BOOL start)
+{
+ if(start)
+ {
+ LinuxLockMutex(&gPVRSRVLock);
+ }
+ else
+ {
+ LinuxUnLockMutex(&gPVRSRVLock);
+ }
+}
+
+
+static void* ProcSeqOff2ElementBridgeStats(struct seq_file *sfile, loff_t off)
+{
+ if(!off)
+ {
+ return PVR_PROC_SEQ_START_TOKEN;
+ }
+
+ if(off > BRIDGE_DISPATCH_TABLE_ENTRY_COUNT)
+ {
+ return (void*)0;
+ }
+
+
+ return (void*)&g_BridgeDispatchTable[off-1];
+}
+
+static void* ProcSeqNextBridgeStats(struct seq_file *sfile,void* el,loff_t off)
+{
+ return ProcSeqOff2ElementBridgeStats(sfile,off);
+}
+
+
+static void ProcSeqShowBridgeStats(struct seq_file *sfile,void* el)
+{
+ PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY *psEntry = ( PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY*)el;
+
+ if(el == PVR_PROC_SEQ_START_TOKEN)
+ {
+ seq_printf(sfile,
+ "Total ioctl call count = %u\n"
+ "Total number of bytes copied via copy_from_user = %u\n"
+ "Total number of bytes copied via copy_to_user = %u\n"
+ "Total number of bytes copied via copy_*_user = %u\n\n"
+ "%-45s | %-40s | %10s | %20s | %10s\n",
+ g_BridgeGlobalStats.ui32IOCTLCount,
+ g_BridgeGlobalStats.ui32TotalCopyFromUserBytes,
+ g_BridgeGlobalStats.ui32TotalCopyToUserBytes,
+ g_BridgeGlobalStats.ui32TotalCopyFromUserBytes+g_BridgeGlobalStats.ui32TotalCopyToUserBytes,
+ "Bridge Name",
+ "Wrapper Function",
+ "Call Count",
+ "copy_from_user Bytes",
+ "copy_to_user Bytes"
+ );
+ return;
+ }
+
+ seq_printf(sfile,
+ "%-45s %-40s %-10u %-20u %-10u\n",
+ psEntry->pszIOCName,
+ psEntry->pszFunctionName,
+ psEntry->ui32CallCount,
+ psEntry->ui32CopyFromUserTotalBytes,
+ psEntry->ui32CopyToUserTotalBytes);
+}
+
+#endif
+
+static inline int support_secure_fd_export(void)
+{
+ unsigned long mask;
+
+ PVRSRV_SGXDEV_INFO *dev_info = pvr_get_sgx_dev_info();
+
+ if (!dev_info)
+ return 0;
+
+ mask = 1 << PVR_DISABLE_SECURE_FD_EXPORT_OFFSET;
+
+ return !(dev_info->ui32ClientBuildOptions & mask);
+}
+
+static int secure_fd_export_prepare(int cmd, void *param_in, void *sec_meminfo)
+{
+ if (!support_secure_fd_export())
+ return 0;
+
+ switch (cmd) {
+ case PVRSRV_BRIDGE_EXPORT_DEVICEMEM:
+ if (sec_meminfo) {
+ pr_err("pvr: %s: can only export one MemInfo "
+ "per file descriptor", __func__);
+ return -EINVAL;
+ }
+ break;
+
+ case PVRSRV_BRIDGE_MAP_DEV_MEMORY:
+ {
+ PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY *map_devmem_in = param_in;
+
+ if (!sec_meminfo) {
+ pr_err("pvr: %s: file descriptor has no "
+ "associated MemInfo handle", __func__);
+ return -EINVAL;
+ }
+ map_devmem_in->hKernelMemInfo = sec_meminfo;
+ break;
+ }
+
+ default:
+ if (sec_meminfo) {
+ pr_err("pvr: %s: import/export handle tried "
+ "to use privileged service", __func__);
+ return -EINVAL;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+static void secure_fd_export_finish(int cmd, void *param_out,
+ void **sec_mem_info, u64 *time_stamp)
+{
+ PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM *map_devmem_out = param_out;
+
+ if (!support_secure_fd_export())
+ return;
+
+ if (cmd != PVRSRV_BRIDGE_EXPORT_DEVICEMEM)
+ return;
+
+ *sec_mem_info = map_devmem_out->hMemInfo;
+
+ ui64Stamp++;
+ *time_stamp = ui64Stamp;
+ map_devmem_out->ui64Stamp = ui64Stamp;
+}
+
+
+#if defined(SUPPORT_DRI_DRM)
+IMG_INT
+PVRSRV_BridgeDispatchKM(struct drm_device unref__ *dev, IMG_VOID *arg, struct drm_file *pFile)
+#else
+IMG_INT32
+PVRSRV_BridgeDispatchKM(struct file *pFile, IMG_UINT unref__ ioctlCmd, IMG_UINT32 arg)
+#endif
+{
+ IMG_UINT32 cmd;
+#if !defined(SUPPORT_DRI_DRM)
+ PVRSRV_BRIDGE_PACKAGE *psBridgePackageUM = (PVRSRV_BRIDGE_PACKAGE *)arg;
+ PVRSRV_BRIDGE_PACKAGE sBridgePackageKM;
+#endif
+ PVRSRV_BRIDGE_PACKAGE *psBridgePackageKM;
+ IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
+ PVRSRV_PER_PROCESS_DATA *psPerProc;
+ PVRSRV_FILE_PRIVATE_DATA *priv_data = PRIVATE_DATA(pFile);
+ IMG_INT err = -EFAULT;
+
+ LinuxLockMutex(&gPVRSRVLock);
+
+#if defined(SUPPORT_DRI_DRM)
+ psBridgePackageKM = (PVRSRV_BRIDGE_PACKAGE *)arg;
+ PVR_ASSERT(psBridgePackageKM != IMG_NULL);
+#else
+ psBridgePackageKM = &sBridgePackageKM;
+
+ if(!OSAccessOK(PVR_VERIFY_WRITE,
+ psBridgePackageUM,
+ sizeof(PVRSRV_BRIDGE_PACKAGE)))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Received invalid pointer to function arguments",
+ __FUNCTION__));
+
+ goto unlock_and_return;
+ }
+
+
+ if(OSCopyFromUser(IMG_NULL,
+ psBridgePackageKM,
+ psBridgePackageUM,
+ sizeof(PVRSRV_BRIDGE_PACKAGE))
+ != PVRSRV_OK)
+ {
+ goto unlock_and_return;
+ }
+#endif
+
+ cmd = psBridgePackageKM->ui32BridgeID;
+
+#if defined(MODULE_TEST)
+ switch (cmd)
+ {
+ case PVRSRV_BRIDGE_SERVICES_TEST_MEM1:
+ {
+ PVRSRV_ERROR eError = MemTest1();
+ if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+ {
+ PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+ pReturn->eError = eError;
+ }
+ }
+ err = 0;
+ goto unlock_and_return;
+ case PVRSRV_BRIDGE_SERVICES_TEST_MEM2:
+ {
+ PVRSRV_ERROR eError = MemTest2();
+ if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+ {
+ PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+ pReturn->eError = eError;
+ }
+ }
+ err = 0;
+ goto unlock_and_return;
+
+ case PVRSRV_BRIDGE_SERVICES_TEST_RESOURCE:
+ {
+ PVRSRV_ERROR eError = ResourceTest();
+ if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+ {
+ PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+ pReturn->eError = eError;
+ }
+ }
+ err = 0;
+ goto unlock_and_return;
+
+ case PVRSRV_BRIDGE_SERVICES_TEST_EVENTOBJECT:
+ {
+ PVRSRV_ERROR eError = EventObjectTest();
+ if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+ {
+ PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+ pReturn->eError = eError;
+ }
+ }
+ err = 0;
+ goto unlock_and_return;
+
+ case PVRSRV_BRIDGE_SERVICES_TEST_MEMMAPPING:
+ {
+ PVRSRV_ERROR eError = MemMappingTest();
+ if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+ {
+ PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+ pReturn->eError = eError;
+ }
+ }
+ err = 0;
+ goto unlock_and_return;
+
+ case PVRSRV_BRIDGE_SERVICES_TEST_PROCESSID:
+ {
+ PVRSRV_ERROR eError = ProcessIDTest();
+ if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+ {
+ PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+ pReturn->eError = eError;
+ }
+ }
+ err = 0;
+ goto unlock_and_return;
+
+ case PVRSRV_BRIDGE_SERVICES_TEST_CLOCKUSWAITUS:
+ {
+ PVRSRV_ERROR eError = ClockusWaitusTest();
+ if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+ {
+ PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+ pReturn->eError = eError;
+ }
+ }
+ err = 0;
+ goto unlock_and_return;
+
+ case PVRSRV_BRIDGE_SERVICES_TEST_TIMER:
+ {
+ PVRSRV_ERROR eError = TimerTest();
+ if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+ {
+ PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+ pReturn->eError = eError;
+ }
+ }
+ err = 0;
+ goto unlock_and_return;
+
+ case PVRSRV_BRIDGE_SERVICES_TEST_PRIVSRV:
+ {
+ PVRSRV_ERROR eError = PrivSrvTest();
+ if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+ {
+ PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+ pReturn->eError = eError;
+ }
+ }
+ err = 0;
+ goto unlock_and_return;
+ case PVRSRV_BRIDGE_SERVICES_TEST_COPYDATA:
+ {
+ IMG_UINT32 ui32PID;
+ PVRSRV_PER_PROCESS_DATA *psPerProc;
+ PVRSRV_ERROR eError;
+
+ ui32PID = OSGetCurrentProcessIDKM();
+
+ PVRSRVTrace("PVRSRV_BRIDGE_SERVICES_TEST_COPYDATA %d", ui32PID);
+
+ psPerProc = PVRSRVPerProcessData(ui32PID);
+
+ eError = CopyDataTest(psBridgePackageKM->pvParamIn, psBridgePackageKM->pvParamOut, psPerProc);
+
+ *(PVRSRV_ERROR*)psBridgePackageKM->pvParamOut = eError;
+ err = 0;
+ goto unlock_and_return;
+ }
+
+
+ case PVRSRV_BRIDGE_SERVICES_TEST_POWERMGMT:
+ {
+ PVRSRV_ERROR eError = PowerMgmtTest();
+ if (psBridgePackageKM->ui32OutBufferSize == sizeof(PVRSRV_BRIDGE_RETURN))
+ {
+ PVRSRV_BRIDGE_RETURN* pReturn = (PVRSRV_BRIDGE_RETURN*)psBridgePackageKM->pvParamOut ;
+ pReturn->eError = eError;
+ }
+ }
+ err = 0;
+ goto unlock_and_return;
+
+ }
+#endif
+
+ if(cmd != PVRSRV_BRIDGE_CONNECT_SERVICES)
+ {
+ PVRSRV_ERROR eError;
+
+ eError = PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
+ (IMG_PVOID *)&psPerProc,
+ psBridgePackageKM->hKernelServices,
+ PVRSRV_HANDLE_TYPE_PERPROC_DATA);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Invalid kernel services handle (%d)",
+ __FUNCTION__, eError));
+ goto unlock_and_return;
+ }
+
+ if(psPerProc->ui32PID != ui32PID)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Process %d tried to access data "
+ "belonging to process %d", __FUNCTION__, ui32PID,
+ psPerProc->ui32PID));
+ goto unlock_and_return;
+ }
+ }
+ else
+ {
+
+ psPerProc = PVRSRVPerProcessData(ui32PID);
+ if(psPerProc == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRV_BridgeDispatchKM: "
+ "Couldn't create per-process data area"));
+ goto unlock_and_return;
+ }
+ }
+
+ psBridgePackageKM->ui32BridgeID = PVRSRV_GET_BRIDGE_ID(psBridgePackageKM->ui32BridgeID);
+
+ /*
+ * FIXME: remove the following workaround, once all user space libraries
+ * have a proper fix for this security issue.
+ */
+ err = secure_fd_export_prepare(cmd, psBridgePackageKM->pvParamIn,
+ priv_data->sec_fd_exp_meminfo);
+ if (err < 0)
+ goto unlock_and_return;
+
+#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
+ switch(cmd)
+ {
+ case PVRSRV_BRIDGE_MAP_DEV_MEMORY:
+ case PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY:
+ {
+ PVRSRV_FILE_PRIVATE_DATA *psPrivateData;
+ IMG_INT authenticated = pFile->authenticated;
+ PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc;
+
+ if (authenticated)
+ {
+ break;
+ }
+
+
+ psEnvPerProc = (PVRSRV_ENV_PER_PROCESS_DATA *)PVRSRVProcessPrivateData(psPerProc);
+ if (psEnvPerProc == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Process private data not allocated", __FUNCTION__));
+ err = -EFAULT;
+ goto unlock_and_return;
+ }
+
+ list_for_each_entry(psPrivateData, &psEnvPerProc->sDRMAuthListHead, sDRMAuthListItem)
+ {
+ struct drm_file *psDRMFile = psPrivateData->psDRMFile;
+
+ if (pFile->master == psDRMFile->master)
+ {
+ authenticated |= psDRMFile->authenticated;
+ if (authenticated)
+ {
+ break;
+ }
+ }
+ }
+
+ if (!authenticated)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Not authenticated for mapping device or device class memory", __FUNCTION__));
+ err = -EPERM;
+ goto unlock_and_return;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+#endif
+
+ err = BridgedDispatchKM(psPerProc, psBridgePackageKM);
+ if(err != PVRSRV_OK)
+ goto unlock_and_return;
+
+ /*
+ * FIXME: remove the following workaround, once all user space libraries
+ * have a proper fix for this security issue.
+ */
+ secure_fd_export_finish(cmd, psBridgePackageKM->pvParamOut,
+ &priv_data->sec_fd_exp_meminfo,
+ &priv_data->ui64Stamp);
+ switch(cmd)
+ {
+#if defined(SUPPORT_MEMINFO_IDS)
+ case PVRSRV_BRIDGE_MAP_DEV_MEMORY:
+ {
+ PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY *psMapDeviceMemoryOUT =
+ (PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY *)psBridgePackageKM->pvParamOut;
+ PVRSRV_FILE_PRIVATE_DATA *psPrivateData = PRIVATE_DATA(pFile);
+ psMapDeviceMemoryOUT->sDstClientMemInfo.ui64Stamp = psPrivateData->ui64Stamp;
+ break;
+ }
+
+ case PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY:
+ {
+ PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY *psDeviceClassMemoryOUT =
+ (PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY *)psBridgePackageKM->pvParamOut;
+ psDeviceClassMemoryOUT->sClientMemInfo.ui64Stamp = ++ui64Stamp;
+ break;
+ }
+#endif
+
+ default:
+ break;
+ }
+
+unlock_and_return:
+ LinuxUnLockMutex(&gPVRSRVLock);
+ return err;
+}
--- /dev/null
+/**********************************************************************
+ *
+ * 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 <asm/io.h>
+#include <asm/uaccess.h>
+#include <linux/kernel.h>
+#include <linux/hardirq.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <stdarg.h>
+#include "img_types.h"
+#include "servicesext.h"
+#include "pvr_debug.h"
+#include "srvkm.h"
+#include "proc.h"
+#include "mutex.h"
+#include "linkage.h"
+
+static IMG_BOOL VBAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz,
+ const IMG_CHAR* pszFormat, va_list VArgs)
+ IMG_FORMAT_PRINTF(3, 0);
+
+
+#if defined(PVRSRV_NEED_PVR_DPF)
+
+#define PVR_MAX_FILEPATH_LEN 256
+
+static IMG_BOOL BAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz,
+ const IMG_CHAR *pszFormat, ...)
+ IMG_FORMAT_PRINTF(3, 4);
+
+IMG_UINT32 gPVRDebugLevel =
+ (DBGPRIV_FATAL | DBGPRIV_ERROR | DBGPRIV_WARNING);
+
+#endif
+
+#define PVR_MAX_MSG_LEN PVR_MAX_DEBUG_MESSAGE_LEN
+
+static IMG_CHAR gszBufferNonIRQ[PVR_MAX_MSG_LEN + 1];
+
+static IMG_CHAR gszBufferIRQ[PVR_MAX_MSG_LEN + 1];
+
+static PVRSRV_LINUX_MUTEX gsDebugMutexNonIRQ;
+
+
+static DEFINE_SPINLOCK(gsDebugLockIRQ);
+
+#if !defined (USE_SPIN_LOCK)
+#define USE_SPIN_LOCK (in_interrupt() || !preemptible())
+#endif
+
+static inline void GetBufferLock(unsigned long *pulLockFlags)
+{
+ if (USE_SPIN_LOCK)
+ {
+ spin_lock_irqsave(&gsDebugLockIRQ, *pulLockFlags);
+ }
+ else
+ {
+ LinuxLockMutex(&gsDebugMutexNonIRQ);
+ }
+}
+
+static inline void ReleaseBufferLock(unsigned long ulLockFlags)
+{
+ if (USE_SPIN_LOCK)
+ {
+ spin_unlock_irqrestore(&gsDebugLockIRQ, ulLockFlags);
+ }
+ else
+ {
+ LinuxUnLockMutex(&gsDebugMutexNonIRQ);
+ }
+}
+
+static inline void SelectBuffer(IMG_CHAR **ppszBuf, IMG_UINT32 *pui32BufSiz)
+{
+ if (USE_SPIN_LOCK)
+ {
+ *ppszBuf = gszBufferIRQ;
+ *pui32BufSiz = sizeof(gszBufferIRQ);
+ }
+ else
+ {
+ *ppszBuf = gszBufferNonIRQ;
+ *pui32BufSiz = sizeof(gszBufferNonIRQ);
+ }
+}
+
+static IMG_BOOL VBAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz, const IMG_CHAR* pszFormat, va_list VArgs)
+{
+ IMG_UINT32 ui32Used;
+ IMG_UINT32 ui32Space;
+ IMG_INT32 i32Len;
+
+ ui32Used = strlen(pszBuf);
+ BUG_ON(ui32Used >= ui32BufSiz);
+ ui32Space = ui32BufSiz - ui32Used;
+
+ i32Len = vsnprintf(&pszBuf[ui32Used], ui32Space, pszFormat, VArgs);
+ pszBuf[ui32BufSiz - 1] = 0;
+
+
+ return (i32Len < 0 || i32Len >= (IMG_INT32)ui32Space) ? IMG_TRUE : IMG_FALSE;
+}
+
+IMG_VOID PVRDPFInit(IMG_VOID)
+{
+ LinuxInitMutex(&gsDebugMutexNonIRQ);
+}
+
+IMG_VOID PVRSRVReleasePrintf(const IMG_CHAR *pszFormat, ...)
+{
+ va_list vaArgs;
+ unsigned long ulLockFlags = 0;
+ IMG_CHAR *pszBuf;
+ IMG_UINT32 ui32BufSiz;
+
+ SelectBuffer(&pszBuf, &ui32BufSiz);
+
+ va_start(vaArgs, pszFormat);
+
+ GetBufferLock(&ulLockFlags);
+ strncpy (pszBuf, "PVR_K: ", (ui32BufSiz -1));
+
+ if (VBAppend(pszBuf, ui32BufSiz, pszFormat, vaArgs))
+ {
+ printk(KERN_INFO "PVR_K:(Message Truncated): %s\n", pszBuf);
+ }
+ else
+ {
+ printk(KERN_INFO "%s\n", pszBuf);
+ }
+
+ ReleaseBufferLock(ulLockFlags);
+ va_end(vaArgs);
+
+}
+
+#if defined(PVRSRV_NEED_PVR_ASSERT)
+
+IMG_VOID PVRSRVDebugAssertFail(const IMG_CHAR* pszFile, IMG_UINT32 uLine)
+{
+ PVRSRVDebugPrintf(DBGPRIV_FATAL, pszFile, uLine, "Debug assertion failed!");
+ BUG();
+}
+
+#endif
+
+#if defined(PVRSRV_NEED_PVR_TRACE)
+
+IMG_VOID PVRSRVTrace(const IMG_CHAR* pszFormat, ...)
+{
+ va_list VArgs;
+ unsigned long ulLockFlags = 0;
+ IMG_CHAR *pszBuf;
+ IMG_UINT32 ui32BufSiz;
+
+ SelectBuffer(&pszBuf, &ui32BufSiz);
+
+ va_start(VArgs, pszFormat);
+
+ GetBufferLock(&ulLockFlags);
+
+ strncpy(pszBuf, "PVR: ", (ui32BufSiz -1));
+
+ if (VBAppend(pszBuf, ui32BufSiz, pszFormat, VArgs))
+ {
+ printk(KERN_INFO "PVR_K:(Message Truncated): %s\n", pszBuf);
+ }
+ else
+ {
+ printk(KERN_INFO "%s\n", pszBuf);
+ }
+
+ ReleaseBufferLock(ulLockFlags);
+
+ va_end(VArgs);
+}
+
+#endif
+
+#if defined(PVRSRV_NEED_PVR_DPF)
+
+static IMG_BOOL BAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz, const IMG_CHAR *pszFormat, ...)
+{
+ va_list VArgs;
+ IMG_BOOL bTrunc;
+
+ va_start (VArgs, pszFormat);
+
+ bTrunc = VBAppend(pszBuf, ui32BufSiz, pszFormat, VArgs);
+
+ va_end (VArgs);
+
+ return bTrunc;
+}
+
+IMG_VOID PVRSRVDebugPrintf (
+ IMG_UINT32 ui32DebugLevel,
+ const IMG_CHAR* pszFullFileName,
+ IMG_UINT32 ui32Line,
+ const IMG_CHAR* pszFormat,
+ ...
+ )
+{
+ IMG_BOOL bTrace;
+ const IMG_CHAR *pszFileName = pszFullFileName;
+ IMG_CHAR *pszLeafName;
+
+
+ bTrace = (IMG_BOOL)(ui32DebugLevel & DBGPRIV_CALLTRACE) ? IMG_TRUE : IMG_FALSE;
+
+ if (gPVRDebugLevel & ui32DebugLevel)
+ {
+ va_list vaArgs;
+ unsigned long ulLockFlags = 0;
+ IMG_CHAR *pszBuf;
+ IMG_UINT32 ui32BufSiz;
+
+ SelectBuffer(&pszBuf, &ui32BufSiz);
+
+ va_start(vaArgs, pszFormat);
+
+ GetBufferLock(&ulLockFlags);
+
+
+ if (bTrace == IMG_FALSE)
+ {
+ switch(ui32DebugLevel)
+ {
+ case DBGPRIV_FATAL:
+ {
+ strncpy (pszBuf, "PVR_K:(Fatal): ", (ui32BufSiz -1));
+ break;
+ }
+ case DBGPRIV_ERROR:
+ {
+ strncpy (pszBuf, "PVR_K:(Error): ", (ui32BufSiz -1));
+ break;
+ }
+ case DBGPRIV_WARNING:
+ {
+ strncpy (pszBuf, "PVR_K:(Warning): ", (ui32BufSiz -1));
+ break;
+ }
+ case DBGPRIV_MESSAGE:
+ {
+ strncpy (pszBuf, "PVR_K:(Message): ", (ui32BufSiz -1));
+ break;
+ }
+ case DBGPRIV_VERBOSE:
+ {
+ strncpy (pszBuf, "PVR_K:(Verbose): ", (ui32BufSiz -1));
+ break;
+ }
+ default:
+ {
+ strncpy (pszBuf, "PVR_K:(Unknown message level)", (ui32BufSiz -1));
+ break;
+ }
+ }
+ }
+ else
+ {
+ strncpy (pszBuf, "PVR_K: ", (ui32BufSiz -1));
+ }
+
+ if (VBAppend(pszBuf, ui32BufSiz, pszFormat, vaArgs))
+ {
+ printk(KERN_INFO "PVR_K:(Message Truncated): %s\n", pszBuf);
+ }
+ else
+ {
+
+ if (bTrace == IMG_FALSE)
+ {
+#ifdef DEBUG_LOG_PATH_TRUNCATE
+
+ static IMG_CHAR szFileNameRewrite[PVR_MAX_FILEPATH_LEN];
+
+ IMG_CHAR* pszTruncIter;
+ IMG_CHAR* pszTruncBackInter;
+
+
+ pszFileName = pszFullFileName + strlen(DEBUG_LOG_PATH_TRUNCATE)+1;
+
+
+ strncpy(szFileNameRewrite, pszFileName,PVR_MAX_FILEPATH_LEN);
+
+ if(strlen(szFileNameRewrite) == PVR_MAX_FILEPATH_LEN-1) {
+ IMG_CHAR szTruncateMassage[] = "FILENAME TRUNCATED";
+ strcpy(szFileNameRewrite + (PVR_MAX_FILEPATH_LEN - 1 - strlen(szTruncateMassage)), szTruncateMassage);
+ }
+
+ pszTruncIter = szFileNameRewrite;
+ while(*pszTruncIter++ != 0)
+ {
+ IMG_CHAR* pszNextStartPoint;
+
+ if(
+ !( ( *pszTruncIter == '/' && (pszTruncIter-4 >= szFileNameRewrite) ) &&
+ ( *(pszTruncIter-1) == '.') &&
+ ( *(pszTruncIter-2) == '.') &&
+ ( *(pszTruncIter-3) == '/') )
+ ) continue;
+
+
+ pszTruncBackInter = pszTruncIter - 3;
+ while(*(--pszTruncBackInter) != '/')
+ {
+ if(pszTruncBackInter <= szFileNameRewrite) break;
+ }
+ pszNextStartPoint = pszTruncBackInter;
+
+
+ while(*pszTruncIter != 0)
+ {
+ *pszTruncBackInter++ = *pszTruncIter++;
+ }
+ *pszTruncBackInter = 0;
+
+
+ pszTruncIter = pszNextStartPoint;
+ }
+
+ pszFileName = szFileNameRewrite;
+
+ if(*pszFileName == '/') pszFileName++;
+#endif
+
+#if !defined(__sh__)
+ pszLeafName = (IMG_CHAR *)strrchr (pszFileName, '\\');
+
+ if (pszLeafName)
+ {
+ pszFileName = pszLeafName;
+ }
+#endif
+
+ if (BAppend(pszBuf, ui32BufSiz, " [%u, %s]", ui32Line, pszFileName))
+ {
+ printk(KERN_INFO "PVR_K:(Message Truncated): %s\n", pszBuf);
+ }
+ else
+ {
+ printk(KERN_INFO "%s\n", pszBuf);
+ }
+ }
+ else
+ {
+ printk(KERN_INFO "%s\n", pszBuf);
+ }
+ }
+
+ ReleaseBufferLock(ulLockFlags);
+
+ va_end (vaArgs);
+ }
+}
+
+#endif
+
+#if defined(DEBUG)
+
+IMG_INT PVRDebugProcSetLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT32 count, IMG_VOID *data)
+{
+#define _PROC_SET_BUFFER_SZ 2
+ IMG_CHAR data_buffer[_PROC_SET_BUFFER_SZ];
+
+ if (count != _PROC_SET_BUFFER_SZ)
+ {
+ return -EINVAL;
+ }
+ else
+ {
+ if (copy_from_user(data_buffer, buffer, count))
+ return -EINVAL;
+ if (data_buffer[count - 1] != '\n')
+ return -EINVAL;
+ gPVRDebugLevel = data_buffer[0] - '0';
+ }
+ return (count);
+}
+
+void ProcSeqShowDebugLevel(struct seq_file *sfile,void* el)
+{
+ seq_printf(sfile, "%u\n", gPVRDebugLevel);
+}
+
+#endif
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#if defined(SUPPORT_DRI_DRM)
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <asm/ioctl.h>
+#include <drm/drmP.h>
+#include <drm/drm.h>
+
+#include "img_defs.h"
+#include "services.h"
+#include "kerneldisplay.h"
+#include "kernelbuffer.h"
+#include "syscommon.h"
+#include "pvrmmap.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 "pvr_bridge.h"
+#include "proc.h"
+#include "pvrmodule.h"
+#include "pvrversion.h"
+#include "lock.h"
+#include "linkage.h"
+#include "pvr_drm.h"
+
+#if defined(PVR_DRI_DRM_NOT_PCI)
+#include "pvr_drm_mod.h"
+#endif
+
+#define PVR_DRM_NAME PVRSRV_MODNAME
+#define PVR_DRM_DESC "Imagination Technologies PVR DRM"
+
+#if !defined(PVR_DRI_DRM_NOT_PCI)
+struct pci_dev *gpsPVRLDMDev;
+#endif
+
+struct drm_device *gpsPVRDRMDev;
+
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,24))
+#error "Linux kernel version 2.6.25 or later required for PVR DRM support"
+#endif
+
+#define PVR_DRM_FILE struct drm_file *
+
+#if !defined(SUPPORT_DRI_DRM_EXT)
+static struct pci_device_id asPciIdList[] = {
+#if defined(PVR_DRI_DRM_NOT_PCI)
+ {1, 1, 1, 1, 0, 0, 0},
+#else
+ {SYS_SGX_DEV_VENDOR_ID, SYS_SGX_DEV_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#if defined(SYS_SGX_DEV1_DEVICE_ID)
+ {SYS_SGX_DEV_VENDOR_ID, SYS_SGX_DEV1_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+#endif
+#endif
+ {0}
+};
+#endif
+
+DRI_DRM_STATIC IMG_INT
+PVRSRVDrmLoad(struct drm_device *dev, IMG_UINT32 flags)
+{
+ IMG_INT iRes;
+
+ PVR_TRACE(("PVRSRVDrmLoad"));
+
+ gpsPVRDRMDev = dev;
+#if !defined(PVR_DRI_DRM_NOT_PCI)
+ gpsPVRLDMDev = dev->pdev;
+#endif
+
+#if defined(PDUMP)
+ iRes = dbgdrv_init();
+ if (iRes != 0)
+ {
+ return iRes;
+ }
+#endif
+
+ iRes = PVRCore_Init();
+ if (iRes != 0)
+ {
+ goto exit_dbgdrv_cleanup;
+ }
+
+#if defined(DISPLAY_CONTROLLER)
+ iRes = PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Init)(dev);
+ if (iRes != 0)
+ {
+ goto exit_pvrcore_cleanup;
+ }
+#endif
+ return 0;
+
+#if defined(DISPLAY_CONTROLLER)
+exit_pvrcore_cleanup:
+ PVRCore_Cleanup();
+#endif
+exit_dbgdrv_cleanup:
+#if defined(PDUMP)
+ dbgdrv_cleanup();
+#endif
+ return iRes;
+}
+
+DRI_DRM_STATIC IMG_INT
+PVRSRVDrmUnload(struct drm_device *dev)
+{
+ PVR_TRACE(("PVRSRVDrmUnload"));
+
+#if defined(DISPLAY_CONTROLLER)
+ PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Cleanup)(dev);
+#endif
+
+ PVRCore_Cleanup();
+
+#if defined(PDUMP)
+ dbgdrv_cleanup();
+#endif
+
+ return 0;
+}
+
+DRI_DRM_STATIC IMG_INT
+PVRSRVDrmOpen(struct drm_device *dev, struct drm_file *file)
+{
+ return PVRSRVOpen(dev, file);
+}
+
+#if defined(SUPPORT_DRI_DRM_EXT) && !defined(PVR_LINUX_USING_WORKQUEUES)
+DRI_DRM_STATIC void
+PVRSRVDrmPostClose(struct drm_device *dev, struct drm_file *file)
+{
+ PVRSRVRelease(file->driver_priv);
+
+ file->driver_priv = NULL;
+}
+#else
+DRI_DRM_STATIC IMG_INT
+PVRSRVDrmRelease(struct inode *inode, struct file *filp)
+{
+ struct drm_file *file_priv = filp->private_data;
+ void *psDriverPriv = file_priv->driver_priv;
+ IMG_INT ret;
+
+ ret = drm_release(inode, filp);
+
+ if (ret != 0)
+ {
+
+ PVR_DPF((PVR_DBG_ERROR, "%s : drm_release failed: %d",
+ __FUNCTION__, ret));
+}
+
+ PVRSRVRelease(psDriverPriv);
+
+ return 0;
+}
+#endif
+
+DRI_DRM_STATIC IMG_INT
+PVRDRMIsMaster(struct drm_device *dev, void *arg, struct drm_file *pFile)
+{
+ return 0;
+}
+
+#if defined(SUPPORT_DRI_DRM_EXT)
+IMG_INT
+PVRDRM_Dummy_ioctl(struct drm_device *dev, void *arg, struct drm_file *pFile)
+{
+ return 0;
+}
+#endif
+
+DRI_DRM_STATIC IMG_INT
+PVRDRMUnprivCmd(struct drm_device *dev, void *arg, struct drm_file *pFile)
+{
+ IMG_INT ret = 0;
+
+ LinuxLockMutex(&gPVRSRVLock);
+
+ if (arg == NULL)
+ {
+ ret = -EFAULT;
+ }
+ else
+ {
+ IMG_UINT32 *pui32Args = (IMG_UINT32 *)arg;
+ IMG_UINT32 ui32Cmd = pui32Args[0];
+ IMG_UINT32 *pui32OutArg = (IMG_UINT32 *)arg;
+
+ switch (ui32Cmd)
+ {
+ case PVR_DRM_UNPRIV_INIT_SUCCESFUL:
+ *pui32OutArg = PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL) ? 1 : 0;
+ break;
+
+ default:
+ ret = -EFAULT;
+ }
+
+ }
+
+ LinuxUnLockMutex(&gPVRSRVLock);
+
+ return ret;
+}
+
+#if defined(DISPLAY_CONTROLLER) && defined(PVR_DISPLAY_CONTROLLER_DRM_IOCTL)
+static IMG_INT
+PVRDRM_Display_ioctl(struct drm_device *dev, void *arg, struct drm_file *pFile)
+{
+ IMG_INT res;
+
+ LinuxLockMutex(&gPVRSRVLock);
+
+ res = PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Ioctl)(dev, arg, pFile);
+
+ LinuxUnLockMutex(&gPVRSRVLock);
+
+ return res;
+}
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
+#define PVR_DRM_FOPS_IOCTL .unlocked_ioctl
+#define PVR_DRM_UNLOCKED DRM_UNLOCKED
+#else
+#define PVR_DRM_FOPS_IOCTL .ioctl
+#define PVR_DRM_UNLOCKED 0
+#endif
+
+#if !defined(SUPPORT_DRI_DRM_EXT)
+struct drm_ioctl_desc sPVRDrmIoctls[] = {
+ DRM_IOCTL_DEF(PVR_DRM_SRVKM_IOCTL, PVRSRV_BridgeDispatchKM, PVR_DRM_UNLOCKED),
+ DRM_IOCTL_DEF(PVR_DRM_IS_MASTER_IOCTL, PVRDRMIsMaster, DRM_MASTER | PVR_DRM_UNLOCKED),
+ DRM_IOCTL_DEF(PVR_DRM_UNPRIV_IOCTL, PVRDRMUnprivCmd, PVR_DRM_UNLOCKED),
+#if defined(PDUMP)
+ DRM_IOCTL_DEF(PVR_DRM_DBGDRV_IOCTL, dbgdrv_ioctl, PVR_DRM_UNLOCKED),
+#endif
+#if defined(DISPLAY_CONTROLLER) && defined(PVR_DISPLAY_CONTROLLER_DRM_IOCTL)
+ DRM_IOCTL_DEF(PVR_DRM_DISP_IOCTL, PVRDRM_Display_ioctl, DRM_MASTER | PVR_DRM_UNLOCKED)
+#endif
+};
+
+static IMG_INT pvr_max_ioctl = DRM_ARRAY_SIZE(sPVRDrmIoctls);
+
+static struct drm_driver sPVRDrmDriver =
+{
+ .driver_features = 0,
+ .dev_priv_size = 0,
+ .load = PVRSRVDrmLoad,
+ .unload = PVRSRVDrmUnload,
+ .open = PVRSRVDrmOpen,
+ .suspend = PVRSRVDriverSuspend,
+ .resume = PVRSRVDriverResume,
+ .get_map_ofs = drm_core_get_map_ofs,
+ .get_reg_ofs = drm_core_get_reg_ofs,
+ .ioctls = sPVRDrmIoctls,
+ .fops =
+ {
+ .owner = THIS_MODULE,
+ .open = drm_open,
+ .release = PVRSRVDrmRelease,
+ PVR_DRM_FOPS_IOCTL = drm_ioctl,
+ .mmap = PVRMMap,
+ .poll = drm_poll,
+ .fasync = drm_fasync,
+ },
+ .pci_driver =
+ {
+ .name = PVR_DRM_NAME,
+ .id_table = asPciIdList,
+ },
+
+ .name = PVR_DRM_NAME,
+ .desc = PVR_DRM_DESC,
+ .date = PVR_BUILD_DATE,
+ .major = PVRVERSION_MAJ,
+ .minor = PVRVERSION_MIN,
+ .patchlevel = PVRVERSION_BUILD,
+};
+
+static IMG_INT __init PVRSRVDrmInit(void)
+{
+ IMG_INT iRes;
+ sPVRDrmDriver.num_ioctls = pvr_max_ioctl;
+
+
+ PVRDPFInit();
+
+#if defined(PVR_DRI_DRM_NOT_PCI)
+ iRes = drm_pvr_dev_add();
+ if (iRes != 0)
+ {
+ return iRes;
+ }
+#endif
+
+ iRes = drm_init(&sPVRDrmDriver);
+#if defined(PVR_DRI_DRM_NOT_PCI)
+ if (iRes != 0)
+ {
+ drm_pvr_dev_remove();
+ }
+#endif
+ return iRes;
+}
+
+static void __exit PVRSRVDrmExit(void)
+{
+ drm_exit(&sPVRDrmDriver);
+
+#if defined(PVR_DRI_DRM_NOT_PCI)
+ drm_pvr_dev_remove();
+#endif
+}
+
+module_init(PVRSRVDrmInit);
+module_exit(PVRSRVDrmExit);
+#endif
+#endif
+
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#if !defined(__PVR_DRM_H__)
+#define __PVR_DRM_H__
+
+#include "pvr_drm_shared.h"
+
+#if defined(SUPPORT_DRI_DRM)
+#define PVR_DRM_MAKENAME_HELPER(x, y) x ## y
+#define PVR_DRM_MAKENAME(x, y) PVR_DRM_MAKENAME_HELPER(x, y)
+
+IMG_INT PVRCore_Init(IMG_VOID);
+IMG_VOID PVRCore_Cleanup(IMG_VOID);
+IMG_INT PVRSRVOpen(struct drm_device *dev, struct drm_file *pFile);
+IMG_VOID PVRSRVRelease(IMG_VOID *pvPrivData);
+IMG_INT PVRSRVDriverSuspend(struct drm_device *pDevice, pm_message_t state);
+IMG_INT PVRSRVDriverResume(struct drm_device *pDevice);
+
+IMG_INT PVRSRV_BridgeDispatchKM(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+
+#if defined(SUPPORT_DRI_DRM_EXT)
+#define DRI_DRM_STATIC
+IMG_INT PVRSRVDrmLoad(struct drm_device *dev, IMG_UINT32 flags);
+IMG_INT PVRSRVDrmUnload(struct drm_device *dev);
+IMG_INT PVRSRVDrmOpen(struct drm_device *dev, struct drm_file *file);
+#if defined(PVR_LINUX_USING_WORKQUEUES)
+DRI_DRM_STATIC IMG_INT PVRSRVDrmRelease(struct inode *inode, struct file *filp);
+#else
+IMG_VOID PVRSRVDrmPostClose(struct drm_device *dev, struct drm_file *file);
+#endif
+IMG_INT PVRDRMIsMaster(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+IMG_INT PVRDRMUnprivCmd(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+IMG_INT PVRDRM_Dummy_ioctl(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+#else
+#define DRI_DRM_STATIC static
+#endif
+
+#if defined(DISPLAY_CONTROLLER)
+extern IMG_INT PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Init)(struct drm_device *);
+extern IMG_VOID PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Cleanup)(struct drm_device *);
+extern IMG_INT PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Suspend)(struct drm_device *);
+extern IMG_INT PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Resume)(struct drm_device *);
+#if defined(PVR_DISPLAY_CONTROLLER_DRM_IOCTL)
+extern IMG_INT PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Ioctl)(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+#endif
+#endif
+
+#if defined(PDUMP)
+IMG_INT dbgdrv_init(IMG_VOID);
+IMG_VOID dbgdrv_cleanup(IMG_VOID);
+IMG_INT dbgdrv_ioctl(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+#endif
+
+#if !defined(SUPPORT_DRI_DRM_EXT)
+#define PVR_DRM_SRVKM_IOCTL _IO(0, PVR_DRM_SRVKM_CMD)
+#define PVR_DRM_IS_MASTER_IOCTL _IO(0, PVR_DRM_IS_MASTER_CMD)
+#define PVR_DRM_UNPRIV_IOCTL _IO(0, PVR_DRM_UNPRIV_CMD)
+#define PVR_DRM_DBGDRV_IOCTL _IO(0, PVR_DRM_DBGDRV_CMD)
+#define PVR_DRM_DISP_IOCTL _IO(0, PVR_DRM_DISP_CMD)
+#endif
+
+#endif
+
+#endif
+
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef _SGX535DEFS_KM_H_
+#define _SGX535DEFS_KM_H_
+
+#define EUR_CR_CLKGATECTL 0x0000
+#define EUR_CR_CLKGATECTL_2D_CLKG_MASK 0x00000003U
+#define EUR_CR_CLKGATECTL_2D_CLKG_SHIFT 0
+#define EUR_CR_CLKGATECTL_ISP_CLKG_MASK 0x00000030U
+#define EUR_CR_CLKGATECTL_ISP_CLKG_SHIFT 4
+#define EUR_CR_CLKGATECTL_TSP_CLKG_MASK 0x00000300U
+#define EUR_CR_CLKGATECTL_TSP_CLKG_SHIFT 8
+#define EUR_CR_CLKGATECTL_TA_CLKG_MASK 0x00003000U
+#define EUR_CR_CLKGATECTL_TA_CLKG_SHIFT 12
+#define EUR_CR_CLKGATECTL_DPM_CLKG_MASK 0x00030000U
+#define EUR_CR_CLKGATECTL_DPM_CLKG_SHIFT 16
+#define EUR_CR_CLKGATECTL_USE_CLKG_MASK 0x00300000U
+#define EUR_CR_CLKGATECTL_USE_CLKG_SHIFT 20
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_MASK 0x01000000U
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_SHIFT 24
+#define EUR_CR_CLKGATESTATUS 0x0004
+#define EUR_CR_CLKGATESTATUS_2D_CLKS_MASK 0x00000001
+#define EUR_CR_CLKGATESTATUS_2D_CLKS_SHIFT 0
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_MASK 0x00000010U
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_SHIFT 4
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_MASK 0x00000100U
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_SHIFT 8
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_MASK 0x00001000U
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_SHIFT 12
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_MASK 0x00010000U
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_SHIFT 16
+#define EUR_CR_CLKGATESTATUS_USE_CLKS_MASK 0x00100000U
+#define EUR_CR_CLKGATESTATUS_USE_CLKS_SHIFT 20
+#define EUR_CR_CLKGATECTLOVR 0x0008
+#define EUR_CR_CLKGATECTLOVR_2D_CLKO_MASK 0x00000003U
+#define EUR_CR_CLKGATECTLOVR_2D_CLKO_SHIFT 0
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_MASK 0x00000030U
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_SHIFT 4
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_MASK 0x00000300U
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_SHIFT 8
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_MASK 0x00003000U
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_SHIFT 12
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_MASK 0x00030000U
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_SHIFT 16
+#define EUR_CR_CLKGATECTLOVR_USE_CLKO_MASK 0x00300000U
+#define EUR_CR_CLKGATECTLOVR_USE_CLKO_SHIFT 20
+#define EUR_CR_CORE_ID 0x0010
+#define EUR_CR_CORE_ID_CONFIG_MASK 0x0000FFFFU
+#define EUR_CR_CORE_ID_CONFIG_SHIFT 0
+#define EUR_CR_CORE_ID_ID_MASK 0xFFFF0000U
+#define EUR_CR_CORE_ID_ID_SHIFT 16
+#define EUR_CR_CORE_REVISION 0x0014
+#define EUR_CR_CORE_REVISION_MAINTENANCE_MASK 0x000000FFU
+#define EUR_CR_CORE_REVISION_MAINTENANCE_SHIFT 0
+#define EUR_CR_CORE_REVISION_MINOR_MASK 0x0000FF00U
+#define EUR_CR_CORE_REVISION_MINOR_SHIFT 8
+#define EUR_CR_CORE_REVISION_MAJOR_MASK 0x00FF0000U
+#define EUR_CR_CORE_REVISION_MAJOR_SHIFT 16
+#define EUR_CR_CORE_REVISION_DESIGNER_MASK 0xFF000000U
+#define EUR_CR_CORE_REVISION_DESIGNER_SHIFT 24
+#define EUR_CR_DESIGNER_REV_FIELD1 0x0018
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_MASK 0xFFFFFFFFU
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_SHIFT 0
+#define EUR_CR_DESIGNER_REV_FIELD2 0x001C
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_MASK 0xFFFFFFFFU
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_SHIFT 0
+#define EUR_CR_SOFT_RESET 0x0080
+#define EUR_CR_SOFT_RESET_BIF_RESET_MASK 0x00000001U
+#define EUR_CR_SOFT_RESET_BIF_RESET_SHIFT 0
+#define EUR_CR_SOFT_RESET_TWOD_RESET_MASK 0x00000002U
+#define EUR_CR_SOFT_RESET_TWOD_RESET_SHIFT 1
+#define EUR_CR_SOFT_RESET_DPM_RESET_MASK 0x00000004U
+#define EUR_CR_SOFT_RESET_DPM_RESET_SHIFT 2
+#define EUR_CR_SOFT_RESET_TA_RESET_MASK 0x00000008U
+#define EUR_CR_SOFT_RESET_TA_RESET_SHIFT 3
+#define EUR_CR_SOFT_RESET_USE_RESET_MASK 0x00000010U
+#define EUR_CR_SOFT_RESET_USE_RESET_SHIFT 4
+#define EUR_CR_SOFT_RESET_ISP_RESET_MASK 0x00000020U
+#define EUR_CR_SOFT_RESET_ISP_RESET_SHIFT 5
+#define EUR_CR_SOFT_RESET_TSP_RESET_MASK 0x00000040U
+#define EUR_CR_SOFT_RESET_TSP_RESET_SHIFT 6
+#define EUR_CR_EVENT_HOST_ENABLE2 0x0110
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_SHIFT 7
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_SHIFT 6
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_SHIFT 5
+#define EUR_CR_EVENT_HOST_ENABLE2_BIF_REQUESTER_FAULT_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_ENABLE2_BIF_REQUESTER_FAULT_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_DHOST_FREE_LOAD_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_DHOST_FREE_LOAD_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_HOST_FREE_LOAD_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_HOST_FREE_LOAD_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_HOST_CLEAR2 0x0114
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_SHIFT 7
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_SHIFT 6
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_SHIFT 5
+#define EUR_CR_EVENT_HOST_CLEAR2_BIF_REQUESTER_FAULT_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_CLEAR2_BIF_REQUESTER_FAULT_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_DHOST_FREE_LOAD_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_DHOST_FREE_LOAD_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_HOST_FREE_LOAD_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_HOST_FREE_LOAD_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_STATUS2 0x0118U
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_MASK 0x00000080U
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_SHIFT 7
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_MASK 0x00000040U
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_SHIFT 6
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_MASK 0x00000020U
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_SHIFT 5
+#define EUR_CR_EVENT_STATUS2_BIF_REQUESTER_FAULT_MASK 0x00000010U
+#define EUR_CR_EVENT_STATUS2_BIF_REQUESTER_FAULT_SHIFT 4
+#define EUR_CR_EVENT_STATUS2_DPM_DHOST_FREE_LOAD_MASK 0x00000008U
+#define EUR_CR_EVENT_STATUS2_DPM_DHOST_FREE_LOAD_SHIFT 3
+#define EUR_CR_EVENT_STATUS2_DPM_HOST_FREE_LOAD_MASK 0x00000004U
+#define EUR_CR_EVENT_STATUS2_DPM_HOST_FREE_LOAD_SHIFT 2
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_STATUS 0x012CU
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_STATUS_TIMER_MASK 0x20000000U
+#define EUR_CR_EVENT_STATUS_TIMER_SHIFT 29
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_STATUS_TWOD_COMPLETE_MASK 0x08000000U
+#define EUR_CR_EVENT_STATUS_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_STATUS_OTPM_INV_MASK 0x00100000U
+#define EUR_CR_EVENT_STATUS_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_STATUS_ISP_HALT_MASK 0x00020000U
+#define EUR_CR_EVENT_STATUS_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_STATUS_SW_EVENT_MASK 0x00004000U
+#define EUR_CR_EVENT_STATUS_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_MASK 0x00000800U
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_MASK 0x00000400U
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_EVENT_HOST_ENABLE 0x0130
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_MASK 0x20000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_ENABLE_TWOD_COMPLETE_MASK 0x08000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_MASK 0x00100000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_HALT_MASK 0x00020000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_MASK 0x00004000U
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_EVENT_HOST_CLEAR 0x0134
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_MASK 0x20000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_CLEAR_TWOD_COMPLETE_MASK 0x08000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_MASK 0x00100000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_HALT_MASK 0x00020000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_MASK 0x00004000U
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_PDS_EXEC_BASE 0x0AB8
+#define EUR_CR_PDS_EXEC_BASE_ADDR_MASK 0xFFF00000U
+#define EUR_CR_PDS_EXEC_BASE_ADDR_SHIFT 20
+#define EUR_CR_EVENT_KICKER 0x0AC4
+#define EUR_CR_EVENT_KICKER_ADDRESS_MASK 0xFFFFFFF0U
+#define EUR_CR_EVENT_KICKER_ADDRESS_SHIFT 4
+#define EUR_CR_EVENT_KICK 0x0AC8
+#define EUR_CR_EVENT_KICK_NOW_MASK 0x00000001U
+#define EUR_CR_EVENT_KICK_NOW_SHIFT 0
+#define EUR_CR_EVENT_TIMER 0x0ACC
+#define EUR_CR_EVENT_TIMER_ENABLE_MASK 0x01000000U
+#define EUR_CR_EVENT_TIMER_ENABLE_SHIFT 24
+#define EUR_CR_EVENT_TIMER_VALUE_MASK 0x00FFFFFFU
+#define EUR_CR_EVENT_TIMER_VALUE_SHIFT 0
+#define EUR_CR_PDS_INV0 0x0AD0
+#define EUR_CR_PDS_INV0_DSC_MASK 0x00000001U
+#define EUR_CR_PDS_INV0_DSC_SHIFT 0
+#define EUR_CR_PDS_INV1 0x0AD4
+#define EUR_CR_PDS_INV1_DSC_MASK 0x00000001U
+#define EUR_CR_PDS_INV1_DSC_SHIFT 0
+#define EUR_CR_PDS_INV2 0x0AD8
+#define EUR_CR_PDS_INV2_DSC_MASK 0x00000001U
+#define EUR_CR_PDS_INV2_DSC_SHIFT 0
+#define EUR_CR_PDS_INV3 0x0ADC
+#define EUR_CR_PDS_INV3_DSC_MASK 0x00000001U
+#define EUR_CR_PDS_INV3_DSC_SHIFT 0
+#define EUR_CR_PDS_INV_CSC 0x0AE0
+#define EUR_CR_PDS_INV_CSC_KICK_MASK 0x00000001U
+#define EUR_CR_PDS_INV_CSC_KICK_SHIFT 0
+#define EUR_CR_PDS_PC_BASE 0x0B2C
+#define EUR_CR_PDS_PC_BASE_ADDRESS_MASK 0x3FFFFFFFU
+#define EUR_CR_PDS_PC_BASE_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_CTRL 0x0C00
+#define EUR_CR_BIF_CTRL_NOREORDER_MASK 0x00000001U
+#define EUR_CR_BIF_CTRL_NOREORDER_SHIFT 0
+#define EUR_CR_BIF_CTRL_PAUSE_MASK 0x00000002U
+#define EUR_CR_BIF_CTRL_PAUSE_SHIFT 1
+#define EUR_CR_BIF_CTRL_FLUSH_MASK 0x00000004U
+#define EUR_CR_BIF_CTRL_FLUSH_SHIFT 2
+#define EUR_CR_BIF_CTRL_INVALDC_MASK 0x00000008U
+#define EUR_CR_BIF_CTRL_INVALDC_SHIFT 3
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_MASK 0x00000010U
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_SHIFT 4
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_MASK 0x00000100U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_SHIFT 8
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_MASK 0x00000200U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_SHIFT 9
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_MASK 0x00000400U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_SHIFT 10
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TWOD_MASK 0x00000800U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TWOD_SHIFT 11
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_MASK 0x00001000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_SHIFT 12
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_MASK 0x00002000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_SHIFT 13
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_MASK 0x00004000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_SHIFT 14
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_MASK 0x00008000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_SHIFT 15
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_MASK 0x00010000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_SHIFT 16
+#define EUR_CR_BIF_INT_STAT 0x0C04
+#define EUR_CR_BIF_INT_STAT_FAULT_MASK 0x00003FFFU
+#define EUR_CR_BIF_INT_STAT_FAULT_SHIFT 0
+#define EUR_CR_BIF_INT_STAT_PF_N_RW_MASK 0x00004000U
+#define EUR_CR_BIF_INT_STAT_PF_N_RW_SHIFT 14
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_MASK 0x00008000U
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_SHIFT 15
+#define EUR_CR_BIF_FAULT 0x0C08
+#define EUR_CR_BIF_FAULT_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_FAULT_ADDR_SHIFT 12
+#define EUR_CR_BIF_TILE0 0x0C0C
+#define EUR_CR_BIF_TILE0_MIN_ADDRESS_MASK 0x00000FFFU
+#define EUR_CR_BIF_TILE0_MIN_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE0_MAX_ADDRESS_MASK 0x00FFF000U
+#define EUR_CR_BIF_TILE0_MAX_ADDRESS_SHIFT 12
+#define EUR_CR_BIF_TILE0_CFG_MASK 0x0F000000U
+#define EUR_CR_BIF_TILE0_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE1 0x0C10
+#define EUR_CR_BIF_TILE1_MIN_ADDRESS_MASK 0x00000FFFU
+#define EUR_CR_BIF_TILE1_MIN_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE1_MAX_ADDRESS_MASK 0x00FFF000U
+#define EUR_CR_BIF_TILE1_MAX_ADDRESS_SHIFT 12
+#define EUR_CR_BIF_TILE1_CFG_MASK 0x0F000000U
+#define EUR_CR_BIF_TILE1_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE2 0x0C14
+#define EUR_CR_BIF_TILE2_MIN_ADDRESS_MASK 0x00000FFFU
+#define EUR_CR_BIF_TILE2_MIN_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE2_MAX_ADDRESS_MASK 0x00FFF000U
+#define EUR_CR_BIF_TILE2_MAX_ADDRESS_SHIFT 12
+#define EUR_CR_BIF_TILE2_CFG_MASK 0x0F000000U
+#define EUR_CR_BIF_TILE2_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE3 0x0C18
+#define EUR_CR_BIF_TILE3_MIN_ADDRESS_MASK 0x00000FFFU
+#define EUR_CR_BIF_TILE3_MIN_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE3_MAX_ADDRESS_MASK 0x00FFF000U
+#define EUR_CR_BIF_TILE3_MAX_ADDRESS_SHIFT 12
+#define EUR_CR_BIF_TILE3_CFG_MASK 0x0F000000U
+#define EUR_CR_BIF_TILE3_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE4 0x0C1C
+#define EUR_CR_BIF_TILE4_MIN_ADDRESS_MASK 0x00000FFFU
+#define EUR_CR_BIF_TILE4_MIN_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE4_MAX_ADDRESS_MASK 0x00FFF000U
+#define EUR_CR_BIF_TILE4_MAX_ADDRESS_SHIFT 12
+#define EUR_CR_BIF_TILE4_CFG_MASK 0x0F000000U
+#define EUR_CR_BIF_TILE4_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE5 0x0C20
+#define EUR_CR_BIF_TILE5_MIN_ADDRESS_MASK 0x00000FFFU
+#define EUR_CR_BIF_TILE5_MIN_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE5_MAX_ADDRESS_MASK 0x00FFF000U
+#define EUR_CR_BIF_TILE5_MAX_ADDRESS_SHIFT 12
+#define EUR_CR_BIF_TILE5_CFG_MASK 0x0F000000U
+#define EUR_CR_BIF_TILE5_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE6 0x0C24
+#define EUR_CR_BIF_TILE6_MIN_ADDRESS_MASK 0x00000FFFU
+#define EUR_CR_BIF_TILE6_MIN_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE6_MAX_ADDRESS_MASK 0x00FFF000U
+#define EUR_CR_BIF_TILE6_MAX_ADDRESS_SHIFT 12
+#define EUR_CR_BIF_TILE6_CFG_MASK 0x0F000000U
+#define EUR_CR_BIF_TILE6_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE7 0x0C28
+#define EUR_CR_BIF_TILE7_MIN_ADDRESS_MASK 0x00000FFFU
+#define EUR_CR_BIF_TILE7_MIN_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE7_MAX_ADDRESS_MASK 0x00FFF000U
+#define EUR_CR_BIF_TILE7_MAX_ADDRESS_SHIFT 12
+#define EUR_CR_BIF_TILE7_CFG_MASK 0x0F000000U
+#define EUR_CR_BIF_TILE7_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE8 0x0C2C
+#define EUR_CR_BIF_TILE8_MIN_ADDRESS_MASK 0x00000FFFU
+#define EUR_CR_BIF_TILE8_MIN_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE8_MAX_ADDRESS_MASK 0x00FFF000U
+#define EUR_CR_BIF_TILE8_MAX_ADDRESS_SHIFT 12
+#define EUR_CR_BIF_TILE8_CFG_MASK 0x0F000000U
+#define EUR_CR_BIF_TILE8_CFG_SHIFT 24
+#define EUR_CR_BIF_TILE9 0x0C30
+#define EUR_CR_BIF_TILE9_MIN_ADDRESS_MASK 0x00000FFFU
+#define EUR_CR_BIF_TILE9_MIN_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_TILE9_MAX_ADDRESS_MASK 0x00FFF000U
+#define EUR_CR_BIF_TILE9_MAX_ADDRESS_SHIFT 12
+#define EUR_CR_BIF_TILE9_CFG_MASK 0x0F000000U
+#define EUR_CR_BIF_TILE9_CFG_SHIFT 24
+#define EUR_CR_BIF_DIR_LIST_BASE1 0x0C38
+#define EUR_CR_BIF_DIR_LIST_BASE1_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE1_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE2 0x0C3C
+#define EUR_CR_BIF_DIR_LIST_BASE2_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE2_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE3 0x0C40
+#define EUR_CR_BIF_DIR_LIST_BASE3_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE3_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE4 0x0C44
+#define EUR_CR_BIF_DIR_LIST_BASE4_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE4_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE5 0x0C48
+#define EUR_CR_BIF_DIR_LIST_BASE5_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE5_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE6 0x0C4C
+#define EUR_CR_BIF_DIR_LIST_BASE6_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE6_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE7 0x0C50
+#define EUR_CR_BIF_DIR_LIST_BASE7_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE7_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE8 0x0C54
+#define EUR_CR_BIF_DIR_LIST_BASE8_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE8_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE9 0x0C58
+#define EUR_CR_BIF_DIR_LIST_BASE9_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE9_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE10 0x0C5C
+#define EUR_CR_BIF_DIR_LIST_BASE10_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE10_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE11 0x0C60
+#define EUR_CR_BIF_DIR_LIST_BASE11_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE11_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE12 0x0C64
+#define EUR_CR_BIF_DIR_LIST_BASE12_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE12_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE13 0x0C68
+#define EUR_CR_BIF_DIR_LIST_BASE13_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE13_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE14 0x0C6C
+#define EUR_CR_BIF_DIR_LIST_BASE14_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE14_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE15 0x0C70
+#define EUR_CR_BIF_DIR_LIST_BASE15_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE15_ADDR_SHIFT 12
+#define EUR_CR_BIF_BANK_SET 0x0C74
+#define EUR_CR_BIF_BANK_SET_SELECT_MASK 0x000003FFU
+#define EUR_CR_BIF_BANK_SET_SELECT_SHIFT 0
+#define EUR_CR_BIF_BANK0 0x0C78
+#define EUR_CR_BIF_BANK0_INDEX_EDM_MASK 0x0000000FU
+#define EUR_CR_BIF_BANK0_INDEX_EDM_SHIFT 0
+#define EUR_CR_BIF_BANK0_INDEX_TA_MASK 0x000000F0U
+#define EUR_CR_BIF_BANK0_INDEX_TA_SHIFT 4
+#define EUR_CR_BIF_BANK0_INDEX_HOST_MASK 0x00000F00U
+#define EUR_CR_BIF_BANK0_INDEX_HOST_SHIFT 8
+#define EUR_CR_BIF_BANK0_INDEX_3D_MASK 0x0000F000U
+#define EUR_CR_BIF_BANK0_INDEX_3D_SHIFT 12
+#define EUR_CR_BIF_BANK0_INDEX_2D_MASK 0x000F0000U
+#define EUR_CR_BIF_BANK0_INDEX_2D_SHIFT 16
+#define EUR_CR_BIF_BANK1 0x0C7C
+#define EUR_CR_BIF_BANK1_INDEX_EDM_MASK 0x0000000FU
+#define EUR_CR_BIF_BANK1_INDEX_EDM_SHIFT 0
+#define EUR_CR_BIF_BANK1_INDEX_TA_MASK 0x000000F0U
+#define EUR_CR_BIF_BANK1_INDEX_TA_SHIFT 4
+#define EUR_CR_BIF_BANK1_INDEX_HOST_MASK 0x00000F00U
+#define EUR_CR_BIF_BANK1_INDEX_HOST_SHIFT 8
+#define EUR_CR_BIF_BANK1_INDEX_3D_MASK 0x0000F000U
+#define EUR_CR_BIF_BANK1_INDEX_3D_SHIFT 12
+#define EUR_CR_BIF_BANK1_INDEX_2D_MASK 0x000F0000U
+#define EUR_CR_BIF_BANK1_INDEX_2D_SHIFT 16
+#define EUR_CR_BIF_ADT_TTE 0x0C80
+#define EUR_CR_BIF_ADT_TTE_VALUE_MASK 0x000000FFU
+#define EUR_CR_BIF_ADT_TTE_VALUE_SHIFT 0
+#define EUR_CR_BIF_DIR_LIST_BASE0 0x0C84
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_SHIFT 12
+#define EUR_CR_BIF_TWOD_REQ_BASE 0x0C88
+#define EUR_CR_BIF_TWOD_REQ_BASE_ADDR_MASK 0xFFF00000U
+#define EUR_CR_BIF_TWOD_REQ_BASE_ADDR_SHIFT 20
+#define EUR_CR_BIF_TA_REQ_BASE 0x0C90
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_MASK 0xFFF00000U
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_SHIFT 20
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1 0x0C94
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_MMU_MASK 0x00000007U
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_MMU_SHIFT 0
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_CACHE_MASK 0x00000038U
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_CACHE_SHIFT 3
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_VDM_MASK 0x000001C0U
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_VDM_SHIFT 6
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_TE_MASK 0x00000E00U
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_TE_SHIFT 9
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_TWOD_MASK 0x00007000U
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_TWOD_SHIFT 12
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_PBE_MASK 0x00038000U
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_1_PBE_SHIFT 15
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2 0x0C98
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_HOST_MASK 0x00000007U
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_HOST_SHIFT 0
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_USE_MASK 0x00000038U
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_USE_SHIFT 3
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_ISP_MASK 0x000001C0U
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_ISP_SHIFT 6
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_TSPP_MASK 0x00000E00U
+#define EUR_CR_BIF_MEM_ARB_FLOWRATES_2_TSPP_SHIFT 9
+#define EUR_CR_BIF_MEM_ARB_CONFIG 0x0CA0
+#define EUR_CR_BIF_MEM_ARB_CONFIG_PAGE_SIZE_MASK 0x0000000FU
+#define EUR_CR_BIF_MEM_ARB_CONFIG_PAGE_SIZE_SHIFT 0
+#define EUR_CR_BIF_MEM_ARB_CONFIG_BEST_CNT_MASK 0x00000FF0U
+#define EUR_CR_BIF_MEM_ARB_CONFIG_BEST_CNT_SHIFT 4
+#define EUR_CR_BIF_MEM_ARB_CONFIG_TTE_THRESH_MASK 0x00FFF000U
+#define EUR_CR_BIF_MEM_ARB_CONFIG_TTE_THRESH_SHIFT 12
+#define EUR_CR_BIF_MEM_REQ_STAT 0x0CA8
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_MASK 0x000000FFU
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_SHIFT 0
+#define EUR_CR_BIF_3D_REQ_BASE 0x0CAC
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_MASK 0xFFF00000U
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_SHIFT 20
+#define EUR_CR_BIF_ZLS_REQ_BASE 0x0CB0
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_MASK 0xFFF00000U
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_SHIFT 20
+#define EUR_CR_BIF_BANK_STATUS 0x0CB4
+#define EUR_CR_BIF_BANK_STATUS_3D_CURRENT_BANK_MASK 0x00000001U
+#define EUR_CR_BIF_BANK_STATUS_3D_CURRENT_BANK_SHIFT 0
+#define EUR_CR_BIF_BANK_STATUS_TA_CURRENT_BANK_MASK 0x00000002U
+#define EUR_CR_BIF_BANK_STATUS_TA_CURRENT_BANK_SHIFT 1
+#define EUR_CR_2D_BLIT_STATUS 0x0E04
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_MASK 0x00FFFFFFU
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_SHIFT 0
+#define EUR_CR_2D_BLIT_STATUS_BUSY_MASK 0x01000000U
+#define EUR_CR_2D_BLIT_STATUS_BUSY_SHIFT 24
+#define EUR_CR_2D_VIRTUAL_FIFO_0 0x0E10
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_MASK 0x00000001U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MASK 0x0000000EU
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_SHIFT 1
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_MASK 0x00000FF0U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_SHIFT 4
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_MASK 0x0000F000U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_SHIFT 12
+#define EUR_CR_2D_VIRTUAL_FIFO_1 0x0E14
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_MASK 0x00000FFFU
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_MASK 0x00FFF000U
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_SHIFT 12
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_MASK 0xFF000000U
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_SHIFT 24
+#define EUR_CR_2D_SOCIF 0x0E18
+#define EUR_CR_2D_SOCIF_FREESPACE_MASK 0x000000FFU
+#define EUR_CR_2D_SOCIF_FREESPACE_SHIFT 0
+#define EUR_CR_2D_ALPHA 0x0E1C
+#define EUR_CR_2D_ALPHA_COMPONENT_ONE_MASK 0x0000FF00U
+#define EUR_CR_2D_ALPHA_COMPONENT_ONE_SHIFT 8
+#define EUR_CR_2D_ALPHA_COMPONENT_ZERO_MASK 0x000000FFU
+#define EUR_CR_2D_ALPHA_COMPONENT_ZERO_SHIFT 0
+#define EUR_CR_USE_CODE_BASE(X) (0x0A0C + (4 * (X)))
+#define EUR_CR_USE_CODE_BASE_ADDR_MASK 0x01FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_SHIFT 0
+#define EUR_CR_USE_CODE_BASE_DM_MASK 0x06000000U
+#define EUR_CR_USE_CODE_BASE_DM_SHIFT 25
+#define EUR_CR_USE_CODE_BASE_SIZE_UINT32 16
+#define EUR_CR_USE_CODE_BASE_NUM_ENTRIES 16
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef _SGX540DEFS_KM_H_
+#define _SGX540DEFS_KM_H_
+
+#define EUR_CR_CLKGATECTL 0x0000
+#define EUR_CR_CLKGATECTL_ISP_CLKG_MASK 0x00000003U
+#define EUR_CR_CLKGATECTL_ISP_CLKG_SHIFT 0
+#define EUR_CR_CLKGATECTL_ISP2_CLKG_MASK 0x0000000CU
+#define EUR_CR_CLKGATECTL_ISP2_CLKG_SHIFT 2
+#define EUR_CR_CLKGATECTL_TSP_CLKG_MASK 0x00000030U
+#define EUR_CR_CLKGATECTL_TSP_CLKG_SHIFT 4
+#define EUR_CR_CLKGATECTL_TE_CLKG_MASK 0x000000C0U
+#define EUR_CR_CLKGATECTL_TE_CLKG_SHIFT 6
+#define EUR_CR_CLKGATECTL_MTE_CLKG_MASK 0x00000300U
+#define EUR_CR_CLKGATECTL_MTE_CLKG_SHIFT 8
+#define EUR_CR_CLKGATECTL_DPM_CLKG_MASK 0x00000C00U
+#define EUR_CR_CLKGATECTL_DPM_CLKG_SHIFT 10
+#define EUR_CR_CLKGATECTL_VDM_CLKG_MASK 0x00003000U
+#define EUR_CR_CLKGATECTL_VDM_CLKG_SHIFT 12
+#define EUR_CR_CLKGATECTL_PDS_CLKG_MASK 0x0000C000U
+#define EUR_CR_CLKGATECTL_PDS_CLKG_SHIFT 14
+#define EUR_CR_CLKGATECTL_IDXFIFO_CLKG_MASK 0x00030000U
+#define EUR_CR_CLKGATECTL_IDXFIFO_CLKG_SHIFT 16
+#define EUR_CR_CLKGATECTL_TA_CLKG_MASK 0x000C0000U
+#define EUR_CR_CLKGATECTL_TA_CLKG_SHIFT 18
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_MASK 0x01000000U
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_SHIFT 24
+#define EUR_CR_CLKGATECTL_SYSTEM_CLKG_MASK 0x10000000U
+#define EUR_CR_CLKGATECTL_SYSTEM_CLKG_SHIFT 28
+#define EUR_CR_CLKGATECTL2 0x0004
+#define EUR_CR_CLKGATECTL2_PBE_CLKG_MASK 0x00000003U
+#define EUR_CR_CLKGATECTL2_PBE_CLKG_SHIFT 0
+#define EUR_CR_CLKGATECTL2_CACHEL2_CLKG_MASK 0x0000000CU
+#define EUR_CR_CLKGATECTL2_CACHEL2_CLKG_SHIFT 2
+#define EUR_CR_CLKGATECTL2_UCACHEL2_CLKG_MASK 0x00000030U
+#define EUR_CR_CLKGATECTL2_UCACHEL2_CLKG_SHIFT 4
+#define EUR_CR_CLKGATECTL2_USE0_CLKG_MASK 0x000000C0U
+#define EUR_CR_CLKGATECTL2_USE0_CLKG_SHIFT 6
+#define EUR_CR_CLKGATECTL2_ITR0_CLKG_MASK 0x00000300U
+#define EUR_CR_CLKGATECTL2_ITR0_CLKG_SHIFT 8
+#define EUR_CR_CLKGATECTL2_TEX0_CLKG_MASK 0x00000C00U
+#define EUR_CR_CLKGATECTL2_TEX0_CLKG_SHIFT 10
+#define EUR_CR_CLKGATECTL2_MADD0_CLKG_MASK 0x00003000U
+#define EUR_CR_CLKGATECTL2_MADD0_CLKG_SHIFT 12
+#define EUR_CR_CLKGATECTL2_USE1_CLKG_MASK 0x0000C000U
+#define EUR_CR_CLKGATECTL2_USE1_CLKG_SHIFT 14
+#define EUR_CR_CLKGATECTL2_ITR1_CLKG_MASK 0x00030000U
+#define EUR_CR_CLKGATECTL2_ITR1_CLKG_SHIFT 16
+#define EUR_CR_CLKGATECTL2_TEX1_CLKG_MASK 0x000C0000U
+#define EUR_CR_CLKGATECTL2_TEX1_CLKG_SHIFT 18
+#define EUR_CR_CLKGATECTL2_MADD1_CLKG_MASK 0x00300000U
+#define EUR_CR_CLKGATECTL2_MADD1_CLKG_SHIFT 20
+#define EUR_CR_CLKGATESTATUS 0x0008
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_MASK 0x00000001U
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_SHIFT 0
+#define EUR_CR_CLKGATESTATUS_ISP2_CLKS_MASK 0x00000002U
+#define EUR_CR_CLKGATESTATUS_ISP2_CLKS_SHIFT 1
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_MASK 0x00000004U
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_SHIFT 2
+#define EUR_CR_CLKGATESTATUS_TE_CLKS_MASK 0x00000008U
+#define EUR_CR_CLKGATESTATUS_TE_CLKS_SHIFT 3
+#define EUR_CR_CLKGATESTATUS_MTE_CLKS_MASK 0x00000010U
+#define EUR_CR_CLKGATESTATUS_MTE_CLKS_SHIFT 4
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_MASK 0x00000020U
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_SHIFT 5
+#define EUR_CR_CLKGATESTATUS_VDM_CLKS_MASK 0x00000040U
+#define EUR_CR_CLKGATESTATUS_VDM_CLKS_SHIFT 6
+#define EUR_CR_CLKGATESTATUS_PDS_CLKS_MASK 0x00000080U
+#define EUR_CR_CLKGATESTATUS_PDS_CLKS_SHIFT 7
+#define EUR_CR_CLKGATESTATUS_PBE_CLKS_MASK 0x00000100U
+#define EUR_CR_CLKGATESTATUS_PBE_CLKS_SHIFT 8
+#define EUR_CR_CLKGATESTATUS_CACHEL2_CLKS_MASK 0x00000200U
+#define EUR_CR_CLKGATESTATUS_CACHEL2_CLKS_SHIFT 9
+#define EUR_CR_CLKGATESTATUS_UCACHEL2_CLKS_MASK 0x00000400U
+#define EUR_CR_CLKGATESTATUS_UCACHEL2_CLKS_SHIFT 10
+#define EUR_CR_CLKGATESTATUS_USE0_CLKS_MASK 0x00000800U
+#define EUR_CR_CLKGATESTATUS_USE0_CLKS_SHIFT 11
+#define EUR_CR_CLKGATESTATUS_ITR0_CLKS_MASK 0x00001000U
+#define EUR_CR_CLKGATESTATUS_ITR0_CLKS_SHIFT 12
+#define EUR_CR_CLKGATESTATUS_TEX0_CLKS_MASK 0x00002000U
+#define EUR_CR_CLKGATESTATUS_TEX0_CLKS_SHIFT 13
+#define EUR_CR_CLKGATESTATUS_MADD0_CLKS_MASK 0x00004000U
+#define EUR_CR_CLKGATESTATUS_MADD0_CLKS_SHIFT 14
+#define EUR_CR_CLKGATESTATUS_USE1_CLKS_MASK 0x00008000U
+#define EUR_CR_CLKGATESTATUS_USE1_CLKS_SHIFT 15
+#define EUR_CR_CLKGATESTATUS_ITR1_CLKS_MASK 0x00010000U
+#define EUR_CR_CLKGATESTATUS_ITR1_CLKS_SHIFT 16
+#define EUR_CR_CLKGATESTATUS_TEX1_CLKS_MASK 0x00020000U
+#define EUR_CR_CLKGATESTATUS_TEX1_CLKS_SHIFT 17
+#define EUR_CR_CLKGATESTATUS_MADD1_CLKS_MASK 0x00040000U
+#define EUR_CR_CLKGATESTATUS_MADD1_CLKS_SHIFT 18
+#define EUR_CR_CLKGATESTATUS_IDXFIFO_CLKS_MASK 0x00080000U
+#define EUR_CR_CLKGATESTATUS_IDXFIFO_CLKS_SHIFT 19
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_MASK 0x00100000U
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_SHIFT 20
+#define EUR_CR_CLKGATECTLOVR 0x000C
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_MASK 0x00000003U
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_SHIFT 0
+#define EUR_CR_CLKGATECTLOVR_ISP2_CLKO_MASK 0x0000000CU
+#define EUR_CR_CLKGATECTLOVR_ISP2_CLKO_SHIFT 2
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_MASK 0x00000030U
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_SHIFT 4
+#define EUR_CR_CLKGATECTLOVR_TE_CLKO_MASK 0x000000C0U
+#define EUR_CR_CLKGATECTLOVR_TE_CLKO_SHIFT 6
+#define EUR_CR_CLKGATECTLOVR_MTE_CLKO_MASK 0x00000300U
+#define EUR_CR_CLKGATECTLOVR_MTE_CLKO_SHIFT 8
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_MASK 0x00000C00U
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_SHIFT 10
+#define EUR_CR_CLKGATECTLOVR_VDM_CLKO_MASK 0x00003000U
+#define EUR_CR_CLKGATECTLOVR_VDM_CLKO_SHIFT 12
+#define EUR_CR_CLKGATECTLOVR_PDS_CLKO_MASK 0x0000C000U
+#define EUR_CR_CLKGATECTLOVR_PDS_CLKO_SHIFT 14
+#define EUR_CR_CLKGATECTLOVR_IDXFIFO_CLKO_MASK 0x00030000U
+#define EUR_CR_CLKGATECTLOVR_IDXFIFO_CLKO_SHIFT 16
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_MASK 0x000C0000U
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_SHIFT 18
+#define EUR_CR_POWER 0x001C
+#define EUR_CR_POWER_PIPE_DISABLE_MASK 0x00000001U
+#define EUR_CR_POWER_PIPE_DISABLE_SHIFT 0
+#define EUR_CR_CORE_ID 0x0020
+#define EUR_CR_CORE_ID_CONFIG_MASK 0x0000FFFFU
+#define EUR_CR_CORE_ID_CONFIG_SHIFT 0
+#define EUR_CR_CORE_ID_ID_MASK 0xFFFF0000U
+#define EUR_CR_CORE_ID_ID_SHIFT 16
+#define EUR_CR_CORE_REVISION 0x0024
+#define EUR_CR_CORE_REVISION_MAINTENANCE_MASK 0x000000FFU
+#define EUR_CR_CORE_REVISION_MAINTENANCE_SHIFT 0
+#define EUR_CR_CORE_REVISION_MINOR_MASK 0x0000FF00U
+#define EUR_CR_CORE_REVISION_MINOR_SHIFT 8
+#define EUR_CR_CORE_REVISION_MAJOR_MASK 0x00FF0000U
+#define EUR_CR_CORE_REVISION_MAJOR_SHIFT 16
+#define EUR_CR_CORE_REVISION_DESIGNER_MASK 0xFF000000U
+#define EUR_CR_CORE_REVISION_DESIGNER_SHIFT 24
+#define EUR_CR_DESIGNER_REV_FIELD1 0x0028
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_MASK 0xFFFFFFFFU
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_SHIFT 0
+#define EUR_CR_DESIGNER_REV_FIELD2 0x002C
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_MASK 0xFFFFFFFFU
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_SHIFT 0
+#define EUR_CR_SOFT_RESET 0x0080
+#define EUR_CR_SOFT_RESET_BIF_RESET_MASK 0x00000001U
+#define EUR_CR_SOFT_RESET_BIF_RESET_SHIFT 0
+#define EUR_CR_SOFT_RESET_VDM_RESET_MASK 0x00000002U
+#define EUR_CR_SOFT_RESET_VDM_RESET_SHIFT 1
+#define EUR_CR_SOFT_RESET_DPM_RESET_MASK 0x00000004U
+#define EUR_CR_SOFT_RESET_DPM_RESET_SHIFT 2
+#define EUR_CR_SOFT_RESET_TE_RESET_MASK 0x00000008U
+#define EUR_CR_SOFT_RESET_TE_RESET_SHIFT 3
+#define EUR_CR_SOFT_RESET_MTE_RESET_MASK 0x00000010U
+#define EUR_CR_SOFT_RESET_MTE_RESET_SHIFT 4
+#define EUR_CR_SOFT_RESET_ISP_RESET_MASK 0x00000020U
+#define EUR_CR_SOFT_RESET_ISP_RESET_SHIFT 5
+#define EUR_CR_SOFT_RESET_ISP2_RESET_MASK 0x00000040U
+#define EUR_CR_SOFT_RESET_ISP2_RESET_SHIFT 6
+#define EUR_CR_SOFT_RESET_TSP_RESET_MASK 0x00000080U
+#define EUR_CR_SOFT_RESET_TSP_RESET_SHIFT 7
+#define EUR_CR_SOFT_RESET_PDS_RESET_MASK 0x00000100U
+#define EUR_CR_SOFT_RESET_PDS_RESET_SHIFT 8
+#define EUR_CR_SOFT_RESET_PBE_RESET_MASK 0x00000200U
+#define EUR_CR_SOFT_RESET_PBE_RESET_SHIFT 9
+#define EUR_CR_SOFT_RESET_CACHEL2_RESET_MASK 0x00000400U
+#define EUR_CR_SOFT_RESET_CACHEL2_RESET_SHIFT 10
+#define EUR_CR_SOFT_RESET_UCACHEL2_RESET_MASK 0x00000800U
+#define EUR_CR_SOFT_RESET_UCACHEL2_RESET_SHIFT 11
+#define EUR_CR_SOFT_RESET_MADD_RESET_MASK 0x00001000U
+#define EUR_CR_SOFT_RESET_MADD_RESET_SHIFT 12
+#define EUR_CR_SOFT_RESET_ITR_RESET_MASK 0x00002000U
+#define EUR_CR_SOFT_RESET_ITR_RESET_SHIFT 13
+#define EUR_CR_SOFT_RESET_TEX_RESET_MASK 0x00004000U
+#define EUR_CR_SOFT_RESET_TEX_RESET_SHIFT 14
+#define EUR_CR_SOFT_RESET_USE_RESET_MASK 0x00008000U
+#define EUR_CR_SOFT_RESET_USE_RESET_SHIFT 15
+#define EUR_CR_SOFT_RESET_IDXFIFO_RESET_MASK 0x00010000U
+#define EUR_CR_SOFT_RESET_IDXFIFO_RESET_SHIFT 16
+#define EUR_CR_SOFT_RESET_TA_RESET_MASK 0x00020000U
+#define EUR_CR_SOFT_RESET_TA_RESET_SHIFT 17
+#define EUR_CR_EVENT_HOST_ENABLE2 0x0110
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_3D_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_DL_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_HOST_CLEAR2 0x0114
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_3D_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_DL_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_STATUS2 0x0118
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_MASK 0x00000010U
+#define EUR_CR_EVENT_STATUS2_TRIG_TA_SHIFT 4
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_MASK 0x00000008U
+#define EUR_CR_EVENT_STATUS2_TRIG_3D_SHIFT 3
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_MASK 0x00000004U
+#define EUR_CR_EVENT_STATUS2_TRIG_DL_SHIFT 2
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_MASK 0x00000002U
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_MASK 0x00000001U
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_SHIFT 0
+#define EUR_CR_EVENT_STATUS 0x012CU
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_STATUS_TIMER_MASK 0x20000000U
+#define EUR_CR_EVENT_STATUS_TIMER_SHIFT 29
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_STATUS_TWOD_COMPLETE_MASK 0x08000000U
+#define EUR_CR_EVENT_STATUS_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_STATUS_OTPM_INV_MASK 0x00100000U
+#define EUR_CR_EVENT_STATUS_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_STATUS_ISP_HALT_MASK 0x00020000U
+#define EUR_CR_EVENT_STATUS_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_STATUS_SW_EVENT_MASK 0x00004000U
+#define EUR_CR_EVENT_STATUS_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_MASK 0x00000800U
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_MASK 0x00000400U
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_EVENT_HOST_ENABLE 0x0130
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_MASK 0x20000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_ENABLE_TWOD_COMPLETE_MASK 0x08000000U
+#define EUR_CR_EVENT_HOST_ENABLE_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_MASK 0x00100000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_HALT_MASK 0x00020000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_MASK 0x00004000U
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_EVENT_HOST_CLEAR 0x0134
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK 0x80000000U
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_MASK 0x20000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_MASK 0x10000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_CLEAR_TWOD_COMPLETE_MASK 0x08000000U
+#define EUR_CR_EVENT_HOST_CLEAR_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000U
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_MASK 0x01000000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_MASK 0x00800000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_MASK 0x00400000U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_MASK 0x00200000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_MASK 0x00100000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_MASK 0x00080000U
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_MASK 0x00040000U
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_HALT_MASK 0x00020000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_MASK 0x00010000U
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_MASK 0x00008000U
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_MASK 0x00004000U
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_MASK 0x00002000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_MASK 0x00001000U
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_MASK 0x00000800U
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_MASK 0x00000400U
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_MASK 0x00000200U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_MASK 0x00000100U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_MASK 0x00000080U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_MASK 0x00000040U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_MASK 0x00000020U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_MASK 0x00000010U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_MASK 0x00000008U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_MASK 0x00000001U
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_SHIFT 0
+#define EUR_CR_TIMER 0x0144
+#define EUR_CR_TIMER_VALUE_MASK 0xFFFFFFFFU
+#define EUR_CR_TIMER_VALUE_SHIFT 0
+#define EUR_CR_EVENT_KICK1 0x0AB0
+#define EUR_CR_EVENT_KICK1_NOW_MASK 0x000000FFU
+#define EUR_CR_EVENT_KICK1_NOW_SHIFT 0
+#define EUR_CR_PDS_EXEC_BASE 0x0AB8
+#define EUR_CR_PDS_EXEC_BASE_ADDR_MASK 0x0FF00000U
+#define EUR_CR_PDS_EXEC_BASE_ADDR_SHIFT 20
+#define EUR_CR_EVENT_KICK2 0x0AC0
+#define EUR_CR_EVENT_KICK2_NOW_MASK 0x00000001U
+#define EUR_CR_EVENT_KICK2_NOW_SHIFT 0
+#define EUR_CR_EVENT_KICKER 0x0AC4
+#define EUR_CR_EVENT_KICKER_ADDRESS_MASK 0x0FFFFFF0U
+#define EUR_CR_EVENT_KICKER_ADDRESS_SHIFT 4
+#define EUR_CR_EVENT_KICK 0x0AC8
+#define EUR_CR_EVENT_KICK_NOW_MASK 0x00000001U
+#define EUR_CR_EVENT_KICK_NOW_SHIFT 0
+#define EUR_CR_EVENT_TIMER 0x0ACC
+#define EUR_CR_EVENT_TIMER_ENABLE_MASK 0x01000000U
+#define EUR_CR_EVENT_TIMER_ENABLE_SHIFT 24
+#define EUR_CR_EVENT_TIMER_VALUE_MASK 0x00FFFFFFU
+#define EUR_CR_EVENT_TIMER_VALUE_SHIFT 0
+#define EUR_CR_PDS_INV0 0x0AD0
+#define EUR_CR_PDS_INV0_DSC_MASK 0x00000001U
+#define EUR_CR_PDS_INV0_DSC_SHIFT 0
+#define EUR_CR_PDS_INV1 0x0AD4
+#define EUR_CR_PDS_INV1_DSC_MASK 0x00000001U
+#define EUR_CR_PDS_INV1_DSC_SHIFT 0
+#define EUR_CR_EVENT_KICK3 0x0AD8
+#define EUR_CR_EVENT_KICK3_NOW_MASK 0x00000001U
+#define EUR_CR_EVENT_KICK3_NOW_SHIFT 0
+#define EUR_CR_PDS_INV3 0x0ADC
+#define EUR_CR_PDS_INV3_DSC_MASK 0x00000001U
+#define EUR_CR_PDS_INV3_DSC_SHIFT 0
+#define EUR_CR_PDS_INV_CSC 0x0AE0
+#define EUR_CR_PDS_INV_CSC_KICK_MASK 0x00000001U
+#define EUR_CR_PDS_INV_CSC_KICK_SHIFT 0
+#define EUR_CR_PDS_PC_BASE 0x0B2C
+#define EUR_CR_PDS_PC_BASE_ADDRESS_MASK 0x00FFFFFFU
+#define EUR_CR_PDS_PC_BASE_ADDRESS_SHIFT 0
+#define EUR_CR_BIF_CTRL 0x0C00
+#define EUR_CR_BIF_CTRL_NOREORDER_MASK 0x00000001U
+#define EUR_CR_BIF_CTRL_NOREORDER_SHIFT 0
+#define EUR_CR_BIF_CTRL_PAUSE_MASK 0x00000002U
+#define EUR_CR_BIF_CTRL_PAUSE_SHIFT 1
+#define EUR_CR_BIF_CTRL_FLUSH_MASK 0x00000004U
+#define EUR_CR_BIF_CTRL_FLUSH_SHIFT 2
+#define EUR_CR_BIF_CTRL_INVALDC_MASK 0x00000008U
+#define EUR_CR_BIF_CTRL_INVALDC_SHIFT 3
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_MASK 0x00000010U
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_SHIFT 4
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_MASK 0x00000100U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_SHIFT 8
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_MASK 0x00000200U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_SHIFT 9
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_MASK 0x00000400U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_SHIFT 10
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_MASK 0x00001000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_SHIFT 12
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_MASK 0x00002000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_SHIFT 13
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_MASK 0x00004000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_SHIFT 14
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_MASK 0x00008000U
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_SHIFT 15
+#define EUR_CR_BIF_INT_STAT 0x0C04
+#define EUR_CR_BIF_INT_STAT_FAULT_MASK 0x00003FFFU
+#define EUR_CR_BIF_INT_STAT_FAULT_SHIFT 0
+#define EUR_CR_BIF_INT_STAT_PF_N_RW_MASK 0x00004000U
+#define EUR_CR_BIF_INT_STAT_PF_N_RW_SHIFT 14
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_MASK 0x00008000U
+#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_SHIFT 15
+#define EUR_CR_BIF_FAULT 0x0C08
+#define EUR_CR_BIF_FAULT_SB_MASK 0x000001F0U
+#define EUR_CR_BIF_FAULT_SB_SHIFT 4
+#define EUR_CR_BIF_FAULT_ADDR_MASK 0x0FFFF000U
+#define EUR_CR_BIF_FAULT_ADDR_SHIFT 12
+#define EUR_CR_BIF_DIR_LIST_BASE0 0x0C84
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_MASK 0xFFFFF000U
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_SHIFT 12
+#define EUR_CR_BIF_TA_REQ_BASE 0x0C90
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_MASK 0x0FF00000U
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_SHIFT 20
+#define EUR_CR_BIF_MEM_REQ_STAT 0x0CA8
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_MASK 0x000000FFU
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_SHIFT 0
+#define EUR_CR_BIF_3D_REQ_BASE 0x0CAC
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_MASK 0x0FF00000U
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_SHIFT 20
+#define EUR_CR_BIF_ZLS_REQ_BASE 0x0CB0
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_MASK 0x0FF00000U
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_SHIFT 20
+#define EUR_CR_2D_BLIT_STATUS 0x0E04
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_MASK 0x00FFFFFFU
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_SHIFT 0
+#define EUR_CR_2D_BLIT_STATUS_BUSY_MASK 0x01000000U
+#define EUR_CR_2D_BLIT_STATUS_BUSY_SHIFT 24
+#define EUR_CR_2D_VIRTUAL_FIFO_0 0x0E10
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_MASK 0x00000001U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MASK 0x0000000EU
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_SHIFT 1
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_MASK 0x00000FF0U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_SHIFT 4
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_MASK 0x0000F000U
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_SHIFT 12
+#define EUR_CR_2D_VIRTUAL_FIFO_1 0x0E14
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_MASK 0x00000FFFU
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_MASK 0x00FFF000U
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_SHIFT 12
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_MASK 0xFF000000U
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_SHIFT 24
+#define EUR_CR_USE_CODE_BASE(X) (0x0A0C + (4 * (X)))
+#define EUR_CR_USE_CODE_BASE_ADDR_MASK 0x00FFFFFFU
+#define EUR_CR_USE_CODE_BASE_ADDR_SHIFT 0
+#define EUR_CR_USE_CODE_BASE_DM_MASK 0x03000000U
+#define EUR_CR_USE_CODE_BASE_DM_SHIFT 24
+#define EUR_CR_USE_CODE_BASE_SIZE_UINT32 16
+#define EUR_CR_USE_CODE_BASE_NUM_ENTRIES 16
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef _SGXDEFS_H_
+#define _SGXDEFS_H_
+
+#include "sgxerrata.h"
+#include "sgxfeaturedefs.h"
+
+#if defined(SGX520)
+#include "sgx520defs.h"
+#else
+#if defined(SGX530)
+#include "sgx530defs.h"
+#else
+#if defined(SGX535)
+#include "sgx535defs.h"
+#else
+#if defined(SGX535_V1_1)
+#include "sgx535defs.h"
+#else
+#if defined(SGX540)
+#include "sgx540defs.h"
+#else
+#if defined(SGX541)
+#include "sgx541defs.h"
+#else
+#if defined(SGX543)
+#include "sgx543defs.h"
+#else
+#if defined(SGX544)
+#include "sgx544defs.h"
+#else
+#if defined(SGX545)
+#include "sgx545defs.h"
+#else
+#if defined(SGX531)
+#include "sgx531defs.h"
+#else
+#if defined(SGX554)
+#include "sgx554defs.h"
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+
+#if defined(SGX_FEATURE_MP)
+#if defined(SGX541)
+#if SGX_CORE_REV == 100
+#include "sgx541_100mpdefs.h"
+#else
+#include "sgx541mpdefs.h"
+#endif
+#else
+#include "sgxmpdefs.h"
+#endif
+#else
+#if defined(SGX_FEATURE_SYSTEM_CACHE)
+#include "mnemedefs.h"
+#endif
+#endif
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef _SGXERRATA_KM_H_
+#define _SGXERRATA_KM_H_
+
+#if defined(SGX520) && !defined(SGX_CORE_DEFINED)
+
+ #define SGX_CORE_REV_HEAD 0
+ #if defined(USE_SGX_CORE_REV_HEAD)
+
+ #define SGX_CORE_REV SGX_CORE_REV_HEAD
+ #endif
+
+ #if SGX_CORE_REV == 100
+ #define FIX_HW_BRN_28889
+ #else
+ #if SGX_CORE_REV == 111
+ #define FIX_HW_BRN_28889
+ #else
+ #if SGX_CORE_REV == SGX_CORE_REV_HEAD
+
+ #else
+ #error "sgxerrata.h: SGX520 Core Revision unspecified"
+ #endif
+ #endif
+ #endif
+
+ #define SGX_CORE_DEFINED
+#endif
+
+#if defined(SGX530) && !defined(SGX_CORE_DEFINED)
+
+ #define SGX_CORE_REV_HEAD 0
+ #if defined(USE_SGX_CORE_REV_HEAD)
+
+ #define SGX_CORE_REV SGX_CORE_REV_HEAD
+ #endif
+
+ #if SGX_CORE_REV == 110
+ #define FIX_HW_BRN_22934
+ #define FIX_HW_BRN_28889
+ #else
+ #if SGX_CORE_REV == 111
+ #define FIX_HW_BRN_22934
+ #define FIX_HW_BRN_28889
+ #else
+ #if SGX_CORE_REV == 120
+ #define FIX_HW_BRN_22934
+ #define FIX_HW_BRN_28889
+ #else
+ #if SGX_CORE_REV == 121
+ #define FIX_HW_BRN_22934
+ #define FIX_HW_BRN_28889
+ #else
+ #if SGX_CORE_REV == 125
+ #define FIX_HW_BRN_22934
+ #define FIX_HW_BRN_28889
+ #else
+ #if SGX_CORE_REV == SGX_CORE_REV_HEAD
+
+ #else
+ #error "sgxerrata.h: SGX530 Core Revision unspecified"
+ #endif
+ #endif
+ #endif
+ #endif
+#endif
+ #endif
+
+ #define SGX_CORE_DEFINED
+#endif
+
+#if defined(SGX531) && !defined(SGX_CORE_DEFINED)
+
+ #define SGX_CORE_REV_HEAD 0
+ #if defined(USE_SGX_CORE_REV_HEAD)
+
+ #define SGX_CORE_REV SGX_CORE_REV_HEAD
+ #endif
+
+ #if SGX_CORE_REV == 101
+ #define FIX_HW_BRN_26620
+ #define FIX_HW_BRN_28011
+ #else
+ #if SGX_CORE_REV == 110
+
+ #else
+ #if SGX_CORE_REV == SGX_CORE_REV_HEAD
+
+ #else
+ #error "sgxerrata.h: SGX531 Core Revision unspecified"
+ #endif
+ #endif
+ #endif
+
+ #define SGX_CORE_DEFINED
+#endif
+
+#if (defined(SGX535) || defined(SGX535_V1_1)) && !defined(SGX_CORE_DEFINED)
+
+ #define SGX_CORE_REV_HEAD 0
+ #if defined(USE_SGX_CORE_REV_HEAD)
+
+ #define SGX_CORE_REV SGX_CORE_REV_HEAD
+ #endif
+
+ #if SGX_CORE_REV == 112
+ #define FIX_HW_BRN_23281
+ #define FIX_HW_BRN_23410
+ #define FIX_HW_BRN_22693
+ #define FIX_HW_BRN_22934
+ #define FIX_HW_BRN_22997
+ #define FIX_HW_BRN_23030
+ #else
+ #if SGX_CORE_REV == 113
+ #define FIX_HW_BRN_22934
+ #define FIX_HW_BRN_23281
+ #define FIX_HW_BRN_23944
+ #define FIX_HW_BRN_23410
+ #else
+ #if SGX_CORE_REV == 121
+ #define FIX_HW_BRN_22934
+ #define FIX_HW_BRN_23944
+ #define FIX_HW_BRN_23410
+ #else
+ #if SGX_CORE_REV == 126
+ #define FIX_HW_BRN_22934
+ #else
+ #if SGX_CORE_REV == SGX_CORE_REV_HEAD
+
+ #else
+ #error "sgxerrata.h: SGX535 Core Revision unspecified"
+
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+
+ #define SGX_CORE_DEFINED
+#endif
+
+#if defined(SGX540) && !defined(SGX_CORE_DEFINED)
+
+ #define SGX_CORE_REV_HEAD 0
+ #if defined(USE_SGX_CORE_REV_HEAD)
+
+ #define SGX_CORE_REV SGX_CORE_REV_HEAD
+ #endif
+
+ #if SGX_CORE_REV == 101
+ #define FIX_HW_BRN_25499
+ #define FIX_HW_BRN_25503
+ #define FIX_HW_BRN_26620
+ #define FIX_HW_BRN_28011
+ #else
+ #if SGX_CORE_REV == 110
+ #define FIX_HW_BRN_25503
+ #define FIX_HW_BRN_26620
+ #define FIX_HW_BRN_28011
+ #else
+ #if SGX_CORE_REV == 120
+ #define FIX_HW_BRN_26620
+ #define FIX_HW_BRN_28011
+ #else
+ #if SGX_CORE_REV == 121
+ #define FIX_HW_BRN_28011
+ #else
+ #if SGX_CORE_REV == SGX_CORE_REV_HEAD
+
+ #else
+ #error "sgxerrata.h: SGX540 Core Revision unspecified"
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+
+ #define SGX_CORE_DEFINED
+#endif
+
+#if defined(SGX541) && !defined(SGX_CORE_DEFINED)
+ #if defined(SGX_FEATURE_MP)
+
+ #define SGX_CORE_REV_HEAD 0
+ #if defined(USE_SGX_CORE_REV_HEAD)
+
+ #define SGX_CORE_REV SGX_CORE_REV_HEAD
+ #endif
+
+ #if SGX_CORE_REV == 100
+ #define FIX_HW_BRN_27270
+ #define FIX_HW_BRN_28011
+ #define FIX_HW_BRN_27510
+
+ #else
+ #if SGX_CORE_REV == SGX_CORE_REV_HEAD
+
+ #else
+ #error "sgxerrata.h: SGX541 Core Revision unspecified"
+ #endif
+ #endif
+
+ #define SGX_CORE_DEFINED
+ #else
+ #error "sgxerrata.h: SGX541 only supports MP configs (SGX_FEATURE_MP)"
+ #endif
+#endif
+
+#if defined(SGX543) && !defined(SGX_CORE_DEFINED)
+
+ #define SGX_CORE_REV_HEAD 0
+ #if defined(USE_SGX_CORE_REV_HEAD)
+
+ #define SGX_CORE_REV SGX_CORE_REV_HEAD
+ #endif
+
+ #if SGX_CORE_REV == 113
+ #define FIX_HW_BRN_29997
+ #define FIX_HW_BRN_30954
+ #define FIX_HW_BRN_31093
+ #define FIX_HW_BRN_31195
+
+ #else
+ #if SGX_CORE_REV == 122
+ #define FIX_HW_BRN_29997
+ #define FIX_HW_BRN_30954
+ #define FIX_HW_BRN_31093
+ #define FIX_HW_BRN_31195
+
+ #else
+ #if SGX_CORE_REV == 140
+ #define FIX_HW_BRN_30954
+ #define FIX_HW_BRN_31195
+
+ #else
+ #if SGX_CORE_REV == SGX_CORE_REV_HEAD
+
+ #else
+ #error "sgxerrata.h: SGX543 Core Revision unspecified"
+ #endif
+ #endif
+ #endif
+ #endif
+
+ #define SGX_CORE_DEFINED
+#endif
+
+#if defined(SGX544) && !defined(SGX_CORE_DEFINED)
+
+ #define SGX_CORE_REV_HEAD 0
+ #if defined(USE_SGX_CORE_REV_HEAD)
+
+ #define SGX_CORE_REV SGX_CORE_REV_HEAD
+ #endif
+
+ #if SGX_CORE_REV == 100
+
+ #else
+ #if SGX_CORE_REV == SGX_CORE_REV_HEAD
+
+ #else
+ #error "sgxerrata.h: SGX544 Core Revision unspecified"
+ #endif
+ #endif
+
+ #define SGX_CORE_DEFINED
+#endif
+
+#if defined(SGX545) && !defined(SGX_CORE_DEFINED)
+
+ #define SGX_CORE_REV_HEAD 0
+ #if defined(USE_SGX_CORE_REV_HEAD)
+
+ #define SGX_CORE_REV SGX_CORE_REV_HEAD
+ #endif
+
+ #if SGX_CORE_REV == 100
+ #define FIX_HW_BRN_26620
+ #define FIX_HW_BRN_27266
+ #define FIX_HW_BRN_27456
+ #define FIX_HW_BRN_29702
+ #define FIX_HW_BRN_29823
+ #else
+ #if SGX_CORE_REV == 109
+ #define FIX_HW_BRN_29702
+ #define FIX_HW_BRN_29823
+ #else
+ #if SGX_CORE_REV == 1012
+ #define FIX_HW_BRN_29823
+ #else
+ #if SGX_CORE_REV == 1013
+ #define FIX_HW_BRN_29823
+ #else
+ #if SGX_CORE_REV == SGX_CORE_REV_HEAD
+
+ #else
+ #error "sgxerrata.h: SGX545 Core Revision unspecified"
+ #endif
+ #endif
+ #endif
+ #endif
+ #endif
+
+ #define SGX_CORE_DEFINED
+#endif
+
+#if defined(SGX554) && !defined(SGX_CORE_DEFINED)
+
+ #define SGX_CORE_REV_HEAD 0
+ #if defined(USE_SGX_CORE_REV_HEAD)
+
+ #define SGX_CORE_REV SGX_CORE_REV_HEAD
+ #endif
+
+ #if SGX_CORE_REV == 100
+
+ #else
+ #if SGX_CORE_REV == SGX_CORE_REV_HEAD
+
+ #else
+ #error "sgxerrata.h: SGX554 Core Revision unspecified"
+ #endif
+ #endif
+
+ #define SGX_CORE_DEFINED
+#endif
+
+#if !defined(SGX_CORE_DEFINED)
+#if defined (__GNUC__)
+ #warning "sgxerrata.h: SGX Core Version unspecified"
+#else
+ #pragma message("sgxerrata.h: SGX Core Version unspecified")
+#endif
+#endif
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#if defined(SGX520)
+ #define SGX_CORE_FRIENDLY_NAME "SGX520"
+ #define SGX_CORE_ID SGX_CORE_ID_520
+ #define SGX_FEATURE_ADDRESS_SPACE_SIZE (28)
+ #define SGX_FEATURE_AUTOCLOCKGATING
+#else
+#if defined(SGX530)
+ #define SGX_CORE_FRIENDLY_NAME "SGX530"
+ #define SGX_CORE_ID SGX_CORE_ID_530
+ #define SGX_FEATURE_ADDRESS_SPACE_SIZE (28)
+ #define SGX_FEATURE_AUTOCLOCKGATING
+#else
+#if defined(SGX531)
+ #define SGX_CORE_FRIENDLY_NAME "SGX531"
+ #define SGX_CORE_ID SGX_CORE_ID_531
+ #define SGX_FEATURE_ADDRESS_SPACE_SIZE (28)
+ #define SGX_FEATURE_AUTOCLOCKGATING
+ #define SGX_FEATURE_MULTI_EVENT_KICK
+#else
+#if defined(SGX535)
+ #define SGX_CORE_FRIENDLY_NAME "SGX535"
+ #define SGX_CORE_ID SGX_CORE_ID_535
+ #define SGX_FEATURE_ADDRESS_SPACE_SIZE (32)
+ #define SGX_FEATURE_MULTIPLE_MEM_CONTEXTS
+ #define SGX_FEATURE_BIF_NUM_DIRLISTS (16)
+ #define SGX_FEATURE_2D_HARDWARE
+ #define SGX_FEATURE_AUTOCLOCKGATING
+ #define SUPPORT_SGX_GENERAL_MAPPING_HEAP
+#else
+#if defined(SGX540)
+ #define SGX_CORE_FRIENDLY_NAME "SGX540"
+ #define SGX_CORE_ID SGX_CORE_ID_540
+ #define SGX_FEATURE_ADDRESS_SPACE_SIZE (28)
+ #define SGX_FEATURE_AUTOCLOCKGATING
+ #define SGX_FEATURE_MULTI_EVENT_KICK
+#else
+#if defined(SGX541)
+ #define SGX_CORE_FRIENDLY_NAME "SGX541"
+ #define SGX_CORE_ID SGX_CORE_ID_541
+ #define SGX_FEATURE_ADDRESS_SPACE_SIZE (32)
+ #define SGX_FEATURE_MULTIPLE_MEM_CONTEXTS
+ #define SGX_FEATURE_BIF_NUM_DIRLISTS (8)
+ #define SGX_FEATURE_AUTOCLOCKGATING
+ #define SGX_FEATURE_SPM_MODE_0
+ #define SGX_FEATURE_MULTI_EVENT_KICK
+#else
+#if defined(SGX543)
+ #define SGX_CORE_FRIENDLY_NAME "SGX543"
+ #define SGX_CORE_ID SGX_CORE_ID_543
+ #define SGX_FEATURE_USE_NO_INSTRUCTION_PAIRING
+ #define SGX_FEATURE_USE_UNLIMITED_PHASES
+ #define SGX_FEATURE_ADDRESS_SPACE_SIZE (32)
+ #define SGX_FEATURE_MULTIPLE_MEM_CONTEXTS
+ #define SGX_FEATURE_BIF_NUM_DIRLISTS (8)
+ #define SGX_FEATURE_AUTOCLOCKGATING
+ #define SGX_FEATURE_MONOLITHIC_UKERNEL
+ #define SGX_FEATURE_SPM_MODE_0
+ #define SGX_FEATURE_MULTI_EVENT_KICK
+ #define SGX_FEATURE_DATA_BREAKPOINTS
+ #define SGX_FEATURE_2D_HARDWARE
+ #define SGX_FEATURE_PTLA
+ #define SGX_FEATURE_EXTENDED_PERF_COUNTERS
+#else
+#if defined(SGX544)
+ #define SGX_CORE_FRIENDLY_NAME "SGX544"
+ #define SGX_CORE_ID SGX_CORE_ID_544
+ #define SGX_FEATURE_USE_NO_INSTRUCTION_PAIRING
+ #define SGX_FEATURE_USE_UNLIMITED_PHASES
+ #define SGX_FEATURE_ADDRESS_SPACE_SIZE (32)
+ #define SGX_FEATURE_MULTIPLE_MEM_CONTEXTS
+ #define SGX_FEATURE_BIF_NUM_DIRLISTS (8)
+ #define SGX_FEATURE_AUTOCLOCKGATING
+ #define SGX_FEATURE_MONOLITHIC_UKERNEL
+ #define SGX_FEATURE_SPM_MODE_0
+ #define SGX_FEATURE_MULTI_EVENT_KICK
+ #define SGX_FEATURE_DATA_BREAKPOINTS
+ #define SGX_FEATURE_EXTENDED_PERF_COUNTERS
+#else
+#if defined(SGX545)
+ #define SGX_CORE_FRIENDLY_NAME "SGX545"
+ #define SGX_CORE_ID SGX_CORE_ID_545
+ #define SGX_FEATURE_ADDRESS_SPACE_SIZE (32)
+ #define SGX_FEATURE_AUTOCLOCKGATING
+ #define SGX_FEATURE_USE_NO_INSTRUCTION_PAIRING
+ #define SGX_FEATURE_USE_UNLIMITED_PHASES
+ #define SGX_FEATURE_VOLUME_TEXTURES
+ #define SGX_FEATURE_HOST_ALLOC_FROM_DPM
+ #define SGX_FEATURE_MULTIPLE_MEM_CONTEXTS
+ #define SGX_FEATURE_BIF_NUM_DIRLISTS (16)
+ #define SGX_FEATURE_NUM_USE_PIPES (4)
+ #define SGX_FEATURE_TEXTURESTRIDE_EXTENSION
+ #define SGX_FEATURE_PDS_DATA_INTERLEAVE_2DWORDS
+ #define SGX_FEATURE_MONOLITHIC_UKERNEL
+ #define SGX_FEATURE_ZLS_EXTERNALZ
+ #define SGX_FEATURE_VDM_CONTEXT_SWITCH_REV_2
+ #define SGX_FEATURE_ISP_CONTEXT_SWITCH_REV_2
+ #define SGX_FEATURE_NUM_PDS_PIPES (2)
+ #define SGX_FEATURE_NATIVE_BACKWARD_BLIT
+ #define SGX_FEATURE_MAX_TA_RENDER_TARGETS (512)
+ #define SGX_FEATURE_SPM_MODE_0
+ #define SGX_FEATURE_SECONDARY_REQUIRES_USE_KICK
+ #define SGX_FEATURE_WRITEBACK_DCU
+
+
+ #define SGX_FEATURE_BIF_WIDE_TILING_AND_4K_ADDRESS
+ #define SGX_FEATURE_MULTI_EVENT_KICK
+#else
+#if defined(SGX554)
+ #define SGX_CORE_FRIENDLY_NAME "SGX554"
+ #define SGX_CORE_ID SGX_CORE_ID_554
+ #define SGX_FEATURE_USE_NO_INSTRUCTION_PAIRING
+ #define SGX_FEATURE_USE_UNLIMITED_PHASES
+ #define SGX_FEATURE_ADDRESS_SPACE_SIZE (32)
+ #define SGX_FEATURE_MULTIPLE_MEM_CONTEXTS
+ #define SGX_FEATURE_BIF_NUM_DIRLISTS (8)
+ #define SGX_FEATURE_AUTOCLOCKGATING
+ #define SGX_FEATURE_MONOLITHIC_UKERNEL
+ #define SGX_FEATURE_SPM_MODE_0
+ #define SGX_FEATURE_MULTI_EVENT_KICK
+ #define SGX_FEATURE_DATA_BREAKPOINTS
+ #define SGX_FEATURE_EXTENDED_PERF_COUNTERS
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+
+#if defined(FIX_HW_BRN_22693)
+#undef SGX_FEATURE_AUTOCLOCKGATING
+#endif
+
+#if defined(FIX_HW_BRN_27266)
+#undef SGX_FEATURE_36BIT_MMU
+#endif
+
+#if defined(FIX_HW_BRN_27456)
+#undef SGX_FEATURE_BIF_WIDE_TILING_AND_4K_ADDRESS
+#endif
+
+#if defined(FIX_HW_BRN_22934) \
+ || defined(FIX_HW_BRN_25499)
+#undef SGX_FEATURE_MULTI_EVENT_KICK
+#endif
+
+#if defined(SGX_FEATURE_SYSTEM_CACHE)
+ #if defined(SGX_FEATURE_36BIT_MMU)
+ #error SGX_FEATURE_SYSTEM_CACHE is incompatible with SGX_FEATURE_36BIT_MMU
+ #endif
+ #if defined(FIX_HW_BRN_26620) && !defined(SGX_FEATURE_MULTI_EVENT_KICK)
+ #define SGX_BYPASS_SYSTEM_CACHE
+ #endif
+#endif
+
+#if defined(SGX_FEATURE_MP)
+#if !defined(SGX_FEATURE_MP_CORE_COUNT)
+#error SGX_FEATURE_MP_CORE_COUNT must be defined when SGX_FEATURE_MP is defined
+#endif
+#else
+#define SGX_FEATURE_MP_CORE_COUNT (1)
+#endif
+
+#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && !defined(SUPPORT_SGX_PRIORITY_SCHEDULING)
+#define SUPPORT_SGX_PRIORITY_SCHEDULING
+#endif
+
+#include "img_types.h"
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#if !defined(__SGXMMU_KM_H__)
+#define __SGXMMU_KM_H__
+
+#define SGX_MMU_PAGE_SHIFT (12)
+#define SGX_MMU_PAGE_SIZE (1U<<SGX_MMU_PAGE_SHIFT)
+#define SGX_MMU_PAGE_MASK (SGX_MMU_PAGE_SIZE - 1U)
+
+#define SGX_MMU_PD_SHIFT (10)
+#define SGX_MMU_PD_SIZE (1U<<SGX_MMU_PD_SHIFT)
+#define SGX_MMU_PD_MASK (0xFFC00000U)
+
+#if defined(SGX_FEATURE_36BIT_MMU)
+ #define SGX_MMU_PDE_ADDR_MASK (0xFFFFFF00U)
+ #define SGX_MMU_PDE_ADDR_ALIGNSHIFT (4)
+#else
+ #define SGX_MMU_PDE_ADDR_MASK (0xFFFFF000U)
+ #define SGX_MMU_PDE_ADDR_ALIGNSHIFT (0)
+#endif
+#define SGX_MMU_PDE_VALID (0x00000001U)
+#define SGX_MMU_PDE_PAGE_SIZE_4K (0x00000000U)
+#if defined(SGX_FEATURE_VARIABLE_MMU_PAGE_SIZE)
+ #define SGX_MMU_PDE_PAGE_SIZE_16K (0x00000002U)
+ #define SGX_MMU_PDE_PAGE_SIZE_64K (0x00000004U)
+ #define SGX_MMU_PDE_PAGE_SIZE_256K (0x00000006U)
+ #define SGX_MMU_PDE_PAGE_SIZE_1M (0x00000008U)
+ #define SGX_MMU_PDE_PAGE_SIZE_4M (0x0000000AU)
+ #define SGX_MMU_PDE_PAGE_SIZE_MASK (0x0000000EU)
+#else
+ #define SGX_MMU_PDE_WRITEONLY (0x00000002U)
+ #define SGX_MMU_PDE_READONLY (0x00000004U)
+ #define SGX_MMU_PDE_CACHECONSISTENT (0x00000008U)
+ #define SGX_MMU_PDE_EDMPROTECT (0x00000010U)
+#endif
+
+#define SGX_MMU_PT_SHIFT (10)
+#define SGX_MMU_PT_SIZE (1U<<SGX_MMU_PT_SHIFT)
+#define SGX_MMU_PT_MASK (0x003FF000U)
+
+#if defined(SGX_FEATURE_36BIT_MMU)
+ #define SGX_MMU_PTE_ADDR_MASK (0xFFFFFF00U)
+ #define SGX_MMU_PTE_ADDR_ALIGNSHIFT (4)
+#else
+ #define SGX_MMU_PTE_ADDR_MASK (0xFFFFF000U)
+ #define SGX_MMU_PTE_ADDR_ALIGNSHIFT (0)
+#endif
+#define SGX_MMU_PTE_VALID (0x00000001U)
+#define SGX_MMU_PTE_WRITEONLY (0x00000002U)
+#define SGX_MMU_PTE_READONLY (0x00000004U)
+#define SGX_MMU_PTE_CACHECONSISTENT (0x00000008U)
+#define SGX_MMU_PTE_EDMPROTECT (0x00000010U)
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef _BUFFER_MANAGER_H_
+#define _BUFFER_MANAGER_H_
+
+#include "img_types.h"
+#include "ra.h"
+#include "perproc.h"
+
+#if defined(__cplusplus)
+extern "C"{
+#endif
+
+typedef struct _BM_HEAP_ BM_HEAP;
+
+struct _BM_MAPPING_
+{
+ enum
+ {
+ hm_wrapped = 1,
+ hm_wrapped_scatter,
+ hm_wrapped_virtaddr,
+ hm_wrapped_scatter_virtaddr,
+ hm_env,
+ hm_contiguous
+ } eCpuMemoryOrigin;
+
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ BM_CONTEXT *pBMContext;
+ BM_HEAP *pBMHeap;
+ RA_ARENA *pArena;
+
+ IMG_CPU_VIRTADDR CpuVAddr;
+ IMG_CPU_PHYADDR CpuPAddr;
+ IMG_DEV_VIRTADDR DevVAddr;
+ IMG_SYS_PHYADDR *psSysAddr;
+ IMG_SIZE_T uSize;
+ IMG_HANDLE hOSMemHandle;
+ IMG_UINT32 ui32Flags;
+};
+
+typedef struct _BM_BUF_
+{
+ IMG_CPU_VIRTADDR *CpuVAddr;
+ IMG_VOID *hOSMemHandle;
+ IMG_CPU_PHYADDR CpuPAddr;
+ IMG_DEV_VIRTADDR DevVAddr;
+
+ BM_MAPPING *pMapping;
+ IMG_UINT32 ui32RefCount;
+ IMG_UINT32 ui32ExportCount;
+} BM_BUF;
+
+struct _BM_HEAP_
+{
+ IMG_UINT32 ui32Attribs;
+ BM_CONTEXT *pBMContext;
+ RA_ARENA *pImportArena;
+ RA_ARENA *pLocalDevMemArena;
+ RA_ARENA *pVMArena;
+ DEV_ARENA_DESCRIPTOR sDevArena;
+ MMU_HEAP *pMMUHeap;
+ PDUMP_MMU_ATTRIB *psMMUAttrib;
+
+ struct _BM_HEAP_ *psNext;
+ struct _BM_HEAP_ **ppsThis;
+};
+
+struct _BM_CONTEXT_
+{
+ MMU_CONTEXT *psMMUContext;
+
+
+ BM_HEAP *psBMHeap;
+
+
+ BM_HEAP *psBMSharedHeap;
+
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+
+
+ HASH_TABLE *pBufferHash;
+
+
+ IMG_HANDLE hResItem;
+
+ IMG_UINT32 ui32RefCount;
+
+
+
+ struct _BM_CONTEXT_ *psNext;
+ struct _BM_CONTEXT_ **ppsThis;
+};
+
+
+
+typedef IMG_VOID *BM_HANDLE;
+
+#define BP_POOL_MASK 0x7
+
+#define BP_CONTIGUOUS (1 << 3)
+#define BP_PARAMBUFFER (1 << 4)
+
+#define BM_MAX_DEVMEM_ARENAS 2
+
+IMG_HANDLE
+BM_CreateContext(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_DEV_PHYADDR *psPDDevPAddr,
+ PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_BOOL *pbCreated);
+
+
+PVRSRV_ERROR
+BM_DestroyContext (IMG_HANDLE hBMContext,
+ IMG_BOOL *pbCreated);
+
+
+IMG_HANDLE
+BM_CreateHeap (IMG_HANDLE hBMContext,
+ DEVICE_MEMORY_HEAP_INFO *psDevMemHeapInfo);
+
+IMG_VOID
+BM_DestroyHeap (IMG_HANDLE hDevMemHeap);
+
+
+IMG_BOOL
+BM_Reinitialise (PVRSRV_DEVICE_NODE *psDeviceNode);
+
+IMG_BOOL
+BM_Alloc (IMG_HANDLE hDevMemHeap,
+ IMG_DEV_VIRTADDR *psDevVAddr,
+ IMG_SIZE_T uSize,
+ IMG_UINT32 *pui32Flags,
+ IMG_UINT32 uDevVAddrAlignment,
+ BM_HANDLE *phBuf);
+
+IMG_BOOL
+BM_Wrap ( IMG_HANDLE hDevMemHeap,
+ IMG_SIZE_T ui32Size,
+ IMG_SIZE_T ui32Offset,
+ IMG_BOOL bPhysContig,
+ IMG_SYS_PHYADDR *psSysAddr,
+ IMG_VOID *pvCPUVAddr,
+ IMG_UINT32 *pui32Flags,
+ BM_HANDLE *phBuf);
+
+IMG_VOID
+BM_Free (BM_HANDLE hBuf,
+ IMG_UINT32 ui32Flags);
+
+
+IMG_CPU_VIRTADDR
+BM_HandleToCpuVaddr (BM_HANDLE hBuf);
+
+IMG_DEV_VIRTADDR
+BM_HandleToDevVaddr (BM_HANDLE hBuf);
+
+IMG_SYS_PHYADDR
+BM_HandleToSysPaddr (BM_HANDLE hBuf);
+
+IMG_HANDLE
+BM_HandleToOSMemHandle (BM_HANDLE hBuf);
+
+IMG_VOID BM_GetPhysPageAddr(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_DEV_VIRTADDR sDevVPageAddr,
+ IMG_DEV_PHYADDR *psDevPAddr);
+
+MMU_CONTEXT* BM_GetMMUContext(IMG_HANDLE hDevMemHeap);
+
+MMU_CONTEXT* BM_GetMMUContextFromMemContext(IMG_HANDLE hDevMemContext);
+
+IMG_HANDLE BM_GetMMUHeap(IMG_HANDLE hDevMemHeap);
+
+PVRSRV_DEVICE_NODE* BM_GetDeviceNode(IMG_HANDLE hDevMemContext);
+
+
+IMG_HANDLE BM_GetMappingHandle(PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+IMG_VOID BM_Export(BM_HANDLE hBuf);
+
+IMG_VOID BM_FreeExport(BM_HANDLE hBuf, IMG_UINT32 ui32Flags);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef __DEVICE_H__
+#define __DEVICE_H__
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#include "servicesint.h"
+#include "ra.h"
+#include "resman.h"
+
+typedef struct _BM_CONTEXT_ BM_CONTEXT;
+
+typedef struct _MMU_HEAP_ MMU_HEAP;
+typedef struct _MMU_CONTEXT_ MMU_CONTEXT;
+
+#define PVRSRV_BACKINGSTORE_SYSMEM_CONTIG (1<<(PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT+0))
+#define PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG (1<<(PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT+1))
+#define PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG (1<<(PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT+2))
+#define PVRSRV_BACKINGSTORE_LOCALMEM_NONCONTIG (1<<(PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT+3))
+
+typedef IMG_UINT32 DEVICE_MEMORY_HEAP_TYPE;
+#define DEVICE_MEMORY_HEAP_PERCONTEXT 0
+#define DEVICE_MEMORY_HEAP_KERNEL 1
+#define DEVICE_MEMORY_HEAP_SHARED 2
+#define DEVICE_MEMORY_HEAP_SHARED_EXPORTED 3
+
+#define PVRSRV_DEVICE_NODE_FLAGS_PORT80DISPLAY 1
+#define PVRSRV_DEVICE_NODE_FLAGS_MMU_OPT_INV 2
+
+typedef struct _DEVICE_MEMORY_HEAP_INFO_
+{
+
+ IMG_UINT32 ui32HeapID;
+
+
+ IMG_CHAR *pszName;
+
+
+ IMG_CHAR *pszBSName;
+
+
+ IMG_DEV_VIRTADDR sDevVAddrBase;
+
+
+ IMG_UINT32 ui32HeapSize;
+
+
+ IMG_UINT32 ui32Attribs;
+
+
+ DEVICE_MEMORY_HEAP_TYPE DevMemHeapType;
+
+
+ IMG_HANDLE hDevMemHeap;
+
+
+ RA_ARENA *psLocalDevMemArena;
+
+
+ IMG_UINT32 ui32DataPageSize;
+
+ IMG_UINT32 ui32XTileStride;
+
+} DEVICE_MEMORY_HEAP_INFO;
+
+typedef struct _DEVICE_MEMORY_INFO_
+{
+
+ IMG_UINT32 ui32AddressSpaceSizeLog2;
+
+
+
+
+ IMG_UINT32 ui32Flags;
+
+
+ IMG_UINT32 ui32HeapCount;
+
+
+ IMG_UINT32 ui32SyncHeapID;
+
+
+ IMG_UINT32 ui32MappingHeapID;
+
+
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+
+
+ BM_CONTEXT *pBMKernelContext;
+
+
+ BM_CONTEXT *pBMContext;
+
+} DEVICE_MEMORY_INFO;
+
+
+typedef struct DEV_ARENA_DESCRIPTOR_TAG
+{
+ IMG_UINT32 ui32HeapID;
+
+ IMG_CHAR *pszName;
+
+ IMG_DEV_VIRTADDR BaseDevVAddr;
+
+ IMG_UINT32 ui32Size;
+
+ DEVICE_MEMORY_HEAP_TYPE DevMemHeapType;
+
+
+ IMG_UINT32 ui32DataPageSize;
+
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeapInfo;
+
+} DEV_ARENA_DESCRIPTOR;
+
+
+typedef struct _PDUMP_MMU_ATTRIB_
+{
+ PVRSRV_DEVICE_IDENTIFIER sDevId;
+
+ IMG_CHAR *pszPDRegRegion;
+
+
+ IMG_UINT32 ui32DataPageMask;
+
+
+ IMG_UINT32 ui32PTEValid;
+ IMG_UINT32 ui32PTSize;
+ IMG_UINT32 ui32PTEAlignShift;
+
+
+ IMG_UINT32 ui32PDEMask;
+ IMG_UINT32 ui32PDEAlignShift;
+
+} PDUMP_MMU_ATTRIB;
+
+typedef struct _SYS_DATA_TAG_ *PSYS_DATA;
+
+typedef struct _PVRSRV_DEVICE_NODE_
+{
+ PVRSRV_DEVICE_IDENTIFIER sDevId;
+ IMG_UINT32 ui32RefCount;
+
+
+
+
+ PVRSRV_ERROR (*pfnInitDevice) (IMG_VOID*);
+
+ PVRSRV_ERROR (*pfnDeInitDevice) (IMG_VOID*);
+
+
+ PVRSRV_ERROR (*pfnInitDeviceCompatCheck) (struct _PVRSRV_DEVICE_NODE_*);
+
+
+ PVRSRV_ERROR (*pfnMMUInitialise)(struct _PVRSRV_DEVICE_NODE_*, MMU_CONTEXT**, IMG_DEV_PHYADDR*);
+ IMG_VOID (*pfnMMUFinalise)(MMU_CONTEXT*);
+ IMG_VOID (*pfnMMUInsertHeap)(MMU_CONTEXT*, MMU_HEAP*);
+ MMU_HEAP* (*pfnMMUCreate)(MMU_CONTEXT*,DEV_ARENA_DESCRIPTOR*,RA_ARENA**,PDUMP_MMU_ATTRIB **ppsMMUAttrib);
+ IMG_VOID (*pfnMMUDelete)(MMU_HEAP*);
+ IMG_BOOL (*pfnMMUAlloc)(MMU_HEAP*pMMU,
+ IMG_SIZE_T uSize,
+ IMG_SIZE_T *pActualSize,
+ IMG_UINT32 uFlags,
+ IMG_UINT32 uDevVAddrAlignment,
+ IMG_DEV_VIRTADDR *pDevVAddr);
+ IMG_VOID (*pfnMMUFree)(MMU_HEAP*,IMG_DEV_VIRTADDR,IMG_UINT32);
+ IMG_VOID (*pfnMMUEnable)(MMU_HEAP*);
+ IMG_VOID (*pfnMMUDisable)(MMU_HEAP*);
+ IMG_VOID (*pfnMMUMapPages)(MMU_HEAP *pMMU,
+ IMG_DEV_VIRTADDR devVAddr,
+ IMG_SYS_PHYADDR SysPAddr,
+ IMG_SIZE_T uSize,
+ IMG_UINT32 ui32MemFlags,
+ IMG_HANDLE hUniqueTag);
+ IMG_VOID (*pfnMMUMapShadow)(MMU_HEAP *pMMU,
+ IMG_DEV_VIRTADDR MapBaseDevVAddr,
+ IMG_SIZE_T uSize,
+ IMG_CPU_VIRTADDR CpuVAddr,
+ IMG_HANDLE hOSMemHandle,
+ IMG_DEV_VIRTADDR *pDevVAddr,
+ IMG_UINT32 ui32MemFlags,
+ IMG_HANDLE hUniqueTag);
+ IMG_VOID (*pfnMMUUnmapPages)(MMU_HEAP *pMMU,
+ IMG_DEV_VIRTADDR dev_vaddr,
+ IMG_UINT32 ui32PageCount,
+ IMG_HANDLE hUniqueTag);
+
+ IMG_VOID (*pfnMMUMapScatter)(MMU_HEAP *pMMU,
+ IMG_DEV_VIRTADDR DevVAddr,
+ IMG_SYS_PHYADDR *psSysAddr,
+ IMG_SIZE_T uSize,
+ IMG_UINT32 ui32MemFlags,
+ IMG_HANDLE hUniqueTag);
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+ IMG_BOOL (*pfnMMUIsHeapShared)(MMU_HEAP *);
+#endif
+ IMG_DEV_PHYADDR (*pfnMMUGetPhysPageAddr)(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR sDevVPageAddr);
+ IMG_DEV_PHYADDR (*pfnMMUGetPDDevPAddr)(MMU_CONTEXT *pMMUContext);
+
+
+ PVRSRV_ERROR (*pfnAllocMemTilingRange)(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode,
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32TilingStride,
+ IMG_UINT32 *pui32RangeIndex);
+ PVRSRV_ERROR (*pfnFreeMemTilingRange)(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode,
+ IMG_UINT32 ui32RangeIndex);
+
+
+ IMG_BOOL (*pfnDeviceISR)(IMG_VOID*);
+
+ IMG_VOID *pvISRData;
+
+ IMG_UINT32 ui32SOCInterruptBit;
+
+ IMG_VOID (*pfnDeviceMISR)(IMG_VOID*);
+
+
+ IMG_VOID (*pfnDeviceCommandComplete)(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode);
+
+ IMG_BOOL bReProcessDeviceCommandComplete;
+
+
+ DEVICE_MEMORY_INFO sDevMemoryInfo;
+
+
+ IMG_VOID *pvDevice;
+ IMG_UINT32 ui32pvDeviceSize;
+
+
+ PRESMAN_CONTEXT hResManContext;
+
+
+ PSYS_DATA psSysData;
+
+
+ RA_ARENA *psLocalDevMemArena;
+
+ IMG_UINT32 ui32Flags;
+
+ struct _PVRSRV_DEVICE_NODE_ *psNext;
+ struct _PVRSRV_DEVICE_NODE_ **ppsThis;
+#if defined(PVRSRV_RESOURCE_PROFILING)
+ PVRSRV_ERROR (*pfnResProfCB)(IMG_VOID *psDeviceNode, IMG_UINT32 ui32AllocedMem, IMG_BOOL bAlloc);
+#endif
+
+#if defined(PDUMP)
+
+ PVRSRV_ERROR (*pfnPDumpInitDevice)(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode);
+
+ IMG_UINT32 (*pfnMMUGetContextID)(IMG_HANDLE hDevMemContext);
+#endif
+} PVRSRV_DEVICE_NODE;
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVRegisterDevice(PSYS_DATA psSysData,
+ PVRSRV_ERROR (*pfnRegisterDevice)(PVRSRV_DEVICE_NODE*),
+ IMG_UINT32 ui32SOCInterruptBit,
+ IMG_UINT32 *pui32DeviceIndex );
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVInitialiseDevice(IMG_UINT32 ui32DevIndex);
+PVRSRV_ERROR IMG_CALLCONV PVRSRVFinaliseSystem(IMG_BOOL bInitSuccesful);
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDeinitialiseDevice(IMG_UINT32 ui32DevIndex);
+
+#if !defined(USE_CODE)
+
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PollForValueKM(volatile IMG_UINT32* pui32LinMemAddr,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask,
+ IMG_UINT32 ui32Timeoutus,
+ IMG_UINT32 ui32PollPeriodus,
+ IMG_BOOL bAllowPreemption);
+
+#endif
+
+
+#if defined (USING_ISR_INTERRUPTS)
+PVRSRV_ERROR IMG_CALLCONV PollForInterruptKM(IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask,
+ IMG_UINT32 ui32Waitus,
+ IMG_UINT32 ui32Tries);
+#endif
+
+PVRSRV_ERROR IMG_CALLCONV PVRSRVInit(PSYS_DATA psSysData);
+IMG_VOID IMG_CALLCONV PVRSRVDeInit(PSYS_DATA psSysData);
+IMG_BOOL IMG_CALLCONV PVRSRVDeviceLISR(PVRSRV_DEVICE_NODE *psDeviceNode);
+IMG_BOOL IMG_CALLCONV PVRSRVSystemLISR(IMG_VOID *pvSysData);
+IMG_VOID IMG_CALLCONV PVRSRVMISR(IMG_VOID *pvSysData);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef __HANDLE_H__
+#define __HANDLE_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include "img_types.h"
+#include "hash.h"
+#include "resman.h"
+
+typedef enum
+{
+ PVRSRV_HANDLE_TYPE_NONE = 0,
+ PVRSRV_HANDLE_TYPE_PERPROC_DATA,
+ PVRSRV_HANDLE_TYPE_DEV_NODE,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+ PVRSRV_HANDLE_TYPE_MEM_INFO,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO,
+ PVRSRV_HANDLE_TYPE_DISP_INFO,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN,
+ PVRSRV_HANDLE_TYPE_BUF_INFO,
+ PVRSRV_HANDLE_TYPE_DISP_BUFFER,
+ PVRSRV_HANDLE_TYPE_BUF_BUFFER,
+ PVRSRV_HANDLE_TYPE_SGX_HW_RENDER_CONTEXT,
+ PVRSRV_HANDLE_TYPE_SGX_HW_TRANSFER_CONTEXT,
+ PVRSRV_HANDLE_TYPE_SGX_HW_2D_CONTEXT,
+ PVRSRV_HANDLE_TYPE_SHARED_PB_DESC,
+ PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+ PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO,
+ PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT,
+ PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT,
+ PVRSRV_HANDLE_TYPE_MMAP_INFO,
+ PVRSRV_HANDLE_TYPE_SOC_TIMER,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO_MOD_OBJ
+} PVRSRV_HANDLE_TYPE;
+
+typedef enum
+{
+
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE = 0,
+
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED = 0x01,
+
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI = 0x02,
+
+ PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE = 0x04
+} PVRSRV_HANDLE_ALLOC_FLAG;
+
+struct _PVRSRV_HANDLE_BASE_;
+typedef struct _PVRSRV_HANDLE_BASE_ PVRSRV_HANDLE_BASE;
+
+#ifdef PVR_SECURE_HANDLES
+extern PVRSRV_HANDLE_BASE *gpsKernelHandleBase;
+
+#define KERNEL_HANDLE_BASE (gpsKernelHandleBase)
+
+PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag);
+
+PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_HANDLE hParent);
+
+PVRSRV_ERROR PVRSRVFindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType);
+
+PVRSRV_ERROR PVRSRVLookupHandleAnyType(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, PVRSRV_HANDLE_TYPE *peType, IMG_HANDLE hHandle);
+
+PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+
+PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hAncestor);
+
+PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *phParent, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+
+PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+
+PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+
+PVRSRV_ERROR PVRSRVNewHandleBatch(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32BatchSize);
+
+PVRSRV_ERROR PVRSRVCommitHandleBatch(PVRSRV_HANDLE_BASE *psBase);
+
+IMG_VOID PVRSRVReleaseHandleBatch(PVRSRV_HANDLE_BASE *psBase);
+
+PVRSRV_ERROR PVRSRVSetMaxHandle(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32MaxHandle);
+
+IMG_UINT32 PVRSRVGetMaxHandle(PVRSRV_HANDLE_BASE *psBase);
+
+PVRSRV_ERROR PVRSRVEnableHandlePurging(PVRSRV_HANDLE_BASE *psBase);
+
+PVRSRV_ERROR PVRSRVPurgeHandles(PVRSRV_HANDLE_BASE *psBase);
+
+PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE **ppsBase);
+
+PVRSRV_ERROR PVRSRVFreeHandleBase(PVRSRV_HANDLE_BASE *psBase);
+
+PVRSRV_ERROR PVRSRVHandleInit(IMG_VOID);
+
+PVRSRV_ERROR PVRSRVHandleDeInit(IMG_VOID);
+
+#else
+
+#define KERNEL_HANDLE_BASE IMG_NULL
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVAllocHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag)
+{
+ PVR_UNREFERENCED_PARAMETER(eType);
+ PVR_UNREFERENCED_PARAMETER(eFlag);
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ *phHandle = pvData;
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVAllocSubHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_HANDLE hParent)
+{
+ PVR_UNREFERENCED_PARAMETER(eType);
+ PVR_UNREFERENCED_PARAMETER(eFlag);
+ PVR_UNREFERENCED_PARAMETER(hParent);
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ *phHandle = pvData;
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVFindHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVFindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType)
+{
+ PVR_UNREFERENCED_PARAMETER(eType);
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ *phHandle = pvData;
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVLookupHandleAnyType)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVLookupHandleAnyType(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, PVRSRV_HANDLE_TYPE *peType, IMG_HANDLE hHandle)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ *peType = PVRSRV_HANDLE_TYPE_NONE;
+
+ *ppvData = hHandle;
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVLookupHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+ PVR_UNREFERENCED_PARAMETER(eType);
+
+ *ppvData = hHandle;
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVLookupSubHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hAncestor)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+ PVR_UNREFERENCED_PARAMETER(eType);
+ PVR_UNREFERENCED_PARAMETER(hAncestor);
+
+ *ppvData = hHandle;
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVGetParentHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *phParent, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+ PVR_UNREFERENCED_PARAMETER(eType);
+ PVR_UNREFERENCED_PARAMETER(hHandle);
+
+ *phParent = IMG_NULL;
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVLookupAndReleaseHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+ PVR_UNREFERENCED_PARAMETER(eType);
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ *ppvData = hHandle;
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVReleaseHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+ PVR_UNREFERENCED_PARAMETER(hHandle);
+ PVR_UNREFERENCED_PARAMETER(eType);
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVNewHandleBatch)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVNewHandleBatch(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32BatchSize)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+ PVR_UNREFERENCED_PARAMETER(ui32BatchSize);
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVCommitHandleBatch)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVCommitHandleBatch(PVRSRV_HANDLE_BASE *psBase)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVReleaseHandleBatch)
+#endif
+static INLINE
+IMG_VOID PVRSRVReleaseHandleBatch(PVRSRV_HANDLE_BASE *psBase)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVSetMaxHandle)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVSetMaxHandle(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32MaxHandle)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+ PVR_UNREFERENCED_PARAMETER(ui32MaxHandle);
+
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVGetMaxHandle)
+#endif
+static INLINE
+IMG_UINT32 PVRSRVGetMaxHandle(PVRSRV_HANDLE_BASE *psBase)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ return 0;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVEnableHandlePurging)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVEnableHandlePurging(PVRSRV_HANDLE_BASE *psBase)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVPurgeHandles)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVPurgeHandles(PVRSRV_HANDLE_BASE *psBase)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVAllocHandleBase)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE **ppsBase)
+{
+ *ppsBase = IMG_NULL;
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVFreeHandleBase)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVFreeHandleBase(PVRSRV_HANDLE_BASE *psBase)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVHandleInit)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVHandleInit(IMG_VOID)
+{
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVHandleDeInit)
+#endif
+static INLINE
+PVRSRV_ERROR PVRSRVHandleDeInit(IMG_VOID)
+{
+ return PVRSRV_OK;
+}
+
+#endif
+
+#define PVRSRVAllocHandleNR(psBase, phHandle, pvData, eType, eFlag) \
+ (IMG_VOID)PVRSRVAllocHandle(psBase, phHandle, pvData, eType, eFlag)
+
+#define PVRSRVAllocSubHandleNR(psBase, phHandle, pvData, eType, eFlag, hParent) \
+ (IMG_VOID)PVRSRVAllocSubHandle(psBase, phHandle, pvData, eType, eFlag, hParent)
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef _HASH_H_
+#define _HASH_H_
+
+#include "img_types.h"
+#include "osfunc.h"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+typedef IMG_UINT32 HASH_FUNC(IMG_SIZE_T uKeySize, IMG_VOID *pKey, IMG_UINT32 uHashTabLen);
+typedef IMG_BOOL HASH_KEY_COMP(IMG_SIZE_T uKeySize, IMG_VOID *pKey1, IMG_VOID *pKey2);
+
+typedef struct _HASH_TABLE_ HASH_TABLE;
+
+IMG_UINT32 HASH_Func_Default (IMG_SIZE_T uKeySize, IMG_VOID *pKey, IMG_UINT32 uHashTabLen);
+
+IMG_BOOL HASH_Key_Comp_Default (IMG_SIZE_T uKeySize, IMG_VOID *pKey1, IMG_VOID *pKey2);
+
+HASH_TABLE * HASH_Create_Extended (IMG_UINT32 uInitialLen, IMG_SIZE_T uKeySize, HASH_FUNC *pfnHashFunc, HASH_KEY_COMP *pfnKeyComp);
+
+HASH_TABLE * HASH_Create (IMG_UINT32 uInitialLen);
+
+IMG_VOID HASH_Delete (HASH_TABLE *pHash);
+
+IMG_BOOL HASH_Insert_Extended (HASH_TABLE *pHash, IMG_VOID *pKey, IMG_UINTPTR_T v);
+
+IMG_BOOL HASH_Insert (HASH_TABLE *pHash, IMG_UINTPTR_T k, IMG_UINTPTR_T v);
+
+IMG_UINTPTR_T HASH_Remove_Extended(HASH_TABLE *pHash, IMG_VOID *pKey);
+
+IMG_UINTPTR_T HASH_Remove (HASH_TABLE *pHash, IMG_UINTPTR_T k);
+
+IMG_UINTPTR_T HASH_Retrieve_Extended (HASH_TABLE *pHash, IMG_VOID *pKey);
+
+IMG_UINTPTR_T HASH_Retrieve (HASH_TABLE *pHash, IMG_UINTPTR_T k);
+
+#ifdef HASH_TRACE
+IMG_VOID HASH_Dump (HASH_TABLE *pHash);
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef __LISTS_UTILS__
+#define __LISTS_UTILS__
+
+#include <stdarg.h>
+#include "img_types.h"
+
+#define DECLARE_LIST_FOR_EACH(TYPE) \
+IMG_VOID List_##TYPE##_ForEach(TYPE *psHead, IMG_VOID(*pfnCallBack)(TYPE* psNode))
+
+#define IMPLEMENT_LIST_FOR_EACH(TYPE) \
+IMG_VOID List_##TYPE##_ForEach(TYPE *psHead, IMG_VOID(*pfnCallBack)(TYPE* psNode))\
+{\
+ while(psHead)\
+ {\
+ pfnCallBack(psHead);\
+ psHead = psHead->psNext;\
+ }\
+}
+
+
+#define DECLARE_LIST_FOR_EACH_VA(TYPE) \
+IMG_VOID List_##TYPE##_ForEach_va(TYPE *psHead, IMG_VOID(*pfnCallBack)(TYPE* psNode, va_list va), ...)
+
+#define IMPLEMENT_LIST_FOR_EACH_VA(TYPE) \
+IMG_VOID List_##TYPE##_ForEach_va(TYPE *psHead, IMG_VOID(*pfnCallBack)(TYPE* psNode, va_list va), ...) \
+{\
+ va_list ap;\
+ while(psHead)\
+ {\
+ va_start(ap, pfnCallBack);\
+ pfnCallBack(psHead, ap);\
+ psHead = psHead->psNext;\
+ va_end(ap);\
+ }\
+}
+
+
+#define DECLARE_LIST_ANY(TYPE) \
+IMG_VOID* List_##TYPE##_Any(TYPE *psHead, IMG_VOID* (*pfnCallBack)(TYPE* psNode))
+
+#define IMPLEMENT_LIST_ANY(TYPE) \
+IMG_VOID* List_##TYPE##_Any(TYPE *psHead, IMG_VOID* (*pfnCallBack)(TYPE* psNode))\
+{ \
+ IMG_VOID *pResult;\
+ TYPE *psNextNode;\
+ pResult = IMG_NULL;\
+ psNextNode = psHead;\
+ while(psHead && !pResult)\
+ {\
+ psNextNode = psNextNode->psNext;\
+ pResult = pfnCallBack(psHead);\
+ psHead = psNextNode;\
+ }\
+ return pResult;\
+}
+
+
+#define DECLARE_LIST_ANY_VA(TYPE) \
+IMG_VOID* List_##TYPE##_Any_va(TYPE *psHead, IMG_VOID*(*pfnCallBack)(TYPE* psNode, va_list va), ...)
+
+#define IMPLEMENT_LIST_ANY_VA(TYPE) \
+IMG_VOID* List_##TYPE##_Any_va(TYPE *psHead, IMG_VOID*(*pfnCallBack)(TYPE* psNode, va_list va), ...)\
+{\
+ va_list ap;\
+ TYPE *psNextNode;\
+ IMG_VOID* pResult = IMG_NULL;\
+ while(psHead && !pResult)\
+ {\
+ psNextNode = psHead->psNext;\
+ va_start(ap, pfnCallBack);\
+ pResult = pfnCallBack(psHead, ap);\
+ va_end(ap);\
+ psHead = psNextNode;\
+ }\
+ return pResult;\
+}
+
+#define DECLARE_LIST_ANY_2(TYPE, RTYPE, CONTINUE) \
+RTYPE List_##TYPE##_##RTYPE##_Any(TYPE *psHead, RTYPE (*pfnCallBack)(TYPE* psNode))
+
+#define IMPLEMENT_LIST_ANY_2(TYPE, RTYPE, CONTINUE) \
+RTYPE List_##TYPE##_##RTYPE##_Any(TYPE *psHead, RTYPE (*pfnCallBack)(TYPE* psNode))\
+{ \
+ RTYPE result;\
+ TYPE *psNextNode;\
+ result = CONTINUE;\
+ psNextNode = psHead;\
+ while(psHead && result == CONTINUE)\
+ {\
+ psNextNode = psNextNode->psNext;\
+ result = pfnCallBack(psHead);\
+ psHead = psNextNode;\
+ }\
+ return result;\
+}
+
+
+#define DECLARE_LIST_ANY_VA_2(TYPE, RTYPE, CONTINUE) \
+RTYPE List_##TYPE##_##RTYPE##_Any_va(TYPE *psHead, RTYPE(*pfnCallBack)(TYPE* psNode, va_list va), ...)
+
+#define IMPLEMENT_LIST_ANY_VA_2(TYPE, RTYPE, CONTINUE) \
+RTYPE List_##TYPE##_##RTYPE##_Any_va(TYPE *psHead, RTYPE(*pfnCallBack)(TYPE* psNode, va_list va), ...)\
+{\
+ va_list ap;\
+ TYPE *psNextNode;\
+ RTYPE result = CONTINUE;\
+ while(psHead && result == CONTINUE)\
+ {\
+ psNextNode = psHead->psNext;\
+ va_start(ap, pfnCallBack);\
+ result = pfnCallBack(psHead, ap);\
+ va_end(ap);\
+ psHead = psNextNode;\
+ }\
+ return result;\
+}
+
+
+#define DECLARE_LIST_REMOVE(TYPE) \
+IMG_VOID List_##TYPE##_Remove(TYPE *psNode)
+
+#define IMPLEMENT_LIST_REMOVE(TYPE) \
+IMG_VOID List_##TYPE##_Remove(TYPE *psNode)\
+{\
+ (*psNode->ppsThis)=psNode->psNext;\
+ if(psNode->psNext)\
+ {\
+ psNode->psNext->ppsThis = psNode->ppsThis;\
+ }\
+}
+
+#define DECLARE_LIST_INSERT(TYPE) \
+IMG_VOID List_##TYPE##_Insert(TYPE **ppsHead, TYPE *psNewNode)
+
+#define IMPLEMENT_LIST_INSERT(TYPE) \
+IMG_VOID List_##TYPE##_Insert(TYPE **ppsHead, TYPE *psNewNode)\
+{\
+ psNewNode->ppsThis = ppsHead;\
+ psNewNode->psNext = *ppsHead;\
+ *ppsHead = psNewNode;\
+ if(psNewNode->psNext)\
+ {\
+ psNewNode->psNext->ppsThis = &(psNewNode->psNext);\
+ }\
+}
+
+#define DECLARE_LIST_FIND(TYPE) \
+IMG_VOID* List_##TYPE##_Find(TYPE *psHead, TYPE *psNode)
+
+#define IMPLEMENT_LIST_FIND(TYPE) \
+IMG_VOID* List_##TYPE##_Find(TYPE *psHead, TYPE *psNode)\
+{\
+ while (psHead)\
+ {\
+ if (psHead == psNode) \
+ {\
+ break;\
+ }\
+ psHead = psHead->psNext;\
+ }\
+ return psHead;\
+}
+
+#define DECLARE_LIST_REVERSE(TYPE) \
+IMG_VOID List_##TYPE##_Reverse(TYPE **ppsHead)
+
+#define IMPLEMENT_LIST_REVERSE(TYPE) \
+IMG_VOID List_##TYPE##_Reverse(TYPE **ppsHead)\
+{\
+ TYPE *psTmpNode1; \
+ TYPE *psTmpNode2; \
+ TYPE *psCurNode; \
+ psTmpNode1 = IMG_NULL; \
+ psCurNode = *ppsHead; \
+ while(psCurNode) { \
+ psTmpNode2 = psCurNode->psNext; \
+ psCurNode->psNext = psTmpNode1; \
+ psTmpNode1 = psCurNode; \
+ psCurNode = psTmpNode2; \
+ if(psCurNode) \
+ { \
+ psTmpNode1->ppsThis = &(psCurNode->psNext); \
+ } \
+ else \
+ { \
+ psTmpNode1->ppsThis = ppsHead; \
+ } \
+ } \
+ *ppsHead = psTmpNode1; \
+}
+
+#define IS_LAST_ELEMENT(x) ((x)->psNext == IMG_NULL)
+
+#include "services_headers.h"
+
+DECLARE_LIST_ANY_VA(BM_HEAP);
+DECLARE_LIST_ANY_2(BM_HEAP, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_ANY_VA_2(BM_HEAP, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_FOR_EACH_VA(BM_HEAP);
+DECLARE_LIST_REMOVE(BM_HEAP);
+DECLARE_LIST_INSERT(BM_HEAP);
+DECLARE_LIST_FIND(BM_HEAP);
+
+DECLARE_LIST_ANY_VA(BM_CONTEXT);
+DECLARE_LIST_ANY_VA_2(BM_CONTEXT, IMG_HANDLE, IMG_NULL);
+DECLARE_LIST_ANY_VA_2(BM_CONTEXT, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_FOR_EACH(BM_CONTEXT);
+DECLARE_LIST_REMOVE(BM_CONTEXT);
+DECLARE_LIST_INSERT(BM_CONTEXT);
+DECLARE_LIST_FIND(BM_CONTEXT);
+
+DECLARE_LIST_ANY_2(PVRSRV_DEVICE_NODE, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_ANY_VA(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_ANY_VA_2(PVRSRV_DEVICE_NODE, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_FOR_EACH(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_FOR_EACH_VA(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_INSERT(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_REMOVE(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_FIND(PVRSRV_DEVICE_NODE);
+
+DECLARE_LIST_ANY_VA(PVRSRV_POWER_DEV);
+DECLARE_LIST_ANY_VA_2(PVRSRV_POWER_DEV, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_INSERT(PVRSRV_POWER_DEV);
+DECLARE_LIST_REMOVE(PVRSRV_POWER_DEV);
+
+#if defined(PERPROC_LIST)
+DECLARE_LIST_FOR_EACH_VA(PVRSRV_PER_PROCESS_DATA);
+DECLARE_LIST_INSERT(PVRSRV_PER_PROCESS_DATA);
+DECLARE_LIST_REMOVE(PVRSRV_PER_PROCESS_DATA);
+#endif
+
+#undef DECLARE_LIST_ANY_2
+#undef DECLARE_LIST_ANY_VA
+#undef DECLARE_LIST_ANY_VA_2
+#undef DECLARE_LIST_FOR_EACH
+#undef DECLARE_LIST_FOR_EACH_VA
+#undef DECLARE_LIST_INSERT
+#undef DECLARE_LIST_REMOVE
+#undef DECLARE_LIST_FIND
+
+IMG_VOID* MatchDeviceKM_AnyVaCb(PVRSRV_DEVICE_NODE* psDeviceNode, va_list va);
+IMG_VOID* MatchPowerDeviceIndex_AnyVaCb(PVRSRV_POWER_DEV *psPowerDev, va_list va);
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef _METRICS_
+#define _METRICS_
+
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+
+#if defined(DEBUG) || defined(TIMING)
+
+
+typedef struct
+{
+ IMG_UINT32 ui32Start;
+ IMG_UINT32 ui32Stop;
+ IMG_UINT32 ui32Total;
+ IMG_UINT32 ui32Count;
+} Temporal_Data;
+
+extern Temporal_Data asTimers[];
+
+extern IMG_UINT32 PVRSRVTimeNow(IMG_VOID);
+extern IMG_VOID PVRSRVSetupMetricTimers(IMG_VOID *pvDevInfo);
+extern IMG_VOID PVRSRVOutputMetricTotals(IMG_VOID);
+
+
+#define PVRSRV_TIMER_DUMMY 0
+
+#define PVRSRV_TIMER_EXAMPLE_1 1
+#define PVRSRV_TIMER_EXAMPLE_2 2
+
+
+#define PVRSRV_NUM_TIMERS (PVRSRV_TIMER_EXAMPLE_2 + 1)
+
+#define PVRSRV_TIME_START(X) { \
+ asTimers[X].ui32Count += 1; \
+ asTimers[X].ui32Count |= 0x80000000L; \
+ asTimers[X].ui32Start = PVRSRVTimeNow(); \
+ asTimers[X].ui32Stop = 0; \
+ }
+
+#define PVRSRV_TIME_SUSPEND(X) { \
+ asTimers[X].ui32Stop += PVRSRVTimeNow() - asTimers[X].ui32Start; \
+ }
+
+#define PVRSRV_TIME_RESUME(X) { \
+ asTimers[X].ui32Start = PVRSRVTimeNow(); \
+ }
+
+#define PVRSRV_TIME_STOP(X) { \
+ asTimers[X].ui32Stop += PVRSRVTimeNow() - asTimers[X].ui32Start; \
+ asTimers[X].ui32Total += asTimers[X].ui32Stop; \
+ asTimers[X].ui32Count &= 0x7FFFFFFFL; \
+ }
+
+#define PVRSRV_TIME_RESET(X) { \
+ asTimers[X].ui32Start = 0; \
+ asTimers[X].ui32Stop = 0; \
+ asTimers[X].ui32Total = 0; \
+ asTimers[X].ui32Count = 0; \
+ }
+
+
+#if defined(__sh__)
+
+#define TST_REG ((volatile IMG_UINT8 *) (psDevInfo->pvSOCRegsBaseKM))
+
+#define TCOR_2 ((volatile IMG_UINT *) (psDevInfo->pvSOCRegsBaseKM+28))
+#define TCNT_2 ((volatile IMG_UINT *) (psDevInfo->pvSOCRegsBaseKM+32))
+#define TCR_2 ((volatile IMG_UINT16 *)(psDevInfo->pvSOCRegsBaseKM+36))
+
+#define TIMER_DIVISOR 4
+
+#endif
+
+
+
+
+
+#else
+
+
+
+#define PVRSRV_TIME_START(X)
+#define PVRSRV_TIME_SUSPEND(X)
+#define PVRSRV_TIME_RESUME(X)
+#define PVRSRV_TIME_STOP(X)
+#define PVRSRV_TIME_RESET(X)
+
+#define PVRSRVSetupMetricTimers(X)
+#define PVRSRVOutputMetricTotals()
+
+
+
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifdef DEBUG_RELEASE_BUILD
+#pragma optimize( "", off )
+#define DEBUG 1
+#endif
+
+#ifndef __OSFUNC_H__
+#define __OSFUNC_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if defined(__linux__) && defined(__KERNEL__)
+#include <linux/hardirq.h>
+#include <linux/string.h>
+#include <asm/system.h>
+#if defined(__arm__)
+#include <asm/memory.h>
+#endif
+#endif
+
+#include "services.h"
+
+
+ #define PVRSRV_PAGEABLE_SELECT PVRSRV_OS_PAGEABLE_HEAP
+
+#define KERNEL_ID 0xffffffffL
+#define POWER_MANAGER_ID 0xfffffffeL
+#define ISR_ID 0xfffffffdL
+#define TIMER_ID 0xfffffffcL
+
+
+#define HOST_PAGESIZE OSGetPageSize
+#define HOST_PAGEMASK (HOST_PAGESIZE()-1)
+#define HOST_PAGEALIGN(addr) (((addr) + HOST_PAGEMASK) & ~HOST_PAGEMASK)
+
+#define PVRSRV_OS_HEAP_MASK 0xf
+#define PVRSRV_OS_PAGEABLE_HEAP 0x1
+#define PVRSRV_OS_NON_PAGEABLE_HEAP 0x2
+
+
+IMG_UINT32 OSClockus(IMG_VOID);
+IMG_SIZE_T OSGetPageSize(IMG_VOID);
+PVRSRV_ERROR OSInstallDeviceLISR(IMG_VOID *pvSysData,
+ IMG_UINT32 ui32Irq,
+ IMG_CHAR *pszISRName,
+ IMG_VOID *pvDeviceNode);
+PVRSRV_ERROR OSUninstallDeviceLISR(IMG_VOID *pvSysData);
+PVRSRV_ERROR OSInstallSystemLISR(IMG_VOID *pvSysData, IMG_UINT32 ui32Irq);
+PVRSRV_ERROR OSUninstallSystemLISR(IMG_VOID *pvSysData);
+PVRSRV_ERROR OSInstallMISR(IMG_VOID *pvSysData);
+PVRSRV_ERROR OSUninstallMISR(IMG_VOID *pvSysData);
+IMG_CPU_PHYADDR OSMapLinToCPUPhys(IMG_HANDLE, IMG_VOID* pvLinAddr);
+IMG_VOID OSMemCopy(IMG_VOID *pvDst, IMG_VOID *pvSrc, IMG_SIZE_T ui32Size);
+IMG_VOID *OSMapPhysToLin(IMG_CPU_PHYADDR BasePAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_HANDLE *phOSMemHandle);
+IMG_BOOL OSUnMapPhysToLin(IMG_VOID *pvLinAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_HANDLE hOSMemHandle);
+
+PVRSRV_ERROR OSReservePhys(IMG_CPU_PHYADDR BasePAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_VOID **ppvCpuVAddr, IMG_HANDLE *phOSMemHandle);
+PVRSRV_ERROR OSUnReservePhys(IMG_VOID *pvCpuVAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_HANDLE hOSMemHandle);
+
+#if defined(__linux__) && defined(__KERNEL__)
+
+IMG_VOID OSFlushCPUCacheKM(IMG_VOID);
+
+IMG_VOID OSCleanCPUCacheKM(IMG_VOID);
+
+IMG_BOOL OSFlushCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32Length);
+IMG_BOOL OSCleanCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32Length);
+IMG_BOOL OSInvalidateCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32Length);
+
+#else
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSFlushCPUCacheKM)
+#endif
+static INLINE IMG_VOID OSFlushCPUCacheKM(IMG_VOID) {}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSCleanCPUCacheKM)
+#endif
+static INLINE IMG_VOID OSCleanCPUCacheKM(IMG_VOID) {}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSFlushCPUCacheRangeKM)
+#endif
+static INLINE IMG_BOOL OSFlushCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32Length)
+{
+ PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+ PVR_UNREFERENCED_PARAMETER(pvRangeAddrStart);
+ PVR_UNREFERENCED_PARAMETER(ui32Length);
+ return IMG_FALSE;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSCleanCPUCacheRangeKM)
+#endif
+static INLINE IMG_BOOL OSCleanCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32Length)
+{
+ PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+ PVR_UNREFERENCED_PARAMETER(pvRangeAddrStart);
+ PVR_UNREFERENCED_PARAMETER(ui32Length);
+ return IMG_FALSE;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSInvalidateCPUCacheRangeKM)
+#endif
+static INLINE IMG_BOOL OSInvalidateCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32Length)
+{
+ PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+ PVR_UNREFERENCED_PARAMETER(pvRangeAddrStart);
+ PVR_UNREFERENCED_PARAMETER(ui32Length);
+ return IMG_FALSE;
+}
+
+#endif
+
+#if defined(__linux__)
+PVRSRV_ERROR OSRegisterDiscontigMem(IMG_SYS_PHYADDR *pBasePAddr,
+ IMG_VOID *pvCpuVAddr,
+ IMG_SIZE_T ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE *phOSMemHandle);
+PVRSRV_ERROR OSUnRegisterDiscontigMem(IMG_VOID *pvCpuVAddr,
+ IMG_SIZE_T ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hOSMemHandle);
+#else
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSRegisterDiscontigMem)
+#endif
+static INLINE PVRSRV_ERROR OSRegisterDiscontigMem(IMG_SYS_PHYADDR *pBasePAddr,
+ IMG_VOID *pvCpuVAddr,
+ IMG_SIZE_T ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE *phOSMemHandle)
+{
+ PVR_UNREFERENCED_PARAMETER(pBasePAddr);
+ PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+ PVR_UNREFERENCED_PARAMETER(ui32Flags);
+ PVR_UNREFERENCED_PARAMETER(phOSMemHandle);
+
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSUnRegisterDiscontigMem)
+#endif
+static INLINE PVRSRV_ERROR OSUnRegisterDiscontigMem(IMG_VOID *pvCpuVAddr,
+ IMG_SIZE_T ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hOSMemHandle)
+{
+ PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+ PVR_UNREFERENCED_PARAMETER(ui32Flags);
+ PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+#endif
+
+
+#if defined(__linux__)
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSReserveDiscontigPhys)
+#endif
+static INLINE PVRSRV_ERROR OSReserveDiscontigPhys(IMG_SYS_PHYADDR *pBasePAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_VOID **ppvCpuVAddr, IMG_HANDLE *phOSMemHandle)
+{
+#if defined(__linux__)
+ *ppvCpuVAddr = IMG_NULL;
+ return OSRegisterDiscontigMem(pBasePAddr, *ppvCpuVAddr, ui32Bytes, ui32Flags, phOSMemHandle);
+#else
+ extern IMG_CPU_PHYADDR SysSysPAddrToCpuPAddr(IMG_SYS_PHYADDR SysPAddr);
+
+
+ return OSReservePhys(SysSysPAddrToCpuPAddr(pBasePAddr[0]), ui32Bytes, ui32Flags, ppvCpuVAddr, phOSMemHandle);
+#endif
+}
+
+static INLINE PVRSRV_ERROR OSUnReserveDiscontigPhys(IMG_VOID *pvCpuVAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_HANDLE hOSMemHandle)
+{
+#if defined(__linux__)
+ OSUnRegisterDiscontigMem(pvCpuVAddr, ui32Bytes, ui32Flags, hOSMemHandle);
+#endif
+
+ return PVRSRV_OK;
+}
+#else
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSReserveDiscontigPhys)
+#endif
+static INLINE PVRSRV_ERROR OSReserveDiscontigPhys(IMG_SYS_PHYADDR *pBasePAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_VOID **ppvCpuVAddr, IMG_HANDLE *phOSMemHandle)
+{
+ PVR_UNREFERENCED_PARAMETER(pBasePAddr);
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+ PVR_UNREFERENCED_PARAMETER(ui32Flags);
+ PVR_UNREFERENCED_PARAMETER(ppvCpuVAddr);
+ PVR_UNREFERENCED_PARAMETER(phOSMemHandle);
+
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSUnReserveDiscontigPhys)
+#endif
+static INLINE PVRSRV_ERROR OSUnReserveDiscontigPhys(IMG_VOID *pvCpuVAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_HANDLE hOSMemHandle)
+{
+ PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+ PVR_UNREFERENCED_PARAMETER(ui32Flags);
+ PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+#endif
+
+PVRSRV_ERROR OSRegisterMem(IMG_CPU_PHYADDR BasePAddr,
+ IMG_VOID *pvCpuVAddr,
+ IMG_SIZE_T ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE *phOSMemHandle);
+PVRSRV_ERROR OSUnRegisterMem(IMG_VOID *pvCpuVAddr,
+ IMG_SIZE_T ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hOSMemHandle);
+
+
+
+#if defined(__linux__)
+PVRSRV_ERROR OSGetSubMemHandle(IMG_HANDLE hOSMemHandle,
+ IMG_UINTPTR_T ui32ByteOffset,
+ IMG_SIZE_T ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE *phOSMemHandleRet);
+PVRSRV_ERROR OSReleaseSubMemHandle(IMG_HANDLE hOSMemHandle, IMG_UINT32 ui32Flags);
+#else
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSGetSubMemHandle)
+#endif
+static INLINE PVRSRV_ERROR OSGetSubMemHandle(IMG_HANDLE hOSMemHandle,
+ IMG_UINTPTR_T ui32ByteOffset,
+ IMG_SIZE_T ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE *phOSMemHandleRet)
+{
+ PVR_UNREFERENCED_PARAMETER(ui32ByteOffset);
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+ PVR_UNREFERENCED_PARAMETER(ui32Flags);
+
+ *phOSMemHandleRet = hOSMemHandle;
+ return PVRSRV_OK;
+}
+
+static INLINE PVRSRV_ERROR OSReleaseSubMemHandle(IMG_HANDLE hOSMemHandle, IMG_UINT32 ui32Flags)
+{
+ PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+ PVR_UNREFERENCED_PARAMETER(ui32Flags);
+ return PVRSRV_OK;
+}
+#endif
+
+IMG_UINT32 OSGetCurrentProcessIDKM(IMG_VOID);
+IMG_UINTPTR_T OSGetCurrentThreadID( IMG_VOID );
+IMG_VOID OSMemSet(IMG_VOID *pvDest, IMG_UINT8 ui8Value, IMG_SIZE_T ui32Size);
+
+PVRSRV_ERROR OSAllocPages_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_UINT32 ui32PageSize, IMG_PVOID *ppvLinAddr, IMG_HANDLE *phPageAlloc);
+PVRSRV_ERROR OSFreePages(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_PVOID pvLinAddr, IMG_HANDLE hPageAlloc);
+
+
+#ifdef PVRSRV_LOG_MEMORY_ALLOCS
+ #define OSAllocMem(flags, size, linAddr, blockAlloc, logStr) \
+ (PVR_TRACE(("OSAllocMem(" #flags ", " #size ", " #linAddr ", " #blockAlloc "): " logStr " (size = 0x%lx)", size)), \
+ OSAllocMem_Debug_Wrapper(flags, size, linAddr, blockAlloc, __FILE__, __LINE__))
+
+ #define OSAllocPages(flags, size, pageSize, linAddr, pageAlloc) \
+ (PVR_TRACE(("OSAllocPages(" #flags ", " #size ", " #pageSize ", " #linAddr ", " #pageAlloc "): (size = 0x%lx)", size)), \
+ OSAllocPages_Impl(flags, size, pageSize, linAddr, pageAlloc))
+
+ #define OSFreeMem(flags, size, linAddr, blockAlloc) \
+ (PVR_TRACE(("OSFreeMem(" #flags ", " #size ", " #linAddr ", " #blockAlloc "): (pointer = 0x%X)", linAddr)), \
+ OSFreeMem_Debug_Wrapper(flags, size, linAddr, blockAlloc, __FILE__, __LINE__))
+#else
+ #define OSAllocMem(flags, size, linAddr, blockAlloc, logString) \
+ OSAllocMem_Debug_Wrapper(flags, size, linAddr, blockAlloc, __FILE__, __LINE__)
+
+ #define OSAllocPages OSAllocPages_Impl
+
+ #define OSFreeMem(flags, size, linAddr, blockAlloc) \
+ OSFreeMem_Debug_Wrapper(flags, size, linAddr, blockAlloc, __FILE__, __LINE__)
+#endif
+
+#ifdef PVRSRV_DEBUG_OS_MEMORY
+
+ PVRSRV_ERROR OSAllocMem_Debug_Wrapper(IMG_UINT32 ui32Flags,
+ IMG_UINT32 ui32Size,
+ IMG_PVOID *ppvCpuVAddr,
+ IMG_HANDLE *phBlockAlloc,
+ IMG_CHAR *pszFilename,
+ IMG_UINT32 ui32Line);
+
+ PVRSRV_ERROR OSFreeMem_Debug_Wrapper(IMG_UINT32 ui32Flags,
+ IMG_UINT32 ui32Size,
+ IMG_PVOID pvCpuVAddr,
+ IMG_HANDLE hBlockAlloc,
+ IMG_CHAR *pszFilename,
+ IMG_UINT32 ui32Line);
+
+
+ typedef struct
+ {
+ IMG_UINT8 sGuardRegionBefore[8];
+ IMG_CHAR sFileName[128];
+ IMG_UINT32 uLineNo;
+ IMG_SIZE_T uSize;
+ IMG_SIZE_T uSizeParityCheck;
+ enum valid_tag
+ { isFree = 0x277260FF,
+ isAllocated = 0x260511AA
+ } eValid;
+ } OSMEM_DEBUG_INFO;
+
+ #define TEST_BUFFER_PADDING_STATUS (sizeof(OSMEM_DEBUG_INFO))
+ #define TEST_BUFFER_PADDING_AFTER (8)
+ #define TEST_BUFFER_PADDING (TEST_BUFFER_PADDING_STATUS + TEST_BUFFER_PADDING_AFTER)
+#else
+ #define OSAllocMem_Debug_Wrapper OSAllocMem_Debug_Linux_Memory_Allocations
+ #define OSFreeMem_Debug_Wrapper OSFreeMem_Debug_Linux_Memory_Allocations
+#endif
+
+#if defined(__linux__) && defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ PVRSRV_ERROR OSAllocMem_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_PVOID *ppvLinAddr, IMG_HANDLE *phBlockAlloc, IMG_CHAR *pszFilename, IMG_UINT32 ui32Line);
+ PVRSRV_ERROR OSFreeMem_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_PVOID pvLinAddr, IMG_HANDLE hBlockAlloc, IMG_CHAR *pszFilename, IMG_UINT32 ui32Line);
+
+ #define OSAllocMem_Debug_Linux_Memory_Allocations OSAllocMem_Impl
+ #define OSFreeMem_Debug_Linux_Memory_Allocations OSFreeMem_Impl
+#else
+ PVRSRV_ERROR OSAllocMem_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_PVOID *ppvLinAddr, IMG_HANDLE *phBlockAlloc);
+ PVRSRV_ERROR OSFreeMem_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_PVOID pvLinAddr, IMG_HANDLE hBlockAlloc);
+
+ #define OSAllocMem_Debug_Linux_Memory_Allocations(flags, size, addr, blockAlloc, file, line) \
+ OSAllocMem_Impl(flags, size, addr, blockAlloc)
+ #define OSFreeMem_Debug_Linux_Memory_Allocations(flags, size, addr, blockAlloc, file, line) \
+ OSFreeMem_Impl(flags, size, addr, blockAlloc)
+#endif
+
+
+#if defined(__linux__)
+IMG_CPU_PHYADDR OSMemHandleToCpuPAddr(IMG_VOID *hOSMemHandle, IMG_SIZE_T ui32ByteOffset);
+#else
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSMemHandleToCpuPAddr)
+#endif
+static INLINE IMG_CPU_PHYADDR OSMemHandleToCpuPAddr(IMG_HANDLE hOSMemHandle, IMG_SIZE_T ui32ByteOffset)
+{
+ IMG_CPU_PHYADDR sCpuPAddr;
+ PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+ PVR_UNREFERENCED_PARAMETER(ui32ByteOffset);
+ sCpuPAddr.uiAddr = 0;
+ return sCpuPAddr;
+}
+#endif
+PVRSRV_ERROR OSInitEnvData(IMG_PVOID *ppvEnvSpecificData);
+PVRSRV_ERROR OSDeInitEnvData(IMG_PVOID pvEnvSpecificData);
+IMG_CHAR* OSStringCopy(IMG_CHAR *pszDest, const IMG_CHAR *pszSrc);
+IMG_INT32 OSSNPrintf(IMG_CHAR *pStr, IMG_SIZE_T ui32Size, const IMG_CHAR *pszFormat, ...) IMG_FORMAT_PRINTF(3, 4);
+#define OSStringLength(pszString) strlen(pszString)
+
+PVRSRV_ERROR OSEventObjectCreate(const IMG_CHAR *pszName,
+ PVRSRV_EVENTOBJECT *psEventObject);
+PVRSRV_ERROR OSEventObjectDestroy(PVRSRV_EVENTOBJECT *psEventObject);
+PVRSRV_ERROR OSEventObjectSignal(IMG_HANDLE hOSEventKM);
+PVRSRV_ERROR OSEventObjectWait(IMG_HANDLE hOSEventKM);
+PVRSRV_ERROR OSEventObjectOpen(PVRSRV_EVENTOBJECT *psEventObject,
+ IMG_HANDLE *phOSEvent);
+PVRSRV_ERROR OSEventObjectClose(PVRSRV_EVENTOBJECT *psEventObject,
+ IMG_HANDLE hOSEventKM);
+
+
+PVRSRV_ERROR OSBaseAllocContigMemory(IMG_SIZE_T ui32Size, IMG_CPU_VIRTADDR *pLinAddr, IMG_CPU_PHYADDR *pPhysAddr);
+PVRSRV_ERROR OSBaseFreeContigMemory(IMG_SIZE_T ui32Size, IMG_CPU_VIRTADDR LinAddr, IMG_CPU_PHYADDR PhysAddr);
+
+IMG_PVOID MapUserFromKernel(IMG_PVOID pvLinAddrKM,IMG_SIZE_T ui32Size,IMG_HANDLE *phMemBlock);
+IMG_PVOID OSMapHWRegsIntoUserSpace(IMG_HANDLE hDevCookie, IMG_SYS_PHYADDR sRegAddr, IMG_UINT32 ulSize, IMG_PVOID *ppvProcess);
+IMG_VOID OSUnmapHWRegsFromUserSpace(IMG_HANDLE hDevCookie, IMG_PVOID pvUserAddr, IMG_PVOID pvProcess);
+
+IMG_VOID UnmapUserFromKernel(IMG_PVOID pvLinAddrUM, IMG_SIZE_T ui32Size, IMG_HANDLE hMemBlock);
+
+PVRSRV_ERROR OSMapPhysToUserSpace(IMG_HANDLE hDevCookie,
+ IMG_SYS_PHYADDR sCPUPhysAddr,
+ IMG_SIZE_T uiSizeInBytes,
+ IMG_UINT32 ui32CacheFlags,
+ IMG_PVOID *ppvUserAddr,
+ IMG_SIZE_T *puiActualSize,
+ IMG_HANDLE hMappingHandle);
+
+PVRSRV_ERROR OSUnmapPhysToUserSpace(IMG_HANDLE hDevCookie,
+ IMG_PVOID pvUserAddr,
+ IMG_PVOID pvProcess);
+
+PVRSRV_ERROR OSLockResource(PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID);
+PVRSRV_ERROR OSUnlockResource(PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID);
+IMG_BOOL OSIsResourceLocked(PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID);
+PVRSRV_ERROR OSCreateResource(PVRSRV_RESOURCE *psResource);
+PVRSRV_ERROR OSDestroyResource(PVRSRV_RESOURCE *psResource);
+IMG_VOID OSBreakResourceLock(PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID);
+IMG_VOID OSWaitus(IMG_UINT32 ui32Timeus);
+IMG_VOID OSSleepms(IMG_UINT32 ui32Timems);
+IMG_VOID OSReleaseThreadQuanta(IMG_VOID);
+IMG_UINT32 OSPCIReadDword(IMG_UINT32 ui32Bus, IMG_UINT32 ui32Dev, IMG_UINT32 ui32Func, IMG_UINT32 ui32Reg);
+IMG_VOID OSPCIWriteDword(IMG_UINT32 ui32Bus, IMG_UINT32 ui32Dev, IMG_UINT32 ui32Func, IMG_UINT32 ui32Reg, IMG_UINT32 ui32Value);
+
+#ifndef OSReadHWReg
+IMG_UINT32 OSReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset);
+#endif
+#ifndef OSWriteHWReg
+IMG_VOID OSWriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value);
+#endif
+
+typedef IMG_VOID (*PFN_TIMER_FUNC)(IMG_VOID*);
+IMG_HANDLE OSAddTimer(PFN_TIMER_FUNC pfnTimerFunc, IMG_VOID *pvData, IMG_UINT32 ui32MsTimeout);
+PVRSRV_ERROR OSRemoveTimer (IMG_HANDLE hTimer);
+PVRSRV_ERROR OSEnableTimer (IMG_HANDLE hTimer);
+PVRSRV_ERROR OSDisableTimer (IMG_HANDLE hTimer);
+
+PVRSRV_ERROR OSGetSysMemSize(IMG_SIZE_T *pui32Bytes);
+
+typedef enum _HOST_PCI_INIT_FLAGS_
+{
+ HOST_PCI_INIT_FLAG_BUS_MASTER = 0x00000001,
+ HOST_PCI_INIT_FLAG_MSI = 0x00000002,
+ HOST_PCI_INIT_FLAG_FORCE_I32 = 0x7fffffff
+} HOST_PCI_INIT_FLAGS;
+
+struct _PVRSRV_PCI_DEV_OPAQUE_STRUCT_;
+typedef struct _PVRSRV_PCI_DEV_OPAQUE_STRUCT_ *PVRSRV_PCI_DEV_HANDLE;
+
+PVRSRV_PCI_DEV_HANDLE OSPCIAcquireDev(IMG_UINT16 ui16VendorID, IMG_UINT16 ui16DeviceID, HOST_PCI_INIT_FLAGS eFlags);
+PVRSRV_PCI_DEV_HANDLE OSPCISetDev(IMG_VOID *pvPCICookie, HOST_PCI_INIT_FLAGS eFlags);
+PVRSRV_ERROR OSPCIReleaseDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI);
+PVRSRV_ERROR OSPCIIRQ(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 *pui32IRQ);
+IMG_UINT32 OSPCIAddrRangeLen(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index);
+IMG_UINT32 OSPCIAddrRangeStart(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index);
+IMG_UINT32 OSPCIAddrRangeEnd(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index);
+PVRSRV_ERROR OSPCIRequestAddrRange(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index);
+PVRSRV_ERROR OSPCIReleaseAddrRange(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index);
+PVRSRV_ERROR OSPCISuspendDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI);
+PVRSRV_ERROR OSPCIResumeDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI);
+
+PVRSRV_ERROR OSScheduleMISR(IMG_VOID *pvSysData);
+
+IMG_VOID OSPanic(IMG_VOID);
+
+IMG_BOOL OSProcHasPrivSrvInit(IMG_VOID);
+
+typedef enum _img_verify_test
+{
+ PVR_VERIFY_WRITE = 0,
+ PVR_VERIFY_READ
+} IMG_VERIFY_TEST;
+
+IMG_BOOL OSAccessOK(IMG_VERIFY_TEST eVerification, IMG_VOID *pvUserPtr, IMG_SIZE_T ui32Bytes);
+
+PVRSRV_ERROR OSCopyToUser(IMG_PVOID pvProcess, IMG_VOID *pvDest, IMG_VOID *pvSrc, IMG_SIZE_T ui32Bytes);
+PVRSRV_ERROR OSCopyFromUser(IMG_PVOID pvProcess, IMG_VOID *pvDest, IMG_VOID *pvSrc, IMG_SIZE_T ui32Bytes);
+
+#if defined(__linux__)
+PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID* pvCPUVAddr,
+ IMG_SIZE_T ui32Bytes,
+ IMG_SYS_PHYADDR *psSysPAddr,
+ IMG_HANDLE *phOSWrapMem);
+PVRSRV_ERROR OSReleasePhysPageAddr(IMG_HANDLE hOSWrapMem);
+#else
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSAcquirePhysPageAddr)
+#endif
+static INLINE PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID* pvCPUVAddr,
+ IMG_SIZE_T ui32Bytes,
+ IMG_SYS_PHYADDR *psSysPAddr,
+ IMG_HANDLE *phOSWrapMem)
+{
+ PVR_UNREFERENCED_PARAMETER(pvCPUVAddr);
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+ PVR_UNREFERENCED_PARAMETER(psSysPAddr);
+ PVR_UNREFERENCED_PARAMETER(phOSWrapMem);
+ return PVRSRV_OK;
+}
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSReleasePhysPageAddr)
+#endif
+static INLINE PVRSRV_ERROR OSReleasePhysPageAddr(IMG_HANDLE hOSWrapMem)
+{
+ PVR_UNREFERENCED_PARAMETER(hOSWrapMem);
+ return PVRSRV_OK;
+}
+#endif
+
+#if defined(__linux__) && defined(__KERNEL__)
+
+#define OS_SUPPORTS_IN_LISR
+
+static inline IMG_BOOL OSInLISR(IMG_VOID unref__ *pvSysData)
+{
+ PVR_UNREFERENCED_PARAMETER(pvSysData);
+ return (in_irq()) ? IMG_TRUE : IMG_FALSE;
+}
+
+static inline IMG_VOID OSWriteMemoryBarrier(IMG_VOID)
+{
+ wmb();
+}
+
+static inline IMG_VOID OSMemoryBarrier(IMG_VOID)
+{
+ mb();
+}
+
+#else
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSWriteMemoryBarrier)
+#endif
+static INLINE IMG_VOID OSWriteMemoryBarrier(IMG_VOID) { }
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSMemoryBarrier)
+#endif
+static INLINE IMG_VOID OSMemoryBarrier(IMG_VOID) { }
+
+#endif
+#ifdef PVRSRV_OS_MEM_INFO
+typedef struct
+{
+ IMG_UINT32 ui32TotalMem;
+ IMG_UINT32 ui32FreeMem;
+} PVRSRV_MEM_INFO;
+
+IMG_VOID OSGetMemoryInfo(PVRSRV_MEM_INFO * psMemInfo);
+#endif
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef __OSPERPROC_H__
+#define __OSPERPROC_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if defined(__linux__)
+PVRSRV_ERROR OSPerProcessPrivateDataInit(IMG_HANDLE *phOsPrivateData);
+PVRSRV_ERROR OSPerProcessPrivateDataDeInit(IMG_HANDLE hOsPrivateData);
+
+PVRSRV_ERROR OSPerProcessSetHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase);
+#else
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSPerProcessPrivateDataInit)
+#endif
+static INLINE PVRSRV_ERROR OSPerProcessPrivateDataInit(IMG_HANDLE *phOsPrivateData)
+{
+ PVR_UNREFERENCED_PARAMETER(phOsPrivateData);
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSPerProcessPrivateDataDeInit)
+#endif
+static INLINE PVRSRV_ERROR OSPerProcessPrivateDataDeInit(IMG_HANDLE hOsPrivateData)
+{
+ PVR_UNREFERENCED_PARAMETER(hOsPrivateData);
+
+ return PVRSRV_OK;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSPerProcessSetHandleOptions)
+#endif
+static INLINE PVRSRV_ERROR OSPerProcessSetHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase)
+{
+ PVR_UNREFERENCED_PARAMETER(psHandleBase);
+
+ return PVRSRV_OK;
+}
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
--- /dev/null
+/*
+ * Copyright (c) 2011, Intel Corporation.
+ *
+ * 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 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.
+ *
+ * Authors:
+ * Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
+ *
+ */
+
+#ifndef _OSSYNC_H_
+#define _OSSYNC_H_
+
+#include "servicesint.h"
+
+#define PVRSRV_SYNC_READ (1 << 0)
+#define PVRSRV_SYNC_WRITE (1 << 1)
+
+int PVRSRVCallbackOnSync(PVRSRV_KERNEL_SYNC_INFO *sync_info, int flags,
+ void (*callback)(void *), void *user_data);
+void PVRSRVCheckPendingSyncs(void);
+
+#endif /* _OSSYNC_H_ */
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef __PDUMP_INT_H__
+#define __PDUMP_INT_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#if !defined(_UITRON)
+#include "dbgdrvif.h"
+
+IMG_EXPORT IMG_VOID PDumpConnectionNotify(IMG_VOID);
+
+#endif
+
+typedef enum
+{
+
+ PDUMP_WRITE_MODE_CONTINUOUS = 0,
+
+ PDUMP_WRITE_MODE_LASTFRAME,
+
+ PDUMP_WRITE_MODE_BINCM,
+
+ PDUMP_WRITE_MODE_PERSISTENT
+} PDUMP_DDWMODE;
+
+
+IMG_UINT32 DbgWrite(PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32BCount, IMG_UINT32 ui32Flags);
+
+IMG_UINT32 PDumpOSDebugDriverWrite( PDBG_STREAM psStream,
+ PDUMP_DDWMODE eDbgDrvWriteMode,
+ IMG_UINT8 *pui8Data,
+ IMG_UINT32 ui32BCount,
+ IMG_UINT32 ui32Level,
+ IMG_UINT32 ui32DbgDrvFlags);
+
+#if defined (__cplusplus)
+}
+#endif
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef _PDUMP_KM_H_
+#define _PDUMP_KM_H_
+
+
+#include "pdump_osfunc.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#include "pdump.h"
+
+#define PDUMP_PD_UNIQUETAG (IMG_HANDLE)0
+#define PDUMP_PT_UNIQUETAG (IMG_HANDLE)0
+
+#define PDUMP_STREAM_PARAM2 0
+#define PDUMP_STREAM_SCRIPT2 1
+#define PDUMP_STREAM_DRIVERINFO 2
+#define PDUMP_NUM_STREAMS 3
+
+#if defined(PDUMP_DEBUG_OUTFILES)
+extern IMG_UINT32 g_ui32EveryLineCounter;
+#endif
+
+#ifndef PDUMP
+#define MAKEUNIQUETAG(hMemInfo) (0)
+#endif
+
+#ifdef PDUMP
+
+#define MAKEUNIQUETAG(hMemInfo) (((BM_BUF *)(((PVRSRV_KERNEL_MEM_INFO *)(hMemInfo))->sMemBlk.hBuffer))->pMapping)
+
+ IMG_IMPORT PVRSRV_ERROR PDumpMemPolKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask,
+ PDUMP_POLL_OPERATOR eOperator,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag);
+
+ IMG_IMPORT PVRSRV_ERROR PDumpMemUM(PVRSRV_PER_PROCESS_DATA *psProcData,
+ IMG_PVOID pvAltLinAddr,
+ IMG_PVOID pvLinAddr,
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag);
+
+ IMG_IMPORT PVRSRV_ERROR PDumpMemKM(IMG_PVOID pvAltLinAddr,
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag);
+ PVRSRV_ERROR PDumpMemPagesKM(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_DEV_PHYADDR *pPages,
+ IMG_UINT32 ui32NumPages,
+ IMG_DEV_VIRTADDR sDevAddr,
+ IMG_UINT32 ui32Start,
+ IMG_UINT32 ui32Length,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag);
+
+ PVRSRV_ERROR PDumpMemPDEntriesKM(PDUMP_MMU_ATTRIB *psMMUAttrib,
+ IMG_HANDLE hOSMemHandle,
+ IMG_CPU_VIRTADDR pvLinAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_BOOL bInitialisePages,
+ IMG_HANDLE hUniqueTag1,
+ IMG_HANDLE hUniqueTag2);
+
+ PVRSRV_ERROR PDumpMemPTEntriesKM(PDUMP_MMU_ATTRIB *psMMUAttrib,
+ IMG_HANDLE hOSMemHandle,
+ IMG_CPU_VIRTADDR pvLinAddr,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_BOOL bInitialisePages,
+ IMG_HANDLE hUniqueTag1,
+ IMG_HANDLE hUniqueTag2);
+ IMG_VOID PDumpInitCommon(IMG_VOID);
+ IMG_VOID PDumpDeInitCommon(IMG_VOID);
+ IMG_VOID PDumpInit(IMG_VOID);
+ IMG_VOID PDumpDeInit(IMG_VOID);
+ IMG_BOOL PDumpIsSuspended(IMG_VOID);
+ PVRSRV_ERROR PDumpStartInitPhaseKM(IMG_VOID);
+ PVRSRV_ERROR PDumpStopInitPhaseKM(IMG_VOID);
+ IMG_IMPORT PVRSRV_ERROR PDumpSetFrameKM(IMG_UINT32 ui32Frame);
+ IMG_IMPORT PVRSRV_ERROR PDumpCommentKM(IMG_CHAR *pszComment, IMG_UINT32 ui32Flags);
+ IMG_IMPORT PVRSRV_ERROR PDumpDriverInfoKM(IMG_CHAR *pszString, IMG_UINT32 ui32Flags);
+
+ PVRSRV_ERROR PDumpRegWithFlagsKM(IMG_CHAR *pszPDumpRegName,
+ IMG_UINT32 ui32RegAddr,
+ IMG_UINT32 ui32RegValue,
+ IMG_UINT32 ui32Flags);
+ PVRSRV_ERROR PDumpRegPolWithFlagsKM(IMG_CHAR *pszPDumpRegName,
+ IMG_UINT32 ui32RegAddr,
+ IMG_UINT32 ui32RegValue,
+ IMG_UINT32 ui32Mask,
+ IMG_UINT32 ui32Flags);
+ PVRSRV_ERROR PDumpRegPolKM(IMG_CHAR *pszPDumpRegName,
+ IMG_UINT32 ui32RegAddr,
+ IMG_UINT32 ui32RegValue,
+ IMG_UINT32 ui32Mask);
+
+ IMG_IMPORT PVRSRV_ERROR PDumpBitmapKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32FileOffset,
+ IMG_UINT32 ui32Width,
+ IMG_UINT32 ui32Height,
+ IMG_UINT32 ui32StrideInBytes,
+ IMG_DEV_VIRTADDR sDevBaseAddr,
+ IMG_HANDLE hDevMemContext,
+ IMG_UINT32 ui32Size,
+ PDUMP_PIXEL_FORMAT ePixelFormat,
+ PDUMP_MEM_FORMAT eMemFormat,
+ IMG_UINT32 ui32PDumpFlags);
+ IMG_IMPORT PVRSRV_ERROR PDumpReadRegKM(IMG_CHAR *pszPDumpRegName,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32FileOffset,
+ IMG_UINT32 ui32Address,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32PDumpFlags);
+
+ PVRSRV_ERROR PDumpRegKM(IMG_CHAR* pszPDumpRegName,
+ IMG_UINT32 dwReg,
+ IMG_UINT32 dwData);
+
+ PVRSRV_ERROR PDumpComment(IMG_CHAR* pszFormat, ...) IMG_FORMAT_PRINTF(1, 2);
+ PVRSRV_ERROR PDumpCommentWithFlags(IMG_UINT32 ui32Flags,
+ IMG_CHAR* pszFormat,
+ ...) IMG_FORMAT_PRINTF(2, 3);
+
+ PVRSRV_ERROR PDumpPDReg(PDUMP_MMU_ATTRIB *psMMUAttrib,
+ IMG_UINT32 ui32Reg,
+ IMG_UINT32 ui32dwData,
+ IMG_HANDLE hUniqueTag);
+ PVRSRV_ERROR PDumpPDRegWithFlags(PDUMP_MMU_ATTRIB *psMMUAttrib,
+ IMG_UINT32 ui32Reg,
+ IMG_UINT32 ui32Data,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag);
+
+ IMG_BOOL PDumpIsLastCaptureFrameKM(IMG_VOID);
+ IMG_IMPORT IMG_BOOL PDumpIsCaptureFrameKM(IMG_VOID);
+
+ IMG_VOID PDumpMallocPagesPhys(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_UINT32 ui32DevVAddr,
+ IMG_PUINT32 pui32PhysPages,
+ IMG_UINT32 ui32NumPages,
+ IMG_HANDLE hUniqueTag);
+ PVRSRV_ERROR PDumpSetMMUContext(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_CHAR *pszMemSpace,
+ IMG_UINT32 *pui32MMUContextID,
+ IMG_UINT32 ui32MMUType,
+ IMG_HANDLE hUniqueTag1,
+ IMG_HANDLE hOSMemHandle,
+ IMG_VOID *pvPDCPUAddr);
+ PVRSRV_ERROR PDumpClearMMUContext(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_CHAR *pszMemSpace,
+ IMG_UINT32 ui32MMUContextID,
+ IMG_UINT32 ui32MMUType);
+
+ PVRSRV_ERROR PDumpPDDevPAddrKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Offset,
+ IMG_DEV_PHYADDR sPDDevPAddr,
+ IMG_HANDLE hUniqueTag1,
+ IMG_HANDLE hUniqueTag2);
+
+ IMG_BOOL PDumpTestNextFrame(IMG_UINT32 ui32CurrentFrame);
+
+ PVRSRV_ERROR PDumpSaveMemKM (PVRSRV_DEVICE_IDENTIFIER *psDevId,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32FileOffset,
+ IMG_DEV_VIRTADDR sDevBaseAddr,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32DataMaster,
+ IMG_UINT32 ui32PDumpFlags);
+
+ PVRSRV_ERROR PDumpTASignatureRegisters(PVRSRV_DEVICE_IDENTIFIER *psDevId,
+ IMG_UINT32 ui32DumpFrameNum,
+ IMG_UINT32 ui32TAKickCount,
+ IMG_BOOL bLastFrame,
+ IMG_UINT32 *pui32Registers,
+ IMG_UINT32 ui32NumRegisters);
+
+ PVRSRV_ERROR PDump3DSignatureRegisters(PVRSRV_DEVICE_IDENTIFIER *psDevId,
+ IMG_UINT32 ui32DumpFrameNum,
+ IMG_BOOL bLastFrame,
+ IMG_UINT32 *pui32Registers,
+ IMG_UINT32 ui32NumRegisters);
+
+ PVRSRV_ERROR PDumpCounterRegisters(PVRSRV_DEVICE_IDENTIFIER *psDevId,
+ IMG_UINT32 ui32DumpFrameNum,
+ IMG_BOOL bLastFrame,
+ IMG_UINT32 *pui32Registers,
+ IMG_UINT32 ui32NumRegisters);
+
+ PVRSRV_ERROR PDumpRegRead(IMG_CHAR *pszPDumpRegName,
+ const IMG_UINT32 dwRegOffset,
+ IMG_UINT32 ui32Flags);
+
+ PVRSRV_ERROR PDumpCycleCountRegRead(PVRSRV_DEVICE_IDENTIFIER *psDevId,
+ const IMG_UINT32 dwRegOffset,
+ IMG_BOOL bLastFrame);
+
+ PVRSRV_ERROR PDumpIDLWithFlags(IMG_UINT32 ui32Clocks, IMG_UINT32 ui32Flags);
+ PVRSRV_ERROR PDumpIDL(IMG_UINT32 ui32Clocks);
+
+ PVRSRV_ERROR PDumpMallocPages(PVRSRV_DEVICE_IDENTIFIER *psDevID,
+ IMG_UINT32 ui32DevVAddr,
+ IMG_CPU_VIRTADDR pvLinAddr,
+ IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32NumBytes,
+ IMG_UINT32 ui32PageSize,
+ IMG_BOOL bShared,
+ IMG_HANDLE hUniqueTag);
+ PVRSRV_ERROR PDumpMallocPageTable(PVRSRV_DEVICE_IDENTIFIER *psDevId,
+ IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32Offset,
+ IMG_CPU_VIRTADDR pvLinAddr,
+ IMG_UINT32 ui32NumBytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag);
+ PVRSRV_ERROR PDumpFreePages(struct _BM_HEAP_ *psBMHeap,
+ IMG_DEV_VIRTADDR sDevVAddr,
+ IMG_UINT32 ui32NumBytes,
+ IMG_UINT32 ui32PageSize,
+ IMG_HANDLE hUniqueTag,
+ IMG_BOOL bInterleaved);
+ PVRSRV_ERROR PDumpFreePageTable(PVRSRV_DEVICE_IDENTIFIER *psDevID,
+ IMG_HANDLE hOSMemHandle,
+ IMG_CPU_VIRTADDR pvLinAddr,
+ IMG_UINT32 ui32NumBytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag);
+
+ IMG_IMPORT PVRSRV_ERROR PDumpHWPerfCBKM(PVRSRV_DEVICE_IDENTIFIER *psDevId,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32FileOffset,
+ IMG_DEV_VIRTADDR sDevBaseAddr,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32PDumpFlags);
+
+ PVRSRV_ERROR PDumpSignatureBuffer(PVRSRV_DEVICE_IDENTIFIER *psDevId,
+ IMG_CHAR *pszFileName,
+ IMG_CHAR *pszBufferType,
+ IMG_UINT32 ui32FileOffset,
+ IMG_DEV_VIRTADDR sDevBaseAddr,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32PDumpFlags);
+
+ PVRSRV_ERROR PDumpCBP(PPVRSRV_KERNEL_MEM_INFO psROffMemInfo,
+ IMG_UINT32 ui32ROffOffset,
+ IMG_UINT32 ui32WPosVal,
+ IMG_UINT32 ui32PacketSize,
+ IMG_UINT32 ui32BufferSize,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag);
+
+ PVRSRV_ERROR PDumpRegBasedCBP(IMG_CHAR *pszPDumpRegName,
+ IMG_UINT32 ui32RegOffset,
+ IMG_UINT32 ui32WPosVal,
+ IMG_UINT32 ui32PacketSize,
+ IMG_UINT32 ui32BufferSize,
+ IMG_UINT32 ui32Flags);
+
+ IMG_VOID PDumpVGXMemToFile(IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32FileOffset,
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 uiAddr,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32PDumpFlags,
+ IMG_HANDLE hUniqueTag);
+
+ IMG_VOID PDumpSuspendKM(IMG_VOID);
+ IMG_VOID PDumpResumeKM(IMG_VOID);
+
+
+ PVRSRV_ERROR PDumpStoreMemToFile(PDUMP_MMU_ATTRIB *psMMUAttrib,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32FileOffset,
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 uiAddr,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32PDumpFlags,
+ IMG_HANDLE hUniqueTag);
+
+ #define PDUMPMEMPOL PDumpMemPolKM
+ #define PDUMPMEM PDumpMemKM
+ #define PDUMPMEMPTENTRIES PDumpMemPTEntriesKM
+ #define PDUMPPDENTRIES PDumpMemPDEntriesKM
+ #define PDUMPMEMUM PDumpMemUM
+ #define PDUMPINIT PDumpInitCommon
+ #define PDUMPDEINIT PDumpDeInitCommon
+ #define PDUMPISLASTFRAME PDumpIsLastCaptureFrameKM
+ #define PDUMPTESTFRAME PDumpIsCaptureFrameKM
+ #define PDUMPTESTNEXTFRAME PDumpTestNextFrame
+ #define PDUMPREGWITHFLAGS PDumpRegWithFlagsKM
+ #define PDUMPREG PDumpRegKM
+ #define PDUMPCOMMENT PDumpComment
+ #define PDUMPCOMMENTWITHFLAGS PDumpCommentWithFlags
+ #define PDUMPREGPOL PDumpRegPolKM
+ #define PDUMPREGPOLWITHFLAGS PDumpRegPolWithFlagsKM
+ #define PDUMPMALLOCPAGES PDumpMallocPages
+ #define PDUMPMALLOCPAGETABLE PDumpMallocPageTable
+ #define PDUMPSETMMUCONTEXT PDumpSetMMUContext
+ #define PDUMPCLEARMMUCONTEXT PDumpClearMMUContext
+ #define PDUMPFREEPAGES PDumpFreePages
+ #define PDUMPFREEPAGETABLE PDumpFreePageTable
+ #define PDUMPPDREG PDumpPDReg
+ #define PDUMPPDREGWITHFLAGS PDumpPDRegWithFlags
+ #define PDUMPCBP PDumpCBP
+ #define PDUMPREGBASEDCBP PDumpRegBasedCBP
+ #define PDUMPMALLOCPAGESPHYS PDumpMallocPagesPhys
+ #define PDUMPENDINITPHASE PDumpStopInitPhaseKM
+ #define PDUMPBITMAPKM PDumpBitmapKM
+ #define PDUMPDRIVERINFO PDumpDriverInfoKM
+ #define PDUMPIDLWITHFLAGS PDumpIDLWithFlags
+ #define PDUMPIDL PDumpIDL
+ #define PDUMPSUSPEND PDumpSuspendKM
+ #define PDUMPRESUME PDumpResumeKM
+
+#else
+ #if ((defined(LINUX) || defined(GCC_IA32)) || defined(GCC_ARM))
+ #define PDUMPMEMPOL(args...)
+ #define PDUMPMEM(args...)
+ #define PDUMPMEMPTENTRIES(args...)
+ #define PDUMPPDENTRIES(args...)
+ #define PDUMPMEMUM(args...)
+ #define PDUMPINIT(args...)
+ #define PDUMPDEINIT(args...)
+ #define PDUMPISLASTFRAME(args...)
+ #define PDUMPTESTFRAME(args...)
+ #define PDUMPTESTNEXTFRAME(args...)
+ #define PDUMPREGWITHFLAGS(args...)
+ #define PDUMPREG(args...)
+ #define PDUMPCOMMENT(args...)
+ #define PDUMPREGPOL(args...)
+ #define PDUMPREGPOLWITHFLAGS(args...)
+ #define PDUMPMALLOCPAGES(args...)
+ #define PDUMPMALLOCPAGETABLE(args...)
+ #define PDUMPSETMMUCONTEXT(args...)
+ #define PDUMPCLEARMMUCONTEXT(args...)
+ #define PDUMPFREEPAGES(args...)
+ #define PDUMPFREEPAGETABLE(args...)
+ #define PDUMPPDREG(args...)
+ #define PDUMPPDREGWITHFLAGS(args...)
+ #define PDUMPSYNC(args...)
+ #define PDUMPCOPYTOMEM(args...)
+ #define PDUMPWRITE(args...)
+ #define PDUMPCBP(args...)
+ #define PDUMPREGBASEDCBP(args...)
+ #define PDUMPCOMMENTWITHFLAGS(args...)
+ #define PDUMPMALLOCPAGESPHYS(args...)
+ #define PDUMPENDINITPHASE(args...)
+ #define PDUMPMSVDXREG(args...)
+ #define PDUMPMSVDXREGWRITE(args...)
+ #define PDUMPMSVDXREGREAD(args...)
+ #define PDUMPMSVDXPOLEQ(args...)
+ #define PDUMPMSVDXPOL(args...)
+ #define PDUMPBITMAPKM(args...)
+ #define PDUMPDRIVERINFO(args...)
+ #define PDUMPIDLWITHFLAGS(args...)
+ #define PDUMPIDL(args...)
+ #define PDUMPSUSPEND(args...)
+ #define PDUMPRESUME(args...)
+ #define PDUMPMSVDXWRITEREF(args...)
+ #else
+ #error Compiler not specified
+ #endif
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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 <stdarg.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+#define MAX_PDUMP_STRING_LENGTH (256)
+
+
+#define PDUMP_GET_SCRIPT_STRING() \
+ IMG_HANDLE hScript; \
+ IMG_UINT32 ui32MaxLen; \
+ PVRSRV_ERROR eError; \
+ eError = PDumpOSGetScriptString(&hScript, &ui32MaxLen);\
+ if(eError != PVRSRV_OK) return eError;
+
+#define PDUMP_GET_MSG_STRING() \
+ IMG_CHAR *pszMsg; \
+ IMG_UINT32 ui32MaxLen; \
+ PVRSRV_ERROR eError; \
+ eError = PDumpOSGetMessageString(&pszMsg, &ui32MaxLen);\
+ if(eError != PVRSRV_OK) return eError;
+
+#define PDUMP_GET_FILE_STRING() \
+ IMG_CHAR *pszFileName; \
+ IMG_UINT32 ui32MaxLen; \
+ PVRSRV_ERROR eError; \
+ eError = PDumpOSGetFilenameString(&pszFileName, &ui32MaxLen);\
+ if(eError != PVRSRV_OK) return eError;
+
+#define PDUMP_GET_SCRIPT_AND_FILE_STRING() \
+ IMG_HANDLE hScript; \
+ IMG_CHAR *pszFileName; \
+ IMG_UINT32 ui32MaxLenScript; \
+ IMG_UINT32 ui32MaxLenFileName; \
+ PVRSRV_ERROR eError; \
+ eError = PDumpOSGetScriptString(&hScript, &ui32MaxLenScript);\
+ if(eError != PVRSRV_OK) return eError; \
+ eError = PDumpOSGetFilenameString(&pszFileName, &ui32MaxLenFileName);\
+ if(eError != PVRSRV_OK) return eError;
+
+
+ PVRSRV_ERROR PDumpOSGetScriptString(IMG_HANDLE *phScript, IMG_UINT32 *pui32MaxLen);
+
+
+ PVRSRV_ERROR PDumpOSGetMessageString(IMG_CHAR **ppszMsg, IMG_UINT32 *pui32MaxLen);
+
+
+ PVRSRV_ERROR PDumpOSGetFilenameString(IMG_CHAR **ppszFile, IMG_UINT32 *pui32MaxLen);
+
+
+
+
+#define PDUMP_va_list va_list
+#define PDUMP_va_start va_start
+#define PDUMP_va_end va_end
+
+
+
+IMG_HANDLE PDumpOSGetStream(IMG_UINT32 ePDumpStream);
+
+IMG_UINT32 PDumpOSGetStreamOffset(IMG_UINT32 ePDumpStream);
+
+IMG_UINT32 PDumpOSGetParamFileNum(IMG_VOID);
+
+IMG_VOID PDumpOSCheckForSplitting(IMG_HANDLE hStream, IMG_UINT32 ui32Size, IMG_UINT32 ui32Flags);
+
+IMG_BOOL PDumpOSIsSuspended(IMG_VOID);
+
+IMG_BOOL PDumpOSJTInitialised(IMG_VOID);
+
+IMG_BOOL PDumpOSWriteString(IMG_HANDLE hDbgStream,
+ IMG_UINT8 *psui8Data,
+ IMG_UINT32 ui32Size,
+ IMG_UINT32 ui32Flags);
+
+IMG_BOOL PDumpOSWriteString2(IMG_HANDLE hScript, IMG_UINT32 ui32Flags);
+
+PVRSRV_ERROR PDumpOSBufprintf(IMG_HANDLE hBuf, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, ...) IMG_FORMAT_PRINTF(3, 4);
+
+IMG_VOID PDumpOSDebugPrintf(IMG_CHAR* pszFormat, ...) IMG_FORMAT_PRINTF(1, 2);
+
+PVRSRV_ERROR PDumpOSSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR *pszFormat, ...) IMG_FORMAT_PRINTF(3, 4);
+
+PVRSRV_ERROR PDumpOSVSprintf(IMG_CHAR *pszMsg, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, PDUMP_va_list vaArgs) IMG_FORMAT_PRINTF(3, 0);
+
+IMG_UINT32 PDumpOSBuflen(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax);
+
+IMG_VOID PDumpOSVerifyLineEnding(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax);
+
+IMG_VOID PDumpOSCPUVAddrToDevPAddr(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT8 *pui8LinAddr,
+ IMG_UINT32 ui32PageSize,
+ IMG_DEV_PHYADDR *psDevPAddr);
+
+IMG_VOID PDumpOSCPUVAddrToPhysPages(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32Offset,
+ IMG_PUINT8 pui8LinAddr,
+ IMG_UINT32 ui32DataPageMask,
+ IMG_UINT32 *pui32PageOffset);
+
+IMG_VOID PDumpOSReleaseExecution(IMG_VOID);
+
+IMG_BOOL PDumpOSIsCaptureFrameKM(IMG_VOID);
+
+PVRSRV_ERROR PDumpOSSetFrameKM(IMG_UINT32 ui32Frame);
+
+#if defined (__cplusplus)
+}
+#endif
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef __PERPROC_H__
+#define __PERPROC_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#include <linux/sched.h>
+
+#include "img_types.h"
+#include "resman.h"
+
+#include "handle.h"
+
+typedef struct _PVRSRV_PER_PROCESS_DATA_
+{
+ IMG_UINT32 ui32PID;
+ char name[TASK_COMM_LEN];
+ IMG_HANDLE hBlockAlloc;
+ PRESMAN_CONTEXT hResManContext;
+ IMG_HANDLE hPerProcData;
+ PVRSRV_HANDLE_BASE *psHandleBase;
+#if defined (PVR_SECURE_HANDLES)
+
+ IMG_BOOL bHandlesBatched;
+#endif
+ IMG_UINT32 ui32RefCount;
+
+
+ IMG_BOOL bInitProcess;
+#if defined(PDUMP)
+
+ IMG_BOOL bPDumpPersistent;
+#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
+
+ IMG_BOOL bPDumpActive;
+#endif
+#endif
+
+ IMG_HANDLE hOsPrivateData;
+#if defined(PERPROC_LIST)
+ struct _PVRSRV_PER_PROCESS_DATA_ *psNext;
+ struct _PVRSRV_PER_PROCESS_DATA_ **ppsThis;
+#endif
+} PVRSRV_PER_PROCESS_DATA;
+
+PVRSRV_PER_PROCESS_DATA *PVRSRVPerProcessData(IMG_UINT32 ui32PID);
+
+PVRSRV_ERROR PVRSRVPerProcessDataConnect(IMG_UINT32 ui32PID, IMG_UINT32 ui32Flags);
+IMG_VOID PVRSRVPerProcessDataDisconnect(IMG_UINT32 ui32PID);
+
+PVRSRV_ERROR PVRSRVPerProcessDataInit(IMG_VOID);
+PVRSRV_ERROR PVRSRVPerProcessDataDeInit(IMG_VOID);
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVFindPerProcessData)
+#endif
+static INLINE
+PVRSRV_PER_PROCESS_DATA *PVRSRVFindPerProcessData(IMG_VOID)
+{
+ return PVRSRVPerProcessData(OSGetCurrentProcessIDKM());
+}
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVProcessPrivateData)
+#endif
+static INLINE
+IMG_HANDLE PVRSRVProcessPrivateData(PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ return (psPerProc != IMG_NULL) ? psPerProc->hOsPrivateData : IMG_NULL;
+}
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVPerProcessPrivateData)
+#endif
+static INLINE
+IMG_HANDLE PVRSRVPerProcessPrivateData(IMG_UINT32 ui32PID)
+{
+ return PVRSRVProcessPrivateData(PVRSRVPerProcessData(ui32PID));
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVFindPerProcessPrivateData)
+#endif
+static INLINE
+IMG_HANDLE PVRSRVFindPerProcessPrivateData(IMG_VOID)
+{
+ return PVRSRVProcessPrivateData(PVRSRVFindPerProcessData());
+}
+
+#if defined(PERPROC_LIST)
+PVRSRV_PER_PROCESS_DATA* PVRSRVPerProcessList(IMG_VOID);
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef POWER_H
+#define POWER_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+
+typedef struct _PVRSRV_POWER_DEV_TAG_
+{
+ PFN_PRE_POWER pfnPrePower;
+ PFN_POST_POWER pfnPostPower;
+ PFN_PRE_CLOCKSPEED_CHANGE pfnPreClockSpeedChange;
+ PFN_POST_CLOCKSPEED_CHANGE pfnPostClockSpeedChange;
+ IMG_HANDLE hDevCookie;
+ IMG_UINT32 ui32DeviceIndex;
+ PVRSRV_DEV_POWER_STATE eDefaultPowerState;
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState;
+ struct _PVRSRV_POWER_DEV_TAG_ *psNext;
+ struct _PVRSRV_POWER_DEV_TAG_ **ppsThis;
+
+} PVRSRV_POWER_DEV;
+
+typedef enum _PVRSRV_INIT_SERVER_STATE_
+{
+ PVRSRV_INIT_SERVER_Unspecified = -1,
+ PVRSRV_INIT_SERVER_RUNNING = 0,
+ PVRSRV_INIT_SERVER_RAN = 1,
+ PVRSRV_INIT_SERVER_SUCCESSFUL = 2,
+ PVRSRV_INIT_SERVER_NUM = 3,
+ PVRSRV_INIT_SERVER_FORCE_I32 = 0x7fffffff
+
+} PVRSRV_INIT_SERVER_STATE, *PPVRSRV_INIT_SERVER_STATE;
+
+IMG_IMPORT
+IMG_BOOL PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_STATE eInitServerState);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_STATE eInitServerState, IMG_BOOL bState);
+
+
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVPowerLock(IMG_UINT32 ui32CallerID,
+ IMG_BOOL bSystemPowerEvent);
+IMG_IMPORT
+IMG_VOID PVRSRVPowerUnlock(IMG_UINT32 ui32CallerID);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetDevicePowerStateKM(IMG_UINT32 ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ IMG_UINT32 ui32CallerID,
+ IMG_BOOL bRetainMutex);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSystemPrePowerStateKM(PVRSRV_SYS_POWER_STATE eNewPowerState);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSystemPostPowerStateKM(PVRSRV_SYS_POWER_STATE eNewPowerState);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVSetPowerStateKM (PVRSRV_SYS_POWER_STATE ePVRState);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVRegisterPowerDevice(IMG_UINT32 ui32DeviceIndex,
+ PFN_PRE_POWER pfnPrePower,
+ PFN_POST_POWER pfnPostPower,
+ PFN_PRE_CLOCKSPEED_CHANGE pfnPreClockSpeedChange,
+ PFN_POST_CLOCKSPEED_CHANGE pfnPostClockSpeedChange,
+ IMG_HANDLE hDevCookie,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState,
+ PVRSRV_DEV_POWER_STATE eDefaultPowerState);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVRemovePowerDevice (IMG_UINT32 ui32DeviceIndex);
+
+IMG_IMPORT
+IMG_BOOL PVRSRVIsDevicePowered(IMG_UINT32 ui32DeviceIndex);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVDevicePreClockSpeedChange(IMG_UINT32 ui32DeviceIndex,
+ IMG_BOOL bIdleDevice,
+ IMG_VOID *pvInfo);
+
+IMG_IMPORT
+IMG_VOID PVRSRVDevicePostClockSpeedChange(IMG_UINT32 ui32DeviceIndex,
+ IMG_BOOL bIdleDevice,
+ IMG_VOID *pvInfo);
+
+
+/*
+ * PVRSRVPowerOnSystemWithDevice
+ *
+ * Description: Power on the System if it is off, but instead of powering all
+ * of the devices to their "default" state, only turn on the specified
+ * device index.
+ */
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVPowerOnSystemWithDevice(IMG_UINT32 ui32DeviceIndex,
+ IMG_UINT32 ui32CallerID,
+ IMG_BOOL bRetainMutex);
+
+#if defined (__cplusplus)
+}
+#endif
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef QUEUE_H
+#define QUEUE_H
+
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#define UPDATE_QUEUE_ROFF(psQueue, ui32Size) \
+ (psQueue)->ui32ReadOffset = ((psQueue)->ui32ReadOffset + (ui32Size)) \
+ & ((psQueue)->ui32QueueSize - 1);
+
+ typedef struct _COMMAND_COMPLETE_DATA_
+ {
+ IMG_BOOL bInUse;
+
+ IMG_UINT32 ui32DstSyncCount;
+ IMG_UINT32 ui32SrcSyncCount;
+ PVRSRV_SYNC_OBJECT *psDstSync;
+ PVRSRV_SYNC_OBJECT *psSrcSync;
+ IMG_UINT32 ui32AllocSize;
+ }COMMAND_COMPLETE_DATA, *PCOMMAND_COMPLETE_DATA;
+
+#if !defined(USE_CODE)
+IMG_VOID QueueDumpDebugInfo(IMG_VOID);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVProcessQueues (IMG_UINT32 ui32CallerID,
+ IMG_BOOL bFlush);
+
+#if defined(__linux__) && defined(__KERNEL__)
+#include <linux/types.h>
+#include <linux/seq_file.h>
+void* ProcSeqOff2ElementQueue(struct seq_file * sfile, loff_t off);
+void ProcSeqShowQueue(struct seq_file *sfile,void* el);
+#endif
+
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateCommandQueueKM(IMG_SIZE_T ui32QueueSize,
+ PVRSRV_QUEUE_INFO **ppsQueueInfo);
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyCommandQueueKM(PVRSRV_QUEUE_INFO *psQueueInfo);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVInsertCommandKM(PVRSRV_QUEUE_INFO *psQueue,
+ PVRSRV_COMMAND **ppsCommand,
+ IMG_UINT32 ui32DevIndex,
+ IMG_UINT16 CommandType,
+ IMG_UINT32 ui32DstSyncCount,
+ PVRSRV_KERNEL_SYNC_INFO *apsDstSync[],
+ IMG_UINT32 ui32SrcSyncCount,
+ PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[],
+ IMG_SIZE_T ui32DataByteSize );
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVGetQueueSpaceKM(PVRSRV_QUEUE_INFO *psQueue,
+ IMG_SIZE_T ui32ParamSize,
+ IMG_VOID **ppvSpace);
+
+IMG_IMPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVSubmitCommandKM(PVRSRV_QUEUE_INFO *psQueue,
+ PVRSRV_COMMAND *psCommand);
+
+IMG_IMPORT
+IMG_VOID PVRSRVCommandCompleteKM(IMG_HANDLE hCmdCookie, IMG_BOOL bScheduleMISR);
+
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVRegisterCmdProcListKM(IMG_UINT32 ui32DevIndex,
+ PFN_CMD_PROC *ppfnCmdProcList,
+ IMG_UINT32 ui32MaxSyncsPerCmd[][2],
+ IMG_UINT32 ui32CmdCount);
+IMG_IMPORT
+PVRSRV_ERROR PVRSRVRemoveCmdProcListKM(IMG_UINT32 ui32DevIndex,
+ IMG_UINT32 ui32CmdCount);
+
+#endif
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef _RA_H_
+#define _RA_H_
+
+#include "img_types.h"
+#include "hash.h"
+#include "osfunc.h"
+
+typedef struct _RA_ARENA_ RA_ARENA;
+typedef struct _BM_MAPPING_ BM_MAPPING;
+
+
+
+#define RA_STATS
+
+
+struct _RA_STATISTICS_
+{
+
+ IMG_SIZE_T uSpanCount;
+
+
+ IMG_SIZE_T uLiveSegmentCount;
+
+
+ IMG_SIZE_T uFreeSegmentCount;
+
+
+ IMG_SIZE_T uTotalResourceCount;
+
+
+ IMG_SIZE_T uFreeResourceCount;
+
+
+ IMG_SIZE_T uCumulativeAllocs;
+
+
+ IMG_SIZE_T uCumulativeFrees;
+
+
+ IMG_SIZE_T uImportCount;
+
+
+ IMG_SIZE_T uExportCount;
+};
+typedef struct _RA_STATISTICS_ RA_STATISTICS;
+
+struct _RA_SEGMENT_DETAILS_
+{
+ IMG_SIZE_T uiSize;
+ IMG_CPU_PHYADDR sCpuPhyAddr;
+ IMG_HANDLE hSegment;
+};
+typedef struct _RA_SEGMENT_DETAILS_ RA_SEGMENT_DETAILS;
+
+RA_ARENA *
+RA_Create (IMG_CHAR *name,
+ IMG_UINTPTR_T base,
+ IMG_SIZE_T uSize,
+ BM_MAPPING *psMapping,
+ IMG_SIZE_T uQuantum,
+ IMG_BOOL (*imp_alloc)(IMG_VOID *_h,
+ IMG_SIZE_T uSize,
+ IMG_SIZE_T *pActualSize,
+ BM_MAPPING **ppsMapping,
+ IMG_UINT32 uFlags,
+ IMG_UINTPTR_T *pBase),
+ IMG_VOID (*imp_free) (IMG_VOID *,
+ IMG_UINTPTR_T,
+ BM_MAPPING *),
+ IMG_VOID (*backingstore_free) (IMG_VOID *,
+ IMG_SIZE_T,
+ IMG_SIZE_T,
+ IMG_HANDLE),
+ IMG_VOID *import_handle);
+
+IMG_VOID
+RA_Delete (RA_ARENA *pArena);
+
+IMG_BOOL
+RA_TestDelete (RA_ARENA *pArena);
+
+IMG_BOOL
+RA_Add (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize);
+
+IMG_BOOL
+RA_Alloc (RA_ARENA *pArena,
+ IMG_SIZE_T uSize,
+ IMG_SIZE_T *pActualSize,
+ BM_MAPPING **ppsMapping,
+ IMG_UINT32 uFlags,
+ IMG_UINT32 uAlignment,
+ IMG_UINT32 uAlignmentOffset,
+ IMG_UINTPTR_T *pBase);
+
+IMG_VOID
+RA_Free (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_BOOL bFreeBackingStore);
+
+
+#ifdef RA_STATS
+
+#define CHECK_SPACE(total) \
+{ \
+ if((total)<100) \
+ return PVRSRV_ERROR_INVALID_PARAMS; \
+}
+
+#define UPDATE_SPACE(str, count, total) \
+{ \
+ if((count) == -1) \
+ return PVRSRV_ERROR_INVALID_PARAMS; \
+ else \
+ { \
+ (str) += (count); \
+ (total) -= (count); \
+ } \
+}
+
+
+IMG_BOOL RA_GetNextLiveSegment(IMG_HANDLE hArena, RA_SEGMENT_DETAILS *psSegDetails);
+
+
+PVRSRV_ERROR RA_GetStats(RA_ARENA *pArena,
+ IMG_CHAR **ppszStr,
+ IMG_UINT32 *pui32StrLen);
+
+PVRSRV_ERROR RA_GetStatsFreeMem(RA_ARENA *pArena,
+ IMG_CHAR **ppszStr,
+ IMG_UINT32 *pui32StrLen);
+
+#endif
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef __RESMAN_H__
+#define __RESMAN_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#ifdef RES_MAN_EXTEND
+#include <stdarg.h>
+#endif
+#include "servicesext.h"
+
+enum {
+
+ RESMAN_TYPE_SHARED_PB_DESC = 1,
+ RESMAN_TYPE_SHARED_PB_DESC_CREATE_LOCK,
+ RESMAN_TYPE_HW_RENDER_CONTEXT,
+ RESMAN_TYPE_HW_TRANSFER_CONTEXT,
+ RESMAN_TYPE_HW_2D_CONTEXT,
+ RESMAN_TYPE_TRANSFER_CONTEXT,
+
+
+
+
+
+ RESMAN_TYPE_DISPLAYCLASS_SWAPCHAIN_REF,
+ RESMAN_TYPE_DISPLAYCLASS_DEVICE,
+
+
+ RESMAN_TYPE_BUFFERCLASS_DEVICE,
+
+
+ RESMAN_TYPE_OS_USERMODE_MAPPING,
+
+
+ RESMAN_TYPE_DEVICEMEM_CONTEXT,
+ RESMAN_TYPE_DEVICECLASSMEM_MAPPING,
+ RESMAN_TYPE_DEVICEMEM_MAPPING,
+ RESMAN_TYPE_DEVICEMEM_WRAP,
+ RESMAN_TYPE_DEVICEMEM_ALLOCATION,
+ RESMAN_TYPE_EVENT_OBJECT,
+ RESMAN_TYPE_SHARED_MEM_INFO,
+ RESMAN_TYPE_MODIFY_SYNC_OPS,
+ RESMAN_TYPE_SYNC_INFO,
+
+
+ RESMAN_TYPE_KERNEL_DEVICEMEM_ALLOCATION
+};
+
+#define RESMAN_CRITERIA_ALL 0x00000000
+#define RESMAN_CRITERIA_RESTYPE 0x00000001
+#define RESMAN_CRITERIA_PVOID_PARAM 0x00000002
+#define RESMAN_CRITERIA_UI32_PARAM 0x00000004
+
+typedef PVRSRV_ERROR (*RESMAN_FREE_FN)(IMG_PVOID pvParam, IMG_UINT32 ui32Param);
+
+typedef struct _RESMAN_ITEM_ *PRESMAN_ITEM;
+typedef struct _RESMAN_CONTEXT_ *PRESMAN_CONTEXT;
+
+PVRSRV_ERROR ResManInit(IMG_VOID);
+IMG_VOID ResManDeInit(IMG_VOID);
+
+PRESMAN_ITEM ResManRegisterRes(PRESMAN_CONTEXT hResManContext,
+ IMG_UINT32 ui32ResType,
+ IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param,
+ RESMAN_FREE_FN pfnFreeResource);
+
+PVRSRV_ERROR ResManFreeResByPtr(PRESMAN_ITEM psResItem);
+
+PVRSRV_ERROR ResManFreeResByCriteria(PRESMAN_CONTEXT hResManContext,
+ IMG_UINT32 ui32SearchCriteria,
+ IMG_UINT32 ui32ResType,
+ IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param);
+
+PVRSRV_ERROR ResManDissociateRes(PRESMAN_ITEM psResItem,
+ PRESMAN_CONTEXT psNewResManContext);
+
+PVRSRV_ERROR ResManFindResourceByPtr(PRESMAN_CONTEXT hResManContext,
+ PRESMAN_ITEM psItem);
+
+PVRSRV_ERROR PVRSRVResManConnect(IMG_HANDLE hPerProc,
+ PRESMAN_CONTEXT *phResManContext);
+IMG_VOID PVRSRVResManDisconnect(PRESMAN_CONTEXT hResManContext,
+ IMG_BOOL bKernelContext);
+#ifdef RES_MAN_EXTEND
+PVRSRV_ERROR PVRSRVResManAnyByCriteria(PRESMAN_CONTEXT psResManContext,
+ IMG_UINT32 ui32SearchCriteria,
+ IMG_UINT32 ui32ResType,
+ IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param,
+ PVRSRV_ERROR(*pfnCallBack)(PRESMAN_ITEM psRes, va_list va), ...);
+IMG_PVOID PVRSRVGetResData(PRESMAN_ITEM psResItem);
+#endif
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef SERVICES_HEADERS_H
+#define SERVICES_HEADERS_H
+
+#ifdef DEBUG_RELEASE_BUILD
+#pragma optimize( "", off )
+#define DEBUG 1
+#endif
+
+#include "img_defs.h"
+#include "services.h"
+#include "servicesint.h"
+#include "power.h"
+#include "resman.h"
+#include "queue.h"
+#include "srvkm.h"
+#include "kerneldisplay.h"
+#include "syscommon.h"
+#include "pvr_debug.h"
+#include "metrics.h"
+#include "osfunc.h"
+#include "ossync.h"
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef SRVKM_H
+#define SRVKM_H
+
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+ #ifdef PVR_DISABLE_LOGGING
+ #define PVR_LOG(X)
+ #else
+
+ #define PVR_LOG(X) PVRSRVReleasePrintf X;
+ #endif
+
+ IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVReleasePrintf(const IMG_CHAR *pszFormat, ...) IMG_FORMAT_PRINTF(1, 2);
+
+ IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVProcessConnect(IMG_UINT32 ui32PID, IMG_UINT32 ui32Flags);
+ IMG_IMPORT IMG_VOID IMG_CALLCONV PVRSRVProcessDisconnect(IMG_UINT32 ui32PID);
+
+ IMG_IMPORT IMG_VOID PVRSRVScheduleDevicesKM(IMG_VOID);
+
+ IMG_VOID IMG_CALLCONV PVRSRVSetDCState(IMG_UINT32 ui32State);
+
+ PVRSRV_ERROR IMG_CALLCONV PVRSRVSaveRestoreLiveSegments(IMG_HANDLE hArena, IMG_PBYTE pbyBuffer, IMG_SIZE_T *puiBufSize, IMG_BOOL bSave);
+
+ IMG_VOID PVRSRVScheduleDeviceCallbacks(IMG_VOID);
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+
+#define LOOP_UNTIL_TIMEOUT(TIMEOUT) \
+{\
+ IMG_UINT32 uiOffset, uiStart, uiCurrent; \
+ IMG_INT32 iNotLastLoop; \
+ for(uiOffset = 0, uiStart = OSClockus(), uiCurrent = uiStart + 1, iNotLastLoop = 1;\
+ ((uiCurrent - uiStart + uiOffset) < (TIMEOUT)) || iNotLastLoop--; \
+ uiCurrent = OSClockus(), \
+ uiOffset = uiCurrent < uiStart ? IMG_UINT32_MAX - uiStart : uiOffset, \
+ uiStart = uiCurrent < uiStart ? 0 : uiStart)
+
+#define END_LOOP_UNTIL_TIMEOUT() \
+}
+
+IMG_IMPORT
+const IMG_CHAR *PVRSRVGetErrorStringKM(PVRSRV_ERROR eError);
+
+#endif
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef _SYSCOMMON_H
+#define _SYSCOMMON_H
+
+#include "sysconfig.h"
+#include "sysinfo.h"
+#include "servicesint.h"
+#include "queue.h"
+#include "power.h"
+#include "resman.h"
+#include "ra.h"
+#include "device.h"
+#include "buffer_manager.h"
+#include "pvr_debug.h"
+#include "services.h"
+
+#if defined(NO_HARDWARE) && defined(__linux__) && defined(__KERNEL__)
+#include <asm/io.h>
+#endif
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+typedef struct _SYS_DEVICE_ID_TAG
+{
+ IMG_UINT32 uiID;
+ IMG_BOOL bInUse;
+
+} SYS_DEVICE_ID;
+
+
+#define SYS_MAX_LOCAL_DEVMEM_ARENAS 4
+
+typedef struct _SYS_DATA_TAG_
+{
+ IMG_UINT32 ui32NumDevices;
+ SYS_DEVICE_ID sDeviceID[SYS_DEVICE_COUNT];
+ PVRSRV_DEVICE_NODE *psDeviceNodeList;
+ PVRSRV_POWER_DEV *psPowerDeviceList;
+ PVRSRV_RESOURCE sPowerStateChangeResource;
+ PVRSRV_SYS_POWER_STATE eCurrentPowerState;
+ PVRSRV_SYS_POWER_STATE eFailedPowerState;
+ IMG_UINT32 ui32CurrentOSPowerState;
+ PVRSRV_QUEUE_INFO *psQueueList;
+ PVRSRV_KERNEL_SYNC_INFO *psSharedSyncInfoList;
+ IMG_PVOID pvEnvSpecificData;
+ IMG_PVOID pvSysSpecificData;
+ PVRSRV_RESOURCE sQProcessResource;
+ IMG_VOID *pvSOCRegsBase;
+ IMG_HANDLE hSOCTimerRegisterOSMemHandle;
+ IMG_UINT32 *pvSOCTimerRegisterKM;
+ IMG_VOID *pvSOCClockGateRegsBase;
+ IMG_UINT32 ui32SOCClockGateRegsSize;
+
+ struct _DEVICE_COMMAND_DATA_ *apsDeviceCommandData[SYS_DEVICE_COUNT];
+
+
+ IMG_BOOL bReProcessQueues;
+
+ RA_ARENA *apsLocalDevMemArena[SYS_MAX_LOCAL_DEVMEM_ARENAS];
+
+ IMG_CHAR *pszVersionString;
+ PVRSRV_EVENTOBJECT *psGlobalEventObject;
+
+ PVRSRV_MISC_INFO_CPUCACHEOP_TYPE ePendingCacheOpType;
+} SYS_DATA;
+
+
+
+PVRSRV_ERROR SysInitialise(IMG_VOID);
+PVRSRV_ERROR SysFinalise(IMG_VOID);
+
+PVRSRV_ERROR SysDeinitialise(SYS_DATA *psSysData);
+PVRSRV_ERROR SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_VOID **ppvDeviceMap);
+
+IMG_VOID SysRegisterExternalDevice(PVRSRV_DEVICE_NODE *psDeviceNode);
+IMG_VOID SysRemoveExternalDevice(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+IMG_UINT32 SysGetInterruptSource(SYS_DATA *psSysData,
+ PVRSRV_DEVICE_NODE *psDeviceNode);
+
+IMG_VOID SysClearInterrupts(SYS_DATA* psSysData, IMG_UINT32 ui32ClearBits);
+
+PVRSRV_ERROR SysResetDevice(IMG_UINT32 ui32DeviceIndex);
+
+PVRSRV_ERROR SysSystemPrePowerState(PVRSRV_SYS_POWER_STATE eNewPowerState);
+PVRSRV_ERROR SysSystemPostPowerState(PVRSRV_SYS_POWER_STATE eNewPowerState);
+PVRSRV_ERROR SysDevicePrePowerState(IMG_UINT32 ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+PVRSRV_ERROR SysDevicePostPowerState(IMG_UINT32 ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+
+#if defined(SYS_CUSTOM_POWERLOCK_WRAP)
+PVRSRV_ERROR SysPowerLockWrap(SYS_DATA *psSysData);
+IMG_VOID SysPowerLockUnwrap(SYS_DATA *psSysData);
+#endif
+
+PVRSRV_ERROR SysOEMFunction ( IMG_UINT32 ui32ID,
+ IMG_VOID *pvIn,
+ IMG_UINT32 ulInSize,
+ IMG_VOID *pvOut,
+ IMG_UINT32 ulOutSize);
+
+
+IMG_DEV_PHYADDR SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE eDeviceType, IMG_CPU_PHYADDR cpu_paddr);
+IMG_DEV_PHYADDR SysSysPAddrToDevPAddr (PVRSRV_DEVICE_TYPE eDeviceType, IMG_SYS_PHYADDR SysPAddr);
+IMG_SYS_PHYADDR SysDevPAddrToSysPAddr (PVRSRV_DEVICE_TYPE eDeviceType, IMG_DEV_PHYADDR SysPAddr);
+IMG_CPU_PHYADDR SysSysPAddrToCpuPAddr (IMG_SYS_PHYADDR SysPAddr);
+IMG_SYS_PHYADDR SysCpuPAddrToSysPAddr (IMG_CPU_PHYADDR cpu_paddr);
+#if defined(PVR_LMA)
+IMG_BOOL SysVerifyCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE eDeviceType, IMG_CPU_PHYADDR CpuPAddr);
+IMG_BOOL SysVerifySysPAddrToDevPAddr (PVRSRV_DEVICE_TYPE eDeviceType, IMG_SYS_PHYADDR SysPAddr);
+#endif
+
+extern SYS_DATA* gpsSysData;
+
+#if !defined(USE_CODE)
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SysAcquireData)
+#endif
+static INLINE IMG_VOID SysAcquireData(SYS_DATA **ppsSysData)
+{
+
+ *ppsSysData = gpsSysData;
+
+
+
+
+
+ PVR_ASSERT (gpsSysData != IMG_NULL);
+}
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SysAcquireDataNoCheck)
+#endif
+static INLINE SYS_DATA * SysAcquireDataNoCheck(IMG_VOID)
+{
+
+ return gpsSysData;
+}
+
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SysInitialiseCommon)
+#endif
+static INLINE PVRSRV_ERROR SysInitialiseCommon(SYS_DATA *psSysData)
+{
+ PVRSRV_ERROR eError;
+
+
+ eError = PVRSRVInit(psSysData);
+
+ return eError;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SysDeinitialiseCommon)
+#endif
+static INLINE IMG_VOID SysDeinitialiseCommon(SYS_DATA *psSysData)
+{
+
+ PVRSRVDeInit(psSysData);
+
+ OSDestroyResource(&psSysData->sPowerStateChangeResource);
+}
+#endif
+
+
+#if !(defined(NO_HARDWARE) && defined(__linux__) && defined(__KERNEL__))
+#define SysReadHWReg(p, o) OSReadHWReg(p, o)
+#define SysWriteHWReg(p, o, v) OSWriteHWReg(p, o, v)
+#else
+static inline IMG_UINT32 SysReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset)
+{
+ return (IMG_UINT32) readl(pvLinRegBaseAddr + ui32Offset);
+}
+
+static inline IMG_VOID SysWriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value)
+{
+ writel(ui32Value, pvLinRegBaseAddr + ui32Offset);
+}
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
+
--- /dev/null
+#include "sgxdefs.h"
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+/*
+ byte offsets to ext cache control registers from the
+ base of the external register bank
+ - TO BE SPECIFIED IN SYSTEM PORT!
+*/
+/* global invalidate */
+/* This address must be the physical address of the cache controller rounded
+ down to the nearest page*/
+#define SYS_EXT_SYS_CACHE_GBL_INV_REG_OFFSET 0x80000000
+
+
+/* per address invalidate (data written in the address) */
+/* This is the offset within the page to the cache controller which we want
+ to write */
+#define SYS_EXT_SYS_CACHE_ADDR_INV_REG_OFFSET 0x0
+
+/*
+ FIXME: these two defines should really live in sgxconfig.h as a heap define
+ not possible right now due to .h include issues
+*/
+
+/* This address must not live within the same virtal address as
+ any of the heaps, but must be within a shared heap */
+
+#if SGX_FEATURE_ADDRESS_SPACE_SIZE == 32
+#define SGX_EXT_SYSTEM_CACHE_REGS_DEVVADDR_BASE (0xF8FFE000)
+#endif
+
+#if SGX_FEATURE_ADDRESS_SPACE_SIZE == 28
+#define SGX_EXT_SYSTEM_CACHE_REGS_DEVVADDR_BASE (0x0F3FE000)
+#endif
+
+/* assume 4k is enough range to cover all control registers */
+#define SGX_EXT_SYSTEM_CACHE_REGS_SIZE 0x00001000
+
+#define INVALIDATE_EXT_SYSTEM_CACHE_INLINE(RegA) \
+ mov RegA, HSH(SGX_EXT_SYSTEM_CACHE_REGS_DEVVADDR_BASE); \
+ stad.bpcache [RegA, HSH(SYS_EXT_SYS_CACHE_ADDR_INV_REG_OFFSET>>2)], HSH(0); \
+ idf drc0, st; \
+ wdf drc0;
+#endif /* SUPPORT_EXTERNAL_SYSTEM_CACHE */
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#if !defined(__OEMFUNCS_H__)
+#define __OEMFUNCS_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define OEM_EXCHANGE_POWER_STATE (1<<0)
+#define OEM_DEVICE_MEMORY_POWER (1<<1)
+#define OEM_DISPLAY_POWER (1<<2)
+#define OEM_GET_EXT_FUNCS (1<<3)
+
+typedef struct OEM_ACCESS_INFO_TAG
+{
+ IMG_UINT32 ui32Size;
+ IMG_UINT32 ui32FBPhysBaseAddress;
+ IMG_UINT32 ui32FBMemAvailable;
+ IMG_UINT32 ui32SysPhysBaseAddress;
+ IMG_UINT32 ui32SysSize;
+ IMG_UINT32 ui32DevIRQ;
+} OEM_ACCESS_INFO, *POEM_ACCESS_INFO;
+
+typedef IMG_UINT32 (*PFN_SRV_BRIDGEDISPATCH)( IMG_UINT32 Ioctl,
+ IMG_BYTE *pInBuf,
+ IMG_UINT32 InBufLen,
+ IMG_BYTE *pOutBuf,
+ IMG_UINT32 OutBufLen,
+ IMG_UINT32 *pdwBytesTransferred);
+
+
+typedef PVRSRV_ERROR (*PFN_SRV_READREGSTRING)(PPVRSRV_REGISTRY_INFO psRegInfo);
+
+
+typedef struct PVRSRV_DC_OEM_JTABLE_TAG
+{
+ PFN_SRV_BRIDGEDISPATCH pfnOEMBridgeDispatch;
+ PFN_SRV_READREGSTRING pfnOEMReadRegistryString;
+ PFN_SRV_READREGSTRING pfnOEMWriteRegistryString;
+
+} PVRSRV_DC_OEM_JTABLE;
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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 <drm/drmP.h>
+#include <drm/drm.h>
+
+#include "pvr_drm_shared.h"
+
+#include "services_headers.h"
+#include "private_data.h"
+#include "pvr_drm.h"
+
+#include "pvr_bridge.h"
+#include "mutex.h"
+#include "lock.h"
+#include "linkage.h"
+#include "mmap.h"
+
+#if defined(PDUMP)
+#include "client/linuxsrv.h"
+#endif
+
+#include "sys_pvr_drm_import.h"
+
+#include "sys_pvr_drm_export.h"
+
+int
+SYSPVRInit(void)
+{
+ PVRDPFInit();
+
+ return 0;
+}
+
+int
+SYSPVRLoad(struct drm_device *dev, unsigned long flags)
+{
+ return PVRSRVDrmLoad(dev, flags);
+}
+
+int
+SYSPVROpen(struct drm_device *dev, struct drm_file *pFile)
+{
+ return PVRSRVDrmOpen(dev, pFile);
+}
+
+int
+SYSPVRUnload(struct drm_device *dev)
+{
+ return PVRSRVDrmUnload(dev);
+}
+
+void
+SYSPVRPostClose(struct drm_device *dev, struct drm_file *file)
+{
+ return PVRSRVDrmPostClose(dev, file);
+}
+
+int
+SYSPVRBridgeDispatch(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile)
+{
+ return PVRSRV_BridgeDispatchKM(dev, arg, pFile);
+}
+
+int
+SYSPVRDCDriverIoctl(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile)
+{
+ return PVRDRM_Dummy_ioctl(dev, arg, pFile);
+
+}
+
+int
+SYSPVRBCDriverIoctl(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile)
+{
+ return PVRDRM_Dummy_ioctl(dev, arg, pFile);
+
+}
+
+int
+SYSPVRIsMaster(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile)
+{
+ return PVRDRMIsMaster(dev, arg, pFile);
+}
+
+int
+SYSPVRUnprivCmd(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile)
+{
+ return PVRDRMUnprivCmd(dev, arg, pFile);
+}
+
+int
+SYSPVRMMap(struct file* pFile, struct vm_area_struct* ps_vma)
+{
+ int ret;
+
+ ret = PVRMMap(pFile, ps_vma);
+ if (ret == -ENOENT)
+ {
+ ret = drm_mmap(pFile, ps_vma);
+ }
+
+ return ret;
+}
+
+int
+SYSPVRDBGDrivIoctl(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile)
+{
+#if defined(PDUMP)
+ return dbgdrv_ioctl(dev, arg, pFile);
+#else
+ PVR_UNREFERENCED_PARAMETER(dev);
+ PVR_UNREFERENCED_PARAMETER(arg);
+ PVR_UNREFERENCED_PARAMETER(pFile);
+
+ return -EINVAL;
+#endif
+}
+
+void
+SYSPVRSuspendLock(struct drm_device *dev)
+{
+ PVR_UNREFERENCED_PARAMETER(dev);
+
+ LinuxLockMutex(&gPVRSRVLock);
+}
+
+void
+SYSPVRSuspendUnlock(struct drm_device *dev)
+{
+ PVR_UNREFERENCED_PARAMETER(dev);
+
+ LinuxUnLockMutex(&gPVRSRVLock);
+}
+
+int
+SYSPVRPreSuspend(struct drm_device *dev)
+{
+ if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D3) != PVRSRV_OK)
+ {
+ return -EBUSY;
+ }
+
+#if defined(DISPLAY_CONTROLLER)
+ if (PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Suspend)(dev) != 0)
+ {
+ (void)PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D0);
+ return -EBUSY;
+ }
+#else
+ PVR_UNREFERENCED_PARAMETER(dev);
+#endif
+
+ return 0;
+}
+
+int
+SYSPVRPostSuspend(struct drm_device *dev)
+{
+ if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D0) != PVRSRV_OK)
+ {
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+int
+SYSPVRResume(struct drm_device *dev)
+{
+#if defined(DISPLAY_CONTROLLER)
+ if (PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Resume)(dev) != 0)
+ {
+ return -EINVAL;
+ }
+#else
+ PVR_UNREFERENCED_PARAMETER(dev);
+#endif
+ return 0;
+}
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#if !defined(__SYS_PVR_DRM_EXPORT_H__)
+#define __SYS_PVR_DRM_EXPORT_H__
+
+#include "pvr_drm_shared.h"
+
+#if defined(__KERNEL__)
+
+#include "services_headers.h"
+#include "private_data.h"
+#include "pvr_drm.h"
+
+#include "pvr_bridge.h"
+
+#if defined(PDUMP)
+#include "client/linuxsrv.h"
+#endif
+
+#define PVR_DRM_SRVKM_IOCTL \
+ DRM_IOW(DRM_COMMAND_BASE + PVR_DRM_SRVKM_CMD, PVRSRV_BRIDGE_PACKAGE)
+
+#define PVR_DRM_DISP_IOCTL \
+ DRM_IO(DRM_COMMAND_BASE + PVR_DRM_DISP_CMD)
+
+#define PVR_DRM_BC_IOCTL \
+ DRM_IO(DRM_COMMAND_BASE + PVR_DRM_BC_CMD)
+
+#define PVR_DRM_IS_MASTER_IOCTL \
+ DRM_IO(DRM_COMMAND_BASE + PVR_DRM_IS_MASTER_CMD)
+
+#define PVR_DRM_UNPRIV_IOCTL \
+ DRM_IOWR(DRM_COMMAND_BASE + PVR_DRM_UNPRIV_CMD, IMG_UINT32)
+
+#if defined(PDUMP)
+#define PVR_DRM_DBGDRV_IOCTL \
+ DRM_IOW(DRM_COMMAND_BASE + PVR_DRM_DBGDRV_CMD, IOCTL_PACKAGE)
+#else
+#define PVR_DRM_DBGDRV_IOCTL \
+ DRM_IO(DRM_COMMAND_BASE + PVR_DRM_DBGDRV_CMD)
+#endif
+
+int SYSPVRInit(void);
+int SYSPVRLoad(struct drm_device *dev, unsigned long flags);
+int SYSPVROpen(struct drm_device *dev, struct drm_file *pFile);
+int SYSPVRUnload(struct drm_device *dev);
+void SYSPVRPostClose(struct drm_device *dev, struct drm_file *file);
+int SYSPVRBridgeDispatch(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+int SYSPVRDCDriverIoctl(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+int SYSPVRBCDriverIoctl(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+int SYSPVRIsMaster(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+int SYSPVRUnprivCmd(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+
+int SYSPVRMMap(struct file* pFile, struct vm_area_struct* ps_vma);
+
+int SYSPVRDBGDrivIoctl(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
+
+int SYSPVRServiceSGXInterrupt(struct drm_device *dev);
+
+void SYSPVRSuspendLock(struct drm_device *dev);
+void SYSPVRSuspendUnlock(struct drm_device *dev);
+int SYSPVRPreSuspend(struct drm_device *dev);
+int SYSPVRPostSuspend(struct drm_device *dev);
+int SYSPVRResume(struct drm_device *dev);
+
+int BC_Video_ModInit(void);
+int BC_Video_ModCleanup(void);
+int BC_Video_Bridge(struct drm_device *dev, IMG_VOID *arg, struct drm_file *file_priv);
+
+#endif
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#if !defined(__SYS_PVR_DRM_IMPORT_H__)
+#define __SYS_PVR_DRM_IMPORT_H__
+
+#if defined(__KERNEL__)
+#include "psb_drm.h"
+#endif
+
+#define DRM_PSB_PLACEMENT_OFFSET 0x13
+
+#if 0
+#define DRM_PVR_RESERVED1 0x0D
+#define DRM_PVR_RESERVED2 0x0E
+#define DRM_PVR_RESERVED3 0x0F
+#define DRM_PVR_RESERVED4 0x10
+#define DRM_PVR_RESERVED5 0x11
+#define DRM_PVR_RESERVED6 0x12
+#endif
+
+
+#endif
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#if defined(LDM_PCI) || defined(SUPPORT_DRI_DRM)
+#include "linux/pci.h"
+#endif
+
+#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 "mdfld_gl3.h"
+#if defined(SUPPORT_DRI_DRM_EXT)
+#include "env_data.h"
+#include "psb_drv.h"
+#include "psb_powermgmt.h"
+#include "sys_pvr_drm_export.h"
+#include "msvdx_power.h"
+#include "topaz_power.h"
+#endif
+
+
+/* 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)
+
+#if defined(SUPPORT_DRI_DRM_EXT)
+#define DRI_DRM_STATIC
+#else
+#define DRI_DRM_STATIC static
+#endif
+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;
+
+#if defined(SUPPORT_DRI_DRM_EXT)
+static PVRSRV_DEVICE_NODE *gpsSGXDevNode;
+#endif
+
+#if !defined(NO_HARDWARE)
+IMG_CPU_VIRTADDR gsPoulsboRegsCPUVaddr;
+
+IMG_CPU_VIRTADDR gsPoulsboDisplayRegsCPUVaddr;
+#endif
+
+#if defined(LDM_PCI) || defined(SUPPORT_DRI_DRM)
+extern struct pci_dev *gpsPVRLDMDev;
+#endif
+
+#if !defined(SUPPORT_DRI_DRM_EXT)
+IMG_UINT32 PVRSRV_BridgeDispatchKM( IMG_UINT32 Ioctl,
+ IMG_BYTE *pInBuf,
+ IMG_UINT32 InBufLen,
+ IMG_BYTE *pOutBuf,
+ IMG_UINT32 OutBufLen,
+ IMG_UINT32 *pdwBytesTransferred);
+#endif
+
+#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 defined(SUPPORT_DRI_DRM_EXT)
+ psSysSpecData->hSGXPCI = OSPCISetDev((IMG_VOID *)psSysSpecData->psPCIDev, 0);
+ ui32MaxOffset = POULSBO_MAX_OFFSET;
+
+#else
+#if defined(LDM_PCI) || defined(SUPPORT_DRI_DRM)
+ psSysSpecData->hSGXPCI = OSPCISetDev((IMG_VOID *)psSysSpecData->psPCIDev, HOST_PCI_INIT_FLAG_BUS_MASTER | HOST_PCI_INIT_FLAG_MSI);
+#else
+ psSysSpecData->hSGXPCI = OSPCIAcquireDev(SYS_SGX_DEV_VENDOR_ID, SYS_SGX_DEV_DEVICE_ID, HOST_PCI_INIT_FLAG_BUS_MASTER | HOST_PCI_INIT_FLAG_MSI);
+#endif
+#endif
+ 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;
+
+
+#if defined(SUPPORT_DRI_DRM_EXT)
+ gsSGXDeviceMap.sRegsSysPBase.uiAddr = ui32BaseAddr + SGX_REGS_OFFSET;
+#else
+ gsSGXDeviceMap.sRegsSysPBase.uiAddr = ui32BaseAddr + SGX_REGS_OFFSET;
+#endif
+ 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);
+ gsSGXDeviceMap.ui32HPSize = 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;
+
+#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+ gsSGXDeviceMap.sExtSysCacheRegsDevPBase.uiAddr = SYS_EXT_SYS_CACHE_GBL_INV_REG_OFFSET;
+ gsSGXDeviceMap.ui32ExtSysCacheRegsSize = SGX_EXT_SYSTEM_CACHE_REGS_SIZE;
+
+ MDFLD_GL3_WRITE(gsSGXDeviceMap.sExtSysCacheRegsDevPBase.uiAddr, MDFLD_GL3_USE_WRT_INVAL);
+#endif
+
+
+#if !defined(NO_HARDWARE)
+
+ {
+ 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);
+ }
+#endif
+#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;
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) gpDrmDevice->dev_private;
+
+ gpsSysData = &gsSysData;
+ OSMemSet(gpsSysData, 0, sizeof(SYS_DATA));
+
+ gpsSysData->pvSysSpecificData = &gsSysSpecificData;
+ gsSysSpecificData.ui32SysSpecificData = 0;
+#if defined(LDM_PCI) || defined(SUPPORT_DRI_DRM)
+
+ PVR_ASSERT(gpsPVRLDMDev != IMG_NULL);
+ gsSysSpecificData.psPCIDev = gpsPVRLDMDev;
+#endif
+
+ 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;
+ }
+
+ if (!dev_priv->topaz_disabled)
+ {
+ /* register TOPAZ, with 0 interrupt bit, no interrupt will be served */
+ eError = PVRSRVRegisterDevice(gpsSysData, TOPAZRegisterDevice,
+ DEVICE_TOPAZ_INTERRUPT, &gui32MRSTTOPAZDeviceID);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to register TOPAZdevice!"));
+ 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
+ }
+
+#if defined(SUPPORT_DRI_DRM_EXT)
+ gpsSGXDevNode = psDeviceNode;
+#endif
+ 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 (!dev_priv->topaz_disabled)
+ {
+ 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;
+}
+
+#if !defined(SUPPORT_DRI_DRM_EXT)
+static IMG_VOID SysEnableInterrupts(SYS_DATA *psSysData)
+{
+#if !defined(NO_HARDWARE)
+ IMG_UINT32 ui32RegData;
+ IMG_UINT32 ui32Mask;
+
+ ui32Mask = POULSBO_THALIA_MASK;
+
+
+ ui32RegData = OSReadHWReg(gsPoulsboRegsCPUVaddr, POULSBO_INTERRUPT_IDENTITY_REG);
+ OSWriteHWReg(gsPoulsboRegsCPUVaddr, POULSBO_INTERRUPT_IDENTITY_REG, ui32RegData | ui32Mask);
+
+
+ ui32RegData = OSReadHWReg(gsPoulsboRegsCPUVaddr, POULSBO_INTERRUPT_MASK_REG);
+ OSWriteHWReg(gsPoulsboRegsCPUVaddr, POULSBO_INTERRUPT_MASK_REG, ui32RegData & (~ui32Mask));
+
+
+ ui32RegData = OSReadHWReg(gsPoulsboRegsCPUVaddr, POULSBO_INTERRUPT_ENABLE_REG);
+ OSWriteHWReg(gsPoulsboRegsCPUVaddr, POULSBO_INTERRUPT_ENABLE_REG, ui32RegData | ui32Mask);
+
+ PVR_DPF((PVR_DBG_MESSAGE, "SysEnableInterrupts: Interrupts enabled"));
+#endif
+ PVR_UNREFERENCED_PARAMETER(psSysData);
+}
+#endif
+
+#if !defined(SUPPORT_DRI_DRM_EXT)
+static IMG_VOID SysDisableInterrupts(SYS_DATA *psSysData)
+{
+#if !defined(NO_HARDWARE)
+ IMG_UINT32 ui32RegData;
+ IMG_UINT32 ui32Mask;
+ ui32Mask = POULSBO_THALIA_MASK;
+
+
+ ui32RegData = OSReadHWReg(gsPoulsboRegsCPUVaddr, POULSBO_INTERRUPT_ENABLE_REG);
+ OSWriteHWReg(gsPoulsboRegsCPUVaddr, POULSBO_INTERRUPT_ENABLE_REG, ui32RegData & (~ui32Mask));
+
+
+ ui32RegData = OSReadHWReg(gsPoulsboRegsCPUVaddr, POULSBO_INTERRUPT_MASK_REG);
+ OSWriteHWReg(gsPoulsboRegsCPUVaddr, POULSBO_INTERRUPT_MASK_REG, ui32RegData | ui32Mask);
+
+ PVR_TRACE(("SysDisableInterrupts: Interrupts disabled"));
+#endif
+ PVR_UNREFERENCED_PARAMETER(psSysData);
+}
+#endif
+
+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);
+
+#if defined(SYS_USING_INTERRUPTS) && !defined(SUPPORT_DRI_DRM_EXT)
+ eError = OSInstallSystemLISR(gpsSysData, gsSGXDeviceMap.ui32IRQ);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysFinalise: OSInstallSystemLISR failed"));
+ return eError;
+ }
+ SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_LISR_INSTALLED);
+#endif
+
+#if (defined(SYS_USING_INTERRUPTS) && !defined(SUPPORT_DRI_DRM_EXT))
+ SysEnableInterrupts(gpsSysData);
+ SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_IRQ_ENABLED);
+#endif
+
+ 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 (defined(SYS_USING_INTERRUPTS) && !defined(SUPPORT_DRI_DRM_EXT))
+ if (SYS_SPECIFIC_DATA_TEST(&gsSysSpecificData, SYS_SPECIFIC_DATA_IRQ_ENABLED))
+ {
+ SysDisableInterrupts(psSysData);
+ }
+#endif
+
+#if defined(SYS_USING_INTERRUPTS) && !defined(SUPPORT_DRI_DRM_EXT)
+ if (SYS_SPECIFIC_DATA_TEST(psSysSpecData, SYS_SPECIFIC_DATA_LISR_INSTALLED))
+ {
+ eError = OSUninstallSystemLISR(psSysData);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysDeinitialise: OSUninstallSystemLISR failed"));
+ return eError;
+ }
+ }
+#endif
+ 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);
+
+
+#if !defined(NO_HARDWARE)
+
+ 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);
+#endif
+ 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)
+{
+#if !defined(SUPPORT_DRI_DRM_EXT)
+ IMG_UINT32 ui32Devices = 0;
+ IMG_UINT32 ui32Data, ui32DIMMask;
+
+ PVR_UNREFERENCED_PARAMETER(psSysData);
+ PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+
+
+ ui32Data = OSReadHWReg(gsPoulsboRegsCPUVaddr, POULSBO_INTERRUPT_IDENTITY_REG);
+
+ if (ui32Data & POULSBO_THALIA_MASK)
+ {
+ ui32Devices |= DEVICE_SGX_INTERRUPT;
+ }
+
+ if (ui32Data & POULSBO_MSVDX_MASK)
+ {
+ ui32Devices |= DEVICE_MSVDX_INTERRUPT;
+ }
+
+
+ ui32DIMMask = OSReadHWReg(gsPoulsboRegsCPUVaddr, POULSBO_INTERRUPT_ENABLE_REG);
+ ui32DIMMask &= ~(POULSBO_THALIA_MASK | POULSBO_MSVDX_MASK);
+
+
+ if (ui32Data & ui32DIMMask)
+ {
+ ui32Devices |= DEVICE_DISP_INTERRUPT;
+ }
+
+ return (ui32Devices);
+#else
+ PVR_UNREFERENCED_PARAMETER(psSysData);
+ PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+
+ return 0;
+#endif
+}
+
+IMG_VOID SysClearInterrupts(SYS_DATA* psSysData, IMG_UINT32 ui32ClearBits)
+{
+#if !defined(SUPPORT_DRI_DRM_EXT)
+ IMG_UINT32 ui32Data;
+ IMG_UINT32 ui32Mask = 0;
+
+ PVR_UNREFERENCED_PARAMETER(psSysData);
+
+ ui32Data = OSReadHWReg(gsPoulsboRegsCPUVaddr, POULSBO_INTERRUPT_IDENTITY_REG);
+
+ if ((ui32ClearBits & DEVICE_SGX_INTERRUPT) &&
+ (ui32Data & POULSBO_THALIA_MASK))
+ {
+ ui32Mask |= POULSBO_THALIA_MASK;
+ }
+
+ if ((ui32ClearBits & DEVICE_MSVDX_INTERRUPT) &&
+ (ui32Data & POULSBO_MSVDX_MASK))
+ {
+ ui32Mask |= POULSBO_MSVDX_MASK;
+ }
+
+ if ((ui32ClearBits & DEVICE_DISP_INTERRUPT) &&
+ (ui32Data & POULSBO_VSYNC_PIPEA_VBLANK_MASK))
+ {
+ ui32Mask |= POULSBO_VSYNC_PIPEA_VBLANK_MASK;
+ }
+
+ if (ui32Mask)
+ {
+ OSWriteHWReg(gsPoulsboRegsCPUVaddr, POULSBO_INTERRUPT_IDENTITY_REG, ui32Mask);
+ }
+#else
+ PVR_UNREFERENCED_PARAMETER(psSysData);
+ PVR_UNREFERENCED_PARAMETER(ui32ClearBits);
+#endif
+}
+
+
+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);
+
+#if !defined(SUPPORT_DRI_DRM_EXT)
+ if ((ui32ID == OEM_GET_EXT_FUNCS) &&
+ (ulOutSize == sizeof(PVRSRV_DC_OEM_JTABLE)))
+ {
+ PVRSRV_DC_OEM_JTABLE *psOEMJTable = (PVRSRV_DC_OEM_JTABLE*)pvOut;
+ psOEMJTable->pfnOEMBridgeDispatch = &PVRSRV_BridgeDispatchKM;
+
+ psOEMJTable->pfnOEMReadRegistryString = IMG_NULL;
+ psOEMJTable->pfnOEMWriteRegistryString = IMG_NULL;
+
+ return PVRSRV_OK;
+ }
+#endif
+
+ 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 !(defined(NO_HARDWARE) && defined(__linux__))
+
+ 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);
+ }
+#endif
+
+ 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;
+ }
+
+#if !(defined(NO_HARDWARE) && defined(__linux__))
+
+ 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);
+
+#endif
+
+ 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))
+ {
+#if !defined(SUPPORT_DRI_DRM_EXT)
+ drm_irq_uninstall(gpDrmDevice);
+#endif
+
+ 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);
+
+#if !defined(SUPPORT_DRI_DRM_EXT)
+ eError = OSPCISuspendDev(gsSysSpecificData.hSGXPCI);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysSystemPrePowerState: OSPCISuspendDev failed (%d)", eError));
+ }
+#endif
+ }
+ }
+
+ 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))
+ {
+#if !defined(SUPPORT_DRI_DRM_EXT)
+ eError = OSPCIResumeDev(gsSysSpecificData.hSGXPCI);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SysSystemPostPowerState: OSPCIResumeDev failed (%d)", eError));
+ return eError;
+ }
+#endif
+
+ //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;
+ }
+
+#if !defined(SUPPORT_DRI_DRM_EXT)
+ drm_irq_install(gpDrmDevice);
+#endif
+ }
+ }
+ 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"));
+#if defined(SUPPORT_DRI_DRM_EXT)
+ psb_irq_uninstall_islands(gpDrmDevice, OSPM_GRAPHICS_ISLAND);
+ ospm_power_island_down(OSPM_GRAPHICS_ISLAND);
+ ospm_power_using_hw_end(OSPM_GRAPHICS_ISLAND);
+#endif
+ }
+#if 1
+ else if (ui32DeviceIndex == gui32MRSTMSVDXDeviceID)
+ {
+ if (ospm_power_is_hw_on(OSPM_DISPLAY_ISLAND)) {
+ ospm_power_island_down(OSPM_VIDEO_DEC_ISLAND);
+ } else {
+ ospm_power_island_up(OSPM_DISPLAY_ISLAND);
+ ospm_power_island_down(OSPM_VIDEO_DEC_ISLAND);
+ ospm_power_island_down(OSPM_DISPLAY_ISLAND);
+ }
+#if 0
+#if defined(SUPPORT_DRI_DRM_EXT)
+ ospm_power_using_hw_end(OSPM_VIDEO_DEC_ISLAND);
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+#endif
+#endif
+ }
+ else if (ui32DeviceIndex == gui32MRSTTOPAZDeviceID)
+ {
+ if (ospm_power_is_hw_on(OSPM_DISPLAY_ISLAND)) {
+ ospm_power_island_down(OSPM_VIDEO_ENC_ISLAND);
+ } else {
+ ospm_power_island_up(OSPM_DISPLAY_ISLAND);
+ ospm_power_island_down(OSPM_VIDEO_ENC_ISLAND);
+ ospm_power_island_down(OSPM_DISPLAY_ISLAND);
+ }
+ }
+#if 0
+#if defined(SUPPORT_DRI_DRM_EXT)
+ ospm_power_using_hw_end(OSPM_VIDEO_ENC_ISLAND);
+ ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+#endif
+#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"));
+#if defined(SUPPORT_DRI_DRM_EXT)
+ ospm_power_using_hw_begin(OSPM_GRAPHICS_ISLAND, true);
+#endif
+
+ }
+#if 1
+ else if (ui32DeviceIndex == gui32MRSTMSVDXDeviceID)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"SysDevicePrePowerState: Restore MSVDX power"));
+ if (ospm_power_is_hw_on(OSPM_DISPLAY_ISLAND)) {
+ ospm_power_island_up(OSPM_VIDEO_DEC_ISLAND);
+ } else {
+ ospm_power_island_up(OSPM_DISPLAY_ISLAND);
+ ospm_power_island_up(OSPM_VIDEO_DEC_ISLAND);
+ ospm_power_island_down(OSPM_DISPLAY_ISLAND);
+ }
+#if 0
+#if defined(SUPPORT_DRI_DRM_EXT)
+ 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
+#endif
+ }
+ else if (ui32DeviceIndex == gui32MRSTTOPAZDeviceID)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"SysDevicePrePowerState: Restore TOPAZ power"));
+ if (ospm_power_is_hw_on(OSPM_DISPLAY_ISLAND)) {
+ ospm_power_island_up(OSPM_VIDEO_ENC_ISLAND);
+ } else {
+ ospm_power_island_up(OSPM_DISPLAY_ISLAND);
+ ospm_power_island_up(OSPM_VIDEO_ENC_ISLAND);
+ ospm_power_island_down(OSPM_DISPLAY_ISLAND);
+ }
+#if 0
+#if defined(SUPPORT_DRI_DRM_EXT)
+ 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
+ }
+#endif
+ }
+
+ return PVRSRV_OK;
+}
+
+#if defined(SUPPORT_DRI_DRM_EXT)
+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;
+}
+#endif
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#if !defined(__SOCCONFIG_H__)
+#define __SOCCONFIG_H__
+#include "syscommon.h"
+#include "extsyscache.h"
+
+#define VS_PRODUCT_NAME "SGX Medfield"
+
+#define SYS_NO_POWER_LOCK_TIMEOUT
+
+/*#define SGX_FEATURE_HOST_PORT */
+
+#define SYS_SGX_USSE_COUNT (2)
+
+#define POULSBO_REGS_OFFSET 0x00000
+#define POULSBO_REG_SIZE 0x2100
+
+#define SGX_REGS_OFFSET 0x80000
+#define PSB_SGX_REGS_OFFSET 0x40000
+#define SGX_REG_SIZE 0x4000
+#define MSVDX_REGS_OFFSET 0x50000
+
+#ifdef SUPPORT_MSVDX
+#define POULSBO_MAX_OFFSET (MSVDX_REGS_OFFSET + MSVDX_REG_SIZE)
+#else
+#define POULSBO_MAX_OFFSET (SGX_REGS_OFFSET + SGX_REG_SIZE)
+#define PSB_POULSBO_MAX_OFFSET (PSB_SGX_REGS_OFFSET + SGX_REG_SIZE)
+#endif
+
+#define SYS_SGX_DEV_VENDOR_ID 0x8086
+#define PSB_SYS_SGX_DEV_DEVICE_ID_1 0x8108
+#define PSB_SYS_SGX_DEV_DEVICE_ID_2 0x8109
+
+#define SYS_SGX_DEV_DEVICE_ID 0x4102
+
+#define SYS_SGX_DEVICE_IDS \
+ {0x8086, 0x8108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PSB_8108}, \
+ {0x8086, 0x8109, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PSB_8109}, \
+ {0x8086, 0x4100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100}, \
+ {0x8086, 0x4101, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100}, \
+ {0x8086, 0x4102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100}, \
+ {0x8086, 0x4103, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100}, \
+ {0x8086, 0x4104, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100}, \
+ {0x8086, 0x4105, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100}, \
+ {0x8086, 0x4106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100}, \
+ {0x8086, 0x4107, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100}, \
+ {0x8086, 0x0130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MDFLD_0130}, \
+ {0x8086, 0x0131, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MDFLD_0130}, \
+ {0x8086, 0x0132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MDFLD_0130}, \
+ {0x8086, 0x0133, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MDFLD_0130}, \
+ {0x8086, 0x0134, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MDFLD_0130}, \
+ {0x8086, 0x0135, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MDFLD_0130}, \
+ {0x8086, 0x0136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MDFLD_0130}, \
+ {0x8086, 0x0137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MDFLD_0130}, \
+ {0, 0, 0}
+
+
+#define MMADR_INDEX 4
+#define IOPORT_INDEX 5
+#define GMADR_INDEX 6
+#define MMUADR_INDEX 7
+#define FBADR_INDEX 23
+#define FBSIZE_INDEX 24
+
+#define DISPLAY_SURFACE_SIZE (4 * 1024 * 1024)
+
+#define DEVICE_SGX_INTERRUPT (1<<0)
+#define DEVICE_MSVDX_INTERRUPT (1<<1)
+#define DEVICE_DISP_INTERRUPT (1<<2)
+#define DEVICE_TOPAZ_INTERRUPT (1<<3)
+
+#define POULSBO_INTERRUPT_ENABLE_REG 0x20A0
+#define POULSBO_INTERRUPT_IDENTITY_REG 0x20A4
+#define POULSBO_INTERRUPT_MASK_REG 0x20A8
+#define POULSBO_INTERRUPT_STATUS_REG 0x20AC
+
+#define POULSBO_DISP_MASK (1<<17)
+#define POULSBO_THALIA_MASK (1<<18)
+#define POULSBO_MSVDX_MASK (1<<19)
+#define POULSBO_VSYNC_PIPEA_VBLANK_MASK (1<<7)
+#define POULSBO_VSYNC_PIPEA_EVENT_MASK (1<<6)
+#define POULSBO_VSYNC_PIPEB_VBLANK_MASK (1<<5)
+#define POULSBO_VSYNC_PIPEB_EVENT_MASK (1<<4)
+
+#define POULSBO_DISPLAY_REGS_OFFSET 0x70000
+#define POULSBO_DISPLAY_REG_SIZE 0x2000
+
+#define POULSBO_DISPLAY_A_CONFIG 0x00008
+#define POULSBO_DISPLAY_A_STATUS_SELECT 0x00024
+#define POULSBO_DISPLAY_B_CONFIG 0x01008
+#define POULSBO_DISPLAY_B_STATUS_SELECT 0x01024
+
+#define POULSBO_DISPLAY_PIPE_ENABLE (1<<31)
+#define POULSBO_DISPLAY_VSYNC_STS_EN (1<<25)
+#define POULSBO_DISPLAY_VSYNC_STS (1<<9)
+
+#if defined(SGX_FEATURE_HOST_PORT)
+ #define SYS_SGX_HP_SIZE 0x8000000
+ #define PSB_SYS_SGX_HP_SIZE 0x4000000
+
+ #define SYS_SGX_HOSTPORT_BASE_DEVVADDR 0xD0000000
+ #if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030)
+
+
+
+ #define SYS_SGX_HOSTPORT_BRN23030_OFFSET 0x7C00000
+ #endif
+#endif
+
+
+typedef struct
+{
+ union
+ {
+#if !defined(VISTA)
+ IMG_UINT8 aui8PCISpace[256];
+ IMG_UINT16 aui16PCISpace[128];
+ IMG_UINT32 aui32PCISpace[64];
+#endif
+ struct
+ {
+ IMG_UINT16 ui16VenID;
+ IMG_UINT16 ui16DevID;
+ IMG_UINT16 ui16PCICmd;
+ IMG_UINT16 ui16PCIStatus;
+ }s;
+ }u;
+} PCICONFIG_SPACE, *PPCICONFIG_SPACE;
+
+#endif
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#if !defined(__SYSINFO_H__)
+#define __SYSINFO_H__
+
+#define MAX_HW_TIME_US (500000)
+#define WAIT_TRY_COUNT (10000)
+
+typedef enum _SYS_DEVICE_TYPE_
+{
+ SYS_DEVICE_SGX = 0,
+
+ SYS_DEVICE_FORCE_I16 = 0x7fff
+
+} SYS_DEVICE_TYPE;
+
+#define SYS_DEVICE_COUNT 10
+
+#endif
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#if !defined(__SYSLOCAL_H__)
+#define __SYSLOCAL_H__
+
+#define SYS_SPECIFIC_DATA_PCI_ACQUIRE_DEV 0x00000001
+#define SYS_SPECIFIC_DATA_PCI_REQUEST_SGX_ADDR_RANGE 0x00000002
+#define SYS_SPECIFIC_DATA_PCI_REQUEST_HOST_PORT_RANGE 0x00000004
+#if defined(NO_HARDWARE)
+#define SYS_SPECIFIC_DATA_ALLOC_DUMMY_SGX_REGS 0x00000008
+#if defined(SUPPORT_MSVDX)
+#define SYS_SPECIFIC_DATA_ALLOC_DUMMY_MSVDX_REGS 0x00000020
+#endif
+#endif
+#define SYS_SPECIFIC_DATA_SGX_INITIALISED 0x00000040
+#if defined(SUPPORT_MSVDX)
+#define SYS_SPECIFIC_DATA_MSVDX_INITIALISED 0x00000080
+#endif
+#define SYS_SPECIFIC_DATA_MISR_INSTALLED 0x00000100
+#define SYS_SPECIFIC_DATA_LISR_INSTALLED 0x00000200
+#define SYS_SPECIFIC_DATA_PDUMP_INIT 0x00000400
+#define SYS_SPECIFIC_DATA_IRQ_ENABLED 0x00000800
+
+#define SYS_SPECIFIC_DATA_PM_UNMAP_SGX_REGS 0x00001000
+#define SYS_SPECIFIC_DATA_PM_UNMAP_SGX_HP 0x00004000
+#define SYS_SPECIFIC_DATA_PM_UNMAP_MSVDX_REGS 0x00008000
+#define SYS_SPECIFIC_DATA_PM_IRQ_DISABLE 0x00010000
+#define SYS_SPECIFIC_DATA_PM_UNINSTALL_LISR 0x00020000
+
+#define SYS_SPECIFIC_DATA_SET(psSysSpecData, flag) ((IMG_VOID)((psSysSpecData)->ui32SysSpecificData |= (flag)))
+
+#define SYS_SPECIFIC_DATA_CLEAR(psSysSpecData, flag) ((IMG_VOID)((psSysSpecData)->ui32SysSpecificData &= ~(flag)))
+
+#define SYS_SPECIFIC_DATA_TEST(psSysSpecData, flag) (((psSysSpecData)->ui32SysSpecificData & (flag)) != 0)
+
+
+typedef struct _SYS_SPECIFIC_DATA_TAG_
+{
+
+ IMG_UINT32 ui32SysSpecificData;
+#ifdef __linux__
+ PVRSRV_PCI_DEV_HANDLE hSGXPCI;
+#endif
+#if defined(LDM_PCI) || defined(SUPPORT_DRI_DRM_EXT)
+ struct pci_dev *psPCIDev;
+#endif
+
+ /* MSI reg save */
+ uint32_t msi_addr;
+ uint32_t msi_data;
+
+ uint32_t saveBSM;
+ uint32_t saveVBT;
+} SYS_SPECIFIC_DATA;
+
+
+#endif
+
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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 "services_headers.h"
+#include "sysinfo.h"
+#include "syslocal.h"
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef _LINUXSRV_H__
+#define _LINUXSRV_H__
+
+typedef struct tagIOCTL_PACKAGE
+{
+ IMG_UINT32 ui32Cmd;
+ IMG_UINT32 ui32Size;
+ IMG_VOID *pInBuffer;
+ IMG_UINT32 ui32InBufferSize;
+ IMG_VOID *pOutBuffer;
+ IMG_UINT32 ui32OutBufferSize;
+} IOCTL_PACKAGE;
+
+IMG_UINT32 DeviceIoControl(IMG_UINT32 hDevice,
+ IMG_UINT32 ui32ControlCode,
+ IMG_VOID *pInBuffer,
+ IMG_UINT32 ui32InBufferSize,
+ IMG_VOID *pOutBuffer,
+ IMG_UINT32 ui32OutBufferSize,
+ IMG_UINT32 *pui32BytesReturned);
+
+#endif
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+
+#ifdef LINUX
+#include <linux/string.h>
+#endif
+
+#include "img_types.h"
+#include "pvr_debug.h"
+#include "dbgdrvif.h"
+#include "dbgdriv.h"
+#include "hotkey.h"
+#include "hostfunc.h"
+#include "pvr_debug.h"
+
+
+
+
+#define LAST_FRAME_BUF_SIZE 1024
+
+typedef struct _DBG_LASTFRAME_BUFFER_
+{
+ PDBG_STREAM psStream;
+ IMG_UINT8 ui8Buffer[LAST_FRAME_BUF_SIZE];
+ IMG_UINT32 ui32BufLen;
+ struct _DBG_LASTFRAME_BUFFER_ *psNext;
+} *PDBG_LASTFRAME_BUFFER;
+
+
+static PDBG_STREAM g_psStreamList = 0;
+static PDBG_LASTFRAME_BUFFER g_psLFBufferList;
+
+static IMG_UINT32 g_ui32LOff = 0;
+static IMG_UINT32 g_ui32Line = 0;
+static IMG_UINT32 g_ui32MonoLines = 25;
+
+static IMG_BOOL g_bHotkeyMiddump = IMG_FALSE;
+static IMG_UINT32 g_ui32HotkeyMiddumpStart = 0xffffffff;
+static IMG_UINT32 g_ui32HotkeyMiddumpEnd = 0xffffffff;
+
+IMG_VOID * g_pvAPIMutex=IMG_NULL;
+
+extern IMG_UINT32 g_ui32HotKeyFrame;
+extern IMG_BOOL g_bHotKeyPressed;
+extern IMG_BOOL g_bHotKeyRegistered;
+
+IMG_BOOL gbDumpThisFrame = IMG_FALSE;
+
+
+IMG_UINT32 SpaceInStream(PDBG_STREAM psStream);
+IMG_BOOL ExpandStreamBuffer(PDBG_STREAM psStream, IMG_UINT32 ui32NewSize);
+PDBG_LASTFRAME_BUFFER FindLFBuf(PDBG_STREAM psStream);
+
+DBGKM_SERVICE_TABLE g_sDBGKMServices =
+{
+ sizeof (DBGKM_SERVICE_TABLE),
+ ExtDBGDrivCreateStream,
+ ExtDBGDrivDestroyStream,
+ ExtDBGDrivFindStream,
+ ExtDBGDrivWriteString,
+ ExtDBGDrivReadString,
+ ExtDBGDrivWrite,
+ ExtDBGDrivRead,
+ ExtDBGDrivSetCaptureMode,
+ ExtDBGDrivSetOutputMode,
+ ExtDBGDrivSetDebugLevel,
+ ExtDBGDrivSetFrame,
+ ExtDBGDrivGetFrame,
+ ExtDBGDrivOverrideMode,
+ ExtDBGDrivDefaultMode,
+ ExtDBGDrivWrite2,
+ ExtDBGDrivWriteStringCM,
+ ExtDBGDrivWriteCM,
+ ExtDBGDrivSetMarker,
+ ExtDBGDrivGetMarker,
+ ExtDBGDrivStartInitPhase,
+ ExtDBGDrivStopInitPhase,
+ ExtDBGDrivIsCaptureFrame,
+ ExtDBGDrivWriteLF,
+ ExtDBGDrivReadLF,
+ ExtDBGDrivGetStreamOffset,
+ ExtDBGDrivSetStreamOffset,
+ ExtDBGDrivIsLastCaptureFrame,
+ ExtDBGDrivWaitForEvent,
+ ExtDBGDrivSetConnectNotifier,
+ ExtDBGDrivWritePersist
+};
+
+
+static IMG_UINT32 DBGDrivWritePersist(PDBG_STREAM psMainStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+static IMG_VOID InvalidateAllStreams(IMG_VOID);
+
+
+
+
+DBGKM_CONNECT_NOTIFIER g_fnDBGKMNotifier;
+
+IMG_VOID IMG_CALLCONV ExtDBGDrivSetConnectNotifier(DBGKM_CONNECT_NOTIFIER fn_notifier)
+{
+
+ g_fnDBGKMNotifier = fn_notifier;
+}
+
+IMG_VOID * IMG_CALLCONV ExtDBGDrivCreateStream(IMG_CHAR * pszName, IMG_UINT32 ui32CapMode, IMG_UINT32 ui32OutMode, IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size)
+{
+ IMG_VOID * pvRet;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ pvRet=DBGDrivCreateStream(pszName, ui32CapMode, ui32OutMode, ui32Flags, ui32Size);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return pvRet;
+}
+
+void IMG_CALLCONV ExtDBGDrivDestroyStream(PDBG_STREAM psStream)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivDestroyStream(psStream);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+IMG_VOID * IMG_CALLCONV ExtDBGDrivFindStream(IMG_CHAR * pszName, IMG_BOOL bResetStream)
+{
+ IMG_VOID * pvRet;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ pvRet=DBGDrivFindStream(pszName, bResetStream);
+ if(g_fnDBGKMNotifier.pfnConnectNotifier)
+ {
+ g_fnDBGKMNotifier.pfnConnectNotifier();
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "pfnConnectNotifier not initialised.\n"));
+ }
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return pvRet;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level)
+{
+ IMG_UINT32 ui32Ret;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret=DBGDrivWriteString(psStream, pszString, ui32Level);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivReadString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Limit)
+{
+ IMG_UINT32 ui32Ret;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret=DBGDrivReadString(psStream, pszString, ui32Limit);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWrite(PDBG_STREAM psStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
+{
+ IMG_UINT32 ui32Ret;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret=DBGDrivWrite(psStream, pui8InBuf, ui32InBuffSize, ui32Level);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivRead(PDBG_STREAM psStream, IMG_BOOL bReadInitBuffer, IMG_UINT32 ui32OutBuffSize,IMG_UINT8 * pui8OutBuf)
+{
+ IMG_UINT32 ui32Ret;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret=DBGDrivRead(psStream, bReadInitBuffer, ui32OutBuffSize, pui8OutBuf);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+void IMG_CALLCONV ExtDBGDrivSetCaptureMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode,IMG_UINT32 ui32Start,IMG_UINT32 ui32End,IMG_UINT32 ui32SampleRate)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivSetCaptureMode(psStream, ui32Mode, ui32Start, ui32End, ui32SampleRate);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+void IMG_CALLCONV ExtDBGDrivSetOutputMode(PDBG_STREAM psStream,IMG_UINT32 ui32OutMode)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivSetOutputMode(psStream, ui32OutMode);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+void IMG_CALLCONV ExtDBGDrivSetDebugLevel(PDBG_STREAM psStream,IMG_UINT32 ui32DebugLevel)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivSetDebugLevel(psStream, ui32DebugLevel);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+void IMG_CALLCONV ExtDBGDrivSetFrame(PDBG_STREAM psStream,IMG_UINT32 ui32Frame)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivSetFrame(psStream, ui32Frame);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetFrame(PDBG_STREAM psStream)
+{
+ IMG_UINT32 ui32Ret;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret=DBGDrivGetFrame(psStream);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+IMG_BOOL IMG_CALLCONV ExtDBGDrivIsLastCaptureFrame(PDBG_STREAM psStream)
+{
+ IMG_BOOL bRet;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ bRet = DBGDrivIsLastCaptureFrame(psStream);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return bRet;
+}
+
+IMG_BOOL IMG_CALLCONV ExtDBGDrivIsCaptureFrame(PDBG_STREAM psStream, IMG_BOOL bCheckPreviousFrame)
+{
+ IMG_BOOL bRet;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ bRet = DBGDrivIsCaptureFrame(psStream, bCheckPreviousFrame);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return bRet;
+}
+
+void IMG_CALLCONV ExtDBGDrivOverrideMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivOverrideMode(psStream, ui32Mode);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+void IMG_CALLCONV ExtDBGDrivDefaultMode(PDBG_STREAM psStream)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivDefaultMode(psStream);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWrite2(PDBG_STREAM psStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
+{
+ IMG_UINT32 ui32Ret;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret=DBGDrivWrite2(psStream, pui8InBuf, ui32InBuffSize, ui32Level);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWritePersist(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
+{
+ IMG_UINT32 ui32Ret;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret=DBGDrivWritePersist(psStream, pui8InBuf, ui32InBuffSize, ui32Level);
+ if(ui32Ret==0xFFFFFFFFU)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "An error occurred in DBGDrivWritePersist."));
+ }
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteStringCM(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level)
+{
+ IMG_UINT32 ui32Ret;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret=DBGDrivWriteStringCM(psStream, pszString, ui32Level);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteCM(PDBG_STREAM psStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
+{
+ IMG_UINT32 ui32Ret;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret=DBGDrivWriteCM(psStream, pui8InBuf, ui32InBuffSize, ui32Level);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+void IMG_CALLCONV ExtDBGDrivSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivSetMarker(psStream, ui32Marker);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetMarker(PDBG_STREAM psStream)
+{
+ IMG_UINT32 ui32Marker;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Marker = DBGDrivGetMarker(psStream);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Marker;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteLF(PDBG_STREAM psStream, IMG_UINT8 * pui8InBuf, IMG_UINT32 ui32InBuffSize, IMG_UINT32 ui32Level, IMG_UINT32 ui32Flags)
+{
+ IMG_UINT32 ui32Ret;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret = DBGDrivWriteLF(psStream, pui8InBuf, ui32InBuffSize, ui32Level, ui32Flags);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivReadLF(PDBG_STREAM psStream, IMG_UINT32 ui32OutBuffSize, IMG_UINT8 * pui8OutBuf)
+{
+ IMG_UINT32 ui32Ret;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret = DBGDrivReadLF(psStream, ui32OutBuffSize, pui8OutBuf);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+
+IMG_VOID IMG_CALLCONV ExtDBGDrivStartInitPhase(PDBG_STREAM psStream)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivStartInitPhase(psStream);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+IMG_VOID IMG_CALLCONV ExtDBGDrivStopInitPhase(PDBG_STREAM psStream)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivStopInitPhase(psStream);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetStreamOffset(PDBG_STREAM psStream)
+{
+ IMG_UINT32 ui32Ret;
+
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret = DBGDrivGetStreamOffset(psStream);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+IMG_VOID IMG_CALLCONV ExtDBGDrivSetStreamOffset(PDBG_STREAM psStream, IMG_UINT32 ui32StreamOffset)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivSetStreamOffset(psStream, ui32StreamOffset);
+
+
+ HostReleaseMutex(g_pvAPIMutex);
+}
+
+IMG_VOID IMG_CALLCONV ExtDBGDrivWaitForEvent(DBG_EVENT eEvent)
+{
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+ DBGDrivWaitForEvent(eEvent);
+#else
+ PVR_UNREFERENCED_PARAMETER(eEvent);
+#endif
+}
+
+IMG_UINT32 AtoI(IMG_CHAR *szIn)
+{
+ IMG_INT iLen = 0;
+ IMG_UINT32 ui32Value = 0;
+ IMG_UINT32 ui32Digit=1;
+ IMG_UINT32 ui32Base=10;
+ IMG_INT iPos;
+ IMG_CHAR bc;
+
+
+ while (szIn[iLen] > 0)
+ {
+ iLen ++;
+ }
+
+
+ if (iLen == 0)
+ {
+ return (0);
+ }
+
+
+ iPos=0;
+ while (szIn[iPos] == '0')
+ {
+ iPos++;
+ }
+ if (szIn[iPos] == '\0')
+ {
+ return 0;
+ }
+ if (szIn[iPos] == 'x' || szIn[iPos] == 'X')
+ {
+ ui32Base=16;
+ szIn[iPos]='0';
+ }
+
+
+ for (iPos = iLen - 1; iPos >= 0; iPos --)
+ {
+ bc = szIn[iPos];
+
+ if ( (bc >= 'a') && (bc <= 'f') && ui32Base == 16)
+ {
+ bc -= 'a' - 0xa;
+ }
+ else
+ if ( (bc >= 'A') && (bc <= 'F') && ui32Base == 16)
+ {
+ bc -= 'A' - 0xa;
+ }
+ else
+ if ((bc >= '0') && (bc <= '9'))
+ {
+ bc -= '0';
+ }
+ else
+ return (0);
+
+ ui32Value += (IMG_UINT32)bc * ui32Digit;
+
+ ui32Digit = ui32Digit * ui32Base;
+ }
+ return (ui32Value);
+}
+
+
+static IMG_BOOL StreamValid(PDBG_STREAM psStream)
+{
+ PDBG_STREAM psThis;
+
+ psThis = g_psStreamList;
+
+ while (psThis)
+ {
+ if (psStream && (psThis == psStream))
+ {
+ return(IMG_TRUE);
+ }
+ else
+ {
+ psThis = psThis->psNext;
+ }
+ }
+
+ return(IMG_FALSE);
+}
+
+
+static IMG_BOOL StreamValidForRead(PDBG_STREAM psStream)
+{
+ if( StreamValid(psStream) &&
+ ((psStream->psCtrl->ui32Flags & DEBUG_FLAGS_WRITEONLY) == 0) )
+ {
+ return(IMG_TRUE);
+ }
+
+ return(IMG_FALSE);
+}
+
+static IMG_BOOL StreamValidForWrite(PDBG_STREAM psStream)
+{
+ if( StreamValid(psStream) &&
+ ((psStream->psCtrl->ui32Flags & DEBUG_FLAGS_READONLY) == 0) )
+ {
+ return(IMG_TRUE);
+ }
+
+ return(IMG_FALSE);
+}
+
+
+static void Write(PDBG_STREAM psStream,IMG_PUINT8 pui8Data,IMG_UINT32 ui32InBuffSize)
+{
+
+
+ if (!psStream->bCircularAllowed)
+ {
+
+ }
+
+ if ((psStream->ui32WPtr + ui32InBuffSize) > psStream->ui32Size)
+ {
+
+ IMG_UINT32 ui32B1 = psStream->ui32Size - psStream->ui32WPtr;
+ IMG_UINT32 ui32B2 = ui32InBuffSize - ui32B1;
+
+
+ HostMemCopy((IMG_PVOID)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32WPtr),
+ (IMG_PVOID) pui8Data,
+ ui32B1);
+
+
+ HostMemCopy(psStream->pvBase,
+ (IMG_PVOID)(pui8Data + ui32B1),
+ ui32B2);
+
+
+ psStream->ui32WPtr = ui32B2;
+ }
+ else
+ {
+ HostMemCopy((IMG_PVOID)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32WPtr),
+ (IMG_PVOID) pui8Data,
+ ui32InBuffSize);
+
+ psStream->ui32WPtr += ui32InBuffSize;
+
+ if (psStream->ui32WPtr == psStream->ui32Size)
+ {
+ psStream->ui32WPtr = 0;
+ }
+ }
+ psStream->ui32DataWritten += ui32InBuffSize;
+}
+
+
+void MonoOut(IMG_CHAR * pszString,IMG_BOOL bNewLine)
+{
+#if defined (_WIN64)
+ PVR_UNREFERENCED_PARAMETER(pszString);
+ PVR_UNREFERENCED_PARAMETER(bNewLine);
+
+#else
+ IMG_UINT32 i;
+ IMG_CHAR * pScreen;
+
+ pScreen = (IMG_CHAR *) DBGDRIV_MONOBASE;
+
+ pScreen += g_ui32Line * 160;
+
+
+
+ i=0;
+ do
+ {
+ pScreen[g_ui32LOff + (i*2)] = pszString[i];
+ pScreen[g_ui32LOff + (i*2)+1] = 127;
+ i++;
+ }
+ while ((pszString[i] != 0) && (i < 4096));
+
+ g_ui32LOff += i * 2;
+
+ if (bNewLine)
+ {
+ g_ui32LOff = 0;
+ g_ui32Line++;
+ }
+
+
+
+ if (g_ui32Line == g_ui32MonoLines)
+ {
+ g_ui32Line = g_ui32MonoLines - 1;
+
+ HostMemCopy((IMG_VOID *)DBGDRIV_MONOBASE,(IMG_VOID *)(DBGDRIV_MONOBASE + 160),160 * (g_ui32MonoLines - 1));
+
+ HostMemSet((IMG_VOID *)(DBGDRIV_MONOBASE + (160 * (g_ui32MonoLines - 1))),0,160);
+ }
+#endif
+}
+
+static IMG_UINT32 WriteExpandingBuffer(PDBG_STREAM psStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize)
+{
+ IMG_UINT ui32Space;
+
+
+
+ ui32Space = SpaceInStream(psStream);
+
+
+
+ if ((psStream->psCtrl->ui32OutMode & DEBUG_OUTMODE_STREAMENABLE) == 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "WriteExpandingBuffer: buffer %x is disabled", (IMG_UINTPTR_T) psStream));
+ return(0);
+ }
+
+
+
+ if (psStream->psCtrl->ui32Flags & DEBUG_FLAGS_NO_BUF_EXPANDSION)
+ {
+
+
+
+ if (ui32Space < 32)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "WriteExpandingBuffer: buffer %x is full and isn't expandable", (IMG_UINTPTR_T) psStream));
+ return(0);
+ }
+ }
+ else
+ {
+ if ((ui32Space < 32) || (ui32Space <= (ui32InBuffSize + 4)))
+ {
+ IMG_UINT32 ui32NewBufSize;
+
+
+
+ ui32NewBufSize = 2 * psStream->ui32Size;
+
+ PVR_DPF((PVR_DBGDRIV_MESSAGE, "Expanding buffer size = %x, new size = %x",
+ psStream->ui32Size, ui32NewBufSize));
+
+ if (ui32InBuffSize > psStream->ui32Size)
+ {
+ ui32NewBufSize += ui32InBuffSize;
+ }
+
+
+
+ if (!ExpandStreamBuffer(psStream,ui32NewBufSize))
+ {
+ if (ui32Space < 32)
+ {
+ if(psStream->bCircularAllowed)
+ {
+ return(0);
+ }
+ else
+ {
+
+ PVR_DPF((PVR_DBG_ERROR, "WriteExpandingBuffer: Unable to expand %x. Out of memory.", (IMG_UINTPTR_T) psStream));
+ InvalidateAllStreams();
+ return (0xFFFFFFFFUL);
+ }
+ }
+ }
+
+
+
+ ui32Space = SpaceInStream(psStream);
+ PVR_DPF((PVR_DBGDRIV_MESSAGE, "Expanded buffer, free space = %x",
+ ui32Space));
+ }
+ }
+
+
+
+ if (ui32Space <= (ui32InBuffSize + 4))
+ {
+ ui32InBuffSize = ui32Space - 4;
+ }
+
+
+
+ Write(psStream,pui8InBuf,ui32InBuffSize);
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+ if (ui32InBuffSize)
+ {
+ HostSignalEvent(DBG_EVENT_STREAM_DATA);
+ }
+#endif
+ return(ui32InBuffSize);
+}
+
+IMG_VOID * IMG_CALLCONV DBGDrivCreateStream(IMG_CHAR * pszName,
+ IMG_UINT32 ui32CapMode,
+ IMG_UINT32 ui32OutMode,
+ IMG_UINT32 ui32Flags,
+ IMG_UINT32 ui32Size)
+{
+ PDBG_STREAM psStream;
+ PDBG_STREAM psInitStream;
+ PDBG_LASTFRAME_BUFFER psLFBuffer;
+ PDBG_STREAM_CONTROL psCtrl;
+ IMG_UINT32 ui32Off;
+ IMG_VOID * pvBase;
+ static IMG_CHAR pszNameInitSuffix[] = "_Init";
+ IMG_UINT32 ui32OffSuffix;
+
+
+
+
+ psStream = (PDBG_STREAM) DBGDrivFindStream(pszName, IMG_FALSE);
+
+ if (psStream)
+ {
+ return ((IMG_VOID *) psStream);
+ }
+
+
+
+ psStream = HostNonPageablePageAlloc(1);
+ psInitStream = HostNonPageablePageAlloc(1);
+ psLFBuffer = HostNonPageablePageAlloc(1);
+ psCtrl = HostNonPageablePageAlloc(1);
+ if (
+ (!psStream) ||
+ (!psInitStream) ||
+ (!psLFBuffer) ||
+ (!psCtrl)
+ )
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DBGDriv: Couldn't alloc control structs\n\r"));
+ return((IMG_VOID *) 0);
+ }
+
+
+ if ((ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
+ {
+ pvBase = HostNonPageablePageAlloc(ui32Size);
+ }
+ else
+ {
+ pvBase = HostPageablePageAlloc(ui32Size);
+ }
+
+ if (!pvBase)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DBGDriv: Couldn't alloc Stream buffer\n\r"));
+ HostNonPageablePageFree(psStream);
+ return((IMG_VOID *) 0);
+ }
+
+
+ psCtrl->ui32Flags = ui32Flags;
+ psCtrl->ui32CapMode = ui32CapMode;
+ psCtrl->ui32OutMode = ui32OutMode;
+ psCtrl->ui32DebugLevel = DEBUG_LEVEL_0;
+ psCtrl->ui32DefaultMode = ui32CapMode;
+ psCtrl->ui32Start = 0;
+ psCtrl->ui32End = 0;
+ psCtrl->ui32Current = 0;
+ psCtrl->ui32SampleRate = 1;
+ psCtrl->bInitPhaseComplete = IMG_FALSE;
+
+
+
+ psStream->psNext = 0;
+ psStream->pvBase = pvBase;
+ psStream->psCtrl = psCtrl;
+ psStream->ui32Size = ui32Size * 4096UL;
+ psStream->ui32RPtr = 0;
+ psStream->ui32WPtr = 0;
+ psStream->ui32DataWritten = 0;
+ psStream->ui32Marker = 0;
+ psStream->bCircularAllowed = IMG_TRUE;
+ psStream->ui32InitPhaseWOff = 0;
+
+
+
+
+ if ((ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
+ {
+ pvBase = HostNonPageablePageAlloc(ui32Size);
+ }
+ else
+ {
+ pvBase = HostPageablePageAlloc(ui32Size);
+ }
+
+ if (!pvBase)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"DBGDriv: Couldn't alloc InitStream buffer\n\r"));
+
+ if ((psStream->psCtrl->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
+ {
+ HostNonPageablePageFree(psStream->pvBase);
+ }
+ else
+ {
+ HostPageablePageFree(psStream->pvBase);
+ }
+ HostNonPageablePageFree(psStream);
+ return((IMG_VOID *) 0);
+ }
+
+
+ psInitStream->psNext = 0;
+ psInitStream->pvBase = pvBase;
+ psInitStream->psCtrl = psCtrl;
+ psInitStream->ui32Size = ui32Size * 4096UL;
+ psInitStream->ui32RPtr = 0;
+ psInitStream->ui32WPtr = 0;
+ psInitStream->ui32DataWritten = 0;
+ psInitStream->ui32Marker = 0;
+ psInitStream->bCircularAllowed = IMG_FALSE;
+ psInitStream->ui32InitPhaseWOff = 0;
+
+
+
+ psStream->psInitStream = psInitStream;
+
+
+ psLFBuffer->psStream = psStream;
+ psLFBuffer->ui32BufLen = 0UL;
+
+ g_bHotkeyMiddump = IMG_FALSE;
+ g_ui32HotkeyMiddumpStart = 0xffffffffUL;
+ g_ui32HotkeyMiddumpEnd = 0xffffffffUL;
+
+
+
+ ui32Off = 0;
+
+ do
+ {
+ psStream->szName[ui32Off] = pszName[ui32Off];
+ psInitStream->szName[ui32Off] = pszName[ui32Off];
+ ui32Off++;
+ }
+ while ((pszName[ui32Off] != 0) && (ui32Off < (4096UL - sizeof(DBG_STREAM))));
+ psStream->szName[ui32Off] = pszName[ui32Off];
+
+
+
+ ui32OffSuffix = 0;
+ do
+ {
+ psInitStream->szName[ui32Off] = pszNameInitSuffix[ui32OffSuffix];
+ ui32Off++;
+ ui32OffSuffix++;
+ }
+ while ( (pszNameInitSuffix[ui32OffSuffix] != 0) &&
+ (ui32Off < (4096UL - sizeof(DBG_STREAM))));
+ psInitStream->szName[ui32Off] = pszNameInitSuffix[ui32OffSuffix];
+
+
+
+ psStream->psNext = g_psStreamList;
+ g_psStreamList = psStream;
+
+ psLFBuffer->psNext = g_psLFBufferList;
+ g_psLFBufferList = psLFBuffer;
+
+ AddSIDEntry(psStream);
+
+ return((IMG_VOID *) psStream);
+}
+
+void IMG_CALLCONV DBGDrivDestroyStream(PDBG_STREAM psStream)
+{
+ PDBG_STREAM psStreamThis;
+ PDBG_STREAM psStreamPrev;
+ PDBG_LASTFRAME_BUFFER psLFBuffer;
+ PDBG_LASTFRAME_BUFFER psLFThis;
+ PDBG_LASTFRAME_BUFFER psLFPrev;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "DBGDriv: Destroying stream %s\r\n", psStream->szName ));
+
+
+
+ if (!StreamValid(psStream))
+ {
+ return;
+ }
+
+ RemoveSIDEntry(psStream);
+
+ psLFBuffer = FindLFBuf(psStream);
+
+
+
+ psStreamThis = g_psStreamList;
+ psStreamPrev = 0;
+
+ while (psStreamThis)
+ {
+ if (psStreamThis == psStream)
+ {
+ if (psStreamPrev)
+ {
+ psStreamPrev->psNext = psStreamThis->psNext;
+ }
+ else
+ {
+ g_psStreamList = psStreamThis->psNext;
+ }
+
+ psStreamThis = 0;
+ }
+ else
+ {
+ psStreamPrev = psStreamThis;
+ psStreamThis = psStreamThis->psNext;
+ }
+ }
+
+ psLFThis = g_psLFBufferList;
+ psLFPrev = 0;
+
+ while (psLFThis)
+ {
+ if (psLFThis == psLFBuffer)
+ {
+ if (psLFPrev)
+ {
+ psLFPrev->psNext = psLFThis->psNext;
+ }
+ else
+ {
+ g_psLFBufferList = psLFThis->psNext;
+ }
+
+ psLFThis = 0;
+ }
+ else
+ {
+ psLFPrev = psLFThis;
+ psLFThis = psLFThis->psNext;
+ }
+ }
+
+
+ if (psStream->psCtrl->ui32CapMode & DEBUG_CAPMODE_HOTKEY)
+ {
+ DeactivateHotKeys();
+ }
+
+
+
+ if ((psStream->psCtrl->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
+ {
+ HostNonPageablePageFree(psStream->psCtrl);
+ HostNonPageablePageFree(psStream->pvBase);
+ HostNonPageablePageFree(psStream->psInitStream->pvBase);
+ }
+ else
+ {
+ HostNonPageablePageFree(psStream->psCtrl);
+ HostPageablePageFree(psStream->pvBase);
+ HostPageablePageFree(psStream->psInitStream->pvBase);
+ }
+
+ HostNonPageablePageFree(psStream->psInitStream);
+ HostNonPageablePageFree(psStream);
+ HostNonPageablePageFree(psLFBuffer);
+
+ if (g_psStreamList == 0)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"DBGDriv: Stream list now empty" ));
+ }
+
+ return;
+}
+
+IMG_VOID * IMG_CALLCONV DBGDrivFindStream(IMG_CHAR * pszName, IMG_BOOL bResetStream)
+{
+ PDBG_STREAM psStream;
+ PDBG_STREAM psThis;
+ IMG_UINT32 ui32Off;
+ IMG_BOOL bAreSame;
+
+ psStream = 0;
+
+ PVR_DPF((PVR_DBGDRIV_MESSAGE, "PDump client connecting to %s %s",
+ pszName,
+ (bResetStream == IMG_TRUE) ? "with reset" : "no reset"));
+
+
+
+ for (psThis = g_psStreamList; psThis != IMG_NULL; psThis = psThis->psNext)
+ {
+ bAreSame = IMG_TRUE;
+ ui32Off = 0;
+
+ if (strlen(psThis->szName) == strlen(pszName))
+ {
+ while ((psThis->szName[ui32Off] != 0) && (pszName[ui32Off] != 0) && (ui32Off < 128) && bAreSame)
+ {
+ if (psThis->szName[ui32Off] != pszName[ui32Off])
+ {
+ bAreSame = IMG_FALSE;
+ }
+
+ ui32Off++;
+ }
+ }
+ else
+ {
+ bAreSame = IMG_FALSE;
+ }
+
+ if (bAreSame)
+ {
+ psStream = psThis;
+ break;
+ }
+ }
+
+ if(bResetStream && psStream)
+ {
+ static IMG_CHAR szComment[] = "-- Init phase terminated\r\n";
+ psStream->psInitStream->ui32RPtr = 0;
+ psStream->ui32RPtr = 0;
+ psStream->ui32WPtr = 0;
+ psStream->ui32DataWritten = psStream->psInitStream->ui32DataWritten;
+ if (psStream->psCtrl->bInitPhaseComplete == IMG_FALSE)
+ {
+ if (psStream->psCtrl->ui32Flags & DEBUG_FLAGS_TEXTSTREAM)
+ {
+ DBGDrivWrite2(psStream, (IMG_UINT8 *)szComment, sizeof(szComment) - 1, 0x01);
+ }
+ psStream->psCtrl->bInitPhaseComplete = IMG_TRUE;
+ }
+
+ {
+
+
+ psStream->psInitStream->ui32InitPhaseWOff = psStream->psInitStream->ui32WPtr;
+ PVR_DPF((PVR_DBGDRIV_MESSAGE, "Set %s client marker bo %x, total bw %x",
+ psStream->szName,
+ psStream->psInitStream->ui32InitPhaseWOff,
+ psStream->psInitStream->ui32DataWritten ));
+ }
+ }
+
+ return((IMG_VOID *) psStream);
+}
+
+static void IMG_CALLCONV DBGDrivInvalidateStream(PDBG_STREAM psStream)
+{
+ IMG_CHAR pszErrorMsg[] = "**OUTOFMEM\n";
+ IMG_UINT32 ui32Space;
+ IMG_UINT32 ui32Off = 0;
+ IMG_UINT32 ui32WPtr = psStream->ui32WPtr;
+ IMG_PUINT8 pui8Buffer = (IMG_UINT8 *) psStream->pvBase;
+
+ PVR_DPF((PVR_DBG_ERROR, "DBGDrivInvalidateStream: An error occurred for stream %s\r\n", psStream->szName ));
+
+
+
+
+
+
+
+
+
+ ui32Space = SpaceInStream(psStream);
+
+
+ if(ui32Space > 0)
+ {
+ ui32Space--;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR, "DBGDrivInvalidateStream: Buffer full."));
+ }
+
+ while((pszErrorMsg[ui32Off] != 0) && (ui32Off < ui32Space))
+ {
+ pui8Buffer[ui32WPtr] = (IMG_UINT8)pszErrorMsg[ui32Off];
+ ui32Off++;
+ ui32WPtr++;
+ }
+ pui8Buffer[ui32WPtr++] = '\0';
+ psStream->ui32WPtr = ui32WPtr;
+
+
+ psStream->psCtrl->ui32Flags |= DEBUG_FLAGS_READONLY;
+}
+
+static IMG_VOID InvalidateAllStreams(IMG_VOID)
+{
+ PDBG_STREAM psStream = g_psStreamList;
+ while (psStream != IMG_NULL)
+ {
+ DBGDrivInvalidateStream(psStream);
+ psStream = psStream->psNext;
+ }
+ return;
+}
+
+
+
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteStringCM(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level)
+{
+
+
+ if (!StreamValidForWrite(psStream))
+ {
+ return(0xFFFFFFFFUL);
+ }
+
+
+
+ if (psStream->psCtrl->ui32CapMode & DEBUG_CAPMODE_FRAMED)
+ {
+ if ((psStream->psCtrl->ui32Flags & DEBUG_FLAGS_ENABLESAMPLE) == 0)
+ {
+ return(0);
+ }
+ }
+ else
+ {
+ if (psStream->psCtrl->ui32CapMode == DEBUG_CAPMODE_HOTKEY)
+ {
+ if ((psStream->psCtrl->ui32Current != g_ui32HotKeyFrame) || (g_bHotKeyPressed == IMG_FALSE))
+ {
+ return(0);
+ }
+ }
+ }
+
+ return(DBGDrivWriteString(psStream,pszString,ui32Level));
+
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level)
+{
+ IMG_UINT32 ui32Len;
+ IMG_UINT32 ui32Space;
+ IMG_UINT32 ui32WPtr;
+ IMG_UINT8 * pui8Buffer;
+
+
+
+ if (!StreamValidForWrite(psStream))
+ {
+ return(0xFFFFFFFFUL);
+ }
+
+
+
+ if ((psStream->psCtrl->ui32DebugLevel & ui32Level) == 0)
+ {
+ return(0xFFFFFFFFUL);
+ }
+
+
+
+
+ if ((psStream->psCtrl->ui32OutMode & DEBUG_OUTMODE_ASYNC) == 0)
+ {
+ if (psStream->psCtrl->ui32OutMode & DEBUG_OUTMODE_STANDARDDBG)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"%s: %s\r\n",psStream->szName, pszString));
+ }
+
+
+
+ if (psStream->psCtrl->ui32OutMode & DEBUG_OUTMODE_MONO)
+ {
+ MonoOut(psStream->szName,IMG_FALSE);
+ MonoOut(": ",IMG_FALSE);
+ MonoOut(pszString,IMG_TRUE);
+ }
+ }
+
+
+
+ if (
+ !(
+ ((psStream->psCtrl->ui32OutMode & DEBUG_OUTMODE_STREAMENABLE) != 0) ||
+ ((psStream->psCtrl->ui32OutMode & DEBUG_OUTMODE_ASYNC) != 0)
+ )
+ )
+ {
+ return(0xFFFFFFFFUL);
+ }
+
+
+
+ ui32Space=SpaceInStream(psStream);
+
+
+ if(ui32Space > 0)
+ {
+ ui32Space--;
+ }
+
+ ui32Len = 0;
+ ui32WPtr = psStream->ui32WPtr;
+ pui8Buffer = (IMG_UINT8 *) psStream->pvBase;
+
+ while((pszString[ui32Len] != 0) && (ui32Len < ui32Space))
+ {
+ pui8Buffer[ui32WPtr] = (IMG_UINT8)pszString[ui32Len];
+ ui32Len++;
+ ui32WPtr++;
+ if (ui32WPtr == psStream->ui32Size)
+ {
+ ui32WPtr = 0;
+ }
+ }
+
+ if (ui32Len < ui32Space)
+ {
+
+ pui8Buffer[ui32WPtr] = (IMG_UINT8)pszString[ui32Len];
+ ui32Len++;
+ ui32WPtr++;
+ if (ui32WPtr == psStream->ui32Size)
+ {
+ ui32WPtr = 0;
+ }
+
+
+ psStream->ui32WPtr = ui32WPtr;
+ psStream->ui32DataWritten+= ui32Len;
+ } else
+ {
+ ui32Len = 0;
+ }
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+ if (ui32Len)
+ {
+ HostSignalEvent(DBG_EVENT_STREAM_DATA);
+ }
+#endif
+
+ return(ui32Len);
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivReadString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Limit)
+{
+ IMG_UINT32 ui32OutLen;
+ IMG_UINT32 ui32Len;
+ IMG_UINT32 ui32Offset;
+ IMG_UINT8 *pui8Buff;
+
+
+
+ if (!StreamValidForRead(psStream))
+ {
+ return(0);
+ }
+
+
+
+ pui8Buff = (IMG_UINT8 *)psStream->pvBase;
+ ui32Offset = psStream->ui32RPtr;
+
+ if (psStream->ui32RPtr == psStream->ui32WPtr)
+ {
+ return(0);
+ }
+
+
+
+ ui32Len = 0;
+ while((pui8Buff[ui32Offset] != 0) && (ui32Offset != psStream->ui32WPtr))
+ {
+ ui32Offset++;
+ ui32Len++;
+
+
+
+ if (ui32Offset == psStream->ui32Size)
+ {
+ ui32Offset = 0;
+ }
+ }
+
+ ui32OutLen = ui32Len + 1;
+
+
+
+ if (ui32Len > ui32Limit)
+ {
+ return(0);
+ }
+
+
+
+ ui32Offset = psStream->ui32RPtr;
+ ui32Len = 0;
+
+ while ((pui8Buff[ui32Offset] != 0) && (ui32Len < ui32Limit))
+ {
+ pszString[ui32Len] = (IMG_CHAR)pui8Buff[ui32Offset];
+ ui32Offset++;
+ ui32Len++;
+
+
+
+ if (ui32Offset == psStream->ui32Size)
+ {
+ ui32Offset = 0;
+ }
+ }
+
+ pszString[ui32Len] = (IMG_CHAR)pui8Buff[ui32Offset];
+
+ psStream->ui32RPtr = ui32Offset + 1;
+
+ if (psStream->ui32RPtr == psStream->ui32Size)
+ {
+ psStream->ui32RPtr = 0;
+ }
+
+ return(ui32OutLen);
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivWrite(PDBG_STREAM psMainStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
+{
+ IMG_UINT32 ui32Space;
+ DBG_STREAM *psStream;
+
+
+
+ if (!StreamValidForWrite(psMainStream))
+ {
+ return(0xFFFFFFFFUL);
+ }
+
+
+
+ if ((psMainStream->psCtrl->ui32DebugLevel & ui32Level) == 0)
+ {
+ return(0xFFFFFFFFUL);
+ }
+
+
+
+ if (psMainStream->psCtrl->ui32CapMode & DEBUG_CAPMODE_FRAMED)
+ {
+ if ((psMainStream->psCtrl->ui32Flags & DEBUG_FLAGS_ENABLESAMPLE) == 0)
+ {
+
+ return(ui32InBuffSize);
+ }
+ }
+ else if (psMainStream->psCtrl->ui32CapMode == DEBUG_CAPMODE_HOTKEY)
+ {
+ if ((psMainStream->psCtrl->ui32Current != g_ui32HotKeyFrame) || (g_bHotKeyPressed == IMG_FALSE))
+ {
+
+ return(ui32InBuffSize);
+ }
+ }
+
+ if(psMainStream->psCtrl->bInitPhaseComplete)
+ {
+ psStream = psMainStream;
+ }
+ else
+ {
+ psStream = psMainStream->psInitStream;
+ }
+
+
+
+ ui32Space=SpaceInStream(psStream);
+
+ PVR_DPF((PVR_DBGDRIV_MESSAGE, "Recv %d b for %s: Roff = %x, WOff = %x",
+ ui32InBuffSize,
+ psStream->szName,
+ psStream->ui32RPtr,
+ psStream->ui32WPtr));
+
+
+
+ if ((psStream->psCtrl->ui32OutMode & DEBUG_OUTMODE_STREAMENABLE) == 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "DBGDrivWrite: buffer %x is disabled", (IMG_UINTPTR_T) psStream));
+ return(0);
+ }
+
+ if (ui32Space < 8)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "DBGDrivWrite: buffer %x is full", (IMG_UINTPTR_T) psStream));
+ return(0);
+ }
+
+
+
+ if (ui32Space <= (ui32InBuffSize + 4))
+ {
+ ui32InBuffSize = ui32Space - 8;
+ }
+
+
+
+ Write(psStream,(IMG_UINT8 *) &ui32InBuffSize,4);
+ Write(psStream,pui8InBuf,ui32InBuffSize);
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+ if (ui32InBuffSize)
+ {
+ HostSignalEvent(DBG_EVENT_STREAM_DATA);
+ }
+#endif
+ return(ui32InBuffSize);
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteCM(PDBG_STREAM psStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
+{
+
+
+ if (!StreamValidForWrite(psStream))
+ {
+ return(0xFFFFFFFFUL);
+ }
+
+
+
+ if (psStream->psCtrl->ui32CapMode & DEBUG_CAPMODE_FRAMED)
+ {
+ if ((psStream->psCtrl->ui32Flags & DEBUG_FLAGS_ENABLESAMPLE) == 0)
+ {
+
+ return(ui32InBuffSize);
+ }
+ }
+ else
+ {
+ if (psStream->psCtrl->ui32CapMode == DEBUG_CAPMODE_HOTKEY)
+ {
+ if ((psStream->psCtrl->ui32Current != g_ui32HotKeyFrame) || (g_bHotKeyPressed == IMG_FALSE))
+ {
+
+ return(ui32InBuffSize);
+ }
+ }
+ }
+
+ return(DBGDrivWrite2(psStream,pui8InBuf,ui32InBuffSize,ui32Level));
+}
+
+
+static IMG_UINT32 DBGDrivWritePersist(PDBG_STREAM psMainStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
+{
+ DBG_STREAM *psStream;
+ PVR_UNREFERENCED_PARAMETER(ui32Level);
+
+
+
+ if (!StreamValidForWrite(psMainStream))
+ {
+ return(0xFFFFFFFFUL);
+ }
+
+
+ psStream = psMainStream->psInitStream;
+ if(psStream->bCircularAllowed == IMG_TRUE)
+ {
+ PVR_DPF((PVR_DBG_WARNING, "DBGDrivWritePersist: Init phase is a circular buffer, some data may be lost"));
+ }
+
+ PVR_DPF((PVR_DBGDRIV_MESSAGE, "Append %x b to %s: Roff = %x, WOff = %x [bw = %x]",
+ ui32InBuffSize,
+ psStream->szName,
+ psStream->ui32RPtr,
+ psStream->ui32WPtr,
+ psStream->ui32DataWritten));
+
+ return( WriteExpandingBuffer(psStream, pui8InBuf, ui32InBuffSize) );
+ }
+
+IMG_UINT32 IMG_CALLCONV DBGDrivWrite2(PDBG_STREAM psMainStream,IMG_UINT8 * pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level)
+ {
+ DBG_STREAM *psStream;
+
+
+
+ if (!StreamValidForWrite(psMainStream))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "DBGDrivWrite2: stream not valid"));
+ return(0xFFFFFFFFUL);
+ }
+
+
+
+ if ((psMainStream->psCtrl->ui32DebugLevel & ui32Level) == 0)
+ {
+ return(0);
+ }
+
+ if(psMainStream->psCtrl->bInitPhaseComplete)
+ {
+ psStream = psMainStream;
+ }
+ else
+ {
+ psStream = psMainStream->psInitStream;
+ }
+
+ PVR_DPF((PVR_DBGDRIV_MESSAGE, "Recv(exp) %d b for %s: Roff = %x, WOff = %x",
+ ui32InBuffSize,
+ psStream->szName,
+ psStream->ui32RPtr,
+ psStream->ui32WPtr));
+
+ return( WriteExpandingBuffer(psStream, pui8InBuf, ui32InBuffSize) );
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivRead(PDBG_STREAM psMainStream, IMG_BOOL bReadInitBuffer, IMG_UINT32 ui32OutBuffSize,IMG_UINT8 * pui8OutBuf)
+{
+ IMG_UINT32 ui32Data;
+ DBG_STREAM *psStream;
+
+
+
+ if (!StreamValidForRead(psMainStream))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "DBGDrivRead: buffer %x is invalid", (IMG_UINTPTR_T) psMainStream));
+ return(0);
+ }
+
+ if(bReadInitBuffer)
+ {
+ psStream = psMainStream->psInitStream;
+ }
+ else
+ {
+ psStream = psMainStream;
+ }
+
+
+ if (psStream->ui32RPtr == psStream->ui32WPtr ||
+ ((psStream->ui32InitPhaseWOff > 0) &&
+ (psStream->ui32RPtr >= psStream->ui32InitPhaseWOff)) )
+ {
+ return(0);
+ }
+
+
+
+ if (psStream->ui32RPtr <= psStream->ui32WPtr)
+ {
+ ui32Data = psStream->ui32WPtr - psStream->ui32RPtr;
+ }
+ else
+ {
+ ui32Data = psStream->ui32WPtr + (psStream->ui32Size - psStream->ui32RPtr);
+ }
+
+
+
+ if ((psStream->ui32InitPhaseWOff > 0) &&
+ (psStream->ui32InitPhaseWOff < psStream->ui32WPtr))
+ {
+ ui32Data = psStream->ui32InitPhaseWOff - psStream->ui32RPtr;
+ }
+
+
+
+ if (ui32Data > ui32OutBuffSize)
+ {
+ ui32Data = ui32OutBuffSize;
+ }
+
+ PVR_DPF((PVR_DBGDRIV_MESSAGE, "Send %x b from %s: Roff = %x, WOff = %x",
+ ui32Data,
+ psStream->szName,
+ psStream->ui32RPtr,
+ psStream->ui32WPtr));
+
+
+
+ if ((psStream->ui32RPtr + ui32Data) > psStream->ui32Size)
+ {
+ IMG_UINT32 ui32B1 = psStream->ui32Size - psStream->ui32RPtr;
+ IMG_UINT32 ui32B2 = ui32Data - ui32B1;
+
+
+ HostMemCopy((IMG_VOID *) pui8OutBuf,
+ (IMG_VOID *)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32RPtr),
+ ui32B1);
+
+
+ HostMemCopy((IMG_VOID *)(pui8OutBuf + ui32B1),
+ psStream->pvBase,
+ ui32B2);
+
+
+ psStream->ui32RPtr = ui32B2;
+ }
+ else
+ {
+ HostMemCopy((IMG_VOID *) pui8OutBuf,
+ (IMG_VOID *)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32RPtr),
+ ui32Data);
+
+
+ psStream->ui32RPtr += ui32Data;
+
+
+ if (psStream->ui32RPtr == psStream->ui32Size)
+ {
+ psStream->ui32RPtr = 0;
+ }
+ }
+
+ return(ui32Data);
+}
+
+void IMG_CALLCONV DBGDrivSetCaptureMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode,IMG_UINT32 ui32Start,IMG_UINT32 ui32End,IMG_UINT32 ui32SampleRate)
+{
+
+
+ if (!StreamValid(psStream))
+ {
+ return;
+ }
+
+ psStream->psCtrl->ui32CapMode = ui32Mode;
+ psStream->psCtrl->ui32DefaultMode = ui32Mode;
+ psStream->psCtrl->ui32Start = ui32Start;
+ psStream->psCtrl->ui32End = ui32End;
+ psStream->psCtrl->ui32SampleRate = ui32SampleRate;
+
+
+
+ if (psStream->psCtrl->ui32CapMode & DEBUG_CAPMODE_HOTKEY)
+ {
+ ActivateHotKeys(psStream);
+ }
+}
+
+void IMG_CALLCONV DBGDrivSetOutputMode(PDBG_STREAM psStream,IMG_UINT32 ui32OutMode)
+{
+
+
+ if (!StreamValid(psStream))
+ {
+ return;
+ }
+
+ psStream->psCtrl->ui32OutMode = ui32OutMode;
+}
+
+void IMG_CALLCONV DBGDrivSetDebugLevel(PDBG_STREAM psStream,IMG_UINT32 ui32DebugLevel)
+{
+
+
+ if (!StreamValid(psStream))
+ {
+ return;
+ }
+
+ psStream->psCtrl->ui32DebugLevel = ui32DebugLevel;
+}
+
+void IMG_CALLCONV DBGDrivSetFrame(PDBG_STREAM psStream,IMG_UINT32 ui32Frame)
+{
+
+
+ if (!StreamValid(psStream))
+ {
+ return;
+ }
+
+ psStream->psCtrl->ui32Current = ui32Frame;
+
+ if ((ui32Frame >= psStream->psCtrl->ui32Start) &&
+ (ui32Frame <= psStream->psCtrl->ui32End) &&
+ (((ui32Frame - psStream->psCtrl->ui32Start) % psStream->psCtrl->ui32SampleRate) == 0))
+ {
+ psStream->psCtrl->ui32Flags |= DEBUG_FLAGS_ENABLESAMPLE;
+ }
+ else
+ {
+ psStream->psCtrl->ui32Flags &= ~DEBUG_FLAGS_ENABLESAMPLE;
+ }
+
+ if (g_bHotkeyMiddump)
+ {
+ if ((ui32Frame >= g_ui32HotkeyMiddumpStart) &&
+ (ui32Frame <= g_ui32HotkeyMiddumpEnd) &&
+ (((ui32Frame - g_ui32HotkeyMiddumpStart) % psStream->psCtrl->ui32SampleRate) == 0))
+ {
+ psStream->psCtrl->ui32Flags |= DEBUG_FLAGS_ENABLESAMPLE;
+ }
+ else
+ {
+ psStream->psCtrl->ui32Flags &= ~DEBUG_FLAGS_ENABLESAMPLE;
+ if (psStream->psCtrl->ui32Current > g_ui32HotkeyMiddumpEnd)
+ {
+ g_bHotkeyMiddump = IMG_FALSE;
+ }
+ }
+ }
+
+
+ if (g_bHotKeyRegistered)
+ {
+ g_bHotKeyRegistered = IMG_FALSE;
+
+ PVR_DPF((PVR_DBG_MESSAGE,"Hotkey pressed (%p)!\n",psStream));
+
+ if (!g_bHotKeyPressed)
+ {
+
+
+ g_ui32HotKeyFrame = psStream->psCtrl->ui32Current + 2;
+
+
+
+ g_bHotKeyPressed = IMG_TRUE;
+ }
+
+
+
+ if (((psStream->psCtrl->ui32CapMode & DEBUG_CAPMODE_FRAMED) != 0) &&
+ ((psStream->psCtrl->ui32CapMode & DEBUG_CAPMODE_HOTKEY) != 0))
+ {
+ if (!g_bHotkeyMiddump)
+ {
+
+ g_ui32HotkeyMiddumpStart = g_ui32HotKeyFrame + 1;
+ g_ui32HotkeyMiddumpEnd = 0xffffffff;
+ g_bHotkeyMiddump = IMG_TRUE;
+ PVR_DPF((PVR_DBG_MESSAGE,"Sampling every %d frame(s)\n", psStream->psCtrl->ui32SampleRate));
+ }
+ else
+ {
+
+ g_ui32HotkeyMiddumpEnd = g_ui32HotKeyFrame;
+ PVR_DPF((PVR_DBG_MESSAGE,"Turning off sampling\n"));
+ }
+ }
+
+ }
+
+
+
+ if (psStream->psCtrl->ui32Current > g_ui32HotKeyFrame)
+ {
+ g_bHotKeyPressed = IMG_FALSE;
+ }
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivGetFrame(PDBG_STREAM psStream)
+{
+
+
+ if (!StreamValid(psStream))
+ {
+ return(0);
+ }
+
+ return(psStream->psCtrl->ui32Current);
+}
+
+IMG_BOOL IMG_CALLCONV DBGDrivIsLastCaptureFrame(PDBG_STREAM psStream)
+{
+ IMG_UINT32 ui32NextFrame;
+
+
+
+ if (!StreamValid(psStream))
+ {
+ return IMG_FALSE;
+ }
+
+ if (psStream->psCtrl->ui32CapMode & DEBUG_CAPMODE_FRAMED)
+ {
+ ui32NextFrame = psStream->psCtrl->ui32Current + psStream->psCtrl->ui32SampleRate;
+ if (ui32NextFrame > psStream->psCtrl->ui32End)
+ {
+ return IMG_TRUE;
+ }
+ }
+ return IMG_FALSE;
+}
+
+IMG_BOOL IMG_CALLCONV DBGDrivIsCaptureFrame(PDBG_STREAM psStream, IMG_BOOL bCheckPreviousFrame)
+{
+ IMG_UINT32 ui32FrameShift = bCheckPreviousFrame ? 1UL : 0UL;
+
+
+
+ if (!StreamValid(psStream))
+ {
+ return IMG_FALSE;
+ }
+
+ if (psStream->psCtrl->ui32CapMode & DEBUG_CAPMODE_FRAMED)
+ {
+
+ if (g_bHotkeyMiddump)
+ {
+ if ((psStream->psCtrl->ui32Current >= (g_ui32HotkeyMiddumpStart - ui32FrameShift)) &&
+ (psStream->psCtrl->ui32Current <= (g_ui32HotkeyMiddumpEnd - ui32FrameShift)) &&
+ ((((psStream->psCtrl->ui32Current + ui32FrameShift) - g_ui32HotkeyMiddumpStart) % psStream->psCtrl->ui32SampleRate) == 0))
+ {
+ return IMG_TRUE;
+ }
+ }
+ else
+ {
+ if ((psStream->psCtrl->ui32Current >= (psStream->psCtrl->ui32Start - ui32FrameShift)) &&
+ (psStream->psCtrl->ui32Current <= (psStream->psCtrl->ui32End - ui32FrameShift)) &&
+ ((((psStream->psCtrl->ui32Current + ui32FrameShift) - psStream->psCtrl->ui32Start) % psStream->psCtrl->ui32SampleRate) == 0))
+ {
+ return IMG_TRUE;
+ }
+ }
+ }
+ else if (psStream->psCtrl->ui32CapMode == DEBUG_CAPMODE_HOTKEY)
+ {
+ if ((psStream->psCtrl->ui32Current == (g_ui32HotKeyFrame-ui32FrameShift)) && (g_bHotKeyPressed))
+ {
+ return IMG_TRUE;
+ }
+ }
+ return IMG_FALSE;
+}
+
+void IMG_CALLCONV DBGDrivOverrideMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode)
+{
+
+
+ if (!StreamValid(psStream))
+ {
+ return;
+ }
+
+ psStream->psCtrl->ui32CapMode = ui32Mode;
+}
+
+void IMG_CALLCONV DBGDrivDefaultMode(PDBG_STREAM psStream)
+{
+
+
+ if (!StreamValid(psStream))
+ {
+ return;
+ }
+
+ psStream->psCtrl->ui32CapMode = psStream->psCtrl->ui32DefaultMode;
+}
+
+IMG_VOID IMG_CALLCONV DBGDrivSetClientMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker)
+{
+
+
+ if (!StreamValid(psStream))
+ {
+ return;
+ }
+
+ psStream->ui32InitPhaseWOff = ui32Marker;
+}
+
+void IMG_CALLCONV DBGDrivSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker)
+{
+
+
+ if (!StreamValid(psStream))
+ {
+ return;
+ }
+
+ psStream->ui32Marker = ui32Marker;
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivGetMarker(PDBG_STREAM psStream)
+{
+
+
+ if (!StreamValid(psStream))
+ {
+ return 0;
+ }
+
+ return psStream->ui32Marker;
+}
+
+
+IMG_UINT32 IMG_CALLCONV DBGDrivGetStreamOffset(PDBG_STREAM psMainStream)
+{
+ PDBG_STREAM psStream;
+
+
+
+ if (!StreamValid(psMainStream))
+ {
+ return 0;
+ }
+
+ if(psMainStream->psCtrl->bInitPhaseComplete)
+ {
+ psStream = psMainStream;
+ }
+ else
+ {
+ psStream = psMainStream->psInitStream;
+ }
+
+ return psStream->ui32DataWritten;
+}
+
+IMG_VOID IMG_CALLCONV DBGDrivSetStreamOffset(PDBG_STREAM psMainStream, IMG_UINT32 ui32StreamOffset)
+{
+ PDBG_STREAM psStream;
+
+
+
+ if (!StreamValid(psMainStream))
+ {
+ return;
+ }
+
+ if(psMainStream->psCtrl->bInitPhaseComplete)
+ {
+ psStream = psMainStream;
+ }
+ else
+ {
+ psStream = psMainStream->psInitStream;
+ }
+
+ PVR_DPF((PVR_DBGDRIV_MESSAGE, "DBGDrivSetStreamOffset: %s set to %x b",
+ psStream->szName,
+ ui32StreamOffset));
+ psStream->ui32DataWritten = ui32StreamOffset;
+}
+
+IMG_PVOID IMG_CALLCONV DBGDrivGetServiceTable(IMG_VOID)
+{
+ return((IMG_PVOID)&g_sDBGKMServices);
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteLF(PDBG_STREAM psStream, IMG_UINT8 * pui8InBuf, IMG_UINT32 ui32InBuffSize, IMG_UINT32 ui32Level, IMG_UINT32 ui32Flags)
+{
+ PDBG_LASTFRAME_BUFFER psLFBuffer;
+
+
+
+ if (!StreamValidForWrite(psStream))
+ {
+ return(0xFFFFFFFFUL);
+ }
+
+
+
+ if ((psStream->psCtrl->ui32DebugLevel & ui32Level) == 0)
+ {
+ return(0xFFFFFFFFUL);
+ }
+
+
+
+ if ((psStream->psCtrl->ui32CapMode & DEBUG_CAPMODE_FRAMED) != 0)
+ {
+ if ((psStream->psCtrl->ui32Flags & DEBUG_FLAGS_ENABLESAMPLE) == 0)
+ {
+
+ return(ui32InBuffSize);
+ }
+ }
+ else if (psStream->psCtrl->ui32CapMode == DEBUG_CAPMODE_HOTKEY)
+ {
+ if ((psStream->psCtrl->ui32Current != g_ui32HotKeyFrame) || (g_bHotKeyPressed == IMG_FALSE))
+ {
+
+ return(ui32InBuffSize);
+ }
+ }
+
+ psLFBuffer = FindLFBuf(psStream);
+
+ if (ui32Flags & WRITELF_FLAGS_RESETBUF)
+ {
+
+
+ ui32InBuffSize = (ui32InBuffSize > LAST_FRAME_BUF_SIZE) ? LAST_FRAME_BUF_SIZE : ui32InBuffSize;
+ HostMemCopy((IMG_VOID *)psLFBuffer->ui8Buffer, (IMG_VOID *)pui8InBuf, ui32InBuffSize);
+ psLFBuffer->ui32BufLen = ui32InBuffSize;
+ }
+ else
+ {
+
+
+ ui32InBuffSize = ((psLFBuffer->ui32BufLen + ui32InBuffSize) > LAST_FRAME_BUF_SIZE) ? (LAST_FRAME_BUF_SIZE - psLFBuffer->ui32BufLen) : ui32InBuffSize;
+ HostMemCopy((IMG_VOID *)(&psLFBuffer->ui8Buffer[psLFBuffer->ui32BufLen]), (IMG_VOID *)pui8InBuf, ui32InBuffSize);
+ psLFBuffer->ui32BufLen += ui32InBuffSize;
+ }
+
+ return(ui32InBuffSize);
+}
+
+IMG_UINT32 IMG_CALLCONV DBGDrivReadLF(PDBG_STREAM psStream, IMG_UINT32 ui32OutBuffSize, IMG_UINT8 * pui8OutBuf)
+{
+ PDBG_LASTFRAME_BUFFER psLFBuffer;
+ IMG_UINT32 ui32Data;
+
+
+
+ if (!StreamValidForRead(psStream))
+ {
+ return(0);
+ }
+
+ psLFBuffer = FindLFBuf(psStream);
+
+
+
+ ui32Data = (ui32OutBuffSize < psLFBuffer->ui32BufLen) ? ui32OutBuffSize : psLFBuffer->ui32BufLen;
+
+
+
+ HostMemCopy((IMG_VOID *)pui8OutBuf, (IMG_VOID *)psLFBuffer->ui8Buffer, ui32Data);
+
+ return ui32Data;
+}
+
+IMG_VOID IMG_CALLCONV DBGDrivStartInitPhase(PDBG_STREAM psStream)
+{
+ psStream->psCtrl->bInitPhaseComplete = IMG_FALSE;
+}
+
+IMG_VOID IMG_CALLCONV DBGDrivStopInitPhase(PDBG_STREAM psStream)
+{
+ psStream->psCtrl->bInitPhaseComplete = IMG_TRUE;
+}
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+IMG_VOID IMG_CALLCONV DBGDrivWaitForEvent(DBG_EVENT eEvent)
+{
+ HostWaitForEvent(eEvent);
+}
+#endif
+
+IMG_BOOL ExpandStreamBuffer(PDBG_STREAM psStream, IMG_UINT32 ui32NewSize)
+{
+ IMG_VOID * pvNewBuf;
+ IMG_UINT32 ui32NewSizeInPages;
+ IMG_UINT32 ui32NewWOffset;
+ IMG_UINT32 ui32NewROffset;
+ IMG_UINT32 ui32SpaceInOldBuf;
+
+
+
+ if (psStream->ui32Size >= ui32NewSize)
+ {
+ return IMG_FALSE;
+ }
+
+
+
+ ui32SpaceInOldBuf = SpaceInStream(psStream);
+
+
+
+ ui32NewSizeInPages = ((ui32NewSize + 0xfffUL) & ~0xfffUL) / 4096UL;
+
+ if ((psStream->psCtrl->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
+ {
+ pvNewBuf = HostNonPageablePageAlloc(ui32NewSizeInPages);
+ }
+ else
+ {
+ pvNewBuf = HostPageablePageAlloc(ui32NewSizeInPages);
+ }
+
+ if (pvNewBuf == IMG_NULL)
+ {
+ return IMG_FALSE;
+ }
+
+ if(psStream->bCircularAllowed)
+ {
+
+
+
+ if (psStream->ui32RPtr <= psStream->ui32WPtr)
+ {
+
+
+ HostMemCopy(pvNewBuf,
+ (IMG_VOID *)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32RPtr),
+ psStream->ui32WPtr - psStream->ui32RPtr);
+ }
+ else
+ {
+ IMG_UINT32 ui32FirstCopySize;
+
+
+
+ ui32FirstCopySize = psStream->ui32Size - psStream->ui32RPtr;
+
+ HostMemCopy(pvNewBuf,
+ (IMG_VOID *)((IMG_UINTPTR_T)psStream->pvBase + psStream->ui32RPtr),
+ ui32FirstCopySize);
+
+
+
+ HostMemCopy((IMG_VOID *)((IMG_UINTPTR_T)pvNewBuf + ui32FirstCopySize),
+ (IMG_VOID *)(IMG_PBYTE)psStream->pvBase,
+ psStream->ui32WPtr);
+ }
+ ui32NewROffset = 0;
+ }
+ else
+ {
+
+ HostMemCopy(pvNewBuf, psStream->pvBase, psStream->ui32WPtr);
+ ui32NewROffset = psStream->ui32RPtr;
+ }
+
+
+
+
+ ui32NewWOffset = psStream->ui32Size - ui32SpaceInOldBuf;
+
+
+
+ if ((psStream->psCtrl->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
+ {
+ HostNonPageablePageFree(psStream->pvBase);
+ }
+ else
+ {
+ HostPageablePageFree(psStream->pvBase);
+ }
+
+
+
+ psStream->pvBase = pvNewBuf;
+ psStream->ui32RPtr = ui32NewROffset;
+ psStream->ui32WPtr = ui32NewWOffset;
+ psStream->ui32Size = ui32NewSizeInPages * 4096;
+
+ return IMG_TRUE;
+}
+
+IMG_UINT32 SpaceInStream(PDBG_STREAM psStream)
+{
+ IMG_UINT32 ui32Space;
+
+ if (psStream->bCircularAllowed)
+ {
+
+ if (psStream->ui32RPtr > psStream->ui32WPtr)
+ {
+ ui32Space = psStream->ui32RPtr - psStream->ui32WPtr;
+ }
+ else
+ {
+ ui32Space = psStream->ui32RPtr + (psStream->ui32Size - psStream->ui32WPtr);
+ }
+ }
+ else
+ {
+
+ ui32Space = psStream->ui32Size - psStream->ui32WPtr;
+ }
+
+ return ui32Space;
+}
+
+
+void DestroyAllStreams(void)
+{
+ while (g_psStreamList != IMG_NULL)
+ {
+ DBGDrivDestroyStream(g_psStreamList);
+ }
+ return;
+}
+
+PDBG_LASTFRAME_BUFFER FindLFBuf(PDBG_STREAM psStream)
+{
+ PDBG_LASTFRAME_BUFFER psLFBuffer;
+
+ psLFBuffer = g_psLFBufferList;
+
+ while (psLFBuffer)
+ {
+ if (psLFBuffer->psStream == psStream)
+ {
+ break;
+ }
+
+ psLFBuffer = psLFBuffer->psNext;
+ }
+
+ return psLFBuffer;
+}
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef _DBGDRIV_
+#define _DBGDRIV_
+
+#define BUFFER_SIZE 64*PAGESIZE
+
+#define DBGDRIV_VERSION 0x100
+#define MAX_PROCESSES 2
+#define BLOCK_USED 0x01
+#define BLOCK_LOCKED 0x02
+#define DBGDRIV_MONOBASE 0x000B0000
+
+
+extern IMG_VOID * g_pvAPIMutex;
+
+IMG_VOID * IMG_CALLCONV DBGDrivCreateStream(IMG_CHAR * pszName,
+ IMG_UINT32 ui32CapMode,
+ IMG_UINT32 ui32OutMode,
+ IMG_UINT32 ui32Flags,
+ IMG_UINT32 ui32Pages);
+IMG_VOID IMG_CALLCONV DBGDrivDestroyStream(PDBG_STREAM psStream);
+IMG_VOID * IMG_CALLCONV DBGDrivFindStream(IMG_CHAR * pszName, IMG_BOOL bResetStream);
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level);
+IMG_UINT32 IMG_CALLCONV DBGDrivReadString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Limit);
+IMG_UINT32 IMG_CALLCONV DBGDrivWrite(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+IMG_UINT32 IMG_CALLCONV DBGDrivWrite2(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+IMG_UINT32 IMG_CALLCONV DBGDrivRead(PDBG_STREAM psStream, IMG_BOOL bReadInitBuffer, IMG_UINT32 ui32OutBufferSize,IMG_UINT8 *pui8OutBuf);
+IMG_VOID IMG_CALLCONV DBGDrivSetCaptureMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode,IMG_UINT32 ui32Start,IMG_UINT32 ui32Stop,IMG_UINT32 ui32SampleRate);
+IMG_VOID IMG_CALLCONV DBGDrivSetOutputMode(PDBG_STREAM psStream,IMG_UINT32 ui32OutMode);
+IMG_VOID IMG_CALLCONV DBGDrivSetDebugLevel(PDBG_STREAM psStream,IMG_UINT32 ui32DebugLevel);
+IMG_VOID IMG_CALLCONV DBGDrivSetFrame(PDBG_STREAM psStream,IMG_UINT32 ui32Frame);
+IMG_UINT32 IMG_CALLCONV DBGDrivGetFrame(PDBG_STREAM psStream);
+IMG_VOID IMG_CALLCONV DBGDrivOverrideMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode);
+IMG_VOID IMG_CALLCONV DBGDrivDefaultMode(PDBG_STREAM psStream);
+IMG_PVOID IMG_CALLCONV DBGDrivGetServiceTable(IMG_VOID);
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteStringCM(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level);
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteCM(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+IMG_VOID IMG_CALLCONV DBGDrivSetClientMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker);
+IMG_VOID IMG_CALLCONV DBGDrivSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker);
+IMG_UINT32 IMG_CALLCONV DBGDrivGetMarker(PDBG_STREAM psStream);
+IMG_BOOL IMG_CALLCONV DBGDrivIsLastCaptureFrame(PDBG_STREAM psStream);
+IMG_BOOL IMG_CALLCONV DBGDrivIsCaptureFrame(PDBG_STREAM psStream, IMG_BOOL bCheckPreviousFrame);
+IMG_UINT32 IMG_CALLCONV DBGDrivWriteLF(PDBG_STREAM psStream, IMG_UINT8 *pui8InBuf, IMG_UINT32 ui32InBuffSize, IMG_UINT32 ui32Level, IMG_UINT32 ui32Flags);
+IMG_UINT32 IMG_CALLCONV DBGDrivReadLF(PDBG_STREAM psStream, IMG_UINT32 ui32OutBuffSize, IMG_UINT8 *pui8OutBuf);
+IMG_VOID IMG_CALLCONV DBGDrivStartInitPhase(PDBG_STREAM psStream);
+IMG_VOID IMG_CALLCONV DBGDrivStopInitPhase(PDBG_STREAM psStream);
+IMG_UINT32 IMG_CALLCONV DBGDrivGetStreamOffset(PDBG_STREAM psStream);
+IMG_VOID IMG_CALLCONV DBGDrivSetStreamOffset(PDBG_STREAM psStream, IMG_UINT32 ui32StreamOffset);
+IMG_VOID IMG_CALLCONV DBGDrivWaitForEvent(DBG_EVENT eEvent);
+
+IMG_VOID DestroyAllStreams(IMG_VOID);
+
+IMG_UINT32 AtoI(IMG_CHAR *szIn);
+
+IMG_VOID HostMemSet(IMG_VOID *pvDest,IMG_UINT8 ui8Value,IMG_UINT32 ui32Size);
+IMG_VOID HostMemCopy(IMG_VOID *pvDest,IMG_VOID *pvSrc,IMG_UINT32 ui32Size);
+IMG_VOID MonoOut(IMG_CHAR * pszString,IMG_BOOL bNewLine);
+
+IMG_SID PStream2SID(PDBG_STREAM psStream);
+PDBG_STREAM SID2PStream(IMG_SID hStream);
+IMG_BOOL AddSIDEntry(PDBG_STREAM psStream);
+IMG_BOOL RemoveSIDEntry(PDBG_STREAM psStream);
+
+IMG_VOID * IMG_CALLCONV ExtDBGDrivCreateStream(IMG_CHAR * pszName, IMG_UINT32 ui32CapMode, IMG_UINT32 ui32OutMode, IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size);
+IMG_VOID IMG_CALLCONV ExtDBGDrivDestroyStream(PDBG_STREAM psStream);
+IMG_VOID * IMG_CALLCONV ExtDBGDrivFindStream(IMG_CHAR * pszName, IMG_BOOL bResetStream);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivReadString(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Limit);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWrite(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivRead(PDBG_STREAM psStream, IMG_BOOL bReadInitBuffer, IMG_UINT32 ui32OutBuffSize,IMG_UINT8 *pui8OutBuf);
+IMG_VOID IMG_CALLCONV ExtDBGDrivSetCaptureMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode,IMG_UINT32 ui32Start,IMG_UINT32 ui32End,IMG_UINT32 ui32SampleRate);
+IMG_VOID IMG_CALLCONV ExtDBGDrivSetOutputMode(PDBG_STREAM psStream,IMG_UINT32 ui32OutMode);
+IMG_VOID IMG_CALLCONV ExtDBGDrivSetDebugLevel(PDBG_STREAM psStream,IMG_UINT32 ui32DebugLevel);
+IMG_VOID IMG_CALLCONV ExtDBGDrivSetFrame(PDBG_STREAM psStream,IMG_UINT32 ui32Frame);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetFrame(PDBG_STREAM psStream);
+IMG_VOID IMG_CALLCONV ExtDBGDrivOverrideMode(PDBG_STREAM psStream,IMG_UINT32 ui32Mode);
+IMG_VOID IMG_CALLCONV ExtDBGDrivDefaultMode(PDBG_STREAM psStream);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWrite2(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteStringCM(PDBG_STREAM psStream,IMG_CHAR * pszString,IMG_UINT32 ui32Level);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteCM(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+IMG_VOID IMG_CALLCONV ExtDBGDrivSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetMarker(PDBG_STREAM psStream);
+IMG_VOID IMG_CALLCONV ExtDBGDrivStartInitPhase(PDBG_STREAM psStream);
+IMG_VOID IMG_CALLCONV ExtDBGDrivStopInitPhase(PDBG_STREAM psStream);
+IMG_BOOL IMG_CALLCONV ExtDBGDrivIsLastCaptureFrame(PDBG_STREAM psStream);
+IMG_BOOL IMG_CALLCONV ExtDBGDrivIsCaptureFrame(PDBG_STREAM psStream, IMG_BOOL bCheckPreviousFrame);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWriteLF(PDBG_STREAM psStream, IMG_UINT8 *pui8InBuf, IMG_UINT32 ui32InBuffSize, IMG_UINT32 ui32Level, IMG_UINT32 ui32Flags);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivReadLF(PDBG_STREAM psStream, IMG_UINT32 ui32OutBuffSize, IMG_UINT8 *pui8OutBuf);
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivGetStreamOffset(PDBG_STREAM psStream);
+IMG_VOID IMG_CALLCONV ExtDBGDrivSetStreamOffset(PDBG_STREAM psStream, IMG_UINT32 ui32StreamOffset);
+IMG_VOID IMG_CALLCONV ExtDBGDrivWaitForEvent(DBG_EVENT eEvent);
+IMG_VOID IMG_CALLCONV ExtDBGDrivSetConnectNotifier(DBGKM_CONNECT_NOTIFIER fn_notifier);
+
+IMG_UINT32 IMG_CALLCONV ExtDBGDrivWritePersist(PDBG_STREAM psStream,IMG_UINT8 *pui8InBuf,IMG_UINT32 ui32InBuffSize,IMG_UINT32 ui32Level);
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef _IOCTL_
+#define _IOCTL_
+
+#define MAX_DBGVXD_W32_API 25
+
+extern IMG_UINT32 (*g_DBGDrivProc[MAX_DBGVXD_W32_API])(IMG_VOID *, IMG_VOID *);
+
+#endif
--- /dev/null
+/**********************************************************************
+ *
+ * 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 "img_defs.h"
+#include "dbgdrvif.h"
+#include "dbgdriv.h"
+
+#define MAX_SID_ENTRIES 8
+
+typedef struct _SID_INFO
+{
+ PDBG_STREAM psStream;
+} SID_INFO, *PSID_INFO;
+
+static SID_INFO gaSID_Xlat_Table[MAX_SID_ENTRIES];
+
+IMG_SID PStream2SID(PDBG_STREAM psStream)
+{
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ IMG_INT32 iIdx;
+
+ for (iIdx = 0; iIdx < MAX_SID_ENTRIES; iIdx++)
+ {
+ if (psStream == gaSID_Xlat_Table[iIdx].psStream)
+ {
+
+ return (IMG_SID)iIdx+1;
+ }
+ }
+ }
+
+ return (IMG_SID)0;
+}
+
+
+PDBG_STREAM SID2PStream(IMG_SID hStream)
+{
+
+ IMG_INT32 iIdx = (IMG_INT32)hStream-1;
+
+ if (iIdx >= 0 && iIdx < MAX_SID_ENTRIES)
+ {
+ return gaSID_Xlat_Table[iIdx].psStream;
+ }
+ else
+ {
+ return (PDBG_STREAM)IMG_NULL;
+ }
+}
+
+
+IMG_BOOL AddSIDEntry(PDBG_STREAM psStream)
+{
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ IMG_INT32 iIdx;
+
+ for (iIdx = 0; iIdx < MAX_SID_ENTRIES; iIdx++)
+ {
+ if (psStream == gaSID_Xlat_Table[iIdx].psStream)
+ {
+
+ return IMG_TRUE;
+ }
+
+ if (gaSID_Xlat_Table[iIdx].psStream == (PDBG_STREAM)IMG_NULL)
+ {
+
+ gaSID_Xlat_Table[iIdx].psStream = psStream;
+ return IMG_TRUE;
+ }
+ }
+ }
+
+ return IMG_FALSE;
+}
+
+IMG_BOOL RemoveSIDEntry(PDBG_STREAM psStream)
+{
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ IMG_INT32 iIdx;
+
+ for (iIdx = 0; iIdx < MAX_SID_ENTRIES; iIdx++)
+ {
+ if (psStream == gaSID_Xlat_Table[iIdx].psStream)
+ {
+ gaSID_Xlat_Table[iIdx].psStream = (PDBG_STREAM)IMG_NULL;
+ return IMG_TRUE;
+ }
+ }
+ }
+
+ return IMG_FALSE;
+}
+
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef _HOSTFUNC_
+#define _HOSTFUNC_
+
+#define HOST_PAGESIZE (4096)
+#define DBG_MEMORY_INITIALIZER (0xe2)
+
+IMG_UINT32 HostReadRegistryDWORDFromString(IMG_CHAR *pcKey, IMG_CHAR *pcValueName, IMG_UINT32 *pui32Data);
+
+IMG_VOID * HostPageablePageAlloc(IMG_UINT32 ui32Pages);
+IMG_VOID HostPageablePageFree(IMG_VOID * pvBase);
+IMG_VOID * HostNonPageablePageAlloc(IMG_UINT32 ui32Pages);
+IMG_VOID HostNonPageablePageFree(IMG_VOID * pvBase);
+
+IMG_VOID * HostMapKrnBufIntoUser(IMG_VOID * pvKrnAddr, IMG_UINT32 ui32Size, IMG_VOID * *ppvMdl);
+IMG_VOID HostUnMapKrnBufFromUser(IMG_VOID * pvUserAddr, IMG_VOID * pvMdl, IMG_VOID * pvProcess);
+
+IMG_VOID HostCreateRegDeclStreams(IMG_VOID);
+
+IMG_VOID * HostCreateMutex(IMG_VOID);
+IMG_VOID HostAquireMutex(IMG_VOID * pvMutex);
+IMG_VOID HostReleaseMutex(IMG_VOID * pvMutex);
+IMG_VOID HostDestroyMutex(IMG_VOID * pvMutex);
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+IMG_INT32 HostCreateEventObjects(IMG_VOID);
+IMG_VOID HostWaitForEvent(DBG_EVENT eEvent);
+IMG_VOID HostSignalEvent(DBG_EVENT eEvent);
+IMG_VOID HostDestroyEventObjects(IMG_VOID);
+#endif
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+
+#if !defined(LINUX)
+#include <ntddk.h>
+#include <windef.h>
+#endif
+
+#include "img_types.h"
+#include "pvr_debug.h"
+#include "dbgdrvif.h"
+#include "dbgdriv.h"
+#include "hotkey.h"
+#include "hostfunc.h"
+
+
+
+
+
+IMG_UINT32 g_ui32HotKeyFrame = 0xFFFFFFFF;
+IMG_BOOL g_bHotKeyPressed = IMG_FALSE;
+IMG_BOOL g_bHotKeyRegistered = IMG_FALSE;
+
+PRIVATEHOTKEYDATA g_PrivateHotKeyData;
+
+
+IMG_VOID ReadInHotKeys(IMG_VOID)
+{
+ g_PrivateHotKeyData.ui32ScanCode = 0x58;
+ g_PrivateHotKeyData.ui32ShiftState = 0x0;
+
+
+
+#if 0
+ if (_RegOpenKey(HKEY_LOCAL_MACHINE,pszRegPath,&hKey) == ERROR_SUCCESS)
+ {
+
+
+ QueryReg(hKey,"ui32ScanCode",&g_PrivateHotKeyData.ui32ScanCode);
+ QueryReg(hKey,"ui32ShiftState",&g_PrivateHotKeyData.ui32ShiftState);
+ }
+#else
+ HostReadRegistryDWORDFromString("DEBUG\\Streams", "ui32ScanCode" , &g_PrivateHotKeyData.ui32ScanCode);
+ HostReadRegistryDWORDFromString("DEBUG\\Streams", "ui32ShiftState", &g_PrivateHotKeyData.ui32ShiftState);
+#endif
+}
+
+IMG_VOID RegisterKeyPressed(IMG_UINT32 dwui32ScanCode, PHOTKEYINFO pInfo)
+{
+ PDBG_STREAM psStream;
+
+ PVR_UNREFERENCED_PARAMETER(pInfo);
+
+ if (dwui32ScanCode == g_PrivateHotKeyData.ui32ScanCode)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"PDUMP Hotkey pressed !\n"));
+
+ psStream = (PDBG_STREAM) g_PrivateHotKeyData.sHotKeyInfo.pvStream;
+
+ if (!g_bHotKeyPressed)
+ {
+
+
+ g_ui32HotKeyFrame = psStream->psCtrl->ui32Current + 2;
+
+
+
+ g_bHotKeyPressed = IMG_TRUE;
+ }
+ }
+}
+
+IMG_VOID ActivateHotKeys(PDBG_STREAM psStream)
+{
+
+
+ ReadInHotKeys();
+
+
+
+ if (!g_PrivateHotKeyData.sHotKeyInfo.hHotKey)
+ {
+ if (g_PrivateHotKeyData.ui32ScanCode != 0)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"Activate HotKey for PDUMP.\n"));
+
+
+
+ g_PrivateHotKeyData.sHotKeyInfo.pvStream = psStream;
+
+ DefineHotKey(g_PrivateHotKeyData.ui32ScanCode, g_PrivateHotKeyData.ui32ShiftState, &g_PrivateHotKeyData.sHotKeyInfo);
+ }
+ else
+ {
+ g_PrivateHotKeyData.sHotKeyInfo.hHotKey = 0;
+ }
+ }
+}
+
+IMG_VOID DeactivateHotKeys(IMG_VOID)
+{
+ if (g_PrivateHotKeyData.sHotKeyInfo.hHotKey != 0)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE,"Deactivate HotKey.\n"));
+
+ RemoveHotKey(g_PrivateHotKeyData.sHotKeyInfo.hHotKey);
+ g_PrivateHotKeyData.sHotKeyInfo.hHotKey = 0;
+ }
+}
+
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+#ifndef _HOTKEY_
+#define _HOTKEY_
+
+
+typedef struct _hotkeyinfo
+{
+ IMG_UINT8 ui8ScanCode;
+ IMG_UINT8 ui8Type;
+ IMG_UINT8 ui8Flag;
+ IMG_UINT8 ui8Filler1;
+ IMG_UINT32 ui32ShiftState;
+ IMG_UINT32 ui32HotKeyProc;
+ IMG_VOID *pvStream;
+ IMG_UINT32 hHotKey;
+} HOTKEYINFO, *PHOTKEYINFO;
+
+typedef struct _privatehotkeydata
+{
+ IMG_UINT32 ui32ScanCode;
+ IMG_UINT32 ui32ShiftState;
+ HOTKEYINFO sHotKeyInfo;
+} PRIVATEHOTKEYDATA, *PPRIVATEHOTKEYDATA;
+
+
+IMG_VOID ReadInHotKeys (IMG_VOID);
+IMG_VOID ActivateHotKeys(PDBG_STREAM psStream);
+IMG_VOID DeactivateHotKeys(IMG_VOID);
+
+IMG_VOID RemoveHotKey (IMG_UINT32 hHotKey);
+IMG_VOID DefineHotKey (IMG_UINT32 ui32ScanCode, IMG_UINT32 ui32ShiftState, PHOTKEYINFO psInfo);
+IMG_VOID RegisterKeyPressed (IMG_UINT32 ui32ScanCode, PHOTKEYINFO psInfo);
+
+#endif
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+
+
+#ifdef LINUX
+#include <asm/uaccess.h>
+#endif
+
+#include "img_types.h"
+#include "dbgdrvif.h"
+#include "dbgdriv.h"
+#include "hotkey.h"
+#include "dbgdriv_ioctl.h"
+
+
+static IMG_UINT32 DBGDIOCDrivCreateStream(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_IN_CREATESTREAM psIn;
+ IMG_VOID * *ppvOut;
+ #ifdef LINUX
+ static IMG_CHAR name[32];
+ #endif
+
+ psIn = (PDBG_IN_CREATESTREAM) pvInBuffer;
+ ppvOut = (IMG_VOID * *) pvOutBuffer;
+
+ #ifdef LINUX
+
+ if(copy_from_user(name, psIn->u.pszName, 32) != 0)
+ {
+ return IMG_FALSE;
+ }
+
+ *ppvOut = ExtDBGDrivCreateStream(name, psIn->ui32CapMode, psIn->ui32OutMode, 0, psIn->ui32Pages);
+
+ #else
+ *ppvOut = ExtDBGDrivCreateStream(psIn->u.pszName, psIn->ui32CapMode, psIn->ui32OutMode, DEBUG_FLAGS_NO_BUF_EXPANDSION, psIn->ui32Pages);
+ #endif
+
+
+ return(IMG_TRUE);
+}
+
+static IMG_UINT32 DBGDIOCDrivDestroyStream(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_STREAM *ppsStream;
+ PDBG_STREAM psStream;
+
+ ppsStream = (PDBG_STREAM *) pvInBuffer;
+ psStream = (PDBG_STREAM) *ppsStream;
+
+ PVR_UNREFERENCED_PARAMETER( pvOutBuffer);
+
+ ExtDBGDrivDestroyStream(psStream);
+
+ return(IMG_TRUE);
+}
+
+static IMG_UINT32 DBGDIOCDrivGetStream(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_IN_FINDSTREAM psParams;
+ IMG_SID * phStream;
+
+ psParams = (PDBG_IN_FINDSTREAM)pvInBuffer;
+ phStream = (IMG_SID *)pvOutBuffer;
+
+ *phStream = PStream2SID(ExtDBGDrivFindStream(psParams->u.pszName, psParams->bResetStream));
+
+ return(IMG_TRUE);
+}
+
+static IMG_UINT32 DBGDIOCDrivWriteString(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_IN_WRITESTRING psParams;
+ IMG_UINT32 *pui32OutLen;
+ PDBG_STREAM psStream;
+
+ psParams = (PDBG_IN_WRITESTRING) pvInBuffer;
+ pui32OutLen = (IMG_UINT32 *) pvOutBuffer;
+
+ psStream = SID2PStream(psParams->hStream);
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ *pui32OutLen = ExtDBGDrivWriteString(psStream,psParams->u.pszString,psParams->ui32Level);
+ return(IMG_TRUE);
+ }
+ else
+ {
+
+ *pui32OutLen = 0;
+ return(IMG_FALSE);
+ }
+}
+
+static IMG_UINT32 DBGDIOCDrivWriteStringCM(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_IN_WRITESTRING psParams;
+ IMG_UINT32 *pui32OutLen;
+ PDBG_STREAM psStream;
+
+ psParams = (PDBG_IN_WRITESTRING) pvInBuffer;
+ pui32OutLen = (IMG_UINT32 *) pvOutBuffer;
+
+ psStream = SID2PStream(psParams->hStream);
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ *pui32OutLen = ExtDBGDrivWriteStringCM(psStream,psParams->u.pszString,psParams->ui32Level);
+ return(IMG_TRUE);
+ }
+ else
+ {
+
+ *pui32OutLen = 0;
+ return(IMG_FALSE);
+ }
+}
+
+static IMG_UINT32 DBGDIOCDrivReadString(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ IMG_UINT32 * pui32OutLen;
+ PDBG_IN_READSTRING psParams;
+ PDBG_STREAM psStream;
+
+ psParams = (PDBG_IN_READSTRING) pvInBuffer;
+ pui32OutLen = (IMG_UINT32 *) pvOutBuffer;
+
+ psStream = SID2PStream(psParams->hStream);
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ *pui32OutLen = ExtDBGDrivReadString(psStream,
+ psParams->u.pszString,psParams->ui32StringLen);
+ return(IMG_TRUE);
+ }
+ else
+ {
+
+ *pui32OutLen = 0;
+ return(IMG_FALSE);
+ }
+}
+
+static IMG_UINT32 DBGDIOCDrivWrite(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ IMG_UINT32 * pui32BytesCopied;
+ PDBG_IN_WRITE psInParams;
+ PDBG_STREAM psStream;
+
+ psInParams = (PDBG_IN_WRITE) pvInBuffer;
+ pui32BytesCopied = (IMG_UINT32 *) pvOutBuffer;
+
+ psStream = SID2PStream(psInParams->hStream);
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ *pui32BytesCopied = ExtDBGDrivWrite(psStream,
+ psInParams->u.pui8InBuffer,
+ psInParams->ui32TransferSize,
+ psInParams->ui32Level);
+ return(IMG_TRUE);
+ }
+ else
+ {
+
+ *pui32BytesCopied = 0;
+ return(IMG_FALSE);
+ }
+}
+
+static IMG_UINT32 DBGDIOCDrivWrite2(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ IMG_UINT32 * pui32BytesCopied;
+ PDBG_IN_WRITE psInParams;
+ PDBG_STREAM psStream;
+
+ psInParams = (PDBG_IN_WRITE) pvInBuffer;
+ pui32BytesCopied = (IMG_UINT32 *) pvOutBuffer;
+
+ psStream = SID2PStream(psInParams->hStream);
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ *pui32BytesCopied = ExtDBGDrivWrite2(psStream,
+ psInParams->u.pui8InBuffer,
+ psInParams->ui32TransferSize,
+ psInParams->ui32Level);
+ return(IMG_TRUE);
+ }
+ else
+ {
+
+ *pui32BytesCopied = 0;
+ return(IMG_FALSE);
+ }
+}
+
+static IMG_UINT32 DBGDIOCDrivWriteCM(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ IMG_UINT32 * pui32BytesCopied;
+ PDBG_IN_WRITE psInParams;
+ PDBG_STREAM psStream;
+
+ psInParams = (PDBG_IN_WRITE) pvInBuffer;
+ pui32BytesCopied = (IMG_UINT32 *) pvOutBuffer;
+
+ psStream = SID2PStream(psInParams->hStream);
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ *pui32BytesCopied = ExtDBGDrivWriteCM(psStream,
+ psInParams->u.pui8InBuffer,
+ psInParams->ui32TransferSize,
+ psInParams->ui32Level);
+ return(IMG_TRUE);
+ }
+ else
+ {
+
+ *pui32BytesCopied = 0;
+ return(IMG_FALSE);
+ }
+}
+
+static IMG_UINT32 DBGDIOCDrivRead(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ IMG_UINT32 * pui32BytesCopied;
+ PDBG_IN_READ psInParams;
+ PDBG_STREAM psStream;
+
+ psInParams = (PDBG_IN_READ) pvInBuffer;
+ pui32BytesCopied = (IMG_UINT32 *) pvOutBuffer;
+
+ psStream = SID2PStream(psInParams->hStream);
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ *pui32BytesCopied = ExtDBGDrivRead(psStream,
+ psInParams->bReadInitBuffer,
+ psInParams->ui32OutBufferSize,
+ psInParams->u.pui8OutBuffer);
+ return(IMG_TRUE);
+ }
+ else
+ {
+
+ *pui32BytesCopied = 0;
+ return(IMG_FALSE);
+ }
+}
+
+static IMG_UINT32 DBGDIOCDrivSetCaptureMode(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_IN_SETDEBUGMODE psParams;
+ PDBG_STREAM psStream;
+
+ psParams = (PDBG_IN_SETDEBUGMODE) pvInBuffer;
+ PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+ psStream = SID2PStream(psParams->hStream);
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ ExtDBGDrivSetCaptureMode(psStream,
+ psParams->ui32Mode,
+ psParams->ui32Start,
+ psParams->ui32End,
+ psParams->ui32SampleRate);
+ return(IMG_TRUE);
+ }
+ else
+ {
+
+ return(IMG_FALSE);
+ }
+}
+
+static IMG_UINT32 DBGDIOCDrivSetOutMode(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_IN_SETDEBUGOUTMODE psParams;
+ PDBG_STREAM psStream;
+
+ psParams = (PDBG_IN_SETDEBUGOUTMODE) pvInBuffer;
+ PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+ psStream = SID2PStream(psParams->hStream);
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ ExtDBGDrivSetOutputMode(psStream,psParams->ui32Mode);
+ return(IMG_TRUE);
+ }
+ else
+ {
+
+ return(IMG_FALSE);
+ }
+}
+
+static IMG_UINT32 DBGDIOCDrivSetDebugLevel(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_IN_SETDEBUGLEVEL psParams;
+ PDBG_STREAM psStream;
+
+ psParams = (PDBG_IN_SETDEBUGLEVEL) pvInBuffer;
+ PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+ psStream = SID2PStream(psParams->hStream);
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ ExtDBGDrivSetDebugLevel(psStream,psParams->ui32Level);
+ return(IMG_TRUE);
+ }
+ else
+ {
+
+ return(IMG_FALSE);
+ }
+}
+
+static IMG_UINT32 DBGDIOCDrivSetFrame(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_IN_SETFRAME psParams;
+ PDBG_STREAM psStream;
+
+ psParams = (PDBG_IN_SETFRAME) pvInBuffer;
+ PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+ psStream = SID2PStream(psParams->hStream);
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ ExtDBGDrivSetFrame(psStream,psParams->ui32Frame);
+ return(IMG_TRUE);
+ }
+ else
+ {
+
+ return(IMG_FALSE);
+ }
+}
+
+static IMG_UINT32 DBGDIOCDrivGetFrame(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_STREAM psStream;
+ IMG_UINT32 *pui32Current;
+
+ pui32Current = (IMG_UINT32 *) pvOutBuffer;
+ psStream = SID2PStream(*(IMG_SID *)pvInBuffer);
+
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ *pui32Current = ExtDBGDrivGetFrame(psStream);
+ return(IMG_TRUE);
+ }
+ else
+ {
+
+ *pui32Current = 0;
+ return(IMG_FALSE);
+ }
+}
+
+static IMG_UINT32 DBGDIOCDrivIsCaptureFrame(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_IN_ISCAPTUREFRAME psParams;
+ IMG_UINT32 * pui32Current;
+ PDBG_STREAM psStream;
+
+ psParams = (PDBG_IN_ISCAPTUREFRAME) pvInBuffer;
+ pui32Current = (IMG_UINT32 *) pvOutBuffer;
+
+ psStream = SID2PStream(psParams->hStream);
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ *pui32Current = ExtDBGDrivIsCaptureFrame(psStream,
+ psParams->bCheckPreviousFrame);
+ return(IMG_TRUE);
+ }
+ else
+ {
+
+ *pui32Current = 0;
+ return(IMG_FALSE);
+ }
+}
+
+static IMG_UINT32 DBGDIOCDrivOverrideMode(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_IN_OVERRIDEMODE psParams;
+ PDBG_STREAM psStream;
+
+ psParams = (PDBG_IN_OVERRIDEMODE) pvInBuffer;
+ PVR_UNREFERENCED_PARAMETER( pvOutBuffer);
+
+ psStream = SID2PStream(psParams->hStream);
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ ExtDBGDrivOverrideMode(psStream,psParams->ui32Mode);
+ return(IMG_TRUE);
+ }
+ else
+ {
+
+ return(IMG_FALSE);
+ }
+}
+
+static IMG_UINT32 DBGDIOCDrivDefaultMode(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_STREAM psStream;
+
+ PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+ psStream = SID2PStream(*(IMG_SID *)pvInBuffer);
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ ExtDBGDrivDefaultMode(psStream);
+ return(IMG_TRUE);
+ }
+ else
+ {
+
+ return(IMG_FALSE);
+ }
+}
+
+static IMG_UINT32 DBGDIOCDrivSetMarker(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_IN_SETMARKER psParams;
+ PDBG_STREAM psStream;
+
+ psParams = (PDBG_IN_SETMARKER) pvInBuffer;
+ PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+ psStream = SID2PStream(psParams->hStream);
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ ExtDBGDrivSetMarker(psStream, psParams->ui32Marker);
+ return(IMG_TRUE);
+ }
+ else
+ {
+
+ return(IMG_FALSE);
+ }
+}
+
+static IMG_UINT32 DBGDIOCDrivGetMarker(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_STREAM psStream;
+ IMG_UINT32 *pui32Current;
+
+ pui32Current = (IMG_UINT32 *) pvOutBuffer;
+
+ psStream = SID2PStream(*(IMG_SID *)pvInBuffer);
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ *pui32Current = ExtDBGDrivGetMarker(psStream);
+ return(IMG_TRUE);
+ }
+ else
+ {
+
+ *pui32Current = 0;
+ return(IMG_FALSE);
+ }
+}
+
+static IMG_UINT32 DBGDIOCDrivGetServiceTable(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ IMG_PVOID * ppvOut;
+
+ PVR_UNREFERENCED_PARAMETER(pvInBuffer);
+ ppvOut = (IMG_PVOID *) pvOutBuffer;
+
+ *ppvOut = DBGDrivGetServiceTable();
+
+ return(IMG_TRUE);
+}
+
+static IMG_UINT32 DBGDIOCDrivWriteLF(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ PDBG_IN_WRITE_LF psInParams;
+ IMG_UINT32 *pui32BytesCopied;
+ PDBG_STREAM psStream;
+
+ psInParams = (PDBG_IN_WRITE_LF) pvInBuffer;
+ pui32BytesCopied = (IMG_UINT32 *) pvOutBuffer;
+
+ psStream = SID2PStream(psInParams->hStream);
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ *pui32BytesCopied = ExtDBGDrivWriteLF(psStream,
+ psInParams->u.pui8InBuffer,
+ psInParams->ui32BufferSize,
+ psInParams->ui32Level,
+ psInParams->ui32Flags);
+ return(IMG_TRUE);
+ }
+ else
+ {
+
+ return(IMG_FALSE);
+ }
+}
+
+static IMG_UINT32 DBGDIOCDrivReadLF(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ IMG_UINT32 * pui32BytesCopied;
+ PDBG_IN_READ psInParams;
+ PDBG_STREAM psStream;
+
+ psInParams = (PDBG_IN_READ) pvInBuffer;
+ pui32BytesCopied = (IMG_UINT32 *) pvOutBuffer;
+
+ psStream = SID2PStream(psInParams->hStream);
+ if (psStream != (PDBG_STREAM)IMG_NULL)
+ {
+ *pui32BytesCopied = ExtDBGDrivReadLF(psStream,
+ psInParams->ui32OutBufferSize,
+ psInParams->u.pui8OutBuffer);
+ return(IMG_TRUE);
+ }
+ else
+ {
+
+ *pui32BytesCopied = 0;
+ return(IMG_FALSE);
+ }
+}
+
+static IMG_UINT32 DBGDIOCDrivWaitForEvent(IMG_VOID * pvInBuffer, IMG_VOID * pvOutBuffer)
+{
+ DBG_EVENT eEvent = (DBG_EVENT)(*(IMG_UINT32 *)pvInBuffer);
+
+ PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+ ExtDBGDrivWaitForEvent(eEvent);
+
+ return(IMG_TRUE);
+}
+
+IMG_UINT32 (*g_DBGDrivProc[25])(IMG_VOID *, IMG_VOID *) =
+{
+ DBGDIOCDrivCreateStream,
+ DBGDIOCDrivDestroyStream,
+ DBGDIOCDrivGetStream,
+ DBGDIOCDrivWriteString,
+ DBGDIOCDrivReadString,
+ DBGDIOCDrivWrite,
+ DBGDIOCDrivRead,
+ DBGDIOCDrivSetCaptureMode,
+ DBGDIOCDrivSetOutMode,
+ DBGDIOCDrivSetDebugLevel,
+ DBGDIOCDrivSetFrame,
+ DBGDIOCDrivGetFrame,
+ DBGDIOCDrivOverrideMode,
+ DBGDIOCDrivDefaultMode,
+ DBGDIOCDrivGetServiceTable,
+ DBGDIOCDrivWrite2,
+ DBGDIOCDrivWriteStringCM,
+ DBGDIOCDrivWriteCM,
+ DBGDIOCDrivSetMarker,
+ DBGDIOCDrivGetMarker,
+ DBGDIOCDrivIsCaptureFrame,
+ DBGDIOCDrivWriteLF,
+ DBGDIOCDrivReadLF,
+ DBGDIOCDrivWaitForEvent
+};
+
--- /dev/null
+/**********************************************************************
+ *
+ * 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/version.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <asm/page.h>
+#include <linux/vmalloc.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15))
+#include <linux/mutex.h>
+#else
+#include <asm/semaphore.h>
+#endif
+#include <linux/hardirq.h>
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/jiffies.h>
+#include <linux/delay.h>
+#endif
+
+#include "img_types.h"
+#include "pvr_debug.h"
+
+#include "dbgdrvif.h"
+#include "hostfunc.h"
+#include "dbgdriv.h"
+
+#if defined(MODULE) && defined(DEBUG) && !defined(SUPPORT_DRI_DRM)
+IMG_UINT32 gPVRDebugLevel = (DBGPRIV_FATAL | DBGPRIV_ERROR | DBGPRIV_WARNING);
+
+#define PVR_STRING_TERMINATOR '\0'
+#define PVR_IS_FILE_SEPARATOR(character) ( ((character) == '\\') || ((character) == '/') )
+
+void PVRSRVDebugPrintf (
+ IMG_UINT32 ui32DebugLevel,
+ const IMG_CHAR* pszFileName,
+ IMG_UINT32 ui32Line,
+ const IMG_CHAR* pszFormat,
+ ...
+ )
+{
+ IMG_BOOL bTrace;
+#if !defined(__sh__)
+ IMG_CHAR *pszLeafName;
+
+ pszLeafName = (char *)strrchr (pszFileName, '\\');
+
+ if (pszLeafName)
+ {
+ pszFileName = pszLeafName;
+ }
+#endif
+
+ bTrace = (IMG_BOOL)(ui32DebugLevel & DBGPRIV_CALLTRACE) ? IMG_TRUE : IMG_FALSE;
+
+ if (gPVRDebugLevel & ui32DebugLevel)
+ {
+ va_list vaArgs;
+ static char szBuffer[256];
+
+ va_start (vaArgs, pszFormat);
+
+
+ if (bTrace == IMG_FALSE)
+ {
+ switch(ui32DebugLevel)
+ {
+ case DBGPRIV_FATAL:
+ {
+ strncpy (szBuffer, "PVR_K:(Fatal): ", sizeof (szBuffer));
+ break;
+ }
+ case DBGPRIV_ERROR:
+ {
+ strncpy (szBuffer, "PVR_K:(Error): ", sizeof (szBuffer));
+ break;
+ }
+ case DBGPRIV_WARNING:
+ {
+ strncpy (szBuffer, "PVR_K:(Warning): ", sizeof (szBuffer));
+ break;
+ }
+ case DBGPRIV_MESSAGE:
+ {
+ strncpy (szBuffer, "PVR_K:(Message): ", sizeof (szBuffer));
+ break;
+ }
+ case DBGPRIV_VERBOSE:
+ {
+ strncpy (szBuffer, "PVR_K:(Verbose): ", sizeof (szBuffer));
+ break;
+ }
+ default:
+ {
+ strncpy (szBuffer, "PVR_K:(Unknown message level)", sizeof (szBuffer));
+ break;
+ }
+ }
+ }
+ else
+ {
+ strncpy (szBuffer, "PVR_K: ", sizeof (szBuffer));
+ }
+
+ vsprintf (&szBuffer[strlen(szBuffer)], pszFormat, vaArgs);
+
+
+ if (bTrace == IMG_FALSE)
+ {
+ sprintf (&szBuffer[strlen(szBuffer)], " [%d, %s]", (int)ui32Line, pszFileName);
+ }
+
+ printk(KERN_INFO "%s\r\n", szBuffer);
+
+ va_end (vaArgs);
+ }
+}
+#endif
+
+IMG_VOID HostMemSet(IMG_VOID *pvDest, IMG_UINT8 ui8Value, IMG_UINT32 ui32Size)
+{
+ memset(pvDest, (int) ui8Value, (size_t) ui32Size);
+}
+
+IMG_VOID HostMemCopy(IMG_VOID *pvDst, IMG_VOID *pvSrc, IMG_UINT32 ui32Size)
+{
+#if defined(USE_UNOPTIMISED_MEMCPY)
+ unsigned char *src,*dst;
+ int i;
+
+ src=(unsigned char *)pvSrc;
+ dst=(unsigned char *)pvDst;
+ for(i=0;i<ui32Size;i++)
+ {
+ dst[i]=src[i];
+ }
+#else
+ memcpy(pvDst, pvSrc, ui32Size);
+#endif
+}
+
+IMG_UINT32 HostReadRegistryDWORDFromString(char *pcKey, char *pcValueName, IMG_UINT32 *pui32Data)
+{
+
+ return 0;
+}
+
+IMG_VOID * HostPageablePageAlloc(IMG_UINT32 ui32Pages)
+{
+ return (void*)vmalloc(ui32Pages * PAGE_SIZE);
+}
+
+IMG_VOID HostPageablePageFree(IMG_VOID * pvBase)
+{
+ vfree(pvBase);
+}
+
+IMG_VOID * HostNonPageablePageAlloc(IMG_UINT32 ui32Pages)
+{
+ return (void*)vmalloc(ui32Pages * PAGE_SIZE);
+}
+
+IMG_VOID HostNonPageablePageFree(IMG_VOID * pvBase)
+{
+ vfree(pvBase);
+}
+
+IMG_VOID * HostMapKrnBufIntoUser(IMG_VOID * pvKrnAddr, IMG_UINT32 ui32Size, IMG_VOID **ppvMdl)
+{
+
+ return IMG_NULL;
+}
+
+IMG_VOID HostUnMapKrnBufFromUser(IMG_VOID * pvUserAddr, IMG_VOID * pvMdl, IMG_VOID * pvProcess)
+{
+
+}
+
+IMG_VOID HostCreateRegDeclStreams(IMG_VOID)
+{
+
+}
+
+IMG_VOID * HostCreateMutex(IMG_VOID)
+{
+ struct semaphore *psSem;
+
+ psSem = kmalloc(sizeof(*psSem), GFP_KERNEL);
+ if (psSem)
+ {
+ init_MUTEX(psSem);
+ }
+
+ return psSem;
+}
+
+IMG_VOID HostAquireMutex(IMG_VOID * pvMutex)
+{
+ BUG_ON(in_interrupt());
+
+#if defined(PVR_DEBUG_DBGDRV_DETECT_HOST_MUTEX_COLLISIONS)
+ if (down_trylock((struct semaphore *)pvMutex))
+ {
+ printk(KERN_INFO "HostAquireMutex: Waiting for mutex\n");
+ down((struct semaphore *)pvMutex);
+ }
+#else
+ down((struct semaphore *)pvMutex);
+#endif
+}
+
+IMG_VOID HostReleaseMutex(IMG_VOID * pvMutex)
+{
+ up((struct semaphore *)pvMutex);
+}
+
+IMG_VOID HostDestroyMutex(IMG_VOID * pvMutex)
+{
+ if (pvMutex)
+ {
+ kfree(pvMutex);
+ }
+}
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+
+#define EVENT_WAIT_TIMEOUT_MS 500
+#define EVENT_WAIT_TIMEOUT_JIFFIES (EVENT_WAIT_TIMEOUT_MS * HZ / 1000)
+
+static int iStreamData;
+static wait_queue_head_t sStreamDataEvent;
+
+IMG_INT32 HostCreateEventObjects(IMG_VOID)
+{
+ init_waitqueue_head(&sStreamDataEvent);
+
+ return 0;
+}
+
+IMG_VOID HostWaitForEvent(DBG_EVENT eEvent)
+{
+ switch(eEvent)
+ {
+ case DBG_EVENT_STREAM_DATA:
+
+ wait_event_interruptible_timeout(sStreamDataEvent, iStreamData != 0, EVENT_WAIT_TIMEOUT_JIFFIES);
+ iStreamData = 0;
+ break;
+ default:
+
+ msleep_interruptible(EVENT_WAIT_TIMEOUT_MS);
+ break;
+ }
+}
+
+IMG_VOID HostSignalEvent(DBG_EVENT eEvent)
+{
+ switch(eEvent)
+ {
+ case DBG_EVENT_STREAM_DATA:
+ iStreamData = 1;
+ wake_up_interruptible(&sStreamDataEvent);
+ break;
+ default:
+ break;
+ }
+}
+
+IMG_VOID HostDestroyEventObjects(IMG_VOID)
+{
+}
+#endif
--- /dev/null
+#
+# 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
+#
+#
+#
+
+MODULE = dbgdrv
+
+INCLUDES = -I$(EURASIAROOT)/services4/srvkm/env/linux
+
+SOURCES =
+
+include $(EURASIAROOT)/tools/intern/debug/dbgdriv/linux/makefile.linux.common
+
+include $(EURASIAROOT)/eurasiacon/build/linux/kbuild/Makefile.kbuild_subdir_common
--- /dev/null
+/**********************************************************************
+ *
+ * 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/errno.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/kdev_t.h>
+#include <linux/pci.h>
+#include <linux/list.h>
+#include <linux/init.h>
+#include <linux/vmalloc.h>
+#include <linux/version.h>
+
+#if defined(LDM_PLATFORM) && !defined(SUPPORT_DRI_DRM)
+#include <linux/platform_device.h>
+#endif
+
+#if defined(LDM_PCI) && !defined(SUPPORT_DRI_DRM)
+#include <linux/pci.h>
+#endif
+
+#include <asm/uaccess.h>
+
+#if defined(SUPPORT_DRI_DRM)
+#include "drmP.h"
+#include "drm.h"
+#endif
+
+#include "img_types.h"
+#include "linuxsrv.h"
+#include "dbgdriv_ioctl.h"
+#include "dbgdrvif.h"
+#include "dbgdriv.h"
+#include "hostfunc.h"
+#include "hotkey.h"
+#include "pvr_debug.h"
+#include "pvrmodule.h"
+
+#if defined(SUPPORT_DRI_DRM)
+
+#include "pvr_drm_shared.h"
+#include "pvr_drm.h"
+
+#else
+
+#define DRVNAME "dbgdrv"
+MODULE_SUPPORTED_DEVICE(DRVNAME);
+
+#if (defined(LDM_PLATFORM) || defined(LDM_PCI)) && !defined(SUPPORT_DRI_DRM)
+static struct class *psDbgDrvClass;
+#endif
+
+static int AssignedMajorNumber = 0;
+
+long dbgdrv_ioctl(struct file *, unsigned int, unsigned long);
+
+static int dbgdrv_open(struct inode unref__ * pInode, struct file unref__ * pFile)
+{
+ return 0;
+}
+
+static int dbgdrv_release(struct inode unref__ * pInode, struct file unref__ * pFile)
+{
+ return 0;
+}
+
+static int dbgdrv_mmap(struct file* pFile, struct vm_area_struct* ps_vma)
+{
+ return 0;
+}
+
+static struct file_operations dbgdrv_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = dbgdrv_ioctl,
+ .open = dbgdrv_open,
+ .release = dbgdrv_release,
+ .mmap = dbgdrv_mmap,
+};
+
+#endif
+
+IMG_VOID DBGDrvGetServiceTable(IMG_VOID **fn_table);
+
+IMG_VOID DBGDrvGetServiceTable(IMG_VOID **fn_table)
+{
+ extern DBGKM_SERVICE_TABLE g_sDBGKMServices;
+
+ *fn_table = &g_sDBGKMServices;
+}
+
+#if defined(SUPPORT_DRI_DRM)
+void dbgdrv_cleanup(void)
+#else
+static void __exit dbgdrv_cleanup(void)
+#endif
+{
+#if !defined(SUPPORT_DRI_DRM)
+#if defined(LDM_PLATFORM) || defined(LDM_PCI)
+ device_destroy(psDbgDrvClass, MKDEV(AssignedMajorNumber, 0));
+ class_destroy(psDbgDrvClass);
+#endif
+ unregister_chrdev(AssignedMajorNumber, DRVNAME);
+#endif
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+ HostDestroyEventObjects();
+#endif
+ HostDestroyMutex(g_pvAPIMutex);
+ return;
+}
+
+#if defined(SUPPORT_DRI_DRM)
+IMG_INT dbgdrv_init(void)
+#else
+static int __init dbgdrv_init(void)
+#endif
+{
+#if (defined(LDM_PLATFORM) || defined(LDM_PCI)) && !defined(SUPPORT_DRI_DRM)
+ struct device *psDev;
+#endif
+
+#if !defined(SUPPORT_DRI_DRM)
+ int err = -EBUSY;
+#endif
+
+
+ if ((g_pvAPIMutex=HostCreateMutex()) == IMG_NULL)
+ {
+ return -ENOMEM;
+ }
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+
+ (void) HostCreateEventObjects();
+#endif
+
+#if !defined(SUPPORT_DRI_DRM)
+ AssignedMajorNumber =
+ register_chrdev(AssignedMajorNumber, DRVNAME, &dbgdrv_fops);
+
+ if (AssignedMajorNumber <= 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR," unable to get major\n"));
+ goto ErrDestroyEventObjects;
+ }
+
+#if defined(LDM_PLATFORM) || defined(LDM_PCI)
+
+ psDbgDrvClass = class_create(THIS_MODULE, DRVNAME);
+ if (IS_ERR(psDbgDrvClass))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: unable to create class (%ld)",
+ __func__, PTR_ERR(psDbgDrvClass)));
+ goto ErrUnregisterCharDev;
+ }
+
+ psDev = device_create(psDbgDrvClass, NULL, MKDEV(AssignedMajorNumber, 0),
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,26))
+ NULL,
+#endif
+ DRVNAME);
+ if (IS_ERR(psDev))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: unable to create device (%ld)",
+ __func__, PTR_ERR(psDev)));
+ goto ErrDestroyClass;
+ }
+#endif
+#endif
+
+ return 0;
+
+#if !defined(SUPPORT_DRI_DRM)
+ErrDestroyEventObjects:
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+ HostDestroyEventObjects();
+#endif
+#if defined(LDM_PLATFORM) || defined(LDM_PCI)
+ErrUnregisterCharDev:
+ unregister_chrdev(AssignedMajorNumber, DRVNAME);
+ErrDestroyClass:
+ class_destroy(psDbgDrvClass);
+#endif
+ return err;
+#endif
+}
+
+#if defined(SUPPORT_DRI_DRM)
+int dbgdrv_ioctl(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile)
+#else
+long dbgdrv_ioctl(struct file *file, unsigned int ioctlCmd, unsigned long arg)
+#endif
+{
+ IOCTL_PACKAGE *pIP = (IOCTL_PACKAGE *) arg;
+ char *buffer, *in, *out;
+ unsigned int cmd;
+
+ if((pIP->ui32InBufferSize > (PAGE_SIZE >> 1) ) || (pIP->ui32OutBufferSize > (PAGE_SIZE >> 1)))
+ {
+ PVR_DPF((PVR_DBG_ERROR,"Sizes of the buffers are too large, cannot do ioctl\n"));
+ return -1;
+ }
+
+ buffer = (char *) HostPageablePageAlloc(1);
+ if(!buffer)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"Failed to allocate buffer, cannot do ioctl\n"));
+ return -EFAULT;
+ }
+
+ in = buffer;
+ out = buffer + (PAGE_SIZE >>1);
+
+ if(copy_from_user(in, pIP->pInBuffer, pIP->ui32InBufferSize) != 0)
+ {
+ goto init_failed;
+ }
+
+ cmd = ((pIP->ui32Cmd >> 2) & 0xFFF) - 0x801;
+
+ if(pIP->ui32Cmd == DEBUG_SERVICE_READ)
+ {
+ IMG_UINT32 *pui32BytesCopied = (IMG_UINT32 *)out;
+ DBG_IN_READ *psReadInParams = (DBG_IN_READ *)in;
+ DBG_STREAM *psStream;
+ IMG_CHAR *ui8Tmp;
+
+ ui8Tmp = vmalloc(psReadInParams->ui32OutBufferSize);
+
+ if(!ui8Tmp)
+ {
+ goto init_failed;
+ }
+
+ psStream = SID2PStream(psReadInParams->hStream);
+ if(!psStream)
+ {
+ goto init_failed;
+ }
+
+ *pui32BytesCopied = ExtDBGDrivRead(psStream,
+ psReadInParams->bReadInitBuffer,
+ psReadInParams->ui32OutBufferSize,
+ ui8Tmp);
+
+ if(copy_to_user(psReadInParams->u.pui8OutBuffer,
+ ui8Tmp,
+ *pui32BytesCopied) != 0)
+ {
+ vfree(ui8Tmp);
+ goto init_failed;
+ }
+
+ vfree(ui8Tmp);
+ }
+ else
+ {
+ (g_DBGDrivProc[cmd])(in, out);
+ }
+
+ if(copy_to_user(pIP->pOutBuffer, out, pIP->ui32OutBufferSize) != 0)
+ {
+ goto init_failed;
+ }
+
+ HostPageablePageFree((IMG_VOID *)buffer);
+ return 0;
+
+init_failed:
+ HostPageablePageFree((IMG_VOID *)buffer);
+ return -EFAULT;
+}
+
+
+IMG_VOID RemoveHotKey (IMG_UINT32 hHotKey)
+{
+ PVR_UNREFERENCED_PARAMETER(hHotKey);
+}
+
+IMG_VOID DefineHotKey (IMG_UINT32 ui32ScanCode, IMG_UINT32 ui32ShiftState, PHOTKEYINFO psInfo)
+{
+ PVR_UNREFERENCED_PARAMETER(ui32ScanCode);
+ PVR_UNREFERENCED_PARAMETER(ui32ShiftState);
+ PVR_UNREFERENCED_PARAMETER(psInfo);
+}
+
+/*EXPORT_SYMBOL(DBGDrvGetServiceTable); */
+
+#if !defined(SUPPORT_DRI_DRM)
+subsys_initcall(dbgdrv_init);
+module_exit(dbgdrv_cleanup);
+#endif
--- /dev/null
+#
+# 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
+#
+#
+#
+
+ifeq ($(SUPPORT_DRI_DRM),1)
+DBGDRV_SOURCES_ROOT = $(KBUILDROOT)/../tools/intern/debug/dbgdriv
+else
+DBGDRV_SOURCES_ROOT = ../..
+endif
+
+INCLUDES += -I$(EURASIAROOT)/include4 \
+ -I$(EURASIAROOT)/tools/intern/debug \
+ -I$(EURASIAROOT)/tools/intern/debug/dbgdriv/common \
+ -I$(EURASIAROOT)/tools/intern/debug/client
+
+SOURCES += $(DBGDRV_SOURCES_ROOT)/linux/main.c \
+ $(DBGDRV_SOURCES_ROOT)/common/dbgdriv.c \
+ $(DBGDRV_SOURCES_ROOT)/common/ioctl.c \
+ $(DBGDRV_SOURCES_ROOT)/common/handle.c \
+ $(DBGDRV_SOURCES_ROOT)/linux/hostfunc.c \
+ $(DBGDRV_SOURCES_ROOT)/common/hotkey.c
* OS abstraction macros.
*/
+#ifndef _DRM_OS_LINUX_H_
+#define _DRM_OS_LINUX_H_
+
#include <linux/interrupt.h> /* For task queue support */
#include <linux/delay.h>
#define DRM_WAKEUP( queue ) wake_up( queue )
#define DRM_INIT_WAITQUEUE( queue ) init_waitqueue_head( queue )
+
+#endif /* _DRM_OS_LINUX_H_ */