aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2012-09-17 00:40:31 -0400
committerAlex Deucher <alexander.deucher@amd.com>2013-11-01 12:43:14 -0400
commit10ebc0bc09344ab6310309169efc73dfe6c23d72 (patch)
tree9d93730a567190aa7b57d91999565273bc002dc0
parent7473e830c400b2ebf54937a4f075279f7713a2b7 (diff)
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>
-rw-r--r--drivers/gpu/drm/radeon/radeon.h8
-rw-r--r--drivers/gpu/drm/radeon/radeon_atpx_handler.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_connectors.c63
-rw-r--r--drivers/gpu/drm/radeon/radeon_device.c52
-rw-r--r--drivers/gpu/drm/radeon/radeon_display.c47
-rw-r--r--drivers/gpu/drm/radeon/radeon_drv.c122
-rw-r--r--drivers/gpu/drm/radeon/radeon_drv.h3
-rw-r--r--drivers/gpu/drm/radeon/radeon_ioc32.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_irq_kms.c8
-rw-r--r--drivers/gpu/drm/radeon/radeon_kms.c26
10 files changed, 299 insertions, 36 deletions
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 986100a6e5ca..ad54525cfa79 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -98,6 +98,7 @@ extern int radeon_lockup_timeout;
98extern int radeon_fastfb; 98extern int radeon_fastfb;
99extern int radeon_dpm; 99extern int radeon_dpm;
100extern int radeon_aspm; 100extern int radeon_aspm;
101extern int radeon_runtime_pm;
101 102
102/* 103/*
103 * Copy from radeon_drv.h so we don't have to include both and have conflicting 104 * Copy from radeon_drv.h so we don't have to include both and have conflicting
@@ -2212,6 +2213,9 @@ struct radeon_device {
2212 /* clock, powergating flags */ 2213 /* clock, powergating flags */
2213 u32 cg_flags; 2214 u32 cg_flags;
2214 u32 pg_flags; 2215 u32 pg_flags;
2216
2217 struct dev_pm_domain vga_pm_domain;
2218 bool have_disp_power_ref;
2215}; 2219};
2216 2220
2217int radeon_device_init(struct radeon_device *rdev, 2221int radeon_device_init(struct radeon_device *rdev,
@@ -2673,8 +2677,8 @@ extern void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain);
2673extern bool radeon_ttm_bo_is_radeon_bo(struct ttm_buffer_object *bo); 2677extern bool radeon_ttm_bo_is_radeon_bo(struct ttm_buffer_object *bo);
2674extern void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64 base); 2678extern void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64 base);
2675extern void radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc); 2679extern void radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc);
2676extern int radeon_resume_kms(struct drm_device *dev, bool resume); 2680extern int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon);
2677extern int radeon_suspend_kms(struct drm_device *dev, bool suspend); 2681extern int radeon_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon);
2678extern void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size); 2682extern void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size);
2679extern void radeon_program_register_sequence(struct radeon_device *rdev, 2683extern void radeon_program_register_sequence(struct radeon_device *rdev,
2680 const u32 *registers, 2684 const u32 *registers,
diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c
index d96070bf8388..6153ec18943a 100644
--- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c
+++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c
@@ -59,6 +59,10 @@ struct atpx_mux {
59 u16 mux; 59 u16 mux;
60} __packed; 60} __packed;
61 61
62bool radeon_is_px(void) {
63 return radeon_atpx_priv.atpx_detected;
64}
65
62/** 66/**
63 * radeon_atpx_call - call an ATPX method 67 * radeon_atpx_call - call an ATPX method
64 * 68 *
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index 43f7600803c3..5a74b173eb79 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -31,6 +31,8 @@
31#include "radeon.h" 31#include "radeon.h"
32#include "atom.h" 32#include "atom.h"
33 33
34#include <linux/pm_runtime.h>
35
34extern void 36extern void
35radeon_combios_connected_scratch_regs(struct drm_connector *connector, 37radeon_combios_connected_scratch_regs(struct drm_connector *connector,
36 struct drm_encoder *encoder, 38 struct drm_encoder *encoder,
@@ -641,6 +643,11 @@ radeon_lvds_detect(struct drm_connector *connector, bool force)
641 struct radeon_connector *radeon_connector = to_radeon_connector(connector); 643 struct radeon_connector *radeon_connector = to_radeon_connector(connector);
642 struct drm_encoder *encoder = radeon_best_single_encoder(connector); 644 struct drm_encoder *encoder = radeon_best_single_encoder(connector);
643 enum drm_connector_status ret = connector_status_disconnected; 645 enum drm_connector_status ret = connector_status_disconnected;
646 int r;
647
648 r = pm_runtime_get_sync(connector->dev->dev);
649 if (r < 0)
650 return connector_status_disconnected;
644 651
645 if (encoder) { 652 if (encoder) {
646 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 653 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
@@ -666,6 +673,8 @@ radeon_lvds_detect(struct drm_connector *connector, bool force)
666 /* check acpi lid status ??? */ 673 /* check acpi lid status ??? */
667 674
668 radeon_connector_update_scratch_regs(connector, ret); 675 radeon_connector_update_scratch_regs(connector, ret);
676 pm_runtime_mark_last_busy(connector->dev->dev);
677 pm_runtime_put_autosuspend(connector->dev->dev);
669 return ret; 678 return ret;
670} 679}
671 680
@@ -765,6 +774,11 @@ radeon_vga_detect(struct drm_connector *connector, bool force)
765 struct drm_encoder_helper_funcs *encoder_funcs; 774 struct drm_encoder_helper_funcs *encoder_funcs;
766 bool dret = false; 775 bool dret = false;
767 enum drm_connector_status ret = connector_status_disconnected; 776 enum drm_connector_status ret = connector_status_disconnected;
777 int r;
778
779 r = pm_runtime_get_sync(connector->dev->dev);
780 if (r < 0)
781 return connector_status_disconnected;
768 782
769 encoder = radeon_best_single_encoder(connector); 783 encoder = radeon_best_single_encoder(connector);
770 if (!encoder) 784 if (!encoder)
@@ -805,9 +819,8 @@ radeon_vga_detect(struct drm_connector *connector, bool force)
805 * detected a monitor via load. 819 * detected a monitor via load.
806 */ 820 */
807 if (radeon_connector->detected_by_load) 821 if (radeon_connector->detected_by_load)
808 return connector->status; 822 ret = connector->status;
809 else 823 goto out;
810 return ret;
811 } 824 }
812 825
813 if (radeon_connector->dac_load_detect && encoder) { 826 if (radeon_connector->dac_load_detect && encoder) {
@@ -832,6 +845,11 @@ radeon_vga_detect(struct drm_connector *connector, bool force)
832 } 845 }
833 846
834 radeon_connector_update_scratch_regs(connector, ret); 847 radeon_connector_update_scratch_regs(connector, ret);
848
849out:
850 pm_runtime_mark_last_busy(connector->dev->dev);
851 pm_runtime_put_autosuspend(connector->dev->dev);
852
835 return ret; 853 return ret;
836} 854}
837 855
@@ -888,10 +906,15 @@ radeon_tv_detect(struct drm_connector *connector, bool force)
888 struct drm_encoder_helper_funcs *encoder_funcs; 906 struct drm_encoder_helper_funcs *encoder_funcs;
889 struct radeon_connector *radeon_connector = to_radeon_connector(connector); 907 struct radeon_connector *radeon_connector = to_radeon_connector(connector);
890 enum drm_connector_status ret = connector_status_disconnected; 908 enum drm_connector_status ret = connector_status_disconnected;
909 int r;
891 910
892 if (!radeon_connector->dac_load_detect) 911 if (!radeon_connector->dac_load_detect)
893 return ret; 912 return ret;
894 913
914 r = pm_runtime_get_sync(connector->dev->dev);
915 if (r < 0)
916 return connector_status_disconnected;
917
895 encoder = radeon_best_single_encoder(connector); 918 encoder = radeon_best_single_encoder(connector);
896 if (!encoder) 919 if (!encoder)
897 ret = connector_status_disconnected; 920 ret = connector_status_disconnected;
@@ -902,6 +925,8 @@ radeon_tv_detect(struct drm_connector *connector, bool force)
902 if (ret == connector_status_connected) 925 if (ret == connector_status_connected)
903 ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, false); 926 ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, false);
904 radeon_connector_update_scratch_regs(connector, ret); 927 radeon_connector_update_scratch_regs(connector, ret);
928 pm_runtime_mark_last_busy(connector->dev->dev);
929 pm_runtime_put_autosuspend(connector->dev->dev);
905 return ret; 930 return ret;
906} 931}
907 932
@@ -969,12 +994,18 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
969 struct drm_encoder *encoder = NULL; 994 struct drm_encoder *encoder = NULL;
970 struct drm_encoder_helper_funcs *encoder_funcs; 995 struct drm_encoder_helper_funcs *encoder_funcs;
971 struct drm_mode_object *obj; 996 struct drm_mode_object *obj;
972 int i; 997 int i, r;
973 enum drm_connector_status ret = connector_status_disconnected; 998 enum drm_connector_status ret = connector_status_disconnected;
974 bool dret = false, broken_edid = false; 999 bool dret = false, broken_edid = false;
975 1000
976 if (!force && radeon_check_hpd_status_unchanged(connector)) 1001 r = pm_runtime_get_sync(connector->dev->dev);
977 return connector->status; 1002 if (r < 0)
1003 return connector_status_disconnected;
1004
1005 if (!force && radeon_check_hpd_status_unchanged(connector)) {
1006 ret = connector->status;
1007 goto exit;
1008 }
978 1009
979 if (radeon_connector->ddc_bus) 1010 if (radeon_connector->ddc_bus)
980 dret = radeon_ddc_probe(radeon_connector, false); 1011 dret = radeon_ddc_probe(radeon_connector, false);
@@ -1125,6 +1156,11 @@ out:
1125 1156
1126 /* updated in get modes as well since we need to know if it's analog or digital */ 1157 /* updated in get modes as well since we need to know if it's analog or digital */
1127 radeon_connector_update_scratch_regs(connector, ret); 1158 radeon_connector_update_scratch_regs(connector, ret);
1159
1160exit:
1161 pm_runtime_mark_last_busy(connector->dev->dev);
1162 pm_runtime_put_autosuspend(connector->dev->dev);
1163
1128 return ret; 1164 return ret;
1129} 1165}
1130 1166
@@ -1392,9 +1428,16 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
1392 enum drm_connector_status ret = connector_status_disconnected; 1428 enum drm_connector_status ret = connector_status_disconnected;
1393 struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv; 1429 struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv;
1394 struct drm_encoder *encoder = radeon_best_single_encoder(connector); 1430 struct drm_encoder *encoder = radeon_best_single_encoder(connector);
1431 int r;
1395 1432
1396 if (!force && radeon_check_hpd_status_unchanged(connector)) 1433 r = pm_runtime_get_sync(connector->dev->dev);
1397 return connector->status; 1434 if (r < 0)
1435 return connector_status_disconnected;
1436
1437 if (!force && radeon_check_hpd_status_unchanged(connector)) {
1438 ret = connector->status;
1439 goto out;
1440 }
1398 1441
1399 if (radeon_connector->edid) { 1442 if (radeon_connector->edid) {
1400 kfree(radeon_connector->edid); 1443 kfree(radeon_connector->edid);
@@ -1458,6 +1501,10 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
1458 } 1501 }
1459 1502
1460 radeon_connector_update_scratch_regs(connector, ret); 1503 radeon_connector_update_scratch_regs(connector, ret);
1504out:
1505 pm_runtime_mark_last_busy(connector->dev->dev);
1506 pm_runtime_put_autosuspend(connector->dev->dev);
1507
1461 return ret; 1508 return ret;
1462} 1509}
1463 1510
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index d08ae5be1598..b512c0098ee9 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -101,6 +101,12 @@ static const char radeon_family_name[][16] = {
101 "LAST", 101 "LAST",
102}; 102};
103 103
104#if defined(CONFIG_VGA_SWITCHEROO)
105bool radeon_is_px(void);
106#else
107static inline bool radeon_is_px(void) { return false; }
108#endif
109
104/** 110/**
105 * radeon_program_register_sequence - program an array of registers. 111 * radeon_program_register_sequence - program an array of registers.
106 * 112 *
@@ -1076,6 +1082,10 @@ static bool radeon_switcheroo_quirk_long_wakeup(struct pci_dev *pdev)
1076static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state) 1082static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state)
1077{ 1083{
1078 struct drm_device *dev = pci_get_drvdata(pdev); 1084 struct drm_device *dev = pci_get_drvdata(pdev);
1085
1086 if (radeon_is_px() && state == VGA_SWITCHEROO_OFF)
1087 return;
1088
1079 if (state == VGA_SWITCHEROO_ON) { 1089 if (state == VGA_SWITCHEROO_ON) {
1080 unsigned d3_delay = dev->pdev->d3_delay; 1090 unsigned d3_delay = dev->pdev->d3_delay;
1081 1091
@@ -1086,7 +1096,7 @@ static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switchero
1086 if (d3_delay < 20 && radeon_switcheroo_quirk_long_wakeup(pdev)) 1096 if (d3_delay < 20 && radeon_switcheroo_quirk_long_wakeup(pdev))
1087 dev->pdev->d3_delay = 20; 1097 dev->pdev->d3_delay = 20;
1088 1098
1089 radeon_resume_kms(dev, 1); 1099 radeon_resume_kms(dev, true, true);
1090 1100
1091 dev->pdev->d3_delay = d3_delay; 1101 dev->pdev->d3_delay = d3_delay;
1092 1102
@@ -1096,7 +1106,7 @@ static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switchero
1096 printk(KERN_INFO "radeon: switched off\n"); 1106 printk(KERN_INFO "radeon: switched off\n");
1097 drm_kms_helper_poll_disable(dev); 1107 drm_kms_helper_poll_disable(dev);
1098 dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; 1108 dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
1099 radeon_suspend_kms(dev, 1); 1109 radeon_suspend_kms(dev, true, true);
1100 dev->switch_power_state = DRM_SWITCH_POWER_OFF; 1110 dev->switch_power_state = DRM_SWITCH_POWER_OFF;
1101 } 1111 }
1102} 1112}
@@ -1146,6 +1156,7 @@ int radeon_device_init(struct radeon_device *rdev,
1146{ 1156{
1147 int r, i; 1157 int r, i;
1148 int dma_bits; 1158 int dma_bits;
1159 bool runtime = false;
1149 1160
1150 rdev->shutdown = false; 1161 rdev->shutdown = false;
1151 rdev->dev = &pdev->dev; 1162 rdev->dev = &pdev->dev;
@@ -1292,7 +1303,14 @@ int radeon_device_init(struct radeon_device *rdev,
1292 /* this will fail for cards that aren't VGA class devices, just 1303 /* this will fail for cards that aren't VGA class devices, just
1293 * ignore it */ 1304 * ignore it */
1294 vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode); 1305 vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode);
1295 vga_switcheroo_register_client(rdev->pdev, &radeon_switcheroo_ops, false); 1306
1307 if (radeon_runtime_pm == 1)
1308 runtime = true;
1309 if ((radeon_runtime_pm == -1) && radeon_is_px())
1310 runtime = true;
1311 vga_switcheroo_register_client(rdev->pdev, &radeon_switcheroo_ops, runtime);
1312 if (runtime)
1313 vga_switcheroo_init_domain_pm_ops(rdev->dev, &rdev->vga_pm_domain);
1296 1314
1297 r = radeon_init(rdev); 1315 r = radeon_init(rdev);
1298 if (r) 1316 if (r)
@@ -1382,7 +1400,7 @@ void radeon_device_fini(struct radeon_device *rdev)
1382 * Returns 0 for success or an error on failure. 1400 * Returns 0 for success or an error on failure.
1383 * Called at driver suspend. 1401 * Called at driver suspend.
1384 */ 1402 */
1385int radeon_suspend_kms(struct drm_device *dev, bool suspend) 1403int radeon_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon)
1386{ 1404{
1387 struct radeon_device *rdev; 1405 struct radeon_device *rdev;
1388 struct drm_crtc *crtc; 1406 struct drm_crtc *crtc;
@@ -1457,9 +1475,12 @@ int radeon_suspend_kms(struct drm_device *dev, bool suspend)
1457 pci_disable_device(dev->pdev); 1475 pci_disable_device(dev->pdev);
1458 pci_set_power_state(dev->pdev, PCI_D3hot); 1476 pci_set_power_state(dev->pdev, PCI_D3hot);
1459 } 1477 }
1460 console_lock(); 1478
1461 radeon_fbdev_set_suspend(rdev, 1); 1479 if (fbcon) {
1462 console_unlock(); 1480 console_lock();
1481 radeon_fbdev_set_suspend(rdev, 1);
1482 console_unlock();
1483 }
1463 return 0; 1484 return 0;
1464} 1485}
1465 1486
@@ -1472,7 +1493,7 @@ int radeon_suspend_kms(struct drm_device *dev, bool suspend)
1472 * Returns 0 for success or an error on failure. 1493 * Returns 0 for success or an error on failure.
1473 * Called at driver resume. 1494 * Called at driver resume.
1474 */ 1495 */
1475int radeon_resume_kms(struct drm_device *dev, bool resume) 1496int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon)
1476{ 1497{
1477 struct drm_connector *connector; 1498 struct drm_connector *connector;
1478 struct radeon_device *rdev = dev->dev_private; 1499 struct radeon_device *rdev = dev->dev_private;
@@ -1481,12 +1502,15 @@ int radeon_resume_kms(struct drm_device *dev, bool resume)
1481 if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) 1502 if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
1482 return 0; 1503 return 0;
1483 1504
1484 console_lock(); 1505 if (fbcon) {
1506 console_lock();
1507 }
1485 if (resume) { 1508 if (resume) {
1486 pci_set_power_state(dev->pdev, PCI_D0); 1509 pci_set_power_state(dev->pdev, PCI_D0);
1487 pci_restore_state(dev->pdev); 1510 pci_restore_state(dev->pdev);
1488 if (pci_enable_device(dev->pdev)) { 1511 if (pci_enable_device(dev->pdev)) {
1489 console_unlock(); 1512 if (fbcon)
1513 console_unlock();
1490 return -1; 1514 return -1;
1491 } 1515 }
1492 } 1516 }
@@ -1501,9 +1525,11 @@ int radeon_resume_kms(struct drm_device *dev, bool resume)
1501 radeon_pm_resume(rdev); 1525 radeon_pm_resume(rdev);
1502 radeon_restore_bios_scratch_regs(rdev); 1526 radeon_restore_bios_scratch_regs(rdev);
1503 1527
1504 radeon_fbdev_set_suspend(rdev, 0); 1528 if (fbcon) {
1505 console_unlock(); 1529 radeon_fbdev_set_suspend(rdev, 0);
1506 1530 console_unlock();
1531 }
1532
1507 /* init dig PHYs, disp eng pll */ 1533 /* init dig PHYs, disp eng pll */
1508 if (rdev->is_atom_bios) { 1534 if (rdev->is_atom_bios) {
1509 radeon_atom_encoder_init(rdev); 1535 radeon_atom_encoder_init(rdev);
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 7adbb7417dd5..0e52cc532c26 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -30,6 +30,7 @@
30#include "atom.h" 30#include "atom.h"
31#include <asm/div64.h> 31#include <asm/div64.h>
32 32
33#include <linux/pm_runtime.h>
33#include <drm/drm_crtc_helper.h> 34#include <drm/drm_crtc_helper.h>
34#include <drm/drm_edid.h> 35#include <drm/drm_edid.h>
35 36
@@ -494,11 +495,55 @@ unlock_free:
494 return r; 495 return r;
495} 496}
496 497
498static int
499radeon_crtc_set_config(struct drm_mode_set *set)
500{
501 struct drm_device *dev;
502 struct radeon_device *rdev;
503 struct drm_crtc *crtc;
504 bool active = false;
505 int ret;
506
507 if (!set || !set->crtc)
508 return -EINVAL;
509
510 dev = set->crtc->dev;
511
512 ret = pm_runtime_get_sync(dev->dev);
513 if (ret < 0)
514 return ret;
515
516 ret = drm_crtc_helper_set_config(set);
517
518 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
519 if (crtc->enabled)
520 active = true;
521
522 pm_runtime_mark_last_busy(dev->dev);
523
524 rdev = dev->dev_private;
525 /* if we have active crtcs and we don't have a power ref,
526 take the current one */
527 if (active && !rdev->have_disp_power_ref) {
528 rdev->have_disp_power_ref = true;
529 return ret;
530 }
531 /* if we have no active crtcs, then drop the power ref
532 we got before */
533 if (!active && rdev->have_disp_power_ref) {
534 pm_runtime_put_autosuspend(dev->dev);
535 rdev->have_disp_power_ref = false;
536 }
537
538 /* drop the power reference we got coming in here */
539 pm_runtime_put_autosuspend(dev->dev);
540 return ret;
541}
497static const struct drm_crtc_funcs radeon_crtc_funcs = { 542static const struct drm_crtc_funcs radeon_crtc_funcs = {
498 .cursor_set = radeon_crtc_cursor_set, 543 .cursor_set = radeon_crtc_cursor_set,
499 .cursor_move = radeon_crtc_cursor_move, 544 .cursor_move = radeon_crtc_cursor_move,
500 .gamma_set = radeon_crtc_gamma_set, 545 .gamma_set = radeon_crtc_gamma_set,
501 .set_config = drm_crtc_helper_set_config, 546 .set_config = radeon_crtc_set_config,
502 .destroy = radeon_crtc_destroy, 547 .destroy = radeon_crtc_destroy,
503 .page_flip = radeon_crtc_page_flip, 548 .page_flip = radeon_crtc_page_flip,
504}; 549};
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index 59f067e857db..9902ac76f683 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -36,8 +36,9 @@
36#include <drm/drm_pciids.h> 36#include <drm/drm_pciids.h>
37#include <linux/console.h> 37#include <linux/console.h>
38#include <linux/module.h> 38#include <linux/module.h>
39 39#include <linux/pm_runtime.h>
40 40#include <linux/vga_switcheroo.h>
41#include "drm_crtc_helper.h"
41/* 42/*
42 * KMS wrapper. 43 * KMS wrapper.
43 * - 2.0.0 - initial interface 44 * - 2.0.0 - initial interface
@@ -87,8 +88,8 @@ void radeon_driver_postclose_kms(struct drm_device *dev,
87 struct drm_file *file_priv); 88 struct drm_file *file_priv);
88void radeon_driver_preclose_kms(struct drm_device *dev, 89void radeon_driver_preclose_kms(struct drm_device *dev,
89 struct drm_file *file_priv); 90 struct drm_file *file_priv);
90int radeon_suspend_kms(struct drm_device *dev, bool suspend); 91int radeon_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon);
91int radeon_resume_kms(struct drm_device *dev, bool resume); 92int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon);
92u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc); 93u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc);
93int radeon_enable_vblank_kms(struct drm_device *dev, int crtc); 94int radeon_enable_vblank_kms(struct drm_device *dev, int crtc);
94void radeon_disable_vblank_kms(struct drm_device *dev, int crtc); 95void radeon_disable_vblank_kms(struct drm_device *dev, int crtc);
@@ -136,9 +137,11 @@ void radeon_debugfs_cleanup(struct drm_minor *minor);
136#if defined(CONFIG_VGA_SWITCHEROO) 137#if defined(CONFIG_VGA_SWITCHEROO)
137void radeon_register_atpx_handler(void); 138void radeon_register_atpx_handler(void);
138void radeon_unregister_atpx_handler(void); 139void radeon_unregister_atpx_handler(void);
140bool radeon_is_px(void);
139#else 141#else
140static inline void radeon_register_atpx_handler(void) {} 142static inline void radeon_register_atpx_handler(void) {}
141static inline void radeon_unregister_atpx_handler(void) {} 143static inline void radeon_unregister_atpx_handler(void) {}
144static inline bool radeon_is_px(void) { return false; }
142#endif 145#endif
143 146
144int radeon_no_wb; 147int radeon_no_wb;
@@ -161,6 +164,7 @@ int radeon_lockup_timeout = 10000;
161int radeon_fastfb = 0; 164int radeon_fastfb = 0;
162int radeon_dpm = -1; 165int radeon_dpm = -1;
163int radeon_aspm = -1; 166int radeon_aspm = -1;
167int radeon_runtime_pm = -1;
164 168
165MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers"); 169MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers");
166module_param_named(no_wb, radeon_no_wb, int, 0444); 170module_param_named(no_wb, radeon_no_wb, int, 0444);
@@ -222,6 +226,9 @@ module_param_named(dpm, radeon_dpm, int, 0444);
222MODULE_PARM_DESC(aspm, "ASPM support (1 = enable, 0 = disable, -1 = auto)"); 226MODULE_PARM_DESC(aspm, "ASPM support (1 = enable, 0 = disable, -1 = auto)");
223module_param_named(aspm, radeon_aspm, int, 0444); 227module_param_named(aspm, radeon_aspm, int, 0444);
224 228
229MODULE_PARM_DESC(runpm, "PX runtime pm (1 = force enable, 0 = disable, -1 = PX only default)");
230module_param_named(runpm, radeon_runtime_pm, int, 0444);
231
225static struct pci_device_id pciidlist[] = { 232static struct pci_device_id pciidlist[] = {
226 radeon_PCI_IDS 233 radeon_PCI_IDS
227}; 234};
@@ -258,6 +265,7 @@ static int radeon_resume(struct drm_device *dev)
258 return 0; 265 return 0;
259} 266}
260 267
268
261static const struct file_operations radeon_driver_old_fops = { 269static const struct file_operations radeon_driver_old_fops = {
262 .owner = THIS_MODULE, 270 .owner = THIS_MODULE,
263 .open = drm_open, 271 .open = drm_open,
@@ -356,28 +364,121 @@ static int radeon_pmops_suspend(struct device *dev)
356{ 364{
357 struct pci_dev *pdev = to_pci_dev(dev); 365 struct pci_dev *pdev = to_pci_dev(dev);
358 struct drm_device *drm_dev = pci_get_drvdata(pdev); 366 struct drm_device *drm_dev = pci_get_drvdata(pdev);
359 return radeon_suspend_kms(drm_dev, 1); 367 return radeon_suspend_kms(drm_dev, true, true);
360} 368}
361 369
362static int radeon_pmops_resume(struct device *dev) 370static int radeon_pmops_resume(struct device *dev)
363{ 371{
364 struct pci_dev *pdev = to_pci_dev(dev); 372 struct pci_dev *pdev = to_pci_dev(dev);
365 struct drm_device *drm_dev = pci_get_drvdata(pdev); 373 struct drm_device *drm_dev = pci_get_drvdata(pdev);
366 return radeon_resume_kms(drm_dev, 1); 374 return radeon_resume_kms(drm_dev, true, true);
367} 375}
368 376
369static int radeon_pmops_freeze(struct device *dev) 377static int radeon_pmops_freeze(struct device *dev)
370{ 378{
371 struct pci_dev *pdev = to_pci_dev(dev); 379 struct pci_dev *pdev = to_pci_dev(dev);
372 struct drm_device *drm_dev = pci_get_drvdata(pdev); 380 struct drm_device *drm_dev = pci_get_drvdata(pdev);
373 return radeon_suspend_kms(drm_dev, 0); 381 return radeon_suspend_kms(drm_dev, false, true);
374} 382}
375 383
376static int radeon_pmops_thaw(struct device *dev) 384static int radeon_pmops_thaw(struct device *dev)
377{ 385{
378 struct pci_dev *pdev = to_pci_dev(dev); 386 struct pci_dev *pdev = to_pci_dev(dev);
379 struct drm_device *drm_dev = pci_get_drvdata(pdev); 387 struct drm_device *drm_dev = pci_get_drvdata(pdev);
380 return radeon_resume_kms(drm_dev, 0); 388 return radeon_resume_kms(drm_dev, false, true);
389}
390
391static int radeon_pmops_runtime_suspend(struct device *dev)
392{
393 struct pci_dev *pdev = to_pci_dev(dev);
394 struct drm_device *drm_dev = pci_get_drvdata(pdev);
395 int ret;
396
397 if (radeon_runtime_pm == 0)
398 return -EINVAL;
399
400 drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
401 drm_kms_helper_poll_disable(drm_dev);
402 vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_OFF);
403
404 ret = radeon_suspend_kms(drm_dev, false, false);
405 pci_save_state(pdev);
406 pci_disable_device(pdev);
407 pci_set_power_state(pdev, PCI_D3cold);
408 drm_dev->switch_power_state = DRM_SWITCH_POWER_DYNAMIC_OFF;
409
410 return 0;
411}
412
413static int radeon_pmops_runtime_resume(struct device *dev)
414{
415 struct pci_dev *pdev = to_pci_dev(dev);
416 struct drm_device *drm_dev = pci_get_drvdata(pdev);
417 int ret;
418
419 if (radeon_runtime_pm == 0)
420 return -EINVAL;
421
422 drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
423
424 pci_set_power_state(pdev, PCI_D0);
425 pci_restore_state(pdev);
426 ret = pci_enable_device(pdev);
427 if (ret)
428 return ret;
429 pci_set_master(pdev);
430
431 ret = radeon_resume_kms(drm_dev, false, false);
432 drm_kms_helper_poll_enable(drm_dev);
433 vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_ON);
434 drm_dev->switch_power_state = DRM_SWITCH_POWER_ON;
435 return 0;
436}
437
438static int radeon_pmops_runtime_idle(struct device *dev)
439{
440 struct pci_dev *pdev = to_pci_dev(dev);
441 struct drm_device *drm_dev = pci_get_drvdata(pdev);
442 struct drm_crtc *crtc;
443
444 if (radeon_runtime_pm == 0)
445 return -EBUSY;
446
447 /* are we PX enabled? */
448 if (radeon_runtime_pm == -1 && !radeon_is_px()) {
449 DRM_DEBUG_DRIVER("failing to power off - not px\n");
450 return -EBUSY;
451 }
452
453 list_for_each_entry(crtc, &drm_dev->mode_config.crtc_list, head) {
454 if (crtc->enabled) {
455 DRM_DEBUG_DRIVER("failing to power off - crtc active\n");
456 return -EBUSY;
457 }
458 }
459
460 pm_runtime_mark_last_busy(dev);
461 pm_runtime_autosuspend(dev);
462 /* we don't want the main rpm_idle to call suspend - we want to autosuspend */
463 return 1;
464}
465
466long radeon_drm_ioctl(struct file *filp,
467 unsigned int cmd, unsigned long arg)
468{
469 struct drm_file *file_priv = filp->private_data;
470 struct drm_device *dev;
471 long ret;
472 dev = file_priv->minor->dev;
473 ret = pm_runtime_get_sync(dev->dev);
474 if (ret < 0)
475 return ret;
476
477 ret = drm_ioctl(filp, cmd, arg);
478
479 pm_runtime_mark_last_busy(dev->dev);
480 pm_runtime_put_autosuspend(dev->dev);
481 return ret;
381} 482}
382 483
383static const struct dev_pm_ops radeon_pm_ops = { 484static const struct dev_pm_ops radeon_pm_ops = {
@@ -387,13 +488,16 @@ static const struct dev_pm_ops radeon_pm_ops = {
387 .thaw = radeon_pmops_thaw, 488 .thaw = radeon_pmops_thaw,
388 .poweroff = radeon_pmops_freeze, 489 .poweroff = radeon_pmops_freeze,
389 .restore = radeon_pmops_resume, 490 .restore = radeon_pmops_resume,
491 .runtime_suspend = radeon_pmops_runtime_suspend,
492 .runtime_resume = radeon_pmops_runtime_resume,
493 .runtime_idle = radeon_pmops_runtime_idle,
390}; 494};
391 495
392static const struct file_operations radeon_driver_kms_fops = { 496static const struct file_operations radeon_driver_kms_fops = {
393 .owner = THIS_MODULE, 497 .owner = THIS_MODULE,
394 .open = drm_open, 498 .open = drm_open,
395 .release = drm_release, 499 .release = drm_release,
396 .unlocked_ioctl = drm_ioctl, 500 .unlocked_ioctl = radeon_drm_ioctl,
397 .mmap = radeon_mmap, 501 .mmap = radeon_mmap,
398 .poll = drm_poll, 502 .poll = drm_poll,
399 .read = drm_read, 503 .read = drm_read,
diff --git a/drivers/gpu/drm/radeon/radeon_drv.h b/drivers/gpu/drm/radeon/radeon_drv.h
index b369d42f7de5..543dcfae7e6f 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.h
+++ b/drivers/gpu/drm/radeon/radeon_drv.h
@@ -113,6 +113,9 @@
113#define DRIVER_MINOR 33 113#define DRIVER_MINOR 33
114#define DRIVER_PATCHLEVEL 0 114#define DRIVER_PATCHLEVEL 0
115 115
116long radeon_drm_ioctl(struct file *filp,
117 unsigned int cmd, unsigned long arg);
118
116/* The rest of the file is DEPRECATED! */ 119/* The rest of the file is DEPRECATED! */
117#ifdef CONFIG_DRM_RADEON_UMS 120#ifdef CONFIG_DRM_RADEON_UMS
118 121
diff --git a/drivers/gpu/drm/radeon/radeon_ioc32.c b/drivers/gpu/drm/radeon/radeon_ioc32.c
index c180df8e84db..bdb0f93e73bc 100644
--- a/drivers/gpu/drm/radeon/radeon_ioc32.c
+++ b/drivers/gpu/drm/radeon/radeon_ioc32.c
@@ -418,7 +418,7 @@ long radeon_kms_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long
418 if (nr < DRM_COMMAND_BASE) 418 if (nr < DRM_COMMAND_BASE)
419 return drm_compat_ioctl(filp, cmd, arg); 419 return drm_compat_ioctl(filp, cmd, arg);
420 420
421 ret = drm_ioctl(filp, cmd, arg); 421 ret = radeon_drm_ioctl(filp, cmd, arg);
422 422
423 return ret; 423 return ret;
424} 424}
diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c
index cc9e8482cf30..ec6240b00469 100644
--- a/drivers/gpu/drm/radeon/radeon_irq_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c
@@ -32,6 +32,8 @@
32#include "radeon.h" 32#include "radeon.h"
33#include "atom.h" 33#include "atom.h"
34 34
35#include <linux/pm_runtime.h>
36
35#define RADEON_WAIT_IDLE_TIMEOUT 200 37#define RADEON_WAIT_IDLE_TIMEOUT 200
36 38
37/** 39/**
@@ -47,8 +49,12 @@ irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS)
47{ 49{
48 struct drm_device *dev = (struct drm_device *) arg; 50 struct drm_device *dev = (struct drm_device *) arg;
49 struct radeon_device *rdev = dev->dev_private; 51 struct radeon_device *rdev = dev->dev_private;
52 irqreturn_t ret;
50 53
51 return radeon_irq_process(rdev); 54 ret = radeon_irq_process(rdev);
55 if (ret == IRQ_HANDLED)
56 pm_runtime_mark_last_busy(dev->dev);
57 return ret;
52} 58}
53 59
54/* 60/*
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
index d6b36766e8c9..bb8710531a1b 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -32,7 +32,7 @@
32 32
33#include <linux/vga_switcheroo.h> 33#include <linux/vga_switcheroo.h>
34#include <linux/slab.h> 34#include <linux/slab.h>
35 35#include <linux/pm_runtime.h>
36/** 36/**
37 * radeon_driver_unload_kms - Main unload function for KMS. 37 * radeon_driver_unload_kms - Main unload function for KMS.
38 * 38 *
@@ -50,9 +50,14 @@ int radeon_driver_unload_kms(struct drm_device *dev)
50 50
51 if (rdev == NULL) 51 if (rdev == NULL)
52 return 0; 52 return 0;
53
53 if (rdev->rmmio == NULL) 54 if (rdev->rmmio == NULL)
54 goto done_free; 55 goto done_free;
56
57 pm_runtime_get_sync(dev->dev);
58
55 radeon_acpi_fini(rdev); 59 radeon_acpi_fini(rdev);
60
56 radeon_modeset_fini(rdev); 61 radeon_modeset_fini(rdev);
57 radeon_device_fini(rdev); 62 radeon_device_fini(rdev);
58 63
@@ -125,9 +130,20 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags)
125 "Error during ACPI methods call\n"); 130 "Error during ACPI methods call\n");
126 } 131 }
127 132
133 if (radeon_runtime_pm != 0) {
134 pm_runtime_use_autosuspend(dev->dev);
135 pm_runtime_set_autosuspend_delay(dev->dev, 5000);
136 pm_runtime_set_active(dev->dev);
137 pm_runtime_allow(dev->dev);
138 pm_runtime_mark_last_busy(dev->dev);
139 pm_runtime_put_autosuspend(dev->dev);
140 }
141
128out: 142out:
129 if (r) 143 if (r)
130 radeon_driver_unload_kms(dev); 144 radeon_driver_unload_kms(dev);
145
146
131 return r; 147 return r;
132} 148}
133 149
@@ -475,9 +491,14 @@ void radeon_driver_lastclose_kms(struct drm_device *dev)
475int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) 491int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
476{ 492{
477 struct radeon_device *rdev = dev->dev_private; 493 struct radeon_device *rdev = dev->dev_private;
494 int r;
478 495
479 file_priv->driver_priv = NULL; 496 file_priv->driver_priv = NULL;
480 497
498 r = pm_runtime_get_sync(dev->dev);
499 if (r < 0)
500 return r;
501
481 /* new gpu have virtual address space support */ 502 /* new gpu have virtual address space support */
482 if (rdev->family >= CHIP_CAYMAN) { 503 if (rdev->family >= CHIP_CAYMAN) {
483 struct radeon_fpriv *fpriv; 504 struct radeon_fpriv *fpriv;
@@ -506,6 +527,9 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
506 527
507 file_priv->driver_priv = fpriv; 528 file_priv->driver_priv = fpriv;
508 } 529 }
530
531 pm_runtime_mark_last_busy(dev->dev);
532 pm_runtime_put_autosuspend(dev->dev);
509 return 0; 533 return 0;
510} 534}
511 535