Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm/amd/display: Use vblank control events for PSR enable/disable

[Why]
PSR can disable the HUBP along with the OTG when PSR is active.

We'll hit a pageflip timeout when the OTG is disable because we're no
longer updating the CRTC vblank counter and the pflip high IRQ will
not fire on the flip.

In order to flip the page flip timeout occur we should modify the
enter/exit conditions to match DRM requirements.

[How]
Use our deferred handlers for DRM vblank control to notify DMCU(B)
when it can enable or disable PSR based on whether vblank is disabled or
enabled respectively.

We'll need to pass along the stream with the notification now because
we want to access the CRTC state while the CRTC is locked to get the
stream state prior to the commit.

Retain a reference to the stream so it remains safe to continue to
access and release that reference once we're done with it.

Enable/disable logic follows what we were previously doing in
update_planes.

The workqueue has to be flushed before programming streams or planes
to ensure that we exit out of idle optimizations and PSR before
these events occur if necessary.

To keep the skip count logic the same to avoid FBCON PSR enablement
requires copying the allow condition onto the DM IRQ parameters - a
field that we can actually access from the worker.

Reviewed-by: Roman Li <Roman.Li@amd.com>
Acked-by: Wayne Lin <wayne.lin@amd.com>
Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Nicholas Kazlauskas and committed by
Alex Deucher
58aa1c50 09a5df6c

+43 -8
+40 -8
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
··· 1061 1061 1062 1062 DRM_DEBUG_KMS("Allow idle optimizations (MALL): %d\n", dm->active_vblank_irq_count == 0); 1063 1063 1064 + /* Control PSR based on vblank requirements from OS */ 1065 + if (vblank_work->stream && vblank_work->stream->link) { 1066 + if (vblank_work->enable) { 1067 + if (vblank_work->stream->link->psr_settings.psr_allow_active) 1068 + amdgpu_dm_psr_disable(vblank_work->stream); 1069 + } else if (vblank_work->stream->link->psr_settings.psr_feature_enabled && 1070 + !vblank_work->stream->link->psr_settings.psr_allow_active && 1071 + vblank_work->acrtc->dm_irq_params.allow_psr_entry) { 1072 + amdgpu_dm_psr_enable(vblank_work->stream); 1073 + } 1074 + } 1075 + 1064 1076 mutex_unlock(&dm->dc_lock); 1077 + 1078 + dc_stream_release(vblank_work->stream); 1079 + 1065 1080 kfree(vblank_work); 1066 1081 } 1067 1082 ··· 6033 6018 work->acrtc = acrtc; 6034 6019 work->enable = enable; 6035 6020 6021 + if (acrtc_state->stream) { 6022 + dc_stream_retain(acrtc_state->stream); 6023 + work->stream = acrtc_state->stream; 6024 + } 6025 + 6036 6026 queue_work(dm->vblank_control_workqueue, &work->work); 6037 6027 #endif 6038 6028 ··· 8643 8623 /* Update the planes if changed or disable if we don't have any. */ 8644 8624 if ((planes_count || acrtc_state->active_planes == 0) && 8645 8625 acrtc_state->stream) { 8626 + /* 8627 + * If PSR or idle optimizations are enabled then flush out 8628 + * any pending work before hardware programming. 8629 + */ 8630 + flush_workqueue(dm->vblank_control_workqueue); 8631 + 8646 8632 bundle->stream_update.stream = acrtc_state->stream; 8647 8633 if (new_pcrtc_state->mode_changed) { 8648 8634 bundle->stream_update.src = acrtc_state->stream->src; ··· 8717 8691 acrtc_state->stream->link->psr_settings.psr_version != DC_PSR_VERSION_UNSUPPORTED && 8718 8692 !acrtc_state->stream->link->psr_settings.psr_feature_enabled) 8719 8693 amdgpu_dm_link_setup_psr(acrtc_state->stream); 8720 - else if ((acrtc_state->update_type == UPDATE_TYPE_FAST) && 8721 - acrtc_state->stream->link->psr_settings.psr_feature_enabled && 8722 - !acrtc_state->stream->link->psr_settings.psr_allow_active) { 8723 - struct amdgpu_dm_connector *aconn = (struct amdgpu_dm_connector *) 8724 - acrtc_state->stream->dm_stream_context; 8694 + 8695 + /* Decrement skip count when PSR is enabled and we're doing fast updates. */ 8696 + if (acrtc_state->update_type == UPDATE_TYPE_FAST && 8697 + acrtc_state->stream->link->psr_settings.psr_feature_enabled) { 8698 + struct amdgpu_dm_connector *aconn = 8699 + (struct amdgpu_dm_connector *)acrtc_state->stream->dm_stream_context; 8725 8700 8726 8701 if (aconn->psr_skip_count > 0) 8727 8702 aconn->psr_skip_count--; 8728 - else 8729 - amdgpu_dm_psr_enable(acrtc_state->stream); 8703 + 8704 + /* Allow PSR when skip count is 0. */ 8705 + acrtc_attach->dm_irq_params.allow_psr_entry = !aconn->psr_skip_count; 8706 + } else { 8707 + acrtc_attach->dm_irq_params.allow_psr_entry = false; 8730 8708 } 8731 8709 8732 8710 mutex_unlock(&dm->dc_lock); ··· 8979 8949 8980 8950 if (dc_state) { 8981 8951 /* if there mode set or reset, disable eDP PSR */ 8982 - if (mode_set_reset_required) 8952 + if (mode_set_reset_required) { 8953 + flush_workqueue(dm->vblank_control_workqueue); 8983 8954 amdgpu_dm_psr_disable_all(dm); 8955 + } 8984 8956 8985 8957 dm_enable_per_frame_crtc_master_sync(dc_state); 8986 8958 mutex_lock(&dm->dc_lock);
+2
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
··· 91 91 * @work: Kernel work data for the work event 92 92 * @dm: amdgpu display manager device 93 93 * @acrtc: amdgpu CRTC instance for which the event has occurred 94 + * @stream: DC stream for which the event has occurred 94 95 * @enable: true if enabling vblank 95 96 */ 96 97 struct vblank_control_work { 97 98 struct work_struct work; 98 99 struct amdgpu_display_manager *dm; 99 100 struct amdgpu_crtc *acrtc; 101 + struct dc_stream_state *stream; 100 102 bool enable; 101 103 }; 102 104
+1
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq_params.h
··· 33 33 struct mod_vrr_params vrr_params; 34 34 struct dc_stream_state *stream; 35 35 int active_planes; 36 + bool allow_psr_entry; 36 37 struct mod_freesync_config freesync_config; 37 38 38 39 #ifdef CONFIG_DEBUG_FS