blob: 4a025b947c07b19f2a4e6af2b1e704d0e4915558 [file] [log] [blame]
/*
* include/media/m2m1shot.h
*
* Copyright (C) 2014 Samsung Electronics Co., Ltd.
*
* Contact: Cho KyongHo <pullip.cho@samsung.com>
*
* 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.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#ifndef _M2M1SHOT_H_
#define _M2M1SHOT_H_
#include <linux/kernel.h>
#include <linux/videodev2.h>
#include <linux/list.h>
#include <linux/miscdevice.h>
#include <linux/dma-direction.h>
#include <linux/kref.h>
#include <linux/completion.h>
#include <uapi/linux/m2m1shot.h>
struct m2m1shot_devops;
struct m2m1shot_task;
/**
* struct m2m1shot_device
*
* @misc : misc device desciptor for user-kernel interface
* @tasks : the list of the tasks that are to be scheduled
* @contexts : the list of the contexts that is created for this device
* @dev : the client device desciptor
* @lock_task : lock to protect the consistency of @tasks list and
* @current_task
* @lock_ctx : lock to protect the consistency of @contexts list
* @timeout_jiffies: timeout jiffoes for a task. If a task is not finished
* until @timeout_jiffies elapsed,
* m2m1shot_devops.timeout_task() is invoked an the task
* is canced. The user will get an error.
* @current_task: indicate the task that is currently being processed
* @ops : callback functions that the client device driver must
* implement according to the events.
*/
struct m2m1shot_device {
struct miscdevice misc;
struct list_head tasks; /* pending tasks for processing */
struct list_head contexts; /* created contexts of this device */
struct device *dev;
spinlock_t lock_task; /* lock with irqsave for tasks */
spinlock_t lock_ctx; /* lock for contexts */
unsigned long timeout_jiffies; /* timeout jiffies for a task */
struct m2m1shot_task *current_task; /* current working task */
const struct m2m1shot_devops *ops;
};
/**
* struct m2m1shot_context - context of tasks
*
* @node : node entry to m2m1shot_device.contexts
* @mutex : lock to prevent racing between tasks between the same contexts
* @kref : usage count of the context not to release the context while a
* : task being processed.
* @m21dev : the singleton device instance that the context is born
* @priv : private data that is allowed to store client drivers' private
* data
*/
struct m2m1shot_context {
struct list_head node;
struct mutex mutex;
struct kref kref;
struct m2m1shot_device *m21dev;
void *priv;
};
/**
* enum m2m1shot_state - state of a task
*
* @M2M1SHOT_BUFSTATE_READY : Task is verified and scheduled for processing
* @M2M1SHOT_BUFSTATE_PROCESSING: Task is being processed by H/W.
* @M2M1SHOT_BUFSTATE_DONE : Task is completed.
* @M2M1SHOT_BUFSTATE_TIMEDOUT : Task is not completed until a timed out value
* @M2M1SHOT_BUFSTATE_ERROR: : Task is not processed due to verification
* failure
*/
enum m2m1shot_state {
M2M1SHOT_BUFSTATE_READY,
M2M1SHOT_BUFSTATE_PROCESSING,
M2M1SHOT_BUFSTATE_DONE,
M2M1SHOT_BUFSTATE_TIMEDOUT,
M2M1SHOT_BUFSTATE_ERROR,
};
/**
* struct m2m1shot_buffer_plane_dma - descriptions of a buffer
*
* @bytes_used : the size of the buffer that is accessed by H/W. This is filled
* by the client device driver when
* m2m1shot_devops.prepare_format() is called.
* @dmabuf : pointer to dmabuf descriptor if the buffer type is
* M2M1SHOT_BUFFER_DMABUF.
* @attachment : pointer to dmabuf attachment descriptor if the buffer type is
* M2M1SHOT_BUFFER_DMABUF.
* @sgt : scatter-gather list that describes physical memory information
* : of the buffer
* @dma_addr : DMA address that is the address of the buffer in the H/W's
* : address space.
* @priv : the client device driver's private data
*/
struct m2m1shot_buffer_plane_dma {
size_t bytes_used;
struct dma_buf *dmabuf;
struct dma_buf_attachment *attachment;
struct sg_table *sgt;
dma_addr_t dma_addr;
void *priv;
off_t offset;
};
/**
* struct m2m1shot_buffer_dma - description of buffers for a task
*
* @buffers : pointer to m2m1shot.buf_out or m2m1shot.buf_cap that are specified
* by user
* @plane : descriptions of buffers to pin the buffers while the task is
* processed.
*/
struct m2m1shot_buffer_dma {
/* pointer to m2m1shot_task.task.buf_out/cap */
const struct m2m1shot_buffer *buffer;
struct m2m1shot_buffer_plane_dma plane[M2M1SHOT_MAX_PLANES];
};
/**
* struct m2m1shot_task - describes a task to process
*
* @task : descriptions about the frames and format to process
* @task_node : list entry to m2m1shot_device.tasks
* @ctx : pointer to m2m1shot_context that the task is valid under.
* @complete : waiter to finish the task
* @dma_buf_out : descriptions of the capture buffers
* @dma_buf_cap : descriptions of the output buffers
* @state : state of the task
*/
struct m2m1shot_task {
struct m2m1shot task;
struct list_head task_node;
struct m2m1shot_context *ctx;
struct completion complete;
struct m2m1shot_buffer_dma dma_buf_out;
struct m2m1shot_buffer_dma dma_buf_cap;
enum m2m1shot_state state;
};
/**
* struct vb2_mem_ops - memory handling/memory allocator operations
*
* @init_context: [MANDATORY]
* called on creation of struct m2m1shot_context to give a chance
* to the driver for registering the driver's private data.
* New m2m1shot_context is created when user opens a device node
* of m2m1shot.
* @free_context: [MANDATORY]
* called on destruction of struct m2m1shot_context to inform
* the driver for unregistring the driver's private data.
* m2m1shot_context is destroyed when a user releases all
* references to the open file of the device node of m2m1shot.
* @prepare_format: [MANDATORY]
* called on user's request to process a task. The driver
* receives the format and resolutions of the images to
* process, should return the sizes in bytes and the number of
* buffers(planes) that the driver needs to process the images.
* @prepare_operation [OPTIONAL]
* called after format checking is finished. The drivers can
* check or prepare the followings:
* - scaling constraint check
* - constructing private or constext data
* @prepare_buffer: [MANDATORY]
* called after all size validation are passed. The driver
* should complete all procedures for safe access by H/W
* accelerators to process the given buffers.
* @finish_buffer: [MANDATORY]
* called after the task is finished to release all references
* to the buffers. The drivers should release all resources
* related to the buffer. This is called for every buffers that
* is called @prepare_buffer regardless of the processing the
* task is successful.
* @device_run: [MANDATORY]
* called on the time of the processing the given task. The driver
* should run H/W. The driver does not wait for an IRQ.
* @timeout_task: [MANDATORY]
* called when timed out of processing of the given task. The
* driver can reset the H/W to cancle the current task.
* @custom_ioctl: [OPTIONAL]
* The driver can directly interact with this @custom_ioctl.
*/
struct m2m1shot_devops {
int (*init_context)(struct m2m1shot_context *ctx);
int (*free_context)(struct m2m1shot_context *ctx);
/* return value: number of planes */
int (*prepare_format)(struct m2m1shot_context *ctx,
struct m2m1shot_pix_format *fmt,
enum dma_data_direction dir,
size_t bytes_used[]);
int (*prepare_operation)(struct m2m1shot_context *ctx,
struct m2m1shot_task *task);
int (*prepare_buffer)(struct m2m1shot_context *ctx,
struct m2m1shot_buffer_dma *dma_buffer,
int plane,
enum dma_data_direction dir);
void (*finish_buffer)(struct m2m1shot_context *ctx,
struct m2m1shot_buffer_dma *dma_buffer,
int plane,
enum dma_data_direction dir);
int (*device_run)(struct m2m1shot_context *ctx,
struct m2m1shot_task *task);
void (*timeout_task)(struct m2m1shot_context *ctx,
struct m2m1shot_task *task);
/* optional */
long (*custom_ioctl)(struct m2m1shot_context *ctx,
unsigned int cmd, unsigned long arg);
};
/**
* m2m1shot_task_finish - notify a task is finishes and schedule new task
*
* - m21dev: pointer to struct m2m1shot_device
* - task: The task that is finished
* - success: true if task is processed successfully, false otherwise.
*
* This function wakes up the process that is waiting for the completion of
* @task. An IRQ handler is the best place to call this function. If @error
* is true, the user that requested @task will receive an error.
*/
void m2m1shot_task_finish(struct m2m1shot_device *m21dev,
struct m2m1shot_task *task, bool error);
/**
* m2m1shot_task_cancel - cancel a task and schedule the next task
*
* - m21dev: pointer to struct m2m1shot_device
* - task: The task that is finished
* - reason: the reason of canceling the task
*
* This function is called by the driver that wants to cancel @task and
* schedule the next task. Most drivers do not need to call this function.
* Keep in mind that this function does not wake up the process that is blocked
* for the completion of @task.
*/
void m2m1shot_task_cancel(struct m2m1shot_device *m21dev,
struct m2m1shot_task *task,
enum m2m1shot_state reason);
/**
* m2m1shot_create_device - create and initialze constructs for m2m1shot
*
* - dev: the device that m2m1shot provides services
* - ops: callbacks to m2m1shot
* - suffix: suffix of device node in /dev after 'm2m1shot_'
* - id: device instance number if a device has multiple instance. @id will be
* attached after @suffix. If @id is -1, no instance number is attached to
* @suffix.
* - timeout_jiffies: timeout jiffies for a task being processed. For 0,
* m2m1shot waits for completion of a task infinitely.
*
* Returns the pointer to struct m2m1shot_device on success.
* Returns -error on failure.
* This function is most likely called in probe() of a driver.
*/
struct m2m1shot_device *m2m1shot_create_device(struct device *dev,
const struct m2m1shot_devops *ops,
const char *suffix, int id,
unsigned long timeout_jiffies);
/**
* m2m1shot_destroy_device - destroy all constructs for m2m1shot
*
* m21dev - pointer to struct m2m1shot_device that is returned by
* m2m1shot_create_device()
*
* The driver that has a valid pointer to struct m2m1shot_device returned by
* m2m1shot_create_device() must call m2m1shot_destroy_device() before removing
* the driver.
*/
void m2m1shot_destroy_device(struct m2m1shot_device *m21dev);
/**
* m2m1shot_get_current_task - request the current task under processing
*
* m21dev - pointer to struct m2m1shot_device.
*
* Returns the pointer to struct m2m1shot_task that is processed by the device
* whose driver is mostly the caller. The returned pointer is valid until
* m2m1shot_task_finish() which schedules another task.
* NULL is returned if no task is currently processed.
*/
static inline struct m2m1shot_task *m2m1shot_get_current_task(
struct m2m1shot_device *m21dev)
{
return m21dev->current_task;
}
/**
* m2m1shot_set_dma_address - set DMA address
*/
static inline void m2m1shot_set_dma_address(
struct m2m1shot_buffer_dma *buffer_dma,
int plane, dma_addr_t dma_addr)
{
buffer_dma->plane[plane].dma_addr = dma_addr;
}
#endif /* _M2M1SHOT_H_ */