drm/amd/pp: Add OVERDRIVE support on Vega10 (v2)
authorRex Zhu <Rex.Zhu@amd.com>
Wed, 18 Apr 2018 10:46:07 +0000 (18:46 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 15 May 2018 18:43:52 +0000 (13:43 -0500)
when bit14 in module parameter ppfeaturemask was set.
od feature will be enabled on Vega10 except vbios not support.

user can read od range by reading sysfs pp_od_clk_voltage,
cat pp_od_clk_voltage
OD_SCLK:
0:        852Mhz        800mV
1:        991Mhz        900mV
2:       1138Mhz        950mV
3:       1269Mhz       1000mV
4:       1348Mhz       1050mV
5:       1399Mhz       1100mV
6:       1440Mhz       1150mV
7:       1500Mhz       1200mV
OD_MCLK:
0:        167Mhz        800mV
1:        500Mhz        800mV
2:        800Mhz        950mV
3:        945Mhz       1000mV
OD_RANGE:
SCLK:     852MHz       2200MHz
MCLK:     167MHz       1500MHz
VDDC:     800mV        1200mV

and can configure the clock/voltage by writing pp_od_clk_voltage
for example:

echo "s 0 900 820">pp_od_clk_voltage to change the sclk/vddc
to 900MHz and 820 mV in dpm level0.

echo "r" to change the clk/voltage to  default value.

echo "c">pp_od_clk_voltage
to commit the change

v2: squash in warning fix (Alex)

Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Rex Zhu <Rex.Zhu@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h
drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h

index 384aa07..7486120 100644 (file)
@@ -285,6 +285,48 @@ static int vega10_set_features_platform_caps(struct pp_hwmgr *hwmgr)
        return 0;
 }
 
+static int vega10_odn_initial_default_setting(struct pp_hwmgr *hwmgr)
+{
+       struct vega10_hwmgr *data = hwmgr->backend;
+       struct phm_ppt_v2_information *table_info =
+                       (struct phm_ppt_v2_information *)(hwmgr->pptable);
+       struct vega10_odn_dpm_table *odn_table = &(data->odn_dpm_table);
+       struct vega10_odn_vddc_lookup_table *od_lookup_table;
+       struct phm_ppt_v1_voltage_lookup_table *vddc_lookup_table;
+       struct phm_ppt_v1_clock_voltage_dependency_table *dep_table[3];
+       struct phm_ppt_v1_clock_voltage_dependency_table *od_table[3];
+       uint32_t i;
+
+       od_lookup_table = &odn_table->vddc_lookup_table;
+       vddc_lookup_table = table_info->vddc_lookup_table;
+
+       for (i = 0; i < vddc_lookup_table->count; i++)
+               od_lookup_table->entries[i].us_vdd = vddc_lookup_table->entries[i].us_vdd;
+
+       od_lookup_table->count = vddc_lookup_table->count;
+
+       dep_table[0] = table_info->vdd_dep_on_sclk;
+       dep_table[1] = table_info->vdd_dep_on_mclk;
+       dep_table[2] = table_info->vdd_dep_on_socclk;
+       od_table[0] = (struct phm_ppt_v1_clock_voltage_dependency_table *)&odn_table->vdd_dep_on_sclk;
+       od_table[1] = (struct phm_ppt_v1_clock_voltage_dependency_table *)&odn_table->vdd_dep_on_mclk;
+       od_table[2] = (struct phm_ppt_v1_clock_voltage_dependency_table *)&odn_table->vdd_dep_on_socclk;
+
+       for (i = 0; i < 3; i++)
+               smu_get_voltage_dependency_table_ppt_v1(dep_table[i], od_table[i]);
+
+       if (odn_table->max_vddc == 0 || odn_table->max_vddc > 2000)
+               odn_table->max_vddc = dep_table[0]->entries[dep_table[0]->count - 1].vddc;
+       if (odn_table->min_vddc == 0 || odn_table->min_vddc > 2000)
+               odn_table->min_vddc = dep_table[0]->entries[0].vddc;
+
+       i = od_table[2]->count - 1;
+       od_table[2]->entries[i].clk = hwmgr->platform_descriptor.overdriveLimit.memoryClock;
+       od_table[2]->entries[i].vddc = odn_table->max_vddc;
+
+       return 0;
+}
+
 static void vega10_init_dpm_defaults(struct pp_hwmgr *hwmgr)
 {
        struct vega10_hwmgr *data = hwmgr->backend;
@@ -421,7 +463,6 @@ static void vega10_init_dpm_defaults(struct pp_hwmgr *hwmgr)
                /* ACG firmware has major version 5 */
        if ((hwmgr->smu_version & 0xff000000) == 0x5000000)
                data->smu_features[GNLD_ACG].supported = true;
-
        if (data->registry_data.didt_support)
                data->smu_features[GNLD_DIDT].supported = true;
 
@@ -1360,48 +1401,6 @@ static int vega10_setup_default_dpm_tables(struct pp_hwmgr *hwmgr)
        memcpy(&(data->golden_dpm_table), &(data->dpm_table),
                        sizeof(struct vega10_dpm_table));
 
-       if (PP_CAP(PHM_PlatformCaps_ODNinACSupport) ||
-           PP_CAP(PHM_PlatformCaps_ODNinDCSupport)) {
-               data->odn_dpm_table.odn_core_clock_dpm_levels.num_of_pl =
-                                               data->dpm_table.gfx_table.count;
-               for (i = 0; i < data->dpm_table.gfx_table.count; i++) {
-                       data->odn_dpm_table.odn_core_clock_dpm_levels.entries[i].clock =
-                                       data->dpm_table.gfx_table.dpm_levels[i].value;
-                       data->odn_dpm_table.odn_core_clock_dpm_levels.entries[i].enabled = true;
-               }
-
-               data->odn_dpm_table.vdd_dependency_on_sclk.count =
-                               dep_gfx_table->count;
-               for (i = 0; i < dep_gfx_table->count; i++) {
-                       data->odn_dpm_table.vdd_dependency_on_sclk.entries[i].clk =
-                                       dep_gfx_table->entries[i].clk;
-                       data->odn_dpm_table.vdd_dependency_on_sclk.entries[i].vddInd =
-                                       dep_gfx_table->entries[i].vddInd;
-                       data->odn_dpm_table.vdd_dependency_on_sclk.entries[i].cks_enable =
-                                       dep_gfx_table->entries[i].cks_enable;
-                       data->odn_dpm_table.vdd_dependency_on_sclk.entries[i].cks_voffset =
-                                       dep_gfx_table->entries[i].cks_voffset;
-               }
-
-               data->odn_dpm_table.odn_memory_clock_dpm_levels.num_of_pl =
-                                               data->dpm_table.mem_table.count;
-               for (i = 0; i < data->dpm_table.mem_table.count; i++) {
-                       data->odn_dpm_table.odn_memory_clock_dpm_levels.entries[i].clock =
-                                       data->dpm_table.mem_table.dpm_levels[i].value;
-                       data->odn_dpm_table.odn_memory_clock_dpm_levels.entries[i].enabled = true;
-               }
-
-               data->odn_dpm_table.vdd_dependency_on_mclk.count = dep_mclk_table->count;
-               for (i = 0; i < dep_mclk_table->count; i++) {
-                       data->odn_dpm_table.vdd_dependency_on_mclk.entries[i].clk =
-                                       dep_mclk_table->entries[i].clk;
-                       data->odn_dpm_table.vdd_dependency_on_mclk.entries[i].vddInd =
-                                       dep_mclk_table->entries[i].vddInd;
-                       data->odn_dpm_table.vdd_dependency_on_mclk.entries[i].vddci =
-                                       dep_mclk_table->entries[i].vddci;
-               }
-       }
-
        return 0;
 }
 
