Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
0004  * Author:Mark Yao <mark.yao@rock-chips.com>
0005  */
0006 
0007 #include <linux/kernel.h>
0008 
0009 #include <drm/drm.h>
0010 #include <drm/drm_atomic.h>
0011 #include <drm/drm_damage_helper.h>
0012 #include <drm/drm_fb_helper.h>
0013 #include <drm/drm_fourcc.h>
0014 #include <drm/drm_framebuffer.h>
0015 #include <drm/drm_gem_framebuffer_helper.h>
0016 #include <drm/drm_probe_helper.h>
0017 
0018 #include "rockchip_drm_drv.h"
0019 #include "rockchip_drm_fb.h"
0020 #include "rockchip_drm_gem.h"
0021 
0022 static const struct drm_framebuffer_funcs rockchip_drm_fb_funcs = {
0023     .destroy       = drm_gem_fb_destroy,
0024     .create_handle = drm_gem_fb_create_handle,
0025     .dirty         = drm_atomic_helper_dirtyfb,
0026 };
0027 
0028 static struct drm_framebuffer *
0029 rockchip_fb_alloc(struct drm_device *dev, const struct drm_mode_fb_cmd2 *mode_cmd,
0030           struct drm_gem_object **obj, unsigned int num_planes)
0031 {
0032     struct drm_framebuffer *fb;
0033     int ret;
0034     int i;
0035 
0036     fb = kzalloc(sizeof(*fb), GFP_KERNEL);
0037     if (!fb)
0038         return ERR_PTR(-ENOMEM);
0039 
0040     drm_helper_mode_fill_fb_struct(dev, fb, mode_cmd);
0041 
0042     for (i = 0; i < num_planes; i++)
0043         fb->obj[i] = obj[i];
0044 
0045     ret = drm_framebuffer_init(dev, fb, &rockchip_drm_fb_funcs);
0046     if (ret) {
0047         DRM_DEV_ERROR(dev->dev,
0048                   "Failed to initialize framebuffer: %d\n",
0049                   ret);
0050         kfree(fb);
0051         return ERR_PTR(ret);
0052     }
0053 
0054     return fb;
0055 }
0056 
0057 static const struct drm_mode_config_helper_funcs rockchip_mode_config_helpers = {
0058     .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,
0059 };
0060 
0061 static struct drm_framebuffer *
0062 rockchip_fb_create(struct drm_device *dev, struct drm_file *file,
0063            const struct drm_mode_fb_cmd2 *mode_cmd)
0064 {
0065     struct drm_afbc_framebuffer *afbc_fb;
0066     const struct drm_format_info *info;
0067     int ret;
0068 
0069     info = drm_get_format_info(dev, mode_cmd);
0070     if (!info)
0071         return ERR_PTR(-ENOMEM);
0072 
0073     afbc_fb = kzalloc(sizeof(*afbc_fb), GFP_KERNEL);
0074     if (!afbc_fb)
0075         return ERR_PTR(-ENOMEM);
0076 
0077     ret = drm_gem_fb_init_with_funcs(dev, &afbc_fb->base, file, mode_cmd,
0078                      &rockchip_drm_fb_funcs);
0079     if (ret) {
0080         kfree(afbc_fb);
0081         return ERR_PTR(ret);
0082     }
0083 
0084     if (drm_is_afbc(mode_cmd->modifier[0])) {
0085         int ret, i;
0086 
0087         ret = drm_gem_fb_afbc_init(dev, mode_cmd, afbc_fb);
0088         if (ret) {
0089             struct drm_gem_object **obj = afbc_fb->base.obj;
0090 
0091             for (i = 0; i < info->num_planes; ++i)
0092                 drm_gem_object_put(obj[i]);
0093 
0094             kfree(afbc_fb);
0095             return ERR_PTR(ret);
0096         }
0097     }
0098 
0099     return &afbc_fb->base;
0100 }
0101 
0102 static const struct drm_mode_config_funcs rockchip_drm_mode_config_funcs = {
0103     .fb_create = rockchip_fb_create,
0104     .output_poll_changed = drm_fb_helper_output_poll_changed,
0105     .atomic_check = drm_atomic_helper_check,
0106     .atomic_commit = drm_atomic_helper_commit,
0107 };
0108 
0109 struct drm_framebuffer *
0110 rockchip_drm_framebuffer_init(struct drm_device *dev,
0111                   const struct drm_mode_fb_cmd2 *mode_cmd,
0112                   struct drm_gem_object *obj)
0113 {
0114     struct drm_framebuffer *fb;
0115 
0116     fb = rockchip_fb_alloc(dev, mode_cmd, &obj, 1);
0117     if (IS_ERR(fb))
0118         return ERR_CAST(fb);
0119 
0120     return fb;
0121 }
0122 
0123 void rockchip_drm_mode_config_init(struct drm_device *dev)
0124 {
0125     dev->mode_config.min_width = 0;
0126     dev->mode_config.min_height = 0;
0127 
0128     /*
0129      * set max width and height as default value(4096x4096).
0130      * this value would be used to check framebuffer size limitation
0131      * at drm_mode_addfb().
0132      */
0133     dev->mode_config.max_width = 4096;
0134     dev->mode_config.max_height = 4096;
0135 
0136     dev->mode_config.funcs = &rockchip_drm_mode_config_funcs;
0137     dev->mode_config.helper_private = &rockchip_mode_config_helpers;
0138 
0139     dev->mode_config.normalize_zpos = true;
0140 }