static int
viv_sync_pt_has_signaled(
    struct sync_pt * sync_pt
    )
{
    gceSTATUS status;
    gctBOOL state;
    struct viv_sync_pt * pt;
    struct viv_sync_timeline * obj;

    pt  = (struct viv_sync_pt *)sync_pt;
    obj = (struct viv_sync_timeline *)sync_pt->parent;

    status = gckOS_QuerySyncPoint(obj->os, pt->sync, &state);

    if (gcmIS_ERROR(status))
    {
        /* Error. */
        return -1;
    }

    return state;
}
gctINT
slScanFieldSelection(
	IN sloCOMPILER Compiler,
	IN gctUINT LineNo,
	IN gctUINT StringNo,
	IN gctSTRING Symbol,
	OUT slsLexToken * Token
	)
{
	gceSTATUS		status;
	sltPOOL_STRING	symbolInPool;

	gcmASSERT(Token);

	Token->lineNo	= LineNo;
	Token->stringNo	= StringNo;

	status = sloCOMPILER_AllocatePoolString(
											Compiler,
											Symbol,
											&symbolInPool);

	if (gcmIS_ERROR(status)) return T_EOF;

	Token->type = T_FIELD_SELECTION;
	Token->u.fieldSelection = symbolInPool;

	gcmVERIFY_OK(sloCOMPILER_Dump(
								Compiler,
								slvDUMP_SCANNER,
								"<TOKEN line=\"%d\" string=\"%d\" type=\"fieldSelection\" symbol=\"%s\" />",
								LineNo,
								StringNo,
								Token->u.fieldSelection));

	return T_FIELD_SELECTION;
}
int
main(
    int argc,
    char * argv[]
    )
{
    gctBOOL         dumpLog      = gcvFALSE;
    gctSTRING       fileName[2]  = { gcvNULL, gcvNULL };
    gcSHADER        shaders[2]   = { gcvNULL, gcvNULL };
    gctINT          i;
    gcoOS           os           = gcvNULL;
    gcoHAL          hal          = gcvNULL;
    gceSTATUS       result;
    gctUINT         option       = 1;   /* no optimization */
    char            outFile[128] = { '\0' };
    char            logVSFile[128] = { '\0' };
    char            logFSFile[128] = { '\0' };

    printf("vCompile version 0.8, Copyright (c) 2005-2011, Vivante Corporation\n\n");

#ifdef _WIN32
    _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) /*| _CRTDBG_CHECK_ALWAYS_DF*/ | _CRTDBG_DELAY_FREE_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
    _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );
    _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDERR );
    /* _CrtSetBreakAlloc(79); */
#endif

#if gcdDEBUG
    gcoOS_SetDebugLevel(gcvLEVEL_VERBOSE);
    gcoOS_SetDebugZone(gcvZONE_COMPILER);
#endif

    for (i = 1; i < argc; i++)
    {
        if (gcmIS_SUCCESS(gcoOS_StrCmp(argv[i], "-l")))
        {
            dumpLog = gcvTRUE;
        }
        else if (gcmIS_SUCCESS(gcoOS_StrCmp(argv[i], "-O0")))
        {
            /* Currently, optimization level is either FULL or NONE */
            option = 0;     /* no optimization */
        }
        else if (gcmIS_SUCCESS(gcoOS_StrCmp(argv[i], "-O")))
        {
            option = 1;     /* full optimization */
        }
        else if (gcmIS_SUCCESS(gcoOS_StrCmp(argv[i], "-OT")))
        {
            /* For optimization unit test */
            if (i++ == argc)
            {
                printf("*ERROR* Optimization testing pattern not provided.\n");
                return 1;
            }
            else
            {
                gctINT testPattern;

                gcmVERIFY_OK(gcoOS_StrToInt(argv[i], (gctINT *)&testPattern));
                if (testPattern < 0)
                {
                    printf("*ERROR* Unknown optimization testing pattern.\n");
                    return 1;
                }
                option = testPattern;
            }
        }
        else
        {
            if (fileName[0] == gcvNULL) fileName[0] = argv[i];
            else if (fileName[1] == gcvNULL) fileName[1] = argv[i];
            else
            {
                printf("*ERROR* Too many shaders.\n");
                return 1;
            }
        }
    }

    if (fileName[0] == gcvNULL)
    {
        printf("Usage: %s [-l] [-O0] shaderFileName [shaderFileName]\n", argv[0]);
        printf("  -l   Generate log file.\n"
               "  -O0  Disable optimizations.\n"
               "\n"
               "If only one shader is specified, that shader will be compiled into a .gcSL\n"
               "file.  If two shaders are specified, those shaders will be compiled and\n"
               "linked into a .gcPGM file. With two shaders, the vertex shader file needs\n"
               "to be the first.\n");
        return 0;
    }

    result = gcoOS_Construct(gcvNULL, &os);
    if (result != gcvSTATUS_OK)
    {
        printf("*ERROR* Failed to construct a new gcoOS object\n");
        return 1;
    }

    result = gcoHAL_Construct(gcvNULL, os, &hal);
    if (result != gcvSTATUS_OK)
    {
        printf("*ERROR* Failed to construct a new gcoHAL object\n");
        goto ErrorExit;
    }

    /* Dump compile log only when one shader is present */
    shaders[0] = CompileFile(os, fileName[0], hal, option, dumpLog && (fileName[1] == gcvNULL), fileName[1] == gcvNULL );

    if (shaders[0] == gcvNULL)
    {
        goto ErrorExit;
    }

    if (fileName[1] != gcvNULL)
    {
        gctSIZE_T programBufferSize = 0;
        gctPOINTER programBuffer = gcvNULL;
        gcsHINT_PTR hints = gcvNULL;
        gceSTATUS status;
        gctPOINTER binary = gcvNULL;
        gctSIZE_T binarySize = 0;
        FILE * f;
        gctSTRING p;

        gcoOS_StrCopySafe(outFile, gcmSIZEOF(outFile), fileName[0]);
        p = strrchr(outFile, '.');
        gcoOS_StrCopySafe(p, gcmSIZEOF(outFile) - (p - outFile), ".gcPGM");

        gcoOS_StrCopySafe(logVSFile, gcmSIZEOF(logVSFile), fileName[0]);
        gcoOS_StrCatSafe(logVSFile, gcmSIZEOF(logVSFile), ".log");

        gcoOS_StrCopySafe(logFSFile, gcmSIZEOF(logFSFile), fileName[1]);
        gcoOS_StrCatSafe(logFSFile, gcmSIZEOF(logFSFile), ".log");

        shaders[1] = CompileFile(os, fileName[1], hal, option, gcvFALSE, gcvFALSE);
        if (shaders[1] == gcvNULL)
        {
            goto ErrorExit;
        }

        if ( dumpLog)
        {
            gcoOS_SetDebugShaderFiles(logVSFile, logFSFile);
        }
        status = gcLinkShaders(shaders[0],
                               shaders[1],
                               gcvSHADER_DEAD_CODE
                               | gcvSHADER_RESOURCE_USAGE
                               | gcvSHADER_OPTIMIZER
                               | gcvSHADER_USE_GL_Z
                               | gcvSHADER_USE_GL_POSITION
                               | gcvSHADER_USE_GL_FACE,
                               &programBufferSize,
                               &programBuffer,
                               &hints);
        if ( dumpLog)
        {
            gcoOS_SetDebugShaderFiles(gcvNULL, gcvNULL);
        }

        if (gcmIS_ERROR(status))
        {
            printf("*ERROR* gcLinkShaders returned errror %d\n", status);
        }
        else
        {
            int ret;
            status = gcSaveProgram(shaders[0],
                                   shaders[1],
                                   programBufferSize,
                                   programBuffer,
                                   hints,
                                   &binary,
                                   &binarySize);

            if (gcmIS_ERROR(status))
            {
                printf("*ERROR* gcSaveShaders returned errror %d\n", status);
            }

            f = fopen(outFile, "wb");
            ret = fwrite(binary, binarySize, 1, f);
            if (ret);
            fclose(f);
        }

        if (programBuffer != gcvNULL) gcoOS_Free(os, programBuffer);
        if (hints         != gcvNULL) gcoOS_Free(os, hints);
        if (binary        != gcvNULL) gcoOS_Free(os, binary);
    }

    gcSHADER_Destroy(shaders[0]);
    if (shaders[1] != gcvNULL) gcSHADER_Destroy(shaders[1]);
    gcoHAL_Destroy(hal);
    gcoOS_Destroy(os);
    return 0;

ErrorExit:
    if (shaders[0] != gcvNULL) gcSHADER_Destroy(shaders[0]);
    if (shaders[1] != gcvNULL) gcSHADER_Destroy(shaders[1]);
    if (gcvNULL != hal) gcoHAL_Destroy(hal);
    if (gcvNULL != os) gcoOS_Destroy(os);

    return 1;
}
static gcSHADER
CompileFile(
    IN gcoOS Os,
    IN gctCONST_STRING FileName,
    IN gcoHAL Hal,
    IN gctUINT Option,
    IN gctBOOL DumpLog,
    IN gctBOOL DumpCompiledShader
    )
{
    gceSTATUS   status;
    gctINT      shaderType;
    gctSIZE_T   sourceSize;
    gctSTRING   source          = gcvNULL;
    gcSHADER    binary;
    gctSTRING   log             = gcvNULL;
    gctSIZE_T   bufferSize;
    gctSTRING   buffer;
    gctSTRING   dataFileName    = gcvNULL;
    gctSIZE_T   length;
    gctFILE     logFile         = gcvNULL;

    gcmASSERT(FileName);

    shaderType = GetShaderType(FileName);

    if (!ReadSource(Os, FileName, &sourceSize, &source)) return gcvNULL;

    status = gcCompileShader(Hal,
                             shaderType,
                             sourceSize, source,
                             &binary,
                             &log);

    if (log != gcvNULL)
    {
        printf("<LOG>\n");
        printf("%s", log);
        printf("</LOG>\n");
    }

    if (gcmIS_ERROR(status))
    {
        gcmASSERT(binary == gcvNULL);
        binary = gcvNULL;

        printf("*ERROR* Failed to compile %s (error: %d)\n", FileName, status);
        goto Exit;
    }

    gcmASSERT(binary != gcvNULL);

    if (DumpLog)
    {
        gcmVERIFY_OK(gcoOS_StrLen(FileName, &length));
        length += 5;
        gcmVERIFY_OK(gcoOS_Allocate(Os, length, (gctPOINTER *) &dataFileName));
        gcmVERIFY_OK(gcoOS_StrCopySafe(dataFileName, length, FileName));
        gcmVERIFY_OK(gcoOS_StrCatSafe(dataFileName, length, ".log"));

        status = gcoOS_Open(Os, dataFileName, gcvFILE_CREATETEXT, &logFile);
        if (gcmIS_ERROR(status))
        {
            logFile = gcvNULL;

            printf("*ERROR* Failed to open the log file: %s\n", dataFileName);
        }
        gcoOS_Free(Os, dataFileName);
    }

    gcmVERIFY_OK(gcSHADER_SetOptimizationOption(binary, Option));

    status = gcOptimizeShader(binary, logFile);

    if (!gcmIS_SUCCESS(status))
    {
        printf("*ERROR* Failed to optimize %s (error: %d)\n", FileName, status);
    }

    if (logFile != gcvNULL)
    {
        gcmVERIFY_OK(gcoOS_Close(Os, logFile));
    }

    if (DumpCompiledShader)
    {
        status = gcSHADER_Save(binary, gcvNULL, &bufferSize);
        if (gcmIS_ERROR(status))
        {
            printf("*ERROR* Failed to get the buffer size of the shader\n");
            goto Exit;
        }

        status = gcoOS_Allocate(Os, bufferSize, (gctPOINTER *) &buffer);
        if (!gcmIS_SUCCESS(status))
        {
            printf("*ERROR* Not enough memory\n");
            goto Exit;
        }

        status = gcSHADER_Save(binary, buffer, &bufferSize);
        if (status != gcvSTATUS_OK)
        {
            printf("*ERROR* Failed to get the buffer size of the shader\n");
            gcoOS_Free(Os, buffer);
            goto Exit;
        }

        OutputShaderData(Os, FileName, bufferSize, buffer);

        gcoOS_Free(Os, buffer);
    }


Exit:
    if (DumpLog && log != gcvNULL)
    {
        printf("**************** Compile Log ****************");
        printf("%s", log);
        printf("*********************************************");
    }

    if (log != gcvNULL) gcoOS_Free(Os, log);

    if (source != gcvNULL) gcoOS_Free(Os, source);

    return binary;
}
/*******************************************************************************
**
**  gckGALDEVICE_Construct
**
**  Constructor.
**
**  INPUT:
**
**  OUTPUT:
**
**      gckGALDEVICE * Device
**          Pointer to a variable receiving the gckGALDEVICE object pointer on
**          success.
*/
gceSTATUS
gckGALDEVICE_Construct(
    IN gctINT IrqLine,
    IN gctUINT32 RegisterMemBase,
    IN gctSIZE_T RegisterMemSize,
    IN gctINT IrqLine2D,
    IN gctUINT32 RegisterMemBase2D,
    IN gctSIZE_T RegisterMemSize2D,
    IN gctINT IrqLineVG,
    IN gctUINT32 RegisterMemBaseVG,
    IN gctSIZE_T RegisterMemSizeVG,
    IN gctUINT32 ContiguousBase,
    IN gctSIZE_T ContiguousSize,
    IN gctSIZE_T BankSize,
    IN gctINT FastClear,
    IN gctINT Compression,
    IN gctUINT32 PhysBaseAddr,
    IN gctUINT32 PhysSize,
    IN gctINT Signal,
    OUT gckGALDEVICE *Device
    )
{
    gctUINT32 internalBaseAddress = 0, internalAlignment = 0;
    gctUINT32 externalBaseAddress = 0, externalAlignment = 0;
    gctUINT32 horizontalTileSize, verticalTileSize;
    struct resource* mem_region;
    gctUINT32 physAddr;
    gctUINT32 physical;
    gckGALDEVICE device;
    gceSTATUS status;
    gctINT32 i;
    gceHARDWARE_TYPE type;
    gckDB sharedDB = gcvNULL;

    gcmkHEADER_ARG("IrqLine=%d RegisterMemBase=0x%08x RegisterMemSize=%u "
                   "IrqLine2D=%d RegisterMemBase2D=0x%08x RegisterMemSize2D=%u "
                   "IrqLineVG=%d RegisterMemBaseVG=0x%08x RegisterMemSizeVG=%u "
                   "ContiguousBase=0x%08x ContiguousSize=%lu BankSize=%lu "
                   "FastClear=%d Compression=%d PhysBaseAddr=0x%x PhysSize=%d Signal=%d",
                   IrqLine, RegisterMemBase, RegisterMemSize,
                   IrqLine2D, RegisterMemBase2D, RegisterMemSize2D,
                   IrqLineVG, RegisterMemBaseVG, RegisterMemSizeVG,
                   ContiguousBase, ContiguousSize, BankSize, FastClear, Compression,
                   PhysBaseAddr, PhysSize, Signal);

    /* Allocate device structure. */
    device = kmalloc(sizeof(struct _gckGALDEVICE), GFP_KERNEL | __GFP_NOWARN);

    if (!device)
    {
        gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
    }

    memset(device, 0, sizeof(struct _gckGALDEVICE));

    if (IrqLine != -1)
    {
        device->requestedRegisterMemBases[gcvCORE_MAJOR]    = RegisterMemBase;
        device->requestedRegisterMemSizes[gcvCORE_MAJOR]    = RegisterMemSize;
    }

    if (IrqLine2D != -1)
    {
        device->requestedRegisterMemBases[gcvCORE_2D]       = RegisterMemBase2D;
        device->requestedRegisterMemSizes[gcvCORE_2D]       = RegisterMemSize2D;
    }

    if (IrqLineVG != -1)
    {
        device->requestedRegisterMemBases[gcvCORE_VG]       = RegisterMemBaseVG;
        device->requestedRegisterMemSizes[gcvCORE_VG]       = RegisterMemSizeVG;
    }

    device->requestedContiguousBase  = 0;
    device->requestedContiguousSize  = 0;


    for (i = 0; i < gcdCORE_COUNT; i++)
    {
        physical = device->requestedRegisterMemBases[i];

        /* Set up register memory region. */
        if (physical != 0)
        {
            mem_region = request_mem_region(
                physical, device->requestedRegisterMemSizes[i], "galcore register region"
                );

#if 0
            if (mem_region == gcvNULL)
            {
                gcmkTRACE_ZONE(
                    gcvLEVEL_ERROR, gcvZONE_DRIVER,
                    "%s(%d): Failed to claim %lu bytes @ 0x%08X\n",
                    __FUNCTION__, __LINE__,
                    physical, device->requestedRegisterMemSizes[i]
                    );

                gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
            }
#endif

            device->registerBases[i] = (gctPOINTER) ioremap_nocache(
                physical, device->requestedRegisterMemSizes[i]);

            if (device->registerBases[i] == gcvNULL)
            {
                gcmkTRACE_ZONE(
                    gcvLEVEL_ERROR, gcvZONE_DRIVER,
                    "%s(%d): Unable to map %ld bytes @ 0x%08X\n",
                    __FUNCTION__, __LINE__,
                    physical, device->requestedRegisterMemSizes[i]
                    );

                gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
            }

            physical += device->requestedRegisterMemSizes[i];
        }
        else
        {
            device->registerBases[i] = gcvNULL;
        }
    }

    /* Set the base address */
    device->baseAddress = PhysBaseAddr;

    /* Construct the gckOS object. */
    gcmkONERROR(gckOS_Construct(device, &device->os));

    if (IrqLine != -1)
    {
        /* Construct the gckKERNEL object. */
        gcmkONERROR(gckKERNEL_Construct(
            device->os, gcvCORE_MAJOR, device,
            gcvNULL, &device->kernels[gcvCORE_MAJOR]));

        sharedDB = device->kernels[gcvCORE_MAJOR]->db;

        /* Initialize core mapping */
        for (i = 0; i < 8; i++)
        {
            device->coreMapping[i] = gcvCORE_MAJOR;
        }

        /* Setup the ISR manager. */
        gcmkONERROR(gckHARDWARE_SetIsrManager(
            device->kernels[gcvCORE_MAJOR]->hardware,
            (gctISRMANAGERFUNC) gckGALDEVICE_Setup_ISR,
            (gctISRMANAGERFUNC) gckGALDEVICE_Release_ISR,
            device
            ));

        gcmkONERROR(gckHARDWARE_SetFastClear(
            device->kernels[gcvCORE_MAJOR]->hardware, FastClear, Compression
            ));


#if COMMAND_PROCESSOR_VERSION == 1
        /* Start the command queue. */
        gcmkONERROR(gckCOMMAND_Start(device->kernels[gcvCORE_MAJOR]->command));
#endif
    }
    else
    {
        device->kernels[gcvCORE_MAJOR] = gcvNULL;
    }

    if (IrqLine2D != -1)
    {
        gcmkONERROR(gckKERNEL_Construct(
            device->os, gcvCORE_2D, device,
            sharedDB, &device->kernels[gcvCORE_2D]));

        if (sharedDB == gcvNULL) sharedDB = device->kernels[gcvCORE_2D]->db;

        /* Verify the hardware type */
        gcmkONERROR(gckHARDWARE_GetType(device->kernels[gcvCORE_2D]->hardware, &type));

        if (type != gcvHARDWARE_2D)
        {
            gcmkTRACE_ZONE(
                gcvLEVEL_ERROR, gcvZONE_DRIVER,
                "%s(%d): Unexpected hardware type: %d\n",
                __FUNCTION__, __LINE__,
                type
                );

            gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
        }

        /* Initialize core mapping */
        if (device->kernels[gcvCORE_MAJOR] == gcvNULL)
        {
            for (i = 0; i < 8; i++)
            {
                device->coreMapping[i] = gcvCORE_2D;
            }
        }
        else
        {
            device->coreMapping[gcvHARDWARE_2D] = gcvCORE_2D;
        }

        /* Setup the ISR manager. */
        gcmkONERROR(gckHARDWARE_SetIsrManager(
            device->kernels[gcvCORE_2D]->hardware,
            (gctISRMANAGERFUNC) gckGALDEVICE_Setup_ISR_2D,
            (gctISRMANAGERFUNC) gckGALDEVICE_Release_ISR_2D,
            device
            ));

#if COMMAND_PROCESSOR_VERSION == 1
        /* Start the command queue. */
        gcmkONERROR(gckCOMMAND_Start(device->kernels[gcvCORE_2D]->command));
#endif
    }
    else
    {
        device->kernels[gcvCORE_2D] = gcvNULL;
    }

    if (IrqLineVG != -1)
    {
#if gcdENABLE_VG
        gcmkONERROR(gckKERNEL_Construct(
            device->os, gcvCORE_VG, device,
            sharedDB, &device->kernels[gcvCORE_VG]));
        /* Initialize core mapping */
        if (device->kernels[gcvCORE_MAJOR] == gcvNULL
            && device->kernels[gcvCORE_2D] == gcvNULL
            )
        {
            for (i = 0; i < 8; i++)
            {
                device->coreMapping[i] = gcvCORE_VG;
            }
        }
        else
        {
            device->coreMapping[gcvHARDWARE_VG] = gcvCORE_VG;
        }

#endif
    }
    else
    {
        device->kernels[gcvCORE_VG] = gcvNULL;
    }

    /* Initialize the ISR. */
    device->irqLines[gcvCORE_MAJOR] = IrqLine;
    device->irqLines[gcvCORE_2D]    = IrqLine2D;
    device->irqLines[gcvCORE_VG]    = IrqLineVG;

    /* Initialize the kernel thread semaphores. */
    for (i = 0; i < gcdCORE_COUNT; i++)
    {
        if (device->irqLines[i] != -1) sema_init(&device->semas[i], 0);
    }

    device->signal = Signal;

    for (i = 0; i < gcdCORE_COUNT; i++)
    {
        if (device->kernels[i] != gcvNULL) break;
    }

    if (i == gcdCORE_COUNT) gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);

