Home | History | Annotate | Download | only in gralloc960
      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 <cstdlib>
     20 #include <string.h>
     21 #include <errno.h>
     22 #include <inttypes.h>
     23 #include <pthread.h>
     24 
     25 #include <cutils/log.h>
     26 #include <cutils/atomic.h>
     27 #include <hardware/hardware.h>
     28 #include <hardware/gralloc.h>
     29 
     30 #include <sys/ioctl.h>
     31 
     32 #include "alloc_device.h"
     33 #include "gralloc_priv.h"
     34 #include "gralloc_helper.h"
     35 #include "framebuffer_device.h"
     36 #include "ion_4.12.h"
     37 
     38 #include "mali_gralloc_formats.h"
     39 
     40 #include <linux/ion.h>
     41 #include <ion/ion.h>
     42 
     43 static void init_afbc(uint8_t *buf, uint64_t internal_format, int w, int h)
     44 {
     45 	uint32_t n_headers = (w * h) / 64;
     46 	uint32_t body_offset = n_headers * 16;
     47 	uint32_t headers[][4] = { {body_offset, 0x1, 0x0, 0x0}, /* Layouts 0, 3, 4 */
     48 	                          {(body_offset + (1 << 28)), 0x200040, 0x4000, 0x80} /* Layouts 1, 5 */
     49 	                        };
     50 	uint32_t i, layout;
     51 
     52 	/* map format if necessary (also removes internal extension bits) */
     53 	uint64_t base_format = internal_format & MALI_GRALLOC_INTFMT_FMT_MASK;
     54 
     55 	switch (base_format)
     56 	{
     57 		case MALI_GRALLOC_FORMAT_INTERNAL_RGBA_8888:
     58 		case MALI_GRALLOC_FORMAT_INTERNAL_RGBX_8888:
     59 		case MALI_GRALLOC_FORMAT_INTERNAL_RGB_888:
     60 		case MALI_GRALLOC_FORMAT_INTERNAL_RGB_565:
     61 		case MALI_GRALLOC_FORMAT_INTERNAL_BGRA_8888:
     62 			layout = 0;
     63 			break;
     64 
     65 		case MALI_GRALLOC_FORMAT_INTERNAL_YV12:
     66 		case MALI_GRALLOC_FORMAT_INTERNAL_NV12:
     67 		case MALI_GRALLOC_FORMAT_INTERNAL_NV21:
     68 			layout = 1;
     69 			break;
     70 		default:
     71 			layout = 0;
     72 	}
     73 
     74 	ALOGV("Writing AFBC header layout %d for format %" PRIu64, layout, base_format);
     75 
     76 	for (i = 0; i < n_headers; i++)
     77 	{
     78 		memcpy(buf, headers[layout], sizeof(headers[layout]));
     79 		buf += sizeof(headers[layout]);
     80 	}
     81 
     82 }
     83 
     84 static ion_user_handle_t alloc_from_ion_heap(int ion_fd, size_t size, unsigned int heap_mask,
     85 		unsigned int flags, int *min_pgsz)
     86 {
     87 	ion_user_handle_t ion_hnd = -1;
     88 	int ret;
     89 
     90 	if ((ion_fd < 0) || (size <= 0) || (heap_mask == 0) || (min_pgsz == NULL))
     91 		return -1;
     92 
     93 	ret = ion_alloc(ion_fd, size, 0, heap_mask, flags, &ion_hnd);
     94 	if (ret < 0)
     95 	{
     96 #if defined(ION_HEAP_SECURE_MASK)
     97 		if (heap_mask == ION_HEAP_SECURE_MASK)
     98 		{
     99 			return -1;
    100 		}
    101 		else
    102 #endif
    103 		{
    104 			/* If everything else failed try system heap */
    105 			flags = 0; /* Fallback option flags are not longer valid */
    106 			heap_mask = ION_HEAP_SYSTEM_MASK;
    107 			ret = ion_alloc(ion_fd, size, 0, heap_mask, flags, &ion_hnd);
    108 		}
    109 	}
    110 
    111 	if (ret >= 0)
    112 	{
    113 		switch (heap_mask)
    114 		{
    115 		case ION_HEAP_SYSTEM_MASK:
    116 			*min_pgsz = SZ_4K;
    117 			break;
    118 		case ION_HEAP_SYSTEM_CONTIG_MASK:
    119 		case ION_HEAP_CARVEOUT_MASK:
    120 #ifdef ION_HEAP_TYPE_DMA_MASK
    121 		case ION_HEAP_TYPE_DMA_MASK:
    122 #endif
    123 			*min_pgsz = size;
    124 			break;
    125 #ifdef ION_HEAP_CHUNK_MASK
    126 		/* NOTE: if have this heap make sure your ION chunk size is 2M*/
    127 		case ION_HEAP_CHUNK_MASK:
    128 			*min_pgsz = SZ_2M;
    129 			break;
    130 #endif
    131 #ifdef ION_HEAP_COMPOUND_PAGE_MASK
    132 		case ION_HEAP_COMPOUND_PAGE_MASK:
    133 			*min_pgsz = SZ_2M;
    134 			break;
    135 #endif
    136 		/* If have customized heap please set the suitable pg type according to
    137 		 * the customized ION implementation
    138 		 */
    139 #ifdef ION_HEAP_CUSTOM_MASK
    140 		case ION_HEAP_CUSTOM_MASK:
    141 			*min_pgsz = SZ_4K;
    142 			break;
    143 #endif
    144 		default:
    145 			*min_pgsz = SZ_4K;
    146 			break;
    147 		}
    148 	}
    149 
    150 	return ion_hnd;
    151 }
    152 
    153 static int find_system_heap_id(int ion_client)
    154 {
    155 	int i, ret, cnt, system_heap_id = -1;
    156 	struct ion_heap_data *data;
    157 
    158 	ret = ion_query_heap_cnt(ion_client, &cnt);
    159 
    160 	if (ret)
    161 	{
    162 		AERR("ion count query failed with %s", strerror(errno));
    163 		return -1;
    164 	}
    165 
    166 	data = (struct ion_heap_data *)malloc(cnt * sizeof(*data));
    167 	if (!data)
    168 	{
    169 		AERR("Error allocating data %s\n", strerror(errno));
    170 		return -1;
    171 	}
    172 
    173 	ret = ion_query_get_heaps(ion_client, cnt, data);
    174 	if (ret)
    175 	{
    176 		AERR("Error querying heaps from ion %s", strerror(errno));
    177 	}
    178 	else
    179 	{
    180 		for (i = 0; i < cnt; i++) {
    181 			if (strcmp(data[i].name, "ion_system_heap") == 0) {
    182 				system_heap_id = data[i].heap_id;
    183 				break;
    184 			}
    185 		}
    186 
    187 		if (i == cnt)
    188 		{
    189 			AERR("No System Heap Found amongst %d heaps\n", cnt);
    190 			system_heap_id = -1;
    191 		}
    192 	}
    193 
    194 	free(data);
    195 	return system_heap_id;
    196 }
    197 
    198 unsigned int pick_ion_heap(int usage)
    199 {
    200 	unsigned int heap_mask;
    201 
    202 	if(usage & GRALLOC_USAGE_PROTECTED)
    203 	{
    204 #if defined(ION_HEAP_SECURE_MASK)
    205 		heap_mask = ION_HEAP_SECURE_MASK;
    206 #else
    207 		AERR("Protected ION memory is not supported on this platform.");
    208 		return 0;
    209 #endif
    210 	}
    211 #if defined(ION_HEAP_TYPE_COMPOUND_PAGE_MASK) && GRALLOC_USE_ION_COMPOUND_PAGE_HEAP
    212 	else if(!(usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) && (usage & (GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_COMPOSER)))
    213 	{
    214 		heap_mask = ION_HEAP_TYPE_COMPOUND_PAGE_MASK;
    215 	}
    216 #elif defined(ION_HEAP_TYPE_DMA_MASK) && GRALLOC_USE_ION_DMA_HEAP
    217 	else if(!(usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) && (usage & (GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_COMPOSER)))
    218 	{
    219 		heap_mask = ION_HEAP_TYPE_DMA_MASK;
    220 	}
    221 #endif
    222 	else
    223 	{
    224 		heap_mask = ION_HEAP_SYSTEM_MASK;
    225 	}
    226 
    227 	return heap_mask;
    228 }
    229 
    230 void set_ion_flags(unsigned int heap_mask, int usage, unsigned int *priv_heap_flag, int *ion_flags)
    231 {
    232 #if !GRALLOC_USE_ION_DMA_HEAP
    233 	GRALLOC_UNUSED(heap_mask);
    234 #endif
    235 
    236 	if (priv_heap_flag)
    237 	{
    238 #if defined(ION_HEAP_TYPE_DMA_MASK) && GRALLOC_USE_ION_DMA_HEAP
    239 		if (heap_mask == ION_HEAP_TYPE_DMA_MASK)
    240 		{
    241 			*priv_heap_flag = private_handle_t::PRIV_FLAGS_USES_ION_DMA_HEAP;
    242 		}
    243 #endif
    244 	}
    245 
    246 	if (ion_flags)
    247 	{
    248 #if defined(ION_HEAP_TYPE_DMA_MASK) && GRALLOC_USE_ION_DMA_HEAP
    249 		if(heap_mask != ION_HEAP_TYPE_DMA_MASK)
    250 		{
    251 #endif
    252 			if ( (usage & GRALLOC_USAGE_SW_READ_MASK) == GRALLOC_USAGE_SW_READ_OFTEN )
    253 			{
    254 				*ion_flags = ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC;
    255 			}
    256 #if defined(ION_HEAP_TYPE_DMA_MASK) && GRALLOC_USE_ION_DMA_HEAP
    257 		}
    258 #endif
    259 	}
    260 }
    261 
    262 int alloc_backend_alloc(alloc_device_t* dev, size_t size, int usage, buffer_handle_t* pHandle, uint64_t fmt, int w, int h)
    263 {
    264 	private_module_t* m = reinterpret_cast<private_module_t*>(dev->common.module);
    265 	unsigned char *cpu_ptr = NULL;
    266 	int shared_fd;
    267 	int ret;
    268 	unsigned int heap_mask, priv_heap_flag = 0;
    269 	int ion_flags = 0;
    270 	static int support_protected = 1; /* initially, assume we support protected memory */
    271 	int lock_state = 0;
    272 	int min_pgsz = 0;
    273 
    274 	if (m->gralloc_legacy_ion)
    275 	{
    276 		ion_user_handle_t ion_hnd;
    277 
    278 		heap_mask = pick_ion_heap(usage);
    279 		if(heap_mask == 0)
    280 		{
    281 			AERR("Failed to find an appropriate ion heap");
    282 			return -1;
    283 		}
    284 		set_ion_flags(heap_mask, usage, &priv_heap_flag, &ion_flags);
    285 
    286 		ion_hnd = alloc_from_ion_heap(m->ion_client, size, heap_mask, ion_flags, &min_pgsz);
    287 		if (ion_hnd < 0)
    288 		{
    289 			AERR("Failed to ion_alloc from ion_client:%d", m->ion_client);
    290 			return -1;
    291 		}
    292 
    293 		ret = ion_share( m->ion_client, ion_hnd, &shared_fd );
    294 		if ( ret != 0 )
    295 		{
    296 			AERR( "ion_share( %d ) failed", m->ion_client );
    297 			if ( 0 != ion_free( m->ion_client, ion_hnd ) ) AERR( "ion_free( %d ) failed", m->ion_client );
    298 			return -1;
    299 		}
    300 
    301 		// we do not need ion_hnd once we have shared_fd
    302 		if (0 != ion_free(m->ion_client, ion_hnd))
    303 		{
    304 		    AWAR("ion_free( %d ) failed", m->ion_client);
    305 		}
    306 		ion_hnd = -1;
    307 	}
    308 	else
    309 	{
    310 		/* Support only System heap to begin with */
    311 		ret = ion_alloc_fd(m->ion_client, size, 0, 1 << m->system_heap_id, 0, &(shared_fd));
    312 		if (ret != 0)
    313 		{
    314 			AERR("Failed to ion_alloc_fd from ion_client:%d", m->ion_client);
    315 			return -1;
    316 		}
    317 		min_pgsz = SZ_4K;
    318 	}
    319 
    320 	if (!(usage & GRALLOC_USAGE_PROTECTED))
    321 	{
    322 		cpu_ptr = (unsigned char*)mmap( NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, shared_fd, 0 );
    323 
    324 		if ( MAP_FAILED == cpu_ptr )
    325 		{
    326 			AERR( "ion_map( %d ) failed", m->ion_client );
    327 			close( shared_fd );
    328 			return -1;
    329 		}
    330 		lock_state = private_handle_t::LOCK_STATE_MAPPED;
    331 
    332 #if GRALLOC_INIT_AFBC == 1
    333 		if (fmt & MALI_GRALLOC_INTFMT_AFBCENABLE_MASK)
    334 		{
    335 			init_afbc(cpu_ptr, fmt, w, h);
    336 		}
    337 #else
    338 		GRALLOC_UNUSED(fmt);
    339 		GRALLOC_UNUSED(w);
    340 		GRALLOC_UNUSED(h);
    341 
    342 #endif /* GRALLOC_INIT_AFBC == 1 */
    343 	}
    344 
    345 	private_handle_t *hnd = new private_handle_t( private_handle_t::PRIV_FLAGS_USES_ION | priv_heap_flag, usage, size, cpu_ptr,
    346 	                                              lock_state, -1, 0);
    347 
    348 	if ( NULL != hnd )
    349 	{
    350 		hnd->share_fd = shared_fd;
    351 		hnd->min_pgsz = min_pgsz;
    352 		*pHandle = hnd;
    353 		return 0;
    354 	}
    355 	else
    356 	{
    357 		AERR( "Gralloc out of mem for ion_client:%d", m->ion_client );
    358 	}
    359 
    360 	close( shared_fd );
    361 
    362 	if(!(usage & GRALLOC_USAGE_PROTECTED))
    363 	{
    364 		ret = munmap( cpu_ptr, size );
    365 		if ( 0 != ret ) AERR( "munmap failed for base:%p size: %zd", cpu_ptr, size );
    366 	}
    367 
    368 	return -1;
    369 }
    370 
    371 int alloc_backend_alloc_framebuffer(private_module_t* m, private_handle_t* hnd)
    372 {
    373 	struct fb_dmabuf_export fb_dma_buf;
    374 	int res;
    375 	res = ioctl( m->framebuffer->shallow_fbdev_fd, FBIOGET_DMABUF, &fb_dma_buf );
    376 	if(res == 0)
    377 	{
    378 		hnd->share_fd = fb_dma_buf.fd;
    379 		return 0;
    380 	}
    381 	else
    382 	{
    383 		AINF("FBIOGET_DMABUF ioctl failed(%d). See gralloc_priv.h and the integration manual for vendor framebuffer integration", res);
    384 		return -1;
    385 	}
    386 }
    387 
    388 void alloc_backend_alloc_free(private_handle_t const* hnd, private_module_t* m)
    389 {
    390 	(void) m;
    391 	if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)
    392 	{
    393 		return;
    394 	}
    395 	else if ( hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION )
    396 	{
    397 		/* Buffer might be unregistered already so we need to assure we have a valid handle*/
    398 		if ( 0 != hnd->base )
    399 		{
    400 			if ( 0 != munmap( (void*)hnd->base, hnd->size ) ) AERR( "Failed to munmap handle %p", hnd );
    401 		}
    402 		close( hnd->share_fd );
    403 		memset( (void*)hnd, 0, sizeof( *hnd ) );
    404 	}
    405 }
    406 
    407 int alloc_backend_open(alloc_device_t *dev)
    408 {
    409 	private_module_t *m = reinterpret_cast<private_module_t *>(dev->common.module);
    410 	m->ion_client = ion_open();
    411 	if ( m->ion_client < 0 )
    412 	{
    413 		AERR( "ion_open failed with %s", strerror(errno) );
    414 		return -1;
    415 	}
    416 
    417 	m->gralloc_legacy_ion = ion_is_legacy(m->ion_client);
    418 
    419 	if (!m->gralloc_legacy_ion)
    420 	{
    421 		m->system_heap_id = find_system_heap_id(m->ion_client);
    422 		if (m->system_heap_id < 0)
    423 		{
    424 			ion_close(m->ion_client);
    425 			m->ion_client = -1;
    426 			AERR( "ion_open failed: no system heap found" );
    427 			return -1;
    428 		}
    429 	}
    430 
    431 	return 0;
    432 }
    433 
    434 int alloc_backend_close(struct hw_device_t *device)
    435 {
    436 	alloc_device_t* dev = reinterpret_cast<alloc_device_t*>(device);
    437 	if (dev)
    438 	{
    439 		private_module_t *m = reinterpret_cast<private_module_t*>(dev->common.module);
    440 		if ( 0 != ion_close(m->ion_client) ) AERR( "Failed to close ion_client: %d err=%s", m->ion_client , strerror(errno));
    441 		delete dev;
    442 	}
    443 	return 0;
    444 }
    445