Skip to content

Commit

Permalink
Merge branch 'drm-next-3.11' of git://people.freedesktop.org/~agd5f/l…
Browse files Browse the repository at this point in the history
…inux into drm-next

A few more DPM fixes based on user testing.

* 'drm-next-3.11' of git://people.freedesktop.org/~agd5f/linux:
  drm/radeon/dpm: implement vblank_too_short callback for si
  drm/radeon/dpm: implement vblank_too_short callback for cayman
  drm/radeon/dpm: implement vblank_too_short callback for btc
  drm/radeon/dpm: implement vblank_too_short callback for evergreen
  drm/radeon/dpm: implement vblank_too_short callback for 7xx
  drm/radeon/dpm: add checks against vblank time
  drm/radeon/dpm: add helper to calculate vblank time
  drm/radeon: remove stray line in old pm code
  drm/radeon/dpm: fix display_gap programming on rv7xx
  drm/radeon/dpm: implement force performance level for TN
  drm/radeon/dpm: implement force performance level for ON/LN
  drm/radeon/dpm: implement force performance level for SI
  drm/radeon/dpm: implement force performance level for cayman
  drm/radeon/dpm: implement force performance levels for 7xx/eg/btc
  drm/radeon/dpm: add infrastructure to force performance levels
  drm/radeon: fix surface setup on r1xx
  drm/radeon: add support for 3d perf states on older asics
  drm/radeon: set default clocks for SI when DPM is disabled
  • Loading branch information
Dave Airlie committed Jul 9, 2013
2 parents fd0932d + f4dec31 commit 774d8e3
Show file tree
Hide file tree
Showing 23 changed files with 401 additions and 54 deletions.
3 changes: 3 additions & 0 deletions drivers/gpu/drm/radeon/atombios_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1841,6 +1841,9 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc,
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;
}

Expand Down
20 changes: 17 additions & 3 deletions drivers/gpu/drm/radeon/btc_dpm.c
Original file line number Diff line number Diff line change
Expand Up @@ -2059,6 +2059,19 @@ static void btc_init_stutter_mode(struct radeon_device *rdev)
}
}

bool btc_dpm_vblank_too_short(struct radeon_device *rdev)
{
struct rv7xx_power_info *pi = rv770_get_pi(rdev);
u32 vblank_time = r600_dpm_get_vblank_time(rdev);
u32 switch_limit = pi->mem_gddr5 ? 450 : 100;

if (vblank_time < switch_limit)
return true;
else
return false;

}

static void btc_apply_state_adjust_rules(struct radeon_device *rdev,
struct radeon_ps *rps)
{
Expand All @@ -2068,7 +2081,8 @@ static void btc_apply_state_adjust_rules(struct radeon_device *rdev,
u32 mclk, sclk;
u16 vddc, vddci;

if (rdev->pm.dpm.new_active_crtc_count > 1)
if ((rdev->pm.dpm.new_active_crtc_count > 1) ||
btc_dpm_vblank_too_short(rdev))
disable_mclk_switching = true;
else
disable_mclk_switching = false;
Expand Down Expand Up @@ -2326,9 +2340,9 @@ int btc_dpm_set_power_state(struct radeon_device *rdev)
return ret;
}

ret = rv770_unrestrict_performance_levels_after_switch(rdev);
ret = rv770_dpm_force_performance_level(rdev, RADEON_DPM_FORCED_LEVEL_AUTO);
if (ret) {
DRM_ERROR("rv770_unrestrict_performance_levels_after_switch failed\n");
DRM_ERROR("rv770_dpm_force_performance_level failed\n");
return ret;
}

Expand Down
17 changes: 15 additions & 2 deletions drivers/gpu/drm/radeon/cypress_dpm.c
Original file line number Diff line number Diff line change
Expand Up @@ -2014,9 +2014,9 @@ int cypress_dpm_set_power_state(struct radeon_device *rdev)
if (eg_pi->pcie_performance_request)
cypress_notify_link_speed_change_after_state_change(rdev, new_ps, old_ps);

ret = rv770_unrestrict_performance_levels_after_switch(rdev);
ret = rv770_dpm_force_performance_level(rdev, RADEON_DPM_FORCED_LEVEL_AUTO);
if (ret) {
DRM_ERROR("rv770_unrestrict_performance_levels_after_switch failed\n");
DRM_ERROR("rv770_dpm_force_performance_level failed\n");
return ret;
}

Expand Down Expand Up @@ -2174,3 +2174,16 @@ void cypress_dpm_fini(struct radeon_device *rdev)
kfree(rdev->pm.dpm.ps);
kfree(rdev->pm.dpm.priv);
}

