kernel_samsung_a34x-permissive/drivers/misc/mediatek/jpeg/v2/jpeg_ion.c
2024-04-28 15:49:01 +02:00

241 lines
5 KiB
C
Executable file

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2020 MediaTek Inc.
*/
#include "jpeg_ion.h"
#include "jpeg_drv_common.h"
#include <ion_drv.h>
#ifdef CONFIG_MTK_IOMMU_V2
#include "mach/mt_iommu.h"
#include "mach/pseudo_m4u.h"
#include <soc/mediatek/smi.h>
#include "mtk_iommu_ext.h"
#include "mtk_ion.h"
#endif
#if defined(CONFIG_MTK_IOMMU_V2)
static struct ion_client *g_jpg_ion_client;
#endif
extern int jpg_dbg_level;
int jpg_ion_get_iova(struct ion_handle *handle,
u64 *iova, int port)
{
#if defined(CONFIG_MTK_IOMMU_V2)
struct ion_mm_data mm_data;
size_t iova_size;
memset((void *)&mm_data, 0, sizeof(struct ion_mm_data));
mm_data.mm_cmd = ION_MM_GET_IOVA;
mm_data.get_phys_param.module_id = port;
mm_data.get_phys_param.kernel_handle = handle;
if (ion_kernel_ioctl(g_jpg_ion_client, ION_CMD_MULTIMEDIA,
(unsigned long)&mm_data) < 0) {
JPEG_LOG(0, "get iova failed.%p -%p\n",
g_jpg_ion_client, handle);
ion_free(g_jpg_ion_client, handle);
return -1;
}
*iova = mm_data.get_phys_param.phy_addr;
iova_size = mm_data.get_phys_param.len;
if (*iova == 0)
JPEG_LOG(0, "alloc mmu addr hnd=0x%p,iova=0x%08lx\n",
handle, *iova);
JPEG_LOG(1, "iova: %llu", *iova);
#endif
return 0;
}
struct ion_handle *jpg_ion_import_handle(int fd)
{
struct ion_handle *handle = NULL;
#if defined(CONFIG_MTK_IOMMU_V2)
/* If no need Ion support, do nothing! */
if (fd <= 0) {
JPEG_LOG(0, "NO NEED ion support, fd %d\n", fd);
return handle;
}
if (!g_jpg_ion_client) {
JPEG_LOG(0, "invalid ion client!");
return handle;
}
handle = ion_import_dma_buf_fd(g_jpg_ion_client, fd);
if (IS_ERR(handle)) {
JPEG_LOG(0, "import ion handle failed!");
return NULL;
}
JPEG_LOG(1, "import ion handle fd=%d, hnd=0x%p", fd, handle);
#endif
return handle;
}
struct ion_handle *jpg_ion_alloc_handle(size_t size, size_t align, unsigned int flags)
{
struct ion_handle *handle = NULL;
#if defined(CONFIG_MTK_IOMMU_V2)
if (!g_jpg_ion_client) {
JPEG_LOG(0, "invalid ion client!");
return handle;
}
handle = ion_alloc(g_jpg_ion_client, size, align, ION_HEAP_MULTIMEDIA_MASK, flags);
if (IS_ERR(handle)) {
JPEG_LOG(0, "alloc ion handle failed!");
return NULL;
}
JPEG_LOG(1, "alloc ion handle hnd=0x%p", handle);
#endif
return handle;
}
int jpg_ion_share_handle(struct ion_handle *handle)
{
int fd = -1;
#if defined(CONFIG_MTK_IOMMU_V2)
if (!g_jpg_ion_client) {
JPEG_LOG(0, "invalid ion client!");
return -1;
}
fd = ion_share_dma_buf_fd(g_jpg_ion_client, handle);
if (fd < 0) {
JPEG_LOG(0, "share ion handle failed!");
return -1;
}
JPEG_LOG(1, "share ion handle hnd=0x%p fd:%d", handle, fd);
#endif
return fd;
}
void *jpg_ion_map_handle(struct ion_handle *handle)
{
void *ptr = NULL;
#if defined(CONFIG_MTK_IOMMU_V2)
if (!g_jpg_ion_client) {
JPEG_LOG(0, "invalid ion client!");
return NULL;
}
ptr = ion_map_kernel(g_jpg_ion_client, handle);
if (ptr == NULL) {
JPEG_LOG(0, "map ion handle failed!");
return NULL;
}
JPEG_LOG(1, "map ion handle hnd=0x%p ptr:%p", handle, ptr);
#endif
return ptr;
}
void jpg_ion_unmap_handle(struct ion_handle *handle)
{
#if defined(CONFIG_MTK_IOMMU_V2)
if (!g_jpg_ion_client) {
JPEG_LOG(0, "invalid ion client!");
return;
}
ion_unmap_kernel(g_jpg_ion_client, handle);
JPEG_LOG(1, "unmap ion handle hnd=0x%p fd:%d", handle);
#endif
}
void jpg_ion_free_handle(struct ion_handle *handle)
{
#if defined(CONFIG_MTK_IOMMU_V2)
if (!g_jpg_ion_client) {
JPEG_LOG(0, "invalid ion client!");
return;
}
if (!handle)
return;
ion_free(g_jpg_ion_client, handle);
JPEG_LOG(1, "handle 0x%p", handle);
#endif
}
void jpg_ion_cache_flush(struct ion_handle *handle)
{
#if defined(CONFIG_MTK_IOMMU_V2)
struct ion_sys_data sys_data;
void *buffer_va;
if (!g_jpg_ion_client || !handle)
return;
sys_data.sys_cmd = ION_SYS_CACHE_SYNC;
sys_data.cache_sync_param.kernel_handle = handle;
sys_data.cache_sync_param.sync_type = ION_CACHE_INVALID_BY_RANGE;
buffer_va = ion_map_kernel(g_jpg_ion_client, handle);
sys_data.cache_sync_param.va = buffer_va;
sys_data.cache_sync_param.size = handle->buffer->size;
if (ion_kernel_ioctl(g_jpg_ion_client, ION_CMD_SYSTEM,
(unsigned long)&sys_data))
JPEG_LOG(0, "ion cache flush failed!");
ion_unmap_kernel(g_jpg_ion_client, handle);
#endif
}
void jpg_ion_create(const char *name)
{
#if defined(CONFIG_MTK_IOMMU_V2)
if (g_ion_device)
g_jpg_ion_client = ion_client_create(g_ion_device, name);
else
JPEG_LOG(0, "invalid g_ion_device");
if (!g_jpg_ion_client)
JPEG_LOG(0, "create ion client failed!");
#endif
}
void jpg_ion_destroy(void)
{
#if defined(CONFIG_MTK_IOMMU_V2)
if (g_jpg_ion_client && g_ion_device)
ion_client_destroy(g_jpg_ion_client);
#endif
}
u64 jpg_translate_fd(u64 fd, u32 offset, u32 port)
{
struct ion_handle *ion_h;
u64 iova = 0;
/* need to map ion handle and iova */
ion_h = jpg_ion_import_handle(fd);
if (!ion_h)
return 0;
jpg_ion_get_iova(ion_h, &iova, port);
iova += offset;
jpg_ion_free_handle(ion_h);
JPEG_LOG(1, "iova 0x%llx", iova);
return iova;
}