Skip to content

Commit

Permalink
drm/radeon/kms: add dynamic engine reclocking (V9)
Browse files Browse the repository at this point in the history
V2: reorganize functions, fix modesetting calls
V3: rebase patch, use radeon's workqueue
V4: enable on tested chipsets only, request VBLANK IRQs
V5: enable PM on older hardware (IRQs, mode_fixup, dpms)
V6: use separate dynpm module parameter
V7: drop RADEON_ prefix, set minimum mode for dpms off
V8: update legacy encoder call, fix order in rs600 IRQ
V9: update compute_clocks call in legacy, not only DPMS_OFF

Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
  • Loading branch information
Rafał Miłecki authored and Dave Airlie committed Feb 8, 2010
1 parent 18917b6 commit c913e23
Show file tree
Hide file tree
Showing 9 changed files with 314 additions and 4 deletions.
4 changes: 4 additions & 0 deletions drivers/gpu/drm/radeon/r100.c
Original file line number Diff line number Diff line change
Expand Up @@ -312,9 +312,13 @@ int r100_irq_process(struct radeon_device *rdev)
/* Vertical blank interrupts */
if (status & RADEON_CRTC_VBLANK_STAT) {
drm_handle_vblank(rdev->ddev, 0);
if (rdev->pm.vblank_callback)
queue_work(rdev->wq, &rdev->pm.reclock_work);
}
if (status & RADEON_CRTC2_VBLANK_STAT) {
drm_handle_vblank(rdev->ddev, 1);
if (rdev->pm.vblank_callback)
queue_work(rdev->wq, &rdev->pm.reclock_work);
}
if (status & RADEON_FP_DETECT_STAT) {
queue_hotplug = true;
Expand Down
4 changes: 4 additions & 0 deletions drivers/gpu/drm/radeon/r600.c
Original file line number Diff line number Diff line change
Expand Up @@ -2744,6 +2744,8 @@ int r600_irq_process(struct radeon_device *rdev)
case 0: /* D1 vblank */
if (disp_int & LB_D1_VBLANK_INTERRUPT) {
drm_handle_vblank(rdev->ddev, 0);
if (rdev->pm.vblank_callback)
queue_work(rdev->wq, &rdev->pm.reclock_work);
disp_int &= ~LB_D1_VBLANK_INTERRUPT;
DRM_DEBUG("IH: D1 vblank\n");
}
Expand All @@ -2764,6 +2766,8 @@ int r600_irq_process(struct radeon_device *rdev)
case 0: /* D2 vblank */
if (disp_int & LB_D2_VBLANK_INTERRUPT) {
drm_handle_vblank(rdev->ddev, 1);
if (rdev->pm.vblank_callback)
queue_work(rdev->wq, &rdev->pm.reclock_work);
disp_int &= ~LB_D2_VBLANK_INTERRUPT;
DRM_DEBUG("IH: D2 vblank\n");
}
Expand Down
28 changes: 28 additions & 0 deletions drivers/gpu/drm/radeon/radeon.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ extern int radeon_testing;
extern int radeon_connector_table;
extern int radeon_tv;
extern int radeon_new_pll;
extern int radeon_dynpm;
extern int radeon_audio;

/*
Expand Down Expand Up @@ -148,6 +149,7 @@ struct radeon_clock {
* Power management
*/
int radeon_pm_init(struct radeon_device *rdev);
void radeon_pm_compute_clocks(struct radeon_device *rdev);

/*
* Fences.
Expand Down Expand Up @@ -569,7 +571,33 @@ struct radeon_wb {
* Equation between gpu/memory clock and available bandwidth is hw dependent
* (type of memory, bus size, efficiency, ...)
*/
enum radeon_pm_state {
PM_STATE_DISABLED,
PM_STATE_MINIMUM,
PM_STATE_PAUSED,
PM_STATE_ACTIVE
};
enum radeon_pm_action {
PM_ACTION_NONE,
PM_ACTION_MINIMUM,
PM_ACTION_DOWNCLOCK,
PM_ACTION_UPCLOCK
};
struct radeon_pm {
struct mutex mutex;
struct work_struct reclock_work;
struct delayed_work idle_work;
enum radeon_pm_state state;
enum radeon_pm_action planned_action;
unsigned long action_timeout;
bool downclocked;
bool vblank_callback;
int active_crtcs;
int req_vblank;
uint32_t min_gpu_engine_clock;
uint32_t min_gpu_memory_clock;
uint32_t min_mode_engine_clock;
uint32_t min_mode_memory_clock;
fixed20_12 max_bandwidth;
fixed20_12 igp_sideport_mclk;
fixed20_12 igp_system_mclk;
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/radeon/radeon_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,7 @@ int radeon_device_init(struct radeon_device *rdev,
if (rdev->family >= CHIP_R600)
spin_lock_init(&rdev->ih.lock);
mutex_init(&rdev->gem.mutex);
mutex_init(&rdev->pm.mutex);
rwlock_init(&rdev->fence_drv.lock);
INIT_LIST_HEAD(&rdev->gem.objects);

Expand Down
4 changes: 4 additions & 0 deletions drivers/gpu/drm/radeon/radeon_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ int radeon_testing = 0;
int radeon_connector_table = 0;
int radeon_tv = 1;
int radeon_new_pll = 1;
int radeon_dynpm = -1;
int radeon_audio = 1;

MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers");
Expand Down Expand Up @@ -125,6 +126,9 @@ module_param_named(tv, radeon_tv, int, 0444);
MODULE_PARM_DESC(new_pll, "Select new PLL code for AVIVO chips");
module_param_named(new_pll, radeon_new_pll, int, 0444);

MODULE_PARM_DESC(dynpm, "Disable/Enable dynamic power management (1 = enable)");
module_param_named(dynpm, radeon_dynpm, int, 0444);

MODULE_PARM_DESC(audio, "Audio enable (0 = disable)");
module_param_named(audio, radeon_audio, int, 0444);

Expand Down
6 changes: 6 additions & 0 deletions drivers/gpu/drm/radeon/radeon_encoders.c
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,9 @@ static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
struct drm_device *dev = encoder->dev;
struct radeon_device *rdev = dev->dev_private;

/* adjust pm to upcoming mode change */
radeon_pm_compute_clocks(rdev);

/* set the active encoder to connector routing */
radeon_encoder_set_active_device(encoder);
drm_mode_set_crtcinfo(adjusted_mode, 0);
Expand Down Expand Up @@ -1013,6 +1016,9 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
}
radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);

/* adjust pm to dpms change */
radeon_pm_compute_clocks(rdev);
}

