20093908+0m5+flat+Lindent
authorNokia <nokia>
Sat, 19 May 2012 12:52:35 +0000 (15:52 +0300)
committerGrazvydas Ignotas <notasas@gmail.com>
Sat, 19 May 2012 13:34:00 +0000 (16:34 +0300)
  * Fixes: NB#129392 - fix object reference counting in the PVR video
    driver
  * Fixes: NB#132086 - Framebuffer resets are ignored by the PVR driver
  * Preparation for a change in the SGX library
  * Fixes: NB#129389 - fix random PVR driver breakage
  * Fixes: NB#128247 - fix size checking for PVR memory mapping requests
  * Fixes: NB#126777 - PVR module can cause dead-lock at reboot time
  * Fixes: NB#125756 - PVR triggers a lockdep warning
  * Fixes: NB#111084 - SGX compilation warnings
  * Fixes: NB#122294 - Performance regression in SGX operations caused
    by DVFS
  * Fixes: NB#121668 - PVR: error returned by drm_ttm_create is ignored
  * Fixes: NB#121947 - PVR: memory should not be released twice
  * Fixes: NB#119655 - PVR: random allocation failure for sizes > 4k
  * Introduce a patch related to NB#108042 -
    PVR: wrapped memory space runs out (not a complete fix)
  * Fixes: NB#112118 - Fix PVR breakage when using DVFS
  * Fix crashes due to power/clock state transitions in PVR
  * Fixes: NB#110835 - PVR: lock dependency bug
  * Enable dynamic power management for SGX
  * upgrade to SGX 1.3 (fingers crossed)

42 files changed:
pvr/Kbuild [deleted file]
pvr/Kconfig [new file with mode: 0644]
pvr/Makefile
pvr/README.keep [new file with mode: 0644]
pvr/bridged_pvr_bridge.c
pvr/buffer_manager.c
pvr/buffer_manager.h
pvr/deviceclass.c
pvr/devicemem.c
pvr/env_data.h
pvr/event.c
pvr/hash.c
pvr/mmap.c
pvr/mmu.c
pvr/module.c
pvr/modules.order [deleted file]
pvr/omaplfb.h
pvr/omaplfb_displayclass.c
pvr/omaplfb_linux.c
pvr/osfunc.c
pvr/osfunc.h
pvr/power.c
pvr/power.h
pvr/pvr_bridge.h
pvr/pvr_bridge_k.c
pvr/pvrsrv.c
pvr/queue.c
pvr/queue.h
pvr/ra.c
pvr/resman.c
pvr/services.h
pvr/servicesext.h
pvr/servicesint.h
pvr/sgx2dcore.c [new file with mode: 0644]
pvr/sgxapi_km.h
pvr/sgxconfig.h
pvr/sgxinfokm.h
pvr/sgxinit.c
pvr/sysconfig.c
pvr/sysconfig.h
pvr/syslocal.h
pvr/sysutils_linux.c

diff --git a/pvr/Kbuild b/pvr/Kbuild
deleted file mode 100644 (file)
index 19f9a24..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-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/
-
diff --git a/pvr/Kconfig b/pvr/Kconfig
new file mode 100644 (file)
index 0000000..1a826ab
--- /dev/null
@@ -0,0 +1,4 @@
+menuconfig PVR
+       tristate "PowerVR Services"
+       depends on OMAP2_DSS
+
index 7f5271d..994c427 100644 (file)
@@ -1,22 +1,77 @@
-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
 
@@ -34,40 +89,47 @@ else
 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
 
@@ -81,77 +143,79 @@ DISABLE_THREADS ?= 0
 
 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)
diff --git a/pvr/README.keep b/pvr/README.keep
new file mode 100644 (file)
index 0000000..788a703
--- /dev/null
@@ -0,0 +1,48 @@
+
+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 
index f651cf7..1e878b5 100644 (file)
 #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
@@ -836,6 +840,52 @@ PVRSRVUnmapDeviceMemoryBW(IMG_UINT32 ui32BridgeID,
        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 *
@@ -1041,11 +1091,12 @@ PVRSRVWrapExtMemoryBW(IMG_UINT32 ui32BridgeID,
                                  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;
        }
 
@@ -1089,7 +1140,7 @@ PVRSRVWrapExtMemoryBW(IMG_UINT32 ui32BridgeID,
                               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);
@@ -4694,6 +4745,8 @@ PVRSRV_ERROR CommonBridgeInit(IMG_VOID)
                              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);
index d293915..4e0eb12 100644 (file)
@@ -23,7 +23,6 @@
  * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
  *
  ******************************************************************************/
-
 #include "services_headers.h"
 
 #include "sysconfig.h"
@@ -611,7 +610,8 @@ static PVRSRV_ERROR BM_DestroyContextCallBack(IMG_PVOID pvParam,
 
                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) {
@@ -638,7 +638,8 @@ static PVRSRV_ERROR BM_DestroyContextCallBack(IMG_PVOID pvParam,
                }
        }
 
-       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, pBMContext, IMG_NULL);
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_CONTEXT), pBMContext,
+                 IMG_NULL);
 
        return PVRSRV_OK;
 }
@@ -855,7 +856,7 @@ ErrorExit:
                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;
 }
@@ -889,8 +890,8 @@ IMG_VOID BM_DestroyHeap(IMG_HANDLE hDevMemHeap)
                        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);
@@ -970,12 +971,29 @@ BM_Alloc(IMG_HANDLE hDevMemHeap,
        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;
@@ -1017,7 +1035,9 @@ BM_Wrap(IMG_HANDLE hDevMemHeap,
                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));
