drm/radeon/kms/pm: rework power management

- Separate dynpm and profile based power management methods.  You can select the pm method
  by echoing the selected method ("dynpm" or "profile") to power_method in sysfs.
- Expose basic 4 profile in profile method
  "default" - default clocks
  "auto" - select between low and high based on ac/dc state
  "low" - DC, low power mode
  "high" - AC, performance mode
  The current base profile is "default", but it should switched to "auto" once we've tested
  on more systems.  Switching the state is a matter of echoing the requested profile to
  power_profile in sysfs.  The lowest power states are selected automatically when dpms turns
  the monitors off in all states but default.
- Remove dynamic fence-based reclocking for the moment.  We can revisit this later once we
  have basic pm in.
- Move pm init/fini to modesetting path.  pm is tightly coupled with display state.  Make sure
  display side is initialized before pm.
- Add pm suspend/resume functions to make sure pm state is properly reinitialized on resume.
- Remove dynpm module option.  It's now selectable via sysfs.

Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 4161a35..4c5d21b 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -68,22 +68,21 @@
  * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280
  */
 
-void r100_get_power_state(struct radeon_device *rdev,
-			  enum radeon_pm_action action)
+void r100_pm_get_dynpm_state(struct radeon_device *rdev)
 {
 	int i;
-	rdev->pm.can_upclock = true;
-	rdev->pm.can_downclock = true;
+	rdev->pm.dynpm_can_upclock = true;
+	rdev->pm.dynpm_can_downclock = true;
 
-	switch (action) {
-	case PM_ACTION_MINIMUM:
+	switch (rdev->pm.dynpm_planned_action) {
+	case DYNPM_ACTION_MINIMUM:
 		rdev->pm.requested_power_state_index = 0;
-		rdev->pm.can_downclock = false;
+		rdev->pm.dynpm_can_downclock = false;
 		break;
-	case PM_ACTION_DOWNCLOCK:
+	case DYNPM_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;
+			rdev->pm.dynpm_can_downclock = false;
 		} else {
 			if (rdev->pm.active_crtc_count > 1) {
 				for (i = 0; i < rdev->pm.num_power_states; i++) {
@@ -108,10 +107,10 @@
 			rdev->pm.requested_power_state_index++;
 		}
 		break;
-	case PM_ACTION_UPCLOCK:
+	case DYNPM_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;
+			rdev->pm.dynpm_can_upclock = false;
 		} else {
 			if (rdev->pm.active_crtc_count > 1) {
 				for (i = (rdev->pm.num_power_states - 1); i >= 0; i--) {
@@ -130,11 +129,11 @@
 					rdev->pm.current_power_state_index + 1;
 		}
 		break;
-	case PM_ACTION_DEFAULT:
+	case DYNPM_ACTION_DEFAULT:
 		rdev->pm.requested_power_state_index = rdev->pm.default_power_state_index;
-		rdev->pm.can_upclock = false;
+		rdev->pm.dynpm_can_upclock = false;
 		break;
-	case PM_ACTION_NONE:
+	case DYNPM_ACTION_NONE:
 	default:
 		DRM_ERROR("Requested mode for not defined action\n");
 		return;
@@ -151,77 +150,33 @@
 		 pcie_lanes);
 }
 
-void r100_set_power_state(struct radeon_device *rdev, bool static_switch)
+void r100_pm_init_profile(struct radeon_device *rdev)
 {
-	u32 sclk, mclk;
-
-	if (rdev->pm.current_power_state_index == rdev->pm.requested_power_state_index)
-		return;
-
-	if (radeon_gui_idle(rdev)) {
-
-		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;
-
-		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;
-
-		/* voltage, pcie lanes, etc.*/
-		radeon_pm_misc(rdev);
-
-		if (static_switch) {
-			radeon_pm_prepare(rdev);
-			/* set engine clock */
-			if (sclk != rdev->pm.current_sclk) {
-				radeon_set_engine_clock(rdev, sclk);
-				rdev->pm.current_sclk = sclk;
-				DRM_INFO("Setting: e: %d\n", sclk);
-			}
-			/* set memory clock */
-			if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) {
-				radeon_set_memory_clock(rdev, mclk);
-				rdev->pm.current_mclk = mclk;
-				DRM_INFO("Setting: m: %d\n", mclk);
-			}
-			radeon_pm_finish(rdev);
-		} else {
-			radeon_sync_with_vblank(rdev);
-
-			if (!radeon_pm_in_vbl(rdev))
-				return;
-
-			radeon_pm_prepare(rdev);
-			/* set engine clock */
-			if (sclk != rdev->pm.current_sclk) {
-				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);
-			}
-
-			/* set memory clock */
-			if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) {
-				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);
-			}
-			radeon_pm_finish(rdev);
-		}
-
-		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("pm: GUI not idle!!!\n");
+	/* default */
+	rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
+	rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
+	rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0;
+	rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 0;
+	/* low sh */
+	rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = 0;
+	rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 0;
+	rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
+	rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
+	/* high sh */
+	rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 0;
+	rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
+	rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0;
+	rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 0;
+	/* low mh */
+	rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = 0;
+	rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
+	rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
+	rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
+	/* high mh */
+	rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 0;
+	rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
+	rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0;
+	rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 0;
 }
 
 void r100_pm_misc(struct radeon_device *rdev)
@@ -3815,7 +3770,6 @@
 
 void r100_fini(struct radeon_device *rdev)
 {
-	radeon_pm_fini(rdev);
 	r100_cp_fini(rdev);
 	r100_wb_fini(rdev);
 	r100_ib_fini(rdev);
@@ -3871,8 +3825,6 @@
 	r100_errata(rdev);
 	/* Initialize clocks */
 	radeon_get_clock_info(rdev->ddev);
-	/* Initialize power management */
-	radeon_pm_init(rdev);
 	/* initialize AGP */
 	if (rdev->flags & RADEON_IS_AGP) {
 		r = radeon_agp_init(rdev);