static long ged_ioctl(struct file *pFile, unsigned int ioctlCmd, unsigned long arg)
{
    int ret = -EFAULT;
	GED_BRIDGE_PACKAGE *psBridgePackageKM, *psBridgePackageUM = (GED_BRIDGE_PACKAGE*)arg;
	GED_BRIDGE_PACKAGE sBridgePackageKM;

    if (down_interruptible(&ged_dal_sem) < 0) 
    {
        GED_LOGE("Fail to down ged_dal_sem\n");
        return -ERESTARTSYS;
    }

	psBridgePackageKM = &sBridgePackageKM;
    if (0 != ged_copy_from_user(psBridgePackageKM, psBridgePackageUM, sizeof(GED_BRIDGE_PACKAGE)))
    {
        GED_LOGE("Fail to ged_copy_from_user\n");
        goto unlock_and_return;
    }

    ret = ged_dispatch(psBridgePackageKM);

unlock_and_return:
    up(&ged_dal_sem);

    return ret;
}
static long ged_dispatch(GED_BRIDGE_PACKAGE *psBridgePackageKM)
{
    int ret = -EFAULT;
    void *pvInt, *pvOut;
    typedef int (ged_bridge_func_type)(void*, void*);
    ged_bridge_func_type* pFunc = NULL;
    
    if ((psBridgePackageKM->i32InBufferSize >=0) && (psBridgePackageKM->i32OutBufferSize >=0) &&
        (psBridgePackageKM->i32InBufferSize + psBridgePackageKM->i32OutBufferSize < GED_IOCTL_PARAM_BUF_SIZE))
    {
        pvInt = gvIOCTLParamBuf;
        pvOut = (void*)((char*)pvInt + (uintptr_t)psBridgePackageKM->i32InBufferSize);
        if (psBridgePackageKM->i32InBufferSize > 0)
        {
            if (0 != ged_copy_from_user(pvInt, psBridgePackageKM->pvParamIn, psBridgePackageKM->i32InBufferSize))
            {
                GED_LOGE("ged_copy_from_user fail\n");
                return ret;
            }
        }

        // we will change the below switch into a function pointer mapping table in the future
        switch(GED_GET_BRIDGE_ID(psBridgePackageKM->ui32FunctionID))
        {
        case GED_BRIDGE_COMMAND_LOG_BUF_GET:
            pFunc = (ged_bridge_func_type*)ged_bridge_log_buf_get;
            break;
        case GED_BRIDGE_COMMAND_LOG_BUF_WRITE:
            pFunc = (ged_bridge_func_type*)ged_bridge_log_buf_write;
            break;
        case GED_BRIDGE_COMMAND_LOG_BUF_RESET:
            pFunc = (ged_bridge_func_type*)ged_bridge_log_buf_reset;
            break;            
        case GED_BRIDGE_COMMAND_BOOST_GPU_FREQ:
            pFunc = (ged_bridge_func_type*)ged_bridge_boost_gpu_freq;
            break;
        case GED_BRIDGE_COMMAND_MONITOR_3D_FENCE:
            pFunc = (ged_bridge_func_type*)ged_bridge_monitor_3D_fence;
            break;
        default:
            GED_LOGE("Unknown Bridge ID: %u\n", GED_GET_BRIDGE_ID(psBridgePackageKM->ui32FunctionID));
            break;
        }

        if (pFunc)
        {
            ret = pFunc(pvInt, pvOut);
        }

        if (psBridgePackageKM->i32OutBufferSize > 0)
        {
            if (0 != ged_copy_to_user(psBridgePackageKM->pvParamOut, pvOut, psBridgePackageKM->i32OutBufferSize))
            {
                return ret;
            }
        }
    }

    return ret;
}
static int ged_init(void)
{
    GED_ERROR err = GED_ERROR_FAIL;

    gvIOCTLParamBuf = vmalloc(GED_IOCTL_PARAM_BUF_SIZE);
    if (NULL == gvIOCTLParamBuf)
    {
        err = GED_ERROR_OOM;
        goto ERROR;
    }

    if (NULL == proc_create(GED_DRIVER_DEVICE_NAME, 0644, NULL, &ged_fops))
    {
        err = GED_ERROR_FAIL;
        GED_LOGE("ged: failed to register ged proc entry!\n");
        goto ERROR;
    }

    err = ged_debugFS_init();
    if (unlikely(err != GED_OK))
    {
        GED_LOGE("ged: failed to init debug FS!\n");
        goto ERROR;
    }

    err = ged_log_system_init();
    if (unlikely(err != GED_OK))
    {
        GED_LOGE("ged: failed to create gedlog entry!\n");
        goto ERROR;
    }

    err = ged_hal_init();
    if (unlikely(err != GED_OK))
    {
        GED_LOGE("ged: failed to create hal entry!\n");
        goto ERROR;
    }

    err = ged_profile_dvfs_init();
    if (unlikely(err != GED_OK))
    {
        GED_LOGE("ged: failed to init profile dvfs!\n");
        goto ERROR;
    }

#ifdef GED_DEBUG
    ghLogBuf_GLES = ged_log_buf_alloc(160, 128 * 160, GED_LOG_BUF_TYPE_RINGBUFFER, GED_LOG_BUF_COMMON_GLES, NULL);
    ghLogBuf_GED = ged_log_buf_alloc(32, 64 * 32, GED_LOG_BUF_TYPE_RINGBUFFER, "GED internal", NULL);
#endif

    return 0;

ERROR:
    ged_exit();

    return -EFAULT;
}
示例#4
0
static void ged_dvfs_custom_ceiling_gpu_freq(unsigned int ui32FreqLevel)
{

	unsigned int ui32MaxLevel;

	if (gpu_debug_enable)
	{
		GED_LOGE("%s: freq = %d", __func__,ui32FreqLevel);
	}

	ui32MaxLevel = mt_gpufreq_get_dvfs_table_num() - 1;
	if (ui32MaxLevel < ui32FreqLevel)
	{
		ui32FreqLevel = ui32MaxLevel;
	}

	mutex_lock(&gsDVFSLock);

	// 0 => The highest frequency
	// table_num - 1 => The lowest frequency
	g_cust_upbound_freq_id = ui32MaxLevel - ui32FreqLevel;

	gpu_cust_upbound_freq = mt_gpufreq_get_freq_by_idx(g_cust_upbound_freq_id);


	if (g_cust_upbound_freq_id > mt_gpufreq_get_cur_freq_index())
	{
		ged_dvfs_gpu_freq_commit(g_cust_upbound_freq_id, GED_DVFS_CUSTOM_CEIL_COMMIT);
	}

	mutex_unlock(&gsDVFSLock);

}
示例#5
0
static void ged_dvfs_set_bottom_gpu_freq(unsigned int ui32FreqLevel)
{


	unsigned int ui32MaxLevel;
	if (gpu_debug_enable)
	{
		GED_LOGE("%s: freq = %d", __func__,ui32FreqLevel);
	}

	ui32MaxLevel = mt_gpufreq_get_dvfs_table_num() - 1;
	if (ui32MaxLevel < ui32FreqLevel)
	{
		ui32FreqLevel = ui32MaxLevel;
	}

	mutex_lock(&gsDVFSLock);

	// 0 => The highest frequency
	// table_num - 1 => The lowest frequency
	g_bottom_freq_id = ui32MaxLevel - ui32FreqLevel;

	gpu_bottom_freq = mt_gpufreq_get_freq_by_idx(g_bottom_freq_id);

	//if current id is larger, ie lower freq, we need to reflect immedately
	if(g_bottom_freq_id < mt_gpufreq_get_cur_freq_index()) 
		ged_dvfs_gpu_freq_commit(g_bottom_freq_id, GED_DVFS_SET_BOTTOM_COMMIT);

	mutex_unlock(&gsDVFSLock);

}
示例#6
0
void ged_dvfs_boost_gpu_freq(void)
{
	if (gpu_debug_enable)
	{
		GED_LOGE("%s", __func__);
	}
	ged_dvfs_freq_input_boostCB(0);
}
static long ged_ioctl_compat(struct file *pFile, unsigned int ioctlCmd, unsigned long arg)
{
    typedef struct GED_BRIDGE_PACKAGE_32_TAG
    {
        unsigned int    ui32FunctionID;
        int             i32Size;
        unsigned int    ui32ParamIn;
        int             i32InBufferSize;
        unsigned int    ui32ParamOut;
        int             i32OutBufferSize;
    } GED_BRIDGE_PACKAGE_32;

    int ret = -EFAULT;
    GED_BRIDGE_PACKAGE sBridgePackageKM64;
    GED_BRIDGE_PACKAGE_32 sBridgePackageKM32;
    GED_BRIDGE_PACKAGE_32 *psBridgePackageKM32 = &sBridgePackageKM32;    
    GED_BRIDGE_PACKAGE_32 *psBridgePackageUM32 = (GED_BRIDGE_PACKAGE_32*)arg;

    if (down_interruptible(&ged_dal_sem) < 0) 
    {
        GED_LOGE("Fail to down ged_dal_sem\n");
        return -ERESTARTSYS;
    }

    if (0 != ged_copy_from_user(psBridgePackageKM32, psBridgePackageUM32, sizeof(GED_BRIDGE_PACKAGE_32)))
    {
        GED_LOGE("Fail to ged_copy_from_user\n");
        goto unlock_and_return;
    }

    sBridgePackageKM64.ui32FunctionID = psBridgePackageKM32->ui32FunctionID;
    sBridgePackageKM64.i32Size = sizeof(GED_BRIDGE_PACKAGE);
    sBridgePackageKM64.pvParamIn = (void*) ((size_t) psBridgePackageKM32->ui32ParamIn);
    sBridgePackageKM64.pvParamOut = (void*) ((size_t) psBridgePackageKM32->ui32ParamOut);
    sBridgePackageKM64.i32InBufferSize = psBridgePackageKM32->i32InBufferSize;
    sBridgePackageKM64.i32OutBufferSize = psBridgePackageKM32->i32OutBufferSize;
    
    ret = ged_dispatch(&sBridgePackageKM64);
    
unlock_and_return:
    up(&ged_dal_sem);
    
    return ret;
}
示例#8
0
void ged_dvfs_vsync_offset_event_switch(GED_DVFS_VSYNC_OFFSET_SWITCH_CMD eEvent, bool bSwitch)
{
	unsigned int  ui32BeforeSwitchInterpret;
	unsigned int  ui32BeforeDebugInterpret;
	mutex_lock(&gsVSyncOffsetLock);

	ui32BeforeSwitchInterpret = g_ui32EventStatus;
	ui32BeforeDebugInterpret = g_ui32EventDebugStatus;

	switch(eEvent)
	{
		case GED_DVFS_VSYNC_OFFSET_FORCE_ON:
			g_ui32EventDebugStatus |= GED_EVENT_FORCE_ON;
			g_ui32EventDebugStatus &= (~GED_EVENT_FORCE_OFF);
			break;
		case GED_DVFS_VSYNC_OFFSET_FORCE_OFF:
			g_ui32EventDebugStatus |= GED_EVENT_FORCE_OFF;
			g_ui32EventDebugStatus &= (~GED_EVENT_FORCE_ON);
			break;
		case GED_DVFS_VSYNC_OFFSET_DEBUG_CLEAR_EVENT:
			g_ui32EventDebugStatus &= (~GED_EVENT_FORCE_ON);
			g_ui32EventDebugStatus &= (~GED_EVENT_FORCE_OFF);
			break;
		case GED_DVFS_VSYNC_OFFSET_TOUCH_EVENT:
			if(GED_TRUE==bSwitch) // touch boost
				ged_dvfs_boost_gpu_freq(); 
			(bSwitch)? (g_ui32EventStatus|=GED_EVENT_TOUCH): (g_ui32EventStatus&= (~GED_EVENT_TOUCH));            
			break;
		case GED_DVFS_VSYNC_OFFSET_THERMAL_EVENT:
			(bSwitch)? (g_ui32EventStatus|=GED_EVENT_THERMAL): (g_ui32EventStatus&= (~GED_EVENT_THERMAL));
			break;
		case GED_DVFS_VSYNC_OFFSET_WFD_EVENT:
			(bSwitch)? (g_ui32EventStatus|=GED_EVENT_WFD): (g_ui32EventStatus&= (~GED_EVENT_WFD));
			break;
		case GED_DVFS_VSYNC_OFFSET_MHL_EVENT:
			(bSwitch)? (g_ui32EventStatus|=GED_EVENT_MHL): (g_ui32EventStatus&= (~GED_EVENT_MHL));
			break;
		case GED_DVFS_VSYNC_OFFSET_GAS_EVENT:
			(bSwitch)? (g_ui32EventStatus|=GED_EVENT_GAS): (g_ui32EventStatus&= (~GED_EVENT_GAS));
			break;
		default:
			GED_LOGE("%s: not acceptable event:%u \n", __func__,  eEvent); 
			goto CHECK_OUT;
	}

	if(ui32BeforeSwitchInterpret != g_ui32EventStatus || ui32BeforeDebugInterpret != g_ui32EventDebugStatus 
			|| g_ui32EventDebugStatus&GED_EVENT_NOT_SYNC)
	{
		ged_dvfs_probe_signal(GED_DVFS_VSYNC_OFFSET_SIGNAL_EVENT);
	}

CHECK_OUT:    
	mutex_unlock(&gsVSyncOffsetLock);
}
示例#9
0
//ged_dvfs_vsync_offset_level_set
static ssize_t ged_vsync_offset_level_write_entry(
	const char __user *pszBuffer,
	size_t uiCount,
	loff_t uiPosition,
	void *pvData)
{
#define GED_HAL_DEBUGFS_SIZE 64
#define NUM_TOKEN 2

/*
 *  This proc node accept only: [CMD] [NUM]
 *  for ex: "touch 1"
 *  
 */    
    
    char acBuffer[GED_HAL_DEBUGFS_SIZE];
    int aint32Indx[NUM_TOKEN];
    char* pcCMD;
    char* pcValue;
    int i;
int i32VsyncOffsetLevel;
	int ret;

	if (!((0 < uiCount) && (uiCount < GED_HAL_DEBUGFS_SIZE - 1)))
		return 0;

	if (ged_copy_from_user(acBuffer, pszBuffer, uiCount))
		return 0;

            acBuffer[uiCount] = '\n';
            acBuffer[uiCount+1] = 0;
            i=tokenizer(acBuffer, uiCount, aint32Indx, NUM_TOKEN);
            GED_LOGE("i=%d",i);
            if(i==NUM_TOKEN)
            {
                pcCMD = acBuffer+aint32Indx[0];
                
                pcValue = acBuffer+aint32Indx[1];
                if(strcmp(pcCMD,"set_vsync_offset")==0)
                {
			ret = kstrtoint(pcValue, 0, &i32VsyncOffsetLevel);
                        ged_dvfs_vsync_offset_level_set(i32VsyncOffsetLevel);
                }
            }

    return 0;
}
static int ged_release(struct inode *inode, struct file *filp)
{
    GED_LOGE("%s:%d:%d\n", __func__, MAJOR(inode->i_rdev), MINOR(inode->i_rdev));
    return 0;
}
示例#11
0
//-----------------------------------------------------------------------------
GED_ERROR ged_hal_init(void)
{
    GED_ERROR err = GED_OK;

    err = ged_debugFS_create_entry_dir(
            "hal",
            NULL,
            &gpsHALDir);

    if (unlikely(err != GED_OK))
    {
        err = GED_ERROR_FAIL;
        GED_LOGE("ged: failed to create hal dir!\n");
        goto ERROR;
    }

    /* Feedback the gpu freq level count */
    err = ged_debugFS_create_entry(
            "total_gpu_freq_level_count",
            gpsHALDir,
            &gsTotalGPUFreqLevelCountReadOps,
            NULL,
            NULL,
            &gpsTotalGPUFreqLevelCountEntry);

    if (unlikely(err != GED_OK))
    {
        GED_LOGE("ged: failed to create total_gpu_freq_level_count entry!\n");
        goto ERROR;
    }

    /* Control the gpu freq */
    err = ged_debugFS_create_entry(
            "custom_boost_gpu_freq",
            gpsHALDir,
            &gsCustomBoostGpuFreqReadOps,
            ged_custom_boost_gpu_freq_write_entry,
            NULL,
            &gpsCustomBoostGPUFreqEntry);

    if (unlikely(err != GED_OK))
    {
        GED_LOGE("ged: failed to create custom_boost_gpu_freq entry!\n");
        goto ERROR;
    }

    /* Control the gpu freq */
    err = ged_debugFS_create_entry(
            "custom_upbound_gpu_freq",
            gpsHALDir,
            &gsCustomUpboundGpuFreqReadOps,
            ged_custom_upbound_gpu_freq_write_entry,
            NULL,
            &gpsCustomUpboundGPUFreqEntry);

    if (unlikely(err != GED_OK))
    {
        GED_LOGE("ged: failed to create custom_upbound_gpu_freq entry!\n");
        goto ERROR;
    }

        /* Enable/Disable the vsync offset */
        
        err = ged_debugFS_create_entry(
            "event_notify",
            gpsHALDir,
            &gsVsync_offset_enableReadOps,
            ged_vsync_offset_enable_write_entry,
            NULL,
            &gpsVsyncOffsetEnableEntry);
    
    
    	/* Control the vsync offset level */
		
		err = ged_debugFS_create_entry(
            "vsync_offset_level",
            gpsHALDir,
            &gsVsync_offset_levelReadOps,
            ged_vsync_offset_level_write_entry,
            NULL,
            &gpsVsyncOffsetLevelEntry);
	
		/* Control the dvfs policy threshold level */
		
		err = ged_debugFS_create_entry(
            "custom_dvfs_mode",
            gpsHALDir,
            &gsDvfs_tuning_mode_ReadOps, 
            ged_dvfs_tuning_mode_write_entry, 
            NULL,
            &gpsDvfsTuningModeEntry);
        
        
        /* Get current GPU freq */
        
        err = ged_debugFS_create_entry(
            "current_freqency",
            gpsHALDir,
            &gsDvfs_cur_freq_ReadOps, 
            NULL, 
            NULL,
            &gpsDvfsCurFreqEntry);
        
      /* Get previous GPU freq */
        
        err = ged_debugFS_create_entry(
            "previous_freqency",
            gpsHALDir,
            &gsDvfs_pre_freq_ReadOps, 
            NULL, 
            NULL,
            &gpsDvfsPreFreqEntry);
     
     /* Get GPU Utilization */
        
        err = ged_debugFS_create_entry(
            "gpu_utilization",
            gpsHALDir,
            &gsDvfs_gpu_util_ReadOps, 
            NULL, 
            NULL,
            &gpsDvfsGpuUtilizationEntry);

	/* Get FPS upper bound */
	err = ged_debugFS_create_entry(
			"fps_upper_bound",
			gpsHALDir,
			&gs_fps_ub_read_ops,
			ged_fps_ub_write,
			NULL,
			&gpsFpsUpperBoundEntry
			);

    if (unlikely(err != GED_OK))
    {
        GED_LOGE("ged: failed to create vsync_offset_level entry!\n");
        goto ERROR;
    }
    

    return err;

ERROR:

    ged_hal_exit();

    return err;
}
示例#12
0
static ssize_t ged_vsync_offset_enable_write_entry(const char __user *pszBuffer, size_t uiCount, loff_t uiPosition, void *pvData)
{
#define GED_HAL_DEBUGFS_SIZE 64
#define NUM_TOKEN 2

/*
 *  This proc node accept only: [CMD] [NUM]
 *  for ex: "touch 1"
 *  
 */    
    
    char acBuffer[GED_HAL_DEBUGFS_SIZE];
    int aint32Indx[NUM_TOKEN];
    char* pcCMD;
    char* pcValue;
    int i;



    if ((0 < uiCount) && (uiCount < GED_HAL_DEBUGFS_SIZE))
    {
        if (0 == ged_copy_from_user(acBuffer, pszBuffer, uiCount))
        {
            acBuffer[uiCount] = '\0';
            i=tokenizer(acBuffer, uiCount, aint32Indx, NUM_TOKEN);
            if(i==NUM_TOKEN)
            {
                pcCMD = acBuffer+aint32Indx[0];
                
                pcValue = acBuffer+aint32Indx[1];
#ifdef ENABLE_COMMON_DVFS                
                if(strcmp(pcCMD,"touch_down")==0)
                {
                    if ( (*pcValue)=='1'|| (*pcValue) =='0')
                    {
                        if( (*pcValue) -'0'==0) // touch up
                            ged_dvfs_vsync_offset_event_switch(GED_DVFS_VSYNC_OFFSET_TOUCH_EVENT , false);
                        else // touch down
                            ged_dvfs_vsync_offset_event_switch(GED_DVFS_VSYNC_OFFSET_TOUCH_EVENT , true);
                    }  
                }
                else if(strcmp(pcCMD,"enable_WFD")==0)
                {
                    if ( (*pcValue) =='1'|| (*pcValue) =='0')
                    {
                        if( (*pcValue) -'0'==0) // WFD turn-off
                            ged_dvfs_vsync_offset_event_switch(GED_DVFS_VSYNC_OFFSET_WFD_EVENT , false);
                        else // WFD turn-on
                            ged_dvfs_vsync_offset_event_switch(GED_DVFS_VSYNC_OFFSET_WFD_EVENT , true);
                    }
                }
                else 
#endif                    
                    if(strcmp(pcCMD,"enable_debug")==0)
                {
                    if ( (*pcValue) =='1'|| (*pcValue) =='0'||(*pcValue) =='2')
                    {
                        if( (*pcValue) -'0'==1) // force off
                        {
                            ged_dvfs_vsync_offset_event_switch(GED_DVFS_VSYNC_OFFSET_FORCE_OFF , true);
                            bForce = GED_FALSE;
                        }
                        else if( (*pcValue) -'0'==2) // force on
                        {
                            ged_dvfs_vsync_offset_event_switch(GED_DVFS_VSYNC_OFFSET_FORCE_ON , true);
                            bForce = GED_TRUE;
                        }
                        else // turn-off debug
                            ged_dvfs_vsync_offset_event_switch(GED_DVFS_VSYNC_OFFSET_DEBUG_CLEAR_EVENT , true);
                    }
                }
                else if(strcmp(pcCMD, "gas") == 0)
                {
                    if ( (*pcValue) =='1'|| (*pcValue) =='0')
                    {
                            if( (*pcValue) -'0'==0)
                                ged_dvfs_vsync_offset_event_switch(GED_DVFS_VSYNC_OFFSET_GAS_EVENT, false);
                        else
                                ged_dvfs_vsync_offset_event_switch(GED_DVFS_VSYNC_OFFSET_GAS_EVENT, true);
                    }
		}
                else
                {
                    GED_LOGE("unknow command:%s %c",pcCMD,*pcValue);
                }
            }
            
        }
    }
    return uiCount;
   
}
示例#13
0
void ged_dvfs_run(unsigned long t, long phase, unsigned long ul3DFenceDoneTime)
{
	bool bError;	
	//ged_profile_dvfs_record_SW_vsync(t, phase, ul3DFenceDoneTime);
	mutex_lock(&gsDVFSLock);

	//gpu_pre_loading = gpu_loading;

	if (0 == gpu_dvfs_enable)
	{
		gpu_power = 0;
		gpu_loading = 0;
		gpu_block= 0;
		gpu_idle = 0;
		goto EXIT_ged_dvfs_run;         
	}

	// SKIP for keeping boost freq
	if(g_dvfs_skip_round>0)
	{
		g_dvfs_skip_round--;
		goto EXIT_ged_dvfs_run;			
	}		

	if (g_iSkipCount > 0)
	{
		gpu_power = 0;
		gpu_loading = 0;
		gpu_block= 0;
		gpu_idle = 0;
		g_iSkipCount -= 1;
	}
	else
	{
		g_ulPreCalResetTS_us = g_ulCalResetTS_us;
		g_ulCalResetTS_us = t;
		bError=ged_dvfs_cal_gpu_utilization(&gpu_loading, &gpu_block, &gpu_idle);

#ifdef GED_DVFS_UM_CAL        
		if(GED_DVFS_FALLBACK==phase) // timer-based DVFS use only
#endif             
		{

			if (ged_dvfs_policy(gpu_loading, &g_ui32FreqIDFromPolicy, t, phase, ul3DFenceDoneTime, false))
			{
				g_computed_freq_id = g_ui32FreqIDFromPolicy;
				ged_dvfs_gpu_freq_commit(g_ui32FreqIDFromPolicy, GED_DVFS_DEFAULT_COMMIT);
			}

		}

	}

	if(gpu_debug_enable)
	{
#ifdef GED_DVFS_ENABLE	
		GED_LOGE("%s:gpu_loading=%d %d, g_iSkipCount=%d",__func__, gpu_loading, mt_gpufreq_get_cur_freq_index(), g_iSkipCount);
#endif        
	}

EXIT_ged_dvfs_run:
	mutex_unlock(&gsDVFSLock);
}