static int __devinit gpu_resume(struct platform_device *dev) { gceSTATUS status; gckGALDEVICE device; gctINT i; gceCHIPPOWERSTATE statesStored; device = platform_get_drvdata(dev); for (i = 0; i < gcdMAX_GPU_COUNT; i++) { if (device->kernels[i] != gcvNULL) { { 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. */ { status = gckHARDWARE_SetPowerManagementState(device->kernels[i]->hardware, statesStored); } if (gcmIS_ERROR(status)) { return -1; } } } return 0; }
/******************************************************************************* ** ** gckGALDEVICE_Stop ** ** Stop the gal device, including the following actions: stop the daemon ** thread, release the irq. ** ** INPUT: ** ** gckGALDEVICE Device ** Pointer to an gckGALDEVICE object. ** ** OUTPUT: ** ** Nothing. ** ** RETURNS: ** ** Nothing. */ gceSTATUS gckGALDEVICE_Stop( gckGALDEVICE Device ) { gceSTATUS status; gcmkHEADER_ARG("Device=0x%x", Device); gcmkVERIFY_ARGUMENT(Device != NULL); if (Device->kernels[gcvCORE_MAJOR] != gcvNULL) { /* Switch to OFF power state. */ gcmkONERROR(gckHARDWARE_SetPowerManagementState( Device->kernels[gcvCORE_MAJOR]->hardware, gcvPOWER_OFF )); /* Remove the ISR routine. */ gcmkONERROR(gckGALDEVICE_Release_ISR(Device)); } if (Device->kernels[gcvCORE_2D] != gcvNULL) { /* Setup the ISR routine. */ gcmkONERROR(gckGALDEVICE_Release_ISR_2D(Device)); /* Switch to OFF power state. */ gcmkONERROR(gckHARDWARE_SetPowerManagementState( Device->kernels[gcvCORE_2D]->hardware, gcvPOWER_OFF )); } if (Device->kernels[gcvCORE_VG] != gcvNULL) { /* Setup the ISR routine. */ gcmkONERROR(gckGALDEVICE_Release_ISR_VG(Device)); } /* Stop the kernel thread. */ gcmkONERROR(gckGALDEVICE_Stop_Threads(Device)); gcmkFOOTER_NO(); return gcvSTATUS_OK; OnError: gcmkFOOTER(); return status; }
static ssize_t store_pm_state (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int core, state, i, gpu_count; gceSTATUS status = gcvSTATUS_OK; /* count core numbers */ for (i = 0, gpu_count = 0; i < gcdMAX_GPU_COUNT; i++) if (galDevice->kernels[i] != gcvNULL) gpu_count++; /* read input and verify */ SYSFS_VERIFY_INPUT(sscanf(buf, "%d,%d", &core, &state), 2); SYSFS_VERIFY_INPUT_RANGE(core, 0, (gpu_count-1)); SYSFS_VERIFY_INPUT_RANGE(state, 0, 3); /* power state transition */ status = gckHARDWARE_SetPowerManagementState(galDevice->kernels[core]->hardware, state); if (gcmIS_ERROR(status)) { printk("[%d] failed in transfering power state to %d\n", core, state); } return count; }
static gctINT __set_gpu_power(gckGALDEVICE Device, gceCHIPPOWERSTATE State) { gceSTATUS status = gcvSTATUS_OK; gctINT i; 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, State); } else #endif { status = gckHARDWARE_SetPowerManagementState(Device->kernels[i]->hardware, State); } if (gcmIS_ERROR(status)) { return -1; } } } return 0; }
/******************************************************************************* ** ** gckGALDEVICE_Start ** ** Start the gal device, including the following actions: setup the isr routine ** and start the daemoni thread. ** ** INPUT: ** ** gckGALDEVICE Device ** Pointer to an gckGALDEVICE object. ** ** OUTPUT: ** ** Nothing. ** ** RETURNS: ** ** gcvSTATUS_OK ** Start successfully. */ gceSTATUS gckGALDEVICE_Start( IN gckGALDEVICE Device ) { gceSTATUS status; gcmkHEADER_ARG("Device=0x%x", Device); /* Start the kernel thread. */ gcmkONERROR(gckGALDEVICE_Start_Threads(Device)); if (Device->kernels[gcvCORE_MAJOR] != gcvNULL) { /* Setup the ISR routine. */ gcmkONERROR(gckGALDEVICE_Setup_ISR(Device)); /* Switch to SUSPEND power state. */ gcmkONERROR(gckHARDWARE_SetPowerManagementState( Device->kernels[gcvCORE_MAJOR]->hardware, gcvPOWER_OFF_BROADCAST )); } if (Device->kernels[gcvCORE_2D] != gcvNULL) { /* Setup the ISR routine. */ gcmkONERROR(gckGALDEVICE_Setup_ISR_2D(Device)); /* Switch to SUSPEND power state. */ gcmkONERROR(gckHARDWARE_SetPowerManagementState( Device->kernels[gcvCORE_2D]->hardware, gcvPOWER_OFF_BROADCAST )); } if (Device->kernels[gcvCORE_VG] != gcvNULL) { /* Setup the ISR routine. */ gcmkONERROR(gckGALDEVICE_Setup_ISR_VG(Device)); } gcmkFOOTER_NO(); return gcvSTATUS_OK; OnError: gcmkFOOTER(); return status; }
static int __devinit gpu_suspend(struct platform_device *dev, pm_message_t state) { gceSTATUS status = gcvSTATUS_OK; gckGALDEVICE device; gctINT i; gctINT ret = 0; device = platform_get_drvdata(dev); printk("[galcore] enter %s\n", __FUNCTION__); for (i = 0; i < gcdMAX_GPU_COUNT; i++) { if (device->kernels[i] != gcvNULL) { /* Store states. */ #if gcdENABLE_VG if (i == gcvCORE_VG) { status = gckVGHARDWARE_QueryPowerManagementState(device->kernels[i]->vg->hardware, &device->statesStored[i]); } else #endif { status = gckHARDWARE_QueryPowerManagementState(device->kernels[i]->hardware, &device->statesStored[i]); } if (gcmIS_ERROR(status)) { ret = -1; goto err_out; } #if gcdENABLE_VG if (i == gcvCORE_VG) { status = gckVGHARDWARE_SetPowerManagementState(device->kernels[i]->vg->hardware, gcvPOWER_OFF); } else #endif { status = gckHARDWARE_SetPowerManagementState(device->kernels[i]->hardware, gcvPOWER_OFF); } if (gcmIS_ERROR(status)) { ret = -1; goto err_out; } galDevice->currentPMode = gcvPM_SUSPEND; } } err_out: printk("[galcore] exit %s, return %d\n", __FUNCTION__, ret); return ret; }
static int gpu_suspend(struct platform_device *dev, pm_message_t state) { gceSTATUS status; gckGALDEVICE device; gctINT i; device = platform_get_drvdata(dev); if (!device) { return -1; } for (i = 0; i < gcdMAX_GPU_COUNT; i++) { if (device->kernels[i] != gcvNULL) { /* Store states. */ #if gcdENABLE_VG if (i == gcvCORE_VG) { status = gckVGHARDWARE_QueryPowerManagementState(device->kernels[i]->vg->hardware, &device->statesStored[i]); } else #endif { status = gckHARDWARE_QueryPowerManagementState(device->kernels[i]->hardware, &device->statesStored[i]); } if (gcmIS_ERROR(status)) { return -1; } #if gcdENABLE_VG if (i == gcvCORE_VG) { status = gckVGHARDWARE_SetPowerManagementState(device->kernels[i]->vg->hardware, gcvPOWER_OFF); } else #endif { status = gckHARDWARE_SetPowerManagementState(device->kernels[i]->hardware, gcvPOWER_OFF); } if (gcmIS_ERROR(status)) { return -1; } } } return 0; }
gceSTATUS gckKERNEL_AttachProcess( IN gckKERNEL Kernel, IN gctBOOL Attach ) { gceSTATUS status; gctINT32 old; gcmkHEADER_ARG("Kernel=0x%x Attach=%d", Kernel, Attach); /* Verify the arguments. */ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL); if (Attach) { /* Increment the number of clients attached. */ gcmkONERROR( gckOS_AtomIncrement(Kernel->os, Kernel->atomClients, &old)); if (old == 0) { /* gcmkONERROR(gckHARDWARE_SetPowerManagementState(Kernel->hardware, gcvPOWER_ON)); */ } } else { /* Decrement the number of clients attached. */ gcmkONERROR( gckOS_AtomDecrement(Kernel->os, Kernel->atomClients, &old)); if (old == 1) { gcmkONERROR(gckHARDWARE_SetPowerManagementState(Kernel->hardware, gcvPOWER_OFF)); /* Flush the debug cache. */ gcmkPRINT("$$FLUSH$$"); } } /* Success. */ gcmkFOOTER_NO(); return gcvSTATUS_OK; OnError: /* Return the status. */ gcmkFOOTER(); return status; }
/* ** PM Thread Routine **/ static int threadRoutinePM(void *ctxt) { gckGALDEVICE device = (gckGALDEVICE) ctxt; gckHARDWARE hardware = device->kernels[gcvCORE_MAJOR]->hardware; gceCHIPPOWERSTATE state; for(;;) { /* wait for idle */ gcmkVERIFY_OK( gckOS_WaitSignal(device->os, hardware->powerOffSignal, gcvINFINITE)); /* We try to power off every 200 ms, until GPU is not idle */ do { if (device->killThread == gcvTRUE) { /* The daemon exits. */ while (!kthread_should_stop()) { gckOS_Delay(device->os, 1); } return 0; } gcmkVERIFY_OK( gckHARDWARE_SetPowerManagementState( hardware, gcvPOWER_OFF_TIMEOUT)); /* relax cpu 200 ms before retry */ gckOS_Delay(device->os, 200); gcmkVERIFY_OK( gckHARDWARE_QueryPowerManagementState(hardware, &state)); } while (state == gcvPOWER_IDLE); } }
/* ** PM Thread Routine **/ static int _threadRoutinePM(gckGALDEVICE Device, gckHARDWARE Hardware) { gceCHIPPOWERSTATE state; for(;;) { /* wait for idle */ gcmkVERIFY_OK( gckOS_AcquireMutex(Device->os, Hardware->powerOffSema, gcvINFINITE)); /* We try to power off every 200 ms, until GPU is not idle */ do { if (Device->killThread == gcvTRUE) { /* The daemon exits. */ while (!kthread_should_stop()) { gckOS_Delay(Device->os, 1); } return 0; } gcmkVERIFY_OK( gckHARDWARE_SetPowerManagementState( Hardware, gcvPOWER_OFF_TIMEOUT)); /* relax cpu 200 ms before retry */ gckOS_Delay(Device->os, 200); gcmkVERIFY_OK( gckHARDWARE_QueryPowerManagementState(Hardware, &state)); } while (state == gcvPOWER_IDLE); } }
/******************************************************************************* ** ** 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; }
/******************************************************************************* ** ** gckKERNEL_Recovery ** ** Try to recover the GPU from a fatal error. ** ** INPUT: ** ** gckKERNEL Kernel ** Pointer to an gckKERNEL object. ** ** OUTPUT: ** ** Nothing. */ gceSTATUS gckKERNEL_Recovery( IN gckKERNEL Kernel ) { gceSTATUS status; gckEVENT event; gckHARDWARE hardware; #if gcdSECURE_USER gctUINT32 processID; #endif gcmkHEADER_ARG("Kernel=0x%x", Kernel); /* Validate the arguemnts. */ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL); /* Grab gckEVENT object. */ event = Kernel->event; gcmkVERIFY_OBJECT(event, gcvOBJ_EVENT); /* Grab gckHARDWARE object. */ hardware = Kernel->hardware; gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE); /* Handle all outstanding events now. */ event->pending = ~0U; gcmkONERROR(gckEVENT_Notify(event, 1)); /* Again in case more events got submitted. */ event->pending = ~0U; gcmkONERROR(gckEVENT_Notify(event, 2)); #if gcdSECURE_USER /* Flush the secure mapping cache. */ gcmkONERROR(gckOS_GetProcessID(&processID)); gcmkONERROR(gckKERNEL_MapLogicalToPhysical(Kernel, processID, gcvNULL)); #endif /* Try issuing a soft reset for the GPU. */ status = gckHARDWARE_Reset(hardware); if (status == gcvSTATUS_NOT_SUPPORTED) { /* Switch to OFF power. The next submit should return the GPU to ON ** state. */ gcmkONERROR( gckHARDWARE_SetPowerManagementState(hardware, gcvPOWER_OFF)); } else { /* Bail out on reset error. */ gcmkONERROR(status); } /* Success. */ gcmkFOOTER_NO(); return gcvSTATUS_OK; OnError: /* Return the status. */ gcmkFOOTER(); return status; }
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; }
/* 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; }
static ssize_t store_power_state (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int state, core, broadcast, gpu_count, i; gceSTATUS status = gcvSTATUS_OK; gctUINT32 tgid; /* count ocre numbers */ for (i=0, gpu_count = 0; i < gcdMAX_GPU_COUNT; i++) if (galDevice->kernels[i] != gcvNULL) gpu_count++; /* scan input value and verify */ SYSFS_VERIFY_INPUT(sscanf(buf, "%d,%d,%d", &state, &core, &broadcast), 3); SYSFS_VERIFY_INPUT_RANGE(state, 0, 2); SYSFS_VERIFY_INPUT_RANGE(core, 0, (gpu_count-1)); SYSFS_VERIFY_INPUT_RANGE(broadcast, 0, 1); gckOS_GetProcessID(&tgid); switch (state) { case 0: /* on */ printk("[pm_test %d] %s core power state on\n", tgid, (core == gcvCORE_MAJOR)?"3D":"2D"); if (broadcast) /* noting done here */ gcmkONERROR(gckOS_Broadcast(galDevice->kernels[core]->os, galDevice->kernels[core]->hardware, gcvBROADCAST_FIRST_PROCESS)); else gcmkONERROR(gckHARDWARE_SetPowerManagementState(galDevice->kernels[core]->hardware, gcvPOWER_ON)); printk("[pm_test %d] %s core power state on - done\n", tgid, (core == gcvCORE_MAJOR)?"3D":"2D"); break; case 1: /* off */ printk("[pm_test %d] %s core power state off\n", tgid, (core == gcvCORE_MAJOR)?"3D":"2D"); if (broadcast) gcmkONERROR(gckOS_Broadcast(galDevice->kernels[core]->os, galDevice->kernels[core]->hardware, gcvBROADCAST_LAST_PROCESS)); else gcmkONERROR(gckHARDWARE_SetPowerManagementState(galDevice->kernels[core]->hardware, gcvPOWER_OFF)); printk("[pm_test %d] %s core power state off - done\n", tgid, (core == gcvCORE_MAJOR)?"3D":"2D"); break; case 2: /* suspend */ printk("[pm_test %d] %s core power state suspend\n", tgid, (core == gcvCORE_MAJOR)?"3D":"2D"); if (broadcast) gcmkONERROR(gckOS_Broadcast(galDevice->kernels[core]->os, galDevice->kernels[core]->hardware, gcvBROADCAST_GPU_IDLE)); else gcmkONERROR(gckHARDWARE_SetPowerManagementState(galDevice->kernels[core]->hardware, gcvPOWER_SUSPEND)); printk("[pm_test %d] %s core power state suspend - done\n", tgid, (core == gcvCORE_MAJOR)?"3D":"2D"); break; default: break; } return count; OnError: printk("[pm_test %d] %s core power state %s - bail out\n", tgid, (core == gcvCORE_MAJOR)?"3D":"2D", (state==1)?"off":"on"); return (ssize_t)-EINVAL; }