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 "dal_asic_id.h" |
27 | #include "dc_types.h" |
28 | #include "dccg.h" |
29 | #include "clk_mgr_internal.h" |
30 | #include "dc_state_priv.h" |
31 | #include "link.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 "dce60/dce60_clk_mgr.h" |
38 | #include "dcn10/rv1_clk_mgr.h" |
39 | #include "dcn10/rv2_clk_mgr.h" |
40 | #include "dcn20/dcn20_clk_mgr.h" |
41 | #include "dcn21/rn_clk_mgr.h" |
42 | #include "dcn201/dcn201_clk_mgr.h" |
43 | #include "dcn30/dcn30_clk_mgr.h" |
44 | #include "dcn301/vg_clk_mgr.h" |
45 | #include "dcn31/dcn31_clk_mgr.h" |
46 | #include "dcn314/dcn314_clk_mgr.h" |
47 | #include "dcn315/dcn315_clk_mgr.h" |
48 | #include "dcn316/dcn316_clk_mgr.h" |
49 | #include "dcn32/dcn32_clk_mgr.h" |
50 | #include "dcn35/dcn35_clk_mgr.h" |
51 | |
52 | int clk_mgr_helper_get_active_display_cnt( |
53 | struct dc *dc, |
54 | struct dc_state *context) |
55 | { |
56 | int i, display_count; |
57 | |
58 | display_count = 0; |
59 | for (i = 0; i < context->stream_count; i++) { |
60 | const struct dc_stream_state *stream = context->streams[i]; |
61 | |
62 | /* Don't count SubVP phantom pipes as part of active |
63 | * display count |
64 | */ |
65 | if (dc_state_get_stream_subvp_type(state: context, stream) == SUBVP_PHANTOM) |
66 | continue; |
67 | |
68 | /* |
69 | * Only notify active stream or virtual stream. |
70 | * Need to notify virtual stream to work around |
71 | * headless case. HPD does not fire when system is in |
72 | * S0i2. |
73 | */ |
74 | if (!stream->dpms_off || stream->signal == SIGNAL_TYPE_VIRTUAL) |
75 | display_count++; |
76 | } |
77 | |
78 | return display_count; |
79 | } |
80 | |
81 | int clk_mgr_helper_get_active_plane_cnt( |
82 | struct dc *dc, |
83 | struct dc_state *context) |
84 | { |
85 | int i, total_plane_count; |
86 | |
87 | total_plane_count = 0; |
88 | for (i = 0; i < context->stream_count; i++) { |
89 | const struct dc_stream_status stream_status = context->stream_status[i]; |
90 | |
91 | /* |
92 | * Sum up plane_count for all streams ( active and virtual ). |
93 | */ |
94 | total_plane_count += stream_status.plane_count; |
95 | } |
96 | |
97 | return total_plane_count; |
98 | } |
99 | |
100 | void clk_mgr_exit_optimized_pwr_state(const struct dc *dc, struct clk_mgr *clk_mgr) |
101 | { |
102 | struct dc_link *edp_links[MAX_NUM_EDP]; |
103 | struct dc_link *edp_link = NULL; |
104 | int edp_num; |
105 | unsigned int panel_inst; |
106 | |
107 | dc_get_edp_links(dc, edp_links, edp_num: &edp_num); |
108 | if (dc->hwss.exit_optimized_pwr_state) |
109 | dc->hwss.exit_optimized_pwr_state(dc, dc->current_state); |
110 | |
111 | if (edp_num) { |
112 | for (panel_inst = 0; panel_inst < edp_num; panel_inst++) { |
113 | bool allow_active = false; |
114 | |
115 | edp_link = edp_links[panel_inst]; |
116 | if (!edp_link->psr_settings.psr_feature_enabled) |
117 | continue; |
118 | clk_mgr->psr_allow_active_cache = edp_link->psr_settings.psr_allow_active; |
119 | dc->link_srv->edp_set_psr_allow_active(edp_link, &allow_active, false, false, NULL); |
120 | dc->link_srv->edp_set_replay_allow_active(edp_link, &allow_active, false, false, NULL); |
121 | } |
122 | } |
123 | |
124 | } |
125 | |
126 | void clk_mgr_optimize_pwr_state(const struct dc *dc, struct clk_mgr *clk_mgr) |
127 | { |
128 | struct dc_link *edp_links[MAX_NUM_EDP]; |
129 | struct dc_link *edp_link = NULL; |
130 | int edp_num; |
131 | unsigned int panel_inst; |
132 | |
133 | dc_get_edp_links(dc, edp_links, edp_num: &edp_num); |
134 | if (edp_num) { |
135 | for (panel_inst = 0; panel_inst < edp_num; panel_inst++) { |
136 | edp_link = edp_links[panel_inst]; |
137 | if (!edp_link->psr_settings.psr_feature_enabled) |
138 | continue; |
139 | dc->link_srv->edp_set_psr_allow_active(edp_link, |
140 | &clk_mgr->psr_allow_active_cache, false, false, NULL); |
141 | dc->link_srv->edp_set_replay_allow_active(edp_link, |
142 | &clk_mgr->psr_allow_active_cache, false, false, NULL); |
143 | } |
144 | } |
145 | |
146 | if (dc->hwss.optimize_pwr_state) |
147 | dc->hwss.optimize_pwr_state(dc, dc->current_state); |
148 | |
149 | } |
150 | |
151 | struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *pp_smu, struct dccg *dccg) |
152 | { |
153 | struct hw_asic_id asic_id = ctx->asic_id; |
154 | |
155 | switch (asic_id.chip_family) { |
156 | #if defined(CONFIG_DRM_AMD_DC_SI) |
157 | case FAMILY_SI: { |
158 | struct clk_mgr_internal *clk_mgr = kzalloc(size: sizeof(*clk_mgr), GFP_KERNEL); |
159 | |
160 | if (clk_mgr == NULL) { |
161 | BREAK_TO_DEBUGGER(); |
162 | return NULL; |
163 | } |
164 | dce60_clk_mgr_construct(ctx, clk_mgr_dce: clk_mgr); |
165 | dce_clk_mgr_construct(ctx, clk_mgr_dce: clk_mgr); |
166 | return &clk_mgr->base; |
167 | } |
168 | #endif |
169 | case FAMILY_CI: |
170 | case FAMILY_KV: { |
171 | struct clk_mgr_internal *clk_mgr = kzalloc(size: sizeof(*clk_mgr), GFP_KERNEL); |
172 | |
173 | if (clk_mgr == NULL) { |
174 | BREAK_TO_DEBUGGER(); |
175 | return NULL; |
176 | } |
177 | dce_clk_mgr_construct(ctx, clk_mgr_dce: clk_mgr); |
178 | return &clk_mgr->base; |
179 | } |
180 | case FAMILY_CZ: { |
181 | struct clk_mgr_internal *clk_mgr = kzalloc(size: sizeof(*clk_mgr), GFP_KERNEL); |
182 | |
183 | if (clk_mgr == NULL) { |
184 | BREAK_TO_DEBUGGER(); |
185 | return NULL; |
186 | } |
187 | dce110_clk_mgr_construct(ctx, clk_mgr); |
188 | return &clk_mgr->base; |
189 | } |
190 | case FAMILY_VI: { |
191 | struct clk_mgr_internal *clk_mgr = kzalloc(size: sizeof(*clk_mgr), GFP_KERNEL); |
192 | |
193 | if (clk_mgr == NULL) { |
194 | BREAK_TO_DEBUGGER(); |
195 | return NULL; |
196 | } |
197 | if (ASIC_REV_IS_TONGA_P(asic_id.hw_internal_rev) || |
198 | ASIC_REV_IS_FIJI_P(asic_id.hw_internal_rev)) { |
199 | dce_clk_mgr_construct(ctx, clk_mgr_dce: clk_mgr); |
200 | return &clk_mgr->base; |
201 | } |
202 | if (ASIC_REV_IS_POLARIS10_P(asic_id.hw_internal_rev) || |
203 | ASIC_REV_IS_POLARIS11_M(asic_id.hw_internal_rev) || |
204 | ASIC_REV_IS_POLARIS12_V(asic_id.hw_internal_rev)) { |
205 | dce112_clk_mgr_construct(ctx, clk_mgr); |
206 | return &clk_mgr->base; |
207 | } |
208 | if (ASIC_REV_IS_VEGAM(asic_id.hw_internal_rev)) { |
209 | dce112_clk_mgr_construct(ctx, clk_mgr); |
210 | return &clk_mgr->base; |
211 | } |
212 | return &clk_mgr->base; |
213 | } |
214 | case FAMILY_AI: { |
215 | struct clk_mgr_internal *clk_mgr = kzalloc(size: sizeof(*clk_mgr), GFP_KERNEL); |
216 | |
217 | if (clk_mgr == NULL) { |
218 | BREAK_TO_DEBUGGER(); |
219 | return NULL; |
220 | } |
221 | if (ASICREV_IS_VEGA20_P(asic_id.hw_internal_rev)) |
222 | dce121_clk_mgr_construct(ctx, clk_mgr); |
223 | else |
224 | dce120_clk_mgr_construct(ctx, clk_mgr); |
225 | return &clk_mgr->base; |
226 | } |
227 | #if defined(CONFIG_DRM_AMD_DC_FP) |
228 | case FAMILY_RV: { |
229 | struct clk_mgr_internal *clk_mgr = kzalloc(size: sizeof(*clk_mgr), GFP_KERNEL); |
230 | |
231 | if (clk_mgr == NULL) { |
232 | BREAK_TO_DEBUGGER(); |
233 | return NULL; |
234 | } |
235 | |
236 | if (ASICREV_IS_RENOIR(asic_id.hw_internal_rev)) { |
237 | rn_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); |
238 | return &clk_mgr->base; |
239 | } |
240 | |
241 | if (ASICREV_IS_GREEN_SARDINE(asic_id.hw_internal_rev)) { |
242 | rn_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); |
243 | return &clk_mgr->base; |
244 | } |
245 | if (ASICREV_IS_RAVEN2(asic_id.hw_internal_rev)) { |
246 | rv2_clk_mgr_construct(ctx, clk_mgr, pp_smu); |
247 | return &clk_mgr->base; |
248 | } |
249 | if (ASICREV_IS_RAVEN(asic_id.hw_internal_rev) || |
250 | ASICREV_IS_PICASSO(asic_id.hw_internal_rev)) { |
251 | rv1_clk_mgr_construct(ctx, clk_mgr, pp_smu); |
252 | return &clk_mgr->base; |
253 | } |
254 | return &clk_mgr->base; |
255 | } |
256 | case FAMILY_NV: { |
257 | struct clk_mgr_internal *clk_mgr = kzalloc(size: sizeof(*clk_mgr), GFP_KERNEL); |
258 | |
259 | if (clk_mgr == NULL) { |
260 | BREAK_TO_DEBUGGER(); |
261 | return NULL; |
262 | } |
263 | if (ASICREV_IS_SIENNA_CICHLID_P(asic_id.hw_internal_rev)) { |
264 | dcn3_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); |
265 | return &clk_mgr->base; |
266 | } |
267 | if (ASICREV_IS_DIMGREY_CAVEFISH_P(asic_id.hw_internal_rev)) { |
268 | dcn3_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); |
269 | return &clk_mgr->base; |
270 | } |
271 | if (ASICREV_IS_BEIGE_GOBY_P(asic_id.hw_internal_rev)) { |
272 | dcn3_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); |
273 | return &clk_mgr->base; |
274 | } |
275 | if (asic_id.chip_id == DEVICE_ID_NV_13FE) { |
276 | dcn201_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); |
277 | return &clk_mgr->base; |
278 | } |
279 | dcn20_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); |
280 | return &clk_mgr->base; |
281 | } |
282 | case FAMILY_VGH: |
283 | if (ASICREV_IS_VANGOGH(asic_id.hw_internal_rev)) { |
284 | struct clk_mgr_vgh *clk_mgr = kzalloc(size: sizeof(*clk_mgr), GFP_KERNEL); |
285 | |
286 | if (clk_mgr == NULL) { |
287 | BREAK_TO_DEBUGGER(); |
288 | return NULL; |
289 | } |
290 | vg_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); |
291 | return &clk_mgr->base.base; |
292 | } |
293 | break; |
294 | |
295 | case FAMILY_YELLOW_CARP: { |
296 | struct clk_mgr_dcn31 *clk_mgr = kzalloc(size: sizeof(*clk_mgr), GFP_KERNEL); |
297 | |
298 | if (clk_mgr == NULL) { |
299 | BREAK_TO_DEBUGGER(); |
300 | return NULL; |
301 | } |
302 | |
303 | dcn31_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); |
304 | return &clk_mgr->base.base; |
305 | } |
306 | break; |
307 | case AMDGPU_FAMILY_GC_10_3_6: { |
308 | struct clk_mgr_dcn315 *clk_mgr = kzalloc(size: sizeof(*clk_mgr), GFP_KERNEL); |
309 | |
310 | if (clk_mgr == NULL) { |
311 | BREAK_TO_DEBUGGER(); |
312 | return NULL; |
313 | } |
314 | |
315 | dcn315_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); |
316 | return &clk_mgr->base.base; |
317 | } |
318 | break; |
319 | case AMDGPU_FAMILY_GC_10_3_7: { |
320 | struct clk_mgr_dcn316 *clk_mgr = kzalloc(size: sizeof(*clk_mgr), GFP_KERNEL); |
321 | |
322 | if (clk_mgr == NULL) { |
323 | BREAK_TO_DEBUGGER(); |
324 | return NULL; |
325 | } |
326 | |
327 | dcn316_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); |
328 | return &clk_mgr->base.base; |
329 | } |
330 | break; |
331 | case AMDGPU_FAMILY_GC_11_0_0: { |
332 | struct clk_mgr_internal *clk_mgr = kzalloc(size: sizeof(*clk_mgr), GFP_KERNEL); |
333 | |
334 | if (clk_mgr == NULL) { |
335 | BREAK_TO_DEBUGGER(); |
336 | return NULL; |
337 | } |
338 | |
339 | dcn32_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); |
340 | return &clk_mgr->base; |
341 | } |
342 | |
343 | case AMDGPU_FAMILY_GC_11_0_1: { |
344 | struct clk_mgr_dcn314 *clk_mgr = kzalloc(size: sizeof(*clk_mgr), GFP_KERNEL); |
345 | |
346 | if (clk_mgr == NULL) { |
347 | BREAK_TO_DEBUGGER(); |
348 | return NULL; |
349 | } |
350 | |
351 | dcn314_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); |
352 | return &clk_mgr->base.base; |
353 | } |
354 | break; |
355 | |
356 | case AMDGPU_FAMILY_GC_11_5_0: { |
357 | struct clk_mgr_dcn35 *clk_mgr = kzalloc(size: sizeof(*clk_mgr), GFP_KERNEL); |
358 | |
359 | if (clk_mgr == NULL) { |
360 | BREAK_TO_DEBUGGER(); |
361 | return NULL; |
362 | } |
363 | |
364 | dcn35_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); |
365 | return &clk_mgr->base.base; |
366 | } |
367 | break; |
368 | |
369 | #endif /* CONFIG_DRM_AMD_DC_FP */ |
370 | default: |
371 | ASSERT(0); /* Unknown Asic */ |
372 | break; |
373 | } |
374 | |
375 | return NULL; |
376 | } |
377 | |
378 | void dc_destroy_clk_mgr(struct clk_mgr *clk_mgr_base) |
379 | { |
380 | struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); |
381 | |
382 | #ifdef CONFIG_DRM_AMD_DC_FP |
383 | switch (clk_mgr_base->ctx->asic_id.chip_family) { |
384 | case FAMILY_NV: |
385 | if (ASICREV_IS_SIENNA_CICHLID_P(clk_mgr_base->ctx->asic_id.hw_internal_rev)) { |
386 | dcn3_clk_mgr_destroy(clk_mgr); |
387 | } else if (ASICREV_IS_DIMGREY_CAVEFISH_P(clk_mgr_base->ctx->asic_id.hw_internal_rev)) { |
388 | dcn3_clk_mgr_destroy(clk_mgr); |
389 | } |
390 | if (ASICREV_IS_BEIGE_GOBY_P(clk_mgr_base->ctx->asic_id.hw_internal_rev)) { |
391 | dcn3_clk_mgr_destroy(clk_mgr); |
392 | } |
393 | break; |
394 | |
395 | case FAMILY_VGH: |
396 | if (ASICREV_IS_VANGOGH(clk_mgr_base->ctx->asic_id.hw_internal_rev)) |
397 | vg_clk_mgr_destroy(clk_mgr); |
398 | break; |
399 | |
400 | case FAMILY_YELLOW_CARP: |
401 | dcn31_clk_mgr_destroy(clk_mgr_int: clk_mgr); |
402 | break; |
403 | |
404 | case AMDGPU_FAMILY_GC_10_3_6: |
405 | dcn315_clk_mgr_destroy(clk_mgr_int: clk_mgr); |
406 | break; |
407 | |
408 | case AMDGPU_FAMILY_GC_10_3_7: |
409 | dcn316_clk_mgr_destroy(clk_mgr_int: clk_mgr); |
410 | break; |
411 | |
412 | case AMDGPU_FAMILY_GC_11_0_0: |
413 | dcn32_clk_mgr_destroy(clk_mgr); |
414 | break; |
415 | |
416 | case AMDGPU_FAMILY_GC_11_0_1: |
417 | dcn314_clk_mgr_destroy(clk_mgr_int: clk_mgr); |
418 | break; |
419 | |
420 | case AMDGPU_FAMILY_GC_11_5_0: |
421 | dcn35_clk_mgr_destroy(clk_mgr_int: clk_mgr); |
422 | break; |
423 | |
424 | default: |
425 | break; |
426 | } |
427 | #endif /* CONFIG_DRM_AMD_DC_FP */ |
428 | |
429 | kfree(objp: clk_mgr); |
430 | } |
431 | |
432 | |