@@ -1027,6 +1047,12 @@ BM_Wrap(IMG_HANDLE hDevMemHeap,
                        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;
                }
        }
@@ -1049,18 +1075,13 @@ BM_Wrap(IMG_HANDLE hDevMemHeap,
        }
 
        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;
                }
@@ -1075,6 +1096,9 @@ BM_Wrap(IMG_HANDLE hDevMemHeap,
        if (pui32Flags)
                *pui32Flags = uFlags;
 
+       /* take ownership of the list if requested so */
+       if (bFreePageList && psSysAddr)
+               pBuf->pvPageList = (void *)psSysAddr;
        return IMG_TRUE;
 }
 
@@ -1082,10 +1106,16 @@ void BM_Free(BM_HANDLE hBuf, IMG_UINT32 ui32Flags)
 {
        BM_BUF *pBuf = (BM_BUF *) hBuf;
        SYS_DATA *psSysData;
-       IMG_SYS_PHYADDR sHashAddr;
 
        PVR_DPF((PVR_DBG_MESSAGE, "BM_Free (h=%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;
@@ -1093,16 +1123,20 @@ void BM_Free(BM_HANDLE hBuf, IMG_UINT32 ui32Flags)
        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);
        }
 }
 
index 1523bce..709b59f 100644 (file)
@@ -67,6 +67,10 @@ extern "C" {
 
                BM_MAPPING *pMapping;
                IMG_UINT32 ui32RefCount;
+               IMG_UINTPTR_T uHashKey;
+               void *pvKernelSyncInfo;
+               void *pvPageList;
+               IMG_HANDLE hOSWrapMem;
        } BM_BUF;
 
        struct _BM_HEAP_ {
@@ -132,12 +136,17 @@ extern "C" {
                     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);
 
index 1385115..f041255 100644 (file)
@@ -217,11 +217,13 @@ PVRSRV_ERROR PVRSRVRegisterDCDeviceKM(PVRSRV_DC_SRV2DISP_KMJTABLE * psFuncTable,
 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;
 }
@@ -273,9 +275,12 @@ FoundDevice:
        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;
 }
 
@@ -344,11 +349,13 @@ PVRSRV_ERROR PVRSRVRegisterBCDeviceKM(PVRSRV_BC_SRV2BUFFER_KMJTABLE *
 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;
 }
@@ -397,9 +404,13 @@ FoundDevice:
 
        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;
 }
 
@@ -442,7 +453,9 @@ static PVRSRV_ERROR CloseDCDeviceCallBack(IMG_PVOID pvParam,
                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;
 }
@@ -716,7 +729,8 @@ static PVRSRV_ERROR DestroyDCSwapChainCallBack(IMG_PVOID pvParam,
                }
        }
 
-       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psSwapChain, IMG_NULL);
+       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN),
+                 psSwapChain, IMG_NULL);
 
        return eError;
 }
@@ -856,7 +870,8 @@ ErrorExit:
        }
 
        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;
@@ -1338,12 +1353,16 @@ static PVRSRV_ERROR CloseBCDeviceCallBack(IMG_PVOID pvParam,
                }
 
                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;
 }
@@ -1360,6 +1379,7 @@ IMG_EXPORT
        SYS_DATA *psSysData;
        IMG_UINT32 i;
        PVRSRV_ERROR eError;
+       BUFFER_INFO sBufferInfo;
 
        if (!phDeviceKM) {
                PVR_DPF((PVR_DBG_ERROR,
@@ -1405,8 +1425,6 @@ FoundDevice:
        OSMemSet(psBCPerContextInfo, 0, sizeof(*psBCPerContextInfo));
 
        if (psBCInfo->ui32RefCount++ == 0) {
-               BUFFER_INFO sBufferInfo;
-
                psDeviceNode = (PVRSRV_DEVICE_NODE *) hDevCookie;
                PVR_ASSERT(psDeviceNode != IMG_NULL);
 
@@ -1510,7 +1528,9 @@ ErrorExit:
        }
 
        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);
        }
 
index 88cc6f3..d6a2de5 100644 (file)
@@ -33,6 +33,8 @@
 #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,
@@ -306,7 +308,8 @@ static PVRSRV_ERROR AllocDeviceMem(IMG_HANDLE hDevCookie,
 
        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;
        }
 
@@ -321,8 +324,6 @@ static PVRSRV_ERROR AllocDeviceMem(IMG_HANDLE hDevCookie,
 
        psMemInfo->ui32AllocSize = ui32Size;
 
-       psMemInfo->pvSysBackupBuffer = IMG_NULL;
-
        *ppsMemInfo = psMemInfo;
 
        return (PVRSRV_OK);
@@ -340,13 +341,8 @@ static PVRSRV_ERROR FreeDeviceMem(PVRSRV_KERNEL_MEM_INFO * psMemInfo)
 
        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);
 }
@@ -391,7 +387,8 @@ IMG_EXPORT
 
                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;
        }
@@ -426,7 +423,8 @@ IMG_EXPORT
                                                   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;
 }
@@ -592,19 +590,16 @@ static PVRSRV_ERROR UnwrapExtMemoryCallBack(IMG_PVOID pvParam,
 {
        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) {
@@ -644,16 +639,21 @@ IMG_EXPORT
        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);
 
@@ -666,8 +666,9 @@ IMG_EXPORT
                        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,
@@ -675,17 +676,34 @@ IMG_EXPORT
                        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) {
@@ -704,18 +722,34 @@ IMG_EXPORT
                           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;
 
@@ -723,21 +757,33 @@ IMG_EXPORT
        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;
 
@@ -748,13 +794,13 @@ ErrorExitPhase2:
                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;
@@ -778,11 +824,6 @@ static PVRSRV_ERROR UnmapDeviceMemoryCallBack(IMG_PVOID pvParam,
 
        PVR_UNREFERENCED_PARAMETER(ui32Param);
 
-       if (psMemInfo->sMemBlk.psIntSysPAddr) {
-               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0,
-                         psMemInfo->sMemBlk.psIntSysPAddr, IMG_NULL);
-       }
-
        return FreeDeviceMem(psMemInfo);
 }
 
