static int thermal_hot_pm_notify(struct notifier_block *nb, unsigned long event, void *dummy) { static gctUINT orgFscale, minFscale, maxFscale; static gctBOOL bAlreadyTooHot = gcvFALSE; gckHARDWARE hardware = galDevice->kernels[gcvCORE_MAJOR]->hardware; if (event && !bAlreadyTooHot) { gckHARDWARE_GetFscaleValue(hardware,&orgFscale,&minFscale, &maxFscale); gckHARDWARE_SetFscaleValue(hardware, minFscale); bAlreadyTooHot = gcvTRUE; gckOS_Print("System is too hot. GPU3D will work at %d/64 clock.\n", minFscale); } else if (!event && bAlreadyTooHot) { gckHARDWARE_SetFscaleValue(hardware, orgFscale); gckOS_Print("Hot alarm is canceled. GPU3D clock will return to %d/64\n", orgFscale); bAlreadyTooHot = gcvFALSE; } return NOTIFY_OK; }
gceSTATUS _SetPower( IN gckPLATFORM Platform, IN gceCORE GPU, IN gctBOOL Enable ) { struct imx_priv* priv = Platform->priv; #if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0) #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) int ret; #endif #endif if (Enable) { #if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0) #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) if(!IS_ERR(priv->gpu_regulator)) { ret = regulator_enable(priv->gpu_regulator); if (ret != 0) gckOS_Print("%s(%d): fail to enable pu regulator %d!\n", __FUNCTION__, __LINE__, ret); } #else imx_gpc_power_up_pu(true); #endif #endif #ifdef CONFIG_PM pm_runtime_get_sync(priv->pmdev); #endif } else { #ifdef CONFIG_PM pm_runtime_put_sync(priv->pmdev); #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0) #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) if(!IS_ERR(priv->gpu_regulator)) regulator_disable(priv->gpu_regulator); #else imx_gpc_power_up_pu(false); #endif #endif } return gcvSTATUS_OK; }
static int thermal_hot_pm_notify(struct notifier_block *nb, unsigned long event, void *dummy) { static gctUINT orgFscale, minFscale, maxFscale; static gctBOOL bAlreadyTooHot = gcvFALSE; gckHARDWARE hardware; gckGALDEVICE galDevice; galDevice = platform_get_drvdata(pdevice); if (!galDevice) { /* GPU is not ready, so it is meaningless to change GPU freq. */ return NOTIFY_OK; } if (!galDevice->kernels[gcvCORE_MAJOR]) { return NOTIFY_OK; } hardware = galDevice->kernels[gcvCORE_MAJOR]->hardware; if (!hardware) { return NOTIFY_OK; } if (event && !bAlreadyTooHot) { gckHARDWARE_GetFscaleValue(hardware,&orgFscale,&minFscale, &maxFscale); gckHARDWARE_SetFscaleValue(hardware, minFscale); bAlreadyTooHot = gcvTRUE; gckOS_Print("System is too hot. GPU3D will work at %d/64 clock.\n", minFscale); } else if (!event && bAlreadyTooHot) { gckHARDWARE_SetFscaleValue(hardware, orgFscale); gckOS_Print("Hot alarm is canceled. GPU3D clock will return to %d/64\n", orgFscale); bAlreadyTooHot = gcvFALSE; } return NOTIFY_OK; }
static int thermal_hot_pm_notify(struct notifier_block *nb, unsigned long event, void *dummy) { static gctUINT orgFscale, minFscale, maxFscale; static gctBOOL critical; gckHARDWARE hardware = galDevice->kernels[gcvCORE_MAJOR]->hardware; if (event > 4) { critical = gcvTRUE; gckHARDWARE_GetFscaleValue(hardware,&orgFscale,&minFscale, &maxFscale); gckHARDWARE_SetFscaleValue(hardware, minFscale); gckOS_Print("System is too hot. GPU3D scalign to %d/64 clock.\n", minFscale); } else if (event > 1) { gckHARDWARE_GetFscaleValue(hardware,&orgFscale,&minFscale, &maxFscale); gckHARDWARE_SetFscaleValue(hardware, maxFscale - (8 * event)); } else if (orgFscale) { gckHARDWARE_SetFscaleValue(hardware, orgFscale); if (critical) { gckOS_Print("Hot alarm is canceled. GPU3D clock will return to %d/64\n", orgFscale); critical = gcvFALSE; } } return NOTIFY_OK; }
gceSTATUS _GetPower( IN gckPLATFORM Platform ) { struct device* pdev = &Platform->device->dev; struct imx_priv *priv = Platform->priv; #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) struct reset_control *rstc; #endif #ifdef CONFIG_PM /*Init runtime pm for gpu*/ pm_runtime_enable(pdev); priv->pmdev = pdev; #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) rstc = devm_reset_control_get(pdev, "gpu3d"); priv->rstc[gcvCORE_MAJOR] = IS_ERR(rstc) ? NULL : rstc; rstc = devm_reset_control_get(pdev, "gpu2d"); priv->rstc[gcvCORE_2D] = IS_ERR(rstc) ? NULL : rstc; rstc = devm_reset_control_get(pdev, "gpuvg"); priv->rstc[gcvCORE_VG] = IS_ERR(rstc) ? NULL : rstc; #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0) #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) /*get gpu regulator*/ priv->gpu_regulator = regulator_get(pdev, "cpu_vddgpu"); #elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) priv->gpu_regulator = devm_regulator_get(pdev, "pu"); #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) if (IS_ERR(priv->gpu_regulator)) { gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER, "%s(%d): Failed to get gpu regulator \n", __FUNCTION__, __LINE__); return gcvSTATUS_NOT_FOUND; } #endif #endif /*Initialize the clock structure*/ priv->clk_3d_core = clk_get(pdev, "gpu3d_clk"); if (!IS_ERR(priv->clk_3d_core)) { #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) if (cpu_is_mx6q()) { priv->clk_3d_shader = clk_get(pdev, "gpu3d_shader_clk"); if (IS_ERR(priv->clk_3d_shader)) { clk_put(priv->clk_3d_core); priv->clk_3d_core = NULL; priv->clk_3d_shader = NULL; gckOS_Print("galcore: clk_get gpu3d_shader_clk failed, disable 3d!\n"); } } #else priv->clk_3d_axi = clk_get(pdev, "gpu3d_axi_clk"); priv->clk_3d_shader = clk_get(pdev, "gpu3d_shader_clk"); if (IS_ERR(priv->clk_3d_shader)) { clk_put(priv->clk_3d_core); priv->clk_3d_core = NULL; priv->clk_3d_shader = NULL; gckOS_Print("galcore: clk_get gpu3d_shader_clk failed, disable 3d!\n"); } #endif } else { priv->clk_3d_core = NULL; gckOS_Print("galcore: clk_get gpu3d_clk failed, disable 3d!\n"); } priv->clk_2d_core = clk_get(pdev, "gpu2d_clk"); if (IS_ERR(priv->clk_2d_core)) { priv->clk_2d_core = NULL; gckOS_Print("galcore: clk_get 2d core clock failed, disable 2d/vg!\n"); } else { priv->clk_2d_axi = clk_get(pdev, "gpu2d_axi_clk"); if (IS_ERR(priv->clk_2d_axi)) { priv->clk_2d_axi = NULL; gckOS_Print("galcore: clk_get 2d axi clock failed, disable 2d\n"); } priv->clk_vg_axi = clk_get(pdev, "openvg_axi_clk"); if (IS_ERR(priv->clk_vg_axi)) { priv->clk_vg_axi = NULL; gckOS_Print("galcore: clk_get vg clock failed, disable vg!\n"); } } #if gcdENABLE_FSCALE_VAL_ADJUST pdevice = Platform->device; REG_THERMAL_NOTIFIER(&thermal_hot_pm_notifier); { int ret = 0; ret = driver_create_file(pdevice->dev.driver, &driver_attr_gpu3DMinClock); if(ret) dev_err(&pdevice->dev, "create gpu3DMinClock attr failed (%d)\n", ret); } #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) imx6sx_optimize_qosc_for_GPU(Platform); #endif return gcvSTATUS_OK; }
gceSTATUS gckPLATFORM_AdjustParam( IN gckPLATFORM Platform, OUT gcsMODULE_PARAMETERS *Args ) { struct resource* res; struct platform_device* pdev = Platform->device; #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) #elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) struct device_node *dn =pdev->dev.of_node; const u32 *prop; #else struct viv_gpu_platform_data *pdata; #endif res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phys_baseaddr"); if (res) Args->baseAddress = res->start; res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq_3d"); if (res) Args->irqLine = res->start; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iobase_3d"); if (res) { Args->registerMemBase = res->start; Args->registerMemSize = res->end - res->start + 1; } res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq_2d"); if (res) Args->irqLine2D = res->start; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iobase_2d"); if (res) { Args->registerMemBase2D = res->start; Args->registerMemSize2D = res->end - res->start + 1; } res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq_vg"); if (res) Args->irqLineVG = res->start; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iobase_vg"); if (res) { Args->registerMemBaseVG = res->start; Args->registerMemSizeVG = res->end - res->start + 1; } #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) Args->contiguousBase = 0; #elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) prop = of_get_property(dn, "contiguousbase", NULL); if(prop) Args->contiguousBase = *prop; of_property_read_u32(dn,"contiguoussize", (u32 *)&contiguousSize); #else pdata = pdev->dev.platform_data; if (pdata) { Args->contiguousBase = pdata->reserved_mem_base; Args->contiguousSize = pdata->reserved_mem_size; } #endif if (Args->contiguousSize == 0) gckOS_Print("Warning: No contiguous memory is reserverd for gpu.!\n "); Args->gpu3DMinClock = initgpu3DMinClock; if(Args->physSize == 0) Args->physSize = 0x80000000; return gcvSTATUS_OK; }
static int force_contiguous_lowmem_shrink(IN gckKERNEL Kernel) { struct task_struct *p; struct task_struct *selected = NULL; int tasksize; int ret = -1; int min_adj = 0; int selected_tasksize = 0; int selected_oom_adj; /* * If we already have a death outstanding, then * bail out right away; indicating to vmscan * that we have nothing further to offer on * this pass. * */ if (lowmem_deathpending && time_before_eq(jiffies, lowmem_deathpending_timeout)) return 0; selected_oom_adj = min_adj; rcu_read_lock(); for_each_process(p) { struct mm_struct *mm; struct signal_struct *sig; gcuDATABASE_INFO info; int oom_adj; task_lock(p); mm = p->mm; sig = p->signal; if (!mm || !sig) { task_unlock(p); continue; } oom_adj = sig->oom_score_adj; if (oom_adj < min_adj) { task_unlock(p); continue; } tasksize = 0; task_unlock(p); rcu_read_unlock(); if (gckKERNEL_QueryProcessDB(Kernel, p->pid, gcvFALSE, gcvDB_VIDEO_MEMORY, &info) == gcvSTATUS_OK){ tasksize += info.counters.bytes / PAGE_SIZE; } if (gckKERNEL_QueryProcessDB(Kernel, p->pid, gcvFALSE, gcvDB_CONTIGUOUS, &info) == gcvSTATUS_OK){ tasksize += info.counters.bytes / PAGE_SIZE; } rcu_read_lock(); if (tasksize <= 0) continue; gckOS_Print("<gpu> pid %d (%s), adj %d, size %d \n", p->pid, p->comm, oom_adj, tasksize); if (selected) { if (oom_adj < selected_oom_adj) continue; if (oom_adj == selected_oom_adj && tasksize <= selected_tasksize) continue; } selected = p; selected_tasksize = tasksize; selected_oom_adj = oom_adj; } if (selected) { gckOS_Print("<gpu> send sigkill to %d (%s), adj %d, size %d\n", selected->pid, selected->comm, selected_oom_adj, selected_tasksize); lowmem_deathpending = selected; lowmem_deathpending_timeout = jiffies + HZ; force_sig(SIGKILL, selected); ret = 0; } rcu_read_unlock(); return ret; }
/******************************************************************************* ** ** 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; } } }
static int __devinit gpu_probe(struct platform_device *pdev) #endif { int ret = -ENODEV; struct resource* res; #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) struct contiguous_mem_pool *pool; struct reset_control *rstc; #elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) struct device_node *dn =pdev->dev.of_node; const u32 *prop; #else struct viv_gpu_platform_data *pdata; #endif gcmkHEADER(); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phys_baseaddr"); if (res) baseAddress = res->start; res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq_3d"); if (res) irqLine = res->start; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iobase_3d"); if (res) { registerMemBase = res->start; registerMemSize = res->end - res->start + 1; } res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq_2d"); if (res) irqLine2D = res->start; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iobase_2d"); if (res) { registerMemBase2D = res->start; registerMemSize2D = res->end - res->start + 1; } res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq_vg"); if (res) irqLineVG = res->start; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "iobase_vg"); if (res) { registerMemBaseVG = res->start; registerMemSizeVG = res->end - res->start + 1; } #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) pool = devm_kzalloc(&pdev->dev, sizeof(*pool), GFP_KERNEL); if (!pool) return -ENOMEM; pool->size = contiguousSize; init_dma_attrs(&pool->attrs); dma_set_attr(DMA_ATTR_WRITE_COMBINE, &pool->attrs); pool->virt = dma_alloc_attrs(&pdev->dev, pool->size, &pool->phys, GFP_KERNEL, &pool->attrs); if (!pool->virt) { dev_err(&pdev->dev, "Failed to allocate contiguous memory\n"); return -ENOMEM; } contiguousBase = pool->phys; dev_set_drvdata(&pdev->dev, pool); #elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) prop = of_get_property(dn, "contiguousbase", NULL); if(prop) contiguousBase = *prop; of_property_read_u32(dn,"contiguoussize", (u32 *)&contiguousSize); #else pdata = pdev->dev.platform_data; if (pdata) { contiguousBase = pdata->reserved_mem_base; contiguousSize = pdata->reserved_mem_size; } #endif if (contiguousSize == 0) gckOS_Print("Warning: No contiguous memory is reserverd for gpu.!\n "); ret = drv_init(&pdev->dev); if (!ret) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) rstc = devm_reset_control_get(&pdev->dev, "gpu3d"); galDevice->rstc[gcvCORE_MAJOR] = IS_ERR(rstc) ? NULL : rstc; rstc = devm_reset_control_get(&pdev->dev, "gpu2d"); galDevice->rstc[gcvCORE_2D] = IS_ERR(rstc) ? NULL : rstc; rstc = devm_reset_control_get(&pdev->dev, "gpuvg"); galDevice->rstc[gcvCORE_VG] = IS_ERR(rstc) ? NULL : rstc; #endif platform_set_drvdata(pdev, galDevice); #if gcdENABLE_FSCALE_VAL_ADJUST if (galDevice->kernels[gcvCORE_MAJOR]) REG_THERMAL_NOTIFIER(&thermal_hot_pm_notifier); #endif gcmkFOOTER_NO(); return ret; } #if gcdENABLE_FSCALE_VAL_ADJUST UNREG_THERMAL_NOTIFIER(&thermal_hot_pm_notifier); #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) dma_free_attrs(&pdev->dev, pool->size, pool->virt, pool->phys, &pool->attrs); #endif gcmkFOOTER_ARG(KERN_INFO "Failed to register gpu driver: %d\n", ret); return ret; }