diff options
| author | Anthony Koo <Anthony.Koo@amd.com> | 2018-08-21 14:40:28 -0500 |
|---|---|---|
| committer | Alex Deucher <alexander.deucher@amd.com> | 2018-08-27 11:10:51 -0500 |
| commit | 98e6436d3af5fef7ca9b59d865dd5807ede36fb9 (patch) | |
| tree | 1ece2c3ff69196a3b22b001da1b6d1a8b58cac7e /drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | |
| parent | drm/amdgpu: fill in amdgpu_dm_remove_sink_from_freesync_module (diff) | |
| download | linux-98e6436d3af5fef7ca9b59d865dd5807ede36fb9.tar.gz linux-98e6436d3af5fef7ca9b59d865dd5807ede36fb9.zip | |
drm/amd/display: Refactor FreeSync module
Remove dependency on internal sink map and instead
use existing stream and plane state
Signed-off-by: Anthony Koo <Anthony.Koo@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Tony Cheng <Tony.Cheng@amd.com>
Acked-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c')
| -rw-r--r-- | drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 288 |
1 files changed, 152 insertions, 136 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 0c805be054a1..5f5e5ea20d78 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -839,8 +839,7 @@ amdgpu_dm_update_connector_after_detect(struct amdgpu_dm_connector *aconnector) if (sink) { if (aconnector->dc_sink) { - amdgpu_dm_remove_sink_from_freesync_module( - connector); + amdgpu_dm_update_freesync_caps(connector, NULL); /* retain and release bellow are used for * bump up refcount for sink because the link don't point * to it anymore after disconnect so on next crtc to connector @@ -850,10 +849,10 @@ amdgpu_dm_update_connector_after_detect(struct amdgpu_dm_connector *aconnector) dc_sink_release(aconnector->dc_sink); } aconnector->dc_sink = sink; - amdgpu_dm_add_sink_to_freesync_module( - connector, aconnector->edid); + amdgpu_dm_update_freesync_caps(connector, + aconnector->edid); } else { - amdgpu_dm_remove_sink_from_freesync_module(connector); + amdgpu_dm_update_freesync_caps(connector, NULL); if (!aconnector->dc_sink) aconnector->dc_sink = aconnector->dc_em_sink; else if (aconnector->dc_sink != aconnector->dc_em_sink) @@ -890,8 +889,7 @@ amdgpu_dm_update_connector_after_detect(struct amdgpu_dm_connector *aconnector) /* TODO: check if we still need the S3 mode update workaround. * If yes, put it here. */ if (aconnector->dc_sink) - amdgpu_dm_remove_sink_from_freesync_module( - connector); + amdgpu_dm_update_freesync_caps(connector, NULL); aconnector->dc_sink = sink; if (sink->dc_edid.length == 0) { @@ -904,10 +902,10 @@ amdgpu_dm_update_connector_after_detect(struct amdgpu_dm_connector *aconnector) drm_connector_update_edid_property(connector, aconnector->edid); } - amdgpu_dm_add_sink_to_freesync_module(connector, aconnector->edid); + amdgpu_dm_update_freesync_caps(connector, aconnector->edid); } else { - amdgpu_dm_remove_sink_from_freesync_module(connector); + amdgpu_dm_update_freesync_caps(connector, NULL); drm_connector_update_edid_property(connector, NULL); aconnector->num_modes = 0; aconnector->dc_sink = NULL; @@ -1580,26 +1578,68 @@ static void dm_bandwidth_update(struct amdgpu_device *adev) static int amdgpu_notify_freesync(struct drm_device *dev, void *data, struct drm_file *filp) { - struct mod_freesync_params freesync_params; - uint8_t num_streams; + struct drm_atomic_state *state; + struct drm_modeset_acquire_ctx ctx; + struct drm_crtc *crtc; + struct drm_connector *connector; + struct drm_connector_state *old_con_state, *new_con_state; + int ret = 0; uint8_t i; + bool enable = false; - struct amdgpu_device *adev = dev->dev_private; - int r = 0; + drm_modeset_acquire_init(&ctx, 0); + + state = drm_atomic_state_alloc(dev); + if (!state) { + ret = -ENOMEM; + goto out; + } + state->acquire_ctx = &ctx; + +retry: + drm_for_each_crtc(crtc, dev) { + ret = drm_atomic_add_affected_connectors(state, crtc); + if (ret) + goto fail; + + /* TODO rework amdgpu_dm_commit_planes so we don't need this */ + ret = drm_atomic_add_affected_planes(state, crtc); + if (ret) + goto fail; + } - /* Get freesync enable flag from DRM */ + for_each_oldnew_connector_in_state(state, connector, old_con_state, new_con_state, i) { + struct dm_connector_state *dm_new_con_state = to_dm_connector_state(new_con_state); + struct drm_crtc_state *new_crtc_state; + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(dm_new_con_state->base.crtc); + struct dm_crtc_state *dm_new_crtc_state; - num_streams = dc_get_current_stream_count(adev->dm.dc); + if (!acrtc) { + ASSERT(0); + continue; + } - for (i = 0; i < num_streams; i++) { - struct dc_stream_state *stream; - stream = dc_get_stream_at_index(adev->dm.dc, i); + new_crtc_state = drm_atomic_get_new_crtc_state(state, &acrtc->base); + dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); - mod_freesync_update_state(adev->dm.freesync_module, - &stream, 1, &freesync_params); + dm_new_crtc_state->freesync_enabled = enable; } - return r; + ret = drm_atomic_commit(state); + +fail: + if (ret == -EDEADLK) { + drm_atomic_state_clear(state); + drm_modeset_backoff(&ctx); + goto retry; + } + + drm_atomic_state_put(state); + +out: + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); + return ret; } static const struct amdgpu_display_funcs dm_display_funcs = { @@ -2563,6 +2603,10 @@ dm_crtc_duplicate_state(struct drm_crtc *crtc) dc_stream_retain(state->stream); } + state->adjust = cur->adjust; + state->vrr_infopacket = cur->vrr_infopacket; + state->freesync_enabled = cur->freesync_enabled; + /* TODO Duplicate dc_stream after objects are stream object is flattened */ return &state->base; @@ -2770,13 +2814,15 @@ amdgpu_dm_connector_atomic_duplicate_state(struct drm_connector *connector) struct dm_connector_state *new_state = kmemdup(state, sizeof(*state), GFP_KERNEL); - if (new_state) { - __drm_atomic_helper_connector_duplicate_state(connector, - &new_state->base); - return &new_state->base; - } + if (!new_state) + return NULL; - return NULL; + __drm_atomic_helper_connector_duplicate_state(connector, &new_state->base); + + new_state->freesync_capable = state->freesync_capable; + new_state->freesync_enable = state->freesync_enable; + + return &new_state->base; } static const struct drm_connector_funcs amdgpu_dm_connector_funcs = { @@ -3786,8 +3832,6 @@ static void remove_stream(struct amdgpu_device *adev, struct dc_stream_state *stream) { /* this is the update mode case */ - if (adev->dm.freesync_module) - mod_freesync_remove_stream(adev->dm.freesync_module, stream); acrtc->otg_inst = -1; acrtc->enabled = false; @@ -4055,6 +4099,11 @@ static bool commit_planes_to_stream( stream_update->dst = dc_stream->dst; stream_update->out_transfer_func = dc_stream->out_transfer_func; + if (dm_new_crtc_state->freesync_enabled != dm_old_crtc_state->freesync_enabled) { + stream_update->vrr_infopacket = &dc_stream->vrr_infopacket; + stream_update->adjust = &dc_stream->adjust; + } + for (i = 0; i < new_plane_count; i++) { updates[i].surface = plane_states[i]; updates[i].gamma = @@ -4190,6 +4239,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, spin_unlock_irqrestore(&pcrtc->dev->event_lock, flags); } + dc_stream_attach->adjust = acrtc_state->adjust; + dc_stream_attach->vrr_infopacket = acrtc_state->vrr_infopacket; if (false == commit_planes_to_stream(dm->dc, plane_states_constructed, @@ -4339,62 +4390,6 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) } } /* for_each_crtc_in_state() */ - /* - * Add streams after required streams from new and replaced streams - * are removed from freesync module - */ - if (adev->dm.freesync_module) { - for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, - new_crtc_state, i) { - struct amdgpu_dm_connector *aconnector = NULL; - struct dm_connector_state *dm_new_con_state = NULL; - struct amdgpu_crtc *acrtc = NULL; - bool modeset_needed; - - dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); - dm_old_crtc_state = to_dm_crtc_state(old_crtc_state); - modeset_needed = modeset_required( - new_crtc_state, - dm_new_crtc_state->stream, - dm_old_crtc_state->stream); - /* We add stream to freesync if: - * 1. Said stream is not null, and - * 2. A modeset is requested. This means that the - * stream was removed previously, and needs to be - * replaced. - */ - if (dm_new_crtc_state->stream == NULL || - !modeset_needed) - continue; - - acrtc = to_amdgpu_crtc(crtc); - - aconnector = - amdgpu_dm_find_first_crtc_matching_connector( - state, crtc); - if (!aconnector) { - DRM_DEBUG_DRIVER("Atomic commit: Failed to " - "find connector for acrtc " - "id:%d skipping freesync " - "init\n", - acrtc->crtc_id); - continue; - } - - mod_freesync_add_stream(adev->dm.freesync_module, - dm_new_crtc_state->stream, - &aconnector->caps); - new_con_state = drm_atomic_get_new_connector_state( - state, &aconnector->base); - dm_new_con_state = to_dm_connector_state(new_con_state); - - mod_freesync_set_user_enable(adev->dm.freesync_module, - &dm_new_crtc_state->stream, - 1, - &dm_new_con_state->user_enable); - } - } - if (dm_state->context) { dm_enable_per_frame_crtc_master_sync(dm_state->context); WARN_ON(!dc_commit_state(dm->dc, dm_state->context)); @@ -4448,6 +4443,9 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) WARN_ON(!status); WARN_ON(!status->plane_count); + dm_new_crtc_state->stream->adjust = dm_new_crtc_state->adjust; + dm_new_crtc_state->stream->vrr_infopacket = dm_new_crtc_state->vrr_infopacket; + /*TODO How it works with MPO ?*/ if (!commit_planes_to_stream( dm->dc, @@ -4480,11 +4478,6 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) if (dm_new_crtc_state->stream == NULL || !modeset_needed) continue; - if (adev->dm.freesync_module) - mod_freesync_notify_mode_change( - adev->dm.freesync_module, - &dm_new_crtc_state->stream, 1); - manage_dm_interrupts(adev, acrtc, true); } @@ -4667,7 +4660,42 @@ static int do_aquire_global_lock(struct drm_device *dev, return ret < 0 ? ret : 0; } -static int dm_update_crtcs_state(struct dc *dc, +void set_freesync_on_stream(struct amdgpu_display_manager *dm, + struct dm_crtc_state *new_crtc_state, + struct dm_connector_state *new_con_state, + struct dc_stream_state *new_stream) +{ + struct mod_freesync_config config = {0}; + struct mod_vrr_params vrr = {0}; + struct dc_info_packet vrr_infopacket = {0}; + struct amdgpu_dm_connector *aconnector = + to_amdgpu_dm_connector(new_con_state->base.connector); + + if (new_con_state->freesync_capable && + new_con_state->freesync_enable) { + config.state = new_crtc_state->freesync_enabled ? + VRR_STATE_ACTIVE_VARIABLE : + VRR_STATE_INACTIVE; + config.min_refresh_in_uhz = + aconnector->min_vfreq * 1000000; + config.max_refresh_in_uhz = + aconnector->max_vfreq * 1000000; + } + + mod_freesync_build_vrr_params(dm->freesync_module, + new_stream, + &config, &vrr); + + mod_freesync_build_vrr_infopacket(dm->freesync_module, + new_stream, + &vrr, + &vrr_infopacket); + + new_crtc_state->adjust = vrr.adjust; + new_crtc_state->vrr_infopacket = vrr_infopacket; +} + +static int dm_update_crtcs_state(struct amdgpu_display_manager *dm, struct drm_atomic_state *state, bool enable, bool *lock_and_validation_needed) @@ -4737,6 +4765,9 @@ static int dm_update_crtcs_state(struct dc *dc, break; } + set_freesync_on_stream(dm, dm_new_crtc_state, + dm_new_conn_state, new_stream); + if (dc_is_stream_unchanged(new_stream, dm_old_crtc_state->stream) && dc_is_stream_scaling_unchanged(new_stream, dm_old_crtc_state->stream)) { new_crtc_state->mode_changed = false; @@ -4745,6 +4776,9 @@ static int dm_update_crtcs_state(struct dc *dc, } } + if (dm_old_crtc_state->freesync_enabled != dm_new_crtc_state->freesync_enabled) + new_crtc_state->mode_changed = true; + if (!drm_atomic_crtc_needs_modeset(new_crtc_state)) goto next_crtc; @@ -4771,7 +4805,7 @@ static int dm_update_crtcs_state(struct dc *dc, /* i.e. reset mode */ if (dc_remove_stream_from_ctx( - dc, + dm->dc, dm_state->context, dm_old_crtc_state->stream) != DC_OK) { ret = -EINVAL; @@ -4808,7 +4842,7 @@ static int dm_update_crtcs_state(struct dc *dc, crtc->base.id); if (dc_add_stream_to_ctx( - dc, + dm->dc, dm_state->context, dm_new_crtc_state->stream) != DC_OK) { ret = -EINVAL; @@ -4857,6 +4891,8 @@ next_crtc: goto fail; amdgpu_dm_set_ctm(dm_new_crtc_state); } + + } return ret; @@ -5024,8 +5060,12 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, goto fail; for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { + struct dm_crtc_state *dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); + struct dm_crtc_state *dm_old_crtc_state = to_dm_crtc_state(old_crtc_state); + if (!drm_atomic_crtc_needs_modeset(new_crtc_state) && - !new_crtc_state->color_mgmt_changed) + !new_crtc_state->color_mgmt_changed && + (dm_old_crtc_state->freesync_enabled == dm_new_crtc_state->freesync_enabled)) continue; if (!new_crtc_state->enable) @@ -5051,13 +5091,13 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, } /* Disable all crtcs which require disable */ - ret = dm_update_crtcs_state(dc, state, false, &lock_and_validation_needed); + ret = dm_update_crtcs_state(&adev->dm, state, false, &lock_and_validation_needed); if (ret) { goto fail; } /* Enable all crtcs which require enable */ - ret = dm_update_crtcs_state(dc, state, true, &lock_and_validation_needed); + ret = dm_update_crtcs_state(&adev->dm, state, true, &lock_and_validation_needed); if (ret) { goto fail; } @@ -5150,8 +5190,8 @@ static bool is_dp_capable_without_timing_msa(struct dc *dc, return capable; } -void amdgpu_dm_add_sink_to_freesync_module(struct drm_connector *connector, - struct edid *edid) +void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, + struct edid *edid) { int i; bool edid_check_required; @@ -5170,6 +5210,18 @@ void amdgpu_dm_add_sink_to_freesync_module(struct drm_connector *connector, return; } + if (!edid) { + dm_con_state = to_dm_connector_state(connector->state); + + amdgpu_dm_connector->min_vfreq = 0; + amdgpu_dm_connector->max_vfreq = 0; + amdgpu_dm_connector->pixel_clock_mhz = 0; + + dm_con_state->freesync_capable = false; + dm_con_state->freesync_enable = false; + return; + } + dm_con_state = to_dm_connector_state(connector->state); edid_check_required = false; @@ -5220,46 +5272,10 @@ void amdgpu_dm_add_sink_to_freesync_module(struct drm_connector *connector, } if (amdgpu_dm_connector->max_vfreq - - amdgpu_dm_connector->min_vfreq > 10) { - amdgpu_dm_connector->caps.supported = true; - amdgpu_dm_connector->caps.min_refresh_in_micro_hz = - amdgpu_dm_connector->min_vfreq * 1000000; - amdgpu_dm_connector->caps.max_refresh_in_micro_hz = - amdgpu_dm_connector->max_vfreq * 1000000; + amdgpu_dm_connector->min_vfreq > 10) { + dm_con_state->freesync_capable = true; } } } -void amdgpu_dm_remove_sink_from_freesync_module(struct drm_connector *connector) -{ - struct amdgpu_dm_connector *amdgpu_dm_connector = - to_amdgpu_dm_connector(connector); - struct dm_connector_state *dm_con_state; - struct drm_device *dev = connector->dev; - struct amdgpu_device *adev = dev->dev_private; - - if (!amdgpu_dm_connector->dc_sink || !adev->dm.freesync_module) { - DRM_ERROR("dc_sink NULL or no free_sync module.\n"); - return; - } - - if (!connector->state) { - DRM_ERROR("%s - Connector has no state", __func__); - return; - } - - dm_con_state = to_dm_connector_state(connector->state); - - amdgpu_dm_connector->min_vfreq = 0; - amdgpu_dm_connector->max_vfreq = 0; - amdgpu_dm_connector->pixel_clock_mhz = 0; - - memset(&amdgpu_dm_connector->caps, 0, sizeof(amdgpu_dm_connector->caps)); - - dm_con_state->freesync_capable = false; - - dm_con_state->user_enable.enable_for_gaming = false; - dm_con_state->user_enable.enable_for_static = false; - dm_con_state->user_enable.enable_for_video = false; -} |
