root/drivers/gpu/drm/rockchip/rockchip_drm_fb.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rockchip_fb_alloc
  2. rockchip_user_fb_create
  3. rockchip_drm_framebuffer_init
  4. rockchip_drm_mode_config_init

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
   4  * Author:Mark Yao <mark.yao@rock-chips.com>
   5  */
   6 
   7 #include <linux/kernel.h>
   8 
   9 #include <drm/drm.h>
  10 #include <drm/drm_atomic.h>
  11 #include <drm/drm_damage_helper.h>
  12 #include <drm/drm_fb_helper.h>
  13 #include <drm/drm_fourcc.h>
  14 #include <drm/drm_gem_framebuffer_helper.h>
  15 #include <drm/drm_probe_helper.h>
  16 
  17 #include "rockchip_drm_drv.h"
  18 #include "rockchip_drm_fb.h"
  19 #include "rockchip_drm_gem.h"
  20 
  21 static const struct drm_framebuffer_funcs rockchip_drm_fb_funcs = {
  22         .destroy       = drm_gem_fb_destroy,
  23         .create_handle = drm_gem_fb_create_handle,
  24         .dirty         = drm_atomic_helper_dirtyfb,
  25 };
  26 
  27 static struct drm_framebuffer *
  28 rockchip_fb_alloc(struct drm_device *dev, const struct drm_mode_fb_cmd2 *mode_cmd,
  29                   struct drm_gem_object **obj, unsigned int num_planes)
  30 {
  31         struct drm_framebuffer *fb;
  32         int ret;
  33         int i;
  34 
  35         fb = kzalloc(sizeof(*fb), GFP_KERNEL);
  36         if (!fb)
  37                 return ERR_PTR(-ENOMEM);
  38 
  39         drm_helper_mode_fill_fb_struct(dev, fb, mode_cmd);
  40 
  41         for (i = 0; i < num_planes; i++)
  42                 fb->obj[i] = obj[i];
  43 
  44         ret = drm_framebuffer_init(dev, fb, &rockchip_drm_fb_funcs);
  45         if (ret) {
  46                 DRM_DEV_ERROR(dev->dev,
  47                               "Failed to initialize framebuffer: %d\n",
  48                               ret);
  49                 kfree(fb);
  50                 return ERR_PTR(ret);
  51         }
  52 
  53         return fb;
  54 }
  55 
  56 static struct drm_framebuffer *
  57 rockchip_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
  58                         const struct drm_mode_fb_cmd2 *mode_cmd)
  59 {
  60         const struct drm_format_info *info = drm_get_format_info(dev,
  61                                                                  mode_cmd);
  62         struct drm_framebuffer *fb;
  63         struct drm_gem_object *objs[ROCKCHIP_MAX_FB_BUFFER];
  64         struct drm_gem_object *obj;
  65         int num_planes = min_t(int, info->num_planes, ROCKCHIP_MAX_FB_BUFFER);
  66         int ret;
  67         int i;
  68 
  69         for (i = 0; i < num_planes; i++) {
  70                 unsigned int width = mode_cmd->width / (i ? info->hsub : 1);
  71                 unsigned int height = mode_cmd->height / (i ? info->vsub : 1);
  72                 unsigned int min_size;
  73 
  74                 obj = drm_gem_object_lookup(file_priv, mode_cmd->handles[i]);
  75                 if (!obj) {
  76                         DRM_DEV_ERROR(dev->dev,
  77                                       "Failed to lookup GEM object\n");
  78                         ret = -ENXIO;
  79                         goto err_gem_object_unreference;
  80                 }
  81 
  82                 min_size = (height - 1) * mode_cmd->pitches[i] +
  83                         mode_cmd->offsets[i] +
  84                         width * info->cpp[i];
  85 
  86                 if (obj->size < min_size) {
  87                         drm_gem_object_put_unlocked(obj);
  88                         ret = -EINVAL;
  89                         goto err_gem_object_unreference;
  90                 }
  91                 objs[i] = obj;
  92         }
  93 
  94         fb = rockchip_fb_alloc(dev, mode_cmd, objs, i);
  95         if (IS_ERR(fb)) {
  96                 ret = PTR_ERR(fb);
  97                 goto err_gem_object_unreference;
  98         }
  99 
 100         return fb;
 101 
 102 err_gem_object_unreference:
 103         for (i--; i >= 0; i--)
 104                 drm_gem_object_put_unlocked(objs[i]);
 105         return ERR_PTR(ret);
 106 }
 107 
 108 static const struct drm_mode_config_helper_funcs rockchip_mode_config_helpers = {
 109         .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,
 110 };
 111 
 112 static const struct drm_mode_config_funcs rockchip_drm_mode_config_funcs = {
 113         .fb_create = rockchip_user_fb_create,
 114         .output_poll_changed = drm_fb_helper_output_poll_changed,
 115         .atomic_check = drm_atomic_helper_check,
 116         .atomic_commit = drm_atomic_helper_commit,
 117 };
 118 
 119 struct drm_framebuffer *
 120 rockchip_drm_framebuffer_init(struct drm_device *dev,
 121                               const struct drm_mode_fb_cmd2 *mode_cmd,
 122                               struct drm_gem_object *obj)
 123 {
 124         struct drm_framebuffer *fb;
 125 
 126         fb = rockchip_fb_alloc(dev, mode_cmd, &obj, 1);
 127         if (IS_ERR(fb))
 128                 return ERR_CAST(fb);
 129 
 130         return fb;
 131 }
 132 
 133 void rockchip_drm_mode_config_init(struct drm_device *dev)
 134 {
 135         dev->mode_config.min_width = 0;
 136         dev->mode_config.min_height = 0;
 137 
 138         /*
 139          * set max width and height as default value(4096x4096).
 140          * this value would be used to check framebuffer size limitation
 141          * at drm_mode_addfb().
 142          */
 143         dev->mode_config.max_width = 4096;
 144         dev->mode_config.max_height = 4096;
 145 
 146         dev->mode_config.funcs = &rockchip_drm_mode_config_funcs;
 147         dev->mode_config.helper_private = &rockchip_mode_config_helpers;
 148 }

/* [<][>][^][v][top][bottom][index][help] */