1 /* 2 * Copyright (C) 2013 ARM Limited. All rights reserved. 3 * 4 * Copyright (C) 2008 The Android Open Source Project 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 #include <string.h> 20 #include <errno.h> 21 #include <inttypes.h> 22 #include <pthread.h> 23 24 #include <cutils/log.h> 25 #include <cutils/atomic.h> 26 #include <hardware/hardware.h> 27 #include <hardware/gralloc.h> 28 29 #include <sys/ioctl.h> 30 31 #include "alloc_device.h" 32 #include "gralloc_priv.h" 33 #include "gralloc_helper.h" 34 #include "framebuffer_device.h" 35 36 #include "mali_gralloc_formats.h" 37 38 #include <linux/ion.h> 39 #include <ion/ion.h> 40 41 static void init_afbc(uint8_t *buf, uint64_t internal_format, int w, int h) 42 { 43 uint32_t n_headers = (w * h) / 64; 44 uint32_t body_offset = n_headers * 16; 45 uint32_t headers[][4] = { {body_offset, 0x1, 0x0, 0x0}, /* Layouts 0, 3, 4 */ 46 {(body_offset + (1 << 28)), 0x200040, 0x4000, 0x80} /* Layouts 1, 5 */ 47 }; 48 uint32_t i, layout; 49 50 /* map format if necessary (also removes internal extension bits) */ 51 uint64_t base_format = internal_format & MALI_GRALLOC_INTFMT_FMT_MASK; 52 53 switch (base_format) 54 { 55 case MALI_GRALLOC_FORMAT_INTERNAL_RGBA_8888: 56 case MALI_GRALLOC_FORMAT_INTERNAL_RGBX_8888: 57 case MALI_GRALLOC_FORMAT_INTERNAL_RGB_888: 58 case MALI_GRALLOC_FORMAT_INTERNAL_RGB_565: 59 case MALI_GRALLOC_FORMAT_INTERNAL_BGRA_8888: 60 layout = 0; 61 break; 62 63 case MALI_GRALLOC_FORMAT_INTERNAL_YV12: 64 case MALI_GRALLOC_FORMAT_INTERNAL_NV12: 65 case MALI_GRALLOC_FORMAT_INTERNAL_NV21: 66 layout = 1; 67 break; 68 default: 69 layout = 0; 70 } 71 72 ALOGV("Writing AFBC header layout %d for format %" PRIu64, layout, base_format); 73 74 for (i = 0; i < n_headers; i++) 75 { 76 memcpy(buf, headers[layout], sizeof(headers[layout])); 77 buf += sizeof(headers[layout]); 78 } 79 80 } 81 82 static ion_user_handle_t alloc_from_ion_heap(int ion_fd, size_t size, unsigned int heap_mask, 83 unsigned int flags, int *min_pgsz) 84 { 85 ion_user_handle_t ion_hnd = -1; 86 int ret; 87 88 if ((ion_fd < 0) || (size <= 0) || (heap_mask == 0) || (min_pgsz == NULL)) 89 return -1; 90 91 ret = ion_alloc(ion_fd, size, 0, heap_mask, flags, &ion_hnd); 92 if (ret < 0) 93 { 94 #if defined(ION_HEAP_SECURE_MASK) 95 if (heap_mask == ION_HEAP_SECURE_MASK) 96 { 97 return -1; 98 } 99 else 100 #endif 101 { 102 /* If everything else failed try system heap */ 103 flags = 0; /* Fallback option flags are not longer valid */ 104 heap_mask = ION_HEAP_SYSTEM_MASK; 105 ret = ion_alloc(ion_fd, size, 0, heap_mask, flags, &ion_hnd); 106 } 107 } 108 109 if (ret >= 0) 110 { 111 switch (heap_mask) 112 { 113 case ION_HEAP_SYSTEM_MASK: 114 *min_pgsz = SZ_4K; 115 break; 116 case ION_HEAP_SYSTEM_CONTIG_MASK: 117 case ION_HEAP_CARVEOUT_MASK: 118 #ifdef ION_HEAP_TYPE_DMA_MASK 119 case ION_HEAP_TYPE_DMA_MASK: 120 #endif 121 *min_pgsz = size; 122 break; 123 #ifdef ION_HEAP_CHUNK_MASK 124 /* NOTE: if have this heap make sure your ION chunk size is 2M*/ 125 case ION_HEAP_CHUNK_MASK: 126 *min_pgsz = SZ_2M; 127 break; 128 #endif 129 #ifdef ION_HEAP_COMPOUND_PAGE_MASK 130 case ION_HEAP_COMPOUND_PAGE_MASK: 131 *min_pgsz = SZ_2M; 132 break; 133 #endif 134 /* If have customized heap please set the suitable pg type according to 135 * the customized ION implementation 136 */ 137 #ifdef ION_HEAP_CUSTOM_MASK 138 case ION_HEAP_CUSTOM_MASK: 139 *min_pgsz = SZ_4K; 140 break; 141 #endif 142 default: 143 *min_pgsz = SZ_4K; 144 break; 145 } 146 } 147 148 return ion_hnd; 149 } 150 151 unsigned int pick_ion_heap(int usage) 152 { 153 unsigned int heap_mask; 154 155 if(usage & GRALLOC_USAGE_PROTECTED) 156 { 157 #if defined(ION_HEAP_SECURE_MASK) 158 heap_mask = ION_HEAP_SECURE_MASK; 159 #else 160 AERR("Protected ION memory is not supported on this platform."); 161 return 0; 162 #endif 163 } 164 #if defined(ION_HEAP_TYPE_COMPOUND_PAGE_MASK) && GRALLOC_USE_ION_COMPOUND_PAGE_HEAP 165 else if(!(usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) && (usage & (GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_COMPOSER))) 166 { 167 heap_mask = ION_HEAP_TYPE_COMPOUND_PAGE_MASK; 168 } 169 #elif defined(ION_HEAP_TYPE_DMA_MASK) && GRALLOC_USE_ION_DMA_HEAP 170 else if(!(usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) && (usage & (GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_COMPOSER))) 171 { 172 heap_mask = ION_HEAP_TYPE_DMA_MASK; 173 } 174 #endif 175 else 176 { 177 heap_mask = ION_HEAP_SYSTEM_MASK; 178 } 179 180 return heap_mask; 181 } 182 183 void set_ion_flags(unsigned int heap_mask, int usage, unsigned int *priv_heap_flag, int *ion_flags) 184 { 185 #if !GRALLOC_USE_ION_DMA_HEAP 186 GRALLOC_UNUSED(heap_mask); 187 #endif 188 189 if (priv_heap_flag) 190 { 191 #if defined(ION_HEAP_TYPE_DMA_MASK) && GRALLOC_USE_ION_DMA_HEAP 192 if (heap_mask == ION_HEAP_TYPE_DMA_MASK) 193 { 194 *priv_heap_flag = private_handle_t::PRIV_FLAGS_USES_ION_DMA_HEAP; 195 } 196 #endif 197 } 198 199 if (ion_flags) 200 { 201 #if defined(ION_HEAP_TYPE_DMA_MASK) && GRALLOC_USE_ION_DMA_HEAP 202 if(heap_mask != ION_HEAP_TYPE_DMA_MASK) 203 { 204 #endif 205 if ( (usage & GRALLOC_USAGE_SW_READ_MASK) == GRALLOC_USAGE_SW_READ_OFTEN ) 206 { 207 *ion_flags = ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC; 208 } 209 #if defined(ION_HEAP_TYPE_DMA_MASK) && GRALLOC_USE_ION_DMA_HEAP 210 } 211 #endif 212 } 213 } 214 215 int alloc_backend_alloc(alloc_device_t* dev, size_t size, int usage, buffer_handle_t* pHandle, uint64_t fmt, int w, int h) 216 { 217 private_module_t* m = reinterpret_cast<private_module_t*>(dev->common.module); 218 ion_user_handle_t ion_hnd; 219 unsigned char *cpu_ptr = NULL; 220 int shared_fd; 221 int ret; 222 unsigned int heap_mask, priv_heap_flag = 0; 223 int ion_flags = 0; 224 static int support_protected = 1; /* initially, assume we support protected memory */ 225 int lock_state = 0; 226 int min_pgsz = 0; 227 228 heap_mask = pick_ion_heap(usage); 229 if(heap_mask == 0) 230 { 231 AERR("Failed to find an appropriate ion heap"); 232 return -1; 233 } 234 set_ion_flags(heap_mask, usage, &priv_heap_flag, &ion_flags); 235 236 ion_hnd = alloc_from_ion_heap(m->ion_client, size, heap_mask, ion_flags, &min_pgsz); 237 if (ion_hnd < 0) 238 { 239 AERR("Failed to ion_alloc from ion_client:%d", m->ion_client); 240 return -1; 241 } 242 243 ret = ion_share( m->ion_client, ion_hnd, &shared_fd ); 244 if ( ret != 0 ) 245 { 246 AERR( "ion_share( %d ) failed", m->ion_client ); 247 if ( 0 != ion_free( m->ion_client, ion_hnd ) ) AERR( "ion_free( %d ) failed", m->ion_client ); 248 return -1; 249 } 250 251 // we do not need ion_hnd once we have shared_fd 252 if (0 != ion_free(m->ion_client, ion_hnd)) 253 { 254 AWAR("ion_free( %d ) failed", m->ion_client); 255 } 256 ion_hnd = -1; 257 258 if (!(usage & GRALLOC_USAGE_PROTECTED)) 259 { 260 cpu_ptr = (unsigned char*)mmap( NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, shared_fd, 0 ); 261 262 if ( MAP_FAILED == cpu_ptr ) 263 { 264 AERR( "ion_map( %d ) failed", m->ion_client ); 265 close( shared_fd ); 266 return -1; 267 } 268 lock_state = private_handle_t::LOCK_STATE_MAPPED; 269 270 #if GRALLOC_INIT_AFBC == 1 271 if (fmt & MALI_GRALLOC_INTFMT_AFBCENABLE_MASK) 272 { 273 init_afbc(cpu_ptr, fmt, w, h); 274 } 275 #else 276 GRALLOC_UNUSED(fmt); 277 GRALLOC_UNUSED(w); 278 GRALLOC_UNUSED(h); 279 280 #endif /* GRALLOC_INIT_AFBC == 1 */ 281 } 282 283 private_handle_t *hnd = new private_handle_t( private_handle_t::PRIV_FLAGS_USES_ION | priv_heap_flag, usage, size, cpu_ptr, 284 lock_state, -1, 0); 285 286 if ( NULL != hnd ) 287 { 288 hnd->share_fd = shared_fd; 289 hnd->min_pgsz = min_pgsz; 290 *pHandle = hnd; 291 return 0; 292 } 293 else 294 { 295 AERR( "Gralloc out of mem for ion_client:%d", m->ion_client ); 296 } 297 298 close( shared_fd ); 299 300 if(!(usage & GRALLOC_USAGE_PROTECTED)) 301 { 302 ret = munmap( cpu_ptr, size ); 303 if ( 0 != ret ) AERR( "munmap failed for base:%p size: %zd", cpu_ptr, size ); 304 } 305 306 return -1; 307 } 308 309 int alloc_backend_alloc_framebuffer(private_module_t* m, private_handle_t* hnd) 310 { 311 struct fb_dmabuf_export fb_dma_buf; 312 int res; 313 res = ioctl( m->framebuffer->shallow_fbdev_fd, FBIOGET_DMABUF, &fb_dma_buf ); 314 if(res == 0) 315 { 316 hnd->share_fd = fb_dma_buf.fd; 317 return 0; 318 } 319 else 320 { 321 AINF("FBIOGET_DMABUF ioctl failed(%d). See gralloc_priv.h and the integration manual for vendor framebuffer integration", res); 322 return -1; 323 } 324 } 325 326 void alloc_backend_alloc_free(private_handle_t const* hnd, private_module_t* m) 327 { 328 (void) m; 329 if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) 330 { 331 return; 332 } 333 else if ( hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION ) 334 { 335 /* Buffer might be unregistered already so we need to assure we have a valid handle*/ 336 if ( 0 != hnd->base ) 337 { 338 if ( 0 != munmap( (void*)hnd->base, hnd->size ) ) AERR( "Failed to munmap handle %p", hnd ); 339 } 340 close( hnd->share_fd ); 341 memset( (void*)hnd, 0, sizeof( *hnd ) ); 342 } 343 } 344 345 int alloc_backend_open(alloc_device_t *dev) 346 { 347 private_module_t *m = reinterpret_cast<private_module_t *>(dev->common.module); 348 m->ion_client = ion_open(); 349 if ( m->ion_client < 0 ) 350 { 351 AERR( "ion_open failed with %s", strerror(errno) ); 352 return -1; 353 } 354 355 return 0; 356 } 357 358 int alloc_backend_close(struct hw_device_t *device) 359 { 360 alloc_device_t* dev = reinterpret_cast<alloc_device_t*>(device); 361 if (dev) 362 { 363 private_module_t *m = reinterpret_cast<private_module_t*>(dev->common.module); 364 if ( 0 != ion_close(m->ion_client) ) AERR( "Failed to close ion_client: %d err=%s", m->ion_client , strerror(errno)); 365 delete dev; 366 } 367 return 0; 368 } 369