diff mbox

[2/4] radeon: perform memory reclocking in atomic context

Message ID 1269284260-12224-2-git-send-email-mjg@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Matthew Garrett March 22, 2010, 6:57 p.m. UTC
None
diff mbox

Patch

diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 9a7d16b..08e22fe 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -197,11 +197,13 @@  void r100_set_power_state(struct radeon_device *rdev)
 
 		/* 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;
+                        if (!rdev->pm.active_crtcs) {
+                                radeon_set_memory_clock(rdev, mclk);
+                                rdev->pm.current_mclk = mclk;
+                        } else {
+                                rdev->pm.new_mclk = mclk;
+                        }
+                        radeon_sync_with_vblank(rdev);
 			DRM_INFO("Setting: m: %d\n", mclk);
 		}
 
@@ -485,11 +487,25 @@  int r100_irq_process(struct radeon_device *rdev)
 		if (status & RADEON_CRTC_VBLANK_STAT) {
 			drm_handle_vblank(rdev->ddev, 0);
 			rdev->pm.vblank_sync = true;
+			if (rdev->pm.new_mclk) {
+				radeon_pm_debug_check_in_vbl(rdev, false);
+				radeon_set_memory_clock(rdev, rdev->pm.new_mclk);
+				radeon_pm_debug_check_in_vbl(rdev, true);
+				rdev->pm.current_mclk = rdev->pm.new_mclk;
+				rdev->pm.new_mclk = 0;
+			}
 			wake_up(&rdev->irq.vblank_queue);
 		}
 		if (status & RADEON_CRTC2_VBLANK_STAT) {
 			drm_handle_vblank(rdev->ddev, 1);
 			rdev->pm.vblank_sync = true;
+			if (rdev->pm.new_mclk) {
+				radeon_pm_debug_check_in_vbl(rdev, false);
+				radeon_set_memory_clock(rdev, rdev->pm.new_mclk);
+				radeon_pm_debug_check_in_vbl(rdev, true);
+				rdev->pm.current_mclk = rdev->pm.new_mclk;
+				rdev->pm.new_mclk = 0;
+			}
 			wake_up(&rdev->irq.vblank_queue);
 		}
 		if (status & RADEON_FP_DETECT_STAT) {
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index adc558b..a89821b 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -299,11 +299,13 @@  void r600_set_power_state(struct radeon_device *rdev)
 
 		/* set memory clock */
 		if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) {
+			if (!rdev->pm.active_crtcs) {
+				radeon_set_memory_clock(rdev, mclk);
+				rdev->pm.current_mclk = mclk;
+			} else {
+				rdev->pm.new_mclk = 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);
 		}
 
@@ -3020,6 +3022,13 @@  restart_ih:
 				if (disp_int & LB_D1_VBLANK_INTERRUPT) {
 					drm_handle_vblank(rdev->ddev, 0);
 					rdev->pm.vblank_sync = true;
+					if (rdev->pm.new_mclk) {
+						radeon_pm_debug_check_in_vbl(rdev, false);
+						radeon_set_memory_clock(rdev, rdev->pm.new_mclk);
+						radeon_pm_debug_check_in_vbl(rdev, true);
+						rdev->pm.current_mclk = rdev->pm.new_mclk;
+						rdev->pm.new_mclk = 0;
+					}
 					wake_up(&rdev->irq.vblank_queue);
 					disp_int &= ~LB_D1_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D1 vblank\n");
@@ -3042,6 +3051,13 @@  restart_ih:
 				if (disp_int & LB_D2_VBLANK_INTERRUPT) {
 					drm_handle_vblank(rdev->ddev, 1);
 					rdev->pm.vblank_sync = true;
+					if (rdev->pm.new_mclk) {
+						radeon_pm_debug_check_in_vbl(rdev, false);
+						radeon_set_memory_clock(rdev, rdev->pm.new_mclk);
+						radeon_pm_debug_check_in_vbl(rdev, true);
+						rdev->pm.current_mclk = rdev->pm.new_mclk;
+						rdev->pm.new_mclk = 0;
+					}
 					wake_up(&rdev->irq.vblank_queue);
 					disp_int &= ~LB_D2_VBLANK_INTERRUPT;
 					DRM_DEBUG("IH: D2 vblank\n");
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index e8e2fe3..ac403e4 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -727,6 +727,7 @@  struct radeon_pm {
 	int                     default_power_state_index;
 	u32                     current_sclk;
 	u32                     current_mclk;
+	u32			new_mclk;
 	struct radeon_i2c_chan *i2c_bus;
 	/* r6xx+ only */
 	u32 low_simd_mask;
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
index 00bae31..0af81b7 100644
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
@@ -1941,7 +1941,7 @@  void radeon_atom_set_memory_clock(struct radeon_device *rdev,
 
 	args.ulTargetMemoryClock = mem_clock;	/* 10 khz */
 
-	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+	atom_execute_table_atomic(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 }
 
 void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev)
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c
index 55f00a7..83eda0e 100644
--- a/drivers/gpu/drm/radeon/rs600.c
+++ b/drivers/gpu/drm/radeon/rs600.c
@@ -484,11 +484,25 @@  int rs600_irq_process(struct radeon_device *rdev)
 		if (G_007EDC_LB_D1_VBLANK_INTERRUPT(r500_disp_int)) {
 			drm_handle_vblank(rdev->ddev, 0);
 			rdev->pm.vblank_sync = true;
+                        if (rdev->pm.new_mclk) {
+                                radeon_pm_debug_check_in_vbl(rdev, false);
+                                radeon_set_memory_clock(rdev, rdev->pm.new_mclk);
+                                radeon_pm_debug_check_in_vbl(rdev, true);
+                                rdev->pm.current_mclk = rdev->pm.new_mclk;
+                                rdev->pm.new_mclk = 0;
+                        }
 			wake_up(&rdev->irq.vblank_queue);
 		}
 		if (G_007EDC_LB_D2_VBLANK_INTERRUPT(r500_disp_int)) {
 			drm_handle_vblank(rdev->ddev, 1);
 			rdev->pm.vblank_sync = true;
+                        if (rdev->pm.new_mclk) {
+                                radeon_pm_debug_check_in_vbl(rdev, false);
+                                radeon_set_memory_clock(rdev, rdev->pm.new_mclk);
+                                radeon_pm_debug_check_in_vbl(rdev, true);
+                                rdev->pm.current_mclk = rdev->pm.new_mclk;
+                                rdev->pm.new_mclk = 0;
+                        }
 			wake_up(&rdev->irq.vblank_queue);
 		}
 		if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(r500_disp_int)) {