@@ -1504,18 +1503,18 @@ static int vega10_populate_single_gfx_level(struct pp_hwmgr *hwmgr,
 {
        struct phm_ppt_v2_information *table_info =
                        (struct phm_ppt_v2_information *)(hwmgr->pptable);
-       struct phm_ppt_v1_clock_voltage_dependency_table *dep_on_sclk =
-                       table_info->vdd_dep_on_sclk;
+       struct phm_ppt_v1_clock_voltage_dependency_table *dep_on_sclk;
        struct vega10_hwmgr *data = hwmgr->backend;
        struct pp_atomfwctrl_clock_dividers_soc15 dividers;
        uint32_t gfx_max_clock =
                        hwmgr->platform_descriptor.overdriveLimit.engineClock;
        uint32_t i = 0;
 
-       if (data->apply_overdrive_next_settings_mask &
-                       DPMTABLE_OD_UPDATE_VDDC)
+       if (hwmgr->od_enabled)
                dep_on_sclk = (struct phm_ppt_v1_clock_voltage_dependency_table *)
-                                               &(data->odn_dpm_table.vdd_dependency_on_sclk);
+                                               &(data->odn_dpm_table.vdd_dep_on_sclk);
+       else
+               dep_on_sclk = table_info->vdd_dep_on_sclk;
 
        PP_ASSERT_WITH_CODE(dep_on_sclk,
                        "Invalid SOC_VDD-GFX_CLK Dependency Table!",
@@ -1567,23 +1566,32 @@ static int vega10_populate_single_soc_level(struct pp_hwmgr *hwmgr,
                uint32_t soc_clock, uint8_t *current_soc_did,
                uint8_t *current_vol_index)
 {
+       struct vega10_hwmgr *data = hwmgr->backend;
        struct phm_ppt_v2_information *table_info =
                        (struct phm_ppt_v2_information *)(hwmgr->pptable);
-       struct phm_ppt_v1_clock_voltage_dependency_table *dep_on_soc =
-                       table_info->vdd_dep_on_socclk;
+       struct phm_ppt_v1_clock_voltage_dependency_table *dep_on_soc;
        struct pp_atomfwctrl_clock_dividers_soc15 dividers;
        uint32_t i;
 
-       PP_ASSERT_WITH_CODE(dep_on_soc,
-                       "Invalid SOC_VDD-SOC_CLK Dependency Table!",
-                       return -EINVAL);
-       for (i = 0; i < dep_on_soc->count; i++) {
-               if (dep_on_soc->entries[i].clk == soc_clock)
-                       break;
+       if (hwmgr->od_enabled) {
+               dep_on_soc = (struct phm_ppt_v1_clock_voltage_dependency_table *)
+                                               &data->odn_dpm_table.vdd_dep_on_socclk;
+               for (i = 0; i < dep_on_soc->count; i++) {
+                       if (dep_on_soc->entries[i].clk >= soc_clock)
+                               break;
+               }
+       } else {
+               dep_on_soc = table_info->vdd_dep_on_socclk;
+               for (i = 0; i < dep_on_soc->count; i++) {
+                       if (dep_on_soc->entries[i].clk == soc_clock)
+                               break;
+               }
        }
+
        PP_ASSERT_WITH_CODE(dep_on_soc->count > i,
                        "Cannot find SOC_CLK in SOC_VDD-SOC_CLK Dependency Table",
                        return -EINVAL);
+
        PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(hwmgr,
                        COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK,
                        soc_clock, &dividers),
@@ -1592,22 +1600,6 @@ static int vega10_populate_single_soc_level(struct pp_hwmgr *hwmgr,
 
        *current_soc_did = (uint8_t)dividers.ulDid;
        *current_vol_index = (uint8_t)(dep_on_soc->entries[i].vddInd);
-
-       return 0;
-}
-
-uint16_t vega10_locate_vddc_given_clock(struct pp_hwmgr *hwmgr,
-               uint32_t clk,
-               struct phm_ppt_v1_clock_voltage_dependency_table *dep_table)
-{
-       uint16_t i;
-
-       for (i = 0; i < dep_table->count; i++) {
-               if (dep_table->entries[i].clk == clk)
-                       return dep_table->entries[i].vddc;
-       }
-
-       pr_info("[LocateVddcGivenClock] Cannot locate SOC Vddc for this clock!");
        return 0;
 }
 
@@ -1621,8 +1613,6 @@ static int vega10_populate_all_graphic_levels(struct pp_hwmgr *hwmgr)
        struct vega10_hwmgr *data = hwmgr->backend;
        struct phm_ppt_v2_information *table_info =
                        (struct phm_ppt_v2_information *)(hwmgr->pptable);
-       struct phm_ppt_v1_clock_voltage_dependency_table *dep_table =
-                       table_info->vdd_dep_on_socclk;
        PPTable_t *pp_table = &(data->smc_state_table.pp_table);
        struct vega10_single_dpm_table *dpm_table = &(data->dpm_table.gfx_table);
        int result = 0;
@@ -1653,11 +1643,6 @@ static int vega10_populate_all_graphic_levels(struct pp_hwmgr *hwmgr)
 
        dpm_table = &(data->dpm_table.soc_table);
        for (i = 0; i < dpm_table->count; i++) {
-               pp_table->SocVid[i] =
-                               (uint8_t)convert_to_vid(
-                               vega10_locate_vddc_given_clock(hwmgr,
-                                               dpm_table->dpm_levels[i].value,
-                                               dep_table));
                result = vega10_populate_single_soc_level(hwmgr,
                                dpm_table->dpm_levels[i].value,
                                &(pp_table->SocclkDid[i]),
@@ -1668,7 +1653,6 @@ static int vega10_populate_all_graphic_levels(struct pp_hwmgr *hwmgr)
 
        j = i - 1;
        while (i < NUM_SOCCLK_DPM_LEVELS) {
-               pp_table->SocVid[i] = pp_table->SocVid[j];
                result = vega10_populate_single_soc_level(hwmgr,
                                dpm_table->dpm_levels[j].value,
                                &(pp_table->SocclkDid[i]),
@@ -1681,6 +1665,32 @@ static int vega10_populate_all_graphic_levels(struct pp_hwmgr *hwmgr)
        return result;
 }
 
+static void vega10_populate_vddc_soc_levels(struct pp_hwmgr *hwmgr)
+{
+       struct vega10_hwmgr *data = hwmgr->backend;
+       PPTable_t *pp_table = &(data->smc_state_table.pp_table);
+       struct phm_ppt_v2_information *table_info = hwmgr->pptable;
+       struct phm_ppt_v1_voltage_lookup_table *vddc_lookup_table;
+
+       uint8_t soc_vid = 0;
+       uint32_t i, max_vddc_level;
+
+       if (hwmgr->od_enabled)
+               vddc_lookup_table = (struct phm_ppt_v1_voltage_lookup_table *)&data->odn_dpm_table.vddc_lookup_table;
+       else
+               vddc_lookup_table = table_info->vddc_lookup_table;
+
+       max_vddc_level = vddc_lookup_table->count;
+       for (i = 0; i < max_vddc_level; i++) {
+               soc_vid = (uint8_t)convert_to_vid(vddc_lookup_table->entries[i].us_vdd);
+               pp_table->SocVid[i] = soc_vid;
+       }
+       while (i < MAX_REGULAR_DPM_NUMBER) {
+               pp_table->SocVid[i] = soc_vid;
+               i++;
+       }
+}
+
 /**
  * @brief Populates single SMC GFXCLK structure using the provided clock.
  *
@@ -1695,25 +1705,25 @@ static int vega10_populate_single_memory_level(struct pp_hwmgr *hwmgr,
        struct vega10_hwmgr *data = hwmgr->backend;
        struct phm_ppt_v2_information *table_info =
                        (struct phm_ppt_v2_information *)(hwmgr->pptable);
-       struct phm_ppt_v1_clock_voltage_dependency_table *dep_on_mclk =
-                       table_info->vdd_dep_on_mclk;
+       struct phm_ppt_v1_clock_voltage_dependency_table *dep_on_mclk;
        struct pp_atomfwctrl_clock_dividers_soc15 dividers;
        uint32_t mem_max_clock =
                        hwmgr->platform_descriptor.overdriveLimit.memoryClock;
        uint32_t i = 0;
 
-       if (data->apply_overdrive_next_settings_mask &
-                       DPMTABLE_OD_UPDATE_VDDC)
+       if (hwmgr->od_enabled)
                dep_on_mclk = (struct phm_ppt_v1_clock_voltage_dependency_table *)
-                                       &data->odn_dpm_table.vdd_dependency_on_mclk;
+                                       &data->odn_dpm_table.vdd_dep_on_mclk;
+       else
+               dep_on_mclk = table_info->vdd_dep_on_mclk;
 
        PP_ASSERT_WITH_CODE(dep_on_mclk,
                        "Invalid SOC_VDD-UCLK Dependency Table!",
                        return -EINVAL);
 
-       if (data->need_update_dpm_table & DPMTABLE_OD_UPDATE_MCLK)
+       if (data->need_update_dpm_table & DPMTABLE_OD_UPDATE_MCLK) {
                mem_clock = mem_clock > mem_max_clock ? mem_max_clock : mem_clock;
-       else {
+       else {
                for (i = 0; i < dep_on_mclk->count; i++) {
                        if (dep_on_mclk->entries[i].clk == mem_clock)
                                break;
@@ -2057,6 +2067,9 @@ static int vega10_populate_avfs_parameters(struct pp_hwmgr *hwmgr)
        if (data->smu_features[GNLD_AVFS].supported) {
                result = pp_atomfwctrl_get_avfs_information(hwmgr, &avfs_params);
                if (!result) {
+                       data->odn_dpm_table.max_vddc = avfs_params.ulMaxVddc;
+                       data->odn_dpm_table.min_vddc = avfs_params.ulMinVddc;
+
                        pp_table->MinVoltageVid = (uint8_t)
                                        convert_to_vid((uint16_t)(avfs_params.ulMinVddc));
                        pp_table->MaxVoltageVid = (uint8_t)
@@ -2335,6 +2348,22 @@ static int vega10_avfs_enable(struct pp_hwmgr *hwmgr, bool enable)
        return 0;
 }
 
+static int vega10_update_avfs(struct pp_hwmgr *hwmgr)
+{
+       struct vega10_hwmgr *data = hwmgr->backend;
+
+       if (data->need_update_dpm_table & DPMTABLE_OD_UPDATE_VDDC) {
+               vega10_avfs_enable(hwmgr, false);
+       } else if (data->need_update_dpm_table) {
+               vega10_avfs_enable(hwmgr, false);
+               vega10_avfs_enable(hwmgr, true);
+       } else {
+               vega10_avfs_enable(hwmgr, true);
+       }
+
+       return 0;
+}
+
 static int vega10_populate_and_upload_avfs_fuse_override(struct pp_hwmgr *hwmgr)
 {
        int result = 0;
@@ -2396,6 +2425,10 @@ static int vega10_init_smc_table(struct pp_hwmgr *hwmgr)
                        "Failed to setup default DPM tables!",
                        return result);
 
+       /* initialize ODN table */
+       if (hwmgr->od_enabled)
+               vega10_odn_initial_default_setting(hwmgr);
+
        pp_atomfwctrl_get_voltage_table_v4(hwmgr, VOLTAGE_TYPE_VDDC,
                        VOLTAGE_OBJ_SVID2,  &voltage_table);
        pp_table->MaxVidStep = voltage_table.max_vid_step;
@@ -2442,6 +2475,8 @@ static int vega10_init_smc_table(struct pp_hwmgr *hwmgr)
                        "Failed to initialize Memory Level!",
                        return result);
 
+       vega10_populate_vddc_soc_levels(hwmgr);
+
        result = vega10_populate_all_display_clock_levels(hwmgr);
        PP_ASSERT_WITH_CODE(!result,
                        "Failed to initialize Display Level!",
@@ -3164,82 +3199,11 @@ static int vega10_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
 
 static int vega10_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, const void *input)
 {
-       const struct phm_set_power_state_input *states =
-                       (const struct phm_set_power_state_input *)input;
-       const struct vega10_power_state *vega10_ps =
-                       cast_const_phw_vega10_power_state(states->pnew_state);
        struct vega10_hwmgr *data = hwmgr->backend;
-       struct vega10_single_dpm_table *sclk_table =
-                       &(data->dpm_table.gfx_table);
-       uint32_t sclk = vega10_ps->performance_levels
-                       [vega10_ps->performance_level_count - 1].gfx_clock;
-       struct vega10_single_dpm_table *mclk_table =
-                       &(data->dpm_table.mem_table);
-       uint32_t mclk = vega10_ps->performance_levels
-                       [vega10_ps->performance_level_count - 1].mem_clock;
-       struct PP_Clocks min_clocks = {0};
-       uint32_t i;
-
-       data->need_update_dpm_table = 0;
-
-       if (PP_CAP(PHM_PlatformCaps_ODNinACSupport) ||
-           PP_CAP(PHM_PlatformCaps_ODNinDCSupport)) {
-               for (i = 0; i < sclk_table->count; i++) {
-                       if (sclk == sclk_table->dpm_levels[i].value)
-                               break;
-               }
-
-               if (!(data->apply_overdrive_next_settings_mask &
-                               DPMTABLE_OD_UPDATE_SCLK) && i >= sclk_table->count) {
-                       /* Check SCLK in DAL's minimum clocks
-                        * in case DeepSleep divider update is required.
-                        */
-                       if (data->display_timing.min_clock_in_sr !=
-                                       min_clocks.engineClockInSR &&
-                               (min_clocks.engineClockInSR >=
-                                               VEGA10_MINIMUM_ENGINE_CLOCK ||
-                                       data->display_timing.min_clock_in_sr >=
-                                               VEGA10_MINIMUM_ENGINE_CLOCK))
-                               data->need_update_dpm_table |= DPMTABLE_UPDATE_SCLK;
-               }
-
-               if (data->display_timing.num_existing_displays !=
-                               hwmgr->display_config->num_display)
-                       data->need_update_dpm_table |= DPMTABLE_UPDATE_MCLK;
-       } else {
-               for (i = 0; i < sclk_table->count; i++) {
-                       if (sclk == sclk_table->dpm_levels[i].value)
-                               break;
-               }
-
-               if (i >= sclk_table->count)
-                       data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_SCLK;
-               else {
-                       /* Check SCLK in DAL's minimum clocks
-                        * in case DeepSleep divider update is required.
-                        */
-                       if (data->display_timing.min_clock_in_sr !=
-                                       min_clocks.engineClockInSR &&
-                               (min_clocks.engineClockInSR >=
-                                               VEGA10_MINIMUM_ENGINE_CLOCK ||
-                                       data->display_timing.min_clock_in_sr >=
-                                               VEGA10_MINIMUM_ENGINE_CLOCK))
-                               data->need_update_dpm_table |= DPMTABLE_UPDATE_SCLK;
-               }
 
-               for (i = 0; i < mclk_table->count; i++) {
-                       if (mclk == mclk_table->dpm_levels[i].value)
-                               break;
-               }
-
-               if (i >= mclk_table->count)
-                       data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_MCLK;
+       if (data->display_timing.num_existing_displays != hwmgr->display_config->num_display)
+               data->need_update_dpm_table |= DPMTABLE_UPDATE_MCLK;
 
-               if (data->display_timing.num_existing_displays !=
-                               hwmgr->display_config->num_display ||
-                               i >= mclk_table->count)
-                       data->need_update_dpm_table |= DPMTABLE_UPDATE_MCLK;
-       }
        return 0;
 }
 
@@ -3247,194 +3211,29 @@ static int vega10_populate_and_upload_sclk_mclk_dpm_levels(
                struct pp_hwmgr *hwmgr, const void *input)
 {
        int result = 0;
-       const struct phm_set_power_state_input *states =
-                       (const struct phm_set_power_state_input *)input;
-       const struct vega10_power_state *vega10_ps =
-                       cast_const_phw_vega10_power_state(states->pnew_state);
        struct vega10_hwmgr *data = hwmgr->backend;
-       uint32_t sclk = vega10_ps->performance_levels
-                       [vega10_ps->performance_level_count - 1].gfx_clock;
-       uint32_t mclk = vega10_ps->performance_levels
-                       [vega10_ps->performance_level_count - 1].mem_clock;
-       struct vega10_dpm_table *dpm_table = &data->dpm_table;
-       struct vega10_dpm_table *golden_dpm_table =
-                       &data->golden_dpm_table;
-       uint32_t dpm_count, clock_percent;
-       uint32_t i;
-
-       if (PP_CAP(PHM_PlatformCaps_ODNinACSupport) ||
-           PP_CAP(PHM_PlatformCaps_ODNinDCSupport)) {
-
-               if (!data->need_update_dpm_table &&
-                       !data->apply_optimized_settings &&
-                       !data->apply_overdrive_next_settings_mask)
-                       return 0;
 
-               if (data->apply_overdrive_next_settings_mask &
-                               DPMTABLE_OD_UPDATE_SCLK) {
-                       for (dpm_count = 0;
-                                       dpm_count < dpm_table->gfx_table.count;
-                                       dpm_count++) {
-                               dpm_table->gfx_table.dpm_levels[dpm_count].enabled =
-                                       data->odn_dpm_table.odn_core_clock_dpm_levels.entries[dpm_count].enabled;
-                               dpm_table->gfx_table.dpm_levels[dpm_count].value =
-                                       data->odn_dpm_table.odn_core_clock_dpm_levels.entries[dpm_count].clock;
-                       }
-               }
-
-               if (data->apply_overdrive_next_settings_mask &
-                               DPMTABLE_OD_UPDATE_MCLK) {
-                       for (dpm_count = 0;
-                                       dpm_count < dpm_table->mem_table.count;
-                                       dpm_count++) {
-                               dpm_table->mem_table.dpm_levels[dpm_count].enabled =
-                                       data->odn_dpm_table.odn_memory_clock_dpm_levels.entries[dpm_count].enabled;
-                               dpm_table->mem_table.dpm_levels[dpm_count].value =
-                                       data->odn_dpm_table.odn_memory_clock_dpm_levels.entries[dpm_count].clock;
-                       }
-               }
-
-               if ((data->need_update_dpm_table & DPMTABLE_UPDATE_SCLK) ||
-                       data->apply_optimized_settings ||
-                       (data->apply_overdrive_next_settings_mask &
-                                       DPMTABLE_OD_UPDATE_SCLK)) {
-                       result = vega10_populate_all_graphic_levels(hwmgr);
-                       PP_ASSERT_WITH_CODE(!result,
-                                       "Failed to populate SCLK during PopulateNewDPMClocksStates Function!",
-                                       return result);
-               }
-
-               if ((data->need_update_dpm_table & DPMTABLE_UPDATE_MCLK) ||
-                       (data->apply_overdrive_next_settings_mask &
-                                       DPMTABLE_OD_UPDATE_MCLK)){
-                       result = vega10_populate_all_memory_levels(hwmgr);
-                       PP_ASSERT_WITH_CODE(!result,
-                                       "Failed to populate MCLK during PopulateNewDPMClocksStates Function!",
-                                       return result);
-               }
-       } else {
-               if (!data->need_update_dpm_table &&
-                               !data->apply_optimized_settings)
-                       return 0;
-
-               if (data->need_update_dpm_table & DPMTABLE_OD_UPDATE_SCLK &&
-                               data->smu_features[GNLD_DPM_GFXCLK].supported) {
-                               dpm_table->
-                               gfx_table.dpm_levels[dpm_table->gfx_table.count - 1].
-                               value = sclk;
-                               if (hwmgr->od_enabled) {
-                                       /* Need to do calculation based on the golden DPM table
-                                        * as the Heatmap GPU Clock axis is also based on
-                                        * the default values
-                                        */
-                                       PP_ASSERT_WITH_CODE(
-                                                       golden_dpm_table->gfx_table.dpm_levels
-                                                       [golden_dpm_table->gfx_table.count - 1].value,
-                                                       "Divide by 0!",
-                                                       return -1);
-
-                                       dpm_count = dpm_table->gfx_table.count < 2 ?
-                                                       0 : dpm_table->gfx_table.count - 2;
-                                       for (i = dpm_count; i > 1; i--) {
-                                               if (sclk > golden_dpm_table->gfx_table.dpm_levels
-                                                       [golden_dpm_table->gfx_table.count - 1].value) {
-                                                       clock_percent =
-                                                               ((sclk - golden_dpm_table->gfx_table.dpm_levels
-                                                               [golden_dpm_table->gfx_table.count - 1].value) *
-                                                               100) /
-                                                               golden_dpm_table->gfx_table.dpm_levels
-                                                               [golden_dpm_table->gfx_table.count - 1].value;
-
-                                                       dpm_table->gfx_table.dpm_levels[i].value =
-                                                               golden_dpm_table->gfx_table.dpm_levels[i].value +
-                                                               (golden_dpm_table->gfx_table.dpm_levels[i].value *
-                                                               clock_percent) / 100;
-                                               } else if (golden_dpm_table->
-                                                               gfx_table.dpm_levels[dpm_table->gfx_table.count-1].value >
-                                                               sclk) {
-                                                       clock_percent =
-                                                               ((golden_dpm_table->gfx_table.dpm_levels
-                                                               [golden_dpm_table->gfx_table.count - 1].value -
-                                                               sclk) * 100) /
-                                                               golden_dpm_table->gfx_table.dpm_levels
-                                                               [golden_dpm_table->gfx_table.count-1].value;
-
-                                                       dpm_table->gfx_table.dpm_levels[i].value =
-                                                               golden_dpm_table->gfx_table.dpm_levels[i].value -
-                                                               (golden_dpm_table->gfx_table.dpm_levels[i].value *
-                                                               clock_percent) / 100;
-                                               } else
-                                                       dpm_table->gfx_table.dpm_levels[i].value =
-                                                               golden_dpm_table->gfx_table.dpm_levels[i].value;
-                                       }
-                               }
-                       }
-
-               if (data->need_update_dpm_table & DPMTABLE_OD_UPDATE_MCLK &&
-                               data->smu_features[GNLD_DPM_UCLK].supported) {
-                       dpm_table->
-                       mem_table.dpm_levels[dpm_table->mem_table.count - 1].
-                       value = mclk;
+       if (!data->need_update_dpm_table)
+               return 0;
 
-                       if (hwmgr->od_enabled) {
-                               PP_ASSERT_WITH_CODE(
-                                       golden_dpm_table->mem_table.dpm_levels
-                                       [golden_dpm_table->mem_table.count - 1].value,
-                                       "Divide by 0!",
-                                       return -1);
+       if (data->need_update_dpm_table &
+                       (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_UPDATE_SCLK + DPMTABLE_UPDATE_SOCCLK)) {
+               result = vega10_populate_all_graphic_levels(hwmgr);
+               PP_ASSERT_WITH_CODE((0 == result),
+                               "Failed to populate SCLK during PopulateNewDPMClocksStates Function!",
+                               return result);
+       }
 
-                               dpm_count = dpm_table->mem_table.count < 2 ?
-                                               0 : dpm_table->mem_table.count - 2;
-                               for (i = dpm_count; i > 1; i--) {
-                                       if (mclk > golden_dpm_table->mem_table.dpm_levels
-                                               [golden_dpm_table->mem_table.count-1].value) {
-                                               clock_percent = ((mclk -
-                                                       golden_dpm_table->mem_table.dpm_levels
-                                                       [golden_dpm_table->mem_table.count-1].value) *
-                                                       100) /
-                                                       golden_dpm_table->mem_table.dpm_levels
-                                                       [golden_dpm_table->mem_table.count-1].value;
-
-                                               dpm_table->mem_table.dpm_levels[i].value =
-                                                       golden_dpm_table->mem_table.dpm_levels[i].value +
-                                                       (golden_dpm_table->mem_table.dpm_levels[i].value *
-                                                       clock_percent) / 100;
-                                       } else if (golden_dpm_table->mem_table.dpm_levels
-                                                       [dpm_table->mem_table.count-1].value > mclk) {
-                                               clock_percent = ((golden_dpm_table->mem_table.dpm_levels
-                                                       [golden_dpm_table->mem_table.count-1].value - mclk) *
-                                                       100) /
-                                                       golden_dpm_table->mem_table.dpm_levels
-                                                       [golden_dpm_table->mem_table.count-1].value;
-
-                                               dpm_table->mem_table.dpm_levels[i].value =
-                                                       golden_dpm_table->mem_table.dpm_levels[i].value -
-                                                       (golden_dpm_table->mem_table.dpm_levels[i].value *
-                                                       clock_percent) / 100;
-                                       } else
-                                               dpm_table->mem_table.dpm_levels[i].value =
-                                                       golden_dpm_table->mem_table.dpm_levels[i].value;
-                               }
-                       }
-               }
+       if (data->need_update_dpm_table &
+                       (DPMTABLE_OD_UPDATE_MCLK + DPMTABLE_UPDATE_MCLK)) {
+               result = vega10_populate_all_memory_levels(hwmgr);
+               PP_ASSERT_WITH_CODE((0 == result),
+                               "Failed to populate MCLK during PopulateNewDPMClocksStates Function!",
+                               return result);
+       }
 
-               if ((data->need_update_dpm_table &
-                       (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_UPDATE_SCLK)) ||
-                       data->apply_optimized_settings) {
-                       result = vega10_populate_all_graphic_levels(hwmgr);
-                       PP_ASSERT_WITH_CODE(!result,
-                                       "Failed to populate SCLK during PopulateNewDPMClocksStates Function!",
-                                       return result);
-               }
+       vega10_populate_vddc_soc_levels(hwmgr);
 
-               if (data->need_update_dpm_table &
-                               (DPMTABLE_OD_UPDATE_MCLK + DPMTABLE_UPDATE_MCLK)) {
-                       result = vega10_populate_all_memory_levels(hwmgr);
-                       PP_ASSERT_WITH_CODE(!result,
-                                       "Failed to populate MCLK during PopulateNewDPMClocksStates Function!",
-                                       return result);
-               }
-       }
        return result;
 }
 
@@ -3730,8 +3529,9 @@ static int vega10_set_power_state_tasks(struct pp_hwmgr *hwmgr,
        PP_ASSERT_WITH_CODE(!result,
                        "Failed to upload PPtable!", return result);
 
-       data->apply_optimized_settings = false;
-       data->apply_overdrive_next_settings_mask = 0;
+       vega10_update_avfs(hwmgr);
+
+       data->need_update_dpm_table &= DPMTABLE_OD_UPDATE_VDDC;
 
        return 0;
 }
@@ -4383,6 +4183,8 @@ static int vega10_print_clock_levels(struct pp_hwmgr *hwmgr,
        struct vega10_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table);
        struct vega10_single_dpm_table *mclk_table = &(data->dpm_table.mem_table);
        struct vega10_pcie_table *pcie_table = &(data->dpm_table.pcie_table);
+       struct vega10_odn_clock_voltage_dependency_table *podn_vdd_dep = NULL;
+
        int i, now, size = 0;
 
        switch (type) {
@@ -4421,6 +4223,40 @@ static int vega10_print_clock_levels(struct pp_hwmgr *hwmgr,
                                        (pcie_table->pcie_gen[i] == 2) ? "8.0GT/s, x16" : "",
                                        (i == now) ? "*" : "");
                break;
+       case OD_SCLK:
+               if (hwmgr->od_enabled) {
+                       size = sprintf(buf, "%s:\n", "OD_SCLK");
+                       podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_sclk;
+                       for (i = 0; i < podn_vdd_dep->count; i++)
+                               size += sprintf(buf + size, "%d: %10uMhz %10umV\n",
+                                       i, podn_vdd_dep->entries[i].clk / 100,
+                                               podn_vdd_dep->entries[i].vddc);
+               }
+               break;
+       case OD_MCLK:
+               if (hwmgr->od_enabled) {
+                       size = sprintf(buf, "%s:\n", "OD_MCLK");
+                       podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_mclk;
+                       for (i = 0; i < podn_vdd_dep->count; i++)
+                               size += sprintf(buf + size, "%d: %10uMhz %10umV\n",
+                                       i, podn_vdd_dep->entries[i].clk/100,
+                                               podn_vdd_dep->entries[i].vddc);
+               }
+               break;
+       case OD_RANGE:
+               if (hwmgr->od_enabled) {
+                       size = sprintf(buf, "%s:\n", "OD_RANGE");
+                       size += sprintf(buf + size, "SCLK: %7uMHz %10uMHz\n",
+                               data->golden_dpm_table.gfx_table.dpm_levels[0].value/100,
+                               hwmgr->platform_descriptor.overdriveLimit.engineClock/100);
+                       size += sprintf(buf + size, "MCLK: %7uMHz %10uMHz\n",
+                               data->golden_dpm_table.mem_table.dpm_levels[0].value/100,
+                               hwmgr->platform_descriptor.overdriveLimit.memoryClock/100);
+                       size += sprintf(buf + size, "VDDC: %7umV %11umV\n",
+                               data->odn_dpm_table.min_vddc,
+                               data->odn_dpm_table.max_vddc);
+               }
+               break;
        default:
                break;
        }
@@ -4808,6 +4644,200 @@ static int vega10_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, ui
        return 0;
 }
 
+
+static bool vega10_check_clk_voltage_valid(struct pp_hwmgr *hwmgr,
+                                       enum PP_OD_DPM_TABLE_COMMAND type,
+                                       uint32_t clk,
+                                       uint32_t voltage)
+{
+       struct vega10_hwmgr *data = hwmgr->backend;
+       struct vega10_odn_dpm_table *odn_table = &(data->odn_dpm_table);
+       struct vega10_single_dpm_table *golden_table;
+
+       if (voltage < odn_table->min_vddc || voltage > odn_table->max_vddc) {
+               pr_info("OD voltage is out of range [%d - %d] mV\n", odn_table->min_vddc, odn_table->max_vddc);
+               return false;
+       }
+
+       if (type == PP_OD_EDIT_SCLK_VDDC_TABLE) {
+               golden_table = &(data->golden_dpm_table.gfx_table);
+               if (golden_table->dpm_levels[0].value > clk ||
+                       hwmgr->platform_descriptor.overdriveLimit.engineClock < clk) {
+                       pr_info("OD engine clock is out of range [%d - %d] MHz\n",
+                               golden_table->dpm_levels[0].value/100,
+                               hwmgr->platform_descriptor.overdriveLimit.engineClock/100);
+                       return false;
+               }
+       } else if (type == PP_OD_EDIT_MCLK_VDDC_TABLE) {
+               golden_table = &(data->golden_dpm_table.mem_table);
+               if (golden_table->dpm_levels[0].value > clk ||
+                       hwmgr->platform_descriptor.overdriveLimit.memoryClock < clk) {
+                       pr_info("OD memory clock is out of range [%d - %d] MHz\n",
+                               golden_table->dpm_levels[0].value/100,
+                               hwmgr->platform_descriptor.overdriveLimit.memoryClock/100);
+                       return false;
+               }
+       } else {
+               return false;
+       }
+
+       return true;
+}
+
+static void vega10_check_dpm_table_updated(struct pp_hwmgr *hwmgr)
+{
+       struct vega10_hwmgr *data = hwmgr->backend;
+       struct vega10_odn_dpm_table *odn_table = &(data->odn_dpm_table);
+       struct phm_ppt_v2_information *table_info = hwmgr->pptable;
+       struct phm_ppt_v1_clock_voltage_dependency_table *dep_table;
+       struct phm_ppt_v1_clock_voltage_dependency_table *odn_dep_table;
+       uint32_t i;
+
+       dep_table = table_info->vdd_dep_on_mclk;
+       odn_dep_table = (struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dep_on_mclk);
+
+       for (i = 0; i < dep_table->count; i++) {
+               if (dep_table->entries[i].vddc != odn_dep_table->entries[i].vddc) {
+                       data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_VDDC | DPMTABLE_OD_UPDATE_MCLK;
+                       return;
+               }
+       }
+
+       dep_table = table_info->vdd_dep_on_sclk;
+       odn_dep_table = (struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dep_on_sclk);
+       for (i = 0; i < dep_table->count; i++) {
+               if (dep_table->entries[i].vddc != odn_dep_table->entries[i].vddc) {
+                       data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_VDDC | DPMTABLE_OD_UPDATE_SCLK;
+                       return;
+               }
+       }
+
+       if (data->need_update_dpm_table & DPMTABLE_OD_UPDATE_VDDC) {
+               data->need_update_dpm_table &= ~DPMTABLE_OD_UPDATE_VDDC;
+               data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_SCLK | DPMTABLE_OD_UPDATE_MCLK;
+       }
+}
+
+static void vega10_odn_update_soc_table(struct pp_hwmgr *hwmgr,
+                                               enum PP_OD_DPM_TABLE_COMMAND type)
+{
+       struct vega10_hwmgr *data = hwmgr->backend;
+       struct phm_ppt_v2_information *table_info = hwmgr->pptable;
+       struct phm_ppt_v1_clock_voltage_dependency_table *dep_table = table_info->vdd_dep_on_socclk;
+       struct vega10_single_dpm_table *dpm_table = &data->golden_dpm_table.soc_table;
+
+       struct vega10_odn_clock_voltage_dependency_table *podn_vdd_dep_on_socclk =
+                                                       &data->odn_dpm_table.vdd_dep_on_socclk;
+       struct vega10_odn_vddc_lookup_table *od_vddc_lookup_table = &data->odn_dpm_table.vddc_lookup_table;
+
+       struct vega10_odn_clock_voltage_dependency_table *podn_vdd_dep;
+       uint8_t i, j;
+
+       if (type == PP_OD_EDIT_SCLK_VDDC_TABLE) {
+               podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_sclk;
+               for (i = 0; i < podn_vdd_dep->count - 1; i++)
+                       od_vddc_lookup_table->entries[i].us_vdd = podn_vdd_dep->entries[i].vddc;
+               if (od_vddc_lookup_table->entries[i].us_vdd < podn_vdd_dep->entries[i].vddc)
+                       od_vddc_lookup_table->entries[i].us_vdd = podn_vdd_dep->entries[i].vddc;
+       } else if (type == PP_OD_EDIT_MCLK_VDDC_TABLE) {
+               podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_mclk;
+               for (i = 0; i < dpm_table->count; i++) {
+                       for (j = 0; j < od_vddc_lookup_table->count; j++) {
+                               if (od_vddc_lookup_table->entries[j].us_vdd >
+                                       podn_vdd_dep->entries[i].vddc)
+                                       break;
+                       }
+                       if (j == od_vddc_lookup_table->count) {
+                               od_vddc_lookup_table->entries[j-1].us_vdd =
+                                       podn_vdd_dep->entries[i].vddc;
+                               data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_VDDC;
+                       }
+                       podn_vdd_dep->entries[i].vddInd = j;
+               }
+               dpm_table = &data->dpm_table.soc_table;
+               for (i = 0; i < dep_table->count; i++) {
+                       if (dep_table->entries[i].vddInd == podn_vdd_dep->entries[dep_table->count-1].vddInd &&
+                                       dep_table->entries[i].clk < podn_vdd_dep->entries[dep_table->count-1].clk) {
+                               data->need_update_dpm_table |= DPMTABLE_UPDATE_SOCCLK;
+                               podn_vdd_dep_on_socclk->entries[i].clk = podn_vdd_dep->entries[dep_table->count-1].clk;
+                               dpm_table->dpm_levels[i].value = podn_vdd_dep_on_socclk->entries[i].clk;
+                       }
+               }
+               if (podn_vdd_dep_on_socclk->entries[podn_vdd_dep_on_socclk->count - 1].clk <
+                                       podn_vdd_dep->entries[dep_table->count-1].clk) {
+                       data->need_update_dpm_table |= DPMTABLE_UPDATE_SOCCLK;
+                       podn_vdd_dep_on_socclk->entries[podn_vdd_dep_on_socclk->count - 1].clk = podn_vdd_dep->entries[dep_table->count-1].clk;
+                       dpm_table->dpm_levels[podn_vdd_dep_on_socclk->count - 1].value = podn_vdd_dep->entries[dep_table->count-1].clk;
+               }
+               if (podn_vdd_dep_on_socclk->entries[podn_vdd_dep_on_socclk->count - 1].vddInd <
+                                       podn_vdd_dep->entries[dep_table->count-1].vddInd) {
+                       data->need_update_dpm_table |= DPMTABLE_UPDATE_SOCCLK;
+                       podn_vdd_dep_on_socclk->entries[podn_vdd_dep_on_socclk->count - 1].vddInd = podn_vdd_dep->entries[dep_table->count-1].vddInd;
+               }
+       }
+}
+
+static int vega10_odn_edit_dpm_table(struct pp_hwmgr *hwmgr,
+                                       enum PP_OD_DPM_TABLE_COMMAND type,
+                                       long *input, uint32_t size)
+{
+       struct vega10_hwmgr *data = hwmgr->backend;
+       struct vega10_odn_clock_voltage_dependency_table *podn_vdd_dep_table;
+       struct vega10_single_dpm_table *dpm_table;
+
+       uint32_t input_clk;
+       uint32_t input_vol;
+       uint32_t input_level;
+       uint32_t i;
+
+       PP_ASSERT_WITH_CODE(input, "NULL user input for clock and voltage",
+                               return -EINVAL);
+
+       if (!hwmgr->od_enabled) {
+               pr_info("OverDrive feature not enabled\n");
+               return -EINVAL;
+       }
+
+       if (PP_OD_EDIT_SCLK_VDDC_TABLE == type) {
+               dpm_table = &data->dpm_table.gfx_table;
+               podn_vdd_dep_table = &data->odn_dpm_table.vdd_dep_on_sclk;
+               data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_SCLK;
+       } else if (PP_OD_EDIT_MCLK_VDDC_TABLE == type) {
+               dpm_table = &data->dpm_table.mem_table;
+               podn_vdd_dep_table = &data->odn_dpm_table.vdd_dep_on_mclk;
+               data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_MCLK;
+       } else if (PP_OD_RESTORE_DEFAULT_TABLE == type) {
+               memcpy(&(data->dpm_table), &(data->golden_dpm_table), sizeof(struct vega10_dpm_table));
+               vega10_odn_initial_default_setting(hwmgr);
+               return 0;
+       } else if (PP_OD_COMMIT_DPM_TABLE == type) {
+               vega10_check_dpm_table_updated(hwmgr);
+               return 0;
+       } else {
+               return -EINVAL;
+       }
+
+       for (i = 0; i < size; i += 3) {
+               if (i + 3 > size || input[i] >= podn_vdd_dep_table->count) {
+                       pr_info("invalid clock voltage input\n");
+                       return 0;
+               }
+               input_level = input[i];
+               input_clk = input[i+1] * 100;
+               input_vol = input[i+2];
+
+               if (vega10_check_clk_voltage_valid(hwmgr, type, input_clk, input_vol)) {
+                       dpm_table->dpm_levels[input_level].value = input_clk;
+                       podn_vdd_dep_table->entries[input_level].clk = input_clk;
+                       podn_vdd_dep_table->entries[input_level].vddc = input_vol;
+               } else {
+                       return -EINVAL;
+               }
+       }
+       vega10_odn_update_soc_table(hwmgr, type);
+       return 0;
+}
+
 static const struct pp_hwmgr_func vega10_hwmgr_funcs = {
        .backend_init = vega10_hwmgr_backend_init,
        .backend_fini = vega10_hwmgr_backend_fini,
@@ -4866,6 +4896,7 @@ static const struct pp_hwmgr_func vega10_hwmgr_funcs = {
        .get_power_profile_mode = vega10_get_power_profile_mode,
        .set_power_profile_mode = vega10_set_power_profile_mode,
        .set_power_limit = vega10_set_power_limit,
+       .odn_edit_dpm_table = vega10_odn_edit_dpm_table,
 };
 
 int vega10_enable_smc_features(struct pp_hwmgr *hwmgr,
index 5339ea1..aadd6cb 100644 (file)
@@ -282,15 +282,21 @@ struct vega10_registry_data {
 
 struct vega10_odn_clock_voltage_dependency_table {
        uint32_t count;
-       struct phm_ppt_v1_clock_voltage_dependency_record
-               entries[MAX_REGULAR_DPM_NUMBER];
+       struct phm_ppt_v1_clock_voltage_dependency_record entries[MAX_REGULAR_DPM_NUMBER];
+};
+
+struct vega10_odn_vddc_lookup_table {
+       uint32_t count;
+       struct phm_ppt_v1_voltage_lookup_record entries[MAX_REGULAR_DPM_NUMBER];
 };
 
 struct vega10_odn_dpm_table {
-       struct phm_odn_clock_levels             odn_core_clock_dpm_levels;
-       struct phm_odn_clock_levels             odn_memory_clock_dpm_levels;
-       struct vega10_odn_clock_voltage_dependency_table                vdd_dependency_on_sclk;
-       struct vega10_odn_clock_voltage_dependency_table                vdd_dependency_on_mclk;
+       struct vega10_odn_clock_voltage_dependency_table vdd_dep_on_sclk;
+       struct vega10_odn_clock_voltage_dependency_table vdd_dep_on_mclk;
+       struct vega10_odn_clock_voltage_dependency_table vdd_dep_on_socclk;
+       struct vega10_odn_vddc_lookup_table vddc_lookup_table;
+       uint32_t max_vddc;
+       uint32_t min_vddc;
 };
 
 struct vega10_odn_fan_table {
@@ -301,8 +307,8 @@ struct vega10_odn_fan_table {
 };
 
 struct vega10_hwmgr {
-       struct vega10_dpm_table                 dpm_table;
-       struct vega10_dpm_table                 golden_dpm_table;
+       struct vega10_dpm_table          dpm_table;
+       struct vega10_dpm_table          golden_dpm_table;
        struct vega10_registry_data      registry_data;
        struct vega10_vbios_boot_state   vbios_boot_state;
        struct vega10_mclk_latency_table mclk_latency_table;
@@ -368,12 +374,8 @@ struct vega10_hwmgr {
        bool                           need_long_memory_training;
 
        /* Internal settings to apply the application power optimization parameters */
-       bool                           apply_optimized_settings;
        uint32_t                       disable_dpm_mask;
 
-       /* ---- Overdrive next setting ---- */
-       uint32_t                       apply_overdrive_next_settings_mask;
-
        /* ---- SMU9 ---- */
        struct smu_features            smu_features[GNLD_FEATURES_MAX];
        struct vega10_smc_state_table  smc_state_table;
index 8b78bbe..9bb8785 100644 (file)
@@ -377,11 +377,7 @@ struct phm_clocks {
 #define DPMTABLE_UPDATE_SCLK        0x00000004
 #define DPMTABLE_UPDATE_MCLK        0x00000008
 #define DPMTABLE_OD_UPDATE_VDDC     0x00000010
-
-/* To determine if sclk and mclk are in overdrive state */
-#define SCLK_OVERDRIVE_ENABLED           0x00000001
-#define MCLK_OVERDRIVE_ENABLED           0x00000002
-#define VDDC_OVERDRIVE_ENABLED           0x00000010
+#define DPMTABLE_UPDATE_SOCCLK      0x00000020
 
 struct phm_odn_performance_level {
        uint32_t clock;