aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd
diff options
context:
space:
mode:
authorJerry (Fangzhi) Zuo <Jerry.Zuo@amd.com>2018-03-05 16:12:23 -0500
committerAlex Deucher <alexander.deucher@amd.com>2018-05-17 11:13:21 -0400
commit8ad63122f9f22dde172b98fe9c75818831e57f4b (patch)
treeb23f5245ead6a586d37afb78795a6edf862fbd31 /drivers/gpu/drm/amd
parent1edb2c8a32160c00273485efea8d18080e31cc09 (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.c208
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
818static 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
826static 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
1013irqs_create_fail:
1014controller_create_fail:
1015disp_clk_create_fail:
1016clk_src_create_fail:
1017res_create_fail:
1018
1019 destruct(pool);
1020
1021 return false;
1022}
1023#else
817static bool construct( 1024static 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
992struct resource_pool *dce120_create_resource_pool( 1200struct resource_pool *dce120_create_resource_pool(
993 uint8_t num_virtual_links, 1201 uint8_t num_virtual_links,