diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c | 34 | 
1 files changed, 30 insertions, 4 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c index 474bfe36c0c2..aa78c2ee9e21 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c @@ -322,6 +322,26 @@ static int vpe_early_init(struct amdgpu_ip_block *ip_block)  	return 0;  } +static bool vpe_need_dpm0_at_power_down(struct amdgpu_device *adev) +{ +	switch (amdgpu_ip_version(adev, VPE_HWIP, 0)) { +	case IP_VERSION(6, 1, 1): +		return adev->pm.fw_version < 0x0a640500; +	default: +		return false; +	} +} + +static int vpe_get_dpm_level(struct amdgpu_device *adev) +{ +	struct amdgpu_vpe *vpe = &adev->vpe; + +	if (!adev->pm.dpm_enabled) +		return 0; + +	return RREG32(vpe_get_reg_offset(vpe, 0, vpe->regs.dpm_request_lv)); +} +  static void vpe_idle_work_handler(struct work_struct *work)  {  	struct amdgpu_device *adev = @@ -329,11 +349,17 @@ static void vpe_idle_work_handler(struct work_struct *work)  	unsigned int fences = 0;  	fences += amdgpu_fence_count_emitted(&adev->vpe.ring); +	if (fences) +		goto reschedule; -	if (fences == 0) -		amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VPE, AMD_PG_STATE_GATE); -	else -		schedule_delayed_work(&adev->vpe.idle_work, VPE_IDLE_TIMEOUT); +	if (vpe_need_dpm0_at_power_down(adev) && vpe_get_dpm_level(adev) != 0) +		goto reschedule; + +	amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VPE, AMD_PG_STATE_GATE); +	return; + +reschedule: +	schedule_delayed_work(&adev->vpe.idle_work, VPE_IDLE_TIMEOUT);  }  static int vpe_common_init(struct amdgpu_vpe *vpe)  | 
