diff options
Diffstat (limited to 'drivers/gpu/drm/msm/msm_fb.c')
-rw-r--r-- | drivers/gpu/drm/msm/msm_fb.c | 51 |
1 files changed, 29 insertions, 22 deletions
diff --git a/drivers/gpu/drm/msm/msm_fb.c b/drivers/gpu/drm/msm/msm_fb.c index 09268e416843..1eff615ff9bf 100644 --- a/drivers/gpu/drm/msm/msm_fb.c +++ b/drivers/gpu/drm/msm/msm_fb.c @@ -30,6 +30,7 @@ struct msm_framebuffer { #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_format_info *info, const struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos); static int msm_framebuffer_dirtyfb(struct drm_framebuffer *fb, @@ -75,20 +76,22 @@ void msm_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m) /* prepare/pin all the fb's bo's for scanout. */ -int msm_framebuffer_prepare(struct drm_framebuffer *fb, - struct msm_gem_address_space *aspace, - bool needs_dirtyfb) +int msm_framebuffer_prepare(struct drm_framebuffer *fb, bool needs_dirtyfb) { + struct msm_drm_private *priv = fb->dev->dev_private; + struct drm_gpuvm *vm = priv->kms->vm; struct msm_framebuffer *msm_fb = to_msm_framebuffer(fb); int ret, i, n = fb->format->num_planes; if (needs_dirtyfb) refcount_inc(&msm_fb->dirtyfb); - atomic_inc(&msm_fb->prepare_count); + if (atomic_inc_return(&msm_fb->prepare_count) > 1) + return 0; for (i = 0; i < n; i++) { - ret = msm_gem_get_and_pin_iova(fb->obj[i], aspace, &msm_fb->iova[i]); + msm_gem_vma_get(fb->obj[i]); + ret = msm_gem_get_and_pin_iova(fb->obj[i], vm, &msm_fb->iova[i]); drm_dbg_state(fb->dev, "FB[%u]: iova[%d]: %08llx (%d)\n", fb->base.id, i, msm_fb->iova[i], ret); if (ret) @@ -98,25 +101,28 @@ int msm_framebuffer_prepare(struct drm_framebuffer *fb, return 0; } -void msm_framebuffer_cleanup(struct drm_framebuffer *fb, - struct msm_gem_address_space *aspace, - bool needed_dirtyfb) +void msm_framebuffer_cleanup(struct drm_framebuffer *fb, bool needed_dirtyfb) { + struct msm_drm_private *priv = fb->dev->dev_private; + struct drm_gpuvm *vm = priv->kms->vm; 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); + if (atomic_dec_return(&msm_fb->prepare_count)) + return; + + memset(msm_fb->iova, 0, sizeof(msm_fb->iova)); - if (!atomic_dec_return(&msm_fb->prepare_count)) - memset(msm_fb->iova, 0, sizeof(msm_fb->iova)); + for (i = 0; i < n; i++) { + msm_gem_unpin_iova(fb->obj[i], vm); + msm_gem_vma_put(fb->obj[i]); + } } -uint32_t msm_framebuffer_iova(struct drm_framebuffer *fb, - struct msm_gem_address_space *aspace, int plane) +uint32_t msm_framebuffer_iova(struct drm_framebuffer *fb, int plane) { struct msm_framebuffer *msm_fb = to_msm_framebuffer(fb); return msm_fb->iova[plane] + fb->offsets[plane]; @@ -134,10 +140,9 @@ const struct msm_format *msm_framebuffer_format(struct drm_framebuffer *fb) } struct drm_framebuffer *msm_framebuffer_create(struct drm_device *dev, - struct drm_file *file, const struct drm_mode_fb_cmd2 *mode_cmd) + struct drm_file *file, const struct drm_format_info *info, + const struct drm_mode_fb_cmd2 *mode_cmd) { - const struct drm_format_info *info = drm_get_format_info(dev, - mode_cmd); struct drm_gem_object *bos[4] = {0}; struct drm_framebuffer *fb; int ret, i, n = info->num_planes; @@ -150,7 +155,7 @@ struct drm_framebuffer *msm_framebuffer_create(struct drm_device *dev, } } - fb = msm_framebuffer_init(dev, mode_cmd, bos); + fb = msm_framebuffer_init(dev, info, mode_cmd, bos); if (IS_ERR(fb)) { ret = PTR_ERR(fb); goto out_unref; @@ -165,10 +170,9 @@ out_unref: } static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev, + const struct drm_format_info *info, const struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos) { - const struct drm_format_info *info = drm_get_format_info(dev, - mode_cmd); struct msm_drm_private *priv = dev->dev_private; struct msm_kms *kms = priv->kms; struct msm_framebuffer *msm_fb = NULL; @@ -222,7 +226,7 @@ static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev, msm_fb->base.obj[i] = bos[i]; } - drm_helper_mode_fill_fb_struct(dev, fb, mode_cmd); + drm_helper_mode_fill_fb_struct(dev, fb, info, mode_cmd); ret = drm_framebuffer_init(dev, fb, &msm_framebuffer_funcs); if (ret) { @@ -271,7 +275,10 @@ msm_alloc_stolen_fb(struct drm_device *dev, int w, int h, int p, uint32_t format msm_gem_object_set_name(bo, "stolenfb"); - fb = msm_framebuffer_init(dev, &mode_cmd, &bo); + fb = msm_framebuffer_init(dev, + drm_get_format_info(dev, mode_cmd.pixel_format, + mode_cmd.modifier[0]), + &mode_cmd, &bo); if (IS_ERR(fb)) { DRM_DEV_ERROR(dev->dev, "failed to allocate fb\n"); /* note: if fb creation failed, we can't rely on fb destroy |