5757
5858#include <drm/drmP.h>
5959#include <drm/drm_atomic.h>
60+ #include <drm/drm_atomic_uapi.h>
6061#include <drm/drm_atomic_helper.h>
6162#include <drm/drm_dp_mst_helper.h>
6263#include <drm/drm_fb_helper.h>
@@ -133,6 +134,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state);
133134static int amdgpu_dm_atomic_check (struct drm_device * dev ,
134135 struct drm_atomic_state * state );
135136
137+ static void handle_cursor_update (struct drm_plane * plane ,
138+ struct drm_plane_state * old_plane_state );
136139
137140
138141
@@ -402,6 +405,8 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
402405 /* Zero all the fields */
403406 memset (& init_data , 0 , sizeof (init_data ));
404407
408+ mutex_init (& adev -> dm .dc_lock );
409+
405410 if (amdgpu_dm_irq_init (adev )) {
406411 DRM_ERROR ("amdgpu: failed to initialize DM IRQ support.\n" );
407412 goto error ;
@@ -516,6 +521,9 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev)
516521 /* DC Destroy TODO: Replace destroy DAL */
517522 if (adev -> dm .dc )
518523 dc_destroy (& adev -> dm .dc );
524+
525+ mutex_destroy (& adev -> dm .dc_lock );
526+
519527 return ;
520528}
521529
@@ -3617,10 +3625,43 @@ static int dm_plane_atomic_check(struct drm_plane *plane,
36173625 return - EINVAL ;
36183626}
36193627
3628+ static int dm_plane_atomic_async_check (struct drm_plane * plane ,
3629+ struct drm_plane_state * new_plane_state )
3630+ {
3631+ /* Only support async updates on cursor planes. */
3632+ if (plane -> type != DRM_PLANE_TYPE_CURSOR )
3633+ return - EINVAL ;
3634+
3635+ return 0 ;
3636+ }
3637+
3638+ static void dm_plane_atomic_async_update (struct drm_plane * plane ,
3639+ struct drm_plane_state * new_state )
3640+ {
3641+ struct drm_plane_state * old_state =
3642+ drm_atomic_get_old_plane_state (new_state -> state , plane );
3643+
3644+ if (plane -> state -> fb != new_state -> fb )
3645+ drm_atomic_set_fb_for_plane (plane -> state , new_state -> fb );
3646+
3647+ plane -> state -> src_x = new_state -> src_x ;
3648+ plane -> state -> src_y = new_state -> src_y ;
3649+ plane -> state -> src_w = new_state -> src_w ;
3650+ plane -> state -> src_h = new_state -> src_h ;
3651+ plane -> state -> crtc_x = new_state -> crtc_x ;
3652+ plane -> state -> crtc_y = new_state -> crtc_y ;
3653+ plane -> state -> crtc_w = new_state -> crtc_w ;
3654+ plane -> state -> crtc_h = new_state -> crtc_h ;
3655+
3656+ handle_cursor_update (plane , old_state );
3657+ }
3658+
36203659static const struct drm_plane_helper_funcs dm_plane_helper_funcs = {
36213660 .prepare_fb = dm_plane_helper_prepare_fb ,
36223661 .cleanup_fb = dm_plane_helper_cleanup_fb ,
36233662 .atomic_check = dm_plane_atomic_check ,
3663+ .atomic_async_check = dm_plane_atomic_async_check ,
3664+ .atomic_async_update = dm_plane_atomic_async_update
36243665};
36253666
36263667/*
@@ -4309,6 +4350,7 @@ static int get_cursor_position(struct drm_plane *plane, struct drm_crtc *crtc,
43094350static void handle_cursor_update (struct drm_plane * plane ,
43104351 struct drm_plane_state * old_plane_state )
43114352{
4353+ struct amdgpu_device * adev = plane -> dev -> dev_private ;
43124354 struct amdgpu_framebuffer * afb = to_amdgpu_framebuffer (plane -> state -> fb );
43134355 struct drm_crtc * crtc = afb ? plane -> state -> crtc : old_plane_state -> crtc ;
43144356 struct dm_crtc_state * crtc_state = crtc ? to_dm_crtc_state (crtc -> state ) : NULL ;
@@ -4333,9 +4375,12 @@ static void handle_cursor_update(struct drm_plane *plane,
43334375
43344376 if (!position .enable ) {
43354377 /* turn off cursor */
4336- if (crtc_state && crtc_state -> stream )
4378+ if (crtc_state && crtc_state -> stream ) {
4379+ mutex_lock (& adev -> dm .dc_lock );
43374380 dc_stream_set_cursor_position (crtc_state -> stream ,
43384381 & position );
4382+ mutex_unlock (& adev -> dm .dc_lock );
4383+ }
43394384 return ;
43404385 }
43414386
@@ -4353,13 +4398,15 @@ static void handle_cursor_update(struct drm_plane *plane,
43534398 attributes .pitch = attributes .width ;
43544399
43554400 if (crtc_state -> stream ) {
4401+ mutex_lock (& adev -> dm .dc_lock );
43564402 if (!dc_stream_set_cursor_attributes (crtc_state -> stream ,
43574403 & attributes ))
43584404 DRM_ERROR ("DC failed to set cursor attributes\n" );
43594405
43604406 if (!dc_stream_set_cursor_position (crtc_state -> stream ,
43614407 & position ))
43624408 DRM_ERROR ("DC failed to set cursor position\n" );
4409+ mutex_unlock (& adev -> dm .dc_lock );
43634410 }
43644411}
43654412
@@ -4575,13 +4622,15 @@ static void amdgpu_dm_do_flip(struct drm_crtc *crtc,
45754622 & acrtc_state -> stream -> vrr_infopacket ;
45764623 }
45774624
4625+ mutex_lock (& adev -> dm .dc_lock );
45784626 dc_commit_updates_for_stream (adev -> dm .dc ,
45794627 surface_updates ,
45804628 1 ,
45814629 acrtc_state -> stream ,
45824630 & stream_update ,
45834631 & surface_updates -> surface ,
45844632 state );
4633+ mutex_unlock (& adev -> dm .dc_lock );
45854634
45864635 DRM_DEBUG_DRIVER ("%s Flipping to hi: 0x%x, low: 0x%x \n" ,
45874636 __func__ ,
@@ -4596,6 +4645,7 @@ static void amdgpu_dm_do_flip(struct drm_crtc *crtc,
45964645 * with a dc_plane_state and follow the atomic model a bit more closely here.
45974646 */
45984647static bool commit_planes_to_stream (
4648+ struct amdgpu_display_manager * dm ,
45994649 struct dc * dc ,
46004650 struct dc_plane_state * * plane_states ,
46014651 uint8_t new_plane_count ,
@@ -4672,11 +4722,13 @@ static bool commit_planes_to_stream(
46724722 updates [i ].scaling_info = & scaling_info [i ];
46734723 }
46744724
4725+ mutex_lock (& dm -> dc_lock );
46754726 dc_commit_updates_for_stream (
46764727 dc ,
46774728 updates ,
46784729 new_plane_count ,
46794730 dc_stream , stream_update , plane_states , state );
4731+ mutex_unlock (& dm -> dc_lock );
46804732
46814733 kfree (flip_addr );
46824734 kfree (plane_info );
@@ -4782,7 +4834,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
47824834
47834835 dc_stream_attach -> abm_level = acrtc_state -> abm_level ;
47844836
4785- if (false == commit_planes_to_stream (dm -> dc ,
4837+ if (false == commit_planes_to_stream (dm ,
4838+ dm -> dc ,
47864839 plane_states_constructed ,
47874840 planes_count ,
47884841 acrtc_state ,
@@ -4952,7 +5005,9 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
49525005
49535006 if (dc_state ) {
49545007 dm_enable_per_frame_crtc_master_sync (dc_state );
5008+ mutex_lock (& dm -> dc_lock );
49555009 WARN_ON (!dc_commit_state (dm -> dc , dc_state ));
5010+ mutex_unlock (& dm -> dc_lock );
49565011 }
49575012
49585013 for_each_new_crtc_in_state (state , crtc , new_crtc_state , i ) {
@@ -5014,6 +5069,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
50145069
50155070 /*TODO How it works with MPO ?*/
50165071 if (!commit_planes_to_stream (
5072+ dm ,
50175073 dm -> dc ,
50185074 status -> plane_states ,
50195075 status -> plane_count ,
@@ -5906,6 +5962,13 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
59065962 ret = - EINVAL ;
59075963 goto fail ;
59085964 }
5965+ } else if (state -> legacy_cursor_update ) {
5966+ /*
5967+ * This is a fast cursor update coming from the plane update
5968+ * helper, check if it can be done asynchronously for better
5969+ * performance.
5970+ */
5971+ state -> async_update = !drm_atomic_helper_async_check (dev , state );
59095972 }
59105973
59115974 /* Must be success */
0 commit comments