aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
diff options
context:
space:
mode:
authorAnthony Koo <Anthony.Koo@amd.com>2018-08-21 14:40:28 -0500
committerAlex Deucher <alexander.deucher@amd.com>2018-08-27 11:10:51 -0500
commit98e6436d3af5fef7ca9b59d865dd5807ede36fb9 (patch)
tree1ece2c3ff69196a3b22b001da1b6d1a8b58cac7e /drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
parentdrm/amdgpu: fill in amdgpu_dm_remove_sink_from_freesync_module (diff)
downloadlinux-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.c288
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;
-}