diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_drv.c')
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_drv.c | 194 | 
1 files changed, 168 insertions, 26 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index cb4445f55a9..e9e36108424 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -36,8 +36,9 @@  #include <drm/drm_pciids.h>  #include <linux/console.h>  #include <linux/module.h> - - +#include <linux/pm_runtime.h> +#include <linux/vga_switcheroo.h> +#include "drm_crtc_helper.h"  /*   * KMS wrapper.   * - 2.0.0 - initial interface @@ -75,9 +76,15 @@   *   2.32.0 - new info request for rings working   *   2.33.0 - Add SI tiling mode array query   *   2.34.0 - Add CIK tiling mode array query + *   2.35.0 - Add CIK macrotile mode array query + *   2.36.0 - Fix CIK DCE tiling setup + *   2.37.0 - allow GS ring setup on r6xx/r7xx + *   2.38.0 - RADEON_GEM_OP (GET_INITIAL_DOMAIN, SET_INITIAL_DOMAIN), + *            CIK: 1D and linear tiling modes contain valid PIPE_CONFIG + *   2.39.0 - Add INFO query for number of active CUs   */  #define KMS_DRIVER_MAJOR	2 -#define KMS_DRIVER_MINOR	34 +#define KMS_DRIVER_MINOR	39  #define KMS_DRIVER_PATCHLEVEL	0  int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);  int radeon_driver_unload_kms(struct drm_device *dev); @@ -87,8 +94,8 @@ void radeon_driver_postclose_kms(struct drm_device *dev,  				 struct drm_file *file_priv);  void radeon_driver_preclose_kms(struct drm_device *dev,  				struct drm_file *file_priv); -int radeon_suspend_kms(struct drm_device *dev, pm_message_t state); -int radeon_resume_kms(struct drm_device *dev); +int radeon_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon); +int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon);  u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc);  int radeon_enable_vblank_kms(struct drm_device *dev, int crtc);  void radeon_disable_vblank_kms(struct drm_device *dev, int crtc); @@ -99,15 +106,17 @@ int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc,  void radeon_driver_irq_preinstall_kms(struct drm_device *dev);  int radeon_driver_irq_postinstall_kms(struct drm_device *dev);  void radeon_driver_irq_uninstall_kms(struct drm_device *dev); -irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS); -int radeon_gem_object_init(struct drm_gem_object *obj); +irqreturn_t radeon_driver_irq_handler_kms(int irq, void *arg);  void radeon_gem_object_free(struct drm_gem_object *obj);  int radeon_gem_object_open(struct drm_gem_object *obj,  				struct drm_file *file_priv);  void radeon_gem_object_close(struct drm_gem_object *obj,  				struct drm_file *file_priv);  extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, -				      int *vpos, int *hpos); +				      unsigned int flags, +				      int *vpos, int *hpos, ktime_t *stime, +				      ktime_t *etime); +extern bool radeon_is_px(struct drm_device *dev);  extern const struct drm_ioctl_desc radeon_ioctls_kms[];  extern int radeon_max_kms_ioctl;  int radeon_mmap(struct file *filp, struct vm_area_struct *vma); @@ -153,7 +162,7 @@ int radeon_benchmarking = 0;  int radeon_testing = 0;  int radeon_connector_table = 0;  int radeon_tv = 1; -int radeon_audio = 0; +int radeon_audio = -1;  int radeon_disp_priority = 0;  int radeon_hw_i2c = 0;  int radeon_pcie_gen2 = -1; @@ -162,6 +171,11 @@ int radeon_lockup_timeout = 10000;  int radeon_fastfb = 0;  int radeon_dpm = -1;  int radeon_aspm = -1; +int radeon_runtime_pm = -1; +int radeon_hard_reset = 0; +int radeon_vm_size = 4; +int radeon_vm_block_size = 9; +int radeon_deep_color = 0;  MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers");  module_param_named(no_wb, radeon_no_wb, int, 0444); @@ -175,7 +189,7 @@ module_param_named(dynclks, radeon_dynclks, int, 0444);  MODULE_PARM_DESC(r4xx_atom, "Enable ATOMBIOS modesetting for R4xx");  module_param_named(r4xx_atom, radeon_r4xx_atom, int, 0444); -MODULE_PARM_DESC(vramlimit, "Restrict VRAM for testing"); +MODULE_PARM_DESC(vramlimit, "Restrict VRAM for testing, in megabytes");  module_param_named(vramlimit, radeon_vram_limit, int, 0600);  MODULE_PARM_DESC(agpmode, "AGP Mode (-1 == PCI)"); @@ -196,7 +210,7 @@ module_param_named(connector_table, radeon_connector_table, int, 0444);  MODULE_PARM_DESC(tv, "TV enable (0 = disable)");  module_param_named(tv, radeon_tv, int, 0444); -MODULE_PARM_DESC(audio, "Audio enable (1 = enable)"); +MODULE_PARM_DESC(audio, "Audio enable (-1 = auto, 0 = disable, 1 = enable)");  module_param_named(audio, radeon_audio, int, 0444);  MODULE_PARM_DESC(disp_priority, "Display Priority (0 = auto, 1 = normal, 2 = high)"); @@ -223,6 +237,21 @@ module_param_named(dpm, radeon_dpm, int, 0444);  MODULE_PARM_DESC(aspm, "ASPM support (1 = enable, 0 = disable, -1 = auto)");  module_param_named(aspm, radeon_aspm, int, 0444); +MODULE_PARM_DESC(runpm, "PX runtime pm (1 = force enable, 0 = disable, -1 = PX only default)"); +module_param_named(runpm, radeon_runtime_pm, int, 0444); + +MODULE_PARM_DESC(hard_reset, "PCI config reset (1 = force enable, 0 = disable (default))"); +module_param_named(hard_reset, radeon_hard_reset, int, 0444); + +MODULE_PARM_DESC(vm_size, "VM address space size in gigabytes (default 4GB)"); +module_param_named(vm_size, radeon_vm_size, int, 0444); + +MODULE_PARM_DESC(vm_block_size, "VM page table size in bits (default 9)"); +module_param_named(vm_block_size, radeon_vm_block_size, int, 0444); + +MODULE_PARM_DESC(deep_color, "Deep Color support (1 = enable, 0 = disable (default))"); +module_param_named(deep_color, radeon_deep_color, int, 0444); +  static struct pci_device_id pciidlist[] = {  	radeon_PCI_IDS  }; @@ -259,6 +288,7 @@ static int radeon_resume(struct drm_device *dev)  	return 0;  } +  static const struct file_operations radeon_driver_old_fops = {  	.owner = THIS_MODULE,  	.open = drm_open, @@ -353,25 +383,142 @@ radeon_pci_remove(struct pci_dev *pdev)  	drm_put_dev(dev);  } -static int -radeon_pci_suspend(struct pci_dev *pdev, pm_message_t state) +static int radeon_pmops_suspend(struct device *dev)  { -	struct drm_device *dev = pci_get_drvdata(pdev); -	return radeon_suspend_kms(dev, state); +	struct pci_dev *pdev = to_pci_dev(dev); +	struct drm_device *drm_dev = pci_get_drvdata(pdev); +	return radeon_suspend_kms(drm_dev, true, true);  } -static int -radeon_pci_resume(struct pci_dev *pdev) +static int radeon_pmops_resume(struct device *dev)  { -	struct drm_device *dev = pci_get_drvdata(pdev); -	return radeon_resume_kms(dev); +	struct pci_dev *pdev = to_pci_dev(dev); +	struct drm_device *drm_dev = pci_get_drvdata(pdev); +	return radeon_resume_kms(drm_dev, true, true); +} + +static int radeon_pmops_freeze(struct device *dev) +{ +	struct pci_dev *pdev = to_pci_dev(dev); +	struct drm_device *drm_dev = pci_get_drvdata(pdev); +	return radeon_suspend_kms(drm_dev, false, true); +} + +static int radeon_pmops_thaw(struct device *dev) +{ +	struct pci_dev *pdev = to_pci_dev(dev); +	struct drm_device *drm_dev = pci_get_drvdata(pdev); +	return radeon_resume_kms(drm_dev, false, true); +} + +static int radeon_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; + +	if (!radeon_is_px(drm_dev)) { +		pm_runtime_forbid(dev); +		return -EBUSY; +	} + +	drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; +	drm_kms_helper_poll_disable(drm_dev); +	vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_OFF); + +	ret = radeon_suspend_kms(drm_dev, false, false); +	pci_save_state(pdev); +	pci_disable_device(pdev); +	pci_set_power_state(pdev, PCI_D3cold); +	drm_dev->switch_power_state = DRM_SWITCH_POWER_DYNAMIC_OFF; + +	return 0; +} + +static int radeon_pmops_runtime_resume(struct device *dev) +{ +	struct pci_dev *pdev = to_pci_dev(dev); +	struct drm_device *drm_dev = pci_get_drvdata(pdev); +	int ret; + +	if (!radeon_is_px(drm_dev)) +		return -EINVAL; + +	drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; + +	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 = radeon_resume_kms(drm_dev, false, false); +	drm_kms_helper_poll_enable(drm_dev); +	vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_ON); +	drm_dev->switch_power_state = DRM_SWITCH_POWER_ON; +	return 0;  } +static int radeon_pmops_runtime_idle(struct device *dev) +{ +	struct pci_dev *pdev = to_pci_dev(dev); +	struct drm_device *drm_dev = pci_get_drvdata(pdev); +	struct drm_crtc *crtc; + +	if (!radeon_is_px(drm_dev)) { +		pm_runtime_forbid(dev); +		return -EBUSY; +	} + +	list_for_each_entry(crtc, &drm_dev->mode_config.crtc_list, head) { +		if (crtc->enabled) { +			DRM_DEBUG_DRIVER("failing to power off - crtc active\n"); +			return -EBUSY; +		} +	} + +	pm_runtime_mark_last_busy(dev); +	pm_runtime_autosuspend(dev); +	/* we don't want the main rpm_idle to call suspend - we want to autosuspend */ +	return 1; +} + +long radeon_drm_ioctl(struct file *filp, +		      unsigned int cmd, unsigned long arg) +{ +	struct drm_file *file_priv = filp->private_data; +	struct drm_device *dev; +	long ret; +	dev = file_priv->minor->dev; +	ret = pm_runtime_get_sync(dev->dev); +	if (ret < 0) +		return ret; + +	ret = drm_ioctl(filp, cmd, arg); +	 +	pm_runtime_mark_last_busy(dev->dev); +	pm_runtime_put_autosuspend(dev->dev); +	return ret; +} + +static const struct dev_pm_ops radeon_pm_ops = { +	.suspend = radeon_pmops_suspend, +	.resume = radeon_pmops_resume, +	.freeze = radeon_pmops_freeze, +	.thaw = radeon_pmops_thaw, +	.poweroff = radeon_pmops_freeze, +	.restore = radeon_pmops_resume, +	.runtime_suspend = radeon_pmops_runtime_suspend, +	.runtime_resume = radeon_pmops_runtime_resume, +	.runtime_idle = radeon_pmops_runtime_idle, +}; +  static const struct file_operations radeon_driver_kms_fops = {  	.owner = THIS_MODULE,  	.open = drm_open,  	.release = drm_release, -	.unlocked_ioctl = drm_ioctl, +	.unlocked_ioctl = radeon_drm_ioctl,  	.mmap = radeon_mmap,  	.poll = drm_poll,  	.read = drm_read, @@ -385,15 +532,12 @@ static struct drm_driver kms_driver = {  	    DRIVER_USE_AGP |  	    DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM |  	    DRIVER_PRIME | DRIVER_RENDER, -	.dev_priv_size = 0,  	.load = radeon_driver_load_kms,  	.open = radeon_driver_open_kms,  	.preclose = radeon_driver_preclose_kms,  	.postclose = radeon_driver_postclose_kms,  	.lastclose = radeon_driver_lastclose_kms,  	.unload = radeon_driver_unload_kms, -	.suspend = radeon_suspend_kms, -	.resume = radeon_resume_kms,  	.get_vblank_counter = radeon_get_vblank_counter_kms,  	.enable_vblank = radeon_enable_vblank_kms,  	.disable_vblank = radeon_disable_vblank_kms, @@ -408,7 +552,6 @@ static struct drm_driver kms_driver = {  	.irq_uninstall = radeon_driver_irq_uninstall_kms,  	.irq_handler = radeon_driver_irq_handler_kms,  	.ioctls = radeon_ioctls_kms, -	.gem_init_object = radeon_gem_object_init,  	.gem_free_object = radeon_gem_object_free,  	.gem_open_object = radeon_gem_object_open,  	.gem_close_object = radeon_gem_object_close, @@ -451,8 +594,7 @@ static struct pci_driver radeon_kms_pci_driver = {  	.id_table = pciidlist,  	.probe = radeon_pci_probe,  	.remove = radeon_pci_remove, -	.suspend = radeon_pci_suspend, -	.resume = radeon_pci_resume, +	.driver.pm = &radeon_pm_ops,  };  static int __init radeon_init(void)  | 
