drm/radeon/kms/pm: add asic specific callbacks for getting power state (v2)

This also simplifies the code and enables reclocking with multiple heads
active by tracking whether the power states are single or multi-head
capable.

Eventually, we will want to select a power state based on external
factors (AC/DC state, user selection, etc.).

(v2) Update for evergreen

Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index 12fb12a..b11aa37 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -251,6 +251,7 @@
 		atombios_blank_crtc(crtc, ATOM_DISABLE);
 		drm_vblank_post_modeset(dev, radeon_crtc->crtc_id);
 		radeon_crtc_load_lut(crtc);
+		radeon_crtc->enabled = true;
 		break;
 	case DRM_MODE_DPMS_STANDBY:
 	case DRM_MODE_DPMS_SUSPEND:
@@ -260,6 +261,7 @@
 		if (ASIC_IS_DCE3(rdev))
 			atombios_enable_crtc_memreq(crtc, ATOM_DISABLE);
 		atombios_enable_crtc(crtc, ATOM_DISABLE);
+		radeon_crtc->enabled = false;
 		break;
 	}
 
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index b076b96f..a6b2aca 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -67,41 +67,133 @@
  * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280
  */
 
+void r100_get_power_state(struct radeon_device *rdev,
+			  enum radeon_pm_action action)
+{
+	int i;
+	rdev->pm.can_upclock = true;
+	rdev->pm.can_downclock = true;
+
+	switch (action) {
+	case PM_ACTION_MINIMUM:
+		rdev->pm.requested_power_state_index = 0;
+		rdev->pm.can_downclock = false;
+		break;
+	case PM_ACTION_DOWNCLOCK:
+		if (rdev->pm.current_power_state_index == 0) {
+			rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index;
+			rdev->pm.can_downclock = false;
+		} else {
+			if (rdev->pm.active_crtc_count > 1) {
+				for (i = 0; i < rdev->pm.num_power_states; i++) {
+					if (rdev->pm.power_state[i].flags & RADEON_PM_SINGLE_DISPLAY_ONLY)
+						continue;
+					else if (i >= rdev->pm.current_power_state_index) {
+						rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index;
+						break;
+					} else {
+						rdev->pm.requested_power_state_index = i;
+						break;
+					}
+				}
+			} else
+				rdev->pm.requested_power_state_index =
+					rdev->pm.current_power_state_index - 1;
+		}
+		break;
+	case PM_ACTION_UPCLOCK:
+		if (rdev->pm.current_power_state_index == (rdev->pm.num_power_states - 1)) {
+			rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index;
+			rdev->pm.can_upclock = false;
+		} else {
+			if (rdev->pm.active_crtc_count > 1) {
+				for (i = (rdev->pm.num_power_states - 1); i >= 0; i--) {
+					if (rdev->pm.power_state[i].flags & RADEON_PM_SINGLE_DISPLAY_ONLY)
+						continue;
+					else if (i <= rdev->pm.current_power_state_index) {
+						rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index;
+						break;
+					} else {
+						rdev->pm.requested_power_state_index = i;
+						break;
+					}
+				}
+			} else
+				rdev->pm.requested_power_state_index =
+					rdev->pm.current_power_state_index + 1;
+		}
+		break;
+	case PM_ACTION_NONE:
+	default:
+		DRM_ERROR("Requested mode for not defined action\n");
+		return;
+	}
+	/* only one clock mode per power state */
+	rdev->pm.requested_clock_mode_index = 0;
+
+	DRM_INFO("Requested: e: %d m: %d p: %d\n",
+		 rdev->pm.power_state[rdev->pm.requested_power_state_index].
+		 clock_info[rdev->pm.requested_clock_mode_index].sclk,
+		 rdev->pm.power_state[rdev->pm.requested_power_state_index].
+		 clock_info[rdev->pm.requested_clock_mode_index].mclk,
+		 rdev->pm.power_state[rdev->pm.requested_power_state_index].
+		 non_clock_info.pcie_lanes);
+}
+
 void r100_set_power_state(struct radeon_device *rdev)
 {
-	/* if *_clock_mode are the same, *_power_state are as well */
-	if (rdev->pm.requested_clock_mode == rdev->pm.current_clock_mode)
+	u32 sclk, mclk;
+
+	if (rdev->pm.current_power_state_index == rdev->pm.requested_power_state_index)
 		return;
 
-	DRM_INFO("Setting: e: %d m: %d p: %d\n",
-		 rdev->pm.requested_clock_mode->sclk,
-		 rdev->pm.requested_clock_mode->mclk,
-		 rdev->pm.requested_power_state->non_clock_info.pcie_lanes);
+	if (radeon_gui_idle(rdev)) {
 
-	/* set pcie lanes */
-	/* TODO */
+		sclk = rdev->pm.power_state[rdev->pm.requested_power_state_index].
+			clock_info[rdev->pm.requested_clock_mode_index].sclk;
+		if (sclk > rdev->clock.default_sclk)
+			sclk = rdev->clock.default_sclk;
 
-	/* set voltage */
-	/* TODO */
+		mclk = rdev->pm.power_state[rdev->pm.requested_power_state_index].
+			clock_info[rdev->pm.requested_clock_mode_index].mclk;
+		if (mclk > rdev->clock.default_mclk)
+			mclk = rdev->clock.default_mclk;
+		/* don't change the mclk with multiple crtcs */
+		if (rdev->pm.active_crtc_count > 1)
+			mclk = rdev->clock.default_mclk;
 
-	/* set engine clock */
-	radeon_sync_with_vblank(rdev);
-	radeon_pm_debug_check_in_vbl(rdev, false);
-	radeon_set_engine_clock(rdev, rdev->pm.requested_clock_mode->sclk);
-	radeon_pm_debug_check_in_vbl(rdev, true);
+		/* set pcie lanes */
+		/* TODO */
+
+		/* set voltage */
+		/* TODO */
+
+		/* set engine clock */
+		if (sclk != rdev->pm.current_sclk) {
+			radeon_sync_with_vblank(rdev);
+			radeon_pm_debug_check_in_vbl(rdev, false);
+			radeon_set_engine_clock(rdev, sclk);
+			radeon_pm_debug_check_in_vbl(rdev, true);
+			rdev->pm.current_sclk = sclk;
+			DRM_INFO("Setting: e: %d\n", sclk);
+		}
 
 #if 0
-	/* set memory clock */
-	if (rdev->asic->set_memory_clock) {
-		radeon_sync_with_vblank(rdev);
-		radeon_pm_debug_check_in_vbl(rdev, false);
-		radeon_set_memory_clock(rdev, rdev->pm.requested_clock_mode->mclk);
-		radeon_pm_debug_check_in_vbl(rdev, true);
-	}
+		/* set memory clock */
+		if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) {
+			radeon_sync_with_vblank(rdev);
+			radeon_pm_debug_check_in_vbl(rdev, false);
+			radeon_set_memory_clock(rdev, mclk);
+			radeon_pm_debug_check_in_vbl(rdev, true);
+			rdev->pm.current_mclk = mclk;
+			DRM_INFO("Setting: m: %d\n", mclk);
+		}
 #endif
 
-	rdev->pm.current_power_state = rdev->pm.requested_power_state;
-	rdev->pm.current_clock_mode = rdev->pm.requested_clock_mode;
+		rdev->pm.current_power_state_index = rdev->pm.requested_power_state_index;
+		rdev->pm.current_clock_mode_index = rdev->pm.requested_clock_mode_index;
+	} else
+		DRM_INFO("GUI not idle!!!\n");
 }
 
 bool r100_gui_idle(struct radeon_device *rdev)
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index c2d1946..cc27979 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -92,41 +92,206 @@
 void r600_fini(struct radeon_device *rdev);
 void r600_irq_disable(struct radeon_device *rdev);
 