#if gcdENABLE_VG
    if (i == gcvCORE_VG)
    {
        /* Query the ceiling of the system memory. */
        gcmkONERROR(gckVGHARDWARE_QuerySystemMemory(
                device->kernels[i]->vg->hardware,
                &device->systemMemorySize,
                &device->systemMemoryBaseAddress
                ));
            /* query the amount of video memory */
        gcmkONERROR(gckVGHARDWARE_QueryMemory(
            device->kernels[i]->vg->hardware,
            &device->internalSize, &internalBaseAddress, &internalAlignment,
            &device->externalSize, &externalBaseAddress, &externalAlignment,
            &horizontalTileSize, &verticalTileSize
            ));
    }
    else
#endif
    {
        /* Query the ceiling of the system memory. */
        gcmkONERROR(gckHARDWARE_QuerySystemMemory(
                device->kernels[i]->hardware,
                &device->systemMemorySize,
                &device->systemMemoryBaseAddress
                ));

            /* query the amount of video memory */
        gcmkONERROR(gckHARDWARE_QueryMemory(
            device->kernels[i]->hardware,
            &device->internalSize, &internalBaseAddress, &internalAlignment,
            &device->externalSize, &externalBaseAddress, &externalAlignment,
            &horizontalTileSize, &verticalTileSize
            ));
    }


    /* Set up the internal memory region. */
    if (device->internalSize > 0)
    {
        status = gckVIDMEM_Construct(
            device->os,
            internalBaseAddress, device->internalSize, internalAlignment,
            0, &device->internalVidMem
            );

        if (gcmIS_ERROR(status))
        {
            /* Error, disable internal heap. */
            device->internalSize = 0;
        }
        else
        {
            /* Map internal memory. */
            device->internalLogical
                = (gctPOINTER) ioremap_nocache(physical, device->internalSize);

            if (device->internalLogical == gcvNULL)
            {
                gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
            }

            device->internalPhysical = (gctPHYS_ADDR) physical;
            physical += device->internalSize;
        }
    }

    if (device->externalSize > 0)
    {
        /* create the external memory heap */
        status = gckVIDMEM_Construct(
            device->os,
            externalBaseAddress, device->externalSize, externalAlignment,
            0, &device->externalVidMem
            );

        if (gcmIS_ERROR(status))
        {
            /* Error, disable internal heap. */
            device->externalSize = 0;
        }
        else
        {
            /* Map external memory. */
            device->externalLogical
                = (gctPOINTER) ioremap_nocache(physical, device->externalSize);

            if (device->externalLogical == gcvNULL)
            {
                gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
            }

            device->externalPhysical = (gctPHYS_ADDR) physical;
            physical += device->externalSize;
        }
    }

    /* set up the contiguous memory */
    device->contiguousSize = ContiguousSize;

    if (ContiguousSize > 0)
    {
        if (ContiguousBase == 0)
        {
            while (device->contiguousSize > 0)
            {
                /* Allocate contiguous memory. */
                status = _AllocateMemory(
                    device,
                    device->contiguousSize,
                    &device->contiguousBase,
                    &device->contiguousPhysical,
                    &physAddr
                    );

                if (gcmIS_SUCCESS(status))
                {
                    status = gckVIDMEM_Construct(
                        device->os,
                        physAddr | device->systemMemoryBaseAddress,
                        device->contiguousSize,
                        64,
                        BankSize,
                        &device->contiguousVidMem
                        );

                    if (gcmIS_SUCCESS(status))
                    {
                        break;
                    }

                    gcmkONERROR(_FreeMemory(
                        device,
                        device->contiguousBase,
                        device->contiguousPhysical
                        ));

                    device->contiguousBase     = gcvNULL;
                    device->contiguousPhysical = gcvNULL;
                }

                if (device->contiguousSize <= (4 << 20))
                {
                    device->contiguousSize = 0;
                }
                else
                {
                    device->contiguousSize -= (4 << 20);
                }
            }
        }
        else
        {
            /* Create the contiguous memory heap. */
            status = gckVIDMEM_Construct(
                device->os,
                (ContiguousBase - device->baseAddress) | device->systemMemoryBaseAddress,
                 ContiguousSize,
                64, BankSize,
                &device->contiguousVidMem
                );

            if (gcmIS_ERROR(status))
            {
                /* Error, disable contiguous memory pool. */
                device->contiguousVidMem = gcvNULL;
                device->contiguousSize   = 0;
            }
            else
            {
                mem_region = request_mem_region(
                    ContiguousBase, ContiguousSize, "galcore managed memory"
                    );

#if 0
                if (mem_region == gcvNULL)
                {
                    gcmkTRACE_ZONE(
                        gcvLEVEL_ERROR, gcvZONE_DRIVER,
                        "%s(%d): Failed to claim %ld bytes @ 0x%08X\n",
                        __FUNCTION__, __LINE__,
                        ContiguousSize, ContiguousBase
                        );

                    gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
                }
#endif

                device->requestedContiguousBase  = ContiguousBase;
                device->requestedContiguousSize  = ContiguousSize;

#if !gcdDYNAMIC_MAP_RESERVED_MEMORY && gcdENABLE_VG
                if (gcmIS_CORE_PRESENT(device, gcvCORE_VG))
                {
                    device->contiguousBase
#if gcdPAGED_MEMORY_CACHEABLE
                        = (gctPOINTER) ioremap_cached(ContiguousBase, ContiguousSize);
#else
                        = (gctPOINTER) ioremap_nocache(ContiguousBase, ContiguousSize);
#endif
                    if (device->contiguousBase == gcvNULL)
                    {
                        device->contiguousVidMem = gcvNULL;
                        device->contiguousSize = 0;

                        gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
                    }
                }
#endif

                device->contiguousPhysical = (gctPHYS_ADDR) ContiguousBase;
                device->contiguousSize     = ContiguousSize;
                device->contiguousMapped   = gcvTRUE;
            }
        }
    }
gceSTATUS
ppoPREPROCESSOR_MacroExpand(
                            ppoPREPROCESSOR     PP,
                            ppoINPUT_STREAM     *IS,
                            ppoTOKEN            *Head,
                            ppoTOKEN            *End,
                            gctBOOL             *AnyExpanationHappened)
{
    gceSTATUS status = gcvSTATUS_INVALID_DATA;
    ppoTOKEN *headtail = gcvNULL;
    ppoTOKEN *expanded_headtail = gcvNULL;
    gctBOOL match_case = gcvFALSE;
    ppoTOKEN id = gcvNULL;
    ppoMACRO_SYMBOL ms = gcvNULL;
    gctPOINTER pointer = gcvNULL;

    if ((*IS) == gcvNULL)
    {
        *AnyExpanationHappened  = gcvFALSE;
        *Head       = gcvNULL;
        *End        = gcvNULL;

        return gcvSTATUS_OK;
    }

    gcmONERROR(
        ppoPREPROCESSOR_MacroExpand_0_SelfContain(PP, IS, Head, End, AnyExpanationHappened, &match_case, &id)
        );

    if (match_case == gcvTRUE) return gcvSTATUS_OK;

    gcmONERROR(
        ppoPREPROCESSOR_MacroExpand_1_NotMacroSymbol(PP, IS, Head, End, AnyExpanationHappened, &match_case, id, &ms)
        );

    if (match_case == gcvTRUE)  return gcvSTATUS_OK;


    gcmONERROR(
        ppoPREPROCESSOR_MacroExpand_2_NoFormalArgs(PP, IS, Head, End, AnyExpanationHappened, &match_case, id, ms)
        );

    if (match_case == gcvTRUE)  return gcvSTATUS_OK;

    gcmONERROR(
        ppoPREPROCESSOR_MacroExpand_3_NoMoreTokenInIS(PP, IS, Head, End, AnyExpanationHappened, &match_case, id)
        );

    if (match_case == gcvTRUE)  return gcvSTATUS_OK;

    gcmONERROR(
        ppoPREPROCESSOR_MacroExpand_4_NoRealArg(PP, IS, Head, End, AnyExpanationHappened, &match_case, id)
        );

    if (match_case == gcvTRUE)  return gcvSTATUS_OK;

    status = sloCOMPILER_Allocate(
        PP->compiler,
        sizeof(ppoTOKEN)*2*(ms->argc),
        &pointer
        );

    if (gcmIS_ERROR(status))
        return status;

    headtail = pointer;

    gcoOS_MemFill((gctPOINTER)headtail, 0, sizeof(ppoTOKEN) * 2 * (ms->argc));

    gcmONERROR(sloCOMPILER_Allocate(
        PP->compiler,
        sizeof(ppoTOKEN)*2*(ms->argc),
        (void*)&expanded_headtail));

    gcoOS_MemFill((gctPOINTER)expanded_headtail, 0, sizeof(ppoTOKEN) * 2 * (ms->argc));

    gcmONERROR(
        ppoPREPROCESSOR_MacroExpand_5_BufferRealArgs(PP, IS, headtail, id, ms)
        );

    if (match_case == gcvTRUE)  return gcvSTATUS_OK;

    gcmONERROR(
        ppoPREPROCESSOR_MacroExpand_6_ExpandHeadTail(PP, IS, headtail, expanded_headtail, id, ms)
        );

    gcmONERROR(
        ppoPREPROCESSOR_MacroExpand_7_ParseReplacementList(PP, IS, Head, End, AnyExpanationHappened,expanded_headtail, id, ms)
        );

    gcmONERROR(
        sloCOMPILER_Free(PP->compiler, headtail)
        );

    gcmONERROR(
        sloCOMPILER_Free(PP->compiler, expanded_headtail)
        );

    return gcvSTATUS_OK;

OnError:
	if (headtail != gcvNULL)
	{
		gcmVERIFY_OK(sloCOMPILER_Free(PP->compiler, headtail));
		headtail = gcvNULL;
	}

	if (expanded_headtail != gcvNULL)
	{
		gcmVERIFY_OK(sloCOMPILER_Free(PP->compiler, expanded_headtail));
		expanded_headtail = gcvNULL;
	}
	return status;
}
static int drv_init(void)
#endif
{
    int ret;
    int result = -EINVAL;
    gceSTATUS status;
    gckGALDEVICE device = gcvNULL;
    struct class* device_class = gcvNULL;

    gcsDEVICE_CONSTRUCT_ARGS args = {
        .recovery  = recovery,
        .stuckDump = stuckDump,
    };

    gcmkHEADER();

#if ENABLE_GPU_CLOCK_BY_DRIVER && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28))
    {
        struct clk * clk;

        clk = clk_get(NULL, "GCCLK");

        if (IS_ERR(clk))
        {
            gcmkTRACE_ZONE(
                gcvLEVEL_ERROR, gcvZONE_DRIVER,
                "%s(%d): clk get error: %d\n",
                __FUNCTION__, __LINE__,
                PTR_ERR(clk)
                );

            result = -ENODEV;
            gcmkONERROR(gcvSTATUS_GENERIC_IO);
        }

        /*
         * APMU_GC_156M, APMU_GC_312M, APMU_GC_PLL2, APMU_GC_PLL2_DIV2 currently.
         * Use the 2X clock.
         */
        if (clk_set_rate(clk, coreClock * 2))
        {
            gcmkTRACE_ZONE(
                gcvLEVEL_ERROR, gcvZONE_DRIVER,
                "%s(%d): Failed to set core clock.\n",
                __FUNCTION__, __LINE__
                );

            result = -EAGAIN;
            gcmkONERROR(gcvSTATUS_GENERIC_IO);
        }

        clk_enable(clk);

#if defined(CONFIG_PXA_DVFM) && (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
        gc_pwr(1);
#   endif
    }
#endif

    printk(KERN_INFO "Galcore version %d.%d.%d.%d\n",
        gcvVERSION_MAJOR, gcvVERSION_MINOR, gcvVERSION_PATCH, gcvVERSION_BUILD);
    /* when enable gpu profiler, we need to turn off gpu powerMangement */
    if(gpuProfiler)
        powerManagement = 0;
    if (showArgs)
    {
        gckOS_DumpParam();
    }

    if(logFileSize != 0)
    {
        gckDEBUGFS_Initialize();
    }

    /* Create the GAL device. */
    status = gckGALDEVICE_Construct(
#if gcdMULTI_GPU || gcdMULTI_GPU_AFFINITY
        irqLine3D0,
        registerMemBase3D0, registerMemSize3D0,
        irqLine3D1,
        registerMemBase3D1, registerMemSize3D1,
#else
        irqLine,
        registerMemBase, registerMemSize,
#endif
        irqLine2D,
        registerMemBase2D, registerMemSize2D,
        irqLineVG,
        registerMemBaseVG, registerMemSizeVG,
        contiguousBase, contiguousSize,
        bankSize, fastClear, compression, baseAddress, physSize, signal,
        logFileSize,
        powerManagement,
        gpuProfiler,
        &args,
        &device
    );

    if (gcmIS_ERROR(status))
    {
        gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
                       "%s(%d): Failed to create the GAL device: status=%d\n",
                       __FUNCTION__, __LINE__, status);

        goto OnError;
    }

    /* Start the GAL device. */
    gcmkONERROR(gckGALDEVICE_Start(device));

    if ((physSize != 0)
       && (device->kernels[gcvCORE_MAJOR] != gcvNULL)
       && (device->kernels[gcvCORE_MAJOR]->hardware->mmuVersion != 0))
    {
#if !gcdSECURITY
        status = gckMMU_Enable(device->kernels[gcvCORE_MAJOR]->mmu, baseAddress, physSize);
        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
            "Enable new MMU: status=%d\n", status);

#if gcdMULTI_GPU_AFFINITY
        status = gckMMU_Enable(device->kernels[gcvCORE_OCL]->mmu, baseAddress, physSize);
        gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
            "Enable new MMU: status=%d\n", status);
#endif

        if ((device->kernels[gcvCORE_2D] != gcvNULL)
            && (device->kernels[gcvCORE_2D]->hardware->mmuVersion != 0))
        {
            status = gckMMU_Enable(device->kernels[gcvCORE_2D]->mmu, baseAddress, physSize);
            gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
                "Enable new MMU for 2D: status=%d\n", status);
        }
#endif

        /* Reset the base address */
        device->baseAddress = 0;
    }

    /* Register the character device. */
    ret = register_chrdev(major, DEVICE_NAME, &driver_fops);

    if (ret < 0)
    {
        gcmkTRACE_ZONE(
            gcvLEVEL_ERROR, gcvZONE_DRIVER,
            "%s(%d): Could not allocate major number for mmap.\n",
            __FUNCTION__, __LINE__
            );

        gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
    }

    if (major == 0)
    {
        major = ret;
    }

    /* Create the device class. */
/*####modified for marvell-bg2*/
    device_class = class_create(THIS_MODULE, "graphics_3d_class");
/*####end for marvell-bg2*/

    if (IS_ERR(device_class))
    {
        gcmkTRACE_ZONE(
            gcvLEVEL_ERROR, gcvZONE_DRIVER,
            "%s(%d): Failed to create the class.\n",
            __FUNCTION__, __LINE__
            );

        gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
    }

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
    device_create(device_class, NULL, MKDEV(major, 0), NULL, DEVICE_NAME);
#else
    device_create(device_class, NULL, MKDEV(major, 0), DEVICE_NAME);
#endif

    galDevice = device;
    gpuClass  = device_class;

#if gcdMULTI_GPU || gcdMULTI_GPU_AFFINITY
    gcmkTRACE_ZONE(
        gcvLEVEL_INFO, gcvZONE_DRIVER,
        "%s(%d): irqLine3D0=%d, contiguousSize=%lu, memBase3D0=0x%lX\n",
        __FUNCTION__, __LINE__,
        irqLine3D0, contiguousSize, registerMemBase3D0
        );
#else
    gcmkTRACE_ZONE(
        gcvLEVEL_INFO, gcvZONE_DRIVER,
        "%s(%d): irqLine=%d, contiguousSize=%lu, memBase=0x%lX\n",
        __FUNCTION__, __LINE__,
        irqLine, contiguousSize, registerMemBase
        );
#endif

    /* Success. */
    gcmkFOOTER_NO();
    return 0;

