]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - drivers/gpu/drm/drm_fb_cma_helper.c
drm/i915: Use the precomputed value for whether to enable command parsing
[mirror_ubuntu-artful-kernel.git] / drivers / gpu / drm / drm_fb_cma_helper.c
index 1fd6eac1400c1c92bae8edaac6a622a322d7ace0..81b3558302b5ab7a307bb9c852859b043dd34378 100644 (file)
  */
 
 #include <drm/drmP.h>
+#include <drm/drm_atomic.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_fb_cma_helper.h>
+#include <linux/dma-buf.h>
 #include <linux/dma-mapping.h>
 #include <linux/module.h>
+#include <linux/reservation.h>
 
 #define DEFAULT_FBDEFIO_DELAY_MS 50
 
@@ -176,20 +179,20 @@ struct drm_framebuffer *drm_fb_cma_create_with_funcs(struct drm_device *dev,
        struct drm_file *file_priv, const struct drm_mode_fb_cmd2 *mode_cmd,
        const struct drm_framebuffer_funcs *funcs)
 {
+       const struct drm_format_info *info;
        struct drm_fb_cma *fb_cma;
        struct drm_gem_cma_object *objs[4];
        struct drm_gem_object *obj;
-       unsigned int hsub;
-       unsigned int vsub;
        int ret;
        int i;
 
-       hsub = drm_format_horz_chroma_subsampling(mode_cmd->pixel_format);
-       vsub = drm_format_vert_chroma_subsampling(mode_cmd->pixel_format);
+       info = drm_format_info(mode_cmd->pixel_format);
+       if (!info)
+               return ERR_PTR(-EINVAL);
 
-       for (i = 0; i < drm_format_num_planes(mode_cmd->pixel_format); i++) {
-               unsigned int width = mode_cmd->width / (i ? hsub : 1);
-               unsigned int height = mode_cmd->height / (i ? vsub : 1);
+       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;
 
                obj = drm_gem_object_lookup(file_priv, mode_cmd->handles[i]);
@@ -200,7 +203,7 @@ struct drm_framebuffer *drm_fb_cma_create_with_funcs(struct drm_device *dev,
                }
 
                min_size = (height - 1) * mode_cmd->pitches[i]
-                        + width * drm_format_plane_cpp(mode_cmd->pixel_format, i)
+                        + width * info->cpp[i]
                         + mode_cmd->offsets[i];
 
                if (obj->size < min_size) {
@@ -265,16 +268,51 @@ struct drm_gem_cma_object *drm_fb_cma_get_gem_obj(struct drm_framebuffer *fb,
 }
 EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_obj);
 
+/**
+ * drm_fb_cma_prepare_fb() - Prepare CMA framebuffer
+ * @plane: Which plane
+ * @state: Plane state attach fence to
+ *
+ * This should be put into prepare_fb hook of struct &drm_plane_helper_funcs .
+ *
+ * This function checks if the plane FB has an dma-buf attached, extracts
+ * the exclusive fence and attaches it to plane state for the atomic helper
+ * to wait on.
+ *
+ * There is no need for cleanup_fb for CMA based framebuffer drivers.
+ */
+int drm_fb_cma_prepare_fb(struct drm_plane *plane,
+                         struct drm_plane_state *state)
+{
+       struct dma_buf *dma_buf;
+       struct dma_fence *fence;
+
+       if ((plane->state->fb == state->fb) || !state->fb)
+               return 0;
+
+       dma_buf = drm_fb_cma_get_gem_obj(state->fb, 0)->base.dma_buf;
+       if (dma_buf) {
+               fence = reservation_object_get_excl_rcu(dma_buf->resv);
+               drm_atomic_set_fence_for_plane(state, fence);
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(drm_fb_cma_prepare_fb);
+
 #ifdef CONFIG_DEBUG_FS
 static void drm_fb_cma_describe(struct drm_framebuffer *fb, struct seq_file *m)
 {
        struct drm_fb_cma *fb_cma = to_fb_cma(fb);
-       int i, n = drm_format_num_planes(fb->pixel_format);
+       const struct drm_format_info *info;
+       int i;
 
        seq_printf(m, "fb: %dx%d@%4.4s\n", fb->width, fb->height,
                        (char *)&fb->pixel_format);
 
-       for (i = 0; i < n; i++) {
+       info = drm_format_info(fb->pixel_format);
+
+       for (i = 0; i < info->num_planes; i++) {
                seq_printf(m, "   %d: offset=%d pitch=%d, obj: ",
                                i, fb->offsets[i], fb->pitches[i]);
                drm_gem_cma_describe(fb_cma->obj[i], m);
@@ -311,14 +349,10 @@ static int drm_fb_cma_mmap(struct fb_info *info, struct vm_area_struct *vma)
 
 static struct fb_ops drm_fbdev_cma_ops = {
        .owner          = THIS_MODULE,
+       DRM_FB_HELPER_DEFAULT_OPS,
        .fb_fillrect    = drm_fb_helper_sys_fillrect,
        .fb_copyarea    = drm_fb_helper_sys_copyarea,
        .fb_imageblit   = drm_fb_helper_sys_imageblit,
-       .fb_check_var   = drm_fb_helper_check_var,
-       .fb_set_par     = drm_fb_helper_set_par,
-       .fb_blank       = drm_fb_helper_blank,
-       .fb_pan_display = drm_fb_helper_pan_display,
-       .fb_setcmap     = drm_fb_helper_setcmap,
        .fb_mmap        = drm_fb_cma_mmap,
 };
 
@@ -557,7 +591,8 @@ EXPORT_SYMBOL_GPL(drm_fbdev_cma_init);
 void drm_fbdev_cma_fini(struct drm_fbdev_cma *fbdev_cma)
 {
        drm_fb_helper_unregister_fbi(&fbdev_cma->fb_helper);
-       drm_fbdev_cma_defio_fini(fbdev_cma->fb_helper.fbdev);
+       if (fbdev_cma->fb_helper.fbdev)
+               drm_fbdev_cma_defio_fini(fbdev_cma->fb_helper.fbdev);
        drm_fb_helper_release_fbi(&fbdev_cma->fb_helper);
 
        if (fbdev_cma->fb) {