|
@@ -61,12 +61,15 @@ struct mdp5_crtc {
|
|
|
|
|
|
/* current cursor being scanned out: */
|
|
/* current cursor being scanned out: */
|
|
struct drm_gem_object *scanout_bo;
|
|
struct drm_gem_object *scanout_bo;
|
|
|
|
+ uint64_t iova;
|
|
uint32_t width, height;
|
|
uint32_t width, height;
|
|
uint32_t x, y;
|
|
uint32_t x, y;
|
|
} cursor;
|
|
} cursor;
|
|
};
|
|
};
|
|
#define to_mdp5_crtc(x) container_of(x, struct mdp5_crtc, base)
|
|
#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)
|
|
static struct mdp5_kms *get_kms(struct drm_crtc *crtc)
|
|
{
|
|
{
|
|
struct msm_drm_private *priv = crtc->dev->dev_private;
|
|
struct msm_drm_private *priv = crtc->dev->dev_private;
|
|
@@ -454,6 +457,21 @@ static void mdp5_crtc_atomic_enable(struct drm_crtc *crtc,
|
|
|
|
|
|
pm_runtime_get_sync(dev);
|
|
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 */
|
|
/* Restore vblank irq handling after power is enabled */
|
|
drm_crtc_vblank_on(crtc);
|
|
drm_crtc_vblank_on(crtc);
|
|
|
|
|
|
@@ -737,6 +755,50 @@ static void get_roi(struct drm_crtc *crtc, uint32_t *roi_w, uint32_t *roi_h)
|
|
mdp5_crtc->cursor.y);
|
|
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,
|
|
static int mdp5_crtc_cursor_set(struct drm_crtc *crtc,
|
|
struct drm_file *file, uint32_t handle,
|
|
struct drm_file *file, uint32_t handle,
|
|
uint32_t width, uint32_t height)
|
|
uint32_t width, uint32_t height)
|
|
@@ -749,13 +811,9 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc,
|
|
struct platform_device *pdev = mdp5_kms->pdev;
|
|
struct platform_device *pdev = mdp5_kms->pdev;
|
|
struct msm_kms *kms = &mdp5_kms->base.base;
|
|
struct msm_kms *kms = &mdp5_kms->base.base;
|
|
struct drm_gem_object *cursor_bo, *old_bo = NULL;
|
|
struct drm_gem_object *cursor_bo, *old_bo = NULL;
|
|
- uint32_t blendcfg, stride;
|
|
|
|
- uint64_t cursor_addr;
|
|
|
|
struct mdp5_ctl *ctl;
|
|
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 flush_mask = mdp_ctl_flush_mask_cursor(0);
|
|
- uint32_t roi_w, roi_h;
|
|
|
|
bool cursor_enable = true;
|
|
bool cursor_enable = true;
|
|
unsigned long flags;
|
|
unsigned long flags;
|
|
|
|
|
|
@@ -775,6 +833,7 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc,
|
|
if (!handle) {
|
|
if (!handle) {
|
|
DBG("Cursor off");
|
|
DBG("Cursor off");
|
|
cursor_enable = false;
|
|
cursor_enable = false;
|
|
|
|
+ mdp5_crtc->cursor.iova = 0;
|
|
pm_runtime_get_sync(&pdev->dev);
|
|
pm_runtime_get_sync(&pdev->dev);
|
|
goto set_cursor;
|
|
goto set_cursor;
|
|
}
|
|
}
|
|
@@ -783,13 +842,11 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc,
|
|
if (!cursor_bo)
|
|
if (!cursor_bo)
|
|
return -ENOENT;
|
|
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)
|
|
if (ret)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
- lm = mdp5_cstate->pipeline.mixer->lm;
|
|
|
|
- stride = width * drm_format_plane_cpp(DRM_FORMAT_ARGB8888, 0);
|
|
|
|
-
|
|
|
|
pm_runtime_get_sync(&pdev->dev);
|
|
pm_runtime_get_sync(&pdev->dev);
|
|
|
|
|
|
spin_lock_irqsave(&mdp5_crtc->cursor.lock, flags);
|
|
spin_lock_irqsave(&mdp5_crtc->cursor.lock, flags);
|
|
@@ -799,22 +856,7 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc,
|
|
mdp5_crtc->cursor.width = width;
|
|
mdp5_crtc->cursor.width = width;
|
|
mdp5_crtc->cursor.height = height;
|
|
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);
|
|
spin_unlock_irqrestore(&mdp5_crtc->cursor.lock, flags);
|
|
|
|
|
|
@@ -845,7 +887,6 @@ static int mdp5_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
|
|
struct mdp5_kms *mdp5_kms = get_kms(crtc);
|
|
struct mdp5_kms *mdp5_kms = get_kms(crtc);
|
|
struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
|
|
struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
|
|
struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
|
|
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 flush_mask = mdp_ctl_flush_mask_cursor(0);
|
|
uint32_t roi_w;
|
|
uint32_t roi_w;
|
|
uint32_t roi_h;
|
|
uint32_t roi_h;
|
|
@@ -867,12 +908,7 @@ static int mdp5_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
|
|
pm_runtime_get_sync(&mdp5_kms->pdev->dev);
|
|
pm_runtime_get_sync(&mdp5_kms->pdev->dev);
|
|
|
|
|
|
spin_lock_irqsave(&mdp5_crtc->cursor.lock, flags);
|
|
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);
|
|
spin_unlock_irqrestore(&mdp5_crtc->cursor.lock, flags);
|
|
|
|
|
|
crtc_flush(crtc, flush_mask);
|
|
crtc_flush(crtc, flush_mask);
|