@@ -874,6 +915,7 @@ IMG_EXPORT
                           ui32PageOffset,
                           IMG_FALSE,
                           psSysPAddr,
+                          IMG_TRUE,
                           pvPageAlignedCPUVAddr,
                           &psMemInfo->ui32Flags, &hBuffer);
 
@@ -889,16 +931,12 @@ IMG_EXPORT
 
        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,
@@ -912,12 +950,15 @@ ErrorExit:
 
        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;
@@ -991,8 +1032,8 @@ PVRSRVMapDeviceClassMemoryKM(PVRSRV_PER_PROCESS_DATA * psPerProc,
        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 =
@@ -1015,13 +1056,15 @@ PVRSRVMapDeviceClassMemoryKM(PVRSRV_PER_PROCESS_DATA * psPerProc,
                           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;
        }
 
@@ -1036,8 +1079,6 @@ PVRSRVMapDeviceClassMemoryKM(PVRSRV_PER_PROCESS_DATA * psPerProc,
        psMemInfo->ui32AllocSize = ui32ByteSize;
        psMemInfo->psKernelSyncInfo = psDeviceClassBuffer->psKernelSyncInfo;
 
-       psMemInfo->pvSysBackupBuffer = IMG_NULL;
-
        psMemInfo->sMemBlk.hResItem =
            ResManRegisterRes(psPerProc->hResManContext,
                              RESMAN_TYPE_DEVICECLASSMEM_MAPPING, psMemInfo, 0,
index ecfaa59..a535a0f 100644 (file)
@@ -29,6 +29,7 @@
 
 #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
@@ -46,7 +47,11 @@ typedef struct _ENV_DATA_TAG {
        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
index 61bcc5a..cb152c3 100644 (file)
@@ -69,7 +69,7 @@ typedef struct PVRSRV_LINUX_EVENT_OBJECT_LIST_TAG {
 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;
@@ -126,7 +126,7 @@ PVRSRV_ERROR LinuxEventObjectDelete(IMG_HANDLE hOSEventObjectList,
                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));
@@ -154,7 +154,7 @@ static PVRSRV_ERROR LinuxEventObjectDeleteCallback(IMG_PVOID pvParam,
        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));
@@ -196,7 +196,7 @@ PVRSRV_ERROR LinuxEventObjectAdd(IMG_HANDLE hOSEventObjectList,
        atomic_set(&psLinuxEventObject->sTimeStamp, 0);
        psLinuxEventObject->ui32TimeStampPrevious = 0;
 
-#if DEBUG
+#ifdef DEBUG
        psLinuxEventObject->ui32Stats = 0;
 #endif
        init_waitqueue_head(&psLinuxEventObject->sWait);
@@ -261,7 +261,7 @@ PVRSRV_ERROR LinuxEventObjectWait(IMG_HANDLE hOSEventObject,
 
                ui32TimeOutJiffies = schedule_timeout(ui32TimeOutJiffies);
 
-#if DEBUG
+#ifdef DEBUG
                psLinuxEventObject->ui32Stats++;
 #endif
                LinuxLockMutex(&gPVRSRVLock);
index 92acdeb..3058f2c 100644 (file)
@@ -166,7 +166,8 @@ static IMG_BOOL _Resize(HASH_TABLE * pHash, IMG_UINT32 uNewSize)
                        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;
@@ -224,7 +225,8 @@ IMG_VOID HASH_Delete(HASH_TABLE * pHash)
                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);
index 8c5b2e5..09c9431 100644 (file)
@@ -53,7 +53,6 @@
 #include "pvr_debug.h"
 #include "osfunc.h"
 #include "proc.h"
-#include "mutex.h"
 
 static PKV_OFFSET_STRUCT FindOffsetStructFromLinuxMemArea(LinuxMemArea *
                                                          psLinuxMemArea);
@@ -70,6 +69,7 @@ static PKV_OFFSET_STRUCT FindOffsetStructByMMapOffset(IMG_UINT32 ui32Offset);
 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);
@@ -83,8 +83,6 @@ open: MMapVOpen,
 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)
@@ -92,6 +90,8 @@ static IMG_UINT32 g_ui32RegisteredAreas = 0;
 static IMG_UINT32 g_ui32TotalByteSize = 0;
 #endif
 
+static struct rw_semaphore g_mmap_sem;
+
 IMG_VOID PVRMMapInit(IMG_VOID)
 {
        g_psKVOffsetTable = 0;
@@ -106,6 +106,7 @@ IMG_VOID PVRMMapInit(IMG_VOID)
                PVR_DPF((PVR_DBG_ERROR, "%s: failed to allocate kmem_cache",
                         __FUNCTION__));
        }
+       init_rwsem(&g_mmap_sem);
 }
 
 IMG_VOID PVRMMapCleanup(void)
@@ -143,24 +144,27 @@ PVRMMapRegisterArea(const IMG_CHAR * pszName,
                    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();
@@ -195,14 +199,17 @@ PVRMMapRegisterArea(const IMG_CHAR * pszName,
        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) {
@@ -215,7 +222,8 @@ PVRSRV_ERROR PVRMMapRemoveRegisteredArea(LinuxMemArea * psLinuxMemArea)
                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)
 
@@ -223,7 +231,8 @@ PVRSRV_ERROR PVRMMapRemoveRegisteredArea(LinuxMemArea * psLinuxMemArea)
                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--;
@@ -243,7 +252,9 @@ PVRSRV_ERROR PVRMMapRemoveRegisteredArea(LinuxMemArea * psLinuxMemArea)
 
        KMemCacheFreeWrapper(g_psMemmapCache, psOffsetStruct);
 
-       return PVRSRV_OK;
+unregister_exit:
+       up_write(&g_mmap_sem);
+       return iError;
 }
 
 static PKV_OFFSET_STRUCT
@@ -291,11 +302,14 @@ PVRMMapKVIndexAddressToMMapData(IMG_VOID * pvKVIndexAddress,
                                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;
@@ -304,7 +318,9 @@ PVRMMapKVIndexAddressToMMapData(IMG_VOID * pvKVIndexAddress,
                                       psOffsetStruct->psLinuxMemArea,
                                       pui32RealByteSize, pui32ByteOffset);
 
-       return PVRSRV_OK;
+indexaddress_exit:
+       up_read(&g_mmap_sem);
+       return iError;
 }
 
 static PKV_OFFSET_STRUCT
@@ -398,10 +414,8 @@ int PVRMMap(struct file *pFile, struct vm_area_struct *ps_vma)
        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__,
@@ -412,7 +426,7 @@ int PVRMMap(struct file *pFile, struct vm_area_struct *ps_vma)
                PVR_DPF((PVR_DBG_ERROR,
                         "PVRMMap: Error - Cannot mmap non-shareable writable areas."));
                iRetVal = -EINVAL;
-               goto unlock_and_return;
+               goto pvrmmap_exit;
        }
 
        psCurrentRec =
