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