1 /*
2 Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
3
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are
6 met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above
10 copyright notice, this list of conditions and the following
11 disclaimer in the documentation and/or other materials provided
12 with the distribution.
13 * Neither the name of The Linux Foundation nor the names of its
14 contributors may be used to endorse or promote products derived
15 from this software without specific prior written permission.
16
17 THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #include <sys/mman.h>
31 #include <fcntl.h>
32 #include <stdio.h>
33 #include <unistd.h>
34 #include <stdlib.h>
35 #include <ctype.h>
36 #include <errno.h>
37 #include <string.h>
38 #include "mm_camera_dbg.h"
39 #include <time.h>
40 #include "mm_camera_interface.h"
41 #include <linux/ion.h>
42
43 #define MM_CAMERA_PROFILE 1
44
45 struct file;
46 struct inode;
47 struct vm_area_struct;
48
49 /*===========================================================================
50 * FUNCTION - do_mmap -
51 *
52 * DESCRIPTION: retured virtual addresss
53 *==========================================================================*/
mm_camera_do_mmap(uint32_t size,int * pmemFd)54 uint8_t *mm_camera_do_mmap(uint32_t size, int *pmemFd)
55 {
56 void *ret; /* returned virtual address */
57 int pmem_fd = open("/dev/pmem_adsp", O_RDWR|O_SYNC);
58
59 if (pmem_fd <= 0) {
60 CDBG("do_mmap: Open device /dev/pmem_adsp failed!\n");
61 return NULL;
62 }
63 /* to make it page size aligned */
64 size = (size + 4095) & (~4095);
65 ret = mmap(NULL,
66 size,
67 PROT_READ | PROT_WRITE,
68 MAP_SHARED,
69 pmem_fd,
70 0);
71 if (ret == MAP_FAILED) {
72 CDBG("do_mmap: pmem mmap() failed: %s (%d)\n", strerror(errno), errno);
73 close(pmem_fd);
74 return NULL;
75 }
76 CDBG("do_mmap: pmem mmap fd %d ptr %p len %u\n", pmem_fd, ret, size);
77 *pmemFd = pmem_fd;
78 return(uint8_t *)ret;
79 }
80
81 /*===========================================================================
82 * FUNCTION - do_munmap -
83 *
84 * DESCRIPTION:
85 *==========================================================================*/
mm_camera_do_munmap(int pmem_fd,void * addr,size_t size)86 int mm_camera_do_munmap(int pmem_fd, void *addr, size_t size)
87 {
88 int rc;
89
90 if (pmem_fd <= 0) {
91 CDBG("%s:invalid fd=%d\n", __func__, pmem_fd);
92 return -1;
93 }
94 size = (size + 4095) & (~4095);
95 CDBG("munmapped size = %d, virt_addr = 0x%p\n",
96 size, addr);
97 rc = (munmap(addr, size));
98 close(pmem_fd);
99 CDBG("do_mmap: pmem munmap fd %d ptr %p len %u rc %d\n", pmem_fd, addr,
100 size, rc);
101 return rc;
102 }
103
104 #ifdef USE_ION
mm_camera_do_mmap_ion(int ion_fd,struct ion_allocation_data * alloc,struct ion_fd_data * ion_info_fd,int * mapFd)105 uint8_t *mm_camera_do_mmap_ion(int ion_fd, struct ion_allocation_data *alloc,
106 struct ion_fd_data *ion_info_fd, int *mapFd)
107 {
108 void *ret; /* returned virtual address */
109 int rc = 0;
110 struct ion_handle_data handle_data;
111
112 /* to make it page size aligned */
113 alloc->len = (alloc->len + 4095) & (~4095);
114
115 rc = ioctl(ion_fd, ION_IOC_ALLOC, alloc);
116 if (rc < 0) {
117 CDBG_ERROR("ION allocation failed\n");
118 goto ION_ALLOC_FAILED;
119 }
120
121 ion_info_fd->handle = alloc->handle;
122 rc = ioctl(ion_fd, ION_IOC_SHARE, ion_info_fd);
123 if (rc < 0) {
124 CDBG_ERROR("ION map failed %s\n", strerror(errno));
125 goto ION_MAP_FAILED;
126 }
127 *mapFd = ion_info_fd->fd;
128 /*ret = mmap(NULL,
129 alloc->len,
130 PROT_READ | PROT_WRITE,
131 MAP_SHARED,
132 *mapFd,
133 0);
134
135 if (ret == MAP_FAILED) {
136 CDBG_ERROR("ION_MMAP_FAILED: %s (%d)\n", strerror(errno), errno);
137 goto ION_MAP_FAILED;
138 }*/
139
140 return ret;
141
142 ION_MAP_FAILED:
143 handle_data.handle = ion_info_fd->handle;
144 ioctl(ion_fd, ION_IOC_FREE, &handle_data);
145 ION_ALLOC_FAILED:
146 return NULL;
147 }
148
mm_camera_do_munmap_ion(int ion_fd,struct ion_fd_data * ion_info_fd,void * addr,size_t size)149 int mm_camera_do_munmap_ion (int ion_fd, struct ion_fd_data *ion_info_fd,
150 void *addr, size_t size)
151 {
152 int rc = 0;
153 rc = munmap(addr, size);
154 close(ion_info_fd->fd);
155
156 struct ion_handle_data handle_data;
157 handle_data.handle = ion_info_fd->handle;
158 ioctl(ion_fd, ION_IOC_FREE, &handle_data);
159 return rc;
160 }
161 #endif
162
163 /*============================================================
164 FUNCTION mm_camera_dump_image
165 DESCRIPTION:
166 ==============================================================*/
mm_camera_dump_image(void * addr,uint32_t size,char * filename)167 int mm_camera_dump_image(void *addr, uint32_t size, char *filename)
168 {
169 int file_fd = open(filename, O_RDWR | O_CREAT, 0777);
170
171 if (file_fd < 0) {
172 CDBG_HIGH("%s: cannot open file\n", __func__);
173 return -1;
174 } else
175 write(file_fd, addr, size);
176 close(file_fd);
177 CDBG("%s: %s, size=%d\n", __func__, filename, size);
178 return 0;
179 }
180
mm_camera_get_msm_frame_len(cam_format_t fmt_type,camera_mode_t mode,int width,int height,int image_type,uint8_t * num_planes,uint32_t plane[])181 uint32_t mm_camera_get_msm_frame_len(cam_format_t fmt_type,
182 camera_mode_t mode,
183 int width,
184 int height,
185 int image_type,
186 uint8_t *num_planes,
187 uint32_t plane[])
188 {
189 uint32_t size;
190 *num_planes = 0;
191 int local_height;
192
193 switch (fmt_type) {
194 case CAMERA_YUV_420_NV12:
195 case CAMERA_YUV_420_NV21:
196 *num_planes = 2;
197 if(CAMERA_MODE_3D == mode) {
198 size = (uint32_t)(PAD_TO_2K(width*height)*3/2);
199 plane[0] = PAD_TO_WORD(width*height);
200 } else {
201 if (image_type == OUTPUT_TYPE_V) {
202 plane[0] = PAD_TO_2K(width * height);
203 plane[1] = PAD_TO_2K(width * height/2);
204 } else if (image_type == OUTPUT_TYPE_P) {
205 plane[0] = PAD_TO_WORD(width * height);
206 plane[1] = PAD_TO_WORD(width * height/2);
207 } else {
208 plane[0] = PAD_TO_WORD(width * CEILING16(height));
209 plane[1] = PAD_TO_WORD(width * CEILING16(height)/2);
210 }
211 size = plane[0] + plane[1];
212 }
213 break;
214 case CAMERA_BAYER_SBGGR10:
215 *num_planes = 1;
216 plane[0] = PAD_TO_WORD(width * height);
217 size = plane[0];
218 break;
219 case CAMERA_YUV_422_NV16:
220 case CAMERA_YUV_422_NV61:
221 if( image_type == OUTPUT_TYPE_S || image_type == OUTPUT_TYPE_V) {
222 local_height = CEILING16(height);
223 } else {
224 local_height = height;
225 }
226 *num_planes = 2;
227 plane[0] = PAD_TO_WORD(width * height);
228 plane[1] = PAD_TO_WORD(width * height);
229 size = plane[0] + plane[1];
230 break;
231 default:
232 CDBG("%s: format %d not supported.\n",
233 __func__, fmt_type);
234 size = 0;
235 }
236 CDBG("%s:fmt=%d,image_type=%d,width=%d,height=%d,frame_len=%d\n",
237 __func__, fmt_type, image_type, width, height, size);
238 return size;
239 }
240
mm_camera_util_profile(const char * str)241 void mm_camera_util_profile(const char *str)
242 {
243 #if (MM_CAMERA_PROFILE)
244 struct timespec cur_time;
245
246 clock_gettime(CLOCK_REALTIME, &cur_time);
247 CDBG_HIGH("PROFILE %s: %ld.%09ld\n", str,
248 cur_time.tv_sec, cur_time.tv_nsec);
249 #endif
250 }
251
252 /*===========================================================================
253 * FUNCTION - mm_camera_do_mmap_ion -
254 *
255 * DESCRIPTION:
256 *==========================================================================*/
mm_camera_do_mmap_ion(int ion_fd,struct ion_allocation_data * alloc,struct ion_fd_data * ion_info_fd,int * mapFd)257 uint8_t *mm_camera_do_mmap_ion(int ion_fd, struct ion_allocation_data *alloc,
258 struct ion_fd_data *ion_info_fd, int *mapFd)
259 {
260 void *ret; /* returned virtual address */
261 int rc = 0;
262 struct ion_handle_data handle_data;
263
264 /* to make it page size aligned */
265 alloc->len = (alloc->len + 4095) & (~4095);
266 alloc->align = 4096;
267
268 rc = ioctl(ion_fd, ION_IOC_ALLOC, alloc);
269 if (rc < 0) {
270 CDBG_ERROR("ION allocation failed %s\n", strerror(errno));
271 goto ION_ALLOC_FAILED;
272 }
273
274 ion_info_fd->handle = alloc->handle;
275 rc = ioctl(ion_fd, ION_IOC_SHARE, ion_info_fd);
276 if (rc < 0) {
277 CDBG_ERROR("ION map failed %s\n", strerror(errno));
278 goto ION_MAP_FAILED;
279 }
280 *mapFd = ion_info_fd->fd;
281 ret = mmap(NULL,
282 alloc->len,
283 PROT_READ | PROT_WRITE,
284 MAP_SHARED,
285 *mapFd,
286 0);
287
288 if (ret == MAP_FAILED) {
289 CDBG_ERROR("ION_MMAP_FAILED: %s (%d)\n", strerror(errno), errno);
290 goto ION_MAP_FAILED;
291 }
292
293 return ret;
294
295 ION_MAP_FAILED:
296 handle_data.handle = ion_info_fd->handle;
297 ioctl(ion_fd, ION_IOC_FREE, &handle_data);
298 ION_ALLOC_FAILED:
299 return NULL;
300 }
301
302 /*===========================================================================
303 * FUNCTION - mm_camera_do_munmap_ion -
304 *
305 * DESCRIPTION:
306 *==========================================================================*/
mm_camera_do_munmap_ion(int ion_fd,struct ion_fd_data * ion_info_fd,void * addr,size_t size)307 int mm_camera_do_munmap_ion (int ion_fd, struct ion_fd_data *ion_info_fd,
308 void *addr, size_t size)
309 {
310 int rc = 0;
311 rc = munmap(addr, size);
312 close(ion_info_fd->fd);
313
314 struct ion_handle_data handle_data;
315 handle_data.handle = ion_info_fd->handle;
316 ioctl(ion_fd, ION_IOC_FREE, &handle_data);
317 return rc;
318 }
319