|
|
@@ -831,7 +831,8 @@ nv50_wndw_atomic_check_release(struct nv50_wndw *wndw,
|
|
|
static int
|
|
|
nv50_wndw_atomic_check_acquire(struct nv50_wndw *wndw,
|
|
|
struct nv50_wndw_atom *asyw,
|
|
|
- struct nv50_head_atom *asyh)
|
|
|
+ struct nv50_head_atom *asyh,
|
|
|
+ u32 pflip_flags)
|
|
|
{
|
|
|
struct nouveau_framebuffer *fb = nouveau_framebuffer(asyw->state.fb);
|
|
|
struct nouveau_drm *drm = nouveau_drm(wndw->plane.dev);
|
|
|
@@ -846,6 +847,9 @@ nv50_wndw_atomic_check_acquire(struct nv50_wndw *wndw,
|
|
|
asyw->image.w = fb->base.width;
|
|
|
asyw->image.h = fb->base.height;
|
|
|
asyw->image.kind = (fb->nvbo->tile_flags & 0x0000ff00) >> 8;
|
|
|
+
|
|
|
+ asyw->interval = pflip_flags & DRM_MODE_PAGE_FLIP_ASYNC ? 0 : 1;
|
|
|
+
|
|
|
if (asyw->image.kind) {
|
|
|
asyw->image.layout = 0;
|
|
|
if (drm->device.info.chipset >= 0xc0)
|
|
|
@@ -883,6 +887,7 @@ nv50_wndw_atomic_check(struct drm_plane *plane, struct drm_plane_state *state)
|
|
|
struct nv50_head_atom *harm = NULL, *asyh = NULL;
|
|
|
bool varm = false, asyv = false, asym = false;
|
|
|
int ret;
|
|
|
+ u32 pflip_flags = 0;
|
|
|
|
|
|
NV_ATOMIC(drm, "%s atomic_check\n", plane->name);
|
|
|
if (asyw->state.crtc) {
|
|
|
@@ -891,6 +896,7 @@ nv50_wndw_atomic_check(struct drm_plane *plane, struct drm_plane_state *state)
|
|
|
return PTR_ERR(asyh);
|
|
|
asym = drm_atomic_crtc_needs_modeset(&asyh->state);
|
|
|
asyv = asyh->state.active;
|
|
|
+ pflip_flags = asyh->state.pageflip_flags;
|
|
|
}
|
|
|
|
|
|
if (armw->state.crtc) {
|
|
|
@@ -907,7 +913,8 @@ nv50_wndw_atomic_check(struct drm_plane *plane, struct drm_plane_state *state)
|
|
|
asyw->set.point = true;
|
|
|
|
|
|
if (!varm || asym || armw->state.fb != asyw->state.fb) {
|
|
|
- ret = nv50_wndw_atomic_check_acquire(wndw, asyw, asyh);
|
|
|
+ ret = nv50_wndw_atomic_check_acquire(
|
|
|
+ wndw, asyw, asyh, pflip_flags);
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
}
|
|
|
@@ -2219,77 +2226,6 @@ nv50_head_help = {
|
|
|
.atomic_check = nv50_head_atomic_check,
|
|
|
};
|
|
|
|
|
|
-/* This is identical to the version in the atomic helpers, except that
|
|
|
- * it supports non-vblanked ("async") page flips.
|
|
|
- */
|
|
|
-static int
|
|
|
-nv50_head_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
|
|
|
- struct drm_pending_vblank_event *event, u32 flags)
|
|
|
-{
|
|
|
- struct drm_plane *plane = crtc->primary;
|
|
|
- struct drm_atomic_state *state;
|
|
|
- struct drm_plane_state *plane_state;
|
|
|
- struct drm_crtc_state *crtc_state;
|
|
|
- int ret = 0;
|
|
|
-
|
|
|
- state = drm_atomic_state_alloc(plane->dev);
|
|
|
- if (!state)
|
|
|
- return -ENOMEM;
|
|
|
-
|
|
|
- state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
|
|
|
-retry:
|
|
|
- crtc_state = drm_atomic_get_crtc_state(state, crtc);
|
|
|
- if (IS_ERR(crtc_state)) {
|
|
|
- ret = PTR_ERR(crtc_state);
|
|
|
- goto fail;
|
|
|
- }
|
|
|
- crtc_state->event = event;
|
|
|
-
|
|
|
- plane_state = drm_atomic_get_plane_state(state, plane);
|
|
|
- if (IS_ERR(plane_state)) {
|
|
|
- ret = PTR_ERR(plane_state);
|
|
|
- goto fail;
|
|
|
- }
|
|
|
-
|
|
|
- ret = drm_atomic_set_crtc_for_plane(plane_state, crtc);
|
|
|
- if (ret != 0)
|
|
|
- goto fail;
|
|
|
- drm_atomic_set_fb_for_plane(plane_state, fb);
|
|
|
-
|
|
|
- /* Make sure we don't accidentally do a full modeset. */
|
|
|
- state->allow_modeset = false;
|
|
|
- if (!crtc_state->active) {
|
|
|
- DRM_DEBUG_ATOMIC("[CRTC:%d] disabled, rejecting legacy flip\n",
|
|
|
- crtc->base.id);
|
|
|
- ret = -EINVAL;
|
|
|
- goto fail;
|
|
|
- }
|
|
|
-
|
|
|
- if (flags & DRM_MODE_PAGE_FLIP_ASYNC)
|
|
|
- nv50_wndw_atom(plane_state)->interval = 0;
|
|
|
-
|
|
|
- ret = drm_atomic_nonblocking_commit(state);
|
|
|
-fail:
|
|
|
- if (ret == -EDEADLK)
|
|
|
- goto backoff;
|
|
|
-
|
|
|
- drm_atomic_state_put(state);
|
|
|
- return ret;
|
|
|
-
|
|
|
-backoff:
|
|
|
- drm_atomic_state_clear(state);
|
|
|
- drm_atomic_legacy_backoff(state);
|
|
|
-
|
|
|
- /*
|
|
|
- * Someone might have exchanged the framebuffer while we dropped locks
|
|
|
- * in the backoff code. We need to fix up the fb refcount tracking the
|
|
|
- * core does for us.
|
|
|
- */
|
|
|
- plane->old_fb = plane->fb;
|
|
|
-
|
|
|
- goto retry;
|
|
|
-}
|
|
|
-
|
|
|
static int
|
|
|
nv50_head_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,
|
|
|
uint32_t size)
|
|
|
@@ -2384,7 +2320,7 @@ nv50_head_func = {
|
|
|
.gamma_set = nv50_head_gamma_set,
|
|
|
.destroy = nv50_head_destroy,
|
|
|
.set_config = drm_atomic_helper_set_config,
|
|
|
- .page_flip = nv50_head_page_flip,
|
|
|
+ .page_flip = drm_atomic_helper_page_flip,
|
|
|
.set_property = drm_atomic_helper_crtc_set_property,
|
|
|
.atomic_duplicate_state = nv50_head_atomic_duplicate_state,
|
|
|
.atomic_destroy_state = nv50_head_atomic_destroy_state,
|