blob: a4f7f7f0a8a178dceb36cc0a9285d6b12037bcf0 [file] [log] [blame]
/****************************************************************************
*
* The MIT License (MIT)
*
* Copyright (c) 2014 - 2018 Vivante Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*****************************************************************************
*
* The GPL License (GPL)
*
* Copyright (C) 2014 - 2018 Vivante Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*****************************************************************************
*
* Note: This software is released under dual MIT and GPL licenses. A
* recipient may use this file under the terms of either the MIT license or
* GPL License. If you wish to use only one license not the other, you can
* indicate your decision by deleting one of the above license notices in your
* version of this file.
*
*****************************************************************************/
#include "gc_hal.h"
#include "gc_hal_kernel.h"
#include "gc_hal_kernel_hardware_command_vg.h"
#include "gc_feature_database.h"
#if gcdENABLE_VG
#define _GC_OBJ_ZONE gcvZONE_HARDWARE
typedef enum
{
gcvPOWER_FLAG_INITIALIZE = 1 << 0,
gcvPOWER_FLAG_STALL = 1 << 1,
gcvPOWER_FLAG_STOP = 1 << 2,
gcvPOWER_FLAG_START = 1 << 3,
gcvPOWER_FLAG_RELEASE = 1 << 4,
gcvPOWER_FLAG_DELAY = 1 << 5,
gcvPOWER_FLAG_SAVE = 1 << 6,
gcvPOWER_FLAG_ACQUIRE = 1 << 7,
gcvPOWER_FLAG_POWER_OFF = 1 << 8,
gcvPOWER_FLAG_CLOCK_OFF = 1 << 9,
gcvPOWER_FLAG_CLOCK_ON = 1 << 10,
gcvPOWER_FLAG_NOP = 1 << 11,
}
gcePOWER_FLAGS;
/******************************************************************************\
********************************* Support Code *********************************
\******************************************************************************/
static gceSTATUS
_ResetGPU(
IN gckOS Os
)
{
gctUINT32 control, idle;
gceSTATUS status;
/* Read register. */
gcmkONERROR(gckOS_ReadRegisterEx(Os,
gcvCORE_VG,
0x00000,
&control));
for (;;)
{
/* Disable clock gating. */
gcmkONERROR(gckOS_WriteRegisterEx(Os,
gcvCORE_VG,
0x00104,
0x00000000));
/* Wait for clock being stable. */
gcmkONERROR(gckOS_Delay(Os, 1));
/* Isolate the GPU. */
control = ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
19:19) - (0 ? 19:19) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 19:19) - (0 ?
19:19) + 1))))))) << (0 ? 19:19))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
19:19) - (0 ? 19:19) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 19:19) - (0 ?
19:19) + 1))))))) << (0 ? 19:19)));
gcmkONERROR(gckOS_WriteRegisterEx(Os,
gcvCORE_VG,
0x00000,
control));
/* Set soft reset. */
gcmkONERROR(gckOS_WriteRegisterEx(Os,
gcvCORE_VG,
0x00000,
((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
12:12) - (0 ? 12:12) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:12) - (0 ?
12:12) + 1))))))) << (0 ? 12:12))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
12:12) - (0 ? 12:12) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:12) - (0 ?
12:12) + 1))))))) << (0 ? 12:12)))));
/* Wait for reset. */
gcmkONERROR(gckOS_Delay(Os, 1));
/* Reset soft reset bit. */
gcmkONERROR(gckOS_WriteRegisterEx(Os,
gcvCORE_VG,
0x00000,
((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
12:12) - (0 ? 12:12) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:12) - (0 ?
12:12) + 1))))))) << (0 ? 12:12))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
12:12) - (0 ? 12:12) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 12:12) - (0 ?
12:12) + 1))))))) << (0 ? 12:12)))));
/* Reset GPU isolation. */
control = ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
19:19) - (0 ? 19:19) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 19:19) - (0 ?
19:19) + 1))))))) << (0 ? 19:19))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ?
19:19) - (0 ? 19:19) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 19:19) - (0 ?
19:19) + 1))))))) << (0 ? 19:19)));
gcmkONERROR(gckOS_WriteRegisterEx(Os,
gcvCORE_VG,
0x00000,
control));
/* Read idle register. */
gcmkONERROR(gckOS_ReadRegisterEx(Os,
gcvCORE_VG,
0x00004,
&idle));
if ((((((gctUINT32) (idle)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ) == 0)
{
continue;
}
/* Read reset register. */
gcmkONERROR(gckOS_ReadRegisterEx(Os,
gcvCORE_VG,
0x00000,
&control));
if (((((((gctUINT32) (control)) >> (0 ? 16:16)) & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 16:16) - (0 ? 16:16) + 1)))))) ) == 0)
|| ((((((gctUINT32) (control)) >> (0 ? 17:17)) & ((gctUINT32) ((((1 ? 17:17) - (0 ? 17:17) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 17:17) - (0 ? 17:17) + 1)))))) ) == 0)
)
{
continue;
}
/* GPU is idle. */
break;
}
/* Success. */
return gcvSTATUS_OK;
OnError:
/* Return the error. */
return status;
}
static gceSTATUS
_IdentifyHardware(
IN gckOS Os,
IN gckVGHARDWARE Hardware,
OUT gceCHIPMODEL * ChipModel,
OUT gctUINT32 * ChipRevision,
OUT gctUINT32 * ChipFeatures,
OUT gctUINT32 * ChipMinorFeatures,
OUT gctUINT32 * ChipMinorFeatures2
)
{
gceSTATUS status;
gctUINT32 chipIdentity;
do
{
/* Read chip identity register. */
gcmkERR_BREAK(gckOS_ReadRegisterEx(Os, gcvCORE_VG, 0x00018, &chipIdentity));
/* Special case for older graphic cores. */
if (((((gctUINT32) (chipIdentity)) >> (0 ? 31:24) & ((gctUINT32) ((((1 ?
31:24) - (0 ? 31:24) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:24) - (0 ?
31:24) + 1)))))) == (0x01 & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 31:24) - (0 ? 31:24) + 1))))))))
{
*ChipModel = gcv500;
*ChipRevision = (((((gctUINT32) (chipIdentity)) >> (0 ? 15:12)) & ((gctUINT32) ((((1 ? 15:12) - (0 ? 15:12) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:12) - (0 ? 15:12) + 1)))))) );
}
else
{
/* Read chip identity register. */
gcmkERR_BREAK(gckOS_ReadRegisterEx(Os, gcvCORE_VG,
0x00020,
(gctUINT32 *) ChipModel));
/* Read CHIP_REV register. */
gcmkERR_BREAK(gckOS_ReadRegisterEx(Os, gcvCORE_VG,
0x00024,
ChipRevision));
}
/* Read chip feature register. */
gcmkERR_BREAK(gckOS_ReadRegisterEx(
Os, gcvCORE_VG, 0x0001C, ChipFeatures
));
/* Read chip minor feature register. */
gcmkERR_BREAK(gckOS_ReadRegisterEx(
Os, gcvCORE_VG, 0x00034, ChipMinorFeatures
));
/* Read chip minor feature register #2. */
gcmkERR_BREAK(gckOS_ReadRegisterEx(
Os, gcvCORE_VG, 0x00074, ChipMinorFeatures2
));
gcmkERR_BREAK(gckOS_ReadRegisterEx(
Os, gcvCORE_VG, 0x000A8, &Hardware->productID
));
gcmkERR_BREAK(gckOS_ReadRegisterEx(
Os, gcvCORE_VG, 0x000E8, &Hardware->ecoID
));
gcmkERR_BREAK(gckOS_ReadRegisterEx(
Os, gcvCORE_VG, 0x00030, &Hardware->customerID
));
gcmkTRACE(
gcvLEVEL_VERBOSE,
"ChipModel=0x%08X\n"
"ChipRevision=0x%08X\n"
"ChipFeatures=0x%08X\n"
"ChipMinorFeatures=0x%08X\n"
"ChipMinorFeatures2=0x%08X\n",
*ChipModel,
*ChipRevision,
*ChipFeatures,
*ChipMinorFeatures,
*ChipMinorFeatures2
);
/* Success. */
return gcvSTATUS_OK;
}
while (gcvFALSE);
/* Return the status. */
return status;
}
#if gcdPOWEROFF_TIMEOUT
void
_VGPowerTimerFunction(
gctPOINTER Data
)
{
gckVGHARDWARE hardware = (gckVGHARDWARE)Data;
gcmkVERIFY_OK(
gckVGHARDWARE_SetPowerManagementState(hardware, gcvPOWER_OFF_TIMEOUT));
}
#endif
/******************************************************************************\
****************************** gckVGHARDWARE API code *****************************
\******************************************************************************/
/*******************************************************************************
**
** gckVGHARDWARE_Construct
**
** Construct a new gckVGHARDWARE object.
**
** INPUT:
**
** gckOS Os
** Pointer to an initialized gckOS object.
**
** OUTPUT:
**
** gckVGHARDWARE * Hardware
** Pointer to a variable that will hold the pointer to the gckVGHARDWARE
** object.
*/
gceSTATUS
gckVGHARDWARE_Construct(
IN gckOS Os,
OUT gckVGHARDWARE * Hardware
)
{
gckVGHARDWARE hardware = gcvNULL;
gceSTATUS status;
gceCHIPMODEL chipModel;
gctUINT32 chipRevision;
gctUINT32 chipFeatures;
gctUINT32 chipMinorFeatures;
gctUINT32 chipMinorFeatures2;
gcsFEATURE_DATABASE * database;
gcmkHEADER_ARG("Os=0x%x Hardware=0x%x ", Os, Hardware);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
gcmkVERIFY_ARGUMENT(Hardware != gcvNULL);
do
{
gcmkERR_BREAK(gckOS_SetGPUPower(Os, gcvCORE_VG, gcvTRUE, gcvTRUE));
status = _ResetGPU(Os);
if (status != gcvSTATUS_OK)
{
gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
"_ResetGPU failed: status=%d\n", status);
}
/* Allocate the gckVGHARDWARE object. */
gcmkERR_BREAK(gckOS_Allocate(Os,
gcmSIZEOF(struct _gckVGHARDWARE), (gctPOINTER *) &hardware
));
/* Identify the hardware. */
gcmkERR_BREAK(_IdentifyHardware(Os, hardware,
&chipModel, &chipRevision,
&chipFeatures, &chipMinorFeatures, &chipMinorFeatures2
));
/* Initialize the gckVGHARDWARE object. */
hardware->object.type = gcvOBJ_HARDWARE;
hardware->os = Os;
/* Set chip identity. */
hardware->chipModel = chipModel;
hardware->chipRevision = chipRevision;
hardware->chipFeatures = chipFeatures;
hardware->chipMinorFeatures = chipMinorFeatures;
hardware->chipMinorFeatures2 = chipMinorFeatures2;
hardware->powerMutex = gcvNULL;
hardware->chipPowerState = gcvPOWER_ON;
hardware->chipPowerStateGlobal = gcvPOWER_ON;
hardware->clockState = gcvTRUE;
hardware->powerState = gcvTRUE;
#if gcdPOWEROFF_TIMEOUT
hardware->powerOffTime = 0;
hardware->powerOffTimeout = gcdPOWEROFF_TIMEOUT;
gcmkVERIFY_OK(gckOS_CreateTimer(Os,
_VGPowerTimerFunction,
(gctPOINTER)hardware,
&hardware->powerOffTimer));
#endif
database = hardware->featureDatabase = gcQueryFeatureDB(
hardware->chipModel,
hardware->chipRevision,
hardware->productID,
hardware->ecoID,
hardware->customerID
);
if (database == gcvNULL)
{
gcmkPRINT("[galcore]: Feature database is not found,"
"chipModel=0x%0x, chipRevision=0x%x, productID=0x%x, ecoID=0x%x",
hardware->chipModel,
hardware->chipRevision,
hardware->productID,
hardware->ecoID);
/* gcmkERR_BREAK(gcvSTATUS_NOT_FOUND); */
}
/* Determine whether FE 2.0 is present. */
hardware->fe20 = ((((gctUINT32) (hardware->chipFeatures)) >> (0 ?
28:28) & ((gctUINT32) ((((1 ? 28:28) - (0 ? 28:28) + 1) == 32) ? ~0U : (~(~0U << ((1 ?
28:28) - (0 ? 28:28) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 28:28) - (0 ?
28:28) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 28:28) - (0 ? 28:28) + 1)))))));
/* Determine whether VG 2.0 is present. */
hardware->vg20 = ((((gctUINT32) (hardware->chipMinorFeatures)) >> (0 ?
13:13) & ((gctUINT32) ((((1 ? 13:13) - (0 ? 13:13) + 1) == 32) ? ~0U : (~(~0U << ((1 ?
13:13) - (0 ? 13:13) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 13:13) - (0 ?
13:13) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 13:13) - (0 ? 13:13) + 1)))))));
/* Determine whether VG 2.1 is present. */
hardware->vg21 = ((((gctUINT32) (hardware->chipMinorFeatures)) >> (0 ?
18:18) & ((gctUINT32) ((((1 ? 18:18) - (0 ? 18:18) + 1) == 32) ? ~0U : (~(~0U << ((1 ?
18:18) - (0 ? 18:18) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 18:18) - (0 ?
18:18) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 18:18) - (0 ? 18:18) + 1)))))));
/* Determine whether fc is present. */
hardware->fc = (((((gctUINT32) (hardware->chipFeatures)) >> (0 ? 0:0 )) & ((gctUINT32) ((((1 ? 0:0 ) - (0 ? 0:0 ) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0 ) - (0 ? 0:0 ) + 1)))))) );
/* Set default event mask. */
hardware->eventMask = 0xFFFFFFFF;
gcmkERR_BREAK(gckOS_AtomConstruct(Os, &hardware->pageTableDirty));
/* Set fast clear to auto. */
gcmkVERIFY_OK(gckVGHARDWARE_SetFastClear(hardware, -1));
gcmkERR_BREAK(gckOS_CreateMutex(Os, &hardware->powerMutex));
/* Enable power management by default. */
hardware->options.powerManagement = gcvTRUE;
/* Return pointer to the gckVGHARDWARE object. */
*Hardware = hardware;
gcmkFOOTER_NO();
/* Success. */
return gcvSTATUS_OK;
}
while (gcvFALSE);
#if gcdPOWEROFF_TIMEOUT
if (hardware != gcvNULL && hardware->powerOffTimer != gcvNULL)
{
gcmkVERIFY_OK(gckOS_StopTimer(Os, hardware->powerOffTimer));
gcmkVERIFY_OK(gckOS_DestroyTimer(Os, hardware->powerOffTimer));
}
#endif
gcmkVERIFY_OK(gckOS_SetGPUPower(Os, gcvCORE_VG, gcvFALSE, gcvFALSE));
if (hardware != gcvNULL && hardware->pageTableDirty != gcvNULL)
{
gcmkVERIFY_OK(gckOS_AtomDestroy(Os, hardware->pageTableDirty));
}
if (hardware != gcvNULL)
{
gcmkVERIFY_OK(gckOS_Free(Os, hardware));
}
gcmkFOOTER();
/* Return the status. */
return status;
}
/*******************************************************************************
**
** gckVGHARDWARE_Destroy
**
** Destroy an gckVGHARDWARE object.
**
** INPUT:
**
** gckVGHARDWARE Hardware
** Pointer to the gckVGHARDWARE object that needs to be destroyed.
**
** OUTPUT:
**
** Nothing.
*/
gceSTATUS
gckVGHARDWARE_Destroy(
IN gckVGHARDWARE Hardware
)
{
gceSTATUS status;
gcmkHEADER_ARG("Hardware=0x%x ", Hardware);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
/* Mark the object as unknown. */
Hardware->object.type = gcvOBJ_UNKNOWN;
if (Hardware->powerMutex != gcvNULL)
{
gcmkVERIFY_OK(gckOS_DeleteMutex(
Hardware->os, Hardware->powerMutex));
}
#if gcdPOWEROFF_TIMEOUT
gcmkVERIFY_OK(gckOS_StopTimer(Hardware->os, Hardware->powerOffTimer));
gcmkVERIFY_OK(gckOS_DestroyTimer(Hardware->os, Hardware->powerOffTimer));
#endif
if (Hardware->pageTableDirty != gcvNULL)
{
gcmkVERIFY_OK(gckOS_AtomDestroy(Hardware->os, Hardware->pageTableDirty));
}
/* Free the object. */
status = gckOS_Free(Hardware->os, Hardware);
gcmkFOOTER();
return status;
}
/*******************************************************************************
**
** gckVGHARDWARE_QueryMemory
**
** Query the amount of memory available on the hardware.
**
** INPUT:
**
** gckVGHARDWARE Hardware
** Pointer to the gckVGHARDWARE object.
**
** OUTPUT:
**
** gctSIZE_T * InternalSize
** Pointer to a variable that will hold the size of the internal video
** memory in bytes. If 'InternalSize' is gcvNULL, no information of the
** internal memory will be returned.
**
** gctUINT32 * InternalBaseAddress
** Pointer to a variable that will hold the hardware's base address for
** the internal video memory. This pointer cannot be gcvNULL if
** 'InternalSize' is also non-gcvNULL.
**
** gctUINT32 * InternalAlignment
** Pointer to a variable that will hold the hardware's base address for
** the internal video memory. This pointer cannot be gcvNULL if
** 'InternalSize' is also non-gcvNULL.
**
** gctSIZE_T * ExternalSize
** Pointer to a variable that will hold the size of the external video
** memory in bytes. If 'ExternalSize' is gcvNULL, no information of the
** external memory will be returned.
**
** gctUINT32 * ExternalBaseAddress
** Pointer to a variable that will hold the hardware's base address for
** the external video memory. This pointer cannot be gcvNULL if
** 'ExternalSize' is also non-gcvNULL.
**
** gctUINT32 * ExternalAlignment
** Pointer to a variable that will hold the hardware's base address for
** the external video memory. This pointer cannot be gcvNULL if
** 'ExternalSize' is also non-gcvNULL.
**
** gctUINT32 * HorizontalTileSize
** Number of horizontal pixels per tile. If 'HorizontalTileSize' is
** gcvNULL, no horizontal pixel per tile will be returned.
**
** gctUINT32 * VerticalTileSize
** Number of vertical pixels per tile. If 'VerticalTileSize' is
** gcvNULL, no vertical pixel per tile will be returned.
*/
gceSTATUS
gckVGHARDWARE_QueryMemory(
IN gckVGHARDWARE Hardware,
OUT gctSIZE_T * InternalSize,
OUT gctUINT32 * InternalBaseAddress,
OUT gctUINT32 * InternalAlignment,
OUT gctSIZE_T * ExternalSize,
OUT gctUINT32 * ExternalBaseAddress,
OUT gctUINT32 * ExternalAlignment,
OUT gctUINT32 * HorizontalTileSize,
OUT gctUINT32 * VerticalTileSize
)
{
gcmkHEADER_ARG("Hardware=0x%x InternalSize=0x%x InternalBaseAddress=0x%x InternalAlignment=0x%x"
"ExternalSize=0x%x ExternalBaseAddress=0x%x ExternalAlignment=0x%x HorizontalTileSize=0x%x VerticalTileSize=0x%x",
Hardware, InternalSize, InternalBaseAddress, InternalAlignment,
ExternalSize, ExternalBaseAddress, ExternalAlignment, HorizontalTileSize, VerticalTileSize);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
if (InternalSize != gcvNULL)
{
/* No internal memory. */
*InternalSize = 0;
}
if (ExternalSize != gcvNULL)
{
/* No external memory. */
*ExternalSize = 0;
}
if (HorizontalTileSize != gcvNULL)
{
/* 4x4 tiles. */
*HorizontalTileSize = 4;
}
if (VerticalTileSize != gcvNULL)
{
/* 4x4 tiles. */
*VerticalTileSize = 4;
}
gcmkFOOTER_NO();
/* Success. */
return gcvSTATUS_OK;
}
/*******************************************************************************
**
** gckVGHARDWARE_QueryChipIdentity
**
** Query the identity of the hardware.
**
** INPUT:
**
** gckVGHARDWARE Hardware
** Pointer to the gckVGHARDWARE object.
**
** OUTPUT:
**
** gceCHIPMODEL * ChipModel
** If 'ChipModel' is not gcvNULL, the variable it points to will
** receive the model of the chip.
**
** gctUINT32 * ChipRevision
** If 'ChipRevision' is not gcvNULL, the variable it points to will
** receive the revision of the chip.
**
** gctUINT32 * ChipFeatures
** If 'ChipFeatures' is not gcvNULL, the variable it points to will
** receive the feature set of the chip.
**
** gctUINT32 * ChipMinorFeatures
** If 'ChipMinorFeatures' is not gcvNULL, the variable it points to
** will receive the minor feature set of the chip.
**
** gctUINT32 * ChipMinorFeatures2
** If 'ChipMinorFeatures2' is not gcvNULL, the variable it points to
** will receive the minor feature set of the chip.
**
*/
gceSTATUS
gckVGHARDWARE_QueryChipIdentity(
IN gckVGHARDWARE Hardware,
OUT gceCHIPMODEL * ChipModel,
OUT gctUINT32 * ChipRevision,
OUT gctUINT32 * ProductID,
OUT gctUINT32 * EcoID,
OUT gctUINT32* CustomerID,
OUT gctUINT32* ChipFeatures,
OUT gctUINT32* ChipMinorFeatures,
OUT gctUINT32* ChipMinorFeatures2
)
{
gcmkHEADER_ARG("Hardware=0x%x ChipModel=0x%x ChipRevision=0x%x ChipFeatures = 0x%x ChipMinorFeatures = 0x%x ChipMinorFeatures2 = 0x%x",
Hardware, ChipModel, ChipRevision, ChipFeatures, ChipMinorFeatures, ChipMinorFeatures2);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
/* Return chip model. */
if (ChipModel != gcvNULL)
{
*ChipModel = Hardware->chipModel;
}
/* Return revision number. */
if (ChipRevision != gcvNULL)
{
*ChipRevision = Hardware->chipRevision;
}
/* Return feature set. */
if (ChipFeatures != gcvNULL)
{
gctUINT32 features = Hardware->chipFeatures;
if (Hardware->fc)
{
features = ((((gctUINT32) (features)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
0:0))) | (((gctUINT32) ((gctUINT32) (Hardware->options.allowFastClear) & ((gctUINT32) ((((1 ?
0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
0:0)));
}
/* Mark 2D pipe as available for GC500.0 since it did not have this *\
\* bit. */
if ((Hardware->chipModel == gcv500)
&& (Hardware->chipRevision == 0)
)
{
features = ((((gctUINT32) (features)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
9:9) - (0 ? 9:9) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ?
9:9))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9)));
}
/* Mark 2D pipe as available for GC300 since it did not have this *\
\* bit. */
if (Hardware->chipModel == gcv300)
{
features = ((((gctUINT32) (features)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
9:9) - (0 ? 9:9) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ?
9:9))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9)));
}
*ChipFeatures = features;
}
/* Return minor feature set. */
if (ChipMinorFeatures != gcvNULL)
{
*ChipMinorFeatures = Hardware->chipMinorFeatures;
}
/* Return minor feature set #2. */
if (ChipMinorFeatures2 != gcvNULL)
{
*ChipMinorFeatures2 = Hardware->chipMinorFeatures2;
}
if (ProductID != gcvNULL)
{
*ProductID = Hardware->productID;
}
if (EcoID != gcvNULL)
{
*EcoID = Hardware->ecoID;
}
if (CustomerID != gcvNULL)
{
*CustomerID = Hardware->customerID;
}
gcmkFOOTER_NO();
/* Success. */
return gcvSTATUS_OK;
}
/*******************************************************************************
**
** gckVGHARDWARE_ConvertFormat
**
** Convert an API format to hardware parameters.
**
** INPUT:
**
** gckVGHARDWARE Hardware
** Pointer to the gckVGHARDWARE object.
**
** gceSURF_FORMAT Format
** API format to convert.
**
** OUTPUT:
**
** gctUINT32 * BitsPerPixel
** Pointer to a variable that will hold the number of bits per pixel.
**
** gctUINT32 * BytesPerTile
** Pointer to a variable that will hold the number of bytes per tile.
*/
gceSTATUS
gckVGHARDWARE_ConvertFormat(
IN gckVGHARDWARE Hardware,
IN gceSURF_FORMAT Format,
OUT gctUINT32 * BitsPerPixel,
OUT gctUINT32 * BytesPerTile
)
{
gctUINT32 bitsPerPixel;
gctUINT32 bytesPerTile;
gcmkHEADER_ARG("Hardware=0x%x Format=0x%x BitsPerPixel=0x%x BytesPerTile = 0x%x",
Hardware, Format, BitsPerPixel, BytesPerTile);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
/* Dispatch on format. */
switch (Format)
{
case gcvSURF_A1:
case gcvSURF_L1:
/* 1-bpp format. */
bitsPerPixel = 1;
bytesPerTile = (1 * 4 * 4) / 8;
break;
case gcvSURF_A4:
/* 4-bpp format. */
bitsPerPixel = 4;
bytesPerTile = (4 * 4 * 4) / 8;
break;
case gcvSURF_INDEX8:
case gcvSURF_A8:
case gcvSURF_L8:
/* 8-bpp format. */
bitsPerPixel = 8;
bytesPerTile = (8 * 4 * 4) / 8;
break;
case gcvSURF_YV12:
/* 12-bpp planar YUV formats. */
bitsPerPixel = 12;
bytesPerTile = (12 * 4 * 4) / 8;
break;
case gcvSURF_NV12:
/* 12-bpp planar YUV formats. */
bitsPerPixel = 12;
bytesPerTile = (12 * 4 * 4) / 8;
break;
/* 4444 variations. */
case gcvSURF_X4R4G4B4:
case gcvSURF_A4R4G4B4:
case gcvSURF_R4G4B4X4:
case gcvSURF_R4G4B4A4:
case gcvSURF_B4G4R4X4:
case gcvSURF_B4G4R4A4:
case gcvSURF_X4B4G4R4:
case gcvSURF_A4B4G4R4:
/* 1555 variations. */
case gcvSURF_X1R5G5B5:
case gcvSURF_A1R5G5B5:
case gcvSURF_R5G5B5X1:
case gcvSURF_R5G5B5A1:
case gcvSURF_X1B5G5R5:
case gcvSURF_A1B5G5R5:
case gcvSURF_B5G5R5X1:
case gcvSURF_B5G5R5A1:
/* 565 variations. */
case gcvSURF_R5G6B5:
case gcvSURF_B5G6R5:
case gcvSURF_A8L8:
case gcvSURF_YUY2:
case gcvSURF_UYVY:
case gcvSURF_D16:
/* 16-bpp format. */
bitsPerPixel = 16;
bytesPerTile = (16 * 4 * 4) / 8;
break;
case gcvSURF_X8R8G8B8:
case gcvSURF_A8R8G8B8:
case gcvSURF_X8B8G8R8:
case gcvSURF_A8B8G8R8:
case gcvSURF_R8G8B8X8:
case gcvSURF_R8G8B8A8:
case gcvSURF_B8G8R8X8:
case gcvSURF_B8G8R8A8:
case gcvSURF_D32:
/* 32-bpp format. */
bitsPerPixel = 32;
bytesPerTile = (32 * 4 * 4) / 8;
break;
case gcvSURF_D24S8:
/* 24-bpp format. */
bitsPerPixel = 32;
bytesPerTile = (32 * 4 * 4) / 8;
break;
case gcvSURF_DXT1:
case gcvSURF_ETC1:
bitsPerPixel = 4;
bytesPerTile = (4 * 4 * 4) / 8;
break;
case gcvSURF_DXT2:
case gcvSURF_DXT3:
case gcvSURF_DXT4:
case gcvSURF_DXT5:
bitsPerPixel = 8;
bytesPerTile = (8 * 4 * 4) / 8;
break;
default:
/* Invalid format. */
gcmkFOOTER_NO();
return gcvSTATUS_INVALID_ARGUMENT;
}
/* Set the result. */
if (BitsPerPixel != gcvNULL)
{
* BitsPerPixel = bitsPerPixel;
}
if (BytesPerTile != gcvNULL)
{
* BytesPerTile = bytesPerTile;
}
gcmkFOOTER_NO();
/* Success. */
return gcvSTATUS_OK;
}
/*******************************************************************************
**
** gckVGHARDWARE_SplitMemory
**
** Split a hardware specific memory address into a pool and offset.
**
** INPUT:
**
** gckVGHARDWARE Hardware
** Pointer to the gckVGHARDWARE object.
**
** gctUINT32 Address
** Address in hardware specific format.
**
** OUTPUT:
**
** gcePOOL * Pool
** Pointer to a variable that will hold the pool type for the address.
**
** gctUINT32 * Offset
** Pointer to a variable that will hold the offset for the address.
*/
gceSTATUS
gckVGHARDWARE_SplitMemory(
IN gckVGHARDWARE Hardware,
IN gctUINT32 Address,
OUT gcePOOL * Pool,
OUT gctUINT32 * Offset
)
{
gcmkHEADER_ARG("Hardware=0x%x Address=0x%x Pool=0x%x Offset = 0x%x",
Hardware, Address, Pool, Offset);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
gcmkVERIFY_ARGUMENT(Pool != gcvNULL);
gcmkVERIFY_ARGUMENT(Offset != gcvNULL);
/* Dispatch on memory type. */
switch ((((((gctUINT32) (Address)) >> (0 ? 1:0)) & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:0) - (0 ? 1:0) + 1)))))) ))
{
case 0x0:
/* System memory. */
*Pool = gcvPOOL_SYSTEM;
break;
case 0x2:
/* Virtual memory. */
*Pool = gcvPOOL_VIRTUAL;
break;
default:
/* Invalid memory type. */
gcmkFOOTER_NO();
return gcvSTATUS_INVALID_ARGUMENT;
}
/* Return offset of address. */
*Offset = ((((gctUINT32) (Address)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
1:0) - (0 ? 1:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ?
1:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 1:0) - (0 ?
1:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ?
1:0)));
gcmkFOOTER_NO();
/* Success. */
return gcvSTATUS_OK;
}
/*******************************************************************************
**
** gckVGHARDWARE_Execute
**
** Kickstart the hardware's command processor with an initialized command
** buffer.
**
** INPUT:
**
** gckVGHARDWARE Hardware
** Pointer to the gckVGHARDWARE object.
**
** gctUINT32 Address
** Address of the command buffer.
**
** gctSIZE_T Count
** Number of command-sized data units to be executed.
**
** OUTPUT:
**
** Nothing.
*/
gceSTATUS
gckVGHARDWARE_Execute(
IN gckVGHARDWARE Hardware,
IN gctUINT32 Address,
IN gctUINT32 Count
)
{
gceSTATUS status;
gcmkHEADER_ARG("Hardware=0x%x Address=0x%x Count=0x%x",
Hardware, Address, Count);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
do
{
/* Enable all events. */
gcmkERR_BREAK(gckOS_WriteRegisterEx(
Hardware->os,
gcvCORE_VG,
0x00014,
Hardware->eventMask
));
if (Hardware->fe20)
{
/* Write address register. */
gcmkERR_BREAK(gckOS_WriteRegisterEx(
Hardware->os,
gcvCORE_VG,
0x00500,
gcmkFIXADDRESS(Address)
));
/* Write control register. */
gcmkERR_BREAK(gckOS_WriteRegisterEx(
Hardware->os,
gcvCORE_VG,
0x00504,
Count
));
}
else
{
/* Write address register. */
gcmkERR_BREAK(gckOS_WriteRegisterEx(
Hardware->os,
gcvCORE_VG,
0x00654,
gcmkFIXADDRESS(Address)
));
/* Write control register. */
gcmkERR_BREAK(gckOS_WriteRegisterEx(
Hardware->os,
gcvCORE_VG,
0x00658,
((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
16:16) - (0 ? 16:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 16:16) - (0 ?
16:16) + 1))))))) << (0 ? 16:16))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ?
16:16) - (0 ? 16:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 16:16) - (0 ?
16:16) + 1))))))) << (0 ? 16:16))) |
((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
15:0))) | (((gctUINT32) ((gctUINT32) (Count) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
15:0)))
));
}
/* Success. */
gcmkFOOTER();
return gcvSTATUS_OK;
}
while (gcvFALSE);
gcmkFOOTER();
/* Return the status. */
return status;
}
/*******************************************************************************
**
** gckVGHARDWARE_AlignToTile
**
** Align the specified width and height to tile boundaries.
**
** INPUT:
**
** gckVGHARDWARE Hardware
** Pointer to an gckVGHARDWARE object.
**
** gceSURF_TYPE Type
** Type of alignment.
**
** gctUINT32 * Width
** Pointer to the width to be aligned. If 'Width' is gcvNULL, no width
** will be aligned.
**
** gctUINT32 * Height
** Pointer to the height to be aligned. If 'Height' is gcvNULL, no height
** will be aligned.
**
** OUTPUT:
**
** gctUINT32 * Width
** Pointer to a variable that will receive the aligned width.
**
** gctUINT32 * Height
** Pointer to a variable that will receive the aligned height.
*/
gceSTATUS
gckVGHARDWARE_AlignToTile(
IN gckVGHARDWARE Hardware,
IN gceSURF_TYPE Type,
IN OUT gctUINT32 * Width,
IN OUT gctUINT32 * Height
)
{
gcmkHEADER_ARG("Hardware=0x%x Type=0x%x Width=0x%x Height=0x%x",
Hardware, Type, Width, Height);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
if (Width != gcvNULL)
{
/* Align the width. */
*Width = gcmALIGN(*Width, (Type == gcvSURF_TEXTURE) ? 4 : 16);
}
if (Height != gcvNULL)
{
/* Special case for VG images. */
if ((*Height == 0) && (Type == gcvSURF_IMAGE))
{
*Height = 4;
}
else
{
/* Align the height. */
*Height = gcmALIGN(*Height, 4);
}
}
gcmkFOOTER_NO();
/* Success. */
return gcvSTATUS_OK;
}
/*******************************************************************************
**
** gckVGHARDWARE_ConvertLogical
**
** Convert a logical system address into a hardware specific address.
**
** INPUT:
**
** gckVGHARDWARE Hardware
** Pointer to an gckVGHARDWARE object.
**
** gctPOINTER Logical
** Logical address to convert.
**
** gctBOOL InUserSpace
** gcvTRUE if the memory in user space.
**
** gctUINT32* Address
** Return hardware specific address.
**
** OUTPUT:
**
** Nothing.
*/
gceSTATUS
gckVGHARDWARE_ConvertLogical(
IN gckVGHARDWARE Hardware,
IN gctPOINTER Logical,
IN gctBOOL InUserSpace,
OUT gctUINT32 * Address
)
{
gctPHYS_ADDR_T physical;
gctUINT32 address;
gceSTATUS status;
gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x InUserSpace=%d Address=0x%x",
Hardware, Logical, InUserSpace, Address);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
gcmkVERIFY_ARGUMENT(Address != gcvNULL);
do
{
/* Convert logical address into a physical address. */
if (InUserSpace)
{
gcmkERR_BREAK(gckOS_UserLogicalToPhysical(
Hardware->os, Logical, &physical
));
}
else
{
gcmkERR_BREAK(gckOS_GetPhysicalAddress(
Hardware->os, Logical, &physical
));
}
gcmkSAFECASTPHYSADDRT(address, physical);
/* Return hardware specific address. */
*Address = ((((gctUINT32) (address)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
1:0) - (0 ? 1:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ?
1:0))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0)));
/* Success. */
gcmkFOOTER();
return gcvSTATUS_OK;
}
while (gcvFALSE);
gcmkFOOTER();
/* Return the status. */
return status;
}
/*******************************************************************************
**
** gckVGHARDWARE_QuerySystemMemory
**
** Query the command buffer alignment and number of reserved bytes.
**
** INPUT:
**
** gckVGHARDWARE Harwdare
** Pointer to an gckVGHARDWARE object.
**
** OUTPUT:
**
** gctSIZE_T * SystemSize
** Pointer to a variable that receives the maximum size of the system
** memory.
**
** gctUINT32 * SystemBaseAddress
** Poinetr to a variable that receives the base address for system
** memory.
*/
gceSTATUS gckVGHARDWARE_QuerySystemMemory(
IN gckVGHARDWARE Hardware,
OUT gctSIZE_T * SystemSize,
OUT gctUINT32 * SystemBaseAddress
)
{
gcmkHEADER_ARG("Hardware=0x%x SystemSize=0x%x SystemBaseAddress=0x%x",
Hardware, SystemSize, SystemBaseAddress);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
if (SystemSize != gcvNULL)
{
/* Maximum system memory can be 2GB. */
*SystemSize = (gctSIZE_T)(1 << 31);
}
if (SystemBaseAddress != gcvNULL)
{
/* Set system memory base address. */
*SystemBaseAddress = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
1:0) - (0 ? 1:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ?
1:0))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0)));
}
gcmkFOOTER_NO();
/* Success. */
return gcvSTATUS_OK;
}
/*******************************************************************************
**
** gckVGHARDWARE_SetMMU
**
** Set the page table base address.
**
** INPUT:
**
** gckVGHARDWARE Harwdare
** Pointer to an gckVGHARDWARE object.
**
** gctPOINTER Logical
** Logical address of the page table.
**
** OUTPUT:
**
** Nothing.
*/
gceSTATUS gckVGHARDWARE_SetMMU(
IN gckVGHARDWARE Hardware,
IN gctPOINTER Logical
)
{
gceSTATUS status;
gctUINT32 address = 0;
gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x",
Hardware, Logical);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
do
{
/* Convert the logical address into an hardware address. */
gcmkERR_BREAK(gckVGHARDWARE_ConvertLogical(Hardware, Logical,
gcvFALSE, &address));
/* Write the AQMemoryFePageTable register. */
gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
0x00400,
gcmkFIXADDRESS(address)));
/* Write the AQMemoryTxPageTable register. */
gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
0x00404,
gcmkFIXADDRESS(address)));
/* Write the AQMemoryPePageTable register. */
gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
0x00408,
gcmkFIXADDRESS(address)));
/* Write the AQMemoryPezPageTable register. */
gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
0x0040C,
gcmkFIXADDRESS(address)));
/* Write the AQMemoryRaPageTable register. */
gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
0x00410,
gcmkFIXADDRESS(address)));
}
while (gcvFALSE);
gcmkFOOTER();
/* Return the status. */
return status;
}
/*******************************************************************************
**
** gckVGHARDWARE_FlushMMU
**
** Flush the page table.
**
** INPUT:
**
** gckVGHARDWARE Harwdare
** Pointer to an gckVGHARDWARE object.
**
** OUTPUT:
**
** Nothing.
*/
gceSTATUS gckVGHARDWARE_FlushMMU(
IN gckVGHARDWARE Hardware
)
{
gceSTATUS status;
gckVGCOMMAND command;
gcmkHEADER_ARG("Hardware=0x%x ", Hardware);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
do
{
gcsCMDBUFFER_PTR commandBuffer;
gctUINT32_PTR buffer;
/* Create a shortcut to the command buffer object. */
command = Hardware->kernel->command;
/* Allocate command buffer space. */
gcmkERR_BREAK(gckVGCOMMAND_Allocate(
command, 8, &commandBuffer, (gctPOINTER *) &buffer
));
gckOS_WriteMemory(
Hardware->os,
&buffer[0],
((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ?
31:27) - (0 ? 31:27) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 31:27) - (0 ?
31:27) + 1))))))) << (0 ? 31:27)))
| ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
15:0) - (0 ? 15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
15:0))) | (((gctUINT32) ((gctUINT32) (0x0E04) & ((gctUINT32) ((((1 ? 15:0) - (0 ?
15:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ?
15:0)))
| ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ?
25:16) - (0 ? 25:16) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 25:16) - (0 ?
25:16) + 1))))))) << (0 ? 25:16)))
);
gckOS_WriteMemory(
Hardware->os,
&buffer[1],
((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ?
0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))
| ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
1:1) - (0 ? 1:1) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ?
1:1))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)))
| ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
2:2) - (0 ? 2:2) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ?
2:2))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2)))
| ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
3:3) - (0 ? 3:3) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ?
3:3))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3)))
| ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
4:4) - (0 ? 4:4) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ?
4:4))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4)))
);
gcmkERR_BREAK(gckVGCOMMAND_Execute(
command,
commandBuffer
));
}
while(gcvFALSE);
gcmkFOOTER();
/* Return the status. */
return status;
}
/*******************************************************************************
**
** gckVGHARDWARE_BuildVirtualAddress
**
** Build a virtual address.
**
** INPUT:
**
** gckVGHARDWARE Harwdare
** Pointer to an gckVGHARDWARE object.
**
** gctUINT32 Index
** Index into page table.
**
** gctUINT32 Offset
** Offset into page.
**
** OUTPUT:
**
** gctUINT32 * Address
** Pointer to a variable receiving te hardware address.
*/
gceSTATUS gckVGHARDWARE_BuildVirtualAddress(
IN gckVGHARDWARE Hardware,
IN gctUINT32 Index,
IN gctUINT32 Offset,
OUT gctUINT32 * Address
)
{
gctUINT32 address;
gcmkHEADER_ARG("Hardware=0x%x Index=0x%x Offset=0x%x Address=0x%x",
Hardware, Index, Offset, Address);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
gcmkVERIFY_ARGUMENT(Address != gcvNULL);
/* Build virtual address. */
address = (Index << 12) | Offset;
/* Set virtual type. */
address = ((((gctUINT32) (address)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
1:0) - (0 ? 1:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ?
1:0))) | (((gctUINT32) (0x2 & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ?
~0U : (~(~0U << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0)));
/* Set the result. */
*Address = address;
gcmkFOOTER_NO();
/* Success. */
return gcvSTATUS_OK;
}
gceSTATUS
gckVGHARDWARE_GetIdle(
IN gckVGHARDWARE Hardware,
OUT gctUINT32 * Data
)
{
gceSTATUS status;
gcmkHEADER_ARG("Hardware=0x%x Data=0x%x", Hardware, Data);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
gcmkVERIFY_ARGUMENT(Data != gcvNULL);
/* Read register and return. */
status = gckOS_ReadRegisterEx(Hardware->os, gcvCORE_VG, 0x00004, Data);
gcmkFOOTER();
return status;
}
gceSTATUS
gckVGHARDWARE_SetFastClear(
IN gckVGHARDWARE Hardware,
IN gctINT Enable
)
{
gctUINT32 debug;
gceSTATUS status;
if (!Hardware->fc)
{
return gcvSTATUS_OK;
}
do
{
if (Enable == -1)
{
Enable = (Hardware->chipModel > gcv500) ||
((Hardware->chipModel == gcv500) && (Hardware->chipRevision >= 3));
}
gcmkERR_BREAK(gckOS_ReadRegisterEx(Hardware->os, gcvCORE_VG,
0x00414,
&debug));
debug = ((((gctUINT32) (debug)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
20:20) - (0 ? 20:20) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 20:20) - (0 ?
20:20) + 1))))))) << (0 ? 20:20))) | (((gctUINT32) ((gctUINT32) (Enable == 0) & ((gctUINT32) ((((1 ?
20:20) - (0 ? 20:20) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 20:20) - (0 ?
20:20) + 1))))))) << (0 ? 20:20)));
#ifdef AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION
debug = ((((gctUINT32) (debug)) & ~(((gctUINT32) (((gctUINT32) ((((1 ?
AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) - (0 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) + 1) == 32) ?
~0U : (~(~0U << ((1 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) - (0 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) + 1))))))) << (0 ?
AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION))) | (((gctUINT32) ((gctUINT32) (Enable == 0) & ((gctUINT32) ((((1 ?
AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) - (0 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) + 1) == 32) ?
~0U : (~(~0U << ((1 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) - (0 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) + 1))))))) << (0 ?
AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION)));
#endif
gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
0x00414,
debug));
Hardware->options.allowFastClear = Enable;
status = gcvFALSE;
}
while (gcvFALSE);
return status;
}
gceSTATUS
gckVGHARDWARE_ReadInterrupt(
IN gckVGHARDWARE Hardware,
OUT gctUINT32_PTR IDs
)
{
gceSTATUS status;
gcmkHEADER_ARG("Hardware=0x%x IDs=0x%x", Hardware, IDs);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
gcmkVERIFY_ARGUMENT(IDs != gcvNULL);
/* Read AQIntrAcknowledge register. */
status = gckOS_ReadRegisterEx(Hardware->os, gcvCORE_VG,
0x00010,
IDs);
gcmkFOOTER();
return status;
}
static gceSTATUS _CommandStall(
gckVGHARDWARE Hardware)
{
gceSTATUS status;
gckVGCOMMAND command;
gcmkHEADER_ARG("Hardware=0x%x", Hardware);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
do
{
gctUINT32_PTR buffer;
command = Hardware->kernel->command;
/* Allocate command buffer space. */
gcmkERR_BREAK(gckVGCOMMAND_Allocate(
command, 8, &command->powerStallBuffer,
(gctPOINTER *) &buffer
));
gcmkERR_BREAK(gckVGCOMMAND_EventCommand(
command, buffer, gcvBLOCK_PIXEL,
command->powerStallInt, gcvNULL));
gcmkERR_BREAK(gckVGCOMMAND_Execute(
command,
command->powerStallBuffer
));
/* Wait the signal. */
gcmkERR_BREAK(gckOS_WaitSignal(
command->os,
command->powerStallSignal,
gcvTRUE,
command->kernel->kernel->timeOut));
}
while(gcvFALSE);
gcmkFOOTER();
/* Return the status. */
return status;
}
/*******************************************************************************
**
** gckHARDWARE_SetPowerManagementState
**
** Set GPU to a specified power state.
**
** INPUT:
**
** gckHARDWARE Harwdare
** Pointer to an gckHARDWARE object.
**
** gceCHIPPOWERSTATE State
** Power State.
**
*/
gceSTATUS
gckVGHARDWARE_SetPowerManagementState(
IN gckVGHARDWARE Hardware,
IN gceCHIPPOWERSTATE State
)
{
gceSTATUS status;
gckVGCOMMAND command = gcvNULL;
gckOS os;
gctUINT flag/*, clock*/;
gctBOOL acquired = gcvFALSE;
gctBOOL stall = gcvTRUE;
gctBOOL commitMutex = gcvFALSE;
gctBOOL mutexAcquired = gcvFALSE;
#if gcdPOWEROFF_TIMEOUT
gctBOOL timeout = gcvFALSE;
gctBOOL isAfter = gcvFALSE;
gctUINT32 currentTime;
#endif
gctBOOL broadcast = gcvFALSE;
gctUINT32 process, thread;
gctBOOL global = gcvFALSE;
#if gcdENABLE_PROFILING
gctUINT64 time, freq, mutexTime, onTime, stallTime, stopTime, delayTime,
initTime, offTime, startTime, totalTime;
#endif
/* State transition flags. */
static const gctUINT flags[4][4] =
{
/* gcvPOWER_ON */
{ /* ON */ 0,
/* OFF */ gcvPOWER_FLAG_ACQUIRE |
gcvPOWER_FLAG_STALL |
gcvPOWER_FLAG_STOP |
gcvPOWER_FLAG_POWER_OFF |
gcvPOWER_FLAG_CLOCK_OFF,
/* IDLE */ gcvPOWER_FLAG_NOP,
/* SUSPEND */ gcvPOWER_FLAG_ACQUIRE |
gcvPOWER_FLAG_STALL |
gcvPOWER_FLAG_STOP |
gcvPOWER_FLAG_CLOCK_OFF,
},
/* gcvPOWER_OFF */
{ /* ON */ gcvPOWER_FLAG_INITIALIZE |
gcvPOWER_FLAG_START |
gcvPOWER_FLAG_RELEASE |
gcvPOWER_FLAG_DELAY,
/* OFF */ 0,
/* IDLE */ gcvPOWER_FLAG_INITIALIZE |
gcvPOWER_FLAG_START |
gcvPOWER_FLAG_RELEASE |
gcvPOWER_FLAG_DELAY,
/* SUSPEND */ gcvPOWER_FLAG_INITIALIZE |
gcvPOWER_FLAG_CLOCK_OFF,
},
/* gcvPOWER_IDLE */
{ /* ON */ gcvPOWER_FLAG_NOP,
/* OFF */ gcvPOWER_FLAG_ACQUIRE |
gcvPOWER_FLAG_STOP |
gcvPOWER_FLAG_POWER_OFF |
gcvPOWER_FLAG_CLOCK_OFF,
/* IDLE */ 0,
/* SUSPEND */ gcvPOWER_FLAG_ACQUIRE |
gcvPOWER_FLAG_STOP |
gcvPOWER_FLAG_CLOCK_OFF,
},
/* gcvPOWER_SUSPEND */
{ /* ON */ gcvPOWER_FLAG_START |
gcvPOWER_FLAG_RELEASE |
gcvPOWER_FLAG_DELAY |
gcvPOWER_FLAG_CLOCK_ON,
/* OFF */ gcvPOWER_FLAG_SAVE |
gcvPOWER_FLAG_POWER_OFF |
gcvPOWER_FLAG_CLOCK_OFF,
/* IDLE */ gcvPOWER_FLAG_START |
gcvPOWER_FLAG_DELAY |
gcvPOWER_FLAG_RELEASE |
gcvPOWER_FLAG_CLOCK_ON,
/* SUSPEND */ 0,
},
};
gcmkHEADER_ARG("Hardware=0x%x State=%d", Hardware, State);
#if gcmIS_DEBUG(gcdDEBUG_TRACE)
gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
"Switching to power state %d",
State);
#endif
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
/* Get the gckOS object pointer. */
os = Hardware->os;
gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
/* Get the gckCOMMAND object pointer. */
gcmkVERIFY_OBJECT(Hardware->kernel, gcvOBJ_KERNEL);
command = Hardware->kernel->command;
gcmkVERIFY_OBJECT(command, gcvOBJ_COMMAND);
if (Hardware->options.powerManagement == gcvFALSE)
{
gcmkFOOTER_NO();
return gcvSTATUS_OK;
}
/* Start profiler. */
gcmkPROFILE_INIT(freq, time);
/* Convert the broadcast power state. */
switch (State)
{
case gcvPOWER_IDLE_BROADCAST:
/* Convert to IDLE and note we are inside broadcast. */
State = gcvPOWER_IDLE;
broadcast = gcvTRUE;
break;
case gcvPOWER_SUSPEND_BROADCAST:
/* Convert to SUSPEND and note we are inside broadcast. */
State = gcvPOWER_SUSPEND;
broadcast = gcvTRUE;
break;
case gcvPOWER_OFF_BROADCAST:
/* Convert to OFF and note we are inside broadcast. */
State = gcvPOWER_OFF;
broadcast = gcvTRUE;
break;
case gcvPOWER_ON_AUTO:
/* Convert to ON and note we are inside recovery. */
State = gcvPOWER_ON;
break;
case gcvPOWER_ON:
case gcvPOWER_IDLE:
case gcvPOWER_SUSPEND:
case gcvPOWER_OFF:
/* Mark as global power management. */
global = gcvTRUE;
break;
#if gcdPOWEROFF_TIMEOUT
case gcvPOWER_OFF_TIMEOUT:
/* Convert to OFF and note we are inside broadcast. */
State = gcvPOWER_OFF;
broadcast = gcvTRUE;
/* Check time out */
timeout = gcvTRUE;
break;
#endif
default:
break;
}
/* Get current process and thread IDs. */
gcmkONERROR(gckOS_GetProcessID(&process));
gcmkONERROR(gckOS_GetThreadID(&thread));
/* Acquire the power mutex. */
if (broadcast)
{
/* Try to acquire the power mutex. */
status = gckOS_AcquireMutex(os, Hardware->powerMutex, 0);
if (status == gcvSTATUS_TIMEOUT)
{
/* Check if we already own this mutex. */
if ((Hardware->powerProcess == process)
&& (Hardware->powerThread == thread)
)
{
/* Bail out on recursive power management. */
gcmkFOOTER_NO();
return gcvSTATUS_OK;
}
else if (State == gcvPOWER_IDLE)
{
/* gcvPOWER_IDLE_BROADCAST is from IST,
** so waiting here will cause deadlock,
** if lock holder call gckCOMMAND_Stall() */
gcmkONERROR(gcvSTATUS_INVALID_REQUEST);
}
else
{
/* Acquire the power mutex. */
gcmkONERROR(gckOS_AcquireMutex(os,
Hardware->powerMutex,
gcvINFINITE));
}
}
}
else
{
/* Acquire the power mutex. */
gcmkONERROR(gckOS_AcquireMutex(os, Hardware->powerMutex, gcvINFINITE));
}
/* Get time until mtuex acquired. */
gcmkPROFILE_QUERY(time, mutexTime);
Hardware->powerProcess = process;
Hardware->powerThread = thread;
mutexAcquired = gcvTRUE;
/* Grab control flags and clock. */
flag = flags[Hardware->chipPowerState][State];
/*clock = clocks[State];*/
#if gcdPOWEROFF_TIMEOUT
if (timeout)
{
gcmkONERROR(gckOS_GetTicks(&currentTime));
gcmkONERROR(
gckOS_TicksAfter(Hardware->powerOffTime, currentTime, &isAfter));
/* powerOffTime is pushed forward, give up.*/
if (isAfter
/* Expect a transition start from IDLE. */
|| (Hardware->chipPowerState == gcvPOWER_ON)
|| (Hardware->chipPowerState == gcvPOWER_OFF)
)
{
/* Release the power mutex. */
gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
/* No need to do anything. */
gcmkFOOTER_NO();
return gcvSTATUS_OK;
}
}
#endif
if (flag == 0)
{
/* Release the power mutex. */
gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
/* No need to do anything. */
gcmkFOOTER_NO();
return gcvSTATUS_OK;
}
/* internal power control */
if (!global)
{
if (Hardware->chipPowerStateGlobal == gcvPOWER_OFF)
{
/* Release the power mutex. */
gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
/* No need to do anything. */
gcmkFOOTER_NO();
return gcvSTATUS_OK;
}
}
else
{
if (flag & gcvPOWER_FLAG_ACQUIRE)
{
/* Acquire the power management semaphore. */
gcmkONERROR(gckOS_AcquireSemaphore(os, command->powerSemaphore));
acquired = gcvTRUE;
/* avoid acquiring again. */
flag &= ~gcvPOWER_FLAG_ACQUIRE;
}
}
if (flag & (gcvPOWER_FLAG_INITIALIZE | gcvPOWER_FLAG_CLOCK_ON))
{
/* Turn on the power. */
gcmkONERROR(gckOS_SetGPUPower(os, gcvCORE_VG, gcvTRUE, gcvTRUE));
/* Mark clock and power as enabled. */
Hardware->clockState = gcvTRUE;
Hardware->powerState = gcvTRUE;
}
/* Get time until powered on. */
gcmkPROFILE_QUERY(time, onTime);
if ((flag & gcvPOWER_FLAG_STALL) && stall)
{
/* Acquire the mutex. */
gcmkONERROR(gckOS_AcquireMutex(
command->os,
command->commitMutex,
gcvINFINITE
));
commitMutex = gcvTRUE;
gcmkONERROR(_CommandStall(Hardware));
}
/* Get time until stalled. */
gcmkPROFILE_QUERY(time, stallTime);
if (flag & gcvPOWER_FLAG_ACQUIRE)
{
/* Acquire the power management semaphore. */
gcmkONERROR(gckOS_AcquireSemaphore(os, command->powerSemaphore));
acquired = gcvTRUE;
}
/* Get time until stopped. */
gcmkPROFILE_QUERY(time, stopTime);
if (flag & gcvPOWER_FLAG_DELAY)
{
/* Wait for the specified amount of time to settle coming back from
** power-off or suspend state. */
gcmkONERROR(gckOS_Delay(os, gcdPOWER_CONTROL_DELAY));
}
/* Get time until delayed. */
gcmkPROFILE_QUERY(time, delayTime);
if (flag & gcvPOWER_FLAG_INITIALIZE)
{
/* Initialize GPU here, replaced by InitializeHardware later */
gcmkONERROR(gckVGHARDWARE_SetMMU(Hardware, Hardware->kernel->mmu->pageTableLogical));
gcmkVERIFY_OK(gckVGHARDWARE_SetFastClear(Hardware, -1));
/* Force the command queue to reload the next context. */
command->currentContext = 0;
}
/* Get time until initialized. */
gcmkPROFILE_QUERY(time, initTime);
if (flag & (gcvPOWER_FLAG_POWER_OFF | gcvPOWER_FLAG_CLOCK_OFF))
{
/* Turn off the GPU power. */
gcmkONERROR(
gckOS_SetGPUPower(os,
gcvCORE_VG,
(flag & gcvPOWER_FLAG_CLOCK_OFF) ? gcvFALSE
: gcvTRUE,
(flag & gcvPOWER_FLAG_POWER_OFF) ? gcvFALSE
: gcvTRUE));
/* Save current hardware power and clock states. */
Hardware->clockState = (flag & gcvPOWER_FLAG_CLOCK_OFF) ? gcvFALSE
: gcvTRUE;
Hardware->powerState = (flag & gcvPOWER_FLAG_POWER_OFF) ? gcvFALSE
: gcvTRUE;
}
/* Get time until off. */
gcmkPROFILE_QUERY(time, offTime);
/* Get time until started. */
gcmkPROFILE_QUERY(time, startTime);
if (flag & gcvPOWER_FLAG_RELEASE)
{
/* Release the power management semaphore. */
gcmkONERROR(gckOS_ReleaseSemaphore(os, command->powerSemaphore));
acquired = gcvFALSE;
}
/* Save the new power state. */
Hardware->chipPowerState = State;
if (global)
{
/* Save the new power state. */
Hardware->chipPowerStateGlobal = State;
}
if (commitMutex)
{
/* Acquire the mutex. */
gcmkVERIFY_OK(gckOS_ReleaseMutex(
command->os,
command->commitMutex
));
}
#if gcdPOWEROFF_TIMEOUT
/* Reset power off time */
gcmkONERROR(gckOS_GetTicks(&currentTime));
Hardware->powerOffTime = currentTime + Hardware->powerOffTimeout;
if (State == gcvPOWER_IDLE)
{
/* Start a timer to power off GPU when GPU enters IDLE or SUSPEND. */
gcmkVERIFY_OK(gckOS_StartTimer(os,
Hardware->powerOffTimer,
Hardware->powerOffTimeout));
}
else
{
gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE, "Cancel powerOfftimer");
/* Cancel running timer when GPU enters ON or OFF. */
gcmkVERIFY_OK(gckOS_StopTimer(os, Hardware->powerOffTimer));
}
#endif
/* Release the power mutex. */
gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
/* Get total time. */
gcmkPROFILE_QUERY(time, totalTime);
#if gcdENABLE_PROFILING
gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
"PROF(%llu): mutex:%llu on:%llu stall:%llu stop:%llu",
freq, mutexTime, onTime, stallTime, stopTime);
gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
" delay:%llu init:%llu off:%llu start:%llu total:%llu",
delayTime, initTime, offTime, startTime, totalTime);
#endif
/* Success. */
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
if (acquired)
{
/* Release semaphore. */
gcmkVERIFY_OK(gckOS_ReleaseSemaphore(Hardware->os,
command->powerSemaphore));
}
if (mutexAcquired)
{
gcmkVERIFY_OK(gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex));
}
if (commitMutex)
{
/* Acquire the mutex. */
gcmkVERIFY_OK(gckOS_ReleaseMutex(
command->os,
command->commitMutex
));
}
/* Return the status. */
gcmkFOOTER();
return status;
}
/*******************************************************************************
**
** gckHARDWARE_QueryPowerManagementState
**
** Get GPU power state.
**
** INPUT:
**
** gckHARDWARE Harwdare
** Pointer to an gckHARDWARE object.
**
** gceCHIPPOWERSTATE* State
** Power State.
**
*/
gceSTATUS
gckVGHARDWARE_QueryPowerManagementState(
IN gckVGHARDWARE Hardware,
OUT gceCHIPPOWERSTATE* State
)
{
gcmkHEADER_ARG("Hardware=0x%x", Hardware);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
gcmkVERIFY_ARGUMENT(State != gcvNULL);
/* Return the statue. */
*State = Hardware->chipPowerState;
/* Success. */
gcmkFOOTER_ARG("*State=%d", *State);
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->options.powerManagement = PowerManagement;
/* Success. */
gcmkFOOTER_NO();
return gcvSTATUS_OK;
}
#if gcdPOWEROFF_TIMEOUT
gceSTATUS
gckVGHARDWARE_SetPowerOffTimeout(
IN gckVGHARDWARE Hardware,
IN gctUINT32 Timeout
)
{
gcmkHEADER_ARG("Hardware=0x%x Timeout=%d", Hardware, Timeout);
Hardware->powerOffTimeout = Timeout;
gcmkFOOTER_NO();
return gcvSTATUS_OK;
}
gceSTATUS
gckVGHARDWARE_QueryPowerOffTimeout(
IN gckVGHARDWARE Hardware,
OUT gctUINT32* Timeout
)
{
gcmkHEADER_ARG("Hardware=0x%x", Hardware);
*Timeout = Hardware->powerOffTimeout;
gcmkFOOTER_ARG("*Timeout=%d", *Timeout);
return gcvSTATUS_OK;
}
#endif
gceSTATUS
gckVGHARDWARE_QueryIdle(
IN gckVGHARDWARE Hardware,
OUT gctBOOL_PTR IsIdle
)
{
gceSTATUS status;
gctUINT32 idle;
gcmkHEADER_ARG("Hardware=0x%x", Hardware);
/* Verify the arguments. */
gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
gcmkVERIFY_ARGUMENT(IsIdle != gcvNULL);
/* We are idle when the power is not ON. */
if (Hardware->chipPowerState != gcvPOWER_ON)
{
*IsIdle = gcvTRUE;
}
else
{
/* Read idle register. */
gcmkONERROR(
gckOS_ReadRegisterEx(Hardware->os, gcvCORE_VG, 0x00004, &idle));
/* Pipe must be idle. */
if (((((((gctUINT32) (idle)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ) != 1)
|| ((((((gctUINT32) (idle)) >> (0 ? 8:8)) & ((gctUINT32) ((((1 ? 8:8) - (0 ? 8:8) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 8:8) - (0 ? 8:8) + 1)))))) ) != 1)
|| ((((((gctUINT32) (idle)) >> (0 ? 9:9)) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 9:9) - (0 ? 9:9) + 1)))))) ) != 1)
|| ((((((gctUINT32) (idle)) >> (0 ? 10:10)) & ((gctUINT32) ((((1 ? 10:10) - (0 ? 10:10) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 10:10) - (0 ? 10:10) + 1)))))) ) != 1)
|| ((((((gctUINT32) (idle)) >> (0 ? 11:11)) & ((gctUINT32) ((((1 ? 11:11) - (0 ? 11:11) + 1) == 32) ? ~0U : (~(~0U << ((1 ? 11:11) - (0 ? 11:11) + 1)))))) ) != 1)
)
{
/* Something is busy. */
*IsIdle = gcvFALSE;
}
else
{
*IsIdle = gcvTRUE;
}
}
/* Success. */
gcmkFOOTER_NO();
return gcvSTATUS_OK;
OnError:
/* Return the status. */
gcmkFOOTER();
return status;
}
#endif /* gcdENABLE_VG */