@@ -422,10 +436,14 @@ int PVRMMap(struct file *pFile, struct vm_area_struct *ps_vma)
                         "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;
@@ -476,7 +494,7 @@ int PVRMMap(struct file *pFile, struct vm_area_struct *ps_vma)
 
        if (!DoMapToUser(psCurrentRec->psLinuxMemArea, ps_vma, 0, ulBytes)) {
                iRetVal = -EAGAIN;
-               goto unlock_and_return;
+               goto pvrmmap_exit;
        }
 
        MMapVOpen(ps_vma);
@@ -484,10 +502,8 @@ int PVRMMap(struct file *pFile, struct vm_area_struct *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;
 }
 
@@ -565,6 +581,30 @@ DoMapToUser(LinuxMemArea * psLinuxMemArea,
        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)
@@ -613,8 +653,7 @@ static off_t PrintMMapRegistrations(char *buffer, size_t size, off_t off)
        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)
@@ -682,8 +721,7 @@ static off_t PrintMMapRegistrations(char *buffer, size_t size, off_t off)
                          HAPFlagsToString(psOffsetStruct->ui32AllocFlags));
 
 unlock_and_return:
-
-       LinuxUnLockMutex(&gPVRSRVLock);
+       up_read(&g_mmap_sem);
        return Ret;
 }
 #endif
index 17c4a1f..5b638b1 100644 (file)
--- a/pvr/mmu.c
+++ b/pvr/mmu.c
@@ -1171,7 +1171,8 @@ MMU_HEAP *MMU_Create(MMU_CONTEXT * psMMUContext,
        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;
        }
 
@@ -1187,7 +1188,8 @@ MMU_HEAP *MMU_Create(MMU_CONTEXT * psMMUContext,
                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
@@ -1234,7 +1236,8 @@ IMG_VOID MMU_Delete(MMU_HEAP * pMMUHeap)
                DisableHostAccess(pMMUHeap->psMMUContext);
 #endif
 
-               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, pMMUHeap, IMG_NULL);
+               OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(MMU_HEAP),
+                         pMMUHeap, IMG_NULL);
        }
 }
 
index 2084705..ae6e03b 100644 (file)
@@ -90,8 +90,8 @@ EXPORT_SYMBOL(PVRGetBufferClassJTable);
 
 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);
 
