@@ -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) {
@@ -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");
@@ -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;
@@ -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)
@@ -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)) {