OnError:
    /* Roll back. */
    if (device_class != gcvNULL)
    {
        device_destroy(device_class, MKDEV(major, 0));
        class_destroy(device_class);
    }

    if (device != gcvNULL)
    {
        gcmkVERIFY_OK(gckGALDEVICE_Stop(device));
        gcmkVERIFY_OK(gckGALDEVICE_Destroy(device));
    }

    gcmkFOOTER();
    return result;
}
/*******************************************************************************
**
**	gckKERNEL_Dispatch
**
**	Dispatch a command received from the user HAL layer.
**
**	INPUT:
**
**		gckKERNEL Kernel
**			Pointer to an gckKERNEL object.
**
**		gctBOOL FromUser
**			whether the call is from the user space.
**
**		gcsHAL_INTERFACE * Interface
**			Pointer to a gcsHAL_INTERFACE structure that defines the command to
**			be dispatched.
**
**	OUTPUT:
**
**		gcsHAL_INTERFACE * Interface
**			Pointer to a gcsHAL_INTERFACE structure that receives any data to be
**			returned.
*/
gceSTATUS
gckKERNEL_Dispatch(
	IN gckKERNEL Kernel,
	IN gctBOOL FromUser,
	IN OUT gcsHAL_INTERFACE * Interface
	)
{
	gceSTATUS status;
	gctUINT32 bitsPerPixel;
	gctSIZE_T bytes;
	gcuVIDMEM_NODE_PTR node;
	gctBOOL locked = gcvFALSE;
	gctPHYS_ADDR physical;
	gctUINT32 address;

	gcmkHEADER_ARG("Kernel=0x%x FromUser=%d Interface=0x%x",
				   Kernel, FromUser, Interface);

	/* Verify the arguments. */
	gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
	gcmkVERIFY_ARGUMENT(Interface != gcvNULL);

	gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_KERNEL,
				   "Dispatching command %d", Interface->command);

	/* Dispatch on command. */
	switch (Interface->command)
	{
	case gcvHAL_GET_BASE_ADDRESS:
		/* Get base address. */
		gcmkONERROR(
			gckOS_GetBaseAddress(Kernel->os,
								 &Interface->u.GetBaseAddress.baseAddress));
		break;

    case gcvHAL_QUERY_VIDEO_MEMORY:
        /* Query video memory size. */
        gcmkONERROR(gckKERNEL_QueryVideoMemory(Kernel, Interface));
		break;

	case gcvHAL_QUERY_CHIP_IDENTITY:
		/* Query chip identity. */
		gcmkONERROR(
			gckHARDWARE_QueryChipIdentity(
				Kernel->hardware,
				&Interface->u.QueryChipIdentity.chipModel,
				&Interface->u.QueryChipIdentity.chipRevision,
				&Interface->u.QueryChipIdentity.chipFeatures,
				&Interface->u.QueryChipIdentity.chipMinorFeatures,
				&Interface->u.QueryChipIdentity.chipMinorFeatures1));

		/* Query chip specifications. */
		gcmkONERROR(
			gckHARDWARE_QueryChipSpecs(
				Kernel->hardware,
				&Interface->u.QueryChipIdentity.streamCount,
				&Interface->u.QueryChipIdentity.registerMax,
				&Interface->u.QueryChipIdentity.threadCount,
				&Interface->u.QueryChipIdentity.shaderCoreCount,
				&Interface->u.QueryChipIdentity.vertexCacheSize,
				&Interface->u.QueryChipIdentity.vertexOutputBufferSize));
		break;

	case gcvHAL_MAP_MEMORY:
		physical = Interface->u.MapMemory.physical;

		/* Map memory. */
		gcmkONERROR(
			gckKERNEL_MapMemory(Kernel,
								physical,
								Interface->u.MapMemory.bytes,
								&Interface->u.MapMemory.logical));
		break;

	case gcvHAL_UNMAP_MEMORY:
		physical = Interface->u.UnmapMemory.physical;

		/* Unmap memory. */
		gcmkONERROR(
			gckKERNEL_UnmapMemory(Kernel,
								  physical,
								  Interface->u.UnmapMemory.bytes,
								  Interface->u.UnmapMemory.logical));
		break;

	case gcvHAL_ALLOCATE_NON_PAGED_MEMORY:
		/* Allocate non-paged memory. */
#ifdef __QNXNTO__
		if (FromUser)
		{
			gcmkONERROR(
				gckOS_AllocateNonPagedMemoryShmPool(
				Kernel->os,
				FromUser,
				Interface->pid,
				Interface->handle,
				&Interface->u.AllocateNonPagedMemory.bytes,
				&Interface->u.AllocateNonPagedMemory.physical,
				&Interface->u.AllocateNonPagedMemory.logical));
			break;
		}
#endif
		gcmkONERROR(
			gckOS_AllocateNonPagedMemory(
				Kernel->os,
				FromUser,
				&Interface->u.AllocateNonPagedMemory.bytes,
				&Interface->u.AllocateNonPagedMemory.physical,
				&Interface->u.AllocateNonPagedMemory.logical));
		break;

	case gcvHAL_FREE_NON_PAGED_MEMORY:
		physical = Interface->u.FreeNonPagedMemory.physical;

		/* Free non-paged memory. */
		gcmkONERROR(
			gckOS_FreeNonPagedMemory(Kernel->os,
									 Interface->u.FreeNonPagedMemory.bytes,
									 physical,
									 Interface->u.FreeNonPagedMemory.logical));
		break;

	case gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY:
		/* Allocate contiguous memory. */
#ifdef __QNXNTO__
		if (FromUser)
		{
			gcmkONERROR(
				gckOS_AllocateNonPagedMemoryShmPool(
				Kernel->os,
				FromUser,
				Interface->pid,
				Interface->handle,
				&Interface->u.AllocateNonPagedMemory.bytes,
				&Interface->u.AllocateNonPagedMemory.physical,
				&Interface->u.AllocateNonPagedMemory.logical));
			break;
		}
#endif
		gcmkONERROR(
			gckOS_AllocateContiguous(
				Kernel->os,
				FromUser,
				&Interface->u.AllocateContiguousMemory.bytes,
				&Interface->u.AllocateContiguousMemory.physical,
				&Interface->u.AllocateContiguousMemory.logical));

		break;

	case gcvHAL_FREE_CONTIGUOUS_MEMORY:
		physical = Interface->u.FreeContiguousMemory.physical;

       /* Free contiguous memory. */
        gcmkONERROR(
            gckOS_FreeContiguous(Kernel->os,
                                 physical,
                                 Interface->u.FreeContiguousMemory.logical,
                                 Interface->u.FreeContiguousMemory.bytes));
        break;

	case gcvHAL_ALLOCATE_VIDEO_MEMORY:
		/* Align width and height to tiles. */
		gcmkONERROR(
			gckHARDWARE_AlignToTile(Kernel->hardware,
									Interface->u.AllocateVideoMemory.type,
									&Interface->u.AllocateVideoMemory.width,
									&Interface->u.AllocateVideoMemory.height,
									gcvNULL));

		/* Convert format into bytes per pixel and bytes per tile. */
		gcmkONERROR(
			gckHARDWARE_ConvertFormat(Kernel->hardware,
									  Interface->u.AllocateVideoMemory.format,
									  &bitsPerPixel,
									  gcvNULL));

		/* Compute number of bytes for the allocation. */
		bytes = Interface->u.AllocateVideoMemory.width * bitsPerPixel
			  * Interface->u.AllocateVideoMemory.height
			  * Interface->u.AllocateVideoMemory.depth / 8;

		/* Allocate memory. */
#ifdef __QNXNTO__
		gcmkONERROR(
			_AllocateMemory(Kernel,
							&Interface->u.AllocateVideoMemory.pool,
							bytes,
							64,
							Interface->u.AllocateVideoMemory.type,
							Interface->handle,
							&Interface->u.AllocateVideoMemory.node));
#else
		gcmkONERROR(
			_AllocateMemory(Kernel,
							&Interface->u.AllocateVideoMemory.pool,
							bytes,
							64,
							Interface->u.AllocateVideoMemory.type,
							&Interface->u.AllocateVideoMemory.node));
#endif
		break;

	case gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY:
		/* Allocate memory. */
#ifdef __QNXNTO__
		gcmkONERROR(
			_AllocateMemory(Kernel,
							&Interface->u.AllocateLinearVideoMemory.pool,
							Interface->u.AllocateLinearVideoMemory.bytes,
							Interface->u.AllocateLinearVideoMemory.alignment,
							Interface->u.AllocateLinearVideoMemory.type,
							Interface->handle,
							&Interface->u.AllocateLinearVideoMemory.node));

		/* Set the current user pid in the node,
		 * which is used while locking memory. */
		gcmkVERIFY_OK(gckVIDMEM_SetPID(
				Interface->u.AllocateLinearVideoMemory.node,
				Interface->pid));
#else
		gcmkONERROR(
			_AllocateMemory(Kernel,
							&Interface->u.AllocateLinearVideoMemory.pool,
							Interface->u.AllocateLinearVideoMemory.bytes,
							Interface->u.AllocateLinearVideoMemory.alignment,
							Interface->u.AllocateLinearVideoMemory.type,
							&Interface->u.AllocateLinearVideoMemory.node));
#endif
		break;

    case gcvHAL_FREE_VIDEO_MEMORY:
#ifdef __QNXNTO__
        node = Interface->u.FreeVideoMemory.node;
        if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM
         && node->VidMem.logical != gcvNULL)
        {
            gcmkONERROR(
                    gckKERNEL_UnmapVideoMemory(Kernel,
                                               node->VidMem.logical,
                                               Interface->pid,
                                               node->VidMem.bytes));
            node->VidMem.logical = gcvNULL;
        }
#endif
        /* Free video memory. */
        gcmkONERROR(
            gckVIDMEM_Free(Interface->u.FreeVideoMemory.node));
        break;

	case gcvHAL_LOCK_VIDEO_MEMORY:
		/* Lock video memory. */
		gcmkONERROR(
			gckVIDMEM_Lock(Interface->u.LockVideoMemory.node,
						   &Interface->u.LockVideoMemory.address));

		locked = gcvTRUE;

		node = Interface->u.LockVideoMemory.node;
		if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
		{
			/* Map video memory address into user space. */
#ifdef __QNXNTO__
        if (node->VidMem.logical == gcvNULL)
        {
			gcmkONERROR(
				gckKERNEL_MapVideoMemory(Kernel,
										 FromUser,
										 Interface->u.LockVideoMemory.address,
										 Interface->pid,
										 node->VidMem.bytes,
										 &node->VidMem.logical));
        }
		Interface->u.LockVideoMemory.memory = node->VidMem.logical;
#else
			gcmkONERROR(
				gckKERNEL_MapVideoMemory(Kernel,
										 FromUser,
										 Interface->u.LockVideoMemory.address,
										 &Interface->u.LockVideoMemory.memory));
#endif

#ifdef __QNXNTO__
			/* Add more information to node, which is used while unmapping. */
			gcmkVERIFY_OK(gckVIDMEM_SetPID(
					Interface->u.LockVideoMemory.node,
					Interface->pid));
#endif
		}

		else
		{
			/* Copy logical memory for virtual memory. */
			Interface->u.LockVideoMemory.memory = node->Virtual.logical;

            /* Success. */
            status = gcvSTATUS_OK;
        }

#if gcdSECURE_USER
        /* Return logical address as physical address. */
        Interface->u.LockVideoMemory.address =
            gcmPTR2INT(Interface->u.LockVideoMemory.memory);
#endif
        break;

	case gcvHAL_UNLOCK_VIDEO_MEMORY:
		/* Unlock video memory. */
		node = Interface->u.UnlockVideoMemory.node;

        /* Unlock video memory. */
        gcmkONERROR(
            gckVIDMEM_Unlock(node,
                             Interface->u.UnlockVideoMemory.type,
                             &Interface->u.UnlockVideoMemory.asynchroneous));
        break;

	case gcvHAL_EVENT_COMMIT:
		/* Commit an event queue. */
		gcmkONERROR(
			gckEVENT_Commit(Kernel->event,
						    Interface->u.Event.queue));
        break;

    case gcvHAL_COMMIT:
        /* Commit a command and context buffer. */
        gcmkONERROR(
            gckCOMMAND_Commit(Kernel->command,
                              Interface->u.Commit.commandBuffer,
                              Interface->u.Commit.contextBuffer,
                              Interface->u.Commit.process));
        break;

    case gcvHAL_STALL:
        /* Stall the command queue. */
        gcmkONERROR(gckCOMMAND_Stall(Kernel->command));
        break;

	case gcvHAL_MAP_USER_MEMORY:
		/* Map user memory to DMA. */
		gcmkONERROR(
			gckOS_MapUserMemory(Kernel->os,
								Interface->u.MapUserMemory.memory,
								Interface->u.MapUserMemory.size,
								&Interface->u.MapUserMemory.info,
								&Interface->u.MapUserMemory.address));
		break;

	case gcvHAL_UNMAP_USER_MEMORY:
		address = Interface->u.MapUserMemory.address;

		/* Unmap user memory. */
		gcmkONERROR(
			gckOS_UnmapUserMemory(Kernel->os,
								  Interface->u.UnmapUserMemory.memory,
								  Interface->u.UnmapUserMemory.size,
								  Interface->u.UnmapUserMemory.info,
								  address));
		break;

#if !USE_NEW_LINUX_SIGNAL
	case gcvHAL_USER_SIGNAL:
     	gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_KERNEL,
				   "Dispatching gcvHAL_USER_SIGNAL %d", Interface->u.UserSignal.command);
		/* Dispatch depends on the user signal subcommands. */
		switch(Interface->u.UserSignal.command)
		{
		case gcvUSER_SIGNAL_CREATE:
			/* Create a signal used in the user space. */
			gcmkONERROR(
				gckOS_CreateUserSignal(Kernel->os,
									   Interface->u.UserSignal.manualReset,
                                       Interface->u.UserSignal.signalType,
									   &Interface->u.UserSignal.id));
			break;

		case gcvUSER_SIGNAL_DESTROY:
			/* Destroy the signal. */
			gcmkONERROR(
				gckOS_DestroyUserSignal(Kernel->os,
										Interface->u.UserSignal.id));
			break;

		case gcvUSER_SIGNAL_SIGNAL:
			/* Signal the signal. */
			gcmkONERROR(
				gckOS_SignalUserSignal(Kernel->os,
									   Interface->u.UserSignal.id,
									   Interface->u.UserSignal.state));
			break;

		case gcvUSER_SIGNAL_WAIT:
			/* Wait on the signal. */
			status = gckOS_WaitUserSignal(Kernel->os,
										  Interface->u.UserSignal.id,
										  Interface->u.UserSignal.wait);
			break;

		default:
			/* Invalid user signal command. */
			gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
		}
        break;
#endif

    case gcvHAL_SET_POWER_MANAGEMENT_STATE:
		/* Set the power management state. */
		gcmkONERROR(
			gckHARDWARE_SetPowerManagementState(
				Kernel->hardware,
				Interface->u.SetPowerManagement.state));
		break;

    case gcvHAL_QUERY_POWER_MANAGEMENT_STATE:
        /* Chip is not idle. */
        Interface->u.QueryPowerManagement.isIdle = gcvFALSE;

		/* Query the power management state. */
        gcmkONERROR(gckHARDWARE_QueryPowerManagementState(
            Kernel->hardware,
            &Interface->u.QueryPowerManagement.state));

        /* Query the idle state. */
        gcmkONERROR(
            gckHARDWARE_QueryIdle(Kernel->hardware,
                                  &Interface->u.QueryPowerManagement.isIdle));
        break;

    case gcvHAL_READ_REGISTER:
#if gcdREGISTER_ACCESS_FROM_USER
        /* Read a register. */
        gcmkONERROR(
            gckOS_ReadRegister(Kernel->os,
                               Interface->u.ReadRegisterData.address,
                               &Interface->u.ReadRegisterData.data));
#else
		/* No access from user land to read registers. */
		Interface->u.ReadRegisterData.data = 0;
		status = gcvSTATUS_NOT_SUPPORTED;
#endif
        break;

    case gcvHAL_WRITE_REGISTER:
#if gcdREGISTER_ACCESS_FROM_USER
        /* Write a register. */
        gcmkONERROR(
            gckOS_WriteRegister(Kernel->os,
                                Interface->u.WriteRegisterData.address,
                                Interface->u.WriteRegisterData.data));
#else
		/* No access from user land to write registers. */
		status = gcvSTATUS_NOT_SUPPORTED;
#endif
        break;

    case gcvHAL_READ_ALL_PROFILE_REGISTERS:
#if VIVANTE_PROFILER
		/* Read all 3D profile registers. */
		gcmkONERROR(
			gckHARDWARE_QueryProfileRegisters(
				Kernel->hardware,
				&Interface->u.RegisterProfileData.counters));
#else
        status = gcvSTATUS_OK;
#endif
        break;

    case gcvHAL_PROFILE_REGISTERS_2D:
#if VIVANTE_PROFILER
		/* Read all 2D profile registers. */
		gcmkONERROR(
			gckHARDWARE_ProfileEngine2D(
				Kernel->hardware,
				Interface->u.RegisterProfileData2D.hwProfile2D));
#else
        status = gcvSTATUS_OK;
#endif
        break;

	case gcvHAL_GET_PROFILE_SETTING:
#if VIVANTE_PROFILER
		/* Get profile setting */
		Interface->u.GetProfileSetting.enable = Kernel->profileEnable;

		gcmkVERIFY_OK(
			gckOS_MemCopy(Interface->u.GetProfileSetting.fileName,
						  Kernel->profileFileName,
						  gcdMAX_PROFILE_FILE_NAME));
#endif

		status = gcvSTATUS_OK;
        break;

	case gcvHAL_SET_PROFILE_SETTING:
#if VIVANTE_PROFILER
		/* Set profile setting */
		Kernel->profileEnable = Interface->u.SetProfileSetting.enable;

		gcmkVERIFY_OK(
			gckOS_MemCopy(Kernel->profileFileName,
						  Interface->u.SetProfileSetting.fileName,
						  gcdMAX_PROFILE_FILE_NAME));
#endif

        status = gcvSTATUS_OK;
		break;

	case gcvHAL_QUERY_KERNEL_SETTINGS:
		/* Get kernel settings. */
		gcmkONERROR(
			gckKERNEL_QuerySettings(Kernel,
									&Interface->u.QueryKernelSettings.settings));
		break;

	case gcvHAL_RESET:
		/* Reset the hardware. */
		gcmkONERROR(
			gckHARDWARE_Reset(Kernel->hardware));
		break;

    case gcvHAL_DEBUG:
        /* Set debug level and zones. */
        if (Interface->u.Debug.set)
        {
            gckOS_SetDebugLevel(Interface->u.Debug.level);
            gckOS_SetDebugZones(Interface->u.Debug.zones,
                                Interface->u.Debug.enable);
        }

        if (Interface->u.Debug.message[0] != '\0')
        {
            /* Print a message to the debugger. */
            gcmkPRINT(Interface->u.Debug.message);
        }
        status = gcvSTATUS_OK;
        break;

    case gcvHAL_CACHE:
        if (Interface->u.Cache.invalidate)
        {
            /* Flush and invalidate the cache. */
            status = gckOS_CacheInvalidate(Kernel->os,
                                           Interface->u.Cache.process,
                                           Interface->u.Cache.logical,
                                           Interface->u.Cache.bytes);
        }
        else
        {
            /* Flush the cache. */
            status = gckOS_CacheFlush(Kernel->os,
                                      Interface->u.Cache.process,
                                      Interface->u.Cache.logical,
                                      Interface->u.Cache.bytes);
        }
		break;
    	
	default:
		/* Invalid command. */
		gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
	}

