diff options
author | Jerry (Fangzhi) Zuo <Jerry.Zuo@amd.com> | 2018-03-05 16:12:23 -0500 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2018-05-17 11:13:21 -0400 |
commit | 8ad63122f9f22dde172b98fe9c75818831e57f4b (patch) | |
tree | b23f5245ead6a586d37afb78795a6edf862fbd31 /drivers/gpu/drm/amd | |
parent | 1edb2c8a32160c00273485efea8d18080e31cc09 (diff) |
drm/amd/display: Add harvest IP support for Vega20
Retrieve fuses to determine the availability of pipes, and
eliminate pipes that cannot be used.
Acked-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Jerry (Fangzhi) Zuo <Jerry.Zuo@amd.com>
Reviewed-by: Hersen Wu <hersenxs.wu@amd.com>
Reviewed-by: Tony Cheng <Tony.Cheng@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Feifei Xu <Feifei.Xu@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd')
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index fda01574d1ba..545f35f0821f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c | |||
@@ -814,6 +814,213 @@ static void bw_calcs_data_update_from_pplib(struct dc *dc) | |||
814 | dm_pp_notify_wm_clock_changes(dc->ctx, &clk_ranges); | 814 | dm_pp_notify_wm_clock_changes(dc->ctx, &clk_ranges); |
815 | } | 815 | } |
816 | 816 | ||
817 | #ifdef CONFIG_DRM_AMD_DC_VG20 | ||
818 | static uint32_t read_pipe_fuses(struct dc_context *ctx) | ||
819 | { | ||
820 | uint32_t value = dm_read_reg_soc15(ctx, mmCC_DC_PIPE_DIS, 0); | ||
821 | /* VG20 support max 6 pipes */ | ||
822 | value = value & 0x3f; | ||
823 | return value; | ||
824 | } | ||
825 | |||
826 | static bool construct( | ||
827 | uint8_t num_virtual_links, | ||
828 | struct dc *dc, | ||
829 | struct dce110_resource_pool *pool) | ||
830 | { | ||
831 | unsigned int i; | ||
832 | int j; | ||
833 | struct dc_context *ctx = dc->ctx; | ||
834 | struct irq_service_init_data irq_init_data; | ||
835 | bool harvest_enabled = ASICREV_IS_VEGA20_P(ctx->asic_id.hw_internal_rev); | ||
836 | uint32_t pipe_fuses; | ||
837 | |||
838 | ctx->dc_bios->regs = &bios_regs; | ||
839 | |||
840 | pool->base.res_cap = &res_cap; | ||
841 | pool->base.funcs = &dce120_res_pool_funcs; | ||
842 | |||
843 | /* TODO: Fill more data from GreenlandAsicCapability.cpp */ | ||
844 | pool->base.pipe_count = res_cap.num_timing_generator; | ||
845 | pool->base.timing_generator_count = pool->base.res_cap->num_timing_generator; | ||
846 | pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE; | ||
847 | |||
848 | dc->caps.max_downscale_ratio = 200; | ||
849 | dc->caps.i2c_speed_in_khz = 100; | ||
850 | dc->caps.max_cursor_size = 128; | ||
851 | dc->caps.dual_link_dvi = true; | ||
852 | |||
853 | dc->debug = debug_defaults; | ||
854 | |||
855 | /************************************************* | ||
856 | * Create resources * | ||
857 | *************************************************/ | ||
858 | |||
859 | pool->base.clock_sources[DCE120_CLK_SRC_PLL0] = | ||
860 | dce120_clock_source_create(ctx, ctx->dc_bios, | ||
861 | CLOCK_SOURCE_COMBO_PHY_PLL0, | ||
862 | &clk_src_regs[0], false); | ||
863 | pool->base.clock_sources[DCE120_CLK_SRC_PLL1] = | ||
864 | dce120_clock_source_create(ctx, ctx->dc_bios, | ||
865 | CLOCK_SOURCE_COMBO_PHY_PLL1, | ||
866 | &clk_src_regs[1], false); | ||
867 | pool->base.clock_sources[DCE120_CLK_SRC_PLL2] = | ||
868 | dce120_clock_source_create(ctx, ctx->dc_bios, | ||
869 | CLOCK_SOURCE_COMBO_PHY_PLL2, | ||
870 | &clk_src_regs[2], false); | ||
871 | pool->base.clock_sources[DCE120_CLK_SRC_PLL3] = | ||
872 | dce120_clock_source_create(ctx, ctx->dc_bios, | ||
873 | CLOCK_SOURCE_COMBO_PHY_PLL3, | ||
874 | &clk_src_regs[3], false); | ||
875 | pool->base.clock_sources[DCE120_CLK_SRC_PLL4] = | ||
876 | dce120_clock_source_create(ctx, ctx->dc_bios, | ||
877 | CLOCK_SOURCE_COMBO_PHY_PLL4, | ||
878 | &clk_src_regs[4], false); | ||
879 | pool->base.clock_sources[DCE120_CLK_SRC_PLL5] = | ||
880 | dce120_clock_source_create(ctx, ctx->dc_bios, | ||
881 | CLOCK_SOURCE_COMBO_PHY_PLL5, | ||
882 | &clk_src_regs[5], false); | ||
883 | pool->base.clk_src_count = DCE120_CLK_SRC_TOTAL; | ||
884 | |||
885 | pool->base.dp_clock_source = | ||
886 | dce120_clock_source_create(ctx, ctx->dc_bios, | ||
887 | CLOCK_SOURCE_ID_DP_DTO, | ||
888 | &clk_src_regs[0], true); | ||
889 | |||
890 | for (i = 0; i < pool->base.clk_src_count; i++) { | ||
891 | if (pool->base.clock_sources[i] == NULL) { | ||
892 | dm_error("DC: failed to create clock sources!\n"); | ||
893 | BREAK_TO_DEBUGGER(); | ||
894 | goto clk_src_create_fail; | ||
895 | } | ||
896 | } | ||
897 | |||
898 | pool->base.display_clock = dce120_disp_clk_create(ctx); | ||
899 | if (pool->base.display_clock == NULL) { | ||
900 | dm_error("DC: failed to create display clock!\n"); | ||
901 | BREAK_TO_DEBUGGER(); | ||
902 | goto disp_clk_create_fail; | ||
903 | } | ||
904 | |||
905 | pool->base.dmcu = dce_dmcu_create(ctx, | ||
906 | &dmcu_regs, | ||
907 | &dmcu_shift, | ||
908 | &dmcu_mask); | ||
909 | if (pool->base.dmcu == NULL) { | ||
910 | dm_error("DC: failed to create dmcu!\n"); | ||
911 | BREAK_TO_DEBUGGER(); | ||
912 | goto res_create_fail; | ||
913 | } | ||
914 | |||
915 | pool->base.abm = dce_abm_create(ctx, | ||
916 | &abm_regs, | ||
917 | &abm_shift, | ||
918 | &abm_mask); | ||
919 | if (pool->base.abm == NULL) { | ||
920 | dm_error("DC: failed to create abm!\n"); | ||
921 | BREAK_TO_DEBUGGER(); | ||
922 | goto res_create_fail; | ||
923 | } | ||
924 | |||
925 | irq_init_data.ctx = dc->ctx; | ||
926 | pool->base.irqs = dal_irq_service_dce120_create(&irq_init_data); | ||
927 | if (!pool->base.irqs) | ||
928 | goto irqs_create_fail; | ||
929 | |||
930 | /* retrieve valid pipe fuses */ | ||
931 | if (harvest_enabled) | ||
932 | pipe_fuses = read_pipe_fuses(ctx); | ||
933 | |||
934 | /* index to valid pipe resource */ | ||
935 | j = 0; | ||
936 | for (i = 0; i < pool->base.pipe_count; i++) { | ||
937 | if (harvest_enabled) { | ||
938 | if ((pipe_fuses & (1 << i)) != 0) { | ||
939 | dm_error("DC: skip invalid pipe %d!\n", i); | ||
940 | continue; | ||
941 | } | ||
942 | } | ||
943 | |||
944 | pool->base.timing_generators[j] = | ||
945 | dce120_timing_generator_create( | ||
946 | ctx, | ||
947 | i, | ||
948 | &dce120_tg_offsets[i]); | ||
949 | if (pool->base.timing_generators[j] == NULL) { | ||
950 | BREAK_TO_DEBUGGER(); | ||
951 | dm_error("DC: failed to create tg!\n"); | ||
952 | goto controller_create_fail; | ||
953 | } | ||
954 | |||
955 | pool->base.mis[j] = dce120_mem_input_create(ctx, i); | ||
956 | |||
957 | if (pool->base.mis[j] == NULL) { | ||
958 | BREAK_TO_DEBUGGER(); | ||
959 | dm_error( | ||
960 | "DC: failed to create memory input!\n"); | ||
961 | goto controller_create_fail; | ||
962 | } | ||
963 | |||
964 | pool->base.ipps[j] = dce120_ipp_create(ctx, i); | ||
965 | if (pool->base.ipps[i] == NULL) { | ||
966 | BREAK_TO_DEBUGGER(); | ||
967 | dm_error( | ||
968 | "DC: failed to create input pixel processor!\n"); | ||
969 | goto controller_create_fail; | ||
970 | } | ||
971 | |||
972 | pool->base.transforms[j] = dce120_transform_create(ctx, i); | ||
973 | if (pool->base.transforms[i] == NULL) { | ||
974 | BREAK_TO_DEBUGGER(); | ||
975 | dm_error( | ||
976 | "DC: failed to create transform!\n"); | ||
977 | goto res_create_fail; | ||
978 | } | ||
979 | |||
980 | pool->base.opps[j] = dce120_opp_create( | ||
981 | ctx, | ||
982 | i); | ||
983 | if (pool->base.opps[j] == NULL) { | ||
984 | BREAK_TO_DEBUGGER(); | ||
985 | dm_error( | ||
986 | "DC: failed to create output pixel processor!\n"); | ||
987 | } | ||
988 | |||
989 | /* check next valid pipe */ | ||
990 | j++; | ||
991 | } | ||
992 | |||
993 | /* valid pipe num */ | ||
994 | pool->base.pipe_count = j; | ||
995 | pool->base.timing_generator_count = j; | ||
996 | |||
997 | if (!resource_construct(num_virtual_links, dc, &pool->base, | ||
998 | &res_create_funcs)) | ||
999 | goto res_create_fail; | ||
1000 | |||
1001 | /* Create hardware sequencer */ | ||
1002 | if (!dce120_hw_sequencer_create(dc)) | ||
1003 | goto controller_create_fail; | ||
1004 | |||
1005 | dc->caps.max_planes = pool->base.pipe_count; | ||
1006 | |||
1007 | bw_calcs_init(dc->bw_dceip, dc->bw_vbios, dc->ctx->asic_id); | ||
1008 | |||
1009 | bw_calcs_data_update_from_pplib(dc); | ||
1010 | |||
1011 | return true; | ||
1012 | |||
1013 | irqs_create_fail: | ||
1014 | controller_create_fail: | ||
1015 | disp_clk_create_fail: | ||
1016 | clk_src_create_fail: | ||
1017 | res_create_fail: | ||
1018 | |||
1019 | destruct(pool); | ||
1020 | |||
1021 | return false; | ||
1022 | } | ||
1023 | #else | ||
817 | static bool construct( | 1024 | static bool construct( |
818 | uint8_t num_virtual_links, | 1025 | uint8_t num_virtual_links, |
819 | struct dc *dc, | 1026 | struct dc *dc, |
@@ -988,6 +1195,7 @@ res_create_fail: | |||
988 | 1195 | ||
989 | return false; | 1196 | return false; |
990 | } | 1197 | } |
1198 | #endif | ||
991 | 1199 | ||
992 | struct resource_pool *dce120_create_resource_pool( | 1200 | struct resource_pool *dce120_create_resource_pool( |
993 | uint8_t num_virtual_links, | 1201 | uint8_t num_virtual_links, |