+void r600_get_power_state(struct radeon_device *rdev,
+			  enum radeon_pm_action action)
+{
+	int i;
+
+	rdev->pm.can_upclock = true;
+	rdev->pm.can_downclock = true;
+
+	/* power state array is low to high, default is first */
+	if ((rdev->flags & RADEON_IS_IGP) || (rdev->family == CHIP_R600)) {
+		int min_power_state_index = 0;
+
+		if (rdev->pm.num_power_states > 2)
+			min_power_state_index = 1;
+
+		switch (action) {
+		case PM_ACTION_MINIMUM:
+			rdev->pm.requested_power_state_index = min_power_state_index;
+			rdev->pm.requested_clock_mode_index = 0;
+			rdev->pm.can_downclock = false;
+			break;
+		case PM_ACTION_DOWNCLOCK:
+			if (rdev->pm.current_power_state_index == min_power_state_index) {
+				rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index;
+				rdev->pm.can_downclock = false;
+			} else {
+				if (rdev->pm.active_crtc_count > 1) {
+					for (i = 0; i < rdev->pm.num_power_states; i++) {
+						if (rdev->pm.power_state[i].flags & RADEON_PM_SINGLE_DISPLAY_ONLY)
+							continue;
+						else if (i >= rdev->pm.current_power_state_index) {
+							rdev->pm.requested_power_state_index =
+								rdev->pm.current_power_state_index;
+							break;
+						} else {
+							rdev->pm.requested_power_state_index = i;
+							break;
+						}
+					}
+				} else
+					rdev->pm.requested_power_state_index =
+						rdev->pm.current_power_state_index - 1;
+			}
+			rdev->pm.requested_clock_mode_index = 0;
+			break;
+		case PM_ACTION_UPCLOCK:
+			if (rdev->pm.current_power_state_index == (rdev->pm.num_power_states - 1)) {
+				rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index;
+				rdev->pm.can_upclock = false;
+			} else {
+				if (rdev->pm.active_crtc_count > 1) {
+					for (i = (rdev->pm.num_power_states - 1); i >= 0; i--) {
+						if (rdev->pm.power_state[i].flags & RADEON_PM_SINGLE_DISPLAY_ONLY)
+							continue;
+						else if (i <= rdev->pm.current_power_state_index) {
+							rdev->pm.requested_power_state_index =
+								rdev->pm.current_power_state_index;
+							break;
+						} else {
+							rdev->pm.requested_power_state_index = i;
+							break;
+						}
+					}
+				} else
+					rdev->pm.requested_power_state_index =
+						rdev->pm.current_power_state_index + 1;
+			}
+			rdev->pm.requested_clock_mode_index = 0;
+			break;
+		case PM_ACTION_NONE:
+		default:
+			DRM_ERROR("Requested mode for not defined action\n");
+			return;
+		}
+	} else {
+		/* XXX select a power state based on AC/DC, single/dualhead, etc. */
+		/* for now just select the first power state and switch between clock modes */
+		/* power state array is low to high, default is first (0) */
+		if (rdev->pm.active_crtc_count > 1) {
+			rdev->pm.requested_power_state_index = -1;
+			/* start at 1 as we don't want the default mode */
+			for (i = 1; i < rdev->pm.num_power_states; i++) {
+				if (rdev->pm.power_state[i].flags & RADEON_PM_SINGLE_DISPLAY_ONLY)
+					continue;
+				else if ((rdev->pm.power_state[i].type == POWER_STATE_TYPE_PERFORMANCE) ||
+					 (rdev->pm.power_state[i].type == POWER_STATE_TYPE_BATTERY)) {
+					rdev->pm.requested_power_state_index = i;
+					break;
+				}
+			}
+			/* if nothing selected, grab the default state. */
+			if (rdev->pm.requested_power_state_index == -1)
+				rdev->pm.requested_power_state_index = 0;
+		} else
+			rdev->pm.requested_power_state_index = 1;
+
+		switch (action) {
+		case PM_ACTION_MINIMUM:
+			rdev->pm.requested_clock_mode_index = 0;
+			rdev->pm.can_downclock = false;
+			break;
+		case PM_ACTION_DOWNCLOCK:
+			if (rdev->pm.requested_power_state_index == rdev->pm.current_power_state_index) {
+				if (rdev->pm.current_clock_mode_index == 0) {
+					rdev->pm.requested_clock_mode_index = 0;
+					rdev->pm.can_downclock = false;
+				} else
+					rdev->pm.requested_clock_mode_index =
+						rdev->pm.current_clock_mode_index - 1;
+			} else {
+				rdev->pm.requested_clock_mode_index = 0;
+				rdev->pm.can_downclock = false;
+			}
+			break;
+		case PM_ACTION_UPCLOCK:
+			if (rdev->pm.requested_power_state_index == rdev->pm.current_power_state_index) {
+				if (rdev->pm.current_clock_mode_index ==
+				    (rdev->pm.power_state[rdev->pm.requested_power_state_index].num_clock_modes - 1)) {
+					rdev->pm.requested_clock_mode_index = rdev->pm.current_clock_mode_index;
+					rdev->pm.can_upclock = false;
+				} else
+					rdev->pm.requested_clock_mode_index =
+						rdev->pm.current_clock_mode_index + 1;
+			} else {
+				rdev->pm.requested_clock_mode_index =
+					rdev->pm.power_state[rdev->pm.requested_power_state_index].num_clock_modes - 1;
+				rdev->pm.can_upclock = false;
+			}
+			break;
+		case PM_ACTION_NONE:
+		default:
+			DRM_ERROR("Requested mode for not defined action\n");
+			return;
+		}
+	}
+
+	DRM_INFO("Requested: e: %d m: %d p: %d\n",
+		 rdev->pm.power_state[rdev->pm.requested_power_state_index].
+		 clock_info[rdev->pm.requested_clock_mode_index].sclk,
+		 rdev->pm.power_state[rdev->pm.requested_power_state_index].
+		 clock_info[rdev->pm.requested_clock_mode_index].mclk,
+		 rdev->pm.power_state[rdev->pm.requested_power_state_index].
+		 non_clock_info.pcie_lanes);
+}
+
 void r600_set_power_state(struct radeon_device *rdev)
 {
-	/* if *_clock_mode are the same, *_power_state are as well */
-	if (rdev->pm.requested_clock_mode == rdev->pm.current_clock_mode)
+	u32 sclk, mclk;
+
+	if ((rdev->pm.requested_clock_mode_index == rdev->pm.current_clock_mode_index) &&
+	    (rdev->pm.requested_power_state_index == rdev->pm.current_power_state_index))
 		return;
 
-	DRM_INFO("Setting: e: %d m: %d p: %d\n",
-		 rdev->pm.requested_clock_mode->sclk,
-		 rdev->pm.requested_clock_mode->mclk,
-		 rdev->pm.requested_power_state->non_clock_info.pcie_lanes);
+	if (radeon_gui_idle(rdev)) {
 
-	/* set pcie lanes */
-	/* TODO */
+		sclk = rdev->pm.power_state[rdev->pm.requested_power_state_index].
+			clock_info[rdev->pm.requested_clock_mode_index].sclk;
+		if (sclk > rdev->clock.default_sclk)
+			sclk = rdev->clock.default_sclk;
 
-	/* set voltage */
-	/* TODO */
+		mclk = rdev->pm.power_state[rdev->pm.requested_power_state_index].
+			clock_info[rdev->pm.requested_clock_mode_index].mclk;
+		if (mclk > rdev->clock.default_mclk)
+			mclk = rdev->clock.default_mclk;
+		/* don't change the mclk with multiple crtcs */
+		if (rdev->pm.active_crtc_count > 1)
+			mclk = rdev->clock.default_mclk;
 
-	/* set engine clock */
-	radeon_sync_with_vblank(rdev);
-	radeon_pm_debug_check_in_vbl(rdev, false);
-	radeon_set_engine_clock(rdev, rdev->pm.requested_clock_mode->sclk);
-	radeon_pm_debug_check_in_vbl(rdev, true);
+		/* set pcie lanes */
+		/* TODO */
+
+		/* set voltage */
+		/* TODO */
+
+		/* set engine clock */
+		if (sclk != rdev->pm.current_sclk) {
+			radeon_sync_with_vblank(rdev);
+			radeon_pm_debug_check_in_vbl(rdev, false);
+			radeon_set_engine_clock(rdev, sclk);
+			radeon_pm_debug_check_in_vbl(rdev, true);
+			rdev->pm.current_sclk = sclk;
+			DRM_INFO("Setting: e: %d\n", sclk);
+		}
 
 #if 0
-	/* set memory clock */
-	if (rdev->asic->set_memory_clock) {
-		radeon_sync_with_vblank(rdev);
-		radeon_pm_debug_check_in_vbl(rdev, false);
-		radeon_set_memory_clock(rdev, rdev->pm.requested_clock_mode->mclk);
-		radeon_pm_debug_check_in_vbl(rdev, true);
-	}
+		/* set memory clock */
+		if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) {
+			radeon_sync_with_vblank(rdev);
+			radeon_pm_debug_check_in_vbl(rdev, false);
+			radeon_set_memory_clock(rdev, mclk);
+			radeon_pm_debug_check_in_vbl(rdev, true);
+			rdev->pm.current_mclk = mclk;
+			DRM_INFO("Setting: m: %d\n", mclk);
+		}
 #endif
 
-	rdev->pm.current_power_state = rdev->pm.requested_power_state;
-	rdev->pm.current_clock_mode = rdev->pm.requested_clock_mode;
+		rdev->pm.current_power_state_index = rdev->pm.requested_power_state_index;
+		rdev->pm.current_clock_mode_index = rdev->pm.requested_clock_mode_index;
+	} else
+		DRM_INFO("GUI not idle!!!\n");
 }
 
 bool r600_gui_idle(struct radeon_device *rdev)
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 11fe1d1..b5eccc4 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -672,6 +672,9 @@
 	u32 flags;
 };
 
