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

Commit 136de91e authored by Alex Deucher's avatar Alex Deucher
Browse files

drm/radeon: dpm updates for KV



This updates dpm support for KV asics. Notably there
are some changes in acp handling and forcing performance
levels.

Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 8c5c6fad
Loading
Loading
Loading
Loading
+88 −15
Original line number Original line Diff line number Diff line
@@ -40,6 +40,7 @@ static int kv_calculate_dpm_settings(struct radeon_device *rdev);
static void kv_enable_new_levels(struct radeon_device *rdev);
static void kv_enable_new_levels(struct radeon_device *rdev);
static void kv_program_nbps_index_settings(struct radeon_device *rdev,
static void kv_program_nbps_index_settings(struct radeon_device *rdev,
					   struct radeon_ps *new_rps);
					   struct radeon_ps *new_rps);
static int kv_set_enabled_level(struct radeon_device *rdev, u32 level);
static int kv_set_enabled_levels(struct radeon_device *rdev);
static int kv_set_enabled_levels(struct radeon_device *rdev);
static int kv_force_dpm_highest(struct radeon_device *rdev);
static int kv_force_dpm_highest(struct radeon_device *rdev);
static int kv_force_dpm_lowest(struct radeon_device *rdev);
static int kv_force_dpm_lowest(struct radeon_device *rdev);
@@ -519,7 +520,7 @@ static int kv_set_dpm_boot_state(struct radeon_device *rdev)


static void kv_program_vc(struct radeon_device *rdev)
static void kv_program_vc(struct radeon_device *rdev)
{
{
	WREG32_SMC(CG_FTV_0, 0x3FFFC000);
	WREG32_SMC(CG_FTV_0, 0x3FFFC100);
}
}


static void kv_clear_vc(struct radeon_device *rdev)
static void kv_clear_vc(struct radeon_device *rdev)
@@ -638,7 +639,10 @@ static int kv_force_lowest_valid(struct radeon_device *rdev)


static int kv_unforce_levels(struct radeon_device *rdev)
static int kv_unforce_levels(struct radeon_device *rdev)
{
{
	if (rdev->family == CHIP_KABINI)
		return kv_notify_message_to_smu(rdev, PPSMC_MSG_NoForcedLevel);
		return kv_notify_message_to_smu(rdev, PPSMC_MSG_NoForcedLevel);
	else
		return kv_set_enabled_levels(rdev);
}
}


static int kv_update_sclk_t(struct radeon_device *rdev)
static int kv_update_sclk_t(struct radeon_device *rdev)
@@ -1076,6 +1080,13 @@ static int kv_enable_ulv(struct radeon_device *rdev, bool enable)
					PPSMC_MSG_EnableULV : PPSMC_MSG_DisableULV);
					PPSMC_MSG_EnableULV : PPSMC_MSG_DisableULV);
}
}


static void kv_reset_acp_boot_level(struct radeon_device *rdev)
{
	struct kv_power_info *pi = kv_get_pi(rdev);

	pi->acp_boot_level = 0xff;
}

static void kv_update_current_ps(struct radeon_device *rdev,
static void kv_update_current_ps(struct radeon_device *rdev,
				 struct radeon_ps *rps)
				 struct radeon_ps *rps)
{
{
@@ -1190,6 +1201,8 @@ int kv_dpm_enable(struct radeon_device *rdev)
		return ret;
		return ret;
	}
	}


	kv_reset_acp_boot_level(rdev);

	if (rdev->irq.installed &&
	if (rdev->irq.installed &&
	    r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
	    r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
		ret = kv_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);
		ret = kv_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);
@@ -1448,6 +1461,39 @@ static int kv_update_samu_dpm(struct radeon_device *rdev, bool gate)
	return kv_enable_samu_dpm(rdev, !gate);
	return kv_enable_samu_dpm(rdev, !gate);
}
}


static u8 kv_get_acp_boot_level(struct radeon_device *rdev)
{
	u8 i;
	struct radeon_clock_voltage_dependency_table *table =
		&rdev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table;

	for (i = 0; i < table->count; i++) {
		if (table->entries[i].clk >= 0) /* XXX */
			break;
	}

	if (i >= table->count)
		i = table->count - 1;

	return i;
}

static void kv_update_acp_boot_level(struct radeon_device *rdev)
{
	struct kv_power_info *pi = kv_get_pi(rdev);
	u8 acp_boot_level;

	if (!pi->caps_stable_p_state) {
		acp_boot_level = kv_get_acp_boot_level(rdev);
		if (acp_boot_level != pi->acp_boot_level) {
			pi->acp_boot_level = acp_boot_level;
			kv_send_msg_to_smc_with_parameter(rdev,
							  PPSMC_MSG_ACPDPM_SetEnabledMask,
							  (1 << pi->acp_boot_level));
		}
	}
}

