303189c78cf1fe0954fae71fbb56d77e84dfdeb4
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / drm / exynos / exynos_drm_buf.c
1 /* exynos_drm_buf.c
2  *
3  * Copyright (c) 2011 Samsung Electronics Co., Ltd.
4  * Author: Inki Dae <inki.dae@samsung.com>
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 "drmP.h"
27 #include "drm.h"
28
29 #include "exynos_drm_drv.h"
30 #include "exynos_drm_buf.h"
31
32 static int lowlevel_buffer_allocate(struct drm_device *dev,
33                 struct exynos_drm_buf_entry *entry)
34 {
35         DRM_DEBUG_KMS("%s\n", __FILE__);
36
37         entry->vaddr = dma_alloc_writecombine(dev->dev, entry->size,
38                         (dma_addr_t *)&entry->paddr, GFP_KERNEL);
39         if (!entry->paddr) {
40                 DRM_ERROR("failed to allocate buffer.\n");
41                 return -ENOMEM;
42         }
43
44         DRM_DEBUG_KMS("allocated : vaddr(0x%x), paddr(0x%x), size(0x%x)\n",
45                         (unsigned int)entry->vaddr, entry->paddr, entry->size);
46
47         return 0;
48 }
49
50 static void lowlevel_buffer_deallocate(struct drm_device *dev,
51                 struct exynos_drm_buf_entry *entry)
52 {
53         DRM_DEBUG_KMS("%s.\n", __FILE__);
54
55         if (entry->paddr && entry->vaddr && entry->size)
56                 dma_free_writecombine(dev->dev, entry->size, entry->vaddr,
57                                 entry->paddr);
58         else
59                 DRM_DEBUG_KMS("entry data is null.\n");
60 }
61
62 struct exynos_drm_buf_entry *exynos_drm_buf_create(struct drm_device *dev,
63                 unsigned int size)
64 {
65         struct exynos_drm_buf_entry *entry;
66
67         DRM_DEBUG_KMS("%s.\n", __FILE__);
68
69         entry = kzalloc(sizeof(*entry), GFP_KERNEL);
70         if (!entry) {
71                 DRM_ERROR("failed to allocate exynos_drm_buf_entry.\n");
72                 return ERR_PTR(-ENOMEM);
73         }
74
75         entry->size = size;
76
77         /*
78          * allocate memory region with size and set the memory information
79          * to vaddr and paddr of a entry object.
80          */
81         if (lowlevel_buffer_allocate(dev, entry) < 0) {
82                 kfree(entry);
83                 entry = NULL;
84                 return ERR_PTR(-ENOMEM);
85         }
86
87         return entry;
88 }
89
90 void exynos_drm_buf_destroy(struct drm_device *dev,
91                 struct exynos_drm_buf_entry *entry)
92 {
93         DRM_DEBUG_KMS("%s.\n", __FILE__);
94
95         if (!entry) {
96                 DRM_DEBUG_KMS("entry is null.\n");
97                 return;
98         }
99
100         lowlevel_buffer_deallocate(dev, entry);
101
102         kfree(entry);
103         entry = NULL;
104 }
105
106 MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
107 MODULE_DESCRIPTION("Samsung SoC DRM Buffer Management Module");
108 MODULE_LICENSE("GPL");