Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 774d8e34 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge branch 'drm-next-3.11' of git://people.freedesktop.org/~agd5f/linux 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
parents fd0932d7 f4dec318
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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;
}

+17 −3
Original line number Diff line number Diff line
@@ -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)
{
@@ -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;
@@ -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;
	}

+15 −2
Original line number Diff line number Diff line
@@ -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;
	}

@@ -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;

}
+4 −4
Original line number Diff line number Diff line
@@ -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);
@@ -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);
+46 −8
Original line number Diff line number Diff line
@@ -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)
{
@@ -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;
@@ -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)
{
	struct radeon_ps *rps = rdev->pm.dpm.current_ps;
	struct ni_ps *ps = ni_get_ps(rps);
	u32 levels;

	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;

	return (ni_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetEnabledLevels, 0) == PPSMC_Result_OK) ?
		0 : -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)
@@ -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;
	}

Loading