+/* state flags */
+#define RADEON_PM_SINGLE_DISPLAY_ONLY (1 << 0)
+
 struct radeon_power_state {
 	enum radeon_pm_state_type type;
 	/* XXX: use a define for num clock modes */
@@ -682,6 +685,8 @@
 	/* non clock info about this state */
 	struct radeon_pm_non_clock_info non_clock_info;
 	bool voltage_drop_active;
+	/* standardized state flags */
+	u32 flags;
 };
 
 /*
@@ -695,8 +700,10 @@
 	enum radeon_pm_state	state;
 	enum radeon_pm_action	planned_action;
 	unsigned long		action_timeout;
-	bool 			downclocked;
-	int			active_crtcs;
+	bool                    can_upclock;
+	bool                    can_downclock;
+	u32			active_crtcs;
+	int			active_crtc_count;
 	int			req_vblank;
 	bool			vblank_sync;
 	bool			gui_idle;
@@ -716,11 +723,13 @@
 	struct radeon_power_state power_state[8];
 	/* number of valid power states */
 	int                     num_power_states;
-	struct radeon_power_state *current_power_state;
-	struct radeon_pm_clock_info *current_clock_mode;
-	struct radeon_power_state *requested_power_state;
-	struct radeon_pm_clock_info *requested_clock_mode;
-	struct radeon_power_state *default_power_state;
+	int                     current_power_state_index;
+	int                     current_clock_mode_index;
+	int                     requested_power_state_index;
+	int                     requested_clock_mode_index;
+	int                     default_power_state_index;
+	u32                     current_sclk;
+	u32                     current_mclk;
 	struct radeon_i2c_chan *i2c_bus;
 };
 
