#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,
        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 {
        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);
 
 #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"
 
        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;
 }
 
        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,
        .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,