summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/armada
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@armlinux.org.uk>2018-07-30 11:52:34 +0100
committerRussell King <rmk+kernel@armlinux.org.uk>2018-07-30 11:52:34 +0100
commit34e25ed60ae2cdf91b953dd3772ae48a6bffbd4c (patch)
tree0f189cdd71e7ae4d166ee706bd092bcd2ec9235d /drivers/gpu/drm/armada
parenta0f75d2468fe4510bb8d0d6c4e1a5fd5e262e7b5 (diff)
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.c71
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,