From 2c3c1048746a4622d8c89a29670120dc8fab93c4 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 20:49:45 +0200 Subject: Adding upstream version 6.1.76. Signed-off-by: Daniel Baumann --- drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 140 +++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_fb.c (limited to 'drivers/gpu/drm/rockchip/rockchip_drm_fb.c') diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c new file mode 100644 index 000000000..092bf8631 --- /dev/null +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd + * Author:Mark Yao + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rockchip_drm_drv.h" +#include "rockchip_drm_fb.h" +#include "rockchip_drm_gem.h" + +static const struct drm_framebuffer_funcs rockchip_drm_fb_funcs = { + .destroy = drm_gem_fb_destroy, + .create_handle = drm_gem_fb_create_handle, + .dirty = drm_atomic_helper_dirtyfb, +}; + +static struct drm_framebuffer * +rockchip_fb_alloc(struct drm_device *dev, const struct drm_mode_fb_cmd2 *mode_cmd, + struct drm_gem_object **obj, unsigned int num_planes) +{ + struct drm_framebuffer *fb; + int ret; + int i; + + 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, &rockchip_drm_fb_funcs); + if (ret) { + DRM_DEV_ERROR(dev->dev, + "Failed to initialize framebuffer: %d\n", + ret); + kfree(fb); + return ERR_PTR(ret); + } + + return fb; +} + +static const struct drm_mode_config_helper_funcs rockchip_mode_config_helpers = { + .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm, +}; + +static struct drm_framebuffer * +rockchip_fb_create(struct drm_device *dev, struct drm_file *file, + const struct drm_mode_fb_cmd2 *mode_cmd) +{ + struct drm_afbc_framebuffer *afbc_fb; + const struct drm_format_info *info; + int ret; + + info = drm_get_format_info(dev, mode_cmd); + if (!info) + return ERR_PTR(-ENOMEM); + + afbc_fb = kzalloc(sizeof(*afbc_fb), GFP_KERNEL); + if (!afbc_fb) + return ERR_PTR(-ENOMEM); + + ret = drm_gem_fb_init_with_funcs(dev, &afbc_fb->base, file, mode_cmd, + &rockchip_drm_fb_funcs); + if (ret) { + kfree(afbc_fb); + return ERR_PTR(ret); + } + + if (drm_is_afbc(mode_cmd->modifier[0])) { + int ret, i; + + ret = drm_gem_fb_afbc_init(dev, mode_cmd, afbc_fb); + if (ret) { + struct drm_gem_object **obj = afbc_fb->base.obj; + + for (i = 0; i < info->num_planes; ++i) + drm_gem_object_put(obj[i]); + + kfree(afbc_fb); + return ERR_PTR(ret); + } + } + + return &afbc_fb->base; +} + +static const struct drm_mode_config_funcs rockchip_drm_mode_config_funcs = { + .fb_create = rockchip_fb_create, + .output_poll_changed = drm_fb_helper_output_poll_changed, + .atomic_check = drm_atomic_helper_check, + .atomic_commit = drm_atomic_helper_commit, +}; + +struct drm_framebuffer * +rockchip_drm_framebuffer_init(struct drm_device *dev, + const struct drm_mode_fb_cmd2 *mode_cmd, + struct drm_gem_object *obj) +{ + struct drm_framebuffer *fb; + + fb = rockchip_fb_alloc(dev, mode_cmd, &obj, 1); + if (IS_ERR(fb)) + return ERR_CAST(fb); + + return fb; +} + +void rockchip_drm_mode_config_init(struct drm_device *dev) +{ + dev->mode_config.min_width = 0; + dev->mode_config.min_height = 0; + + /* + * set max width and height as default value(4096x4096). + * this value would be used to check framebuffer size limitation + * at drm_mode_addfb(). + */ + dev->mode_config.max_width = 4096; + dev->mode_config.max_height = 4096; + + dev->mode_config.funcs = &rockchip_drm_mode_config_funcs; + dev->mode_config.helper_private = &rockchip_mode_config_helpers; + + dev->mode_config.normalize_zpos = true; +} -- cgit v1.2.3