aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/display/amdgpu_dm
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2022-08-02 10:06:12 -0700
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2022-08-02 10:06:12 -0700
commit8bb5e7f4dcd9b9ef22a3ea25c9066a8a968f12dd (patch)
tree0f1383880607a227142f9388a066959926233ff1 /drivers/gpu/drm/amd/display/amdgpu_dm
parentInput: document the units for resolution of size axes (diff)
parentInput: adc-joystick - fix ordering in adc_joystick_probe() (diff)
downloadlinux-rng-8bb5e7f4dcd9b9ef22a3ea25c9066a8a968f12dd.tar.xz
linux-rng-8bb5e7f4dcd9b9ef22a3ea25c9066a8a968f12dd.zip
Merge branch 'next' into for-linus
Prepare input updates for 5.20 (or 6.0) merge window.
Diffstat (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm')
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c335
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h27
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c179
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c6
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c205
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c6
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c295
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h17
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c248
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c77
10 files changed, 930 insertions, 465 deletions
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 075429bea427..9dd2e0601ea8 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -48,7 +48,7 @@
#include "amdgpu_dm.h"
#ifdef CONFIG_DRM_AMD_DC_HDCP
#include "amdgpu_dm_hdcp.h"
-#include <drm/drm_hdcp.h>
+#include <drm/display/drm_hdcp_helper.h>
#endif
#include "amdgpu_pm.h"
#include "amdgpu_atombios.h"
@@ -73,17 +73,17 @@
#include <linux/firmware.h>
#include <linux/component.h>
+#include <drm/display/drm_dp_mst_helper.h>
+#include <drm/display/drm_hdmi_helper.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_uapi.h>
#include <drm/drm_atomic_helper.h>
-#include <drm/drm_dp_mst_helper.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_edid.h>
#include <drm/drm_vblank.h>
#include <drm/drm_audio_component.h>
-#if defined(CONFIG_DRM_AMD_DC_DCN)
#include "ivsrcid/dcn/irqsrcs_dcn_1_0.h"
#include "dcn/dcn_1_0_offset.h"
@@ -92,7 +92,6 @@
#include "vega10_ip_offset.h"
#include "soc15_common.h"
-#endif
#include "modules/inc/mod_freesync.h"
#include "modules/power/power_helpers.h"
@@ -114,6 +113,10 @@ MODULE_FIRMWARE(FIRMWARE_DIMGREY_CAVEFISH_DMUB);
MODULE_FIRMWARE(FIRMWARE_BEIGE_GOBY_DMUB);
#define FIRMWARE_YELLOW_CARP_DMUB "amdgpu/yellow_carp_dmcub.bin"
MODULE_FIRMWARE(FIRMWARE_YELLOW_CARP_DMUB);
+#define FIRMWARE_DCN_315_DMUB "amdgpu/dcn_3_1_5_dmcub.bin"
+MODULE_FIRMWARE(FIRMWARE_DCN_315_DMUB);
+#define FIRMWARE_DCN316_DMUB "amdgpu/dcn_3_1_6_dmcub.bin"
+MODULE_FIRMWARE(FIRMWARE_DCN316_DMUB);
#define FIRMWARE_RAVEN_DMCU "amdgpu/raven_dmcu.bin"
MODULE_FIRMWARE(FIRMWARE_RAVEN_DMCU);
@@ -599,7 +602,6 @@ static void dm_crtc_high_irq(void *interrupt_params)
spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
}
-#if defined(CONFIG_DRM_AMD_DC_DCN)
#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
/**
* dm_dcn_vertical_interrupt0_high_irq() - Handles OTG Vertical interrupt0 for
@@ -767,7 +769,7 @@ static void dm_dmub_outbox1_low_irq(void *interrupt_params)
do {
dc_stat_get_dmub_notification(adev->dm.dc, &notify);
- if (notify.type > ARRAY_SIZE(dm->dmub_thread_offload)) {
+ if (notify.type >= ARRAY_SIZE(dm->dmub_thread_offload)) {
DRM_ERROR("DM: notify type %d invalid!", notify.type);
continue;
}
@@ -823,7 +825,6 @@ static void dm_dmub_outbox1_low_irq(void *interrupt_params)
if (count > DMUB_TRACE_MAX_READ)
DRM_DEBUG_DRIVER("Warning : count > DMUB_TRACE_MAX_READ");
}
-#endif /* CONFIG_DRM_AMD_DC_DCN */
static int dm_set_clockgating_state(void *handle,
enum amd_clockgating_state state)
@@ -1027,7 +1028,6 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev)
const unsigned char *fw_inst_const, *fw_bss_data;
uint32_t i, fw_inst_const_size, fw_bss_data_size;
bool has_hw_support;
- struct dc *dc = adev->dm.dc;
if (!dmub_srv)
/* DMUB isn't supported on the ASIC. */
@@ -1119,14 +1119,10 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev)
for (i = 0; i < fb_info->num_fb; ++i)
hw_params.fb[i] = &fb_info->fb[i];
- switch (adev->asic_type) {
- case CHIP_YELLOW_CARP:
- if (dc->ctx->asic_id.hw_internal_rev != YELLOW_CARP_A0) {
- hw_params.dpia_supported = true;
-#if defined(CONFIG_DRM_AMD_DC_DCN)
- hw_params.disable_dpia = dc->debug.dpia_debug.bits.disable_dpia;
-#endif
- }
+ switch (adev->ip_versions[DCE_HWIP][0]) {
+ case IP_VERSION(3, 1, 3): /* Only for this asic hw internal rev B0 */
+ hw_params.dpia_supported = true;
+ hw_params.disable_dpia = adev->dm.dc->debug.dpia_debug.bits.disable_dpia;
break;
default:
break;
@@ -1188,7 +1184,6 @@ static void dm_dmub_hw_resume(struct amdgpu_device *adev)
}
}
-#if defined(CONFIG_DRM_AMD_DC_DCN)
static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_addr_space_config *pa_config)
{
uint64_t pt_base;
@@ -1243,8 +1238,7 @@ static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_
pa_config->is_hvm_enabled = 0;
}
-#endif
-#if defined(CONFIG_DRM_AMD_DC_DCN)
+
static void vblank_control_worker(struct work_struct *work)
{
struct vblank_control_work *vblank_work =
@@ -1281,8 +1275,6 @@ static void vblank_control_worker(struct work_struct *work)
kfree(vblank_work);
}
-#endif
-
static void dm_handle_hpd_rx_offload_work(struct work_struct *work)
{
struct hpd_rx_irq_offload_work *offload_work;
@@ -1409,9 +1401,7 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
mutex_init(&adev->dm.dc_lock);
mutex_init(&adev->dm.audio_lock);
-#if defined(CONFIG_DRM_AMD_DC_DCN)
spin_lock_init(&adev->dm.vblank_lock);
-#endif
if(amdgpu_dm_irq_init(adev)) {
DRM_ERROR("amdgpu: failed to initialize DM IRQ support.\n");
@@ -1442,6 +1432,25 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
init_data.dce_environment = DCE_ENV_PRODUCTION_DRV;
+ switch (adev->ip_versions[DCE_HWIP][0]) {
+ case IP_VERSION(2, 1, 0):
+ switch (adev->dm.dmcub_fw_version) {
+ case 0: /* development */
+ case 0x1: /* linux-firmware.git hash 6d9f399 */
+ case 0x01000000: /* linux-firmware.git hash 9a0b0f4 */
+ init_data.flags.disable_dmcu = false;
+ break;
+ default:
+ init_data.flags.disable_dmcu = true;
+ }
+ break;
+ case IP_VERSION(2, 0, 3):
+ init_data.flags.disable_dmcu = true;
+ break;
+ default:
+ break;
+ }
+
switch (adev->asic_type) {
case CHIP_CARRIZO:
case CHIP_STONEY:
@@ -1449,34 +1458,30 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
break;
default:
switch (adev->ip_versions[DCE_HWIP][0]) {
- case IP_VERSION(2, 1, 0):
- init_data.flags.gpu_vm_support = true;
- switch (adev->dm.dmcub_fw_version) {
- case 0: /* development */
- case 0x1: /* linux-firmware.git hash 6d9f399 */
- case 0x01000000: /* linux-firmware.git hash 9a0b0f4 */
- init_data.flags.disable_dmcu = false;
- break;
- default:
- init_data.flags.disable_dmcu = true;
- }
- break;
case IP_VERSION(1, 0, 0):
case IP_VERSION(1, 0, 1):
+ /* enable S/G on PCO and RV2 */
+ if ((adev->apu_flags & AMD_APU_IS_RAVEN2) ||
+ (adev->apu_flags & AMD_APU_IS_PICASSO))
+ init_data.flags.gpu_vm_support = true;
+ break;
+ case IP_VERSION(2, 1, 0):
case IP_VERSION(3, 0, 1):
case IP_VERSION(3, 1, 2):
case IP_VERSION(3, 1, 3):
+ case IP_VERSION(3, 1, 5):
+ case IP_VERSION(3, 1, 6):
init_data.flags.gpu_vm_support = true;
break;
- case IP_VERSION(2, 0, 3):
- init_data.flags.disable_dmcu = true;
- break;
default:
break;
}
break;
}
+ if (init_data.flags.gpu_vm_support)
+ adev->mode_info.gpu_vm_support = true;
+
if (amdgpu_dc_feature_mask & DC_FBC_MASK)
init_data.flags.fbc_support = true;
@@ -1489,17 +1494,15 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
if (amdgpu_dc_feature_mask & DC_EDP_NO_POWER_SEQUENCING)
init_data.flags.edp_no_power_sequencing = true;
-#ifdef CONFIG_DRM_AMD_DC_DCN
if (amdgpu_dc_feature_mask & DC_DISABLE_LTTPR_DP1_4A)
init_data.flags.allow_lttpr_non_transparent_mode.bits.DP1_4A = true;
if (amdgpu_dc_feature_mask & DC_DISABLE_LTTPR_DP2_0)
init_data.flags.allow_lttpr_non_transparent_mode.bits.DP2_0 = true;
-#endif
- init_data.flags.power_down_display_on_boot = true;
+ init_data.flags.seamless_boot_edp_requested = false;
if (check_seamless_boot_capability(adev)) {
- init_data.flags.power_down_display_on_boot = false;
+ init_data.flags.seamless_boot_edp_requested = true;
init_data.flags.allow_seamless_boot_optimization = true;
DRM_INFO("Seamless boot condition check passed\n");
}
@@ -1550,7 +1553,6 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
goto error;
}
-#if defined(CONFIG_DRM_AMD_DC_DCN)
if ((adev->flags & AMD_IS_APU) && (adev->asic_type >= CHIP_CARRIZO)) {
struct dc_phy_addr_space_config pa_config;
@@ -1559,7 +1561,6 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
// Call the DC init_memory func
dc_setup_system_context(adev->dm.dc, &pa_config);
}
-#endif
adev->dm.freesync_module = mod_freesync_create(adev->dm.dc);
if (!adev->dm.freesync_module) {
@@ -1571,14 +1572,12 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
amdgpu_dm_init_color_mod();
-#if defined(CONFIG_DRM_AMD_DC_DCN)
if (adev->dm.dc->caps.max_links > 0) {
adev->dm.vblank_control_workqueue =
create_singlethread_workqueue("dm_vblank_control_workqueue");
if (!adev->dm.vblank_control_workqueue)
DRM_ERROR("amdgpu: failed to initialize vblank_workqueue.\n");
}
-#endif
#ifdef CONFIG_DRM_AMD_DC_HDCP
if (adev->dm.dc->caps.max_links > 0 && adev->family >= AMDGPU_FAMILY_RV) {
@@ -1610,7 +1609,6 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
}
amdgpu_dm_outbox_init(adev);
-#if defined(CONFIG_DRM_AMD_DC_DCN)
if (!register_dmub_notify_callback(adev, DMUB_NOTIFICATION_AUX_REPLY,
dmub_aux_setconfig_callback, false)) {
DRM_ERROR("amdgpu: fail to register dmub aux callback");
@@ -1624,7 +1622,6 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
DRM_ERROR("amdgpu: fail to register dmub hpd callback");
goto error;
}
-#endif /* CONFIG_DRM_AMD_DC_DCN */
}
if (amdgpu_dm_initialize_drm_device(adev)) {
@@ -1671,12 +1668,10 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev)
{
int i;
-#if defined(CONFIG_DRM_AMD_DC_DCN)
if (adev->dm.vblank_control_workqueue) {
destroy_workqueue(adev->dm.vblank_control_workqueue);
adev->dm.vblank_control_workqueue = NULL;
}
-#endif
for (i = 0; i < adev->dm.display_indexes_num; i++) {
drm_encoder_cleanup(&adev->dm.mst_encoders[i].base);
@@ -1804,6 +1799,8 @@ static int load_dmcu_fw(struct amdgpu_device *adev)
case IP_VERSION(3, 0, 1):
case IP_VERSION(3, 1, 2):
case IP_VERSION(3, 1, 3):
+ case IP_VERSION(3, 1, 5):
+ case IP_VERSION(3, 1, 6):
return 0;
default:
break;
@@ -1919,7 +1916,14 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev)
dmub_asic = (adev->external_rev_id == YELLOW_CARP_B0) ? DMUB_ASIC_DCN31B : DMUB_ASIC_DCN31;
fw_name_dmub = FIRMWARE_YELLOW_CARP_DMUB;
break;
-
+ case IP_VERSION(3, 1, 5):
+ dmub_asic = DMUB_ASIC_DCN315;
+ fw_name_dmub = FIRMWARE_DCN_315_DMUB;
+ break;
+ case IP_VERSION(3, 1, 6):
+ dmub_asic = DMUB_ASIC_DCN316;
+ fw_name_dmub = FIRMWARE_DCN316_DMUB;
+ break;
default:
/* ASIC doesn't support DMUB. */
return 0;
@@ -2179,12 +2183,8 @@ static void s3_handle_mst(struct drm_device *dev, bool suspend)
static int amdgpu_dm_smu_write_watermarks_table(struct amdgpu_device *adev)
{
- struct smu_context *smu = &adev->smu;
int ret = 0;
- if (!is_support_sw_smu(adev))
- return 0;
-
/* This interface is for dGPU Navi1x.Linux dc-pplib interface depends
* on window driver dc implementation.
* For Navi1x, clock settings of dcn watermarks are fixed. the settings
@@ -2223,7 +2223,7 @@ static int amdgpu_dm_smu_write_watermarks_table(struct amdgpu_device *adev)
return 0;
}
- ret = smu_write_watermarks_table(smu);
+ ret = amdgpu_dpm_write_watermarks_table(adev);
if (ret) {
DRM_ERROR("Failed to update WMTABLE!\n");
return ret;
@@ -2382,9 +2382,7 @@ static int dm_suspend(void *handle)
if (amdgpu_in_reset(adev)) {
mutex_lock(&dm->dc_lock);
-#if defined(CONFIG_DRM_AMD_DC_DCN)
dc_allow_idle_optimizations(adev->dm.dc, false);
-#endif
dm->cached_dc_state = dc_copy_state(dm->dc->current_state);
@@ -2413,7 +2411,7 @@ static int dm_suspend(void *handle)
return 0;
}
-static struct amdgpu_dm_connector *
+struct amdgpu_dm_connector *
amdgpu_dm_find_first_crtc_matching_connector(struct drm_atomic_state *state,
struct drm_crtc *crtc)
{
@@ -2613,10 +2611,13 @@ static int dm_resume(void *handle)
* before the 0 streams commit.
*
* DC expects that link encoder assignments are *not* valid
- * when committing a state, so as a workaround it needs to be
- * cleared here.
+ * when committing a state, so as a workaround we can copy
+ * off of the current state.
+ *
+ * We lose the previous assignments, but we had already
+ * commit 0 streams anyway.
*/
- link_enc_cfg_init(dm->dc, dc_state);
+ link_enc_cfg_copy(adev->dm.dc->current_state, dc_state);
if (dc_enable_dmub_notifications(adev->dm.dc))
amdgpu_dm_outbox_init(adev);
@@ -2690,7 +2691,8 @@ static int dm_resume(void *handle)
* this is the case when traversing through already created
* MST connectors, should be skipped
*/
- if (aconnector->mst_port)
+ if (aconnector->dc_link &&
+ aconnector->dc_link->type == dc_connection_mst_branch)
continue;
mutex_lock(&aconnector->hpd_lock);
@@ -2810,7 +2812,7 @@ static struct drm_mode_config_helper_funcs amdgpu_dm_mode_config_helperfuncs = {
static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
{
- u32 max_cll, min_cll, max, min, q, r;
+ u32 max_avg, min_cll, max, min, q, r;
struct amdgpu_dm_backlight_caps *caps;
struct amdgpu_display_manager *dm;
struct drm_connector *conn_base;
@@ -2840,7 +2842,7 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
caps = &dm->backlight_caps[i];
caps->ext_caps = &aconnector->dc_link->dpcd_sink_ext_caps;
caps->aux_support = false;
- max_cll = conn_base->hdr_sink_metadata.hdmi_type1.max_cll;
+ max_avg = conn_base->hdr_sink_metadata.hdmi_type1.max_fall;
min_cll = conn_base->hdr_sink_metadata.hdmi_type1.min_cll;
if (caps->ext_caps->bits.oled == 1 /*||
@@ -2868,8 +2870,8 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
* The results of the above expressions can be verified at
* pre_computed_values.
*/
- q = max_cll >> 5;
- r = max_cll % 32;
+ q = max_avg >> 5;
+ r = max_avg % 32;
max = (1 << q) * pre_computed_values[r];
// min luminance: maxLum * (CV/255)^2 / 100
@@ -3533,7 +3535,6 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev)
return 0;
}
-#if defined(CONFIG_DRM_AMD_DC_DCN)
/* Register IRQ sources and initialize IRQ callbacks */
static int dcn10_register_irq_handlers(struct amdgpu_device *adev)
{
@@ -3722,7 +3723,6 @@ static int register_outbox_irq_handlers(struct amdgpu_device *adev)
return 0;
}
-#endif
/*
* Acquires the lock for the atomic state object and returns
@@ -3730,8 +3730,8 @@ static int register_outbox_irq_handlers(struct amdgpu_device *adev)
*
* This should only be called during atomic check.
*/
-static int dm_atomic_get_state(struct drm_atomic_state *state,
- struct dm_atomic_state **dm_state)
+int dm_atomic_get_state(struct drm_atomic_state *state,
+ struct dm_atomic_state **dm_state)
{
struct drm_device *dev = state->dev;
struct amdgpu_device *adev = drm_to_adev(dev);
@@ -3948,7 +3948,7 @@ static u32 convert_brightness_to_user(const struct amdgpu_dm_backlight_caps *cap
max - min);
}
-static int amdgpu_dm_backlight_set_level(struct amdgpu_display_manager *dm,
+static void amdgpu_dm_backlight_set_level(struct amdgpu_display_manager *dm,
int bl_idx,
u32 user_brightness)
{
@@ -3979,7 +3979,8 @@ static int amdgpu_dm_backlight_set_level(struct amdgpu_display_manager *dm,
DRM_DEBUG("DM: Failed to update backlight on eDP[%d]\n", bl_idx);
}
- return rc ? 0 : 1;
+ if (rc)
+ dm->actual_brightness[bl_idx] = user_brightness;
}
static int amdgpu_dm_backlight_update_status(struct backlight_device *bd)
@@ -4225,12 +4226,13 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
goto fail;
}
-#if defined(CONFIG_DRM_AMD_DC_DCN)
/* Use Outbox interrupt */
switch (adev->ip_versions[DCE_HWIP][0]) {
case IP_VERSION(3, 0, 0):
case IP_VERSION(3, 1, 2):
case IP_VERSION(3, 1, 3):
+ case IP_VERSION(3, 1, 5):
+ case IP_VERSION(3, 1, 6):
case IP_VERSION(2, 1, 0):
if (register_outbox_irq_handlers(dm->adev)) {
DRM_ERROR("DM: Failed to initialize IRQ\n");
@@ -4247,6 +4249,8 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
switch (adev->ip_versions[DCE_HWIP][0]) {
case IP_VERSION(3, 1, 2):
case IP_VERSION(3, 1, 3):
+ case IP_VERSION(3, 1, 5):
+ case IP_VERSION(3, 1, 6):
psr_feature_enabled = true;
break;
default:
@@ -4254,10 +4258,6 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
break;
}
}
-#endif
-
- /* Disable vblank IRQs aggressively for power-saving. */
- adev_to_drm(adev)->vblank_disable_immediate = true;
/* loops over all connectors on the board */
for (i = 0; i < link_cnt; i++) {
@@ -4350,7 +4350,6 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
}
break;
default:
-#if defined(CONFIG_DRM_AMD_DC_DCN)
switch (adev->ip_versions[DCE_HWIP][0]) {
case IP_VERSION(1, 0, 0):
case IP_VERSION(1, 0, 1):
@@ -4364,6 +4363,8 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
case IP_VERSION(3, 0, 1):
case IP_VERSION(3, 1, 2):
case IP_VERSION(3, 1, 3):
+ case IP_VERSION(3, 1, 5):
+ case IP_VERSION(3, 1, 6):
if (dcn10_register_irq_handlers(dm->adev)) {
DRM_ERROR("DM: Failed to initialize IRQ\n");
goto fail;
@@ -4374,7 +4375,6 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
adev->ip_versions[DCE_HWIP][0]);
goto fail;
}
-#endif
break;
}
@@ -4523,7 +4523,7 @@ static int dm_early_init(void *handle)
adev->mode_info.num_dig = 6;
break;
default:
-#if defined(CONFIG_DRM_AMD_DC_DCN)
+
switch (adev->ip_versions[DCE_HWIP][0]) {
case IP_VERSION(2, 0, 2):
case IP_VERSION(3, 0, 0):
@@ -4549,6 +4549,8 @@ static int dm_early_init(void *handle)
case IP_VERSION(2, 1, 0):
case IP_VERSION(3, 1, 2):
case IP_VERSION(3, 1, 3):
+ case IP_VERSION(3, 1, 5):
+ case IP_VERSION(3, 1, 6):
adev->mode_info.num_crtc = 4;
adev->mode_info.num_hpd = 4;
adev->mode_info.num_dig = 4;
@@ -4558,7 +4560,6 @@ static int dm_early_init(void *handle)
adev->ip_versions[DCE_HWIP][0]);
return -EINVAL;
}
-#endif
break;
}
@@ -5221,6 +5222,8 @@ get_plane_modifiers(const struct amdgpu_device *adev, unsigned int plane_type, u
case AMDGPU_FAMILY_NV:
case AMDGPU_FAMILY_VGH:
case AMDGPU_FAMILY_YC:
+ case AMDGPU_FAMILY_GC_10_3_6:
+ case AMDGPU_FAMILY_GC_10_3_7:
if (adev->ip_versions[GC_HWIP][0] >= IP_VERSION(10, 3, 0))
add_gfx10_3_modifiers(adev, mods, &size, &capacity);
else
@@ -5375,17 +5378,19 @@ fill_plane_buffer_attributes(struct amdgpu_device *adev,
static void
fill_blending_from_plane_state(const struct drm_plane_state *plane_state,
- bool *per_pixel_alpha, bool *global_alpha,
- int *global_alpha_value)
+ bool *per_pixel_alpha, bool *pre_multiplied_alpha,
+ bool *global_alpha, int *global_alpha_value)
{
*per_pixel_alpha = false;
+ *pre_multiplied_alpha = true;
*global_alpha = false;
*global_alpha_value = 0xff;
if (plane_state->plane->type != DRM_PLANE_TYPE_OVERLAY)
return;
- if (plane_state->pixel_blend_mode == DRM_MODE_BLEND_PREMULTI) {
+ if (plane_state->pixel_blend_mode == DRM_MODE_BLEND_PREMULTI ||
+ plane_state->pixel_blend_mode == DRM_MODE_BLEND_COVERAGE) {
static const uint32_t alpha_formats[] = {
DRM_FORMAT_ARGB8888,
DRM_FORMAT_RGBA8888,
@@ -5400,6 +5405,9 @@ fill_blending_from_plane_state(const struct drm_plane_state *plane_state,
break;
}
}
+
+ if (per_pixel_alpha && plane_state->pixel_blend_mode == DRM_MODE_BLEND_COVERAGE)
+ *pre_multiplied_alpha = false;
}
if (plane_state->alpha < 0xffff) {
@@ -5562,7 +5570,7 @@ fill_dc_plane_info_and_addr(struct amdgpu_device *adev,
return ret;
fill_blending_from_plane_state(
- plane_state, &plane_info->per_pixel_alpha,
+ plane_state, &plane_info->per_pixel_alpha, &plane_info->pre_multiplied_alpha,
&plane_info->global_alpha, &plane_info->global_alpha_value);
return 0;
@@ -5609,6 +5617,7 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev,
dc_plane_state->tiling_info = plane_info.tiling_info;
dc_plane_state->visible = plane_info.visible;
dc_plane_state->per_pixel_alpha = plane_info.per_pixel_alpha;
+ dc_plane_state->pre_multiplied_alpha = plane_info.pre_multiplied_alpha;
dc_plane_state->global_alpha = plane_info.global_alpha;
dc_plane_state->global_alpha_value = plane_info.global_alpha_value;
dc_plane_state->dcc = plane_info.dcc;
@@ -5857,7 +5866,7 @@ static void fill_stream_properties_from_drm_display_mode(
else if (drm_mode_is_420_also(info, mode_in)
&& aconnector->force_yuv420_output)
timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420;
- else if ((connector->display_info.color_formats & DRM_COLOR_FORMAT_YCRCB444)
+ else if ((connector->display_info.color_formats & DRM_COLOR_FORMAT_YCBCR444)
&& stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR444;
else
@@ -6187,7 +6196,7 @@ static void apply_dsc_policy_for_stream(struct amdgpu_dm_connector *aconnector,
if (stream->link && stream->link->local_sink)
max_dsc_target_bpp_limit_override =
stream->link->local_sink->edid_caps.panel_patch.max_dsc_target_bpp_limit;
-
+
/* Set DSC policy according to dsc_clock_en */
dc_dsc_policy_set_enable_dsc_when_not_needed(
aconnector->dsc_settings.dsc_force_enable == DSC_CLK_FORCE_ENABLE);
@@ -6326,7 +6335,7 @@ get_highest_refresh_rate_mode(struct amdgpu_dm_connector *aconnector,
}
}
- aconnector->freesync_vid_base = *m_pref;
+ drm_mode_copy(&aconnector->freesync_vid_base, m_pref);
return m_pref;
}
@@ -6436,12 +6445,11 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
*/
DRM_DEBUG_DRIVER("No preferred mode found\n");
} else {
- recalculate_timing = amdgpu_freesync_vid_mode &&
- is_freesync_video_mode(&mode, aconnector);
+ recalculate_timing = is_freesync_video_mode(&mode, aconnector);
if (recalculate_timing) {
freesync_mode = get_highest_refresh_rate_mode(aconnector, false);
- saved_mode = mode;
- mode = *freesync_mode;
+ drm_mode_copy(&saved_mode, &mode);
+ drm_mode_copy(&mode, freesync_mode);
} else {
decide_crtc_timing_for_drm_display_mode(
&mode, preferred_mode, scale);
@@ -6500,7 +6508,7 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
if (stream->link->dpcd_caps.dprx_feature.bits.VSC_SDP_COLORIMETRY_SUPPORTED)
stream->use_vsc_sdp_for_colorimetry = true;
}
- mod_build_vsc_infopacket(stream, &stream->vsc_infopacket);
+ mod_build_vsc_infopacket(stream, &stream->vsc_infopacket, stream->output_color_space);
aconnector->psr_skip_count = AMDGPU_DM_PSR_ENTRY_DELAY;
}
@@ -6611,10 +6619,8 @@ static inline int dm_set_vblank(struct drm_crtc *crtc, bool enable)
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);
-#if defined(CONFIG_DRM_AMD_DC_DCN)
struct amdgpu_display_manager *dm = &adev->dm;
struct vblank_control_work *work;
-#endif
int rc = 0;
if (enable) {
@@ -6637,7 +6643,6 @@ static inline int dm_set_vblank(struct drm_crtc *crtc, bool enable)
if (amdgpu_in_reset(adev))
return 0;
-#if defined(CONFIG_DRM_AMD_DC_DCN)
if (dm->vblank_control_workqueue) {
work = kzalloc(sizeof(*work), GFP_ATOMIC);
if (!work)
@@ -6655,7 +6660,6 @@ static inline int dm_set_vblank(struct drm_crtc *crtc, bool enable)
queue_work(dm->vblank_control_workqueue, &work->work);
}
-#endif
return 0;
}
@@ -7011,7 +7015,7 @@ static void handle_edid_mgmt(struct amdgpu_dm_connector *aconnector)
create_eml_sink(aconnector);
}
-static struct dc_stream_state *
+struct dc_stream_state *
create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector,
const struct drm_display_mode *drm_mode,
const struct dm_connector_state *dm_state,
@@ -7548,9 +7552,6 @@ static int dm_plane_helper_prepare_fb(struct drm_plane *plane,
struct amdgpu_device *adev;
struct amdgpu_bo *rbo;
struct dm_plane_state *dm_plane_state_new, *dm_plane_state_old;
- struct list_head list;
- struct ttm_validate_buffer tv;
- struct ww_acquire_ctx ticket;
uint32_t domain;
int r;
@@ -7563,18 +7564,19 @@ static int dm_plane_helper_prepare_fb(struct drm_plane *plane,
obj = new_state->fb->obj[0];
rbo = gem_to_amdgpu_bo(obj);
adev = amdgpu_ttm_adev(rbo->tbo.bdev);
- INIT_LIST_HEAD(&list);
-
- tv.bo = &rbo->tbo;
- tv.num_shared = 1;
- list_add(&tv.head, &list);
- r = ttm_eu_reserve_buffers(&ticket, &list, false, NULL);
+ r = amdgpu_bo_reserve(rbo, true);
if (r) {
dev_err(adev->dev, "fail to reserve bo (%d)\n", r);
return r;
}
+ r = dma_resv_reserve_fences(rbo->tbo.base.resv, 1);
+ if (r) {
+ dev_err(adev->dev, "reserving fence slot failed (%d)\n", r);
+ goto error_unlock;
+ }
+
if (plane->type != DRM_PLANE_TYPE_CURSOR)
domain = amdgpu_display_supported_domains(adev, rbo->flags);
else
@@ -7584,19 +7586,16 @@ static int dm_plane_helper_prepare_fb(struct drm_plane *plane,
if (unlikely(r != 0)) {
if (r != -ERESTARTSYS)
DRM_ERROR("Failed to pin framebuffer with error %d\n", r);
- ttm_eu_backoff_reservation(&ticket, &list);
- return r;
+ goto error_unlock;
}
r = amdgpu_ttm_alloc_gart(&rbo->tbo);
if (unlikely(r != 0)) {
- amdgpu_bo_unpin(rbo);
- ttm_eu_backoff_reservation(&ticket, &list);
DRM_ERROR("%p bind failed\n", rbo);
- return r;
+ goto error_unpin;
}
- ttm_eu_backoff_reservation(&ticket, &list);
+ amdgpu_bo_unreserve(rbo);
afb->address = amdgpu_bo_gpu_offset(rbo);
@@ -7628,6 +7627,13 @@ static int dm_plane_helper_prepare_fb(struct drm_plane *plane,
}
return 0;
+
+error_unpin:
+ amdgpu_bo_unpin(rbo);
+
+error_unlock:
+ amdgpu_bo_unreserve(rbo);
+ return r;
}
static void dm_plane_helper_cleanup_fb(struct drm_plane *plane,
@@ -7895,6 +7901,9 @@ static int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
if (res)
return res;
+ if (modifiers == NULL)
+ adev_to_drm(dm->adev)->mode_config.fb_modifiers_not_supported = true;
+
res = drm_universal_plane_init(adev_to_drm(dm->adev), plane, possible_crtcs,
&dm_plane_funcs, formats, num_formats,
modifiers, plane->type, NULL);
@@ -7905,7 +7914,8 @@ static int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
if (plane->type == DRM_PLANE_TYPE_OVERLAY &&
plane_cap && plane_cap->per_pixel_alpha) {
unsigned int blend_caps = BIT(DRM_MODE_BLEND_PIXEL_NONE) |
- BIT(DRM_MODE_BLEND_PREMULTI);
+ BIT(DRM_MODE_BLEND_PREMULTI) |
+ BIT(DRM_MODE_BLEND_COVERAGE);
drm_plane_create_alpha_property(plane);
drm_plane_create_blend_mode_property(plane, blend_caps);
@@ -8144,6 +8154,9 @@ static void amdgpu_dm_connector_add_common_modes(struct drm_encoder *encoder,
mode = amdgpu_dm_create_common_mode(encoder,
common_modes[i].name, common_modes[i].w,
common_modes[i].h);
+ if (!mode)
+ continue;
+
drm_mode_probed_add(connector, mode);
amdgpu_dm_connector->num_modes++;
}
@@ -8305,7 +8318,7 @@ static void amdgpu_dm_connector_add_freesync_modes(struct drm_connector *connect
struct amdgpu_dm_connector *amdgpu_dm_connector =
to_amdgpu_dm_connector(connector);
- if (!(amdgpu_freesync_vid_mode && edid))
+ if (!edid)
return;
if (amdgpu_dm_connector->max_vfreq - amdgpu_dm_connector->min_vfreq > 10)
@@ -8372,7 +8385,7 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
break;
case DRM_MODE_CONNECTOR_DisplayPort:
aconnector->base.polled = DRM_CONNECTOR_POLL_HPD;
- link->link_enc = dp_get_link_enc(link);
+ link->link_enc = link_enc_cfg_get_link_enc(link);
ASSERT(link->link_enc);
if (link->link_enc)
aconnector->base.ycbcr_420_allowed =
@@ -9197,7 +9210,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
* deadlock during GPU reset when this fence will not signal
* but we hold reservation lock for the BO.
*/
- r = dma_resv_wait_timeout(abo->tbo.base.resv, true, false,
+ r = dma_resv_wait_timeout(abo->tbo.base.resv,
+ DMA_RESV_USAGE_WRITE, false,
msecs_to_jiffies(5000));
if (unlikely(r <= 0))
DRM_ERROR("Waiting for fences timed out!");
@@ -9209,7 +9223,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
&bundle->flip_addrs[planes_count].address,
afb->tmz_surface, false);
- DRM_DEBUG_ATOMIC("plane: id=%d dcc_en=%d\n",
+ drm_dbg_state(state->dev, "plane: id=%d dcc_en=%d\n",
new_plane_state->plane->index,
bundle->plane_infos[planes_count].dcc.enable);
@@ -9243,7 +9257,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
dc_plane,
bundle->flip_addrs[planes_count].flip_timestamp_in_us);
- DRM_DEBUG_ATOMIC("%s Flipping to hi: 0x%x, low: 0x%x\n",
+ drm_dbg_state(state->dev, "%s Flipping to hi: 0x%x, low: 0x%x\n",
__func__,
bundle->flip_addrs[planes_count].address.grph.addr.high_part,
bundle->flip_addrs[planes_count].address.grph.addr.low_part);
@@ -9324,14 +9338,12 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
/* Update the planes if changed or disable if we don't have any. */
if ((planes_count || acrtc_state->active_planes == 0) &&
acrtc_state->stream) {
-#if defined(CONFIG_DRM_AMD_DC_DCN)
/*
* If PSR or idle optimizations are enabled then flush out
* any pending work before hardware programming.
*/
if (dm->vblank_control_workqueue)
flush_workqueue(dm->vblank_control_workqueue);
-#endif
bundle->stream_update.stream = acrtc_state->stream;
if (new_pcrtc_state->mode_changed) {
@@ -9585,7 +9597,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
- DRM_DEBUG_ATOMIC(
+ drm_dbg_state(state->dev,
"amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, "
"planes_changed:%d, mode_changed:%d,active_changed:%d,"
"connectors_changed:%d\n",
@@ -9664,21 +9676,19 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
if (dc_state) {
/* if there mode set or reset, disable eDP PSR */
if (mode_set_reset_required) {
-#if defined(CONFIG_DRM_AMD_DC_DCN)
if (dm->vblank_control_workqueue)
flush_workqueue(dm->vblank_control_workqueue);
-#endif
+
amdgpu_dm_psr_disable_all(dm);
}
dm_enable_per_frame_crtc_master_sync(dc_state);
mutex_lock(&dm->dc_lock);
WARN_ON(!dc_commit_state(dm->dc, dc_state));
-#if defined(CONFIG_DRM_AMD_DC_DCN)
- /* Allow idle optimization when vblank count is 0 for display off */
- if (dm->active_vblank_irq_count == 0)
- dc_allow_idle_optimizations(dm->dc,true);
-#endif
+
+ /* Allow idle optimization when vblank count is 0 for display off */
+ if (dm->active_vblank_irq_count == 0)
+ dc_allow_idle_optimizations(dm->dc, true);
mutex_unlock(&dm->dc_lock);
}
@@ -9908,7 +9918,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
/* restore the backlight level */
for (i = 0; i < dm->num_of_edps; i++) {
if (dm->backlight_dev[i] &&
- (amdgpu_dm_backlight_get_level(dm, i) != dm->brightness[i]))
+ (dm->actual_brightness[i] != dm->brightness[i]))
amdgpu_dm_backlight_set_level(dm, i, dm->brightness[i]);
}
#endif
@@ -10142,27 +10152,27 @@ static bool
is_timing_unchanged_for_freesync(struct drm_crtc_state *old_crtc_state,
struct drm_crtc_state *new_crtc_state)
{
- struct drm_display_mode old_mode, new_mode;
+ const struct drm_display_mode *old_mode, *new_mode;
if (!old_crtc_state || !new_crtc_state)
return false;
- old_mode = old_crtc_state->mode;
- new_mode = new_crtc_state->mode;
-
- if (old_mode.clock == new_mode.clock &&
- old_mode.hdisplay == new_mode.hdisplay &&
- old_mode.vdisplay == new_mode.vdisplay &&
- old_mode.htotal == new_mode.htotal &&
- old_mode.vtotal != new_mode.vtotal &&
- old_mode.hsync_start == new_mode.hsync_start &&
- old_mode.vsync_start != new_mode.vsync_start &&
- old_mode.hsync_end == new_mode.hsync_end &&
- old_mode.vsync_end != new_mode.vsync_end &&
- old_mode.hskew == new_mode.hskew &&
- old_mode.vscan == new_mode.vscan &&
- (old_mode.vsync_end - old_mode.vsync_start) ==
- (new_mode.vsync_end - new_mode.vsync_start))
+ old_mode = &old_crtc_state->mode;
+ new_mode = &new_crtc_state->mode;
+
+ if (old_mode->clock == new_mode->clock &&
+ old_mode->hdisplay == new_mode->hdisplay &&
+ old_mode->vdisplay == new_mode->vdisplay &&
+ old_mode->htotal == new_mode->htotal &&
+ old_mode->vtotal != new_mode->vtotal &&
+ old_mode->hsync_start == new_mode->hsync_start &&
+ old_mode->vsync_start != new_mode->vsync_start &&
+ old_mode->hsync_end == new_mode->hsync_end &&
+ old_mode->vsync_end != new_mode->vsync_end &&
+ old_mode->hskew == new_mode->hskew &&
+ old_mode->vscan == new_mode->vscan &&
+ (old_mode->vsync_end - old_mode->vsync_start) ==
+ (new_mode->vsync_end - new_mode->vsync_start))
return true;
return false;
@@ -10183,12 +10193,12 @@ static void set_freesync_fixed_config(struct dm_crtc_state *dm_new_crtc_state) {
}
static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
- struct drm_atomic_state *state,
- struct drm_crtc *crtc,
- struct drm_crtc_state *old_crtc_state,
- struct drm_crtc_state *new_crtc_state,
- bool enable,
- bool *lock_and_validation_needed)
+ struct drm_atomic_state *state,
+ struct drm_crtc *crtc,
+ struct drm_crtc_state *old_crtc_state,
+ struct drm_crtc_state *new_crtc_state,
+ bool enable,
+ bool *lock_and_validation_needed)
{
struct dm_atomic_state *dm_state = NULL;
struct dm_crtc_state *dm_old_crtc_state, *dm_new_crtc_state;
@@ -10272,8 +10282,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
* TODO: Refactor this function to allow this check to work
* in all conditions.
*/
- if (amdgpu_freesync_vid_mode &&
- dm_new_crtc_state->stream &&
+ if (dm_new_crtc_state->stream &&
is_timing_unchanged_for_freesync(new_crtc_state, old_crtc_state))
goto skip_modeset;
@@ -10290,7 +10299,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
if (!drm_atomic_crtc_needs_modeset(new_crtc_state))
goto skip_modeset;
- DRM_DEBUG_ATOMIC(
+ drm_dbg_state(state->dev,
"amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, "
"planes_changed:%d, mode_changed:%d,active_changed:%d,"
"connectors_changed:%d\n",
@@ -10308,7 +10317,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
if (!dm_old_crtc_state->stream)
goto skip_modeset;
- if (amdgpu_freesync_vid_mode && dm_new_crtc_state->stream &&
+ if (dm_new_crtc_state->stream &&
is_timing_unchanged_for_freesync(new_crtc_state,
old_crtc_state)) {
new_crtc_state->mode_changed = false;
@@ -10320,7 +10329,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
set_freesync_fixed_config(dm_new_crtc_state);
goto skip_modeset;
- } else if (amdgpu_freesync_vid_mode && aconnector &&
+ } else if (aconnector &&
is_freesync_video_mode(&new_crtc_state->mode,
aconnector)) {
struct drm_display_mode *high_mode;
@@ -10858,10 +10867,13 @@ static int dm_check_crtc_cursor(struct drm_atomic_state *state,
static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm_crtc *crtc)
{
struct drm_connector *connector;
- struct drm_connector_state *conn_state;
+ struct drm_connector_state *conn_state, *old_conn_state;
struct amdgpu_dm_connector *aconnector = NULL;
int i;
- for_each_new_connector_in_state(state, connector, conn_state, i) {
+ for_each_oldnew_connector_in_state(state, connector, old_conn_state, conn_state, i) {
+ if (!conn_state->crtc)
+ conn_state = old_conn_state;
+
if (conn_state->crtc != crtc)
continue;
@@ -10968,6 +10980,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
}
}
}
+ pre_validate_dsc(state, &dm_state, vars);
}
#endif
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_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 b9a69b0cef23..aa34c0068f41 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -26,10 +26,10 @@
#ifndef __AMDGPU_DM_H__
#define __AMDGPU_DM_H__
+#include <drm/display/drm_dp_mst_helper.h>
#include <drm/drm_atomic.h>
#include <drm/drm_connector.h>
#include <drm/drm_crtc.h>
-#include <drm/drm_dp_mst_helper.h>
#include <drm/drm_plane.h>
/*
@@ -358,14 +358,12 @@ struct amdgpu_display_manager {
*/
struct mutex audio_lock;
-#if defined(CONFIG_DRM_AMD_DC_DCN)
/**
* @vblank_lock:
*
* Guards access to deferred vblank work state.
*/
spinlock_t vblank_lock;
-#endif
/**
* @audio_component:
@@ -469,14 +467,12 @@ struct amdgpu_display_manager {
struct hdcp_workqueue *hdcp_workqueue;
#endif
-#if defined(CONFIG_DRM_AMD_DC_DCN)
/**
* @vblank_control_workqueue:
*
* Deferred work for vblank control events.
*/
struct workqueue_struct *vblank_control_workqueue;
-#endif
struct drm_atomic_state *cached_state;
struct dc_state *cached_dc_state;
@@ -493,14 +489,12 @@ struct amdgpu_display_manager {
*/
const struct gpu_info_soc_bounding_box_v1_0 *soc_bounding_box;
-#if defined(CONFIG_DRM_AMD_DC_DCN)
/**
* @active_vblank_irq_count:
*
* number of currently active vblank irqs
*/
uint32_t active_vblank_irq_count;
-#endif
#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
/**
@@ -540,6 +534,12 @@ struct amdgpu_display_manager {
* cached backlight values.
*/
u32 brightness[AMDGPU_DM_MAX_NUM_EDP];
+ /**
+ * @actual_brightness:
+ *
+ * last successfully applied backlight values.
+ */
+ u32 actual_brightness[AMDGPU_DM_MAX_NUM_EDP];
};
enum dsc_clock_force_state {
@@ -604,6 +604,7 @@ struct amdgpu_dm_connector {
#endif
bool force_yuv420_output;
struct dsc_preferred_settings dsc_settings;
+ union dp_downstream_port_present mst_downstream_port_present;
/* Cached display modes */
struct drm_display_mode freesync_vid_base;
@@ -736,4 +737,16 @@ int amdgpu_dm_process_dmub_aux_transfer_sync(bool is_cmd_aux,
bool check_seamless_boot_capability(struct amdgpu_device *adev);
+struct dc_stream_state *
+ create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector,
+ const struct drm_display_mode *drm_mode,
+ const struct dm_connector_state *dm_state,
+ const struct dc_stream_state *old_stream);
+
+int dm_atomic_get_state(struct drm_atomic_state *state,
+ struct dm_atomic_state **dm_state);
+
+struct amdgpu_dm_connector *
+amdgpu_dm_find_first_crtc_matching_connector(struct drm_atomic_state *state,
+ struct drm_crtc *crtc);
#endif /* __AMDGPU_DM_H__ */
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 26719efa5396..c7a592d68feb 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
@@ -23,6 +23,7 @@
*
*/
+#include <linux/string_helpers.h>
#include <linux/uaccess.h>
#include "dc.h"
@@ -49,11 +50,6 @@ struct dmub_debugfs_trace_entry {
uint32_t param1;
};
-static inline const char *yesno(bool v)
-{
- return v ? "yes" : "no";
-}
-
/* parse_write_buffer_into_params - Helper function to parse debugfs write buffer into an array
*
* Function takes in attributes passed to debugfs write entry
@@ -227,8 +223,10 @@ static ssize_t dp_link_settings_read(struct file *f, char __user *buf,
break;
r = put_user(*(rd_buf + result), buf);
- if (r)
+ if (r) {
+ kfree(rd_buf);
return r; /* r = -EFAULT */
+ }
buf += 1;
size -= 1;
@@ -245,6 +243,7 @@ static ssize_t dp_link_settings_write(struct file *f, const char __user *buf,
{
struct amdgpu_dm_connector *connector = file_inode(f)->i_private;
struct dc_link *link = connector->dc_link;
+ struct amdgpu_device *adev = drm_to_adev(connector->base.dev);
struct dc *dc = (struct dc *)link->dc;
struct dc_link_settings prefer_link_settings;
char *wr_buf = NULL;
@@ -292,9 +291,7 @@ static ssize_t dp_link_settings_write(struct file *f, const char __user *buf,
case LINK_RATE_RBR2:
case LINK_RATE_HIGH2:
case LINK_RATE_HIGH3:
-#if defined(CONFIG_DRM_AMD_DC_DCN)
case LINK_RATE_UHBR10:
-#endif
break;
default:
valid_input = false;
@@ -304,6 +301,9 @@ static ssize_t dp_link_settings_write(struct file *f, const char __user *buf,
if (!valid_input) {
kfree(wr_buf);
DRM_DEBUG_DRIVER("Invalid Input value No HW will be programmed\n");
+ mutex_lock(&adev->dm.dc_lock);
+ dc_link_set_preferred_training_settings(dc, NULL, NULL, link, false);
+ mutex_unlock(&adev->dm.dc_lock);
return size;
}
@@ -315,7 +315,9 @@ static ssize_t dp_link_settings_write(struct file *f, const char __user *buf,
prefer_link_settings.lane_count = param[0];
prefer_link_settings.link_rate = param[1];
- dc_link_set_preferred_training_settings(dc, &prefer_link_settings, NULL, link, true);
+ mutex_lock(&adev->dm.dc_lock);
+ dc_link_set_preferred_training_settings(dc, &prefer_link_settings, NULL, link, false);
+ mutex_unlock(&adev->dm.dc_lock);
kfree(wr_buf);
return size;
@@ -389,8 +391,10 @@ static ssize_t dp_phy_settings_read(struct file *f, char __user *buf,
break;
r = put_user((*(rd_buf + result)), buf);
- if (r)
+ if (r) {
+ kfree(rd_buf);
return r; /* r = -EFAULT */
+ }
buf += 1;
size -= 1;
@@ -853,12 +857,12 @@ static int psr_capability_show(struct seq_file *m, void *data)
if (!(link->connector_signal & SIGNAL_TYPE_EDP))
return -ENODEV;
- seq_printf(m, "Sink support: %s", yesno(link->dpcd_caps.psr_caps.psr_version != 0));
- if (link->dpcd_caps.psr_caps.psr_version)
- seq_printf(m, " [0x%02x]", link->dpcd_caps.psr_caps.psr_version);
+ seq_printf(m, "Sink support: %s", str_yes_no(link->dpcd_caps.psr_info.psr_version != 0));
+ if (link->dpcd_caps.psr_info.psr_version)
+ seq_printf(m, " [0x%02x]", link->dpcd_caps.psr_info.psr_version);
seq_puts(m, "\n");
- seq_printf(m, "Driver support: %s", yesno(link->psr_settings.psr_feature_enabled));
+ seq_printf(m, "Driver support: %s", str_yes_no(link->psr_settings.psr_feature_enabled));
if (link->psr_settings.psr_version)
seq_printf(m, " [0x%02x]", link->psr_settings.psr_version);
seq_puts(m, "\n");
@@ -1207,8 +1211,8 @@ static int dp_dsc_fec_support_show(struct seq_file *m, void *data)
drm_modeset_drop_locks(&ctx);
drm_modeset_acquire_fini(&ctx);
- seq_printf(m, "FEC_Sink_Support: %s\n", yesno(is_fec_supported));
- seq_printf(m, "DSC_Sink_Support: %s\n", yesno(is_dsc_supported));
+ seq_printf(m, "FEC_Sink_Support: %s\n", str_yes_no(is_fec_supported));
+ seq_printf(m, "DSC_Sink_Support: %s\n", str_yes_no(is_dsc_supported));
return ret;
}
@@ -1359,8 +1363,10 @@ static ssize_t dp_dsc_clock_en_read(struct file *f, char __user *buf,
break;
}
- if (!pipe_ctx)
+ if (!pipe_ctx) {
+ kfree(rd_buf);
return -ENXIO;
+ }
dsc = pipe_ctx->stream_res.dsc;
if (dsc)
@@ -1376,8 +1382,10 @@ static ssize_t dp_dsc_clock_en_read(struct file *f, char __user *buf,
break;
r = put_user(*(rd_buf + result), buf);
- if (r)
+ if (r) {
+ kfree(rd_buf);
return r; /* r = -EFAULT */
+ }
buf += 1;
size -= 1;
@@ -1546,8 +1554,10 @@ static ssize_t dp_dsc_slice_width_read(struct file *f, char __user *buf,
break;
}
- if (!pipe_ctx)
+ if (!pipe_ctx) {
+ kfree(rd_buf);
return -ENXIO;
+ }
dsc = pipe_ctx->stream_res.dsc;
if (dsc)
@@ -1563,8 +1573,10 @@ static ssize_t dp_dsc_slice_width_read(struct file *f, char __user *buf,
break;
r = put_user(*(rd_buf + result), buf);
- if (r)
+ if (r) {
+ kfree(rd_buf);
return r; /* r = -EFAULT */
+ }
buf += 1;
size -= 1;
@@ -1731,8 +1743,10 @@ static ssize_t dp_dsc_slice_height_read(struct file *f, char __user *buf,
break;
}
- if (!pipe_ctx)
+ if (!pipe_ctx) {
+ kfree(rd_buf);
return -ENXIO;
+ }
dsc = pipe_ctx->stream_res.dsc;
if (dsc)
@@ -1748,8 +1762,10 @@ static ssize_t dp_dsc_slice_height_read(struct file *f, char __user *buf,
break;
r = put_user(*(rd_buf + result), buf);
- if (r)
+ if (r) {
+ kfree(rd_buf);
return r; /* r = -EFAULT */
+ }
buf += 1;
size -= 1;
@@ -1912,8 +1928,10 @@ static ssize_t dp_dsc_bits_per_pixel_read(struct file *f, char __user *buf,
break;
}
- if (!pipe_ctx)
+ if (!pipe_ctx) {
+ kfree(rd_buf);
return -ENXIO;
+ }
dsc = pipe_ctx->stream_res.dsc;
if (dsc)
@@ -1929,8 +1947,10 @@ static ssize_t dp_dsc_bits_per_pixel_read(struct file *f, char __user *buf,
break;
r = put_user(*(rd_buf + result), buf);
- if (r)
+ if (r) {
+ kfree(rd_buf);
return r; /* r = -EFAULT */
+ }
buf += 1;
size -= 1;
@@ -2088,8 +2108,10 @@ static ssize_t dp_dsc_pic_width_read(struct file *f, char __user *buf,
break;
}
- if (!pipe_ctx)
+ if (!pipe_ctx) {
+ kfree(rd_buf);
return -ENXIO;
+ }
dsc = pipe_ctx->stream_res.dsc;
if (dsc)
@@ -2105,8 +2127,10 @@ static ssize_t dp_dsc_pic_width_read(struct file *f, char __user *buf,
break;
r = put_user(*(rd_buf + result), buf);
- if (r)
+ if (r) {
+ kfree(rd_buf);
return r; /* r = -EFAULT */
+ }
buf += 1;
size -= 1;
@@ -2145,8 +2169,10 @@ static ssize_t dp_dsc_pic_height_read(struct file *f, char __user *buf,
break;
}
- if (!pipe_ctx)
+ if (!pipe_ctx) {
+ kfree(rd_buf);
return -ENXIO;
+ }
dsc = pipe_ctx->stream_res.dsc;
if (dsc)
@@ -2162,8 +2188,10 @@ static ssize_t dp_dsc_pic_height_read(struct file *f, char __user *buf,
break;
r = put_user(*(rd_buf + result), buf);
- if (r)
+ if (r) {
+ kfree(rd_buf);
return r; /* r = -EFAULT */
+ }
buf += 1;
size -= 1;
@@ -2217,8 +2245,10 @@ static ssize_t dp_dsc_chunk_size_read(struct file *f, char __user *buf,
break;
}
- if (!pipe_ctx)
+ if (!pipe_ctx) {
+ kfree(rd_buf);
return -ENXIO;
+ }
dsc = pipe_ctx->stream_res.dsc;
if (dsc)
@@ -2234,8 +2264,10 @@ static ssize_t dp_dsc_chunk_size_read(struct file *f, char __user *buf,
break;
r = put_user(*(rd_buf + result), buf);
- if (r)
+ if (r) {
+ kfree(rd_buf);
return r; /* r = -EFAULT */
+ }
buf += 1;
size -= 1;
@@ -2289,8 +2321,10 @@ static ssize_t dp_dsc_slice_bpg_offset_read(struct file *f, char __user *buf,
break;
}
- if (!pipe_ctx)
+ if (!pipe_ctx) {
+ kfree(rd_buf);
return -ENXIO;
+ }
dsc = pipe_ctx->stream_res.dsc;
if (dsc)
@@ -2306,8 +2340,10 @@ static ssize_t dp_dsc_slice_bpg_offset_read(struct file *f, char __user *buf,
break;
r = put_user(*(rd_buf + result), buf);
- if (r)
+ if (r) {
+ kfree(rd_buf);
return r; /* r = -EFAULT */
+ }
buf += 1;
size -= 1;
@@ -2851,7 +2887,9 @@ static ssize_t edp_ilr_write(struct file *f, const char __user *buf,
kfree(wr_buf);
DRM_DEBUG_DRIVER("Invalid Input value. No HW will be programmed\n");
prefer_link_settings.use_link_rate_set = false;
- dc_link_set_preferred_training_settings(dc, NULL, NULL, link, true);
+ mutex_lock(&adev->dm.dc_lock);
+ dc_link_set_preferred_training_settings(dc, NULL, NULL, link, false);
+ mutex_unlock(&adev->dm.dc_lock);
return size;
}
@@ -3371,7 +3409,6 @@ static int disable_hpd_get(void *data, u64 *val)
DEFINE_DEBUGFS_ATTRIBUTE(disable_hpd_ops, disable_hpd_get,
disable_hpd_set, "%llu\n");
-#if defined(CONFIG_DRM_AMD_DC_DCN)
/*
* Temporary w/a to force sst sequence in M42D DP2 mst receiver
* Example usage: echo 1 > /sys/kernel/debug/dri/0/amdgpu_dm_dp_set_mst_en_for_sst
@@ -3395,7 +3432,30 @@ static int dp_force_sst_get(void *data, u64 *val)
}
DEFINE_DEBUGFS_ATTRIBUTE(dp_set_mst_en_for_sst_ops, dp_force_sst_get,
dp_force_sst_set, "%llu\n");
-#endif
+
+/*
+ * Force DP2 sequence without VESA certified cable.
+ * Example usage: echo 1 > /sys/kernel/debug/dri/0/amdgpu_dm_dp_ignore_cable_id
+ */
+static int dp_ignore_cable_id_set(void *data, u64 val)
+{
+ struct amdgpu_device *adev = data;
+
+ adev->dm.dc->debug.ignore_cable_id = val;
+
+ return 0;
+}
+
+static int dp_ignore_cable_id_get(void *data, u64 *val)
+{
+ struct amdgpu_device *adev = data;
+
+ *val = adev->dm.dc->debug.ignore_cable_id;
+
+ return 0;
+}
+DEFINE_DEBUGFS_ATTRIBUTE(dp_ignore_cable_id_ops, dp_ignore_cable_id_get,
+ dp_ignore_cable_id_set, "%llu\n");
/*
* Sets the DC visual confirm debug option from the given string.
@@ -3427,6 +3487,40 @@ DEFINE_SHOW_ATTRIBUTE(mst_topo);
DEFINE_DEBUGFS_ATTRIBUTE(visual_confirm_fops, visual_confirm_get,
visual_confirm_set, "%llu\n");
+
+/*
+ * Sets the DC skip_detection_link_training debug option from the given string.
+ * Example usage: echo 1 > /sys/kernel/debug/dri/0/amdgpu_skip_detection_link_training
+ */
+static int skip_detection_link_training_set(void *data, u64 val)
+{
+ struct amdgpu_device *adev = data;
+
+ if (val == 0)
+ adev->dm.dc->debug.skip_detection_link_training = false;
+ else
+ adev->dm.dc->debug.skip_detection_link_training = true;
+
+ return 0;
+}
+
+/*
+ * Reads the DC skip_detection_link_training debug option value into the given buffer.
+ * Example usage: cat /sys/kernel/debug/dri/0/amdgpu_dm_skip_detection_link_training
+ */
+static int skip_detection_link_training_get(void *data, u64 *val)
+{
+ struct amdgpu_device *adev = data;
+
+ *val = adev->dm.dc->debug.skip_detection_link_training;
+
+ return 0;
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(skip_detection_link_training_fops,
+ skip_detection_link_training_get,
+ skip_detection_link_training_set, "%llu\n");
+
/*
* Dumps the DCC_EN bit for each pipe.
* Example usage: cat /sys/kernel/debug/dri/0/amdgpu_dm_dcc_en
@@ -3459,8 +3553,10 @@ static ssize_t dcc_en_bits_read(
dc->hwss.get_dcc_en_bits(dc, dcc_en_bits);
rd_buf = kcalloc(rd_buf_size, sizeof(char), GFP_KERNEL);
- if (!rd_buf)
+ if (!rd_buf) {
+ kfree(dcc_en_bits);
return -ENOMEM;
+ }
for (i = 0; i < num_pipes; i++)
offset += snprintf(rd_buf + offset, rd_buf_size - offset,
@@ -3473,8 +3569,10 @@ static ssize_t dcc_en_bits_read(
if (*pos >= rd_buf_size)
break;
r = put_user(*(rd_buf + result), buf);
- if (r)
+ if (r) {
+ kfree(rd_buf);
return r; /* r = -EFAULT */
+ }
buf += 1;
size -= 1;
*pos += 1;
@@ -3506,14 +3604,17 @@ void dtn_debugfs_init(struct amdgpu_device *adev)
adev, &mst_topo_fops);
debugfs_create_file("amdgpu_dm_dtn_log", 0644, root, adev,
&dtn_log_fops);
-#if defined(CONFIG_DRM_AMD_DC_DCN)
debugfs_create_file("amdgpu_dm_dp_set_mst_en_for_sst", 0644, root, adev,
&dp_set_mst_en_for_sst_ops);
-#endif
+ debugfs_create_file("amdgpu_dm_dp_ignore_cable_id", 0644, root, adev,
+ &dp_ignore_cable_id_ops);
debugfs_create_file_unsafe("amdgpu_dm_visual_confirm", 0644, root, adev,
&visual_confirm_fops);
+ debugfs_create_file_unsafe("amdgpu_dm_skip_detection_link_training", 0644, root, adev,
+ &skip_detection_link_training_fops);
+
debugfs_create_file_unsafe("amdgpu_dm_dmub_tracebuffer", 0644, root,
adev, &dmub_tracebuffer_fops);
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 5bfdc66b5867..15c0e3f2a9c3 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
@@ -27,7 +27,7 @@
#include "amdgpu.h"
#include "amdgpu_dm.h"
#include "dm_helpers.h"
-#include <drm/drm_hdcp.h>
+#include <drm/display/drm_hdcp_helper.h>
#include "hdcp_psp.h"
/*
@@ -663,7 +663,9 @@ struct hdcp_workqueue *hdcp_create_workqueue(struct amdgpu_device *adev, struct
INIT_DELAYED_WORK(&hdcp_work[i].property_validate_dwork, event_property_validate);
hdcp_work[i].hdcp.config.psp.handle = &adev->psp;
- if (dc->ctx->dce_version == DCN_VERSION_3_1)
+ if (dc->ctx->dce_version == DCN_VERSION_3_1 ||
+ dc->ctx->dce_version == DCN_VERSION_3_15 ||
+ dc->ctx->dce_version == DCN_VERSION_3_16)
hdcp_work[i].hdcp.config.psp.caps.dtm_v3_supported = 1;
hdcp_work[i].hdcp.config.ddc.handle = dc_get_link_at_index(dc, i);
hdcp_work[i].hdcp.config.ddc.funcs.write_i2c = lp_write_i2c;
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 29f07c26d080..7c799ddc1d27 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
@@ -39,6 +39,7 @@
#include "amdgpu_dm_mst_types.h"
#include "dm_helpers.h"
+#include "ddc_service_types.h"
struct monitor_patch_info {
unsigned int manufacturer_id;
@@ -89,7 +90,7 @@ enum dc_edid_status dm_helpers_parse_edid_caps(
{
struct amdgpu_dm_connector *aconnector = link->priv;
struct drm_connector *connector = &aconnector->base;
- struct edid *edid_buf = (struct edid *) edid->raw_edid;
+ struct edid *edid_buf = edid ? (struct edid *) edid->raw_edid : NULL;
struct cea_sad *sads;
int sad_count = -1;
int sadb_count = -1;
@@ -445,7 +446,7 @@ bool dm_helpers_dp_mst_start_top_mgr(
return (drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, true) == 0);
}
-void dm_helpers_dp_mst_stop_top_mgr(
+bool dm_helpers_dp_mst_stop_top_mgr(
struct dc_context *ctx,
struct dc_link *link)
{
@@ -454,7 +455,7 @@ void dm_helpers_dp_mst_stop_top_mgr(
if (!aconnector) {
DRM_ERROR("Failed to find connector for link!");
- return;
+ return false;
}
DRM_INFO("DM_MST: stopping TM on aconnector: %p [id: %d]\n",
@@ -479,6 +480,8 @@ void dm_helpers_dp_mst_stop_top_mgr(
}
}
}
+
+ return false;
}
bool dm_helpers_dp_read_dpcd(
@@ -552,6 +555,177 @@ 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,
+ unsigned int length,
+ unsigned int offset,
+ unsigned char *data)
+{
+ bool success = false;
+ unsigned char rc_data[16] = {0};
+ unsigned char rc_offset[4] = {0};
+ unsigned char rc_length[2] = {0};
+ unsigned char rc_cmd = 0;
+ unsigned char rc_result = 0xFF;
+ unsigned char i = 0;
+ uint8_t ret = 0;
+
+ if (is_write_cmd) {
+ // write rc data
+ memmove(rc_data, data, length);
+ ret = drm_dp_dpcd_write(aux, SYNAPTICS_RC_DATA, rc_data, sizeof(rc_data));
+ }
+
+ // write rc offset
+ rc_offset[0] = (unsigned char) offset & 0xFF;
+ rc_offset[1] = (unsigned char) (offset >> 8) & 0xFF;
+ rc_offset[2] = (unsigned char) (offset >> 16) & 0xFF;
+ rc_offset[3] = (unsigned char) (offset >> 24) & 0xFF;
+ ret = drm_dp_dpcd_write(aux, SYNAPTICS_RC_OFFSET, rc_offset, sizeof(rc_offset));
+
+ // write rc length
+ rc_length[0] = (unsigned char) length & 0xFF;
+ rc_length[1] = (unsigned char) (length >> 8) & 0xFF;
+ ret = drm_dp_dpcd_write(aux, SYNAPTICS_RC_LENGTH, rc_length, sizeof(rc_length));
+
+ // write rc cmd
+ rc_cmd = cmd | 0x80;
+ ret = drm_dp_dpcd_write(aux, SYNAPTICS_RC_COMMAND, &rc_cmd, sizeof(rc_cmd));
+
+ if (ret < 0) {
+ DRM_ERROR(" execute_synaptics_rc_command - write cmd ..., err = %d\n", ret);
+ return false;
+ }
+
+ // poll until active is 0
+ for (i = 0; i < 10; i++) {
+ drm_dp_dpcd_read(aux, SYNAPTICS_RC_COMMAND, &rc_cmd, sizeof(rc_cmd));
+ if (rc_cmd == cmd)
+ // active is 0
+ break;
+ msleep(10);
+ }
+
+ // read rc result
+ drm_dp_dpcd_read(aux, SYNAPTICS_RC_RESULT, &rc_result, sizeof(rc_result));
+ success = (rc_result == 0);
+
+ if (success && !is_write_cmd) {
+ // read rc data
+ drm_dp_dpcd_read(aux, SYNAPTICS_RC_DATA, data, length);
+ }
+
+ DC_LOG_DC(" execute_synaptics_rc_command - success = %d\n", success);
+
+ return success;
+}
+
+static void apply_synaptics_fifo_reset_wa(struct drm_dp_aux *aux)
+{
+ unsigned char data[16] = {0};
+
+ DC_LOG_DC("Start apply_synaptics_fifo_reset_wa\n");
+
+ // Step 2
+ data[0] = 'P';
+ data[1] = 'R';
+ data[2] = 'I';
+ data[3] = 'U';
+ data[4] = 'S';
+
+ if (!execute_synaptics_rc_command(aux, true, 0x01, 5, 0, data))
+ return;
+
+ // Step 3 and 4
+ if (!execute_synaptics_rc_command(aux, false, 0x31, 4, 0x220998, data))
+ return;
+
+ data[0] &= (~(1 << 1)); // set bit 1 to 0
+ if (!execute_synaptics_rc_command(aux, true, 0x21, 4, 0x220998, data))
+ return;
+
+ if (!execute_synaptics_rc_command(aux, false, 0x31, 4, 0x220D98, data))
+ return;
+
+ data[0] &= (~(1 << 1)); // set bit 1 to 0
+ if (!execute_synaptics_rc_command(aux, true, 0x21, 4, 0x220D98, data))
+ return;
+
+ if (!execute_synaptics_rc_command(aux, false, 0x31, 4, 0x221198, data))
+ return;
+
+ data[0] &= (~(1 << 1)); // set bit 1 to 0
+ if (!execute_synaptics_rc_command(aux, true, 0x21, 4, 0x221198, data))
+ return;
+
+ // Step 3 and 5
+ if (!execute_synaptics_rc_command(aux, false, 0x31, 4, 0x220998, data))
+ return;
+
+ data[0] |= (1 << 1); // set bit 1 to 1
+ if (!execute_synaptics_rc_command(aux, true, 0x21, 4, 0x220998, data))
+ return;
+
+ if (!execute_synaptics_rc_command(aux, false, 0x31, 4, 0x220D98, data))
+ return;
+
+ data[0] |= (1 << 1); // set bit 1 to 1
+ return;
+
+ if (!execute_synaptics_rc_command(aux, false, 0x31, 4, 0x221198, data))
+ return;
+
+ data[0] |= (1 << 1); // set bit 1 to 1
+ if (!execute_synaptics_rc_command(aux, true, 0x21, 4, 0x221198, data))
+ return;
+
+ // Step 6
+ if (!execute_synaptics_rc_command(aux, true, 0x02, 0, 0, NULL))
+ return;
+
+ DC_LOG_DC("Done apply_synaptics_fifo_reset_wa\n");
+}
+
+static uint8_t write_dsc_enable_synaptics_non_virtual_dpcd_mst(
+ struct drm_dp_aux *aux,
+ const struct dc_stream_state *stream,
+ bool enable)
+{
+ uint8_t ret = 0;
+
+ DC_LOG_DC("Configure DSC to non-virtual dpcd synaptics\n");
+
+ if (enable) {
+ /* When DSC is enabled on previous boot and reboot with the hub,
+ * there is a chance that Synaptics hub gets stuck during reboot sequence.
+ * Applying a workaround to reset Synaptics SDP fifo before enabling the first stream
+ */
+ if (!stream->link->link_status.link_active &&
+ memcmp(stream->link->dpcd_caps.branch_dev_name,
+ (int8_t *)SYNAPTICS_DEVICE_ID, 4) == 0)
+ apply_synaptics_fifo_reset_wa(aux);
+
+ ret = drm_dp_dpcd_write(aux, DP_DSC_ENABLE, &enable, 1);
+ DRM_INFO("Send DSC enable to synaptics\n");
+
+ } else {
+ /* Synaptics hub not support virtual dpcd,
+ * external monitor occur garbage while disable DSC,
+ * Disable DSC only when entire link status turn to false,
+ */
+ if (!stream->link->link_status.link_active) {
+ ret = drm_dp_dpcd_write(aux, DP_DSC_ENABLE, &enable, 1);
+ DRM_INFO("Send DSC disable to synaptics\n");
+ }
+ }
+
+ return ret;
+}
+#endif
+
bool dm_helpers_dp_write_dsc_enable(
struct dc_context *ctx,
const struct dc_stream_state *stream,
@@ -570,7 +744,16 @@ 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
+
ret = drm_dp_dpcd_write(aconnector->dsc_aux, DP_DSC_ENABLE, &enable_dsc, 1);
+ DC_LOG_DC("Send DSC %s to MST RX\n", enable_dsc ? "enable" : "disable");
}
if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT || stream->signal == SIGNAL_TYPE_EDP) {
@@ -648,14 +831,6 @@ enum dc_edid_status dm_helpers_read_local_edid(
/* We don't need the original edid anymore */
kfree(edid);
- /* connector->display_info is parsed from EDID and saved
- * into drm_connector->display_info
- *
- * drm_connector->display_info will be used by amdgpu_dm funcs,
- * like fill_stream_properties_from_drm_display_mode
- */
- amdgpu_dm_update_connector_after_detect(aconnector);
-
edid_status = dm_helpers_parse_edid_caps(
link,
&sink->dc_edid,
@@ -797,16 +972,12 @@ void dm_helpers_mst_enable_stream_features(const struct dc_stream_state *stream)
sizeof(new_downspread));
}
-#if defined(CONFIG_DRM_AMD_DC_DCN)
void dm_set_phyd32clk(struct dc_context *ctx, int freq_khz)
{
- // FPGA programming for this clock in diags framework that
- // needs to go through dm layer, therefore leave dummy interace here
+ // TODO
}
-
void dm_helpers_enable_periodic_detection(struct dc_context *ctx, bool enable)
{
- /* TODO: add peridic detection implementation */
+ /* TODO: add periodic detection implementation */
}
-#endif
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c
index 4aba0e8c84f8..19f543ba7205 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c
@@ -928,7 +928,11 @@ void amdgpu_dm_hpd_fini(struct amdgpu_device *adev)
to_amdgpu_dm_connector(connector);
const struct dc_link *dc_link = amdgpu_dm_connector->dc_link;
- dc_interrupt_set(adev->dm.dc, dc_link->irq_source_hpd, false);
+ if (DC_IRQ_SOURCE_INVALID != dc_link->irq_source_hpd) {
+ dc_interrupt_set(adev->dm.dc,
+ dc_link->irq_source_hpd,
+ false);
+ }
if (DC_IRQ_SOURCE_INVALID != dc_link->irq_source_hpd_rx) {
dc_interrupt_set(adev->dm.dc,
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 cc34a35d0bcb..9221b6690a4a 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
@@ -23,10 +23,10 @@
*
*/
+#include <drm/display/drm_dp_helper.h>
+#include <drm/display/drm_dp_mst_helper.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
-#include <drm/drm_dp_mst_helper.h>
-#include <drm/drm_dp_helper.h>
#include "dm_services.h"
#include "amdgpu.h"
#include "amdgpu_dm.h"
@@ -45,9 +45,10 @@
#include "amdgpu_dm_debugfs.h"
#endif
-#if defined(CONFIG_DRM_AMD_DC_DCN)
#include "dc/dcn20/dcn20_resource.h"
-#endif
+bool is_timing_changed(struct dc_stream_state *cur_stream,
+ struct dc_stream_state *new_stream);
+
static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux,
struct drm_dp_aux_msg *msg)
@@ -159,7 +160,7 @@ static const struct drm_connector_funcs dm_dp_mst_connector_funcs = {
};
#if defined(CONFIG_DRM_AMD_DC_DCN)
-static bool needs_dsc_aux_workaround(struct dc_link *link)
+bool needs_dsc_aux_workaround(struct dc_link *link)
{
if (link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_90CC24 &&
(link->dpcd_caps.dpcd_rev.raw == DPCD_REV_14 || link->dpcd_caps.dpcd_rev.raw == DPCD_REV_12) &&
@@ -209,6 +210,25 @@ static bool validate_dsc_caps_on_connector(struct amdgpu_dm_connector *aconnecto
return true;
}
+
+static bool retrieve_downstream_port_device(struct amdgpu_dm_connector *aconnector)
+{
+ union dp_downstream_port_present ds_port_present;
+
+ if (!aconnector->dsc_aux)
+ return false;
+
+ if (drm_dp_dpcd_read(aconnector->dsc_aux, DP_DOWNSTREAMPORT_PRESENT, &ds_port_present, 1) < 0) {
+ DRM_INFO("Failed to read downstream_port_present 0x05 from DFP of branch device\n");
+ return false;
+ }
+
+ aconnector->mst_downstream_port_present = ds_port_present;
+ DRM_INFO("Downstream port present %d, type %d\n",
+ ds_port_present.fields.PORT_PRESENT, ds_port_present.fields.PORT_TYPE);
+
+ return true;
+}
#endif
static int dm_dp_mst_get_modes(struct drm_connector *connector)
@@ -289,6 +309,10 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector)
if (!validate_dsc_caps_on_connector(aconnector))
memset(&aconnector->dc_sink->dsc_caps,
0, sizeof(aconnector->dc_sink->dsc_caps));
+
+ if (!retrieve_downstream_port_device(aconnector))
+ memset(&aconnector->mst_downstream_port_present,
+ 0, sizeof(aconnector->mst_downstream_port_present));
#endif
}
}
@@ -576,6 +600,21 @@ static void set_dsc_configs_from_fairness_vars(struct dsc_mst_fairness_params *p
} else {
params[i].timing->flags.DSC = 0;
}
+ params[i].timing->dsc_cfg.mst_pbn = vars[i + k].pbn;
+ }
+
+ for (i = 0; i < count; i++) {
+ if (params[i].sink) {
+ if (params[i].sink->sink_signal != SIGNAL_TYPE_VIRTUAL &&
+ params[i].sink->sink_signal != SIGNAL_TYPE_NONE)
+ DRM_DEBUG_DRIVER("%s i=%d dispname=%s\n", __func__, i,
+ params[i].sink->edid_caps.display_name);
+ }
+
+ DRM_DEBUG_DRIVER("dsc=%d bits_per_pixel=%d pbn=%d\n",
+ params[i].timing->flags.DSC,
+ params[i].timing->dsc_cfg.bits_per_pixel,
+ vars[i + k].pbn);
}
}
@@ -888,22 +927,31 @@ static bool is_dsc_need_re_compute(
struct dc_state *dc_state,
struct dc_link *dc_link)
{
- int i;
+ int i, j;
bool is_dsc_need_re_compute = false;
+ struct amdgpu_dm_connector *stream_on_link[MAX_PIPES];
+ int new_stream_on_link_num = 0;
+ struct amdgpu_dm_connector *aconnector;
+ struct dc_stream_state *stream;
+ const struct dc *dc = dc_link->dc;
- /* only check phy used by mst branch */
+ /* only check phy used by dsc mst branch */
if (dc_link->type != dc_connection_mst_branch)
return false;
+ if (!(dc_link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_SUPPORT ||
+ dc_link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_PASSTHROUGH_SUPPORT))
+ return false;
+
+ for (i = 0; i < MAX_PIPES; i++)
+ stream_on_link[i] = NULL;
+
/* check if there is mode change in new request */
for (i = 0; i < dc_state->stream_count; i++) {
- struct amdgpu_dm_connector *aconnector;
- struct dc_stream_state *stream;
struct drm_crtc_state *new_crtc_state;
struct drm_connector_state *new_conn_state;
stream = dc_state->streams[i];
-
if (!stream)
continue;
@@ -915,8 +963,10 @@ static bool is_dsc_need_re_compute(
if (!aconnector)
continue;
- new_conn_state = drm_atomic_get_new_connector_state(state, &aconnector->base);
+ stream_on_link[new_stream_on_link_num] = aconnector;
+ new_stream_on_link_num++;
+ new_conn_state = drm_atomic_get_new_connector_state(state, &aconnector->base);
if (!new_conn_state)
continue;
@@ -927,7 +977,6 @@ static bool is_dsc_need_re_compute(
continue;
new_crtc_state = drm_atomic_get_new_crtc_state(state, new_conn_state->crtc);
-
if (!new_crtc_state)
continue;
@@ -937,7 +986,34 @@ static bool is_dsc_need_re_compute(
if (new_crtc_state->enable && new_crtc_state->active) {
if (new_crtc_state->mode_changed || new_crtc_state->active_changed ||
new_crtc_state->connectors_changed)
- is_dsc_need_re_compute = true;
+ return true;
+ }
+ }
+
+ /* check current_state if there stream on link but it is not in
+ * new request state
+ */
+ for (i = 0; i < dc->current_state->stream_count; i++) {
+ stream = dc->current_state->streams[i];
+ /* only check stream on the mst hub */
+ if (stream->link != dc_link)
+ continue;
+
+ aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context;
+ if (!aconnector)
+ continue;
+
+ for (j = 0; j < new_stream_on_link_num; j++) {
+ if (stream_on_link[j]) {
+ if (aconnector == stream_on_link[j])
+ break;
+ }
+ }
+
+ if (j == new_stream_on_link_num) {
+ /* not in new state */
+ is_dsc_need_re_compute = true;
+ break;
}
}
@@ -1005,4 +1081,197 @@ bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
return true;
}
+static bool
+ pre_compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
+ struct dc_state *dc_state,
+ struct dsc_mst_fairness_vars *vars)
+{
+ int i, j;
+ struct dc_stream_state *stream;
+ bool computed_streams[MAX_PIPES];
+ struct amdgpu_dm_connector *aconnector;
+ int link_vars_start_index = 0;
+
+ for (i = 0; i < dc_state->stream_count; i++)
+ computed_streams[i] = false;
+
+ for (i = 0; i < dc_state->stream_count; i++) {
+ stream = dc_state->streams[i];
+
+ if (stream->signal != SIGNAL_TYPE_DISPLAY_PORT_MST)
+ continue;
+
+ aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context;
+
+ if (!aconnector || !aconnector->dc_sink)
+ continue;
+
+ if (!aconnector->dc_sink->dsc_caps.dsc_dec_caps.is_dsc_supported)
+ continue;
+
+ if (computed_streams[i])
+ continue;
+
+ if (!is_dsc_need_re_compute(state, dc_state, stream->link))
+ continue;
+
+ mutex_lock(&aconnector->mst_mgr.lock);
+ if (!compute_mst_dsc_configs_for_link(state,
+ dc_state,
+ stream->link,
+ vars,
+ &link_vars_start_index)) {
+ mutex_unlock(&aconnector->mst_mgr.lock);
+ return false;
+ }
+ mutex_unlock(&aconnector->mst_mgr.lock);
+
+ for (j = 0; j < dc_state->stream_count; j++) {
+ if (dc_state->streams[j]->link == stream->link)
+ computed_streams[j] = true;
+ }
+ }
+
+ return true;
+}
+
+static int find_crtc_index_in_state_by_stream(struct drm_atomic_state *state,
+ struct dc_stream_state *stream)
+{
+ int i;
+ struct drm_crtc *crtc;
+ struct drm_crtc_state *new_state, *old_state;
+
+ for_each_oldnew_crtc_in_state(state, crtc, old_state, new_state, i) {
+ struct dm_crtc_state *dm_state = to_dm_crtc_state(new_state);
+
+ if (dm_state->stream == stream)
+ return i;
+ }
+ return -1;
+}
+
+static bool is_link_to_dschub(struct dc_link *dc_link)
+{
+ union dpcd_dsc_basic_capabilities *dsc_caps =
+ &dc_link->dpcd_caps.dsc_caps.dsc_basic_caps;
+
+ /* only check phy used by dsc mst branch */
+ if (dc_link->type != dc_connection_mst_branch)
+ return false;
+
+ if (!(dsc_caps->fields.dsc_support.DSC_SUPPORT ||
+ dsc_caps->fields.dsc_support.DSC_PASSTHROUGH_SUPPORT))
+ return false;
+ return true;
+}
+
+static bool is_dsc_precompute_needed(struct drm_atomic_state *state)
+{
+ int i;
+ struct drm_crtc *crtc;
+ struct drm_crtc_state *old_crtc_state, *new_crtc_state;
+ bool ret = false;
+
+ for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
+ struct dm_crtc_state *dm_crtc_state = to_dm_crtc_state(new_crtc_state);
+
+ if (!amdgpu_dm_find_first_crtc_matching_connector(state, crtc)) {
+ ret = false;
+ break;
+ }
+ if (dm_crtc_state->stream && dm_crtc_state->stream->link)
+ if (is_link_to_dschub(dm_crtc_state->stream->link))
+ ret = true;
+ }
+ return ret;
+}
+
+void pre_validate_dsc(struct drm_atomic_state *state,
+ struct dm_atomic_state **dm_state_ptr,
+ struct dsc_mst_fairness_vars *vars)
+{
+ int i;
+ struct dm_atomic_state *dm_state;
+ struct dc_state *local_dc_state = NULL;
+
+ if (!is_dsc_precompute_needed(state)) {
+ DRM_INFO_ONCE("DSC precompute is not needed.\n");
+ return;
+ }
+ if (dm_atomic_get_state(state, dm_state_ptr)) {
+ DRM_INFO_ONCE("dm_atomic_get_state() failed\n");
+ return;
+ }
+ dm_state = *dm_state_ptr;
+
+ /*
+ * create local vailable for dc_state. copy content of streams of dm_state->context
+ * to local variable. make sure stream pointer of local variable not the same as stream
+ * from dm_state->context.
+ */
+
+ local_dc_state = kmemdup(dm_state->context, sizeof(struct dc_state), GFP_KERNEL);
+ if (!local_dc_state)
+ return;
+
+ for (i = 0; i < local_dc_state->stream_count; i++) {
+ struct dc_stream_state *stream = dm_state->context->streams[i];
+ int ind = find_crtc_index_in_state_by_stream(state, stream);
+
+ if (ind >= 0) {
+ struct amdgpu_dm_connector *aconnector;
+ struct drm_connector_state *drm_new_conn_state;
+ struct dm_connector_state *dm_new_conn_state;
+ struct dm_crtc_state *dm_old_crtc_state;
+
+ aconnector =
+ amdgpu_dm_find_first_crtc_matching_connector(state,
+ state->crtcs[ind].ptr);
+ drm_new_conn_state =
+ drm_atomic_get_new_connector_state(state,
+ &aconnector->base);
+ dm_new_conn_state = to_dm_connector_state(drm_new_conn_state);
+ dm_old_crtc_state = to_dm_crtc_state(state->crtcs[ind].old_state);
+
+ local_dc_state->streams[i] =
+ create_validate_stream_for_sink(aconnector,
+ &state->crtcs[ind].new_state->mode,
+ dm_new_conn_state,
+ dm_old_crtc_state->stream);
+ }
+ }
+
+ if (!pre_compute_mst_dsc_configs_for_state(state, local_dc_state, vars)) {
+ DRM_INFO_ONCE("pre_compute_mst_dsc_configs_for_state() failed\n");
+ goto clean_exit;
+ }
+
+ /*
+ * compare local_streams -> timing with dm_state->context,
+ * if the same set crtc_state->mode-change = 0;
+ */
+ for (i = 0; i < local_dc_state->stream_count; i++) {
+ struct dc_stream_state *stream = dm_state->context->streams[i];
+
+ if (local_dc_state->streams[i] &&
+ is_timing_changed(stream, local_dc_state->streams[i])) {
+ DRM_INFO_ONCE("crtc[%d] needs mode_changed\n", i);
+ } else {
+ int ind = find_crtc_index_in_state_by_stream(state, stream);
+
+ if (ind >= 0)
+ state->crtcs[ind].new_state->mode_changed = 0;
+ }
+ }
+clean_exit:
+ for (i = 0; i < local_dc_state->stream_count; i++) {
+ struct dc_stream_state *stream = dm_state->context->streams[i];
+
+ if (local_dc_state->streams[i] != stream)
+ dc_stream_release(local_dc_state->streams[i]);
+ }
+
+ kfree(local_dc_state);
+}
#endif
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
index 900d3f7a8498..85628ad59e6c 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
@@ -26,6 +26,14 @@
#ifndef __DAL_AMDGPU_DM_MST_TYPES_H__
#define __DAL_AMDGPU_DM_MST_TYPES_H__
+#define DP_BRANCH_DEVICE_ID_90CC24 0x90CC24
+
+#define SYNAPTICS_RC_COMMAND 0x4B2
+#define SYNAPTICS_RC_RESULT 0x4B3
+#define SYNAPTICS_RC_LENGTH 0x4B8
+#define SYNAPTICS_RC_OFFSET 0x4BC
+#define SYNAPTICS_RC_DATA 0x4C0
+
struct amdgpu_display_manager;
struct amdgpu_dm_connector;
@@ -38,8 +46,6 @@ void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm,
void
dm_dp_create_fake_mst_encoders(struct amdgpu_device *adev);
-#if defined(CONFIG_DRM_AMD_DC_DCN)
-
struct dsc_mst_fairness_vars {
int pbn;
bool dsc_enabled;
@@ -50,6 +56,11 @@ struct dsc_mst_fairness_vars {
bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
struct dc_state *dc_state,
struct dsc_mst_fairness_vars *vars);
-#endif
+
+bool needs_dsc_aux_workaround(struct dc_link *link);
+
+void pre_validate_dsc(struct drm_atomic_state *state,
+ struct dm_atomic_state **dm_state_ptr,
+ struct dsc_mst_fairness_vars *vars);
#endif
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c
index eba270121698..75284e2cec74 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c
@@ -99,12 +99,9 @@ bool dm_pp_apply_display_requirements(
adev->pm.pm_display_cfg.displays[i].controller_id = dc_cfg->pipe_idx + 1;
}
- if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->display_configuration_change)
- adev->powerplay.pp_funcs->display_configuration_change(
- adev->powerplay.pp_handle,
- &adev->pm.pm_display_cfg);
+ amdgpu_dpm_display_configuration_change(adev, &adev->pm.pm_display_cfg);
- amdgpu_pm_compute_clocks(adev);
+ amdgpu_dpm_compute_clocks(adev);
}
return true;
@@ -298,31 +295,25 @@ bool dm_pp_get_clock_levels_by_type(
struct dm_pp_clock_levels *dc_clks)
{
struct amdgpu_device *adev = ctx->driver_context;
- void *pp_handle = adev->powerplay.pp_handle;
struct amd_pp_clocks pp_clks = { 0 };
struct amd_pp_simple_clock_info validation_clks = { 0 };
uint32_t i;
- if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->get_clock_by_type) {
- if (adev->powerplay.pp_funcs->get_clock_by_type(pp_handle,
- dc_to_pp_clock_type(clk_type), &pp_clks)) {
- /* Error in pplib. Provide default values. */
- get_default_clock_levels(clk_type, dc_clks);
- return true;
- }
+ if (amdgpu_dpm_get_clock_by_type(adev,
+ dc_to_pp_clock_type(clk_type), &pp_clks)) {
+ /* Error in pplib. Provide default values. */
+ get_default_clock_levels(clk_type, dc_clks);
+ return true;
}
pp_to_dc_clock_levels(&pp_clks, dc_clks, clk_type);
- if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->get_display_mode_validation_clocks) {
- if (adev->powerplay.pp_funcs->get_display_mode_validation_clocks(
- pp_handle, &validation_clks)) {
- /* Error in pplib. Provide default values. */
- DRM_INFO("DM_PPLIB: Warning: using default validation clocks!\n");
- validation_clks.engine_max_clock = 72000;
- validation_clks.memory_max_clock = 80000;
- validation_clks.level = 0;
- }
+ if (amdgpu_dpm_get_display_mode_validation_clks(adev, &validation_clks)) {
+ /* Error in pplib. Provide default values. */
+ DRM_INFO("DM_PPLIB: Warning: using default validation clocks!\n");
+ validation_clks.engine_max_clock = 72000;
+ validation_clks.memory_max_clock = 80000;
+ validation_clks.level = 0;
}
DRM_INFO("DM_PPLIB: Validation clocks:\n");
@@ -370,18 +361,14 @@ bool dm_pp_get_clock_levels_by_type_with_latency(
struct dm_pp_clock_levels_with_latency *clk_level_info)
{
struct amdgpu_device *adev = ctx->driver_context;
- void *pp_handle = adev->powerplay.pp_handle;
struct pp_clock_levels_with_latency pp_clks = { 0 };
- const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
int ret;
- if (pp_funcs && pp_funcs->get_clock_by_type_with_latency) {
- ret = pp_funcs->get_clock_by_type_with_latency(pp_handle,
- dc_to_pp_clock_type(clk_type),
- &pp_clks);
- if (ret)
- return false;
- }
+ ret = amdgpu_dpm_get_clock_by_type_with_latency(adev,
+ dc_to_pp_clock_type(clk_type),
+ &pp_clks);
+ if (ret)
+ return false;
pp_to_dc_clock_levels_with_latency(&pp_clks, clk_level_info, clk_type);
@@ -394,18 +381,14 @@ bool dm_pp_get_clock_levels_by_type_with_voltage(
struct dm_pp_clock_levels_with_voltage *clk_level_info)
{
struct amdgpu_device *adev = ctx->driver_context;
- void *pp_handle = adev->powerplay.pp_handle;
struct pp_clock_levels_with_voltage pp_clk_info = {0};
- const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
int ret;
- if (pp_funcs && pp_funcs->get_clock_by_type_with_voltage) {
- ret = pp_funcs->get_clock_by_type_with_voltage(pp_handle,
- dc_to_pp_clock_type(clk_type),
- &pp_clk_info);
- if (ret)
- return false;
- }
+ ret = amdgpu_dpm_get_clock_by_type_with_voltage(adev,
+ dc_to_pp_clock_type(clk_type),
+ &pp_clk_info);
+ if (ret)
+ return false;
pp_to_dc_clock_levels_with_voltage(&pp_clk_info, clk_level_info, clk_type);
@@ -417,19 +400,16 @@ bool dm_pp_notify_wm_clock_changes(
struct dm_pp_wm_sets_with_clock_ranges *wm_with_clock_ranges)
{
struct amdgpu_device *adev = ctx->driver_context;
- void *pp_handle = adev->powerplay.pp_handle;
- const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
/*
* Limit this watermark setting for Polaris for now
* TODO: expand this to other ASICs
*/
- if ((adev->asic_type >= CHIP_POLARIS10) && (adev->asic_type <= CHIP_VEGAM)
- && pp_funcs && pp_funcs->set_watermarks_for_clocks_ranges) {
- if (!pp_funcs->set_watermarks_for_clocks_ranges(pp_handle,
+ if ((adev->asic_type >= CHIP_POLARIS10) &&
+ (adev->asic_type <= CHIP_VEGAM) &&
+ !amdgpu_dpm_set_watermarks_for_clocks_ranges(adev,
(void *)wm_with_clock_ranges))
return true;
- }
return false;
}
@@ -456,12 +436,10 @@ bool dm_pp_apply_clock_for_voltage_request(
if (!pp_clock_request.clock_type)
return false;
- if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->display_clock_voltage_request)
- ret = adev->powerplay.pp_funcs->display_clock_voltage_request(
- adev->powerplay.pp_handle,
- &pp_clock_request);
- if (ret)
+ ret = amdgpu_dpm_display_clock_voltage_request(adev, &pp_clock_request);
+ if (ret && (ret != -EOPNOTSUPP))
return false;
+
return true;
}
@@ -471,15 +449,8 @@ bool dm_pp_get_static_clocks(
{
struct amdgpu_device *adev = ctx->driver_context;
struct amd_pp_clock_info pp_clk_info = {0};
- int ret = 0;
- if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->get_current_clocks)
- ret = adev->powerplay.pp_funcs->get_current_clocks(
- adev->powerplay.pp_handle,
- &pp_clk_info);
- else
- return false;
- if (ret)
+ if (amdgpu_dpm_get_current_clocks(adev, &pp_clk_info))
return false;
static_clk_info->max_clocks_state = pp_to_dc_powerlevel_state(pp_clk_info.max_clocks_state);
@@ -494,8 +465,6 @@ static void pp_rv_set_wm_ranges(struct pp_smu *pp,
{
const struct dc_context *ctx = pp->dm;
struct amdgpu_device *adev = ctx->driver_context;
- void *pp_handle = adev->powerplay.pp_handle;
- const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
struct dm_pp_wm_sets_with_clock_ranges_soc15 wm_with_clock_ranges;
struct dm_pp_clock_range_for_dmif_wm_set_soc15 *wm_dce_clocks = wm_with_clock_ranges.wm_dmif_clocks_ranges;
struct dm_pp_clock_range_for_mcif_wm_set_soc15 *wm_soc_clocks = wm_with_clock_ranges.wm_mcif_clocks_ranges;
@@ -536,72 +505,48 @@ static void pp_rv_set_wm_ranges(struct pp_smu *pp,
ranges->writer_wm_sets[i].min_drain_clk_mhz * 1000;
}
- if (pp_funcs && pp_funcs->set_watermarks_for_clocks_ranges)
- pp_funcs->set_watermarks_for_clocks_ranges(pp_handle,
- &wm_with_clock_ranges);
+ amdgpu_dpm_set_watermarks_for_clocks_ranges(adev,
+ &wm_with_clock_ranges);
}
static void pp_rv_set_pme_wa_enable(struct pp_smu *pp)
{
const struct dc_context *ctx = pp->dm;
struct amdgpu_device *adev = ctx->driver_context;
- void *pp_handle = adev->powerplay.pp_handle;
- const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
- if (pp_funcs && pp_funcs->notify_smu_enable_pwe)
- pp_funcs->notify_smu_enable_pwe(pp_handle);
+ amdgpu_dpm_notify_smu_enable_pwe(adev);
}
static void pp_rv_set_active_display_count(struct pp_smu *pp, int count)
{
const struct dc_context *ctx = pp->dm;
struct amdgpu_device *adev = ctx->driver_context;
- void *pp_handle = adev->powerplay.pp_handle;
- const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
- if (!pp_funcs || !pp_funcs->set_active_display_count)
- return;
-
- pp_funcs->set_active_display_count(pp_handle, count);
+ amdgpu_dpm_set_active_display_count(adev, count);
}
static void pp_rv_set_min_deep_sleep_dcfclk(struct pp_smu *pp, int clock)
{
const struct dc_context *ctx = pp->dm;
struct amdgpu_device *adev = ctx->driver_context;
- void *pp_handle = adev->powerplay.pp_handle;
- const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
-
- if (!pp_funcs || !pp_funcs->set_min_deep_sleep_dcefclk)
- return;
- pp_funcs->set_min_deep_sleep_dcefclk(pp_handle, clock);
+ amdgpu_dpm_set_min_deep_sleep_dcefclk(adev, clock);
}
static void pp_rv_set_hard_min_dcefclk_by_freq(struct pp_smu *pp, int clock)
{
const struct dc_context *ctx = pp->dm;
struct amdgpu_device *adev = ctx->driver_context;
- void *pp_handle = adev->powerplay.pp_handle;
- const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
- if (!pp_funcs || !pp_funcs->set_hard_min_dcefclk_by_freq)
- return;
-
- pp_funcs->set_hard_min_dcefclk_by_freq(pp_handle, clock);
+ amdgpu_dpm_set_hard_min_dcefclk_by_freq(adev, clock);
}
static void pp_rv_set_hard_min_fclk_by_freq(struct pp_smu *pp, int mhz)
{
const struct dc_context *ctx = pp->dm;
struct amdgpu_device *adev = ctx->driver_context;
- void *pp_handle = adev->powerplay.pp_handle;
- const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
-
- if (!pp_funcs || !pp_funcs->set_hard_min_fclk_by_freq)
- return;
- pp_funcs->set_hard_min_fclk_by_freq(pp_handle, mhz);
+ amdgpu_dpm_set_hard_min_fclk_by_freq(adev, mhz);
}
static enum pp_smu_status pp_nv_set_wm_ranges(struct pp_smu *pp,
@@ -609,11 +554,8 @@ static enum pp_smu_status pp_nv_set_wm_ranges(struct pp_smu *pp,
{
const struct dc_context *ctx = pp->dm;
struct amdgpu_device *adev = ctx->driver_context;
- void *pp_handle = adev->powerplay.pp_handle;
- const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
- if (pp_funcs && pp_funcs->set_watermarks_for_clocks_ranges)
- pp_funcs->set_watermarks_for_clocks_ranges(pp_handle, ranges);
+ amdgpu_dpm_set_watermarks_for_clocks_ranges(adev, ranges);
return PP_SMU_RESULT_OK;
}
@@ -622,14 +564,13 @@ static enum pp_smu_status pp_nv_set_display_count(struct pp_smu *pp, int count)
{
const struct dc_context *ctx = pp->dm;
struct amdgpu_device *adev = ctx->driver_context;
- void *pp_handle = adev->powerplay.pp_handle;
- const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
+ int ret = 0;
- if (!pp_funcs || !pp_funcs->set_active_display_count)
+ ret = amdgpu_dpm_set_active_display_count(adev, count);
+ if (ret == -EOPNOTSUPP)
return PP_SMU_RESULT_UNSUPPORTED;
-
- /* 0: successful or smu.ppt_funcs->set_display_count = NULL; 1: fail */
- if (pp_funcs->set_active_display_count(pp_handle, count))
+ else if (ret)
+ /* 0: successful or smu.ppt_funcs->set_display_count = NULL; 1: fail */
return PP_SMU_RESULT_FAIL;
return PP_SMU_RESULT_OK;
@@ -640,14 +581,13 @@ pp_nv_set_min_deep_sleep_dcfclk(struct pp_smu *pp, int mhz)
{
const struct dc_context *ctx = pp->dm;
struct amdgpu_device *adev = ctx->driver_context;
- void *pp_handle = adev->powerplay.pp_handle;
- const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
-
- if (!pp_funcs || !pp_funcs->set_min_deep_sleep_dcefclk)
- return PP_SMU_RESULT_UNSUPPORTED;
+ int ret = 0;
/* 0: successful or smu.ppt_funcs->set_deep_sleep_dcefclk = NULL;1: fail */
- if (pp_funcs->set_min_deep_sleep_dcefclk(pp_handle, mhz))
+ ret = amdgpu_dpm_set_min_deep_sleep_dcefclk(adev, mhz);
+ if (ret == -EOPNOTSUPP)
+ return PP_SMU_RESULT_UNSUPPORTED;
+ else if (ret)
return PP_SMU_RESULT_FAIL;
return PP_SMU_RESULT_OK;
@@ -658,12 +598,8 @@ static enum pp_smu_status pp_nv_set_hard_min_dcefclk_by_freq(
{
const struct dc_context *ctx = pp->dm;
struct amdgpu_device *adev = ctx->driver_context;
- void *pp_handle = adev->powerplay.pp_handle;
- const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
struct pp_display_clock_request clock_req;
-
- if (!pp_funcs || !pp_funcs->display_clock_voltage_request)
- return PP_SMU_RESULT_UNSUPPORTED;
+ int ret = 0;
clock_req.clock_type = amd_pp_dcef_clock;
clock_req.clock_freq_in_khz = mhz * 1000;
@@ -671,7 +607,10 @@ static enum pp_smu_status pp_nv_set_hard_min_dcefclk_by_freq(
/* 0: successful or smu.ppt_funcs->display_clock_voltage_request = NULL
* 1: fail
*/
- if (pp_funcs->display_clock_voltage_request(pp_handle, &clock_req))
+ ret = amdgpu_dpm_display_clock_voltage_request(adev, &clock_req);
+ if (ret == -EOPNOTSUPP)
+ return PP_SMU_RESULT_UNSUPPORTED;
+ else if (ret)
return PP_SMU_RESULT_FAIL;
return PP_SMU_RESULT_OK;
@@ -682,12 +621,8 @@ pp_nv_set_hard_min_uclk_by_freq(struct pp_smu *pp, int mhz)
{
const struct dc_context *ctx = pp->dm;
struct amdgpu_device *adev = ctx->driver_context;
- void *pp_handle = adev->powerplay.pp_handle;
- const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
struct pp_display_clock_request clock_req;
-
- if (!pp_funcs || !pp_funcs->display_clock_voltage_request)
- return PP_SMU_RESULT_UNSUPPORTED;
+ int ret = 0;
clock_req.clock_type = amd_pp_mem_clock;
clock_req.clock_freq_in_khz = mhz * 1000;
@@ -695,7 +630,10 @@ pp_nv_set_hard_min_uclk_by_freq(struct pp_smu *pp, int mhz)
/* 0: successful or smu.ppt_funcs->display_clock_voltage_request = NULL
* 1: fail
*/
- if (pp_funcs->display_clock_voltage_request(pp_handle, &clock_req))
+ ret = amdgpu_dpm_display_clock_voltage_request(adev, &clock_req);
+ if (ret == -EOPNOTSUPP)
+ return PP_SMU_RESULT_UNSUPPORTED;
+ else if (ret)
return PP_SMU_RESULT_FAIL;
return PP_SMU_RESULT_OK;
@@ -706,14 +644,10 @@ static enum pp_smu_status pp_nv_set_pstate_handshake_support(
{
const struct dc_context *ctx = pp->dm;
struct amdgpu_device *adev = ctx->driver_context;
- void *pp_handle = adev->powerplay.pp_handle;
- const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
- if (pp_funcs && pp_funcs->display_disable_memory_clock_switch) {
- if (pp_funcs->display_disable_memory_clock_switch(pp_handle,
- !pstate_handshake_supported))
- return PP_SMU_RESULT_FAIL;
- }
+ if (amdgpu_dpm_display_disable_memory_clock_switch(adev,
+ !pstate_handshake_supported))
+ return PP_SMU_RESULT_FAIL;
return PP_SMU_RESULT_OK;
}
@@ -723,12 +657,8 @@ static enum pp_smu_status pp_nv_set_voltage_by_freq(struct pp_smu *pp,
{
const struct dc_context *ctx = pp->dm;
struct amdgpu_device *adev = ctx->driver_context;
- void *pp_handle = adev->powerplay.pp_handle;
- const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
struct pp_display_clock_request clock_req;
-
- if (!pp_funcs || !pp_funcs->display_clock_voltage_request)
- return PP_SMU_RESULT_UNSUPPORTED;
+ int ret = 0;
switch (clock_id) {
case PP_SMU_NV_DISPCLK:
@@ -748,7 +678,10 @@ static enum pp_smu_status pp_nv_set_voltage_by_freq(struct pp_smu *pp,
/* 0: successful or smu.ppt_funcs->display_clock_voltage_request = NULL
* 1: fail
*/
- if (pp_funcs->display_clock_voltage_request(pp_handle, &clock_req))
+ ret = amdgpu_dpm_display_clock_voltage_request(adev, &clock_req);
+ if (ret == -EOPNOTSUPP)
+ return PP_SMU_RESULT_UNSUPPORTED;
+ else if (ret)
return PP_SMU_RESULT_FAIL;
return PP_SMU_RESULT_OK;
@@ -759,16 +692,16 @@ static enum pp_smu_status pp_nv_get_maximum_sustainable_clocks(
{
const struct dc_context *ctx = pp->dm;
struct amdgpu_device *adev = ctx->driver_context;
- void *pp_handle = adev->powerplay.pp_handle;
- const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
+ int ret = 0;
- if (!pp_funcs || !pp_funcs->get_max_sustainable_clocks_by_dc)
+ ret = amdgpu_dpm_get_max_sustainable_clocks_by_dc(adev,
+ max_clocks);
+ if (ret == -EOPNOTSUPP)
return PP_SMU_RESULT_UNSUPPORTED;
+ else if (ret)
+ return PP_SMU_RESULT_FAIL;
- if (!pp_funcs->get_max_sustainable_clocks_by_dc(pp_handle, max_clocks))
- return PP_SMU_RESULT_OK;
-
- return PP_SMU_RESULT_FAIL;
+ return PP_SMU_RESULT_OK;
}
static enum pp_smu_status pp_nv_get_uclk_dpm_states(struct pp_smu *pp,
@@ -776,18 +709,17 @@ static enum pp_smu_status pp_nv_get_uclk_dpm_states(struct pp_smu *pp,
{
const struct dc_context *ctx = pp->dm;
struct amdgpu_device *adev = ctx->driver_context;
- void *pp_handle = adev->powerplay.pp_handle;
- const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
+ int ret = 0;
- if (!pp_funcs || !pp_funcs->get_uclk_dpm_states)
+ ret = amdgpu_dpm_get_uclk_dpm_states(adev,
+ clock_values_in_khz,
+ num_states);
+ if (ret == -EOPNOTSUPP)
return PP_SMU_RESULT_UNSUPPORTED;
+ else if (ret)
+ return PP_SMU_RESULT_FAIL;
- if (!pp_funcs->get_uclk_dpm_states(pp_handle,
- clock_values_in_khz,
- num_states))
- return PP_SMU_RESULT_OK;
-
- return PP_SMU_RESULT_FAIL;
+ return PP_SMU_RESULT_OK;
}
static enum pp_smu_status pp_rn_get_dpm_clock_table(
@@ -795,16 +727,15 @@ static enum pp_smu_status pp_rn_get_dpm_clock_table(
{
const struct dc_context *ctx = pp->dm;
struct amdgpu_device *adev = ctx->driver_context;
- void *pp_handle = adev->powerplay.pp_handle;
- const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
+ int ret = 0;
- if (!pp_funcs || !pp_funcs->get_dpm_clock_table)
+ ret = amdgpu_dpm_get_dpm_clock_table(adev, clock_table);
+ if (ret == -EOPNOTSUPP)
return PP_SMU_RESULT_UNSUPPORTED;
+ else if (ret)
+ return PP_SMU_RESULT_FAIL;
- if (!pp_funcs->get_dpm_clock_table(pp_handle, clock_table))
- return PP_SMU_RESULT_OK;
-
- return PP_SMU_RESULT_FAIL;
+ return PP_SMU_RESULT_OK;
}
static enum pp_smu_status pp_rn_set_wm_ranges(struct pp_smu *pp,
@@ -812,11 +743,8 @@ static enum pp_smu_status pp_rn_set_wm_ranges(struct pp_smu *pp,
{
const struct dc_context *ctx = pp->dm;
struct amdgpu_device *adev = ctx->driver_context;
- void *pp_handle = adev->powerplay.pp_handle;
- const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
- if (pp_funcs && pp_funcs->set_watermarks_for_clocks_ranges)
- pp_funcs->set_watermarks_for_clocks_ranges(pp_handle, ranges);
+ amdgpu_dpm_set_watermarks_for_clocks_ranges(adev, ranges);
return PP_SMU_RESULT_OK;
}
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c
index c510638b4f99..141fd2721501 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c
@@ -27,51 +27,8 @@
#include "dc.h"
#include "dm_helpers.h"
#include "amdgpu_dm.h"
+#include "modules/power/power_helpers.h"
-static bool link_get_psr_caps(struct dc_link *link)
-{
- uint8_t psr_dpcd_data[EDP_PSR_RECEIVER_CAP_SIZE];
- uint8_t edp_rev_dpcd_data;
-
-
-
- if (!dm_helpers_dp_read_dpcd(NULL, link, DP_PSR_SUPPORT,
- psr_dpcd_data, sizeof(psr_dpcd_data)))
- return false;
-
- if (!dm_helpers_dp_read_dpcd(NULL, link, DP_EDP_DPCD_REV,
- &edp_rev_dpcd_data, sizeof(edp_rev_dpcd_data)))
- return false;
-
- link->dpcd_caps.psr_caps.psr_version = psr_dpcd_data[0];
- link->dpcd_caps.psr_caps.edp_revision = edp_rev_dpcd_data;
-
-#ifdef CONFIG_DRM_AMD_DC_DCN
- if (link->dpcd_caps.psr_caps.psr_version > 0x1) {
- uint8_t alpm_dpcd_data;
- uint8_t su_granularity_dpcd_data;
-
- if (!dm_helpers_dp_read_dpcd(NULL, link, DP_RECEIVER_ALPM_CAP,
- &alpm_dpcd_data, sizeof(alpm_dpcd_data)))
- return false;
-
- if (!dm_helpers_dp_read_dpcd(NULL, link, DP_PSR2_SU_Y_GRANULARITY,
- &su_granularity_dpcd_data, sizeof(su_granularity_dpcd_data)))
- return false;
-
- link->dpcd_caps.psr_caps.y_coordinate_required = psr_dpcd_data[1] & DP_PSR2_SU_Y_COORDINATE_REQUIRED;
- link->dpcd_caps.psr_caps.su_granularity_required = psr_dpcd_data[1] & DP_PSR2_SU_GRANULARITY_REQUIRED;
-
- link->dpcd_caps.psr_caps.alpm_cap = alpm_dpcd_data & DP_ALPM_CAP;
- link->dpcd_caps.psr_caps.standby_support = alpm_dpcd_data & (1 << 1);
-
- link->dpcd_caps.psr_caps.su_y_granularity = su_granularity_dpcd_data;
- }
-#endif
- return true;
-}
-
-#ifdef CONFIG_DRM_AMD_DC_DCN
static bool link_supports_psrsu(struct dc_link *link)
{
struct dc *dc = link->ctx->dc;
@@ -82,17 +39,19 @@ static bool link_supports_psrsu(struct dc_link *link)
if (dc->ctx->dce_version < DCN_VERSION_3_1)
return false;
- if (!link->dpcd_caps.psr_caps.alpm_cap ||
- !link->dpcd_caps.psr_caps.y_coordinate_required)
+ if (!is_psr_su_specific_panel(link))
return false;
- if (link->dpcd_caps.psr_caps.su_granularity_required &&
- !link->dpcd_caps.psr_caps.su_y_granularity)
+ if (!link->dpcd_caps.alpm_caps.bits.AUX_WAKE_ALPM_CAP ||
+ !link->dpcd_caps.psr_info.psr_dpcd_caps.bits.Y_COORDINATE_REQUIRED)
+ return false;
+
+ if (link->dpcd_caps.psr_info.psr_dpcd_caps.bits.SU_GRANULARITY_REQUIRED &&
+ !link->dpcd_caps.psr_info.psr2_su_y_granularity_cap)
return false;
return true;
}
-#endif
/*
* amdgpu_dm_set_psr_caps() - set link psr capabilities
@@ -107,27 +66,23 @@ void amdgpu_dm_set_psr_caps(struct dc_link *link)
if (link->type == dc_connection_none)
return;
- if (!link_get_psr_caps(link)) {
- DRM_ERROR("amdgpu: Failed to read PSR Caps!\n");
- return;
- }
-
- if (link->dpcd_caps.psr_caps.psr_version == 0) {
+ if (link->dpcd_caps.psr_info.psr_version == 0) {
link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED;
link->psr_settings.psr_feature_enabled = false;
} else {
-#ifdef CONFIG_DRM_AMD_DC_DCN
if (link_supports_psrsu(link))
link->psr_settings.psr_version = DC_PSR_VERSION_SU_1;
else
-#endif
link->psr_settings.psr_version = DC_PSR_VERSION_1;
link->psr_settings.psr_feature_enabled = true;
}
- DRM_INFO("PSR support:%d\n", link->psr_settings.psr_feature_enabled);
+ DRM_INFO("PSR support %d, DC PSR ver %d, sink PSR ver %d\n",
+ link->psr_settings.psr_feature_enabled,
+ link->psr_settings.psr_version,
+ link->dpcd_caps.psr_info.psr_version);
}
@@ -149,10 +104,8 @@ bool amdgpu_dm_link_setup_psr(struct dc_stream_state *stream)
link = stream->link;
- psr_config.psr_version = link->dpcd_caps.psr_caps.psr_version;
-
- if (psr_config.psr_version > 0) {
- psr_config.psr_exit_link_training_required = 0x1;
+ if (link->psr_settings.psr_version != DC_PSR_VERSION_UNSUPPORTED) {
+ psr_config.psr_version = link->psr_settings.psr_version;
psr_config.psr_frame_capture_indication_req = 0;
psr_config.psr_rfb_setup_time = 0x37;
psr_config.psr_sdp_transmit_line_num_deadline = 0x20;