@@ -99,7 +99,7 @@ PVRSRV_LINUX_MUTEX gPVRSRVLock;
 
 static struct file_operations pvrsrv_fops = {
 owner: THIS_MODULE,
-ioctl: PVRSRV_BridgeDispatchKM,
+unlocked_ioctl:PVRSRV_BridgeDispatchKM,
 open:  PVRSRVOpen,
 release:PVRSRVRelease,
 mmap:  PVRMMap,
@@ -192,6 +192,8 @@ static int __devinit PVRSRVDriverProbe(LDM_DEV * pDevice,
 
        PVR_TRACE(("PVRSRVDriverProbe(pDevice=%p)", pDevice));
 
+       pDevice->dev.driver_data = NULL;
+
 #if 0
 
        if (PerDeviceSysInitialise((IMG_PVOID) pDevice) != PVRSRV_OK) {
@@ -415,6 +417,8 @@ static int __init PVRCore_Init(void)
                goto init_failed;
        }
 
+       powervr_device.dev.devt = MKDEV(AssignedMajorNumber, 0);
+
        if ((error = platform_device_register(&powervr_device)) != 0) {
                platform_driver_unregister(&powervr_driver);
 
diff --git a/pvr/modules.order b/pvr/modules.order
deleted file mode 100644 (file)
index 33eed37..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-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
index d10cdd7..43241bb 100644 (file)
@@ -159,7 +159,7 @@ typedef struct OMAPLFB_DEVINFO_TAG {
 
        IMG_BOOL bDeviceSuspended;
 
-       spinlock_t *psSwapChainLock;
+       spinlock_t SwapChainLock;
 } OMAPLFB_DEVINFO;
 
 #define        OMAPLFB_PAGE_SIZE 4096
@@ -196,13 +196,8 @@ PVRSRV_ERROR OMAPLFBUninstallVSyncISR(OMAPLFB_SWAPCHAIN * psSwapChain);
 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
index 55e6f81..5e3d6d9 100644 (file)
@@ -140,11 +140,11 @@ static IMG_VOID SetFlushStateInternal(OMAPLFB_DEVINFO * psDevInfo,
 {
        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,
@@ -152,14 +152,14 @@ 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)
@@ -219,40 +219,15 @@ static PVRSRV_ERROR UnblankDisplay(OMAPLFB_DEVINFO * psDevInfo)
        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;
@@ -555,7 +530,7 @@ static PVRSRV_ERROR CreateDCSwapChain(IMG_HANDLE hDevice,
        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];
@@ -581,7 +556,7 @@ static PVRSRV_ERROR CreateDCSwapChain(IMG_HANDLE hDevice,
                psVSyncFlips[i].bFlipped = IMG_FALSE;
                psVSyncFlips[i].bCmdCompleted = IMG_FALSE;
        }
-#if defined (SUPPORT_TI_DSS_FW)
+
        OMAPLFBEnableDisplayRegisterAccess();
 
        psSwapChain->pvRegs =
@@ -592,14 +567,14 @@ static PVRSRV_ERROR CreateDCSwapChain(IMG_HANDLE hDevice,
                       ": 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;
 
@@ -612,7 +587,7 @@ static PVRSRV_ERROR CreateDCSwapChain(IMG_HANDLE hDevice,
                OMAPLFBEnableVSyncInterrupt(psSwapChain);
        }
 
-       spin_unlock_irqrestore(psDevInfo->psSwapChainLock, ulLockFlags);
+       spin_unlock_irqrestore(&psDevInfo->SwapChainLock, ulLockFlags);
 
        eError = EnableLFBEventNotification(psDevInfo);
        if (eError != PVRSRV_OK) {
@@ -631,11 +606,9 @@ ErrorUninstallVSyncInterrupt:
                       ": Couldn't uninstall VSync ISR\n");
        }
 ErrorUnmapRegisters:
-#if defined (SUPPORT_TI_DSS_FW)
        iounmap(psSwapChain->pvRegs);
 ErrorDisableDisplayRegisters:
        OMAPLFBDisableDisplayRegisterAccess();
-#endif
        OMAPLFBFreeKernelMem(psVSyncFlips);
 ErrorFreeBuffers:
        OMAPLFBFreeKernelMem(psBuffer);
@@ -669,7 +642,7 @@ static PVRSRV_ERROR DestroyDCSwapChain(IMG_HANDLE hDevice,
                       ": Couldn't disable framebuffer event notification\n");
        }
 
-       spin_lock_irqsave(psDevInfo->psSwapChainLock, ulLockFlags);
+       spin_lock_irqsave(&psDevInfo->SwapChainLock, ulLockFlags);
 
        OMAPLFBDisableVSyncInterrupt(psSwapChain);
 
@@ -679,19 +652,17 @@ static PVRSRV_ERROR DestroyDCSwapChain(IMG_HANDLE hDevice,
 
        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);
@@ -810,13 +781,13 @@ static PVRSRV_ERROR SwapToDCSystem(IMG_HANDLE hDevice, IMG_HANDLE hSwapChain)
                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;
 }
@@ -885,6 +856,7 @@ IMG_BOOL OMAPLFBVSyncIHandler(OMAPLFB_SWAPCHAIN * psSwapChain)
 
 ExitUnlock:
        spin_unlock_irqrestore(psSwapChain->psSwapChainLock, ulLockFlags);
+
        return bStatus;
 }
 
@@ -916,7 +888,7 @@ static IMG_BOOL ProcessFlip(IMG_HANDLE hCmdCookie,
        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,
@@ -965,54 +937,21 @@ static IMG_BOOL ProcessFlip(IMG_HANDLE 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
@@ -1045,7 +984,8 @@ static PVRSRV_ERROR InitDev(OMAPLFB_DEVINFO * psDevInfo)
        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);
@@ -1058,48 +998,96 @@ static PVRSRV_ERROR InitDev(OMAPLFB_DEVINFO * psDevInfo)
                    (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;
@@ -1170,19 +1158,15 @@ PVRSRV_ERROR OMAPLFBInit(IMG_VOID)
                        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;
@@ -1195,24 +1179,10 @@ PVRSRV_ERROR OMAPLFBInit(IMG_VOID)
                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;
@@ -1310,7 +1280,7 @@ IMG_VOID OMAPLFBDriverSuspend(IMG_VOID)
        OMAPLFB_DEVINFO *psDevInfo = GetAnchorPtr();
        unsigned long ulLockFlags;
 
-       spin_lock_irqsave(psDevInfo->psSwapChainLock, ulLockFlags);
+       spin_lock_irqsave(&psDevInfo->SwapChainLock, ulLockFlags);
 
        if (psDevInfo->bDeviceSuspended) {
                goto ExitUnlock;
@@ -1319,17 +1289,16 @@ IMG_VOID OMAPLFBDriverSuspend(IMG_VOID)
 
        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)
@@ -1340,17 +1309,17 @@ 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
index fa96a19..5d4ddd8 100644 (file)
 #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)
@@ -88,157 +87,77 @@ PVRSRV_ERROR OMAPLFBGetLibFuncAddr(IMG_CHAR * szFunctionName,
        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)
 
index 8370e1a..68b441d 100644 (file)
@@ -67,6 +67,8 @@ extern PVRSRV_LINUX_MUTEX gPVRSRVLock;
 #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)
@@ -76,35 +78,40 @@ PVRSRV_ERROR _OSAllocMem(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size,
                         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;
@@ -120,9 +127,8 @@ PVRSRV_ERROR _OSFreeMem(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size,
 #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
@@ -415,6 +421,8 @@ PVRSRV_ERROR OSInitEnvData(IMG_PVOID * ppvEnvSpecificData)
                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,
@@ -439,8 +447,9 @@ PVRSRV_ERROR OSDeInitEnvData(IMG_PVOID pvEnvSpecificData)
        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);
@@ -519,7 +528,7 @@ static irqreturn_t DeviceISRWrapper(int irq, void *dev_id
                SYS_DATA *psSysData = psDeviceNode->psSysData;
                ENV_DATA *psEnvData = (ENV_DATA *) psSysData->pvEnvSpecificData;
 
-               tasklet_schedule(&psEnvData->sMISRTasklet);
+               queue_work(psEnvData->psMISRWorkqueue, &psEnvData->sMISRWork);
        }
 
 out:
@@ -551,7 +560,7 @@ static irqreturn_t SystemISRWrapper(int irq, void *dev_id
        if (bStatus) {
                ENV_DATA *psEnvData = (ENV_DATA *) psSysData->pvEnvSpecificData;
 
-               tasklet_schedule(&psEnvData->sMISRTasklet);
+               queue_work(psEnvData->psMISRWorkqueue, &psEnvData->sMISRWork);
        }
 
 out:
@@ -676,12 +685,10 @@ PVRSRV_ERROR OSUninstallSystemLISR(IMG_VOID * pvSysData)
        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);
 }
 
@@ -698,8 +705,9 @@ PVRSRV_ERROR OSInstallMISR(IMG_VOID * pvSysData)
 
        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;
 
@@ -719,7 +727,8 @@ PVRSRV_ERROR OSUninstallMISR(IMG_VOID * pvSysData)
 
        PVR_TRACE(("Uninstalling MISR"));
 
-       tasklet_kill(&psEnvData->sMISRTasklet);
+       flush_workqueue(psEnvData->psMISRWorkqueue);
+       destroy_workqueue(psEnvData->psMISRWorkqueue);
 
        psEnvData->bMISRInstalled = IMG_FALSE;
 
@@ -732,7 +741,7 @@ PVRSRV_ERROR OSScheduleMISR(IMG_VOID * pvSysData)
        ENV_DATA *psEnvData = (ENV_DATA *) psSysData->pvEnvSpecificData;
 
        if (psEnvData->bMISRInstalled) {
-               tasklet_schedule(&psEnvData->sMISRTasklet);
+               queue_work(psEnvData->psMISRWorkqueue, &psEnvData->sMISRWork);
        }
 
        return PVRSRV_OK;
index f8b91e9..c0fbd69 100644 (file)
@@ -67,6 +67,8 @@ extern "C" {
        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);
index 00a7957..2b016ee 100644 (file)
  * 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
@@ -85,53 +91,43 @@ static IMG_BOOL _IsSystemStatePowered(PVR_POWER_STATE eSystemPowerState)
        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
@@ -170,6 +166,9 @@ PVRSRV_ERROR PVRSRVDevicePrePowerStateKM(IMG_BOOL bAllDevices,
                                                        psPowerDevice->
                                                        eCurrentPowerState);
                                        if (eError != PVRSRV_OK) {
+                                               pr_err
+                                                   ("pfnPrePower failed (%u)\n",
+                                                    eError);
                                                return eError;
                                        }
                                }
@@ -181,6 +180,9 @@ PVRSRV_ERROR PVRSRVDevicePrePowerStateKM(IMG_BOOL bAllDevices,
                                                           psPowerDevice->
                                                           eCurrentPowerState);
                                if (eError != PVRSRV_OK) {
+                                       pr_err
+                                           ("SysDevicePrePowerState failed (%u)\n",
+                                            eError);
                                        return eError;
                                }
                        }
@@ -226,6 +228,9 @@ PVRSRV_ERROR PVRSRVDevicePostPowerStateKM(IMG_BOOL bAllDevices,
                                                            psPowerDevice->
                                                            eCurrentPowerState);
                                if (eError != PVRSRV_OK) {
+                                       pr_err
+                                           ("SysDevicePostPowerState failed (%u)\n",
+                                            eError);
                                        return eError;
                                }
 
@@ -239,6 +244,9 @@ PVRSRV_ERROR PVRSRVDevicePostPowerStateKM(IMG_BOOL bAllDevices,
                                                         psPowerDevice->
                                                         eCurrentPowerState);
                                        if (eError != PVRSRV_OK) {
+                                               pr_err
+                                                   ("pfnPostPower failed (%u)\n",
+                                                    eError);
                                                return eError;
                                        }
                                }
