linux/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c
<<
>>
Prefs
   1/*
   2 * Copyright 2018 Advanced Micro Devices, Inc.
   3 *
   4 * Permission is hereby granted, free of charge, to any person obtaining a
   5 * copy of this software and associated documentation files (the "Software"),
   6 * to deal in the Software without restriction, including without limitation
   7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8 * and/or sell copies of the Software, and to permit persons to whom the
   9 * Software is furnished to do so, subject to the following conditions:
  10 *
  11 * The above copyright notice and this permission notice shall be included in
  12 * all copies or substantial portions of the Software.
  13 *
  14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20 * OTHER DEALINGS IN THE SOFTWARE.
  21 *
  22 * Authors: AMD
  23 */
  24#include <linux/string.h>
  25#include <linux/acpi.h>
  26
  27#include <drm/drmP.h>
  28#include <drm/drm_crtc_helper.h>
  29#include <drm/amdgpu_drm.h>
  30#include "dm_services.h"
  31#include "amdgpu.h"
  32#include "amdgpu_dm.h"
  33#include "amdgpu_dm_irq.h"
  34#include "amdgpu_pm.h"
  35#include "dm_pp_smu.h"
  36
  37
  38bool dm_pp_apply_display_requirements(
  39                const struct dc_context *ctx,
  40                const struct dm_pp_display_configuration *pp_display_cfg)
  41{
  42        struct amdgpu_device *adev = ctx->driver_context;
  43        int i;
  44
  45        if (adev->pm.dpm_enabled) {
  46
  47                memset(&adev->pm.pm_display_cfg, 0,
  48                                sizeof(adev->pm.pm_display_cfg));
  49
  50                adev->pm.pm_display_cfg.cpu_cc6_disable =
  51                        pp_display_cfg->cpu_cc6_disable;
  52
  53                adev->pm.pm_display_cfg.cpu_pstate_disable =
  54                        pp_display_cfg->cpu_pstate_disable;
  55
  56                adev->pm.pm_display_cfg.cpu_pstate_separation_time =
  57                        pp_display_cfg->cpu_pstate_separation_time;
  58
  59                adev->pm.pm_display_cfg.nb_pstate_switch_disable =
  60                        pp_display_cfg->nb_pstate_switch_disable;
  61
  62                adev->pm.pm_display_cfg.num_display =
  63                                pp_display_cfg->display_count;
  64                adev->pm.pm_display_cfg.num_path_including_non_display =
  65                                pp_display_cfg->display_count;
  66
  67                adev->pm.pm_display_cfg.min_core_set_clock =
  68                                pp_display_cfg->min_engine_clock_khz/10;
  69                adev->pm.pm_display_cfg.min_core_set_clock_in_sr =
  70                                pp_display_cfg->min_engine_clock_deep_sleep_khz/10;
  71                adev->pm.pm_display_cfg.min_mem_set_clock =
  72                                pp_display_cfg->min_memory_clock_khz/10;
  73
  74                adev->pm.pm_display_cfg.min_dcef_deep_sleep_set_clk =
  75                                pp_display_cfg->min_engine_clock_deep_sleep_khz/10;
  76                adev->pm.pm_display_cfg.min_dcef_set_clk =
  77                                pp_display_cfg->min_dcfclock_khz/10;
  78
  79                adev->pm.pm_display_cfg.multi_monitor_in_sync =
  80                                pp_display_cfg->all_displays_in_sync;
  81                adev->pm.pm_display_cfg.min_vblank_time =
  82                                pp_display_cfg->avail_mclk_switch_time_us;
  83
  84                adev->pm.pm_display_cfg.display_clk =
  85                                pp_display_cfg->disp_clk_khz/10;
  86
  87                adev->pm.pm_display_cfg.dce_tolerable_mclk_in_active_latency =
  88                                pp_display_cfg->avail_mclk_switch_time_in_disp_active_us;
  89
  90                adev->pm.pm_display_cfg.crtc_index = pp_display_cfg->crtc_index;
  91                adev->pm.pm_display_cfg.line_time_in_us =
  92                                pp_display_cfg->line_time_in_us;
  93
  94                adev->pm.pm_display_cfg.vrefresh = pp_display_cfg->disp_configs[0].v_refresh;
  95                adev->pm.pm_display_cfg.crossfire_display_index = -1;
  96                adev->pm.pm_display_cfg.min_bus_bandwidth = 0;
  97
  98                for (i = 0; i < pp_display_cfg->display_count; i++) {
  99                        const struct dm_pp_single_disp_config *dc_cfg =
 100                                                &pp_display_cfg->disp_configs[i];
 101                        adev->pm.pm_display_cfg.displays[i].controller_id = dc_cfg->pipe_idx + 1;
 102                }
 103
 104                /* TODO: complete implementation of
 105                 * pp_display_configuration_change().
 106                 * Follow example of:
 107                 * PHM_StoreDALConfigurationData - powerplay\hwmgr\hardwaremanager.c
 108                 * PP_IRI_DisplayConfigurationChange - powerplay\eventmgr\iri.c */
 109                if (adev->powerplay.pp_funcs->display_configuration_change)
 110                        adev->powerplay.pp_funcs->display_configuration_change(
 111                                adev->powerplay.pp_handle,
 112                                &adev->pm.pm_display_cfg);
 113
 114                /* TODO: replace by a separate call to 'apply display cfg'? */
 115                amdgpu_pm_compute_clocks(adev);
 116        }
 117
 118        return true;
 119}
 120
 121static void get_default_clock_levels(
 122                enum dm_pp_clock_type clk_type,
 123                struct dm_pp_clock_levels *clks)
 124{
 125        uint32_t disp_clks_in_khz[6] = {
 126                        300000, 400000, 496560, 626090, 685720, 757900 };
 127        uint32_t sclks_in_khz[6] = {
 128                        300000, 360000, 423530, 514290, 626090, 720000 };
 129        uint32_t mclks_in_khz[2] = { 333000, 800000 };
 130
 131        switch (clk_type) {
 132        case DM_PP_CLOCK_TYPE_DISPLAY_CLK:
 133                clks->num_levels = 6;
 134                memmove(clks->clocks_in_khz, disp_clks_in_khz,
 135                                sizeof(disp_clks_in_khz));
 136                break;
 137        case DM_PP_CLOCK_TYPE_ENGINE_CLK:
 138                clks->num_levels = 6;
 139                memmove(clks->clocks_in_khz, sclks_in_khz,
 140                                sizeof(sclks_in_khz));
 141                break;
 142        case DM_PP_CLOCK_TYPE_MEMORY_CLK:
 143                clks->num_levels = 2;
 144                memmove(clks->clocks_in_khz, mclks_in_khz,
 145                                sizeof(mclks_in_khz));
 146                break;
 147        default:
 148                clks->num_levels = 0;
 149                break;
 150        }
 151}
 152
 153static enum amd_pp_clock_type dc_to_pp_clock_type(
 154                enum dm_pp_clock_type dm_pp_clk_type)
 155{
 156        enum amd_pp_clock_type amd_pp_clk_type = 0;
 157
 158        switch (dm_pp_clk_type) {
 159        case DM_PP_CLOCK_TYPE_DISPLAY_CLK:
 160                amd_pp_clk_type = amd_pp_disp_clock;
 161                break;
 162        case DM_PP_CLOCK_TYPE_ENGINE_CLK:
 163                amd_pp_clk_type = amd_pp_sys_clock;
 164                break;
 165        case DM_PP_CLOCK_TYPE_MEMORY_CLK:
 166                amd_pp_clk_type = amd_pp_mem_clock;
 167                break;
 168        case DM_PP_CLOCK_TYPE_DCEFCLK:
 169                amd_pp_clk_type  = amd_pp_dcef_clock;
 170                break;
 171        case DM_PP_CLOCK_TYPE_DCFCLK:
 172                amd_pp_clk_type = amd_pp_dcf_clock;
 173                break;
 174        case DM_PP_CLOCK_TYPE_PIXELCLK:
 175                amd_pp_clk_type = amd_pp_pixel_clock;
 176                break;
 177        case DM_PP_CLOCK_TYPE_FCLK:
 178                amd_pp_clk_type = amd_pp_f_clock;
 179                break;
 180        case DM_PP_CLOCK_TYPE_DISPLAYPHYCLK:
 181                amd_pp_clk_type = amd_pp_phy_clock;
 182                break;
 183        case DM_PP_CLOCK_TYPE_DPPCLK:
 184                amd_pp_clk_type = amd_pp_dpp_clock;
 185                break;
 186        default:
 187                DRM_ERROR("DM_PPLIB: invalid clock type: %d!\n",
 188                                dm_pp_clk_type);
 189                break;
 190        }
 191
 192        return amd_pp_clk_type;
 193}
 194
 195static enum dm_pp_clocks_state pp_to_dc_powerlevel_state(
 196                        enum PP_DAL_POWERLEVEL max_clocks_state)
 197{
 198        switch (max_clocks_state) {
 199        case PP_DAL_POWERLEVEL_0:
 200                return DM_PP_CLOCKS_DPM_STATE_LEVEL_0;
 201        case PP_DAL_POWERLEVEL_1:
 202                return DM_PP_CLOCKS_DPM_STATE_LEVEL_1;
 203        case PP_DAL_POWERLEVEL_2:
 204                return DM_PP_CLOCKS_DPM_STATE_LEVEL_2;
 205        case PP_DAL_POWERLEVEL_3:
 206                return DM_PP_CLOCKS_DPM_STATE_LEVEL_3;
 207        case PP_DAL_POWERLEVEL_4:
 208                return DM_PP_CLOCKS_DPM_STATE_LEVEL_4;
 209        case PP_DAL_POWERLEVEL_5:
 210                return DM_PP_CLOCKS_DPM_STATE_LEVEL_5;
 211        case PP_DAL_POWERLEVEL_6:
 212                return DM_PP_CLOCKS_DPM_STATE_LEVEL_6;
 213        case PP_DAL_POWERLEVEL_7:
 214                return DM_PP_CLOCKS_DPM_STATE_LEVEL_7;
 215        default:
 216                DRM_ERROR("DM_PPLIB: invalid powerlevel state: %d!\n",
 217                                max_clocks_state);
 218                return DM_PP_CLOCKS_STATE_INVALID;
 219        }
 220}
 221
 222static void pp_to_dc_clock_levels(
 223                const struct amd_pp_clocks *pp_clks,
 224                struct dm_pp_clock_levels *dc_clks,
 225                enum dm_pp_clock_type dc_clk_type)
 226{
 227        uint32_t i;
 228
 229        if (pp_clks->count > DM_PP_MAX_CLOCK_LEVELS) {
 230                DRM_INFO("DM_PPLIB: Warning: %s clock: number of levels %d exceeds maximum of %d!\n",
 231                                DC_DECODE_PP_CLOCK_TYPE(dc_clk_type),
 232                                pp_clks->count,
 233                                DM_PP_MAX_CLOCK_LEVELS);
 234
 235                dc_clks->num_levels = DM_PP_MAX_CLOCK_LEVELS;
 236        } else
 237                dc_clks->num_levels = pp_clks->count;
 238
 239        DRM_INFO("DM_PPLIB: values for %s clock\n",
 240                        DC_DECODE_PP_CLOCK_TYPE(dc_clk_type));
 241
 242        for (i = 0; i < dc_clks->num_levels; i++) {
 243                DRM_INFO("DM_PPLIB:\t %d\n", pp_clks->clock[i]);
 244                dc_clks->clocks_in_khz[i] = pp_clks->clock[i];
 245        }
 246}
 247
 248static void pp_to_dc_clock_levels_with_latency(
 249                const struct pp_clock_levels_with_latency *pp_clks,
 250                struct dm_pp_clock_levels_with_latency *clk_level_info,
 251                enum dm_pp_clock_type dc_clk_type)
 252{
 253        uint32_t i;
 254
 255        if (pp_clks->num_levels > DM_PP_MAX_CLOCK_LEVELS) {
 256                DRM_INFO("DM_PPLIB: Warning: %s clock: number of levels %d exceeds maximum of %d!\n",
 257                                DC_DECODE_PP_CLOCK_TYPE(dc_clk_type),
 258                                pp_clks->num_levels,
 259                                DM_PP_MAX_CLOCK_LEVELS);
 260
 261                clk_level_info->num_levels = DM_PP_MAX_CLOCK_LEVELS;
 262        } else
 263                clk_level_info->num_levels = pp_clks->num_levels;
 264
 265        DRM_DEBUG("DM_PPLIB: values for %s clock\n",
 266                        DC_DECODE_PP_CLOCK_TYPE(dc_clk_type));
 267
 268        for (i = 0; i < clk_level_info->num_levels; i++) {
 269                DRM_DEBUG("DM_PPLIB:\t %d in kHz\n", pp_clks->data[i].clocks_in_khz);
 270                clk_level_info->data[i].clocks_in_khz = pp_clks->data[i].clocks_in_khz;
 271                clk_level_info->data[i].latency_in_us = pp_clks->data[i].latency_in_us;
 272        }
 273}
 274
 275static void pp_to_dc_clock_levels_with_voltage(
 276                const struct pp_clock_levels_with_voltage *pp_clks,
 277                struct dm_pp_clock_levels_with_voltage *clk_level_info,
 278                enum dm_pp_clock_type dc_clk_type)
 279{
 280        uint32_t i;
 281
 282        if (pp_clks->num_levels > DM_PP_MAX_CLOCK_LEVELS) {
 283                DRM_INFO("DM_PPLIB: Warning: %s clock: number of levels %d exceeds maximum of %d!\n",
 284                                DC_DECODE_PP_CLOCK_TYPE(dc_clk_type),
 285                                pp_clks->num_levels,
 286                                DM_PP_MAX_CLOCK_LEVELS);
 287
 288                clk_level_info->num_levels = DM_PP_MAX_CLOCK_LEVELS;
 289        } else
 290                clk_level_info->num_levels = pp_clks->num_levels;
 291
 292        DRM_INFO("DM_PPLIB: values for %s clock\n",
 293                        DC_DECODE_PP_CLOCK_TYPE(dc_clk_type));
 294
 295        for (i = 0; i < clk_level_info->num_levels; i++) {
 296                DRM_INFO("DM_PPLIB:\t %d in kHz\n", pp_clks->data[i].clocks_in_khz);
 297                clk_level_info->data[i].clocks_in_khz = pp_clks->data[i].clocks_in_khz;
 298                clk_level_info->data[i].voltage_in_mv = pp_clks->data[i].voltage_in_mv;
 299        }
 300}
 301
 302bool dm_pp_get_clock_levels_by_type(
 303                const struct dc_context *ctx,
 304                enum dm_pp_clock_type clk_type,
 305                struct dm_pp_clock_levels *dc_clks)
 306{
 307        struct amdgpu_device *adev = ctx->driver_context;
 308        void *pp_handle = adev->powerplay.pp_handle;
 309        struct amd_pp_clocks pp_clks = { 0 };
 310        struct amd_pp_simple_clock_info validation_clks = { 0 };
 311        uint32_t i;
 312
 313        if (adev->powerplay.pp_funcs->get_clock_by_type) {
 314                if (adev->powerplay.pp_funcs->get_clock_by_type(pp_handle,
 315                        dc_to_pp_clock_type(clk_type), &pp_clks)) {
 316                /* Error in pplib. Provide default values. */
 317                        get_default_clock_levels(clk_type, dc_clks);
 318                        return true;
 319                }
 320        }
 321
 322        pp_to_dc_clock_levels(&pp_clks, dc_clks, clk_type);
 323
 324        if (adev->powerplay.pp_funcs->get_display_mode_validation_clocks) {
 325                if (adev->powerplay.pp_funcs->get_display_mode_validation_clocks(
 326                                                pp_handle, &validation_clks)) {
 327                        /* Error in pplib. Provide default values. */
 328                        DRM_INFO("DM_PPLIB: Warning: using default validation clocks!\n");
 329                        validation_clks.engine_max_clock = 72000;
 330                        validation_clks.memory_max_clock = 80000;
 331                        validation_clks.level = 0;
 332                }
 333        }
 334
 335        DRM_INFO("DM_PPLIB: Validation clocks:\n");
 336        DRM_INFO("DM_PPLIB:    engine_max_clock: %d\n",
 337                        validation_clks.engine_max_clock);
 338        DRM_INFO("DM_PPLIB:    memory_max_clock: %d\n",
 339                        validation_clks.memory_max_clock);
 340        DRM_INFO("DM_PPLIB:    level           : %d\n",
 341                        validation_clks.level);
 342
 343        /* Translate 10 kHz to kHz. */
 344        validation_clks.engine_max_clock *= 10;
 345        validation_clks.memory_max_clock *= 10;
 346
 347        /* Determine the highest non-boosted level from the Validation Clocks */
 348        if (clk_type == DM_PP_CLOCK_TYPE_ENGINE_CLK) {
 349                for (i = 0; i < dc_clks->num_levels; i++) {
 350                        if (dc_clks->clocks_in_khz[i] > validation_clks.engine_max_clock) {
 351                                /* This clock is higher the validation clock.
 352                                 * Than means the previous one is the highest
 353                                 * non-boosted one. */
 354                                DRM_INFO("DM_PPLIB: reducing engine clock level from %d to %d\n",
 355                                                dc_clks->num_levels, i);
 356                                dc_clks->num_levels = i > 0 ? i : 1;
 357                                break;
 358                        }
 359                }
 360        } else if (clk_type == DM_PP_CLOCK_TYPE_MEMORY_CLK) {
 361                for (i = 0; i < dc_clks->num_levels; i++) {
 362                        if (dc_clks->clocks_in_khz[i] > validation_clks.memory_max_clock) {
 363                                DRM_INFO("DM_PPLIB: reducing memory clock level from %d to %d\n",
 364                                                dc_clks->num_levels, i);
 365                                dc_clks->num_levels = i > 0 ? i : 1;
 366                                break;
 367                        }
 368                }
 369        }
 370
 371        return true;
 372}
 373
 374bool dm_pp_get_clock_levels_by_type_with_latency(
 375        const struct dc_context *ctx,
 376        enum dm_pp_clock_type clk_type,
 377        struct dm_pp_clock_levels_with_latency *clk_level_info)
 378{
 379        struct amdgpu_device *adev = ctx->driver_context;
 380        void *pp_handle = adev->powerplay.pp_handle;
 381        struct pp_clock_levels_with_latency pp_clks = { 0 };
 382        const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
 383
 384        if (!pp_funcs || !pp_funcs->get_clock_by_type_with_latency)
 385                return false;
 386
 387        if (pp_funcs->get_clock_by_type_with_latency(pp_handle,
 388                                                     dc_to_pp_clock_type(clk_type),
 389                                                     &pp_clks))
 390                return false;
 391
 392        pp_to_dc_clock_levels_with_latency(&pp_clks, clk_level_info, clk_type);
 393
 394        return true;
 395}
 396
 397bool dm_pp_get_clock_levels_by_type_with_voltage(
 398        const struct dc_context *ctx,
 399        enum dm_pp_clock_type clk_type,
 400        struct dm_pp_clock_levels_with_voltage *clk_level_info)
 401{
 402        struct amdgpu_device *adev = ctx->driver_context;
 403        void *pp_handle = adev->powerplay.pp_handle;
 404        struct pp_clock_levels_with_voltage pp_clk_info = {0};
 405        const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
 406
 407        if (pp_funcs->get_clock_by_type_with_voltage(pp_handle,
 408                                                     dc_to_pp_clock_type(clk_type),
 409                                                     &pp_clk_info))
 410                return false;
 411
 412        pp_to_dc_clock_levels_with_voltage(&pp_clk_info, clk_level_info, clk_type);
 413
 414        return true;
 415}
 416
 417bool dm_pp_notify_wm_clock_changes(
 418        const struct dc_context *ctx,
 419        struct dm_pp_wm_sets_with_clock_ranges *wm_with_clock_ranges)
 420{
 421        /* TODO: to be implemented */
 422        return false;
 423}
 424
 425bool dm_pp_apply_power_level_change_request(
 426        const struct dc_context *ctx,
 427        struct dm_pp_power_level_change_request *level_change_req)
 428{
 429        /* TODO: to be implemented */
 430        return false;
 431}
 432
 433bool dm_pp_apply_clock_for_voltage_request(
 434        const struct dc_context *ctx,
 435        struct dm_pp_clock_for_voltage_req *clock_for_voltage_req)
 436{
 437        struct amdgpu_device *adev = ctx->driver_context;
 438        struct pp_display_clock_request pp_clock_request = {0};
 439        int ret = 0;
 440
 441        pp_clock_request.clock_type = dc_to_pp_clock_type(clock_for_voltage_req->clk_type);
 442        pp_clock_request.clock_freq_in_khz = clock_for_voltage_req->clocks_in_khz;
 443
 444        if (!pp_clock_request.clock_type)
 445                return false;
 446
 447        if (adev->powerplay.pp_funcs->display_clock_voltage_request)
 448                ret = adev->powerplay.pp_funcs->display_clock_voltage_request(
 449                        adev->powerplay.pp_handle,
 450                        &pp_clock_request);
 451        if (ret)
 452                return false;
 453        return true;
 454}
 455
 456bool dm_pp_get_static_clocks(
 457        const struct dc_context *ctx,
 458        struct dm_pp_static_clock_info *static_clk_info)
 459{
 460        struct amdgpu_device *adev = ctx->driver_context;
 461        struct amd_pp_clock_info pp_clk_info = {0};
 462        int ret = 0;
 463
 464        if (adev->powerplay.pp_funcs->get_current_clocks)
 465                ret = adev->powerplay.pp_funcs->get_current_clocks(
 466                        adev->powerplay.pp_handle,
 467                        &pp_clk_info);
 468        if (ret)
 469                return false;
 470
 471        static_clk_info->max_clocks_state = pp_to_dc_powerlevel_state(pp_clk_info.max_clocks_state);
 472        static_clk_info->max_mclk_khz = pp_clk_info.max_memory_clock * 10;
 473        static_clk_info->max_sclk_khz = pp_clk_info.max_engine_clock * 10;
 474
 475        return true;
 476}
 477
 478void pp_rv_set_display_requirement(struct pp_smu *pp,
 479                struct pp_smu_display_requirement_rv *req)
 480{
 481        struct dc_context *ctx = pp->ctx;
 482        struct amdgpu_device *adev = ctx->driver_context;
 483        void *pp_handle = adev->powerplay.pp_handle;
 484        const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
 485        struct pp_display_clock_request clock = {0};
 486
 487        if (!pp_funcs || !pp_funcs->display_clock_voltage_request)
 488                return;
 489
 490        clock.clock_type = amd_pp_dcf_clock;
 491        clock.clock_freq_in_khz = req->hard_min_dcefclk_khz;
 492        pp_funcs->display_clock_voltage_request(pp_handle, &clock);
 493
 494        clock.clock_type = amd_pp_f_clock;
 495        clock.clock_freq_in_khz = req->hard_min_fclk_khz;
 496        pp_funcs->display_clock_voltage_request(pp_handle, &clock);
 497}
 498
 499void pp_rv_set_wm_ranges(struct pp_smu *pp,
 500                struct pp_smu_wm_range_sets *ranges)
 501{
 502        struct dc_context *ctx = pp->ctx;
 503        struct amdgpu_device *adev = ctx->driver_context;
 504        void *pp_handle = adev->powerplay.pp_handle;
 505        const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
 506        struct dm_pp_wm_sets_with_clock_ranges_soc15 wm_with_clock_ranges;
 507        struct dm_pp_clock_range_for_dmif_wm_set_soc15 *wm_dce_clocks = wm_with_clock_ranges.wm_dmif_clocks_ranges;
 508        struct dm_pp_clock_range_for_mcif_wm_set_soc15 *wm_soc_clocks = wm_with_clock_ranges.wm_mcif_clocks_ranges;
 509        int32_t i;
 510
 511        wm_with_clock_ranges.num_wm_dmif_sets = ranges->num_reader_wm_sets;
 512        wm_with_clock_ranges.num_wm_mcif_sets = ranges->num_writer_wm_sets;
 513
 514        for (i = 0; i < wm_with_clock_ranges.num_wm_dmif_sets; i++) {
 515                if (ranges->reader_wm_sets[i].wm_inst > 3)
 516                        wm_dce_clocks[i].wm_set_id = WM_SET_A;
 517                else
 518                        wm_dce_clocks[i].wm_set_id =
 519                                        ranges->reader_wm_sets[i].wm_inst;
 520                wm_dce_clocks[i].wm_max_dcfclk_clk_in_khz =
 521                                ranges->reader_wm_sets[i].max_drain_clk_khz;
 522                wm_dce_clocks[i].wm_min_dcfclk_clk_in_khz =
 523                                ranges->reader_wm_sets[i].min_drain_clk_khz;
 524                wm_dce_clocks[i].wm_max_mem_clk_in_khz =
 525                                ranges->reader_wm_sets[i].max_fill_clk_khz;
 526                wm_dce_clocks[i].wm_min_mem_clk_in_khz =
 527                                ranges->reader_wm_sets[i].min_fill_clk_khz;
 528        }
 529
 530        for (i = 0; i < wm_with_clock_ranges.num_wm_mcif_sets; i++) {
 531                if (ranges->writer_wm_sets[i].wm_inst > 3)
 532                        wm_soc_clocks[i].wm_set_id = WM_SET_A;
 533                else
 534                        wm_soc_clocks[i].wm_set_id =
 535                                        ranges->writer_wm_sets[i].wm_inst;
 536                wm_soc_clocks[i].wm_max_socclk_clk_in_khz =
 537                                ranges->writer_wm_sets[i].max_fill_clk_khz;
 538                wm_soc_clocks[i].wm_min_socclk_clk_in_khz =
 539                                ranges->writer_wm_sets[i].min_fill_clk_khz;
 540                wm_soc_clocks[i].wm_max_mem_clk_in_khz =
 541                                ranges->writer_wm_sets[i].max_drain_clk_khz;
 542                wm_soc_clocks[i].wm_min_mem_clk_in_khz =
 543                                ranges->writer_wm_sets[i].min_drain_clk_khz;
 544        }
 545
 546        pp_funcs->set_watermarks_for_clocks_ranges(pp_handle, &wm_with_clock_ranges);
 547}
 548
 549void pp_rv_set_pme_wa_enable(struct pp_smu *pp)
 550{
 551        struct dc_context *ctx = pp->ctx;
 552        struct amdgpu_device *adev = ctx->driver_context;
 553        void *pp_handle = adev->powerplay.pp_handle;
 554        const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
 555
 556        if (!pp_funcs || !pp_funcs->notify_smu_enable_pwe)
 557                return;
 558
 559        pp_funcs->notify_smu_enable_pwe(pp_handle);
 560}
 561
 562void dm_pp_get_funcs_rv(
 563                struct dc_context *ctx,
 564                struct pp_smu_funcs_rv *funcs)
 565{
 566        funcs->pp_smu.ctx = ctx;
 567        funcs->set_display_requirement = pp_rv_set_display_requirement;
 568        funcs->set_wm_ranges = pp_rv_set_wm_ranges;
 569        funcs->set_pme_wa_enable = pp_rv_set_pme_wa_enable;
 570}
 571