提交 da5c47f6 编写于 作者: A Andrey Grodzovsky 提交者: Alex Deucher

drm/amd/display: Remove acrtc->stream

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.
Signed-off-by: NAndrey Grodzovsky <Andrey.Grodzovsky@amd.com>
Reviewed-by: NTony Cheng <Tony.Cheng@amd.com>
Acked-by: NHarry Wentland <Harry.Wentland@amd.com>
Signed-off-by: NAlex Deucher <alexander.deucher@amd.com>
上级 89a1fc59
...@@ -100,13 +100,16 @@ static u32 dm_vblank_get_counter(struct amdgpu_device *adev, int crtc) ...@@ -100,13 +100,16 @@ static u32 dm_vblank_get_counter(struct amdgpu_device *adev, int crtc)
return 0; return 0;
else { else {
struct amdgpu_crtc *acrtc = adev->mode_info.crtcs[crtc]; 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); DRM_ERROR("dc_stream is NULL for crtc '%d'!\n", crtc);
return 0; 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, ...@@ -119,8 +122,10 @@ static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
return -EINVAL; return -EINVAL;
else { else {
struct amdgpu_crtc *acrtc = adev->mode_info.crtcs[crtc]; 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); DRM_ERROR("dc_stream is NULL for crtc '%d'!\n", crtc);
return 0; return 0;
} }
...@@ -129,7 +134,7 @@ static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc, ...@@ -129,7 +134,7 @@ static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
* TODO rework base driver to use values directly. * TODO rework base driver to use values directly.
* for now parse it back into reg-format * 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_start,
&v_blank_end, &v_blank_end,
&h_position, &h_position,
...@@ -652,22 +657,12 @@ dm_atomic_state_alloc(struct drm_device *dev) ...@@ -652,22 +657,12 @@ dm_atomic_state_alloc(struct drm_device *dev)
void dm_atomic_state_clear(struct drm_atomic_state *state) void dm_atomic_state_clear(struct drm_atomic_state *state)
{ {
struct dm_atomic_state *dm_state = to_dm_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); if (dm_state->context) {
dm_state->set[i].stream = NULL; 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); drm_atomic_state_default_clear(state);
} }
...@@ -676,7 +671,7 @@ static const struct drm_mode_config_funcs amdgpu_dm_mode_funcs = { ...@@ -676,7 +671,7 @@ static const struct drm_mode_config_funcs amdgpu_dm_mode_funcs = {
.fb_create = amdgpu_user_framebuffer_create, .fb_create = amdgpu_user_framebuffer_create,
.output_poll_changed = amdgpu_output_poll_changed, .output_poll_changed = amdgpu_output_poll_changed,
.atomic_check = amdgpu_dm_atomic_check, .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_alloc = dm_atomic_state_alloc,
.atomic_state_clear = dm_atomic_state_clear, .atomic_state_clear = dm_atomic_state_clear,
}; };
......
...@@ -86,6 +86,7 @@ static void dm_set_cursor( ...@@ -86,6 +86,7 @@ static void dm_set_cursor(
struct drm_crtc *crtc = &amdgpu_crtc->base; struct drm_crtc *crtc = &amdgpu_crtc->base;
int x, y; int x, y;
int xorigin = 0, yorigin = 0; 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_width = width;
amdgpu_crtc->cursor_height = height; amdgpu_crtc->cursor_height = height;
...@@ -124,13 +125,13 @@ static void dm_set_cursor( ...@@ -124,13 +125,13 @@ static void dm_set_cursor(
position.y_hotspot = yorigin; position.y_hotspot = yorigin;
if (!dc_stream_set_cursor_attributes( if (!dc_stream_set_cursor_attributes(
amdgpu_crtc->stream, acrtc_state->stream,
&attributes)) { &attributes)) {
DRM_ERROR("DC failed to set cursor attributes\n"); DRM_ERROR("DC failed to set cursor attributes\n");
} }
if (!dc_stream_set_cursor_position( if (!dc_stream_set_cursor_position(
amdgpu_crtc->stream, acrtc_state->stream,
&position)) { &position)) {
DRM_ERROR("DC failed to set cursor position\n"); DRM_ERROR("DC failed to set cursor position\n");
} }
...@@ -143,6 +144,7 @@ static int dm_crtc_cursor_set( ...@@ -143,6 +144,7 @@ static int dm_crtc_cursor_set(
uint32_t height) uint32_t height)
{ {
struct dc_cursor_position position; struct dc_cursor_position position;
struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state);
int ret; int ret;
...@@ -162,10 +164,10 @@ static int dm_crtc_cursor_set( ...@@ -162,10 +164,10 @@ static int dm_crtc_cursor_set(
position.x = 0; position.x = 0;
position.y = 0; position.y = 0;
if (amdgpu_crtc->stream) { if (acrtc_state->stream) {
/*set cursor visible false*/ /*set cursor visible false*/
dc_stream_set_cursor_position( dc_stream_set_cursor_position(
amdgpu_crtc->stream, acrtc_state->stream,
&position); &position);
} }
goto release; goto release;
...@@ -196,6 +198,7 @@ static int dm_crtc_cursor_move(struct drm_crtc *crtc, ...@@ -196,6 +198,7 @@ static int dm_crtc_cursor_move(struct drm_crtc *crtc,
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
int xorigin = 0, yorigin = 0; int xorigin = 0, yorigin = 0;
struct dc_cursor_position position; 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_x = x;
amdgpu_crtc->cursor_y = y; amdgpu_crtc->cursor_y = y;
...@@ -233,9 +236,9 @@ static int dm_crtc_cursor_move(struct drm_crtc *crtc, ...@@ -233,9 +236,9 @@ static int dm_crtc_cursor_move(struct drm_crtc *crtc,
position.x_hotspot = xorigin; position.x_hotspot = xorigin;
position.y_hotspot = yorigin; position.y_hotspot = yorigin;
if (amdgpu_crtc->stream) { if (acrtc_state->stream) {
if (!dc_stream_set_cursor_position( if (!dc_stream_set_cursor_position(
amdgpu_crtc->stream, acrtc_state->stream,
&position)) { &position)) {
DRM_ERROR("DC failed to set cursor position\n"); DRM_ERROR("DC failed to set cursor position\n");
return -EINVAL; return -EINVAL;
...@@ -611,7 +614,8 @@ static void add_surface(struct dc *dc, ...@@ -611,7 +614,8 @@ static void add_surface(struct dc *dc,
{ {
struct dc_surface *dc_surface; struct dc_surface *dc_surface;
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); 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; unsigned long flags;
spin_lock_irqsave(&crtc->dev->event_lock, flags); spin_lock_irqsave(&crtc->dev->event_lock, flags);
...@@ -965,11 +969,10 @@ static void dm_crtc_destroy_state(struct drm_crtc *crtc, ...@@ -965,11 +969,10 @@ static void dm_crtc_destroy_state(struct drm_crtc *crtc,
{ {
struct dm_crtc_state *cur = to_dm_crtc_state(state); struct dm_crtc_state *cur = to_dm_crtc_state(state);
if (cur->dc_stream) { /* TODO Destroy dc_stream objects are stream object is flattened */
/* TODO Destroy dc_stream objects are stream object is flattened */ if (cur->stream)
dm_free(cur->dc_stream); dc_stream_release(cur->stream);
} else
WARN_ON(1);
__drm_atomic_helper_crtc_destroy_state(state); __drm_atomic_helper_crtc_destroy_state(state);
...@@ -988,40 +991,29 @@ static void dm_crtc_reset_state(struct drm_crtc *crtc) ...@@ -988,40 +991,29 @@ static void dm_crtc_reset_state(struct drm_crtc *crtc)
if (WARN_ON(!state)) if (WARN_ON(!state))
return; return;
crtc->state = &state->base; crtc->state = &state->base;
crtc->state->crtc = crtc; crtc->state->crtc = crtc;
state->dc_stream = dm_alloc(sizeof(*state->dc_stream));
WARN_ON(!state->dc_stream);
} }
static struct drm_crtc_state * static struct drm_crtc_state *
dm_crtc_duplicate_state(struct drm_crtc *crtc) dm_crtc_duplicate_state(struct drm_crtc *crtc)
{ {
struct dm_crtc_state *state, *cur; 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); 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(!crtc->state))
if (WARN_ON(!dc_stream))
return NULL; return NULL;
state = dm_alloc(sizeof(*state)); state = dm_alloc(sizeof(*state));
if (WARN_ON(!state)) {
dm_free(dc_stream);
return NULL;
}
__drm_atomic_helper_crtc_duplicate_state(crtc, &state->base); __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 */ /* TODO Duplicate dc_stream after objects are stream object is flattened */
...@@ -2238,21 +2230,15 @@ static bool is_scaling_state_different( ...@@ -2238,21 +2230,15 @@ static bool is_scaling_state_different(
return false; 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 */ /* this is the update mode case */
if (adev->dm.freesync_module) if (adev->dm.freesync_module)
mod_freesync_remove_stream(adev->dm.freesync_module, mod_freesync_remove_stream(adev->dm.freesync_module, stream);
acrtc->stream);
dc_stream_release(acrtc->stream);
acrtc->stream = NULL;
acrtc->otg_inst = -1; acrtc->otg_inst = -1;
acrtc->enabled = false; acrtc->enabled = false;
} }
...@@ -2324,6 +2310,8 @@ static void amdgpu_dm_do_flip( ...@@ -2324,6 +2310,8 @@ static void amdgpu_dm_do_flip(
bool async_flip = (acrtc->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC) != 0; bool async_flip = (acrtc->flip_flags & DRM_MODE_PAGE_FLIP_ASYNC) != 0;
struct dc_flip_addrs addr = { {0} }; struct dc_flip_addrs addr = { {0} };
struct dc_surface_update surface_updates[1] = { {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 */ /* Prepare wait for target vblank early - before the fence-waits */
target_vblank = target - drm_crtc_vblank_count(crtc) + target_vblank = target - drm_crtc_vblank_count(crtc) +
...@@ -2366,7 +2354,7 @@ static void amdgpu_dm_do_flip( ...@@ -2366,7 +2354,7 @@ static void amdgpu_dm_do_flip(
crtc->primary->fb = fb; crtc->primary->fb = fb;
WARN_ON(acrtc->pflip_status != AMDGPU_FLIP_NONE); 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.low_part = lower_32_bits(afb->address);
addr.address.grph.addr.high_part = upper_32_bits(afb->address); addr.address.grph.addr.high_part = upper_32_bits(afb->address);
...@@ -2376,11 +2364,11 @@ static void amdgpu_dm_do_flip( ...@@ -2376,11 +2364,11 @@ static void amdgpu_dm_do_flip(
if (acrtc->base.state->event) if (acrtc->base.state->event)
prepare_flip_isr(acrtc); 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; 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", DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n",
__func__, __func__,
...@@ -2403,6 +2391,7 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, ...@@ -2403,6 +2391,7 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state,
const struct dc_stream *dc_stream_attach; const struct dc_stream *dc_stream_attach;
const struct dc_surface *dc_surfaces_constructed[MAX_SURFACES]; const struct dc_surface *dc_surfaces_constructed[MAX_SURFACES];
struct amdgpu_crtc *acrtc_attach = to_amdgpu_crtc(pcrtc); 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; int planes_count = 0;
/* update planes when needed */ /* update planes when needed */
...@@ -2457,7 +2446,7 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, ...@@ -2457,7 +2446,7 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state,
dm_error("%s: Failed to add surface!\n", __func__); dm_error("%s: Failed to add surface!\n", __func__);
continue; continue;
} }
dc_stream_attach = acrtc_attach->stream; dc_stream_attach = acrtc_state->stream;
planes_count++; planes_count++;
} else if (crtc->state->planes_changed) { } else if (crtc->state->planes_changed) {
...@@ -2511,6 +2500,37 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, ...@@ -2511,6 +2500,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( void amdgpu_dm_atomic_commit_tail(
struct drm_atomic_state *state) struct drm_atomic_state *state)
{ {
...@@ -2528,6 +2548,7 @@ void amdgpu_dm_atomic_commit_tail( ...@@ -2528,6 +2548,7 @@ void amdgpu_dm_atomic_commit_tail(
bool wait_for_vblank = true; bool wait_for_vblank = true;
struct drm_connector *connector; struct drm_connector *connector;
struct drm_connector_state *old_conn_state; 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); drm_atomic_helper_update_legacy_modeset_state(dev, state);
...@@ -2535,16 +2556,10 @@ void amdgpu_dm_atomic_commit_tail( ...@@ -2535,16 +2556,10 @@ void amdgpu_dm_atomic_commit_tail(
/* update changed items */ /* update changed items */
for_each_crtc_in_state(state, crtc, old_crtc_state, i) { for_each_crtc_in_state(state, crtc, old_crtc_state, i) {
struct amdgpu_crtc *acrtc; struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
struct amdgpu_connector *aconnector = NULL;
struct drm_crtc_state *new_state = crtc->state; struct drm_crtc_state *new_state = crtc->state;
new_acrtc_state = to_dm_crtc_state(new_state);
acrtc = to_amdgpu_crtc(crtc); old_acrtc_state = to_dm_crtc_state(old_crtc_state);
aconnector =
amdgpu_dm_find_first_crct_matching_connector(
state,
crtc,
false);
DRM_DEBUG_KMS( DRM_DEBUG_KMS(
"amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, " "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, "
...@@ -2563,109 +2578,60 @@ void amdgpu_dm_atomic_commit_tail( ...@@ -2563,109 +2578,60 @@ void amdgpu_dm_atomic_commit_tail(
*/ */
if (modeset_required(new_state)) { 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); 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 * this could happen because of issues with
* userspace notifications delivery. * userspace notifications delivery.
* In this case userspace tries to set mode on * In this case userspace tries to set mode on
* display which is disconnect in fact. * display which is disconnect in fact.
* dc_sink in NULL in this case on aconnector. * dc_sink in NULL in this case on aconnector.
* We expect reset mode will come soon. * We expect reset mode will come soon.
* *
* This can also happen when unplug is done * This can also happen when unplug is done
* during resume sequence ended * during resume sequence ended
* *
* In this case, we want to pretend we still * In this case, we want to pretend we still
* have a sink to keep the pipe running so that * have a sink to keep the pipe running so that
* hw state is consistent with the sw state * hw state is consistent with the sw state
*/ */
DRM_DEBUG_KMS("%s: Failed to create new stream for crtc %d\n", DRM_DEBUG_KMS("%s: Failed to create new stream for crtc %d\n",
__func__, acrtc->base.base.id); __func__, acrtc->base.base.id);
break; continue;
} }
if (acrtc->stream)
remove_stream(adev, acrtc);
/* TODO clean this stupid hack */ if (old_acrtc_state->stream)
for (j = 0; j < dm_state->set_count; j++) remove_stream(adev, acrtc, old_acrtc_state->stream);
if (dm_state->set[j].stream->priv == acrtc) {
ASSERT(acrtc->stream == NULL);
new_stream = dm_state->set[j].stream;
break;
}
/* /*
* this loop saves set mode crtcs * this loop saves set mode crtcs
* we needed to enable vblanks once all * we needed to enable vblanks once all
* resources acquired in dc after dc_commit_streams * 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[new_crtcs_count] = acrtc;
new_crtcs_count++; new_crtcs_count++;
acrtc->stream = new_stream;
acrtc->enabled = true; acrtc->enabled = true;
acrtc->hw_mode = crtc->state->mode; acrtc->hw_mode = crtc->state->mode;
crtc->hwmode = crtc->state->mode; crtc->hwmode = crtc->state->mode;
} else if (modereset_required(new_state)) { } else if (modereset_required(new_state)) {
DRM_INFO("Atomic commit: RESET. crtc id %d:[%p]\n", acrtc->crtc_id, acrtc); DRM_INFO("Atomic commit: RESET. crtc id %d:[%p]\n", acrtc->crtc_id, acrtc);
/* i.e. reset mode */ /* i.e. reset mode */
if (acrtc->stream) if (old_acrtc_state->stream)
remove_stream(adev, acrtc); remove_stream(adev, acrtc, old_acrtc_state->stream);
} }
} /* for_each_crtc_in_state() */ } /* 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 * Add streams after required streams from new and replaced streams
* are removed from freesync module * are removed from freesync module
...@@ -2673,7 +2639,9 @@ void amdgpu_dm_atomic_commit_tail( ...@@ -2673,7 +2639,9 @@ void amdgpu_dm_atomic_commit_tail(
if (adev->dm.freesync_module) { if (adev->dm.freesync_module) {
for (i = 0; i < new_crtcs_count; i++) { for (i = 0; i < new_crtcs_count; i++) {
struct amdgpu_connector *aconnector = NULL; 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 = aconnector =
amdgpu_dm_find_first_crct_matching_connector( amdgpu_dm_find_first_crct_matching_connector(
state, state,
...@@ -2698,35 +2666,77 @@ void amdgpu_dm_atomic_commit_tail( ...@@ -2698,35 +2666,77 @@ void amdgpu_dm_atomic_commit_tail(
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
new_acrtc_state = to_dm_crtc_state(crtc->state);
if (acrtc->stream != NULL) { if (new_acrtc_state->stream != NULL) {
const struct dc_stream_status *status = dc_stream_get_status(acrtc->stream); const struct dc_stream_status *status =
dc_stream_get_status(new_acrtc_state->stream);
if (!status) 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 else
acrtc->otg_inst = status->primary_otg_inst; 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++) { for (i = 0; i < new_crtcs_count; i++) {
/* /*
* loop to enable interrupts on newly arrived crtc * loop to enable interrupts on newly arrived crtc
*/ */
struct amdgpu_crtc *acrtc = new_crtcs[i]; struct amdgpu_crtc *acrtc = new_crtcs[i];
new_acrtc_state = to_dm_crtc_state(acrtc->base.state);
if (adev->dm.freesync_module) if (adev->dm.freesync_module)
mod_freesync_notify_mode_change( 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); manage_dm_interrupts(adev, acrtc, true);
} }
/* update planes when needed per crtc*/ /* update planes when needed per crtc*/
for_each_crtc_in_state(state, pcrtc, old_crtc_state, j) { 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); amdgpu_dm_commit_surfaces(state, dev, dm, pcrtc, &wait_for_vblank);
} }
...@@ -2822,13 +2832,15 @@ void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector ...@@ -2822,13 +2832,15 @@ void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector
{ {
struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); struct amdgpu_connector *aconnector = to_amdgpu_connector(connector);
struct amdgpu_crtc *disconnected_acrtc; struct amdgpu_crtc *disconnected_acrtc;
struct dm_crtc_state *acrtc_state;
if (!aconnector->dc_sink || !connector->state || !connector->encoder) if (!aconnector->dc_sink || !connector->state || !connector->encoder)
return; return;
disconnected_acrtc = to_amdgpu_crtc(connector->encoder->crtc); 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; return;
/* /*
...@@ -2836,7 +2848,7 @@ void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector ...@@ -2836,7 +2848,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 * 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 * 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); dm_force_atomic_commit(&aconnector->base);
} }
...@@ -2880,17 +2892,11 @@ static uint32_t update_in_val_sets_stream( ...@@ -2880,17 +2892,11 @@ static uint32_t update_in_val_sets_stream(
} }
val_sets[i].stream = new_stream; val_sets[i].stream = new_stream;
dc_stream_retain(new_stream);
crtcs[i] = crtc; crtcs[i] = crtc;
if (i == set_count) { if (i == set_count)
/* nothing found. add new one to the end */ /* nothing found. add new one to the end */
return set_count + 1; return set_count + 1;
} else {
/* update. relase old stream */
dc_stream_release(old_stream);
}
return set_count; return set_count;
} }
...@@ -2911,7 +2917,6 @@ static uint32_t remove_from_val_sets( ...@@ -2911,7 +2917,6 @@ static uint32_t remove_from_val_sets(
return set_count; return set_count;
} }
dc_stream_release(stream);
set_count--; set_count--;
for (; i < set_count; i++) { for (; i < set_count; i++) {
...@@ -2981,14 +2986,16 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, ...@@ -2981,14 +2986,16 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
struct drm_plane_state *plane_state; struct drm_plane_state *plane_state;
int i, j; int i, j;
int ret; int ret;
int new_stream_count;
struct dc_stream *new_streams[MAX_STREAMS] = { 0 };
struct drm_crtc *crtc_set[MAX_STREAMS] = { 0 }; struct drm_crtc *crtc_set[MAX_STREAMS] = { 0 };
struct amdgpu_device *adev = dev->dev_private; struct amdgpu_device *adev = dev->dev_private;
struct dc *dc = adev->dm.dc; struct dc *dc = adev->dm.dc;
bool need_to_validate = false; bool need_to_validate = false;
struct drm_connector *connector; struct drm_connector *connector;
struct drm_connector_state *conn_state; 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 * This bool will be set for true for any modeset/reset
* or surface update which implies non fast surfae update. * or surface update which implies non fast surfae update.
...@@ -3008,17 +3015,16 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, ...@@ -3008,17 +3015,16 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
dm_state = to_dm_atomic_state(state); dm_state = to_dm_atomic_state(state);
/* copy existing configuration */ /* copy existing configuration */
new_stream_count = 0; set_count = 0;
dm_state->set_count = 0;
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 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) { if (old_acrtc_state->stream) {
dc_stream_retain(acrtc->stream); dc_stream_retain(old_acrtc_state->stream);
dm_state->set[dm_state->set_count].stream = acrtc->stream; set[set_count].stream = old_acrtc_state->stream;
crtc_set[dm_state->set_count] = crtc; crtc_set[set_count] = crtc;
++dm_state->set_count; ++set_count;
} }
} }
...@@ -3026,7 +3032,8 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, ...@@ -3026,7 +3032,8 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
for_each_crtc_in_state(state, crtc, crtc_state, i) { for_each_crtc_in_state(state, crtc, crtc_state, i) {
struct amdgpu_crtc *acrtc = NULL; struct amdgpu_crtc *acrtc = NULL;
struct amdgpu_connector *aconnector = 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); acrtc = to_amdgpu_crtc(crtc);
aconnector = amdgpu_dm_find_first_crct_matching_connector(state, crtc, true); aconnector = amdgpu_dm_find_first_crct_matching_connector(state, crtc, true);
...@@ -3057,7 +3064,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, ...@@ -3057,7 +3064,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 = 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 * we can have no stream on ACTION_SET if a display
...@@ -3071,27 +3077,33 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, ...@@ -3071,27 +3077,33 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
break; break;
} }
new_streams[new_stream_count] = new_stream; if (new_acrtc_state->stream)
dm_state->set_count = update_in_val_sets_stream( dc_stream_release(new_acrtc_state->stream);
dm_state->set, new_acrtc_state->stream = new_stream;
set_count = update_in_val_sets_stream(
set,
crtc_set, crtc_set,
dm_state->set_count, set_count,
acrtc->stream, old_acrtc_state->stream,
new_stream, new_acrtc_state->stream,
crtc); crtc);
new_stream_count++;
need_to_validate = true; need_to_validate = true;
aquire_global_lock = true; aquire_global_lock = true;
} else if (modereset_required(crtc_state)) { } else if (modereset_required(crtc_state)) {
/* i.e. reset mode */ /* i.e. reset mode */
if (acrtc->stream) { if (new_acrtc_state->stream) {
dm_state->set_count = remove_from_val_sets( set_count = remove_from_val_sets(
dm_state->set, set,
dm_state->set_count, set_count,
acrtc->stream); new_acrtc_state->stream);
dc_stream_release(new_acrtc_state->stream);
new_acrtc_state->stream = NULL;
aquire_global_lock = true; aquire_global_lock = true;
} }
} }
...@@ -3112,6 +3124,10 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, ...@@ -3112,6 +3124,10 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
} }
/* Check scaling and undersacn changes*/ /* 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) { for_each_connector_in_state(state, connector, conn_state, i) {
struct amdgpu_connector *aconnector = to_amdgpu_connector(connector); struct amdgpu_connector *aconnector = to_amdgpu_connector(connector);
struct dm_connector_state *con_old_state = struct dm_connector_state *con_old_state =
...@@ -3119,7 +3135,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, ...@@ -3119,7 +3135,6 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
struct dm_connector_state *con_new_state = struct dm_connector_state *con_new_state =
to_dm_connector_state(conn_state); to_dm_connector_state(conn_state);
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(con_new_state->base.crtc); struct amdgpu_crtc *acrtc = to_amdgpu_crtc(con_new_state->base.crtc);
struct dc_stream *new_stream;
/* Skip any modesets/resets */ /* Skip any modesets/resets */
if (!acrtc || drm_atomic_crtc_needs_modeset(acrtc->base.state)) if (!acrtc || drm_atomic_crtc_needs_modeset(acrtc->base.state))
...@@ -3129,32 +3144,11 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, ...@@ -3129,32 +3144,11 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
if (!is_scaling_state_different(con_new_state, con_old_state)) if (!is_scaling_state_different(con_new_state, con_old_state))
continue; 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; need_to_validate = true;
aquire_global_lock = 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) { for_each_plane_in_state(state, plane, plane_state, j) {
struct drm_crtc *crtc = plane_state->crtc; struct drm_crtc *crtc = plane_state->crtc;
struct drm_framebuffer *fb = plane_state->fb; struct drm_framebuffer *fb = plane_state->fb;
...@@ -3210,9 +3204,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, ...@@ -3210,9 +3204,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
plane_state, plane_state,
false); false);
add_val_sets_surface(dm_state->set, add_val_sets_surface(set,
dm_state->set_count, set_count,
dm_state->set[i].stream, set[i].stream,
surface); surface);
need_to_validate = true; need_to_validate = true;
...@@ -3221,9 +3215,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, ...@@ -3221,9 +3215,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; ret = 0;
/* /*
* For full updates case when * For full updates case when
...@@ -3239,6 +3233,21 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, ...@@ -3239,6 +3233,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 != 0) {
if (ret == -EDEADLK) if (ret == -EDEADLK)
DRM_DEBUG_KMS("Atomic check stopped due to to deadlock.\n"); DRM_DEBUG_KMS("Atomic check stopped due to to deadlock.\n");
......
...@@ -45,7 +45,7 @@ struct dm_plane_state { ...@@ -45,7 +45,7 @@ struct dm_plane_state {
struct dm_crtc_state { struct dm_crtc_state {
struct drm_crtc_state base; 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) #define to_dm_crtc_state(x) container_of(x, struct dm_crtc_state, base)
...@@ -53,8 +53,6 @@ struct dm_crtc_state { ...@@ -53,8 +53,6 @@ struct dm_crtc_state {
struct dm_atomic_state { struct dm_atomic_state {
struct drm_atomic_state base; struct drm_atomic_state base;
struct dc_validation_set set[MAX_STREAMS];
int set_count;
struct validate_context *context; struct validate_context *context;
}; };
...@@ -83,6 +81,11 @@ void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder); ...@@ -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_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( void amdgpu_dm_atomic_commit_tail(
struct drm_atomic_state *state); struct drm_atomic_state *state);
......
...@@ -481,8 +481,6 @@ struct dc_stream { ...@@ -481,8 +481,6 @@ struct dc_stream {
/* TODO: ABM info (DMCU) */ /* TODO: ABM info (DMCU) */
/* TODO: PSR info */ /* TODO: PSR info */
/* TODO: CEA VIC */ /* TODO: CEA VIC */
void *priv;
}; };
struct dc_stream_update { struct dc_stream_update {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册