lineage_kernel_xcoverpro/drivers/vision/vipx/vipx-core.c

344 lines
7.3 KiB
C
Executable File

/*
* Samsung Exynos SoC series VIPx driver
*
* Copyright (c) 2018 Samsung Electronics Co., Ltd
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include "vipx-log.h"
#include "vipx-util.h"
#include "vipx-ioctl.h"
#include "vipx-device.h"
#include "vipx-graph.h"
#include "vipx-context.h"
#include "vipx-core.h"
static int vipx_core_load_kernel_binary(struct vipx_context *vctx,
struct vipx_ioc_load_kernel_binary *args)
{
int ret;
vipx_enter();
if (mutex_lock_interruptible(&vctx->lock)) {
ret = -ERESTARTSYS;
vipx_err("Failed to lock for loading kernel binary (%d)\n",
ret);
goto p_err_lock;
}
ret = vctx->vops->load_kernel_binary(vctx, args);
if (ret)
goto p_err_vops;
mutex_unlock(&vctx->lock);
args->ret = 0;
vipx_leave();
return 0;
p_err_vops:
mutex_unlock(&vctx->lock);
p_err_lock:
args->ret = ret;
vipx_err("Failed to load kernel binary(%d)\n", ret);
/* return value is included in args->ret */
return 0;
}
static int vipx_core_unload_kernel_binary(struct vipx_context *vctx,
struct vipx_ioc_unload_kernel_binary *args)
{
int ret;
vipx_enter();
if (mutex_lock_interruptible(&vctx->lock)) {
ret = -ERESTARTSYS;
vipx_err("Failed to lock for loading kernel binary (%d)\n",
ret);
goto p_err_lock;
}
ret = vctx->vops->unload_kernel_binary(vctx, args);
if (ret)
goto p_err_vops;
mutex_unlock(&vctx->lock);
args->ret = 0;
vipx_leave();
return 0;
p_err_vops:
mutex_unlock(&vctx->lock);
p_err_lock:
args->ret = ret;
vipx_err("Failed to unload kernel binary(%d)\n", ret);
/* return value is included in args->ret */
return 0;
}
static int vipx_core_load_graph_info(struct vipx_context *vctx,
struct vipx_ioc_load_graph_info *args)
{
int ret;
vipx_enter();
if (mutex_lock_interruptible(&vctx->lock)) {
ret = -ERESTARTSYS;
vipx_err("Failed to lock for loadding graph info (%d)\n", ret);
goto p_err_lock;
}
ret = vctx->vops->load_graph_info(vctx, args);
if (ret)
goto p_err_vops;
mutex_unlock(&vctx->lock);
args->ret = 0;
vipx_leave();
return 0;
p_err_vops:
mutex_unlock(&vctx->lock);
p_err_lock:
args->ret = ret;
vipx_err("Failed to load graph(%d)\n", ret);
/* return value is included in args->ret */
return 0;
}
static int vipx_core_unload_graph_info(struct vipx_context *vctx,
struct vipx_ioc_unload_graph_info *args)
{
int ret;
vipx_enter();
if (mutex_lock_interruptible(&vctx->lock)) {
ret = -ERESTARTSYS;
vipx_err("Failed to lock for unloading graph info (%d)\n", ret);
goto p_err_lock;
}
ret = vctx->vops->unload_graph_info(vctx, args);
if (ret)
goto p_err_vops;
mutex_unlock(&vctx->lock);
args->ret = 0;
vipx_leave();
return 0;
p_err_vops:
mutex_unlock(&vctx->lock);
p_err_lock:
args->ret = ret;
vipx_err("Failed to unload graph(%d)\n", ret);
/* return value is included in args->ret */
return 0;
}
static int vipx_core_execute_submodel(struct vipx_context *vctx,
struct vipx_ioc_execute_submodel *args)
{
int ret;
vipx_enter();
if (mutex_lock_interruptible(&vctx->lock)) {
ret = -ERESTARTSYS;
vipx_err("Failed to lock for executing submodel (%d)\n", ret);
goto p_err_lock;
}
ret = vctx->vops->execute_submodel(vctx, args);
if (ret)
goto p_err_vops;
mutex_unlock(&vctx->lock);
args->ret = 0;
vipx_leave();
return 0;
p_err_vops:
mutex_unlock(&vctx->lock);
p_err_lock:
args->ret = ret;
vipx_err("Failed to execute submodel(%d)\n", ret);
/* return value is included in args->ret */
return 0;
}
const struct vipx_ioctl_ops vipx_core_ioctl_ops = {
.load_kernel_binary = vipx_core_load_kernel_binary,
.unload_kernel_binary = vipx_core_unload_kernel_binary,
.load_graph_info = vipx_core_load_graph_info,
.unload_graph_info = vipx_core_unload_graph_info,
.execute_submodel = vipx_core_execute_submodel,
};
static int vipx_open(struct inode *inode, struct file *file)
{
int ret;
struct miscdevice *miscdev;
struct vipx_device *vdev;
struct vipx_core *core;
struct vipx_context *vctx;
struct vipx_graph *graph;
vipx_enter();
miscdev = file->private_data;
vdev = dev_get_drvdata(miscdev->parent);
core = &vdev->core;
if (mutex_lock_interruptible(&core->lock)) {
ret = -ERESTARTSYS;
vipx_err("Failed to lock device lock for open (%d)\n", ret);
goto p_err_lock;
}
ret = vipx_device_open(vdev);
if (ret)
goto p_err_device_open;
ret = vipx_device_start(vdev);
if (ret)
goto p_err_device_start;
vctx = vipx_context_create(core);
if (IS_ERR(vctx)) {
ret = PTR_ERR(vctx);
goto p_err_vctx;
}
graph = vipx_graph_create(vctx, &core->system->graphmgr);
if (IS_ERR(graph)) {
ret = PTR_ERR(graph);
goto p_err_graph;
}
vctx->graph = graph;
file->private_data = vctx;
mutex_unlock(&core->lock);
vipx_info("The vipx has been successfully opened(count:%d)\n",
vdev->open_count);
vipx_leave();
return 0;
p_err_graph:
p_err_vctx:
vipx_device_stop(vdev);
p_err_device_start:
vipx_device_close(vdev);
p_err_device_open:
mutex_unlock(&core->lock);
vipx_err("Failed to open the vipx(count:%d)(%d)\n",
vdev->open_count, ret);
p_err_lock:
return ret;
}
static int vipx_release(struct inode *inode, struct file *file)
{
int ret;
struct vipx_context *vctx;
struct vipx_core *core;
vipx_enter();
vctx = file->private_data;
core = vctx->core;
if (mutex_lock_interruptible(&core->lock)) {
ret = -ERESTARTSYS;
vipx_err("Failed to lock device lock for release (%d)\n", ret);
return ret;
}
vipx_graph_destroy(vctx->graph);
vipx_context_destroy(vctx);
vipx_device_stop(core->device);
vipx_device_close(core->device);
mutex_unlock(&core->lock);
vipx_info("The vipx has been closed(count:%d)\n",
core->device->open_count);
vipx_leave();
return 0;
}
static unsigned int vipx_poll(struct file *file, struct poll_table_struct *poll)
{
int ret;
struct vipx_context *vctx;
vipx_enter();
vctx = file->private_data;
if (!(vctx->state & BIT(VIPX_CONTEXT_START))) {
ret = POLLERR;
vipx_err("Context state(%x) is not start (%d)\n",
vctx->state, ret);
goto p_err;
}
ret = vctx->queue_ops->poll(&vctx->queue_list, file, poll);
if (ret)
goto p_err;
vipx_leave();
return 0;
p_err:
return ret;
}
const struct file_operations vipx_file_ops = {
.owner = THIS_MODULE,
.open = vipx_open,
.release = vipx_release,
.poll = vipx_poll,
.unlocked_ioctl = vipx_ioctl,
.compat_ioctl = vipx_compat_ioctl
};
/* Top-level data for debugging */
static struct vipx_miscdev *misc_vdev;
int vipx_core_probe(struct vipx_device *vdev)
{
int ret;
struct vipx_core *core;
vipx_enter();
core = &vdev->core;
core->device = vdev;
core->system = &vdev->system;
misc_vdev = &core->misc_vdev;
mutex_init(&core->lock);
core->ioc_ops = &vipx_core_ioctl_ops;
vipx_util_bitmap_init(core->vctx_map, VIPX_MAX_CONTEXT);
INIT_LIST_HEAD(&core->vctx_list);
core->vctx_count = 0;
core->misc_vdev.miscdev.minor = MISC_DYNAMIC_MINOR;
core->misc_vdev.miscdev.name = VIPX_DEV_NAME;
core->misc_vdev.miscdev.fops = &vipx_file_ops;
core->misc_vdev.miscdev.parent = vdev->dev;
ret = misc_register(&core->misc_vdev.miscdev);
if (ret) {
vipx_err("miscdevice is not registered (%d)\n", ret);
goto p_err_misc;
}
vipx_leave();
return 0;
p_err_misc:
mutex_destroy(&core->lock);
return ret;
}
void vipx_core_remove(struct vipx_core *core)
{
vipx_enter();
misc_deregister(&core->misc_vdev.miscdev);
mutex_destroy(&core->lock);
vipx_leave();
}