diff options
| author | Dave Airlie <airlied@redhat.com> | 2026-01-19 06:53:41 +1000 |
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2026-01-19 06:54:46 +1000 |
| commit | c098b1aa2fa60fad42df8a1a6250099329e33311 (patch) | |
| tree | 59f8067c25de3a4e6bde2fb3bc067b6df2798ff1 /drivers/gpu/drm/amd/display | |
| parent | 971c2b68bddb87f4929e66cd4563fca78b722210 (diff) | |
| parent | 6a681cd9034587fe3550868bacfbd639d1c6891f (diff) | |
| download | linux-next-c098b1aa2fa60fad42df8a1a6250099329e33311.tar.gz linux-next-c098b1aa2fa60fad42df8a1a6250099329e33311.zip | |
Merge tag 'amd-drm-next-6.20-2026-01-16' of https://gitlab.freedesktop.org/agd5f/linux into drm-next
amd-drm-next-6.20-2026-01-16:
amdgpu:
- SR-IOV fixes
- Rework SMU mailbox handling
- Drop MMIO_REMAP domain
- UserQ fixes
- MES cleanups
- Panel Replay updates
- HDMI fixes
- Backlight fixes
- SMU 14.x fixes
- SMU 15 updates
amdkfd:
- Fix a memory leak
- Fixes for systems with non-4K pages
- LDS/Scratch cleanup
- MES process eviction fix
Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Alex Deucher <alexander.deucher@amd.com>
Link: https://patch.msgid.link/20260116202609.23107-1-alexander.deucher@amd.com
Diffstat (limited to 'drivers/gpu/drm/amd/display')
35 files changed, 796 insertions, 451 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 06b97029001b..cb13a2b0de62 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1137,7 +1137,7 @@ static int amdgpu_dm_audio_component_get_eld(struct device *kdev, int port, mutex_unlock(&adev->dm.audio_lock); - DRM_DEBUG_KMS("Get ELD : idx=%d ret=%d en=%d\n", port, ret, *enabled); + drm_dbg_kms(adev_to_drm(adev), "Get ELD : idx=%d ret=%d en=%d\n", port, ret, *enabled); return ret; } @@ -1231,7 +1231,7 @@ static void amdgpu_dm_audio_eld_notify(struct amdgpu_device *adev, int pin) struct drm_audio_component *acomp = adev->dm.audio_component; if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify) { - DRM_DEBUG_KMS("Notify ELD: %d\n", pin); + drm_dbg_kms(adev_to_drm(adev), "Notify ELD: %d\n", pin); acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, pin, -1); @@ -2377,7 +2377,7 @@ static int load_dmcu_fw(struct amdgpu_device *adev) } if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) { - DRM_DEBUG_KMS("dm: DMCU firmware not supported on direct or SMU loading\n"); + drm_dbg_kms(adev_to_drm(adev), "dm: DMCU firmware not supported on direct or SMU loading\n"); return 0; } @@ -2385,7 +2385,7 @@ static int load_dmcu_fw(struct amdgpu_device *adev) "%s", fw_name_dmcu); if (r == -ENODEV) { /* DMCU firmware is not necessary, so don't raise a fuss if it's missing */ - DRM_DEBUG_KMS("dm: DMCU firmware not found\n"); + drm_dbg_kms(adev_to_drm(adev), "dm: DMCU firmware not found\n"); adev->dm.fw_dmcu = NULL; return 0; } @@ -2409,7 +2409,7 @@ static int load_dmcu_fw(struct amdgpu_device *adev) adev->dm.dmcu_fw_version = le32_to_cpu(hdr->header.ucode_version); - DRM_DEBUG_KMS("PSP loading DMCU firmware\n"); + drm_dbg_kms(adev_to_drm(adev), "PSP loading DMCU firmware\n"); return 0; } @@ -4157,7 +4157,7 @@ static void schedule_hpd_rx_offload_work(struct amdgpu_device *adev, struct hpd_ offload_work->adev = adev; queue_work(offload_wq->wq, &offload_work->work); - DRM_DEBUG_KMS("queue work to handle hpd_rx offload work"); + drm_dbg_kms(adev_to_drm(adev), "queue work to handle hpd_rx offload work"); } static void handle_hpd_rx_irq(void *param) @@ -4986,7 +4986,7 @@ static void amdgpu_dm_update_backlight_caps(struct amdgpu_display_manager *dm, caps->min_input_signal < 0 || spread > AMDGPU_DM_DEFAULT_MAX_BACKLIGHT || spread < AMDGPU_DM_MIN_SPREAD) { - DRM_DEBUG_KMS("DM: Invalid backlight caps: min=%d, max=%d\n", + drm_dbg_kms(adev_to_drm(dm->adev), "DM: Invalid backlight caps: min=%d, max=%d\n", caps->min_input_signal, caps->max_input_signal); caps->caps_valid = false; } @@ -5279,6 +5279,8 @@ amdgpu_dm_register_backlight_device(struct amdgpu_dm_connector *aconnector) struct amdgpu_dm_backlight_caps *caps; char bl_name[16]; int min, max; + int real_brightness; + int init_brightness; if (aconnector->bl_idx == -1) return; @@ -5303,6 +5305,8 @@ amdgpu_dm_register_backlight_device(struct amdgpu_dm_connector *aconnector) } else props.brightness = props.max_brightness = MAX_BACKLIGHT_LEVEL; + init_brightness = props.brightness; + if (caps->data_points && !(amdgpu_dc_debug_mask & DC_DISABLE_CUSTOM_BRIGHTNESS_CURVE)) { drm_info(drm, "Using custom brightness curve\n"); props.scale = BACKLIGHT_SCALE_NON_LINEAR; @@ -5321,8 +5325,20 @@ amdgpu_dm_register_backlight_device(struct amdgpu_dm_connector *aconnector) if (IS_ERR(dm->backlight_dev[aconnector->bl_idx])) { drm_err(drm, "DM: Backlight registration failed!\n"); dm->backlight_dev[aconnector->bl_idx] = NULL; - } else + } else { + /* + * dm->brightness[x] can be inconsistent just after startup until + * ops.get_brightness is called. + */ + real_brightness = + amdgpu_dm_backlight_ops.get_brightness(dm->backlight_dev[aconnector->bl_idx]); + + if (real_brightness != init_brightness) { + dm->actual_brightness[aconnector->bl_idx] = real_brightness; + dm->brightness[aconnector->bl_idx] = real_brightness; + } drm_dbg_driver(drm, "DM: Registered Backlight device: %s\n", bl_name); + } } static int initialize_plane(struct amdgpu_display_manager *dm, @@ -5515,7 +5531,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) } break; default: - DRM_DEBUG_KMS("Unsupported DCN IP version for outbox: 0x%X\n", + drm_dbg_kms(adev_to_drm(adev), "Unsupported DCN IP version for outbox: 0x%X\n", amdgpu_ip_version(adev, DCE_HWIP, 0)); } @@ -5639,7 +5655,8 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) if (psr_feature_enabled) { amdgpu_dm_set_psr_caps(link); - drm_info(adev_to_drm(adev), "PSR support %d, DC PSR ver %d, sink PSR ver %d DPCD caps 0x%x su_y_granularity %d\n", + drm_info(adev_to_drm(adev), "%s: PSR support %d, DC PSR ver %d, sink PSR ver %d DPCD caps 0x%x su_y_granularity %d\n", + aconnector->base.name, link->psr_settings.psr_feature_enabled, link->psr_settings.psr_version, link->dpcd_caps.psr_info.psr_version, @@ -6417,7 +6434,8 @@ ffu: &flip_addrs->dirty_rect_count, true); } -static void update_stream_scaling_settings(const struct drm_display_mode *mode, +static void update_stream_scaling_settings(struct drm_device *dev, + const struct drm_display_mode *mode, const struct dm_connector_state *dm_state, struct dc_stream_state *stream) { @@ -6467,8 +6485,8 @@ static void update_stream_scaling_settings(const struct drm_display_mode *mode, stream->src = src; stream->dst = dst; - DRM_DEBUG_KMS("Destination Rectangle x:%d y:%d width:%d height:%d\n", - dst.x, dst.y, dst.width, dst.height); + drm_dbg_kms(dev, "Destination Rectangle x:%d y:%d width:%d height:%d\n", + dst.x, dst.y, dst.width, dst.height); } @@ -7356,7 +7374,7 @@ create_stream_for_sink(struct drm_connector *connector, apply_dsc_policy_for_stream(aconnector, sink, stream, &dsc_caps); #endif - update_stream_scaling_settings(&mode, dm_state, stream); + update_stream_scaling_settings(dev, &mode, dm_state, stream); fill_audio_info( &stream->audio_info, @@ -8091,7 +8109,7 @@ create_validate_stream_for_sink(struct drm_connector *connector, dc_result = dm_validate_stream_and_context(adev->dm.dc, stream); if (dc_result != DC_OK) { - DRM_DEBUG_KMS("Pruned mode %d x %d (clk %d) %s %s -- %s\n", + drm_dbg_kms(connector->dev, "Pruned mode %d x %d (clk %d) %s %s -- %s\n", drm_mode->hdisplay, drm_mode->vdisplay, drm_mode->clock, @@ -8443,7 +8461,7 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder, drm_dp_atomic_find_time_slots(state, mst_mgr, mst_port, dm_new_connector_state->pbn); if (dm_new_connector_state->vcpi_slots < 0) { - DRM_DEBUG_ATOMIC("failed finding vcpi slots: %d\n", (int)dm_new_connector_state->vcpi_slots); + drm_dbg_atomic(connector->dev, "failed finding vcpi slots: %d\n", (int)dm_new_connector_state->vcpi_slots); return dm_new_connector_state->vcpi_slots; } return 0; @@ -8943,9 +8961,18 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm, mutex_init(&aconnector->hpd_lock); mutex_init(&aconnector->handle_mst_msg_ready); - aconnector->hdmi_hpd_debounce_delay_ms = AMDGPU_DM_HDMI_HPD_DEBOUNCE_MS; - INIT_DELAYED_WORK(&aconnector->hdmi_hpd_debounce_work, hdmi_hpd_debounce_work); - aconnector->hdmi_prev_sink = NULL; + /* + * If HDMI HPD debounce delay is set, use the minimum between selected + * value and AMDGPU_DM_MAX_HDMI_HPD_DEBOUNCE_MS + */ + if (amdgpu_hdmi_hpd_debounce_delay_ms) { + aconnector->hdmi_hpd_debounce_delay_ms = min(amdgpu_hdmi_hpd_debounce_delay_ms, + AMDGPU_DM_MAX_HDMI_HPD_DEBOUNCE_MS); + INIT_DELAYED_WORK(&aconnector->hdmi_hpd_debounce_work, hdmi_hpd_debounce_work); + aconnector->hdmi_prev_sink = NULL; + } else { + aconnector->hdmi_hpd_debounce_delay_ms = 0; + } /* * configure support HPD hot plug connector_>polled default value is 0 @@ -9627,7 +9654,7 @@ static void update_freesync_state_on_stream( new_stream->allow_freesync = mod_freesync_get_freesync_enabled(&vrr_params); if (new_crtc_state->freesync_vrr_info_changed) - DRM_DEBUG_KMS("VRR packet update: crtc=%u enabled=%d state=%d", + drm_dbg_kms(adev_to_drm(adev), "VRR packet update: crtc=%u enabled=%d state=%d", new_crtc_state->base.crtc->base.id, (int)new_crtc_state->base.vrr_enabled, (int)vrr_params.state); @@ -10893,7 +10920,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) stream_update.stream = dm_new_crtc_state->stream; if (scaling_changed) { - update_stream_scaling_settings(&dm_new_con_state->base.crtc->mode, + update_stream_scaling_settings(dev, &dm_new_con_state->base.crtc->mode, dm_new_con_state, dm_new_crtc_state->stream); stream_update.src = dm_new_crtc_state->stream->src; @@ -11573,7 +11600,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm, dc_stream_retain(new_stream); - DRM_DEBUG_ATOMIC("Enabling DRM crtc: %d\n", + drm_dbg_atomic(adev_to_drm(adev), "Enabling DRM crtc: %d\n", crtc->base.id); if (dc_state_add_stream( @@ -11612,7 +11639,7 @@ skip_modeset: /* Scaling or underscan settings */ if (is_scaling_state_different(dm_old_conn_state, dm_new_conn_state) || drm_atomic_crtc_needs_modeset(new_crtc_state)) - update_stream_scaling_settings( + update_stream_scaling_settings(adev_to_drm(adev), &new_crtc_state->mode, dm_new_conn_state, dm_new_crtc_state->stream); /* ABM settings */ @@ -11803,14 +11830,14 @@ static int dm_check_cursor_fb(struct amdgpu_crtc *new_acrtc, if (fb->width > new_acrtc->max_cursor_width || fb->height > new_acrtc->max_cursor_height) { - DRM_DEBUG_ATOMIC("Bad cursor FB size %dx%d\n", + drm_dbg_atomic(adev_to_drm(adev), "Bad cursor FB size %dx%d\n", new_plane_state->fb->width, new_plane_state->fb->height); return -EINVAL; } if (new_plane_state->src_w != fb->width << 16 || new_plane_state->src_h != fb->height << 16) { - DRM_DEBUG_ATOMIC("Cropping not supported for cursor plane\n"); + drm_dbg_atomic(adev_to_drm(adev), "Cropping not supported for cursor plane\n"); return -EINVAL; } @@ -11818,7 +11845,7 @@ static int dm_check_cursor_fb(struct amdgpu_crtc *new_acrtc, pitch = fb->pitches[0] / fb->format->cpp[0]; if (fb->width != pitch) { - DRM_DEBUG_ATOMIC("Cursor FB width %d doesn't match pitch %d", + drm_dbg_atomic(adev_to_drm(adev), "Cursor FB width %d doesn't match pitch %d", fb->width, pitch); return -EINVAL; } @@ -11830,7 +11857,7 @@ static int dm_check_cursor_fb(struct amdgpu_crtc *new_acrtc, /* FB pitch is supported by cursor plane */ break; default: - DRM_DEBUG_ATOMIC("Bad cursor FB pitch %d px\n", pitch); + drm_dbg_atomic(adev_to_drm(adev), "Bad cursor FB pitch %d px\n", pitch); return -EINVAL; } @@ -11848,7 +11875,7 @@ static int dm_check_cursor_fb(struct amdgpu_crtc *new_acrtc, AMDGPU_TILING_GET(afb->tiling_flags, MICRO_TILE_MODE) == 0; } if (!linear) { - DRM_DEBUG_ATOMIC("Cursor FB not linear"); + drm_dbg_atomic(adev_to_drm(adev), "Cursor FB not linear"); return -EINVAL; } } @@ -11875,7 +11902,7 @@ static int dm_check_native_cursor_state(struct drm_crtc *new_plane_crtc, new_acrtc = to_amdgpu_crtc(new_plane_crtc); if (new_plane_state->src_x != 0 || new_plane_state->src_y != 0) { - DRM_DEBUG_ATOMIC("Cropping not supported for cursor plane\n"); + drm_dbg_atomic(new_plane_crtc->dev, "Cropping not supported for cursor plane\n"); return -EINVAL; } @@ -11974,7 +12001,7 @@ static int dm_update_plane_state(struct dc *dc, if (!dm_old_crtc_state->stream) return 0; - DRM_DEBUG_ATOMIC("Disabling DRM plane: %d on DRM crtc %d\n", + drm_dbg_atomic(old_plane_crtc->dev, "Disabling DRM plane: %d on DRM crtc %d\n", plane->base.id, old_plane_crtc->base.id); ret = dm_atomic_get_state(state, &dm_state); @@ -12027,7 +12054,7 @@ static int dm_update_plane_state(struct dc *dc, goto out; } - DRM_DEBUG_ATOMIC("Enabling DRM plane: %d on DRM crtc %d\n", + drm_dbg_atomic(new_plane_crtc->dev, "Enabling DRM plane: %d on DRM crtc %d\n", plane->base.id, new_plane_crtc->base.id); ret = fill_dc_plane_attributes( @@ -13119,7 +13146,7 @@ static int parse_amd_vsdb(struct amdgpu_dm_connector *aconnector, amd_vsdb->version == HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_VERSION_3) { vsdb_info->replay_mode = (amd_vsdb->feature_caps & AMD_VSDB_VERSION_3_FEATURECAP_REPLAYMODE) ? true : false; vsdb_info->amd_vsdb_version = HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_VERSION_3; - DRM_DEBUG_KMS("Panel supports Replay Mode: %d\n", vsdb_info->replay_mode); + drm_dbg_kms(aconnector->base.dev, "Panel supports Replay Mode: %d\n", vsdb_info->replay_mode); return true; } 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 ab363f2f6d47..115efd8ec68b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -59,7 +59,10 @@ #define AMDGPU_HDR_MULT_DEFAULT (0x100000000LL) -#define AMDGPU_DM_HDMI_HPD_DEBOUNCE_MS 1500 +/* + * Maximum HDMI HPD debounce delay in milliseconds + */ +#define AMDGPU_DM_MAX_HDMI_HPD_DEBOUNCE_MS 5000 /* #include "include/amdgpu_dal_power_if.h" #include "amdgpu_dm_irq.h" @@ -815,6 +818,7 @@ struct amdgpu_dm_connector { int sr_skip_count; bool disallow_edp_enter_psr; + bool disallow_edp_enter_replay; /* Record progress status of mst*/ uint8_t mst_status; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c index 327b20055729..5851f2d55dde 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c @@ -32,6 +32,7 @@ #include "dc.h" #include "amdgpu_securedisplay.h" #include "amdgpu_dm_psr.h" +#include "amdgpu_dm_replay.h" static const char *const pipe_crc_sources[] = { "none", @@ -502,6 +503,7 @@ int amdgpu_dm_crtc_configure_crc_source(struct drm_crtc *crtc, { struct amdgpu_device *adev = drm_to_adev(crtc->dev); struct dc_stream_state *stream_state = dm_crtc_state->stream; + struct amdgpu_dm_connector *aconnector = NULL; bool enable = amdgpu_dm_is_valid_crc_source(source); int ret = 0; @@ -509,11 +511,22 @@ int amdgpu_dm_crtc_configure_crc_source(struct drm_crtc *crtc, if (!stream_state) return -EINVAL; + /* Get connector from stream */ + aconnector = (struct amdgpu_dm_connector *)stream_state->dm_stream_context; + mutex_lock(&adev->dm.dc_lock); - /* For PSR1, check that the panel has exited PSR */ - if (stream_state->link->psr_settings.psr_version < DC_PSR_VERSION_SU_1) - amdgpu_dm_psr_wait_disable(stream_state); + + if (enable) { + /* For PSR1, check that the panel has exited PSR */ + if (stream_state->link->psr_settings.psr_version < DC_PSR_VERSION_SU_1) + amdgpu_dm_psr_wait_disable(stream_state); + + /* Set flag to disallow enter replay when CRC source is enabled */ + if (aconnector) + aconnector->disallow_edp_enter_replay = true; + amdgpu_dm_replay_disable(stream_state); + } /* Enable or disable CRTC CRC generation */ if (dm_is_crc_source_crtc(source) || source == AMDGPU_DM_PIPE_CRC_SOURCE_NONE) { @@ -536,6 +549,12 @@ int amdgpu_dm_crtc_configure_crc_source(struct drm_crtc *crtc, DYN_EXPANSION_AUTO); } + if (!enable) { + /* Clear flag to allow enter replay when CRC source is disabled */ + if (aconnector) + aconnector->disallow_edp_enter_replay = false; + } + unlock: mutex_unlock(&adev->dm.dc_lock); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_replay.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_replay.c index da94e3544b65..8c150b001105 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_replay.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_replay.c @@ -154,14 +154,21 @@ bool amdgpu_dm_replay_enable(struct dc_stream_state *stream, bool wait) { bool replay_active = true; struct dc_link *link = NULL; + struct amdgpu_dm_connector *aconnector = NULL; if (stream == NULL) return false; + /* Check if replay is disabled by connector flag */ + aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context; + if (!aconnector || aconnector->disallow_edp_enter_replay) { + return false; + } + link = stream->link; if (link) { - link->dc->link_srv->edp_setup_replay(link, stream); + link->dc->link_srv->dp_setup_replay(link, stream); link->dc->link_srv->edp_set_coasting_vtotal(link, stream->timing.v_total, 0); DRM_DEBUG_DRIVER("Enabling replay...\n"); link->dc->link_srv->edp_set_replay_allow_active(link, &replay_active, wait, false, NULL); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 57f6a4c8afff..aba5ad2a7a33 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -7246,6 +7246,14 @@ static bool update_planes_and_stream_prepare_v3_intermediate_seamless( ); } +static void transition_countdown_init(struct dc *dc) +{ + dc->check_config.transition_countdown_to_steady_state = + dc->debug.num_fast_flips_to_steady_state_override ? + dc->debug.num_fast_flips_to_steady_state_override : + NUM_FAST_FLIPS_TO_STEADY_STATE; +} + static bool update_planes_and_stream_prepare_v3( struct dc_update_scratch_space *scratch ) @@ -7305,9 +7313,17 @@ static bool update_planes_and_stream_prepare_v3( ); if (seamless) { scratch->flow = UPDATE_V3_FLOW_NEW_CONTEXT_SEAMLESS; + if (scratch->dc->check_config.deferred_transition_state) + /* reset countdown as steady state not reached */ + transition_countdown_init(scratch->dc); return true; } + if (!scratch->dc->debug.disable_deferred_minimal_transitions) { + scratch->dc->check_config.deferred_transition_state = true; + transition_countdown_init(scratch->dc); + } + scratch->intermediate_context = create_minimal_transition_state( scratch->dc, scratch->new_context, @@ -7351,7 +7367,8 @@ static bool update_planes_and_stream_prepare_v3( static void update_planes_and_stream_execute_v3_commit( const struct dc_update_scratch_space *scratch, bool intermediate_update, - bool intermediate_context + bool intermediate_context, + bool use_stream_update ) { commit_planes_for_stream( @@ -7359,7 +7376,7 @@ static void update_planes_and_stream_execute_v3_commit( intermediate_update ? scratch->intermediate_updates : scratch->surface_updates, intermediate_update ? scratch->intermediate_count : scratch->surface_count, scratch->stream, - intermediate_context ? NULL : scratch->stream_update, + use_stream_update ? scratch->stream_update : NULL, intermediate_context ? UPDATE_TYPE_FULL : scratch->update_type, // `dc->current_state` only used in `NO_NEW_CONTEXT`, where it is equal to `new_context` intermediate_context ? scratch->intermediate_context : scratch->new_context @@ -7385,15 +7402,16 @@ static void update_planes_and_stream_execute_v3( case UPDATE_V3_FLOW_NO_NEW_CONTEXT_CONTEXT_FULL: case UPDATE_V3_FLOW_NEW_CONTEXT_SEAMLESS: - update_planes_and_stream_execute_v3_commit(scratch, false, false); + update_planes_and_stream_execute_v3_commit(scratch, false, false, true); break; case UPDATE_V3_FLOW_NEW_CONTEXT_MINIMAL_NEW: - update_planes_and_stream_execute_v3_commit(scratch, false, true); + update_planes_and_stream_execute_v3_commit(scratch, false, true, + scratch->dc->check_config.deferred_transition_state); break; case UPDATE_V3_FLOW_NEW_CONTEXT_MINIMAL_CURRENT: - update_planes_and_stream_execute_v3_commit(scratch, true, true); + update_planes_and_stream_execute_v3_commit(scratch, true, true, false); break; case UPDATE_V3_FLOW_INVALID: @@ -7402,13 +7420,6 @@ static void update_planes_and_stream_execute_v3( } } -static void update_planes_and_stream_cleanup_v3_new_context( - struct dc_update_scratch_space *scratch -) -{ - swap_and_release_current_context(scratch->dc, scratch->new_context, scratch->stream); -} - static void update_planes_and_stream_cleanup_v3_release_minimal( struct dc_update_scratch_space *scratch, bool backup @@ -7439,17 +7450,23 @@ static bool update_planes_and_stream_cleanup_v3( switch (scratch->flow) { case UPDATE_V3_FLOW_NO_NEW_CONTEXT_CONTEXT_FAST: case UPDATE_V3_FLOW_NO_NEW_CONTEXT_CONTEXT_FULL: - // No cleanup required + if (scratch->dc->check_config.transition_countdown_to_steady_state) + scratch->dc->check_config.transition_countdown_to_steady_state--; break; case UPDATE_V3_FLOW_NEW_CONTEXT_SEAMLESS: - update_planes_and_stream_cleanup_v3_new_context(scratch); + swap_and_release_current_context(scratch->dc, scratch->new_context, scratch->stream); break; case UPDATE_V3_FLOW_NEW_CONTEXT_MINIMAL_NEW: update_planes_and_stream_cleanup_v3_intermediate(scratch, false); - scratch->flow = UPDATE_V3_FLOW_NEW_CONTEXT_SEAMLESS; - return true; + if (scratch->dc->check_config.deferred_transition_state) { + dc_state_release(scratch->new_context); + } else { + scratch->flow = UPDATE_V3_FLOW_NEW_CONTEXT_SEAMLESS; + return true; + } + break; case UPDATE_V3_FLOW_NEW_CONTEXT_MINIMAL_CURRENT: update_planes_and_stream_cleanup_v3_intermediate(scratch, true); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c index a8d7228907c2..7bb4504889be 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c @@ -493,24 +493,24 @@ bool dc_link_get_replay_state(const struct dc_link *link, uint64_t *state) bool dc_link_set_pr_enable(struct dc_link *link, bool enable) { - return link->dc->link_srv->edp_pr_enable(link, enable); + return link->dc->link_srv->dp_pr_enable(link, enable); } bool dc_link_update_pr_state(struct dc_link *link, struct dmub_cmd_pr_update_state_data *update_state_data) { - return link->dc->link_srv->edp_pr_update_state(link, update_state_data); + return link->dc->link_srv->dp_pr_update_state(link, update_state_data); } bool dc_link_set_pr_general_cmd(struct dc_link *link, struct dmub_cmd_pr_general_cmd_data *general_cmd_data) { - return link->dc->link_srv->edp_pr_set_general_cmd(link, general_cmd_data); + return link->dc->link_srv->dp_pr_set_general_cmd(link, general_cmd_data); } bool dc_link_get_pr_state(const struct dc_link *link, uint64_t *state) { - return link->dc->link_srv->edp_pr_get_state(link, state); + return link->dc->link_srv->dp_pr_get_state(link, state); } bool dc_link_wait_for_t12(struct dc_link *link) @@ -549,4 +549,3 @@ void dc_link_get_alpm_support(struct dc_link *link, { link->dc->link_srv->edp_get_alpm_support(link, auxless_support, auxwake_support); } - diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 69fa7fc02fa8..fc3dd1054710 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -63,7 +63,7 @@ struct dcn_dsc_reg_state; struct dcn_optc_reg_state; struct dcn_dccg_reg_state; -#define DC_VER "3.2.364" +#define DC_VER "3.2.365" /** * MAX_SURFACES - representative of the upper bound of surfaces that can be piped to a single CRTC diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c index 602655dd1323..2dc6ae6b5bea 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c @@ -999,6 +999,7 @@ void dc_dmub_srv_log_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv) DC_LOG_DEBUG(" is_traceport_en : %d", dc_dmub_srv->dmub->debug.is_traceport_en); DC_LOG_DEBUG(" is_cw0_en : %d", dc_dmub_srv->dmub->debug.is_cw0_enabled); DC_LOG_DEBUG(" is_cw6_en : %d", dc_dmub_srv->dmub->debug.is_cw6_enabled); + DC_LOG_DEBUG(" is_pwait : %d", dc_dmub_srv->dmub->debug.is_pwait); } static bool dc_dmub_should_update_cursor_data(struct pipe_ctx *pipe_ctx) diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h index 273610d85438..5e3646b7550c 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h @@ -1167,6 +1167,25 @@ union dpcd_panel_replay_capability_supported { unsigned char raw; }; +union dpcd_panel_replay_capability { + struct { + unsigned char RESERVED :2; + unsigned char DSC_DECODE_NOT_SUPPORTED :1; + unsigned char ASYNC_VIDEO_TIMING_NOT_SUPPORTED :1; + unsigned char DSC_CRC_OF_MULTI_SU_SUPPORTED :1; + unsigned char PR_SU_GRANULARITY_NEEDED :1; + unsigned char SU_Y_GRANULARITY_EXT_CAP_SUPPORTED :1; + unsigned char LINK_OFF_SUPPORTED_IN_PR_ACTIVE :1; + } bits; + unsigned char raw; +}; + +struct dpcd_panel_replay_selective_update_info { + uint16_t pr_su_x_granularity; + uint8_t pr_su_y_granularity; + uint16_t pr_su_y_granularity_extended_caps; +}; + enum dpcd_downstream_port_max_bpc { DOWN_STREAM_MAX_8BPC = 0, DOWN_STREAM_MAX_10BPC, @@ -1290,7 +1309,9 @@ struct dpcd_caps { struct edp_psr_info psr_info; struct replay_info pr_info; - union dpcd_panel_replay_capability_supported pr_caps_supported; + union dpcd_panel_replay_capability_supported vesa_replay_caps_supported; + union dpcd_panel_replay_capability vesa_replay_caps; + struct dpcd_panel_replay_selective_update_info vesa_replay_su_info; uint16_t edp_oled_emission_rate; union dp_receive_port0_cap receive_port0_cap; /* Indicates the number of SST links supported by MSO (Multi-Stream Output) */ @@ -1402,6 +1423,17 @@ union dpcd_sink_active_vtotal_control_mode { unsigned char raw; }; +union pr_error_status { + struct { + unsigned char LINK_CRC_ERROR :1; + unsigned char RFB_STORAGE_ERROR :1; + unsigned char VSC_SDP_ERROR :1; + unsigned char ASSDP_MISSING_ERROR :1; + unsigned char RESERVED :4; + } bits; + unsigned char raw; +}; + union psr_error_status { struct { unsigned char LINK_CRC_ERROR :1; diff --git a/drivers/gpu/drm/amd/display/dc/dc_hdmi_types.h b/drivers/gpu/drm/amd/display/dc/dc_hdmi_types.h index b015e80672ec..fcd3ab4b0045 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hdmi_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hdmi_types.h @@ -41,7 +41,7 @@ /* kHZ*/ #define DP_ADAPTOR_DVI_MAX_TMDS_CLK 165000 /* kHZ*/ -#define DP_ADAPTOR_HDMI_SAFE_MAX_TMDS_CLK 165000 +#define DP_ADAPTOR_HDMI_SAFE_MAX_TMDS_CLK 340000 struct dp_hdmi_dongle_signature_data { int8_t id[15];/* "DP-HDMI ADAPTOR"*/ diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 667852517246..cfa569a7bff1 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -491,6 +491,12 @@ struct dc_cursor_position { * for each plane. */ bool translate_by_source; + + /** + * @use_viewport_for_clip: Use viewport position for clip_x calculation + * instead of clip_rect. Required to protect against clip being overwritten + */ + bool use_viewport_for_clip; }; struct dc_cursor_mi_param { diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index b3b785f1897d..bb1387233bd8 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -1101,7 +1101,6 @@ enum replay_FW_Message_type { Replay_Set_Residency_Frameupdate_Timer, Replay_Set_Pseudo_VTotal, Replay_Disabled_Adaptive_Sync_SDP, - Replay_Set_Version, Replay_Set_General_Cmd, }; @@ -1224,6 +1223,8 @@ struct replay_settings { uint32_t replay_desync_error_fail_count; /* The frame skip number dal send to DMUB */ uint16_t frame_skip_number; + /* Current Panel Replay event */ + uint32_t replay_events; }; /* To split out "global" and "per-panel" config settings. diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c index 5bfa2b0d2afd..7116fdd4c7ec 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c @@ -69,7 +69,7 @@ bool dmub_hw_lock_mgr_does_link_require_lock(const struct dc *dc, const struct d if (link->psr_settings.psr_version == DC_PSR_VERSION_SU_1) return true; - if (link->replay_settings.replay_feature_enabled) + if (link->replay_settings.replay_feature_enabled && dc_is_embedded_signal(link->connector_signal)) return true; if (link->psr_settings.psr_version == DC_PSR_VERSION_1) { diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c index cf1372aaff6c..fd8244c94687 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c @@ -387,19 +387,6 @@ static void dmub_replay_send_cmd(struct dmub_replay *dmub, cmd.replay_disabled_adaptive_sync_sdp.data.force_disabled = cmd_element->disabled_adaptive_sync_sdp_data.force_disabled; break; - case Replay_Set_Version: - //Header - cmd.replay_set_version.header.sub_type = - DMUB_CMD__REPLAY_SET_VERSION; - cmd.replay_set_version.header.payload_bytes = - sizeof(struct dmub_rb_cmd_replay_set_version) - - sizeof(struct dmub_cmd_header); - //Cmd Body - cmd.replay_set_version.replay_set_version_data.panel_inst = - cmd_element->version_data.panel_inst; - cmd.replay_set_version.replay_set_version_data.version = - cmd_element->version_data.version; - break; case Replay_Set_General_Cmd: //Header cmd.replay_set_general_cmd.header.sub_type = diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c index fa62e40a9858..8a23763ca98e 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c @@ -3666,7 +3666,11 @@ void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx) int y_plane = pipe_ctx->plane_state->dst_rect.y; int x_pos = pos_cpy.x; int y_pos = pos_cpy.y; - int clip_x = pipe_ctx->plane_state->clip_rect.x; + bool is_primary_plane = (pipe_ctx->plane_state->layer_index == 0); + + int clip_x = (pos_cpy.use_viewport_for_clip && is_primary_plane && + !odm_combine_on && !pipe_split_on && param.viewport.x != 0) + ? param.viewport.x : pipe_ctx->plane_state->clip_rect.x; int clip_width = pipe_ctx->plane_state->clip_rect.width; if ((pipe_ctx->top_pipe != NULL) || (pipe_ctx->bottom_pipe != NULL)) { diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c index 1271bf55dac3..2675d7dca586 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c @@ -1727,3 +1727,55 @@ void dcn35_program_cursor_offload_now(struct dc *dc, const struct pipe_ctx *pipe { dc_dmub_srv_program_cursor_now(dc, pipe); } + +static void disable_link_output_symclk_on_tx_off(struct dc_link *link, enum dp_link_encoding link_encoding) +{ + struct dc *dc = link->ctx->dc; + struct pipe_ctx *pipe_ctx = NULL; + uint8_t i; + + for (i = 0; i < MAX_PIPES; i++) { + pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; + if (pipe_ctx->stream && pipe_ctx->stream->link == link && pipe_ctx->top_pipe == NULL) { + pipe_ctx->clock_source->funcs->program_pix_clk( + pipe_ctx->clock_source, + &pipe_ctx->stream_res.pix_clk_params, + link_encoding, + &pipe_ctx->pll_settings); + break; + } + } +} + +void dcn35_disable_link_output(struct dc_link *link, + const struct link_resource *link_res, + enum signal_type signal) +{ + struct dc *dc = link->ctx->dc; + const struct link_hwss *link_hwss = get_link_hwss(link, link_res); + struct dmcu *dmcu = dc->res_pool->dmcu; + + if (signal == SIGNAL_TYPE_EDP && + link->dc->hwss.edp_backlight_control && + !link->skip_implict_edp_power_control) + link->dc->hwss.edp_backlight_control(link, false); + else if (dmcu != NULL && dmcu->funcs->lock_phy) + dmcu->funcs->lock_phy(dmcu); + + if (dc_is_tmds_signal(signal) && link->phy_state.symclk_ref_cnts.otg > 0) { + disable_link_output_symclk_on_tx_off(link, DP_UNKNOWN_ENCODING); + link->phy_state.symclk_state = SYMCLK_ON_TX_OFF; + } else { + link_hwss->disable_link_output(link, link_res, signal); + link->phy_state.symclk_state = SYMCLK_OFF_TX_OFF; + } + /* + * Add the logic to extract BOTH power up and power down sequences + * from enable/disable link output and only call edp panel control + * in enable_link_dp and disable_link_dp once. + */ + if (dmcu != NULL && dmcu->funcs->unlock_phy) + dmcu->funcs->unlock_phy(dmcu); + + dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_LINK_PHY); +} diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h index 1ff41dba556c..e3459546a908 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h @@ -108,5 +108,8 @@ void dcn35_update_cursor_offload_pipe(struct dc *dc, const struct pipe_ctx *pipe void dcn35_notify_cursor_offload_drr_update(struct dc *dc, struct dc_state *context, const struct dc_stream_state *stream); void dcn35_program_cursor_offload_now(struct dc *dc, const struct pipe_ctx *pipe); +void dcn35_disable_link_output(struct dc_link *link, + const struct link_resource *link_res, + enum signal_type signal); #endif /* __DC_HWSS_DCN35_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c index 5a66c9db2670..81bd36f3381d 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c @@ -113,7 +113,7 @@ static const struct hw_sequencer_funcs dcn35_funcs = { .enable_lvds_link_output = dce110_enable_lvds_link_output, .enable_tmds_link_output = dce110_enable_tmds_link_output, .enable_dp_link_output = dce110_enable_dp_link_output, - .disable_link_output = dcn32_disable_link_output, + .disable_link_output = dcn35_disable_link_output, .z10_restore = dcn35_z10_restore, .z10_save_init = dcn31_z10_save_init, .set_disp_pattern_generator = dcn30_set_disp_pattern_generator, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c index b7593b886dc6..22c1d5e68420 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c @@ -287,6 +287,8 @@ void dcn401_init_hw(struct dc *dc) for (i = 0; i < dc->link_count; i++) { struct dc_link *link = dc->links[i]; + if (link->ep_type != DISPLAY_ENDPOINT_PHY) + continue; if (link->link_enc->funcs->is_dig_enabled && link->link_enc->funcs->is_dig_enabled(link->link_enc) && hws->funcs.power_down) { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h index 500a601e99b5..1e6ffd86a4c0 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h @@ -333,6 +333,7 @@ struct dccg_funcs { void (*set_ref_dscclk)(struct dccg *dccg, uint32_t dsc_inst); void (*dccg_root_gate_disable_control)(struct dccg *dccg, uint32_t pipe_idx, uint32_t disable_clock_gating); void (*dccg_read_reg_state)(struct dccg *dccg, struct dcn_dccg_reg_state *dccg_reg_state); + void (*dccg_enable_global_fgcg)(struct dccg *dccg, bool enable); }; #endif //__DAL_DCCG_H__ diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_service.h b/drivers/gpu/drm/amd/display/dc/inc/link_service.h index 4b092a9ee4c6..57bb82e94942 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/link_service.h +++ b/drivers/gpu/drm/amd/display/dc/inc/link_service.h @@ -283,8 +283,6 @@ struct link_service { bool (*edp_set_replay_allow_active)(struct dc_link *dc_link, const bool *enable, bool wait, bool force_static, const unsigned int *power_opts); - bool (*edp_setup_replay)(struct dc_link *link, - const struct dc_stream_state *stream); bool (*edp_send_replay_cmd)(struct dc_link *link, enum replay_FW_Message_type msg, union dmub_replay_cmd_set *cmd_data); @@ -304,10 +302,12 @@ struct link_service { bool (*edp_receiver_ready_T9)(struct dc_link *link); bool (*edp_receiver_ready_T7)(struct dc_link *link); bool (*edp_power_alpm_dpcd_enable)(struct dc_link *link, bool enable); - bool (*edp_pr_enable)(struct dc_link *link, bool enable); - bool (*edp_pr_update_state)(struct dc_link *link, struct dmub_cmd_pr_update_state_data *update_state_data); - bool (*edp_pr_set_general_cmd)(struct dc_link *link, struct dmub_cmd_pr_general_cmd_data *general_cmd_data); - bool (*edp_pr_get_state)(const struct dc_link *link, uint64_t *state); + bool (*dp_setup_replay)(struct dc_link *link, const struct dc_stream_state *stream); + bool (*dp_pr_get_panel_inst)(const struct dc *dc, const struct dc_link *link, unsigned int *inst_out); + bool (*dp_pr_enable)(struct dc_link *link, bool enable); + bool (*dp_pr_update_state)(struct dc_link *link, struct dmub_cmd_pr_update_state_data *update_state_data); + bool (*dp_pr_set_general_cmd)(struct dc_link *link, struct dmub_cmd_pr_general_cmd_data *general_cmd_data); + bool (*dp_pr_get_state)(const struct dc_link *link, uint64_t *state); void (*edp_set_panel_power)(struct dc_link *link, bool powerOn); diff --git a/drivers/gpu/drm/amd/display/dc/link/Makefile b/drivers/gpu/drm/amd/display/dc/link/Makefile index 84c7af5fa589..84dace27daf7 100644 --- a/drivers/gpu/drm/amd/display/dc/link/Makefile +++ b/drivers/gpu/drm/amd/display/dc/link/Makefile @@ -56,7 +56,7 @@ LINK_PROTOCOLS = link_hpd.o link_ddc.o link_dpcd.o link_dp_dpia.o \ link_dp_training.o link_dp_training_8b_10b.o link_dp_training_128b_132b.o \ link_dp_training_dpia.o link_dp_training_auxless.o \ link_dp_training_fixed_vs_pe_retimer.o link_dp_phy.o link_dp_capability.o \ -link_edp_panel_control.o link_dp_irq_handler.o link_dp_dpia_bw.o +link_edp_panel_control.o link_dp_panel_replay.o link_dp_irq_handler.o link_dp_dpia_bw.o AMD_DAL_LINK_PROTOCOLS = $(addprefix $(AMDDALPATH)/dc/link/protocols/, \ $(LINK_PROTOCOLS)) diff --git a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c index 5a547d41d4a1..693d852b1c40 100644 --- a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c +++ b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c @@ -70,6 +70,7 @@ static void dp_retrain_link_dp_test(struct dc_link *link, struct dc_state *state = link->dc->current_state; struct dc_stream_update stream_update = { 0 }; bool dpms_off = false; + bool needs_divider_update = false; bool was_hpo_acquired = resource_is_hpo_acquired(link->dc->current_state); bool is_hpo_acquired; uint8_t count; @@ -79,6 +80,10 @@ static void dp_retrain_link_dp_test(struct dc_link *link, int num_streams_on_link = 0; struct dc *dc = (struct dc *)link->dc; + needs_divider_update = (link->dc->link_srv->dp_get_encoding_format(link_setting) != + link->dc->link_srv->dp_get_encoding_format((const struct dc_link_settings *) &link->cur_link_settings)) + || link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA; + udelay(100); link_get_master_pipes_with_dpms_on(link, state, &count, pipes); @@ -95,7 +100,7 @@ static void dp_retrain_link_dp_test(struct dc_link *link, pipes[i]->stream_res.tg->funcs->disable_crtc(pipes[i]->stream_res.tg); } - if (link->dc->res_pool->funcs->update_dc_state_for_encoder_switch) { + if (needs_divider_update && link->dc->res_pool->funcs->update_dc_state_for_encoder_switch) { link->dc->res_pool->funcs->update_dc_state_for_encoder_switch(link, link_setting, count, *pipes, &audio_output[0]); diff --git a/drivers/gpu/drm/amd/display/dc/link/link_detection.c b/drivers/gpu/drm/amd/display/dc/link/link_detection.c index f24365395cd9..578509e8d0e2 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_detection.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_detection.c @@ -335,7 +335,7 @@ static void query_dp_dual_mode_adaptor( /* Assume we have no valid DP passive dongle connected */ *dongle = DISPLAY_DONGLE_NONE; - sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_HDMI_SAFE_MAX_TMDS_CLK; + sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_DVI_MAX_TMDS_CLK; /* Read DP-HDMI dongle I2c (no response interpreted as DP-DVI dongle)*/ if (!i2c_read( @@ -391,6 +391,8 @@ static void query_dp_dual_mode_adaptor( } } + if (is_valid_hdmi_signature) + sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_HDMI_SAFE_MAX_TMDS_CLK; if (is_type2_dongle) { uint32_t max_tmds_clk = @@ -993,7 +995,7 @@ static bool detect_link_and_local_sink(struct dc_link *link, (link->dpcd_sink_ext_caps.bits.oled == 1)) { dpcd_set_source_specific_data(link); msleep(post_oui_delay); - set_default_brightness(link); + set_default_brightness_aux(link); } return true; diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c index 323cc0b3c09a..91742bde4dc2 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c @@ -46,6 +46,7 @@ #include "protocols/link_dp_capability.h" #include "protocols/link_dp_training.h" #include "protocols/link_edp_panel_control.h" +#include "protocols/link_dp_panel_replay.h" #include "protocols/link_dp_dpia_bw.h" #include "dm_helpers.h" @@ -2061,7 +2062,7 @@ static enum dc_status enable_link_dp(struct dc_state *state, skip_video_pattern = false; if (stream->sink_patches.oled_optimize_display_on) - set_default_brightness(link); + set_default_brightness_aux(link); if (perform_link_training_with_retries(link_settings, skip_video_pattern, @@ -2087,7 +2088,7 @@ static enum dc_status enable_link_dp(struct dc_state *state, link->dpcd_sink_ext_caps.bits.sdr_aux_backlight_control == 1 || link->dpcd_sink_ext_caps.bits.hdr_aux_backlight_control == 1) { if (!stream->sink_patches.oled_optimize_display_on) { - set_default_brightness(link); + set_default_brightness_aux(link); if (link->dpcd_sink_ext_caps.bits.oled == 1) msleep(bl_oled_enable_delay); edp_backlight_enable_aux(link, true); @@ -2529,6 +2530,9 @@ void link_set_dpms_on( link_set_dsc_enable(pipe_ctx, true); } + if (link->replay_settings.config.replay_supported && !dc_is_embedded_signal(link->connector_signal)) + dp_setup_replay(link, stream); + status = enable_link(state, pipe_ctx); if (status != DC_OK) { diff --git a/drivers/gpu/drm/amd/display/dc/link/link_factory.c b/drivers/gpu/drm/amd/display/dc/link/link_factory.c index 923517715651..5fbcf04c6251 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_factory.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_factory.c @@ -41,6 +41,7 @@ #include "protocols/link_dp_phy.h" #include "protocols/link_dp_training.h" #include "protocols/link_edp_panel_control.h" +#include "protocols/link_dp_panel_replay.h" #include "protocols/link_hpd.h" #include "gpio_service_interface.h" #include "atomfirmware.h" @@ -214,7 +215,6 @@ static void construct_link_service_edp_panel_control(struct link_service *link_s link_srv->edp_get_replay_state = edp_get_replay_state; link_srv->edp_set_replay_allow_active = edp_set_replay_allow_active; - link_srv->edp_setup_replay = edp_setup_replay; link_srv->edp_send_replay_cmd = edp_send_replay_cmd; link_srv->edp_set_coasting_vtotal = edp_set_coasting_vtotal; link_srv->edp_replay_residency = edp_replay_residency; @@ -228,13 +228,21 @@ static void construct_link_service_edp_panel_control(struct link_service *link_s link_srv->edp_receiver_ready_T9 = edp_receiver_ready_T9; link_srv->edp_receiver_ready_T7 = edp_receiver_ready_T7; link_srv->edp_power_alpm_dpcd_enable = edp_power_alpm_dpcd_enable; - link_srv->edp_pr_enable = edp_pr_enable; - link_srv->edp_pr_update_state = edp_pr_update_state; - link_srv->edp_pr_set_general_cmd = edp_pr_set_general_cmd; - link_srv->edp_pr_get_state = edp_pr_get_state; link_srv->edp_set_panel_power = edp_set_panel_power; } +/* link dp panel replay implements DP panel replay functionality. + */ +static void construct_link_service_dp_panel_replay(struct link_service *link_srv) +{ + link_srv->dp_setup_replay = dp_setup_replay; + link_srv->dp_pr_get_panel_inst = dp_pr_get_panel_inst; + link_srv->dp_pr_enable = dp_pr_enable; + link_srv->dp_pr_update_state = dp_pr_update_state; + link_srv->dp_pr_set_general_cmd = dp_pr_set_general_cmd; + link_srv->dp_pr_get_state = dp_pr_get_state; +} + /* link dp cts implements dp compliance test automation protocols and manual * testing interfaces for debugging and certification purpose. */ @@ -287,6 +295,7 @@ static void construct_link_service(struct link_service *link_srv) construct_link_service_dp_phy_or_dpia(link_srv); construct_link_service_dp_irq_handler(link_srv); construct_link_service_edp_panel_control(link_srv); + construct_link_service_dp_panel_replay(link_srv); construct_link_service_dp_cts(link_srv); construct_link_service_dp_trace(link_srv); } diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c index 54c417928b61..cdc7587cf0b6 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c @@ -1593,6 +1593,41 @@ static bool dpcd_read_sink_ext_caps(struct dc_link *link) return true; } +static void retrieve_vesa_replay_su_info(struct dc_link *link) +{ + uint8_t dpcd_data = 0; + + core_link_read_dpcd(link, + DP_PR_SU_X_GRANULARITY_LOW, + &dpcd_data, + sizeof(dpcd_data)); + link->dpcd_caps.vesa_replay_su_info.pr_su_x_granularity = dpcd_data; + + core_link_read_dpcd(link, + DP_PR_SU_X_GRANULARITY_HIGH, + &dpcd_data, + sizeof(dpcd_data)); + link->dpcd_caps.vesa_replay_su_info.pr_su_x_granularity |= (dpcd_data << 8); + + core_link_read_dpcd(link, + DP_PR_SU_Y_GRANULARITY, + &dpcd_data, + sizeof(dpcd_data)); + link->dpcd_caps.vesa_replay_su_info.pr_su_y_granularity = dpcd_data; + + core_link_read_dpcd(link, + DP_PR_SU_Y_GRANULARITY_EXTENDED_CAP_LOW, + &dpcd_data, + sizeof(dpcd_data)); + link->dpcd_caps.vesa_replay_su_info.pr_su_y_granularity_extended_caps = dpcd_data; + + core_link_read_dpcd(link, + DP_PR_SU_Y_GRANULARITY_EXTENDED_CAP_HIGH, + &dpcd_data, + sizeof(dpcd_data)); + link->dpcd_caps.vesa_replay_su_info.pr_su_y_granularity_extended_caps |= (dpcd_data << 8); +} + enum dc_status dp_retrieve_lttpr_cap(struct dc_link *link) { uint8_t lttpr_dpcd_data[10] = {0}; @@ -2094,8 +2129,16 @@ static bool retrieve_link_cap(struct dc_link *link) core_link_read_dpcd(link, DP_PANEL_REPLAY_CAPABILITY_SUPPORT, - &link->dpcd_caps.pr_caps_supported.raw, - sizeof(link->dpcd_caps.pr_caps_supported.raw)); + &link->dpcd_caps.vesa_replay_caps_supported.raw, + sizeof(link->dpcd_caps.vesa_replay_caps_supported.raw)); + + core_link_read_dpcd(link, + DP_PANEL_REPLAY_CAPABILITY, + &link->dpcd_caps.vesa_replay_caps.raw, + sizeof(link->dpcd_caps.vesa_replay_caps.raw)); + + /* Read VESA Panel Replay Selective Update caps */ + retrieve_vesa_replay_su_info(link); /* Read DP tunneling information. */ status = dpcd_get_tunneling_device_data(link); @@ -2167,7 +2210,7 @@ void detect_edp_sink_caps(struct dc_link *link) link->dpcd_caps.set_power_state_capable_edp = (general_edp_cap & DP_EDP_SET_POWER_CAP) ? true : false; - set_default_brightness(link); + set_default_brightness_aux(link); core_link_read_dpcd(link, DP_EDP_DPCD_REV, &link->dpcd_caps.edp_rev, diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c index 4b01ab0a5a7f..cc18a3bebef2 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c @@ -34,10 +34,12 @@ #include "link_dp_training.h" #include "link_dp_capability.h" #include "link_edp_panel_control.h" +#include "link_dp_panel_replay.h" #include "link/accessories/link_dp_trace.h" #include "link/link_dpms.h" #include "dm_helpers.h" #include "link_dp_dpia_bw.h" +#include "link_dp_panel_replay.h" #define DC_LOGGER \ link->ctx->logger @@ -185,6 +187,42 @@ static bool handle_hpd_irq_psr_sink(struct dc_link *link) return false; } +static void handle_hpd_irq_vesa_replay_sink(struct dc_link *link) +{ + union pr_error_status pr_error_status = {0}; + + if (!link->replay_settings.replay_feature_enabled || + link->replay_settings.config.replay_version != DC_VESA_PANEL_REPLAY) + return; + + dm_helpers_dp_read_dpcd( + link->ctx, + link, + DP_PR_ERROR_STATUS, + &pr_error_status.raw, + sizeof(pr_error_status.raw)); + + if (pr_error_status.bits.LINK_CRC_ERROR || + pr_error_status.bits.RFB_STORAGE_ERROR || + pr_error_status.bits.VSC_SDP_ERROR || + pr_error_status.bits.ASSDP_MISSING_ERROR) { + + /* Acknowledge and clear error bits */ + dm_helpers_dp_write_dpcd( + link->ctx, + link, + DP_PR_ERROR_STATUS, /*DpcdAddress_PR_Error_Status*/ + &pr_error_status.raw, + sizeof(pr_error_status.raw)); + + /* Replay error, disable and re-enable Replay */ + if (link->replay_settings.replay_allow_active) { + dp_pr_enable(link, false); + dp_pr_enable(link, true); + } + } +} + static void handle_hpd_irq_replay_sink(struct dc_link *link) { union dpcd_replay_configuration replay_configuration = {0}; @@ -196,6 +234,11 @@ static void handle_hpd_irq_replay_sink(struct dc_link *link) if (!link->replay_settings.replay_feature_enabled) return; + if (link->replay_settings.config.replay_version != DC_FREESYNC_REPLAY) { + handle_hpd_irq_vesa_replay_sink(link); + return; + } + while (retries < 10) { ret = dm_helpers_dp_read_dpcd( link->ctx, diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_panel_replay.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_panel_replay.c new file mode 100644 index 000000000000..be441851d876 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_panel_replay.c @@ -0,0 +1,343 @@ +/* + * Copyright 2025 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "link_dp_panel_replay.h" +#include "link_edp_panel_control.h" +#include "link_dpcd.h" +#include "dm_helpers.h" +#include "dc/dc_dmub_srv.h" +#include "dce/dmub_replay.h" + +#define DC_LOGGER \ + link->ctx->logger + +#define DP_SINK_PR_ENABLE_AND_CONFIGURATION 0x37B + +static bool dp_setup_panel_replay(struct dc_link *link, const struct dc_stream_state *stream) +{ + /* To-do: Setup Replay */ + struct dc *dc; + struct dmub_replay *replay; + int i; + unsigned int panel_inst; + struct replay_context replay_context = { 0 }; + unsigned int lineTimeInNs = 0; + + union panel_replay_enable_and_configuration_1 pr_config_1 = { 0 }; + union panel_replay_enable_and_configuration_2 pr_config_2 = { 0 }; + + union dpcd_alpm_configuration alpm_config; + + replay_context.controllerId = CONTROLLER_ID_UNDEFINED; + + if (!link) + return false; + + //Clear Panel Replay enable & config + dm_helpers_dp_write_dpcd(link->ctx, link, + DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_1, + (uint8_t *)&(pr_config_1.raw), sizeof(uint8_t)); + + dm_helpers_dp_write_dpcd(link->ctx, link, + DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_2, + (uint8_t *)&(pr_config_2.raw), sizeof(uint8_t)); + + if (!(link->replay_settings.config.replay_supported)) + return false; + + dc = link->ctx->dc; + + //not sure should keep or not + replay = dc->res_pool->replay; + + if (!replay) + return false; + + if (!dp_pr_get_panel_inst(dc, link, &panel_inst)) + return false; + + replay_context.aux_inst = link->ddc->ddc_pin->hw_info.ddc_channel; + replay_context.digbe_inst = link->link_enc->transmitter; + replay_context.digfe_inst = link->link_enc->preferred_engine; + + for (i = 0; i < MAX_PIPES; i++) { + if (dc->current_state->res_ctx.pipe_ctx[i].stream + == stream) { + /* dmcu -1 for all controller id values, + * therefore +1 here + */ + replay_context.controllerId = + dc->current_state->res_ctx.pipe_ctx[i].stream_res.tg->inst + 1; + break; + } + } + + lineTimeInNs = + ((stream->timing.h_total * 1000000) / + (stream->timing.pix_clk_100hz / 10)) + 1; + + replay_context.line_time_in_ns = lineTimeInNs; + + link->replay_settings.replay_feature_enabled = dp_pr_copy_settings(link, &replay_context); + + if (link->replay_settings.replay_feature_enabled) { + if (dc_is_embedded_signal(link->connector_signal)) { + pr_config_1.bits.PANEL_REPLAY_ENABLE = 1; + pr_config_1.bits.PANEL_REPLAY_CRC_ENABLE = 1; + pr_config_1.bits.IRQ_HPD_ASSDP_MISSING = 1; + pr_config_1.bits.IRQ_HPD_VSCSDP_UNCORRECTABLE_ERROR = 1; + pr_config_1.bits.IRQ_HPD_RFB_ERROR = 1; + pr_config_1.bits.IRQ_HPD_ACTIVE_FRAME_CRC_ERROR = 1; + pr_config_1.bits.PANEL_REPLAY_SELECTIVE_UPDATE_ENABLE = 1; + pr_config_1.bits.PANEL_REPLAY_EARLY_TRANSPORT_ENABLE = 1; + } else { + pr_config_1.bits.PANEL_REPLAY_ENABLE = 1; + } + + pr_config_2.bits.SINK_REFRESH_RATE_UNLOCK_GRANTED = 0; + + if (link->dpcd_caps.vesa_replay_caps.bits.SU_Y_GRANULARITY_EXT_CAP_SUPPORTED) + pr_config_2.bits.SU_Y_GRANULARITY_EXT_VALUE_ENABLED = 1; + + pr_config_2.bits.SU_REGION_SCAN_LINE_CAPTURE_INDICATION = 0; + + dm_helpers_dp_write_dpcd(link->ctx, link, + DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_1, + (uint8_t *)&(pr_config_1.raw), sizeof(uint8_t)); + + dm_helpers_dp_write_dpcd(link->ctx, link, + DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_2, + (uint8_t *)&(pr_config_2.raw), sizeof(uint8_t)); + + //ALPM Setup + memset(&alpm_config, 0, sizeof(alpm_config)); + alpm_config.bits.ENABLE = link->replay_settings.config.alpm_mode != DC_ALPM_UNSUPPORTED ? 1 : 0; + + if (link->replay_settings.config.alpm_mode == DC_ALPM_AUXLESS) { + alpm_config.bits.ALPM_MODE_SEL = 1; + alpm_config.bits.ACDS_PERIOD_DURATION = 1; + } + + dm_helpers_dp_write_dpcd( + link->ctx, + link, + DP_RECEIVER_ALPM_CONFIG, + &alpm_config.raw, + sizeof(alpm_config.raw)); + } + + return true; +} + + +bool dp_pr_get_panel_inst(const struct dc *dc, + const struct dc_link *link, + unsigned int *inst_out) +{ + if (dc_is_embedded_signal(link->connector_signal)) { + /* TODO: just get edp link panel inst for now, fix it */ + return dc_get_edp_link_panel_inst(dc, link, inst_out); + } else if (dc_is_dp_sst_signal(link->connector_signal)) { + /* TODO: just set to 1 for now, fix it */ + *inst_out = 1; + return true; + } + + return false; +} + +bool dp_setup_replay(struct dc_link *link, const struct dc_stream_state *stream) +{ + if (!link) + return false; + if (link->replay_settings.config.replay_version == DC_VESA_PANEL_REPLAY) + return dp_setup_panel_replay(link, stream); + else if (link->replay_settings.config.replay_version == DC_FREESYNC_REPLAY) + return edp_setup_freesync_replay(link, stream); + else + return false; +} + +bool dp_pr_enable(struct dc_link *link, bool enable) +{ + struct dc *dc = link->ctx->dc; + unsigned int panel_inst = 0; + union dmub_rb_cmd cmd; + + if (!dp_pr_get_panel_inst(dc, link, &panel_inst)) + return false; + + if (link->replay_settings.replay_allow_active != enable) { + //for sending PR enable commands to DMUB + memset(&cmd, 0, sizeof(cmd)); + + cmd.pr_enable.header.type = DMUB_CMD__PR; + cmd.pr_enable.header.sub_type = DMUB_CMD__PR_ENABLE; + cmd.pr_enable.header.payload_bytes = sizeof(struct dmub_cmd_pr_enable_data); + cmd.pr_enable.data.panel_inst = panel_inst; + cmd.pr_enable.data.enable = enable ? 1 : 0; + + dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + + link->replay_settings.replay_allow_active = enable; + } + return true; +} + +bool dp_pr_copy_settings(struct dc_link *link, struct replay_context *replay_context) +{ + struct dc *dc = link->ctx->dc; + unsigned int panel_inst = 0; + union dmub_rb_cmd cmd; + struct pipe_ctx *pipe_ctx = NULL; + + if (!dp_pr_get_panel_inst(dc, link, &panel_inst)) + return false; + + for (unsigned int i = 0; i < MAX_PIPES; i++) { + if (dc->current_state->res_ctx.pipe_ctx[i].stream && + dc->current_state->res_ctx.pipe_ctx[i].stream->link && + dc->current_state->res_ctx.pipe_ctx[i].stream->link == link && + dc_is_dp_sst_signal(dc->current_state->res_ctx.pipe_ctx[i].stream->link->connector_signal)) { + pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; + /* todo: need update for MST */ + break; + } + } + + if (!pipe_ctx) + return false; + + memset(&cmd, 0, sizeof(cmd)); + cmd.pr_copy_settings.header.type = DMUB_CMD__PR; + cmd.pr_copy_settings.header.sub_type = DMUB_CMD__PR_COPY_SETTINGS; + cmd.pr_copy_settings.header.payload_bytes = sizeof(struct dmub_cmd_pr_copy_settings_data); + cmd.pr_copy_settings.data.panel_inst = panel_inst; + // HW inst + cmd.pr_copy_settings.data.aux_inst = replay_context->aux_inst; + cmd.pr_copy_settings.data.digbe_inst = replay_context->digbe_inst; + cmd.pr_copy_settings.data.digfe_inst = replay_context->digfe_inst; + if (pipe_ctx->plane_res.dpp) + cmd.pr_copy_settings.data.dpp_inst = pipe_ctx->plane_res.dpp->inst; + else + cmd.pr_copy_settings.data.dpp_inst = 0; + if (pipe_ctx->stream_res.tg) + cmd.pr_copy_settings.data.otg_inst = pipe_ctx->stream_res.tg->inst; + else + cmd.pr_copy_settings.data.otg_inst = 0; + + cmd.pr_copy_settings.data.dpphy_inst = link->link_enc->transmitter; + + cmd.pr_copy_settings.data.line_time_in_ns = replay_context->line_time_in_ns; + cmd.pr_copy_settings.data.flags.bitfields.fec_enable_status = (link->fec_state == dc_link_fec_enabled); + cmd.pr_copy_settings.data.flags.bitfields.dsc_enable_status = (pipe_ctx->stream->timing.flags.DSC == 1); + cmd.pr_copy_settings.data.debug.u32All = link->replay_settings.config.debug_flags; + + cmd.pr_copy_settings.data.su_granularity_needed = link->dpcd_caps.vesa_replay_caps.bits.PR_SU_GRANULARITY_NEEDED; + cmd.pr_copy_settings.data.su_x_granularity = link->dpcd_caps.vesa_replay_su_info.pr_su_x_granularity; + cmd.pr_copy_settings.data.su_y_granularity = link->dpcd_caps.vesa_replay_su_info.pr_su_y_granularity; + cmd.pr_copy_settings.data.su_y_granularity_extended_caps = + link->dpcd_caps.vesa_replay_su_info.pr_su_y_granularity_extended_caps; + + if (pipe_ctx->stream->timing.dsc_cfg.num_slices_v > 0) + cmd.pr_copy_settings.data.dsc_slice_height = (pipe_ctx->stream->timing.v_addressable + + pipe_ctx->stream->timing.v_border_top + pipe_ctx->stream->timing.v_border_bottom) / + pipe_ctx->stream->timing.dsc_cfg.num_slices_v; + + dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + return true; +} + +bool dp_pr_update_state(struct dc_link *link, struct dmub_cmd_pr_update_state_data *update_state_data) +{ + struct dc *dc = link->ctx->dc; + unsigned int panel_inst = 0; + union dmub_rb_cmd cmd; + + if (!dp_pr_get_panel_inst(dc, link, &panel_inst)) + return false; + + memset(&cmd, 0, sizeof(cmd)); + cmd.pr_update_state.header.type = DMUB_CMD__PR; + cmd.pr_update_state.header.sub_type = DMUB_CMD__PR_UPDATE_STATE; + cmd.pr_update_state.header.payload_bytes = sizeof(struct dmub_cmd_pr_update_state_data); + cmd.pr_update_state.data.panel_inst = panel_inst; + + memcpy(&cmd.pr_update_state.data, update_state_data, sizeof(struct dmub_cmd_pr_update_state_data)); + + dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + return true; +} + +bool dp_pr_set_general_cmd(struct dc_link *link, struct dmub_cmd_pr_general_cmd_data *general_cmd_data) +{ + struct dc *dc = link->ctx->dc; + unsigned int panel_inst = 0; + union dmub_rb_cmd cmd; + + if (!dp_pr_get_panel_inst(dc, link, &panel_inst)) + return false; + + memset(&cmd, 0, sizeof(cmd)); + cmd.pr_general_cmd.header.type = DMUB_CMD__PR; + cmd.pr_general_cmd.header.sub_type = DMUB_CMD__PR_GENERAL_CMD; + cmd.pr_general_cmd.header.payload_bytes = sizeof(struct dmub_cmd_pr_general_cmd_data); + cmd.pr_general_cmd.data.panel_inst = panel_inst; + + memcpy(&cmd.pr_general_cmd.data, general_cmd_data, sizeof(struct dmub_cmd_pr_general_cmd_data)); + + dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); + return true; +} + +bool dp_pr_get_state(const struct dc_link *link, uint64_t *state) +{ + const struct dc *dc = link->ctx->dc; + unsigned int panel_inst = 0; + uint32_t retry_count = 0; + uint32_t replay_state = 0; + + if (!dp_pr_get_panel_inst(dc, link, &panel_inst)) + return false; + + do { + // Send gpint command and wait for ack + if (!dc_wake_and_execute_gpint(dc->ctx, DMUB_GPINT__GET_REPLAY_STATE, panel_inst, + &replay_state, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) { + // Return invalid state when GPINT times out + replay_state = PR_STATE_INVALID; + } + /* Copy 32-bit result into 64-bit output */ + *state = replay_state; + } while (++retry_count <= 1000 && *state == PR_STATE_INVALID); + + // Assert if max retry hit + if (retry_count >= 1000 && *state == PR_STATE_INVALID) { + ASSERT(0); + /* To-do: Add retry fail log */ + } + + return true; +} diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_panel_replay.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_panel_replay.h new file mode 100644 index 000000000000..5522d5911fd1 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_panel_replay.h @@ -0,0 +1,38 @@ +/* + * Copyright 2025 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ +#ifndef __DC_LINK_DP_PANEL_REPLAY_H__ +#define __DC_LINK_DP_PANEL_REPLAY_H__ + +#include "link_service.h" + +bool dp_setup_replay(struct dc_link *link, const struct dc_stream_state *stream); +bool dp_pr_get_panel_inst(const struct dc *dc, const struct dc_link *link, unsigned int *inst_out); +bool dp_pr_enable(struct dc_link *link, bool enable); +bool dp_pr_copy_settings(struct dc_link *link, struct replay_context *replay_context); +bool dp_pr_update_state(struct dc_link *link, struct dmub_cmd_pr_update_state_data *update_state_data); +bool dp_pr_set_general_cmd(struct dc_link *link, struct dmub_cmd_pr_general_cmd_data *general_cmd_data); +bool dp_pr_get_state(const struct dc_link *link, uint64_t *state); + +#endif /* __DC_LINK_DP_PANEL_REPLAY_H__ */
\ No newline at end of file diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c index d6e91da72ef8..cb4129c0937a 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c @@ -50,11 +50,6 @@ static const uint8_t DP_VGA_LVDS_CONVERTER_ID_2[] = "sivarT"; /* Nutmeg */ static const uint8_t DP_VGA_LVDS_CONVERTER_ID_3[] = "dnomlA"; -static const unsigned int pwr_default_min_brightness_millinits = 1000; -static const unsigned int pwr_default_sdr_brightness_millinits = 270000; -static const unsigned int pwr_default_min_backlight_pwm = 0xC0C; -static const unsigned int pwr_default_max_backlight_pwm = 0xFFFF; - void dp_set_panel_mode(struct dc_link *link, enum dp_panel_mode panel_mode) { union dpcd_edp_config edp_config_set; @@ -313,7 +308,7 @@ static bool read_default_bl_aux(struct dc_link *link, uint32_t *backlight_millin return true; } -bool set_default_brightness(struct dc_link *link) +bool set_default_brightness_aux(struct dc_link *link) { uint32_t default_backlight; @@ -324,23 +319,8 @@ bool set_default_brightness(struct dc_link *link) if (default_backlight < 1000 || default_backlight > 5000000) default_backlight = 150000; - if (link->backlight_control_type == BACKLIGHT_CONTROL_VESA_AUX && - link->dc->caps.dmub_caps.aux_backlight_support) { - struct set_backlight_level_params backlight_level_params = { 0 }; - - backlight_level_params.aux_inst = link->ddc->ddc_pin->hw_info.ddc_channel; - backlight_level_params.control_type = BACKLIGHT_CONTROL_VESA_AUX; - backlight_level_params.backlight_pwm_u16_16 = default_backlight; - backlight_level_params.transition_time_in_ms = 0; - // filled in the driver BL default values - backlight_level_params.min_luminance = pwr_default_min_brightness_millinits; - backlight_level_params.max_luminance = pwr_default_sdr_brightness_millinits; - backlight_level_params.min_backlight_pwm = pwr_default_min_backlight_pwm; - backlight_level_params.max_backlight_pwm = pwr_default_max_backlight_pwm; - return edp_set_backlight_level(link, &backlight_level_params); - } else - return edp_set_backlight_level_nits(link, true, - default_backlight, 0); + return edp_set_backlight_level_nits(link, true, + default_backlight, 0); } return false; } @@ -1003,116 +983,8 @@ bool edp_get_replay_state(const struct dc_link *link, uint64_t *state) return true; } -static bool edp_setup_panel_replay(struct dc_link *link, const struct dc_stream_state *stream) -{ - /* To-do: Setup Replay */ - struct dc *dc; - struct dmub_replay *replay; - int i; - unsigned int panel_inst; - struct replay_context replay_context = { 0 }; - unsigned int lineTimeInNs = 0; - - union panel_replay_enable_and_configuration_1 pr_config_1 = { 0 }; - union panel_replay_enable_and_configuration_2 pr_config_2 = { 0 }; - - union dpcd_alpm_configuration alpm_config; - - replay_context.controllerId = CONTROLLER_ID_UNDEFINED; - - if (!link) - return false; - - //Clear Panel Replay enable & config - dm_helpers_dp_write_dpcd(link->ctx, link, - DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_1, - (uint8_t *)&(pr_config_1.raw), sizeof(uint8_t)); - - dm_helpers_dp_write_dpcd(link->ctx, link, - DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_2, - (uint8_t *)&(pr_config_2.raw), sizeof(uint8_t)); - - if (!(link->replay_settings.config.replay_supported)) - return false; - - dc = link->ctx->dc; - - //not sure should keep or not - replay = dc->res_pool->replay; - - if (!replay) - return false; - - if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst)) - return false; - - replay_context.aux_inst = link->ddc->ddc_pin->hw_info.ddc_channel; - replay_context.digbe_inst = link->link_enc->transmitter; - replay_context.digfe_inst = link->link_enc->preferred_engine; - - for (i = 0; i < MAX_PIPES; i++) { - if (dc->current_state->res_ctx.pipe_ctx[i].stream - == stream) { - /* dmcu -1 for all controller id values, - * therefore +1 here - */ - replay_context.controllerId = - dc->current_state->res_ctx.pipe_ctx[i].stream_res.tg->inst + 1; - break; - } - } - - lineTimeInNs = - ((stream->timing.h_total * 1000000) / - (stream->timing.pix_clk_100hz / 10)) + 1; - - replay_context.line_time_in_ns = lineTimeInNs; - - link->replay_settings.replay_feature_enabled = edp_pr_copy_settings(link, &replay_context); - - if (link->replay_settings.replay_feature_enabled) { - pr_config_1.bits.PANEL_REPLAY_ENABLE = 1; - pr_config_1.bits.PANEL_REPLAY_CRC_ENABLE = 1; - pr_config_1.bits.IRQ_HPD_ASSDP_MISSING = 1; - pr_config_1.bits.IRQ_HPD_VSCSDP_UNCORRECTABLE_ERROR = 1; - pr_config_1.bits.IRQ_HPD_RFB_ERROR = 1; - pr_config_1.bits.IRQ_HPD_ACTIVE_FRAME_CRC_ERROR = 1; - pr_config_1.bits.PANEL_REPLAY_SELECTIVE_UPDATE_ENABLE = 1; - pr_config_1.bits.PANEL_REPLAY_EARLY_TRANSPORT_ENABLE = 1; - - pr_config_2.bits.SINK_REFRESH_RATE_UNLOCK_GRANTED = 0; - pr_config_2.bits.SU_Y_GRANULARITY_EXT_VALUE_ENABLED = 0; - pr_config_2.bits.SU_REGION_SCAN_LINE_CAPTURE_INDICATION = 0; - - dm_helpers_dp_write_dpcd(link->ctx, link, - DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_1, - (uint8_t *)&(pr_config_1.raw), sizeof(uint8_t)); - - dm_helpers_dp_write_dpcd(link->ctx, link, - DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_2, - (uint8_t *)&(pr_config_2.raw), sizeof(uint8_t)); - - //ALPM Setup - memset(&alpm_config, 0, sizeof(alpm_config)); - alpm_config.bits.ENABLE = link->replay_settings.config.alpm_mode != DC_ALPM_UNSUPPORTED ? 1 : 0; - - if (link->replay_settings.config.alpm_mode == DC_ALPM_AUXLESS) { - alpm_config.bits.ALPM_MODE_SEL = 1; - alpm_config.bits.ACDS_PERIOD_DURATION = 1; - } - - dm_helpers_dp_write_dpcd( - link->ctx, - link, - DP_RECEIVER_ALPM_CONFIG, - &alpm_config.raw, - sizeof(alpm_config.raw)); - } - - return true; -} -static bool edp_setup_freesync_replay(struct dc_link *link, const struct dc_stream_state *stream) +bool edp_setup_freesync_replay(struct dc_link *link, const struct dc_stream_state *stream) { /* To-do: Setup Replay */ struct dc *dc; @@ -1208,17 +1080,6 @@ static bool edp_setup_freesync_replay(struct dc_link *link, const struct dc_stre return true; } -bool edp_setup_replay(struct dc_link *link, const struct dc_stream_state *stream) -{ - if (!link) - return false; - if (link->replay_settings.config.replay_version == DC_VESA_PANEL_REPLAY) - return edp_setup_panel_replay(link, stream); - else if (link->replay_settings.config.replay_version == DC_FREESYNC_REPLAY) - return edp_setup_freesync_replay(link, stream); - else - return false; -} /* * This is general Interface for Replay to set an 32 bit variable to dmub @@ -1323,156 +1184,6 @@ bool edp_set_replay_power_opt_and_coasting_vtotal(struct dc_link *link, return true; } -bool edp_pr_enable(struct dc_link *link, bool enable) -{ - struct dc *dc = link->ctx->dc; - unsigned int panel_inst = 0; - union dmub_rb_cmd cmd; - - if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst)) - return false; - - if (link->replay_settings.replay_allow_active != enable) { - //for sending PR enable commands to DMUB - memset(&cmd, 0, sizeof(cmd)); - - cmd.pr_enable.header.type = DMUB_CMD__PR; - cmd.pr_enable.header.sub_type = DMUB_CMD__PR_ENABLE; - cmd.pr_enable.header.payload_bytes = sizeof(struct dmub_cmd_pr_enable_data); - cmd.pr_enable.data.panel_inst = panel_inst; - cmd.pr_enable.data.enable = enable ? 1 : 0; - - dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); - - link->replay_settings.replay_allow_active = enable; - } - return true; -} - -bool edp_pr_copy_settings(struct dc_link *link, struct replay_context *replay_context) -{ - struct dc *dc = link->ctx->dc; - unsigned int panel_inst = 0; - union dmub_rb_cmd cmd; - struct pipe_ctx *pipe_ctx = NULL; - - if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst)) - return false; - - for (unsigned int i = 0; i < MAX_PIPES; i++) { - if (dc->current_state->res_ctx.pipe_ctx[i].stream && - dc->current_state->res_ctx.pipe_ctx[i].stream->link && - dc->current_state->res_ctx.pipe_ctx[i].stream->link == link && - dc->current_state->res_ctx.pipe_ctx[i].stream->link->connector_signal == SIGNAL_TYPE_EDP) { - pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; - //TODO: refactor for multi edp support - break; - } - } - - if (!pipe_ctx) - return false; - - memset(&cmd, 0, sizeof(cmd)); - cmd.pr_copy_settings.header.type = DMUB_CMD__PR; - cmd.pr_copy_settings.header.sub_type = DMUB_CMD__PR_COPY_SETTINGS; - cmd.pr_copy_settings.header.payload_bytes = sizeof(struct dmub_cmd_pr_copy_settings_data); - cmd.pr_copy_settings.data.panel_inst = panel_inst; - // HW inst - cmd.pr_copy_settings.data.aux_inst = replay_context->aux_inst; - cmd.pr_copy_settings.data.digbe_inst = replay_context->digbe_inst; - cmd.pr_copy_settings.data.digfe_inst = replay_context->digfe_inst; - if (pipe_ctx->plane_res.dpp) - cmd.pr_copy_settings.data.dpp_inst = pipe_ctx->plane_res.dpp->inst; - else - cmd.pr_copy_settings.data.dpp_inst = 0; - if (pipe_ctx->stream_res.tg) - cmd.pr_copy_settings.data.otg_inst = pipe_ctx->stream_res.tg->inst; - else - cmd.pr_copy_settings.data.otg_inst = 0; - - cmd.pr_copy_settings.data.dpphy_inst = link->link_enc->transmitter; - - cmd.pr_copy_settings.data.line_time_in_ns = replay_context->line_time_in_ns; - cmd.pr_copy_settings.data.flags.bitfields.fec_enable_status = (link->fec_state == dc_link_fec_enabled); - cmd.pr_copy_settings.data.flags.bitfields.dsc_enable_status = (pipe_ctx->stream->timing.flags.DSC == 1); - cmd.pr_copy_settings.data.debug.u32All = link->replay_settings.config.debug_flags; - - dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); - return true; -} - -bool edp_pr_update_state(struct dc_link *link, struct dmub_cmd_pr_update_state_data *update_state_data) -{ - struct dc *dc = link->ctx->dc; - unsigned int panel_inst = 0; - union dmub_rb_cmd cmd; - - if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst)) - return false; - - memset(&cmd, 0, sizeof(cmd)); - cmd.pr_update_state.header.type = DMUB_CMD__PR; - cmd.pr_update_state.header.sub_type = DMUB_CMD__PR_UPDATE_STATE; - cmd.pr_update_state.header.payload_bytes = sizeof(struct dmub_cmd_pr_update_state_data); - cmd.pr_update_state.data.panel_inst = panel_inst; - - memcpy(&cmd.pr_update_state.data, update_state_data, sizeof(struct dmub_cmd_pr_update_state_data)); - - dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); - return true; -} - -bool edp_pr_set_general_cmd(struct dc_link *link, struct dmub_cmd_pr_general_cmd_data *general_cmd_data) -{ - struct dc *dc = link->ctx->dc; - unsigned int panel_inst = 0; - union dmub_rb_cmd cmd; - - if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst)) - return false; - - memset(&cmd, 0, sizeof(cmd)); - cmd.pr_general_cmd.header.type = DMUB_CMD__PR; - cmd.pr_general_cmd.header.sub_type = DMUB_CMD__PR_GENERAL_CMD; - cmd.pr_general_cmd.header.payload_bytes = sizeof(struct dmub_cmd_pr_general_cmd_data); - cmd.pr_general_cmd.data.panel_inst = panel_inst; - - memcpy(&cmd.pr_general_cmd.data, general_cmd_data, sizeof(struct dmub_cmd_pr_general_cmd_data)); - - dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); - return true; -} - -bool edp_pr_get_state(const struct dc_link *link, uint64_t *state) -{ - const struct dc *dc = link->ctx->dc; - unsigned int panel_inst = 0; - uint32_t retry_count = 0; - uint32_t replay_state = 0; - - if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst)) - return false; - - do { - // Send gpint command and wait for ack - if (!dc_wake_and_execute_gpint(dc->ctx, DMUB_GPINT__GET_REPLAY_STATE, panel_inst, - &replay_state, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) { - // Return invalid state when GPINT times out - replay_state = PR_STATE_INVALID; - } - /* Copy 32-bit result into 64-bit output */ - *state = replay_state; - } while (++retry_count <= 1000 && *state == PR_STATE_INVALID); - - // Assert if max retry hit - if (retry_count >= 1000 && *state == PR_STATE_INVALID) { - ASSERT(0); - /* To-do: Add retry fail log */ - } - - return true; -} static struct abm *get_abm_from_stream_res(const struct dc_link *link) { diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h index fd63b5d0f948..8fdb76d9953e 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h @@ -29,7 +29,7 @@ enum dp_panel_mode dp_get_panel_mode(struct dc_link *link); void dp_set_panel_mode(struct dc_link *link, enum dp_panel_mode panel_mode); -bool set_default_brightness(struct dc_link *link); +bool set_default_brightness_aux(struct dc_link *link); bool is_smartmux_suported(struct dc_link *link); void edp_panel_backlight_power_on(struct dc_link *link, bool wait_for_hpd); int edp_get_backlight_level(const struct dc_link *link); @@ -54,8 +54,6 @@ bool edp_set_sink_vtotal_in_psr_active(const struct dc_link *link, void edp_get_psr_residency(const struct dc_link *link, uint32_t *residency, enum psr_residency_mode mode); bool edp_set_replay_allow_active(struct dc_link *dc_link, const bool *enable, bool wait, bool force_static, const unsigned int *power_opts); -bool edp_setup_replay(struct dc_link *link, - const struct dc_stream_state *stream); bool edp_send_replay_cmd(struct dc_link *link, enum replay_FW_Message_type msg, union dmub_replay_cmd_set *cmd_data); @@ -75,11 +73,7 @@ void edp_add_delay_for_T9(struct dc_link *link); bool edp_receiver_ready_T9(struct dc_link *link); bool edp_receiver_ready_T7(struct dc_link *link); bool edp_power_alpm_dpcd_enable(struct dc_link *link, bool enable); -bool edp_pr_enable(struct dc_link *link, bool enable); -bool edp_pr_copy_settings(struct dc_link *link, struct replay_context *replay_context); -bool edp_pr_update_state(struct dc_link *link, struct dmub_cmd_pr_update_state_data *update_state_data); -bool edp_pr_set_general_cmd(struct dc_link *link, struct dmub_cmd_pr_general_cmd_data *general_cmd_data); -bool edp_pr_get_state(const struct dc_link *link, uint64_t *state); +bool edp_setup_freesync_replay(struct dc_link *link, const struct dc_stream_state *stream); void edp_set_panel_power(struct dc_link *link, bool powerOn); void edp_set_panel_assr(struct dc_link *link, struct pipe_ctx *pipe_ctx, enum dp_panel_mode *panel_mode, bool enable); diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c index 0d667b54ccf8..e853ea110310 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c @@ -2250,12 +2250,15 @@ enum dc_status dcn31_update_dc_state_for_encoder_switch(struct dc_link *link, int i; #if defined(CONFIG_DRM_AMD_DC_FP) - for (i = 0; i < state->stream_count; i++) - if (state->streams[i] && state->streams[i]->link && state->streams[i]->link == link) - link->dc->hwss.calculate_pix_rate_divider((struct dc *)link->dc, state, state->streams[i]); + if (link->dc->hwss.calculate_pix_rate_divider) { + for (i = 0; i < state->stream_count; i++) + if (state->streams[i] && state->streams[i]->link && state->streams[i]->link == link) + link->dc->hwss.calculate_pix_rate_divider((struct dc *)link->dc, state, state->streams[i]); + } for (i = 0; i < pipe_count; i++) { - link->dc->res_pool->funcs->build_pipe_pix_clk_params(&pipes[i]); + if (link->dc->res_pool->funcs->build_pipe_pix_clk_params) + link->dc->res_pool->funcs->build_pipe_pix_clk_params(&pipes[i]); // Setup audio if (pipes[i].stream_res.audio != NULL) diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index 6c599559c5da..9d0852760e78 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -1091,7 +1091,10 @@ union dmub_fw_boot_options { uint32_t lower_hbr3_phy_ssc: 1; /**< 1 to lower hbr3 phy ssc to 0.125 percent */ uint32_t override_hbr3_pll_vco: 1; /**< 1 to override the hbr3 pll vco to 0 */ uint32_t disable_dpia_bw_allocation: 1; /**< 1 to disable the USB4 DPIA BW allocation */ - uint32_t reserved : 4; /**< reserved */ + uint32_t bootcrc_en_at_preos: 1; /**< 1 to run the boot time crc during warm/cold boot*/ + uint32_t bootcrc_en_at_S0i3: 1; /**< 1 to run the boot time crc during S0i3 boot*/ + uint32_t bootcrc_boot_mode: 1; /**< 1 for S0i3 resume and 0 for Warm/cold boot*/ + uint32_t reserved : 1; /**< reserved */ } bits; /**< boot bits */ uint32_t all; /**< 32-bit access to bits */ }; @@ -2638,7 +2641,7 @@ union dmub_fams2_global_feature_config { uint32_t enable_visual_confirm: 1; uint32_t allow_delay_check_mode: 2; uint32_t legacy_method_no_fams2 : 1; - uint32_t reserved: 23; + uint32_t reserved : 23; } bits; uint32_t all; }; @@ -4335,10 +4338,6 @@ enum dmub_cmd_replay_type { */ DMUB_CMD__REPLAY_DISABLED_ADAPTIVE_SYNC_SDP = 8, /** - * Set version - */ - DMUB_CMD__REPLAY_SET_VERSION = 9, - /** * Set Replay General command. */ DMUB_CMD__REPLAY_SET_GENERAL_CMD = 16, @@ -4379,6 +4378,7 @@ enum dmub_cmd_replay_general_subtype { REPLAY_GENERAL_CMD_UPDATE_ERROR_STATUS, REPLAY_GENERAL_CMD_SET_LOW_RR_ACTIVATE, REPLAY_GENERAL_CMD_VIDEO_CONFERENCING, + REPLAY_GENERAL_CMD_SET_CONTINUOUSLY_RESYNC, }; struct dmub_alpm_auxless_data { @@ -4506,40 +4506,6 @@ enum replay_version { }; /** - * Data passed from driver to FW in a DMUB_CMD___SET_REPLAY_VERSION command. - */ -struct dmub_cmd_replay_set_version_data { - /** - * Panel Instance. - * Panel instance to identify which psr_state to use - * Currently the support is only for 0 or 1 - */ - uint8_t panel_inst; - /** - * Replay version that FW should implement. - */ - enum replay_version version; - /** - * Explicit padding to 4 byte boundary. - */ - uint8_t pad[3]; -}; - -/** - * Definition of a DMUB_CMD__REPLAY_SET_VERSION command. - */ -struct dmub_rb_cmd_replay_set_version { - /** - * Command header. - */ - struct dmub_cmd_header header; - /** - * Data passed from driver to FW in a DMUB_CMD__REPLAY_SET_VERSION command. - */ - struct dmub_cmd_replay_set_version_data replay_set_version_data; -}; - -/** * Definition of a DMUB_CMD__REPLAY_COPY_SETTINGS command. */ struct dmub_rb_cmd_replay_copy_settings { @@ -4930,10 +4896,6 @@ union dmub_replay_cmd_set { */ struct dmub_cmd_replay_disabled_adaptive_sync_sdp_data disabled_adaptive_sync_sdp_data; /** - * Definition of DMUB_CMD__REPLAY_SET_VERSION command data. - */ - struct dmub_cmd_replay_set_version_data version_data; - /** * Definition of DMUB_CMD__REPLAY_SET_GENERAL_CMD command data. */ struct dmub_cmd_replay_set_general_cmd_data set_general_cmd_data; @@ -7020,10 +6982,6 @@ union dmub_rb_cmd { * Definition of a DMUB_CMD__IDLE_OPT_SET_DC_POWER_STATE command. */ struct dmub_rb_cmd_idle_opt_set_dc_power_state idle_opt_set_dc_power_state; - /** - * Definition of a DMUB_CMD__REPLAY_SET_VERSION command. - */ - struct dmub_rb_cmd_replay_set_version replay_set_version; /* * Definition of a DMUB_CMD__REPLAY_COPY_SETTINGS command. */ diff --git a/drivers/gpu/drm/amd/display/include/dpcd_defs.h b/drivers/gpu/drm/amd/display/include/dpcd_defs.h index 8445c540f042..7d8359a7d99d 100644 --- a/drivers/gpu/drm/amd/display/include/dpcd_defs.h +++ b/drivers/gpu/drm/amd/display/include/dpcd_defs.h @@ -37,6 +37,21 @@ #ifndef DP_PANEL_REPLAY_CAPABILITY // can remove this once the define gets into linux drm_dp_helper.h #define DP_PANEL_REPLAY_CAPABILITY 0x0b1 #endif /* DP_PANEL_REPLAY_CAPABILITY */ +#ifndef DP_PR_SU_X_GRANULARITY_LOW // can remove this once the define gets into linux drm_dp_helper.h +#define DP_PR_SU_X_GRANULARITY_LOW 0x0b2 +#endif /* DP_PR_SU_X_GRANULARITY_LOW */ +#ifndef DP_PR_SU_X_GRANULARITY_HIGH // can remove this once the define gets into linux drm_dp_helper.h +#define DP_PR_SU_X_GRANULARITY_HIGH 0x0b3 +#endif /* DP_PR_SU_X_GRANULARITY_HIGH */ +#ifndef DP_PR_SU_Y_GRANULARITY // can remove this once the define gets into linux drm_dp_helper.h +#define DP_PR_SU_Y_GRANULARITY 0x0b4 +#endif /* DP_PR_SU_Y_GRANULARITY */ +#ifndef DP_PR_SU_Y_GRANULARITY_EXTENDED_CAP_LOW // can remove this once the define gets into linux drm_dp_helper.h +#define DP_PR_SU_Y_GRANULARITY_EXTENDED_CAP_LOW 0x0b5 +#endif /* DP_PR_SU_Y_GRANULARITY_EXTENDED_CAP_LOW */ +#ifndef DP_PR_SU_Y_GRANULARITY_EXTENDED_CAP_HIGH // can remove this once the define gets into linux drm_dp_helper.h +#define DP_PR_SU_Y_GRANULARITY_EXTENDED_CAP_HIGH 0x0b6 +#endif /* DP_PR_SU_Y_GRANULARITY_EXTENDED_CAP_HIGH */ #ifndef DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_1 // can remove this once the define gets into linux drm_dp_helper.h #define DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_1 0x1b0 #endif /* DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_1 */ @@ -46,6 +61,21 @@ #ifndef DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_2 // can remove this once the define gets into linux drm_dp_helper.h #define DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_2 0x1b1 #endif /* DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_2 */ +#ifndef DP_PR_ERROR_STATUS // can remove this once the define gets into linux drm_dp_helper.h +#define DP_PR_ERROR_STATUS 0x2020 /* DP 2.0 */ +#endif /* DP_PR_ERROR_STATUS */ +#ifndef DP_PR_LINK_CRC_ERROR // can remove this once the define gets into linux drm_dp_helper.h +#define DP_PR_LINK_CRC_ERROR (1 << 0) +#endif /* DP_PR_LINK_CRC_ERROR */ +#ifndef DP_PR_RFB_STORAGE_ERROR // can remove this once the define gets into linux drm_dp_helper.h +#define DP_PR_RFB_STORAGE_ERROR (1 << 1) +#endif /* DP_PR_RFB_STORAGE_ERROR */ +#ifndef DP_PR_VSC_SDP_UNCORRECTABLE_ERROR // can remove this once the define gets into linux drm_dp_helper.h +#define DP_PR_VSC_SDP_UNCORRECTABLE_ERROR (1 << 2) /* eDP 1.4 */ +#endif /* DP_PR_VSC_SDP_UNCORRECTABLE_ERROR */ +#ifndef DP_PR_ASSDP_MISSING_ERROR // can remove this once the define gets into linux drm_dp_helper.h +#define DP_PR_ASSDP_MISSING_ERROR (1 << 3) /* eDP 1.5 */ +#endif /* DP_PR_ASSDP_MISSING_ERROR */ enum dpcd_revision { DPCD_REV_10 = 0x10, |
