aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMario Kleiner <mario.kleiner.de@gmail.com>2019-04-26 17:40:16 -0400
committerAlex Deucher <alexander.deucher@amd.com>2019-04-29 15:59:44 -0400
commit09aef2c48e799b39d1595038c3a993c0279c292d (patch)
tree948ea5765a6c4f40bf78c65b78a9943f25264916
parentdc4a9049f023cff6f3c7f0765a706595444c4bd2 (diff)
drm/amd/display: Compensate for pre-DCE12 BTR-VRR hw limitations. (v3)
Pre-DCE12 needs special treatment for BTR / low framerate compensation for more stable behaviour: According to comments in the code and some testing on DCE-8 and DCE-11, DCE-11 and earlier only apply VTOTAL_MIN/MAX programming with a lag of one frame, so the special BTR hw programming for intermediate fixed duration frames must be done inside the current frame at flip submission in atomic commit tail, ie. one vblank earlier, and the fixed refresh intermediate frame mode must be also terminated one vblank earlier on pre-DCE12 display engines. To achieve proper termination on < DCE-12 shift the point when the switch-back from fixed vblank duration to variable vblank duration happens from the start of VBLANK (vblank irq, as done on DCE-12+) to back-porch or end of VBLANK (handled by vupdate irq handler). We must leave the switch-back code inside VBLANK irq for DCE12+, as before. Doing this, we get much better behaviour of BTR for up-sweeps, ie. going from short to long frame durations (~high to low fps) and for constant framerate flips, as tested on DCE-8 and DCE-11. Behaviour is still not quite as good as on DCN-1 though. On down-sweeps, going from long to short frame durations (low fps to high fps) < DCE-12 is a little bit improved, although by far not as much as for up-sweeps and constant fps. v2: Fix some wrong locking, as pointed out by Nicholas. v3: Simplify if-condition in vupdate-irq - nit by Nicholas. Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com> Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c48
1 files changed, 44 insertions, 4 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 645188baa708..6eb2bd554ba1 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -364,6 +364,7 @@ static void dm_vupdate_high_irq(void *interrupt_params)
364 struct amdgpu_device *adev = irq_params->adev; 364 struct amdgpu_device *adev = irq_params->adev;
365 struct amdgpu_crtc *acrtc; 365 struct amdgpu_crtc *acrtc;
366 struct dm_crtc_state *acrtc_state; 366 struct dm_crtc_state *acrtc_state;
367 unsigned long flags;
367 368
368 acrtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_VUPDATE); 369 acrtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_VUPDATE);
369 370
@@ -379,8 +380,25 @@ static void dm_vupdate_high_irq(void *interrupt_params)
379 * page-flip completion events that have been queued to us 380 * page-flip completion events that have been queued to us
380 * if a pageflip happened inside front-porch. 381 * if a pageflip happened inside front-porch.
381 */ 382 */
382 if (amdgpu_dm_vrr_active(acrtc_state)) 383 if (amdgpu_dm_vrr_active(acrtc_state)) {
383 drm_crtc_handle_vblank(&acrtc->base); 384 drm_crtc_handle_vblank(&acrtc->base);
385
386 /* BTR processing for pre-DCE12 ASICs */
387 if (acrtc_state->stream &&
388 adev->family < AMDGPU_FAMILY_AI) {
389 spin_lock_irqsave(&adev->ddev->event_lock, flags);
390 mod_freesync_handle_v_update(
391 adev->dm.freesync_module,
392 acrtc_state->stream,
393 &acrtc_state->vrr_params);
394
395 dc_stream_adjust_vmin_vmax(
396 adev->dm.dc,
397 acrtc_state->stream,
398 &acrtc_state->vrr_params.adjust);
399 spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
400 }
401 }
384 } 402 }
385} 403}
386 404
@@ -390,6 +408,7 @@ static void dm_crtc_high_irq(void *interrupt_params)
390 struct amdgpu_device *adev = irq_params->adev; 408 struct amdgpu_device *adev = irq_params->adev;
391 struct amdgpu_crtc *acrtc; 409 struct amdgpu_crtc *acrtc;
392 struct dm_crtc_state *acrtc_state; 410 struct dm_crtc_state *acrtc_state;
411 unsigned long flags;
393 412
394 acrtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_VBLANK); 413 acrtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_VBLANK);
395 414
@@ -412,9 +431,10 @@ static void dm_crtc_high_irq(void *interrupt_params)
412 */ 431 */
413 amdgpu_dm_crtc_handle_crc_irq(&acrtc->base); 432 amdgpu_dm_crtc_handle_crc_irq(&acrtc->base);
414 433
415 if (acrtc_state->stream && 434 if (acrtc_state->stream && adev->family >= AMDGPU_FAMILY_AI &&
416 acrtc_state->vrr_params.supported && 435 acrtc_state->vrr_params.supported &&
417 acrtc_state->freesync_config.state == VRR_STATE_ACTIVE_VARIABLE) { 436 acrtc_state->freesync_config.state == VRR_STATE_ACTIVE_VARIABLE) {
437 spin_lock_irqsave(&adev->ddev->event_lock, flags);
418 mod_freesync_handle_v_update( 438 mod_freesync_handle_v_update(
419 adev->dm.freesync_module, 439 adev->dm.freesync_module,
420 acrtc_state->stream, 440 acrtc_state->stream,
@@ -424,6 +444,7 @@ static void dm_crtc_high_irq(void *interrupt_params)
424 adev->dm.dc, 444 adev->dm.dc,
425 acrtc_state->stream, 445 acrtc_state->stream,
426 &acrtc_state->vrr_params.adjust); 446 &acrtc_state->vrr_params.adjust);
447 spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
427 } 448 }
428 } 449 }
429} 450}
@@ -5054,8 +5075,10 @@ static void update_freesync_state_on_stream(
5054 struct dc_plane_state *surface, 5075 struct dc_plane_state *surface,
5055 u32 flip_timestamp_in_us) 5076 u32 flip_timestamp_in_us)
5056{ 5077{
5057 struct mod_vrr_params vrr_params = new_crtc_state->vrr_params; 5078 struct mod_vrr_params vrr_params;
5058 struct dc_info_packet vrr_infopacket = {0}; 5079 struct dc_info_packet vrr_infopacket = {0};
5080 struct amdgpu_device *adev = dm->adev;
5081 unsigned long flags;
5059 5082
5060 if (!new_stream) 5083 if (!new_stream)
5061 return; 5084 return;
@@ -5068,6 +5091,9 @@ static void update_freesync_state_on_stream(
5068 if (!new_stream->timing.h_total || !new_stream->timing.v_total) 5091 if (!new_stream->timing.h_total || !new_stream->timing.v_total)
5069 return; 5092 return;
5070 5093
5094 spin_lock_irqsave(&adev->ddev->event_lock, flags);
5095 vrr_params = new_crtc_state->vrr_params;
5096
5071 if (surface) { 5097 if (surface) {
5072 mod_freesync_handle_preflip( 5098 mod_freesync_handle_preflip(
5073 dm->freesync_module, 5099 dm->freesync_module,
@@ -5075,6 +5101,12 @@ static void update_freesync_state_on_stream(
5075 new_stream, 5101 new_stream,
5076 flip_timestamp_in_us, 5102 flip_timestamp_in_us,
5077 &vrr_params); 5103 &vrr_params);
5104
5105 if (adev->family < AMDGPU_FAMILY_AI &&
5106 amdgpu_dm_vrr_active(new_crtc_state)) {
5107 mod_freesync_handle_v_update(dm->freesync_module,
5108 new_stream, &vrr_params);
5109 }
5078 } 5110 }
5079 5111
5080 mod_freesync_build_vrr_infopacket( 5112 mod_freesync_build_vrr_infopacket(
@@ -5106,6 +5138,8 @@ static void update_freesync_state_on_stream(
5106 new_crtc_state->base.crtc->base.id, 5138 new_crtc_state->base.crtc->base.id,
5107 (int)new_crtc_state->base.vrr_enabled, 5139 (int)new_crtc_state->base.vrr_enabled,
5108 (int)vrr_params.state); 5140 (int)vrr_params.state);
5141
5142 spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
5109} 5143}
5110 5144
5111static void pre_update_freesync_state_on_stream( 5145static void pre_update_freesync_state_on_stream(
@@ -5113,8 +5147,10 @@ static void pre_update_freesync_state_on_stream(
5113 struct dm_crtc_state *new_crtc_state) 5147 struct dm_crtc_state *new_crtc_state)
5114{ 5148{
5115 struct dc_stream_state *new_stream = new_crtc_state->stream; 5149 struct dc_stream_state *new_stream = new_crtc_state->stream;
5116 struct mod_vrr_params vrr_params = new_crtc_state->vrr_params; 5150 struct mod_vrr_params vrr_params;
5117 struct mod_freesync_config config = new_crtc_state->freesync_config; 5151 struct mod_freesync_config config = new_crtc_state->freesync_config;
5152 struct amdgpu_device *adev = dm->adev;
5153 unsigned long flags;
5118 5154
5119 if (!new_stream) 5155 if (!new_stream)
5120 return; 5156 return;
@@ -5126,6 +5162,9 @@ static void pre_update_freesync_state_on_stream(
5126 if (!new_stream->timing.h_total || !new_stream->timing.v_total) 5162 if (!new_stream->timing.h_total || !new_stream->timing.v_total)
5127 return; 5163 return;
5128 5164
5165 spin_lock_irqsave(&adev->ddev->event_lock, flags);
5166 vrr_params = new_crtc_state->vrr_params;
5167
5129 if (new_crtc_state->vrr_supported && 5168 if (new_crtc_state->vrr_supported &&
5130 config.min_refresh_in_uhz && 5169 config.min_refresh_in_uhz &&
5131 config.max_refresh_in_uhz) { 5170 config.max_refresh_in_uhz) {
@@ -5146,6 +5185,7 @@ static void pre_update_freesync_state_on_stream(
5146 sizeof(vrr_params.adjust)) != 0); 5185 sizeof(vrr_params.adjust)) != 0);
5147 5186
5148 new_crtc_state->vrr_params = vrr_params; 5187 new_crtc_state->vrr_params = vrr_params;
5188 spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
5149} 5189}
5150 5190
5151static void amdgpu_dm_handle_vrr_transition(struct dm_crtc_state *old_state, 5191static void amdgpu_dm_handle_vrr_transition(struct dm_crtc_state *old_state,