diff options
author | Russell King <rmk+kernel@armlinux.org.uk> | 2018-07-30 11:52:34 +0100 |
---|---|---|
committer | Russell King <rmk+kernel@armlinux.org.uk> | 2018-07-30 11:52:34 +0100 |
commit | 34e25ed60ae2cdf91b953dd3772ae48a6bffbd4c (patch) | |
tree | 0f189cdd71e7ae4d166ee706bd092bcd2ec9235d /drivers/gpu/drm/armada | |
parent | a0f75d2468fe4510bb8d0d6c4e1a5fd5e262e7b5 (diff) | |
download | linux-34e25ed60ae2cdf91b953dd3772ae48a6bffbd4c.tar.gz linux-34e25ed60ae2cdf91b953dd3772ae48a6bffbd4c.tar.bz2 linux-34e25ed60ae2cdf91b953dd3772ae48a6bffbd4c.zip |
drm/armada: implement atomic_enable()/atomic_disable() methods
Implement the atomic_enable()/atomic_disable() methods used by the
atomic modeset helpers. atomic_disable() will need some transitional
code during conversion to ensure proper ordering is maintained.
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
Diffstat (limited to 'drivers/gpu/drm/armada')
-rw-r--r-- | drivers/gpu/drm/armada/armada_crtc.c | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index 554135062d93..e93097d3aa06 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -581,6 +581,75 @@ static void armada_drm_crtc_atomic_flush(struct drm_crtc *crtc, armada_drm_crtc_queue_state_event(crtc); } +static void armada_drm_crtc_atomic_disable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) +{ + struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); + struct drm_pending_vblank_event *event; + struct drm_plane *plane; + + DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name); + + /* + * For transition only - we must wait for completion of our + * untransitioned paths before changing anything. + */ + plane = dcrtc->plane; + if (plane) + WARN_ON(!armada_drm_plane_work_wait(drm_to_armada_plane(plane), + HZ)); + armada_drm_plane_work_wait(drm_to_armada_plane(dcrtc->crtc.primary), + MAX_SCHEDULE_TIMEOUT); + + dcrtc->dpms = DRM_MODE_DPMS_OFF; + drm_crtc_vblank_off(crtc); + armada_drm_crtc_update(dcrtc, false); + + if (!crtc->state->active) { + /* + * This modeset will be leaving the CRTC disabled, so + * call the backend to disable upstream clocks etc. + */ + if (dcrtc->variant->disable) + dcrtc->variant->disable(dcrtc); + + /* + * We will not receive any further vblank events. + * Send the flip_done event manually. + */ + event = crtc->state->event; + crtc->state->event = NULL; + if (event) { + spin_lock_irq(&crtc->dev->event_lock); + drm_crtc_send_vblank_event(crtc, event); + spin_unlock_irq(&crtc->dev->event_lock); + } + } +} + +static void armada_drm_crtc_atomic_enable(struct drm_crtc *crtc, + struct drm_crtc_state *old_state) +{ + struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); + + DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name); + + dcrtc->dpms = DRM_MODE_DPMS_ON; + if (!old_state->active) { + /* + * This modeset is enabling the CRTC after it having + * been disabled. Reverse the call to ->disable in + * the atomic_disable(). + */ + if (dcrtc->variant->enable) + dcrtc->variant->enable(dcrtc, &crtc->state->adjusted_mode); + } + armada_drm_crtc_update(dcrtc, true); + drm_crtc_vblank_on(crtc); + + armada_drm_crtc_queue_state_event(crtc); +} + static const struct drm_crtc_helper_funcs armada_crtc_helper_funcs = { .dpms = armada_drm_crtc_dpms, .prepare = armada_drm_crtc_prepare, @@ -592,6 +661,8 @@ static const struct drm_crtc_helper_funcs armada_crtc_helper_funcs = { .disable = armada_drm_crtc_disable, .atomic_begin = armada_drm_crtc_atomic_begin, .atomic_flush = armada_drm_crtc_atomic_flush, + .atomic_disable = armada_drm_crtc_atomic_disable, + .atomic_enable = armada_drm_crtc_atomic_enable, }; static void armada_load_cursor_argb(void __iomem *base, uint32_t *pix, |