diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc')
114 files changed, 5574 insertions, 1685 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/Makefile b/drivers/gpu/drm/amd/display/dc/Makefile index bbde6e6a4e43..505158a5fcc1 100644 --- a/drivers/gpu/drm/amd/display/dc/Makefile +++ b/drivers/gpu/drm/amd/display/dc/Makefile @@ -33,6 +33,7 @@ DC_LIBS += dcn21 DC_LIBS += dcn30 DC_LIBS += dcn301 DC_LIBS += dcn302 +DC_LIBS += dcn303 endif DC_LIBS += dce120 @@ -54,8 +55,9 @@ AMD_DC = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DISPLAY_PATH)/dc/,$(DC_LI include $(AMD_DC) -DISPLAY_CORE = dc.o dc_stat.o dc_link.o dc_resource.o dc_hw_sequencer.o dc_sink.o \ -dc_surface.o dc_link_hwss.o dc_link_dp.o dc_link_ddc.o dc_debug.o dc_stream.o +DISPLAY_CORE = dc.o dc_stat.o dc_link.o dc_resource.o dc_hw_sequencer.o dc_sink.o \ +dc_surface.o dc_link_hwss.o dc_link_dp.o dc_link_ddc.o dc_debug.o dc_stream.o \ +dc_link_enc_cfg.o ifdef CONFIG_DRM_AMD_DC_DCN DISPLAY_CORE += dc_vm_helper.o diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index b208f06ed514..49126a0f66af 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -836,8 +836,10 @@ static enum bp_result bios_parser_get_spread_spectrum_info( return get_ss_info_v4_1(bp, signal, index, ss_info); case 2: case 3: + case 4: return get_ss_info_v4_2(bp, signal, index, ss_info); default: + ASSERT(0); break; } break; @@ -916,6 +918,192 @@ static enum bp_result bios_parser_get_soc_bb_info( return result; } +static enum bp_result get_disp_caps_v4_1( + struct bios_parser *bp, + uint8_t *dce_caps) +{ + enum bp_result result = BP_RESULT_OK; + struct atom_display_controller_info_v4_1 *disp_cntl_tbl = NULL; + + if (!dce_caps) + return BP_RESULT_BADINPUT; + + if (!DATA_TABLES(dce_info)) + return BP_RESULT_BADBIOSTABLE; + + disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_1, + DATA_TABLES(dce_info)); + + if (!disp_cntl_tbl) + return BP_RESULT_BADBIOSTABLE; + + *dce_caps = disp_cntl_tbl->display_caps; + + return result; +} + +static enum bp_result get_disp_caps_v4_2( + struct bios_parser *bp, + uint8_t *dce_caps) +{ + enum bp_result result = BP_RESULT_OK; + struct atom_display_controller_info_v4_2 *disp_cntl_tbl = NULL; + + if (!dce_caps) + return BP_RESULT_BADINPUT; + + if (!DATA_TABLES(dce_info)) + return BP_RESULT_BADBIOSTABLE; + + disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_2, + DATA_TABLES(dce_info)); + + if (!disp_cntl_tbl) + return BP_RESULT_BADBIOSTABLE; + + *dce_caps = disp_cntl_tbl->display_caps; + + return result; +} + +static enum bp_result get_disp_caps_v4_3( + struct bios_parser *bp, + uint8_t *dce_caps) +{ + enum bp_result result = BP_RESULT_OK; + struct atom_display_controller_info_v4_3 *disp_cntl_tbl = NULL; + + if (!dce_caps) + return BP_RESULT_BADINPUT; + + if (!DATA_TABLES(dce_info)) + return BP_RESULT_BADBIOSTABLE; + + disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_3, + DATA_TABLES(dce_info)); + + if (!disp_cntl_tbl) + return BP_RESULT_BADBIOSTABLE; + + *dce_caps = disp_cntl_tbl->display_caps; + + return result; +} + +static enum bp_result get_disp_caps_v4_4( + struct bios_parser *bp, + uint8_t *dce_caps) +{ + enum bp_result result = BP_RESULT_OK; + struct atom_display_controller_info_v4_4 *disp_cntl_tbl = NULL; + + if (!dce_caps) + return BP_RESULT_BADINPUT; + + if (!DATA_TABLES(dce_info)) + return BP_RESULT_BADBIOSTABLE; + + disp_cntl_tbl = GET_IMAGE(struct atom_display_controller_info_v4_4, + DATA_TABLES(dce_info)); + + if (!disp_cntl_tbl) + return BP_RESULT_BADBIOSTABLE; + + *dce_caps = disp_cntl_tbl->display_caps; + + return result; +} + +static enum bp_result bios_parser_get_lttpr_interop( + struct dc_bios *dcb, + uint8_t *dce_caps) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + enum bp_result result = BP_RESULT_UNSUPPORTED; + struct atom_common_table_header *header; + struct atom_data_revision tbl_revision; + + if (!DATA_TABLES(dce_info)) + return BP_RESULT_UNSUPPORTED; + + header = GET_IMAGE(struct atom_common_table_header, + DATA_TABLES(dce_info)); + get_atom_data_table_revision(header, &tbl_revision); + switch (tbl_revision.major) { + case 4: + switch (tbl_revision.minor) { + case 1: + result = get_disp_caps_v4_1(bp, dce_caps); + *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE); + break; + case 2: + result = get_disp_caps_v4_2(bp, dce_caps); + *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE); + break; + case 3: + result = get_disp_caps_v4_3(bp, dce_caps); + *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE); + break; + case 4: + result = get_disp_caps_v4_4(bp, dce_caps); + *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_VBIOS_LTTPR_TRANSPARENT_ENABLE); + break; + default: + break; + } + break; + default: + break; + } + + return result; +} + +static enum bp_result bios_parser_get_lttpr_caps( + struct dc_bios *dcb, + uint8_t *dce_caps) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + enum bp_result result = BP_RESULT_UNSUPPORTED; + struct atom_common_table_header *header; + struct atom_data_revision tbl_revision; + + if (!DATA_TABLES(dce_info)) + return BP_RESULT_UNSUPPORTED; + + header = GET_IMAGE(struct atom_common_table_header, + DATA_TABLES(dce_info)); + get_atom_data_table_revision(header, &tbl_revision); + switch (tbl_revision.major) { + case 4: + switch (tbl_revision.minor) { + case 1: + result = get_disp_caps_v4_1(bp, dce_caps); + *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE); + break; + case 2: + result = get_disp_caps_v4_2(bp, dce_caps); + *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE); + break; + case 3: + result = get_disp_caps_v4_3(bp, dce_caps); + *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE); + break; + case 4: + result = get_disp_caps_v4_4(bp, dce_caps); + *dce_caps = !!(*dce_caps & DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE); + break; + default: + break; + } + break; + default: + break; + } + + return result; +} + static enum bp_result get_embedded_panel_info_v2_1( struct bios_parser *bp, struct embedded_panel_info *info) @@ -2531,6 +2719,10 @@ static const struct dc_vbios_funcs vbios_funcs = { .get_soc_bb_info = bios_parser_get_soc_bb_info, .get_disp_connector_caps_info = bios_parser_get_disp_connector_caps_info, + + .get_lttpr_caps = bios_parser_get_lttpr_caps, + + .get_lttpr_interop = bios_parser_get_lttpr_interop, }; static bool bios_parser2_construct( diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c index 455ee2be15a3..00706b072b5f 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c @@ -73,6 +73,7 @@ bool dal_bios_parser_init_cmd_tbl_helper2( case DCN_VERSION_3_0: case DCN_VERSION_3_01: case DCN_VERSION_3_02: + case DCN_VERSION_3_03: *h = dal_cmd_tbl_helper_dce112_get_table2(); return true; #endif diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c index e633f8a51edb..1244fcb0f446 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c @@ -98,16 +98,16 @@ static void calculate_bandwidth( int32_t num_cursor_lines; int32_t i, j, k; - struct bw_fixed yclk[3]; - struct bw_fixed sclk[8]; + struct bw_fixed *yclk; + struct bw_fixed *sclk; bool d0_underlay_enable; bool d1_underlay_enable; bool fbc_enabled; bool lpt_enabled; enum bw_defines sclk_message; enum bw_defines yclk_message; - enum bw_defines tiling_mode[maximum_number_of_surfaces]; - enum bw_defines surface_type[maximum_number_of_surfaces]; + enum bw_defines *tiling_mode; + enum bw_defines *surface_type; enum bw_defines voltage; enum bw_defines pipe_check; enum bw_defines hsr_check; @@ -122,6 +122,22 @@ static void calculate_bandwidth( int32_t number_of_displays_enabled_with_margin = 0; int32_t number_of_aligned_displays_with_no_margin = 0; + yclk = kcalloc(3, sizeof(*yclk), GFP_KERNEL); + if (!yclk) + return; + + sclk = kcalloc(8, sizeof(*sclk), GFP_KERNEL); + if (!sclk) + goto free_yclk; + + tiling_mode = kcalloc(maximum_number_of_surfaces, sizeof(*tiling_mode), GFP_KERNEL); + if (!tiling_mode) + goto free_sclk; + + surface_type = kcalloc(maximum_number_of_surfaces, sizeof(*surface_type), GFP_KERNEL); + if (!surface_type) + goto free_tiling_mode; + yclk[low] = vbios->low_yclk; yclk[mid] = vbios->mid_yclk; yclk[high] = vbios->high_yclk; @@ -2013,6 +2029,14 @@ static void calculate_bandwidth( } } } + + kfree(surface_type); +free_tiling_mode: + kfree(tiling_mode); +free_yclk: + kfree(yclk); +free_sclk: + kfree(sclk); } /******************************************************************************* @@ -2022,707 +2046,719 @@ void bw_calcs_init(struct bw_calcs_dceip *bw_dceip, struct bw_calcs_vbios *bw_vbios, struct hw_asic_id asic_id) { - struct bw_calcs_dceip dceip = { 0 }; - struct bw_calcs_vbios vbios = { 0 }; + struct bw_calcs_dceip *dceip; + struct bw_calcs_vbios *vbios; enum bw_calcs_version version = bw_calcs_version_from_asic_id(asic_id); - dceip.version = version; + dceip = kzalloc(sizeof(*dceip), GFP_KERNEL); + if (!dceip) + return; + + vbios = kzalloc(sizeof(*vbios), GFP_KERNEL); + if (!vbios) { + kfree(dceip); + return; + } + + dceip->version = version; switch (version) { case BW_CALCS_VERSION_CARRIZO: - vbios.memory_type = bw_def_gddr5; - vbios.dram_channel_width_in_bits = 64; - vbios.number_of_dram_channels = asic_id.vram_width / vbios.dram_channel_width_in_bits; - vbios.number_of_dram_banks = 8; - vbios.high_yclk = bw_int_to_fixed(1600); - vbios.mid_yclk = bw_int_to_fixed(1600); - vbios.low_yclk = bw_frc_to_fixed(66666, 100); - vbios.low_sclk = bw_int_to_fixed(200); - vbios.mid1_sclk = bw_int_to_fixed(300); - vbios.mid2_sclk = bw_int_to_fixed(300); - vbios.mid3_sclk = bw_int_to_fixed(300); - vbios.mid4_sclk = bw_int_to_fixed(300); - vbios.mid5_sclk = bw_int_to_fixed(300); - vbios.mid6_sclk = bw_int_to_fixed(300); - vbios.high_sclk = bw_frc_to_fixed(62609, 100); - vbios.low_voltage_max_dispclk = bw_int_to_fixed(352); - vbios.mid_voltage_max_dispclk = bw_int_to_fixed(467); - vbios.high_voltage_max_dispclk = bw_int_to_fixed(643); - vbios.low_voltage_max_phyclk = bw_int_to_fixed(540); - vbios.mid_voltage_max_phyclk = bw_int_to_fixed(810); - vbios.high_voltage_max_phyclk = bw_int_to_fixed(810); - vbios.data_return_bus_width = bw_int_to_fixed(32); - vbios.trc = bw_int_to_fixed(50); - vbios.dmifmc_urgent_latency = bw_int_to_fixed(4); - vbios.stutter_self_refresh_exit_latency = bw_frc_to_fixed(153, 10); - vbios.stutter_self_refresh_entry_latency = bw_int_to_fixed(0); - vbios.nbp_state_change_latency = bw_frc_to_fixed(19649, 1000); - vbios.mcifwrmc_urgent_latency = bw_int_to_fixed(10); - vbios.scatter_gather_enable = true; - vbios.down_spread_percentage = bw_frc_to_fixed(5, 10); - vbios.cursor_width = 32; - vbios.average_compression_rate = 4; - vbios.number_of_request_slots_gmc_reserves_for_dmif_per_channel = 256; - vbios.blackout_duration = bw_int_to_fixed(0); /* us */ - vbios.maximum_blackout_recovery_time = bw_int_to_fixed(0); - - dceip.max_average_percent_of_ideal_port_bw_display_can_use_in_normal_system_operation = 100; - dceip.max_average_percent_of_ideal_drambw_display_can_use_in_normal_system_operation = 100; - dceip.percent_of_ideal_port_bw_received_after_urgent_latency = 100; - dceip.large_cursor = false; - dceip.dmif_request_buffer_size = bw_int_to_fixed(768); - dceip.dmif_pipe_en_fbc_chunk_tracker = false; - dceip.cursor_max_outstanding_group_num = 1; - dceip.lines_interleaved_into_lb = 2; - dceip.chunk_width = 256; - dceip.number_of_graphics_pipes = 3; - dceip.number_of_underlay_pipes = 1; - dceip.low_power_tiling_mode = 0; - dceip.display_write_back_supported = false; - dceip.argb_compression_support = false; - dceip.underlay_vscaler_efficiency6_bit_per_component = + vbios->memory_type = bw_def_gddr5; + vbios->dram_channel_width_in_bits = 64; + vbios->number_of_dram_channels = asic_id.vram_width / vbios->dram_channel_width_in_bits; + vbios->number_of_dram_banks = 8; + vbios->high_yclk = bw_int_to_fixed(1600); + vbios->mid_yclk = bw_int_to_fixed(1600); + vbios->low_yclk = bw_frc_to_fixed(66666, 100); + vbios->low_sclk = bw_int_to_fixed(200); + vbios->mid1_sclk = bw_int_to_fixed(300); + vbios->mid2_sclk = bw_int_to_fixed(300); + vbios->mid3_sclk = bw_int_to_fixed(300); + vbios->mid4_sclk = bw_int_to_fixed(300); + vbios->mid5_sclk = bw_int_to_fixed(300); + vbios->mid6_sclk = bw_int_to_fixed(300); + vbios->high_sclk = bw_frc_to_fixed(62609, 100); + vbios->low_voltage_max_dispclk = bw_int_to_fixed(352); + vbios->mid_voltage_max_dispclk = bw_int_to_fixed(467); + vbios->high_voltage_max_dispclk = bw_int_to_fixed(643); + vbios->low_voltage_max_phyclk = bw_int_to_fixed(540); + vbios->mid_voltage_max_phyclk = bw_int_to_fixed(810); + vbios->high_voltage_max_phyclk = bw_int_to_fixed(810); + vbios->data_return_bus_width = bw_int_to_fixed(32); + vbios->trc = bw_int_to_fixed(50); + vbios->dmifmc_urgent_latency = bw_int_to_fixed(4); + vbios->stutter_self_refresh_exit_latency = bw_frc_to_fixed(153, 10); + vbios->stutter_self_refresh_entry_latency = bw_int_to_fixed(0); + vbios->nbp_state_change_latency = bw_frc_to_fixed(19649, 1000); + vbios->mcifwrmc_urgent_latency = bw_int_to_fixed(10); + vbios->scatter_gather_enable = true; + vbios->down_spread_percentage = bw_frc_to_fixed(5, 10); + vbios->cursor_width = 32; + vbios->average_compression_rate = 4; + vbios->number_of_request_slots_gmc_reserves_for_dmif_per_channel = 256; + vbios->blackout_duration = bw_int_to_fixed(0); /* us */ + vbios->maximum_blackout_recovery_time = bw_int_to_fixed(0); + + dceip->max_average_percent_of_ideal_port_bw_display_can_use_in_normal_system_operation = 100; + dceip->max_average_percent_of_ideal_drambw_display_can_use_in_normal_system_operation = 100; + dceip->percent_of_ideal_port_bw_received_after_urgent_latency = 100; + dceip->large_cursor = false; + dceip->dmif_request_buffer_size = bw_int_to_fixed(768); + dceip->dmif_pipe_en_fbc_chunk_tracker = false; + dceip->cursor_max_outstanding_group_num = 1; + dceip->lines_interleaved_into_lb = 2; + dceip->chunk_width = 256; + dceip->number_of_graphics_pipes = 3; + dceip->number_of_underlay_pipes = 1; + dceip->low_power_tiling_mode = 0; + dceip->display_write_back_supported = false; + dceip->argb_compression_support = false; + dceip->underlay_vscaler_efficiency6_bit_per_component = bw_frc_to_fixed(35556, 10000); - dceip.underlay_vscaler_efficiency8_bit_per_component = + dceip->underlay_vscaler_efficiency8_bit_per_component = bw_frc_to_fixed(34286, 10000); - dceip.underlay_vscaler_efficiency10_bit_per_component = + dceip->underlay_vscaler_efficiency10_bit_per_component = bw_frc_to_fixed(32, 10); - dceip.underlay_vscaler_efficiency12_bit_per_component = + dceip->underlay_vscaler_efficiency12_bit_per_component = bw_int_to_fixed(3); - dceip.graphics_vscaler_efficiency6_bit_per_component = + dceip->graphics_vscaler_efficiency6_bit_per_component = bw_frc_to_fixed(35, 10); - dceip.graphics_vscaler_efficiency8_bit_per_component = + dceip->graphics_vscaler_efficiency8_bit_per_component = bw_frc_to_fixed(34286, 10000); - dceip.graphics_vscaler_efficiency10_bit_per_component = + dceip->graphics_vscaler_efficiency10_bit_per_component = bw_frc_to_fixed(32, 10); - dceip.graphics_vscaler_efficiency12_bit_per_component = + dceip->graphics_vscaler_efficiency12_bit_per_component = bw_int_to_fixed(3); - dceip.alpha_vscaler_efficiency = bw_int_to_fixed(3); - dceip.max_dmif_buffer_allocated = 2; - dceip.graphics_dmif_size = 12288; - dceip.underlay_luma_dmif_size = 19456; - dceip.underlay_chroma_dmif_size = 23552; - dceip.pre_downscaler_enabled = true; - dceip.underlay_downscale_prefetch_enabled = true; - dceip.lb_write_pixels_per_dispclk = bw_int_to_fixed(1); - dceip.lb_size_per_component444 = bw_int_to_fixed(82176); - dceip.graphics_lb_nodownscaling_multi_line_prefetching = false; - dceip.stutter_and_dram_clock_state_change_gated_before_cursor = + dceip->alpha_vscaler_efficiency = bw_int_to_fixed(3); + dceip->max_dmif_buffer_allocated = 2; + dceip->graphics_dmif_size = 12288; + dceip->underlay_luma_dmif_size = 19456; + dceip->underlay_chroma_dmif_size = 23552; + dceip->pre_downscaler_enabled = true; + dceip->underlay_downscale_prefetch_enabled = true; + dceip->lb_write_pixels_per_dispclk = bw_int_to_fixed(1); + dceip->lb_size_per_component444 = bw_int_to_fixed(82176); + dceip->graphics_lb_nodownscaling_multi_line_prefetching = false; + dceip->stutter_and_dram_clock_state_change_gated_before_cursor = bw_int_to_fixed(0); - dceip.underlay420_luma_lb_size_per_component = bw_int_to_fixed( + dceip->underlay420_luma_lb_size_per_component = bw_int_to_fixed( 82176); - dceip.underlay420_chroma_lb_size_per_component = + dceip->underlay420_chroma_lb_size_per_component = bw_int_to_fixed(164352); - dceip.underlay422_lb_size_per_component = bw_int_to_fixed( + dceip->underlay422_lb_size_per_component = bw_int_to_fixed( 82176); - dceip.cursor_chunk_width = bw_int_to_fixed(64); - dceip.cursor_dcp_buffer_lines = bw_int_to_fixed(4); - dceip.underlay_maximum_width_efficient_for_tiling = + dceip->cursor_chunk_width = bw_int_to_fixed(64); + dceip->cursor_dcp_buffer_lines = bw_int_to_fixed(4); + dceip->underlay_maximum_width_efficient_for_tiling = bw_int_to_fixed(1920); - dceip.underlay_maximum_height_efficient_for_tiling = + dceip->underlay_maximum_height_efficient_for_tiling = bw_int_to_fixed(1080); - dceip.peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display = + dceip->peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display = bw_frc_to_fixed(3, 10); - dceip.peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation = + dceip->peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation = bw_int_to_fixed(25); - dceip.minimum_outstanding_pte_request_limit = bw_int_to_fixed( + dceip->minimum_outstanding_pte_request_limit = bw_int_to_fixed( 2); - dceip.maximum_total_outstanding_pte_requests_allowed_by_saw = + dceip->maximum_total_outstanding_pte_requests_allowed_by_saw = bw_int_to_fixed(128); - dceip.limit_excessive_outstanding_dmif_requests = true; - dceip.linear_mode_line_request_alternation_slice = + dceip->limit_excessive_outstanding_dmif_requests = true; + dceip->linear_mode_line_request_alternation_slice = bw_int_to_fixed(64); - dceip.scatter_gather_lines_of_pte_prefetching_in_linear_mode = + dceip->scatter_gather_lines_of_pte_prefetching_in_linear_mode = 32; - dceip.display_write_back420_luma_mcifwr_buffer_size = 12288; - dceip.display_write_back420_chroma_mcifwr_buffer_size = 8192; - dceip.request_efficiency = bw_frc_to_fixed(8, 10); - dceip.dispclk_per_request = bw_int_to_fixed(2); - dceip.dispclk_ramping_factor = bw_frc_to_fixed(105, 100); - dceip.display_pipe_throughput_factor = bw_frc_to_fixed(105, 100); - dceip.scatter_gather_pte_request_rows_in_tiling_mode = 2; - dceip.mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); /* todo: this is a bug*/ + dceip->display_write_back420_luma_mcifwr_buffer_size = 12288; + dceip->display_write_back420_chroma_mcifwr_buffer_size = 8192; + dceip->request_efficiency = bw_frc_to_fixed(8, 10); + dceip->dispclk_per_request = bw_int_to_fixed(2); + dceip->dispclk_ramping_factor = bw_frc_to_fixed(105, 100); + dceip->display_pipe_throughput_factor = bw_frc_to_fixed(105, 100); + dceip->scatter_gather_pte_request_rows_in_tiling_mode = 2; + dceip->mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); /* todo: this is a bug*/ break; case BW_CALCS_VERSION_POLARIS10: /* TODO: Treat VEGAM the same as P10 for now * Need to tune the para for VEGAM if needed */ case BW_CALCS_VERSION_VEGAM: - vbios.memory_type = bw_def_gddr5; - vbios.dram_channel_width_in_bits = 32; - vbios.number_of_dram_channels = asic_id.vram_width / vbios.dram_channel_width_in_bits; - vbios.number_of_dram_banks = 8; - vbios.high_yclk = bw_int_to_fixed(6000); - vbios.mid_yclk = bw_int_to_fixed(3200); - vbios.low_yclk = bw_int_to_fixed(1000); - vbios.low_sclk = bw_int_to_fixed(300); - vbios.mid1_sclk = bw_int_to_fixed(400); - vbios.mid2_sclk = bw_int_to_fixed(500); - vbios.mid3_sclk = bw_int_to_fixed(600); - vbios.mid4_sclk = bw_int_to_fixed(700); - vbios.mid5_sclk = bw_int_to_fixed(800); - vbios.mid6_sclk = bw_int_to_fixed(974); - vbios.high_sclk = bw_int_to_fixed(1154); - vbios.low_voltage_max_dispclk = bw_int_to_fixed(459); - vbios.mid_voltage_max_dispclk = bw_int_to_fixed(654); - vbios.high_voltage_max_dispclk = bw_int_to_fixed(1108); - vbios.low_voltage_max_phyclk = bw_int_to_fixed(540); - vbios.mid_voltage_max_phyclk = bw_int_to_fixed(810); - vbios.high_voltage_max_phyclk = bw_int_to_fixed(810); - vbios.data_return_bus_width = bw_int_to_fixed(32); - vbios.trc = bw_int_to_fixed(48); - vbios.dmifmc_urgent_latency = bw_int_to_fixed(3); - vbios.stutter_self_refresh_exit_latency = bw_int_to_fixed(5); - vbios.stutter_self_refresh_entry_latency = bw_int_to_fixed(0); - vbios.nbp_state_change_latency = bw_int_to_fixed(45); - vbios.mcifwrmc_urgent_latency = bw_int_to_fixed(10); - vbios.scatter_gather_enable = true; - vbios.down_spread_percentage = bw_frc_to_fixed(5, 10); - vbios.cursor_width = 32; - vbios.average_compression_rate = 4; - vbios.number_of_request_slots_gmc_reserves_for_dmif_per_channel = 256; - vbios.blackout_duration = bw_int_to_fixed(0); /* us */ - vbios.maximum_blackout_recovery_time = bw_int_to_fixed(0); - - dceip.max_average_percent_of_ideal_port_bw_display_can_use_in_normal_system_operation = 100; - dceip.max_average_percent_of_ideal_drambw_display_can_use_in_normal_system_operation = 100; - dceip.percent_of_ideal_port_bw_received_after_urgent_latency = 100; - dceip.large_cursor = false; - dceip.dmif_request_buffer_size = bw_int_to_fixed(768); - dceip.dmif_pipe_en_fbc_chunk_tracker = false; - dceip.cursor_max_outstanding_group_num = 1; - dceip.lines_interleaved_into_lb = 2; - dceip.chunk_width = 256; - dceip.number_of_graphics_pipes = 6; - dceip.number_of_underlay_pipes = 0; - dceip.low_power_tiling_mode = 0; - dceip.display_write_back_supported = false; - dceip.argb_compression_support = true; - dceip.underlay_vscaler_efficiency6_bit_per_component = + vbios->memory_type = bw_def_gddr5; + vbios->dram_channel_width_in_bits = 32; + vbios->number_of_dram_channels = asic_id.vram_width / vbios->dram_channel_width_in_bits; + vbios->number_of_dram_banks = 8; + vbios->high_yclk = bw_int_to_fixed(6000); + vbios->mid_yclk = bw_int_to_fixed(3200); + vbios->low_yclk = bw_int_to_fixed(1000); + vbios->low_sclk = bw_int_to_fixed(300); + vbios->mid1_sclk = bw_int_to_fixed(400); + vbios->mid2_sclk = bw_int_to_fixed(500); + vbios->mid3_sclk = bw_int_to_fixed(600); + vbios->mid4_sclk = bw_int_to_fixed(700); + vbios->mid5_sclk = bw_int_to_fixed(800); + vbios->mid6_sclk = bw_int_to_fixed(974); + vbios->high_sclk = bw_int_to_fixed(1154); + vbios->low_voltage_max_dispclk = bw_int_to_fixed(459); + vbios->mid_voltage_max_dispclk = bw_int_to_fixed(654); + vbios->high_voltage_max_dispclk = bw_int_to_fixed(1108); + vbios->low_voltage_max_phyclk = bw_int_to_fixed(540); + vbios->mid_voltage_max_phyclk = bw_int_to_fixed(810); + vbios->high_voltage_max_phyclk = bw_int_to_fixed(810); + vbios->data_return_bus_width = bw_int_to_fixed(32); + vbios->trc = bw_int_to_fixed(48); + vbios->dmifmc_urgent_latency = bw_int_to_fixed(3); + vbios->stutter_self_refresh_exit_latency = bw_int_to_fixed(5); + vbios->stutter_self_refresh_entry_latency = bw_int_to_fixed(0); + vbios->nbp_state_change_latency = bw_int_to_fixed(45); + vbios->mcifwrmc_urgent_latency = bw_int_to_fixed(10); + vbios->scatter_gather_enable = true; + vbios->down_spread_percentage = bw_frc_to_fixed(5, 10); + vbios->cursor_width = 32; + vbios->average_compression_rate = 4; + vbios->number_of_request_slots_gmc_reserves_for_dmif_per_channel = 256; + vbios->blackout_duration = bw_int_to_fixed(0); /* us */ + vbios->maximum_blackout_recovery_time = bw_int_to_fixed(0); + + dceip->max_average_percent_of_ideal_port_bw_display_can_use_in_normal_system_operation = 100; + dceip->max_average_percent_of_ideal_drambw_display_can_use_in_normal_system_operation = 100; + dceip->percent_of_ideal_port_bw_received_after_urgent_latency = 100; + dceip->large_cursor = false; + dceip->dmif_request_buffer_size = bw_int_to_fixed(768); + dceip->dmif_pipe_en_fbc_chunk_tracker = false; + dceip->cursor_max_outstanding_group_num = 1; + dceip->lines_interleaved_into_lb = 2; + dceip->chunk_width = 256; + dceip->number_of_graphics_pipes = 6; + dceip->number_of_underlay_pipes = 0; + dceip->low_power_tiling_mode = 0; + dceip->display_write_back_supported = false; + dceip->argb_compression_support = true; + dceip->underlay_vscaler_efficiency6_bit_per_component = bw_frc_to_fixed(35556, 10000); - dceip.underlay_vscaler_efficiency8_bit_per_component = + dceip->underlay_vscaler_efficiency8_bit_per_component = bw_frc_to_fixed(34286, 10000); - dceip.underlay_vscaler_efficiency10_bit_per_component = + dceip->underlay_vscaler_efficiency10_bit_per_component = bw_frc_to_fixed(32, 10); - dceip.underlay_vscaler_efficiency12_bit_per_component = + dceip->underlay_vscaler_efficiency12_bit_per_component = bw_int_to_fixed(3); - dceip.graphics_vscaler_efficiency6_bit_per_component = + dceip->graphics_vscaler_efficiency6_bit_per_component = bw_frc_to_fixed(35, 10); - dceip.graphics_vscaler_efficiency8_bit_per_component = + dceip->graphics_vscaler_efficiency8_bit_per_component = bw_frc_to_fixed(34286, 10000); - dceip.graphics_vscaler_efficiency10_bit_per_component = + dceip->graphics_vscaler_efficiency10_bit_per_component = bw_frc_to_fixed(32, 10); - dceip.graphics_vscaler_efficiency12_bit_per_component = + dceip->graphics_vscaler_efficiency12_bit_per_component = bw_int_to_fixed(3); - dceip.alpha_vscaler_efficiency = bw_int_to_fixed(3); - dceip.max_dmif_buffer_allocated = 4; - dceip.graphics_dmif_size = 12288; - dceip.underlay_luma_dmif_size = 19456; - dceip.underlay_chroma_dmif_size = 23552; - dceip.pre_downscaler_enabled = true; - dceip.underlay_downscale_prefetch_enabled = true; - dceip.lb_write_pixels_per_dispclk = bw_int_to_fixed(1); - dceip.lb_size_per_component444 = bw_int_to_fixed(245952); - dceip.graphics_lb_nodownscaling_multi_line_prefetching = true; - dceip.stutter_and_dram_clock_state_change_gated_before_cursor = + dceip->alpha_vscaler_efficiency = bw_int_to_fixed(3); + dceip->max_dmif_buffer_allocated = 4; + dceip->graphics_dmif_size = 12288; + dceip->underlay_luma_dmif_size = 19456; + dceip->underlay_chroma_dmif_size = 23552; + dceip->pre_downscaler_enabled = true; + dceip->underlay_downscale_prefetch_enabled = true; + dceip->lb_write_pixels_per_dispclk = bw_int_to_fixed(1); + dceip->lb_size_per_component444 = bw_int_to_fixed(245952); + dceip->graphics_lb_nodownscaling_multi_line_prefetching = true; + dceip->stutter_and_dram_clock_state_change_gated_before_cursor = bw_int_to_fixed(1); - dceip.underlay420_luma_lb_size_per_component = bw_int_to_fixed( + dceip->underlay420_luma_lb_size_per_component = bw_int_to_fixed( 82176); - dceip.underlay420_chroma_lb_size_per_component = + dceip->underlay420_chroma_lb_size_per_component = bw_int_to_fixed(164352); - dceip.underlay422_lb_size_per_component = bw_int_to_fixed( + dceip->underlay422_lb_size_per_component = bw_int_to_fixed( 82176); - dceip.cursor_chunk_width = bw_int_to_fixed(64); - dceip.cursor_dcp_buffer_lines = bw_int_to_fixed(4); - dceip.underlay_maximum_width_efficient_for_tiling = + dceip->cursor_chunk_width = bw_int_to_fixed(64); + dceip->cursor_dcp_buffer_lines = bw_int_to_fixed(4); + dceip->underlay_maximum_width_efficient_for_tiling = bw_int_to_fixed(1920); - dceip.underlay_maximum_height_efficient_for_tiling = + dceip->underlay_maximum_height_efficient_for_tiling = bw_int_to_fixed(1080); - dceip.peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display = + dceip->peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display = bw_frc_to_fixed(3, 10); - dceip.peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation = + dceip->peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation = bw_int_to_fixed(25); - dceip.minimum_outstanding_pte_request_limit = bw_int_to_fixed( + dceip->minimum_outstanding_pte_request_limit = bw_int_to_fixed( 2); - dceip.maximum_total_outstanding_pte_requests_allowed_by_saw = + dceip->maximum_total_outstanding_pte_requests_allowed_by_saw = bw_int_to_fixed(128); - dceip.limit_excessive_outstanding_dmif_requests = true; - dceip.linear_mode_line_request_alternation_slice = + dceip->limit_excessive_outstanding_dmif_requests = true; + dceip->linear_mode_line_request_alternation_slice = bw_int_to_fixed(64); - dceip.scatter_gather_lines_of_pte_prefetching_in_linear_mode = + dceip->scatter_gather_lines_of_pte_prefetching_in_linear_mode = 32; - dceip.display_write_back420_luma_mcifwr_buffer_size = 12288; - dceip.display_write_back420_chroma_mcifwr_buffer_size = 8192; - dceip.request_efficiency = bw_frc_to_fixed(8, 10); - dceip.dispclk_per_request = bw_int_to_fixed(2); - dceip.dispclk_ramping_factor = bw_frc_to_fixed(105, 100); - dceip.display_pipe_throughput_factor = bw_frc_to_fixed(105, 100); - dceip.scatter_gather_pte_request_rows_in_tiling_mode = 2; - dceip.mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); + dceip->display_write_back420_luma_mcifwr_buffer_size = 12288; + dceip->display_write_back420_chroma_mcifwr_buffer_size = 8192; + dceip->request_efficiency = bw_frc_to_fixed(8, 10); + dceip->dispclk_per_request = bw_int_to_fixed(2); + dceip->dispclk_ramping_factor = bw_frc_to_fixed(105, 100); + dceip->display_pipe_throughput_factor = bw_frc_to_fixed(105, 100); + dceip->scatter_gather_pte_request_rows_in_tiling_mode = 2; + dceip->mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); break; case BW_CALCS_VERSION_POLARIS11: - vbios.memory_type = bw_def_gddr5; - vbios.dram_channel_width_in_bits = 32; - vbios.number_of_dram_channels = asic_id.vram_width / vbios.dram_channel_width_in_bits; - vbios.number_of_dram_banks = 8; - vbios.high_yclk = bw_int_to_fixed(6000); - vbios.mid_yclk = bw_int_to_fixed(3200); - vbios.low_yclk = bw_int_to_fixed(1000); - vbios.low_sclk = bw_int_to_fixed(300); - vbios.mid1_sclk = bw_int_to_fixed(400); - vbios.mid2_sclk = bw_int_to_fixed(500); - vbios.mid3_sclk = bw_int_to_fixed(600); - vbios.mid4_sclk = bw_int_to_fixed(700); - vbios.mid5_sclk = bw_int_to_fixed(800); - vbios.mid6_sclk = bw_int_to_fixed(974); - vbios.high_sclk = bw_int_to_fixed(1154); - vbios.low_voltage_max_dispclk = bw_int_to_fixed(459); - vbios.mid_voltage_max_dispclk = bw_int_to_fixed(654); - vbios.high_voltage_max_dispclk = bw_int_to_fixed(1108); - vbios.low_voltage_max_phyclk = bw_int_to_fixed(540); - vbios.mid_voltage_max_phyclk = bw_int_to_fixed(810); - vbios.high_voltage_max_phyclk = bw_int_to_fixed(810); - vbios.data_return_bus_width = bw_int_to_fixed(32); - vbios.trc = bw_int_to_fixed(48); - if (vbios.number_of_dram_channels == 2) // 64-bit - vbios.dmifmc_urgent_latency = bw_int_to_fixed(4); + vbios->memory_type = bw_def_gddr5; + vbios->dram_channel_width_in_bits = 32; + vbios->number_of_dram_channels = asic_id.vram_width / vbios->dram_channel_width_in_bits; + vbios->number_of_dram_banks = 8; + vbios->high_yclk = bw_int_to_fixed(6000); + vbios->mid_yclk = bw_int_to_fixed(3200); + vbios->low_yclk = bw_int_to_fixed(1000); + vbios->low_sclk = bw_int_to_fixed(300); + vbios->mid1_sclk = bw_int_to_fixed(400); + vbios->mid2_sclk = bw_int_to_fixed(500); + vbios->mid3_sclk = bw_int_to_fixed(600); + vbios->mid4_sclk = bw_int_to_fixed(700); + vbios->mid5_sclk = bw_int_to_fixed(800); + vbios->mid6_sclk = bw_int_to_fixed(974); + vbios->high_sclk = bw_int_to_fixed(1154); + vbios->low_voltage_max_dispclk = bw_int_to_fixed(459); + vbios->mid_voltage_max_dispclk = bw_int_to_fixed(654); + vbios->high_voltage_max_dispclk = bw_int_to_fixed(1108); + vbios->low_voltage_max_phyclk = bw_int_to_fixed(540); + vbios->mid_voltage_max_phyclk = bw_int_to_fixed(810); + vbios->high_voltage_max_phyclk = bw_int_to_fixed(810); + vbios->data_return_bus_width = bw_int_to_fixed(32); + vbios->trc = bw_int_to_fixed(48); + if (vbios->number_of_dram_channels == 2) // 64-bit + vbios->dmifmc_urgent_latency = bw_int_to_fixed(4); else - vbios.dmifmc_urgent_latency = bw_int_to_fixed(3); - vbios.stutter_self_refresh_exit_latency = bw_int_to_fixed(5); - vbios.stutter_self_refresh_entry_latency = bw_int_to_fixed(0); - vbios.nbp_state_change_latency = bw_int_to_fixed(45); - vbios.mcifwrmc_urgent_latency = bw_int_to_fixed(10); - vbios.scatter_gather_enable = true; - vbios.down_spread_percentage = bw_frc_to_fixed(5, 10); - vbios.cursor_width = 32; - vbios.average_compression_rate = 4; - vbios.number_of_request_slots_gmc_reserves_for_dmif_per_channel = 256; - vbios.blackout_duration = bw_int_to_fixed(0); /* us */ - vbios.maximum_blackout_recovery_time = bw_int_to_fixed(0); - - dceip.max_average_percent_of_ideal_port_bw_display_can_use_in_normal_system_operation = 100; - dceip.max_average_percent_of_ideal_drambw_display_can_use_in_normal_system_operation = 100; - dceip.percent_of_ideal_port_bw_received_after_urgent_latency = 100; - dceip.large_cursor = false; - dceip.dmif_request_buffer_size = bw_int_to_fixed(768); - dceip.dmif_pipe_en_fbc_chunk_tracker = false; - dceip.cursor_max_outstanding_group_num = 1; - dceip.lines_interleaved_into_lb = 2; - dceip.chunk_width = 256; - dceip.number_of_graphics_pipes = 5; - dceip.number_of_underlay_pipes = 0; - dceip.low_power_tiling_mode = 0; - dceip.display_write_back_supported = false; - dceip.argb_compression_support = true; - dceip.underlay_vscaler_efficiency6_bit_per_component = + vbios->dmifmc_urgent_latency = bw_int_to_fixed(3); + vbios->stutter_self_refresh_exit_latency = bw_int_to_fixed(5); + vbios->stutter_self_refresh_entry_latency = bw_int_to_fixed(0); + vbios->nbp_state_change_latency = bw_int_to_fixed(45); + vbios->mcifwrmc_urgent_latency = bw_int_to_fixed(10); + vbios->scatter_gather_enable = true; + vbios->down_spread_percentage = bw_frc_to_fixed(5, 10); + vbios->cursor_width = 32; + vbios->average_compression_rate = 4; + vbios->number_of_request_slots_gmc_reserves_for_dmif_per_channel = 256; + vbios->blackout_duration = bw_int_to_fixed(0); /* us */ + vbios->maximum_blackout_recovery_time = bw_int_to_fixed(0); + + dceip->max_average_percent_of_ideal_port_bw_display_can_use_in_normal_system_operation = 100; + dceip->max_average_percent_of_ideal_drambw_display_can_use_in_normal_system_operation = 100; + dceip->percent_of_ideal_port_bw_received_after_urgent_latency = 100; + dceip->large_cursor = false; + dceip->dmif_request_buffer_size = bw_int_to_fixed(768); + dceip->dmif_pipe_en_fbc_chunk_tracker = false; + dceip->cursor_max_outstanding_group_num = 1; + dceip->lines_interleaved_into_lb = 2; + dceip->chunk_width = 256; + dceip->number_of_graphics_pipes = 5; + dceip->number_of_underlay_pipes = 0; + dceip->low_power_tiling_mode = 0; + dceip->display_write_back_supported = false; + dceip->argb_compression_support = true; + dceip->underlay_vscaler_efficiency6_bit_per_component = bw_frc_to_fixed(35556, 10000); - dceip.underlay_vscaler_efficiency8_bit_per_component = + dceip->underlay_vscaler_efficiency8_bit_per_component = bw_frc_to_fixed(34286, 10000); - dceip.underlay_vscaler_efficiency10_bit_per_component = + dceip->underlay_vscaler_efficiency10_bit_per_component = bw_frc_to_fixed(32, 10); - dceip.underlay_vscaler_efficiency12_bit_per_component = + dceip->underlay_vscaler_efficiency12_bit_per_component = bw_int_to_fixed(3); - dceip.graphics_vscaler_efficiency6_bit_per_component = + dceip->graphics_vscaler_efficiency6_bit_per_component = bw_frc_to_fixed(35, 10); - dceip.graphics_vscaler_efficiency8_bit_per_component = + dceip->graphics_vscaler_efficiency8_bit_per_component = bw_frc_to_fixed(34286, 10000); - dceip.graphics_vscaler_efficiency10_bit_per_component = + dceip->graphics_vscaler_efficiency10_bit_per_component = bw_frc_to_fixed(32, 10); - dceip.graphics_vscaler_efficiency12_bit_per_component = + dceip->graphics_vscaler_efficiency12_bit_per_component = bw_int_to_fixed(3); - dceip.alpha_vscaler_efficiency = bw_int_to_fixed(3); - dceip.max_dmif_buffer_allocated = 4; - dceip.graphics_dmif_size = 12288; - dceip.underlay_luma_dmif_size = 19456; - dceip.underlay_chroma_dmif_size = 23552; - dceip.pre_downscaler_enabled = true; - dceip.underlay_downscale_prefetch_enabled = true; - dceip.lb_write_pixels_per_dispclk = bw_int_to_fixed(1); - dceip.lb_size_per_component444 = bw_int_to_fixed(245952); - dceip.graphics_lb_nodownscaling_multi_line_prefetching = true; - dceip.stutter_and_dram_clock_state_change_gated_before_cursor = + dceip->alpha_vscaler_efficiency = bw_int_to_fixed(3); + dceip->max_dmif_buffer_allocated = 4; + dceip->graphics_dmif_size = 12288; + dceip->underlay_luma_dmif_size = 19456; + dceip->underlay_chroma_dmif_size = 23552; + dceip->pre_downscaler_enabled = true; + dceip->underlay_downscale_prefetch_enabled = true; + dceip->lb_write_pixels_per_dispclk = bw_int_to_fixed(1); + dceip->lb_size_per_component444 = bw_int_to_fixed(245952); + dceip->graphics_lb_nodownscaling_multi_line_prefetching = true; + dceip->stutter_and_dram_clock_state_change_gated_before_cursor = bw_int_to_fixed(1); - dceip.underlay420_luma_lb_size_per_component = bw_int_to_fixed( + dceip->underlay420_luma_lb_size_per_component = bw_int_to_fixed( 82176); - dceip.underlay420_chroma_lb_size_per_component = + dceip->underlay420_chroma_lb_size_per_component = bw_int_to_fixed(164352); - dceip.underlay422_lb_size_per_component = bw_int_to_fixed( + dceip->underlay422_lb_size_per_component = bw_int_to_fixed( 82176); - dceip.cursor_chunk_width = bw_int_to_fixed(64); - dceip.cursor_dcp_buffer_lines = bw_int_to_fixed(4); - dceip.underlay_maximum_width_efficient_for_tiling = + dceip->cursor_chunk_width = bw_int_to_fixed(64); + dceip->cursor_dcp_buffer_lines = bw_int_to_fixed(4); + dceip->underlay_maximum_width_efficient_for_tiling = bw_int_to_fixed(1920); - dceip.underlay_maximum_height_efficient_for_tiling = + dceip->underlay_maximum_height_efficient_for_tiling = bw_int_to_fixed(1080); - dceip.peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display = + dceip->peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display = bw_frc_to_fixed(3, 10); - dceip.peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation = + dceip->peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation = bw_int_to_fixed(25); - dceip.minimum_outstanding_pte_request_limit = bw_int_to_fixed( + dceip->minimum_outstanding_pte_request_limit = bw_int_to_fixed( 2); - dceip.maximum_total_outstanding_pte_requests_allowed_by_saw = + dceip->maximum_total_outstanding_pte_requests_allowed_by_saw = bw_int_to_fixed(128); - dceip.limit_excessive_outstanding_dmif_requests = true; - dceip.linear_mode_line_request_alternation_slice = + dceip->limit_excessive_outstanding_dmif_requests = true; + dceip->linear_mode_line_request_alternation_slice = bw_int_to_fixed(64); - dceip.scatter_gather_lines_of_pte_prefetching_in_linear_mode = + dceip->scatter_gather_lines_of_pte_prefetching_in_linear_mode = 32; - dceip.display_write_back420_luma_mcifwr_buffer_size = 12288; - dceip.display_write_back420_chroma_mcifwr_buffer_size = 8192; - dceip.request_efficiency = bw_frc_to_fixed(8, 10); - dceip.dispclk_per_request = bw_int_to_fixed(2); - dceip.dispclk_ramping_factor = bw_frc_to_fixed(105, 100); - dceip.display_pipe_throughput_factor = bw_frc_to_fixed(105, 100); - dceip.scatter_gather_pte_request_rows_in_tiling_mode = 2; - dceip.mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); + dceip->display_write_back420_luma_mcifwr_buffer_size = 12288; + dceip->display_write_back420_chroma_mcifwr_buffer_size = 8192; + dceip->request_efficiency = bw_frc_to_fixed(8, 10); + dceip->dispclk_per_request = bw_int_to_fixed(2); + dceip->dispclk_ramping_factor = bw_frc_to_fixed(105, 100); + dceip->display_pipe_throughput_factor = bw_frc_to_fixed(105, 100); + dceip->scatter_gather_pte_request_rows_in_tiling_mode = 2; + dceip->mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); break; case BW_CALCS_VERSION_POLARIS12: - vbios.memory_type = bw_def_gddr5; - vbios.dram_channel_width_in_bits = 32; - vbios.number_of_dram_channels = asic_id.vram_width / vbios.dram_channel_width_in_bits; - vbios.number_of_dram_banks = 8; - vbios.high_yclk = bw_int_to_fixed(6000); - vbios.mid_yclk = bw_int_to_fixed(3200); - vbios.low_yclk = bw_int_to_fixed(1000); - vbios.low_sclk = bw_int_to_fixed(678); - vbios.mid1_sclk = bw_int_to_fixed(864); - vbios.mid2_sclk = bw_int_to_fixed(900); - vbios.mid3_sclk = bw_int_to_fixed(920); - vbios.mid4_sclk = bw_int_to_fixed(940); - vbios.mid5_sclk = bw_int_to_fixed(960); - vbios.mid6_sclk = bw_int_to_fixed(980); - vbios.high_sclk = bw_int_to_fixed(1049); - vbios.low_voltage_max_dispclk = bw_int_to_fixed(459); - vbios.mid_voltage_max_dispclk = bw_int_to_fixed(654); - vbios.high_voltage_max_dispclk = bw_int_to_fixed(1108); - vbios.low_voltage_max_phyclk = bw_int_to_fixed(540); - vbios.mid_voltage_max_phyclk = bw_int_to_fixed(810); - vbios.high_voltage_max_phyclk = bw_int_to_fixed(810); - vbios.data_return_bus_width = bw_int_to_fixed(32); - vbios.trc = bw_int_to_fixed(48); - if (vbios.number_of_dram_channels == 2) // 64-bit - vbios.dmifmc_urgent_latency = bw_int_to_fixed(4); + vbios->memory_type = bw_def_gddr5; + vbios->dram_channel_width_in_bits = 32; + vbios->number_of_dram_channels = asic_id.vram_width / vbios->dram_channel_width_in_bits; + vbios->number_of_dram_banks = 8; + vbios->high_yclk = bw_int_to_fixed(6000); + vbios->mid_yclk = bw_int_to_fixed(3200); + vbios->low_yclk = bw_int_to_fixed(1000); + vbios->low_sclk = bw_int_to_fixed(678); + vbios->mid1_sclk = bw_int_to_fixed(864); + vbios->mid2_sclk = bw_int_to_fixed(900); + vbios->mid3_sclk = bw_int_to_fixed(920); + vbios->mid4_sclk = bw_int_to_fixed(940); + vbios->mid5_sclk = bw_int_to_fixed(960); + vbios->mid6_sclk = bw_int_to_fixed(980); + vbios->high_sclk = bw_int_to_fixed(1049); + vbios->low_voltage_max_dispclk = bw_int_to_fixed(459); + vbios->mid_voltage_max_dispclk = bw_int_to_fixed(654); + vbios->high_voltage_max_dispclk = bw_int_to_fixed(1108); + vbios->low_voltage_max_phyclk = bw_int_to_fixed(540); + vbios->mid_voltage_max_phyclk = bw_int_to_fixed(810); + vbios->high_voltage_max_phyclk = bw_int_to_fixed(810); + vbios->data_return_bus_width = bw_int_to_fixed(32); + vbios->trc = bw_int_to_fixed(48); + if (vbios->number_of_dram_channels == 2) // 64-bit + vbios->dmifmc_urgent_latency = bw_int_to_fixed(4); else - vbios.dmifmc_urgent_latency = bw_int_to_fixed(3); - vbios.stutter_self_refresh_exit_latency = bw_int_to_fixed(5); - vbios.stutter_self_refresh_entry_latency = bw_int_to_fixed(0); - vbios.nbp_state_change_latency = bw_int_to_fixed(250); - vbios.mcifwrmc_urgent_latency = bw_int_to_fixed(10); - vbios.scatter_gather_enable = false; - vbios.down_spread_percentage = bw_frc_to_fixed(5, 10); - vbios.cursor_width = 32; - vbios.average_compression_rate = 4; - vbios.number_of_request_slots_gmc_reserves_for_dmif_per_channel = 256; - vbios.blackout_duration = bw_int_to_fixed(0); /* us */ - vbios.maximum_blackout_recovery_time = bw_int_to_fixed(0); - - dceip.max_average_percent_of_ideal_port_bw_display_can_use_in_normal_system_operation = 100; - dceip.max_average_percent_of_ideal_drambw_display_can_use_in_normal_system_operation = 100; - dceip.percent_of_ideal_port_bw_received_after_urgent_latency = 100; - dceip.large_cursor = false; - dceip.dmif_request_buffer_size = bw_int_to_fixed(768); - dceip.dmif_pipe_en_fbc_chunk_tracker = false; - dceip.cursor_max_outstanding_group_num = 1; - dceip.lines_interleaved_into_lb = 2; - dceip.chunk_width = 256; - dceip.number_of_graphics_pipes = 5; - dceip.number_of_underlay_pipes = 0; - dceip.low_power_tiling_mode = 0; - dceip.display_write_back_supported = true; - dceip.argb_compression_support = true; - dceip.underlay_vscaler_efficiency6_bit_per_component = + vbios->dmifmc_urgent_latency = bw_int_to_fixed(3); + vbios->stutter_self_refresh_exit_latency = bw_int_to_fixed(5); + vbios->stutter_self_refresh_entry_latency = bw_int_to_fixed(0); + vbios->nbp_state_change_latency = bw_int_to_fixed(250); + vbios->mcifwrmc_urgent_latency = bw_int_to_fixed(10); + vbios->scatter_gather_enable = false; + vbios->down_spread_percentage = bw_frc_to_fixed(5, 10); + vbios->cursor_width = 32; + vbios->average_compression_rate = 4; + vbios->number_of_request_slots_gmc_reserves_for_dmif_per_channel = 256; + vbios->blackout_duration = bw_int_to_fixed(0); /* us */ + vbios->maximum_blackout_recovery_time = bw_int_to_fixed(0); + + dceip->max_average_percent_of_ideal_port_bw_display_can_use_in_normal_system_operation = 100; + dceip->max_average_percent_of_ideal_drambw_display_can_use_in_normal_system_operation = 100; + dceip->percent_of_ideal_port_bw_received_after_urgent_latency = 100; + dceip->large_cursor = false; + dceip->dmif_request_buffer_size = bw_int_to_fixed(768); + dceip->dmif_pipe_en_fbc_chunk_tracker = false; + dceip->cursor_max_outstanding_group_num = 1; + dceip->lines_interleaved_into_lb = 2; + dceip->chunk_width = 256; + dceip->number_of_graphics_pipes = 5; + dceip->number_of_underlay_pipes = 0; + dceip->low_power_tiling_mode = 0; + dceip->display_write_back_supported = true; + dceip->argb_compression_support = true; + dceip->underlay_vscaler_efficiency6_bit_per_component = bw_frc_to_fixed(35556, 10000); - dceip.underlay_vscaler_efficiency8_bit_per_component = + dceip->underlay_vscaler_efficiency8_bit_per_component = bw_frc_to_fixed(34286, 10000); - dceip.underlay_vscaler_efficiency10_bit_per_component = + dceip->underlay_vscaler_efficiency10_bit_per_component = bw_frc_to_fixed(32, 10); - dceip.underlay_vscaler_efficiency12_bit_per_component = + dceip->underlay_vscaler_efficiency12_bit_per_component = bw_int_to_fixed(3); - dceip.graphics_vscaler_efficiency6_bit_per_component = + dceip->graphics_vscaler_efficiency6_bit_per_component = bw_frc_to_fixed(35, 10); - dceip.graphics_vscaler_efficiency8_bit_per_component = + dceip->graphics_vscaler_efficiency8_bit_per_component = bw_frc_to_fixed(34286, 10000); - dceip.graphics_vscaler_efficiency10_bit_per_component = + dceip->graphics_vscaler_efficiency10_bit_per_component = bw_frc_to_fixed(32, 10); - dceip.graphics_vscaler_efficiency12_bit_per_component = + dceip->graphics_vscaler_efficiency12_bit_per_component = bw_int_to_fixed(3); - dceip.alpha_vscaler_efficiency = bw_int_to_fixed(3); - dceip.max_dmif_buffer_allocated = 4; - dceip.graphics_dmif_size = 12288; - dceip.underlay_luma_dmif_size = 19456; - dceip.underlay_chroma_dmif_size = 23552; - dceip.pre_downscaler_enabled = true; - dceip.underlay_downscale_prefetch_enabled = true; - dceip.lb_write_pixels_per_dispclk = bw_int_to_fixed(1); - dceip.lb_size_per_component444 = bw_int_to_fixed(245952); - dceip.graphics_lb_nodownscaling_multi_line_prefetching = true; - dceip.stutter_and_dram_clock_state_change_gated_before_cursor = + dceip->alpha_vscaler_efficiency = bw_int_to_fixed(3); + dceip->max_dmif_buffer_allocated = 4; + dceip->graphics_dmif_size = 12288; + dceip->underlay_luma_dmif_size = 19456; + dceip->underlay_chroma_dmif_size = 23552; + dceip->pre_downscaler_enabled = true; + dceip->underlay_downscale_prefetch_enabled = true; + dceip->lb_write_pixels_per_dispclk = bw_int_to_fixed(1); + dceip->lb_size_per_component444 = bw_int_to_fixed(245952); + dceip->graphics_lb_nodownscaling_multi_line_prefetching = true; + dceip->stutter_and_dram_clock_state_change_gated_before_cursor = bw_int_to_fixed(1); - dceip.underlay420_luma_lb_size_per_component = bw_int_to_fixed( + dceip->underlay420_luma_lb_size_per_component = bw_int_to_fixed( 82176); - dceip.underlay420_chroma_lb_size_per_component = + dceip->underlay420_chroma_lb_size_per_component = bw_int_to_fixed(164352); - dceip.underlay422_lb_size_per_component = bw_int_to_fixed( + dceip->underlay422_lb_size_per_component = bw_int_to_fixed( 82176); - dceip.cursor_chunk_width = bw_int_to_fixed(64); - dceip.cursor_dcp_buffer_lines = bw_int_to_fixed(4); - dceip.underlay_maximum_width_efficient_for_tiling = + dceip->cursor_chunk_width = bw_int_to_fixed(64); + dceip->cursor_dcp_buffer_lines = bw_int_to_fixed(4); + dceip->underlay_maximum_width_efficient_for_tiling = bw_int_to_fixed(1920); - dceip.underlay_maximum_height_efficient_for_tiling = + dceip->underlay_maximum_height_efficient_for_tiling = bw_int_to_fixed(1080); - dceip.peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display = + dceip->peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display = bw_frc_to_fixed(3, 10); - dceip.peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation = + dceip->peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation = bw_int_to_fixed(25); - dceip.minimum_outstanding_pte_request_limit = bw_int_to_fixed( + dceip->minimum_outstanding_pte_request_limit = bw_int_to_fixed( 2); - dceip.maximum_total_outstanding_pte_requests_allowed_by_saw = + dceip->maximum_total_outstanding_pte_requests_allowed_by_saw = bw_int_to_fixed(128); - dceip.limit_excessive_outstanding_dmif_requests = true; - dceip.linear_mode_line_request_alternation_slice = + dceip->limit_excessive_outstanding_dmif_requests = true; + dceip->linear_mode_line_request_alternation_slice = bw_int_to_fixed(64); - dceip.scatter_gather_lines_of_pte_prefetching_in_linear_mode = + dceip->scatter_gather_lines_of_pte_prefetching_in_linear_mode = 32; - dceip.display_write_back420_luma_mcifwr_buffer_size = 12288; - dceip.display_write_back420_chroma_mcifwr_buffer_size = 8192; - dceip.request_efficiency = bw_frc_to_fixed(8, 10); - dceip.dispclk_per_request = bw_int_to_fixed(2); - dceip.dispclk_ramping_factor = bw_frc_to_fixed(105, 100); - dceip.display_pipe_throughput_factor = bw_frc_to_fixed(105, 100); - dceip.scatter_gather_pte_request_rows_in_tiling_mode = 2; - dceip.mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); + dceip->display_write_back420_luma_mcifwr_buffer_size = 12288; + dceip->display_write_back420_chroma_mcifwr_buffer_size = 8192; + dceip->request_efficiency = bw_frc_to_fixed(8, 10); + dceip->dispclk_per_request = bw_int_to_fixed(2); + dceip->dispclk_ramping_factor = bw_frc_to_fixed(105, 100); + dceip->display_pipe_throughput_factor = bw_frc_to_fixed(105, 100); + dceip->scatter_gather_pte_request_rows_in_tiling_mode = 2; + dceip->mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); break; case BW_CALCS_VERSION_STONEY: - vbios.memory_type = bw_def_gddr5; - vbios.dram_channel_width_in_bits = 64; - vbios.number_of_dram_channels = asic_id.vram_width / vbios.dram_channel_width_in_bits; - vbios.number_of_dram_banks = 8; - vbios.high_yclk = bw_int_to_fixed(1866); - vbios.mid_yclk = bw_int_to_fixed(1866); - vbios.low_yclk = bw_int_to_fixed(1333); - vbios.low_sclk = bw_int_to_fixed(200); - vbios.mid1_sclk = bw_int_to_fixed(600); - vbios.mid2_sclk = bw_int_to_fixed(600); - vbios.mid3_sclk = bw_int_to_fixed(600); - vbios.mid4_sclk = bw_int_to_fixed(600); - vbios.mid5_sclk = bw_int_to_fixed(600); - vbios.mid6_sclk = bw_int_to_fixed(600); - vbios.high_sclk = bw_int_to_fixed(800); - vbios.low_voltage_max_dispclk = bw_int_to_fixed(352); - vbios.mid_voltage_max_dispclk = bw_int_to_fixed(467); - vbios.high_voltage_max_dispclk = bw_int_to_fixed(643); - vbios.low_voltage_max_phyclk = bw_int_to_fixed(540); - vbios.mid_voltage_max_phyclk = bw_int_to_fixed(810); - vbios.high_voltage_max_phyclk = bw_int_to_fixed(810); - vbios.data_return_bus_width = bw_int_to_fixed(32); - vbios.trc = bw_int_to_fixed(50); - vbios.dmifmc_urgent_latency = bw_int_to_fixed(4); - vbios.stutter_self_refresh_exit_latency = bw_frc_to_fixed(158, 10); - vbios.stutter_self_refresh_entry_latency = bw_int_to_fixed(0); - vbios.nbp_state_change_latency = bw_frc_to_fixed(2008, 100); - vbios.mcifwrmc_urgent_latency = bw_int_to_fixed(10); - vbios.scatter_gather_enable = true; - vbios.down_spread_percentage = bw_frc_to_fixed(5, 10); - vbios.cursor_width = 32; - vbios.average_compression_rate = 4; - vbios.number_of_request_slots_gmc_reserves_for_dmif_per_channel = 256; - vbios.blackout_duration = bw_int_to_fixed(0); /* us */ - vbios.maximum_blackout_recovery_time = bw_int_to_fixed(0); - - dceip.max_average_percent_of_ideal_port_bw_display_can_use_in_normal_system_operation = 100; - dceip.max_average_percent_of_ideal_drambw_display_can_use_in_normal_system_operation = 100; - dceip.percent_of_ideal_port_bw_received_after_urgent_latency = 100; - dceip.large_cursor = false; - dceip.dmif_request_buffer_size = bw_int_to_fixed(768); - dceip.dmif_pipe_en_fbc_chunk_tracker = false; - dceip.cursor_max_outstanding_group_num = 1; - dceip.lines_interleaved_into_lb = 2; - dceip.chunk_width = 256; - dceip.number_of_graphics_pipes = 2; - dceip.number_of_underlay_pipes = 1; - dceip.low_power_tiling_mode = 0; - dceip.display_write_back_supported = false; - dceip.argb_compression_support = true; - dceip.underlay_vscaler_efficiency6_bit_per_component = + vbios->memory_type = bw_def_gddr5; + vbios->dram_channel_width_in_bits = 64; + vbios->number_of_dram_channels = asic_id.vram_width / vbios->dram_channel_width_in_bits; + vbios->number_of_dram_banks = 8; + vbios->high_yclk = bw_int_to_fixed(1866); + vbios->mid_yclk = bw_int_to_fixed(1866); + vbios->low_yclk = bw_int_to_fixed(1333); + vbios->low_sclk = bw_int_to_fixed(200); + vbios->mid1_sclk = bw_int_to_fixed(600); + vbios->mid2_sclk = bw_int_to_fixed(600); + vbios->mid3_sclk = bw_int_to_fixed(600); + vbios->mid4_sclk = bw_int_to_fixed(600); + vbios->mid5_sclk = bw_int_to_fixed(600); + vbios->mid6_sclk = bw_int_to_fixed(600); + vbios->high_sclk = bw_int_to_fixed(800); + vbios->low_voltage_max_dispclk = bw_int_to_fixed(352); + vbios->mid_voltage_max_dispclk = bw_int_to_fixed(467); + vbios->high_voltage_max_dispclk = bw_int_to_fixed(643); + vbios->low_voltage_max_phyclk = bw_int_to_fixed(540); + vbios->mid_voltage_max_phyclk = bw_int_to_fixed(810); + vbios->high_voltage_max_phyclk = bw_int_to_fixed(810); + vbios->data_return_bus_width = bw_int_to_fixed(32); + vbios->trc = bw_int_to_fixed(50); + vbios->dmifmc_urgent_latency = bw_int_to_fixed(4); + vbios->stutter_self_refresh_exit_latency = bw_frc_to_fixed(158, 10); + vbios->stutter_self_refresh_entry_latency = bw_int_to_fixed(0); + vbios->nbp_state_change_latency = bw_frc_to_fixed(2008, 100); + vbios->mcifwrmc_urgent_latency = bw_int_to_fixed(10); + vbios->scatter_gather_enable = true; + vbios->down_spread_percentage = bw_frc_to_fixed(5, 10); + vbios->cursor_width = 32; + vbios->average_compression_rate = 4; + vbios->number_of_request_slots_gmc_reserves_for_dmif_per_channel = 256; + vbios->blackout_duration = bw_int_to_fixed(0); /* us */ + vbios->maximum_blackout_recovery_time = bw_int_to_fixed(0); + + dceip->max_average_percent_of_ideal_port_bw_display_can_use_in_normal_system_operation = 100; + dceip->max_average_percent_of_ideal_drambw_display_can_use_in_normal_system_operation = 100; + dceip->percent_of_ideal_port_bw_received_after_urgent_latency = 100; + dceip->large_cursor = false; + dceip->dmif_request_buffer_size = bw_int_to_fixed(768); + dceip->dmif_pipe_en_fbc_chunk_tracker = false; + dceip->cursor_max_outstanding_group_num = 1; + dceip->lines_interleaved_into_lb = 2; + dceip->chunk_width = 256; + dceip->number_of_graphics_pipes = 2; + dceip->number_of_underlay_pipes = 1; + dceip->low_power_tiling_mode = 0; + dceip->display_write_back_supported = false; + dceip->argb_compression_support = true; + dceip->underlay_vscaler_efficiency6_bit_per_component = bw_frc_to_fixed(35556, 10000); - dceip.underlay_vscaler_efficiency8_bit_per_component = + dceip->underlay_vscaler_efficiency8_bit_per_component = bw_frc_to_fixed(34286, 10000); - dceip.underlay_vscaler_efficiency10_bit_per_component = + dceip->underlay_vscaler_efficiency10_bit_per_component = bw_frc_to_fixed(32, 10); - dceip.underlay_vscaler_efficiency12_bit_per_component = + dceip->underlay_vscaler_efficiency12_bit_per_component = bw_int_to_fixed(3); - dceip.graphics_vscaler_efficiency6_bit_per_component = + dceip->graphics_vscaler_efficiency6_bit_per_component = bw_frc_to_fixed(35, 10); - dceip.graphics_vscaler_efficiency8_bit_per_component = + dceip->graphics_vscaler_efficiency8_bit_per_component = bw_frc_to_fixed(34286, 10000); - dceip.graphics_vscaler_efficiency10_bit_per_component = + dceip->graphics_vscaler_efficiency10_bit_per_component = bw_frc_to_fixed(32, 10); - dceip.graphics_vscaler_efficiency12_bit_per_component = + dceip->graphics_vscaler_efficiency12_bit_per_component = bw_int_to_fixed(3); - dceip.alpha_vscaler_efficiency = bw_int_to_fixed(3); - dceip.max_dmif_buffer_allocated = 2; - dceip.graphics_dmif_size = 12288; - dceip.underlay_luma_dmif_size = 19456; - dceip.underlay_chroma_dmif_size = 23552; - dceip.pre_downscaler_enabled = true; - dceip.underlay_downscale_prefetch_enabled = true; - dceip.lb_write_pixels_per_dispclk = bw_int_to_fixed(1); - dceip.lb_size_per_component444 = bw_int_to_fixed(82176); - dceip.graphics_lb_nodownscaling_multi_line_prefetching = false; - dceip.stutter_and_dram_clock_state_change_gated_before_cursor = + dceip->alpha_vscaler_efficiency = bw_int_to_fixed(3); + dceip->max_dmif_buffer_allocated = 2; + dceip->graphics_dmif_size = 12288; + dceip->underlay_luma_dmif_size = 19456; + dceip->underlay_chroma_dmif_size = 23552; + dceip->pre_downscaler_enabled = true; + dceip->underlay_downscale_prefetch_enabled = true; + dceip->lb_write_pixels_per_dispclk = bw_int_to_fixed(1); + dceip->lb_size_per_component444 = bw_int_to_fixed(82176); + dceip->graphics_lb_nodownscaling_multi_line_prefetching = false; + dceip->stutter_and_dram_clock_state_change_gated_before_cursor = bw_int_to_fixed(0); - dceip.underlay420_luma_lb_size_per_component = bw_int_to_fixed( + dceip->underlay420_luma_lb_size_per_component = bw_int_to_fixed( 82176); - dceip.underlay420_chroma_lb_size_per_component = + dceip->underlay420_chroma_lb_size_per_component = bw_int_to_fixed(164352); - dceip.underlay422_lb_size_per_component = bw_int_to_fixed( + dceip->underlay422_lb_size_per_component = bw_int_to_fixed( 82176); - dceip.cursor_chunk_width = bw_int_to_fixed(64); - dceip.cursor_dcp_buffer_lines = bw_int_to_fixed(4); - dceip.underlay_maximum_width_efficient_for_tiling = + dceip->cursor_chunk_width = bw_int_to_fixed(64); + dceip->cursor_dcp_buffer_lines = bw_int_to_fixed(4); + dceip->underlay_maximum_width_efficient_for_tiling = bw_int_to_fixed(1920); - dceip.underlay_maximum_height_efficient_for_tiling = + dceip->underlay_maximum_height_efficient_for_tiling = bw_int_to_fixed(1080); - dceip.peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display = + dceip->peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display = bw_frc_to_fixed(3, 10); - dceip.peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation = + dceip->peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation = bw_int_to_fixed(25); - dceip.minimum_outstanding_pte_request_limit = bw_int_to_fixed( + dceip->minimum_outstanding_pte_request_limit = bw_int_to_fixed( 2); - dceip.maximum_total_outstanding_pte_requests_allowed_by_saw = + dceip->maximum_total_outstanding_pte_requests_allowed_by_saw = bw_int_to_fixed(128); - dceip.limit_excessive_outstanding_dmif_requests = true; - dceip.linear_mode_line_request_alternation_slice = + dceip->limit_excessive_outstanding_dmif_requests = true; + dceip->linear_mode_line_request_alternation_slice = bw_int_to_fixed(64); - dceip.scatter_gather_lines_of_pte_prefetching_in_linear_mode = + dceip->scatter_gather_lines_of_pte_prefetching_in_linear_mode = 32; - dceip.display_write_back420_luma_mcifwr_buffer_size = 12288; - dceip.display_write_back420_chroma_mcifwr_buffer_size = 8192; - dceip.request_efficiency = bw_frc_to_fixed(8, 10); - dceip.dispclk_per_request = bw_int_to_fixed(2); - dceip.dispclk_ramping_factor = bw_frc_to_fixed(105, 100); - dceip.display_pipe_throughput_factor = bw_frc_to_fixed(105, 100); - dceip.scatter_gather_pte_request_rows_in_tiling_mode = 2; - dceip.mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); + dceip->display_write_back420_luma_mcifwr_buffer_size = 12288; + dceip->display_write_back420_chroma_mcifwr_buffer_size = 8192; + dceip->request_efficiency = bw_frc_to_fixed(8, 10); + dceip->dispclk_per_request = bw_int_to_fixed(2); + dceip->dispclk_ramping_factor = bw_frc_to_fixed(105, 100); + dceip->display_pipe_throughput_factor = bw_frc_to_fixed(105, 100); + dceip->scatter_gather_pte_request_rows_in_tiling_mode = 2; + dceip->mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); break; case BW_CALCS_VERSION_VEGA10: - vbios.memory_type = bw_def_hbm; - vbios.dram_channel_width_in_bits = 128; - vbios.number_of_dram_channels = asic_id.vram_width / vbios.dram_channel_width_in_bits; - vbios.number_of_dram_banks = 16; - vbios.high_yclk = bw_int_to_fixed(2400); - vbios.mid_yclk = bw_int_to_fixed(1700); - vbios.low_yclk = bw_int_to_fixed(1000); - vbios.low_sclk = bw_int_to_fixed(300); - vbios.mid1_sclk = bw_int_to_fixed(350); - vbios.mid2_sclk = bw_int_to_fixed(400); - vbios.mid3_sclk = bw_int_to_fixed(500); - vbios.mid4_sclk = bw_int_to_fixed(600); - vbios.mid5_sclk = bw_int_to_fixed(700); - vbios.mid6_sclk = bw_int_to_fixed(760); - vbios.high_sclk = bw_int_to_fixed(776); - vbios.low_voltage_max_dispclk = bw_int_to_fixed(460); - vbios.mid_voltage_max_dispclk = bw_int_to_fixed(670); - vbios.high_voltage_max_dispclk = bw_int_to_fixed(1133); - vbios.low_voltage_max_phyclk = bw_int_to_fixed(540); - vbios.mid_voltage_max_phyclk = bw_int_to_fixed(810); - vbios.high_voltage_max_phyclk = bw_int_to_fixed(810); - vbios.data_return_bus_width = bw_int_to_fixed(32); - vbios.trc = bw_int_to_fixed(48); - vbios.dmifmc_urgent_latency = bw_int_to_fixed(3); - vbios.stutter_self_refresh_exit_latency = bw_frc_to_fixed(75, 10); - vbios.stutter_self_refresh_entry_latency = bw_frc_to_fixed(19, 10); - vbios.nbp_state_change_latency = bw_int_to_fixed(39); - vbios.mcifwrmc_urgent_latency = bw_int_to_fixed(10); - vbios.scatter_gather_enable = false; - vbios.down_spread_percentage = bw_frc_to_fixed(5, 10); - vbios.cursor_width = 32; - vbios.average_compression_rate = 4; - vbios.number_of_request_slots_gmc_reserves_for_dmif_per_channel = 8; - vbios.blackout_duration = bw_int_to_fixed(0); /* us */ - vbios.maximum_blackout_recovery_time = bw_int_to_fixed(0); - - dceip.max_average_percent_of_ideal_port_bw_display_can_use_in_normal_system_operation = 100; - dceip.max_average_percent_of_ideal_drambw_display_can_use_in_normal_system_operation = 100; - dceip.percent_of_ideal_port_bw_received_after_urgent_latency = 100; - dceip.large_cursor = false; - dceip.dmif_request_buffer_size = bw_int_to_fixed(2304); - dceip.dmif_pipe_en_fbc_chunk_tracker = true; - dceip.cursor_max_outstanding_group_num = 1; - dceip.lines_interleaved_into_lb = 2; - dceip.chunk_width = 256; - dceip.number_of_graphics_pipes = 6; - dceip.number_of_underlay_pipes = 0; - dceip.low_power_tiling_mode = 0; - dceip.display_write_back_supported = true; - dceip.argb_compression_support = true; - dceip.underlay_vscaler_efficiency6_bit_per_component = + vbios->memory_type = bw_def_hbm; + vbios->dram_channel_width_in_bits = 128; + vbios->number_of_dram_channels = asic_id.vram_width / vbios->dram_channel_width_in_bits; + vbios->number_of_dram_banks = 16; + vbios->high_yclk = bw_int_to_fixed(2400); + vbios->mid_yclk = bw_int_to_fixed(1700); + vbios->low_yclk = bw_int_to_fixed(1000); + vbios->low_sclk = bw_int_to_fixed(300); + vbios->mid1_sclk = bw_int_to_fixed(350); + vbios->mid2_sclk = bw_int_to_fixed(400); + vbios->mid3_sclk = bw_int_to_fixed(500); + vbios->mid4_sclk = bw_int_to_fixed(600); + vbios->mid5_sclk = bw_int_to_fixed(700); + vbios->mid6_sclk = bw_int_to_fixed(760); + vbios->high_sclk = bw_int_to_fixed(776); + vbios->low_voltage_max_dispclk = bw_int_to_fixed(460); + vbios->mid_voltage_max_dispclk = bw_int_to_fixed(670); + vbios->high_voltage_max_dispclk = bw_int_to_fixed(1133); + vbios->low_voltage_max_phyclk = bw_int_to_fixed(540); + vbios->mid_voltage_max_phyclk = bw_int_to_fixed(810); + vbios->high_voltage_max_phyclk = bw_int_to_fixed(810); + vbios->data_return_bus_width = bw_int_to_fixed(32); + vbios->trc = bw_int_to_fixed(48); + vbios->dmifmc_urgent_latency = bw_int_to_fixed(3); + vbios->stutter_self_refresh_exit_latency = bw_frc_to_fixed(75, 10); + vbios->stutter_self_refresh_entry_latency = bw_frc_to_fixed(19, 10); + vbios->nbp_state_change_latency = bw_int_to_fixed(39); + vbios->mcifwrmc_urgent_latency = bw_int_to_fixed(10); + vbios->scatter_gather_enable = false; + vbios->down_spread_percentage = bw_frc_to_fixed(5, 10); + vbios->cursor_width = 32; + vbios->average_compression_rate = 4; + vbios->number_of_request_slots_gmc_reserves_for_dmif_per_channel = 8; + vbios->blackout_duration = bw_int_to_fixed(0); /* us */ + vbios->maximum_blackout_recovery_time = bw_int_to_fixed(0); + + dceip->max_average_percent_of_ideal_port_bw_display_can_use_in_normal_system_operation = 100; + dceip->max_average_percent_of_ideal_drambw_display_can_use_in_normal_system_operation = 100; + dceip->percent_of_ideal_port_bw_received_after_urgent_latency = 100; + dceip->large_cursor = false; + dceip->dmif_request_buffer_size = bw_int_to_fixed(2304); + dceip->dmif_pipe_en_fbc_chunk_tracker = true; + dceip->cursor_max_outstanding_group_num = 1; + dceip->lines_interleaved_into_lb = 2; + dceip->chunk_width = 256; + dceip->number_of_graphics_pipes = 6; + dceip->number_of_underlay_pipes = 0; + dceip->low_power_tiling_mode = 0; + dceip->display_write_back_supported = true; + dceip->argb_compression_support = true; + dceip->underlay_vscaler_efficiency6_bit_per_component = bw_frc_to_fixed(35556, 10000); - dceip.underlay_vscaler_efficiency8_bit_per_component = + dceip->underlay_vscaler_efficiency8_bit_per_component = bw_frc_to_fixed(34286, 10000); - dceip.underlay_vscaler_efficiency10_bit_per_component = + dceip->underlay_vscaler_efficiency10_bit_per_component = bw_frc_to_fixed(32, 10); - dceip.underlay_vscaler_efficiency12_bit_per_component = + dceip->underlay_vscaler_efficiency12_bit_per_component = bw_int_to_fixed(3); - dceip.graphics_vscaler_efficiency6_bit_per_component = + dceip->graphics_vscaler_efficiency6_bit_per_component = bw_frc_to_fixed(35, 10); - dceip.graphics_vscaler_efficiency8_bit_per_component = + dceip->graphics_vscaler_efficiency8_bit_per_component = bw_frc_to_fixed(34286, 10000); - dceip.graphics_vscaler_efficiency10_bit_per_component = + dceip->graphics_vscaler_efficiency10_bit_per_component = bw_frc_to_fixed(32, 10); - dceip.graphics_vscaler_efficiency12_bit_per_component = + dceip->graphics_vscaler_efficiency12_bit_per_component = bw_int_to_fixed(3); - dceip.alpha_vscaler_efficiency = bw_int_to_fixed(3); - dceip.max_dmif_buffer_allocated = 4; - dceip.graphics_dmif_size = 24576; - dceip.underlay_luma_dmif_size = 19456; - dceip.underlay_chroma_dmif_size = 23552; - dceip.pre_downscaler_enabled = true; - dceip.underlay_downscale_prefetch_enabled = false; - dceip.lb_write_pixels_per_dispclk = bw_int_to_fixed(1); - dceip.lb_size_per_component444 = bw_int_to_fixed(245952); - dceip.graphics_lb_nodownscaling_multi_line_prefetching = true; - dceip.stutter_and_dram_clock_state_change_gated_before_cursor = + dceip->alpha_vscaler_efficiency = bw_int_to_fixed(3); + dceip->max_dmif_buffer_allocated = 4; + dceip->graphics_dmif_size = 24576; + dceip->underlay_luma_dmif_size = 19456; + dceip->underlay_chroma_dmif_size = 23552; + dceip->pre_downscaler_enabled = true; + dceip->underlay_downscale_prefetch_enabled = false; + dceip->lb_write_pixels_per_dispclk = bw_int_to_fixed(1); + dceip->lb_size_per_component444 = bw_int_to_fixed(245952); + dceip->graphics_lb_nodownscaling_multi_line_prefetching = true; + dceip->stutter_and_dram_clock_state_change_gated_before_cursor = bw_int_to_fixed(1); - dceip.underlay420_luma_lb_size_per_component = bw_int_to_fixed( + dceip->underlay420_luma_lb_size_per_component = bw_int_to_fixed( 82176); - dceip.underlay420_chroma_lb_size_per_component = + dceip->underlay420_chroma_lb_size_per_component = bw_int_to_fixed(164352); - dceip.underlay422_lb_size_per_component = bw_int_to_fixed( + dceip->underlay422_lb_size_per_component = bw_int_to_fixed( 82176); - dceip.cursor_chunk_width = bw_int_to_fixed(64); - dceip.cursor_dcp_buffer_lines = bw_int_to_fixed(4); - dceip.underlay_maximum_width_efficient_for_tiling = + dceip->cursor_chunk_width = bw_int_to_fixed(64); + dceip->cursor_dcp_buffer_lines = bw_int_to_fixed(4); + dceip->underlay_maximum_width_efficient_for_tiling = bw_int_to_fixed(1920); - dceip.underlay_maximum_height_efficient_for_tiling = + dceip->underlay_maximum_height_efficient_for_tiling = bw_int_to_fixed(1080); - dceip.peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display = + dceip->peak_pte_request_to_eviction_ratio_limiting_multiple_displays_or_single_rotated_display = bw_frc_to_fixed(3, 10); - dceip.peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation = + dceip->peak_pte_request_to_eviction_ratio_limiting_single_display_no_rotation = bw_int_to_fixed(25); - dceip.minimum_outstanding_pte_request_limit = bw_int_to_fixed( + dceip->minimum_outstanding_pte_request_limit = bw_int_to_fixed( 2); - dceip.maximum_total_outstanding_pte_requests_allowed_by_saw = + dceip->maximum_total_outstanding_pte_requests_allowed_by_saw = bw_int_to_fixed(128); - dceip.limit_excessive_outstanding_dmif_requests = true; - dceip.linear_mode_line_request_alternation_slice = + dceip->limit_excessive_outstanding_dmif_requests = true; + dceip->linear_mode_line_request_alternation_slice = bw_int_to_fixed(64); - dceip.scatter_gather_lines_of_pte_prefetching_in_linear_mode = + dceip->scatter_gather_lines_of_pte_prefetching_in_linear_mode = 32; - dceip.display_write_back420_luma_mcifwr_buffer_size = 12288; - dceip.display_write_back420_chroma_mcifwr_buffer_size = 8192; - dceip.request_efficiency = bw_frc_to_fixed(8, 10); - dceip.dispclk_per_request = bw_int_to_fixed(2); - dceip.dispclk_ramping_factor = bw_frc_to_fixed(105, 100); - dceip.display_pipe_throughput_factor = bw_frc_to_fixed(105, 100); - dceip.scatter_gather_pte_request_rows_in_tiling_mode = 2; - dceip.mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); + dceip->display_write_back420_luma_mcifwr_buffer_size = 12288; + dceip->display_write_back420_chroma_mcifwr_buffer_size = 8192; + dceip->request_efficiency = bw_frc_to_fixed(8, 10); + dceip->dispclk_per_request = bw_int_to_fixed(2); + dceip->dispclk_ramping_factor = bw_frc_to_fixed(105, 100); + dceip->display_pipe_throughput_factor = bw_frc_to_fixed(105, 100); + dceip->scatter_gather_pte_request_rows_in_tiling_mode = 2; + dceip->mcifwr_all_surfaces_burst_time = bw_int_to_fixed(0); break; default: break; } - *bw_dceip = dceip; - *bw_vbios = vbios; + *bw_dceip = *dceip; + *bw_vbios = *vbios; + kfree(dceip); + kfree(vbios); } /* diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c index f7c728d4f50a..dd52ebf56d62 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c @@ -125,87 +125,140 @@ struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *p { struct hw_asic_id asic_id = ctx->asic_id; - struct clk_mgr_internal *clk_mgr = kzalloc(sizeof(*clk_mgr), GFP_KERNEL); - - if (clk_mgr == NULL) { - BREAK_TO_DEBUGGER(); - return NULL; - } - switch (asic_id.chip_family) { #if defined(CONFIG_DRM_AMD_DC_SI) - case FAMILY_SI: + case FAMILY_SI: { + struct clk_mgr_internal *clk_mgr = kzalloc(sizeof(*clk_mgr), GFP_KERNEL); + + if (clk_mgr == NULL) { + BREAK_TO_DEBUGGER(); + return NULL; + } dce60_clk_mgr_construct(ctx, clk_mgr); - break; + dce_clk_mgr_construct(ctx, clk_mgr); + return &clk_mgr->base; + } #endif case FAMILY_CI: - case FAMILY_KV: + case FAMILY_KV: { + struct clk_mgr_internal *clk_mgr = kzalloc(sizeof(*clk_mgr), GFP_KERNEL); + + if (clk_mgr == NULL) { + BREAK_TO_DEBUGGER(); + return NULL; + } dce_clk_mgr_construct(ctx, clk_mgr); - break; - case FAMILY_CZ: + return &clk_mgr->base; + } + case FAMILY_CZ: { + struct clk_mgr_internal *clk_mgr = kzalloc(sizeof(*clk_mgr), GFP_KERNEL); + + if (clk_mgr == NULL) { + BREAK_TO_DEBUGGER(); + return NULL; + } dce110_clk_mgr_construct(ctx, clk_mgr); - break; - case FAMILY_VI: + return &clk_mgr->base; + } + case FAMILY_VI: { + struct clk_mgr_internal *clk_mgr = kzalloc(sizeof(*clk_mgr), GFP_KERNEL); + + if (clk_mgr == NULL) { + BREAK_TO_DEBUGGER(); + return NULL; + } if (ASIC_REV_IS_TONGA_P(asic_id.hw_internal_rev) || ASIC_REV_IS_FIJI_P(asic_id.hw_internal_rev)) { dce_clk_mgr_construct(ctx, clk_mgr); - break; + return &clk_mgr->base; } if (ASIC_REV_IS_POLARIS10_P(asic_id.hw_internal_rev) || ASIC_REV_IS_POLARIS11_M(asic_id.hw_internal_rev) || ASIC_REV_IS_POLARIS12_V(asic_id.hw_internal_rev)) { dce112_clk_mgr_construct(ctx, clk_mgr); - break; + return &clk_mgr->base; } if (ASIC_REV_IS_VEGAM(asic_id.hw_internal_rev)) { dce112_clk_mgr_construct(ctx, clk_mgr); - break; + return &clk_mgr->base; + } + return &clk_mgr->base; + } + case FAMILY_AI: { + struct clk_mgr_internal *clk_mgr = kzalloc(sizeof(*clk_mgr), GFP_KERNEL); + + if (clk_mgr == NULL) { + BREAK_TO_DEBUGGER(); + return NULL; } - break; - case FAMILY_AI: if (ASICREV_IS_VEGA20_P(asic_id.hw_internal_rev)) dce121_clk_mgr_construct(ctx, clk_mgr); else dce120_clk_mgr_construct(ctx, clk_mgr); - break; - + return &clk_mgr->base; + } #if defined(CONFIG_DRM_AMD_DC_DCN) - case FAMILY_RV: + case FAMILY_RV: { + struct clk_mgr_internal *clk_mgr = kzalloc(sizeof(*clk_mgr), GFP_KERNEL); + + if (clk_mgr == NULL) { + BREAK_TO_DEBUGGER(); + return NULL; + } + if (ASICREV_IS_RENOIR(asic_id.hw_internal_rev)) { rn_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); - break; + return &clk_mgr->base; } if (ASICREV_IS_GREEN_SARDINE(asic_id.hw_internal_rev)) { rn_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); - break; + return &clk_mgr->base; } if (ASICREV_IS_RAVEN2(asic_id.hw_internal_rev)) { rv2_clk_mgr_construct(ctx, clk_mgr, pp_smu); - break; + return &clk_mgr->base; } if (ASICREV_IS_RAVEN(asic_id.hw_internal_rev) || ASICREV_IS_PICASSO(asic_id.hw_internal_rev)) { rv1_clk_mgr_construct(ctx, clk_mgr, pp_smu); - break; + return &clk_mgr->base; } - break; + return &clk_mgr->base; + } + case FAMILY_NV: { + struct clk_mgr_internal *clk_mgr = kzalloc(sizeof(*clk_mgr), GFP_KERNEL); - case FAMILY_NV: + if (clk_mgr == NULL) { + BREAK_TO_DEBUGGER(); + return NULL; + } if (ASICREV_IS_SIENNA_CICHLID_P(asic_id.hw_internal_rev)) { dcn3_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); - break; + return &clk_mgr->base; } if (ASICREV_IS_DIMGREY_CAVEFISH_P(asic_id.hw_internal_rev)) { dcn3_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); - break; + return &clk_mgr->base; + } + if (ASICREV_IS_BEIGE_GOBY_P(asic_id.hw_internal_rev)) { + dcn3_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); + return &clk_mgr->base; } dcn20_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); - break; - + return &clk_mgr->base; + } case FAMILY_VGH: - if (ASICREV_IS_VANGOGH(asic_id.hw_internal_rev)) + if (ASICREV_IS_VANGOGH(asic_id.hw_internal_rev)) { + struct clk_mgr_vgh *clk_mgr = kzalloc(sizeof(*clk_mgr), GFP_KERNEL); + + if (clk_mgr == NULL) { + BREAK_TO_DEBUGGER(); + return NULL; + } vg_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); + return &clk_mgr->base.base; + } break; #endif default: @@ -213,7 +266,7 @@ struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *p break; } - return &clk_mgr->base; + return NULL; } void dc_destroy_clk_mgr(struct clk_mgr *clk_mgr_base) @@ -226,6 +279,12 @@ void dc_destroy_clk_mgr(struct clk_mgr *clk_mgr_base) if (ASICREV_IS_SIENNA_CICHLID_P(clk_mgr_base->ctx->asic_id.hw_internal_rev)) { dcn3_clk_mgr_destroy(clk_mgr); } + if (ASICREV_IS_DIMGREY_CAVEFISH_P(clk_mgr_base->ctx->asic_id.hw_internal_rev)) { + dcn3_clk_mgr_destroy(clk_mgr); + } + if (ASICREV_IS_BEIGE_GOBY_P(clk_mgr_base->ctx->asic_id.hw_internal_rev)) { + dcn3_clk_mgr_destroy(clk_mgr); + } break; case FAMILY_VGH: diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c index 01b1853b7750..416a24db17a9 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c @@ -106,10 +106,10 @@ static void rn_update_clocks_update_dpp_dto(struct clk_mgr_internal *clk_mgr, for (i = 0; i < clk_mgr->base.ctx->dc->res_pool->pipe_count; i++) { int dpp_inst, dppclk_khz, prev_dppclk_khz; - /* Loop index will match dpp->inst if resource exists, - * and we want to avoid dependency on dpp object + /* Loop index may not match dpp->inst if some pipes disabled, + * so select correct inst from res_pool */ - dpp_inst = i; + dpp_inst = clk_mgr->base.ctx->dc->res_pool->dpps[i]->inst; dppclk_khz = context->res_ctx.pipe_ctx[i].plane_res.bw.dppclk_khz; prev_dppclk_khz = clk_mgr->dccg->pipe_dppclk_khz[i]; @@ -761,6 +761,43 @@ static struct wm_table ddr4_wm_table_rn = { } }; +static struct wm_table ddr4_1R_wm_table_rn = { + .entries = { + { + .wm_inst = WM_A, + .wm_type = WM_TYPE_PSTATE_CHG, + .pstate_latency_us = 11.72, + .sr_exit_time_us = 13.90, + .sr_enter_plus_exit_time_us = 14.80, + .valid = true, + }, + { + .wm_inst = WM_B, + .wm_type = WM_TYPE_PSTATE_CHG, + .pstate_latency_us = 11.72, + .sr_exit_time_us = 13.90, + .sr_enter_plus_exit_time_us = 14.80, + .valid = true, + }, + { + .wm_inst = WM_C, + .wm_type = WM_TYPE_PSTATE_CHG, + .pstate_latency_us = 11.72, + .sr_exit_time_us = 13.90, + .sr_enter_plus_exit_time_us = 14.80, + .valid = true, + }, + { + .wm_inst = WM_D, + .wm_type = WM_TYPE_PSTATE_CHG, + .pstate_latency_us = 11.72, + .sr_exit_time_us = 13.90, + .sr_enter_plus_exit_time_us = 14.80, + .valid = true, + }, + } +}; + static struct wm_table lpddr4_wm_table_rn = { .entries = { { @@ -798,34 +835,66 @@ static struct wm_table lpddr4_wm_table_rn = { } }; -static unsigned int find_dcfclk_for_voltage(struct dpm_clocks *clock_table, unsigned int voltage) +static unsigned int find_max_fclk_for_voltage(struct dpm_clocks *clock_table, + unsigned int voltage) { int i; + uint32_t max_clk = 0; - for (i = 0; i < PP_SMU_NUM_DCFCLK_DPM_LEVELS; i++) { - if (clock_table->DcfClocks[i].Vol == voltage) - return clock_table->DcfClocks[i].Freq; + for (i = 0; i < PP_SMU_NUM_FCLK_DPM_LEVELS; i++) { + if (clock_table->FClocks[i].Vol <= voltage) { + max_clk = clock_table->FClocks[i].Freq > max_clk ? + clock_table->FClocks[i].Freq : max_clk; + } } - ASSERT(0); - return 0; + return max_clk; +} + +static unsigned int find_max_memclk_for_voltage(struct dpm_clocks *clock_table, + unsigned int voltage) +{ + int i; + uint32_t max_clk = 0; + + for (i = 0; i < PP_SMU_NUM_MEMCLK_DPM_LEVELS; i++) { + if (clock_table->MemClocks[i].Vol <= voltage) { + max_clk = clock_table->MemClocks[i].Freq > max_clk ? + clock_table->MemClocks[i].Freq : max_clk; + } + } + + return max_clk; +} + +static unsigned int find_max_socclk_for_voltage(struct dpm_clocks *clock_table, + unsigned int voltage) +{ + int i; + uint32_t max_clk = 0; + + for (i = 0; i < PP_SMU_NUM_SOCCLK_DPM_LEVELS; i++) { + if (clock_table->SocClocks[i].Vol <= voltage) { + max_clk = clock_table->SocClocks[i].Freq > max_clk ? + clock_table->SocClocks[i].Freq : max_clk; + } + } + + return max_clk; } static void rn_clk_mgr_helper_populate_bw_params(struct clk_bw_params *bw_params, struct dpm_clocks *clock_table, struct integrated_info *bios_info) { int i, j = 0; + unsigned int volt; j = -1; - ASSERT(PP_SMU_NUM_FCLK_DPM_LEVELS <= MAX_NUM_DPM_LVL); - - /* Find lowest DPM, FCLK is filled in reverse order*/ - - for (i = PP_SMU_NUM_FCLK_DPM_LEVELS - 1; i >= 0; i--) { - if (clock_table->FClocks[i].Freq != 0 && clock_table->FClocks[i].Vol != 0) { + /* Find max DPM */ + for (i = 0; i < PP_SMU_NUM_DCFCLK_DPM_LEVELS; ++i) { + if (clock_table->DcfClocks[i].Freq != 0 && + clock_table->DcfClocks[i].Vol != 0) j = i; - break; - } } if (j == -1) { @@ -836,11 +905,18 @@ static void rn_clk_mgr_helper_populate_bw_params(struct clk_bw_params *bw_params bw_params->clk_table.num_entries = j + 1; - for (i = 0; i < bw_params->clk_table.num_entries; i++, j--) { - bw_params->clk_table.entries[i].fclk_mhz = clock_table->FClocks[j].Freq; - bw_params->clk_table.entries[i].memclk_mhz = clock_table->MemClocks[j].Freq; - bw_params->clk_table.entries[i].voltage = clock_table->FClocks[j].Vol; - bw_params->clk_table.entries[i].dcfclk_mhz = find_dcfclk_for_voltage(clock_table, clock_table->FClocks[j].Vol); + for (i = 0; i < bw_params->clk_table.num_entries; i++) { + volt = clock_table->DcfClocks[i].Vol; + + bw_params->clk_table.entries[i].voltage = volt; + bw_params->clk_table.entries[i].dcfclk_mhz = + clock_table->DcfClocks[i].Freq; + bw_params->clk_table.entries[i].fclk_mhz = + find_max_fclk_for_voltage(clock_table, volt); + bw_params->clk_table.entries[i].memclk_mhz = + find_max_memclk_for_voltage(clock_table, volt); + bw_params->clk_table.entries[i].socclk_mhz = + find_max_socclk_for_voltage(clock_table, volt); } bw_params->vram_type = bios_info->memory_type; @@ -932,8 +1008,12 @@ void rn_clk_mgr_construct( } else { if (is_green_sardine) rn_bw_params.wm_table = ddr4_wm_table_gs; - else - rn_bw_params.wm_table = ddr4_wm_table_rn; + else { + if (ctx->dc->config.is_single_rank_dimm) + rn_bw_params.wm_table = ddr4_1R_wm_table_rn; + else + rn_bw_params.wm_table = ddr4_wm_table_rn; + } } /* Saved clocks configured at boot for debug purposes */ rn_dump_clk_registers(&clk_mgr->base.boot_snapshot, &clk_mgr->base, &log_info); @@ -951,6 +1031,9 @@ void rn_clk_mgr_construct( if (status == PP_SMU_RESULT_OK && ctx->dc_bios && ctx->dc_bios->integrated_info) { rn_clk_mgr_helper_populate_bw_params (clk_mgr->base.bw_params, &clock_table, ctx->dc_bios->integrated_info); + /* treat memory config as single channel if memory is asymmetrics. */ + if (ctx->dc->config.is_asymmetric_memory) + clk_mgr->base.bw_params->num_channels = 1; } } diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c index 81ea5d3a1947..652fa89fae5f 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c @@ -432,6 +432,12 @@ static void dcn3_get_memclk_states_from_smu(struct clk_mgr *clk_mgr_base) clk_mgr->base.ctx->dc, clk_mgr_base->bw_params); } +static bool dcn3_is_smu_present(struct clk_mgr *clk_mgr_base) +{ + struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); + return clk_mgr->smu_present; +} + static bool dcn3_are_clock_states_equal(struct dc_clocks *a, struct dc_clocks *b) { @@ -494,6 +500,7 @@ static struct clk_mgr_funcs dcn3_funcs = { .are_clock_states_equal = dcn3_are_clock_states_equal, .enable_pme_wa = dcn3_enable_pme_wa, .notify_link_rate_change = dcn30_notify_link_rate_change, + .is_smu_present = dcn3_is_smu_present }; static void dcn3_init_clocks_fpga(struct clk_mgr *clk_mgr) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/dcn301_smu.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/dcn301_smu.c index 68942bbc7472..07774fa2c2cf 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/dcn301_smu.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/dcn301_smu.c @@ -113,10 +113,13 @@ int dcn301_smu_send_msg_with_param( int dcn301_smu_get_smu_version(struct clk_mgr_internal *clk_mgr) { - return dcn301_smu_send_msg_with_param( - clk_mgr, - VBIOSSMC_MSG_GetSmuVersion, - 0); + int smu_version = dcn301_smu_send_msg_with_param(clk_mgr, + VBIOSSMC_MSG_GetSmuVersion, + 0); + + DC_LOG_DEBUG("%s %x\n", __func__, smu_version); + + return smu_version; } @@ -124,6 +127,8 @@ int dcn301_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dispc { int actual_dispclk_set_mhz = -1; + DC_LOG_DEBUG("%s(%d)\n", __func__, requested_dispclk_khz); + /* Unit of SMU msg parameter is Mhz */ actual_dispclk_set_mhz = dcn301_smu_send_msg_with_param( clk_mgr, @@ -137,6 +142,8 @@ int dcn301_smu_set_dprefclk(struct clk_mgr_internal *clk_mgr) { int actual_dprefclk_set_mhz = -1; + DC_LOG_DEBUG("%s %d\n", __func__, clk_mgr->base.dprefclk_khz / 1000); + actual_dprefclk_set_mhz = dcn301_smu_send_msg_with_param( clk_mgr, VBIOSSMC_MSG_SetDprefclkFreq, @@ -151,6 +158,8 @@ int dcn301_smu_set_hard_min_dcfclk(struct clk_mgr_internal *clk_mgr, int request { int actual_dcfclk_set_mhz = -1; + DC_LOG_DEBUG("%s(%d)\n", __func__, requested_dcfclk_khz); + actual_dcfclk_set_mhz = dcn301_smu_send_msg_with_param( clk_mgr, VBIOSSMC_MSG_SetHardMinDcfclkByFreq, @@ -163,6 +172,8 @@ int dcn301_smu_set_min_deep_sleep_dcfclk(struct clk_mgr_internal *clk_mgr, int r { int actual_min_ds_dcfclk_mhz = -1; + DC_LOG_DEBUG("%s(%d)\n", __func__, requested_min_ds_dcfclk_khz); + actual_min_ds_dcfclk_mhz = dcn301_smu_send_msg_with_param( clk_mgr, VBIOSSMC_MSG_SetMinDeepSleepDcfclk, @@ -175,6 +186,8 @@ int dcn301_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_kh { int actual_dppclk_set_mhz = -1; + DC_LOG_DEBUG("%s(%d)\n", __func__, requested_dpp_khz); + actual_dppclk_set_mhz = dcn301_smu_send_msg_with_param( clk_mgr, VBIOSSMC_MSG_SetDppclkFreq, @@ -187,6 +200,8 @@ void dcn301_smu_set_display_idle_optimization(struct clk_mgr_internal *clk_mgr, { //TODO: Work with smu team to define optimization options. + DC_LOG_DEBUG("%s(%x)\n", __func__, idle_info); + dcn301_smu_send_msg_with_param( clk_mgr, VBIOSSMC_MSG_SetDisplayIdleOptimizations, @@ -202,6 +217,8 @@ void dcn301_smu_enable_phy_refclk_pwrdwn(struct clk_mgr_internal *clk_mgr, bool idle_info.idle_info.phy_ref_clk_off = 1; } + DC_LOG_DEBUG("%s(%d)\n", __func__, enable); + dcn301_smu_send_msg_with_param( clk_mgr, VBIOSSMC_MSG_SetDisplayIdleOptimizations, @@ -218,12 +235,16 @@ void dcn301_smu_enable_pme_wa(struct clk_mgr_internal *clk_mgr) void dcn301_smu_set_dram_addr_high(struct clk_mgr_internal *clk_mgr, uint32_t addr_high) { + DC_LOG_DEBUG("%s(%x)\n", __func__, addr_high); + dcn301_smu_send_msg_with_param(clk_mgr, VBIOSSMC_MSG_SetVbiosDramAddrHigh, addr_high); } void dcn301_smu_set_dram_addr_low(struct clk_mgr_internal *clk_mgr, uint32_t addr_low) { + DC_LOG_DEBUG("%s(%x)\n", __func__, addr_low); + dcn301_smu_send_msg_with_param(clk_mgr, VBIOSSMC_MSG_SetVbiosDramAddrLow, addr_low); } diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c index aadb801447a7..c636b589d69d 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c @@ -32,9 +32,8 @@ // For dcn20_update_clocks_update_dpp_dto #include "dcn20/dcn20_clk_mgr.h" - - #include "vg_clk_mgr.h" +#include "dcn301_smu.h" #include "reg_helper.h" #include "core_types.h" #include "dm_helpers.h" @@ -50,11 +49,14 @@ /* Macros */ +#define TO_CLK_MGR_VGH(clk_mgr)\ + container_of(clk_mgr, struct clk_mgr_vgh, base) + #define REG(reg_name) \ (CLK_BASE.instance[0].segment[mm ## reg_name ## _BASE_IDX] + mm ## reg_name) /* TODO: evaluate how to lower or disable all dcn clocks in screen off case */ -int vg_get_active_display_cnt_wa( +static int vg_get_active_display_cnt_wa( struct dc *dc, struct dc_state *context) { @@ -134,13 +136,13 @@ void vg_update_clocks(struct clk_mgr *clk_mgr_base, } } - if (should_set_clock(safe_to_lower, new_clocks->dcfclk_khz, clk_mgr_base->clks.dcfclk_khz)) { + if (should_set_clock(safe_to_lower, new_clocks->dcfclk_khz, clk_mgr_base->clks.dcfclk_khz) && !dc->debug.disable_min_fclk) { clk_mgr_base->clks.dcfclk_khz = new_clocks->dcfclk_khz; dcn301_smu_set_hard_min_dcfclk(clk_mgr, clk_mgr_base->clks.dcfclk_khz); } if (should_set_clock(safe_to_lower, - new_clocks->dcfclk_deep_sleep_khz, clk_mgr_base->clks.dcfclk_deep_sleep_khz)) { + new_clocks->dcfclk_deep_sleep_khz, clk_mgr_base->clks.dcfclk_deep_sleep_khz) && !dc->debug.disable_min_fclk) { clk_mgr_base->clks.dcfclk_deep_sleep_khz = new_clocks->dcfclk_deep_sleep_khz; dcn301_smu_set_min_deep_sleep_dcfclk(clk_mgr, clk_mgr_base->clks.dcfclk_deep_sleep_khz); } @@ -377,7 +379,7 @@ void vg_get_clk_states(struct clk_mgr *clk_mgr_base, struct clk_states *s) s->dprefclk_khz = sb.dprefclk * 1000; } -void vg_enable_pme_wa(struct clk_mgr *clk_mgr_base) +static void vg_enable_pme_wa(struct clk_mgr *clk_mgr_base) { struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); @@ -449,15 +451,16 @@ static void vg_build_watermark_ranges(struct clk_bw_params *bw_params, struct wa } -void vg_notify_wm_ranges(struct clk_mgr *clk_mgr_base) +static void vg_notify_wm_ranges(struct clk_mgr *clk_mgr_base) { struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); - struct watermarks *table = clk_mgr_base->smu_wm_set.wm_set; + struct clk_mgr_vgh *clk_mgr_vgh = TO_CLK_MGR_VGH(clk_mgr); + struct watermarks *table = clk_mgr_vgh->smu_wm_set.wm_set; if (!clk_mgr->smu_ver) return; - if (!table || clk_mgr_base->smu_wm_set.mc_address.quad_part == 0) + if (!table || clk_mgr_vgh->smu_wm_set.mc_address.quad_part == 0) return; memset(table, 0, sizeof(*table)); @@ -465,9 +468,9 @@ void vg_notify_wm_ranges(struct clk_mgr *clk_mgr_base) vg_build_watermark_ranges(clk_mgr_base->bw_params, table); dcn301_smu_set_dram_addr_high(clk_mgr, - clk_mgr_base->smu_wm_set.mc_address.high_part); + clk_mgr_vgh->smu_wm_set.mc_address.high_part); dcn301_smu_set_dram_addr_low(clk_mgr, - clk_mgr_base->smu_wm_set.mc_address.low_part); + clk_mgr_vgh->smu_wm_set.mc_address.low_part); dcn301_smu_transfer_wm_table_dram_2_smu(clk_mgr); } @@ -625,7 +628,7 @@ static unsigned int find_dcfclk_for_voltage(const struct vg_dpm_clocks *clock_ta return 0; } -void vg_clk_mgr_helper_populate_bw_params( +static void vg_clk_mgr_helper_populate_bw_params( struct clk_mgr_internal *clk_mgr, struct integrated_info *bios_info, const struct vg_dpm_clocks *clock_table) @@ -703,7 +706,7 @@ static struct vg_dpm_clocks dummy_clocks = { static struct watermarks dummy_wms = { 0 }; -void vg_get_dpm_table_from_smu(struct clk_mgr_internal *clk_mgr, +static void vg_get_dpm_table_from_smu(struct clk_mgr_internal *clk_mgr, struct smu_dpm_clks *smu_dpm_clks) { struct vg_dpm_clocks *table = smu_dpm_clks->dpm_clks; @@ -725,39 +728,39 @@ void vg_get_dpm_table_from_smu(struct clk_mgr_internal *clk_mgr, void vg_clk_mgr_construct( struct dc_context *ctx, - struct clk_mgr_internal *clk_mgr, + struct clk_mgr_vgh *clk_mgr, struct pp_smu_funcs *pp_smu, struct dccg *dccg) { struct smu_dpm_clks smu_dpm_clks = { 0 }; - clk_mgr->base.ctx = ctx; - clk_mgr->base.funcs = &vg_funcs; + clk_mgr->base.base.ctx = ctx; + clk_mgr->base.base.funcs = &vg_funcs; - clk_mgr->pp_smu = pp_smu; + clk_mgr->base.pp_smu = pp_smu; - clk_mgr->dccg = dccg; - clk_mgr->dfs_bypass_disp_clk = 0; + clk_mgr->base.dccg = dccg; + clk_mgr->base.dfs_bypass_disp_clk = 0; - clk_mgr->dprefclk_ss_percentage = 0; - clk_mgr->dprefclk_ss_divider = 1000; - clk_mgr->ss_on_dprefclk = false; - clk_mgr->dfs_ref_freq_khz = 48000; + clk_mgr->base.dprefclk_ss_percentage = 0; + clk_mgr->base.dprefclk_ss_divider = 1000; + clk_mgr->base.ss_on_dprefclk = false; + clk_mgr->base.dfs_ref_freq_khz = 48000; - clk_mgr->base.smu_wm_set.wm_set = (struct watermarks *)dm_helpers_allocate_gpu_mem( - clk_mgr->base.ctx, + clk_mgr->smu_wm_set.wm_set = (struct watermarks *)dm_helpers_allocate_gpu_mem( + clk_mgr->base.base.ctx, DC_MEM_ALLOC_TYPE_FRAME_BUFFER, sizeof(struct watermarks), - &clk_mgr->base.smu_wm_set.mc_address.quad_part); + &clk_mgr->smu_wm_set.mc_address.quad_part); - if (clk_mgr->base.smu_wm_set.wm_set == 0) { - clk_mgr->base.smu_wm_set.wm_set = &dummy_wms; - clk_mgr->base.smu_wm_set.mc_address.quad_part = 0; + if (clk_mgr->smu_wm_set.wm_set == 0) { + clk_mgr->smu_wm_set.wm_set = &dummy_wms; + clk_mgr->smu_wm_set.mc_address.quad_part = 0; } - ASSERT(clk_mgr->base.smu_wm_set.wm_set); + ASSERT(clk_mgr->smu_wm_set.wm_set); smu_dpm_clks.dpm_clks = (struct vg_dpm_clocks *)dm_helpers_allocate_gpu_mem( - clk_mgr->base.ctx, + clk_mgr->base.base.ctx, DC_MEM_ALLOC_TYPE_FRAME_BUFFER, sizeof(struct vg_dpm_clocks), &smu_dpm_clks.mc_address.quad_part); @@ -771,21 +774,21 @@ void vg_clk_mgr_construct( if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) { vg_funcs.update_clocks = dcn2_update_clocks_fpga; - clk_mgr->base.dentist_vco_freq_khz = 3600000; + clk_mgr->base.base.dentist_vco_freq_khz = 3600000; } else { struct clk_log_info log_info = {0}; - clk_mgr->smu_ver = dcn301_smu_get_smu_version(clk_mgr); + clk_mgr->base.smu_ver = dcn301_smu_get_smu_version(&clk_mgr->base); - if (clk_mgr->smu_ver) - clk_mgr->smu_present = true; + if (clk_mgr->base.smu_ver) + clk_mgr->base.smu_present = true; /* TODO: Check we get what we expect during bringup */ - clk_mgr->base.dentist_vco_freq_khz = get_vco_frequency_from_reg(clk_mgr); + clk_mgr->base.base.dentist_vco_freq_khz = get_vco_frequency_from_reg(&clk_mgr->base); /* in case we don't get a value from the register, use default */ - if (clk_mgr->base.dentist_vco_freq_khz == 0) - clk_mgr->base.dentist_vco_freq_khz = 3600000; + if (clk_mgr->base.base.dentist_vco_freq_khz == 0) + clk_mgr->base.base.dentist_vco_freq_khz = 3600000; if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) { vg_bw_params.wm_table = lpddr5_wm_table; @@ -793,36 +796,38 @@ void vg_clk_mgr_construct( vg_bw_params.wm_table = ddr4_wm_table; } /* Saved clocks configured at boot for debug purposes */ - vg_dump_clk_registers(&clk_mgr->base.boot_snapshot, &clk_mgr->base, &log_info); + vg_dump_clk_registers(&clk_mgr->base.base.boot_snapshot, &clk_mgr->base.base, &log_info); } - clk_mgr->base.dprefclk_khz = 600000; - dce_clock_read_ss_info(clk_mgr); + clk_mgr->base.base.dprefclk_khz = 600000; + dce_clock_read_ss_info(&clk_mgr->base); - clk_mgr->base.bw_params = &vg_bw_params; + clk_mgr->base.base.bw_params = &vg_bw_params; - vg_get_dpm_table_from_smu(clk_mgr, &smu_dpm_clks); + vg_get_dpm_table_from_smu(&clk_mgr->base, &smu_dpm_clks); if (ctx->dc_bios && ctx->dc_bios->integrated_info) { vg_clk_mgr_helper_populate_bw_params( - clk_mgr, + &clk_mgr->base, ctx->dc_bios->integrated_info, smu_dpm_clks.dpm_clks); } if (smu_dpm_clks.dpm_clks && smu_dpm_clks.mc_address.quad_part != 0) - dm_helpers_free_gpu_mem(clk_mgr->base.ctx, DC_MEM_ALLOC_TYPE_FRAME_BUFFER, + dm_helpers_free_gpu_mem(clk_mgr->base.base.ctx, DC_MEM_ALLOC_TYPE_FRAME_BUFFER, smu_dpm_clks.dpm_clks); /* - if (!IS_FPGA_MAXIMUS_DC(ctx->dce_environment) && clk_mgr->smu_ver) { + if (!IS_FPGA_MAXIMUS_DC(ctx->dce_environment) && clk_mgr->base.smu_ver) { enable powerfeatures when displaycount goes to 0 dcn301_smu_enable_phy_refclk_pwrdwn(clk_mgr, !debug->disable_48mhz_pwrdwn); } */ } -void vg_clk_mgr_destroy(struct clk_mgr_internal *clk_mgr) +void vg_clk_mgr_destroy(struct clk_mgr_internal *clk_mgr_int) { - if (clk_mgr->base.smu_wm_set.wm_set && clk_mgr->base.smu_wm_set.mc_address.quad_part != 0) - dm_helpers_free_gpu_mem(clk_mgr->base.ctx, DC_MEM_ALLOC_TYPE_FRAME_BUFFER, - clk_mgr->base.smu_wm_set.wm_set); + struct clk_mgr_vgh *clk_mgr = TO_CLK_MGR_VGH(clk_mgr_int); + + if (clk_mgr->smu_wm_set.wm_set && clk_mgr->smu_wm_set.mc_address.quad_part != 0) + dm_helpers_free_gpu_mem(clk_mgr_int->base.ctx, DC_MEM_ALLOC_TYPE_FRAME_BUFFER, + clk_mgr->smu_wm_set.wm_set); } diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.h index b5115b3123a1..7255477307f1 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.h +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.h @@ -25,29 +25,25 @@ #ifndef __VG_CLK_MGR_H__ #define __VG_CLK_MGR_H__ +#include "clk_mgr_internal.h" -int vg_get_active_display_cnt_wa( - struct dc *dc, - struct dc_state *context); +struct watermarks; -void vg_enable_pme_wa(struct clk_mgr *clk_mgr_base); +struct smu_watermark_set { + struct watermarks *wm_set; + union large_integer mc_address; +}; + +struct clk_mgr_vgh { + struct clk_mgr_internal base; + struct smu_watermark_set smu_wm_set; +}; void vg_clk_mgr_construct(struct dc_context *ctx, - struct clk_mgr_internal *clk_mgr, + struct clk_mgr_vgh *clk_mgr, struct pp_smu_funcs *pp_smu, struct dccg *dccg); void vg_clk_mgr_destroy(struct clk_mgr_internal *clk_mgr); -#include "dcn301_smu.h" -void vg_notify_wm_ranges(struct clk_mgr *clk_mgr_base); - -void vg_get_dpm_table_from_smu(struct clk_mgr_internal *clk_mgr, - struct smu_dpm_clks *smu_dpm_clks); - -void vg_clk_mgr_helper_populate_bw_params( - struct clk_mgr_internal *clk_mgr, - struct integrated_info *bios_info, - const struct vg_dpm_clocks *clock_table); - #endif //__VG_CLK_MGR_H__ diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 8e6c815b55d2..ef157b83bacd 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -49,14 +49,16 @@ #include "timing_generator.h" #include "abm.h" #include "virtual/virtual_link_encoder.h" +#include "hubp.h" #include "link_hwss.h" #include "link_encoder.h" +#include "link_enc_cfg.h" +#include "dc_link.h" #include "dc_link_ddc.h" #include "dm_helpers.h" #include "mem_input.h" -#include "hubp.h" #include "dc_link_dp.h" #include "dc_dmub_srv.h" @@ -304,7 +306,10 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc, int i = 0; bool ret = false; - stream->adjust = *adjust; + stream->adjust.v_total_max = adjust->v_total_max; + stream->adjust.v_total_mid = adjust->v_total_mid; + stream->adjust.v_total_mid_frame_num = adjust->v_total_mid_frame_num; + stream->adjust.v_total_min = adjust->v_total_min; for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i]; @@ -312,10 +317,7 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc, if (pipe->stream == stream && pipe->stream_res.tg) { dc->hwss.set_drr(&pipe, 1, - adjust->v_total_min, - adjust->v_total_max, - adjust->v_total_mid, - adjust->v_total_mid_frame_num); + *adjust); ret = true; } @@ -870,6 +872,9 @@ static bool dc_construct(struct dc *dc, if (!create_links(dc, init_params->num_virtual_links)) goto fail; + /* Initialise DIG link encoder resource tracking variables. */ + link_enc_cfg_init(dc, dc->current_state); + return true; fail: @@ -1317,11 +1322,10 @@ bool dc_validate_seamless_boot_timing(const struct dc *dc, struct dc_link *link = sink->link; unsigned int i, enc_inst, tg_inst = 0; - // Seamless port only support single DP and EDP so far - if ((sink->sink_signal != SIGNAL_TYPE_DISPLAY_PORT && - sink->sink_signal != SIGNAL_TYPE_EDP) || - sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT_MST) + /* Support seamless boot on EDP displays only */ + if (sink->sink_signal != SIGNAL_TYPE_EDP) { return false; + } /* Check for enabled DIG to identify enabled display */ if (!link->link_enc->funcs->is_dig_enabled(link->link_enc)) @@ -1394,6 +1398,10 @@ bool dc_validate_seamless_boot_timing(const struct dc *dc, if (crtc_timing->v_sync_width != hw_crtc_timing.v_sync_width) return false; + /* block DSC for now, as VBIOS does not currently support DSC timings */ + if (crtc_timing->flags.DSC) + return false; + if (dc_is_dp_signal(link->connector_signal)) { unsigned int pix_clk_100hz; @@ -1424,6 +1432,11 @@ bool dc_validate_seamless_boot_timing(const struct dc *dc, return false; } + if (is_edp_ilr_optimization_required(link, crtc_timing)) { + DC_LOG_EVENT_LINK_TRAINING("Seamless boot disabled to optimize eDP link rate\n"); + return false; + } + return true; } @@ -2091,6 +2104,10 @@ static enum surface_update_type check_update_surfaces_for_stream( if (stream_status == NULL || stream_status->plane_count != surface_count) overall_type = UPDATE_TYPE_FULL; + if (stream_update && stream_update->pending_test_pattern) { + overall_type = UPDATE_TYPE_FULL; + } + /* some stream updates require passive update */ if (stream_update) { union stream_update_flags *su_flags = &stream_update->stream->update_flags; @@ -2390,6 +2407,8 @@ static void copy_stream_update_to_stream(struct dc *dc, if (update->dither_option) stream->dither_option = *update->dither_option; + if (update->pending_test_pattern) + stream->test_pattern = *update->pending_test_pattern; /* update current stream with writeback info */ if (update->wb_update) { int i; @@ -2485,6 +2504,7 @@ static void commit_planes_do_stream_update(struct dc *dc, } } + /* Full fe update*/ if (update_type == UPDATE_TYPE_FAST) continue; @@ -2492,6 +2512,15 @@ static void commit_planes_do_stream_update(struct dc *dc, if (stream_update->dsc_config) dp_update_dsc_config(pipe_ctx); + if (stream_update->pending_test_pattern) { + dc_link_dp_set_test_pattern(stream->link, + stream->test_pattern.type, + stream->test_pattern.color_space, + stream->test_pattern.p_link_settings, + stream->test_pattern.p_custom_pattern, + stream->test_pattern.cust_pattern_size); + } + if (stream_update->dpms_off) { if (*stream_update->dpms_off) { core_link_disable_stream(pipe_ctx); @@ -2578,6 +2607,17 @@ static void commit_planes_for_stream(struct dc *dc, } } +#ifdef CONFIG_DRM_AMD_DC_DCN + if (stream->test_pattern.type != DP_TEST_PATTERN_VIDEO_MODE) { + struct pipe_ctx *mpcc_pipe; + struct pipe_ctx *odm_pipe; + + for (mpcc_pipe = top_pipe_to_program; mpcc_pipe; mpcc_pipe = mpcc_pipe->bottom_pipe) + for (odm_pipe = mpcc_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) + odm_pipe->ttu_regs.min_ttu_vblank = MAX_TTU; + } +#endif + if ((update_type != UPDATE_TYPE_FAST) && stream->update_flags.bits.dsc_changed) if (top_pipe_to_program->stream_res.tg->funcs->lock_doublebuffer_enable) { if (should_use_dmub_lock(stream->link)) { @@ -2623,7 +2663,6 @@ static void commit_planes_for_stream(struct dc *dc, dc->hwss.interdependent_update_lock(dc, context, false); else dc->hwss.pipe_control_lock(dc, top_pipe_to_program, false); - dc->hwss.post_unlock_program_front_end(dc, context); return; } @@ -2646,6 +2685,10 @@ static void commit_planes_for_stream(struct dc *dc, plane_state->triplebuffer_flips = true; } } + if (update_type == UPDATE_TYPE_FULL) { + /* force vsync flip when reconfiguring pipes to prevent underflow */ + plane_state->flip_immediate = false; + } } } @@ -2720,6 +2763,7 @@ static void commit_planes_for_stream(struct dc *dc, plane_state->flip_immediate); } } + /* Perform requested Updates */ for (i = 0; i < surface_count; i++) { struct dc_plane_state *plane_state = srf_updates[i].surface; @@ -2742,6 +2786,7 @@ static void commit_planes_for_stream(struct dc *dc, dc->hwss.update_plane_addr(dc, pipe_ctx); } } + } if ((update_type != UPDATE_TYPE_FAST) && dc->hwss.interdependent_update_lock) @@ -2784,9 +2829,13 @@ static void commit_planes_for_stream(struct dc *dc, for (j = 0; j < dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; + if (!pipe_ctx->plane_state) + continue; + if (pipe_ctx->bottom_pipe || pipe_ctx->next_odm_pipe || !pipe_ctx->stream || pipe_ctx->stream != stream || - !pipe_ctx->plane_state->update_flags.bits.addr_update) + !pipe_ctx->plane_state->update_flags.bits.addr_update || + pipe_ctx->plane_state->skip_manual_trigger) continue; if (pipe_ctx->stream_res.tg->funcs->program_manual_trigger) @@ -3225,6 +3274,10 @@ void dc_allow_idle_optimizations(struct dc *dc, bool allow) if (dc->debug.disable_idle_power_optimizations) return; + if (dc->clk_mgr != NULL && dc->clk_mgr->funcs->is_smu_present) + if (!dc->clk_mgr->funcs->is_smu_present(dc->clk_mgr)) + return; + if (allow == dc->idle_optimizations_allowed) return; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index f9a33dc52c45..c07b45c021d5 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -48,6 +48,7 @@ #include "dce/dmub_psr.h" #include "dmub/dmub_srv.h" #include "inc/hw/panel_cntl.h" +#include "inc/link_enc_cfg.h" #define DC_LOGGER_INIT(logger) @@ -92,11 +93,14 @@ static void dc_link_destruct(struct dc_link *link) link->panel_cntl->funcs->destroy(&link->panel_cntl); if (link->link_enc) { - /* Update link encoder tracking variables. These are used for the dynamic - * assignment of link encoders to streams. + /* Update link encoder resource tracking variables. These are used for + * the dynamic assignment of link encoders to streams. Virtual links + * are not assigned encoder resources on creation. */ - link->dc->res_pool->link_encoders[link->link_enc->preferred_engine] = NULL; - link->dc->res_pool->dig_link_enc_count--; + if (link->link_id.id != CONNECTOR_ID_VIRTUAL) { + link->dc->res_pool->link_encoders[link->eng_id - ENGINE_ID_DIGA] = NULL; + link->dc->res_pool->dig_link_enc_count--; + } link->link_enc->funcs->destroy(&link->link_enc); } @@ -244,6 +248,16 @@ bool dc_link_detect_sink(struct dc_link *link, enum dc_connection_type *type) link->dc->hwss.edp_wait_for_hpd_ready(link, true); } + /* Link may not have physical HPD pin. */ + if (link->ep_type != DISPLAY_ENDPOINT_PHY) { + if (link->hpd_status) + *type = dc_connection_single; + else + *type = dc_connection_none; + + return true; + } + /* todo: may need to lock gpio access */ hpd_pin = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service); @@ -429,8 +443,18 @@ bool dc_link_is_dp_sink_present(struct dc_link *link) static enum signal_type link_detect_sink(struct dc_link *link, enum dc_detect_reason reason) { - enum signal_type result = get_basic_signal_type(link->link_enc->id, - link->link_id); + enum signal_type result; + struct graphics_object_id enc_id; + + if (link->is_dig_mapping_flexible) + enc_id = (struct graphics_object_id){.id = ENCODER_ID_UNKNOWN}; + else + enc_id = link->link_enc->id; + result = get_basic_signal_type(enc_id, link->link_id); + + /* Use basic signal type for link without physical connector. */ + if (link->ep_type != DISPLAY_ENDPOINT_PHY) + return result; /* Internal digital encoder will detect only dongles * that require digital signal @@ -759,19 +783,20 @@ static bool detect_dp(struct dc_link *link, } if (link->type != dc_connection_mst_branch && - is_dp_active_dongle(link)) { - /* DP active dongles */ - link->type = dc_connection_active_dongle; + is_dp_branch_device(link)) { + /* DP SST branch */ + link->type = dc_connection_sst_branch; if (!link->dpcd_caps.sink_count.bits.SINK_COUNT) { /* - * active dongle unplug processing for short irq + * SST branch unplug processing for short irq */ link_disconnect_sink(link); return true; } - if (link->dpcd_caps.dongle_type != - DISPLAY_DONGLE_DP_HDMI_CONVERTER) + if (is_dp_active_dongle(link) && + (link->dpcd_caps.dongle_type != + DISPLAY_DONGLE_DP_HDMI_CONVERTER)) *converter_disable_audio = true; } } else { @@ -951,7 +976,8 @@ static bool dc_link_detect_helper(struct dc_link *link, case SIGNAL_TYPE_DISPLAY_PORT: { /* wa HPD high coming too early*/ - if (link->link_enc->features.flags.bits.DP_IS_USB_C == 1) { + if (link->ep_type == DISPLAY_ENDPOINT_PHY && + link->link_enc->features.flags.bits.DP_IS_USB_C == 1) { /* if alt mode times out, return false */ if (!wait_for_entering_dp_alt_mode(link)) return false; @@ -971,8 +997,8 @@ static bool dc_link_detect_helper(struct dc_link *link, sizeof(struct dpcd_caps))) same_dpcd = false; } - /* Active dongle downstream unplug*/ - if (link->type == dc_connection_active_dongle && + /* Active SST downstream branch device unplug*/ + if (link->type == dc_connection_sst_branch && link->dpcd_caps.sink_count.bits.SINK_COUNT == 0) { if (prev_sink) /* Downstream unplug */ @@ -1073,6 +1099,24 @@ static bool dc_link_detect_helper(struct dc_link *link, dc_is_dvi_signal(link->connector_signal)) { if (prev_sink) dc_sink_release(prev_sink); + link_disconnect_sink(link); + + return false; + } + /* + * Abort detection for DP connectors if we have + * no EDID and connector is active converter + * as there are no display downstream + * + */ + if (dc_is_dp_sst_signal(link->connector_signal) && + (link->dpcd_caps.dongle_type == + DISPLAY_DONGLE_DP_VGA_CONVERTER || + link->dpcd_caps.dongle_type == + DISPLAY_DONGLE_DP_DVI_CONVERTER)) { + if (prev_sink) + dc_sink_release(prev_sink); + link_disconnect_sink(link); return false; } @@ -1203,14 +1247,25 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) { const struct dc *dc = link->dc; bool ret; + bool can_apply_seamless_boot = false; + int i; + + for (i = 0; i < dc->current_state->stream_count; i++) { + if (dc->current_state->streams[i]->apply_seamless_boot_optimization) { + can_apply_seamless_boot = true; + break; + } + } /* get out of low power state */ - clk_mgr_exit_optimized_pwr_state(dc, dc->clk_mgr); + if (!can_apply_seamless_boot && reason != DETECT_REASON_BOOT) + clk_mgr_exit_optimized_pwr_state(dc, dc->clk_mgr); ret = dc_link_detect_helper(link, reason); /* Go back to power optimized state */ - clk_mgr_optimize_pwr_state(dc, dc->clk_mgr); + if (!can_apply_seamless_boot && reason != DETECT_REASON_BOOT) + clk_mgr_optimize_pwr_state(dc, dc->clk_mgr); return ret; } @@ -1407,6 +1462,8 @@ static bool dc_link_construct(struct dc_link *link, link->link_id = bios->funcs->get_connector_id(bios, init_params->connector_index); + link->ep_type = DISPLAY_ENDPOINT_PHY; + DC_LOG_DC("BIOS object table - link_id: %d", link->link_id.id); if (bios->funcs->get_disp_connector_caps_info) { @@ -1506,10 +1563,12 @@ static bool dc_link_construct(struct dc_link *link, (link->link_id.id == CONNECTOR_ID_EDP || link->link_id.id == CONNECTOR_ID_LVDS)) { panel_cntl_init_data.ctx = dc_ctx; - panel_cntl_init_data.inst = link->link_index; + panel_cntl_init_data.inst = + panel_cntl_init_data.ctx->dc_edp_id_count; link->panel_cntl = link->dc->res_pool->funcs->panel_cntl_create( &panel_cntl_init_data); + panel_cntl_init_data.ctx->dc_edp_id_count++; if (link->panel_cntl == NULL) { DC_ERROR("Failed to create link panel_cntl!\n"); @@ -1541,7 +1600,8 @@ static bool dc_link_construct(struct dc_link *link, /* Update link encoder tracking variables. These are used for the dynamic * assignment of link encoders to streams. */ - link->dc->res_pool->link_encoders[link->link_enc->preferred_engine] = link->link_enc; + link->eng_id = link->link_enc->preferred_engine; + link->dc->res_pool->link_encoders[link->eng_id - ENGINE_ID_DIGA] = link->link_enc; link->dc->res_pool->dig_link_enc_count++; link->link_enc_hw_inst = link->link_enc->transmitter; @@ -1671,21 +1731,27 @@ void link_destroy(struct dc_link **link) static void enable_stream_features(struct pipe_ctx *pipe_ctx) { struct dc_stream_state *stream = pipe_ctx->stream; - struct dc_link *link = stream->link; - union down_spread_ctrl old_downspread; - union down_spread_ctrl new_downspread; - core_link_read_dpcd(link, DP_DOWNSPREAD_CTRL, - &old_downspread.raw, sizeof(old_downspread)); + if (pipe_ctx->stream->signal != SIGNAL_TYPE_DISPLAY_PORT_MST) { + struct dc_link *link = stream->link; + union down_spread_ctrl old_downspread; + union down_spread_ctrl new_downspread; + + core_link_read_dpcd(link, DP_DOWNSPREAD_CTRL, + &old_downspread.raw, sizeof(old_downspread)); + + new_downspread.raw = old_downspread.raw; - new_downspread.raw = old_downspread.raw; + new_downspread.bits.IGNORE_MSA_TIMING_PARAM = + (stream->ignore_msa_timing_param) ? 1 : 0; - new_downspread.bits.IGNORE_MSA_TIMING_PARAM = - (stream->ignore_msa_timing_param) ? 1 : 0; + if (new_downspread.raw != old_downspread.raw) { + core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL, + &new_downspread.raw, sizeof(new_downspread)); + } - if (new_downspread.raw != old_downspread.raw) { - core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL, - &new_downspread.raw, sizeof(new_downspread)); + } else { + dm_helpers_mst_enable_stream_features(stream); } } @@ -1702,6 +1768,8 @@ static enum dc_status enable_link_dp(struct dc_state *state, bool apply_seamless_boot_optimization = false; uint32_t bl_oled_enable_delay = 50; // in ms const uint32_t post_oui_delay = 30; // 30ms + /* Reduce link bandwidth between failed link training attempts. */ + bool do_fallback = false; // check for seamless boot for (i = 0; i < state->stream_count; i++) { @@ -1740,7 +1808,8 @@ static enum dc_status enable_link_dp(struct dc_state *state, skip_video_pattern, LINK_TRAINING_ATTEMPTS, pipe_ctx, - pipe_ctx->stream->signal)) { + pipe_ctx->stream->signal, + do_fallback)) { link->cur_link_settings = link_settings; status = DC_OK; } else { @@ -2805,12 +2874,9 @@ bool dc_link_setup_psr(struct dc_link *link, psr_context->psr_level.u32all = 0; -#if defined(CONFIG_DRM_AMD_DC_DCN) /*skip power down the single pipe since it blocks the cstate*/ - if ((link->ctx->asic_id.chip_family == FAMILY_RV) && - ASICREV_IS_RAVEN(link->ctx->asic_id.hw_internal_rev)) + if (link->ctx->asic_id.chip_family >= FAMILY_RV) psr_context->psr_level.bits.SKIP_CRTC_DISABLE = true; -#endif /* SMU will perform additional powerdown sequence. * For unsupported ASICs, set psr_level flag to skip PSR @@ -2883,8 +2949,8 @@ static struct fixed31_32 get_pbn_per_slot(struct dc_stream_state *stream) static struct fixed31_32 get_pbn_from_bw_in_kbps(uint64_t kbps) { struct fixed31_32 peak_kbps; - uint32_t numerator; - uint32_t denominator; + uint32_t numerator = 0; + uint32_t denominator = 1; /* * margin 5300ppm + 300ppm ~ 0.6% as per spec, factor is 1.006 @@ -3131,50 +3197,6 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) return DC_OK; } -enum dc_status dc_link_reallocate_mst_payload(struct dc_link *link) -{ - int i; - struct pipe_ctx *pipe_ctx; - - // Clear all of MST payload then reallocate - for (i = 0; i < MAX_PIPES; i++) { - pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i]; - - /* driver enable split pipe for external monitors - * we have to check pipe_ctx is split pipe or not - * If it's split pipe, driver using top pipe to - * reaallocate. - */ - if (!pipe_ctx || pipe_ctx->top_pipe) - continue; - - if (pipe_ctx->stream && pipe_ctx->stream->link == link && - pipe_ctx->stream->dpms_off == false && - pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { - deallocate_mst_payload(pipe_ctx); - } - } - - for (i = 0; i < MAX_PIPES; i++) { - pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i]; - - if (!pipe_ctx || pipe_ctx->top_pipe) - continue; - - if (pipe_ctx->stream && pipe_ctx->stream->link == link && - pipe_ctx->stream->dpms_off == false && - pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { - /* enable/disable PHY will clear connection between BE and FE - * need to restore it. - */ - link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc, - pipe_ctx->stream_res.stream_enc->id, true); - dc_link_allocate_mst_payload(pipe_ctx); - } - } - - return DC_OK; -} #if defined(CONFIG_DRM_AMD_DC_HDCP) static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off) @@ -3288,7 +3310,8 @@ void core_link_enable_stream( /* eDP lit up by bios already, no need to enable again. */ if (pipe_ctx->stream->signal == SIGNAL_TYPE_EDP && - apply_edp_fast_boot_optimization) { + apply_edp_fast_boot_optimization && + !pipe_ctx->stream->timing.flags.DSC) { pipe_ctx->stream->dpms_off = false; #if defined(CONFIG_DRM_AMD_DC_HDCP) update_psp_stream_config(pipe_ctx, false); @@ -3350,8 +3373,10 @@ void core_link_enable_stream( /* Set DPS PPS SDP (AKA "info frames") */ if (pipe_ctx->stream->timing.flags.DSC) { if (dc_is_dp_signal(pipe_ctx->stream->signal) || - dc_is_virtual_signal(pipe_ctx->stream->signal)) + dc_is_virtual_signal(pipe_ctx->stream->signal)) { + dp_set_dsc_on_rx(pipe_ctx, true); dp_set_dsc_pps_sdp(pipe_ctx, true); + } } if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) @@ -3505,9 +3530,11 @@ uint32_t dc_bandwidth_in_kbps_from_timing( uint32_t kbps; #if defined(CONFIG_DRM_AMD_DC_DCN) - if (timing->flags.DSC) { - return dc_dsc_stream_bandwidth_in_kbps(timing->pix_clk_100hz, timing->dsc_cfg.bits_per_pixel); - } + if (timing->flags.DSC) + return dc_dsc_stream_bandwidth_in_kbps(timing, + timing->dsc_cfg.bits_per_pixel, + timing->dsc_cfg.num_slices_h, + timing->dsc_cfg.is_dp); #endif switch (timing->display_color_depth) { @@ -3569,19 +3596,6 @@ void dc_link_set_drive_settings(struct dc *dc, dc_link_dp_set_drive_settings(dc->links[i], lt_settings); } -void dc_link_perform_link_training(struct dc *dc, - struct dc_link_settings *link_setting, - bool skip_video_pattern) -{ - int i; - - for (i = 0; i < dc->link_count; i++) - dc_link_dp_perform_link_training( - dc->links[i], - link_setting, - skip_video_pattern); -} - void dc_link_set_preferred_link_settings(struct dc *dc, struct dc_link_settings *link_setting, struct dc_link *link) @@ -3732,8 +3746,22 @@ void dc_link_overwrite_extended_receiver_cap( bool dc_link_is_fec_supported(const struct dc_link *link) { + struct link_encoder *link_enc = NULL; + + /* Links supporting dynamically assigned link encoder will be assigned next + * available encoder if one not already assigned. + */ + if (link->is_dig_mapping_flexible && + link->dc->res_pool->funcs->link_encs_assign) { + link_enc = link_enc_cfg_get_link_enc_used_by_link(link->dc->current_state, link); + if (link_enc == NULL) + link_enc = link_enc_cfg_get_next_avail_link_enc(link->dc, link->dc->current_state); + } else + link_enc = link->link_enc; + ASSERT(link_enc); + return (dc_is_dp_signal(link->connector_signal) && - link->link_enc->features.fec_supported && + link_enc->features.fec_supported && link->dpcd_caps.fec_cap.bits.FEC_CAPABLE && !IS_FPGA_MAXIMUS_DC(link->ctx->dce_environment)); } @@ -3746,7 +3774,8 @@ bool dc_link_should_enable_fec(const struct dc_link *link) if ((link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT_MST && link->local_sink && link->local_sink->edid_caps.panel_patch.disable_fec) || - link->connector_signal == SIGNAL_TYPE_EDP) // Disable FEC for eDP + (link->connector_signal == SIGNAL_TYPE_EDP && + link->dc->debug.force_enable_edp_fec == false)) // Disable FEC for eDP is_fec_disable = true; if (dc_link_is_fec_supported(link) && !link->dc->debug.disable_fec && !is_fec_disable) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c index 64414c51312d..ba6b56f20269 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c @@ -658,7 +658,10 @@ int dc_link_aux_transfer_raw(struct ddc_service *ddc, struct aux_payload *payload, enum aux_return_code_type *operation_result) { - return dce_aux_transfer_raw(ddc, payload, operation_result); + if (dc_enable_dmub_notifications(ddc->ctx->dc)) + return dce_aux_transfer_dmub_raw(ddc, payload, operation_result); + else + return dce_aux_transfer_raw(ddc, payload, operation_result); } /* dc_link_aux_transfer_with_retries() - Attempt to submit an @@ -682,6 +685,10 @@ bool dc_link_aux_try_to_configure_timeout(struct ddc_service *ddc, bool result = false; struct ddc *ddc_pin = ddc->ddc_pin; + /* Do not try to access nonexistent DDC pin. */ + if (ddc->link->ep_type != DISPLAY_ENDPOINT_PHY) + return true; + if (ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]->funcs->configure_timeout) { ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]->funcs->configure_timeout(ddc, timeout); result = true; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 47e6c33f73cb..9e08410bfdfd 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -14,6 +14,7 @@ #include "dpcd_defs.h" #include "dc_dmub_srv.h" #include "dce/dmub_hw_lock_mgr.h" +#include "inc/link_enc_cfg.h" /*Travis*/ static const uint8_t DP_VGA_LVDS_CONVERTER_ID_2[] = "sivarT"; @@ -107,10 +108,50 @@ static void wait_for_training_aux_rd_interval( wait_in_micro_secs); } +static enum dpcd_training_patterns + dc_dp_training_pattern_to_dpcd_training_pattern( + struct dc_link *link, + enum dc_dp_training_pattern pattern) +{ + enum dpcd_training_patterns dpcd_tr_pattern = + DPCD_TRAINING_PATTERN_VIDEOIDLE; + + switch (pattern) { + case DP_TRAINING_PATTERN_SEQUENCE_1: + dpcd_tr_pattern = DPCD_TRAINING_PATTERN_1; + break; + case DP_TRAINING_PATTERN_SEQUENCE_2: + dpcd_tr_pattern = DPCD_TRAINING_PATTERN_2; + break; + case DP_TRAINING_PATTERN_SEQUENCE_3: + dpcd_tr_pattern = DPCD_TRAINING_PATTERN_3; + break; + case DP_TRAINING_PATTERN_SEQUENCE_4: + dpcd_tr_pattern = DPCD_TRAINING_PATTERN_4; + break; + case DP_TRAINING_PATTERN_VIDEOIDLE: + dpcd_tr_pattern = DPCD_TRAINING_PATTERN_VIDEOIDLE; + break; + default: + ASSERT(0); + DC_LOG_HW_LINK_TRAINING("%s: Invalid HW Training pattern: %d\n", + __func__, pattern); + break; + } + + return dpcd_tr_pattern; +} + static void dpcd_set_training_pattern( struct dc_link *link, - union dpcd_training_pattern dpcd_pattern) + enum dc_dp_training_pattern training_pattern) { + union dpcd_training_pattern dpcd_pattern = { {0} }; + + dpcd_pattern.v1_4.TRAINING_PATTERN_SET = + dc_dp_training_pattern_to_dpcd_training_pattern( + link, training_pattern); + core_link_write_dpcd( link, DP_TRAINING_PATTERN_SET, @@ -132,10 +173,22 @@ static enum dc_dp_training_pattern decide_cr_training_pattern( static enum dc_dp_training_pattern decide_eq_training_pattern(struct dc_link *link, const struct dc_link_settings *link_settings) { + struct link_encoder *link_enc; enum dc_dp_training_pattern highest_tp = DP_TRAINING_PATTERN_SEQUENCE_2; - struct encoder_feature_support *features = &link->link_enc->features; + struct encoder_feature_support *features; struct dpcd_caps *dpcd_caps = &link->dpcd_caps; + /* Access link encoder capability based on whether it is statically + * or dynamically assigned to a link. + */ + if (link->is_dig_mapping_flexible && + link->dc->res_pool->funcs->link_encs_assign) + link_enc = link_enc_cfg_get_link_enc_used_by_link(link->dc->current_state, link); + else + link_enc = link->link_enc; + ASSERT(link_enc); + features = &link_enc->features; + if (features->flags.bits.IS_TPS3_CAPABLE) highest_tp = DP_TRAINING_PATTERN_SEQUENCE_3; @@ -227,37 +280,6 @@ static void dpcd_set_link_settings( } } -static enum dpcd_training_patterns - dc_dp_training_pattern_to_dpcd_training_pattern( - struct dc_link *link, - enum dc_dp_training_pattern pattern) -{ - enum dpcd_training_patterns dpcd_tr_pattern = - DPCD_TRAINING_PATTERN_VIDEOIDLE; - - switch (pattern) { - case DP_TRAINING_PATTERN_SEQUENCE_1: - dpcd_tr_pattern = DPCD_TRAINING_PATTERN_1; - break; - case DP_TRAINING_PATTERN_SEQUENCE_2: - dpcd_tr_pattern = DPCD_TRAINING_PATTERN_2; - break; - case DP_TRAINING_PATTERN_SEQUENCE_3: - dpcd_tr_pattern = DPCD_TRAINING_PATTERN_3; - break; - case DP_TRAINING_PATTERN_SEQUENCE_4: - dpcd_tr_pattern = DPCD_TRAINING_PATTERN_4; - break; - default: - ASSERT(0); - DC_LOG_HW_LINK_TRAINING("%s: Invalid HW Training pattern: %d\n", - __func__, pattern); - break; - } - - return dpcd_tr_pattern; -} - static uint8_t dc_dp_initialize_scrambling_data_symbols( struct dc_link *link, enum dc_dp_training_pattern pattern) @@ -284,7 +306,7 @@ static uint8_t dc_dp_initialize_scrambling_data_symbols( static inline bool is_repeater(struct dc_link *link, uint32_t offset) { - return (link->lttpr_non_transparent_mode && offset != 0); + return (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) && (offset != 0); } static void dpcd_set_lt_pattern_and_lane_settings( @@ -420,20 +442,30 @@ static bool is_cr_done(enum dc_lane_count ln_count, } static bool is_ch_eq_done(enum dc_lane_count ln_count, - union lane_status *dpcd_lane_status, - union lane_align_status_updated *lane_status_updated) + union lane_status *dpcd_lane_status) { + bool done = true; uint32_t lane; - if (!lane_status_updated->bits.INTERLANE_ALIGN_DONE) - return false; - else { - for (lane = 0; lane < (uint32_t)(ln_count); lane++) { - if (!dpcd_lane_status[lane].bits.SYMBOL_LOCKED_0 || - !dpcd_lane_status[lane].bits.CHANNEL_EQ_DONE_0) - return false; - } - } - return true; + for (lane = 0; lane < (uint32_t)(ln_count); lane++) + if (!dpcd_lane_status[lane].bits.CHANNEL_EQ_DONE_0) + done = false; + return done; +} + +static bool is_symbol_locked(enum dc_lane_count ln_count, + union lane_status *dpcd_lane_status) +{ + bool locked = true; + uint32_t lane; + for (lane = 0; lane < (uint32_t)(ln_count); lane++) + if (!dpcd_lane_status[lane].bits.SYMBOL_LOCKED_0) + locked = false; + return locked; +} + +static inline bool is_interlane_aligned(union lane_align_status_updated align_status) +{ + return align_status.bits.INTERLANE_ALIGN_DONE == 1; } static void update_drive_settings( @@ -835,10 +867,9 @@ static bool perform_post_lt_adj_req_sequence( if (!is_cr_done(lane_count, dpcd_lane_status)) return false; - if (!is_ch_eq_done( - lane_count, - dpcd_lane_status, - &dpcd_lane_status_updated)) + if (!is_ch_eq_done(lane_count, dpcd_lane_status) || + !is_symbol_locked(lane_count, dpcd_lane_status) || + !is_interlane_aligned(dpcd_lane_status_updated)) return false; for (lane = 0; lane < (uint32_t)(lane_count); lane++) { @@ -992,9 +1023,9 @@ static enum link_training_result perform_channel_equalization_sequence( return LINK_TRAINING_EQ_FAIL_CR; /* 6. check CHEQ done*/ - if (is_ch_eq_done(lane_count, - dpcd_lane_status, - &dpcd_lane_status_updated)) + if (is_ch_eq_done(lane_count, dpcd_lane_status) && + is_symbol_locked(lane_count, dpcd_lane_status) && + is_interlane_aligned(dpcd_lane_status_updated)) return LINK_TRAINING_SUCCESS; /* 7. update VS/PE/PC2 in lt_settings*/ @@ -1072,7 +1103,7 @@ static enum link_training_result perform_clock_recovery_sequence( /* 3. wait receiver to lock-on*/ wait_time_microsec = lt_settings->cr_pattern_time; - if (link->lttpr_non_transparent_mode) + if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) wait_time_microsec = TRAINING_AUX_RD_INTERVAL; wait_for_training_aux_rd_interval( @@ -1098,11 +1129,13 @@ static enum link_training_result perform_clock_recovery_sequence( if (is_max_vs_reached(lt_settings)) break; - /* 7. same voltage*/ - /* Note: VS same for all lanes, - * so comparing first lane is sufficient*/ - if (lt_settings->lane_settings[0].VOLTAGE_SWING == + /* 7. same lane settings*/ + /* Note: settings are the same for all lanes, + * so comparing first lane is sufficient*/ + if ((lt_settings->lane_settings[0].VOLTAGE_SWING == req_settings.lane_settings[0].VOLTAGE_SWING) + && (lt_settings->lane_settings[0].PRE_EMPHASIS == + req_settings.lane_settings[0].PRE_EMPHASIS)) retries_cr++; else retries_cr = 0; @@ -1124,17 +1157,12 @@ static enum link_training_result perform_clock_recovery_sequence( return get_cr_failure(lane_count, dpcd_lane_status); } -static inline enum link_training_result perform_link_training_int( +static inline enum link_training_result dp_transition_to_video_idle( struct dc_link *link, struct link_training_settings *lt_settings, enum link_training_result status) { union lane_count_set lane_count_set = { {0} }; - union dpcd_training_pattern dpcd_pattern = { {0} }; - - /* 3. set training not in progress*/ - dpcd_pattern.v1_4.TRAINING_PATTERN_SET = DPCD_TRAINING_PATTERN_VIDEOIDLE; - dpcd_set_training_pattern(link, dpcd_pattern); /* 4. mainlink output idle pattern*/ dp_set_hw_test_pattern(link, DP_TEST_PATTERN_VIDEO_MODE, NULL, 0); @@ -1165,7 +1193,7 @@ static inline enum link_training_result perform_link_training_int( return status; } -static enum link_training_result check_link_loss_status( +enum link_training_result dp_check_link_loss_status( struct dc_link *link, const struct link_training_settings *link_training_setting) { @@ -1203,7 +1231,7 @@ static enum link_training_result check_link_loss_status( return status; } -static void initialize_training_settings( +static inline void decide_8b_10b_training_settings( struct dc_link *link, const struct dc_link_settings *link_setting, const struct dc_link_training_overrides *overrides, @@ -1247,6 +1275,8 @@ static void initialize_training_settings( else lt_settings->link_settings.link_spread = LINK_SPREAD_05_DOWNSPREAD_30KHZ; + lt_settings->lttpr_mode = link->lttpr_mode; + /* Initialize lane settings overrides */ if (overrides->voltage_swing != NULL) lt_settings->voltage_swing = overrides->voltage_swing; @@ -1299,7 +1329,18 @@ static void initialize_training_settings( lt_settings->enhanced_framing = 1; } -static uint8_t convert_to_count(uint8_t lttpr_repeater_count) +static void decide_training_settings( + struct dc_link *link, + const struct dc_link_settings *link_settings, + const struct dc_link_training_overrides *overrides, + struct link_training_settings *lt_settings) +{ + if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING) + decide_8b_10b_training_settings(link, link_settings, overrides, lt_settings); +} + + +uint8_t dp_convert_to_count(uint8_t lttpr_repeater_count) { switch (lttpr_repeater_count) { case 0x80: // 1 lttpr repeater @@ -1324,7 +1365,20 @@ static uint8_t convert_to_count(uint8_t lttpr_repeater_count) return 0; // invalid value } -static void configure_lttpr_mode(struct dc_link *link) +static void configure_lttpr_mode_transparent(struct dc_link *link) +{ + uint8_t repeater_mode = DP_PHY_REPEATER_MODE_TRANSPARENT; + + DC_LOG_HW_LINK_TRAINING("%s\n Set LTTPR to Transparent Mode\n", __func__); + core_link_write_dpcd(link, + DP_PHY_REPEATER_MODE, + (uint8_t *)&repeater_mode, + sizeof(repeater_mode)); +} + +static void configure_lttpr_mode_non_transparent( + struct dc_link *link, + const struct link_training_settings *lt_settings) { /* aux timeout is already set to extended */ /* RESET/SET lttpr mode to enable non transparent mode */ @@ -1334,17 +1388,22 @@ static void configure_lttpr_mode(struct dc_link *link) enum dc_status result = DC_ERROR_UNEXPECTED; uint8_t repeater_mode = DP_PHY_REPEATER_MODE_TRANSPARENT; - DC_LOG_HW_LINK_TRAINING("%s\n Set LTTPR to Transparent Mode\n", __func__); - result = core_link_write_dpcd(link, - DP_PHY_REPEATER_MODE, - (uint8_t *)&repeater_mode, - sizeof(repeater_mode)); + enum dp_link_encoding encoding = dp_get_link_encoding_format(<_settings->link_settings); + + if (encoding == DP_8b_10b_ENCODING) { + DC_LOG_HW_LINK_TRAINING("%s\n Set LTTPR to Transparent Mode\n", __func__); + result = core_link_write_dpcd(link, + DP_PHY_REPEATER_MODE, + (uint8_t *)&repeater_mode, + sizeof(repeater_mode)); + + } if (result == DC_OK) { link->dpcd_caps.lttpr_caps.mode = repeater_mode; } - if (link->lttpr_non_transparent_mode) { + if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) { DC_LOG_HW_LINK_TRAINING("%s\n Set LTTPR to Non Transparent Mode\n", __func__); @@ -1358,16 +1417,18 @@ static void configure_lttpr_mode(struct dc_link *link) link->dpcd_caps.lttpr_caps.mode = repeater_mode; } - repeater_cnt = convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt); - for (repeater_id = repeater_cnt; repeater_id > 0; repeater_id--) { - aux_interval_address = DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1 + - ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (repeater_id - 1)); - core_link_read_dpcd( - link, - aux_interval_address, - (uint8_t *)&link->dpcd_caps.lttpr_caps.aux_rd_interval[repeater_id - 1], - sizeof(link->dpcd_caps.lttpr_caps.aux_rd_interval[repeater_id - 1])); - link->dpcd_caps.lttpr_caps.aux_rd_interval[repeater_id - 1] &= 0x7F; + if (encoding == DP_8b_10b_ENCODING) { + repeater_cnt = dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt); + for (repeater_id = repeater_cnt; repeater_id > 0; repeater_id--) { + aux_interval_address = DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1 + + ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (repeater_id - 1)); + core_link_read_dpcd( + link, + aux_interval_address, + (uint8_t *)&link->dpcd_caps.lttpr_caps.aux_rd_interval[repeater_id - 1], + sizeof(link->dpcd_caps.lttpr_caps.aux_rd_interval[repeater_id - 1])); + link->dpcd_caps.lttpr_caps.aux_rd_interval[repeater_id - 1] &= 0x7F; + } } } } @@ -1503,7 +1564,7 @@ bool dc_link_dp_perform_link_training_skip_aux( { struct link_training_settings lt_settings; - initialize_training_settings( + decide_training_settings( link, link_setting, &link->preferred_training_settings, @@ -1553,15 +1614,17 @@ enum link_training_result dc_link_dp_perform_link_training( uint8_t repeater_cnt; uint8_t repeater_id; - initialize_training_settings( + decide_training_settings( link, link_setting, &link->preferred_training_settings, <_settings); /* Configure lttpr mode */ - if (link->lttpr_non_transparent_mode) - configure_lttpr_mode(link); + if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) + configure_lttpr_mode_non_transparent(link, <_settings); + else if (link->lttpr_mode == LTTPR_MODE_TRANSPARENT) + configure_lttpr_mode_transparent(link); if (link->ctx->dc->work_arounds.lt_early_cr_pattern) start_clock_recovery_pattern_early(link, <_settings, DPRX); @@ -1576,12 +1639,12 @@ enum link_training_result dc_link_dp_perform_link_training( dp_set_fec_ready(link, fec_enable); - if (link->lttpr_non_transparent_mode) { + if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) { /* 2. perform link training (set link training done * to false is done as well) */ - repeater_cnt = convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt); + repeater_cnt = dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt); for (repeater_id = repeater_cnt; (repeater_id > 0 && status == LINK_TRAINING_SUCCESS); repeater_id--) { @@ -1610,8 +1673,10 @@ enum link_training_result dc_link_dp_perform_link_training( } } + /* 3. set training not in progress*/ + dpcd_set_training_pattern(link, DP_TRAINING_PATTERN_VIDEOIDLE); if ((status == LINK_TRAINING_SUCCESS) || !skip_video_pattern) { - status = perform_link_training_int(link, + status = dp_transition_to_video_idle(link, <_settings, status); } @@ -1621,7 +1686,7 @@ enum link_training_result dc_link_dp_perform_link_training( */ if (link->connector_signal != SIGNAL_TYPE_EDP && status == LINK_TRAINING_SUCCESS) { msleep(5); - status = check_link_loss_status(link, <_settings); + status = dp_check_link_loss_status(link, <_settings); } /* 6. print status message*/ @@ -1633,23 +1698,72 @@ enum link_training_result dc_link_dp_perform_link_training( return status; } +static enum dp_panel_mode try_enable_assr(struct dc_stream_state *stream) +{ + struct dc_link *link = stream->link; + enum dp_panel_mode panel_mode = dp_get_panel_mode(link); +#ifdef CONFIG_DRM_AMD_DC_HDCP + struct cp_psp *cp_psp = &stream->ctx->cp_psp; +#endif + + /* ASSR must be supported on the panel */ + if (panel_mode == DP_PANEL_MODE_DEFAULT) + return panel_mode; + + /* eDP or internal DP only */ + if (link->connector_signal != SIGNAL_TYPE_EDP && + !(link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT && + link->is_internal_display)) + return DP_PANEL_MODE_DEFAULT; + +#ifdef CONFIG_DRM_AMD_DC_HDCP + if (cp_psp && cp_psp->funcs.enable_assr) { + if (!cp_psp->funcs.enable_assr(cp_psp->handle, link)) { + /* since eDP implies ASSR on, change panel + * mode to disable ASSR + */ + panel_mode = DP_PANEL_MODE_DEFAULT; + } + } else + panel_mode = DP_PANEL_MODE_DEFAULT; + +#else + /* turn off ASSR if the implementation is not compiled in */ + panel_mode = DP_PANEL_MODE_DEFAULT; +#endif + return panel_mode; +} + bool perform_link_training_with_retries( const struct dc_link_settings *link_setting, bool skip_video_pattern, int attempts, struct pipe_ctx *pipe_ctx, - enum signal_type signal) + enum signal_type signal, + bool do_fallback) { uint8_t j; uint8_t delay_between_attempts = LINK_TRAINING_RETRY_DELAY; struct dc_stream_state *stream = pipe_ctx->stream; struct dc_link *link = stream->link; - enum dp_panel_mode panel_mode = dp_get_panel_mode(link); + enum dp_panel_mode panel_mode; + struct link_encoder *link_enc; + enum link_training_result status = LINK_TRAINING_CR_FAIL_LANE0; + struct dc_link_settings currnet_setting = *link_setting; + + /* Dynamically assigned link encoders associated with stream rather than + * link. + */ + if (link->dc->res_pool->funcs->link_encs_assign) + link_enc = stream->link_enc; + else + link_enc = link->link_enc; + ASSERT(link_enc); /* We need to do this before the link training to ensure the idle pattern in SST * mode will be sent right after the link training */ - link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc, + link_enc->funcs->connect_dig_be_to_fe(link_enc, pipe_ctx->stream_res.stream_enc->id, true); for (j = 0; j < attempts; ++j) { @@ -1661,7 +1775,7 @@ bool perform_link_training_with_retries( link, signal, pipe_ctx->clock_source->id, - link_setting); + &currnet_setting); if (stream->sink_patches.dppowerup_delay > 0) { int delay_dp_power_up_in_ms = stream->sink_patches.dppowerup_delay; @@ -1669,36 +1783,27 @@ bool perform_link_training_with_retries( msleep(delay_dp_power_up_in_ms); } -#ifdef CONFIG_DRM_AMD_DC_HDCP - if (panel_mode == DP_PANEL_MODE_EDP) { - struct cp_psp *cp_psp = &stream->ctx->cp_psp; - - if (cp_psp && cp_psp->funcs.enable_assr) { - if (!cp_psp->funcs.enable_assr(cp_psp->handle, link)) { - /* since eDP implies ASSR on, change panel - * mode to disable ASSR - */ - panel_mode = DP_PANEL_MODE_DEFAULT; - } - } else - panel_mode = DP_PANEL_MODE_DEFAULT; - } -#endif - + panel_mode = try_enable_assr(stream); dp_set_panel_mode(link, panel_mode); + DC_LOG_DETECTION_DP_CAPS("Link: %d ASSR enabled: %d\n", + link->link_index, + panel_mode != DP_PANEL_MODE_DEFAULT); if (link->aux_access_disabled) { - dc_link_dp_perform_link_training_skip_aux(link, link_setting); - return true; - } else if (dc_link_dp_perform_link_training( - link, - link_setting, - skip_video_pattern) == LINK_TRAINING_SUCCESS) + dc_link_dp_perform_link_training_skip_aux(link, &currnet_setting); return true; + } else { + status = dc_link_dp_perform_link_training( + link, + &currnet_setting, + skip_video_pattern); + if (status == LINK_TRAINING_SUCCESS) + return true; + } /* latest link training still fail, skip delay and keep PHY on */ - if (j == (attempts - 1)) + if (j == (attempts - 1) && link->ep_type == DISPLAY_ENDPOINT_PHY) break; DC_LOG_WARNING("%s: Link training attempt %u of %d failed\n", @@ -1706,6 +1811,19 @@ bool perform_link_training_with_retries( dp_disable_link_phy(link, signal); + /* Abort link training if failure due to sink being unplugged. */ + if (status == LINK_TRAINING_ABORT) + break; + else if (do_fallback) { + decide_fallback_link_setting(*link_setting, &currnet_setting, status); + /* Fail link training if reduced link bandwidth no longer meets + * stream requirements. + */ + if (dc_bandwidth_in_kbps_from_timing(&stream->timing) < + dc_link_bandwidth_kbps(link, &currnet_setting)) + break; + } + msleep(delay_between_attempts); delay_between_attempts += LINK_TRAINING_RETRY_DELAY; @@ -1781,7 +1899,7 @@ enum link_training_result dc_link_dp_sync_lt_attempt( enum clock_source_id dp_cs_id = CLOCK_SOURCE_ID_EXTERNAL; bool fec_enable = false; - initialize_training_settings( + decide_training_settings( link, link_settings, lt_overrides, @@ -1851,6 +1969,24 @@ bool dc_link_dp_sync_lt_end(struct dc_link *link, bool link_down) return true; } +bool dc_link_dp_get_max_link_enc_cap(const struct dc_link *link, struct dc_link_settings *max_link_enc_cap) +{ + if (!max_link_enc_cap) { + DC_LOG_ERROR("%s: Could not return max link encoder caps", __func__); + return false; + } + + if (link->link_enc->funcs->get_max_link_cap) { + link->link_enc->funcs->get_max_link_cap(link->link_enc, max_link_enc_cap); + return true; + } + + DC_LOG_ERROR("%s: Max link encoder caps unknown", __func__); + max_link_enc_cap->lane_count = 1; + max_link_enc_cap->link_rate = 6; + return false; +} + static struct dc_link_settings get_max_link_cap(struct dc_link *link) { struct dc_link_settings max_link_cap = {0}; @@ -1873,7 +2009,7 @@ static struct dc_link_settings get_max_link_cap(struct dc_link *link) * account for lttpr repeaters cap * notes: repeaters do not snoop in the DPRX Capabilities addresses (3.6.3). */ - if (link->lttpr_non_transparent_mode) { + if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) { if (link->dpcd_caps.lttpr_caps.max_lane_count < max_link_cap.lane_count) max_link_cap.lane_count = link->dpcd_caps.lttpr_caps.max_lane_count; @@ -2031,7 +2167,7 @@ bool dp_verify_link_cap( max_link_cap = get_max_link_cap(link); /* Grant extended timeout request */ - if (link->lttpr_non_transparent_mode && link->dpcd_caps.lttpr_caps.max_ext_timeout > 0) { + if ((link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) && (link->dpcd_caps.lttpr_caps.max_ext_timeout > 0)) { uint8_t grant = link->dpcd_caps.lttpr_caps.max_ext_timeout & 0x80; core_link_write_dpcd(link, DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT, &grant, sizeof(grant)); @@ -2369,6 +2505,12 @@ bool dp_validate_mode_timing( const struct dc_link_settings *link_setting; + /* According to spec, VSC SDP should be used if pixel format is YCbCr420 */ + if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420 && + !link->dpcd_caps.dprx_feature.bits.VSC_SDP_COLORIMETRY_SUPPORTED && + dal_graphics_object_id_get_connector_id(link->link_id) != CONNECTOR_ID_VIRTUAL) + return false; + /*always DP fail safe mode*/ if ((timing->pix_clk_100hz / 10) == (uint32_t) 25175 && timing->h_addressable == (uint32_t) 640 && @@ -2447,13 +2589,17 @@ static bool decide_dp_link_settings(struct dc_link *link, struct dc_link_setting return false; } -static bool decide_edp_link_settings(struct dc_link *link, struct dc_link_settings *link_setting, uint32_t req_bw) +bool decide_edp_link_settings(struct dc_link *link, struct dc_link_settings *link_setting, uint32_t req_bw) { struct dc_link_settings initial_link_setting; struct dc_link_settings current_link_setting; uint32_t link_bw; - if (link->dpcd_caps.dpcd_rev.raw < DPCD_REV_14 || + /* + * edp_supported_link_rates_count is only valid for eDP v1.4 or higher. + * Per VESA eDP spec, "The DPCD revision for eDP v1.4 is 13h" + */ + if (link->dpcd_caps.dpcd_rev.raw < DPCD_REV_13 || link->dpcd_caps.edp_supported_link_rates_count == 0) { *link_setting = link->verified_link_cap; return true; @@ -2551,13 +2697,11 @@ static bool allow_hpd_rx_irq(const struct dc_link *link) /* * Don't handle RX IRQ unless one of following is met: * 1) The link is established (cur_link_settings != unknown) - * 2) We kicked off MST detection - * 3) We know we're dealing with an active dongle + * 2) We know we're dealing with a branch device, SST or MST */ if ((link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) || - (link->type == dc_connection_mst_branch) || - is_dp_active_dongle(link)) + is_dp_branch_device(link)) return true; return false; @@ -2655,9 +2799,10 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link) union phy_test_pattern dpcd_test_pattern; union lane_adjust dpcd_lane_adjustment[2]; unsigned char dpcd_post_cursor_2_adjustment = 0; - unsigned char test_80_bit_pattern[ + unsigned char test_pattern_buffer[ (DP_TEST_80BIT_CUSTOM_PATTERN_79_72 - DP_TEST_80BIT_CUSTOM_PATTERN_7_0)+1] = {0}; + unsigned int test_pattern_size = 0; enum dp_test_pattern test_pattern; struct dc_link_training_settings link_settings; union lane_adjust dpcd_lane_adjust; @@ -2727,12 +2872,15 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link) break; } - if (test_pattern == DP_TEST_PATTERN_80BIT_CUSTOM) + if (test_pattern == DP_TEST_PATTERN_80BIT_CUSTOM) { + test_pattern_size = (DP_TEST_80BIT_CUSTOM_PATTERN_79_72 - + DP_TEST_80BIT_CUSTOM_PATTERN_7_0) + 1; core_link_read_dpcd( link, DP_TEST_80BIT_CUSTOM_PATTERN_7_0, - test_80_bit_pattern, - sizeof(test_80_bit_pattern)); + test_pattern_buffer, + test_pattern_size); + } /* prepare link training settings */ link_settings.link = link->cur_link_settings; @@ -2770,9 +2918,8 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link) test_pattern, DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED, &link_training_settings, - test_80_bit_pattern, - (DP_TEST_80BIT_CUSTOM_PATTERN_79_72 - - DP_TEST_80BIT_CUSTOM_PATTERN_7_0)+1); + test_pattern_buffer, + test_pattern_size); } static void dp_test_send_link_test_pattern(struct dc_link *link) @@ -2782,10 +2929,27 @@ static void dp_test_send_link_test_pattern(struct dc_link *link) enum dp_test_pattern test_pattern; enum dp_test_pattern_color_space test_pattern_color_space = DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED; + enum dc_color_depth requestColorDepth = COLOR_DEPTH_UNDEFINED; + struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx; + struct pipe_ctx *pipe_ctx = NULL; + int i; memset(&dpcd_test_pattern, 0, sizeof(dpcd_test_pattern)); memset(&dpcd_test_params, 0, sizeof(dpcd_test_params)); + for (i = 0; i < MAX_PIPES; i++) { + if (pipes[i].stream == NULL) + continue; + + if (pipes[i].stream->link == link && !pipes[i].top_pipe && !pipes[i].prev_odm_pipe) { + pipe_ctx = &pipes[i]; + break; + } + } + + if (pipe_ctx == NULL) + return; + /* get link test pattern and pattern parameters */ core_link_read_dpcd( link, @@ -2823,6 +2987,50 @@ static void dp_test_send_link_test_pattern(struct dc_link *link) DP_TEST_PATTERN_COLOR_SPACE_YCBCR709 : DP_TEST_PATTERN_COLOR_SPACE_YCBCR601; + switch (dpcd_test_params.bits.BPC) { + case 0: // 6 bits + requestColorDepth = COLOR_DEPTH_666; + break; + case 1: // 8 bits + requestColorDepth = COLOR_DEPTH_888; + break; + case 2: // 10 bits + requestColorDepth = COLOR_DEPTH_101010; + break; + case 3: // 12 bits + requestColorDepth = COLOR_DEPTH_121212; + break; + default: + break; + } + + switch (dpcd_test_params.bits.CLR_FORMAT) { + case 0: + pipe_ctx->stream->timing.pixel_encoding = PIXEL_ENCODING_RGB; + break; + case 1: + pipe_ctx->stream->timing.pixel_encoding = PIXEL_ENCODING_YCBCR422; + break; + case 2: + pipe_ctx->stream->timing.pixel_encoding = PIXEL_ENCODING_YCBCR444; + break; + default: + pipe_ctx->stream->timing.pixel_encoding = PIXEL_ENCODING_RGB; + break; + } + + + if (requestColorDepth != COLOR_DEPTH_UNDEFINED + && pipe_ctx->stream->timing.display_color_depth != requestColorDepth) { + DC_LOG_DEBUG("%s: original bpc %d, changing to %d\n", + __func__, + pipe_ctx->stream->timing.display_color_depth, + requestColorDepth); + pipe_ctx->stream->timing.display_color_depth = requestColorDepth; + } + + dp_update_dsc_config(pipe_ctx); + dc_link_dp_set_test_pattern( link, test_pattern, @@ -3078,7 +3286,7 @@ bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd *out_link_loss = true; } - if (link->type == dc_connection_active_dongle && + if (link->type == dc_connection_sst_branch && hpd_irq_dpcd_data.bytes.sink_cnt.bits.SINK_COUNT != link->dpcd_sink_count) status = true; @@ -3129,6 +3337,12 @@ bool is_mst_supported(struct dc_link *link) bool is_dp_active_dongle(const struct dc_link *link) { + return (link->dpcd_caps.dongle_type >= DISPLAY_DONGLE_DP_VGA_CONVERTER) && + (link->dpcd_caps.dongle_type <= DISPLAY_DONGLE_DP_HDMI_CONVERTER); +} + +bool is_dp_branch_device(const struct dc_link *link) +{ return link->dpcd_caps.is_branch_dev; } @@ -3369,6 +3583,9 @@ static bool retrieve_link_cap(struct dc_link *link) struct dp_sink_hw_fw_revision dp_hw_fw_revision; bool is_lttpr_present = false; const uint32_t post_oui_delay = 30; // 30ms + bool vbios_lttpr_enable = false; + bool vbios_lttpr_interop = false; + struct dc_bios *bios = link->dc->ctx->dc_bios; memset(dpcd_data, '\0', sizeof(dpcd_data)); memset(lttpr_dpcd_data, '\0', sizeof(lttpr_dpcd_data)); @@ -3416,13 +3633,45 @@ static bool retrieve_link_cap(struct dc_link *link) return false; } - if (link->dc->caps.extended_aux_timeout_support && - link->dc->config.allow_lttpr_non_transparent_mode) { + /* Query BIOS to determine if LTTPR functionality is forced on by system */ + if (bios->funcs->get_lttpr_caps) { + enum bp_result bp_query_result; + uint8_t is_vbios_lttpr_enable = 0; + + bp_query_result = bios->funcs->get_lttpr_caps(bios, &is_vbios_lttpr_enable); + vbios_lttpr_enable = (bp_query_result == BP_RESULT_OK) && !!is_vbios_lttpr_enable; + } + + if (bios->funcs->get_lttpr_interop) { + enum bp_result bp_query_result; + uint8_t is_vbios_interop_enabled = 0; + + bp_query_result = bios->funcs->get_lttpr_interop(bios, &is_vbios_interop_enabled); + vbios_lttpr_interop = (bp_query_result == BP_RESULT_OK) && !!is_vbios_interop_enabled; + } + + /* + * Logic to determine LTTPR mode + */ + link->lttpr_mode = LTTPR_MODE_NON_LTTPR; + if (vbios_lttpr_enable && vbios_lttpr_interop) + link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT; + else if (!vbios_lttpr_enable && vbios_lttpr_interop) { + if (link->dc->config.allow_lttpr_non_transparent_mode) + link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT; + else + link->lttpr_mode = LTTPR_MODE_TRANSPARENT; + } else if (!vbios_lttpr_enable && !vbios_lttpr_interop) { + if (!link->dc->config.allow_lttpr_non_transparent_mode + || !link->dc->caps.extended_aux_timeout_support) + link->lttpr_mode = LTTPR_MODE_NON_LTTPR; + else + link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT; + } + + if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT || link->lttpr_mode == LTTPR_MODE_TRANSPARENT) { /* By reading LTTPR capability, RX assumes that we will enable - * LTTPR non transparent if LTTPR is present. - * Therefore, only query LTTPR capability when both LTTPR - * extended aux timeout and - * non transparent mode is supported by hardware + * LTTPR extended aux timeout if LTTPR is present. */ status = core_link_read_dpcd( link, @@ -3454,17 +3703,18 @@ static bool retrieve_link_cap(struct dc_link *link) lttpr_dpcd_data[DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT - DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; + /* Attempt to train in LTTPR transparent mode if repeater count exceeds 8. */ is_lttpr_present = (link->dpcd_caps.lttpr_caps.phy_repeater_cnt > 0 && + link->dpcd_caps.lttpr_caps.phy_repeater_cnt < 0xff && link->dpcd_caps.lttpr_caps.max_lane_count > 0 && link->dpcd_caps.lttpr_caps.max_lane_count <= 4 && link->dpcd_caps.lttpr_caps.revision.raw >= 0x14); if (is_lttpr_present) CONN_DATA_DETECT(link, lttpr_dpcd_data, sizeof(lttpr_dpcd_data), "LTTPR Caps: "); + else + link->lttpr_mode = LTTPR_MODE_NON_LTTPR; } - /* decide lttpr non transparent mode */ - link->lttpr_non_transparent_mode = is_lttpr_present; - if (!is_lttpr_present) dc_link_aux_try_to_configure_timeout(link->ddc, LINK_AUX_DEFAULT_TIMEOUT_PERIOD); @@ -3772,8 +4022,12 @@ void detect_edp_sink_caps(struct dc_link *link) link->dpcd_caps.edp_supported_link_rates_count = 0; memset(supported_link_rates, 0, sizeof(supported_link_rates)); - if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_14 && - (link->dc->config.optimize_edp_link_rate || + /* + * edp_supported_link_rates_count is only valid for eDP v1.4 or higher. + * Per VESA eDP spec, "The DPCD revision for eDP v1.4 is 13h" + */ + if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_13 && + (link->dc->debug.optimize_edp_link_rate || link->reported_link_cap.link_rate == LINK_RATE_UNKNOWN)) { // Read DPCD 00010h - 0001Fh 16 bytes at one shot core_link_read_dpcd(link, DP_SUPPORTED_LINK_RATES, @@ -4599,3 +4853,58 @@ bool dc_link_set_default_brightness_aux(struct dc_link *link) } return false; } + +bool is_edp_ilr_optimization_required(struct dc_link *link, struct dc_crtc_timing *crtc_timing) +{ + struct dc_link_settings link_setting; + uint8_t link_bw_set; + uint8_t link_rate_set; + uint32_t req_bw; + union lane_count_set lane_count_set = { {0} }; + + ASSERT(link || crtc_timing); // invalid input + + if (link->dpcd_caps.edp_supported_link_rates_count == 0 || + !link->dc->debug.optimize_edp_link_rate) + return false; + + + // Read DPCD 00100h to find if standard link rates are set + core_link_read_dpcd(link, DP_LINK_BW_SET, + &link_bw_set, sizeof(link_bw_set)); + + if (link_bw_set) { + DC_LOG_EVENT_LINK_TRAINING("eDP ILR: Optimization required, VBIOS used link_bw_set\n"); + return true; + } + + // Read DPCD 00115h to find the edp link rate set used + core_link_read_dpcd(link, DP_LINK_RATE_SET, + &link_rate_set, sizeof(link_rate_set)); + + // Read DPCD 00101h to find out the number of lanes currently set + core_link_read_dpcd(link, DP_LANE_COUNT_SET, + &lane_count_set.raw, sizeof(lane_count_set)); + + req_bw = dc_bandwidth_in_kbps_from_timing(crtc_timing); + + decide_edp_link_settings(link, &link_setting, req_bw); + + if (link->dpcd_caps.edp_supported_link_rates[link_rate_set] != link_setting.link_rate || + lane_count_set.bits.LANE_COUNT_SET != link_setting.lane_count) { + DC_LOG_EVENT_LINK_TRAINING("eDP ILR: Optimization required, VBIOS link_rate_set not optimal\n"); + return true; + } + + DC_LOG_EVENT_LINK_TRAINING("eDP ILR: No optimization required, VBIOS set optimal link_rate_set\n"); + return false; +} + +enum dp_link_encoding dp_get_link_encoding_format(const struct dc_link_settings *link_settings) +{ + if ((link_settings->link_rate >= LINK_RATE_LOW) && + (link_settings->link_rate <= LINK_RATE_HIGH3)) + return DP_8b_10b_ENCODING; + return DP_UNKNOWN_ENCODING; +} + diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c new file mode 100644 index 000000000000..1a89d565c92e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c @@ -0,0 +1,315 @@ +/* + * Copyright 2021 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "link_enc_cfg.h" +#include "resource.h" +#include "dc_link_dp.h" + +/* Check whether stream is supported by DIG link encoders. */ +static bool is_dig_link_enc_stream(struct dc_stream_state *stream) +{ + bool is_dig_stream = false; + struct link_encoder *link_enc = NULL; + int i; + + /* Loop over created link encoder objects. */ + for (i = 0; i < stream->ctx->dc->res_pool->res_cap->num_dig_link_enc; i++) { + link_enc = stream->ctx->dc->res_pool->link_encoders[i]; + + if (link_enc && + ((uint32_t)stream->signal & link_enc->output_signals)) { + if (dc_is_dp_signal(stream->signal)) { + /* DIGs do not support DP2.0 streams with 128b/132b encoding. */ + struct dc_link_settings link_settings = {0}; + + decide_link_settings(stream, &link_settings); + if ((link_settings.link_rate >= LINK_RATE_LOW) && + link_settings.link_rate <= LINK_RATE_HIGH3) { + is_dig_stream = true; + break; + } + } else { + is_dig_stream = true; + break; + } + } + } + + return is_dig_stream; +} + +/* Update DIG link encoder resource tracking variables in dc_state. */ +static void update_link_enc_assignment( + struct dc_state *state, + struct dc_stream_state *stream, + enum engine_id eng_id, + bool add_enc) +{ + int eng_idx; + int stream_idx; + int i; + + if (eng_id != ENGINE_ID_UNKNOWN) { + eng_idx = eng_id - ENGINE_ID_DIGA; + stream_idx = -1; + + /* Index of stream in dc_state used to update correct entry in + * link_enc_assignments table. + */ + for (i = 0; i < state->stream_count; i++) { + if (stream == state->streams[i]) { + stream_idx = i; + break; + } + } + + /* Update link encoder assignments table, link encoder availability + * pool and link encoder assigned to stream in state. + * Add/remove encoder resource to/from stream. + */ + if (stream_idx != -1) { + if (add_enc) { + state->res_ctx.link_enc_assignments[stream_idx] = (struct link_enc_assignment){ + .valid = true, + .ep_id = (struct display_endpoint_id) { + .link_id = stream->link->link_id, + .ep_type = stream->link->ep_type}, + .eng_id = eng_id}; + state->res_ctx.link_enc_avail[eng_idx] = ENGINE_ID_UNKNOWN; + stream->link_enc = stream->ctx->dc->res_pool->link_encoders[eng_idx]; + } else { + state->res_ctx.link_enc_assignments[stream_idx].valid = false; + state->res_ctx.link_enc_avail[eng_idx] = eng_id; + stream->link_enc = NULL; + } + } else { + dm_output_to_console("%s: Stream not found in dc_state.\n", __func__); + } + } +} + +/* Return first available DIG link encoder. */ +static enum engine_id find_first_avail_link_enc( + const struct dc_context *ctx, + const struct dc_state *state) +{ + enum engine_id eng_id = ENGINE_ID_UNKNOWN; + int i; + + for (i = 0; i < ctx->dc->res_pool->res_cap->num_dig_link_enc; i++) { + eng_id = state->res_ctx.link_enc_avail[i]; + if (eng_id != ENGINE_ID_UNKNOWN) + break; + } + + return eng_id; +} + +/* Return stream using DIG link encoder resource. NULL if unused. */ +static struct dc_stream_state *get_stream_using_link_enc( + struct dc_state *state, + enum engine_id eng_id) +{ + struct dc_stream_state *stream = NULL; + int stream_idx = -1; + int i; + + for (i = 0; i < state->stream_count; i++) { + struct link_enc_assignment assignment = state->res_ctx.link_enc_assignments[i]; + + if (assignment.valid && (assignment.eng_id == eng_id)) { + stream_idx = i; + break; + } + } + + if (stream_idx != -1) + stream = state->streams[stream_idx]; + else + dm_output_to_console("%s: No stream using DIG(%d).\n", __func__, eng_id); + + return stream; +} + +void link_enc_cfg_init( + struct dc *dc, + struct dc_state *state) +{ + int i; + + for (i = 0; i < dc->res_pool->res_cap->num_dig_link_enc; i++) { + if (dc->res_pool->link_encoders[i]) + state->res_ctx.link_enc_avail[i] = (enum engine_id) i; + else + state->res_ctx.link_enc_avail[i] = ENGINE_ID_UNKNOWN; + } +} + +void link_enc_cfg_link_encs_assign( + struct dc *dc, + struct dc_state *state, + struct dc_stream_state *streams[], + uint8_t stream_count) +{ + enum engine_id eng_id = ENGINE_ID_UNKNOWN; + int i; + + /* Release DIG link encoder resources before running assignment algorithm. */ + for (i = 0; i < stream_count; i++) + dc->res_pool->funcs->link_enc_unassign(state, streams[i]); + + /* (a) Assign DIG link encoders to physical (unmappable) endpoints first. */ + for (i = 0; i < stream_count; i++) { + struct dc_stream_state *stream = streams[i]; + + /* Skip stream if not supported by DIG link encoder. */ + if (!is_dig_link_enc_stream(stream)) + continue; + + /* Physical endpoints have a fixed mapping to DIG link encoders. */ + if (!stream->link->is_dig_mapping_flexible) { + eng_id = stream->link->eng_id; + update_link_enc_assignment(state, stream, eng_id, true); + } + } + + /* (b) Then assign encoders to mappable endpoints. */ + eng_id = ENGINE_ID_UNKNOWN; + + for (i = 0; i < stream_count; i++) { + struct dc_stream_state *stream = streams[i]; + + /* Skip stream if not supported by DIG link encoder. */ + if (!is_dig_link_enc_stream(stream)) + continue; + + /* Mappable endpoints have a flexible mapping to DIG link encoders. */ + if (stream->link->is_dig_mapping_flexible) { + eng_id = find_first_avail_link_enc(stream->ctx, state); + update_link_enc_assignment(state, stream, eng_id, true); + } + } +} + +void link_enc_cfg_link_enc_unassign( + struct dc_state *state, + struct dc_stream_state *stream) +{ + enum engine_id eng_id = ENGINE_ID_UNKNOWN; + + /* Only DIG link encoders. */ + if (!is_dig_link_enc_stream(stream)) + return; + + if (stream->link_enc) + eng_id = stream->link_enc->preferred_engine; + + update_link_enc_assignment(state, stream, eng_id, false); +} + +bool link_enc_cfg_is_transmitter_mappable( + struct dc_state *state, + struct link_encoder *link_enc) +{ + bool is_mappable = false; + enum engine_id eng_id = link_enc->preferred_engine; + struct dc_stream_state *stream = get_stream_using_link_enc(state, eng_id); + + if (stream) + is_mappable = stream->link->is_dig_mapping_flexible; + + return is_mappable; +} + +struct dc_link *link_enc_cfg_get_link_using_link_enc( + struct dc_state *state, + enum engine_id eng_id) +{ + struct dc_link *link = NULL; + int stream_idx = -1; + int i; + + for (i = 0; i < state->stream_count; i++) { + struct link_enc_assignment assignment = state->res_ctx.link_enc_assignments[i]; + + if (assignment.valid && (assignment.eng_id == eng_id)) { + stream_idx = i; + break; + } + } + + if (stream_idx != -1) + link = state->streams[stream_idx]->link; + else + dm_output_to_console("%s: No link using DIG(%d).\n", __func__, eng_id); + + return link; +} + +struct link_encoder *link_enc_cfg_get_link_enc_used_by_link( + struct dc_state *state, + const struct dc_link *link) +{ + struct link_encoder *link_enc = NULL; + struct display_endpoint_id ep_id; + int stream_idx = -1; + int i; + + ep_id = (struct display_endpoint_id) { + .link_id = link->link_id, + .ep_type = link->ep_type}; + + for (i = 0; i < state->stream_count; i++) { + struct link_enc_assignment assignment = state->res_ctx.link_enc_assignments[i]; + + if (assignment.valid && + assignment.ep_id.link_id.id == ep_id.link_id.id && + assignment.ep_id.link_id.enum_id == ep_id.link_id.enum_id && + assignment.ep_id.link_id.type == ep_id.link_id.type && + assignment.ep_id.ep_type == ep_id.ep_type) { + stream_idx = i; + break; + } + } + + if (stream_idx != -1) + link_enc = state->streams[stream_idx]->link_enc; + + return link_enc; +} + +struct link_encoder *link_enc_cfg_get_next_avail_link_enc( + const struct dc *dc, + const struct dc_state *state) +{ + struct link_encoder *link_enc = NULL; + enum engine_id eng_id = ENGINE_ID_UNKNOWN; + + eng_id = find_first_avail_link_enc(dc->ctx, state); + if (eng_id != ENGINE_ID_UNKNOWN) + link_enc = dc->res_pool->link_encoders[eng_id - ENGINE_ID_DIGA]; + + return link_enc; +} diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 124ce215fca5..13c5c4a34a58 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -14,6 +14,7 @@ #include "dpcd_defs.h" #include "dsc.h" #include "resource.h" +#include "link_enc_cfg.h" #include "clk_mgr.h" static uint8_t convert_to_count(uint8_t lttpr_repeater_count) @@ -95,7 +96,7 @@ void dp_enable_link_phy( enum clock_source_id clock_source, const struct dc_link_settings *link_settings) { - struct link_encoder *link_enc = link->link_enc; + struct link_encoder *link_enc; struct dc *dc = link->ctx->dc; struct dmcu *dmcu = dc->res_pool->dmcu; @@ -105,6 +106,13 @@ void dp_enable_link_phy( link->dc->res_pool->dp_clock_source; unsigned int i; + /* Link should always be assigned encoder when en-/disabling. */ + if (link->is_dig_mapping_flexible && dc->res_pool->funcs->link_encs_assign) + link_enc = link_enc_cfg_get_link_enc_used_by_link(link->dc->current_state, link); + else + link_enc = link->link_enc; + ASSERT(link_enc); + if (link->connector_signal == SIGNAL_TYPE_EDP) { link->dc->hwss.edp_power_control(link, true); link->dc->hwss.edp_wait_for_hpd_ready(link, true); @@ -227,6 +235,14 @@ void dp_disable_link_phy(struct dc_link *link, enum signal_type signal) { struct dc *dc = link->ctx->dc; struct dmcu *dmcu = dc->res_pool->dmcu; + struct link_encoder *link_enc; + + /* Link should always be assigned encoder when en-/disabling. */ + if (link->is_dig_mapping_flexible && dc->res_pool->funcs->link_encs_assign) + link_enc = link_enc_cfg_get_link_enc_used_by_link(link->dc->current_state, link); + else + link_enc = link->link_enc; + ASSERT(link_enc); if (!link->wa_flags.dp_keep_receiver_powered) dp_receiver_power_ctrl(link, false); @@ -234,13 +250,13 @@ void dp_disable_link_phy(struct dc_link *link, enum signal_type signal) if (signal == SIGNAL_TYPE_EDP) { if (link->dc->hwss.edp_backlight_control) link->dc->hwss.edp_backlight_control(link, false); - link->link_enc->funcs->disable_output(link->link_enc, signal); + link_enc->funcs->disable_output(link_enc, signal); link->dc->hwss.edp_power_control(link, false); } else { if (dmcu != NULL && dmcu->funcs->lock_phy) dmcu->funcs->lock_phy(dmcu); - link->link_enc->funcs->disable_output(link->link_enc, signal); + link_enc->funcs->disable_output(link_enc, signal); if (dmcu != NULL && dmcu->funcs->unlock_phy) dmcu->funcs->unlock_phy(dmcu); @@ -302,7 +318,7 @@ void dp_set_hw_lane_settings( { struct link_encoder *encoder = link->link_enc; - if (link->lttpr_non_transparent_mode && !is_immediate_downstream(link, offset)) + if ((link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) && !is_immediate_downstream(link, offset)) return; /* call Encoder to set lane settings */ @@ -368,7 +384,8 @@ void dp_retrain_link_dp_test(struct dc_link *link, skip_video_pattern, LINK_TRAINING_ATTEMPTS, &pipes[i], - SIGNAL_TYPE_DISPLAY_PORT); + SIGNAL_TYPE_DISPLAY_PORT, + false); link->dc->hwss.enable_stream(&pipes[i]); @@ -415,7 +432,7 @@ static void dsc_optc_config_log(struct display_stream_compressor *dsc, DC_LOG_DSC("\tslice_width %d", config->slice_width); } -static bool dp_set_dsc_on_rx(struct pipe_ctx *pipe_ctx, bool enable) +bool dp_set_dsc_on_rx(struct pipe_ctx *pipe_ctx, bool enable) { struct dc *dc = pipe_ctx->stream->ctx->dc; struct dc_stream_state *stream = pipe_ctx->stream; @@ -525,7 +542,7 @@ bool dp_set_dsc_enable(struct pipe_ctx *pipe_ctx, bool enable) goto out; if (enable) { - if (dp_set_dsc_on_rx(pipe_ctx, true)) { + { dp_set_dsc_on_stream(pipe_ctx, true); result = true; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 3c91d16c2710..8a158a192ec0 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -57,6 +57,7 @@ #include "dcn30/dcn30_resource.h" #include "dcn301/dcn301_resource.h" #include "dcn302/dcn302_resource.h" +#include "dcn303/dcn303_resource.h" #endif #define DC_LOGGER_INIT(logger) @@ -130,6 +131,8 @@ enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) dc_version = DCN_VERSION_3_0; if (ASICREV_IS_DIMGREY_CAVEFISH_P(asic_id.hw_internal_rev)) dc_version = DCN_VERSION_3_02; + if (ASICREV_IS_BEIGE_GOBY_P(asic_id.hw_internal_rev)) + dc_version = DCN_VERSION_3_03; break; case FAMILY_VGH: @@ -216,6 +219,9 @@ struct resource_pool *dc_create_resource_pool(struct dc *dc, case DCN_VERSION_3_02: res_pool = dcn302_create_resource_pool(init_data, dc); break; + case DCN_VERSION_3_03: + res_pool = dcn303_create_resource_pool(init_data, dc); + break; #endif default: break; @@ -1706,12 +1712,6 @@ static bool is_timing_changed(struct dc_stream_state *cur_stream, if (cur_stream == NULL) return true; - /* If sink pointer changed, it means this is a hotplug, we should do - * full hw setting. - */ - if (cur_stream->sink != new_stream->sink) - return true; - /* If output color space is changed, need to reprogram info frames */ if (cur_stream->output_color_space != new_stream->output_color_space) return true; @@ -1930,6 +1930,9 @@ enum dc_status dc_remove_stream_from_ctx( dc->res_pool, del_pipe->stream_res.stream_enc, false); + /* Release link encoder from stream in new dc_state. */ + if (dc->res_pool->funcs->link_enc_unassign) + dc->res_pool->funcs->link_enc_unassign(new_ctx, del_pipe->stream); if (del_pipe->stream_res.audio) update_audio_usage( @@ -2503,26 +2506,31 @@ static void set_avi_info_frame( hdmi_info.bits.ITC = itc_value; } + if (stream->qs_bit == 1) { + if (color_space == COLOR_SPACE_SRGB || + color_space == COLOR_SPACE_2020_RGB_FULLRANGE) + hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_FULL_RANGE; + else if (color_space == COLOR_SPACE_SRGB_LIMITED || + color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE) + hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_LIMITED_RANGE; + else + hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_DEFAULT_RANGE; + } else + hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_DEFAULT_RANGE; + /* TODO : We should handle YCC quantization */ /* but we do not have matrix calculation */ - if (stream->qs_bit == 1 && - stream->qy_bit == 1) { + if (stream->qy_bit == 1) { if (color_space == COLOR_SPACE_SRGB || - color_space == COLOR_SPACE_2020_RGB_FULLRANGE) { - hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_FULL_RANGE; + color_space == COLOR_SPACE_2020_RGB_FULLRANGE) hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; - } else if (color_space == COLOR_SPACE_SRGB_LIMITED || - color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE) { - hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_LIMITED_RANGE; + else if (color_space == COLOR_SPACE_SRGB_LIMITED || + color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE) hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; - } else { - hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_DEFAULT_RANGE; + else hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; - } - } else { - hdmi_info.bits.Q0_Q1 = RGB_QUANTIZATION_DEFAULT_RANGE; - hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; - } + } else + hdmi_info.bits.YQ0_YQ1 = YYC_QUANTIZATION_LIMITED_RANGE; ///VIC format = stream->timing.timing_3d_format; @@ -2671,6 +2679,7 @@ void dc_resource_state_destruct(struct dc_state *context) dc_stream_release(context->streams[i]); context->streams[i] = NULL; } + context->stream_count = 0; } void dc_resource_state_copy_construct( @@ -2842,6 +2851,10 @@ bool pipe_need_reprogram( if (pipe_ctx_old->stream_res.dsc != pipe_ctx->stream_res.dsc) return true; + /* DIG link encoder resource assignment for stream changed. */ + if (pipe_ctx_old->stream->link_enc != pipe_ctx->stream->link_enc) + return true; + return false; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index d163007e057c..7da5e7a2e88d 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -45,7 +45,7 @@ /* forward declaration */ struct aux_payload; -#define DC_VER "3.2.127" +#define DC_VER "3.2.136" #define MAX_SURFACES 3 #define MAX_PLANES 6 @@ -293,7 +293,6 @@ struct dc_config { bool gpu_vm_support; bool disable_disp_pll_sharing; bool fbc_support; - bool optimize_edp_link_rate; bool disable_fractional_pwm; bool allow_seamless_boot_optimization; bool power_down_display_on_boot; @@ -309,6 +308,8 @@ struct dc_config { #endif uint64_t vblank_alignment_dto_params; uint8_t vblank_alignment_max_frame_time_diff; + bool is_asymmetric_memory; + bool is_single_rank_dimm; }; enum visual_confirm { @@ -460,6 +461,7 @@ struct dc_debug_options { enum pipe_split_policy pipe_split_policy; bool force_single_disp_pipe_split; bool voltage_align_fclk; + bool disable_min_fclk; bool disable_dfs_bypass; bool disable_dpp_power_gate; @@ -540,6 +542,11 @@ struct dc_debug_options { /* Enable dmub aux for legacy ddc */ bool enable_dmub_aux_for_legacy_ddc; + bool optimize_edp_link_rate; /* eDP ILR */ + /* force enable edp FEC */ + bool force_enable_edp_fec; + /* FEC/PSR1 sequence enable delay in 100us */ + uint8_t fec_enable_delay_in100us; }; struct dc_debug_data { @@ -593,7 +600,6 @@ struct dc_bounding_box_overrides { int min_dcfclk_mhz; }; -struct dc_state; struct resource_pool; struct dce_hwseq; struct gpu_info_soc_bounding_box_v1_0; @@ -899,6 +905,8 @@ struct dc_plane_state { union surface_update_flags update_flags; bool flip_int_enabled; + bool skip_manual_trigger; + /* private to DC core */ struct dc_plane_status status; struct dc_context *ctx; diff --git a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h index 86ab8f16f621..67abda44eb1f 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h @@ -150,6 +150,12 @@ struct dc_vbios_funcs { struct dc_bios *dcb, struct graphics_object_id object_id, struct bp_disp_connector_caps_info *info); + enum bp_result (*get_lttpr_caps)( + struct dc_bios *dcb, + uint8_t *dce_caps); + enum bp_result (*get_lttpr_interop)( + struct dc_bios *dcb, + uint8_t *dce_caps); }; struct bios_registers { diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c index 6b72af2b3f4c..c5dc3a947020 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c @@ -180,5 +180,5 @@ bool dc_dmub_srv_get_dmub_outbox0_msg(const struct dc *dc, struct dmcub_trace_bu void dc_dmub_trace_event_control(struct dc *dc, bool enable) { - dm_helpers_dmub_outbox0_interrupt_control(dc->ctx, enable); + dm_helpers_dmub_outbox_interrupt_control(dc->ctx, enable); } diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h index cc6fb838420e..1948cd9427d7 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h @@ -95,6 +95,12 @@ enum dc_dp_training_pattern { DP_TRAINING_PATTERN_SEQUENCE_2, DP_TRAINING_PATTERN_SEQUENCE_3, DP_TRAINING_PATTERN_SEQUENCE_4, + DP_TRAINING_PATTERN_VIDEOIDLE, +}; + +enum dp_link_encoding { + DP_UNKNOWN_ENCODING = 0, + DP_8b_10b_ENCODING = 1, }; struct dc_link_settings { diff --git a/drivers/gpu/drm/amd/display/dc/dc_dsc.h b/drivers/gpu/drm/amd/display/dc/dc_dsc.h index c51d2d961b7a..16cc76ce3739 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dsc.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dsc.h @@ -78,7 +78,8 @@ bool dc_dsc_compute_config( const struct dc_crtc_timing *timing, struct dc_dsc_config *dsc_cfg); -uint32_t dc_dsc_stream_bandwidth_in_kbps(uint32_t pix_clk_100hz, uint32_t bpp_x16); +uint32_t dc_dsc_stream_bandwidth_in_kbps(const struct dc_crtc_timing *timing, + uint32_t bpp_x16, uint32_t num_slices_h, bool is_dp); void dc_dsc_get_policy_for_timing(const struct dc_crtc_timing *timing, uint32_t max_target_bpp_limit_override_x16, @@ -88,6 +89,6 @@ void dc_dsc_policy_set_max_target_bpp_limit(uint32_t limit); void dc_dsc_policy_set_enable_dsc_when_not_needed(bool enable); -uint32_t dc_dsc_stream_bandwidth_in_kbps(uint32_t pix_clk_100hz, uint32_t bpp_x16); +void dc_dsc_policy_set_disable_dsc_stream_overhead(bool disable); #endif diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index bcec019efa6f..04957a9efab2 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -739,6 +739,7 @@ struct dc_dsc_config { uint32_t version_minor; /* DSC minor version. Full version is formed as 1.version_minor. */ bool ycbcr422_simple; /* Tell DSC engine to convert YCbCr 4:2:2 to 'YCbCr 4:2:2 simple'. */ int32_t rc_buffer_size; /* DSC RC buffer block size in bytes */ + bool is_dp; /* indicate if DSC is applied based on DP's capability */ }; struct dc_crtc_timing { uint32_t h_total; diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h index c50ef5a909a6..c871923e7db0 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_link.h +++ b/drivers/gpu/drm/amd/display/dc/dc_link.h @@ -35,6 +35,7 @@ enum dc_link_fec_state { dc_link_fec_ready, dc_link_fec_enabled }; + struct dc_link_status { bool link_active; struct dpcd_caps *dpcd_caps; @@ -100,12 +101,13 @@ struct dc_link { bool link_state_valid; bool aux_access_disabled; bool sync_lt_in_progress; - bool lttpr_non_transparent_mode; + enum lttpr_mode lttpr_mode; bool is_internal_display; /* TODO: Rename. Flag an endpoint as having a programmable mapping to a * DIG encoder. */ bool is_dig_mapping_flexible; + bool hpd_status; /* HPD status of link without physical HPD pin. */ bool edp_sink_present; @@ -125,6 +127,11 @@ struct dc_link { uint8_t hpd_src; uint8_t link_enc_hw_inst; + /* DIG link encoder ID. Used as index in link encoder resource pool. + * For links with fixed mapping to DIG, this is not changed after dc_link + * object creation. + */ + enum engine_id eng_id; bool test_pattern_enabled; union compliance_test_state compliance_test_state; @@ -144,6 +151,11 @@ struct dc_link { struct panel_cntl *panel_cntl; struct link_encoder *link_enc; struct graphics_object_id link_id; + /* Endpoint type distinguishes display endpoints which do not have entries + * in the BIOS connector table from those that do. Helps when tracking link + * encoder to display endpoint assignments. + */ + enum display_endpoint_type ep_type; union ddi_channel_mapping ddi_channel_mapping; struct connector_device_tag_info device_tag; struct dpcd_caps dpcd_caps; @@ -259,7 +271,6 @@ enum dc_detect_reason { bool dc_link_detect(struct dc_link *dc_link, enum dc_detect_reason reason); bool dc_link_get_hpd_state(struct dc_link *dc_link); enum dc_status dc_link_allocate_mst_payload(struct pipe_ctx *pipe_ctx); -enum dc_status dc_link_reallocate_mst_payload(struct dc_link *link); /* Notify DC about DP RX Interrupt (aka Short Pulse Interrupt). * Return: @@ -329,6 +340,8 @@ bool dc_link_dp_set_test_pattern( const unsigned char *p_custom_pattern, unsigned int cust_pattern_size); +bool dc_link_dp_get_max_link_enc_cap(const struct dc_link *link, struct dc_link_settings *max_link_enc_cap); + void dc_link_enable_hpd_filter(struct dc_link *link, bool enable); bool dc_link_is_dp_sink_present(struct dc_link *link); @@ -345,9 +358,6 @@ bool dc_link_is_hdcp22(struct dc_link *link, enum signal_type signal); void dc_link_set_drive_settings(struct dc *dc, struct link_training_settings *lt_settings, const struct dc_link *link); -void dc_link_perform_link_training(struct dc *dc, - struct dc_link_settings *link_setting, - bool skip_video_pattern); void dc_link_set_preferred_link_settings(struct dc *dc, struct dc_link_settings *link_setting, struct dc_link *link); diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h index e747370fc43b..13dae7238a58 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_stream.h +++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h @@ -130,12 +130,24 @@ union stream_update_flags { uint32_t raw; }; +struct test_pattern { + enum dp_test_pattern type; + enum dp_test_pattern_color_space color_space; + struct link_training_settings const *p_link_settings; + unsigned char const *p_custom_pattern; + unsigned int cust_pattern_size; +}; + struct dc_stream_state { // sink is deprecated, new code should not reference // this pointer struct dc_sink *sink; struct dc_link *link; + /* For dynamic link encoder assignment, update the link encoder assigned to + * a stream via the volatile dc_state rather than the static dc_link. + */ + struct link_encoder *link_enc; struct dc_panel_patch sink_patches; union display_content_support content_support; struct dc_crtc_timing timing; @@ -226,7 +238,8 @@ struct dc_stream_state { bool apply_seamless_boot_optimization; uint32_t stream_id; - bool is_dsc_enabled; + + struct test_pattern test_pattern; union stream_update_flags update_flags; bool has_non_synchronizable_pclk; @@ -264,6 +277,8 @@ struct dc_stream_update { struct dc_dsc_config *dsc_config; struct dc_transfer_func *func_shaper; struct dc_3dlut *lut3d_func; + + struct test_pattern *pending_test_pattern; }; bool dc_is_stream_unchanged( diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 80757a0ea7c6..535da8db70b6 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -113,6 +113,7 @@ struct dc_context { struct gpio_service *gpio_service; uint32_t dc_sink_id_count; uint32_t dc_stream_id_count; + uint32_t dc_edp_id_count; uint64_t fbc_gpu_addr; struct dc_dmub_srv *dmub_srv; @@ -403,7 +404,7 @@ enum dc_connection_type { dc_connection_none, dc_connection_single, dc_connection_mst_branch, - dc_connection_active_dongle + dc_connection_sst_branch }; struct dc_csc_adjustments { @@ -687,7 +688,8 @@ enum dc_psr_state { PSR_STATE5, PSR_STATE5a, PSR_STATE5b, - PSR_STATE5c + PSR_STATE5c, + PSR_STATE_INVALID = 0xFF }; struct psr_config { @@ -907,6 +909,7 @@ struct dsc_dec_dpcd_caps { uint32_t branch_overall_throughput_0_mps; /* In MPs */ uint32_t branch_overall_throughput_1_mps; /* In MPs */ uint32_t branch_max_line_width; + bool is_dp; }; struct dc_golden_table { @@ -934,4 +937,19 @@ enum dc_psr_version { DC_PSR_VERSION_UNSUPPORTED = 0xFFFFFFFF, }; +/* Possible values of display_endpoint_id.endpoint */ +enum display_endpoint_type { + DISPLAY_ENDPOINT_PHY = 0, /* Physical connector. */ + DISPLAY_ENDPOINT_UNKNOWN = -1 +}; + +/* Extends graphics_object_id with an additional member 'ep_type' for + * distinguishing between physical endpoints (with entries in BIOS connector table) and + * logical endpoints. + */ +struct display_endpoint_id { + struct graphics_object_id link_id; + enum display_endpoint_type ep_type; +}; + #endif /* DC_TYPES_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c index 4e87e70237e3..874b132fe1d7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c @@ -283,7 +283,7 @@ struct abm *dce_abm_create( const struct dce_abm_shift *abm_shift, const struct dce_abm_mask *abm_mask) { - struct dce_abm *abm_dce = kzalloc(sizeof(*abm_dce), GFP_KERNEL); + struct dce_abm *abm_dce = kzalloc(sizeof(*abm_dce), GFP_ATOMIC); if (abm_dce == NULL) { BREAK_TO_DEBUGGER(); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c index 87d57e81de12..83d97dfe328f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c @@ -595,6 +595,25 @@ int dce_aux_transfer_raw(struct ddc_service *ddc, return res; } +int dce_aux_transfer_dmub_raw(struct ddc_service *ddc, + struct aux_payload *payload, + enum aux_return_code_type *operation_result) +{ + struct ddc *ddc_pin = ddc->ddc_pin; + + if (ddc_pin != NULL) { + struct dce_aux *aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]; + /* XXX: Workaround to configure ddc channels for aux transactions */ + if (!acquire(aux_engine, ddc_pin)) { + *operation_result = AUX_RET_ERROR_ENGINE_ACQUIRE; + return -1; + } + release_engine(aux_engine); + } + + return dm_helper_dmub_aux_transfer_sync(ddc->ctx, ddc->link, payload, operation_result); +} + #define AUX_MAX_RETRIES 7 #define AUX_MAX_DEFER_RETRIES 7 #define AUX_MAX_I2C_DEFER_RETRIES 7 diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.h b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.h index 566b1bddd8cc..e69f1899fbf0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.h @@ -304,6 +304,9 @@ int dce_aux_transfer_raw(struct ddc_service *ddc, struct aux_payload *cmd, enum aux_return_code_type *operation_result); +int dce_aux_transfer_dmub_raw(struct ddc_service *ddc, + struct aux_payload *payload, + enum aux_return_code_type *operation_result); bool dce_aux_transfer_with_retries(struct ddc_service *ddc, struct aux_payload *cmd); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h index 7fe5a07e2233..3139285bd403 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h @@ -142,6 +142,15 @@ SRII(PIXEL_RATE_CNTL, OTG, 3),\ SRII(PIXEL_RATE_CNTL, OTG, 4) +#define CS_COMMON_REG_LIST_DCN3_03(index, pllid) \ + SRI(PIXCLK_RESYNC_CNTL, PHYPLL, pllid),\ + SRII(PHASE, DP_DTO, 0),\ + SRII(PHASE, DP_DTO, 1),\ + SRII(MODULO, DP_DTO, 0),\ + SRII(MODULO, DP_DTO, 1),\ + SRII(PIXEL_RATE_CNTL, OTG, 0),\ + SRII(PIXEL_RATE_CNTL, OTG, 1) + #endif #define CS_COMMON_MASK_SH_LIST_DCN2_0(mask_sh)\ CS_SF(DP_DTO0_PHASE, DP_DTO0_PHASE, mask_sh),\ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c index 4f864501e046..8cd841320ded 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c @@ -1133,7 +1133,7 @@ struct dmcu *dcn10_dmcu_create( const struct dce_dmcu_shift *dmcu_shift, const struct dce_dmcu_mask *dmcu_mask) { - struct dce_dmcu *dmcu_dce = kzalloc(sizeof(*dmcu_dce), GFP_KERNEL); + struct dce_dmcu *dmcu_dce = kzalloc(sizeof(*dmcu_dce), GFP_ATOMIC); if (dmcu_dce == NULL) { BREAK_TO_DEBUGGER(); @@ -1154,7 +1154,7 @@ struct dmcu *dcn20_dmcu_create( const struct dce_dmcu_shift *dmcu_shift, const struct dce_dmcu_mask *dmcu_mask) { - struct dce_dmcu *dmcu_dce = kzalloc(sizeof(*dmcu_dce), GFP_KERNEL); + struct dce_dmcu *dmcu_dce = kzalloc(sizeof(*dmcu_dce), GFP_ATOMIC); if (dmcu_dce == NULL) { BREAK_TO_DEBUGGER(); @@ -1175,7 +1175,7 @@ struct dmcu *dcn21_dmcu_create( const struct dce_dmcu_shift *dmcu_shift, const struct dce_dmcu_mask *dmcu_mask) { - struct dce_dmcu *dmcu_dce = kzalloc(sizeof(*dmcu_dce), GFP_KERNEL); + struct dce_dmcu *dmcu_dce = kzalloc(sizeof(*dmcu_dce), GFP_ATOMIC); if (dmcu_dce == NULL) { BREAK_TO_DEBUGGER(); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index fe31abfa6c85..0db1bad7a93c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h @@ -480,6 +480,35 @@ SR(AZALIA_AUDIO_DTO), \ SR(AZALIA_CONTROLLER_CLOCK_GATING) +#define HWSEQ_DCN303_REG_LIST() \ + HWSEQ_DCN_REG_LIST(), \ + HSWEQ_DCN_PIXEL_RATE_REG_LIST(OTG, 0), \ + HSWEQ_DCN_PIXEL_RATE_REG_LIST(OTG, 1), \ + SR(MICROSECOND_TIME_BASE_DIV), \ + SR(MILLISECOND_TIME_BASE_DIV), \ + SR(DISPCLK_FREQ_CHANGE_CNTL), \ + SR(RBBMIF_TIMEOUT_DIS), \ + SR(RBBMIF_TIMEOUT_DIS_2), \ + SR(DCHUBBUB_CRC_CTRL), \ + SR(DPP_TOP0_DPP_CRC_CTRL), \ + SR(DPP_TOP0_DPP_CRC_VAL_B_A), \ + SR(DPP_TOP0_DPP_CRC_VAL_R_G), \ + SR(MPC_CRC_CTRL), \ + SR(MPC_CRC_RESULT_GB), \ + SR(MPC_CRC_RESULT_C), \ + SR(MPC_CRC_RESULT_AR), \ + SR(D1VGA_CONTROL), \ + SR(D2VGA_CONTROL), \ + SR(D3VGA_CONTROL), \ + SR(D4VGA_CONTROL), \ + SR(D5VGA_CONTROL), \ + SR(D6VGA_CONTROL), \ + HWSEQ_PIXEL_RATE_REG_LIST_303(OTG), \ + HWSEQ_PHYPLL_REG_LIST_303(OTG), \ + SR(AZALIA_AUDIO_DTO), \ + SR(AZALIA_CONTROLLER_CLOCK_GATING), \ + SR(HPO_TOP_CLOCK_CONTROL) + #define HWSEQ_PIXEL_RATE_REG_LIST_302(blk) \ SRII(PIXEL_RATE_CNTL, blk, 0), \ SRII(PIXEL_RATE_CNTL, blk, 1),\ @@ -494,6 +523,14 @@ SRII(PHYPLL_PIXEL_RATE_CNTL, blk, 3), \ SRII(PHYPLL_PIXEL_RATE_CNTL, blk, 4) +#define HWSEQ_PIXEL_RATE_REG_LIST_303(blk) \ + SRII(PIXEL_RATE_CNTL, blk, 0), \ + SRII(PIXEL_RATE_CNTL, blk, 1) + +#define HWSEQ_PHYPLL_REG_LIST_303(blk) \ + SRII(PHYPLL_PIXEL_RATE_CNTL, blk, 0), \ + SRII(PHYPLL_PIXEL_RATE_CNTL, blk, 1) + struct dce_hwseq_registers { uint32_t DCFE_CLOCK_CONTROL[6]; uint32_t DCFEV_CLOCK_CONTROL; @@ -934,6 +971,12 @@ struct dce_hwseq_registers { HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \ HWS_SF(, AZALIA_AUDIO_DTO, AZALIA_AUDIO_DTO_MODULE, mask_sh) +#define HWSEQ_DCN303_MASK_SH_LIST(mask_sh) \ + HWSEQ_DCN_MASK_SH_LIST(mask_sh), \ + HWS_SF(, DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, mask_sh), \ + HWS_SF(, AZALIA_AUDIO_DTO, AZALIA_AUDIO_DTO_MODULE, mask_sh), \ + HWS_SF(, HPO_TOP_CLOCK_CONTROL, HPO_HDMISTREAMCLK_GATE_DIS, mask_sh) + #define HWSEQ_REG_FIELD_LIST(type) \ type DCFE_CLOCK_ENABLE; \ type DCFEV_CLOCK_ENABLE; \ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c index eb1698d54a48..6939ca2e8212 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c @@ -56,11 +56,19 @@ static void dmub_abm_enable_fractional_pwm(struct dc_context *dc) { union dmub_rb_cmd cmd; uint32_t fractional_pwm = (dc->dc->config.disable_fractional_pwm == false) ? 1 : 0; + uint32_t edp_id_count = dc->dc_edp_id_count; + int i; + uint8_t panel_mask = 0; + + for (i = 0; i < edp_id_count; i++) + panel_mask |= 0x01 << i; memset(&cmd, 0, sizeof(cmd)); cmd.abm_set_pwm_frac.header.type = DMUB_CMD__ABM; cmd.abm_set_pwm_frac.header.sub_type = DMUB_CMD__ABM_SET_PWM_FRAC; cmd.abm_set_pwm_frac.abm_set_pwm_frac_data.fractional_pwm = fractional_pwm; + cmd.abm_set_pwm_frac.abm_set_pwm_frac_data.version = DMUB_CMD_ABM_CONTROL_VERSION_1; + cmd.abm_set_pwm_frac.abm_set_pwm_frac_data.panel_mask = panel_mask; cmd.abm_set_pwm_frac.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_pwm_frac_data); dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd); @@ -135,11 +143,24 @@ static bool dmub_abm_set_level(struct abm *abm, uint32_t level) { union dmub_rb_cmd cmd; struct dc_context *dc = abm->ctx; + struct dc_link *edp_links[MAX_NUM_EDP]; + int i; + int edp_num; + uint8_t panel_mask = 0; + + get_edp_links(dc->dc, edp_links, &edp_num); + + for (i = 0; i < edp_num; i++) { + if (edp_links[i]->link_status.link_active) + panel_mask |= (0x01 << i); + } memset(&cmd, 0, sizeof(cmd)); cmd.abm_set_level.header.type = DMUB_CMD__ABM; cmd.abm_set_level.header.sub_type = DMUB_CMD__ABM_SET_LEVEL; cmd.abm_set_level.abm_set_level_data.level = level; + cmd.abm_set_level.abm_set_level_data.version = DMUB_CMD_ABM_CONTROL_VERSION_1; + cmd.abm_set_level.abm_set_level_data.panel_mask = panel_mask; cmd.abm_set_level.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_level_data); dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd); @@ -155,6 +176,12 @@ static bool dmub_abm_init_config(struct abm *abm, { union dmub_rb_cmd cmd; struct dc_context *dc = abm->ctx; + uint32_t edp_id_count = dc->dc_edp_id_count; + int i; + uint8_t panel_mask = 0; + + for (i = 0; i < edp_id_count; i++) + panel_mask |= 0x01 << i; // TODO: Optimize by only reading back final 4 bytes dmub_flush_buffer_mem(&dc->dmub_srv->dmub->scratch_mem_fb); @@ -168,6 +195,9 @@ static bool dmub_abm_init_config(struct abm *abm, cmd.abm_init_config.header.sub_type = DMUB_CMD__ABM_INIT_CONFIG; cmd.abm_init_config.abm_init_config_data.src.quad_part = dc->dmub_srv->dmub->scratch_mem_fb.gpu_addr; cmd.abm_init_config.abm_init_config_data.bytes = bytes; + cmd.abm_init_config.abm_init_config_data.version = DMUB_CMD_ABM_CONTROL_VERSION_1; + cmd.abm_init_config.abm_init_config_data.panel_mask = panel_mask; + cmd.abm_init_config.header.payload_bytes = sizeof(struct dmub_cmd_abm_init_config_data); dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c index 15ed09b7a452..5e99553fcdd4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c @@ -80,19 +80,26 @@ static enum dc_psr_state convert_psr_state(uint32_t raw_state) static void dmub_psr_get_state(struct dmub_psr *dmub, enum dc_psr_state *state) { struct dmub_srv *srv = dmub->ctx->dmub_srv->dmub; - uint32_t raw_state; + uint32_t raw_state = 0; + uint32_t retry_count = 0; enum dmub_status status; - // Send gpint command and wait for ack - status = dmub_srv_send_gpint_command(srv, DMUB_GPINT__GET_PSR_STATE, 0, 30); - - if (status == DMUB_STATUS_OK) { - // GPINT was executed, get response - dmub_srv_get_gpint_response(srv, &raw_state); - *state = convert_psr_state(raw_state); - } else - // Return invalid state when GPINT times out - *state = 0xFF; + do { + // Send gpint command and wait for ack + status = dmub_srv_send_gpint_command(srv, DMUB_GPINT__GET_PSR_STATE, 0, 30); + + if (status == DMUB_STATUS_OK) { + // GPINT was executed, get response + dmub_srv_get_gpint_response(srv, &raw_state); + *state = convert_psr_state(raw_state); + } else + // Return invalid state when GPINT times out + *state = PSR_STATE_INVALID; + + // Assert if max retry hit + if (retry_count >= 1000) + ASSERT(0); + } while (++retry_count <= 1000 && *state == PSR_STATE_INVALID); } /* @@ -277,6 +284,8 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub, copy_settings_data->debug.u32All = 0; copy_settings_data->debug.bitfields.visual_confirm = dc->dc->debug.visual_confirm == VISUAL_CONFIRM_PSR; copy_settings_data->debug.bitfields.use_hw_lock_mgr = 1; + copy_settings_data->fec_enable_status = (link->fec_state == dc_link_fec_enabled); + copy_settings_data->fec_enable_delay_in100us = link->dc->debug.fec_enable_delay_in100us; dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd); dc_dmub_srv_cmd_execute(dc->dmub_srv); diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 804092f81f85..5ddeee96bf23 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -48,6 +48,7 @@ #include "stream_encoder.h" #include "link_encoder.h" #include "link_hwss.h" +#include "dc_link_dp.h" #include "clock_source.h" #include "clk_mgr.h" #include "abm.h" @@ -1694,6 +1695,8 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context) bool can_apply_edp_fast_boot = false; bool can_apply_seamless_boot = false; bool keep_edp_vdd_on = false; + DC_LOGGER_INIT(); + get_edp_links_with_sink(dc, edp_links_with_sink, &edp_with_sink_num); get_edp_links(dc, edp_links, &edp_num); @@ -1714,8 +1717,11 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context) /* Set optimization flag on eDP stream*/ if (edp_stream_num && edp_link->link_status.link_active) { edp_stream = edp_streams[0]; - edp_stream->apply_edp_fast_boot_optimization = true; - can_apply_edp_fast_boot = true; + can_apply_edp_fast_boot = !is_edp_ilr_optimization_required(edp_stream->link, &edp_stream->timing); + edp_stream->apply_edp_fast_boot_optimization = can_apply_edp_fast_boot; + if (can_apply_edp_fast_boot) + DC_LOG_EVENT_LINK_TRAINING("eDP fast boot disabled to optimize link rate\n"); + break; } } @@ -1846,8 +1852,7 @@ void dce110_set_safe_displaymarks( ******************************************************************************/ static void set_drr(struct pipe_ctx **pipe_ctx, - int num_pipes, unsigned int vmin, unsigned int vmax, - unsigned int vmid, unsigned int vmid_frame_number) + int num_pipes, struct dc_crtc_timing_adjust adjust) { int i = 0; struct drr_params params = {0}; @@ -1856,8 +1861,8 @@ static void set_drr(struct pipe_ctx **pipe_ctx, // Note DRR trigger events are generated regardless of whether num frames met. unsigned int num_frames = 2; - params.vertical_total_max = vmax; - params.vertical_total_min = vmin; + params.vertical_total_max = adjust.v_total_max; + params.vertical_total_min = adjust.v_total_min; /* TODO: If multiple pipes are to be supported, you need * some GSL stuff. Static screen triggers may be programmed differently @@ -1867,7 +1872,7 @@ static void set_drr(struct pipe_ctx **pipe_ctx, pipe_ctx[i]->stream_res.tg->funcs->set_drr( pipe_ctx[i]->stream_res.tg, ¶ms); - if (vmax != 0 && vmin != 0) + if (adjust.v_total_max != 0 && adjust.v_total_min != 0) pipe_ctx[i]->stream_res.tg->funcs->set_static_screen_control( pipe_ctx[i]->stream_res.tg, event_triggers, num_frames); diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 612450f99278..725d92e40cd3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c @@ -526,7 +526,7 @@ static struct output_pixel_processor *dce80_opp_create( return &opp->base; } -struct dce_aux *dce80_aux_engine_create( +static struct dce_aux *dce80_aux_engine_create( struct dc_context *ctx, uint32_t inst) { @@ -564,7 +564,7 @@ static const struct dce_i2c_mask i2c_masks = { I2C_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK) }; -struct dce_i2c_hw *dce80_i2c_hw_create( +static struct dce_i2c_hw *dce80_i2c_hw_create( struct dc_context *ctx, uint32_t inst) { @@ -580,7 +580,7 @@ struct dce_i2c_hw *dce80_i2c_hw_create( return dce_i2c_hw; } -struct dce_i2c_sw *dce80_i2c_sw_create( +static struct dce_i2c_sw *dce80_i2c_sw_create( struct dc_context *ctx) { struct dce_i2c_sw *dce_i2c_sw = @@ -714,7 +714,7 @@ static const struct encoder_feature_support link_enc_feature = { .flags.bits.IS_TPS3_CAPABLE = true }; -struct link_encoder *dce80_link_encoder_create( +static struct link_encoder *dce80_link_encoder_create( const struct encoder_init_data *enc_init_data) { struct dce110_link_encoder *enc110 = @@ -753,7 +753,7 @@ static struct panel_cntl *dce80_panel_cntl_create(const struct panel_cntl_init_d return &panel_cntl->base; } -struct clock_source *dce80_clock_source_create( +static struct clock_source *dce80_clock_source_create( struct dc_context *ctx, struct dc_bios *bios, enum clock_source_id id, @@ -777,7 +777,7 @@ struct clock_source *dce80_clock_source_create( return NULL; } -void dce80_clock_source_destroy(struct clock_source **clk_src) +static void dce80_clock_source_destroy(struct clock_source **clk_src) { kfree(TO_DCE110_CLK_SRC(*clk_src)); *clk_src = NULL; @@ -867,7 +867,7 @@ static void dce80_resource_destruct(struct dce110_resource_pool *pool) } } -bool dce80_validate_bandwidth( +static bool dce80_validate_bandwidth( struct dc *dc, struct dc_state *context, bool fast_validate) @@ -912,7 +912,7 @@ static bool dce80_validate_surface_sets( return true; } -enum dc_status dce80_validate_global( +static enum dc_status dce80_validate_global( struct dc *dc, struct dc_state *context) { diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c index efa86d5c6847..0bd8de4c73a9 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c @@ -496,10 +496,13 @@ static enum lb_memory_config dpp1_dscl_find_lb_memory_config(struct dcn10_dpp *d int vtaps_c = scl_data->taps.v_taps_c; int ceil_vratio = dc_fixpt_ceil(scl_data->ratios.vert); int ceil_vratio_c = dc_fixpt_ceil(scl_data->ratios.vert_c); - enum lb_memory_config mem_cfg = LB_MEMORY_CONFIG_0; - if (dpp->base.ctx->dc->debug.use_max_lb) - return mem_cfg; + if (dpp->base.ctx->dc->debug.use_max_lb) { + if (scl_data->format == PIXEL_FORMAT_420BPP8 + || scl_data->format == PIXEL_FORMAT_420BPP10) + return LB_MEMORY_CONFIG_3; + return LB_MEMORY_CONFIG_0; + } dpp->base.caps->dscl_calc_lb_num_partitions( scl_data, LB_MEMORY_CONFIG_1, &num_part_y, &num_part_c); @@ -650,33 +653,50 @@ static void dpp1_dscl_set_manual_ratio_init( } } - - -static void dpp1_dscl_set_recout( - struct dcn10_dpp *dpp, const struct rect *recout) +/** + * dpp1_dscl_set_recout - Set the first pixel of RECOUT in the OTG active area + * + * @dpp: DPP data struct + * @recount: Rectangle information + * + * This function sets the MPC RECOUT_START and RECOUT_SIZE registers based on + * the values specified in the recount parameter. + * + * Note: This function only have effect if AutoCal is disabled. + */ +static void dpp1_dscl_set_recout(struct dcn10_dpp *dpp, + const struct rect *recout) { int visual_confirm_on = 0; if (dpp->base.ctx->dc->debug.visual_confirm != VISUAL_CONFIRM_DISABLE) visual_confirm_on = 1; REG_SET_2(RECOUT_START, 0, - /* First pixel of RECOUT */ - RECOUT_START_X, recout->x, - /* First line of RECOUT */ - RECOUT_START_Y, recout->y); + /* First pixel of RECOUT in the active OTG area */ + RECOUT_START_X, recout->x, + /* First line of RECOUT in the active OTG area */ + RECOUT_START_Y, recout->y); REG_SET_2(RECOUT_SIZE, 0, - /* Number of RECOUT horizontal pixels */ - RECOUT_WIDTH, recout->width, - /* Number of RECOUT vertical lines */ - RECOUT_HEIGHT, recout->height + /* Number of RECOUT horizontal pixels */ + RECOUT_WIDTH, recout->width, + /* Number of RECOUT vertical lines */ + RECOUT_HEIGHT, recout->height - visual_confirm_on * 2 * (dpp->base.inst + 1)); } -/* Main function to program scaler and line buffer in manual scaling mode */ -void dpp1_dscl_set_scaler_manual_scale( - struct dpp *dpp_base, - const struct scaler_data *scl_data) +/** + * dpp1_dscl_set_scaler_manual_scale - Manually program scaler and line buffer + * + * @dpp_base: High level DPP struct + * @scl_data: scalaer_data info + * + * This is the primary function to program scaler and line buffer in manual + * scaling mode. To execute the required operations for manual scale, we need + * to disable AutoCal first. + */ +void dpp1_dscl_set_scaler_manual_scale(struct dpp *dpp_base, + const struct scaler_data *scl_data) { enum lb_memory_config lb_config; struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c index 714c71a5fbde..e39e8a2f715d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c @@ -1226,6 +1226,14 @@ void hubp1_cursor_set_position( /* TODO Handle surface pixel formats other than 4:4:4 */ } +/** + * hubp1_clk_cntl - Disable or enable clocks for DCHUBP + * + * @hubp: hubp struct reference. + * @enable: Set true for enabling gate clock. + * + * When enabling/disabling DCHUBP clock, we affect dcfclk/dppclk. + */ void hubp1_clk_cntl(struct hubp *hubp, bool enable) { struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); @@ -1257,6 +1265,11 @@ void hubp1_soft_reset(struct hubp *hubp, bool reset) REG_UPDATE(DCHUBP_CNTL, HUBP_DISABLE, reset ? 1 : 0); } +/** + * hubp1_set_flip_int - Enable surface flip interrupt + * + * @hubp: hubp struct reference. + */ void hubp1_set_flip_int(struct hubp *hubp) { struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 9eb33eae0e81..81803463ca9b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -72,6 +72,9 @@ #define GAMMA_HW_POINTS_NUM 256 +#define PGFSM_POWER_ON 0 +#define PGFSM_POWER_OFF 2 + void print_microsec(struct dc_context *dc_ctx, struct dc_log_buffer_ctx *log_ctx, uint32_t ref_cycle) @@ -536,13 +539,22 @@ void dcn10_disable_vga( REG_UPDATE(VGA_TEST_CONTROL, VGA_TEST_RENDER_START, 1); } +/** + * dcn10_dpp_pg_control - DPP power gate control. + * + * @hws: dce_hwseq reference. + * @dpp_inst: DPP instance reference. + * @power_on: true if we want to enable power gate, false otherwise. + * + * Enable or disable power gate in the specific DPP instance. + */ void dcn10_dpp_pg_control( struct dce_hwseq *hws, unsigned int dpp_inst, bool power_on) { uint32_t power_gate = power_on ? 0 : 1; - uint32_t pwr_status = power_on ? 0 : 2; + uint32_t pwr_status = power_on ? PGFSM_POWER_ON : PGFSM_POWER_OFF; if (hws->ctx->dc->debug.disable_dpp_power_gate) return; @@ -588,13 +600,22 @@ void dcn10_dpp_pg_control( } } +/** + * dcn10_hubp_pg_control - HUBP power gate control. + * + * @hws: dce_hwseq reference. + * @hubp_inst: DPP instance reference. + * @power_on: true if we want to enable power gate, false otherwise. + * + * Enable or disable power gate in the specific HUBP instance. + */ void dcn10_hubp_pg_control( struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on) { uint32_t power_gate = power_on ? 0 : 1; - uint32_t pwr_status = power_on ? 0 : 2; + uint32_t pwr_status = power_on ? PGFSM_POWER_ON : PGFSM_POWER_OFF; if (hws->ctx->dc->debug.disable_hubp_power_gate) return; @@ -1078,6 +1099,19 @@ void dcn10_plane_atomic_disconnect(struct dc *dc, struct pipe_ctx *pipe_ctx) hws->funcs.verify_allow_pstate_change_high(dc); } +/** + * dcn10_plane_atomic_power_down - Power down plane components. + * + * @dc: dc struct reference. used for grab hwseq. + * @dpp: dpp struct reference. + * @hubp: hubp struct reference. + * + * Keep in mind that this operation requires a power gate configuration; + * however, requests for switch power gate are precisely controlled to avoid + * problems. For this reason, power gate request is usually disabled. This + * function first needs to enable the power gate request before disabling DPP + * and HUBP. Finally, it disables the power gate request again. + */ void dcn10_plane_atomic_power_down(struct dc *dc, struct dpp *dpp, struct hubp *hubp) @@ -1893,7 +1927,7 @@ uint64_t reduceSizeAndFraction( num = *numerator; denom = *denominator; for (i = 0; i < count; i++) { - uint32_t num_reminder, denom_reminder; + uint32_t num_remainder, denom_remainder; uint64_t num_result, denom_result; if (checkUint32Bounary && num <= max_int32 && denom <= max_int32) { @@ -1901,13 +1935,13 @@ uint64_t reduceSizeAndFraction( break; } do { - num_result = div_u64_rem(num, prime_numbers[i], &num_reminder); - denom_result = div_u64_rem(denom, prime_numbers[i], &denom_reminder); - if (num_reminder == 0 && denom_reminder == 0) { + num_result = div_u64_rem(num, prime_numbers[i], &num_remainder); + denom_result = div_u64_rem(denom, prime_numbers[i], &denom_remainder); + if (num_remainder == 0 && denom_remainder == 0) { num = num_result; denom = denom_result; } - } while (num_reminder == 0 && denom_reminder == 0); + } while (num_remainder == 0 && denom_remainder == 0); } *numerator = num; *denominator = denom; @@ -2165,129 +2199,6 @@ void dcn10_enable_per_frame_crtc_position_reset( DC_SYNC_INFO("Multi-display sync is complete\n"); } -/*static void print_rq_dlg_ttu( - struct dc *dc, - struct pipe_ctx *pipe_ctx) -{ - DC_LOG_BANDWIDTH_CALCS(dc->ctx->logger, - "\n============== DML TTU Output parameters [%d] ==============\n" - "qos_level_low_wm: %d, \n" - "qos_level_high_wm: %d, \n" - "min_ttu_vblank: %d, \n" - "qos_level_flip: %d, \n" - "refcyc_per_req_delivery_l: %d, \n" - "qos_level_fixed_l: %d, \n" - "qos_ramp_disable_l: %d, \n" - "refcyc_per_req_delivery_pre_l: %d, \n" - "refcyc_per_req_delivery_c: %d, \n" - "qos_level_fixed_c: %d, \n" - "qos_ramp_disable_c: %d, \n" - "refcyc_per_req_delivery_pre_c: %d\n" - "=============================================================\n", - pipe_ctx->pipe_idx, - pipe_ctx->ttu_regs.qos_level_low_wm, - pipe_ctx->ttu_regs.qos_level_high_wm, - pipe_ctx->ttu_regs.min_ttu_vblank, - pipe_ctx->ttu_regs.qos_level_flip, - pipe_ctx->ttu_regs.refcyc_per_req_delivery_l, - pipe_ctx->ttu_regs.qos_level_fixed_l, - pipe_ctx->ttu_regs.qos_ramp_disable_l, - pipe_ctx->ttu_regs.refcyc_per_req_delivery_pre_l, - pipe_ctx->ttu_regs.refcyc_per_req_delivery_c, - pipe_ctx->ttu_regs.qos_level_fixed_c, - pipe_ctx->ttu_regs.qos_ramp_disable_c, - pipe_ctx->ttu_regs.refcyc_per_req_delivery_pre_c - ); - - DC_LOG_BANDWIDTH_CALCS(dc->ctx->logger, - "\n============== DML DLG Output parameters [%d] ==============\n" - "refcyc_h_blank_end: %d, \n" - "dlg_vblank_end: %d, \n" - "min_dst_y_next_start: %d, \n" - "refcyc_per_htotal: %d, \n" - "refcyc_x_after_scaler: %d, \n" - "dst_y_after_scaler: %d, \n" - "dst_y_prefetch: %d, \n" - "dst_y_per_vm_vblank: %d, \n" - "dst_y_per_row_vblank: %d, \n" - "ref_freq_to_pix_freq: %d, \n" - "vratio_prefetch: %d, \n" - "refcyc_per_pte_group_vblank_l: %d, \n" - "refcyc_per_meta_chunk_vblank_l: %d, \n" - "dst_y_per_pte_row_nom_l: %d, \n" - "refcyc_per_pte_group_nom_l: %d, \n", - pipe_ctx->pipe_idx, - pipe_ctx->dlg_regs.refcyc_h_blank_end, - pipe_ctx->dlg_regs.dlg_vblank_end, - pipe_ctx->dlg_regs.min_dst_y_next_start, - pipe_ctx->dlg_regs.refcyc_per_htotal, - pipe_ctx->dlg_regs.refcyc_x_after_scaler, - pipe_ctx->dlg_regs.dst_y_after_scaler, - pipe_ctx->dlg_regs.dst_y_prefetch, - pipe_ctx->dlg_regs.dst_y_per_vm_vblank, - pipe_ctx->dlg_regs.dst_y_per_row_vblank, - pipe_ctx->dlg_regs.ref_freq_to_pix_freq, - pipe_ctx->dlg_regs.vratio_prefetch, - pipe_ctx->dlg_regs.refcyc_per_pte_group_vblank_l, - pipe_ctx->dlg_regs.refcyc_per_meta_chunk_vblank_l, - pipe_ctx->dlg_regs.dst_y_per_pte_row_nom_l, - pipe_ctx->dlg_regs.refcyc_per_pte_group_nom_l - ); - - DC_LOG_BANDWIDTH_CALCS(dc->ctx->logger, - "\ndst_y_per_meta_row_nom_l: %d, \n" - "refcyc_per_meta_chunk_nom_l: %d, \n" - "refcyc_per_line_delivery_pre_l: %d, \n" - "refcyc_per_line_delivery_l: %d, \n" - "vratio_prefetch_c: %d, \n" - "refcyc_per_pte_group_vblank_c: %d, \n" - "refcyc_per_meta_chunk_vblank_c: %d, \n" - "dst_y_per_pte_row_nom_c: %d, \n" - "refcyc_per_pte_group_nom_c: %d, \n" - "dst_y_per_meta_row_nom_c: %d, \n" - "refcyc_per_meta_chunk_nom_c: %d, \n" - "refcyc_per_line_delivery_pre_c: %d, \n" - "refcyc_per_line_delivery_c: %d \n" - "========================================================\n", - pipe_ctx->dlg_regs.dst_y_per_meta_row_nom_l, - pipe_ctx->dlg_regs.refcyc_per_meta_chunk_nom_l, - pipe_ctx->dlg_regs.refcyc_per_line_delivery_pre_l, - pipe_ctx->dlg_regs.refcyc_per_line_delivery_l, - pipe_ctx->dlg_regs.vratio_prefetch_c, - pipe_ctx->dlg_regs.refcyc_per_pte_group_vblank_c, - pipe_ctx->dlg_regs.refcyc_per_meta_chunk_vblank_c, - pipe_ctx->dlg_regs.dst_y_per_pte_row_nom_c, - pipe_ctx->dlg_regs.refcyc_per_pte_group_nom_c, - pipe_ctx->dlg_regs.dst_y_per_meta_row_nom_c, - pipe_ctx->dlg_regs.refcyc_per_meta_chunk_nom_c, - pipe_ctx->dlg_regs.refcyc_per_line_delivery_pre_c, - pipe_ctx->dlg_regs.refcyc_per_line_delivery_c - ); - - DC_LOG_BANDWIDTH_CALCS(dc->ctx->logger, - "\n============== DML RQ Output parameters [%d] ==============\n" - "chunk_size: %d \n" - "min_chunk_size: %d \n" - "meta_chunk_size: %d \n" - "min_meta_chunk_size: %d \n" - "dpte_group_size: %d \n" - "mpte_group_size: %d \n" - "swath_height: %d \n" - "pte_row_height_linear: %d \n" - "========================================================\n", - pipe_ctx->pipe_idx, - pipe_ctx->rq_regs.rq_regs_l.chunk_size, - pipe_ctx->rq_regs.rq_regs_l.min_chunk_size, - pipe_ctx->rq_regs.rq_regs_l.meta_chunk_size, - pipe_ctx->rq_regs.rq_regs_l.min_meta_chunk_size, - pipe_ctx->rq_regs.rq_regs_l.dpte_group_size, - pipe_ctx->rq_regs.rq_regs_l.mpte_group_size, - pipe_ctx->rq_regs.rq_regs_l.swath_height, - pipe_ctx->rq_regs.rq_regs_l.pte_row_height_linear - ); -} -*/ - static void mmhub_read_vm_system_aperture_settings(struct dcn10_hubp *hubp1, struct vm_system_aperture_param *apt, struct dce_hwseq *hws) @@ -2395,43 +2306,6 @@ static void dcn10_enable_plane( pipe_ctx->stream_res.opp, true); -/* TODO: enable/disable in dm as per update type. - if (plane_state) { - DC_LOG_DC(dc->ctx->logger, - "Pipe:%d 0x%x: addr hi:0x%x, " - "addr low:0x%x, " - "src: %d, %d, %d," - " %d; dst: %d, %d, %d, %d;\n", - pipe_ctx->pipe_idx, - plane_state, - plane_state->address.grph.addr.high_part, - plane_state->address.grph.addr.low_part, - plane_state->src_rect.x, - plane_state->src_rect.y, - plane_state->src_rect.width, - plane_state->src_rect.height, - plane_state->dst_rect.x, - plane_state->dst_rect.y, - plane_state->dst_rect.width, - plane_state->dst_rect.height); - - DC_LOG_DC(dc->ctx->logger, - "Pipe %d: width, height, x, y format:%d\n" - "viewport:%d, %d, %d, %d\n" - "recout: %d, %d, %d, %d\n", - pipe_ctx->pipe_idx, - plane_state->format, - pipe_ctx->plane_res.scl_data.viewport.width, - pipe_ctx->plane_res.scl_data.viewport.height, - pipe_ctx->plane_res.scl_data.viewport.x, - pipe_ctx->plane_res.scl_data.viewport.y, - pipe_ctx->plane_res.scl_data.recout.width, - pipe_ctx->plane_res.scl_data.recout.height, - pipe_ctx->plane_res.scl_data.recout.x, - pipe_ctx->plane_res.scl_data.recout.y); - print_rq_dlg_ttu(dc, pipe_ctx); - } -*/ if (dc->config.gpu_vm_support) dcn10_program_pte_vm(hws, pipe_ctx->plane_res.hubp); @@ -2628,9 +2502,25 @@ static void dcn10_update_dpp(struct dpp *dpp, struct dc_plane_state *plane_state dpp->funcs->dpp_program_bias_and_scale(dpp, &bns_params); } -void dcn10_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx) +void dcn10_update_visual_confirm_color(struct dc *dc, struct pipe_ctx *pipe_ctx, struct tg_color *color, int mpcc_id) { struct dce_hwseq *hws = dc->hwseq; + struct mpc *mpc = dc->res_pool->mpc; + + if (dc->debug.visual_confirm == VISUAL_CONFIRM_HDR) + hws->funcs.get_hdr_visual_confirm_color(pipe_ctx, color); + else if (dc->debug.visual_confirm == VISUAL_CONFIRM_SURFACE) + hws->funcs.get_surface_visual_confirm_color(pipe_ctx, color); + else + color_space_to_black_color( + dc, pipe_ctx->stream->output_color_space, color); + + if (mpc->funcs->set_bg_color) + mpc->funcs->set_bg_color(mpc, color, mpcc_id); +} + +void dcn10_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx) +{ struct hubp *hubp = pipe_ctx->plane_res.hubp; struct mpcc_blnd_cfg blnd_cfg = {{0}}; bool per_pixel_alpha = pipe_ctx->plane_state->per_pixel_alpha && pipe_ctx->bottom_pipe; @@ -2639,18 +2529,6 @@ void dcn10_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx) struct mpc *mpc = dc->res_pool->mpc; struct mpc_tree *mpc_tree_params = &(pipe_ctx->stream_res.opp->mpc_tree_params); - if (dc->debug.visual_confirm == VISUAL_CONFIRM_HDR) { - hws->funcs.get_hdr_visual_confirm_color( - pipe_ctx, &blnd_cfg.black_color); - } else if (dc->debug.visual_confirm == VISUAL_CONFIRM_SURFACE) { - hws->funcs.get_surface_visual_confirm_color( - pipe_ctx, &blnd_cfg.black_color); - } else { - color_space_to_black_color( - dc, pipe_ctx->stream->output_color_space, - &blnd_cfg.black_color); - } - if (per_pixel_alpha) blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA; else @@ -2682,6 +2560,8 @@ void dcn10_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx) */ mpcc_id = hubp->inst; + dc->hwss.update_visual_confirm_color(dc, pipe_ctx, &blnd_cfg.black_color, mpcc_id); + /* If there is no full update, don't need to touch MPC tree*/ if (!pipe_ctx->plane_state->update_flags.bits.full_update) { mpc->funcs->update_blending(mpc, &blnd_cfg, mpcc_id); @@ -2956,35 +2836,6 @@ void dcn10_program_pipe( { struct dce_hwseq *hws = dc->hwseq; - if (pipe_ctx->plane_state->update_flags.bits.full_update) - dcn10_enable_plane(dc, pipe_ctx, context); - - dcn10_update_dchubp_dpp(dc, pipe_ctx, context); - - hws->funcs.set_hdr_multiplier(pipe_ctx); - - if (pipe_ctx->plane_state->update_flags.bits.full_update || - pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change || - pipe_ctx->plane_state->update_flags.bits.gamma_change) - hws->funcs.set_input_transfer_func(dc, pipe_ctx, pipe_ctx->plane_state); - - /* dcn10_translate_regamma_to_hw_format takes 750us to finish - * only do gamma programming for full update. - * TODO: This can be further optimized/cleaned up - * Always call this for now since it does memcmp inside before - * doing heavy calculation and programming - */ - if (pipe_ctx->plane_state->update_flags.bits.full_update) - hws->funcs.set_output_transfer_func(dc, pipe_ctx, pipe_ctx->stream); -} - -static void dcn10_program_all_pipe_in_tree( - struct dc *dc, - struct pipe_ctx *pipe_ctx, - struct dc_state *context) -{ - struct dce_hwseq *hws = dc->hwseq; - if (pipe_ctx->top_pipe == NULL) { bool blank = !is_pipe_tree_visible(pipe_ctx); @@ -3004,35 +2855,26 @@ static void dcn10_program_all_pipe_in_tree( hws->funcs.blank_pixel_data(dc, pipe_ctx, blank); } - if (pipe_ctx->plane_state != NULL) - hws->funcs.program_pipe(dc, pipe_ctx, context); - - if (pipe_ctx->bottom_pipe != NULL && pipe_ctx->bottom_pipe != pipe_ctx) - dcn10_program_all_pipe_in_tree(dc, pipe_ctx->bottom_pipe, context); -} - -static struct pipe_ctx *dcn10_find_top_pipe_for_stream( - struct dc *dc, - struct dc_state *context, - const struct dc_stream_state *stream) -{ - int i; + if (pipe_ctx->plane_state->update_flags.bits.full_update) + dcn10_enable_plane(dc, pipe_ctx, context); - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - struct pipe_ctx *old_pipe_ctx = - &dc->current_state->res_ctx.pipe_ctx[i]; + dcn10_update_dchubp_dpp(dc, pipe_ctx, context); - if (!pipe_ctx->plane_state && !old_pipe_ctx->plane_state) - continue; + hws->funcs.set_hdr_multiplier(pipe_ctx); - if (pipe_ctx->stream != stream) - continue; + if (pipe_ctx->plane_state->update_flags.bits.full_update || + pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change || + pipe_ctx->plane_state->update_flags.bits.gamma_change) + hws->funcs.set_input_transfer_func(dc, pipe_ctx, pipe_ctx->plane_state); - if (!pipe_ctx->top_pipe && !pipe_ctx->prev_odm_pipe) - return pipe_ctx; - } - return NULL; + /* dcn10_translate_regamma_to_hw_format takes 750us to finish + * only do gamma programming for full update. + * TODO: This can be further optimized/cleaned up + * Always call this for now since it does memcmp inside before + * doing heavy calculation and programming + */ + if (pipe_ctx->plane_state->update_flags.bits.full_update) + hws->funcs.set_output_transfer_func(dc, pipe_ctx, pipe_ctx->stream); } void dcn10_wait_for_pending_cleared(struct dc *dc, @@ -3067,91 +2909,6 @@ void dcn10_wait_for_pending_cleared(struct dc *dc, } } -void dcn10_apply_ctx_for_surface( - struct dc *dc, - const struct dc_stream_state *stream, - int num_planes, - struct dc_state *context) -{ - struct dce_hwseq *hws = dc->hwseq; - int i; - struct timing_generator *tg; - uint32_t underflow_check_delay_us; - bool interdependent_update = false; - struct pipe_ctx *top_pipe_to_program = - dcn10_find_top_pipe_for_stream(dc, context, stream); - DC_LOGGER_INIT(dc->ctx->logger); - - // Clear pipe_ctx flag - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - pipe_ctx->update_flags.raw = 0; - } - - if (!top_pipe_to_program) - return; - - tg = top_pipe_to_program->stream_res.tg; - - interdependent_update = top_pipe_to_program->plane_state && - top_pipe_to_program->plane_state->update_flags.bits.full_update; - - underflow_check_delay_us = dc->debug.underflow_assert_delay_us; - - if (underflow_check_delay_us != 0xFFFFFFFF && hws->funcs.did_underflow_occur) - ASSERT(hws->funcs.did_underflow_occur(dc, top_pipe_to_program)); - - if (underflow_check_delay_us != 0xFFFFFFFF) - udelay(underflow_check_delay_us); - - if (underflow_check_delay_us != 0xFFFFFFFF && hws->funcs.did_underflow_occur) - ASSERT(hws->funcs.did_underflow_occur(dc, top_pipe_to_program)); - - if (num_planes == 0) { - /* OTG blank before remove all front end */ - hws->funcs.blank_pixel_data(dc, top_pipe_to_program, true); - } - - /* Disconnect unused mpcc */ - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - struct pipe_ctx *old_pipe_ctx = - &dc->current_state->res_ctx.pipe_ctx[i]; - - if ((!pipe_ctx->plane_state || - pipe_ctx->stream_res.tg != old_pipe_ctx->stream_res.tg) && - old_pipe_ctx->plane_state && - old_pipe_ctx->stream_res.tg == tg) { - - hws->funcs.plane_atomic_disconnect(dc, old_pipe_ctx); - pipe_ctx->update_flags.bits.disable = 1; - - DC_LOG_DC("Reset mpcc for pipe %d\n", - old_pipe_ctx->pipe_idx); - } - } - - if (num_planes > 0) - dcn10_program_all_pipe_in_tree(dc, top_pipe_to_program, context); - - /* Program secondary blending tree and writeback pipes */ - if ((stream->num_wb_info > 0) && (hws->funcs.program_all_writeback_pipes_in_tree)) - hws->funcs.program_all_writeback_pipes_in_tree(dc, stream, context); - if (interdependent_update) - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - /* Skip inactive pipes and ones already updated */ - if (!pipe_ctx->stream || pipe_ctx->stream == stream || - !pipe_ctx->plane_state || !tg->funcs->is_tg_enabled(tg)) - continue; - - pipe_ctx->plane_res.hubp->funcs->hubp_setup_interdependent( - pipe_ctx->plane_res.hubp, - &pipe_ctx->dlg_regs, - &pipe_ctx->ttu_regs); - } -} - void dcn10_post_unlock_program_front_end( struct dc *dc, struct dc_state *context) @@ -3271,8 +3028,7 @@ void dcn10_optimize_bandwidth( } void dcn10_set_drr(struct pipe_ctx **pipe_ctx, - int num_pipes, unsigned int vmin, unsigned int vmax, - unsigned int vmid, unsigned int vmid_frame_number) + int num_pipes, struct dc_crtc_timing_adjust adjust) { int i = 0; struct drr_params params = {0}; @@ -3281,11 +3037,10 @@ void dcn10_set_drr(struct pipe_ctx **pipe_ctx, // Note DRR trigger events are generated regardless of whether num frames met. unsigned int num_frames = 2; - params.vertical_total_max = vmax; - params.vertical_total_min = vmin; - params.vertical_total_mid = vmid; - params.vertical_total_mid_frame_num = vmid_frame_number; - + params.vertical_total_max = adjust.v_total_max; + params.vertical_total_min = adjust.v_total_min; + params.vertical_total_mid = adjust.v_total_mid; + params.vertical_total_mid_frame_num = adjust.v_total_mid_frame_num; /* TODO: If multiple pipes are to be supported, you need * some GSL stuff. Static screen triggers may be programmed differently * as well. @@ -3293,7 +3048,7 @@ void dcn10_set_drr(struct pipe_ctx **pipe_ctx, for (i = 0; i < num_pipes; i++) { pipe_ctx[i]->stream_res.tg->funcs->set_drr( pipe_ctx[i]->stream_res.tg, ¶ms); - if (vmax != 0 && vmin != 0) + if (adjust.v_total_max != 0 && adjust.v_total_min != 0) pipe_ctx[i]->stream_res.tg->funcs->set_static_screen_control( pipe_ctx[i]->stream_res.tg, event_triggers, num_frames); @@ -3981,3 +3736,19 @@ void dcn10_get_clock(struct dc *dc, dc->clk_mgr->funcs->get_clock(dc->clk_mgr, context, clock_type, clock_cfg); } + +void dcn10_get_dcc_en_bits(struct dc *dc, int *dcc_en_bits) +{ + struct resource_pool *pool = dc->res_pool; + int i; + + for (i = 0; i < pool->pipe_count; i++) { + struct hubp *hubp = pool->hubps[i]; + struct dcn_hubp_state *s = &(TO_DCN10_HUBP(hubp)->state); + + hubp->funcs->hubp_read_state(hubp); + + if (!s->blank_en) + dcc_en_bits[i] = s->dcc_en ? 1 : 0; + } +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h index e0800cd1cc02..478180b96d8d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h @@ -1,5 +1,5 @@ /* -* Copyright 2016 Advanced Micro Devices, Inc. +* Copyright 2016-2020 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -80,11 +80,6 @@ void dcn10_lock_all_pipes( struct dc *dc, struct dc_state *context, bool lock); -void dcn10_apply_ctx_for_surface( - struct dc *dc, - const struct dc_stream_state *stream, - int num_planes, - struct dc_state *context); void dcn10_post_unlock_program_front_end( struct dc *dc, struct dc_state *context); @@ -145,8 +140,7 @@ bool dcn10_dummy_display_power_gating( struct dc_bios *dcb, enum pipe_gating_control power_gating); void dcn10_set_drr(struct pipe_ctx **pipe_ctx, - int num_pipes, unsigned int vmin, unsigned int vmax, - unsigned int vmid, unsigned int vmid_frame_number); + int num_pipes, struct dc_crtc_timing_adjust adjust); void dcn10_get_position(struct pipe_ctx **pipe_ctx, int num_pipes, struct crtc_position *position); @@ -210,4 +204,12 @@ void dcn10_wait_for_pending_cleared(struct dc *dc, void dcn10_set_hdr_multiplier(struct pipe_ctx *pipe_ctx); void dcn10_verify_allow_pstate_change_high(struct dc *dc); +void dcn10_get_dcc_en_bits(struct dc *dc, int *dcc_en_bits); + +void dcn10_update_visual_confirm_color( + struct dc *dc, + struct pipe_ctx *pipe_ctx, + struct tg_color *color, + int mpcc_id); + #endif /* __DC_HWSS_DCN10_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c index 254300b06b43..4ff3ebc25438 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c @@ -1,5 +1,5 @@ /* - * Copyright 2016 Advanced Micro Devices, Inc. + * Copyright 2016-2020 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -26,13 +26,15 @@ #include "hw_sequencer_private.h" #include "dce110/dce110_hw_sequencer.h" #include "dcn10_hw_sequencer.h" +#include "dcn20/dcn20_hwseq.h" static const struct hw_sequencer_funcs dcn10_funcs = { .program_gamut_remap = dcn10_program_gamut_remap, .init_hw = dcn10_init_hw, .power_down_on_boot = dcn10_power_down_on_boot, .apply_ctx_to_hw = dce110_apply_ctx_to_hw, - .apply_ctx_for_surface = dcn10_apply_ctx_for_surface, + .apply_ctx_for_surface = NULL, + .program_front_end_for_ctx = dcn20_program_front_end_for_ctx, .post_unlock_program_front_end = dcn10_post_unlock_program_front_end, .wait_for_pending_cleared = dcn10_wait_for_pending_cleared, .update_plane_addr = dcn10_update_plane_addr, @@ -79,6 +81,8 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .set_backlight_level = dce110_set_backlight_level, .set_abm_immediate_disable = dce110_set_abm_immediate_disable, .set_pipe = dce110_set_pipe, + .get_dcc_en_bits = dcn10_get_dcc_en_bits, + .update_visual_confirm_color = dcn10_update_visual_confirm_color, }; static const struct hwseq_private_funcs dcn10_private_funcs = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c index b096011acb49..da74269feb75 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c @@ -64,6 +64,8 @@ void mpc1_set_bg_color(struct mpc *mpc, MPCC_BG_G_Y, bg_g_y); REG_SET(MPCC_BG_B_CB[bottommost_mpcc->mpcc_id], 0, MPCC_BG_B_CB, bg_b_cb); + + bottommost_mpcc->blnd_cfg.black_color = *bg_color; } static void mpc1_update_blending( @@ -246,6 +248,8 @@ struct mpcc *mpc1_insert_plane( } } + mpc->funcs->set_bg_color(mpc, &blnd_cfg->black_color, mpcc_id); + /* update the blending configuration */ mpc->funcs->update_blending(mpc, blnd_cfg, mpcc_id); @@ -495,6 +499,7 @@ static const struct mpc_funcs dcn10_mpc_funcs = { .set_output_csc = NULL, .set_output_gamma = NULL, .get_mpc_out_mux = mpc1_get_mpc_out_mux, + .set_bg_color = mpc1_set_bg_color, }; void dcn10_mpc_construct(struct dcn10_mpc *mpc10, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c index 6138f4887de7..677663cc7bff 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c @@ -132,6 +132,22 @@ void optc1_setup_vertical_interrupt2( } /** + * Vupdate keepout can be set to a window to block the update lock for that pipe from changing. + * Start offset begins with vstartup and goes for x number of clocks, + * end offset starts from end of vupdate to x number of clocks. + */ +void optc1_set_vupdate_keepout(struct timing_generator *optc, + struct vupdate_keepout_params *params) +{ + struct optc *optc1 = DCN10TG_FROM_TG(optc); + + REG_SET_3(OTG_VUPDATE_KEEPOUT, 0, + MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET, params->start_offset, + MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET, params->end_offset, + OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, params->enable); +} + +/** * program_timing_generator used by mode timing set * Program CRTC Timing Registers - OTG_H_*, OTG_V_*, Pixel repetition. * Including SYNC. Call BIOS command table to program Timings. diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h index 2529723beeb1..cabfe83fd634 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h @@ -194,6 +194,9 @@ struct dcn_optc_registers { SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_UPDATE_PENDING, mask_sh),\ SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_BLANK_DATA_DOUBLE_BUFFER_EN, mask_sh),\ SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_RANGE_TIMING_DBUF_UPDATE_MODE, mask_sh),\ + SF(OTG0_OTG_VUPDATE_KEEPOUT, OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, mask_sh), \ + SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET, mask_sh), \ + SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET, mask_sh), \ SF(OTG0_OTG_H_TOTAL, OTG_H_TOTAL, mask_sh),\ SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_START, mask_sh),\ SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_END, mask_sh),\ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index d079f4e491e5..f962b905e79e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -82,7 +82,7 @@ const struct _vcs_dpi_ip_params_st dcn1_0_ip = { .meta_chunk_size_kbytes = 2, .writeback_chunk_size_kbytes = 2, .line_buffer_size_bits = 589824, - .max_line_buffer_lines = 32, + .max_line_buffer_lines = 12, .IsLineBufferBppFixed = 0, .LineBufferFixedBpp = -1, .writeback_luma_buffer_size_kbytes = 12, @@ -619,7 +619,6 @@ static const struct dc_debug_options debug_defaults_drv = { .recovery_enabled = false, /*enable this by default after testing.*/ .max_downscale_src_width = 3840, .underflow_assert_delay_us = 0xFFFFFFFF, - .use_max_lb = true }; static const struct dc_debug_options debug_defaults_diags = { @@ -631,7 +630,6 @@ static const struct dc_debug_options debug_defaults_diags = { .disable_pplib_clock_request = true, .disable_pplib_wm_range = true, .underflow_assert_delay_us = 0xFFFFFFFF, - .use_max_lb = true }; static void dcn10_dpp_destroy(struct dpp **dpp) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.c index 62cc2651e00c..8774406120fc 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.c @@ -112,7 +112,7 @@ struct dccg *dccg2_create( const struct dccg_shift *dccg_shift, const struct dccg_mask *dccg_mask) { - struct dcn_dccg *dccg_dcn = kzalloc(sizeof(*dccg_dcn), GFP_KERNEL); + struct dcn_dccg *dccg_dcn = kzalloc(sizeof(*dccg_dcn), GFP_ATOMIC); struct dccg *base; if (dccg_dcn == NULL) { diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dpp_cm.c index 8dc3d1f73984..2feb051a2002 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dpp_cm.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dpp_cm.c @@ -482,7 +482,7 @@ bool dpp20_program_blnd_lut( next_mode = LUT_RAM_A; dpp20_power_on_blnd_lut(dpp_base, true); - dpp20_configure_blnd_lut(dpp_base, next_mode == LUT_RAM_A ? true:false); + dpp20_configure_blnd_lut(dpp_base, next_mode == LUT_RAM_A); if (next_mode == LUT_RAM_A) dpp20_program_blnd_luta_settings(dpp_base, params); @@ -893,7 +893,7 @@ bool dpp20_program_shaper( else next_mode = LUT_RAM_A; - dpp20_configure_shaper_lut(dpp_base, next_mode == LUT_RAM_A ? true:false); + dpp20_configure_shaper_lut(dpp_base, next_mode == LUT_RAM_A); if (next_mode == LUT_RAM_A) dpp20_program_shaper_luta_settings(dpp_base, params); diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c index bec7059f6d5d..a1318c31bcfa 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c @@ -1,5 +1,5 @@ /* - * Copyright 2012-17 Advanced Micro Devices, Inc. + * Copyright 2012-2021 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -181,11 +181,14 @@ void hubp2_vready_at_or_After_vsync(struct hubp *hubp, else Set HUBP_VREADY_AT_OR_AFTER_VSYNC = 0 */ - if ((pipe_dest->vstartup_start - (pipe_dest->vready_offset+pipe_dest->vupdate_width - + pipe_dest->vupdate_offset) / pipe_dest->htotal) <= pipe_dest->vblank_end) { - value = 1; - } else - value = 0; + if (pipe_dest->htotal != 0) { + if ((pipe_dest->vstartup_start - (pipe_dest->vready_offset+pipe_dest->vupdate_width + + pipe_dest->vupdate_offset) / pipe_dest->htotal) <= pipe_dest->vblank_end) { + value = 1; + } else + value = 0; + } + REG_UPDATE(DCHUBP_CNTL, HUBP_VREADY_AT_OR_AFTER_VSYNC, value); } diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index 6a10daec15cc..25de15158801 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -1700,7 +1700,11 @@ void dcn20_program_front_end_for_ctx( if (pipe->plane_state && !pipe->top_pipe) { while (pipe) { - dcn20_program_pipe(dc, pipe, context); + if (hws->funcs.program_pipe) + hws->funcs.program_pipe(dc, pipe, context); + else + dcn20_program_pipe(dc, pipe, context); + pipe = pipe->bottom_pipe; } /* Program secondary blending tree and writeback pipes */ @@ -2263,9 +2267,25 @@ void dcn20_get_mpctree_visual_confirm_color( *color = pipe_colors[top_pipe->pipe_idx]; } -void dcn20_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx) +void dcn20_update_visual_confirm_color(struct dc *dc, struct pipe_ctx *pipe_ctx, struct tg_color *color, int mpcc_id) { struct dce_hwseq *hws = dc->hwseq; + struct mpc *mpc = dc->res_pool->mpc; + + /* input to MPCC is always RGB, by default leave black_color at 0 */ + if (dc->debug.visual_confirm == VISUAL_CONFIRM_HDR) + hws->funcs.get_hdr_visual_confirm_color(pipe_ctx, color); + else if (dc->debug.visual_confirm == VISUAL_CONFIRM_SURFACE) + hws->funcs.get_surface_visual_confirm_color(pipe_ctx, color); + else if (dc->debug.visual_confirm == VISUAL_CONFIRM_MPCTREE) + dcn20_get_mpctree_visual_confirm_color(pipe_ctx, color); + + if (mpc->funcs->set_bg_color) + mpc->funcs->set_bg_color(mpc, color, mpcc_id); +} + +void dcn20_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx) +{ struct hubp *hubp = pipe_ctx->plane_res.hubp; struct mpcc_blnd_cfg blnd_cfg = { {0} }; bool per_pixel_alpha = pipe_ctx->plane_state->per_pixel_alpha; @@ -2274,15 +2294,6 @@ void dcn20_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx) struct mpc *mpc = dc->res_pool->mpc; struct mpc_tree *mpc_tree_params = &(pipe_ctx->stream_res.opp->mpc_tree_params); - // input to MPCC is always RGB, by default leave black_color at 0 - if (dc->debug.visual_confirm == VISUAL_CONFIRM_HDR) { - hws->funcs.get_hdr_visual_confirm_color(pipe_ctx, &blnd_cfg.black_color); - } else if (dc->debug.visual_confirm == VISUAL_CONFIRM_SURFACE) { - hws->funcs.get_surface_visual_confirm_color(pipe_ctx, &blnd_cfg.black_color); - } else if (dc->debug.visual_confirm == VISUAL_CONFIRM_MPCTREE) { - dcn20_get_mpctree_visual_confirm_color(pipe_ctx, &blnd_cfg.black_color); - } - if (per_pixel_alpha) blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA; else @@ -2316,6 +2327,8 @@ void dcn20_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx) */ mpcc_id = hubp->inst; + dc->hwss.update_visual_confirm_color(dc, pipe_ctx, &blnd_cfg.black_color, mpcc_id); + /* If there is no full update, don't need to touch MPC tree*/ if (!pipe_ctx->plane_state->update_flags.bits.full_update && !pipe_ctx->update_flags.bits.mpcc) { diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h index c69f766a40ce..6bba191cd33e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h @@ -146,5 +146,10 @@ void dcn20_set_disp_pattern_generator(const struct dc *dc, const struct tg_color *solid_color, int width, int height, int offset); +void dcn20_update_visual_confirm_color(struct dc *dc, + struct pipe_ctx *pipe_ctx, + struct tg_color *color, + int mpcc_id); + #endif /* __DC_HWSS_DCN20_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c index 7218ed9e43dc..2f59f10e5f09 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c @@ -95,6 +95,8 @@ static const struct hw_sequencer_funcs dcn20_funcs = { .optimize_timing_for_fsft = dcn20_optimize_timing_for_fsft, #endif .set_disp_pattern_generator = dcn20_set_disp_pattern_generator, + .get_dcc_en_bits = dcn10_get_dcc_en_bits, + .update_visual_confirm_color = dcn20_update_visual_confirm_color, }; static const struct hwseq_private_funcs dcn20_private_funcs = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.c index fa013496e26b..2f9bfaeaba8d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.c @@ -341,8 +341,7 @@ void enc2_hw_init(struct link_encoder *enc) } else { AUX_REG_WRITE(AUX_DPHY_RX_CONTROL0, 0x103d1110); - AUX_REG_WRITE(AUX_DPHY_TX_CONTROL, 0x21c4d); - + AUX_REG_WRITE(AUX_DPHY_TX_CONTROL, 0x21c7a); } //AUX_DPHY_TX_REF_CONTROL'AUX_TX_REF_DIV HW default is 0x32; diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mpc.c index 6a99fdd55e8c..947eb0df3f12 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mpc.c @@ -67,7 +67,6 @@ void mpc2_update_blending( REG_SET(MPCC_BOT_GAIN_INSIDE[mpcc_id], 0, MPCC_BOT_GAIN_INSIDE, blnd_cfg->bottom_inside_gain); REG_SET(MPCC_BOT_GAIN_OUTSIDE[mpcc_id], 0, MPCC_BOT_GAIN_OUTSIDE, blnd_cfg->bottom_outside_gain); - mpc1_set_bg_color(mpc, &blnd_cfg->black_color, mpcc_id); mpcc->blnd_cfg = *blnd_cfg; } @@ -557,6 +556,7 @@ const struct mpc_funcs dcn20_mpc_funcs = { .set_output_gamma = mpc2_set_output_gamma, .power_on_mpc_mem_pwr = mpc20_power_on_ogam_lut, .get_mpc_out_mux = mpc1_get_mpc_out_mux, + .set_bg_color = mpc1_set_bg_color, }; void dcn20_mpc_construct(struct dcn20_mpc *mpc20, diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c index ea7eaf7d755f..3139d90017ee 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c @@ -134,22 +134,6 @@ void optc2_set_gsl_window(struct timing_generator *optc, OTG_GSL_WINDOW_END_Y, params->gsl_window_end_y); } -/** - * Vupdate keepout can be set to a window to block the update lock for that pipe from changing. - * Start offset begins with vstartup and goes for x number of clocks, - * end offset starts from end of vupdate to x number of clocks. - */ -void optc2_set_vupdate_keepout(struct timing_generator *optc, - const struct vupdate_keepout_params *params) -{ - struct optc *optc1 = DCN10TG_FROM_TG(optc); - - REG_SET_3(OTG_VUPDATE_KEEPOUT, 0, - MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET, params->start_offset, - MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET, params->end_offset, - OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, params->enable); -} - void optc2_set_gsl_source_select( struct timing_generator *optc, int group_idx, diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h index e0a0a8a8e2c6..3dee2ec2a1bb 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h @@ -56,9 +56,6 @@ SF(OTG0_OTG_GSL_WINDOW_X, OTG_GSL_WINDOW_END_X, mask_sh), \ SF(OTG0_OTG_GSL_WINDOW_Y, OTG_GSL_WINDOW_START_Y, mask_sh),\ SF(OTG0_OTG_GSL_WINDOW_Y, OTG_GSL_WINDOW_END_Y, mask_sh),\ - SF(OTG0_OTG_VUPDATE_KEEPOUT, OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, mask_sh), \ - SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET, mask_sh), \ - SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET, mask_sh), \ SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_MASTER_MODE, mask_sh), \ SF(OTG0_OTG_GSL_CONTROL, OTG_MASTER_UPDATE_LOCK_GSL_EN, mask_sh), \ SF(OTG0_OTG_DSC_START_POSITION, OTG_DSC_START_POSITION_X, mask_sh), \ diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c index 2307b3517821..6a56a03cfba3 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -112,7 +112,7 @@ struct _vcs_dpi_ip_params_st dcn2_0_ip = { .is_line_buffer_bpp_fixed = 0, .line_buffer_fixed_bpp = 0, .dcc_supported = true, - .max_line_buffer_lines = 32, + .max_line_buffer_lines = 12, .writeback_luma_buffer_size_kbytes = 12, .writeback_chroma_buffer_size_kbytes = 8, .writeback_chroma_line_buffer_width_pixels = 4, @@ -180,7 +180,7 @@ static struct _vcs_dpi_ip_params_st dcn2_0_nv14_ip = { .is_line_buffer_bpp_fixed = 0, .line_buffer_fixed_bpp = 0, .dcc_supported = true, - .max_line_buffer_lines = 32, + .max_line_buffer_lines = 12, .writeback_luma_buffer_size_kbytes = 12, .writeback_chroma_buffer_size_kbytes = 8, .writeback_chroma_line_buffer_width_pixels = 4, @@ -1075,7 +1075,6 @@ static const struct dc_debug_options debug_defaults_drv = { .scl_reset_length10 = true, .sanity_checks = false, .underflow_assert_delay_us = 0xFFFFFFFF, - .use_max_lb = true }; static const struct dc_debug_options debug_defaults_diags = { @@ -1092,7 +1091,6 @@ static const struct dc_debug_options debug_defaults_diags = { .scl_reset_length10 = true, .underflow_assert_delay_us = 0xFFFFFFFF, .enable_tri_buf = true, - .use_max_lb = true }; void dcn20_dpp_destroy(struct dpp **dpp) @@ -1106,7 +1104,7 @@ struct dpp *dcn20_dpp_create( uint32_t inst) { struct dcn20_dpp *dpp = - kzalloc(sizeof(struct dcn20_dpp), GFP_KERNEL); + kzalloc(sizeof(struct dcn20_dpp), GFP_ATOMIC); if (!dpp) return NULL; @@ -1124,7 +1122,7 @@ struct input_pixel_processor *dcn20_ipp_create( struct dc_context *ctx, uint32_t inst) { struct dcn10_ipp *ipp = - kzalloc(sizeof(struct dcn10_ipp), GFP_KERNEL); + kzalloc(sizeof(struct dcn10_ipp), GFP_ATOMIC); if (!ipp) { BREAK_TO_DEBUGGER(); @@ -1141,7 +1139,7 @@ struct output_pixel_processor *dcn20_opp_create( struct dc_context *ctx, uint32_t inst) { struct dcn20_opp *opp = - kzalloc(sizeof(struct dcn20_opp), GFP_KERNEL); + kzalloc(sizeof(struct dcn20_opp), GFP_ATOMIC); if (!opp) { BREAK_TO_DEBUGGER(); @@ -1158,7 +1156,7 @@ struct dce_aux *dcn20_aux_engine_create( uint32_t inst) { struct aux_engine_dce110 *aux_engine = - kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); + kzalloc(sizeof(struct aux_engine_dce110), GFP_ATOMIC); if (!aux_engine) return NULL; @@ -1196,7 +1194,7 @@ struct dce_i2c_hw *dcn20_i2c_hw_create( uint32_t inst) { struct dce_i2c_hw *dce_i2c_hw = - kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); + kzalloc(sizeof(struct dce_i2c_hw), GFP_ATOMIC); if (!dce_i2c_hw) return NULL; @@ -1209,7 +1207,7 @@ struct dce_i2c_hw *dcn20_i2c_hw_create( struct mpc *dcn20_mpc_create(struct dc_context *ctx) { struct dcn20_mpc *mpc20 = kzalloc(sizeof(struct dcn20_mpc), - GFP_KERNEL); + GFP_ATOMIC); if (!mpc20) return NULL; @@ -1227,7 +1225,7 @@ struct hubbub *dcn20_hubbub_create(struct dc_context *ctx) { int i; struct dcn20_hubbub *hubbub = kzalloc(sizeof(struct dcn20_hubbub), - GFP_KERNEL); + GFP_ATOMIC); if (!hubbub) return NULL; @@ -1255,7 +1253,7 @@ struct timing_generator *dcn20_timing_generator_create( uint32_t instance) { struct optc *tgn10 = - kzalloc(sizeof(struct optc), GFP_KERNEL); + kzalloc(sizeof(struct optc), GFP_ATOMIC); if (!tgn10) return NULL; @@ -1334,7 +1332,7 @@ static struct clock_source *dcn20_clock_source_create( bool dp_clk_src) { struct dce110_clk_src *clk_src = - kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); + kzalloc(sizeof(struct dce110_clk_src), GFP_ATOMIC); if (!clk_src) return NULL; @@ -1440,7 +1438,7 @@ struct display_stream_compressor *dcn20_dsc_create( struct dc_context *ctx, uint32_t inst) { struct dcn20_dsc *dsc = - kzalloc(sizeof(struct dcn20_dsc), GFP_KERNEL); + kzalloc(sizeof(struct dcn20_dsc), GFP_ATOMIC); if (!dsc) { BREAK_TO_DEBUGGER(); @@ -1574,7 +1572,7 @@ struct hubp *dcn20_hubp_create( uint32_t inst) { struct dcn20_hubp *hubp2 = - kzalloc(sizeof(struct dcn20_hubp), GFP_KERNEL); + kzalloc(sizeof(struct dcn20_hubp), GFP_ATOMIC); if (!hubp2) return NULL; @@ -2203,10 +2201,11 @@ int dcn20_populate_dml_pipes_from_context( pipes[pipe_cnt].dout.output_bpp = (output_bpc * 3.0) / 2; break; case PIXEL_ENCODING_YCBCR422: - if (true) /* todo */ - pipes[pipe_cnt].dout.output_format = dm_s422; - else + if (res_ctx->pipe_ctx[i].stream->timing.flags.DSC && + !res_ctx->pipe_ctx[i].stream->timing.dsc_cfg.ycbcr422_simple) pipes[pipe_cnt].dout.output_format = dm_n422; + else + pipes[pipe_cnt].dout.output_format = dm_s422; pipes[pipe_cnt].dout.output_bpp = output_bpc * 2; break; default: @@ -2218,7 +2217,7 @@ int dcn20_populate_dml_pipes_from_context( pipes[pipe_cnt].dout.output_bpp = res_ctx->pipe_ctx[i].stream->timing.dsc_cfg.bits_per_pixel / 16.0; /* todo: default max for now, until there is logic reflecting this in dc*/ - pipes[pipe_cnt].dout.output_bpc = 12; + pipes[pipe_cnt].dout.dsc_input_bpc = 12; /*fill up the audio sample rate (unit in kHz)*/ get_audio_check(&res_ctx->pipe_ctx[i].stream->audio_info, &aud_check); pipes[pipe_cnt].dout.max_audio_sample_rate = aud_check.max_audiosample_rate / 1000; @@ -3396,7 +3395,7 @@ bool dcn20_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool) static struct pp_smu_funcs *dcn20_pp_smu_create(struct dc_context *ctx) { - struct pp_smu_funcs *pp_smu = kzalloc(sizeof(*pp_smu), GFP_KERNEL); + struct pp_smu_funcs *pp_smu = kzalloc(sizeof(*pp_smu), GFP_ATOMIC); if (!pp_smu) return pp_smu; @@ -3668,7 +3667,7 @@ static bool dcn20_resource_construct( int i; struct dc_context *ctx = dc->ctx; struct irq_service_init_data init_data; - struct ddc_service_init_data ddc_init_data; + struct ddc_service_init_data ddc_init_data = {0}; struct _vcs_dpi_soc_bounding_box_st *loaded_bb = get_asic_rev_soc_bb(ctx->asic_id.hw_internal_rev); struct _vcs_dpi_ip_params_st *loaded_ip = @@ -4042,7 +4041,7 @@ struct resource_pool *dcn20_create_resource_pool( struct dc *dc) { struct dcn20_resource_pool *pool = - kzalloc(sizeof(struct dcn20_resource_pool), GFP_KERNEL); + kzalloc(sizeof(struct dcn20_resource_pool), GFP_ATOMIC); if (!pool) return NULL; diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hwseq.c index d3b643089603..69cc192a7e71 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hwseq.c @@ -218,6 +218,8 @@ bool dcn21_set_backlight_level(struct pipe_ctx *pipe_ctx, cmd.abm_set_backlight.header.sub_type = DMUB_CMD__ABM_SET_BACKLIGHT; cmd.abm_set_backlight.abm_set_backlight_data.frame_ramp = frame_ramp; cmd.abm_set_backlight.abm_set_backlight_data.backlight_user_level = backlight_pwm_u16_16; + cmd.abm_set_backlight.abm_set_backlight_data.version = DMUB_CMD_ABM_CONTROL_VERSION_1; + cmd.abm_set_backlight.abm_set_backlight_data.panel_mask = (0x01 << panel_cntl->inst); cmd.abm_set_backlight.header.payload_bytes = sizeof(struct dmub_cmd_abm_set_backlight_data); dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd); diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c index 074e2713257f..523e25f7e410 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c @@ -1,5 +1,5 @@ /* - * Copyright 2016 Advanced Micro Devices, Inc. + * Copyright 2016-2020 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -99,6 +99,8 @@ static const struct hw_sequencer_funcs dcn21_funcs = { #endif .is_abm_supported = dcn21_is_abm_supported, .set_disp_pattern_generator = dcn20_set_disp_pattern_generator, + .get_dcc_en_bits = dcn10_get_dcc_en_bits, + .update_visual_confirm_color = dcn20_update_visual_confirm_color, }; static const struct hwseq_private_funcs dcn21_private_funcs = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c index e62f931fc269..38a2aa87f5f5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c @@ -55,7 +55,6 @@ #include "dce/dce_audio.h" #include "dce/dce_hwseq.h" #include "virtual/virtual_stream_encoder.h" -#include "dce110/dce110_resource.h" #include "dml/display_mode_vba.h" #include "dcn20/dcn20_dccg.h" #include "dcn21/dcn21_dccg.h" @@ -115,7 +114,7 @@ struct _vcs_dpi_ip_params_st dcn2_1_ip = { .is_line_buffer_bpp_fixed = 0, .line_buffer_fixed_bpp = 0, .dcc_supported = true, - .max_line_buffer_lines = 32, + .max_line_buffer_lines = 12, .writeback_luma_buffer_size_kbytes = 12, .writeback_chroma_buffer_size_kbytes = 8, .writeback_chroma_line_buffer_width_pixels = 4, @@ -1576,10 +1575,12 @@ static struct _vcs_dpi_voltage_scaling_st construct_low_pstate_lvl(struct clk_li low_pstate_lvl.phyclk_d18_mhz = dcn2_1_soc.clock_limits[high_voltage_lvl].phyclk_d18_mhz; low_pstate_lvl.phyclk_mhz = dcn2_1_soc.clock_limits[high_voltage_lvl].phyclk_mhz; - for (i = clk_table->num_entries; i > 1; i--) - clk_table->entries[i] = clk_table->entries[i-1]; - clk_table->entries[1] = clk_table->entries[0]; - clk_table->num_entries++; + if (clk_table->num_entries < MAX_NUM_DPM_LVL) { + for (i = clk_table->num_entries; i > 1; i--) + clk_table->entries[i] = clk_table->entries[i-1]; + clk_table->entries[1] = clk_table->entries[0]; + clk_table->num_entries++; + } return low_pstate_lvl; } @@ -1611,10 +1612,6 @@ static void update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_param } } - /* clk_table[1] is reserved for min DF PState. skip here to fill in later. */ - if (i == 1) - k++; - clock_limits[k].state = k; clock_limits[k].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz; clock_limits[k].fabricclk_mhz = clk_table->entries[i].fclk_mhz; @@ -1631,14 +1628,25 @@ static void update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_param k++; } - for (i = 0; i < clk_table->num_entries + 1; i++) - dcn2_1_soc.clock_limits[i] = clock_limits[i]; + + if (clk_table->num_entries >= MAX_NUM_DPM_LVL) { + for (i = 0; i < clk_table->num_entries + 1; i++) + dcn2_1_soc.clock_limits[i] = clock_limits[i]; + } else { + dcn2_1_soc.clock_limits[0] = clock_limits[0]; + for (i = 2; i < clk_table->num_entries + 1; i++) { + dcn2_1_soc.clock_limits[i] = clock_limits[i - 1]; + dcn2_1_soc.clock_limits[i].state = i; + } + } + if (clk_table->num_entries) { - dcn2_1_soc.num_states = clk_table->num_entries + 1; /* fill in min DF PState */ dcn2_1_soc.clock_limits[1] = construct_low_pstate_lvl(clk_table, closest_clk_lvl); + dcn2_1_soc.num_states = clk_table->num_entries; /* duplicate last level */ - dcn2_1_soc.clock_limits[dcn2_1_soc.num_states] = dcn2_1_soc.clock_limits[dcn2_1_soc.num_states - 1]; + dcn2_1_soc.clock_limits[dcn2_1_soc.num_states] = + dcn2_1_soc.clock_limits[dcn2_1_soc.num_states - 1]; dcn2_1_soc.clock_limits[dcn2_1_soc.num_states].state = dcn2_1_soc.num_states; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.h index 0b1755f1dea8..9566b9037458 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.h @@ -85,7 +85,9 @@ SRI(DP_MSE_RATE_UPDATE, DP, id), \ SRI(DP_PIXEL_FORMAT, DP, id), \ SRI(DP_SEC_CNTL, DP, id), \ + SRI(DP_SEC_CNTL1, DP, id), \ SRI(DP_SEC_CNTL2, DP, id), \ + SRI(DP_SEC_CNTL5, DP, id), \ SRI(DP_SEC_CNTL6, DP, id), \ SRI(DP_STEER_FIFO, DP, id), \ SRI(DP_VID_M, DP, id), \ @@ -169,7 +171,9 @@ SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP5_ENABLE, mask_sh),\ SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP6_ENABLE, mask_sh),\ SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP7_ENABLE, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL1, DP_SEC_GSP5_LINE_REFERENCE, mask_sh),\ SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP7_SEND, mask_sh),\ + SE_SF(DP0_DP_SEC_CNTL5, DP_SEC_GSP5_LINE_NUM, mask_sh),\ SE_SF(DP0_DP_SEC_CNTL6, DP_SEC_GSP7_LINE_NUM, mask_sh),\ SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP11_PPS, mask_sh),\ SE_SF(DP0_DP_GSP11_CNTL, DP_SEC_GSP11_ENABLE, mask_sh),\ diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.h index 705fbfc37502..8a32772d4e91 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.h @@ -134,6 +134,7 @@ HUBP_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, SECONDARY_SURFACE_DCC_EN, mask_sh),\ HUBP_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, SECONDARY_SURFACE_DCC_IND_BLK, mask_sh),\ HUBP_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, SECONDARY_SURFACE_DCC_IND_BLK_C, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_FLIP_INTERRUPT, SURFACE_FLIP_INT_MASK, mask_sh),\ HUBP_SF(HUBPRET0_HUBPRET_CONTROL, DET_BUF_PLANE1_BASE_ADDRESS, mask_sh),\ HUBP_SF(HUBPRET0_HUBPRET_CONTROL, CROSSBAR_SRC_CB_B, mask_sh),\ HUBP_SF(HUBPRET0_HUBPRET_CONTROL, CROSSBAR_SRC_CR_R, mask_sh),\ diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c index d53f8b39699b..83685310a391 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c @@ -813,6 +813,15 @@ bool dcn30_apply_idle_power_optimizations(struct dc *dc, bool enable) (100LL + dc->debug.mall_additional_timer_percent) + denom - 1), denom) - 64LL; + /* In some cases the stutter period is really big (tiny modes) in these + * cases MALL cant be enabled, So skip these cases to avoid a ASSERT() + * + * We can check if stutter_period is more than 1/10th the frame time to + * consider if we can actually meet the range of hysteresis timer + */ + if (stutter_period > 100000/refresh_hz) + return false; + /* scale should be increased until it fits into 6 bits */ while (tmr_delay & ~0x3F) { tmr_scale++; diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c index c4c14e9c1309..a978d848d370 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c @@ -1,5 +1,5 @@ /* - * Copyright 2020 Advanced Micro Devices, Inc. + * Copyright 2016-2020 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -98,6 +98,8 @@ static const struct hw_sequencer_funcs dcn30_funcs = { .hardware_release = dcn30_hardware_release, .set_pipe = dcn21_set_pipe, .set_disp_pattern_generator = dcn30_set_disp_pattern_generator, + .get_dcc_en_bits = dcn10_get_dcc_en_bits, + .update_visual_confirm_color = dcn20_update_visual_confirm_color, }; static const struct hwseq_private_funcs dcn30_private_funcs = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c index 910c17fd4278..a82319f4d081 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c @@ -874,7 +874,7 @@ bool mpc3_program_shaper( else next_mode = LUT_RAM_A; - mpc3_configure_shaper_lut(mpc, next_mode == LUT_RAM_A ? true:false, rmu_idx); + mpc3_configure_shaper_lut(mpc, next_mode == LUT_RAM_A, rmu_idx); if (next_mode == LUT_RAM_A) mpc3_program_shaper_luta_settings(mpc, params, rmu_idx); @@ -1431,7 +1431,7 @@ const struct mpc_funcs dcn30_mpc_funcs = { .release_rmu = mpcc3_release_rmu, .power_on_mpc_mem_pwr = mpc3_power_on_ogam_lut, .get_mpc_out_mux = mpc1_get_mpc_out_mux, - + .set_bg_color = mpc1_set_bg_color, }; void dcn30_mpc_construct(struct dcn30_mpc *mpc30, diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.h index d1fd0b9aa0f9..b7dc78624963 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.h @@ -585,6 +585,181 @@ type MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS;\ type MPC_RMU_SHAPER_MODE_CURRENT +#define MPC_COMMON_MASK_SH_LIST_DCN303(mask_sh) \ + MPC_COMMON_MASK_SH_LIST_DCN1_0(mask_sh),\ + SF(MPCC0_MPCC_CONTROL, MPCC_BG_BPC, mask_sh),\ + SF(MPCC0_MPCC_CONTROL, MPCC_BOT_GAIN_MODE, mask_sh),\ + SF(MPCC0_MPCC_TOP_GAIN, MPCC_TOP_GAIN, mask_sh),\ + SF(MPCC0_MPCC_BOT_GAIN_INSIDE, MPCC_BOT_GAIN_INSIDE, mask_sh),\ + SF(MPCC0_MPCC_BOT_GAIN_OUTSIDE, MPCC_BOT_GAIN_OUTSIDE, mask_sh),\ + SF(MPC_OUT0_CSC_MODE, MPC_OCSC_MODE, mask_sh),\ + SF(MPC_OUT0_CSC_C11_C12_A, MPC_OCSC_C11_A, mask_sh),\ + SF(MPC_OUT0_CSC_C11_C12_A, MPC_OCSC_C12_A, mask_sh),\ + SF(MPCC0_MPCC_STATUS, MPCC_DISABLED, mask_sh),\ + SF(MPCC0_MPCC_MEM_PWR_CTRL, MPCC_OGAM_MEM_PWR_FORCE, mask_sh),\ + SF(MPCC0_MPCC_MEM_PWR_CTRL, MPCC_OGAM_MEM_PWR_DIS, mask_sh),\ + SF(MPCC0_MPCC_MEM_PWR_CTRL, MPCC_OGAM_MEM_LOW_PWR_MODE, mask_sh),\ + SF(MPCC0_MPCC_MEM_PWR_CTRL, MPCC_OGAM_MEM_PWR_STATE, mask_sh),\ + SF(MPC_OUT0_DENORM_CONTROL, MPC_OUT_DENORM_MODE, mask_sh),\ + SF(MPC_OUT0_DENORM_CONTROL, MPC_OUT_DENORM_CLAMP_MAX_R_CR, mask_sh),\ + SF(MPC_OUT0_DENORM_CONTROL, MPC_OUT_DENORM_CLAMP_MIN_R_CR, mask_sh),\ + SF(MPC_OUT0_DENORM_CLAMP_G_Y, MPC_OUT_DENORM_CLAMP_MAX_G_Y, mask_sh),\ + SF(MPC_OUT0_DENORM_CLAMP_G_Y, MPC_OUT_DENORM_CLAMP_MIN_G_Y, mask_sh),\ + SF(MPC_OUT0_DENORM_CLAMP_B_CB, MPC_OUT_DENORM_CLAMP_MAX_B_CB, mask_sh),\ + SF(MPC_OUT0_DENORM_CLAMP_B_CB, MPC_OUT_DENORM_CLAMP_MIN_B_CB, mask_sh),\ + SF(MPCC_OGAM0_MPCC_GAMUT_REMAP_MODE, MPCC_GAMUT_REMAP_MODE, mask_sh),\ + SF(MPCC_OGAM0_MPCC_GAMUT_REMAP_MODE, MPCC_GAMUT_REMAP_MODE_CURRENT, mask_sh),\ + SF(MPCC_OGAM0_MPCC_GAMUT_REMAP_COEF_FORMAT, MPCC_GAMUT_REMAP_COEF_FORMAT, mask_sh),\ + SF(MPCC_OGAM0_MPC_GAMUT_REMAP_C11_C12_A, MPCC_GAMUT_REMAP_C11_A, mask_sh),\ + SF(MPCC_OGAM0_MPC_GAMUT_REMAP_C11_C12_A, MPCC_GAMUT_REMAP_C12_A, mask_sh),\ + SF(MPC_DWB0_MUX, MPC_DWB0_MUX, mask_sh),\ + SF(MPC_DWB0_MUX, MPC_DWB0_MUX_STATUS, mask_sh),\ + SF(MPC_OUT0_MUX, MPC_OUT_RATE_CONTROL, mask_sh),\ + SF(MPC_OUT0_MUX, MPC_OUT_RATE_CONTROL_DISABLE, mask_sh),\ + SF(MPC_OUT0_MUX, MPC_OUT_FLOW_CONTROL_MODE, mask_sh),\ + SF(MPC_OUT0_MUX, MPC_OUT_FLOW_CONTROL_COUNT, mask_sh), \ + SF(MPC_RMU_CONTROL, MPC_RMU0_MUX, mask_sh), \ + SF(MPC_RMU_CONTROL, MPC_RMU0_MUX_STATUS, mask_sh), \ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_REGION_0_1, MPCC_OGAM_RAMA_EXP_REGION0_LUT_OFFSET, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_REGION_0_1, MPCC_OGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_REGION_0_1, MPCC_OGAM_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_REGION_0_1, MPCC_OGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_END_CNTL2_B, MPCC_OGAM_RAMA_EXP_REGION_END_SLOPE_B, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_END_CNTL2_B, MPCC_OGAM_RAMA_EXP_REGION_END_B, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_END_CNTL1_B, MPCC_OGAM_RAMA_EXP_REGION_END_BASE_B, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_START_SLOPE_CNTL_B, MPCC_OGAM_RAMA_EXP_REGION_START_SLOPE_B, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_START_BASE_CNTL_B, MPCC_OGAM_RAMA_EXP_REGION_START_BASE_B, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_START_CNTL_B, MPCC_OGAM_RAMA_EXP_REGION_START_B, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_START_CNTL_B, MPCC_OGAM_RAMA_EXP_REGION_START_SEGMENT_B, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_OFFSET_B, MPCC_OGAM_RAMA_OFFSET_B, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_OFFSET_G, MPCC_OGAM_RAMA_OFFSET_G, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_RAMA_OFFSET_R, MPCC_OGAM_RAMA_OFFSET_R, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_LUT_INDEX, MPCC_OGAM_LUT_INDEX, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_CONTROL, MPCC_OGAM_MODE, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_CONTROL, MPCC_OGAM_SELECT, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_CONTROL, MPCC_OGAM_PWL_DISABLE, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_CONTROL, MPCC_OGAM_MODE_CURRENT, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_CONTROL, MPCC_OGAM_SELECT_CURRENT, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_WRITE_COLOR_MASK, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_READ_COLOR_SEL, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_READ_DBG, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_HOST_SEL, mask_sh),\ + SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_CONFIG_MODE, mask_sh),\ + /*SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_STATUS, mask_sh),*/\ + SF(MPCC_OGAM0_MPCC_OGAM_LUT_DATA, MPCC_OGAM_LUT_DATA, mask_sh),\ + SF(MPC_RMU0_3DLUT_MODE, MPC_RMU_3DLUT_MODE, mask_sh),\ + SF(MPC_RMU0_3DLUT_MODE, MPC_RMU_3DLUT_SIZE, mask_sh),\ + /*SF(MPC_RMU0_3DLUT_MODE, MPC_RMU_3DLUT_MODE_CURRENT, mask_sh),*/\ + SF(MPC_RMU0_3DLUT_READ_WRITE_CONTROL, MPC_RMU_3DLUT_WRITE_EN_MASK, mask_sh),\ + SF(MPC_RMU0_3DLUT_READ_WRITE_CONTROL, MPC_RMU_3DLUT_RAM_SEL, mask_sh),\ + SF(MPC_RMU0_3DLUT_READ_WRITE_CONTROL, MPC_RMU_3DLUT_30BIT_EN, mask_sh),\ + /*SF(MPC_RMU0_3DLUT_READ_WRITE_CONTROL, MPC_RMU_3DLUT_CONFIG_STATUS, mask_sh),*/\ + SF(MPC_RMU0_3DLUT_READ_WRITE_CONTROL, MPC_RMU_3DLUT_READ_SEL, mask_sh),\ + SF(MPC_RMU0_3DLUT_INDEX, MPC_RMU_3DLUT_INDEX, mask_sh),\ + SF(MPC_RMU0_3DLUT_DATA, MPC_RMU_3DLUT_DATA0, mask_sh),\ + SF(MPC_RMU0_3DLUT_DATA, MPC_RMU_3DLUT_DATA1, mask_sh),\ + SF(MPC_RMU0_3DLUT_DATA_30BIT, MPC_RMU_3DLUT_DATA_30BIT, mask_sh),\ + SF(MPC_RMU0_SHAPER_CONTROL, MPC_RMU_SHAPER_LUT_MODE, mask_sh),\ + /*SF(MPC_RMU0_SHAPER_CONTROL, MPC_RMU_SHAPER_LUT_MODE_CURRENT, mask_sh),*/\ + SF(MPC_RMU0_SHAPER_OFFSET_R, MPC_RMU_SHAPER_OFFSET_R, mask_sh),\ + SF(MPC_RMU0_SHAPER_OFFSET_G, MPC_RMU_SHAPER_OFFSET_G, mask_sh),\ + SF(MPC_RMU0_SHAPER_OFFSET_B, MPC_RMU_SHAPER_OFFSET_B, mask_sh),\ + SF(MPC_RMU0_SHAPER_SCALE_R, MPC_RMU_SHAPER_SCALE_R, mask_sh),\ + SF(MPC_RMU0_SHAPER_SCALE_G_B, MPC_RMU_SHAPER_SCALE_G, mask_sh),\ + SF(MPC_RMU0_SHAPER_SCALE_G_B, MPC_RMU_SHAPER_SCALE_B, mask_sh),\ + SF(MPC_RMU0_SHAPER_LUT_INDEX, MPC_RMU_SHAPER_LUT_INDEX, mask_sh),\ + SF(MPC_RMU0_SHAPER_LUT_DATA, MPC_RMU_SHAPER_LUT_DATA, mask_sh),\ + SF(MPC_RMU0_SHAPER_LUT_WRITE_EN_MASK, MPC_RMU_SHAPER_LUT_WRITE_EN_MASK, mask_sh),\ + SF(MPC_RMU0_SHAPER_LUT_WRITE_EN_MASK, MPC_RMU_SHAPER_LUT_WRITE_SEL, mask_sh),\ + /*SF(MPC_RMU0_SHAPER_LUT_WRITE_EN_MASK, MPC_RMU_SHAPER_CONFIG_STATUS, mask_sh),*/\ + SF(MPC_RMU0_SHAPER_RAMA_START_CNTL_B, MPC_RMU_SHAPER_RAMA_EXP_REGION_START_B, mask_sh),\ + SF(MPC_RMU0_SHAPER_RAMA_START_CNTL_B, MPC_RMU_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, mask_sh),\ + SF(MPC_RMU0_SHAPER_RAMA_END_CNTL_B, MPC_RMU_SHAPER_RAMA_EXP_REGION_END_B, mask_sh),\ + SF(MPC_RMU0_SHAPER_RAMA_END_CNTL_B, MPC_RMU_SHAPER_RAMA_EXP_REGION_END_BASE_B, mask_sh),\ + SF(MPC_RMU0_SHAPER_RAMA_REGION_0_1, MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, mask_sh),\ + SF(MPC_RMU0_SHAPER_RAMA_REGION_0_1, MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMU0_SHAPER_RAMA_REGION_0_1, MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh),\ + SF(MPC_RMU0_SHAPER_RAMA_REGION_0_1, MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\ + SF(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_MEM_PWR_FORCE, mask_sh),\ + SF(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_MEM_PWR_DIS, mask_sh),\ + SF(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_SHAPER_MEM_PWR_STATE, mask_sh),\ + SF(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_3DLUT_MEM_PWR_STATE, mask_sh),\ + SF(MPC_RMU_MEM_PWR_CTRL, MPC_RMU0_MEM_LOW_PWR_MODE, mask_sh),\ + SF(MPC_RMU0_SHAPER_CONTROL, MPC_RMU_SHAPER_MODE_CURRENT, mask_sh),\ + SF(CUR_VUPDATE_LOCK_SET0, CUR_VUPDATE_LOCK_SET, mask_sh) + +#define MPC_REG_FIELD_LIST_DCN3_03(type) \ + MPC_REG_FIELD_LIST_DCN2_0(type) \ + type MPC_DWB0_MUX;\ + type MPC_DWB0_MUX_STATUS;\ + type MPC_OUT_RATE_CONTROL;\ + type MPC_OUT_RATE_CONTROL_DISABLE;\ + type MPC_OUT_FLOW_CONTROL_MODE;\ + type MPC_OUT_FLOW_CONTROL_COUNT; \ + type MPCC_GAMUT_REMAP_MODE; \ + type MPCC_GAMUT_REMAP_MODE_CURRENT;\ + type MPCC_GAMUT_REMAP_COEF_FORMAT; \ + type MPCC_GAMUT_REMAP_C11_A; \ + type MPCC_GAMUT_REMAP_C12_A; \ + type MPC_RMU0_MUX; \ + type MPC_RMU0_MUX_STATUS; \ + type MPC_RMU0_MEM_PWR_FORCE;\ + type MPC_RMU0_MEM_PWR_DIS;\ + type MPC_RMU0_MEM_LOW_PWR_MODE;\ + type MPC_RMU0_SHAPER_MEM_PWR_STATE;\ + type MPC_RMU0_3DLUT_MEM_PWR_STATE;\ + type MPCC_OGAM_RAMA_EXP_REGION_START_SLOPE_B; \ + type MPCC_OGAM_RAMA_EXP_REGION_START_BASE_B;\ + type MPCC_OGAM_RAMA_OFFSET_B;\ + type MPCC_OGAM_RAMA_OFFSET_G;\ + type MPCC_OGAM_RAMA_OFFSET_R;\ + type MPCC_OGAM_SELECT; \ + type MPCC_OGAM_PWL_DISABLE; \ + type MPCC_OGAM_MODE_CURRENT; \ + type MPCC_OGAM_SELECT_CURRENT; \ + type MPCC_OGAM_LUT_WRITE_COLOR_MASK; \ + type MPCC_OGAM_LUT_READ_COLOR_SEL; \ + type MPCC_OGAM_LUT_READ_DBG; \ + type MPCC_OGAM_LUT_HOST_SEL; \ + type MPCC_OGAM_LUT_CONFIG_MODE; \ + type MPCC_OGAM_LUT_STATUS; \ + type MPCC_OGAM_RAMA_START_BASE_CNTL_B;\ + type MPCC_OGAM_MEM_LOW_PWR_MODE;\ + type MPCC_OGAM_MEM_PWR_STATE;\ + type MPC_RMU_3DLUT_MODE; \ + type MPC_RMU_3DLUT_SIZE; \ + type MPC_RMU_3DLUT_MODE_CURRENT; \ + type MPC_RMU_3DLUT_WRITE_EN_MASK;\ + type MPC_RMU_3DLUT_RAM_SEL;\ + type MPC_RMU_3DLUT_30BIT_EN;\ + type MPC_RMU_3DLUT_CONFIG_STATUS;\ + type MPC_RMU_3DLUT_READ_SEL;\ + type MPC_RMU_3DLUT_INDEX;\ + type MPC_RMU_3DLUT_DATA0;\ + type MPC_RMU_3DLUT_DATA1;\ + type MPC_RMU_3DLUT_DATA_30BIT;\ + type MPC_RMU_SHAPER_LUT_MODE;\ + type MPC_RMU_SHAPER_LUT_MODE_CURRENT;\ + type MPC_RMU_SHAPER_OFFSET_R;\ + type MPC_RMU_SHAPER_OFFSET_G;\ + type MPC_RMU_SHAPER_OFFSET_B;\ + type MPC_RMU_SHAPER_SCALE_R;\ + type MPC_RMU_SHAPER_SCALE_G;\ + type MPC_RMU_SHAPER_SCALE_B;\ + type MPC_RMU_SHAPER_LUT_INDEX;\ + type MPC_RMU_SHAPER_LUT_DATA;\ + type MPC_RMU_SHAPER_LUT_WRITE_EN_MASK;\ + type MPC_RMU_SHAPER_LUT_WRITE_SEL;\ + type MPC_RMU_SHAPER_CONFIG_STATUS;\ + type MPC_RMU_SHAPER_RAMA_EXP_REGION_START_B;\ + type MPC_RMU_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B;\ + type MPC_RMU_SHAPER_RAMA_EXP_REGION_END_B;\ + type MPC_RMU_SHAPER_RAMA_EXP_REGION_END_BASE_B;\ + type MPC_RMU_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET;\ + type MPC_RMU_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS;\ + type MPC_RMU_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET;\ + type MPC_RMU_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS;\ + type MPC_RMU_SHAPER_MODE_CURRENT struct dcn30_mpc_registers { MPC_REG_VARIABLE_LIST_DCN3_0; diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c index 8980c90b2277..ac478bdcfb2a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c @@ -97,7 +97,7 @@ void optc3_lock_doublebuffer_disable(struct timing_generator *optc) MASTER_UPDATE_LOCK_DB_END_Y, 0); REG_UPDATE(OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, 0); - REG_UPDATE(OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_EN, 1); + REG_UPDATE(OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_EN, 0); } void optc3_lock(struct timing_generator *optc) diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c index 263c2986682d..39920422409d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c @@ -120,7 +120,7 @@ struct _vcs_dpi_ip_params_st dcn3_0_ip = { .dcc_supported = true, .writeback_interface_buffer_size_kbytes = 90, .writeback_line_buffer_buffer_size = 0, - .max_line_buffer_lines = 32, + .max_line_buffer_lines = 12, .writeback_luma_buffer_size_kbytes = 12, // writeback_line_buffer_buffer_size = 656640 .writeback_chroma_buffer_size_kbytes = 8, .writeback_chroma_line_buffer_width_pixels = 4, @@ -826,10 +826,11 @@ static const struct dc_plane_cap plane_cap = { .fp16 = 16000 }, + /* 6:1 downscaling ratio: 1000/6 = 166.666 */ .max_downscale_factor = { - .argb8888 = 600, - .nv12 = 600, - .fp16 = 600 + .argb8888 = 167, + .nv12 = 167, + .fp16 = 167 } }; @@ -1724,7 +1725,7 @@ static bool init_soc_bounding_box(struct dc *dc, DC_LOGGER_INIT(dc->ctx->logger); if (!is_soc_bounding_box_valid(dc)) { - DC_LOG_ERROR("%s: not valid soc bounding box/n", __func__); + DC_LOG_ERROR("%s: not valid soc bounding box\n", __func__); return false; } @@ -2538,7 +2539,7 @@ static bool dcn30_resource_construct( int i; struct dc_context *ctx = dc->ctx; struct irq_service_init_data init_data; - struct ddc_service_init_data ddc_init_data; + struct ddc_service_init_data ddc_init_data = {0}; uint32_t pipe_fuses = read_pipe_fuses(ctx); uint32_t num_pipes = 0; diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_init.c b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_init.c index bdad72140cbc..181f2175ac95 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_init.c @@ -1,5 +1,5 @@ /* - * Copyright 2020 Advanced Micro Devices, Inc. + * Copyright 2016-2020 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -98,6 +98,10 @@ static const struct hw_sequencer_funcs dcn301_funcs = { .set_abm_immediate_disable = dcn21_set_abm_immediate_disable, .set_pipe = dcn21_set_pipe, .set_disp_pattern_generator = dcn30_set_disp_pattern_generator, + .get_dcc_en_bits = dcn10_get_dcc_en_bits, + .optimize_pwr_state = dcn21_optimize_pwr_state, + .exit_optimized_pwr_state = dcn21_exit_optimized_pwr_state, + .update_visual_confirm_color = dcn20_update_visual_confirm_color, }; static const struct hwseq_private_funcs dcn301_private_funcs = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c index 622a5bf9737f..9776d1737818 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c @@ -1,5 +1,5 @@ /* - * Copyright 2020 Advanced Micro Devices, Inc. + * Copyright 2019-2021 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -116,7 +116,7 @@ struct _vcs_dpi_ip_params_st dcn3_01_ip = { .dcc_supported = true, .writeback_interface_buffer_size_kbytes = 90, .writeback_line_buffer_buffer_size = 656640, - .max_line_buffer_lines = 32, + .max_line_buffer_lines = 12, .writeback_luma_buffer_size_kbytes = 12, // writeback_line_buffer_buffer_size = 656640 .writeback_chroma_buffer_size_kbytes = 8, .writeback_chroma_line_buffer_width_pixels = 4, @@ -843,10 +843,11 @@ static const struct dc_plane_cap plane_cap = { .fp16 = 16000 }, + /* 6:1 downscaling ratio: 1000/6 = 166.666 */ .max_downscale_factor = { - .argb8888 = 600, - .nv12 = 600, - .fp16 = 600 + .argb8888 = 167, + .nv12 = 167, + .fp16 = 167 }, 64, 64 @@ -1497,7 +1498,7 @@ static bool init_soc_bounding_box(struct dc *dc, DC_LOGGER_INIT(dc->ctx->logger); if (!is_soc_bounding_box_valid(dc)) { - DC_LOG_ERROR("%s: not valid soc bounding box/n", __func__); + DC_LOG_ERROR("%s: not valid soc bounding box\n", __func__); return false; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c index 0723e29fd42e..00cb6d11ed0d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c @@ -101,7 +101,7 @@ struct _vcs_dpi_ip_params_st dcn3_02_ip = { .dcc_supported = true, .writeback_interface_buffer_size_kbytes = 90, .writeback_line_buffer_buffer_size = 0, - .max_line_buffer_lines = 32, + .max_line_buffer_lines = 12, .writeback_luma_buffer_size_kbytes = 12, // writeback_line_buffer_buffer_size = 656640 .writeback_chroma_buffer_size_kbytes = 8, .writeback_chroma_line_buffer_width_pixels = 4, @@ -164,7 +164,7 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_02_soc = { .min_dcfclk = 500.0, /* TODO: set this to actual min DCFCLK */ .num_states = 1, - .sr_exit_time_us = 12, + .sr_exit_time_us = 15.5, .sr_enter_plus_exit_time_us = 20, .urgent_latency_us = 4.0, .urgent_latency_pixel_data_only_us = 4.0, @@ -284,10 +284,11 @@ static const struct dc_plane_cap plane_cap = { .nv12 = 16000, .fp16 = 16000 }, + /* 6:1 downscaling ratio: 1000/6 = 166.666 */ .max_downscale_factor = { - .argb8888 = 600, - .nv12 = 600, - .fp16 = 600 + .argb8888 = 167, + .nv12 = 167, + .fp16 = 167 }, 16, 16 @@ -1093,7 +1094,7 @@ static bool init_soc_bounding_box(struct dc *dc, struct resource_pool *pool) DC_LOGGER_INIT(dc->ctx->logger); if (!is_soc_bounding_box_valid(dc)) { - DC_LOG_ERROR("%s: not valid soc bounding box/n", __func__); + DC_LOG_ERROR("%s: not valid soc bounding box\n", __func__); return false; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn303/Makefile b/drivers/gpu/drm/amd/display/dc/dcn303/Makefile new file mode 100644 index 000000000000..6f7a1f2b49f0 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn303/Makefile @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: MIT +# +# Copyright (C) 2021 Advanced Micro Devices, Inc. All the rights reserved +# +# Authors: AMD +# +# Makefile for dcn303. + +DCN3_03 = dcn303_init.o dcn303_hwseq.o dcn303_resource.o + +ifdef CONFIG_X86 +CFLAGS_$(AMDDALPATH)/dc/dcn303/dcn303_resource.o := -msse +endif + +ifdef CONFIG_PPC64 +CFLAGS_$(AMDDALPATH)/dc/dcn303/dcn303_resource.o := -mhard-float -maltivec +endif + +ifdef CONFIG_CC_IS_GCC +ifeq ($(call cc-ifversion, -lt, 0701, y), y) +IS_OLD_GCC = 1 +endif +CFLAGS_$(AMDDALPATH)/dc/dcn303/dcn303_resource.o += -mhard-float +endif + +ifdef CONFIG_X86 +ifdef IS_OLD_GCC +# Stack alignment mismatch, proceed with caution. +# GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3 +# (8B stack alignment). +CFLAGS_$(AMDDALPATH)/dc/dcn303/dcn303_resource.o += -mpreferred-stack-boundary=4 +else +CFLAGS_$(AMDDALPATH)/dc/dcn303/dcn303_resource.o += -msse2 +endif +endif + +AMD_DAL_DCN3_03 = $(addprefix $(AMDDALPATH)/dc/dcn303/,$(DCN3_03)) + +AMD_DISPLAY_FILES += $(AMD_DAL_DCN3_03) diff --git a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_dccg.h b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_dccg.h new file mode 100644 index 000000000000..a79c54bbc899 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_dccg.h @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright (C) 2021 Advanced Micro Devices, Inc. + * + * Authors: AMD + */ + +#ifndef __DCN303_DCCG_H__ +#define __DCN303_DCCG_H__ + +#include "dcn30/dcn30_dccg.h" + + +#define DCCG_REG_LIST_DCN3_03() \ + SR(DPPCLK_DTO_CTRL),\ + DCCG_SRII(DTO_PARAM, DPPCLK, 0),\ + DCCG_SRII(DTO_PARAM, DPPCLK, 1),\ + SR(REFCLK_CNTL) + +#define DCCG_MASK_SH_LIST_DCN3_03(mask_sh) \ + DCCG_SFI(DPPCLK_DTO_CTRL, DTO_ENABLE, DPPCLK, 0, mask_sh),\ + DCCG_SFI(DPPCLK_DTO_CTRL, DTO_DB_EN, DPPCLK, 0, mask_sh),\ + DCCG_SFI(DPPCLK_DTO_CTRL, DTO_ENABLE, DPPCLK, 1, mask_sh),\ + DCCG_SFI(DPPCLK_DTO_CTRL, DTO_DB_EN, DPPCLK, 1, mask_sh),\ + DCCG_SF(DPPCLK0_DTO_PARAM, DPPCLK0_DTO_PHASE, mask_sh),\ + DCCG_SF(DPPCLK0_DTO_PARAM, DPPCLK0_DTO_MODULO, mask_sh),\ + DCCG_SF(REFCLK_CNTL, REFCLK_CLOCK_EN, mask_sh),\ + DCCG_SF(REFCLK_CNTL, REFCLK_SRC_SEL, mask_sh) + +#endif //__DCN303_DCCG_H__ diff --git a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_hwseq.c new file mode 100644 index 000000000000..dc33ec8b7bdb --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_hwseq.c @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright (C) 2021 Advanced Micro Devices, Inc. + * + * Authors: AMD + */ + +#include "dcn303_hwseq.h" + +#include "dce/dce_hwseq.h" + +#include "reg_helper.h" +#include "dc.h" + +#define DC_LOGGER_INIT(logger) + +#define CTX \ + hws->ctx +#define REG(reg)\ + hws->regs->reg + +#undef FN +#define FN(reg_name, field_name) \ + hws->shifts->field_name, hws->masks->field_name + + +void dcn303_dpp_pg_control(struct dce_hwseq *hws, unsigned int dpp_inst, bool power_on) +{ + /*DCN303 removes PG registers*/ +} + +void dcn303_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on) +{ + /*DCN303 removes PG registers*/ +} + +void dcn303_dsc_pg_control(struct dce_hwseq *hws, unsigned int dsc_inst, bool power_on) +{ + /*DCN303 removes PG registers*/ +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_hwseq.h b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_hwseq.h new file mode 100644 index 000000000000..fc6cab720b6d --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_hwseq.h @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright (C) 2021 Advanced Micro Devices, Inc. + * + * Authors: AMD + */ + +#ifndef __DC_HWSS_DCN303_H__ +#define __DC_HWSS_DCN303_H__ + +#include "hw_sequencer_private.h" + +void dcn303_dpp_pg_control(struct dce_hwseq *hws, unsigned int dpp_inst, bool power_on); +void dcn303_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on); +void dcn303_dsc_pg_control(struct dce_hwseq *hws, unsigned int dsc_inst, bool power_on); + +#endif /* __DC_HWSS_DCN303_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_init.c b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_init.c new file mode 100644 index 000000000000..86d4b303d02f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_init.c @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright (C) 2021 Advanced Micro Devices, Inc. + * + * Authors: AMD + */ + +#include "dcn303_hwseq.h" +#include "dcn30/dcn30_init.h" +#include "dc.h" + +void dcn303_hw_sequencer_construct(struct dc *dc) +{ + dcn30_hw_sequencer_construct(dc); + + dc->hwseq->funcs.dpp_pg_control = dcn303_dpp_pg_control; + dc->hwseq->funcs.hubp_pg_control = dcn303_hubp_pg_control; + dc->hwseq->funcs.dsc_pg_control = dcn303_dsc_pg_control; +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_init.h b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_init.h new file mode 100644 index 000000000000..66b1e3604f07 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_init.h @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright (C) 2021 Advanced Micro Devices, Inc. + * + * Authors: AMD + */ + +#ifndef __DC_DCN303_INIT_H__ +#define __DC_DCN303_INIT_H__ + +struct dc; + +void dcn303_hw_sequencer_construct(struct dc *dc); + +#endif /* __DC_DCN303_INIT_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c new file mode 100644 index 000000000000..aff0230c9193 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c @@ -0,0 +1,1675 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright (C) 2021 Advanced Micro Devices, Inc. + * + * Authors: AMD + */ + +#include "dcn303_init.h" +#include "dcn303_resource.h" +#include "dcn303_dccg.h" +#include "irq/dcn303/irq_service_dcn303.h" + +#include "dcn30/dcn30_dio_link_encoder.h" +#include "dcn30/dcn30_dio_stream_encoder.h" +#include "dcn30/dcn30_dpp.h" +#include "dcn30/dcn30_dwb.h" +#include "dcn30/dcn30_hubbub.h" +#include "dcn30/dcn30_hubp.h" +#include "dcn30/dcn30_mmhubbub.h" +#include "dcn30/dcn30_mpc.h" +#include "dcn30/dcn30_opp.h" +#include "dcn30/dcn30_optc.h" +#include "dcn30/dcn30_resource.h" + +#include "dcn20/dcn20_dsc.h" +#include "dcn20/dcn20_resource.h" + +#include "dcn10/dcn10_resource.h" + +#include "dc_link_ddc.h" + +#include "dce/dce_abm.h" +#include "dce/dce_audio.h" +#include "dce/dce_aux.h" +#include "dce/dce_clock_source.h" +#include "dce/dce_hwseq.h" +#include "dce/dce_i2c_hw.h" +#include "dce/dce_panel_cntl.h" +#include "dce/dmub_abm.h" +#include "dce/dmub_psr.h" +#include "clk_mgr.h" + +#include "hw_sequencer_private.h" +#include "reg_helper.h" +#include "resource.h" +#include "vm_helper.h" + +#include "sienna_cichlid_ip_offset.h" +#include "dcn/dcn_3_0_3_offset.h" +#include "dcn/dcn_3_0_3_sh_mask.h" +#include "dcn/dpcs_3_0_3_offset.h" +#include "dcn/dpcs_3_0_3_sh_mask.h" +#include "nbio/nbio_2_3_offset.h" + +#define DC_LOGGER_INIT(logger) + +struct _vcs_dpi_ip_params_st dcn3_03_ip = { + .use_min_dcfclk = 0, + .clamp_min_dcfclk = 0, + .odm_capable = 1, + .gpuvm_enable = 1, + .hostvm_enable = 0, + .gpuvm_max_page_table_levels = 4, + .hostvm_max_page_table_levels = 4, + .hostvm_cached_page_table_levels = 0, + .pte_group_size_bytes = 2048, + .num_dsc = 2, + .rob_buffer_size_kbytes = 184, + .det_buffer_size_kbytes = 184, + .dpte_buffer_size_in_pte_reqs_luma = 64, + .dpte_buffer_size_in_pte_reqs_chroma = 34, + .pde_proc_buffer_size_64k_reqs = 48, + .dpp_output_buffer_pixels = 2560, + .opp_output_buffer_lines = 1, + .pixel_chunk_size_kbytes = 8, + .pte_enable = 1, + .max_page_table_levels = 2, + .pte_chunk_size_kbytes = 2, // ? + .meta_chunk_size_kbytes = 2, + .writeback_chunk_size_kbytes = 8, + .line_buffer_size_bits = 789504, + .is_line_buffer_bpp_fixed = 0, // ? + .line_buffer_fixed_bpp = 0, // ? + .dcc_supported = true, + .writeback_interface_buffer_size_kbytes = 90, + .writeback_line_buffer_buffer_size = 0, + .max_line_buffer_lines = 12, + .writeback_luma_buffer_size_kbytes = 12, // writeback_line_buffer_buffer_size = 656640 + .writeback_chroma_buffer_size_kbytes = 8, + .writeback_chroma_line_buffer_width_pixels = 4, + .writeback_max_hscl_ratio = 1, + .writeback_max_vscl_ratio = 1, + .writeback_min_hscl_ratio = 1, + .writeback_min_vscl_ratio = 1, + .writeback_max_hscl_taps = 1, + .writeback_max_vscl_taps = 1, + .writeback_line_buffer_luma_buffer_size = 0, + .writeback_line_buffer_chroma_buffer_size = 14643, + .cursor_buffer_size = 8, + .cursor_chunk_size = 2, + .max_num_otg = 2, + .max_num_dpp = 2, + .max_num_wb = 1, + .max_dchub_pscl_bw_pix_per_clk = 4, + .max_pscl_lb_bw_pix_per_clk = 2, + .max_lb_vscl_bw_pix_per_clk = 4, + .max_vscl_hscl_bw_pix_per_clk = 4, + .max_hscl_ratio = 6, + .max_vscl_ratio = 6, + .hscl_mults = 4, + .vscl_mults = 4, + .max_hscl_taps = 8, + .max_vscl_taps = 8, + .dispclk_ramp_margin_percent = 1, + .underscan_factor = 1.11, + .min_vblank_lines = 32, + .dppclk_delay_subtotal = 46, + .dynamic_metadata_vm_enabled = true, + .dppclk_delay_scl_lb_only = 16, + .dppclk_delay_scl = 50, + .dppclk_delay_cnvc_formatter = 27, + .dppclk_delay_cnvc_cursor = 6, + .dispclk_delay_subtotal = 119, + .dcfclk_cstate_latency = 5.2, // SRExitTime + .max_inter_dcn_tile_repeaters = 8, + .max_num_hdmi_frl_outputs = 1, + .odm_combine_4to1_supported = false, + .xfc_supported = false, + .xfc_fill_bw_overhead_percent = 10.0, + .xfc_fill_constant_bytes = 0, + .gfx7_compat_tiling_supported = 0, + .number_of_cursors = 1, +}; + +struct _vcs_dpi_soc_bounding_box_st dcn3_03_soc = { + .clock_limits = { + { + .state = 0, + .dispclk_mhz = 1217.0, + .dppclk_mhz = 1217.0, + .phyclk_mhz = 810.0, + .phyclk_d18_mhz = 667.0, + .dscclk_mhz = 405.6, + }, + }, + + .min_dcfclk = 500.0, /* TODO: set this to actual min DCFCLK */ + .num_states = 1, + .sr_exit_time_us = 15.5, + .sr_enter_plus_exit_time_us = 20, + .urgent_latency_us = 4.0, + .urgent_latency_pixel_data_only_us = 4.0, + .urgent_latency_pixel_mixed_with_vm_data_us = 4.0, + .urgent_latency_vm_data_only_us = 4.0, + .urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096, + .urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096, + .urgent_out_of_order_return_per_channel_vm_only_bytes = 4096, + .pct_ideal_dram_sdp_bw_after_urgent_pixel_only = 80.0, + .pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm = 60.0, + .pct_ideal_dram_sdp_bw_after_urgent_vm_only = 40.0, + .max_avg_sdp_bw_use_normal_percent = 60.0, + .max_avg_dram_bw_use_normal_percent = 40.0, + .writeback_latency_us = 12.0, + .max_request_size_bytes = 256, + .fabric_datapath_to_dcn_data_return_bytes = 64, + .dcn_downspread_percent = 0.5, + .downspread_percent = 0.38, + .dram_page_open_time_ns = 50.0, + .dram_rw_turnaround_time_ns = 17.5, + .dram_return_buffer_per_channel_bytes = 8192, + .round_trip_ping_latency_dcfclk_cycles = 156, + .urgent_out_of_order_return_per_channel_bytes = 4096, + .channel_interleave_bytes = 256, + .num_banks = 8, + .gpuvm_min_page_size_bytes = 4096, + .hostvm_min_page_size_bytes = 4096, + .dram_clock_change_latency_us = 404, + .dummy_pstate_latency_us = 5, + .writeback_dram_clock_change_latency_us = 23.0, + .return_bus_width_bytes = 64, + .dispclk_dppclk_vco_speed_mhz = 3650, + .xfc_bus_transport_time_us = 20, // ? + .xfc_xbuf_latency_tolerance_us = 4, // ? + .use_urgent_burst_bw = 1, // ? + .do_urgent_latency_adjustment = true, + .urgent_latency_adjustment_fabric_clock_component_us = 1.0, + .urgent_latency_adjustment_fabric_clock_reference_mhz = 1000, +}; + +static const struct dc_debug_options debug_defaults_drv = { + .disable_dmcu = true, + .force_abm_enable = false, + .timing_trace = false, + .clock_trace = true, + .disable_pplib_clock_request = true, + .pipe_split_policy = MPC_SPLIT_DYNAMIC, + .force_single_disp_pipe_split = false, + .disable_dcc = DCC_ENABLE, + .vsr_support = true, + .performance_trace = false, + .max_downscale_src_width = 7680,/*upto 8K*/ + .disable_pplib_wm_range = false, + .scl_reset_length10 = true, + .sanity_checks = false, + .underflow_assert_delay_us = 0xFFFFFFFF, + .dwb_fi_phase = -1, // -1 = disable, + .dmub_command_table = true, + .disable_idle_power_optimizations = false, +}; + +static const struct dc_debug_options debug_defaults_diags = { + .disable_dmcu = true, + .force_abm_enable = false, + .timing_trace = true, + .clock_trace = true, + .disable_dpp_power_gate = true, + .disable_hubp_power_gate = true, + .disable_clock_gate = true, + .disable_pplib_clock_request = true, + .disable_pplib_wm_range = true, + .disable_stutter = false, + .scl_reset_length10 = true, + .dwb_fi_phase = -1, // -1 = disable + .dmub_command_table = true, + .enable_tri_buf = true, + .disable_psr = true, +}; + +enum dcn303_clk_src_array_id { + DCN303_CLK_SRC_PLL0, + DCN303_CLK_SRC_PLL1, + DCN303_CLK_SRC_TOTAL +}; + +static const struct resource_caps res_cap_dcn303 = { + .num_timing_generator = 2, + .num_opp = 2, + .num_video_plane = 2, + .num_audio = 2, + .num_stream_encoder = 2, + .num_dwb = 1, + .num_ddc = 2, + .num_vmid = 16, + .num_mpc_3dlut = 1, + .num_dsc = 2, +}; + +static const struct dc_plane_cap plane_cap = { + .type = DC_PLANE_TYPE_DCN_UNIVERSAL, + .blends_with_above = true, + .blends_with_below = true, + .per_pixel_alpha = true, + .pixel_format_support = { + .argb8888 = true, + .nv12 = true, + .fp16 = true, + .p010 = false, + .ayuv = false, + }, + .max_upscale_factor = { + .argb8888 = 16000, + .nv12 = 16000, + .fp16 = 16000 + }, + .max_downscale_factor = { + .argb8888 = 600, + .nv12 = 600, + .fp16 = 600 + }, + 16, + 16 +}; + +/* NBIO */ +#define NBIO_BASE_INNER(seg) \ + NBIO_BASE__INST0_SEG ## seg + +#define NBIO_BASE(seg) \ + NBIO_BASE_INNER(seg) + +#define NBIO_SR(reg_name)\ + .reg_name = NBIO_BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name + +/* DCN */ +#undef BASE_INNER +#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg + +#define BASE(seg) BASE_INNER(seg) + +#define SR(reg_name)\ + .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + mm ## reg_name + +#define SF(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define SRI(reg_name, block, id)\ + .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + mm ## block ## id ## _ ## reg_name + +#define SRI2(reg_name, block, id)\ + .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + mm ## reg_name + +#define SRII(reg_name, block, id)\ + .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +#define DCCG_SRII(reg_name, block, id)\ + .block ## _ ## reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +#define VUPDATE_SRII(reg_name, block, id)\ + .reg_name[id] = BASE(mm ## reg_name ## _ ## block ## id ## _BASE_IDX) + \ + mm ## reg_name ## _ ## block ## id + +#define SRII_DWB(reg_name, temp_name, block, id)\ + .reg_name[id] = BASE(mm ## block ## id ## _ ## temp_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## temp_name + +#define SRII_MPC_RMU(reg_name, block, id)\ + .RMU##_##reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + +static const struct dcn_hubbub_registers hubbub_reg = { + HUBBUB_REG_LIST_DCN30(0) +}; + +static const struct dcn_hubbub_shift hubbub_shift = { + HUBBUB_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn_hubbub_mask hubbub_mask = { + HUBBUB_MASK_SH_LIST_DCN30(_MASK) +}; + +#define vmid_regs(id)\ + [id] = { DCN20_VMID_REG_LIST(id) } + +static const struct dcn_vmid_registers vmid_regs[] = { + vmid_regs(0), + vmid_regs(1), + vmid_regs(2), + vmid_regs(3), + vmid_regs(4), + vmid_regs(5), + vmid_regs(6), + vmid_regs(7), + vmid_regs(8), + vmid_regs(9), + vmid_regs(10), + vmid_regs(11), + vmid_regs(12), + vmid_regs(13), + vmid_regs(14), + vmid_regs(15) +}; + +static const struct dcn20_vmid_shift vmid_shifts = { + DCN20_VMID_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn20_vmid_mask vmid_masks = { + DCN20_VMID_MASK_SH_LIST(_MASK) +}; + +static struct hubbub *dcn303_hubbub_create(struct dc_context *ctx) +{ + int i; + + struct dcn20_hubbub *hubbub3 = kzalloc(sizeof(struct dcn20_hubbub), GFP_KERNEL); + + if (!hubbub3) + return NULL; + + hubbub3_construct(hubbub3, ctx, &hubbub_reg, &hubbub_shift, &hubbub_mask); + + for (i = 0; i < res_cap_dcn303.num_vmid; i++) { + struct dcn20_vmid *vmid = &hubbub3->vmid[i]; + + vmid->ctx = ctx; + + vmid->regs = &vmid_regs[i]; + vmid->shifts = &vmid_shifts; + vmid->masks = &vmid_masks; + } + + return &hubbub3->base; +} + +#define vpg_regs(id)\ + [id] = { VPG_DCN3_REG_LIST(id) } + +static const struct dcn30_vpg_registers vpg_regs[] = { + vpg_regs(0), + vpg_regs(1), + vpg_regs(2) +}; + +static const struct dcn30_vpg_shift vpg_shift = { + DCN3_VPG_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn30_vpg_mask vpg_mask = { + DCN3_VPG_MASK_SH_LIST(_MASK) +}; + +static struct vpg *dcn303_vpg_create(struct dc_context *ctx, uint32_t inst) +{ + struct dcn30_vpg *vpg3 = kzalloc(sizeof(struct dcn30_vpg), GFP_KERNEL); + + if (!vpg3) + return NULL; + + vpg3_construct(vpg3, ctx, inst, &vpg_regs[inst], &vpg_shift, &vpg_mask); + + return &vpg3->base; +} + +#define afmt_regs(id)\ + [id] = { AFMT_DCN3_REG_LIST(id) } + +static const struct dcn30_afmt_registers afmt_regs[] = { + afmt_regs(0), + afmt_regs(1), + afmt_regs(2) +}; + +static const struct dcn30_afmt_shift afmt_shift = { + DCN3_AFMT_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn30_afmt_mask afmt_mask = { + DCN3_AFMT_MASK_SH_LIST(_MASK) +}; + +static struct afmt *dcn303_afmt_create(struct dc_context *ctx, uint32_t inst) +{ + struct dcn30_afmt *afmt3 = kzalloc(sizeof(struct dcn30_afmt), GFP_KERNEL); + + if (!afmt3) + return NULL; + + afmt3_construct(afmt3, ctx, inst, &afmt_regs[inst], &afmt_shift, &afmt_mask); + + return &afmt3->base; +} + +#define audio_regs(id)\ + [id] = { AUD_COMMON_REG_LIST(id) } + +static const struct dce_audio_registers audio_regs[] = { + audio_regs(0), + audio_regs(1), + audio_regs(2), + audio_regs(3), + audio_regs(4), + audio_regs(5), + audio_regs(6) +}; + +#define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\ + SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\ + AUD_COMMON_MASK_SH_LIST_BASE(mask_sh) + +static const struct dce_audio_shift audio_shift = { + DCE120_AUD_COMMON_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_audio_mask audio_mask = { + DCE120_AUD_COMMON_MASK_SH_LIST(_MASK) +}; + +static struct audio *dcn303_create_audio(struct dc_context *ctx, unsigned int inst) +{ + return dce_audio_create(ctx, inst, &audio_regs[inst], &audio_shift, &audio_mask); +} + +#define stream_enc_regs(id)\ + [id] = { SE_DCN3_REG_LIST(id) } + +static const struct dcn10_stream_enc_registers stream_enc_regs[] = { + stream_enc_regs(0), + stream_enc_regs(1) +}; + +static const struct dcn10_stream_encoder_shift se_shift = { + SE_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn10_stream_encoder_mask se_mask = { + SE_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +static struct stream_encoder *dcn303_stream_encoder_create(enum engine_id eng_id, struct dc_context *ctx) +{ + struct dcn10_stream_encoder *enc1; + struct vpg *vpg; + struct afmt *afmt; + int vpg_inst; + int afmt_inst; + + /* Mapping of VPG, AFMT, DME register blocks to DIO block instance */ + if (eng_id <= ENGINE_ID_DIGE) { + vpg_inst = eng_id; + afmt_inst = eng_id; + } else + return NULL; + + enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL); + vpg = dcn303_vpg_create(ctx, vpg_inst); + afmt = dcn303_afmt_create(ctx, afmt_inst); + + if (!enc1 || !vpg || !afmt) + return NULL; + + dcn30_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios, eng_id, vpg, afmt, &stream_enc_regs[eng_id], + &se_shift, &se_mask); + + return &enc1->base; +} + +#define clk_src_regs(index, pllid)\ + [index] = { CS_COMMON_REG_LIST_DCN3_03(index, pllid) } + +static const struct dce110_clk_src_regs clk_src_regs[] = { + clk_src_regs(0, A), + clk_src_regs(1, B) +}; + +static const struct dce110_clk_src_shift cs_shift = { + CS_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT) +}; + +static const struct dce110_clk_src_mask cs_mask = { + CS_COMMON_MASK_SH_LIST_DCN2_0(_MASK) +}; + +static struct clock_source *dcn303_clock_source_create(struct dc_context *ctx, struct dc_bios *bios, + enum clock_source_id id, const struct dce110_clk_src_regs *regs, bool dp_clk_src) +{ + struct dce110_clk_src *clk_src = kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL); + + if (!clk_src) + return NULL; + + if (dcn3_clk_src_construct(clk_src, ctx, bios, id, regs, &cs_shift, &cs_mask)) { + clk_src->base.dp_clk_src = dp_clk_src; + return &clk_src->base; + } + + BREAK_TO_DEBUGGER(); + return NULL; +} + +static const struct dce_hwseq_registers hwseq_reg = { + HWSEQ_DCN303_REG_LIST() +}; + +static const struct dce_hwseq_shift hwseq_shift = { + HWSEQ_DCN303_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_hwseq_mask hwseq_mask = { + HWSEQ_DCN303_MASK_SH_LIST(_MASK) +}; + +static struct dce_hwseq *dcn303_hwseq_create(struct dc_context *ctx) +{ + struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); + + if (hws) { + hws->ctx = ctx; + hws->regs = &hwseq_reg; + hws->shifts = &hwseq_shift; + hws->masks = &hwseq_mask; + } + return hws; +} + +#define hubp_regs(id)\ + [id] = { HUBP_REG_LIST_DCN30(id) } + +static const struct dcn_hubp2_registers hubp_regs[] = { + hubp_regs(0), + hubp_regs(1) +}; + +static const struct dcn_hubp2_shift hubp_shift = { + HUBP_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn_hubp2_mask hubp_mask = { + HUBP_MASK_SH_LIST_DCN30(_MASK) +}; + +static struct hubp *dcn303_hubp_create(struct dc_context *ctx, uint32_t inst) +{ + struct dcn20_hubp *hubp2 = kzalloc(sizeof(struct dcn20_hubp), GFP_KERNEL); + + if (!hubp2) + return NULL; + + if (hubp3_construct(hubp2, ctx, inst, &hubp_regs[inst], &hubp_shift, &hubp_mask)) + return &hubp2->base; + + BREAK_TO_DEBUGGER(); + kfree(hubp2); + return NULL; +} + +#define dpp_regs(id)\ + [id] = { DPP_REG_LIST_DCN30(id) } + +static const struct dcn3_dpp_registers dpp_regs[] = { + dpp_regs(0), + dpp_regs(1) +}; + +static const struct dcn3_dpp_shift tf_shift = { + DPP_REG_LIST_SH_MASK_DCN30(__SHIFT) +}; + +static const struct dcn3_dpp_mask tf_mask = { + DPP_REG_LIST_SH_MASK_DCN30(_MASK) +}; + +static struct dpp *dcn303_dpp_create(struct dc_context *ctx, uint32_t inst) +{ + struct dcn3_dpp *dpp = kzalloc(sizeof(struct dcn3_dpp), GFP_KERNEL); + + if (!dpp) + return NULL; + + if (dpp3_construct(dpp, ctx, inst, &dpp_regs[inst], &tf_shift, &tf_mask)) + return &dpp->base; + + BREAK_TO_DEBUGGER(); + kfree(dpp); + return NULL; +} + +#define opp_regs(id)\ + [id] = { OPP_REG_LIST_DCN30(id) } + +static const struct dcn20_opp_registers opp_regs[] = { + opp_regs(0), + opp_regs(1) +}; + +static const struct dcn20_opp_shift opp_shift = { + OPP_MASK_SH_LIST_DCN20(__SHIFT) +}; + +static const struct dcn20_opp_mask opp_mask = { + OPP_MASK_SH_LIST_DCN20(_MASK) +}; + +static struct output_pixel_processor *dcn303_opp_create(struct dc_context *ctx, uint32_t inst) +{ + struct dcn20_opp *opp = kzalloc(sizeof(struct dcn20_opp), GFP_KERNEL); + + if (!opp) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dcn20_opp_construct(opp, ctx, inst, &opp_regs[inst], &opp_shift, &opp_mask); + return &opp->base; +} + +#define optc_regs(id)\ + [id] = { OPTC_COMMON_REG_LIST_DCN3_0(id) } + +static const struct dcn_optc_registers optc_regs[] = { + optc_regs(0), + optc_regs(1) +}; + +static const struct dcn_optc_shift optc_shift = { + OPTC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn_optc_mask optc_mask = { + OPTC_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +static struct timing_generator *dcn303_timing_generator_create(struct dc_context *ctx, uint32_t instance) +{ + struct optc *tgn10 = kzalloc(sizeof(struct optc), GFP_KERNEL); + + if (!tgn10) + return NULL; + + tgn10->base.inst = instance; + tgn10->base.ctx = ctx; + + tgn10->tg_regs = &optc_regs[instance]; + tgn10->tg_shift = &optc_shift; + tgn10->tg_mask = &optc_mask; + + dcn30_timing_generator_init(tgn10); + + return &tgn10->base; +} + +static const struct dcn30_mpc_registers mpc_regs = { + MPC_REG_LIST_DCN3_0(0), + MPC_REG_LIST_DCN3_0(1), + MPC_OUT_MUX_REG_LIST_DCN3_0(0), + MPC_OUT_MUX_REG_LIST_DCN3_0(1), + MPC_RMU_GLOBAL_REG_LIST_DCN3AG, + MPC_RMU_REG_LIST_DCN3AG(0), + MPC_DWB_MUX_REG_LIST_DCN3_0(0), +}; + +static const struct dcn30_mpc_shift mpc_shift = { + MPC_COMMON_MASK_SH_LIST_DCN303(__SHIFT) +}; + +static const struct dcn30_mpc_mask mpc_mask = { + MPC_COMMON_MASK_SH_LIST_DCN303(_MASK) +}; + +static struct mpc *dcn303_mpc_create(struct dc_context *ctx, int num_mpcc, int num_rmu) +{ + struct dcn30_mpc *mpc30 = kzalloc(sizeof(struct dcn30_mpc), GFP_KERNEL); + + if (!mpc30) + return NULL; + + dcn30_mpc_construct(mpc30, ctx, &mpc_regs, &mpc_shift, &mpc_mask, num_mpcc, num_rmu); + + return &mpc30->base; +} + +#define dsc_regsDCN20(id)\ +[id] = { DSC_REG_LIST_DCN20(id) } + +static const struct dcn20_dsc_registers dsc_regs[] = { + dsc_regsDCN20(0), + dsc_regsDCN20(1) +}; + +static const struct dcn20_dsc_shift dsc_shift = { + DSC_REG_LIST_SH_MASK_DCN20(__SHIFT) +}; + +static const struct dcn20_dsc_mask dsc_mask = { + DSC_REG_LIST_SH_MASK_DCN20(_MASK) +}; + +static struct display_stream_compressor *dcn303_dsc_create(struct dc_context *ctx, uint32_t inst) +{ + struct dcn20_dsc *dsc = kzalloc(sizeof(struct dcn20_dsc), GFP_KERNEL); + + if (!dsc) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dsc2_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask); + return &dsc->base; +} + +#define dwbc_regs_dcn3(id)\ +[id] = { DWBC_COMMON_REG_LIST_DCN30(id) } + +static const struct dcn30_dwbc_registers dwbc30_regs[] = { + dwbc_regs_dcn3(0) +}; + +static const struct dcn30_dwbc_shift dwbc30_shift = { + DWBC_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn30_dwbc_mask dwbc30_mask = { + DWBC_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +static bool dcn303_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) +{ + int i; + uint32_t pipe_count = pool->res_cap->num_dwb; + + for (i = 0; i < pipe_count; i++) { + struct dcn30_dwbc *dwbc30 = kzalloc(sizeof(struct dcn30_dwbc), GFP_KERNEL); + + if (!dwbc30) { + dm_error("DC: failed to create dwbc30!\n"); + return false; + } + + dcn30_dwbc_construct(dwbc30, ctx, &dwbc30_regs[i], &dwbc30_shift, &dwbc30_mask, i); + + pool->dwbc[i] = &dwbc30->base; + } + return true; +} + +#define mcif_wb_regs_dcn3(id)\ +[id] = { MCIF_WB_COMMON_REG_LIST_DCN30(id) } + +static const struct dcn30_mmhubbub_registers mcif_wb30_regs[] = { + mcif_wb_regs_dcn3(0) +}; + +static const struct dcn30_mmhubbub_shift mcif_wb30_shift = { + MCIF_WB_COMMON_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dcn30_mmhubbub_mask mcif_wb30_mask = { + MCIF_WB_COMMON_MASK_SH_LIST_DCN30(_MASK) +}; + +static bool dcn303_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool) +{ + int i; + uint32_t pipe_count = pool->res_cap->num_dwb; + + for (i = 0; i < pipe_count; i++) { + struct dcn30_mmhubbub *mcif_wb30 = kzalloc(sizeof(struct dcn30_mmhubbub), GFP_KERNEL); + + if (!mcif_wb30) { + dm_error("DC: failed to create mcif_wb30!\n"); + return false; + } + + dcn30_mmhubbub_construct(mcif_wb30, ctx, &mcif_wb30_regs[i], &mcif_wb30_shift, &mcif_wb30_mask, i); + + pool->mcif_wb[i] = &mcif_wb30->base; + } + return true; +} + +#define aux_engine_regs(id)\ +[id] = {\ + AUX_COMMON_REG_LIST0(id), \ + .AUXN_IMPCAL = 0, \ + .AUXP_IMPCAL = 0, \ + .AUX_RESET_MASK = DP_AUX0_AUX_CONTROL__AUX_RESET_MASK, \ +} + +static const struct dce110_aux_registers aux_engine_regs[] = { + aux_engine_regs(0), + aux_engine_regs(1) +}; + +static const struct dce110_aux_registers_shift aux_shift = { + DCN_AUX_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce110_aux_registers_mask aux_mask = { + DCN_AUX_MASK_SH_LIST(_MASK) +}; + +static struct dce_aux *dcn303_aux_engine_create(struct dc_context *ctx, uint32_t inst) +{ + struct aux_engine_dce110 *aux_engine = kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL); + + if (!aux_engine) + return NULL; + + dce110_aux_engine_construct(aux_engine, ctx, inst, SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD, + &aux_engine_regs[inst], &aux_mask, &aux_shift, ctx->dc->caps.extended_aux_timeout_support); + + return &aux_engine->base; +} + +#define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST(id) } + +static const struct dce_i2c_registers i2c_hw_regs[] = { + i2c_inst_regs(1), + i2c_inst_regs(2) +}; + +static const struct dce_i2c_shift i2c_shifts = { + I2C_COMMON_MASK_SH_LIST_DCN2(__SHIFT) +}; + +static const struct dce_i2c_mask i2c_masks = { + I2C_COMMON_MASK_SH_LIST_DCN2(_MASK) +}; + +static struct dce_i2c_hw *dcn303_i2c_hw_create(struct dc_context *ctx, uint32_t inst) +{ + struct dce_i2c_hw *dce_i2c_hw = kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL); + + if (!dce_i2c_hw) + return NULL; + + dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst, &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks); + + return dce_i2c_hw; +} + +static const struct encoder_feature_support link_enc_feature = { + .max_hdmi_deep_color = COLOR_DEPTH_121212, + .max_hdmi_pixel_clock = 600000, + .hdmi_ycbcr420_supported = true, + .dp_ycbcr420_supported = true, + .fec_supported = true, + .flags.bits.IS_HBR2_CAPABLE = true, + .flags.bits.IS_HBR3_CAPABLE = true, + .flags.bits.IS_TPS3_CAPABLE = true, + .flags.bits.IS_TPS4_CAPABLE = true +}; + +#define link_regs(id, phyid)\ + [id] = {\ + LE_DCN3_REG_LIST(id), \ + UNIPHY_DCN2_REG_LIST(phyid), \ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id) \ + } + +static const struct dcn10_link_enc_registers link_enc_regs[] = { + link_regs(0, A), + link_regs(1, B) +}; + +static const struct dcn10_link_enc_shift le_shift = { + LINK_ENCODER_MASK_SH_LIST_DCN30(__SHIFT), + DPCS_DCN2_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn10_link_enc_mask le_mask = { + LINK_ENCODER_MASK_SH_LIST_DCN30(_MASK), + DPCS_DCN2_MASK_SH_LIST(_MASK) +}; + +#define aux_regs(id)\ + [id] = { DCN2_AUX_REG_LIST(id) } + +static const struct dcn10_link_enc_aux_registers link_enc_aux_regs[] = { + aux_regs(0), + aux_regs(1) +}; + +#define hpd_regs(id)\ + [id] = { HPD_REG_LIST(id) } + +static const struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[] = { + hpd_regs(0), + hpd_regs(1) +}; + +static struct link_encoder *dcn303_link_encoder_create(const struct encoder_init_data *enc_init_data) +{ + struct dcn20_link_encoder *enc20 = kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL); + + if (!enc20) + return NULL; + + dcn30_link_encoder_construct(enc20, enc_init_data, &link_enc_feature, + &link_enc_regs[enc_init_data->transmitter], &link_enc_aux_regs[enc_init_data->channel - 1], + &link_enc_hpd_regs[enc_init_data->hpd_source], &le_shift, &le_mask); + + return &enc20->enc10.base; +} + +static const struct dce_panel_cntl_registers panel_cntl_regs[] = { + { DCN_PANEL_CNTL_REG_LIST() } +}; + +static const struct dce_panel_cntl_shift panel_cntl_shift = { + DCE_PANEL_CNTL_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_panel_cntl_mask panel_cntl_mask = { + DCE_PANEL_CNTL_MASK_SH_LIST(_MASK) +}; + +static struct panel_cntl *dcn303_panel_cntl_create(const struct panel_cntl_init_data *init_data) +{ + struct dce_panel_cntl *panel_cntl = kzalloc(sizeof(struct dce_panel_cntl), GFP_KERNEL); + + if (!panel_cntl) + return NULL; + + dce_panel_cntl_construct(panel_cntl, init_data, &panel_cntl_regs[init_data->inst], + &panel_cntl_shift, &panel_cntl_mask); + + return &panel_cntl->base; +} + +static void read_dce_straps(struct dc_context *ctx, struct resource_straps *straps) +{ + generic_reg_get(ctx, mmDC_PINSTRAPS + BASE(mmDC_PINSTRAPS_BASE_IDX), + FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio); +} + +static const struct resource_create_funcs res_create_funcs = { + .read_dce_straps = read_dce_straps, + .create_audio = dcn303_create_audio, + .create_stream_encoder = dcn303_stream_encoder_create, + .create_hwseq = dcn303_hwseq_create, +}; + +static const struct resource_create_funcs res_create_maximus_funcs = { + .read_dce_straps = NULL, + .create_audio = NULL, + .create_stream_encoder = NULL, + .create_hwseq = dcn303_hwseq_create, +}; + +static bool is_soc_bounding_box_valid(struct dc *dc) +{ + uint32_t hw_internal_rev = dc->ctx->asic_id.hw_internal_rev; + + if (ASICREV_IS_BEIGE_GOBY_P(hw_internal_rev)) + return true; + + return false; +} + +static bool init_soc_bounding_box(struct dc *dc, struct resource_pool *pool) +{ + struct _vcs_dpi_soc_bounding_box_st *loaded_bb = &dcn3_03_soc; + struct _vcs_dpi_ip_params_st *loaded_ip = &dcn3_03_ip; + + DC_LOGGER_INIT(dc->ctx->logger); + + if (!is_soc_bounding_box_valid(dc)) { + DC_LOG_ERROR("%s: not valid soc bounding box/n", __func__); + return false; + } + + loaded_ip->max_num_otg = pool->pipe_count; + loaded_ip->max_num_dpp = pool->pipe_count; + loaded_ip->clamp_min_dcfclk = dc->config.clamp_min_dcfclk; + dcn20_patch_bounding_box(dc, loaded_bb); + return true; +} + +static void dcn303_resource_destruct(struct resource_pool *pool) +{ + unsigned int i; + + for (i = 0; i < pool->stream_enc_count; i++) { + if (pool->stream_enc[i] != NULL) { + if (pool->stream_enc[i]->vpg != NULL) { + kfree(DCN30_VPG_FROM_VPG(pool->stream_enc[i]->vpg)); + pool->stream_enc[i]->vpg = NULL; + } + if (pool->stream_enc[i]->afmt != NULL) { + kfree(DCN30_AFMT_FROM_AFMT(pool->stream_enc[i]->afmt)); + pool->stream_enc[i]->afmt = NULL; + } + kfree(DCN10STRENC_FROM_STRENC(pool->stream_enc[i])); + pool->stream_enc[i] = NULL; + } + } + + for (i = 0; i < pool->res_cap->num_dsc; i++) { + if (pool->dscs[i] != NULL) + dcn20_dsc_destroy(&pool->dscs[i]); + } + + if (pool->mpc != NULL) { + kfree(TO_DCN20_MPC(pool->mpc)); + pool->mpc = NULL; + } + + if (pool->hubbub != NULL) { + kfree(pool->hubbub); + pool->hubbub = NULL; + } + + for (i = 0; i < pool->pipe_count; i++) { + if (pool->dpps[i] != NULL) { + kfree(TO_DCN20_DPP(pool->dpps[i])); + pool->dpps[i] = NULL; + } + + if (pool->hubps[i] != NULL) { + kfree(TO_DCN20_HUBP(pool->hubps[i])); + pool->hubps[i] = NULL; + } + + if (pool->irqs != NULL) + dal_irq_service_destroy(&pool->irqs); + } + + for (i = 0; i < pool->res_cap->num_ddc; i++) { + if (pool->engines[i] != NULL) + dce110_engine_destroy(&pool->engines[i]); + if (pool->hw_i2cs[i] != NULL) { + kfree(pool->hw_i2cs[i]); + pool->hw_i2cs[i] = NULL; + } + if (pool->sw_i2cs[i] != NULL) { + kfree(pool->sw_i2cs[i]); + pool->sw_i2cs[i] = NULL; + } + } + + for (i = 0; i < pool->res_cap->num_opp; i++) { + if (pool->opps[i] != NULL) + pool->opps[i]->funcs->opp_destroy(&pool->opps[i]); + } + + for (i = 0; i < pool->res_cap->num_timing_generator; i++) { + if (pool->timing_generators[i] != NULL) { + kfree(DCN10TG_FROM_TG(pool->timing_generators[i])); + pool->timing_generators[i] = NULL; + } + } + + for (i = 0; i < pool->res_cap->num_dwb; i++) { + if (pool->dwbc[i] != NULL) { + kfree(TO_DCN30_DWBC(pool->dwbc[i])); + pool->dwbc[i] = NULL; + } + if (pool->mcif_wb[i] != NULL) { + kfree(TO_DCN30_MMHUBBUB(pool->mcif_wb[i])); + pool->mcif_wb[i] = NULL; + } + } + + for (i = 0; i < pool->audio_count; i++) { + if (pool->audios[i]) + dce_aud_destroy(&pool->audios[i]); + } + + for (i = 0; i < pool->clk_src_count; i++) { + if (pool->clock_sources[i] != NULL) + dcn20_clock_source_destroy(&pool->clock_sources[i]); + } + + if (pool->dp_clock_source != NULL) + dcn20_clock_source_destroy(&pool->dp_clock_source); + + for (i = 0; i < pool->res_cap->num_mpc_3dlut; i++) { + if (pool->mpc_lut[i] != NULL) { + dc_3dlut_func_release(pool->mpc_lut[i]); + pool->mpc_lut[i] = NULL; + } + if (pool->mpc_shaper[i] != NULL) { + dc_transfer_func_release(pool->mpc_shaper[i]); + pool->mpc_shaper[i] = NULL; + } + } + + for (i = 0; i < pool->pipe_count; i++) { + if (pool->multiple_abms[i] != NULL) + dce_abm_destroy(&pool->multiple_abms[i]); + } + + if (pool->psr != NULL) + dmub_psr_destroy(&pool->psr); + + if (pool->dccg != NULL) + dcn_dccg_destroy(&pool->dccg); + + if (pool->oem_device != NULL) + dal_ddc_service_destroy(&pool->oem_device); +} + +static void dcn303_destroy_resource_pool(struct resource_pool **pool) +{ + dcn303_resource_destruct(*pool); + kfree(*pool); + *pool = NULL; +} + +static void dcn303_get_optimal_dcfclk_fclk_for_uclk(unsigned int uclk_mts, + unsigned int *optimal_dcfclk, + unsigned int *optimal_fclk) +{ + double bw_from_dram, bw_from_dram1, bw_from_dram2; + + bw_from_dram1 = uclk_mts * dcn3_03_soc.num_chans * + dcn3_03_soc.dram_channel_width_bytes * (dcn3_03_soc.max_avg_dram_bw_use_normal_percent / 100); + bw_from_dram2 = uclk_mts * dcn3_03_soc.num_chans * + dcn3_03_soc.dram_channel_width_bytes * (dcn3_03_soc.max_avg_sdp_bw_use_normal_percent / 100); + + bw_from_dram = (bw_from_dram1 < bw_from_dram2) ? bw_from_dram1 : bw_from_dram2; + + if (optimal_fclk) + *optimal_fclk = bw_from_dram / + (dcn3_03_soc.fabric_datapath_to_dcn_data_return_bytes * + (dcn3_03_soc.max_avg_sdp_bw_use_normal_percent / 100)); + + if (optimal_dcfclk) + *optimal_dcfclk = bw_from_dram / + (dcn3_03_soc.return_bus_width_bytes * (dcn3_03_soc.max_avg_sdp_bw_use_normal_percent / 100)); +} + +void dcn303_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) +{ + unsigned int i, j; + unsigned int num_states = 0; + + unsigned int dcfclk_mhz[DC__VOLTAGE_STATES] = {0}; + unsigned int dram_speed_mts[DC__VOLTAGE_STATES] = {0}; + unsigned int optimal_uclk_for_dcfclk_sta_targets[DC__VOLTAGE_STATES] = {0}; + unsigned int optimal_dcfclk_for_uclk[DC__VOLTAGE_STATES] = {0}; + + unsigned int dcfclk_sta_targets[DC__VOLTAGE_STATES] = {694, 875, 1000, 1200}; + unsigned int num_dcfclk_sta_targets = 4; + unsigned int num_uclk_states; + + + if (dc->ctx->dc_bios->vram_info.num_chans) + dcn3_03_soc.num_chans = dc->ctx->dc_bios->vram_info.num_chans; + + if (dc->ctx->dc_bios->vram_info.dram_channel_width_bytes) + dcn3_03_soc.dram_channel_width_bytes = dc->ctx->dc_bios->vram_info.dram_channel_width_bytes; + + dcn3_03_soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0; + dc->dml.soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0; + + if (bw_params->clk_table.entries[0].memclk_mhz) { + int max_dcfclk_mhz = 0, max_dispclk_mhz = 0, max_dppclk_mhz = 0, max_phyclk_mhz = 0; + + for (i = 0; i < MAX_NUM_DPM_LVL; i++) { + if (bw_params->clk_table.entries[i].dcfclk_mhz > max_dcfclk_mhz) + max_dcfclk_mhz = bw_params->clk_table.entries[i].dcfclk_mhz; + if (bw_params->clk_table.entries[i].dispclk_mhz > max_dispclk_mhz) + max_dispclk_mhz = bw_params->clk_table.entries[i].dispclk_mhz; + if (bw_params->clk_table.entries[i].dppclk_mhz > max_dppclk_mhz) + max_dppclk_mhz = bw_params->clk_table.entries[i].dppclk_mhz; + if (bw_params->clk_table.entries[i].phyclk_mhz > max_phyclk_mhz) + max_phyclk_mhz = bw_params->clk_table.entries[i].phyclk_mhz; + } + if (!max_dcfclk_mhz) + max_dcfclk_mhz = dcn3_03_soc.clock_limits[0].dcfclk_mhz; + if (!max_dispclk_mhz) + max_dispclk_mhz = dcn3_03_soc.clock_limits[0].dispclk_mhz; + if (!max_dppclk_mhz) + max_dppclk_mhz = dcn3_03_soc.clock_limits[0].dppclk_mhz; + if (!max_phyclk_mhz) + max_phyclk_mhz = dcn3_03_soc.clock_limits[0].phyclk_mhz; + + if (max_dcfclk_mhz > dcfclk_sta_targets[num_dcfclk_sta_targets-1]) { + dcfclk_sta_targets[num_dcfclk_sta_targets] = max_dcfclk_mhz; + num_dcfclk_sta_targets++; + } else if (max_dcfclk_mhz < dcfclk_sta_targets[num_dcfclk_sta_targets-1]) { + for (i = 0; i < num_dcfclk_sta_targets; i++) { + if (dcfclk_sta_targets[i] > max_dcfclk_mhz) { + dcfclk_sta_targets[i] = max_dcfclk_mhz; + break; + } + } + /* Update size of array since we "removed" duplicates */ + num_dcfclk_sta_targets = i + 1; + } + + num_uclk_states = bw_params->clk_table.num_entries; + + /* Calculate optimal dcfclk for each uclk */ + for (i = 0; i < num_uclk_states; i++) { + dcn303_get_optimal_dcfclk_fclk_for_uclk(bw_params->clk_table.entries[i].memclk_mhz * 16, + &optimal_dcfclk_for_uclk[i], NULL); + if (optimal_dcfclk_for_uclk[i] < bw_params->clk_table.entries[0].dcfclk_mhz) + optimal_dcfclk_for_uclk[i] = bw_params->clk_table.entries[0].dcfclk_mhz; + } + + /* Calculate optimal uclk for each dcfclk sta target */ + for (i = 0; i < num_dcfclk_sta_targets; i++) { + for (j = 0; j < num_uclk_states; j++) { + if (dcfclk_sta_targets[i] < optimal_dcfclk_for_uclk[j]) { + optimal_uclk_for_dcfclk_sta_targets[i] = + bw_params->clk_table.entries[j].memclk_mhz * 16; + break; + } + } + } + + i = 0; + j = 0; + /* create the final dcfclk and uclk table */ + while (i < num_dcfclk_sta_targets && j < num_uclk_states && num_states < DC__VOLTAGE_STATES) { + if (dcfclk_sta_targets[i] < optimal_dcfclk_for_uclk[j] && i < num_dcfclk_sta_targets) { + dcfclk_mhz[num_states] = dcfclk_sta_targets[i]; + dram_speed_mts[num_states++] = optimal_uclk_for_dcfclk_sta_targets[i++]; + } else { + if (j < num_uclk_states && optimal_dcfclk_for_uclk[j] <= max_dcfclk_mhz) { + dcfclk_mhz[num_states] = optimal_dcfclk_for_uclk[j]; + dram_speed_mts[num_states++] = + bw_params->clk_table.entries[j++].memclk_mhz * 16; + } else { + j = num_uclk_states; + } + } + } + + while (i < num_dcfclk_sta_targets && num_states < DC__VOLTAGE_STATES) { + dcfclk_mhz[num_states] = dcfclk_sta_targets[i]; + dram_speed_mts[num_states++] = optimal_uclk_for_dcfclk_sta_targets[i++]; + } + + while (j < num_uclk_states && num_states < DC__VOLTAGE_STATES && + optimal_dcfclk_for_uclk[j] <= max_dcfclk_mhz) { + dcfclk_mhz[num_states] = optimal_dcfclk_for_uclk[j]; + dram_speed_mts[num_states++] = bw_params->clk_table.entries[j++].memclk_mhz * 16; + } + + dcn3_03_soc.num_states = num_states; + for (i = 0; i < dcn3_03_soc.num_states; i++) { + dcn3_03_soc.clock_limits[i].state = i; + dcn3_03_soc.clock_limits[i].dcfclk_mhz = dcfclk_mhz[i]; + dcn3_03_soc.clock_limits[i].fabricclk_mhz = dcfclk_mhz[i]; + dcn3_03_soc.clock_limits[i].dram_speed_mts = dram_speed_mts[i]; + + /* Fill all states with max values of all other clocks */ + dcn3_03_soc.clock_limits[i].dispclk_mhz = max_dispclk_mhz; + dcn3_03_soc.clock_limits[i].dppclk_mhz = max_dppclk_mhz; + dcn3_03_soc.clock_limits[i].phyclk_mhz = max_phyclk_mhz; + dcn3_03_soc.clock_limits[i].dtbclk_mhz = dcn3_03_soc.clock_limits[0].dtbclk_mhz; + /* These clocks cannot come from bw_params, always fill from dcn3_03_soc[1] */ + /* FCLK, PHYCLK_D18, SOCCLK, DSCCLK */ + dcn3_03_soc.clock_limits[i].phyclk_d18_mhz = dcn3_03_soc.clock_limits[0].phyclk_d18_mhz; + dcn3_03_soc.clock_limits[i].socclk_mhz = dcn3_03_soc.clock_limits[0].socclk_mhz; + dcn3_03_soc.clock_limits[i].dscclk_mhz = dcn3_03_soc.clock_limits[0].dscclk_mhz; + } + /* re-init DML with updated bb */ + dml_init_instance(&dc->dml, &dcn3_03_soc, &dcn3_03_ip, DML_PROJECT_DCN30); + if (dc->current_state) + dml_init_instance(&dc->current_state->bw_ctx.dml, &dcn3_03_soc, &dcn3_03_ip, DML_PROJECT_DCN30); + } +} + +static struct resource_funcs dcn303_res_pool_funcs = { + .destroy = dcn303_destroy_resource_pool, + .link_enc_create = dcn303_link_encoder_create, + .panel_cntl_create = dcn303_panel_cntl_create, + .validate_bandwidth = dcn30_validate_bandwidth, + .calculate_wm_and_dlg = dcn30_calculate_wm_and_dlg, + .update_soc_for_wm_a = dcn30_update_soc_for_wm_a, + .populate_dml_pipes = dcn30_populate_dml_pipes_from_context, + .acquire_idle_pipe_for_layer = dcn20_acquire_idle_pipe_for_layer, + .add_stream_to_ctx = dcn30_add_stream_to_ctx, + .add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource, + .remove_stream_from_ctx = dcn20_remove_stream_from_ctx, + .populate_dml_writeback_from_context = dcn30_populate_dml_writeback_from_context, + .set_mcif_arb_params = dcn30_set_mcif_arb_params, + .find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link, + .acquire_post_bldn_3dlut = dcn30_acquire_post_bldn_3dlut, + .release_post_bldn_3dlut = dcn30_release_post_bldn_3dlut, + .update_bw_bounding_box = dcn303_update_bw_bounding_box, + .patch_unknown_plane_state = dcn20_patch_unknown_plane_state, +}; + +static struct dc_cap_funcs cap_funcs = { + .get_dcc_compression_cap = dcn20_get_dcc_compression_cap +}; + +static const struct bios_registers bios_regs = { + NBIO_SR(BIOS_SCRATCH_3), + NBIO_SR(BIOS_SCRATCH_6) +}; + +static const struct dccg_registers dccg_regs = { + DCCG_REG_LIST_DCN3_03() +}; + +static const struct dccg_shift dccg_shift = { + DCCG_MASK_SH_LIST_DCN3_03(__SHIFT) +}; + +static const struct dccg_mask dccg_mask = { + DCCG_MASK_SH_LIST_DCN3_03(_MASK) +}; + +#define abm_regs(id)\ + [id] = { ABM_DCN301_REG_LIST(id) } + +static const struct dce_abm_registers abm_regs[] = { + abm_regs(0), + abm_regs(1) +}; + +static const struct dce_abm_shift abm_shift = { + ABM_MASK_SH_LIST_DCN30(__SHIFT) +}; + +static const struct dce_abm_mask abm_mask = { + ABM_MASK_SH_LIST_DCN30(_MASK) +}; + +static bool dcn303_resource_construct( + uint8_t num_virtual_links, + struct dc *dc, + struct resource_pool *pool) +{ + int i; + struct dc_context *ctx = dc->ctx; + struct irq_service_init_data init_data; + struct ddc_service_init_data ddc_init_data; + + ctx->dc_bios->regs = &bios_regs; + + pool->res_cap = &res_cap_dcn303; + + pool->funcs = &dcn303_res_pool_funcs; + + /************************************************* + * Resource + asic cap harcoding * + *************************************************/ + pool->underlay_pipe_index = NO_UNDERLAY_PIPE; + pool->pipe_count = pool->res_cap->num_timing_generator; + pool->mpcc_count = pool->res_cap->num_timing_generator; + dc->caps.max_downscale_ratio = 600; + dc->caps.i2c_speed_in_khz = 100; + dc->caps.i2c_speed_in_khz_hdcp = 5; /*1.4 w/a applied by derfault*/ + dc->caps.max_cursor_size = 256; + dc->caps.min_horizontal_blanking_period = 80; + dc->caps.dmdata_alloc_size = 2048; +#if defined(CONFIG_DRM_AMD_DC_DCN) + dc->caps.mall_size_per_mem_channel = 4; + /* total size = mall per channel * num channels * 1024 * 1024 */ + dc->caps.mall_size_total = dc->caps.mall_size_per_mem_channel * + dc->ctx->dc_bios->vram_info.num_chans * + 1024 * 1024; + dc->caps.cursor_cache_size = + dc->caps.max_cursor_size * dc->caps.max_cursor_size * 8; +#endif + dc->caps.max_slave_planes = 1; + dc->caps.post_blend_color_processing = true; + dc->caps.force_dp_tps4_for_cp2520 = true; + dc->caps.extended_aux_timeout_support = true; + dc->caps.dmcub_support = true; + + /* Color pipeline capabilities */ + dc->caps.color.dpp.dcn_arch = 1; + dc->caps.color.dpp.input_lut_shared = 0; + dc->caps.color.dpp.icsc = 1; + dc->caps.color.dpp.dgam_ram = 0; // must use gamma_corr + dc->caps.color.dpp.dgam_rom_caps.srgb = 1; + dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1; + dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 1; + dc->caps.color.dpp.dgam_rom_caps.pq = 1; + dc->caps.color.dpp.dgam_rom_caps.hlg = 1; + dc->caps.color.dpp.post_csc = 1; + dc->caps.color.dpp.gamma_corr = 1; + dc->caps.color.dpp.dgam_rom_for_yuv = 0; + + dc->caps.color.dpp.hw_3d_lut = 1; + dc->caps.color.dpp.ogam_ram = 1; + // no OGAM ROM on DCN3 + dc->caps.color.dpp.ogam_rom_caps.srgb = 0; + dc->caps.color.dpp.ogam_rom_caps.bt2020 = 0; + dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0; + dc->caps.color.dpp.ogam_rom_caps.pq = 0; + dc->caps.color.dpp.ogam_rom_caps.hlg = 0; + dc->caps.color.dpp.ocsc = 0; + + dc->caps.color.mpc.gamut_remap = 1; + dc->caps.color.mpc.num_3dluts = pool->res_cap->num_mpc_3dlut; //3 + dc->caps.color.mpc.ogam_ram = 1; + dc->caps.color.mpc.ogam_rom_caps.srgb = 0; + dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0; + dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0; + dc->caps.color.mpc.ogam_rom_caps.pq = 0; + dc->caps.color.mpc.ogam_rom_caps.hlg = 0; + dc->caps.color.mpc.ocsc = 1; + + if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) + dc->debug = debug_defaults_drv; + else + dc->debug = debug_defaults_diags; + + // Init the vm_helper + if (dc->vm_helper) + vm_helper_init(dc->vm_helper, 16); + + /************************************************* + * Create resources * + *************************************************/ + + /* Clock Sources for Pixel Clock*/ + pool->clock_sources[DCN303_CLK_SRC_PLL0] = + dcn303_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL0, + &clk_src_regs[0], false); + pool->clock_sources[DCN303_CLK_SRC_PLL1] = + dcn303_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_COMBO_PHY_PLL1, + &clk_src_regs[1], false); + + pool->clk_src_count = DCN303_CLK_SRC_TOTAL; + + /* todo: not reuse phy_pll registers */ + pool->dp_clock_source = + dcn303_clock_source_create(ctx, ctx->dc_bios, + CLOCK_SOURCE_ID_DP_DTO, + &clk_src_regs[0], true); + + for (i = 0; i < pool->clk_src_count; i++) { + if (pool->clock_sources[i] == NULL) { + dm_error("DC: failed to create clock sources!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + } + + /* DCCG */ + pool->dccg = dccg30_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask); + if (pool->dccg == NULL) { + dm_error("DC: failed to create dccg!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + + /* PP Lib and SMU interfaces */ + init_soc_bounding_box(dc, pool); + + /* DML */ + dml_init_instance(&dc->dml, &dcn3_03_soc, &dcn3_03_ip, DML_PROJECT_DCN30); + + /* IRQ */ + init_data.ctx = dc->ctx; + pool->irqs = dal_irq_service_dcn303_create(&init_data); + if (!pool->irqs) + goto create_fail; + + /* HUBBUB */ + pool->hubbub = dcn303_hubbub_create(ctx); + if (pool->hubbub == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create hubbub!\n"); + goto create_fail; + } + + /* HUBPs, DPPs, OPPs and TGs */ + for (i = 0; i < pool->pipe_count; i++) { + pool->hubps[i] = dcn303_hubp_create(ctx, i); + if (pool->hubps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create hubps!\n"); + goto create_fail; + } + + pool->dpps[i] = dcn303_dpp_create(ctx, i); + if (pool->dpps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create dpps!\n"); + goto create_fail; + } + } + + for (i = 0; i < pool->res_cap->num_opp; i++) { + pool->opps[i] = dcn303_opp_create(ctx, i); + if (pool->opps[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create output pixel processor!\n"); + goto create_fail; + } + } + + for (i = 0; i < pool->res_cap->num_timing_generator; i++) { + pool->timing_generators[i] = dcn303_timing_generator_create(ctx, i); + if (pool->timing_generators[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create tg!\n"); + goto create_fail; + } + } + pool->timing_generator_count = i; + + /* PSR */ + pool->psr = dmub_psr_create(ctx); + if (pool->psr == NULL) { + dm_error("DC: failed to create psr!\n"); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + + /* ABM */ + for (i = 0; i < pool->res_cap->num_timing_generator; i++) { + pool->multiple_abms[i] = dmub_abm_create(ctx, &abm_regs[i], &abm_shift, &abm_mask); + if (pool->multiple_abms[i] == NULL) { + dm_error("DC: failed to create abm for pipe %d!\n", i); + BREAK_TO_DEBUGGER(); + goto create_fail; + } + } + + /* MPC and DSC */ + pool->mpc = dcn303_mpc_create(ctx, pool->mpcc_count, pool->res_cap->num_mpc_3dlut); + if (pool->mpc == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create mpc!\n"); + goto create_fail; + } + + for (i = 0; i < pool->res_cap->num_dsc; i++) { + pool->dscs[i] = dcn303_dsc_create(ctx, i); + if (pool->dscs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create display stream compressor %d!\n", i); + goto create_fail; + } + } + + /* DWB and MMHUBBUB */ + if (!dcn303_dwbc_create(ctx, pool)) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create dwbc!\n"); + goto create_fail; + } + + if (!dcn303_mmhubbub_create(ctx, pool)) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create mcif_wb!\n"); + goto create_fail; + } + + /* AUX and I2C */ + for (i = 0; i < pool->res_cap->num_ddc; i++) { + pool->engines[i] = dcn303_aux_engine_create(ctx, i); + if (pool->engines[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC:failed to create aux engine!!\n"); + goto create_fail; + } + pool->hw_i2cs[i] = dcn303_i2c_hw_create(ctx, i); + if (pool->hw_i2cs[i] == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC:failed to create hw i2c!!\n"); + goto create_fail; + } + pool->sw_i2cs[i] = NULL; + } + + /* Audio, Stream Encoders including HPO and virtual, MPC 3D LUTs */ + if (!resource_construct(num_virtual_links, dc, pool, + (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) ? + &res_create_funcs : &res_create_maximus_funcs))) + goto create_fail; + + /* HW Sequencer and Plane caps */ + dcn303_hw_sequencer_construct(dc); + + dc->caps.max_planes = pool->pipe_count; + + for (i = 0; i < dc->caps.max_planes; ++i) + dc->caps.planes[i] = plane_cap; + + dc->cap_funcs = cap_funcs; + + if (dc->ctx->dc_bios->fw_info.oem_i2c_present) { + ddc_init_data.ctx = dc->ctx; + ddc_init_data.link = NULL; + ddc_init_data.id.id = dc->ctx->dc_bios->fw_info.oem_i2c_obj_id; + ddc_init_data.id.enum_id = 0; + ddc_init_data.id.type = OBJECT_TYPE_GENERIC; + pool->oem_device = dal_ddc_service_create(&ddc_init_data); + } else { + pool->oem_device = NULL; + } + + return true; + +create_fail: + + dcn303_resource_destruct(pool); + + return false; +} + +struct resource_pool *dcn303_create_resource_pool(const struct dc_init_data *init_data, struct dc *dc) +{ + struct resource_pool *pool = kzalloc(sizeof(struct resource_pool), GFP_KERNEL); + + if (!pool) + return NULL; + + if (dcn303_resource_construct(init_data->num_virtual_links, dc, pool)) + return pool; + + BREAK_TO_DEBUGGER(); + kfree(pool); + return NULL; +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.h b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.h new file mode 100644 index 000000000000..5b590c169763 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.h @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright (C) 2021 Advanced Micro Devices, Inc. + * + * Authors: AMD + */ + +#ifndef _DCN303_RESOURCE_H_ +#define _DCN303_RESOURCE_H_ + +#include "core_types.h" + +struct resource_pool *dcn303_create_resource_pool(const struct dc_init_data *init_data, struct dc *dc); + +void dcn303_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params); + +#endif /* _DCN303_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h index f41db27c44de..304d50d16d01 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_helpers.h +++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h @@ -34,6 +34,8 @@ #include "dc.h" struct dp_mst_stream_allocation_table; +struct aux_payload; +enum aux_return_code_type; /* * Allocate memory accessible by the GPU @@ -147,6 +149,8 @@ bool dm_helpers_dp_write_dsc_enable( bool dm_helpers_is_dp_sink_present( struct dc_link *link); +void dm_helpers_mst_enable_stream_features(const struct dc_stream_state *stream); + enum dc_edid_status dm_helpers_read_local_edid( struct dc_context *ctx, struct dc_link *link, @@ -156,6 +160,11 @@ void dm_set_dcn_clocks( struct dc_context *ctx, struct dc_clocks *clks); -bool dm_helpers_dmub_outbox0_interrupt_control(struct dc_context *ctx, bool enable); +bool dm_helpers_dmub_outbox_interrupt_control(struct dc_context *ctx, bool enable); +int dm_helper_dmub_aux_transfer_sync( + struct dc_context *ctx, + const struct dc_link *link, + struct aux_payload *payload, + enum aux_return_code_type *operation_result); #endif /* __DM_HELPERS__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c index 9729cf292e84..d3b5b6fedf04 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c @@ -2895,7 +2895,7 @@ static void dml20_DisplayPipeConfiguration(struct display_mode_lib *mode_lib) RoundedUpMaxSwathSizeBytesC = 0.0; if (RoundedUpMaxSwathSizeBytesY + RoundedUpMaxSwathSizeBytesC - <= mode_lib->vba.DETBufferSizeInKByte * 1024.0 / 2.0) { + <= mode_lib->vba.DETBufferSizeInKByte[0] * 1024.0 / 2.0) { mode_lib->vba.SwathHeightY[k] = MaximumSwathHeightY; mode_lib->vba.SwathHeightC[k] = MaximumSwathHeightC; } else { @@ -2904,17 +2904,17 @@ static void dml20_DisplayPipeConfiguration(struct display_mode_lib *mode_lib) } if (mode_lib->vba.SwathHeightC[k] == 0) { - mode_lib->vba.DETBufferSizeY[k] = mode_lib->vba.DETBufferSizeInKByte * 1024; + mode_lib->vba.DETBufferSizeY[k] = mode_lib->vba.DETBufferSizeInKByte[0] * 1024; mode_lib->vba.DETBufferSizeC[k] = 0; } else if (mode_lib->vba.SwathHeightY[k] <= mode_lib->vba.SwathHeightC[k]) { - mode_lib->vba.DETBufferSizeY[k] = mode_lib->vba.DETBufferSizeInKByte + mode_lib->vba.DETBufferSizeY[k] = mode_lib->vba.DETBufferSizeInKByte[0] * 1024.0 / 2; - mode_lib->vba.DETBufferSizeC[k] = mode_lib->vba.DETBufferSizeInKByte + mode_lib->vba.DETBufferSizeC[k] = mode_lib->vba.DETBufferSizeInKByte[0] * 1024.0 / 2; } else { - mode_lib->vba.DETBufferSizeY[k] = mode_lib->vba.DETBufferSizeInKByte + mode_lib->vba.DETBufferSizeY[k] = mode_lib->vba.DETBufferSizeInKByte[0] * 1024.0 * 2 / 3; - mode_lib->vba.DETBufferSizeC[k] = mode_lib->vba.DETBufferSizeInKByte + mode_lib->vba.DETBufferSizeC[k] = mode_lib->vba.DETBufferSizeInKByte[0] * 1024.0 / 3; } } @@ -3819,7 +3819,7 @@ void dml20_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l mode_lib->vba.MaximumSwathWidthInDETBuffer = dml_min( mode_lib->vba.MaximumSwathWidthSupport, - mode_lib->vba.DETBufferSizeInKByte * 1024.0 / 2.0 + mode_lib->vba.DETBufferSizeInKByte[0] * 1024.0 / 2.0 / (locals->BytePerPixelInDETY[k] * locals->MinSwathHeightY[k] + locals->BytePerPixelInDETC[k] @@ -4322,7 +4322,7 @@ void dml20_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l locals->RoundedUpMaxSwathSizeBytesC = 0; } - if (locals->RoundedUpMaxSwathSizeBytesY + locals->RoundedUpMaxSwathSizeBytesC <= locals->DETBufferSizeInKByte * 1024 / 2) { + if (locals->RoundedUpMaxSwathSizeBytesY + locals->RoundedUpMaxSwathSizeBytesC <= locals->DETBufferSizeInKByte[0] * 1024 / 2) { locals->SwathHeightYPerState[i][j][k] = locals->MaxSwathHeightY[k]; locals->SwathHeightCPerState[i][j][k] = locals->MaxSwathHeightC[k]; } else { @@ -4331,15 +4331,15 @@ void dml20_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l } if (locals->BytePerPixelInDETC[k] == 0) { - locals->LinesInDETLuma = locals->DETBufferSizeInKByte * 1024 / locals->BytePerPixelInDETY[k] / locals->SwathWidthYPerState[i][j][k]; + locals->LinesInDETLuma = locals->DETBufferSizeInKByte[0] * 1024 / locals->BytePerPixelInDETY[k] / locals->SwathWidthYPerState[i][j][k]; locals->LinesInDETChroma = 0; } else if (locals->SwathHeightYPerState[i][j][k] <= locals->SwathHeightCPerState[i][j][k]) { - locals->LinesInDETLuma = locals->DETBufferSizeInKByte * 1024 / 2 / locals->BytePerPixelInDETY[k] / + locals->LinesInDETLuma = locals->DETBufferSizeInKByte[0] * 1024 / 2 / locals->BytePerPixelInDETY[k] / locals->SwathWidthYPerState[i][j][k]; - locals->LinesInDETChroma = locals->DETBufferSizeInKByte * 1024 / 2 / locals->BytePerPixelInDETC[k] / (locals->SwathWidthYPerState[i][j][k] / 2); + locals->LinesInDETChroma = locals->DETBufferSizeInKByte[0] * 1024 / 2 / locals->BytePerPixelInDETC[k] / (locals->SwathWidthYPerState[i][j][k] / 2); } else { - locals->LinesInDETLuma = locals->DETBufferSizeInKByte * 1024 * 2 / 3 / locals->BytePerPixelInDETY[k] / locals->SwathWidthYPerState[i][j][k]; - locals->LinesInDETChroma = locals->DETBufferSizeInKByte * 1024 / 3 / locals->BytePerPixelInDETY[k] / (locals->SwathWidthYPerState[i][j][k] / 2); + locals->LinesInDETLuma = locals->DETBufferSizeInKByte[0] * 1024 * 2 / 3 / locals->BytePerPixelInDETY[k] / locals->SwathWidthYPerState[i][j][k]; + locals->LinesInDETChroma = locals->DETBufferSizeInKByte[0] * 1024 / 3 / locals->BytePerPixelInDETY[k] / (locals->SwathWidthYPerState[i][j][k] / 2); } locals->EffectiveLBLatencyHidingSourceLinesLuma = dml_min(locals->MaxLineBufferLines, diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c index 51098c2c9854..fbed5304692d 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c @@ -2968,7 +2968,7 @@ static void dml20v2_DisplayPipeConfiguration(struct display_mode_lib *mode_lib) RoundedUpMaxSwathSizeBytesC = 0.0; if (RoundedUpMaxSwathSizeBytesY + RoundedUpMaxSwathSizeBytesC - <= mode_lib->vba.DETBufferSizeInKByte * 1024.0 / 2.0) { + <= mode_lib->vba.DETBufferSizeInKByte[0] * 1024.0 / 2.0) { mode_lib->vba.SwathHeightY[k] = MaximumSwathHeightY; mode_lib->vba.SwathHeightC[k] = MaximumSwathHeightC; } else { @@ -2977,17 +2977,17 @@ static void dml20v2_DisplayPipeConfiguration(struct display_mode_lib *mode_lib) } if (mode_lib->vba.SwathHeightC[k] == 0) { - mode_lib->vba.DETBufferSizeY[k] = mode_lib->vba.DETBufferSizeInKByte * 1024; + mode_lib->vba.DETBufferSizeY[k] = mode_lib->vba.DETBufferSizeInKByte[0] * 1024; mode_lib->vba.DETBufferSizeC[k] = 0; } else if (mode_lib->vba.SwathHeightY[k] <= mode_lib->vba.SwathHeightC[k]) { - mode_lib->vba.DETBufferSizeY[k] = mode_lib->vba.DETBufferSizeInKByte + mode_lib->vba.DETBufferSizeY[k] = mode_lib->vba.DETBufferSizeInKByte[0] * 1024.0 / 2; - mode_lib->vba.DETBufferSizeC[k] = mode_lib->vba.DETBufferSizeInKByte + mode_lib->vba.DETBufferSizeC[k] = mode_lib->vba.DETBufferSizeInKByte[0] * 1024.0 / 2; } else { - mode_lib->vba.DETBufferSizeY[k] = mode_lib->vba.DETBufferSizeInKByte + mode_lib->vba.DETBufferSizeY[k] = mode_lib->vba.DETBufferSizeInKByte[0] * 1024.0 * 2 / 3; - mode_lib->vba.DETBufferSizeC[k] = mode_lib->vba.DETBufferSizeInKByte + mode_lib->vba.DETBufferSizeC[k] = mode_lib->vba.DETBufferSizeInKByte[0] * 1024.0 / 3; } } @@ -3926,7 +3926,7 @@ void dml20v2_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode mode_lib->vba.MaximumSwathWidthInDETBuffer = dml_min( mode_lib->vba.MaximumSwathWidthSupport, - mode_lib->vba.DETBufferSizeInKByte * 1024.0 / 2.0 + mode_lib->vba.DETBufferSizeInKByte[0] * 1024.0 / 2.0 / (locals->BytePerPixelInDETY[k] * locals->MinSwathHeightY[k] + locals->BytePerPixelInDETC[k] @@ -4443,7 +4443,7 @@ void dml20v2_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode locals->RoundedUpMaxSwathSizeBytesC = 0; } - if (locals->RoundedUpMaxSwathSizeBytesY + locals->RoundedUpMaxSwathSizeBytesC <= locals->DETBufferSizeInKByte * 1024 / 2) { + if (locals->RoundedUpMaxSwathSizeBytesY + locals->RoundedUpMaxSwathSizeBytesC <= locals->DETBufferSizeInKByte[0] * 1024 / 2) { locals->SwathHeightYPerState[i][j][k] = locals->MaxSwathHeightY[k]; locals->SwathHeightCPerState[i][j][k] = locals->MaxSwathHeightC[k]; } else { @@ -4452,15 +4452,15 @@ void dml20v2_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode } if (locals->BytePerPixelInDETC[k] == 0) { - locals->LinesInDETLuma = locals->DETBufferSizeInKByte * 1024 / locals->BytePerPixelInDETY[k] / locals->SwathWidthYPerState[i][j][k]; + locals->LinesInDETLuma = locals->DETBufferSizeInKByte[0] * 1024 / locals->BytePerPixelInDETY[k] / locals->SwathWidthYPerState[i][j][k]; locals->LinesInDETChroma = 0; } else if (locals->SwathHeightYPerState[i][j][k] <= locals->SwathHeightCPerState[i][j][k]) { - locals->LinesInDETLuma = locals->DETBufferSizeInKByte * 1024 / 2 / locals->BytePerPixelInDETY[k] / + locals->LinesInDETLuma = locals->DETBufferSizeInKByte[0] * 1024 / 2 / locals->BytePerPixelInDETY[k] / locals->SwathWidthYPerState[i][j][k]; - locals->LinesInDETChroma = locals->DETBufferSizeInKByte * 1024 / 2 / locals->BytePerPixelInDETC[k] / (locals->SwathWidthYPerState[i][j][k] / 2); + locals->LinesInDETChroma = locals->DETBufferSizeInKByte[0] * 1024 / 2 / locals->BytePerPixelInDETC[k] / (locals->SwathWidthYPerState[i][j][k] / 2); } else { - locals->LinesInDETLuma = locals->DETBufferSizeInKByte * 1024 * 2 / 3 / locals->BytePerPixelInDETY[k] / locals->SwathWidthYPerState[i][j][k]; - locals->LinesInDETChroma = locals->DETBufferSizeInKByte * 1024 / 3 / locals->BytePerPixelInDETY[k] / (locals->SwathWidthYPerState[i][j][k] / 2); + locals->LinesInDETLuma = locals->DETBufferSizeInKByte[0] * 1024 * 2 / 3 / locals->BytePerPixelInDETY[k] / locals->SwathWidthYPerState[i][j][k]; + locals->LinesInDETChroma = locals->DETBufferSizeInKByte[0] * 1024 / 3 / locals->BytePerPixelInDETY[k] / (locals->SwathWidthYPerState[i][j][k] / 2); } locals->EffectiveLBLatencyHidingSourceLinesLuma = dml_min(locals->MaxLineBufferLines, diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c index 72423dc425dc..799bae229e67 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c @@ -293,13 +293,31 @@ static void handle_det_buf_split(struct display_mode_lib *mode_lib, if (surf_linear) { log2_swath_height_l = 0; log2_swath_height_c = 0; - } else if (!surf_vert) { - log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_height) - req128_l; - log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_height) - req128_c; } else { - log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_width) - req128_l; - log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_width) - req128_c; + unsigned int swath_height_l; + unsigned int swath_height_c; + + if (!surf_vert) { + swath_height_l = rq_param->misc.rq_l.blk256_height; + swath_height_c = rq_param->misc.rq_c.blk256_height; + } else { + swath_height_l = rq_param->misc.rq_l.blk256_width; + swath_height_c = rq_param->misc.rq_c.blk256_width; + } + + if (swath_height_l > 0) + log2_swath_height_l = dml_log2(swath_height_l); + + if (req128_l && log2_swath_height_l > 0) + log2_swath_height_l -= 1; + + if (swath_height_c > 0) + log2_swath_height_c = dml_log2(swath_height_c); + + if (req128_c && log2_swath_height_c > 0) + log2_swath_height_c -= 1; } + rq_param->dlg.rq_l.swath_height = 1 << log2_swath_height_l; rq_param->dlg.rq_c.swath_height = 1 << log2_swath_height_c; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c index 9c78446c3a9d..6a6d5970d1d5 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c @@ -293,13 +293,31 @@ static void handle_det_buf_split(struct display_mode_lib *mode_lib, if (surf_linear) { log2_swath_height_l = 0; log2_swath_height_c = 0; - } else if (!surf_vert) { - log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_height) - req128_l; - log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_height) - req128_c; } else { - log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_width) - req128_l; - log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_width) - req128_c; + unsigned int swath_height_l; + unsigned int swath_height_c; + + if (!surf_vert) { + swath_height_l = rq_param->misc.rq_l.blk256_height; + swath_height_c = rq_param->misc.rq_c.blk256_height; + } else { + swath_height_l = rq_param->misc.rq_l.blk256_width; + swath_height_c = rq_param->misc.rq_c.blk256_width; + } + + if (swath_height_l > 0) + log2_swath_height_l = dml_log2(swath_height_l); + + if (req128_l && log2_swath_height_l > 0) + log2_swath_height_l -= 1; + + if (swath_height_c > 0) + log2_swath_height_c = dml_log2(swath_height_c); + + if (req128_c && log2_swath_height_c > 0) + log2_swath_height_c -= 1; } + rq_param->dlg.rq_l.swath_height = 1 << log2_swath_height_l; rq_param->dlg.rq_c.swath_height = 1 << log2_swath_height_c; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c index 398210d1af34..c26e742e8137 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c @@ -148,7 +148,7 @@ static double CalculateDCCConfiguration( bool DCCProgrammingAssumesScanDirectionUnknown, unsigned int ViewportWidth, unsigned int ViewportHeight, - double DETBufferSize, + unsigned int DETBufferSize, unsigned int RequestHeight256Byte, unsigned int SwathHeight, enum dm_swizzle_mode TilingFormat, @@ -289,7 +289,7 @@ static void CalculateWatermarksAndDRAMSpeedChangeSupport( unsigned int MaxLineBufferLines, unsigned int LineBufferSize, unsigned int DPPOutputBufferPixels, - double DETBufferSizeInKByte, + unsigned int DETBufferSizeInKByte, unsigned int WritebackInterfaceLumaBufferSize, unsigned int WritebackInterfaceChromaBufferSize, double DCFCLK, @@ -354,11 +354,11 @@ static void CalculateDCFCLKDeepSleep( double DPPCLK[], double *DCFCLKDeepSleep); static void CalculateDETBufferSize( - double DETBufferSizeInKByte, + unsigned int DETBufferSizeInKByte, unsigned int SwathHeightY, unsigned int SwathHeightC, - double *DETBufferSizeY, - double *DETBufferSizeC); + unsigned int *DETBufferSizeY, + unsigned int *DETBufferSizeC); static void CalculateUrgentBurstFactor( unsigned int DETBufferSizeInKByte, unsigned int SwathHeightY, @@ -1074,7 +1074,7 @@ static double CalculateDCCConfiguration( bool DCCProgrammingAssumesScanDirectionUnknown, unsigned int ViewportWidth, unsigned int ViewportHeight, - double DETBufferSize, + unsigned int DETBufferSize, unsigned int RequestHeight256Byte, unsigned int SwathHeight, enum dm_swizzle_mode TilingFormat, @@ -2246,7 +2246,7 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman } CalculateUrgentBurstFactor( - mode_lib->vba.DETBufferSizeInKByte, + mode_lib->vba.DETBufferSizeInKByte[0], mode_lib->vba.SwathHeightY[k], mode_lib->vba.SwathHeightC[k], locals->SwathWidthY[k], @@ -2415,7 +2415,7 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman mode_lib->vba.MaxLineBufferLines, mode_lib->vba.LineBufferSize, mode_lib->vba.DPPOutputBufferPixels, - mode_lib->vba.DETBufferSizeInKByte, + mode_lib->vba.DETBufferSizeInKByte[0], mode_lib->vba.WritebackInterfaceLumaBufferSize, mode_lib->vba.WritebackInterfaceChromaBufferSize, mode_lib->vba.DCFCLK, @@ -2588,7 +2588,7 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman false, // We should always know the direction DCCProgrammingAssumesScanDirectionUnknown, mode_lib->vba.ViewportWidth[k], mode_lib->vba.ViewportHeight[k], - mode_lib->vba.DETBufferSizeInKByte * 1024, + mode_lib->vba.DETBufferSizeInKByte[0] * 1024, locals->BlockHeight256BytesY[k], mode_lib->vba.SwathHeightY[k], mode_lib->vba.SurfaceTiling[k], @@ -2689,13 +2689,13 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman // Stutter Efficiency for (k = 0; k < mode_lib->vba.NumberOfActivePlanes; ++k) { CalculateDETBufferSize( - mode_lib->vba.DETBufferSizeInKByte, + mode_lib->vba.DETBufferSizeInKByte[0], mode_lib->vba.SwathHeightY[k], mode_lib->vba.SwathHeightC[k], &locals->DETBufferSizeY[k], &locals->DETBufferSizeC[k]); - locals->LinesInDETY[k] = locals->DETBufferSizeY[k] + locals->LinesInDETY[k] = (double)locals->DETBufferSizeY[k] / locals->BytePerPixelDETY[k] / locals->SwathWidthY[k]; locals->LinesInDETYRoundedDownToSwath[k] = dml_floor( locals->LinesInDETY[k], @@ -2984,7 +2984,7 @@ static void DisplayPipeConfiguration(struct display_mode_lib *mode_lib) RoundedUpMaxSwathSizeBytesC = 0.0; if (RoundedUpMaxSwathSizeBytesY + RoundedUpMaxSwathSizeBytesC - <= mode_lib->vba.DETBufferSizeInKByte * 1024.0 / 2.0) { + <= mode_lib->vba.DETBufferSizeInKByte[0] * 1024.0 / 2.0) { mode_lib->vba.SwathHeightY[k] = MaximumSwathHeightY; mode_lib->vba.SwathHeightC[k] = MaximumSwathHeightC; } else { @@ -2993,7 +2993,7 @@ static void DisplayPipeConfiguration(struct display_mode_lib *mode_lib) } CalculateDETBufferSize( - mode_lib->vba.DETBufferSizeInKByte, + mode_lib->vba.DETBufferSizeInKByte[0], mode_lib->vba.SwathHeightY[k], mode_lib->vba.SwathHeightC[k], &mode_lib->vba.DETBufferSizeY[k], @@ -3888,7 +3888,7 @@ void dml21_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l mode_lib->vba.MaximumSwathWidthInDETBuffer = dml_min( mode_lib->vba.MaximumSwathWidthSupport, - mode_lib->vba.DETBufferSizeInKByte * 1024.0 / 2.0 + mode_lib->vba.DETBufferSizeInKByte[0] * 1024.0 / 2.0 / (locals->BytePerPixelInDETY[k] * locals->MinSwathHeightY[k] + locals->BytePerPixelInDETC[k] @@ -4437,7 +4437,7 @@ void dml21_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l mode_lib->vba.RoundedUpMaxSwathSizeBytesC = 0.0; } if (mode_lib->vba.RoundedUpMaxSwathSizeBytesY + mode_lib->vba.RoundedUpMaxSwathSizeBytesC - <= mode_lib->vba.DETBufferSizeInKByte * 1024.0 / 2.0) { + <= mode_lib->vba.DETBufferSizeInKByte[0] * 1024.0 / 2.0) { locals->SwathHeightYThisState[k] = locals->MaxSwathHeightY[k]; locals->SwathHeightCThisState[k] = locals->MaxSwathHeightC[k]; } else { @@ -4801,7 +4801,7 @@ void dml21_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l } CalculateUrgentBurstFactor( - mode_lib->vba.DETBufferSizeInKByte, + mode_lib->vba.DETBufferSizeInKByte[0], locals->SwathHeightYThisState[k], locals->SwathHeightCThisState[k], locals->SwathWidthYThisState[k], @@ -4975,7 +4975,7 @@ void dml21_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l mode_lib->vba.MaxLineBufferLines, mode_lib->vba.LineBufferSize, mode_lib->vba.DPPOutputBufferPixels, - mode_lib->vba.DETBufferSizeInKByte, + mode_lib->vba.DETBufferSizeInKByte[0], mode_lib->vba.WritebackInterfaceLumaBufferSize, mode_lib->vba.WritebackInterfaceChromaBufferSize, mode_lib->vba.DCFCLKPerState[i], @@ -5230,7 +5230,7 @@ static void CalculateWatermarksAndDRAMSpeedChangeSupport( unsigned int MaxLineBufferLines, unsigned int LineBufferSize, unsigned int DPPOutputBufferPixels, - double DETBufferSizeInKByte, + unsigned int DETBufferSizeInKByte, unsigned int WritebackInterfaceLumaBufferSize, unsigned int WritebackInterfaceChromaBufferSize, double DCFCLK, @@ -5285,8 +5285,8 @@ static void CalculateWatermarksAndDRAMSpeedChangeSupport( double EffectiveLBLatencyHidingC; double DPPOutputBufferLinesY; double DPPOutputBufferLinesC; - double DETBufferSizeY; - double DETBufferSizeC; + unsigned int DETBufferSizeY; + unsigned int DETBufferSizeC; double LinesInDETY[DC__NUM_DPP__MAX]; double LinesInDETC; unsigned int LinesInDETYRoundedDownToSwath[DC__NUM_DPP__MAX]; @@ -5382,12 +5382,12 @@ static void CalculateWatermarksAndDRAMSpeedChangeSupport( &DETBufferSizeY, &DETBufferSizeC); - LinesInDETY[k] = DETBufferSizeY / BytePerPixelDETY[k] / SwathWidthY[k]; + LinesInDETY[k] = (double)DETBufferSizeY / BytePerPixelDETY[k] / SwathWidthY[k]; LinesInDETYRoundedDownToSwath[k] = dml_floor(LinesInDETY[k], SwathHeightY[k]); FullDETBufferingTimeY[k] = LinesInDETYRoundedDownToSwath[k] * (HTotal[k] / PixelClock[k]) / VRatio[k]; if (BytePerPixelDETC[k] > 0) { - LinesInDETC = DETBufferSizeC / BytePerPixelDETC[k] / (SwathWidthY[k] / 2.0); + LinesInDETC = (double)DETBufferSizeC / BytePerPixelDETC[k] / (SwathWidthY[k] / 2.0); LinesInDETCRoundedDownToSwath = dml_floor(LinesInDETC, SwathHeightC[k]); FullDETBufferingTimeC = LinesInDETCRoundedDownToSwath * (HTotal[k] / PixelClock[k]) / (VRatio[k] / 2); @@ -5574,11 +5574,11 @@ static void CalculateDCFCLKDeepSleep( } static void CalculateDETBufferSize( - double DETBufferSizeInKByte, + unsigned int DETBufferSizeInKByte, unsigned int SwathHeightY, unsigned int SwathHeightC, - double *DETBufferSizeY, - double *DETBufferSizeC) + unsigned int *DETBufferSizeY, + unsigned int *DETBufferSizeC) { if (SwathHeightC == 0) { *DETBufferSizeY = DETBufferSizeInKByte * 1024; @@ -5625,8 +5625,8 @@ static void CalculateUrgentBurstFactor( double DETBufferSizeInTimeLumaPre; double DETBufferSizeInTimeChroma; double DETBufferSizeInTimeChromaPre; - double DETBufferSizeY; - double DETBufferSizeC; + unsigned int DETBufferSizeY; + unsigned int DETBufferSizeC; *NotEnoughUrgentLatencyHiding = 0; *NotEnoughUrgentLatencyHidingPre = 0; @@ -5663,7 +5663,7 @@ static void CalculateUrgentBurstFactor( &DETBufferSizeY, &DETBufferSizeC); - LinesInDETLuma = DETBufferSizeY / BytePerPixelInDETY / SwathWidthY; + LinesInDETLuma = (double)DETBufferSizeY / BytePerPixelInDETY / SwathWidthY; DETBufferSizeInTimeLuma = dml_floor(LinesInDETLuma, SwathHeightY) * LineTime / VRatio; if (DETBufferSizeInTimeLuma - UrgentLatency <= 0) { *NotEnoughUrgentLatencyHiding = 1; @@ -5687,7 +5687,7 @@ static void CalculateUrgentBurstFactor( } if (BytePerPixelInDETC > 0) { - LinesInDETChroma = DETBufferSizeC / BytePerPixelInDETC / (SwathWidthY / 2); + LinesInDETChroma = (double)DETBufferSizeC / BytePerPixelInDETC / (SwathWidthY / 2); DETBufferSizeInTimeChroma = dml_floor(LinesInDETChroma, SwathHeightC) * LineTime / (VRatio / 2); if (DETBufferSizeInTimeChroma - UrgentLatency <= 0) { diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c index edd41d358291..dc1c81a6e377 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c @@ -277,13 +277,31 @@ static void handle_det_buf_split( if (surf_linear) { log2_swath_height_l = 0; log2_swath_height_c = 0; - } else if (!surf_vert) { - log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_height) - req128_l; - log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_height) - req128_c; } else { - log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_width) - req128_l; - log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_width) - req128_c; + unsigned int swath_height_l; + unsigned int swath_height_c; + + if (!surf_vert) { + swath_height_l = rq_param->misc.rq_l.blk256_height; + swath_height_c = rq_param->misc.rq_c.blk256_height; + } else { + swath_height_l = rq_param->misc.rq_l.blk256_width; + swath_height_c = rq_param->misc.rq_c.blk256_width; + } + + if (swath_height_l > 0) + log2_swath_height_l = dml_log2(swath_height_l); + + if (req128_l && log2_swath_height_l > 0) + log2_swath_height_l -= 1; + + if (swath_height_c > 0) + log2_swath_height_c = dml_log2(swath_height_c); + + if (req128_c && log2_swath_height_c > 0) + log2_swath_height_c -= 1; } + rq_param->dlg.rq_l.swath_height = 1 << log2_swath_height_l; rq_param->dlg.rq_c.swath_height = 1 << log2_swath_height_c; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c index cb3f70a71b51..ec56210b6180 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c @@ -299,7 +299,7 @@ static void CalculateWatermarksAndDRAMSpeedChangeSupport( unsigned int MaxLineBufferLines, unsigned int LineBufferSize, unsigned int DPPOutputBufferPixels, - double DETBufferSizeInKByte, + unsigned int DETBufferSizeInKByte, unsigned int WritebackInterfaceBufferSize, double DCFCLK, double ReturnBW, @@ -318,8 +318,8 @@ static void CalculateWatermarksAndDRAMSpeedChangeSupport( unsigned int DPPPerPlane[], bool DCCEnable[], double DPPCLK[], - double DETBufferSizeY[], - double DETBufferSizeC[], + unsigned int DETBufferSizeY[], + unsigned int DETBufferSizeC[], unsigned int SwathHeightY[], unsigned int SwathHeightC[], unsigned int LBBitPerPixel[], @@ -570,7 +570,7 @@ static void CalculateStutterEfficiency( double SRExitTime, bool SynchronizedVBlank, int DPPPerPlane[], - double DETBufferSizeY[], + unsigned int DETBufferSizeY[], int BytePerPixelY[], double BytePerPixelDETY[], double SwathWidthY[], @@ -603,7 +603,7 @@ static void CalculateStutterEfficiency( static void CalculateSwathAndDETConfiguration( bool ForceSingleDPP, int NumberOfActivePlanes, - long DETBufferSizeInKByte, + unsigned int DETBufferSizeInKByte, double MaximumSwathWidthLuma[], double MaximumSwathWidthChroma[], enum scan_direction_class SourceScan[], @@ -635,8 +635,8 @@ static void CalculateSwathAndDETConfiguration( double SwathWidthChroma[], int SwathHeightY[], int SwathHeightC[], - double DETBufferSizeY[], - double DETBufferSizeC[], + unsigned int DETBufferSizeY[], + unsigned int DETBufferSizeC[], bool ViewportSizeSupportPerPlane[], bool *ViewportSizeSupport); static void CalculateSwathWidth( @@ -2613,7 +2613,7 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman CalculateUrgentBurstFactor( v->swath_width_luma_ub[k], v->swath_width_chroma_ub[k], - v->DETBufferSizeInKByte, + v->DETBufferSizeInKByte[0], v->SwathHeightY[k], v->SwathHeightC[k], v->HTotal[k] / v->PixelClock[k], @@ -2635,7 +2635,7 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman CalculateUrgentBurstFactor( v->swath_width_luma_ub[k], v->swath_width_chroma_ub[k], - v->DETBufferSizeInKByte, + v->DETBufferSizeInKByte[0], v->SwathHeightY[k], v->SwathHeightC[k], v->HTotal[k] / v->PixelClock[k], @@ -2808,7 +2808,7 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman v->MaxLineBufferLines, v->LineBufferSize, v->DPPOutputBufferPixels, - v->DETBufferSizeInKByte, + v->DETBufferSizeInKByte[0], v->WritebackInterfaceBufferSize, v->DCFCLK, v->ReturnBW, @@ -3027,7 +3027,7 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman v->SurfaceWidthC[k], v->SurfaceHeightY[k], v->SurfaceHeightC[k], - v->DETBufferSizeInKByte * 1024, + v->DETBufferSizeInKByte[0] * 1024, v->BlockHeight256BytesY[k], v->BlockHeight256BytesC[k], v->SurfaceTiling[k], @@ -3177,7 +3177,7 @@ static void DisplayPipeConfiguration(struct display_mode_lib *mode_lib) CalculateSwathAndDETConfiguration( false, mode_lib->vba.NumberOfActivePlanes, - mode_lib->vba.DETBufferSizeInKByte, + mode_lib->vba.DETBufferSizeInKByte[0], dummy1, dummy2, mode_lib->vba.SourceScan, @@ -3911,7 +3911,7 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l CalculateSwathAndDETConfiguration( true, v->NumberOfActivePlanes, - v->DETBufferSizeInKByte, + v->DETBufferSizeInKByte[0], v->MaximumSwathWidthLuma, v->MaximumSwathWidthChroma, v->SourceScan, @@ -4399,7 +4399,7 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l CalculateSwathAndDETConfiguration( false, v->NumberOfActivePlanes, - v->DETBufferSizeInKByte, + v->DETBufferSizeInKByte[0], v->MaximumSwathWidthLuma, v->MaximumSwathWidthChroma, v->SourceScan, @@ -4622,7 +4622,7 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l CalculateUrgentBurstFactor( v->swath_width_luma_ub_this_state[k], v->swath_width_chroma_ub_this_state[k], - v->DETBufferSizeInKByte, + v->DETBufferSizeInKByte[0], v->SwathHeightYThisState[k], v->SwathHeightCThisState[k], v->HTotal[k] / v->PixelClock[k], @@ -5025,7 +5025,7 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l CalculateUrgentBurstFactor( v->swath_width_luma_ub_this_state[k], v->swath_width_chroma_ub_this_state[k], - v->DETBufferSizeInKByte, + v->DETBufferSizeInKByte[0], v->SwathHeightYThisState[k], v->SwathHeightCThisState[k], v->HTotal[k] / v->PixelClock[k], @@ -5197,7 +5197,7 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l v->MaxLineBufferLines, v->LineBufferSize, v->DPPOutputBufferPixels, - v->DETBufferSizeInKByte, + v->DETBufferSizeInKByte[0], v->WritebackInterfaceBufferSize, v->DCFCLKState[i][j], v->ReturnBWPerState[i][j], @@ -5369,7 +5369,7 @@ static void CalculateWatermarksAndDRAMSpeedChangeSupport( unsigned int MaxLineBufferLines, unsigned int LineBufferSize, unsigned int DPPOutputBufferPixels, - double DETBufferSizeInKByte, + unsigned int DETBufferSizeInKByte, unsigned int WritebackInterfaceBufferSize, double DCFCLK, double ReturnBW, @@ -5388,8 +5388,8 @@ static void CalculateWatermarksAndDRAMSpeedChangeSupport( unsigned int DPPPerPlane[], bool DCCEnable[], double DPPCLK[], - double DETBufferSizeY[], - double DETBufferSizeC[], + unsigned int DETBufferSizeY[], + unsigned int DETBufferSizeC[], unsigned int SwathHeightY[], unsigned int SwathHeightC[], unsigned int LBBitPerPixel[], @@ -6126,7 +6126,7 @@ static void CalculateStutterEfficiency( double SRExitTime, bool SynchronizedVBlank, int DPPPerPlane[], - double DETBufferSizeY[], + unsigned int DETBufferSizeY[], int BytePerPixelY[], double BytePerPixelDETY[], double SwathWidthY[], @@ -6273,7 +6273,7 @@ static void CalculateStutterEfficiency( static void CalculateSwathAndDETConfiguration( bool ForceSingleDPP, int NumberOfActivePlanes, - long DETBufferSizeInKByte, + unsigned int DETBufferSizeInKByte, double MaximumSwathWidthLuma[], double MaximumSwathWidthChroma[], enum scan_direction_class SourceScan[], @@ -6305,8 +6305,8 @@ static void CalculateSwathAndDETConfiguration( double SwathWidthChroma[], int SwathHeightY[], int SwathHeightC[], - double DETBufferSizeY[], - double DETBufferSizeC[], + unsigned int DETBufferSizeY[], + unsigned int DETBufferSizeC[], bool ViewportSizeSupportPerPlane[], bool *ViewportSizeSupport) { diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c index 0f14f205ebe5..04601a767a8f 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c @@ -237,13 +237,31 @@ static void handle_det_buf_split(struct display_mode_lib *mode_lib, if (surf_linear) { log2_swath_height_l = 0; log2_swath_height_c = 0; - } else if (!surf_vert) { - log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_height) - req128_l; - log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_height) - req128_c; } else { - log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_width) - req128_l; - log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_width) - req128_c; + unsigned int swath_height_l; + unsigned int swath_height_c; + + if (!surf_vert) { + swath_height_l = rq_param->misc.rq_l.blk256_height; + swath_height_c = rq_param->misc.rq_c.blk256_height; + } else { + swath_height_l = rq_param->misc.rq_l.blk256_width; + swath_height_c = rq_param->misc.rq_c.blk256_width; + } + + if (swath_height_l > 0) + log2_swath_height_l = dml_log2(swath_height_l); + + if (req128_l && log2_swath_height_l > 0) + log2_swath_height_l -= 1; + + if (swath_height_c > 0) + log2_swath_height_c = dml_log2(swath_height_c); + + if (req128_c && log2_swath_height_c > 0) + log2_swath_height_c -= 1; } + rq_param->dlg.rq_l.swath_height = 1 << log2_swath_height_l; rq_param->dlg.rq_c.swath_height = 1 << log2_swath_height_c; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c index 098d6433f7f3..1f7b6ddf3020 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c @@ -226,7 +226,7 @@ void dml_log_pipe_params( dml_print("DML PARAMS: PIPE [%d] DISPLAY OUTPUT PARAMS:\n", i); dml_print("DML PARAMS: output_type = %d\n", dout->output_type); dml_print("DML PARAMS: output_format = %d\n", dout->output_format); - dml_print("DML PARAMS: output_bpc = %d\n", dout->output_bpc); + dml_print("DML PARAMS: dsc_input_bpc = %d\n", dout->dsc_input_bpc); dml_print("DML PARAMS: output_bpp = %3.4f\n", dout->output_bpp); dml_print("DML PARAMS: dp_lanes = %d\n", dout->dp_lanes); dml_print("DML PARAMS: dsc_enable = %d\n", dout->dsc_enable); diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h index 0c5128187e08..2ece3690bfa3 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h @@ -164,7 +164,7 @@ struct _vcs_dpi_ip_params_st { double writeback_max_vscl_ratio; double writeback_min_hscl_ratio; double writeback_min_vscl_ratio; - double maximum_dsc_bits_per_component; + unsigned int maximum_dsc_bits_per_component; unsigned int writeback_max_hscl_taps; unsigned int writeback_max_vscl_taps; unsigned int writeback_line_buffer_luma_buffer_size; @@ -292,10 +292,10 @@ struct writeback_st { struct _vcs_dpi_display_output_params_st { int dp_lanes; double output_bpp; + unsigned int dsc_input_bpc; int dsc_enable; int wb_enable; int num_active_wb; - int output_bpc; int output_type; int is_virtual; int output_format; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c index 94036a9612cf..d764d784e279 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c @@ -299,7 +299,7 @@ static void fetch_ip_params(struct display_mode_lib *mode_lib) mode_lib->vba.MaxDCHUBToPSCLThroughput = ip->max_dchub_pscl_bw_pix_per_clk; mode_lib->vba.MaxPSCLToLBThroughput = ip->max_pscl_lb_bw_pix_per_clk; mode_lib->vba.ROBBufferSizeInKByte = ip->rob_buffer_size_kbytes; - mode_lib->vba.DETBufferSizeInKByte = ip->det_buffer_size_kbytes; + mode_lib->vba.DETBufferSizeInKByte[0] = ip->det_buffer_size_kbytes; mode_lib->vba.PixelChunkSizeInKByte = ip->pixel_chunk_size_kbytes; mode_lib->vba.MetaChunkSize = ip->meta_chunk_size_kbytes; @@ -471,7 +471,13 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib) mode_lib->vba.DSCEnable[mode_lib->vba.NumberOfActivePlanes] = dout->dsc_enable; mode_lib->vba.NumberOfDSCSlices[mode_lib->vba.NumberOfActivePlanes] = dout->dsc_slices; - mode_lib->vba.DSCInputBitPerComponent[mode_lib->vba.NumberOfActivePlanes] = dout->output_bpc; + if (!dout->dsc_input_bpc) { + mode_lib->vba.DSCInputBitPerComponent[mode_lib->vba.NumberOfActivePlanes] = + ip->maximum_dsc_bits_per_component; + } else { + mode_lib->vba.DSCInputBitPerComponent[mode_lib->vba.NumberOfActivePlanes] = + dout->dsc_input_bpc; + } mode_lib->vba.WritebackEnable[mode_lib->vba.NumberOfActivePlanes] = dout->wb_enable; mode_lib->vba.ActiveWritebacksPerPlane[mode_lib->vba.NumberOfActivePlanes] = dout->num_active_wb; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h index 025aa5bd8ea0..86db86b7153e 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h @@ -233,7 +233,7 @@ struct vba_vars_st { // IP Parameters // unsigned int ROBBufferSizeInKByte; - double DETBufferSizeInKByte; + unsigned int DETBufferSizeInKByte[DC__NUM_DPP__MAX]; double DETBufferSizeInTime; unsigned int DPPOutputBufferPixels; unsigned int OPPOutputBufferLines; @@ -351,8 +351,8 @@ struct vba_vars_st { // Intermediates/Informational bool ImmediateFlipSupport; - double DETBufferSizeY[DC__NUM_DPP__MAX]; - double DETBufferSizeC[DC__NUM_DPP__MAX]; + unsigned int DETBufferSizeY[DC__NUM_DPP__MAX]; + unsigned int DETBufferSizeC[DC__NUM_DPP__MAX]; unsigned int SwathHeightY[DC__NUM_DPP__MAX]; unsigned int SwathHeightC[DC__NUM_DPP__MAX]; unsigned int LBBitPerPixel[DC__NUM_DPP__MAX]; @@ -631,8 +631,8 @@ struct vba_vars_st { enum odm_combine_mode odm_combine_dummy[DC__NUM_DPP__MAX]; double dummy1[DC__NUM_DPP__MAX]; double dummy2[DC__NUM_DPP__MAX]; - double dummy3[DC__NUM_DPP__MAX]; - double dummy4[DC__NUM_DPP__MAX]; + unsigned int dummy3[DC__NUM_DPP__MAX]; + unsigned int dummy4[DC__NUM_DPP__MAX]; double dummy5; double dummy6; double dummy7[DC__NUM_DPP__MAX]; @@ -872,8 +872,8 @@ struct vba_vars_st { int PercentMarginOverMinimumRequiredDCFCLK; bool DynamicMetadataSupported[DC__VOLTAGE_STATES][2]; enum immediate_flip_requirement ImmediateFlipRequirement; - double DETBufferSizeYThisState[DC__NUM_DPP__MAX]; - double DETBufferSizeCThisState[DC__NUM_DPP__MAX]; + unsigned int DETBufferSizeYThisState[DC__NUM_DPP__MAX]; + unsigned int DETBufferSizeCThisState[DC__NUM_DPP__MAX]; bool NoUrgentLatencyHiding[DC__NUM_DPP__MAX]; bool NoUrgentLatencyHidingPre[DC__NUM_DPP__MAX]; int swath_width_luma_ub_this_state[DC__NUM_DPP__MAX]; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c index 4c3e9cc30167..414da64f5734 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c @@ -344,13 +344,31 @@ static void handle_det_buf_split( if (surf_linear) { log2_swath_height_l = 0; log2_swath_height_c = 0; - } else if (!surf_vert) { - log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_height) - req128_l; - log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_height) - req128_c; } else { - log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_width) - req128_l; - log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_width) - req128_c; + unsigned int swath_height_l; + unsigned int swath_height_c; + + if (!surf_vert) { + swath_height_l = rq_param->misc.rq_l.blk256_height; + swath_height_c = rq_param->misc.rq_c.blk256_height; + } else { + swath_height_l = rq_param->misc.rq_l.blk256_width; + swath_height_c = rq_param->misc.rq_c.blk256_width; + } + + if (swath_height_l > 0) + log2_swath_height_l = dml_log2(swath_height_l); + + if (req128_l && log2_swath_height_l > 0) + log2_swath_height_l -= 1; + + if (swath_height_c > 0) + log2_swath_height_c = dml_log2(swath_height_c); + + if (req128_c && log2_swath_height_c > 0) + log2_swath_height_c -= 1; } + rq_param->dlg.rq_l.swath_height = 1 << log2_swath_height_l; rq_param->dlg.rq_c.swath_height = 1 << log2_swath_height_c; diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c index be57088d185d..f403d8e84a8c 100644 --- a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c +++ b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c @@ -37,6 +37,8 @@ static uint32_t dsc_policy_max_target_bpp_limit = 16; /* default DSC policy enables DSC only when needed */ static bool dsc_policy_enable_dsc_when_not_needed; +static bool dsc_policy_disable_dsc_stream_overhead; + static bool dsc_buff_block_size_from_dpcd(int dpcd_buff_block_size, int *buff_block_size) { @@ -250,6 +252,7 @@ static bool intersect_dsc_caps( if (pixel_encoding == PIXEL_ENCODING_YCBCR422 || pixel_encoding == PIXEL_ENCODING_YCBCR420) dsc_common_caps->bpp_increment_div = min(dsc_common_caps->bpp_increment_div, (uint32_t)8); + dsc_common_caps->is_dp = dsc_sink_caps->is_dp; return true; } @@ -258,12 +261,63 @@ static inline uint32_t dsc_div_by_10_round_up(uint32_t value) return (value + 9) / 10; } +static struct fixed31_32 compute_dsc_max_bandwidth_overhead( + const struct dc_crtc_timing *timing, + const int num_slices_h, + const bool is_dp) +{ + struct fixed31_32 max_dsc_overhead; + struct fixed31_32 refresh_rate; + + if (dsc_policy_disable_dsc_stream_overhead || !is_dp) + return dc_fixpt_from_int(0); + + /* use target bpp that can take entire target bandwidth */ + refresh_rate = dc_fixpt_from_int(timing->pix_clk_100hz); + refresh_rate = dc_fixpt_div_int(refresh_rate, timing->h_total); + refresh_rate = dc_fixpt_div_int(refresh_rate, timing->v_total); + refresh_rate = dc_fixpt_mul_int(refresh_rate, 100); + + max_dsc_overhead = dc_fixpt_from_int(num_slices_h); + max_dsc_overhead = dc_fixpt_mul_int(max_dsc_overhead, timing->v_total); + max_dsc_overhead = dc_fixpt_mul_int(max_dsc_overhead, 256); + max_dsc_overhead = dc_fixpt_div_int(max_dsc_overhead, 1000); + max_dsc_overhead = dc_fixpt_mul(max_dsc_overhead, refresh_rate); + + return max_dsc_overhead; +} + +static uint32_t compute_bpp_x16_from_target_bandwidth( + const uint32_t bandwidth_in_kbps, + const struct dc_crtc_timing *timing, + const uint32_t num_slices_h, + const uint32_t bpp_increment_div, + const bool is_dp) +{ + struct fixed31_32 overhead_in_kbps; + struct fixed31_32 effective_bandwidth_in_kbps; + struct fixed31_32 bpp_x16; + + overhead_in_kbps = compute_dsc_max_bandwidth_overhead( + timing, num_slices_h, is_dp); + effective_bandwidth_in_kbps = dc_fixpt_from_int(bandwidth_in_kbps); + effective_bandwidth_in_kbps = dc_fixpt_sub(effective_bandwidth_in_kbps, + overhead_in_kbps); + bpp_x16 = dc_fixpt_mul_int(effective_bandwidth_in_kbps, 10); + bpp_x16 = dc_fixpt_div_int(bpp_x16, timing->pix_clk_100hz); + bpp_x16 = dc_fixpt_from_int(dc_fixpt_floor(dc_fixpt_mul_int(bpp_x16, bpp_increment_div))); + bpp_x16 = dc_fixpt_div_int(bpp_x16, bpp_increment_div); + bpp_x16 = dc_fixpt_mul_int(bpp_x16, 16); + return dc_fixpt_floor(bpp_x16); +} + /* Get DSC bandwidth range based on [min_bpp, max_bpp] target bitrate range, and timing's pixel clock * and uncompressed bandwidth. */ static void get_dsc_bandwidth_range( const uint32_t min_bpp_x16, const uint32_t max_bpp_x16, + const uint32_t num_slices_h, const struct dsc_enc_caps *dsc_caps, const struct dc_crtc_timing *timing, struct dc_dsc_bw_range *range) @@ -272,16 +326,21 @@ static void get_dsc_bandwidth_range( range->stream_kbps = dc_bandwidth_in_kbps_from_timing(timing); /* max dsc target bpp */ - range->max_kbps = dc_dsc_stream_bandwidth_in_kbps(timing->pix_clk_100hz, max_bpp_x16); + range->max_kbps = dc_dsc_stream_bandwidth_in_kbps(timing, + max_bpp_x16, num_slices_h, dsc_caps->is_dp); range->max_target_bpp_x16 = max_bpp_x16; if (range->max_kbps > range->stream_kbps) { /* max dsc target bpp is capped to native bandwidth */ range->max_kbps = range->stream_kbps; - range->max_target_bpp_x16 = calc_dsc_bpp_x16(range->stream_kbps, timing->pix_clk_100hz, dsc_caps->bpp_increment_div); + range->max_target_bpp_x16 = compute_bpp_x16_from_target_bandwidth( + range->max_kbps, timing, num_slices_h, + dsc_caps->bpp_increment_div, + dsc_caps->is_dp); } /* min dsc target bpp */ - range->min_kbps = dc_dsc_stream_bandwidth_in_kbps(timing->pix_clk_100hz, min_bpp_x16); + range->min_kbps = dc_dsc_stream_bandwidth_in_kbps(timing, + min_bpp_x16, num_slices_h, dsc_caps->is_dp); range->min_target_bpp_x16 = min_bpp_x16; if (range->min_kbps > range->max_kbps) { /* min dsc target bpp is capped to max dsc bandwidth*/ @@ -290,7 +349,6 @@ static void get_dsc_bandwidth_range( } } - /* Decides if DSC should be used and calculates target bpp if it should, applying DSC policy. * * Returns: @@ -303,6 +361,7 @@ static bool decide_dsc_target_bpp_x16( const struct dsc_enc_caps *dsc_common_caps, const int target_bandwidth_kbps, const struct dc_crtc_timing *timing, + const int num_slices_h, int *target_bpp_x16) { bool should_use_dsc = false; @@ -311,7 +370,7 @@ static bool decide_dsc_target_bpp_x16( memset(&range, 0, sizeof(range)); get_dsc_bandwidth_range(policy->min_target_bpp * 16, policy->max_target_bpp * 16, - dsc_common_caps, timing, &range); + num_slices_h, dsc_common_caps, timing, &range); if (!policy->enable_dsc_when_not_needed && target_bandwidth_kbps >= range.stream_kbps) { /* enough bandwidth without dsc */ *target_bpp_x16 = 0; @@ -327,7 +386,10 @@ static bool decide_dsc_target_bpp_x16( should_use_dsc = true; } else if (target_bandwidth_kbps >= range.min_kbps) { /* use target bpp that can take entire target bandwidth */ - *target_bpp_x16 = calc_dsc_bpp_x16(target_bandwidth_kbps, timing->pix_clk_100hz, dsc_common_caps->bpp_increment_div); + *target_bpp_x16 = compute_bpp_x16_from_target_bandwidth( + target_bandwidth_kbps, timing, num_slices_h, + dsc_common_caps->bpp_increment_div, + dsc_common_caps->is_dp); should_use_dsc = true; } else { /* not enough bandwidth to fulfill minimum requirement */ @@ -531,18 +593,6 @@ static bool setup_dsc_config( if (!is_dsc_possible) goto done; - if (target_bandwidth_kbps > 0) { - is_dsc_possible = decide_dsc_target_bpp_x16( - &policy, - &dsc_common_caps, - target_bandwidth_kbps, - timing, - &target_bpp); - dsc_cfg->bits_per_pixel = target_bpp; - } - if (!is_dsc_possible) - goto done; - sink_per_slice_throughput_mps = 0; // Validate available DSC settings against the mode timing @@ -690,12 +740,26 @@ static bool setup_dsc_config( dsc_cfg->num_slices_v = pic_height/slice_height; + if (target_bandwidth_kbps > 0) { + is_dsc_possible = decide_dsc_target_bpp_x16( + &policy, + &dsc_common_caps, + target_bandwidth_kbps, + timing, + num_slices_h, + &target_bpp); + dsc_cfg->bits_per_pixel = target_bpp; + } + if (!is_dsc_possible) + goto done; + // Final decission: can we do DSC or not? if (is_dsc_possible) { // Fill out the rest of DSC settings dsc_cfg->block_pred_enable = dsc_common_caps.is_block_pred_supported; dsc_cfg->linebuf_depth = dsc_common_caps.lb_bit_depth; dsc_cfg->version_minor = (dsc_common_caps.dsc_version & 0xf0) >> 4; + dsc_cfg->is_dp = dsc_sink_caps->is_dp; } done: @@ -806,6 +870,7 @@ bool dc_dsc_parse_dsc_dpcd(const struct dc *dc, const uint8_t *dpcd_dsc_basic_da dsc_sink_caps->branch_max_line_width = dpcd_dsc_branch_decoder_caps[DP_DSC_BRANCH_MAX_LINE_WIDTH - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0] * 320; ASSERT(dsc_sink_caps->branch_max_line_width == 0 || dsc_sink_caps->branch_max_line_width >= 5120); + dsc_sink_caps->is_dp = true; return true; } @@ -838,7 +903,8 @@ bool dc_dsc_compute_bandwidth_range( dsc_min_slice_height_override, max_bpp_x16, &config); if (is_dsc_possible) - get_dsc_bandwidth_range(min_bpp_x16, max_bpp_x16, &dsc_common_caps, timing, range); + get_dsc_bandwidth_range(min_bpp_x16, max_bpp_x16, + config.num_slices_h, &dsc_common_caps, timing, range); return is_dsc_possible; } @@ -864,13 +930,20 @@ bool dc_dsc_compute_config( return is_dsc_possible; } -uint32_t dc_dsc_stream_bandwidth_in_kbps(uint32_t pix_clk_100hz, uint32_t bpp_x16) +uint32_t dc_dsc_stream_bandwidth_in_kbps(const struct dc_crtc_timing *timing, + uint32_t bpp_x16, uint32_t num_slices_h, bool is_dp) { - struct fixed31_32 link_bw_kbps; - link_bw_kbps = dc_fixpt_from_int(pix_clk_100hz); - link_bw_kbps = dc_fixpt_div_int(link_bw_kbps, 160); - link_bw_kbps = dc_fixpt_mul_int(link_bw_kbps, bpp_x16); - return dc_fixpt_ceil(link_bw_kbps); + struct fixed31_32 overhead_in_kbps; + struct fixed31_32 bpp; + struct fixed31_32 actual_bandwidth_in_kbps; + + overhead_in_kbps = compute_dsc_max_bandwidth_overhead( + timing, num_slices_h, is_dp); + bpp = dc_fixpt_from_fraction(bpp_x16, 16); + actual_bandwidth_in_kbps = dc_fixpt_from_fraction(timing->pix_clk_100hz, 10); + actual_bandwidth_in_kbps = dc_fixpt_mul(actual_bandwidth_in_kbps, bpp); + actual_bandwidth_in_kbps = dc_fixpt_add(actual_bandwidth_in_kbps, overhead_in_kbps); + return dc_fixpt_ceil(actual_bandwidth_in_kbps); } void dc_dsc_get_policy_for_timing(const struct dc_crtc_timing *timing, uint32_t max_target_bpp_limit_override_x16, struct dc_dsc_policy *policy) @@ -954,3 +1027,8 @@ void dc_dsc_policy_set_enable_dsc_when_not_needed(bool enable) { dsc_policy_enable_dsc_when_not_needed = enable; } + +void dc_dsc_policy_set_disable_dsc_stream_overhead(bool disable) +{ + dsc_policy_disable_dsc_stream_overhead = disable; +} diff --git a/drivers/gpu/drm/amd/display/dc/dsc/rc_calc.c b/drivers/gpu/drm/amd/display/dc/dsc/rc_calc.c index c6a1cd80aeae..7b294f637881 100644 --- a/drivers/gpu/drm/amd/display/dc/dsc/rc_calc.c +++ b/drivers/gpu/drm/amd/display/dc/dsc/rc_calc.c @@ -284,26 +284,6 @@ static u32 _do_bytes_per_pixel_calc(int slice_width, u16 drm_bpp, return bytes_per_pixel; } -static u32 _do_calc_dsc_bpp_x16(u32 stream_bandwidth_kbps, u32 pix_clk_100hz, - u32 bpp_increment_div) -{ - u32 dsc_target_bpp_x16; - float f_dsc_target_bpp; - float f_stream_bandwidth_100bps; - // bpp_increment_div is actually precision - u32 precision = bpp_increment_div; - - f_stream_bandwidth_100bps = stream_bandwidth_kbps * 10.0f; - f_dsc_target_bpp = f_stream_bandwidth_100bps / pix_clk_100hz; - - // Round down to the nearest precision stop to bring it into DSC spec - // range - dsc_target_bpp_x16 = (u32)(f_dsc_target_bpp * precision); - dsc_target_bpp_x16 = (dsc_target_bpp_x16 * 16) / precision; - - return dsc_target_bpp_x16; -} - /** * calc_rc_params - reads the user's cmdline mode * @rc: DC internal DSC parameters @@ -367,26 +347,3 @@ u32 calc_dsc_bytes_per_pixel(const struct drm_dsc_config *pps) DC_FP_END(); return ret; } - -/** - * calc_dsc_bpp_x16 - retrieve the dsc bits per pixel - * @stream_bandwidth_kbps: - * @pix_clk_100hz: - * @bpp_increment_div: - * - * Calculate the total of bits per pixel for DSC configuration. - * - * @note This calculation requires float point operation, most of it executes - * under kernel_fpu_{begin,end}. - */ -u32 calc_dsc_bpp_x16(u32 stream_bandwidth_kbps, u32 pix_clk_100hz, - u32 bpp_increment_div) -{ - u32 dsc_bpp; - - DC_FP_START(); - dsc_bpp = _do_calc_dsc_bpp_x16(stream_bandwidth_kbps, pix_clk_100hz, - bpp_increment_div); - DC_FP_END(); - return dsc_bpp; -} diff --git a/drivers/gpu/drm/amd/display/dc/dsc/rc_calc.h b/drivers/gpu/drm/amd/display/dc/dsc/rc_calc.h index 8123827840c5..262f06afcbf9 100644 --- a/drivers/gpu/drm/amd/display/dc/dsc/rc_calc.h +++ b/drivers/gpu/drm/amd/display/dc/dsc/rc_calc.h @@ -79,8 +79,6 @@ typedef struct qp_entry qp_table[]; void calc_rc_params(struct rc_params *rc, const struct drm_dsc_config *pps); u32 calc_dsc_bytes_per_pixel(const struct drm_dsc_config *pps); -u32 calc_dsc_bpp_x16(u32 stream_bandwidth_kbps, u32 pix_clk_100hz, - u32 bpp_increment_div); #endif diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c index 92c65d2fa7d7..5aa714e831dd 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c @@ -111,6 +111,7 @@ bool dal_hw_factory_init( case DCN_VERSION_3_0: case DCN_VERSION_3_01: case DCN_VERSION_3_02: + case DCN_VERSION_3_03: dal_hw_factory_dcn30_init(factory); return true; #endif diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c index da9499c09a11..199a9dd0e0e3 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c @@ -106,6 +106,7 @@ bool dal_hw_translate_init( case DCN_VERSION_3_0: case DCN_VERSION_3_01: case DCN_VERSION_3_02: + case DCN_VERSION_3_03: dal_hw_translate_dcn30_init(translate); return true; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index eb1a19bf0d81..81b92f20d5b6 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -118,6 +118,27 @@ struct resource_funcs { display_e2e_pipe_params_st *pipes, bool fast_validate); + /* + * Algorithm for assigning available link encoders to links. + * + * Update link_enc_assignments table and link_enc_avail list accordingly in + * struct resource_context. + */ + void (*link_encs_assign)( + struct dc *dc, + struct dc_state *state, + struct dc_stream_state *streams[], + uint8_t stream_count); + /* + * Unassign a link encoder from a stream. + * + * Update link_enc_assignments table and link_enc_avail list accordingly in + * struct resource_context. + */ + void (*link_enc_unassign)( + struct dc_state *state, + struct dc_stream_state *stream); + enum dc_status (*validate_global)( struct dc *dc, struct dc_state *context); @@ -358,6 +379,12 @@ struct resource_context { uint8_t clock_source_ref_count[MAX_CLOCK_SOURCES]; uint8_t dp_clock_source_ref_count; bool is_dsc_acquired[MAX_PIPES]; + /* A table/array of encoder-to-link assignments. One entry per stream. + * Indexed by stream index in dc_state. + */ + struct link_enc_assignment link_enc_assignments[MAX_PIPES]; + /* List of available link encoders. Uses engine ID as encoder identifier. */ + enum engine_id link_enc_avail[MAX_DIG_LINK_ENCODERS]; #if defined(CONFIG_DRM_AMD_DC_DCN) bool is_mpc_3dlut_acquired[MAX_PIPES]; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h index b970a32177af..ffc3f2c63db8 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h @@ -52,6 +52,10 @@ bool dp_validate_mode_timing( struct dc_link *link, const struct dc_crtc_timing *timing); +bool decide_edp_link_settings(struct dc_link *link, + struct dc_link_settings *link_setting, + uint32_t req_bw); + void decide_link_settings( struct dc_stream_state *stream, struct dc_link_settings *link_setting); @@ -61,7 +65,8 @@ bool perform_link_training_with_retries( bool skip_video_pattern, int attempts, struct pipe_ctx *pipe_ctx, - enum signal_type signal); + enum signal_type signal, + bool do_fallback); bool is_mst_supported(struct dc_link *link); @@ -71,6 +76,10 @@ void detect_edp_sink_caps(struct dc_link *link); bool is_dp_active_dongle(const struct dc_link *link); +bool is_dp_branch_device(const struct dc_link *link); + +bool is_edp_ilr_optimization_required(struct dc_link *link, struct dc_crtc_timing *crtc_timing); + void dp_enable_mst_on_sink(struct dc_link *link, bool enable); enum dp_panel_mode dp_get_panel_mode(struct dc_link *link); @@ -86,5 +95,15 @@ bool dp_set_dsc_enable(struct pipe_ctx *pipe_ctx, bool enable); bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable); void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable); bool dp_update_dsc_config(struct pipe_ctx *pipe_ctx); +bool dp_set_dsc_on_rx(struct pipe_ctx *pipe_ctx, bool enable); + +/* Convert PHY repeater count read from DPCD uint8_t. */ +uint8_t dp_convert_to_count(uint8_t lttpr_repeater_count); + +/* Check DPCD training status registers to detect link loss. */ +enum link_training_result dp_check_link_loss_status( + struct dc_link *link, + const struct link_training_settings *link_training_setting); +enum dp_link_encoding dp_get_link_encoding_format(const struct dc_link_settings *link_settings); #endif /* __DC_LINK_DP_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h index 3a29f379d0c8..5dc8d02b40c3 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h @@ -262,14 +262,9 @@ struct clk_mgr_funcs { /* Get current memclk states from PMFW, update relevant structures */ void (*get_memclk_states_from_smu)(struct clk_mgr *clk_mgr); -}; - -struct dpm_clocks; -struct wartermarks; -struct smu_watermark_set { - struct watermarks *wm_set; - union large_integer mc_address; + /* Get SMU present */ + bool (*is_smu_present)(struct clk_mgr *clk_mgr); }; struct clk_mgr { @@ -283,7 +278,6 @@ struct clk_mgr { struct clk_state_registers_and_bypass boot_snapshot; struct clk_bw_params *bw_params; struct pp_smu_wm_range_sets ranges; - struct smu_watermark_set smu_wm_set; }; /* forward declarations */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h index ddbe4bb52724..00fc81431b43 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h @@ -32,6 +32,12 @@ struct dpp { const struct dpp_funcs *funcs; struct dc_context *ctx; + /** + * @inst: + * + * inst stands for "instance," and it is an id number that references a + * specific DPP. + */ int inst; struct dpp_caps *caps; struct pwl_params regamma_params; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dsc.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dsc.h index f520e13aee4c..f94135c6e3c2 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dsc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dsc.h @@ -88,6 +88,7 @@ struct dsc_enc_caps { int32_t max_total_throughput_mps; /* Maximum total throughput with all the slices combined */ int32_t max_slice_width; uint32_t bpp_increment_div; /* bpp increment divisor, e.g. if 16, it's 1/16th of a bit */ + bool is_dp; }; struct dsc_funcs { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h index 346dcd87dc10..80e1a32bc63d 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h @@ -29,6 +29,7 @@ #include "mem_input.h" #define OPP_ID_INVALID 0xf +#define MAX_TTU 0xffffff enum cursor_pitch { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h index 7f5acd8fb918..80bc99500645 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h @@ -187,4 +187,17 @@ struct link_encoder_funcs { struct link_encoder *enc); }; +/* + * Used to track assignments of links (display endpoints) to link encoders. + * + * Entry in link_enc_assignments table in struct resource_context. + * Entries only marked valid once encoder assigned to a link and invalidated once unassigned. + * Uses engine ID as identifier since PHY ID not relevant for USB4 DPIA endpoint. + */ +struct link_enc_assignment { + bool valid; + struct display_endpoint_id ep_id; + enum engine_id eng_id; +}; + #endif /* LINK_ENCODER_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h index 75c77ad9cbfe..640bb432bd6a 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h @@ -363,6 +363,9 @@ struct mpc_funcs { struct mpc *mpc, int opp_id); + void (*set_bg_color)(struct mpc *mpc, + struct tg_color *bg_color, + int mpcc_id); }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 2fedfcac6705..43284d410687 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -118,8 +118,7 @@ struct hw_sequencer_funcs { struct pipe_ctx *pipe_ctx, enum vline_select vline); void (*set_drr)(struct pipe_ctx **pipe_ctx, int num_pipes, - unsigned int vmin, unsigned int vmax, - unsigned int vmid, unsigned int vmid_frame_number); + struct dc_crtc_timing_adjust adjust); void (*set_static_screen_control)(struct pipe_ctx **pipe_ctx, int num_pipes, const struct dc_static_screen_params *events); @@ -218,6 +217,8 @@ struct hw_sequencer_funcs { void (*set_pipe)(struct pipe_ctx *pipe_ctx); + void (*get_dcc_en_bits)(struct dc *dc, int *dcc_en_bits); + /* Idle Optimization Related */ bool (*apply_idle_power_optimizations)(struct dc *dc, bool enable); @@ -234,6 +235,10 @@ struct hw_sequencer_funcs { enum dc_color_depth color_depth, const struct tg_color *solid_color, int width, int height, int offset); + void (*update_visual_confirm_color)(struct dc *dc, + struct pipe_ctx *pipe_ctx, + struct tg_color *color, + int mpcc_id); }; void color_space_to_black_color( diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_enc_cfg.h b/drivers/gpu/drm/amd/display/dc/inc/link_enc_cfg.h new file mode 100644 index 000000000000..883dd8733ea4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/link_enc_cfg.h @@ -0,0 +1,91 @@ +/* + * Copyright 2021 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#ifndef DC_INC_LINK_ENC_CFG_H_ +#define DC_INC_LINK_ENC_CFG_H_ + +/* This module implements functionality for dynamically assigning DIG link + * encoder resources to display endpoints (links). + */ + +#include "core_types.h" + +/* + * Initialise link encoder resource tracking. + */ +void link_enc_cfg_init( + struct dc *dc, + struct dc_state *state); + +/* + * Algorithm for assigning available DIG link encoders to streams. + * + * Update link_enc_assignments table and link_enc_avail list accordingly in + * struct resource_context. + * + * Loop over all streams twice: + * a) First assign encoders to unmappable endpoints. + * b) Then assign encoders to mappable endpoints. + */ +void link_enc_cfg_link_encs_assign( + struct dc *dc, + struct dc_state *state, + struct dc_stream_state *streams[], + uint8_t stream_count); + +/* + * Unassign a link encoder from a stream. + * + * Update link_enc_assignments table and link_enc_avail list accordingly in + * struct resource_context. + */ +void link_enc_cfg_link_enc_unassign( + struct dc_state *state, + struct dc_stream_state *stream); + +/* + * Check whether the transmitter driven by a link encoder is a mappable + * endpoint. + */ +bool link_enc_cfg_is_transmitter_mappable( + struct dc_state *state, + struct link_encoder *link_enc); + +/* Return link using DIG link encoder resource. NULL if unused. */ +struct dc_link *link_enc_cfg_get_link_using_link_enc( + struct dc_state *state, + enum engine_id eng_id); + +/* Return DIG link encoder used by link. NULL if unused. */ +struct link_encoder *link_enc_cfg_get_link_enc_used_by_link( + struct dc_state *state, + const struct dc_link *link); + +/* Return next available DIG link encoder. NULL if none available. */ +struct link_encoder *link_enc_cfg_get_next_avail_link_enc( + const struct dc *dc, + const struct dc_state *state); + +#endif /* DC_INC_LINK_ENC_CFG_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/irq/Makefile b/drivers/gpu/drm/amd/display/dc/irq/Makefile index ca8168726324..e9fabb85741f 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/Makefile +++ b/drivers/gpu/drm/amd/display/dc/irq/Makefile @@ -109,4 +109,12 @@ IRQ_DCN3_02 = irq_service_dcn302.o AMD_DAL_IRQ_DCN3_02 = $(addprefix $(AMDDALPATH)/dc/irq/dcn302/,$(IRQ_DCN3_02)) AMD_DISPLAY_FILES += $(AMD_DAL_IRQ_DCN3_02) +############################################################################### +# DCN 3_03 +############################################################################### +IRQ_DCN3_03 = irq_service_dcn303.o + +AMD_DAL_IRQ_DCN3_03 = $(addprefix $(AMDDALPATH)/dc/irq/dcn303/,$(IRQ_DCN3_03)) + +AMD_DISPLAY_FILES += $(AMD_DAL_IRQ_DCN3_03) endif diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c b/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c index 6ee9dd833b85..ed54e1c819be 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c @@ -58,8 +58,8 @@ enum dc_irq_source to_dal_irq_source_dcn21( return DC_IRQ_SOURCE_VBLANK5; case DCN_1_0__SRCID__DC_D6_OTG_VSTARTUP: return DC_IRQ_SOURCE_VBLANK6; - case DCN_1_0__SRCID__DMCUB_OUTBOX_HIGH_PRIORITY_READY_INT: - return DC_IRQ_SOURCE_DMCUB_OUTBOX0; + case DCN_1_0__SRCID__DMCUB_OUTBOX_LOW_PRIORITY_READY_INT: + return DC_IRQ_SOURCE_DMCUB_OUTBOX; case DCN_1_0__SRCID__OTG1_VERTICAL_INTERRUPT0_CONTROL: return DC_IRQ_SOURCE_DC1_VLINE0; case DCN_1_0__SRCID__OTG2_VERTICAL_INTERRUPT0_CONTROL: @@ -187,6 +187,10 @@ static const struct irq_source_info_funcs vupdate_no_lock_irq_info_funcs = { .ack = NULL }; +static const struct irq_source_info_funcs dmub_outbox_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; static const struct irq_source_info_funcs vline0_irq_info_funcs = { .set = NULL, @@ -205,6 +209,9 @@ static const struct irq_source_info_funcs vline0_irq_info_funcs = { BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ mm ## block ## id ## _ ## reg_name +#define SRI_DMUB(reg_name)\ + BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name #define IRQ_REG_ENTRY(block, reg_num, reg1, mask1, reg2, mask2)\ .enable_reg = SRI(reg1, block, reg_num),\ @@ -220,7 +227,19 @@ static const struct irq_source_info_funcs vline0_irq_info_funcs = { .ack_value = \ block ## reg_num ## _ ## reg2 ## __ ## mask2 ## _MASK \ - +#define IRQ_REG_ENTRY_DMUB(reg1, mask1, reg2, mask2)\ + .enable_reg = SRI_DMUB(reg1),\ + .enable_mask = \ + reg1 ## __ ## mask1 ## _MASK,\ + .enable_value = {\ + reg1 ## __ ## mask1 ## _MASK,\ + ~reg1 ## __ ## mask1 ## _MASK \ + },\ + .ack_reg = SRI_DMUB(reg2),\ + .ack_mask = \ + reg2 ## __ ## mask2 ## _MASK,\ + .ack_value = \ + reg2 ## __ ## mask2 ## _MASK \ #define hpd_int_entry(reg_num)\ [DC_IRQ_SOURCE_HPD1 + reg_num] = {\ @@ -282,6 +301,13 @@ static const struct irq_source_info_funcs vline0_irq_info_funcs = { .funcs = &vline0_irq_info_funcs\ } +#define dmub_outbox_int_entry()\ + [DC_IRQ_SOURCE_DMCUB_OUTBOX] = {\ + IRQ_REG_ENTRY_DMUB(DMCUB_INTERRUPT_ENABLE, DMCUB_OUTBOX1_READY_INT_EN,\ + DMCUB_INTERRUPT_ACK, DMCUB_OUTBOX1_READY_INT_ACK),\ + .funcs = &dmub_outbox_irq_info_funcs\ + } + #define dummy_irq_entry() \ {\ .funcs = &dummy_irq_info_funcs\ @@ -400,6 +426,7 @@ irq_source_info_dcn21[DAL_IRQ_SOURCES_NUMBER] = { vline0_int_entry(3), vline0_int_entry(4), vline0_int_entry(5), + dmub_outbox_int_entry(), }; static const struct irq_service_funcs irq_service_funcs_dcn21 = { diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn30/irq_service_dcn30.c b/drivers/gpu/drm/amd/display/dc/irq/dcn30/irq_service_dcn30.c index 4ec6f6ad8c48..914ce2ce1c2f 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dcn30/irq_service_dcn30.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn30/irq_service_dcn30.c @@ -215,6 +215,9 @@ static const struct irq_source_info_funcs vline0_irq_info_funcs = { BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ mm ## block ## id ## _ ## reg_name +#define SRI_DMUB(reg_name)\ + BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name #define IRQ_REG_ENTRY(block, reg_num, reg1, mask1, reg2, mask2)\ .enable_reg = SRI(reg1, block, reg_num),\ @@ -230,7 +233,19 @@ static const struct irq_source_info_funcs vline0_irq_info_funcs = { .ack_value = \ block ## reg_num ## _ ## reg2 ## __ ## mask2 ## _MASK \ - +#define IRQ_REG_ENTRY_DMUB(reg1, mask1, reg2, mask2)\ + .enable_reg = SRI_DMUB(reg1),\ + .enable_mask = \ + reg1 ## __ ## mask1 ## _MASK,\ + .enable_value = {\ + reg1 ## __ ## mask1 ## _MASK,\ + ~reg1 ## __ ## mask1 ## _MASK \ + },\ + .ack_reg = SRI_DMUB(reg2),\ + .ack_mask = \ + reg2 ## __ ## mask2 ## _MASK,\ + .ack_value = \ + reg2 ## __ ## mask2 ## _MASK \ #define hpd_int_entry(reg_num)\ [DC_IRQ_SOURCE_HPD1 + reg_num] = {\ @@ -284,6 +299,13 @@ static const struct irq_source_info_funcs vline0_irq_info_funcs = { .funcs = &vline0_irq_info_funcs\ } +#define dmub_trace_int_entry()\ + [DC_IRQ_SOURCE_DMCUB_OUTBOX0] = {\ + IRQ_REG_ENTRY_DMUB(DMCUB_INTERRUPT_ENABLE, DMCUB_OUTBOX0_READY_INT_EN,\ + DMCUB_INTERRUPT_ACK, DMCUB_OUTBOX0_READY_INT_ACK),\ + .funcs = &dmub_trace_irq_info_funcs\ + } + #define dummy_irq_entry() \ {\ .funcs = &dummy_irq_info_funcs\ @@ -398,6 +420,7 @@ irq_source_info_dcn30[DAL_IRQ_SOURCES_NUMBER] = { vline0_int_entry(3), vline0_int_entry(4), vline0_int_entry(5), + dmub_trace_int_entry(), }; static const struct irq_service_funcs irq_service_funcs_dcn30 = { diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn302/irq_service_dcn302.c b/drivers/gpu/drm/amd/display/dc/irq/dcn302/irq_service_dcn302.c index 2313a5664f44..40fd34fb1d5e 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dcn302/irq_service_dcn302.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn302/irq_service_dcn302.c @@ -50,6 +50,8 @@ static enum dc_irq_source to_dal_irq_source_dcn302(struct irq_service *irq_servi return DC_IRQ_SOURCE_VBLANK5; case DCN_1_0__SRCID__DC_D6_OTG_VSTARTUP: return DC_IRQ_SOURCE_VBLANK6; + case DCN_1_0__SRCID__DMCUB_OUTBOX_HIGH_PRIORITY_READY_INT: + return DC_IRQ_SOURCE_DMCUB_OUTBOX0; case DCN_1_0__SRCID__OTG1_VERTICAL_INTERRUPT0_CONTROL: return DC_IRQ_SOURCE_DC1_VLINE0; case DCN_1_0__SRCID__OTG2_VERTICAL_INTERRUPT0_CONTROL: @@ -166,6 +168,11 @@ static const struct irq_source_info_funcs vblank_irq_info_funcs = { .ack = NULL }; +static const struct irq_source_info_funcs dmub_trace_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; + static const struct irq_source_info_funcs vline0_irq_info_funcs = { .set = NULL, .ack = NULL @@ -181,6 +188,9 @@ static const struct irq_source_info_funcs vline0_irq_info_funcs = { BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ mm ## block ## id ## _ ## reg_name +#define SRI_DMUB(reg_name)\ + BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name #define IRQ_REG_ENTRY(block, reg_num, reg1, mask1, reg2, mask2)\ .enable_reg = SRI(reg1, block, reg_num),\ @@ -193,7 +203,26 @@ static const struct irq_source_info_funcs vline0_irq_info_funcs = { .ack_mask = block ## reg_num ## _ ## reg2 ## __ ## mask2 ## _MASK,\ .ack_value = block ## reg_num ## _ ## reg2 ## __ ## mask2 ## _MASK \ +#define dmub_trace_int_entry()\ + [DC_IRQ_SOURCE_DMCUB_OUTBOX0] = {\ + IRQ_REG_ENTRY_DMUB(DMCUB_INTERRUPT_ENABLE, DMCUB_OUTBOX0_READY_INT_EN,\ + DMCUB_INTERRUPT_ACK, DMCUB_OUTBOX0_READY_INT_ACK),\ + .funcs = &dmub_trace_irq_info_funcs\ + } +#define IRQ_REG_ENTRY_DMUB(reg1, mask1, reg2, mask2)\ + .enable_reg = SRI_DMUB(reg1),\ + .enable_mask = \ + reg1 ## __ ## mask1 ## _MASK,\ + .enable_value = {\ + reg1 ## __ ## mask1 ## _MASK,\ + ~reg1 ## __ ## mask1 ## _MASK \ + },\ + .ack_reg = SRI_DMUB(reg2),\ + .ack_mask = \ + reg2 ## __ ## mask2 ## _MASK,\ + .ack_value = \ + reg2 ## __ ## mask2 ## _MASK \ #define hpd_int_entry(reg_num)\ [DC_IRQ_SOURCE_HPD1 + reg_num] = {\ @@ -348,6 +377,7 @@ static const struct irq_source_info irq_source_info_dcn302[DAL_IRQ_SOURCES_NUMBE vline0_int_entry(2), vline0_int_entry(3), vline0_int_entry(4), + dmub_trace_int_entry(), }; static const struct irq_service_funcs irq_service_funcs_dcn302 = { diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn303/irq_service_dcn303.c b/drivers/gpu/drm/amd/display/dc/irq/dcn303/irq_service_dcn303.c new file mode 100644 index 000000000000..66e60762388e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn303/irq_service_dcn303.c @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright (C) 2021 Advanced Micro Devices, Inc. + * + * Authors: AMD + */ + +#include "dm_services.h" +#include "irq_service_dcn303.h" +#include "../dce110/irq_service_dce110.h" + +#include "sienna_cichlid_ip_offset.h" +#include "dcn/dcn_3_0_3_offset.h" +#include "dcn/dcn_3_0_3_sh_mask.h" + +#include "ivsrcid/dcn/irqsrcs_dcn_1_0.h" + +static enum dc_irq_source to_dal_irq_source_dcn303(struct irq_service *irq_service, + uint32_t src_id, + uint32_t ext_id) +{ + switch (src_id) { + case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP: + return DC_IRQ_SOURCE_VBLANK1; + case DCN_1_0__SRCID__DC_D2_OTG_VSTARTUP: + return DC_IRQ_SOURCE_VBLANK2; + case DCN_1_0__SRCID__HUBP0_FLIP_INTERRUPT: + return DC_IRQ_SOURCE_PFLIP1; + case DCN_1_0__SRCID__HUBP1_FLIP_INTERRUPT: + return DC_IRQ_SOURCE_PFLIP2; + case DCN_1_0__SRCID__OTG0_IHC_V_UPDATE_NO_LOCK_INTERRUPT: + return DC_IRQ_SOURCE_VUPDATE1; + case DCN_1_0__SRCID__OTG1_IHC_V_UPDATE_NO_LOCK_INTERRUPT: + return DC_IRQ_SOURCE_VUPDATE2; + + case DCN_1_0__SRCID__DC_HPD1_INT: + /* generic src_id for all HPD and HPDRX interrupts */ + switch (ext_id) { + case DCN_1_0__CTXID__DC_HPD1_INT: + return DC_IRQ_SOURCE_HPD1; + case DCN_1_0__CTXID__DC_HPD2_INT: + return DC_IRQ_SOURCE_HPD2; + case DCN_1_0__CTXID__DC_HPD1_RX_INT: + return DC_IRQ_SOURCE_HPD1RX; + case DCN_1_0__CTXID__DC_HPD2_RX_INT: + return DC_IRQ_SOURCE_HPD2RX; + default: + return DC_IRQ_SOURCE_INVALID; + } + break; + + default: + return DC_IRQ_SOURCE_INVALID; + } +} + +static bool hpd_ack(struct irq_service *irq_service, const struct irq_source_info *info) +{ + uint32_t addr = info->status_reg; + uint32_t value = dm_read_reg(irq_service->ctx, addr); + uint32_t current_status = get_reg_field_value(value, HPD0_DC_HPD_INT_STATUS, DC_HPD_SENSE_DELAYED); + + dal_irq_service_ack_generic(irq_service, info); + + value = dm_read_reg(irq_service->ctx, info->enable_reg); + + set_reg_field_value(value, current_status ? 0 : 1, HPD0_DC_HPD_INT_CONTROL, DC_HPD_INT_POLARITY); + + dm_write_reg(irq_service->ctx, info->enable_reg, value); + + return true; +} + +static const struct irq_source_info_funcs hpd_irq_info_funcs = { + .set = NULL, + .ack = hpd_ack +}; + +static const struct irq_source_info_funcs hpd_rx_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; + +static const struct irq_source_info_funcs pflip_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; + +static const struct irq_source_info_funcs vupdate_no_lock_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; + +static const struct irq_source_info_funcs vblank_irq_info_funcs = { + .set = NULL, + .ack = NULL +}; + +#undef BASE_INNER +#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg + +/* compile time expand base address. */ +#define BASE(seg) BASE_INNER(seg) + +#define SRI(reg_name, block, id)\ + BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ + mm ## block ## id ## _ ## reg_name + + +#define IRQ_REG_ENTRY(block, reg_num, reg1, mask1, reg2, mask2)\ + .enable_reg = SRI(reg1, block, reg_num),\ + .enable_mask = block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ + .enable_value = {\ + block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\ + ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \ + },\ + .ack_reg = SRI(reg2, block, reg_num),\ + .ack_mask = block ## reg_num ## _ ## reg2 ## __ ## mask2 ## _MASK,\ + .ack_value = block ## reg_num ## _ ## reg2 ## __ ## mask2 ## _MASK \ + + + +#define hpd_int_entry(reg_num)\ + [DC_IRQ_SOURCE_HPD1 + reg_num] = {\ + IRQ_REG_ENTRY(HPD, reg_num,\ + DC_HPD_INT_CONTROL, DC_HPD_INT_EN,\ + DC_HPD_INT_CONTROL, DC_HPD_INT_ACK),\ + .status_reg = SRI(DC_HPD_INT_STATUS, HPD, reg_num),\ + .funcs = &hpd_irq_info_funcs\ +} + +#define hpd_rx_int_entry(reg_num)\ + [DC_IRQ_SOURCE_HPD1RX + reg_num] = {\ + IRQ_REG_ENTRY(HPD, reg_num,\ + DC_HPD_INT_CONTROL, DC_HPD_RX_INT_EN,\ + DC_HPD_INT_CONTROL, DC_HPD_RX_INT_ACK),\ + .status_reg = SRI(DC_HPD_INT_STATUS, HPD, reg_num),\ + .funcs = &hpd_rx_irq_info_funcs\ +} +#define pflip_int_entry(reg_num)\ + [DC_IRQ_SOURCE_PFLIP1 + reg_num] = {\ + IRQ_REG_ENTRY(HUBPREQ, reg_num,\ + DCSURF_SURFACE_FLIP_INTERRUPT, SURFACE_FLIP_INT_MASK,\ + DCSURF_SURFACE_FLIP_INTERRUPT, SURFACE_FLIP_CLEAR),\ + .funcs = &pflip_irq_info_funcs\ +} + +/* vupdate_no_lock_int_entry maps to DC_IRQ_SOURCE_VUPDATEx, to match semantic + * of DCE's DC_IRQ_SOURCE_VUPDATEx. + */ +#define vupdate_no_lock_int_entry(reg_num)\ + [DC_IRQ_SOURCE_VUPDATE1 + reg_num] = {\ + IRQ_REG_ENTRY(OTG, reg_num,\ + OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_INT_EN,\ + OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_EVENT_CLEAR),\ + .funcs = &vupdate_no_lock_irq_info_funcs\ + } + +#define vblank_int_entry(reg_num)\ + [DC_IRQ_SOURCE_VBLANK1 + reg_num] = {\ + IRQ_REG_ENTRY(OTG, reg_num,\ + OTG_GLOBAL_SYNC_STATUS, VSTARTUP_INT_EN,\ + OTG_GLOBAL_SYNC_STATUS, VSTARTUP_EVENT_CLEAR),\ + .funcs = &vblank_irq_info_funcs\ + } + +#define dummy_irq_entry() { .funcs = &dummy_irq_info_funcs } + +#define i2c_int_entry(reg_num) \ + [DC_IRQ_SOURCE_I2C_DDC ## reg_num] = dummy_irq_entry() + +#define dp_sink_int_entry(reg_num) \ + [DC_IRQ_SOURCE_DPSINK ## reg_num] = dummy_irq_entry() + +#define gpio_pad_int_entry(reg_num) \ + [DC_IRQ_SOURCE_GPIOPAD ## reg_num] = dummy_irq_entry() + +#define dc_underflow_int_entry(reg_num) \ + [DC_IRQ_SOURCE_DC ## reg_num ## UNDERFLOW] = dummy_irq_entry() + +static const struct irq_source_info_funcs dummy_irq_info_funcs = { + .set = dal_irq_service_dummy_set, + .ack = dal_irq_service_dummy_ack +}; + +static const struct irq_source_info irq_source_info_dcn303[DAL_IRQ_SOURCES_NUMBER] = { + [DC_IRQ_SOURCE_INVALID] = dummy_irq_entry(), + hpd_int_entry(0), + hpd_int_entry(1), + hpd_rx_int_entry(0), + hpd_rx_int_entry(1), + i2c_int_entry(1), + i2c_int_entry(2), + dp_sink_int_entry(1), + dp_sink_int_entry(2), + [DC_IRQ_SOURCE_TIMER] = dummy_irq_entry(), + pflip_int_entry(0), + pflip_int_entry(1), + [DC_IRQ_SOURCE_PFLIP_UNDERLAY0] = dummy_irq_entry(), + gpio_pad_int_entry(0), + gpio_pad_int_entry(1), + gpio_pad_int_entry(2), + gpio_pad_int_entry(3), + gpio_pad_int_entry(4), + gpio_pad_int_entry(5), + gpio_pad_int_entry(6), + gpio_pad_int_entry(7), + gpio_pad_int_entry(8), + gpio_pad_int_entry(9), + gpio_pad_int_entry(10), + gpio_pad_int_entry(11), + gpio_pad_int_entry(12), + gpio_pad_int_entry(13), + gpio_pad_int_entry(14), + gpio_pad_int_entry(15), + gpio_pad_int_entry(16), + gpio_pad_int_entry(17), + gpio_pad_int_entry(18), + gpio_pad_int_entry(19), + gpio_pad_int_entry(20), + gpio_pad_int_entry(21), + gpio_pad_int_entry(22), + gpio_pad_int_entry(23), + gpio_pad_int_entry(24), + gpio_pad_int_entry(25), + gpio_pad_int_entry(26), + gpio_pad_int_entry(27), + gpio_pad_int_entry(28), + gpio_pad_int_entry(29), + gpio_pad_int_entry(30), + dc_underflow_int_entry(1), + dc_underflow_int_entry(2), + [DC_IRQ_SOURCE_DMCU_SCP] = dummy_irq_entry(), + [DC_IRQ_SOURCE_VBIOS_SW] = dummy_irq_entry(), + vupdate_no_lock_int_entry(0), + vupdate_no_lock_int_entry(1), + vblank_int_entry(0), + vblank_int_entry(1), +}; + +static const struct irq_service_funcs irq_service_funcs_dcn303 = { + .to_dal_irq_source = to_dal_irq_source_dcn303 +}; + +static void dcn303_irq_construct(struct irq_service *irq_service, struct irq_service_init_data *init_data) +{ + dal_irq_service_construct(irq_service, init_data); + + irq_service->info = irq_source_info_dcn303; + irq_service->funcs = &irq_service_funcs_dcn303; +} + +struct irq_service *dal_irq_service_dcn303_create(struct irq_service_init_data *init_data) +{ + struct irq_service *irq_service = kzalloc(sizeof(*irq_service), GFP_KERNEL); + + if (!irq_service) + return NULL; + + dcn303_irq_construct(irq_service, init_data); + return irq_service; +} diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn303/irq_service_dcn303.h b/drivers/gpu/drm/amd/display/dc/irq/dcn303/irq_service_dcn303.h new file mode 100644 index 000000000000..fd64e3848ff3 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn303/irq_service_dcn303.h @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright (C) 2021 Advanced Micro Devices, Inc. + * + * Authors: AMD + */ + +#ifndef __DAL_IRQ_SERVICE_DCN303_H__ +#define __DAL_IRQ_SERVICE_DCN303_H__ + +#include "../irq_service.h" + +struct irq_service *dal_irq_service_dcn303_create(struct irq_service_init_data *init_data); + +#endif /* __DAL_IRQ_SERVICE_DCN303_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/irq_types.h b/drivers/gpu/drm/amd/display/dc/irq_types.h index ae8f47ec0f8c..5f9346622301 100644 --- a/drivers/gpu/drm/amd/display/dc/irq_types.h +++ b/drivers/gpu/drm/amd/display/dc/irq_types.h @@ -150,7 +150,7 @@ enum dc_irq_source { DC_IRQ_SOURCE_DC4_VLINE1, DC_IRQ_SOURCE_DC5_VLINE1, DC_IRQ_SOURCE_DC6_VLINE1, - DC_IRQ_DMCUB_OUTBOX1, + DC_IRQ_SOURCE_DMCUB_OUTBOX, DC_IRQ_SOURCE_DMCUB_OUTBOX0, DAL_IRQ_SOURCES_NUMBER |