@@ -810,6 +819,7 @@
 	 */
 	void (*ioctl_wait_idle)(struct radeon_device *rdev, struct radeon_bo *bo);
 	bool (*gui_idle)(struct radeon_device *rdev);
+	void (*get_power_state)(struct radeon_device *rdev, enum radeon_pm_action action);
 	void (*set_power_state)(struct radeon_device *rdev);
 };
 
@@ -1218,6 +1228,7 @@
 #define radeon_hpd_sense(rdev, hpd) (rdev)->asic->hpd_sense((rdev), (hpd))
 #define radeon_hpd_set_polarity(rdev, hpd) (rdev)->asic->hpd_set_polarity((rdev), (hpd))
 #define radeon_gui_idle(rdev) (rdev)->asic->gui_idle((rdev))
+#define radeon_get_power_state(rdev, a) (rdev)->asic->get_power_state((rdev), (a))
 #define radeon_set_power_state(rdev) (rdev)->asic->set_power_state((rdev))
 
 /* Common functions */
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c
index 48893fb..1053115 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.c
+++ b/drivers/gpu/drm/radeon/radeon_asic.c
@@ -166,6 +166,7 @@
 	.hpd_set_polarity = &r100_hpd_set_polarity,
 	.ioctl_wait_idle = NULL,
 	.gui_idle = &r100_gui_idle,
+	.get_power_state = &r100_get_power_state,
 	.set_power_state = &r100_set_power_state,
 };
 
@@ -206,6 +207,7 @@
 	.hpd_set_polarity = &r100_hpd_set_polarity,
 	.ioctl_wait_idle = NULL,
 	.gui_idle = &r100_gui_idle,
+	.get_power_state = &r100_get_power_state,
 	.set_power_state = &r100_set_power_state,
 };
 
@@ -247,6 +249,7 @@
 	.hpd_set_polarity = &r100_hpd_set_polarity,
 	.ioctl_wait_idle = NULL,
 	.gui_idle = &r100_gui_idle,
+	.get_power_state = &r100_get_power_state,
 	.set_power_state = &r100_set_power_state,
 };
 
@@ -287,6 +290,7 @@
 	.hpd_set_polarity = &r100_hpd_set_polarity,
 	.ioctl_wait_idle = NULL,
 	.gui_idle = &r100_gui_idle,
+	.get_power_state = &r100_get_power_state,
 	.set_power_state = &r100_set_power_state,
 };
 
@@ -328,6 +332,7 @@
 	.hpd_set_polarity = &r100_hpd_set_polarity,
 	.ioctl_wait_idle = NULL,
 	.gui_idle = &r100_gui_idle,
+	.get_power_state = &r100_get_power_state,
 	.set_power_state = &r100_set_power_state,
 };
 
@@ -369,6 +374,7 @@
 	.hpd_set_polarity = &r100_hpd_set_polarity,
 	.ioctl_wait_idle = NULL,
 	.gui_idle = &r100_gui_idle,
+	.get_power_state = &r100_get_power_state,
 	.set_power_state = &r100_set_power_state,
 };
 
@@ -410,6 +416,7 @@
 	.hpd_set_polarity = &rs600_hpd_set_polarity,
 	.ioctl_wait_idle = NULL,
 	.gui_idle = &r100_gui_idle,
+	.get_power_state = &r100_get_power_state,
 	.set_power_state = &r100_set_power_state,
 };
 
@@ -451,6 +458,7 @@
 	.hpd_set_polarity = &rs600_hpd_set_polarity,
 	.ioctl_wait_idle = NULL,
 	.gui_idle = &r100_gui_idle,
+	.get_power_state = &r100_get_power_state,
 	.set_power_state = &r100_set_power_state,
 };
 
@@ -492,6 +500,7 @@
 	.hpd_set_polarity = &rs600_hpd_set_polarity,
 	.ioctl_wait_idle = NULL,
 	.gui_idle = &r100_gui_idle,
+	.get_power_state = &r100_get_power_state,
 	.set_power_state = &r100_set_power_state,
 };
 
@@ -533,6 +542,7 @@
 	.hpd_set_polarity = &rs600_hpd_set_polarity,
 	.ioctl_wait_idle = NULL,
 	.gui_idle = &r100_gui_idle,
+	.get_power_state = &r100_get_power_state,
 	.set_power_state = &r100_set_power_state,
 };
 
@@ -573,6 +583,7 @@
 	.hpd_set_polarity = &r600_hpd_set_polarity,
 	.ioctl_wait_idle = r600_ioctl_wait_idle,
 	.gui_idle = &r600_gui_idle,
+	.get_power_state = &r600_get_power_state,
 	.set_power_state = &r600_set_power_state,
 };
 
@@ -613,6 +624,7 @@
 	.hpd_set_polarity = &r600_hpd_set_polarity,
 	.ioctl_wait_idle = r600_ioctl_wait_idle,
 	.gui_idle = &r600_gui_idle,
+	.get_power_state = &r600_get_power_state,
 	.set_power_state = &r600_set_power_state,
 };
 
@@ -653,6 +665,7 @@
 	.hpd_set_polarity = &r600_hpd_set_polarity,
 	.ioctl_wait_idle = r600_ioctl_wait_idle,
 	.gui_idle = &r600_gui_idle,
+	.get_power_state = &r600_get_power_state,
 	.set_power_state = &r600_set_power_state,
 };
 
@@ -691,6 +704,7 @@
 	.hpd_sense = &evergreen_hpd_sense,
 	.hpd_set_polarity = &evergreen_hpd_set_polarity,
 	.gui_idle = &r600_gui_idle,
+	.get_power_state = &r600_get_power_state,
 	.set_power_state = &r600_set_power_state,
 };
 
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h
index 90d8e6d..71b21bb 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.h
+++ b/drivers/gpu/drm/radeon/radeon_asic.h
@@ -128,6 +128,8 @@
 void r100_bm_disable(struct radeon_device *rdev);
 extern bool r100_gui_idle(struct radeon_device *rdev);
 extern void r100_set_power_state(struct radeon_device *rdev);
