1/* $NetBSD: amdgpu_clk_mgr.c,v 1.2 2021/12/18 23:45:01 riastradh Exp $ */ 2 3/* 4 * Copyright 2012-16 Advanced Micro Devices, Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: AMD 25 * 26 */ 27 28#include <sys/cdefs.h> 29__KERNEL_RCSID(0, "$NetBSD: amdgpu_clk_mgr.c,v 1.2 2021/12/18 23:45:01 riastradh Exp $"); 30 31#include <linux/slab.h> 32 33#include "dal_asic_id.h" 34#include "dc_types.h" 35#include "dccg.h" 36#include "clk_mgr_internal.h" 37 38#include "dce100/dce_clk_mgr.h" 39#include "dce110/dce110_clk_mgr.h" 40#include "dce112/dce112_clk_mgr.h" 41#include "dce120/dce120_clk_mgr.h" 42#include "dcn10/rv1_clk_mgr.h" 43#include "dcn10/rv2_clk_mgr.h" 44#include "dcn20/dcn20_clk_mgr.h" 45#include "dcn21/rn_clk_mgr.h" 46 47 48int clk_mgr_helper_get_active_display_cnt( 49 struct dc *dc, 50 struct dc_state *context) 51{ 52 int i, display_count; 53 54 display_count = 0; 55 for (i = 0; i < context->stream_count; i++) { 56 const struct dc_stream_state *stream = context->streams[i]; 57 58 /* 59 * Only notify active stream or virtual stream. 60 * Need to notify virtual stream to work around 61 * headless case. HPD does not fire when system is in 62 * S0i2. 63 */ 64 if (!stream->dpms_off || stream->signal == SIGNAL_TYPE_VIRTUAL) 65 display_count++; 66 } 67 68 return display_count; 69} 70 71void clk_mgr_exit_optimized_pwr_state(const struct dc *dc, struct clk_mgr *clk_mgr) 72{ 73 struct dc_link *edp_link = get_edp_link(dc); 74 75 if (dc->hwss.exit_optimized_pwr_state) 76 dc->hwss.exit_optimized_pwr_state(dc, dc->current_state); 77 78 if (edp_link) { 79 clk_mgr->psr_allow_active_cache = edp_link->psr_allow_active; 80 dc_link_set_psr_allow_active(edp_link, false, false); 81 } 82 83} 84 85void clk_mgr_optimize_pwr_state(const struct dc *dc, struct clk_mgr *clk_mgr) 86{ 87 struct dc_link *edp_link = get_edp_link(dc); 88 89 if (edp_link) 90 dc_link_set_psr_allow_active(edp_link, clk_mgr->psr_allow_active_cache, false); 91 92 if (dc->hwss.optimize_pwr_state) 93 dc->hwss.optimize_pwr_state(dc, dc->current_state); 94 95} 96 97struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *pp_smu, struct dccg *dccg) 98{ 99 struct hw_asic_id asic_id = ctx->asic_id; 100 101 struct clk_mgr_internal *clk_mgr = kzalloc(sizeof(*clk_mgr), GFP_KERNEL); 102 103 if (clk_mgr == NULL) { 104 BREAK_TO_DEBUGGER(); 105 return NULL; 106 } 107 108 switch (asic_id.chip_family) { 109 case FAMILY_CI: 110 case FAMILY_KV: 111 dce_clk_mgr_construct(ctx, clk_mgr); 112 break; 113 case FAMILY_CZ: 114 dce110_clk_mgr_construct(ctx, clk_mgr); 115 break; 116 case FAMILY_VI: 117 if (ASIC_REV_IS_TONGA_P(asic_id.hw_internal_rev) || 118 ASIC_REV_IS_FIJI_P(asic_id.hw_internal_rev)) { 119 dce_clk_mgr_construct(ctx, clk_mgr); 120 break; 121 } 122 if (ASIC_REV_IS_POLARIS10_P(asic_id.hw_internal_rev) || 123 ASIC_REV_IS_POLARIS11_M(asic_id.hw_internal_rev) || 124 ASIC_REV_IS_POLARIS12_V(asic_id.hw_internal_rev)) { 125 dce112_clk_mgr_construct(ctx, clk_mgr); 126 break; 127 } 128 if (ASIC_REV_IS_VEGAM(asic_id.hw_internal_rev)) { 129 dce112_clk_mgr_construct(ctx, clk_mgr); 130 break; 131 } 132 break; 133 case FAMILY_AI: 134 if (ASICREV_IS_VEGA20_P(asic_id.hw_internal_rev)) 135 dce121_clk_mgr_construct(ctx, clk_mgr); 136 else 137 dce120_clk_mgr_construct(ctx, clk_mgr); 138 break; 139 140#if defined(CONFIG_DRM_AMD_DC_DCN) 141 case FAMILY_RV: 142 if (ASICREV_IS_DALI(asic_id.hw_internal_rev) || 143 ASICREV_IS_POLLOCK(asic_id.hw_internal_rev)) { 144 /* TEMP: this check has to come before ASICREV_IS_RENOIR */ 145 /* which also incorrectly returns true for Dali/Pollock*/ 146 rv2_clk_mgr_construct(ctx, clk_mgr, pp_smu); 147 break; 148 } 149 if (ASICREV_IS_RENOIR(asic_id.hw_internal_rev)) { 150 rn_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); 151 break; 152 } 153 if (ASICREV_IS_RAVEN2(asic_id.hw_internal_rev)) { 154 rv2_clk_mgr_construct(ctx, clk_mgr, pp_smu); 155 break; 156 } 157 if (ASICREV_IS_RAVEN(asic_id.hw_internal_rev) || 158 ASICREV_IS_PICASSO(asic_id.hw_internal_rev)) { 159 rv1_clk_mgr_construct(ctx, clk_mgr, pp_smu); 160 break; 161 } 162 break; 163 164 case FAMILY_NV: 165 dcn20_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); 166 break; 167#endif /* Family RV and NV*/ 168 169 default: 170 ASSERT(0); /* Unknown Asic */ 171 break; 172 } 173 174 return &clk_mgr->base; 175} 176 177void dc_destroy_clk_mgr(struct clk_mgr *clk_mgr_base) 178{ 179 struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); 180 181 kfree(clk_mgr); 182} 183 184