/* * Copyright (C) 2013 ARM Limited. All rights reserved. * * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include #include "alloc_device.h" #include "gralloc_priv.h" #include "gralloc_helper.h" #include "framebuffer_device.h" #include #include #include #if PLATFORM_SDK_VERSION >= 24 #include "gralloc_usage_ext.h" #endif bool isChunkHeapAvail = true; int alloc_backend_alloc(alloc_device_t* dev, size_t size, int usage, buffer_handle_t* pHandle) { private_module_t* m = reinterpret_cast(dev->common.module); ion_user_handle_t ion_hnd; unsigned char *cpu_ptr = NULL; int shared_fd; int ret = -1; unsigned int heap_type; int ion_flags = 0; static int support_protected = 1; /* initially, assume we support protected memory */ int lock_state = 0; #define ION_HEAP_TYPE_SECURE ION_HEAP_TYPE_SYSTEM bool secureOrProtectedLayer = false; #ifdef GRALLOC_ENABLE_SECURE_LAYER if (usage & GRALLOC_USAGE_AML_SECURE) { secureOrProtectedLayer = true; } #endif if (usage & GRALLOC_USAGE_PROTECTED) { secureOrProtectedLayer = true; usage &= ~GRALLOC_USAGE_PROTECTED; } /* Select heap type based on usage hints */ if (usage & GRALLOC_USAGE_PROTECTED) { #if defined(ION_HEAP_TYPE_SECURE) heap_type = ION_HEAP_TYPE_SECURE; #else AERR("Protected ION memory is not supported on this platform."); return -1; #endif } else { heap_type = ION_HEAP_TYPE_SYSTEM; } if ( (usage & GRALLOC_USAGE_SW_READ_MASK) == GRALLOC_USAGE_SW_READ_OFTEN ) { ion_flags = ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC; } if (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) { ion_flags = ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC; } #ifdef GRALLOC_APP_ALLOC_CONTINUOUS_BUF bool layerAllocContinousBuf = false; #endif if (usage & GRALLOC_USAGE_AML_DMA_BUFFER) //alloc from carveout heap. { #if PLATFORM_SDK_VERSION < 26 ret = ion_alloc(m->ion_client, size, 0, ION_HEAP_CARVEOUT_MASK, ion_flags, &ion_hnd); if (ret != 0) #endif { ret = ion_alloc(m->ion_client, size, 0, 1<ion_client, size, 0, 1<ion_client, size, 0, 1<ion_client, size, 0, 1<ion_client, size, 0, 1<ion_client, size, 0, 1<ion_client); return -1; } ret = ion_share( m->ion_client, ion_hnd, &shared_fd ); if ( ret != 0 ) { AERR( "ion_share( %d ) failed", m->ion_client ); if ( 0 != ion_free( m->ion_client, ion_hnd ) ) AERR( "ion_free( %d ) failed", m->ion_client ); return -1; } if (!(usage & GRALLOC_USAGE_PROTECTED)) { cpu_ptr = (unsigned char*)mmap( NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, shared_fd, 0 ); if ( MAP_FAILED == cpu_ptr ) { AERR( "ion_map( %d ) failed", m->ion_client ); if ( 0 != ion_free( m->ion_client, ion_hnd ) ) AERR( "ion_free( %d ) failed", m->ion_client ); close( shared_fd ); return -1; } lock_state = private_handle_t::LOCK_STATE_MAPPED; } private_handle_t *hnd = new private_handle_t( private_handle_t::PRIV_FLAGS_USES_ION /*TODO ion extend*| priv_heap_flag*/, usage, size, cpu_ptr, lock_state ); if ( NULL != hnd ) { hnd->share_fd = shared_fd; hnd->ion_hnd = ion_hnd; /*TODO ion extend hnd->min_pgsz = min_pgsz; */ *pHandle = hnd; #ifdef GRALLOC_APP_ALLOC_CONTINUOUS_BUF if (layerAllocContinousBuf) { hnd->flags |= private_handle_t::PRIV_FLAGS_CONTINUOUS_BUF; } #endif #ifdef GRALLOC_ENABLE_SECURE_LAYER if (secureOrProtectedLayer) { hnd->flags |= private_handle_t::PRIV_FLAGS_SECURE_PROTECTED; } #endif return 0; } else { AERR( "Gralloc out of mem for ion_client:%d", m->ion_client ); } close( shared_fd ); if (!(usage & GRALLOC_USAGE_PROTECTED)) { ret = munmap( cpu_ptr, size ); if ( 0 != ret ) AERR( "munmap failed for base:%p size: %zd", cpu_ptr, size ); } ret = ion_free( m->ion_client, ion_hnd ); if ( 0 != ret ) AERR( "ion_free( %d ) failed", m->ion_client ); return -1; } int alloc_backend_alloc_framebuffer(private_module_t* m, private_handle_t* hnd, uint32_t idx) { #ifdef GRALLOC_T83X framebuffer_mapper_t* m_fb = NULL; #ifdef DEBUG_EXTERNAL_DISPLAY_ON_PANEL ALOGD("always alloc from fb0"); m_fb = &(m->fb_primary); #else if (hnd->usage & GRALLOC_USAGE_EXTERNAL_DISP) { m_fb = &(m->fb_external); } else { m_fb = &(m->fb_primary); } #endif struct fb_dmabuf_export fb_dma_buf; int res; fb_dma_buf.buffer_idx = idx; res = ioctl( m_fb->framebuffer->fd, FBIOGET_DMABUF, &fb_dma_buf ); if (res == 0) { hnd->share_fd = fb_dma_buf.fd; return 0; } else { AINF("FBIOGET_DMABUF ioctl failed(%d). try FBIOGET_OSD_DMABUF", res); res = ioctl( m_fb->framebuffer->fd, FBIOGET_OSD_DMABUF, &fb_dma_buf ); if (res == 0) { hnd->share_fd = fb_dma_buf.fd; return 0; } else { AINF("FBIOGET_OSD_DMABUF ioctl failed(%d). See gralloc_priv.h and the integration manual for vendor framebuffer integration", res); #if MALI_ARCHITECTURE_UTGARD /* On Utgard we do not have a strict requirement of DMA-BUF integration */ return 0; #else return -1; #endif } } #else return 0; #endif } void alloc_backend_alloc_free(private_handle_t const* hnd, private_module_t* m) { if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) { return; } else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_UMP) { AERR( "Can't free ump memory for handle:%p. Not supported.", hnd ); } else if ( hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION ) { /* Buffer might be unregistered already so we need to assure we have a valid handle*/ if ( 0 != hnd->base ) { if ( 0 != munmap( (void*)hnd->base, hnd->size ) ) AERR( "Failed to munmap handle %p", hnd ); } close( hnd->share_fd ); if ( 0 != ion_free( m->ion_client, hnd->ion_hnd ) ) AERR( "Failed to ion_free( ion_client: %d ion_hnd: %p )", m->ion_client, hnd->ion_hnd ); memset( (void*)hnd, 0, sizeof( *hnd ) ); } } int alloc_backend_open(alloc_device_t *dev) { private_module_t *m = reinterpret_cast(dev->common.module); m->ion_client = ion_open(); if ( m->ion_client < 0 ) { AERR( "ion_open failed with %s", strerror(errno) ); return -1; } return 0; } int alloc_backend_close(struct hw_device_t *device) { alloc_device_t* dev = reinterpret_cast(device); if (dev) { private_module_t *m = reinterpret_cast(dev->common.module); if ( 0 != ion_close(m->ion_client) ) AERR( "Failed to close ion_client: %d err=%s", m->ion_client , strerror(errno)); delete dev; } return 0; }