+extern void r100_get_power_state(struct radeon_device *rdev,
+				 enum radeon_pm_action action);
 
 /*
  * r200,rv250,rs300,rv280
@@ -274,6 +276,8 @@
 extern void r600_ioctl_wait_idle(struct radeon_device *rdev, struct radeon_bo *bo);
 extern bool r600_gui_idle(struct radeon_device *rdev);
 extern void r600_set_power_state(struct radeon_device *rdev);
+extern void r600_get_power_state(struct radeon_device *rdev,
+				 enum radeon_pm_action action);
 
 /*
  * rv770,rv730,rv710,rv740
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
index aa0a973..dbfb837 100644
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
@@ -1489,7 +1489,7 @@
 	int state_index = 0, mode_index = 0;
 	struct radeon_i2c_bus_rec i2c_bus;
 
-	rdev->pm.default_power_state = NULL;
+	rdev->pm.default_power_state_index = -1;
 
 	if (atom_parse_data_header(mode_info->atom_context, index, NULL,
 				   &frev, &crev, &data_offset)) {
@@ -1520,12 +1520,6 @@
 					if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) ||
 					    (rdev->pm.power_state[state_index].clock_info[0].sclk == 0))
 						continue;
-					/* skip overclock modes for now */
-					if ((rdev->pm.power_state[state_index].clock_info[0].mclk >
-					     rdev->clock.default_mclk + RADEON_MODE_OVERCLOCK_MARGIN) ||
-					    (rdev->pm.power_state[state_index].clock_info[0].sclk >
-					     rdev->clock.default_sclk + RADEON_MODE_OVERCLOCK_MARGIN))
-						continue;
 					rdev->pm.power_state[state_index].non_clock_info.pcie_lanes =
 						power_info->info.asPowerPlayInfo[i].ucNumPciELanes;
 					misc = le32_to_cpu(power_info->info.asPowerPlayInfo[i].ulMiscInfo);
@@ -1547,6 +1541,7 @@
 						rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id =
 							power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex;
 					}
+					rdev->pm.power_state[state_index].flags = RADEON_PM_SINGLE_DISPLAY_ONLY;
 					/* order matters! */
 					if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE)
 						rdev->pm.power_state[state_index].type =
@@ -1560,15 +1555,20 @@
 					if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN)
 						rdev->pm.power_state[state_index].type =
 							POWER_STATE_TYPE_BALANCED;
-					if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN)
+					if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN) {
 						rdev->pm.power_state[state_index].type =
 							POWER_STATE_TYPE_PERFORMANCE;
+						rdev->pm.power_state[state_index].flags &=
+							~RADEON_PM_SINGLE_DISPLAY_ONLY;
+					}
 					if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) {
 						rdev->pm.power_state[state_index].type =
 							POWER_STATE_TYPE_DEFAULT;
-						rdev->pm.default_power_state = &rdev->pm.power_state[state_index];
+						rdev->pm.default_power_state_index = state_index;
 						rdev->pm.power_state[state_index].default_clock_mode =
 							&rdev->pm.power_state[state_index].clock_info[0];
+						rdev->pm.power_state[state_index].flags &=
+							~RADEON_PM_SINGLE_DISPLAY_ONLY;
 					}
 					state_index++;
 					break;
@@ -1582,12 +1582,6 @@
 					if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) ||
 					    (rdev->pm.power_state[state_index].clock_info[0].sclk == 0))
 						continue;
-					/* skip overclock modes for now */
-					if ((rdev->pm.power_state[state_index].clock_info[0].mclk >
-					     rdev->clock.default_mclk + RADEON_MODE_OVERCLOCK_MARGIN) ||
-					    (rdev->pm.power_state[state_index].clock_info[0].sclk >
-					     rdev->clock.default_sclk + RADEON_MODE_OVERCLOCK_MARGIN))
-						continue;
 					rdev->pm.power_state[state_index].non_clock_info.pcie_lanes =
 						power_info->info_2.asPowerPlayInfo[i].ucNumPciELanes;
 					misc = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo);
@@ -1610,6 +1604,7 @@
 						rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id =
 							power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex;
 					}
+					rdev->pm.power_state[state_index].flags = RADEON_PM_SINGLE_DISPLAY_ONLY;
 					/* order matters! */
 					if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE)
 						rdev->pm.power_state[state_index].type =
@@ -1623,18 +1618,26 @@
 					if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN)
 						rdev->pm.power_state[state_index].type =
 							POWER_STATE_TYPE_BALANCED;
-					if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN)
+					if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN) {
 						rdev->pm.power_state[state_index].type =
 							POWER_STATE_TYPE_PERFORMANCE;
+						rdev->pm.power_state[state_index].flags &=
+							~RADEON_PM_SINGLE_DISPLAY_ONLY;
+					}
 					if (misc2 & ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE)
 						rdev->pm.power_state[state_index].type =
 							POWER_STATE_TYPE_BALANCED;
+					if (misc2 & ATOM_PM_MISCINFO2_MULTI_DISPLAY_SUPPORT)
+						rdev->pm.power_state[state_index].flags &=
+							~RADEON_PM_SINGLE_DISPLAY_ONLY;
 					if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) {
 						rdev->pm.power_state[state_index].type =
 							POWER_STATE_TYPE_DEFAULT;
-						rdev->pm.default_power_state = &rdev->pm.power_state[state_index];
+						rdev->pm.default_power_state_index = state_index;
 						rdev->pm.power_state[state_index].default_clock_mode =
 							&rdev->pm.power_state[state_index].clock_info[0];
+						rdev->pm.power_state[state_index].flags &=
+							~RADEON_PM_SINGLE_DISPLAY_ONLY;
 					}
 					state_index++;
 					break;
@@ -1648,12 +1651,6 @@
 					if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) ||
 					    (rdev->pm.power_state[state_index].clock_info[0].sclk == 0))
 						continue;
-					/* skip overclock modes for now */
-					if ((rdev->pm.power_state[state_index].clock_info[0].mclk >
-					     rdev->clock.default_mclk + RADEON_MODE_OVERCLOCK_MARGIN) ||
-					    (rdev->pm.power_state[state_index].clock_info[0].sclk >
-					     rdev->clock.default_sclk + RADEON_MODE_OVERCLOCK_MARGIN))
-						continue;
 					rdev->pm.power_state[state_index].non_clock_info.pcie_lanes =
 						power_info->info_3.asPowerPlayInfo[i].ucNumPciELanes;
 					misc = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo);
@@ -1682,6 +1679,7 @@
 							power_info->info_3.asPowerPlayInfo[i].ucVDDCI_VoltageDropIndex;
 						}
 					}
+					rdev->pm.power_state[state_index].flags = RADEON_PM_SINGLE_DISPLAY_ONLY;
 					/* order matters! */
 					if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE)
 						rdev->pm.power_state[state_index].type =