OnError:
	/* Save status. */
	Interface->status = status;

    if (gcmIS_ERROR(status))
    {
        if (locked)
        {
            /* Roll back the lock. */
            gcmkVERIFY_OK(
                gckVIDMEM_Unlock(Interface->u.LockVideoMemory.node,
                                 gcvSURF_TYPE_UNKNOWN,
                                 gcvNULL));
        }
    }

	/* Return the status. */
	gcmkFOOTER();
	return status;
}
Exemple #9
0
static int __init gpu_init(void)
{
    int ret = 0;

    memset(&platform, 0, sizeof(gcsPLATFORM));

    gckPLATFORM_QueryOperations(&platform.ops);

    if (platform.ops == gcvNULL)
    {
        printk(KERN_ERR "galcore: No platform specific operations.\n");
        ret = -ENODEV;
        goto out;
    }

    if (platform.ops->allocPriv)
    {
        /* Allocate platform private data. */
        if (gcmIS_ERROR(platform.ops->allocPriv(&platform)))
        {
            ret = -ENOMEM;
            goto out;
        }
    }

    if (platform.ops->needAddDevice
     && platform.ops->needAddDevice(&platform))
    {
        /* Allocate device */
        platform.device = platform_device_alloc(DEVICE_NAME, -1);
        if (!platform.device)
        {
            printk(KERN_ERR "galcore: platform_device_alloc failed.\n");
            ret = -ENOMEM;
            goto out;
        }

        /* Add device */
        ret = platform_device_add(platform.device);
        if (ret)
        {
            printk(KERN_ERR "galcore: platform_device_add failed.\n");
            goto put_dev;
        }
    }

    platform.driver = &gpu_driver;

    if (platform.ops->adjustDriver)
    {
        /* Override default platform_driver struct. */
        platform.ops->adjustDriver(&platform);
    }

    ret = platform_driver_register(&gpu_driver);
    if (!ret)
    {
        goto out;
    }

    platform_device_del(platform.device);
put_dev:
    platform_device_put(platform.device);

out:
    return ret;
}
static int __devinit gpu_resume(struct platform_device *dev)
{
    gceSTATUS status = gcvSTATUS_OK;
    gckGALDEVICE device;
    gctINT i;
    gctINT ret = 0;
    gceCHIPPOWERSTATE   statesStored;

    device = platform_get_drvdata(dev);

    printk("[galcore] enter %s\n", __FUNCTION__);

    for (i = 0; i < gcdMAX_GPU_COUNT; i++)
    {
        if (device->kernels[i] != gcvNULL)
        {
#if gcdENABLE_VG
            if (i == gcvCORE_VG)
            {
                status = gckVGHARDWARE_SetPowerManagementState(device->kernels[i]->vg->hardware, gcvPOWER_ON);
            }
            else
#endif
            {
                status = gckHARDWARE_SetPowerManagementState(device->kernels[i]->hardware, gcvPOWER_ON);
            }

            if (gcmIS_ERROR(status))
            {
                ret = -1;
                goto err_out;
            }

            /* Convert global state to crossponding internal state. */
            switch(device->statesStored[i])
            {
            case gcvPOWER_OFF:
                statesStored = gcvPOWER_OFF_BROADCAST;
                break;
            case gcvPOWER_IDLE:
                statesStored = gcvPOWER_IDLE_BROADCAST;
                break;
            case gcvPOWER_SUSPEND:
                statesStored = gcvPOWER_SUSPEND_BROADCAST;
                break;
            case gcvPOWER_ON:
                statesStored = gcvPOWER_ON_AUTO;
                break;
            default:
                statesStored = device->statesStored[i];
                break;
            }

            /* Restore states. */
#if gcdENABLE_VG
            if (i == gcvCORE_VG)
            {
                status = gckVGHARDWARE_SetPowerManagementState(device->kernels[i]->vg->hardware, statesStored);
            }
            else
#endif
            {
                status = gckHARDWARE_SetPowerManagementState(device->kernels[i]->hardware, statesStored);
            }

            if (gcmIS_ERROR(status))
            {
                ret = -1;
                goto err_out;
            }
#if MRVL_CONFIG_ENABLE_EARLYSUSPEND
            galDevice->currentPMode = gcvPM_EARLY_SUSPEND;
#else
            galDevice->currentPMode = gcvPM_NORMAL;
#endif
        }
    }

err_out:
    printk("[galcore] exit %s, return %d\n", __FUNCTION__, ret);
    return ret;
}
gceSTATUS
_StretchBlitPE1x(
    IN gcsCOPYBIT_CONTEXT * Context,
    IN struct copybit_image_t const  * Dest,
    IN struct copybit_image_t const  * Source,
    IN struct copybit_rect_t const   * DestRect,
    IN struct copybit_rect_t const   * SourceRect,
    IN struct copybit_region_t const * Clip)
{
    gceSTATUS status = gcvSTATUS_OK;

    gceSURF_FORMAT siFormat;
    gceSURF_FORMAT diFormat;

    gctUINT32      diPhysical = ~0;
    gctUINT32      diAlignedWidth;
    gctUINT32      diAlignedHeight;
    gctINT         diStride;

    gcsRECT srcRect;
    gcsRECT dstRect;
    copybit_rect_t rect;

    gctUINT32      srcPhysical = ~0;
    gctINT         srcStride;
    gctUINT32      srcAlignedWidth;
    gctUINT32      srcAlignedHeight;
    gceSURF_FORMAT srcFormat;

    gctUINT32      dstPhysical = ~0;
    gctINT         dstStride;
    gctUINT32      dstAlignedWidth;
    gctUINT32      dstAlignedHeight;
    gceSURF_FORMAT dstFormat;

    gctBOOL stretch   = gcvFALSE;
    gctBOOL yuvFormat = gcvFALSE;
    gctBOOL perpixelAlpha;

    gc_private_handle_t* dsthnd = (gc_private_handle_t *) Dest->handle;
    gc_private_handle_t* srchnd = (gc_private_handle_t *) Source->handle;

    LOGV("Blit from Source hnd=%p, to Dest hnd=%p", srchnd, dsthnd);

    if (gc_private_handle_t::validate(dsthnd) < 0)
    {
        gcmTRACE(gcvLEVEL_ERROR,
                 "Invalid hnd in funciton %s",
                 __func__);

        return gcvSTATUS_INVALID_ARGUMENT;
    }

    siFormat = (gceSURF_FORMAT) srchnd->format;
    diFormat = (gceSURF_FORMAT) dsthnd->format;

    if ((siFormat == gcvSURF_UNKNOWN)
    ||  (diFormat == gcvSURF_UNKNOWN)
    )
    {
        gcmTRACE(gcvLEVEL_ERROR,
                 "Image format not support in copybit!");

        return gcvSTATUS_INVALID_ARGUMENT;
    }

    /* Convert to supported Source format. */
    siFormat = (siFormat == gcvSURF_A8B8G8R8) ? gcvSURF_A8R8G8B8 : siFormat;
    siFormat = (siFormat == gcvSURF_X8B8G8R8) ? gcvSURF_X8R8G8B8 : siFormat;

    /* Convert to supported Dest format. */
    diFormat = (diFormat == gcvSURF_A8B8G8R8) ? gcvSURF_A8R8G8B8 : diFormat;
    diFormat = (diFormat == gcvSURF_X8B8G8R8) ? gcvSURF_X8R8G8B8 : diFormat;

    do
    {
        srcPhysical = srchnd->phys;
        gcoSURF_GetAlignedSize((gcoSURF) srchnd->surface,
                               &srcAlignedWidth,
                               &srcAlignedHeight,
                               &srcStride);

        diPhysical = dsthnd->phys;
        gcoSURF_GetAlignedSize((gcoSURF) dsthnd->surface,
                               &diAlignedWidth,
                               &diAlignedHeight,
                               &diStride);

        if  ((((gcoSURF)srchnd->surface)->info.type == gcvSURF_BITMAP) &&
            !(srchnd->flags & gc_private_handle_t::PRIV_FLAGS_FRAMEBUFFER))
        {
            /* Clean the CPU cache. Source would've been rendered by the CPU. */
            gcmERR_BREAK(
                gcoSURF_CPUCacheOperation(
                            (gcoSURF) srchnd->surface,
                            gcvCACHE_CLEAN
                            )
            );
        }

        perpixelAlpha = _HasAlpha(siFormat) &&
                 (dsthnd->flags & gc_private_handle_t::PRIV_FLAGS_FRAMEBUFFER) &&
                 !(srchnd->flags & gc_private_handle_t::PRIV_FLAGS_FRAMEBUFFER);

        if (Context->perpixelAlpha != perpixelAlpha)
        {
            Context->perpixelAlpha = perpixelAlpha;

            if (Context->planeAlpha == 0xff)
            {
                Context->dirty.s.alphaKey = 1;
            }
        }

        /* Need temp surface if source has alpha channel, but dest not. */
        Context->needAlphaDest = Context->perpixelAlpha &&
                !_HasAlpha(diFormat);

        if (Context->needAlphaDest)
        {
            gcsRECT tempRect;

            tempRect.left   = gcmMAX(0, DestRect->l);
            tempRect.top    = gcmMAX(0, DestRect->t);
            tempRect.right  = gcmMIN((int32_t) Dest->w, DestRect->r);
            tempRect.bottom = gcmMIN((int32_t) Dest->h, DestRect->b);

            gcmERR_BREAK(
                _FitSurface(Context,
                            &Context->alphaDest,
                            Dest->w,
                            Dest->h));

            if (Context->alphaDest.surface == gcvNULL)
            {
                gcmTRACE(gcvLEVEL_ERROR,
                         "fail to construct tmp surface for per_pixel_alpha");

                break;
            }

            /* Copy dest surface to temp surface. */
            gcmERR_BREAK(
                _MonoBlit(Context,
                          diPhysical,
                          diStride,
                          diFormat,
                          Context->alphaDest.physical,
                          Context->alphaDest.stride,
                          Context->alphaDest.format,
                          &tempRect));
        }

        gcmERR_BREAK(
            _UploadStates(Context));

        if (Context->needAlphaDest)
        {
            dstPhysical      = Context->alphaDest.physical;
            dstStride        = Context->alphaDest.stride;
            dstAlignedWidth  = Context->alphaDest.alignedWidth;
            dstAlignedHeight = Context->alphaDest.alignedHeight;
            dstFormat        = Context->alphaDest.format;
        }
        else
        {
            dstPhysical      = diPhysical;
            dstStride        = diStride;
            dstAlignedWidth  = diAlignedWidth;
            dstAlignedHeight = diAlignedHeight;
            dstFormat        = diFormat;
        }

        srcFormat = siFormat;

        if (Context->transform == COPYBIT_TRANSFORM_ROT_270)
        {
            srcRect.left   = SourceRect->t;
            srcRect.top    = Source->w - SourceRect->r;
            srcRect.right  = SourceRect->b;
            srcRect.bottom = Source->w - SourceRect->l;
        }
        else
        {
            srcRect.left   = SourceRect->l;
            srcRect.top    = SourceRect->t;
            srcRect.right  = SourceRect->r;
            srcRect.bottom = SourceRect->b;
        }

        if (Context->transform ==  COPYBIT_TRANSFORM_ROT_90)
        {
            dstRect.left   = DestRect->t;
            dstRect.top    = Dest->w - DestRect->r;
            dstRect.right  = DestRect->b;
            dstRect.bottom = Dest->w - DestRect->l;
        }
        else
        {
            dstRect.left   = DestRect->l;
            dstRect.top    = DestRect->t;
            dstRect.right  = DestRect->r;
            dstRect.bottom = DestRect->b;
        }

        /* Check yuv format. */
        yuvFormat = (srcFormat == gcvSURF_YUY2 || srcFormat == gcvSURF_UYVY);

        stretch =
            (srcRect.right - srcRect.left) != (dstRect.right - dstRect.left) ||
            (srcRect.bottom - srcRect.top) != (dstRect.bottom - dstRect.top);

        /* Upload stretch factor. */
        if (stretch)
        {
            int hFactor;
            int vFactor;

            if ((dstRect.right-dstRect.left) > 1 && (dstRect.bottom-dstRect.top) > 1)
            {
                hFactor = ((srcRect.right - srcRect.left - 1) << 16) /
                        (dstRect.right - dstRect.left - 1);

                vFactor = ((srcRect.bottom - srcRect.top - 1) << 16) /
                        (dstRect.bottom - dstRect.top - 1);
            }
            else
            {
                hFactor = 0;
                vFactor = 0;
            }

            gcmERR_BREAK(
                gco2D_SetStretchFactors(Context->engine,
                                        hFactor,
                                        vFactor));
        }

        /* Prepare source and target for normal blit. */
        gcmERR_BREAK(
            gco2D_SetColorSource(Context->engine,
                                 srcPhysical,
                                 srcStride,
                                 srcFormat,
                                 Context->srcRotation,
                                 srcAlignedWidth,
                                 gcvFALSE,
                                 gcvSURF_OPAQUE,
                                 0));

        gcmERR_BREAK(
            gco2D_SetSource(Context->engine,
                            &srcRect));

        gcmERR_BREAK(
            gco2D_SetTarget(Context->engine,
                            dstPhysical,
                            dstStride,
                            Context->dstRotation,
                            dstAlignedWidth));

        gcsRECT srcRectBackup = srcRect;
        gcsRECT dstRectBackup = dstRect;

        /* Go though all clip rectangles. */
        while (Clip->next(Clip, &rect))
        {
            gcsRECT clipRect;

            srcRect = srcRectBackup;
            dstRect = dstRectBackup;

            if (Context->transform ==  COPYBIT_TRANSFORM_ROT_90)
            {
                clipRect.left   = rect.t;
                clipRect.top    = Dest->w - rect.r;
                clipRect.right  = rect.b;
                clipRect.bottom = Dest->w - rect.l;
            }
            else if (Context->transform == COPYBIT_TRANSFORM_ROT_180)
            {
                float hfactor = (float) (SourceRect->r - SourceRect->l)
                                 / (DestRect->r - DestRect->l);

                float vfactor = (float) (SourceRect->b - SourceRect->t)
                                 / (DestRect->b - DestRect->t);

                /* Intersect. */
                clipRect.left   = gcmMAX(dstRect.left, rect.l);
                clipRect.top    = gcmMAX(dstRect.top, rect.t);
                clipRect.right  = gcmMIN(dstRect.right, rect.r);
                clipRect.bottom = gcmMIN(dstRect.bottom, rect.b);

                /* Adjust src rectangle. */
                srcRect.left   += (int) ((dstRect.right - clipRect.right) * hfactor);
                srcRect.top    += (int) ((dstRect.bottom - clipRect.bottom) * vfactor);
                srcRect.right  -= (int) ((clipRect.left - dstRect.left) * hfactor);
                srcRect.bottom -= (int) ((clipRect.top - dstRect.top) * vfactor);

                /* Set dstRect to clip rectangle. */
                dstRect = clipRect;

                if ((srcRect.left   != srcRectBackup.left)
                ||  (srcRect.right  != srcRectBackup.right)
                ||  (srcRect.top    != srcRectBackup.top)
                ||  (srcRect.bottom != srcRectBackup.bottom)
                )
                {
                    gcmERR_BREAK(
                        gco2D_SetSource(Context->engine,
                                        &srcRect));
                }
            }
            else
            {
                clipRect.left   = rect.l;
                clipRect.top    = rect.t;
                clipRect.right  = rect.r;
                clipRect.bottom = rect.b;
            }

            /* Clamp clip rectangle. */
            if (clipRect.right > dstRect.right)
                clipRect.right = dstRect.right;

            if (clipRect.bottom > dstRect.bottom)
                clipRect.bottom = dstRect.bottom;

            if (clipRect.left < dstRect.left)
                clipRect.left = dstRect.left;

            if (clipRect.top < dstRect.top)
                clipRect.top = dstRect.top;

            gcmERR_BREAK(
                gco2D_SetClipping(Context->engine,
                                  &clipRect));

            if (yuvFormat)
            {
                /* TODO: FilterBlit does not support rotation before PE20. */
                /* Video filter blit */
                /* 1. SetClipping() has no effect for FilterBlit()
                 *    so we use dstSubRect to realize clipping effect
                 * 2. Only FilterBlit support yuv format covertion.
                 */
                gcsRECT dstSubRect;
                int dstWidth   = dstRect.right   - dstRect.left;
                int dstHeight  = dstRect.bottom  - dstRect.top;
                int clipWidth  = clipRect.right  - clipRect.left;
                int clipHeight = clipRect.bottom - clipRect.top;

                dstSubRect.left   = clipRect.left - dstRect.left;
                dstSubRect.top    = clipRect.top - dstRect.top;
                dstSubRect.right  = dstWidth < clipWidth ?
                        dstSubRect.left + dstWidth :
                        dstSubRect.left + clipWidth;
                dstSubRect.bottom = dstHeight < clipHeight ?
                        dstSubRect.top  + dstHeight :
                        dstSubRect.top  + clipHeight;

                gcmERR_BREAK(
                    gco2D_SetKernelSize(Context->engine,
                                        gcdFILTER_BLOCK_SIZE,
                                        gcdFILTER_BLOCK_SIZE));

                gcmERR_BREAK(
                    gco2D_SetFilterType(Context->engine,
                                        gcvFILTER_SYNC));

                gcmERR_BREAK(
                    gco2D_FilterBlit(Context->engine,
                                     srcPhysical,
                                     srcStride,
                                     0, 0, 0, 0,
                                     srcFormat,
                                     Context->srcRotation,
                                     srcAlignedWidth,
                                     &srcRect,
                                     dstPhysical,
                                     dstStride,
                                     dstFormat,
                                     Context->dstRotation,
                                     dstAlignedWidth,
                                     &dstRect,
                                     &dstSubRect));
            }
            else if (Context->blur)
            {
                /* TODO: FilterBlit does not support rotation before PE20. */
                gcsRECT dstSubRect;
                dstSubRect.left  = 0;
                dstSubRect.top   = 0;
                dstSubRect.right = dstRect.right - dstRect.left;
                dstSubRect.bottom = dstRect.bottom - dstRect.top;

                /* Blur blit. */
                gcmERR_BREAK(
                    gco2D_SetKernelSize(Context->engine,
                                        gcdFILTER_BLOCK_SIZE,
                                        gcdFILTER_BLOCK_SIZE));

                gcmERR_BREAK(
                    gco2D_SetFilterType(Context->engine,
                                        gcvFILTER_BLUR));

                gcmERR_BREAK(
                    gco2D_FilterBlit(Context->engine,
                                     srcPhysical,
                                     srcStride,
                                     0, 0, 0, 0,
                                     srcFormat,
                                     gcvSURF_0_DEGREE,
                                     srcAlignedWidth,
                                     &srcRect,
                                     dstPhysical,
                                     dstStride,
                                     dstFormat,
                                     gcvSURF_0_DEGREE,
                                     dstAlignedWidth,
                                     &dstRect,
                                     &dstSubRect));

                gcmERR_BREAK(
                    gco2D_FilterBlit(Context->engine,
                                     dstPhysical,
                                     dstStride,
                                     0, 0, 0, 0,
                                     dstFormat,
                                     gcvSURF_0_DEGREE,
                                     dstAlignedWidth,
                                     &dstRect,
                                     dstPhysical,
                                     dstStride,
                                     dstFormat,
                                     gcvSURF_0_DEGREE,
                                     dstAlignedWidth,
                                     &dstRect,
                                     &dstSubRect));

                /* TODO: surfaceflinger set blur issue. */
                Context->blur = COPYBIT_DISABLE;
            }
            else if (stretch == gcvFALSE)
            {
                /* BitBlit. */
                gcmERR_BREAK(
                    gco2D_Blit(Context->engine,
                               1,
                               &dstRect,
                               0xCC,
                               0xCC,
                               dstFormat));
            }
            else
            {
                /* Normal stretch blit. */
                gcmERR_BREAK(
                    gco2D_StretchBlit(Context->engine,
                                      1,
                                      &dstRect,
                                      0xCC,
                                      0xCC,
                                      dstFormat));
            }
        }

        if (gcmIS_ERROR(status))
        {
            break;
        }

        if (Context->needAlphaDest)
        {
            gcsRECT tempRect;

            tempRect.left   = gcmMAX(0, DestRect->l);
            tempRect.top    = gcmMAX(0, DestRect->t);
            tempRect.right  = gcmMIN((int32_t) Dest->w, DestRect->r);
            tempRect.bottom = gcmMIN((int32_t) Dest->h, DestRect->b);

            /* Blit back to actual dest. */
            gcmERR_BREAK(
                _MonoBlit(Context,
                          Context->alphaDest.physical,
                          Context->alphaDest.stride,
                          Context->alphaDest.format,
                          diPhysical,
                          diStride,
                          diFormat,
                          &tempRect));
        }

        /* Flush and commit. */
        gcmERR_BREAK(
            gco2D_Flush(Context->engine));

        gcmERR_BREAK(
            gcoHAL_Commit(gcvNULL, gcvFALSE));
    }
    while (gcvFALSE);

    return status;
}
static gceSTATUS _DereferenceObjectCache(
	vgsCONTEXT_PTR Context,
	vgsOBJECT_CACHE_PTR * ObjectCache
	)
{
	/* Define the result and assume success. */
	gceSTATUS status = gcvSTATUS_OK;

	do
	{
		vgsOBJECT_PTR object;
		vgsOBJECT_LIST_PTR objectList;

		/* Get a shortcut to the object cache. */
		vgsOBJECT_CACHE_PTR objectCache = *ObjectCache;

		/* Existing object cache? */
		if (objectCache == gcvNULL)
		{
			break;
		}

		/* Valid reference count? */
		if (objectCache->referenceCount < 1)
		{
			gcmFATAL("Invalid reference count found.\n");
			status = gcvSTATUS_INVALID_OBJECT;
			break;
		}

		/* Decrement the counter. */
		objectCache->referenceCount--;

		/* Time to destroy? */
		if (objectCache->referenceCount == 0)
		{
			gctUINT i;

			/* Delete objects that are still in the cache. */
			for (i = 0; i < vgvOBJECTTYPE_COUNT; i++)
			{
				gctUINT32 index;

				/* Get the current object list. */
				objectList = &objectCache->cache[i];

				for (index = 0; index < vgvNAMED_OBJECTS_HASH; index++)
				{
					/* Are there objects in the list? */
					if (objectList->head[index] != gcvNULL)
					{
						gcmTRACE(
							gcvLEVEL_ERROR,
							"%s (%d): object cache %d still has objects in it.\n",
							__FUNCTION__, __LINE__, i
							);

						/* Delete the objects. */
						while (objectList->head[index])
                                        	{
							/* Copy the head object. */
							object = objectList->head[index];

							/* Dereference it. */
							gcmERR_BREAK(vgfDereferenceObject(
								Context,
								&object
								));
						}
					}
				 }

				/* Error? */
				if (gcmIS_ERROR(status))
				{
					break;
				}
			}

			/* Error? */
			if (gcmIS_ERROR(status))
			{
				break;
			}

			/* Allocate the context structure. */
			gcmERR_BREAK(gcoOS_Free(
				Context->os,
				(gctPOINTER *) objectCache
				));

			/* Reset the object. */
			*ObjectCache = gcvNULL;
		}
	}
	while (gcvFALSE);

	/* Return status. */
	return status;
}
/* echo xx > /proc/driver/gc set ... */
static ssize_t gc_proc_write(struct file *file,
		const char *buff, size_t len, loff_t *off)
{
    char messages[256];

	if(len > 256)
		len = 256;

	if(copy_from_user(messages, buff, len))
		return -EFAULT;

    printk("\n");
    if(strncmp(messages, "printPID", 8) == 0)
    {
        galDevice->printPID = galDevice->printPID ? gcvFALSE : gcvTRUE;
        printk("==>Change printPID to %s\n", galDevice->printPID ? "gcvTRUE" : "gcvFALSE");
    }
    else if(strncmp(messages, "profile", 7) == 0)
    {
        gctUINT32 idleTime, timeSlice;
        gctUINT32 start,end;
        timeSlice = 10000;
        start = gckOS_GetTicks();
        gckOS_IdleProfile(galDevice->os, &timeSlice, &idleTime);
        end = gckOS_GetTicks();

        printk("idle:total [%d, %d]\n", idleTime, timeSlice);
        printk("profile cost %d\n", end - start);
    }
    else if(strncmp(messages, "hang", 4) == 0)
    {
		galDevice->kernel->hardware->hang = galDevice->kernel->hardware->hang ? gcvFALSE : gcvTRUE;
    }
    else if(strncmp(messages, "reset", 5) == 0)
    {
        galDevice->reset = galDevice->reset ? gcvFALSE : gcvTRUE;
    }
#ifdef CONFIG_PXA_DVFM
    else if(strncmp(messages, "d2debug", 7) == 0)
    {
        galDevice->needD2DebugInfo = galDevice->needD2DebugInfo ? gcvFALSE : gcvTRUE;
    }
    else if(strncmp(messages, "D1", 2) == 0)
    {
        galDevice->enableD1 = galDevice->enableD1 ? gcvFALSE : gcvTRUE;
        gckOS_SetConstraint(galDevice->os, gcvTRUE, gcvTRUE);
    }
    else if(strncmp(messages, "D2", 2) == 0)
    {
        galDevice->enableD2 = galDevice->enableD2 ? gcvFALSE : gcvTRUE;
        gckOS_SetConstraint(galDevice->os, gcvTRUE, gcvTRUE);
    }
    else if(strncmp(messages, "D0", 2) == 0)
    {
        galDevice->enableD0CS= galDevice->enableD0CS ? gcvFALSE : gcvTRUE;
        gckOS_SetConstraint(galDevice->os, gcvTRUE, gcvTRUE);
    }
    else if(strncmp(messages, "CG", 2) == 0)
    {
        galDevice->enableCG= galDevice->enableCG ? gcvFALSE : gcvTRUE;
        gckOS_SetConstraint(galDevice->os, gcvTRUE, gcvTRUE);
    }
    else if(strncmp(messages, "needreset", 9) == 0)
    {
        galDevice->needResetAfterD2 = galDevice->needResetAfterD2 ? gcvFALSE : gcvTRUE;
    }
#endif
    else if(strncmp(messages, "su", 2) == 0)
    {
        gceSTATUS status;

        if(galDevice->kernel->hardware->chipPowerState != gcvPOWER_OFF)
        {
            status = gckHARDWARE_SetPowerManagementState(galDevice->kernel->hardware, gcvPOWER_OFF);
            if (gcmIS_ERROR(status))
            {
                return -1;
            }

            gckOS_SuspendInterrupt(galDevice->os);
            gckOS_ClockOff();
        }
    }
    else if(strncmp(messages, "re", 2) == 0)
    {
        gceSTATUS status;

        if(galDevice->kernel->hardware->chipPowerState != gcvPOWER_ON)
        {
            gckOS_ClockOn(0);
            gckOS_ResumeInterrupt(galDevice->os);

            status = gckHARDWARE_SetPowerManagementState(galDevice->kernel->hardware, gcvPOWER_ON);
		if (gcmIS_ERROR(status))
		{
			return -1;
		}
        }
    }
    else if(strncmp(messages, "stress", 6) == 0)
    {
        int i;
         /* struct vmalloc_info vmi; */

     /* {get_vmalloc_info(&vmi);printk("%s,%d,VmallocUsed: %8lu kB\n",__func__,__LINE__,vmi.used >> 10); } */

#ifdef _DEBUG
	gckOS_SetDebugLevel(gcvLEVEL_VERBOSE);
	gckOS_SetDebugZone(1023);
#endif

        for(i=0;i<20000;i++)
        {
            gceSTATUS status;
            static int count = 0;

            printk("count:%d\n",count++);
            printk("!!!\t");
            if(galDevice->kernel->hardware->chipPowerState != gcvPOWER_OFF)
            {
                status = gckHARDWARE_SetPowerManagementState(galDevice->kernel->hardware, gcvPOWER_OFF);
		if (gcmIS_ERROR(status))
		{
			return -1;
		}

                gckOS_SuspendInterrupt(galDevice->os);
                gckOS_ClockOff();

            }
            printk("@@@\t");
            if(galDevice->kernel->hardware->chipPowerState != gcvPOWER_ON)
            {
                gckOS_ClockOn(0);
                gckOS_ResumeInterrupt(galDevice->os);

                status = gckHARDWARE_SetPowerManagementState(galDevice->kernel->hardware, gcvPOWER_ON);
		if (gcmIS_ERROR(status))
		{
			return -1;
		}
            }
            printk("###\n");
        }

    }
    else if(strncmp(messages, "debug", 5) == 0)
    {
#ifdef _DEBUG
        static int count = 0;

        if(count%2 == 0)
        {
		gckOS_SetDebugLevel(gcvLEVEL_VERBOSE);
		gckOS_SetDebugZone(1023);
        }
        else
        {
            gckOS_SetDebugLevel(gcvLEVEL_NONE);
		gckOS_SetDebugZone(0);
        }
        count++;
#endif
    }
    else if(strncmp(messages, "16", 2) == 0)
    {
		printk("frequency change to 1/16\n");
        /* frequency change to 1/16 */
        gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x210));
        /* Loading the frequency scaler. */
	gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x010));

    }
    else if(strncmp(messages, "32", 2) == 0)
    {
		printk("frequency change to 1/32\n");
        /* frequency change to 1/32*/
        gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x208));
        /* Loading the frequency scaler. */
	gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x008));

    }
	else if(strncmp(messages, "64", 2) == 0)
    {
		printk("frequency change to 1/64\n");
        /* frequency change to 1/64 */
        gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x204));
        /* Loading the frequency scaler. */
	gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x004));

    }
    else if('1' == messages[0])
    {
        printk("frequency change to full speed\n");
        /* frequency change to full speed */
        gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x300));
        /* Loading the frequency scaler. */
	gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x100));

    }
    else if('2' == messages[0])
    {
        printk("frequency change to 1/2\n");
        /* frequency change to 1/2 */
        gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x280));
        /* Loading the frequency scaler. */
	gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x080));

    }
    else if('4' == messages[0])
    {
        printk("frequency change to 1/4\n");
        /* frequency change to 1/4 */
        gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x240));
        /* Loading the frequency scaler. */
	gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x040));

    }
    else if('8' == messages[0])
    {
        printk("frequency change to 1/8\n");
        /* frequency change to 1/8 */
        gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x220));
        /* Loading the frequency scaler. */
	gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x020));

    }
    else
    {
        printk("unknown echo\n");
    }

    return len;
}
/*******************************************************************************
**
**  _WorkaroundForFilterBlit
**
**  Workaround for the dirty region issue of filter blit.
**  It only exists for old GC300 before 2.0.2 (included).
**
**  INPUT:
**
**      gctHAL Hal
**          Pointer to HAL.
**
**  OUTPUT:
**
**      Nothing.
*/
static gceSTATUS
_WorkaroundForFilterBlit(
    IN gcoHAL Hal
    )
{
    gceSTATUS status;

    gcoSURF    srcSurf = gcvNULL;
    gcsRECT    srcRect;

    gcoSURF    dstSurf = gcvNULL;
    gcsRECT    dstRect;

    do
    {
        gcmERR_BREAK(gcoSURF_Construct(
            gcvNULL,
            256,
            256,
            1,
            gcvSURF_BITMAP,
            gcvSURF_A8R8G8B8,
            gcvPOOL_DEFAULT,
            &srcSurf
            ));

        gcmERR_BREAK(gcoSURF_Construct(
            gcvNULL,
            256,
            256,
            1,
            gcvSURF_BITMAP,
            gcvSURF_A8R8G8B8,
            gcvPOOL_DEFAULT,
            &dstSurf
            ));

        srcRect.left   = 0;
        srcRect.top    = 0;
        srcRect.right  = 64;
        srcRect.bottom = 16;

        dstRect.left   = 0;
        dstRect.top    = 0;
        dstRect.right  = 128;
        dstRect.bottom = 32;

        gcmERR_BREAK(gcoSURF_FilterBlit(
            srcSurf,
            dstSurf,
            &srcRect,
            &dstRect,
            gcvNULL
            ));

        gcmERR_BREAK(gcoSURF_Destroy(srcSurf));
        srcSurf = gcvNULL;

        gcmERR_BREAK(gcoSURF_Destroy(dstSurf));
        dstSurf = gcvNULL;
    }
    while(gcvFALSE);

    if (gcmIS_ERROR(status)) {
        gcmTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_HAL,
            "Failed to workarond for GC300.");

        if (srcSurf)
        {
            gcmVERIFY_OK(gcoSURF_Destroy(srcSurf));
        }

        if (dstSurf)
        {
            gcmVERIFY_OK(gcoSURF_Destroy(dstSurf));
        }
    }

    return status;
}
/*******************************************************************************
**
**  gckGALDEVICE_Construct
**
**  Constructor.
**
**  INPUT:
**
**  OUTPUT:
**
**      gckGALDEVICE * Device
**          Pointer to a variable receiving the gckGALDEVICE object pointer on
**          success.
*/
gceSTATUS
gckGALDEVICE_Construct(
    IN gctINT IrqLine,
    IN gctUINT32 RegisterMemBase,
    IN gctSIZE_T RegisterMemSize,
    IN gctINT IrqLine2D,
    IN gctUINT32 RegisterMemBase2D,
    IN gctSIZE_T RegisterMemSize2D,
    IN gctINT IrqLineVG,
    IN gctUINT32 RegisterMemBaseVG,
    IN gctSIZE_T RegisterMemSizeVG,
    IN gctUINT32 ContiguousBase,
    IN gctSIZE_T ContiguousSize,
    IN gctSIZE_T BankSize,
    IN gctINT FastClear,
    IN gctINT Compression,
    IN gctUINT32 PhysBaseAddr,
    IN gctUINT32 PhysSize,
    IN gctINT Signal,
    IN gctUINT LogFileSize,
    IN struct device *pdev,
    IN gctINT PowerManagement,
    OUT gckGALDEVICE *Device
    )
{
    gctUINT32 internalBaseAddress = 0, internalAlignment = 0;
    gctUINT32 externalBaseAddress = 0, externalAlignment = 0;
    gctUINT32 horizontalTileSize, verticalTileSize;
    struct resource* mem_region;
    gctUINT32 physAddr;
    gctUINT32 physical;
    gckGALDEVICE device;
    gceSTATUS status;
    gctINT32 i;
    gceHARDWARE_TYPE type;
    gckDB sharedDB = gcvNULL;
    gckKERNEL kernel = gcvNULL;

    gcmkHEADER_ARG("IrqLine=%d RegisterMemBase=0x%08x RegisterMemSize=%u "
                   "IrqLine2D=%d RegisterMemBase2D=0x%08x RegisterMemSize2D=%u "
                   "IrqLineVG=%d RegisterMemBaseVG=0x%08x RegisterMemSizeVG=%u "
                   "ContiguousBase=0x%08x ContiguousSize=%lu BankSize=%lu "
                   "FastClear=%d Compression=%d PhysBaseAddr=0x%x PhysSize=%d Signal=%d",
                   IrqLine, RegisterMemBase, RegisterMemSize,
                   IrqLine2D, RegisterMemBase2D, RegisterMemSize2D,
                   IrqLineVG, RegisterMemBaseVG, RegisterMemSizeVG,
                   ContiguousBase, ContiguousSize, BankSize, FastClear, Compression,
                   PhysBaseAddr, PhysSize, Signal);

    /* Allocate device structure. */
    device = kmalloc(sizeof(struct _gckGALDEVICE), GFP_KERNEL | __GFP_NOWARN);

    if (!device)
    {
        gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
    }

    memset(device, 0, sizeof(struct _gckGALDEVICE));

   device->dbgnode = gcvNULL;
   if(LogFileSize != 0)
   {
	if(gckDebugFileSystemCreateNode(LogFileSize,PARENT_FILE,DEBUG_FILE,&(device->dbgnode)) != 0)
	{
		gcmkTRACE_ZONE(
		gcvLEVEL_ERROR, gcvZONE_DRIVER,
		"%s(%d): Failed to create  the debug file system  %s/%s \n",
		__FUNCTION__, __LINE__,
		PARENT_FILE, DEBUG_FILE
		);
	}
	else
	{
		/*Everything is OK*/
	 	gckDebugFileSystemSetCurrentNode(device->dbgnode);
	}
    }
#ifdef CONFIG_PM
    /*Init runtime pm for gpu*/
    pm_runtime_enable(pdev);
    device->pmdev = pdev;
#endif

#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
    /*get gpu regulator*/
    device->gpu_regulator = regulator_get(pdev, "cpu_vddgpu");
    if (IS_ERR(device->gpu_regulator)) {
	gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
		"%s(%d): Failed to get gpu regulator  %s/%s \n",
		__FUNCTION__, __LINE__,
		PARENT_FILE, DEBUG_FILE);
	gcmkONERROR(gcvSTATUS_NOT_FOUND);
    }
