1f9490399SQingqing Zhuo /* 2f9490399SQingqing Zhuo * Copyright 2021 Advanced Micro Devices, Inc. 3f9490399SQingqing Zhuo * 4f9490399SQingqing Zhuo * Permission is hereby granted, free of charge, to any person obtaining a 5f9490399SQingqing Zhuo * copy of this software and associated documentation files (the "Software"), 6f9490399SQingqing Zhuo * to deal in the Software without restriction, including without limitation 7f9490399SQingqing Zhuo * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8f9490399SQingqing Zhuo * and/or sell copies of the Software, and to permit persons to whom the 9f9490399SQingqing Zhuo * Software is furnished to do so, subject to the following conditions: 10f9490399SQingqing Zhuo * 11f9490399SQingqing Zhuo * The above copyright notice and this permission notice shall be included in 12f9490399SQingqing Zhuo * all copies or substantial portions of the Software. 13f9490399SQingqing Zhuo * 14f9490399SQingqing Zhuo * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15f9490399SQingqing Zhuo * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16f9490399SQingqing Zhuo * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17f9490399SQingqing Zhuo * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18f9490399SQingqing Zhuo * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19f9490399SQingqing Zhuo * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20f9490399SQingqing Zhuo * OTHER DEALINGS IN THE SOFTWARE. 21f9490399SQingqing Zhuo * 22f9490399SQingqing Zhuo * Authors: AMD 23f9490399SQingqing Zhuo * 24f9490399SQingqing Zhuo */ 25f9490399SQingqing Zhuo 26f9490399SQingqing Zhuo 27f9490399SQingqing Zhuo 28f9490399SQingqing Zhuo #include "dccg.h" 29f9490399SQingqing Zhuo #include "clk_mgr_internal.h" 30f9490399SQingqing Zhuo 31f9490399SQingqing Zhuo // For dce12_get_dp_ref_freq_khz 32f9490399SQingqing Zhuo #include "dce100/dce_clk_mgr.h" 33f9490399SQingqing Zhuo // For dcn20_update_clocks_update_dpp_dto 34f9490399SQingqing Zhuo #include "dcn20/dcn20_clk_mgr.h" 35f9490399SQingqing Zhuo #include "dcn31/dcn31_clk_mgr.h" 36f9490399SQingqing Zhuo #include "dcn315_clk_mgr.h" 37f9490399SQingqing Zhuo 38f9490399SQingqing Zhuo #include "core_types.h" 39f9490399SQingqing Zhuo #include "dcn315_smu.h" 40f9490399SQingqing Zhuo #include "dm_helpers.h" 41f9490399SQingqing Zhuo 42f9490399SQingqing Zhuo #include "dc_dmub_srv.h" 43f9490399SQingqing Zhuo 44c8b1d0feSLeo Chen #include "logger_types.h" 45c8b1d0feSLeo Chen #undef DC_LOGGER 46c8b1d0feSLeo Chen #define DC_LOGGER \ 47c8b1d0feSLeo Chen clk_mgr->base.base.ctx->logger 48c8b1d0feSLeo Chen 49*6ca7415fSWenjing Liu #include "link.h" 50f9490399SQingqing Zhuo 51f9490399SQingqing Zhuo #define TO_CLK_MGR_DCN315(clk_mgr)\ 52f9490399SQingqing Zhuo container_of(clk_mgr, struct clk_mgr_dcn315, base) 53f9490399SQingqing Zhuo 5463423cf1SDmytro Laktyushkin #define UNSUPPORTED_DCFCLK 10000000 5563423cf1SDmytro Laktyushkin #define MIN_DPP_DISP_CLK 100000 5663423cf1SDmytro Laktyushkin 57f9490399SQingqing Zhuo static int dcn315_get_active_display_cnt_wa( 58f9490399SQingqing Zhuo struct dc *dc, 59f9490399SQingqing Zhuo struct dc_state *context) 60f9490399SQingqing Zhuo { 61f9490399SQingqing Zhuo int i, display_count; 62f9490399SQingqing Zhuo bool tmds_present = false; 63f9490399SQingqing Zhuo 64f9490399SQingqing Zhuo display_count = 0; 65f9490399SQingqing Zhuo for (i = 0; i < context->stream_count; i++) { 66f9490399SQingqing Zhuo const struct dc_stream_state *stream = context->streams[i]; 67f9490399SQingqing Zhuo 68f9490399SQingqing Zhuo if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A || 69f9490399SQingqing Zhuo stream->signal == SIGNAL_TYPE_DVI_SINGLE_LINK || 70f9490399SQingqing Zhuo stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK) 71f9490399SQingqing Zhuo tmds_present = true; 72f9490399SQingqing Zhuo } 73f9490399SQingqing Zhuo 74f9490399SQingqing Zhuo for (i = 0; i < dc->link_count; i++) { 75f9490399SQingqing Zhuo const struct dc_link *link = dc->links[i]; 76f9490399SQingqing Zhuo 77f9490399SQingqing Zhuo /* abusing the fact that the dig and phy are coupled to see if the phy is enabled */ 78f9490399SQingqing Zhuo if (link->link_enc && link->link_enc->funcs->is_dig_enabled && 79f9490399SQingqing Zhuo link->link_enc->funcs->is_dig_enabled(link->link_enc)) 80f9490399SQingqing Zhuo display_count++; 81f9490399SQingqing Zhuo } 82f9490399SQingqing Zhuo 83f9490399SQingqing Zhuo /* WA for hang on HDMI after display off back back on*/ 84f9490399SQingqing Zhuo if (display_count == 0 && tmds_present) 85f9490399SQingqing Zhuo display_count = 1; 86f9490399SQingqing Zhuo 87f9490399SQingqing Zhuo return display_count; 88f9490399SQingqing Zhuo } 89f9490399SQingqing Zhuo 90abffd871SMeenakshikumar Somasundaram static void dcn315_disable_otg_wa(struct clk_mgr *clk_mgr_base, struct dc_state *context, bool disable) 91f9490399SQingqing Zhuo { 92f9490399SQingqing Zhuo struct dc *dc = clk_mgr_base->ctx->dc; 93f9490399SQingqing Zhuo int i; 94f9490399SQingqing Zhuo 95f9490399SQingqing Zhuo for (i = 0; i < dc->res_pool->pipe_count; ++i) { 96165ab7b4SNicholas Kazlauskas struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i]; 97f9490399SQingqing Zhuo 98f9490399SQingqing Zhuo if (pipe->top_pipe || pipe->prev_odm_pipe) 99f9490399SQingqing Zhuo continue; 10066a19720SNicholas Kazlauskas if (pipe->stream && (pipe->stream->dpms_off || pipe->plane_state == NULL || 10166a19720SNicholas Kazlauskas dc_is_virtual_signal(pipe->stream->signal))) { 102abffd871SMeenakshikumar Somasundaram if (disable) { 103f9490399SQingqing Zhuo pipe->stream_res.tg->funcs->immediate_disable_crtc(pipe->stream_res.tg); 104abffd871SMeenakshikumar Somasundaram reset_sync_context_for_pipe(dc, context, i); 105abffd871SMeenakshikumar Somasundaram } else 106f9490399SQingqing Zhuo pipe->stream_res.tg->funcs->enable_crtc(pipe->stream_res.tg); 107f9490399SQingqing Zhuo } 108f9490399SQingqing Zhuo } 109f9490399SQingqing Zhuo } 110f9490399SQingqing Zhuo 111f9490399SQingqing Zhuo static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base, 112f9490399SQingqing Zhuo struct dc_state *context, 113f9490399SQingqing Zhuo bool safe_to_lower) 114f9490399SQingqing Zhuo { 115f9490399SQingqing Zhuo union dmub_rb_cmd cmd; 116f9490399SQingqing Zhuo struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); 117f9490399SQingqing Zhuo struct dc_clocks *new_clocks = &context->bw_ctx.bw.dcn.clk; 118f9490399SQingqing Zhuo struct dc *dc = clk_mgr_base->ctx->dc; 119f9490399SQingqing Zhuo int display_count; 120f9490399SQingqing Zhuo bool update_dppclk = false; 121f9490399SQingqing Zhuo bool update_dispclk = false; 122f9490399SQingqing Zhuo bool dpp_clock_lowered = false; 123f9490399SQingqing Zhuo 124f9490399SQingqing Zhuo if (dc->work_arounds.skip_clock_update) 125f9490399SQingqing Zhuo return; 126f9490399SQingqing Zhuo 127f9490399SQingqing Zhuo clk_mgr_base->clks.zstate_support = new_clocks->zstate_support; 128f9490399SQingqing Zhuo /* 129f9490399SQingqing Zhuo * if it is safe to lower, but we are already in the lower state, we don't have to do anything 130f9490399SQingqing Zhuo * also if safe to lower is false, we just go in the higher state 131f9490399SQingqing Zhuo */ 132f9490399SQingqing Zhuo clk_mgr_base->clks.zstate_support = new_clocks->zstate_support; 133f9490399SQingqing Zhuo if (safe_to_lower) { 134f9490399SQingqing Zhuo /* check that we're not already in lower */ 135f9490399SQingqing Zhuo if (clk_mgr_base->clks.pwr_state != DCN_PWR_STATE_LOW_POWER) { 136f9490399SQingqing Zhuo display_count = dcn315_get_active_display_cnt_wa(dc, context); 137f9490399SQingqing Zhuo /* if we can go lower, go lower */ 138f9490399SQingqing Zhuo if (display_count == 0) { 139f9490399SQingqing Zhuo union display_idle_optimization_u idle_info = { 0 }; 140f9490399SQingqing Zhuo idle_info.idle_info.df_request_disabled = 1; 141f9490399SQingqing Zhuo idle_info.idle_info.phy_ref_clk_off = 1; 142e7145aaeSCharlene Liu idle_info.idle_info.s0i2_rdy = 1; 143f9490399SQingqing Zhuo dcn315_smu_set_display_idle_optimization(clk_mgr, idle_info.data); 144f9490399SQingqing Zhuo /* update power state */ 145f9490399SQingqing Zhuo clk_mgr_base->clks.pwr_state = DCN_PWR_STATE_LOW_POWER; 146f9490399SQingqing Zhuo } 147f9490399SQingqing Zhuo } 148f9490399SQingqing Zhuo } else { 149f9490399SQingqing Zhuo /* check that we're not already in D0 */ 150f9490399SQingqing Zhuo if (clk_mgr_base->clks.pwr_state != DCN_PWR_STATE_MISSION_MODE) { 151f9490399SQingqing Zhuo union display_idle_optimization_u idle_info = { 0 }; 152f9490399SQingqing Zhuo dcn315_smu_set_display_idle_optimization(clk_mgr, idle_info.data); 153f9490399SQingqing Zhuo /* update power state */ 154f9490399SQingqing Zhuo clk_mgr_base->clks.pwr_state = DCN_PWR_STATE_MISSION_MODE; 155f9490399SQingqing Zhuo } 156f9490399SQingqing Zhuo } 157f9490399SQingqing Zhuo 15863423cf1SDmytro Laktyushkin /* Lock pstate by requesting unsupported dcfclk if change is unsupported */ 15963423cf1SDmytro Laktyushkin if (!new_clocks->p_state_change_support) 16063423cf1SDmytro Laktyushkin new_clocks->dcfclk_khz = UNSUPPORTED_DCFCLK; 161f9490399SQingqing Zhuo if (should_set_clock(safe_to_lower, new_clocks->dcfclk_khz, clk_mgr_base->clks.dcfclk_khz)) { 162f9490399SQingqing Zhuo clk_mgr_base->clks.dcfclk_khz = new_clocks->dcfclk_khz; 163f9490399SQingqing Zhuo dcn315_smu_set_hard_min_dcfclk(clk_mgr, clk_mgr_base->clks.dcfclk_khz); 164f9490399SQingqing Zhuo } 165f9490399SQingqing Zhuo 166f9490399SQingqing Zhuo if (should_set_clock(safe_to_lower, 167f9490399SQingqing Zhuo new_clocks->dcfclk_deep_sleep_khz, clk_mgr_base->clks.dcfclk_deep_sleep_khz)) { 168f9490399SQingqing Zhuo clk_mgr_base->clks.dcfclk_deep_sleep_khz = new_clocks->dcfclk_deep_sleep_khz; 169f9490399SQingqing Zhuo dcn315_smu_set_min_deep_sleep_dcfclk(clk_mgr, clk_mgr_base->clks.dcfclk_deep_sleep_khz); 170f9490399SQingqing Zhuo } 171f9490399SQingqing Zhuo 172f9490399SQingqing Zhuo // workaround: Limit dppclk to 100Mhz to avoid lower eDP panel switch to plus 4K monitor underflow. 173f9490399SQingqing Zhuo if (!IS_DIAG_DC(dc->ctx->dce_environment)) { 17463423cf1SDmytro Laktyushkin if (new_clocks->dppclk_khz < MIN_DPP_DISP_CLK) 17563423cf1SDmytro Laktyushkin new_clocks->dppclk_khz = MIN_DPP_DISP_CLK; 17663423cf1SDmytro Laktyushkin if (new_clocks->dispclk_khz < MIN_DPP_DISP_CLK) 17763423cf1SDmytro Laktyushkin new_clocks->dispclk_khz = MIN_DPP_DISP_CLK; 178f9490399SQingqing Zhuo } 179f9490399SQingqing Zhuo 180f9490399SQingqing Zhuo if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr->base.clks.dppclk_khz)) { 181f9490399SQingqing Zhuo if (clk_mgr->base.clks.dppclk_khz > new_clocks->dppclk_khz) 182f9490399SQingqing Zhuo dpp_clock_lowered = true; 183f9490399SQingqing Zhuo clk_mgr_base->clks.dppclk_khz = new_clocks->dppclk_khz; 184f9490399SQingqing Zhuo update_dppclk = true; 185f9490399SQingqing Zhuo } 186f9490399SQingqing Zhuo 187f9490399SQingqing Zhuo if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) { 1888a077d9cSDmytro Laktyushkin /* No need to apply the w/a if we haven't taken over from bios yet */ 1898a077d9cSDmytro Laktyushkin if (clk_mgr_base->clks.dispclk_khz) 190abffd871SMeenakshikumar Somasundaram dcn315_disable_otg_wa(clk_mgr_base, context, true); 191f9490399SQingqing Zhuo 192f9490399SQingqing Zhuo clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz; 193f9490399SQingqing Zhuo dcn315_smu_set_dispclk(clk_mgr, clk_mgr_base->clks.dispclk_khz); 1948a077d9cSDmytro Laktyushkin if (clk_mgr_base->clks.dispclk_khz) 195abffd871SMeenakshikumar Somasundaram dcn315_disable_otg_wa(clk_mgr_base, context, false); 196f9490399SQingqing Zhuo 197f9490399SQingqing Zhuo update_dispclk = true; 198f9490399SQingqing Zhuo } 199f9490399SQingqing Zhuo 200f9490399SQingqing Zhuo if (dpp_clock_lowered) { 201f9490399SQingqing Zhuo // increase per DPP DTO before lowering global dppclk 202f9490399SQingqing Zhuo dcn20_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower); 203f9490399SQingqing Zhuo dcn315_smu_set_dppclk(clk_mgr, clk_mgr_base->clks.dppclk_khz); 204f9490399SQingqing Zhuo } else { 205f9490399SQingqing Zhuo // increase global DPPCLK before lowering per DPP DTO 206f9490399SQingqing Zhuo if (update_dppclk || update_dispclk) 207f9490399SQingqing Zhuo dcn315_smu_set_dppclk(clk_mgr, clk_mgr_base->clks.dppclk_khz); 208f9490399SQingqing Zhuo // always update dtos unless clock is lowered and not safe to lower 209f9490399SQingqing Zhuo if (new_clocks->dppclk_khz >= dc->current_state->bw_ctx.bw.dcn.clk.dppclk_khz) 210f9490399SQingqing Zhuo dcn20_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower); 211f9490399SQingqing Zhuo } 212f9490399SQingqing Zhuo 213f9490399SQingqing Zhuo // notify DMCUB of latest clocks 214f9490399SQingqing Zhuo memset(&cmd, 0, sizeof(cmd)); 215f9490399SQingqing Zhuo cmd.notify_clocks.header.type = DMUB_CMD__CLK_MGR; 216f9490399SQingqing Zhuo cmd.notify_clocks.header.sub_type = DMUB_CMD__CLK_MGR_NOTIFY_CLOCKS; 217f9490399SQingqing Zhuo cmd.notify_clocks.clocks.dcfclk_khz = clk_mgr_base->clks.dcfclk_khz; 218f9490399SQingqing Zhuo cmd.notify_clocks.clocks.dcfclk_deep_sleep_khz = 219f9490399SQingqing Zhuo clk_mgr_base->clks.dcfclk_deep_sleep_khz; 220f9490399SQingqing Zhuo cmd.notify_clocks.clocks.dispclk_khz = clk_mgr_base->clks.dispclk_khz; 221f9490399SQingqing Zhuo cmd.notify_clocks.clocks.dppclk_khz = clk_mgr_base->clks.dppclk_khz; 222f9490399SQingqing Zhuo 223f9490399SQingqing Zhuo dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd); 224f9490399SQingqing Zhuo dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv); 225f9490399SQingqing Zhuo dc_dmub_srv_wait_idle(dc->ctx->dmub_srv); 226f9490399SQingqing Zhuo } 227f9490399SQingqing Zhuo 228f9490399SQingqing Zhuo static void dcn315_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass, 229f9490399SQingqing Zhuo struct clk_mgr *clk_mgr_base, struct clk_log_info *log_info) 230f9490399SQingqing Zhuo { 231f9490399SQingqing Zhuo return; 232f9490399SQingqing Zhuo } 233f9490399SQingqing Zhuo 234f9490399SQingqing Zhuo static struct clk_bw_params dcn315_bw_params = { 235f9490399SQingqing Zhuo .vram_type = Ddr4MemType, 23689c342a9SDmytro Laktyushkin .num_channels = 2, 237f9490399SQingqing Zhuo .clk_table = { 23889c342a9SDmytro Laktyushkin .entries = { 23989c342a9SDmytro Laktyushkin { 24089c342a9SDmytro Laktyushkin .voltage = 0, 24189c342a9SDmytro Laktyushkin .dispclk_mhz = 640, 24289c342a9SDmytro Laktyushkin .dppclk_mhz = 640, 24389c342a9SDmytro Laktyushkin .phyclk_mhz = 810, 24489c342a9SDmytro Laktyushkin .phyclk_d18_mhz = 667, 24589c342a9SDmytro Laktyushkin .dtbclk_mhz = 600, 24689c342a9SDmytro Laktyushkin }, 24789c342a9SDmytro Laktyushkin { 24889c342a9SDmytro Laktyushkin .voltage = 1, 24989c342a9SDmytro Laktyushkin .dispclk_mhz = 739, 25089c342a9SDmytro Laktyushkin .dppclk_mhz = 739, 25189c342a9SDmytro Laktyushkin .phyclk_mhz = 810, 25289c342a9SDmytro Laktyushkin .phyclk_d18_mhz = 667, 25389c342a9SDmytro Laktyushkin .dtbclk_mhz = 600, 25489c342a9SDmytro Laktyushkin }, 25589c342a9SDmytro Laktyushkin { 25689c342a9SDmytro Laktyushkin .voltage = 2, 25789c342a9SDmytro Laktyushkin .dispclk_mhz = 960, 25889c342a9SDmytro Laktyushkin .dppclk_mhz = 960, 25989c342a9SDmytro Laktyushkin .phyclk_mhz = 810, 26089c342a9SDmytro Laktyushkin .phyclk_d18_mhz = 667, 26189c342a9SDmytro Laktyushkin .dtbclk_mhz = 600, 26289c342a9SDmytro Laktyushkin }, 26389c342a9SDmytro Laktyushkin { 26489c342a9SDmytro Laktyushkin .voltage = 3, 26589c342a9SDmytro Laktyushkin .dispclk_mhz = 1200, 26689c342a9SDmytro Laktyushkin .dppclk_mhz = 1200, 26789c342a9SDmytro Laktyushkin .phyclk_mhz = 810, 26889c342a9SDmytro Laktyushkin .phyclk_d18_mhz = 667, 26989c342a9SDmytro Laktyushkin .dtbclk_mhz = 600, 27089c342a9SDmytro Laktyushkin }, 27189c342a9SDmytro Laktyushkin { 27289c342a9SDmytro Laktyushkin .voltage = 4, 27389c342a9SDmytro Laktyushkin .dispclk_mhz = 1372, 27489c342a9SDmytro Laktyushkin .dppclk_mhz = 1372, 27589c342a9SDmytro Laktyushkin .phyclk_mhz = 810, 27689c342a9SDmytro Laktyushkin .phyclk_d18_mhz = 667, 27789c342a9SDmytro Laktyushkin .dtbclk_mhz = 600, 27889c342a9SDmytro Laktyushkin }, 27989c342a9SDmytro Laktyushkin }, 280f9490399SQingqing Zhuo .num_entries = 5, 281f9490399SQingqing Zhuo }, 282f9490399SQingqing Zhuo 283f9490399SQingqing Zhuo }; 284f9490399SQingqing Zhuo 285f9490399SQingqing Zhuo static struct wm_table ddr5_wm_table = { 286f9490399SQingqing Zhuo .entries = { 287f9490399SQingqing Zhuo { 288f9490399SQingqing Zhuo .wm_inst = WM_A, 289f9490399SQingqing Zhuo .wm_type = WM_TYPE_PSTATE_CHG, 29063423cf1SDmytro Laktyushkin .pstate_latency_us = 129.0, 291f9490399SQingqing Zhuo .sr_exit_time_us = 11.5, 292f9490399SQingqing Zhuo .sr_enter_plus_exit_time_us = 14.5, 293f9490399SQingqing Zhuo .valid = true, 294f9490399SQingqing Zhuo }, 295f9490399SQingqing Zhuo { 296f9490399SQingqing Zhuo .wm_inst = WM_B, 297f9490399SQingqing Zhuo .wm_type = WM_TYPE_PSTATE_CHG, 29863423cf1SDmytro Laktyushkin .pstate_latency_us = 129.0, 299f9490399SQingqing Zhuo .sr_exit_time_us = 11.5, 300f9490399SQingqing Zhuo .sr_enter_plus_exit_time_us = 14.5, 301f9490399SQingqing Zhuo .valid = true, 302f9490399SQingqing Zhuo }, 303f9490399SQingqing Zhuo { 304f9490399SQingqing Zhuo .wm_inst = WM_C, 305f9490399SQingqing Zhuo .wm_type = WM_TYPE_PSTATE_CHG, 30663423cf1SDmytro Laktyushkin .pstate_latency_us = 129.0, 307f9490399SQingqing Zhuo .sr_exit_time_us = 11.5, 308f9490399SQingqing Zhuo .sr_enter_plus_exit_time_us = 14.5, 309f9490399SQingqing Zhuo .valid = true, 310f9490399SQingqing Zhuo }, 311f9490399SQingqing Zhuo { 312f9490399SQingqing Zhuo .wm_inst = WM_D, 313f9490399SQingqing Zhuo .wm_type = WM_TYPE_PSTATE_CHG, 31463423cf1SDmytro Laktyushkin .pstate_latency_us = 129.0, 315f9490399SQingqing Zhuo .sr_exit_time_us = 11.5, 316f9490399SQingqing Zhuo .sr_enter_plus_exit_time_us = 14.5, 317f9490399SQingqing Zhuo .valid = true, 318f9490399SQingqing Zhuo }, 319f9490399SQingqing Zhuo } 320f9490399SQingqing Zhuo }; 321f9490399SQingqing Zhuo 322f9490399SQingqing Zhuo static struct wm_table lpddr5_wm_table = { 323f9490399SQingqing Zhuo .entries = { 324f9490399SQingqing Zhuo { 325f9490399SQingqing Zhuo .wm_inst = WM_A, 326f9490399SQingqing Zhuo .wm_type = WM_TYPE_PSTATE_CHG, 327f9490399SQingqing Zhuo .pstate_latency_us = 11.65333, 328f9490399SQingqing Zhuo .sr_exit_time_us = 11.5, 329f9490399SQingqing Zhuo .sr_enter_plus_exit_time_us = 14.5, 330f9490399SQingqing Zhuo .valid = true, 331f9490399SQingqing Zhuo }, 332f9490399SQingqing Zhuo { 333f9490399SQingqing Zhuo .wm_inst = WM_B, 334f9490399SQingqing Zhuo .wm_type = WM_TYPE_PSTATE_CHG, 335f9490399SQingqing Zhuo .pstate_latency_us = 11.65333, 336f9490399SQingqing Zhuo .sr_exit_time_us = 11.5, 337f9490399SQingqing Zhuo .sr_enter_plus_exit_time_us = 14.5, 338f9490399SQingqing Zhuo .valid = true, 339f9490399SQingqing Zhuo }, 340f9490399SQingqing Zhuo { 341f9490399SQingqing Zhuo .wm_inst = WM_C, 342f9490399SQingqing Zhuo .wm_type = WM_TYPE_PSTATE_CHG, 343f9490399SQingqing Zhuo .pstate_latency_us = 11.65333, 344f9490399SQingqing Zhuo .sr_exit_time_us = 11.5, 345f9490399SQingqing Zhuo .sr_enter_plus_exit_time_us = 14.5, 346f9490399SQingqing Zhuo .valid = true, 347f9490399SQingqing Zhuo }, 348f9490399SQingqing Zhuo { 349f9490399SQingqing Zhuo .wm_inst = WM_D, 350f9490399SQingqing Zhuo .wm_type = WM_TYPE_PSTATE_CHG, 351f9490399SQingqing Zhuo .pstate_latency_us = 11.65333, 352f9490399SQingqing Zhuo .sr_exit_time_us = 11.5, 353f9490399SQingqing Zhuo .sr_enter_plus_exit_time_us = 14.5, 354f9490399SQingqing Zhuo .valid = true, 355f9490399SQingqing Zhuo }, 356f9490399SQingqing Zhuo } 357f9490399SQingqing Zhuo }; 358f9490399SQingqing Zhuo 35989c342a9SDmytro Laktyushkin /* Temporary Place holder until we can get them from fuse */ 36089c342a9SDmytro Laktyushkin static DpmClocks_315_t dummy_clocks = { 0 }; 361f9490399SQingqing Zhuo static struct dcn315_watermarks dummy_wms = { 0 }; 362f9490399SQingqing Zhuo 363f9490399SQingqing Zhuo static void dcn315_build_watermark_ranges(struct clk_bw_params *bw_params, struct dcn315_watermarks *table) 364f9490399SQingqing Zhuo { 365f9490399SQingqing Zhuo int i, num_valid_sets; 366f9490399SQingqing Zhuo 367f9490399SQingqing Zhuo num_valid_sets = 0; 368f9490399SQingqing Zhuo 369f9490399SQingqing Zhuo for (i = 0; i < WM_SET_COUNT; i++) { 370f9490399SQingqing Zhuo /* skip empty entries, the smu array has no holes*/ 371f9490399SQingqing Zhuo if (!bw_params->wm_table.entries[i].valid) 372f9490399SQingqing Zhuo continue; 373f9490399SQingqing Zhuo 374f9490399SQingqing Zhuo table->WatermarkRow[WM_DCFCLK][num_valid_sets].WmSetting = bw_params->wm_table.entries[i].wm_inst; 375f9490399SQingqing Zhuo table->WatermarkRow[WM_DCFCLK][num_valid_sets].WmType = bw_params->wm_table.entries[i].wm_type; 376f9490399SQingqing Zhuo /* We will not select WM based on fclk, so leave it as unconstrained */ 377f9490399SQingqing Zhuo table->WatermarkRow[WM_DCFCLK][num_valid_sets].MinClock = 0; 378f9490399SQingqing Zhuo table->WatermarkRow[WM_DCFCLK][num_valid_sets].MaxClock = 0xFFFF; 379f9490399SQingqing Zhuo 380f9490399SQingqing Zhuo if (table->WatermarkRow[WM_DCFCLK][num_valid_sets].WmType == WM_TYPE_PSTATE_CHG) { 381f9490399SQingqing Zhuo if (i == 0) 382f9490399SQingqing Zhuo table->WatermarkRow[WM_DCFCLK][num_valid_sets].MinMclk = 0; 383f9490399SQingqing Zhuo else { 384f9490399SQingqing Zhuo /* add 1 to make it non-overlapping with next lvl */ 385f9490399SQingqing Zhuo table->WatermarkRow[WM_DCFCLK][num_valid_sets].MinMclk = 386f9490399SQingqing Zhuo bw_params->clk_table.entries[i - 1].dcfclk_mhz + 1; 387f9490399SQingqing Zhuo } 388f9490399SQingqing Zhuo table->WatermarkRow[WM_DCFCLK][num_valid_sets].MaxMclk = 389f9490399SQingqing Zhuo bw_params->clk_table.entries[i].dcfclk_mhz; 390f9490399SQingqing Zhuo 391f9490399SQingqing Zhuo } else { 392f9490399SQingqing Zhuo /* unconstrained for memory retraining */ 393f9490399SQingqing Zhuo table->WatermarkRow[WM_DCFCLK][num_valid_sets].MinClock = 0; 394f9490399SQingqing Zhuo table->WatermarkRow[WM_DCFCLK][num_valid_sets].MaxClock = 0xFFFF; 395f9490399SQingqing Zhuo 396f9490399SQingqing Zhuo /* Modify previous watermark range to cover up to max */ 397f9490399SQingqing Zhuo table->WatermarkRow[WM_DCFCLK][num_valid_sets - 1].MaxClock = 0xFFFF; 398f9490399SQingqing Zhuo } 399f9490399SQingqing Zhuo num_valid_sets++; 400f9490399SQingqing Zhuo } 401f9490399SQingqing Zhuo 402f9490399SQingqing Zhuo ASSERT(num_valid_sets != 0); /* Must have at least one set of valid watermarks */ 403f9490399SQingqing Zhuo 404f9490399SQingqing Zhuo /* modify the min and max to make sure we cover the whole range*/ 405f9490399SQingqing Zhuo table->WatermarkRow[WM_DCFCLK][0].MinMclk = 0; 406f9490399SQingqing Zhuo table->WatermarkRow[WM_DCFCLK][0].MinClock = 0; 407f9490399SQingqing Zhuo table->WatermarkRow[WM_DCFCLK][num_valid_sets - 1].MaxMclk = 0xFFFF; 408f9490399SQingqing Zhuo table->WatermarkRow[WM_DCFCLK][num_valid_sets - 1].MaxClock = 0xFFFF; 409f9490399SQingqing Zhuo 410f9490399SQingqing Zhuo /* This is for writeback only, does not matter currently as no writeback support*/ 411f9490399SQingqing Zhuo table->WatermarkRow[WM_SOCCLK][0].WmSetting = WM_A; 412f9490399SQingqing Zhuo table->WatermarkRow[WM_SOCCLK][0].MinClock = 0; 413f9490399SQingqing Zhuo table->WatermarkRow[WM_SOCCLK][0].MaxClock = 0xFFFF; 414f9490399SQingqing Zhuo table->WatermarkRow[WM_SOCCLK][0].MinMclk = 0; 415f9490399SQingqing Zhuo table->WatermarkRow[WM_SOCCLK][0].MaxMclk = 0xFFFF; 416f9490399SQingqing Zhuo } 417f9490399SQingqing Zhuo 418f9490399SQingqing Zhuo static void dcn315_notify_wm_ranges(struct clk_mgr *clk_mgr_base) 419f9490399SQingqing Zhuo { 420f9490399SQingqing Zhuo struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); 421f9490399SQingqing Zhuo struct clk_mgr_dcn315 *clk_mgr_dcn315 = TO_CLK_MGR_DCN315(clk_mgr); 422f9490399SQingqing Zhuo struct dcn315_watermarks *table = clk_mgr_dcn315->smu_wm_set.wm_set; 423f9490399SQingqing Zhuo 424f9490399SQingqing Zhuo if (!clk_mgr->smu_ver) 425f9490399SQingqing Zhuo return; 426f9490399SQingqing Zhuo 427f9490399SQingqing Zhuo if (!table || clk_mgr_dcn315->smu_wm_set.mc_address.quad_part == 0) 428f9490399SQingqing Zhuo return; 429f9490399SQingqing Zhuo 430f9490399SQingqing Zhuo memset(table, 0, sizeof(*table)); 431f9490399SQingqing Zhuo 432f9490399SQingqing Zhuo dcn315_build_watermark_ranges(clk_mgr_base->bw_params, table); 433f9490399SQingqing Zhuo 434f9490399SQingqing Zhuo dcn315_smu_set_dram_addr_high(clk_mgr, 435f9490399SQingqing Zhuo clk_mgr_dcn315->smu_wm_set.mc_address.high_part); 436f9490399SQingqing Zhuo dcn315_smu_set_dram_addr_low(clk_mgr, 437f9490399SQingqing Zhuo clk_mgr_dcn315->smu_wm_set.mc_address.low_part); 438f9490399SQingqing Zhuo dcn315_smu_transfer_wm_table_dram_2_smu(clk_mgr); 439f9490399SQingqing Zhuo } 440f9490399SQingqing Zhuo 441f9490399SQingqing Zhuo static void dcn315_get_dpm_table_from_smu(struct clk_mgr_internal *clk_mgr, 442f9490399SQingqing Zhuo struct dcn315_smu_dpm_clks *smu_dpm_clks) 443f9490399SQingqing Zhuo { 444f9490399SQingqing Zhuo DpmClocks_315_t *table = smu_dpm_clks->dpm_clks; 445f9490399SQingqing Zhuo 446f9490399SQingqing Zhuo if (!clk_mgr->smu_ver) 447f9490399SQingqing Zhuo return; 448f9490399SQingqing Zhuo 449f9490399SQingqing Zhuo if (!table || smu_dpm_clks->mc_address.quad_part == 0) 450f9490399SQingqing Zhuo return; 451f9490399SQingqing Zhuo 452f9490399SQingqing Zhuo memset(table, 0, sizeof(*table)); 453f9490399SQingqing Zhuo 454f9490399SQingqing Zhuo dcn315_smu_set_dram_addr_high(clk_mgr, 455f9490399SQingqing Zhuo smu_dpm_clks->mc_address.high_part); 456f9490399SQingqing Zhuo dcn315_smu_set_dram_addr_low(clk_mgr, 457f9490399SQingqing Zhuo smu_dpm_clks->mc_address.low_part); 458f9490399SQingqing Zhuo dcn315_smu_transfer_dpm_table_smu_2_dram(clk_mgr); 459f9490399SQingqing Zhuo } 460f9490399SQingqing Zhuo 461f728eb3aSMagali Lemes static void dcn315_clk_mgr_helper_populate_bw_params( 462f9490399SQingqing Zhuo struct clk_mgr_internal *clk_mgr, 463f9490399SQingqing Zhuo struct integrated_info *bios_info, 464f9490399SQingqing Zhuo const DpmClocks_315_t *clock_table) 465f9490399SQingqing Zhuo { 46660f6fe66SDmytro Laktyushkin int i; 467f9490399SQingqing Zhuo struct clk_bw_params *bw_params = clk_mgr->base.bw_params; 468174fc824SDmytro Laktyushkin uint32_t max_pstate = clock_table->NumDfPstatesEnabled - 1; 46960f6fe66SDmytro Laktyushkin struct clk_limit_table_entry def_max = bw_params->clk_table.entries[bw_params->clk_table.num_entries - 1]; 470f9490399SQingqing Zhuo 47160f6fe66SDmytro Laktyushkin /* For 315 we want to base clock table on dcfclk, need at least one entry regardless of pmfw table */ 47260f6fe66SDmytro Laktyushkin for (i = 0; i < clock_table->NumDcfClkLevelsEnabled; i++) { 47360f6fe66SDmytro Laktyushkin int j; 474f9490399SQingqing Zhuo 475174fc824SDmytro Laktyushkin /* DF table is sorted with clocks decreasing */ 476174fc824SDmytro Laktyushkin for (j = clock_table->NumDfPstatesEnabled - 2; j >= 0; j--) { 477174fc824SDmytro Laktyushkin if (clock_table->DfPstateTable[j].Voltage <= clock_table->SocVoltage[i]) 478174fc824SDmytro Laktyushkin max_pstate = j; 47960f6fe66SDmytro Laktyushkin } 480174fc824SDmytro Laktyushkin /* Max DCFCLK should match up with max pstate */ 481174fc824SDmytro Laktyushkin if (i == clock_table->NumDcfClkLevelsEnabled - 1) 482174fc824SDmytro Laktyushkin max_pstate = 0; 48360f6fe66SDmytro Laktyushkin 48489c342a9SDmytro Laktyushkin /* First search defaults for the clocks we don't read using closest lower or equal default dcfclk */ 48589c342a9SDmytro Laktyushkin for (j = bw_params->clk_table.num_entries - 1; j > 0; j--) 48689c342a9SDmytro Laktyushkin if (bw_params->clk_table.entries[j].dcfclk_mhz <= clock_table->DcfClocks[i]) 48789c342a9SDmytro Laktyushkin break; 48889c342a9SDmytro Laktyushkin bw_params->clk_table.entries[i].phyclk_mhz = bw_params->clk_table.entries[j].phyclk_mhz; 48989c342a9SDmytro Laktyushkin bw_params->clk_table.entries[i].phyclk_d18_mhz = bw_params->clk_table.entries[j].phyclk_d18_mhz; 49089c342a9SDmytro Laktyushkin bw_params->clk_table.entries[i].dtbclk_mhz = bw_params->clk_table.entries[j].dtbclk_mhz; 49189c342a9SDmytro Laktyushkin 49289c342a9SDmytro Laktyushkin /* Now update clocks we do read */ 493174fc824SDmytro Laktyushkin bw_params->clk_table.entries[i].fclk_mhz = clock_table->DfPstateTable[max_pstate].FClk; 494174fc824SDmytro Laktyushkin bw_params->clk_table.entries[i].memclk_mhz = clock_table->DfPstateTable[max_pstate].MemClk; 495174fc824SDmytro Laktyushkin bw_params->clk_table.entries[i].voltage = clock_table->SocVoltage[i]; 49660f6fe66SDmytro Laktyushkin bw_params->clk_table.entries[i].dcfclk_mhz = clock_table->DcfClocks[i]; 49760f6fe66SDmytro Laktyushkin bw_params->clk_table.entries[i].socclk_mhz = clock_table->SocClocks[i]; 49889c342a9SDmytro Laktyushkin bw_params->clk_table.entries[i].dispclk_mhz = clock_table->DispClocks[i]; 49989c342a9SDmytro Laktyushkin bw_params->clk_table.entries[i].dppclk_mhz = clock_table->DppClocks[i]; 50060f6fe66SDmytro Laktyushkin bw_params->clk_table.entries[i].wck_ratio = 1; 501b34e44bcSmin tang } 502f9490399SQingqing Zhuo 503174fc824SDmytro Laktyushkin /* Make sure to include at least one entry */ 504174fc824SDmytro Laktyushkin if (i == 0) { 505174fc824SDmytro Laktyushkin bw_params->clk_table.entries[i].fclk_mhz = clock_table->DfPstateTable[0].FClk; 506174fc824SDmytro Laktyushkin bw_params->clk_table.entries[i].memclk_mhz = clock_table->DfPstateTable[0].MemClk; 507174fc824SDmytro Laktyushkin bw_params->clk_table.entries[i].voltage = clock_table->DfPstateTable[0].Voltage; 508174fc824SDmytro Laktyushkin bw_params->clk_table.entries[i].dcfclk_mhz = clock_table->DcfClocks[0]; 50960f6fe66SDmytro Laktyushkin bw_params->clk_table.entries[i].wck_ratio = 1; 51060f6fe66SDmytro Laktyushkin i++; 51160f6fe66SDmytro Laktyushkin } 512174fc824SDmytro Laktyushkin bw_params->clk_table.num_entries = i; 51360f6fe66SDmytro Laktyushkin 51460f6fe66SDmytro Laktyushkin /* Set any 0 clocks to max default setting. Not an issue for 51560f6fe66SDmytro Laktyushkin * power since we aren't doing switching in such case anyway 51660f6fe66SDmytro Laktyushkin */ 51760f6fe66SDmytro Laktyushkin for (i = 0; i < bw_params->clk_table.num_entries; i++) { 51860f6fe66SDmytro Laktyushkin if (!bw_params->clk_table.entries[i].fclk_mhz) { 51960f6fe66SDmytro Laktyushkin bw_params->clk_table.entries[i].fclk_mhz = def_max.fclk_mhz; 52060f6fe66SDmytro Laktyushkin bw_params->clk_table.entries[i].memclk_mhz = def_max.memclk_mhz; 52160f6fe66SDmytro Laktyushkin bw_params->clk_table.entries[i].voltage = def_max.voltage; 52260f6fe66SDmytro Laktyushkin } 52360f6fe66SDmytro Laktyushkin if (!bw_params->clk_table.entries[i].dcfclk_mhz) 52460f6fe66SDmytro Laktyushkin bw_params->clk_table.entries[i].dcfclk_mhz = def_max.dcfclk_mhz; 52560f6fe66SDmytro Laktyushkin if (!bw_params->clk_table.entries[i].socclk_mhz) 52660f6fe66SDmytro Laktyushkin bw_params->clk_table.entries[i].socclk_mhz = def_max.socclk_mhz; 52760f6fe66SDmytro Laktyushkin if (!bw_params->clk_table.entries[i].dispclk_mhz) 52860f6fe66SDmytro Laktyushkin bw_params->clk_table.entries[i].dispclk_mhz = def_max.dispclk_mhz; 52960f6fe66SDmytro Laktyushkin if (!bw_params->clk_table.entries[i].dppclk_mhz) 53060f6fe66SDmytro Laktyushkin bw_params->clk_table.entries[i].dppclk_mhz = def_max.dppclk_mhz; 53189c342a9SDmytro Laktyushkin if (!bw_params->clk_table.entries[i].phyclk_mhz) 53289c342a9SDmytro Laktyushkin bw_params->clk_table.entries[i].phyclk_mhz = def_max.phyclk_mhz; 53389c342a9SDmytro Laktyushkin if (!bw_params->clk_table.entries[i].phyclk_d18_mhz) 53489c342a9SDmytro Laktyushkin bw_params->clk_table.entries[i].phyclk_d18_mhz = def_max.phyclk_d18_mhz; 53589c342a9SDmytro Laktyushkin if (!bw_params->clk_table.entries[i].dtbclk_mhz) 53689c342a9SDmytro Laktyushkin bw_params->clk_table.entries[i].dtbclk_mhz = def_max.dtbclk_mhz; 53760f6fe66SDmytro Laktyushkin } 538174fc824SDmytro Laktyushkin 539174fc824SDmytro Laktyushkin /* Make sure all highest default clocks are included*/ 540174fc824SDmytro Laktyushkin ASSERT(bw_params->clk_table.entries[i-1].phyclk_mhz == def_max.phyclk_mhz); 541174fc824SDmytro Laktyushkin ASSERT(bw_params->clk_table.entries[i-1].phyclk_d18_mhz == def_max.phyclk_d18_mhz); 542174fc824SDmytro Laktyushkin ASSERT(bw_params->clk_table.entries[i-1].dtbclk_mhz == def_max.dtbclk_mhz); 543f173fbe5SQingqing Zhuo ASSERT(bw_params->clk_table.entries[i-1].dcfclk_mhz); 544f9490399SQingqing Zhuo bw_params->vram_type = bios_info->memory_type; 545f9490399SQingqing Zhuo bw_params->num_channels = bios_info->ma_channel_number; 54662f0576cSDmytro Laktyushkin bw_params->dram_channel_width_bytes = bios_info->memory_type == 0x22 ? 8 : 4; 547f9490399SQingqing Zhuo 548f9490399SQingqing Zhuo for (i = 0; i < WM_SET_COUNT; i++) { 549f9490399SQingqing Zhuo bw_params->wm_table.entries[i].wm_inst = i; 550f9490399SQingqing Zhuo 551f9490399SQingqing Zhuo if (i >= bw_params->clk_table.num_entries) { 552f9490399SQingqing Zhuo bw_params->wm_table.entries[i].valid = false; 553f9490399SQingqing Zhuo continue; 554f9490399SQingqing Zhuo } 555f9490399SQingqing Zhuo 556f9490399SQingqing Zhuo bw_params->wm_table.entries[i].wm_type = WM_TYPE_PSTATE_CHG; 557f9490399SQingqing Zhuo bw_params->wm_table.entries[i].valid = true; 558f9490399SQingqing Zhuo } 559f9490399SQingqing Zhuo } 560f9490399SQingqing Zhuo 561f9490399SQingqing Zhuo static void dcn315_enable_pme_wa(struct clk_mgr *clk_mgr_base) 562f9490399SQingqing Zhuo { 563f9490399SQingqing Zhuo struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); 564f9490399SQingqing Zhuo 565f9490399SQingqing Zhuo dcn315_smu_enable_pme_wa(clk_mgr); 566f9490399SQingqing Zhuo } 567f9490399SQingqing Zhuo 568f9490399SQingqing Zhuo static struct clk_mgr_funcs dcn315_funcs = { 569f9490399SQingqing Zhuo .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz, 5700ec74408SLeung, Martin .get_dtb_ref_clk_frequency = dcn31_get_dtb_ref_freq_khz, 571f9490399SQingqing Zhuo .update_clocks = dcn315_update_clocks, 572f9490399SQingqing Zhuo .init_clocks = dcn31_init_clocks, 573f9490399SQingqing Zhuo .enable_pme_wa = dcn315_enable_pme_wa, 574f9490399SQingqing Zhuo .are_clock_states_equal = dcn31_are_clock_states_equal, 575f9490399SQingqing Zhuo .notify_wm_ranges = dcn315_notify_wm_ranges 576f9490399SQingqing Zhuo }; 577f9490399SQingqing Zhuo extern struct clk_mgr_funcs dcn3_fpga_funcs; 578f9490399SQingqing Zhuo 579f9490399SQingqing Zhuo void dcn315_clk_mgr_construct( 580f9490399SQingqing Zhuo struct dc_context *ctx, 581f9490399SQingqing Zhuo struct clk_mgr_dcn315 *clk_mgr, 582f9490399SQingqing Zhuo struct pp_smu_funcs *pp_smu, 583f9490399SQingqing Zhuo struct dccg *dccg) 584f9490399SQingqing Zhuo { 585f9490399SQingqing Zhuo struct dcn315_smu_dpm_clks smu_dpm_clks = { 0 }; 586f9490399SQingqing Zhuo 587f9490399SQingqing Zhuo clk_mgr->base.base.ctx = ctx; 588f9490399SQingqing Zhuo clk_mgr->base.base.funcs = &dcn315_funcs; 589f9490399SQingqing Zhuo 590f9490399SQingqing Zhuo clk_mgr->base.pp_smu = pp_smu; 591f9490399SQingqing Zhuo 592f9490399SQingqing Zhuo clk_mgr->base.dccg = dccg; 593f9490399SQingqing Zhuo clk_mgr->base.dfs_bypass_disp_clk = 0; 594f9490399SQingqing Zhuo 595f9490399SQingqing Zhuo clk_mgr->base.dprefclk_ss_percentage = 0; 596f9490399SQingqing Zhuo clk_mgr->base.dprefclk_ss_divider = 1000; 597f9490399SQingqing Zhuo clk_mgr->base.ss_on_dprefclk = false; 598f9490399SQingqing Zhuo clk_mgr->base.dfs_ref_freq_khz = 48000; 599f9490399SQingqing Zhuo 600f9490399SQingqing Zhuo clk_mgr->smu_wm_set.wm_set = (struct dcn315_watermarks *)dm_helpers_allocate_gpu_mem( 601f9490399SQingqing Zhuo clk_mgr->base.base.ctx, 602f9490399SQingqing Zhuo DC_MEM_ALLOC_TYPE_FRAME_BUFFER, 603f9490399SQingqing Zhuo sizeof(struct dcn315_watermarks), 604f9490399SQingqing Zhuo &clk_mgr->smu_wm_set.mc_address.quad_part); 605f9490399SQingqing Zhuo 606f9490399SQingqing Zhuo if (!clk_mgr->smu_wm_set.wm_set) { 607f9490399SQingqing Zhuo clk_mgr->smu_wm_set.wm_set = &dummy_wms; 608f9490399SQingqing Zhuo clk_mgr->smu_wm_set.mc_address.quad_part = 0; 609f9490399SQingqing Zhuo } 610f9490399SQingqing Zhuo ASSERT(clk_mgr->smu_wm_set.wm_set); 611f9490399SQingqing Zhuo 612f9490399SQingqing Zhuo smu_dpm_clks.dpm_clks = (DpmClocks_315_t *)dm_helpers_allocate_gpu_mem( 613f9490399SQingqing Zhuo clk_mgr->base.base.ctx, 614f9490399SQingqing Zhuo DC_MEM_ALLOC_TYPE_FRAME_BUFFER, 615f9490399SQingqing Zhuo sizeof(DpmClocks_315_t), 616f9490399SQingqing Zhuo &smu_dpm_clks.mc_address.quad_part); 617f9490399SQingqing Zhuo 618f9490399SQingqing Zhuo if (smu_dpm_clks.dpm_clks == NULL) { 619f9490399SQingqing Zhuo smu_dpm_clks.dpm_clks = &dummy_clocks; 620f9490399SQingqing Zhuo smu_dpm_clks.mc_address.quad_part = 0; 621f9490399SQingqing Zhuo } 622f9490399SQingqing Zhuo 623f9490399SQingqing Zhuo ASSERT(smu_dpm_clks.dpm_clks); 624f9490399SQingqing Zhuo 625f9490399SQingqing Zhuo if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) { 626f9490399SQingqing Zhuo clk_mgr->base.base.funcs = &dcn3_fpga_funcs; 627f9490399SQingqing Zhuo } else { 628f9490399SQingqing Zhuo struct clk_log_info log_info = {0}; 629f9490399SQingqing Zhuo 630f9490399SQingqing Zhuo clk_mgr->base.smu_ver = dcn315_smu_get_smu_version(&clk_mgr->base); 631f9490399SQingqing Zhuo 632f9490399SQingqing Zhuo if (clk_mgr->base.smu_ver > 0) 633f9490399SQingqing Zhuo clk_mgr->base.smu_present = true; 634f9490399SQingqing Zhuo 635f9490399SQingqing Zhuo if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) { 636f9490399SQingqing Zhuo dcn315_bw_params.wm_table = lpddr5_wm_table; 637f9490399SQingqing Zhuo } else { 638f9490399SQingqing Zhuo dcn315_bw_params.wm_table = ddr5_wm_table; 639f9490399SQingqing Zhuo } 640f9490399SQingqing Zhuo /* Saved clocks configured at boot for debug purposes */ 641203dc777SJiapeng Chong dcn315_dump_clk_registers(&clk_mgr->base.base.boot_snapshot, 642203dc777SJiapeng Chong &clk_mgr->base.base, &log_info); 643f9490399SQingqing Zhuo 644f9490399SQingqing Zhuo } 645f9490399SQingqing Zhuo 646f9490399SQingqing Zhuo clk_mgr->base.base.dprefclk_khz = 600000; 6473b8b44a4SCharlene Liu clk_mgr->base.base.dprefclk_khz = dcn315_smu_get_dpref_clk(&clk_mgr->base); 6480ec74408SLeung, Martin clk_mgr->base.base.clks.ref_dtbclk_khz = clk_mgr->base.base.dprefclk_khz; 649f9490399SQingqing Zhuo dce_clock_read_ss_info(&clk_mgr->base); 6500ec74408SLeung, Martin clk_mgr->base.base.clks.ref_dtbclk_khz = dce_adjust_dp_ref_freq_for_ss(&clk_mgr->base, clk_mgr->base.base.dprefclk_khz); 651f9490399SQingqing Zhuo 652f9490399SQingqing Zhuo clk_mgr->base.base.bw_params = &dcn315_bw_params; 653f9490399SQingqing Zhuo 654f9490399SQingqing Zhuo if (clk_mgr->base.base.ctx->dc->debug.pstate_enabled) { 655c8b1d0feSLeo Chen int i; 656c8b1d0feSLeo Chen 657f9490399SQingqing Zhuo dcn315_get_dpm_table_from_smu(&clk_mgr->base, &smu_dpm_clks); 658c8b1d0feSLeo Chen DC_LOG_SMU("NumDcfClkLevelsEnabled: %d\n" 659c8b1d0feSLeo Chen "NumDispClkLevelsEnabled: %d\n" 660c8b1d0feSLeo Chen "NumSocClkLevelsEnabled: %d\n" 661c8b1d0feSLeo Chen "VcnClkLevelsEnabled: %d\n" 662c8b1d0feSLeo Chen "NumDfPst atesEnabled: %d\n" 663c8b1d0feSLeo Chen "MinGfxClk: %d\n" 664c8b1d0feSLeo Chen "MaxGfxClk: %d\n", 665c8b1d0feSLeo Chen smu_dpm_clks.dpm_clks->NumDcfClkLevelsEnabled, 666c8b1d0feSLeo Chen smu_dpm_clks.dpm_clks->NumDispClkLevelsEnabled, 667c8b1d0feSLeo Chen smu_dpm_clks.dpm_clks->NumSocClkLevelsEnabled, 668c8b1d0feSLeo Chen smu_dpm_clks.dpm_clks->VcnClkLevelsEnabled, 669c8b1d0feSLeo Chen smu_dpm_clks.dpm_clks->NumDfPstatesEnabled, 670c8b1d0feSLeo Chen smu_dpm_clks.dpm_clks->MinGfxClk, 671c8b1d0feSLeo Chen smu_dpm_clks.dpm_clks->MaxGfxClk); 672c8b1d0feSLeo Chen for (i = 0; i < smu_dpm_clks.dpm_clks->NumDcfClkLevelsEnabled; i++) { 673c8b1d0feSLeo Chen DC_LOG_SMU("smu_dpm_clks.dpm_clks->DcfClocks[%d] = %d\n", 674c8b1d0feSLeo Chen i, 675c8b1d0feSLeo Chen smu_dpm_clks.dpm_clks->DcfClocks[i]); 676c8b1d0feSLeo Chen } 677c8b1d0feSLeo Chen for (i = 0; i < smu_dpm_clks.dpm_clks->NumDispClkLevelsEnabled; i++) { 678c8b1d0feSLeo Chen DC_LOG_SMU("smu_dpm_clks.dpm_clks->DispClocks[%d] = %d\n", 679c8b1d0feSLeo Chen i, smu_dpm_clks.dpm_clks->DispClocks[i]); 680c8b1d0feSLeo Chen } 681c8b1d0feSLeo Chen for (i = 0; i < smu_dpm_clks.dpm_clks->NumSocClkLevelsEnabled; i++) { 682c8b1d0feSLeo Chen DC_LOG_SMU("smu_dpm_clks.dpm_clks->SocClocks[%d] = %d\n", 683c8b1d0feSLeo Chen i, smu_dpm_clks.dpm_clks->SocClocks[i]); 684c8b1d0feSLeo Chen } 685c8b1d0feSLeo Chen for (i = 0; i < NUM_SOC_VOLTAGE_LEVELS; i++) 686c8b1d0feSLeo Chen DC_LOG_SMU("smu_dpm_clks.dpm_clks->SocVoltage[%d] = %d\n", 687c8b1d0feSLeo Chen i, smu_dpm_clks.dpm_clks->SocVoltage[i]); 688c8b1d0feSLeo Chen 689c8b1d0feSLeo Chen for (i = 0; i < NUM_DF_PSTATE_LEVELS; i++) { 690c8b1d0feSLeo Chen DC_LOG_SMU("smu_dpm_clks.dpm_clks.DfPstateTable[%d].FClk = %d\n" 691c8b1d0feSLeo Chen "smu_dpm_clks.dpm_clks->DfPstateTable[%d].MemClk= %d\n" 692c8b1d0feSLeo Chen "smu_dpm_clks.dpm_clks->DfPstateTable[%d].Voltage = %d\n", 693c8b1d0feSLeo Chen i, smu_dpm_clks.dpm_clks->DfPstateTable[i].FClk, 694c8b1d0feSLeo Chen i, smu_dpm_clks.dpm_clks->DfPstateTable[i].MemClk, 695c8b1d0feSLeo Chen i, smu_dpm_clks.dpm_clks->DfPstateTable[i].Voltage); 696c8b1d0feSLeo Chen } 697f9490399SQingqing Zhuo 698f9490399SQingqing Zhuo if (ctx->dc_bios && ctx->dc_bios->integrated_info) { 699f9490399SQingqing Zhuo dcn315_clk_mgr_helper_populate_bw_params( 700f9490399SQingqing Zhuo &clk_mgr->base, 701f9490399SQingqing Zhuo ctx->dc_bios->integrated_info, 702f9490399SQingqing Zhuo smu_dpm_clks.dpm_clks); 703f9490399SQingqing Zhuo } 704f9490399SQingqing Zhuo } 705f9490399SQingqing Zhuo 706f9490399SQingqing Zhuo if (smu_dpm_clks.dpm_clks && smu_dpm_clks.mc_address.quad_part != 0) 707f9490399SQingqing Zhuo dm_helpers_free_gpu_mem(clk_mgr->base.base.ctx, DC_MEM_ALLOC_TYPE_FRAME_BUFFER, 708f9490399SQingqing Zhuo smu_dpm_clks.dpm_clks); 709f9490399SQingqing Zhuo } 710f9490399SQingqing Zhuo 711f9490399SQingqing Zhuo void dcn315_clk_mgr_destroy(struct clk_mgr_internal *clk_mgr_int) 712f9490399SQingqing Zhuo { 713f9490399SQingqing Zhuo struct clk_mgr_dcn315 *clk_mgr = TO_CLK_MGR_DCN315(clk_mgr_int); 714f9490399SQingqing Zhuo 715f9490399SQingqing Zhuo if (clk_mgr->smu_wm_set.wm_set && clk_mgr->smu_wm_set.mc_address.quad_part != 0) 716f9490399SQingqing Zhuo dm_helpers_free_gpu_mem(clk_mgr_int->base.ctx, DC_MEM_ALLOC_TYPE_FRAME_BUFFER, 717f9490399SQingqing Zhuo clk_mgr->smu_wm_set.wm_set); 718f9490399SQingqing Zhuo } 719