bool cypress_dpm_vblank_too_short(struct radeon_device *rdev)
{
struct rv7xx_power_info *pi = rv770_get_pi(rdev);
u32 vblank_time = r600_dpm_get_vblank_time(rdev);
u32 switch_limit = pi->mem_gddr5 ? 450 : 300;

if (vblank_time < switch_limit)
return true;
else
return false;

}
8 changes: 4 additions & 4 deletions drivers/gpu/drm/radeon/evergreen.c
Original file line number Diff line number Diff line change
Expand Up @@ -1504,8 +1504,8 @@ void evergreen_pm_misc(struct radeon_device *rdev)
struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage;

if (voltage->type == VOLTAGE_SW) {
/* 0xff01 is a flag rather then an actual voltage */
if (voltage->voltage == 0xff01)
/* 0xff0x are flags rather then an actual voltage */
if ((voltage->voltage & 0xff00) == 0xff00)
return;
if (voltage->voltage && (voltage->voltage != rdev->pm.current_vddc)) {
radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC);
Expand All @@ -1525,8 +1525,8 @@ void evergreen_pm_misc(struct radeon_device *rdev)
voltage = &rdev->pm.power_state[req_ps_idx].
clock_info[rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx].voltage;

/* 0xff01 is a flag rather then an actual voltage */
if (voltage->vddci == 0xff01)
/* 0xff0x are flags rather then an actual voltage */
if ((voltage->vddci & 0xff00) == 0xff00)
return;
if (voltage->vddci && (voltage->vddci != rdev->pm.current_vddci)) {
radeon_atom_set_voltage(rdev, voltage->vddci, SET_VOLTAGE_TYPE_ASIC_VDDCI);
Expand Down
54 changes: 46 additions & 8 deletions drivers/gpu/drm/radeon/ni_dpm.c
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,19 @@ static void ni_calculate_leakage_for_v_and_t(struct radeon_device *rdev,
ni_calculate_leakage_for_v_and_t_formula(coeff, v, t, i_leakage, leakage);
}

bool ni_dpm_vblank_too_short(struct radeon_device *rdev)
{
struct rv7xx_power_info *pi = rv770_get_pi(rdev);
u32 vblank_time = r600_dpm_get_vblank_time(rdev);
u32 switch_limit = pi->mem_gddr5 ? 450 : 300;

if (vblank_time < switch_limit)
return true;
else
return false;

}

static void ni_apply_state_adjust_rules(struct radeon_device *rdev,
struct radeon_ps *rps)
{
Expand All @@ -775,7 +788,8 @@ static void ni_apply_state_adjust_rules(struct radeon_device *rdev,
u16 vddc, vddci;
int i;

if (rdev->pm.dpm.new_active_crtc_count > 1)
if ((rdev->pm.dpm.new_active_crtc_count > 1) ||
ni_dpm_vblank_too_short(rdev))
disable_mclk_switching = true;
else
disable_mclk_switching = false;
Expand Down Expand Up @@ -1037,13 +1051,37 @@ static int ni_restrict_performance_levels_before_switch(struct radeon_device *rd
0 : -EINVAL;
}

static int ni_unrestrict_performance_levels_after_switch(struct radeon_device *rdev)
int ni_dpm_force_performance_level(struct radeon_device *rdev,
enum radeon_dpm_forced_level level)
{
if (ni_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetForcedLevels, 0) != PPSMC_Result_OK)
return -EINVAL;
struct radeon_ps *rps = rdev->pm.dpm.current_ps;
struct ni_ps *ps = ni_get_ps(rps);
u32 levels;

return (ni_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetEnabledLevels, 0) == PPSMC_Result_OK) ?
0 : -EINVAL;
if (level == RADEON_DPM_FORCED_LEVEL_HIGH) {
if (ni_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetEnabledLevels, 0) != PPSMC_Result_OK)
return -EINVAL;

if (ni_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetForcedLevels, 1) != PPSMC_Result_OK)
return -EINVAL;
} else if (level == RADEON_DPM_FORCED_LEVEL_LOW) {
if (ni_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetForcedLevels, 0) != PPSMC_Result_OK)
return -EINVAL;

levels = ps->performance_level_count - 1;
if (ni_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetEnabledLevels, levels) != PPSMC_Result_OK)
return -EINVAL;
} else if (level == RADEON_DPM_FORCED_LEVEL_AUTO) {
if (ni_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetForcedLevels, 0) != PPSMC_Result_OK)
return -EINVAL;