#endif
    /*Initialize the clock structure*/
    if (IrqLine != -1) {
        device->clk_3d_core = clk_get(pdev, "gpu3d_clk");
        if (!IS_ERR(device->clk_3d_core)) {
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
            if (cpu_is_mx6q()) {
	            device->clk_3d_shader = clk_get(pdev, "gpu3d_shader_clk");
	            if (IS_ERR(device->clk_3d_shader)) {
	                IrqLine = -1;
	                clk_put(device->clk_3d_core);
	                device->clk_3d_core = NULL;
	                device->clk_3d_shader = NULL;
	                gckOS_Print("galcore: clk_get gpu3d_shader_clk failed, disable 3d!\n");
	            }
	          }
#else
	            device->clk_3d_axi = clk_get(pdev, "gpu3d_axi_clk");
	            device->clk_3d_shader = clk_get(pdev, "gpu3d_shader_clk");
	            if (IS_ERR(device->clk_3d_shader)) {
	                IrqLine = -1;
	                clk_put(device->clk_3d_core);
	                device->clk_3d_core = NULL;
	                device->clk_3d_shader = NULL;
	                gckOS_Print("galcore: clk_get gpu3d_shader_clk failed, disable 3d!\n");
	            }
#endif
        } else {
            IrqLine = -1;
            device->clk_3d_core = NULL;
            gckOS_Print("galcore: clk_get gpu3d_clk failed, disable 3d!\n");
        }
    }
    if ((IrqLine2D != -1) || (IrqLineVG != -1)) {
        device->clk_2d_core = clk_get(pdev, "gpu2d_clk");
        if (IS_ERR(device->clk_2d_core)) {
            IrqLine2D = -1;
            IrqLineVG = -1;
            device->clk_2d_core = NULL;
            gckOS_Print("galcore: clk_get 2d core clock failed, disable 2d/vg!\n");
        } else {
	    if (IrqLine2D != -1) {
                device->clk_2d_axi = clk_get(pdev, "gpu2d_axi_clk");
                if (IS_ERR(device->clk_2d_axi)) {
                    device->clk_2d_axi = NULL;
                    IrqLine2D = -1;
                    gckOS_Print("galcore: clk_get 2d axi clock failed, disable 2d\n");
                }
            }
            if (IrqLineVG != -1) {
                device->clk_vg_axi = clk_get(pdev, "openvg_axi_clk");
                if (IS_ERR(device->clk_vg_axi)) {
                    IrqLineVG = -1;
	                device->clk_vg_axi = NULL;
	                gckOS_Print("galcore: clk_get vg clock failed, disable vg!\n");
                }
            }
        }
    }

    if (IrqLine != -1)
    {
        device->requestedRegisterMemBases[gcvCORE_MAJOR]    = RegisterMemBase;
        device->requestedRegisterMemSizes[gcvCORE_MAJOR]    = RegisterMemSize;
    }

    if (IrqLine2D != -1)
    {
        device->requestedRegisterMemBases[gcvCORE_2D]       = RegisterMemBase2D;
        device->requestedRegisterMemSizes[gcvCORE_2D]       = RegisterMemSize2D;
    }

    if (IrqLineVG != -1)
    {
        device->requestedRegisterMemBases[gcvCORE_VG]       = RegisterMemBaseVG;
        device->requestedRegisterMemSizes[gcvCORE_VG]       = RegisterMemSizeVG;
    }

    device->requestedContiguousBase  = 0;
    device->requestedContiguousSize  = 0;


    for (i = 0; i < gcdMAX_GPU_COUNT; i++)
    {
        physical = device->requestedRegisterMemBases[i];

        /* Set up register memory region. */
        if (physical != 0)
        {
            mem_region = request_mem_region(
                physical, device->requestedRegisterMemSizes[i], "galcore register region"
                );

            if (mem_region == gcvNULL)
            {
                gcmkTRACE_ZONE(
                    gcvLEVEL_ERROR, gcvZONE_DRIVER,
                    "%s(%d): Failed to claim %lu bytes @ 0x%08X\n",
                    __FUNCTION__, __LINE__,
                    physical, device->requestedRegisterMemSizes[i]
                    );

                gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
            }

            device->registerBases[i] = (gctPOINTER) ioremap_nocache(
                physical, device->requestedRegisterMemSizes[i]);

            if (device->registerBases[i] == gcvNULL)
            {
                gcmkTRACE_ZONE(
                    gcvLEVEL_ERROR, gcvZONE_DRIVER,
                    "%s(%d): Unable to map %ld bytes @ 0x%08X\n",
                    __FUNCTION__, __LINE__,
                    physical, device->requestedRegisterMemSizes[i]
                    );

                gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
            }

            physical += device->requestedRegisterMemSizes[i];
        }
        else
        {
            device->registerBases[i] = gcvNULL;
        }
    }

    /* Set the base address */
    device->baseAddress = PhysBaseAddr;

    /* Construct the gckOS object. */
    gcmkONERROR(gckOS_Construct(device, &device->os));

    if (IrqLine != -1)
    {
        /* Construct the gckKERNEL object. */
        gcmkONERROR(gckKERNEL_Construct(
            device->os, gcvCORE_MAJOR, device,
            gcvNULL, &device->kernels[gcvCORE_MAJOR]));

        sharedDB = device->kernels[gcvCORE_MAJOR]->db;

        /* Initialize core mapping */
        for (i = 0; i < 8; i++)
        {
            device->coreMapping[i] = gcvCORE_MAJOR;
        }

        /* Setup the ISR manager. */
        gcmkONERROR(gckHARDWARE_SetIsrManager(
            device->kernels[gcvCORE_MAJOR]->hardware,
            (gctISRMANAGERFUNC) gckGALDEVICE_Setup_ISR,
            (gctISRMANAGERFUNC) gckGALDEVICE_Release_ISR,
            device
            ));

        gcmkONERROR(gckHARDWARE_SetFastClear(
            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. */
        gcmkONERROR(gckCOMMAND_Start(device->kernels[gcvCORE_MAJOR]->command));
#endif
    }
    else
    {
        device->kernels[gcvCORE_MAJOR] = gcvNULL;
    }

    if (IrqLine2D != -1)
    {
        gcmkONERROR(gckKERNEL_Construct(
            device->os, gcvCORE_2D, device,
            sharedDB, &device->kernels[gcvCORE_2D]));

        if (sharedDB == gcvNULL) sharedDB = device->kernels[gcvCORE_2D]->db;

        /* Verify the hardware type */
        gcmkONERROR(gckHARDWARE_GetType(device->kernels[gcvCORE_2D]->hardware, &type));

        if (type != gcvHARDWARE_2D)
        {
            gcmkTRACE_ZONE(
                gcvLEVEL_ERROR, gcvZONE_DRIVER,
                "%s(%d): Unexpected hardware type: %d\n",
                __FUNCTION__, __LINE__,
                type
                );

            gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
        }

        /* Initialize core mapping */
        if (device->kernels[gcvCORE_MAJOR] == gcvNULL)
        {
            for (i = 0; i < 8; i++)
            {
                device->coreMapping[i] = gcvCORE_2D;
            }
        }
        else
        {
            device->coreMapping[gcvHARDWARE_2D] = gcvCORE_2D;
        }

        /* Setup the ISR manager. */
        gcmkONERROR(gckHARDWARE_SetIsrManager(
            device->kernels[gcvCORE_2D]->hardware,
            (gctISRMANAGERFUNC) gckGALDEVICE_Setup_ISR_2D,
            (gctISRMANAGERFUNC) gckGALDEVICE_Release_ISR_2D,
            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));
#endif
    }
    else
    {
        device->kernels[gcvCORE_2D] = gcvNULL;
    }

    if (IrqLineVG != -1)
    {
#if gcdENABLE_VG
        gcmkONERROR(gckKERNEL_Construct(
            device->os, gcvCORE_VG, device,
            sharedDB, &device->kernels[gcvCORE_VG]));
        /* Initialize core mapping */
        if (device->kernels[gcvCORE_MAJOR] == gcvNULL
            && device->kernels[gcvCORE_2D] == gcvNULL
            )
        {
            for (i = 0; i < 8; i++)
            {
                device->coreMapping[i] = gcvCORE_VG;
            }
        }
        else
        {
            device->coreMapping[gcvHARDWARE_VG] = gcvCORE_VG;
        }


        gcmkONERROR(gckVGHARDWARE_SetPowerManagement(
            device->kernels[gcvCORE_VG]->vg->hardware,
            PowerManagement
            ));
#endif
    }
    else
    {
        device->kernels[gcvCORE_VG] = gcvNULL;
    }

    /* Initialize the ISR. */
    device->irqLines[gcvCORE_MAJOR] = IrqLine;
    device->irqLines[gcvCORE_2D]    = IrqLine2D;
    device->irqLines[gcvCORE_VG]    = IrqLineVG;

    /* Initialize the kernel thread semaphores. */
    for (i = 0; i < gcdMAX_GPU_COUNT; i++)
    {
        if (device->irqLines[i] != -1) sema_init(&device->semas[i], 0);
    }

    device->signal = Signal;

    for (i = 0; i < gcdMAX_GPU_COUNT; i++)
    {
        if (device->kernels[i] != gcvNULL) break;
    }

    if (i == gcdMAX_GPU_COUNT)
	{
		gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
	}

#if gcdENABLE_VG
    if (i == gcvCORE_VG)
    {
        /* Query the ceiling of the system memory. */
        gcmkONERROR(gckVGHARDWARE_QuerySystemMemory(
                device->kernels[i]->vg->hardware,
                &device->systemMemorySize,
                &device->systemMemoryBaseAddress
                ));
            /* query the amount of video memory */
        gcmkONERROR(gckVGHARDWARE_QueryMemory(
            device->kernels[i]->vg->hardware,
            &device->internalSize, &internalBaseAddress, &internalAlignment,
            &device->externalSize, &externalBaseAddress, &externalAlignment,
            &horizontalTileSize, &verticalTileSize
            ));
    }
    else
#endif
    {
        /* Query the ceiling of the system memory. */
        gcmkONERROR(gckHARDWARE_QuerySystemMemory(
                device->kernels[i]->hardware,
                &device->systemMemorySize,
                &device->systemMemoryBaseAddress
                ));

            /* query the amount of video memory */
        gcmkONERROR(gckHARDWARE_QueryMemory(
            device->kernels[i]->hardware,
            &device->internalSize, &internalBaseAddress, &internalAlignment,
            &device->externalSize, &externalBaseAddress, &externalAlignment,
            &horizontalTileSize, &verticalTileSize
            ));
    }


    /* Grab the first availiable kernel */
    for (i = 0; i < gcdMAX_GPU_COUNT; i++)
    {
        if (device->irqLines[i] != -1)
        {
            kernel = device->kernels[i];
            break;
        }
    }

    /* Set up the internal memory region. */
    if (device->internalSize > 0)
    {
        status = gckVIDMEM_Construct(
            device->os,
            internalBaseAddress, device->internalSize, internalAlignment,
            0, &device->internalVidMem
            );

        if (gcmIS_ERROR(status))
        {
            /* Error, disable internal heap. */
            device->internalSize = 0;
        }
        else
        {
            /* Map internal memory. */
            device->internalLogical
                = (gctPOINTER) ioremap_nocache(physical, device->internalSize);

            if (device->internalLogical == gcvNULL)
            {
                gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
            }

            device->internalPhysical = (gctPHYS_ADDR)(gctUINTPTR_T) physical;
            device->internalPhysicalName = gcmPTR_TO_NAME(device->internalPhysical);
            physical += device->internalSize;
        }
    }

    if (device->externalSize > 0)
    {
        /* create the external memory heap */
        status = gckVIDMEM_Construct(
            device->os,
            externalBaseAddress, device->externalSize, externalAlignment,
            0, &device->externalVidMem
            );

        if (gcmIS_ERROR(status))
        {
            /* Error, disable internal heap. */
            device->externalSize = 0;
        }
        else
        {
            /* Map external memory. */
            device->externalLogical
                = (gctPOINTER) ioremap_nocache(physical, device->externalSize);

            if (device->externalLogical == gcvNULL)
            {
                gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
            }

            device->externalPhysical = (gctPHYS_ADDR)(gctUINTPTR_T) physical;
            device->externalPhysicalName = gcmPTR_TO_NAME(device->externalPhysical);
            physical += device->externalSize;
        }
    }

    /* set up the contiguous memory */
    device->contiguousSize = ContiguousSize;

    if (ContiguousSize > 0)
    {
        if (ContiguousBase == 0)
        {
            while (device->contiguousSize > 0)
            {
                /* Allocate contiguous memory. */
                status = _AllocateMemory(
                    device,
                    device->contiguousSize,
                    &device->contiguousBase,
                    &device->contiguousPhysical,
                    &physAddr
                    );

                if (gcmIS_SUCCESS(status))
                {
                    device->contiguousPhysicalName = gcmPTR_TO_NAME(device->contiguousPhysical);
                    status = gckVIDMEM_Construct(
                        device->os,
                        physAddr | device->systemMemoryBaseAddress,
                        device->contiguousSize,
                        64,
                        BankSize,
                        &device->contiguousVidMem
                        );

                    if (gcmIS_SUCCESS(status))
                    {
                        break;
                    }

                    gcmkONERROR(_FreeMemory(
                        device,
                        device->contiguousBase,
                        device->contiguousPhysical
                        ));

                    gcmRELEASE_NAME(device->contiguousPhysicalName);
                    device->contiguousBase     = gcvNULL;
                    device->contiguousPhysical = gcvNULL;
                }

                if (device->contiguousSize <= (4 << 20))
                {
                    device->contiguousSize = 0;
                }
                else
                {
                    device->contiguousSize -= (4 << 20);
                }
            }
        }
        else
        {
            /* Create the contiguous memory heap. */
            status = gckVIDMEM_Construct(
                device->os,
                ContiguousBase | device->systemMemoryBaseAddress,
                ContiguousSize,
                64, BankSize,
                &device->contiguousVidMem
                );

            if (gcmIS_ERROR(status))
            {
                /* Error, disable contiguous memory pool. */
                device->contiguousVidMem = gcvNULL;
                device->contiguousSize   = 0;
            }
            else
            {
                mem_region = request_mem_region(
                    ContiguousBase, ContiguousSize, "galcore managed memory"
                    );

                if (mem_region == gcvNULL)
                {
                    gcmkTRACE_ZONE(
                        gcvLEVEL_ERROR, gcvZONE_DRIVER,
                        "%s(%d): Failed to claim %ld bytes @ 0x%08X\n",
                        __FUNCTION__, __LINE__,
                        ContiguousSize, ContiguousBase
                        );

                    gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
                }

                device->requestedContiguousBase  = ContiguousBase;
                device->requestedContiguousSize  = ContiguousSize;

#if !gcdDYNAMIC_MAP_RESERVED_MEMORY && gcdENABLE_VG
                if (gcmIS_CORE_PRESENT(device, gcvCORE_VG))
                {
                    device->contiguousBase
#if gcdPAGED_MEMORY_CACHEABLE
                        = (gctPOINTER) ioremap_cached(ContiguousBase, ContiguousSize);
#else
                        = (gctPOINTER) ioremap_nocache(ContiguousBase, ContiguousSize);
#endif
                    if (device->contiguousBase == gcvNULL)
                    {
                        device->contiguousVidMem = gcvNULL;
                        device->contiguousSize = 0;

                        gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
                    }
                }
#endif

                device->contiguousPhysical = gcvNULL;
                device->contiguousPhysicalName = 0;
                device->contiguousSize     = ContiguousSize;
                device->contiguousMapped   = gcvTRUE;
            }
        }
    }
Exemple #16
0
static int __devinit gpu_probe(struct platform_device *pdev)
#endif
{
    int ret = -ENODEV;
    gcsMODULE_PARAMETERS moduleParam = {
#if gcdMULTI_GPU || gcdMULTI_GPU_AFFINITY
#else
        .irqLine            = irqLine,
        .registerMemBase    = registerMemBase,
        .registerMemSize    = registerMemSize,
#endif
        .irqLine2D          = irqLine2D,
        .registerMemBase2D  = registerMemBase2D,
        .registerMemSize2D  = registerMemSize2D,
        .irqLineVG          = irqLineVG,
        .registerMemBaseVG  = registerMemBaseVG,
        .registerMemSizeVG  = registerMemSizeVG,
        .contiguousSize     = contiguousSize,
        .contiguousBase     = contiguousBase,
        .bankSize           = bankSize,
        .fastClear          = fastClear,
        .compression        = compression,
        .powerManagement    = powerManagement,
        .gpuProfiler        = gpuProfiler,
        .signal             = signal,
        .baseAddress        = baseAddress,
        .physSize           = physSize,
        .logFileSize        = logFileSize,
        .recovery           = recovery,
        .stuckDump          = stuckDump,
        .showArgs           = showArgs,
        .gpu3DMinClock      = gpu3DMinClock,
    };

    gcmkHEADER();

    platform.device = pdev;

    if (platform.ops->getPower)
    {
        if (gcmIS_ERROR(platform.ops->getPower(&platform)))
        {
            gcmkFOOTER_NO();
            return ret;
        }
    }

    if (platform.ops->adjustParam)
    {
        /* Override default module param. */
        platform.ops->adjustParam(&platform, &moduleParam);

        /* Update module param because drv_init() uses them directly. */
        _UpdateModuleParam(&moduleParam);
    }

    ret = drv_init();

    if (!ret)
    {
        platform_set_drvdata(pdev, galDevice);

        gcmkFOOTER_NO();
        return ret;
    }

    gcmkFOOTER_ARG(KERN_INFO "Failed to register gpu driver: %d\n", ret);
    return ret;
}
/*******************************************************************************
**	InitializeVGProfiler
**
**	Initialize the profiler for the context provided.
**
**	Arguments:
**
**		VGContext Context
**			Pointer to a new VGContext object.
*/
void
InitializeVGProfiler(
    _VGContext * Context
	)
{
	gceSTATUS status;
	gctUINT rev;
        char *env;

	status = gcoPROFILER_Initialize(Context->hal);

	if (gcmIS_ERROR(status))
	{
		Context->profiler.enable = gcvFALSE;
		return;
	}

    /* Clear the profiler. */
	gcmVERIFY_OK(
		gcoOS_ZeroMemory(&Context->profiler, gcmSIZEOF(Context->profiler)));

    gcoOS_GetEnv(Context->os, "VP_COUNTER_FILTER", &env);
    if ((env == gcvNULL) || (env[0] ==0))
    {
        Context->profiler.drvEnable =
            Context->profiler.timeEnable =
            Context->profiler.memEnable = gcvTRUE;
    }
    else
    {
        gctSIZE_T bitsLen;
        gcoOS_StrLen(env, &bitsLen);
        if (bitsLen > 0)
        {
            Context->profiler.timeEnable = (env[0] == '1');
        }
        else
        {
            Context->profiler.timeEnable = gcvTRUE;
        }
        if (bitsLen > 1)
        {
            Context->profiler.memEnable = (env[1] == '1');
        }
        else
        {
            Context->profiler.memEnable = gcvTRUE;
        }
        if (bitsLen > 4)
        {
            Context->profiler.drvEnable = (env[4] == '1');
        }
        else
        {
            Context->profiler.drvEnable = gcvTRUE;
        }
    }

    Context->profiler.enable = gcvTRUE;

#if gcdNEW_PROFILER_FILE
    {
        /* Write Generic Info. */
        char* infoCompany = "Vivante Corporation";
        char* infoVersion = "1.0";
        char  infoRevision[255] = {'\0'};   /* read from hw */
        char* infoRenderer = Context->chipName;
        char* infoDriver = "OpenVG 1.1";
        gctUINT offset = 0;
        rev = Context->revision;
#define BCD(digit)      ((rev >> (digit * 4)) & 0xF)
        gcoOS_MemFill(infoRevision, 0, gcmSIZEOF(infoRevision));
        gcoOS_MemFill(infoRevision, 0, gcmSIZEOF(infoRevision));
        if (BCD(3) == 0)
        {
            /* Old format. */
            gcoOS_PrintStrSafe(infoRevision, gcmSIZEOF(infoRevision),
                &offset, "revision=\"%d.%d\" ", BCD(1), BCD(0));
        }
        else
        {
            /* New format. */
            gcoOS_PrintStrSafe(infoRevision, gcmSIZEOF(infoRevision),
                &offset, "revision=\"%d.%d.%d_rc%d\" ",
                BCD(3), BCD(2), BCD(1), BCD(0));
        }


        gcmWRITE_CONST(VPG_INFO);

        gcmWRITE_CONST(VPC_INFOCOMPANY);
        gcmWRITE_STRING(infoCompany);
        gcmWRITE_CONST(VPC_INFOVERSION);
        gcmWRITE_STRING(infoVersion);
        gcmWRITE_CONST(VPC_INFORENDERER);
        gcmWRITE_STRING(infoRenderer);
        gcmWRITE_CONST(VPC_INFOREVISION);
        gcmWRITE_STRING(infoRevision);
        gcmWRITE_CONST(VPC_INFODRIVER);
        gcmWRITE_STRING(infoDriver);

        gcmWRITE_CONST(VPG_END);
    }
#else
    /* Print generic info */
    _Print(Context, "<GenericInfo company=\"Vivante Corporation\" "
		"version=\"%d.%d\" renderer=\"%s\" ",
		1, 0, Context->chipName);

   	rev = Context->revision;
#define BCD(digit)		((rev >> (digit * 4)) & 0xF)
   	if (BCD(3) == 0)
   	{
   		/* Old format. */
   		_Print(Context, "revision=\"%d.%d\" ", BCD(1), BCD(0));
   	}
   	else
   	{
   		/* New format. */
   		_Print(Context, "revision=\"%d.%d.%d_rc%d\" ",
   			   BCD(3), BCD(2), BCD(1), BCD(0));
   	}
    _Print(Context, "driver=\"%s\" />\n", "OpenVG 1.1");
#endif

	gcoOS_GetTime(&Context->profiler.frameStart);
    Context->profiler.frameStartTimeusec     = Context->profiler.frameStart;
    Context->profiler.primitiveStartTimeusec = Context->profiler.frameStart;
	gcoOS_GetCPUTime(&Context->profiler.frameStartCPUTimeusec);
}
Exemple #18
0
static int drv_init(void)
#endif
{
    int ret;
    int result = -EINVAL;
    gceSTATUS status;
    gckGALDEVICE device = gcvNULL;
    struct class* device_class = gcvNULL;

    gcsDEVICE_CONSTRUCT_ARGS args = {
        .recovery           = recovery,
        .stuckDump          = stuckDump,
        .gpu3DMinClock      = gpu3DMinClock,
        .contiguousRequested = contiguousRequested,
        .platform           = &platform,
        .mmu                = mmu,
    };

    gcmkHEADER();

    printk(KERN_INFO "Galcore version %d.%d.%d.%d\n",
        gcvVERSION_MAJOR, gcvVERSION_MINOR, gcvVERSION_PATCH, gcvVERSION_BUILD);

#if !VIVANTE_PROFILER_PM
    /* when enable gpu profiler, we need to turn off gpu powerMangement */
    if (gpuProfiler)
    {
        powerManagement = 0;
    }
#endif

    if (showArgs)
    {
        gckOS_DumpParam();
    }

    if (logFileSize != 0)
    {
        gckDEBUGFS_Initialize();
    }

    /* Create the GAL device. */
    status = gckGALDEVICE_Construct(
#if gcdMULTI_GPU || gcdMULTI_GPU_AFFINITY
        irqLine3D0,
        registerMemBase3D0, registerMemSize3D0,
        irqLine3D1,
        registerMemBase3D1, registerMemSize3D1,
#else
        irqLine,
        registerMemBase, registerMemSize,
#endif
        irqLine2D,
        registerMemBase2D, registerMemSize2D,
        irqLineVG,
        registerMemBaseVG, registerMemSizeVG,
        contiguousBase, contiguousSize,
        bankSize, fastClear, compression, baseAddress, physSize, signal,
        logFileSize,
        powerManagement,
        gpuProfiler,
        &args,
        &device
    );

    if (gcmIS_ERROR(status))
    {
        gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
                       "%s(%d): Failed to create the GAL device: status=%d\n",
                       __FUNCTION__, __LINE__, status);

        goto OnError;
    }

    /* Start the GAL device. */
    gcmkONERROR(gckGALDEVICE_Start(device));

    if ((physSize != 0)
       && (device->kernels[gcvCORE_MAJOR] != gcvNULL)
       && (device->kernels[gcvCORE_MAJOR]->hardware->mmuVersion != 0))
    {
        /* Reset the base address */
        device->baseAddress = 0;
    }

    /* Register the character device. */
    ret = register_chrdev(major, DEVICE_NAME, &driver_fops);

    if (ret < 0)
    {
        gcmkTRACE_ZONE(
            gcvLEVEL_ERROR, gcvZONE_DRIVER,
            "%s(%d): Could not allocate major number for mmap.\n",
            __FUNCTION__, __LINE__
            );

        gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
    }

    if (major == 0)
    {
        major = ret;
    }

    /* Create the device class. */
    device_class = class_create(THIS_MODULE, "graphics_class");

    if (IS_ERR(device_class))
    {
        gcmkTRACE_ZONE(
            gcvLEVEL_ERROR, gcvZONE_DRIVER,
            "%s(%d): Failed to create the class.\n",
            __FUNCTION__, __LINE__
            );

        gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
    }

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
    device_create(device_class, NULL, MKDEV(major, 0), NULL, DEVICE_NAME);
#else
    device_create(device_class, NULL, MKDEV(major, 0), DEVICE_NAME);
#endif

    galDevice = device;
    gpuClass  = device_class;

#if gcdMULTI_GPU || gcdMULTI_GPU_AFFINITY
    gcmkTRACE_ZONE(
        gcvLEVEL_INFO, gcvZONE_DRIVER,
        "%s(%d): irqLine3D0=%d, contiguousSize=%lu, memBase3D0=0x%lX\n",
        __FUNCTION__, __LINE__,
        irqLine3D0, contiguousSize, registerMemBase3D0
        );
#else
    gcmkTRACE_ZONE(
        gcvLEVEL_INFO, gcvZONE_DRIVER,
        "%s(%d): irqLine=%d, contiguousSize=%lu, memBase=0x%lX\n",
        __FUNCTION__, __LINE__,
        irqLine, contiguousSize, registerMemBase
        );
#endif

    /* Success. */
    gcmkFOOTER_NO();
    return 0;

OnError:
    /* Roll back. */
    if (device_class != gcvNULL)
    {
        device_destroy(device_class, MKDEV(major, 0));
        class_destroy(device_class);
    }

    if (device != gcvNULL)
    {
        gcmkVERIFY_OK(gckGALDEVICE_Stop(device));
        gcmkVERIFY_OK(gckGALDEVICE_Destroy(device));
    }

    gcmkFOOTER();
    return result;
}
gceSTATUS
gcoPROFILER_EndDraw(
    IN gcoHAL Hal,
    IN gctBOOL FirstDraw
    )
{
/*#if	(PROFILE_HAL_COUNTERS || PROFILE_HW_COUNTERS)*/
	gcsHAL_INTERFACE iface;
    gceSTATUS status;
    static gcsPROFILER previous;
    static gcsPROFILER_COUNTERS    precounters;

/*#endif*/

    gcmHEADER();

	if (!gcPLS.hal->profiler.enable)
	{
        gcmFOOTER_NO();
		return gcvSTATUS_OK;
	}

/*#if PROFILE_HAL_COUNTERS*/
    if (gcPLS.hal->profiler.enableHal)
    {
#if gcdNEW_PROFILER_FILE
        if(FirstDraw == gcvTRUE)
            {
            gcoOS_ZeroMemory(&previous, gcmSIZEOF(previous));
            }

        gcmWRITE_CONST(VPG_HAL);

        gcmWRITE_COUNTER(VPC_HALVERTBUFNEWBYTEALLOC, gcPLS.hal->profiler.vertexBufferNewBytesAlloc-previous.vertexBufferNewBytesAlloc);
        gcmWRITE_COUNTER(VPC_HALVERTBUFTOTALBYTEALLOC, gcPLS.hal->profiler.vertexBufferTotalBytesAlloc-previous.vertexBufferTotalBytesAlloc);
        gcmWRITE_COUNTER(VPC_HALVERTBUFNEWOBJALLOC, gcPLS.hal->profiler.vertexBufferNewObjectsAlloc-previous.vertexBufferNewObjectsAlloc);
        gcmWRITE_COUNTER(VPC_HALVERTBUFTOTALOBJALLOC, gcPLS.hal->profiler.vertexBufferTotalObjectsAlloc-previous.vertexBufferTotalObjectsAlloc);

        gcmWRITE_COUNTER(VPC_HALINDBUFNEWBYTEALLOC, gcPLS.hal->profiler.indexBufferNewBytesAlloc-previous.indexBufferNewBytesAlloc);
        gcmWRITE_COUNTER(VPC_HALINDBUFTOTALBYTEALLOC, gcPLS.hal->profiler.indexBufferTotalBytesAlloc-previous.indexBufferTotalBytesAlloc);
        gcmWRITE_COUNTER(VPC_HALINDBUFNEWOBJALLOC, gcPLS.hal->profiler.indexBufferNewObjectsAlloc-previous.indexBufferNewObjectsAlloc);
        gcmWRITE_COUNTER(VPC_HALINDBUFTOTALOBJALLOC, gcPLS.hal->profiler.indexBufferTotalObjectsAlloc-previous.indexBufferTotalObjectsAlloc);

        gcmWRITE_COUNTER(VPC_HALTEXBUFNEWBYTEALLOC, gcPLS.hal->profiler.textureBufferNewBytesAlloc-previous.textureBufferNewBytesAlloc);
        gcmWRITE_COUNTER(VPC_HALTEXBUFTOTALBYTEALLOC, gcPLS.hal->profiler.textureBufferTotalBytesAlloc-previous.textureBufferTotalBytesAlloc);
        gcmWRITE_COUNTER(VPC_HALTEXBUFNEWOBJALLOC, gcPLS.hal->profiler.textureBufferNewObjectsAlloc-previous.textureBufferNewObjectsAlloc);
        gcmWRITE_COUNTER(VPC_HALTEXBUFTOTALOBJALLOC, gcPLS.hal->profiler.textureBufferTotalObjectsAlloc-previous.textureBufferTotalObjectsAlloc);

        gcmWRITE_CONST(VPG_END);
        gcoOS_MemCopy(&previous,&gcPLS.hal->profiler,gcmSIZEOF(gcsPROFILER));
#else
    	gcmWRITE_STRING("<HALCounters>\n");

	    gcmPRINT_XML_COUNTER(vertexBufferNewBytesAlloc);
    	gcmPRINT_XML_COUNTER(vertexBufferTotalBytesAlloc);
	    gcmPRINT_XML_COUNTER(vertexBufferNewObjectsAlloc);
    	gcmPRINT_XML_COUNTER(vertexBufferTotalObjectsAlloc);

	    gcmPRINT_XML_COUNTER(indexBufferNewBytesAlloc);
    	gcmPRINT_XML_COUNTER(indexBufferTotalBytesAlloc);
	    gcmPRINT_XML_COUNTER(indexBufferNewObjectsAlloc);
    	gcmPRINT_XML_COUNTER(indexBufferTotalObjectsAlloc);

	    gcmPRINT_XML_COUNTER(textureBufferNewBytesAlloc);
    	gcmPRINT_XML_COUNTER(textureBufferTotalBytesAlloc);
	    gcmPRINT_XML_COUNTER(textureBufferNewObjectsAlloc);
    	gcmPRINT_XML_COUNTER(textureBufferTotalObjectsAlloc);

	    gcmWRITE_STRING("</HALCounters>\n");
#endif

	    /* Reset per-frame counters. */
	}
/*#endif*/

/*#if PROFILE_HW_COUNTERS*/
    /* gcvHAL_READ_ALL_PROFILE_REGISTERS. */
    if (gcPLS.hal->profiler.enableHW)
    {
		if (gcPLS.hal->profiler.isSyncMode)
			gcoHAL_Commit(gcvNULL, gcvTRUE);
#if VIVANTE_PROFILER_PERDRAW
            /* Set Register clear Flag. */
            iface.command = gcvHAL_READ_PROFILER_REGISTER_SETTING;
            iface.u.SetProfilerRegisterClear.bclear = gcvFALSE;

            /* Call the kernel. */
            status = gcoOS_DeviceControl(gcvNULL,
                                       IOCTL_GCHAL_INTERFACE,
                                       &iface, gcmSIZEOF(iface),
                                       &iface, gcmSIZEOF(iface));

		/* Verify result. */
		if (gcmIS_ERROR(status))    return gcvSTATUS_GENERIC_IO;
#endif
		iface.command = gcvHAL_READ_ALL_PROFILE_REGISTERS;

		/* Call the kernel. */
		status = gcoOS_DeviceControl(gcvNULL,
									 IOCTL_GCHAL_INTERFACE,
									 &iface, gcmSIZEOF(iface),
									 &iface, gcmSIZEOF(iface));

		/* Verify result. */
		if (gcmNO_ERROR(status))
		{
        #define gcmCOUNTERCOMPARE(name)    ((iface.u.RegisterProfileData.counters.name) - (precounters.name))
        #define gcmDRAWCOUNTERPRE(name)   (precounters.name)

#if gcdNEW_PROFILER_FILE
            if(FirstDraw == gcvFALSE)
                {
                gcoOS_ZeroMemory(&precounters, gcmSIZEOF(precounters));

                gcmDRAWCOUNTERPRE(vs_inst_counter) =   gcPLS.hal->profiler.prevVSInstCount;
		   gcmDRAWCOUNTERPRE(vtx_branch_inst_counter) =	gcPLS.hal->profiler.prevVSBranchInstCount ;
		   gcmDRAWCOUNTERPRE(vtx_texld_inst_counter) = gcPLS.hal->profiler.prevVSTexInstCount;
                gcmDRAWCOUNTERPRE(rendered_vertice_counter) =	gcPLS.hal->profiler.prevVSVertexCount;

                gcmDRAWCOUNTERPRE(ps_inst_counter) =gcPLS.hal->profiler.prevPSInstCount;
                gcmDRAWCOUNTERPRE(pxl_branch_inst_counter) = gcPLS.hal->profiler.prevPSBranchInstCount;
                gcmDRAWCOUNTERPRE(pxl_texld_inst_counter) =	gcPLS.hal->profiler.prevPSTexInstCount;
                gcmDRAWCOUNTERPRE(rendered_pixel_counter) = gcPLS.hal->profiler.prevPSPixelCount;
                }
            gcmWRITE_CONST(VPG_HW);
            gcmWRITE_CONST(VPG_GPU);
            gcmWRITE_COUNTER(VPC_GPUREAD64BYTE, gcmCOUNTERCOMPARE(gpuTotalRead64BytesPerFrame));
            gcmWRITE_COUNTER(VPC_GPUWRITE64BYTE, gcmCOUNTERCOMPARE(gpuTotalWrite64BytesPerFrame));
            gcmWRITE_COUNTER(VPC_GPUCYCLES, gcmCOUNTERCOMPARE(gpuCyclesCounter));
            gcmWRITE_COUNTER(VPC_GPUTOTALCYCLES, gcmCOUNTERCOMPARE(gpuTotalCyclesCounter));
            gcmWRITE_COUNTER(VPC_GPUIDLECYCLES, gcmCOUNTERCOMPARE(gpuIdleCyclesCounter));
            gcmWRITE_CONST(VPG_END);

            gcmWRITE_CONST(VPG_VS);
            gcmWRITE_COUNTER(VPC_VSINSTCOUNT, gcmCOUNTERCOMPARE(vs_inst_counter));
            gcmWRITE_COUNTER(VPC_VSBRANCHINSTCOUNT, gcmCOUNTERCOMPARE(vtx_branch_inst_counter));
            gcmWRITE_COUNTER(VPC_VSTEXLDINSTCOUNT, gcmCOUNTERCOMPARE(vtx_texld_inst_counter));
            gcmWRITE_COUNTER(VPC_VSRENDEREDVERTCOUNT, gcmCOUNTERCOMPARE(rendered_vertice_counter));
            gcmWRITE_CONST(VPG_END);

            gcmWRITE_CONST(VPG_PA);
            gcmWRITE_COUNTER(VPC_PAINVERTCOUNT, gcmCOUNTERCOMPARE(pa_input_vtx_counter));
            gcmWRITE_COUNTER(VPC_PAINPRIMCOUNT, gcmCOUNTERCOMPARE(pa_input_prim_counter));
            gcmWRITE_COUNTER(VPC_PAOUTPRIMCOUNT, gcmCOUNTERCOMPARE(pa_output_prim_counter));
            gcmWRITE_COUNTER(VPC_PADEPTHCLIPCOUNT, gcmCOUNTERCOMPARE(pa_depth_clipped_counter));
            gcmWRITE_COUNTER(VPC_PATRIVIALREJCOUNT, gcmCOUNTERCOMPARE(pa_trivial_rejected_counter));
            gcmWRITE_COUNTER(VPC_PACULLCOUNT, gcmCOUNTERCOMPARE(pa_culled_counter));
            gcmWRITE_CONST(VPG_END);

            gcmWRITE_CONST(VPG_SETUP);
            gcmWRITE_COUNTER(VPC_SETRIANGLECOUNT, gcmCOUNTERCOMPARE(se_culled_triangle_count));
            gcmWRITE_COUNTER(VPC_SELINECOUNT, gcmCOUNTERCOMPARE(se_culled_lines_count));
            gcmWRITE_CONST(VPG_END);

            gcmWRITE_CONST(VPG_RA);
            gcmWRITE_COUNTER(VPC_RAVALIDPIXCOUNT, gcmCOUNTERCOMPARE(ra_valid_pixel_count));
            gcmWRITE_COUNTER(VPC_RATOTALQUADCOUNT, gcmCOUNTERCOMPARE(ra_total_quad_count));
            gcmWRITE_COUNTER(VPC_RAVALIDQUADCOUNTEZ, gcmCOUNTERCOMPARE(ra_valid_quad_count_after_early_z));
            gcmWRITE_COUNTER(VPC_RATOTALPRIMCOUNT, gcmCOUNTERCOMPARE(ra_total_primitive_count));
            gcmWRITE_COUNTER(VPC_RAPIPECACHEMISSCOUNT, gcmCOUNTERCOMPARE(ra_pipe_cache_miss_counter));
            gcmWRITE_COUNTER(VPC_RAPREFCACHEMISSCOUNT, gcmCOUNTERCOMPARE(ra_prefetch_cache_miss_counter));
            gcmWRITE_COUNTER(VPC_RAEEZCULLCOUNT, gcmCOUNTERCOMPARE(ra_eez_culled_counter));
            gcmWRITE_CONST(VPG_END);

            gcmWRITE_CONST(VPG_TX);
            gcmWRITE_COUNTER(VPC_TXTOTBILINEARREQ, gcmCOUNTERCOMPARE(tx_total_bilinear_requests));
            gcmWRITE_COUNTER(VPC_TXTOTTRILINEARREQ, gcmCOUNTERCOMPARE(tx_total_trilinear_requests));
            gcmWRITE_COUNTER(VPC_TXTOTTEXREQ, gcmCOUNTERCOMPARE(tx_total_texture_requests));
            gcmWRITE_COUNTER(VPC_TXMEMREADCOUNT, gcmCOUNTERCOMPARE(tx_mem_read_count));
            gcmWRITE_COUNTER(VPC_TXMEMREADIN8BCOUNT, gcmCOUNTERCOMPARE(tx_mem_read_in_8B_count));
            gcmWRITE_COUNTER(VPC_TXCACHEMISSCOUNT, gcmCOUNTERCOMPARE(tx_cache_miss_count));
            gcmWRITE_COUNTER(VPC_TXCACHEHITTEXELCOUNT, gcmCOUNTERCOMPARE(tx_cache_hit_texel_count));
            gcmWRITE_COUNTER(VPC_TXCACHEMISSTEXELCOUNT, gcmCOUNTERCOMPARE(tx_cache_miss_texel_count));
            gcmWRITE_CONST(VPG_END);

            gcmWRITE_CONST(VPG_PS);
            gcmWRITE_COUNTER(VPC_PSINSTCOUNT, gcmCOUNTERCOMPARE(ps_inst_counter));
            gcmWRITE_COUNTER(VPC_PSBRANCHINSTCOUNT, gcmCOUNTERCOMPARE(pxl_branch_inst_counter));
            gcmWRITE_COUNTER(VPC_PSTEXLDINSTCOUNT, gcmCOUNTERCOMPARE(pxl_texld_inst_counter));
       	gcmWRITE_COUNTER(VPC_PSRENDEREDPIXCOUNT, gcmCOUNTERCOMPARE(rendered_pixel_counter));
            gcmWRITE_CONST(VPG_END);

            gcmWRITE_CONST(VPG_PE);
            gcmWRITE_COUNTER(VPC_PEKILLEDBYCOLOR, gcmCOUNTERCOMPARE(pe_pixel_count_killed_by_color_pipe));
            gcmWRITE_COUNTER(VPC_PEKILLEDBYDEPTH, gcmCOUNTERCOMPARE(pe_pixel_count_killed_by_depth_pipe));
            gcmWRITE_COUNTER(VPC_PEDRAWNBYCOLOR, gcmCOUNTERCOMPARE(pe_pixel_count_drawn_by_color_pipe));
            gcmWRITE_COUNTER(VPC_PEDRAWNBYDEPTH, gcmCOUNTERCOMPARE(pe_pixel_count_drawn_by_depth_pipe));
            gcmWRITE_CONST(VPG_END);

            gcmWRITE_CONST(VPG_MC);
            gcmWRITE_COUNTER(VPC_MCREADREQ8BPIPE, gcmCOUNTERCOMPARE(mc_total_read_req_8B_from_pipeline));
            gcmWRITE_COUNTER(VPC_MCREADREQ8BIP, gcmCOUNTERCOMPARE(mc_total_read_req_8B_from_IP));
            gcmWRITE_COUNTER(VPC_MCWRITEREQ8BPIPE, gcmCOUNTERCOMPARE(mc_total_write_req_8B_from_pipeline));
            gcmWRITE_CONST(VPG_END);

            gcmWRITE_CONST(VPG_AXI);
            gcmWRITE_COUNTER(VPC_AXIREADREQSTALLED, gcmCOUNTERCOMPARE(hi_axi_cycles_read_request_stalled));
            gcmWRITE_COUNTER(VPC_AXIWRITEREQSTALLED, gcmCOUNTERCOMPARE(hi_axi_cycles_write_request_stalled));
            gcmWRITE_COUNTER(VPC_AXIWRITEDATASTALLED, gcmCOUNTERCOMPARE(hi_axi_cycles_write_data_stalled));
            gcmWRITE_CONST(VPG_END);

            gcmWRITE_CONST(VPG_END);
            gcoOS_MemCopy(&precounters,&iface.u.RegisterProfileData.counters,gcmSIZEOF(precounters));
#else
		    gcmWRITE_STRING("<HWCounters>\n");

	        gcmPRINT_XML("<read_64Byte value=\"%u\"/>\n",
    	    			 gcmCOUNTER(gpuTotalRead64BytesPerFrame));
        	gcmPRINT_XML("<write_64Byte value=\"%u\"/>\n",
	        			 gcmCOUNTER(gpuTotalWrite64BytesPerFrame));
	        gcmPRINT_XML("<gpu_cycles value=\"%u\"/>\n",
    	    			 gcmCOUNTER(gpuCyclesCounter));
        	gcmPRINT_XML("<pe_pixel_count_killed_by_color_pipe value=\"%u\"/>\n",
        				 gcmCOUNTER(pe_pixel_count_killed_by_color_pipe));
	        gcmPRINT_XML("<pe_pixel_count_killed_by_depth_pipe value=\"%u\"/>\n",
    	    			 gcmCOUNTER(pe_pixel_count_killed_by_depth_pipe));
        	gcmPRINT_XML("<pe_pixel_count_drawn_by_color_pipe value=\"%u\"/>\n",
						 gcmCOUNTER(pe_pixel_count_drawn_by_color_pipe));
	        gcmPRINT_XML("<pe_pixel_count_drawn_by_depth_pipe value=\"%u\"/>\n",
						 gcmCOUNTER(pe_pixel_count_drawn_by_depth_pipe));
        	gcmPRINT_XML("<ps_inst_counter value=\"%u\"/>\n",
						 gcmCOUNTER(ps_inst_counter));
	        gcmPRINT_XML("<rendered_pixel_counter value=\"%u\"/>\n",
						 gcmCOUNTER(rendered_pixel_counter));
        	gcmPRINT_XML("<vs_inst_counter value=\"%u\"/>\n",
						 gcmCOUNTER(vs_inst_counter));
	        gcmPRINT_XML("<rendered_vertice_counter value=\"%u\"/>\n",
						 gcmCOUNTER(rendered_vertice_counter));
        	gcmPRINT_XML("<vtx_branch_inst_counter value=\"%u\"/>\n",
					 gcmCOUNTER(vtx_branch_inst_counter));
	        gcmPRINT_XML("<vtx_texld_inst_counter value=\"%u\"/>\n",
						 gcmCOUNTER(vtx_texld_inst_counter));
        	gcmPRINT_XML("<pxl_branch_inst_counter value=\"%u\"/>\n",
						 gcmCOUNTER(pxl_branch_inst_counter));
	        gcmPRINT_XML("<pxl_texld_inst_counter value=\"%u\"/>\n",
						 gcmCOUNTER(pxl_texld_inst_counter));
        	gcmPRINT_XML("<pa_input_vtx_counter value=\"%u\"/>\n",
					 gcmCOUNTER(pa_input_vtx_counter));
	        gcmPRINT_XML("<pa_input_prim_counter value=\"%u\"/>\n",
						 gcmCOUNTER(pa_input_prim_counter));
        	gcmPRINT_XML("<pa_output_prim_counter value=\"%u\"/>\n",
					 gcmCOUNTER(pa_output_prim_counter));
	        gcmPRINT_XML("<pa_depth_clipped_counter value=\"%u\"/>\n",
						 gcmCOUNTER(pa_depth_clipped_counter));
        	gcmPRINT_XML("<pa_trivial_rejected_counter value=\"%u\"/>\n",
					 gcmCOUNTER(pa_trivial_rejected_counter));
	        gcmPRINT_XML("<pa_culled_counter value=\"%u\"/>\n",
						 gcmCOUNTER(pa_culled_counter));
        	gcmPRINT_XML("<se_culled_triangle_count value=\"%u\"/>\n",
						 gcmCOUNTER(se_culled_triangle_count));
	        gcmPRINT_XML("<se_culled_lines_count value=\"%u\"/>\n",
						 gcmCOUNTER(se_culled_lines_count));
        	gcmPRINT_XML("<ra_valid_pixel_count value=\"%u\"/>\n",
					 gcmCOUNTER(ra_valid_pixel_count));
	        gcmPRINT_XML("<ra_total_quad_count value=\"%u\"/>\n",
						 gcmCOUNTER(ra_total_quad_count));
        	gcmPRINT_XML("<ra_valid_quad_count_after_early_z value=\"%u\"/>\n",
					 gcmCOUNTER(ra_valid_quad_count_after_early_z));
	        gcmPRINT_XML("<ra_total_primitive_count value=\"%u\"/>\n",
						 gcmCOUNTER(ra_total_primitive_count));
        	gcmPRINT_XML("<ra_pipe_cache_miss_counter value=\"%u\"/>\n",
						 gcmCOUNTER(ra_pipe_cache_miss_counter));
	        gcmPRINT_XML("<ra_prefetch_cache_miss_counter value=\"%u\"/>\n",
						 gcmCOUNTER(ra_prefetch_cache_miss_counter));
        	gcmPRINT_XML("<ra_eez_culled_counter value=\"%u\"/>\n",
					 gcmCOUNTER(ra_eez_culled_counter));
	        gcmPRINT_XML("<tx_total_bilinear_requests value=\"%u\"/>\n",
						 gcmCOUNTER(tx_total_bilinear_requests));
        	gcmPRINT_XML("<tx_total_trilinear_requests value=\"%u\"/>\n",
					 gcmCOUNTER(tx_total_trilinear_requests));
	        gcmPRINT_XML("<tx_total_discarded_texture_requests value=\"%u\"/>\n",
						 gcmCOUNTER(tx_total_discarded_texture_requests));
        	gcmPRINT_XML("<tx_total_texture_requests value=\"%u\"/>\n",
						 gcmCOUNTER(tx_total_texture_requests));
    	    gcmPRINT_XML("<tx_mem_read_count value=\"%u\"/>\n",
						 gcmCOUNTER(tx_mem_read_count));
	        gcmPRINT_XML("<tx_mem_read_in_8B_count value=\"%u\"/>\n",
						 gcmCOUNTER(tx_mem_read_in_8B_count));
        	gcmPRINT_XML("<tx_cache_miss_count value=\"%u\"/>\n",
						 gcmCOUNTER(tx_cache_miss_count));
    	    gcmPRINT_XML("<tx_cache_hit_texel_count value=\"%u\"/>\n",
						 gcmCOUNTER(tx_cache_hit_texel_count));
	        gcmPRINT_XML("<tx_cache_miss_texel_count value=\"%u\"/>\n",
						 gcmCOUNTER(tx_cache_miss_texel_count));
        	gcmPRINT_XML("<mc_total_read_req_8B_from_pipeline value=\"%u\"/>\n",
						 gcmCOUNTER(mc_total_read_req_8B_from_pipeline));
    	    gcmPRINT_XML("<mc_total_read_req_8B_from_IP value=\"%u\"/>\n",
						 gcmCOUNTER(mc_total_read_req_8B_from_IP));
	        gcmPRINT_XML("<mc_total_write_req_8B_from_pipeline value=\"%u\"/>\n",
						 gcmCOUNTER(mc_total_write_req_8B_from_pipeline));
	        gcmPRINT_XML("<hi_axi_cycles_read_request_stalled value=\"%u\"/>\n",
						 gcmCOUNTER(hi_axi_cycles_read_request_stalled));
	        gcmPRINT_XML("<hi_axi_cycles_write_request_stalled value=\"%u\"/>\n",
						 gcmCOUNTER(hi_axi_cycles_write_request_stalled));
        	gcmPRINT_XML("<hi_axi_cycles_write_data_stalled value=\"%u\"/>\n",
						 gcmCOUNTER(hi_axi_cycles_write_data_stalled));

	    	gcmWRITE_STRING("</HWCounters>\n");
#endif
		}
	}
/*#endif*/

	/* Success. */
    gcmFOOTER_NO();
    return gcvSTATUS_OK;
}
static int gpu_resume(struct platform_device *dev)
{
    gceSTATUS status;
    gckGALDEVICE device;
    gctINT i;
    gceCHIPPOWERSTATE   statesStored;

    device = platform_get_drvdata(dev);

    if (!device)
    {
        return -1;
    }

    for (i = 0; i < gcdMAX_GPU_COUNT; i++)
    {
        if (device->kernels[i] != gcvNULL)
        {
#if gcdENABLE_VG
            if (i == gcvCORE_VG)
            {
                status = gckVGHARDWARE_SetPowerManagementState(device->kernels[i]->vg->hardware, gcvPOWER_ON);
            }
            else
#endif
            {
                status = gckHARDWARE_SetPowerManagementState(device->kernels[i]->hardware, gcvPOWER_ON);
            }

            if (gcmIS_ERROR(status))
            {
                return -1;
            }

            /* Convert global state to crossponding internal state. */
            switch(device->statesStored[i])
            {
            case gcvPOWER_OFF:
                statesStored = gcvPOWER_OFF_BROADCAST;
                break;
            case gcvPOWER_IDLE:
                statesStored = gcvPOWER_IDLE_BROADCAST;
                break;
            case gcvPOWER_SUSPEND:
                statesStored = gcvPOWER_SUSPEND_BROADCAST;
                break;
            case gcvPOWER_ON:
                statesStored = gcvPOWER_ON_AUTO;
                break;
            default:
                statesStored = device->statesStored[i];
                break;
            }

            /* Restore states. */
#if gcdENABLE_VG
            if (i == gcvCORE_VG)
            {
                status = gckVGHARDWARE_SetPowerManagementState(device->kernels[i]->vg->hardware, statesStored);
            }
            else
#endif
            {
                status = gckHARDWARE_SetPowerManagementState(device->kernels[i]->hardware, statesStored);
            }

            if (gcmIS_ERROR(status))
            {
                return -1;
            }
        }
    }

    return 0;
}
gctINT
slScanIdentifier(
	IN sloCOMPILER Compiler,
	IN gctUINT LineNo,
	IN gctUINT StringNo,
	IN gctSTRING Symbol,
	OUT slsLexToken * Token
	)
{
	gceSTATUS		status;
	gctINT			tokenType;
	sleSHADER_TYPE	shaderType;
	sltPOOL_STRING	symbolInPool;
	slsNAME *		typeName;

    gcmTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_COMPILER, "LineNo=%u", LineNo);
    gcmTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_COMPILER, "StringNo=%u", StringNo);
    gcmTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_COMPILER, "Symbol=%s", gcmOPT_STRING(Symbol));

	gcmASSERT(Token);

	gcmVERIFY_OK(sloCOMPILER_GetShaderType(Compiler, &shaderType));

	Token->lineNo	= LineNo;
	Token->stringNo	= StringNo;

	/* Check as a reserved keyword */
	tokenType = _SearchKeyword(Symbol);

	if (tokenType == T_RESERVED_KEYWORD)
	{
		Token->type = T_RESERVED_KEYWORD;

		gcmVERIFY_OK(sloCOMPILER_Report(
										Compiler,
										LineNo,
										StringNo,
										slvREPORT_ERROR,
										"reserved keyword : '%s'",
										Symbol));

		return T_RESERVED_KEYWORD;
	}
	else if (tokenType != T_NOT_KEYWORD)
	{
		Token->type = tokenType;

		switch (tokenType)
		{
		case T_CONST:				Token->u.qualifier	= slvQUALIFIER_CONST;				break;
		case T_UNIFORM:				Token->u.qualifier	= slvQUALIFIER_UNIFORM;				break;

		case T_ATTRIBUTE:
			if (shaderType != slvSHADER_TYPE_VERTEX)
			{
				gcmVERIFY_OK(sloCOMPILER_Report(
												Compiler,
												LineNo,
												StringNo,
												slvREPORT_ERROR,
												"'attribute' is only for the vertex shaders",
												Symbol));
			}

			Token->u.qualifier	= slvQUALIFIER_ATTRIBUTE;
			break;

		case T_VARYING:
			Token->u.qualifier	= (shaderType == slvSHADER_TYPE_VERTEX)?
					slvQUALIFIER_VARYING_OUT : slvQUALIFIER_VARYING_IN;
			break;

		case T_INVARIANT:
			Token->u.qualifier	= (shaderType == slvSHADER_TYPE_VERTEX)?
					slvQUALIFIER_INVARIANT_VARYING_OUT : slvQUALIFIER_INVARIANT_VARYING_IN;
			break;

		case T_IN:					Token->u.qualifier	= slvQUALIFIER_IN;					break;
		case T_OUT:					Token->u.qualifier	= slvQUALIFIER_OUT;					break;
		case T_INOUT:				Token->u.qualifier	= slvQUALIFIER_INOUT;				break;

		case T_HIGH_PRECISION:		Token->u.precision	= slvPRECISION_HIGH;				break;
		case T_MEDIUM_PRECISION:	Token->u.precision	= slvPRECISION_MEDIUM;				break;
		case T_LOW_PRECISION:		Token->u.precision	= slvPRECISION_LOW;					break;
		}

		gcmVERIFY_OK(sloCOMPILER_Dump(
									Compiler,
									slvDUMP_SCANNER,
									"<TOKEN line=\"%d\" string=\"%d\" type=\"keyword\" symbol=\"%s\" />",
									LineNo,
									StringNo,
									Symbol));

		return tokenType;
	}

	status = sloCOMPILER_AllocatePoolString(
											Compiler,
											Symbol,
											&symbolInPool);

	if (gcmIS_ERROR(status)) return T_EOF;

	if (sloCOMPILER_GetScannerState(Compiler) == slvSCANNER_NOMRAL)
	{
		/* Check as a type name */
		status = sloCOMPILER_SearchName(
										Compiler,
										symbolInPool,
										gcvTRUE,
										&typeName);

		if (status == gcvSTATUS_OK && typeName->type == slvSTRUCT_NAME)
		{
			Token->type			= T_TYPE_NAME;
			Token->u.typeName	= typeName;

			gcmVERIFY_OK(sloCOMPILER_Dump(
										Compiler,
										slvDUMP_SCANNER,
										"<TOKEN line=\"%d\" string=\"%d\" type=\"typeName\" symbol=\"%s\" />",
										LineNo,
										StringNo,
										symbolInPool));

			return T_TYPE_NAME;
		}
	}

	/* Treat as an identifier */
	Token->type			= T_IDENTIFIER;
	Token->u.identifier = symbolInPool;

	gcmVERIFY_OK(sloCOMPILER_Dump(
								Compiler,
								slvDUMP_SCANNER,
								"<TOKEN line=\"%d\" string=\"%d\" type=\"identifier\" symbol=\"%s\" />",
								LineNo,
								StringNo,
								Token->u.identifier));

	return T_IDENTIFIER;
}
gceSTATUS
gcoPROFILER_Initialize(
	IN gcoHAL Hal
	)
{
    gceSTATUS status = gcvSTATUS_OK;
    char* fileName;
    char* filter = gcvNULL;
    gctSTRING portName;
    gctINT port;
	gcsHAL_INTERFACE iface;

    gcmHEADER();

    /* Check if already initialized. */
   	if (gcPLS.hal->profiler.enable)
    {
        gcPLS.hal->profiler.enable++;
        gcmFOOTER();
        return status;
    }

	/* Get profile setting. */
	iface.command = gcvHAL_GET_PROFILE_SETTING;

	/* Call the kernel. */
	status = gcoOS_DeviceControl(gcvNULL,
								 IOCTL_GCHAL_INTERFACE,
								 &iface, gcmSIZEOF(iface),
								 &iface, gcmSIZEOF(iface));

	if (gcmIS_ERROR(status) || !iface.u.GetProfileSetting.enable)
	{
    	gcPLS.hal->profiler.enable = 0;
        status = gcvSTATUS_GENERIC_IO;

        gcmFOOTER();
        return status;
	}

	gcmVERIFY_OK(gcoOS_ZeroMemory(&gcPLS.hal->profiler, gcmSIZEOF(gcPLS.hal->profiler)));

    gcoOS_GetEnv(gcvNULL,
                 "VP_COUNTER_FILTER",
                 &filter);

    /* Enable/Disable specific counters. */
    if ((filter != gcvNULL))
    {
        gctSIZE_T bitsLen;
        gcoOS_StrLen(filter, &bitsLen);
        if (bitsLen > 2)
        {
            gcPLS.hal->profiler.enableHal = (filter[2] == '1');
        }
        else
        {
            gcPLS.hal->profiler.enableHal = gcvTRUE;
        }

        if (bitsLen > 3)
        {
            gcPLS.hal->profiler.enableHW = (filter[3] == '1');
        }
        else
        {
            gcPLS.hal->profiler.enableHW = gcvTRUE;
        }

        if (bitsLen > 8)
        {
            gcPLS.hal->profiler.enableSH = (filter[8] == '1');
        }
        else
        {
            gcPLS.hal->profiler.enableSH = gcvTRUE;
        }
    }
    else
    {
        gcPLS.hal->profiler.enableHal = gcvTRUE;
        gcPLS.hal->profiler.enableHW = gcvTRUE;
        gcPLS.hal->profiler.enableSH = gcvTRUE;
    }

	gcoOS_GetEnv(gcvNULL,
				 "VPROFILER_OUTPUT",
				 &fileName);

    gcPLS.hal->profiler.useSocket = gcvFALSE;
	if (fileName && *fileName != '\0' && *fileName != ' ')
	{
        /* Extract port info. */
        gcoOS_StrFindReverse(fileName, ':', &portName);

        if (portName)
        {
            gcoOS_StrToInt(portName + 1, &port);

            if (port > 0)
            {
                /*status = gcoOS_Socket(gcvNULL, AF_INET, SOCK_STREAM, 0, &gcPLS.hal->profiler.sockFd);*/
                status = gcoOS_Socket(gcvNULL, 2, 1, 0, &gcPLS.hal->profiler.sockFd);

                if (gcmIS_SUCCESS(status))
                {
                    *portName = '\0';
                    status = gcoOS_Connect(gcvNULL,
                            gcPLS.hal->profiler.sockFd, fileName, port);
                    *portName = ':';

                    if (gcmIS_SUCCESS(status))
	                {
                        gcPLS.hal->profiler.useSocket = gcvTRUE;
                    }
                }
            }
        }
	}
    else
    {
		fileName = iface.u.GetProfileSetting.fileName;
    }

    if (! gcPLS.hal->profiler.useSocket)
	{
		status = gcoOS_Open(gcvNULL,
							fileName,
#ifdef gcdNEW_PROFILER_FILE
							gcvFILE_CREATE,
#else
							gcvFILE_CREATETEXT,
#endif
							&gcPLS.hal->profiler.file);
	}

    if (gcmIS_ERROR(status))
	{
    	gcPLS.hal->profiler.enable = 0;
        status = gcvSTATUS_GENERIC_IO;

        gcmFOOTER();
        return status;
	}

    gcPLS.hal->profiler.enable = 1;
	gcoOS_GetTime(&gcPLS.hal->profiler.frameStart);
	gcPLS.hal->profiler.frameStartTimeusec = gcPLS.hal->profiler.frameStart;
	gcPLS.hal->profiler.prevVSInstCount = 0;
	gcPLS.hal->profiler.prevVSBranchInstCount = 0;
	gcPLS.hal->profiler.prevVSTexInstCount = 0;
	gcPLS.hal->profiler.prevVSVertexCount = 0;
	gcPLS.hal->profiler.prevPSInstCount = 0;
	gcPLS.hal->profiler.prevPSBranchInstCount = 0;
	gcPLS.hal->profiler.prevPSTexInstCount = 0;
	gcPLS.hal->profiler.prevPSPixelCount = 0;

#if gcdNEW_PROFILER_FILE
    gcmWRITE_CONST(VPHEADER);
    gcmWRITE_BUFFER(4, "VP12");
#else
	gcmWRITE_STRING("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<VProfile>\n");
#endif

    /* Success. */
    gcmFOOTER();
    return status;
}
/*******************************************************************************
**
**	gckCOMMAND_Stall
**
**	The calling thread will be suspended until the command queue has been
**  completed.
**
**	INPUT:
**
**		gckCOMMAND Command
**			Pointer to an gckCOMMAND object.
**
**	OUTPUT:
**
**		Nothing.
*/
gceSTATUS
gckCOMMAND_Stall(
    IN gckCOMMAND Command
    )
{
    gckOS os;
    gckHARDWARE hardware;
    gckEVENT event;
    gceSTATUS status;
	gctSIGNAL signal = gcvNULL;

	gcmkHEADER_ARG("Command=0x%x", Command);

    /* Verify the arguments. */
    gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);

