162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2011 Texas Instruments Incorporated - https://www.ti.com/ 462306a36Sopenharmony_ci * Author: Rob Clark <rob.clark@linaro.org> 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <linux/dma-buf.h> 862306a36Sopenharmony_ci#include <linux/highmem.h> 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <drm/drm_prime.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include "omap_drv.h" 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ciMODULE_IMPORT_NS(DMA_BUF); 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci/* ----------------------------------------------------------------------------- 1762306a36Sopenharmony_ci * DMABUF Export 1862306a36Sopenharmony_ci */ 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_cistatic struct sg_table *omap_gem_map_dma_buf( 2162306a36Sopenharmony_ci struct dma_buf_attachment *attachment, 2262306a36Sopenharmony_ci enum dma_data_direction dir) 2362306a36Sopenharmony_ci{ 2462306a36Sopenharmony_ci struct drm_gem_object *obj = attachment->dmabuf->priv; 2562306a36Sopenharmony_ci struct sg_table *sg; 2662306a36Sopenharmony_ci sg = omap_gem_get_sg(obj, dir); 2762306a36Sopenharmony_ci if (IS_ERR(sg)) 2862306a36Sopenharmony_ci return sg; 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci return sg; 3162306a36Sopenharmony_ci} 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_cistatic void omap_gem_unmap_dma_buf(struct dma_buf_attachment *attachment, 3462306a36Sopenharmony_ci struct sg_table *sg, enum dma_data_direction dir) 3562306a36Sopenharmony_ci{ 3662306a36Sopenharmony_ci struct drm_gem_object *obj = attachment->dmabuf->priv; 3762306a36Sopenharmony_ci omap_gem_put_sg(obj, sg); 3862306a36Sopenharmony_ci} 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_cistatic int omap_gem_dmabuf_begin_cpu_access(struct dma_buf *buffer, 4162306a36Sopenharmony_ci enum dma_data_direction dir) 4262306a36Sopenharmony_ci{ 4362306a36Sopenharmony_ci struct drm_gem_object *obj = buffer->priv; 4462306a36Sopenharmony_ci struct page **pages; 4562306a36Sopenharmony_ci if (omap_gem_flags(obj) & OMAP_BO_TILED_MASK) { 4662306a36Sopenharmony_ci /* TODO we would need to pin at least part of the buffer to 4762306a36Sopenharmony_ci * get de-tiled view. For now just reject it. 4862306a36Sopenharmony_ci */ 4962306a36Sopenharmony_ci return -ENOMEM; 5062306a36Sopenharmony_ci } 5162306a36Sopenharmony_ci /* make sure we have the pages: */ 5262306a36Sopenharmony_ci return omap_gem_get_pages(obj, &pages, true); 5362306a36Sopenharmony_ci} 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_cistatic int omap_gem_dmabuf_end_cpu_access(struct dma_buf *buffer, 5662306a36Sopenharmony_ci enum dma_data_direction dir) 5762306a36Sopenharmony_ci{ 5862306a36Sopenharmony_ci struct drm_gem_object *obj = buffer->priv; 5962306a36Sopenharmony_ci omap_gem_put_pages(obj); 6062306a36Sopenharmony_ci return 0; 6162306a36Sopenharmony_ci} 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_cistatic int omap_gem_dmabuf_mmap(struct dma_buf *buffer, 6462306a36Sopenharmony_ci struct vm_area_struct *vma) 6562306a36Sopenharmony_ci{ 6662306a36Sopenharmony_ci struct drm_gem_object *obj = buffer->priv; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci return drm_gem_mmap_obj(obj, omap_gem_mmap_size(obj), vma); 6962306a36Sopenharmony_ci} 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_cistatic const struct dma_buf_ops omap_dmabuf_ops = { 7262306a36Sopenharmony_ci .map_dma_buf = omap_gem_map_dma_buf, 7362306a36Sopenharmony_ci .unmap_dma_buf = omap_gem_unmap_dma_buf, 7462306a36Sopenharmony_ci .release = drm_gem_dmabuf_release, 7562306a36Sopenharmony_ci .begin_cpu_access = omap_gem_dmabuf_begin_cpu_access, 7662306a36Sopenharmony_ci .end_cpu_access = omap_gem_dmabuf_end_cpu_access, 7762306a36Sopenharmony_ci .mmap = omap_gem_dmabuf_mmap, 7862306a36Sopenharmony_ci}; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_cistruct dma_buf *omap_gem_prime_export(struct drm_gem_object *obj, int flags) 8162306a36Sopenharmony_ci{ 8262306a36Sopenharmony_ci DEFINE_DMA_BUF_EXPORT_INFO(exp_info); 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci exp_info.ops = &omap_dmabuf_ops; 8562306a36Sopenharmony_ci exp_info.size = omap_gem_mmap_size(obj); 8662306a36Sopenharmony_ci exp_info.flags = flags; 8762306a36Sopenharmony_ci exp_info.priv = obj; 8862306a36Sopenharmony_ci exp_info.resv = obj->resv; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci return drm_gem_dmabuf_export(obj->dev, &exp_info); 9162306a36Sopenharmony_ci} 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci/* ----------------------------------------------------------------------------- 9462306a36Sopenharmony_ci * DMABUF Import 9562306a36Sopenharmony_ci */ 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_cistruct drm_gem_object *omap_gem_prime_import(struct drm_device *dev, 9862306a36Sopenharmony_ci struct dma_buf *dma_buf) 9962306a36Sopenharmony_ci{ 10062306a36Sopenharmony_ci struct dma_buf_attachment *attach; 10162306a36Sopenharmony_ci struct drm_gem_object *obj; 10262306a36Sopenharmony_ci struct sg_table *sgt; 10362306a36Sopenharmony_ci int ret; 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci if (dma_buf->ops == &omap_dmabuf_ops) { 10662306a36Sopenharmony_ci obj = dma_buf->priv; 10762306a36Sopenharmony_ci if (obj->dev == dev) { 10862306a36Sopenharmony_ci /* 10962306a36Sopenharmony_ci * Importing dmabuf exported from out own gem increases 11062306a36Sopenharmony_ci * refcount on gem itself instead of f_count of dmabuf. 11162306a36Sopenharmony_ci */ 11262306a36Sopenharmony_ci drm_gem_object_get(obj); 11362306a36Sopenharmony_ci return obj; 11462306a36Sopenharmony_ci } 11562306a36Sopenharmony_ci } 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci attach = dma_buf_attach(dma_buf, dev->dev); 11862306a36Sopenharmony_ci if (IS_ERR(attach)) 11962306a36Sopenharmony_ci return ERR_CAST(attach); 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci get_dma_buf(dma_buf); 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci sgt = dma_buf_map_attachment_unlocked(attach, DMA_TO_DEVICE); 12462306a36Sopenharmony_ci if (IS_ERR(sgt)) { 12562306a36Sopenharmony_ci ret = PTR_ERR(sgt); 12662306a36Sopenharmony_ci goto fail_detach; 12762306a36Sopenharmony_ci } 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci obj = omap_gem_new_dmabuf(dev, dma_buf->size, sgt); 13062306a36Sopenharmony_ci if (IS_ERR(obj)) { 13162306a36Sopenharmony_ci ret = PTR_ERR(obj); 13262306a36Sopenharmony_ci goto fail_unmap; 13362306a36Sopenharmony_ci } 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci obj->import_attach = attach; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci return obj; 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_cifail_unmap: 14062306a36Sopenharmony_ci dma_buf_unmap_attachment_unlocked(attach, sgt, DMA_TO_DEVICE); 14162306a36Sopenharmony_cifail_detach: 14262306a36Sopenharmony_ci dma_buf_detach(dma_buf, attach); 14362306a36Sopenharmony_ci dma_buf_put(dma_buf); 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci return ERR_PTR(ret); 14662306a36Sopenharmony_ci} 147