Am 18.08.22 um 11:45 schrieb oushixiong:
This patch adds ast specific codes for DRM prime feature, this is to
allow for offloading of rending in one direction and outputs in other.

v1->v2:
   - Fix the comment.

Signed-off-by: oushixiong <oushixi...@kylinos.cn>
---
  drivers/gpu/drm/ast/ast_drv.c  |  22 ++++++
  drivers/gpu/drm/ast/ast_mode.c | 125 ++++++++++++++++++++++++++++++++-
  2 files changed, 146 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c
index 7465c4f0156a..6c1f75174368 100644
--- a/drivers/gpu/drm/ast/ast_drv.c
+++ b/drivers/gpu/drm/ast/ast_drv.c
@@ -28,6 +28,7 @@
#include <linux/module.h>
  #include <linux/pci.h>
+#include <linux/dma-buf.h>
#include <drm/drm_aperture.h>
  #include <drm/drm_atomic_helper.h>
@@ -50,6 +51,23 @@ module_param_named(modeset, ast_modeset, int, 0400);
DEFINE_DRM_GEM_FOPS(ast_fops); +static struct drm_gem_object *ast_gem_prime_import_sg_table(struct drm_device *dev,
+                                       struct dma_buf_attachment *attach,
+                                       struct sg_table *sg)
+{
+       struct drm_gem_vram_object *gbo;
+       struct dma_resv *resv = attach->dmabuf->resv;
+
+       ww_mutex_lock(&resv->lock, NULL);
+       gbo = drm_gem_vram_create(dev, attach->dmabuf->size, 0);
+       ww_mutex_unlock(&resv->lock);
+
+       if (IS_ERR(gbo))
+               return NULL;

Well where do you use the sg_table here?

Christian.

+
+       return &gbo->bo.base;
+}
+
  static const struct drm_driver ast_driver = {
        .driver_features = DRIVER_ATOMIC |
                           DRIVER_GEM |
@@ -63,6 +81,10 @@ static const struct drm_driver ast_driver = {
        .minor = DRIVER_MINOR,
        .patchlevel = DRIVER_PATCHLEVEL,
+ .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
+       .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
+       .gem_prime_import_sg_table = ast_gem_prime_import_sg_table,
+
        DRM_GEM_VRAM_DRIVER
  };
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index 45b56b39ad47..ebe732705e34 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -48,6 +48,8 @@
  #include "ast_drv.h"
  #include "ast_tables.h"
+MODULE_IMPORT_NS(DMA_BUF);
+
  static inline void ast_load_palette_index(struct ast_private *ast,
                                     u8 index, u8 red, u8 green,
                                     u8 blue)
@@ -1535,8 +1537,129 @@ static const struct drm_mode_config_helper_funcs 
ast_mode_config_helper_funcs =
        .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,
  };
+static int ast_handle_damage(struct drm_framebuffer *fb, int x, int y,
+                                       int width, int height)
+{
+       struct drm_gem_vram_object *dst_bo = NULL;
+       void *dst = NULL;
+       int ret = 0, i;
+       unsigned long offset = 0;
+       bool unmap = false;
+       unsigned int bytesPerPixel;
+       struct iosys_map map;
+       struct iosys_map dmabuf_map;
+
+       bytesPerPixel = fb->format->cpp[0];
+
+       if (!fb->obj[0]->import_attach)
+               return -EINVAL;
+
+       if (!fb->obj[0]->import_attach->dmabuf->vmap_ptr.vaddr) {
+               ret = dma_buf_vmap(fb->obj[0]->import_attach->dmabuf, 
&dmabuf_map);
+               if (ret)
+                       return 0;
+       } else
+               dmabuf_map.vaddr = 
fb->obj[0]->import_attach->dmabuf->vmap_ptr.vaddr;
+
+       dst_bo = drm_gem_vram_of_gem(fb->obj[0]);
+
+       ret = drm_gem_vram_pin(dst_bo, 0);
+       if (ret) {
+               DRM_ERROR("ast_bo_pin failed\n");
+               goto error;
+       }
+
+       if (!dst_bo->map.vaddr) {
+               ret = drm_gem_vram_vmap(dst_bo, &map);
+               if (ret) {
+                       DRM_ERROR("failed to vmap fbcon\n");
+                       drm_gem_vram_unpin(dst_bo);
+                       goto error;
+               }
+               unmap = true;
+       }
+       dst = dst_bo->map.vaddr;
+
+       for (i = y; i < y + height; i++) {
+               offset = i * fb->pitches[0] + (x * bytesPerPixel);
+               memcpy_toio(dst + offset, dmabuf_map.vaddr + offset,
+                       width * bytesPerPixel);
+       }
+
+       if (unmap)
+               drm_gem_vram_vunmap(dst_bo, &map);
+
+       drm_gem_vram_unpin(dst_bo);
+error:
+       return 0;
+}
+
+
+static int ast_user_framebuffer_dirty(struct drm_framebuffer *fb,
+                               struct drm_file *file,
+                               unsigned int flags,
+                               unsigned int color,
+                               struct drm_clip_rect *clips,
+                               unsigned int num_clips)
+{
+       int i, ret = 0;
+
+       drm_modeset_lock_all(fb->dev);
+       if (fb->obj[0]->import_attach) {
+               ret = 
dma_buf_begin_cpu_access(fb->obj[0]->import_attach->dmabuf,
+                               DMA_FROM_DEVICE);
+               if (ret)
+                       goto unlock;
+       }
+
+       for (i = 0; i < num_clips; i++) {
+               ret = ast_handle_damage(fb, clips[i].x1, clips[i].y1,
+                               clips[i].x2 - clips[i].x1, clips[i].y2 - 
clips[i].y1);
+               if (ret)
+                       break;
+       }
+
+       if (fb->obj[0]->import_attach) {
+               dma_buf_end_cpu_access(fb->obj[0]->import_attach->dmabuf,
+                               DMA_FROM_DEVICE);
+       }
+
+unlock:
+       drm_modeset_unlock_all(fb->dev);
+
+       return ret;
+}
+
+static void ast_user_framebuffer_destroy(struct drm_framebuffer *fb)
+{
+       struct iosys_map dmabuf_map;
+
+       if (fb->obj[0]->import_attach) {
+               dmabuf_map.vaddr = 
fb->obj[0]->import_attach->dmabuf->vmap_ptr.vaddr;
+               if (dmabuf_map.vaddr)
+                       dma_buf_vunmap(fb->obj[0]->import_attach->dmabuf,
+                                       &dmabuf_map);
+       }
+
+       drm_gem_fb_destroy(fb);
+}
+
+static const struct drm_framebuffer_funcs ast_gem_fb_funcs_dirtyfb = {
+       .destroy        = ast_user_framebuffer_destroy,
+       .create_handle  = drm_gem_fb_create_handle,
+       .dirty          = ast_user_framebuffer_dirty,
+};
+
+static struct drm_framebuffer *
+ast_gem_fb_create_with_dirty(struct drm_device *dev, struct drm_file *file,
+                               const struct drm_mode_fb_cmd2 *mode_cmd)
+{
+       return drm_gem_fb_create_with_funcs(dev, file, mode_cmd,
+                                       &ast_gem_fb_funcs_dirtyfb);
+}
+
  static const struct drm_mode_config_funcs ast_mode_config_funcs = {
-       .fb_create = drm_gem_fb_create,
+       .fb_create = ast_gem_fb_create_with_dirty,
        .mode_valid = drm_vram_helper_mode_valid,
        .atomic_check = drm_atomic_helper_check,
        .atomic_commit = drm_atomic_helper_commit,

Reply via email to