1 /* 2 * Copyright 2012-16 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 <linux/slab.h> 27 28 #include "dal_asic_id.h" 29 #include "dc_types.h" 30 #include "dccg.h" 31 #include "clk_mgr_internal.h" 32 33 #include "dce100/dce_clk_mgr.h" 34 #include "dce110/dce110_clk_mgr.h" 35 #include "dce112/dce112_clk_mgr.h" 36 #include "dce120/dce120_clk_mgr.h" 37 #include "dcn10/rv1_clk_mgr.h" 38 #include "dcn10/rv2_clk_mgr.h" 39 #include "dcn20/dcn20_clk_mgr.h" 40 #include "dcn21/rn_clk_mgr.h" 41 42 43 int clk_mgr_helper_get_active_display_cnt( 44 struct dc *dc, 45 struct dc_state *context) 46 { 47 int i, display_count; 48 49 display_count = 0; 50 for (i = 0; i < context->stream_count; i++) { 51 const struct dc_stream_state *stream = context->streams[i]; 52 53 /* 54 * Only notify active stream or virtual stream. 55 * Need to notify virtual stream to work around 56 * headless case. HPD does not fire when system is in 57 * S0i2. 58 */ 59 if (!stream->dpms_off || stream->signal == SIGNAL_TYPE_VIRTUAL) 60 display_count++; 61 } 62 63 return display_count; 64 } 65 66 int clk_mgr_helper_get_active_plane_cnt( 67 struct dc *dc, 68 struct dc_state *context) 69 { 70 int i, total_plane_count; 71 72 total_plane_count = 0; 73 for (i = 0; i < context->stream_count; i++) { 74 const struct dc_stream_status stream_status = context->stream_status[i]; 75 76 /* 77 * Sum up plane_count for all streams ( active and virtual ). 78 */ 79 total_plane_count += stream_status.plane_count; 80 } 81 82 return total_plane_count; 83 } 84 85 void clk_mgr_exit_optimized_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 (dc->hwss.exit_optimized_pwr_state) 90 dc->hwss.exit_optimized_pwr_state(dc, dc->current_state); 91 92 if (edp_link) { 93 clk_mgr->psr_allow_active_cache = edp_link->psr_allow_active; 94 dc_link_set_psr_allow_active(edp_link, false, false); 95 } 96 97 } 98 99 void clk_mgr_optimize_pwr_state(const struct dc *dc, struct clk_mgr *clk_mgr) 100 { 101 struct dc_link *edp_link = get_edp_link(dc); 102 103 if (edp_link) 104 dc_link_set_psr_allow_active(edp_link, clk_mgr->psr_allow_active_cache, false); 105 106 if (dc->hwss.optimize_pwr_state) 107 dc->hwss.optimize_pwr_state(dc, dc->current_state); 108 109 } 110 111 struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *pp_smu, struct dccg *dccg) 112 { 113 struct hw_asic_id asic_id = ctx->asic_id; 114 115 struct clk_mgr_internal *clk_mgr = kzalloc(sizeof(*clk_mgr), GFP_KERNEL); 116 117 if (clk_mgr == NULL) { 118 BREAK_TO_DEBUGGER(); 119 return NULL; 120 } 121 122 switch (asic_id.chip_family) { 123 case FAMILY_CI: 124 case FAMILY_KV: 125 dce_clk_mgr_construct(ctx, clk_mgr); 126 break; 127 case FAMILY_CZ: 128 dce110_clk_mgr_construct(ctx, clk_mgr); 129 break; 130 case FAMILY_VI: 131 if (ASIC_REV_IS_TONGA_P(asic_id.hw_internal_rev) || 132 ASIC_REV_IS_FIJI_P(asic_id.hw_internal_rev)) { 133 dce_clk_mgr_construct(ctx, clk_mgr); 134 break; 135 } 136 if (ASIC_REV_IS_POLARIS10_P(asic_id.hw_internal_rev) || 137 ASIC_REV_IS_POLARIS11_M(asic_id.hw_internal_rev) || 138 ASIC_REV_IS_POLARIS12_V(asic_id.hw_internal_rev)) { 139 dce112_clk_mgr_construct(ctx, clk_mgr); 140 break; 141 } 142 if (ASIC_REV_IS_VEGAM(asic_id.hw_internal_rev)) { 143 dce112_clk_mgr_construct(ctx, clk_mgr); 144 break; 145 } 146 break; 147 case FAMILY_AI: 148 if (ASICREV_IS_VEGA20_P(asic_id.hw_internal_rev)) 149 dce121_clk_mgr_construct(ctx, clk_mgr); 150 else 151 dce120_clk_mgr_construct(ctx, clk_mgr); 152 break; 153 154 #if defined(CONFIG_DRM_AMD_DC_DCN) 155 case FAMILY_RV: 156 if (ASICREV_IS_RENOIR(asic_id.hw_internal_rev)) { 157 rn_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); 158 break; 159 } 160 if (ASICREV_IS_RAVEN2(asic_id.hw_internal_rev)) { 161 rv2_clk_mgr_construct(ctx, clk_mgr, pp_smu); 162 break; 163 } 164 if (ASICREV_IS_RAVEN(asic_id.hw_internal_rev) || 165 ASICREV_IS_PICASSO(asic_id.hw_internal_rev)) { 166 rv1_clk_mgr_construct(ctx, clk_mgr, pp_smu); 167 break; 168 } 169 break; 170 171 case FAMILY_NV: 172 dcn20_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); 173 break; 174 #endif /* Family RV and NV*/ 175 176 default: 177 ASSERT(0); /* Unknown Asic */ 178 break; 179 } 180 181 return &clk_mgr->base; 182 } 183 184 void dc_destroy_clk_mgr(struct clk_mgr *clk_mgr_base) 185 { 186 struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); 187 188 kfree(clk_mgr); 189 } 190 191