Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
exynos_drm_buf.c
Go to the documentation of this file.
1 /* exynos_drm_buf.c
2  *
3  * Copyright (c) 2011 Samsung Electronics Co., Ltd.
4  * Author: Inki Dae <[email protected]>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice (including the next
14  * paragraph) shall be included in all copies or substantial portions of the
15  * Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23  * OTHER DEALINGS IN THE SOFTWARE.
24  */
25 
26 #include <drm/drmP.h>
27 #include <drm/exynos_drm.h>
28 
29 #include "exynos_drm_drv.h"
30 #include "exynos_drm_gem.h"
31 #include "exynos_drm_buf.h"
32 
33 static int lowlevel_buffer_allocate(struct drm_device *dev,
34  unsigned int flags, struct exynos_drm_gem_buf *buf)
35 {
37  unsigned int npages, i = 0;
38  struct scatterlist *sgl;
39  int ret = 0;
40 
41  DRM_DEBUG_KMS("%s\n", __FILE__);
42 
43  if (IS_NONCONTIG_BUFFER(flags)) {
44  DRM_DEBUG_KMS("not support allocation type.\n");
45  return -EINVAL;
46  }
47 
48  if (buf->dma_addr) {
49  DRM_DEBUG_KMS("already allocated.\n");
50  return 0;
51  }
52 
53  if (buf->size >= SZ_1M) {
54  npages = buf->size >> SECTION_SHIFT;
55  buf->page_size = SECTION_SIZE;
56  } else if (buf->size >= SZ_64K) {
57  npages = buf->size >> 16;
58  buf->page_size = SZ_64K;
59  } else {
60  npages = buf->size >> PAGE_SHIFT;
61  buf->page_size = PAGE_SIZE;
62  }
63 
64  buf->sgt = kzalloc(sizeof(struct sg_table), GFP_KERNEL);
65  if (!buf->sgt) {
66  DRM_ERROR("failed to allocate sg table.\n");
67  return -ENOMEM;
68  }
69 
70  ret = sg_alloc_table(buf->sgt, npages, GFP_KERNEL);
71  if (ret < 0) {
72  DRM_ERROR("failed to initialize sg table.\n");
73  kfree(buf->sgt);
74  buf->sgt = NULL;
75  return -ENOMEM;
76  }
77 
78  buf->kvaddr = dma_alloc_writecombine(dev->dev, buf->size,
79  &buf->dma_addr, GFP_KERNEL);
80  if (!buf->kvaddr) {
81  DRM_ERROR("failed to allocate buffer.\n");
82  ret = -ENOMEM;
83  goto err1;
84  }
85 
86  buf->pages = kzalloc(sizeof(struct page) * npages, GFP_KERNEL);
87  if (!buf->pages) {
88  DRM_ERROR("failed to allocate pages.\n");
89  ret = -ENOMEM;
90  goto err2;
91  }
92 
93  sgl = buf->sgt->sgl;
94  start_addr = buf->dma_addr;
95 
96  while (i < npages) {
97  buf->pages[i] = phys_to_page(start_addr);
98  sg_set_page(sgl, buf->pages[i], buf->page_size, 0);
100  start_addr += buf->page_size;
101  sgl = sg_next(sgl);
102  i++;
103  }
104 
105  DRM_DEBUG_KMS("vaddr(0x%lx), dma_addr(0x%lx), size(0x%lx)\n",
106  (unsigned long)buf->kvaddr,
107  (unsigned long)buf->dma_addr,
108  buf->size);
109 
110  return ret;
111 err2:
112  dma_free_writecombine(dev->dev, buf->size, buf->kvaddr,
113  (dma_addr_t)buf->dma_addr);
114  buf->dma_addr = (dma_addr_t)NULL;
115 err1:
116  sg_free_table(buf->sgt);
117  kfree(buf->sgt);
118  buf->sgt = NULL;
119 
120  return ret;
121 }
122 
123 static void lowlevel_buffer_deallocate(struct drm_device *dev,
124  unsigned int flags, struct exynos_drm_gem_buf *buf)
125 {
126  DRM_DEBUG_KMS("%s.\n", __FILE__);
127 
128  /*
129  * release only physically continuous memory and
130  * non-continuous memory would be released by exynos
131  * gem framework.
132  */
133  if (IS_NONCONTIG_BUFFER(flags)) {
134  DRM_DEBUG_KMS("not support allocation type.\n");
135  return;
136  }
137 
138  if (!buf->dma_addr) {
139  DRM_DEBUG_KMS("dma_addr is invalid.\n");
140  return;
141  }
142 
143  DRM_DEBUG_KMS("vaddr(0x%lx), dma_addr(0x%lx), size(0x%lx)\n",
144  (unsigned long)buf->kvaddr,
145  (unsigned long)buf->dma_addr,
146  buf->size);
147 
148  sg_free_table(buf->sgt);
149 
150  kfree(buf->sgt);
151  buf->sgt = NULL;
152 
153  kfree(buf->pages);
154  buf->pages = NULL;
155 
156  dma_free_writecombine(dev->dev, buf->size, buf->kvaddr,
157  (dma_addr_t)buf->dma_addr);
158  buf->dma_addr = (dma_addr_t)NULL;
159 }
160 
162  unsigned int size)
163 {
164  struct exynos_drm_gem_buf *buffer;
165 
166  DRM_DEBUG_KMS("%s.\n", __FILE__);
167  DRM_DEBUG_KMS("desired size = 0x%x\n", size);
168 
169  buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
170  if (!buffer) {
171  DRM_ERROR("failed to allocate exynos_drm_gem_buf.\n");
172  return NULL;
173  }
174 
175  buffer->size = size;
176  return buffer;
177 }
178 
180  struct exynos_drm_gem_buf *buffer)
181 {
182  DRM_DEBUG_KMS("%s.\n", __FILE__);
183 
184  if (!buffer) {
185  DRM_DEBUG_KMS("buffer is null.\n");
186  return;
187  }
188 
189  kfree(buffer);
190  buffer = NULL;
191 }
192 
194  struct exynos_drm_gem_buf *buf, unsigned int flags)
195 {
196 
197  /*
198  * allocate memory region and set the memory information
199  * to vaddr and dma_addr of a buffer object.
200  */
201  if (lowlevel_buffer_allocate(dev, flags, buf) < 0)
202  return -ENOMEM;
203 
204  return 0;
205 }
206 
208  unsigned int flags, struct exynos_drm_gem_buf *buffer)
209 {
210 
211  lowlevel_buffer_deallocate(dev, flags, buffer);
212 }