diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
index b9bcd310ca2d..b3494f6b66bb 100644
--- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c
+++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
@@ -54,6 +54,69 @@ struct drm_gem_object *drm_gem_fb_get_obj(struct drm_framebuffer *fb,
 }
 EXPORT_SYMBOL_GPL(drm_gem_fb_get_obj);
 
+/**
+ * drm_gem_fb_init_with_funcs() - Initialize an already allocated framebuffer
+ * @fb: Framebuffer
+ * @dev: DRM device
+ * @mode_cmd: Metadata from the userspace framebuffer creation request
+ * @obj: GEM objects to be assigned to the framebuffer
+ * @num_planes: number of planes
+ * @funcs: vtable to be used for the framebuffer object
+ *
+ * This variant of the function allows passing a custom vtable.
+ *
+ * Returns:
+ * 0 on success or a negative error code
+ */
+int drm_gem_fb_init_with_funcs(struct drm_framebuffer *fb,
+			       struct drm_device *dev,
+			       const struct drm_mode_fb_cmd2 *mode_cmd,
+			       struct drm_gem_object **obj,
+			       unsigned int num_planes,
+			       const struct drm_framebuffer_funcs *funcs)
+{
+	int ret, i;
+
+	drm_helper_mode_fill_fb_struct(dev, fb, mode_cmd);
+
+	for (i = 0; i < num_planes; i++)
+		fb->obj[i] = obj[i];
+
+	ret = drm_framebuffer_init(dev, fb, funcs);
+	if (ret)
+		DRM_DEV_ERROR(dev->dev, "Failed to init framebuffer: %d\n", ret);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(drm_gem_fb_init_with_funcs);
+
+static const struct drm_framebuffer_funcs drm_gem_fb_funcs = {
+	.destroy	= drm_gem_fb_destroy,
+	.create_handle	= drm_gem_fb_create_handle,
+};
+
+/**
+ * drm_gem_fb_init() - Initialize an already allocated framebuffer
+ * @fb: Framebuffer
+ * @dev: DRM device
+ * @mode_cmd: Metadata from the userspace framebuffer creation request
+ * @obj: GEM objects to be assigned to the framebuffer
+ * @num_planes: number of planes
+ *
+ * This variant of the function uses a default vtable.
+ *
+ * Returns:
+ * 0 on success or a negative error code
+ */
+int drm_gem_fb_init(struct drm_framebuffer *fb,
+		    struct drm_device *dev,
+		    const struct drm_mode_fb_cmd2 *mode_cmd,
+		    struct drm_gem_object **obj, unsigned int num_planes)
+{
+	return drm_gem_fb_init_with_funcs(fb, dev, mode_cmd, obj, num_planes, &drm_gem_fb_funcs);
+}
+EXPORT_SYMBOL_GPL(drm_gem_fb_init);
+
 static struct drm_framebuffer *
 drm_gem_fb_alloc(struct drm_device *dev,
 		 const struct drm_mode_fb_cmd2 *mode_cmd,
@@ -61,21 +124,14 @@ drm_gem_fb_alloc(struct drm_device *dev,
 		 const struct drm_framebuffer_funcs *funcs)
 {
 	struct drm_framebuffer *fb;
-	int ret, i;
+	int ret;
 
 	fb = kzalloc(sizeof(*fb), GFP_KERNEL);
 	if (!fb)
 		return ERR_PTR(-ENOMEM);
 
-	drm_helper_mode_fill_fb_struct(dev, fb, mode_cmd);
-
-	for (i = 0; i < num_planes; i++)
-		fb->obj[i] = obj[i];
-
-	ret = drm_framebuffer_init(dev, fb, funcs);
+	ret = drm_gem_fb_init_with_funcs(fb, dev, mode_cmd, obj, num_planes, funcs);
 	if (ret) {
-		DRM_DEV_ERROR(dev->dev, "Failed to init framebuffer: %d\n",
-			      ret);
 		kfree(fb);
 		return ERR_PTR(ret);
 	}
@@ -144,59 +200,29 @@ drm_gem_fb_create_with_funcs(struct drm_device *dev, struct drm_file *file,
 			     const struct drm_mode_fb_cmd2 *mode_cmd,
 			     const struct drm_framebuffer_funcs *funcs)
 {
-	const struct drm_format_info *info;
 	struct drm_gem_object *objs[4];
 	struct drm_framebuffer *fb;
-	int ret, i;
-
-	info = drm_get_format_info(dev, mode_cmd);
-	if (!info)
-		return ERR_PTR(-EINVAL);
-
-	for (i = 0; i < info->num_planes; i++) {
-		unsigned int width = mode_cmd->width / (i ? info->hsub : 1);
-		unsigned int height = mode_cmd->height / (i ? info->vsub : 1);
-		unsigned int min_size;
+	int ret, num_planes;
 
-		objs[i] = drm_gem_object_lookup(file, mode_cmd->handles[i]);
-		if (!objs[i]) {
-			DRM_DEBUG_KMS("Failed to lookup GEM object\n");
-			ret = -ENOENT;
-			goto err_gem_object_put;
-		}
-
-		min_size = (height - 1) * mode_cmd->pitches[i]
-			 + drm_format_info_min_pitch(info, i, width)
-			 + mode_cmd->offsets[i];
+	ret = drm_gem_fb_lookup(dev, file, mode_cmd, objs);
+	if (ret < 0)
+		return ERR_PTR(ret);
+	num_planes = ret;
 
-		if (objs[i]->size < min_size) {
-			drm_gem_object_put_unlocked(objs[i]);
-			ret = -EINVAL;
-			goto err_gem_object_put;
-		}
-	}
+	ret = drm_gem_fb_size_check(dev, mode_cmd, objs);
+	if (ret)
+		fb = ERR_PTR(ret);
+	else
+		fb = drm_gem_fb_alloc(dev, mode_cmd, objs, num_planes, funcs);
 
-	fb = drm_gem_fb_alloc(dev, mode_cmd, objs, i, funcs);
-	if (IS_ERR(fb)) {
-		ret = PTR_ERR(fb);
-		goto err_gem_object_put;
-	}
+	if (IS_ERR(fb))
+		for (num_planes--; num_planes >= 0; num_planes--)
+			drm_gem_object_put_unlocked(objs[num_planes]);
 
 	return fb;
-
-err_gem_object_put:
-	for (i--; i >= 0; i--)
-		drm_gem_object_put_unlocked(objs[i]);
-
-	return ERR_PTR(ret);
 }
 EXPORT_SYMBOL_GPL(drm_gem_fb_create_with_funcs);
 
-static const struct drm_framebuffer_funcs drm_gem_fb_funcs = {
-	.destroy	= drm_gem_fb_destroy,
-	.create_handle	= drm_gem_fb_create_handle,
-};
-
 /**
  * drm_gem_fb_create() - Helper function for the
  *                       &drm_mode_config_funcs.fb_create callback
@@ -228,6 +254,92 @@ drm_gem_fb_create(struct drm_device *dev, struct drm_file *file,
 }
 EXPORT_SYMBOL_GPL(drm_gem_fb_create);
 
+/**
+ * drm_gem_fb_lookup() - Helper function for use in
+ *			 &drm_mode_config_funcs.fb_create implementations
+ * @dev: DRM device
+ * @file: DRM file that holds the GEM handle(s) backing the framebuffer
+ * @mode_cmd: Metadata from the userspace framebuffer creation request
+ *
+ * This function can be used to look up the objects for all planes.
+ * In case an error is returned all the objects are put by the
+ * function before returning.
+ *
+ * Returns:
+ * Number of planes on success or a negative error code on failure.
+ */
+int drm_gem_fb_lookup(struct drm_device *dev,
+		      struct drm_file *file,
+		      const struct drm_mode_fb_cmd2 *mode_cmd,
+		      struct drm_gem_object **objs)
+{
+	const struct drm_format_info *info;
+	int ret, i;
+
+	info = drm_get_format_info(dev, mode_cmd);
+	if (!info)
+		return -EINVAL;
+
+	for (i = 0; i < info->num_planes; i++) {
+		objs[i] = drm_gem_object_lookup(file, mode_cmd->handles[i]);
+		if (!objs[i]) {
+			DRM_DEBUG_KMS("Failed to lookup GEM object\n");
+			ret = -ENOENT;
+			goto err_gem_object_put;
+		}
+	}
+
+	return i;
+
+err_gem_object_put:
+	for (i--; i >= 0; i--)
+		drm_gem_object_put_unlocked(objs[i]);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(drm_gem_fb_lookup);
+
+/**
+ * drm_gem_fb_size_check() - Helper function for use in
+ *			     &drm_mode_config_funcs.fb_create implementations
+ * @dev: DRM device
+ * @mode_cmd: Metadata from the userspace framebuffer creation request
+ *
+ * This function can be used to verify buffer sizes for all planes.
+ * It is caller's responsibility to put the objects on failure.
+ *
+ * Returns:
+ * Zero on success or a negative error code on failure.
+ */
+int drm_gem_fb_size_check(struct drm_device *dev,
+			  const struct drm_mode_fb_cmd2 *mode_cmd,
+			  struct drm_gem_object **objs)
+{
+	const struct drm_format_info *info;
+	int i;
+
+	info = drm_get_format_info(dev, mode_cmd);
+	if (!info)
+		return -EINVAL;
+
+	for (i = 0; i < info->num_planes; i++) {
+		unsigned int width = mode_cmd->width / (i ? info->hsub : 1);
+		unsigned int height = mode_cmd->height / (i ? info->vsub : 1);
+		unsigned int min_size;
+
+		min_size = (height - 1) * mode_cmd->pitches[i]
+			 + drm_format_info_min_pitch(info, i, width)
+			 + mode_cmd->offsets[i];
+
+		if (objs[i]->size < min_size)
+			return -EINVAL;
+	}
+
+	return 0;
+
+}
+EXPORT_SYMBOL_GPL(drm_gem_fb_size_check);
+
 static const struct drm_framebuffer_funcs drm_gem_fb_funcs_dirtyfb = {
 	.destroy	= drm_gem_fb_destroy,
 	.create_handle	= drm_gem_fb_create_handle,
diff --git a/include/drm/drm_gem_framebuffer_helper.h b/include/drm/drm_gem_framebuffer_helper.h
index d9f13fd25b0a..c85d4b152e91 100644
--- a/include/drm/drm_gem_framebuffer_helper.h
+++ b/include/drm/drm_gem_framebuffer_helper.h
@@ -14,10 +14,27 @@ struct drm_simple_display_pipe;
 
 struct drm_gem_object *drm_gem_fb_get_obj(struct drm_framebuffer *fb,
 					  unsigned int plane);
+int drm_gem_fb_init_with_funcs(struct drm_framebuffer *fb,
+			       struct drm_device *dev,
+			       const struct drm_mode_fb_cmd2 *mode_cmd,
+			       struct drm_gem_object **obj,
+			       unsigned int num_planes,
+			       const struct drm_framebuffer_funcs *funcs);
+int drm_gem_fb_init(struct drm_framebuffer *fb,
+		    struct drm_device *dev,
+		    const struct drm_mode_fb_cmd2 *mode_cmd,
+		    struct drm_gem_object **obj, unsigned int num_planes);
 void drm_gem_fb_destroy(struct drm_framebuffer *fb);
 int drm_gem_fb_create_handle(struct drm_framebuffer *fb, struct drm_file *file,
 			     unsigned int *handle);
 
+int drm_gem_fb_lookup(struct drm_device *dev,
+		      struct drm_file *file,
+		      const struct drm_mode_fb_cmd2 *mode_cmd,
+		      struct drm_gem_object **objs);
+int drm_gem_fb_size_check(struct drm_device *dev,
+			  const struct drm_mode_fb_cmd2 *mode_cmd,
+			  struct drm_gem_object **objs);
 struct drm_framebuffer *
 drm_gem_fb_create_with_funcs(struct drm_device *dev, struct drm_file *file,
 			     const struct drm_mode_fb_cmd2 *mode_cmd,
