diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 100 | 
1 files changed, 66 insertions, 34 deletions
| diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 30a1e3ac21d6..94e2fd758e01 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -1147,7 +1147,7 @@ static int amdgpu_pmops_suspend(struct device *dev)  {  	struct drm_device *drm_dev = dev_get_drvdata(dev); -	return amdgpu_device_suspend(drm_dev, true, true); +	return amdgpu_device_suspend(drm_dev, true);  }  static int amdgpu_pmops_resume(struct device *dev) @@ -1155,13 +1155,14 @@ static int amdgpu_pmops_resume(struct device *dev)  	struct drm_device *drm_dev = dev_get_drvdata(dev);  	/* GPU comes up enabled by the bios on resume */ -	if (amdgpu_device_is_px(drm_dev)) { +	if (amdgpu_device_supports_boco(drm_dev) || +	    amdgpu_device_supports_baco(drm_dev)) {  		pm_runtime_disable(dev);  		pm_runtime_set_active(dev);  		pm_runtime_enable(dev);  	} -	return amdgpu_device_resume(drm_dev, true, true); +	return amdgpu_device_resume(drm_dev, true);  }  static int amdgpu_pmops_freeze(struct device *dev) @@ -1170,7 +1171,7 @@ static int amdgpu_pmops_freeze(struct device *dev)  	struct amdgpu_device *adev = drm_dev->dev_private;  	int r; -	r = amdgpu_device_suspend(drm_dev, false, true); +	r = amdgpu_device_suspend(drm_dev, true);  	if (r)  		return r;  	return amdgpu_asic_reset(adev); @@ -1180,46 +1181,66 @@ static int amdgpu_pmops_thaw(struct device *dev)  {  	struct drm_device *drm_dev = dev_get_drvdata(dev); -	return amdgpu_device_resume(drm_dev, false, true); +	return amdgpu_device_resume(drm_dev, true);  }  static int amdgpu_pmops_poweroff(struct device *dev)  {  	struct drm_device *drm_dev = dev_get_drvdata(dev); -	return amdgpu_device_suspend(drm_dev, true, true); +	return amdgpu_device_suspend(drm_dev, true);  }  static int amdgpu_pmops_restore(struct device *dev)  {  	struct drm_device *drm_dev = dev_get_drvdata(dev); -	return amdgpu_device_resume(drm_dev, false, true); +	return amdgpu_device_resume(drm_dev, true);  }  static int amdgpu_pmops_runtime_suspend(struct device *dev)  {  	struct pci_dev *pdev = to_pci_dev(dev);  	struct drm_device *drm_dev = pci_get_drvdata(pdev); -	int ret; +	struct amdgpu_device *adev = drm_dev->dev_private; +	int ret, i; -	if (!amdgpu_device_is_px(drm_dev)) { +	if (!adev->runpm) {  		pm_runtime_forbid(dev);  		return -EBUSY;  	} -	drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; +	/* wait for all rings to drain before suspending */ +	for (i = 0; i < AMDGPU_MAX_RINGS; i++) { +		struct amdgpu_ring *ring = adev->rings[i]; +		if (ring && ring->sched.ready) { +			ret = amdgpu_fence_wait_empty(ring); +			if (ret) +				return -EBUSY; +		} +	} + +	if (amdgpu_device_supports_boco(drm_dev)) +		drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;  	drm_kms_helper_poll_disable(drm_dev); -	ret = amdgpu_device_suspend(drm_dev, false, false); -	pci_save_state(pdev); -	pci_disable_device(pdev); -	pci_ignore_hotplug(pdev); -	if (amdgpu_is_atpx_hybrid()) -		pci_set_power_state(pdev, PCI_D3cold); -	else if (!amdgpu_has_atpx_dgpu_power_cntl()) -		pci_set_power_state(pdev, PCI_D3hot); -	drm_dev->switch_power_state = DRM_SWITCH_POWER_DYNAMIC_OFF; +	ret = amdgpu_device_suspend(drm_dev, false); +	if (amdgpu_device_supports_boco(drm_dev)) { +		/* Only need to handle PCI state in the driver for ATPX +		 * PCI core handles it for _PR3. +		 */ +		if (amdgpu_is_atpx_hybrid()) { +			pci_ignore_hotplug(pdev); +		} else { +			pci_save_state(pdev); +			pci_disable_device(pdev); +			pci_ignore_hotplug(pdev); +			pci_set_power_state(pdev, PCI_D3cold); +		} +		drm_dev->switch_power_state = DRM_SWITCH_POWER_DYNAMIC_OFF; +	} else if (amdgpu_device_supports_baco(drm_dev)) { +		amdgpu_device_baco_enter(drm_dev); +	}  	return 0;  } @@ -1228,34 +1249,45 @@ static int amdgpu_pmops_runtime_resume(struct device *dev)  {  	struct pci_dev *pdev = to_pci_dev(dev);  	struct drm_device *drm_dev = pci_get_drvdata(pdev); +	struct amdgpu_device *adev = drm_dev->dev_private;  	int ret; -	if (!amdgpu_device_is_px(drm_dev)) +	if (!adev->runpm)  		return -EINVAL; -	drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; - -	if (amdgpu_is_atpx_hybrid() || -	    !amdgpu_has_atpx_dgpu_power_cntl()) -		pci_set_power_state(pdev, PCI_D0); -	pci_restore_state(pdev); -	ret = pci_enable_device(pdev); -	if (ret) -		return ret; -	pci_set_master(pdev); - -	ret = amdgpu_device_resume(drm_dev, false, false); +	if (amdgpu_device_supports_boco(drm_dev)) { +		drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; + +		/* Only need to handle PCI state in the driver for ATPX +		 * PCI core handles it for _PR3. +		 */ +		if (amdgpu_is_atpx_hybrid()) { +			pci_set_master(pdev); +		} else { +			pci_set_power_state(pdev, PCI_D0); +			pci_restore_state(pdev); +			ret = pci_enable_device(pdev); +			if (ret) +				return ret; +			pci_set_master(pdev); +		} +	} else if (amdgpu_device_supports_baco(drm_dev)) { +		amdgpu_device_baco_exit(drm_dev); +	} +	ret = amdgpu_device_resume(drm_dev, false);  	drm_kms_helper_poll_enable(drm_dev); -	drm_dev->switch_power_state = DRM_SWITCH_POWER_ON; +	if (amdgpu_device_supports_boco(drm_dev)) +		drm_dev->switch_power_state = DRM_SWITCH_POWER_ON;  	return 0;  }  static int amdgpu_pmops_runtime_idle(struct device *dev)  {  	struct drm_device *drm_dev = dev_get_drvdata(dev); +	struct amdgpu_device *adev = drm_dev->dev_private;  	struct drm_crtc *crtc; -	if (!amdgpu_device_is_px(drm_dev)) { +	if (!adev->runpm) {  		pm_runtime_forbid(dev);  		return -EBUSY;  	} |