static void drv_exit(void) #endif { gcmkHEADER(); gcmkASSERT(gpuClass != gcvNULL); device_destroy(gpuClass, MKDEV(major, 0)); class_destroy(gpuClass); unregister_chrdev(major, DEVICE_NAME); gcmkVERIFY_OK(gckGALDEVICE_Stop(galDevice)); gcmkVERIFY_OK(gckGALDEVICE_Destroy(galDevice)); if(gckDEBUGFS_IsEnabled()) { gckDEBUGFS_Terminate(); } #if ENABLE_GPU_CLOCK_BY_DRIVER && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) { struct clk * clk = NULL; #if defined(CONFIG_PXA_DVFM) && (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)) gc_pwr(0); #endif clk = clk_get(NULL, "GCCLK"); clk_disable(clk); } #endif gcmkFOOTER_NO(); }
static void drv_exit(void) #endif { gcmkHEADER(); gcmkASSERT(gpuClass != gcvNULL); device_destroy(gpuClass, MKDEV(major, 0)); class_destroy(gpuClass); unregister_chrdev(major, DRV_NAME); gcmkVERIFY_OK(gckGALDEVICE_Stop(galDevice)); gcmkVERIFY_OK(gckGALDEVICE_Destroy(galDevice)); if(gckDebugFileSystemIsEnabled()) { gckDebugFileSystemTerminate(); } #if ENABLE_GPU_CLOCK_BY_DRIVER && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) { #if MRVL_PLATFORM_PXA1088 gcmkVERIFY_OK(gckOS_GpuPowerDisable(galDevice->os, gcvCORE_2D, gcvTRUE, gcvFALSE)); #endif gcmkVERIFY_OK(gckOS_GpuPowerDisable(galDevice->os, gcvCORE_MAJOR, gcvTRUE, gcvTRUE)); } #endif gcmkFOOTER_NO(); }
static void drv_exit(void) #endif { gcmkHEADER(); #ifdef CONFIG_GPU_LOW_MEMORY_KILLER task_free_unregister(&task_nb); #endif #ifdef CONFIG_ANDROID_RESERVED_MEMORY_ACCOUNT unregister_reserved_memory_account(&viv_gpu_resmem_handler); #endif gcmkASSERT(gpuClass != gcvNULL); device_destroy(gpuClass, MKDEV(major, 0)); class_destroy(gpuClass); unregister_chrdev(major, DRV_NAME); gcmkVERIFY_OK(gckGALDEVICE_Stop(galDevice)); gcmkVERIFY_OK(gckGALDEVICE_Destroy(galDevice)); if(gckDebugFileSystemIsEnabled()) { gckDebugFileSystemTerminate(); } #if ENABLE_GPU_CLOCK_BY_DRIVER && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) { # if 0 struct clk * clk = NULL; #if defined(CONFIG_PXA_DVFM) && (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)) gc_pwr(0); #endif clk = clk_get(NULL, "GCCLK"); clk_disable(clk); # endif } #endif gcmkFOOTER_NO(); }
static void drv_exit(void) #endif { gcmkHEADER(); gcmkASSERT(gpuClass != gcvNULL); device_destroy(gpuClass, MKDEV(major, 0)); class_destroy(gpuClass); unregister_chrdev(major, DEVICE_NAME); gcmkVERIFY_OK(gckGALDEVICE_Stop(galDevice)); gcmkVERIFY_OK(gckGALDEVICE_Destroy(galDevice)); if(gckDEBUGFS_IsEnabled()) { gckDEBUGFS_Terminate(); } gcmkFOOTER_NO(); }
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; }
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; }
static int drv_init(struct device *pdev) #endif { int ret; int result = -EINVAL; gceSTATUS status; gckGALDEVICE device = gcvNULL; struct class* device_class = gcvNULL; gcmkHEADER(); #if ENABLE_GPU_CLOCK_BY_DRIVER && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)) { # if 0 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 } #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) { printk("galcore options:\n"); printk(" irqLine = %d\n", irqLine); printk(" registerMemBase = 0x%08lX\n", registerMemBase); printk(" registerMemSize = 0x%08lX\n", registerMemSize); if (irqLine2D != -1) { printk(" irqLine2D = %d\n", irqLine2D); printk(" registerMemBase2D = 0x%08lX\n", registerMemBase2D); printk(" registerMemSize2D = 0x%08lX\n", registerMemSize2D); } if (irqLineVG != -1) { printk(" irqLineVG = %d\n", irqLineVG); printk(" registerMemBaseVG = 0x%08lX\n", registerMemBaseVG); printk(" registerMemSizeVG = 0x%08lX\n", registerMemSizeVG); } printk(" contiguousSize = %ld\n", contiguousSize); printk(" contiguousBase = 0x%08lX\n", contiguousBase); printk(" bankSize = 0x%08lX\n", bankSize); printk(" fastClear = %d\n", fastClear); printk(" compression = %d\n", compression); printk(" signal = %d\n", signal); printk(" baseAddress = 0x%08lX\n", baseAddress); printk(" physSize = 0x%08lX\n", physSize); printk(" logFileSize = %d KB \n", logFileSize); printk(" powerManagement = %d\n", powerManagement); printk(" gpuProfiler = %d\n", gpuProfiler); #if ENABLE_GPU_CLOCK_BY_DRIVER printk(" coreClock = %lu\n", coreClock); #endif } if(logFileSize != 0) { gckDebugFileSystemInitialize(); } /* Create the GAL device. */ gcmkONERROR(gckGALDEVICE_Construct( irqLine, registerMemBase, registerMemSize, irqLine2D, registerMemBase2D, registerMemSize2D, irqLineVG, registerMemBaseVG, registerMemSizeVG, contiguousBase, contiguousSize, bankSize, fastClear, compression, baseAddress, physSize, signal, logFileSize, pdev, powerManagement, gpuProfiler, &device )); #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) device->pool = dev_get_drvdata(pdev); #endif /* Start the GAL device. */ gcmkONERROR(gckGALDEVICE_Start(device)); if ((physSize != 0) && (device->kernels[gcvCORE_MAJOR] != gcvNULL) && (device->kernels[gcvCORE_MAJOR]->hardware->mmuVersion != 0)) { status = gckMMU_Enable(device->kernels[gcvCORE_MAJOR]->mmu, baseAddress, physSize); gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER, "Enable new MMU: status=%d\n", status); 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); } /* Reset the base address */ device->baseAddress = 0; } #ifdef CONFIG_ANDROID_RESERVED_MEMORY_ACCOUNT task_free_register(&task_nb); viv_gpu_resmem_handler.data = device->kernels[gcvCORE_MAJOR]; register_reserved_memory_account(&viv_gpu_resmem_handler); #endif /* Register the character device. */ ret = register_chrdev(major, DRV_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, "galcore"); #else device_create(device_class, NULL, MKDEV(major, 0), "galcore"); #endif galDevice = device; gpuClass = device_class; gcmkTRACE_ZONE( gcvLEVEL_INFO, gcvZONE_DRIVER, "%s(%d): irqLine=%d, contiguousSize=%lu, memBase=0x%lX\n", __FUNCTION__, __LINE__, irqLine, contiguousSize, registerMemBase ); /* 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; }
/******************************************************************************* ** ** 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, 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); } } 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 )); #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) { } 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); } { /* 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; device->contiguousPhysical = gcvNULL; device->contiguousPhysicalName = 0; device->contiguousSize = ContiguousSize; device->contiguousMapped = gcvTRUE; } } } /* Return pointer to the device. */ * Device = device; gcmkFOOTER_ARG("*Device=0x%x", * Device); return gcvSTATUS_OK; OnError: /* Roll back. */ gcmkVERIFY_OK(gckGALDEVICE_Destroy(device)); gcmkFOOTER(); return status; }
static int drv_init(void) #endif { int ret, i; int result = -EINVAL; gceSTATUS status = gcvSTATUS_OK; gckGALDEVICE device = gcvNULL; struct class* device_class = gcvNULL; gcmkHEADER(); #if ENABLE_GPU_CLOCK_BY_DRIVER && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)) gcmkONERROR(gckOS_GpuPowerEnable(gcvNULL, gcvCORE_MAJOR, gcvTRUE, gcvTRUE, coreClock*1000*1000)); #if MRVL_PLATFORM_PXA1088 /* PXA1088: 2D power is shared with 3D */ gcmkONERROR(gckOS_GpuPowerEnable(gcvNULL, gcvCORE_2D, gcvTRUE, gcvFALSE, coreClock*1000*1000)); #endif #endif #if MRVL_PLATFORM_NEVO if (cpu_is_pxa978_Dx()) { baseAddress = 0x0; } else { baseAddress = 0x80000000; } #endif if (showArgs) { printk("galcore options:\n"); printk(" irqLine = %d\n", irqLine); printk(" registerMemBase = 0x%08lX\n", registerMemBase); printk(" registerMemSize = 0x%08lX\n", registerMemSize); if (irqLine2D != -1) { printk(" irqLine2D = %d\n", irqLine2D); printk(" registerMemBase2D = 0x%08lX\n", registerMemBase2D); printk(" registerMemSize2D = 0x%08lX\n", registerMemSize2D); } if (irqLineVG != -1) { printk(" irqLineVG = %d\n", irqLineVG); printk(" registerMemBaseVG = 0x%08lX\n", registerMemBaseVG); printk(" registerMemSizeVG = 0x%08lX\n", registerMemSizeVG); } printk(" contiguousSize = %ld\n", contiguousSize); printk(" contiguousBase = 0x%08lX\n", contiguousBase); printk(" bankSize = 0x%08lX\n", bankSize); #if (MRVL_VIDEO_MEMORY_USE_TYPE != gcdMEM_TYPE_NONE) printk(" pmemSize = %ld\n", pmemSize); #endif printk(" fastClear = %d\n", fastClear); printk(" compression = %d\n", compression); printk(" signal = %d\n", signal); printk(" baseAddress = 0x%08lX\n", baseAddress); printk(" physSize = 0x%08lX\n", physSize); printk(" logFileSize = %d KB \n", logFileSize); #if ENABLE_GPU_CLOCK_BY_DRIVER printk(" coreClock = %lu\n", coreClock); #endif } physSize = 0x80000000; #ifndef CONFIG_CPU_PXA988 pmemSize = 0x0; #endif printk(" physSize modified to = 0x%08lX\n", physSize); if(logFileSize != 0) { gckDebugFileSystemInitialize(); } /* Create the GAL device. */ gcmkONERROR(gckGALDEVICE_Construct( irqLine, registerMemBase, registerMemSize, irqLine2D, registerMemBase2D, registerMemSize2D, irqLineVG, registerMemBaseVG, registerMemSizeVG, contiguousBase, contiguousSize, #if (MRVL_VIDEO_MEMORY_USE_TYPE != gcdMEM_TYPE_NONE) pmemSize, #endif bankSize, fastClear, compression, baseAddress, physSize, signal, logFileSize, &device )); /* Start the GAL device. */ gcmkONERROR(gckGALDEVICE_Start(device)); if ((physSize != 0) && (device->kernels[gcvCORE_MAJOR] != gcvNULL) && (device->kernels[gcvCORE_MAJOR]->hardware->mmuVersion != 0)) { status = gckMMU_Enable(device->kernels[gcvCORE_MAJOR]->mmu, mmuBaseAddress, physSize); //status = gckMMU_Enable(device->kernels[gcvCORE_MAJOR]->mmu, (gctUINT32)device->contiguousStart, contiguousSize); gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER, "Enable new MMU: status=%d\n", status); if ((device->kernels[gcvCORE_2D] != gcvNULL) && (device->kernels[gcvCORE_2D]->hardware->mmuVersion != 0)) { status = gckMMU_Enable(device->kernels[gcvCORE_2D]->mmu, mmuBaseAddress, physSize); gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER, "Enable new MMU for 2D: status=%d\n", status); } /* Reset the base address */ device->baseAddress = 0; } for (i = 0; i < gcdMAX_GPU_COUNT; i++) { if(device->kernels[i] != gcvNULL) { device->kernels[i]->bTryIdleGPUEnable = gcvTRUE; } } /* Register the character device. */ ret = register_chrdev(major, DRV_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 (pdevice == gcvNULL) gcmkONERROR(gcvSTATUS_DEVICE); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) device_create(device_class, pdevice, MKDEV(major, 0), NULL, "galcore"); #else device_create(device_class, pdevice, MKDEV(major, 0), "galcore"); #endif galDevice = device; gpuClass = device_class; gcmkTRACE_ZONE( gcvLEVEL_INFO, gcvZONE_DRIVER, "%s(%d): irqLine=%d, contiguousSize=%lu, memBase=0x%lX\n", __FUNCTION__, __LINE__, irqLine, contiguousSize, registerMemBase ); /* 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; }