union crtc_source_param {
Expand Down
20 changes: 20 additions & 0 deletions drivers/gpu/drm/radeon/radeon_legacy_encoders.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,9 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
else
radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);

/* adjust pm to dpms change */
radeon_pm_compute_clocks(rdev);
}

static void radeon_legacy_lvds_prepare(struct drm_encoder *encoder)
Expand Down Expand Up @@ -214,6 +217,11 @@ static bool radeon_legacy_mode_fixup(struct drm_encoder *encoder,
struct drm_display_mode *adjusted_mode)
{
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct drm_device *dev = encoder->dev;
struct radeon_device *rdev = dev->dev_private;

/* adjust pm to upcoming mode change */
radeon_pm_compute_clocks(rdev);

/* set the active encoder to connector routing */
radeon_encoder_set_active_device(encoder);
Expand Down Expand Up @@ -285,6 +293,9 @@ static void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode
radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
else
radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);

/* adjust pm to dpms change */
radeon_pm_compute_clocks(rdev);
}

static void radeon_legacy_primary_dac_prepare(struct drm_encoder *encoder)
Expand Down Expand Up @@ -470,6 +481,9 @@ static void radeon_legacy_tmds_int_dpms(struct drm_encoder *encoder, int mode)
radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
else
radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);

/* adjust pm to dpms change */
radeon_pm_compute_clocks(rdev);
}

static void radeon_legacy_tmds_int_prepare(struct drm_encoder *encoder)
Expand Down Expand Up @@ -635,6 +649,9 @@ static void radeon_legacy_tmds_ext_dpms(struct drm_encoder *encoder, int mode)
radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
else
radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);

/* adjust pm to dpms change */
radeon_pm_compute_clocks(rdev);
}

static void radeon_legacy_tmds_ext_prepare(struct drm_encoder *encoder)
Expand Down Expand Up @@ -842,6 +859,9 @@ static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode)
radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
else
radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);

/* adjust pm to dpms change */
radeon_pm_compute_clocks(rdev);
}

static void radeon_legacy_tv_dac_prepare(struct drm_encoder *encoder)
Expand Down
Loading

0 comments on commit c913e23

Please sign in to comment.