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