@@ -1695,16 +1693,19 @@
 					if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN)
 						rdev->pm.power_state[state_index].type =
 							POWER_STATE_TYPE_BALANCED;
-					if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN)
+					if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN) {
 						rdev->pm.power_state[state_index].type =
 							POWER_STATE_TYPE_PERFORMANCE;
+						rdev->pm.power_state[state_index].flags &=
+							~RADEON_PM_SINGLE_DISPLAY_ONLY;
+					}
 					if (misc2 & ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE)
 						rdev->pm.power_state[state_index].type =
 							POWER_STATE_TYPE_BALANCED;
 					if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) {
 						rdev->pm.power_state[state_index].type =
 							POWER_STATE_TYPE_DEFAULT;
-						rdev->pm.default_power_state = &rdev->pm.power_state[state_index];
+						rdev->pm.default_power_state_index = state_index;
 						rdev->pm.power_state[state_index].default_clock_mode =
 							&rdev->pm.power_state[state_index].clock_info[0];
 					}
@@ -1713,12 +1714,14 @@
 				}
 			}
 			/* last mode is usually default */
-			if (!rdev->pm.default_power_state) {
+			if (rdev->pm.default_power_state_index == -1) {
 				rdev->pm.power_state[state_index - 1].type =
 					POWER_STATE_TYPE_DEFAULT;
-				rdev->pm.default_power_state = &rdev->pm.power_state[state_index - 1];
+				rdev->pm.default_power_state_index = state_index - 1;
 				rdev->pm.power_state[state_index - 1].default_clock_mode =
 					&rdev->pm.power_state[state_index - 1].clock_info[0];
+				rdev->pm.power_state[state_index].flags &=
+					~RADEON_PM_SINGLE_DISPLAY_ONLY;
 			}
 		} else {
 			/* add the i2c bus for thermal/fan chip */
@@ -1774,10 +1777,6 @@
 						/* skip invalid modes */
 						if (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0)
 							continue;
-						/* skip overclock modes for now */
-						if (rdev->pm.power_state[state_index].clock_info[mode_index].sclk >
-						    rdev->clock.default_sclk + RADEON_MODE_OVERCLOCK_MARGIN)
-							continue;
 						rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type =
 							VOLTAGE_SW;
 						rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage =
@@ -1801,12 +1800,6 @@
 						if ((rdev->pm.power_state[state_index].clock_info[mode_index].mclk == 0) ||
 						    (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0))
 							continue;
-						/* skip overclock modes for now */
-						if ((rdev->pm.power_state[state_index].clock_info[mode_index].mclk >
-						     rdev->clock.default_mclk + RADEON_MODE_OVERCLOCK_MARGIN) ||
-						    (rdev->pm.power_state[state_index].clock_info[mode_index].sclk >
-						     rdev->clock.default_sclk + RADEON_MODE_OVERCLOCK_MARGIN))
-							continue;
 						rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type =
 							VOLTAGE_SW;
 						rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage =
@@ -1831,12 +1824,6 @@
 						if ((rdev->pm.power_state[state_index].clock_info[mode_index].mclk == 0) ||
 						    (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0))
 							continue;
-						/* skip overclock modes for now */
-						if ((rdev->pm.power_state[state_index].clock_info[mode_index].mclk >
-						     rdev->clock.default_mclk + RADEON_MODE_OVERCLOCK_MARGIN) ||
-						    (rdev->pm.power_state[state_index].clock_info[mode_index].sclk >
-						     rdev->clock.default_sclk + RADEON_MODE_OVERCLOCK_MARGIN))
-							continue;
 						rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type =
 							VOLTAGE_SW;
 						rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage =
@@ -1865,10 +1852,14 @@
 							POWER_STATE_TYPE_PERFORMANCE;
 						break;
 					}
+					rdev->pm.power_state[state_index].flags = 0;
+					if (misc & ATOM_PPLIB_SINGLE_DISPLAY_ONLY)
+						rdev->pm.power_state[state_index].flags |=
+							RADEON_PM_SINGLE_DISPLAY_ONLY;
 					if (misc2 & ATOM_PPLIB_CLASSIFICATION_BOOT) {
 						rdev->pm.power_state[state_index].type =
 							POWER_STATE_TYPE_DEFAULT;
-						rdev->pm.default_power_state = &rdev->pm.power_state[state_index];
+						rdev->pm.default_power_state_index = state_index;
 						rdev->pm.power_state[state_index].default_clock_mode =
 							&rdev->pm.power_state[state_index].clock_info[mode_index - 1];
 					}
@@ -1876,10 +1867,10 @@
 				}
 			}
 			/* first mode is usually default */
-			if (!rdev->pm.default_power_state) {
+			if (rdev->pm.default_power_state_index == -1) {
 				rdev->pm.power_state[0].type =
 					POWER_STATE_TYPE_DEFAULT;
-				rdev->pm.default_power_state = &rdev->pm.power_state[0];
+				rdev->pm.default_power_state_index = 0;
 				rdev->pm.power_state[0].default_clock_mode =
 					&rdev->pm.power_state[0].clock_info[0];
 			}
@@ -1898,15 +1889,15 @@
 			rdev->pm.power_state[state_index].non_clock_info.pcie_lanes = radeon_get_pcie_lanes(rdev);
 		else
 			rdev->pm.power_state[state_index].non_clock_info.pcie_lanes = 16;
-		rdev->pm.default_power_state = &rdev->pm.power_state[state_index];
+		rdev->pm.default_power_state_index = state_index;
+		rdev->pm.power_state[state_index].flags = 0;
 		state_index++;
 	}
 
 	rdev->pm.num_power_states = state_index;
 
-	rdev->pm.current_power_state = rdev->pm.default_power_state;
-	rdev->pm.current_clock_mode =
-		rdev->pm.default_power_state->default_clock_mode;
+	rdev->pm.current_power_state_index = rdev->pm.default_power_state_index;
+	rdev->pm.current_clock_mode_index = 0;
 }
 
 void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable)
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c
index 44198581..6a9ec85 100644
--- a/drivers/gpu/drm/radeon/radeon_combios.c
+++ b/drivers/gpu/drm/radeon/radeon_combios.c
@@ -2368,7 +2368,7 @@
 	u8 rev, blocks, tmp;
 	int state_index = 0;
 
