drm/radeon/dpm: add helper to calculate vblank time

Required for checking vblank time for mclk changes.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index c7ad4b9..b9d3b43 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -1841,6 +1841,9 @@
 	atombios_crtc_set_base(crtc, x, y, old_fb);
 	atombios_overscan_setup(crtc, mode, adjusted_mode);
 	atombios_scaler_setup(crtc);
+	/* update the hw version fpr dpm */
+	radeon_crtc->hw_mode = *adjusted_mode;
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/radeon/r600_dpm.c b/drivers/gpu/drm/radeon/r600_dpm.c
index 76368c0..b88f54b 100644
--- a/drivers/gpu/drm/radeon/r600_dpm.c
+++ b/drivers/gpu/drm/radeon/r600_dpm.c
@@ -150,6 +150,30 @@
 	printk("\n");
 }
 
+u32 r600_dpm_get_vblank_time(struct radeon_device *rdev)
+{
+	struct drm_device *dev = rdev->ddev;
+	struct drm_crtc *crtc;
+	struct radeon_crtc *radeon_crtc;
+	u32 line_time_us, vblank_lines;
+	u32 vblank_time_us = 0xffffffff; /* if the displays are off, vblank time is max */
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		radeon_crtc = to_radeon_crtc(crtc);
+		if (crtc->enabled && radeon_crtc->enabled && radeon_crtc->hw_mode.clock) {
+			line_time_us = (radeon_crtc->hw_mode.crtc_htotal * 1000) /
+				radeon_crtc->hw_mode.clock;
+			vblank_lines = radeon_crtc->hw_mode.crtc_vblank_end -
+				radeon_crtc->hw_mode.crtc_vdisplay +
+				(radeon_crtc->v_border * 2);
+			vblank_time_us = vblank_lines * line_time_us;
+			break;
+		}
+	}
+
+	return vblank_time_us;
+}
+
 void r600_calculate_u_and_p(u32 i, u32 r_c, u32 p_b,
 			    u32 *p, u32 *u)
 {
diff --git a/drivers/gpu/drm/radeon/r600_dpm.h b/drivers/gpu/drm/radeon/r600_dpm.h
index a95ab21..7c822d9 100644
--- a/drivers/gpu/drm/radeon/r600_dpm.h
+++ b/drivers/gpu/drm/radeon/r600_dpm.h
@@ -129,6 +129,7 @@
 void r600_dpm_print_cap_info(u32 caps);
 void r600_dpm_print_ps_status(struct radeon_device *rdev,
 			      struct radeon_ps *rps);
+u32 r600_dpm_get_vblank_time(struct radeon_device *rdev);
 bool r600_is_uvd_state(u32 class, u32 class2);
 void r600_calculate_u_and_p(u32 i, u32 r_c, u32 p_b,
 			    u32 *p, u32 *u);
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index b568cb1..8296632 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -335,6 +335,7 @@
 	u32 line_time;
 	u32 wm_low;
 	u32 wm_high;
+	struct drm_display_mode hw_mode;
 };
 
 struct radeon_encoder_primary_dac {