]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c
drm/amd/display: Roll core_stream into dc_stream
[mirror_ubuntu-bionic-kernel.git] / drivers / gpu / drm / amd / display / dc / dce112 / dce112_resource.c
1 /*
2 * Copyright 2012-15 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 "dm_services.h"
27
28 #include "link_encoder.h"
29 #include "stream_encoder.h"
30
31 #include "resource.h"
32 #include "include/irq_service_interface.h"
33 #include "dce110/dce110_resource.h"
34 #include "dce110/dce110_timing_generator.h"
35
36 #include "irq/dce110/irq_service_dce110.h"
37
38 #include "dce/dce_mem_input.h"
39 #include "dce/dce_transform.h"
40 #include "dce/dce_link_encoder.h"
41 #include "dce/dce_stream_encoder.h"
42 #include "dce/dce_audio.h"
43 #include "dce/dce_opp.h"
44 #include "dce/dce_ipp.h"
45 #include "dce/dce_clocks.h"
46 #include "dce/dce_clock_source.h"
47
48 #include "dce/dce_hwseq.h"
49 #include "dce112/dce112_hw_sequencer.h"
50 #include "dce/dce_abm.h"
51 #include "dce/dce_dmcu.h"
52
53 #include "reg_helper.h"
54
55 #include "dce/dce_11_2_d.h"
56 #include "dce/dce_11_2_sh_mask.h"
57
58 #ifndef mmDP_DPHY_INTERNAL_CTRL
59 #define mmDP_DPHY_INTERNAL_CTRL 0x4aa7
60 #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x4aa7
61 #define mmDP1_DP_DPHY_INTERNAL_CTRL 0x4ba7
62 #define mmDP2_DP_DPHY_INTERNAL_CTRL 0x4ca7
63 #define mmDP3_DP_DPHY_INTERNAL_CTRL 0x4da7
64 #define mmDP4_DP_DPHY_INTERNAL_CTRL 0x4ea7
65 #define mmDP5_DP_DPHY_INTERNAL_CTRL 0x4fa7
66 #define mmDP6_DP_DPHY_INTERNAL_CTRL 0x54a7
67 #define mmDP7_DP_DPHY_INTERNAL_CTRL 0x56a7
68 #define mmDP8_DP_DPHY_INTERNAL_CTRL 0x57a7
69 #endif
70
71 #ifndef mmBIOS_SCRATCH_2
72 #define mmBIOS_SCRATCH_2 0x05CB
73 #define mmBIOS_SCRATCH_6 0x05CF
74 #endif
75
76 #ifndef mmDP_DPHY_BS_SR_SWAP_CNTL
77 #define mmDP_DPHY_BS_SR_SWAP_CNTL 0x4ADC
78 #define mmDP0_DP_DPHY_BS_SR_SWAP_CNTL 0x4ADC
79 #define mmDP1_DP_DPHY_BS_SR_SWAP_CNTL 0x4BDC
80 #define mmDP2_DP_DPHY_BS_SR_SWAP_CNTL 0x4CDC
81 #define mmDP3_DP_DPHY_BS_SR_SWAP_CNTL 0x4DDC
82 #define mmDP4_DP_DPHY_BS_SR_SWAP_CNTL 0x4EDC
83 #define mmDP5_DP_DPHY_BS_SR_SWAP_CNTL 0x4FDC
84 #define mmDP6_DP_DPHY_BS_SR_SWAP_CNTL 0x54DC
85 #endif
86
87 #ifndef mmDP_DPHY_FAST_TRAINING
88 #define mmDP_DPHY_FAST_TRAINING 0x4ABC
89 #define mmDP0_DP_DPHY_FAST_TRAINING 0x4ABC
90 #define mmDP1_DP_DPHY_FAST_TRAINING 0x4BBC
91 #define mmDP2_DP_DPHY_FAST_TRAINING 0x4CBC
92 #define mmDP3_DP_DPHY_FAST_TRAINING 0x4DBC
93 #define mmDP4_DP_DPHY_FAST_TRAINING 0x4EBC
94 #define mmDP5_DP_DPHY_FAST_TRAINING 0x4FBC
95 #define mmDP6_DP_DPHY_FAST_TRAINING 0x54BC
96 #endif
97
98 enum dce112_clk_src_array_id {
99 DCE112_CLK_SRC_PLL0,
100 DCE112_CLK_SRC_PLL1,
101 DCE112_CLK_SRC_PLL2,
102 DCE112_CLK_SRC_PLL3,
103 DCE112_CLK_SRC_PLL4,
104 DCE112_CLK_SRC_PLL5,
105
106 DCE112_CLK_SRC_TOTAL
107 };
108
109 static const struct dce110_timing_generator_offsets dce112_tg_offsets[] = {
110 {
111 .crtc = (mmCRTC0_CRTC_CONTROL - mmCRTC_CONTROL),
112 .dcp = (mmDCP0_GRPH_CONTROL - mmGRPH_CONTROL),
113 },
114 {
115 .crtc = (mmCRTC1_CRTC_CONTROL - mmCRTC_CONTROL),
116 .dcp = (mmDCP1_GRPH_CONTROL - mmGRPH_CONTROL),
117 },
118 {
119 .crtc = (mmCRTC2_CRTC_CONTROL - mmCRTC_CONTROL),
120 .dcp = (mmDCP2_GRPH_CONTROL - mmGRPH_CONTROL),
121 },
122 {
123 .crtc = (mmCRTC3_CRTC_CONTROL - mmCRTC_CONTROL),
124 .dcp = (mmDCP3_GRPH_CONTROL - mmGRPH_CONTROL),
125 },
126 {
127 .crtc = (mmCRTC4_CRTC_CONTROL - mmCRTC_CONTROL),
128 .dcp = (mmDCP4_GRPH_CONTROL - mmGRPH_CONTROL),
129 },
130 {
131 .crtc = (mmCRTC5_CRTC_CONTROL - mmCRTC_CONTROL),
132 .dcp = (mmDCP5_GRPH_CONTROL - mmGRPH_CONTROL),
133 }
134 };
135
136 /* set register offset */
137 #define SR(reg_name)\
138 .reg_name = mm ## reg_name
139
140 /* set register offset with instance */
141 #define SRI(reg_name, block, id)\
142 .reg_name = mm ## block ## id ## _ ## reg_name
143
144
145 static const struct dce_disp_clk_registers disp_clk_regs = {
146 CLK_COMMON_REG_LIST_DCE_BASE()
147 };
148
149 static const struct dce_disp_clk_shift disp_clk_shift = {
150 CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT)
151 };
152
153 static const struct dce_disp_clk_mask disp_clk_mask = {
154 CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK)
155 };
156
157 static const struct dce_dmcu_registers dmcu_regs = {
158 DMCU_DCE110_COMMON_REG_LIST()
159 };
160
161 static const struct dce_dmcu_shift dmcu_shift = {
162 DMCU_MASK_SH_LIST_DCE110(__SHIFT)
163 };
164
165 static const struct dce_dmcu_mask dmcu_mask = {
166 DMCU_MASK_SH_LIST_DCE110(_MASK)
167 };
168
169 static const struct dce_abm_registers abm_regs = {
170 ABM_DCE110_COMMON_REG_LIST()
171 };
172
173 static const struct dce_abm_shift abm_shift = {
174 ABM_MASK_SH_LIST_DCE110(__SHIFT)
175 };
176
177 static const struct dce_abm_mask abm_mask = {
178 ABM_MASK_SH_LIST_DCE110(_MASK)
179 };
180
181 #define ipp_regs(id)\
182 [id] = {\
183 IPP_DCE110_REG_LIST_DCE_BASE(id)\
184 }
185
186 static const struct dce_ipp_registers ipp_regs[] = {
187 ipp_regs(0),
188 ipp_regs(1),
189 ipp_regs(2),
190 ipp_regs(3),
191 ipp_regs(4),
192 ipp_regs(5)
193 };
194
195 static const struct dce_ipp_shift ipp_shift = {
196 IPP_DCE100_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT)
197 };
198
199 static const struct dce_ipp_mask ipp_mask = {
200 IPP_DCE100_MASK_SH_LIST_DCE_COMMON_BASE(_MASK)
201 };
202
203 #define transform_regs(id)\
204 [id] = {\
205 XFM_COMMON_REG_LIST_DCE110(id)\
206 }
207
208 static const struct dce_transform_registers xfm_regs[] = {
209 transform_regs(0),
210 transform_regs(1),
211 transform_regs(2),
212 transform_regs(3),
213 transform_regs(4),
214 transform_regs(5)
215 };
216
217 static const struct dce_transform_shift xfm_shift = {
218 XFM_COMMON_MASK_SH_LIST_DCE110(__SHIFT)
219 };
220
221 static const struct dce_transform_mask xfm_mask = {
222 XFM_COMMON_MASK_SH_LIST_DCE110(_MASK)
223 };
224
225 #define aux_regs(id)\
226 [id] = {\
227 AUX_REG_LIST(id)\
228 }
229
230 static const struct dce110_link_enc_aux_registers link_enc_aux_regs[] = {
231 aux_regs(0),
232 aux_regs(1),
233 aux_regs(2),
234 aux_regs(3),
235 aux_regs(4),
236 aux_regs(5)
237 };
238
239 #define hpd_regs(id)\
240 [id] = {\
241 HPD_REG_LIST(id)\
242 }
243
244 static const struct dce110_link_enc_hpd_registers link_enc_hpd_regs[] = {
245 hpd_regs(0),
246 hpd_regs(1),
247 hpd_regs(2),
248 hpd_regs(3),
249 hpd_regs(4),
250 hpd_regs(5)
251 };
252
253 #define link_regs(id)\
254 [id] = {\
255 LE_DCE110_REG_LIST(id)\
256 }
257
258 static const struct dce110_link_enc_registers link_enc_regs[] = {
259 link_regs(0),
260 link_regs(1),
261 link_regs(2),
262 link_regs(3),
263 link_regs(4),
264 link_regs(5),
265 link_regs(6),
266 };
267
268 #define stream_enc_regs(id)\
269 [id] = {\
270 SE_COMMON_REG_LIST(id),\
271 .TMDS_CNTL = 0,\
272 }
273
274 static const struct dce110_stream_enc_registers stream_enc_regs[] = {
275 stream_enc_regs(0),
276 stream_enc_regs(1),
277 stream_enc_regs(2),
278 stream_enc_regs(3),
279 stream_enc_regs(4),
280 stream_enc_regs(5)
281 };
282
283 static const struct dce_stream_encoder_shift se_shift = {
284 SE_COMMON_MASK_SH_LIST_DCE112(__SHIFT)
285 };
286
287 static const struct dce_stream_encoder_mask se_mask = {
288 SE_COMMON_MASK_SH_LIST_DCE112(_MASK)
289 };
290
291 #define opp_regs(id)\
292 [id] = {\
293 OPP_DCE_112_REG_LIST(id),\
294 }
295
296 static const struct dce_opp_registers opp_regs[] = {
297 opp_regs(0),
298 opp_regs(1),
299 opp_regs(2),
300 opp_regs(3),
301 opp_regs(4),
302 opp_regs(5)
303 };
304
305 static const struct dce_opp_shift opp_shift = {
306 OPP_COMMON_MASK_SH_LIST_DCE_112(__SHIFT)
307 };
308
309 static const struct dce_opp_mask opp_mask = {
310 OPP_COMMON_MASK_SH_LIST_DCE_112(_MASK)
311 };
312
313 #define audio_regs(id)\
314 [id] = {\
315 AUD_COMMON_REG_LIST(id)\
316 }
317
318 static const struct dce_audio_registers audio_regs[] = {
319 audio_regs(0),
320 audio_regs(1),
321 audio_regs(2),
322 audio_regs(3),
323 audio_regs(4),
324 audio_regs(5)
325 };
326
327 static const struct dce_audio_shift audio_shift = {
328 AUD_COMMON_MASK_SH_LIST(__SHIFT)
329 };
330
331 static const struct dce_aduio_mask audio_mask = {
332 AUD_COMMON_MASK_SH_LIST(_MASK)
333 };
334
335 #define clk_src_regs(index, id)\
336 [index] = {\
337 CS_COMMON_REG_LIST_DCE_112(id),\
338 }
339
340 static const struct dce110_clk_src_regs clk_src_regs[] = {
341 clk_src_regs(0, A),
342 clk_src_regs(1, B),
343 clk_src_regs(2, C),
344 clk_src_regs(3, D),
345 clk_src_regs(4, E),
346 clk_src_regs(5, F)
347 };
348
349 static const struct dce110_clk_src_shift cs_shift = {
350 CS_COMMON_MASK_SH_LIST_DCE_112(__SHIFT)
351 };
352
353 static const struct dce110_clk_src_mask cs_mask = {
354 CS_COMMON_MASK_SH_LIST_DCE_112(_MASK)
355 };
356
357 static const struct bios_registers bios_regs = {
358 .BIOS_SCRATCH_6 = mmBIOS_SCRATCH_6
359 };
360
361 static const struct resource_caps polaris_10_resource_cap = {
362 .num_timing_generator = 6,
363 .num_audio = 6,
364 .num_stream_encoder = 6,
365 .num_pll = 8, /* why 8? 6 combo PHY PLL + 2 regular PLLs? */
366 };
367
368 static const struct resource_caps polaris_11_resource_cap = {
369 .num_timing_generator = 5,
370 .num_audio = 5,
371 .num_stream_encoder = 5,
372 .num_pll = 8, /* why 8? 6 combo PHY PLL + 2 regular PLLs? */
373 };
374
375 #define CTX ctx
376 #define REG(reg) mm ## reg
377
378 #ifndef mmCC_DC_HDMI_STRAPS
379 #define mmCC_DC_HDMI_STRAPS 0x4819
380 #define CC_DC_HDMI_STRAPS__HDMI_DISABLE_MASK 0x40
381 #define CC_DC_HDMI_STRAPS__HDMI_DISABLE__SHIFT 0x6
382 #define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER_MASK 0x700
383 #define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER__SHIFT 0x8
384 #endif
385
386 static void read_dce_straps(
387 struct dc_context *ctx,
388 struct resource_straps *straps)
389 {
390 REG_GET_2(CC_DC_HDMI_STRAPS,
391 HDMI_DISABLE, &straps->hdmi_disable,
392 AUDIO_STREAM_NUMBER, &straps->audio_stream_number);
393
394 REG_GET(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO, &straps->dc_pinstraps_audio);
395 }
396
397 static struct audio *create_audio(
398 struct dc_context *ctx, unsigned int inst)
399 {
400 return dce_audio_create(ctx, inst,
401 &audio_regs[inst], &audio_shift, &audio_mask);
402 }
403
404
405 static struct timing_generator *dce112_timing_generator_create(
406 struct dc_context *ctx,
407 uint32_t instance,
408 const struct dce110_timing_generator_offsets *offsets)
409 {
410 struct dce110_timing_generator *tg110 =
411 dm_alloc(sizeof(struct dce110_timing_generator));
412
413 if (!tg110)
414 return NULL;
415
416 if (dce110_timing_generator_construct(tg110, ctx, instance, offsets))
417 return &tg110->base;
418
419 BREAK_TO_DEBUGGER();
420 dm_free(tg110);
421 return NULL;
422 }
423
424 static struct stream_encoder *dce112_stream_encoder_create(
425 enum engine_id eng_id,
426 struct dc_context *ctx)
427 {
428 struct dce110_stream_encoder *enc110 =
429 dm_alloc(sizeof(struct dce110_stream_encoder));
430
431 if (!enc110)
432 return NULL;
433
434 if (dce110_stream_encoder_construct(
435 enc110, ctx, ctx->dc_bios, eng_id,
436 &stream_enc_regs[eng_id], &se_shift, &se_mask))
437 return &enc110->base;
438
439 BREAK_TO_DEBUGGER();
440 dm_free(enc110);
441 return NULL;
442 }
443
444 #define SRII(reg_name, block, id)\
445 .reg_name[id] = mm ## block ## id ## _ ## reg_name
446
447 static const struct dce_hwseq_registers hwseq_reg = {
448 HWSEQ_DCE112_REG_LIST()
449 };
450
451 static const struct dce_hwseq_shift hwseq_shift = {
452 HWSEQ_DCE112_MASK_SH_LIST(__SHIFT)
453 };
454
455 static const struct dce_hwseq_mask hwseq_mask = {
456 HWSEQ_DCE112_MASK_SH_LIST(_MASK)
457 };
458
459 static struct dce_hwseq *dce112_hwseq_create(
460 struct dc_context *ctx)
461 {
462 struct dce_hwseq *hws = dm_alloc(sizeof(struct dce_hwseq));
463
464 if (hws) {
465 hws->ctx = ctx;
466 hws->regs = &hwseq_reg;
467 hws->shifts = &hwseq_shift;
468 hws->masks = &hwseq_mask;
469 }
470 return hws;
471 }
472
473 static const struct resource_create_funcs res_create_funcs = {
474 .read_dce_straps = read_dce_straps,
475 .create_audio = create_audio,
476 .create_stream_encoder = dce112_stream_encoder_create,
477 .create_hwseq = dce112_hwseq_create,
478 };
479
480 #define mi_inst_regs(id) { MI_DCE11_2_REG_LIST(id) }
481 static const struct dce_mem_input_registers mi_regs[] = {
482 mi_inst_regs(0),
483 mi_inst_regs(1),
484 mi_inst_regs(2),
485 mi_inst_regs(3),
486 mi_inst_regs(4),
487 mi_inst_regs(5),
488 };
489
490 static const struct dce_mem_input_shift mi_shifts = {
491 MI_DCE11_2_MASK_SH_LIST(__SHIFT)
492 };
493
494 static const struct dce_mem_input_mask mi_masks = {
495 MI_DCE11_2_MASK_SH_LIST(_MASK)
496 };
497
498 static struct mem_input *dce112_mem_input_create(
499 struct dc_context *ctx,
500 uint32_t inst)
501 {
502 struct dce_mem_input *dce_mi = dm_alloc(sizeof(struct dce_mem_input));
503
504 if (!dce_mi) {
505 BREAK_TO_DEBUGGER();
506 return NULL;
507 }
508
509 dce112_mem_input_construct(dce_mi, ctx, inst, &mi_regs[inst], &mi_shifts, &mi_masks);
510 return &dce_mi->base;
511 }
512
513 static void dce112_transform_destroy(struct transform **xfm)
514 {
515 dm_free(TO_DCE_TRANSFORM(*xfm));
516 *xfm = NULL;
517 }
518
519 static struct transform *dce112_transform_create(
520 struct dc_context *ctx,
521 uint32_t inst)
522 {
523 struct dce_transform *transform =
524 dm_alloc(sizeof(struct dce_transform));
525
526 if (!transform)
527 return NULL;
528
529 if (dce_transform_construct(transform, ctx, inst,
530 &xfm_regs[inst], &xfm_shift, &xfm_mask)) {
531 transform->lb_memory_size = 0x1404; /*5124*/
532 return &transform->base;
533 }
534
535 BREAK_TO_DEBUGGER();
536 dm_free(transform);
537 return NULL;
538 }
539
540 static const struct encoder_feature_support link_enc_feature = {
541 .max_hdmi_deep_color = COLOR_DEPTH_121212,
542 .max_hdmi_pixel_clock = 600000,
543 .ycbcr420_supported = true,
544 .flags.bits.IS_HBR2_CAPABLE = true,
545 .flags.bits.IS_HBR3_CAPABLE = true,
546 .flags.bits.IS_TPS3_CAPABLE = true,
547 .flags.bits.IS_TPS4_CAPABLE = true,
548 .flags.bits.IS_YCBCR_CAPABLE = true
549 };
550
551 struct link_encoder *dce112_link_encoder_create(
552 const struct encoder_init_data *enc_init_data)
553 {
554 struct dce110_link_encoder *enc110 =
555 dm_alloc(sizeof(struct dce110_link_encoder));
556
557 if (!enc110)
558 return NULL;
559
560 if (dce110_link_encoder_construct(
561 enc110,
562 enc_init_data,
563 &link_enc_feature,
564 &link_enc_regs[enc_init_data->transmitter],
565 &link_enc_aux_regs[enc_init_data->channel - 1],
566 &link_enc_hpd_regs[enc_init_data->hpd_source])) {
567
568 return &enc110->base;
569 }
570
571 BREAK_TO_DEBUGGER();
572 dm_free(enc110);
573 return NULL;
574 }
575
576 static struct input_pixel_processor *dce112_ipp_create(
577 struct dc_context *ctx, uint32_t inst)
578 {
579 struct dce_ipp *ipp = dm_alloc(sizeof(struct dce_ipp));
580
581 if (!ipp) {
582 BREAK_TO_DEBUGGER();
583 return NULL;
584 }
585
586 dce_ipp_construct(ipp, ctx, inst,
587 &ipp_regs[inst], &ipp_shift, &ipp_mask);
588 return &ipp->base;
589 }
590
591 struct output_pixel_processor *dce112_opp_create(
592 struct dc_context *ctx,
593 uint32_t inst)
594 {
595 struct dce110_opp *opp =
596 dm_alloc(sizeof(struct dce110_opp));
597
598 if (!opp)
599 return NULL;
600
601 if (dce110_opp_construct(opp,
602 ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask))
603 return &opp->base;
604
605 BREAK_TO_DEBUGGER();
606 dm_free(opp);
607 return NULL;
608 }
609
610 struct clock_source *dce112_clock_source_create(
611 struct dc_context *ctx,
612 struct dc_bios *bios,
613 enum clock_source_id id,
614 const struct dce110_clk_src_regs *regs,
615 bool dp_clk_src)
616 {
617 struct dce110_clk_src *clk_src =
618 dm_alloc(sizeof(struct dce110_clk_src));
619
620 if (!clk_src)
621 return NULL;
622
623 if (dce110_clk_src_construct(clk_src, ctx, bios, id,
624 regs, &cs_shift, &cs_mask)) {
625 clk_src->base.dp_clk_src = dp_clk_src;
626 return &clk_src->base;
627 }
628
629 BREAK_TO_DEBUGGER();
630 return NULL;
631 }
632
633 void dce112_clock_source_destroy(struct clock_source **clk_src)
634 {
635 dm_free(TO_DCE110_CLK_SRC(*clk_src));
636 *clk_src = NULL;
637 }
638
639 static void destruct(struct dce110_resource_pool *pool)
640 {
641 unsigned int i;
642
643 for (i = 0; i < pool->base.pipe_count; i++) {
644 if (pool->base.opps[i] != NULL)
645 dce110_opp_destroy(&pool->base.opps[i]);
646
647 if (pool->base.transforms[i] != NULL)
648 dce112_transform_destroy(&pool->base.transforms[i]);
649
650 if (pool->base.ipps[i] != NULL)
651 dce_ipp_destroy(&pool->base.ipps[i]);
652
653 if (pool->base.mis[i] != NULL) {
654 dm_free(TO_DCE_MEM_INPUT(pool->base.mis[i]));
655 pool->base.mis[i] = NULL;
656 }
657
658 if (pool->base.timing_generators[i] != NULL) {
659 dm_free(DCE110TG_FROM_TG(pool->base.timing_generators[i]));
660 pool->base.timing_generators[i] = NULL;
661 }
662 }
663
664 for (i = 0; i < pool->base.stream_enc_count; i++) {
665 if (pool->base.stream_enc[i] != NULL)
666 dm_free(DCE110STRENC_FROM_STRENC(pool->base.stream_enc[i]));
667 }
668
669 for (i = 0; i < pool->base.clk_src_count; i++) {
670 if (pool->base.clock_sources[i] != NULL) {
671 dce112_clock_source_destroy(&pool->base.clock_sources[i]);
672 }
673 }
674
675 if (pool->base.dp_clock_source != NULL)
676 dce112_clock_source_destroy(&pool->base.dp_clock_source);
677
678 for (i = 0; i < pool->base.audio_count; i++) {
679 if (pool->base.audios[i] != NULL) {
680 dce_aud_destroy(&pool->base.audios[i]);
681 }
682 }
683
684 if (pool->base.abm != NULL)
685 dce_abm_destroy(&pool->base.abm);
686
687 if (pool->base.dmcu != NULL)
688 dce_dmcu_destroy(&pool->base.dmcu);
689
690 if (pool->base.display_clock != NULL)
691 dce_disp_clk_destroy(&pool->base.display_clock);
692
693 if (pool->base.irqs != NULL) {
694 dal_irq_service_destroy(&pool->base.irqs);
695 }
696 }
697
698 static struct clock_source *find_matching_pll(
699 struct resource_context *res_ctx,
700 const struct resource_pool *pool,
701 const struct dc_stream *const stream)
702 {
703 switch (stream->sink->link->link_enc->transmitter) {
704 case TRANSMITTER_UNIPHY_A:
705 return pool->clock_sources[DCE112_CLK_SRC_PLL0];
706 case TRANSMITTER_UNIPHY_B:
707 return pool->clock_sources[DCE112_CLK_SRC_PLL1];
708 case TRANSMITTER_UNIPHY_C:
709 return pool->clock_sources[DCE112_CLK_SRC_PLL2];
710 case TRANSMITTER_UNIPHY_D:
711 return pool->clock_sources[DCE112_CLK_SRC_PLL3];
712 case TRANSMITTER_UNIPHY_E:
713 return pool->clock_sources[DCE112_CLK_SRC_PLL4];
714 case TRANSMITTER_UNIPHY_F:
715 return pool->clock_sources[DCE112_CLK_SRC_PLL5];
716 default:
717 return NULL;
718 };
719
720 return 0;
721 }
722
723 static enum dc_status build_mapped_resource(
724 const struct core_dc *dc,
725 struct validate_context *context,
726 struct validate_context *old_context)
727 {
728 enum dc_status status = DC_OK;
729 uint8_t i, j;
730
731 for (i = 0; i < context->stream_count; i++) {
732 struct dc_stream *stream = context->streams[i];
733
734 if (old_context && resource_is_stream_unchanged(old_context, stream))
735 continue;
736
737 for (j = 0; j < MAX_PIPES; j++) {
738 struct pipe_ctx *pipe_ctx =
739 &context->res_ctx.pipe_ctx[j];
740
741 if (context->res_ctx.pipe_ctx[j].stream != stream)
742 continue;
743
744 status = dce110_resource_build_pipe_hw_param(pipe_ctx);
745
746 if (status != DC_OK)
747 return status;
748
749 resource_build_info_frame(pipe_ctx);
750
751 /* do not need to validate non root pipes */
752 break;
753 }
754 }
755
756 return DC_OK;
757 }
758
759 bool dce112_validate_bandwidth(
760 const struct core_dc *dc,
761 struct validate_context *context)
762 {
763 bool result = false;
764
765 dm_logger_write(
766 dc->ctx->logger, LOG_BANDWIDTH_CALCS,
767 "%s: start",
768 __func__);
769
770 if (bw_calcs(
771 dc->ctx,
772 &dc->bw_dceip,
773 &dc->bw_vbios,
774 context->res_ctx.pipe_ctx,
775 dc->res_pool->pipe_count,
776 &context->bw.dce))
777 result = true;
778
779 if (!result)
780 dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_VALIDATION,
781 "%s: Bandwidth validation failed!",
782 __func__);
783
784 if (memcmp(&dc->current_context->bw.dce,
785 &context->bw.dce, sizeof(context->bw.dce))) {
786 struct log_entry log_entry;
787 dm_logger_open(
788 dc->ctx->logger,
789 &log_entry,
790 LOG_BANDWIDTH_CALCS);
791 dm_logger_append(&log_entry, "%s: finish,\n"
792 "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n"
793 "stutMark_b: %d stutMark_a: %d\n",
794 __func__,
795 context->bw.dce.nbp_state_change_wm_ns[0].b_mark,
796 context->bw.dce.nbp_state_change_wm_ns[0].a_mark,
797 context->bw.dce.urgent_wm_ns[0].b_mark,
798 context->bw.dce.urgent_wm_ns[0].a_mark,
799 context->bw.dce.stutter_exit_wm_ns[0].b_mark,
800 context->bw.dce.stutter_exit_wm_ns[0].a_mark);
801 dm_logger_append(&log_entry,
802 "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n"
803 "stutMark_b: %d stutMark_a: %d\n",
804 context->bw.dce.nbp_state_change_wm_ns[1].b_mark,
805 context->bw.dce.nbp_state_change_wm_ns[1].a_mark,
806 context->bw.dce.urgent_wm_ns[1].b_mark,
807 context->bw.dce.urgent_wm_ns[1].a_mark,
808 context->bw.dce.stutter_exit_wm_ns[1].b_mark,
809 context->bw.dce.stutter_exit_wm_ns[1].a_mark);
810 dm_logger_append(&log_entry,
811 "nbpMark_b: %d nbpMark_a: %d urgentMark_b: %d urgentMark_a: %d\n"
812 "stutMark_b: %d stutMark_a: %d stutter_mode_enable: %d\n",
813 context->bw.dce.nbp_state_change_wm_ns[2].b_mark,
814 context->bw.dce.nbp_state_change_wm_ns[2].a_mark,
815 context->bw.dce.urgent_wm_ns[2].b_mark,
816 context->bw.dce.urgent_wm_ns[2].a_mark,
817 context->bw.dce.stutter_exit_wm_ns[2].b_mark,
818 context->bw.dce.stutter_exit_wm_ns[2].a_mark,
819 context->bw.dce.stutter_mode_enable);
820 dm_logger_append(&log_entry,
821 "cstate: %d pstate: %d nbpstate: %d sync: %d dispclk: %d\n"
822 "sclk: %d sclk_sleep: %d yclk: %d blackout_recovery_time_us: %d\n",
823 context->bw.dce.cpuc_state_change_enable,
824 context->bw.dce.cpup_state_change_enable,
825 context->bw.dce.nbp_state_change_enable,
826 context->bw.dce.all_displays_in_sync,
827 context->bw.dce.dispclk_khz,
828 context->bw.dce.sclk_khz,
829 context->bw.dce.sclk_deep_sleep_khz,
830 context->bw.dce.yclk_khz,
831 context->bw.dce.blackout_recovery_time_us);
832 dm_logger_close(&log_entry);
833 }
834 return result;
835 }
836
837 enum dc_status resource_map_phy_clock_resources(
838 const struct core_dc *dc,
839 struct validate_context *context,
840 struct validate_context *old_context)
841 {
842 uint8_t i, j;
843
844 /* acquire new resources */
845 for (i = 0; i < context->stream_count; i++) {
846 struct dc_stream *stream = context->streams[i];
847
848 if (old_context && resource_is_stream_unchanged(old_context, stream))
849 continue;
850
851 for (j = 0; j < MAX_PIPES; j++) {
852 struct pipe_ctx *pipe_ctx =
853 &context->res_ctx.pipe_ctx[j];
854
855 if (context->res_ctx.pipe_ctx[j].stream != stream)
856 continue;
857
858 if (dc_is_dp_signal(pipe_ctx->stream->signal)
859 || pipe_ctx->stream->signal == SIGNAL_TYPE_VIRTUAL)
860 pipe_ctx->clock_source =
861 dc->res_pool->dp_clock_source;
862 else
863 pipe_ctx->clock_source = find_matching_pll(
864 &context->res_ctx, dc->res_pool,
865 stream);
866
867 if (pipe_ctx->clock_source == NULL)
868 return DC_NO_CLOCK_SOURCE_RESOURCE;
869
870 resource_reference_clock_source(
871 &context->res_ctx,
872 dc->res_pool,
873 pipe_ctx->clock_source);
874
875 /* only one cs per stream regardless of mpo */
876 break;
877 }
878 }
879
880 return DC_OK;
881 }
882
883 static bool dce112_validate_surface_sets(
884 const struct dc_validation_set set[],
885 int set_count)
886 {
887 int i;
888
889 for (i = 0; i < set_count; i++) {
890 if (set[i].surface_count == 0)
891 continue;
892
893 if (set[i].surface_count > 1)
894 return false;
895
896 if (set[i].surfaces[0]->format
897 >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
898 return false;
899 }
900
901 return true;
902 }
903
904 enum dc_status dce112_validate_with_context(
905 const struct core_dc *dc,
906 const struct dc_validation_set set[],
907 int set_count,
908 struct validate_context *context,
909 struct validate_context *old_context)
910 {
911 struct dc_context *dc_ctx = dc->ctx;
912 enum dc_status result = DC_ERROR_UNEXPECTED;
913 int i;
914
915 if (!dce112_validate_surface_sets(set, set_count))
916 return DC_FAIL_SURFACE_VALIDATE;
917
918 for (i = 0; i < set_count; i++) {
919 context->streams[i] = set[i].stream;
920 dc_stream_retain(context->streams[i]);
921 context->stream_count++;
922 }
923
924 result = resource_map_pool_resources(dc, context, old_context);
925
926 if (result == DC_OK)
927 result = resource_map_phy_clock_resources(dc, context, old_context);
928
929 if (!resource_validate_attach_surfaces(set, set_count,
930 old_context, context, dc->res_pool)) {
931 DC_ERROR("Failed to attach surface to stream!\n");
932 return DC_FAIL_ATTACH_SURFACES;
933 }
934
935 if (result == DC_OK)
936 result = build_mapped_resource(dc, context, old_context);
937
938 if (result == DC_OK)
939 result = resource_build_scaling_params_for_context(dc, context);
940
941 if (result == DC_OK)
942 if (!dce112_validate_bandwidth(dc, context))
943 result = DC_FAIL_BANDWIDTH_VALIDATE;
944
945 return result;
946 }
947
948 enum dc_status dce112_validate_guaranteed(
949 const struct core_dc *dc,
950 struct dc_stream *stream,
951 struct validate_context *context)
952 {
953 enum dc_status result = DC_ERROR_UNEXPECTED;
954
955 context->streams[0] = stream;
956 dc_stream_retain(context->streams[0]);
957 context->stream_count++;
958
959 result = resource_map_pool_resources(dc, context, NULL);
960
961 if (result == DC_OK)
962 result = resource_map_phy_clock_resources(dc, context, NULL);
963
964 if (result == DC_OK)
965 result = build_mapped_resource(dc, context, NULL);
966
967 if (result == DC_OK) {
968 validate_guaranteed_copy_streams(
969 context, dc->public.caps.max_streams);
970 result = resource_build_scaling_params_for_context(dc, context);
971 }
972
973 if (result == DC_OK)
974 if (!dce112_validate_bandwidth(dc, context))
975 result = DC_FAIL_BANDWIDTH_VALIDATE;
976
977 return result;
978 }
979
980 static void dce112_destroy_resource_pool(struct resource_pool **pool)
981 {
982 struct dce110_resource_pool *dce110_pool = TO_DCE110_RES_POOL(*pool);
983
984 destruct(dce110_pool);
985 dm_free(dce110_pool);
986 *pool = NULL;
987 }
988
989 static const struct resource_funcs dce112_res_pool_funcs = {
990 .destroy = dce112_destroy_resource_pool,
991 .link_enc_create = dce112_link_encoder_create,
992 .validate_with_context = dce112_validate_with_context,
993 .validate_guaranteed = dce112_validate_guaranteed,
994 .validate_bandwidth = dce112_validate_bandwidth,
995 };
996
997 static void bw_calcs_data_update_from_pplib(struct core_dc *dc)
998 {
999 struct dm_pp_clock_levels_with_latency eng_clks = {0};
1000 struct dm_pp_clock_levels_with_latency mem_clks = {0};
1001 struct dm_pp_wm_sets_with_clock_ranges clk_ranges = {0};
1002 struct dm_pp_clock_levels clks = {0};
1003
1004 /*do system clock TODO PPLIB: after PPLIB implement,
1005 * then remove old way
1006 */
1007 if (!dm_pp_get_clock_levels_by_type_with_latency(
1008 dc->ctx,
1009 DM_PP_CLOCK_TYPE_ENGINE_CLK,
1010 &eng_clks)) {
1011
1012 /* This is only for temporary */
1013 dm_pp_get_clock_levels_by_type(
1014 dc->ctx,
1015 DM_PP_CLOCK_TYPE_ENGINE_CLK,
1016 &clks);
1017 /* convert all the clock fro kHz to fix point mHz */
1018 dc->bw_vbios.high_sclk = bw_frc_to_fixed(
1019 clks.clocks_in_khz[clks.num_levels-1], 1000);
1020 dc->bw_vbios.mid1_sclk = bw_frc_to_fixed(
1021 clks.clocks_in_khz[clks.num_levels/8], 1000);
1022 dc->bw_vbios.mid2_sclk = bw_frc_to_fixed(
1023 clks.clocks_in_khz[clks.num_levels*2/8], 1000);
1024 dc->bw_vbios.mid3_sclk = bw_frc_to_fixed(
1025 clks.clocks_in_khz[clks.num_levels*3/8], 1000);
1026 dc->bw_vbios.mid4_sclk = bw_frc_to_fixed(
1027 clks.clocks_in_khz[clks.num_levels*4/8], 1000);
1028 dc->bw_vbios.mid5_sclk = bw_frc_to_fixed(
1029 clks.clocks_in_khz[clks.num_levels*5/8], 1000);
1030 dc->bw_vbios.mid6_sclk = bw_frc_to_fixed(
1031 clks.clocks_in_khz[clks.num_levels*6/8], 1000);
1032 dc->bw_vbios.low_sclk = bw_frc_to_fixed(
1033 clks.clocks_in_khz[0], 1000);
1034
1035 /*do memory clock*/
1036 dm_pp_get_clock_levels_by_type(
1037 dc->ctx,
1038 DM_PP_CLOCK_TYPE_MEMORY_CLK,
1039 &clks);
1040
1041 dc->bw_vbios.low_yclk = bw_frc_to_fixed(
1042 clks.clocks_in_khz[0] * MEMORY_TYPE_MULTIPLIER, 1000);
1043 dc->bw_vbios.mid_yclk = bw_frc_to_fixed(
1044 clks.clocks_in_khz[clks.num_levels>>1] * MEMORY_TYPE_MULTIPLIER,
1045 1000);
1046 dc->bw_vbios.high_yclk = bw_frc_to_fixed(
1047 clks.clocks_in_khz[clks.num_levels-1] * MEMORY_TYPE_MULTIPLIER,
1048 1000);
1049
1050 return;
1051 }
1052
1053 /* convert all the clock fro kHz to fix point mHz TODO: wloop data */
1054 dc->bw_vbios.high_sclk = bw_frc_to_fixed(
1055 eng_clks.data[eng_clks.num_levels-1].clocks_in_khz, 1000);
1056 dc->bw_vbios.mid1_sclk = bw_frc_to_fixed(
1057 eng_clks.data[eng_clks.num_levels/8].clocks_in_khz, 1000);
1058 dc->bw_vbios.mid2_sclk = bw_frc_to_fixed(
1059 eng_clks.data[eng_clks.num_levels*2/8].clocks_in_khz, 1000);
1060 dc->bw_vbios.mid3_sclk = bw_frc_to_fixed(
1061 eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz, 1000);
1062 dc->bw_vbios.mid4_sclk = bw_frc_to_fixed(
1063 eng_clks.data[eng_clks.num_levels*4/8].clocks_in_khz, 1000);
1064 dc->bw_vbios.mid5_sclk = bw_frc_to_fixed(
1065 eng_clks.data[eng_clks.num_levels*5/8].clocks_in_khz, 1000);
1066 dc->bw_vbios.mid6_sclk = bw_frc_to_fixed(
1067 eng_clks.data[eng_clks.num_levels*6/8].clocks_in_khz, 1000);
1068 dc->bw_vbios.low_sclk = bw_frc_to_fixed(
1069 eng_clks.data[0].clocks_in_khz, 1000);
1070
1071 /*do memory clock*/
1072 dm_pp_get_clock_levels_by_type_with_latency(
1073 dc->ctx,
1074 DM_PP_CLOCK_TYPE_MEMORY_CLK,
1075 &mem_clks);
1076
1077 /* we don't need to call PPLIB for validation clock since they
1078 * also give us the highest sclk and highest mclk (UMA clock).
1079 * ALSO always convert UMA clock (from PPLIB) to YCLK (HW formula):
1080 * YCLK = UMACLK*m_memoryTypeMultiplier
1081 */
1082 dc->bw_vbios.low_yclk = bw_frc_to_fixed(
1083 mem_clks.data[0].clocks_in_khz * MEMORY_TYPE_MULTIPLIER, 1000);
1084 dc->bw_vbios.mid_yclk = bw_frc_to_fixed(
1085 mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz * MEMORY_TYPE_MULTIPLIER,
1086 1000);
1087 dc->bw_vbios.high_yclk = bw_frc_to_fixed(
1088 mem_clks.data[mem_clks.num_levels-1].clocks_in_khz * MEMORY_TYPE_MULTIPLIER,
1089 1000);
1090
1091 /* Now notify PPLib/SMU about which Watermarks sets they should select
1092 * depending on DPM state they are in. And update BW MGR GFX Engine and
1093 * Memory clock member variables for Watermarks calculations for each
1094 * Watermark Set
1095 */
1096 clk_ranges.num_wm_sets = 4;
1097 clk_ranges.wm_clk_ranges[0].wm_set_id = WM_SET_A;
1098 clk_ranges.wm_clk_ranges[0].wm_min_eng_clk_in_khz =
1099 eng_clks.data[0].clocks_in_khz;
1100 clk_ranges.wm_clk_ranges[0].wm_max_eng_clk_in_khz =
1101 eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz - 1;
1102 clk_ranges.wm_clk_ranges[0].wm_min_memg_clk_in_khz =
1103 mem_clks.data[0].clocks_in_khz;
1104 clk_ranges.wm_clk_ranges[0].wm_max_mem_clk_in_khz =
1105 mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz - 1;
1106
1107 clk_ranges.wm_clk_ranges[1].wm_set_id = WM_SET_B;
1108 clk_ranges.wm_clk_ranges[1].wm_min_eng_clk_in_khz =
1109 eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz;
1110 /* 5 GHz instead of data[7].clockInKHz to cover Overdrive */
1111 clk_ranges.wm_clk_ranges[1].wm_max_eng_clk_in_khz = 5000000;
1112 clk_ranges.wm_clk_ranges[1].wm_min_memg_clk_in_khz =
1113 mem_clks.data[0].clocks_in_khz;
1114 clk_ranges.wm_clk_ranges[1].wm_max_mem_clk_in_khz =
1115 mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz - 1;
1116
1117 clk_ranges.wm_clk_ranges[2].wm_set_id = WM_SET_C;
1118 clk_ranges.wm_clk_ranges[2].wm_min_eng_clk_in_khz =
1119 eng_clks.data[0].clocks_in_khz;
1120 clk_ranges.wm_clk_ranges[2].wm_max_eng_clk_in_khz =
1121 eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz - 1;
1122 clk_ranges.wm_clk_ranges[2].wm_min_memg_clk_in_khz =
1123 mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz;
1124 /* 5 GHz instead of data[2].clockInKHz to cover Overdrive */
1125 clk_ranges.wm_clk_ranges[2].wm_max_mem_clk_in_khz = 5000000;
1126
1127 clk_ranges.wm_clk_ranges[3].wm_set_id = WM_SET_D;
1128 clk_ranges.wm_clk_ranges[3].wm_min_eng_clk_in_khz =
1129 eng_clks.data[eng_clks.num_levels*3/8].clocks_in_khz;
1130 /* 5 GHz instead of data[7].clockInKHz to cover Overdrive */
1131 clk_ranges.wm_clk_ranges[3].wm_max_eng_clk_in_khz = 5000000;
1132 clk_ranges.wm_clk_ranges[3].wm_min_memg_clk_in_khz =
1133 mem_clks.data[mem_clks.num_levels>>1].clocks_in_khz;
1134 /* 5 GHz instead of data[2].clockInKHz to cover Overdrive */
1135 clk_ranges.wm_clk_ranges[3].wm_max_mem_clk_in_khz = 5000000;
1136
1137 /* Notify PP Lib/SMU which Watermarks to use for which clock ranges */
1138 dm_pp_notify_wm_clock_changes(dc->ctx, &clk_ranges);
1139 }
1140
1141 const struct resource_caps *dce112_resource_cap(
1142 struct hw_asic_id *asic_id)
1143 {
1144 if (ASIC_REV_IS_POLARIS11_M(asic_id->hw_internal_rev) ||
1145 ASIC_REV_IS_POLARIS12_V(asic_id->hw_internal_rev))
1146 return &polaris_11_resource_cap;
1147 else
1148 return &polaris_10_resource_cap;
1149 }
1150
1151 static bool construct(
1152 uint8_t num_virtual_links,
1153 struct core_dc *dc,
1154 struct dce110_resource_pool *pool)
1155 {
1156 unsigned int i;
1157 struct dc_context *ctx = dc->ctx;
1158 struct dm_pp_static_clock_info static_clk_info = {0};
1159
1160 ctx->dc_bios->regs = &bios_regs;
1161
1162 pool->base.res_cap = dce112_resource_cap(&ctx->asic_id);
1163 pool->base.funcs = &dce112_res_pool_funcs;
1164
1165 /*************************************************
1166 * Resource + asic cap harcoding *
1167 *************************************************/
1168 pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
1169 pool->base.pipe_count = pool->base.res_cap->num_timing_generator;
1170 dc->public.caps.max_downscale_ratio = 200;
1171 dc->public.caps.i2c_speed_in_khz = 100;
1172 dc->public.caps.max_cursor_size = 128;
1173
1174 /*************************************************
1175 * Create resources *
1176 *************************************************/
1177
1178 pool->base.clock_sources[DCE112_CLK_SRC_PLL0] =
1179 dce112_clock_source_create(
1180 ctx, ctx->dc_bios,
1181 CLOCK_SOURCE_COMBO_PHY_PLL0,
1182 &clk_src_regs[0], false);
1183 pool->base.clock_sources[DCE112_CLK_SRC_PLL1] =
1184 dce112_clock_source_create(
1185 ctx, ctx->dc_bios,
1186 CLOCK_SOURCE_COMBO_PHY_PLL1,
1187 &clk_src_regs[1], false);
1188 pool->base.clock_sources[DCE112_CLK_SRC_PLL2] =
1189 dce112_clock_source_create(
1190 ctx, ctx->dc_bios,
1191 CLOCK_SOURCE_COMBO_PHY_PLL2,
1192 &clk_src_regs[2], false);
1193 pool->base.clock_sources[DCE112_CLK_SRC_PLL3] =
1194 dce112_clock_source_create(
1195 ctx, ctx->dc_bios,
1196 CLOCK_SOURCE_COMBO_PHY_PLL3,
1197 &clk_src_regs[3], false);
1198 pool->base.clock_sources[DCE112_CLK_SRC_PLL4] =
1199 dce112_clock_source_create(
1200 ctx, ctx->dc_bios,
1201 CLOCK_SOURCE_COMBO_PHY_PLL4,
1202 &clk_src_regs[4], false);
1203 pool->base.clock_sources[DCE112_CLK_SRC_PLL5] =
1204 dce112_clock_source_create(
1205 ctx, ctx->dc_bios,
1206 CLOCK_SOURCE_COMBO_PHY_PLL5,
1207 &clk_src_regs[5], false);
1208 pool->base.clk_src_count = DCE112_CLK_SRC_TOTAL;
1209
1210 pool->base.dp_clock_source = dce112_clock_source_create(
1211 ctx, ctx->dc_bios,
1212 CLOCK_SOURCE_ID_DP_DTO, &clk_src_regs[0], true);
1213
1214
1215 for (i = 0; i < pool->base.clk_src_count; i++) {
1216 if (pool->base.clock_sources[i] == NULL) {
1217 dm_error("DC: failed to create clock sources!\n");
1218 BREAK_TO_DEBUGGER();
1219 goto res_create_fail;
1220 }
1221 }
1222
1223 pool->base.display_clock = dce112_disp_clk_create(ctx,
1224 &disp_clk_regs,
1225 &disp_clk_shift,
1226 &disp_clk_mask);
1227 if (pool->base.display_clock == NULL) {
1228 dm_error("DC: failed to create display clock!\n");
1229 BREAK_TO_DEBUGGER();
1230 goto res_create_fail;
1231 }
1232
1233 pool->base.dmcu = dce_dmcu_create(ctx,
1234 &dmcu_regs,
1235 &dmcu_shift,
1236 &dmcu_mask);
1237 if (pool->base.dmcu == NULL) {
1238 dm_error("DC: failed to create dmcu!\n");
1239 BREAK_TO_DEBUGGER();
1240 goto res_create_fail;
1241 }
1242
1243 pool->base.abm = dce_abm_create(ctx,
1244 &abm_regs,
1245 &abm_shift,
1246 &abm_mask);
1247 if (pool->base.abm == NULL) {
1248 dm_error("DC: failed to create abm!\n");
1249 BREAK_TO_DEBUGGER();
1250 goto res_create_fail;
1251 }
1252
1253 /* get static clock information for PPLIB or firmware, save
1254 * max_clock_state
1255 */
1256 if (dm_pp_get_static_clocks(ctx, &static_clk_info))
1257 pool->base.display_clock->max_clks_state =
1258 static_clk_info.max_clocks_state;
1259
1260 {
1261 struct irq_service_init_data init_data;
1262 init_data.ctx = dc->ctx;
1263 pool->base.irqs = dal_irq_service_dce110_create(&init_data);
1264 if (!pool->base.irqs)
1265 goto res_create_fail;
1266 }
1267
1268 for (i = 0; i < pool->base.pipe_count; i++) {
1269 pool->base.timing_generators[i] =
1270 dce112_timing_generator_create(
1271 ctx,
1272 i,
1273 &dce112_tg_offsets[i]);
1274 if (pool->base.timing_generators[i] == NULL) {
1275 BREAK_TO_DEBUGGER();
1276 dm_error("DC: failed to create tg!\n");
1277 goto res_create_fail;
1278 }
1279
1280 pool->base.mis[i] = dce112_mem_input_create(ctx, i);
1281 if (pool->base.mis[i] == NULL) {
1282 BREAK_TO_DEBUGGER();
1283 dm_error(
1284 "DC: failed to create memory input!\n");
1285 goto res_create_fail;
1286 }
1287
1288 pool->base.ipps[i] = dce112_ipp_create(ctx, i);
1289 if (pool->base.ipps[i] == NULL) {
1290 BREAK_TO_DEBUGGER();
1291 dm_error(
1292 "DC:failed to create input pixel processor!\n");
1293 goto res_create_fail;
1294 }
1295
1296 pool->base.transforms[i] = dce112_transform_create(ctx, i);
1297 if (pool->base.transforms[i] == NULL) {
1298 BREAK_TO_DEBUGGER();
1299 dm_error(
1300 "DC: failed to create transform!\n");
1301 goto res_create_fail;
1302 }
1303
1304 pool->base.opps[i] = dce112_opp_create(
1305 ctx,
1306 i);
1307 if (pool->base.opps[i] == NULL) {
1308 BREAK_TO_DEBUGGER();
1309 dm_error(
1310 "DC:failed to create output pixel processor!\n");
1311 goto res_create_fail;
1312 }
1313 }
1314
1315 if (!resource_construct(num_virtual_links, dc, &pool->base,
1316 &res_create_funcs))
1317 goto res_create_fail;
1318
1319 dc->public.caps.max_surfaces = pool->base.pipe_count;
1320
1321 /* Create hardware sequencer */
1322 if (!dce112_hw_sequencer_construct(dc))
1323 goto res_create_fail;
1324
1325 bw_calcs_init(&dc->bw_dceip, &dc->bw_vbios, dc->ctx->asic_id);
1326
1327 bw_calcs_data_update_from_pplib(dc);
1328
1329 return true;
1330
1331 res_create_fail:
1332 destruct(pool);
1333 return false;
1334 }
1335
1336 struct resource_pool *dce112_create_resource_pool(
1337 uint8_t num_virtual_links,
1338 struct core_dc *dc)
1339 {
1340 struct dce110_resource_pool *pool =
1341 dm_alloc(sizeof(struct dce110_resource_pool));
1342
1343 if (!pool)
1344 return NULL;
1345
1346 if (construct(num_virtual_links, dc, pool))
1347 return &pool->base;
1348
1349 BREAK_TO_DEBUGGER();
1350 return NULL;
1351 }