@@ -189,11 +189,14 @@ void r100_set_power_state(struct radeon_device *rdev)
/* reclocking the engine appears to be ok as long as the engine is idle
* no need for vblank waiting
*/
- if (sclk != rdev->pm.current_sclk) {
- radeon_set_engine_clock(rdev, sclk);
- rdev->pm.current_sclk = sclk;
- DRM_INFO("Setting: e: %d\n", sclk);
- }
+ if (sclk != rdev->pm.current_sclk) {
+ if (!rdev->pm.active_crtcs) {
+ radeon_set_engine_clock(rdev, sclk);
+ rdev->pm.current_sclk = sclk;
+ } else {
+ rdev->pm.new_mclk = sclk;
+ }
+ }
/* set memory clock */
if (rdev->asic->set_memory_clock && (mclk != rdev->pm.current_mclk)) {
@@ -461,6 +464,7 @@ int r100_irq_process(struct radeon_device *rdev)
{
uint32_t status, msi_rearm;
bool queue_hotplug = false;
+ int i = 0;
/* reset gui idle ack. the status bit is broken */
rdev->irq.gui_idle_acked = false;
@@ -487,24 +491,44 @@ 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);
+ if (rdev->pm.new_mclk || rdev->pm.new_sclk) {
+ while (!radeon_pm_debug_check_in_vbl(rdev, false) && i <100) {
+ udelay(1);
+ i++;
+ }
+ if (i==100) {
+ dev_err(rdev->dev, "Failed to sync with vblank\n");
+ } else if (rdev->pm.new_mclk) {
+ radeon_set_memory_clock(rdev, rdev->pm.new_mclk);
+ rdev->pm.current_mclk = rdev->pm.new_mclk;
+ } else if (rdev->pm.new_sclk) {
+ radeon_set_engine_clock(rdev, rdev->pm.new_sclk);
+ rdev->pm.current_sclk = rdev->pm.new_sclk;
+ }
radeon_pm_debug_check_in_vbl(rdev, true);
- rdev->pm.current_mclk = rdev->pm.new_mclk;
- rdev->pm.new_mclk = 0;
+ rdev->pm.new_mclk = rdev->pm.new_sclk = 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);
+ if (rdev->pm.new_mclk || rdev->pm.new_sclk) {
+ while (!radeon_pm_debug_check_in_vbl(rdev, false) && i <100) {
+ udelay(1);
+ i++;
+ }
+ if (i==100) {
+ dev_err(rdev->dev, "Failed to sync with vblank\n");
+ } else if (rdev->pm.new_mclk) {
+ radeon_set_memory_clock(rdev, rdev->pm.new_mclk);
+ rdev->pm.current_mclk = rdev->pm.new_mclk;
+ } else if (rdev->pm.new_sclk) {
+ radeon_set_engine_clock(rdev, rdev->pm.new_sclk);
+ rdev->pm.current_sclk = rdev->pm.new_sclk;
+ }
radeon_pm_debug_check_in_vbl(rdev, true);
- rdev->pm.current_mclk = rdev->pm.new_mclk;
- rdev->pm.new_mclk = 0;
+ rdev->pm.new_mclk = rdev->pm.new_sclk = 0;
}
wake_up(&rdev->irq.vblank_queue);
}
@@ -292,9 +292,12 @@ void r600_set_power_state(struct radeon_device *rdev)
* no need for vblank waiting
*/
if (sclk != rdev->pm.current_sclk) {
- radeon_set_engine_clock(rdev, sclk);
- rdev->pm.current_sclk = sclk;
- DRM_INFO("Setting: e: %d\n", sclk);
+ if (!rdev->pm.active_crtcs) {
+ radeon_set_engine_clock(rdev, sclk);
+ rdev->pm.current_sclk = sclk;
+ } else {
+ rdev->pm.new_mclk = sclk;
+ }
}
/* set memory clock */
@@ -305,10 +308,12 @@ void r600_set_power_state(struct radeon_device *rdev)
} else {
rdev->pm.new_mclk = mclk;
}
- radeon_sync_with_vblank(rdev);
DRM_INFO("Setting: m: %d\n", mclk);
}
+ if (rdev->pm.new_mclk || rdev->pm.new_sclk)
+ radeon_sync_with_vblank(rdev);
+
#if 0
if (radeon_gui_idle(rdev) &&
(rdev->pm.current_simd_mask != rdev->pm.requested_simd_mask)) {
@@ -2988,6 +2993,7 @@ int r600_irq_process(struct radeon_device *rdev)
u32 ring_index, disp_int, disp_int_cont, disp_int_cont2;
unsigned long flags;
bool queue_hotplug = false;
+ int i = 0;
DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr);
if (!rdev->ih.enabled)
@@ -3022,12 +3028,22 @@ 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);
+ if (rdev->pm.new_mclk || rdev->pm.new_sclk) {
+ while (!radeon_pm_debug_check_in_vbl(rdev, false) && i <100) {
+ udelay(1);
+ i++;
+ }
+ if (i==100) {
+ dev_err(rdev->dev, "Failed to sync with vblank\n");
+ } else if (rdev->pm.new_mclk) {
+ radeon_set_memory_clock(rdev, rdev->pm.new_mclk);
+ rdev->pm.current_mclk = rdev->pm.new_mclk;
+ } else if (rdev->pm.new_sclk) {
+ radeon_set_engine_clock(rdev, rdev->pm.new_sclk);
+ rdev->pm.current_sclk = rdev->pm.new_sclk;
+ }
radeon_pm_debug_check_in_vbl(rdev, true);
- rdev->pm.current_mclk = rdev->pm.new_mclk;
- rdev->pm.new_mclk = 0;
+ rdev->pm.new_mclk = rdev->pm.new_sclk = 0;
}
wake_up(&rdev->irq.vblank_queue);
disp_int &= ~LB_D1_VBLANK_INTERRUPT;
@@ -3051,12 +3067,22 @@ 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);
+ if (rdev->pm.new_mclk || rdev->pm.new_sclk) {
+ while (!radeon_pm_debug_check_in_vbl(rdev, false) && i <100) {
+ udelay(1);
+ i++;
+ }
+ if (i==100) {
+ dev_err(rdev->dev, "Failed to sync with vblank\n");
+ } else if (rdev->pm.new_mclk) {
+ radeon_set_memory_clock(rdev, rdev->pm.new_mclk);
+ rdev->pm.current_mclk = rdev->pm.new_mclk;
+ } else if (rdev->pm.new_sclk) {
+ radeon_set_engine_clock(rdev, rdev->pm.new_sclk);
+ rdev->pm.current_sclk = rdev->pm.new_sclk;
+ }
radeon_pm_debug_check_in_vbl(rdev, true);
- rdev->pm.current_mclk = rdev->pm.new_mclk;
- rdev->pm.new_mclk = 0;
+ rdev->pm.new_mclk = rdev->pm.new_sclk = 0;
}
wake_up(&rdev->irq.vblank_queue);
disp_int &= ~LB_D2_VBLANK_INTERRUPT;
@@ -729,6 +729,7 @@ struct radeon_pm {
u32 current_sclk;
u32 current_mclk;
u32 new_mclk;
+ u32 new_sclk;
u32 *mc_arb_init_values;
struct radeon_i2c_chan *i2c_bus;
/* r6xx+ only */
@@ -1940,7 +1940,7 @@ void radeon_atom_set_engine_clock(struct radeon_device *rdev,
args.ulTargetEngineClock = eng_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_set_memory_clock(struct radeon_device *rdev,