/* current cursor being scanned out: */
                struct drm_gem_object *scanout_bo;
+               uint64_t iova;
                uint32_t width, height;
                uint32_t x, y;
        } cursor;
 };
 #define to_mdp5_crtc(x) container_of(x, struct mdp5_crtc, base)
 
+static void mdp5_crtc_restore_cursor(struct drm_crtc *crtc);
+
 static struct mdp5_kms *get_kms(struct drm_crtc *crtc)
 {
        struct msm_drm_private *priv = crtc->dev->dev_private;
 
        pm_runtime_get_sync(dev);
 
+       /* Restore cursor state, as it might have been lost with suspend: */
+       if (mdp5_crtc->cursor.iova) {
+               unsigned long flags;
+
+               spin_lock_irqsave(&mdp5_crtc->cursor.lock, flags);
+               mdp5_crtc_restore_cursor(crtc);
+               spin_unlock_irqrestore(&mdp5_crtc->cursor.lock, flags);
+
+               mdp5_ctl_set_cursor(mdp5_cstate->ctl,
+                       &mdp5_cstate->pipeline, 0, true);
+       } else {
+               mdp5_ctl_set_cursor(mdp5_cstate->ctl,
+                       &mdp5_cstate->pipeline, 0, false);
+       }
+
        /* Restore vblank irq handling after power is enabled */
        drm_crtc_vblank_on(crtc);
 
                        mdp5_crtc->cursor.y);
 }
 
+static void mdp5_crtc_restore_cursor(struct drm_crtc *crtc)
+{
+       struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
+       struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+       struct mdp5_kms *mdp5_kms = get_kms(crtc);
+       const enum mdp5_cursor_alpha cur_alpha = CURSOR_ALPHA_PER_PIXEL;
+       uint32_t blendcfg, stride;
+       uint32_t x, y, width, height;
+       uint32_t roi_w, roi_h;
+       int lm;
+
+       assert_spin_locked(&mdp5_crtc->cursor.lock);
+
+       lm = mdp5_cstate->pipeline.mixer->lm;
+
+       x = mdp5_crtc->cursor.x;
+       y = mdp5_crtc->cursor.y;
+       width = mdp5_crtc->cursor.width;
+       height = mdp5_crtc->cursor.height;
+
+       stride = width * drm_format_plane_cpp(DRM_FORMAT_ARGB8888, 0);
+
+       get_roi(crtc, &roi_w, &roi_h);
+
+       mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_STRIDE(lm), stride);
+       mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_FORMAT(lm),
+                       MDP5_LM_CURSOR_FORMAT_FORMAT(CURSOR_FMT_ARGB8888));
+       mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_IMG_SIZE(lm),
+                       MDP5_LM_CURSOR_IMG_SIZE_SRC_H(height) |
+                       MDP5_LM_CURSOR_IMG_SIZE_SRC_W(width));
+       mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_SIZE(lm),
+                       MDP5_LM_CURSOR_SIZE_ROI_H(roi_h) |
+                       MDP5_LM_CURSOR_SIZE_ROI_W(roi_w));
+       mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_START_XY(lm),
+                       MDP5_LM_CURSOR_START_XY_Y_START(y) |
+                       MDP5_LM_CURSOR_START_XY_X_START(x));
+       mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_BASE_ADDR(lm),
+                       mdp5_crtc->cursor.iova);
+
+       blendcfg = MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_EN;
+       blendcfg |= MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_ALPHA_SEL(cur_alpha);
+       mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_BLEND_CONFIG(lm), blendcfg);
+}
+
 static int mdp5_crtc_cursor_set(struct drm_crtc *crtc,
                struct drm_file *file, uint32_t handle,
                uint32_t width, uint32_t height)
        struct platform_device *pdev = mdp5_kms->pdev;
        struct msm_kms *kms = &mdp5_kms->base.base;
        struct drm_gem_object *cursor_bo, *old_bo = NULL;
-       uint32_t blendcfg, stride;
-       uint64_t cursor_addr;
        struct mdp5_ctl *ctl;
-       int ret, lm;
-       enum mdp5_cursor_alpha cur_alpha = CURSOR_ALPHA_PER_PIXEL;
+       int ret;
        uint32_t flush_mask = mdp_ctl_flush_mask_cursor(0);
-       uint32_t roi_w, roi_h;
        bool cursor_enable = true;
        unsigned long flags;
 
        if (!handle) {
                DBG("Cursor off");
                cursor_enable = false;
+               mdp5_crtc->cursor.iova = 0;
                pm_runtime_get_sync(&pdev->dev);
                goto set_cursor;
        }
        if (!cursor_bo)
                return -ENOENT;
 
-       ret = msm_gem_get_iova(cursor_bo, kms->aspace, &cursor_addr);
+       ret = msm_gem_get_iova(cursor_bo, kms->aspace,
+                       &mdp5_crtc->cursor.iova);
        if (ret)
                return -EINVAL;
 
-       lm = mdp5_cstate->pipeline.mixer->lm;
-       stride = width * drm_format_plane_cpp(DRM_FORMAT_ARGB8888, 0);
-
        pm_runtime_get_sync(&pdev->dev);
 
        spin_lock_irqsave(&mdp5_crtc->cursor.lock, flags);
        mdp5_crtc->cursor.width = width;
        mdp5_crtc->cursor.height = height;
 
-       get_roi(crtc, &roi_w, &roi_h);
-
-       mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_STRIDE(lm), stride);
-       mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_FORMAT(lm),
-                       MDP5_LM_CURSOR_FORMAT_FORMAT(CURSOR_FMT_ARGB8888));
-       mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_IMG_SIZE(lm),
-                       MDP5_LM_CURSOR_IMG_SIZE_SRC_H(height) |
-                       MDP5_LM_CURSOR_IMG_SIZE_SRC_W(width));
-       mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_SIZE(lm),
-                       MDP5_LM_CURSOR_SIZE_ROI_H(roi_h) |
-                       MDP5_LM_CURSOR_SIZE_ROI_W(roi_w));
-       mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_BASE_ADDR(lm), cursor_addr);
-
-       blendcfg = MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_EN;
-       blendcfg |= MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_ALPHA_SEL(cur_alpha);
-       mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_BLEND_CONFIG(lm), blendcfg);
+       mdp5_crtc_restore_cursor(crtc);
 
        spin_unlock_irqrestore(&mdp5_crtc->cursor.lock, flags);
 
        struct mdp5_kms *mdp5_kms = get_kms(crtc);
        struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
        struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
-       uint32_t lm = mdp5_cstate->pipeline.mixer->lm;
        uint32_t flush_mask = mdp_ctl_flush_mask_cursor(0);
        uint32_t roi_w;
        uint32_t roi_h;
        pm_runtime_get_sync(&mdp5_kms->pdev->dev);
 
        spin_lock_irqsave(&mdp5_crtc->cursor.lock, flags);
-       mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_SIZE(lm),
-                       MDP5_LM_CURSOR_SIZE_ROI_H(roi_h) |
-                       MDP5_LM_CURSOR_SIZE_ROI_W(roi_w));
-       mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_START_XY(lm),
-                       MDP5_LM_CURSOR_START_XY_Y_START(y) |
-                       MDP5_LM_CURSOR_START_XY_X_START(x));
+       mdp5_crtc_restore_cursor(crtc);
        spin_unlock_irqrestore(&mdp5_crtc->cursor.lock, flags);
 
        crtc_flush(crtc, flush_mask);