drm/radeon: add runtime PM support (v2)
This hooks radeon up to the runtime PM system to enable dynamic power management for secondary GPUs in switchable and powerxpress laptops. v2: agd5f: clean up, add module parameter Signed-off-by: Dave Airlie <airlied@redhat.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
committed by
Alex Deucher
parent
7473e830c4
commit
10ebc0bc09
@@ -101,6 +101,12 @@ static const char radeon_family_name[][16] = {
|
||||
"LAST",
|
||||
};
|
||||
|
||||
#if defined(CONFIG_VGA_SWITCHEROO)
|
||||
bool radeon_is_px(void);
|
||||
#else
|
||||
static inline bool radeon_is_px(void) { return false; }
|
||||
#endif
|
||||
|
||||
/**
|
||||
* radeon_program_register_sequence - program an array of registers.
|
||||
*
|
||||
@@ -1076,6 +1082,10 @@ static bool radeon_switcheroo_quirk_long_wakeup(struct pci_dev *pdev)
|
||||
static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state)
|
||||
{
|
||||
struct drm_device *dev = pci_get_drvdata(pdev);
|
||||
|
||||
if (radeon_is_px() && state == VGA_SWITCHEROO_OFF)
|
||||
return;
|
||||
|
||||
if (state == VGA_SWITCHEROO_ON) {
|
||||
unsigned d3_delay = dev->pdev->d3_delay;
|
||||
|
||||
@@ -1086,7 +1096,7 @@ static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switchero
|
||||
if (d3_delay < 20 && radeon_switcheroo_quirk_long_wakeup(pdev))
|
||||
dev->pdev->d3_delay = 20;
|
||||
|
||||
radeon_resume_kms(dev, 1);
|
||||
radeon_resume_kms(dev, true, true);
|
||||
|
||||
dev->pdev->d3_delay = d3_delay;
|
||||
|
||||
@@ -1096,7 +1106,7 @@ static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switchero
|
||||
printk(KERN_INFO "radeon: switched off\n");
|
||||
drm_kms_helper_poll_disable(dev);
|
||||
dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
|
||||
radeon_suspend_kms(dev, 1);
|
||||
radeon_suspend_kms(dev, true, true);
|
||||
dev->switch_power_state = DRM_SWITCH_POWER_OFF;
|
||||
}
|
||||
}
|
||||
@@ -1146,6 +1156,7 @@ int radeon_device_init(struct radeon_device *rdev,
|
||||
{
|
||||
int r, i;
|
||||
int dma_bits;
|
||||
bool runtime = false;
|
||||
|
||||
rdev->shutdown = false;
|
||||
rdev->dev = &pdev->dev;
|
||||
@@ -1292,7 +1303,14 @@ int radeon_device_init(struct radeon_device *rdev,
|
||||
/* this will fail for cards that aren't VGA class devices, just
|
||||
* ignore it */
|
||||
vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode);
|
||||
vga_switcheroo_register_client(rdev->pdev, &radeon_switcheroo_ops, false);
|
||||
|
||||
if (radeon_runtime_pm == 1)
|
||||
runtime = true;
|
||||
if ((radeon_runtime_pm == -1) && radeon_is_px())
|
||||
runtime = true;
|
||||
vga_switcheroo_register_client(rdev->pdev, &radeon_switcheroo_ops, runtime);
|
||||
if (runtime)
|
||||
vga_switcheroo_init_domain_pm_ops(rdev->dev, &rdev->vga_pm_domain);
|
||||
|
||||
r = radeon_init(rdev);
|
||||
if (r)
|
||||
@@ -1382,7 +1400,7 @@ void radeon_device_fini(struct radeon_device *rdev)
|
||||
* Returns 0 for success or an error on failure.
|
||||
* Called at driver suspend.
|
||||
*/
|
||||
int radeon_suspend_kms(struct drm_device *dev, bool suspend)
|
||||
int radeon_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon)
|
||||
{
|
||||
struct radeon_device *rdev;
|
||||
struct drm_crtc *crtc;
|
||||
@@ -1457,9 +1475,12 @@ int radeon_suspend_kms(struct drm_device *dev, bool suspend)
|
||||
pci_disable_device(dev->pdev);
|
||||
pci_set_power_state(dev->pdev, PCI_D3hot);
|
||||
}
|
||||
console_lock();
|
||||
radeon_fbdev_set_suspend(rdev, 1);
|
||||
console_unlock();
|
||||
|
||||
if (fbcon) {
|
||||
console_lock();
|
||||
radeon_fbdev_set_suspend(rdev, 1);
|
||||
console_unlock();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1472,7 +1493,7 @@ int radeon_suspend_kms(struct drm_device *dev, bool suspend)
|
||||
* Returns 0 for success or an error on failure.
|
||||
* Called at driver resume.
|
||||
*/
|
||||
int radeon_resume_kms(struct drm_device *dev, bool resume)
|
||||
int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon)
|
||||
{
|
||||
struct drm_connector *connector;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
@@ -1481,12 +1502,15 @@ int radeon_resume_kms(struct drm_device *dev, bool resume)
|
||||
if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
|
||||
return 0;
|
||||
|
||||
console_lock();
|
||||
if (fbcon) {
|
||||
console_lock();
|
||||
}
|
||||
if (resume) {
|
||||
pci_set_power_state(dev->pdev, PCI_D0);
|
||||
pci_restore_state(dev->pdev);
|
||||
if (pci_enable_device(dev->pdev)) {
|
||||
console_unlock();
|
||||
if (fbcon)
|
||||
console_unlock();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -1501,9 +1525,11 @@ int radeon_resume_kms(struct drm_device *dev, bool resume)
|
||||
radeon_pm_resume(rdev);
|
||||
radeon_restore_bios_scratch_regs(rdev);
|
||||
|
||||
radeon_fbdev_set_suspend(rdev, 0);
|
||||
console_unlock();
|
||||
|
||||
if (fbcon) {
|
||||
radeon_fbdev_set_suspend(rdev, 0);
|
||||
console_unlock();
|
||||
}
|
||||
|
||||
/* init dig PHYs, disp eng pll */
|
||||
if (rdev->is_atom_bios) {
|
||||
radeon_atom_encoder_init(rdev);
|
||||
|
||||
Reference in New Issue
Block a user