From d24b77e444bef83155557ebf4c2b3c551f198926 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 15 Feb 2023 12:38:33 +0100 Subject: drm/amd/display: Pass proper parent for DM backlight device registration The parent for the backlight device should be the drm-connector object, not the PCI device. Userspace relies on this to be able to detect which backlight class device to use on hybrid gfx devices where there may be multiple native (raw) backlight devices registered. Specifically gnome-settings-daemon expects the parent device to have an "enabled" sysfs attribute (as drm_connector devices do) and tests that this returns "enabled" when read. This aligns the parent of the backlight device with i915, nouveau, radeon. Note that drivers/gpu/drm/amd/amdgpu/atombios_encoders.c also already uses the drm_connector as parent, only amdgpu_dm.c used the PCI device as parent before this change. Note this is marked as a RFC because I don't have hw to test, so this has only been compile tested! If someone can test this on actual hw which hits the changed code path that would be great. Link: https://gitlab.gnome.org/GNOME/gnome-settings-daemon/-/issues/730 Signed-off-by: Hans de Goede Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index c420bce47acb..49ae4ef6bbf0 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4142,7 +4142,8 @@ static const struct backlight_ops amdgpu_dm_backlight_ops = { }; static void -amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm) +amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm, + struct amdgpu_dm_connector *aconnector) { char bl_name[16]; struct backlight_properties props = { 0 }; @@ -4165,7 +4166,7 @@ amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm) adev_to_drm(dm->adev)->primary->index + dm->num_of_edps); dm->backlight_dev[dm->num_of_edps] = backlight_device_register(bl_name, - adev_to_drm(dm->adev)->dev, + aconnector->base.kdev, dm, &amdgpu_dm_backlight_ops, &props); @@ -4218,6 +4219,7 @@ static int initialize_plane(struct amdgpu_display_manager *dm, static void register_backlight_device(struct amdgpu_display_manager *dm, + struct amdgpu_dm_connector *aconnector, struct dc_link *link) { if ((link->connector_signal & (SIGNAL_TYPE_EDP | SIGNAL_TYPE_LVDS)) && @@ -4228,7 +4230,7 @@ static void register_backlight_device(struct amdgpu_display_manager *dm, * is better then a black screen. */ if (!dm->backlight_dev[dm->num_of_edps]) - amdgpu_dm_register_backlight_device(dm); + amdgpu_dm_register_backlight_device(dm, aconnector); if (dm->backlight_dev[dm->num_of_edps]) { dm->backlight_link[dm->num_of_edps] = link; @@ -4415,7 +4417,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) if (ret) { amdgpu_dm_update_connector_after_detect(aconnector); - register_backlight_device(dm, link); + register_backlight_device(dm, aconnector, link); if (dm->num_of_edps) update_connector_ext_caps(aconnector); -- cgit v1.2.3 From e47f1691adbcbba22b364888cb34686d6c7d1152 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 12 Dec 2022 13:02:25 -0500 Subject: drm/amd/display: Don't restrict bpc to 8 bpc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will let us pass the kms_hdr.bpc_switch IGT test. The reason the bpc restriction was required is historical. At one point in time we were not falling back to a lower bpc when we didn't have enough bandwidth for the maximum bpc reported by a display. This meant that we couldn't enable some high refresh modes unless we limitted the bpc. Starting with this patch the issue is fixed: commit cbd14ae7ea93 ("drm/amd/display: Fix incorrectly pruned modes with deep color") This patch implemented a fallback mechanism if mode validation failed at the max bpc. This means users now automatically get all modes that can be supported by at least 6 bpc. The driver will enable the mode with the highest possible bpc that is supported by the display. v2: - explain why this is no longer needed (Michel) - refer to commit that fixed bpc fallback (Michel) Signed-off-by: Harry Wentland Cc: Pekka Paalanen Cc: Sebastian Wick Cc: Vitaly.Prosyak@amd.com Cc: Joshua Ashton Cc: dri-devel@lists.freedesktop.org Cc: amd-gfx@lists.freedesktop.org Cc: Michel Dänzer Reviewed-by: Joshua Ashton Reviewed-by: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 49ae4ef6bbf0..d433be2587f4 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -7237,7 +7237,7 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm, drm_connector_attach_max_bpc_property(&aconnector->base, 8, 16); /* This defaults to the max in the range, but we want 8bpc for non-edp. */ - aconnector->base.state->max_bpc = (connector_type == DRM_MODE_CONNECTOR_eDP) ? 16 : 8; + aconnector->base.state->max_bpc = 16; aconnector->base.state->max_requested_bpc = aconnector->base.state->max_bpc; if (connector_type == DRM_MODE_CONNECTOR_eDP && -- cgit v1.2.3 From 60971b204c615a6881f50c3dc9a2182551282b94 Mon Sep 17 00:00:00 2001 From: tiancyin Date: Wed, 8 Feb 2023 14:10:04 +0800 Subject: drm/amd/display: fix dm irq error message in gpu recover [Why] Variable adev->crtc_irq.num_types was initialized as the value of adev->mode_info.num_crtc at early_init stage, later at hw_init stage, the num_crtc changed due to the display pipe harvest on some SKUs, but the num_types was not updated accordingly, that cause below error in gpu recover. *ERROR* amdgpu_dm_set_crtc_irq_state: crtc is NULL at id :3 *ERROR* amdgpu_dm_set_crtc_irq_state: crtc is NULL at id :3 *ERROR* amdgpu_dm_set_crtc_irq_state: crtc is NULL at id :3 *ERROR* amdgpu_dm_set_pflip_irq_state: crtc is NULL at id :3 *ERROR* amdgpu_dm_set_pflip_irq_state: crtc is NULL at id :3 *ERROR* amdgpu_dm_set_pflip_irq_state: crtc is NULL at id :3 *ERROR* amdgpu_dm_set_pflip_irq_state: crtc is NULL at id :3 *ERROR* amdgpu_dm_set_vupdate_irq_state: crtc is NULL at id :3 *ERROR* amdgpu_dm_set_vupdate_irq_state: crtc is NULL at id :3 *ERROR* amdgpu_dm_set_vupdate_irq_state: crtc is NULL at id :3 [How] Defer the initialization of num_types to eliminate the error logs. Signed-off-by: tiancyin Reviewed-by: Hamza Mahfooz Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index d433be2587f4..ff4cf292781c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4267,6 +4267,8 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) /* Update the actual used number of crtc */ adev->mode_info.num_crtc = adev->dm.display_indexes_num; + amdgpu_dm_set_irq_funcs(adev); + link_cnt = dm->dc->caps.max_links; if (amdgpu_dm_mode_config_init(dm->adev)) { DRM_ERROR("DM: Failed to initialize mode config\n"); @@ -4759,8 +4761,6 @@ static int dm_early_init(void *handle) break; } - amdgpu_dm_set_irq_funcs(adev); - if (adev->mode_info.funcs == NULL) adev->mode_info.funcs = &dm_display_funcs; -- cgit v1.2.3 From 1e5d4d8eb8c0f15d90c50e7abd686c980e54e42e Mon Sep 17 00:00:00 2001 From: Ryan Lin Date: Tue, 7 Feb 2023 23:03:48 +0800 Subject: drm/amd/display: Ext displays with dock can't recognized after resume [Why] Needs to set the default value of the LTTPR timeout after resume. [How] Set the default (3.2ms) timeout at resuming if the sink supports LTTPR Reviewed-by: Jerry Zuo Acked-by: Qingqing Zhuo Signed-off-by: Ryan Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 10 ++++++++++ drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.h | 1 + .../gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c | 2 -- 3 files changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index ff4cf292781c..9534bb8cb40e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -41,6 +41,8 @@ #include "dpcd_defs.h" #include "link/protocols/link_dpcd.h" #include "link_service_types.h" +#include "link/protocols/link_dp_capability.h" +#include "link/protocols/link_ddc.h" #include "vid.h" #include "amdgpu.h" @@ -2302,6 +2304,14 @@ static void s3_handle_mst(struct drm_device *dev, bool suspend) if (suspend) { drm_dp_mst_topology_mgr_suspend(mgr); } else { + /* if extended timeout is supported in hardware, + * default to LTTPR timeout (3.2ms) first as a W/A for DP link layer + * CTS 4.2.1.1 regression introduced by CTS specs requirement update. + */ + try_to_configure_aux_timeout(aconnector->dc_link->ddc, LINK_AUX_DEFAULT_LTTPR_TIMEOUT_PERIOD); + if (!dp_is_lttpr_present(aconnector->dc_link)) + try_to_configure_aux_timeout(aconnector->dc_link->ddc, LINK_AUX_DEFAULT_TIMEOUT_PERIOD); + ret = drm_dp_mst_topology_mgr_resume(mgr, true); if (ret < 0) { dm_helpers_dp_mst_stop_top_mgr(aconnector->dc_link->ctx, diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.h index 86e9d2e886d6..aaa5064408ba 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.h +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.h @@ -33,6 +33,7 @@ #define DPVGA_DONGLE_AUX_DEFER_WA_DELAY 40 #define I2C_OVER_AUX_DEFER_WA_DELAY_1MS 1 #define LINK_AUX_DEFAULT_LTTPR_TIMEOUT_PERIOD 3200 /*us*/ +#define LINK_AUX_DEFAULT_TIMEOUT_PERIOD 552 /*us*/ #define EDID_SEGMENT_SIZE 256 diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c index 4874d1bf1dcb..d4370856f164 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c @@ -60,8 +60,6 @@ #define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) #endif -#define LINK_AUX_DEFAULT_TIMEOUT_PERIOD 552 /*us*/ - struct dp_lt_fallback_entry { enum dc_lane_count lane_count; enum dc_link_rate link_rate; -- cgit v1.2.3 From c32699caeca802cfa3416f798abcff719d1633f7 Mon Sep 17 00:00:00 2001 From: Jasdeep Dhillon Date: Wed, 25 Jan 2023 10:50:19 -0500 Subject: drm/amd/display: Updating Video Format Fall Back Policy. [WHY] Adding 1920x1080 as fail safe mode for Video Format Fall Back Policy. Reviewed-by: Jerry Zuo Acked-by: Qingqing Zhuo Signed-off-by: Jasdeep Dhillon Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 5 +++++ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c | 1 + drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h | 1 + 3 files changed, 7 insertions(+) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 9534bb8cb40e..cfbde4fde852 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -7160,12 +7160,17 @@ static int amdgpu_dm_connector_get_modes(struct drm_connector *connector) to_amdgpu_dm_connector(connector); struct drm_encoder *encoder; struct edid *edid = amdgpu_dm_connector->edid; + struct dc_link_settings *verified_link_cap = + &amdgpu_dm_connector->dc_link->verified_link_cap; encoder = amdgpu_dm_connector_to_encoder(connector); if (!drm_edid_is_valid(edid)) { amdgpu_dm_connector->num_modes = drm_add_modes_noedid(connector, 640, 480); + if (link_dp_get_encoding_format(verified_link_cap) == DP_128b_132b_ENCODING) + amdgpu_dm_connector->num_modes += + drm_add_modes_noedid(connector, 1920, 1080); } else { amdgpu_dm_connector_ddc_get_modes(connector, edid); amdgpu_dm_connector_add_common_modes(encoder, connector); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c index 8e572f07ec47..125012426a92 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c @@ -559,6 +559,7 @@ static void update_config(void *handle, struct cp_psp_stream_config *config) link->dp.rev = aconnector->dc_link->dpcd_caps.dpcd_rev.raw; link->dp.assr_enabled = config->assr_enabled; link->dp.mst_enabled = config->mst_enabled; + link->dp.dp2_enabled = config->dp2_enabled; link->dp.usb4_enabled = config->usb4_enabled; display->adjust.disable = MOD_HDCP_DISPLAY_DISABLE_AUTHENTICATION; link->adjust.auth_delay = 0; diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h b/drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h index 3348bb97ef81..a4d344a4db9e 100644 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h @@ -104,6 +104,7 @@ struct mod_hdcp_displayport { uint8_t rev; uint8_t assr_enabled; uint8_t mst_enabled; + uint8_t dp2_enabled; uint8_t usb4_enabled; }; -- cgit v1.2.3 From 7ae1dbe6547c39410d82156c96eaa9c8cf55e87a Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Mon, 6 Feb 2023 17:58:52 -0500 Subject: drm/amd/display: merge dc_link.h into dc.h and dc_types.h [why] Remove the need to include dc_link.h separately. dc.h should contain everything needed on DM side. [How] Merge dc_link.h into dc.h and dc_types.h so DM only needs to include dc.h to use all link public functions. Reviewed-by: Jun Lei Acked-by: Qingqing Zhuo Signed-off-by: Wenjing Liu Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- .../drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 2 +- drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c | 4 +- drivers/gpu/drm/amd/display/dc/core/dc.c | 156 +----- .../gpu/drm/amd/display/dc/core/dc_link_exports.c | 87 ++++ drivers/gpu/drm/amd/display/dc/dc.h | 553 ++++++++++++++++++++- drivers/gpu/drm/amd/display/dc/dc_dp_types.h | 107 ++++ drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 14 + drivers/gpu/drm/amd/display/dc/dc_types.h | 104 ++++ drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c | 2 +- drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h | 5 +- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 2 +- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 2 +- .../display/dc/dcn30/dcn30_dio_stream_encoder.c | 1 + drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c | 2 +- .../display/dc/dcn31/dcn31_hpo_dp_link_encoder.c | 1 - .../display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c | 2 +- .../display/dc/dcn32/dcn32_hpo_dp_link_encoder.c | 1 - drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c | 2 +- .../amd/display/dc/dml/dcn30/display_mode_vba_30.c | 1 - .../amd/display/dc/dml/dcn31/display_mode_vba_31.c | 1 - .../display/dc/dml/dcn314/display_mode_vba_314.c | 1 - .../amd/display/dc/dml/dcn32/display_mode_vba_32.c | 1 - drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h | 14 - .../gpu/drm/amd/display/dc/inc/hw/link_encoder.h | 52 -- .../gpu/drm/amd/display/dc/inc/hw/stream_encoder.h | 1 - drivers/gpu/drm/amd/display/dc/inc/link.h | 1 - .../amd/display/dc/link/accessories/link_dp_cts.c | 17 - .../gpu/drm/amd/display/dc/link/link_detection.c | 99 ++++ .../amd/display/dc/link/protocols/link_dp_dpia.c | 1 - .../display/dc/link/protocols/link_dp_dpia_bw.c | 1 - .../dc/link/protocols/link_dp_training_dpia.c | 1 - .../drm/amd/display/include/link_service_types.h | 26 - 33 files changed, 978 insertions(+), 288 deletions(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index cfbde4fde852..824cfc4a0293 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2273,7 +2273,7 @@ static int dm_late_init(void *handle) struct dc_link *edp_links[MAX_NUM_EDP]; int edp_num; - get_edp_links(adev->dm.dc, edp_links, &edp_num); + dc_get_edp_links(adev->dm.dc, edp_links, &edp_num); for (i = 0; i < edp_num; i++) { if (!dmub_init_abm_config(adev->dm.dc->res_pool, params, i)) return -EINVAL; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index 09a3efa517da..4a5dae578d97 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -724,7 +724,7 @@ static ssize_t dp_phy_test_pattern_debugfs_write(struct file *f, const char __us for (i = 0; i < (unsigned int)(link_training_settings.link_settings.lane_count); i++) link_training_settings.hw_lane_settings[i] = link->cur_lane_setting[i]; - dc_link_set_test_pattern( + dc_link_dp_set_test_pattern( link, test_pattern, DP_TEST_PATTERN_COLOR_SPACE_RGB, 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 69691daf4dbb..73a45ec27f90 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 @@ -104,7 +104,7 @@ void clk_mgr_exit_optimized_pwr_state(const struct dc *dc, struct clk_mgr *clk_m int edp_num; unsigned int panel_inst; - get_edp_links(dc, edp_links, &edp_num); + dc_get_edp_links(dc, edp_links, &edp_num); if (dc->hwss.exit_optimized_pwr_state) dc->hwss.exit_optimized_pwr_state(dc, dc->current_state); @@ -129,7 +129,7 @@ void clk_mgr_optimize_pwr_state(const struct dc *dc, struct clk_mgr *clk_mgr) int edp_num; unsigned int panel_inst; - get_edp_links(dc, edp_links, &edp_num); + dc_get_edp_links(dc, edp_links, &edp_num); if (edp_num) { for (panel_inst = 0; panel_inst < edp_num; panel_inst++) { edp_link = edp_links[panel_inst]; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 1c218c526650..d406d7b74c6c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -53,7 +53,6 @@ #include "link_encoder.h" #include "link_enc_cfg.h" -#include "dc_link.h" #include "link.h" #include "dm_helpers.h" #include "mem_input.h" @@ -1298,7 +1297,7 @@ static void detect_edp_presence(struct dc *dc) int i; int edp_num; - get_edp_links(dc, edp_links, &edp_num); + dc_get_edp_links(dc, edp_links, &edp_num); if (!edp_num) return; @@ -4317,157 +4316,6 @@ bool dc_is_dmcu_initialized(struct dc *dc) return false; } -bool dc_is_oem_i2c_device_present( - struct dc *dc, - size_t slave_address) -{ - if (dc->res_pool->oem_device) - return dce_i2c_oem_device_present( - dc->res_pool, - dc->res_pool->oem_device, - slave_address); - - return false; -} - -bool dc_submit_i2c( - struct dc *dc, - uint32_t link_index, - struct i2c_command *cmd) -{ - - struct dc_link *link = dc->links[link_index]; - struct ddc_service *ddc = link->ddc; - return dce_i2c_submit_command( - dc->res_pool, - ddc->ddc_pin, - cmd); -} - -bool dc_submit_i2c_oem( - struct dc *dc, - struct i2c_command *cmd) -{ - struct ddc_service *ddc = dc->res_pool->oem_device; - if (ddc) - return dce_i2c_submit_command( - dc->res_pool, - ddc->ddc_pin, - cmd); - - return false; -} - -static bool link_add_remote_sink_helper(struct dc_link *dc_link, struct dc_sink *sink) -{ - if (dc_link->sink_count >= MAX_SINKS_PER_LINK) { - BREAK_TO_DEBUGGER(); - return false; - } - - dc_sink_retain(sink); - - dc_link->remote_sinks[dc_link->sink_count] = sink; - dc_link->sink_count++; - - return true; -} - -/* - * dc_link_add_remote_sink() - Create a sink and attach it to an existing link - * - * EDID length is in bytes - */ -struct dc_sink *dc_link_add_remote_sink( - struct dc_link *link, - const uint8_t *edid, - int len, - struct dc_sink_init_data *init_data) -{ - struct dc_sink *dc_sink; - enum dc_edid_status edid_status; - - if (len > DC_MAX_EDID_BUFFER_SIZE) { - dm_error("Max EDID buffer size breached!\n"); - return NULL; - } - - if (!init_data) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - if (!init_data->link) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - dc_sink = dc_sink_create(init_data); - - if (!dc_sink) - return NULL; - - memmove(dc_sink->dc_edid.raw_edid, edid, len); - dc_sink->dc_edid.length = len; - - if (!link_add_remote_sink_helper( - link, - dc_sink)) - goto fail_add_sink; - - edid_status = dm_helpers_parse_edid_caps( - link, - &dc_sink->dc_edid, - &dc_sink->edid_caps); - - /* - * Treat device as no EDID device if EDID - * parsing fails - */ - if (edid_status != EDID_OK && edid_status != EDID_PARTIAL_VALID) { - dc_sink->dc_edid.length = 0; - dm_error("Bad EDID, status%d!\n", edid_status); - } - - return dc_sink; - -fail_add_sink: - dc_sink_release(dc_sink); - return NULL; -} - -/* - * dc_link_remove_remote_sink() - Remove a remote sink from a dc_link - * - * Note that this just removes the struct dc_sink - it doesn't - * program hardware or alter other members of dc_link - */ -void dc_link_remove_remote_sink(struct dc_link *link, struct dc_sink *sink) -{ - int i; - - if (!link->sink_count) { - BREAK_TO_DEBUGGER(); - return; - } - - for (i = 0; i < link->sink_count; i++) { - if (link->remote_sinks[i] == sink) { - dc_sink_release(sink); - link->remote_sinks[i] = NULL; - - /* shrink array to remove empty place */ - while (i < link->sink_count - 1) { - link->remote_sinks[i] = link->remote_sinks[i+1]; - i++; - } - link->remote_sinks[i] = NULL; - link->sink_count--; - return; - } - } -} - void get_clock_requirements_for_state(struct dc_state *state, struct AsicStateEx *info) { info->displayClock = (unsigned int)state->bw_ctx.bw.dcn.clk.dispclk_khz; @@ -4990,7 +4838,7 @@ void dc_notify_vsync_int_state(struct dc *dc, struct dc_stream_state *stream, bo return; } - get_edp_links(dc, edp_links, &edp_num); + dc_get_edp_links(dc, edp_links, &edp_num); /* Determine panel inst */ for (i = 0; i < edp_num; i++) { diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c index a951e10416ee..862cb0f93b7d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c @@ -34,6 +34,49 @@ * in this file which calls link functions. */ #include "link.h" +#include "dce/dce_i2c.h" +struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_index) +{ + return dc->links[link_index]; +} + +void dc_get_edp_links(const struct dc *dc, + struct dc_link **edp_links, + int *edp_num) +{ + int i; + + *edp_num = 0; + for (i = 0; i < dc->link_count; i++) { + // report any eDP links, even unconnected DDI's + if (!dc->links[i]) + continue; + if (dc->links[i]->connector_signal == SIGNAL_TYPE_EDP) { + edp_links[*edp_num] = dc->links[i]; + if (++(*edp_num) == MAX_NUM_EDP) + return; + } + } +} + +bool dc_get_edp_link_panel_inst(const struct dc *dc, + const struct dc_link *link, + unsigned int *inst_out) +{ + struct dc_link *edp_links[MAX_NUM_EDP]; + int edp_num, i; + + *inst_out = 0; + if (link->connector_signal != SIGNAL_TYPE_EDP) + return false; + dc_get_edp_links(dc, edp_links, &edp_num); + for (i = 0; i < edp_num; i++) { + if (link == edp_links[i]) + break; + (*inst_out)++; + } + return true; +} bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) { @@ -101,3 +144,47 @@ bool dc_link_update_dsc_config(struct pipe_ctx *pipe_ctx) { return link_update_dsc_config(pipe_ctx); } + +bool dc_is_oem_i2c_device_present( + struct dc *dc, + size_t slave_address) +{ + if (dc->res_pool->oem_device) + return dce_i2c_oem_device_present( + dc->res_pool, + dc->res_pool->oem_device, + slave_address); + + return false; +} + +bool dc_submit_i2c( + struct dc *dc, + uint32_t link_index, + struct i2c_command *cmd) +{ + + struct dc_link *link = dc->links[link_index]; + struct ddc_service *ddc = link->ddc; + + return dce_i2c_submit_command( + dc->res_pool, + ddc->ddc_pin, + cmd); +} + +bool dc_submit_i2c_oem( + struct dc *dc, + struct i2c_command *cmd) +{ + struct ddc_service *ddc = dc->res_pool->oem_device; + + if (ddc) + return dce_i2c_submit_command( + dc->res_pool, + ddc->ddc_pin, + cmd); + + return false; +} + diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 8a62f3e93e35..c84554933dc2 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -1380,8 +1380,159 @@ struct dc_plane_state *dc_get_surface_for_mpcc(struct dc *dc, uint32_t dc_get_opp_for_plane(struct dc *dc, struct dc_plane_state *plane); /* Link Interfaces */ -/* TODO: remove this after resolving external dependencies */ -#include "dc_link.h" +/* + * A link contains one or more sinks and their connected status. + * The currently active signal type (HDMI, DP-SST, DP-MST) is also reported. + */ +struct dc_link { + struct dc_sink *remote_sinks[MAX_SINKS_PER_LINK]; + unsigned int sink_count; + struct dc_sink *local_sink; + unsigned int link_index; + enum dc_connection_type type; + enum signal_type connector_signal; + enum dc_irq_source irq_source_hpd; + enum dc_irq_source irq_source_hpd_rx;/* aka DP Short Pulse */ + + bool is_hpd_filter_disabled; + bool dp_ss_off; + + /** + * @link_state_valid: + * + * If there is no link and local sink, this variable should be set to + * false. Otherwise, it should be set to true; usually, the function + * core_link_enable_stream sets this field to true. + */ + bool link_state_valid; + bool aux_access_disabled; + bool sync_lt_in_progress; + bool skip_stream_reenable; + 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 is_hpd_pending; /* Indicates a new received hpd */ + bool is_automated; /* Indicates automated testing */ + + bool edp_sink_present; + + struct dp_trace dp_trace; + + /* caps is the same as reported_link_cap. link_traing use + * reported_link_cap. Will clean up. TODO + */ + struct dc_link_settings reported_link_cap; + struct dc_link_settings verified_link_cap; + struct dc_link_settings cur_link_settings; + struct dc_lane_settings cur_lane_setting[LANE_COUNT_DP_MAX]; + struct dc_link_settings preferred_link_setting; + /* preferred_training_settings are override values that + * come from DM. DM is responsible for the memory + * management of the override pointers. + */ + struct dc_link_training_overrides preferred_training_settings; + struct dp_audio_test_data audio_test_data; + + uint8_t ddc_hw_inst; + + 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; + + void *priv; + + struct ddc_service *ddc; + + bool aux_mode; + + /* Private to DC core */ + + const struct dc *dc; + + struct dc_context *ctx; + + 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; + uint32_t dongle_max_pix_clk; + unsigned short chip_caps; + unsigned int dpcd_sink_count; +#if defined(CONFIG_DRM_AMD_DC_HDCP) + struct hdcp_caps hdcp_caps; +#endif + enum edp_revision edp_revision; + union dpcd_sink_ext_caps dpcd_sink_ext_caps; + + struct psr_settings psr_settings; + + /* Drive settings read from integrated info table */ + struct dc_lane_settings bios_forced_drive_settings; + + /* Vendor specific LTTPR workaround variables */ + uint8_t vendor_specific_lttpr_link_rate_wa; + bool apply_vendor_specific_lttpr_link_rate_wa; + + /* MST record stream using this link */ + struct link_flags { + bool dp_keep_receiver_powered; + bool dp_skip_DID2; + bool dp_skip_reset_segment; + bool dp_skip_fs_144hz; + bool dp_mot_reset_segment; + /* Some USB4 docks do not handle turning off MST DSC once it has been enabled. */ + bool dpia_mst_dsc_always_on; + /* Forced DPIA into TBT3 compatibility mode. */ + bool dpia_forced_tbt3_mode; + bool dongle_mode_timing_override; + } wa_flags; + struct link_mst_stream_allocation_table mst_stream_alloc_table; + + struct dc_link_status link_status; + struct dprx_states dprx_states; + + struct gpio *hpd_gpio; + enum dc_link_fec_state fec_state; + bool link_powered_externally; // Used to bypass hardware sequencing delays when panel is powered down forcibly + + struct dc_panel_config panel_config; + struct phy_state phy_state; + // BW ALLOCATON USB4 ONLY + struct dc_dpia_bw_alloc dpia_bw_alloc_config; +}; + +/* Return an enumerated dc_link. + * dc_link order is constant and determined at + * boot time. They cannot be created or destroyed. + * Use dc_get_caps() to get number of links. + */ +struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_index); + +/* Return instance id of the edp link. Inst 0 is primary edp link. */ +bool dc_get_edp_link_panel_inst(const struct dc *dc, + const struct dc_link *link, + unsigned int *inst_out); + +/* Return an array of link pointers to edp links. */ +void dc_get_edp_links(const struct dc *dc, + struct dc_link **edp_links, + int *edp_num); /* The function initiates detection handshake over the given link. It first * determines if there are display connections over the link. If so it initiates @@ -1405,6 +1556,38 @@ uint32_t dc_get_opp_for_plane(struct dc *dc, struct dc_plane_state *plane); */ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason); +struct dc_sink_init_data; + +/* When link connection type is dc_connection_mst_branch, remote sink can be + * added to the link. The interface creates a remote sink and associates it with + * current link. The sink will be retained by link until remove remote sink is + * called. + * + * @dc_link - link the remote sink will be added to. + * @edid - byte array of EDID raw data. + * @len - size of the edid in byte + * @init_data - + */ +struct dc_sink *dc_link_add_remote_sink( + struct dc_link *dc_link, + const uint8_t *edid, + int len, + struct dc_sink_init_data *init_data); + +/* Remove remote sink from a link with dc_connection_mst_branch connection type. + * @link - link the sink should be removed from + * @sink - sink to be removed. + */ +void dc_link_remove_remote_sink( + struct dc_link *link, + struct dc_sink *sink); + +/* Enable HPD interrupt handler for a given link */ +void dc_link_enable_hpd(const struct dc_link *link); + +/* Disable HPD interrupt handler for a given link */ +void dc_link_disable_hpd(const struct dc_link *link); + /* determine if there is a sink connected to the link * * @type - dc_connection_single if connected, dc_connection_none otherwise. @@ -1418,15 +1601,119 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason); bool dc_link_detect_connection_type(struct dc_link *link, enum dc_connection_type *type); +/* query current hpd pin value + * return - true HPD is asserted (HPD high), false otherwise (HPD low) + * + */ +bool dc_link_get_hpd_state(struct dc_link *dc_link); + /* Getter for cached link status from given link */ const struct dc_link_status *dc_link_get_status(const struct dc_link *link); +/* enable/disable hardware HPD filter. + * + * @link - The link the HPD pin is associated with. + * @enable = true - enable hardware HPD filter. HPD event will only queued to irq + * handler once after no HPD change has been detected within dc default HPD + * filtering interval since last HPD event. i.e if display keeps toggling hpd + * pulses within default HPD interval, no HPD event will be received until HPD + * toggles have stopped. Then HPD event will be queued to irq handler once after + * dc default HPD filtering interval since last HPD event. + * + * @enable = false - disable hardware HPD filter. HPD event will be queued + * immediately to irq handler after no HPD change has been detected within + * IRQ_HPD (aka HPD short pulse) interval (i.e 2ms). + */ +void dc_link_enable_hpd_filter(struct dc_link *link, bool enable); + +/* submit i2c read/write payloads through ddc channel + * @link_index - index to a link with ddc in i2c mode + * @cmd - i2c command structure + * return - true if success, false otherwise. + */ +bool dc_submit_i2c( + struct dc *dc, + uint32_t link_index, + struct i2c_command *cmd); + +/* submit i2c read/write payloads through oem channel + * @link_index - index to a link with ddc in i2c mode + * @cmd - i2c command structure + * return - true if success, false otherwise. + */ +bool dc_submit_i2c_oem( + struct dc *dc, + struct i2c_command *cmd); + +enum aux_return_code_type; +/* Attempt to transfer the given aux payload. This function does not perform + * retries or handle error states. The reply is returned in the payload->reply + * and the result through operation_result. Returns the number of bytes + * transferred,or -1 on a failure. + */ +int dc_link_aux_transfer_raw(struct ddc_service *ddc, + struct aux_payload *payload, + enum aux_return_code_type *operation_result); + +bool dc_is_oem_i2c_device_present( + struct dc *dc, + size_t slave_address +); + #ifdef CONFIG_DRM_AMD_DC_HDCP + /* return true if the connected receiver supports the hdcp version */ bool dc_link_is_hdcp14(struct dc_link *link, enum signal_type signal); bool dc_link_is_hdcp22(struct dc_link *link, enum signal_type signal); #endif +/* Notify DC about DP RX Interrupt (aka DP IRQ_HPD). + * + * TODO - When defer_handling is true the function will have a different purpose. + * It no longer does complete hpd rx irq handling. We should create a separate + * interface specifically for this case. + * + * Return: + * true - Downstream port status changed. DM should call DC to do the + * detection. + * false - no change in Downstream port status. No further action required + * from DM. + */ +bool dc_link_handle_hpd_rx_irq(struct dc_link *dc_link, + union hpd_irq_data *hpd_irq_dpcd_data, bool *out_link_loss, + bool defer_handling, bool *has_left_work); +/* handle DP specs define test automation sequence*/ +void dc_link_dp_handle_automated_test(struct dc_link *link); + +/* handle DP Link loss sequence and try to recover RX link loss with best + * effort + */ +void dc_link_dp_handle_link_loss(struct dc_link *link); + +/* Determine if hpd rx irq should be handled or ignored + * return true - hpd rx irq should be handled. + * return false - it is safe to ignore hpd rx irq event + */ +bool dc_link_dp_allow_hpd_rx_irq(const struct dc_link *link); + +/* Determine if link loss is indicated with a given hpd_irq_dpcd_data. + * @link - link the hpd irq data associated with + * @hpd_irq_dpcd_data - input hpd irq data + * return - true if hpd irq data indicates a link lost + */ +bool dc_link_check_link_loss_status(struct dc_link *link, + union hpd_irq_data *hpd_irq_dpcd_data); + +/* Read hpd rx irq data from a given link + * @link - link where the hpd irq data should be read from + * @irq_data - output hpd irq data + * return - DC_OK if hpd irq data is read successfully, otherwise hpd irq data + * read has failed. + */ +enum dc_status dc_link_dp_read_hpd_rx_irq_data( + struct dc_link *link, + union hpd_irq_data *irq_data); + /* The function clears recorded DP RX states in the link. DM should call this * function when it is resuming from S3 power state to previously connected links. * @@ -1494,6 +1781,268 @@ void dc_restore_link_res_map(const struct dc *dc, uint32_t *map); * interface i.e stream_update->dsc_config */ bool dc_link_update_dsc_config(struct pipe_ctx *pipe_ctx); + +/* translate a raw link rate data to bandwidth in kbps */ +uint32_t dc_link_bw_kbps_from_raw_frl_link_rate_data(uint8_t bw); + +/* determine the optimal bandwidth given link and required bw. + * @link - current detected link + * @req_bw - requested bandwidth in kbps + * @link_settings - returned most optimal link settings that can fit the + * requested bandwidth + * return - false if link can't support requested bandwidth, true if link + * settings is found. + */ +bool dc_link_decide_edp_link_settings(struct dc_link *link, + struct dc_link_settings *link_settings, + uint32_t req_bw); + +/* return the max dp link settings can be driven by the link without considering + * connected RX device and its capability + */ +bool dc_link_dp_get_max_link_enc_cap(const struct dc_link *link, + struct dc_link_settings *max_link_enc_cap); + +/* determine when the link is driving MST mode, what DP link channel coding + * format will be used. The decision will remain unchanged until next HPD event. + * + * @link - a link with DP RX connection + * return - if stream is committed to this link with MST signal type, type of + * channel coding format dc will choose. + */ +enum dp_link_encoding dc_link_dp_mst_decide_link_encoding_format( + const struct dc_link *link); + +/* get max dp link settings the link can enable with all things considered. (i.e + * TX/RX/Cable capabilities and dp override policies. + * + * @link - a link with DP RX connection + * return - max dp link settings the link can enable. + * + */ +const struct dc_link_settings *dc_link_get_link_cap(const struct dc_link *link); + +/* Check if a RX (ex. DP sink, MST hub, passive or active dongle) is connected + * to a link with dp connector signal type. + * @link - a link with dp connector signal type + * return - true if connected, false otherwise + */ +bool dc_link_is_dp_sink_present(struct dc_link *link); + +/* Force DP lane settings update to main-link video signal and notify the change + * to DP RX via DPCD. This is a debug interface used for video signal integrity + * tuning purpose. The interface assumes link has already been enabled with DP + * signal. + * + * @lt_settings - a container structure with desired hw_lane_settings + */ +void dc_link_set_drive_settings(struct dc *dc, + struct link_training_settings *lt_settings, + const struct dc_link *link); + +/* Enable a test pattern in Link or PHY layer in an active link for compliance + * test or debugging purpose. The test pattern will remain until next un-plug. + * + * @link - active link with DP signal output enabled. + * @test_pattern - desired test pattern to output. + * NOTE: set to DP_TEST_PATTERN_VIDEO_MODE to disable previous test pattern. + * @test_pattern_color_space - for video test pattern choose a desired color + * space. + * @p_link_settings - For PHY pattern choose a desired link settings + * @p_custom_pattern - some test pattern will require a custom input to + * customize some pattern details. Otherwise keep it to NULL. + * @cust_pattern_size - size of the custom pattern input. + * + */ +bool dc_link_dp_set_test_pattern( + struct dc_link *link, + enum dp_test_pattern test_pattern, + enum dp_test_pattern_color_space test_pattern_color_space, + const struct link_training_settings *p_link_settings, + const unsigned char *p_custom_pattern, + unsigned int cust_pattern_size); + +/* Force DP link settings to always use a specific value until reboot to a + * specific link. If link has already been enabled, the interface will also + * switch to desired link settings immediately. This is a debug interface to + * generic dp issue trouble shooting. + */ +void dc_link_set_preferred_link_settings(struct dc *dc, + struct dc_link_settings *link_setting, + struct dc_link *link); + +/* Force DP link to customize a specific link training behavior by overriding to + * standard DP specs defined protocol. This is a debug interface to trouble shoot + * display specific link training issues or apply some display specific + * workaround in link training. + * + * @link_settings - if not NULL, force preferred link settings to the link. + * @lt_override - a set of override pointers. If any pointer is none NULL, dc + * will apply this particular override in future link training. If NULL is + * passed in, dc resets previous overrides. + * NOTE: DM must keep the memory from override pointers until DM resets preferred + * training settings. + */ +void dc_link_set_preferred_training_settings(struct dc *dc, + struct dc_link_settings *link_setting, + struct dc_link_training_overrides *lt_overrides, + struct dc_link *link, + bool skip_immediate_retrain); + +/* return - true if FEC is supported with connected DP RX, false otherwise */ +bool dc_link_is_fec_supported(const struct dc_link *link); + +/* query FEC enablement policy to determine if FEC will be enabled by dc during + * link enablement. + * return - true if FEC should be enabled, false otherwise. + */ +bool dc_link_should_enable_fec(const struct dc_link *link); + +/* determine lttpr mode the current link should be enabled with a specific link + * settings. + */ +enum lttpr_mode dc_link_decide_lttpr_mode(struct dc_link *link, + struct dc_link_settings *link_setting); + +/* Force DP RX to update its power state. + * NOTE: this interface doesn't update dp main-link. Calling this function will + * cause DP TX main-link and DP RX power states out of sync. DM has to restore + * RX power state back upon finish DM specific execution requiring DP RX in a + * specific power state. + * @on - true to set DP RX in D0 power state, false to set DP RX in D3 power + * state. + */ +void dc_link_dp_receiver_power_ctrl(struct dc_link *link, bool on); + +/* Force link to read base dp receiver caps from dpcd 000h - 00Fh and overwrite + * current value read from extended receiver cap from 02200h - 0220Fh. + * Some DP RX has problems of providing accurate DP receiver caps from extended + * field, this interface is a workaround to revert link back to use base caps. + */ +void dc_link_overwrite_extended_receiver_cap( + struct dc_link *link); + +void dc_link_edp_panel_backlight_power_on(struct dc_link *link, + bool wait_for_hpd); + +/* Set backlight level of an embedded panel (eDP, LVDS). + * backlight_pwm_u16_16 is unsigned 32 bit with 16 bit integer + * and 16 bit fractional, where 1.0 is max backlight value. + */ +bool dc_link_set_backlight_level(const struct dc_link *dc_link, + uint32_t backlight_pwm_u16_16, + uint32_t frame_ramp); + +/* Set/get nits-based backlight level of an embedded panel (eDP, LVDS). */ +bool dc_link_set_backlight_level_nits(struct dc_link *link, + bool isHDR, + uint32_t backlight_millinits, + uint32_t transition_time_in_ms); + +bool dc_link_get_backlight_level_nits(struct dc_link *link, + uint32_t *backlight_millinits, + uint32_t *backlight_millinits_peak); + +int dc_link_get_backlight_level(const struct dc_link *dc_link); + +int dc_link_get_target_backlight_pwm(const struct dc_link *link); + +bool dc_link_set_psr_allow_active(struct dc_link *dc_link, const bool *enable, + bool wait, bool force_static, const unsigned int *power_opts); + +bool dc_link_get_psr_state(const struct dc_link *dc_link, enum dc_psr_state *state); + +bool dc_link_setup_psr(struct dc_link *dc_link, + const struct dc_stream_state *stream, struct psr_config *psr_config, + struct psr_context *psr_context); + +/* On eDP links this function call will stall until T12 has elapsed. + * If the panel is not in power off state, this function will return + * immediately. + */ +bool dc_link_wait_for_t12(struct dc_link *link); + +/* Determine if dp trace has been initialized to reflect upto date result * + * return - true if trace is initialized and has valid data. False dp trace + * doesn't have valid result. + */ +bool dc_dp_trace_is_initialized(struct dc_link *link); + +/* Query a dp trace flag to indicate if the current dp trace data has been + * logged before + */ +bool dc_dp_trace_is_logged(struct dc_link *link, + bool in_detection); + +/* Set dp trace flag to indicate whether DM has already logged the current dp + * trace data. DM can set is_logged to true upon logging and check + * dc_dp_trace_is_logged before logging to avoid logging the same result twice. + */ +void dc_dp_trace_set_is_logged_flag(struct dc_link *link, + bool in_detection, + bool is_logged); + +/* Obtain driver time stamp for last dp link training end. The time stamp is + * formatted based on dm_get_timestamp DM function. + * @in_detection - true to get link training end time stamp of last link + * training in detection sequence. false to get link training end time stamp + * of last link training in commit (dpms) sequence + */ +unsigned long long dc_dp_trace_get_lt_end_timestamp(struct dc_link *link, + bool in_detection); + +/* Get how many link training attempts dc has done with latest sequence. + * @in_detection - true to get link training count of last link + * training in detection sequence. false to get link training count of last link + * training in commit (dpms) sequence + */ +struct dp_trace_lt_counts *dc_dp_trace_get_lt_counts(struct dc_link *link, + bool in_detection); + +/* Get how many link loss has happened since last link training attempts */ +unsigned int dc_dp_trace_get_link_loss_count(struct dc_link *link); + +/* + * USB4 DPIA BW ALLOCATION PUBLIC FUNCTIONS + */ +/* + * Send a request from DP-Tx requesting to allocate BW remotely after + * allocating it locally. This will get processed by CM and a CB function + * will be called. + * + * @link: pointer to the dc_link struct instance + * @req_bw: The requested bw in Kbyte to allocated + * + * return: none + */ +void dc_link_set_usb4_req_bw_req(struct dc_link *link, int req_bw); + +/* + * Handle function for when the status of the Request above is complete. + * We will find out the result of allocating on CM and update structs. + * + * @link: pointer to the dc_link struct instance + * @bw: Allocated or Estimated BW depending on the result + * @result: Response type + * + * return: none + */ +void dc_link_handle_usb4_bw_alloc_response(struct dc_link *link, + uint8_t bw, uint8_t result); + +/* + * Handle the USB4 BW Allocation related functionality here: + * Plug => Try to allocate max bw from timing parameters supported by the sink + * Unplug => de-allocate bw + * + * @link: pointer to the dc_link struct instance + * @peak_bw: Peak bw used by the link/sink + * + * return: allocated bw else return 0 + */ +int dc_link_dp_dpia_handle_usb4_bandwidth_allocation_for_link( + struct dc_link *link, int peak_bw); + /* Sink Interfaces - A sink corresponds to a display output device */ struct dc_container_id { 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 809a1851f196..4bccce94d83b 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h @@ -1261,4 +1261,111 @@ union dpcd_sink_ext_caps { } bits; uint8_t raw; }; + +enum dc_link_fec_state { + dc_link_fec_not_ready, + dc_link_fec_ready, + dc_link_fec_enabled +}; + +union dpcd_psr_configuration { + struct { + unsigned char ENABLE : 1; + unsigned char TRANSMITTER_ACTIVE_IN_PSR : 1; + unsigned char CRC_VERIFICATION : 1; + unsigned char FRAME_CAPTURE_INDICATION : 1; + /* For eDP 1.4, PSR v2*/ + unsigned char LINE_CAPTURE_INDICATION : 1; + /* For eDP 1.4, PSR v2*/ + unsigned char IRQ_HPD_WITH_CRC_ERROR : 1; + unsigned char ENABLE_PSR2 : 1; + unsigned char EARLY_TRANSPORT_ENABLE : 1; + } bits; + unsigned char raw; +}; + +union dpcd_alpm_configuration { + struct { + unsigned char ENABLE : 1; + unsigned char IRQ_HPD_ENABLE : 1; + unsigned char RESERVED : 6; + } bits; + unsigned char raw; +}; + +union dpcd_sink_active_vtotal_control_mode { + struct { + unsigned char ENABLE : 1; + unsigned char RESERVED : 7; + } bits; + unsigned char raw; +}; + +union psr_error_status { + struct { + unsigned char LINK_CRC_ERROR :1; + unsigned char RFB_STORAGE_ERROR :1; + unsigned char VSC_SDP_ERROR :1; + unsigned char RESERVED :5; + } bits; + unsigned char raw; +}; + +union psr_sink_psr_status { + struct { + unsigned char SINK_SELF_REFRESH_STATUS :3; + unsigned char RESERVED :5; + } bits; + unsigned char raw; +}; + +struct edp_trace_power_timestamps { + uint64_t poweroff; + uint64_t poweron; +}; + +struct dp_trace_lt_counts { + unsigned int total; + unsigned int fail; +}; + +enum link_training_result { + LINK_TRAINING_SUCCESS, + LINK_TRAINING_CR_FAIL_LANE0, + LINK_TRAINING_CR_FAIL_LANE1, + LINK_TRAINING_CR_FAIL_LANE23, + /* CR DONE bit is cleared during EQ step */ + LINK_TRAINING_EQ_FAIL_CR, + /* CR DONE bit is cleared but LANE0_CR_DONE is set during EQ step */ + LINK_TRAINING_EQ_FAIL_CR_PARTIAL, + /* other failure during EQ step */ + LINK_TRAINING_EQ_FAIL_EQ, + LINK_TRAINING_LQA_FAIL, + /* one of the CR,EQ or symbol lock is dropped */ + LINK_TRAINING_LINK_LOSS, + /* Abort link training (because sink unplugged) */ + LINK_TRAINING_ABORT, + DP_128b_132b_LT_FAILED, + DP_128b_132b_MAX_LOOP_COUNT_REACHED, + DP_128b_132b_CHANNEL_EQ_DONE_TIMEOUT, + DP_128b_132b_CDS_DONE_TIMEOUT, +}; + +struct dp_trace_lt { + struct dp_trace_lt_counts counts; + struct dp_trace_timestamps { + unsigned long long start; + unsigned long long end; + } timestamps; + enum link_training_result result; + bool is_logged; +}; + +struct dp_trace { + struct dp_trace_lt detect_lt_trace; + struct dp_trace_lt commit_lt_trace; + unsigned int link_loss_count; + bool is_initialized; + struct edp_trace_power_timestamps edp_trace_power_timestamps; +}; #endif /* DC_DP_TYPES_H */ 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 cc3d6fb39364..a583a72845fe 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -1085,5 +1085,19 @@ struct tg_color { uint16_t color_b_cb; }; +enum symclk_state { + SYMCLK_OFF_TX_OFF, + SYMCLK_ON_TX_ON, + SYMCLK_ON_TX_OFF, +}; + +struct phy_state { + struct { + uint8_t otg : 1; + uint8_t reserved : 7; + } symclk_ref_cnts; + enum symclk_state symclk_state; +}; + #endif /* DC_HW_TYPES_H */ diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 27d0242d6cbd..f28b8597cc1e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -38,6 +38,7 @@ #include "dc_hw_types.h" #include "dal_types.h" #include "grph_object_defs.h" +#include "grph_object_ctrl_defs.h" #ifdef CONFIG_DRM_AMD_DC_HDCP #include "dm_cp_psp.h" @@ -982,4 +983,107 @@ struct hdcp_caps { union hdcp_bcaps bcaps; }; #endif + +/* DP MST stream allocation (payload bandwidth number) */ +struct link_mst_stream_allocation { + /* DIG front */ + const struct stream_encoder *stream_enc; + /* HPO DP Stream Encoder */ + const struct hpo_dp_stream_encoder *hpo_dp_stream_enc; + /* associate DRM payload table with DC stream encoder */ + uint8_t vcp_id; + /* number of slots required for the DP stream in transport packet */ + uint8_t slot_count; +}; + +#define MAX_CONTROLLER_NUM 6 + +/* DP MST stream allocation table */ +struct link_mst_stream_allocation_table { + /* number of DP video streams */ + int stream_count; + /* array of stream allocations */ + struct link_mst_stream_allocation stream_allocations[MAX_CONTROLLER_NUM]; +}; + +/* PSR feature flags */ +struct psr_settings { + bool psr_feature_enabled; // PSR is supported by sink + bool psr_allow_active; // PSR is currently active + enum dc_psr_version psr_version; // Internal PSR version, determined based on DPCD + bool psr_vtotal_control_support; // Vtotal control is supported by sink + unsigned long long psr_dirty_rects_change_timestamp_ns; // for delay of enabling PSR-SU + + /* These parameters are calculated in Driver, + * based on display timing and Sink capabilities. + * If VBLANK region is too small and Sink takes a long time + * to set up RFB, it may take an extra frame to enter PSR state. + */ + bool psr_frame_capture_indication_req; + unsigned int psr_sdp_transmit_line_num_deadline; + uint8_t force_ffu_mode; + unsigned int psr_power_opt; +}; + +/* To split out "global" and "per-panel" config settings. + * Add a struct dc_panel_config under dc_link + */ +struct dc_panel_config { + /* extra panel power sequence parameters */ + struct pps { + unsigned int extra_t3_ms; + unsigned int extra_t7_ms; + unsigned int extra_delay_backlight_off; + unsigned int extra_post_t7_ms; + unsigned int extra_pre_t11_ms; + unsigned int extra_t12_ms; + unsigned int extra_post_OUI_ms; + } pps; + /* nit brightness */ + struct nits_brightness { + unsigned int peak; /* nits */ + unsigned int max_avg; /* nits */ + unsigned int min; /* 1/10000 nits */ + unsigned int max_nonboost_brightness_millinits; + unsigned int min_brightness_millinits; + } nits_brightness; + /* PSR */ + struct psr { + bool disable_psr; + bool disallow_psrsu; + bool rc_disable; + bool rc_allow_static_screen; + bool rc_allow_fullscreen_VPB; + } psr; + /* ABM */ + struct varib { + unsigned int varibright_feature_enable; + unsigned int def_varibright_level; + unsigned int abm_config_setting; + } varib; + /* edp DSC */ + struct dsc { + bool disable_dsc_edp; + unsigned int force_dsc_edp_policy; + } dsc; + /* eDP ILR */ + struct ilr { + bool optimize_edp_link_rate; /* eDP ILR */ + } ilr; +}; + +/* + * USB4 DPIA BW ALLOCATION STRUCTS + */ +struct dc_dpia_bw_alloc { + int sink_verified_bw; // The Verified BW that sink can allocated and use that has been verified already + int sink_allocated_bw; // The Actual Allocated BW that sink currently allocated + int sink_max_bw; // The Max BW that sink can require/support + int estimated_bw; // The estimated available BW for this DPIA + int bw_granularity; // BW Granularity + bool bw_alloc_enabled; // The BW Alloc Mode Support is turned ON for all 3: DP-Tx & Dpia & CM + bool response_ready; // Response ready from the CM side +}; + +#define MAX_SINKS_PER_LINK 4 #endif /* DC_TYPES_H_ */ 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 fb0dec4ed3a6..9fc48208c2e4 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c @@ -148,7 +148,7 @@ static bool dmub_abm_set_level(struct abm *abm, uint32_t level) int edp_num; uint8_t panel_mask = 0; - get_edp_links(dc->dc, edp_links, &edp_num); + dc_get_edp_links(dc->dc, edp_links, &edp_num); for (i = 0; i < edp_num; i++) { if (edp_links[i]->link_status.link_active) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h index 74005b9d352a..289e42070ece 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.h @@ -26,8 +26,9 @@ #ifndef _DMUB_PSR_H_ #define _DMUB_PSR_H_ -#include "os_types.h" -#include "dc_link.h" +#include "dc_types.h" +struct dc_link; +struct dmub_psr_funcs; struct dmub_psr { struct dc_context *ctx; 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 0d4d3d586166..cb3bb5402c52 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 @@ -1739,7 +1739,7 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context) get_edp_links_with_sink(dc, edp_links_with_sink, &edp_with_sink_num); - get_edp_links(dc, edp_links, &edp_num); + dc_get_edp_links(dc, edp_links, &edp_num); if (hws->funcs.init_pipes) hws->funcs.init_pipes(dc, context); 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 a1a29c508394..5b34066ffcf6 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 @@ -1638,7 +1638,7 @@ void dcn10_power_down_on_boot(struct dc *dc) int edp_num; int i = 0; - get_edp_links(dc, edp_links, &edp_num); + dc_get_edp_links(dc, edp_links, &edp_num); if (edp_num) edp_link = edp_links[0]; diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c index 5f9079d3943a..9d08127d209b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c @@ -28,6 +28,7 @@ #include "dcn30_dio_stream_encoder.h" #include "reg_helper.h" #include "hw_shared.h" +#include "dc.h" #include "core_types.h" #include 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 1d243c549562..f8733ff6970e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c @@ -559,7 +559,7 @@ void dcn30_init_hw(struct dc *dc) struct dc_link *edp_links[MAX_NUM_EDP]; struct dc_link *edp_link = NULL; - get_edp_links(dc, edp_links, &edp_num); + dc_get_edp_links(dc, edp_links, &edp_num); if (edp_num) edp_link = edp_links[0]; if (edp_link && edp_link->link_enc->funcs->is_dig_enabled && diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.c index 0b317ed31f91..5b7ad38f85e0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.c @@ -26,7 +26,6 @@ #include "dc_bios_types.h" #include "dcn31_hpo_dp_link_encoder.h" #include "reg_helper.h" -#include "dc_link.h" #include "stream_encoder.h" #define DC_LOGGER \ diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c index d76f55a12eb4..0278bae50a9d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c @@ -26,7 +26,7 @@ #include "dc_bios_types.h" #include "dcn31_hpo_dp_stream_encoder.h" #include "reg_helper.h" -#include "dc_link.h" +#include "dc.h" #define DC_LOGGER \ enc3->base.ctx->logger diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hpo_dp_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hpo_dp_link_encoder.c index 4dbad8d4b4fc..8af01f579690 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hpo_dp_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hpo_dp_link_encoder.c @@ -26,7 +26,6 @@ #include "dcn31/dcn31_hpo_dp_link_encoder.h" #include "dcn32_hpo_dp_link_encoder.h" #include "reg_helper.h" -#include "dc_link.h" #include "stream_encoder.h" #define DC_LOGGER \ diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c index f667f2a6f686..4ba7a10dd7ec 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c @@ -837,7 +837,7 @@ void dcn32_init_hw(struct dc *dc) struct dc_link *edp_links[MAX_NUM_EDP]; struct dc_link *edp_link; - get_edp_links(dc, edp_links, &edp_num); + dc_get_edp_links(dc, edp_links, &edp_num); if (edp_num) { for (i = 0; i < edp_num; i++) { edp_link = edp_links[i]; 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 c3d75e56410c..899105da0433 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 @@ -25,7 +25,6 @@ #ifdef CONFIG_DRM_AMD_DC_DCN #include "dc.h" -#include "dc_link.h" #include "../display_mode_lib.h" #include "display_mode_vba_30.h" #include "../dml_inline_defs.h" diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c index 27f488405335..2b57f5b2362a 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c @@ -24,7 +24,6 @@ */ #include "dc.h" -#include "dc_link.h" #include "../display_mode_lib.h" #include "../dcn30/display_mode_vba_30.h" #include "display_mode_vba_31.h" diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c b/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c index c843b394aeb4..461ab6d2030e 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c @@ -27,7 +27,6 @@ #define UNIT_TEST 0 #if !UNIT_TEST #include "dc.h" -#include "dc_link.h" #endif #include "../display_mode_lib.h" #include "display_mode_vba_314.h" diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c index 3b2a014ccf8f..f2499811e269 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c @@ -24,7 +24,6 @@ */ #include "dc.h" -#include "dc_link.h" #include "../display_mode_lib.h" #include "display_mode_vba_32.h" #include "../dml_inline_defs.h" diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h index a819f0f97c5f..b95ae9596c3b 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h @@ -275,20 +275,6 @@ enum dc_lut_mode { LUT_RAM_B }; -enum symclk_state { - SYMCLK_OFF_TX_OFF, - SYMCLK_ON_TX_ON, - SYMCLK_ON_TX_OFF, -}; - -struct phy_state { - struct { - uint8_t otg : 1; - uint8_t reserved : 7; - } symclk_ref_cnts; - enum symclk_state symclk_state; -}; - /** * speakersToChannels * 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 ec572a9e4054..dbe7afa9d3a2 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 @@ -75,58 +75,6 @@ struct encoder_feature_support { bool fec_supported; }; -union dpcd_psr_configuration { - struct { - unsigned char ENABLE : 1; - unsigned char TRANSMITTER_ACTIVE_IN_PSR : 1; - unsigned char CRC_VERIFICATION : 1; - unsigned char FRAME_CAPTURE_INDICATION : 1; - /* For eDP 1.4, PSR v2*/ - unsigned char LINE_CAPTURE_INDICATION : 1; - /* For eDP 1.4, PSR v2*/ - unsigned char IRQ_HPD_WITH_CRC_ERROR : 1; - unsigned char ENABLE_PSR2 : 1; - /* For eDP 1.5, PSR v2 w/ early transport */ - unsigned char EARLY_TRANSPORT_ENABLE : 1; - } bits; - unsigned char raw; -}; - -union dpcd_alpm_configuration { - struct { - unsigned char ENABLE : 1; - unsigned char IRQ_HPD_ENABLE : 1; - unsigned char RESERVED : 6; - } bits; - unsigned char raw; -}; - -union dpcd_sink_active_vtotal_control_mode { - struct { - unsigned char ENABLE : 1; - unsigned char RESERVED : 7; - } bits; - unsigned char raw; -}; - -union psr_error_status { - struct { - unsigned char LINK_CRC_ERROR :1; - unsigned char RFB_STORAGE_ERROR :1; - unsigned char VSC_SDP_ERROR :1; - unsigned char RESERVED :5; - } bits; - unsigned char raw; -}; - -union psr_sink_psr_status { - struct { - unsigned char SINK_SELF_REFRESH_STATUS :3; - unsigned char RESERVED :5; - } bits; - unsigned char raw; -}; - struct link_encoder { const struct link_encoder_funcs *funcs; int32_t aux_channel_offset; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h index bb5ad70d4266..c4fbbf08ef86 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h @@ -30,7 +30,6 @@ #include "audio_types.h" #include "hw_shared.h" -#include "dc_link.h" struct dc_bios; struct dc_context; diff --git a/drivers/gpu/drm/amd/display/dc/inc/link.h b/drivers/gpu/drm/amd/display/dc/inc/link.h index e70fa0059223..6a346a41f07b 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/link.h +++ b/drivers/gpu/drm/amd/display/dc/inc/link.h @@ -38,7 +38,6 @@ * into this file and prefix it with "link_". */ #include "core_types.h" -#include "dc_link.h" struct link_init_data { const struct dc *dc; diff --git a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c index 942300e0bd92..7f36d733bfca 100644 --- a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c +++ b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c @@ -1027,20 +1027,3 @@ void dc_link_set_preferred_training_settings(struct dc *dc, if (skip_immediate_retrain == false) dc_link_set_preferred_link_settings(dc, &link->preferred_link_setting, link); } - -void dc_link_set_test_pattern(struct dc_link *link, - enum dp_test_pattern test_pattern, - enum dp_test_pattern_color_space test_pattern_color_space, - const struct link_training_settings *p_link_settings, - const unsigned char *p_custom_pattern, - unsigned int cust_pattern_size) -{ - if (link != NULL) - dc_link_dp_set_test_pattern( - link, - test_pattern, - test_pattern_color_space, - p_link_settings, - p_custom_pattern, - cust_pattern_size); -} diff --git a/drivers/gpu/drm/amd/display/dc/link/link_detection.c b/drivers/gpu/drm/amd/display/dc/link/link_detection.c index 5394d8a6087a..393bdefba0ba 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_detection.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_detection.c @@ -1321,3 +1321,102 @@ const struct dc_link_status *link_get_status(const struct dc_link *link) return &link->link_status; } + +static bool link_add_remote_sink_helper(struct dc_link *dc_link, struct dc_sink *sink) +{ + if (dc_link->sink_count >= MAX_SINKS_PER_LINK) { + BREAK_TO_DEBUGGER(); + return false; + } + + dc_sink_retain(sink); + + dc_link->remote_sinks[dc_link->sink_count] = sink; + dc_link->sink_count++; + + return true; +} + +struct dc_sink *dc_link_add_remote_sink( + struct dc_link *link, + const uint8_t *edid, + int len, + struct dc_sink_init_data *init_data) +{ + struct dc_sink *dc_sink; + enum dc_edid_status edid_status; + + if (len > DC_MAX_EDID_BUFFER_SIZE) { + dm_error("Max EDID buffer size breached!\n"); + return NULL; + } + + if (!init_data) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + if (!init_data->link) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dc_sink = dc_sink_create(init_data); + + if (!dc_sink) + return NULL; + + memmove(dc_sink->dc_edid.raw_edid, edid, len); + dc_sink->dc_edid.length = len; + + if (!link_add_remote_sink_helper( + link, + dc_sink)) + goto fail_add_sink; + + edid_status = dm_helpers_parse_edid_caps( + link, + &dc_sink->dc_edid, + &dc_sink->edid_caps); + + /* + * Treat device as no EDID device if EDID + * parsing fails + */ + if (edid_status != EDID_OK && edid_status != EDID_PARTIAL_VALID) { + dc_sink->dc_edid.length = 0; + dm_error("Bad EDID, status%d!\n", edid_status); + } + + return dc_sink; + +fail_add_sink: + dc_sink_release(dc_sink); + return NULL; +} + +void dc_link_remove_remote_sink(struct dc_link *link, struct dc_sink *sink) +{ + int i; + + if (!link->sink_count) { + BREAK_TO_DEBUGGER(); + return; + } + + for (i = 0; i < link->sink_count; i++) { + if (link->remote_sinks[i] == sink) { + dc_sink_release(sink); + link->remote_sinks[i] = NULL; + + /* shrink array to remove empty place */ + while (i < link->sink_count - 1) { + link->remote_sinks[i] = link->remote_sinks[i+1]; + i++; + } + link->remote_sinks[i] = NULL; + link->sink_count--; + return; + } + } +} diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia.c index 32f48a48e9dd..cbfa9343ffaf 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia.c @@ -26,7 +26,6 @@ #include "dc.h" #include "inc/core_status.h" -#include "dc_link.h" #include "dpcd_defs.h" #include "link_dp_dpia.h" diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.c index 72ff0ae44d01..7b32fd010f11 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.c @@ -27,7 +27,6 @@ // USB4 DPIA BANDWIDTH ALLOCATION LOGIC /*********************************************************************/ #include "dc.h" -#include "dc_link.h" #include "link_dp_dpia_bw.h" #include "drm_dp_helper_dc.h" #include "link_dpcd.h" diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c index 9715fa754d56..7711fda42261 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c @@ -29,7 +29,6 @@ #include "link_dp_training_dpia.h" #include "dc.h" #include "inc/core_status.h" -#include "dc_link.h" #include "dpcd_defs.h" #include "link_dp_dpia.h" diff --git a/drivers/gpu/drm/amd/display/include/link_service_types.h b/drivers/gpu/drm/amd/display/include/link_service_types.h index 18b9173d5a96..cd870af5fd25 100644 --- a/drivers/gpu/drm/amd/display/include/link_service_types.h +++ b/drivers/gpu/drm/amd/display/include/link_service_types.h @@ -34,10 +34,6 @@ struct ddc; struct irq_manager; -enum { - MAX_CONTROLLER_NUM = 6 -}; - enum dp_power_state { DP_POWER_STATE_D0 = 1, DP_POWER_STATE_D3 @@ -60,28 +56,6 @@ enum { DATA_EFFICIENCY_128b_132b_x10000 = 9646, /* 96.71% data efficiency x 99.75% downspread factor */ }; -enum link_training_result { - LINK_TRAINING_SUCCESS, - LINK_TRAINING_CR_FAIL_LANE0, - LINK_TRAINING_CR_FAIL_LANE1, - LINK_TRAINING_CR_FAIL_LANE23, - /* CR DONE bit is cleared during EQ step */ - LINK_TRAINING_EQ_FAIL_CR, - /* CR DONE bit is cleared but LANE0_CR_DONE is set during EQ step */ - LINK_TRAINING_EQ_FAIL_CR_PARTIAL, - /* other failure during EQ step */ - LINK_TRAINING_EQ_FAIL_EQ, - LINK_TRAINING_LQA_FAIL, - /* one of the CR,EQ or symbol lock is dropped */ - LINK_TRAINING_LINK_LOSS, - /* Abort link training (because sink unplugged) */ - LINK_TRAINING_ABORT, - DP_128b_132b_LT_FAILED, - DP_128b_132b_MAX_LOOP_COUNT_REACHED, - DP_128b_132b_CHANNEL_EQ_DONE_TIMEOUT, - DP_128b_132b_CDS_DONE_TIMEOUT, -}; - enum lttpr_mode { LTTPR_MODE_UNKNOWN, LTTPR_MODE_NON_LTTPR, -- cgit v1.2.3 From de534c1cb0313a070f45938a53b53927cd34e5b9 Mon Sep 17 00:00:00 2001 From: Mike Hsieh Date: Tue, 10 Jan 2023 10:52:03 +0800 Subject: drm/amd/display: Add height granularity limitation for dsc slice height calculation [WHY] eDP add new limitation for Y granularity for selected update feature. DSC does not include this limitation while calculating slice height. [HOW] Add new limitation while looking for DSC slice height. Reviewed-by: Cruise Hung Acked-by: Qingqing Zhuo Signed-off-by: Mike Hsieh Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 20 +++++++------ .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 16 +++++++---- drivers/gpu/drm/amd/display/dc/dc_dsc.h | 11 ++++++-- drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c | 33 ++++++++++++++-------- 4 files changed, 52 insertions(+), 28 deletions(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 824cfc4a0293..7f627ab43a29 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -5786,6 +5786,10 @@ static void apply_dsc_policy_for_edp(struct amdgpu_dm_connector *aconnector, struct dc *dc = sink->ctx->dc; struct dc_dsc_bw_range bw_range = {0}; struct dc_dsc_config dsc_cfg = {0}; + struct dc_dsc_config_options dsc_options = {0}; + + dc_dsc_get_default_config_option(dc, &dsc_options); + dsc_options.max_target_bpp_limit_override_x16 = max_dsc_target_bpp_limit_override * 16; verified_link_cap = dc_link_get_link_cap(stream->link); link_bw_in_kbps = dc_link_bandwidth_kbps(stream->link, verified_link_cap); @@ -5808,8 +5812,7 @@ static void apply_dsc_policy_for_edp(struct amdgpu_dm_connector *aconnector, if (bw_range.max_kbps < link_bw_in_kbps) { if (dc_dsc_compute_config(dc->res_pool->dscs[0], dsc_caps, - dc->debug.dsc_min_slice_height_override, - max_dsc_target_bpp_limit_override, + &dsc_options, 0, &stream->timing, &dsc_cfg)) { @@ -5823,8 +5826,7 @@ static void apply_dsc_policy_for_edp(struct amdgpu_dm_connector *aconnector, if (dc_dsc_compute_config(dc->res_pool->dscs[0], dsc_caps, - dc->debug.dsc_min_slice_height_override, - max_dsc_target_bpp_limit_override, + &dsc_options, link_bw_in_kbps, &stream->timing, &dsc_cfg)) { @@ -5845,6 +5847,10 @@ static void apply_dsc_policy_for_stream(struct amdgpu_dm_connector *aconnector, u32 dsc_max_supported_bw_in_kbps; u32 max_dsc_target_bpp_limit_override = drm_connector->display_info.max_dsc_bpp; + struct dc_dsc_config_options dsc_options = {0}; + + dc_dsc_get_default_config_option(dc, &dsc_options); + dsc_options.max_target_bpp_limit_override_x16 = max_dsc_target_bpp_limit_override * 16; link_bandwidth_kbps = dc_link_bandwidth_kbps(aconnector->dc_link, dc_link_get_link_cap(aconnector->dc_link)); @@ -5863,8 +5869,7 @@ static void apply_dsc_policy_for_stream(struct amdgpu_dm_connector *aconnector, if (sink->link->dpcd_caps.dongle_type == DISPLAY_DONGLE_NONE) { if (dc_dsc_compute_config(aconnector->dc_link->ctx->dc->res_pool->dscs[0], dsc_caps, - aconnector->dc_link->ctx->dc->debug.dsc_min_slice_height_override, - max_dsc_target_bpp_limit_override, + &dsc_options, link_bandwidth_kbps, &stream->timing, &stream->timing.dsc_cfg)) { @@ -5881,8 +5886,7 @@ static void apply_dsc_policy_for_stream(struct amdgpu_dm_connector *aconnector, dsc_max_supported_bw_in_kbps > 0) if (dc_dsc_compute_config(aconnector->dc_link->ctx->dc->res_pool->dscs[0], dsc_caps, - aconnector->dc_link->ctx->dc->debug.dsc_min_slice_height_override, - max_dsc_target_bpp_limit_override, + &dsc_options, dsc_max_supported_bw_in_kbps, &stream->timing, &stream->timing.dsc_cfg)) { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index e25e1b2bf194..e10ed2935971 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -678,16 +678,19 @@ static void set_dsc_configs_from_fairness_vars(struct dsc_mst_fairness_params *p { struct drm_connector *drm_connector; int i; + struct dc_dsc_config_options dsc_options = {0}; for (i = 0; i < count; i++) { drm_connector = ¶ms[i].aconnector->base; + dc_dsc_get_default_config_option(params[i].sink->ctx->dc, &dsc_options); + dsc_options.max_target_bpp_limit_override_x16 = drm_connector->display_info.max_dsc_bpp * 16; + memset(¶ms[i].timing->dsc_cfg, 0, sizeof(params[i].timing->dsc_cfg)); if (vars[i + k].dsc_enabled && dc_dsc_compute_config( params[i].sink->ctx->dc->res_pool->dscs[0], ¶ms[i].sink->dsc_caps.dsc_dec_caps, - params[i].sink->ctx->dc->debug.dsc_min_slice_height_override, - drm_connector->display_info.max_dsc_bpp, + &dsc_options, 0, params[i].timing, ¶ms[i].timing->dsc_cfg)) { @@ -730,15 +733,16 @@ static int bpp_x16_from_pbn(struct dsc_mst_fairness_params param, int pbn) u64 kbps; struct drm_connector *drm_connector = ¶m.aconnector->base; - uint32_t max_dsc_target_bpp_limit_override = - drm_connector->display_info.max_dsc_bpp; + struct dc_dsc_config_options dsc_options = {0}; + + dc_dsc_get_default_config_option(param.sink->ctx->dc, &dsc_options); + dsc_options.max_target_bpp_limit_override_x16 = drm_connector->display_info.max_dsc_bpp * 16; kbps = div_u64((u64)pbn * 994 * 8 * 54, 64); dc_dsc_compute_config( param.sink->ctx->dc->res_pool->dscs[0], ¶m.sink->dsc_caps.dsc_dec_caps, - param.sink->ctx->dc->debug.dsc_min_slice_height_override, - max_dsc_target_bpp_limit_override, + &dsc_options, (int) kbps, param.timing, &dsc_config); return dsc_config.bits_per_pixel; diff --git a/drivers/gpu/drm/amd/display/dc/dc_dsc.h b/drivers/gpu/drm/amd/display/dc/dc_dsc.h index 684713b2cff7..81e62a630d78 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dsc.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dsc.h @@ -54,6 +54,12 @@ struct dc_dsc_policy { bool enable_dsc_when_not_needed; }; +struct dc_dsc_config_options { + uint32_t dsc_min_slice_height_override; + uint32_t max_target_bpp_limit_override_x16; + uint32_t slight_height_granularity; +}; + bool dc_dsc_parse_dsc_dpcd(const struct dc *dc, const uint8_t *dpcd_dsc_basic_data, const uint8_t *dpcd_dsc_ext_data, @@ -71,8 +77,7 @@ bool dc_dsc_compute_bandwidth_range( bool dc_dsc_compute_config( const struct display_stream_compressor *dsc, const struct dsc_dec_dpcd_caps *dsc_sink_caps, - uint32_t dsc_min_slice_height_override, - uint32_t max_target_bpp_limit_override, + const struct dc_dsc_config_options *options, uint32_t target_bandwidth_kbps, const struct dc_crtc_timing *timing, struct dc_dsc_config *dsc_cfg); @@ -100,4 +105,6 @@ void dc_dsc_policy_set_enable_dsc_when_not_needed(bool enable); void dc_dsc_policy_set_disable_dsc_stream_overhead(bool disable); +void dc_dsc_get_default_config_option(const struct dc *dc, struct dc_dsc_config_options *options); + #endif 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 d52cbc0e9b67..8b5663853efb 100644 --- a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c +++ b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c @@ -79,8 +79,7 @@ static bool setup_dsc_config( const struct dsc_enc_caps *dsc_enc_caps, int target_bandwidth_kbps, const struct dc_crtc_timing *timing, - int min_slice_height_override, - int max_dsc_target_bpp_limit_override_x16, + const struct dc_dsc_config_options *options, struct dc_dsc_config *dsc_cfg); static bool dsc_buff_block_size_from_dpcd(int dpcd_buff_block_size, int *buff_block_size) @@ -352,6 +351,11 @@ bool dc_dsc_compute_bandwidth_range( struct dsc_enc_caps dsc_enc_caps; struct dsc_enc_caps dsc_common_caps; struct dc_dsc_config config; + struct dc_dsc_config_options options = {0}; + + options.dsc_min_slice_height_override = dsc_min_slice_height_override; + options.max_target_bpp_limit_override_x16 = max_bpp_x16; + options.slight_height_granularity = 1; get_dsc_enc_caps(dsc, &dsc_enc_caps, timing->pix_clk_100hz); @@ -360,7 +364,7 @@ bool dc_dsc_compute_bandwidth_range( if (is_dsc_possible) is_dsc_possible = setup_dsc_config(dsc_sink_caps, &dsc_enc_caps, 0, timing, - dsc_min_slice_height_override, max_bpp_x16, &config); + &options, &config); if (is_dsc_possible) is_dsc_possible = decide_dsc_bandwidth_range(min_bpp_x16, max_bpp_x16, @@ -740,8 +744,7 @@ static bool setup_dsc_config( const struct dsc_enc_caps *dsc_enc_caps, int target_bandwidth_kbps, const struct dc_crtc_timing *timing, - int min_slice_height_override, - int max_dsc_target_bpp_limit_override_x16, + const struct dc_dsc_config_options *options, struct dc_dsc_config *dsc_cfg) { struct dsc_enc_caps dsc_common_caps; @@ -760,7 +763,7 @@ static bool setup_dsc_config( memset(dsc_cfg, 0, sizeof(struct dc_dsc_config)); - dc_dsc_get_policy_for_timing(timing, max_dsc_target_bpp_limit_override_x16, &policy); + dc_dsc_get_policy_for_timing(timing, options->max_target_bpp_limit_override_x16, &policy); pic_width = timing->h_addressable + timing->h_border_left + timing->h_border_right; pic_height = timing->v_addressable + timing->v_border_top + timing->v_border_bottom; @@ -909,12 +912,13 @@ static bool setup_dsc_config( // Slice height (i.e. number of slices per column): start with policy and pick the first one that height is divisible by. // For 4:2:0 make sure the slice height is divisible by 2 as well. - if (min_slice_height_override == 0) + if (options->dsc_min_slice_height_override == 0) slice_height = min(policy.min_slice_height, pic_height); else - slice_height = min(min_slice_height_override, pic_height); + slice_height = min((int)(options->dsc_min_slice_height_override), pic_height); while (slice_height < pic_height && (pic_height % slice_height != 0 || + slice_height % options->slight_height_granularity != 0 || (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420 && slice_height % 2 != 0))) slice_height++; @@ -958,8 +962,7 @@ done: bool dc_dsc_compute_config( const struct display_stream_compressor *dsc, const struct dsc_dec_dpcd_caps *dsc_sink_caps, - uint32_t dsc_min_slice_height_override, - uint32_t max_target_bpp_limit_override, + const struct dc_dsc_config_options *options, uint32_t target_bandwidth_kbps, const struct dc_crtc_timing *timing, struct dc_dsc_config *dsc_cfg) @@ -971,8 +974,7 @@ bool dc_dsc_compute_config( is_dsc_possible = setup_dsc_config(dsc_sink_caps, &dsc_enc_caps, target_bandwidth_kbps, - timing, dsc_min_slice_height_override, - max_target_bpp_limit_override * 16, dsc_cfg); + timing, options, dsc_cfg); return is_dsc_possible; } @@ -1104,3 +1106,10 @@ void dc_dsc_policy_set_disable_dsc_stream_overhead(bool disable) { dsc_policy_disable_dsc_stream_overhead = disable; } + +void dc_dsc_get_default_config_option(const struct dc *dc, struct dc_dsc_config_options *options) +{ + options->dsc_min_slice_height_override = dc->debug.dsc_min_slice_height_override; + options->max_target_bpp_limit_override_x16 = 0; + options->slight_height_granularity = 1; +} -- cgit v1.2.3 From 1e88eb1b2c259994d034b0833cb489105a984ebb Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 13 Feb 2023 11:19:31 -0500 Subject: drm/amd/display: Drop CONFIG_DRM_AMD_DC_HDCP [Why & How] There is no reason we still need a config option for this. Reviewed-by: Wenjing Liu Acked-by: Qingqing Zhuo Signed-off-by: Harry Wentland Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/Kconfig | 6 -- drivers/gpu/drm/amd/display/Makefile | 4 - drivers/gpu/drm/amd/display/amdgpu_dm/Makefile | 2 - drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 24 ----- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 4 - .../drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 11 +-- .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 5 - drivers/gpu/drm/amd/display/dc/Makefile | 2 - drivers/gpu/drm/amd/display/dc/core/dc.c | 4 - .../gpu/drm/amd/display/dc/core/dc_link_exports.c | 2 - drivers/gpu/drm/amd/display/dc/dc.h | 15 +-- drivers/gpu/drm/amd/display/dc/dc_types.h | 6 -- .../display/dc/dcn32/dcn32_dio_stream_encoder.c | 2 - drivers/gpu/drm/amd/display/dc/hdcp/hdcp_msg.c | 2 +- drivers/gpu/drm/amd/display/dc/inc/core_types.h | 2 - drivers/gpu/drm/amd/display/dc/inc/link.h | 2 - .../gpu/drm/amd/display/dc/link/link_detection.c | 10 -- drivers/gpu/drm/amd/display/dc/link/link_dpms.c | 10 -- .../display/dc/link/protocols/link_dp_training.c | 2 - .../gpu/drm/amd/display/include/hdcp_msg_types.h | 103 +++++++++++++++++++++ drivers/gpu/drm/amd/display/include/hdcp_types.h | 103 --------------------- .../gpu/drm/amd/display/modules/hdcp/hdcp_log.h | 2 - 22 files changed, 106 insertions(+), 217 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/include/hdcp_msg_types.h delete mode 100644 drivers/gpu/drm/amd/display/include/hdcp_types.h (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/Kconfig b/drivers/gpu/drm/amd/display/Kconfig index 0c9bd0a53e60..578a8b547ddf 100644 --- a/drivers/gpu/drm/amd/display/Kconfig +++ b/drivers/gpu/drm/amd/display/Kconfig @@ -25,12 +25,6 @@ config DRM_AMD_DC_DCN help Raven, Navi, and newer family support for display engine -config DRM_AMD_DC_HDCP - bool "Enable HDCP support in DC" - depends on DRM_AMD_DC - help - Choose this option if you want to support HDCP authentication. - config DRM_AMD_DC_SI bool "AMD DC support for Southern Islands ASICs" depends on DRM_AMDGPU_SI diff --git a/drivers/gpu/drm/amd/display/Makefile b/drivers/gpu/drm/amd/display/Makefile index 2633de77de5e..0d610cb376bb 100644 --- a/drivers/gpu/drm/amd/display/Makefile +++ b/drivers/gpu/drm/amd/display/Makefile @@ -36,18 +36,14 @@ subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/info_packet subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/power subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dmub/inc -ifdef CONFIG_DRM_AMD_DC_HDCP subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/hdcp -endif #TODO: remove when Timing Sync feature is complete subdir-ccflags-y += -DBUILD_FEATURE_TIMING_SYNC=0 DAL_LIBS = amdgpu_dm dc modules/freesync modules/color modules/info_packet modules/power dmub/src -ifdef CONFIG_DRM_AMD_DC_HDCP DAL_LIBS += modules/hdcp -endif AMD_DAL = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DISPLAY_PATH)/,$(DAL_LIBS))) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile b/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile index 90fb0f3cdb6f..aef782ca3706 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile @@ -41,9 +41,7 @@ ifneq ($(CONFIG_DRM_AMD_DC),) AMDGPUDM += amdgpu_dm_services.o amdgpu_dm_helpers.o amdgpu_dm_pp_smu.o amdgpu_dm_psr.o endif -ifdef CONFIG_DRM_AMD_DC_HDCP AMDGPUDM += amdgpu_dm_hdcp.o -endif ifneq ($(CONFIG_DEBUG_FS),) AMDGPUDM += amdgpu_dm_crc.o amdgpu_dm_debugfs.o diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 7f627ab43a29..de270f0969f5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -52,10 +52,8 @@ #include "amdgpu_dm.h" #include "amdgpu_dm_plane.h" #include "amdgpu_dm_crtc.h" -#ifdef CONFIG_DRM_AMD_DC_HDCP #include "amdgpu_dm_hdcp.h" #include -#endif #include "amdgpu_pm.h" #include "amdgpu_atombios.h" @@ -1488,9 +1486,7 @@ static void retrieve_dmi_info(struct amdgpu_display_manager *dm) static int amdgpu_dm_init(struct amdgpu_device *adev) { struct dc_init_data init_data; -#ifdef CONFIG_DRM_AMD_DC_HDCP struct dc_callback_init init_params; -#endif int r; adev->dm.ddev = adev_to_drm(adev); @@ -1498,9 +1494,7 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) /* Zero all the fields */ memset(&init_data, 0, sizeof(init_data)); -#ifdef CONFIG_DRM_AMD_DC_HDCP memset(&init_params, 0, sizeof(init_params)); -#endif mutex_init(&adev->dm.dpia_aux_lock); mutex_init(&adev->dm.dc_lock); @@ -1726,7 +1720,6 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) DRM_ERROR("amdgpu: failed to initialize vblank_workqueue.\n"); } -#ifdef CONFIG_DRM_AMD_DC_HDCP if (adev->dm.dc->caps.max_links > 0 && adev->family >= AMDGPU_FAMILY_RV) { adev->dm.hdcp_workqueue = hdcp_create_workqueue(adev, &init_params.cp_psp, adev->dm.dc); @@ -1737,7 +1730,6 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) dc_init_callbacks(adev->dm.dc, &init_params); } -#endif #if defined(CONFIG_DRM_AMD_SECURE_DISPLAY) adev->dm.secure_display_ctxs = amdgpu_dm_crtc_secure_display_create_contexts(adev); if (!adev->dm.secure_display_ctxs) { @@ -1844,7 +1836,6 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev) adev->dm.secure_display_ctxs = NULL; } #endif -#ifdef CONFIG_DRM_AMD_DC_HDCP if (adev->dm.hdcp_workqueue) { hdcp_destroy(&adev->dev->kobj, adev->dm.hdcp_workqueue); adev->dm.hdcp_workqueue = NULL; @@ -1852,7 +1843,6 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev) if (adev->dm.dc) dc_deinit_callbacks(adev->dm.dc); -#endif dc_dmub_srv_destroy(&adev->dm.dc->ctx->dmub_srv); @@ -3111,11 +3101,9 @@ void amdgpu_dm_update_connector_after_detect( aconnector->edid = NULL; kfree(aconnector->timing_requested); aconnector->timing_requested = NULL; -#ifdef CONFIG_DRM_AMD_DC_HDCP /* Set CP to DESIRED if it was ENABLED, so we can re-enable it again on hotplug */ if (connector->state->content_protection == DRM_MODE_CONTENT_PROTECTION_ENABLED) connector->state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED; -#endif } mutex_unlock(&dev->mode_config.mutex); @@ -3132,9 +3120,7 @@ static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector) struct drm_device *dev = connector->dev; enum dc_connection_type new_connection_type = dc_connection_none; struct amdgpu_device *adev = drm_to_adev(dev); -#ifdef CONFIG_DRM_AMD_DC_HDCP struct dm_connector_state *dm_con_state = to_dm_connector_state(connector->state); -#endif bool ret = false; if (adev->dm.disable_hpd_irq) @@ -3146,12 +3132,10 @@ static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector) */ mutex_lock(&aconnector->hpd_lock); -#ifdef CONFIG_DRM_AMD_DC_HDCP if (adev->dm.hdcp_workqueue) { hdcp_reset_display(adev->dm.hdcp_workqueue, aconnector->dc_link->link_index); dm_con_state->update_hdcp = true; } -#endif if (aconnector->fake_enable) aconnector->fake_enable = false; @@ -3398,12 +3382,10 @@ out: } } } -#ifdef CONFIG_DRM_AMD_DC_HDCP if (hpd_irq_data.bytes.device_service_irq.bits.CP_IRQ) { if (adev->dm.hdcp_workqueue) hdcp_handle_cpirq(adev->dm.hdcp_workqueue, aconnector->base.index); } -#endif if (dc_link->type != dc_connection_mst_branch) drm_dp_cec_irq(&aconnector->dm_dp_aux.aux); @@ -7273,10 +7255,8 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm, if (!aconnector->mst_root) drm_connector_attach_vrr_capable_property(&aconnector->base); -#ifdef CONFIG_DRM_AMD_DC_HDCP if (adev->dm.hdcp_workqueue) drm_connector_attach_content_protection_property(&aconnector->base, true); -#endif } } @@ -7538,7 +7518,6 @@ is_scaling_state_different(const struct dm_connector_state *dm_state, return false; } -#ifdef CONFIG_DRM_AMD_DC_HDCP static bool is_content_protection_different(struct drm_crtc_state *new_crtc_state, struct drm_crtc_state *old_crtc_state, struct drm_connector_state *new_conn_state, @@ -7658,7 +7637,6 @@ static bool is_content_protection_different(struct drm_crtc_state *new_crtc_stat pr_debug("[HDCP_DM] DESIRED->ENABLED %s :false\n", __func__); return false; } -#endif static void remove_stream(struct amdgpu_device *adev, struct amdgpu_crtc *acrtc, @@ -8538,7 +8516,6 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) acrtc->otg_inst = status->primary_otg_inst; } } -#ifdef CONFIG_DRM_AMD_DC_HDCP for_each_oldnew_connector_in_state(state, connector, old_con_state, new_con_state, i) { struct dm_connector_state *dm_new_con_state = to_dm_connector_state(new_con_state); struct amdgpu_crtc *acrtc = to_amdgpu_crtc(dm_new_con_state->base.crtc); @@ -8649,7 +8626,6 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) new_con_state->hdcp_content_type, enable_encryption); } } -#endif /* Handle connector state changes */ for_each_oldnew_connector_in_state(state, connector, old_con_state, new_con_state, i) { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index ed5cbe9da40c..904f9e2fd35b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -461,9 +461,7 @@ struct amdgpu_display_manager { struct amdgpu_dm_backlight_caps backlight_caps[AMDGPU_DM_MAX_NUM_EDP]; struct mod_freesync *freesync_module; -#ifdef CONFIG_DRM_AMD_DC_HDCP struct hdcp_workqueue *hdcp_workqueue; -#endif /** * @vblank_control_workqueue: @@ -747,9 +745,7 @@ struct dm_connector_state { uint8_t underscan_hborder; bool underscan_enable; bool freesync_capable; -#ifdef CONFIG_DRM_AMD_DC_HDCP bool update_hdcp; -#endif uint8_t abm_level; int vcpi_slots; uint64_t pbn; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index 4a5dae578d97..abf7895d1608 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -947,7 +947,6 @@ static ssize_t dp_dsc_passthrough_set(struct file *f, const char __user *buf, return 0; } -#ifdef CONFIG_DRM_AMD_DC_HDCP /* * Returns the HDCP capability of the Display (1.4 for now). * @@ -984,7 +983,6 @@ static int hdcp_sink_capability_show(struct seq_file *m, void *data) return 0; } -#endif /* * Returns whether the connected display is internal and not hotpluggable. @@ -2593,9 +2591,7 @@ DEFINE_SHOW_ATTRIBUTE(dp_dsc_fec_support); DEFINE_SHOW_ATTRIBUTE(dmub_fw_state); DEFINE_SHOW_ATTRIBUTE(dmub_tracebuffer); DEFINE_SHOW_ATTRIBUTE(dp_lttpr_status); -#ifdef CONFIG_DRM_AMD_DC_HDCP DEFINE_SHOW_ATTRIBUTE(hdcp_sink_capability); -#endif DEFINE_SHOW_ATTRIBUTE(internal_display); DEFINE_SHOW_ATTRIBUTE(psr_capability); DEFINE_SHOW_ATTRIBUTE(dp_is_mst_connector); @@ -2726,9 +2722,7 @@ static const struct { {"phy_settings", &dp_phy_settings_debugfs_fop}, {"lttpr_status", &dp_lttpr_status_fops}, {"test_pattern", &dp_phy_test_pattern_fops}, -#ifdef CONFIG_DRM_AMD_DC_HDCP {"hdcp_sink_capability", &hdcp_sink_capability_fops}, -#endif {"sdp_message", &sdp_message_fops}, {"aux_dpcd_address", &dp_dpcd_address_debugfs_fops}, {"aux_dpcd_size", &dp_dpcd_size_debugfs_fops}, @@ -2749,14 +2743,13 @@ static const struct { {"is_dpia_link", &is_dpia_link_fops} }; -#ifdef CONFIG_DRM_AMD_DC_HDCP static const struct { char *name; const struct file_operations *fops; } hdmi_debugfs_entries[] = { {"hdcp_sink_capability", &hdcp_sink_capability_fops} }; -#endif + /* * Force YUV420 output if available from the given mode */ @@ -3015,7 +3008,6 @@ void connector_debugfs_init(struct amdgpu_dm_connector *connector) connector->debugfs_dpcd_address = 0; connector->debugfs_dpcd_size = 0; -#ifdef CONFIG_DRM_AMD_DC_HDCP if (connector->base.connector_type == DRM_MODE_CONNECTOR_HDMIA) { for (i = 0; i < ARRAY_SIZE(hdmi_debugfs_entries); i++) { debugfs_create_file(hdmi_debugfs_entries[i].name, @@ -3023,7 +3015,6 @@ void connector_debugfs_init(struct amdgpu_dm_connector *connector) hdmi_debugfs_entries[i].fops); } } -#endif } #ifdef CONFIG_DRM_AMD_SECURE_DISPLAY diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 19721941b069..1579c2839ce3 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -31,10 +31,7 @@ #include "amdgpu.h" #include "amdgpu_dm.h" #include "amdgpu_dm_mst_types.h" - -#ifdef CONFIG_DRM_AMD_DC_HDCP #include "amdgpu_dm_hdcp.h" -#endif #include "dc.h" #include "dm_helpers.h" @@ -362,7 +359,6 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector) * plugged back with same display index, its hdcp properties * will be retrieved from hdcp_work within dm_dp_mst_get_modes */ -#ifdef CONFIG_DRM_AMD_DC_HDCP if (aconnector->dc_sink && connector->state) { struct drm_device *dev = connector->dev; struct amdgpu_device *adev = drm_to_adev(dev); @@ -374,7 +370,6 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector) connector->state->content_protection = hdcp_w->content_protection[connector->index]; } -#endif if (aconnector->dc_sink) { amdgpu_dm_update_freesync_caps( diff --git a/drivers/gpu/drm/amd/display/dc/Makefile b/drivers/gpu/drm/amd/display/dc/Makefile index 94f156d57220..ba75e91ef62b 100644 --- a/drivers/gpu/drm/amd/display/dc/Makefile +++ b/drivers/gpu/drm/amd/display/dc/Makefile @@ -56,9 +56,7 @@ ifdef CONFIG_DRM_AMD_DC_SI DC_LIBS += dce60 endif -ifdef CONFIG_DRM_AMD_DC_HDCP DC_LIBS += hdcp -endif AMD_DC = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DISPLAY_PATH)/dc/,$(DC_LIBS))) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 9b821d78aaaa..8be7a1fc5295 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1377,16 +1377,12 @@ void dc_hardware_init(struct dc *dc) void dc_init_callbacks(struct dc *dc, const struct dc_callback_init *init_params) { -#ifdef CONFIG_DRM_AMD_DC_HDCP dc->ctx->cp_psp = init_params->cp_psp; -#endif } void dc_deinit_callbacks(struct dc *dc) { -#ifdef CONFIG_DRM_AMD_DC_HDCP memset(&dc->ctx->cp_psp, 0, sizeof(dc->ctx->cp_psp)); -#endif } void dc_destroy(struct dc **dc) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c index 862cb0f93b7d..565c62a272d6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c @@ -93,7 +93,6 @@ const struct dc_link_status *dc_link_get_status(const struct dc_link *link) { return link_get_status(link); } -#ifdef CONFIG_DRM_AMD_DC_HDCP /* return true if the connected receiver supports the hdcp version */ bool dc_link_is_hdcp14(struct dc_link *link, enum signal_type signal) @@ -105,7 +104,6 @@ bool dc_link_is_hdcp22(struct dc_link *link, enum signal_type signal) { return link_is_hdcp22(link, signal); } -#endif void dc_link_clear_dprx_states(struct dc_link *link) { diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index f1ea9031a191..ae9d31cf9a23 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -29,9 +29,7 @@ #include "dc_types.h" #include "grph_object_defs.h" #include "logger_types.h" -#if defined(CONFIG_DRM_AMD_DC_HDCP) -#include "hdcp_types.h" -#endif +#include "hdcp_msg_types.h" #include "gpio_types.h" #include "link_service_types.h" #include "grph_object_ctrl_defs.h" @@ -993,11 +991,7 @@ struct dc_init_data { }; struct dc_callback_init { -#ifdef CONFIG_DRM_AMD_DC_HDCP struct cp_psp cp_psp; -#else - uint8_t reserved; -#endif }; struct dc *dc_create(const struct dc_init_data *init_params); @@ -1475,9 +1469,7 @@ struct dc_link { uint32_t dongle_max_pix_clk; unsigned short chip_caps; unsigned int dpcd_sink_count; -#if defined(CONFIG_DRM_AMD_DC_HDCP) struct hdcp_caps hdcp_caps; -#endif enum edp_revision edp_revision; union dpcd_sink_ext_caps dpcd_sink_ext_caps; @@ -1661,12 +1653,9 @@ bool dc_is_oem_i2c_device_present( size_t slave_address ); -#ifdef CONFIG_DRM_AMD_DC_HDCP - /* return true if the connected receiver supports the hdcp version */ bool dc_link_is_hdcp14(struct dc_link *link, enum signal_type signal); bool dc_link_is_hdcp22(struct dc_link *link, enum signal_type signal); -#endif /* Notify DC about DP RX Interrupt (aka DP IRQ_HPD). * @@ -2154,7 +2143,6 @@ void dc_resume(struct dc *dc); void dc_power_down_on_boot(struct dc *dc); -#if defined(CONFIG_DRM_AMD_DC_HDCP) /* * HDCP Interfaces */ @@ -2162,7 +2150,6 @@ enum hdcp_message_status dc_process_hdcp_msg( enum signal_type signal, struct dc_link *link, struct hdcp_protection_message *message_info); -#endif bool dc_is_dmcu_initialized(struct dc *dc); enum dc_status dc_set_clock(struct dc *dc, enum dc_clock_type clock_type, uint32_t clk_khz, uint32_t stepping); diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index f28b8597cc1e..4b47fa00610b 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -40,9 +40,7 @@ #include "grph_object_defs.h" #include "grph_object_ctrl_defs.h" -#ifdef CONFIG_DRM_AMD_DC_HDCP #include "dm_cp_psp.h" -#endif /* forward declarations */ struct dc_plane_state; @@ -813,9 +811,7 @@ struct dc_context { uint32_t dc_edp_id_count; uint64_t fbc_gpu_addr; struct dc_dmub_srv *dmub_srv; -#ifdef CONFIG_DRM_AMD_DC_HDCP struct cp_psp cp_psp; -#endif uint32_t *dcn_reg_offsets; uint32_t *nbio_reg_offsets; }; @@ -955,7 +951,6 @@ struct dc_link_status { struct dpcd_caps *dpcd_caps; }; -#if defined(CONFIG_DRM_AMD_DC_HDCP) union hdcp_rx_caps { struct { uint8_t version; @@ -982,7 +977,6 @@ struct hdcp_caps { union hdcp_rx_caps rx_caps; union hdcp_bcaps bcaps; }; -#endif /* DP MST stream allocation (payload bandwidth number) */ struct link_mst_stream_allocation { diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.c index 36e6f5657942..ccf6b181c349 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.c @@ -211,10 +211,8 @@ static void enc32_stream_encoder_hdmi_set_stream_attribute( HDMI_GC_SEND, 1, HDMI_NULL_SEND, 1); -#if defined(CONFIG_DRM_AMD_DC_HDCP) /* Disable Audio Content Protection packet transmission */ REG_UPDATE(HDMI_VBI_PACKET_CONTROL, HDMI_ACP_SEND, 0); -#endif /* following belongs to audio */ /* Enable Audio InfoFrame packet transmission. */ diff --git a/drivers/gpu/drm/amd/display/dc/hdcp/hdcp_msg.c b/drivers/gpu/drm/amd/display/dc/hdcp/hdcp_msg.c index e1422e5e86c9..25ffc052d53b 100644 --- a/drivers/gpu/drm/amd/display/dc/hdcp/hdcp_msg.c +++ b/drivers/gpu/drm/amd/display/dc/hdcp/hdcp_msg.c @@ -27,7 +27,7 @@ #include "dm_services.h" #include "dm_helpers.h" -#include "include/hdcp_types.h" +#include "include/hdcp_msg_types.h" #include "include/signal_types.h" #include "core_types.h" #include "link.h" 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 ed3c03108da6..2eb597a24425 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -51,9 +51,7 @@ void enable_surface_flip_reporting(struct dc_plane_state *plane_state, #include "clock_source.h" #include "audio.h" #include "dm_pp_smu.h" -#ifdef CONFIG_DRM_AMD_DC_HDCP #include "dm_cp_psp.h" -#endif #include "link_hwss.h" /********** DAL Core*********************/ diff --git a/drivers/gpu/drm/amd/display/dc/inc/link.h b/drivers/gpu/drm/amd/display/dc/inc/link.h index 6a346a41f07b..a3fcfa918a8f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/link.h +++ b/drivers/gpu/drm/amd/display/dc/inc/link.h @@ -139,11 +139,9 @@ bool link_detect(struct dc_link *link, enum dc_detect_reason reason); bool link_detect_connection_type(struct dc_link *link, enum dc_connection_type *type); const struct dc_link_status *link_get_status(const struct dc_link *link); -#ifdef CONFIG_DRM_AMD_DC_HDCP /* return true if the connected receiver supports the hdcp version */ bool link_is_hdcp14(struct dc_link *link, enum signal_type signal); bool link_is_hdcp22(struct dc_link *link, enum signal_type signal); -#endif void link_clear_dprx_states(struct dc_link *link); bool link_reset_cur_dp_mst_topology(struct dc_link *link); uint32_t dp_link_bandwidth_kbps( diff --git a/drivers/gpu/drm/amd/display/dc/link/link_detection.c b/drivers/gpu/drm/amd/display/dc/link/link_detection.c index 393bdefba0ba..99279e1e7330 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_detection.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_detection.c @@ -466,7 +466,6 @@ static void link_disconnect_remap(struct dc_sink *prev_sink, struct dc_link *lin link->local_sink = prev_sink; } -#if defined(CONFIG_DRM_AMD_DC_HDCP) static void query_hdcp_capability(enum signal_type signal, struct dc_link *link) { struct hdcp_protection_message msg22; @@ -508,7 +507,6 @@ static void query_hdcp_capability(enum signal_type signal, struct dc_link *link) } } -#endif // CONFIG_DRM_AMD_DC_HDCP static void read_current_link_settings_on_detect(struct dc_link *link) { union lane_count_set lane_count_set = {0}; @@ -1084,9 +1082,7 @@ static bool detect_link_and_local_sink(struct dc_link *link, * TODO debug why certain monitors don't like * two link trainings */ -#if defined(CONFIG_DRM_AMD_DC_HDCP) query_hdcp_capability(sink->sink_signal, link); -#endif } else { // If edid is the same, then discard new sink and revert back to original sink if (same_edid) { @@ -1094,9 +1090,7 @@ static bool detect_link_and_local_sink(struct dc_link *link, sink = prev_sink; prev_sink = NULL; } -#if defined(CONFIG_DRM_AMD_DC_HDCP) query_hdcp_capability(sink->sink_signal, link); -#endif } /* HDMI-DVI Dongle */ @@ -1162,9 +1156,7 @@ static bool detect_link_and_local_sink(struct dc_link *link, /* From Connected-to-Disconnected. */ link->type = dc_connection_none; sink_caps.signal = SIGNAL_TYPE_NONE; -#if defined(CONFIG_DRM_AMD_DC_HDCP) memset(&link->hdcp_caps, 0, sizeof(struct hdcp_caps)); -#endif /* When we unplug a passive DP-HDMI dongle connection, dongle_max_pix_clk * is not cleared. If we emulate a DP signal on this connection, it thinks * the dongle is still there and limits the number of modes we can emulate. @@ -1266,7 +1258,6 @@ void link_clear_dprx_states(struct dc_link *link) { memset(&link->dprx_states, 0, sizeof(link->dprx_states)); } -#if defined(CONFIG_DRM_AMD_DC_HDCP) bool link_is_hdcp14(struct dc_link *link, enum signal_type signal) { @@ -1314,7 +1305,6 @@ bool link_is_hdcp22(struct dc_link *link, enum signal_type signal) return ret; } -#endif // CONFIG_DRM_AMD_DC_HDCP const struct dc_link_status *link_get_status(const struct dc_link *link) { diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c index a1214e5606dd..0039928186ff 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c @@ -647,7 +647,6 @@ static void write_i2c_redriver_setting( if (!i2c_success) DC_LOG_DEBUG("Set redriver failed"); } -#if defined(CONFIG_DRM_AMD_DC_HDCP) static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off) { @@ -713,7 +712,6 @@ static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off) cp_psp->funcs.update_stream_config(cp_psp->handle, &config); } -#endif static void set_avmute(struct pipe_ctx *pipe_ctx, bool enable) { @@ -2269,9 +2267,7 @@ void link_set_dpms_off(struct pipe_ctx *pipe_ctx) dc->hwss.disable_audio_stream(pipe_ctx); -#if defined(CONFIG_DRM_AMD_DC_HDCP) update_psp_stream_config(pipe_ctx, true); -#endif dc->hwss.blank_stream(pipe_ctx); if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) @@ -2417,9 +2413,7 @@ void link_set_dpms_on( dc->hwss.enable_audio_stream(pipe_ctx); } -#if defined(CONFIG_DRM_AMD_DC_HDCP) update_psp_stream_config(pipe_ctx, false); -#endif return; } @@ -2429,9 +2423,7 @@ void link_set_dpms_on( !pipe_ctx->stream->timing.flags.DSC && !pipe_ctx->next_odm_pipe) { pipe_ctx->stream->dpms_off = false; -#if defined(CONFIG_DRM_AMD_DC_HDCP) update_psp_stream_config(pipe_ctx, false); -#endif return; } @@ -2515,9 +2507,7 @@ void link_set_dpms_on( if (dc_is_dp_signal(pipe_ctx->stream->signal)) enable_stream_features(pipe_ctx); -#if defined(CONFIG_DRM_AMD_DC_HDCP) update_psp_stream_config(pipe_ctx, false); -#endif dc->hwss.enable_audio_stream(pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c index 5e613ea2cd3f..cb0049cd1133 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c @@ -1570,7 +1570,6 @@ 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; @@ -1584,7 +1583,6 @@ bool perform_link_training_with_retries( result = cp_psp->funcs.enable_assr(cp_psp->handle, link); } } -#endif dp_set_panel_mode(link, panel_mode); diff --git a/drivers/gpu/drm/amd/display/include/hdcp_msg_types.h b/drivers/gpu/drm/amd/display/include/hdcp_msg_types.h new file mode 100644 index 000000000000..42229b4effdc --- /dev/null +++ b/drivers/gpu/drm/amd/display/include/hdcp_msg_types.h @@ -0,0 +1,103 @@ +/* +* Copyright 2019 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_HDCP_TYPES_H__ +#define __DC_HDCP_TYPES_H__ + +enum hdcp_message_id { + HDCP_MESSAGE_ID_INVALID = -1, + + /* HDCP 1.4 */ + + HDCP_MESSAGE_ID_READ_BKSV = 0, + /* HDMI is called Ri', DP is called R0' */ + HDCP_MESSAGE_ID_READ_RI_R0, + HDCP_MESSAGE_ID_READ_PJ, + HDCP_MESSAGE_ID_WRITE_AKSV, + HDCP_MESSAGE_ID_WRITE_AINFO, + HDCP_MESSAGE_ID_WRITE_AN, + HDCP_MESSAGE_ID_READ_VH_X, + HDCP_MESSAGE_ID_READ_VH_0, + HDCP_MESSAGE_ID_READ_VH_1, + HDCP_MESSAGE_ID_READ_VH_2, + HDCP_MESSAGE_ID_READ_VH_3, + HDCP_MESSAGE_ID_READ_VH_4, + HDCP_MESSAGE_ID_READ_BCAPS, + HDCP_MESSAGE_ID_READ_BSTATUS, + HDCP_MESSAGE_ID_READ_KSV_FIFO, + HDCP_MESSAGE_ID_READ_BINFO, + + /* HDCP 2.2 */ + + HDCP_MESSAGE_ID_HDCP2VERSION, + HDCP_MESSAGE_ID_RX_CAPS, + HDCP_MESSAGE_ID_WRITE_AKE_INIT, + HDCP_MESSAGE_ID_READ_AKE_SEND_CERT, + HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM, + HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM, + HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME, + HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO, + HDCP_MESSAGE_ID_WRITE_LC_INIT, + HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME, + HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS, + HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST, + HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK, + HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE, + HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY, + HDCP_MESSAGE_ID_READ_RXSTATUS, + HDCP_MESSAGE_ID_WRITE_CONTENT_STREAM_TYPE, + + HDCP_MESSAGE_ID_MAX +}; + +enum hdcp_version { + HDCP_Unknown = 0, + HDCP_VERSION_14, + HDCP_VERSION_22, +}; + +enum hdcp_link { + HDCP_LINK_PRIMARY, + HDCP_LINK_SECONDARY +}; + +enum hdcp_message_status { + HDCP_MESSAGE_SUCCESS, + HDCP_MESSAGE_FAILURE, + HDCP_MESSAGE_UNSUPPORTED +}; + +struct hdcp_protection_message { + enum hdcp_version version; + /* relevant only for DVI */ + enum hdcp_link link; + enum hdcp_message_id msg_id; + uint32_t length; + uint8_t max_retries; + uint8_t *data; + enum hdcp_message_status status; +}; + +#endif diff --git a/drivers/gpu/drm/amd/display/include/hdcp_types.h b/drivers/gpu/drm/amd/display/include/hdcp_types.h deleted file mode 100644 index 42229b4effdc..000000000000 --- a/drivers/gpu/drm/amd/display/include/hdcp_types.h +++ /dev/null @@ -1,103 +0,0 @@ -/* -* Copyright 2019 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_HDCP_TYPES_H__ -#define __DC_HDCP_TYPES_H__ - -enum hdcp_message_id { - HDCP_MESSAGE_ID_INVALID = -1, - - /* HDCP 1.4 */ - - HDCP_MESSAGE_ID_READ_BKSV = 0, - /* HDMI is called Ri', DP is called R0' */ - HDCP_MESSAGE_ID_READ_RI_R0, - HDCP_MESSAGE_ID_READ_PJ, - HDCP_MESSAGE_ID_WRITE_AKSV, - HDCP_MESSAGE_ID_WRITE_AINFO, - HDCP_MESSAGE_ID_WRITE_AN, - HDCP_MESSAGE_ID_READ_VH_X, - HDCP_MESSAGE_ID_READ_VH_0, - HDCP_MESSAGE_ID_READ_VH_1, - HDCP_MESSAGE_ID_READ_VH_2, - HDCP_MESSAGE_ID_READ_VH_3, - HDCP_MESSAGE_ID_READ_VH_4, - HDCP_MESSAGE_ID_READ_BCAPS, - HDCP_MESSAGE_ID_READ_BSTATUS, - HDCP_MESSAGE_ID_READ_KSV_FIFO, - HDCP_MESSAGE_ID_READ_BINFO, - - /* HDCP 2.2 */ - - HDCP_MESSAGE_ID_HDCP2VERSION, - HDCP_MESSAGE_ID_RX_CAPS, - HDCP_MESSAGE_ID_WRITE_AKE_INIT, - HDCP_MESSAGE_ID_READ_AKE_SEND_CERT, - HDCP_MESSAGE_ID_WRITE_AKE_NO_STORED_KM, - HDCP_MESSAGE_ID_WRITE_AKE_STORED_KM, - HDCP_MESSAGE_ID_READ_AKE_SEND_H_PRIME, - HDCP_MESSAGE_ID_READ_AKE_SEND_PAIRING_INFO, - HDCP_MESSAGE_ID_WRITE_LC_INIT, - HDCP_MESSAGE_ID_READ_LC_SEND_L_PRIME, - HDCP_MESSAGE_ID_WRITE_SKE_SEND_EKS, - HDCP_MESSAGE_ID_READ_REPEATER_AUTH_SEND_RECEIVERID_LIST, - HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_SEND_ACK, - HDCP_MESSAGE_ID_WRITE_REPEATER_AUTH_STREAM_MANAGE, - HDCP_MESSAGE_ID_READ_REPEATER_AUTH_STREAM_READY, - HDCP_MESSAGE_ID_READ_RXSTATUS, - HDCP_MESSAGE_ID_WRITE_CONTENT_STREAM_TYPE, - - HDCP_MESSAGE_ID_MAX -}; - -enum hdcp_version { - HDCP_Unknown = 0, - HDCP_VERSION_14, - HDCP_VERSION_22, -}; - -enum hdcp_link { - HDCP_LINK_PRIMARY, - HDCP_LINK_SECONDARY -}; - -enum hdcp_message_status { - HDCP_MESSAGE_SUCCESS, - HDCP_MESSAGE_FAILURE, - HDCP_MESSAGE_UNSUPPORTED -}; - -struct hdcp_protection_message { - enum hdcp_version version; - /* relevant only for DVI */ - enum hdcp_link link; - enum hdcp_message_id msg_id; - uint32_t length; - uint8_t max_retries; - uint8_t *data; - enum hdcp_message_status status; -}; - -#endif diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.h b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.h index eb6f9b9c504a..c62df3bcc7cb 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.h +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_log.h @@ -26,13 +26,11 @@ #ifndef MOD_HDCP_LOG_H_ #define MOD_HDCP_LOG_H_ -#ifdef CONFIG_DRM_AMD_DC_HDCP #define HDCP_LOG_ERR(hdcp, ...) DRM_DEBUG_KMS(__VA_ARGS__) #define HDCP_LOG_VER(hdcp, ...) DRM_DEBUG_KMS(__VA_ARGS__) #define HDCP_LOG_FSM(hdcp, ...) DRM_DEBUG_KMS(__VA_ARGS__) #define HDCP_LOG_TOP(hdcp, ...) pr_debug("[HDCP_TOP]:"__VA_ARGS__) #define HDCP_LOG_DDC(hdcp, ...) pr_debug("[HDCP_DDC]:"__VA_ARGS__) -#endif /* default logs */ #define HDCP_ERROR_TRACE(hdcp, status) \ -- cgit v1.2.3 From bf77fda02411fe2cac3522f40d8d6882d27ac14b Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 13 Feb 2023 17:46:45 -0500 Subject: drm/amd/display: Drop unnecessary DCN guards [Why] DM is littered with DCN guards leading to frequent breakages on non-DCN builds when new code is added. [How] Remove all guards that are not needed. Reviewed-by: Rodrigo Siqueira Acked-by: Qingqing Zhuo Signed-off-by: Harry Wentland Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 20 -------------------- .../drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 8 -------- .../drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 14 -------------- 3 files changed, 42 deletions(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index de270f0969f5..26abb62bbd93 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -5737,7 +5737,6 @@ static bool is_freesync_video_mode(const struct drm_display_mode *mode, return true; } -#if defined(CONFIG_DRM_AMD_DC_DCN) static void update_dsc_caps(struct amdgpu_dm_connector *aconnector, struct dc_sink *sink, struct dc_stream_state *stream, struct dsc_dec_dpcd_caps *dsc_caps) @@ -5892,7 +5891,6 @@ static void apply_dsc_policy_for_stream(struct amdgpu_dm_connector *aconnector, if (stream->timing.flags.DSC && aconnector->dsc_settings.dsc_bits_per_pixel) stream->timing.dsc_cfg.bits_per_pixel = aconnector->dsc_settings.dsc_bits_per_pixel; } -#endif /* CONFIG_DRM_AMD_DC_DCN */ static struct dc_stream_state * create_stream_for_sink(struct amdgpu_dm_connector *aconnector, @@ -5915,9 +5913,7 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, int mode_refresh; int preferred_refresh = 0; enum color_transfer_func tf = TRANSFER_FUNC_UNKNOWN; -#if defined(CONFIG_DRM_AMD_DC_DCN) struct dsc_dec_dpcd_caps dsc_caps; -#endif struct dc_sink *sink = NULL; @@ -6016,12 +6012,10 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, stream->timing = *aconnector->timing_requested; } -#if defined(CONFIG_DRM_AMD_DC_DCN) /* SST DSC determination policy */ update_dsc_caps(aconnector, sink, stream, &dsc_caps); if (aconnector->dsc_settings.dsc_force_enable != DSC_CLK_FORCE_DISABLE && dsc_caps.is_dsc_supported) apply_dsc_policy_for_stream(aconnector, sink, stream, &dsc_caps); -#endif update_stream_scaling_settings(&mode, dm_state, stream); @@ -6747,7 +6741,6 @@ const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs = { .atomic_check = dm_encoder_helper_atomic_check }; -#if defined(CONFIG_DRM_AMD_DC_DCN) static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state, struct dc_state *dc_state, struct dsc_mst_fairness_vars *vars) @@ -6821,7 +6814,6 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state, } return 0; } -#endif static int to_drm_connector_type(enum signal_type st) { @@ -9758,7 +9750,6 @@ static int dm_check_crtc_cursor(struct drm_atomic_state *state, return 0; } -#if defined(CONFIG_DRM_AMD_DC_DCN) static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm_crtc *crtc) { struct drm_connector *connector; @@ -9784,7 +9775,6 @@ static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm return drm_dp_mst_add_affected_dsc_crtcs(state, &aconnector->mst_root->mst_mgr); } -#endif /** * amdgpu_dm_atomic_check() - Atomic check implementation for AMDgpu DM. @@ -9828,11 +9818,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, bool lock_and_validation_needed = false; bool is_top_most_overlay = true; struct dm_crtc_state *dm_old_crtc_state, *dm_new_crtc_state; -#if defined(CONFIG_DRM_AMD_DC_DCN) struct drm_dp_mst_topology_mgr *mgr; struct drm_dp_mst_topology_state *mst_state; struct dsc_mst_fairness_vars vars[MAX_PIPES]; -#endif trace_amdgpu_dm_atomic_check_begin(state); @@ -9863,7 +9851,6 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, new_crtc_state->connectors_changed = true; } -#if defined(CONFIG_DRM_AMD_DC_DCN) if (dc_resource_is_dsc_encoding_supported(dc)) { for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { if (drm_atomic_crtc_needs_modeset(new_crtc_state)) { @@ -9875,7 +9862,6 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, } } } -#endif for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { dm_old_crtc_state = to_dm_crtc_state(old_crtc_state); @@ -10013,13 +9999,11 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, } } -#if defined(CONFIG_DRM_AMD_DC_DCN) if (dc_resource_is_dsc_encoding_supported(dc)) { ret = pre_validate_dsc(state, &dm_state, vars); if (ret != 0) goto fail; } -#endif /* Run this here since we want to validate the streams we created */ ret = drm_atomic_helper_check_planes(dev, state); @@ -10085,7 +10069,6 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, lock_and_validation_needed = true; } -#if defined(CONFIG_DRM_AMD_DC_DCN) /* set the slot info for each mst_state based on the link encoding format */ for_each_new_mst_mgr_in_state(state, mgr, mst_state, i) { struct amdgpu_dm_connector *aconnector; @@ -10105,7 +10088,6 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, } drm_connector_list_iter_end(&iter); } -#endif /** * Streams and planes are reset when there are changes that affect @@ -10133,7 +10115,6 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, goto fail; } -#if defined(CONFIG_DRM_AMD_DC_DCN) ret = compute_mst_dsc_configs_for_state(state, dm_state->context, vars); if (ret) { DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state() failed\n"); @@ -10145,7 +10126,6 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, DRM_DEBUG_DRIVER("dm_update_mst_vcpi_slots_for_dsc() failed\n"); goto fail; } -#endif /* * Perform validation of MST topology in the state: diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index 1583157da355..1be04c613deb 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -525,7 +525,6 @@ bool dm_helpers_submit_i2c( return result; } -#if defined(CONFIG_DRM_AMD_DC_DCN) static bool execute_synaptics_rc_command(struct drm_dp_aux *aux, bool is_write_cmd, unsigned char cmd, @@ -693,7 +692,6 @@ static uint8_t write_dsc_enable_synaptics_non_virtual_dpcd_mst( return ret; } -#endif bool dm_helpers_dp_write_dsc_enable( struct dc_context *ctx, @@ -719,13 +717,11 @@ bool dm_helpers_dp_write_dsc_enable( if (!aconnector->dsc_aux) return false; -#if defined(CONFIG_DRM_AMD_DC_DCN) // apply w/a to synaptics if (needs_dsc_aux_workaround(aconnector->dc_link) && (aconnector->mst_downstream_port_present.byte & 0x7) != 0x3) return write_dsc_enable_synaptics_non_virtual_dpcd_mst( aconnector->dsc_aux, stream, enable_dsc); -#endif port = aconnector->mst_output_port; @@ -763,17 +759,13 @@ bool dm_helpers_dp_write_dsc_enable( } if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT || stream->signal == SIGNAL_TYPE_EDP) { -#if defined(CONFIG_DRM_AMD_DC_DCN) if (stream->sink->link->dpcd_caps.dongle_type == DISPLAY_DONGLE_NONE) { -#endif ret = dm_helpers_dp_write_dpcd(ctx, stream->link, DP_DSC_ENABLE, &enable_dsc, 1); DC_LOG_DC("Send DSC %s to SST RX\n", enable_dsc ? "enable" : "disable"); -#if defined(CONFIG_DRM_AMD_DC_DCN) } else if (stream->sink->link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER) { ret = dm_helpers_dp_write_dpcd(ctx, stream->link, DP_DSC_ENABLE, &enable_dsc, 1); DC_LOG_DC("Send DSC %s to DP-HDMI PCON\n", enable_dsc ? "enable" : "disable"); } -#endif } return ret; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 248f25943748..2739bef9b90c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -198,7 +198,6 @@ static const struct drm_connector_funcs dm_dp_mst_connector_funcs = { .early_unregister = amdgpu_dm_mst_connector_early_unregister, }; -#if defined(CONFIG_DRM_AMD_DC_DCN) bool needs_dsc_aux_workaround(struct dc_link *link) { if (link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_90CC24 && @@ -268,7 +267,6 @@ static bool retrieve_downstream_port_device(struct amdgpu_dm_connector *aconnect return true; } -#endif static int dm_dp_mst_get_modes(struct drm_connector *connector) { @@ -375,7 +373,6 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector) amdgpu_dm_update_freesync_caps( connector, aconnector->edid); -#if defined(CONFIG_DRM_AMD_DC_DCN) if (!validate_dsc_caps_on_connector(aconnector)) memset(&aconnector->dc_sink->dsc_caps, 0, sizeof(aconnector->dc_sink->dsc_caps)); @@ -383,7 +380,6 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector) if (!retrieve_downstream_port_device(aconnector)) memset(&aconnector->mst_downstream_port_present, 0, sizeof(aconnector->mst_downstream_port_present)); -#endif } } @@ -642,8 +638,6 @@ int dm_mst_get_pbn_divider(struct dc_link *link) dc_link_get_link_cap(link)) / (8 * 1000 * 54); } -#if defined(CONFIG_DRM_AMD_DC_DCN) - struct dsc_mst_fairness_params { struct dc_crtc_timing *timing; struct dc_sink *sink; @@ -1427,7 +1421,6 @@ static unsigned int kbps_from_pbn(unsigned int pbn) static bool is_dsc_common_config_possible(struct dc_stream_state *stream, struct dc_dsc_bw_range *bw_range) { -#if defined(CONFIG_DRM_AMD_DC_DCN) struct dc_dsc_policy dsc_policy = {0}; dc_dsc_get_policy_for_timing(&stream->timing, 0, &dsc_policy); @@ -1439,17 +1432,13 @@ static bool is_dsc_common_config_possible(struct dc_stream_state *stream, &stream->timing, bw_range); return bw_range->max_target_bpp_x16 && bw_range->min_target_bpp_x16; -#endif - return false; } -#endif /* CONFIG_DRM_AMD_DC_DCN */ enum dc_status dm_dp_mst_is_port_support_mode( struct amdgpu_dm_connector *aconnector, struct dc_stream_state *stream) { int bpp, pbn, branch_max_throughput_mps = 0; -#if defined(CONFIG_DRM_AMD_DC_DCN) struct dc_link_settings cur_link_settings; unsigned int end_to_end_bw_in_kbps = 0; unsigned int upper_link_bw_in_kbps = 0, down_link_bw_in_kbps = 0; @@ -1491,16 +1480,13 @@ enum dc_status dm_dp_mst_is_port_support_mode( return DC_FAIL_BANDWIDTH_VALIDATE; } } else { -#endif /* check if mode could be supported within full_pbn */ bpp = convert_dc_color_depth_into_bpc(stream->timing.display_color_depth) * 3; pbn = drm_dp_calc_pbn_mode(stream->timing.pix_clk_100hz / 10, bpp, false); if (pbn > aconnector->mst_output_port->full_pbn) return DC_FAIL_BANDWIDTH_VALIDATE; -#if defined(CONFIG_DRM_AMD_DC_DCN) } -#endif /* check is mst dsc output bandwidth branch_overall_throughput_0_mps */ switch (stream->timing.pixel_encoding) { -- cgit v1.2.3 From b8272241ff9df5b57e2777a07c1fe8af3d9cbf93 Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Thu, 6 Oct 2022 14:57:31 -0400 Subject: drm/amd/display: Drop dc_commit_state in favor of dc_commit_streams [Why & How] There are two functions responsible for handling the DC commit state: dc_commit_state and dc_commit_streams. Both have the same goal, but dc_commit_streams surpess dc_commit_state in terms of completeness. For this reason, maintaining these two functions makes maintainability unnecessarily complicated. This commit replaces the old dc_commit_state in favor of dc_commit_streams, and removes the old dc_commit_state. Reviewed-by: Harry Wentland Acked-by: Qingqing Zhuo Signed-off-by: Rodrigo Siqueira Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 6 +-- drivers/gpu/drm/amd/display/dc/core/dc.c | 47 ----------------------- drivers/gpu/drm/amd/display/dc/dc.h | 4 -- 3 files changed, 3 insertions(+), 54 deletions(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 26abb62bbd93..0d0d2f8b4e3b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2486,7 +2486,7 @@ static enum dc_status amdgpu_dm_commit_zero_streams(struct dc *dc) goto fail; } - res = dc_commit_state(dc, context); + res = dc_commit_streams(dc, context->streams, context->stream_count); fail: dc_release_state(context); @@ -2745,7 +2745,7 @@ static int dm_resume(void *handle) dc_enable_dmub_outbox(adev->dm.dc); } - WARN_ON(!dc_commit_state(dm->dc, dc_state)); + WARN_ON(!dc_commit_streams(dm->dc, dc_state->streams, dc_state->stream_count)); dm_gpureset_commit_state(dm->cached_dc_state, dm); @@ -8482,7 +8482,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) dm_enable_per_frame_crtc_master_sync(dc_state); mutex_lock(&dm->dc_lock); - WARN_ON(!dc_commit_state(dm->dc, dc_state)); + WARN_ON(!dc_commit_streams(dm->dc, dc_state->streams, dc_state->stream_count)); /* Allow idle optimization when vblank count is 0 for display off */ if (dm->active_vblank_irq_count == 0) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 4ac11f169119..a5f2f880610d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -2061,53 +2061,6 @@ context_alloc_fail: return res; } -/* TODO: When the transition to the new commit sequence is done, remove this - * function in favor of dc_commit_streams. */ -bool dc_commit_state(struct dc *dc, struct dc_state *context) -{ - enum dc_status result = DC_ERROR_UNEXPECTED; - int i; - - /* TODO: Since change commit sequence can have a huge impact, - * we decided to only enable it for DCN3x. However, as soon as - * we get more confident about this change we'll need to enable - * the new sequence for all ASICs. */ - if (dc->ctx->dce_version >= DCN_VERSION_3_2) { - result = dc_commit_streams(dc, context->streams, context->stream_count); - return result == DC_OK; - } - - if (!streams_changed(dc, context->streams, context->stream_count)) { - return DC_OK; - } - - DC_LOG_DC("%s: %d streams\n", - __func__, context->stream_count); - - for (i = 0; i < context->stream_count; i++) { - struct dc_stream_state *stream = context->streams[i]; - - dc_stream_log(dc, stream); - } - - /* - * Previous validation was perfomred with fast_validation = true and - * the full DML state required for hardware programming was skipped. - * - * Re-validate here to calculate these parameters / watermarks. - */ - result = dc_validate_global_state(dc, context, false); - if (result != DC_OK) { - DC_LOG_ERROR("DC commit global validation failure: %s (%d)", - dc_status_to_str(result), result); - return result; - } - - result = dc_commit_state_no_check(dc, context); - - return (result == DC_OK); -} - bool dc_acquire_release_mpc_3dlut( struct dc *dc, bool acquire, struct dc_stream_state *stream, diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 0f6873449d15..b51dfe0f507c 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -1360,10 +1360,6 @@ enum dc_status dc_commit_streams(struct dc *dc, struct dc_stream_state *streams[], uint8_t stream_count); -/* TODO: When the transition to the new commit sequence is done, remove this - * function in favor of dc_commit_streams. */ -bool dc_commit_state(struct dc *dc, struct dc_state *context); - struct dc_state *dc_create_state(struct dc *dc); struct dc_state *dc_copy_state(struct dc_state *src_ctx); void dc_retain_state(struct dc_state *context); -- cgit v1.2.3 From f7511289821ffccc07579406d6ab520aa11049f5 Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Thu, 6 Oct 2022 16:40:55 -0400 Subject: drm/amd/display: Use dc_update_planes_and_stream [Why & How] The old dc_commit_updates_for_stream lacks manipulation for many corner cases where the DC feature requires special attention; as a result, it starts to show its limitation (e.g., the SubVP feature is not supported by it, among other cases). To modernize and unify our internal API, this commit replaces the old dc_commit_updates_for_stream with dc_update_planes_and_stream, which has more features. Reviewed-by: Harry Wentland Acked-by: Qingqing Zhuo Signed-off-by: Rodrigo Siqueira Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 30 +++++++++++------------ 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 0d0d2f8b4e3b..5e2e4aee5896 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2672,10 +2672,12 @@ static void dm_gpureset_commit_state(struct dc_state *dc_state, bundle->surface_updates[m].surface->force_full_update = true; } - dc_commit_updates_for_stream( - dm->dc, bundle->surface_updates, + + dc_update_planes_and_stream(dm->dc, + bundle->surface_updates, dc_state->stream_status->plane_count, - dc_state->streams[k], &bundle->stream_update, dc_state); + dc_state->streams[k], + &bundle->stream_update); } cleanup: @@ -8159,12 +8161,11 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, acrtc_state->stream->link->psr_settings.psr_allow_active) amdgpu_dm_psr_disable(acrtc_state->stream); - dc_commit_updates_for_stream(dm->dc, - bundle->surface_updates, - planes_count, - acrtc_state->stream, - &bundle->stream_update, - dc_state); + dc_update_planes_and_stream(dm->dc, + bundle->surface_updates, + planes_count, + acrtc_state->stream, + &bundle->stream_update); /** * Enable or disable the interrupts on the backend. @@ -8694,12 +8695,11 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) mutex_lock(&dm->dc_lock); - dc_commit_updates_for_stream(dm->dc, - dummy_updates, - status->plane_count, - dm_new_crtc_state->stream, - &stream_update, - dc_state); + dc_update_planes_and_stream(dm->dc, + dummy_updates, + status->plane_count, + dm_new_crtc_state->stream, + &stream_update); mutex_unlock(&dm->dc_lock); } -- cgit v1.2.3 From 81f743a08f3b214638aa389e252ae5e6c3592e7c Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Thu, 23 Feb 2023 11:36:08 -0700 Subject: drm/amd/display: Add wrapper to call planes and stream update [Why & How] This commit is part of a sequence of changes that replaces the commit sequence used in the DC with a new one. As a result of this transition, we moved some specific parts from the commit sequence and brought them to amdgpu_dm. This commit adds a wrapper inside DM that enable our drivers to do any necessary preparation or change before we offload the plane/stream update to DC. Reviewed-by: Harry Wentland Acked-by: Qingqing Zhuo Signed-off-by: Rodrigo Siqueira Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 51 ++++++++++++++++++----- 1 file changed, 41 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 5e2e4aee5896..53dcb3518976 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -348,6 +348,35 @@ static inline bool is_dc_timing_adjust_needed(struct dm_crtc_state *old_state, return false; } +/** + * update_planes_and_stream_adapter() - Send planes to be updated in DC + * + * DC has a generic way to update planes and stream via + * dc_update_planes_and_stream function; however, DM might need some + * adjustments and preparation before calling it. This function is a wrapper + * for the dc_update_planes_and_stream that does any required configuration + * before passing control to DC. + */ +static inline bool update_planes_and_stream_adapter(struct dc *dc, + int update_type, + int planes_count, + struct dc_stream_state *stream, + struct dc_stream_update *stream_update, + struct dc_surface_update *array_of_surface_update) +{ + /* + * Previous frame finished and HW is ready for optimization. + */ + if (update_type == UPDATE_TYPE_FAST) + dc_post_update_surfaces_to_stream(dc); + + return dc_update_planes_and_stream(dc, + array_of_surface_update, + planes_count, + stream, + stream_update); +} + /** * dm_pflip_high_irq() - Handle pageflip interrupt * @interrupt_params: ignored @@ -2673,11 +2702,12 @@ static void dm_gpureset_commit_state(struct dc_state *dc_state, true; } - dc_update_planes_and_stream(dm->dc, - bundle->surface_updates, - dc_state->stream_status->plane_count, - dc_state->streams[k], - &bundle->stream_update); + update_planes_and_stream_adapter(dm->dc, + UPDATE_TYPE_FULL, + dc_state->stream_status->plane_count, + dc_state->streams[k], + &bundle->stream_update, + bundle->surface_updates); } cleanup: @@ -8161,11 +8191,12 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, acrtc_state->stream->link->psr_settings.psr_allow_active) amdgpu_dm_psr_disable(acrtc_state->stream); - dc_update_planes_and_stream(dm->dc, - bundle->surface_updates, - planes_count, - acrtc_state->stream, - &bundle->stream_update); + update_planes_and_stream_adapter(dm->dc, + acrtc_state->update_type, + planes_count, + acrtc_state->stream, + &bundle->stream_update, + bundle->surface_updates); /** * Enable or disable the interrupts on the backend. -- cgit v1.2.3 From bb46a6a9bab134b9d15043ea8fa9d6c276e938b8 Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Thu, 16 Feb 2023 09:49:22 -0700 Subject: drm/amd/display: Ensure that planes are in the same order The function dc_update_planes_and_stream handles multiple cases where DC needs to remove and add planes in the commit tail phase. After Linux started to use this function, some of the IGT kms_plane started to fail; one good example to illustrate why the new sequence regressed IGT is the subtest plane-position-hole which has the following diagram as a template: +--------------------+ +-----------------------+ | +-----+ | | +-----+ | | | | | | | +-----+ | | | +--+ | ==> | | | | | | | |__| | | +-|---+ | | | | | +-----+ | | | | | +--------------------+ +-----------------------+ (a) Final image (b) Composed image IGT expects image (a) as the final result of two plane compositions as described in figure (b). After the migration to the new sequence, the last plane order is changed, and DC generates the following image: +---------------------+ | +-----+ | | | | | | | | | | +-----+ | | | +---------------------+ Notice that the generated image by DC is different because the small square that should be composed on top of the primary plane is below the primary plane. For this reason, the CRC will mismatch with the expected value. Since the function dc_add_all_planes_for_stream re-append all the new planes back to the dc_validation_set, this commit ensures that the original sequence is maintained. After this change, all CI tests in all ASICs start to pass again. Reviewed-by: Harry Wentland Acked-by: Qingqing Zhuo Suggested-by: Melissa Wen Signed-off-by: Rodrigo Siqueira Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 53dcb3518976..c27fb97b0135 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -348,6 +348,19 @@ static inline bool is_dc_timing_adjust_needed(struct dm_crtc_state *old_state, return false; } +static inline void reverse_planes_order(struct dc_surface_update *array_of_surface_update, + int planes_count) +{ + int i, j; + struct dc_surface_update surface_updates_temp; + + for (i = 0, j = planes_count - 1; i < j; i++, j--) { + surface_updates_temp = array_of_surface_update[i]; + array_of_surface_update[i] = array_of_surface_update[j]; + array_of_surface_update[j] = surface_updates_temp; + } +} + /** * update_planes_and_stream_adapter() - Send planes to be updated in DC * @@ -364,6 +377,8 @@ static inline bool update_planes_and_stream_adapter(struct dc *dc, struct dc_stream_update *stream_update, struct dc_surface_update *array_of_surface_update) { + reverse_planes_order(array_of_surface_update, planes_count); + /* * Previous frame finished and HW is ready for optimization. */ -- cgit v1.2.3 From 8bf0d9cdf36b0bebf17b733e3f5158783d765df3 Mon Sep 17 00:00:00 2001 From: David Tadokoro Date: Sun, 5 Mar 2023 23:24:27 -0300 Subject: drm/amd/display: add prefix to amdgpu_dm_plane.h functions The amdgpu_dm_plane.h functions didn't have names that indicated where they were declared. To better filter results in debug tools like ftrace, prefix these functions with 'amdgpu_dm_plane_'. Note that we may want to make this same change in other files like amdgpu_dm_crtc.h. Signed-off-by: David Tadokoro Signed-off-by: Alex Deucher --- Documentation/gpu/amdgpu/display/display-manager.rst | 2 +- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 14 +++++++------- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c | 20 ++++++++++---------- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.h | 12 ++++++------ 4 files changed, 24 insertions(+), 24 deletions(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/Documentation/gpu/amdgpu/display/display-manager.rst b/Documentation/gpu/amdgpu/display/display-manager.rst index b7abb18cfc82..be2651ecdd7f 100644 --- a/Documentation/gpu/amdgpu/display/display-manager.rst +++ b/Documentation/gpu/amdgpu/display/display-manager.rst @@ -173,7 +173,7 @@ The alpha blending equation is configured from DRM to DC interface by the following path: 1. When updating a :c:type:`drm_plane_state `, DM calls - :c:type:`fill_blending_from_plane_state()` that maps + :c:type:`amdgpu_dm_plane_fill_blending_from_plane_state()` that maps :c:type:`drm_plane_state ` attributes to :c:type:`dc_plane_info ` struct to be handled in the OS-agnostic component (DC). diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index c27fb97b0135..6db59972ae27 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2960,7 +2960,7 @@ const struct amdgpu_ip_block_version dm_ip_block = static const struct drm_mode_config_funcs amdgpu_dm_mode_funcs = { .fb_create = amdgpu_display_user_framebuffer_create, - .get_format_info = amd_get_format_info, + .get_format_info = amdgpu_dm_plane_get_format_info, .atomic_check = amdgpu_dm_atomic_check, .atomic_commit = drm_atomic_helper_commit, }; @@ -4978,7 +4978,7 @@ fill_dc_plane_info_and_addr(struct amdgpu_device *adev, if (ret) return ret; - ret = fill_plane_buffer_attributes(adev, afb, plane_info->format, + ret = amdgpu_dm_plane_fill_plane_buffer_attributes(adev, afb, plane_info->format, plane_info->rotation, tiling_flags, &plane_info->tiling_info, &plane_info->plane_size, @@ -4987,7 +4987,7 @@ fill_dc_plane_info_and_addr(struct amdgpu_device *adev, if (ret) return ret; - fill_blending_from_plane_state( + amdgpu_dm_plane_fill_blending_from_plane_state( plane_state, &plane_info->per_pixel_alpha, &plane_info->pre_multiplied_alpha, &plane_info->global_alpha, &plane_info->global_alpha_value); @@ -5006,7 +5006,7 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev, int ret; bool force_disable_dcc = false; - ret = fill_dc_scaling_info(adev, plane_state, &scaling_info); + ret = amdgpu_dm_plane_fill_dc_scaling_info(adev, plane_state, &scaling_info); if (ret) return ret; @@ -7901,7 +7901,7 @@ static void amdgpu_dm_commit_cursors(struct drm_atomic_state *state) */ for_each_old_plane_in_state(state, plane, old_plane_state, i) if (plane->type == DRM_PLANE_TYPE_CURSOR) - handle_cursor_update(plane, old_plane_state); + amdgpu_dm_plane_handle_cursor_update(plane, old_plane_state); } static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, @@ -7986,7 +7986,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, bundle->surface_updates[planes_count].gamut_remap_matrix = &dc_plane->gamut_remap_matrix; } - fill_dc_scaling_info(dm->adev, new_plane_state, + amdgpu_dm_plane_fill_dc_scaling_info(dm->adev, new_plane_state, &bundle->scaling_infos[planes_count]); bundle->surface_updates[planes_count].scaling_info = @@ -9650,7 +9650,7 @@ static int dm_update_plane_state(struct dc *dc, if (!needs_reset) return 0; - ret = dm_plane_helper_check_state(new_plane_state, new_crtc_state); + ret = amdgpu_dm_plane_helper_check_state(new_plane_state, new_crtc_state); if (ret) return ret; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c index a8d6b06cee95..322668973747 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c @@ -90,12 +90,12 @@ enum dm_micro_swizzle { MICRO_SWIZZLE_R = 3 }; -const struct drm_format_info *amd_get_format_info(const struct drm_mode_fb_cmd2 *cmd) +const struct drm_format_info *amdgpu_dm_plane_get_format_info(const struct drm_mode_fb_cmd2 *cmd) { return amdgpu_lookup_format_info(cmd->pixel_format, cmd->modifier[0]); } -void fill_blending_from_plane_state(const struct drm_plane_state *plane_state, +void amdgpu_dm_plane_fill_blending_from_plane_state(const struct drm_plane_state *plane_state, bool *per_pixel_alpha, bool *pre_multiplied_alpha, bool *global_alpha, int *global_alpha_value) { @@ -741,7 +741,7 @@ static int get_plane_formats(const struct drm_plane *plane, return num_formats; } -int fill_plane_buffer_attributes(struct amdgpu_device *adev, +int amdgpu_dm_plane_fill_plane_buffer_attributes(struct amdgpu_device *adev, const struct amdgpu_framebuffer *afb, const enum surface_pixel_format format, const enum dc_rotation_angle rotation, @@ -900,7 +900,7 @@ static int dm_plane_helper_prepare_fb(struct drm_plane *plane, dm_plane_state_new->dc_state; bool force_disable_dcc = !plane_state->dcc.enable; - fill_plane_buffer_attributes( + amdgpu_dm_plane_fill_plane_buffer_attributes( adev, afb, plane_state->format, plane_state->rotation, afb->tiling_flags, &plane_state->tiling_info, &plane_state->plane_size, @@ -981,7 +981,7 @@ static void get_min_max_dc_plane_scaling(struct drm_device *dev, *min_downscale = 1000; } -int dm_plane_helper_check_state(struct drm_plane_state *state, +int amdgpu_dm_plane_helper_check_state(struct drm_plane_state *state, struct drm_crtc_state *new_crtc_state) { struct drm_framebuffer *fb = state->fb; @@ -1035,7 +1035,7 @@ int dm_plane_helper_check_state(struct drm_plane_state *state, state, new_crtc_state, min_scale, max_scale, true, true); } -int fill_dc_scaling_info(struct amdgpu_device *adev, +int amdgpu_dm_plane_fill_dc_scaling_info(struct amdgpu_device *adev, const struct drm_plane_state *state, struct dc_scaling_info *scaling_info) { @@ -1143,11 +1143,11 @@ static int dm_plane_atomic_check(struct drm_plane *plane, if (!new_crtc_state) return -EINVAL; - ret = dm_plane_helper_check_state(new_plane_state, new_crtc_state); + ret = amdgpu_dm_plane_helper_check_state(new_plane_state, new_crtc_state); if (ret) return ret; - ret = fill_dc_scaling_info(adev, new_plane_state, &scaling_info); + ret = amdgpu_dm_plane_fill_dc_scaling_info(adev, new_plane_state, &scaling_info); if (ret) return ret; @@ -1211,7 +1211,7 @@ static int get_cursor_position(struct drm_plane *plane, struct drm_crtc *crtc, return 0; } -void handle_cursor_update(struct drm_plane *plane, +void amdgpu_dm_plane_handle_cursor_update(struct drm_plane *plane, struct drm_plane_state *old_plane_state) { struct amdgpu_device *adev = drm_to_adev(plane->dev); @@ -1296,7 +1296,7 @@ static void dm_plane_atomic_async_update(struct drm_plane *plane, plane->state->crtc_w = new_state->crtc_w; plane->state->crtc_h = new_state->crtc_h; - handle_cursor_update(plane, old_state); + amdgpu_dm_plane_handle_cursor_update(plane, old_state); } static const struct drm_plane_helper_funcs dm_plane_helper_funcs = { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.h index a4bee8528a51..930f1572f898 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.h @@ -29,17 +29,17 @@ #include "dc.h" -void handle_cursor_update(struct drm_plane *plane, +void amdgpu_dm_plane_handle_cursor_update(struct drm_plane *plane, struct drm_plane_state *old_plane_state); -int fill_dc_scaling_info(struct amdgpu_device *adev, +int amdgpu_dm_plane_fill_dc_scaling_info(struct amdgpu_device *adev, const struct drm_plane_state *state, struct dc_scaling_info *scaling_info); -int dm_plane_helper_check_state(struct drm_plane_state *state, +int amdgpu_dm_plane_helper_check_state(struct drm_plane_state *state, struct drm_crtc_state *new_crtc_state); -int fill_plane_buffer_attributes(struct amdgpu_device *adev, +int amdgpu_dm_plane_fill_plane_buffer_attributes(struct amdgpu_device *adev, const struct amdgpu_framebuffer *afb, const enum surface_pixel_format format, const enum dc_rotation_angle rotation, @@ -56,9 +56,9 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, unsigned long possible_crtcs, const struct dc_plane_cap *plane_cap); -const struct drm_format_info *amd_get_format_info(const struct drm_mode_fb_cmd2 *cmd); +const struct drm_format_info *amdgpu_dm_plane_get_format_info(const struct drm_mode_fb_cmd2 *cmd); -void fill_blending_from_plane_state(const struct drm_plane_state *plane_state, +void amdgpu_dm_plane_fill_blending_from_plane_state(const struct drm_plane_state *plane_state, bool *per_pixel_alpha, bool *pre_multiplied_alpha, bool *global_alpha, int *global_alpha_value); -- cgit v1.2.3 From c0a76ae8743a8d6cfa5c06b5efa497139100bed6 Mon Sep 17 00:00:00 2001 From: David Tadokoro Date: Tue, 7 Mar 2023 19:53:41 -0300 Subject: drm/amd/display: remove legacy fields of dc_plane_cap struct The fields blends_with_above and blends_with_below of struct dc_plane_cap (defined in dc/dc.h) are boolean and set to true by default. All instances of a dc_plane_cap maintain the default values of both. Also, there is only one if statement that checks those fields and there would be the same effect if it was deleted (assuming that those fields are always going to be true). For this reason, considering both fields as legacy ones, this commit removes them and the aforementioned if statement. Reviewed-by: Rodrigo Siqueira Signed-off-by: David Tadokoro Signed-off-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 --- drivers/gpu/drm/amd/display/dc/dc.h | 2 -- drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c | 3 --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 2 -- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 2 -- drivers/gpu/drm/amd/display/dc/dcn201/dcn201_resource.c | 2 -- drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c | 2 -- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c | 2 -- drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c | 2 -- drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c | 2 -- drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c | 2 -- drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c | 2 -- drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c | 2 -- drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c | 2 -- drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c | 2 -- drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c | 2 -- drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c | 2 -- 17 files changed, 36 deletions(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 6db59972ae27..4458e00f5b15 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4351,9 +4351,6 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) if (plane->type != DC_PLANE_TYPE_DCN_UNIVERSAL) continue; - if (!plane->blends_with_above || !plane->blends_with_below) - continue; - if (!plane->pixel_format_support.argb8888) continue; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index f0a1934ebf8c..ccc27d482640 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -82,8 +82,6 @@ enum det_size { struct dc_plane_cap { enum dc_plane_type type; - uint32_t blends_with_above : 1; - uint32_t blends_with_below : 1; uint32_t per_pixel_alpha : 1; struct { uint32_t argb8888 : 1; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index f808315b2835..a4a45a6ce61e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -401,8 +401,6 @@ static const struct resource_caps stoney_resource_cap = { static const struct dc_plane_cap plane_cap = { .type = DC_PLANE_TYPE_DCE_RGB, - .blends_with_below = true, - .blends_with_above = true, .per_pixel_alpha = 1, .pixel_format_support = { @@ -428,7 +426,6 @@ static const struct dc_plane_cap plane_cap = { static const struct dc_plane_cap underlay_plane_cap = { .type = DC_PLANE_TYPE_DCE_UNDERLAY, - .blends_with_above = true, .per_pixel_alpha = 1, .pixel_format_support = { 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 6bfac8088ab0..2bb8e11f26e0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -504,8 +504,6 @@ static const struct resource_caps rv2_res_cap = { 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 = { 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 3af24ef9cb2d..00668df0938e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -670,8 +670,6 @@ static const struct resource_caps res_cap_nv10 = { 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 = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_resource.c b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_resource.c index cd46701398d9..6ea70da28aaa 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_resource.c @@ -571,8 +571,6 @@ static const struct resource_caps res_cap_dnc201 = { 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 = { 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 c10ff621cb1d..19aaa557b2db 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c @@ -609,8 +609,6 @@ static const struct resource_caps res_cap_rn_FPGA_2pipe_dsc = { 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 = { 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 b5b5320c7bef..d60c17d5a0d8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c @@ -680,8 +680,6 @@ static const struct resource_caps res_cap_dcn3 = { 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 = { 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 ee62ae3eb98f..b93b4498dba4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c @@ -651,8 +651,6 @@ static struct resource_caps res_cap_dcn301 = { 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 = { 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 03ddf4f5f065..6ccad53f1e49 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c @@ -147,8 +147,6 @@ static const struct resource_caps res_cap_dcn302 = { 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, diff --git a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c index 727f458f6ee9..5c28f7151d13 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c @@ -126,8 +126,6 @@ static const struct resource_caps res_cap_dcn303 = { 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, diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c index d3918a10773a..eaaa2e01f6d0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c @@ -827,8 +827,6 @@ static const struct resource_caps res_cap_dcn31 = { 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 = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c index f9dfbc7407ee..50ed7e09d5ba 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c @@ -855,8 +855,6 @@ static const struct resource_caps res_cap_dcn314 = { 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 = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c index 7887078c5f64..41c972c8eb19 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c @@ -824,8 +824,6 @@ static const struct resource_caps res_cap_dcn31 = { 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 = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c b/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c index dc0b49506275..9ead347a33e9 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c @@ -824,8 +824,6 @@ static const struct resource_caps res_cap_dcn31 = { 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 = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c index 87f7669e81d7..100b6df33b33 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c @@ -657,8 +657,6 @@ static const struct resource_caps res_cap_dcn32 = { 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 = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c b/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c index deaa4769be10..0f477d50e935 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c @@ -655,8 +655,6 @@ static const struct resource_caps res_cap_dcn321 = { 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 = { -- cgit v1.2.3 From a9d491d99ece898fe6fd5f7374eacb5223e1531b Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 8 Mar 2023 09:29:37 -0500 Subject: Revert "drm/amd/display: Pass proper parent for DM backlight device registration" This reverts commit d24b77e444bef83155557ebf4c2b3c551f198926. This does not work as expected. Bug: https://gitlab.gnome.org/GNOME/gnome-settings-daemon/-/issues/730 Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 4458e00f5b15..0e92bf6d286e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4181,8 +4181,7 @@ static const struct backlight_ops amdgpu_dm_backlight_ops = { }; static void -amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm, - struct amdgpu_dm_connector *aconnector) +amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm) { char bl_name[16]; struct backlight_properties props = { 0 }; @@ -4205,7 +4204,7 @@ amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm, adev_to_drm(dm->adev)->primary->index + dm->num_of_edps); dm->backlight_dev[dm->num_of_edps] = backlight_device_register(bl_name, - aconnector->base.kdev, + adev_to_drm(dm->adev)->dev, dm, &amdgpu_dm_backlight_ops, &props); @@ -4258,7 +4257,6 @@ static int initialize_plane(struct amdgpu_display_manager *dm, static void register_backlight_device(struct amdgpu_display_manager *dm, - struct amdgpu_dm_connector *aconnector, struct dc_link *link) { if ((link->connector_signal & (SIGNAL_TYPE_EDP | SIGNAL_TYPE_LVDS)) && @@ -4269,7 +4267,7 @@ static void register_backlight_device(struct amdgpu_display_manager *dm, * is better then a black screen. */ if (!dm->backlight_dev[dm->num_of_edps]) - amdgpu_dm_register_backlight_device(dm, aconnector); + amdgpu_dm_register_backlight_device(dm); if (dm->backlight_dev[dm->num_of_edps]) { dm->backlight_link[dm->num_of_edps] = link; @@ -4455,7 +4453,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) if (ret) { amdgpu_dm_update_connector_after_detect(aconnector); - register_backlight_device(dm, aconnector, link); + register_backlight_device(dm, link); if (dm->num_of_edps) update_connector_ext_caps(aconnector); -- cgit v1.2.3 From 6c5e25a0255d56e8455869cd7f90bb9be7478132 Mon Sep 17 00:00:00 2001 From: David Tadokoro Date: Tue, 7 Mar 2023 16:14:17 -0300 Subject: drm/amd/display: add prefix to amdgpu_dm_crtc.h functions Some amdgpu_dm_crtc.h functions didn't have names that indicated where they were declared. To better filter results in debug tools like ftrace, prefix these functions with 'amdgpu_dm_crtc_'. Signed-off-by: David Tadokoro Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 32 +++++++++++----------- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c | 26 +++++++++--------- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h | 14 +++++----- 3 files changed, 36 insertions(+), 36 deletions(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 0e92bf6d286e..ae994c6c65ac 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -342,7 +342,7 @@ static inline bool is_dc_timing_adjust_needed(struct dm_crtc_state *old_state, { if (new_state->freesync_config.state == VRR_STATE_ACTIVE_FIXED) return true; - else if (amdgpu_dm_vrr_active(old_state) != amdgpu_dm_vrr_active(new_state)) + else if (amdgpu_dm_crtc_vrr_active(old_state) != amdgpu_dm_crtc_vrr_active(new_state)) return true; else return false; @@ -436,7 +436,7 @@ static void dm_pflip_high_irq(void *interrupt_params) WARN_ON(!e); - vrr_active = amdgpu_dm_vrr_active_irq(amdgpu_crtc); + vrr_active = amdgpu_dm_crtc_vrr_active_irq(amdgpu_crtc); /* Fixed refresh rate, or VRR scanout position outside front-porch? */ if (!vrr_active || @@ -510,7 +510,7 @@ static void dm_vupdate_high_irq(void *interrupt_params) acrtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_VUPDATE); if (acrtc) { - vrr_active = amdgpu_dm_vrr_active_irq(acrtc); + vrr_active = amdgpu_dm_crtc_vrr_active_irq(acrtc); drm_dev = acrtc->base.dev; vblank = &drm_dev->vblank[acrtc->base.index]; previous_timestamp = atomic64_read(&irq_params->previous_timestamp); @@ -534,7 +534,7 @@ static void dm_vupdate_high_irq(void *interrupt_params) * if a pageflip happened inside front-porch. */ if (vrr_active) { - dm_crtc_handle_vblank(acrtc); + amdgpu_dm_crtc_handle_vblank(acrtc); /* BTR processing for pre-DCE12 ASICs */ if (acrtc->dm_irq_params.stream && @@ -574,7 +574,7 @@ static void dm_crtc_high_irq(void *interrupt_params) if (!acrtc) return; - vrr_active = amdgpu_dm_vrr_active_irq(acrtc); + vrr_active = amdgpu_dm_crtc_vrr_active_irq(acrtc); DC_LOG_VBLANK("crtc:%d, vupdate-vrr:%d, planes:%d\n", acrtc->crtc_id, vrr_active, acrtc->dm_irq_params.active_planes); @@ -586,7 +586,7 @@ static void dm_crtc_high_irq(void *interrupt_params) * to dm_vupdate_high_irq after end of front-porch. */ if (!vrr_active) - dm_crtc_handle_vblank(acrtc); + amdgpu_dm_crtc_handle_vblank(acrtc); /** * Following stuff must happen at start of vblank, for crc @@ -2483,11 +2483,11 @@ static void dm_gpureset_toggle_interrupts(struct amdgpu_device *adev, enable ? "enable" : "disable"); if (enable) { - rc = dm_enable_vblank(&acrtc->base); + rc = amdgpu_dm_crtc_enable_vblank(&acrtc->base); if (rc) DRM_WARN("Failed to enable vblank interrupts\n"); } else { - dm_disable_vblank(&acrtc->base); + amdgpu_dm_crtc_disable_vblank(&acrtc->base); } } @@ -7739,7 +7739,7 @@ static void update_freesync_state_on_stream( &vrr_params); if (adev->family < AMDGPU_FAMILY_AI && - amdgpu_dm_vrr_active(new_crtc_state)) { + amdgpu_dm_crtc_vrr_active(new_crtc_state)) { mod_freesync_handle_v_update(dm->freesync_module, new_stream, &vrr_params); @@ -7857,8 +7857,8 @@ static void update_stream_irq_parameters( static void amdgpu_dm_handle_vrr_transition(struct dm_crtc_state *old_state, struct dm_crtc_state *new_state) { - bool old_vrr_active = amdgpu_dm_vrr_active(old_state); - bool new_vrr_active = amdgpu_dm_vrr_active(new_state); + bool old_vrr_active = amdgpu_dm_crtc_vrr_active(old_state); + bool new_vrr_active = amdgpu_dm_crtc_vrr_active(new_state); if (!old_vrr_active && new_vrr_active) { /* Transition VRR inactive -> active: @@ -7869,7 +7869,7 @@ static void amdgpu_dm_handle_vrr_transition(struct dm_crtc_state *old_state, * We also need vupdate irq for the actual core vblank handling * at end of vblank. */ - WARN_ON(dm_set_vupdate_irq(new_state->base.crtc, true) != 0); + WARN_ON(amdgpu_dm_crtc_set_vupdate_irq(new_state->base.crtc, true) != 0); WARN_ON(drm_crtc_vblank_get(new_state->base.crtc) != 0); DRM_DEBUG_DRIVER("%s: crtc=%u VRR off->on: Get vblank ref\n", __func__, new_state->base.crtc->base.id); @@ -7877,7 +7877,7 @@ static void amdgpu_dm_handle_vrr_transition(struct dm_crtc_state *old_state, /* Transition VRR active -> inactive: * Allow vblank irq disable again for fixed refresh rate. */ - WARN_ON(dm_set_vupdate_irq(new_state->base.crtc, false) != 0); + WARN_ON(amdgpu_dm_crtc_set_vupdate_irq(new_state->base.crtc, false) != 0); drm_crtc_vblank_put(new_state->base.crtc); DRM_DEBUG_DRIVER("%s: crtc=%u VRR on->off: Drop vblank ref\n", __func__, new_state->base.crtc->base.id); @@ -7919,7 +7919,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, int planes_count = 0, vpos, hpos; unsigned long flags; u32 target_vblank, last_flip_vblank; - bool vrr_active = amdgpu_dm_vrr_active(acrtc_state); + bool vrr_active = amdgpu_dm_crtc_vrr_active(acrtc_state); bool cursor_update = false; bool pflip_present = false; bool dirty_rects_changed = false; @@ -8469,7 +8469,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) * aconnector as needed */ - if (modeset_required(new_crtc_state, dm_new_crtc_state->stream, dm_old_crtc_state->stream)) { + if (amdgpu_dm_crtc_modeset_required(new_crtc_state, dm_new_crtc_state->stream, dm_old_crtc_state->stream)) { DRM_DEBUG_ATOMIC("Atomic commit: SET crtc id %d: [%p]\n", acrtc->crtc_id, acrtc); @@ -9294,7 +9294,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm, if (modereset_required(new_crtc_state)) goto skip_modeset; - if (modeset_required(new_crtc_state, new_stream, + if (amdgpu_dm_crtc_modeset_required(new_crtc_state, new_stream, dm_old_crtc_state->stream)) { WARN_ON(dm_new_crtc_state->stream); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c index dc4f37240beb..1d924dc51a3e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c @@ -34,7 +34,7 @@ #include "amdgpu_dm_trace.h" #include "amdgpu_dm_debugfs.h" -void dm_crtc_handle_vblank(struct amdgpu_crtc *acrtc) +void amdgpu_dm_crtc_handle_vblank(struct amdgpu_crtc *acrtc) { struct drm_crtc *crtc = &acrtc->base; struct drm_device *dev = crtc->dev; @@ -54,14 +54,14 @@ void dm_crtc_handle_vblank(struct amdgpu_crtc *acrtc) spin_unlock_irqrestore(&dev->event_lock, flags); } -bool modeset_required(struct drm_crtc_state *crtc_state, +bool amdgpu_dm_crtc_modeset_required(struct drm_crtc_state *crtc_state, struct dc_stream_state *new_stream, struct dc_stream_state *old_stream) { return crtc_state->active && drm_atomic_crtc_needs_modeset(crtc_state); } -bool amdgpu_dm_vrr_active_irq(struct amdgpu_crtc *acrtc) +bool amdgpu_dm_crtc_vrr_active_irq(struct amdgpu_crtc *acrtc) { return acrtc->dm_irq_params.freesync_config.state == @@ -70,7 +70,7 @@ bool amdgpu_dm_vrr_active_irq(struct amdgpu_crtc *acrtc) VRR_STATE_ACTIVE_FIXED; } -int dm_set_vupdate_irq(struct drm_crtc *crtc, bool enable) +int amdgpu_dm_crtc_set_vupdate_irq(struct drm_crtc *crtc, bool enable) { enum dc_irq_source irq_source; struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); @@ -89,7 +89,7 @@ int dm_set_vupdate_irq(struct drm_crtc *crtc, bool enable) return rc; } -bool amdgpu_dm_vrr_active(struct dm_crtc_state *dm_state) +bool amdgpu_dm_crtc_vrr_active(struct dm_crtc_state *dm_state) { return dm_state->freesync_config.state == VRR_STATE_ACTIVE_VARIABLE || dm_state->freesync_config.state == VRR_STATE_ACTIVE_FIXED; @@ -159,11 +159,11 @@ static inline int dm_set_vblank(struct drm_crtc *crtc, bool enable) if (enable) { /* vblank irq on -> Only need vupdate irq in vrr mode */ - if (amdgpu_dm_vrr_active(acrtc_state)) - rc = dm_set_vupdate_irq(crtc, true); + if (amdgpu_dm_crtc_vrr_active(acrtc_state)) + rc = amdgpu_dm_crtc_set_vupdate_irq(crtc, true); } else { /* vblank irq off -> vupdate irq off */ - rc = dm_set_vupdate_irq(crtc, false); + rc = amdgpu_dm_crtc_set_vupdate_irq(crtc, false); } if (rc) @@ -199,12 +199,12 @@ skip: return 0; } -int dm_enable_vblank(struct drm_crtc *crtc) +int amdgpu_dm_crtc_enable_vblank(struct drm_crtc *crtc) { return dm_set_vblank(crtc, true); } -void dm_disable_vblank(struct drm_crtc *crtc) +void amdgpu_dm_crtc_disable_vblank(struct drm_crtc *crtc) { dm_set_vblank(crtc, false); } @@ -300,8 +300,8 @@ static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = { .verify_crc_source = amdgpu_dm_crtc_verify_crc_source, .get_crc_sources = amdgpu_dm_crtc_get_crc_sources, .get_vblank_counter = amdgpu_get_vblank_counter_kms, - .enable_vblank = dm_enable_vblank, - .disable_vblank = dm_disable_vblank, + .enable_vblank = amdgpu_dm_crtc_enable_vblank, + .disable_vblank = amdgpu_dm_crtc_disable_vblank, .get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp, #if defined(CONFIG_DEBUG_FS) .late_register = amdgpu_dm_crtc_late_register, @@ -381,7 +381,7 @@ static int dm_crtc_helper_atomic_check(struct drm_crtc *crtc, dm_update_crtc_active_planes(crtc, crtc_state); if (WARN_ON(unlikely(!dm_crtc_state->stream && - modeset_required(crtc_state, NULL, dm_crtc_state->stream)))) { + amdgpu_dm_crtc_modeset_required(crtc_state, NULL, dm_crtc_state->stream)))) { return ret; } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h index 1ac8692354cf..17e948753f59 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h @@ -27,21 +27,21 @@ #ifndef __AMDGPU_DM_CRTC_H__ #define __AMDGPU_DM_CRTC_H__ -void dm_crtc_handle_vblank(struct amdgpu_crtc *acrtc); +void amdgpu_dm_crtc_handle_vblank(struct amdgpu_crtc *acrtc); -bool modeset_required(struct drm_crtc_state *crtc_state, +bool amdgpu_dm_crtc_modeset_required(struct drm_crtc_state *crtc_state, struct dc_stream_state *new_stream, struct dc_stream_state *old_stream); -int dm_set_vupdate_irq(struct drm_crtc *crtc, bool enable); +int amdgpu_dm_crtc_set_vupdate_irq(struct drm_crtc *crtc, bool enable); -bool amdgpu_dm_vrr_active_irq(struct amdgpu_crtc *acrtc); +bool amdgpu_dm_crtc_vrr_active_irq(struct amdgpu_crtc *acrtc); -bool amdgpu_dm_vrr_active(struct dm_crtc_state *dm_state); +bool amdgpu_dm_crtc_vrr_active(struct dm_crtc_state *dm_state); -int dm_enable_vblank(struct drm_crtc *crtc); +int amdgpu_dm_crtc_enable_vblank(struct drm_crtc *crtc); -void dm_disable_vblank(struct drm_crtc *crtc); +void amdgpu_dm_crtc_disable_vblank(struct drm_crtc *crtc); int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, struct drm_plane *plane, -- cgit v1.2.3 From 8866d62716c918e5d09d8297281ef93155434da0 Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Thu, 9 Mar 2023 10:52:50 +0800 Subject: drm/amd/display: Use swap() instead of open coding it Swap is a function interface that provides exchange function. To avoid code duplication, we can use swap function. ./drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c:359:57-58: WARNING opportunity for swap(). Reported-by: Abaci Robot Link: https://bugzilla.openanolis.cn/show_bug.cgi?id=4448 Signed-off-by: Jiapeng Chong Signed-off-by: Hamza Mahfooz Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index ae994c6c65ac..f6d9bbce15b2 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -352,13 +352,9 @@ static inline void reverse_planes_order(struct dc_surface_update *array_of_surfa int planes_count) { int i, j; - struct dc_surface_update surface_updates_temp; - for (i = 0, j = planes_count - 1; i < j; i++, j--) { - surface_updates_temp = array_of_surface_update[i]; - array_of_surface_update[i] = array_of_surface_update[j]; - array_of_surface_update[j] = surface_updates_temp; - } + for (i = 0, j = planes_count - 1; i < j; i++, j--) + swap(array_of_surface_update[i], array_of_surface_update[j]); } /** -- cgit v1.2.3 From 566b6577849fcca743aa63d43793062aba62166c Mon Sep 17 00:00:00 2001 From: Benjamin Cheng Date: Sun, 12 Mar 2023 20:47:39 -0400 Subject: drm/amd/display: Write to correct dirty_rect When FB_DAMAGE_CLIPS are provided in a non-MPO scenario, the loop does not use the counter i. This causes the fill_dc_dity_rect() to always fill dirty_rects[0], causing graphical artifacts when a damage clip aware DRM client sends more than 1 damage clip. Instead, use the flip_addrs->dirty_rect_count which is incremented by fill_dc_dirty_rect() on a successful fill. Fixes: 30ebe41582d1 ("drm/amd/display: add FB_DAMAGE_CLIPS support") Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/2453 Signed-off-by: Benjamin Cheng Signed-off-by: Hamza Mahfooz Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index f6d9bbce15b2..92783cb97439 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -5127,9 +5127,9 @@ static void fill_dc_dirty_rects(struct drm_plane *plane, for (; flip_addrs->dirty_rect_count < num_clips; clips++) fill_dc_dirty_rect(new_plane_state->plane, - &dirty_rects[i], clips->x1, - clips->y1, clips->x2 - clips->x1, - clips->y2 - clips->y1, + &dirty_rects[flip_addrs->dirty_rect_count], + clips->x1, clips->y1, + clips->x2 - clips->x1, clips->y2 - clips->y1, &flip_addrs->dirty_rect_count, false); return; -- cgit v1.2.3 From 751281c55579f0cb0e56c9797d4663f689909681 Mon Sep 17 00:00:00 2001 From: Benjamin Cheng Date: Sun, 12 Mar 2023 20:47:39 -0400 Subject: drm/amd/display: Write to correct dirty_rect When FB_DAMAGE_CLIPS are provided in a non-MPO scenario, the loop does not use the counter i. This causes the fill_dc_dity_rect() to always fill dirty_rects[0], causing graphical artifacts when a damage clip aware DRM client sends more than 1 damage clip. Instead, use the flip_addrs->dirty_rect_count which is incremented by fill_dc_dirty_rect() on a successful fill. Fixes: 30ebe41582d1 ("drm/amd/display: add FB_DAMAGE_CLIPS support") Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/2453 Signed-off-by: Benjamin Cheng Signed-off-by: Hamza Mahfooz Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org # 6.1.x --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 009ef917dad4..32abbafd43fa 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -5105,9 +5105,9 @@ static void fill_dc_dirty_rects(struct drm_plane *plane, for (; flip_addrs->dirty_rect_count < num_clips; clips++) fill_dc_dirty_rect(new_plane_state->plane, - &dirty_rects[i], clips->x1, - clips->y1, clips->x2 - clips->x1, - clips->y2 - clips->y1, + &dirty_rects[flip_addrs->dirty_rect_count], + clips->x1, clips->y1, + clips->x2 - clips->x1, clips->y2 - clips->y1, &flip_addrs->dirty_rect_count, false); return; -- cgit v1.2.3 From 932698c88dc414e36e0683fbf6cf551b928441ac Mon Sep 17 00:00:00 2001 From: Swapnil Patel Date: Fri, 24 Feb 2023 20:16:09 -0500 Subject: drm/amd/display: default values for luminance range if they are 0 [why] Currently if invalid luminescence range is reported in edid, then the driver doesn't have default range to fallback to. [How] Add default range if, the range is 0. Reviewed-by: Roman Li Acked-by: Qingqing Zhuo Signed-off-by: Swapnil Patel Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 92783cb97439..1629a750dc55 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3007,8 +3007,14 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector) caps->aux_support = true; luminance_range = &conn_base->display_info.luminance_range; - caps->aux_min_input_signal = luminance_range->min_luminance; - caps->aux_max_input_signal = luminance_range->max_luminance; + + if (luminance_range->max_luminance) { + caps->aux_min_input_signal = luminance_range->min_luminance; + caps->aux_max_input_signal = luminance_range->max_luminance; + } else { + caps->aux_min_input_signal = 0; + caps->aux_max_input_signal = 512; + } } void amdgpu_dm_update_connector_after_detect( -- cgit v1.2.3 From 98ce7d32e2154a6676d4dc7e6877af68cebf8832 Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Thu, 23 Feb 2023 17:04:47 -0500 Subject: drm/amd/display: convert link.h functions to function pointer style [Why & How] All dc subcomponents should call another dc component via function pointers stored in a component structure. This is part of dc coding convention since the beginning. The reason behind this is to improve encapsulation and polymorphism. The function contract is extracted into a single link service structure defined in link.h header file and implemented only in link_factory.c instead of spreading across multiple files in link component file structure. Reviewed-by: Jun Lei Acked-by: Qingqing Zhuo Signed-off-by: Wenjing Liu Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 +- .../drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 2 +- drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c | 4 +- drivers/gpu/drm/amd/display/dc/core/dc.c | 33 ++- .../gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c | 2 +- .../gpu/drm/amd/display/dc/core/dc_link_exports.c | 34 +-- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 13 +- drivers/gpu/drm/amd/display/dc/dc.h | 13 +- .../amd/display/dc/dce110/dce110_hw_sequencer.c | 60 ++-- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 6 +- .../amd/display/dc/dcn10/dcn10_stream_encoder.c | 7 +- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 14 +- .../gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 9 +- .../amd/display/dc/dcn20/dcn20_stream_encoder.c | 3 +- drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hwseq.c | 4 +- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c | 2 +- .../gpu/drm/amd/display/dc/dcn30/dcn30_resource.c | 9 +- .../drm/amd/display/dc/dcn302/dcn302_resource.c | 9 +- .../drm/amd/display/dc/dcn303/dcn303_resource.c | 9 +- drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c | 10 +- .../display/dc/dcn314/dcn314_dio_stream_encoder.c | 2 +- .../gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c | 2 +- .../display/dc/dcn32/dcn32_dio_stream_encoder.c | 2 +- drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c | 13 +- .../gpu/drm/amd/display/dc/dcn32/dcn32_resource.c | 9 +- .../drm/amd/display/dc/dcn321/dcn321_resource.c | 9 +- .../gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c | 4 +- .../gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | 2 +- drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c | 53 ++++ drivers/gpu/drm/amd/display/dc/inc/link.h | 314 ++++++++++++--------- .../amd/display/dc/link/accessories/link_dp_cts.c | 1 + .../display/dc/link/accessories/link_dp_trace.c | 8 +- .../display/dc/link/accessories/link_dp_trace.h | 5 + .../drm/amd/display/dc/link/hwss/link_hwss_dio.c | 22 +- .../amd/display/dc/link/hwss/link_hwss_hpo_dp.c | 8 +- .../gpu/drm/amd/display/dc/link/link_detection.c | 2 +- .../gpu/drm/amd/display/dc/link/link_detection.h | 9 +- drivers/gpu/drm/amd/display/dc/link/link_dpms.c | 43 +-- drivers/gpu/drm/amd/display/dc/link/link_dpms.h | 23 +- drivers/gpu/drm/amd/display/dc/link/link_factory.c | 313 +++++++++++++++----- drivers/gpu/drm/amd/display/dc/link/link_factory.h | 2 + .../gpu/drm/amd/display/dc/link/link_resource.h | 4 + .../gpu/drm/amd/display/dc/link/link_validation.c | 5 +- .../gpu/drm/amd/display/dc/link/link_validation.h | 7 + .../drm/amd/display/dc/link/protocols/link_ddc.h | 28 ++ .../display/dc/link/protocols/link_dp_capability.c | 10 +- .../display/dc/link/protocols/link_dp_capability.h | 9 + .../amd/display/dc/link/protocols/link_dp_phy.h | 5 + .../display/dc/link/protocols/link_dp_training.c | 6 +- .../dc/link/protocols/link_edp_panel_control.c | 20 +- .../dc/link/protocols/link_edp_panel_control.h | 10 + .../drm/amd/display/dc/link/protocols/link_hpd.h | 3 + 52 files changed, 806 insertions(+), 393 deletions(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 1629a750dc55..e0b7ef6d1a62 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -7184,13 +7184,14 @@ static int amdgpu_dm_connector_get_modes(struct drm_connector *connector) struct edid *edid = amdgpu_dm_connector->edid; struct dc_link_settings *verified_link_cap = &amdgpu_dm_connector->dc_link->verified_link_cap; + const struct dc *dc = amdgpu_dm_connector->dc_link->dc; encoder = amdgpu_dm_connector_to_encoder(connector); if (!drm_edid_is_valid(edid)) { amdgpu_dm_connector->num_modes = drm_add_modes_noedid(connector, 640, 480); - if (link_dp_get_encoding_format(verified_link_cap) == DP_128b_132b_ENCODING) + if (dc->link_srv->dp_get_encoding_format(verified_link_cap) == DP_128b_132b_ENCODING) amdgpu_dm_connector->num_modes += drm_add_modes_noedid(connector, 1920, 1080); } else { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index f669f8a16c20..827fcb4fb3b3 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -2802,7 +2802,7 @@ static int psr_read_residency(void *data, u64 *val) struct dc_link *link = connector->dc_link; u32 residency; - link_get_psr_residency(link, &residency); + link->dc->link_srv->edp_get_psr_residency(link, &residency); *val = (u64)residency; 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 ee81d36146e4..6127d6045336 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 @@ -116,7 +116,7 @@ void clk_mgr_exit_optimized_pwr_state(const struct dc *dc, struct clk_mgr *clk_m if (!edp_link->psr_settings.psr_feature_enabled) continue; clk_mgr->psr_allow_active_cache = edp_link->psr_settings.psr_allow_active; - dc_link_set_psr_allow_active(edp_link, &allow_active, false, false, NULL); + dc->link_srv->edp_set_psr_allow_active(edp_link, &allow_active, false, false, NULL); } } @@ -135,7 +135,7 @@ void clk_mgr_optimize_pwr_state(const struct dc *dc, struct clk_mgr *clk_mgr) edp_link = edp_links[panel_inst]; if (!edp_link->psr_settings.psr_feature_enabled) continue; - dc_link_set_psr_allow_active(edp_link, + dc->link_srv->edp_set_psr_allow_active(edp_link, &clk_mgr->psr_allow_active_cache, false, false, NULL); } } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index a5f2f880610d..ae5f1b7b4fef 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -148,7 +148,7 @@ static void destroy_links(struct dc *dc) for (i = 0; i < dc->link_count; i++) { if (NULL != dc->links[i]) - link_destroy(&dc->links[i]); + dc->link_srv->destroy_link(&dc->links[i]); } } @@ -217,7 +217,7 @@ static bool create_links( link_init_params.connector_index = i; link_init_params.link_index = dc->link_count; link_init_params.dc = dc; - link = link_create(&link_init_params); + link = dc->link_srv->create_link(&link_init_params); if (link) { dc->links[dc->link_count] = link; @@ -239,7 +239,7 @@ static bool create_links( link_init_params.dc = dc; link_init_params.is_dpia_link = true; - link = link_create(&link_init_params); + link = dc->link_srv->create_link(&link_init_params); if (link) { dc->links[dc->link_count] = link; link->dc = dc; @@ -823,6 +823,9 @@ static void dc_destruct(struct dc *dc) dc_destroy_resource_pool(dc); + if (dc->link_srv) + link_destroy_link_service(&dc->link_srv); + if (dc->ctx->gpio_service) dal_gpio_service_destroy(&dc->ctx->gpio_service); @@ -982,7 +985,7 @@ static bool dc_construct(struct dc *dc, goto fail; } - dc->link_srv = link_get_link_service(); + dc->link_srv = link_create_link_service(); dc->res_pool = dc_create_resource_pool(dc, init_params, dc_ctx->dce_version); if (!dc->res_pool) @@ -1263,7 +1266,7 @@ static void disable_vbios_mode_if_required( pipe->stream_res.pix_clk_params.requested_pix_clk_100hz; if (pix_clk_100hz != requested_pix_clk_100hz) { - link_set_dpms_off(pipe); + dc->link_srv->set_dpms_off(pipe); pipe->stream->dpms_off = false; } } @@ -1718,7 +1721,7 @@ bool dc_validate_boot_timing(const struct dc *dc, return false; } - if (link_is_edp_ilr_optimization_required(link, crtc_timing)) { + if (dc->link_srv->edp_is_ilr_optimization_required(link, crtc_timing)) { DC_LOG_EVENT_LINK_TRAINING("Seamless boot disabled to optimize eDP link rate\n"); return false; } @@ -3192,7 +3195,9 @@ static void commit_planes_do_stream_update(struct dc *dc, dc->hwss.update_info_frame(pipe_ctx); if (dc_is_dp_signal(pipe_ctx->stream->signal)) - link_dp_source_sequence_trace(pipe_ctx->stream->link, DPCD_SOURCE_SEQ_AFTER_UPDATE_INFO_FRAME); + dc->link_srv->dp_trace_source_sequence( + pipe_ctx->stream->link, + DPCD_SOURCE_SEQ_AFTER_UPDATE_INFO_FRAME); } if (stream_update->hdr_static_metadata && @@ -3228,13 +3233,15 @@ static void commit_planes_do_stream_update(struct dc *dc, continue; if (stream_update->dsc_config) - link_update_dsc_config(pipe_ctx); + dc->link_srv->update_dsc_config(pipe_ctx); if (stream_update->mst_bw_update) { if (stream_update->mst_bw_update->is_increase) - link_increase_mst_payload(pipe_ctx, stream_update->mst_bw_update->mst_stream_bw); + dc->link_srv->increase_mst_payload(pipe_ctx, + stream_update->mst_bw_update->mst_stream_bw); else - link_reduce_mst_payload(pipe_ctx, stream_update->mst_bw_update->mst_stream_bw); + dc->link_srv->reduce_mst_payload(pipe_ctx, + stream_update->mst_bw_update->mst_stream_bw); } if (stream_update->pending_test_pattern) { @@ -3248,7 +3255,7 @@ static void commit_planes_do_stream_update(struct dc *dc, if (stream_update->dpms_off) { if (*stream_update->dpms_off) { - link_set_dpms_off(pipe_ctx); + dc->link_srv->set_dpms_off(pipe_ctx); /* for dpms, keep acquired resources*/ if (pipe_ctx->stream_res.audio && !dc->debug.az_endpoint_mute_only) pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio); @@ -3258,7 +3265,7 @@ static void commit_planes_do_stream_update(struct dc *dc, } else { if (get_seamless_boot_stream_count(context) == 0) dc->hwss.prepare_bandwidth(dc, dc->current_state); - link_set_dpms_on(dc->current_state, pipe_ctx); + dc->link_srv->set_dpms_on(dc->current_state, pipe_ctx); } } @@ -4322,7 +4329,7 @@ void dc_resume(struct dc *dc) uint32_t i; for (i = 0; i < dc->link_count; i++) - link_resume(dc->links[i]); + dc->link_srv->resume(dc->links[i]); } bool dc_is_dmcu_initialized(struct dc *dc) 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 index 74e465ba158d..41198c729d90 100644 --- 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 @@ -48,7 +48,7 @@ static bool is_dig_link_enc_stream(struct dc_stream_state *stream) /* DIGs do not support DP2.0 streams with 128b/132b encoding. */ struct dc_link_settings link_settings = {0}; - link_decide_link_settings(stream, &link_settings); + stream->ctx->dc->link_srv->dp_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; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c index 217c80db190d..58fa911b1417 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c @@ -80,67 +80,63 @@ bool dc_get_edp_link_panel_inst(const struct dc *dc, bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) { - return link_detect(link, reason); + return link->dc->link_srv->detect_link(link, reason); } bool dc_link_detect_connection_type(struct dc_link *link, enum dc_connection_type *type) { - return link_detect_connection_type(link, type); + return link->dc->link_srv->detect_connection_type(link, type); } const struct dc_link_status *dc_link_get_status(const struct dc_link *link) { - return link_get_status(link); + return link->dc->link_srv->get_status(link); } /* return true if the connected receiver supports the hdcp version */ bool dc_link_is_hdcp14(struct dc_link *link, enum signal_type signal) { - return link_is_hdcp14(link, signal); + return link->dc->link_srv->is_hdcp1x_supported(link, signal); } bool dc_link_is_hdcp22(struct dc_link *link, enum signal_type signal) { - return link_is_hdcp22(link, signal); + return link->dc->link_srv->is_hdcp2x_supported(link, signal); } void dc_link_clear_dprx_states(struct dc_link *link) { - link_clear_dprx_states(link); + link->dc->link_srv->clear_dprx_states(link); } bool dc_link_reset_cur_dp_mst_topology(struct dc_link *link) { - return link_reset_cur_dp_mst_topology(link); + return link->dc->link_srv->reset_cur_dp_mst_topology(link); } uint32_t dc_link_bandwidth_kbps( const struct dc_link *link, const struct dc_link_settings *link_settings) { - return dp_link_bandwidth_kbps(link, link_settings); -} - -uint32_t dc_bandwidth_in_kbps_from_timing( - const struct dc_crtc_timing *timing) -{ - return link_timing_bandwidth_kbps(timing); + return link->dc->link_srv->dp_link_bandwidth_kbps(link, link_settings); } void dc_get_cur_link_res_map(const struct dc *dc, uint32_t *map) { - link_get_cur_res_map(dc, map); + dc->link_srv->get_cur_res_map(dc, map); } void dc_restore_link_res_map(const struct dc *dc, uint32_t *map) { - link_restore_res_map(dc, map); + dc->link_srv->restore_res_map(dc, map); } bool dc_link_update_dsc_config(struct pipe_ctx *pipe_ctx) { - return link_update_dsc_config(pipe_ctx); + struct dc_link *link = pipe_ctx->stream->link; + + return link->dc->link_srv->update_dsc_config(pipe_ctx); } bool dc_is_oem_i2c_device_present( @@ -210,8 +206,8 @@ void dc_link_set_drive_settings(struct dc *dc, { struct link_resource link_res; - link_get_cur_link_res(link, &link_res); - dp_set_drive_settings(link, &link_res, lt_settings); + dc->link_srv->get_cur_link_res(link, &link_res); + dc->link_srv->dp_set_drive_settings(link, &link_res, lt_settings); } void dc_link_set_preferred_link_settings(struct dc *dc, 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 2e3b2fd23b56..85d54bfb595c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -2213,7 +2213,7 @@ enum dc_status dc_remove_stream_from_ctx( del_pipe->stream_res.stream_enc, false); - if (link_is_dp_128b_132b_signal(del_pipe)) { + if (dc->link_srv->dp_is_128b_132b_signal(del_pipe)) { update_hpo_dp_stream_engine_usage( &new_ctx->res_ctx, dc->res_pool, del_pipe->stream_res.hpo_dp_stream_enc, @@ -2513,9 +2513,10 @@ enum dc_status resource_map_pool_resources( * and link settings */ if (dc_is_dp_signal(stream->signal)) { - if (!link_decide_link_settings(stream, &pipe_ctx->link_config.dp_link_settings)) + if (!dc->link_srv->dp_decide_link_settings(stream, &pipe_ctx->link_config.dp_link_settings)) return DC_FAIL_DP_LINK_BANDWIDTH; - if (link_dp_get_encoding_format(&pipe_ctx->link_config.dp_link_settings) == DP_128b_132b_ENCODING) { + if (dc->link_srv->dp_get_encoding_format( + &pipe_ctx->link_config.dp_link_settings) == DP_128b_132b_ENCODING) { pipe_ctx->stream_res.hpo_dp_stream_enc = find_first_free_match_hpo_dp_stream_enc_for_link( &context->res_ctx, pool, stream); @@ -3685,7 +3686,7 @@ enum dc_status dc_validate_stream(struct dc *dc, struct dc_stream_state *stream) /* TODO: validate audio ASIC caps, encoder */ if (res == DC_OK) - res = link_validate_mode_timing(stream, + res = dc->link_srv->validate_mode_timing(stream, link, &stream->timing); @@ -3812,7 +3813,7 @@ bool get_temp_dp_link_res(struct dc_link *link, memset(link_res, 0, sizeof(*link_res)); - if (link_dp_get_encoding_format(link_settings) == DP_128b_132b_ENCODING) { + if (dc->link_srv->dp_get_encoding_format(link_settings) == DP_128b_132b_ENCODING) { link_res->hpo_dp_link_enc = get_temp_hpo_dp_link_enc(res_ctx, dc->res_pool, link); if (!link_res->hpo_dp_link_enc) @@ -4046,7 +4047,7 @@ enum dc_status update_dp_encoder_resources_for_test_harness(const struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx) { - if (link_dp_get_encoding_format(&pipe_ctx->link_config.dp_link_settings) == DP_128b_132b_ENCODING) { + if (dc->link_srv->dp_get_encoding_format(&pipe_ctx->link_config.dp_link_settings) == DP_128b_132b_ENCODING) { if (pipe_ctx->stream_res.hpo_dp_stream_enc == NULL) { pipe_ctx->stream_res.hpo_dp_stream_enc = find_first_free_match_hpo_dp_stream_enc_for_link( diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index ccc27d482640..3f25a1620f4f 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -889,7 +889,7 @@ struct dc { uint8_t link_count; struct dc_link *links[MAX_PIPES * 2]; - const struct link_service *link_srv; + struct link_service *link_srv; struct dc_state *current_state; struct resource_pool *res_pool; @@ -1370,6 +1370,11 @@ struct dc_plane_state *dc_get_surface_for_mpcc(struct dc *dc, uint32_t dc_get_opp_for_plane(struct dc *dc, struct dc_plane_state *plane); +/* The function returns minimum bandwidth required to drive a given timing + * return - minimum required timing bandwidth in kbps. + */ +uint32_t dc_bandwidth_in_kbps_from_timing(const struct dc_crtc_timing *timing); + /* Link Interfaces */ /* * A link contains one or more sinks and their connected status. @@ -1724,12 +1729,6 @@ uint32_t dc_link_bandwidth_kbps( const struct dc_link *link, const struct dc_link_settings *link_setting); -/* The function returns minimum bandwidth required to drive a given timing - * return - minimum required timing bandwidth in kbps. - */ -uint32_t dc_bandwidth_in_kbps_from_timing( - const struct dc_crtc_timing *timing); - /* The function takes a snapshot of current link resource allocation state * @dc: pointer to dc of the dm calling this * @map: a dc link resource snapshot defined internally to dc. 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 cb3bb5402c52..9fe0ce91db00 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 @@ -741,7 +741,7 @@ void dce110_edp_wait_for_hpd_ready( /* obtain HPD */ /* TODO what to do with this? */ - hpd = link_get_hpd_gpio(ctx->dc_bios, connector, ctx->gpio_service); + hpd = ctx->dc->link_srv->get_hpd_gpio(ctx->dc_bios, connector, ctx->gpio_service); if (!hpd) { BREAK_TO_DEBUGGER(); @@ -809,19 +809,19 @@ void dce110_edp_power_control( div64_u64(dm_get_elapse_time_in_ns( ctx, current_ts, - link_dp_trace_get_edp_poweroff_timestamp(link)), 1000000); + ctx->dc->link_srv->dp_trace_get_edp_poweroff_timestamp(link)), 1000000); unsigned long long time_since_edp_poweron_ms = div64_u64(dm_get_elapse_time_in_ns( ctx, current_ts, - link_dp_trace_get_edp_poweron_timestamp(link)), 1000000); + ctx->dc->link_srv->dp_trace_get_edp_poweron_timestamp(link)), 1000000); DC_LOG_HW_RESUME_S3( "%s: transition: power_up=%d current_ts=%llu edp_poweroff=%llu edp_poweron=%llu time_since_edp_poweroff_ms=%llu time_since_edp_poweron_ms=%llu", __func__, power_up, current_ts, - link_dp_trace_get_edp_poweroff_timestamp(link), - link_dp_trace_get_edp_poweron_timestamp(link), + ctx->dc->link_srv->dp_trace_get_edp_poweroff_timestamp(link), + ctx->dc->link_srv->dp_trace_get_edp_poweron_timestamp(link), time_since_edp_poweroff_ms, time_since_edp_poweron_ms); @@ -836,7 +836,7 @@ void dce110_edp_power_control( link->panel_config.pps.extra_t12_ms; /* Adjust remaining_min_edp_poweroff_time_ms if this is not the first time. */ - if (link_dp_trace_get_edp_poweroff_timestamp(link) != 0) { + if (ctx->dc->link_srv->dp_trace_get_edp_poweroff_timestamp(link) != 0) { if (time_since_edp_poweroff_ms < remaining_min_edp_poweroff_time_ms) remaining_min_edp_poweroff_time_ms = remaining_min_edp_poweroff_time_ms - time_since_edp_poweroff_ms; @@ -896,13 +896,13 @@ void dce110_edp_power_control( __func__, (power_up ? "On":"Off"), bp_result); - link_dp_trace_set_edp_power_timestamp(link, power_up); + ctx->dc->link_srv->dp_trace_set_edp_power_timestamp(link, power_up); DC_LOG_HW_RESUME_S3( "%s: updated values: edp_poweroff=%llu edp_poweron=%llu\n", __func__, - link_dp_trace_get_edp_poweroff_timestamp(link), - link_dp_trace_get_edp_poweron_timestamp(link)); + ctx->dc->link_srv->dp_trace_get_edp_poweroff_timestamp(link), + ctx->dc->link_srv->dp_trace_get_edp_poweron_timestamp(link)); if (bp_result != BP_RESULT_OK) DC_LOG_ERROR( @@ -930,14 +930,14 @@ void dce110_edp_wait_for_T12( return; if (!link->panel_cntl->funcs->is_panel_powered_on(link->panel_cntl) && - link_dp_trace_get_edp_poweroff_timestamp(link) != 0) { + ctx->dc->link_srv->dp_trace_get_edp_poweroff_timestamp(link) != 0) { unsigned int t12_duration = 500; // Default T12 as per spec unsigned long long current_ts = dm_get_timestamp(ctx); unsigned long long time_since_edp_poweroff_ms = div64_u64(dm_get_elapse_time_in_ns( ctx, current_ts, - link_dp_trace_get_edp_poweroff_timestamp(link)), 1000000); + ctx->dc->link_srv->dp_trace_get_edp_poweroff_timestamp(link)), 1000000); t12_duration += link->panel_config.pps.extra_t12_ms; // Add extra T12 @@ -1018,7 +1018,7 @@ void dce110_edp_backlight_control( * we shouldn't be doing power-sequencing, hence we can skip * waiting for T7-ready. */ - link_edp_receiver_ready_T7(link); + ctx->dc->link_srv->edp_receiver_ready_T7(link); else DC_LOG_DC("edp_receiver_ready_T7 skipped\n"); } @@ -1049,7 +1049,7 @@ void dce110_edp_backlight_control( if (link->dpcd_sink_ext_caps.bits.oled || link->dpcd_sink_ext_caps.bits.hdr_aux_backlight_control == 1 || link->dpcd_sink_ext_caps.bits.sdr_aux_backlight_control == 1) - link_backlight_enable_aux(link, enable); + ctx->dc->link_srv->edp_backlight_enable_aux(link, enable); /*edp 1.2*/ if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_OFF) { @@ -1061,7 +1061,7 @@ void dce110_edp_backlight_control( * we shouldn't be doing power-sequencing, hence we can skip * waiting for T9-ready. */ - link_edp_add_delay_for_T9(link); + ctx->dc->link_srv->edp_add_delay_for_T9(link); else DC_LOG_DC("edp_receiver_ready_T9 skipped\n"); } @@ -1161,7 +1161,7 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) pipe_ctx->stream_res.stream_enc); } - if (link_is_dp_128b_132b_signal(pipe_ctx)) { + if (dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->stop_dp_info_packets( pipe_ctx->stream_res.hpo_dp_stream_enc); } else if (dc_is_dp_signal(pipe_ctx->stream->signal)) @@ -1172,7 +1172,7 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) link_hwss->reset_stream_encoder(pipe_ctx); - if (link_is_dp_128b_132b_signal(pipe_ctx)) { + if (dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { dto_params.otg_inst = tg->inst; dto_params.timing = &pipe_ctx->stream->timing; dp_hpo_inst = pipe_ctx->stream_res.hpo_dp_stream_enc->inst; @@ -1181,7 +1181,7 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) dccg->funcs->set_dpstreamclk(dccg, REFCLK, tg->inst, dp_hpo_inst); } - if (link_is_dp_128b_132b_signal(pipe_ctx)) { + if (dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { /* TODO: This looks like a bug to me as we are disabling HPO IO when * we are just disabling a single HPO stream. Shouldn't we disable HPO * HW control only when HPOs for all streams are disabled? @@ -1223,7 +1223,7 @@ void dce110_blank_stream(struct pipe_ctx *pipe_ctx) link->dc->hwss.set_abm_immediate_disable(pipe_ctx); } - if (link_is_dp_128b_132b_signal(pipe_ctx)) { + if (link->dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { /* TODO - DP2.0 HW: Set ODM mode in dp hpo encoder here */ pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_blank( pipe_ctx->stream_res.hpo_dp_stream_enc); @@ -1245,7 +1245,7 @@ void dce110_blank_stream(struct pipe_ctx *pipe_ctx) * we shouldn't be doing power-sequencing, hence we can skip * waiting for T9-ready. */ - link_edp_receiver_ready_T9(link); + link->dc->link_srv->edp_receiver_ready_T9(link); } } } @@ -1428,7 +1428,7 @@ static enum dc_status dce110_enable_stream_timing( if (false == pipe_ctx->clock_source->funcs->program_pix_clk( pipe_ctx->clock_source, &pipe_ctx->stream_res.pix_clk_params, - link_dp_get_encoding_format(&pipe_ctx->link_config.dp_link_settings), + dc->link_srv->dp_get_encoding_format(&pipe_ctx->link_config.dp_link_settings), &pipe_ctx->pll_settings)) { BREAK_TO_DEBUGGER(); return DC_ERROR_UNEXPECTED; @@ -1532,7 +1532,7 @@ static enum dc_status apply_single_controller_ctx_to_hw( * To do so, move calling function enable_stream_timing to only be done AFTER calling * function core_link_enable_stream */ - if (!(hws->wa.dp_hpo_and_otg_sequence && link_is_dp_128b_132b_signal(pipe_ctx))) + if (!(hws->wa.dp_hpo_and_otg_sequence && dc->link_srv->dp_is_128b_132b_signal(pipe_ctx))) /* */ /* Do not touch stream timing on seamless boot optimization. */ if (!pipe_ctx->stream->apply_seamless_boot_optimization) @@ -1564,17 +1564,17 @@ static enum dc_status apply_single_controller_ctx_to_hw( pipe_ctx->stream_res.tg->inst); if (dc_is_dp_signal(pipe_ctx->stream->signal)) - link_dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_CONNECT_DIG_FE_OTG); + dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_CONNECT_DIG_FE_OTG); if (!stream->dpms_off) - link_set_dpms_on(context, pipe_ctx); + dc->link_srv->set_dpms_on(context, pipe_ctx); /* DCN3.1 FPGA Workaround * Need to enable HPO DP Stream Encoder before setting OTG master enable. * To do so, move calling function enable_stream_timing to only be done AFTER calling * function core_link_enable_stream */ - if (hws->wa.dp_hpo_and_otg_sequence && link_is_dp_128b_132b_signal(pipe_ctx)) { + if (hws->wa.dp_hpo_and_otg_sequence && dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { if (!pipe_ctx->stream->apply_seamless_boot_optimization) hws->funcs.enable_stream_timing(pipe_ctx, context, dc); } @@ -1600,7 +1600,7 @@ static void power_down_encoders(struct dc *dc) for (i = 0; i < dc->link_count; i++) { enum signal_type signal = dc->links[i]->connector_signal; - link_blank_dp_stream(dc->links[i], false); + dc->link_srv->blank_dp_stream(dc->links[i], false); if (signal != SIGNAL_TYPE_EDP) signal = SIGNAL_TYPE_NONE; @@ -2083,7 +2083,7 @@ static void dce110_reset_hw_ctx_wrap( * disabled already, no need to disable again. */ if (!pipe_ctx->stream || !pipe_ctx->stream->dpms_off) { - link_set_dpms_off(pipe_ctx_old); + dc->link_srv->set_dpms_off(pipe_ctx_old); /* free acquired resources*/ if (pipe_ctx_old->stream_res.audio) { @@ -3054,13 +3054,13 @@ void dce110_enable_dp_link_output( pipes[i].clock_source->funcs->program_pix_clk( pipes[i].clock_source, &pipes[i].stream_res.pix_clk_params, - link_dp_get_encoding_format(link_settings), + dc->link_srv->dp_get_encoding_format(link_settings), &pipes[i].pll_settings); } } } - if (link_dp_get_encoding_format(link_settings) == DP_8b_10b_ENCODING) { + if (dc->link_srv->dp_get_encoding_format(link_settings) == DP_8b_10b_ENCODING) { if (dc->clk_mgr->funcs->notify_link_rate_change) dc->clk_mgr->funcs->notify_link_rate_change(dc->clk_mgr, link); } @@ -3077,7 +3077,7 @@ void dce110_enable_dp_link_output( if (dmcu != NULL && dmcu->funcs->unlock_phy) dmcu->funcs->unlock_phy(dmcu); - link_dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_ENABLE_LINK_PHY); + dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_ENABLE_LINK_PHY); } void dce110_disable_link_output(struct dc_link *link, @@ -3102,7 +3102,7 @@ void dce110_disable_link_output(struct dc_link *link, link->dc->hwss.edp_power_control(link, false); else if (dmcu != NULL && dmcu->funcs->lock_phy) dmcu->funcs->unlock_phy(dmcu); - link_dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_LINK_PHY); + dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_LINK_PHY); } static const struct hw_sequencer_funcs dce110_funcs = { 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 5b34066ffcf6..7f9cceb49f4e 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 @@ -919,7 +919,7 @@ enum dc_status dcn10_enable_stream_timing( if (false == pipe_ctx->clock_source->funcs->program_pix_clk( pipe_ctx->clock_source, &pipe_ctx->stream_res.pix_clk_params, - link_dp_get_encoding_format(&pipe_ctx->link_config.dp_link_settings), + dc->link_srv->dp_get_encoding_format(&pipe_ctx->link_config.dp_link_settings), &pipe_ctx->pll_settings)) { BREAK_TO_DEBUGGER(); return DC_ERROR_UNEXPECTED; @@ -1017,7 +1017,7 @@ static void dcn10_reset_back_end_for_pipe( * VBIOS lit up eDP, so check link status too. */ if (!pipe_ctx->stream->dpms_off || link->link_status.link_active) - link_set_dpms_off(pipe_ctx); + dc->link_srv->set_dpms_off(pipe_ctx); else if (pipe_ctx->stream_res.audio) dc->hwss.disable_audio_stream(pipe_ctx); @@ -1564,7 +1564,7 @@ void dcn10_init_hw(struct dc *dc) } /* we want to turn off all dp displays before doing detection */ - link_blank_all_dp_displays(dc); + dc->link_srv->blank_all_dp_displays(dc); if (hws->funcs.enable_power_gating_plane) hws->funcs.enable_power_gating_plane(dc->hwseq, true); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c index 2e5f8dc401ff..f496e952ceec 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c @@ -933,7 +933,7 @@ void enc1_stream_encoder_dp_blank( /* disable DP stream */ REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, 0); - link_dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_DP_VID_STREAM); + link->dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_DP_VID_STREAM); /* the encoder stops sending the video stream * at the start of the vertical blanking. @@ -952,7 +952,7 @@ void enc1_stream_encoder_dp_blank( REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, true); - link_dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_FIFO_STEER_RESET); + link->dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_FIFO_STEER_RESET); } /* output video stream to link encoder */ @@ -1025,7 +1025,8 @@ void enc1_stream_encoder_dp_unblank( REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, true); - link_dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_ENABLE_DP_VID_STREAM); + link->dc->link_srv->dp_trace_source_sequence(link, + DPCD_SOURCE_SEQ_AFTER_ENABLE_DP_VID_STREAM); } void enc1_stream_encoder_set_avmute( 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 8b5181f3d13a..53669f832ba5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -720,7 +720,7 @@ enum dc_status dcn20_enable_stream_timing( if (false == pipe_ctx->clock_source->funcs->program_pix_clk( pipe_ctx->clock_source, &pipe_ctx->stream_res.pix_clk_params, - link_dp_get_encoding_format(&pipe_ctx->link_config.dp_link_settings), + dc->link_srv->dp_get_encoding_format(&pipe_ctx->link_config.dp_link_settings), &pipe_ctx->pll_settings)) { BREAK_TO_DEBUGGER(); return DC_ERROR_UNEXPECTED; @@ -2405,7 +2405,7 @@ void dcn20_unblank_stream(struct pipe_ctx *pipe_ctx, params.link_settings.link_rate = link_settings->link_rate; - if (link_is_dp_128b_132b_signal(pipe_ctx)) { + if (link->dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { /* TODO - DP2.0 HW: Set ODM mode in dp hpo encoder here */ pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_unblank( pipe_ctx->stream_res.hpo_dp_stream_enc, @@ -2458,7 +2458,7 @@ static void dcn20_reset_back_end_for_pipe( * VBIOS lit up eDP, so check link status too. */ if (!pipe_ctx->stream->dpms_off || link->link_status.link_active) - link_set_dpms_off(pipe_ctx); + dc->link_srv->set_dpms_off(pipe_ctx); else if (pipe_ctx->stream_res.audio) dc->hwss.disable_audio_stream(pipe_ctx); @@ -2478,7 +2478,7 @@ static void dcn20_reset_back_end_for_pipe( } } else if (pipe_ctx->stream_res.dsc) { - link_set_dsc_enable(pipe_ctx, false); + dc->link_srv->set_dsc_enable(pipe_ctx, false); } /* by upper caller loop, parent pipe: pipe0, will be reset last. @@ -2713,12 +2713,12 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx) unsigned int k1_div = PIXEL_RATE_DIV_NA; unsigned int k2_div = PIXEL_RATE_DIV_NA; - if (link_is_dp_128b_132b_signal(pipe_ctx)) { + if (dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { if (dc->hwseq->funcs.setup_hpo_hw_control) dc->hwseq->funcs.setup_hpo_hw_control(dc->hwseq, true); } - if (link_is_dp_128b_132b_signal(pipe_ctx)) { + if (dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { dp_hpo_inst = pipe_ctx->stream_res.hpo_dp_stream_enc->inst; dccg->funcs->set_dpstreamclk(dccg, DTBCLK0, tg->inst, dp_hpo_inst); @@ -2752,7 +2752,7 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx) dc->hwss.update_info_frame(pipe_ctx); if (dc_is_dp_signal(pipe_ctx->stream->signal)) - link_dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_UPDATE_INFO_FRAME); + dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_UPDATE_INFO_FRAME); /* enable early control to avoid corruption on DP monitor*/ active_total_with_borders = 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 00668df0938e..77ef474ced07 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -1211,8 +1211,11 @@ static void dcn20_resource_destruct(struct dcn20_resource_pool *pool) if (pool->base.pp_smu != NULL) dcn20_pp_smu_destroy(&pool->base.pp_smu); - if (pool->base.oem_device != NULL) - link_destroy_ddc_service(&pool->base.oem_device); + if (pool->base.oem_device != NULL) { + struct dc *dc = pool->base.oem_device->ctx->dc; + + dc->link_srv->destroy_ddc_service(&pool->base.oem_device); + } } struct hubp *dcn20_hubp_create( @@ -2763,7 +2766,7 @@ static bool dcn20_resource_construct( 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->base.oem_device = link_create_ddc_service(&ddc_init_data); + pool->base.oem_device = dc->link_srv->create_ddc_service(&ddc_init_data); } else { pool->base.oem_device = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c index 42865d6c0cdd..0b47aeb60e79 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c @@ -546,7 +546,8 @@ void enc2_stream_encoder_dp_unblank( REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, true); - link_dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_ENABLE_DP_VID_STREAM); + link->dc->link_srv->dp_trace_source_sequence(link, + DPCD_SOURCE_SEQ_AFTER_ENABLE_DP_VID_STREAM); } static void enc2_dp_set_odm_combine( 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 15475c7e2cf9..2a182c2f57d6 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hwseq.c @@ -132,8 +132,8 @@ void dcn21_PLAT_58856_wa(struct dc_state *context, struct pipe_ctx *pipe_ctx) return; pipe_ctx->stream->dpms_off = false; - link_set_dpms_on(context, pipe_ctx); - link_set_dpms_off(pipe_ctx); + pipe_ctx->stream->ctx->dc->link_srv->set_dpms_on(context, pipe_ctx); + pipe_ctx->stream->ctx->dc->link_srv->set_dpms_off(pipe_ctx); pipe_ctx->stream->dpms_off = true; } 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 f8733ff6970e..586de81fc2da 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c @@ -532,7 +532,7 @@ void dcn30_init_hw(struct dc *dc) } /* we want to turn off all dp displays before doing detection */ - link_blank_all_dp_displays(dc); + dc->link_srv->blank_all_dp_displays(dc); if (hws->funcs.enable_power_gating_plane) hws->funcs.enable_power_gating_plane(dc->hwseq, true); 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 d60c17d5a0d8..c9e45da6ccd1 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c @@ -1205,8 +1205,11 @@ static void dcn30_resource_destruct(struct dcn30_resource_pool *pool) if (pool->base.dccg != NULL) dcn_dccg_destroy(&pool->base.dccg); - if (pool->base.oem_device != NULL) - link_destroy_ddc_service(&pool->base.oem_device); + if (pool->base.oem_device != NULL) { + struct dc *dc = pool->base.oem_device->ctx->dc; + + dc->link_srv->destroy_ddc_service(&pool->base.oem_device); + } } static struct hubp *dcn30_hubp_create( @@ -2590,7 +2593,7 @@ static bool dcn30_resource_construct( 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->base.oem_device = link_create_ddc_service(&ddc_init_data); + pool->base.oem_device = dc->link_srv->create_ddc_service(&ddc_init_data); } else { pool->base.oem_device = NULL; } 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 6ccad53f1e49..9f93c43115ba 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c @@ -1125,8 +1125,11 @@ static void dcn302_resource_destruct(struct resource_pool *pool) if (pool->dccg != NULL) dcn_dccg_destroy(&pool->dccg); - if (pool->oem_device != NULL) - link_destroy_ddc_service(&pool->oem_device); + if (pool->oem_device != NULL) { + struct dc *dc = pool->oem_device->ctx->dc; + + dc->link_srv->destroy_ddc_service(&pool->oem_device); + } } static void dcn302_destroy_resource_pool(struct resource_pool **pool) @@ -1506,7 +1509,7 @@ static bool dcn302_resource_construct( 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 = link_create_ddc_service(&ddc_init_data); + pool->oem_device = dc->link_srv->create_ddc_service(&ddc_init_data); } else { pool->oem_device = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c index 5c28f7151d13..7f72ef882ca4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c @@ -1051,8 +1051,11 @@ static void dcn303_resource_destruct(struct resource_pool *pool) if (pool->dccg != NULL) dcn_dccg_destroy(&pool->dccg); - if (pool->oem_device != NULL) - link_destroy_ddc_service(&pool->oem_device); + if (pool->oem_device != NULL) { + struct dc *dc = pool->oem_device->ctx->dc; + + dc->link_srv->destroy_ddc_service(&pool->oem_device); + } } static void dcn303_destroy_resource_pool(struct resource_pool **pool) @@ -1417,7 +1420,7 @@ static bool dcn303_resource_construct( 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 = link_create_ddc_service(&ddc_init_data); + pool->oem_device = dc->link_srv->create_ddc_service(&ddc_init_data); } else { pool->oem_device = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c index 80a0c5a575a9..10e3cc17f71a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c @@ -202,7 +202,7 @@ void dcn31_init_hw(struct dc *dc) dmub_enable_outbox_notification(dc->ctx->dmub_srv); /* we want to turn off all dp displays before doing detection */ - link_blank_all_dp_displays(dc); + dc->link_srv->blank_all_dp_displays(dc); if (hws->funcs.enable_power_gating_plane) hws->funcs.enable_power_gating_plane(dc->hwseq, true); @@ -230,7 +230,7 @@ void dcn31_init_hw(struct dc *dc) } if (num_opps > 1) { - link_blank_all_edp_displays(dc); + dc->link_srv->blank_all_edp_displays(dc); break; } } @@ -414,7 +414,7 @@ void dcn31_update_info_frame(struct pipe_ctx *pipe_ctx) pipe_ctx->stream_res.stream_enc->funcs->update_hdmi_info_packets( pipe_ctx->stream_res.stream_enc, &pipe_ctx->stream_res.encoder_info_frame); - else if (link_is_dp_128b_132b_signal(pipe_ctx)) { + else if (pipe_ctx->stream->ctx->dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->update_dp_info_packets( pipe_ctx->stream_res.hpo_dp_stream_enc, &pipe_ctx->stream_res.encoder_info_frame); @@ -565,7 +565,7 @@ static void dcn31_reset_back_end_for_pipe( * VBIOS lit up eDP, so check link status too. */ if (!pipe_ctx->stream->dpms_off || link->link_status.link_active) - link_set_dpms_off(pipe_ctx); + dc->link_srv->set_dpms_off(pipe_ctx); else if (pipe_ctx->stream_res.audio) dc->hwss.disable_audio_stream(pipe_ctx); @@ -584,7 +584,7 @@ static void dcn31_reset_back_end_for_pipe( } } } else if (pipe_ctx->stream_res.dsc) { - link_set_dsc_enable(pipe_ctx, false); + dc->link_srv->set_dsc_enable(pipe_ctx, false); } pipe_ctx->stream = NULL; diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dio_stream_encoder.c index 742e43cb8880..467509a65fa7 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dio_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dio_stream_encoder.c @@ -372,7 +372,7 @@ static void enc314_stream_encoder_dp_unblank( */ enc314_enable_fifo(enc); - link_dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_ENABLE_DP_VID_STREAM); + link->dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_ENABLE_DP_VID_STREAM); } /* Set DSC-related configuration. diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c index 575d3501c848..bcc03426fc3e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_hwseq.c @@ -346,7 +346,7 @@ unsigned int dcn314_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsig two_pix_per_container = optc2_is_two_pixels_per_containter(&stream->timing); odm_combine_factor = get_odm_config(pipe_ctx, NULL); - if (link_is_dp_128b_132b_signal(pipe_ctx)) { + if (stream->ctx->dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { *k1_div = PIXEL_RATE_DIV_BY_1; *k2_div = PIXEL_RATE_DIV_BY_1; } else if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal) || dc_is_dvi_signal(pipe_ctx->stream->signal)) { diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.c index ccf6b181c349..c72448125976 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.c @@ -371,7 +371,7 @@ static void enc32_stream_encoder_dp_unblank( REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, true); - link_dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_ENABLE_DP_VID_STREAM); + link->dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_ENABLE_DP_VID_STREAM); } /* Set DSC-related configuration. diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c index f87db2271924..5016b1313f3d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c @@ -801,7 +801,7 @@ void dcn32_init_hw(struct dc *dc) hws->funcs.enable_power_gating_plane(dc->hwseq, true); /* we want to turn off all dp displays before doing detection */ - link_blank_all_dp_displays(dc); + dc->link_srv->blank_all_dp_displays(dc); /* If taking control over from VBIOS, we may want to optimize our first * mode set, so we need to skip powering down pipes until we know which @@ -1102,7 +1102,7 @@ unsigned int dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsign two_pix_per_container = optc2_is_two_pixels_per_containter(&stream->timing); odm_combine_factor = get_odm_config(pipe_ctx, NULL); - if (link_is_dp_128b_132b_signal(pipe_ctx)) { + if (stream->ctx->dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { *k1_div = PIXEL_RATE_DIV_BY_1; *k2_div = PIXEL_RATE_DIV_BY_1; } else if (dc_is_hdmi_tmds_signal(stream->signal) || dc_is_dvi_signal(stream->signal)) { @@ -1166,7 +1166,7 @@ void dcn32_unblank_stream(struct pipe_ctx *pipe_ctx, params.link_settings.link_rate = link_settings->link_rate; - if (link_is_dp_128b_132b_signal(pipe_ctx)) { + if (link->dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { /* TODO - DP2.0 HW: Set ODM mode in dp hpo encoder here */ pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_unblank( pipe_ctx->stream_res.hpo_dp_stream_enc, @@ -1193,7 +1193,7 @@ bool dcn32_is_dp_dig_pixel_rate_div_policy(struct pipe_ctx *pipe_ctx) if (!is_h_timing_divisible_by_2(pipe_ctx->stream)) return false; - if (dc_is_dp_signal(pipe_ctx->stream->signal) && !link_is_dp_128b_132b_signal(pipe_ctx) && + if (dc_is_dp_signal(pipe_ctx->stream->signal) && !dc->link_srv->dp_is_128b_132b_signal(pipe_ctx) && dc->debug.enable_dp_dig_pixel_rate_div_policy) return true; return false; @@ -1227,7 +1227,8 @@ static void apply_symclk_on_tx_off_wa(struct dc_link *link) pipe_ctx->clock_source->funcs->program_pix_clk( pipe_ctx->clock_source, &pipe_ctx->stream_res.pix_clk_params, - link_dp_get_encoding_format(&pipe_ctx->link_config.dp_link_settings), + dc->link_srv->dp_get_encoding_format( + &pipe_ctx->link_config.dp_link_settings), &pipe_ctx->pll_settings); link->phy_state.symclk_state = SYMCLK_ON_TX_OFF; break; @@ -1259,7 +1260,7 @@ void dcn32_disable_link_output(struct dc_link *link, else if (dmcu != NULL && dmcu->funcs->lock_phy) dmcu->funcs->unlock_phy(dmcu); - link_dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_LINK_PHY); + dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_LINK_PHY); apply_symclk_on_tx_off_wa(link); } diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c index 100b6df33b33..f6f72e7c9e86 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c @@ -1505,8 +1505,11 @@ static void dcn32_resource_destruct(struct dcn32_resource_pool *pool) if (pool->base.dccg != NULL) dcn_dccg_destroy(&pool->base.dccg); - if (pool->base.oem_device != NULL) - link_destroy_ddc_service(&pool->base.oem_device); + if (pool->base.oem_device != NULL) { + struct dc *dc = pool->base.oem_device->ctx->dc; + + dc->link_srv->destroy_ddc_service(&pool->base.oem_device); + } } @@ -2451,7 +2454,7 @@ static bool dcn32_resource_construct( 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->base.oem_device = link_create_ddc_service(&ddc_init_data); + pool->base.oem_device = dc->link_srv->create_ddc_service(&ddc_init_data); } else { pool->base.oem_device = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c b/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c index 0f477d50e935..c6a0e84885a2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c @@ -1490,8 +1490,11 @@ static void dcn321_resource_destruct(struct dcn321_resource_pool *pool) if (pool->base.dccg != NULL) dcn_dccg_destroy(&pool->base.dccg); - if (pool->base.oem_device != NULL) - link_destroy_ddc_service(&pool->base.oem_device); + if (pool->base.oem_device != NULL) { + struct dc *dc = pool->base.oem_device->ctx->dc; + + dc->link_srv->destroy_ddc_service(&pool->base.oem_device); + } } @@ -1995,7 +1998,7 @@ static bool dcn321_resource_construct( 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->base.oem_device = link_create_ddc_service(&ddc_init_data); + pool->base.oem_device = dc->link_srv->create_ddc_service(&ddc_init_data); } else { pool->base.oem_device = NULL; } diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c index f3cfc144e358..38d1f2be8cf3 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c @@ -938,7 +938,7 @@ static bool is_dtbclk_required(struct dc *dc, struct dc_state *context) for (i = 0; i < dc->res_pool->pipe_count; i++) { if (!context->res_ctx.pipe_ctx[i].stream) continue; - if (link_is_dp_128b_132b_signal(&context->res_ctx.pipe_ctx[i])) + if (dc->link_srv->dp_is_128b_132b_signal(&context->res_ctx.pipe_ctx[i])) return true; } return false; @@ -1341,7 +1341,7 @@ int dcn20_populate_dml_pipes_from_context( case SIGNAL_TYPE_DISPLAY_PORT_MST: case SIGNAL_TYPE_DISPLAY_PORT: pipes[pipe_cnt].dout.output_type = dm_dp; - if (link_is_dp_128b_132b_signal(&res_ctx->pipe_ctx[i])) + if (dc->link_srv->dp_is_128b_132b_signal(&res_ctx->pipe_ctx[i])) pipes[pipe_cnt].dout.output_type = dm_dp2p0; break; case SIGNAL_TYPE_EDP: diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c index 077674be452b..6b29d3a9520f 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c @@ -1270,7 +1270,7 @@ static bool is_dtbclk_required(struct dc *dc, struct dc_state *context) for (i = 0; i < dc->res_pool->pipe_count; i++) { if (!context->res_ctx.pipe_ctx[i].stream) continue; - if (link_is_dp_128b_132b_signal(&context->res_ctx.pipe_ctx[i])) + if (dc->link_srv->dp_is_128b_132b_signal(&context->res_ctx.pipe_ctx[i])) return true; } return false; 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 d9622a0f448a..2bdc47615543 100644 --- a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c +++ b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c @@ -47,6 +47,59 @@ static bool dsc_policy_disable_dsc_stream_overhead; #define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) #endif +uint32_t dc_bandwidth_in_kbps_from_timing( + const struct dc_crtc_timing *timing) +{ + uint32_t bits_per_channel = 0; + uint32_t kbps; + + 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); + + switch (timing->display_color_depth) { + case COLOR_DEPTH_666: + bits_per_channel = 6; + break; + case COLOR_DEPTH_888: + bits_per_channel = 8; + break; + case COLOR_DEPTH_101010: + bits_per_channel = 10; + break; + case COLOR_DEPTH_121212: + bits_per_channel = 12; + break; + case COLOR_DEPTH_141414: + bits_per_channel = 14; + break; + case COLOR_DEPTH_161616: + bits_per_channel = 16; + break; + default: + ASSERT(bits_per_channel != 0); + bits_per_channel = 8; + break; + } + + kbps = timing->pix_clk_100hz / 10; + kbps *= bits_per_channel; + + if (timing->flags.Y_ONLY != 1) { + /*Only YOnly make reduce bandwidth by 1/3 compares to RGB*/ + kbps *= 3; + if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) + kbps /= 2; + else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) + kbps = kbps * 2 / 3; + } + + return kbps; +} + + /* Forward Declerations */ static bool decide_dsc_bandwidth_range( const uint32_t min_bpp_x16, diff --git a/drivers/gpu/drm/amd/display/dc/inc/link.h b/drivers/gpu/drm/amd/display/dc/inc/link.h index 45cdf3bce2d3..11aaa7a9518a 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/link.h +++ b/drivers/gpu/drm/amd/display/dc/inc/link.h @@ -28,13 +28,58 @@ /* FILE POLICY AND INTENDED USAGE: * - * This header declares link functions exposed to dc. All functions must use - * function pointers. This header is strictly private in dc and should never be - * included by DM. If DM needs to call a new link function, it needs to be - * translated by dc_link_exports.c. + * This header defines link component function interfaces aka link_service. + * link_service provides the only entry point to link functions with function + * pointer style. This header is strictly private in dc and should never be + * included by DM because it exposes too much dc detail including all dc + * private types defined in core_types.h. Otherwise it will break DM - DC + * encapsulation and turn DM into a maintenance nightmare. + * + * The following shows a link component relation map. + * + * DM to DC: + * DM includes dc.h + * dc_link_exports.c or other dc files implement dc.h + * + * DC to Link: + * dc_link_exports.c or other dc files include link.h + * link_factory.c implements link.h + * + * Link sub-component to Link sub-component: + * link_factory.c includes --> link_xxx.h + * link_xxx.c implements link_xxx.h + + * As you can see if you ever need to add a new dc link function and call it on + * DM/dc side, it is very difficult because you will need layers of translation. + * The most appropriate approach to implement new requirements on DM/dc side is + * to extend or generalize the functionality of existing link function + * interfaces so minimal modification is needed outside link component to + * achieve your new requirements. This approach reduces or even eliminates the + * effort needed outside link component to support a new link feature. This also + * reduces code discrepancy among DMs to support the same link feature. If we + * test full code path on one version of DM, and there is no feature specific + * modification required on other DMs, then we can have higher confidence that + * the feature will run on other DMs and produce the same result. The following + * are some good examples to start with: + * + * - detect_link --> to add new link detection or capability retrieval routines + * + * - validate_mode_timing --> to add new timing validation conditions + * + * - set_dpms_on/set_dpms_off --> to include new link enablement sequences + * + * If you must add new link functions, you will need to: + * 1. declare the function pointer here under the suitable commented category. + * 2. Implement your function in the suitable link_xxx.c file. + * 3. Assign the function to link_service in link_factory.c + * 4. NEVER include link_xxx.h headers outside link component. + * 5. NEVER include link.h on DM side. */ #include "core_types.h" +struct link_service *link_create_link_service(void); +void link_destroy_link_service(struct link_service **link_srv); + struct link_init_data { const struct dc *dc; struct dc_context *ctx; /* TODO: remove 'dal' when DC is complete. */ @@ -44,8 +89,24 @@ struct link_init_data { bool is_dpia_link; }; +struct ddc_service_init_data { + struct graphics_object_id id; + struct dc_context *ctx; + struct dc_link *link; + bool is_dpia_link; +}; + struct link_service { - /* Detection */ + /************************** Factory ***********************************/ + struct dc_link *(*create_link)( + const struct link_init_data *init_params); + void (*destroy_link)(struct dc_link **link); + + + /************************** Detection *********************************/ + bool (*detect_link)(struct dc_link *link, enum dc_detect_reason reason); + bool (*detect_connection_type)(struct dc_link *link, + enum dc_connection_type *type); struct dc_sink *(*add_remote_sink)( struct dc_link *link, const uint8_t *edid, @@ -53,24 +114,90 @@ struct link_service { struct dc_sink_init_data *init_data); void (*remove_remote_sink)(struct dc_link *link, struct dc_sink *sink); bool (*get_hpd_state)(struct dc_link *link); + struct gpio *(*get_hpd_gpio)(struct dc_bios *dcb, + struct graphics_object_id link_id, + struct gpio_service *gpio_service); void (*enable_hpd)(const struct dc_link *link); void (*disable_hpd)(const struct dc_link *link); void (*enable_hpd_filter)(struct dc_link *link, bool enable); + bool (*reset_cur_dp_mst_topology)(struct dc_link *link); + const struct dc_link_status *(*get_status)(const struct dc_link *link); + bool (*is_hdcp1x_supported)(struct dc_link *link, + enum signal_type signal); + bool (*is_hdcp2x_supported)(struct dc_link *link, + enum signal_type signal); + void (*clear_dprx_states)(struct dc_link *link); + + + /*************************** Resource *********************************/ + void (*get_cur_res_map)(const struct dc *dc, uint32_t *map); + void (*restore_res_map)(const struct dc *dc, uint32_t *map); + void (*get_cur_link_res)(const struct dc_link *link, + struct link_resource *link_res); + + + /*************************** Validation *******************************/ + enum dc_status (*validate_mode_timing)( + const struct dc_stream_state *stream, + struct dc_link *link, + const struct dc_crtc_timing *timing); + uint32_t (*dp_link_bandwidth_kbps)( + const struct dc_link *link, + const struct dc_link_settings *link_settings); + + + /*************************** DPMS *************************************/ + void (*set_dpms_on)(struct dc_state *state, struct pipe_ctx *pipe_ctx); + void (*set_dpms_off)(struct pipe_ctx *pipe_ctx); + void (*resume)(struct dc_link *link); + void (*blank_all_dp_displays)(struct dc *dc); + void (*blank_all_edp_displays)(struct dc *dc); + void (*blank_dp_stream)(struct dc_link *link, bool hw_init); + enum dc_status (*increase_mst_payload)( + struct pipe_ctx *pipe_ctx, uint32_t req_pbn); + enum dc_status (*reduce_mst_payload)( + struct pipe_ctx *pipe_ctx, uint32_t req_pbn); + void (*set_dsc_on_stream)(struct pipe_ctx *pipe_ctx, bool enable); + bool (*set_dsc_enable)(struct pipe_ctx *pipe_ctx, bool enable); + bool (*update_dsc_config)(struct pipe_ctx *pipe_ctx); - /* DDC */ + + /*************************** DDC **************************************/ + struct ddc_service *(*create_ddc_service)( + struct ddc_service_init_data *ddc_init_data); + void (*destroy_ddc_service)(struct ddc_service **ddc); + bool (*query_ddc_data)( + struct ddc_service *ddc, + uint32_t address, + uint8_t *write_buf, + uint32_t write_size, + uint8_t *read_buf, + uint32_t read_size); int (*aux_transfer_raw)(struct ddc_service *ddc, struct aux_payload *payload, enum aux_return_code_type *operation_result); + bool (*aux_transfer_with_retries_no_mutex)(struct ddc_service *ddc, + struct aux_payload *payload); + bool (*is_in_aux_transaction_mode)(struct ddc_service *ddc); + uint32_t (*get_aux_defer_delay)(struct ddc_service *ddc); + - /* DP Capability */ + /*************************** DP Capability ****************************/ bool (*dp_is_sink_present)(struct dc_link *link); bool (*dp_is_fec_supported)(const struct dc_link *link); + bool (*dp_is_128b_132b_signal)(struct pipe_ctx *pipe_ctx); bool (*dp_get_max_link_enc_cap)(const struct dc_link *link, struct dc_link_settings *max_link_enc_cap); const struct dc_link_settings *(*dp_get_verified_link_cap)( const struct dc_link *link); + enum dp_link_encoding (*dp_get_encoding_format)( + const struct dc_link_settings *link_settings); bool (*dp_should_enable_fec)(const struct dc_link *link); - enum dp_link_encoding (*mst_decide_link_encoding_format)(const struct dc_link *link); + bool (*dp_decide_link_settings)( + struct dc_stream_state *stream, + struct dc_link_settings *link_setting); + enum dp_link_encoding (*mst_decide_link_encoding_format)( + const struct dc_link *link); bool (*edp_decide_link_settings)(struct dc_link *link, struct dc_link_settings *link_setting, uint32_t req_bw); uint32_t (*bw_kbps_from_raw_frl_link_rate_data)(uint8_t bw); @@ -78,12 +205,20 @@ struct link_service { enum lttpr_mode (*dp_decide_lttpr_mode)(struct dc_link *link, struct dc_link_settings *link_setting); - /* DP DPIA/PHY */ - int (*dpia_handle_usb4_bandwidth_allocation_for_link)(struct dc_link *link, int peak_bw); - void (*dpia_handle_bw_alloc_response)(struct dc_link *link, uint8_t bw, uint8_t result); + + /*************************** DP DPIA/PHY ******************************/ + int (*dpia_handle_usb4_bandwidth_allocation_for_link)( + struct dc_link *link, int peak_bw); + void (*dpia_handle_bw_alloc_response)( + struct dc_link *link, uint8_t bw, uint8_t result); + void (*dp_set_drive_settings)( + struct dc_link *link, + const struct link_resource *link_res, + struct link_training_settings *lt_settings); void (*dpcd_write_rx_power_ctrl)(struct dc_link *link, bool on); - /* DP IRQ Handler */ + + /*************************** DP IRQ Handler ***************************/ bool (*dp_parse_link_loss_status)( struct dc_link *link, union hpd_irq_data *hpd_irq_dpcd_data); @@ -93,11 +228,14 @@ struct link_service { struct dc_link *link, union hpd_irq_data *irq_data); bool (*dp_handle_hpd_rx_irq)(struct dc_link *link, - union hpd_irq_data *out_hpd_irq_dpcd_data, bool *out_link_loss, + union hpd_irq_data *out_hpd_irq_dpcd_data, + bool *out_link_loss, bool defer_handling, bool *has_left_work); - /* eDP Panel Control */ - void (*edp_panel_backlight_power_on)(struct dc_link *link, bool wait_for_hpd); + + /*************************** eDP Panel Control ************************/ + void (*edp_panel_backlight_power_on)( + struct dc_link *link, bool wait_for_hpd); int (*edp_get_backlight_level)(const struct dc_link *link); bool (*edp_get_backlight_level_nits)(struct dc_link *link, uint32_t *backlight_millinits_avg, @@ -110,16 +248,35 @@ struct link_service { uint32_t backlight_millinits, uint32_t transition_time_in_ms); int (*edp_get_target_backlight_pwm)(const struct dc_link *link); - bool (*edp_get_psr_state)(const struct dc_link *link, enum dc_psr_state *state); - bool (*edp_set_psr_allow_active)(struct dc_link *link, const bool *allow_active, - bool wait, bool force_static, const unsigned int *power_opts); + bool (*edp_get_psr_state)( + const struct dc_link *link, enum dc_psr_state *state); + bool (*edp_set_psr_allow_active)( + struct dc_link *link, + const bool *allow_active, + bool wait, + bool force_static, + const unsigned int *power_opts); bool (*edp_setup_psr)(struct dc_link *link, const struct dc_stream_state *stream, struct psr_config *psr_config, struct psr_context *psr_context); + bool (*edp_set_sink_vtotal_in_psr_active)( + const struct dc_link *link, + uint16_t psr_vtotal_idle, + uint16_t psr_vtotal_su); + void (*edp_get_psr_residency)( + const struct dc_link *link, uint32_t *residency); bool (*edp_wait_for_t12)(struct dc_link *link); + bool (*edp_is_ilr_optimization_required)(struct dc_link *link, + struct dc_crtc_timing *crtc_timing); + bool (*edp_backlight_enable_aux)(struct dc_link *link, bool enable); + void (*edp_add_delay_for_T9)(struct dc_link *link); + bool (*edp_receiver_ready_T9)(struct dc_link *link); + bool (*edp_receiver_ready_T7)(struct dc_link *link); + bool (*edp_power_alpm_dpcd_enable)(struct dc_link *link, bool enable); - /* DP CTS */ + + /*************************** DP CTS ************************************/ void (*dp_handle_automated_test)(struct dc_link *link); bool (*dp_set_test_pattern)( struct dc_link *link, @@ -137,7 +294,8 @@ struct link_service { struct dc_link *link, bool skip_immediate_retrain); - /* DP Trace */ + + /*************************** DP Trace *********************************/ bool (*dp_trace_is_initialized)(struct dc_link *link); void (*dp_trace_set_is_logged_flag)(struct dc_link *link, bool in_detection, @@ -148,115 +306,11 @@ struct link_service { const struct dp_trace_lt_counts *(*dp_trace_get_lt_counts)( struct dc_link *link, bool in_detection); unsigned int (*dp_trace_get_link_loss_count)(struct dc_link *link); + void (*dp_trace_set_edp_power_timestamp)(struct dc_link *link, + bool power_up); + uint64_t (*dp_trace_get_edp_poweron_timestamp)(struct dc_link *link); + uint64_t (*dp_trace_get_edp_poweroff_timestamp)(struct dc_link *link); + void (*dp_trace_source_sequence)( + struct dc_link *link, uint8_t dp_test_mode); }; - -struct dc_link *link_create(const struct link_init_data *init_params); -void link_destroy(struct dc_link **link); -const struct link_service *link_get_link_service(void); - -// TODO - convert any function declarations below to function pointers -struct gpio *link_get_hpd_gpio(struct dc_bios *dcb, - struct graphics_object_id link_id, - struct gpio_service *gpio_service); - -struct ddc_service_init_data { - struct graphics_object_id id; - struct dc_context *ctx; - struct dc_link *link; - bool is_dpia_link; -}; - -struct ddc_service *link_create_ddc_service( - struct ddc_service_init_data *ddc_init_data); - -void link_destroy_ddc_service(struct ddc_service **ddc); - -bool link_is_in_aux_transaction_mode(struct ddc_service *ddc); - -bool link_query_ddc_data( - struct ddc_service *ddc, - uint32_t address, - uint8_t *write_buf, - uint32_t write_size, - uint8_t *read_buf, - uint32_t read_size); - - -/* Attempt to submit an aux payload, retrying on timeouts, defers, and busy - * states as outlined in the DP spec. Returns true if the request was - * successful. - * - * NOTE: The function requires explicit mutex on DM side in order to prevent - * potential race condition. DC components should call the dpcd read/write - * function in dm_helpers in order to access dpcd safely - */ -bool link_aux_transfer_with_retries_no_mutex(struct ddc_service *ddc, - struct aux_payload *payload); - -uint32_t link_get_aux_defer_delay(struct ddc_service *ddc); - -bool link_is_dp_128b_132b_signal(struct pipe_ctx *pipe_ctx); - -enum dp_link_encoding link_dp_get_encoding_format( - const struct dc_link_settings *link_settings); - -bool link_decide_link_settings( - struct dc_stream_state *stream, - struct dc_link_settings *link_setting); - -void link_dp_trace_set_edp_power_timestamp(struct dc_link *link, - bool power_up); -uint64_t link_dp_trace_get_edp_poweron_timestamp(struct dc_link *link); -uint64_t link_dp_trace_get_edp_poweroff_timestamp(struct dc_link *link); - -bool link_is_edp_ilr_optimization_required(struct dc_link *link, - struct dc_crtc_timing *crtc_timing); - -bool link_backlight_enable_aux(struct dc_link *link, bool enable); -void link_edp_add_delay_for_T9(struct dc_link *link); -bool link_edp_receiver_ready_T9(struct dc_link *link); -bool link_edp_receiver_ready_T7(struct dc_link *link); -bool link_power_alpm_dpcd_enable(struct dc_link *link, bool enable); -bool link_set_sink_vtotal_in_psr_active(const struct dc_link *link, - uint16_t psr_vtotal_idle, uint16_t psr_vtotal_su); -void link_get_psr_residency(const struct dc_link *link, uint32_t *residency); -enum dc_status link_increase_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t req_pbn); -enum dc_status link_reduce_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t req_pbn); -void link_blank_all_dp_displays(struct dc *dc); -void link_blank_all_edp_displays(struct dc *dc); -void link_blank_dp_stream(struct dc_link *link, bool hw_init); -void link_resume(struct dc_link *link); -void link_set_dpms_on( - struct dc_state *state, - struct pipe_ctx *pipe_ctx); -void link_set_dpms_off(struct pipe_ctx *pipe_ctx); -void link_dp_source_sequence_trace(struct dc_link *link, uint8_t dp_test_mode); -void link_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable); -bool link_set_dsc_enable(struct pipe_ctx *pipe_ctx, bool enable); -bool link_update_dsc_config(struct pipe_ctx *pipe_ctx); -enum dc_status link_validate_mode_timing( - const struct dc_stream_state *stream, - struct dc_link *link, - const struct dc_crtc_timing *timing); -bool link_detect(struct dc_link *link, enum dc_detect_reason reason); -bool link_detect_connection_type(struct dc_link *link, - enum dc_connection_type *type); -const struct dc_link_status *link_get_status(const struct dc_link *link); -/* return true if the connected receiver supports the hdcp version */ -bool link_is_hdcp14(struct dc_link *link, enum signal_type signal); -bool link_is_hdcp22(struct dc_link *link, enum signal_type signal); -void link_clear_dprx_states(struct dc_link *link); -bool link_reset_cur_dp_mst_topology(struct dc_link *link); -uint32_t dp_link_bandwidth_kbps( - const struct dc_link *link, - const struct dc_link_settings *link_settings); -uint32_t link_timing_bandwidth_kbps(const struct dc_crtc_timing *timing); -void link_get_cur_res_map(const struct dc *dc, uint32_t *map); -void link_restore_res_map(const struct dc *dc, uint32_t *map); -void link_get_cur_link_res(const struct dc_link *link, - struct link_resource *link_res); -void dp_set_drive_settings( - struct dc_link *link, - const struct link_resource *link_res, - struct link_training_settings *lt_settings); #endif /* __DC_LINK_HPD_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c index 704373d4d110..db9f1baa27e5 100644 --- a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c +++ b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c @@ -28,6 +28,7 @@ #include "link/protocols/link_dp_training.h" #include "link/protocols/link_dp_phy.h" #include "link/protocols/link_dp_training_fixed_vs_pe_retimer.h" +#include "link/protocols/link_dp_capability.h" #include "link/link_dpms.h" #include "resource.h" #include "dm_helpers.h" diff --git a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_trace.c b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_trace.c index 277fe9137a97..fbcd8fb58ea8 100644 --- a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_trace.c +++ b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_trace.c @@ -145,7 +145,7 @@ unsigned int dp_trace_get_link_loss_count(struct dc_link *link) return link->dp_trace.link_loss_count; } -void link_dp_trace_set_edp_power_timestamp(struct dc_link *link, +void dp_trace_set_edp_power_timestamp(struct dc_link *link, bool power_up) { if (!power_up) @@ -155,17 +155,17 @@ void link_dp_trace_set_edp_power_timestamp(struct dc_link *link, link->dp_trace.edp_trace_power_timestamps.poweron = dm_get_timestamp(link->dc->ctx); } -uint64_t link_dp_trace_get_edp_poweron_timestamp(struct dc_link *link) +uint64_t dp_trace_get_edp_poweron_timestamp(struct dc_link *link) { return link->dp_trace.edp_trace_power_timestamps.poweron; } -uint64_t link_dp_trace_get_edp_poweroff_timestamp(struct dc_link *link) +uint64_t dp_trace_get_edp_poweroff_timestamp(struct dc_link *link) { return link->dp_trace.edp_trace_power_timestamps.poweroff; } -void link_dp_source_sequence_trace(struct dc_link *link, uint8_t dp_test_mode) +void dp_trace_source_sequence(struct dc_link *link, uint8_t dp_test_mode) { if (link != NULL && link->dc->debug.enable_driver_sequence_debug) core_link_write_dpcd(link, DP_SOURCE_SEQUENCE, diff --git a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_trace.h b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_trace.h index 9a0aff81a251..ab437a0c9101 100644 --- a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_trace.h +++ b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_trace.h @@ -54,5 +54,10 @@ unsigned long long dp_trace_get_lt_end_timestamp(struct dc_link *link, const struct dp_trace_lt_counts *dp_trace_get_lt_counts(struct dc_link *link, bool in_detection); unsigned int dp_trace_get_link_loss_count(struct dc_link *link); +void dp_trace_set_edp_power_timestamp(struct dc_link *link, + bool power_up); +uint64_t dp_trace_get_edp_poweron_timestamp(struct dc_link *link); +uint64_t dp_trace_get_edp_poweroff_timestamp(struct dc_link *link); +void dp_trace_source_sequence(struct dc_link *link, uint8_t dp_test_mode); #endif /* __LINK_DP_TRACE_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.c b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.c index b092b00b3599..bebf9c4c8702 100644 --- a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.c +++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.c @@ -44,7 +44,7 @@ void setup_dio_stream_encoder(struct pipe_ctx *pipe_ctx) link_enc->funcs->connect_dig_be_to_fe(link_enc, pipe_ctx->stream_res.stream_enc->id, true); if (dc_is_dp_signal(pipe_ctx->stream->signal)) - link_dp_source_sequence_trace(pipe_ctx->stream->link, + pipe_ctx->stream->ctx->dc->link_srv->dp_trace_source_sequence(pipe_ctx->stream->link, DPCD_SOURCE_SEQ_AFTER_CONNECT_DIG_FE_BE); if (stream_enc->funcs->enable_fifo) stream_enc->funcs->enable_fifo(stream_enc); @@ -63,7 +63,8 @@ void reset_dio_stream_encoder(struct pipe_ctx *pipe_ctx) pipe_ctx->stream_res.stream_enc->id, false); if (dc_is_dp_signal(pipe_ctx->stream->signal)) - link_dp_source_sequence_trace(pipe_ctx->stream->link, + pipe_ctx->stream->ctx->dc->link_srv->dp_trace_source_sequence( + pipe_ctx->stream->link, DPCD_SOURCE_SEQ_AFTER_DISCONNECT_DIG_FE_BE); } @@ -105,7 +106,8 @@ void setup_dio_stream_attribute(struct pipe_ctx *pipe_ctx) &stream->timing); if (dc_is_dp_signal(stream->signal)) - link_dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DP_STREAM_ATTR); + link->dc->link_srv->dp_trace_source_sequence(link, + DPCD_SOURCE_SEQ_AFTER_DP_STREAM_ATTR); } void enable_dio_dp_link_output(struct dc_link *link, @@ -126,7 +128,8 @@ void enable_dio_dp_link_output(struct dc_link *link, link_enc, link_settings, clock_source); - link_dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_ENABLE_LINK_PHY); + link->dc->link_srv->dp_trace_source_sequence(link, + DPCD_SOURCE_SEQ_AFTER_ENABLE_LINK_PHY); } void disable_dio_link_output(struct dc_link *link, @@ -136,7 +139,8 @@ void disable_dio_link_output(struct dc_link *link, struct link_encoder *link_enc = link_enc_cfg_get_link_enc(link); link_enc->funcs->disable_output(link_enc, signal); - link_dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_LINK_PHY); + link->dc->link_srv->dp_trace_source_sequence(link, + DPCD_SOURCE_SEQ_AFTER_DISABLE_LINK_PHY); } void set_dio_dp_link_test_pattern(struct dc_link *link, @@ -146,7 +150,7 @@ void set_dio_dp_link_test_pattern(struct dc_link *link, struct link_encoder *link_enc = link_enc_cfg_get_link_enc(link); link_enc->funcs->dp_set_phy_pattern(link_enc, tp_params); - link_dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_SET_SOURCE_PATTERN); + link->dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_SET_SOURCE_PATTERN); } void set_dio_dp_lane_settings(struct dc_link *link, @@ -195,7 +199,8 @@ void enable_dio_audio_packet(struct pipe_ctx *pipe_ctx) pipe_ctx->stream_res.stream_enc, false); if (dc_is_dp_signal(pipe_ctx->stream->signal)) - link_dp_source_sequence_trace(pipe_ctx->stream->link, + pipe_ctx->stream->ctx->dc->link_srv->dp_trace_source_sequence( + pipe_ctx->stream->link, DPCD_SOURCE_SEQ_AFTER_ENABLE_AUDIO_STREAM); } @@ -214,7 +219,8 @@ void disable_dio_audio_packet(struct pipe_ctx *pipe_ctx) } if (dc_is_dp_signal(pipe_ctx->stream->signal)) - link_dp_source_sequence_trace(pipe_ctx->stream->link, + pipe_ctx->stream->ctx->dc->link_srv->dp_trace_source_sequence( + pipe_ctx->stream->link, DPCD_SOURCE_SEQ_AFTER_DISABLE_AUDIO_STREAM); } diff --git a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_dp.c b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_dp.c index aa1c5e253b43..edd7d026a762 100644 --- a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_dp.c +++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_dp.c @@ -68,7 +68,8 @@ static void set_hpo_dp_hblank_min_symbol_width(struct pipe_ctx *pipe_ctx, struct dc_crtc_timing *timing = &pipe_ctx->stream->timing; struct fixed31_32 h_blank_in_ms, time_slot_in_ms, mtp_cnt_per_h_blank; uint32_t link_bw_in_kbps = - dc_link_bandwidth_kbps(pipe_ctx->stream->link, link_settings); + hpo_dp_stream_encoder->ctx->dc->link_srv->dp_link_bandwidth_kbps( + pipe_ctx->stream->link, link_settings); uint16_t hblank_min_symbol_width = 0; if (link_bw_in_kbps > 0) { @@ -115,7 +116,8 @@ static void setup_hpo_dp_stream_attribute(struct pipe_ctx *pipe_ctx) stream->use_vsc_sdp_for_colorimetry, stream->timing.flags.DSC, false); - link_dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DP_STREAM_ATTR); + link->dc->link_srv->dp_trace_source_sequence(link, + DPCD_SOURCE_SEQ_AFTER_DP_STREAM_ATTR); } static void enable_hpo_dp_fpga_link_output(struct dc_link *link, @@ -201,7 +203,7 @@ static void set_hpo_dp_link_test_pattern(struct dc_link *link, { link_res->hpo_dp_link_enc->funcs->set_link_test_pattern( link_res->hpo_dp_link_enc, tp_params); - link_dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_SET_SOURCE_PATTERN); + link->dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_SET_SOURCE_PATTERN); } static void set_hpo_dp_lane_settings(struct dc_link *link, diff --git a/drivers/gpu/drm/amd/display/dc/link/link_detection.c b/drivers/gpu/drm/amd/display/dc/link/link_detection.c index a51f761ba018..13e5222249ec 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_detection.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_detection.c @@ -876,7 +876,7 @@ static bool detect_link_and_local_sink(struct dc_link *link, return true; } - if (!dc_link_detect_connection_type(link, &new_connection_type)) { + if (!link_detect_connection_type(link, &new_connection_type)) { BREAK_TO_DEBUGGER(); return false; } diff --git a/drivers/gpu/drm/amd/display/dc/link/link_detection.h b/drivers/gpu/drm/amd/display/dc/link/link_detection.h index 4b1731c4fd3d..7da05078721e 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_detection.h +++ b/drivers/gpu/drm/amd/display/dc/link/link_detection.h @@ -26,11 +26,18 @@ #ifndef __DC_LINK_DETECTION_H__ #define __DC_LINK_DETECTION_H__ #include "link.h" +bool link_detect(struct dc_link *link, enum dc_detect_reason reason); +bool link_detect_connection_type(struct dc_link *link, + enum dc_connection_type *type); struct dc_sink *link_add_remote_sink( struct dc_link *link, const uint8_t *edid, int len, struct dc_sink_init_data *init_data); void link_remove_remote_sink(struct dc_link *link, struct dc_sink *sink); - +bool link_reset_cur_dp_mst_topology(struct dc_link *link); +const struct dc_link_status *link_get_status(const struct dc_link *link); +bool link_is_hdcp14(struct dc_link *link, enum signal_type signal); +bool link_is_hdcp22(struct dc_link *link, enum signal_type signal); +void link_clear_dprx_states(struct dc_link *link); #endif /* __DC_LINK_DETECTION_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c index 00d441cacbff..020d668ce09e 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c @@ -37,6 +37,7 @@ #include "link_dpms.h" #include "link_hwss.h" +#include "link_validation.h" #include "accessories/link_fpga.h" #include "accessories/link_dp_trace.h" #include "protocols/link_dpcd.h" @@ -672,7 +673,7 @@ static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off) /* stream encoder index */ config.stream_enc_idx = pipe_ctx->stream_res.stream_enc->id - ENGINE_ID_DIGA; - if (link_is_dp_128b_132b_signal(pipe_ctx)) + if (dp_is_128b_132b_signal(pipe_ctx)) config.stream_enc_idx = pipe_ctx->stream_res.hpo_dp_stream_enc->id - ENGINE_ID_HPO_DP_0; @@ -681,7 +682,7 @@ static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off) /* link encoder index */ config.link_enc_idx = link_enc->transmitter - TRANSMITTER_UNIPHY_A; - if (link_is_dp_128b_132b_signal(pipe_ctx)) + if (dp_is_128b_132b_signal(pipe_ctx)) config.link_enc_idx = pipe_ctx->link_res.hpo_dp_link_enc->inst; /* dio output index is dpia index for DPIA endpoint & dcio index by default */ @@ -702,7 +703,7 @@ static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off) config.assr_enabled = (panel_mode == DP_PANEL_MODE_EDP) ? 1 : 0; config.mst_enabled = (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) ? 1 : 0; - config.dp2_enabled = link_is_dp_128b_132b_signal(pipe_ctx) ? 1 : 0; + config.dp2_enabled = dp_is_128b_132b_signal(pipe_ctx) ? 1 : 0; config.usb4_enabled = (pipe_ctx->stream->link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) ? 1 : 0; config.dpms_off = dpms_off; @@ -816,7 +817,7 @@ void link_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable) /* Enable DSC in encoder */ if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) - && !link_is_dp_128b_132b_signal(pipe_ctx)) { + && !dp_is_128b_132b_signal(pipe_ctx)) { DC_LOG_DSC("Setting stream encoder DSC config for engine %d:", (int)pipe_ctx->stream_res.stream_enc->id); dsc_optc_config_log(dsc, &dsc_optc_cfg); pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(pipe_ctx->stream_res.stream_enc, @@ -842,7 +843,7 @@ void link_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable) /* disable DSC in stream encoder */ if (dc_is_dp_signal(stream->signal)) { - if (link_is_dp_128b_132b_signal(pipe_ctx)) + if (dp_is_128b_132b_signal(pipe_ctx)) pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet( pipe_ctx->stream_res.hpo_dp_stream_enc, false, @@ -901,7 +902,7 @@ bool link_set_dsc_pps_packet(struct pipe_ctx *pipe_ctx, bool enable, bool immedi memcpy(&stream->dsc_packed_pps[0], &dsc_packed_pps[0], sizeof(stream->dsc_packed_pps)); if (dc_is_dp_signal(stream->signal)) { DC_LOG_DSC("Setting stream encoder DSC PPS SDP for engine %d\n", (int)pipe_ctx->stream_res.stream_enc->id); - if (link_is_dp_128b_132b_signal(pipe_ctx)) + if (dp_is_128b_132b_signal(pipe_ctx)) pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet( pipe_ctx->stream_res.hpo_dp_stream_enc, true, @@ -918,7 +919,7 @@ bool link_set_dsc_pps_packet(struct pipe_ctx *pipe_ctx, bool enable, bool immedi /* disable DSC PPS in stream encoder */ memset(&stream->dsc_packed_pps[0], 0, sizeof(stream->dsc_packed_pps)); if (dc_is_dp_signal(stream->signal)) { - if (link_is_dp_128b_132b_signal(pipe_ctx)) + if (dp_is_128b_132b_signal(pipe_ctx)) pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet( pipe_ctx->stream_res.hpo_dp_stream_enc, false, @@ -1043,7 +1044,7 @@ static void log_vcp_x_y(const struct dc_link *link, struct fixed31_32 avg_time_s static struct fixed31_32 get_pbn_per_slot(struct dc_stream_state *stream) { struct fixed31_32 mbytes_per_sec; - uint32_t link_rate_in_mbytes_per_sec = dc_link_bandwidth_kbps(stream->link, + uint32_t link_rate_in_mbytes_per_sec = dp_link_bandwidth_kbps(stream->link, &stream->link->cur_link_settings); link_rate_in_mbytes_per_sec /= 8000; /* Kbits to MBytes */ @@ -1534,7 +1535,7 @@ struct fixed31_32 link_calculate_sst_avg_time_slots_per_mtp( { struct fixed31_32 link_bw_effective = dc_fixpt_from_int( - dc_link_bandwidth_kbps(link, &link->cur_link_settings)); + dp_link_bandwidth_kbps(link, &link->cur_link_settings)); struct fixed31_32 timeslot_bw_effective = dc_fixpt_div_int(link_bw_effective, MAX_MTP_SLOT_COUNT); struct fixed31_32 timing_bw = @@ -2122,7 +2123,7 @@ static enum dc_status enable_link_dp(struct dc_state *state, set_default_brightness_aux(link); // TODO: use cached if known if (link->dpcd_sink_ext_caps.bits.oled == 1) msleep(bl_oled_enable_delay); - link_backlight_enable_aux(link, true); + edp_backlight_enable_aux(link, true); } return status; @@ -2242,7 +2243,7 @@ void link_set_dpms_off(struct pipe_ctx *pipe_ctx) ASSERT(is_master_pipe_for_link(link, pipe_ctx)); - if (link_is_dp_128b_132b_signal(pipe_ctx)) + if (dp_is_128b_132b_signal(pipe_ctx)) vpg = pipe_ctx->stream_res.hpo_dp_stream_enc->vpg; DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger); @@ -2273,7 +2274,7 @@ void link_set_dpms_off(struct pipe_ctx *pipe_ctx) if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) deallocate_mst_payload(pipe_ctx); else if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT && - link_is_dp_128b_132b_signal(pipe_ctx)) + dp_is_128b_132b_signal(pipe_ctx)) update_sst_payload(pipe_ctx, false); if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) { @@ -2302,7 +2303,7 @@ void link_set_dpms_off(struct pipe_ctx *pipe_ctx) } if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT && - !link_is_dp_128b_132b_signal(pipe_ctx)) { + !dp_is_128b_132b_signal(pipe_ctx)) { /* In DP1.x SST mode, our encoder will go to TPS1 * when link is on but stream is off. @@ -2322,7 +2323,7 @@ void link_set_dpms_off(struct pipe_ctx *pipe_ctx) if (dc_is_dp_signal(pipe_ctx->stream->signal)) link_set_dsc_enable(pipe_ctx, false); } - if (link_is_dp_128b_132b_signal(pipe_ctx)) { + if (dp_is_128b_132b_signal(pipe_ctx)) { if (pipe_ctx->stream_res.tg->funcs->set_out_mux) pipe_ctx->stream_res.tg->funcs->set_out_mux(pipe_ctx->stream_res.tg, OUT_MUX_DIO); } @@ -2346,7 +2347,7 @@ void link_set_dpms_on( ASSERT(is_master_pipe_for_link(link, pipe_ctx)); - if (link_is_dp_128b_132b_signal(pipe_ctx)) + if (dp_is_128b_132b_signal(pipe_ctx)) vpg = pipe_ctx->stream_res.hpo_dp_stream_enc->vpg; DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger); @@ -2368,7 +2369,7 @@ void link_set_dpms_on( ASSERT(link_enc); if (!dc_is_virtual_signal(pipe_ctx->stream->signal) - && !link_is_dp_128b_132b_signal(pipe_ctx)) { + && !dp_is_128b_132b_signal(pipe_ctx)) { if (link_enc) link_enc->funcs->setup( link_enc, @@ -2378,7 +2379,7 @@ void link_set_dpms_on( pipe_ctx->stream->link->link_state_valid = true; if (pipe_ctx->stream_res.tg->funcs->set_out_mux) { - if (link_is_dp_128b_132b_signal(pipe_ctx)) + if (dp_is_128b_132b_signal(pipe_ctx)) otg_out_dest = OUT_MUX_HPO_DP; else otg_out_dest = OUT_MUX_DIO; @@ -2401,7 +2402,7 @@ void link_set_dpms_on( dc->hwss.update_info_frame(pipe_ctx); if (dc_is_dp_signal(pipe_ctx->stream->signal)) - link_dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_UPDATE_INFO_FRAME); + dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_UPDATE_INFO_FRAME); /* Do not touch link on seamless boot optimization. */ if (pipe_ctx->stream->apply_seamless_boot_optimization) { @@ -2476,7 +2477,7 @@ void link_set_dpms_on( * from transmitter control. */ if (!(dc_is_virtual_signal(pipe_ctx->stream->signal) || - link_is_dp_128b_132b_signal(pipe_ctx))) + dp_is_128b_132b_signal(pipe_ctx))) if (link_enc) link_enc->funcs->setup( link_enc, @@ -2496,7 +2497,7 @@ void link_set_dpms_on( if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) allocate_mst_payload(pipe_ctx); else if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT && - link_is_dp_128b_132b_signal(pipe_ctx)) + dp_is_128b_132b_signal(pipe_ctx)) update_sst_payload(pipe_ctx, true); dc->hwss.unblank_stream(pipe_ctx, @@ -2512,7 +2513,7 @@ void link_set_dpms_on( dc->hwss.enable_audio_stream(pipe_ctx); } else { // if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) - if (link_is_dp_128b_132b_signal(pipe_ctx)) + if (dp_is_128b_132b_signal(pipe_ctx)) dp_fpga_hpo_enable_link_and_stream(state, pipe_ctx); if (dc_is_dp_signal(pipe_ctx->stream->signal) || dc_is_virtual_signal(pipe_ctx->stream->signal)) diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dpms.h b/drivers/gpu/drm/amd/display/dc/link/link_dpms.h index 33d312dabdb8..9398f9c1666a 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_dpms.h +++ b/drivers/gpu/drm/amd/display/dc/link/link_dpms.h @@ -27,14 +27,27 @@ #define __DC_LINK_DPMS_H__ #include "link.h" -bool link_set_dsc_pps_packet(struct pipe_ctx *pipe_ctx, - bool enable, bool immediate_update); -struct fixed31_32 link_calculate_sst_avg_time_slots_per_mtp( - const struct dc_stream_state *stream, - const struct dc_link *link); +void link_set_dpms_on( + struct dc_state *state, + struct pipe_ctx *pipe_ctx); +void link_set_dpms_off(struct pipe_ctx *pipe_ctx); +void link_resume(struct dc_link *link); +void link_blank_all_dp_displays(struct dc *dc); +void link_blank_all_edp_displays(struct dc *dc); +void link_blank_dp_stream(struct dc_link *link, bool hw_init); void link_set_all_streams_dpms_off_for_link(struct dc_link *link); void link_get_master_pipes_with_dpms_on(const struct dc_link *link, struct dc_state *state, uint8_t *count, struct pipe_ctx *pipes[MAX_PIPES]); +enum dc_status link_increase_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t req_pbn); +enum dc_status link_reduce_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t req_pbn); +bool link_set_dsc_pps_packet(struct pipe_ctx *pipe_ctx, + bool enable, bool immediate_update); +struct fixed31_32 link_calculate_sst_avg_time_slots_per_mtp( + const struct dc_stream_state *stream, + const struct dc_link *link); +void link_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable); +bool link_set_dsc_enable(struct pipe_ctx *pipe_ctx, bool enable); +bool link_update_dsc_config(struct pipe_ctx *pipe_ctx); #endif /* __DC_LINK_DPMS_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/link/link_factory.c b/drivers/gpu/drm/amd/display/dc/link/link_factory.c index d9ce83f0bbef..995032a341b3 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_factory.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_factory.c @@ -28,6 +28,9 @@ */ #include "link_factory.h" #include "link_detection.h" +#include "link_resource.h" +#include "link_validation.h" +#include "link_dpms.h" #include "accessories/link_dp_cts.h" #include "accessories/link_dp_trace.h" #include "accessories/link_fpga.h" @@ -49,69 +52,248 @@ DC_LOG_HW_HOTPLUG( \ __VA_ARGS__) -static struct link_service link_srv = { - /* Detection */ - .add_remote_sink = link_add_remote_sink, - .remove_remote_sink = link_remove_remote_sink, - .get_hpd_state = link_get_hpd_state, - .enable_hpd = link_enable_hpd, - .disable_hpd = link_disable_hpd, - .enable_hpd_filter = link_enable_hpd_filter, - - /* DDC */ - .aux_transfer_raw = link_aux_transfer_raw, - - /* DP Capability */ - .dp_is_sink_present = dp_is_sink_present, - .dp_is_fec_supported = dp_is_fec_supported, - .dp_get_max_link_enc_cap = dp_get_max_link_enc_cap, - .dp_get_verified_link_cap = dp_get_verified_link_cap, - .dp_should_enable_fec = dp_should_enable_fec, - .mst_decide_link_encoding_format = mst_decide_link_encoding_format, - .edp_decide_link_settings = edp_decide_link_settings, - .bw_kbps_from_raw_frl_link_rate_data = link_bw_kbps_from_raw_frl_link_rate_data, - .dp_overwrite_extended_receiver_cap = dp_overwrite_extended_receiver_cap, - .dp_decide_lttpr_mode = dp_decide_lttpr_mode, - - /* DP DPIA/PHY */ - .dpia_handle_usb4_bandwidth_allocation_for_link = dpia_handle_usb4_bandwidth_allocation_for_link, - .dpia_handle_bw_alloc_response = dpia_handle_bw_alloc_response, - /* DP IRQ Handler */ - .dp_parse_link_loss_status = dp_parse_link_loss_status, - .dp_should_allow_hpd_rx_irq = dp_should_allow_hpd_rx_irq, - .dp_handle_link_loss = dp_handle_link_loss, - .dp_read_hpd_rx_irq_data = dp_read_hpd_rx_irq_data, - .dp_handle_hpd_rx_irq = dp_handle_hpd_rx_irq, - .dpcd_write_rx_power_ctrl = dpcd_write_rx_power_ctrl, - - /* eDP Panel Control */ - .edp_panel_backlight_power_on = edp_panel_backlight_power_on, - .edp_get_backlight_level = edp_get_backlight_level, - .edp_get_backlight_level_nits = edp_get_backlight_level_nits, - .edp_set_backlight_level = edp_set_backlight_level, - .edp_set_backlight_level_nits = edp_set_backlight_level_nits, - .edp_get_target_backlight_pwm = edp_get_target_backlight_pwm, - .edp_get_psr_state = edp_get_psr_state, - .edp_set_psr_allow_active = edp_set_psr_allow_active, - .edp_setup_psr = edp_setup_psr, - .edp_wait_for_t12 = edp_wait_for_t12, - - /* DP CTS */ - .dp_handle_automated_test = dp_handle_automated_test, - .dp_set_test_pattern = dp_set_test_pattern, - .dp_set_preferred_link_settings = dp_set_preferred_link_settings, - .dp_set_preferred_training_settings = dp_set_preferred_training_settings, - - /* DP Trace */ - .dp_trace_is_initialized = dp_trace_is_initialized, - .dp_trace_set_is_logged_flag = dp_trace_set_is_logged_flag, - .dp_trace_is_logged = dp_trace_is_logged, - .dp_trace_get_lt_end_timestamp = dp_trace_get_lt_end_timestamp, - .dp_trace_get_lt_counts = dp_trace_get_lt_counts, - .dp_trace_get_link_loss_count = dp_trace_get_link_loss_count, -}; - -static enum transmitter translate_encoder_to_transmitter(struct graphics_object_id encoder) +/* link factory owns the creation/destruction of link structures. */ +static void construct_link_service_factory(struct link_service *link_srv) +{ + + link_srv->create_link = link_create; + link_srv->destroy_link = link_destroy; +} + +/* link_detection manages link detection states and receiver states by using + * various link protocols. It also provides helper functions to interpret + * certain capabilities or status based on the states it manages or retrieve + * them directly from connected receivers. + */ +static void construct_link_service_detection(struct link_service *link_srv) +{ + link_srv->detect_link = link_detect; + link_srv->detect_connection_type = link_detect_connection_type; + link_srv->add_remote_sink = link_add_remote_sink; + link_srv->remove_remote_sink = link_remove_remote_sink; + link_srv->get_hpd_state = link_get_hpd_state; + link_srv->get_hpd_gpio = link_get_hpd_gpio; + link_srv->enable_hpd = link_enable_hpd; + link_srv->disable_hpd = link_disable_hpd; + link_srv->enable_hpd_filter = link_enable_hpd_filter; + link_srv->reset_cur_dp_mst_topology = link_reset_cur_dp_mst_topology; + link_srv->get_status = link_get_status; + link_srv->is_hdcp1x_supported = link_is_hdcp14; + link_srv->is_hdcp2x_supported = link_is_hdcp22; + link_srv->clear_dprx_states = link_clear_dprx_states; +} + +/* link resource implements accessors to link resource. */ +static void construct_link_service_resource(struct link_service *link_srv) +{ + link_srv->get_cur_res_map = link_get_cur_res_map; + link_srv->restore_res_map = link_restore_res_map; + link_srv->get_cur_link_res = link_get_cur_link_res; +} + +/* link validation owns timing validation against various link limitations. (ex. + * link bandwidth, receiver capability or our hardware capability) It also + * provides helper functions exposing bandwidth formulas used in validation. + */ +static void construct_link_service_validation(struct link_service *link_srv) +{ + link_srv->validate_mode_timing = link_validate_mode_timing; + link_srv->dp_link_bandwidth_kbps = dp_link_bandwidth_kbps; +} + +/* link dpms owns the programming sequence of stream's dpms state associated + * with the link and link's enable/disable sequences as result of the stream's + * dpms state change. + */ +static void construct_link_service_dpms(struct link_service *link_srv) +{ + link_srv->set_dpms_on = link_set_dpms_on; + link_srv->set_dpms_off = link_set_dpms_off; + link_srv->resume = link_resume; + link_srv->blank_all_dp_displays = link_blank_all_dp_displays; + link_srv->blank_all_edp_displays = link_blank_all_edp_displays; + link_srv->blank_dp_stream = link_blank_dp_stream; + link_srv->increase_mst_payload = link_increase_mst_payload; + link_srv->reduce_mst_payload = link_reduce_mst_payload; + link_srv->set_dsc_on_stream = link_set_dsc_on_stream; + link_srv->set_dsc_enable = link_set_dsc_enable; + link_srv->update_dsc_config = link_update_dsc_config; +} + +/* link ddc implements generic display communication protocols such as i2c, aux + * and scdc. It should not contain any specific applications of these + * protocols such as display capability query, detection, or handshaking such as + * link training. + */ +static void construct_link_service_ddc(struct link_service *link_srv) +{ + link_srv->create_ddc_service = link_create_ddc_service; + link_srv->destroy_ddc_service = link_destroy_ddc_service; + link_srv->query_ddc_data = link_query_ddc_data; + link_srv->aux_transfer_raw = link_aux_transfer_raw; + link_srv->aux_transfer_with_retries_no_mutex = + link_aux_transfer_with_retries_no_mutex; + link_srv->is_in_aux_transaction_mode = link_is_in_aux_transaction_mode; + link_srv->get_aux_defer_delay = link_get_aux_defer_delay; +} + +/* link dp capability implements dp specific link capability retrieval sequence. + * It is responsible for retrieving, parsing, overriding, deciding capability + * obtained from dp link. Link capability consists of encoders, DPRXs, cables, + * retimers, usb and all other possible backend capabilities. + */ +static void construct_link_service_dp_capability(struct link_service *link_srv) +{ + link_srv->dp_is_sink_present = dp_is_sink_present; + link_srv->dp_is_fec_supported = dp_is_fec_supported; + link_srv->dp_is_128b_132b_signal = dp_is_128b_132b_signal; + link_srv->dp_get_max_link_enc_cap = dp_get_max_link_enc_cap; + link_srv->dp_get_verified_link_cap = dp_get_verified_link_cap; + link_srv->dp_get_encoding_format = link_dp_get_encoding_format; + link_srv->dp_should_enable_fec = dp_should_enable_fec; + link_srv->dp_decide_link_settings = link_decide_link_settings; + link_srv->mst_decide_link_encoding_format = + mst_decide_link_encoding_format; + link_srv->edp_decide_link_settings = edp_decide_link_settings; + link_srv->bw_kbps_from_raw_frl_link_rate_data = + link_bw_kbps_from_raw_frl_link_rate_data; + link_srv->dp_overwrite_extended_receiver_cap = + dp_overwrite_extended_receiver_cap; + link_srv->dp_decide_lttpr_mode = dp_decide_lttpr_mode; +} + +/* link dp phy/dpia implements basic dp phy/dpia functionality such as + * enable/disable output and set lane/drive settings. It is responsible for + * maintaining and update software state representing current phy/dpia status + * such as current link settings. + */ +static void construct_link_service_dp_phy_or_dpia(struct link_service *link_srv) +{ + link_srv->dpia_handle_usb4_bandwidth_allocation_for_link = + dpia_handle_usb4_bandwidth_allocation_for_link; + link_srv->dpia_handle_bw_alloc_response = dpia_handle_bw_alloc_response; + link_srv->dp_set_drive_settings = dp_set_drive_settings; + link_srv->dpcd_write_rx_power_ctrl = dpcd_write_rx_power_ctrl; +} + +/* link dp irq handler implements DP HPD short pulse handling sequence according + * to DP specifications + */ +static void construct_link_service_dp_irq_handler(struct link_service *link_srv) +{ + link_srv->dp_parse_link_loss_status = dp_parse_link_loss_status; + link_srv->dp_should_allow_hpd_rx_irq = dp_should_allow_hpd_rx_irq; + link_srv->dp_handle_link_loss = dp_handle_link_loss; + link_srv->dp_read_hpd_rx_irq_data = dp_read_hpd_rx_irq_data; + link_srv->dp_handle_hpd_rx_irq = dp_handle_hpd_rx_irq; +} + +/* link edp panel control implements retrieval and configuration of eDP panel + * features such as PSR and ABM and it also manages specs defined eDP panel + * power sequences. + */ +static void construct_link_service_edp_panel_control(struct link_service *link_srv) +{ + link_srv->edp_panel_backlight_power_on = edp_panel_backlight_power_on; + link_srv->edp_get_backlight_level = edp_get_backlight_level; + link_srv->edp_get_backlight_level_nits = edp_get_backlight_level_nits; + link_srv->edp_set_backlight_level = edp_set_backlight_level; + link_srv->edp_set_backlight_level_nits = edp_set_backlight_level_nits; + link_srv->edp_get_target_backlight_pwm = edp_get_target_backlight_pwm; + link_srv->edp_get_psr_state = edp_get_psr_state; + link_srv->edp_set_psr_allow_active = edp_set_psr_allow_active; + link_srv->edp_setup_psr = edp_setup_psr; + link_srv->edp_set_sink_vtotal_in_psr_active = + edp_set_sink_vtotal_in_psr_active; + link_srv->edp_get_psr_residency = edp_get_psr_residency; + link_srv->edp_wait_for_t12 = edp_wait_for_t12; + link_srv->edp_is_ilr_optimization_required = + edp_is_ilr_optimization_required; + link_srv->edp_backlight_enable_aux = edp_backlight_enable_aux; + link_srv->edp_add_delay_for_T9 = edp_add_delay_for_T9; + link_srv->edp_receiver_ready_T9 = edp_receiver_ready_T9; + link_srv->edp_receiver_ready_T7 = edp_receiver_ready_T7; + link_srv->edp_power_alpm_dpcd_enable = edp_power_alpm_dpcd_enable; +} + +/* link dp cts implements dp compliance test automation protocols and manual + * testing interfaces for debugging and certification purpose. + */ +static void construct_link_service_dp_cts(struct link_service *link_srv) +{ + link_srv->dp_handle_automated_test = dp_handle_automated_test; + link_srv->dp_set_test_pattern = dp_set_test_pattern; + link_srv->dp_set_preferred_link_settings = + dp_set_preferred_link_settings; + link_srv->dp_set_preferred_training_settings = + dp_set_preferred_training_settings; +} + +/* link dp trace implements tracing interfaces for tracking major dp sequences + * including execution status and timestamps + */ +static void construct_link_service_dp_trace(struct link_service *link_srv) +{ + link_srv->dp_trace_is_initialized = dp_trace_is_initialized; + link_srv->dp_trace_set_is_logged_flag = dp_trace_set_is_logged_flag; + link_srv->dp_trace_is_logged = dp_trace_is_logged; + link_srv->dp_trace_get_lt_end_timestamp = dp_trace_get_lt_end_timestamp; + link_srv->dp_trace_get_lt_counts = dp_trace_get_lt_counts; + link_srv->dp_trace_get_link_loss_count = dp_trace_get_link_loss_count; + link_srv->dp_trace_set_edp_power_timestamp = + dp_trace_set_edp_power_timestamp; + link_srv->dp_trace_get_edp_poweron_timestamp = + dp_trace_get_edp_poweron_timestamp; + link_srv->dp_trace_get_edp_poweroff_timestamp = + dp_trace_get_edp_poweroff_timestamp; + link_srv->dp_trace_source_sequence = dp_trace_source_sequence; +} + +static void construct_link_service(struct link_service *link_srv) +{ + /* All link service functions should fall under some sub categories. + * If a new function doesn't perfectly fall under an existing sub + * category, it must be that you are either adding a whole new aspect of + * responsibility to link service or something doesn't belong to link + * service. In that case please contact the arch owner to arrange a + * design review meeting. + */ + construct_link_service_factory(link_srv); + construct_link_service_detection(link_srv); + construct_link_service_resource(link_srv); + construct_link_service_validation(link_srv); + construct_link_service_dpms(link_srv); + construct_link_service_ddc(link_srv); + construct_link_service_dp_capability(link_srv); + construct_link_service_dp_phy_or_dpia(link_srv); + construct_link_service_dp_irq_handler(link_srv); + construct_link_service_edp_panel_control(link_srv); + construct_link_service_dp_cts(link_srv); + construct_link_service_dp_trace(link_srv); +} + +struct link_service *link_create_link_service(void) +{ + struct link_service *link_srv = kzalloc(sizeof(*link_srv), GFP_KERNEL); + + if (link_srv == NULL) + goto fail; + + construct_link_service(link_srv); + + return link_srv; +fail: + return NULL; +} + +void link_destroy_link_service(struct link_service **link_srv) +{ + kfree(*link_srv); + *link_srv = NULL; +} + +static enum transmitter translate_encoder_to_transmitter( + struct graphics_object_id encoder) { switch (encoder.id) { case ENCODER_ID_INTERNAL_UNIPHY: @@ -646,8 +828,3 @@ void link_destroy(struct dc_link **link) kfree(*link); *link = NULL; } - -const struct link_service *link_get_link_service(void) -{ - return &link_srv; -} diff --git a/drivers/gpu/drm/amd/display/dc/link/link_factory.h b/drivers/gpu/drm/amd/display/dc/link/link_factory.h index 5b846147c4a6..e96220d48d03 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_factory.h +++ b/drivers/gpu/drm/amd/display/dc/link/link_factory.h @@ -25,5 +25,7 @@ #ifndef __LINK_FACTORY_H__ #define __LINK_FACTORY_H__ #include "link.h" +struct dc_link *link_create(const struct link_init_data *init_params); +void link_destroy(struct dc_link **link); #endif /* __LINK_FACTORY_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/link/link_resource.h b/drivers/gpu/drm/amd/display/dc/link/link_resource.h index 68dfbfc973cc..1907bda3cb6e 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_resource.h +++ b/drivers/gpu/drm/amd/display/dc/link/link_resource.h @@ -25,4 +25,8 @@ #ifndef __LINK_RESOURCE_H__ #define __LINK_RESOURCE_H__ #include "link.h" +void link_get_cur_res_map(const struct dc *dc, uint32_t *map); +void link_restore_res_map(const struct dc *dc, uint32_t *map); +void link_get_cur_link_res(const struct dc_link *link, + struct link_resource *link_res); #endif /* __LINK_RESOURCE_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/link/link_validation.c b/drivers/gpu/drm/amd/display/dc/link/link_validation.c index 62aa5f6b1f0c..9a5010f86003 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_validation.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_validation.c @@ -255,8 +255,7 @@ uint32_t dp_link_bandwidth_kbps( return link_rate_per_lane_kbps * link_settings->lane_count / 10000 * total_data_bw_efficiency_x10000; } -uint32_t link_timing_bandwidth_kbps( - const struct dc_crtc_timing *timing) +uint32_t link_timing_bandwidth_kbps(const struct dc_crtc_timing *timing) { uint32_t bits_per_channel = 0; uint32_t kbps; @@ -337,7 +336,7 @@ static bool dp_validate_mode_timing( */ req_bw = dc_bandwidth_in_kbps_from_timing(timing); - max_bw = dc_link_bandwidth_kbps(link, link_setting); + max_bw = dp_link_bandwidth_kbps(link, link_setting); if (req_bw <= max_bw) { /* remember the biggest mode here, during diff --git a/drivers/gpu/drm/amd/display/dc/link/link_validation.h b/drivers/gpu/drm/amd/display/dc/link/link_validation.h index ab6a44f50032..2191d3a4950c 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_validation.h +++ b/drivers/gpu/drm/amd/display/dc/link/link_validation.h @@ -25,4 +25,11 @@ #ifndef __LINK_VALIDATION_H__ #define __LINK_VALIDATION_H__ #include "link.h" +enum dc_status link_validate_mode_timing( + const struct dc_stream_state *stream, + struct dc_link *link, + const struct dc_crtc_timing *timing); +uint32_t dp_link_bandwidth_kbps( + const struct dc_link *link, + const struct dc_link_settings *link_settings); #endif /* __LINK_VALIDATION_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.h index f002fa01508e..860ef15d7f1b 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.h +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.h @@ -37,13 +37,41 @@ #define EDID_SEGMENT_SIZE 256 +struct ddc_service *link_create_ddc_service( + struct ddc_service_init_data *ddc_init_data); + +void link_destroy_ddc_service(struct ddc_service **ddc); + void set_ddc_transaction_type( struct ddc_service *ddc, enum ddc_transaction_type type); +uint32_t link_get_aux_defer_delay(struct ddc_service *ddc); + +bool link_is_in_aux_transaction_mode(struct ddc_service *ddc); + bool try_to_configure_aux_timeout(struct ddc_service *ddc, uint32_t timeout); +bool link_query_ddc_data( + struct ddc_service *ddc, + uint32_t address, + uint8_t *write_buf, + uint32_t write_size, + uint8_t *read_buf, + uint32_t read_size); + +/* Attempt to submit an aux payload, retrying on timeouts, defers, and busy + * states as outlined in the DP spec. Returns true if the request was + * successful. + * + * NOTE: The function requires explicit mutex on DM side in order to prevent + * potential race condition. DC components should call the dpcd read/write + * function in dm_helpers in order to access dpcd safely + */ +bool link_aux_transfer_with_retries_no_mutex(struct ddc_service *ddc, + struct aux_payload *payload); + void write_scdc_data( struct ddc_service *ddc_service, uint32_t pix_clk, diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c index 75e1a687608a..e9bcb35ae185 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c @@ -347,7 +347,7 @@ bool dp_should_enable_fec(const struct dc_link *link) return !force_disable && dp_is_fec_supported(link); } -bool link_is_dp_128b_132b_signal(struct pipe_ctx *pipe_ctx) +bool dp_is_128b_132b_signal(struct pipe_ctx *pipe_ctx) { /* If this assert is hit then we have a link encoder dynamic management issue */ ASSERT(pipe_ctx->stream_res.hpo_dp_stream_enc ? pipe_ctx->link_res.hpo_dp_link_enc != NULL : true); @@ -656,7 +656,7 @@ static bool decide_dp_link_settings(struct dc_link *link, struct dc_link_setting */ while (current_link_setting.link_rate <= link->verified_link_cap.link_rate) { - link_bw = dc_link_bandwidth_kbps( + link_bw = dp_link_bandwidth_kbps( link, ¤t_link_setting); if (req_bw <= link_bw) { @@ -712,7 +712,7 @@ bool edp_decide_link_settings(struct dc_link *link, */ while (current_link_setting.link_rate <= link->verified_link_cap.link_rate) { - link_bw = dc_link_bandwidth_kbps( + link_bw = dp_link_bandwidth_kbps( link, ¤t_link_setting); if (req_bw <= link_bw) { @@ -891,7 +891,7 @@ bool link_decide_link_settings(struct dc_stream_state *stream, struct dc_link_settings *link_setting) { struct dc_link *link = stream->link; - uint32_t req_bw = link_timing_bandwidth_kbps(&stream->timing); + uint32_t req_bw = dc_bandwidth_in_kbps_from_timing(&stream->timing); memset(link_setting, 0, sizeof(*link_setting)); @@ -924,7 +924,7 @@ bool link_decide_link_settings(struct dc_stream_state *stream, tmp_link_setting.link_rate = LINK_RATE_UNKNOWN; tmp_timing.flags.DSC = 0; - orig_req_bw = link_timing_bandwidth_kbps(&tmp_timing); + orig_req_bw = dc_bandwidth_in_kbps_from_timing(&tmp_timing); edp_decide_link_settings(link, &tmp_link_setting, orig_req_bw); max_link_rate = tmp_link_setting.link_rate; } diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.h index 62980ae17d41..8f0ce97f2362 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.h +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.h @@ -40,6 +40,9 @@ bool dp_get_max_link_enc_cap(const struct dc_link *link, const struct dc_link_settings *dp_get_verified_link_cap( const struct dc_link *link); +enum dp_link_encoding link_dp_get_encoding_format( + const struct dc_link_settings *link_settings); + enum dc_status dp_retrieve_lttpr_cap(struct dc_link *link); /* Convert PHY repeater count read from DPCD uint8_t. */ @@ -59,12 +62,18 @@ void dpcd_write_cable_id_to_dprx(struct dc_link *link); bool dp_should_enable_fec(const struct dc_link *link); +bool dp_is_128b_132b_signal(struct pipe_ctx *pipe_ctx); + /* Initialize output parameter lt_settings. */ void dp_decide_training_settings( struct dc_link *link, const struct dc_link_settings *link_setting, struct link_training_settings *lt_settings); +bool link_decide_link_settings( + struct dc_stream_state *stream, + struct dc_link_settings *link_setting); + bool edp_decide_link_settings(struct dc_link *link, struct dc_link_settings *link_setting, uint32_t req_bw); diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.h index 207bff2ec32e..1eb0619d6710 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.h +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_phy.h @@ -44,6 +44,11 @@ void dp_set_hw_lane_settings( const struct link_training_settings *link_settings, uint32_t offset); +void dp_set_drive_settings( + struct dc_link *link, + const struct link_resource *link_res, + struct link_training_settings *lt_settings); + enum dc_status dp_set_fec_ready(struct dc_link *link, const struct link_resource *link_res, bool ready); diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c index eee1853f6b32..a9025671ee4a 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c @@ -42,6 +42,7 @@ #include "link_dp_capability.h" #include "link_edp_panel_control.h" #include "link/link_detection.h" +#include "link/link_validation.h" #include "atomfirmware.h" #include "link_enc_cfg.h" #include "resource.h" @@ -861,8 +862,9 @@ static enum dc_status configure_lttpr_mode_non_transparent( uint8_t repeater_id; enum dc_status result = DC_ERROR_UNEXPECTED; uint8_t repeater_mode = DP_PHY_REPEATER_MODE_TRANSPARENT; + const struct dc *dc = link->dc; - enum dp_link_encoding encoding = link_dp_get_encoding_format(<_settings->link_settings); + enum dp_link_encoding encoding = dc->link_srv->dp_get_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__); @@ -1675,7 +1677,7 @@ bool perform_link_training_with_retries( /* Flag if reduced link bandwidth no longer meets stream requirements or fallen back to * minimum link bandwidth. */ - req_bw = link_timing_bandwidth_kbps(&stream->timing); + req_bw = dc_bandwidth_in_kbps_from_timing(&stream->timing); link_bw = dp_link_bandwidth_kbps(link, &cur_link_settings); is_link_bw_low = (req_bw > link_bw); is_link_bw_min = ((cur_link_settings.link_rate <= LINK_RATE_LOW) && diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c index 4d78ac932845..93a6bbe954bb 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c @@ -201,7 +201,7 @@ bool edp_get_backlight_level_nits(struct dc_link *link, return true; } -bool link_backlight_enable_aux(struct dc_link *link, bool enable) +bool edp_backlight_enable_aux(struct dc_link *link, bool enable) { uint8_t backlight_enable = enable ? 1 : 0; @@ -249,7 +249,7 @@ bool set_default_brightness_aux(struct dc_link *link) return false; } -bool link_is_edp_ilr_optimization_required(struct dc_link *link, +bool edp_is_ilr_optimization_required(struct dc_link *link, struct dc_crtc_timing *crtc_timing) { struct dc_link_settings link_setting; @@ -282,7 +282,7 @@ bool link_is_edp_ilr_optimization_required(struct dc_link *link, core_link_read_dpcd(link, DP_LANE_COUNT_SET, &lane_count_set.raw, sizeof(lane_count_set)); - req_bw = link_timing_bandwidth_kbps(crtc_timing); + req_bw = dc_bandwidth_in_kbps_from_timing(crtc_timing); if (!crtc_timing->flags.DSC) edp_decide_link_settings(link, &link_setting, req_bw); @@ -322,13 +322,13 @@ bool edp_wait_for_t12(struct dc_link *link) return false; } -void link_edp_add_delay_for_T9(struct dc_link *link) +void edp_add_delay_for_T9(struct dc_link *link) { if (link && link->panel_config.pps.extra_delay_backlight_off > 0) fsleep(link->panel_config.pps.extra_delay_backlight_off * 1000); } -bool link_edp_receiver_ready_T9(struct dc_link *link) +bool edp_receiver_ready_T9(struct dc_link *link) { unsigned int tries = 0; unsigned char sinkstatus = 0; @@ -353,7 +353,7 @@ bool link_edp_receiver_ready_T9(struct dc_link *link) return result; } -bool link_edp_receiver_ready_T7(struct dc_link *link) +bool edp_receiver_ready_T7(struct dc_link *link) { unsigned char sinkstatus = 0; unsigned char edpRev = 0; @@ -388,7 +388,7 @@ bool link_edp_receiver_ready_T7(struct dc_link *link) return result; } -bool link_power_alpm_dpcd_enable(struct dc_link *link, bool enable) +bool edp_power_alpm_dpcd_enable(struct dc_link *link, bool enable) { bool ret = false; union dpcd_alpm_configuration alpm_config; @@ -623,7 +623,7 @@ bool edp_setup_psr(struct dc_link *link, sizeof(psr_configuration.raw)); if (link->psr_settings.psr_version == DC_PSR_VERSION_SU_1) { - link_power_alpm_dpcd_enable(link, true); + edp_power_alpm_dpcd_enable(link, true); psr_context->su_granularity_required = psr_config->su_granularity_required; psr_context->su_y_granularity = @@ -752,7 +752,7 @@ bool edp_setup_psr(struct dc_link *link, } -void link_get_psr_residency(const struct dc_link *link, uint32_t *residency) +void edp_get_psr_residency(const struct dc_link *link, uint32_t *residency) { struct dc *dc = link->ctx->dc; struct dmub_psr *psr = dc->res_pool->psr; @@ -767,7 +767,7 @@ void link_get_psr_residency(const struct dc_link *link, uint32_t *residency) else *residency = 0; } -bool link_set_sink_vtotal_in_psr_active(const struct dc_link *link, uint16_t psr_vtotal_idle, uint16_t psr_vtotal_su) +bool edp_set_sink_vtotal_in_psr_active(const struct dc_link *link, uint16_t psr_vtotal_idle, uint16_t psr_vtotal_su) { struct dc *dc = link->ctx->dc; struct dmub_psr *psr = dc->res_pool->psr; diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h index 4439598f9f7d..28f552080558 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h @@ -49,5 +49,15 @@ bool edp_set_psr_allow_active(struct dc_link *link, const bool *allow_active, bool edp_setup_psr(struct dc_link *link, const struct dc_stream_state *stream, struct psr_config *psr_config, struct psr_context *psr_context); +bool edp_set_sink_vtotal_in_psr_active(const struct dc_link *link, + uint16_t psr_vtotal_idle, uint16_t psr_vtotal_su); +void edp_get_psr_residency(const struct dc_link *link, uint32_t *residency); bool edp_wait_for_t12(struct dc_link *link); +bool edp_is_ilr_optimization_required(struct dc_link *link, + struct dc_crtc_timing *crtc_timing); +bool edp_backlight_enable_aux(struct dc_link *link, bool enable); +void edp_add_delay_for_T9(struct dc_link *link); +bool edp_receiver_ready_T9(struct dc_link *link); +bool edp_receiver_ready_T7(struct dc_link *link); +bool edp_power_alpm_dpcd_enable(struct dc_link *link, bool enable); #endif /* __DC_LINK_EDP_POWER_CONTROL_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_hpd.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_hpd.h index bd471b63476e..4fb526b264f9 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_hpd.h +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_hpd.h @@ -45,6 +45,9 @@ bool program_hpd_filter(const struct dc_link *link); bool dpia_query_hpd_status(struct dc_link *link); bool query_hpd_status(struct dc_link *link, uint32_t *is_hpd_high); bool link_get_hpd_state(struct dc_link *link); +struct gpio *link_get_hpd_gpio(struct dc_bios *dcb, + struct graphics_object_id link_id, + struct gpio_service *gpio_service); void link_enable_hpd(const struct dc_link *link); void link_disable_hpd(const struct dc_link *link); void link_enable_hpd_filter(struct dc_link *link, bool enable); -- cgit v1.2.3 From c416a9e4e31eaec5a35417b056a22c73652db544 Mon Sep 17 00:00:00 2001 From: Stylon Wang Date: Wed, 1 Mar 2023 23:56:51 +0800 Subject: drm/amd/display: Clearly states if long or short HPD event in dmesg logs [Why] The log "DMUB HPD callback" is crucial to identify when DP tunneling is been established and driver is notified of this event from DMUB. Same log is shared for long and short hotplug event and we need to check trailing DC debug log to distinguish between them two, making debugging on DPIA related issues a bit more troublesome. [How] Clearly states in dmesg logs whether this is a long or short hotplug event. Reviewed-by: Hamza Mahfooz Acked-by: Qingqing Zhuo Signed-off-by: Stylon Wang Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index e0b7ef6d1a62..eeaeca8b51f4 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -713,7 +713,14 @@ static void dmub_hpd_callback(struct amdgpu_device *adev, drm_for_each_connector_iter(connector, &iter) { aconnector = to_amdgpu_dm_connector(connector); if (link && aconnector->dc_link == link) { - DRM_INFO("DMUB HPD callback: link_index=%u\n", link_index); + if (notify->type == DMUB_NOTIFICATION_HPD) + DRM_INFO("DMUB HPD callback: link_index=%u\n", link_index); + else if (notify->type == DMUB_NOTIFICATION_HPD_IRQ) + DRM_INFO("DMUB HPD IRQ callback: link_index=%u\n", link_index); + else + DRM_WARN("DMUB Unknown HPD callback type %d, link_index=%u\n", + notify->type, link_index); + hpd_aconnector = aconnector; break; } -- cgit v1.2.3 From 4db231d7dd80163fd251635f81280f1c93a393ab Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 12 Mar 2023 20:17:46 +0100 Subject: drm/amd/display/amdgpu_dm: Fix backlight_device_register() error handling backlight_device_register() returns an ERR_PTR on error, but other code such as amdgpu_dm_connector_destroy() assumes dm->backlight_dev[i] is NULL if no backlight is registered. Clear dm->backlight_dev[i] on registration failure, to avoid other code trying to deref an ERR_PTR pointer. Reviewed-by: Rodrigo Siqueira Signed-off-by: Hans de Goede Signed-off-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index eeaeca8b51f4..1c69353defb5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4218,9 +4218,10 @@ amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm) &amdgpu_dm_backlight_ops, &props); - if (IS_ERR(dm->backlight_dev[dm->num_of_edps])) + if (IS_ERR(dm->backlight_dev[dm->num_of_edps])) { DRM_ERROR("DM: Backlight registration failed!\n"); - else + dm->backlight_dev[dm->num_of_edps] = NULL; + } else DRM_DEBUG_DRIVER("DM: Registered Backlight device: %s\n", bl_name); } -- cgit v1.2.3 From ceb4a5619c734ea679bf5a2446e6869056e353d4 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 12 Mar 2023 20:17:47 +0100 Subject: drm/amd/display/amdgpu_dm: Refactor register_backlight_device() Refactor register_backlight_device(): 1) Turn the connector-type + signal check into an early exit condition to avoid the indentation level of the rest of the code 2) Add an array bounds check for the arrays indexed by dm->num_of_edps 3) register_backlight_device() always increases dm->num_of_edps if amdgpu_dm_register_backlight_device() has assigned a backlight_dev to the current dm->backlight_link[dm->num_of_edps] slot. So on its next call dm->backlight_dev[dm->num_of_edps] always point to the next empty slot and the "if (!dm->backlight_dev[dm->num_of_edps])" check will thus always succeed and can be removed. 4) Add a bl_idx local variable to use as array index, rather then using dm->num_of_edps to improve the code readability. Reviewed-by: Rodrigo Siqueira Signed-off-by: Hans de Goede Signed-off-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 28 ++++++++++++----------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 1c69353defb5..cbf36131cdd0 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4269,21 +4269,23 @@ static int initialize_plane(struct amdgpu_display_manager *dm, static void register_backlight_device(struct amdgpu_display_manager *dm, struct dc_link *link) { - if ((link->connector_signal & (SIGNAL_TYPE_EDP | SIGNAL_TYPE_LVDS)) && - link->type != dc_connection_none) { - /* - * Event if registration failed, we should continue with - * DM initialization because not having a backlight control - * is better then a black screen. - */ - if (!dm->backlight_dev[dm->num_of_edps]) - amdgpu_dm_register_backlight_device(dm); + int bl_idx = dm->num_of_edps; - if (dm->backlight_dev[dm->num_of_edps]) { - dm->backlight_link[dm->num_of_edps] = link; - dm->num_of_edps++; - } + if (!(link->connector_signal & (SIGNAL_TYPE_EDP | SIGNAL_TYPE_LVDS)) || + link->type == dc_connection_none) + return; + + if (dm->num_of_edps >= AMDGPU_DM_MAX_NUM_EDP) { + drm_warn(adev_to_drm(dm->adev), "Too much eDP connections, skipping backlight setup for additional eDPs\n"); + return; } + + amdgpu_dm_register_backlight_device(dm); + if (!dm->backlight_dev[bl_idx]) + return; + + dm->backlight_link[bl_idx] = link; + dm->num_of_edps++; } static void amdgpu_set_panel_orientation(struct drm_connector *connector); -- cgit v1.2.3 From 52b29307a98789853d87ed0a68031ec18063cba4 Mon Sep 17 00:00:00 2001 From: Alex Hung Date: Mon, 6 Mar 2023 11:39:51 +0800 Subject: drm/amd/display: remove outdated 8bpc comments [Why] The commit c76e483cd916 ("drm/amd/display: Don't restrict bpc to 8 bpc") removes the historical 8bpc dependency and sets max_bpc to 16. [How] The comment that states "8bpc for non-edp" needs to be removed as well. Reviewed-by: Harry Wentland Acked-by: Qingqing Zhuo Signed-off-by: Alex Hung Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index cbf36131cdd0..5bac5781a06b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -7284,7 +7284,6 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm, if (!aconnector->mst_root) drm_connector_attach_max_bpc_property(&aconnector->base, 8, 16); - /* This defaults to the max in the range, but we want 8bpc for non-edp. */ aconnector->base.state->max_bpc = 16; aconnector->base.state->max_requested_bpc = aconnector->base.state->max_bpc; -- cgit v1.2.3 From 6d457ca162da98a6a1a381320e936d7448177de9 Mon Sep 17 00:00:00 2001 From: Alex Hung Date: Mon, 6 Mar 2023 11:39:51 +0800 Subject: drm/amd/display: remove outdated 8bpc comments [Why] The commit c76e483cd916 ("drm/amd/display: Don't restrict bpc to 8 bpc") removes the historical 8bpc dependency and sets max_bpc to 16. [How] The comment that states "8bpc for non-edp" needs to be removed as well. Reviewed-by: Harry Wentland Acked-by: Qingqing Zhuo Signed-off-by: Alex Hung Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 32abbafd43fa..a01fd41643fc 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -7244,7 +7244,6 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm, if (!aconnector->mst_root) drm_connector_attach_max_bpc_property(&aconnector->base, 8, 16); - /* This defaults to the max in the range, but we want 8bpc for non-edp. */ aconnector->base.state->max_bpc = 16; aconnector->base.state->max_requested_bpc = aconnector->base.state->max_bpc; -- cgit v1.2.3 From 0e909e4fa8895bcef1b1ef2e39b9f1a158933ffe Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Tue, 21 Mar 2023 18:58:50 +0100 Subject: drm/amd/display: Slightly optimize dm_dmub_outbox1_low_irq() A kzalloc()+memcpy() can be optimized in a single kmemdup(). This saves a few cycles because some memory doesn't need to be zeroed. Signed-off-by: Christophe JAILLET Signed-off-by: Hamza Mahfooz Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 5bac5781a06b..57a5fbdab890 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -820,15 +820,14 @@ static void dm_dmub_outbox1_low_irq(void *interrupt_params) DRM_ERROR("Failed to allocate dmub_hpd_wrk"); return; } - dmub_hpd_wrk->dmub_notify = kzalloc(sizeof(struct dmub_notification), GFP_ATOMIC); + dmub_hpd_wrk->dmub_notify = kmemdup(¬ify, sizeof(struct dmub_notification), + GFP_ATOMIC); if (!dmub_hpd_wrk->dmub_notify) { kfree(dmub_hpd_wrk); DRM_ERROR("Failed to allocate dmub_hpd_wrk->dmub_notify"); return; } INIT_WORK(&dmub_hpd_wrk->handle_hpd_work, dm_handle_hpd_work); - if (dmub_hpd_wrk->dmub_notify) - memcpy(dmub_hpd_wrk->dmub_notify, ¬ify, sizeof(struct dmub_notification)); dmub_hpd_wrk->adev = adev; if (notify.type == DMUB_NOTIFICATION_HPD) { plink = adev->dm.dc->links[notify.link_index]; -- cgit v1.2.3 From f196198cafb8f0f2bedf1d8abc755f791fc03648 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 12 Mar 2023 20:17:48 +0100 Subject: drm/amd/display/amdgpu_dm: Add a bl_idx to amdgpu_dm_connector Currently functions like update_connector_ext_caps() and amdgpu_dm_connector_destroy() are iterating over dm->backlight_link[i] to find the index of the (optional) backlight_dev associated with the connector. Instead make register_backlight_device() store the dm->backlight_dev[] index used for the connector inside the amdgpu_dm_connector struct. This removes the need to iterate over the dm->backlight_link[] array and this is necessary as a preparation patch for moving the actual backlight_device_register() call to drm_connector_funcs.late_register. While reworking update_connector_ext_caps() also remove the aconnector and aconnector->dc_link NULL checks in this function. These are both never NULL and are unconditionally derefed in its callers. Reviewed-by: Rodrigo Siqueira Signed-off-by: Hans de Goede Signed-off-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 42 +++++++++-------------- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 1 + 2 files changed, 17 insertions(+), 26 deletions(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 57a5fbdab890..ee252158ef87 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2975,30 +2975,18 @@ static struct drm_mode_config_helper_funcs amdgpu_dm_mode_config_helperfuncs = { static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector) { struct amdgpu_dm_backlight_caps *caps; - struct amdgpu_display_manager *dm; struct drm_connector *conn_base; struct amdgpu_device *adev; - struct dc_link *link = NULL; struct drm_luminance_range_info *luminance_range; - int i; - - if (!aconnector || !aconnector->dc_link) - return; - link = aconnector->dc_link; - if (link->connector_signal != SIGNAL_TYPE_EDP) + if (aconnector->bl_idx == -1 || + aconnector->dc_link->connector_signal != SIGNAL_TYPE_EDP) return; conn_base = &aconnector->base; adev = drm_to_adev(conn_base->dev); - dm = &adev->dm; - for (i = 0; i < dm->num_of_edps; i++) { - if (link == dm->backlight_link[i]) - break; - } - if (i >= dm->num_of_edps) - return; - caps = &dm->backlight_caps[i]; + + caps = &adev->dm.backlight_caps[aconnector->bl_idx]; caps->ext_caps = &aconnector->dc_link->dpcd_sink_ext_caps; caps->aux_support = false; @@ -4266,8 +4254,9 @@ static int initialize_plane(struct amdgpu_display_manager *dm, static void register_backlight_device(struct amdgpu_display_manager *dm, - struct dc_link *link) + struct amdgpu_dm_connector *aconnector) { + struct dc_link *link = aconnector->dc_link; int bl_idx = dm->num_of_edps; if (!(link->connector_signal & (SIGNAL_TYPE_EDP | SIGNAL_TYPE_LVDS)) || @@ -4279,9 +4268,13 @@ static void register_backlight_device(struct amdgpu_display_manager *dm, return; } + aconnector->bl_idx = bl_idx; + amdgpu_dm_register_backlight_device(dm); - if (!dm->backlight_dev[bl_idx]) + if (!dm->backlight_dev[bl_idx]) { + aconnector->bl_idx = -1; return; + } dm->backlight_link[bl_idx] = link; dm->num_of_edps++; @@ -4464,7 +4457,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) if (ret) { amdgpu_dm_update_connector_after_detect(aconnector); - register_backlight_device(dm, link); + register_backlight_device(dm, aconnector); if (dm->num_of_edps) update_connector_ext_caps(aconnector); @@ -6243,10 +6236,8 @@ static void amdgpu_dm_connector_unregister(struct drm_connector *connector) static void amdgpu_dm_connector_destroy(struct drm_connector *connector) { struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); - const struct dc_link *link = aconnector->dc_link; struct amdgpu_device *adev = drm_to_adev(connector->dev); struct amdgpu_display_manager *dm = &adev->dm; - int i; /* * Call only if mst_mgr was initialized before since it's not done @@ -6255,11 +6246,9 @@ static void amdgpu_dm_connector_destroy(struct drm_connector *connector) if (aconnector->mst_mgr.dev) drm_dp_mst_topology_mgr_destroy(&aconnector->mst_mgr); - for (i = 0; i < dm->num_of_edps; i++) { - if ((link == dm->backlight_link[i]) && dm->backlight_dev[i]) { - backlight_device_unregister(dm->backlight_dev[i]); - dm->backlight_dev[i] = NULL; - } + if (aconnector->bl_idx != -1) { + backlight_device_unregister(dm->backlight_dev[aconnector->bl_idx]); + dm->backlight_dev[aconnector->bl_idx] = NULL; } if (aconnector->dc_em_sink) @@ -7229,6 +7218,7 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm, aconnector->base.funcs->reset(&aconnector->base); aconnector->connector_id = link_index; + aconnector->bl_idx = -1; aconnector->dc_link = link; aconnector->base.interlace_allowed = false; aconnector->base.doublescan_allowed = false; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index 904f9e2fd35b..2e2413fd73a4 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -610,6 +610,7 @@ struct amdgpu_dm_connector { struct drm_connector base; uint32_t connector_id; + int bl_idx; /* we need to mind the EDID between detect and get modes due to analog/digital/tvencoder */ -- cgit v1.2.3 From 618e51cd526cbbb2ea9ad01ef1f67719b775f792 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 12 Mar 2023 20:17:49 +0100 Subject: drm/amd/display/amdgpu_dm: Move most backlight setup into setup_backlight_device() Rename register_backlight_device() to setup_backlight_device() and move all backlight setup related calls from amdgpu_dm_register_backlight_device() and from amdgpu_dm_initialize_drm_device() there. This leaves amdgpu_dm_register_backlight_device() dealing purely with registering the actual backlight class device. This is a preparation patch for moving the actual backlight class device registering to drm_connector_funcs.late_register. Reviewed-by: Rodrigo Siqueira Signed-off-by: Hans de Goede Signed-off-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index ee252158ef87..52248616c737 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4182,9 +4182,6 @@ amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm) char bl_name[16]; struct backlight_properties props = { 0 }; - amdgpu_dm_update_backlight_caps(dm, dm->num_of_edps); - dm->brightness[dm->num_of_edps] = AMDGPU_MAX_BL_LEVEL; - if (!acpi_video_backlight_use_native()) { drm_info(adev_to_drm(dm->adev), "Skipping amdgpu DM backlight registration\n"); /* Try registering an ACPI video backlight device instead. */ @@ -4253,8 +4250,8 @@ static int initialize_plane(struct amdgpu_display_manager *dm, } -static void register_backlight_device(struct amdgpu_display_manager *dm, - struct amdgpu_dm_connector *aconnector) +static void setup_backlight_device(struct amdgpu_display_manager *dm, + struct amdgpu_dm_connector *aconnector) { struct dc_link *link = aconnector->dc_link; int bl_idx = dm->num_of_edps; @@ -4270,6 +4267,9 @@ static void register_backlight_device(struct amdgpu_display_manager *dm, aconnector->bl_idx = bl_idx; + amdgpu_dm_update_backlight_caps(dm, bl_idx); + dm->brightness[bl_idx] = AMDGPU_MAX_BL_LEVEL; + amdgpu_dm_register_backlight_device(dm); if (!dm->backlight_dev[bl_idx]) { aconnector->bl_idx = -1; @@ -4278,6 +4278,8 @@ static void register_backlight_device(struct amdgpu_display_manager *dm, dm->backlight_link[bl_idx] = link; dm->num_of_edps++; + + update_connector_ext_caps(aconnector); } static void amdgpu_set_panel_orientation(struct drm_connector *connector); @@ -4457,10 +4459,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) if (ret) { amdgpu_dm_update_connector_after_detect(aconnector); - register_backlight_device(dm, aconnector); - - if (dm->num_of_edps) - update_connector_ext_caps(aconnector); + setup_backlight_device(dm, aconnector); if (psr_feature_enabled) amdgpu_dm_set_psr_caps(link); -- cgit v1.2.3 From 213eca2b0c042b024bf9697a278619f887bab4e5 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 12 Mar 2023 20:17:50 +0100 Subject: drm/amd/display/amdgpu_dm: Make amdgpu_dm_register_backlight_device() take an amdgpu_dm_connector Make amdgpu_dm_register_backlight_device() take an amdgpu_dm_connector pointer to the connector for which it should register the backlight as its only argument. This is a preparation patch for moving the actual backlight class device registering to drm_connector_funcs.late_register. Reviewed-by: Rodrigo Siqueira Signed-off-by: Hans de Goede Signed-off-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 24 +++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 52248616c737..aee79506a969 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4177,13 +4177,15 @@ static const struct backlight_ops amdgpu_dm_backlight_ops = { }; static void -amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm) +amdgpu_dm_register_backlight_device(struct amdgpu_dm_connector *aconnector) { - char bl_name[16]; + struct drm_device *drm = aconnector->base.dev; + struct amdgpu_display_manager *dm = &drm_to_adev(drm)->dm; struct backlight_properties props = { 0 }; + char bl_name[16]; if (!acpi_video_backlight_use_native()) { - drm_info(adev_to_drm(dm->adev), "Skipping amdgpu DM backlight registration\n"); + drm_info(drm, "Skipping amdgpu DM backlight registration\n"); /* Try registering an ACPI video backlight device instead. */ acpi_video_register_backlight(); return; @@ -4194,17 +4196,15 @@ amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm) props.type = BACKLIGHT_RAW; snprintf(bl_name, sizeof(bl_name), "amdgpu_bl%d", - adev_to_drm(dm->adev)->primary->index + dm->num_of_edps); + drm->primary->index + aconnector->bl_idx); - dm->backlight_dev[dm->num_of_edps] = backlight_device_register(bl_name, - adev_to_drm(dm->adev)->dev, - dm, - &amdgpu_dm_backlight_ops, - &props); + dm->backlight_dev[aconnector->bl_idx] = + backlight_device_register(bl_name, drm->dev, dm, + &amdgpu_dm_backlight_ops, &props); - if (IS_ERR(dm->backlight_dev[dm->num_of_edps])) { + if (IS_ERR(dm->backlight_dev[aconnector->bl_idx])) { DRM_ERROR("DM: Backlight registration failed!\n"); - dm->backlight_dev[dm->num_of_edps] = NULL; + dm->backlight_dev[aconnector->bl_idx] = NULL; } else DRM_DEBUG_DRIVER("DM: Registered Backlight device: %s\n", bl_name); } @@ -4270,7 +4270,7 @@ static void setup_backlight_device(struct amdgpu_display_manager *dm, amdgpu_dm_update_backlight_caps(dm, bl_idx); dm->brightness[bl_idx] = AMDGPU_MAX_BL_LEVEL; - amdgpu_dm_register_backlight_device(dm); + amdgpu_dm_register_backlight_device(aconnector); if (!dm->backlight_dev[bl_idx]) { aconnector->bl_idx = -1; return; -- cgit v1.2.3 From 62f03dad76441ee3a58c26a0bbe703028e846db0 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 12 Mar 2023 20:17:51 +0100 Subject: drm/amd/display/amdgpu_dm: Pass proper parent for backlight device registration v3 The parent for the backlight device should be the drm-connector object, not the PCI device. Userspace relies on this to be able to detect which backlight class device to use on hybrid gfx devices where there may be multiple native (raw) backlight devices registered. Specifically gnome-settings-daemon expects the parent device to have an "enabled" sysfs attribute (as drm_connector devices do) and tests that this returns "enabled" when read. This aligns the parent of the backlight device with i915, nouveau, radeon. Note that drivers/gpu/drm/amd/amdgpu/atombios_encoders.c also already uses the drm_connector as parent, only amdgpu_dm.c used the PCI device as parent before this change. Changes in v3: Make amdgpu_dm_register_backlight_device() check bl_idx != 1 before registering the backlight since amdgpu_dm_connector_late_register() now calls it for _all_ connectors. Changes in v2: Together with changing the parent, also move the registration to drm_connector_funcs.late_register() this is necessary because the parent device (which now is the drm_connector) must be registered before the backlight class device is, otherwise the backlight class device ends up without any parent set at all. This brings the backlight class device registration timing inline with nouveau and i915 which also use drm_connector_funcs.late_register() for this. Note this slightly changes backlight_device_register() error handling, instead of not increasing dm->num_of_edps and re-using the current bl_idx for a potential other backlight device, dm->backlight_dev[bl_idx] is now simply left NULL on failure. This is ok because all code looking at dm->backlight_dev[i] also checks it is not NULL. Link: https://gitlab.gnome.org/GNOME/gnome-settings-daemon/-/issues/730 Reviewed-by: Rodrigo Siqueira Signed-off-by: Hans de Goede Signed-off-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index aee79506a969..5d0069f383d4 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4184,6 +4184,9 @@ amdgpu_dm_register_backlight_device(struct amdgpu_dm_connector *aconnector) struct backlight_properties props = { 0 }; char bl_name[16]; + if (aconnector->bl_idx == -1) + return; + if (!acpi_video_backlight_use_native()) { drm_info(drm, "Skipping amdgpu DM backlight registration\n"); /* Try registering an ACPI video backlight device instead. */ @@ -4199,7 +4202,7 @@ amdgpu_dm_register_backlight_device(struct amdgpu_dm_connector *aconnector) drm->primary->index + aconnector->bl_idx); dm->backlight_dev[aconnector->bl_idx] = - backlight_device_register(bl_name, drm->dev, dm, + backlight_device_register(bl_name, aconnector->base.kdev, dm, &amdgpu_dm_backlight_ops, &props); if (IS_ERR(dm->backlight_dev[aconnector->bl_idx])) { @@ -4269,13 +4272,6 @@ static void setup_backlight_device(struct amdgpu_display_manager *dm, amdgpu_dm_update_backlight_caps(dm, bl_idx); dm->brightness[bl_idx] = AMDGPU_MAX_BL_LEVEL; - - amdgpu_dm_register_backlight_device(aconnector); - if (!dm->backlight_dev[bl_idx]) { - aconnector->bl_idx = -1; - return; - } - dm->backlight_link[bl_idx] = link; dm->num_of_edps++; @@ -6329,6 +6325,8 @@ amdgpu_dm_connector_late_register(struct drm_connector *connector) to_amdgpu_dm_connector(connector); int r; + amdgpu_dm_register_backlight_device(amdgpu_dm_connector); + if ((connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) || (connector->connector_type == DRM_MODE_CONNECTOR_eDP)) { amdgpu_dm_connector->dm_dp_aux.aux.dev = connector->kdev; -- cgit v1.2.3 From 3335a13535312c9fad4d8d1307a621e6617d6ed8 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 27 Mar 2023 18:07:54 +0200 Subject: drm/amd/display: Whitespace cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 075e2099c32c ("drm/amd/display: Fix race condition in DPIA AUX transfer") was backported to stable, which I noticed because of git saying linux-6.1/.git/rebase-apply/patch:37154: space before tab in indent. while applying patch-6.1.21. While fixing the code location that issued that warning, improve in few more places. Signed-off-by: Uwe Kleine-König Signed-off-by: Hamza Mahfooz Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 26 +++++++++++------------ 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 5d0069f383d4..e29655a26dd4 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2299,9 +2299,9 @@ static int dm_late_init(void *handle) */ params.min_abm_backlight = 0x28F; /* In the case where abm is implemented on dmcub, - * dmcu object will be null. - * ABM 2.4 and up are implemented on dmcub. - */ + * dmcu object will be null. + * ABM 2.4 and up are implemented on dmcub. + */ if (dmcu) { if (!dmcu_load_iram(dmcu, params)) return -EINVAL; @@ -7091,13 +7091,13 @@ static uint add_fs_modes(struct amdgpu_dm_connector *aconnector) /* Standard FPS values * * 23.976 - TV/NTSC - * 24 - Cinema - * 25 - TV/PAL + * 24 - Cinema + * 25 - TV/PAL * 29.97 - TV/NTSC - * 30 - TV/NTSC - * 48 - Cinema HFR - * 50 - TV/PAL - * 60 - Commonly used + * 30 - TV/NTSC + * 48 - Cinema HFR + * 50 - TV/PAL + * 60 - Commonly used * 48,72,96,120 - Multiples of 24 */ static const u32 common_rates[] = { @@ -7726,7 +7726,7 @@ static void update_freesync_state_on_stream( return; spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags); - vrr_params = acrtc->dm_irq_params.vrr_params; + vrr_params = acrtc->dm_irq_params.vrr_params; if (surface) { mod_freesync_handle_preflip( @@ -8307,7 +8307,7 @@ static void amdgpu_dm_commit_audio(struct drm_device *dev, if (!drm_atomic_crtc_needs_modeset(new_crtc_state)) continue; - notify: +notify: aconnector = to_amdgpu_dm_connector(connector); mutex_lock(&adev->dm.audio_lock); @@ -9323,7 +9323,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm, skip_modeset: /* Release extra reference */ if (new_stream) - dc_stream_release(new_stream); + dc_stream_release(new_stream); /* * We want to do dc stream updates that do not require a @@ -10657,7 +10657,7 @@ int amdgpu_dm_process_dmub_aux_transfer_sync( if (!dc_process_dmub_aux_transfer_async(ctx->dc, link_index, payload)) { *operation_result = AUX_RET_ERROR_ENGINE_ACQUIRE; goto out; - } + } if (!wait_for_completion_timeout(&adev->dm.dmub_aux_transfer_done, 10 * HZ)) { DRM_ERROR("wait_for_completion_timeout timeout!"); -- cgit v1.2.3 From 67abe9c6a8077819aae490dcd3b9629c2e87bfc2 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 4 Apr 2023 13:02:50 +0200 Subject: ACPI: video: Remove register_backlight_delay module option and code Since commit 5aa9d943e9b6 ("ACPI: video: Don't enable fallback path for creating ACPI backlight by default"), the delayed registering of acpi_video# backlight devices has been disabled by default. The few bugreports where this option was used as a workaround were all cases where the GPU driver did not call acpi_video_register_backlight() and the workaround was to pass video.register_backlight_delay=1. With the recent "ACPI: video: Make acpi_backlight=video work independent from GPU driver" changes acpi_backlight=video can be used to achieve the same result. So there is no need for the register_backlight_delay option + code anymore. Reviewed-by: Mario Limonciello Signed-off-by: Hans de Goede Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_video.c | 38 ----------------------- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 --- include/acpi/video.h | 2 -- 3 files changed, 44 deletions(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/acpi/acpi_video.c b/drivers/acpi/acpi_video.c index c7a6d0b69dab..62f4364e4460 100644 --- a/drivers/acpi/acpi_video.c +++ b/drivers/acpi/acpi_video.c @@ -70,12 +70,6 @@ module_param(device_id_scheme, bool, 0444); static int only_lcd = -1; module_param(only_lcd, int, 0444); -static int register_backlight_delay; -module_param(register_backlight_delay, int, 0444); -MODULE_PARM_DESC(register_backlight_delay, - "Delay in seconds before doing fallback (non GPU driver triggered) " - "backlight registration, set to 0 to disable."); - static bool may_report_brightness_keys; static int register_count; static DEFINE_MUTEX(register_count_mutex); @@ -84,9 +78,6 @@ static LIST_HEAD(video_bus_head); static int acpi_video_bus_add(struct acpi_device *device); static void acpi_video_bus_remove(struct acpi_device *device); static void acpi_video_bus_notify(struct acpi_device *device, u32 event); -static void acpi_video_bus_register_backlight_work(struct work_struct *ignored); -static DECLARE_DELAYED_WORK(video_bus_register_backlight_work, - acpi_video_bus_register_backlight_work); /* * Indices in the _BCL method response: the first two items are special, @@ -2096,11 +2087,6 @@ static void acpi_video_bus_remove(struct acpi_device *device) kfree(video); } -static void acpi_video_bus_register_backlight_work(struct work_struct *ignored) -{ - acpi_video_register_backlight(); -} - static int __init is_i740(struct pci_dev *dev) { if (dev->device == 0x00D1) @@ -2183,17 +2169,6 @@ static bool should_check_lcd_flag(void) return false; } -/* - * At least one graphics driver has reported that no LCD is connected - * via the native interface. cancel the registration for fallback acpi_video0. - * If another driver still deems this necessary, it can explicitly register it. - */ -void acpi_video_report_nolcd(void) -{ - cancel_delayed_work(&video_bus_register_backlight_work); -} -EXPORT_SYMBOL(acpi_video_report_nolcd); - int acpi_video_register(void) { int ret = 0; @@ -2222,18 +2197,6 @@ int acpi_video_register(void) */ register_count = 1; - /* - * acpi_video_bus_add() skips registering the userspace visible - * backlight_device. The intend is for this to be registered by the - * drm/kms driver calling acpi_video_register_backlight() *after* it is - * done setting up its own native backlight device. The delayed work - * ensures that acpi_video_register_backlight() always gets called - * eventually, in case there is no drm/kms driver or it is disabled. - */ - if (register_backlight_delay) - schedule_delayed_work(&video_bus_register_backlight_work, - register_backlight_delay * HZ); - leave: mutex_unlock(®ister_count_mutex); return ret; @@ -2244,7 +2207,6 @@ void acpi_video_unregister(void) { mutex_lock(®ister_count_mutex); if (register_count) { - cancel_delayed_work_sync(&video_bus_register_backlight_work); acpi_bus_unregister_driver(&acpi_video_bus); register_count = 0; may_report_brightness_keys = false; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index a01fd41643fc..d8b3e1224ec2 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4445,10 +4445,6 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) amdgpu_set_panel_orientation(&aconnector->base); } - /* If we didn't find a panel, notify the acpi video detection */ - if (dm->adev->flags & AMD_IS_APU && dm->num_of_edps == 0) - acpi_video_report_nolcd(); - /* Software is initialized. Now we can register interrupt handlers. */ switch (adev->asic_type) { #if defined(CONFIG_DRM_AMD_DC_SI) diff --git a/include/acpi/video.h b/include/acpi/video.h index ff5a8da5d883..4230392b5b0b 100644 --- a/include/acpi/video.h +++ b/include/acpi/video.h @@ -53,7 +53,6 @@ enum acpi_backlight_type { }; #if IS_ENABLED(CONFIG_ACPI_VIDEO) -extern void acpi_video_report_nolcd(void); extern int acpi_video_register(void); extern void acpi_video_unregister(void); extern void acpi_video_register_backlight(void); @@ -81,7 +80,6 @@ static inline bool acpi_video_backlight_use_native(void) return __acpi_video_get_backlight_type(true, NULL) == acpi_backlight_native; } #else -static inline void acpi_video_report_nolcd(void) { return; }; static inline int acpi_video_register(void) { return -ENODEV; } static inline void acpi_video_unregister(void) { return; } static inline void acpi_video_register_backlight(void) { return; } -- cgit v1.2.3 From 52f1783ff4146344342422c1cd94fcb4ce39b6fe Mon Sep 17 00:00:00 2001 From: Igor Artemiev Date: Mon, 3 Apr 2023 16:10:37 +0300 Subject: drm/amd/display: Fix potential null dereference The adev->dm.dc pointer can be NULL and dereferenced in amdgpu_dm_fini() without checking. Add a NULL pointer check before calling dc_dmub_srv_destroy(). Found by Linux Verification Center (linuxtesting.org) with SVACE. Fixes: 9a71c7d31734 ("drm/amd/display: Register DMUB service with DC") Signed-off-by: Igor Artemiev Signed-off-by: Hamza Mahfooz Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index e29655a26dd4..6cacb76f389e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1890,7 +1890,8 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev) if (adev->dm.dc) dc_deinit_callbacks(adev->dm.dc); - dc_dmub_srv_destroy(&adev->dm.dc->ctx->dmub_srv); + if (adev->dm.dc) + dc_dmub_srv_destroy(&adev->dm.dc->ctx->dmub_srv); if (dc_enable_dmub_notifications(adev->dm.dc)) { kfree(adev->dm.dmub_notify); -- cgit v1.2.3 From da5e14909776edea4462672fb4a3007802d262e7 Mon Sep 17 00:00:00 2001 From: Aurabindo Pillai Date: Fri, 24 Mar 2023 10:42:37 -0400 Subject: drm/amd/display: Fix hang when skipping modeset [Why&How] When skipping full modeset since the only state change was a front porch change, the DC commit sequence requires extra checks to handle non existant plane states being asked to be removed from context. Reviewed-by: Alvin Lee Acked-by: Qingqing Zhuo Signed-off-by: Aurabindo Pillai Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 5 ++++- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 6cacb76f389e..c432436cd66d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -7972,6 +7972,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, continue; dc_plane = dm_new_plane_state->dc_state; + if (!dc_plane) + continue; bundle->surface_updates[planes_count].surface = dc_plane; if (new_pcrtc_state->color_mgmt_changed) { @@ -9620,8 +9622,9 @@ static int dm_update_plane_state(struct dc *dc, return -EINVAL; } + if (dm_old_plane_state->dc_state) + dc_plane_state_release(dm_old_plane_state->dc_state); - dc_plane_state_release(dm_old_plane_state->dc_state); dm_new_plane_state->dc_state = NULL; *lock_and_validation_needed = 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 85d54bfb595c..117d80cb36fb 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1707,6 +1707,9 @@ bool dc_remove_plane_from_context( struct dc_stream_status *stream_status = NULL; struct resource_pool *pool = dc->res_pool; + if (!plane_state) + return true; + for (i = 0; i < context->stream_count; i++) if (context->streams[i] == stream) { stream_status = &context->stream_status[i]; -- cgit v1.2.3 From 025ce392b5f213696ca0af3e07735d0fae020694 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Mon, 27 Mar 2023 09:10:48 -0400 Subject: drm/amd/display: fix memleak in aconnector->timing_requested [Why] when amdgpu_dm_update_connector_after_detect is called two times successively with valid sink, memory allocated of aconnector->timing_requested for the first call is not free. this causes memeleak. [How] allocate memory only when aconnector->timing_requested is null. Reviewed-by: Qingqing Zhuo Acked-by: Qingqing Zhuo Signed-off-by: Hersen Wu Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index c432436cd66d..8b03c8d8f0b8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3128,9 +3128,12 @@ void amdgpu_dm_update_connector_after_detect( aconnector->edid); } - aconnector->timing_requested = kzalloc(sizeof(struct dc_crtc_timing), GFP_KERNEL); - if (!aconnector->timing_requested) - dm_error("%s: failed to create aconnector->requested_timing\n", __func__); + if (!aconnector->timing_requested) { + aconnector->timing_requested = + kzalloc(sizeof(struct dc_crtc_timing), GFP_KERNEL); + if (!aconnector->timing_requested) + dm_error("failed to create aconnector->requested_timing\n"); + } drm_connector_update_edid_property(connector, aconnector->edid); amdgpu_dm_update_freesync_caps(connector, aconnector->edid); -- cgit v1.2.3 From 3cf7cd3f770a0b89dc5f06e19edb52e65b93b214 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Tue, 28 Mar 2023 10:45:24 -0400 Subject: drm/amd/display: fix access hdcp_workqueue assert MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [Why] hdcp are enabled for asics from raven. for old asics which hdcp are not enabled, hdcp_workqueue are null. some access to hdcp work queue are not guarded with pointer check. [How] add hdcp_workqueue pointer check before access workqueue. Fixes: 82986fd631fa ("drm/amd/display: save restore hdcp state when display is unplugged from mst hub") Link: https://gitlab.freedesktop.org/drm/amd/-/issues/2444 Reported-by: Niklāvs Koļesņikovs <89q1r14hd@relay.firefox.com> Reviewed-by: Bhawanpreet Lakha Acked-by: Qingqing Zhuo Signed-off-by: Hersen Wu Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 6 ++++++ .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 16 ++++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 8b03c8d8f0b8..fc08b4191e24 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -8559,6 +8559,9 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) struct amdgpu_crtc *acrtc = to_amdgpu_crtc(dm_new_con_state->base.crtc); struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); + if (!adev->dm.hdcp_workqueue) + continue; + pr_debug("[HDCP_DM] -------------- i : %x ----------\n", i); if (!connector) @@ -8607,6 +8610,9 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) struct amdgpu_crtc *acrtc = to_amdgpu_crtc(dm_new_con_state->base.crtc); struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); + if (!adev->dm.hdcp_workqueue) + continue; + new_crtc_state = NULL; old_crtc_state = NULL; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 994ba426ca66..5dc79b753d5f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -379,13 +379,17 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector) if (aconnector->dc_sink && connector->state) { struct drm_device *dev = connector->dev; struct amdgpu_device *adev = drm_to_adev(dev); - struct hdcp_workqueue *hdcp_work = adev->dm.hdcp_workqueue; - struct hdcp_workqueue *hdcp_w = &hdcp_work[aconnector->dc_link->link_index]; - connector->state->hdcp_content_type = - hdcp_w->hdcp_content_type[connector->index]; - connector->state->content_protection = - hdcp_w->content_protection[connector->index]; + if (adev->dm.hdcp_workqueue) { + struct hdcp_workqueue *hdcp_work = adev->dm.hdcp_workqueue; + struct hdcp_workqueue *hdcp_w = + &hdcp_work[aconnector->dc_link->link_index]; + + connector->state->hdcp_content_type = + hdcp_w->hdcp_content_type[connector->index]; + connector->state->content_protection = + hdcp_w->content_protection[connector->index]; + } } if (aconnector->dc_sink) { -- cgit v1.2.3 From dd24662d9dfbad281bbf030f06d68c7938fa0c66 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Sun, 29 May 2022 10:54:30 -0400 Subject: drm/amd/display: Return error code on DSC atomic check failure [Why&How] We were not returning -EINVAL on DSC atomic check fail. Add it. Fixes: 71be4b16d39a ("drm/amd/display: dsc validate fail not pass to atomic check") Reviewed-by: Aurabindo Pillai Signed-off-by: Hersen Wu Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1 + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index fc08b4191e24..b619d7cdb525 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -10170,6 +10170,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, ret = compute_mst_dsc_configs_for_state(state, dm_state->context, vars); if (ret) { DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state() failed\n"); + ret = -EINVAL; goto fail; } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 5dc79b753d5f..810ab682f424 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -1410,6 +1410,7 @@ int pre_validate_dsc(struct drm_atomic_state *state, ret = pre_compute_mst_dsc_configs_for_state(state, local_dc_state, vars); if (ret != 0) { DRM_INFO_ONCE("pre_compute_mst_dsc_configs_for_state() failed\n"); + ret = -EINVAL; goto clean_exit; } -- cgit v1.2.3 From 08da182175db4c7f80850354849d95f2670e8cd9 Mon Sep 17 00:00:00 2001 From: Hamza Mahfooz Date: Fri, 14 Apr 2023 14:26:27 -0400 Subject: drm/amd/display: fix flickering caused by S/G mode Currently, on a handful of ASICs. We allow the framebuffer for a given plane to exist in either VRAM or GTT. However, if the plane's new framebuffer is in a different memory domain than it's previous framebuffer, flipping between them can cause the screen to flicker. So, to fix this, don't perform an immediate flip in the aforementioned case. Cc: stable@vger.kernel.org Link: https://gitlab.freedesktop.org/drm/amd/-/issues/2354 Reviewed-by: Roman Li Fixes: 81d0bcf99009 ("drm/amdgpu: make display pinning more flexible (v2)") Signed-off-by: Hamza Mahfooz Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index b619d7cdb525..8d17fd5a817e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -7901,6 +7901,13 @@ static void amdgpu_dm_commit_cursors(struct drm_atomic_state *state) amdgpu_dm_plane_handle_cursor_update(plane, old_plane_state); } +static inline uint32_t get_mem_type(struct drm_framebuffer *fb) +{ + struct amdgpu_bo *abo = gem_to_amdgpu_bo(fb->obj[0]); + + return abo->tbo.resource ? abo->tbo.resource->mem_type : 0; +} + static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, struct dc_state *dc_state, struct drm_device *dev, @@ -8043,11 +8050,13 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, /* * Only allow immediate flips for fast updates that don't - * change FB pitch, DCC state, rotation or mirroing. + * change memory domain, FB pitch, DCC state, rotation or + * mirroring. */ bundle->flip_addrs[planes_count].flip_immediate = crtc->state->async_flip && - acrtc_state->update_type == UPDATE_TYPE_FAST; + acrtc_state->update_type == UPDATE_TYPE_FAST && + get_mem_type(old_plane_state->fb) == get_mem_type(fb); timestamp_ns = ktime_get_ns(); bundle->flip_addrs[planes_count].flip_timestamp_in_us = div_u64(timestamp_ns, 1000); -- cgit v1.2.3 From 137f9cee113df91107cf91c130d5c414c4b191f0 Mon Sep 17 00:00:00 2001 From: Alan Liu Date: Tue, 2 May 2023 17:54:50 +0800 Subject: drm/amd/display: Fix warning in disabling vblank irq [Why] During gpu-reset, we toggle vblank irq by calling dc_interrupt_set() instead of amdgpu_irq_get/put() because we don't want to change the irq source's refcount. However, we see the warning when vblank irq is enabled by dc_interrupt_set() during gpu-reset but disabled by amdgpu_irq_put() after gpu-reset. [How] Only in dm_gpureset_toggle_interrupts() we toggle vblank interrupts by calling dc_interrupt_set(). Apart from this we call dm_set_vblank() which uses amdgpu_irq_get/put() to operate vblank irq. Reviewed-by: Bhawanpreet Lakha Acked-by: Tom Chung Signed-off-by: Alan Liu Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 21 +++++++++++++-------- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c | 16 +++------------- 2 files changed, 16 insertions(+), 21 deletions(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 8b4b186c57f5..26b5cbc97046 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2479,20 +2479,25 @@ static void dm_gpureset_toggle_interrupts(struct amdgpu_device *adev, if (acrtc && state->stream_status[i].plane_count != 0) { irq_source = IRQ_TYPE_PFLIP + acrtc->otg_inst; rc = dc_interrupt_set(adev->dm.dc, irq_source, enable) ? 0 : -EBUSY; - DRM_DEBUG_VBL("crtc %d - vupdate irq %sabling: r=%d\n", - acrtc->crtc_id, enable ? "en" : "dis", rc); if (rc) DRM_WARN("Failed to %s pflip interrupts\n", enable ? "enable" : "disable"); if (enable) { - rc = amdgpu_dm_crtc_enable_vblank(&acrtc->base); - if (rc) - DRM_WARN("Failed to enable vblank interrupts\n"); - } else { - amdgpu_dm_crtc_disable_vblank(&acrtc->base); - } + if (amdgpu_dm_crtc_vrr_active(to_dm_crtc_state(acrtc->base.state))) + rc = amdgpu_dm_crtc_set_vupdate_irq(&acrtc->base, true); + } else + rc = amdgpu_dm_crtc_set_vupdate_irq(&acrtc->base, false); + if (rc) + DRM_WARN("Failed to %sable vupdate interrupt\n", enable ? "en" : "dis"); + + irq_source = IRQ_TYPE_VBLANK + acrtc->otg_inst; + /* During gpu-reset we disable and then enable vblank irq, so + * don't use amdgpu_irq_get/put() to avoid refcount change. + */ + if (!dc_interrupt_set(adev->dm.dc, irq_source, enable)) + DRM_WARN("Failed to %sable vblank interrupt\n", enable ? "en" : "dis"); } } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c index e3762e806617..440fc0869a34 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c @@ -146,7 +146,6 @@ static void vblank_control_worker(struct work_struct *work) static inline int dm_set_vblank(struct drm_crtc *crtc, bool enable) { - enum dc_irq_source irq_source; struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); struct amdgpu_device *adev = drm_to_adev(crtc->dev); struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); @@ -169,18 +168,9 @@ static inline int dm_set_vblank(struct drm_crtc *crtc, bool enable) if (rc) return rc; - if (amdgpu_in_reset(adev)) { - irq_source = IRQ_TYPE_VBLANK + acrtc->otg_inst; - /* During gpu-reset we disable and then enable vblank irq, so - * don't use amdgpu_irq_get/put() to avoid refcount change. - */ - if (!dc_interrupt_set(adev->dm.dc, irq_source, enable)) - rc = -EBUSY; - } else { - rc = (enable) - ? amdgpu_irq_get(adev, &adev->crtc_irq, acrtc->crtc_id) - : amdgpu_irq_put(adev, &adev->crtc_irq, acrtc->crtc_id); - } + rc = (enable) + ? amdgpu_irq_get(adev, &adev->crtc_irq, acrtc->crtc_id) + : amdgpu_irq_put(adev, &adev->crtc_irq, acrtc->crtc_id); if (rc) return rc; -- cgit v1.2.3 From 482e6ad9adde69d9da08864b4ccf4dfd53edb2f0 Mon Sep 17 00:00:00 2001 From: Fangzhi Zuo Date: Wed, 10 May 2023 16:43:30 -0400 Subject: drm/amd/display: Have Payload Properly Created After Resume At drm suspend sequence, MST dc_sink is removed. When commit cached MST stream back in drm resume sequence, the MST stream payload is not properly created and added into the payload table. After resume, topology change is reprobed by removing existing streams first. That leads to no payload is found in the existing payload table as below error "[drm] ERROR No payload for [MST PORT:] found in mst state" 1. In encoder .atomic_check routine, remove check existance of dc_sink 2. Bypass MST by checking existence of MST root port. dc_link_type cannot differentiate MST port before topology is rediscovered. Reviewed-by: Wayne Lin Acked-by: Tom Chung Signed-off-by: Fangzhi Zuo Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 26b5cbc97046..d5cec03eaa8d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2857,7 +2857,7 @@ static int dm_resume(void *handle) * this is the case when traversing through already created * MST connectors, should be skipped */ - if (aconnector->dc_link->type == dc_connection_mst_branch) + if (aconnector && aconnector->mst_root) continue; mutex_lock(&aconnector->hpd_lock); @@ -6742,7 +6742,7 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder, int clock, bpp = 0; bool is_y420 = false; - if (!aconnector->mst_output_port || !aconnector->dc_sink) + if (!aconnector->mst_output_port) return 0; mst_port = aconnector->mst_output_port; -- cgit v1.2.3 From e749dd10e5f292061ad63d2b030194bf7d7d452c Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Thu, 25 May 2023 08:37:40 -0400 Subject: drm/amd/display: edp do not add non-edid timings [Why] most edp support only timings from edid. applying non-edid timings, especially those timings out of edp bandwidth, may damage edp. [How] do not add non-edid timings for edp. Cc: Mario Limonciello Cc: Alex Deucher Cc: stable@vger.kernel.org Acked-by: Stylon Wang Signed-off-by: Hersen Wu Reviewed-by: Roman Li Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index d5cec03eaa8d..2b8d42de1f73 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -7196,7 +7196,13 @@ static int amdgpu_dm_connector_get_modes(struct drm_connector *connector) drm_add_modes_noedid(connector, 1920, 1080); } else { amdgpu_dm_connector_ddc_get_modes(connector, edid); - amdgpu_dm_connector_add_common_modes(encoder, connector); + /* most eDP supports only timings from its edid, + * usually only detailed timings are available + * from eDP edid. timings which are not from edid + * may damage eDP + */ + if (connector->connector_type != DRM_MODE_CONNECTOR_eDP) + amdgpu_dm_connector_add_common_modes(encoder, connector); amdgpu_dm_connector_add_freesync_modes(connector, edid); } amdgpu_dm_fbc_init(connector); -- cgit v1.2.3 From ea2062dd1f0384ae1b136d333ee4ced15bedae38 Mon Sep 17 00:00:00 2001 From: Tom Chung Date: Mon, 29 May 2023 18:00:09 +0800 Subject: drm/amd/display: fix the system hang while disable PSR [Why] When the PSR enabled. If you try to adjust the timing parameters, it may cause system hang. Because the timing mismatch with the DMCUB settings. [How] Disable the PSR before adjusting timing parameters. Cc: Mario Limonciello Cc: Alex Deucher Cc: stable@vger.kernel.org Acked-by: Stylon Wang Signed-off-by: Tom Chung Reviewed-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 2b8d42de1f73..7acd73e5004f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -8204,6 +8204,12 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, if (acrtc_state->abm_level != dm_old_crtc_state->abm_level) bundle->stream_update.abm_level = &acrtc_state->abm_level; + mutex_lock(&dm->dc_lock); + if ((acrtc_state->update_type > UPDATE_TYPE_FAST) && + acrtc_state->stream->link->psr_settings.psr_allow_active) + amdgpu_dm_psr_disable(acrtc_state->stream); + mutex_unlock(&dm->dc_lock); + /* * If FreeSync state on the stream has changed then we need to * re-adjust the min/max bounds now that DC doesn't handle this @@ -8217,10 +8223,6 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, spin_unlock_irqrestore(&pcrtc->dev->event_lock, flags); } mutex_lock(&dm->dc_lock); - if ((acrtc_state->update_type > UPDATE_TYPE_FAST) && - acrtc_state->stream->link->psr_settings.psr_allow_active) - amdgpu_dm_psr_disable(acrtc_state->stream); - update_planes_and_stream_adapter(dm->dc, acrtc_state->update_type, planes_count, -- cgit v1.2.3