@@ -254,23 +262,6 @@ PVRSRV_ERROR PVRSRVDevicePostPowerStateKM(IMG_BOOL bAllDevices,
        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,
@@ -537,7 +528,8 @@ PVRSRV_ERROR PVRSRVRemovePowerDevice(IMG_UINT32 ui32DeviceIndex)
                                    psCurrent->psNext;
                        }
 
-                       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, 0, psCurrent,
+                       OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+                                 sizeof(PVRSRV_POWER_DEV), psCurrent,
                                  IMG_NULL);
 
                        break;
@@ -580,11 +572,11 @@ IMG_EXPORT IMG_BOOL PVRSRVIsDevicePowered(IMG_UINT32 ui32DeviceIndex)
        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;
 
@@ -600,8 +592,12 @@ IMG_VOID PVRSRVDevicePreClockSpeedChange(IMG_UINT32 ui32DeviceIndex,
                                    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));
@@ -611,13 +607,14 @@ IMG_VOID PVRSRVDevicePreClockSpeedChange(IMG_UINT32 ui32DeviceIndex,
 
                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;
 
@@ -633,8 +630,12 @@ IMG_VOID PVRSRVDevicePostClockSpeedChange(IMG_UINT32 ui32DeviceIndex,
                                    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));
index a3fefd9..20270b2 100644 (file)
@@ -67,6 +67,10 @@ extern "C" {
                                         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
@@ -103,9 +107,10 @@ extern "C" {
         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
index abbe9c7..1168999 100644 (file)
@@ -82,7 +82,8 @@ extern "C" {
 #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)
@@ -320,6 +321,17 @@ extern "C" {
 
        } 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;
index bf668fb..1037cd7 100644 (file)
@@ -127,9 +127,8 @@ unlock_and_return:
 }
 #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 =
index 50e39e7..4539b44 100644 (file)
@@ -260,7 +260,7 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVRegisterDevice(PSYS_DATA psSysData,
        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);
@@ -495,7 +495,8 @@ FoundDevice:
        *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);
 }