#if gcdNULL_DRIVER == 2
	/* Do nothing with infinite hardware. */
	gcmkFOOTER_NO();
	return gcvSTATUS_OK;
#endif

    /* Extract the gckOS object pointer. */
    os = Command->os;
    gcmkVERIFY_OBJECT(os, gcvOBJ_OS);

    /* Extract the gckHARDWARE object pointer. */
    hardware = Command->kernel->hardware;
    gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);

    /* Extract the gckEVENT object pointer. */
    event = Command->kernel->event;
    gcmkVERIFY_OBJECT(event, gcvOBJ_EVENT);

    /* Allocate the signal. */
	gcmkONERROR(
		gckOS_CreateSignal(os, gcvTRUE, &signal));

    /* Append the EVENT command to trigger the signal. */
    gcmkONERROR(gckEVENT_Signal(event,
                                signal,
                                gcvKERNEL_PIXEL,
								gcvFALSE));

    /* Submit the event queue. */
	gcmkONERROR(gckEVENT_Submit(event, gcvTRUE, gcvFALSE));

#if gcdDUMP_COMMAND
    gcmkPRINT("@[kernel.stall]");
#endif

    if (status == gcvSTATUS_CHIP_NOT_READY)
    {
        /* Error. */
        goto OnError;
    }

	do
	{
		/* Wait for the signal. */
		status = gckOS_WaitSignal(os, signal, gcvINFINITE);

		if (status == gcvSTATUS_TIMEOUT)
		{
#if gcdDEBUG
			gctUINT32 idle;

			/* IDLE */
			gckOS_ReadRegister(Command->os, 0x0004, &idle);
                
			gcmkTRACE(gcvLEVEL_ERROR,
					  "%s(%d): idle=%08x",
					  __FUNCTION__, __LINE__, idle);
        	    	gckOS_Log(_GFX_LOG_WARNING_, "%s : %d : idle register = 0x%08x \n", 
                            __FUNCTION__, __LINE__, idle);                
#endif 

#if MRVL_PRINT_CMD_BUFFER
            {
    			gctUINT i;
                gctUINT32 idle;
    			gctUINT32 intAck;
    			gctUINT32 prevAddr = 0;
    			gctUINT32 currAddr;
    			gctBOOL changeDetected;

    			changeDetected = gcvFALSE;

                /* IDLE */
			    gckOS_ReadRegister(Command->os, 0x0004, &idle);
                
				/* INT ACK */
				gckOS_ReadRegister(Command->os, 0x0010, &intAck);

				/* DMA POS */
				for (i = 0; i < 300; i += 1)
				{
					gckOS_ReadRegister(Command->os, 0x0664, &currAddr);

					if ((i > 0) && (prevAddr != currAddr))
					{
						changeDetected = gcvTRUE;
					}

					prevAddr = currAddr;
				}

				gcmTRACE(0,
					"\n%s(%d):\n"
					"  idle = 0x%08X\n"
					"  int  = 0x%08X\n"
					"  dma  = 0x%08X (change=%d)\n",
					__FUNCTION__, __LINE__,
					idle,
					intAck,
					currAddr,
					changeDetected
					);
                
				_PrintCmdBuffer(Command, currAddr);
				_PrintLinkChain();
            }
#endif


#if MRVL_LOW_POWER_MODE_DEBUG
            	{
                	int i = 0;
                
                	printk(">>>>>>>>>>>>galDevice->kernel->kernelMSG\n");
                	printk("galDevice->kernel->msgLen=%d\n",Command->kernel->msgLen);
                
                	for(i=0;i<Command->kernel->msgLen;i+=1024)
                	{
                    		Command->kernel->kernelMSG[i+1023] = '\0';
            	    		printk("%s\n",(char*)Command->kernel->kernelMSG + i);
                	}
            	}
#endif
#ifdef __QNXNTO__
            gctUINT32 reg_cmdbuf_fetch;
            gctUINT32 reg_intr;

            gcmkVERIFY_OK(
                    gckOS_ReadRegister(Command->kernel->hardware->os, 0x0664, &reg_cmdbuf_fetch));

            if (idle == 0x7FFFFFFE)
            {
                /*
                 * GPU is idle so there should not be pending interrupts.
                 * Just double check.
                 *
                 * Note that reading interrupt register clears it.
                 * That's why we don't read it in all cases.
                 */
                gcmkVERIFY_OK(
                        gckOS_ReadRegister(Command->kernel->hardware->os, 0x10, &reg_intr));

                slogf(
                    _SLOG_SETCODE(1, 0),
                    _SLOG_CRITICAL,
                    "GALcore: Stall timeout (idle = 0x%X, command buffer fetch = 0x%X, interrupt = 0x%X)",
                    idle, reg_cmdbuf_fetch, reg_intr);
            }
            else
            {
                slogf(
                    _SLOG_SETCODE(1, 0),
                    _SLOG_CRITICAL,
                    "GALcore: Stall timeout (idle = 0x%X, command buffer fetch = 0x%X)",
                    idle, reg_cmdbuf_fetch);
            }
#endif
			gcmkVERIFY_OK(
				gckOS_MemoryBarrier(os, gcvNULL));
		}

	}
	while (gcmIS_ERROR(status));

	/* Delete the signal. */
	gcmkVERIFY_OK(gckOS_DestroySignal(os, signal));

    /* Success. */
    gcmkFOOTER_NO();
    return gcvSTATUS_OK;

OnError:
    /* Free the signal. */
    if (signal != gcvNULL)
    {
    	gcmkVERIFY_OK(gckOS_DestroySignal(os, signal));
    }

    /* Return the status. */
    gcmkFOOTER();
    return status;
}