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 496ca7415fSWenjing 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 9034a24462STom Rix static bool should_disable_otg(struct pipe_ctx *pipe) 913119668cSJingwen Zhu { 923119668cSJingwen Zhu bool ret = true; 933119668cSJingwen Zhu 943119668cSJingwen Zhu if (pipe->stream->link->link_enc && pipe->stream->link->link_enc->funcs->is_dig_enabled && 953119668cSJingwen Zhu pipe->stream->link->link_enc->funcs->is_dig_enabled(pipe->stream->link->link_enc)) 963119668cSJingwen Zhu ret = false; 973119668cSJingwen Zhu return ret; 983119668cSJingwen Zhu } 993119668cSJingwen Zhu 100abffd871SMeenakshikumar Somasundaram static void dcn315_disable_otg_wa(struct clk_mgr *clk_mgr_base, struct dc_state *context, bool disable) 101f9490399SQingqing Zhuo { 102f9490399SQingqing Zhuo struct dc *dc = clk_mgr_base->ctx->dc; 103f9490399SQingqing Zhuo int i; 104f9490399SQingqing Zhuo 105f9490399SQingqing Zhuo for (i = 0; i < dc->res_pool->pipe_count; ++i) { 106165ab7b4SNicholas Kazlauskas struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i]; 107f9490399SQingqing Zhuo 108f9490399SQingqing Zhuo if (pipe->top_pipe || pipe->prev_odm_pipe) 109f9490399SQingqing Zhuo continue; 11066a19720SNicholas Kazlauskas if (pipe->stream && (pipe->stream->dpms_off || pipe->plane_state == NULL || 11166a19720SNicholas Kazlauskas dc_is_virtual_signal(pipe->stream->signal))) { 1123119668cSJingwen Zhu 1133119668cSJingwen Zhu /* This w/a should not trigger when we have a dig active */ 1143119668cSJingwen Zhu if (should_disable_otg(pipe)) { 115abffd871SMeenakshikumar Somasundaram if (disable) { 116f9490399SQingqing Zhuo pipe->stream_res.tg->funcs->immediate_disable_crtc(pipe->stream_res.tg); 117abffd871SMeenakshikumar Somasundaram reset_sync_context_for_pipe(dc, context, i); 118abffd871SMeenakshikumar Somasundaram } else 119f9490399SQingqing Zhuo pipe->stream_res.tg->funcs->enable_crtc(pipe->stream_res.tg); 120f9490399SQingqing Zhuo } 121f9490399SQingqing Zhuo } 122f9490399SQingqing Zhuo } 1233119668cSJingwen Zhu } 124f9490399SQingqing Zhuo 125f9490399SQingqing Zhuo static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base, 126f9490399SQingqing Zhuo struct dc_state *context, 127f9490399SQingqing Zhuo bool safe_to_lower) 128f9490399SQingqing Zhuo { 129f9490399SQingqing Zhuo union dmub_rb_cmd cmd; 130f9490399SQingqing Zhuo struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); 131f9490399SQingqing Zhuo struct dc_clocks *new_clocks = &context->bw_ctx.bw.dcn.clk; 132f9490399SQingqing Zhuo struct dc *dc = clk_mgr_base->ctx->dc; 133f9490399SQingqing Zhuo int display_count; 134f9490399SQingqing Zhuo bool update_dppclk = false; 135f9490399SQingqing Zhuo bool update_dispclk = false; 136f9490399SQingqing Zhuo bool dpp_clock_lowered = false; 137f9490399SQingqing Zhuo 138f9490399SQingqing Zhuo if (dc->work_arounds.skip_clock_update) 139f9490399SQingqing Zhuo return; 140f9490399SQingqing Zhuo 141f9490399SQingqing Zhuo clk_mgr_base->clks.zstate_support = new_clocks->zstate_support; 142f9490399SQingqing Zhuo /* 143f9490399SQingqing Zhuo * if it is safe to lower, but we are already in the lower state, we don't have to do anything 144f9490399SQingqing Zhuo * also if safe to lower is false, we just go in the higher state 145f9490399SQingqing Zhuo */ 146f9490399SQingqing Zhuo clk_mgr_base->clks.zstate_support = new_clocks->zstate_support; 147f9490399SQingqing Zhuo if (safe_to_lower) { 148f9490399SQingqing Zhuo /* check that we're not already in lower */ 149f9490399SQingqing Zhuo if (clk_mgr_base->clks.pwr_state != DCN_PWR_STATE_LOW_POWER) { 150f9490399SQingqing Zhuo display_count = dcn315_get_active_display_cnt_wa(dc, context); 151f9490399SQingqing Zhuo /* if we can go lower, go lower */ 152f9490399SQingqing Zhuo if (display_count == 0) { 153f9490399SQingqing Zhuo union display_idle_optimization_u idle_info = { 0 }; 154f9490399SQingqing Zhuo idle_info.idle_info.df_request_disabled = 1; 155f9490399SQingqing Zhuo idle_info.idle_info.phy_ref_clk_off = 1; 156e7145aaeSCharlene Liu idle_info.idle_info.s0i2_rdy = 1; 157f9490399SQingqing Zhuo dcn315_smu_set_display_idle_optimization(clk_mgr, idle_info.data); 158f9490399SQingqing Zhuo /* update power state */ 159f9490399SQingqing Zhuo clk_mgr_base->clks.pwr_state = DCN_PWR_STATE_LOW_POWER; 160f9490399SQingqing Zhuo } 161f9490399SQingqing Zhuo } 162f9490399SQingqing Zhuo } else { 163f9490399SQingqing Zhuo /* check that we're not already in D0 */ 164f9490399SQingqing Zhuo if (clk_mgr_base->clks.pwr_state != DCN_PWR_STATE_MISSION_MODE) { 165f9490399SQingqing Zhuo union display_idle_optimization_u idle_info = { 0 }; 166f9490399SQingqing Zhuo dcn315_smu_set_display_idle_optimization(clk_mgr, idle_info.data); 167f9490399SQingqing Zhuo /* update power state */ 168f9490399SQingqing Zhuo clk_mgr_base->clks.pwr_state = DCN_PWR_STATE_MISSION_MODE; 169f9490399SQingqing Zhuo } 170f9490399SQingqing Zhuo } 171f9490399SQingqing Zhuo 17263423cf1SDmytro Laktyushkin /* Lock pstate by requesting unsupported dcfclk if change is unsupported */ 17363423cf1SDmytro Laktyushkin if (!new_clocks->p_state_change_support) 17463423cf1SDmytro Laktyushkin new_clocks->dcfclk_khz = UNSUPPORTED_DCFCLK; 175f9490399SQingqing Zhuo if (should_set_clock(safe_to_lower, new_clocks->dcfclk_khz, clk_mgr_base->clks.dcfclk_khz)) { 176f9490399SQingqing Zhuo clk_mgr_base->clks.dcfclk_khz = new_clocks->dcfclk_khz; 177f9490399SQingqing Zhuo dcn315_smu_set_hard_min_dcfclk(clk_mgr, clk_mgr_base->clks.dcfclk_khz); 178f9490399SQingqing Zhuo } 179f9490399SQingqing Zhuo 180f9490399SQingqing Zhuo if (should_set_clock(safe_to_lower, 181f9490399SQingqing Zhuo new_clocks->dcfclk_deep_sleep_khz, clk_mgr_base->clks.dcfclk_deep_sleep_khz)) { 182f9490399SQingqing Zhuo clk_mgr_base->clks.dcfclk_deep_sleep_khz = new_clocks->dcfclk_deep_sleep_khz; 183f9490399SQingqing Zhuo dcn315_smu_set_min_deep_sleep_dcfclk(clk_mgr, clk_mgr_base->clks.dcfclk_deep_sleep_khz); 184f9490399SQingqing Zhuo } 185f9490399SQingqing Zhuo 186f9490399SQingqing Zhuo // workaround: Limit dppclk to 100Mhz to avoid lower eDP panel switch to plus 4K monitor underflow. 18763423cf1SDmytro Laktyushkin if (new_clocks->dppclk_khz < MIN_DPP_DISP_CLK) 18863423cf1SDmytro Laktyushkin new_clocks->dppclk_khz = MIN_DPP_DISP_CLK; 18963423cf1SDmytro Laktyushkin if (new_clocks->dispclk_khz < MIN_DPP_DISP_CLK) 19063423cf1SDmytro Laktyushkin new_clocks->dispclk_khz = MIN_DPP_DISP_CLK; 191f9490399SQingqing Zhuo 192f9490399SQingqing Zhuo if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr->base.clks.dppclk_khz)) { 193f9490399SQingqing Zhuo if (clk_mgr->base.clks.dppclk_khz > new_clocks->dppclk_khz) 194f9490399SQingqing Zhuo dpp_clock_lowered = true; 195f9490399SQingqing Zhuo clk_mgr_base->clks.dppclk_khz = new_clocks->dppclk_khz; 196f9490399SQingqing Zhuo update_dppclk = true; 197f9490399SQingqing Zhuo } 198f9490399SQingqing Zhuo 199f9490399SQingqing Zhuo if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) { 2008a077d9cSDmytro Laktyushkin /* No need to apply the w/a if we haven't taken over from bios yet */ 2018a077d9cSDmytro Laktyushkin if (clk_mgr_base->clks.dispclk_khz) 202abffd871SMeenakshikumar Somasundaram dcn315_disable_otg_wa(clk_mgr_base, context, true); 203f9490399SQingqing Zhuo 204f9490399SQingqing Zhuo clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz; 205f9490399SQingqing Zhuo dcn315_smu_set_dispclk(clk_mgr, clk_mgr_base->clks.dispclk_khz); 2068a077d9cSDmytro Laktyushkin if (clk_mgr_base->clks.dispclk_khz) 207abffd871SMeenakshikumar Somasundaram dcn315_disable_otg_wa(clk_mgr_base, context, false); 208f9490399SQingqing Zhuo 209f9490399SQingqing Zhuo update_dispclk = true; 210f9490399SQingqing Zhuo } 211f9490399SQingqing Zhuo 212f9490399SQingqing Zhuo if (dpp_clock_lowered) { 213f9490399SQingqing Zhuo // increase per DPP DTO before lowering global dppclk 214f9490399SQingqing Zhuo dcn20_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower); 215f9490399SQingqing Zhuo dcn315_smu_set_dppclk(clk_mgr, clk_mgr_base->clks.dppclk_khz); 216f9490399SQingqing Zhuo } else { 217f9490399SQingqing Zhuo // increase global DPPCLK before lowering per DPP DTO 218f9490399SQingqing Zhuo if (update_dppclk || update_dispclk) 219f9490399SQingqing Zhuo dcn315_smu_set_dppclk(clk_mgr, clk_mgr_base->clks.dppclk_khz); 220f9490399SQingqing Zhuo // always update dtos unless clock is lowered and not safe to lower 221f9490399SQingqing Zhuo if (new_clocks->dppclk_khz >= dc->current_state->bw_ctx.bw.dcn.clk.dppclk_khz) 222f9490399SQingqing Zhuo dcn20_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower); 223f9490399SQingqing Zhuo } 224f9490399SQingqing Zhuo 225f9490399SQingqing Zhuo // notify DMCUB of latest clocks 226f9490399SQingqing Zhuo memset(&cmd, 0, sizeof(cmd)); 227f9490399SQingqing Zhuo cmd.notify_clocks.header.type = DMUB_CMD__CLK_MGR; 228f9490399SQingqing Zhuo cmd.notify_clocks.header.sub_type = DMUB_CMD__CLK_MGR_NOTIFY_CLOCKS; 229f9490399SQingqing Zhuo cmd.notify_clocks.clocks.dcfclk_khz = clk_mgr_base->clks.dcfclk_khz; 230f9490399SQingqing Zhuo cmd.notify_clocks.clocks.dcfclk_deep_sleep_khz = 231f9490399SQingqing Zhuo clk_mgr_base->clks.dcfclk_deep_sleep_khz; 232f9490399SQingqing Zhuo cmd.notify_clocks.clocks.dispclk_khz = clk_mgr_base->clks.dispclk_khz; 233f9490399SQingqing Zhuo cmd.notify_clocks.clocks.dppclk_khz = clk_mgr_base->clks.dppclk_khz; 234f9490399SQingqing Zhuo 235e97cc04fSJosip Pavic dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); 236f9490399SQingqing Zhuo } 237f9490399SQingqing Zhuo 238f9490399SQingqing Zhuo static void dcn315_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass, 239f9490399SQingqing Zhuo struct clk_mgr *clk_mgr_base, struct clk_log_info *log_info) 240f9490399SQingqing Zhuo { 241f9490399SQingqing Zhuo return; 242f9490399SQingqing Zhuo } 243f9490399SQingqing Zhuo 244f9490399SQingqing Zhuo static struct clk_bw_params dcn315_bw_params = { 245f9490399SQingqing Zhuo .vram_type = Ddr4MemType, 24689c342a9SDmytro Laktyushkin .num_channels = 2, 247f9490399SQingqing Zhuo .clk_table = { 24889c342a9SDmytro Laktyushkin .entries = { 24989c342a9SDmytro Laktyushkin { 25089c342a9SDmytro Laktyushkin .voltage = 0, 25189c342a9SDmytro Laktyushkin .dispclk_mhz = 640, 25289c342a9SDmytro Laktyushkin .dppclk_mhz = 640, 25389c342a9SDmytro Laktyushkin .phyclk_mhz = 810, 25489c342a9SDmytro Laktyushkin .phyclk_d18_mhz = 667, 25589c342a9SDmytro Laktyushkin .dtbclk_mhz = 600, 25689c342a9SDmytro Laktyushkin }, 25789c342a9SDmytro Laktyushkin { 25889c342a9SDmytro Laktyushkin .voltage = 1, 25989c342a9SDmytro Laktyushkin .dispclk_mhz = 739, 26089c342a9SDmytro Laktyushkin .dppclk_mhz = 739, 26189c342a9SDmytro Laktyushkin .phyclk_mhz = 810, 26289c342a9SDmytro Laktyushkin .phyclk_d18_mhz = 667, 26389c342a9SDmytro Laktyushkin .dtbclk_mhz = 600, 26489c342a9SDmytro Laktyushkin }, 26589c342a9SDmytro Laktyushkin { 26689c342a9SDmytro Laktyushkin .voltage = 2, 26789c342a9SDmytro Laktyushkin .dispclk_mhz = 960, 26889c342a9SDmytro Laktyushkin .dppclk_mhz = 960, 26989c342a9SDmytro Laktyushkin .phyclk_mhz = 810, 27089c342a9SDmytro Laktyushkin .phyclk_d18_mhz = 667, 27189c342a9SDmytro Laktyushkin .dtbclk_mhz = 600, 27289c342a9SDmytro Laktyushkin }, 27389c342a9SDmytro Laktyushkin { 27489c342a9SDmytro Laktyushkin .voltage = 3, 27589c342a9SDmytro Laktyushkin .dispclk_mhz = 1200, 27689c342a9SDmytro Laktyushkin .dppclk_mhz = 1200, 27789c342a9SDmytro Laktyushkin .phyclk_mhz = 810, 27889c342a9SDmytro Laktyushkin .phyclk_d18_mhz = 667, 27989c342a9SDmytro Laktyushkin .dtbclk_mhz = 600, 28089c342a9SDmytro Laktyushkin }, 28189c342a9SDmytro Laktyushkin { 28289c342a9SDmytro Laktyushkin .voltage = 4, 28389c342a9SDmytro Laktyushkin .dispclk_mhz = 1372, 28489c342a9SDmytro Laktyushkin .dppclk_mhz = 1372, 28589c342a9SDmytro Laktyushkin .phyclk_mhz = 810, 28689c342a9SDmytro Laktyushkin .phyclk_d18_mhz = 667, 28789c342a9SDmytro Laktyushkin .dtbclk_mhz = 600, 28889c342a9SDmytro Laktyushkin }, 28989c342a9SDmytro Laktyushkin }, 290f9490399SQingqing Zhuo .num_entries = 5, 291f9490399SQingqing Zhuo }, 292f9490399SQingqing Zhuo 293f9490399SQingqing Zhuo }; 294f9490399SQingqing Zhuo 295f9490399SQingqing Zhuo static struct wm_table ddr5_wm_table = { 296f9490399SQingqing Zhuo .entries = { 297f9490399SQingqing Zhuo { 298f9490399SQingqing Zhuo .wm_inst = WM_A, 299f9490399SQingqing Zhuo .wm_type = WM_TYPE_PSTATE_CHG, 30063423cf1SDmytro Laktyushkin .pstate_latency_us = 129.0, 301f9490399SQingqing Zhuo .sr_exit_time_us = 11.5, 302f9490399SQingqing Zhuo .sr_enter_plus_exit_time_us = 14.5, 303f9490399SQingqing Zhuo .valid = true, 304f9490399SQingqing Zhuo }, 305f9490399SQingqing Zhuo { 306f9490399SQingqing Zhuo .wm_inst = WM_B, 307f9490399SQingqing Zhuo .wm_type = WM_TYPE_PSTATE_CHG, 30863423cf1SDmytro Laktyushkin .pstate_latency_us = 129.0, 309f9490399SQingqing Zhuo .sr_exit_time_us = 11.5, 310f9490399SQingqing Zhuo .sr_enter_plus_exit_time_us = 14.5, 311f9490399SQingqing Zhuo .valid = true, 312f9490399SQingqing Zhuo }, 313f9490399SQingqing Zhuo { 314f9490399SQingqing Zhuo .wm_inst = WM_C, 315f9490399SQingqing Zhuo .wm_type = WM_TYPE_PSTATE_CHG, 31663423cf1SDmytro Laktyushkin .pstate_latency_us = 129.0, 317f9490399SQingqing Zhuo .sr_exit_time_us = 11.5, 318f9490399SQingqing Zhuo .sr_enter_plus_exit_time_us = 14.5, 319f9490399SQingqing Zhuo .valid = true, 320f9490399SQingqing Zhuo }, 321f9490399SQingqing Zhuo { 322f9490399SQingqing Zhuo .wm_inst = WM_D, 323f9490399SQingqing Zhuo .wm_type = WM_TYPE_PSTATE_CHG, 32463423cf1SDmytro Laktyushkin .pstate_latency_us = 129.0, 325f9490399SQingqing Zhuo .sr_exit_time_us = 11.5, 326f9490399SQingqing Zhuo .sr_enter_plus_exit_time_us = 14.5, 327f9490399SQingqing Zhuo .valid = true, 328f9490399SQingqing Zhuo }, 329f9490399SQingqing Zhuo } 330f9490399SQingqing Zhuo }; 331f9490399SQingqing Zhuo 332f9490399SQingqing Zhuo static struct wm_table lpddr5_wm_table = { 333f9490399SQingqing Zhuo .entries = { 334f9490399SQingqing Zhuo { 335f9490399SQingqing Zhuo .wm_inst = WM_A, 336f9490399SQingqing Zhuo .wm_type = WM_TYPE_PSTATE_CHG, 337f9490399SQingqing Zhuo .pstate_latency_us = 11.65333, 338f9490399SQingqing Zhuo .sr_exit_time_us = 11.5, 339f9490399SQingqing Zhuo .sr_enter_plus_exit_time_us = 14.5, 340f9490399SQingqing Zhuo .valid = true, 341f9490399SQingqing Zhuo }, 342f9490399SQingqing Zhuo { 343f9490399SQingqing Zhuo .wm_inst = WM_B, 344f9490399SQingqing Zhuo .wm_type = WM_TYPE_PSTATE_CHG, 345f9490399SQingqing Zhuo .pstate_latency_us = 11.65333, 346f9490399SQingqing Zhuo .sr_exit_time_us = 11.5, 347f9490399SQingqing Zhuo .sr_enter_plus_exit_time_us = 14.5, 348f9490399SQingqing Zhuo .valid = true, 349f9490399SQingqing Zhuo }, 350f9490399SQingqing Zhuo { 351f9490399SQingqing Zhuo .wm_inst = WM_C, 352f9490399SQingqing Zhuo .wm_type = WM_TYPE_PSTATE_CHG, 353f9490399SQingqing Zhuo .pstate_latency_us = 11.65333, 354f9490399SQingqing Zhuo .sr_exit_time_us = 11.5, 355f9490399SQingqing Zhuo .sr_enter_plus_exit_time_us = 14.5, 356f9490399SQingqing Zhuo .valid = true, 357f9490399SQingqing Zhuo }, 358f9490399SQingqing Zhuo { 359f9490399SQingqing Zhuo .wm_inst = WM_D, 360f9490399SQingqing Zhuo .wm_type = WM_TYPE_PSTATE_CHG, 361f9490399SQingqing Zhuo .pstate_latency_us = 11.65333, 362f9490399SQingqing Zhuo .sr_exit_time_us = 11.5, 363f9490399SQingqing Zhuo .sr_enter_plus_exit_time_us = 14.5, 364f9490399SQingqing Zhuo .valid = true, 365f9490399SQingqing Zhuo }, 366f9490399SQingqing Zhuo } 367f9490399SQingqing Zhuo }; 368f9490399SQingqing Zhuo 36989c342a9SDmytro Laktyushkin /* Temporary Place holder until we can get them from fuse */ 37089c342a9SDmytro Laktyushkin static DpmClocks_315_t dummy_clocks = { 0 }; 371f9490399SQingqing Zhuo static struct dcn315_watermarks dummy_wms = { 0 }; 372f9490399SQingqing Zhuo 373f9490399SQingqing Zhuo static void dcn315_build_watermark_ranges(struct clk_bw_params *bw_params, struct dcn315_watermarks *table) 374f9490399SQingqing Zhuo { 375f9490399SQingqing Zhuo int i, num_valid_sets; 376f9490399SQingqing Zhuo 377f9490399SQingqing Zhuo num_valid_sets = 0; 378f9490399SQingqing Zhuo 379f9490399SQingqing Zhuo for (i = 0; i < WM_SET_COUNT; i++) { 380f9490399SQingqing Zhuo /* skip empty entries, the smu array has no holes*/ 381f9490399SQingqing Zhuo if (!bw_params->wm_table.entries[i].valid) 382f9490399SQingqing Zhuo continue; 383f9490399SQingqing Zhuo 384f9490399SQingqing Zhuo table->WatermarkRow[WM_DCFCLK][num_valid_sets].WmSetting = bw_params->wm_table.entries[i].wm_inst; 385f9490399SQingqing Zhuo table->WatermarkRow[WM_DCFCLK][num_valid_sets].WmType = bw_params->wm_table.entries[i].wm_type; 386f9490399SQingqing Zhuo /* We will not select WM based on fclk, so leave it as unconstrained */ 387f9490399SQingqing Zhuo table->WatermarkRow[WM_DCFCLK][num_valid_sets].MinClock = 0; 388f9490399SQingqing Zhuo table->WatermarkRow[WM_DCFCLK][num_valid_sets].MaxClock = 0xFFFF; 389f9490399SQingqing Zhuo 390f9490399SQingqing Zhuo if (table->WatermarkRow[WM_DCFCLK][num_valid_sets].WmType == WM_TYPE_PSTATE_CHG) { 391f9490399SQingqing Zhuo if (i == 0) 392f9490399SQingqing Zhuo table->WatermarkRow[WM_DCFCLK][num_valid_sets].MinMclk = 0; 393f9490399SQingqing Zhuo else { 394f9490399SQingqing Zhuo /* add 1 to make it non-overlapping with next lvl */ 395f9490399SQingqing Zhuo table->WatermarkRow[WM_DCFCLK][num_valid_sets].MinMclk = 396f9490399SQingqing Zhuo bw_params->clk_table.entries[i - 1].dcfclk_mhz + 1; 397f9490399SQingqing Zhuo } 398f9490399SQingqing Zhuo table->WatermarkRow[WM_DCFCLK][num_valid_sets].MaxMclk = 399f9490399SQingqing Zhuo bw_params->clk_table.entries[i].dcfclk_mhz; 400f9490399SQingqing Zhuo 401f9490399SQingqing Zhuo } else { 402f9490399SQingqing Zhuo /* unconstrained for memory retraining */ 403f9490399SQingqing Zhuo table->WatermarkRow[WM_DCFCLK][num_valid_sets].MinClock = 0; 404f9490399SQingqing Zhuo table->WatermarkRow[WM_DCFCLK][num_valid_sets].MaxClock = 0xFFFF; 405f9490399SQingqing Zhuo 406f9490399SQingqing Zhuo /* Modify previous watermark range to cover up to max */ 407f9490399SQingqing Zhuo table->WatermarkRow[WM_DCFCLK][num_valid_sets - 1].MaxClock = 0xFFFF; 408f9490399SQingqing Zhuo } 409f9490399SQingqing Zhuo num_valid_sets++; 410f9490399SQingqing Zhuo } 411f9490399SQingqing Zhuo 412f9490399SQingqing Zhuo ASSERT(num_valid_sets != 0); /* Must have at least one set of valid watermarks */ 413f9490399SQingqing Zhuo 414f9490399SQingqing Zhuo /* modify the min and max to make sure we cover the whole range*/ 415f9490399SQingqing Zhuo table->WatermarkRow[WM_DCFCLK][0].MinMclk = 0; 416f9490399SQingqing Zhuo table->WatermarkRow[WM_DCFCLK][0].MinClock = 0; 417f9490399SQingqing Zhuo table->WatermarkRow[WM_DCFCLK][num_valid_sets - 1].MaxMclk = 0xFFFF; 418f9490399SQingqing Zhuo table->WatermarkRow[WM_DCFCLK][num_valid_sets - 1].MaxClock = 0xFFFF; 419f9490399SQingqing Zhuo 420f9490399SQingqing Zhuo /* This is for writeback only, does not matter currently as no writeback support*/ 421f9490399SQingqing Zhuo table->WatermarkRow[WM_SOCCLK][0].WmSetting = WM_A; 422f9490399SQingqing Zhuo table->WatermarkRow[WM_SOCCLK][0].MinClock = 0; 423f9490399SQingqing Zhuo table->WatermarkRow[WM_SOCCLK][0].MaxClock = 0xFFFF; 424f9490399SQingqing Zhuo table->WatermarkRow[WM_SOCCLK][0].MinMclk = 0; 425f9490399SQingqing Zhuo table->WatermarkRow[WM_SOCCLK][0].MaxMclk = 0xFFFF; 426f9490399SQingqing Zhuo } 427f9490399SQingqing Zhuo 428f9490399SQingqing Zhuo static void dcn315_notify_wm_ranges(struct clk_mgr *clk_mgr_base) 429f9490399SQingqing Zhuo { 430f9490399SQingqing Zhuo struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); 431f9490399SQingqing Zhuo struct clk_mgr_dcn315 *clk_mgr_dcn315 = TO_CLK_MGR_DCN315(clk_mgr); 432f9490399SQingqing Zhuo struct dcn315_watermarks *table = clk_mgr_dcn315->smu_wm_set.wm_set; 433f9490399SQingqing Zhuo 434f9490399SQingqing Zhuo if (!clk_mgr->smu_ver) 435f9490399SQingqing Zhuo return; 436f9490399SQingqing Zhuo 437f9490399SQingqing Zhuo if (!table || clk_mgr_dcn315->smu_wm_set.mc_address.quad_part == 0) 438f9490399SQingqing Zhuo return; 439f9490399SQingqing Zhuo 440f9490399SQingqing Zhuo memset(table, 0, sizeof(*table)); 441f9490399SQingqing Zhuo 442f9490399SQingqing Zhuo dcn315_build_watermark_ranges(clk_mgr_base->bw_params, table); 443f9490399SQingqing Zhuo 444f9490399SQingqing Zhuo dcn315_smu_set_dram_addr_high(clk_mgr, 445f9490399SQingqing Zhuo clk_mgr_dcn315->smu_wm_set.mc_address.high_part); 446f9490399SQingqing Zhuo dcn315_smu_set_dram_addr_low(clk_mgr, 447f9490399SQingqing Zhuo clk_mgr_dcn315->smu_wm_set.mc_address.low_part); 448f9490399SQingqing Zhuo dcn315_smu_transfer_wm_table_dram_2_smu(clk_mgr); 449f9490399SQingqing Zhuo } 450f9490399SQingqing Zhuo 451f9490399SQingqing Zhuo static void dcn315_get_dpm_table_from_smu(struct clk_mgr_internal *clk_mgr, 452f9490399SQingqing Zhuo struct dcn315_smu_dpm_clks *smu_dpm_clks) 453f9490399SQingqing Zhuo { 454f9490399SQingqing Zhuo DpmClocks_315_t *table = smu_dpm_clks->dpm_clks; 455f9490399SQingqing Zhuo 456f9490399SQingqing Zhuo if (!clk_mgr->smu_ver) 457f9490399SQingqing Zhuo return; 458f9490399SQingqing Zhuo 459f9490399SQingqing Zhuo if (!table || smu_dpm_clks->mc_address.quad_part == 0) 460f9490399SQingqing Zhuo return; 461f9490399SQingqing Zhuo 462f9490399SQingqing Zhuo memset(table, 0, sizeof(*table)); 463f9490399SQingqing Zhuo 464f9490399SQingqing Zhuo dcn315_smu_set_dram_addr_high(clk_mgr, 465f9490399SQingqing Zhuo smu_dpm_clks->mc_address.high_part); 466f9490399SQingqing Zhuo dcn315_smu_set_dram_addr_low(clk_mgr, 467f9490399SQingqing Zhuo smu_dpm_clks->mc_address.low_part); 468f9490399SQingqing Zhuo dcn315_smu_transfer_dpm_table_smu_2_dram(clk_mgr); 469f9490399SQingqing Zhuo } 470f9490399SQingqing Zhuo 471f728eb3aSMagali Lemes static void dcn315_clk_mgr_helper_populate_bw_params( 472f9490399SQingqing Zhuo struct clk_mgr_internal *clk_mgr, 473f9490399SQingqing Zhuo struct integrated_info *bios_info, 474f9490399SQingqing Zhuo const DpmClocks_315_t *clock_table) 475f9490399SQingqing Zhuo { 47660f6fe66SDmytro Laktyushkin int i; 477f9490399SQingqing Zhuo struct clk_bw_params *bw_params = clk_mgr->base.bw_params; 478174fc824SDmytro Laktyushkin uint32_t max_pstate = clock_table->NumDfPstatesEnabled - 1; 47960f6fe66SDmytro Laktyushkin struct clk_limit_table_entry def_max = bw_params->clk_table.entries[bw_params->clk_table.num_entries - 1]; 480f9490399SQingqing Zhuo 48160f6fe66SDmytro Laktyushkin /* For 315 we want to base clock table on dcfclk, need at least one entry regardless of pmfw table */ 48260f6fe66SDmytro Laktyushkin for (i = 0; i < clock_table->NumDcfClkLevelsEnabled; i++) { 48360f6fe66SDmytro Laktyushkin int j; 484f9490399SQingqing Zhuo 485174fc824SDmytro Laktyushkin /* DF table is sorted with clocks decreasing */ 486174fc824SDmytro Laktyushkin for (j = clock_table->NumDfPstatesEnabled - 2; j >= 0; j--) { 487174fc824SDmytro Laktyushkin if (clock_table->DfPstateTable[j].Voltage <= clock_table->SocVoltage[i]) 488174fc824SDmytro Laktyushkin max_pstate = j; 48960f6fe66SDmytro Laktyushkin } 490174fc824SDmytro Laktyushkin /* Max DCFCLK should match up with max pstate */ 491174fc824SDmytro Laktyushkin if (i == clock_table->NumDcfClkLevelsEnabled - 1) 492174fc824SDmytro Laktyushkin max_pstate = 0; 49360f6fe66SDmytro Laktyushkin 49489c342a9SDmytro Laktyushkin /* First search defaults for the clocks we don't read using closest lower or equal default dcfclk */ 49589c342a9SDmytro Laktyushkin for (j = bw_params->clk_table.num_entries - 1; j > 0; j--) 49689c342a9SDmytro Laktyushkin if (bw_params->clk_table.entries[j].dcfclk_mhz <= clock_table->DcfClocks[i]) 49789c342a9SDmytro Laktyushkin break; 49889c342a9SDmytro Laktyushkin bw_params->clk_table.entries[i].phyclk_mhz = bw_params->clk_table.entries[j].phyclk_mhz; 49989c342a9SDmytro Laktyushkin bw_params->clk_table.entries[i].phyclk_d18_mhz = bw_params->clk_table.entries[j].phyclk_d18_mhz; 50089c342a9SDmytro Laktyushkin bw_params->clk_table.entries[i].dtbclk_mhz = bw_params->clk_table.entries[j].dtbclk_mhz; 50189c342a9SDmytro Laktyushkin 50289c342a9SDmytro Laktyushkin /* Now update clocks we do read */ 503174fc824SDmytro Laktyushkin bw_params->clk_table.entries[i].fclk_mhz = clock_table->DfPstateTable[max_pstate].FClk; 504174fc824SDmytro Laktyushkin bw_params->clk_table.entries[i].memclk_mhz = clock_table->DfPstateTable[max_pstate].MemClk; 505174fc824SDmytro Laktyushkin bw_params->clk_table.entries[i].voltage = clock_table->SocVoltage[i]; 50660f6fe66SDmytro Laktyushkin bw_params->clk_table.entries[i].dcfclk_mhz = clock_table->DcfClocks[i]; 50760f6fe66SDmytro Laktyushkin bw_params->clk_table.entries[i].socclk_mhz = clock_table->SocClocks[i]; 50889c342a9SDmytro Laktyushkin bw_params->clk_table.entries[i].dispclk_mhz = clock_table->DispClocks[i]; 50989c342a9SDmytro Laktyushkin bw_params->clk_table.entries[i].dppclk_mhz = clock_table->DppClocks[i]; 51060f6fe66SDmytro Laktyushkin bw_params->clk_table.entries[i].wck_ratio = 1; 511b34e44bcSmin tang } 512f9490399SQingqing Zhuo 513174fc824SDmytro Laktyushkin /* Make sure to include at least one entry */ 514174fc824SDmytro Laktyushkin if (i == 0) { 515174fc824SDmytro Laktyushkin bw_params->clk_table.entries[i].fclk_mhz = clock_table->DfPstateTable[0].FClk; 516174fc824SDmytro Laktyushkin bw_params->clk_table.entries[i].memclk_mhz = clock_table->DfPstateTable[0].MemClk; 517174fc824SDmytro Laktyushkin bw_params->clk_table.entries[i].voltage = clock_table->DfPstateTable[0].Voltage; 518174fc824SDmytro Laktyushkin bw_params->clk_table.entries[i].dcfclk_mhz = clock_table->DcfClocks[0]; 51960f6fe66SDmytro Laktyushkin bw_params->clk_table.entries[i].wck_ratio = 1; 52060f6fe66SDmytro Laktyushkin i++; 52179978cc7SDmytro Laktyushkin } else if (clock_table->NumDcfClkLevelsEnabled != clock_table->NumSocClkLevelsEnabled) { 52279978cc7SDmytro Laktyushkin bw_params->clk_table.entries[i-1].voltage = clock_table->SocVoltage[clock_table->NumSocClkLevelsEnabled - 1]; 52379978cc7SDmytro Laktyushkin bw_params->clk_table.entries[i-1].socclk_mhz = clock_table->SocClocks[clock_table->NumSocClkLevelsEnabled - 1]; 52479978cc7SDmytro Laktyushkin bw_params->clk_table.entries[i-1].dispclk_mhz = clock_table->DispClocks[clock_table->NumDispClkLevelsEnabled - 1]; 52579978cc7SDmytro Laktyushkin bw_params->clk_table.entries[i-1].dppclk_mhz = clock_table->DppClocks[clock_table->NumDispClkLevelsEnabled - 1]; 52660f6fe66SDmytro Laktyushkin } 527174fc824SDmytro Laktyushkin bw_params->clk_table.num_entries = i; 52860f6fe66SDmytro Laktyushkin 52960f6fe66SDmytro Laktyushkin /* Set any 0 clocks to max default setting. Not an issue for 53060f6fe66SDmytro Laktyushkin * power since we aren't doing switching in such case anyway 53160f6fe66SDmytro Laktyushkin */ 53260f6fe66SDmytro Laktyushkin for (i = 0; i < bw_params->clk_table.num_entries; i++) { 53360f6fe66SDmytro Laktyushkin if (!bw_params->clk_table.entries[i].fclk_mhz) { 53460f6fe66SDmytro Laktyushkin bw_params->clk_table.entries[i].fclk_mhz = def_max.fclk_mhz; 53560f6fe66SDmytro Laktyushkin bw_params->clk_table.entries[i].memclk_mhz = def_max.memclk_mhz; 53660f6fe66SDmytro Laktyushkin bw_params->clk_table.entries[i].voltage = def_max.voltage; 53760f6fe66SDmytro Laktyushkin } 53860f6fe66SDmytro Laktyushkin if (!bw_params->clk_table.entries[i].dcfclk_mhz) 53960f6fe66SDmytro Laktyushkin bw_params->clk_table.entries[i].dcfclk_mhz = def_max.dcfclk_mhz; 54060f6fe66SDmytro Laktyushkin if (!bw_params->clk_table.entries[i].socclk_mhz) 54160f6fe66SDmytro Laktyushkin bw_params->clk_table.entries[i].socclk_mhz = def_max.socclk_mhz; 54260f6fe66SDmytro Laktyushkin if (!bw_params->clk_table.entries[i].dispclk_mhz) 54360f6fe66SDmytro Laktyushkin bw_params->clk_table.entries[i].dispclk_mhz = def_max.dispclk_mhz; 54460f6fe66SDmytro Laktyushkin if (!bw_params->clk_table.entries[i].dppclk_mhz) 54560f6fe66SDmytro Laktyushkin bw_params->clk_table.entries[i].dppclk_mhz = def_max.dppclk_mhz; 54689c342a9SDmytro Laktyushkin if (!bw_params->clk_table.entries[i].phyclk_mhz) 54789c342a9SDmytro Laktyushkin bw_params->clk_table.entries[i].phyclk_mhz = def_max.phyclk_mhz; 54889c342a9SDmytro Laktyushkin if (!bw_params->clk_table.entries[i].phyclk_d18_mhz) 54989c342a9SDmytro Laktyushkin bw_params->clk_table.entries[i].phyclk_d18_mhz = def_max.phyclk_d18_mhz; 55089c342a9SDmytro Laktyushkin if (!bw_params->clk_table.entries[i].dtbclk_mhz) 55189c342a9SDmytro Laktyushkin bw_params->clk_table.entries[i].dtbclk_mhz = def_max.dtbclk_mhz; 55260f6fe66SDmytro Laktyushkin } 553174fc824SDmytro Laktyushkin 554174fc824SDmytro Laktyushkin /* Make sure all highest default clocks are included*/ 555174fc824SDmytro Laktyushkin ASSERT(bw_params->clk_table.entries[i-1].phyclk_mhz == def_max.phyclk_mhz); 556174fc824SDmytro Laktyushkin ASSERT(bw_params->clk_table.entries[i-1].phyclk_d18_mhz == def_max.phyclk_d18_mhz); 557174fc824SDmytro Laktyushkin ASSERT(bw_params->clk_table.entries[i-1].dtbclk_mhz == def_max.dtbclk_mhz); 558f173fbe5SQingqing Zhuo ASSERT(bw_params->clk_table.entries[i-1].dcfclk_mhz); 559f9490399SQingqing Zhuo bw_params->vram_type = bios_info->memory_type; 560f9490399SQingqing Zhuo bw_params->num_channels = bios_info->ma_channel_number; 56162f0576cSDmytro Laktyushkin bw_params->dram_channel_width_bytes = bios_info->memory_type == 0x22 ? 8 : 4; 562f9490399SQingqing Zhuo 563f9490399SQingqing Zhuo for (i = 0; i < WM_SET_COUNT; i++) { 564f9490399SQingqing Zhuo bw_params->wm_table.entries[i].wm_inst = i; 565f9490399SQingqing Zhuo 566f9490399SQingqing Zhuo if (i >= bw_params->clk_table.num_entries) { 567f9490399SQingqing Zhuo bw_params->wm_table.entries[i].valid = false; 568f9490399SQingqing Zhuo continue; 569f9490399SQingqing Zhuo } 570f9490399SQingqing Zhuo 571f9490399SQingqing Zhuo bw_params->wm_table.entries[i].wm_type = WM_TYPE_PSTATE_CHG; 572f9490399SQingqing Zhuo bw_params->wm_table.entries[i].valid = true; 573f9490399SQingqing Zhuo } 574f9490399SQingqing Zhuo } 575f9490399SQingqing Zhuo 576f9490399SQingqing Zhuo static void dcn315_enable_pme_wa(struct clk_mgr *clk_mgr_base) 577f9490399SQingqing Zhuo { 578f9490399SQingqing Zhuo struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); 579f9490399SQingqing Zhuo 580f9490399SQingqing Zhuo dcn315_smu_enable_pme_wa(clk_mgr); 581f9490399SQingqing Zhuo } 582f9490399SQingqing Zhuo 583f9490399SQingqing Zhuo static struct clk_mgr_funcs dcn315_funcs = { 584f9490399SQingqing Zhuo .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz, 5850ec74408SLeung, Martin .get_dtb_ref_clk_frequency = dcn31_get_dtb_ref_freq_khz, 586f9490399SQingqing Zhuo .update_clocks = dcn315_update_clocks, 587f9490399SQingqing Zhuo .init_clocks = dcn31_init_clocks, 588f9490399SQingqing Zhuo .enable_pme_wa = dcn315_enable_pme_wa, 589f9490399SQingqing Zhuo .are_clock_states_equal = dcn31_are_clock_states_equal, 590f9490399SQingqing Zhuo .notify_wm_ranges = dcn315_notify_wm_ranges 591f9490399SQingqing Zhuo }; 592f9490399SQingqing Zhuo extern struct clk_mgr_funcs dcn3_fpga_funcs; 593f9490399SQingqing Zhuo 594f9490399SQingqing Zhuo void dcn315_clk_mgr_construct( 595f9490399SQingqing Zhuo struct dc_context *ctx, 596f9490399SQingqing Zhuo struct clk_mgr_dcn315 *clk_mgr, 597f9490399SQingqing Zhuo struct pp_smu_funcs *pp_smu, 598f9490399SQingqing Zhuo struct dccg *dccg) 599f9490399SQingqing Zhuo { 600f9490399SQingqing Zhuo struct dcn315_smu_dpm_clks smu_dpm_clks = { 0 }; 601*25879d7bSQingqing Zhuo struct clk_log_info log_info = {0}; 602f9490399SQingqing Zhuo 603f9490399SQingqing Zhuo clk_mgr->base.base.ctx = ctx; 604f9490399SQingqing Zhuo clk_mgr->base.base.funcs = &dcn315_funcs; 605f9490399SQingqing Zhuo 606f9490399SQingqing Zhuo clk_mgr->base.pp_smu = pp_smu; 607f9490399SQingqing Zhuo 608f9490399SQingqing Zhuo clk_mgr->base.dccg = dccg; 609f9490399SQingqing Zhuo clk_mgr->base.dfs_bypass_disp_clk = 0; 610f9490399SQingqing Zhuo 611f9490399SQingqing Zhuo clk_mgr->base.dprefclk_ss_percentage = 0; 612f9490399SQingqing Zhuo clk_mgr->base.dprefclk_ss_divider = 1000; 613f9490399SQingqing Zhuo clk_mgr->base.ss_on_dprefclk = false; 614f9490399SQingqing Zhuo clk_mgr->base.dfs_ref_freq_khz = 48000; 615f9490399SQingqing Zhuo 616f9490399SQingqing Zhuo clk_mgr->smu_wm_set.wm_set = (struct dcn315_watermarks *)dm_helpers_allocate_gpu_mem( 617f9490399SQingqing Zhuo clk_mgr->base.base.ctx, 618f9490399SQingqing Zhuo DC_MEM_ALLOC_TYPE_FRAME_BUFFER, 619f9490399SQingqing Zhuo sizeof(struct dcn315_watermarks), 620f9490399SQingqing Zhuo &clk_mgr->smu_wm_set.mc_address.quad_part); 621f9490399SQingqing Zhuo 622f9490399SQingqing Zhuo if (!clk_mgr->smu_wm_set.wm_set) { 623f9490399SQingqing Zhuo clk_mgr->smu_wm_set.wm_set = &dummy_wms; 624f9490399SQingqing Zhuo clk_mgr->smu_wm_set.mc_address.quad_part = 0; 625f9490399SQingqing Zhuo } 626f9490399SQingqing Zhuo ASSERT(clk_mgr->smu_wm_set.wm_set); 627f9490399SQingqing Zhuo 628f9490399SQingqing Zhuo smu_dpm_clks.dpm_clks = (DpmClocks_315_t *)dm_helpers_allocate_gpu_mem( 629f9490399SQingqing Zhuo clk_mgr->base.base.ctx, 630f9490399SQingqing Zhuo DC_MEM_ALLOC_TYPE_FRAME_BUFFER, 631f9490399SQingqing Zhuo sizeof(DpmClocks_315_t), 632f9490399SQingqing Zhuo &smu_dpm_clks.mc_address.quad_part); 633f9490399SQingqing Zhuo 634f9490399SQingqing Zhuo if (smu_dpm_clks.dpm_clks == NULL) { 635f9490399SQingqing Zhuo smu_dpm_clks.dpm_clks = &dummy_clocks; 636f9490399SQingqing Zhuo smu_dpm_clks.mc_address.quad_part = 0; 637f9490399SQingqing Zhuo } 638f9490399SQingqing Zhuo 639f9490399SQingqing Zhuo ASSERT(smu_dpm_clks.dpm_clks); 640f9490399SQingqing Zhuo 641f9490399SQingqing Zhuo clk_mgr->base.smu_ver = dcn315_smu_get_smu_version(&clk_mgr->base); 642f9490399SQingqing Zhuo 643f9490399SQingqing Zhuo if (clk_mgr->base.smu_ver > 0) 644f9490399SQingqing Zhuo clk_mgr->base.smu_present = true; 645f9490399SQingqing Zhuo 646f9490399SQingqing Zhuo if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) { 647f9490399SQingqing Zhuo dcn315_bw_params.wm_table = lpddr5_wm_table; 648f9490399SQingqing Zhuo } else { 649f9490399SQingqing Zhuo dcn315_bw_params.wm_table = ddr5_wm_table; 650f9490399SQingqing Zhuo } 651f9490399SQingqing Zhuo /* Saved clocks configured at boot for debug purposes */ 652203dc777SJiapeng Chong dcn315_dump_clk_registers(&clk_mgr->base.base.boot_snapshot, 653203dc777SJiapeng Chong &clk_mgr->base.base, &log_info); 654f9490399SQingqing Zhuo 655f9490399SQingqing Zhuo clk_mgr->base.base.dprefclk_khz = 600000; 6563b8b44a4SCharlene Liu clk_mgr->base.base.dprefclk_khz = dcn315_smu_get_dpref_clk(&clk_mgr->base); 6570ec74408SLeung, Martin clk_mgr->base.base.clks.ref_dtbclk_khz = clk_mgr->base.base.dprefclk_khz; 658f9490399SQingqing Zhuo dce_clock_read_ss_info(&clk_mgr->base); 6590ec74408SLeung, 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); 660f9490399SQingqing Zhuo 661f9490399SQingqing Zhuo clk_mgr->base.base.bw_params = &dcn315_bw_params; 662f9490399SQingqing Zhuo 663f9490399SQingqing Zhuo if (clk_mgr->base.base.ctx->dc->debug.pstate_enabled) { 664c8b1d0feSLeo Chen int i; 665c8b1d0feSLeo Chen 666f9490399SQingqing Zhuo dcn315_get_dpm_table_from_smu(&clk_mgr->base, &smu_dpm_clks); 667c8b1d0feSLeo Chen DC_LOG_SMU("NumDcfClkLevelsEnabled: %d\n" 668c8b1d0feSLeo Chen "NumDispClkLevelsEnabled: %d\n" 669c8b1d0feSLeo Chen "NumSocClkLevelsEnabled: %d\n" 670c8b1d0feSLeo Chen "VcnClkLevelsEnabled: %d\n" 671c8b1d0feSLeo Chen "NumDfPst atesEnabled: %d\n" 672c8b1d0feSLeo Chen "MinGfxClk: %d\n" 673c8b1d0feSLeo Chen "MaxGfxClk: %d\n", 674c8b1d0feSLeo Chen smu_dpm_clks.dpm_clks->NumDcfClkLevelsEnabled, 675c8b1d0feSLeo Chen smu_dpm_clks.dpm_clks->NumDispClkLevelsEnabled, 676c8b1d0feSLeo Chen smu_dpm_clks.dpm_clks->NumSocClkLevelsEnabled, 677c8b1d0feSLeo Chen smu_dpm_clks.dpm_clks->VcnClkLevelsEnabled, 678c8b1d0feSLeo Chen smu_dpm_clks.dpm_clks->NumDfPstatesEnabled, 679c8b1d0feSLeo Chen smu_dpm_clks.dpm_clks->MinGfxClk, 680c8b1d0feSLeo Chen smu_dpm_clks.dpm_clks->MaxGfxClk); 681c8b1d0feSLeo Chen for (i = 0; i < smu_dpm_clks.dpm_clks->NumDcfClkLevelsEnabled; i++) { 682c8b1d0feSLeo Chen DC_LOG_SMU("smu_dpm_clks.dpm_clks->DcfClocks[%d] = %d\n", 683c8b1d0feSLeo Chen i, 684c8b1d0feSLeo Chen smu_dpm_clks.dpm_clks->DcfClocks[i]); 685c8b1d0feSLeo Chen } 686c8b1d0feSLeo Chen for (i = 0; i < smu_dpm_clks.dpm_clks->NumDispClkLevelsEnabled; i++) { 687c8b1d0feSLeo Chen DC_LOG_SMU("smu_dpm_clks.dpm_clks->DispClocks[%d] = %d\n", 688c8b1d0feSLeo Chen i, smu_dpm_clks.dpm_clks->DispClocks[i]); 689c8b1d0feSLeo Chen } 690c8b1d0feSLeo Chen for (i = 0; i < smu_dpm_clks.dpm_clks->NumSocClkLevelsEnabled; i++) { 691c8b1d0feSLeo Chen DC_LOG_SMU("smu_dpm_clks.dpm_clks->SocClocks[%d] = %d\n", 692c8b1d0feSLeo Chen i, smu_dpm_clks.dpm_clks->SocClocks[i]); 693c8b1d0feSLeo Chen } 694c8b1d0feSLeo Chen for (i = 0; i < NUM_SOC_VOLTAGE_LEVELS; i++) 695c8b1d0feSLeo Chen DC_LOG_SMU("smu_dpm_clks.dpm_clks->SocVoltage[%d] = %d\n", 696c8b1d0feSLeo Chen i, smu_dpm_clks.dpm_clks->SocVoltage[i]); 697c8b1d0feSLeo Chen 698c8b1d0feSLeo Chen for (i = 0; i < NUM_DF_PSTATE_LEVELS; i++) { 699c8b1d0feSLeo Chen DC_LOG_SMU("smu_dpm_clks.dpm_clks.DfPstateTable[%d].FClk = %d\n" 700c8b1d0feSLeo Chen "smu_dpm_clks.dpm_clks->DfPstateTable[%d].MemClk= %d\n" 701c8b1d0feSLeo Chen "smu_dpm_clks.dpm_clks->DfPstateTable[%d].Voltage = %d\n", 702c8b1d0feSLeo Chen i, smu_dpm_clks.dpm_clks->DfPstateTable[i].FClk, 703c8b1d0feSLeo Chen i, smu_dpm_clks.dpm_clks->DfPstateTable[i].MemClk, 704c8b1d0feSLeo Chen i, smu_dpm_clks.dpm_clks->DfPstateTable[i].Voltage); 705c8b1d0feSLeo Chen } 706f9490399SQingqing Zhuo 707f9490399SQingqing Zhuo if (ctx->dc_bios && ctx->dc_bios->integrated_info) { 708f9490399SQingqing Zhuo dcn315_clk_mgr_helper_populate_bw_params( 709f9490399SQingqing Zhuo &clk_mgr->base, 710f9490399SQingqing Zhuo ctx->dc_bios->integrated_info, 711f9490399SQingqing Zhuo smu_dpm_clks.dpm_clks); 712f9490399SQingqing Zhuo } 713f9490399SQingqing Zhuo } 714f9490399SQingqing Zhuo 715f9490399SQingqing Zhuo if (smu_dpm_clks.dpm_clks && smu_dpm_clks.mc_address.quad_part != 0) 716f9490399SQingqing Zhuo dm_helpers_free_gpu_mem(clk_mgr->base.base.ctx, DC_MEM_ALLOC_TYPE_FRAME_BUFFER, 717f9490399SQingqing Zhuo smu_dpm_clks.dpm_clks); 718f9490399SQingqing Zhuo } 719f9490399SQingqing Zhuo 720f9490399SQingqing Zhuo void dcn315_clk_mgr_destroy(struct clk_mgr_internal *clk_mgr_int) 721f9490399SQingqing Zhuo { 722f9490399SQingqing Zhuo struct clk_mgr_dcn315 *clk_mgr = TO_CLK_MGR_DCN315(clk_mgr_int); 723f9490399SQingqing Zhuo 724f9490399SQingqing Zhuo if (clk_mgr->smu_wm_set.wm_set && clk_mgr->smu_wm_set.mc_address.quad_part != 0) 725f9490399SQingqing Zhuo dm_helpers_free_gpu_mem(clk_mgr_int->base.ctx, DC_MEM_ALLOC_TYPE_FRAME_BUFFER, 726f9490399SQingqing Zhuo clk_mgr->smu_wm_set.wm_set); 727f9490399SQingqing Zhuo } 728