diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 86 | 
1 files changed, 74 insertions, 12 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index ad95de6399af..c610e2794c18 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -31,7 +31,6 @@  #include "amdgpu_drv.h"  #include <drm/drm_pciids.h> -#include <linux/console.h>  #include <linux/module.h>  #include <linux/pm_runtime.h>  #include <linux/vga_switcheroo.h> @@ -39,6 +38,7 @@  #include <linux/mmu_notifier.h>  #include <linux/suspend.h>  #include <linux/cc_platform.h> +#include <linux/fb.h>  #include "amdgpu.h"  #include "amdgpu_irq.h" @@ -314,9 +314,12 @@ module_param_named(dpm, amdgpu_dpm, int, 0444);  /**   * DOC: fw_load_type (int) - * Set different firmware loading type for debugging (0 = direct, 1 = SMU, 2 = PSP). The default is -1 (auto). + * Set different firmware loading type for debugging, if supported. + * Set to 0 to force direct loading if supported by the ASIC.  Set + * to -1 to select the default loading mode for the ASIC, as defined + * by the driver.  The default is -1 (auto).   */ -MODULE_PARM_DESC(fw_load_type, "firmware loading type (0 = direct, 1 = SMU, 2 = PSP, -1 = auto)"); +MODULE_PARM_DESC(fw_load_type, "firmware loading type (0 = force direct if supported, -1 = auto)");  module_param_named(fw_load_type, amdgpu_fw_load_type, int, 0444);  /** @@ -328,10 +331,11 @@ module_param_named(aspm, amdgpu_aspm, int, 0444);  /**   * DOC: runpm (int) - * Override for runtime power management control for dGPUs in PX/HG laptops. The amdgpu driver can dynamically power down - * the dGPU on PX/HG laptops when it is idle. The default is -1 (auto enable). Setting the value to 0 disables this functionality. + * Override for runtime power management control for dGPUs. The amdgpu driver can dynamically power down + * the dGPUs when they are idle if supported. The default is -1 (auto enable). + * Setting the value to 0 disables this functionality.   */ -MODULE_PARM_DESC(runpm, "PX runtime pm (2 = force enable with BAMACO, 1 = force enable with BACO, 0 = disable, -1 = PX only default)"); +MODULE_PARM_DESC(runpm, "PX runtime pm (2 = force enable with BAMACO, 1 = force enable with BACO, 0 = disable, -1 = auto)");  module_param_named(runpm, amdgpu_runtime_pm, int, 0444);  /** @@ -1889,6 +1893,26 @@ MODULE_DEVICE_TABLE(pci, pciidlist);  static const struct drm_driver amdgpu_kms_driver; +static bool amdgpu_is_fw_framebuffer(resource_size_t base, +				     resource_size_t size) +{ +	bool found = false; +#if IS_REACHABLE(CONFIG_FB) +	struct apertures_struct *a; + +	a = alloc_apertures(1); +	if (!a) +		return false; + +	a->ranges[0].base = base; +	a->ranges[0].size = size; + +	found = is_firmware_framebuffer(a); +	kfree(a); +#endif +	return found; +} +  static int amdgpu_pci_probe(struct pci_dev *pdev,  			    const struct pci_device_id *ent)  { @@ -1897,6 +1921,8 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,  	unsigned long flags = ent->driver_data;  	int ret, retry = 0, i;  	bool supports_atomic = false; +	bool is_fw_fb; +	resource_size_t base, size;  	/* skip devices which are owned by radeon */  	for (i = 0; i < ARRAY_SIZE(amdgpu_unsupported_pciidlist); i++) { @@ -1965,6 +1991,10 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,  	}  #endif +	base = pci_resource_start(pdev, 0); +	size = pci_resource_len(pdev, 0); +	is_fw_fb = amdgpu_is_fw_framebuffer(base, size); +  	/* Get rid of things like offb */  	ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, &amdgpu_kms_driver);  	if (ret) @@ -1977,6 +2007,7 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,  	adev->dev  = &pdev->dev;  	adev->pdev = pdev;  	ddev = adev_to_drm(adev); +	adev->is_fw_fb = is_fw_fb;  	if (!supports_atomic)  		ddev->driver_features &= ~DRIVER_ATOMIC; @@ -2002,6 +2033,19 @@ retry_init:  		goto err_pci;  	} +	/* +	 * 1. don't init fbdev on hw without DCE +	 * 2. don't init fbdev if there are no connectors +	 */ +	if (adev->mode_info.mode_config_initialized && +	    !list_empty(&adev_to_drm(adev)->mode_config.connector_list)) { +		/* select 8 bpp console on low vram cards */ +		if (adev->gmc.real_vram_size <= (32*1024*1024)) +			drm_fbdev_generic_setup(adev_to_drm(adev), 8); +		else +			drm_fbdev_generic_setup(adev_to_drm(adev), 32); +	} +  	ret = amdgpu_debugfs_init(adev);  	if (ret)  		DRM_ERROR("Creating debugfs files failed (%d).\n", ret); @@ -2150,10 +2194,13 @@ static int amdgpu_pmops_suspend(struct device *dev)  	if (amdgpu_acpi_is_s0ix_active(adev))  		adev->in_s0ix = true; -	adev->in_s3 = true; +	else +		adev->in_s3 = true;  	r = amdgpu_device_suspend(drm_dev, true); -	adev->in_s3 = false; - +	if (r) +		return r; +	if (!adev->in_s0ix) +		r = amdgpu_asic_reset(adev);  	return r;  } @@ -2170,6 +2217,8 @@ static int amdgpu_pmops_resume(struct device *dev)  	r = amdgpu_device_resume(drm_dev, true);  	if (amdgpu_acpi_is_s0ix_active(adev))  		adev->in_s0ix = false; +	else +		adev->in_s3 = false;  	return r;  } @@ -2234,12 +2283,27 @@ static int amdgpu_pmops_runtime_suspend(struct device *dev)  	if (amdgpu_device_supports_px(drm_dev))  		drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; +	/* +	 * By setting mp1_state as PP_MP1_STATE_UNLOAD, MP1 will do some +	 * proper cleanups and put itself into a state ready for PNP. That +	 * can address some random resuming failure observed on BOCO capable +	 * platforms. +	 * TODO: this may be also needed for PX capable platform. +	 */ +	if (amdgpu_device_supports_boco(drm_dev)) +		adev->mp1_state = PP_MP1_STATE_UNLOAD; +  	ret = amdgpu_device_suspend(drm_dev, false);  	if (ret) {  		adev->in_runpm = false; +		if (amdgpu_device_supports_boco(drm_dev)) +			adev->mp1_state = PP_MP1_STATE_NONE;  		return ret;  	} +	if (amdgpu_device_supports_boco(drm_dev)) +		adev->mp1_state = PP_MP1_STATE_NONE; +  	if (amdgpu_device_supports_px(drm_dev)) {  		/* Only need to handle PCI state in the driver for ATPX  		 * PCI core handles it for _PR3. @@ -2516,10 +2580,8 @@ static int __init amdgpu_init(void)  {  	int r; -	if (vgacon_text_force()) { -		DRM_ERROR("VGACON disables amdgpu kernel modesetting.\n"); +	if (drm_firmware_drivers_only())  		return -EINVAL; -	}  	r = amdgpu_sync_init();  	if (r)  |