-	rdev->pm.default_power_state = NULL;
+	rdev->pm.default_power_state_index = -1;
 
 	if (rdev->flags & RADEON_IS_MOBILITY) {
 		offset = combios_get_table_offset(dev, COMBIOS_POWERPLAY_INFO_TABLE);
@@ -2441,6 +2441,7 @@
 			if (rev > 6)
 				rdev->pm.power_state[state_index].non_clock_info.pcie_lanes =
 					RBIOS8(offset + 0x5 + 0x10);
+			rdev->pm.power_state[state_index].flags = RADEON_PM_SINGLE_DISPLAY_ONLY;
 			state_index++;
 		} else {
 			/* XXX figure out some good default low power mode for mobility cards w/out power tables */
@@ -2462,12 +2463,12 @@
 		rdev->pm.power_state[state_index].non_clock_info.pcie_lanes = radeon_get_pcie_lanes(rdev);
 	else
 		rdev->pm.power_state[state_index].non_clock_info.pcie_lanes = 16;
-	rdev->pm.default_power_state = &rdev->pm.power_state[state_index];
+	rdev->pm.power_state[state_index].flags = 0;
+	rdev->pm.default_power_state_index = state_index;
 	rdev->pm.num_power_states = state_index + 1;
 
-	rdev->pm.current_power_state = rdev->pm.default_power_state;
-	rdev->pm.current_clock_mode =
-		rdev->pm.default_power_state->default_clock_mode;
+	rdev->pm.current_power_state_index = rdev->pm.default_power_state_index;
+	rdev->pm.current_clock_mode_index = 0;
 }
 
 void radeon_external_tmds_setup(struct drm_encoder *encoder)
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
index 60c0dcb..f4f9cb2 100644
--- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
+++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
@@ -323,6 +323,7 @@
 		}
 		drm_vblank_post_modeset(dev, radeon_crtc->crtc_id);
 		radeon_crtc_load_lut(crtc);
+		radeon_crtc->enabled = true;
 		break;
 	case DRM_MODE_DPMS_STANDBY:
 	case DRM_MODE_DPMS_SUSPEND:
@@ -335,6 +336,7 @@
 										    RADEON_CRTC_DISP_REQ_EN_B));
 			WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~mask);
 		}
+		radeon_crtc->enabled = false;
 		break;
 	}
 
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c
index 129956d..10ef8924 100644
--- a/drivers/gpu/drm/radeon/radeon_pm.c
+++ b/drivers/gpu/drm/radeon/radeon_pm.c
@@ -56,7 +56,7 @@
 
 	DRM_INFO("%d Power State(s)\n", rdev->pm.num_power_states);
 	for (i = 0; i < rdev->pm.num_power_states; i++) {
-		if (rdev->pm.default_power_state == &rdev->pm.power_state[i])
+		if (rdev->pm.default_power_state_index == i)
 			is_default = true;
 		else
 			is_default = false;
@@ -65,6 +65,8 @@
 			 is_default ? "(default)" : "");
 		if ((rdev->flags & RADEON_IS_PCIE) && !(rdev->flags & RADEON_IS_IGP))
 			DRM_INFO("\t%d PCIE Lanes\n", rdev->pm.power_state[i].non_clock_info.pcie_lanes);
+		if (rdev->pm.power_state[i].flags & RADEON_PM_SINGLE_DISPLAY_ONLY)
+			DRM_INFO("\tSingle display only\n");
 		DRM_INFO("\t%d Clock Mode(s)\n", rdev->pm.power_state[i].num_clock_modes);
 		for (j = 0; j < rdev->pm.power_state[i].num_clock_modes; j++) {
 			if (rdev->flags & RADEON_IS_IGP)
@@ -80,106 +82,6 @@
 	}
 }
 