if (ni_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetEnabledLevels, 0) != PPSMC_Result_OK)
return -EINVAL;
}

rdev->pm.dpm.forced_level = level;

return 0;
}

static void ni_stop_smc(struct radeon_device *rdev)
Expand Down Expand Up @@ -3831,9 +3869,9 @@ int ni_dpm_set_power_state(struct radeon_device *rdev)
return ret;
}

ret = ni_unrestrict_performance_levels_after_switch(rdev);
ret = ni_dpm_force_performance_level(rdev, RADEON_DPM_FORCED_LEVEL_AUTO);
if (ret) {
DRM_ERROR("ni_unrestrict_performance_levels_after_switch failed\n");
DRM_ERROR("ni_dpm_force_performance_level failed\n");
return ret;
}

Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/radeon/ni_dpm.h
Original file line number Diff line number Diff line change
Expand Up @@ -245,4 +245,6 @@ void ni_set_uvd_clock_after_set_eng_clock(struct radeon_device *rdev,
struct radeon_ps *new_ps,
struct radeon_ps *old_ps);

bool ni_dpm_vblank_too_short(struct radeon_device *rdev);

#endif
3 changes: 3 additions & 0 deletions drivers/gpu/drm/radeon/ppsmc.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ typedef uint8_t PPSMC_Result;
#define PPSMC_MSG_SwitchToSwState ((uint8_t)0x20)
#define PPSMC_MSG_SwitchToInitialState ((uint8_t)0x40)
#define PPSMC_MSG_NoForcedLevel ((uint8_t)0x41)
#define PPSMC_MSG_ForceHigh ((uint8_t)0x42)
#define PPSMC_MSG_ForceMediumOrHigh ((uint8_t)0x43)
#define PPSMC_MSG_SwitchToMinimumPower ((uint8_t)0x51)
#define PPSMC_MSG_ResumeFromMinimumPower ((uint8_t)0x52)
#define PPSMC_MSG_EnableCac ((uint8_t)0x53)
Expand Down Expand Up @@ -101,6 +103,7 @@ typedef uint8_t PPSMC_Result;
#define PPSMC_MSG_DPM_Config ((uint32_t) 0x102)
#define PPSMC_MSG_DPM_ForceState ((uint32_t) 0x104)
#define PPSMC_MSG_PG_SIMD_Config ((uint32_t) 0x108)
#define PPSMC_MSG_DPM_N_LevelsDisabled ((uint32_t) 0x112)
#define PPSMC_MSG_DCE_RemoveVoltageAdjustment ((uint32_t) 0x11d)
#define PPSMC_MSG_DCE_AllowVoltageAdjustment ((uint32_t) 0x11e)
#define PPSMC_MSG_UVD_DPM_Config ((uint32_t) 0x124)
Expand Down
11 changes: 4 additions & 7 deletions drivers/gpu/drm/radeon/r100.c
Original file line number Diff line number Diff line change
Expand Up @@ -3077,6 +3077,10 @@ int r100_set_surface_reg(struct radeon_device *rdev, int reg,
flags |= RADEON_SURF_TILE_COLOR_BOTH;
if (tiling_flags & RADEON_TILING_MACRO)
flags |= RADEON_SURF_TILE_COLOR_MACRO;
/* setting pitch to 0 disables tiling */
if ((tiling_flags & (RADEON_TILING_MACRO|RADEON_TILING_MICRO))
== 0)
pitch = 0;
} else if (rdev->family <= CHIP_RV280) {
if (tiling_flags & (RADEON_TILING_MACRO))
flags |= R200_SURF_TILE_COLOR_MACRO;
Expand All @@ -3094,13 +3098,6 @@ int r100_set_surface_reg(struct radeon_device *rdev, int reg,
if (tiling_flags & RADEON_TILING_SWAP_32BIT)
flags |= RADEON_SURF_AP0_SWP_32BPP | RADEON_SURF_AP1_SWP_32BPP;

/* when we aren't tiling the pitch seems to needs to be furtherdivided down. - tested on power5 + rn50 server */
if (tiling_flags & (RADEON_TILING_SWAP_16BIT | RADEON_TILING_SWAP_32BIT)) {
if (!(tiling_flags & (RADEON_TILING_MACRO | RADEON_TILING_MICRO)))
if (ASIC_IS_RN50(rdev))
pitch /= 16;
}

/* r100/r200 divide by 16 */
if (rdev->family < CHIP_R300)
flags |= pitch / 16;
Expand Down
24 changes: 24 additions & 0 deletions drivers/gpu/drm/radeon/r600_dpm.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,30 @@ void r600_dpm_print_ps_status(struct radeon_device *rdev,
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)
{
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/radeon/r600_dpm.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ void r600_dpm_print_class_info(u32 class, u32 class2);
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);
Expand Down
13 changes: 13 additions & 0 deletions drivers/gpu/drm/radeon/radeon.h
Original file line number Diff line number Diff line change
Expand Up @@ -1100,6 +1100,7 @@ enum radeon_pm_state_type {
POWER_STATE_TYPE_INTERNAL_THERMAL,
POWER_STATE_TYPE_INTERNAL_ACPI,
POWER_STATE_TYPE_INTERNAL_ULV,
POWER_STATE_TYPE_INTERNAL_3DPERF,
};

enum radeon_pm_profile_type {
Expand Down Expand Up @@ -1334,6 +1335,12 @@ enum radeon_pcie_gen {
RADEON_PCIE_GEN_INVALID = 0xffff
};

enum radeon_dpm_forced_level {
RADEON_DPM_FORCED_LEVEL_AUTO = 0,
RADEON_DPM_FORCED_LEVEL_LOW = 1,
RADEON_DPM_FORCED_LEVEL_HIGH = 2,
};

struct radeon_dpm {
struct radeon_ps *ps;
/* number of valid power states */
Expand Down Expand Up @@ -1373,6 +1380,8 @@ struct radeon_dpm {
bool uvd_active;
/* thermal handling */
struct radeon_dpm_thermal thermal;
/* forced levels */
enum radeon_dpm_forced_level forced_level;
};

void radeon_dpm_enable_power_state(struct radeon_device *rdev,
Expand Down Expand Up @@ -1668,6 +1677,8 @@ struct radeon_asic {
u32 (*get_mclk)(struct radeon_device *rdev, bool low);
void (*print_power_state)(struct radeon_device *rdev, struct radeon_ps *ps);
void (*debugfs_print_current_performance_level)(struct radeon_device *rdev, struct seq_file *m);
int (*force_performance_level)(struct radeon_device *rdev, enum radeon_dpm_forced_level level);
bool (*vblank_too_short)(struct radeon_device *rdev);
} dpm;
/* pageflipping */
struct {
Expand Down Expand Up @@ -2435,6 +2446,8 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v);
#define radeon_dpm_get_mclk(rdev, l) rdev->asic->dpm.get_mclk((rdev), (l))
#define radeon_dpm_print_power_state(rdev, ps) rdev->asic->dpm.print_power_state((rdev), (ps))
#define radeon_dpm_debugfs_print_current_performance_level(rdev, m) rdev->asic->dpm.debugfs_print_current_performance_level((rdev), (m))
#define radeon_dpm_force_performance_level(rdev, l) rdev->asic->dpm.force_performance_level((rdev), (l))
#define radeon_dpm_vblank_too_short(rdev) rdev->asic->dpm.vblank_too_short((rdev))

/* Common functions */
/* AGP */
Expand Down
12 changes: 12 additions & 0 deletions drivers/gpu/drm/radeon/radeon_asic.c
Original file line number Diff line number Diff line change
Expand Up @@ -1393,6 +1393,8 @@ static struct radeon_asic rv770_asic = {
.get_mclk = &rv770_dpm_get_mclk,
.print_power_state = &rv770_dpm_print_power_state,
.debugfs_print_current_performance_level = &rv770_dpm_debugfs_print_current_performance_level,
.force_performance_level = &rv770_dpm_force_performance_level,
.vblank_too_short = &rv770_dpm_vblank_too_short,
},
.pflip = {
.pre_page_flip = &rs600_pre_page_flip,
Expand Down Expand Up @@ -1516,6 +1518,8 @@ static struct radeon_asic evergreen_asic = {
.get_mclk = &rv770_dpm_get_mclk,
.print_power_state = &rv770_dpm_print_power_state,
.debugfs_print_current_performance_level = &rv770_dpm_debugfs_print_current_performance_level,
.force_performance_level = &rv770_dpm_force_performance_level,
.vblank_too_short = &cypress_dpm_vblank_too_short,
},
.pflip = {
.pre_page_flip = &evergreen_pre_page_flip,
Expand Down Expand Up @@ -1639,6 +1643,7 @@ static struct radeon_asic sumo_asic = {
.get_mclk = &sumo_dpm_get_mclk,
.print_power_state = &sumo_dpm_print_power_state,
.debugfs_print_current_performance_level = &sumo_dpm_debugfs_print_current_performance_level,
.force_performance_level = &sumo_dpm_force_performance_level,
},
.pflip = {
.pre_page_flip = &evergreen_pre_page_flip,
Expand Down Expand Up @@ -1762,6 +1767,8 @@ static struct radeon_asic btc_asic = {
.get_mclk = &btc_dpm_get_mclk,
.print_power_state = &rv770_dpm_print_power_state,
.debugfs_print_current_performance_level = &rv770_dpm_debugfs_print_current_performance_level,
.force_performance_level = &rv770_dpm_force_performance_level,
.vblank_too_short = &btc_dpm_vblank_too_short,
},
.pflip = {
.pre_page_flip = &evergreen_pre_page_flip,
Expand Down Expand Up @@ -1937,6 +1944,8 @@ static struct radeon_asic cayman_asic = {
.get_mclk = &ni_dpm_get_mclk,
.print_power_state = &ni_dpm_print_power_state,
.debugfs_print_current_performance_level = &ni_dpm_debugfs_print_current_performance_level,
.force_performance_level = &ni_dpm_force_performance_level,
.vblank_too_short = &ni_dpm_vblank_too_short,
},
.pflip = {
.pre_page_flip = &evergreen_pre_page_flip,
Expand Down Expand Up @@ -2110,6 +2119,7 @@ static struct radeon_asic trinity_asic = {
.get_mclk = &trinity_dpm_get_mclk,
.print_power_state = &trinity_dpm_print_power_state,
.debugfs_print_current_performance_level = &trinity_dpm_debugfs_print_current_performance_level,
.force_performance_level = &trinity_dpm_force_performance_level,
},
.pflip = {
.pre_page_flip = &evergreen_pre_page_flip,
Expand Down Expand Up @@ -2283,6 +2293,8 @@ static struct radeon_asic si_asic = {
.get_mclk = &ni_dpm_get_mclk,
.print_power_state = &ni_dpm_print_power_state,
.debugfs_print_current_performance_level = &si_dpm_debugfs_print_current_performance_level,
.force_performance_level = &si_dpm_force_performance_level,
.vblank_too_short = &ni_dpm_vblank_too_short,
},
.pflip = {
.pre_page_flip = &evergreen_pre_page_flip,
Expand Down
Loading

0 comments on commit 774d8e3

Please sign in to comment.