[PATCH 34/81] drm/amd/display: Remove acrtc->stream
sunpeng.li at amd.com
sunpeng.li at amd.com
Tue Jul 25 13:53:54 UTC 2017
From: Andrey Grodzovsky <Andrey.Grodzovsky at amd.com>
Remove acrtc->stream and move it into dm_crtc_state.
This allows to get rid of dm_atomic_state->dm_set.
Also reuse streams created in atomic_check during
commit.
Change-Id: I8d9868695a3a530c55e7fa934f9d5ea3800dfb8b
Signed-off-by: Andrey Grodzovsky <Andrey.Grodzovsky at amd.com>
Reviewed-by: Tony Cheng <Tony.Cheng at amd.com>
Acked-by: Harry Wentland <Harry.Wentland at amd.com>
---
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 33 +-
.../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 411 +++++++++++----------
.../drm/amd/display/amdgpu_dm/amdgpu_dm_types.h | 9 +-
drivers/gpu/drm/amd/display/dc/dc.h | 2 -
4 files changed, 232 insertions(+), 223 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 d0651b6..e5a27ab 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -100,13 +100,16 @@ static u32 dm_vblank_get_counter(struct amdgpu_device *adev, int crtc)
return 0;
else {
struct amdgpu_crtc *acrtc = adev->mode_info.crtcs[crtc];
+ struct dm_crtc_state *acrtc_state = to_dm_crtc_state(
+ acrtc->base.state);
- if (NULL == acrtc->stream) {
+
+ if (acrtc_state->stream == NULL) {
DRM_ERROR("dc_stream is NULL for crtc '%d'!\n", crtc);
return 0;
}
- return dc_stream_get_vblank_counter(acrtc->stream);
+ return dc_stream_get_vblank_counter(acrtc_state->stream);
}
}
@@ -119,8 +122,10 @@ static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
return -EINVAL;
else {
struct amdgpu_crtc *acrtc = adev->mode_info.crtcs[crtc];
+ struct dm_crtc_state *acrtc_state = to_dm_crtc_state(
+ acrtc->base.state);
- if (NULL == acrtc->stream) {
+ if (acrtc_state->stream == NULL) {
DRM_ERROR("dc_stream is NULL for crtc '%d'!\n", crtc);
return 0;
}
@@ -129,7 +134,7 @@ static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
* TODO rework base driver to use values directly.
* for now parse it back into reg-format
*/
- dc_stream_get_scanoutpos(acrtc->stream,
+ dc_stream_get_scanoutpos(acrtc_state->stream,
&v_blank_start,
&v_blank_end,
&h_position,
@@ -652,22 +657,12 @@ dm_atomic_state_alloc(struct drm_device *dev)
void dm_atomic_state_clear(struct drm_atomic_state *state)
{
struct dm_atomic_state *dm_state = to_dm_atomic_state(state);
- int i, j;
-
- for (i = 0; i < dm_state->set_count; i++) {
- for (j = 0; j < dm_state->set[i].surface_count; j++) {
- dc_surface_release(dm_state->set[i].surfaces[j]);
- dm_state->set[i].surfaces[j] = NULL;
- }
- dc_stream_release(dm_state->set[i].stream);
- dm_state->set[i].stream = NULL;
+ if (dm_state->context) {
+ dc_resource_validate_ctx_destruct(dm_state->context);
+ dm_free(dm_state->context);
+ dm_state->context = NULL;
}
- dm_state->set_count = 0;
-
- dc_resource_validate_ctx_destruct(dm_state->context);
- dm_free(dm_state->context);
- dm_state->context = NULL;
drm_atomic_state_default_clear(state);
}
@@ -676,7 +671,7 @@ static const struct drm_mode_config_funcs amdgpu_dm_mode_funcs = {
.fb_create = amdgpu_user_framebuffer_create,
.output_poll_changed = amdgpu_output_poll_changed,
.atomic_check = amdgpu_dm_atomic_check,
- .atomic_commit = drm_atomic_helper_commit,
+ .atomic_commit = amdgpu_dm_atomic_commit,
.atomic_state_alloc = dm_atomic_state_alloc,
.atomic_state_clear = dm_atomic_state_clear,
};
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c
index 2a5c7b1..750e095 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c
@@ -87,6 +87,7 @@ static void dm_set_cursor(
struct drm_crtc *crtc = &amdgpu_crtc->base;
int x, y;
int xorigin = 0, yorigin = 0;
+ struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state);
amdgpu_crtc->cursor_width = width;
amdgpu_crtc->cursor_height = height;
@@ -125,13 +126,13 @@ static void dm_set_cursor(
position.y_hotspot = yorigin;
if (!dc_stream_set_cursor_attributes(
- amdgpu_crtc->stream,
+ acrtc_state->stream,
&attributes)) {
DRM_ERROR("DC failed to set cursor attributes\n");
}
if (!dc_stream_set_cursor_position(
- amdgpu_crtc->stream,
+ acrtc_state->stream,
&position)) {
DRM_ERROR("DC failed to set cursor position\n");
}
@@ -144,6 +145,7 @@ static int dm_crtc_cursor_set(
uint32_t height)
{
struct dc_cursor_position position;
+ struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state);
int ret;
@@ -163,10 +165,10 @@ static int dm_crtc_cursor_set(
position.x = 0;
position.y = 0;
- if (amdgpu_crtc->stream) {
+ if (acrtc_state->stream) {
/*set cursor visible false*/
dc_stream_set_cursor_position(
- amdgpu_crtc->stream,
+ acrtc_state->stream,
&position);
}
goto release;
@@ -197,6 +199,7 @@ static int dm_crtc_cursor_move(struct drm_crtc *crtc,
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
int xorigin = 0, yorigin = 0;
struct dc_cursor_position position;
+ struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state);
amdgpu_crtc->cursor_x = x;
amdgpu_crtc->cursor_y = y;
@@ -234,9 +237,9 @@ static int dm_crtc_cursor_move(struct drm_crtc *crtc,
position.x_hotspot = xorigin;
position.y_hotspot = yorigin;
- if (amdgpu_crtc->stream) {
+ if (acrtc_state->stream) {
if (!dc_stream_set_cursor_position(
- amdgpu_crtc->stream,
+ acrtc_state->stream,
&position)) {
DRM_ERROR("DC failed to set cursor position\n");
return -EINVAL;
@@ -612,7 +615,8 @@ static void add_surface(struct dc *dc,
{
struct dc_surface *dc_surface;
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
- const struct dc_stream *dc_stream = acrtc->stream;
+ struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state);
+ const struct dc_stream *dc_stream = acrtc_state->stream;
unsigned long flags;
spin_lock_irqsave(&crtc->dev->event_lock, flags);
@@ -1038,11 +1042,10 @@ static void dm_crtc_destroy_state(struct drm_crtc *crtc,
{
struct dm_crtc_state *cur = to_dm_crtc_state(state);
- if (cur->dc_stream) {
- /* TODO Destroy dc_stream objects are stream object is flattened */
- dm_free(cur->dc_stream);
- } else
- WARN_ON(1);
+ /* TODO Destroy dc_stream objects are stream object is flattened */
+ if (cur->stream)
+ dc_stream_release(cur->stream);
+
__drm_atomic_helper_crtc_destroy_state(state);
@@ -1061,40 +1064,29 @@ static void dm_crtc_reset_state(struct drm_crtc *crtc)
if (WARN_ON(!state))
return;
-
crtc->state = &state->base;
crtc->state->crtc = crtc;
- state->dc_stream = dm_alloc(sizeof(*state->dc_stream));
- WARN_ON(!state->dc_stream);
}
static struct drm_crtc_state *
dm_crtc_duplicate_state(struct drm_crtc *crtc)
{
struct dm_crtc_state *state, *cur;
- struct dc_stream *dc_stream;
-
- if (WARN_ON(!crtc->state))
- return NULL;
cur = to_dm_crtc_state(crtc->state);
- if (WARN_ON(!cur->dc_stream))
- return NULL;
- dc_stream = dm_alloc(sizeof(*dc_stream));
- if (WARN_ON(!dc_stream))
+ if (WARN_ON(!crtc->state))
return NULL;
state = dm_alloc(sizeof(*state));
- if (WARN_ON(!state)) {
- dm_free(dc_stream);
- return NULL;
- }
__drm_atomic_helper_crtc_duplicate_state(crtc, &state->base);
- state->dc_stream = dc_stream;
+ if (cur->stream) {
+ state->stream = cur->stream;
+ dc_stream_retain(state->stream);
+ }
/* TODO Duplicate dc_stream after objects are stream object is flattened */
@@ -1161,6 +1153,7 @@ static int amdgpu_freesync_set_property_atomic(
struct amdgpu_crtc *acrtc;
int ret;
uint64_t val_capable;
+ struct dm_crtc_state *acrtc_state;
dev = connector->dev;
adev = dev->dev_private;
@@ -1184,9 +1177,12 @@ static int amdgpu_freesync_set_property_atomic(
user_enable.enable_for_video = user_enable.enable_for_gaming;
ret = -EINVAL;
acrtc = to_amdgpu_crtc(connector_state->crtc);
- if (connector_state->connector == connector && acrtc->stream) {
+ acrtc_state = to_dm_crtc_state(connector_state->crtc->state);
+
+
+ if (connector_state->connector == connector && acrtc_state->stream) {
mod_freesync_set_user_enable(adev->dm.freesync_module,
- &acrtc->stream, 1,
+ &acrtc_state->stream, 1,
&user_enable);
ret = 0;
}
@@ -2401,21 +2397,15 @@ static bool is_scaling_state_different(
return false;
}
-static void remove_stream(struct amdgpu_device *adev, struct amdgpu_crtc *acrtc)
+static void remove_stream(
+ struct amdgpu_device *adev,
+ struct amdgpu_crtc *acrtc,
+ const struct dc_stream *stream)
{
- /*
- * we evade vblanks and pflips on crtc that
- * should be changed
- */
- manage_dm_interrupts(adev, acrtc, false);
-
/* this is the update mode case */
if (adev->dm.freesync_module)
- mod_freesync_remove_stream(adev->dm.freesync_module,
- acrtc->stream);
+ mod_freesync_remove_stream(adev->dm.freesync_module, stream);
- dc_stream_release(acrtc->stream);
- acrtc->stream = NULL;
acrtc->otg_inst = -1;
acrtc->enabled = false;
}
@@ -2487,6 +2477,8 @@ static void amdgpu_dm_do_flip(
bool async_flip = (acrtc->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC) != 0;
struct dc_flip_addrs addr = { {0} };
struct dc_surface_update surface_updates[1] = { {0} };
+ struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state);
+
/* Prepare wait for target vblank early - before the fence-waits */
target_vblank = target - drm_crtc_vblank_count(crtc) +
@@ -2529,7 +2521,7 @@ static void amdgpu_dm_do_flip(
crtc->primary->fb = fb;
WARN_ON(acrtc->pflip_status != AMDGPU_FLIP_NONE);
- WARN_ON(!acrtc->stream);
+ WARN_ON(!acrtc_state->stream);
addr.address.grph.addr.low_part = lower_32_bits(afb->address);
addr.address.grph.addr.high_part = upper_32_bits(afb->address);
@@ -2539,11 +2531,11 @@ static void amdgpu_dm_do_flip(
if (acrtc->base.state->event)
prepare_flip_isr(acrtc);
- surface_updates->surface = dc_stream_get_status(acrtc->stream)->surfaces[0];
+ surface_updates->surface = dc_stream_get_status(acrtc_state->stream)->surfaces[0];
surface_updates->flip_addr = &addr;
- dc_update_surfaces_and_stream(adev->dm.dc, surface_updates, 1, acrtc->stream, NULL);
+ dc_update_surfaces_and_stream(adev->dm.dc, surface_updates, 1, acrtc_state->stream, NULL);
DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n",
__func__,
@@ -2566,6 +2558,7 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state,
const struct dc_stream *dc_stream_attach;
const struct dc_surface *dc_surfaces_constructed[MAX_SURFACES];
struct amdgpu_crtc *acrtc_attach = to_amdgpu_crtc(pcrtc);
+ struct dm_crtc_state *acrtc_state = to_dm_crtc_state(pcrtc->state);
int planes_count = 0;
/* update planes when needed */
@@ -2620,7 +2613,7 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state,
dm_error("%s: Failed to add surface!\n", __func__);
continue;
}
- dc_stream_attach = acrtc_attach->stream;
+ dc_stream_attach = acrtc_state->stream;
planes_count++;
} else if (crtc->state->planes_changed) {
@@ -2675,6 +2668,37 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state,
}
}
+
+int amdgpu_dm_atomic_commit(
+ struct drm_device *dev,
+ struct drm_atomic_state *state,
+ bool nonblock)
+{
+ struct drm_crtc *crtc;
+ struct drm_crtc_state *new_state;
+ struct amdgpu_device *adev = dev->dev_private;
+ int i;
+
+ /*
+ * We evade vblanks and pflips on crtc that
+ * should be changed. We do it here to flush & disable
+ * interrupts before drm_swap_state is called in drm_atomic_helper_commit
+ * it will update crtc->dm_crtc_state->stream pointer which is used in
+ * the ISRs.
+ */
+ for_each_crtc_in_state(state, crtc, new_state, i) {
+ struct dm_crtc_state *old_acrtc_state = to_dm_crtc_state(crtc->state);
+ struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
+
+ if (drm_atomic_crtc_needs_modeset(new_state) && old_acrtc_state->stream)
+ manage_dm_interrupts(adev, acrtc, false);
+ }
+
+ return drm_atomic_helper_commit(dev, state, nonblock);
+
+ /*TODO Handle EINTR, reenable IRQ*/
+}
+
void amdgpu_dm_atomic_commit_tail(
struct drm_atomic_state *state)
{
@@ -2692,6 +2716,7 @@ void amdgpu_dm_atomic_commit_tail(
bool wait_for_vblank = true;
struct drm_connector *connector;
struct drm_connector_state *old_conn_state;
+ struct dm_crtc_state *old_acrtc_state, *new_acrtc_state;
drm_atomic_helper_update_legacy_modeset_state(dev, state);
@@ -2699,16 +2724,10 @@ void amdgpu_dm_atomic_commit_tail(
/* update changed items */
for_each_crtc_in_state(state, crtc, old_crtc_state, i) {
- struct amdgpu_crtc *acrtc;
- struct amdgpu_connector *aconnector = NULL;
+ struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
struct drm_crtc_state *new_state = crtc->state;
-
- acrtc = to_amdgpu_crtc(crtc);
- aconnector =
- amdgpu_dm_find_first_crct_matching_connector(
- state,
- crtc,
- false);
+ new_acrtc_state = to_dm_crtc_state(new_state);
+ old_acrtc_state = to_dm_crtc_state(old_crtc_state);
DRM_DEBUG_KMS(
"amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, "
@@ -2727,109 +2746,60 @@ void amdgpu_dm_atomic_commit_tail(
*/
if (modeset_required(new_state)) {
- struct dm_connector_state *dm_conn_state = NULL;
- new_stream = NULL;
-
- if (aconnector)
- dm_conn_state = to_dm_connector_state(aconnector->base.state);
-
- new_stream = create_stream_for_sink(
- aconnector,
- &crtc->state->mode,
- dm_conn_state);
DRM_INFO("Atomic commit: SET crtc id %d: [%p]\n", acrtc->crtc_id, acrtc);
- if (!new_stream) {
+ if (!new_acrtc_state->stream) {
/*
- * this could happen because of issues with
- * userspace notifications delivery.
- * In this case userspace tries to set mode on
- * display which is disconnect in fact.
- * dc_sink in NULL in this case on aconnector.
- * We expect reset mode will come soon.
- *
- * This can also happen when unplug is done
- * during resume sequence ended
- *
- * In this case, we want to pretend we still
- * have a sink to keep the pipe running so that
- * hw state is consistent with the sw state
- */
+ * this could happen because of issues with
+ * userspace notifications delivery.
+ * In this case userspace tries to set mode on
+ * display which is disconnect in fact.
+ * dc_sink in NULL in this case on aconnector.
+ * We expect reset mode will come soon.
+ *
+ * This can also happen when unplug is done
+ * during resume sequence ended
+ *
+ * In this case, we want to pretend we still
+ * have a sink to keep the pipe running so that
+ * hw state is consistent with the sw state
+ */
DRM_DEBUG_KMS("%s: Failed to create new stream for crtc %d\n",
__func__, acrtc->base.base.id);
- break;
+ continue;
}
- if (acrtc->stream)
- remove_stream(adev, acrtc);
- /* TODO clean this stupid hack */
- for (j = 0; j < dm_state->set_count; j++)
- if (dm_state->set[j].stream->priv == acrtc) {
- ASSERT(acrtc->stream == NULL);
- new_stream = dm_state->set[j].stream;
- break;
- }
+ if (old_acrtc_state->stream)
+ remove_stream(adev, acrtc, old_acrtc_state->stream);
+
/*
* this loop saves set mode crtcs
* we needed to enable vblanks once all
* resources acquired in dc after dc_commit_streams
*/
+
+ /*TODO move all this into dm_crtc_state, get rid of
+ * new_crtcs array and use old and new atomic states
+ * instead
+ */
new_crtcs[new_crtcs_count] = acrtc;
new_crtcs_count++;
- acrtc->stream = new_stream;
acrtc->enabled = true;
acrtc->hw_mode = crtc->state->mode;
crtc->hwmode = crtc->state->mode;
} else if (modereset_required(new_state)) {
-
DRM_INFO("Atomic commit: RESET. crtc id %d:[%p]\n", acrtc->crtc_id, acrtc);
+
/* i.e. reset mode */
- if (acrtc->stream)
- remove_stream(adev, acrtc);
+ if (old_acrtc_state->stream)
+ remove_stream(adev, acrtc, old_acrtc_state->stream);
}
} /* for_each_crtc_in_state() */
- /* Handle scaling and undersacn changes*/
- for_each_connector_in_state(state, connector, old_conn_state, i) {
- struct amdgpu_connector *aconnector = to_amdgpu_connector(connector);
- struct dm_connector_state *con_new_state =
- to_dm_connector_state(aconnector->base.state);
- struct dm_connector_state *con_old_state =
- to_dm_connector_state(old_conn_state);
- struct amdgpu_crtc *acrtc = to_amdgpu_crtc(con_new_state->base.crtc);
- const struct dc_stream_status *status = NULL;
-
- /* Skip any modesets/resets */
- if (!acrtc || drm_atomic_crtc_needs_modeset(acrtc->base.state))
- continue;
-
- /* Skip any thing not scale or underscan chnages */
- if (!is_scaling_state_different(con_new_state, con_old_state))
- continue;
-
- update_stream_scaling_settings(&con_new_state->base.crtc->mode,
- con_new_state, (struct dc_stream *)acrtc->stream);
-
- status = dc_stream_get_status(acrtc->stream);
- WARN_ON(!status);
- WARN_ON(!status->surface_count);
-
- if (!acrtc->stream)
- continue;
-
- /*TODO How it works with MPO ?*/
- if (!dc_commit_surfaces_to_stream(
- dm->dc,
- (const struct dc_surface **)status->surfaces,
- status->surface_count,
- acrtc->stream))
- dm_error("%s: Failed to update stream scaling!\n", __func__);
- }
-
/*
* Add streams after required streams from new and replaced streams
* are removed from freesync module
@@ -2837,7 +2807,9 @@ void amdgpu_dm_atomic_commit_tail(
if (adev->dm.freesync_module) {
for (i = 0; i < new_crtcs_count; i++) {
struct amdgpu_connector *aconnector = NULL;
- new_stream = new_crtcs[i]->stream;
+ new_acrtc_state = to_dm_crtc_state(new_crtcs[i]->base.state);
+
+ new_stream = new_acrtc_state->stream;
aconnector =
amdgpu_dm_find_first_crct_matching_connector(
state,
@@ -2862,35 +2834,77 @@ void amdgpu_dm_atomic_commit_tail(
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
+ new_acrtc_state = to_dm_crtc_state(crtc->state);
- if (acrtc->stream != NULL) {
- const struct dc_stream_status *status = dc_stream_get_status(acrtc->stream);
+ if (new_acrtc_state->stream != NULL) {
+ const struct dc_stream_status *status =
+ dc_stream_get_status(new_acrtc_state->stream);
if (!status)
- DC_ERR("got no status for stream %p on acrtc%p\n", acrtc->stream, acrtc);
+ DC_ERR("got no status for stream %p on acrtc%p\n", new_acrtc_state->stream, acrtc);
else
acrtc->otg_inst = status->primary_otg_inst;
}
}
+ /* Handle scaling and undersacn changes*/
+ for_each_connector_in_state(state, connector, old_conn_state, i) {
+ struct amdgpu_connector *aconnector = to_amdgpu_connector(connector);
+ struct dm_connector_state *con_new_state =
+ to_dm_connector_state(aconnector->base.state);
+ struct dm_connector_state *con_old_state =
+ to_dm_connector_state(old_conn_state);
+ struct amdgpu_crtc *acrtc = to_amdgpu_crtc(con_new_state->base.crtc);
+ const struct dc_stream_status *status = NULL;
+
+ /* Skip any modesets/resets */
+ if (!acrtc || drm_atomic_crtc_needs_modeset(acrtc->base.state))
+ continue;
+
+ /* Skip any thing not scale or underscan changes */
+ if (!is_scaling_state_different(con_new_state, con_old_state))
+ continue;
+
+ new_acrtc_state = to_dm_crtc_state(acrtc->base.state);
+
+ update_stream_scaling_settings(&con_new_state->base.crtc->mode,
+ con_new_state, (struct dc_stream *)new_acrtc_state->stream);
+
+ status = dc_stream_get_status(new_acrtc_state->stream);
+ WARN_ON(!status);
+ WARN_ON(!status->surface_count);
+
+ if (!new_acrtc_state->stream)
+ continue;
+
+ /*TODO How it works with MPO ?*/
+ if (!dc_commit_surfaces_to_stream(
+ dm->dc,
+ (const struct dc_surface **)status->surfaces,
+ status->surface_count,
+ new_acrtc_state->stream))
+ dm_error("%s: Failed to update stream scaling!\n", __func__);
+ }
+
for (i = 0; i < new_crtcs_count; i++) {
/*
* loop to enable interrupts on newly arrived crtc
*/
struct amdgpu_crtc *acrtc = new_crtcs[i];
+ new_acrtc_state = to_dm_crtc_state(acrtc->base.state);
if (adev->dm.freesync_module)
mod_freesync_notify_mode_change(
- adev->dm.freesync_module, &acrtc->stream, 1);
+ adev->dm.freesync_module, &new_acrtc_state->stream, 1);
manage_dm_interrupts(adev, acrtc, true);
}
/* update planes when needed per crtc*/
for_each_crtc_in_state(state, pcrtc, old_crtc_state, j) {
- struct amdgpu_crtc *acrtc = to_amdgpu_crtc(pcrtc);
+ new_acrtc_state = to_dm_crtc_state(pcrtc->state);
- if (acrtc->stream)
+ if (new_acrtc_state->stream)
amdgpu_dm_commit_surfaces(state, dev, dm, pcrtc, &wait_for_vblank);
}
@@ -2986,13 +3000,15 @@ void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector
{
struct amdgpu_connector *aconnector = to_amdgpu_connector(connector);
struct amdgpu_crtc *disconnected_acrtc;
+ struct dm_crtc_state *acrtc_state;
if (!aconnector->dc_sink || !connector->state || !connector->encoder)
return;
disconnected_acrtc = to_amdgpu_crtc(connector->encoder->crtc);
+ acrtc_state = to_dm_crtc_state(disconnected_acrtc->base.state);
- if (!disconnected_acrtc || !disconnected_acrtc->stream)
+ if (!disconnected_acrtc || !acrtc_state->stream)
return;
/*
@@ -3000,7 +3016,7 @@ void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector
* we deduce we are in a state where we can not rely on usermode call
* to turn on the display, so we do it here
*/
- if (disconnected_acrtc->stream->sink != aconnector->dc_sink)
+ if (acrtc_state->stream->sink != aconnector->dc_sink)
dm_force_atomic_commit(&aconnector->base);
}
@@ -3044,17 +3060,11 @@ static uint32_t update_in_val_sets_stream(
}
val_sets[i].stream = new_stream;
- dc_stream_retain(new_stream);
crtcs[i] = crtc;
- if (i == set_count) {
+ if (i == set_count)
/* nothing found. add new one to the end */
return set_count + 1;
- } else {
- /* update. relase old stream */
- dc_stream_release(old_stream);
-
- }
return set_count;
}
@@ -3075,7 +3085,6 @@ static uint32_t remove_from_val_sets(
return set_count;
}
- dc_stream_release(stream);
set_count--;
for (; i < set_count; i++) {
@@ -3145,14 +3154,16 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
struct drm_plane_state *plane_state;
int i, j;
int ret;
- int new_stream_count;
- struct dc_stream *new_streams[MAX_STREAMS] = { 0 };
struct drm_crtc *crtc_set[MAX_STREAMS] = { 0 };
struct amdgpu_device *adev = dev->dev_private;
struct dc *dc = adev->dm.dc;
bool need_to_validate = false;
struct drm_connector *connector;
struct drm_connector_state *conn_state;
+ int set_count;
+ struct dc_validation_set set[MAX_STREAMS] = { { 0 } };
+ struct dm_crtc_state *old_acrtc_state, *new_acrtc_state;
+
/*
* This bool will be set for true for any modeset/reset
* or surface update which implies non fast surfae update.
@@ -3172,17 +3183,16 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
dm_state = to_dm_atomic_state(state);
/* copy existing configuration */
- new_stream_count = 0;
- dm_state->set_count = 0;
+ set_count = 0;
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
- struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
+ old_acrtc_state = to_dm_crtc_state(crtc->state);
- if (acrtc->stream) {
- dc_stream_retain(acrtc->stream);
- dm_state->set[dm_state->set_count].stream = acrtc->stream;
- crtc_set[dm_state->set_count] = crtc;
- ++dm_state->set_count;
+ if (old_acrtc_state->stream) {
+ dc_stream_retain(old_acrtc_state->stream);
+ set[set_count].stream = old_acrtc_state->stream;
+ crtc_set[set_count] = crtc;
+ ++set_count;
}
}
@@ -3190,7 +3200,8 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
for_each_crtc_in_state(state, crtc, crtc_state, i) {
struct amdgpu_crtc *acrtc = NULL;
struct amdgpu_connector *aconnector = NULL;
-
+ old_acrtc_state = to_dm_crtc_state(crtc->state);
+ new_acrtc_state = to_dm_crtc_state(crtc_state);
acrtc = to_amdgpu_crtc(crtc);
aconnector = amdgpu_dm_find_first_crct_matching_connector(state, crtc, true);
@@ -3221,7 +3232,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
}
new_stream = create_stream_for_sink(aconnector, &crtc_state->mode, dm_conn_state);
- new_stream->priv = acrtc;
/*
* we can have no stream on ACTION_SET if a display
@@ -3235,27 +3245,33 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
break;
}
- new_streams[new_stream_count] = new_stream;
- dm_state->set_count = update_in_val_sets_stream(
- dm_state->set,
+ if (new_acrtc_state->stream)
+ dc_stream_release(new_acrtc_state->stream);
+ new_acrtc_state->stream = new_stream;
+
+ set_count = update_in_val_sets_stream(
+ set,
crtc_set,
- dm_state->set_count,
- acrtc->stream,
- new_stream,
+ set_count,
+ old_acrtc_state->stream,
+ new_acrtc_state->stream,
crtc);
- new_stream_count++;
need_to_validate = true;
aquire_global_lock = true;
} else if (modereset_required(crtc_state)) {
/* i.e. reset mode */
- if (acrtc->stream) {
- dm_state->set_count = remove_from_val_sets(
- dm_state->set,
- dm_state->set_count,
- acrtc->stream);
+ if (new_acrtc_state->stream) {
+ set_count = remove_from_val_sets(
+ set,
+ set_count,
+ new_acrtc_state->stream);
+
+ dc_stream_release(new_acrtc_state->stream);
+ new_acrtc_state->stream = NULL;
+
aquire_global_lock = true;
}
}
@@ -3276,6 +3292,10 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
}
/* Check scaling and undersacn changes*/
+ /*TODO Removed scaling changes validation due to inability to commit
+ * new stream into context w\o causing full reset. Need to
+ * decide how to handle.
+ */
for_each_connector_in_state(state, connector, conn_state, i) {
struct amdgpu_connector *aconnector = to_amdgpu_connector(connector);
struct dm_connector_state *con_old_state =
@@ -3283,7 +3303,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
struct dm_connector_state *con_new_state =
to_dm_connector_state(conn_state);
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(con_new_state->base.crtc);
- struct dc_stream *new_stream;
/* Skip any modesets/resets */
if (!acrtc || drm_atomic_crtc_needs_modeset(acrtc->base.state))
@@ -3293,32 +3312,11 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
if (!is_scaling_state_different(con_new_state, con_old_state))
continue;
- new_stream = create_stream_for_sink(
- aconnector,
- &acrtc->base.state->mode,
- con_new_state);
-
- if (!new_stream) {
- DRM_ERROR("%s: Failed to create new stream for crtc %d\n",
- __func__, acrtc->base.base.id);
- continue;
- }
-
- new_streams[new_stream_count] = new_stream;
- dm_state->set_count = update_in_val_sets_stream(
- dm_state->set,
- crtc_set,
- dm_state->set_count,
- acrtc->stream,
- new_stream,
- &acrtc->base);
-
- new_stream_count++;
need_to_validate = true;
aquire_global_lock = true;
}
- for (i = 0; i < dm_state->set_count; i++) {
+ for (i = 0; i < set_count; i++) {
for_each_plane_in_state(state, plane, plane_state, j) {
struct drm_crtc *crtc = plane_state->crtc;
struct drm_framebuffer *fb = plane_state->fb;
@@ -3374,9 +3372,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
plane_state,
false);
- add_val_sets_surface(dm_state->set,
- dm_state->set_count,
- dm_state->set[i].stream,
+ add_val_sets_surface(set,
+ set_count,
+ set[i].stream,
surface);
need_to_validate = true;
@@ -3385,9 +3383,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
}
}
- dm_state->context = dc_get_validate_context(dc, dm_state->set, dm_state->set_count);
+ dm_state->context = dc_get_validate_context(dc, set, set_count);
- if (need_to_validate == false || dm_state->set_count == 0 || dm_state->context) {
+ if (need_to_validate == false || set_count == 0 || dm_state->context) {
ret = 0;
/*
* For full updates case when
@@ -3403,6 +3401,21 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
}
+ /* TODO until surfaces are moved into dm_plane_state release them
+ * here
+ */
+ for (i = 0; i < set_count; i++)
+ for (j = 0; j < set[i].surface_count; j++)
+ dc_surface_release(set[i].surfaces[j]);
+
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ old_acrtc_state = to_dm_crtc_state(crtc->state);
+
+ if (old_acrtc_state->stream)
+ dc_stream_release(old_acrtc_state->stream);
+ }
+
+
if (ret != 0) {
if (ret == -EDEADLK)
DRM_DEBUG_KMS("Atomic check stopped due to to deadlock.\n");
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h
index 1e444cb..36cb1c8 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.h
@@ -45,7 +45,7 @@ struct dm_plane_state {
struct dm_crtc_state {
struct drm_crtc_state base;
- struct dc_stream *dc_stream;
+ const struct dc_stream *stream;
};
#define to_dm_crtc_state(x) container_of(x, struct dm_crtc_state, base)
@@ -53,8 +53,6 @@ struct dm_crtc_state {
struct dm_atomic_state {
struct drm_atomic_state base;
- struct dc_validation_set set[MAX_STREAMS];
- int set_count;
struct validate_context *context;
};
@@ -83,6 +81,11 @@ void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder);
int amdgpu_dm_connector_get_modes(struct drm_connector *connector);
+int amdgpu_dm_atomic_commit(
+ struct drm_device *dev,
+ struct drm_atomic_state *state,
+ bool nonblock);
+
void amdgpu_dm_atomic_commit_tail(
struct drm_atomic_state *state);
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index 5d65416..42c1aa8 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -481,8 +481,6 @@ struct dc_stream {
/* TODO: ABM info (DMCU) */
/* TODO: PSR info */
/* TODO: CEA VIC */
-
- void *priv;
};
struct dc_stream_update {
--
2.7.4
More information about the amd-gfx
mailing list