1 /* 2 Copyright (c) 2011, 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_interface2.h" 41 #include <linux/msm_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 *==========================================================================*/ 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 *==========================================================================*/ 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 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 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 ==============================================================*/ 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 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_YUV_420_YV12: 215 if (CAMERA_MODE_3D == mode) { 216 *num_planes = 1; 217 size = (uint32_t)(PAD_TO_2K(width*height)*3/2); 218 plane[0] = PAD_TO_WORD(width*height); 219 } else { 220 *num_planes = 3; 221 plane[0] = PAD_TO_2K(CEILING16(width) * height); 222 plane[1] = PAD_TO_2K(CEILING16(width/2) * height/2); 223 plane[2] = PAD_TO_2K(CEILING16(width/2) * height/2); 224 size = plane[0] + plane[1] + plane[2]; 225 } 226 break; 227 case CAMERA_BAYER_SBGGR10: 228 *num_planes = 1; 229 plane[0] = PAD_TO_WORD(width * height); 230 size = plane[0]; 231 break; 232 case CAMERA_YUV_422_YUYV: 233 *num_planes = 1; 234 plane[0] = PAD_TO_WORD(width * height); 235 size = plane[0]; 236 break; 237 case CAMERA_YUV_422_NV16: 238 case CAMERA_YUV_422_NV61: 239 if( image_type == OUTPUT_TYPE_S || image_type == OUTPUT_TYPE_V) { 240 local_height = CEILING16(height); 241 } else { 242 local_height = height; 243 } 244 *num_planes = 2; 245 plane[0] = PAD_TO_WORD(width * height); 246 plane[1] = PAD_TO_WORD(width * height); 247 size = plane[0] + plane[1]; 248 break; 249 default: 250 CDBG("%s: format %d not supported.\n", 251 __func__, fmt_type); 252 size = 0; 253 } 254 CDBG("%s:fmt=%d,image_type=%d,width=%d,height=%d,frame_len=%d\n", 255 __func__, fmt_type, image_type, width, height, size); 256 return size; 257 } 258 259 void mm_camera_util_profile(const char *str) 260 { 261 #if (MM_CAMERA_PROFILE) 262 struct timespec cur_time; 263 264 clock_gettime(CLOCK_REALTIME, &cur_time); 265 CDBG_HIGH("PROFILE %s: %ld.%09ld\n", str, 266 cur_time.tv_sec, cur_time.tv_nsec); 267 #endif 268 } 269 270 /*=========================================================================== 271 * FUNCTION - mm_camera_do_mmap_ion - 272 * 273 * DESCRIPTION: 274 *==========================================================================*/ 275 uint8_t *mm_camera_do_mmap_ion(int ion_fd, struct ion_allocation_data *alloc, 276 struct ion_fd_data *ion_info_fd, int *mapFd) 277 { 278 void *ret; /* returned virtual address */ 279 int rc = 0; 280 struct ion_handle_data handle_data; 281 282 /* to make it page size aligned */ 283 alloc->len = (alloc->len + 4095) & (~4095); 284 285 rc = ioctl(ion_fd, ION_IOC_ALLOC, alloc); 286 if (rc < 0) { 287 CDBG_ERROR("ION allocation failed %s\n", strerror(errno)); 288 goto ION_ALLOC_FAILED; 289 } 290 291 ion_info_fd->handle = alloc->handle; 292 rc = ioctl(ion_fd, ION_IOC_SHARE, ion_info_fd); 293 if (rc < 0) { 294 CDBG_ERROR("ION map failed %s\n", strerror(errno)); 295 goto ION_MAP_FAILED; 296 } 297 *mapFd = ion_info_fd->fd; 298 ret = mmap(NULL, 299 alloc->len, 300 PROT_READ | PROT_WRITE, 301 MAP_SHARED, 302 *mapFd, 303 0); 304 305 if (ret == MAP_FAILED) { 306 CDBG_ERROR("ION_MMAP_FAILED: %s (%d)\n", strerror(errno), errno); 307 goto ION_MAP_FAILED; 308 } 309 310 return ret; 311 312 ION_MAP_FAILED: 313 handle_data.handle = ion_info_fd->handle; 314 ioctl(ion_fd, ION_IOC_FREE, &handle_data); 315 ION_ALLOC_FAILED: 316 return NULL; 317 } 318 319 /*=========================================================================== 320 * FUNCTION - mm_camera_do_munmap_ion - 321 * 322 * DESCRIPTION: 323 *==========================================================================*/ 324 int mm_camera_do_munmap_ion (int ion_fd, struct ion_fd_data *ion_info_fd, 325 void *addr, size_t size) 326 { 327 int rc = 0; 328 rc = munmap(addr, size); 329 close(ion_info_fd->fd); 330 331 struct ion_handle_data handle_data; 332 handle_data.handle = ion_info_fd->handle; 333 ioctl(ion_fd, ION_IOC_FREE, &handle_data); 334 return rc; 335 } 336