| /* |
| * Copyright (c) 2014 Amlogic, Inc. All rights reserved. |
| * |
| * This source code is subject to the terms and conditions defined in the |
| * file 'LICENSE' which is part of this source code package. |
| * |
| * Description: |
| */ |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <sys/mman.h> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <sys/ioctl.h> |
| #include <fcntl.h> |
| #include <errno.h> |
| #include <string.h> |
| #include <ion/IONmem.h> |
| #include <ion/ion.h> |
| #include <linux/ion.h> |
| #include "ion_4.12.h" |
| |
| #ifdef __DEBUG |
| #define __D(fmt, args...) printf("ionmem debug: " fmt, ## args) |
| #else |
| #define __D(fmt, args...) |
| #endif |
| |
| #define __E(fmt, args...) printf("ionmem error: " fmt, ## args) |
| |
| int ion_mem_init(void) |
| { |
| int ion_fd = -1; |
| ion_fd = ion_open(); |
| |
| if (ion_fd < 0) { |
| __E("%s failed: '%s'\n", __func__, strerror(errno)); |
| return -1; |
| } |
| __D("%s, ion_fd=%d\n", __func__, ion_fd); |
| |
| return ion_fd; |
| } |
| |
| int ion_mem_alloc_fd(int ion_fd, size_t size, IONMEM_AllocParams *params, unsigned int flag, unsigned int alloc_hmask) |
| { |
| int ret = 0; |
| int num_heaps = 0; |
| unsigned int heap_mask = 0; |
| |
| ret = ion_query_heap_cnt(ion_fd, &num_heaps); |
| if (ret < 0) { |
| __E("ion_query_heap_cnt fail! no ion heaps for alloc!!!\n"); |
| return -ENOMEM; |
| } |
| |
| __D("num_heaps=%d\n", num_heaps); |
| struct ion_heap_data *const heaps = (struct ion_heap_data *)malloc(num_heaps * sizeof(struct ion_heap_data)); |
| if (num_heaps <= 0 || heaps == NULL) { |
| free(heaps); |
| __E("heaps is NULL or no heaps,num_heaps=%d\n", num_heaps); |
| return -ENOMEM; |
| } |
| |
| ret = ion_query_get_heaps(ion_fd, num_heaps, heaps); |
| if (ret < 0) { |
| free(heaps); |
| __E("ion_query_get_heaps fail! no ion heaps for alloc!!!\n"); |
| return -ENOMEM; |
| } |
| |
| for (int i = 0; i != num_heaps; ++i) { |
| __D("heaps[%d].type=%d, heap_id=%d\n", i, heaps[i].type, heaps[i].heap_id); |
| if ((1 << heaps[i].type) == alloc_hmask) { |
| heap_mask = 1 << heaps[i].heap_id; |
| __D("%d, m=%x, 1<<heap_id=%x, heap_mask=%x, name=%s, alloc_hmask=%x\n", |
| heaps[i].type, 1<<heaps[i].type, heaps[i].heap_id, heap_mask, heaps[i].name, alloc_hmask); |
| break; |
| } |
| } |
| |
| free(heaps); |
| if (heap_mask == 0) { |
| __E("don't find match heap!!\n"); |
| return -ENOMEM; |
| } |
| |
| ret = ion_alloc_fd(ion_fd, size, 0, heap_mask, flag, ¶ms->mImageFd); |
| if (ret < 0) { |
| __E("ion_alloc failed, errno=%d\n", errno); |
| return -ENOMEM; |
| } |
| |
| return 0; |
| } |
| |
| unsigned long ion_mem_alloc(int ion_fd, size_t size, IONMEM_AllocParams *params, bool cache_flag) |
| { |
| int ret = -1; |
| int legacy_ion = 0; |
| unsigned flag = 0; |
| |
| legacy_ion = ion_is_legacy(ion_fd); |
| |
| if (cache_flag) { |
| flag = ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC; |
| } |
| __D("%s, cache=%d, bytes=%d, legacy_ion=%d, flag=0x%x\n", |
| __func__, cache_flag, size, legacy_ion, flag); |
| |
| if (legacy_ion == 1) { |
| if (!cache_flag) { |
| ret = ion_alloc(ion_fd, size, 0, ION_HEAP_TYPE_DMA_MASK, flag, |
| ¶ms->mIonHnd); |
| if (ret < 0) |
| ret = ion_alloc(ion_fd, size, 0, ION_HEAP_CARVEOUT_MASK, flag, |
| ¶ms->mIonHnd); |
| } |
| if (ret < 0) { |
| ret = ion_alloc(ion_fd, size, 0, 1 << ION_HEAP_TYPE_CUSTOM, flag, |
| ¶ms->mIonHnd); |
| if (ret < 0) { |
| __E("%s failed, errno=%d\n", __func__, errno); |
| return -ENOMEM; |
| } |
| } |
| |
| ret = ion_share(ion_fd, params->mIonHnd, ¶ms->mImageFd); |
| if (ret < 0) { |
| __E("ion_share failed, errno=%d\n", errno); |
| ion_free(ion_fd, params->mIonHnd); |
| return -EINVAL; |
| } |
| ion_free(ion_fd, params->mIonHnd); |
| } else { |
| flag |= ION_FLAG_EXTEND_MESON_HEAP; |
| ret = ion_mem_alloc_fd(ion_fd, size, params, flag, |
| ION_HEAP_TYPE_DMA_MASK); |
| if (ret < 0) |
| ret = ion_mem_alloc_fd(ion_fd, size, params, flag, |
| ION_HEAP_CARVEOUT_MASK); |
| if (ret < 0) |
| ret = ion_mem_alloc_fd(ion_fd, size, params, flag, |
| ION_HEAP_TYPE_CUSTOM); |
| if (ret < 0) { |
| __E("%s failed, errno=%d\n", __func__, errno); |
| return -ENOMEM; |
| } |
| } |
| |
| __D("%s okay done!, legacy_ion=%d\n", __func__, legacy_ion); |
| __D("%s, shared_fd=%d\n", __func__, params->mImageFd); |
| |
| return ret; |
| } |
| |
| int ion_mem_sync_cache(int ion_fd, int shared_fd) |
| { |
| int legacy_ion = 0; |
| |
| legacy_ion = ion_is_legacy(ion_fd); |
| if (!legacy_ion) |
| return 0; |
| if (ion_fd >= 0 && shared_fd >= 0) { |
| if (ion_sync_fd(ion_fd, shared_fd)) { |
| __E("ion_mem_sync_cache err!\n"); |
| return -1; |
| } |
| } else { |
| __E("ion_mem_sync_cache err!\n"); |
| return -1; |
| } |
| return 0; |
| } |
| |
| int ion_mem_invalid_cache(int ion_fd, int shared_fd) |
| { |
| int legacy_ion = 0; |
| |
| legacy_ion = ion_is_legacy(ion_fd); |
| if (!legacy_ion) |
| return 0; |
| if (ion_fd >= 0 && shared_fd >= 0) { |
| if (ion_cache_invalid(ion_fd, shared_fd)) { |
| __E("ion_mem_invalid_cache err!\n"); |
| return -1; |
| } |
| } else { |
| __E("ion_mem_invalid_cache err!\n"); |
| return -1; |
| } |
| return 0; |
| } |
| |
| void ion_mem_exit(int ion_fd) |
| { |
| int ret = -1; |
| |
| __D("exit: %s, ion_fd=%d\n", __func__, ion_fd); |
| |
| ret = ion_close(ion_fd); |
| if (ret < 0) { |
| __E("%s err (%s)! ion_fd=%d\n", __func__, strerror(errno), ion_fd); |
| return; |
| } |
| } |
| |