index 9bb8360..c49cb4e 100644 (file)
@@ -783,6 +783,10 @@ IMG_EXPORT
                         "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++) {
 
@@ -815,6 +819,7 @@ IMG_EXPORT
                psCmdCompleteData->psSrcSync = (PVRSRV_SYNC_OBJECT *)
                    (((IMG_UINT32) psCmdCompleteData->psDstSync)
                     + (sizeof(PVRSRV_SYNC_OBJECT) * ui32MaxSyncsPerCmd[i][0]));
+               psCmdCompleteData->ui32AllocSize = ui32AllocSize;
        }
 
        return PVRSRV_OK;
@@ -825,20 +830,24 @@ ErrorExit:
                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);
        }
 
@@ -872,20 +881,24 @@ IMG_EXPORT
 
                        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);
        }
 
index 687b36b..a380a9f 100644 (file)
@@ -42,6 +42,7 @@ extern "C" {
                IMG_UINT32 ui32SrcSyncCount;
                PVRSRV_SYNC_OBJECT *psDstSync;
                PVRSRV_SYNC_OBJECT *psSrcSync;
+               IMG_UINT32 ui32AllocSize;
        } COMMAND_COMPLETE_DATA, *PCOMMAND_COMPLETE_DATA;
 
 #if !defined(USE_CODE)
index e7253bf..e6e5850 100644 (file)
--- a/pvr/ra.c
+++ b/pvr/ra.c
@@ -676,7 +676,7 @@ RA_ARENA *RA_Create(IMG_CHAR * name,
 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;
 }
@@ -705,7 +705,7 @@ void RA_Delete(RA_ARENA * pArena)
        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)
