+++ /dev/null
-obj-m := pvrsrvkm.o
-
-FILES := \
-services4/srvkm/common/queue.c \
-services4/srvkm/common/hash.c \
-services4/srvkm/common/perproc.c \
-services4/srvkm/common/mem.c \
-services4/srvkm/common/power.c \
-services4/srvkm/common/deviceclass.c \
-services4/srvkm/common/metrics.c \
-services4/srvkm/common/resman.c \
-services4/srvkm/common/buffer_manager.c \
-services4/srvkm/common/pvrsrv.c \
-services4/srvkm/common/handle.c \
-services4/srvkm/common/ra.c \
-services4/srvkm/common/devicemem.c \
-services4/srvkm/env/linux/pvr_debug.c \
-services4/srvkm/env/linux/mm.c \
-services4/srvkm/env/linux/mutex.c \
-services4/srvkm/env/linux/mmap.c \
-services4/srvkm/env/linux/module.c \
-services4/srvkm/env/linux/proc.c \
-services4/srvkm/env/linux/event.c \
-services4/srvkm/env/linux/osfunc.c \
-services4/srvkm/env/linux/pvr_bridge_k.c \
-services4/srvkm/env/linux/pdump.c \
-services4/srvkm/devices/sgx/sgxtransfer.c \
-services4/srvkm/devices/sgx/sgxinit.c \
-services4/srvkm/devices/sgx/sgxutils.c \
-services4/srvkm/devices/sgx/pb.c \
-services4/srvkm/devices/sgx/sgxkick.c \
-services4/srvkm/devices/sgx/mmu.c \
-services4/srvkm/devices/sgx/sgxreset.c \
-services4/srvkm/bridged/bridged_pvr_bridge.c \
-services4/system/omap3430/sysutils_linux.c \
-services4/system/omap3430/sysconfig.c
-
-EXTRA_CFLAGS += -I$(src)/include4
-EXTRA_CFLAGS += -I$(src)/services4/include
-EXTRA_CFLAGS += -I$(src)/services4/srvkm/include
-EXTRA_CFLAGS += -I$(src)/services4/srvkm/hwdefs
-EXTRA_CFLAGS += -I$(src)/services4/srvkm/bridged
-EXTRA_CFLAGS += -I$(src)/services4/srvkm/devices/sgx
-EXTRA_CFLAGS += -I$(src)/services4/srvkm/env/linux
-EXTRA_CFLAGS += -I$(src)/services4/system/include
-EXTRA_CFLAGS += -I$(src)/services4/system/omap3430
-
-EXTRA_CFLAGS += $(ALL_CFLAGS)
-
-pvrsrvkm-y := $(FILES:.c=.o)
-
-obj-y := services4/3rdparty/dc_omap3430_linux/
-
--- /dev/null
+menuconfig PVR
+ tristate "PowerVR Services"
+ depends on OMAP2_DSS
+
-export DISCIMAGE = /home/pratheesh/nfsexport/glibc_rootfs
-
-export KERNELDIR = /home1/pratheesh/workdir/opt/linux/kernel_org/REL_OMAP35x_02.01.00.04/src/kernel/linux-02.01.00.04
-export KERNEL_PATH=$(KERNELDIR)
-export KERNEL_SRC=$(KERNELDIR)
-export KDIR=$(KERNELDIR)
-
-export BUILD = debug
-
-export KBUILD_EXTRA_SYMBOLS = `pwd`/services4/srvkm/env/linux/kbuild/Module.symvers
+PVR_SYSTEM := omap3430
+
+EXTRA_CFLAGS += -D__linux__
+
+obj-$(CONFIG_PVR) += \
+ omaplfb.o \
+ pvrsrvkm.o
+
+omaplfb-objs := \
+ services4/3rdparty/dc_omap3430_linux/omaplfb_displayclass.o \
+ services4/3rdparty/dc_omap3430_linux/omaplfb_linux.o
+
+pvrsrvkm-objs := \
+ services4/srvkm/env/linux/osfunc.o \
+ services4/srvkm/env/linux/mmap.o \
+ services4/srvkm/env/linux/module.o \
+ services4/srvkm/env/linux/pdump.o \
+ services4/srvkm/env/linux/proc.o \
+ services4/srvkm/env/linux/pvr_bridge_k.o \
+ services4/srvkm/env/linux/pvr_debug.o \
+ services4/srvkm/env/linux/mm.o \
+ services4/srvkm/env/linux/mutex.o \
+ services4/srvkm/env/linux/event.o \
+ services4/srvkm/common/buffer_manager.o \
+ services4/srvkm/common/devicemem.o \
+ services4/srvkm/common/deviceclass.o \
+ services4/srvkm/common/handle.o \
+ services4/srvkm/common/hash.o \
+ services4/srvkm/common/metrics.o \
+ services4/srvkm/common/pvrsrv.o \
+ services4/srvkm/common/queue.o \
+ services4/srvkm/common/ra.o \
+ services4/srvkm/common/resman.o \
+ services4/srvkm/common/power.o \
+ services4/srvkm/common/mem.o \
+ services4/srvkm/bridged/bridged_pvr_bridge.o \
+ services4/srvkm/devices/sgx/sgxinit.o \
+ services4/srvkm/devices/sgx/sgxreset.o \
+ services4/srvkm/devices/sgx/sgxutils.o \
+ services4/srvkm/devices/sgx/sgxkick.o \
+ services4/srvkm/devices/sgx/sgxtransfer.o \
+ services4/srvkm/devices/sgx/mmu.o \
+ services4/srvkm/devices/sgx/pb.o \
+ services4/srvkm/common/perproc.o \
+ services4/system/$(PVR_SYSTEM)/sysconfig.o \
+ services4/system/$(PVR_SYSTEM)/sysutils.o
+
+ccflags-y := \
+ -I$(src)/include4 \
+ -I$(src)/services4/include \
+ -I$(src)/services4/srvkm/env/linux \
+ -I$(src)/services4/srvkm/include \
+ -I$(src)/services4/srvkm/bridged \
+ -I$(src)/services4/srvkm/devices/sgx \
+ -I$(src)/services4/system/$(PVR_SYSTEM) \
+ -I$(src)/services4/system/include \
+ -I$(src)/services4/srvkm/hwdefs \
+ -Iarch/arm/plat-omap/include/mach
+
+# Work out our origins. eurasiacon.pj is not supplied to end-users
+# so instead we supply pvrversion.h. We produce pvrversion.h if
+# if doesn't exist.
+#
+DATE := $(shell date "+%a %B %d %Z %Y" )
SGXCORE = 530
-CORE = -DSGX530 -DSUPPORT_SGX530 -DSGX_CORE_REV=103
+CORE = -DSGX530 -DSUPPORT_SGX530 -DSGX_CORE_REV=121
+
+# --------------------------------------------------------------------------------
SUPPORT_SGX = 1
SUPPORT_HW_RECOVERY = 1
SUPPORT_SGX_HWPERF = 1
SYS_USING_INTERRUPTS = 1
-SUPPORT_TI_PM = 0
PVR2D_ALT_2DHW = 1
SUPPORT_ACTIVE_POWER_MANAGEMENT = 0
endif
-export PVR_BUILD_DIR := $(shell pwd)
-
-DATE := $(shell date "+%a %B %d %Z %Y" )
+BUILD ?= release
+# The standard CFLAGS macro can be overridden on the 'make' command line. We
+# put CBUILD in a separate macro so its setting doesn't get lost when a user
+# *does* override CFLAGS.
+#
CBUILD = -DPVR_BUILD_DIR="\"$(PVR_BUILD_DIR)\"" \
- -DPVR_BUILD_DATE="\"$(DATE)\"" \
- -DPVR_BUILD_TYPE="\"$(BUILD)\""
+ -DPVR_BUILD_DATE="\"$(DATE)\"" \
+ -DPVR_BUILD_TYPE="\"$(BUILD)\""
+
+# OPTIM contains the optimisation level in timing and release builds
+OPTIM = -O2
# Don't support HW recovery on debug builds
CBUILD.debug = -DDEBUG
CBUILD.timing = -DTIMING
CBUILD.release = -DRELEASE
-CFLAGS.debug = -g -O0 -DDLL_METRIC=1
-CFLAGS.timing = $(OPTIM) -g -DDLL_METRIC=1 -DTIMING
-CFLAGS.release = $(OPTIM) -g
-CFLAGS = $(CFLAGS.$(BUILD))
+_CFLAGS.debug = -g -O0 -DDLL_METRIC=1
+_CFLAGS.timing = $(OPTIM) -g -DDLL_METRIC=1 -DTIMING
+_CFLAGS.release = $(OPTIM) -g
+_CFLAGS = $(_CFLAGS.$(BUILD)) -DSGX_DYNAMIC_TIMING_INFO
+# Defaults for useful things.
+#
ifeq ("$(BUILD)", "debug")
-DEBUG_LINUX_MEMORY_ALLOCATIONS ?= 1
-DEBUG_LINUX_MEM_AREAS ?= 1
-DEBUG_LINUX_MMAP_AREAS ?= 1
-DEBUG_LINUX_XML_PROC_FILES ?= 0
-DEBUG_LINUX_SLAB_ALLOCATIONS ?= 0
-DEBUG_BRIDGE_KM ?= 1
-DEBUG_TRACE_BRIDGE_KM ?= 0
-DEBUG_BRIDGE_KM_DISPATCH_TABLE ?= 0
+DEBUG_LINUX_MEMORY_ALLOCATIONS ?= 1
+DEBUG_LINUX_MEM_AREAS ?= 1
+DEBUG_LINUX_MMAP_AREAS ?= 1
+DEBUG_LINUX_XML_PROC_FILES ?= 0
+DEBUG_LINUX_SLAB_ALLOCATIONS ?= 0
+DEBUG_BRIDGE_KM ?= 1
+DEBUG_TRACE_BRIDGE_KM ?= 0
+DEBUG_BRIDGE_KM_DISPATCH_TABLE ?= 0
endif
-TRANSFER_QUEUE ?= 1
-SUPPORT_SGX_EVENT_OBJECT ?= 1
+TRANSFER_QUEUE ?= 1
+SUPPORT_SGX_EVENT_OBJECT ?=1
SUPPORT_SECURE_HANDLES ?= 1
-SUPPORT_SRVINIT = 1
-SUPPORT_PERCONTEXT_PB = 1
+SUPPORT_SRVINIT = 1
+SUPPORT_PERCONTEXT_PB = 1
SYS_CFLAGS += -DSERVICES4 -D_XOPEN_SOURCE=600 -DPVR2D_VALIDATE_INPUT_PARAMS
SYS_CFLAGS.$(SUPPORT_SRVINIT) += -DSUPPORT_SRVINIT
-SYS_CFLAGS.$(SUPPORT_SGX) += -DSUPPORT_SGX
-SYS_CFLAGS.$(SUPPORT_XWS) += -DSUPPORT_XWS
-SYS_CFLAGS.$(PDUMP) += -DPDUMP
-SYS_CFLAGS.$(SUPPORT_POWER_MANAGEMENT) += -DSUPPORT_POWER_MANAGEMENT
+SYS_CFLAGS.$(SUPPORT_SGX) += -DSUPPORT_SGX
+SYS_CFLAGS.$(SUPPORT_XWS) += -DSUPPORT_XWS
+SYS_CFLAGS.$(PDUMP) += -DPDUMP
+SYS_CFLAGS.$(SUPPORT_POWER_MANAGEMENT) += -DSUPPORT_POWER_MANAGEMENT
SYS_CFLAGS.$(SUPPORT_BUFFER_CLASS) += -DSUPPORT_BUFFER_CLASS
SYS_CFLAGS.$(SUPPORT_PERCONTEXT_PB) += -DSUPPORT_PERCONTEXT_PB
-SYS_CFLAGS.$(SUPPORT_DYNAMIC_PBRESIZE) += -DSUPPORT_DYNAMIC_PBRESIZE
+SYS_CFLAGS.$(SUPPORT_DYNAMIC_PBRESIZE) += -DSUPPORT_DYNAMIC_PBRESIZE
-SYS_CFLAGS.$(USE_FBDEV) += -DUSE_FBDEV
-SYS_CFLAGS.$(USE_FBDEV) += -DFBDEV_NAME="\"$(FBDEV_NAME)\""
-SYS_CFLAGS.$(SUPPORT_DYNAMIC_3DCLOCKGATING) += -DSUPPORT_DYNAMIC_3DCLOCKGATING
+SYS_CFLAGS.$(USE_FBDEV) += -DUSE_FBDEV
+SYS_CFLAGS.$(USE_FBDEV) += -DFBDEV_NAME="\"$(FBDEV_NAME)\""
+SYS_CFLAGS.$(SUPPORT_DYNAMIC_3DCLOCKGATING) += -DSUPPORT_DYNAMIC_3DCLOCKGATING
SYS_CFLAGS.$(REENTRANCY_PROTECTION) += -DREENTRANCY_PROTECTION
-SYS_CFLAGS.$(SCHEDULER_CONTROL_SUPPORT) += -DSCHEDULER_CONTROL_SUPPORT
-SYS_CFLAGS.$(USE_IMG_POWER_DOMAIN_FUNCTION) += -DUSE_IMG_POWER_DOMAIN_FUNCTION
+SYS_CFLAGS.$(SCHEDULER_CONTROL_SUPPORT) += -DSCHEDULER_CONTROL_SUPPORT
+SYS_CFLAGS.$(USE_IMG_POWER_DOMAIN_FUNCTION) += -DUSE_IMG_POWER_DOMAIN_FUNCTION
-SYS_CFLAGS.$(USE_DMALLOC) += -DDMALLOC
+SYS_CFLAGS.$(USE_DMALLOC) += -DDMALLOC
-SYS_CFLAGS.$(DEBUG_LINUX_MEMORY_ALLOCATIONS) += -DDEBUG_LINUX_MEMORY_ALLOCATIONS
-SYS_CFLAGS.$(DEBUG_LINUX_MEM_AREAS) += -DDEBUG_LINUX_MEM_AREAS
+SYS_CFLAGS.$(DEBUG_LINUX_MEMORY_ALLOCATIONS) += -DDEBUG_LINUX_MEMORY_ALLOCATIONS
+SYS_CFLAGS.$(DEBUG_LINUX_MEM_AREAS) += -DDEBUG_LINUX_MEM_AREAS
SYS_CFLAGS.$(DEBUG_LINUX_MMAP_AREAS) += -DDEBUG_LINUX_MMAP_AREAS
SYS_CFLAGS.$(DEBUG_LINUX_XML_PROC_FILES) += -DDEBUG_LINUX_XML_PROC_FILES
SYS_CFLAGS.$(DEBUG_LINUX_SLAB_ALLOCATIONS) += -DDEBUG_LINUX_SLAB_ALLOCATIONS
-SYS_CFLAGS.$(DEBUG_BRIDGE_KM) += -DDEBUG_BRIDGE_KM
-SYS_CFLAGS.$(DEBUG_TRACE_BRIDGE_KM) += -DDEBUG_TRACE_BRIDGE_KM
-SYS_CFLAGS.$(DEBUG_BRIDGE_KM_DISPATCH_TABLE) += -DDEBUG_BRIDGE_KM_DISPATCH_TABLE
+SYS_CFLAGS.$(DEBUG_BRIDGE_KM) += -DDEBUG_BRIDGE_KM
+SYS_CFLAGS.$(DEBUG_TRACE_BRIDGE_KM) += -DDEBUG_TRACE_BRIDGE_KM
+SYS_CFLAGS.$(DEBUG_BRIDGE_KM_DISPATCH_TABLE) += -DDEBUG_BRIDGE_KM_DISPATCH_TABLE
-SYS_CFLAGS.$(SUPPORT_LINUX_X86_WRITECOMBINE) += -DSUPPORT_LINUX_X86_WRITECOMBINE
+SYS_CFLAGS.$(SUPPORT_LINUX_X86_WRITECOMBINE) += -DSUPPORT_LINUX_X86_WRITECOMBINE
SYS_CFLAGS.$(SGX_PDS_EVENTS_DISABLED) += -DSGX_PDS_EVENTS_DISABLED
SYS_CFLAGS.$(USE_SUPPORT_NO_TA3D_OVERLAP) += -DUSE_SUPPORT_NO_TA3D_OVERLAP
-SYS_CFLAGS.$(SUPPORT_SGX_TILING) += -DSUPPORT_SGX_TILING
-SYS_CFLAGS.$(TRANSFER_QUEUE) += -DTRANSFER_QUEUE
+SYS_CFLAGS.$(SUPPORT_SGX_TILING) += -DSUPPORT_SGX_TILING
+SYS_CFLAGS.$(TRANSFER_QUEUE) += -DTRANSFER_QUEUE
SYS_CFLAGS.$(SUPPORT_SGX_MMU_DUMMY_PAGE) += -DSUPPORT_SGX_MMU_DUMMY_PAGE
SYS_CFLAGS.$(PVRSRV_USSE_EDM_STATUS_DEBUG) += -DPVRSRV_USSE_EDM_STATUS_DEBUG
+SYS_CFLAGS.$(NO_HARDWARE) += -DNO_HARDWARE
+
SYS_CFLAGS.$(SUPPORT_DRI_DRM) += -DSUPPORT_DRI_DRM
-SYS_CFLAGS.$(SYS_USING_INTERRUPTS) += -DSYS_USING_INTERRUPTS
-SYS_CFLAGS.$(SUPPORT_HW_RECOVERY) += -DSUPPORT_HW_RECOVERY
-SYS_CFLAGS.$(SUPPORT_ACTIVE_POWER_MANAGEMENT) += -DSUPPORT_ACTIVE_POWER_MANAGEMENT
+ifneq ("$(NO_HARDWARE)", "1")
+SYS_CFLAGS.$(SYS_USING_INTERRUPTS) += -DSYS_USING_INTERRUPTS
+SYS_CFLAGS.$(SUPPORT_HW_RECOVERY) += -DSUPPORT_HW_RECOVERY
+SYS_CFLAGS.$(SUPPORT_ACTIVE_POWER_MANAGEMENT) += -DSUPPORT_ACTIVE_POWER_MANAGEMENT
+endif
-SYS_CFLAGS.$(SUPPORT_SECURE_HANDLES) += -DPVR_SECURE_HANDLES
+SYS_CFLAGS.$(SUPPORT_SECURE_HANDLES) += -DPVR_SECURE_HANDLES
SYS_CFLAGS.$(USE_PTHREADS) += -DUSE_PTHREADS
-SYS_CFLAGS.$(USE_GCC__thread_KEYWORD) += -DUSE_GCC__thread_KEYWORD
-SYS_CFLAGS.$(OPTIMISE_NON_NPTL_SINGLE_THREAD_TLS_LOOKUP) += -DOPTIMISE_NON_NPTL_SINGLE_THREAD_TLS_LOOKUP
-SYS_CFLAGS.$(DISABLE_THREADS) += -DDISABLE_THREADS
+SYS_CFLAGS.$(USE_GCC__thread_KEYWORD) += -DUSE_GCC__thread_KEYWORD
+SYS_CFLAGS.$(OPTIMISE_NON_NPTL_SINGLE_THREAD_TLS_LOOKUP) += -DOPTIMISE_NON_NPTL_SINGLE_THREAD_TLS_LOOKUP
+SYS_CFLAGS.$(DISABLE_THREADS) += -DDISABLE_THREADS
SYS_CFLAGS.$(SUPPORT_SGX_EVENT_OBJECT) += -DSUPPORT_SGX_EVENT_OBJECT
-SYS_CFLAGS.$(LDM_PLATFORM) += -DLDM_PLATFORM
-SYS_CFLAGS.$(LDM_PCI) += -DLDM_PCI
-SYS_CFLAGS.$(PVR_MANUAL_POWER_CONTROL) += -DPVR_MANUAL_POWER_CONTROL
-
-SYS_CFLAGS.$(PVR2D_ALT_2DHW) += -DPVR2D_ALT_2DHW
-
-SYS_CFLAGS.$(SUPPORT_SGX_HWPERF) += -DSUPPORT_SGX_HWPERF
+SYS_CFLAGS.$(LDM_PLATFORM) += -DLDM_PLATFORM
+SYS_CFLAGS.$(LDM_PCI) += -DLDM_PCI
+SYS_CFLAGS.$(PVR_MANUAL_POWER_CONTROL) += -DPVR_MANUAL_POWER_CONTROL
-SYS_CFLAGS.$(SUPPORT_TI_PM) += -DSUPPORT_TI_PM
+SYS_CFLAGS.$(PVR2D_ALT_2DHW) += -DPVR2D_ALT_2DHW
-export ALL_CFLAGS = -DLINUX \
- $(CBUILD) $(CBUILD.$(BUILD)) \
- $(SYS_CFLAGS) $(SYS_CFLAGS.1) \
- $(MODULE_CFLAGS) $(MODULE_CFLAGS.$(BUILD)) \
- $(CORE) \
- $(CFLAGS)
+SYS_CFLAGS.$(SUPPORT_SGX_HWPERF) += -DSUPPORT_SGX_HWPERF
-all:
- $(MAKE) -C $(KERNELDIR) M=`pwd` $*
+SYS_INCLUDES = -I$(EURASIAROOT)/include4 \
+ -I$(EURASIAROOT)/eurasiacon/includeext \
+ -isystem $(KERNELDIR)/include
-clean:
- $(MAKE) -C $(KERNELDIR) M=`pwd` clean
+ALL_CFLAGS_kbuild = -DLINUX \
+ $(CBUILD) $(CBUILD.$(BUILD)) \
+ $(SYS_CFLAGS) $(SYS_CFLAGS.1) \
+ $(MODULE_CFLAGS) $(MODULE_CFLAGS.$(BUILD)) \
+ $(CORE) \
+ -Wall -fno-strict-aliasing \
+ $(_CFLAGS)
+ccflags-y += $(ALL_CFLAGS_kbuild)
--- /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
#define PVRMMapKVIndexAddressToMMapData(A,B,C,D,E) PVRSRV_OK
#endif
+#ifdef __KERNEL__
+#include <linux/pagemap.h> /* for cache flush */
+#endif /* __KERNEL__ */
+
#ifndef ENOMEM
#define ENOMEM 12
#endif
return 0;
}
+static int
+FlushCacheDRI(IMG_UINT32 ui32Type, IMG_UINT32 ui32Virt, IMG_UINT32 ui32Length)
+{
+ switch (ui32Type) {
+ case DRM_PVR2D_CFLUSH_FROM_GPU:
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "DRM_PVR2D_CFLUSH_FROM_GPU 0x%08x, length 0x%08x\n",
+ ui32Virt, ui32Length));
+#ifdef CONFIG_ARM
+ dmac_inv_range((const void *)ui32Virt,
+ (const void *)(ui32Virt + ui32Length));
+#endif
+ return 0;
+ case DRM_PVR2D_CFLUSH_TO_GPU:
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "DRM_PVR2D_CFLUSH_TO_GPU 0x%08x, length 0x%08x\n",
+ ui32Virt, ui32Length));
+#ifdef CONFIG_ARM
+ dmac_clean_range((const void *)ui32Virt,
+ (const void *)(ui32Virt + ui32Length));
+#endif
+ return 0;
+ default:
+ PVR_DPF((PVR_DBG_ERROR, "Invalid cflush type 0x%x\n",
+ ui32Type));
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int
+PVRSRVCacheFlushDRIBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_CACHEFLUSHDRMFROMUSER * psCacheFlushIN,
+ PVRSRV_BRIDGE_RETURN * psRetOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CACHE_FLUSH_DRM);
+
+ psRetOUT->eError = FlushCacheDRI(psCacheFlushIN->ui32Type,
+ psCacheFlushIN->ui32Virt,
+ psCacheFlushIN->ui32Length);
+
+ return 0;
+}
+
static int
PVRSRVMapDeviceClassMemoryBW(IMG_UINT32 ui32BridgeID,
PVRSRV_BRIDGE_IN_MAP_DEVICECLASS_MEMORY *
psWrapExtMemIN->bPhysContig,
psSysPAddr,
psWrapExtMemIN->pvLinAddr, &psMemInfo);
- if (psWrapExtMemIN->ui32NumPageTableEntries) {
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
- ui32PageTableSize, (IMG_VOID *) psSysPAddr, 0);
- }
if (psWrapExtMemOUT->eError != PVRSRV_OK) {
+ /* PVRSRVWrapExtMemoryKM failed, so clean up page list */
+ if (psWrapExtMemIN->ui32NumPageTableEntries)
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32PageTableSize,
+ (IMG_VOID *) psSysPAddr, 0);
return 0;
}
hKernelSyncInfo,
(IMG_HANDLE) psMemInfo->psKernelSyncInfo,
PVRSRV_HANDLE_TYPE_SYNC_INFO,
- PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
psWrapExtMemOUT->sClientMemInfo.hKernelMemInfo);
COMMIT_HANDLE_BATCH_OR_ERROR(psWrapExtMemOUT->eError, psPerProc);
PVRSRVUnmapDeviceClassMemoryBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_MEM_INFO_TO_USER, DummyBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_UNMAP_MEM_INFO_FROM_USER, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_CACHE_FLUSH_DRM,
+ PVRSRVCacheFlushDRIBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_PROCESS_SIMISR_EVENT, DummyBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_REGISTER_SIM_PROCESS, DummyBW);
* Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
*
******************************************************************************/
-
#include "services_headers.h"
#include "sysconfig.h"
psBMHeap = psBMHeap->psNext;
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psTmpBMHeap, IMG_NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_HEAP),
+ psTmpBMHeap, IMG_NULL);
}
if (pBMContext->psMMUContext) {
}
}
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, pBMContext, IMG_NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_CONTEXT), pBMContext,
+ IMG_NULL);
return PVRSRV_OK;
}
psDeviceNode->pfnMMUFinalise(pBMContext->psMMUContext);
}
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psBMHeap, IMG_NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_HEAP), psBMHeap, IMG_NULL);
return IMG_NULL;
}
if (*ppsBMHeap == psBMHeap) {
*ppsBMHeap = psBMHeap->psNext;
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psBMHeap,
- IMG_NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(BM_HEAP), psBMHeap, IMG_NULL);
break;
}
ppsBMHeap = &((*ppsBMHeap)->psNext);
return IMG_TRUE;
}
+IMG_BOOL
+BM_IsWrapped(IMG_HANDLE hDevMemHeap,
+ IMG_UINT32 ui32Offset, IMG_SYS_PHYADDR sSysAddr)
+{
+ BM_BUF *pBuf;
+ BM_CONTEXT *psBMContext;
+ BM_HEAP *psBMHeap;
+
+ psBMHeap = (BM_HEAP *) hDevMemHeap;
+ psBMContext = psBMHeap->pBMContext;
+ sSysAddr.uiAddr += ui32Offset;
+ pBuf = (BM_BUF *) HASH_Retrieve(psBMContext->pBufferHash,
+ (IMG_UINTPTR_T) sSysAddr.uiAddr);
+ return pBuf != IMG_NULL;
+}
+
IMG_BOOL
BM_Wrap(IMG_HANDLE hDevMemHeap,
IMG_UINT32 ui32Size,
IMG_UINT32 ui32Offset,
IMG_BOOL bPhysContig,
IMG_SYS_PHYADDR * psSysAddr,
+ IMG_BOOL bFreePageList,
IMG_VOID * pvCPUVAddr, IMG_UINT32 * pui32Flags, BM_HANDLE * phBuf)
{
BM_BUF *pBuf;
if (pBuf->pMapping->uSize == ui32MappingSize
&& (pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped
|| pBuf->pMapping->eCpuMemoryOrigin ==
- hm_wrapped_virtaddr)) {
+ hm_wrapped_virtaddr
+ || pBuf->pMapping->eCpuMemoryOrigin ==
+ hm_wrapped_scatter)) {
PVR_DPF((PVR_DBG_MESSAGE,
"BM_Wrap (Matched previous Wrap! uSize=0x%x, uOffset=0x%x, SysAddr=%08X)",
ui32Size, ui32Offset, sHashAddress.uiAddr));
if (pui32Flags)
*pui32Flags = uFlags;
+ /* reusing previous mapping, free the page list */
+ if (bFreePageList && psSysAddr)
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32MappingSize / HOST_PAGESIZE() *
+ sizeof(IMG_SYS_PHYADDR),
+ (IMG_VOID *) psSysAddr, 0);
return IMG_TRUE;
}
}
}
if (pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped
- || pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr) {
-
- PVR_ASSERT(SysSysPAddrToCpuPAddr(sHashAddress).uiAddr ==
- pBuf->CpuPAddr.uiAddr);
-
+ || pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr
+ || pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_scatter) {
+ pBuf->uHashKey = (IMG_UINTPTR_T) sHashAddress.uiAddr;
if (!HASH_Insert
- (psBMContext->pBufferHash,
- (IMG_UINTPTR_T) sHashAddress.uiAddr,
+ (psBMContext->pBufferHash, pBuf->uHashKey,
(IMG_UINTPTR_T) pBuf)) {
FreeBuf(pBuf, uFlags);
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_BUF), pBuf,
- IMG_NULL);
PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: HASH_Insert FAILED"));
return IMG_FALSE;
}
if (pui32Flags)
*pui32Flags = uFlags;
+ /* take ownership of the list if requested so */
+ if (bFreePageList && psSysAddr)
+ pBuf->pvPageList = (void *)psSysAddr;
return IMG_TRUE;
}
{
BM_BUF *pBuf = (BM_BUF *) hBuf;
SYS_DATA *psSysData;
- IMG_SYS_PHYADDR sHashAddr;
PVR_DPF((PVR_DBG_MESSAGE, "BM_Free (h=%08X)", hBuf));
+ /* Calling BM_Free with NULL hBuf is either a bug or out-of-memory condition.
+ * Bail out if in debug mode, continue in release builds */
PVR_ASSERT(pBuf != IMG_NULL);
+#if !defined(DEBUG)
+ if (!pBuf) {
+ return;
+ }
+#endif
if (SysAcquireData(&psSysData) != PVRSRV_OK)
return;
pBuf->ui32RefCount--;
if (pBuf->ui32RefCount == 0) {
+ void *pPageList = pBuf->pvPageList;
+ IMG_UINT32 ui32ListSize =
+ pBuf->pMapping->uSize / HOST_PAGESIZE() *
+ sizeof(IMG_SYS_PHYADDR);
if (pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped
- || pBuf->pMapping->eCpuMemoryOrigin ==
- hm_wrapped_virtaddr) {
- sHashAddr = SysCpuPAddrToSysPAddr(pBuf->CpuPAddr);
-
+ || pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr
+ || pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_scatter) {
HASH_Remove(pBuf->pMapping->pBMHeap->pBMContext->
- pBufferHash,
- (IMG_UINTPTR_T) sHashAddr.uiAddr);
+ pBufferHash, pBuf->uHashKey);
}
FreeBuf(pBuf, ui32Flags);
+ if (pPageList)
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32ListSize,
+ pPageList, 0);
}
}
BM_MAPPING *pMapping;
IMG_UINT32 ui32RefCount;
+ IMG_UINTPTR_T uHashKey;
+ void *pvKernelSyncInfo;
+ void *pvPageList;
+ IMG_HANDLE hOSWrapMem;
} BM_BUF;
struct _BM_HEAP_ {
IMG_UINT32 * pui32Flags,
IMG_UINT32 uDevVAddrAlignment, BM_HANDLE * phBuf);
+ IMG_BOOL
+ BM_IsWrapped(IMG_HANDLE hDevMemHeap,
+ IMG_UINT32 ui32Offset, IMG_SYS_PHYADDR sSysAddr);
+
IMG_BOOL
BM_Wrap(IMG_HANDLE hDevMemHeap,
IMG_UINT32 ui32Size,
IMG_UINT32 ui32Offset,
IMG_BOOL bPhysContig,
IMG_SYS_PHYADDR * psSysAddr,
+ IMG_BOOL bFreePageList,
IMG_VOID * pvCPUVAddr,
IMG_UINT32 * pui32Flags, BM_HANDLE * phBuf);
ErrorExit:
if (psDCInfo->psFuncTable) {
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psDCInfo->psFuncTable,
- IMG_NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE),
+ psDCInfo->psFuncTable, IMG_NULL);
}
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psDCInfo, IMG_NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DISPLAYCLASS_INFO),
+ psDCInfo, IMG_NULL);
return PVRSRV_ERROR_OUT_OF_MEMORY;
}
psDCInfo = (PVRSRV_DISPLAYCLASS_INFO *) psDeviceNode->pvDevice;
PVR_ASSERT(psDCInfo->ui32RefCount == 0);
FreeDeviceID(psSysData, ui32DevIndex);
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psDCInfo->psFuncTable, IMG_NULL);
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psDCInfo, IMG_NULL);
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psDeviceNode, IMG_NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE),
+ psDCInfo->psFuncTable, IMG_NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DISPLAYCLASS_INFO),
+ psDCInfo, IMG_NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DEVICE_NODE),
+ psDeviceNode, IMG_NULL);
return PVRSRV_OK;
}
ErrorExit:
if (psBCInfo->psFuncTable) {
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psBCInfo->psFuncTable,
- IMG_NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE),
+ psBCInfo->psFuncTable, IMG_NULL);
}
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psBCInfo, IMG_NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BUFFERCLASS_INFO),
+ psBCInfo, IMG_NULL);
return PVRSRV_ERROR_OUT_OF_MEMORY;
}
FreeDeviceID(psSysData, ui32DevIndex);
psBCInfo = (PVRSRV_BUFFERCLASS_INFO *) psDevNode->pvDevice;
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psBCInfo->psFuncTable, IMG_NULL);
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psBCInfo, IMG_NULL);
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psDevNode, IMG_NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE), psBCInfo->psFuncTable,
+ IMG_NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BUFFERCLASS_INFO),
+ psBCInfo, IMG_NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DEVICE_NODE),
+ psDevNode, IMG_NULL);
return PVRSRV_OK;
}
psDCInfo->hExtDevice = IMG_NULL;
}
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psDCPerContextInfo, IMG_NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO),
+ psDCPerContextInfo, IMG_NULL);
return PVRSRV_OK;
}
}
}
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psSwapChain, IMG_NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN),
+ psSwapChain, IMG_NULL);
return eError;
}
}
if (psSwapChain) {
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psSwapChain, IMG_NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN),
+ psSwapChain, IMG_NULL);
}
return eError;
}
if (psBCInfo->psBuffer) {
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0,
- psBCInfo->psBuffer, IMG_NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_BC_BUFFER) *
+ psBCInfo->ui32BufferCount, psBCInfo->psBuffer,
+ IMG_NULL);
}
}
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psBCPerContextInfo, IMG_NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_BUFFERCLASS_PERCONTEXT_INFO),
+ psBCPerContextInfo, IMG_NULL);
return PVRSRV_OK;
}
SYS_DATA *psSysData;
IMG_UINT32 i;
PVRSRV_ERROR eError;
+ BUFFER_INFO sBufferInfo;
if (!phDeviceKM) {
PVR_DPF((PVR_DBG_ERROR,
OSMemSet(psBCPerContextInfo, 0, sizeof(*psBCPerContextInfo));
if (psBCInfo->ui32RefCount++ == 0) {
- BUFFER_INFO sBufferInfo;
-
psDeviceNode = (PVRSRV_DEVICE_NODE *) hDevCookie;
PVR_ASSERT(psDeviceNode != IMG_NULL);
}
if (psBCInfo->psBuffer) {
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psBCInfo->psBuffer,
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_BC_BUFFER) *
+ sBufferInfo.ui32BufferCount, psBCInfo->psBuffer,
IMG_NULL);
}
#include "sgxapi_km.h"
#include "pvr_bridge_km.h"
+#include "linux/kernel.h"
+
static PVRSRV_ERROR AllocDeviceMem(IMG_HANDLE hDevCookie,
IMG_HANDLE hDevMemHeap,
IMG_UINT32 ui32Flags,
if (!bBMError) {
PVR_DPF((PVR_DBG_ERROR, "AllocDeviceMem: BM_Alloc Failed"));
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psMemInfo, IMG_NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
return PVRSRV_ERROR_OUT_OF_MEMORY;
}
psMemInfo->ui32AllocSize = ui32Size;
- psMemInfo->pvSysBackupBuffer = IMG_NULL;
-
*ppsMemInfo = psMemInfo;
return (PVRSRV_OK);
BM_Free(hBuffer, psMemInfo->ui32Flags);
- if (psMemInfo->pvSysBackupBuffer) {
-
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0,
- psMemInfo->pvSysBackupBuffer, IMG_NULL);
- }
-
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psMemInfo, IMG_NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_MEM_INFO),
+ psMemInfo, IMG_NULL);
return (PVRSRV_OK);
}
PVR_DPF((PVR_DBG_ERROR,
"PVRSRVAllocSyncInfoKM: Failed to alloc memory"));
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psKernelSyncInfo,
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_SYNC_INFO), psKernelSyncInfo,
IMG_NULL);
return PVRSRV_ERROR_OUT_OF_MEMORY;
}
psKernelSyncInfo)
{
FreeDeviceMem(psKernelSyncInfo->psSyncDataMemInfoKM);
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psKernelSyncInfo, IMG_NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_SYNC_INFO),
+ psKernelSyncInfo, IMG_NULL);
return PVRSRV_OK;
}
{
PVRSRV_ERROR eError = PVRSRV_OK;
PVRSRV_KERNEL_MEM_INFO *psMemInfo = pvParam;
- IMG_HANDLE hOSWrapMem;
+ IMG_HANDLE hOSWrapMem = IMG_NULL;
+ BM_BUF *psBMBuf;
PVR_UNREFERENCED_PARAMETER(ui32Param);
- hOSWrapMem = psMemInfo->sMemBlk.hOSWrapMem;
+ psBMBuf = (BM_BUF *) psMemInfo->sMemBlk.hBuffer;
- if (psMemInfo->psKernelSyncInfo) {
+ if ((psBMBuf->ui32RefCount == 1) && (psMemInfo->psKernelSyncInfo)) {
eError = PVRSRVFreeSyncInfoKM(psMemInfo->psKernelSyncInfo);
- }
-
- if (psMemInfo->sMemBlk.psIntSysPAddr) {
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0,
- psMemInfo->sMemBlk.psIntSysPAddr, IMG_NULL);
+ hOSWrapMem = psBMBuf->hOSWrapMem;
}
if (eError == PVRSRV_OK) {
IMG_VOID *pvPageAlignedCPUVAddr;
IMG_SYS_PHYADDR *psIntSysPAddr = IMG_NULL;
IMG_HANDLE hOSWrapMem = IMG_NULL;
+ BM_BUF *psBMBuf;
+ IMG_SYS_PHYADDR *pPageList = psExtSysPAddr;
+ IMG_UINT32 ui32PageCount;
psDeviceNode = (PVRSRV_DEVICE_NODE *) hDevCookie;
PVR_ASSERT(psDeviceNode != IMG_NULL);
+ psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+ hDevMemHeap =
+ psDevMemoryInfo->psDeviceMemoryHeap[psDevMemoryInfo->
+ ui32MappingHeapID].hDevMemHeap;
- if (pvLinAddr) {
- IMG_UINT32 ui32PageCount;
+ ui32PageCount =
+ HOST_PAGEALIGN(ui32ByteSize + ui32PageOffset) / ui32HostPageSize;
- ui32PageCount =
- HOST_PAGEALIGN(ui32ByteSize +
- ui32PageOffset) / ui32HostPageSize;
+ if (pvLinAddr) {
pvPageAlignedCPUVAddr =
(IMG_VOID *) ((IMG_UINT8 *) pvLinAddr - ui32PageOffset);
return PVRSRV_ERROR_OUT_OF_MEMORY;
}
+ /* let's start by getting the address of the first page */
eError = OSAcquirePhysPageAddr(pvPageAlignedCPUVAddr,
- ui32PageCount * ui32HostPageSize,
+ ui32HostPageSize,
psIntSysPAddr, &hOSWrapMem);
if (eError != PVRSRV_OK) {
PVR_DPF((PVR_DBG_ERROR,
eError = PVRSRV_ERROR_OUT_OF_MEMORY;
goto ErrorExitPhase1;
}
+ /* now check if this memory address is already wrapped */
+ if (BM_IsWrapped(hDevMemHeap, ui32PageOffset, psIntSysPAddr[0])) {
+ /* already wrapped */
+ OSReleasePhysPageAddr(hOSWrapMem);
+ hOSWrapMem = IMG_NULL;
+ } else if (ui32PageCount > 1) {
+ OSReleasePhysPageAddr(hOSWrapMem);
+ hOSWrapMem = IMG_NULL;
+ /* the memory is going to wrapped for the first time,
+ * so we need full page list */
+ 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;
} else {
}
- psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
- hDevMemHeap =
- psDevMemoryInfo->psDeviceMemoryHeap[psDevMemoryInfo->
- ui32MappingHeapID].hDevMemHeap;
-
if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
sizeof(PVRSRV_KERNEL_MEM_INFO),
(IMG_VOID **) & psMemInfo, IMG_NULL) != PVRSRV_OK) {
ui32PageOffset,
bPhysContig,
psExtSysPAddr,
- IMG_NULL, &psMemInfo->ui32Flags, &hBuffer);
+ IMG_TRUE, IMG_NULL, &psMemInfo->ui32Flags, &hBuffer);
if (!bBMError) {
- PVR_DPF((PVR_DBG_ERROR,
- "PVRSRVWrapExtMemoryKM: BM_Wrap Failed"));
- eError = PVRSRV_ERROR_BAD_MAPPING;
- goto ErrorExitPhase2;
+ /* Alloc failed from current mapping heap, try the other one */
+ psDevMemoryInfo->ui32MappingHeapID =
+ psDevMemoryInfo->ui32MappingHeapID ==
+ SGX_GENERAL_MAPPING_HEAP_ID ? SGX_ALT_MAPPING_HEAP_ID :
+ SGX_GENERAL_MAPPING_HEAP_ID;
+ hDevMemHeap =
+ psDevMemoryInfo->psDeviceMemoryHeap[psDevMemoryInfo->
+ ui32MappingHeapID].
+ hDevMemHeap;
+ bBMError =
+ BM_Wrap(hDevMemHeap, ui32ByteSize, ui32PageOffset,
+ bPhysContig, psExtSysPAddr, IMG_TRUE, IMG_NULL,
+ &psMemInfo->ui32Flags, &hBuffer);
+ if (!bBMError) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVWrapExtMemoryKM: BM_Wrap Failed"));
+ eError = PVRSRV_ERROR_BAD_MAPPING;
+ goto ErrorExitPhase2;
+ }
}
+ /* wrap was successful and BM_Wrap has taken ownership of the page list,
+ * clear psIntSysPAddr here, so we don't double free the memory */
+ psIntSysPAddr = IMG_NULL;
psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
- psMemBlock->hOSWrapMem = hOSWrapMem;
- psMemBlock->psIntSysPAddr = psIntSysPAddr;
psMemBlock->hBuffer = (IMG_HANDLE) 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 ErrorExitPhase2;
+ psBMBuf = (BM_BUF *) hBuffer;
+ if (psBMBuf->ui32RefCount == 1) {
+ eError = PVRSRVAllocSyncInfoKM(hDevCookie,
+ hDevMemContext,
+ &psMemInfo->psKernelSyncInfo);
+ if (eError != PVRSRV_OK) {
+ goto ErrorExitPhase2;
+ }
+ psBMBuf->pvKernelSyncInfo = psMemInfo->psKernelSyncInfo;
+ psBMBuf->hOSWrapMem = hOSWrapMem;
+ } else {
+ psMemInfo->psKernelSyncInfo = psBMBuf->pvKernelSyncInfo;
}
psMemInfo->sMemBlk.hResItem =
ResManRegisterRes(psPerProc->hResManContext,
RESMAN_TYPE_DEVICEMEM_WRAP, psMemInfo, 0,
UnwrapExtMemoryCallBack);
+ /* check if we were passed a page list
+ * but we didn't use use it */
+ if (pPageList && (pPageList != psExtSysPAddr)) {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32PageCount * sizeof(IMG_SYS_PHYADDR),
+ (IMG_VOID *) pPageList, 0);
+ }
*ppsMemInfo = psMemInfo;
FreeDeviceMem(psMemInfo);
}
- if (psIntSysPAddr) {
+ if (hOSWrapMem)
OSReleasePhysPageAddr(hOSWrapMem);
- }
-
ErrorExitPhase1:
if (psIntSysPAddr) {
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psIntSysPAddr, IMG_NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32PageCount * sizeof(IMG_SYS_PHYADDR),
+ psIntSysPAddr, IMG_NULL);
}
return eError;
PVR_UNREFERENCED_PARAMETER(ui32Param);
- if (psMemInfo->sMemBlk.psIntSysPAddr) {
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0,
- psMemInfo->sMemBlk.psIntSysPAddr, IMG_NULL);
- }
-
return FreeDeviceMem(psMemInfo);
}
ui32PageOffset,
IMG_FALSE,
psSysPAddr,
+ IMG_TRUE,
pvPageAlignedCPUVAddr,
&psMemInfo->ui32Flags, &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;
- psMemInfo->pvSysBackupBuffer = IMG_NULL;
-
psMemInfo->sMemBlk.hResItem =
ResManRegisterRes(psPerProc->hResManContext,
RESMAN_TYPE_DEVICEMEM_MAPPING, psMemInfo, 0,
if (psSysPAddr) {
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psSysPAddr, IMG_NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32PageCount * sizeof(IMG_SYS_PHYADDR), psSysPAddr,
+ IMG_NULL);
}
if (psMemInfo) {
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psMemInfo, IMG_NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
}
return eError;
psBMContext = (BM_CONTEXT *) psDeviceClassBuffer->hDevMemContext;
psDevMemoryInfo = &psBMContext->psDeviceNode->sDevMemoryInfo;
hDevMemHeap =
- psDevMemoryInfo->psDeviceMemoryHeap[psDevMemoryInfo->
- ui32MappingHeapID].hDevMemHeap;
+ psDevMemoryInfo->psDeviceMemoryHeap[SGX_GENERAL_MAPPING_HEAP_ID].
+ hDevMemHeap;
ui32Offset = ((IMG_UINT32) pvCPUVAddr) & (ui32PageSize - 1);
pvPageAlignedCPUVAddr =
ui32Offset,
bPhysContig,
psSysPAddr,
+ IMG_FALSE,
pvPageAlignedCPUVAddr,
&psMemInfo->ui32Flags, &hBuffer);
if (!bBMError) {
PVR_DPF((PVR_DBG_ERROR,
"PVRSRVMapDeviceClassMemoryKM: BM_Wrap Failed"));
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psMemInfo, IMG_NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
return PVRSRV_ERROR_BAD_MAPPING;
}
psMemInfo->ui32AllocSize = ui32ByteSize;
psMemInfo->psKernelSyncInfo = psDeviceClassBuffer->psKernelSyncInfo;
- psMemInfo->pvSysBackupBuffer = IMG_NULL;
-
psMemInfo->sMemBlk.hResItem =
ResManRegisterRes(psPerProc->hResManContext,
RESMAN_TYPE_DEVICECLASSMEM_MAPPING, psMemInfo, 0,
#include <linux/interrupt.h>
#include <linux/pci.h>
+#include <linux/workqueue.h>
#define PVRSRV_MAX_BRIDGE_IN_SIZE 0x1000
#define PVRSRV_MAX_BRIDGE_OUT_SIZE 0x1000
IMG_BOOL bMISRInstalled;
IMG_UINT32 ui32IRQ;
IMG_VOID *pvISRCookie;
- struct tasklet_struct sMISRTasklet;
+ struct workqueue_struct *psMISRWorkqueue;
+ struct work_struct sMISRWork;
+ struct workqueue_struct *psPerfWorkqueue;
+ struct delayed_work sPerfWork;
+ IMG_VOID *pvSysData; /*for MISR work */
} ENV_DATA;
#endif
typedef struct PVRSRV_LINUX_EVENT_OBJECT_TAG {
atomic_t sTimeStamp;
IMG_UINT32 ui32TimeStampPrevious;
-#if DEBUG
+#ifdef DEBUG
unsigned int ui32Stats;
#endif
wait_queue_head_t sWait;
if (hOSEventObject) {
PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject =
(PVRSRV_LINUX_EVENT_OBJECT *) hOSEventObject;
-#if DEBUG
+#ifdef DEBUG
PVR_DPF((PVR_DBG_MESSAGE,
"LinuxEventObjectListDelete: Event object waits: %lu",
psLinuxEventObject->ui32Stats));
list_del(&psLinuxEventObject->sList);
write_unlock_bh(&psLinuxEventObjectList->sLock);
-#if DEBUG
+#ifdef DEBUG
PVR_DPF((PVR_DBG_MESSAGE,
"LinuxEventObjectDeleteCallback: Event object waits: %lu",
psLinuxEventObject->ui32Stats));
atomic_set(&psLinuxEventObject->sTimeStamp, 0);
psLinuxEventObject->ui32TimeStampPrevious = 0;
-#if DEBUG
+#ifdef DEBUG
psLinuxEventObject->ui32Stats = 0;
#endif
init_waitqueue_head(&psLinuxEventObject->sWait);
ui32TimeOutJiffies = schedule_timeout(ui32TimeOutJiffies);
-#if DEBUG
+#ifdef DEBUG
psLinuxEventObject->ui32Stats++;
#endif
LinuxLockMutex(&gPVRSRVLock);
ppNewTable[uIndex] = IMG_NULL;
_Rehash(pHash, pHash->ppBucketTable, pHash->uSize, ppNewTable,
uNewSize);
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, pHash->ppBucketTable,
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(BUCKET *) * pHash->uSize, pHash->ppBucketTable,
IMG_NULL);
pHash->ppBucketTable = ppNewTable;
pHash->uSize = uNewSize;
PVR_DPF((PVR_DBG_MESSAGE, "HASH_Delete"));
PVR_ASSERT(pHash->uCount == 0);
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, pHash->ppBucketTable,
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(BUCKET *) * pHash->uSize, pHash->ppBucketTable,
IMG_NULL);
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(HASH_TABLE), pHash,
IMG_NULL);
#include "pvr_debug.h"
#include "osfunc.h"
#include "proc.h"
-#include "mutex.h"
static PKV_OFFSET_STRUCT FindOffsetStructFromLinuxMemArea(LinuxMemArea *
psLinuxMemArea);
static IMG_BOOL DoMapToUser(LinuxMemArea * psLinuxMemArea,
struct vm_area_struct *ps_vma,
IMG_UINT32 ui32ByteOffset, IMG_UINT32 ui32Size);
+static IMG_BOOL CheckSize(LinuxMemArea * psLinuxMemArea, IMG_UINT32 ui32Size);
#if defined(DEBUG_LINUX_MMAP_AREAS)
static off_t PrintMMapRegistrations(char *buffer, size_t size, off_t off);
close: MMapVClose
};
-extern PVRSRV_LINUX_MUTEX gPVRSRVLock;
-
static PKV_OFFSET_STRUCT g_psKVOffsetTable = 0;
static LinuxKMemCache *g_psMemmapCache = 0;
#if defined(DEBUG_LINUX_MMAP_AREAS)
static IMG_UINT32 g_ui32TotalByteSize = 0;
#endif
+static struct rw_semaphore g_mmap_sem;
+
IMG_VOID PVRMMapInit(IMG_VOID)
{
g_psKVOffsetTable = 0;
PVR_DPF((PVR_DBG_ERROR, "%s: failed to allocate kmem_cache",
__FUNCTION__));
}
+ init_rwsem(&g_mmap_sem);
}
IMG_VOID PVRMMapCleanup(void)
LinuxMemArea * psLinuxMemArea, IMG_UINT32 ui32AllocFlags)
{
PKV_OFFSET_STRUCT psOffsetStruct;
-
+ PVRSRV_ERROR iError = PVRSRV_OK;
PVR_DPF((PVR_DBG_MESSAGE,
"%s(%s, psLinuxMemArea=%p, ui32AllocFlags=0x%8lx)",
__FUNCTION__, pszName, psLinuxMemArea, ui32AllocFlags));
+ down_write(&g_mmap_sem);
psOffsetStruct = FindOffsetStructFromLinuxMemArea(psLinuxMemArea);
if (psOffsetStruct) {
PVR_DPF((PVR_DBG_ERROR,
"PVRMMapRegisterArea: psLinuxMemArea=%p is already registered",
psOffsetStruct->psLinuxMemArea));
- return PVRSRV_ERROR_INVALID_PARAMS;
+ iError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto register_exit;
}
psOffsetStruct = KMemCacheAllocWrapper(g_psMemmapCache, GFP_KERNEL);
if (!psOffsetStruct) {
PVR_DPF((PVR_DBG_ERROR,
"PVRMMapRegisterArea: Couldn't alloc another mapping record from cache"));
- return PVRSRV_ERROR_OUT_OF_MEMORY;
+ iError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto register_exit;
}
psOffsetStruct->ui32MMapOffset = GetFirstFreePageAlignedNumber();
psOffsetStruct->psNext = g_psKVOffsetTable;
g_psKVOffsetTable = psOffsetStruct;
-
- return PVRSRV_OK;
+register_exit:
+ up_write(&g_mmap_sem);
+ return iError;
}
PVRSRV_ERROR PVRMMapRemoveRegisteredArea(LinuxMemArea * psLinuxMemArea)
{
PKV_OFFSET_STRUCT *ppsOffsetStruct, psOffsetStruct;
+ PVRSRV_ERROR iError = PVRSRV_OK;
+ down_write(&g_mmap_sem);
for (ppsOffsetStruct = &g_psKVOffsetTable;
(psOffsetStruct = *ppsOffsetStruct);
ppsOffsetStruct = &(*ppsOffsetStruct)->psNext) {
PVR_DPF((PVR_DBG_ERROR,
"%s: Registration for psLinuxMemArea = 0x%p not found",
__FUNCTION__, psLinuxMemArea));
- return PVRSRV_ERROR_BAD_MAPPING;
+ iError = PVRSRV_ERROR_BAD_MAPPING;
+ goto unregister_exit;
}
#if defined(DEBUG_LINUX_MMAP_AREAS)
PVR_DPF((PVR_DBG_ERROR,
"%s: Unregistering still-mapped area! (psLinuxMemArea=0x%p)\n",
__FUNCTION__, psOffsetStruct->psLinuxMemArea));
- return PVRSRV_ERROR_BAD_MAPPING;
+ iError = PVRSRV_ERROR_BAD_MAPPING;
+ goto unregister_exit;
}
g_ui32RegisteredAreas--;
KMemCacheFreeWrapper(g_psMemmapCache, psOffsetStruct);
- return PVRSRV_OK;
+unregister_exit:
+ up_write(&g_mmap_sem);
+ return iError;
}
static PKV_OFFSET_STRUCT
IMG_UINT32 * pui32RealByteSize)
{
PKV_OFFSET_STRUCT psOffsetStruct;
+ PVRSRV_ERROR iError = PVRSRV_OK;
+ down_read(&g_mmap_sem);
psOffsetStruct =
FindOffsetStructByKVIndexAddress(pvKVIndexAddress, ui32Size);
if (!psOffsetStruct) {
- return PVRSRV_ERROR_BAD_MAPPING;
+ iError = PVRSRV_ERROR_BAD_MAPPING;
+ goto indexaddress_exit;
}
*pui32MMapOffset = psOffsetStruct->ui32MMapOffset;
psOffsetStruct->psLinuxMemArea,
pui32RealByteSize, pui32ByteOffset);
- return PVRSRV_OK;
+indexaddress_exit:
+ up_read(&g_mmap_sem);
+ return iError;
}
static PKV_OFFSET_STRUCT
PKV_OFFSET_STRUCT psCurrentRec = NULL;
int iRetVal = 0;
- LinuxLockMutex(&gPVRSRVLock);
-
ulBytes = ps_vma->vm_end - ps_vma->vm_start;
-
+ down_read(&g_mmap_sem);
PVR_DPF((PVR_DBG_MESSAGE,
"%s: Recieved mmap(2) request with a ui32MMapOffset=0x%08lx,"
" and ui32ByteSize=%ld(0x%08lx)\n", __FUNCTION__,
PVR_DPF((PVR_DBG_ERROR,
"PVRMMap: Error - Cannot mmap non-shareable writable areas."));
iRetVal = -EINVAL;
- goto unlock_and_return;
+ goto pvrmmap_exit;
}
psCurrentRec =
"PVRMMap: Error - Attempted to mmap unregistered area at vm_pgoff=%ld",
ps_vma->vm_pgoff));
iRetVal = -EINVAL;
- goto unlock_and_return;
+ goto pvrmmap_exit;
}
PVR_DPF((PVR_DBG_MESSAGE, "%s: > psCurrentRec->psLinuxMemArea=%p\n",
__FUNCTION__, psCurrentRec->psLinuxMemArea));
+ if (!CheckSize(psCurrentRec->psLinuxMemArea, ulBytes)) {
+ iRetVal = -EINVAL;
+ goto pvrmmap_exit;
+ }
ps_vma->vm_flags |= VM_RESERVED;
ps_vma->vm_flags |= VM_IO;
if (!DoMapToUser(psCurrentRec->psLinuxMemArea, ps_vma, 0, ulBytes)) {
iRetVal = -EAGAIN;
- goto unlock_and_return;
+ goto pvrmmap_exit;
}
MMapVOpen(ps_vma);
PVR_DPF((PVR_DBG_MESSAGE, "%s: Mapped area at offset 0x%08lx\n",
__FUNCTION__, ps_vma->vm_pgoff));
-unlock_and_return:
-
- LinuxUnLockMutex(&gPVRSRVLock);
-
+pvrmmap_exit:
+ up_read(&g_mmap_sem);
return iRetVal;
}
return IMG_TRUE;
}
+static IMG_BOOL
+CheckSize(LinuxMemArea * psLinuxMemArea, IMG_UINT32 ui32ByteSize)
+{
+ IMG_CPU_PHYADDR CpuPAddr;
+ IMG_UINT32 ui32PageAlignmentOffset;
+ IMG_UINT32 ui32RealByteSize;
+ CpuPAddr = LinuxMemAreaToCpuPAddr(psLinuxMemArea, 0);
+ ui32PageAlignmentOffset = ADDR_TO_PAGE_OFFSET(CpuPAddr.uiAddr);
+ ui32RealByteSize =
+ PAGE_ALIGN(psLinuxMemArea->ui32ByteSize + ui32PageAlignmentOffset);
+ if (ui32RealByteSize < ui32ByteSize) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "Cannot mmap %ld bytes from: %-8p %-8p %08lx %-8ld %-24s\n",
+ ui32ByteSize,
+ psLinuxMemArea,
+ LinuxMemAreaToCpuVAddr(psLinuxMemArea),
+ LinuxMemAreaToCpuPAddr(psLinuxMemArea, 0).uiAddr,
+ psLinuxMemArea->ui32ByteSize,
+ LinuxMemAreaTypeToString(psLinuxMemArea->eAreaType)));
+ return IMG_FALSE;
+ }
+ return IMG_TRUE;
+}
+
static void MMapVOpen(struct vm_area_struct *ps_vma)
{
#if defined(DEBUG_LINUX_MMAP_AREAS)
PKV_OFFSET_STRUCT psOffsetStruct;
off_t Ret;
- LinuxLockMutex(&gPVRSRVLock);
-
+ down_read(&g_mmap_sem);
if (!off) {
Ret = printAppend(buffer, size, 0,
#if !defined(DEBUG_LINUX_XML_PROC_FILES)
HAPFlagsToString(psOffsetStruct->ui32AllocFlags));
unlock_and_return:
-
- LinuxUnLockMutex(&gPVRSRVLock);
+ up_read(&g_mmap_sem);
return Ret;
}
#endif
if (!bRes) {
PVR_DPF((PVR_DBG_ERROR,
"MMU_Create: ERROR call to _AllocPageTables failed"));
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, pMMUHeap, IMG_NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(MMU_HEAP), pMMUHeap,
+ IMG_NULL);
return IMG_NULL;
}
PVR_DPF((PVR_DBG_ERROR,
"MMU_Create: ERROR call to RA_Create failed"));
_DeferredFreePageTables(pMMUHeap);
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, pMMUHeap, IMG_NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(MMU_HEAP),
+ pMMUHeap, IMG_NULL);
return IMG_NULL;
}
#if 0
DisableHostAccess(pMMUHeap->psMMUContext);
#endif
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, pMMUHeap, IMG_NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(MMU_HEAP),
+ pMMUHeap, IMG_NULL);
}
}
static int AssignedMajorNumber;
-extern int PVRSRV_BridgeDispatchKM(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg);
+extern long PVRSRV_BridgeDispatchKM(struct file *file, unsigned int cmd,
+ unsigned long arg);
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,
-ioctl: PVRSRV_BridgeDispatchKM,
+unlocked_ioctl:PVRSRV_BridgeDispatchKM,
open: PVRSRVOpen,
release:PVRSRVRelease,
mmap: PVRMMap,
PVR_TRACE(("PVRSRVDriverProbe(pDevice=%p)", pDevice));
+ pDevice->dev.driver_data = NULL;
+
#if 0
if (PerDeviceSysInitialise((IMG_PVOID) pDevice) != PVRSRV_OK) {
goto init_failed;
}
+ powervr_device.dev.devt = MKDEV(AssignedMajorNumber, 0);
+
if ((error = platform_device_register(&powervr_device)) != 0) {
platform_driver_unregister(&powervr_driver);
+++ /dev/null
-kernel//home/pratheesh/webkit/release_work/omap3-sgx-modules-1.3.13.1607/services4/3rdparty/dc_omap3430_linux/omaplfb.ko
-kernel//home/pratheesh/webkit/release_work/omap3-sgx-modules-1.3.13.1607/pvrsrvkm.ko
IMG_BOOL bDeviceSuspended;
- spinlock_t *psSwapChainLock;
+ spinlock_t SwapChainLock;
} OMAPLFB_DEVINFO;
#define OMAPLFB_PAGE_SIZE 4096
IMG_BOOL OMAPLFBVSyncIHandler(OMAPLFB_SWAPCHAIN * psSwapChain);
IMG_VOID OMAPLFBEnableVSyncInterrupt(OMAPLFB_SWAPCHAIN * psSwapChain);
IMG_VOID OMAPLFBDisableVSyncInterrupt(OMAPLFB_SWAPCHAIN * psSwapChain);
-#if defined (SUPPORT_TI_DSS_FW)
IMG_VOID OMAPLFBEnableDisplayRegisterAccess(IMG_VOID);
IMG_VOID OMAPLFBDisableDisplayRegisterAccess(IMG_VOID);
-#endif
-#if defined (CONFIG_OMAP2_DSS)
-IMG_VOID OMAPLFBFlipDSS2(OMAPLFB_SWAPCHAIN * psSwapChain, IMG_UINT32 aPhyAddr);
-#endif
IMG_VOID OMAPLFBFlip(OMAPLFB_SWAPCHAIN * psSwapChain, IMG_UINT32 aPhyAddr);
#endif
{
unsigned long ulLockFlags;
- spin_lock_irqsave(psDevInfo->psSwapChainLock, ulLockFlags);
+ spin_lock_irqsave(&psDevInfo->SwapChainLock, ulLockFlags);
SetFlushStateInternalNoLock(psDevInfo, bFlushState);
- spin_unlock_irqrestore(psDevInfo->psSwapChainLock, ulLockFlags);
+ spin_unlock_irqrestore(&psDevInfo->SwapChainLock, ulLockFlags);
}
static IMG_VOID SetFlushStateExternal(OMAPLFB_DEVINFO * psDevInfo,
{
unsigned long ulLockFlags;
- spin_lock_irqsave(psDevInfo->psSwapChainLock, ulLockFlags);
+ spin_lock_irqsave(&psDevInfo->SwapChainLock, ulLockFlags);
if (psDevInfo->bFlushCommands != bFlushState) {
psDevInfo->bFlushCommands = bFlushState;
SetFlushStateInternalNoLock(psDevInfo, bFlushState);
}
- spin_unlock_irqrestore(psDevInfo->psSwapChainLock, ulLockFlags);
+ spin_unlock_irqrestore(&psDevInfo->SwapChainLock, ulLockFlags);
}
static IMG_VOID SetDCState(IMG_HANDLE hDevice, IMG_UINT32 ui32State)
acquire_console_sem();
res = fb_blank(psDevInfo->psLINFBInfo, 0);
release_console_sem();
-#if !defined (CONFIG_OMAP2_DSS)
- /* DSS2 returns error if unblank from a non-suspend state
- ignore the error status for timebeing */
if (res != 0) {
printk(KERN_WARNING DRIVER_PREFIX
": fb_blank failed (%d)", res);
return PVRSRV_ERROR_GENERIC;
}
-#endif
return PVRSRV_OK;
}
-#if defined (CONFIG_OMAP2_DSS)
-
-/*
- Flip implementation for DSS2 using fb_pan_display
-*/
-IMG_VOID OMAPLFBFlipDSS2(OMAPLFB_SWAPCHAIN * psSwapChain, IMG_UINT32 aPhyAddr)
-{
- OMAPLFB_DEVINFO *psDevInfo = GetAnchorPtr();
- struct fb_info *psLINFBInfo = psDevInfo->psLINFBInfo;
- struct fb_var_screeninfo var;
- memcpy(&var, &psLINFBInfo->var, sizeof(struct fb_var_screeninfo));
- var.yoffset =
- (aPhyAddr -
- psLINFBInfo->fix.smem_start) / psLINFBInfo->fix.line_length;
- if (psLINFBInfo->fbops->fb_pan_display != NULL) {
- psLINFBInfo->fbops->fb_pan_display(&var, psLINFBInfo);
-
- }
-}
-#endif
-
static PVRSRV_ERROR EnableLFBEventNotification(OMAPLFB_DEVINFO * psDevInfo)
{
int res;
psSwapChain->ui32InsertIndex = 0;
psSwapChain->ui32RemoveIndex = 0;
psSwapChain->psPVRJTable = &psDevInfo->sPVRJTable;
- psSwapChain->psSwapChainLock = psDevInfo->psSwapChainLock;
+ psSwapChain->psSwapChainLock = &psDevInfo->SwapChainLock;
for (i = 0; i < ui32BufferCount - 1; i++) {
psBuffer[i].psNext = &psBuffer[i + 1];
psVSyncFlips[i].bFlipped = IMG_FALSE;
psVSyncFlips[i].bCmdCompleted = IMG_FALSE;
}
-#if defined (SUPPORT_TI_DSS_FW)
+
OMAPLFBEnableDisplayRegisterAccess();
psSwapChain->pvRegs =
": Couldn't map registers needed for flipping\n");
goto ErrorDisableDisplayRegisters;
}
-#endif
+
if (OMAPLFBInstallVSyncISR(psSwapChain) != PVRSRV_OK) {
printk(KERN_WARNING DRIVER_PREFIX
": ISR handler failed to register\n");
goto ErrorUnmapRegisters;
}
- spin_lock_irqsave(psDevInfo->psSwapChainLock, ulLockFlags);
+ spin_lock_irqsave(&psDevInfo->SwapChainLock, ulLockFlags);
psDevInfo->psSwapChain = psSwapChain;
OMAPLFBEnableVSyncInterrupt(psSwapChain);
}
- spin_unlock_irqrestore(psDevInfo->psSwapChainLock, ulLockFlags);
+ spin_unlock_irqrestore(&psDevInfo->SwapChainLock, ulLockFlags);
eError = EnableLFBEventNotification(psDevInfo);
if (eError != PVRSRV_OK) {
": Couldn't uninstall VSync ISR\n");
}
ErrorUnmapRegisters:
-#if defined (SUPPORT_TI_DSS_FW)
iounmap(psSwapChain->pvRegs);
ErrorDisableDisplayRegisters:
OMAPLFBDisableDisplayRegisterAccess();
-#endif
OMAPLFBFreeKernelMem(psVSyncFlips);
ErrorFreeBuffers:
OMAPLFBFreeKernelMem(psBuffer);
": Couldn't disable framebuffer event notification\n");
}
- spin_lock_irqsave(psDevInfo->psSwapChainLock, ulLockFlags);
+ spin_lock_irqsave(&psDevInfo->SwapChainLock, ulLockFlags);
OMAPLFBDisableVSyncInterrupt(psSwapChain);
psDevInfo->psSwapChain = IMG_NULL;
- spin_unlock_irqrestore(psDevInfo->psSwapChainLock, ulLockFlags);
+ spin_unlock_irqrestore(&psDevInfo->SwapChainLock, ulLockFlags);
if (OMAPLFBUninstallVSyncISR(psSwapChain) != PVRSRV_OK) {
printk(KERN_WARNING DRIVER_PREFIX
": Couldn't uninstall VSync ISR\n");
return PVRSRV_ERROR_GENERIC;
}
-#if defined (SUPPORT_TI_DSS_FW)
iounmap(psSwapChain->pvRegs);
OMAPLFBDisableDisplayRegisterAccess();
-#endif
OMAPLFBFreeKernelMem(psSwapChain->psVSyncFlips);
OMAPLFBFreeKernelMem(psSwapChain->psBuffer);
return PVRSRV_ERROR_INVALID_PARAMS;
}
- spin_lock_irqsave(psDevInfo->psSwapChainLock, ulLockFlags);
+ spin_lock_irqsave(&psDevInfo->SwapChainLock, ulLockFlags);
FlushInternalVSyncQueue(psSwapChain);
OMAPLFBFlip(psSwapChain, psDevInfo->sFBInfo.sSysAddr.uiAddr);
- spin_unlock_irqrestore(psDevInfo->psSwapChainLock, ulLockFlags);
+ spin_unlock_irqrestore(&psDevInfo->SwapChainLock, ulLockFlags);
return PVRSRV_OK;
}
ExitUnlock:
spin_unlock_irqrestore(psSwapChain->psSwapChainLock, ulLockFlags);
+
return bStatus;
}
psBuffer = (OMAPLFB_BUFFER *) psFlipCmd->hExtBuffer;
psSwapChain = (OMAPLFB_SWAPCHAIN *) psFlipCmd->hExtSwapChain;
- spin_lock_irqsave(psDevInfo->psSwapChainLock, ulLockFlags);
+ spin_lock_irqsave(&psDevInfo->SwapChainLock, ulLockFlags);
if (psDevInfo->bDeviceSuspended) {
psSwapChain->psPVRJTable->pfnPVRSRVCmdComplete(hCmdCookie,
goto ExitTrueUnlock;
}
- spin_unlock_irqrestore(psDevInfo->psSwapChainLock, ulLockFlags);
+ spin_unlock_irqrestore(&psDevInfo->SwapChainLock, ulLockFlags);
return IMG_FALSE;
#endif
ExitTrueUnlock:
- spin_unlock_irqrestore(psDevInfo->psSwapChainLock, ulLockFlags);
+ spin_unlock_irqrestore(&psDevInfo->SwapChainLock, ulLockFlags);
return IMG_TRUE;
}
-static PVRSRV_ERROR InitDev(OMAPLFB_DEVINFO * psDevInfo)
+static void SetDevinfo(OMAPLFB_DEVINFO * psDevInfo)
{
- struct fb_info *psLINFBInfo;
- struct module *psLINFBOwner;
OMAPLFB_FBINFO *psPVRFBInfo = &psDevInfo->sFBInfo;
- PVRSRV_ERROR eError = PVRSRV_ERROR_GENERIC;
+ struct fb_info *psLINFBInfo = psDevInfo->psLINFBInfo;
unsigned long FBSize;
- acquire_console_sem();
-
- if (fb_idx < 0 || fb_idx >= num_registered_fb) {
- eError = PVRSRV_ERROR_INVALID_DEVICE;
- goto errRelSem;
- }
-
- psLINFBInfo = registered_fb[fb_idx];
-
- psLINFBOwner = psLINFBInfo->fbops->owner;
- if (!try_module_get(psLINFBOwner)) {
- printk(KERN_INFO DRIVER_PREFIX
- ": Couldn't get framebuffer module\n");
-
- goto errRelSem;
- }
-
- if (psLINFBInfo->fbops->fb_open != NULL) {
- int res;
-
- res = psLINFBInfo->fbops->fb_open(psLINFBInfo, 0);
- if (res != 0) {
- printk(KERN_INFO DRIVER_PREFIX
- ": Couldn't open framebuffer: %d\n", res);
-
- goto errModPut;
- }
- }
-
- psDevInfo->psLINFBInfo = psLINFBInfo;
-
FBSize = (psLINFBInfo->screen_size) != 0 ?
psLINFBInfo->screen_size : psLINFBInfo->fix.smem_len;
DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
psPVRFBInfo->ui32ByteStride = psLINFBInfo->fix.line_length;
psPVRFBInfo->ui32FBSize = FBSize;
psPVRFBInfo->ui32BufferSize =
- psPVRFBInfo->ui32Height * psPVRFBInfo->ui32ByteStride;
+ max(psPVRFBInfo->ui32Height, psPVRFBInfo->ui32Width)
+ * psPVRFBInfo->ui32ByteStride;
psPVRFBInfo->ui32RoundedBufferSize =
OMAPLFB_PAGE_ROUNDUP(psPVRFBInfo->ui32BufferSize);
(psLINFBInfo->var.green.offset == 5) &&
(psLINFBInfo->var.blue.offset == 0) &&
(psLINFBInfo->var.red.msb_right == 0)) {
- printk("PVRSRV_PIXEL_FORMAT_RGB565\n");
psPVRFBInfo->ePixelFormat = PVRSRV_PIXEL_FORMAT_RGB565;
} else {
printk("Unknown FB format\n");
}
- } else {
- if (psLINFBInfo->var.bits_per_pixel == 32) {
- if ((psLINFBInfo->var.red.length == 8) &&
- (psLINFBInfo->var.green.length == 8) &&
- (psLINFBInfo->var.blue.length == 8) &&
- (psLINFBInfo->var.transp.length == 8) &&
- (psLINFBInfo->var.red.offset == 16) &&
- (psLINFBInfo->var.green.offset == 8) &&
- (psLINFBInfo->var.blue.offset == 0) &&
- (psLINFBInfo->var.transp.offset == 24) &&
- (psLINFBInfo->var.red.msb_right == 0)) {
- printk("PVRSRV_PIXEL_FORMAT_ARGB8888\n");
- psPVRFBInfo->ePixelFormat =
- PVRSRV_PIXEL_FORMAT_ARGB8888;
- } else {
- if ((psLINFBInfo->var.red.length == 8) &&
- (psLINFBInfo->var.green.length == 8) &&
- (psLINFBInfo->var.blue.length == 8) &&
- (psLINFBInfo->var.transp.length == 0) &&
- (psLINFBInfo->var.red.offset == 16) &&
- (psLINFBInfo->var.green.offset == 8) &&
- (psLINFBInfo->var.blue.offset == 0) &&
- (psLINFBInfo->var.transp.offset == 0) &&
- (psLINFBInfo->var.red.msb_right == 0)) {
- printk("PVRSRV_PIXEL_FORMAT_RGB888\n");
- printk
- ("EGL library does not support RGB888 !!!\n");
- psPVRFBInfo->ePixelFormat =
- PVRSRV_PIXEL_FORMAT_RGB888;
- } else {
- printk("Unknown FB format\n");
- }
- }
+ } else if (psLINFBInfo->var.bits_per_pixel == 32) {
+ if ((psLINFBInfo->var.red.length == 8) &&
+ (psLINFBInfo->var.green.length == 8) &&
+ (psLINFBInfo->var.blue.length == 8) &&
+ (psLINFBInfo->var.red.offset == 16) &&
+ (psLINFBInfo->var.green.offset == 8) &&
+ (psLINFBInfo->var.blue.offset == 0) &&
+ (psLINFBInfo->var.red.msb_right == 0)) {
+ psPVRFBInfo->ePixelFormat =
+ PVRSRV_PIXEL_FORMAT_ARGB8888;
} else {
printk("Unknown FB format\n");
}
+ } else {
+ printk("Unknown FB format\n");
+ }
+ psDevInfo->sDisplayFormat.pixelformat = psDevInfo->sFBInfo.ePixelFormat;
+ psDevInfo->sDisplayDim.ui32Width = psDevInfo->sFBInfo.ui32Width;
+ psDevInfo->sDisplayDim.ui32Height = psDevInfo->sFBInfo.ui32Height;
+ psDevInfo->sDisplayDim.ui32ByteStride =
+ psDevInfo->sFBInfo.ui32ByteStride;
+ psDevInfo->sSystemBuffer.sSysAddr = psDevInfo->sFBInfo.sSysAddr;
+ psDevInfo->sSystemBuffer.sCPUVAddr = psDevInfo->sFBInfo.sCPUVAddr;
+ psDevInfo->sSystemBuffer.ui32BufferSize =
+ psDevInfo->sFBInfo.ui32RoundedBufferSize;
+}
+
+static struct FB_EVENTS {
+ struct notifier_block notif;
+ OMAPLFB_DEVINFO *psDevInfo;
+} gFBEventsData;
+
+static int FBEvents(struct notifier_block *psNotif,
+ unsigned long event, void *data)
+{
+ if (event == FB_EVENT_MODE_CHANGE) {
+ struct FB_EVENTS *psEvents =
+ container_of(psNotif, struct FB_EVENTS, notif);
+ SetDevinfo(psEvents->psDevInfo);
}
+ return 0;
+}
+
+static PVRSRV_ERROR InitDev(OMAPLFB_DEVINFO * psDevInfo)
+{
+ struct fb_info *psLINFBInfo;
+ struct module *psLINFBOwner;
+ OMAPLFB_FBINFO *psPVRFBInfo = &psDevInfo->sFBInfo;
+ PVRSRV_ERROR eError = PVRSRV_ERROR_GENERIC;
+
+ acquire_console_sem();
+
+ if (fb_idx < 0 || fb_idx >= num_registered_fb) {
+ eError = PVRSRV_ERROR_INVALID_DEVICE;
+ goto errRelSem;
+ }
+
+ psLINFBInfo = registered_fb[fb_idx];
+
+ psLINFBOwner = psLINFBInfo->fbops->owner;
+ if (!try_module_get(psLINFBOwner)) {
+ printk(KERN_INFO DRIVER_PREFIX
+ ": Couldn't get framebuffer module\n");
+
+ goto errRelSem;
+ }
+
+ if (psLINFBInfo->fbops->fb_open != NULL) {
+ int res;
+
+ res = psLINFBInfo->fbops->fb_open(psLINFBInfo, 0);
+ if (res != 0) {
+ printk(KERN_INFO DRIVER_PREFIX
+ ": Couldn't open framebuffer: %d\n", res);
+
+ goto errModPut;
+ }
+ }
+
+ psDevInfo->psLINFBInfo = psLINFBInfo;
+
+ SetDevinfo(psDevInfo);
+
+ gFBEventsData.notif.notifier_call = FBEvents;
+ gFBEventsData.psDevInfo = psDevInfo;
+ fb_register_client(&gFBEventsData.notif);
psDevInfo->sFBInfo.sSysAddr.uiAddr = psPVRFBInfo->sSysAddr.uiAddr;
psDevInfo->sFBInfo.sCPUVAddr = psPVRFBInfo->sCPUVAddr;
return PVRSRV_ERROR_INIT_FAILURE;
}
- spin_lock_init(psDevInfo->psSwapChainLock);
+ spin_lock_init(&psDevInfo->SwapChainLock);
psDevInfo->psSwapChain = IMG_NULL;
psDevInfo->bFlushCommands = IMG_FALSE;
psDevInfo->bDeviceSuspended = IMG_FALSE;
+
psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers =
psDevInfo->sFBInfo.ui32FBSize /
psDevInfo->sFBInfo.ui32RoundedBufferSize;
-#if !defined (SUPPORT_TI_DSS_FW)
- /* DSS2 have trouble with ui32MaxSwapChainBuffers > 3 */
- if (psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers > 3)
- psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers = 3;
-#endif
if (psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers == 0) {
psDevInfo->sDisplayInfo.ui32MaxSwapChains = 0;
psDevInfo->sDisplayInfo.ui32MaxSwapInterval = 0;
strncpy(psDevInfo->sDisplayInfo.szDisplayName,
DISPLAY_DEVICE_NAME, MAX_DISPLAY_NAME_SIZE);
- psDevInfo->sDisplayFormat.pixelformat =
- psDevInfo->sFBInfo.ePixelFormat;
- psDevInfo->sDisplayDim.ui32Width = psDevInfo->sFBInfo.ui32Width;
- psDevInfo->sDisplayDim.ui32Height =
- psDevInfo->sFBInfo.ui32Height;
- psDevInfo->sDisplayDim.ui32ByteStride =
- psDevInfo->sFBInfo.ui32ByteStride;
-
DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
": Maximum number of swap chain buffers: %lu\n",
psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers));
- psDevInfo->sSystemBuffer.sSysAddr = psDevInfo->sFBInfo.sSysAddr;
- psDevInfo->sSystemBuffer.sCPUVAddr =
- psDevInfo->sFBInfo.sCPUVAddr;
- psDevInfo->sSystemBuffer.ui32BufferSize =
- (psDevInfo->sFBInfo.ui32RoundedBufferSize);
-
psDevInfo->sDCJTable.ui32TableSize =
sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE);
psDevInfo->sDCJTable.pfnOpenDCDevice = OpenDCDevice;
OMAPLFB_DEVINFO *psDevInfo = GetAnchorPtr();
unsigned long ulLockFlags;
- spin_lock_irqsave(psDevInfo->psSwapChainLock, ulLockFlags);
+ spin_lock_irqsave(&psDevInfo->SwapChainLock, ulLockFlags);
if (psDevInfo->bDeviceSuspended) {
goto ExitUnlock;
SetFlushStateInternalNoLock(psDevInfo, IMG_TRUE);
- spin_unlock_irqrestore(psDevInfo->psSwapChainLock, ulLockFlags);
+ spin_unlock_irqrestore(&psDevInfo->SwapChainLock, ulLockFlags);
-#if defined (SUPPORT_TI_DSS_FW)
if (psDevInfo->psSwapChain != IMG_NULL) {
OMAPLFBDisableDisplayRegisterAccess();
}
-#endif
+
return;
ExitUnlock:
- spin_unlock_irqrestore(psDevInfo->psSwapChainLock, ulLockFlags);
+ spin_unlock_irqrestore(&psDevInfo->SwapChainLock, ulLockFlags);
}
IMG_VOID OMAPLFBDriverResume(IMG_VOID)
if (!psDevInfo->bDeviceSuspended) {
return;
}
-#if defined (SUPPORT_TI_DSS_FW)
+
if (psDevInfo->psSwapChain != IMG_NULL) {
OMAPLFBEnableDisplayRegisterAccess();
}
-#endif
- spin_lock_irqsave(psDevInfo->psSwapChainLock, ulLockFlags);
+
+ spin_lock_irqsave(&psDevInfo->SwapChainLock, ulLockFlags);
SetFlushStateInternalNoLock(psDevInfo, IMG_FALSE);
psDevInfo->bDeviceSuspended = IMG_FALSE;
- spin_unlock_irqrestore(psDevInfo->psSwapChainLock, ulLockFlags);
+ spin_unlock_irqrestore(&psDevInfo->SwapChainLock, ulLockFlags);
}
#endif
#include <linux/platform_device.h>
#endif
+#include <asm/io.h>
+
+/*#include <asm/arch-omap/display.h>*/
+
#include "img_defs.h"
#include "servicesext.h"
#include "kerneldisplay.h"
#include "omaplfb.h"
#include "pvrmodule.h"
-#if defined (SUPPORT_TI_DSS_FW)
-#include <asm/io.h>
-#include <asm/arch-omap/display.h>
-#else
-#if !defined (CONFIG_OMAP2_DSS)
-#define DISPC_IRQ_VSYNC 0x0002
-extern int omap_dispc_request_irq(unsigned long, void (*)(void *), void *);
-extern void omap_dispc_free_irq(unsigned long, void (*)(void *), void *);
+#if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE)
extern void omap_dispc_set_plane_base(int plane, IMG_UINT32 phys_addr);
-#else
+#elif defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE)
#include <mach/display.h>
-#include <linux/console.h>
-#include <linux/fb.h>
-#endif
+#else
+#error "PVR needs OMAPFB, but it's disabled"
#endif
MODULE_SUPPORTED_DEVICE(DEVNAME);
+extern int omap_dispc_request_irq(unsigned long, void (*)(void *), void *);
+extern void omap_dispc_free_irq(unsigned long, void (*)(void *), void *);
+
#define unref__ __attribute__ ((unused))
IMG_VOID *OMAPLFBAllocKernelMem(IMG_UINT32 ui32Size)
return PVRSRV_OK;
}
-#if !defined (SUPPORT_TI_DSS_FW)
IMG_VOID OMAPLFBEnableVSyncInterrupt(OMAPLFB_SWAPCHAIN * psSwapChain)
{
- OMAPLFBInstallVSyncISR(psSwapChain);
}
IMG_VOID OMAPLFBDisableVSyncInterrupt(OMAPLFB_SWAPCHAIN * psSwapChain)
{
- OMAPLFBUninstallVSyncISR(psSwapChain);
-}
-#else
-static IMG_VOID OMAPLFBVSyncWriteReg(OMAPLFB_SWAPCHAIN * psSwapChain,
- IMG_UINT32 ui32Offset,
- IMG_UINT32 ui32Value)
-{
- IMG_VOID *pvRegAddr =
- (IMG_VOID *) ((IMG_UINT8 *) psSwapChain->pvRegs + ui32Offset);
-
- writel(ui32Value, pvRegAddr);
-}
-
-static IMG_UINT32 OMAPLFBVSyncReadReg(OMAPLFB_SWAPCHAIN * psSwapChain,
- IMG_UINT32 ui32Offset)
-{
- return readl((IMG_UINT8 *) psSwapChain->pvRegs + ui32Offset);
}
-IMG_VOID OMAPLFBEnableVSyncInterrupt(OMAPLFB_SWAPCHAIN * psSwapChain)
-{
#if defined(SYS_USING_INTERRUPTS)
-
- IMG_UINT32 ui32InterruptEnable =
- OMAPLFBVSyncReadReg(psSwapChain, OMAPLCD_IRQENABLE);
- ui32InterruptEnable |= OMAPLCD_INTMASK_VSYNC;
- OMAPLFBVSyncWriteReg(psSwapChain, OMAPLCD_IRQENABLE,
- ui32InterruptEnable);
+#if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE)
+static void OMAPLFBVSyncISR(void *arg)
+#else
+static void OMAPLFBVSyncISR(void *arg, u32 mask)
#endif
-}
-
-IMG_VOID OMAPLFBDisableVSyncInterrupt(OMAPLFB_SWAPCHAIN * psSwapChain)
{
-#if defined(SYS_USING_INTERRUPTS)
-
- IMG_UINT32 ui32InterruptEnable =
- OMAPLFBVSyncReadReg(psSwapChain, OMAPLCD_IRQENABLE);
- ui32InterruptEnable &= ~(OMAPLCD_INTMASK_VSYNC);
- OMAPLFBVSyncWriteReg(psSwapChain, OMAPLCD_IRQENABLE,
- ui32InterruptEnable);
-#endif
+ (void)OMAPLFBVSyncIHandler((OMAPLFB_SWAPCHAIN *) arg);
}
#endif
-#if defined(SYS_USING_INTERRUPTS)
-static void
-#if defined (SUPPORT_TI_DSS_FW)
-OMAPLFBVSyncISR(void *arg, struct pt_regs unref__ * regs)
-#else
-#if defined (CONFIG_OMAP2_DSS)
-OMAPLFBVSyncISR(void *arg, u32 mask)
-#else
-OMAPLFBVSyncISR(void *arg)
-#endif
-#endif
-{
- OMAPLFB_SWAPCHAIN *psSwapChain = (OMAPLFB_SWAPCHAIN *) arg;
- (void)OMAPLFBVSyncIHandler(psSwapChain);
-}
+#if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE)
+#define DISPC_IRQ_VSYNC 0x0002
#endif
-#if !defined (SUPPORT_TI_DSS_FW)
PVRSRV_ERROR OMAPLFBInstallVSyncISR(OMAPLFB_SWAPCHAIN * psSwapChain)
{
-#if !defined (CONFIG_OMAP2_DSS)
+#if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE)
if (omap_dispc_request_irq
(DISPC_IRQ_VSYNC, OMAPLFBVSyncISR, psSwapChain) != 0)
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
#else
if (omap_dispc_register_isr
- ((omap_dispc_isr_t) OMAPLFBVSyncISR, psSwapChain,
- DISPC_IRQ_VSYNC) != 0)
+ (OMAPLFBVSyncISR, psSwapChain, DISPC_IRQ_VSYNC) != 0)
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
#endif
- return PVRSRV_ERROR_OUT_OF_MEMORY; /* not worth a proper mapping */
+
return PVRSRV_OK;
}
PVRSRV_ERROR OMAPLFBUninstallVSyncISR(OMAPLFB_SWAPCHAIN * psSwapChain)
{
-#if !defined (CONFIG_OMAP2_DSS)
+#if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE)
omap_dispc_free_irq(DISPC_IRQ_VSYNC, OMAPLFBVSyncISR, psSwapChain);
#else
- omap_dispc_unregister_isr(OMAPLFBVSyncISR);
-#endif
- return PVRSRV_OK;
-}
-
-IMG_VOID OMAPLFBFlip(OMAPLFB_SWAPCHAIN * psSwapChain, IMG_UINT32 aPhyAddr)
-{
-#if !defined (CONFIG_OMAP2_DSS)
- omap_dispc_set_plane_base(0, aPhyAddr);
-#else
- OMAPLFBFlipDSS2(psSwapChain, aPhyAddr);
-#endif
-}
-#else
-PVRSRV_ERROR OMAPLFBInstallVSyncISR(OMAPLFB_SWAPCHAIN * psSwapChain)
-{
-#if defined(SYS_USING_INTERRUPTS)
- OMAPLFBDisableVSyncInterrupt(psSwapChain);
-
- if (omap2_disp_register_isr(OMAPLFBVSyncISR, psSwapChain,
- DISPC_IRQSTATUS_VSYNC)) {
- printk(KERN_INFO DRIVER_PREFIX
- ": OMAPLFBInstallVSyncISR: Request OMAPLCD IRQ failed\n");
- return PVRSRV_ERROR_INIT_FAILURE;
- }
-#endif
- return PVRSRV_OK;
-}
-
-PVRSRV_ERROR OMAPLFBUninstallVSyncISR(OMAPLFB_SWAPCHAIN * psSwapChain)
-{
-#if defined(SYS_USING_INTERRUPTS)
- OMAPLFBDisableVSyncInterrupt(psSwapChain);
-
- omap2_disp_unregister_isr(OMAPLFBVSyncISR);
-
+ omap_dispc_unregister_isr(OMAPLFBVSyncISR, psSwapChain,
+ DISPC_IRQ_VSYNC);
#endif
return PVRSRV_OK;
}
IMG_VOID OMAPLFBEnableDisplayRegisterAccess(IMG_VOID)
{
- omap2_disp_get_dss();
+ printk(KERN_WARNING DRIVER_PREFIX
+ ": Attempting to call OMAPLFBEnableDisplayRegisterAccess\n");
+ /*omap2_disp_get_dss(); */
}
IMG_VOID OMAPLFBDisableDisplayRegisterAccess(IMG_VOID)
{
- omap2_disp_put_dss();
+ printk(KERN_WARNING DRIVER_PREFIX
+ ": Attempting to call OMAPLFBDisableDisplayRegisterAccess\n");
+ /*omap2_disp_put_dss(); */
}
IMG_VOID OMAPLFBFlip(OMAPLFB_SWAPCHAIN * psSwapChain, IMG_UINT32 aPhyAddr)
{
- IMG_UINT32 control;
-
- OMAPLFBVSyncWriteReg(psSwapChain, OMAPLCD_GFX_BA0, aPhyAddr);
- OMAPLFBVSyncWriteReg(psSwapChain, OMAPLCD_GFX_BA1, aPhyAddr);
-
- control = OMAPLFBVSyncReadReg(psSwapChain, OMAPLCD_CONTROL);
- control |= OMAP_CONTROL_GOLCD;
- OMAPLFBVSyncWriteReg(psSwapChain, OMAPLCD_CONTROL, control);
-}
+#if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE)
+ omap_dispc_set_plane_base(0, aPhyAddr);
+#else
+ omap_dispc_set_plane_ba0(OMAP_DSS_CHANNEL_LCD, OMAP_DSS_GFX, aPhyAddr);
#endif
+}
#if defined(LDM_PLATFORM)
#define HOST_ALLOC_MEM_USING_KMALLOC ((IMG_HANDLE)0)
#define HOST_ALLOC_MEM_USING_VMALLOC ((IMG_HANDLE)1)
+#define LINUX_KMALLOC_LIMIT PAGE_SIZE /* 4k */
+
#if !defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
PVRSRV_ERROR OSAllocMem(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size,
IMG_PVOID * ppvCpuVAddr, IMG_HANDLE * phBlockAlloc)
IMG_CHAR * pszFilename, IMG_UINT32 ui32Line)
#endif
{
+ IMG_UINT32 ui32Threshold;
+
PVR_UNREFERENCED_PARAMETER(ui32Flags);
+ /* determine whether to go straight to vmalloc */
+ ui32Threshold = LINUX_KMALLOC_LIMIT;
+
+ if (ui32Size > ui32Threshold) {
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
- *ppvCpuVAddr = _KMallocWrapper(ui32Size, pszFilename, ui32Line);
+ *ppvCpuVAddr = _VMallocWrapper(ui32Size, PVRSRV_HAP_CACHED,
+ pszFilename, ui32Line);
#else
- *ppvCpuVAddr = KMallocWrapper(ui32Size);
+ *ppvCpuVAddr = VMallocWrapper(ui32Size, PVRSRV_HAP_CACHED);
#endif
- if (*ppvCpuVAddr) {
- if (phBlockAlloc) {
+ if (!*ppvCpuVAddr)
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
- *phBlockAlloc = HOST_ALLOC_MEM_USING_KMALLOC;
- }
+ if (phBlockAlloc)
+ *phBlockAlloc = HOST_ALLOC_MEM_USING_VMALLOC;
} else {
- if (!phBlockAlloc) {
- return PVRSRV_ERROR_OUT_OF_MEMORY;
- }
+ /* default - try kmalloc first */
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
- *ppvCpuVAddr =
- _VMallocWrapper(ui32Size, PVRSRV_HAP_CACHED, pszFilename,
- ui32Line);
+ *ppvCpuVAddr = _KMallocWrapper(ui32Size, pszFilename, ui32Line);
#else
- *ppvCpuVAddr = VMallocWrapper(ui32Size, PVRSRV_HAP_CACHED);
+ *ppvCpuVAddr = KMallocWrapper(ui32Size);
#endif
- if (!*ppvCpuVAddr) {
+
+ if (!*ppvCpuVAddr)
return PVRSRV_ERROR_OUT_OF_MEMORY;
- }
- *phBlockAlloc = HOST_ALLOC_MEM_USING_VMALLOC;
+ if (phBlockAlloc)
+ *phBlockAlloc = HOST_ALLOC_MEM_USING_KMALLOC;
+
}
return PVRSRV_OK;
#endif
{
PVR_UNREFERENCED_PARAMETER(ui32Flags);
- PVR_UNREFERENCED_PARAMETER(ui32Size);
- if (hBlockAlloc == HOST_ALLOC_MEM_USING_VMALLOC) {
+ if (ui32Size > LINUX_KMALLOC_LIMIT) {
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
_VFreeWrapper(pvCpuVAddr, pszFilename, ui32Line);
#else
return PVRSRV_ERROR_GENERIC;
}
+ memset(psEnvData, 0, sizeof(*psEnvData));
+
if (OSAllocMem
(PVRSRV_OS_PAGEABLE_HEAP,
PVRSRV_MAX_BRIDGE_IN_SIZE + PVRSRV_MAX_BRIDGE_OUT_SIZE,
PVR_ASSERT(!psEnvData->bMISRInstalled);
PVR_ASSERT(!psEnvData->bLISRInstalled);
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0x1000, psEnvData->pvBridgeData,
- IMG_NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ PVRSRV_MAX_BRIDGE_IN_SIZE + PVRSRV_MAX_BRIDGE_OUT_SIZE,
+ psEnvData->pvBridgeData, IMG_NULL);
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(ENV_DATA), pvEnvSpecificData,
IMG_NULL);
SYS_DATA *psSysData = psDeviceNode->psSysData;
ENV_DATA *psEnvData = (ENV_DATA *) psSysData->pvEnvSpecificData;
- tasklet_schedule(&psEnvData->sMISRTasklet);
+ queue_work(psEnvData->psMISRWorkqueue, &psEnvData->sMISRWork);
}
out:
if (bStatus) {
ENV_DATA *psEnvData = (ENV_DATA *) psSysData->pvEnvSpecificData;
- tasklet_schedule(&psEnvData->sMISRTasklet);
+ queue_work(psEnvData->psMISRWorkqueue, &psEnvData->sMISRWork);
}
out:
return PVRSRV_OK;
}
-static void MISRWrapper(unsigned long data)
+static void MISRWrapper(struct work_struct *work)
{
- SYS_DATA *psSysData;
-
- psSysData = (SYS_DATA *) data;
-
+ ENV_DATA *psEnvData = container_of(work, ENV_DATA, sMISRWork);
+ SYS_DATA *psSysData = (SYS_DATA *) psEnvData->pvSysData;
PVRSRVMISR(psSysData);
}
PVR_TRACE(("Installing MISR with cookie %x", pvSysData));
- tasklet_init(&psEnvData->sMISRTasklet, MISRWrapper,
- (unsigned long)pvSysData);
+ psEnvData->pvSysData = pvSysData;
+ psEnvData->psMISRWorkqueue = create_singlethread_workqueue("sgx_misr");
+ INIT_WORK(&psEnvData->sMISRWork, MISRWrapper);
psEnvData->bMISRInstalled = IMG_TRUE;
PVR_TRACE(("Uninstalling MISR"));
- tasklet_kill(&psEnvData->sMISRTasklet);
+ flush_workqueue(psEnvData->psMISRWorkqueue);
+ destroy_workqueue(psEnvData->psMISRWorkqueue);
psEnvData->bMISRInstalled = IMG_FALSE;
ENV_DATA *psEnvData = (ENV_DATA *) psSysData->pvEnvSpecificData;
if (psEnvData->bMISRInstalled) {
- tasklet_schedule(&psEnvData->sMISRTasklet);
+ queue_work(psEnvData->psMISRWorkqueue, &psEnvData->sMISRWork);
}
return PVRSRV_OK;
PVRSRV_ERROR OSUninstallSystemLISR(IMG_VOID * pvSysData);
PVRSRV_ERROR OSInstallMISR(IMG_VOID * pvSysData);
PVRSRV_ERROR OSUninstallMISR(IMG_VOID * pvSysData);
+ PVRSRV_ERROR OSInitPerf(IMG_VOID * pvSysData);
+ PVRSRV_ERROR OSCleanupPerf(IMG_VOID * pvSysData);
IMG_CPU_PHYADDR OSMapLinToCPUPhys(IMG_VOID * pvLinAddr);
IMG_VOID OSMemCopy(IMG_VOID * pvDst, IMG_VOID * pvSrc,
IMG_UINT32 ui32Size);
* Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
*
******************************************************************************/
-
#include "services_headers.h"
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
static IMG_BOOL gbInitServerRunning = IMG_FALSE;
static IMG_BOOL gbInitServerRan = IMG_FALSE;
static IMG_BOOL gbInitSuccessful = IMG_FALSE;
+static DEFINE_MUTEX(hPowerAndFreqLock);
+static DECLARE_WAIT_QUEUE_HEAD(hDvfsWq);
+static IMG_BOOL gbDvfsActive;
IMG_EXPORT
PVRSRV_ERROR PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_STATE
return (IMG_BOOL) (eSystemPowerState < PVRSRV_POWER_STATE_D2);
}
+IMG_EXPORT IMG_VOID PVRSRVDvfsLock(IMG_VOID)
+{
+ mutex_lock(&hPowerAndFreqLock);
+ gbDvfsActive = 1;
+ mutex_unlock(&hPowerAndFreqLock);
+}
+
+IMG_EXPORT IMG_VOID PVRSRVDvfsUnlock(IMG_VOID)
+{
+ mutex_lock(&hPowerAndFreqLock);
+ gbDvfsActive = 0;
+ wake_up(&hDvfsWq);
+ mutex_unlock(&hPowerAndFreqLock);
+}
+
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
-
- eError = SysAcquireData(&psSysData);
- if (eError != PVRSRV_OK) {
- return eError;
+ if ((ui32CallerID == TIMER_ID) &&
+ (mutex_is_locked(&hPowerAndFreqLock) || gbDvfsActive))
+ return PVRSRV_ERROR_RETRY;
+ mutex_lock(&hPowerAndFreqLock);
+ while (gbDvfsActive) {
+ DEFINE_WAIT(__wait);
+ prepare_to_wait(&hDvfsWq, &__wait, TASK_UNINTERRUPTIBLE);
+ mutex_unlock(&hPowerAndFreqLock);
+ schedule();
+ mutex_lock(&hPowerAndFreqLock);
+ finish_wait(&hDvfsWq, &__wait);
}
-
- 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 ((eError == PVRSRV_OK) &&
- !bSystemPowerEvent &&
- !_IsSystemStatePowered(psSysData->eCurrentPowerState)) {
-
- PVRSRVPowerUnlock(ui32CallerID);
- eError = PVRSRV_ERROR_RETRY;
- }
-
- return eError;
+ return PVRSRV_OK;
}
IMG_EXPORT IMG_VOID PVRSRVPowerUnlock(IMG_UINT32 ui32CallerID)
{
- OSUnlockResource(&gpsSysData->sPowerStateChangeResource, ui32CallerID);
+ mutex_unlock(&hPowerAndFreqLock);
}
static
psPowerDevice->
eCurrentPowerState);
if (eError != PVRSRV_OK) {
+ pr_err
+ ("pfnPrePower failed (%u)\n",
+ eError);
return eError;
}
}
psPowerDevice->
eCurrentPowerState);
if (eError != PVRSRV_OK) {
+ pr_err
+ ("SysDevicePrePowerState failed (%u)\n",
+ eError);
return eError;
}
}
psPowerDevice->
eCurrentPowerState);
if (eError != PVRSRV_OK) {
+ pr_err
+ ("SysDevicePostPowerState failed (%u)\n",
+ eError);
return eError;
}
psPowerDevice->
eCurrentPowerState);
if (eError != PVRSRV_OK) {
+ pr_err
+ ("pfnPostPower failed (%u)\n",
+ eError);
return eError;
}
}
return PVRSRV_OK;
}
-PVRSRV_ERROR PVRSRVSetDevicePowerStateCoreKM(IMG_UINT32 ui32DeviceIndex,
- PVR_POWER_STATE eNewPowerState)
-{
- PVRSRV_ERROR eError;
- eError =
- PVRSRVDevicePrePowerStateKM(IMG_FALSE, ui32DeviceIndex,
- eNewPowerState);
- if (eError != PVRSRV_OK) {
- return eError;
- }
-
- eError =
- PVRSRVDevicePostPowerStateKM(IMG_FALSE, ui32DeviceIndex,
- eNewPowerState);
- return eError;
-}
-
IMG_EXPORT
PVRSRV_ERROR PVRSRVSetDevicePowerStateKM(IMG_UINT32 ui32DeviceIndex,
PVR_POWER_STATE eNewPowerState,
psCurrent->psNext;
}
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psCurrent,
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_POWER_DEV), psCurrent,
IMG_NULL);
break;
return IMG_FALSE;
}
-IMG_VOID PVRSRVDevicePreClockSpeedChange(IMG_UINT32 ui32DeviceIndex,
- IMG_BOOL bIdleDevice,
- IMG_VOID * pvInfo)
+PVRSRV_ERROR PVRSRVDevicePreClockSpeedChange(IMG_UINT32 ui32DeviceIndex,
+ IMG_BOOL bIdleDevice,
+ IMG_VOID * pvInfo)
{
- PVRSRV_ERROR eError;
+ PVRSRV_ERROR eError = PVRSRV_OK;
SYS_DATA *psSysData;
PVRSRV_POWER_DEV *psPowerDevice;
psPowerDevice->
pfnPreClockSpeedChange(psPowerDevice->
hDevCookie,
- bIdleDevice);
+ bIdleDevice,
+ psPowerDevice->
+ eCurrentPowerState);
if (eError != PVRSRV_OK) {
+ pr_err
+ ("pfnPreClockSpeedChange failed\n");
PVR_DPF((PVR_DBG_ERROR,
"PVRSRVDevicePreClockSpeedChange : Device %lu failed, error:0x%lx",
ui32DeviceIndex, eError));
psPowerDevice = psPowerDevice->psNext;
}
+ return eError;
}
IMG_VOID PVRSRVDevicePostClockSpeedChange(IMG_UINT32 ui32DeviceIndex,
IMG_BOOL bIdleDevice,
IMG_VOID * pvInfo)
{
- PVRSRV_ERROR eError;
+ PVRSRV_ERROR eError = PVRSRV_OK;
SYS_DATA *psSysData;
PVRSRV_POWER_DEV *psPowerDevice;
psPowerDevice->
pfnPostClockSpeedChange(psPowerDevice->
hDevCookie,
- bIdleDevice);
+ bIdleDevice,
+ psPowerDevice->
+ eCurrentPowerState);
if (eError != PVRSRV_OK) {
+ pr_err
+ ("pfnPostClockSpeedChange failed\n");
PVR_DPF((PVR_DBG_ERROR,
"PVRSRVDevicePostClockSpeedChange : Device %lu failed, error:0x%lx",
ui32DeviceIndex, eError));
IMG_BOOL bSystemPowerEvent);
IMG_IMPORT IMG_VOID PVRSRVPowerUnlock(IMG_UINT32 ui32CallerID);
+ IMG_IMPORT IMG_VOID PVRSRVDvfsLock(IMG_VOID);
+
+ IMG_IMPORT IMG_VOID PVRSRVDvfsUnlock(IMG_VOID);
+
IMG_IMPORT
PVRSRV_ERROR PVRSRVSetDevicePowerStateKM(IMG_UINT32 ui32DeviceIndex,
PVR_POWER_STATE
IMG_IMPORT IMG_BOOL PVRSRVIsDevicePowered(IMG_UINT32 ui32DeviceIndex);
IMG_IMPORT
- IMG_VOID PVRSRVDevicePreClockSpeedChange(IMG_UINT32 ui32DeviceIndex,
- IMG_BOOL bIdleDevice,
- IMG_VOID * pvInfo);
+ PVRSRV_ERROR PVRSRVDevicePreClockSpeedChange(IMG_UINT32
+ ui32DeviceIndex,
+ IMG_BOOL bIdleDevice,
+ IMG_VOID * pvInfo);
IMG_IMPORT
IMG_VOID PVRSRVDevicePostClockSpeedChange(IMG_UINT32
#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_CORE_CMD_LAST (PVRSRV_BRIDGE_CORE_CMD_FIRST+25)
+#define PVRSRV_BRIDGE_CACHE_FLUSH_DRM PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+26)
+#define PVRSRV_BRIDGE_CORE_CMD_LAST (PVRSRV_BRIDGE_CORE_CMD_FIRST+26)
#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)
} PVRSRV_BRIDGE_IN_UNMAPMEMINFOFROMUSER;
+#define DRM_PVR2D_CFLUSH_FROM_GPU 1
+#define DRM_PVR2D_CFLUSH_TO_GPU 2
+
+ typedef struct PVRSRV_BRIDGE_IN_CACHEFLUSHDRMFROMUSER_TAG {
+ IMG_UINT32 ui32BridgeFlags;
+ IMG_UINT32 ui32Type;
+ IMG_UINT32 ui32Virt;
+ IMG_UINT32 ui32Length;
+
+ } PVRSRV_BRIDGE_IN_CACHEFLUSHDRMFROMUSER;
+
typedef struct PVRSRV_BRIDGE_IN_FREEDEVICEMEM_TAG {
IMG_UINT32 ui32BridgeFlags;
IMG_HANDLE hDevCookie;
}
#endif
-int
-PVRSRV_BridgeDispatchKM(struct inode *inode,
- struct file *file, unsigned int cmd, unsigned long arg)
+long
+PVRSRV_BridgeDispatchKM(struct file *file, unsigned int cmd, unsigned long arg)
{
IMG_UINT32 ui32BridgeID = PVRSRV_GET_BRIDGE_ID(cmd);
PVRSRV_BRIDGE_PACKAGE *psBridgePackageUM =
eError = pfnRegisterDevice(psDeviceNode);
if (eError != PVRSRV_OK) {
OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
- 0, psDeviceNode, IMG_NULL);
+ sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL);
PVR_DPF((PVR_DBG_ERROR,
"PVRSRVRegisterDevice : Failed to register device"));
return (PVRSRV_ERROR_DEVICE_REGISTER_FAILED);
*ppsDevNode = psDeviceNode->psNext;
FreeDeviceID(psSysData, ui32DevIndex);
- OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, 0, psDeviceNode, IMG_NULL);
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_DEVICE_NODE),
+ psDeviceNode, IMG_NULL);
return (PVRSRV_OK);
}
"PVRSRVRegisterCmdProcListKM: Failed to alloc CC data"));
goto ErrorExit;
}
+ /* clear the list to ensure that we don't try to access uninitialised pointer
+ * in the 'error' execution path */
+ OSMemSet(psSysData->ppsCmdCompleteData[ui32DevIndex], 0x00,
+ ui32AllocSize);
for (i = 0; i < ui32CmdCount; i++) {
psCmdCompleteData->psSrcSync = (PVRSRV_SYNC_OBJECT *)
(((IMG_UINT32) psCmdCompleteData->psDstSync)
+ (sizeof(PVRSRV_SYNC_OBJECT) * ui32MaxSyncsPerCmd[i][0]));
+ psCmdCompleteData->ui32AllocSize = ui32AllocSize;
}
return PVRSRV_OK;
for (i = 0; i < ui32CmdCount; i++) {
if (psSysData->ppsCmdCompleteData[ui32DevIndex][i] !=
IMG_NULL) {
- OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, 0,
- psSysData->
- ppsCmdCompleteData[ui32DevIndex][i],
- IMG_NULL);
+ psCmdCompleteData =
+ psSysData->
+ ppsCmdCompleteData[ui32DevIndex][i];
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ psCmdCompleteData->ui32AllocSize,
+ psCmdCompleteData, IMG_NULL);
}
}
- OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, 0,
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ ui32CmdCount * sizeof(COMMAND_COMPLETE_DATA *),
psSysData->ppsCmdCompleteData[ui32DevIndex],
IMG_NULL);
}
if (psSysData->ppfnCmdProcList[ui32DevIndex] != IMG_NULL) {
- OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, 0,
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ ui32CmdCount * sizeof(PFN_CMD_PROC),
psSysData->ppfnCmdProcList[ui32DevIndex], IMG_NULL);
}
if (psSysData->ppsCmdCompleteData[ui32DevIndex][i] !=
IMG_NULL) {
- OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, 0,
- psSysData->
- ppsCmdCompleteData[ui32DevIndex][i],
- IMG_NULL);
+ COMMAND_COMPLETE_DATA *psCmdCompleteData =
+ psSysData->
+ ppsCmdCompleteData[ui32DevIndex][i];
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ psCmdCompleteData->ui32AllocSize,
+ psCmdCompleteData, IMG_NULL);
}
}
- OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, 0,
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ ui32CmdCount * sizeof(COMMAND_COMPLETE_DATA *),
psSysData->ppsCmdCompleteData[ui32DevIndex],
IMG_NULL);
}
if (psSysData->ppfnCmdProcList[ui32DevIndex] != IMG_NULL) {
- OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, 0,
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ ui32CmdCount * sizeof(PFN_CMD_PROC),
psSysData->ppfnCmdProcList[ui32DevIndex], IMG_NULL);
}
IMG_UINT32 ui32SrcSyncCount;
PVRSRV_SYNC_OBJECT *psDstSync;
PVRSRV_SYNC_OBJECT *psSrcSync;
+ IMG_UINT32 ui32AllocSize;
} COMMAND_COMPLETE_DATA, *PCOMMAND_COMPLETE_DATA;
#if !defined(USE_CODE)
insert_fail:
HASH_Delete(pArena->pSegmentHash);
hash_fail:
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, pArena, IMG_NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RA_ARENA), pArena, IMG_NULL);
arena_fail:
return IMG_NULL;
}
RemoveProcEntry(pArena->szProcSegsName);
#endif
HASH_Delete(pArena->pSegmentHash);
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, pArena, IMG_NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RA_ARENA), pArena, IMG_NULL);
}
IMG_BOOL RA_Add(RA_ARENA * pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize)
psResManContext->psNext->ppsThis = psResManContext->ppsThis;
}
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psResManContext, IMG_NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RESMAN_CONTEXT),
+ psResManContext, IMG_NULL);
VALIDATERESLIST();
ACQUIRE_SYNC_OBJ;
- if (OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psItem, IMG_NULL) !=
- PVRSRV_OK) {
+ if (OSFreeMem
+ (PVRSRV_OS_PAGEABLE_HEAP, sizeof(RESMAN_ITEM), psItem, IMG_NULL)
+ != PVRSRV_OK) {
PVR_DPF((PVR_DBG_ERROR,
"FreeResourceByPtr: ERROR freeing resource list item memory"));
eError = PVRSRV_ERROR_GENERIC;
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 PVRSRV_ERROR(*PFN_POST_POWER) (IMG_HANDLE, PVR_POWER_STATE,
PVR_POWER_STATE);
-typedef PVRSRV_ERROR(*PFN_PRE_CLOCKSPEED_CHANGE) (IMG_HANDLE, IMG_BOOL);
-typedef PVRSRV_ERROR(*PFN_POST_CLOCKSPEED_CHANGE) (IMG_HANDLE, IMG_BOOL);
+typedef PVRSRV_ERROR(*PFN_PRE_CLOCKSPEED_CHANGE) (IMG_HANDLE, IMG_BOOL,
+ PVR_POWER_STATE);
+typedef PVRSRV_ERROR(*PFN_POST_CLOCKSPEED_CHANGE) (IMG_HANDLE, IMG_BOOL,
+ PVR_POWER_STATE);
typedef enum _PVRSRV_PIXEL_FORMAT_ {
PVRSRV_PIXEL_FORMAT_UNKNOWN = 0,
PVRSRV_MEMBLK sMemBlk;
- IMG_PVOID pvSysBackupBuffer;
-
struct _PVRSRV_KERNEL_SYNC_INFO_ *psKernelSyncInfo;
} PVRSRV_KERNEL_MEM_INFO;
--- /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 "services_headers.h"
+#include "sgxinfo.h"
+#include "sgxinfokm.h"
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+
+#include "sgx2dcore.h"
+
+#define SGX2D_FLUSH_BH 0xF0000000
+#define SGX2D_FENCE_BH 0x70000000
+
+#define SGX2D_QUEUED_BLIT_PAD 4
+
+#define SGX2D_COMMAND_QUEUE_SIZE 1024
+
+#define SGX2D_2D_NOT_IDLE(psDevInfo) ((psDevInfo)->ui322DFifoSize > SGX2DFifoFreeSpace(psDevInfo) || SGX2DIsBusy(psDevInfo))
+
+static IMG_VOID SGX2DHardwareKick(PVRSRV_SGXDEV_INFO * psDevInfo)
+{
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS,
+ EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_MASK |
+ EUR_CR_EVENT_STATUS_TWOD_COMPLETE_MASK);
+}
+
+IMG_VOID SGX2DHWRecoveryStart(PVRSRV_SGXDEV_INFO * psDevInfo)
+{
+ psDevInfo->b2DHWRecoveryInProgress = IMG_TRUE;
+ psDevInfo->b2DHWRecoveryEndPending = IMG_FALSE;
+}
+
+IMG_VOID SGX2DHWRecoveryEnd(PVRSRV_SGXDEV_INFO * psDevInfo)
+{
+ psDevInfo->b2DHWRecoveryEndPending = IMG_TRUE;
+ psDevInfo->b2DHWRecoveryInProgress = IMG_FALSE;
+ SGX2DHardwareKick(psDevInfo);
+}
+
+#if !defined(NO_HARDWARE)
+static IMG_VOID SGX2DKick(PVRSRV_SGXDEV_INFO * psDevInfo)
+{
+ IMG_BOOL bStart = IMG_FALSE;
+ IMG_UINT32 uiStart = 0;
+
+ PVR_UNREFERENCED_PARAMETER(psDevInfo);
+
+ do {
+ if (PVRSRVProcessQueues(KERNEL_ID, IMG_FALSE) !=
+ PVRSRV_ERROR_PROCESSING_BLOCKED) {
+ break;
+ }
+
+ if (bStart == IMG_FALSE) {
+ uiStart = OSClockus();
+ bStart = IMG_TRUE;
+ }
+ OSWaitus(MAX_HW_TIME_US / WAIT_TRY_COUNT);
+ } while ((OSClockus() - uiStart) < MAX_HW_TIME_US);
+}
+#endif
+
+IMG_BOOL SGX2DIsBusy(PVRSRV_SGXDEV_INFO * psDevInfo)
+{
+ IMG_UINT32 ui32BlitStatus;
+
+ ui32BlitStatus = OSReadHWReg(psDevInfo->pvRegsBaseKM,
+ EUR_CR_2D_BLIT_STATUS);
+
+ return (ui32BlitStatus & EUR_CR_2D_BLIT_STATUS_BUSY_MASK) != 0;
+}
+
+IMG_UINT32 SGX2DCompletedBlits(PVRSRV_SGXDEV_INFO * psDevInfo)
+{
+ IMG_UINT32 ui32BlitStatus;
+
+ ui32BlitStatus = OSReadHWReg(psDevInfo->pvRegsBaseKM,
+ EUR_CR_2D_BLIT_STATUS);
+
+ return (ui32BlitStatus & EUR_CR_2D_BLIT_STATUS_COMPLETE_MASK) >>
+ EUR_CR_2D_BLIT_STATUS_COMPLETE_SHIFT;
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SGX2DAcquireSlavePort)
+#endif
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SGX2DAcquireSlavePort)
+#endif
+static INLINE
+ PVRSRV_ERROR SGX2DAcquireSlavePort(PVRSRV_SGXDEV_INFO * psDevInfo,
+ IMG_BOOL bBlock)
+{
+#if defined(SGX2D_DIRECT_BLITS)
+ PVR_UNREFERENCED_PARAMETER(bBlock);
+ return OSLockResource(&psDevInfo->s2DSlaveportResource, ISR_ID);
+#else
+ PVR_UNREFERENCED_PARAMETER(psDevInfo);
+ PVR_UNREFERENCED_PARAMETER(bBlock);
+
+ return PVRSRV_OK;
+#endif
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SGX2DReleaseSlavePort)
+#endif
+static INLINE PVRSRV_ERROR SGX2DReleaseSlavePort(PVRSRV_SGXDEV_INFO * psDevInfo)
+{
+#if defined(SGX2D_DIRECT_BLITS)
+ return OSUnlockResource(&psDevInfo->s2DSlaveportResource, ISR_ID);
+#else
+ PVR_UNREFERENCED_PARAMETER(psDevInfo);
+
+ return PVRSRV_OK;
+#endif
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SGX2DAcquireFifoSpace)
+#endif
+static INLINE
+ PVRSRV_ERROR SGX2DAcquireFifoSpace(PVRSRV_SGXDEV_INFO * psDevInfo,
+ IMG_UINT32 ui32MinBytesRequired,
+ IMG_UINT32 * pui32BytesObtained)
+{
+ PVRSRV_ERROR eError = PVRSRV_ERROR_FIFO_SPACE;
+ IMG_UINT32 ui32FifoBytes;
+
+#if defined(DEBUG) && defined(SGX2D_DIRECT_BLITS)
+
+ if (OSIsResourceLocked(&psDevInfo->s2DSlaveportResource, ISR_ID) ==
+ IMG_FALSE) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "SGX2DAcquireFifoSpace: 2D slaveport is not locked"));
+ return PVRSRV_ERROR_PROCESSING_BLOCKED;
+ }
+#endif
+
+ ui32FifoBytes = SGX2DFifoFreeSpace(psDevInfo);
+
+ if (ui32FifoBytes >= ui32MinBytesRequired) {
+ if (pui32BytesObtained)
+ *pui32BytesObtained = ui32FifoBytes;
+
+ eError = PVRSRV_OK;
+ }
+
+ return eError;
+}
+
+#if defined(DEBUG) && defined (SGX2D_TRACE_BLIT)
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SGX2DTraceBlt)
+#endif
+FORCE_INLINE
+ IMG_VOID SGX2DTraceBlt(IMG_UINT32 * pui32BltData, IMG_UINT32 ui32Count)
+{
+ IMG_UINT32 i;
+
+ PVR_TRACE(("----SGX 2D BLIT----"));
+
+ for (i = 0; i < ui32Count; i++) {
+ PVR_TRACE(("word[%02d]: 0x%08x", i, pui32BltData[i]));
+ }
+}
+#else
+#define SGX2DTraceBlt(pui32BltData, ui32Count)
+#endif
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SGX2DWriteSlavePort)
+#endif
+FORCE_INLINE
+ IMG_VOID SGX2DWriteSlavePort(PVRSRV_SGXDEV_INFO * psDevInfo,
+ IMG_UINT32 ui32Value)
+{
+ SGX_SLAVE_PORT *psSlavePort = &psDevInfo->s2DSlavePortKM;
+#if defined(SGX2D_INCREMENTING_SP_WRITES)
+ IMG_UINT32 *pui32Offset = psSlavePort->pui32Offset;
+
+ if (*pui32Offset > (psSlavePort->ui32DataRange >> 1)) {
+
+ *pui32Offset = 0;
+ }
+#endif
+
+ SGX2DTraceBlt(&ui32Value, 1);
+
+#if defined(SGX2D_INCREMENTING_SP_WRITES)
+ *((IMG_UINT32 *) ((IMG_UINT32) psSlavePort->pvData + *pui32Offset)) =
+ ui32Value;
+#else
+ *((IMG_UINT32 *) psSlavePort->pvData) = ui32Value;
+#endif
+
+#if defined(SGX2D_INCREMENTING_SP_WRITES)
+ *pui32Offset += 4;
+#endif
+}
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SGX2DWriteSlavePortBatch)
+#endif
+FORCE_INLINE
+ PVRSRV_ERROR SGX2DWriteSlavePortBatch(PVRSRV_SGXDEV_INFO * psDevInfo,
+ IMG_UINT32 * pui32LinDataAddr,
+ IMG_UINT32 ui32Bytes)
+{
+ IMG_INT32 i;
+ SGX_SLAVE_PORT *psSlavePort = &psDevInfo->s2DSlavePortKM;
+ IMG_UINT32 *pui32LinPortAddrBase = (IMG_UINT32 *) psSlavePort->pvData;
+ IMG_UINT32 ui32DWORDs = ui32Bytes >> 2;
+#if defined(SGX2D_INCREMENTING_SP_WRITES)
+ IMG_UINT32 *pui32Offset = psSlavePort->pui32Offset;
+ IMG_UINT32 *pui32LinPortAddr;
+
+ if (ui32Bytes > (psSlavePort->ui32DataRange >> 1)) {
+ return PVRSRV_ERROR_CMD_TOO_BIG;
+ }
+
+ if (*pui32Offset > (psSlavePort->ui32DataRange >> 1)) {
+
+ *pui32Offset = 0;
+ }
+
+ pui32LinPortAddr =
+ (IMG_UINT32 *) ((IMG_UINT32) pui32LinPortAddrBase + *pui32Offset);
+#endif
+
+ SGX2DTraceBlt(pui32LinDataAddr, ui32DWORDs);
+
+ for (i = ui32DWORDs; i != 0; i -= ui32DWORDs) {
+ ui32DWORDs = (i < 32) ? i : 32;
+
+ switch (ui32DWORDs) {
+#if defined(SGX2D_INCREMENTING_SP_WRITES)
+ case 32:
+ *pui32LinPortAddr++ = *pui32LinDataAddr++;
+ case 31:
+ *pui32LinPortAddr++ = *pui32LinDataAddr++;
+ case 30:
+ *pui32LinPortAddr++ = *pui32LinDataAddr++;
+ case 29:
+ *pui32LinPortAddr++ = *pui32LinDataAddr++;
+ case 28:
+ *pui32LinPortAddr++ = *pui32LinDataAddr++;
+ case 27:
+ *pui32LinPortAddr++ = *pui32LinDataAddr++;
+ case 26:
+ *pui32LinPortAddr++ = *pui32LinDataAddr++;
+ case 25:
+ *pui32LinPortAddr++ = *pui32LinDataAddr++;
+ case 24:
+ *pui32LinPortAddr++ = *pui32LinDataAddr++;
+ case 23:
+ *pui32LinPortAddr++ = *pui32LinDataAddr++;
+ case 22:
+ *pui32LinPortAddr++ = *pui32LinDataAddr++;
+ case 21:
+ *pui32LinPortAddr++ = *pui32LinDataAddr++;
+ case 20:
+ *pui32LinPortAddr++ = *pui32LinDataAddr++;
+ case 19:
+ *pui32LinPortAddr++ = *pui32LinDataAddr++;
+ case 18:
+ *pui32LinPortAddr++ = *pui32LinDataAddr++;
+ case 17:
+ *pui32LinPortAddr++ = *pui32LinDataAddr++;
+ case 16:
+ *pui32LinPortAddr++ = *pui32LinDataAddr++;
+ case 15:
+ *pui32LinPortAddr++ = *pui32LinDataAddr++;
+ case 14:
+ *pui32LinPortAddr++ = *pui32LinDataAddr++;
+ case 13:
+ *pui32LinPortAddr++ = *pui32LinDataAddr++;
+ case 12:
+ *pui32LinPortAddr++ = *pui32LinDataAddr++;
+ case 11:
+ *pui32LinPortAddr++ = *pui32LinDataAddr++;
+ case 10:
+ *pui32LinPortAddr++ = *pui32LinDataAddr++;
+ case 9:
+ *pui32LinPortAddr++ = *pui32LinDataAddr++;
+ case 8:
+ *pui32LinPortAddr++ = *pui32LinDataAddr++;
+ case 7:
+ *pui32LinPortAddr++ = *pui32LinDataAddr++;
+ case 6:
+ *pui32LinPortAddr++ = *pui32LinDataAddr++;
+ case 5:
+ *pui32LinPortAddr++ = *pui32LinDataAddr++;
+ case 4:
+ *pui32LinPortAddr++ = *pui32LinDataAddr++;
+ case 3:
+ *pui32LinPortAddr++ = *pui32LinDataAddr++;
+ case 2:
+ *pui32LinPortAddr++ = *pui32LinDataAddr++;
+ case 1:
+ *pui32LinPortAddr++ = *pui32LinDataAddr++;
+#else
+ case 32:
+ *pui32LinPortAddrBase = *pui32LinDataAddr++;
+ case 31:
+ *pui32LinPortAddrBase = *pui32LinDataAddr++;
+ case 30:
+ *pui32LinPortAddrBase = *pui32LinDataAddr++;
+ case 29:
+ *pui32LinPortAddrBase = *pui32LinDataAddr++;
+ case 28:
+ *pui32LinPortAddrBase = *pui32LinDataAddr++;
+ case 27:
+ *pui32LinPortAddrBase = *pui32LinDataAddr++;
+ case 26:
+ *pui32LinPortAddrBase = *pui32LinDataAddr++;
+ case 25:
+ *pui32LinPortAddrBase = *pui32LinDataAddr++;
+ case 24:
+ *pui32LinPortAddrBase = *pui32LinDataAddr++;
+ case 23:
+ *pui32LinPortAddrBase = *pui32LinDataAddr++;
+ case 22:
+ *pui32LinPortAddrBase = *pui32LinDataAddr++;
+ case 21:
+ *pui32LinPortAddrBase = *pui32LinDataAddr++;
+ case 20:
+ *pui32LinPortAddrBase = *pui32LinDataAddr++;
+ case 19:
+ *pui32LinPortAddrBase = *pui32LinDataAddr++;
+ case 18:
+ *pui32LinPortAddrBase = *pui32LinDataAddr++;
+ case 17:
+ *pui32LinPortAddrBase = *pui32LinDataAddr++;
+ case 16:
+ *pui32LinPortAddrBase = *pui32LinDataAddr++;
+ case 15:
+ *pui32LinPortAddrBase = *pui32LinDataAddr++;
+ case 14:
+ *pui32LinPortAddrBase = *pui32LinDataAddr++;
+ case 13:
+ *pui32LinPortAddrBase = *pui32LinDataAddr++;
+ case 12:
+ *pui32LinPortAddrBase = *pui32LinDataAddr++;
+ case 11:
+ *pui32LinPortAddrBase = *pui32LinDataAddr++;
+ case 10:
+ *pui32LinPortAddrBase = *pui32LinDataAddr++;
+ case 9:
+ *pui32LinPortAddrBase = *pui32LinDataAddr++;
+ case 8:
+ *pui32LinPortAddrBase = *pui32LinDataAddr++;
+ case 7:
+ *pui32LinPortAddrBase = *pui32LinDataAddr++;
+ case 6:
+ *pui32LinPortAddrBase = *pui32LinDataAddr++;
+ case 5:
+ *pui32LinPortAddrBase = *pui32LinDataAddr++;
+ case 4:
+ *pui32LinPortAddrBase = *pui32LinDataAddr++;
+ case 3:
+ *pui32LinPortAddrBase = *pui32LinDataAddr++;
+ case 2:
+ *pui32LinPortAddrBase = *pui32LinDataAddr++;
+ case 1:
+ *pui32LinPortAddrBase = *pui32LinDataAddr++;
+#endif
+ }
+ }
+
+#if defined(SGX2D_INCREMENTING_SP_WRITES)
+
+ *pui32Offset += ui32Bytes;
+#endif
+
+ return PVRSRV_OK;
+}
+
+IMG_BOOL SGX2DProcessBlit(IMG_HANDLE hCmdCookie,
+ IMG_UINT32 ui32DataSize, IMG_VOID * pvData)
+{
+ PVRSRV_BLT_CMD_INFO *psBltCmd;
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+ IMG_UINT32 ui32BytesRequired;
+ IMG_UINT32 ui32BytesObtained = 0;
+ IMG_BOOL bError = IMG_TRUE;
+ PVRSRV_ERROR eError;
+
+ PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DProcessBlit: Start"));
+
+ psBltCmd = (PVRSRV_BLT_CMD_INFO *) pvData;
+
+ if (psBltCmd == IMG_NULL || psBltCmd->ui32CmdSize != ui32DataSize) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "ProcessBlit: Data packet size is incorrect"));
+ return IMG_FALSE;
+ }
+
+ psDevInfo = psBltCmd->psDevInfo;
+
+ if (psDevInfo->h2DCmdCookie != IMG_NULL) {
+ return IMG_FALSE;
+ }
+
+ if (psDevInfo->b2DHWRecoveryInProgress) {
+ psDevInfo->h2DCmdCookie = hCmdCookie;
+ SGX2DHardwareKick(psDevInfo);
+ return IMG_TRUE;
+ }
+
+ if (SGX2DAcquireSlavePort(psDevInfo, IMG_FALSE) != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "ProcessBlit: Couldn't acquire slaveport"));
+ return IMG_FALSE;
+ }
+#ifdef FIXME
+
+#endif
+
+ if (psDevInfo->b2DHWRecoveryEndPending && SGX2D_2D_NOT_IDLE(psDevInfo)) {
+ psDevInfo->h2DCmdCookie = hCmdCookie;
+ SGX2DHardwareKick(psDevInfo);
+ PVR_ASSERT(bError);
+ goto ErrorExit;
+ }
+ psDevInfo->b2DHWRecoveryEndPending = IMG_FALSE;
+
+ ui32BytesRequired = psBltCmd->ui32DataByteSize + SGX2D_QUEUED_BLIT_PAD;
+
+ eError =
+ SGX2DAcquireFifoSpace(psDevInfo, ui32BytesRequired,
+ &ui32BytesObtained);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR, "ProcessBlit: Get Fifo Space failed"));
+ bError = IMG_FALSE;
+ goto ErrorExit;
+ }
+
+ SGX2DWriteSlavePortBatch(psDevInfo,
+ psBltCmd->aui32BltData,
+ psBltCmd->ui32DataByteSize);
+
+ psDevInfo->h2DCmdCookie = hCmdCookie;
+
+ SGX2DWriteSlavePort(psDevInfo, SGX2D_FLUSH_BH);
+
+ PVR_ASSERT(bError);
+ErrorExit:
+
+ if (SGX2DReleaseSlavePort(psDevInfo) != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "SGX2DReleaseSlavePort: failed to release slaveport"));
+ }
+
+ PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DProcessBlit: Exit. Error %d",
+ (int)bError));
+
+ return bError;
+}
+
+IMG_VOID SGX2DHandle2DComplete(PVRSRV_SGXDEV_INFO * psDevInfo)
+{
+ IMG_HANDLE hCmdCookie;
+
+ PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DHandle2DComplete: Start"));
+
+ hCmdCookie = psDevInfo->h2DCmdCookie;
+ psDevInfo->h2DCmdCookie = IMG_NULL;
+
+ if (hCmdCookie != IMG_NULL) {
+ PVRSRVCommandCompleteKM(hCmdCookie, IMG_TRUE);
+ }
+
+ PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DHandle2DComplete: Exit"));
+}
+
+IMG_EXPORT
+ PVRSRV_ERROR SGX2DQueueBlitKM(PVRSRV_SGXDEV_INFO * psDevInfo,
+ PVRSRV_KERNEL_SYNC_INFO * psDstSync,
+ IMG_UINT32 ui32NumSrcSyncs,
+ PVRSRV_KERNEL_SYNC_INFO * apsSrcSync[],
+ IMG_UINT32 ui32DataByteSize,
+ IMG_UINT32 * pui32BltData)
+{
+#if defined(NO_HARDWARE)
+ PVR_UNREFERENCED_PARAMETER(psDevInfo);
+ PVR_UNREFERENCED_PARAMETER(psDstSync);
+ PVR_UNREFERENCED_PARAMETER(ui32NumSrcSyncs);
+ PVR_UNREFERENCED_PARAMETER(apsSrcSync);
+ PVR_UNREFERENCED_PARAMETER(ui32DataByteSize);
+ PVR_UNREFERENCED_PARAMETER(pui32BltData);
+
+ return PVRSRV_OK;
+#else
+ PVRSRV_COMMAND *psCommand;
+ PVRSRV_BLT_CMD_INFO *psBltCmd;
+ IMG_UINT32 ui32CmdByteSize;
+ IMG_UINT32 i;
+ PVRSRV_ERROR eError;
+
+ PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DQueueBlitKM: Start"));
+
+ if (psDevInfo->b2DHWRecoveryInProgress == IMG_TRUE) {
+ return PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE;
+ }
+
+ if ((ui32DataByteSize + SGX2D_QUEUED_BLIT_PAD) >
+ psDevInfo->ui322DFifoSize) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "SGX2DQueueBlitKM: Blit too big for FIFO. Blit size: %d (+ padding %d), FIFO size: %d",
+ ui32DataByteSize, SGX2D_QUEUED_BLIT_PAD,
+ psDevInfo->ui322DFifoSize));
+
+ return PVRSRV_ERROR_CMD_TOO_BIG;
+ }
+
+ ui32CmdByteSize = sizeof(PVRSRV_BLT_CMD_INFO)
+ + ui32DataByteSize - sizeof(IMG_UINT32);
+
+ eError =
+ PVRSRVInsertCommandKM((PVRSRV_QUEUE_INFO *) psDevInfo->h2DQueue,
+ &psCommand, SYS_DEVICE_SGX,
+ SGX_2D_BLT_COMMAND,
+ (psDstSync == IMG_NULL) ? 0 : 1, &psDstSync,
+ ui32NumSrcSyncs, apsSrcSync, ui32CmdByteSize);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "SGX2DQueueBlitKM: PVRSRVInsertCommandKM failed. Error %d",
+ eError));
+#ifdef DEBUG
+ if (eError == PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE) {
+ if (!SGX2DIsBusy(psDevInfo)) {
+
+ PVR_DPF((PVR_DBG_ERROR,
+ "SGX2DQueueBlitKM: 2D core not busy, command queue full - lockup suspected"));
+ }
+ }
+#endif
+ return eError;
+ }
+
+ psBltCmd = (PVRSRV_BLT_CMD_INFO *) psCommand->pvData;
+ psBltCmd->ui32CmdSize = ui32CmdByteSize;
+ psBltCmd->psDevInfo = psDevInfo;
+
+ psBltCmd->psDstSync = psDstSync;
+
+ psBltCmd->ui32NumSrcSyncInfos = ui32NumSrcSyncs;
+ for (i = 0; i < ui32NumSrcSyncs; i++) {
+
+ psBltCmd->apsSrcSync[i] = apsSrcSync[i];
+ }
+
+ if (pui32BltData != IMG_NULL) {
+ for (i = 0; i < (ui32DataByteSize >> 2); i++) {
+ psBltCmd->aui32BltData[i] = pui32BltData[i];
+ }
+ }
+
+ psBltCmd->ui32DataByteSize = ui32DataByteSize;
+
+ eError =
+ PVRSRVSubmitCommandKM((PVRSRV_QUEUE_INFO *) psDevInfo->h2DQueue,
+ psCommand);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "SGX2DQueueBlitKM: PVRSRVSubmitCommandKM failed. Error %d",
+ eError));
+ }
+
+ SGX2DKick(psDevInfo);
+
+ PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DQueueBlitKM: Exit. Error: %d",
+ eError));
+
+ return eError;
+#endif
+}
+
+#if defined(SGX2D_DIRECT_BLITS)
+IMG_EXPORT
+ PVRSRV_ERROR SGX2DDirectBlitKM(PVRSRV_SGXDEV_INFO * psDevInfo,
+ IMG_UINT32 ui32DataByteSize,
+ IMG_UINT32 * pui32BltData)
+{
+#if defined(NO_HARDWARE)
+ PVR_UNREFERENCED_PARAMETER(psDevInfo);
+ PVR_UNREFERENCED_PARAMETER(ui32DataByteSize);
+ PVR_UNREFERENCED_PARAMETER(pui32BltData);
+
+ return PVRSRV_OK;
+#else
+ PVRSRV_ERROR eError;
+ PVRSRV_ERROR eSrvErr;
+
+ IMG_UINT32 ui32CmdByteSize = ui32DataByteSize + 4;
+ IMG_BOOL bStart = IMG_FALSE;
+ IMG_UINT32 uiStart = 0;
+
+ PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DDirectBlitKM: Start"));
+
+ if (psDevInfo->b2DHWRecoveryInProgress == IMG_TRUE) {
+ return PVRSRV_ERROR_FIFO_SPACE;
+ }
+
+ if (ui32CmdByteSize > psDevInfo->ui322DFifoSize) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "SGX2DDirectBlitKM: Blit too big for FIFO. Blit size: %d (+ padding %d), FIFO size: %d",
+ ui32DataByteSize, 4, psDevInfo->ui322DFifoSize));
+
+ return PVRSRV_ERROR_CMD_TOO_BIG;
+ }
+
+ eSrvErr = SGX2DAcquireSlavePort(psDevInfo, IMG_TRUE);
+ if (eSrvErr != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "SGX2DDirectBlitKM: Cannot acquire slaveport. Error %d",
+ eSrvErr));
+ return eSrvErr;
+ }
+#ifdef FIXME
+
+#endif
+ do {
+ eSrvErr = SGX2DAcquireFifoSpace(psDevInfo,
+ ui32CmdByteSize, IMG_NULL);
+ if (eSrvErr == PVRSRV_OK) {
+ break;
+ }
+
+ if (bStart == IMG_FALSE) {
+ uiStart = OSClockus();
+ bStart = IMG_TRUE;
+ }
+
+ OSWaitus(MAX_HW_TIME_US / WAIT_TRY_COUNT);
+ } while ((OSClockus() - uiStart) < MAX_HW_TIME_US);
+
+ if (eSrvErr != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "SGX2DDirectBlitKM: Cannot acquire FIFO space. Error %d",
+ eSrvErr));
+
+ eError = eSrvErr;
+ } else {
+
+ if (psDevInfo->b2DHWRecoveryEndPending
+ && SGX2D_2D_NOT_IDLE(psDevInfo)) {
+ eError = PVRSRV_ERROR_FIFO_SPACE;
+ } else {
+ eError = PVRSRV_OK;
+
+ psDevInfo->b2DHWRecoveryEndPending = IMG_FALSE;
+
+ SGX2DWriteSlavePortBatch(psDevInfo, pui32BltData,
+ ui32DataByteSize);
+
+ SGX2DWriteSlavePort(psDevInfo, SGX2D_FENCE_BH);
+ }
+ }
+
+ eSrvErr = SGX2DReleaseSlavePort(psDevInfo);
+ if (eSrvErr != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "SGX2DDirectBlitKM: Cannot release slave port. Error %d",
+ eSrvErr));
+
+ if (eError != PVRSRV_OK) {
+ eError = eSrvErr;
+ }
+ }
+
+ PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DDirectBlitKM: Exit. Error: %d",
+ eError));
+
+ SGX2DKick(psDevInfo);
+
+ return eError;
+#endif
+}
+#endif
+
+#endif
+
+#if defined(SGX_FEATURE_2D_HARDWARE) || defined(PVR2D_ALT_2DHW)
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(SGX2DQuerySyncOpsComplete)
+#endif
+static INLINE
+ IMG_BOOL SGX2DQuerySyncOpsComplete(PVRSRV_KERNEL_SYNC_INFO * psSyncInfo)
+{
+ PVRSRV_SYNC_DATA *psSyncData = psSyncInfo->psSyncData;
+
+ return (IMG_BOOL) ((psSyncData->ui32ReadOpsComplete ==
+ psSyncData->ui32ReadOpsPending)
+ && (psSyncData->ui32WriteOpsComplete ==
+ psSyncData->ui32WriteOpsPending)
+ );
+}
+
+IMG_EXPORT
+ PVRSRV_ERROR SGX2DQueryBlitsCompleteKM(PVRSRV_SGXDEV_INFO * psDevInfo,
+ PVRSRV_KERNEL_SYNC_INFO * psSyncInfo,
+ IMG_BOOL bWaitForComplete)
+{
+ IMG_BOOL bStart = IMG_FALSE;
+ IMG_UINT32 uiStart = 0;
+
+ PVR_UNREFERENCED_PARAMETER(psDevInfo);
+
+ PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DQueryBlitsCompleteKM: Start"));
+
+ if (SGX2DQuerySyncOpsComplete(psSyncInfo)) {
+
+ 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."));
+ do {
+ OSWaitus(MAX_HW_TIME_US / WAIT_TRY_COUNT);
+
+ if (SGX2DQuerySyncOpsComplete(psSyncInfo)) {
+
+ PVR_DPF((PVR_DBG_CALLTRACE,
+ "SGX2DQueryBlitsCompleteKM: Wait over. Blits complete."));
+ return PVRSRV_OK;
+ }
+
+ if (bStart == IMG_FALSE) {
+ uiStart = OSClockus();
+ bStart = IMG_TRUE;
+ }
+
+ OSWaitus(MAX_HW_TIME_US / WAIT_TRY_COUNT);
+ } while ((OSClockus() - uiStart) < MAX_HW_TIME_US);
+
+ PVR_DPF((PVR_DBG_ERROR,
+ "SGX2DQueryBlitsCompleteKM: Timed out. Ops pending."));
+
+#if defined(DEBUG)
+ {
+ PVRSRV_SYNC_DATA *psSyncData = psSyncInfo->psSyncData;
+
+ PVR_TRACE(("SGX2DQueryBlitsCompleteKM: Syncinfo: %p, Syncdata: %p", psSyncInfo, 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;
+}
+#endif
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+PVRSRV_ERROR SGX2DInit(PVRSRV_SGXDEV_INFO * psDevInfo)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(psDevInfo->ui322DFifoSize == 0);
+ psDevInfo->ui322DFifoSize = SGX2DFifoFreeSpace(psDevInfo);
+
+ PVR_TRACE(("SGX2DInit: 2D FIFO size: %d", psDevInfo->ui322DFifoSize));
+
+ PVR_ASSERT(psDevInfo->s2DSlavePortKM.pui32Offset == 0);
+ PVR_ASSERT(psDevInfo->ui322DFifoOffset == 0);
+ psDevInfo->s2DSlavePortKM.pui32Offset = &psDevInfo->ui322DFifoOffset;
+
+ PVR_ASSERT(psDevInfo->h2DQueue == IMG_NULL);
+ eError = PVRSRVCreateCommandQueueKM(SGX2D_COMMAND_QUEUE_SIZE,
+ (PVRSRV_QUEUE_INFO **) & psDevInfo->
+ h2DQueue);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "SGX2DInit: PVRSRVCreateCommandQueueKM failed (%d)",
+ eError));
+
+ return eError;
+ }
+
+ PVR_ASSERT(psDevInfo->h2DCmdCookie == IMG_NULL);
+ PVR_ASSERT(!psDevInfo->b2DHWRecoveryInProgress);
+ PVR_ASSERT(!psDevInfo->b2DHWRecoveryEndPending);
+ PVR_ASSERT(psDevInfo->ui322DCompletedBlits == 0);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR SGX2DDeInit(PVRSRV_SGXDEV_INFO * psDevInfo)
+{
+ PVRSRV_ERROR eError;
+
+ if (psDevInfo->h2DQueue != IMG_NULL) {
+ eError =
+ PVRSRVDestroyCommandQueueKM((PVRSRV_QUEUE_INFO *)
+ psDevInfo->h2DQueue);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "SGX2DDeInit: PVRSRVDestroyCommandQueueKM failed (%d)",
+ eError));
+
+ return eError;
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+#endif
#if defined(SGX_FEATURE_2D_HARDWARE)
#define SGX_2D_HEAP_ID 12
-#define SGX_MAX_HEAP_ID 13
+#define SGX_ALT_MAPPING_HEAP_ID 13
+#define SGX_MAX_HEAP_ID 14
#else
-#define SGX_MAX_HEAP_ID 12
+#define SGX_ALT_MAPPING_HEAP_ID 12
+#define SGX_MAX_HEAP_ID 13
#endif
#define SGX_MAX_TA_STATUS_VALS 32
#if SGX_FEATURE_ADDRESS_SPACE_SIZE == 28
#define SGX_ADDRESS_SPACE_SIZE 28
-#define SGX_GENERAL_HEAP_BASE 0x00400000
-#define SGX_GENERAL_HEAP_SIZE (0x07000000-0x00401000)
+#define SGX_GENERAL_HEAP_BASE 0x00400000
+#define SGX_GENERAL_HEAP_SIZE (0x05000000-0x00401000)
+
+#define SGX_GENERAL_MAPPING_HEAP_BASE 0x05000000
+#define SGX_GENERAL_MAPPING_HEAP_SIZE (0x07000000-0x05001000)
#define SGX_TADATA_HEAP_BASE 0x07000000
#define SGX_TADATA_HEAP_SIZE (0x01000000-0x00001000)
#define SGX_3DPARAMETERS_HEAP_BASE 0x08000000
#define SGX_3DPARAMETERS_HEAP_SIZE (0x04000000-0x00001000)
-#define SGX_GENERAL_MAPPING_HEAP_BASE 0x0C000000
-#define SGX_GENERAL_MAPPING_HEAP_SIZE (0x01000000-0x00001000)
+#define SGX_ALT_MAPPING_HEAP_BASE (0x0C000000)
+#define SGX_ALT_MAPPING_HEAP_SIZE (0x0D000000 - 0x0C001000)
#define SGX_PIXELSHADER_HEAP_BASE 0x0D000000
#define SGX_PIXELSHADER_HEAP_SIZE 0x00500000
#define SGX_HOSTPORT_PRESENT 0x00000001UL
-#define PVRSRV_USSE_EDM_POWMAN_POWEROFF_REQUEST (1UL << 0)
-#define PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE (1UL << 1)
-#define PVRSRV_USSE_EDM_POWMAN_POWEROFF_RESTART_IMMEDIATE (1UL << 2)
-#define PVRSRV_USSE_EDM_POWMAN_NO_WORK (1UL << 3)
+#define PVRSRV_USSE_EDM_POWMAN_IDLE_REQUEST (1UL << 0)
+#define PVRSRV_USSE_EDM_POWMAN_POWEROFF_REQUEST (1UL << 1)
+#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)
IMG_UINT32 ui32IRQ;
+#if !defined(SGX_DYNAMIC_TIMING_INFO)
+
SGX_TIMING_INFORMATION sTimingInfo;
+#endif
} SGX_DEVICE_MAP;
typedef struct _PVRSRV_STUB_PBDESC_ PVRSRV_STUB_PBDESC;
IMG_VOID SGXOSTimer(IMG_VOID * pvData);
+#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,
******************************************************************************/
#include <stddef.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
#include "sgxdefs.h"
#include "sgxmmu.h"
IMG_BOOL bHardwareRecovery);
PVRSRV_ERROR SGXDeinitialise(IMG_HANDLE hDevCookie);
+typedef enum _PVR_DEVICE_POWER_STATE_ {
+ PVR_DEVICE_POWER_STATE_ON = 0,
+ PVR_DEVICE_POWER_STATE_IDLE = 1,
+ PVR_DEVICE_POWER_STATE_OFF = 2,
+
+ PVR_DEVICE_POWER_STATE_FORCE_I32 = 0x7fffffff
+} PVR_DEVICE_POWER_STATE, *PPVR_DEVICE_POWER_STATE;
+
+static PVR_DEVICE_POWER_STATE MapDevicePowerState(PVR_POWER_STATE ePowerState)
+{
+ PVR_DEVICE_POWER_STATE eDevicePowerState;
+
+ switch (ePowerState) {
+ case PVRSRV_POWER_STATE_D0:
+ {
+ eDevicePowerState = PVR_DEVICE_POWER_STATE_ON;
+ break;
+ }
+ case PVRSRV_POWER_STATE_D3:
+ {
+ eDevicePowerState = PVR_DEVICE_POWER_STATE_OFF;
+ break;
+ }
+ default:
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "MapDevicePowerState: Invalid state: %ld",
+ ePowerState));
+ eDevicePowerState = PVR_DEVICE_POWER_STATE_FORCE_I32;
+ PVR_ASSERT(eDevicePowerState !=
+ PVR_DEVICE_POWER_STATE_FORCE_I32);
+ }
+ }
+
+ return eDevicePowerState;
+}
+
static IMG_VOID SGXCommandComplete(PVRSRV_DEVICE_NODE * psDeviceNode)
{
SGXScheduleProcessQueues(psDeviceNode);
return eError;
}
-static IMG_VOID SGXStartTimer(PVRSRV_SGXDEV_INFO * psDevInfo)
+static IMG_VOID SGXGetTimingInfo(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) {
+ eError = OSRemoveTimer(psDevInfo->hTimer);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "SGXGetTimingInfo: Failed to remove timer"));
+ }
+ psDevInfo->hTimer = IMG_NULL;
+ }
+ }
+ if (psDevInfo->hTimer == IMG_NULL) {
+
+ psDevInfo->hTimer = OSAddTimer(SGXOSTimer, psDeviceNode,
+ 1000 * 50 /
+ psSGXTimingInfo->
+ ui32uKernelFreq);
+ if (psDevInfo->hTimer == IMG_NULL) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "SGXGetTimingInfo : Failed to register timer callback function"));
+ }
+ }
+
+ psDevInfo->psSGXHostCtl->ui32HWRecoverySampleRate =
+ psSGXTimingInfo->ui32uKernelFreq /
+ psSGXTimingInfo->ui32HWRecoveryFreq;
+ }
+#endif
+
+ psDevInfo->ui32CoreClockSpeed = psSGXTimingInfo->ui32CoreClockSpeed;
+ psDevInfo->ui32uKernelTimerClock =
+ psSGXTimingInfo->ui32CoreClockSpeed /
+ psSGXTimingInfo->ui32uKernelFreq;
+
+ ui32ActivePowManSampleRate =
+ psSGXTimingInfo->ui32uKernelFreq *
+ psSGXTimingInfo->ui32ActivePowManLatencyms / 1000;
+ ui32ActivePowManSampleRate += 1;
+ psDevInfo->psSGXHostCtl->ui32ActivePowManSampleRate =
+ ui32ActivePowManSampleRate;
+}
+
+static IMG_VOID SGXStartTimer(PVRSRV_SGXDEV_INFO * psDevInfo,
+ IMG_BOOL bStartOSTimer)
{
- IMG_UINT32 ui32RegVal =
+ IMG_UINT32 ui32RegVal;
+
+#if !defined(SUPPORT_HW_RECOVERY)
+ PVR_UNREFERENCED_PARAMETER(bStartOSTimer);
+#endif
+
+ ui32RegVal =
EUR_CR_EVENT_TIMER_ENABLE_MASK | psDevInfo->ui32uKernelTimerClock;
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_TIMER, ui32RegVal);
PDUMPREGWITHFLAGS(EUR_CR_EVENT_TIMER, ui32RegVal,
PDUMP_FLAGS_CONTINUOUS);
+
+#if defined(SUPPORT_HW_RECOVERY)
+ if (bStartOSTimer) {
+ PVRSRV_ERROR eError;
+ eError = OSEnableTimer(psDevInfo->hTimer);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "SGXStartTimer : Failed to enable host timer"));
+ }
+ }
+#endif
}
-PVRSRV_ERROR SGXPrePowerState(IMG_HANDLE hDevHandle,
- PVR_POWER_STATE eNewPowerState,
- PVR_POWER_STATE eCurrentPowerState)
+static PVRSRV_ERROR SGXPrePowerState(IMG_HANDLE hDevHandle,
+ PVR_DEVICE_POWER_STATE eNewPowerState,
+ PVR_DEVICE_POWER_STATE eCurrentPowerState)
{
- if (eNewPowerState != eCurrentPowerState) {
- PVRSRV_DEVICE_NODE *psDeviceNode =
- (PVRSRV_DEVICE_NODE *) hDevHandle;
- PVRSRV_SGXDEV_INFO *psDevInfo =
- (PVRSRV_SGXDEV_INFO *) psDeviceNode->pvDevice;
-
- if (eNewPowerState == PVRSRV_POWER_STATE_D3) {
- PVRSRV_SGX_HOST_CTL *psSGXHostCtl =
- psDevInfo->psSGXHostCtl;
-
-#if defined (SGX_FEATURE_AUTOCLOCKGATING) && (!defined(NO_HARDWARE) || defined(PDUMP))
- IMG_UINT32 ui32ClockMask =
- psDevInfo->ui32ClkGateStatusMask;
-#endif
+ if ((eNewPowerState != eCurrentPowerState) &&
+ (eNewPowerState != PVR_DEVICE_POWER_STATE_ON)) {
+ PVRSRV_ERROR eError;
+ PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ PVRSRV_SGX_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl;
+ IMG_UINT32 ui32PowManRequest, ui32PowManComplete;
#if defined(SUPPORT_HW_RECOVERY)
-
- if (OSDisableTimer(psDevInfo->hTimer) != PVRSRV_OK) {
- PVR_DPF((PVR_DBG_ERROR,
- "SGXPrePowerState: Failed to disable timer"));
- return PVRSRV_ERROR_GENERIC;
- }
+ eError = OSDisableTimer(psDevInfo->hTimer);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "SGXPrePowerState: Failed to disable timer"));
+ return eError;
+ }
#endif
- psSGXHostCtl->ui32PowManFlags |=
+ if (eNewPowerState == PVR_DEVICE_POWER_STATE_OFF) {
+ ui32PowManRequest =
PVRSRV_USSE_EDM_POWMAN_POWEROFF_REQUEST;
-
+ ui32PowManComplete =
+ PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE;
PDUMPCOMMENT
- ("TA/3D CCB Control - Trigger power down event on uKernel...");
- PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
- offsetof(PVRSRV_SGX_HOST_CTL, ui32PowManFlags),
- sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
- MAKEUNIQUETAG(psDevInfo->
- psKernelSGXHostCtlMemInfo));
+ ("TA/3D CCB Control - SGX power off request");
+ } else {
+ ui32PowManRequest = PVRSRV_USSE_EDM_POWMAN_IDLE_REQUEST;
+ ui32PowManComplete =
+ PVRSRV_USSE_EDM_POWMAN_IDLE_COMPLETE;
+ PDUMPCOMMENT("TA/3D CCB Control - SGX idle request");
+ }
-#if !defined(NO_HARDWARE)
- if (PollForValueKM
- ((volatile IMG_UINT32 *)(&psSGXHostCtl->
- ui32PowManFlags),
- PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE,
- PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE,
- MAX_HW_TIME_US / WAIT_TRY_COUNT,
- WAIT_TRY_COUNT) != PVRSRV_OK) {
- PVR_DPF((PVR_DBG_ERROR,
- "SGXPrePowerState: Wait for chip power off failed."));
- }
+ psSGXHostCtl->ui32PowManFlags |= ui32PowManRequest;
+#if defined(PDUMP)
+ PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+ offsetof(PVRSRV_SGX_HOST_CTL, ui32PowManFlags),
+ sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
#endif
-#ifdef PDUMP
-
- PDUMPCOMMENT
- ("TA/3D CCB Control - Wait for power down event on uKernel...");
- PDUMPMEMPOL(psDevInfo->psKernelSGXHostCtlMemInfo,
- offsetof(PVRSRV_SGX_HOST_CTL,
- ui32PowManFlags),
- PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE,
- PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE,
- PDUMP_POLL_OPERATOR_EQUAL, IMG_FALSE,
- IMG_FALSE,
- MAKEUNIQUETAG(psDevInfo->
- psKernelSGXHostCtlMemInfo));
+#if !defined(NO_HARDWARE)
+ if (PollForValueKM(&psSGXHostCtl->ui32PowManFlags,
+ ui32PowManComplete,
+ ui32PowManComplete,
+ MAX_HW_TIME_US / WAIT_TRY_COUNT,
+ WAIT_TRY_COUNT) != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "SGXPrePowerState: Wait for SGX ukernel power transition failed."));
+ }
#endif
- SGXDeinitialise(psDevInfo);
+#if defined(PDUMP)
+ PDUMPCOMMENT
+ ("TA/3D CCB Control - Wait for power event on uKernel.");
+ PDUMPMEMPOL(psDevInfo->psKernelSGXHostCtlMemInfo,
+ offsetof(PVRSRV_SGX_HOST_CTL, ui32PowManFlags),
+ ui32PowManComplete, ui32PowManComplete,
+ PDUMP_POLL_OPERATOR_EQUAL, IMG_FALSE, IMG_FALSE,
+ MAKEUNIQUETAG(psDevInfo->
+ psKernelSGXHostCtlMemInfo));
+#endif
#if defined(SGX_FEATURE_AUTOCLOCKGATING)
+ {
#if !defined(NO_HARDWARE)
if (PollForValueKM
- ((volatile IMG_UINT32 *)((IMG_UINT8 *) psDevInfo->
- pvRegsBaseKM +
- EUR_CR_CLKGATESTATUS), 0,
- ui32ClockMask, MAX_HW_TIME_US / WAIT_TRY_COUNT,
+ ((IMG_UINT32 *) psDevInfo->pvRegsBaseKM +
+ (EUR_CR_CLKGATESTATUS >> 2), 0,
+ psDevInfo->ui32ClkGateStatusMask,
+ MAX_HW_TIME_US / WAIT_TRY_COUNT,
WAIT_TRY_COUNT) != PVRSRV_OK) {
PVR_DPF((PVR_DBG_ERROR,
- "SGXPrePowerState: Wait for chip idle failed."));
+ "SGXPrePowerState: Wait for SGX clock gating failed."));
}
#endif
- PDUMPREGPOL(EUR_CR_CLKGATESTATUS, 0, ui32ClockMask);
+
+ PDUMPCOMMENT("Wait for SGX clock gating.");
+ PDUMPREGPOL(EUR_CR_CLKGATESTATUS, 0,
+ psDevInfo->ui32ClkGateStatusMask);
+ }
#endif
+
+ if (eNewPowerState == PVR_DEVICE_POWER_STATE_OFF) {
+ eError = SGXDeinitialise(psDevInfo);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "SGXPrePowerState: SGXDeinitialise failed: %lu",
+ eError));
+ return eError;
+ }
}
}
return PVRSRV_OK;
}
-PVRSRV_ERROR SGXPostPowerState(IMG_HANDLE hDevHandle,
- PVR_POWER_STATE eNewPowerState,
- PVR_POWER_STATE eCurrentPowerState)
+static PVRSRV_ERROR SGXPostPowerState(IMG_HANDLE hDevHandle,
+ PVR_DEVICE_POWER_STATE eNewPowerState,
+ PVR_DEVICE_POWER_STATE eCurrentPowerState)
{
- if (eNewPowerState != eCurrentPowerState) {
+ if ((eNewPowerState != eCurrentPowerState) &&
+ (eCurrentPowerState != PVR_DEVICE_POWER_STATE_ON)) {
PVRSRV_ERROR eError;
- PVRSRV_DEVICE_NODE *psDeviceNode =
- (PVRSRV_DEVICE_NODE *) hDevHandle;
- PVRSRV_SGXDEV_INFO *psDevInfo =
- (PVRSRV_SGXDEV_INFO *) psDeviceNode->pvDevice;
- SYS_DATA *psSysData;
-
- eError = SysAcquireData(&psSysData);
- if (eError != PVRSRV_OK) {
- return eError;
- }
+ PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
+ PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ PVRSRV_SGX_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl;
- if (eCurrentPowerState == PVRSRV_POWER_STATE_D3) {
- PVRSRV_SGX_HOST_CTL *psSGXHostCtl =
- psDevInfo->psSGXHostCtl;
+ psSGXHostCtl->ui32PowManFlags = 0;
+ PDUMPCOMMENT("TA/3D CCB Control - Reset Power Manager flags");
+#if defined(PDUMP)
+ PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+ offsetof(PVRSRV_SGX_HOST_CTL, ui32PowManFlags),
+ sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+#endif
- psSGXHostCtl->ui32PowManFlags = 0;
+ if (eCurrentPowerState == PVR_DEVICE_POWER_STATE_OFF) {
- PDUMPCOMMENT
- ("TA/3D CCB Control - Reset Power Manager flags");
- PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
- offsetof(PVRSRV_SGX_HOST_CTL, ui32PowManFlags),
- sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
- MAKEUNIQUETAG(psDevInfo->
- psKernelSGXHostCtlMemInfo));
+ SGXGetTimingInfo(psDeviceNode);
eError = SGXInitialise(psDevInfo, IMG_FALSE);
-
if (eError != PVRSRV_OK) {
PVR_DPF((PVR_DBG_ERROR,
"SGXPostPowerState: SGXInitialise failed"));
return eError;
}
-#if defined(SUPPORT_HW_RECOVERY)
- eError = OSEnableTimer(psDevInfo->hTimer);
- if (eError != PVRSRV_OK) {
- PVR_DPF((PVR_DBG_ERROR,
- "SGXPostPowerState : Failed to enable host timer"));
- return PVRSRV_ERROR_GENERIC;
- }
-#endif
}
-
- PVR_DPF((PVR_DBG_WARNING,
- "SGXPostPowerState : SGX Power Transition from %d to %d OK",
- eCurrentPowerState, eNewPowerState));
}
return PVRSRV_OK;
}
-static IMG_VOID SGXGetTimingInfo(PVRSRV_SGXDEV_INFO * psDevInfo,
- SGX_TIMING_INFORMATION * psSGXTimingInfo)
+PVRSRV_ERROR SGXPrePowerStateExt(IMG_HANDLE hDevHandle,
+ PVR_POWER_STATE eNewPowerState,
+ PVR_POWER_STATE eCurrentPowerState)
{
- IMG_UINT32 ui32ActivePowManSampleRate;
+ PVR_DEVICE_POWER_STATE eNewDevicePowerState =
+ MapDevicePowerState(eNewPowerState);
+ PVR_DEVICE_POWER_STATE eCurrentDevicePowerState =
+ MapDevicePowerState(eCurrentPowerState);
- psDevInfo->ui32CoreClockSpeed = psSGXTimingInfo->ui32CoreClockSpeed;
- psDevInfo->ui32uKernelTimerClock =
- psSGXTimingInfo->ui32CoreClockSpeed /
- psSGXTimingInfo->ui32uKernelFreq;
+ return SGXPrePowerState(hDevHandle, eNewDevicePowerState,
+ eCurrentDevicePowerState);
+}
-#if defined(SUPPORT_HW_RECOVERY)
- psDevInfo->psSGXHostCtl->ui32HWRecoverySampleRate =
- psSGXTimingInfo->ui32uKernelFreq /
- psSGXTimingInfo->ui32HWRecoveryFreq;
-#endif
+PVRSRV_ERROR SGXPostPowerStateExt(IMG_HANDLE hDevHandle,
+ PVR_POWER_STATE eNewPowerState,
+ PVR_POWER_STATE eCurrentPowerState)
+{
+ PVRSRV_ERROR eError;
+ PVR_DEVICE_POWER_STATE eNewDevicePowerState =
+ MapDevicePowerState(eNewPowerState);
+ PVR_DEVICE_POWER_STATE eCurrentDevicePowerState =
+ MapDevicePowerState(eCurrentPowerState);
- ui32ActivePowManSampleRate =
- psSGXTimingInfo->ui32uKernelFreq *
- psSGXTimingInfo->ui32ActivePowManLatencyms / 1000;
+ eError =
+ SGXPostPowerState(hDevHandle, eNewDevicePowerState,
+ eCurrentDevicePowerState);
+ if (eError != PVRSRV_OK) {
+ return eError;
+ }
- ui32ActivePowManSampleRate += 1;
+ PVR_DPF((PVR_DBG_WARNING,
+ "SGXPostPowerState : SGX Power Transition from %d to %d OK",
+ eCurrentPowerState, eNewPowerState));
- psDevInfo->psSGXHostCtl->ui32ActivePowManSampleRate =
- ui32ActivePowManSampleRate;
+ return eError;
}
static PVRSRV_ERROR SGXPreClockSpeedChange(IMG_HANDLE hDevHandle,
- IMG_BOOL bIdleDevice)
+ IMG_BOOL bIdleDevice,
+ PVR_POWER_STATE eCurrentPowerState)
{
PVRSRV_ERROR eError;
PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
- SGX_DEVICE_MAP *psSGXDeviceMap;
- 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;
- }
+ PVR_UNREFERENCED_PARAMETER(psDevInfo);
- if (bIdleDevice) {
+ if (eCurrentPowerState == PVRSRV_POWER_STATE_D0) {
+ if (bIdleDevice) {
- }
+ eError =
+ SGXPrePowerState(hDevHandle,
+ PVR_DEVICE_POWER_STATE_IDLE,
+ PVR_DEVICE_POWER_STATE_ON);
- SGXGetTimingInfo(psDevInfo, &psSGXDeviceMap->sTimingInfo);
+ if (eError != PVRSRV_OK) {
+ return eError;
+ }
+ }
+ }
PVR_DPF((PVR_DBG_MESSAGE,
- "SGXPreClockSpeedChange: SGX clock speed now %luHz",
+ "SGXPreClockSpeedChange: SGX clock speed was %luHz",
psDevInfo->ui32CoreClockSpeed));
return PVRSRV_OK;
}
static PVRSRV_ERROR SGXPostClockSpeedChange(IMG_HANDLE hDevHandle,
- IMG_BOOL bIdleDevice)
+ IMG_BOOL bIdleDevice,
+ PVR_POWER_STATE eCurrentPowerState)
{
+ PVRSRV_ERROR eError = PVRSRV_OK;
PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ IMG_UINT32 ui32OldClockSpeed = psDevInfo->ui32CoreClockSpeed;
- if (bIdleDevice) {
+ PVR_UNREFERENCED_PARAMETER(ui32OldClockSpeed);
- } else {
- SGXStartTimer(psDevInfo);
+ if (eCurrentPowerState == PVRSRV_POWER_STATE_D0) {
+ SGXGetTimingInfo(psDeviceNode);
+ if (bIdleDevice) {
+ eError =
+ SGXPostPowerState(hDevHandle,
+ PVR_DEVICE_POWER_STATE_ON,
+ PVR_DEVICE_POWER_STATE_IDLE);
+
+ if (eError != PVRSRV_OK) {
+ return eError;
+ }
+ }
+ SGXStartTimer(psDevInfo, IMG_TRUE);
}
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "SGXPostClockSpeedChange: SGX clock speed changed from %luHz to %luHz",
+ ui32OldClockSpeed, psDevInfo->ui32CoreClockSpeed));
+
return PVRSRV_OK;
}
return (PVRSRV_ERROR_GENERIC);
}
- SGXStartTimer(psDevInfo);
+ SGXStartTimer(psDevInfo, !bHardwareRecovery);
if (bHardwareRecovery) {
PVRSRV_SGX_HOST_CTL *psSGXHostCtl =
psDevInfo->s2DSlavePortKM.sPhysBase = psSGXDeviceMap->sSPSysPBase;
#endif
- SGXGetTimingInfo(psDevInfo, &psSGXDeviceMap->sTimingInfo);
-
#if defined (SYS_USING_INTERRUPTS)
psDeviceNode->pvISRData = psDeviceNode;
eDefaultPowerState = PVRSRV_POWER_STATE_D0;
#endif
eError = PVRSRVRegisterPowerDevice(psDeviceNode->sDevId.ui32DeviceIndex,
- SGXPrePowerState, SGXPostPowerState,
+ SGXPrePowerStateExt,
+ SGXPostPowerStateExt,
SGXPreClockSpeedChange,
SGXPostClockSpeedChange,
(IMG_HANDLE) psDeviceNode,
PDUMP_FLAGS_CONTINUOUS,
MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
-#if defined(SUPPORT_HW_RECOVERY)
-
- psDevInfo->hTimer = OSAddTimer(SGXOSTimer, psDeviceNode,
- 1000 * 50 /
- psSGXDeviceMap->sTimingInfo.
- ui32uKernelFreq);
- if (psDevInfo->hTimer == IMG_NULL) {
- PVR_DPF((PVR_DBG_ERROR,
- "DevInitSGXPart2KM : Failed to register timer callback function"));
- return PVRSRV_ERROR_GENERIC;
- }
-#endif
-
return PVRSRV_OK;
failed_init_dev_info:
}
#endif
+static struct workdata {
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ IMG_UINT32 ui32Component;
+ IMG_UINT32 ui32CallerID;
+} gHWRecoveryParams;
+
+static void HWRecoveryWrapper(struct work_struct *work)
+{
+ HWRecoveryResetSGX(gHWRecoveryParams.psDeviceNode,
+ gHWRecoveryParams.ui32Component,
+ gHWRecoveryParams.ui32CallerID);
+}
+
+DECLARE_WORK(gWork, HWRecoveryWrapper);
+
#if defined(SUPPORT_HW_RECOVERY)
IMG_VOID SGXOSTimer(IMG_VOID * pvData)
{
psSGXHostCtl->ui32HostDetectedLockups++;
- HWRecoveryResetSGX(psDeviceNode, 0, KERNEL_ID);
+ /*
+ * schedule HWRecoveryResetSGX from a work
+ * in the shared queue
+ */
+ gHWRecoveryParams.psDeviceNode = psDeviceNode;
+ gHWRecoveryParams.ui32Component = 0;
+ gHWRecoveryParams.ui32CallerID = TIMER_ID;
+ schedule_work(&gWork);
}
}
#endif
OSWriteHWReg(psDevInfo->pvRegsBaseKM,
EUR_CR_EVENT_HOST_CLEAR, ui32EventClear);
- //Read back to flush posted write to fix spurious IRQ
- OSReadHWReg(psDevInfo->pvRegsBaseKM,
- EUR_CR_EVENT_HOST_CLEAR);
}
}
psDeviceMemoryHeap[SGX_GENERAL_MAPPING_HEAP_ID].DevMemHeapType =
DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+ psDeviceMemoryHeap[SGX_ALT_MAPPING_HEAP_ID].ui32HeapID =
+ HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_ALT_MAPPING_HEAP_ID);
+ psDeviceMemoryHeap[SGX_ALT_MAPPING_HEAP_ID].sDevVAddrBase.uiAddr =
+ SGX_ALT_MAPPING_HEAP_BASE;
+ psDeviceMemoryHeap[SGX_ALT_MAPPING_HEAP_ID].ui32HeapSize =
+ SGX_ALT_MAPPING_HEAP_SIZE;
+ psDeviceMemoryHeap[SGX_ALT_MAPPING_HEAP_ID].ui32Attribs =
+ PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_MULTI_PROCESS;
+ psDeviceMemoryHeap[SGX_ALT_MAPPING_HEAP_ID].pszName = "AltMapping";
+ psDeviceMemoryHeap[SGX_ALT_MAPPING_HEAP_ID].pszBSName = "AltMapping BS";
+
+ psDeviceMemoryHeap[SGX_ALT_MAPPING_HEAP_ID].DevMemHeapType =
+ DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+
#if defined(SGX_FEATURE_2D_HARDWARE)
psDeviceMemoryHeap[SGX_2D_HEAP_ID].ui32HeapID =
SYS_DATA gsSysData;
static SYS_SPECIFIC_DATA gsSysSpecificData;
+SYS_SPECIFIC_DATA *gpsSysSpecificData;
static IMG_UINT32 gui32SGXDeviceID;
static SGX_DEVICE_MAP gsSGXDeviceMap;
PVRSRV_ERROR eError;
PVRSRV_DEVICE_NODE *psDeviceNode;
IMG_CPU_PHYADDR TimerRegPhysBase;
+#if !defined(SGX_DYNAMIC_TIMING_INFO)
SGX_TIMING_INFORMATION *psTimingInfo;
+#endif
gpsSysData = &gsSysData;
OSMemSet(gpsSysData, 0, sizeof(SYS_DATA));
- gpsSysData->pvSysSpecificData = &gsSysSpecificData;
- gsSysSpecificData.ui32SysSpecificData = 0;
+ gpsSysSpecificData = &gsSysSpecificData;
+ OSMemSet(gpsSysSpecificData, 0, sizeof(SYS_SPECIFIC_DATA));
+
+ gpsSysData->pvSysSpecificData = gpsSysSpecificData;
eError = OSInitEnvData(&gpsSysData->pvEnvSpecificData);
if (eError != PVRSRV_OK) {
return eError;
}
- TimerRegPhysBase.uiAddr = SYS_OMAP3430_GP11TIMER_REGS_SYS_PHYS_BASE;
+ TimerRegPhysBase.uiAddr =
+ SYS_OMAP3430_GP11TIMER_PHYS_BASE + SYS_OMAP3430_GPTIMER_REGS;
gpsSysData->pvSOCTimerRegisterKM = IMG_NULL;
gpsSysData->hSOCTimerRegisterOSMemHandle = 0;
OSReservePhys(TimerRegPhysBase,
(IMG_VOID **) & gpsSysData->pvSOCTimerRegisterKM,
&gpsSysData->hSOCTimerRegisterOSMemHandle);
+#if !defined(SGX_DYNAMIC_TIMING_INFO)
+
psTimingInfo = &gsSGXDeviceMap.sTimingInfo;
psTimingInfo->ui32CoreClockSpeed = SYS_SGX_CLOCK_SPEED;
psTimingInfo->ui32HWRecoveryFreq = SYS_SGX_HWRECOVERY_TIMEOUT_FREQ;
psTimingInfo->ui32ActivePowManLatencyms =
SYS_SGX_ACTIVE_POWER_LATENCY_MS;
psTimingInfo->ui32uKernelFreq = SYS_SGX_PDS_TIMER_FREQ;
+#endif
eError = SysLocateDevices(gpsSysData);
if (eError != PVRSRV_OK) {
SYS_SPECIFIC_DATA_SET(&gsSysSpecificData,
SYS_SPECIFIC_DATA_ENABLE_PDUMPINIT);
- eError = EnableSystemClocks(gpsSysData, &gsSGXDeviceMap.sTimingInfo);
+ eError = InitSystemClocks(gpsSysData);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "SysInitialise: Failed to init system clocks (%d)",
+ eError));
+ SysDeinitialise(gpsSysData);
+ gpsSysData = IMG_NULL;
+ return eError;
+ }
+
+ eError = EnableSystemClocks(gpsSysData);
if (eError != PVRSRV_OK) {
PVR_DPF((PVR_DBG_ERROR,
"SysInitialise: Failed to Enable system clocks (%d)",
}
SYS_SPECIFIC_DATA_SET(&gsSysSpecificData,
SYS_SPECIFIC_DATA_ENABLE_SYSCLOCKS);
+
+ eError = OSInitPerf(gpsSysData);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "SysInitialise: Failed to init DVFS (%d)", eError));
+ SysDeinitialise(gpsSysData);
+ gpsSysData = IMG_NULL;
+ return eError;
+ }
#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
eError = EnableSGXClocks(gpsSysData);
if (eError != PVRSRV_OK) {
DisableSGXClocks(gpsSysData);
#endif
+ gpsSysSpecificData->bSGXInitComplete = IMG_TRUE;
+
return eError;
}
{
PVRSRV_ERROR eError;
- SYS_SPECIFIC_DATA *psSysSpecData =
- (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
-
PVR_UNREFERENCED_PARAMETER(psSysData);
#if defined(SYS_USING_INTERRUPTS)
if (SYS_SPECIFIC_DATA_TEST
- (psSysSpecData, SYS_SPECIFIC_DATA_ENABLE_LISR)) {
+ (gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_LISR)) {
eError = OSUninstallDeviceLISR(psSysData);
if (eError != PVRSRV_OK) {
PVR_DPF((PVR_DBG_ERROR,
}
if (SYS_SPECIFIC_DATA_TEST
- (psSysSpecData, SYS_SPECIFIC_DATA_ENABLE_MISR)) {
+ (gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_MISR)) {
eError = OSUninstallMISR(psSysData);
if (eError != PVRSRV_OK) {
PVR_DPF((PVR_DBG_ERROR,
}
#endif
+ eError = OSCleanupPerf(gpsSysSpecificData);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "SysDeinitialise: OSCleanupDvfs failed"));
+ return eError;
+ }
+
if (SYS_SPECIFIC_DATA_TEST
- (psSysSpecData, SYS_SPECIFIC_DATA_ENABLE_INITDEV)) {
+ (gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_INITDEV)) {
#if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
PVR_ASSERT(SYS_SPECIFIC_DATA_TEST
- (psSysSpecData, SYS_SPECIFIC_DATA_ENABLE_SYSCLOCKS));
+ (gpsSysSpecificData,
+ SYS_SPECIFIC_DATA_ENABLE_SYSCLOCKS));
eError = EnableSGXClocks(gpsSysData);
if (eError != PVRSRV_OK) {
}
if (SYS_SPECIFIC_DATA_TEST
- (psSysSpecData, SYS_SPECIFIC_DATA_ENABLE_SYSCLOCKS)) {
+ (gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_SYSCLOCKS)) {
DisableSystemClocks(gpsSysData);
}
+ CleanupSystemClocks(gpsSysData);
+
if (SYS_SPECIFIC_DATA_TEST
- (psSysSpecData, SYS_SPECIFIC_DATA_ENABLE_ENVDATA)) {
+ (gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_ENVDATA)) {
eError = OSDeInitEnvData(gpsSysData->pvEnvSpecificData);
if (eError != PVRSRV_OK) {
PVR_DPF((PVR_DBG_ERROR,
#if defined(NO_HARDWARE)
if (SYS_SPECIFIC_DATA_TEST
- (psSysSpecData, SYS_SPECIFIC_DATA_ENABLE_LOCATEDEV)) {
+ (gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_LOCATEDEV)) {
OSBaseFreeContigMemory(SYS_OMAP3430_SGX_REGS_SIZE,
gsSGXRegsCPUVAddr,
#endif
if (SYS_SPECIFIC_DATA_TEST
- (psSysSpecData, SYS_SPECIFIC_DATA_ENABLE_PDUMPINIT)) {
+ (gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_PDUMPINIT)) {
PDUMPDEINIT();
}
- psSysSpecData->ui32SysSpecificData = 0;
+ gpsSysSpecificData->ui32SysSpecificData = 0;
+ gpsSysSpecificData->bSGXInitComplete = IMG_FALSE;
+
gpsSysData = IMG_NULL;
return PVRSRV_OK;
PVR_UNREFERENCED_PARAMETER(psSysData);
PVR_UNREFERENCED_PARAMETER(ui32ClearBits);
+ /* Flush posted write for the irq status to avoid spurious interrupts */
+ OSReadHWReg(((PVRSRV_SGXDEV_INFO *) gpsSGXDevNode->pvDevice)->
+ pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR);
}
PVRSRV_ERROR SysSystemPrePowerState(PVR_POWER_STATE eNewPowerState)
if (SYS_SPECIFIC_DATA_TEST
(&gsSysSpecificData,
SYS_SPECIFIC_DATA_PM_DISABLE_SYSCLOCKS)) {
- eError =
- EnableSystemClocks(gpsSysData,
- &gsSGXDeviceMap.sTimingInfo);
+ eError = EnableSystemClocks(gpsSysData);
if (eError != PVRSRV_OK) {
PVR_DPF((PVR_DBG_ERROR,
"SysSystemPostPowerState: EnableSystemClocks failed (%d)",
#define SYS_OMAP3430_SGX_IRQ 21
-#define SYS_OMAP3430_GP11TIMER_ENABLE_SYS_PHYS_BASE 0x48088024
-#define SYS_OMAP3430_GP11TIMER_REGS_SYS_PHYS_BASE 0x48088028
-#define SYS_OMAP3430_GP11TIMER_TSICR_SYS_PHYS_BASE 0x48088040
+#define SYS_OMAP3430_GP11TIMER_PHYS_BASE 0x48088000
+#define SYS_OMAP3430_GPTIMER_ENABLE 0x24
+#define SYS_OMAP3430_GPTIMER_REGS 0x28
+#define SYS_OMAP3430_GPTIMER_TSICR 0x40
+#define SYS_OMAP3430_GPTIMER_SIZE 1024
#endif
#if defined(__linux__)
#include <linux/version.h>
#include <linux/clk.h>
-#if defined (SUPPORT_TI_PM)
-#include <asm/semaphore.h>
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22))
-#include <asm/arch/resource.h>
-#endif
-#else
#include <linux/semaphore.h>
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22))
+/*#include <asm/arch/resource.h>*/
#endif
#endif
IMG_CHAR *SysCreateVersionString(IMG_CPU_PHYADDR sRegRegion);
+ PVRSRV_ERROR InitSystemClocks(SYS_DATA * psSysData);
+ IMG_VOID CleanupSystemClocks(SYS_DATA * psSysData);
IMG_VOID DisableSystemClocks(SYS_DATA * psSysData);
- PVRSRV_ERROR EnableSystemClocks(SYS_DATA * psSysData,
- SGX_TIMING_INFORMATION *
- psSGXTimingInfo);
+ PVRSRV_ERROR EnableSystemClocks(SYS_DATA * psSysData);
IMG_VOID DisableSGXClocks(SYS_DATA * psSysData);
PVRSRV_ERROR EnableSGXClocks(SYS_DATA * psSysData);
typedef struct _SYS_SPECIFIC_DATA_TAG_ {
IMG_UINT32 ui32SysSpecificData;
- IMG_BOOL bSGXClocksEnabled;
PVRSRV_DEVICE_NODE *psSGXDevNode;
+ IMG_BOOL bSGXInitComplete;
+ IMG_BOOL bSGXClocksEnabled;
#if defined(__linux__)
- IMG_BOOL bSysClocksOneTimeInit;
-
struct clk *psCORE_CK;
struct clk *psSGX_FCK;
struct clk *psSGX_ICK;
#if defined(DEBUG) || defined(TIMING)
struct clk *psGPT11_FCK;
struct clk *psGPT11_ICK;
+ void __iomem *gpt_base;
#endif
-#if defined (SUPPORT_TI_PM)
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22))
- SGX_TIMING_INFORMATION *psSGXTimingInfo;
-
struct constraint_handle *pVdd2Handle;
#endif
-#endif
-
- struct semaphore sConstraintNotifierLock;
#endif
} SYS_SPECIFIC_DATA;
+ extern SYS_SPECIFIC_DATA *gpsSysSpecificData;
+
#if defined(__cplusplus)
}
#endif
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/hardirq.h>
+#include <mach/omap-pm.h>
#include <asm/bug.h>
-#if defined (SUPPORT_TI_PM)
-#include <asm/semaphore.h>
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22))
-#include <asm/arch/resource.h>
-#endif
-#endif
+#include <clock.h>
#include "sgxdefs.h"
#include "services_headers.h"
#include "sysinfo.h"
#include "sysconfig.h"
#include "sgxinfokm.h"
#include "syslocal.h"
+#include "env_data.h"
#define HZ_TO_MHZ(m) ((m) / 1000000)
-#define MUTEX_INIT(pl) init_MUTEX(pl)
-#define MUTEX_LOCK(pl) down(pl)
-#define MUTEX_UNLOCK(pl) up(pl)
-#if defined (SUPPORT_TI_PM)
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22))
-
-static SYS_SPECIFIC_DATA *psNotifierSysSpecData;
-
+#if defined(SGX_DYNAMIC_TIMING_INFO)
static inline unsigned long scale_by_rate(unsigned long val,
unsigned long rate1,
unsigned long rate2)
return scale_by_rate(val, SYS_SGX_CLOCK_SPEED, rate);
}
-static void post_clock_rate_change(void)
+IMG_VOID SysGetSGXTimingInformation(SGX_TIMING_INFORMATION * psTimingInfo)
{
unsigned long rate;
- SGX_TIMING_INFORMATION *psTimingInfo =
- psNotifierSysSpecData->psSGXTimingInfo;
- rate = clk_get_rate(psNotifierSysSpecData->psSGX_FCK);
+#if defined(NO_HARDWARE)
+ rate = SYS_SGX_CLOCK_SPEED;
+#else
+ PVR_ASSERT(gpsSysSpecificData->bSGXClocksEnabled);
+ rate = clk_get_rate(gpsSysSpecificData->psSGX_FCK);
PVR_ASSERT(rate != 0);
-
+#endif
psTimingInfo->ui32CoreClockSpeed = rate;
psTimingInfo->ui32HWRecoveryFreq =
scale_prop_to_SGX_clock(SYS_SGX_HWRECOVERY_TIMEOUT_FREQ, rate);
psTimingInfo->ui32uKernelFreq =
scale_prop_to_SGX_clock(SYS_SGX_PDS_TIMER_FREQ, rate);
-
- PVR_TRACE(("post_clock_rate_change: SGX clock rate: %dMHz",
- HZ_TO_MHZ(psTimingInfo->ui32CoreClockSpeed)));
-
-#if 0
- PVR_TRACE(("post_clock_rate_change: HW Recovery frequency: %dHz",
- psTimingInfo->ui32HWRecoveryFreq));
- PVR_TRACE(("post_clock_rate_change: PDS Timer frequency: %dHz",
- psTimingInfo->ui32uKernelFreq));
-#endif
-
- PVRSRVDevicePostClockSpeedChange(psNotifierSysSpecData->psSGXDevNode->
- sDevId.ui32DeviceIndex, IMG_FALSE,
- IMG_NULL);
+ psTimingInfo->ui32ActivePowManLatencyms =
+ SYS_SGX_ACTIVE_POWER_LATENCY_MS;
}
+#endif
-static void pre_clock_rate_change(void)
-{
- PVRSRVDevicePreClockSpeedChange(psNotifierSysSpecData->psSGXDevNode->
- sDevId.ui32DeviceIndex, IMG_FALSE,
- IMG_NULL);
-
-}
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22))
+#if !defined(SGX_DYNAMIC_TIMING_INFO)
+#error "SGX_DYNAMIC_TIMING_INFO must be defined for this platform"
+#endif
static int vdd2_post_func(struct notifier_block *n, unsigned long event,
void *ptr)
PVR_UNREFERENCED_PARAMETER(event);
PVR_UNREFERENCED_PARAMETER(ptr);
- BUG_ON(in_irq());
+ if (gpsSysSpecificData->bSGXClocksEnabled
+ && gpsSysSpecificData->bSGXInitComplete) {
+#if defined(DEBUG)
+ unsigned long rate;
- if (psNotifierSysSpecData->bSGXClocksEnabled) {
- post_clock_rate_change();
- }
+ rate = clk_get_rate(gpsSysSpecificData->psSGX_FCK);
- MUTEX_UNLOCK(&psNotifierSysSpecData->sConstraintNotifierLock);
+ PVR_ASSERT(rate != 0);
+ PVR_TRACE(("%s: SGX clock rate: %dMHz", __FUNCTION__,
+ HZ_TO_MHZ(rate)));
+#endif
+ PVRSRVDevicePostClockSpeedChange(gpsSysSpecificData->
+ psSGXDevNode->sDevId.
+ ui32DeviceIndex, IMG_TRUE,
+ IMG_NULL);
+ }
return 0;
}
PVR_UNREFERENCED_PARAMETER(event);
PVR_UNREFERENCED_PARAMETER(ptr);
- BUG_ON(in_irq());
+ if (gpsSysSpecificData->bSGXClocksEnabled
+ && gpsSysSpecificData->bSGXInitComplete) {
+ BUG_ON(gpsSysData->eCurrentPowerState > PVRSRV_POWER_STATE_D1);
+ PVRSRVDevicePreClockSpeedChange(gpsSysSpecificData->
+ psSGXDevNode->sDevId.
+ ui32DeviceIndex, IMG_TRUE,
+ IMG_NULL);
+ }
- MUTEX_LOCK(&psNotifierSysSpecData->sConstraintNotifierLock);
+ return 0;
+}
- if (psNotifierSysSpecData->bSGXClocksEnabled) {
- pre_clock_rate_change();
- }
+static int vdd2_pre_post_func(struct notifier_block *n, unsigned long event,
+ void *ptr)
+{
+ struct clk_notifier_data *cnd;
+ PVR_UNREFERENCED_PARAMETER(n);
+
+ cnd = (struct clk_notifier_data *)ptr;
+
+ PVR_TRACE(("vdd2_pre_post_func: old clock rate = %lu", cnd->old_rate));
+ PVR_TRACE(("vdd2_pre_post_func: new clock rate = %lu", cnd->new_rate));
+
+ if (CLK_PRE_RATE_CHANGE == event) {
+ PVRSRVDvfsLock();
+ PVR_TRACE(("vdd2_pre_post_func: CLK_PRE_RATE_CHANGE event"));
+ vdd2_pre_func(n, event, ptr);
+ } else if (CLK_POST_RATE_CHANGE == event) {
+ PVR_TRACE(("vdd2_pre_post_func: CLK_POST_RATE_CHANGE event"));
+ vdd2_post_func(n, event, ptr);
+ PVRSRVDvfsUnlock();
+ } else if (CLK_ABORT_RATE_CHANGE == event) {
+ PVR_TRACE(("vdd2_pre_post_func: CLK_ABORT_RATE_CHANGE event"));
+ PVRSRVDvfsUnlock();
+ } else {
+ printk("vdd2_pre_post_func: unexpected event (%lu)\n", event);
+ PVR_DPF((PVR_DBG_ERROR,
+ "vdd2_pre_post_func: unexpected event (%lu)", event));
+ }
+ PVR_TRACE(("vdd2_pre_post_func end."));
return 0;
}
-static struct notifier_block vdd2_pre = {
- vdd2_pre_func,
+static struct notifier_block vdd2_pre_post = {
+ vdd2_pre_post_func,
NULL
};
-static struct notifier_block vdd2_post = {
- vdd2_post_func,
- NULL
-};
+static IMG_VOID RegisterConstraintNotifications(SYS_SPECIFIC_DATA *
+ psSysSpecData)
+{
+ PVR_TRACE(("Registering constraint notifications"));
-static struct constraint_id cnstr_id_vdd2 = {
- .type = RES_OPP_CO,
- .data = (void *)"vdd2_opp"
-};
+ clk_notifier_register(psSysSpecData->psSGX_FCK, &vdd2_pre_post);
+ PVR_TRACE(("VDD2 constraint notifications registered"));
+}
-static IMG_VOID RegisterConstraintNotifications(SYS_DATA * psSysData,
- SGX_TIMING_INFORMATION *
- psSGXTimingInfo)
+static IMG_VOID UnRegisterConstraintNotifications(SYS_SPECIFIC_DATA *
+ psSysSpecData)
{
- PVR_TRACE(("Registering constraint notifications"));
+ PVR_TRACE(("Unregistering constraint notifications"));
- PVR_ASSERT(psNotifierSysSpecData == IMG_NULL);
+ clk_notifier_unregister(psSysSpecData->psSGX_FCK, &vdd2_pre_post);
+}
+#endif
- psNotifierSysSpecData =
- (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
- psNotifierSysSpecData->psSGXTimingInfo = psSGXTimingInfo;
+static struct device sgx_dev;
+static int sgx_clock_enabled;
+
+/* return value: current sgx load
+ * 0 - not busy
+ * 100 - busy
+ */
+static unsigned int sgx_current_load(void)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+ SYS_SPECIFIC_DATA *psSysSpecData;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ static unsigned int kicks_prev;
+ static long time_prev;
+
+ eError = SysAcquireData(&psSysData);
+ if (eError != PVRSRV_OK)
+ return 0;
+ psSysSpecData = (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
+ if ((!psSysSpecData) || (!psSysSpecData->bSGXClocksEnabled))
+ return 0;
+#if defined(SUPPORT_SGX_HWPERF)
+ psDeviceNode = psSysData->psDeviceNodeList;
+ while (psDeviceNode) {
+ if ((psDeviceNode->sDevId.eDeviceType == PVRSRV_DEVICE_TYPE_SGX)
+ && (psDeviceNode->pvDevice)) {
+ PVRSRV_SGXDEV_INFO *psDevInfo =
+ (PVRSRV_SGXDEV_INFO *) psDeviceNode->pvDevice;
+ unsigned int kicks = psDevInfo->ui32KickTACounter;
+ unsigned int load;
+ long time_elapsed;
+
+ time_elapsed = jiffies - time_prev;
+ if (likely(time_elapsed))
+ load =
+ 1000 * (kicks - kicks_prev) / time_elapsed;
+ else
+ load = 0;
+ kicks_prev = kicks;
+ time_prev += time_elapsed;
+ /* if the period between calls to this function was too long,
+ * then load stats are invalid
+ */
+ if (time_elapsed > 5 * HZ)
+ return 0;
+ /*pr_err("SGX load %u\n", load); */
+
+ /* 'load' shows how many times sgx was kicked per 1000 jiffies
+ * 150 is arbitrarily chosen threshold.
+ * If the number of kicks is below threshold then sgx is doing
+ * some small jobs and we can keep the clock freq low.
+ */
+ if (load < 150)
+ return 0;
+ else
+ return 100;
+ }
+ psDeviceNode = psDeviceNode->psNext;
+ }
+ return 0;
+#else
+ return 100;
+#endif
+}
- constraint_register_pre_notification(psNotifierSysSpecData->pVdd2Handle,
- &vdd2_pre, max_vdd2_opp + 1);
+static void sgx_lock_perf(struct work_struct *work)
+{
+ int vdd1, vdd2;
+ static int bHigh;
+ int high;
+ unsigned int load;
+ struct delayed_work *d_work =
+ container_of(work, struct delayed_work, work);
+ ENV_DATA *psEnvData = container_of(d_work, ENV_DATA, sPerfWork);
+
+ load = sgx_current_load();
+ if (load) {
+ vdd1 = 500000000;
+ vdd2 = 400000;
+ high = 1;
+ } else {
+ vdd1 = 0;
+ vdd2 = 0;
+ high = 0;
+ }
+ if (high != bHigh) {
+ omap_pm_set_min_bus_tput(&sgx_dev, OCP_INITIATOR_AGENT, vdd2);
+ omap_pm_set_min_mpu_freq(&sgx_dev, vdd1);
+ bHigh = high;
+ }
+ if (sgx_clock_enabled || load)
+ queue_delayed_work(psEnvData->psPerfWorkqueue,
+ &psEnvData->sPerfWork, HZ / 5);
+}
- constraint_register_post_notification(psNotifierSysSpecData->
- pVdd2Handle, &vdd2_post,
- max_vdd2_opp + 1);
+static void sgx_need_perf(SYS_DATA * psSysData, int ena)
+{
+ ENV_DATA *psEnvData = (ENV_DATA *) psSysData->pvEnvSpecificData;
- PVR_TRACE(("VDD2 constraint notifications registered"));
+ sgx_clock_enabled = ena;
+ cancel_delayed_work(&psEnvData->sPerfWork);
+ queue_delayed_work(psEnvData->psPerfWorkqueue, &psEnvData->sPerfWork,
+ 0);
}
-static IMG_VOID UnRegisterConstraintNotifications(IMG_VOID)
+PVRSRV_ERROR OSInitPerf(IMG_VOID * pvSysData)
{
- if (psNotifierSysSpecData == IMG_NULL) {
- return;
+ SYS_DATA *psSysData = (SYS_DATA *) pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *) psSysData->pvEnvSpecificData;
+
+ if (psEnvData->psPerfWorkqueue) {
+ PVR_DPF((PVR_DBG_ERROR, "OSInitPerf: already inited"));
+ return PVRSRV_ERROR_GENERIC;
}
- PVR_TRACE(("Unregistering constraint notifications"));
+ PVR_TRACE(("Initing DVFS %x", pvSysData));
+
+ psEnvData->psPerfWorkqueue = create_singlethread_workqueue("sgx_perf");
+ INIT_DELAYED_WORK(&psEnvData->sPerfWork, sgx_lock_perf);
+
+ return PVRSRV_OK;
+}
- constraint_unregister_pre_notification(psNotifierSysSpecData->
- pVdd2Handle, &vdd2_pre,
- max_vdd2_opp + 1);
+PVRSRV_ERROR OSCleanupPerf(IMG_VOID * pvSysData)
+{
+ SYS_DATA *psSysData = (SYS_DATA *) pvSysData;
+ ENV_DATA *psEnvData = (ENV_DATA *) psSysData->pvEnvSpecificData;
+
+ if (!psEnvData->psPerfWorkqueue) {
+ PVR_DPF((PVR_DBG_ERROR, "OSCleanupPerf: not inited"));
+ return PVRSRV_ERROR_GENERIC;
+ }
- constraint_unregister_post_notification(psNotifierSysSpecData->
- pVdd2Handle, &vdd2_post,
- max_vdd2_opp + 1);
+ PVR_TRACE(("Cleaning up DVFS"));
- psNotifierSysSpecData = IMG_NULL;
+ flush_workqueue(psEnvData->psPerfWorkqueue);
+ destroy_workqueue(psEnvData->psPerfWorkqueue);
+
+ return PVRSRV_OK;
}
-#endif
-#endif
+
PVRSRV_ERROR EnableSGXClocks(SYS_DATA * psSysData)
{
#if !defined(NO_HARDWARE)
SYS_SPECIFIC_DATA *psSysSpecData =
(SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
+#if defined(DEBUG)
unsigned long rate;
+#endif
int res;
if (psSysSpecData->bSGXClocksEnabled) {
clk_disable(psSysSpecData->psSGX_FCK);
return PVRSRV_ERROR_GENERIC;
}
+#if 0
+ /* Code section removed for Fremnatle -
+ * call to clk_set_rate was causing crash */
rate = clk_get_rate(psSysSpecData->psSGX_FCK);
if (rate < SYS_SGX_CLOCK_SPEED) {
}
PVR_TRACE(("SGX Functional Clock rate is %dMhz",
HZ_TO_MHZ(clk_get_rate(psSysSpecData->psSGX_FCK))));
-
-#if defined (SUPPORT_TI_PM)
BUG_ON(in_irq());
#endif
- MUTEX_LOCK(&psSysSpecData->sConstraintNotifierLock);
psSysSpecData->bSGXClocksEnabled = IMG_TRUE;
-#if defined (SUPPORT_TI_PM)
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22))
-
- pre_clock_rate_change();
-
- post_clock_rate_change();
-#endif
-#endif
-
- MUTEX_UNLOCK(&psSysSpecData->sConstraintNotifierLock);
-
#else
PVR_UNREFERENCED_PARAMETER(psSysData);
#endif
+ sgx_need_perf(psSysData, 1);
return PVRSRV_OK;
}
if (psSysSpecData->psSGX_FCK) {
clk_disable(psSysSpecData->psSGX_FCK);
}
- MUTEX_LOCK(&psSysSpecData->sConstraintNotifierLock);
psSysSpecData->bSGXClocksEnabled = IMG_FALSE;
-
- MUTEX_UNLOCK(&psSysSpecData->sConstraintNotifierLock);
#else
PVR_UNREFERENCED_PARAMETER(psSysData);
#endif
+ sgx_need_perf(psSysData, 0);
}
-PVRSRV_ERROR EnableSystemClocks(SYS_DATA * psSysData,
- SGX_TIMING_INFORMATION * psSGXTimingInfo)
+static PVRSRV_ERROR InitSgxClocks(SYS_DATA * psSysData)
{
- SYS_SPECIFIC_DATA *psSysSpecData =
- (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
+ SYS_SPECIFIC_DATA *psSysSpecData = psSysData->pvSysSpecificData;
struct clk *psCLK;
- int res;
-#if !defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
- PVRSRV_ERROR eError;
-#endif
-#if defined(DEBUG) || defined(TIMING)
- int rate;
- struct clk *sys_ck;
- IMG_CPU_PHYADDR TimerRegPhysBase;
- IMG_HANDLE hTimerEnable;
- IMG_UINT32 *pui32TimerEnable;
+ struct clk *core_ck = NULL;
+
+ psCLK = clk_get(NULL, "sgx_fck");
+ if (IS_ERR(psCLK))
+ goto err0;
+ psSysSpecData->psSGX_FCK = psCLK;
+
+ psCLK = clk_get(NULL, "sgx_ick");
+ if (IS_ERR(psCLK))
+ goto err1;
+ psSysSpecData->psSGX_ICK = psCLK;
+
+ core_ck = clk_get(NULL, "core_ck");
+ if (IS_ERR(core_ck))
+ goto err2;
+ if (clk_set_parent(psSysSpecData->psSGX_FCK, core_ck) < 0) {
+ clk_put(core_ck);
+ goto err2;
+ }
+ clk_put(core_ck);
-#endif
+ RegisterConstraintNotifications(psSysSpecData);
- PVR_TRACE(("EnableSystemClocks: Enabling System Clocks"));
+ return PVRSRV_OK;
- if (!psSysSpecData->bSysClocksOneTimeInit) {
- MUTEX_INIT(&psSysSpecData->sConstraintNotifierLock);
- psCLK = clk_get(NULL, "core_ck");
- if (IS_ERR(psCLK)) {
- PVR_DPF((PVR_DBG_ERROR,
- "EnableSsystemClocks: Couldn't get Core Clock"));
- goto ExitError;
- }
- psSysSpecData->psCORE_CK = psCLK;
+err2:
+ clk_put(psSysSpecData->psSGX_ICK);
+err1:
+ clk_put(psSysSpecData->psSGX_FCK);
+err0:
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: couldn't init clocks fck %p ick %p core %p", __func__,
+ psSysSpecData->psSGX_FCK, psSysSpecData->psSGX_ICK, core_ck));
+ psSysSpecData->psSGX_FCK = NULL;
+ psSysSpecData->psSGX_ICK = NULL;
- psCLK = clk_get(NULL, "sgx_fck");
- if (IS_ERR(psCLK)) {
- PVR_DPF((PVR_DBG_ERROR,
- "EnableSsystemClocks: Couldn't get SGX Functional Clock"));
- goto ExitError;
- }
- psSysSpecData->psSGX_FCK = psCLK;
+ return PVRSRV_ERROR_GENERIC;
+}
- psCLK = clk_get(NULL, "sgx_ick");
- if (IS_ERR(psCLK)) {
- PVR_DPF((PVR_DBG_ERROR,
- "EnableSystemClocks: Couldn't get SGX Interface Clock"));
- goto ExitError;
- }
- psSysSpecData->psSGX_ICK = psCLK;
+static void CleanupSgxClocks(SYS_DATA * psSysData)
+{
+ SYS_SPECIFIC_DATA *psSysSpecData = psSysData->pvSysSpecificData;
-#if defined(DEBUG)
- psCLK = clk_get(NULL, "mpu_ck");
- if (IS_ERR(psCLK)) {
- PVR_DPF((PVR_DBG_ERROR,
- "EnableSystemClocks: Couldn't get MPU Clock"));
- goto ExitError;
- }
- psSysSpecData->psMPU_CK = psCLK;
-#endif
- res =
- clk_set_parent(psSysSpecData->psSGX_FCK,
- psSysSpecData->psCORE_CK);
- if (res < 0) {
- PVR_DPF((PVR_DBG_ERROR,
- "EnableSystemClocks: Couldn't set SGX parent clock (%d)",
- res));
- goto ExitError;
- }
+ UnRegisterConstraintNotifications(psSysSpecData);
- psSysSpecData->bSysClocksOneTimeInit = IMG_TRUE;
- }
-#if defined (SUPPORT_TI_PM)
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22))
- psSysSpecData->pVdd2Handle = constraint_get("pvrsrvkm", &cnstr_id_vdd2);
- if (IS_ERR(psSysSpecData->pVdd2Handle)) {
- PVR_DPF((PVR_DBG_ERROR,
- "EnableSystemClocks: Couldn't get VDD2 constraint handle"));
- goto ExitError;
+ if (psSysSpecData->psSGX_ICK) {
+ clk_put(psSysSpecData->psSGX_ICK);
+ psSysSpecData->psSGX_ICK = NULL;
}
- RegisterConstraintNotifications(psSysData, psSGXTimingInfo);
-#endif
-#endif
-#if !defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
-
- eError = EnableSGXClocks(psSysData);
- if (eError != PVRSRV_OK) {
- goto ExitUnRegisterConstraintNotifications;
+ if (psSysSpecData->psSGX_FCK) {
+ clk_put(psSysSpecData->psSGX_FCK);
+ psSysSpecData->psSGX_FCK = NULL;
}
-#endif
+}
#if defined(DEBUG) || defined(TIMING)
+static u32 inline gpt_read_reg(SYS_DATA * psSysData, u32 reg)
+{
+ SYS_SPECIFIC_DATA *psSysSpecData = psSysData->pvSysSpecificData;
+
+ return __raw_readl(psSysSpecData->gpt_base + reg);
+}
+
+static void inline gpt_write_reg(SYS_DATA * psSysData, u32 reg, u32 val)
+{
+ SYS_SPECIFIC_DATA *psSysSpecData = psSysData->pvSysSpecificData;
+
+ __raw_writel(val, psSysSpecData->gpt_base + reg);
+}
+
+static PVRSRV_ERROR InitDebugClocks(SYS_DATA * psSysData)
+{
+ SYS_SPECIFIC_DATA *psSysSpecData = psSysData->pvSysSpecificData;
+ struct clk *psCLK;
+ struct clk *sys_ck = NULL;
+ u32 rate;
+
+ psCLK = clk_get(NULL, "mpu_ck");
+ if (IS_ERR(psCLK))
+ goto err0;
+ psSysSpecData->psMPU_CK = psCLK;
psCLK = clk_get(NULL, "gpt11_fck");
- if (IS_ERR(psCLK)) {
- PVR_DPF((PVR_DBG_ERROR,
- "EnableSystemClocks: Couldn't get GPTIMER11 functional clock"));
- goto ExitDisableSGXClocks;
- }
+ if (IS_ERR(psCLK))
+ goto err1;
psSysSpecData->psGPT11_FCK = psCLK;
psCLK = clk_get(NULL, "gpt11_ick");
- if (IS_ERR(psCLK)) {
- PVR_DPF((PVR_DBG_ERROR,
- "EnableSystemClocks: Couldn't get GPTIMER11 interface clock"));
- goto ExitDisableSGXClocks;
- }
+ if (IS_ERR(psCLK))
+ goto err2;
psSysSpecData->psGPT11_ICK = psCLK;
sys_ck = clk_get(NULL, "sys_ck");
- if (IS_ERR(sys_ck)) {
- PVR_DPF((PVR_DBG_ERROR,
- "EnableSystemClocks: Couldn't get System clock"));
- goto ExitDisableSGXClocks;
- }
-
+ if (IS_ERR(sys_ck))
+ goto err3;
if (clk_get_parent(psSysSpecData->psGPT11_FCK) != sys_ck) {
- PVR_TRACE(("Setting GPTIMER11 parent to System Clock"));
- res = clk_set_parent(psSysSpecData->psGPT11_FCK, sys_ck);
- if (res < 0) {
- PVR_DPF((PVR_DBG_ERROR,
- "EnableSystemClocks: Couldn't set GPTIMER11 parent clock (%d)",
- res));
- goto ExitDisableSGXClocks;
+ if (clk_set_parent(psSysSpecData->psGPT11_FCK, sys_ck) < 0) {
+ clk_put(sys_ck);
+ goto err3;
}
}
+ clk_put(sys_ck);
- rate = clk_get_rate(psSysSpecData->psGPT11_FCK);
- PVR_TRACE(("GPTIMER11 clock is %dMHz", HZ_TO_MHZ(rate)));
+ PVR_TRACE(("GPTIMER11 clock is %dMHz",
+ HZ_TO_MHZ(clk_get_rate(psSysSpecData->psGPT11_FCK))));
- res = clk_enable(psSysSpecData->psGPT11_FCK);
- if (res < 0) {
- PVR_DPF((PVR_DBG_ERROR,
- "EnableSystemClocks: Couldn't enable GPTIMER11 functional clock (%d)",
- res));
- goto ExitDisableSGXClocks;
- }
+ psSysSpecData->gpt_base = ioremap(SYS_OMAP3430_GP11TIMER_PHYS_BASE,
+ SYS_OMAP3430_GPTIMER_SIZE);
+ if (!psSysSpecData->gpt_base)
+ goto err3;
- res = clk_enable(psSysSpecData->psGPT11_ICK);
- if (res < 0) {
- PVR_DPF((PVR_DBG_ERROR,
- "EnableSystemClocks: Couldn't enable GPTIMER11 interface clock (%d)",
- res));
- goto ExitDisableGPT11FCK;
- }
-
- TimerRegPhysBase.uiAddr = SYS_OMAP3430_GP11TIMER_TSICR_SYS_PHYS_BASE;
- pui32TimerEnable = OSMapPhysToLin(TimerRegPhysBase,
- 4,
- PVRSRV_HAP_KERNEL_ONLY |
- PVRSRV_HAP_UNCACHED, &hTimerEnable);
+ clk_enable(psSysSpecData->psGPT11_ICK);
+ clk_enable(psSysSpecData->psGPT11_FCK);
- if (pui32TimerEnable == IMG_NULL) {
- PVR_DPF((PVR_DBG_ERROR,
- "EnableSystemClocks: OSMapPhysToLin failed"));
- goto ExitDisableGPT11ICK;
- }
-
- rate = *pui32TimerEnable;
+ rate = gpt_read_reg(psSysData, SYS_OMAP3430_GPTIMER_TSICR);
if (!(rate & 4)) {
PVR_TRACE(("Setting GPTIMER11 mode to posted (currently is non-posted)"));
-
- *pui32TimerEnable = rate | 4;
+ gpt_write_reg(psSysData, SYS_OMAP3430_GPTIMER_TSICR, rate | 4);
}
- OSUnMapPhysToLin(pui32TimerEnable,
- 4,
- PVRSRV_HAP_KERNEL_ONLY | PVRSRV_HAP_UNCACHED,
- hTimerEnable);
+ clk_disable(psSysSpecData->psGPT11_FCK);
+ clk_disable(psSysSpecData->psGPT11_ICK);
+
+ return PVRSRV_OK;
- TimerRegPhysBase.uiAddr = SYS_OMAP3430_GP11TIMER_ENABLE_SYS_PHYS_BASE;
- pui32TimerEnable = OSMapPhysToLin(TimerRegPhysBase,
- 4,
- PVRSRV_HAP_KERNEL_ONLY |
- PVRSRV_HAP_UNCACHED, &hTimerEnable);
+err3:
+ clk_put(psSysSpecData->psGPT11_ICK);
+err2:
+ clk_put(psSysSpecData->psGPT11_FCK);
+err1:
+ clk_put(psSysSpecData->psMPU_CK);
+err0:
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: couldn't init clocks: mpu %p sys %p fck %p ick %p",
+ __func__, psSysSpecData->psMPU_CK, sys_ck,
+ psSysSpecData->psGPT11_FCK, psSysSpecData->psGPT11_ICK));
+
+ psSysSpecData->psMPU_CK = NULL;
+ psSysSpecData->psGPT11_FCK = NULL;
+ psSysSpecData->psGPT11_ICK = NULL;
- if (pui32TimerEnable == IMG_NULL) {
- PVR_DPF((PVR_DBG_ERROR,
- "EnableSystemClocks: OSMapPhysToLin failed"));
- goto ExitDisableGPT11ICK;
+ return PVRSRV_ERROR_GENERIC;
+}
+
+static void CleanupDebugClocks(SYS_DATA * psSysData)
+{
+ SYS_SPECIFIC_DATA *psSysSpecData = psSysData->pvSysSpecificData;
+
+ if (psSysSpecData->psMPU_CK) {
+ clk_put(psSysSpecData->psMPU_CK);
+ psSysSpecData->psMPU_CK = NULL;
+ }
+ if (psSysSpecData->psGPT11_FCK) {
+ clk_put(psSysSpecData->psGPT11_FCK);
+ psSysSpecData->psGPT11_FCK = NULL;
+ }
+ if (psSysSpecData->psGPT11_ICK) {
+ clk_put(psSysSpecData->psGPT11_ICK);
+ psSysSpecData->psGPT11_ICK = NULL;
}
+}
+
+static PVRSRV_ERROR EnableDebugClocks(SYS_DATA * psSysData)
+{
+ SYS_SPECIFIC_DATA *psSysSpecData = psSysData->pvSysSpecificData;
- *pui32TimerEnable = 3;
+ if (clk_enable(psSysSpecData->psGPT11_FCK) < 0)
+ goto err0;
- OSUnMapPhysToLin(pui32TimerEnable,
- 4,
- PVRSRV_HAP_KERNEL_ONLY | PVRSRV_HAP_UNCACHED,
- hTimerEnable);
+ if (clk_enable(psSysSpecData->psGPT11_ICK) < 0)
+ goto err1;
-#endif
+ gpt_write_reg(psSysData, SYS_OMAP3430_GPTIMER_ENABLE, 3);
return PVRSRV_OK;
-#if defined(DEBUG) || defined(TIMING)
-ExitDisableGPT11ICK:
- clk_disable(psSysSpecData->psGPT11_ICK);
-ExitDisableGPT11FCK:
+err1:
clk_disable(psSysSpecData->psGPT11_FCK);
-ExitDisableSGXClocks:
-#if !defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
- DisableSGXClocks(psSysData);
-#endif
-#endif
-#if !defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
-ExitUnRegisterConstraintNotifications:
-#endif
-#if defined (SUPPORT_TI_PM)
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22))
- UnRegisterConstraintNotifications();
- constraint_put(psSysSpecData->pVdd2Handle);
-#endif
-#endif
-ExitError:
+err0:
+ PVR_DPF((PVR_DBG_ERROR, "%s: can't enable clocks", __func__));
+
return PVRSRV_ERROR_GENERIC;
}
-IMG_VOID DisableSystemClocks(SYS_DATA * psSysData)
+static inline void DisableDebugClocks(SYS_DATA * psSysData)
{
-#if defined(SUPPORT_TI_PM) || defined(DEBUG) || defined(TIMING)
- SYS_SPECIFIC_DATA *psSysSpecData =
- (SYS_SPECIFIC_DATA *) psSysData->pvSysSpecificData;
-#endif
-#if defined(DEBUG) || defined(TIMING)
- IMG_CPU_PHYADDR TimerRegPhysBase;
- IMG_HANDLE hTimerDisable;
- IMG_UINT32 *pui32TimerDisable;
-#endif
+ SYS_SPECIFIC_DATA *psSysSpecData = psSysData->pvSysSpecificData;
- PVR_TRACE(("DisableSystemClocks: Disabling System Clocks"));
-#if defined (SUPPORT_TI_PM)
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22))
- UnRegisterConstraintNotifications();
-#endif
-#endif
+ gpt_write_reg(psSysData, SYS_OMAP3430_GPTIMER_ENABLE, 0);
- DisableSGXClocks(psSysData);
+ clk_disable(psSysSpecData->psGPT11_ICK);
+ clk_disable(psSysSpecData->psGPT11_FCK);
+}
-#if defined(DEBUG) || defined(TIMING)
+#else
- TimerRegPhysBase.uiAddr = SYS_OMAP3430_GP11TIMER_ENABLE_SYS_PHYS_BASE;
- pui32TimerDisable = OSMapPhysToLin(TimerRegPhysBase,
- 4,
- PVRSRV_HAP_KERNEL_ONLY |
- PVRSRV_HAP_UNCACHED, &hTimerDisable);
+PVRSRV_ERROR inline InitDebugClocks(SYS_DATA * psSysData)
+{
+ return PVRSRV_OK;
+}
- if (pui32TimerDisable == IMG_NULL) {
- PVR_DPF((PVR_DBG_ERROR,
- "DisableSystemClocks: OSMapPhysToLin failed"));
- } else {
- *pui32TimerDisable = 0;
+static void inline CleanupDebugClocks(SYS_DATA * psSysData)
+{
+}
- OSUnMapPhysToLin(pui32TimerDisable,
- 4,
- PVRSRV_HAP_KERNEL_ONLY | PVRSRV_HAP_UNCACHED,
- hTimerDisable);
- }
+static inline PVRSRV_ERROR EnableDebugClocks(SYS_DATA * psSysData)
+{
+ return PVRSRV_OK;
+}
- clk_disable(psSysSpecData->psGPT11_ICK);
+static inline void DisableDebugClocks(SYS_DATA * psSysData)
+{
+}
+#endif
- clk_disable(psSysSpecData->psGPT11_FCK);
+PVRSRV_ERROR InitSystemClocks(SYS_DATA * psSysData)
+{
+ if (InitSgxClocks(psSysData) != PVRSRV_OK)
+ goto err0;
+ if (InitDebugClocks(psSysData) != PVRSRV_OK)
+ goto err1;
+
+ return PVRSRV_OK;
+
+err1:
+ CleanupSgxClocks(psSysData);
+err0:
+ return PVRSRV_ERROR_GENERIC;
+}
+
+void CleanupSystemClocks(SYS_DATA * psSysData)
+{
+ CleanupDebugClocks(psSysData);
+ CleanupSgxClocks(psSysData);
+}
+
+PVRSRV_ERROR EnableSystemClocks(SYS_DATA * psSysData)
+{
+ PVR_TRACE(("EnableSystemClocks: Enabling System Clocks"));
+
+#if !defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+ if (EnableSGXClocks(psSysData) != PVRSRV_OK)
+ goto err0;
#endif
-#if defined (SUPPORT_TI_PM)
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22))
- constraint_put(psSysSpecData->pVdd2Handle);
-#endif
+
+ if (EnableDebugClocks(psSysData) != PVRSRV_OK)
+ goto err1;
+
+ return PVRSRV_OK;
+
+err1:
+#if !defined(SUPPORT_ACTIVE_POWER_MANAGEMENT)
+ DisableSGXClocks(psSysData);
+err0:
#endif
+ return PVRSRV_ERROR_GENERIC;
+}
+
+IMG_VOID DisableSystemClocks(SYS_DATA * psSysData)
+{
+ PVR_TRACE(("DisableSystemClocks: Disabling System Clocks"));
+
+ DisableSGXClocks(psSysData);
+ DisableDebugClocks(psSysData);
}