drm/rockchip: convert to helper nonblocking atomic commit
With the various bits fixed rockchip now has an atomic compliant handling/signalling of crtc_state->event, which means we can just switch over to the new nonblocking helpers and remove some code. v2: Fixes from Tomeu. v3: Send out vblank events correctly when shutting down a crtc for good. This is part of the atomic interface contract. v4: Properly protect vop->event. v5: Add more WARN_ON to check vop->event isn't clobbered. Cc: Tomeu Vizoso <tomeu.vizoso@collabora.com> Cc: Mark yao <mark.yao@rock-chips.com> Tested-by: Tomeu Vizoso <tomeu.vizoso@collabora.com> Reviewed-by: Tomeu Vizoso <tomeu.vizoso@collabora.com> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
This commit is contained in:
parent
4f9d39a78e
commit
893b6cad4d
|
@ -157,9 +157,6 @@ static int rockchip_drm_bind(struct device *dev)
|
|||
goto err_unregister;
|
||||
}
|
||||
|
||||
mutex_init(&private->commit.lock);
|
||||
INIT_WORK(&private->commit.work, rockchip_drm_atomic_work);
|
||||
|
||||
drm_dev->dev_private = private;
|
||||
|
||||
drm_mode_config_init(drm_dev);
|
||||
|
|
|
@ -43,13 +43,6 @@ struct rockchip_crtc_funcs {
|
|||
void (*cancel_pending_vblank)(struct drm_crtc *crtc, struct drm_file *file_priv);
|
||||
};
|
||||
|
||||
struct rockchip_atomic_commit {
|
||||
struct work_struct work;
|
||||
struct drm_atomic_state *state;
|
||||
struct drm_device *dev;
|
||||
struct mutex lock;
|
||||
};
|
||||
|
||||
struct rockchip_crtc_state {
|
||||
struct drm_crtc_state base;
|
||||
int output_type;
|
||||
|
@ -68,11 +61,8 @@ struct rockchip_drm_private {
|
|||
struct drm_fb_helper fbdev_helper;
|
||||
struct drm_gem_object *fbdev_bo;
|
||||
const struct rockchip_crtc_funcs *crtc_funcs[ROCKCHIP_MAX_CRTC];
|
||||
|
||||
struct rockchip_atomic_commit commit;
|
||||
};
|
||||
|
||||
void rockchip_drm_atomic_work(struct work_struct *work);
|
||||
int rockchip_register_crtc_funcs(struct drm_crtc *crtc,
|
||||
const struct rockchip_crtc_funcs *crtc_funcs);
|
||||
void rockchip_unregister_crtc_funcs(struct drm_crtc *crtc);
|
||||
|
|
|
@ -228,87 +228,32 @@ rockchip_atomic_wait_for_complete(struct drm_device *dev, struct drm_atomic_stat
|
|||
}
|
||||
|
||||
static void
|
||||
rockchip_atomic_commit_complete(struct rockchip_atomic_commit *commit)
|
||||
rockchip_atomic_commit_tail(struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_atomic_state *state = commit->state;
|
||||
struct drm_device *dev = commit->dev;
|
||||
struct drm_device *dev = state->dev;
|
||||
|
||||
/*
|
||||
* TODO: do fence wait here.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Rockchip crtc support runtime PM, can't update display planes
|
||||
* when crtc is disabled.
|
||||
*
|
||||
* drm_atomic_helper_commit comments detail that:
|
||||
* For drivers supporting runtime PM the recommended sequence is
|
||||
*
|
||||
* drm_atomic_helper_commit_modeset_disables(dev, state);
|
||||
*
|
||||
* drm_atomic_helper_commit_modeset_enables(dev, state);
|
||||
*
|
||||
* drm_atomic_helper_commit_planes(dev, state, true);
|
||||
*
|
||||
* See the kerneldoc entries for these three functions for more details.
|
||||
*/
|
||||
drm_atomic_helper_commit_modeset_disables(dev, state);
|
||||
|
||||
drm_atomic_helper_commit_modeset_enables(dev, state);
|
||||
|
||||
drm_atomic_helper_commit_planes(dev, state, true);
|
||||
|
||||
drm_atomic_helper_commit_hw_done(state);
|
||||
|
||||
rockchip_atomic_wait_for_complete(dev, state);
|
||||
|
||||
drm_atomic_helper_cleanup_planes(dev, state);
|
||||
|
||||
drm_atomic_state_free(state);
|
||||
}
|
||||
|
||||
void rockchip_drm_atomic_work(struct work_struct *work)
|
||||
{
|
||||
struct rockchip_atomic_commit *commit = container_of(work,
|
||||
struct rockchip_atomic_commit, work);
|
||||
|
||||
rockchip_atomic_commit_complete(commit);
|
||||
}
|
||||
|
||||
int rockchip_drm_atomic_commit(struct drm_device *dev,
|
||||
struct drm_atomic_state *state,
|
||||
bool nonblock)
|
||||
{
|
||||
struct rockchip_drm_private *private = dev->dev_private;
|
||||
struct rockchip_atomic_commit *commit = &private->commit;
|
||||
int ret;
|
||||
|
||||
ret = drm_atomic_helper_prepare_planes(dev, state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* serialize outstanding nonblocking commits */
|
||||
mutex_lock(&commit->lock);
|
||||
flush_work(&commit->work);
|
||||
|
||||
drm_atomic_helper_swap_state(state, true);
|
||||
|
||||
commit->dev = dev;
|
||||
commit->state = state;
|
||||
|
||||
if (nonblock)
|
||||
schedule_work(&commit->work);
|
||||
else
|
||||
rockchip_atomic_commit_complete(commit);
|
||||
|
||||
mutex_unlock(&commit->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
struct drm_mode_config_helper_funcs rockchip_mode_config_helpers = {
|
||||
.atomic_commit_tail = rockchip_atomic_commit_tail,
|
||||
};
|
||||
|
||||
static const struct drm_mode_config_funcs rockchip_drm_mode_config_funcs = {
|
||||
.fb_create = rockchip_user_fb_create,
|
||||
.output_poll_changed = rockchip_drm_output_poll_changed,
|
||||
.atomic_check = drm_atomic_helper_check,
|
||||
.atomic_commit = rockchip_drm_atomic_commit,
|
||||
.atomic_commit = drm_atomic_helper_commit,
|
||||
};
|
||||
|
||||
struct drm_framebuffer *
|
||||
|
@ -339,4 +284,5 @@ void rockchip_drm_mode_config_init(struct drm_device *dev)
|
|||
dev->mode_config.max_height = 4096;
|
||||
|
||||
dev->mode_config.funcs = &rockchip_drm_mode_config_funcs;
|
||||
dev->mode_config.helper_private = &rockchip_mode_config_helpers;
|
||||
}
|
||||
|
|
|
@ -502,6 +502,8 @@ static void vop_crtc_disable(struct drm_crtc *crtc)
|
|||
struct vop *vop = to_vop(crtc);
|
||||
int i;
|
||||
|
||||
WARN_ON(vop->event);
|
||||
|
||||
/*
|
||||
* We need to make sure that all windows are disabled before we
|
||||
* disable that crtc. Otherwise we might try to scan from a destroyed
|
||||
|
@ -551,6 +553,14 @@ static void vop_crtc_disable(struct drm_crtc *crtc)
|
|||
clk_disable(vop->aclk);
|
||||
clk_disable(vop->hclk);
|
||||
pm_runtime_put(vop->dev);
|
||||
|
||||
if (crtc->state->event && !crtc->state->active) {
|
||||
spin_lock_irq(&crtc->dev->event_lock);
|
||||
drm_crtc_send_vblank_event(crtc, crtc->state->event);
|
||||
spin_unlock_irq(&crtc->dev->event_lock);
|
||||
|
||||
crtc->state->event = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void vop_plane_destroy(struct drm_plane *plane)
|
||||
|
@ -939,6 +949,8 @@ static void vop_crtc_enable(struct drm_crtc *crtc)
|
|||
u16 vact_end = vact_st + vdisplay;
|
||||
uint32_t val;
|
||||
|
||||
WARN_ON(vop->event);
|
||||
|
||||
vop_enable(crtc);
|
||||
/*
|
||||
* If dclk rate is zero, mean that scanout is stop,
|
||||
|
@ -1035,12 +1047,15 @@ static void vop_crtc_atomic_begin(struct drm_crtc *crtc,
|
|||
{
|
||||
struct vop *vop = to_vop(crtc);
|
||||
|
||||
spin_lock_irq(&crtc->dev->event_lock);
|
||||
if (crtc->state->event) {
|
||||
WARN_ON(drm_crtc_vblank_get(crtc) != 0);
|
||||
WARN_ON(vop->event);
|
||||
|
||||
vop->event = crtc->state->event;
|
||||
crtc->state->event = NULL;
|
||||
}
|
||||
spin_unlock_irq(&crtc->dev->event_lock);
|
||||
}
|
||||
|
||||
static const struct drm_crtc_helper_funcs vop_crtc_helper_funcs = {
|
||||
|
@ -1110,15 +1125,16 @@ static void vop_handle_vblank(struct vop *vop)
|
|||
return;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&drm->event_lock, flags);
|
||||
if (vop->event) {
|
||||
spin_lock_irqsave(&drm->event_lock, flags);
|
||||
|
||||
drm_crtc_send_vblank_event(crtc, vop->event);
|
||||
drm_crtc_vblank_put(crtc);
|
||||
vop->event = NULL;
|
||||
|
||||
spin_unlock_irqrestore(&drm->event_lock, flags);
|
||||
}
|
||||
spin_unlock_irqrestore(&drm->event_lock, flags);
|
||||
|
||||
if (!completion_done(&vop->wait_update_complete))
|
||||
complete(&vop->wait_update_complete);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue