Home | History | Annotate | Download | only in gralloc
      1 /*
      2  * Copyright (C) 2010 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 <pthread.h>
     22 
     23 #include <cutils/log.h>
     24 #include <cutils/atomic.h>
     25 #include <hardware/hardware.h>
     26 #include <hardware/gralloc.h>
     27 
     28 #include <sys/ioctl.h>
     29 
     30 #include "alloc_device.h"
     31 #include "gralloc_priv.h"
     32 #include "gralloc_helper.h"
     33 #include "framebuffer_device.h"
     34 
     35 #if GRALLOC_ARM_UMP_MODULE
     36 #include <ump/ump.h>
     37 #include <ump/ump_ref_drv.h>
     38 #endif
     39 
     40 #if GRALLOC_ARM_DMA_BUF_MODULE
     41 #include <linux/ion.h>
     42 #include <ion/ion.h>
     43 #endif
     44 
     45 #define GRALLOC_ALIGN( value, base ) (((value) + ((base) - 1)) & ~((base) - 1))
     46 
     47 
     48 #if GRALLOC_SIMULATE_FAILURES
     49 #include <cutils/properties.h>
     50 
     51 /* system property keys for controlling simulated UMP allocation failures */
     52 #define PROP_MALI_TEST_GRALLOC_FAIL_FIRST     "mali.test.gralloc.fail_first"
     53 #define PROP_MALI_TEST_GRALLOC_FAIL_INTERVAL  "mali.test.gralloc.fail_interval"
     54 
     55 static int __ump_alloc_should_fail()
     56 {
     57 
     58 	static unsigned int call_count  = 0;
     59 	unsigned int        first_fail  = 0;
     60 	int                 fail_period = 0;
     61 	int                 fail        = 0;
     62 
     63 	++call_count;
     64 
     65 	/* read the system properties that control failure simulation */
     66 	{
     67 		char prop_value[PROPERTY_VALUE_MAX];
     68 
     69 		if (property_get(PROP_MALI_TEST_GRALLOC_FAIL_FIRST, prop_value, "0") > 0)
     70 		{
     71 			sscanf(prop_value, "%11u", &first_fail);
     72 		}
     73 
     74 		if (property_get(PROP_MALI_TEST_GRALLOC_FAIL_INTERVAL, prop_value, "0") > 0)
     75 		{
     76 			sscanf(prop_value, "%11u", &fail_period);
     77 		}
     78 	}
     79 
     80 	/* failure simulation is enabled by setting the first_fail property to non-zero */
     81 	if (first_fail > 0)
     82 	{
     83 		LOGI("iteration %u (fail=%u, period=%u)\n", call_count, first_fail, fail_period);
     84 
     85 		fail = (call_count == first_fail) ||
     86 		       (call_count > first_fail && fail_period > 0 && 0 == (call_count - first_fail) % fail_period);
     87 
     88 		if (fail)
     89 		{
     90 			AERR("failed ump_ref_drv_allocate on iteration #%d\n", call_count);
     91 		}
     92 	}
     93 
     94 	return fail;
     95 }
     96 #endif
     97 
     98 
     99 static int gralloc_alloc_buffer(alloc_device_t *dev, size_t size, int usage, buffer_handle_t *pHandle)
    100 {
    101 #if GRALLOC_ARM_DMA_BUF_MODULE
    102 	{
    103 		private_module_t *m = reinterpret_cast<private_module_t *>(dev->common.module);
    104 		ion_user_handle_t ion_hnd;
    105 		unsigned char *cpu_ptr;
    106 		int shared_fd;
    107 		int ret;
    108 
    109 		ret = ion_alloc(m->ion_client, size, 0, ION_HEAP_SYSTEM_MASK, 0, &(ion_hnd));
    110 
    111 		if (ret != 0)
    112 		{
    113 			AERR("Failed to ion_alloc from ion_client:%d", m->ion_client);
    114 			return -1;
    115 		}
    116 
    117 		ret = ion_share(m->ion_client, ion_hnd, &shared_fd);
    118 
    119 		if (ret != 0)
    120 		{
    121 			AERR("ion_share( %d ) failed", m->ion_client);
    122 
    123 			if (0 != ion_free(m->ion_client, ion_hnd))
    124 			{
    125 				AERR("ion_free( %d ) failed", m->ion_client);
    126 			}
    127 
    128 			return -1;
    129 		}
    130 
    131 		// we do not need ion_hnd once we have shared_fd
    132 		if (0 != ion_free(m->ion_client, ion_hnd))
    133 		{
    134 			AWAR("ion_free( %d ) failed", m->ion_client);
    135 		}
    136 		ion_hnd = ION_INVALID_HANDLE;
    137 
    138 		cpu_ptr = (unsigned char *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, shared_fd, 0);
    139 
    140 		if (MAP_FAILED == cpu_ptr)
    141 		{
    142 			AERR("ion_map( %d ) failed", m->ion_client);
    143 
    144 			close(shared_fd);
    145 			return -1;
    146 		}
    147 
    148 		private_handle_t *hnd = new private_handle_t(private_handle_t::PRIV_FLAGS_USES_ION, usage, size, cpu_ptr, private_handle_t::LOCK_STATE_MAPPED);
    149 
    150 		if (NULL != hnd)
    151 		{
    152 			hnd->share_fd = shared_fd;
    153 			*pHandle = hnd;
    154 			return 0;
    155 		}
    156 		else
    157 		{
    158 			AERR("Gralloc out of mem for ion_client:%d", m->ion_client);
    159 		}
    160 
    161 		close(shared_fd);
    162 		ret = munmap(cpu_ptr, size);
    163 
    164 		if (0 != ret)
    165 		{
    166 			AERR("munmap failed for base:%p size: %lu", cpu_ptr, (unsigned long)size);
    167 		}
    168 
    169 		return -1;
    170 	}
    171 #endif
    172 
    173 #if GRALLOC_ARM_UMP_MODULE
    174 	MALI_IGNORE(dev);
    175 	{
    176 		ump_handle ump_mem_handle;
    177 		void *cpu_ptr;
    178 		ump_secure_id ump_id;
    179 		ump_alloc_constraints constraints;
    180 
    181 		size = round_up_to_page_size(size);
    182 
    183 		if ((usage & GRALLOC_USAGE_SW_READ_MASK) == GRALLOC_USAGE_SW_READ_OFTEN)
    184 		{
    185 			constraints =  UMP_REF_DRV_CONSTRAINT_USE_CACHE;
    186 		}
    187 		else
    188 		{
    189 			constraints = UMP_REF_DRV_CONSTRAINT_NONE;
    190 		}
    191 
    192 #ifdef GRALLOC_SIMULATE_FAILURES
    193 
    194 		/* if the failure condition matches, fail this iteration */
    195 		if (__ump_alloc_should_fail())
    196 		{
    197 			ump_mem_handle = UMP_INVALID_MEMORY_HANDLE;
    198 		}
    199 		else
    200 #endif
    201 		{
    202 			ump_mem_handle = ump_ref_drv_allocate(size, constraints);
    203 
    204 			if (UMP_INVALID_MEMORY_HANDLE != ump_mem_handle)
    205 			{
    206 				cpu_ptr = ump_mapped_pointer_get(ump_mem_handle);
    207 
    208 				if (NULL != cpu_ptr)
    209 				{
    210 					ump_id = ump_secure_id_get(ump_mem_handle);
    211 
    212 					if (UMP_INVALID_SECURE_ID != ump_id)
    213 					{
    214 						private_handle_t *hnd = new private_handle_t(private_handle_t::PRIV_FLAGS_USES_UMP, usage, size, cpu_ptr,
    215 						        private_handle_t::LOCK_STATE_MAPPED, ump_id, ump_mem_handle);
    216 
    217 						if (NULL != hnd)
    218 						{
    219 							*pHandle = hnd;
    220 							return 0;
    221 						}
    222 						else
    223 						{
    224 							AERR("gralloc_alloc_buffer() failed to allocate handle. ump_handle = %p, ump_id = %d", ump_mem_handle, ump_id);
    225 						}
    226 					}
    227 					else
    228 					{
    229 						AERR("gralloc_alloc_buffer() failed to retrieve valid secure id. ump_handle = %p", ump_mem_handle);
    230 					}
    231 
    232 					ump_mapped_pointer_release(ump_mem_handle);
    233 				}
    234 				else
    235 				{
    236 					AERR("gralloc_alloc_buffer() failed to map UMP memory. ump_handle = %p", ump_mem_handle);
    237 				}
    238 
    239 				ump_reference_release(ump_mem_handle);
    240 			}
    241 			else
    242 			{
    243 				AERR("gralloc_alloc_buffer() failed to allocate UMP memory. size:%d constraints: %d", size, constraints);
    244 			}
    245 		}
    246 
    247 		return -1;
    248 	}
    249 #endif
    250 
    251 }
    252 
    253 static int gralloc_alloc_framebuffer_locked(alloc_device_t *dev, size_t size, int usage, buffer_handle_t *pHandle)
    254 {
    255 	private_module_t *m = reinterpret_cast<private_module_t *>(dev->common.module);
    256 
    257 	// allocate the framebuffer
    258 	if (m->framebuffer == NULL)
    259 	{
    260 		// initialize the framebuffer, the framebuffer is mapped once and forever.
    261 		int err = init_frame_buffer_locked(m);
    262 
    263 		if (err < 0)
    264 		{
    265 			return err;
    266 		}
    267 	}
    268 
    269 	const uint32_t bufferMask = m->bufferMask;
    270 	const uint32_t numBuffers = m->numBuffers;
    271 	const size_t bufferSize = m->finfo.line_length * m->info.yres;
    272 
    273 	if (numBuffers == 1)
    274 	{
    275 		// If we have only one buffer, we never use page-flipping. Instead,
    276 		// we return a regular buffer which will be memcpy'ed to the main
    277 		// screen when post is called.
    278 		int newUsage = (usage & ~GRALLOC_USAGE_HW_FB) | GRALLOC_USAGE_HW_2D;
    279 		AERR("fallback to single buffering. Virtual Y-res too small %d", m->info.yres);
    280 		return gralloc_alloc_buffer(dev, bufferSize, newUsage, pHandle);
    281 	}
    282 
    283 	if (bufferMask >= ((1LU << numBuffers) - 1))
    284 	{
    285 		// We ran out of buffers.
    286 		return -ENOMEM;
    287 	}
    288 
    289 	void *vaddr = m->framebuffer->base;
    290 
    291 	// find a free slot
    292 	for (uint32_t i = 0 ; i < numBuffers ; i++)
    293 	{
    294 		if ((bufferMask & (1LU << i)) == 0)
    295 		{
    296 			m->bufferMask |= (1LU << i);
    297 			break;
    298 		}
    299 
    300 		vaddr = (void *)((uintptr_t)vaddr + bufferSize);
    301 	}
    302 
    303 	int fbdev_fd = m->framebuffer->shallow_fbdev_fd;
    304 	// The entire framebuffer memory is already mapped, now create a buffer object for parts of this memory
    305 	private_handle_t *hnd = new private_handle_t(private_handle_t::PRIV_FLAGS_FRAMEBUFFER, usage, size, vaddr,
    306 	        0, fbdev_fd, (uintptr_t)vaddr - (uintptr_t) m->framebuffer->base);
    307 #if GRALLOC_ARM_UMP_MODULE
    308 	hnd->ump_id = m->framebuffer->ump_id;
    309 
    310 	/* create a backing ump memory handle if the framebuffer is exposed as a secure ID */
    311 	if ((int)UMP_INVALID_SECURE_ID != hnd->ump_id)
    312 	{
    313 		hnd->ump_mem_handle = (int)ump_handle_create_from_secure_id(hnd->ump_id);
    314 
    315 		if ((int)UMP_INVALID_MEMORY_HANDLE == hnd->ump_mem_handle)
    316 		{
    317 			AINF("warning: unable to create UMP handle from secure ID %i\n", hnd->ump_id);
    318 		}
    319 	}
    320 
    321 #endif
    322 
    323 #if GRALLOC_ARM_DMA_BUF_MODULE
    324 	{
    325 #ifdef FBIOGET_DMABUF
    326 		struct fb_dmabuf_export fb_dma_buf;
    327 
    328 		if (ioctl(fbdev_fd, FBIOGET_DMABUF, &fb_dma_buf) == 0)
    329 		{
    330 			AINF("framebuffer accessed with dma buf (fd 0x%x)\n", (int)fb_dma_buf.fd);
    331 			hnd->share_fd = fb_dma_buf.fd;
    332 		}
    333 
    334 #endif
    335 	}
    336 
    337 	// correct numFds/numInts when there is no dmabuf fd
    338 	if (hnd->share_fd < 0) {
    339 		hnd->numFds--;
    340 		hnd->numInts++;
    341 	}
    342 #endif
    343 
    344 	*pHandle = hnd;
    345 
    346 	return 0;
    347 }
    348 
    349 static int gralloc_alloc_framebuffer(alloc_device_t *dev, size_t size, int usage, buffer_handle_t *pHandle)
    350 {
    351 	private_module_t *m = reinterpret_cast<private_module_t *>(dev->common.module);
    352 	pthread_mutex_lock(&m->lock);
    353 	int err = gralloc_alloc_framebuffer_locked(dev, size, usage, pHandle);
    354 	pthread_mutex_unlock(&m->lock);
    355 	return err;
    356 }
    357 
    358 static int alloc_device_alloc(alloc_device_t *dev, int w, int h, int format, int usage, buffer_handle_t *pHandle, int *pStride)
    359 {
    360 	if (!pHandle || !pStride)
    361 	{
    362 		return -EINVAL;
    363 	}
    364 
    365 	size_t size;
    366 	size_t stride;
    367 
    368 	if (format == HAL_PIXEL_FORMAT_YCrCb_420_SP || format == HAL_PIXEL_FORMAT_YV12
    369 	        /* HAL_PIXEL_FORMAT_YCbCr_420_SP, HAL_PIXEL_FORMAT_YCbCr_420_P, HAL_PIXEL_FORMAT_YCbCr_422_I are not defined in Android.
    370 	         * To enable Mali DDK EGLImage support for those formats, firstly, you have to add them in Android system/core/include/system/graphics.h.
    371 	         * Then, define SUPPORT_LEGACY_FORMAT in the same header file(Mali DDK will also check this definition).
    372 	         */
    373 #ifdef SUPPORT_LEGACY_FORMAT
    374 	        || format == HAL_PIXEL_FORMAT_YCbCr_420_SP || format == HAL_PIXEL_FORMAT_YCbCr_420_P || format == HAL_PIXEL_FORMAT_YCbCr_422_I
    375 #endif
    376 	   )
    377 	{
    378 		switch (format)
    379 		{
    380 			case HAL_PIXEL_FORMAT_YCrCb_420_SP:
    381 				stride = GRALLOC_ALIGN(w, 16);
    382 				size = GRALLOC_ALIGN(h, 16) * (stride + GRALLOC_ALIGN(stride / 2, 16));
    383 				break;
    384 
    385 			case HAL_PIXEL_FORMAT_YV12:
    386 #ifdef SUPPORT_LEGACY_FORMAT
    387 			case HAL_PIXEL_FORMAT_YCbCr_420_P:
    388 #endif
    389 				stride = GRALLOC_ALIGN(w, 16);
    390 				size = GRALLOC_ALIGN(h, 2) * (stride + GRALLOC_ALIGN(stride / 2, 16));
    391 
    392 				break;
    393 #ifdef SUPPORT_LEGACY_FORMAT
    394 
    395 			case HAL_PIXEL_FORMAT_YCbCr_420_SP:
    396 				stride = GRALLOC_ALIGN(w, 16);
    397 				size = GRALLOC_ALIGN(h, 16) * (stride + GRALLOC_ALIGN(stride / 2, 16));
    398 				break;
    399 
    400 			case HAL_PIXEL_FORMAT_YCbCr_422_I:
    401 				stride = GRALLOC_ALIGN(w, 16);
    402 				size = h * stride * 2;
    403 
    404 				break;
    405 #endif
    406 
    407 			default:
    408 				return -EINVAL;
    409 		}
    410 	}
    411 	else
    412 	{
    413 		int bpp = 0;
    414 
    415 		switch (format)
    416 		{
    417 			case HAL_PIXEL_FORMAT_RGBA_8888:
    418 			case HAL_PIXEL_FORMAT_RGBX_8888:
    419 			case HAL_PIXEL_FORMAT_BGRA_8888:
    420 				bpp = 4;
    421 				break;
    422 
    423 			case HAL_PIXEL_FORMAT_RGB_888:
    424 				bpp = 3;
    425 				break;
    426 
    427 			case HAL_PIXEL_FORMAT_RGB_565:
    428 #if PLATFORM_SDK_VERSION < 19
    429 			case HAL_PIXEL_FORMAT_RGBA_5551:
    430 			case HAL_PIXEL_FORMAT_RGBA_4444:
    431 #endif
    432 				bpp = 2;
    433 				break;
    434 
    435 			default:
    436 				return -EINVAL;
    437 		}
    438 
    439 		size_t bpr = GRALLOC_ALIGN(w * bpp, 64);
    440 		size = bpr * h;
    441 		stride = bpr / bpp;
    442 	}
    443 
    444 	int err;
    445 
    446 #ifndef MALI_600
    447 
    448 	if (usage & GRALLOC_USAGE_HW_FB)
    449 	{
    450 		err = gralloc_alloc_framebuffer(dev, size, usage, pHandle);
    451 	}
    452 	else
    453 #endif
    454 
    455 	{
    456 		err = gralloc_alloc_buffer(dev, size, usage, pHandle);
    457 	}
    458 
    459 	if (err < 0)
    460 	{
    461 		return err;
    462 	}
    463 
    464 	/* match the framebuffer format */
    465 	if (usage & GRALLOC_USAGE_HW_FB)
    466 	{
    467 #ifdef GRALLOC_16_BITS
    468 		format = HAL_PIXEL_FORMAT_RGB_565;
    469 #else
    470 		format = HAL_PIXEL_FORMAT_BGRA_8888;
    471 #endif
    472 	}
    473 
    474 	private_handle_t *hnd = (private_handle_t *)*pHandle;
    475 	int               private_usage = usage & (GRALLOC_USAGE_PRIVATE_0 |
    476 	                                  GRALLOC_USAGE_PRIVATE_1);
    477 
    478 	switch (private_usage)
    479 	{
    480 		case 0:
    481 			hnd->yuv_info = MALI_YUV_BT601_NARROW;
    482 			break;
    483 
    484 		case GRALLOC_USAGE_PRIVATE_1:
    485 			hnd->yuv_info = MALI_YUV_BT601_WIDE;
    486 			break;
    487 
    488 		case GRALLOC_USAGE_PRIVATE_0:
    489 			hnd->yuv_info = MALI_YUV_BT709_NARROW;
    490 			break;
    491 
    492 		case (GRALLOC_USAGE_PRIVATE_0 | GRALLOC_USAGE_PRIVATE_1):
    493 			hnd->yuv_info = MALI_YUV_BT709_WIDE;
    494 			break;
    495 	}
    496 
    497 	hnd->width = w;
    498 	hnd->height = h;
    499 	hnd->format = format;
    500 	hnd->stride = stride;
    501 
    502 	*pStride = stride;
    503 	return 0;
    504 }
    505 
    506 static int alloc_device_free(alloc_device_t *dev, buffer_handle_t handle)
    507 {
    508 	if (private_handle_t::validate(handle) < 0)
    509 	{
    510 		return -EINVAL;
    511 	}
    512 
    513 	private_handle_t const *hnd = reinterpret_cast<private_handle_t const *>(handle);
    514 
    515 	if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)
    516 	{
    517 		// free this buffer
    518 		private_module_t *m = reinterpret_cast<private_module_t *>(dev->common.module);
    519 		const size_t bufferSize = m->finfo.line_length * m->info.yres;
    520 		int index = ((uintptr_t)hnd->base - (uintptr_t)m->framebuffer->base) / bufferSize;
    521 		m->bufferMask &= ~(1 << index);
    522 
    523 #if GRALLOC_ARM_UMP_MODULE
    524 
    525 		if ((int)UMP_INVALID_MEMORY_HANDLE != hnd->ump_mem_handle)
    526 		{
    527 			ump_reference_release((ump_handle)hnd->ump_mem_handle);
    528 		}
    529 
    530 #endif
    531 	}
    532 	else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_UMP)
    533 	{
    534 #if GRALLOC_ARM_UMP_MODULE
    535 
    536 		/* Buffer might be unregistered so we need to check for invalid ump handle*/
    537 		if ((int)UMP_INVALID_MEMORY_HANDLE != hnd->ump_mem_handle)
    538 		{
    539 			ump_mapped_pointer_release((ump_handle)hnd->ump_mem_handle);
    540 			ump_reference_release((ump_handle)hnd->ump_mem_handle);
    541 		}
    542 
    543 #else
    544 		AERR("Can't free ump memory for handle:0x%p. Not supported.", hnd);
    545 #endif
    546 	}
    547 	else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION)
    548 	{
    549 #if GRALLOC_ARM_DMA_BUF_MODULE
    550 		private_module_t *m = reinterpret_cast<private_module_t *>(dev->common.module);
    551 
    552 		/* Buffer might be unregistered so we need to check for invalid ump handle*/
    553 		if (0 != hnd->base)
    554 		{
    555 			if (0 != munmap((void *)hnd->base, hnd->size))
    556 			{
    557 				AERR("Failed to munmap handle 0x%p", hnd);
    558 			}
    559 		}
    560 
    561 		close(hnd->share_fd);
    562 
    563 		memset((void *)hnd, 0, sizeof(*hnd));
    564 #else
    565 		AERR("Can't free dma_buf memory for handle:0x%x. Not supported.", (unsigned int)hnd);
    566 #endif
    567 
    568 	}
    569 
    570 	delete hnd;
    571 
    572 	return 0;
    573 }
    574 
    575 static int alloc_device_close(struct hw_device_t *device)
    576 {
    577 	alloc_device_t *dev = reinterpret_cast<alloc_device_t *>(device);
    578 
    579 	if (dev)
    580 	{
    581 #if GRALLOC_ARM_DMA_BUF_MODULE
    582 		private_module_t *m = reinterpret_cast<private_module_t *>(device);
    583 
    584 		if (0 != ion_close(m->ion_client))
    585 		{
    586 			AERR("Failed to close ion_client: %d", m->ion_client);
    587 		}
    588 
    589 		close(m->ion_client);
    590 #endif
    591 		delete dev;
    592 #if GRALLOC_ARM_UMP_MODULE
    593 		ump_close(); // Our UMP memory refs will be released automatically here...
    594 #endif
    595 	}
    596 
    597 	return 0;
    598 }
    599 
    600 int alloc_device_open(hw_module_t const *module, const char *name, hw_device_t **device)
    601 {
    602 	MALI_IGNORE(name);
    603 	alloc_device_t *dev;
    604 
    605 	dev = new alloc_device_t;
    606 
    607 	if (NULL == dev)
    608 	{
    609 		return -1;
    610 	}
    611 
    612 #if GRALLOC_ARM_UMP_MODULE
    613 	ump_result ump_res = ump_open();
    614 
    615 	if (UMP_OK != ump_res)
    616 	{
    617 		AERR("UMP open failed with %d", ump_res);
    618 		delete dev;
    619 		return -1;
    620 	}
    621 
    622 #endif
    623 
    624 	/* initialize our state here */
    625 	memset(dev, 0, sizeof(*dev));
    626 
    627 	/* initialize the procs */
    628 	dev->common.tag = HARDWARE_DEVICE_TAG;
    629 	dev->common.version = 0;
    630 	dev->common.module = const_cast<hw_module_t *>(module);
    631 	dev->common.close = alloc_device_close;
    632 	dev->alloc = alloc_device_alloc;
    633 	dev->free = alloc_device_free;
    634 
    635 #if GRALLOC_ARM_DMA_BUF_MODULE
    636 	private_module_t *m = reinterpret_cast<private_module_t *>(dev->common.module);
    637 	m->ion_client = ion_open();
    638 
    639 	if (m->ion_client < 0)
    640 	{
    641 		AERR("ion_open failed with %s", strerror(errno));
    642 		delete dev;
    643 		return -1;
    644 	}
    645 
    646 #endif
    647 
    648 	*device = &dev->common;
    649 
    650 	return 0;
    651 }
    652