2 * Copyright 2016 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 "dm_services.h"
30 #include "include/irq_service_interface.h"
31 #include "dcn10/dcn10_resource.h"
33 #include "dcn10/dcn10_ipp.h"
34 #include "dcn10/dcn10_mpc.h"
35 #include "irq/dcn10/irq_service_dcn10.h"
36 #include "dcn10/dcn10_transform.h"
37 #include "dcn10/dcn10_timing_generator.h"
38 #include "dcn10/dcn10_hw_sequencer.h"
39 #include "dce110/dce110_hw_sequencer.h"
40 #include "dcn10/dcn10_opp.h"
41 #include "dce/dce_link_encoder.h"
42 #include "dce/dce_stream_encoder.h"
43 #include "dce/dce_clocks.h"
44 #include "dce/dce_clock_source.h"
45 #include "dcn10/dcn10_mem_input.h"
46 #include "dce/dce_audio.h"
47 #include "dce/dce_hwseq.h"
48 #include "../virtual/virtual_stream_encoder.h"
49 #include "dce110/dce110_resource.h"
51 #include "vega10/soc15ip.h"
53 #include "raven1/DCN/dcn_1_0_offset.h"
54 #include "raven1/DCN/dcn_1_0_sh_mask.h"
56 #include "raven1/NBIO/nbio_7_0_offset.h"
58 #include "raven1/MMHUB/mmhub_9_1_offset.h"
59 #include "raven1/MMHUB/mmhub_9_1_sh_mask.h"
61 #include "reg_helper.h"
62 #include "dce/dce_abm.h"
63 #include "dce/dce_dmcu.h"
65 #ifndef mmDP0_DP_DPHY_INTERNAL_CTRL
66 #define mmDP0_DP_DPHY_INTERNAL_CTRL 0x210f
67 #define mmDP0_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2
68 #define mmDP1_DP_DPHY_INTERNAL_CTRL 0x220f
69 #define mmDP1_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2
70 #define mmDP2_DP_DPHY_INTERNAL_CTRL 0x230f
71 #define mmDP2_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2
72 #define mmDP3_DP_DPHY_INTERNAL_CTRL 0x240f
73 #define mmDP3_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2
74 #define mmDP4_DP_DPHY_INTERNAL_CTRL 0x250f
75 #define mmDP4_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2
76 #define mmDP5_DP_DPHY_INTERNAL_CTRL 0x260f
77 #define mmDP5_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2
78 #define mmDP6_DP_DPHY_INTERNAL_CTRL 0x270f
79 #define mmDP6_DP_DPHY_INTERNAL_CTRL_BASE_IDX 2
83 enum dcn10_clk_src_array_id
{
91 /* begin *********************
92 * macros to expend register list macro defined in HW object header file */
95 #define BASE_INNER(seg) \
96 DCE_BASE__INST0_SEG ## seg
101 #define SR(reg_name)\
102 .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \
105 #define SRI(reg_name, block, id)\
106 .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
107 mm ## block ## id ## _ ## reg_name
110 #define SRII(reg_name, block, id)\
111 .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
112 mm ## block ## id ## _ ## reg_name
115 #define NBIO_BASE_INNER(seg) \
116 NBIF_BASE__INST0_SEG ## seg
118 #define NBIO_BASE(seg) \
121 #define NBIO_SR(reg_name)\
122 .reg_name = NBIO_BASE(mm ## reg_name ## _BASE_IDX) + \
126 #define MMHUB_BASE_INNER(seg) \
127 MMHUB_BASE__INST0_SEG ## seg
129 #define MMHUB_BASE(seg) \
130 MMHUB_BASE_INNER(seg)
132 #define MMHUB_SR(reg_name)\
133 .reg_name = MMHUB_BASE(mm ## reg_name ## _BASE_IDX) + \
136 /* macros to expend register list macro defined in HW object header file
137 * end *********************/
139 static const struct dce_disp_clk_registers disp_clk_regs
= {
143 static const struct dce_disp_clk_shift disp_clk_shift
= {
144 CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(__SHIFT
)
147 static const struct dce_disp_clk_mask disp_clk_mask
= {
148 CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK
)
151 static const struct dce_dmcu_registers dmcu_regs
= {
152 DMCU_DCN10_REG_LIST()
155 static const struct dce_dmcu_shift dmcu_shift
= {
156 DMCU_MASK_SH_LIST_DCN10(__SHIFT
)
159 static const struct dce_dmcu_mask dmcu_mask
= {
160 DMCU_MASK_SH_LIST_DCN10(_MASK
)
163 static const struct dce_abm_registers abm_regs
= {
164 ABM_DCN10_REG_LIST(0)
167 static const struct dce_abm_shift abm_shift
= {
168 ABM_MASK_SH_LIST_DCN10(__SHIFT
)
171 static const struct dce_abm_mask abm_mask
= {
172 ABM_MASK_SH_LIST_DCN10(_MASK
)
175 #define stream_enc_regs(id)\
177 SE_DCN_REG_LIST(id),\
179 .AFMT_AVI_INFO0 = 0,\
180 .AFMT_AVI_INFO1 = 0,\
181 .AFMT_AVI_INFO2 = 0,\
182 .AFMT_AVI_INFO3 = 0,\
185 static const struct dce110_stream_enc_registers stream_enc_regs
[] = {
192 static const struct dce_stream_encoder_shift se_shift
= {
193 SE_COMMON_MASK_SH_LIST_DCN10(__SHIFT
)
196 static const struct dce_stream_encoder_mask se_mask
= {
197 SE_COMMON_MASK_SH_LIST_DCN10(_MASK
),
198 .AFMT_GENERIC0_UPDATE
= 0,
199 .AFMT_GENERIC2_UPDATE
= 0,
202 .HDMI_AVI_INFO_SEND
= 0,
203 .HDMI_AVI_INFO_CONT
= 0,
204 .HDMI_AVI_INFO_LINE
= 0,
205 .DP_SEC_AVI_ENABLE
= 0,
206 .AFMT_AVI_INFO_VERSION
= 0
209 #define audio_regs(id)\
211 AUD_COMMON_REG_LIST(id)\
214 static const struct dce_audio_registers audio_regs
[] = {
221 #define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\
222 SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\
223 SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\
224 AUD_COMMON_MASK_SH_LIST_BASE(mask_sh)
226 static const struct dce_audio_shift audio_shift
= {
227 DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT
)
230 static const struct dce_aduio_mask audio_mask
= {
231 DCE120_AUD_COMMON_MASK_SH_LIST(_MASK
)
234 #define aux_regs(id)\
239 static const struct dce110_link_enc_aux_registers link_enc_aux_regs
[] = {
248 #define hpd_regs(id)\
253 static const struct dce110_link_enc_hpd_registers link_enc_hpd_regs
[] = {
262 #define link_regs(id)\
264 LE_DCN10_REG_LIST(id), \
265 SRI(DP_DPHY_INTERNAL_CTRL, DP, id) \
268 static const struct dce110_link_enc_registers link_enc_regs
[] = {
278 #define ipp_regs(id)\
280 IPP_DCN10_REG_LIST(id),\
283 static const struct dcn10_ipp_registers ipp_regs
[] = {
290 static const struct dcn10_ipp_shift ipp_shift
= {
291 IPP_DCN10_MASK_SH_LIST(__SHIFT
)
294 static const struct dcn10_ipp_mask ipp_mask
= {
295 IPP_DCN10_MASK_SH_LIST(_MASK
),
298 #define opp_regs(id)\
300 OPP_DCN10_REG_LIST(id),\
303 static const struct dcn10_opp_registers opp_regs
[] = {
310 static const struct dcn10_opp_shift opp_shift
= {
311 OPP_DCN10_MASK_SH_LIST(__SHIFT
)
314 static const struct dcn10_opp_mask opp_mask
= {
315 OPP_DCN10_MASK_SH_LIST(_MASK
),
320 TF_REG_LIST_DCN(id),\
323 static const struct dcn_transform_registers tf_regs
[] = {
330 static const struct dcn_transform_shift tf_shift
= {
331 TF_REG_LIST_SH_MASK_DCN(__SHIFT
)
334 static const struct dcn_transform_mask tf_mask
= {
335 TF_REG_LIST_SH_MASK_DCN(_MASK
),
339 #define mpcc_regs(id)\
341 MPCC_COMMON_REG_LIST_DCN1_0(id),\
342 MPC_COMMON_REG_LIST_DCN1_0(0),\
343 MPC_COMMON_REG_LIST_DCN1_0(1),\
344 MPC_COMMON_REG_LIST_DCN1_0(2),\
345 MPC_COMMON_REG_LIST_DCN1_0(3),\
348 static const struct dcn_mpcc_registers mpcc_regs
[] = {
355 static const struct dcn_mpcc_shift mpcc_shift
= {
356 MPCC_COMMON_MASK_SH_LIST_DCN1_0(__SHIFT
)
359 static const struct dcn_mpcc_mask mpcc_mask
= {
360 MPCC_COMMON_MASK_SH_LIST_DCN1_0(_MASK
),
364 [id] = {TG_COMMON_REG_LIST_DCN1_0(id)}
366 static const struct dcn_tg_registers tg_regs
[] = {
373 static const struct dcn_tg_shift tg_shift
= {
374 TG_COMMON_MASK_SH_LIST_DCN1_0(__SHIFT
)
377 static const struct dcn_tg_mask tg_mask
= {
378 TG_COMMON_MASK_SH_LIST_DCN1_0(_MASK
)
382 static const struct bios_registers bios_regs
= {
383 NBIO_SR(BIOS_SCRATCH_6
)
388 MI_DCN10_REG_LIST(id)\
392 static const struct dcn_mi_registers mi_regs
[] = {
399 static const struct dcn_mi_shift mi_shift
= {
400 MI_DCN10_MASK_SH_LIST(__SHIFT
)
403 static const struct dcn_mi_mask mi_mask
= {
404 MI_DCN10_MASK_SH_LIST(_MASK
)
407 #define clk_src_regs(index, pllid)\
409 CS_COMMON_REG_LIST_DCN1_0(index, pllid),\
412 static const struct dce110_clk_src_regs clk_src_regs
[] = {
419 static const struct dce110_clk_src_shift cs_shift
= {
420 CS_COMMON_MASK_SH_LIST_DCN1_0(__SHIFT
)
423 static const struct dce110_clk_src_mask cs_mask
= {
424 CS_COMMON_MASK_SH_LIST_DCN1_0(_MASK
)
428 static const struct resource_caps res_cap
= {
429 .num_timing_generator
= 4,
430 .num_video_plane
= 4,
432 .num_stream_encoder
= 4,
436 static const struct dc_debug debug_defaults_drv
= {
437 .disable_dcc
= false,
438 .disable_dmcu
= true,
439 .force_abm_enable
= false,
440 .timing_trace
= false,
442 .disable_pplib_clock_request
= true,
443 .disable_pplib_wm_range
= false,
444 #if defined(CONFIG_DRM_AMD_DC_DCN1_0)
446 .disable_pipe_split
= true
450 static const struct dc_debug debug_defaults_diags
= {
451 .disable_dmcu
= true,
452 .force_abm_enable
= false,
453 .timing_trace
= true,
455 #if defined(CONFIG_DRM_AMD_DC_DCN1_0)
456 .disable_pplib_clock_request
= true,
457 .disable_pplib_wm_range
= true,
459 .disable_pipe_split
= false
463 static void dcn10_transform_destroy(struct transform
**xfm
)
465 dm_free(TO_DCN10_TRANSFORM(*xfm
));
469 static struct transform
*dcn10_transform_create(
470 struct dc_context
*ctx
,
473 struct dcn10_transform
*transform
=
474 dm_alloc(sizeof(struct dcn10_transform
));
479 if (dcn10_transform_construct(transform
, ctx
,
480 &tf_regs
[inst
], &tf_shift
, &tf_mask
))
481 return &transform
->base
;
488 static struct input_pixel_processor
*dcn10_ipp_create(
489 struct dc_context
*ctx
, uint32_t inst
)
491 struct dcn10_ipp
*ipp
=
492 dm_alloc(sizeof(struct dcn10_ipp
));
499 dcn10_ipp_construct(ipp
, ctx
, inst
,
500 &ipp_regs
[inst
], &ipp_shift
, &ipp_mask
);
505 static struct output_pixel_processor
*dcn10_opp_create(
506 struct dc_context
*ctx
, uint32_t inst
)
508 struct dcn10_opp
*opp
=
509 dm_alloc(sizeof(struct dcn10_opp
));
516 dcn10_opp_construct(opp
, ctx
, inst
,
517 &opp_regs
[inst
], &opp_shift
, &opp_mask
);
521 static struct mpcc
*dcn10_mpcc_create(
522 struct dc_context
*ctx
,
525 struct dcn10_mpcc
*mpcc10
= dm_alloc(sizeof(struct dcn10_mpcc
));
530 dcn10_mpcc_construct(mpcc10
, ctx
,
536 return &mpcc10
->base
;
539 static struct timing_generator
*dcn10_timing_generator_create(
540 struct dc_context
*ctx
,
543 struct dcn10_timing_generator
*tgn10
=
544 dm_alloc(sizeof(struct dcn10_timing_generator
));
549 tgn10
->base
.inst
= instance
;
550 tgn10
->base
.ctx
= ctx
;
552 tgn10
->tg_regs
= &tg_regs
[instance
];
553 tgn10
->tg_shift
= &tg_shift
;
554 tgn10
->tg_mask
= &tg_mask
;
556 dcn10_timing_generator_init(tgn10
);
561 static const struct encoder_feature_support link_enc_feature
= {
562 .max_hdmi_deep_color
= COLOR_DEPTH_121212
,
563 .max_hdmi_pixel_clock
= 600000,
564 .ycbcr420_supported
= true,
565 .flags
.bits
.IS_HBR2_CAPABLE
= true,
566 .flags
.bits
.IS_HBR3_CAPABLE
= true,
567 .flags
.bits
.IS_TPS3_CAPABLE
= true,
568 .flags
.bits
.IS_TPS4_CAPABLE
= true,
569 .flags
.bits
.IS_YCBCR_CAPABLE
= true
572 struct link_encoder
*dcn10_link_encoder_create(
573 const struct encoder_init_data
*enc_init_data
)
575 struct dce110_link_encoder
*enc110
=
576 dm_alloc(sizeof(struct dce110_link_encoder
));
581 if (dce110_link_encoder_construct(
585 &link_enc_regs
[enc_init_data
->transmitter
],
586 &link_enc_aux_regs
[enc_init_data
->channel
- 1],
587 &link_enc_hpd_regs
[enc_init_data
->hpd_source
])) {
589 return &enc110
->base
;
597 struct clock_source
*dcn10_clock_source_create(
598 struct dc_context
*ctx
,
599 struct dc_bios
*bios
,
600 enum clock_source_id id
,
601 const struct dce110_clk_src_regs
*regs
,
604 struct dce110_clk_src
*clk_src
=
605 dm_alloc(sizeof(struct dce110_clk_src
));
610 if (dce110_clk_src_construct(clk_src
, ctx
, bios
, id
,
611 regs
, &cs_shift
, &cs_mask
)) {
612 clk_src
->base
.dp_clk_src
= dp_clk_src
;
613 return &clk_src
->base
;
620 static void read_dce_straps(
621 struct dc_context
*ctx
,
622 struct resource_straps
*straps
)
624 /* TODO: Registers are missing */
625 /*REG_GET_2(CC_DC_HDMI_STRAPS,
626 HDMI_DISABLE, &straps->hdmi_disable,
627 AUDIO_STREAM_NUMBER, &straps->audio_stream_number);
629 REG_GET(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO, &straps->dc_pinstraps_audio);*/
632 static struct audio
*create_audio(
633 struct dc_context
*ctx
, unsigned int inst
)
635 return dce_audio_create(ctx
, inst
,
636 &audio_regs
[inst
], &audio_shift
, &audio_mask
);
639 static struct stream_encoder
*dcn10_stream_encoder_create(
640 enum engine_id eng_id
,
641 struct dc_context
*ctx
)
643 struct dce110_stream_encoder
*enc110
=
644 dm_alloc(sizeof(struct dce110_stream_encoder
));
649 if (dce110_stream_encoder_construct(
650 enc110
, ctx
, ctx
->dc_bios
, eng_id
,
651 &stream_enc_regs
[eng_id
], &se_shift
, &se_mask
))
652 return &enc110
->base
;
659 static const struct dce_hwseq_registers hwseq_reg
= {
660 HWSEQ_DCN1_REG_LIST()
663 static const struct dce_hwseq_shift hwseq_shift
= {
664 HWSEQ_DCN1_MASK_SH_LIST(__SHIFT
)
667 static const struct dce_hwseq_mask hwseq_mask
= {
668 HWSEQ_DCN1_MASK_SH_LIST(_MASK
)
671 static struct dce_hwseq
*dcn10_hwseq_create(
672 struct dc_context
*ctx
)
674 struct dce_hwseq
*hws
= dm_alloc(sizeof(struct dce_hwseq
));
678 hws
->regs
= &hwseq_reg
;
679 hws
->shifts
= &hwseq_shift
;
680 hws
->masks
= &hwseq_mask
;
685 static const struct resource_create_funcs res_create_funcs
= {
686 .read_dce_straps
= read_dce_straps
,
687 .create_audio
= create_audio
,
688 .create_stream_encoder
= dcn10_stream_encoder_create
,
689 .create_hwseq
= dcn10_hwseq_create
,
692 static const struct resource_create_funcs res_create_maximus_funcs
= {
693 .read_dce_straps
= NULL
,
694 .create_audio
= NULL
,
695 .create_stream_encoder
= NULL
,
696 .create_hwseq
= dcn10_hwseq_create
,
699 void dcn10_clock_source_destroy(struct clock_source
**clk_src
)
701 dm_free(TO_DCE110_CLK_SRC(*clk_src
));
705 static void destruct(struct dcn10_resource_pool
*pool
)
709 for (i
= 0; i
< pool
->base
.stream_enc_count
; i
++) {
710 if (pool
->base
.stream_enc
[i
] != NULL
) {
711 /* TODO: free dcn version of stream encoder once implemented
712 * rather than using virtual stream encoder
714 dm_free(pool
->base
.stream_enc
[i
]);
715 pool
->base
.stream_enc
[i
] = NULL
;
719 for (i
= 0; i
< pool
->base
.pipe_count
; i
++) {
720 if (pool
->base
.opps
[i
] != NULL
)
721 pool
->base
.opps
[i
]->funcs
->opp_destroy(&pool
->base
.opps
[i
]);
723 if (pool
->base
.transforms
[i
] != NULL
)
724 dcn10_transform_destroy(&pool
->base
.transforms
[i
]);
726 if (pool
->base
.ipps
[i
] != NULL
)
727 pool
->base
.ipps
[i
]->funcs
->ipp_destroy(&pool
->base
.ipps
[i
]);
729 if (pool
->base
.mis
[i
] != NULL
) {
730 dm_free(TO_DCN10_MEM_INPUT(pool
->base
.mis
[i
]));
731 pool
->base
.mis
[i
] = NULL
;
734 if (pool
->base
.irqs
!= NULL
) {
735 dal_irq_service_destroy(&pool
->base
.irqs
);
738 if (pool
->base
.timing_generators
[i
] != NULL
) {
739 dm_free(DCN10TG_FROM_TG(pool
->base
.timing_generators
[i
]));
740 pool
->base
.timing_generators
[i
] = NULL
;
743 if (pool
->base
.mpcc
[i
] != NULL
) {
744 dm_free(TO_DCN10_MPCC(pool
->base
.mpcc
[i
]));
745 pool
->base
.mpcc
[i
] = NULL
;
749 for (i
= 0; i
< pool
->base
.stream_enc_count
; i
++) {
750 if (pool
->base
.stream_enc
[i
] != NULL
)
751 dm_free(DCE110STRENC_FROM_STRENC(pool
->base
.stream_enc
[i
]));
754 for (i
= 0; i
< pool
->base
.audio_count
; i
++) {
755 if (pool
->base
.audios
[i
])
756 dce_aud_destroy(&pool
->base
.audios
[i
]);
759 for (i
= 0; i
< pool
->base
.clk_src_count
; i
++) {
760 if (pool
->base
.clock_sources
[i
] != NULL
) {
761 dcn10_clock_source_destroy(&pool
->base
.clock_sources
[i
]);
762 pool
->base
.clock_sources
[i
] = NULL
;
766 if (pool
->base
.dp_clock_source
!= NULL
) {
767 dcn10_clock_source_destroy(&pool
->base
.dp_clock_source
);
768 pool
->base
.dp_clock_source
= NULL
;
771 if (pool
->base
.abm
!= NULL
)
772 dce_abm_destroy(&pool
->base
.abm
);
774 if (pool
->base
.dmcu
!= NULL
)
775 dce_dmcu_destroy(&pool
->base
.dmcu
);
777 if (pool
->base
.display_clock
!= NULL
)
778 dce_disp_clk_destroy(&pool
->base
.display_clock
);
781 static struct mem_input
*dcn10_mem_input_create(
782 struct dc_context
*ctx
,
785 struct dcn10_mem_input
*mem_inputn10
=
786 dm_alloc(sizeof(struct dcn10_mem_input
));
791 if (dcn10_mem_input_construct(mem_inputn10
, ctx
, inst
,
792 &mi_regs
[inst
], &mi_shift
, &mi_mask
))
793 return &mem_inputn10
->base
;
796 dm_free(mem_inputn10
);
800 static void get_pixel_clock_parameters(
801 const struct pipe_ctx
*pipe_ctx
,
802 struct pixel_clk_params
*pixel_clk_params
)
804 const struct core_stream
*stream
= pipe_ctx
->stream
;
805 pixel_clk_params
->requested_pix_clk
= stream
->public.timing
.pix_clk_khz
;
806 pixel_clk_params
->encoder_object_id
= stream
->sink
->link
->link_enc
->id
;
807 pixel_clk_params
->signal_type
= pipe_ctx
->stream
->signal
;
808 pixel_clk_params
->controller_id
= pipe_ctx
->pipe_idx
+ 1;
809 /* TODO: un-hardcode*/
810 pixel_clk_params
->requested_sym_clk
= LINK_RATE_LOW
*
811 LINK_RATE_REF_FREQ_IN_KHZ
;
812 pixel_clk_params
->flags
.ENABLE_SS
= 0;
813 pixel_clk_params
->color_depth
=
814 stream
->public.timing
.display_color_depth
;
815 pixel_clk_params
->flags
.DISPLAY_BLANKED
= 1;
816 pixel_clk_params
->pixel_encoding
= stream
->public.timing
.pixel_encoding
;
818 if (stream
->public.timing
.pixel_encoding
== PIXEL_ENCODING_YCBCR422
)
819 pixel_clk_params
->color_depth
= COLOR_DEPTH_888
;
821 if (stream
->public.timing
.pixel_encoding
== PIXEL_ENCODING_YCBCR420
)
822 pixel_clk_params
->requested_pix_clk
/= 2;
826 static void build_clamping_params(struct core_stream
*stream
)
828 stream
->clamping
.clamping_level
= CLAMPING_FULL_RANGE
;
829 stream
->clamping
.c_depth
= stream
->public.timing
.display_color_depth
;
830 stream
->clamping
.pixel_encoding
= stream
->public.timing
.pixel_encoding
;
833 static enum dc_status
build_pipe_hw_param(struct pipe_ctx
*pipe_ctx
)
836 get_pixel_clock_parameters(pipe_ctx
, &pipe_ctx
->pix_clk_params
);
838 pipe_ctx
->clock_source
->funcs
->get_pix_clk_dividers(
839 pipe_ctx
->clock_source
,
840 &pipe_ctx
->pix_clk_params
,
841 &pipe_ctx
->pll_settings
);
843 pipe_ctx
->stream
->clamping
.pixel_encoding
= pipe_ctx
->stream
->public.timing
.pixel_encoding
;
845 resource_build_bit_depth_reduction_params(pipe_ctx
->stream
,
846 &pipe_ctx
->stream
->bit_depth_params
);
847 build_clamping_params(pipe_ctx
->stream
);
852 static enum dc_status
validate_mapped_resource(
853 const struct core_dc
*dc
,
854 struct validate_context
*context
,
855 struct validate_context
*old_context
)
857 enum dc_status status
= DC_OK
;
860 for (i
= 0; i
< context
->stream_count
; i
++) {
861 struct core_stream
*stream
= context
->streams
[i
];
862 struct core_link
*link
= stream
->sink
->link
;
864 if (old_context
&& resource_is_stream_unchanged(old_context
, stream
)) {
865 if (stream
!= NULL
&& old_context
->streams
[i
] != NULL
) {
866 /* todo: shouldn't have to copy missing parameter here */
867 resource_build_bit_depth_reduction_params(stream
,
868 &stream
->bit_depth_params
);
869 stream
->clamping
.pixel_encoding
=
870 stream
->public.timing
.pixel_encoding
;
872 resource_build_bit_depth_reduction_params(stream
,
873 &stream
->bit_depth_params
);
874 build_clamping_params(stream
);
880 for (j
= 0; j
< dc
->res_pool
->pipe_count
; j
++) {
881 struct pipe_ctx
*pipe_ctx
=
882 &context
->res_ctx
.pipe_ctx
[j
];
884 if (context
->res_ctx
.pipe_ctx
[j
].stream
!= stream
)
888 if (!pipe_ctx
->tg
->funcs
->validate_timing(
889 pipe_ctx
->tg
, &stream
->public.timing
))
890 return DC_FAIL_CONTROLLER_VALIDATE
;
892 status
= build_pipe_hw_param(pipe_ctx
);
897 if (!link
->link_enc
->funcs
->validate_output_with_stream(
898 link
->link_enc
, pipe_ctx
))
899 return DC_FAIL_ENC_VALIDATE
;
901 /* TODO: validate audio ASIC caps, encoder */
903 status
= dc_link_validate_mode_timing(
904 stream
, link
, &stream
->public.timing
);
910 /* do not need to validate non root pipes */
918 enum dc_status
dcn10_validate_with_context(
919 const struct core_dc
*dc
,
920 const struct dc_validation_set set
[],
922 struct validate_context
*context
,
923 struct validate_context
*old_context
)
925 enum dc_status result
= DC_OK
;
931 for (i
= 0; i
< set_count
; i
++) {
932 context
->streams
[i
] = DC_STREAM_TO_CORE(set
[i
].stream
);
933 dc_stream_retain(&context
->streams
[i
]->public);
934 context
->stream_count
++;
937 result
= resource_map_pool_resources(dc
, context
, old_context
);
941 result
= resource_map_phy_clock_resources(dc
, context
, old_context
);
945 result
= validate_mapped_resource(dc
, context
, old_context
);
949 if (!resource_validate_attach_surfaces(set
, set_count
,
950 old_context
, context
, dc
->res_pool
))
951 return DC_FAIL_ATTACH_SURFACES
;
953 result
= resource_build_scaling_params_for_context(dc
, context
);
957 if (!dcn_validate_bandwidth(dc
, context
))
958 return DC_FAIL_BANDWIDTH_VALIDATE
;
963 enum dc_status
dcn10_validate_guaranteed(
964 const struct core_dc
*dc
,
965 const struct dc_stream
*dc_stream
,
966 struct validate_context
*context
)
968 enum dc_status result
= DC_ERROR_UNEXPECTED
;
970 context
->streams
[0] = DC_STREAM_TO_CORE(dc_stream
);
971 dc_stream_retain(&context
->streams
[0]->public);
972 context
->stream_count
++;
974 result
= resource_map_pool_resources(dc
, context
, NULL
);
977 result
= resource_map_phy_clock_resources(dc
, context
, NULL
);
980 result
= validate_mapped_resource(dc
, context
, NULL
);
982 if (result
== DC_OK
) {
983 validate_guaranteed_copy_streams(
984 context
, dc
->public.caps
.max_streams
);
985 result
= resource_build_scaling_params_for_context(dc
, context
);
987 if (result
== DC_OK
&& !dcn_validate_bandwidth(dc
, context
))
988 return DC_FAIL_BANDWIDTH_VALIDATE
;
993 static struct pipe_ctx
*dcn10_acquire_idle_pipe_for_layer(
994 struct validate_context
*context
,
995 const struct resource_pool
*pool
,
996 struct core_stream
*stream
)
998 struct resource_context
*res_ctx
= &context
->res_ctx
;
999 struct pipe_ctx
*head_pipe
= resource_get_head_pipe_for_stream(res_ctx
, stream
);
1000 struct pipe_ctx
*idle_pipe
= find_idle_secondary_pipe(res_ctx
, pool
);
1008 idle_pipe
->stream
= head_pipe
->stream
;
1009 idle_pipe
->tg
= head_pipe
->tg
;
1011 idle_pipe
->mpcc
= pool
->mpcc
[idle_pipe
->pipe_idx
];
1012 idle_pipe
->mi
= pool
->mis
[idle_pipe
->pipe_idx
];
1013 idle_pipe
->ipp
= pool
->ipps
[idle_pipe
->pipe_idx
];
1014 idle_pipe
->xfm
= pool
->transforms
[idle_pipe
->pipe_idx
];
1015 idle_pipe
->opp
= pool
->opps
[idle_pipe
->pipe_idx
];
1021 dcc_control__256_256_xxx
,
1022 dcc_control__128_128_xxx
,
1023 dcc_control__256_64_64
,
1026 enum segment_order
{
1028 segment_order__contiguous
,
1029 segment_order__non_contiguous
,
1032 static bool dcc_support_pixel_format(
1033 enum surface_pixel_format format
,
1034 unsigned int *bytes_per_element
)
1036 /* DML: get_bytes_per_element */
1038 case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555
:
1039 case SURFACE_PIXEL_FORMAT_GRPH_RGB565
:
1040 *bytes_per_element
= 2;
1042 case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888
:
1043 case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888
:
1044 case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010
:
1045 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010
:
1046 *bytes_per_element
= 4;
1048 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616
:
1049 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F
:
1050 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F
:
1051 *bytes_per_element
= 8;
1058 static bool dcc_support_swizzle(
1059 enum swizzle_mode_values swizzle
,
1060 unsigned int bytes_per_element
,
1061 enum segment_order
*segment_order_horz
,
1062 enum segment_order
*segment_order_vert
)
1064 bool standard_swizzle
= false;
1065 bool display_swizzle
= false;
1072 case DC_SW_64KB_S_X
:
1074 standard_swizzle
= true;
1080 case DC_SW_64KB_D_X
:
1082 display_swizzle
= true;
1088 if (bytes_per_element
== 1 && standard_swizzle
) {
1089 *segment_order_horz
= segment_order__contiguous
;
1090 *segment_order_vert
= segment_order__na
;
1093 if (bytes_per_element
== 2 && standard_swizzle
) {
1094 *segment_order_horz
= segment_order__non_contiguous
;
1095 *segment_order_vert
= segment_order__contiguous
;
1098 if (bytes_per_element
== 4 && standard_swizzle
) {
1099 *segment_order_horz
= segment_order__non_contiguous
;
1100 *segment_order_vert
= segment_order__contiguous
;
1103 if (bytes_per_element
== 8 && standard_swizzle
) {
1104 *segment_order_horz
= segment_order__na
;
1105 *segment_order_vert
= segment_order__contiguous
;
1108 if (bytes_per_element
== 8 && display_swizzle
) {
1109 *segment_order_horz
= segment_order__contiguous
;
1110 *segment_order_vert
= segment_order__non_contiguous
;
1117 static void get_blk256_size(unsigned int *blk256_width
, unsigned int *blk256_height
,
1118 unsigned int bytes_per_element
)
1120 /* copied from DML. might want to refactor DML to leverage from DML */
1121 /* DML : get_blk256_size */
1122 if (bytes_per_element
== 1) {
1124 *blk256_height
= 16;
1125 } else if (bytes_per_element
== 2) {
1128 } else if (bytes_per_element
== 4) {
1131 } else if (bytes_per_element
== 8) {
1137 static void det_request_size(
1138 unsigned int height
,
1141 bool *req128_horz_wc
,
1142 bool *req128_vert_wc
)
1144 unsigned int detile_buf_size
= 164 * 1024; /* 164KB for DCN1.0 */
1146 unsigned int blk256_height
= 0;
1147 unsigned int blk256_width
= 0;
1148 unsigned int swath_bytes_horz_wc
, swath_bytes_vert_wc
;
1150 get_blk256_size(&blk256_width
, &blk256_height
, bpe
);
1152 swath_bytes_horz_wc
= height
* blk256_height
* bpe
;
1153 swath_bytes_vert_wc
= width
* blk256_width
* bpe
;
1155 *req128_horz_wc
= (2 * swath_bytes_horz_wc
<= detile_buf_size
) ?
1156 false : /* full 256B request */
1157 true; /* half 128b request */
1159 *req128_vert_wc
= (2 * swath_bytes_vert_wc
<= detile_buf_size
) ?
1160 false : /* full 256B request */
1161 true; /* half 128b request */
1164 static bool get_dcc_compression_cap(const struct dc
*dc
,
1165 const struct dc_dcc_surface_param
*input
,
1166 struct dc_surface_dcc_cap
*output
)
1168 /* implement section 1.6.2.1 of DCN1_Programming_Guide.docx */
1169 enum dcc_control dcc_control
;
1171 enum segment_order segment_order_horz
, segment_order_vert
;
1172 bool req128_horz_wc
, req128_vert_wc
;
1174 memset(output
, 0, sizeof(*output
));
1176 if (dc
->debug
.disable_dcc
)
1179 if (!dcc_support_pixel_format(input
->format
,
1183 if (!dcc_support_swizzle(input
->swizzle_mode
, bpe
,
1184 &segment_order_horz
, &segment_order_vert
))
1187 det_request_size(input
->surface_size
.height
, input
->surface_size
.width
,
1188 bpe
, &req128_horz_wc
, &req128_vert_wc
);
1190 if (!req128_horz_wc
&& !req128_vert_wc
) {
1191 dcc_control
= dcc_control__256_256_xxx
;
1192 } else if (input
->scan
== SCAN_DIRECTION_HORIZONTAL
) {
1193 if (!req128_horz_wc
)
1194 dcc_control
= dcc_control__256_256_xxx
;
1195 else if (segment_order_horz
== segment_order__contiguous
)
1196 dcc_control
= dcc_control__128_128_xxx
;
1198 dcc_control
= dcc_control__256_64_64
;
1199 } else if (input
->scan
== SCAN_DIRECTION_VERTICAL
) {
1200 if (!req128_vert_wc
)
1201 dcc_control
= dcc_control__256_256_xxx
;
1202 else if (segment_order_vert
== segment_order__contiguous
)
1203 dcc_control
= dcc_control__128_128_xxx
;
1205 dcc_control
= dcc_control__256_64_64
;
1207 if ((req128_horz_wc
&&
1208 segment_order_horz
== segment_order__non_contiguous
) ||
1210 segment_order_vert
== segment_order__non_contiguous
))
1211 /* access_dir not known, must use most constraining */
1212 dcc_control
= dcc_control__256_64_64
;
1214 /* reg128 is true for either horz and vert
1215 * but segment_order is contiguous
1217 dcc_control
= dcc_control__128_128_xxx
;
1220 switch (dcc_control
) {
1221 case dcc_control__256_256_xxx
:
1222 output
->grph
.rgb
.max_uncompressed_blk_size
= 256;
1223 output
->grph
.rgb
.max_compressed_blk_size
= 256;
1224 output
->grph
.rgb
.independent_64b_blks
= false;
1226 case dcc_control__128_128_xxx
:
1227 output
->grph
.rgb
.max_uncompressed_blk_size
= 128;
1228 output
->grph
.rgb
.max_compressed_blk_size
= 128;
1229 output
->grph
.rgb
.independent_64b_blks
= false;
1231 case dcc_control__256_64_64
:
1232 output
->grph
.rgb
.max_uncompressed_blk_size
= 256;
1233 output
->grph
.rgb
.max_compressed_blk_size
= 64;
1234 output
->grph
.rgb
.independent_64b_blks
= true;
1237 output
->capable
= true;
1238 output
->const_color_support
= false;
1244 static void dcn10_destroy_resource_pool(struct resource_pool
**pool
)
1246 struct dcn10_resource_pool
*dcn10_pool
= TO_DCN10_RES_POOL(*pool
);
1248 destruct(dcn10_pool
);
1249 dm_free(dcn10_pool
);
1254 static struct dc_cap_funcs cap_funcs
= {
1255 .get_dcc_compression_cap
= get_dcc_compression_cap
1258 static struct resource_funcs dcn10_res_pool_funcs
= {
1259 .destroy
= dcn10_destroy_resource_pool
,
1260 .link_enc_create
= dcn10_link_encoder_create
,
1261 .validate_with_context
= dcn10_validate_with_context
,
1262 .validate_guaranteed
= dcn10_validate_guaranteed
,
1263 .validate_bandwidth
= dcn_validate_bandwidth
,
1264 .acquire_idle_pipe_for_layer
= dcn10_acquire_idle_pipe_for_layer
,
1267 static bool construct(
1268 uint8_t num_virtual_links
,
1270 struct dcn10_resource_pool
*pool
)
1273 struct dc_context
*ctx
= dc
->ctx
;
1275 ctx
->dc_bios
->regs
= &bios_regs
;
1277 pool
->base
.res_cap
= &res_cap
;
1278 pool
->base
.funcs
= &dcn10_res_pool_funcs
;
1281 * TODO fill in from actual raven resource when we create
1282 * more than virtual encoder
1285 /*************************************************
1286 * Resource + asic cap harcoding *
1287 *************************************************/
1288 pool
->base
.underlay_pipe_index
= NO_UNDERLAY_PIPE
;
1290 /* TODO: Hardcode to correct number of functional controllers */
1291 pool
->base
.pipe_count
= 4;
1292 dc
->public.caps
.max_downscale_ratio
= 200;
1293 dc
->public.caps
.i2c_speed_in_khz
= 100;
1294 dc
->public.caps
.max_cursor_size
= 256;
1296 dc
->public.caps
.max_slave_planes
= 1;
1298 if (dc
->ctx
->dce_environment
== DCE_ENV_PRODUCTION_DRV
)
1299 dc
->public.debug
= debug_defaults_drv
;
1301 dc
->public.debug
= debug_defaults_diags
;
1303 /*************************************************
1304 * Create resources *
1305 *************************************************/
1307 pool
->base
.clock_sources
[DCN10_CLK_SRC_PLL0
] =
1308 dcn10_clock_source_create(ctx
, ctx
->dc_bios
,
1309 CLOCK_SOURCE_COMBO_PHY_PLL0
,
1310 &clk_src_regs
[0], false);
1311 pool
->base
.clock_sources
[DCN10_CLK_SRC_PLL1
] =
1312 dcn10_clock_source_create(ctx
, ctx
->dc_bios
,
1313 CLOCK_SOURCE_COMBO_PHY_PLL1
,
1314 &clk_src_regs
[1], false);
1315 pool
->base
.clock_sources
[DCN10_CLK_SRC_PLL2
] =
1316 dcn10_clock_source_create(ctx
, ctx
->dc_bios
,
1317 CLOCK_SOURCE_COMBO_PHY_PLL2
,
1318 &clk_src_regs
[2], false);
1319 pool
->base
.clock_sources
[DCN10_CLK_SRC_PLL3
] =
1320 dcn10_clock_source_create(ctx
, ctx
->dc_bios
,
1321 CLOCK_SOURCE_COMBO_PHY_PLL3
,
1322 &clk_src_regs
[3], false);
1324 pool
->base
.clk_src_count
= DCN10_CLK_SRC_TOTAL
;
1326 pool
->base
.dp_clock_source
=
1327 dcn10_clock_source_create(ctx
, ctx
->dc_bios
,
1328 CLOCK_SOURCE_ID_DP_DTO
,
1329 /* todo: not reuse phy_pll registers */
1330 &clk_src_regs
[0], true);
1332 for (i
= 0; i
< pool
->base
.clk_src_count
; i
++) {
1333 if (pool
->base
.clock_sources
[i
] == NULL
) {
1334 dm_error("DC: failed to create clock sources!\n");
1335 BREAK_TO_DEBUGGER();
1336 goto clock_source_create_fail
;
1340 if (!IS_FPGA_MAXIMUS_DC(dc
->ctx
->dce_environment
)) {
1341 pool
->base
.display_clock
= dce120_disp_clk_create(ctx
,
1345 if (pool
->base
.display_clock
== NULL
) {
1346 dm_error("DC: failed to create display clock!\n");
1347 BREAK_TO_DEBUGGER();
1348 goto disp_clk_create_fail
;
1352 pool
->base
.dmcu
= dcn10_dmcu_create(ctx
,
1356 if (pool
->base
.dmcu
== NULL
) {
1357 dm_error("DC: failed to create dmcu!\n");
1358 BREAK_TO_DEBUGGER();
1359 goto res_create_fail
;
1362 pool
->base
.abm
= dce_abm_create(ctx
,
1366 if (pool
->base
.abm
== NULL
) {
1367 dm_error("DC: failed to create abm!\n");
1368 BREAK_TO_DEBUGGER();
1369 goto res_create_fail
;
1372 dml_init_instance(&dc
->dml
, DML_PROJECT_RAVEN1
);
1373 dc
->dcn_ip
= dcn10_ip_defaults
;
1374 dc
->dcn_soc
= dcn10_soc_defaults
;
1375 if (!dc
->public.debug
.disable_pplib_clock_request
)
1376 dcn_bw_update_from_pplib(dc
);
1377 dcn_bw_sync_calcs_and_dml(dc
);
1378 if (!dc
->public.debug
.disable_pplib_wm_range
)
1379 dcn_bw_notify_pplib_of_wm_ranges(dc
);
1382 #if defined(CONFIG_DRM_AMD_DC_DCN1_0)
1383 struct irq_service_init_data init_data
;
1384 init_data
.ctx
= dc
->ctx
;
1385 pool
->base
.irqs
= dal_irq_service_dcn10_create(&init_data
);
1386 if (!pool
->base
.irqs
)
1387 goto irqs_create_fail
;
1391 /* mem input -> ipp -> transform -> opp -> TG */
1392 for (i
= 0; i
< pool
->base
.pipe_count
; i
++) {
1393 pool
->base
.mis
[i
] = dcn10_mem_input_create(ctx
, i
);
1394 if (pool
->base
.mis
[i
] == NULL
) {
1395 BREAK_TO_DEBUGGER();
1397 "DC: failed to create memory input!\n");
1398 goto mi_create_fail
;
1401 pool
->base
.ipps
[i
] = dcn10_ipp_create(ctx
, i
);
1402 if (pool
->base
.ipps
[i
] == NULL
) {
1403 BREAK_TO_DEBUGGER();
1405 "DC: failed to create input pixel processor!\n");
1406 goto ipp_create_fail
;
1409 pool
->base
.transforms
[i
] = dcn10_transform_create(ctx
, i
);
1410 if (pool
->base
.transforms
[i
] == NULL
) {
1411 BREAK_TO_DEBUGGER();
1413 "DC: failed to create transform!\n");
1414 goto transform_create_fail
;
1417 pool
->base
.opps
[i
] = dcn10_opp_create(ctx
, i
);
1418 if (pool
->base
.opps
[i
] == NULL
) {
1419 BREAK_TO_DEBUGGER();
1421 "DC: failed to create output pixel processor!\n");
1422 goto opp_create_fail
;
1425 pool
->base
.timing_generators
[i
] = dcn10_timing_generator_create(
1427 if (pool
->base
.timing_generators
[i
] == NULL
) {
1428 BREAK_TO_DEBUGGER();
1429 dm_error("DC: failed to create tg!\n");
1430 goto otg_create_fail
;
1432 pool
->base
.mpcc
[i
] = dcn10_mpcc_create(ctx
, i
);
1433 if (pool
->base
.mpcc
[i
] == NULL
) {
1434 BREAK_TO_DEBUGGER();
1435 dm_error("DC: failed to create mpcc!\n");
1436 goto mpcc_create_fail
;
1440 if (!resource_construct(num_virtual_links
, dc
, &pool
->base
,
1441 (!IS_FPGA_MAXIMUS_DC(dc
->ctx
->dce_environment
) ?
1442 &res_create_funcs
: &res_create_maximus_funcs
)))
1443 goto res_create_fail
;
1445 dcn10_hw_sequencer_construct(dc
);
1446 dc
->public.caps
.max_surfaces
= pool
->base
.pipe_count
;
1448 dc
->public.cap_funcs
= cap_funcs
;
1452 disp_clk_create_fail
:
1456 transform_create_fail
:
1461 clock_source_create_fail
:
1468 struct resource_pool
*dcn10_create_resource_pool(
1469 uint8_t num_virtual_links
,
1472 struct dcn10_resource_pool
*pool
=
1473 dm_alloc(sizeof(struct dcn10_resource_pool
));
1478 if (construct(num_virtual_links
, dc
, pool
))
1481 BREAK_TO_DEBUGGER();