-static struct radeon_power_state * radeon_pick_power_state(struct radeon_device *rdev,
-							   enum radeon_pm_state_type type)
-{
-	int i, j;
-	enum radeon_pm_state_type wanted_types[2];
-	int wanted_count;
-
-	switch (type) {
-	case POWER_STATE_TYPE_DEFAULT:
-	default:
-		return rdev->pm.default_power_state;
-	case POWER_STATE_TYPE_POWERSAVE:
-		if (rdev->flags & RADEON_IS_MOBILITY) {
-			wanted_types[0] = POWER_STATE_TYPE_POWERSAVE;
-			wanted_types[1] = POWER_STATE_TYPE_BATTERY;
-			wanted_count = 2;
-		} else {
-			wanted_types[0] = POWER_STATE_TYPE_PERFORMANCE;
-			wanted_count = 1;
-		}
-		break;
-	case POWER_STATE_TYPE_BATTERY:
-		if (rdev->flags & RADEON_IS_MOBILITY) {
-			wanted_types[0] = POWER_STATE_TYPE_BATTERY;
-			wanted_types[1] = POWER_STATE_TYPE_POWERSAVE;
-			wanted_count = 2;
-		} else {
-			wanted_types[0] = POWER_STATE_TYPE_PERFORMANCE;
-			wanted_count = 1;
-		}
-		break;
-	case POWER_STATE_TYPE_BALANCED:
-	case POWER_STATE_TYPE_PERFORMANCE:
-		wanted_types[0] = type;
-		wanted_count = 1;
-		break;
-	}
-
-	for (i = 0; i < wanted_count; i++) {
-		for (j = 0; j < rdev->pm.num_power_states; j++) {
-			if (rdev->pm.power_state[j].type == wanted_types[i])
-				return &rdev->pm.power_state[j];
-		}
-	}
-
-	return rdev->pm.default_power_state;
-}
-
-static struct radeon_pm_clock_info * radeon_pick_clock_mode(struct radeon_device *rdev,
-							    struct radeon_power_state *power_state,
-							    enum radeon_pm_clock_mode_type type)
-{
-	switch (type) {
-	case POWER_MODE_TYPE_DEFAULT:
-	default:
-		return power_state->default_clock_mode;
-	case POWER_MODE_TYPE_LOW:
-		return &power_state->clock_info[0];
-	case POWER_MODE_TYPE_MID:
-		if (power_state->num_clock_modes > 2)
-			return &power_state->clock_info[1];
-		else
-			return &power_state->clock_info[0];
-		break;
-	case POWER_MODE_TYPE_HIGH:
-		return &power_state->clock_info[power_state->num_clock_modes - 1];
-	}
-
-}
-
-static void radeon_get_power_state(struct radeon_device *rdev,
-				   enum radeon_pm_action action)
-{
-	switch (action) {
-	case PM_ACTION_MINIMUM:
-		rdev->pm.requested_power_state = radeon_pick_power_state(rdev, POWER_STATE_TYPE_BATTERY);
-		rdev->pm.requested_clock_mode =
-			radeon_pick_clock_mode(rdev, rdev->pm.requested_power_state, POWER_MODE_TYPE_LOW);
-		break;
-	case PM_ACTION_DOWNCLOCK:
-		rdev->pm.requested_power_state = radeon_pick_power_state(rdev, POWER_STATE_TYPE_POWERSAVE);
-		rdev->pm.requested_clock_mode =
-			radeon_pick_clock_mode(rdev, rdev->pm.requested_power_state, POWER_MODE_TYPE_MID);
-		break;
-	case PM_ACTION_UPCLOCK:
-		rdev->pm.requested_power_state = radeon_pick_power_state(rdev, POWER_STATE_TYPE_DEFAULT);
-		rdev->pm.requested_clock_mode =
-			radeon_pick_clock_mode(rdev, rdev->pm.requested_power_state, POWER_MODE_TYPE_HIGH);
-		break;
-	case PM_ACTION_NONE:
-	default:
-		DRM_ERROR("Requested mode for not defined action\n");
-		return;
-	}
-	DRM_INFO("Requested: e: %d m: %d p: %d\n",
-		 rdev->pm.requested_clock_mode->sclk,
-		 rdev->pm.requested_clock_mode->mclk,
-		 rdev->pm.requested_power_state->non_clock_info.pcie_lanes);
-}
-
 void radeon_sync_with_vblank(struct radeon_device *rdev)
 {
 	if (rdev->pm.active_crtcs) {
@@ -194,7 +96,8 @@
 {
 	rdev->pm.state = PM_STATE_DISABLED;
 	rdev->pm.planned_action = PM_ACTION_NONE;
-	rdev->pm.downclocked = false;
+	rdev->pm.can_upclock = true;
+	rdev->pm.can_downclock = true;
 
 	if (rdev->bios) {
 		if (rdev->is_atom_bios)
@@ -229,9 +132,8 @@
 void radeon_pm_compute_clocks(struct radeon_device *rdev)
 {
 	struct drm_device *ddev = rdev->ddev;
-	struct drm_connector *connector;
+	struct drm_crtc *crtc;
 	struct radeon_crtc *radeon_crtc;
-	int count = 0;
 
 	if (rdev->pm.state == PM_STATE_DISABLED)
 		return;
@@ -239,29 +141,27 @@
 	mutex_lock(&rdev->pm.mutex);
 
 	rdev->pm.active_crtcs = 0;
-	list_for_each_entry(connector,
-		&ddev->mode_config.connector_list, head) {
-		if (connector->encoder &&
-		    connector->encoder->crtc &&
-		    connector->dpms != DRM_MODE_DPMS_OFF) {
-			radeon_crtc = to_radeon_crtc(connector->encoder->crtc);
+	rdev->pm.active_crtc_count = 0;
+	list_for_each_entry(crtc,
+		&ddev->mode_config.crtc_list, head) {
+		radeon_crtc = to_radeon_crtc(crtc);
+		if (radeon_crtc->enabled) {
 			rdev->pm.active_crtcs |= (1 << radeon_crtc->crtc_id);
-			++count;
+			rdev->pm.active_crtc_count++;
 		}
 	}
 
-	if (count > 1) {
+	if (rdev->pm.active_crtc_count > 1) {
 		if (rdev->pm.state == PM_STATE_ACTIVE) {
 			cancel_delayed_work(&rdev->pm.idle_work);
 
 			rdev->pm.state = PM_STATE_PAUSED;
 			rdev->pm.planned_action = PM_ACTION_UPCLOCK;
-			if (rdev->pm.downclocked)
-				radeon_pm_set_clocks(rdev);
+			radeon_pm_set_clocks(rdev);
 
 			DRM_DEBUG("radeon: dynamic power management deactivated\n");
 		}
-	} else if (count == 1) {
+	} else if (rdev->pm.active_crtc_count == 1) {
 		/* TODO: Increase clocks if needed for current mode */
 
 		if (rdev->pm.state == PM_STATE_MINIMUM) {
@@ -271,15 +171,13 @@
 
 			queue_delayed_work(rdev->wq, &rdev->pm.idle_work,
 				msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
-		}
-		else if (rdev->pm.state == PM_STATE_PAUSED) {
+		} else if (rdev->pm.state == PM_STATE_PAUSED) {
 			rdev->pm.state = PM_STATE_ACTIVE;
 			queue_delayed_work(rdev->wq, &rdev->pm.idle_work,
 				msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
 			DRM_DEBUG("radeon: dynamic power management activated\n");
 		}
-	}
-	else { /* count == 0 */
+	} else { /* count == 0 */
 		if (rdev->pm.state != PM_STATE_MINIMUM) {
 			cancel_delayed_work(&rdev->pm.idle_work);
 
@@ -359,19 +257,6 @@
 static void radeon_pm_set_clocks_locked(struct radeon_device *rdev)
 {
 	/*radeon_fence_wait_last(rdev);*/
-	switch (rdev->pm.planned_action) {
-	case PM_ACTION_UPCLOCK:
-		rdev->pm.downclocked = false;
-		break;
-	case PM_ACTION_DOWNCLOCK:
-		rdev->pm.downclocked = true;
-		break;
-	case PM_ACTION_MINIMUM:
-		break;
-	case PM_ACTION_NONE:
-		DRM_ERROR("%s: PM_ACTION_NONE\n", __func__);
-		break;
-	}
 
 	radeon_set_power_state(rdev);
 	rdev->pm.planned_action = PM_ACTION_NONE;
@@ -437,7 +322,7 @@
 			if (rdev->pm.planned_action == PM_ACTION_DOWNCLOCK) {
 				rdev->pm.planned_action = PM_ACTION_NONE;
 			} else if (rdev->pm.planned_action == PM_ACTION_NONE &&
-				rdev->pm.downclocked) {
+				   rdev->pm.can_upclock) {
 				rdev->pm.planned_action =
 					PM_ACTION_UPCLOCK;
 				rdev->pm.action_timeout = jiffies +
@@ -447,7 +332,7 @@
 			if (rdev->pm.planned_action == PM_ACTION_UPCLOCK) {
 				rdev->pm.planned_action = PM_ACTION_NONE;
 			} else if (rdev->pm.planned_action == PM_ACTION_NONE &&
-				!rdev->pm.downclocked) {
+				   rdev->pm.can_downclock) {
 				rdev->pm.planned_action =
 					PM_ACTION_DOWNCLOCK;
 				rdev->pm.action_timeout = jiffies +