Merge branch '3.2-without-smb2' of git://git.samba.org/sfrench/cifs-2.6
[pandora-kernel.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 DEFINE_MUTEX(exynos_drm_buf_lock);
33
34 static int lowlevel_buffer_allocate(struct drm_device *dev,
35                 struct exynos_drm_buf_entry *entry)
36 {
37         DRM_DEBUG_KMS("%s\n", __FILE__);
38
39         entry->vaddr = dma_alloc_writecombine(dev->dev, entry->size,
40                         (dma_addr_t *)&entry->paddr, GFP_KERNEL);
41         if (!entry->paddr) {
42                 DRM_ERROR("failed to allocate buffer.\n");
43                 return -ENOMEM;
44         }
45
46         DRM_DEBUG_KMS("allocated : vaddr(0x%x), paddr(0x%x), size(0x%x)\n",
47                         (unsigned int)entry->vaddr, entry->paddr, entry->size);
48
49         return 0;
50 }
51
52 static void lowlevel_buffer_deallocate(struct drm_device *dev,
53                 struct exynos_drm_buf_entry *entry)
54 {
55         DRM_DEBUG_KMS("%s.\n", __FILE__);
56
57         if (entry->paddr && entry->vaddr && entry->size)
58                 dma_free_writecombine(dev->dev, entry->size, entry->vaddr,
59                                 entry->paddr);
60         else
61                 DRM_DEBUG_KMS("entry data is null.\n");
62 }
63
64 struct exynos_drm_buf_entry *exynos_drm_buf_create(struct drm_device *dev,
65                 unsigned int size)
66 {
67         struct exynos_drm_buf_entry *entry;
68
69         DRM_DEBUG_KMS("%s.\n", __FILE__);
70
71         entry = kzalloc(sizeof(*entry), GFP_KERNEL);
72         if (!entry) {
73                 DRM_ERROR("failed to allocate exynos_drm_buf_entry.\n");
74                 return ERR_PTR(-ENOMEM);
75         }
76
77         entry->size = size;
78
79         /*
80          * allocate memory region with size and set the memory information
81          * to vaddr and paddr of a entry object.
82          */
83         if (lowlevel_buffer_allocate(dev, entry) < 0) {
84                 kfree(entry);
85                 entry = NULL;
86                 return ERR_PTR(-ENOMEM);
87         }
88
89         return entry;
90 }
91
92 void exynos_drm_buf_destroy(struct drm_device *dev,
93                 struct exynos_drm_buf_entry *entry)
94 {
95         DRM_DEBUG_KMS("%s.\n", __FILE__);
96
97         if (!entry) {
98                 DRM_DEBUG_KMS("entry is null.\n");
99                 return;
100         }
101
102         lowlevel_buffer_deallocate(dev, entry);
103
104         kfree(entry);
105         entry = NULL;
106 }
107
108 MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
109 MODULE_DESCRIPTION("Samsung SoC DRM Buffer Management Module");
110 MODULE_LICENSE("GPL");