diff options
Diffstat (limited to 'drivers/gpu/drm/msm/msm_fb.c')
-rw-r--r-- | drivers/gpu/drm/msm/msm_fb.c | 43 |
1 files changed, 36 insertions, 7 deletions
diff --git a/drivers/gpu/drm/msm/msm_fb.c b/drivers/gpu/drm/msm/msm_fb.c index 4d34df5354e0..7137492fe78e 100644 --- a/drivers/gpu/drm/msm/msm_fb.c +++ b/drivers/gpu/drm/msm/msm_fb.c @@ -18,16 +18,36 @@ struct msm_framebuffer { struct drm_framebuffer base; const struct msm_format *format; + + /* Count of # of attached planes which need dirtyfb: */ + refcount_t dirtyfb; }; #define to_msm_framebuffer(x) container_of(x, struct msm_framebuffer, base) static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev, const struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos); +static int msm_framebuffer_dirtyfb(struct drm_framebuffer *fb, + struct drm_file *file_priv, unsigned int flags, + unsigned int color, struct drm_clip_rect *clips, + unsigned int num_clips) +{ + struct msm_framebuffer *msm_fb = to_msm_framebuffer(fb); + + /* If this fb is not used on any display requiring pixel data to be + * flushed, then skip dirtyfb + */ + if (refcount_read(&msm_fb->dirtyfb) == 1) + return 0; + + return drm_atomic_helper_dirtyfb(fb, file_priv, flags, color, + clips, num_clips); +} + static const struct drm_framebuffer_funcs msm_framebuffer_funcs = { .create_handle = drm_gem_fb_create_handle, .destroy = drm_gem_fb_destroy, - .dirty = drm_atomic_helper_dirtyfb, + .dirty = msm_framebuffer_dirtyfb, }; #ifdef CONFIG_DEBUG_FS @@ -48,17 +68,19 @@ void msm_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m) } #endif -/* prepare/pin all the fb's bo's for scanout. Note that it is not valid - * to prepare an fb more multiple different initiator 'id's. But that - * should be fine, since only the scanout (mdpN) side of things needs - * this, the gpu doesn't care about fb's. +/* prepare/pin all the fb's bo's for scanout. */ int msm_framebuffer_prepare(struct drm_framebuffer *fb, - struct msm_gem_address_space *aspace) + struct msm_gem_address_space *aspace, + bool needs_dirtyfb) { + struct msm_framebuffer *msm_fb = to_msm_framebuffer(fb); int ret, i, n = fb->format->num_planes; uint64_t iova; + if (needs_dirtyfb) + refcount_inc(&msm_fb->dirtyfb); + for (i = 0; i < n; i++) { ret = msm_gem_get_and_pin_iova(fb->obj[i], aspace, &iova); drm_dbg_state(fb->dev, "FB[%u]: iova[%d]: %08llx (%d)", fb->base.id, i, iova, ret); @@ -70,10 +92,15 @@ int msm_framebuffer_prepare(struct drm_framebuffer *fb, } void msm_framebuffer_cleanup(struct drm_framebuffer *fb, - struct msm_gem_address_space *aspace) + struct msm_gem_address_space *aspace, + bool needed_dirtyfb) { + struct msm_framebuffer *msm_fb = to_msm_framebuffer(fb); int i, n = fb->format->num_planes; + if (needed_dirtyfb) + refcount_dec(&msm_fb->dirtyfb); + for (i = 0; i < n; i++) msm_gem_unpin_iova(fb->obj[i], aspace); } @@ -194,6 +221,8 @@ static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev, goto fail; } + refcount_set(&msm_fb->dirtyfb, 1); + drm_dbg_state(dev, "create: FB ID: %d (%p)", fb->base.id, fb); return fb; |