| /* |
| * 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_ */ |