linux/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.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 */
  25
  26#include "dccg.h"
  27#include "clk_mgr_internal.h"
  28
  29
  30#include "dcn20/dcn20_clk_mgr.h"
  31#include "rn_clk_mgr.h"
  32
  33
  34#include "dce100/dce_clk_mgr.h"
  35#include "rn_clk_mgr_vbios_smu.h"
  36#include "reg_helper.h"
  37#include "core_types.h"
  38#include "dm_helpers.h"
  39
  40#include "atomfirmware.h"
  41#include "clk/clk_10_0_2_offset.h"
  42#include "clk/clk_10_0_2_sh_mask.h"
  43#include "renoir_ip_offset.h"
  44
  45
  46/* Constants */
  47
  48#define LPDDR_MEM_RETRAIN_LATENCY 4.977 /* Number obtained from LPDDR4 Training Counter Requirement doc */
  49#define SMU_VER_55_51_0 0x373300 /* SMU Version that is able to set DISPCLK below 100MHz */
  50
  51/* Macros */
  52
  53#define REG(reg_name) \
  54        (CLK_BASE.instance[0].segment[mm ## reg_name ## _BASE_IDX] + mm ## reg_name)
  55
  56
  57/* TODO: evaluate how to lower or disable all dcn clocks in screen off case */
  58int rn_get_active_display_cnt_wa(
  59                struct dc *dc,
  60                struct dc_state *context)
  61{
  62        int i, display_count;
  63        bool tmds_present = false;
  64
  65        display_count = 0;
  66        for (i = 0; i < context->stream_count; i++) {
  67                const struct dc_stream_state *stream = context->streams[i];
  68
  69                /* Extend the WA to DP for Linux*/
  70                if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A ||
  71                                stream->signal == SIGNAL_TYPE_DVI_SINGLE_LINK ||
  72                                stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK ||
  73                                stream->signal == SIGNAL_TYPE_DISPLAY_PORT)
  74                        tmds_present = true;
  75        }
  76
  77        for (i = 0; i < dc->link_count; i++) {
  78                const struct dc_link *link = dc->links[i];
  79
  80                /* abusing the fact that the dig and phy are coupled to see if the phy is enabled */
  81                if (link->link_enc->funcs->is_dig_enabled(link->link_enc))
  82                        display_count++;
  83        }
  84
  85        /* WA for hang on HDMI after display off back back on*/
  86        if (display_count == 0 && tmds_present)
  87                display_count = 1;
  88
  89        return display_count;
  90}
  91
  92void rn_set_low_power_state(struct clk_mgr *clk_mgr_base)
  93{
  94        struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
  95
  96        rn_vbios_smu_set_dcn_low_power_state(clk_mgr, DCN_PWR_STATE_LOW_POWER);
  97        /* update power state */
  98        clk_mgr_base->clks.pwr_state = DCN_PWR_STATE_LOW_POWER;
  99}
 100
 101static void rn_update_clocks_update_dpp_dto(struct clk_mgr_internal *clk_mgr,
 102                struct dc_state *context, int ref_dpp_clk, bool safe_to_lower)
 103{
 104        int i;
 105
 106        clk_mgr->dccg->ref_dppclk = ref_dpp_clk;
 107
 108        for (i = 0; i < clk_mgr->base.ctx->dc->res_pool->pipe_count; i++) {
 109                int dpp_inst, dppclk_khz, prev_dppclk_khz;
 110
 111                /* Loop index may not match dpp->inst if some pipes disabled,
 112                 * so select correct inst from res_pool
 113                 */
 114                dpp_inst = clk_mgr->base.ctx->dc->res_pool->dpps[i]->inst;
 115                dppclk_khz = context->res_ctx.pipe_ctx[i].plane_res.bw.dppclk_khz;
 116
 117                prev_dppclk_khz = clk_mgr->dccg->pipe_dppclk_khz[i];
 118
 119                if (safe_to_lower || prev_dppclk_khz < dppclk_khz)
 120                        clk_mgr->dccg->funcs->update_dpp_dto(
 121                                                        clk_mgr->dccg, dpp_inst, dppclk_khz);
 122        }
 123}
 124
 125
 126void rn_update_clocks(struct clk_mgr *clk_mgr_base,
 127                        struct dc_state *context,
 128                        bool safe_to_lower)
 129{
 130        struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
 131        struct dc_clocks *new_clocks = &context->bw_ctx.bw.dcn.clk;
 132        struct dc *dc = clk_mgr_base->ctx->dc;
 133        int display_count;
 134        bool update_dppclk = false;
 135        bool update_dispclk = false;
 136        bool dpp_clock_lowered = false;
 137
 138        struct dmcu *dmcu = clk_mgr_base->ctx->dc->res_pool->dmcu;
 139
 140        if (dc->work_arounds.skip_clock_update)
 141                return;
 142
 143        /*
 144         * if it is safe to lower, but we are already in the lower state, we don't have to do anything
 145         * also if safe to lower is false, we just go in the higher state
 146         */
 147        if (safe_to_lower && !dc->debug.disable_48mhz_pwrdwn) {
 148                /* check that we're not already in lower */
 149                if (clk_mgr_base->clks.pwr_state != DCN_PWR_STATE_LOW_POWER) {
 150
 151                        display_count = rn_get_active_display_cnt_wa(dc, context);
 152                        /* if we can go lower, go lower */
 153                        if (display_count == 0) {
 154                                rn_vbios_smu_set_dcn_low_power_state(clk_mgr, DCN_PWR_STATE_LOW_POWER);
 155                                /* update power state */
 156                                clk_mgr_base->clks.pwr_state = DCN_PWR_STATE_LOW_POWER;
 157                        }
 158                }
 159        } else {
 160                /* check that we're not already in D0 */
 161                if (clk_mgr_base->clks.pwr_state != DCN_PWR_STATE_MISSION_MODE) {
 162                        rn_vbios_smu_set_dcn_low_power_state(clk_mgr, DCN_PWR_STATE_MISSION_MODE);
 163                        /* update power state */
 164                        clk_mgr_base->clks.pwr_state = DCN_PWR_STATE_MISSION_MODE;
 165                }
 166        }
 167
 168        if (should_set_clock(safe_to_lower, new_clocks->dcfclk_khz, clk_mgr_base->clks.dcfclk_khz)) {
 169                clk_mgr_base->clks.dcfclk_khz = new_clocks->dcfclk_khz;
 170                rn_vbios_smu_set_hard_min_dcfclk(clk_mgr, clk_mgr_base->clks.dcfclk_khz);
 171        }
 172
 173        if (should_set_clock(safe_to_lower,
 174                        new_clocks->dcfclk_deep_sleep_khz, clk_mgr_base->clks.dcfclk_deep_sleep_khz)) {
 175                clk_mgr_base->clks.dcfclk_deep_sleep_khz = new_clocks->dcfclk_deep_sleep_khz;
 176                rn_vbios_smu_set_min_deep_sleep_dcfclk(clk_mgr, clk_mgr_base->clks.dcfclk_deep_sleep_khz);
 177        }
 178
 179        // workaround: Limit dppclk to 100Mhz to avoid lower eDP panel switch to plus 4K monitor underflow.
 180        // Do not adjust dppclk if dppclk is 0 to avoid unexpected result
 181        if (new_clocks->dppclk_khz < 100000 && new_clocks->dppclk_khz > 0)
 182                new_clocks->dppclk_khz = 100000;
 183
 184        /*
 185         * Temporally ignore thew 0 cases for disp and dpp clks.
 186         * We may have a new feature that requires 0 clks in the future.
 187         */
 188        if (new_clocks->dppclk_khz == 0 || new_clocks->dispclk_khz == 0) {
 189                new_clocks->dppclk_khz = clk_mgr_base->clks.dppclk_khz;
 190                new_clocks->dispclk_khz = clk_mgr_base->clks.dispclk_khz;
 191        }
 192
 193        if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr_base->clks.dppclk_khz)) {
 194                if (clk_mgr_base->clks.dppclk_khz > new_clocks->dppclk_khz)
 195                        dpp_clock_lowered = true;
 196                clk_mgr_base->clks.dppclk_khz = new_clocks->dppclk_khz;
 197                update_dppclk = true;
 198        }
 199
 200        if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) {
 201                clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz;
 202                clk_mgr_base->clks.actual_dispclk_khz = rn_vbios_smu_set_dispclk(clk_mgr, clk_mgr_base->clks.dispclk_khz);
 203
 204                update_dispclk = true;
 205        }
 206
 207        if (dpp_clock_lowered) {
 208                // increase per DPP DTO before lowering global dppclk with requested dppclk
 209                rn_update_clocks_update_dpp_dto(
 210                                clk_mgr,
 211                                context,
 212                                clk_mgr_base->clks.dppclk_khz,
 213                                safe_to_lower);
 214
 215                clk_mgr_base->clks.actual_dppclk_khz =
 216                                rn_vbios_smu_set_dppclk(clk_mgr, clk_mgr_base->clks.dppclk_khz);
 217
 218                //update dpp dto with actual dpp clk.
 219                rn_update_clocks_update_dpp_dto(
 220                                clk_mgr,
 221                                context,
 222                                clk_mgr_base->clks.actual_dppclk_khz,
 223                                safe_to_lower);
 224
 225        } else {
 226                // increase global DPPCLK before lowering per DPP DTO
 227                if (update_dppclk || update_dispclk)
 228                        clk_mgr_base->clks.actual_dppclk_khz =
 229                                        rn_vbios_smu_set_dppclk(clk_mgr, clk_mgr_base->clks.dppclk_khz);
 230
 231                // always update dtos unless clock is lowered and not safe to lower
 232                rn_update_clocks_update_dpp_dto(
 233                                clk_mgr,
 234                                context,
 235                                clk_mgr_base->clks.actual_dppclk_khz,
 236                                safe_to_lower);
 237        }
 238
 239        if (update_dispclk &&
 240                        dmcu && dmcu->funcs->is_dmcu_initialized(dmcu)) {
 241                /*update dmcu for wait_loop count*/
 242                dmcu->funcs->set_psr_wait_loop(dmcu,
 243                        clk_mgr_base->clks.dispclk_khz / 1000 / 7);
 244        }
 245}
 246
 247static int get_vco_frequency_from_reg(struct clk_mgr_internal *clk_mgr)
 248{
 249        /* get FbMult value */
 250        struct fixed31_32 pll_req;
 251        unsigned int fbmult_frac_val = 0;
 252        unsigned int fbmult_int_val = 0;
 253
 254
 255        /*
 256         * Register value of fbmult is in 8.16 format, we are converting to 31.32
 257         * to leverage the fix point operations available in driver
 258         */
 259
 260        REG_GET(CLK1_CLK_PLL_REQ, FbMult_frac, &fbmult_frac_val); /* 16 bit fractional part*/
 261        REG_GET(CLK1_CLK_PLL_REQ, FbMult_int, &fbmult_int_val); /* 8 bit integer part */
 262
 263        pll_req = dc_fixpt_from_int(fbmult_int_val);
 264
 265        /*
 266         * since fractional part is only 16 bit in register definition but is 32 bit
 267         * in our fix point definiton, need to shift left by 16 to obtain correct value
 268         */
 269        pll_req.value |= fbmult_frac_val << 16;
 270
 271        /* multiply by REFCLK period */
 272        pll_req = dc_fixpt_mul_int(pll_req, clk_mgr->dfs_ref_freq_khz);
 273
 274        /* integer part is now VCO frequency in kHz */
 275        return dc_fixpt_floor(pll_req);
 276}
 277
 278static void rn_dump_clk_registers_internal(struct rn_clk_internal *internal, struct clk_mgr *clk_mgr_base)
 279{
 280        struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
 281
 282        internal->CLK1_CLK3_CURRENT_CNT = REG_READ(CLK1_CLK3_CURRENT_CNT);
 283        internal->CLK1_CLK3_BYPASS_CNTL = REG_READ(CLK1_CLK3_BYPASS_CNTL);
 284
 285        internal->CLK1_CLK3_DS_CNTL = REG_READ(CLK1_CLK3_DS_CNTL);      //dcf deep sleep divider
 286        internal->CLK1_CLK3_ALLOW_DS = REG_READ(CLK1_CLK3_ALLOW_DS);
 287
 288        internal->CLK1_CLK1_CURRENT_CNT = REG_READ(CLK1_CLK1_CURRENT_CNT);
 289        internal->CLK1_CLK1_BYPASS_CNTL = REG_READ(CLK1_CLK1_BYPASS_CNTL);
 290
 291        internal->CLK1_CLK2_CURRENT_CNT = REG_READ(CLK1_CLK2_CURRENT_CNT);
 292        internal->CLK1_CLK2_BYPASS_CNTL = REG_READ(CLK1_CLK2_BYPASS_CNTL);
 293
 294        internal->CLK1_CLK0_CURRENT_CNT = REG_READ(CLK1_CLK0_CURRENT_CNT);
 295        internal->CLK1_CLK0_BYPASS_CNTL = REG_READ(CLK1_CLK0_BYPASS_CNTL);
 296}
 297
 298/* This function collect raw clk register values */
 299static void rn_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
 300                struct clk_mgr *clk_mgr_base, struct clk_log_info *log_info)
 301{
 302        struct rn_clk_internal internal = {0};
 303        char *bypass_clks[5] = {"0x0 DFS", "0x1 REFCLK", "0x2 ERROR", "0x3 400 FCH", "0x4 600 FCH"};
 304        unsigned int chars_printed = 0;
 305        unsigned int remaining_buffer = log_info->bufSize;
 306
 307        rn_dump_clk_registers_internal(&internal, clk_mgr_base);
 308
 309        regs_and_bypass->dcfclk = internal.CLK1_CLK3_CURRENT_CNT / 10;
 310        regs_and_bypass->dcf_deep_sleep_divider = internal.CLK1_CLK3_DS_CNTL / 10;
 311        regs_and_bypass->dcf_deep_sleep_allow = internal.CLK1_CLK3_ALLOW_DS;
 312        regs_and_bypass->dprefclk = internal.CLK1_CLK2_CURRENT_CNT / 10;
 313        regs_and_bypass->dispclk = internal.CLK1_CLK0_CURRENT_CNT / 10;
 314        regs_and_bypass->dppclk = internal.CLK1_CLK1_CURRENT_CNT / 10;
 315
 316        regs_and_bypass->dppclk_bypass = internal.CLK1_CLK1_BYPASS_CNTL & 0x0007;
 317        if (regs_and_bypass->dppclk_bypass < 0 || regs_and_bypass->dppclk_bypass > 4)
 318                regs_and_bypass->dppclk_bypass = 0;
 319        regs_and_bypass->dcfclk_bypass = internal.CLK1_CLK3_BYPASS_CNTL & 0x0007;
 320        if (regs_and_bypass->dcfclk_bypass < 0 || regs_and_bypass->dcfclk_bypass > 4)
 321                regs_and_bypass->dcfclk_bypass = 0;
 322        regs_and_bypass->dispclk_bypass = internal.CLK1_CLK0_BYPASS_CNTL & 0x0007;
 323        if (regs_and_bypass->dispclk_bypass < 0 || regs_and_bypass->dispclk_bypass > 4)
 324                regs_and_bypass->dispclk_bypass = 0;
 325        regs_and_bypass->dprefclk_bypass = internal.CLK1_CLK2_BYPASS_CNTL & 0x0007;
 326        if (regs_and_bypass->dprefclk_bypass < 0 || regs_and_bypass->dprefclk_bypass > 4)
 327                regs_and_bypass->dprefclk_bypass = 0;
 328
 329        if (log_info->enabled) {
 330                chars_printed = snprintf_count(log_info->pBuf, remaining_buffer, "clk_type,clk_value,deepsleep_cntl,deepsleep_allow,bypass\n");
 331                remaining_buffer -= chars_printed;
 332                *log_info->sum_chars_printed += chars_printed;
 333                log_info->pBuf += chars_printed;
 334
 335                chars_printed = snprintf_count(log_info->pBuf, remaining_buffer, "dcfclk,%d,%d,%d,%s\n",
 336                        regs_and_bypass->dcfclk,
 337                        regs_and_bypass->dcf_deep_sleep_divider,
 338                        regs_and_bypass->dcf_deep_sleep_allow,
 339                        bypass_clks[(int) regs_and_bypass->dcfclk_bypass]);
 340                remaining_buffer -= chars_printed;
 341                *log_info->sum_chars_printed += chars_printed;
 342                log_info->pBuf += chars_printed;
 343
 344                chars_printed = snprintf_count(log_info->pBuf, remaining_buffer, "dprefclk,%d,N/A,N/A,%s\n",
 345                        regs_and_bypass->dprefclk,
 346                        bypass_clks[(int) regs_and_bypass->dprefclk_bypass]);
 347                remaining_buffer -= chars_printed;
 348                *log_info->sum_chars_printed += chars_printed;
 349                log_info->pBuf += chars_printed;
 350
 351                chars_printed = snprintf_count(log_info->pBuf, remaining_buffer, "dispclk,%d,N/A,N/A,%s\n",
 352                        regs_and_bypass->dispclk,
 353                        bypass_clks[(int) regs_and_bypass->dispclk_bypass]);
 354                remaining_buffer -= chars_printed;
 355                *log_info->sum_chars_printed += chars_printed;
 356                log_info->pBuf += chars_printed;
 357
 358                //split
 359                chars_printed = snprintf_count(log_info->pBuf, remaining_buffer, "SPLIT\n");
 360                remaining_buffer -= chars_printed;
 361                *log_info->sum_chars_printed += chars_printed;
 362                log_info->pBuf += chars_printed;
 363
 364                // REGISTER VALUES
 365                chars_printed = snprintf_count(log_info->pBuf, remaining_buffer, "reg_name,value,clk_type\n");
 366                remaining_buffer -= chars_printed;
 367                *log_info->sum_chars_printed += chars_printed;
 368                log_info->pBuf += chars_printed;
 369
 370                chars_printed = snprintf_count(log_info->pBuf, remaining_buffer, "CLK1_CLK3_CURRENT_CNT,%d,dcfclk\n",
 371                                internal.CLK1_CLK3_CURRENT_CNT);
 372                remaining_buffer -= chars_printed;
 373                *log_info->sum_chars_printed += chars_printed;
 374                log_info->pBuf += chars_printed;
 375
 376                chars_printed = snprintf_count(log_info->pBuf, remaining_buffer, "CLK1_CLK3_DS_CNTL,%d,dcf_deep_sleep_divider\n",
 377                                        internal.CLK1_CLK3_DS_CNTL);
 378                remaining_buffer -= chars_printed;
 379                *log_info->sum_chars_printed += chars_printed;
 380                log_info->pBuf += chars_printed;
 381
 382                chars_printed = snprintf_count(log_info->pBuf, remaining_buffer, "CLK1_CLK3_ALLOW_DS,%d,dcf_deep_sleep_allow\n",
 383                                        internal.CLK1_CLK3_ALLOW_DS);
 384                remaining_buffer -= chars_printed;
 385                *log_info->sum_chars_printed += chars_printed;
 386                log_info->pBuf += chars_printed;
 387
 388                chars_printed = snprintf_count(log_info->pBuf, remaining_buffer, "CLK1_CLK2_CURRENT_CNT,%d,dprefclk\n",
 389                                        internal.CLK1_CLK2_CURRENT_CNT);
 390                remaining_buffer -= chars_printed;
 391                *log_info->sum_chars_printed += chars_printed;
 392                log_info->pBuf += chars_printed;
 393
 394                chars_printed = snprintf_count(log_info->pBuf, remaining_buffer, "CLK1_CLK0_CURRENT_CNT,%d,dispclk\n",
 395                                        internal.CLK1_CLK0_CURRENT_CNT);
 396                remaining_buffer -= chars_printed;
 397                *log_info->sum_chars_printed += chars_printed;
 398                log_info->pBuf += chars_printed;
 399
 400                chars_printed = snprintf_count(log_info->pBuf, remaining_buffer, "CLK1_CLK1_CURRENT_CNT,%d,dppclk\n",
 401                                        internal.CLK1_CLK1_CURRENT_CNT);
 402                remaining_buffer -= chars_printed;
 403                *log_info->sum_chars_printed += chars_printed;
 404                log_info->pBuf += chars_printed;
 405
 406                chars_printed = snprintf_count(log_info->pBuf, remaining_buffer, "CLK1_CLK3_BYPASS_CNTL,%d,dcfclk_bypass\n",
 407                                        internal.CLK1_CLK3_BYPASS_CNTL);
 408                remaining_buffer -= chars_printed;
 409                *log_info->sum_chars_printed += chars_printed;
 410                log_info->pBuf += chars_printed;
 411
 412                chars_printed = snprintf_count(log_info->pBuf, remaining_buffer, "CLK1_CLK2_BYPASS_CNTL,%d,dprefclk_bypass\n",
 413                                        internal.CLK1_CLK2_BYPASS_CNTL);
 414                remaining_buffer -= chars_printed;
 415                *log_info->sum_chars_printed += chars_printed;
 416                log_info->pBuf += chars_printed;
 417
 418                chars_printed = snprintf_count(log_info->pBuf, remaining_buffer, "CLK1_CLK0_BYPASS_CNTL,%d,dispclk_bypass\n",
 419                                        internal.CLK1_CLK0_BYPASS_CNTL);
 420                remaining_buffer -= chars_printed;
 421                *log_info->sum_chars_printed += chars_printed;
 422                log_info->pBuf += chars_printed;
 423
 424                chars_printed = snprintf_count(log_info->pBuf, remaining_buffer, "CLK1_CLK1_BYPASS_CNTL,%d,dppclk_bypass\n",
 425                                        internal.CLK1_CLK1_BYPASS_CNTL);
 426                remaining_buffer -= chars_printed;
 427                *log_info->sum_chars_printed += chars_printed;
 428                log_info->pBuf += chars_printed;
 429        }
 430}
 431
 432/* This function produce translated logical clk state values*/
 433void rn_get_clk_states(struct clk_mgr *clk_mgr_base, struct clk_states *s)
 434{
 435        struct clk_state_registers_and_bypass sb = { 0 };
 436        struct clk_log_info log_info = { 0 };
 437
 438        rn_dump_clk_registers(&sb, clk_mgr_base, &log_info);
 439
 440        s->dprefclk_khz = sb.dprefclk * 1000;
 441}
 442
 443void rn_enable_pme_wa(struct clk_mgr *clk_mgr_base)
 444{
 445        struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
 446
 447        rn_vbios_smu_enable_pme_wa(clk_mgr);
 448}
 449
 450void rn_init_clocks(struct clk_mgr *clk_mgr)
 451{
 452        memset(&(clk_mgr->clks), 0, sizeof(struct dc_clocks));
 453        // Assumption is that boot state always supports pstate
 454        clk_mgr->clks.p_state_change_support = true;
 455        clk_mgr->clks.prev_p_state_change_support = true;
 456        clk_mgr->clks.pwr_state = DCN_PWR_STATE_UNKNOWN;
 457}
 458
 459static void build_watermark_ranges(struct clk_bw_params *bw_params, struct pp_smu_wm_range_sets *ranges)
 460{
 461        int i, num_valid_sets;
 462
 463        num_valid_sets = 0;
 464
 465        for (i = 0; i < WM_SET_COUNT; i++) {
 466                /* skip empty entries, the smu array has no holes*/
 467                if (!bw_params->wm_table.entries[i].valid)
 468                        continue;
 469
 470                ranges->reader_wm_sets[num_valid_sets].wm_inst = bw_params->wm_table.entries[i].wm_inst;
 471                ranges->reader_wm_sets[num_valid_sets].wm_type = bw_params->wm_table.entries[i].wm_type;
 472                /* We will not select WM based on fclk, so leave it as unconstrained */
 473                ranges->reader_wm_sets[num_valid_sets].min_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
 474                ranges->reader_wm_sets[num_valid_sets].max_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
 475                /* dcfclk wil be used to select WM*/
 476
 477                if (ranges->reader_wm_sets[num_valid_sets].wm_type == WM_TYPE_PSTATE_CHG) {
 478                        if (i == 0)
 479                                ranges->reader_wm_sets[num_valid_sets].min_drain_clk_mhz = 0;
 480                        else {
 481                                /* add 1 to make it non-overlapping with next lvl */
 482                                ranges->reader_wm_sets[num_valid_sets].min_drain_clk_mhz = bw_params->clk_table.entries[i - 1].dcfclk_mhz + 1;
 483                        }
 484                        ranges->reader_wm_sets[num_valid_sets].max_drain_clk_mhz = bw_params->clk_table.entries[i].dcfclk_mhz;
 485
 486                } else {
 487                        /* unconstrained for memory retraining */
 488                        ranges->reader_wm_sets[num_valid_sets].min_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
 489                        ranges->reader_wm_sets[num_valid_sets].max_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
 490
 491                        /* Modify previous watermark range to cover up to max */
 492                        ranges->reader_wm_sets[num_valid_sets - 1].max_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
 493                }
 494                num_valid_sets++;
 495        }
 496
 497        ASSERT(num_valid_sets != 0); /* Must have at least one set of valid watermarks */
 498        ranges->num_reader_wm_sets = num_valid_sets;
 499
 500        /* modify the min and max to make sure we cover the whole range*/
 501        ranges->reader_wm_sets[0].min_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
 502        ranges->reader_wm_sets[0].min_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
 503        ranges->reader_wm_sets[ranges->num_reader_wm_sets - 1].max_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
 504        ranges->reader_wm_sets[ranges->num_reader_wm_sets - 1].max_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
 505
 506        /* This is for writeback only, does not matter currently as no writeback support*/
 507        ranges->num_writer_wm_sets = 1;
 508        ranges->writer_wm_sets[0].wm_inst = WM_A;
 509        ranges->writer_wm_sets[0].min_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
 510        ranges->writer_wm_sets[0].max_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
 511        ranges->writer_wm_sets[0].min_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
 512        ranges->writer_wm_sets[0].max_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
 513
 514}
 515
 516static void rn_notify_wm_ranges(struct clk_mgr *clk_mgr_base)
 517{
 518        struct dc_debug_options *debug = &clk_mgr_base->ctx->dc->debug;
 519        struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
 520        struct pp_smu_funcs *pp_smu = clk_mgr->pp_smu;
 521
 522        if (!debug->disable_pplib_wm_range) {
 523                build_watermark_ranges(clk_mgr_base->bw_params, &clk_mgr_base->ranges);
 524
 525                /* Notify PP Lib/SMU which Watermarks to use for which clock ranges */
 526                if (pp_smu && pp_smu->rn_funcs.set_wm_ranges)
 527                        pp_smu->rn_funcs.set_wm_ranges(&pp_smu->rn_funcs.pp_smu, &clk_mgr_base->ranges);
 528        }
 529
 530}
 531
 532static bool rn_are_clock_states_equal(struct dc_clocks *a,
 533                struct dc_clocks *b)
 534{
 535        if (a->dispclk_khz != b->dispclk_khz)
 536                return false;
 537        else if (a->dppclk_khz != b->dppclk_khz)
 538                return false;
 539        else if (a->dcfclk_khz != b->dcfclk_khz)
 540                return false;
 541        else if (a->dcfclk_deep_sleep_khz != b->dcfclk_deep_sleep_khz)
 542                return false;
 543
 544        return true;
 545}
 546
 547
 548/* Notify clk_mgr of a change in link rate, update phyclk frequency if necessary */
 549static void rn_notify_link_rate_change(struct clk_mgr *clk_mgr_base, struct dc_link *link)
 550{
 551        struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
 552        unsigned int i, max_phyclk_req = 0;
 553
 554        clk_mgr->cur_phyclk_req_table[link->link_index] = link->cur_link_settings.link_rate * LINK_RATE_REF_FREQ_IN_KHZ;
 555
 556        for (i = 0; i < MAX_PIPES * 2; i++) {
 557                if (clk_mgr->cur_phyclk_req_table[i] > max_phyclk_req)
 558                        max_phyclk_req = clk_mgr->cur_phyclk_req_table[i];
 559        }
 560
 561        if (max_phyclk_req != clk_mgr_base->clks.phyclk_khz) {
 562                clk_mgr_base->clks.phyclk_khz = max_phyclk_req;
 563                rn_vbios_smu_set_phyclk(clk_mgr, clk_mgr_base->clks.phyclk_khz);
 564        }
 565}
 566
 567static struct clk_mgr_funcs dcn21_funcs = {
 568        .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
 569        .update_clocks = rn_update_clocks,
 570        .init_clocks = rn_init_clocks,
 571        .enable_pme_wa = rn_enable_pme_wa,
 572        .are_clock_states_equal = rn_are_clock_states_equal,
 573        .set_low_power_state = rn_set_low_power_state,
 574        .notify_wm_ranges = rn_notify_wm_ranges,
 575        .notify_link_rate_change = rn_notify_link_rate_change,
 576};
 577
 578static struct clk_bw_params rn_bw_params = {
 579        .vram_type = Ddr4MemType,
 580        .num_channels = 1,
 581        .clk_table = {
 582                .entries = {
 583                        {
 584                                .voltage = 0,
 585                                .dcfclk_mhz = 400,
 586                                .fclk_mhz = 400,
 587                                .memclk_mhz = 800,
 588                                .socclk_mhz = 0,
 589                        },
 590                        {
 591                                .voltage = 0,
 592                                .dcfclk_mhz = 483,
 593                                .fclk_mhz = 800,
 594                                .memclk_mhz = 1600,
 595                                .socclk_mhz = 0,
 596                        },
 597                        {
 598                                .voltage = 0,
 599                                .dcfclk_mhz = 602,
 600                                .fclk_mhz = 1067,
 601                                .memclk_mhz = 1067,
 602                                .socclk_mhz = 0,
 603                        },
 604                        {
 605                                .voltage = 0,
 606                                .dcfclk_mhz = 738,
 607                                .fclk_mhz = 1333,
 608                                .memclk_mhz = 1600,
 609                                .socclk_mhz = 0,
 610                        },
 611                },
 612
 613                .num_entries = 4,
 614        },
 615
 616};
 617
 618static struct wm_table ddr4_wm_table_gs = {
 619        .entries = {
 620                {
 621                        .wm_inst = WM_A,
 622                        .wm_type = WM_TYPE_PSTATE_CHG,
 623                        .pstate_latency_us = 11.72,
 624                        .sr_exit_time_us = 7.09,
 625                        .sr_enter_plus_exit_time_us = 8.14,
 626                        .valid = true,
 627                },
 628                {
 629                        .wm_inst = WM_B,
 630                        .wm_type = WM_TYPE_PSTATE_CHG,
 631                        .pstate_latency_us = 11.72,
 632                        .sr_exit_time_us = 10.12,
 633                        .sr_enter_plus_exit_time_us = 11.48,
 634                        .valid = true,
 635                },
 636                {
 637                        .wm_inst = WM_C,
 638                        .wm_type = WM_TYPE_PSTATE_CHG,
 639                        .pstate_latency_us = 11.72,
 640                        .sr_exit_time_us = 10.12,
 641                        .sr_enter_plus_exit_time_us = 11.48,
 642                        .valid = true,
 643                },
 644                {
 645                        .wm_inst = WM_D,
 646                        .wm_type = WM_TYPE_PSTATE_CHG,
 647                        .pstate_latency_us = 11.72,
 648                        .sr_exit_time_us = 10.12,
 649                        .sr_enter_plus_exit_time_us = 11.48,
 650                        .valid = true,
 651                },
 652        }
 653};
 654
 655static struct wm_table lpddr4_wm_table_gs = {
 656        .entries = {
 657                {
 658                        .wm_inst = WM_A,
 659                        .wm_type = WM_TYPE_PSTATE_CHG,
 660                        .pstate_latency_us = 11.65333,
 661                        .sr_exit_time_us = 5.32,
 662                        .sr_enter_plus_exit_time_us = 6.38,
 663                        .valid = true,
 664                },
 665                {
 666                        .wm_inst = WM_B,
 667                        .wm_type = WM_TYPE_PSTATE_CHG,
 668                        .pstate_latency_us = 11.65333,
 669                        .sr_exit_time_us = 9.82,
 670                        .sr_enter_plus_exit_time_us = 11.196,
 671                        .valid = true,
 672                },
 673                {
 674                        .wm_inst = WM_C,
 675                        .wm_type = WM_TYPE_PSTATE_CHG,
 676                        .pstate_latency_us = 11.65333,
 677                        .sr_exit_time_us = 9.89,
 678                        .sr_enter_plus_exit_time_us = 11.24,
 679                        .valid = true,
 680                },
 681                {
 682                        .wm_inst = WM_D,
 683                        .wm_type = WM_TYPE_PSTATE_CHG,
 684                        .pstate_latency_us = 11.65333,
 685                        .sr_exit_time_us = 9.748,
 686                        .sr_enter_plus_exit_time_us = 11.102,
 687                        .valid = true,
 688                },
 689        }
 690};
 691
 692static struct wm_table lpddr4_wm_table_with_disabled_ppt = {
 693        .entries = {
 694                {
 695                        .wm_inst = WM_A,
 696                        .wm_type = WM_TYPE_PSTATE_CHG,
 697                        .pstate_latency_us = 11.65333,
 698                        .sr_exit_time_us = 8.32,
 699                        .sr_enter_plus_exit_time_us = 9.38,
 700                        .valid = true,
 701                },
 702                {
 703                        .wm_inst = WM_B,
 704                        .wm_type = WM_TYPE_PSTATE_CHG,
 705                        .pstate_latency_us = 11.65333,
 706                        .sr_exit_time_us = 9.82,
 707                        .sr_enter_plus_exit_time_us = 11.196,
 708                        .valid = true,
 709                },
 710                {
 711                        .wm_inst = WM_C,
 712                        .wm_type = WM_TYPE_PSTATE_CHG,
 713                        .pstate_latency_us = 11.65333,
 714                        .sr_exit_time_us = 9.89,
 715                        .sr_enter_plus_exit_time_us = 11.24,
 716                        .valid = true,
 717                },
 718                {
 719                        .wm_inst = WM_D,
 720                        .wm_type = WM_TYPE_PSTATE_CHG,
 721                        .pstate_latency_us = 11.65333,
 722                        .sr_exit_time_us = 9.748,
 723                        .sr_enter_plus_exit_time_us = 11.102,
 724                        .valid = true,
 725                },
 726        }
 727};
 728
 729static struct wm_table ddr4_wm_table_rn = {
 730        .entries = {
 731                {
 732                        .wm_inst = WM_A,
 733                        .wm_type = WM_TYPE_PSTATE_CHG,
 734                        .pstate_latency_us = 11.72,
 735                        .sr_exit_time_us = 11.90,
 736                        .sr_enter_plus_exit_time_us = 12.80,
 737                        .valid = true,
 738                },
 739                {
 740                        .wm_inst = WM_B,
 741                        .wm_type = WM_TYPE_PSTATE_CHG,
 742                        .pstate_latency_us = 11.72,
 743                        .sr_exit_time_us = 13.18,
 744                        .sr_enter_plus_exit_time_us = 14.30,
 745                        .valid = true,
 746                },
 747                {
 748                        .wm_inst = WM_C,
 749                        .wm_type = WM_TYPE_PSTATE_CHG,
 750                        .pstate_latency_us = 11.72,
 751                        .sr_exit_time_us = 13.18,
 752                        .sr_enter_plus_exit_time_us = 14.30,
 753                        .valid = true,
 754                },
 755                {
 756                        .wm_inst = WM_D,
 757                        .wm_type = WM_TYPE_PSTATE_CHG,
 758                        .pstate_latency_us = 11.72,
 759                        .sr_exit_time_us = 13.18,
 760                        .sr_enter_plus_exit_time_us = 14.30,
 761                        .valid = true,
 762                },
 763        }
 764};
 765
 766static struct wm_table ddr4_1R_wm_table_rn = {
 767        .entries = {
 768                {
 769                        .wm_inst = WM_A,
 770                        .wm_type = WM_TYPE_PSTATE_CHG,
 771                        .pstate_latency_us = 11.72,
 772                        .sr_exit_time_us = 13.90,
 773                        .sr_enter_plus_exit_time_us = 14.80,
 774                        .valid = true,
 775                },
 776                {
 777                        .wm_inst = WM_B,
 778                        .wm_type = WM_TYPE_PSTATE_CHG,
 779                        .pstate_latency_us = 11.72,
 780                        .sr_exit_time_us = 13.90,
 781                        .sr_enter_plus_exit_time_us = 14.80,
 782                        .valid = true,
 783                },
 784                {
 785                        .wm_inst = WM_C,
 786                        .wm_type = WM_TYPE_PSTATE_CHG,
 787                        .pstate_latency_us = 11.72,
 788                        .sr_exit_time_us = 13.90,
 789                        .sr_enter_plus_exit_time_us = 14.80,
 790                        .valid = true,
 791                },
 792                {
 793                        .wm_inst = WM_D,
 794                        .wm_type = WM_TYPE_PSTATE_CHG,
 795                        .pstate_latency_us = 11.72,
 796                        .sr_exit_time_us = 13.90,
 797                        .sr_enter_plus_exit_time_us = 14.80,
 798                        .valid = true,
 799                },
 800        }
 801};
 802
 803static struct wm_table lpddr4_wm_table_rn = {
 804        .entries = {
 805                {
 806                        .wm_inst = WM_A,
 807                        .wm_type = WM_TYPE_PSTATE_CHG,
 808                        .pstate_latency_us = 11.65333,
 809                        .sr_exit_time_us = 7.32,
 810                        .sr_enter_plus_exit_time_us = 8.38,
 811                        .valid = true,
 812                },
 813                {
 814                        .wm_inst = WM_B,
 815                        .wm_type = WM_TYPE_PSTATE_CHG,
 816                        .pstate_latency_us = 11.65333,
 817                        .sr_exit_time_us = 9.82,
 818                        .sr_enter_plus_exit_time_us = 11.196,
 819                        .valid = true,
 820                },
 821                {
 822                        .wm_inst = WM_C,
 823                        .wm_type = WM_TYPE_PSTATE_CHG,
 824                        .pstate_latency_us = 11.65333,
 825                        .sr_exit_time_us = 9.89,
 826                        .sr_enter_plus_exit_time_us = 11.24,
 827                        .valid = true,
 828                },
 829                {
 830                        .wm_inst = WM_D,
 831                        .wm_type = WM_TYPE_PSTATE_CHG,
 832                        .pstate_latency_us = 11.65333,
 833                        .sr_exit_time_us = 9.748,
 834                        .sr_enter_plus_exit_time_us = 11.102,
 835                        .valid = true,
 836                },
 837        }
 838};
 839
 840static unsigned int find_socclk_for_voltage(struct dpm_clocks *clock_table, unsigned int voltage)
 841{
 842        int i;
 843
 844        for (i = 0; i < PP_SMU_NUM_SOCCLK_DPM_LEVELS; i++) {
 845                if (clock_table->SocClocks[i].Vol == voltage)
 846                        return clock_table->SocClocks[i].Freq;
 847        }
 848
 849        ASSERT(0);
 850        return 0;
 851}
 852
 853static unsigned int find_dcfclk_for_voltage(struct dpm_clocks *clock_table, unsigned int voltage)
 854{
 855        int i;
 856
 857        for (i = 0; i < PP_SMU_NUM_DCFCLK_DPM_LEVELS; i++) {
 858                if (clock_table->DcfClocks[i].Vol == voltage)
 859                        return clock_table->DcfClocks[i].Freq;
 860        }
 861
 862        ASSERT(0);
 863        return 0;
 864}
 865
 866static void rn_clk_mgr_helper_populate_bw_params(struct clk_bw_params *bw_params, struct dpm_clocks *clock_table, struct integrated_info *bios_info)
 867{
 868        int i, j = 0;
 869
 870        j = -1;
 871
 872        ASSERT(PP_SMU_NUM_FCLK_DPM_LEVELS <= MAX_NUM_DPM_LVL);
 873
 874        /* Find lowest DPM, FCLK is filled in reverse order*/
 875
 876        for (i = PP_SMU_NUM_FCLK_DPM_LEVELS - 1; i >= 0; i--) {
 877                if (clock_table->FClocks[i].Freq != 0 && clock_table->FClocks[i].Vol != 0) {
 878                        j = i;
 879                        break;
 880                }
 881        }
 882
 883        if (j == -1) {
 884                /* clock table is all 0s, just use our own hardcode */
 885                ASSERT(0);
 886                return;
 887        }
 888
 889        bw_params->clk_table.num_entries = j + 1;
 890
 891        for (i = 0; i < bw_params->clk_table.num_entries; i++, j--) {
 892                bw_params->clk_table.entries[i].fclk_mhz = clock_table->FClocks[j].Freq;
 893                bw_params->clk_table.entries[i].memclk_mhz = clock_table->MemClocks[j].Freq;
 894                bw_params->clk_table.entries[i].voltage = clock_table->FClocks[j].Vol;
 895                bw_params->clk_table.entries[i].dcfclk_mhz = find_dcfclk_for_voltage(clock_table, clock_table->FClocks[j].Vol);
 896                bw_params->clk_table.entries[i].socclk_mhz = find_socclk_for_voltage(clock_table,
 897                                                                        bw_params->clk_table.entries[i].voltage);
 898        }
 899
 900        bw_params->vram_type = bios_info->memory_type;
 901        bw_params->num_channels = bios_info->ma_channel_number;
 902
 903        for (i = 0; i < WM_SET_COUNT; i++) {
 904                bw_params->wm_table.entries[i].wm_inst = i;
 905
 906                if (i >= bw_params->clk_table.num_entries) {
 907                        bw_params->wm_table.entries[i].valid = false;
 908                        continue;
 909                }
 910
 911                bw_params->wm_table.entries[i].wm_type = WM_TYPE_PSTATE_CHG;
 912                bw_params->wm_table.entries[i].valid = true;
 913        }
 914
 915        if (bw_params->vram_type == LpDdr4MemType) {
 916                /*
 917                 * WM set D will be re-purposed for memory retraining
 918                 */
 919                bw_params->wm_table.entries[WM_D].pstate_latency_us = LPDDR_MEM_RETRAIN_LATENCY;
 920                bw_params->wm_table.entries[WM_D].wm_inst = WM_D;
 921                bw_params->wm_table.entries[WM_D].wm_type = WM_TYPE_RETRAINING;
 922                bw_params->wm_table.entries[WM_D].valid = true;
 923        }
 924
 925}
 926
 927void rn_clk_mgr_construct(
 928                struct dc_context *ctx,
 929                struct clk_mgr_internal *clk_mgr,
 930                struct pp_smu_funcs *pp_smu,
 931                struct dccg *dccg)
 932{
 933        struct dc_debug_options *debug = &ctx->dc->debug;
 934        struct dpm_clocks clock_table = { 0 };
 935        enum pp_smu_status status = 0;
 936        int is_green_sardine = 0;
 937
 938#if defined(CONFIG_DRM_AMD_DC_DCN)
 939        is_green_sardine = ASICREV_IS_GREEN_SARDINE(ctx->asic_id.hw_internal_rev);
 940#endif
 941
 942        clk_mgr->base.ctx = ctx;
 943        clk_mgr->base.funcs = &dcn21_funcs;
 944
 945        clk_mgr->pp_smu = pp_smu;
 946
 947        clk_mgr->dccg = dccg;
 948        clk_mgr->dfs_bypass_disp_clk = 0;
 949
 950        clk_mgr->dprefclk_ss_percentage = 0;
 951        clk_mgr->dprefclk_ss_divider = 1000;
 952        clk_mgr->ss_on_dprefclk = false;
 953        clk_mgr->dfs_ref_freq_khz = 48000;
 954
 955        clk_mgr->smu_ver = rn_vbios_smu_get_smu_version(clk_mgr);
 956
 957        if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) {
 958                dcn21_funcs.update_clocks = dcn2_update_clocks_fpga;
 959                clk_mgr->base.dentist_vco_freq_khz = 3600000;
 960        } else {
 961                struct clk_log_info log_info = {0};
 962
 963                clk_mgr->periodic_retraining_disabled = rn_vbios_smu_is_periodic_retraining_disabled(clk_mgr);
 964
 965                /* SMU Version 55.51.0 and up no longer have an issue
 966                 * that needs to limit minimum dispclk */
 967                if (clk_mgr->smu_ver >= SMU_VER_55_51_0)
 968                        debug->min_disp_clk_khz = 0;
 969
 970                /* TODO: Check we get what we expect during bringup */
 971                clk_mgr->base.dentist_vco_freq_khz = get_vco_frequency_from_reg(clk_mgr);
 972
 973                /* in case we don't get a value from the register, use default */
 974                if (clk_mgr->base.dentist_vco_freq_khz == 0)
 975                        clk_mgr->base.dentist_vco_freq_khz = 3600000;
 976
 977                if (ctx->dc_bios->integrated_info->memory_type == LpDdr4MemType) {
 978                        if (clk_mgr->periodic_retraining_disabled) {
 979                                rn_bw_params.wm_table = lpddr4_wm_table_with_disabled_ppt;
 980                        } else {
 981                                if (is_green_sardine)
 982                                        rn_bw_params.wm_table = lpddr4_wm_table_gs;
 983                                else
 984                                        rn_bw_params.wm_table = lpddr4_wm_table_rn;
 985                        }
 986                } else {
 987                        if (is_green_sardine)
 988                                rn_bw_params.wm_table = ddr4_wm_table_gs;
 989                        else {
 990                                if (ctx->dc->config.is_single_rank_dimm)
 991                                        rn_bw_params.wm_table = ddr4_1R_wm_table_rn;
 992                                else
 993                                        rn_bw_params.wm_table = ddr4_wm_table_rn;
 994                        }
 995                }
 996                /* Saved clocks configured at boot for debug purposes */
 997                rn_dump_clk_registers(&clk_mgr->base.boot_snapshot, &clk_mgr->base, &log_info);
 998        }
 999
