3 * Copyright (C) ROCKCHIP, Inc.
4 * Author:yzq<yzq@rock-chips.com>
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
16 #include <drm/rockchip_drm.h>
18 #include "rockchip_drm_drv.h"
19 #include "rockchip_drm_gem.h"
20 #include "rockchip_drm_buf.h"
21 #include "rockchip_drm_iommu.h"
23 static int lowlevel_buffer_allocate(struct drm_device *dev,
24 unsigned int flags, struct rockchip_drm_gem_buf *buf)
28 unsigned int nr_pages;
30 DRM_DEBUG_KMS("%s\n", __FILE__);
33 DRM_DEBUG_KMS("already allocated.\n");
37 init_dma_attrs(&buf->dma_attrs);
40 * if ROCKCHIP_BO_CONTIG, fully physically contiguous memory
41 * region will be allocated else physically contiguous
44 if (!(flags & ROCKCHIP_BO_NONCONTIG))
45 dma_set_attr(DMA_ATTR_FORCE_CONTIGUOUS, &buf->dma_attrs);
48 * if ROCKCHIP_BO_WC or ROCKCHIP_BO_NONCACHABLE, writecombine mapping
49 * else cachable mapping.
51 if (flags & ROCKCHIP_BO_WC || !(flags & ROCKCHIP_BO_CACHABLE))
52 attr = DMA_ATTR_WRITE_COMBINE;
54 attr = DMA_ATTR_NON_CONSISTENT;
56 dma_set_attr(attr, &buf->dma_attrs);
57 dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &buf->dma_attrs);
59 nr_pages = buf->size >> PAGE_SHIFT;
61 if (!is_drm_iommu_supported(dev)) {
62 dma_addr_t start_addr;
65 buf->pages = kzalloc(sizeof(struct page) * nr_pages,
68 DRM_ERROR("failed to allocate pages.\n");
72 buf->kvaddr = dma_alloc_attrs(dev->dev, buf->size,
73 &buf->dma_addr, GFP_KERNEL,
76 DRM_ERROR("failed to allocate buffer.\n");
81 start_addr = buf->dma_addr;
82 while (i < nr_pages) {
83 buf->pages[i] = phys_to_page(start_addr);
84 start_addr += PAGE_SIZE;
89 buf->pages = dma_alloc_attrs(dev->dev, buf->size,
90 &buf->dma_addr, GFP_KERNEL,
93 DRM_ERROR("failed to allocate buffer.\n");
98 buf->sgt = drm_prime_pages_to_sg(buf->pages, nr_pages);
100 DRM_ERROR("failed to get sg table.\n");
105 DRM_DEBUG_KMS("dma_addr(0x%lx), size(0x%lx)\n",
106 (unsigned long)buf->dma_addr,
112 dma_free_attrs(dev->dev, buf->size, buf->pages,
113 (dma_addr_t)buf->dma_addr, &buf->dma_attrs);
114 buf->dma_addr = (dma_addr_t)NULL;
116 if (!is_drm_iommu_supported(dev))
122 static void lowlevel_buffer_deallocate(struct drm_device *dev,
123 unsigned int flags, struct rockchip_drm_gem_buf *buf)
125 DRM_DEBUG_KMS("%s.\n", __FILE__);
127 if (!buf->dma_addr) {
128 DRM_DEBUG_KMS("dma_addr is invalid.\n");
132 DRM_DEBUG_KMS("dma_addr(0x%lx), size(0x%lx)\n",
133 (unsigned long)buf->dma_addr,
136 sg_free_table(buf->sgt);
141 if (!is_drm_iommu_supported(dev)) {
142 dma_free_attrs(dev->dev, buf->size, buf->kvaddr,
143 (dma_addr_t)buf->dma_addr, &buf->dma_attrs);
146 dma_free_attrs(dev->dev, buf->size, buf->pages,
147 (dma_addr_t)buf->dma_addr, &buf->dma_attrs);
149 buf->dma_addr = (dma_addr_t)NULL;
152 struct rockchip_drm_gem_buf *rockchip_drm_init_buf(struct drm_device *dev,
155 struct rockchip_drm_gem_buf *buffer;
157 DRM_DEBUG_KMS("%s.\n", __FILE__);
158 DRM_DEBUG_KMS("desired size = 0x%x\n", size);
160 buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
162 DRM_ERROR("failed to allocate rockchip_drm_gem_buf.\n");
170 void rockchip_drm_fini_buf(struct drm_device *dev,
171 struct rockchip_drm_gem_buf *buffer)
173 DRM_DEBUG_KMS("%s.\n", __FILE__);
176 DRM_DEBUG_KMS("buffer is null.\n");
184 int rockchip_drm_alloc_buf(struct drm_device *dev,
185 struct rockchip_drm_gem_buf *buf, unsigned int flags)
189 * allocate memory region and set the memory information
190 * to vaddr and dma_addr of a buffer object.
192 if (lowlevel_buffer_allocate(dev, flags, buf) < 0)
198 void rockchip_drm_free_buf(struct drm_device *dev,
199 unsigned int flags, struct rockchip_drm_gem_buf *buffer)
202 lowlevel_buffer_deallocate(dev, flags, buffer);