--- /dev/null
+From 46e3a6de5adb9379f9d6eef2c038c2f18637d407 Mon Sep 17 00:00:00 2001
+From: Loren Huang <b02279@freescale.com>
+Date: Mon, 25 Mar 2013 15:43:57 +0800
+Subject: [PATCH 1/6] ENGR00255688 4.6.9p11.1 [gpu]GPU Kernel driver
+ integration
+
+4.6.9p11.1 GPU kernel driver integration
+Cherry pick from imx_3.0.35
+
+Upstream-Status: Backport [3.5.7-1.0.0]
+
+Signed-off-by: Loren Huang <b02279@freescale.com>
+Acked-by: Lily Zhang
+---
+ drivers/mxc/gpu-viv/Kbuild | 2 +-
+ .../arch/XAQ2/hal/kernel/gc_hal_kernel_context.c | 2 +-
+ .../arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c | 7 +-
+ drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h | 2 +-
+ drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_db.c | 53 ++++--
+ .../mxc/gpu-viv/hal/kernel/gc_hal_kernel_event.c | 5 +-
+ drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu.c | 178 ++++++++++++---------
+ .../hal/kernel/gc_hal_kernel_video_memory.c | 3 +-
+ .../gpu-viv/hal/kernel/inc/gc_hal_eglplatform.h | 13 +-
+ drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine.h | 25 +++
+ .../mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h | 35 ++++
+ .../mxc/gpu-viv/hal/kernel/inc/gc_hal_version.h | 2 +-
+ .../hal/os/linux/kernel/gc_hal_kernel_driver.c | 2 +-
+ .../hal/os/linux/kernel/gc_hal_kernel_linux.h | 6 +
+ .../gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c | 82 +++++++++-
+ 15 files changed, 304 insertions(+), 113 deletions(-)
+
+diff --git a/drivers/mxc/gpu-viv/Kbuild b/drivers/mxc/gpu-viv/Kbuild
+index 0b18a7b..93b1259 100644
+--- a/drivers/mxc/gpu-viv/Kbuild
++++ b/drivers/mxc/gpu-viv/Kbuild
+@@ -1,6 +1,6 @@
+ ##############################################################################
+ #
+-# Copyright (C) 2005 - 2012 by Vivante Corp.
++# Copyright (C) 2005 - 2013 by Vivante Corp.
+ #
+ # This program is free software; you can redistribute it and/or modify
+ # it under the terms of the GNU General Public License as published by
+diff --git a/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_context.c b/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_context.c
+index 22e1f27..24003e7 100644
+--- a/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_context.c
++++ b/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_context.c
+@@ -471,7 +471,7 @@ _InitializeContextBuffer(
+ index += _SwitchPipe(Context, index, gcvPIPE_3D);
+
+ /* Current context pointer. */
+-#if gcdDEBUG
++#if gcdDEBUG
+ index += _State(Context, index, 0x03850 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
+ #endif
+
+diff --git a/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c b/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c
+index a87259e..3829999 100644
+--- a/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c
++++ b/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c
+@@ -232,7 +232,8 @@ _IdentifyHardware(
+ }
+
+ /* Exception for GC1000, revision 5035 & GC800, revision 4612 */
+- if (((Identity->chipModel == gcv1000) && (Identity->chipRevision == 0x5035))
++ if (((Identity->chipModel == gcv1000) && ((Identity->chipRevision == 0x5035)
++ || (Identity->chipRevision == 0x5036)))
+ || ((Identity->chipModel == gcv800) && (Identity->chipRevision == 0x4612)))
+ {
+ Identity->superTileMode = 1;
+@@ -751,7 +752,7 @@ gckHARDWARE_Construct(
+ /* Initialize the fast clear. */
+ gcmkONERROR(gckHARDWARE_SetFastClear(hardware, -1, -1));
+
+-#if !gcdENABLE_128B_MERGE
++#if !gcdENABLE_128B_MERGE
+
+ if (((((gctUINT32) (hardware->identity.chipMinorFeatures2)) >> (0 ? 21:21) & ((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1))))))))
+ {
+@@ -1027,7 +1028,7 @@ gckHARDWARE_InitializeHardware(
+ 0x00424,
+ baseAddress));
+
+-#if !VIVANTE_PROFILER
++#if !VIVANTE_PROFILER
+ {
+ gctUINT32 data;
+
+diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h
+index 1da80b7..5896e93 100644
+--- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h
++++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h
+@@ -186,7 +186,7 @@ typedef struct _gcsDATABASE
+ gctUINT64 idle;
+
+ /* Pointer to database. */
+- gcsDATABASE_RECORD_PTR list;
++ gcsDATABASE_RECORD_PTR list[48];
+
+ #if gcdSECURE_USER
+ /* Secure cache. */
+diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_db.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_db.c
+index 1fb18fb..bc5f083 100644
+--- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_db.c
++++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_db.c
+@@ -26,6 +26,9 @@
+ /*******************************************************************************
+ ***** Private fuctions ********************************************************/
+
++#define _GetSlot(database, x) \
++ (gctUINT32)(((gcmPTR_TO_UINT64(x) >> 7) % gcmCOUNTOF(database->list)))
++
+ /*******************************************************************************
+ ** gckKERNEL_NewDatabase
+ **
+@@ -56,6 +59,7 @@ gckKERNEL_NewDatabase(
+ gcsDATABASE_PTR database;
+ gctBOOL acquired = gcvFALSE;
+ gctSIZE_T slot;
++ gcsDATABASE_PTR existingDatabase;
+
+ gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d", Kernel, ProcessID);
+
+@@ -63,6 +67,21 @@ gckKERNEL_NewDatabase(
+ gcmkONERROR(gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
++ /* Compute the hash for the database. */
++ slot = ProcessID % gcmCOUNTOF(Kernel->db->db);
++
++ /* Walk the hash list. */
++ for (existingDatabase = Kernel->db->db[slot];
++ existingDatabase != gcvNULL;
++ existingDatabase = existingDatabase->next)
++ {
++ if (existingDatabase->processID == ProcessID)
++ {
++ /* One process can't be added twice. */
++ gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
++ }
++ }
++
+ if (Kernel->db->freeDatabase != gcvNULL)
+ {
+ /* Allocate a database from the free list. */
+@@ -81,9 +100,6 @@ gckKERNEL_NewDatabase(
+ database = pointer;
+ }
+
+- /* Compute the hash for the database. */
+- slot = ProcessID % gcmCOUNTOF(Kernel->db->db);
+-
+ /* Insert the database into the hash. */
+ database->next = Kernel->db->db[slot];
+ Kernel->db->db[slot] = database;
+@@ -350,6 +366,7 @@ static gceSTATUS
+ gckKERNEL_NewRecord(
+ IN gckKERNEL Kernel,
+ IN gcsDATABASE_PTR Database,
++ IN gctUINT32 Slot,
+ OUT gcsDATABASE_RECORD_PTR * Record
+ )
+ {
+@@ -383,8 +400,8 @@ gckKERNEL_NewRecord(
+ }
+
+ /* Insert the record in the database. */
+- record->next = Database->list;
+- Database->list = record;
++ record->next = Database->list[Slot];
++ Database->list[Slot] = record;
+
+ /* Release the database mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
+@@ -449,6 +466,7 @@ gckKERNEL_DeleteRecord(
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+ gcsDATABASE_RECORD_PTR record, previous;
++ gctUINT32 slot = _GetSlot(Database, Data);
+
+ gcmkHEADER_ARG("Kernel=0x%x Database=0x%x Type=%d Data=0x%x",
+ Kernel, Database, Type, Data);
+@@ -458,8 +476,9 @@ gckKERNEL_DeleteRecord(
+ gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
++
+ /* Scan the database for this record. */
+- for (record = Database->list, previous = gcvNULL;
++ for (record = Database->list[slot], previous = gcvNULL;
+ record != gcvNULL;
+ record = record->next
+ )
+@@ -490,7 +509,7 @@ gckKERNEL_DeleteRecord(
+ /* Remove record from database. */
+ if (previous == gcvNULL)
+ {
+- Database->list = record->next;
++ Database->list[slot] = record->next;
+ }
+ else
+ {
+@@ -557,6 +576,7 @@ gckKERNEL_FindRecord(
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+ gcsDATABASE_RECORD_PTR record;
++ gctUINT32 slot = _GetSlot(Database, Data);
+
+ gcmkHEADER_ARG("Kernel=0x%x Database=0x%x Type=%d Data=0x%x",
+ Kernel, Database, Type, Data);
+@@ -567,7 +587,7 @@ gckKERNEL_FindRecord(
+ acquired = gcvTRUE;
+
+ /* Scan the database for this record. */
+- for (record = Database->list;
++ for (record = Database->list[slot];
+ record != gcvNULL;
+ record = record->next
+ )
+@@ -642,6 +662,7 @@ gckKERNEL_CreateProcessDB(
+ {
+ gceSTATUS status;
+ gcsDATABASE_PTR database = gcvNULL;
++ gctUINT32 i;
+
+ gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d", Kernel, ProcessID);
+
+@@ -668,7 +689,11 @@ gckKERNEL_CreateProcessDB(
+ database->mapUserMemory.bytes = 0;
+ database->mapUserMemory.maxBytes = 0;
+ database->mapUserMemory.totalBytes = 0;
+- database->list = gcvNULL;
++
++ for (i = 0; i < gcmCOUNTOF(database->list); i++)
++ {
++ database->list[i] = gcvNULL;
++ }
+
+ #if gcdSECURE_USER
+ {
+@@ -848,7 +873,7 @@ gckKERNEL_AddProcessDB(
+ gcmkONERROR(gckKERNEL_FindDatabase(Kernel, ProcessID, gcvFALSE, &database));
+
+ /* Create a new record in the database. */
+- gcmkONERROR(gckKERNEL_NewRecord(Kernel, database, &record));
++ gcmkONERROR(gckKERNEL_NewRecord(Kernel, database, _GetSlot(database, Pointer), &record));
+
+ /* Initialize the record. */
+ record->kernel = Kernel;
+@@ -1086,6 +1111,7 @@ gckKERNEL_DestroyProcessDB(
+ gctPHYS_ADDR physical;
+ gcuVIDMEM_NODE_PTR node;
+ gckKERNEL kernel = Kernel;
++ gctUINT32 i;
+
+ gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d", Kernel, ProcessID);
+
+@@ -1126,8 +1152,11 @@ gckKERNEL_DestroyProcessDB(
+ ProcessID);
+ }
+
++ for(i = 0; i < gcmCOUNTOF(database->list); i++)
++ {
++
+ /* Walk all records. */
+- for (record = database->list; record != gcvNULL; record = next)
++ for (record = database->list[i]; record != gcvNULL; record = next)
+ {
+ /* Next next record. */
+ next = record->next;
+@@ -1293,6 +1322,8 @@ gckKERNEL_DestroyProcessDB(
+ gcvNULL));
+ }
+
++ }
++
+ /* Delete the database. */
+ gcmkONERROR(gckKERNEL_DeleteDatabase(Kernel, database));
+
+diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_event.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_event.c
+index f78d096..217f7f1 100644
+--- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_event.c
++++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_event.c
+@@ -959,6 +959,8 @@ gckEVENT_AddList(
+ record->kernel = Event->kernel;
+ #endif
+
++ gcmkONERROR(__RemoveRecordFromProcessDB(Event, record));
++
+ /* Acquire the mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Event->os, Event->eventListMutex, gcvINFINITE));
+ acquired = gcvTRUE;
+@@ -1539,9 +1541,6 @@ gckEVENT_Submit(
+ gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->eventListMutex));
+ acquired = gcvFALSE;
+
+- gcmkONERROR(__RemoveRecordFromProcessDB(Event,
+- Event->queues[id].head));
+-
+ #if gcdNULL_DRIVER
+ /* Notify immediately on infinite hardware. */
+ gcmkONERROR(gckEVENT_Interrupt(Event, 1 << id));
+diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu.c
+index 0c71e28..43c9297 100644
+--- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu.c
++++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu.c
+@@ -97,6 +97,43 @@ static gcsMirrorPageTable_PTR mirrorPageTable = gcvNULL;
+ static gctPOINTER mirrorPageTableMutex = gcvNULL;
+ #endif
+
++static void
++_WritePageEntry(
++ IN gctUINT32_PTR PageEntry,
++ IN gctUINT32 EntryValue
++ )
++{
++ static gctUINT16 data = 0xff00;
++
++ if (*(gctUINT8 *)&data == 0xff)
++ {
++ *PageEntry = gcmSWAB32(EntryValue);
++ }
++ else
++ {
++ *PageEntry = EntryValue;
++ }
++}
++
++static gctUINT32
++_ReadPageEntry(
++ IN gctUINT32_PTR PageEntry
++ )
++{
++ static gctUINT16 data = 0xff00;
++ gctUINT32 entryValue;
++
++ if (*(gctUINT8 *)&data == 0xff)
++ {
++ entryValue = *PageEntry;
++ return gcmSWAB32(entryValue);
++ }
++ else
++ {
++ return *PageEntry;
++ }
++}
++
+ static gceSTATUS
+ _FillPageTable(
+ IN gctUINT32_PTR PageTable,
+@@ -108,7 +145,7 @@ _FillPageTable(
+
+ for (i = 0; i < PageCount; i++)
+ {
+- PageTable[i] = EntryValue;
++ _WritePageEntry(PageTable + i, EntryValue);
+ }
+
+ return gcvSTATUS_OK;
+@@ -132,16 +169,16 @@ _Link(
+ gctUINT32_PTR pageTable = Mmu->pageTableLogical;
+
+ /* Dispatch on node type. */
+- switch (gcmENTRY_TYPE(pageTable[Index]))
++ switch (gcmENTRY_TYPE(_ReadPageEntry(&pageTable[Index])))
+ {
+ case gcvMMU_SINGLE:
+ /* Set single index. */
+- pageTable[Index] = (Next << 8) | gcvMMU_SINGLE;
++ _WritePageEntry(&pageTable[Index], (Next << 8) | gcvMMU_SINGLE);
+ break;
+
+ case gcvMMU_FREE:
+ /* Set index. */
+- pageTable[Index + 1] = Next;
++ _WritePageEntry(&pageTable[Index + 1], Next);
+ break;
+
+ default:
+@@ -167,13 +204,13 @@ _AddFree(
+ if (Count == 1)
+ {
+ /* Initialize a single page node. */
+- pageTable[Node] = (~((1U<<8)-1)) | gcvMMU_SINGLE;
++ _WritePageEntry(pageTable + Node, (~((1U<<8)-1)) | gcvMMU_SINGLE);
+ }
+ else
+ {
+ /* Initialize the node. */
+- pageTable[Node + 0] = (Count << 8) | gcvMMU_FREE;
+- pageTable[Node + 1] = ~0U;
++ _WritePageEntry(pageTable + Node + 0, (Count << 8) | gcvMMU_FREE);
++ _WritePageEntry(pageTable + Node + 1, ~0U);
+ }
+
+ /* Append the node. */
+@@ -196,7 +233,7 @@ _Collect(
+ for (i = 0; i < Mmu->pageTableEntries; ++i)
+ {
+ /* Dispatch based on type of page. */
+- switch (gcmENTRY_TYPE(pageTable[i]))
++ switch (gcmENTRY_TYPE(_ReadPageEntry(&pageTable[i])))
+ {
+ case gcvMMU_USED:
+ /* Used page, so close any open node. */
+@@ -229,10 +266,10 @@ _Collect(
+ }
+
+ /* Advance the count. */
+- count += pageTable[i] >> 8;
++ count += _ReadPageEntry(&pageTable[i]) >> 8;
+
+ /* Advance the index into the page table. */
+- i += (pageTable[i] >> 8) - 1;
++ i += (_ReadPageEntry(&pageTable[i]) >> 8) - 1;
+ break;
+
+ default:
+@@ -341,19 +378,20 @@ _FillFlatMapping(
+ gcmkONERROR(gcvSTATUS_NOT_ALIGNED);
+ }
+
+- *(Mmu->mtlbLogical + mStart)
+- = stlb->physBase
+- /* 64KB page size */
+- | (1 << 2)
+- /* Ignore exception */
+- | (0 << 1)
+- /* Present */
+- | (1 << 0);
++ _WritePageEntry(Mmu->mtlbLogical + mStart,
++ stlb->physBase
++ /* 64KB page size */
++ | (1 << 2)
++ /* Ignore exception */
++ | (0 << 1)
++ /* Present */
++ | (1 << 0)
++ );
+ #if gcdMMU_TABLE_DUMP
+ gckOS_Print("%s(%d): insert MTLB[%d]: %08x\n",
+ __FUNCTION__, __LINE__,
+ mStart,
+- *(Mmu->mtlbLogical + mStart));
++ _ReadPageEntry(Mmu->mtlbLogical + mStart));
+ #endif
+
+ stlb->mtlbIndex = mStart;
+@@ -368,12 +406,12 @@ _FillFlatMapping(
+ while (sStart <= last)
+ {
+ gcmkASSERT(!(start & gcdMMU_PAGE_64K_MASK));
+- *(stlb->logical + sStart) = _SetPage(start);
++ _WritePageEntry(stlb->logical + sStart, _SetPage(start));
+ #if gcdMMU_TABLE_DUMP
+ gckOS_Print("%s(%d): insert STLB[%d]: %08x\n",
+ __FUNCTION__, __LINE__,
+ sStart,
+- *(stlb->logical + sStart));
++ _ReadPageEntry(stlb->logical + sStart));
+ #endif
+ /* next page. */
+ start += gcdMMU_PAGE_64K_SIZE;
+@@ -428,7 +466,7 @@ OnError:
+ if (pre->mtlbEntryNum != 0)
+ {
+ gcmkASSERT(pre->mtlbEntryNum == 1);
+- *(Mmu->mtlbLogical + pre->mtlbIndex) = 0;
++ _WritePageEntry(Mmu->mtlbLogical + pre->mtlbIndex, 0);
+ }
+
+ gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Mmu->os, pre));
+@@ -493,8 +531,8 @@ _SetupDynamicSpace(
+
+ /* Initilization. */
+ pageTable = Mmu->pageTableLogical;
+- pageTable[0] = (Mmu->pageTableEntries << 8) | gcvMMU_FREE;
+- pageTable[1] = ~0U;
++ _WritePageEntry(pageTable, (Mmu->pageTableEntries << 8) | gcvMMU_FREE);
++ _WritePageEntry(pageTable + 1, ~0U);
+ Mmu->heapList = 0;
+ Mmu->freeNodes = gcvFALSE;
+
+@@ -509,18 +547,20 @@ _SetupDynamicSpace(
+ /* Map to Master TLB. */
+ for (; i < gcdMMU_MTLB_ENTRY_NUM; i++)
+ {
+- Mmu->mtlbLogical[i] = physical
+- /* 4KB page size */
+- | (0 << 2)
+- /* Ignore exception */
+- | (0 << 1)
+- /* Present */
+- | (1 << 0);
++ _WritePageEntry(Mmu->mtlbLogical + i,
++ physical
++ /* 4KB page size */
++ | (0 << 2)
++ /* Ignore exception */
++ | (0 << 1)
++ /* Present */
++ | (1 << 0)
++ );
+ #if gcdMMU_TABLE_DUMP
+ gckOS_Print("%s(%d): insert MTLB[%d]: %08x\n",
+ __FUNCTION__, __LINE__,
+ i,
+- *(Mmu->mtlbLogical + i));
++ _ReadPageEntry(Mmu->mtlbLogical + i));
+ #endif
+ physical += gcdMMU_STLB_4K_SIZE;
+ }
+@@ -645,18 +685,11 @@ _Construct(
+ pageTable = mmu->pageTableLogical;
+
+ #if gcdMMU_CLEAR_VALUE
+- {
+- gctUINT32 i;
+-
+- for (i = 0; i < mmu->pageTableEntries; ++i)
+- {
+- pageTable[i] = gcdMMU_CLEAR_VALUE;
+- }
+- }
++ _FillPageTable(pageTable, mmu->pageTableEntries, gcdMMU_CLEAR_VALUE);
+ #endif
+
+- pageTable[0] = (mmu->pageTableEntries << 8) | gcvMMU_FREE;
+- pageTable[1] = ~0U;
++ _WritePageEntry(pageTable, (mmu->pageTableEntries << 8) | gcvMMU_FREE);
++ _WritePageEntry(pageTable + 1, ~0U);
+ mmu->heapList = 0;
+ mmu->freeNodes = gcvFALSE;
+
+@@ -797,7 +830,7 @@ _Destroy(
+ if (pre->mtlbEntryNum != 0)
+ {
+ gcmkASSERT(pre->mtlbEntryNum == 1);
+- *(Mmu->mtlbLogical + pre->mtlbIndex) = 0;
++ _WritePageEntry(Mmu->mtlbLogical + pre->mtlbIndex, 0);
+ #if gcdMMU_TABLE_DUMP
+ gckOS_Print("%s(%d): clean MTLB[%d]\n",
+ __FUNCTION__, __LINE__,
+@@ -1044,7 +1077,7 @@ _AllocatePages(
+ for (index = Mmu->heapList; !gotIt && (index < Mmu->pageTableEntries);)
+ {
+ /* Check the node type. */
+- switch (gcmENTRY_TYPE(pageTable[index]))
++ switch (gcmENTRY_TYPE(_ReadPageEntry(&pageTable[index])))
+ {
+ case gcvMMU_SINGLE:
+ /* Single odes are valid if we only need 1 page. */
+@@ -1056,13 +1089,13 @@ _AllocatePages(
+ {
+ /* Move to next node. */
+ previous = index;
+- index = pageTable[index] >> 8;
++ index = _ReadPageEntry(&pageTable[index]) >> 8;
+ }
+ break;
+
+ case gcvMMU_FREE:
+ /* Test if the node has enough space. */
+- if (PageCount <= (pageTable[index] >> 8))
++ if (PageCount <= (_ReadPageEntry(&pageTable[index]) >> 8))
+ {
+ gotIt = gcvTRUE;
+ }
+@@ -1070,7 +1103,7 @@ _AllocatePages(
+ {
+ /* Move to next node. */
+ previous = index;
+- index = pageTable[index + 1];
++ index = _ReadPageEntry(&pageTable[index + 1]);
+ }
+ break;
+
+@@ -1099,36 +1132,36 @@ _AllocatePages(
+ }
+ }
+
+- switch (gcmENTRY_TYPE(pageTable[index]))
++ switch (gcmENTRY_TYPE(_ReadPageEntry(&pageTable[index])))
+ {
+ case gcvMMU_SINGLE:
+ /* Unlink single node from free list. */
+ gcmkONERROR(
+- _Link(Mmu, previous, pageTable[index] >> 8));
++ _Link(Mmu, previous, _ReadPageEntry(&pageTable[index]) >> 8));
+ break;
+
+ case gcvMMU_FREE:
+ /* Check how many pages will be left. */
+- left = (pageTable[index] >> 8) - PageCount;
++ left = (_ReadPageEntry(&pageTable[index]) >> 8) - PageCount;
+ switch (left)
+ {
+ case 0:
+ /* The entire node is consumed, just unlink it. */
+ gcmkONERROR(
+- _Link(Mmu, previous, pageTable[index + 1]));
++ _Link(Mmu, previous, _ReadPageEntry(&pageTable[index + 1])));
+ break;
+
+ case 1:
+ /* One page will remain. Convert the node to a single node and
+ ** advance the index. */
+- pageTable[index] = (pageTable[index + 1] << 8) | gcvMMU_SINGLE;
++ _WritePageEntry(&pageTable[index], (_ReadPageEntry(&pageTable[index + 1]) << 8) | gcvMMU_SINGLE);
+ index ++;
+ break;
+
+ default:
+ /* Enough pages remain for a new node. However, we will just adjust
+ ** the size of the current node and advance the index. */
+- pageTable[index] = (left << 8) | gcvMMU_FREE;
++ _WritePageEntry(&pageTable[index], (left << 8) | gcvMMU_FREE);
+ index += left;
+ break;
+ }
+@@ -1232,35 +1265,32 @@ _FreePages(
+ #if gcdMMU_CLEAR_VALUE
+ if (Mmu->hardware->mmuVersion == 0)
+ {
+- gctUINT32 i;
+-
+- for (i = 0; i < PageCount; ++i)
+- {
+- pageTable[i] = gcdMMU_CLEAR_VALUE;
+- }
++ _FillPageTable(pageTable, PageCount, gcdMMU_CLEAR_VALUE);
+ }
+ #endif
+
+ if (PageCount == 1)
+ {
+ /* Single page node. */
+- pageTable[0] = (~((1U<<8)-1)) | gcvMMU_SINGLE
++ _WritePageEntry(pageTable,
++ (~((1U<<8)-1)) | gcvMMU_SINGLE
+ #if gcdUSE_MMU_EXCEPTION
+- /* Enable exception */
+- | (1 << 1)
++ /* Enable exception */
++ | 1 << 1
+ #endif
+- ;
++ );
+ }
+ else
+ {
+ /* Mark the node as free. */
+- pageTable[0] = (PageCount << 8) | gcvMMU_FREE
++ _WritePageEntry(pageTable,
++ (PageCount << 8) | gcvMMU_FREE
+ #if gcdUSE_MMU_EXCEPTION
+- /* Enable exception */
+- | (1 << 1)
++ /* Enable exception */
++ | 1 << 1
+ #endif
+- ;
+- pageTable[1] = ~0U;
++ );
++ _WritePageEntry(pageTable + 1, ~0U);
+
+ #if gcdUSE_MMU_EXCEPTION
+ /* Enable exception */
+@@ -1509,12 +1539,8 @@ gckMMU_SetPage(
+ data = _SetPage(PageAddress);
+ }
+
+- if (Mmu->hardware->bigEndian)
+- {
+- data = gcmSWAB32(data);
+- }
++ _WritePageEntry(PageEntry, data);
+
+- *PageEntry = data;
+ #if gcdMIRROR_PAGETABLE
+ for (i = 0; i < mirrorPageTable->reference; i++)
+ {
+@@ -1526,11 +1552,11 @@ gckMMU_SetPage(
+
+ if (mmu->hardware->mmuVersion == 0)
+ {
+- *pageEntry = PageAddress;
++ _WritePageEntry(pageEntry, PageAddress);
+ }
+ else
+ {
+- *pageEntry = _SetPage(PageAddress);
++ _WritePageEntry(pageEntry, _SetPage(PageAddress));
+ }
+ }
+
+@@ -1734,7 +1760,7 @@ gckMMU_DumpPageTableEntry(
+ * gcdMMU_STLB_4K_ENTRY_NUM
+ + stlb;
+
+- gcmkPRINT(" Page table entry = 0x%08X", pageTable[index]);
++ gcmkPRINT(" Page table entry = 0x%08X", _ReadPageEntry(pageTable + index));
+ }
+
+ gcmkFOOTER_NO();
+diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c
+index d49aa64..8a442a2 100644
+--- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c
++++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c
+@@ -1027,7 +1027,8 @@ gckVIDMEM_AllocateLinear(
+ )
+ {
+ /* The left memory is for small memory.*/
+- gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
++ status = gcvSTATUS_OUT_OF_MEMORY;
++ goto OnError;
+ }
+ #endif
+
+diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_eglplatform.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_eglplatform.h
+index 496276e..06eea79 100644
+--- a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_eglplatform.h
++++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_eglplatform.h
+@@ -227,7 +227,8 @@ gcoOS_GetDisplayInfoEx(
+ );
+
+ gceSTATUS
+-gcoOS_GetNextDisplayInfoEx(
++gcoOS_GetNextDisplayInfoExByIndex(
++ IN gctINT Index,
+ IN HALNativeDisplayType Display,
+ IN HALNativeWindowType Window,
+ IN gctUINT DisplayInfoSize,
+@@ -274,15 +275,15 @@ gcoOS_SetDisplayVirtualEx(
+
+ gceSTATUS
+ gcoOS_SetSwapInterval(
+- IN HALNativeDisplayType Display,
+- IN gctINT Interval
++ IN HALNativeDisplayType Display,
++ IN gctINT Interval
+ );
+
+ gceSTATUS
+ gcoOS_GetSwapInterval(
+- IN HALNativeDisplayType Display,
+- IN gctINT_PTR Min,
+- IN gctINT_PTR Max
++ IN HALNativeDisplayType Display,
++ IN gctINT_PTR Min,
++ IN gctINT_PTR Max
+ );
+
+ gceSTATUS
+diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine.h
+index d441d1d..249b61b 100644
+--- a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine.h
++++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine.h
+@@ -1430,6 +1430,16 @@ typedef enum _gceTEXTURE_FACE
+ }
+ gceTEXTURE_FACE;
+
++#if gcdFORCE_MIPMAP
++typedef enum
++{
++ gcvForceMipDisabled = 0,
++ gcvForceMipEnable = 1,
++ gcvForceMipGenerated = 2,
++ gcvForceMipNever = 3,
++}gceFORCE_MIPMAP;
++#endif
++
+ typedef struct _gcsTEXTURE
+ {
+ /* Addressing modes. */
+@@ -1446,6 +1456,10 @@ typedef struct _gcsTEXTURE
+ gceTEXTURE_FILTER mipFilter;
+ gctUINT anisoFilter;
+ gctBOOL forceTopLevel;
++ gctBOOL autoMipmap;
++#if gcdFORCE_MIPMAP
++ gceFORCE_MIPMAP forceMipmap;
++#endif
+ /* Level of detail. */
+ gctFIXED_POINT lodBias;
+ gctFIXED_POINT lodMin;
+@@ -1479,7 +1493,18 @@ gceSTATUS
+ gcoTEXTURE_Destroy(
+ IN gcoTEXTURE Texture
+ );
++#if gcdFORCE_MIPMAP
++gceSTATUS
++gcoTEXTURE_DestroyForceMipmap(
++ IN gcoTEXTURE Texture
++ );
+
++gceSTATUS
++gcoTEXTURE_GetMipLevels(
++ IN gcoTEXTURE Texture,
++ OUT gctINT * levels
++ );
++#endif
+ /* Replace a mipmap in gcoTEXTURE object. */
+ gceSTATUS
+ gcoTEXTURE_ReplaceMipMap(
+diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h
+index 86e9133..afe83d0 100644
+--- a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h
++++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h
+@@ -114,6 +114,30 @@
+ #define COMMAND_PROCESSOR_VERSION 1
+
+ /*
++ gcdDUMP_KEY
++
++ Set this to a string that appears in 'cat /proc/<pid>/cmdline'. E.g. 'camera'.
++ HAL will create dumps for the processes matching this key.
++*/
++#ifndef gcdDUMP_KEY
++# define gcdDUMP_KEY "process"
++#endif
++
++/*
++ gcdDUMP_PATH
++
++ The dump file location. Some processes cannot write to the sdcard.
++ Try apps' data dir, e.g. /data/data/com.android.launcher
++*/
++#ifndef gcdDUMP_PATH
++#if defined(ANDROID)
++# define gcdDUMP_PATH "/mnt/sdcard/"
++#else
++# define gcdDUMP_PATH "./"
++#endif
++#endif
++
++/*
+ gcdDUMP
+
+ When set to 1, a dump of all states and memory uploads, as well as other
+@@ -342,6 +366,17 @@
+ #endif
+
+ /*
++ gcdUSER_HEAP_ALLOCATOR
++
++ Set to 1 to enable user mode heap allocator for fast memory allocation
++ and destroying. Otherwise, memory allocation/destroying in user mode
++ will be directly managed by system. Only for linux for now.
++*/
++#ifndef gcdUSER_HEAP_ALLOCATOR
++# define gcdUSER_HEAP_ALLOCATOR 1
++#endif
++
++/*
+ gcdHEAP_SIZE
+
+ Set the allocation size for the internal heaps. Each time a heap is
+diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_version.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_version.h
+index 2881604..808fde0 100644
+--- a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_version.h
++++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_version.h
+@@ -28,7 +28,7 @@
+
+ #define gcvVERSION_PATCH 9
+
+-#define gcvVERSION_BUILD 1210
++#define gcvVERSION_BUILD 4651
+
+ #define gcvVERSION_DATE __DATE__
+
+diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_driver.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_driver.c
+index 4e3819c..2ed3d0e 100644
+--- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_driver.c
++++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_driver.c
+@@ -663,7 +663,7 @@ static int drv_mmap(
+
+ #if !gcdPAGED_MEMORY_CACHEABLE
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+- vma->vm_flags |= VM_IO | VM_DONTCOPY | VM_DONTEXPAND;
++ vma->vm_flags |= gcdVM_FLAGS;
+ #endif
+ vma->vm_pgoff = 0;
+
+diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.h b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.h
+index 9c0bcd5..3c148f6 100644
+--- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.h
++++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.h
+@@ -73,6 +73,12 @@
+
+ #define GetPageCount(size, offset) ((((size) + ((offset) & ~PAGE_CACHE_MASK)) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT)
+
++#if LINUX_VERSION_CODE >= KERNEL_VERSION (3,7,0)
++#define gcdVM_FLAGS (VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_DONTDUMP)
++#else
++#define gcdVM_FLAGS (VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED)
++#endif
++
+ static inline gctINT
+ GetOrder(
+ IN gctINT numPages
+diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c
+index c07ded8..9c2bae6 100644
+--- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c
++++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c
+@@ -869,6 +869,60 @@ _UnmapUserLogical(
+ #endif
+ }
+
++gceSTATUS
++_QueryProcessPageTable(
++ IN gctPOINTER Logical,
++ OUT gctUINT32 * Address
++ )
++{
++ spinlock_t *lock;
++ gctUINTPTR_T logical = (gctUINTPTR_T)Logical;
++ pgd_t *pgd;
++ pud_t *pud;
++ pmd_t *pmd;
++ pte_t *pte;
++
++ if (!current->mm)
++ {
++ return gcvSTATUS_NOT_FOUND;
++ }
++
++ pgd = pgd_offset(current->mm, logical);
++ if (pgd_none(*pgd) || pgd_bad(*pgd))
++ {
++ return gcvSTATUS_NOT_FOUND;
++ }
++
++ pud = pud_offset(pgd, logical);
++ if (pud_none(*pud) || pud_bad(*pud))
++ {
++ return gcvSTATUS_NOT_FOUND;
++ }
++
++ pmd = pmd_offset(pud, logical);
++ if (pmd_none(*pmd) || pmd_bad(*pmd))
++ {
++ return gcvSTATUS_NOT_FOUND;
++ }
++
++ pte = pte_offset_map_lock(current->mm, pmd, logical, &lock);
++ if (!pte)
++ {
++ return gcvSTATUS_NOT_FOUND;
++ }
++
++ if (!pte_present(*pte))
++ {
++ pte_unmap_unlock(pte, lock);
++ return gcvSTATUS_NOT_FOUND;
++ }
++
++ *Address = (pte_pfn(*pte) << PAGE_SHIFT) | (logical & ~PAGE_MASK);
++ pte_unmap_unlock(pte, lock);
++
++ return gcvSTATUS_OK;
++}
++
+ /*******************************************************************************
+ **
+ ** gckOS_Construct
+@@ -1106,6 +1160,9 @@ _CreateKernelVirtualMapping(
+ numPages,
+ 0,
+ PAGE_KERNEL);
++
++ /* Trigger a page fault. */
++ memset(addr, 0, numPages * PAGE_SIZE);
+ }
+ #else
+ struct page ** pages;
+@@ -1136,6 +1193,9 @@ _CreateKernelVirtualMapping(
+ /* ioremap() can't work on system memory since 2.6.38. */
+ addr = vmap(pages, numPages, 0, gcmkNONPAGED_MEMROY_PROT(PAGE_KERNEL));
+
++ /* Trigger a page fault. */
++ memset(addr, 0, numPages * PAGE_SIZE);
++
+ if (free)
+ {
+ kfree(pages);
+@@ -1540,7 +1600,7 @@ gckOS_MapMemory(
+ #else
+ #if !gcdPAGED_MEMORY_CACHEABLE
+ mdlMap->vma->vm_page_prot = gcmkPAGED_MEMROY_PROT(mdlMap->vma->vm_page_prot);
+- mdlMap->vma->vm_flags |= VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED;
++ mdlMap->vma->vm_flags |= gcdVM_FLAGS;
+ # endif
+ mdlMap->vma->vm_pgoff = 0;
+
+@@ -1987,7 +2047,7 @@ gckOS_AllocateNonPagedMemory(
+ }
+ #else
+ mdlMap->vma->vm_page_prot = gcmkNONPAGED_MEMROY_PROT(mdlMap->vma->vm_page_prot);
+- mdlMap->vma->vm_flags |= VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED;
++ mdlMap->vma->vm_flags |= gcdVM_FLAGS;
+ mdlMap->vma->vm_pgoff = 0;
+
+ if (remap_pfn_range(mdlMap->vma,
+@@ -2367,12 +2427,18 @@ gckOS_GetPhysicalAddress(
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+- /* Get current process ID. */
+- processID = _GetProcessID();
++ /* Query page table of current process first. */
++ status = _QueryProcessPageTable(Logical, Address);
+
+- /* Route through other function. */
+- gcmkONERROR(
+- gckOS_GetPhysicalAddressProcess(Os, Logical, processID, Address));
++ if (gcmIS_ERROR(status))
++ {
++ /* Get current process ID. */
++ processID = _GetProcessID();
++
++ /* Route through other function. */
++ gcmkONERROR(
++ gckOS_GetPhysicalAddressProcess(Os, Logical, processID, Address));
++ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Address=0x%08x", *Address);
+@@ -4139,7 +4205,7 @@ gckOS_LockPages(
+ return gcvSTATUS_OUT_OF_RESOURCES;
+ }
+
+- mdlMap->vma->vm_flags |= VM_RESERVED;
++ mdlMap->vma->vm_flags |= gcdVM_FLAGS;
+ #if !gcdPAGED_MEMORY_CACHEABLE
+ if (Cacheable == gcvFALSE)
+ {
+--
+1.8.3.2
+
--- /dev/null
+From c090a0238315094d245de2503b6f9a5bce0bda03 Mon Sep 17 00:00:00 2001
+From: Loren Huang <b02279@freescale.com>
+Date: Mon, 27 May 2013 17:45:48 +0800
+Subject: [PATCH 4/6] ENGR00264288-1 [GPU]Integrate 4.6.9p12 release kernel
+ part code
+
+Integrate 4.6.9p12 release kernel part code.
+Cherry-pick from 3.0.35 branch.
+
+Upstream-Status: Backport [3.5.7-1.0.0]
+
+Signed-off-by: Loren Huang <b02279@freescale.com>
+Acked-by: Lily Zhang
+---
+ .../GC350/hal/kernel/gc_hal_kernel_hardware_vg.c | 63 +++-
+ .../GC350/hal/kernel/gc_hal_kernel_hardware_vg.h | 2 +
+ .../arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c | 174 ++++++++---
+ .../arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.h | 2 +
+ drivers/mxc/gpu-viv/config | 1 -
+ drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c | 329 +++++++--------------
+ .../mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c | 6 +-
+ .../gpu-viv/hal/kernel/gc_hal_kernel_command_vg.c | 14 +-
+ drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_db.c | 6 +-
+ drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu.c | 119 +++++++-
+ .../hal/kernel/gc_hal_kernel_video_memory.c | 3 +
+ drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal.h | 6 +
+ drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_base.h | 34 +--
+ .../mxc/gpu-viv/hal/kernel/inc/gc_hal_compiler.h | 20 +-
+ drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_driver.h | 35 ++-
+ drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine.h | 62 +---
+ drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_enum.h | 7 -
+ .../mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h | 31 +-
+ .../mxc/gpu-viv/hal/kernel/inc/gc_hal_version.h | 2 +-
+ drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_vg.h | 6 +
+ .../hal/os/linux/kernel/gc_hal_kernel_device.c | 13 +
+ .../hal/os/linux/kernel/gc_hal_kernel_device.h | 1 +
+ .../hal/os/linux/kernel/gc_hal_kernel_driver.c | 10 +-
+ .../gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c | 74 +++--
+ .../gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.h | 3 +
+ 25 files changed, 574 insertions(+), 449 deletions(-)
+
+diff --git a/drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_vg.c b/drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_vg.c
+index 4a6010d..70c2cd6 100644
+--- a/drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_vg.c
++++ b/drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_vg.c
+@@ -217,7 +217,6 @@ _IdentifyHardware(
+ return status;
+ }
+
+-#if gcdPOWER_MANAGEMENT
+ static gctTHREADFUNCRESULT gctTHREADFUNCTYPE
+ _TimeIdleThread(
+ gctTHREADFUNCPARAMETER ThreadParameter
+@@ -262,8 +261,6 @@ _TimeIdleThread(
+ }
+ return 0;
+ }
+-#endif
+-
+
+ /******************************************************************************\
+ ****************************** gckVGHARDWARE API code *****************************
+@@ -309,6 +306,7 @@ gckVGHARDWARE_Construct(
+ do
+ {
+ gcmkERR_BREAK(gckOS_SetGPUPower(Os, gcvCORE_VG, gcvTRUE, gcvTRUE));
++
+ status = _ResetGPU(Os);
+
+ if (status != gcvSTATUS_OK)
+@@ -368,14 +366,17 @@ gckVGHARDWARE_Construct(
+
+ gcmkERR_BREAK(gckOS_CreateMutex(Os, &hardware->powerMutex));
+ gcmkERR_BREAK(gckOS_CreateSignal(Os, gcvFALSE, &hardware->idleSignal));
+-#if gcdPOWER_MANAGEMENT
++
++ /* Enable power management by default. */
++ hardware->powerManagement = gcvTRUE;
++
+ gcmkERR_BREAK(gckOS_StartThread(
+ hardware->os,
+ _TimeIdleThread,
+ hardware,
+ &hardware->timeIdleThread
+ ));
+-#endif
++
+ /* Return pointer to the gckVGHARDWARE object. */
+ *Hardware = hardware;
+
+@@ -395,6 +396,8 @@ gckVGHARDWARE_Construct(
+ gcmkVERIFY_OK(gckOS_Free(Os, hardware));
+ }
+
++ gcmkVERIFY_OK(gckOS_SetGPUPower(Os, gcvCORE_VG, gcvFALSE, gcvFALSE));
++
+ gcmkFOOTER();
+ /* Return the status. */
+ return status;
+@@ -425,11 +428,10 @@ gckVGHARDWARE_Destroy(
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+-#if gcdPOWER_MANAGEMENT
+ Hardware->killThread = gcvTRUE;
+ gcmkVERIFY_OK(gckOS_Signal(Hardware->os, Hardware->idleSignal, gcvTRUE));
+ gcmkVERIFY_OK(gckOS_StopThread(Hardware->os, Hardware->timeIdleThread));
+-#endif
++
+ /* Mark the object as unknown. */
+ Hardware->object.type = gcvOBJ_UNKNOWN;
+
+@@ -1432,7 +1434,6 @@ gckVGHARDWARE_ReadInterrupt(
+ return status;
+ }
+
+-#if gcdPOWER_MANAGEMENT
+ static gceSTATUS _CommandStall(
+ gckVGHARDWARE Hardware)
+ {
+@@ -1477,7 +1478,6 @@ static gceSTATUS _CommandStall(
+ /* Return the status. */
+ return status;
+ }
+-#endif
+
+ /*******************************************************************************
+ **
+@@ -1500,7 +1500,6 @@ gckVGHARDWARE_SetPowerManagementState(
+ IN gceCHIPPOWERSTATE State
+ )
+ {
+-#if gcdPOWER_MANAGEMENT
+ gceSTATUS status;
+ gckVGCOMMAND command = gcvNULL;
+ gckOS os;
+@@ -1600,6 +1599,12 @@ gckVGHARDWARE_SetPowerManagementState(
+ command = Hardware->kernel->command;
+ gcmkVERIFY_OBJECT(command, gcvOBJ_COMMAND);
+
++ if (Hardware->powerManagement == gcvFALSE)
++ {
++ gcmkFOOTER_NO();
++ return gcvSTATUS_OK;
++ }
++
+ /* Start profiler. */
+ gcmkPROFILE_INIT(freq, time);
+
+@@ -1914,10 +1919,6 @@ OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+-#else /* gcdPOWER_MANAGEMENT */
+- /* Do nothing */
+- return gcvSTATUS_OK;
+-#endif
+ }
+
+ /*******************************************************************************
+@@ -1955,6 +1956,40 @@ gckVGHARDWARE_QueryPowerManagementState(
+ return gcvSTATUS_OK;
+ }
+
++/*******************************************************************************
++**
++** gckVGHARDWARE_SetPowerManagement
++**
++** Configure GPU power management function.
++** Only used in driver initialization stage.
++**
++** INPUT:
++**
++** gckVGHARDWARE Harwdare
++** Pointer to an gckHARDWARE object.
++**
++** gctBOOL PowerManagement
++** Power Mangement State.
++**
++*/
++gceSTATUS
++gckVGHARDWARE_SetPowerManagement(
++ IN gckVGHARDWARE Hardware,
++ IN gctBOOL PowerManagement
++ )
++{
++ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
++
++ /* Verify the arguments. */
++ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
++
++ Hardware->powerManagement = PowerManagement;
++
++ /* Success. */
++ gcmkFOOTER_NO();
++ return gcvSTATUS_OK;
++}
++
+ gceSTATUS
+ gckVGHARDWARE_SetPowerOffTimeout(
+ IN gckVGHARDWARE Hardware,
+diff --git a/drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_vg.h b/drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_vg.h
+index 83a603e..16b81ae 100644
+--- a/drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_vg.h
++++ b/drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_vg.h
+@@ -66,6 +66,8 @@ struct _gckVGHARDWARE
+ gctTHREAD timeIdleThread;
+ gctBOOL killThread;
+ gctPOINTER pageTableDirty;
++
++ gctBOOL powerManagement;
+ };
+
+ #endif /* __gc_hal_kernel_hardware_h_ */
+diff --git a/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c b/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c
+index ebd36fe..00f3839 100644
+--- a/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c
++++ b/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c
+@@ -176,6 +176,7 @@ _IdentifyHardware(
+ Identity->chipMinorFeatures1 = 0;
+ Identity->chipMinorFeatures2 = 0;
+ Identity->chipMinorFeatures3 = 0;
++ Identity->chipMinorFeatures4 = 0;
+ }
+ else
+ {
+@@ -207,13 +208,20 @@ _IdentifyHardware(
+ gckOS_ReadRegisterEx(Os, Core,
+ 0x00088,
+ &Identity->chipMinorFeatures3));
++
++ /* Read chip minor featuress register #4. */
++ gcmkONERROR(
++ gckOS_ReadRegisterEx(Os, Core,
++ 0x00094,
++ &Identity->chipMinorFeatures4));
+ }
+ else
+ {
+- /* Chip doesn't has minor features register #1 or 2 or 3. */
++ /* Chip doesn't has minor features register #1 or 2 or 3 or 4. */
+ Identity->chipMinorFeatures1 = 0;
+ Identity->chipMinorFeatures2 = 0;
+ Identity->chipMinorFeatures3 = 0;
++ Identity->chipMinorFeatures4 = 0;
+ }
+ }
+
+@@ -234,14 +242,14 @@ _IdentifyHardware(
+
+ /* Exception for GC1000, revision 5035 & GC800, revision 4612 */
+ if (((Identity->chipModel == gcv1000) && ((Identity->chipRevision == 0x5035)
+- || (Identity->chipRevision == 0x5036)))
++ || (Identity->chipRevision == 0x5036)
++ || (Identity->chipRevision == 0x5037)))
+ || ((Identity->chipModel == gcv800) && (Identity->chipRevision == 0x4612)))
+ {
+ Identity->superTileMode = 1;
+ }
+
+
+-
+ /* Disable HZ when EZ is present for older chips. */
+ if (!((((gctUINT32) (Identity->chipFeatures)) >> (0 ? 16:16) & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1))))))))
+ {
+@@ -285,6 +293,10 @@ _IdentifyHardware(
+ "Identity: chipMinorFeatures3=0x%08X",
+ Identity->chipMinorFeatures3);
+
++ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
++ "Identity: chipMinorFeatures4=0x%08X",
++ Identity->chipMinorFeatures4);
++
+ /***************************************************************************
+ ** Get chip specs.
+ */
+@@ -576,7 +588,6 @@ OnError:
+ return status;
+ }
+
+-#if gcdPOWER_MANAGEMENT
+ static gceSTATUS
+ _IsGPUPresent(
+ IN gckHARDWARE Hardware
+@@ -631,7 +642,6 @@ OnError:
+ gcmkFOOTER();
+ return status;
+ }
+-#endif
+
+ /******************************************************************************\
+ ****************************** gckHARDWARE API code *****************************
+@@ -708,6 +718,7 @@ gckHARDWARE_Construct(
+
+ case gcv300:
+ case gcv320:
++ case gcv420:
+ hardware->type = gcvHARDWARE_2D;
+ /*set outstanding limit*/
+ gcmkONERROR(gckOS_ReadRegisterEx(Os, Core, 0x00414, &axi_ot));
+@@ -795,6 +806,9 @@ gckHARDWARE_Construct(
+ hardware->linkQueue.count = 0;
+ #endif
+
++ /* Enable power management by default. */
++ hardware->powerManagement = gcvTRUE;
++
+ /* Return pointer to the gckHARDWARE object. */
+ *Hardware = hardware;
+
+@@ -1404,6 +1418,7 @@ gckHARDWARE_QueryChipIdentity(
+ Identity->chipMinorFeatures1 = Hardware->identity.chipMinorFeatures1;
+ Identity->chipMinorFeatures2 = Hardware->identity.chipMinorFeatures2;
+ Identity->chipMinorFeatures3 = Hardware->identity.chipMinorFeatures3;
++ Identity->chipMinorFeatures4 = Hardware->identity.chipMinorFeatures4;
+
+ /* Return chip specs. */
+ Identity->streamCount = Hardware->identity.streamCount;
+@@ -3129,7 +3144,7 @@ gckHARDWARE_FlushMMU(
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+ buffer[9]
+- = (((((gctUINT32) (~0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) & ((((gctUINT32) (~0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ? 7:7))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ? 7:7))) );
++ = (((((gctUINT32) (~0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) & ((((gctUINT32) (~0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ? 7:7))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ? 7:7))));
+
+ /* Arm the PE-FE Semaphore. */
+ buffer[10]
+@@ -3660,7 +3675,7 @@ typedef enum
+ }
+ gcePOWER_FLAGS;
+
+-#if gcmIS_DEBUG(gcdDEBUG_TRACE) && gcdPOWER_MANAGEMENT
++#if gcmIS_DEBUG(gcdDEBUG_TRACE)
+ static gctCONST_STRING
+ _PowerEnum(gceCHIPPOWERSTATE State)
+ {
+@@ -3709,7 +3724,6 @@ gckHARDWARE_SetPowerManagementState(
+ IN gceCHIPPOWERSTATE State
+ )
+ {
+-#if gcdPOWER_MANAGEMENT
+ gceSTATUS status;
+ gckCOMMAND command = gcvNULL;
+ gckOS os;
+@@ -3841,6 +3855,12 @@ gckHARDWARE_SetPowerManagementState(
+ command = Hardware->kernel->command;
+ gcmkVERIFY_OBJECT(command, gcvOBJ_COMMAND);
+
++ if (Hardware->powerManagement == gcvFALSE)
++ {
++ gcmkFOOTER_NO();
++ return gcvSTATUS_OK;
++ }
++
+ /* Start profiler. */
+ gcmkPROFILE_INIT(freq, time);
+
+@@ -4491,10 +4511,6 @@ OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+-#else /* gcdPOWER_MANAGEMENT */
+- /* Do nothing */
+- return gcvSTATUS_OK;
+-#endif
+ }
+
+ /*******************************************************************************
+@@ -4532,6 +4548,40 @@ gckHARDWARE_QueryPowerManagementState(
+ return gcvSTATUS_OK;
+ }
+
++/*******************************************************************************
++**
++** gckHARDWARE_SetPowerManagement
++**
++** Configure GPU power management function.
++** Only used in driver initialization stage.
++**
++** INPUT:
++**
++** gckHARDWARE Harwdare
++** Pointer to an gckHARDWARE object.
++**
++** gctBOOL PowerManagement
++** Power Mangement State.
++**
++*/
++gceSTATUS
++gckHARDWARE_SetPowerManagement(
++ IN gckHARDWARE Hardware,
++ IN gctBOOL PowerManagement
++ )
++{
++ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
++
++ /* Verify the arguments. */
++ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
++
++ Hardware->powerManagement = PowerManagement;
++
++ /* Success. */
++ gcmkFOOTER_NO();
++ return gcvSTATUS_OK;
++}
++
+ #if gcdENABLE_FSCALE_VAL_ADJUST
+ gceSTATUS
+ gckHARDWARE_SetFscaleValue(
+@@ -4767,6 +4817,21 @@ OnError:
+ GC_DEBUG_SIGNALS_##block##_Address, \
+ &profiler->data))
+
++#define gcmkREAD_DEBUG_REGISTER_N(control, block, index, data) \
++ gcmkONERROR(\
++ gckOS_WriteRegisterEx(Hardware->os, \
++ Hardware->core, \
++ GC_DEBUG_CONTROL##control##_Address, \
++ gcmSETFIELD(0, \
++ GC_DEBUG_CONTROL##control, \
++ block, \
++ index))); \
++ gcmkONERROR(\
++ gckOS_ReadRegisterEx(Hardware->os, \
++ Hardware->core, \
++ GC_DEBUG_SIGNALS_##block##_Address, \
++ &data))
++
+ #define gcmkRESET_DEBUG_REGISTER(control, block) \
+ gcmkONERROR(\
+ gckOS_WriteRegisterEx(Hardware->os, \
+@@ -4857,6 +4922,9 @@ gckHARDWARE_QueryProfileRegisters(
+ {
+ gceSTATUS status;
+ gcsPROFILER_COUNTERS * profiler = Counters;
++ gctUINT i, clock;
++ gctUINT32 colorKilled, colorDrawn, depthKilled, depthDrawn;
++ gctUINT32 totalRead, totalWrite;
+
+ gcmkHEADER_ARG("Hardware=0x%x Counters=0x%x", Hardware, Counters);
+
+@@ -4867,16 +4935,6 @@ gckHARDWARE_QueryProfileRegisters(
+ gcmkONERROR(
+ gckOS_ReadRegisterEx(Hardware->os,
+ Hardware->core,
+- 0x00040,
+- &profiler->gpuTotalRead64BytesPerFrame));
+- gcmkONERROR(
+- gckOS_ReadRegisterEx(Hardware->os,
+- Hardware->core,
+- 0x00044,
+- &profiler->gpuTotalWrite64BytesPerFrame));
+- gcmkONERROR(
+- gckOS_ReadRegisterEx(Hardware->os,
+- Hardware->core,
+ 0x00438,
+ &profiler->gpuCyclesCounter));
+
+@@ -4892,8 +4950,63 @@ gckHARDWARE_QueryProfileRegisters(
+ 0x0007C,
+ &profiler->gpuIdleCyclesCounter));
+
+- if(Reset){
+
++ /* Read clock control register. */
++ gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
++ Hardware->core,
++ 0x00000,
++ &clock));
++
++ profiler->gpuTotalRead64BytesPerFrame = 0;
++ profiler->gpuTotalWrite64BytesPerFrame = 0;
++ profiler->pe_pixel_count_killed_by_color_pipe = 0;
++ profiler->pe_pixel_count_killed_by_depth_pipe = 0;
++ profiler->pe_pixel_count_drawn_by_color_pipe = 0;
++ profiler->pe_pixel_count_drawn_by_depth_pipe = 0;
++
++ /* Walk through all avaiable pixel pipes. */
++ for (i = 0; i < Hardware->identity.pixelPipes; ++i)
++ {
++ /* Select proper pipe. */
++ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
++ Hardware->core,
++ 0x00000,
++ ((((gctUINT32) (clock)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:20) - (0 ? 23:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:20) - (0 ? 23:20) + 1))))))) << (0 ? 23:20))) | (((gctUINT32) ((gctUINT32) (i) & ((gctUINT32) ((((1 ? 23:20) - (0 ? 23:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:20) - (0 ? 23:20) + 1))))))) << (0 ? 23:20)))));
++
++ /* BW */
++ gcmkONERROR(
++ gckOS_ReadRegisterEx(Hardware->os,
++ Hardware->core,
++ 0x00040,
++ &totalRead));
++ gcmkONERROR(
++ gckOS_ReadRegisterEx(Hardware->os,
++ Hardware->core,
++ 0x00044,
++ &totalWrite));
++
++ profiler->gpuTotalRead64BytesPerFrame += totalRead;
++ profiler->gpuTotalWrite64BytesPerFrame += totalWrite;
++
++ /* PE */
++ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16)))));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454, &colorKilled));
++ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16)))));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454, &depthKilled));
++ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16)))));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454, &colorDrawn));
++ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16)))));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454, &depthDrawn));
++
++ profiler->pe_pixel_count_killed_by_color_pipe += colorKilled;
++ profiler->pe_pixel_count_killed_by_depth_pipe += depthKilled;
++ profiler->pe_pixel_count_drawn_by_color_pipe += colorDrawn;
++ profiler->pe_pixel_count_drawn_by_depth_pipe += depthDrawn;
++ }
++
++ /* Reset clock control register. */
++ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
++ Hardware->core,
++ 0x00000,
++ clock));
++
++ if(Reset){
+ /* Reset counters. */
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x0003C, 1));
+@@ -4903,19 +5016,10 @@ gckHARDWARE_QueryProfileRegisters(
+ gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00438, 0));
+ gcmkONERROR(
+ gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00078, 0));
+- }
+- /* PE */
+- gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
+-gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454, &profiler->pe_pixel_count_killed_by_color_pipe));
+- gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
+-gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454, &profiler->pe_pixel_count_killed_by_depth_pipe));
+- gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
+-gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454, &profiler->pe_pixel_count_drawn_by_color_pipe));
+- gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
+-gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454, &profiler->pe_pixel_count_drawn_by_depth_pipe));
+- if(Reset){ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
++ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16)))
+-)); }
++));
++ }
+
+ /* SH */
+ gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (7) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
+diff --git a/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.h b/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.h
+index 517b35c..37226b7 100644
+--- a/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.h
++++ b/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.h
+@@ -90,6 +90,8 @@ struct _gckHARDWARE
+ #if gcdLINK_QUEUE_SIZE
+ struct _gckLINKQUEUE linkQueue;
+ #endif
++
++ gctBOOL powerManagement;
+ };
+
+ gceSTATUS
+diff --git a/drivers/mxc/gpu-viv/config b/drivers/mxc/gpu-viv/config
+index 1196efa..cdd143e 100644
+--- a/drivers/mxc/gpu-viv/config
++++ b/drivers/mxc/gpu-viv/config
+@@ -22,7 +22,6 @@
+ ARCH_TYPE ?= arm
+ SDK_DIR ?= $(AQROOT)/build/sdk
+ USE_3D_VG ?= 1
+-USE_POWER_MANAGEMENT ?= 1
+ FORCE_ALL_VIDEO_MEMORY_CACHED ?= 0
+ NONPAGED_MEMORY_CACHEABLE ?= 0
+ NONPAGED_MEMORY_BUFFERABLE ?= 1
+diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c
+index 7964585..b7b0d28 100644
+--- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c
++++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c
+@@ -904,9 +904,6 @@ gckKERNEL_Dispatch(
+ gctSIGNAL signal;
+ #endif
+
+- gcsDATABASE_RECORD record;
+- gctPOINTER data;
+-
+ gcmkHEADER_ARG("Kernel=0x%x FromUser=%d Interface=0x%x",
+ Kernel, FromUser, Interface);
+
+@@ -1940,249 +1937,133 @@ gckKERNEL_Dispatch(
+ #endif
+
+ case gcvHAL_GET_SHARED_INFO:
+- bytes = (gctSIZE_T) Interface->u.GetSharedInfo.size;
+-
+- if (Interface->u.GetSharedInfo.dataId != 0)
++ if (Interface->u.GetSharedInfo.data == gcvNULL)
+ {
+- gcmkONERROR(gckKERNEL_FindProcessDB(Kernel,
+- Interface->u.GetSharedInfo.pid,
+- 0,
+- gcvDB_SHARED_INFO,
+- gcmINT2PTR(Interface->u.GetSharedInfo.dataId),
+- &record));
+-
+- /* find a record in db, check size */
+- if (record.bytes != bytes)
+- {
+- /* Size change is not allowed */
+- gcmkONERROR(gcvSTATUS_INVALID_DATA);
+- }
+-
+- /* fetch data */
+- gcmkONERROR(gckOS_CopyToUserData(
+- Kernel->os,
+- record.physical,
+- gcmUINT64_TO_PTR(Interface->u.GetSharedInfo.data),
+- bytes
+- ));
+-
++ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+-
+- if ((node = gcmUINT64_TO_PTR(Interface->u.GetSharedInfo.node)) != gcvNULL)
++ else
+ {
+- switch (Interface->u.GetSharedInfo.infoType)
+- {
+- case gcvVIDMEM_INFO_GENERIC:
+- { /* Generic data stored */
+- if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+- {
+- data = &node->VidMem.sharedInfo;
+-
+- }
+- else
+- {
+- data = &node->Virtual.sharedInfo;
+- }
++ gctUINT32 pid = Interface->u.GetSharedInfo.pid;
++ gctUINT32 dataId = Interface->u.GetSharedInfo.dataId;
++ gctSIZE_T bytes = Interface->u.GetSharedInfo.bytes;
++ gctPOINTER data = Interface->u.GetSharedInfo.data;
++ gcsDATABASE_RECORD record;
+
+- gcmkONERROR(gckOS_CopyToUserData(
+- Kernel->os,
+- data,
+- gcmUINT64_TO_PTR(Interface->u.GetSharedInfo.nodeData),
+- sizeof(gcsVIDMEM_NODE_SHARED_INFO)
+- ));
+- }
+- break;
+-
+- case gcvVIDMEM_INFO_DIRTY_RECTANGLE:
+- { /* Dirty rectangle stored */
+- gcsVIDMEM_NODE_SHARED_INFO *storedSharedInfo;
+- gcsVIDMEM_NODE_SHARED_INFO alignedSharedInfo;
+-
+- if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+- {
+- storedSharedInfo = &node->VidMem.sharedInfo;
+- }
+- else
+- {
+- storedSharedInfo = &node->Virtual.sharedInfo;
+- }
+-
+- /* Stored shared info holds the unaligned dirty rectangle.
+- Align it first. */
+-
+- /* Hardware requires 64-byte aligned address, and 16x4 pixel aligned rectsize.
+- We simply align to 32 pixels which covers both 16- and 32-bpp formats. */
+-
+- /* Make sure we have a legit rectangle. */
+- gcmkASSERT((storedSharedInfo->RectSize.width != 0) && (storedSharedInfo->RectSize.height != 0));
+-
+- alignedSharedInfo.SrcOrigin.x = gcmALIGN_BASE(storedSharedInfo->SrcOrigin.x, 32);
+- alignedSharedInfo.RectSize.width = gcmALIGN((storedSharedInfo->RectSize.width + (storedSharedInfo->SrcOrigin.x - alignedSharedInfo.SrcOrigin.x)), 16);
+-
+- alignedSharedInfo.SrcOrigin.y = gcmALIGN_BASE(storedSharedInfo->SrcOrigin.y, 4);
+- alignedSharedInfo.RectSize.height = gcmALIGN((storedSharedInfo->RectSize.height + (storedSharedInfo->SrcOrigin.y - alignedSharedInfo.SrcOrigin.y)), 4);
+-
+- gcmkONERROR(gckOS_CopyToUserData(
+- Kernel->os,
+- &alignedSharedInfo,
+- gcmUINT64_TO_PTR(Interface->u.GetSharedInfo.nodeData),
+- sizeof(gcsVIDMEM_NODE_SHARED_INFO)
+- ));
+-
+- gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_KERNEL,
+- "Node = %p, unaligned rectangle (l=%d, t=%d, w=%d, h=%d) aligned to (l=%d, t=%d, w=%d, h=%d)", node,
+- storedSharedInfo->SrcOrigin.x, storedSharedInfo->SrcOrigin.y,
+- storedSharedInfo->RectSize.width, storedSharedInfo->RectSize.height,
+- alignedSharedInfo.SrcOrigin.x, alignedSharedInfo.SrcOrigin.y,
+- alignedSharedInfo.RectSize.width, alignedSharedInfo.RectSize.height);
++ /* Find record. */
++ gcmkONERROR(
++ gckKERNEL_FindProcessDB(Kernel,
++ pid,
++ 0,
++ gcvDB_SHARED_INFO,
++ gcmINT2PTR(dataId),
++ &record));
++
++ /* Check memory size. */
++ if (bytes < record.bytes)
++ {
++ /* Insufficient memory to hold shared data. */
++ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
++ }
+
+- /* Rectangle */
+- storedSharedInfo->SrcOrigin.x =
+- storedSharedInfo->SrcOrigin.y =
+- storedSharedInfo->RectSize.width =
+- storedSharedInfo->RectSize.height = 0;
+- }
+- break;
+- }
++ /* Copy to user. */
++ status = gckOS_CopyToUserData(Kernel->os,
++ record.physical,
++ data,
++ record.bytes);
++
++ /*
++ * Remove from process db.
++ * Every time when shared info is taken, the record is erased in
++ * kernel side.
++ */
++ gcmkVERIFY_OK(
++ gckKERNEL_RemoveProcessDB(Kernel,
++ pid,
++ gcvDB_SHARED_INFO,
++ gcmINT2PTR(dataId)));
++ /* Free existed data. */
++ gcmkVERIFY_OK(
++ gckOS_FreeMemory(Kernel->os, record.physical));
+ }
+ break;
+
+ case gcvHAL_SET_SHARED_INFO:
+- bytes = (gctSIZE_T) Interface->u.SetSharedInfo.size;
+-
+- if (Interface->u.SetSharedInfo.dataId != 0)
+ {
+- status = gckKERNEL_FindProcessDB(Kernel, processID, 0,
+- gcvDB_SHARED_INFO,
+- gcmINT2PTR(Interface->u.SetSharedInfo.dataId),
+- &record);
+-
+- if (status == gcvSTATUS_INVALID_DATA)
+- {
+- /* private data has not been created yet */
+- /* Note: we count on DestoryProcessDB to free it */
+- gcmkONERROR(gckOS_AllocateMemory(
+- Kernel->os,
+- bytes,
+- &data
+- ));
+-
+- gcmkONERROR(
+- gckKERNEL_AddProcessDB(Kernel, processID,
+- gcvDB_SHARED_INFO,
+- gcmINT2PTR(Interface->u.SetSharedInfo.dataId),
+- data,
+- bytes
+- ));
+- }
+- else
++ gctUINT32 dataId = Interface->u.SetSharedInfo.dataId;
++ gctPOINTER data = Interface->u.SetSharedInfo.data;
++ gctUINT32 bytes = Interface->u.SetSharedInfo.bytes;
++ gctPOINTER memory = gcvNULL;
++ gcsDATABASE_RECORD record;
++
++ if (gcmIS_SUCCESS(gckKERNEL_FindProcessDB(Kernel,
++ processID,
++ 0,
++ gcvDB_SHARED_INFO,
++ gcmINT2PTR(dataId),
++ &record)))
+ {
+- /* bail on other errors */
+- gcmkONERROR(status);
+-
+- /* find a record in db, check size */
+- if (record.bytes != bytes)
++ /* Find a record with the same id. */
++ if (bytes != record.bytes)
+ {
+- /* Size change is not allowed */
+- gcmkONERROR(gcvSTATUS_INVALID_DATA);
++ /* Remove from process db. */
++ gcmkVERIFY_OK(
++ gckKERNEL_RemoveProcessDB(Kernel,
++ processID,
++ gcvDB_SHARED_INFO,
++ gcmINT2PTR(dataId)));
++
++ /* Free existed data. */
++ gcmkVERIFY_OK(
++ gckOS_FreeMemory(Kernel->os, record.physical));
+ }
+-
+- /* get storage address */
+- data = record.physical;
+- }
+-
+- gcmkONERROR(gckOS_CopyFromUserData(
+- Kernel->os,
+- data,
+- gcmUINT64_TO_PTR(Interface->u.SetSharedInfo.data),
+- bytes
+- ));
+- }
+-
+- if ((node = gcmUINT64_TO_PTR(Interface->u.SetSharedInfo.node)) != gcvNULL)
+- {
+- switch (Interface->u.SetSharedInfo.infoType)
++ else
+ {
+- case gcvVIDMEM_INFO_GENERIC:
+- { /* Generic data stored */
+- if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+- {
+- data = &node->VidMem.sharedInfo;
+- }
+- else
+- {
+- data = &node->Virtual.sharedInfo;
+- }
+-
+- gcmkONERROR(gckOS_CopyFromUserData(
+- Kernel->os,
+- data,
+- gcmUINT64_TO_PTR(Interface->u.SetSharedInfo.nodeData),
+- sizeof(gcsVIDMEM_NODE_SHARED_INFO)
+- ));
+- }
+- break;
++ /* Re-use allocated memory. */
++ memory = record.physical;
++ }
++ }
+
+- case gcvVIDMEM_INFO_DIRTY_RECTANGLE:
+- { /* Dirty rectangle stored */
+- gcsVIDMEM_NODE_SHARED_INFO newSharedInfo;
+- gcsVIDMEM_NODE_SHARED_INFO *currentSharedInfo;
+- gctINT dirtyX, dirtyY, right, bottom;
+-
+- /* Expand the dirty rectangle stored in the node to include the rectangle passed in. */
+- gcmkONERROR(gckOS_CopyFromUserData(
+- Kernel->os,
+- &newSharedInfo,
+- gcmUINT64_TO_PTR(Interface->u.SetSharedInfo.nodeData),
+- gcmSIZEOF(gcsVIDMEM_NODE_SHARED_INFO)
+- ));
+-
+- if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+- {
+- currentSharedInfo = &node->VidMem.sharedInfo;
+- }
+- else
+- {
+- currentSharedInfo = &node->Virtual.sharedInfo;
+- }
++ if ((data == gcvNULL) || (bytes == 0))
++ {
++ /* Nothing to record. */
++ break;
++ }
+
+- gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_KERNEL, "Node = %p Stored rectangle (l=%d, t=%d, w=%d, h=%d)", node,
+- currentSharedInfo->SrcOrigin.x, currentSharedInfo->SrcOrigin.y,
+- currentSharedInfo->RectSize.width, currentSharedInfo->RectSize.height);
++ if (bytes > 1024)
++ {
++ /* Limite data size. */
++ gcmkONERROR(gcvSTATUS_TOO_COMPLEX);
++ }
+
+- gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_KERNEL, "To combine with (l=%d, t=%d, w=%d, h=%d)",
+- newSharedInfo.SrcOrigin.x, newSharedInfo.SrcOrigin.y,
+- newSharedInfo.RectSize.width, newSharedInfo.RectSize.height);
++ if (memory == gcvNULL)
++ {
++ /* Allocate memory for holding shared data. */
++ gcmkONERROR(
++ gckOS_AllocateMemory(Kernel->os, bytes, &memory));
+
+- if ((currentSharedInfo->RectSize.width == 0) || (currentSharedInfo->RectSize.height == 0))
+- { /* Setting it for the first time */
+- currentSharedInfo->SrcOrigin.x = newSharedInfo.SrcOrigin.x;
+- currentSharedInfo->SrcOrigin.y = newSharedInfo.SrcOrigin.y;
+- currentSharedInfo->RectSize.width = newSharedInfo.RectSize.width;
+- currentSharedInfo->RectSize.height = newSharedInfo.RectSize.height;
+- }
+- else
+- {
+- /* Expand the stored rectangle to include newly locked rectangle */
+- dirtyX = (newSharedInfo.SrcOrigin.x < currentSharedInfo->SrcOrigin.x) ? newSharedInfo.SrcOrigin.x : currentSharedInfo->SrcOrigin.x;
+- right = gcmMAX((currentSharedInfo->SrcOrigin.x + currentSharedInfo->RectSize.width), (newSharedInfo.SrcOrigin.x + newSharedInfo.RectSize.width));
+- currentSharedInfo->RectSize.width = right - dirtyX;
+- currentSharedInfo->SrcOrigin.x = dirtyX;
+-
+- dirtyY = (newSharedInfo.SrcOrigin.y < currentSharedInfo->SrcOrigin.y) ? newSharedInfo.SrcOrigin.y : currentSharedInfo->SrcOrigin.y;
+- bottom = gcmMAX((currentSharedInfo->SrcOrigin.y + currentSharedInfo->RectSize.height), (newSharedInfo.SrcOrigin.y + newSharedInfo.RectSize.height));
+- currentSharedInfo->RectSize.height = bottom - dirtyY;
+- currentSharedInfo->SrcOrigin.y = dirtyY;
+- }
++ /* Add to process db. */
++ status = gckKERNEL_AddProcessDB(Kernel,
++ processID,
++ gcvDB_SHARED_INFO,
++ gcmINT2PTR(dataId),
++ memory,
++ bytes);
+
+- gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_KERNEL, "Combined rectangle (l=%d, t=%d, w=%d, h=%d)",
+- currentSharedInfo->SrcOrigin.x, currentSharedInfo->SrcOrigin.y,
+- currentSharedInfo->RectSize.width, currentSharedInfo->RectSize.height);
+- }
++ if (gcmIS_ERROR(status))
++ {
++ /* Failed to add process db. Free allocated memory. */
++ gcmkVERIFY_OK(gckOS_FreeMemory(Kernel->os, memory));
+ break;
+ }
+- }
++ }
+
++ /* Copy shared data to kernel memory. */
++ gcmkONERROR(
++ gckOS_CopyFromUserData(Kernel->os,
++ memory,
++ data,
++ bytes));
++ }
+ break;
+
+ case gcvHAL_SET_FSCALE_VALUE:
+diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c
+index 66ce0d1..9ee9ea1 100644
+--- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c
++++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c
+@@ -2047,14 +2047,14 @@ gckCOMMAND_Commit(
+ EventQueue = nextEventRecord;
+ }
+
+-#if gcdPOWER_MANAGEMENT
+- if (Command->kernel->eventObj->queueHead == gcvNULL)
++ if (Command->kernel->eventObj->queueHead == gcvNULL
++ && Command->kernel->hardware->powerManagement == gcvTRUE
++ )
+ {
+ /* Commit done event by which work thread knows all jobs done. */
+ gcmkVERIFY_OK(
+ gckEVENT_CommitDone(Command->kernel->eventObj, gcvKERNEL_PIXEL));
+ }
+-#endif
+
+ /* Submit events. */
+ status = gckEVENT_Submit(Command->kernel->eventObj, gcvTRUE, gcvFALSE);
+diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command_vg.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command_vg.c
+index 9685a5d..76c1c10 100644
+--- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command_vg.c
++++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command_vg.c
+@@ -1234,7 +1234,6 @@ _EventHandler_BusError(
+ return gcvSTATUS_OK;
+ }
+
+-#if gcdPOWER_MANAGEMENT
+ /******************************************************************************\
+ ****************************** Power Stall Handler *******************************
+ \******************************************************************************/
+@@ -1250,7 +1249,6 @@ _EventHandler_PowerStall(
+ Kernel->command->powerStallSignal,
+ gcvTRUE);
+ }
+-#endif
+
+ /******************************************************************************\
+ ******************************** Task Routines *********************************
+@@ -1965,15 +1963,12 @@ gcmDECLARE_INTERRUPT_HANDLER(COMMAND, 0)
+ );
+ }
+ }
+-#if gcdPOWER_MANAGEMENT
+ else
+ {
+-
+ status = gckVGHARDWARE_SetPowerManagementState(
+ Kernel->command->hardware, gcvPOWER_IDLE_BROADCAST
+ );
+ }
+-#endif
+
+ /* Break out of the loop. */
+ break;
+@@ -2848,7 +2843,7 @@ gckVGCOMMAND_Construct(
+ _EventHandler_BusError
+ ));
+
+-#if gcdPOWER_MANAGEMENT
++
+ command->powerStallInt = 30;
+ /* Enable the interrupt. */
+ gcmkERR_BREAK(gckVGINTERRUPT_Enable(
+@@ -2856,7 +2851,6 @@ gckVGCOMMAND_Construct(
+ &command->powerStallInt,
+ _EventHandler_PowerStall
+ ));
+-#endif
+
+ /***********************************************************************
+ ** Task management initialization.
+@@ -3419,7 +3413,6 @@ gckVGCOMMAND_Commit(
+ gcvINFINITE
+ ));
+
+-#if gcdPOWER_MANAGEMENT
+ status = gckVGHARDWARE_SetPowerManagementState(
+ Command->hardware, gcvPOWER_ON_AUTO);
+
+@@ -3447,7 +3440,7 @@ gckVGCOMMAND_Commit(
+
+ break;
+ }
+-#endif
++
+ gcmkERR_BREAK(_FlushMMU(Command));
+
+ do
+@@ -3676,10 +3669,9 @@ gckVGCOMMAND_Commit(
+ }
+ while (gcvFALSE);
+
+-#if gcdPOWER_MANAGEMENT
+ gcmkVERIFY_OK(gckOS_ReleaseSemaphore(
+ Command->os, Command->powerSemaphore));
+-#endif
++
+ /* Release the mutex. */
+ gcmkCHECK_STATUS(gckOS_ReleaseMutex(
+ Command->os,
+diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_db.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_db.c
+index bc5f083..673d4f7 100644
+--- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_db.c
++++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_db.c
+@@ -1303,9 +1303,9 @@ gckKERNEL_DestroyProcessDB(
+ gcmPTR2INT(record->data), status);
+ break;
+
+- case gcvDB_SHARED_INFO:
+- status = gckOS_FreeMemory(Kernel->os, record->physical);
+- break;
++ case gcvDB_SHARED_INFO:
++ status = gckOS_FreeMemory(Kernel->os, record->physical);
++ break;
+
+ default:
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DATABASE,
+diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu.c
+index 43c9297..c7f67c7 100644
+--- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu.c
++++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu.c
+@@ -97,6 +97,14 @@ static gcsMirrorPageTable_PTR mirrorPageTable = gcvNULL;
+ static gctPOINTER mirrorPageTableMutex = gcvNULL;
+ #endif
+
++typedef struct _gcsDynamicSpaceNode * gcsDynamicSpaceNode_PTR;
++typedef struct _gcsDynamicSpaceNode
++{
++ gctUINT32 start;
++ gctINT32 entries;
++}
++gcsDynamicSpaceNode;
++
+ static void
+ _WritePageEntry(
+ IN gctUINT32_PTR PageEntry,
+@@ -482,30 +490,117 @@ OnError:
+ }
+
+ static gceSTATUS
++_FindDynamicSpace(
++ IN gckMMU Mmu,
++ OUT gcsDynamicSpaceNode_PTR *Array,
++ OUT gctINT * Size
++ )
++{
++ gceSTATUS status = gcvSTATUS_OK;
++ gctPOINTER pointer = gcvNULL;
++ gcsDynamicSpaceNode_PTR array = gcvNULL;
++ gctINT size = 0;
++ gctINT i = 0, nodeStart = -1, nodeEntries = 0;
++
++ /* Allocate memory for the array. */
++ gcmkONERROR(gckOS_Allocate(Mmu->os,
++ gcmSIZEOF(*array) * (gcdMMU_MTLB_ENTRY_NUM / 2),
++ &pointer));
++
++ array = (gcsDynamicSpaceNode_PTR)pointer;
++
++ /* Loop all the entries. */
++ while (i < gcdMMU_MTLB_ENTRY_NUM)
++ {
++ if (!Mmu->mtlbLogical[i])
++ {
++ if (nodeStart < 0)
++ {
++ /* This is the first entry of the dynamic space. */
++ nodeStart = i;
++ nodeEntries = 1;
++ }
++ else
++ {
++ /* Other entries of the dynamic space. */
++ nodeEntries++;
++ }
++ }
++ else if (nodeStart >= 0)
++ {
++ /* Save the previous node. */
++ array[size].start = nodeStart;
++ array[size].entries = nodeEntries;
++ size++;
++
++ /* Reset the start. */
++ nodeStart = -1;
++ nodeEntries = 0;
++ }
++
++ i++;
++ }
++
++ /* Save the previous node. */
++ if (nodeStart >= 0)
++ {
++ array[size].start = nodeStart;
++ array[size].entries = nodeEntries;
++ size++;
++ }
++
++#if gcdMMU_TABLE_DUMP
++ for (i = 0; i < size; i++)
++ {
++ gckOS_Print("%s(%d): [%d]: start=%d, entries=%d.\n",
++ __FUNCTION__, __LINE__,
++ i,
++ array[i].start,
++ array[i].entries);
++ }
++#endif
++
++ *Array = array;
++ *Size = size;
++
++ return gcvSTATUS_OK;
++
++OnError:
++ if (pointer != gcvNULL)
++ {
++ gckOS_Free(Mmu->os, pointer);
++ }
++
++ return status;
++}
++
++static gceSTATUS
+ _SetupDynamicSpace(
+ IN gckMMU Mmu
+ )
+ {
+ gceSTATUS status;
+- gctINT i;
++ gcsDynamicSpaceNode_PTR nodeArray = gcvNULL;
++ gctINT i, nodeArraySize = 0;
+ gctUINT32 physical;
+- gctINT numEntries;
++ gctINT numEntries = 0;
+ gctUINT32_PTR pageTable;
+ gctBOOL acquired = gcvFALSE;
+
+- /* find the start of dynamic address space. */
+- for (i = 0; i < gcdMMU_MTLB_ENTRY_NUM; i++)
++ /* Find all the dynamic address space. */
++ gcmkONERROR(_FindDynamicSpace(Mmu, &nodeArray, &nodeArraySize));
++
++ /* TODO: We only use the largest one for now. */
++ for (i = 0; i < nodeArraySize; i++)
+ {
+- if (!Mmu->mtlbLogical[i])
++ if (nodeArray[i].entries > numEntries)
+ {
+- break;
++ Mmu->dynamicMappingStart = nodeArray[i].start;
++ numEntries = nodeArray[i].entries;
+ }
+ }
+
+- Mmu->dynamicMappingStart = i;
+-
+- /* Number of entries in Master TLB for dynamic mapping. */
+- numEntries = gcdMMU_MTLB_ENTRY_NUM - i;
++ gckOS_Free(Mmu->os, (gctPOINTER)nodeArray);
+
+ Mmu->pageTableSize = numEntries * 4096;
+
+@@ -545,7 +640,9 @@ _SetupDynamicSpace(
+ acquired = gcvTRUE;
+
+ /* Map to Master TLB. */
+- for (; i < gcdMMU_MTLB_ENTRY_NUM; i++)
++ for (i = (gctINT)Mmu->dynamicMappingStart;
++ i < (gctINT)Mmu->dynamicMappingStart + numEntries;
++ i++)
+ {
+ _WritePageEntry(Mmu->mtlbLogical + i,
+ physical
+diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c
+index 8a442a2..8b8bbdc 100644
+--- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c
++++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c
+@@ -2144,6 +2144,9 @@ gckVIDMEM_Unlock(
+
+ if (!Node->Virtual.contiguous
+ && (Node->Virtual.lockeds[Kernel->core] == 1)
++#if gcdENABLE_VG
++ && (Kernel->vg == gcvNULL)
++#endif
+ )
+ {
+ if (Type == gcvSURF_BITMAP)
+diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal.h
+index 7077412..4406d7e 100644
+--- a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal.h
++++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal.h
+@@ -2072,6 +2072,12 @@ gckHARDWARE_QueryPowerManagementState(
+ OUT gceCHIPPOWERSTATE* State
+ );
+
++gceSTATUS
++gckHARDWARE_SetPowerManagement(
++ IN gckHARDWARE Hardware,
++ IN gctBOOL PowerManagement
++ );
++
+ #if gcdENABLE_FSCALE_VAL_ADJUST
+ gceSTATUS
+ gckHARDWARE_SetFscaleValue(
+diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_base.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_base.h
+index ac86399..44689b0 100644
+--- a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_base.h
++++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_base.h
+@@ -74,7 +74,6 @@ typedef struct _gcsSYNC_CONTEXT * gcsSYNC_CONTEXT_PTR;
+ /******************************************************************************\
+ ******************************* Process local storage *************************
+ \******************************************************************************/
+-
+ typedef struct _gcsPLS * gcsPLS_PTR;
+ typedef struct _gcsPLS
+ {
+@@ -107,6 +106,7 @@ typedef struct _gcsPLS
+
+ /* Reference count for destructor. */
+ gcsATOM_PTR reference;
++ gctBOOL bKFS;
+ #if gcdUSE_NPOT_PATCH
+ gctBOOL bNeedSupportNP2Texture;
+ #endif
+@@ -123,7 +123,7 @@ extern gcsPLS gcPLS;
+ typedef struct _gcsTLS * gcsTLS_PTR;
+
+ typedef void (* gctTLS_DESTRUCTOR) (
+- gcsTLS_PTR TLS
++ gcsTLS_PTR
+ );
+
+ typedef struct _gcsTLS
+@@ -658,8 +658,6 @@ gcoHAL_QueryChipFeature(
+ IN gceFEATURE Feature);
+
+ #endif
+-
+-
+ /******************************************************************************\
+ ********************************** gcoOS Object *********************************
+ \******************************************************************************/
+@@ -1775,20 +1773,6 @@ gcoSURF_QueryVidMemNode(
+ OUT gctUINT_PTR Bytes
+ );
+
+-/* Set usage attribute of a surface. */
+-gceSTATUS
+-gcoSURF_SetUsage(
+- IN gcoSURF Surface,
+- IN gceSURF_USAGE Usage
+- );
+-
+-/* Return usage attribute of a surface. */
+-gceSTATUS
+-gcoSURF_QueryUsage(
+- IN gcoSURF Surface,
+- OUT gceSURF_USAGE *Usage
+- );
+-
+ /* Set the color type of the surface. */
+ gceSTATUS
+ gcoSURF_SetColorType(
+@@ -1975,6 +1959,14 @@ gcoSURF_SetWindow(
+ IN gctUINT Height
+ );
+
++/* Set width/height alignment of the surface directly and calculate stride/size. This is only for dri backend now. Please be careful before use. */
++gceSTATUS
++gcoSURF_SetAlignment(
++ IN gcoSURF Surface,
++ IN gctUINT Width,
++ IN gctUINT Height
++ );
++
+ /* Increase reference count of the surface. */
+ gceSTATUS
+ gcoSURF_ReferenceSurface(
+@@ -2009,6 +2001,12 @@ gcoSURF_SetOffset(
+ );
+
+ gceSTATUS
++gcoSURF_GetOffset(
++ IN gcoSURF Surface,
++ OUT gctUINT *Offset
++ );
++
++gceSTATUS
+ gcoSURF_NODE_Cache(
+ IN gcsSURF_NODE_PTR Node,
+ IN gctPOINTER Logical,
+diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_compiler.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_compiler.h
+index 4a0870f..8693c37 100644
+--- a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_compiler.h
++++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_compiler.h
+@@ -36,12 +36,16 @@ extern "C" {
+ #endif
+
+ #ifndef GC_ENABLE_LOADTIME_OPT
+-#define GC_ENABLE_LOADTIME_OPT 1
++#define GC_ENABLE_LOADTIME_OPT 1
+ #endif
+
+ #define TEMP_OPT_CONSTANT_TEXLD_COORD 1
+
+-#define TEMP_SHADER_PATCH 1
++#define TEMP_SHADER_PATCH 1
++
++#define ADD_PRE_ROTATION_TO_VS 0
++
++#define TEMP_INLINE_ALL_EXPANSION 1
+ /******************************* IR VERSION ******************/
+ #define gcdSL_IR_VERSION gcmCC('\0','\0','\0','\1')
+
+@@ -683,6 +687,13 @@ typedef enum _gceSHADER_FLAGS
+ gcvSHADER_USE_ALPHA_KILL = 0x100,
+ #endif
+
++#if ADD_PRE_ROTATION_TO_VS
++ gcvSHADER_VS_PRE_ROTATION = 0x200,
++#endif
++
++#if TEMP_INLINE_ALL_EXPANSION
++ gcvSHADER_INLINE_ALL_EXPANSION = 0x200,
++#endif
+ }
+ gceSHADER_FLAGS;
+
+@@ -771,10 +782,15 @@ typedef enum _gceSHADER_OPTIMIZATION
+ /* optimize varying packing */
+ gcvOPTIMIZATION_VARYINGPACKING = 1 << 22,
+
++#if TEMP_INLINE_ALL_EXPANSION
++ gcvOPTIMIZATION_INLINE_ALL_EXPANSION = 1 << 23,
++#endif
++
+ /* Full optimization. */
+ /* Note that gcvOPTIMIZATION_LOAD_SW_WORKAROUND is off. */
+ gcvOPTIMIZATION_FULL = 0x7FFFFFFF &
+ ~gcvOPTIMIZATION_LOAD_SW_WORKAROUND &
++ ~gcvOPTIMIZATION_INLINE_ALL_EXPANSION &
+ ~gcvOPTIMIZATION_POWER_OPTIMIZATION,
+
+ /* Optimization Unit Test flag. */
+diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_driver.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_driver.h
+index 028bbd1..b056c52 100644
+--- a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_driver.h
++++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_driver.h
+@@ -210,6 +210,9 @@ typedef struct _gcsHAL_QUERY_CHIP_IDENTITY
+ /* Supported minor feature 3 fields. */
+ gctUINT32 chipMinorFeatures3;
+
++ /* Supported minor feature 4 fields. */
++ gctUINT32 chipMinorFeatures4;
++
+ /* Number of streams supported. */
+ gctUINT32 streamCount;
+
+@@ -929,30 +932,30 @@ typedef struct _gcsHAL_INTERFACE
+
+ struct _gcsHAL_GET_SHARED_INFO
+ {
++ /* Process id. */
+ IN gctUINT32 pid;
++
++ /* Data id. */
+ IN gctUINT32 dataId;
+- /* gcuVIDMEM_NODE_PTR */
+- IN gctUINT64 node;
+- /* gctUINT8_PTR */
+- OUT gctUINT64 data;
+- /* fix size. gctUINT8_PTR*/
+- OUT gctUINT64 nodeData;
+- gctUINT64 size;
+- IN gceVIDMEM_NODE_SHARED_INFO_TYPE infoType;
++
++ /* Data size. */
++ IN gctSIZE_T bytes;
++
++ /* Pointer to save the shared data. */
++ OUT gctPOINTER data;
+ }
+ GetSharedInfo;
+
+ struct _gcsHAL_SET_SHARED_INFO
+ {
++ /* Data id. */
+ IN gctUINT32 dataId;
+- /* gcuVIDMEM_NODE_PTR */
+- IN gctUINT64 node;
+- /* gctUINT8_PTR */
+- IN gctUINT64 data;
+- /* gctUINT8_PTR */
+- IN gctUINT64 nodeData;
+- IN gctUINT64 size;
+- IN gceVIDMEM_NODE_SHARED_INFO_TYPE infoType;
++
++ /* Data to be shared. */
++ IN gctPOINTER data;
++
++ /* Data size. */
++ IN gctSIZE_T bytes;
+ }
+ SetSharedInfo;
+
+diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine.h
+index 249b61b..8481375 100644
+--- a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine.h
++++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine.h
+@@ -323,50 +323,6 @@ gcoSURF_Resolve(
+ IN gcoSURF DestSurface
+ );
+
+-/* Export the render target. */
+-gceSTATUS
+-gcoSURF_ExportRenderTarget(
+- IN gcoSURF SrcSurface
+-);
+-
+-/* Import the render target. */
+-gceSTATUS
+-gcoSURF_ImportRenderTarget(
+- IN gctUINT32 Pid,
+- IN gcoSURF SrcSurface
+-);
+-
+-/* Save the Resolve info to kernel. */
+-gceSTATUS
+-gcoSURF_PrepareRemoteResolveRect(
+- IN gcoSURF SrcSurface,
+- IN gcsPOINT_PTR SrcOrigin,
+- IN gcsPOINT_PTR DestOrigin,
+- IN gcsPOINT_PTR RectSize
+- );
+-
+-/* Resolve using the rectangle info previously saved in the vid mem node. */
+-gceSTATUS
+-gcoSURF_ResolveFromStoredRect(
+- IN gcoSURF SrcSurface,
+- IN gcoSURF DestSurface
+- );
+-
+-/* Using the info that Process Pid saved to do resolve. */
+-gceSTATUS
+-gcoSURF_RemoteResolveRect(
+- IN gcoSURF SrcSurface,
+- IN gcoSURF DestSurface,
+- IN gctBOOL *resolveDiscarded
+- );
+-
+-/* Return the "resolve submitted indicator" signal. */
+-gceSTATUS
+-gcoSURF_GetRTSignal(
+- IN gcoSURF RTSurface,
+- OUT gctSIGNAL * resolveSubmittedSignal
+- );
+-
+ /* Resolve rectangular area of a surface. */
+ gceSTATUS
+ gcoSURF_ResolveRect(
+@@ -1684,6 +1640,12 @@ gcoTEXTURE_IsRenderable(
+ );
+
+ gceSTATUS
++gcoTEXTURE_IsRenderableEx(
++ IN gcoTEXTURE Texture,
++ IN gctUINT Level
++ );
++
++gceSTATUS
+ gcoTEXTURE_IsComplete(
+ IN gcoTEXTURE Texture,
+ IN gctINT MaxLevel
+@@ -2028,21 +1990,15 @@ gceSTATUS
+ gcoHAL_GetSharedInfo(
+ IN gctUINT32 Pid,
+ IN gctUINT32 DataId,
+- OUT gctUINT8_PTR Data,
+ IN gctSIZE_T Bytes,
+- IN gctUINT64 Node,
+- OUT gctUINT8_PTR NodeData,
+- IN gceVIDMEM_NODE_SHARED_INFO_TYPE SharedInfoType
++ OUT gctPOINTER Data
+ );
+
+ gceSTATUS
+ gcoHAL_SetSharedInfo(
+ IN gctUINT32 DataId,
+- IN gctUINT8_PTR Data,
+- IN gctSIZE_T Bytes,
+- IN gctUINT64 Node,
+- IN gctUINT8_PTR NodeData,
+- IN gceVIDMEM_NODE_SHARED_INFO_TYPE SharedInfoType
++ IN gctPOINTER Data,
++ IN gctSIZE_T Bytes
+ );
+
+ #ifdef __cplusplus
+diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_enum.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_enum.h
+index cf6b425..a1d9ae5 100644
+--- a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_enum.h
++++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_enum.h
+@@ -181,13 +181,6 @@ typedef enum _gceCACHEOPERATION
+ }
+ gceCACHEOPERATION;
+
+-typedef enum _gceVIDMEM_NODE_SHARED_INFO_TYPE
+-{
+- gcvVIDMEM_INFO_GENERIC,
+- gcvVIDMEM_INFO_DIRTY_RECTANGLE
+-}
+-gceVIDMEM_NODE_SHARED_INFO_TYPE;
+-
+ /* Surface types. */
+ typedef enum _gceSURF_TYPE
+ {
+diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h
+index afe83d0..9e2a8db 100644
+--- a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h
++++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h
+@@ -391,15 +391,6 @@
+ #endif
+
+ /*
+- gcdPOWER_MANAGEMENT
+-
+- This define enables the power management code.
+-*/
+-#ifndef gcdPOWER_MANAGEMENT
+-# define gcdPOWER_MANAGEMENT 1
+-#endif
+-
+-/*
+ gcdPOWER_SUSNPEND_WHEN_IDLE
+
+ Set to 1 to make GPU enter gcvPOWER_SUSPEND when idle detected,
+@@ -428,7 +419,7 @@
+ If the value is 0, no timeout will be checked for.
+ */
+ #ifndef gcdGPU_TIMEOUT
+-# if gcdFPGA_BUILD
++#if gcdFPGA_BUILD
+ # define gcdGPU_TIMEOUT 0
+ # else
+ # define gcdGPU_TIMEOUT 20000
+@@ -726,31 +717,13 @@
+
+ Support swap with a specific rectangle.
+
+- Set the rectangle with eglSetSwapRectangleANDROID api.
++ Set the rectangle with eglSetSwapRectangleVIV api.
+ */
+ #ifndef gcdSUPPORT_SWAP_RECTANGLE
+ # define gcdSUPPORT_SWAP_RECTANGLE 0
+ #endif
+
+ /*
+- gcdDEFER_RESOLVES
+-
+- Support deferred resolves for 3D apps.
+-*/
+-#ifndef gcdDEFER_RESOLVES
+-# define gcdDEFER_RESOLVES 0
+-#endif
+-
+-/*
+- gcdCOPYBLT_OPTIMIZATION
+-
+- Combine dirty areas resulting from Android's copyBlt.
+-*/
+-#ifndef gcdCOPYBLT_OPTIMIZATION
+-# define gcdCOPYBLT_OPTIMIZATION 0
+-#endif
+-
+-/*
+ gcdGPU_LINEAR_BUFFER_ENABLED
+
+ Use linear buffer for GPU apps so HWC can do 2D composition.
+diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_version.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_version.h
+index 808fde0..03cb4d6 100644
+--- a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_version.h
++++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_version.h
+@@ -28,7 +28,7 @@
+
+ #define gcvVERSION_PATCH 9
+
+-#define gcvVERSION_BUILD 4651
++#define gcvVERSION_BUILD 6622
+
+ #define gcvVERSION_DATE __DATE__
+
+diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_vg.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_vg.h
+index 5ff0281..2a910e8 100644
+--- a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_vg.h
++++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_vg.h
+@@ -552,6 +552,12 @@ gckVGHARDWARE_QueryPowerManagementState(
+ );
+
+ gceSTATUS
++gckVGHARDWARE_SetPowerManagement(
++ IN gckVGHARDWARE Hardware,
++ IN gctBOOL PowerManagement
++ );
++
++gceSTATUS
+ gckVGHARDWARE_SetPowerOffTimeout(
+ IN gckVGHARDWARE Hardware,
+ IN gctUINT32 Timeout
+diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.c
+index 7168f0e..168987a 100644
+--- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.c
++++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.c
+@@ -304,6 +304,7 @@ gckGALDEVICE_Construct(
+ IN gctINT Signal,
+ IN gctUINT LogFileSize,
+ IN struct device *pdev,
++ IN gctINT PowerManagement,
+ OUT gckGALDEVICE *Device
+ )
+ {
+@@ -538,6 +539,9 @@ gckGALDEVICE_Construct(
+ device->kernels[gcvCORE_MAJOR]->hardware, FastClear, Compression
+ ));
+
++ gcmkONERROR(gckHARDWARE_SetPowerManagement(
++ device->kernels[gcvCORE_MAJOR]->hardware, PowerManagement
++ ));
+
+ #if COMMAND_PROCESSOR_VERSION == 1
+ /* Start the command queue. */
+@@ -593,6 +597,10 @@ gckGALDEVICE_Construct(
+ device
+ ));
+
++ gcmkONERROR(gckHARDWARE_SetPowerManagement(
++ device->kernels[gcvCORE_2D]->hardware, PowerManagement
++ ));
++
+ #if COMMAND_PROCESSOR_VERSION == 1
+ /* Start the command queue. */
+ gcmkONERROR(gckCOMMAND_Start(device->kernels[gcvCORE_2D]->command));
+@@ -624,6 +632,11 @@ gckGALDEVICE_Construct(
+ device->coreMapping[gcvHARDWARE_VG] = gcvCORE_VG;
+ }
+
++
++ gcmkONERROR(gckVGHARDWARE_SetPowerManagement(
++ device->kernels[gcvCORE_VG]->vg->hardware,
++ PowerManagement
++ ));
+ #endif
+ }
+ else
+diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.h b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.h
+index 460f022..d488fc8 100644
+--- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.h
++++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_device.h
+@@ -169,6 +169,7 @@ gceSTATUS gckGALDEVICE_Construct(
+ IN gctINT Signal,
+ IN gctUINT LogFileSize,
+ IN struct device *pdev,
++ IN gctINT PowerManagement,
+ OUT gckGALDEVICE *Device
+ );
+
+diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_driver.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_driver.c
+index 64cace1..183000d 100644
+--- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_driver.c
++++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_driver.c
+@@ -131,6 +131,9 @@ module_param(fastClear, int, 0644);
+ static int compression = -1;
+ module_param(compression, int, 0644);
+
++static int powerManagement = 1;
++module_param(powerManagement, int, 0644);
++
+ static int signal = 48;
+ module_param(signal, int, 0644);
+
+@@ -781,6 +784,9 @@ static int drv_init(struct device *pdev)
+ }
+ #endif
+
++ printk(KERN_INFO "Galcore version %d.%d.%d.%d\n",
++ gcvVERSION_MAJOR, gcvVERSION_MINOR, gcvVERSION_PATCH, gcvVERSION_BUILD);
++
+ if (showArgs)
+ {
+ printk("galcore options:\n");
+@@ -810,7 +816,8 @@ static int drv_init(struct device *pdev)
+ printk(" signal = %d\n", signal);
+ printk(" baseAddress = 0x%08lX\n", baseAddress);
+ printk(" physSize = 0x%08lX\n", physSize);
+- printk(" logFileSize = %d KB \n", logFileSize);
++ printk(" logFileSize = %d KB \n", logFileSize);
++ printk(" powerManagement = %d\n", powerManagement);
+ #if ENABLE_GPU_CLOCK_BY_DRIVER
+ printk(" coreClock = %lu\n", coreClock);
+ #endif
+@@ -833,6 +840,7 @@ static int drv_init(struct device *pdev)
+ bankSize, fastClear, compression, baseAddress, physSize, signal,
+ logFileSize,
+ pdev,
++ powerManagement,
+ &device
+ ));
+
+diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c
+index dfbc699..6a0295d 100644
+--- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c
++++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c
+@@ -55,6 +55,7 @@ const char * _PLATFORM = "\n\0$PLATFORM$Linux$\n";
+ #endif
+
+ #define USER_SIGNAL_TABLE_LEN_INIT 64
++#define gcdSUPPRESS_OOM_MESSAGE 1
+
+ #define MEMORY_LOCK(os) \
+ gcmkVERIFY_OK(gckOS_AcquireMutex( \
+@@ -85,6 +86,12 @@ const char * _PLATFORM = "\n\0$PLATFORM$Linux$\n";
+ #define gcmkNONPAGED_MEMROY_PROT(x) pgprot_noncached(x)
+ #endif
+
++#if gcdSUPPRESS_OOM_MESSAGE
++#define gcdNOWARN __GFP_NOWARN
++#else
++#define gcdNOWARN 0
++#endif
++
+ #define gcdINFINITE_TIMEOUT (60 * 1000)
+ #define gcdDETECT_TIMEOUT 0
+ #define gcdDETECT_DMA_ADDRESS 1
+@@ -261,7 +268,7 @@ _CreateMdl(
+
+ gcmkHEADER_ARG("ProcessID=%d", ProcessID);
+
+- mdl = (PLINUX_MDL)kzalloc(sizeof(struct _LINUX_MDL), GFP_KERNEL | __GFP_NOWARN);
++ mdl = (PLINUX_MDL)kzalloc(sizeof(struct _LINUX_MDL), GFP_KERNEL | gcdNOWARN);
+ if (mdl == gcvNULL)
+ {
+ gcmkFOOTER_NO();
+@@ -322,7 +329,7 @@ _CreateMdlMap(
+
+ gcmkHEADER_ARG("Mdl=0x%X ProcessID=%d", Mdl, ProcessID);
+
+- mdlMap = (PLINUX_MDL_MAP)kmalloc(sizeof(struct _LINUX_MDL_MAP), GFP_KERNEL | __GFP_NOWARN);
++ mdlMap = (PLINUX_MDL_MAP)kmalloc(sizeof(struct _LINUX_MDL_MAP), GFP_KERNEL | gcdNOWARN);
+ if (mdlMap == gcvNULL)
+ {
+ gcmkFOOTER_NO();
+@@ -481,7 +488,7 @@ _NonContiguousAlloc(
+
+ size = NumPages * sizeof(struct page *);
+
+- pages = kmalloc(size, GFP_KERNEL | __GFP_NOWARN);
++ pages = kmalloc(size, GFP_KERNEL | gcdNOWARN);
+
+ if (!pages)
+ {
+@@ -496,7 +503,7 @@ _NonContiguousAlloc(
+
+ for (i = 0; i < NumPages; i++)
+ {
+- p = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_NOWARN);
++ p = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | gcdNOWARN);
+
+ if (!p)
+ {
+@@ -762,7 +769,7 @@ _AllocateIntegerId(
+ int result;
+
+ again:
+- if (idr_pre_get(&Database->idr, GFP_KERNEL | __GFP_NOWARN) == 0)
++ if (idr_pre_get(&Database->idr, GFP_KERNEL | gcdNOWARN) == 0)
+ {
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+@@ -954,7 +961,7 @@ gckOS_Construct(
+ gcmkVERIFY_ARGUMENT(Os != gcvNULL);
+
+ /* Allocate the gckOS object. */
+- os = (gckOS) kmalloc(gcmSIZEOF(struct _gckOS), GFP_KERNEL | __GFP_NOWARN);
++ os = (gckOS) kmalloc(gcmSIZEOF(struct _gckOS), GFP_KERNEL | gcdNOWARN);
+
+ if (os == gcvNULL)
+ {
+@@ -1171,7 +1178,7 @@ _CreateKernelVirtualMapping(
+
+ if (Mdl->contiguous)
+ {
+- pages = kmalloc(sizeof(struct page *) * numPages, GFP_KERNEL | __GFP_NOWARN);
++ pages = kmalloc(sizeof(struct page *) * numPages, GFP_KERNEL | gcdNOWARN);
+
+ if (!pages)
+ {
+@@ -1385,7 +1392,7 @@ gckOS_AllocateMemory(
+ }
+ else
+ {
+- memory = (gctPOINTER) kmalloc(Bytes, GFP_KERNEL | __GFP_NOWARN);
++ memory = (gctPOINTER) kmalloc(Bytes, GFP_KERNEL | gcdNOWARN);
+ }
+
+ if (memory == gcvNULL)
+@@ -1904,7 +1911,7 @@ gckOS_AllocateNonPagedMemory(
+ addr = dma_alloc_coherent(gcvNULL,
+ mdl->numPages * PAGE_SIZE,
+ &mdl->dmaHandle,
+- GFP_KERNEL | __GFP_NOWARN);
++ GFP_KERNEL | gcdNOWARN);
+ }
+ #else
+ size = mdl->numPages * PAGE_SIZE;
+@@ -1915,7 +1922,7 @@ gckOS_AllocateNonPagedMemory(
+ if (page == gcvNULL)
+ #endif
+ {
+- page = alloc_pages(GFP_KERNEL | __GFP_NOWARN, order);
++ page = alloc_pages(GFP_KERNEL | gcdNOWARN, order);
+ }
+
+ if (page == gcvNULL)
+@@ -3848,6 +3855,9 @@ gckOS_AllocatePagedMemoryEx(
+ gctSIZE_T bytes;
+ gctBOOL locked = gcvFALSE;
+ gceSTATUS status;
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
++ gctPOINTER addr = gcvNULL;
++#endif
+
+ gcmkHEADER_ARG("Os=0x%X Contiguous=%d Bytes=%lu", Os, Contiguous, Bytes);
+
+@@ -3873,13 +3883,27 @@ gckOS_AllocatePagedMemoryEx(
+ {
+ /* Get contiguous pages, and suppress warning (stack dump) from kernel when
+ we run out of memory. */
+- mdl->u.contiguousPages =
+- alloc_pages(GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY, GetOrder(numPages));
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
++ addr =
++ alloc_pages_exact(numPages * PAGE_SIZE, GFP_KERNEL | gcdNOWARN | __GFP_NORETRY);
+
++ mdl->u.contiguousPages = addr
++ ? virt_to_page(addr)
++ : gcvNULL;
++
++ mdl->exact = gcvTRUE;
++#else
++ mdl->u.contiguousPages =
++ alloc_pages(GFP_KERNEL | gcdNOWARN | __GFP_NORETRY, GetOrder(numPages));
++#endif
+ if (mdl->u.contiguousPages == gcvNULL)
+ {
+ mdl->u.contiguousPages =
+- alloc_pages(GFP_KERNEL | __GFP_HIGHMEM | __GFP_NOWARN, GetOrder(numPages));
++ alloc_pages(GFP_KERNEL | __GFP_HIGHMEM | gcdNOWARN, GetOrder(numPages));
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
++ mdl->exact = gcvFALSE;
++#endif
+ }
+ }
+ else
+@@ -4024,7 +4048,16 @@ gckOS_FreePagedMemory(
+
+ if (mdl->contiguous)
+ {
+- __free_pages(mdl->u.contiguousPages, GetOrder(mdl->numPages));
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
++ if (mdl->exact == gcvTRUE)
++ {
++ free_pages_exact(page_address(mdl->u.contiguousPages), mdl->numPages * PAGE_SIZE);
++ }
++ else
++#endif
++ {
++ __free_pages(mdl->u.contiguousPages, GetOrder(mdl->numPages));
++ }
+ }
+ else
+ {
+@@ -4859,7 +4892,7 @@ gckOS_MapUserPointer(
+ gcmkVERIFY_ARGUMENT(Size > 0);
+ gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
+
+- buf = kmalloc(Size, GFP_KERNEL | __GFP_NOWARN);
++ buf = kmalloc(Size, GFP_KERNEL | gcdNOWARN);
+ if (buf == gcvNULL)
+ {
+ gcmkTRACE(
+@@ -5274,7 +5307,7 @@ OnError:
+ MEMORY_MAP_LOCK(Os);
+
+ /* Allocate the Info struct. */
+- info = (gcsPageInfo_PTR)kmalloc(sizeof(gcsPageInfo), GFP_KERNEL | __GFP_NOWARN);
++ info = (gcsPageInfo_PTR)kmalloc(sizeof(gcsPageInfo), GFP_KERNEL | gcdNOWARN);
+
+ if (info == gcvNULL)
+ {
+@@ -5283,7 +5316,7 @@ OnError:
+ }
+
+ /* Allocate the array of page addresses. */
+- pages = (struct page **)kmalloc(pageCount * sizeof(struct page *), GFP_KERNEL | __GFP_NOWARN);
++ pages = (struct page **)kmalloc(pageCount * sizeof(struct page *), GFP_KERNEL | gcdNOWARN);
+
+ if (pages == gcvNULL)
+ {
+@@ -6502,7 +6535,7 @@ gckOS_CreateSemaphore(
+ gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
+
+ /* Allocate the semaphore structure. */
+- sem = (struct semaphore *)kmalloc(gcmSIZEOF(struct semaphore), GFP_KERNEL | __GFP_NOWARN);
++ sem = (struct semaphore *)kmalloc(gcmSIZEOF(struct semaphore), GFP_KERNEL | gcdNOWARN);
+ if (sem == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+@@ -6942,6 +6975,7 @@ gckOS_SetGPUPower(
+ #else
+ imx_gpc_power_up_pu(false);
+ #endif
++
+ }
+ /* TODO: Put your code here. */
+ gcmkFOOTER_NO();
+@@ -7255,7 +7289,7 @@ gckOS_CreateSignal(
+ gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
+
+ /* Create an event structure. */
+- signal = (gcsSIGNAL_PTR) kmalloc(sizeof(gcsSIGNAL), GFP_KERNEL | __GFP_NOWARN);
++ signal = (gcsSIGNAL_PTR) kmalloc(sizeof(gcsSIGNAL), GFP_KERNEL | gcdNOWARN);
+
+ if (signal == gcvNULL)
+ {
+@@ -8000,7 +8034,7 @@ gckOS_CreateSemaphoreVG(
+ do
+ {
+ /* Allocate the semaphore structure. */
+- newSemaphore = (struct semaphore *)kmalloc(gcmSIZEOF(struct semaphore), GFP_KERNEL | __GFP_NOWARN);
++ newSemaphore = (struct semaphore *)kmalloc(gcmSIZEOF(struct semaphore), GFP_KERNEL | gcdNOWARN);
+ if (newSemaphore == gcvNULL)
+ {
+ gcmkERR_BREAK(gcvSTATUS_OUT_OF_MEMORY);
+diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.h b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.h
+index e970477..006632c 100644
+--- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.h
++++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.h
+@@ -54,6 +54,9 @@ typedef struct _LINUX_MDL
+ gctINT numPages;
+ gctINT pagedMem;
+ gctBOOL contiguous;
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
++ gctBOOL exact;
++#endif
+ dma_addr_t dmaHandle;
+ PLINUX_MDL_MAP maps;
+ struct _LINUX_MDL * prev;
+--
+1.8.3.2
+