index d503b0e..e6fc1f8 100644 (file)
@@ -270,7 +270,8 @@ IMG_VOID PVRSRVResManDisconnect(PRESMAN_CONTEXT psResManContext,
                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();
 
@@ -495,8 +496,9 @@ static PVRSRV_ERROR FreeResourceByPtr(RESMAN_ITEM * psItem,
 
        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;
index 8e10c83..c151f54 100644 (file)
@@ -165,11 +165,8 @@ extern "C" {
        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;
index cd35306..1f05e4d 100644 (file)
@@ -94,8 +94,10 @@ typedef PVRSRV_ERROR(*PFN_PRE_POWER) (IMG_HANDLE, PVR_POWER_STATE,
 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,
index 8ccdd45..49269e2 100644 (file)
@@ -50,8 +50,6 @@ extern "C" {
 
                PVRSRV_MEMBLK sMemBlk;
 
-               IMG_PVOID pvSysBackupBuffer;
-
                struct _PVRSRV_KERNEL_SYNC_INFO_ *psKernelSyncInfo;
 
        } PVRSRV_KERNEL_MEM_INFO;
diff --git a/pvr/sgx2dcore.c b/pvr/sgx2dcore.c
new file mode 100644 (file)
index 0000000..fcf4dfa
--- /dev/null
@@ -0,0 +1,846 @@
+/**********************************************************************
+ *
+ * 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
index ea7ba9b..4ce6525 100644 (file)
@@ -57,9 +57,11 @@ extern "C" {
 
 #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
index 5f0d4d2..9f8da2d 100644 (file)
 #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)
@@ -90,8 +93,8 @@
 #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
index 3c413a4..0a84a86 100644 (file)
@@ -39,10 +39,12 @@ extern "C" {
 
 #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)
@@ -210,7 +212,10 @@ extern "C" {
 
                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;
@@ -241,6 +246,11 @@ extern "C" {
 
        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,
index 18bbe1f..e80e94f 100644 (file)
@@ -25,6 +25,8 @@
  ******************************************************************************/
 
 #include <stddef.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
 
 #include "sgxdefs.h"
 #include "sgxmmu.h"
@@ -59,6 +61,43 @@ static PVRSRV_ERROR SGXInitialise(PVRSRV_SGXDEV_INFO * psDevInfo,
                                  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);
@@ -173,228 +212,337 @@ failed_allockernelccb:
        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;
 }
 
@@ -514,7 +662,7 @@ static PVRSRV_ERROR SGXInitialise(PVRSRV_SGXDEV_INFO * psDevInfo,
                return (PVRSRV_ERROR_GENERIC);
        }
 
-       SGXStartTimer(psDevInfo);
+       SGXStartTimer(psDevInfo, !bHardwareRecovery);
 
        if (bHardwareRecovery) {
                PVRSRV_SGX_HOST_CTL *psSGXHostCtl =
@@ -748,8 +896,6 @@ IMG_EXPORT
        psDevInfo->s2DSlavePortKM.sPhysBase = psSGXDeviceMap->sSPSysPBase;
 #endif
 
-       SGXGetTimingInfo(psDevInfo, &psSGXDeviceMap->sTimingInfo);
-
 #if defined (SYS_USING_INTERRUPTS)
 
        psDeviceNode->pvISRData = psDeviceNode;
@@ -767,7 +913,8 @@ IMG_EXPORT
        eDefaultPowerState = PVRSRV_POWER_STATE_D0;
 #endif
        eError = PVRSRVRegisterPowerDevice(psDeviceNode->sDevId.ui32DeviceIndex,
-                                          SGXPrePowerState, SGXPostPowerState,
+                                          SGXPrePowerStateExt,
+                                          SGXPostPowerStateExt,
                                           SGXPreClockSpeedChange,
                                           SGXPostClockSpeedChange,
                                           (IMG_HANDLE) psDeviceNode,
@@ -797,19 +944,6 @@ IMG_EXPORT
                 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:
@@ -994,6 +1128,21 @@ IMG_VOID HWRecoveryResetSGX(PVRSRV_DEVICE_NODE * psDeviceNode,
 }
 #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)
 {
@@ -1046,7 +1195,14 @@ 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
@@ -1094,9 +1250,6 @@ IMG_BOOL SGX_ISRHandler(IMG_VOID * pvData)
 
                        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);
                }
        }
 
@@ -1384,6 +1537,20 @@ PVRSRV_ERROR SGXRegisterDevice(PVRSRV_DEVICE_NODE * psDeviceNode)
        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 =
index 6a6fa74..3ef2dc4 100644 (file)
@@ -37,6 +37,7 @@ SYS_DATA *gpsSysData = (SYS_DATA *) IMG_NULL;
 SYS_DATA gsSysData;
 
 static SYS_SPECIFIC_DATA gsSysSpecificData;
+SYS_SPECIFIC_DATA *gpsSysSpecificData;
 
 static IMG_UINT32 gui32SGXDeviceID;
 static SGX_DEVICE_MAP gsSGXDeviceMap;
@@ -167,13 +168,17 @@ PVRSRV_ERROR SysInitialise(IMG_VOID)
        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) {
@@ -205,7 +210,8 @@ PVRSRV_ERROR SysInitialise(IMG_VOID)
                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,
@@ -214,12 +220,15 @@ PVRSRV_ERROR SysInitialise(IMG_VOID)
                      (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) {
@@ -283,7 +292,17 @@ PVRSRV_ERROR SysInitialise(IMG_VOID)
        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)",
@@ -294,6 +313,15 @@ PVRSRV_ERROR SysInitialise(IMG_VOID)
        }
        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) {
@@ -381,6 +409,8 @@ PVRSRV_ERROR SysFinalise(IMG_VOID)
        DisableSGXClocks(gpsSysData);
 #endif
 
+       gpsSysSpecificData->bSGXInitComplete = IMG_TRUE;
+
        return eError;
 }
 
@@ -388,14 +418,11 @@ PVRSRV_ERROR SysDeinitialise(SYS_DATA * psSysData)
 {
        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,
@@ -405,7 +432,7 @@ PVRSRV_ERROR SysDeinitialise(SYS_DATA * psSysData)
        }
 
        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,
@@ -415,11 +442,19 @@ PVRSRV_ERROR SysDeinitialise(SYS_DATA * psSysData)
        }
 #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) {
@@ -438,12 +473,14 @@ PVRSRV_ERROR SysDeinitialise(SYS_DATA * psSysData)
        }
 
        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,
@@ -463,7 +500,7 @@ PVRSRV_ERROR SysDeinitialise(SYS_DATA * psSysData)
 
 #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,
@@ -472,11 +509,13 @@ PVRSRV_ERROR SysDeinitialise(SYS_DATA * psSysData)
 #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;
@@ -583,6 +622,9 @@ IMG_VOID SysClearInterrupts(SYS_DATA * psSysData, IMG_UINT32 ui32ClearBits)
        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)
@@ -633,9 +675,7 @@ PVRSRV_ERROR SysSystemPostPowerState(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)",
index 81ce9ad..2d7f474 100644 (file)
 
 #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
index c541e7a..e12406a 100644 (file)
 #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
 
@@ -46,10 +42,10 @@ extern "C" {
 
        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);
@@ -75,11 +71,10 @@ extern "C" {
 
        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;
@@ -87,19 +82,16 @@ extern "C" {
 #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
index 1d1e848..0dee22f 100644 (file)
 #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)
@@ -76,44 +66,32 @@ static inline unsigned long scale_inv_prop_to_SGX_clock(unsigned long val,
        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)
@@ -122,14 +100,23 @@ static int vdd2_post_func(struct notifier_block *n, unsigned long event,
        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;
 }
 
@@ -140,80 +127,223 @@ static int vdd2_pre_func(struct notifier_block *n, unsigned long event,
        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) {
@@ -244,6 +374,9 @@ PVRSRV_ERROR EnableSGXClocks(SYS_DATA * psSysData)
                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) {
@@ -258,27 +391,14 @@ PVRSRV_ERROR EnableSGXClocks(SYS_DATA * psSysData)
        }
        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;
 }
 
@@ -301,278 +421,282 @@ IMG_VOID DisableSGXClocks(SYS_DATA * psSysData)
        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);
 }