2 * Copyright 2012-15 Advanced Micro Devices, Inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
26 #include "dce/dce_8_0_d.h"
27 #include "dce/dce_8_0_sh_mask.h"
29 #include "dm_services.h"
31 #include "link_encoder.h"
32 #include "stream_encoder.h"
35 #include "include/irq_service_interface.h"
36 #include "irq/dce80/irq_service_dce80.h"
37 #include "dce110/dce110_timing_generator.h"
38 #include "dce110/dce110_mem_input.h"
39 #include "dce110/dce110_resource.h"
40 #include "dce80/dce80_timing_generator.h"
41 #include "dce/dce_link_encoder.h"
42 #include "dce/dce_stream_encoder.h"
43 #include "dce80/dce80_mem_input.h"
44 #include "dce80/dce80_ipp.h"
45 #include "dce/dce_transform.h"
46 #include "dce80/dce80_opp.h"
47 #include "dce110/dce110_ipp.h"
48 #include "dce/dce_clock_source.h"
49 #include "dce/dce_audio.h"
50 #include "dce/dce_hwseq.h"
51 #include "dce80/dce80_hw_sequencer.h"
53 #include "reg_helper.h"
55 /* TODO remove this include */
57 #ifndef mmMC_HUB_RDREQ_DMIF_LIMIT
58 #include "gmc/gmc_7_1_d.h"
59 #include "gmc/gmc_7_1_sh_mask.h"
62 #ifndef mmDP_DPHY_INTERNAL_CTRL
63 #define mmDP_DPHY_INTERNAL_CTRL 0x1CDE
64 #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x1CDE
65 #define mmDP1_DP_DPHY_INTERNAL_CTRL 0x1FDE
66 #define mmDP2_DP_DPHY_INTERNAL_CTRL 0x42DE
67 #define mmDP3_DP_DPHY_INTERNAL_CTRL 0x45DE
68 #define mmDP4_DP_DPHY_INTERNAL_CTRL 0x48DE
69 #define mmDP5_DP_DPHY_INTERNAL_CTRL 0x4BDE
70 #define mmDP6_DP_DPHY_INTERNAL_CTRL 0x4EDE
74 #ifndef mmBIOS_SCRATCH_2
75 #define mmBIOS_SCRATCH_2 0x05CB
76 #define mmBIOS_SCRATCH_6 0x05CF
79 #ifndef mmDP_DPHY_FAST_TRAINING
80 #define mmDP_DPHY_FAST_TRAINING 0x1CCE
81 #define mmDP0_DP_DPHY_FAST_TRAINING 0x1CCE
82 #define mmDP1_DP_DPHY_FAST_TRAINING 0x1FCE
83 #define mmDP2_DP_DPHY_FAST_TRAINING 0x42CE
84 #define mmDP3_DP_DPHY_FAST_TRAINING 0x45CE
85 #define mmDP4_DP_DPHY_FAST_TRAINING 0x48CE
86 #define mmDP5_DP_DPHY_FAST_TRAINING 0x4BCE
87 #define mmDP6_DP_DPHY_FAST_TRAINING 0x4ECE
91 #ifndef mmHPD_DC_HPD_CONTROL
92 #define mmHPD_DC_HPD_CONTROL 0x189A
93 #define mmHPD0_DC_HPD_CONTROL 0x189A
94 #define mmHPD1_DC_HPD_CONTROL 0x18A2
95 #define mmHPD2_DC_HPD_CONTROL 0x18AA
96 #define mmHPD3_DC_HPD_CONTROL 0x18B2
97 #define mmHPD4_DC_HPD_CONTROL 0x18BA
98 #define mmHPD5_DC_HPD_CONTROL 0x18C2
101 #define DCE11_DIG_FE_CNTL 0x4a00
102 #define DCE11_DIG_BE_CNTL 0x4a47
103 #define DCE11_DP_SEC 0x4ac3
105 static const struct dce110_timing_generator_offsets dce80_tg_offsets
[] = {
107 .crtc
= (mmCRTC0_CRTC_CONTROL
- mmCRTC_CONTROL
),
108 .dcp
= (mmGRPH_CONTROL
- mmGRPH_CONTROL
),
109 .dmif
= (mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL
110 - mmDPG_WATERMARK_MASK_CONTROL
),
113 .crtc
= (mmCRTC1_CRTC_CONTROL
- mmCRTC_CONTROL
),
114 .dcp
= (mmDCP1_GRPH_CONTROL
- mmGRPH_CONTROL
),
115 .dmif
= (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL
116 - mmDPG_WATERMARK_MASK_CONTROL
),
119 .crtc
= (mmCRTC2_CRTC_CONTROL
- mmCRTC_CONTROL
),
120 .dcp
= (mmDCP2_GRPH_CONTROL
- mmGRPH_CONTROL
),
121 .dmif
= (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL
122 - mmDPG_WATERMARK_MASK_CONTROL
),
125 .crtc
= (mmCRTC3_CRTC_CONTROL
- mmCRTC_CONTROL
),
126 .dcp
= (mmDCP3_GRPH_CONTROL
- mmGRPH_CONTROL
),
127 .dmif
= (mmDMIF_PG3_DPG_WATERMARK_MASK_CONTROL
128 - mmDPG_WATERMARK_MASK_CONTROL
),
131 .crtc
= (mmCRTC4_CRTC_CONTROL
- mmCRTC_CONTROL
),
132 .dcp
= (mmDCP4_GRPH_CONTROL
- mmGRPH_CONTROL
),
133 .dmif
= (mmDMIF_PG4_DPG_WATERMARK_MASK_CONTROL
134 - mmDPG_WATERMARK_MASK_CONTROL
),
137 .crtc
= (mmCRTC5_CRTC_CONTROL
- mmCRTC_CONTROL
),
138 .dcp
= (mmDCP5_GRPH_CONTROL
- mmGRPH_CONTROL
),
139 .dmif
= (mmDMIF_PG5_DPG_WATERMARK_MASK_CONTROL
140 - mmDPG_WATERMARK_MASK_CONTROL
),
144 static const struct dce110_mem_input_reg_offsets dce80_mi_reg_offsets
[] = {
146 .dcp
= (mmGRPH_CONTROL
- mmGRPH_CONTROL
),
147 .dmif
= (mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL
148 - mmDPG_WATERMARK_MASK_CONTROL
),
149 .pipe
= (mmPIPE0_DMIF_BUFFER_CONTROL
150 - mmPIPE0_DMIF_BUFFER_CONTROL
),
153 .dcp
= (mmDCP1_GRPH_CONTROL
- mmGRPH_CONTROL
),
154 .dmif
= (mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL
155 - mmDPG_WATERMARK_MASK_CONTROL
),
156 .pipe
= (mmPIPE1_DMIF_BUFFER_CONTROL
157 - mmPIPE0_DMIF_BUFFER_CONTROL
),
160 .dcp
= (mmDCP2_GRPH_CONTROL
- mmGRPH_CONTROL
),
161 .dmif
= (mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL
162 - mmDPG_WATERMARK_MASK_CONTROL
),
163 .pipe
= (mmPIPE2_DMIF_BUFFER_CONTROL
164 - mmPIPE0_DMIF_BUFFER_CONTROL
),
167 .dcp
= (mmDCP3_GRPH_CONTROL
- mmGRPH_CONTROL
),
168 .dmif
= (mmDMIF_PG3_DPG_WATERMARK_MASK_CONTROL
169 - mmDPG_WATERMARK_MASK_CONTROL
),
170 .pipe
= (mmPIPE3_DMIF_BUFFER_CONTROL
171 - mmPIPE0_DMIF_BUFFER_CONTROL
),
174 .dcp
= (mmDCP4_GRPH_CONTROL
- mmGRPH_CONTROL
),
175 .dmif
= (mmDMIF_PG4_DPG_WATERMARK_MASK_CONTROL
176 - mmDPG_WATERMARK_MASK_CONTROL
),
177 .pipe
= (mmPIPE4_DMIF_BUFFER_CONTROL
178 - mmPIPE0_DMIF_BUFFER_CONTROL
),
181 .dcp
= (mmDCP5_GRPH_CONTROL
- mmGRPH_CONTROL
),
182 .dmif
= (mmDMIF_PG5_DPG_WATERMARK_MASK_CONTROL
183 - mmDPG_WATERMARK_MASK_CONTROL
),
184 .pipe
= (mmPIPE5_DMIF_BUFFER_CONTROL
185 - mmPIPE0_DMIF_BUFFER_CONTROL
),
189 static const struct dce110_ipp_reg_offsets ipp_reg_offsets
[] = {
191 .dcp_offset
= (mmDCP0_CUR_CONTROL
- mmDCP0_CUR_CONTROL
),
194 .dcp_offset
= (mmDCP1_CUR_CONTROL
- mmDCP0_CUR_CONTROL
),
197 .dcp_offset
= (mmDCP2_CUR_CONTROL
- mmDCP0_CUR_CONTROL
),
200 .dcp_offset
= (mmDCP3_CUR_CONTROL
- mmDCP0_CUR_CONTROL
),
203 .dcp_offset
= (mmDCP4_CUR_CONTROL
- mmDCP0_CUR_CONTROL
),
206 .dcp_offset
= (mmDCP5_CUR_CONTROL
- mmDCP0_CUR_CONTROL
),
210 /* set register offset */
211 #define SR(reg_name)\
212 .reg_name = mm ## reg_name
214 /* set register offset with instance */
215 #define SRI(reg_name, block, id)\
216 .reg_name = mm ## block ## id ## _ ## reg_name
218 #define transform_regs(id)\
220 XFM_COMMON_REG_LIST_DCE_BASE(id)\
223 static const struct dce_transform_registers xfm_regs
[] = {
232 static const struct dce_transform_shift xfm_shift
= {
233 XFM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT
)
236 static const struct dce_transform_mask xfm_mask
= {
237 XFM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK
)
240 #define aux_regs(id)\
245 static const struct dce110_link_enc_aux_registers link_enc_aux_regs
[] = {
254 #define hpd_regs(id)\
259 static const struct dce110_link_enc_hpd_registers link_enc_hpd_regs
[] = {
268 #define link_regs(id)\
270 LE_DCE80_REG_LIST(id)\
273 static const struct dce110_link_enc_registers link_enc_regs
[] = {
283 #define stream_enc_regs(id)\
285 SE_COMMON_REG_LIST_DCE_BASE(id),\
289 static const struct dce110_stream_enc_registers stream_enc_regs
[] = {
298 static const struct dce_stream_encoder_shift se_shift
= {
299 SE_COMMON_MASK_SH_LIST_DCE80_100(__SHIFT
)
302 static const struct dce_stream_encoder_mask se_mask
= {
303 SE_COMMON_MASK_SH_LIST_DCE80_100(_MASK
)
306 #define audio_regs(id)\
308 AUD_COMMON_REG_LIST(id)\
311 static const struct dce_audio_registers audio_regs
[] = {
321 static const struct dce_audio_shift audio_shift
= {
322 AUD_COMMON_MASK_SH_LIST(__SHIFT
)
325 static const struct dce_aduio_mask audio_mask
= {
326 AUD_COMMON_MASK_SH_LIST(_MASK
)
329 #define clk_src_regs(id)\
331 CS_COMMON_REG_LIST_DCE_80(id),\
335 static const struct dce110_clk_src_regs clk_src_regs
[] = {
341 static const struct dce110_clk_src_shift cs_shift
= {
342 CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT
)
345 static const struct dce110_clk_src_mask cs_mask
= {
346 CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK
)
349 static const struct bios_registers bios_regs
= {
350 .BIOS_SCRATCH_6
= mmBIOS_SCRATCH_6
353 static const struct resource_caps res_cap
= {
354 .num_timing_generator
= 6,
356 .num_stream_encoder
= 6,
361 #define REG(reg) mm ## reg
363 #ifndef mmCC_DC_HDMI_STRAPS
364 #define mmCC_DC_HDMI_STRAPS 0x1918
365 #define CC_DC_HDMI_STRAPS__HDMI_DISABLE_MASK 0x40
366 #define CC_DC_HDMI_STRAPS__HDMI_DISABLE__SHIFT 0x6
367 #define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER_MASK 0x700
368 #define CC_DC_HDMI_STRAPS__AUDIO_STREAM_NUMBER__SHIFT 0x8
371 static void read_dce_straps(
372 struct dc_context
*ctx
,
373 struct resource_straps
*straps
)
375 REG_GET_2(CC_DC_HDMI_STRAPS
,
376 HDMI_DISABLE
, &straps
->hdmi_disable
,
377 AUDIO_STREAM_NUMBER
, &straps
->audio_stream_number
);
379 REG_GET(DC_PINSTRAPS
, DC_PINSTRAPS_AUDIO
, &straps
->dc_pinstraps_audio
);
382 static struct audio
*create_audio(
383 struct dc_context
*ctx
, unsigned int inst
)
385 return dce_audio_create(ctx
, inst
,
386 &audio_regs
[inst
], &audio_shift
, &audio_mask
);
389 static struct timing_generator
*dce80_timing_generator_create(
390 struct dc_context
*ctx
,
392 const struct dce110_timing_generator_offsets
*offsets
)
394 struct dce110_timing_generator
*tg110
=
395 dm_alloc(sizeof(struct dce110_timing_generator
));
400 if (dce80_timing_generator_construct(tg110
, ctx
, instance
, offsets
))
408 static struct stream_encoder
*dce80_stream_encoder_create(
409 enum engine_id eng_id
,
410 struct dc_context
*ctx
)
412 struct dce110_stream_encoder
*enc110
=
413 dm_alloc(sizeof(struct dce110_stream_encoder
));
418 if (dce110_stream_encoder_construct(
419 enc110
, ctx
, ctx
->dc_bios
, eng_id
,
420 &stream_enc_regs
[eng_id
], &se_shift
, &se_mask
))
421 return &enc110
->base
;
428 #define SRII(reg_name, block, id)\
429 .reg_name[id] = mm ## block ## id ## _ ## reg_name
431 static const struct dce_hwseq_registers hwseq_reg
= {
432 HWSEQ_DCE8_REG_LIST()
435 static const struct dce_hwseq_shift hwseq_shift
= {
436 HWSEQ_DCE8_MASK_SH_LIST(__SHIFT
)
439 static const struct dce_hwseq_mask hwseq_mask
= {
440 HWSEQ_DCE8_MASK_SH_LIST(_MASK
)
443 static struct dce_hwseq
*dce80_hwseq_create(
444 struct dc_context
*ctx
)
446 struct dce_hwseq
*hws
= dm_alloc(sizeof(struct dce_hwseq
));
450 hws
->regs
= &hwseq_reg
;
451 hws
->shifts
= &hwseq_shift
;
452 hws
->masks
= &hwseq_mask
;
457 static const struct resource_create_funcs res_create_funcs
= {
458 .read_dce_straps
= read_dce_straps
,
459 .create_audio
= create_audio
,
460 .create_stream_encoder
= dce80_stream_encoder_create
,
461 .create_hwseq
= dce80_hwseq_create
,
464 #define mi_inst_regs(id) { \
465 MI_DCE8_REG_LIST(id), \
466 .MC_HUB_RDREQ_DMIF_LIMIT = mmMC_HUB_RDREQ_DMIF_LIMIT \
468 static const struct dce_mem_input_registers mi_regs
[] = {
477 static const struct dce_mem_input_shift mi_shifts
= {
478 MI_DCE8_MASK_SH_LIST(__SHIFT
),
479 .ENABLE
= MC_HUB_RDREQ_DMIF_LIMIT__ENABLE__SHIFT
482 static const struct dce_mem_input_mask mi_masks
= {
483 MI_DCE8_MASK_SH_LIST(_MASK
),
484 .ENABLE
= MC_HUB_RDREQ_DMIF_LIMIT__ENABLE_MASK
487 static struct mem_input
*dce80_mem_input_create(
488 struct dc_context
*ctx
,
490 const struct dce110_mem_input_reg_offsets
*offsets
)
492 struct dce110_mem_input
*mem_input80
=
493 dm_alloc(sizeof(struct dce110_mem_input
));
498 if (dce80_mem_input_construct(mem_input80
, ctx
, inst
, offsets
)) {
499 struct mem_input
*mi
= &mem_input80
->base
;
501 mi
->regs
= &mi_regs
[inst
];
502 mi
->shifts
= &mi_shifts
;
503 mi
->masks
= &mi_masks
;
504 mi
->wa
.single_head_rdreq_dmif_limit
= 2;
509 dm_free(mem_input80
);
513 static void dce80_transform_destroy(struct transform
**xfm
)
515 dm_free(TO_DCE_TRANSFORM(*xfm
));
519 static struct transform
*dce80_transform_create(
520 struct dc_context
*ctx
,
523 struct dce_transform
*transform
=
524 dm_alloc(sizeof(struct dce_transform
));
529 if (dce_transform_construct(transform
, ctx
, inst
,
530 &xfm_regs
[inst
], &xfm_shift
, &xfm_mask
)) {
531 transform
->prescaler_on
= false;
532 return &transform
->base
;
540 static struct input_pixel_processor
*dce80_ipp_create(
541 struct dc_context
*ctx
,
543 const struct dce110_ipp_reg_offsets
*offset
)
545 struct dce110_ipp
*ipp
=
546 dm_alloc(sizeof(struct dce110_ipp
));
551 if (dce80_ipp_construct(ipp
, ctx
, inst
, offset
))
559 struct link_encoder
*dce80_link_encoder_create(
560 const struct encoder_init_data
*enc_init_data
)
562 struct dce110_link_encoder
*enc110
=
563 dm_alloc(sizeof(struct dce110_link_encoder
));
568 if (dce110_link_encoder_construct(
571 &link_enc_regs
[enc_init_data
->transmitter
],
572 &link_enc_aux_regs
[enc_init_data
->channel
- 1],
573 &link_enc_hpd_regs
[enc_init_data
->hpd_source
])) {
575 enc110
->base
.features
.ycbcr420_supported
= false;
576 enc110
->base
.features
.max_hdmi_pixel_clock
= 297000;
577 return &enc110
->base
;
585 struct clock_source
*dce80_clock_source_create(
586 struct dc_context
*ctx
,
587 struct dc_bios
*bios
,
588 enum clock_source_id id
,
589 const struct dce110_clk_src_regs
*regs
,
592 struct dce110_clk_src
*clk_src
=
593 dm_alloc(sizeof(struct dce110_clk_src
));
598 if (dce110_clk_src_construct(clk_src
, ctx
, bios
, id
,
599 regs
, &cs_shift
, &cs_mask
)) {
600 clk_src
->base
.dp_clk_src
= dp_clk_src
;
601 return &clk_src
->base
;
608 void dce80_clock_source_destroy(struct clock_source
**clk_src
)
610 dm_free(TO_DCE110_CLK_SRC(*clk_src
));
614 static void destruct(struct dce110_resource_pool
*pool
)
618 for (i
= 0; i
< pool
->base
.pipe_count
; i
++) {
619 if (pool
->base
.opps
[i
] != NULL
)
620 dce80_opp_destroy(&pool
->base
.opps
[i
]);
622 if (pool
->base
.transforms
[i
] != NULL
)
623 dce80_transform_destroy(&pool
->base
.transforms
[i
]);
625 if (pool
->base
.ipps
[i
] != NULL
)
626 dce80_ipp_destroy(&pool
->base
.ipps
[i
]);
628 if (pool
->base
.mis
[i
] != NULL
) {
629 dm_free(TO_DCE110_MEM_INPUT(pool
->base
.mis
[i
]));
630 pool
->base
.mis
[i
] = NULL
;
633 if (pool
->base
.timing_generators
[i
] != NULL
) {
634 dm_free(DCE110TG_FROM_TG(pool
->base
.timing_generators
[i
]));
635 pool
->base
.timing_generators
[i
] = NULL
;
639 for (i
= 0; i
< pool
->base
.stream_enc_count
; i
++) {
640 if (pool
->base
.stream_enc
[i
] != NULL
)
641 dm_free(DCE110STRENC_FROM_STRENC(pool
->base
.stream_enc
[i
]));
644 for (i
= 0; i
< pool
->base
.clk_src_count
; i
++) {
645 if (pool
->base
.clock_sources
[i
] != NULL
) {
646 dce80_clock_source_destroy(&pool
->base
.clock_sources
[i
]);
650 if (pool
->base
.dp_clock_source
!= NULL
)
651 dce80_clock_source_destroy(&pool
->base
.dp_clock_source
);
653 for (i
= 0; i
< pool
->base
.audio_count
; i
++) {
654 if (pool
->base
.audios
[i
] != NULL
) {
655 dce_aud_destroy(&pool
->base
.audios
[i
]);
659 if (pool
->base
.display_clock
!= NULL
) {
660 pool
->base
.display_clock
->funcs
->destroy(
661 &pool
->base
.display_clock
);
662 pool
->base
.display_clock
= NULL
;
665 if (pool
->base
.irqs
!= NULL
) {
666 dal_irq_service_destroy(&pool
->base
.irqs
);
670 static enum dc_status
validate_mapped_resource(
671 const struct core_dc
*dc
,
672 struct validate_context
*context
)
674 enum dc_status status
= DC_OK
;
677 for (i
= 0; i
< context
->target_count
; i
++) {
678 struct core_target
*target
= context
->targets
[i
];
680 for (j
= 0; j
< target
->public.stream_count
; j
++) {
681 struct core_stream
*stream
=
682 DC_STREAM_TO_CORE(target
->public.streams
[j
]);
683 struct core_link
*link
= stream
->sink
->link
;
685 if (resource_is_stream_unchanged(dc
->current_context
, stream
))
688 for (k
= 0; k
< MAX_PIPES
; k
++) {
689 struct pipe_ctx
*pipe_ctx
=
690 &context
->res_ctx
.pipe_ctx
[k
];
692 if (context
->res_ctx
.pipe_ctx
[k
].stream
!= stream
)
695 if (!pipe_ctx
->tg
->funcs
->validate_timing(
696 pipe_ctx
->tg
, &stream
->public.timing
))
697 return DC_FAIL_CONTROLLER_VALIDATE
;
699 status
= dce110_resource_build_pipe_hw_param(pipe_ctx
);
704 if (!link
->link_enc
->funcs
->validate_output_with_stream(
707 return DC_FAIL_ENC_VALIDATE
;
709 /* TODO: validate audio ASIC caps, encoder */
711 status
= dc_link_validate_mode_timing(stream
,
713 &stream
->public.timing
);
718 resource_build_info_frame(pipe_ctx
);
720 /* do not need to validate non root pipes */
729 enum dc_status
dce80_validate_bandwidth(
730 const struct core_dc
*dc
,
731 struct validate_context
*context
)
733 /* TODO implement when needed but for now hardcode max value*/
734 context
->bw_results
.dispclk_khz
= 681000;
735 context
->bw_results
.required_yclk
= 250000 * MEMORY_TYPE_MULTIPLIER
;
740 static bool dce80_validate_surface_sets(
741 const struct dc_validation_set set
[],
746 for (i
= 0; i
< set_count
; i
++) {
747 if (set
[i
].surface_count
== 0)
750 if (set
[i
].surface_count
> 1)
753 if (set
[i
].surfaces
[0]->clip_rect
.width
754 != set
[i
].target
->streams
[0]->src
.width
755 || set
[i
].surfaces
[0]->clip_rect
.height
756 != set
[i
].target
->streams
[0]->src
.height
)
758 if (set
[i
].surfaces
[0]->format
759 >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN
)
766 enum dc_status
dce80_validate_with_context(
767 const struct core_dc
*dc
,
768 const struct dc_validation_set set
[],
770 struct validate_context
*context
)
772 struct dc_context
*dc_ctx
= dc
->ctx
;
773 enum dc_status result
= DC_ERROR_UNEXPECTED
;
776 if (!dce80_validate_surface_sets(set
, set_count
))
777 return DC_FAIL_SURFACE_VALIDATE
;
779 context
->res_ctx
.pool
= dc
->res_pool
;
781 for (i
= 0; i
< set_count
; i
++) {
782 context
->targets
[i
] = DC_TARGET_TO_CORE(set
[i
].target
);
783 dc_target_retain(&context
->targets
[i
]->public);
784 context
->target_count
++;
787 result
= resource_map_pool_resources(dc
, context
);
790 result
= resource_map_clock_resources(dc
, context
);
792 if (!resource_validate_attach_surfaces(
793 set
, set_count
, dc
->current_context
, context
)) {
794 DC_ERROR("Failed to attach surface to target!\n");
795 return DC_FAIL_ATTACH_SURFACES
;
799 result
= validate_mapped_resource(dc
, context
);
802 result
= resource_build_scaling_params_for_context(dc
, context
);
805 result
= dce80_validate_bandwidth(dc
, context
);
810 enum dc_status
dce80_validate_guaranteed(
811 const struct core_dc
*dc
,
812 const struct dc_target
*dc_target
,
813 struct validate_context
*context
)
815 enum dc_status result
= DC_ERROR_UNEXPECTED
;
817 context
->res_ctx
.pool
= dc
->res_pool
;
819 context
->targets
[0] = DC_TARGET_TO_CORE(dc_target
);
820 dc_target_retain(&context
->targets
[0]->public);
821 context
->target_count
++;
823 result
= resource_map_pool_resources(dc
, context
);
826 result
= resource_map_clock_resources(dc
, context
);
829 result
= validate_mapped_resource(dc
, context
);
831 if (result
== DC_OK
) {
832 validate_guaranteed_copy_target(
833 context
, dc
->public.caps
.max_targets
);
834 result
= resource_build_scaling_params_for_context(dc
, context
);
838 result
= dce80_validate_bandwidth(dc
, context
);
843 static void dce80_destroy_resource_pool(struct resource_pool
**pool
)
845 struct dce110_resource_pool
*dce110_pool
= TO_DCE110_RES_POOL(*pool
);
847 destruct(dce110_pool
);
848 dm_free(dce110_pool
);
852 static const struct resource_funcs dce80_res_pool_funcs
= {
853 .destroy
= dce80_destroy_resource_pool
,
854 .link_enc_create
= dce80_link_encoder_create
,
855 .validate_with_context
= dce80_validate_with_context
,
856 .validate_guaranteed
= dce80_validate_guaranteed
,
857 .validate_bandwidth
= dce80_validate_bandwidth
860 static enum clocks_state
dce80_resource_convert_clock_state_pp_to_dc(
861 enum dm_pp_clocks_state pp_clock_state
)
863 enum clocks_state dc_clocks_state
= CLOCKS_STATE_INVALID
;
865 switch (pp_clock_state
) {
866 case DM_PP_CLOCKS_STATE_INVALID
:
867 dc_clocks_state
= CLOCKS_STATE_INVALID
;
869 case DM_PP_CLOCKS_STATE_ULTRA_LOW
:
870 dc_clocks_state
= CLOCKS_STATE_ULTRA_LOW
;
872 case DM_PP_CLOCKS_STATE_LOW
:
873 dc_clocks_state
= CLOCKS_STATE_LOW
;
875 case DM_PP_CLOCKS_STATE_NOMINAL
:
876 dc_clocks_state
= CLOCKS_STATE_NOMINAL
;
878 case DM_PP_CLOCKS_STATE_PERFORMANCE
:
879 dc_clocks_state
= CLOCKS_STATE_PERFORMANCE
;
881 case DM_PP_CLOCKS_DPM_STATE_LEVEL_4
:
882 dc_clocks_state
= CLOCKS_DPM_STATE_LEVEL_4
;
884 case DM_PP_CLOCKS_DPM_STATE_LEVEL_5
:
885 dc_clocks_state
= CLOCKS_DPM_STATE_LEVEL_5
;
887 case DM_PP_CLOCKS_DPM_STATE_LEVEL_6
:
888 dc_clocks_state
= CLOCKS_DPM_STATE_LEVEL_6
;
890 case DM_PP_CLOCKS_DPM_STATE_LEVEL_7
:
891 dc_clocks_state
= CLOCKS_DPM_STATE_LEVEL_7
;
894 dc_clocks_state
= CLOCKS_STATE_INVALID
;
898 return dc_clocks_state
;
901 static bool construct(
902 uint8_t num_virtual_links
,
904 struct dce110_resource_pool
*pool
)
907 struct dc_context
*ctx
= dc
->ctx
;
908 struct firmware_info info
;
910 struct dm_pp_static_clock_info static_clk_info
= {0};
912 ctx
->dc_bios
->regs
= &bios_regs
;
914 pool
->base
.res_cap
= &res_cap
;
915 pool
->base
.funcs
= &dce80_res_pool_funcs
;
918 /*************************************************
919 * Resource + asic cap harcoding *
920 *************************************************/
921 pool
->base
.underlay_pipe_index
= -1;
922 pool
->base
.pipe_count
= res_cap
.num_timing_generator
;
923 dc
->public.caps
.max_downscale_ratio
= 200;
924 dc
->public.caps
.i2c_speed_in_khz
= 40;
926 /*************************************************
928 *************************************************/
932 if ((bp
->funcs
->get_firmware_info(bp
, &info
) == BP_RESULT_OK
) &&
933 info
.external_clock_source_frequency_for_dp
!= 0) {
934 pool
->base
.dp_clock_source
=
935 dce80_clock_source_create(ctx
, bp
, CLOCK_SOURCE_ID_EXTERNAL
, NULL
, true);
937 pool
->base
.clock_sources
[0] =
938 dce80_clock_source_create(ctx
, bp
, CLOCK_SOURCE_ID_PLL0
, &clk_src_regs
[0], false);
939 pool
->base
.clock_sources
[1] =
940 dce80_clock_source_create(ctx
, bp
, CLOCK_SOURCE_ID_PLL1
, &clk_src_regs
[1], false);
941 pool
->base
.clock_sources
[2] =
942 dce80_clock_source_create(ctx
, bp
, CLOCK_SOURCE_ID_PLL2
, &clk_src_regs
[2], false);
943 pool
->base
.clk_src_count
= 3;
946 pool
->base
.dp_clock_source
=
947 dce80_clock_source_create(ctx
, bp
, CLOCK_SOURCE_ID_PLL0
, &clk_src_regs
[0], true);
949 pool
->base
.clock_sources
[0] =
950 dce80_clock_source_create(ctx
, bp
, CLOCK_SOURCE_ID_PLL1
, &clk_src_regs
[1], false);
951 pool
->base
.clock_sources
[1] =
952 dce80_clock_source_create(ctx
, bp
, CLOCK_SOURCE_ID_PLL2
, &clk_src_regs
[2], false);
953 pool
->base
.clk_src_count
= 2;
956 if (pool
->base
.dp_clock_source
== NULL
) {
957 dm_error("DC: failed to create dp clock source!\n");
959 goto res_create_fail
;
962 for (i
= 0; i
< pool
->base
.clk_src_count
; i
++) {
963 if (pool
->base
.clock_sources
[i
] == NULL
) {
964 dm_error("DC: failed to create clock sources!\n");
966 goto res_create_fail
;
970 pool
->base
.display_clock
= dal_display_clock_dce80_create(ctx
);
971 if (pool
->base
.display_clock
== NULL
) {
972 dm_error("DC: failed to create display clock!\n");
974 goto res_create_fail
;
978 if (dm_pp_get_static_clocks(ctx
, &static_clk_info
))
979 pool
->base
.display_clock
->max_clks_state
=
980 dce80_resource_convert_clock_state_pp_to_dc(
981 static_clk_info
.max_clocks_state
);
984 struct irq_service_init_data init_data
;
985 init_data
.ctx
= dc
->ctx
;
986 pool
->base
.irqs
= dal_irq_service_dce80_create(&init_data
);
987 if (!pool
->base
.irqs
)
988 goto res_create_fail
;
991 for (i
= 0; i
< pool
->base
.pipe_count
; i
++) {
992 pool
->base
.timing_generators
[i
] = dce80_timing_generator_create(
993 ctx
, i
, &dce80_tg_offsets
[i
]);
994 if (pool
->base
.timing_generators
[i
] == NULL
) {
996 dm_error("DC: failed to create tg!\n");
997 goto res_create_fail
;
1000 pool
->base
.mis
[i
] = dce80_mem_input_create(ctx
, i
,
1001 &dce80_mi_reg_offsets
[i
]);
1002 if (pool
->base
.mis
[i
] == NULL
) {
1003 BREAK_TO_DEBUGGER();
1004 dm_error("DC: failed to create memory input!\n");
1005 goto res_create_fail
;
1008 pool
->base
.ipps
[i
] = dce80_ipp_create(ctx
, i
, &ipp_reg_offsets
[i
]);
1009 if (pool
->base
.ipps
[i
] == NULL
) {
1010 BREAK_TO_DEBUGGER();
1011 dm_error("DC: failed to create input pixel processor!\n");
1012 goto res_create_fail
;
1015 pool
->base
.transforms
[i
] = dce80_transform_create(ctx
, i
);
1016 if (pool
->base
.transforms
[i
] == NULL
) {
1017 BREAK_TO_DEBUGGER();
1018 dm_error("DC: failed to create transform!\n");
1019 goto res_create_fail
;
1022 pool
->base
.opps
[i
] = dce80_opp_create(ctx
, i
);
1023 if (pool
->base
.opps
[i
] == NULL
) {
1024 BREAK_TO_DEBUGGER();
1025 dm_error("DC: failed to create output pixel processor!\n");
1026 goto res_create_fail
;
1030 if (!resource_construct(num_virtual_links
, dc
, &pool
->base
,
1032 goto res_create_fail
;
1034 /* Create hardware sequencer */
1035 if (!dce80_hw_sequencer_construct(dc
))
1036 goto res_create_fail
;
1045 struct resource_pool
*dce80_create_resource_pool(
1046 uint8_t num_virtual_links
,
1049 struct dce110_resource_pool
*pool
=
1050 dm_alloc(sizeof(struct dce110_resource_pool
));
1055 if (construct(num_virtual_links
, dc
, pool
))
1058 BREAK_TO_DEBUGGER();