1000        clk_mgr->base.dprefclk_khz = 600000;
1001        dce_clock_read_ss_info(clk_mgr);
1002
1003
1004        clk_mgr->base.bw_params = &rn_bw_params;
1005
1006        if (pp_smu && pp_smu->rn_funcs.get_dpm_clock_table) {
1007                status = pp_smu->rn_funcs.get_dpm_clock_table(&pp_smu->rn_funcs.pp_smu, &clock_table);
1008
1009                if (status == PP_SMU_RESULT_OK &&
1010                    ctx->dc_bios && ctx->dc_bios->integrated_info) {
1011                        rn_clk_mgr_helper_populate_bw_params (clk_mgr->base.bw_params, &clock_table, ctx->dc_bios->integrated_info);
1012                        /* treat memory config as single channel if memory is asymmetrics. */
1013                        if (ctx->dc->config.is_asymmetric_memory)
1014                                clk_mgr->base.bw_params->num_channels = 1;
1015                }
1016        }
1017
1018        if (!IS_FPGA_MAXIMUS_DC(ctx->dce_environment) && clk_mgr->smu_ver >= 0x00371500) {
1019                /* enable powerfeatures when displaycount goes to 0 */
1020                rn_vbios_smu_enable_48mhz_tmdp_refclk_pwrdwn(clk_mgr, !debug->disable_48mhz_pwrdwn);
1021        }
1022}
1023
1024