[PATCH] drm/amd/pp: Add OVERDRIVE support on Vega10

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Apr 23, 2018 at 6:14 AM, Rex Zhu <Rex.Zhu at amd.com> wrote:
> 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
>
> Signed-off-by: Rex Zhu <Rex.Zhu at amd.com>

Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

> ---
>  drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c | 719 +++++++++++----------
>  drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h |  25 +-
>  .../gpu/drm/amd/powerplay/inc/hardwaremanager.h    |   6 +-
>  3 files changed, 389 insertions(+), 361 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
> index 384aa07..99d5974 100644
> --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
> +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
> @@ -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;
> +       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,
> +                               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 int vega10_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, ui
>         .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,
> diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h
> index 5339ea1..07910ed 100644
> --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h
> +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h
> @@ -282,15 +282,20 @@ 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 +306,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 +373,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;
> diff --git a/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h b/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h
> index 8b78bbe..9bb8785 100644
> --- a/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h
> +++ b/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h
> @@ -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;
> --
> 1.9.1
>
> _______________________________________________
> amd-gfx mailing list
> amd-gfx at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/amd-gfx


[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux