diff options
| -rw-r--r-- | drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 67 | ||||
| -rw-r--r-- | drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 8 |
2 files changed, 73 insertions, 2 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 ad0848dbd909..c13856a46d8e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | |||
| @@ -57,6 +57,7 @@ | |||
| 57 | 57 | ||
| 58 | #include <drm/drmP.h> | 58 | #include <drm/drmP.h> |
| 59 | #include <drm/drm_atomic.h> | 59 | #include <drm/drm_atomic.h> |
| 60 | #include <drm/drm_atomic_uapi.h> | ||
| 60 | #include <drm/drm_atomic_helper.h> | 61 | #include <drm/drm_atomic_helper.h> |
| 61 | #include <drm/drm_dp_mst_helper.h> | 62 | #include <drm/drm_dp_mst_helper.h> |
| 62 | #include <drm/drm_fb_helper.h> | 63 | #include <drm/drm_fb_helper.h> |
| @@ -133,6 +134,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state); | |||
| 133 | static int amdgpu_dm_atomic_check(struct drm_device *dev, | 134 | static int amdgpu_dm_atomic_check(struct drm_device *dev, |
| 134 | struct drm_atomic_state *state); | 135 | struct drm_atomic_state *state); |
| 135 | 136 | ||
| 137 | static void handle_cursor_update(struct drm_plane *plane, | ||
| 138 | struct drm_plane_state *old_plane_state); | ||
| 136 | 139 | ||
| 137 | 140 | ||
| 138 | 141 | ||
| @@ -402,6 +405,8 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) | |||
| 402 | /* Zero all the fields */ | 405 | /* Zero all the fields */ |
| 403 | memset(&init_data, 0, sizeof(init_data)); | 406 | memset(&init_data, 0, sizeof(init_data)); |
| 404 | 407 | ||
| 408 | mutex_init(&adev->dm.dc_lock); | ||
| 409 | |||
| 405 | if(amdgpu_dm_irq_init(adev)) { | 410 | if(amdgpu_dm_irq_init(adev)) { |
| 406 | DRM_ERROR("amdgpu: failed to initialize DM IRQ support.\n"); | 411 | DRM_ERROR("amdgpu: failed to initialize DM IRQ support.\n"); |
| 407 | goto error; | 412 | goto error; |
| @@ -516,6 +521,9 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev) | |||
| 516 | /* DC Destroy TODO: Replace destroy DAL */ | 521 | /* DC Destroy TODO: Replace destroy DAL */ |
| 517 | if (adev->dm.dc) | 522 | if (adev->dm.dc) |
| 518 | dc_destroy(&adev->dm.dc); | 523 | dc_destroy(&adev->dm.dc); |
| 524 | |||
| 525 | mutex_destroy(&adev->dm.dc_lock); | ||
| 526 | |||
| 519 | return; | 527 | return; |
| 520 | } | 528 | } |
| 521 | 529 | ||
| @@ -3617,10 +3625,43 @@ static int dm_plane_atomic_check(struct drm_plane *plane, | |||
| 3617 | return -EINVAL; | 3625 | return -EINVAL; |
| 3618 | } | 3626 | } |
| 3619 | 3627 | ||
| 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 | |||
| 3620 | static const struct drm_plane_helper_funcs dm_plane_helper_funcs = { | 3659 | static const struct drm_plane_helper_funcs dm_plane_helper_funcs = { |
| 3621 | .prepare_fb = dm_plane_helper_prepare_fb, | 3660 | .prepare_fb = dm_plane_helper_prepare_fb, |
| 3622 | .cleanup_fb = dm_plane_helper_cleanup_fb, | 3661 | .cleanup_fb = dm_plane_helper_cleanup_fb, |
| 3623 | .atomic_check = dm_plane_atomic_check, | 3662 | .atomic_check = dm_plane_atomic_check, |
| 3663 | .atomic_async_check = dm_plane_atomic_async_check, | ||
| 3664 | .atomic_async_update = dm_plane_atomic_async_update | ||
| 3624 | }; | 3665 | }; |
| 3625 | 3666 | ||
| 3626 | /* | 3667 | /* |
| @@ -4309,6 +4350,7 @@ static int get_cursor_position(struct drm_plane *plane, struct drm_crtc *crtc, | |||
| 4309 | static void handle_cursor_update(struct drm_plane *plane, | 4350 | static void handle_cursor_update(struct drm_plane *plane, |
| 4310 | struct drm_plane_state *old_plane_state) | 4351 | struct drm_plane_state *old_plane_state) |
| 4311 | { | 4352 | { |
| 4353 | struct amdgpu_device *adev = plane->dev->dev_private; | ||
| 4312 | struct amdgpu_framebuffer *afb = to_amdgpu_framebuffer(plane->state->fb); | 4354 | struct amdgpu_framebuffer *afb = to_amdgpu_framebuffer(plane->state->fb); |
| 4313 | struct drm_crtc *crtc = afb ? plane->state->crtc : old_plane_state->crtc; | 4355 | struct drm_crtc *crtc = afb ? plane->state->crtc : old_plane_state->crtc; |
| 4314 | struct dm_crtc_state *crtc_state = crtc ? to_dm_crtc_state(crtc->state) : NULL; | 4356 | 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, | |||
| 4333 | 4375 | ||
| 4334 | if (!position.enable) { | 4376 | if (!position.enable) { |
| 4335 | /* turn off cursor */ | 4377 | /* turn off cursor */ |
| 4336 | if (crtc_state && crtc_state->stream) | 4378 | if (crtc_state && crtc_state->stream) { |
| 4379 | mutex_lock(&adev->dm.dc_lock); | ||
| 4337 | dc_stream_set_cursor_position(crtc_state->stream, | 4380 | dc_stream_set_cursor_position(crtc_state->stream, |
| 4338 | &position); | 4381 | &position); |
| 4382 | mutex_unlock(&adev->dm.dc_lock); | ||
| 4383 | } | ||
| 4339 | return; | 4384 | return; |
| 4340 | } | 4385 | } |
| 4341 | 4386 | ||
| @@ -4353,6 +4398,7 @@ static void handle_cursor_update(struct drm_plane *plane, | |||
| 4353 | attributes.pitch = attributes.width; | 4398 | attributes.pitch = attributes.width; |
| 4354 | 4399 | ||
| 4355 | if (crtc_state->stream) { | 4400 | if (crtc_state->stream) { |
| 4401 | mutex_lock(&adev->dm.dc_lock); | ||
| 4356 | if (!dc_stream_set_cursor_attributes(crtc_state->stream, | 4402 | if (!dc_stream_set_cursor_attributes(crtc_state->stream, |
| 4357 | &attributes)) | 4403 | &attributes)) |
| 4358 | DRM_ERROR("DC failed to set cursor attributes\n"); | 4404 | DRM_ERROR("DC failed to set cursor attributes\n"); |
| @@ -4360,6 +4406,7 @@ static void handle_cursor_update(struct drm_plane *plane, | |||
| 4360 | if (!dc_stream_set_cursor_position(crtc_state->stream, | 4406 | if (!dc_stream_set_cursor_position(crtc_state->stream, |
| 4361 | &position)) | 4407 | &position)) |
| 4362 | DRM_ERROR("DC failed to set cursor position\n"); | 4408 | DRM_ERROR("DC failed to set cursor position\n"); |
| 4409 | mutex_unlock(&adev->dm.dc_lock); | ||
| 4363 | } | 4410 | } |
| 4364 | } | 4411 | } |
| 4365 | 4412 | ||
| @@ -4575,6 +4622,7 @@ static void amdgpu_dm_do_flip(struct drm_crtc *crtc, | |||
| 4575 | &acrtc_state->stream->vrr_infopacket; | 4622 | &acrtc_state->stream->vrr_infopacket; |
| 4576 | } | 4623 | } |
| 4577 | 4624 | ||
| 4625 | mutex_lock(&adev->dm.dc_lock); | ||
| 4578 | dc_commit_updates_for_stream(adev->dm.dc, | 4626 | dc_commit_updates_for_stream(adev->dm.dc, |
| 4579 | surface_updates, | 4627 | surface_updates, |
| 4580 | 1, | 4628 | 1, |
| @@ -4582,6 +4630,7 @@ static void amdgpu_dm_do_flip(struct drm_crtc *crtc, | |||
| 4582 | &stream_update, | 4630 | &stream_update, |
| 4583 | &surface_updates->surface, | 4631 | &surface_updates->surface, |
| 4584 | state); | 4632 | state); |
| 4633 | mutex_unlock(&adev->dm.dc_lock); | ||
| 4585 | 4634 | ||
| 4586 | DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n", | 4635 | DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n", |
| 4587 | __func__, | 4636 | __func__, |
| @@ -4596,6 +4645,7 @@ static void amdgpu_dm_do_flip(struct drm_crtc *crtc, | |||
| 4596 | * with a dc_plane_state and follow the atomic model a bit more closely here. | 4645 | * with a dc_plane_state and follow the atomic model a bit more closely here. |
| 4597 | */ | 4646 | */ |
| 4598 | static bool commit_planes_to_stream( | 4647 | static bool commit_planes_to_stream( |
| 4648 | struct amdgpu_display_manager *dm, | ||
| 4599 | struct dc *dc, | 4649 | struct dc *dc, |
| 4600 | struct dc_plane_state **plane_states, | 4650 | struct dc_plane_state **plane_states, |
| 4601 | uint8_t new_plane_count, | 4651 | uint8_t new_plane_count, |
| @@ -4672,11 +4722,13 @@ static bool commit_planes_to_stream( | |||
| 4672 | updates[i].scaling_info = &scaling_info[i]; | 4722 | updates[i].scaling_info = &scaling_info[i]; |
| 4673 | } | 4723 | } |
| 4674 | 4724 | ||
| 4725 | mutex_lock(&dm->dc_lock); | ||
| 4675 | dc_commit_updates_for_stream( | 4726 | dc_commit_updates_for_stream( |
| 4676 | dc, | 4727 | dc, |
| 4677 | updates, | 4728 | updates, |
| 4678 | new_plane_count, | 4729 | new_plane_count, |
| 4679 | dc_stream, stream_update, plane_states, state); | 4730 | dc_stream, stream_update, plane_states, state); |
| 4731 | mutex_unlock(&dm->dc_lock); | ||
| 4680 | 4732 | ||
| 4681 | kfree(flip_addr); | 4733 | kfree(flip_addr); |
| 4682 | kfree(plane_info); | 4734 | kfree(plane_info); |
| @@ -4782,7 +4834,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, | |||
| 4782 | 4834 | ||
| 4783 | dc_stream_attach->abm_level = acrtc_state->abm_level; | 4835 | dc_stream_attach->abm_level = acrtc_state->abm_level; |
| 4784 | 4836 | ||
| 4785 | if (false == commit_planes_to_stream(dm->dc, | 4837 | if (false == commit_planes_to_stream(dm, |
| 4838 | dm->dc, | ||
| 4786 | plane_states_constructed, | 4839 | plane_states_constructed, |
| 4787 | planes_count, | 4840 | planes_count, |
| 4788 | acrtc_state, | 4841 | acrtc_state, |
| @@ -4952,7 +5005,9 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) | |||
| 4952 | 5005 | ||
| 4953 | if (dc_state) { | 5006 | if (dc_state) { |
| 4954 | dm_enable_per_frame_crtc_master_sync(dc_state); | 5007 | dm_enable_per_frame_crtc_master_sync(dc_state); |
| 5008 | mutex_lock(&dm->dc_lock); | ||
| 4955 | WARN_ON(!dc_commit_state(dm->dc, dc_state)); | 5009 | WARN_ON(!dc_commit_state(dm->dc, dc_state)); |
| 5010 | mutex_unlock(&dm->dc_lock); | ||
| 4956 | } | 5011 | } |
| 4957 | 5012 | ||
| 4958 | for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { | 5013 | 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) | |||
| 5014 | 5069 | ||
| 5015 | /*TODO How it works with MPO ?*/ | 5070 | /*TODO How it works with MPO ?*/ |
| 5016 | if (!commit_planes_to_stream( | 5071 | if (!commit_planes_to_stream( |
| 5072 | dm, | ||
| 5017 | dm->dc, | 5073 | dm->dc, |
| 5018 | status->plane_states, | 5074 | status->plane_states, |
| 5019 | status->plane_count, | 5075 | status->plane_count, |
| @@ -5906,6 +5962,13 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, | |||
| 5906 | ret = -EINVAL; | 5962 | ret = -EINVAL; |
| 5907 | goto fail; | 5963 | goto fail; |
| 5908 | } | 5964 | } |
| 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); | ||
| 5909 | } | 5972 | } |
| 5910 | 5973 | ||
| 5911 | /* Must be success */ | 5974 | /* Must be success */ |
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 4326dc256491..25bb91ee80ba 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | |||
| @@ -135,6 +135,14 @@ struct amdgpu_display_manager { | |||
| 135 | struct drm_modeset_lock atomic_obj_lock; | 135 | struct drm_modeset_lock atomic_obj_lock; |
| 136 | 136 | ||
| 137 | /** | 137 | /** |
| 138 | * @dc_lock: | ||
| 139 | * | ||
| 140 | * Guards access to DC functions that can issue register write | ||
| 141 | * sequences. | ||
| 142 | */ | ||
| 143 | struct mutex dc_lock; | ||
| 144 | |||
| 145 | /** | ||
| 138 | * @irq_handler_list_low_tab: | 146 | * @irq_handler_list_low_tab: |
| 139 | * | 147 | * |
| 140 | * Low priority IRQ handler table. | 148 | * Low priority IRQ handler table. |
