1/*
2 *  ion.c
3 *
4 * Memory Allocator functions for ion
5 *
6 *   Copyright 2011 Google, Inc
7 *
8 *  Licensed under the Apache License, Version 2.0 (the "License");
9 *  you may not use this file except in compliance with the License.
10 *  You may obtain a copy of the License at
11 *
12 *      http://www.apache.org/licenses/LICENSE-2.0
13 *
14 *  Unless required by applicable law or agreed to in writing, software
15 *  distributed under the License is distributed on an "AS IS" BASIS,
16 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 *  See the License for the specific language governing permissions and
18 *  limitations under the License.
19 */
20#define LOG_TAG "ion"
21
22#include <cutils/log.h>
23#include <errno.h>
24#include <fcntl.h>
25#include <stdio.h>
26#include <sys/ioctl.h>
27#include <sys/mman.h>
28#include <sys/types.h>
29
30#include <linux/ion.h>
31#include <ion/ion.h>
32
33int ion_open()
34{
35        int fd = open("/dev/ion", O_RDWR);
36        if (fd < 0)
37                ALOGE("open /dev/ion failed!\n");
38        return fd;
39}
40
41int ion_close(int fd)
42{
43        return close(fd);
44}
45
46static int ion_ioctl(int fd, int req, void *arg)
47{
48        int ret = ioctl(fd, req, arg);
49        if (ret < 0) {
50                ALOGE("ioctl %d failed with code %d: %s\n", req,
51                       ret, strerror(errno));
52                return -errno;
53        }
54        return ret;
55}
56
57int ion_alloc(int fd, size_t len, size_t align,
58	      unsigned int flags, struct ion_handle **handle)
59{
60        int ret;
61        struct ion_allocation_data data = {
62                .len = len,
63                .align = align,
64                .flags = flags,
65        };
66
67        ret = ion_ioctl(fd, ION_IOC_ALLOC, &data);
68        if (ret < 0)
69                return ret;
70        *handle = data.handle;
71        return ret;
72}
73
74int ion_alloc_tiler(int fd, size_t w, size_t h, int fmt, unsigned int flags,
75            struct ion_handle **handle, size_t *stride)
76{
77        int ret;
78        struct omap_ion_tiler_alloc_data alloc_data = {
79                .w = w,
80                .h = h,
81                .fmt = fmt,
82                .flags = flags,
83                .out_align = PAGE_SIZE,
84                .token = 0,
85        };
86
87        struct ion_custom_data custom_data = {
88                .cmd = OMAP_ION_TILER_ALLOC,
89                .arg = (unsigned long)(&alloc_data),
90        };
91
92        ret = ion_ioctl(fd, ION_IOC_CUSTOM, &custom_data);
93        if (ret < 0)
94                return ret;
95        *stride = alloc_data.stride;
96        *handle = alloc_data.handle;
97        return ret;
98}
99
100int ion_free(int fd, struct ion_handle *handle)
101{
102        struct ion_handle_data data = {
103                .handle = handle,
104        };
105        return ion_ioctl(fd, ION_IOC_FREE, &data);
106}
107
108int ion_map(int fd, struct ion_handle *handle, size_t length, int prot,
109            int flags, off_t offset, unsigned char **ptr, int *map_fd)
110{
111        struct ion_fd_data data = {
112                .handle = handle,
113        };
114        int ret = ion_ioctl(fd, ION_IOC_MAP, &data);
115        if (ret < 0)
116                return ret;
117        *map_fd = data.fd;
118        if (*map_fd < 0) {
119                ALOGE("map ioctl returned negative fd\n");
120                return -EINVAL;
121        }
122        *ptr = mmap(NULL, length, prot, flags, *map_fd, offset);
123        if (*ptr == MAP_FAILED) {
124                ALOGE("mmap failed: %s\n", strerror(errno));
125                return -errno;
126        }
127        return ret;
128}
129
130int ion_share(int fd, struct ion_handle *handle, int *share_fd)
131{
132        int map_fd;
133        struct ion_fd_data data = {
134                .handle = handle,
135        };
136        int ret = ion_ioctl(fd, ION_IOC_SHARE, &data);
137        if (ret < 0)
138                return ret;
139        *share_fd = data.fd;
140        if (*share_fd < 0) {
141                ALOGE("map ioctl returned negative fd\n");
142                return -EINVAL;
143        }
144        return ret;
145}
146
147int ion_import(int fd, int share_fd, struct ion_handle **handle)
148{
149        struct ion_fd_data data = {
150                .fd = share_fd,
151        };
152        int ret = ion_ioctl(fd, ION_IOC_IMPORT, &data);
153        if (ret < 0)
154                return ret;
155        *handle = data.handle;
156        return ret;
157}
158
159#if 0
160int ion_sync_fd(int fd, int handle_fd)
161{
162	struct ion_fd_data data = {
163		.fd = handle_fd,
164	};
165	return ion_ioctl(fd, ION_IOC_SYNC, &data);
166}
167#endif
168
169int ion_map_cacheable(int fd, struct ion_handle *handle, size_t length, int prot,
170            int flags, off_t offset, unsigned char **ptr, int *map_fd)
171{
172        struct ion_fd_data data = {
173                .handle = handle,
174                .cacheable = 1,
175        };
176        int ret = ion_ioctl(fd, ION_IOC_MAP, &data);
177        if (ret < 0)
178                return ret;
179        *map_fd = data.fd;
180        if (*map_fd < 0) {
181                ALOGE("map ioctl returned negative fd\n");
182                return -EINVAL;
183        }
184        *ptr = mmap(NULL, length, prot, flags, *map_fd, offset);
185        if (*ptr == MAP_FAILED) {
186                ALOGE("mmap failed: %s\n", strerror(errno));
187                return -errno;
188        }
189        return ret;
190}
191
192int ion_flush_cached(int fd, struct ion_handle *handle, size_t length,
193            unsigned char *ptr)
194{
195        struct ion_cached_user_buf_data data = {
196                .handle = handle,
197                .vaddr = (unsigned long)ptr,
198                .size = length,
199        };
200        return ion_ioctl(fd, ION_IOC_FLUSH_CACHED, &data);
201}
202
203int ion_inval_cached(int fd, struct ion_handle *handle, size_t length,
204            unsigned char *ptr)
205{
206        struct ion_cached_user_buf_data data = {
207                .handle = handle,
208                .vaddr = (unsigned long)ptr,
209                .size = length,
210        };
211        return ion_ioctl(fd, ION_IOC_INVAL_CACHED, &data);
212}
213