diff options
Diffstat (limited to 'drivers/gpu/drm/msm/msm_gpu_devfreq.c')
| -rw-r--r-- | drivers/gpu/drm/msm/msm_gpu_devfreq.c | 38 | 
1 files changed, 30 insertions, 8 deletions
diff --git a/drivers/gpu/drm/msm/msm_gpu_devfreq.c b/drivers/gpu/drm/msm/msm_gpu_devfreq.c index 20006d060b5b..8b7473f69cb8 100644 --- a/drivers/gpu/drm/msm/msm_gpu_devfreq.c +++ b/drivers/gpu/drm/msm/msm_gpu_devfreq.c @@ -88,8 +88,12 @@ static struct devfreq_dev_profile msm_devfreq_profile = {  	.get_cur_freq = msm_devfreq_get_cur_freq,  }; +static void msm_devfreq_idle_work(struct kthread_work *work); +  void msm_devfreq_init(struct msm_gpu *gpu)  { +	struct msm_gpu_devfreq *df = &gpu->devfreq; +  	/* We need target support to do devfreq */  	if (!gpu->funcs->gpu_busy)  		return; @@ -105,25 +109,27 @@ void msm_devfreq_init(struct msm_gpu *gpu)  	msm_devfreq_profile.freq_table = NULL;  	msm_devfreq_profile.max_state = 0; -	gpu->devfreq.devfreq = devm_devfreq_add_device(&gpu->pdev->dev, +	df->devfreq = devm_devfreq_add_device(&gpu->pdev->dev,  			&msm_devfreq_profile, DEVFREQ_GOV_SIMPLE_ONDEMAND,  			NULL); -	if (IS_ERR(gpu->devfreq.devfreq)) { +	if (IS_ERR(df->devfreq)) {  		DRM_DEV_ERROR(&gpu->pdev->dev, "Couldn't initialize GPU devfreq\n"); -		gpu->devfreq.devfreq = NULL; +		df->devfreq = NULL;  		return;  	} -	devfreq_suspend_device(gpu->devfreq.devfreq); +	devfreq_suspend_device(df->devfreq); -	gpu->cooling = of_devfreq_cooling_register(gpu->pdev->dev.of_node, -			gpu->devfreq.devfreq); +	gpu->cooling = of_devfreq_cooling_register(gpu->pdev->dev.of_node, df->devfreq);  	if (IS_ERR(gpu->cooling)) {  		DRM_DEV_ERROR(&gpu->pdev->dev,  				"Couldn't register GPU cooling device\n");  		gpu->cooling = NULL;  	} + +	msm_hrtimer_work_init(&df->idle_work, gpu->worker, msm_devfreq_idle_work, +			      CLOCK_MONOTONIC, HRTIMER_MODE_REL);  }  void msm_devfreq_cleanup(struct msm_gpu *gpu) @@ -155,6 +161,11 @@ void msm_devfreq_active(struct msm_gpu *gpu)  		return;  	/* +	 * Cancel any pending transition to idle frequency: +	 */ +	hrtimer_cancel(&df->idle_work.timer); + +	/*  	 * Hold devfreq lock to synchronize with get_dev_status()/  	 * target() callbacks  	 */ @@ -184,9 +195,12 @@ void msm_devfreq_active(struct msm_gpu *gpu)  	mutex_unlock(&df->devfreq->lock);  } -void msm_devfreq_idle(struct msm_gpu *gpu) + +static void msm_devfreq_idle_work(struct kthread_work *work)  { -	struct msm_gpu_devfreq *df = &gpu->devfreq; +	struct msm_gpu_devfreq *df = container_of(work, +			struct msm_gpu_devfreq, idle_work.work); +	struct msm_gpu *gpu = container_of(df, struct msm_gpu, devfreq);  	unsigned long idle_freq, target_freq = 0;  	if (!df->devfreq) @@ -208,3 +222,11 @@ void msm_devfreq_idle(struct msm_gpu *gpu)  	mutex_unlock(&df->devfreq->lock);  } + +void msm_devfreq_idle(struct msm_gpu *gpu) +{ +	struct msm_gpu_devfreq *df = &gpu->devfreq; + +	msm_hrtimer_queue_work(&df->idle_work, ms_to_ktime(1), +			       HRTIMER_MODE_ABS); +}  |