static int kv_update_acp_dpm(struct radeon_device *rdev, bool gate)
static int kv_update_acp_dpm(struct radeon_device *rdev, bool gate)
{
{
	struct kv_power_info *pi = kv_get_pi(rdev);
	struct kv_power_info *pi = kv_get_pi(rdev);
@@ -1459,7 +1505,7 @@ static int kv_update_acp_dpm(struct radeon_device *rdev, bool gate)
		if (pi->caps_stable_p_state)
		if (pi->caps_stable_p_state)
			pi->acp_boot_level = table->count - 1;
			pi->acp_boot_level = table->count - 1;
		else
		else
			pi->acp_boot_level = 0;
			pi->acp_boot_level = kv_get_acp_boot_level(rdev);


		ret = kv_copy_bytes_to_smc(rdev,
		ret = kv_copy_bytes_to_smc(rdev,
					   pi->dpm_table_start +
					   pi->dpm_table_start +
@@ -1769,6 +1815,7 @@ int kv_dpm_set_power_state(struct radeon_device *rdev)
				return ret;
				return ret;
			}
			}
#endif
#endif
			kv_update_acp_boot_level(rdev);
			kv_update_sclk_t(rdev);
			kv_update_sclk_t(rdev);
			kv_enable_nb_dpm(rdev);
			kv_enable_nb_dpm(rdev);
		}
		}
@@ -1800,12 +1847,23 @@ void kv_dpm_setup_asic(struct radeon_device *rdev)


void kv_dpm_reset_asic(struct radeon_device *rdev)
void kv_dpm_reset_asic(struct radeon_device *rdev)
{
{
	struct kv_power_info *pi = kv_get_pi(rdev);

	if (rdev->family == CHIP_KABINI) {
		kv_force_lowest_valid(rdev);
		kv_force_lowest_valid(rdev);
		kv_init_graphics_levels(rdev);
		kv_init_graphics_levels(rdev);
		kv_program_bootup_state(rdev);
		kv_program_bootup_state(rdev);
		kv_upload_dpm_settings(rdev);
		kv_upload_dpm_settings(rdev);
		kv_force_lowest_valid(rdev);
		kv_force_lowest_valid(rdev);
		kv_unforce_levels(rdev);
		kv_unforce_levels(rdev);
	} else {
		kv_init_graphics_levels(rdev);
		kv_program_bootup_state(rdev);
		kv_freeze_sclk_dpm(rdev, true);
		kv_upload_dpm_settings(rdev);
		kv_freeze_sclk_dpm(rdev, false);
		kv_set_enabled_level(rdev, pi->graphics_boot_level);
	}
}
}


//XXX use sumo_dpm_display_configuration_changed
//XXX use sumo_dpm_display_configuration_changed
@@ -1870,7 +1928,10 @@ static int kv_force_dpm_highest(struct radeon_device *rdev)
			break;
			break;
	}
	}


	if (rdev->family == CHIP_KABINI)
		return kv_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_DPM_ForceState, i);
		return kv_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_DPM_ForceState, i);
	else
		return kv_set_enabled_level(rdev, i);
}
}


static int kv_force_dpm_lowest(struct radeon_device *rdev)
static int kv_force_dpm_lowest(struct radeon_device *rdev)
@@ -1887,7 +1948,10 @@ static int kv_force_dpm_lowest(struct radeon_device *rdev)
			break;
			break;
	}
	}


	if (rdev->family == CHIP_KABINI)
		return kv_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_DPM_ForceState, i);
		return kv_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_DPM_ForceState, i);
	else
		return kv_set_enabled_level(rdev, i);
}
}


static u8 kv_get_sleep_divider_id_from_clock(struct radeon_device *rdev,
static u8 kv_get_sleep_divider_id_from_clock(struct radeon_device *rdev,
@@ -2033,12 +2097,12 @@ static void kv_apply_state_adjust_rules(struct radeon_device *rdev,
		ps->dpmx_nb_ps_lo = 0x1;
		ps->dpmx_nb_ps_lo = 0x1;
		ps->dpmx_nb_ps_hi = 0x0;
		ps->dpmx_nb_ps_hi = 0x0;
	} else {
	} else {
		ps->dpm0_pg_nb_ps_lo = 0x1;
		ps->dpm0_pg_nb_ps_lo = 0x3;
		ps->dpm0_pg_nb_ps_hi = 0x0;
		ps->dpm0_pg_nb_ps_hi = 0x0;
		ps->dpmx_nb_ps_lo = 0x2;
		ps->dpmx_nb_ps_lo = 0x3;
		ps->dpmx_nb_ps_hi = 0x1;
		ps->dpmx_nb_ps_hi = 0x0;


		if (pi->sys_info.nb_dpm_enable && pi->battery_state) {
		if (pi->sys_info.nb_dpm_enable) {
			force_high = (mclk >= pi->sys_info.nbp_memory_clock[3]) ||
			force_high = (mclk >= pi->sys_info.nbp_memory_clock[3]) ||
				pi->video_start || (rdev->pm.dpm.new_active_crtc_count >= 3) ||
				pi->video_start || (rdev->pm.dpm.new_active_crtc_count >= 3) ||
				pi->disable_nb_ps3_in_battery;
				pi->disable_nb_ps3_in_battery;
@@ -2204,6 +2268,15 @@ static void kv_enable_new_levels(struct radeon_device *rdev)
	}
	}
}
}


static int kv_set_enabled_level(struct radeon_device *rdev, u32 level)
{
	u32 new_mask = (1 << level);

	return kv_send_msg_to_smc_with_parameter(rdev,
						 PPSMC_MSG_SCLKDPM_SetEnabledMask,
						 new_mask);
}

static int kv_set_enabled_levels(struct radeon_device *rdev)
static int kv_set_enabled_levels(struct radeon_device *rdev)
{
{
	struct kv_power_info *pi = kv_get_pi(rdev);
	struct kv_power_info *pi = kv_get_pi(rdev);