Commit 8554e67d authored by Chengming Gui's avatar Chengming Gui Committed by Alex Deucher
Browse files

drm/amd/powerplay: implement power_dpm_state sys interface for SMU11



Add functions to get/set dpm state for SMU11.

Signed-off-by: default avatarChengming Gui <Jack.Gui@amd.com>
Acked-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Acked-by: default avatarKevin Wang <kevin.wang@amd.com>
Reviewd-by: default avatarEvan Quan <evan.quan@amd.com>
Acked-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent ad88f051
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -290,6 +290,12 @@ enum amdgpu_pcie_gen {
#define amdgpu_dpm_get_current_power_state(adev) \
		((adev)->powerplay.pp_funcs->get_current_power_state((adev)->powerplay.pp_handle))

#define amdgpu_smu_get_current_power_state(adev) \
		((adev)->smu.ppt_funcs->get_current_power_state(&((adev)->smu)))

#define amdgpu_smu_set_power_state(adev) \
		((adev)->smu.ppt_funcs->set_power_state(&((adev)->smu)))

#define amdgpu_dpm_get_pp_num_states(adev, data) \
		((adev)->powerplay.pp_funcs->get_pp_num_states((adev)->powerplay.pp_handle, data))

+3 −1
Original line number Diff line number Diff line
@@ -144,7 +144,9 @@ static ssize_t amdgpu_get_dpm_state(struct device *dev,
	struct amdgpu_device *adev = ddev->dev_private;
	enum amd_pm_state_type pm;

	if (adev->powerplay.pp_funcs->get_current_power_state)
	if (adev->smu.ppt_funcs->get_current_power_state)
		pm = amdgpu_smu_get_current_power_state(adev);
	else if (adev->powerplay.pp_funcs->get_current_power_state)
		pm = amdgpu_dpm_get_current_power_state(adev);
	else
		pm = adev->pm.dpm.user_state;
+116 −0
Original line number Diff line number Diff line
@@ -26,6 +26,118 @@
#include "kgd_pp_interface.h"
#include "dm_pp_interface.h"

struct smu_hw_power_state {
	unsigned int magic;
};

struct smu_power_state;

enum smu_state_ui_label {
	SMU_STATE_UI_LABEL_NONE,
	SMU_STATE_UI_LABEL_BATTERY,
	SMU_STATE_UI_TABEL_MIDDLE_LOW,
	SMU_STATE_UI_LABEL_BALLANCED,
	SMU_STATE_UI_LABEL_MIDDLE_HIGHT,
	SMU_STATE_UI_LABEL_PERFORMANCE,
	SMU_STATE_UI_LABEL_BACO,
};

enum smu_state_classification_flag {
	SMU_STATE_CLASSIFICATION_FLAG_BOOT                     = 0x0001,
	SMU_STATE_CLASSIFICATION_FLAG_THERMAL                  = 0x0002,
	SMU_STATE_CLASSIFICATIN_FLAG_LIMITED_POWER_SOURCE      = 0x0004,
	SMU_STATE_CLASSIFICATION_FLAG_RESET                    = 0x0008,
	SMU_STATE_CLASSIFICATION_FLAG_FORCED                   = 0x0010,
	SMU_STATE_CLASSIFICATION_FLAG_USER_3D_PERFORMANCE      = 0x0020,
	SMU_STATE_CLASSIFICATION_FLAG_USER_2D_PERFORMANCE      = 0x0040,
	SMU_STATE_CLASSIFICATION_FLAG_3D_PERFORMANCE           = 0x0080,
	SMU_STATE_CLASSIFICATION_FLAG_AC_OVERDIRVER_TEMPLATE   = 0x0100,
	SMU_STATE_CLASSIFICATION_FLAG_UVD                      = 0x0200,
	SMU_STATE_CLASSIFICATION_FLAG_3D_PERFORMANCE_LOW       = 0x0400,
	SMU_STATE_CLASSIFICATION_FLAG_ACPI                     = 0x0800,
	SMU_STATE_CLASSIFICATION_FLAG_HD2                      = 0x1000,
	SMU_STATE_CLASSIFICATION_FLAG_UVD_HD                   = 0x2000,
	SMU_STATE_CLASSIFICATION_FLAG_UVD_SD                   = 0x4000,
	SMU_STATE_CLASSIFICATION_FLAG_USER_DC_PERFORMANCE      = 0x8000,
	SMU_STATE_CLASSIFICATION_FLAG_DC_OVERDIRVER_TEMPLATE   = 0x10000,
	SMU_STATE_CLASSIFICATION_FLAG_BACO                     = 0x20000,
	SMU_STATE_CLASSIFICATIN_FLAG_LIMITED_POWER_SOURCE2      = 0x40000,
	SMU_STATE_CLASSIFICATION_FLAG_ULV                      = 0x80000,
	SMU_STATE_CLASSIFICATION_FLAG_UVD_MVC                  = 0x100000,
};

struct smu_state_classification_block {
	enum smu_state_ui_label         ui_label;
	enum smu_state_classification_flag  flags;
	int                          bios_index;
	bool                      temporary_state;
	bool                      to_be_deleted;
};

struct smu_state_pcie_block {
	unsigned int lanes;
};

enum smu_refreshrate_source {
	SMU_REFRESHRATE_SOURCE_EDID,
	SMU_REFRESHRATE_SOURCE_EXPLICIT
};

struct smu_state_display_block {
	bool              disable_frame_modulation;
	bool              limit_refreshrate;
	enum smu_refreshrate_source refreshrate_source;
	int                  explicit_refreshrate;
	int                  edid_refreshrate_index;
	bool              enable_vari_bright;
};

struct smu_state_memroy_block {
	bool              dll_off;
	uint8_t                 m3arb;
	uint8_t                 unused[3];
};

struct smu_state_software_algorithm_block {
	bool disable_load_balancing;
	bool enable_sleep_for_timestamps;
};

struct smu_temperature_range {
	int min;
	int max;
};

struct smu_state_validation_block {
	bool single_display_only;
	bool disallow_on_dc;
	uint8_t supported_power_levels;
};

struct smu_uvd_clocks {
	uint32_t vclk;
	uint32_t dclk;
};

/**
* Structure to hold a SMU Power State.
*/
struct smu_power_state {
	uint32_t                                      id;
	struct list_head                              ordered_list;
	struct list_head                              all_states_list;

	struct smu_state_classification_block         classification;
	struct smu_state_validation_block             validation;
	struct smu_state_pcie_block                   pcie;
	struct smu_state_display_block                display;
	struct smu_state_memroy_block                 memory;
	struct smu_temperature_range                  temperatures;
	struct smu_state_software_algorithm_block     software;
	struct smu_uvd_clocks                         uvd_clocks;
	struct smu_hw_power_state                     hardware;
};

enum smu_message_type
{
	SMU_MSG_TestMessage = 0,
@@ -204,6 +316,8 @@ struct smu_dpm_context {
	uint32_t dpm_context_size;
	void *dpm_context;
	void *golden_dpm_context;
	struct smu_power_state *dpm_request_power_state;
	struct smu_power_state *dpm_current_power_state;
};

struct smu_power_context {
@@ -257,7 +371,9 @@ struct pptable_funcs {
	int (*get_smu_msg_index)(struct smu_context *smu, uint32_t index);
	int (*run_afll_btc)(struct smu_context *smu);
	int (*get_unallowed_feature_mask)(struct smu_context *smu, uint32_t *feature_mask, uint32_t num);
	enum amd_pm_state_type (*get_current_power_state)(struct smu_context *smu);
	int (*set_default_dpm_table)(struct smu_context *smu);
	int (*set_power_state)(struct smu_context *smu);
	int (*populate_umd_state_clk)(struct smu_context *smu);
	int (*print_clk_levels)(struct smu_context *smu, enum pp_clock_type type, char *buf);
	int (*force_clk_levels)(struct smu_context *smu, enum pp_clock_type type, uint32_t mask);
+4 −0
Original line number Diff line number Diff line
@@ -273,9 +273,13 @@ static int smu_v11_0_fini_dpm_context(struct smu_context *smu)

	kfree(smu_dpm->dpm_context);
	kfree(smu_dpm->golden_dpm_context);
	kfree(smu_dpm->dpm_current_power_state);
	kfree(smu_dpm->dpm_request_power_state);
	smu_dpm->dpm_context = NULL;
	smu_dpm->golden_dpm_context = NULL;
	smu_dpm->dpm_context_size = 0;
	smu_dpm->dpm_current_power_state = NULL;
	smu_dpm->dpm_request_power_state = NULL;

	return 0;
}
+46 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@
#include "smu11_driver_if.h"
#include "soc15_common.h"
#include "atom.h"
#include "power_state.h"
#include "vega20_ppt.h"
#include "vega20_pptable.h"
#include "vega20_ppsmc.h"
@@ -154,6 +155,16 @@ static int vega20_allocate_dpm_context(struct smu_context *smu)

	smu_dpm->dpm_context_size = sizeof(struct vega20_dpm_table);

	smu_dpm->dpm_current_power_state = kzalloc(sizeof(struct smu_power_state),
				       GFP_KERNEL);
	if (!smu_dpm->dpm_current_power_state)
		return -ENOMEM;

	smu_dpm->dpm_request_power_state = kzalloc(sizeof(struct smu_power_state),
				       GFP_KERNEL);
	if (!smu_dpm->dpm_request_power_state)
		return -ENOMEM;

	return 0;
}

@@ -389,6 +400,39 @@ vega20_get_unallowed_feature_mask(struct smu_context *smu,
	return 0;
}

static enum
amd_pm_state_type vega20_get_current_power_state(struct smu_context *smu)
{
	enum amd_pm_state_type pm_type;
	struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);

	if (!smu_dpm_ctx->dpm_context ||
	    !smu_dpm_ctx->dpm_current_power_state)
		return -EINVAL;

	mutex_lock(&(smu->mutex));
	switch (smu_dpm_ctx->dpm_current_power_state->classification.ui_label) {
	case SMU_STATE_UI_LABEL_BATTERY:
		pm_type = POWER_STATE_TYPE_BATTERY;
		break;
	case SMU_STATE_UI_LABEL_BALLANCED:
		pm_type = POWER_STATE_TYPE_BALANCED;
		break;
	case SMU_STATE_UI_LABEL_PERFORMANCE:
		pm_type = POWER_STATE_TYPE_PERFORMANCE;
		break;
	default:
		if (smu_dpm_ctx->dpm_current_power_state->classification.flags & SMU_STATE_CLASSIFICATION_FLAG_BOOT)
			pm_type = POWER_STATE_TYPE_INTERNAL_BOOT;
		else
			pm_type = POWER_STATE_TYPE_DEFAULT;
		break;
	}
	mutex_unlock(&(smu->mutex));

	return pm_type;
}

static int
vega20_set_single_dpm_table(struct smu_context *smu,
			    struct vega20_single_dpm_table *single_dpm_table,
@@ -1263,7 +1307,9 @@ static const struct pptable_funcs vega20_ppt_funcs = {
	.get_smu_msg_index = vega20_get_smu_msg_index,
	.run_afll_btc = vega20_run_btc_afll,
	.get_unallowed_feature_mask = vega20_get_unallowed_feature_mask,
	.get_current_power_state = vega20_get_current_power_state,
	.set_default_dpm_table = vega20_set_default_dpm_table,
	.set_power_state = NULL,
	.populate_umd_state_clk = vega20_populate_umd_state_clk,
	.print_clk_levels = vega20_print_clk_levels,
	.force_clk_levels = vega20_force_clk_levels,