mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-27 11:19:37 +00:00
drm/armada: handle atomic modeset crtc events
Prepare handling for atomic modeset CRTC events. Currently, using the transition helpers, CRTC events do not exist, but once we switch to proper atomic modeset, they have to be handled. We queue an event for the next vblank in two places: - armada_drm_crtc_atomic_flush() provided we aren't doing an atomic modeset. - armada_drm_crtc_commit() if we are committing a modeset. This ensures that the event is sent at the correct time (after all updates have been written to the hardware and after the following vblank.) Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
This commit is contained in:
parent
4e4b3563ac
commit
dbb4ca8aca
2 changed files with 34 additions and 0 deletions
|
@ -232,6 +232,19 @@ static void armada_drm_vblank_off(struct armada_crtc *dcrtc)
|
|||
armada_drm_plane_work_run(dcrtc, dcrtc->crtc.primary);
|
||||
}
|
||||
|
||||
static void armada_drm_crtc_queue_state_event(struct drm_crtc *crtc)
|
||||
{
|
||||
struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
|
||||
struct drm_pending_vblank_event *event;
|
||||
|
||||
/* If we have an event, we need vblank events enabled */
|
||||
event = xchg(&crtc->state->event, NULL);
|
||||
if (event) {
|
||||
WARN_ON(drm_crtc_vblank_get(crtc) != 0);
|
||||
dcrtc->event = event;
|
||||
}
|
||||
}
|
||||
|
||||
/* The mode_config.mutex will be held for this call */
|
||||
static void armada_drm_crtc_dpms(struct drm_crtc *crtc, int dpms)
|
||||
{
|
||||
|
@ -294,6 +307,8 @@ static void armada_drm_crtc_commit(struct drm_crtc *crtc)
|
|||
dcrtc->dpms = DRM_MODE_DPMS_ON;
|
||||
armada_drm_crtc_update(dcrtc);
|
||||
drm_crtc_vblank_on(crtc);
|
||||
|
||||
armada_drm_crtc_queue_state_event(crtc);
|
||||
}
|
||||
|
||||
/* The mode_config.mutex will be held for this call */
|
||||
|
@ -337,6 +352,7 @@ static void armada_drm_crtc_enable_irq(struct armada_crtc *dcrtc, u32 mask)
|
|||
|
||||
static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat)
|
||||
{
|
||||
struct drm_pending_vblank_event *event;
|
||||
void __iomem *base = dcrtc->base;
|
||||
struct drm_plane *ovl_plane;
|
||||
|
||||
|
@ -383,6 +399,16 @@ static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat)
|
|||
|
||||
if (stat & GRA_FRAME_IRQ)
|
||||
armada_drm_plane_work_run(dcrtc, dcrtc->crtc.primary);
|
||||
|
||||
if (stat & VSYNC_IRQ) {
|
||||
event = xchg(&dcrtc->event, NULL);
|
||||
if (event) {
|
||||
spin_lock(&dcrtc->crtc.dev->event_lock);
|
||||
drm_crtc_send_vblank_event(&dcrtc->crtc, event);
|
||||
spin_unlock(&dcrtc->crtc.dev->event_lock);
|
||||
drm_crtc_vblank_put(&dcrtc->crtc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static irqreturn_t armada_drm_irq(int irq, void *arg)
|
||||
|
@ -554,6 +580,13 @@ static void armada_drm_crtc_atomic_flush(struct drm_crtc *crtc,
|
|||
spin_lock_irqsave(&dcrtc->irq_lock, flags);
|
||||
armada_drm_crtc_update_regs(dcrtc, dcrtc->regs);
|
||||
spin_unlock_irqrestore(&dcrtc->irq_lock, flags);
|
||||
|
||||
/*
|
||||
* If we aren't doing a full modeset, then we need to queue
|
||||
* the event here.
|
||||
*/
|
||||
if (!drm_atomic_crtc_needs_modeset(crtc->state))
|
||||
armada_drm_crtc_queue_state_event(crtc);
|
||||
}
|
||||
|
||||
static const struct drm_crtc_helper_funcs armada_crtc_helper_funcs = {
|
||||
|
|
|
@ -90,6 +90,7 @@ struct armada_crtc {
|
|||
spinlock_t irq_lock;
|
||||
uint32_t irq_ena;
|
||||
|
||||
struct drm_pending_vblank_event *event;
|
||||
struct armada_regs atomic_regs[32];
|
||||
struct armada_regs *regs;
|
||||
unsigned int regs_idx;
|
||||
|
|
Loading…
Reference in a new issue